~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to arch/ia64/kernel/iosapic.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * I/O SAPIC support.
 
3
 *
 
4
 * Copyright (C) 1999 Intel Corp.
 
5
 * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
 
6
 * Copyright (C) 2000-2002 J.I. Lee <jung-ik.lee@intel.com>
 
7
 * Copyright (C) 1999-2000, 2002-2003 Hewlett-Packard Co.
 
8
 *      David Mosberger-Tang <davidm@hpl.hp.com>
 
9
 * Copyright (C) 1999 VA Linux Systems
 
10
 * Copyright (C) 1999,2000 Walt Drummond <drummond@valinux.com>
 
11
 *
 
12
 * 00/04/19     D. Mosberger    Rewritten to mirror more closely the x86 I/O
 
13
 *                              APIC code.  In particular, we now have separate
 
14
 *                              handlers for edge and level triggered
 
15
 *                              interrupts.
 
16
 * 00/10/27     Asit Mallick, Goutham Rao <goutham.rao@intel.com> IRQ vector
 
17
 *                              allocation PCI to vector mapping, shared PCI
 
18
 *                              interrupts.
 
19
 * 00/10/27     D. Mosberger    Document things a bit more to make them more
 
20
 *                              understandable.  Clean up much of the old
 
21
 *                              IOSAPIC cruft.
 
22
 * 01/07/27     J.I. Lee        PCI irq routing, Platform/Legacy interrupts
 
23
 *                              and fixes for ACPI S5(SoftOff) support.
 
24
 * 02/01/23     J.I. Lee        iosapic pgm fixes for PCI irq routing from _PRT
 
25
 * 02/01/07     E. Focht        <efocht@ess.nec.de> Redirectable interrupt
 
26
 *                              vectors in iosapic_set_affinity(),
 
27
 *                              initializations for /proc/irq/#/smp_affinity
 
28
 * 02/04/02     P. Diefenbaugh  Cleaned up ACPI PCI IRQ routing.
 
29
 * 02/04/18     J.I. Lee        bug fix in iosapic_init_pci_irq
 
30
 * 02/04/30     J.I. Lee        bug fix in find_iosapic to fix ACPI PCI IRQ to
 
31
 *                              IOSAPIC mapping error
 
32
 * 02/07/29     T. Kochi        Allocate interrupt vectors dynamically
 
33
 * 02/08/04     T. Kochi        Cleaned up terminology (irq, global system
 
34
 *                              interrupt, vector, etc.)
 
35
 * 02/09/20     D. Mosberger    Simplified by taking advantage of ACPI's
 
36
 *                              pci_irq code.
 
37
 * 03/02/19     B. Helgaas      Make pcat_compat system-wide, not per-IOSAPIC.
 
38
 *                              Remove iosapic_address & gsi_base from
 
39
 *                              external interfaces.  Rationalize
 
40
 *                              __init/__devinit attributes.
 
41
 * 04/12/04 Ashok Raj   <ashok.raj@intel.com> Intel Corporation 2004
 
42
 *                              Updated to work with irq migration necessary
 
43
 *                              for CPU Hotplug
 
44
 */
 
45
/*
 
46
 * Here is what the interrupt logic between a PCI device and the kernel looks
 
47
 * like:
 
48
 *
 
49
 * (1) A PCI device raises one of the four interrupt pins (INTA, INTB, INTC,
 
50
 *     INTD).  The device is uniquely identified by its bus-, and slot-number
 
51
 *     (the function number does not matter here because all functions share
 
52
 *     the same interrupt lines).
 
53
 *
 
54
 * (2) The motherboard routes the interrupt line to a pin on a IOSAPIC
 
55
 *     controller.  Multiple interrupt lines may have to share the same
 
56
 *     IOSAPIC pin (if they're level triggered and use the same polarity).
 
57
 *     Each interrupt line has a unique Global System Interrupt (GSI) number
 
58
 *     which can be calculated as the sum of the controller's base GSI number
 
59
 *     and the IOSAPIC pin number to which the line connects.
 
60
 *
 
61
 * (3) The IOSAPIC uses an internal routing table entries (RTEs) to map the
 
62
 * IOSAPIC pin into the IA-64 interrupt vector.  This interrupt vector is then
 
63
 * sent to the CPU.
 
64
 *
 
65
 * (4) The kernel recognizes an interrupt as an IRQ.  The IRQ interface is
 
66
 *     used as architecture-independent interrupt handling mechanism in Linux.
 
67
 *     As an IRQ is a number, we have to have
 
68
 *     IA-64 interrupt vector number <-> IRQ number mapping.  On smaller
 
69
 *     systems, we use one-to-one mapping between IA-64 vector and IRQ.  A
 
70
 *     platform can implement platform_irq_to_vector(irq) and
 
71
 *     platform_local_vector_to_irq(vector) APIs to differentiate the mapping.
 
72
 *     Please see also arch/ia64/include/asm/hw_irq.h for those APIs.
 
73
 *
 
74
 * To sum up, there are three levels of mappings involved:
 
75
 *
 
76
 *      PCI pin -> global system interrupt (GSI) -> IA-64 vector <-> IRQ
 
77
 *
 
78
 * Note: The term "IRQ" is loosely used everywhere in Linux kernel to
 
79
 * describeinterrupts.  Now we use "IRQ" only for Linux IRQ's.  ISA IRQ
 
80
 * (isa_irq) is the only exception in this source code.
 
81
 */
 
82
 
 
83
#include <linux/acpi.h>
 
84
#include <linux/init.h>
 
85
#include <linux/irq.h>
 
86
#include <linux/kernel.h>
 
87
#include <linux/list.h>
 
88
#include <linux/pci.h>
 
89
#include <linux/slab.h>
 
90
#include <linux/smp.h>
 
91
#include <linux/string.h>
 
92
#include <linux/bootmem.h>
 
93
 
 
94
#include <asm/delay.h>
 
95
#include <asm/hw_irq.h>
 
96
#include <asm/io.h>
 
97
#include <asm/iosapic.h>
 
98
#include <asm/machvec.h>
 
99
#include <asm/processor.h>
 
100
#include <asm/ptrace.h>
 
101
#include <asm/system.h>
 
102
 
 
103
#undef DEBUG_INTERRUPT_ROUTING
 
