aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJiang Liu <jiang.liu@linux.intel.com>2014-06-09 04:19:52 -0400
committerThomas Gleixner <tglx@linutronix.de>2014-06-21 17:05:42 -0400
commitd7f3d4781852f5160b939f526afbc21a813a0206 (patch)
tree1524a81dd5c6906cf1b291b5a959b774c5ded437 /arch
parent84245af7297ced9e8fe837dc0fc4782438771bd2 (diff)
x86, irq: Introduce mechanisms to support dynamically allocate IRQ for IOAPIC
Currently x86 support identity mapping between GSI(IOAPIC pin) and IRQ number, so continous IRQs at low end are statically allocated to IOAPICs at boot time. This design causes trouble to support IOAPIC hotplug. This patch implements basic mechanism to dynamically allocate IRQ on demand for IOAPIC pins by using irqdomain framework. It first adds several fields into struct ioapic to support irqdomain. Then it implements an algorithm to dynamically allocate IRQ number for IOAPIC pins on demand. Currently it supports three types of irqdomain: 1) LEGACY: used to support IOAPIC hosting legacy IRQs and building identity mapping for legacy IRQs. A speical case, we dynamically allocate IRQ number for IOAPIC pin which has GSI number below nr_legacy_irqs() but isn't legacy IRQ. This is for backward compatibility and avoid regression. 2) STRICT: build identity mapping between GSI and IRQ nubmer. 3) DYNAMIC: dynamically allocate IRQ number for IOAPIC pin on demand. Legacy(ISA) IRQs is not managed by irqdomain because there may be multiple pins sharing the same IRQ number and current irqdomain only supports 1:1 mapping between pins and IRQ. Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Cc: Tony Luck <tony.luck@intel.com> Cc: Joerg Roedel <joro@8bytes.org> Cc: Paul Gortmaker <paul.gortmaker@windriver.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Grant Likely <grant.likely@linaro.org> Cc: Rafael J. Wysocki <rjw@rjwysocki.net> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Randy Dunlap <rdunlap@infradead.org> Cc: Yinghai Lu <yinghai@kernel.org> Cc: Len Brown <len.brown@intel.com> Cc: Pavel Machek <pavel@ucw.cz> Link: http://lkml.kernel.org/r/1402302011-23642-24-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/Kconfig1
-rw-r--r--arch/x86/include/asm/io_apic.h21
-rw-r--r--arch/x86/kernel/acpi/boot.c8
-rw-r--r--arch/x86/kernel/apic/io_apic.c158
4 files changed, 147 insertions, 41 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 9df5c453171e..147a7b788100 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -836,6 +836,7 @@ config X86_IO_APIC
836 def_bool y 836 def_bool y
837 depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_IOAPIC || PCI_MSI 837 depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_IOAPIC || PCI_MSI
838 select GENERIC_IRQ_LEGACY_ALLOC_HWIRQ 838 select GENERIC_IRQ_LEGACY_ALLOC_HWIRQ
839 select IRQ_DOMAIN
839 840
840config X86_REROUTE_FOR_BROKEN_BOOT_IRQS 841config X86_REROUTE_FOR_BROKEN_BOOT_IRQS
841 bool "Reroute for broken boot IRQs" 842 bool "Reroute for broken boot IRQs"
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 978e51fdcb59..64c6e344399b 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -98,6 +98,8 @@ struct IR_IO_APIC_route_entry {
98#define IOAPIC_AUTO -1 98#define IOAPIC_AUTO -1
99#define IOAPIC_EDGE 0 99#define IOAPIC_EDGE 0
100#define IOAPIC_LEVEL 1 100#define IOAPIC_LEVEL 1
101#define IOAPIC_MAP_ALLOC 0x1
102#define IOAPIC_MAP_CHECK 0x2
101 103
102#ifdef CONFIG_X86_IO_APIC 104#ifdef CONFIG_X86_IO_APIC
103 105
@@ -163,6 +165,21 @@ extern int restore_ioapic_entries(void);
163extern void setup_ioapic_ids_from_mpc(void); 165extern void setup_ioapic_ids_from_mpc(void);
164extern void setup_ioapic_ids_from_mpc_nocheck(void); 166extern void setup_ioapic_ids_from_mpc_nocheck(void);
165 167
168enum ioapic_domain_type {
169 IOAPIC_DOMAIN_INVALID,
170 IOAPIC_DOMAIN_LEGACY,
171 IOAPIC_DOMAIN_STRICT,
172 IOAPIC_DOMAIN_DYNAMIC,
173};
174
175struct device_node;
176struct irq_domain_ops;
177struct ioapic_domain_cfg {
178 enum ioapic_domain_type type;
179 const struct irq_domain_ops *ops;
180 struct device_node *dev;
181};
182
166struct mp_ioapic_gsi{ 183struct mp_ioapic_gsi{
167 u32 gsi_base; 184 u32 gsi_base;
168 u32 gsi_end; 185 u32 gsi_end;
@@ -172,7 +189,7 @@ extern u32 gsi_top;
172extern int mp_find_ioapic(u32 gsi); 189extern int mp_find_ioapic(u32 gsi);
173extern int mp_find_ioapic_pin(int ioapic, u32 gsi); 190extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
174extern u32 mp_pin_to_gsi(int ioapic, int pin); 191extern u32 mp_pin_to_gsi(int ioapic, int pin);
175extern int mp_map_gsi_to_irq(u32 gsi); 192extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
176extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base); 193extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
177extern void __init pre_init_apic_IRQ0(void); 194extern void __init pre_init_apic_IRQ0(void);
178 195
@@ -215,7 +232,7 @@ static inline void ioapic_insert_resources(void) { }
215#define gsi_top (NR_IRQS_LEGACY) 232#define gsi_top (NR_IRQS_LEGACY)
216static inline int mp_find_ioapic(u32 gsi) { return 0; } 233static inline int mp_find_ioapic(u32 gsi) { return 0; }
217static inline u32 mp_pin_to_gsi(int ioapic, int pin) { return UINT_MAX; } 234static inline u32 mp_pin_to_gsi(int ioapic, int pin) { return UINT_MAX; }
218static inline int mp_map_gsi_to_irq(u32 gsi) { return gsi; } 235static inline int mp_map_gsi_to_irq(u32 gsi, unsigned int flags) { return gsi; }
219 236
220struct io_apic_irq_attr; 237struct io_apic_irq_attr;
221static inline int io_apic_set_pci_routing(struct device *dev, int irq, 238static inline int io_apic_set_pci_routing(struct device *dev, int irq,
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 0cf311c72bce..d6635baf9e3d 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -100,7 +100,7 @@ static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = {
100 100
101#define ACPI_INVALID_GSI INT_MIN 101#define ACPI_INVALID_GSI INT_MIN
102 102
103static int map_gsi_to_irq(unsigned int gsi) 103static int map_gsi_to_irq(unsigned int gsi, unsigned int flags)
104{ 104{
105 int i; 105 int i;
106 106
@@ -108,7 +108,7 @@ static int map_gsi_to_irq(unsigned int gsi)
108 if (isa_irq_to_gsi[i] == gsi) 108 if (isa_irq_to_gsi[i] == gsi)
109 return i; 109 return i;
110 110
111 return mp_map_gsi_to_irq(gsi); 111 return mp_map_gsi_to_irq(gsi, flags);
112} 112}
113 113
114/* 114/*
@@ -417,7 +417,7 @@ static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
417 if (acpi_gbl_FADT.sci_interrupt == gsi) 417 if (acpi_gbl_FADT.sci_interrupt == gsi)
418 return gsi; 418 return gsi;
419 419
420 irq = map_gsi_to_irq(gsi); 420 irq = map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC);
421 if (irq < 0) 421 if (irq < 0)
422 return irq; 422 return irq;
423 423
@@ -608,7 +608,7 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
608 608
609int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp) 609int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
610{ 610{
611 int irq = map_gsi_to_irq(gsi); 611 int irq = map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);
612 612
613 if (irq >= 0) { 613 if (irq >= 0) {
614#ifdef CONFIG_X86_IO_APIC 614#ifdef CONFIG_X86_IO_APIC
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 7fd9f1befe0b..51ce80004a78 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -31,6 +31,7 @@
31#include <linux/acpi.h> 31#include <linux/acpi.h>
32#include <linux/module.h> 32#include <linux/module.h>
33#include <linux/syscore_ops.h> 33#include <linux/syscore_ops.h>
34#include <linux/irqdomain.h>
34#include <linux/msi.h> 35#include <linux/msi.h>
35#include <linux/htirq.h> 36#include <linux/htirq.h>
36#include <linux/freezer.h> 37#include <linux/freezer.h>
@@ -83,6 +84,7 @@ int sis_apic_bug = -1;
83 84
84static DEFINE_RAW_SPINLOCK(ioapic_lock); 85static DEFINE_RAW_SPINLOCK(ioapic_lock);
85static DEFINE_RAW_SPINLOCK(vector_lock); 86static DEFINE_RAW_SPINLOCK(vector_lock);
87static DEFINE_MUTEX(ioapic_mutex);
86 88
87static struct ioapic { 89static struct ioapic {
88 /* 90 /*
@@ -97,6 +99,8 @@ static struct ioapic {
97 struct mpc_ioapic mp_config; 99 struct mpc_ioapic mp_config;
98 /* IO APIC gsi routing info */ 100 /* IO APIC gsi routing info */
99 struct mp_ioapic_gsi gsi_config; 101 struct mp_ioapic_gsi gsi_config;
102 struct ioapic_domain_cfg irqdomain_cfg;
103 struct irq_domain *irqdomain;
100 DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1); 104 DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
101} ioapics[MAX_IO_APICS]; 105} ioapics[MAX_IO_APICS];
102 106
@@ -142,6 +146,11 @@ static inline int mp_init_irq_at_boot(int ioapic, int irq)
142 return ioapic == 0 || (irq >= 0 && irq < nr_legacy_irqs()); 146 return ioapic == 0 || (irq >= 0 && irq < nr_legacy_irqs());
143} 147}
144 148
149static inline struct irq_domain *mp_ioapic_irqdomain(int ioapic)
150{
151 return ioapics[ioapic].irqdomain;
152}
153
145int nr_ioapics; 154int nr_ioapics;
146 155
147/* The one past the highest gsi number used */ 156/* The one past the highest gsi number used */
@@ -959,19 +968,79 @@ static int irq_trigger(int idx)
959 return trigger; 968 return trigger;
960} 969}
961 970
962int mp_map_gsi_to_irq(u32 gsi) 971static int alloc_irq_from_domain(struct irq_domain *domain, u32 gsi, int pin)
963{ 972{
973 int irq = -1;
974 int ioapic = (int)(long)domain->host_data;
975 int type = ioapics[ioapic].irqdomain_cfg.type;
976
977 switch (type) {
978 case IOAPIC_DOMAIN_LEGACY:
979 /*
980 * Dynamically allocate IRQ number for non-ISA IRQs in the first 16
981 * GSIs on some weird platforms.
982 */
983 if (gsi < nr_legacy_irqs())
984 irq = irq_create_mapping(domain, pin);
985 else if (irq_create_strict_mappings(domain, gsi, pin, 1) == 0)
986 irq = gsi;
987 break;
988 case IOAPIC_DOMAIN_STRICT:
989 if (irq_create_strict_mappings(domain, gsi, pin, 1) == 0)
990 irq = gsi;
991 break;
992 case IOAPIC_DOMAIN_DYNAMIC:
993 irq = irq_create_mapping(domain, pin);
994 break;
995 default:
996 WARN(1, "ioapic: unknown irqdomain type %d\n", type);
997 break;
998 }
999
1000 return irq > 0 ? irq : -1;
1001}
1002
1003static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin,
1004 unsigned int flags)
1005{
1006 int irq;
1007 struct irq_domain *domain = mp_ioapic_irqdomain(ioapic);
1008
964 /* 1009 /*
965 * Provide an identity mapping of gsi == irq except on truly weird 1010 * Don't use irqdomain to manage ISA IRQs because there may be
966 * platforms that have non isa irqs in the first 16 gsis. 1011 * multiple IOAPIC pins sharing the same ISA IRQ number and
1012 * irqdomain only supports 1:1 mapping between IOAPIC pin and
1013 * IRQ number. A typical IOAPIC has 24 pins, pin 0-15 are used
1014 * for legacy IRQs and pin 16-23 are used for PCI IRQs (PIRQ A-H).
1015 * When ACPI is disabled, only legacy IRQ numbers (IRQ0-15) are
1016 * available, and some BIOSes may use MP Interrupt Source records
1017 * to override IRQ numbers for PIRQs instead of reprogramming
1018 * the interrupt routing logic. Thus there may be multiple pins
1019 * sharing the same legacy IRQ number when ACPI is disabled.
967 */ 1020 */
968 return gsi >= nr_legacy_irqs() ? gsi : gsi_top + gsi; 1021 if (idx >= 0 && test_bit(mp_irqs[idx].srcbus, mp_bus_not_pci))
1022 return mp_irqs[idx].srcbusirq;
1023
1024 if (!domain) {
1025 /*
1026 * Provide an identity mapping of gsi == irq except on truly
1027 * weird platforms that have non isa irqs in the first 16 gsis.
1028 */
1029 return gsi >= nr_legacy_irqs() ? gsi : gsi_top + gsi;
1030 }
1031
1032 mutex_lock(&ioapic_mutex);
1033 irq = irq_find_mapping(domain, pin);
1034 if (irq <= 0 && (flags & IOAPIC_MAP_ALLOC))
1035 irq = alloc_irq_from_domain(domain, gsi, pin);
1036 mutex_unlock(&ioapic_mutex);
1037
1038 return irq > 0 ? irq : -1;
969} 1039}
970 1040
971static int pin_2_irq(int idx, int apic, int pin) 1041static int pin_2_irq(int idx, int ioapic, int pin, unsigned int flags)
972{ 1042{
973 int irq; 1043 u32 gsi = mp_pin_to_gsi(ioapic, pin);
974 int bus = mp_irqs[idx].srcbus;
975 1044
976 /* 1045 /*
977 * Debugging check, we are in big trouble if this message pops up! 1046 * Debugging check, we are in big trouble if this message pops up!
@@ -989,7 +1058,7 @@ static int pin_2_irq(int idx, int apic, int pin)
989 apic_printk(APIC_VERBOSE, KERN_DEBUG 1058 apic_printk(APIC_VERBOSE, KERN_DEBUG
990 "disabling PIRQ%d\n", pin-16); 1059 "disabling PIRQ%d\n", pin-16);
991 } else { 1060 } else {
992 irq = pirq_entries[pin-16]; 1061 int irq = pirq_entries[pin-16];
993 apic_printk(APIC_VERBOSE, KERN_DEBUG 1062 apic_printk(APIC_VERBOSE, KERN_DEBUG
994 "using PIRQ%d -> IRQ %d\n", 1063 "using PIRQ%d -> IRQ %d\n",
995 pin-16, irq); 1064 pin-16, irq);
@@ -999,12 +1068,23 @@ static int pin_2_irq(int idx, int apic, int pin)
999 } 1068 }
1000#endif 1069#endif
1001 1070
1002 if (test_bit(bus, mp_bus_not_pci)) 1071 return mp_map_pin_to_irq(gsi, idx, ioapic, pin, flags);
1003 irq = mp_irqs[idx].srcbusirq; 1072}
1004 else
1005 irq = mp_map_gsi_to_irq(mp_pin_to_gsi(apic, pin));
1006 1073
1007 return irq; 1074int mp_map_gsi_to_irq(u32 gsi, unsigned int flags)
1075{
1076 int ioapic, pin, idx;
1077
1078 ioapic = mp_find_ioapic(gsi);
1079 if (ioapic < 0)
1080 return -1;
1081
1082 pin = mp_find_ioapic_pin(ioapic, gsi);
1083 idx = find_irq_entry(ioapic, pin, mp_INT);
1084 if ((flags & IOAPIC_MAP_CHECK) && idx < 0)
1085 return -1;
1086
1087 return mp_map_pin_to_irq(gsi, idx, ioapic, pin, flags);
1008} 1088}
1009 1089
1010/* 1090/*
@@ -1014,7 +1094,7 @@ static int pin_2_irq(int idx, int apic, int pin)
1014int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin, 1094int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
1015 struct io_apic_irq_attr *irq_attr) 1095 struct io_apic_irq_attr *irq_attr)
1016{ 1096{
1017 int irq, i, best_guess = -1; 1097 int irq, i, best_ioapic = -1, best_idx = -1;
1018 1098
1019 apic_printk(APIC_DEBUG, 1099 apic_printk(APIC_DEBUG,
1020 "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n", 1100 "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
@@ -1043,30 +1123,37 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin,
1043 continue; 1123 continue;
1044 1124
1045 /* Skip ISA IRQs */ 1125 /* Skip ISA IRQs */
1046 irq = pin_2_irq(i, ioapic_idx, mp_irqs[i].dstirq); 1126 irq = pin_2_irq(i, ioapic_idx, mp_irqs[i].dstirq, 0);
1047 if (ioapic_idx == 0 && !IO_APIC_IRQ(irq)) 1127 if (irq > 0 && !IO_APIC_IRQ(irq))
1048 continue; 1128 continue;
1049 1129
1050 if (pin == (mp_irqs[i].srcbusirq & 3)) { 1130 if (pin == (mp_irqs[i].srcbusirq & 3)) {
1051 set_io_apic_irq_attr(irq_attr, ioapic_idx, 1131 best_idx = i;
1052 mp_irqs[i].dstirq, 1132 best_ioapic = ioapic_idx;
1053 irq_trigger(i), 1133 goto out;
1054 irq_polarity(i));
1055 return irq;
1056 } 1134 }
1135
1057 /* 1136 /*
1058 * Use the first all-but-pin matching entry as a 1137 * Use the first all-but-pin matching entry as a
1059 * best-guess fuzzy result for broken mptables. 1138 * best-guess fuzzy result for broken mptables.
1060 */ 1139 */
1061 if (best_guess < 0) { 1140 if (best_idx < 0) {
1062 set_io_apic_irq_attr(irq_attr, ioapic_idx, 1141 best_idx = i;
1063 mp_irqs[i].dstirq, 1142 best_ioapic = ioapic_idx;
1064 irq_trigger(i),
1065 irq_polarity(i));
1066 best_guess = irq;
1067 } 1143 }
1068 } 1144 }
1069 return best_guess; 1145 if (best_idx < 0)
1146 return -1;
1147
1148out:
1149 irq = pin_2_irq(best_idx, best_ioapic, mp_irqs[best_idx].dstirq,
1150 IOAPIC_MAP_ALLOC);
1151 if (irq > 0)
1152 set_io_apic_irq_attr(irq_attr, best_ioapic,
1153 mp_irqs[best_idx].dstirq,
1154 irq_trigger(best_idx),
1155 irq_polarity(best_idx));
1156 return irq;
1070} 1157}
1071EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector); 1158EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
1072 1159
@@ -1257,7 +1344,7 @@ static inline int IO_APIC_irq_trigger(int irq)
1257 1344
1258 for_each_ioapic_pin(apic, pin) { 1345 for_each_ioapic_pin(apic, pin) {
1259 idx = find_irq_entry(apic, pin, mp_INT); 1346 idx = find_irq_entry(apic, pin, mp_INT);
1260 if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin))) 1347 if ((idx != -1) && (irq == pin_2_irq(idx, apic, pin, 0)))
1261 return irq_trigger(idx); 1348 return irq_trigger(idx);
1262 } 1349 }
1263 /* 1350 /*
@@ -1383,8 +1470,9 @@ static void __init __io_apic_setup_irqs(unsigned int ioapic_idx)
1383 if (io_apic_pin_not_connected(idx, ioapic_idx, pin)) 1470 if (io_apic_pin_not_connected(idx, ioapic_idx, pin))
1384 continue; 1471 continue;
1385 1472
1386 irq = pin_2_irq(idx, ioapic_idx, pin); 1473 irq = pin_2_irq(idx, ioapic_idx, pin,
1387 if (!mp_init_irq_at_boot(ioapic_idx, irq)) 1474 ioapic_idx ? 0 : IOAPIC_MAP_ALLOC);
1475 if (irq < 0 || !mp_init_irq_at_boot(ioapic_idx, irq))
1388 continue; 1476 continue;
1389 1477
1390 /* 1478 /*
@@ -1434,8 +1522,8 @@ void setup_IO_APIC_irq_extra(u32 gsi)
1434 if (idx == -1) 1522 if (idx == -1)
1435 return; 1523 return;
1436 1524
1437 irq = pin_2_irq(idx, ioapic_idx, pin); 1525 irq = pin_2_irq(idx, ioapic_idx, pin, IOAPIC_MAP_ALLOC);
1438 if (mp_init_irq_at_boot(ioapic_idx, irq)) 1526 if (irq < 0 || mp_init_irq_at_boot(ioapic_idx, irq))
1439 return; 1527 return;
1440 1528
1441 set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx), 1529 set_io_apic_irq_attr(&attr, ioapic_idx, pin, irq_trigger(idx),
@@ -3543,8 +3631,8 @@ void __init setup_ioapic_dest(void)
3543 if (irq_entry == -1) 3631 if (irq_entry == -1)
3544 continue; 3632 continue;
3545 3633
3546 irq = pin_2_irq(irq_entry, ioapic, pin); 3634 irq = pin_2_irq(irq_entry, ioapic, pin, 0);
3547 if (!mp_init_irq_at_boot(ioapic, irq)) 3635 if (irq < 0 || !mp_init_irq_at_boot(ioapic, irq))
3548 continue; 3636 continue;
3549 3637
3550 idata = irq_get_irq_data(irq); 3638 idata = irq_get_irq_data(irq);