104
 
 
105
#ifdef DEBUG_INTERRUPT_ROUTING
 
106
#define DBG(fmt...)     printk(fmt)
 
107
#else
 
108
#define DBG(fmt...)
 
109
#endif
 
110
 
 
111
static DEFINE_SPINLOCK(iosapic_lock);
 
112
 
 
113
/*
 
114
 * These tables map IA-64 vectors to the IOSAPIC pin that generates this
 
115
 * vector.
 
116
 */
 
117
 
 
118
#define NO_REF_RTE      0
 
119
 
 
120
static struct iosapic {
 
121
        char __iomem    *addr;          /* base address of IOSAPIC */
 
122
        unsigned int    gsi_base;       /* GSI base */
 
123
        unsigned short  num_rte;        /* # of RTEs on this IOSAPIC */
 
124
        int             rtes_inuse;     /* # of RTEs in use on this IOSAPIC */
 
125
#ifdef CONFIG_NUMA
 
126
        unsigned short  node;           /* numa node association via pxm */
 
127
#endif
 
128
        spinlock_t      lock;           /* lock for indirect reg access */
 
129
} iosapic_lists[NR_IOSAPICS];
 
130
 
 
131
struct iosapic_rte_info {
 
132
        struct list_head rte_list;      /* RTEs sharing the same vector */
 
133
        char            rte_index;      /* IOSAPIC RTE index */
 
134
        int             refcnt;         /* reference counter */
 
135
        struct iosapic  *iosapic;
 
136
} ____cacheline_aligned;
 
137
 
 
138
static struct iosapic_intr_info {
 
139
        struct list_head rtes;          /* RTEs using this vector (empty =>
 
140
                                         * not an IOSAPIC interrupt) */
 
141
        int             count;          /* # of registered RTEs */
 
142
        u32             low32;          /* current value of low word of
 
143
                                         * Redirection table entry */
 
144
        unsigned int    dest;           /* destination CPU physical ID */
 
145
        unsigned char   dmode   : 3;    /* delivery mode (see iosapic.h) */
 
146
        unsigned char   polarity: 1;    /* interrupt polarity
 
147
                                         * (see iosapic.h) */
 
148
        unsigned char   trigger : 1;    /* trigger mode (see iosapic.h) */
 
149
} iosapic_intr_info[NR_IRQS];
 
150
 
 
151
static unsigned char pcat_compat __devinitdata; /* 8259 compatibility flag */
 
152
 
 
153
static inline void
 
154
iosapic_write(struct iosapic *iosapic, unsigned int reg, u32 val)
 
155
{
 
156
        unsigned long flags;
 
157
 
 
158
        spin_lock_irqsave(&iosapic->lock, flags);
 
159
        __iosapic_write(iosapic->addr, reg, val);
 
160
        spin_unlock_irqrestore(&iosapic->lock, flags);
 
161
}
 
162
 
 
163
/*
 
164
 * Find an IOSAPIC associated with a GSI
 
165
 */
 
166
static inline int
 
167
find_iosapic (unsigned int gsi)
 
168
{
 
169
        int i;
 
170
 
 
171
        for (i = 0; i < NR_IOSAPICS; i++) {
 
172
                if ((unsigned) (gsi - iosapic_lists[i].gsi_base) <
 
173
                    iosapic_lists[i].num_rte)
 
174
                        return i;
 
175
        }
 
176
 
 
177
        return -1;
 
178
}
 
179
 
 
180
static inline int __gsi_to_irq(unsigned int gsi)
 
181
{
 
182
        int irq;
 
183
        struct iosapic_intr_info *info;
 
184
        struct iosapic_rte_info *rte;
 
185
 
 
186
        for (irq = 0; irq < NR_IRQS; irq++) {
 
187
                info = &iosapic_intr_info[irq];
 
188
                list_for_each_entry(rte, &info->rtes, rte_list)
 
189
                        if (rte->iosapic->gsi_base + rte->rte_index == gsi)
 
190
                                return irq;
 
191
        }
 
192
        return -1;
 
193
}
 
194
 
 
195
int
 
196
gsi_to_irq (unsigned int gsi)
 
197
{
 
198
        unsigned long flags;
 
199
        int irq;
 
200
 
 
201
        spin_lock_irqsave(&iosapic_lock, flags);
 
202
        irq = __gsi_to_irq(gsi);
 
203
        spin_unlock_irqrestore(&iosapic_lock, flags);
 
204
        return irq;
 
205
}
 
206
 
 
207
static struct iosapic_rte_info *find_rte(unsigned int irq, unsigned int gsi)
 
208
{
 
209
        struct iosapic_rte_info *rte;
 
210
 
 
211
        list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list)
 
212
                if (rte->iosapic->gsi_base + rte->rte_index == gsi)
 
213
                        return rte;
 
214
        return NULL;
 
215
}
 
216
 
 
217
static void
 
218
set_rte (unsigned int gsi, unsigned int irq, unsigned int dest, int mask)
 
219
{
 
220
        unsigned long pol, trigger, dmode;
 
221
        u32 low32, high32;
 
222
        int rte_index;
 
223
        char redir;
 
224
        struct iosapic_rte_info *rte;
 
225
        ia64_vector vector = irq_to_vector(irq);
 
226
 
 
227
        DBG(KERN_DEBUG"IOSAPIC: routing vector %d to 0x%x\n", vector, dest);
 
228
 
 
229
        rte = find_rte(irq, gsi);
 
230
        if (!rte)
 
231
                return;         /* not an IOSAPIC interrupt */
 
232
 
 
233
        rte_index = rte->rte_index;
 
234
        pol     = iosapic_intr_info[irq].polarity;
 
235
        trigger = iosapic_intr_info[irq].trigger;
 
236
        dmode   = iosapic_intr_info[irq].dmode;
 
237
 
 
238
        redir = (dmode == IOSAPIC_LOWEST_PRIORITY) ? 1 : 0;
 
239
 
 
240
#ifdef CONFIG_SMP
 
241
        set_irq_affinity_info(irq, (int)(dest & 0xffff), redir);
 
242
#endif
 
243
 
 
244
        low32 = ((pol << IOSAPIC_POLARITY_SHIFT) |
 
245
                 (trigger << IOSAPIC_TRIGGER_SHIFT) |
 
246
                 (dmode << IOSAPIC_DELIVERY_SHIFT) |
 
247
                 ((mask ? 1 : 0) << IOSAPIC_MASK_SHIFT) |
 
248
                 vector);
 
249
 
 
250
        /* dest contains both id and eid */
 
251
        high32 = (dest << IOSAPIC_DEST_SHIFT);
 
252
 
 
253
        iosapic_write(rte->iosapic, IOSAPIC_RTE_HIGH(rte_index), high32);
 
254
        iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32);
 
255
        iosapic_intr_info[irq].low32 = low32;
 
256
        iosapic_intr_info[irq].dest = dest;
 
257
}
 
258
 
 
259
static void
 
260
nop (struct irq_data *data)
 
261
{
 
262
        /* do nothing... */
 
263
}
 
264
 
 
265
 
 
266
#ifdef CONFIG_KEXEC
 
267
void
 
268
kexec_disable_iosapic(void)
 
269
{
 
270
        struct iosapic_intr_info *info;
 
271
        struct iosapic_rte_info *rte;
 
272
        ia64_vector vec;
 
273
        int irq;
 
274
 
 
275
        for (irq = 0; irq < NR_IRQS; irq++) {
 
276
                info = &iosapic_intr_info[irq];
 
277
                vec = irq_to_vector(irq);
 
278
                list_for_each_entry(rte, &info->rtes,
 
279
                                rte_list) {
 
280
                        iosapic_write(rte->iosapic,
 
281
                                        IOSAPIC_RTE_LOW(rte->rte_index),
 
282
                                        IOSAPIC_MASK|vec);
 
283
                        iosapic_eoi(rte->iosapic->addr, vec);
 
284
                }
 
285
        }
 
286
}
 
287
#endif
 
288
 
 
289
static void
 
290
mask_irq (struct irq_data *data)
 
291
{
 
292
        unsigned int irq = data->irq;
 
293
        u32 low32;
 
294
        int rte_index;
 
295
        struct iosapic_rte_info *rte;
 
296
 
 
297
        if (!iosapic_intr_info[irq].count)
 
298
                return;                 /* not an IOSAPIC interrupt! */
 
299
 
 
300
        /* set only the mask bit */
 
301
        low32 = iosapic_intr_info[irq].low32 |= IOSAPIC_MASK;
 
302
        list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list) {
 
303
                rte_index = rte->rte_index;
 
304
                iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32);
 
305
        }
 
306
}
 
307
 
 
308
static void
 
309
unmask_irq (struct irq_data *data)
 
310
{
 
311
        unsigned int irq = data->irq;
 
312
        u32 low32;
 
313
        int rte_index;
 
314
        struct iosapic_rte_info *rte;
 
315
 
 
316
        if (!iosapic_intr_info[irq].count)
 
317
                return;                 /* not an IOSAPIC interrupt! */
 
318
 
 
319
        low32 = iosapic_intr_info[irq].low32 &= ~IOSAPIC_MASK;
 
320
        list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list) {
 
321
                rte_index = rte->rte_index;
 
322
                iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte_index), low32);
 
323
        }
 
324
}
 
325
 
 
326
 
 
327
static int
 
328
iosapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
 
329
                     bool force)
 
330
{
 
331
#ifdef CONFIG_SMP
 
332
        unsigned int irq = data->irq;
 
333
        u32 high32, low32;
 
334
        int cpu, dest, rte_index;
 
335
        int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0;
 
336
        struct iosapic_rte_info *rte;
 
337
        struct iosapic *iosapic;
 
338
 
 
339
        irq &= (~IA64_IRQ_REDIRECTED);
 
340
 
 
341
        cpu = cpumask_first_and(cpu_online_mask, mask);
 
342
        if (cpu >= nr_cpu_ids)
 
343
                return -1;
 
344
 
 
345
        if (irq_prepare_move(irq, cpu))
 
346
                return -1;
 
347
 
 
348
        dest = cpu_physical_id(cpu);
 
349
 
 
350
        if (!iosapic_intr_info[irq].count)
 
351
                return -1;                      /* not an IOSAPIC interrupt */
 
352
 
 
353
        set_irq_affinity_info(irq, dest, redir);
 
354
 
 
355
        /* dest contains both id and eid */
 
356
        high32 = dest << IOSAPIC_DEST_SHIFT;
 
357
 
 
358
        low32 = iosapic_intr_info[irq].low32 & ~(7 << IOSAPIC_DELIVERY_SHIFT);
 
359
        if (redir)
 
360
                /* change delivery mode to lowest priority */
 
361
                low32 |= (IOSAPIC_LOWEST_PRIORITY << IOSAPIC_DELIVERY_SHIFT);
 
362
        else
 
363
                /* change delivery mode to fixed */
 
364
                low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT);
 
365
        low32 &= IOSAPIC_VECTOR_MASK;
 
366
        low32 |= irq_to_vector(irq);
 
367
 
 
368
        iosapic_intr_info[irq].low32 = low32;
 
369
        iosapic_intr_info[irq].dest = dest;
 
370
        list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list) {
 
371
                iosapic = rte->iosapic;
 
372
                rte_index = rte->rte_index;
 
373
                iosapic_write(iosapic, IOSAPIC_RTE_HIGH(rte_index), high32);
 
374
                iosapic_write(iosapic, IOSAPIC_RTE_LOW(rte_index), low32);
 
375
        }
 
376
 
 
377
#endif
 
378
        return 0;
 
379
}
 
380
 
 
381
/*
 
382
 * Handlers for level-triggered interrupts.
 
383
 */
 
384
 
 
385
static unsigned int
 
386
iosapic_startup_level_irq (struct irq_data *data)
 
387
{
 
388
        unmask_irq(data);
 
389
        return 0;
 
390
}
 
391
 
 
392
static void
 
393
iosapic_unmask_level_irq (struct irq_data *data)
 
394
{
 
395
        unsigned int irq = data->irq;
 
396
        ia64_vector vec = irq_to_vector(irq);
 
397
        struct iosapic_rte_info *rte;
 
398
        int do_unmask_irq = 0;
 
399
 
 
400
        irq_complete_move(irq);
 
401
        if (unlikely(irqd_is_setaffinity_pending(data))) {
 
402
                do_unmask_irq = 1;
 
403
                mask_irq(data);
 
404
        } else
 
405
                unmask_irq(data);
 
406
 
 
407
        list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list)
 
408
                iosapic_eoi(rte->iosapic->addr, vec);
 
409
 
 
410
        if (unlikely(do_unmask_irq)) {
 
411
                irq_move_masked_irq(data);
 
412
                unmask_irq(data);
 
413
        }
 
414
}
 
415
 
 
416
#define iosapic_shutdown_level_irq      mask_irq
 
417
#define iosapic_enable_level_irq        unmask_irq
 
418
#define iosapic_disable_level_irq       mask_irq
 
419
#define iosapic_ack_level_irq           nop
 
420
 
 
421
static struct irq_chip irq_type_iosapic_level = {
 
422
        .name =                 "IO-SAPIC-level",
 
423
        .irq_startup =          iosapic_startup_level_irq,
 
424
        .irq_shutdown =         iosapic_shutdown_level_irq,
 
425
        .irq_enable =           iosapic_enable_level_irq,
 
426
        .irq_disable =          iosapic_disable_level_irq,
 
427
        .irq_ack =              iosapic_ack_level_irq,
 
428
        .irq_mask =             mask_irq,
 
429
        .irq_unmask =           iosapic_unmask_level_irq,
 
430
        .irq_set_affinity =     iosapic_set_affinity
 
431
};
 
432
 
 
433
/*
 
434
 * Handlers for edge-triggered interrupts.
 
435
 */
 
436
 
 
437
static unsigned int
 
438
iosapic_startup_edge_irq (struct irq_data *data)
 
439
{
 
440
        unmask_irq(data);
 
441
        /*
 
442
         * IOSAPIC simply drops interrupts pended while the
 
443
         * corresponding pin was masked, so we can't know if an
 
444
         * interrupt is pending already.  Let's hope not...
 
445
         */
 
446
        return 0;
 
447
}
 
448
 
 
449
static void
 
450
iosapic_ack_edge_irq (struct irq_data *data)
 
451
{
 
452
        irq_complete_move(data->irq);
 
453
        irq_move_irq(data);
 
454
}
 
455
 
 
456
#define iosapic_enable_edge_irq         unmask_irq
 
457
#define iosapic_disable_edge_irq        nop
 
458
 
 
459
static struct irq_chip irq_type_iosapic_edge = {
 
460
        .name =                 "IO-SAPIC-edge",
 
461
        .irq_startup =          iosapic_startup_edge_irq,
 
462
        .irq_shutdown =         iosapic_disable_edge_irq,
 
463
        .irq_enable =           iosapic_enable_edge_irq,
 
464
        .irq_disable =          iosapic_disable_edge_irq,
 
465
        .irq_ack =              iosapic_ack_edge_irq,
 
466
        .irq_mask =             mask_irq,
 
467
        .irq_unmask =           unmask_irq,
 
468
        .irq_set_affinity =     iosapic_set_affinity
 
469
};
 
470
 
 
471
static unsigned int
 
472
iosapic_version (char __iomem *addr)
 
473
{
 
474
        /*
 
475
         * IOSAPIC Version Register return 32 bit structure like:
 
476
         * {
 
477
         *      unsigned int version   : 8;
 
478
         *      unsigned int reserved1 : 8;
 
479
         *      unsigned int max_redir : 8;
 
480
         *      unsigned int reserved2 : 8;
 
481
         * }
 
482
         */
 
483
        return __iosapic_read(addr, IOSAPIC_VERSION);
 
484
}
 
485
 
 
486
static int iosapic_find_sharable_irq(unsigned long trigger, unsigned long pol)
 
487
{
 
488
        int i, irq = -ENOSPC, min_count = -1;
 
489
        struct iosapic_intr_info *info;
 
490
 
 
491
        /*
 
492
         * shared vectors for edge-triggered interrupts are not
 
493
         * supported yet
 
494
         */
 
495
        if (trigger == IOSAPIC_EDGE)
 
496
                return -EINVAL;
 
497
 
 
498
        for (i = 0; i < NR_IRQS; i++) {
 
499
                info = &iosapic_intr_info[i];
 
500
                if (info->trigger == trigger && info->polarity == pol &&
 
501
                    (info->dmode == IOSAPIC_FIXED ||
 
502
                     info->dmode == IOSAPIC_LOWEST_PRIORITY) &&
 
503
                    can_request_irq(i, IRQF_SHARED)) {
 
504
                        if (min_count == -1 || info->count < min_count) {
 
505
                                irq = i;
 
506
                                min_count = info->count;
 
507
                        }
 
508
                }
 
509
        }
 
510
        return irq;
 
511
}
 
512
 
 
513
/*
 
514
 * if the given vector is already owned by other,
 
515
 *  assign a new vector for the other and make the vector available
 
516
 */
 
517
static void __init
 
518
iosapic_reassign_vector (int irq)
 
519
{
 
520
        int new_irq;
 
521
 
 
522
        if (iosapic_intr_info[irq].count) {
 
523
                new_irq = create_irq();
 
524
                if (new_irq < 0)
 
525
                        panic("%s: out of interrupt vectors!\n", __func__);
 
526
                printk(KERN_INFO "Reassigning vector %d to %d\n",
 
527
                       irq_to_vector(irq), irq_to_vector(new_irq));
 
528
                memcpy(&iosapic_intr_info[new_irq], &iosapic_intr_info[irq],
 
529
                       sizeof(struct iosapic_intr_info));
 
530
                INIT_LIST_HEAD(&iosapic_intr_info[new_irq].rtes);
 
531
                list_move(iosapic_intr_info[irq].rtes.next,
 
532
                          &iosapic_intr_info[new_irq].rtes);
 
533
                memset(&iosapic_intr_info[irq], 0,
 
534
                       sizeof(struct iosapic_intr_info));
 
535
                iosapic_intr_info[irq].low32 = IOSAPIC_MASK;
 
536
                INIT_LIST_HEAD(&iosapic_intr_info[irq].rtes);
 
537
        }
 
538
}
 
539
 
 
540
static inline int irq_is_shared (int irq)
 
541
{
 
542
        return (iosapic_intr_info[irq].count > 1);
 
543
}
 
544
 
 
545
struct irq_chip*
 
546
ia64_native_iosapic_get_irq_chip(unsigned long trigger)
 
547
{
 
548
        if (trigger == IOSAPIC_EDGE)
 
549
                return &irq_type_iosapic_edge;
 
550
        else
 
551
                return &irq_type_iosapic_level;
 
552
}
 
553
 
 
554
static int
 
555
register_intr (unsigned int gsi, int irq, unsigned char delivery,
 
556
               unsigned long polarity, unsigned long trigger)
 
557
{
 
558
        struct irq_chip *chip, *irq_type;
 
559
        int index;
 
560
        struct iosapic_rte_info *rte;
 
561
 
 
562
        index = find_iosapic(gsi);
 
563
        if (index < 0) {
 
564
                printk(KERN_WARNING "%s: No IOSAPIC for GSI %u\n",
 
565
                       __func__, gsi);
 
566
                return -ENODEV;
 
567
        }
 
568
 
 
569
        rte = find_rte(irq, gsi);
 
570
        if (!rte) {
 
571
                rte = kzalloc(sizeof (*rte), GFP_ATOMIC);
 
572
                if (!rte) {
 
573
                        printk(KERN_WARNING "%s: cannot allocate memory\n",
 
574
                               __func__);
 
575
                        return -ENOMEM;
 
576
                }
 
577
 
 
578
                rte->iosapic    = &iosapic_lists[index];
 
579
                rte->rte_index  = gsi - rte->iosapic->gsi_base;
 
580
                rte->refcnt++;
 
581
                list_add_tail(&rte->rte_list, &iosapic_intr_info[irq].rtes);
 
582
                iosapic_intr_info[irq].count++;
 
583
                iosapic_lists[index].rtes_inuse++;
 
584
        }
 
585
        else if (rte->refcnt == NO_REF_RTE) {
 
586
                struct iosapic_intr_info *info = &iosapic_intr_info[irq];
 
587
                if (info->count > 0 &&
 
588
                    (info->trigger != trigger || info->polarity != polarity)){
 
589
                        printk (KERN_WARNING
 
590
                                "%s: cannot override the interrupt\n",
 
591
                                __func__);
 
592
                        return -EINVAL;
 
593
                }
 
594
                rte->refcnt++;
 
595
                iosapic_intr_info[irq].count++;
 
596
                iosapic_lists[index].rtes_inuse++;
 
597
        }
 
598
 
 
599
        iosapic_intr_info[irq].polarity = polarity;
 
600
        iosapic_intr_info[irq].dmode    = delivery;
 
601
        iosapic_intr_info[irq].trigger  = trigger;
 
602
 
 
603
        irq_type = iosapic_get_irq_chip(trigger);
 
604
 
 
605
        chip = irq_get_chip(irq);
 
606
        if (irq_type != NULL && chip != irq_type) {
 
607
                if (chip != &no_irq_chip)
 
608
                        printk(KERN_WARNING
 
609
                               "%s: changing vector %d from %s to %s\n",
 
610
                               __func__, irq_to_vector(irq),
 
611
                               chip->name, irq_type->name);
 
612
                chip = irq_type;
 
613
        }
 
614
        __irq_set_chip_handler_name_locked(irq, chip, trigger == IOSAPIC_EDGE ?
 
615
                                           handle_edge_irq : handle_level_irq,
 
616
                                           NULL);
 
617
        return 0;
 
618
}
 
619
 
 
620
static unsigned int
 
621
get_target_cpu (unsigned int gsi, int irq)
 
622
{
 
623
#ifdef CONFIG_SMP
 
624
        static int cpu = -1;
 
625
        extern int cpe_vector;
 
626
        cpumask_t domain = irq_to_domain(irq);
 
627
 
 
628
        /*
 
629
         * In case of vector shared by multiple RTEs, all RTEs that
 
630
         * share the vector need to use the same destination CPU.
 
631
         */
 
632
        if (iosapic_intr_info[irq].count)
 
633
                return iosapic_intr_info[irq].dest;
 
634
 
 
635
        /*
 
636
         * If the platform supports redirection via XTP, let it
 
637
         * distribute interrupts.
 
638
         */
 
639
        if (smp_int_redirect & SMP_IRQ_REDIRECTION)
 
640
                return cpu_physical_id(smp_processor_id());
 
641
 
 
642
        /*
 
643
         * Some interrupts (ACPI SCI, for instance) are registered
 
644
         * before the BSP is marked as online.
 
645
         */
 
646
        if (!cpu_online(smp_processor_id()))
 
647
                return cpu_physical_id(smp_processor_id());
 
648
 
 
649
#ifdef CONFIG_ACPI
 
650
        if (cpe_vector > 0 && irq_to_vector(irq) == IA64_CPEP_VECTOR)
 
651
                return get_cpei_target_cpu();
 
652
#endif
 
653
 
 
654
#ifdef CONFIG_NUMA
 
655
        {
 
656
                int num_cpus, cpu_index, iosapic_index, numa_cpu, i = 0;
 
657
                const struct cpumask *cpu_mask;
 
658
 
 
659
                iosapic_index = find_iosapic(gsi);
 
660
                if (iosapic_index < 0 ||
 
661
                    iosapic_lists[iosapic_index].node == MAX_NUMNODES)
 
662
                        goto skip_numa_setup;
 
663
 
 
664
                cpu_mask = cpumask_of_node(iosapic_lists[iosapic_index].node);
 
665
                num_cpus = 0;
 
666
                for_each_cpu_and(numa_cpu, cpu_mask, &domain) {
 
667
                        if (cpu_online(numa_cpu))
 
668
                                num_cpus++;
 
669
                }
 
670
 
 
671
                if (!num_cpus)
 
672
                        goto skip_numa_setup;
 
673
 
 
674
                /* Use irq assignment to distribute across cpus in node */
 
675
                cpu_index = irq % num_cpus;
 
676
 
 
677
                for_each_cpu_and(numa_cpu, cpu_mask, &domain)
 
678
                        if (cpu_online(numa_cpu) && i++ >= cpu_index)
 
679
                                break;
 
680
 
 
681
                if (numa_cpu < nr_cpu_ids)
 
682
                        return cpu_physical_id(numa_cpu);
 
683
        }
 
684
skip_numa_setup:
 
685
#endif
 
686
        /*
 
687
         * Otherwise, round-robin interrupt vectors across all the
 
688
         * processors.  (It'd be nice if we could be smarter in the
 
689
         * case of NUMA.)
 
690
         */
 
691
        do {
 
692
                if (++cpu >= nr_cpu_ids)
 
693
                        cpu = 0;
 
694
        } while (!cpu_online(cpu) || !cpu_isset(cpu, domain));
 
695
 
 
696
        return cpu_physical_id(cpu);
 
697
#else  /* CONFIG_SMP */
 
698
        return cpu_physical_id(smp_processor_id());
 
699
#endif
 
700
}
 
701
 
 
702
static inline unsigned char choose_dmode(void)
 
703
{
 
704
#ifdef CONFIG_SMP
 
705
        if (smp_int_redirect & SMP_IRQ_REDIRECTION)
 
706
                return IOSAPIC_LOWEST_PRIORITY;
 
707
#endif
 
708
        return IOSAPIC_FIXED;
 
709
}
 
710
 
 
711
/*
 
712
 * ACPI can describe IOSAPIC interrupts via static tables and namespace
 
713
 * methods.  This provides an interface to register those interrupts and
 
714
 * program the IOSAPIC RTE.
 
715
 */
 
716
int
 
717
iosapic_register_intr (unsigned int gsi,
 
718
                       unsigned long polarity, unsigned long trigger)
 
719
{
 
720
        int irq, mask = 1, err;
 
721
        unsigned int dest;
 
722
        unsigned long flags;
 
723
        struct iosapic_rte_info *rte;
 
724
        u32 low32;
 
725
        unsigned char dmode;
 
726
        struct irq_desc *desc;
 
727
 
 
728
        /*
 
729
         * If this GSI has already been registered (i.e., it's a
 
730
         * shared interrupt, or we lost a race to register it),
 
731
         * don't touch the RTE.
 
732
         */
 
733
        spin_lock_irqsave(&iosapic_lock, flags);
 
734
        irq = __gsi_to_irq(gsi);
 
735
        if (irq > 0) {
 
736
                rte = find_rte(irq, gsi);
 
737
                if(iosapic_intr_info[irq].count == 0) {
 
738
                        assign_irq_vector(irq);
 
739
                        dynamic_irq_init(irq);
 
740
                } else if (rte->refcnt != NO_REF_RTE) {
 
741
                        rte->refcnt++;
 
742
                        goto unlock_iosapic_lock;
 
743
                }
 
744
        } else
 
745
                irq = create_irq();
 
746
 
 
747
        /* If vector is running out, we try to find a sharable vector */
 
748
        if (irq < 0) {
 
749
                irq = iosapic_find_sharable_irq(trigger, polarity);
 
750
                if (irq < 0)
 
751
                        goto unlock_iosapic_lock;
 
752
        }
 
753
 
 
754
        desc = irq_to_desc(irq);
 
755
        raw_spin_lock(&desc->lock);
 
756
        dest = get_target_cpu(gsi, irq);
 
757
        dmode = choose_dmode();
 
758
        err = register_intr(gsi, irq, dmode, polarity, trigger);
 
759
        if (err < 0) {
 
760
                raw_spin_unlock(&desc->lock);
 
761
                irq = err;
 
762
                goto unlock_iosapic_lock;
 
763
        }
 
764
 
 
765
        /*
 
766
         * If the vector is shared and already unmasked for other
 
767
         * interrupt sources, don't mask it.
 
768
         */
 
769
        low32 = iosapic_intr_info[irq].low32;
 
770
        if (irq_is_shared(irq) && !(low32 & IOSAPIC_MASK))
 
771
                mask = 0;
 
772
        set_rte(gsi, irq, dest, mask);
 
773
 
 
774
        printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n",
 
775
               gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
 
776
               (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
 
777
               cpu_logical_id(dest), dest, irq_to_vector(irq));
 
778
 
 
779
        raw_spin_unlock(&desc->lock);
 
780
 unlock_iosapic_lock:
 
781
        spin_unlock_irqrestore(&iosapic_lock, flags);
 
782
        return irq;
 
783
}
 
784
 
 
785
void
 
786
iosapic_unregister_intr (unsigned int gsi)
 
787
{
 
788
        unsigned long flags;
 
789
        int irq, index;
 
790
        u32 low32;
 
791
        unsigned long trigger, polarity;
 
792
        unsigned int dest;
 
793
        struct iosapic_rte_info *rte;
 
794
 
 
795
        /*
 
796
         * If the irq associated with the gsi is not found,
 
797
         * iosapic_unregister_intr() is unbalanced. We need to check
 
798
         * this again after getting locks.
 
799
         */
 
800
        irq = gsi_to_irq(gsi);
 
801
        if (irq < 0) {
 
802
                printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n",
 
803
                       gsi);
 
804
                WARN_ON(1);
 
805
                return;
 
806
        }
 
807
 
 
808
        spin_lock_irqsave(&iosapic_lock, flags);
 
809
        if ((rte = find_rte(irq, gsi)) == NULL) {
 
810
                printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n",
 
811
                       gsi);
 
812
                WARN_ON(1);
 
813
                goto out;
 
814
        }
 
815
 
 
816
        if (--rte->refcnt > 0)
 
817
                goto out;
 
818
 
 
819
        rte->refcnt = NO_REF_RTE;
 
820
 
 
821
        /* Mask the interrupt */
 
822
        low32 = iosapic_intr_info[irq].low32 | IOSAPIC_MASK;
 
823
        iosapic_write(rte->iosapic, IOSAPIC_RTE_LOW(rte->rte_index), low32);
 
824
 
 
825
        iosapic_intr_info[irq].count--;
 
826
        index = find_iosapic(gsi);
 
827
        iosapic_lists[index].rtes_inuse--;
 
828
        WARN_ON(iosapic_lists[index].rtes_inuse < 0);
 
829
 
 
830
        trigger  = iosapic_intr_info[irq].trigger;
 
831
        polarity = iosapic_intr_info[irq].polarity;
 
832
        dest     = iosapic_intr_info[irq].dest;
 
833
        printk(KERN_INFO
 
834
               "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d unregistered\n",
 
835
               gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
 
836
               (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
 
837
               cpu_logical_id(dest), dest, irq_to_vector(irq));
 
838
 
 
839
        if (iosapic_intr_info[irq].count == 0) {
 
840
#ifdef CONFIG_SMP
 
841
                /* Clear affinity */
 
842
                cpumask_setall(irq_get_irq_data(irq)->affinity);
 
843
#endif
 
844
                /* Clear the interrupt information */
 
845
                iosapic_intr_info[irq].dest = 0;
 
846
                iosapic_intr_info[irq].dmode = 0;
 
847
                iosapic_intr_info[irq].polarity = 0;
 
848
                iosapic_intr_info[irq].trigger = 0;
 
849
                iosapic_intr_info[irq].low32 |= IOSAPIC_MASK;
 
850
 
 
851
                /* Destroy and reserve IRQ */
 
852
                destroy_and_reserve_irq(irq);
 
853
        }
 
854
 out:
 
855
        spin_unlock_irqrestore(&iosapic_lock, flags);
 
856
}
 
857
 
 
858
/*
 
859
 * ACPI calls this when it finds an entry for a platform interrupt.
 
860
 */
 
861
int __init
 
862
iosapic_register_platform_intr (u32 int_type, unsigned int gsi,
 
863
                                int iosapic_vector, u16 eid, u16 id,
 
864
                                unsigned long polarity, unsigned long trigger)
 
865
{
 
866
        static const char * const name[] = {"unknown", "PMI", "INIT", "CPEI"};
 
867
        unsigned char delivery;
 
868
        int irq, vector, mask = 0;
 
869
        unsigned int dest = ((id << 8) | eid) & 0xffff;
 
870
 
 
871
        switch (int_type) {
 
872
              case ACPI_INTERRUPT_PMI:
 
873
                irq = vector = iosapic_vector;
 
874
                bind_irq_vector(irq, vector, CPU_MASK_ALL);
 
875
                /*
 
876
                 * since PMI vector is alloc'd by FW(ACPI) not by kernel,
 
877
                 * we need to make sure the vector is available
 
878
                 */
 
879
                iosapic_reassign_vector(irq);
 
880
                delivery = IOSAPIC_PMI;
 
881
                break;
 
882
              case ACPI_INTERRUPT_INIT:
 
883
                irq = create_irq();
 
884
                if (irq < 0)
 
885
                        panic("%s: out of interrupt vectors!\n", __func__);
 
886
                vector = irq_to_vector(irq);
 
887
                delivery = IOSAPIC_INIT;
 
888
                break;
 
889
              case ACPI_INTERRUPT_CPEI:
 
890
                irq = vector = IA64_CPE_VECTOR;
 
891
                BUG_ON(bind_irq_vector(irq, vector, CPU_MASK_ALL));
 
892
                delivery = IOSAPIC_FIXED;
 
893
                mask = 1;
 
894
                break;
 
895
              default:
 
896
                printk(KERN_ERR "%s: invalid int type 0x%x\n", __func__,
 
897
                       int_type);
 
898
                return -1;
 
899
        }
 
900
 
 
901
        register_intr(gsi, irq, delivery, polarity, trigger);
 
902
 
 
903
        printk(KERN_INFO
 
904
               "PLATFORM int %s (0x%x): GSI %u (%s, %s) -> CPU %d (0x%04x)"
 
905
               " vector %d\n",
 
906
               int_type < ARRAY_SIZE(name) ? name[int_type] : "unknown",
 
907
               int_type, gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),
 
908
               (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
 
909
               cpu_logical_id(dest), dest, vector);
 
910
 
 
911
        set_rte(gsi, irq, dest, mask);
 
912
        return vector;
 
913
}
 
914
 
 
915
/*
 
916
 * ACPI calls this when it finds an entry for a legacy ISA IRQ override.
 
917
 */
 
918
void __devinit
 
919
iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
 
920
                          unsigned long polarity,
 
921
                          unsigned long trigger)
 
922
{
 
923
        int vector, irq;
 
924
        unsigned int dest = cpu_physical_id(smp_processor_id());
 
925
        unsigned char dmode;
 
926
 
 
927
        irq = vector = isa_irq_to_vector(isa_irq);
 
928
        BUG_ON(bind_irq_vector(irq, vector, CPU_MASK_ALL));
 
929
        dmode = choose_dmode();
 
930
        register_intr(gsi, irq, dmode, polarity, trigger);
 
931
 
 
932
        DBG("ISA: IRQ %u -> GSI %u (%s,%s) -> CPU %d (0x%04x) vector %d\n",
 
933
            isa_irq, gsi, trigger == IOSAPIC_EDGE ? "edge" : "level",
 
934
            polarity == IOSAPIC_POL_HIGH ? "high" : "low",
 
935
            cpu_logical_id(dest), dest, vector);
 
936
 
 
937
        set_rte(gsi, irq, dest, 1);
 
938
}
 
939
 
 
940
void __init
 
941
ia64_native_iosapic_pcat_compat_init(void)
 
942
{
 
943
        if (pcat_compat) {
 
944
                /*
 
945
                 * Disable the compatibility mode interrupts (8259 style),
 
946
                 * needs IN/OUT support enabled.
 
947
                 */
 
948
                printk(KERN_INFO
 
949
                       "%s: Disabling PC-AT compatible 8259 interrupts\n",
 
950
                       __func__);
 
951
                outb(0xff, 0xA1);
 
952
                outb(0xff, 0x21);
 
953
        }
 
954
}
 
955
 
 
956
void __init
 
957
iosapic_system_init (int system_pcat_compat)
 
958
{
 
959
        int irq;
 
960
 
 
961
        for (irq = 0; irq < NR_IRQS; ++irq) {
 
962
                iosapic_intr_info[irq].low32 = IOSAPIC_MASK;
 
963
                /* mark as unused */
 
964
                INIT_LIST_HEAD(&iosapic_intr_info[irq].rtes);
 
965
 
 
966
                iosapic_intr_info[irq].count = 0;
 
967
        }
 
968
 
 
969
        pcat_compat = system_pcat_compat;
 
970
        if (pcat_compat)
 
971
                iosapic_pcat_compat_init();
 
972
}
 
973
 
 
974
static inline int
 
975
iosapic_alloc (void)
 
976
{
 
977
        int index;
 
978
 
 
979
        for (index = 0; index < NR_IOSAPICS; index++)
 
980
                if (!iosapic_lists[index].addr)
 
981
                        return index;
 
982
 
 
983
        printk(KERN_WARNING "%s: failed to allocate iosapic\n", __func__);
 
984
        return -1;
 
985
}
 
986
 
 
987
static inline void
 
988
iosapic_free (int index)
 
989
{
 
990
        memset(&iosapic_lists[index], 0, sizeof(iosapic_lists[0]));
 
991
}
 
992
 
 
993
static inline int
 
994
iosapic_check_gsi_range (unsigned int gsi_base, unsigned int ver)
 
995
{
 
996
        int index;
 
997
        unsigned int gsi_end, base, end;
 
998
 
 
999
        /* check gsi range */
 
1000
        gsi_end = gsi_base + ((ver >> 16) & 0xff);
 
1001
        for (index = 0; index < NR_IOSAPICS; index++) {
 
1002
                if (!iosapic_lists[index].addr)
 
1003
                        continue;
 
1004
 
 
1005
                base = iosapic_lists[index].gsi_base;
 
1006
                end  = base + iosapic_lists[index].num_rte - 1;
 
1007
 
 
1008
                if (gsi_end < base || end < gsi_base)
 
1009
                        continue; /* OK */
 
1010
 
 
1011
                return -EBUSY;
 
1012
        }
 
1013
        return 0;
 
1014
}
 
1015
 
 
1016
int __devinit
 
1017
iosapic_init (unsigned long phys_addr, unsigned int gsi_base)
 
1018
{
 
1019
        int num_rte, err, index;
 
1020
        unsigned int isa_irq, ver;
 
1021
        char __iomem *addr;
 
1022
        unsigned long flags;
 
1023
 
 
1024
        spin_lock_irqsave(&iosapic_lock, flags);
 
1025
        index = find_iosapic(gsi_base);
 
1026
        if (index >= 0) {
 
1027
                spin_unlock_irqrestore(&iosapic_lock, flags);
 
1028
                return -EBUSY;
 
1029
        }
 
1030
 
 
1031
        addr = ioremap(phys_addr, 0);
 
1032
        if (addr == NULL) {
 
1033
                spin_unlock_irqrestore(&iosapic_lock, flags);
 
1034
                return -ENOMEM;
 
1035
        }
 
1036
        ver = iosapic_version(addr);
 
1037
        if ((err = iosapic_check_gsi_range(gsi_base, ver))) {
 
1038
                iounmap(addr);
 
1039
                spin_unlock_irqrestore(&iosapic_lock, flags);
 
1040
                return err;
 
1041
        }
 
1042
 
 
1043
        /*
 
1044
         * The MAX_REDIR register holds the highest input pin number
 
1045
         * (starting from 0).  We add 1 so that we can use it for
 
1046
         * number of pins (= RTEs)
 
1047
         */
 
1048
        num_rte = ((ver >> 16) & 0xff) + 1;
 
1049
 
 
1050
        index = iosapic_alloc();
 
1051
        iosapic_lists[index].addr = addr;
 
1052
        iosapic_lists[index].gsi_base = gsi_base;
 
1053
        iosapic_lists[index].num_rte = num_rte;
 
1054
#ifdef CONFIG_NUMA
 
1055
        iosapic_lists[index].node = MAX_NUMNODES;
 
1056
#endif
 
1057
        spin_lock_init(&iosapic_lists[index].lock);
 
1058
        spin_unlock_irqrestore(&iosapic_lock, flags);
 
1059
 
 
1060
        if ((gsi_base == 0) && pcat_compat) {
 
1061
                /*
 
1062
                 * Map the legacy ISA devices into the IOSAPIC data.  Some of
 
1063
                 * these may get reprogrammed later on with data from the ACPI
 
1064
                 * Interrupt Source Override table.
 
1065
                 */
 
1066
                for (isa_irq = 0; isa_irq < 16; ++isa_irq)
 
1067
                        iosapic_override_isa_irq(isa_irq, isa_irq,
 
1068
                                                 IOSAPIC_POL_HIGH,
 
1069
                                                 IOSAPIC_EDGE);
 
1070
        }
 
1071
        return 0;
 
1072
}
 
1073
 
 
1074
#ifdef CONFIG_HOTPLUG
 
1075
int
 
1076
iosapic_remove (unsigned int gsi_base)
 
1077
{
 
1078
        int index, err = 0;
 
1079
        unsigned long flags;
 
1080
 
 
1081
        spin_lock_irqsave(&iosapic_lock, flags);
 
1082
        index = find_iosapic(gsi_base);
 
1083
        if (index < 0) {
 
1084
                printk(KERN_WARNING "%s: No IOSAPIC for GSI base %u\n",
 
1085
                       __func__, gsi_base);
 
1086
                goto out;
 
1087
        }
 
1088
 
 
1089
        if (iosapic_lists[index].rtes_inuse) {
 
1090
                err = -EBUSY;
 
1091
                printk(KERN_WARNING "%s: IOSAPIC for GSI base %u is busy\n",
 
1092
                       __func__, gsi_base);
 
1093
                goto out;
 
1094
        }
 
1095
 
 
1096
        iounmap(iosapic_lists[index].addr);
 
1097
        iosapic_free(index);
 
1098
 out:
 
1099
        spin_unlock_irqrestore(&iosapic_lock, flags);
 
1100
        return err;
 
1101
}
 
1102
#endif /* CONFIG_HOTPLUG */
 
1103
 
 
1104
#ifdef CONFIG_NUMA
 
1105
void __devinit
 
1106
map_iosapic_to_node(unsigned int gsi_base, int node)
 
1107
{
 
1108
        int index;
 
1109
 
 
1110
        index = find_iosapic(gsi_base);
 
1111
        if (index < 0) {
 
1112
                printk(KERN_WARNING "%s: No IOSAPIC for GSI %u\n",
 
1113
                       __func__, gsi_base);
 
1114
                return;
 
1115
        }
 
1116
        iosapic_lists[index].node = node;
 
1117
        return;
 
1118
}
 
1119
#endif