diff options
Diffstat (limited to 'arch/x86/kernel/apic/io_apic.c')
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 494 |
1 files changed, 221 insertions, 273 deletions
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 697dc34b7b87..68df09bba92e 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <linux/compiler.h> | 30 | #include <linux/compiler.h> |
31 | #include <linux/acpi.h> | 31 | #include <linux/acpi.h> |
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | #include <linux/sysdev.h> | 33 | #include <linux/syscore_ops.h> |
34 | #include <linux/msi.h> | 34 | #include <linux/msi.h> |
35 | #include <linux/htirq.h> | 35 | #include <linux/htirq.h> |
36 | #include <linux/freezer.h> | 36 | #include <linux/freezer.h> |
@@ -108,7 +108,10 @@ DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES); | |||
108 | 108 | ||
109 | int skip_ioapic_setup; | 109 | int skip_ioapic_setup; |
110 | 110 | ||
111 | void arch_disable_smp_support(void) | 111 | /** |
112 | * disable_ioapic_support() - disables ioapic support at runtime | ||
113 | */ | ||
114 | void disable_ioapic_support(void) | ||
112 | { | 115 | { |
113 | #ifdef CONFIG_PCI | 116 | #ifdef CONFIG_PCI |
114 | noioapicquirk = 1; | 117 | noioapicquirk = 1; |
@@ -120,11 +123,14 @@ void arch_disable_smp_support(void) | |||
120 | static int __init parse_noapic(char *str) | 123 | static int __init parse_noapic(char *str) |
121 | { | 124 | { |
122 | /* disable IO-APIC */ | 125 | /* disable IO-APIC */ |
123 | arch_disable_smp_support(); | 126 | disable_ioapic_support(); |
124 | return 0; | 127 | return 0; |
125 | } | 128 | } |
126 | early_param("noapic", parse_noapic); | 129 | early_param("noapic", parse_noapic); |
127 | 130 | ||
131 | static int io_apic_setup_irq_pin_once(unsigned int irq, int node, | ||
132 | struct io_apic_irq_attr *attr); | ||
133 | |||
128 | /* Will be called in mpparse/acpi/sfi codes for saving IRQ info */ | 134 | /* Will be called in mpparse/acpi/sfi codes for saving IRQ info */ |
129 | void mp_save_irq(struct mpc_intsrc *m) | 135 | void mp_save_irq(struct mpc_intsrc *m) |
130 | { | 136 | { |
@@ -181,7 +187,7 @@ int __init arch_early_irq_init(void) | |||
181 | irq_reserve_irqs(0, legacy_pic->nr_legacy_irqs); | 187 | irq_reserve_irqs(0, legacy_pic->nr_legacy_irqs); |
182 | 188 | ||
183 | for (i = 0; i < count; i++) { | 189 | for (i = 0; i < count; i++) { |
184 | set_irq_chip_data(i, &cfg[i]); | 190 | irq_set_chip_data(i, &cfg[i]); |
185 | zalloc_cpumask_var_node(&cfg[i].domain, GFP_KERNEL, node); | 191 | zalloc_cpumask_var_node(&cfg[i].domain, GFP_KERNEL, node); |
186 | zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_KERNEL, node); | 192 | zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_KERNEL, node); |
187 | /* | 193 | /* |
@@ -200,7 +206,7 @@ int __init arch_early_irq_init(void) | |||
200 | #ifdef CONFIG_SPARSE_IRQ | 206 | #ifdef CONFIG_SPARSE_IRQ |
201 | static struct irq_cfg *irq_cfg(unsigned int irq) | 207 | static struct irq_cfg *irq_cfg(unsigned int irq) |
202 | { | 208 | { |
203 | return get_irq_chip_data(irq); | 209 | return irq_get_chip_data(irq); |
204 | } | 210 | } |
205 | 211 | ||
206 | static struct irq_cfg *alloc_irq_cfg(unsigned int irq, int node) | 212 | static struct irq_cfg *alloc_irq_cfg(unsigned int irq, int node) |
@@ -226,7 +232,7 @@ static void free_irq_cfg(unsigned int at, struct irq_cfg *cfg) | |||
226 | { | 232 | { |
227 | if (!cfg) | 233 | if (!cfg) |
228 | return; | 234 | return; |
229 | set_irq_chip_data(at, NULL); | 235 | irq_set_chip_data(at, NULL); |
230 | free_cpumask_var(cfg->domain); | 236 | free_cpumask_var(cfg->domain); |
231 | free_cpumask_var(cfg->old_domain); | 237 | free_cpumask_var(cfg->old_domain); |
232 | kfree(cfg); | 238 | kfree(cfg); |
@@ -256,14 +262,14 @@ static struct irq_cfg *alloc_irq_and_cfg_at(unsigned int at, int node) | |||
256 | if (res < 0) { | 262 | if (res < 0) { |
257 | if (res != -EEXIST) | 263 | if (res != -EEXIST) |
258 | return NULL; | 264 | return NULL; |
259 | cfg = get_irq_chip_data(at); | 265 | cfg = irq_get_chip_data(at); |
260 | if (cfg) | 266 | if (cfg) |
261 | return cfg; | 267 | return cfg; |
262 | } | 268 | } |
263 | 269 | ||
264 | cfg = alloc_irq_cfg(at, node); | 270 | cfg = alloc_irq_cfg(at, node); |
265 | if (cfg) | 271 | if (cfg) |
266 | set_irq_chip_data(at, cfg); | 272 | irq_set_chip_data(at, cfg); |
267 | else | 273 | else |
268 | irq_free_desc(at); | 274 | irq_free_desc(at); |
269 | return cfg; | 275 | return cfg; |
@@ -818,7 +824,7 @@ static int EISA_ELCR(unsigned int irq) | |||
818 | #define default_MCA_trigger(idx) (1) | 824 | #define default_MCA_trigger(idx) (1) |
819 | #define default_MCA_polarity(idx) default_ISA_polarity(idx) | 825 | #define default_MCA_polarity(idx) default_ISA_polarity(idx) |
820 | 826 | ||
821 | static int MPBIOS_polarity(int idx) | 827 | static int irq_polarity(int idx) |
822 | { | 828 | { |
823 | int bus = mp_irqs[idx].srcbus; | 829 | int bus = mp_irqs[idx].srcbus; |
824 | int polarity; | 830 | int polarity; |
@@ -860,7 +866,7 @@ static int MPBIOS_polarity(int idx) | |||
860 | return polarity; | 866 | return polarity; |
861 | } | 867 | } |
862 | 868 | ||
863 | static int MPBIOS_trigger(int idx) | 869 | static int irq_trigger(int idx) |
864 | { | 870 | { |
865 | int bus = mp_irqs[idx].srcbus; | 871 | int bus = mp_irqs[idx].srcbus; |
866 | int trigger; | 872 | int trigger; |
@@ -932,16 +938,6 @@ static int MPBIOS_trigger(int idx) | |||
932 | return trigger; | 938 | return trigger; |
933 | } | 939 | } |
934 | 940 | ||
935 | static inline int irq_polarity(int idx) | ||
936 | { | ||
937 | return MPBIOS_polarity(idx); | ||
938 | } | ||
939 | |||
940 | static inline int irq_trigger(int idx) | ||
941 | { | ||
942 | return MPBIOS_trigger(idx); | ||
943 | } | ||
944 | |||
945 | static int pin_2_irq(int idx, int apic, int pin) | 941 | static int pin_2_irq(int idx, int apic, int pin) |
946 | { | 942 | { |
947 | int irq; | 943 | int irq; |
@@ -1189,7 +1185,7 @@ void __setup_vector_irq(int cpu) | |||
1189 | raw_spin_lock(&vector_lock); | 1185 | raw_spin_lock(&vector_lock); |
1190 | /* Mark the inuse vectors */ | 1186 | /* Mark the inuse vectors */ |
1191 | for_each_active_irq(irq) { | 1187 | for_each_active_irq(irq) { |
1192 | cfg = get_irq_chip_data(irq); | 1188 | cfg = irq_get_chip_data(irq); |
1193 | if (!cfg) | 1189 | if (!cfg) |
1194 | continue; | 1190 | continue; |
1195 | /* | 1191 | /* |
@@ -1220,10 +1216,6 @@ void __setup_vector_irq(int cpu) | |||
1220 | static struct irq_chip ioapic_chip; | 1216 | static struct irq_chip ioapic_chip; |
1221 | static struct irq_chip ir_ioapic_chip; | 1217 | static struct irq_chip ir_ioapic_chip; |
1222 | 1218 | ||
1223 | #define IOAPIC_AUTO -1 | ||
1224 | #define IOAPIC_EDGE 0 | ||
1225 | #define IOAPIC_LEVEL 1 | ||
1226 | |||
1227 | #ifdef CONFIG_X86_32 | 1219 | #ifdef CONFIG_X86_32 |
1228 | static inline int IO_APIC_irq_trigger(int irq) | 1220 | static inline int IO_APIC_irq_trigger(int irq) |
1229 | { | 1221 | { |
@@ -1248,35 +1240,31 @@ static inline int IO_APIC_irq_trigger(int irq) | |||
1248 | } | 1240 | } |
1249 | #endif | 1241 | #endif |
1250 | 1242 | ||
1251 | static void ioapic_register_intr(unsigned int irq, unsigned long trigger) | 1243 | static void ioapic_register_intr(unsigned int irq, struct irq_cfg *cfg, |
1244 | unsigned long trigger) | ||
1252 | { | 1245 | { |
1246 | struct irq_chip *chip = &ioapic_chip; | ||
1247 | irq_flow_handler_t hdl; | ||
1248 | bool fasteoi; | ||
1253 | 1249 | ||
1254 | if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) || | 1250 | if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) || |
1255 | trigger == IOAPIC_LEVEL) | 1251 | trigger == IOAPIC_LEVEL) { |
1256 | irq_set_status_flags(irq, IRQ_LEVEL); | 1252 | irq_set_status_flags(irq, IRQ_LEVEL); |
1257 | else | 1253 | fasteoi = true; |
1254 | } else { | ||
1258 | irq_clear_status_flags(irq, IRQ_LEVEL); | 1255 | irq_clear_status_flags(irq, IRQ_LEVEL); |
1256 | fasteoi = false; | ||
1257 | } | ||
1259 | 1258 | ||
1260 | if (irq_remapped(get_irq_chip_data(irq))) { | 1259 | if (irq_remapped(cfg)) { |
1261 | irq_set_status_flags(irq, IRQ_MOVE_PCNTXT); | 1260 | irq_set_status_flags(irq, IRQ_MOVE_PCNTXT); |
1262 | if (trigger) | 1261 | chip = &ir_ioapic_chip; |
1263 | set_irq_chip_and_handler_name(irq, &ir_ioapic_chip, | 1262 | fasteoi = trigger != 0; |
1264 | handle_fasteoi_irq, | ||
1265 | "fasteoi"); | ||
1266 | else | ||
1267 | set_irq_chip_and_handler_name(irq, &ir_ioapic_chip, | ||
1268 | handle_edge_irq, "edge"); | ||
1269 | return; | ||
1270 | } | 1263 | } |
1271 | 1264 | ||
1272 | if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) || | 1265 | hdl = fasteoi ? handle_fasteoi_irq : handle_edge_irq; |
1273 | trigger == IOAPIC_LEVEL) | 1266 | irq_set_chip_and_handler_name(irq, chip, hdl, |
1274 | set_irq_chip_and_handler_name(irq, &ioapic_chip, | 1267 | fasteoi ? "fasteoi" : "edge"); |
1275 | handle_fasteoi_irq, | ||
1276 | "fasteoi"); | ||
1277 | else | ||
1278 | set_irq_chip_and_handler_name(irq, &ioapic_chip, | ||
1279 | handle_edge_irq, "edge"); | ||
1280 | } | 1268 | } |
1281 | 1269 | ||
1282 | static int setup_ioapic_entry(int apic_id, int irq, | 1270 | static int setup_ioapic_entry(int apic_id, int irq, |
@@ -1374,7 +1362,7 @@ static void setup_ioapic_irq(int apic_id, int pin, unsigned int irq, | |||
1374 | return; | 1362 | return; |
1375 | } | 1363 | } |
1376 | 1364 | ||
1377 | ioapic_register_intr(irq, trigger); | 1365 | ioapic_register_intr(irq, cfg, trigger); |
1378 | if (irq < legacy_pic->nr_legacy_irqs) | 1366 | if (irq < legacy_pic->nr_legacy_irqs) |
1379 | legacy_pic->mask(irq); | 1367 | legacy_pic->mask(irq); |
1380 | 1368 | ||
@@ -1385,33 +1373,26 @@ static struct { | |||
1385 | DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1); | 1373 | DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1); |
1386 | } mp_ioapic_routing[MAX_IO_APICS]; | 1374 | } mp_ioapic_routing[MAX_IO_APICS]; |
1387 | 1375 | ||
1388 | static void __init setup_IO_APIC_irqs(void) | 1376 | static bool __init io_apic_pin_not_connected(int idx, int apic_id, int pin) |
1389 | { | 1377 | { |
1390 | int apic_id, pin, idx, irq, notcon = 0; | 1378 | if (idx != -1) |
1391 | int node = cpu_to_node(0); | 1379 | return false; |
1392 | struct irq_cfg *cfg; | ||
1393 | 1380 | ||
1394 | apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); | 1381 | apic_printk(APIC_VERBOSE, KERN_DEBUG " apic %d pin %d not connected\n", |
1382 | mp_ioapics[apic_id].apicid, pin); | ||
1383 | return true; | ||
1384 | } | ||
1385 | |||
1386 | static void __init __io_apic_setup_irqs(unsigned int apic_id) | ||
1387 | { | ||
1388 | int idx, node = cpu_to_node(0); | ||
1389 | struct io_apic_irq_attr attr; | ||
1390 | unsigned int pin, irq; | ||
1395 | 1391 | ||
1396 | for (apic_id = 0; apic_id < nr_ioapics; apic_id++) | ||
1397 | for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) { | 1392 | for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) { |
1398 | idx = find_irq_entry(apic_id, pin, mp_INT); | 1393 | idx = find_irq_entry(apic_id, pin, mp_INT); |
1399 | if (idx == -1) { | 1394 | if (io_apic_pin_not_connected(idx, apic_id, pin)) |
1400 | if (!notcon) { | ||
1401 | notcon = 1; | ||
1402 | apic_printk(APIC_VERBOSE, | ||
1403 | KERN_DEBUG " %d-%d", | ||
1404 | mp_ioapics[apic_id].apicid, pin); | ||
1405 | } else | ||
1406 | apic_printk(APIC_VERBOSE, " %d-%d", | ||
1407 | mp_ioapics[apic_id].apicid, pin); | ||
1408 | continue; | 1395 | continue; |
1409 | } | ||
1410 | if (notcon) { | ||
1411 | apic_printk(APIC_VERBOSE, | ||
1412 | " (apicid-pin) not connected\n"); | ||
1413 | notcon = 0; | ||
1414 | } | ||
1415 | 1396 | ||
1416 | irq = pin_2_irq(idx, apic_id, pin); | 1397 | irq = pin_2_irq(idx, apic_id, pin); |
1417 | 1398 | ||
@@ -1423,25 +1404,24 @@ static void __init setup_IO_APIC_irqs(void) | |||
1423 | * installed and if it returns 1: | 1404 | * installed and if it returns 1: |
1424 | */ | 1405 | */ |
1425 | if (apic->multi_timer_check && | 1406 | if (apic->multi_timer_check && |
1426 | apic->multi_timer_check(apic_id, irq)) | 1407 | apic->multi_timer_check(apic_id, irq)) |
1427 | continue; | 1408 | continue; |
1428 | 1409 | ||
1429 | cfg = alloc_irq_and_cfg_at(irq, node); | 1410 | set_io_apic_irq_attr(&attr, apic_id, pin, irq_trigger(idx), |
1430 | if (!cfg) | 1411 | irq_polarity(idx)); |
1431 | continue; | ||
1432 | 1412 | ||
1433 | add_pin_to_irq_node(cfg, node, apic_id, pin); | 1413 | io_apic_setup_irq_pin(irq, node, &attr); |
1434 | /* | ||
1435 | * don't mark it in pin_programmed, so later acpi could | ||
1436 | * set it correctly when irq < 16 | ||
1437 | */ | ||
1438 | setup_ioapic_irq(apic_id, pin, irq, cfg, irq_trigger(idx), | ||
1439 | irq_polarity(idx)); | ||
1440 | } | 1414 | } |
1415 | } | ||
1441 | 1416 | ||
1442 | if (notcon) | 1417 | static void __init setup_IO_APIC_irqs(void) |
1443 | apic_printk(APIC_VERBOSE, | 1418 | { |
1444 | " (apicid-pin) not connected\n"); | 1419 | unsigned int apic_id; |
1420 | |||
1421 | apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); | ||
1422 | |||
1423 | for (apic_id = 0; apic_id < nr_ioapics; apic_id++) | ||
1424 | __io_apic_setup_irqs(apic_id); | ||
1445 | } | 1425 | } |
1446 | 1426 | ||
1447 | /* | 1427 | /* |
@@ -1452,7 +1432,7 @@ static void __init setup_IO_APIC_irqs(void) | |||
1452 | void setup_IO_APIC_irq_extra(u32 gsi) | 1432 | void setup_IO_APIC_irq_extra(u32 gsi) |
1453 | { | 1433 | { |
1454 | int apic_id = 0, pin, idx, irq, node = cpu_to_node(0); | 1434 | int apic_id = 0, pin, idx, irq, node = cpu_to_node(0); |
1455 | struct irq_cfg *cfg; | 1435 | struct io_apic_irq_attr attr; |
1456 | 1436 | ||
1457 | /* | 1437 | /* |
1458 | * Convert 'gsi' to 'ioapic.pin'. | 1438 | * Convert 'gsi' to 'ioapic.pin'. |
@@ -1472,21 +1452,10 @@ void setup_IO_APIC_irq_extra(u32 gsi) | |||
1472 | if (apic_id == 0 || irq < NR_IRQS_LEGACY) | 1452 | if (apic_id == 0 || irq < NR_IRQS_LEGACY) |
1473 | return; | 1453 | return; |
1474 | 1454 | ||
1475 | cfg = alloc_irq_and_cfg_at(irq, node); | 1455 | set_io_apic_irq_attr(&attr, apic_id, pin, irq_trigger(idx), |
1476 | if (!cfg) | 1456 | irq_polarity(idx)); |
1477 | return; | ||
1478 | |||
1479 | add_pin_to_irq_node(cfg, node, apic_id, pin); | ||
1480 | |||
1481 | if (test_bit(pin, mp_ioapic_routing[apic_id].pin_programmed)) { | ||
1482 | pr_debug("Pin %d-%d already programmed\n", | ||
1483 | mp_ioapics[apic_id].apicid, pin); | ||
1484 | return; | ||
1485 | } | ||
1486 | set_bit(pin, mp_ioapic_routing[apic_id].pin_programmed); | ||
1487 | 1457 | ||
1488 | setup_ioapic_irq(apic_id, pin, irq, cfg, | 1458 | io_apic_setup_irq_pin_once(irq, node, &attr); |
1489 | irq_trigger(idx), irq_polarity(idx)); | ||
1490 | } | 1459 | } |
1491 | 1460 | ||
1492 | /* | 1461 | /* |
@@ -1518,7 +1487,8 @@ static void __init setup_timer_IRQ0_pin(unsigned int apic_id, unsigned int pin, | |||
1518 | * The timer IRQ doesn't have to know that behind the | 1487 | * The timer IRQ doesn't have to know that behind the |
1519 | * scene we may have a 8259A-master in AEOI mode ... | 1488 | * scene we may have a 8259A-master in AEOI mode ... |
1520 | */ | 1489 | */ |
1521 | set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge"); | 1490 | irq_set_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, |
1491 | "edge"); | ||
1522 | 1492 | ||
1523 | /* | 1493 | /* |
1524 | * Add it to the IO-APIC irq-routing table: | 1494 | * Add it to the IO-APIC irq-routing table: |
@@ -1625,7 +1595,7 @@ __apicdebuginit(void) print_IO_APIC(void) | |||
1625 | for_each_active_irq(irq) { | 1595 | for_each_active_irq(irq) { |
1626 | struct irq_pin_list *entry; | 1596 | struct irq_pin_list *entry; |
1627 | 1597 | ||
1628 | cfg = get_irq_chip_data(irq); | 1598 | cfg = irq_get_chip_data(irq); |
1629 | if (!cfg) | 1599 | if (!cfg) |
1630 | continue; | 1600 | continue; |
1631 | entry = cfg->irq_2_pin; | 1601 | entry = cfg->irq_2_pin; |
@@ -1916,7 +1886,7 @@ void disable_IO_APIC(void) | |||
1916 | * | 1886 | * |
1917 | * With interrupt-remapping, for now we will use virtual wire A mode, | 1887 | * With interrupt-remapping, for now we will use virtual wire A mode, |
1918 | * as virtual wire B is little complex (need to configure both | 1888 | * as virtual wire B is little complex (need to configure both |
1919 | * IOAPIC RTE aswell as interrupt-remapping table entry). | 1889 | * IOAPIC RTE as well as interrupt-remapping table entry). |
1920 | * As this gets called during crash dump, keep this simple for now. | 1890 | * As this gets called during crash dump, keep this simple for now. |
1921 | */ | 1891 | */ |
1922 | if (ioapic_i8259.pin != -1 && !intr_remapping_enabled) { | 1892 | if (ioapic_i8259.pin != -1 && !intr_remapping_enabled) { |
@@ -2391,7 +2361,7 @@ static void irq_complete_move(struct irq_cfg *cfg) | |||
2391 | 2361 | ||
2392 | void irq_force_complete_move(int irq) | 2362 | void irq_force_complete_move(int irq) |
2393 | { | 2363 | { |
2394 | struct irq_cfg *cfg = get_irq_chip_data(irq); | 2364 | struct irq_cfg *cfg = irq_get_chip_data(irq); |
2395 | 2365 | ||
2396 | if (!cfg) | 2366 | if (!cfg) |
2397 | return; | 2367 | return; |
@@ -2405,7 +2375,7 @@ static inline void irq_complete_move(struct irq_cfg *cfg) { } | |||
2405 | static void ack_apic_edge(struct irq_data *data) | 2375 | static void ack_apic_edge(struct irq_data *data) |
2406 | { | 2376 | { |
2407 | irq_complete_move(data->chip_data); | 2377 | irq_complete_move(data->chip_data); |
2408 | move_native_irq(data->irq); | 2378 | irq_move_irq(data); |
2409 | ack_APIC_irq(); | 2379 | ack_APIC_irq(); |
2410 | } | 2380 | } |
2411 | 2381 | ||
@@ -2462,7 +2432,7 @@ static void ack_apic_level(struct irq_data *data) | |||
2462 | irq_complete_move(cfg); | 2432 | irq_complete_move(cfg); |
2463 | #ifdef CONFIG_GENERIC_PENDING_IRQ | 2433 | #ifdef CONFIG_GENERIC_PENDING_IRQ |
2464 | /* If we are moving the irq we need to mask it */ | 2434 | /* If we are moving the irq we need to mask it */ |
2465 | if (unlikely(irq_to_desc(irq)->status & IRQ_MOVE_PENDING)) { | 2435 | if (unlikely(irqd_is_setaffinity_pending(data))) { |
2466 | do_unmask_irq = 1; | 2436 | do_unmask_irq = 1; |
2467 | mask_ioapic(cfg); | 2437 | mask_ioapic(cfg); |
2468 | } | 2438 | } |
@@ -2551,7 +2521,7 @@ static void ack_apic_level(struct irq_data *data) | |||
2551 | * and you can go talk to the chipset vendor about it. | 2521 | * and you can go talk to the chipset vendor about it. |
2552 | */ | 2522 | */ |
2553 | if (!io_apic_level_ack_pending(cfg)) | 2523 | if (!io_apic_level_ack_pending(cfg)) |
2554 | move_masked_irq(irq); | 2524 | irq_move_masked_irq(data); |
2555 | unmask_ioapic(cfg); | 2525 | unmask_ioapic(cfg); |
2556 | } | 2526 | } |
2557 | } | 2527 | } |
@@ -2614,7 +2584,7 @@ static inline void init_IO_APIC_traps(void) | |||
2614 | * 0x80, because int 0x80 is hm, kind of importantish. ;) | 2584 | * 0x80, because int 0x80 is hm, kind of importantish. ;) |
2615 | */ | 2585 | */ |
2616 | for_each_active_irq(irq) { | 2586 | for_each_active_irq(irq) { |
2617 | cfg = get_irq_chip_data(irq); | 2587 | cfg = irq_get_chip_data(irq); |
2618 | if (IO_APIC_IRQ(irq) && cfg && !cfg->vector) { | 2588 | if (IO_APIC_IRQ(irq) && cfg && !cfg->vector) { |
2619 | /* | 2589 | /* |
2620 | * Hmm.. We don't have an entry for this, | 2590 | * Hmm.. We don't have an entry for this, |
@@ -2625,7 +2595,7 @@ static inline void init_IO_APIC_traps(void) | |||
2625 | legacy_pic->make_irq(irq); | 2595 | legacy_pic->make_irq(irq); |
2626 | else | 2596 | else |
2627 | /* Strange. Oh, well.. */ | 2597 | /* Strange. Oh, well.. */ |
2628 | set_irq_chip(irq, &no_irq_chip); | 2598 | irq_set_chip(irq, &no_irq_chip); |
2629 | } | 2599 | } |
2630 | } | 2600 | } |
2631 | } | 2601 | } |
@@ -2665,7 +2635,7 @@ static struct irq_chip lapic_chip __read_mostly = { | |||
2665 | static void lapic_register_intr(int irq) | 2635 | static void lapic_register_intr(int irq) |
2666 | { | 2636 | { |
2667 | irq_clear_status_flags(irq, IRQ_LEVEL); | 2637 | irq_clear_status_flags(irq, IRQ_LEVEL); |
2668 | set_irq_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq, | 2638 | irq_set_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq, |
2669 | "edge"); | 2639 | "edge"); |
2670 | } | 2640 | } |
2671 | 2641 | ||
@@ -2749,7 +2719,7 @@ int timer_through_8259 __initdata; | |||
2749 | */ | 2719 | */ |
2750 | static inline void __init check_timer(void) | 2720 | static inline void __init check_timer(void) |
2751 | { | 2721 | { |
2752 | struct irq_cfg *cfg = get_irq_chip_data(0); | 2722 | struct irq_cfg *cfg = irq_get_chip_data(0); |
2753 | int node = cpu_to_node(0); | 2723 | int node = cpu_to_node(0); |
2754 | int apic1, pin1, apic2, pin2; | 2724 | int apic1, pin1, apic2, pin2; |
2755 | unsigned long flags; | 2725 | unsigned long flags; |
@@ -2935,7 +2905,7 @@ void __init setup_IO_APIC(void) | |||
2935 | } | 2905 | } |
2936 | 2906 | ||
2937 | /* | 2907 | /* |
2938 | * Called after all the initialization is done. If we didnt find any | 2908 | * Called after all the initialization is done. If we didn't find any |
2939 | * APIC bugs then we can allow the modify fast path | 2909 | * APIC bugs then we can allow the modify fast path |
2940 | */ | 2910 | */ |
2941 | 2911 | ||
@@ -2948,89 +2918,84 @@ static int __init io_apic_bug_finalize(void) | |||
2948 | 2918 | ||
2949 | late_initcall(io_apic_bug_finalize); | 2919 | late_initcall(io_apic_bug_finalize); |
2950 | 2920 | ||
2951 | struct sysfs_ioapic_data { | 2921 | static struct IO_APIC_route_entry *ioapic_saved_data[MAX_IO_APICS]; |
2952 | struct sys_device dev; | ||
2953 | struct IO_APIC_route_entry entry[0]; | ||
2954 | }; | ||
2955 | static struct sysfs_ioapic_data * mp_ioapic_data[MAX_IO_APICS]; | ||
2956 | 2922 | ||
2957 | static int ioapic_suspend(struct sys_device *dev, pm_message_t state) | 2923 | static void suspend_ioapic(int ioapic_id) |
2958 | { | 2924 | { |
2959 | struct IO_APIC_route_entry *entry; | 2925 | struct IO_APIC_route_entry *saved_data = ioapic_saved_data[ioapic_id]; |
2960 | struct sysfs_ioapic_data *data; | ||
2961 | int i; | 2926 | int i; |
2962 | 2927 | ||
2963 | data = container_of(dev, struct sysfs_ioapic_data, dev); | 2928 | if (!saved_data) |
2964 | entry = data->entry; | 2929 | return; |
2965 | for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) | 2930 | |
2966 | *entry = ioapic_read_entry(dev->id, i); | 2931 | for (i = 0; i < nr_ioapic_registers[ioapic_id]; i++) |
2932 | saved_data[i] = ioapic_read_entry(ioapic_id, i); | ||
2933 | } | ||
2934 | |||
2935 | static int ioapic_suspend(void) | ||
2936 | { | ||
2937 | int ioapic_id; | ||
2938 | |||
2939 | for (ioapic_id = 0; ioapic_id < nr_ioapics; ioapic_id++) | ||
2940 | suspend_ioapic(ioapic_id); | ||
2967 | 2941 | ||
2968 | return 0; | 2942 | return 0; |
2969 | } | 2943 | } |
2970 | 2944 | ||
2971 | static int ioapic_resume(struct sys_device *dev) | 2945 | static void resume_ioapic(int ioapic_id) |
2972 | { | 2946 | { |
2973 | struct IO_APIC_route_entry *entry; | 2947 | struct IO_APIC_route_entry *saved_data = ioapic_saved_data[ioapic_id]; |
2974 | struct sysfs_ioapic_data *data; | ||
2975 | unsigned long flags; | 2948 | unsigned long flags; |
2976 | union IO_APIC_reg_00 reg_00; | 2949 | union IO_APIC_reg_00 reg_00; |
2977 | int i; | 2950 | int i; |
2978 | 2951 | ||
2979 | data = container_of(dev, struct sysfs_ioapic_data, dev); | 2952 | if (!saved_data) |
2980 | entry = data->entry; | 2953 | return; |
2981 | 2954 | ||
2982 | raw_spin_lock_irqsave(&ioapic_lock, flags); | 2955 | raw_spin_lock_irqsave(&ioapic_lock, flags); |
2983 | reg_00.raw = io_apic_read(dev->id, 0); | 2956 | reg_00.raw = io_apic_read(ioapic_id, 0); |
2984 | if (reg_00.bits.ID != mp_ioapics[dev->id].apicid) { | 2957 | if (reg_00.bits.ID != mp_ioapics[ioapic_id].apicid) { |
2985 | reg_00.bits.ID = mp_ioapics[dev->id].apicid; | 2958 | reg_00.bits.ID = mp_ioapics[ioapic_id].apicid; |
2986 | io_apic_write(dev->id, 0, reg_00.raw); | 2959 | io_apic_write(ioapic_id, 0, reg_00.raw); |
2987 | } | 2960 | } |
2988 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); | 2961 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); |
2989 | for (i = 0; i < nr_ioapic_registers[dev->id]; i++) | 2962 | for (i = 0; i < nr_ioapic_registers[ioapic_id]; i++) |
2990 | ioapic_write_entry(dev->id, i, entry[i]); | 2963 | ioapic_write_entry(ioapic_id, i, saved_data[i]); |
2964 | } | ||
2991 | 2965 | ||
2992 | return 0; | 2966 | static void ioapic_resume(void) |
2967 | { | ||
2968 | int ioapic_id; | ||
2969 | |||
2970 | for (ioapic_id = nr_ioapics - 1; ioapic_id >= 0; ioapic_id--) | ||
2971 | resume_ioapic(ioapic_id); | ||
2993 | } | 2972 | } |
2994 | 2973 | ||
2995 | static struct sysdev_class ioapic_sysdev_class = { | 2974 | static struct syscore_ops ioapic_syscore_ops = { |
2996 | .name = "ioapic", | ||
2997 | .suspend = ioapic_suspend, | 2975 | .suspend = ioapic_suspend, |
2998 | .resume = ioapic_resume, | 2976 | .resume = ioapic_resume, |
2999 | }; | 2977 | }; |
3000 | 2978 | ||
3001 | static int __init ioapic_init_sysfs(void) | 2979 | static int __init ioapic_init_ops(void) |
3002 | { | 2980 | { |
3003 | struct sys_device * dev; | 2981 | int i; |
3004 | int i, size, error; | ||
3005 | 2982 | ||
3006 | error = sysdev_class_register(&ioapic_sysdev_class); | 2983 | for (i = 0; i < nr_ioapics; i++) { |
3007 | if (error) | 2984 | unsigned int size; |
3008 | return error; | ||
3009 | 2985 | ||
3010 | for (i = 0; i < nr_ioapics; i++ ) { | 2986 | size = nr_ioapic_registers[i] |
3011 | size = sizeof(struct sys_device) + nr_ioapic_registers[i] | ||
3012 | * sizeof(struct IO_APIC_route_entry); | 2987 | * sizeof(struct IO_APIC_route_entry); |
3013 | mp_ioapic_data[i] = kzalloc(size, GFP_KERNEL); | 2988 | ioapic_saved_data[i] = kzalloc(size, GFP_KERNEL); |
3014 | if (!mp_ioapic_data[i]) { | 2989 | if (!ioapic_saved_data[i]) |
3015 | printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i); | 2990 | pr_err("IOAPIC %d: suspend/resume impossible!\n", i); |
3016 | continue; | ||
3017 | } | ||
3018 | dev = &mp_ioapic_data[i]->dev; | ||
3019 | dev->id = i; | ||
3020 | dev->cls = &ioapic_sysdev_class; | ||
3021 | error = sysdev_register(dev); | ||
3022 | if (error) { | ||
3023 | kfree(mp_ioapic_data[i]); | ||
3024 | mp_ioapic_data[i] = NULL; | ||
3025 | printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i); | ||
3026 | continue; | ||
3027 | } | ||
3028 | } | 2991 | } |
3029 | 2992 | ||
2993 | register_syscore_ops(&ioapic_syscore_ops); | ||
2994 | |||
3030 | return 0; | 2995 | return 0; |
3031 | } | 2996 | } |
3032 | 2997 | ||
3033 | device_initcall(ioapic_init_sysfs); | 2998 | device_initcall(ioapic_init_ops); |
3034 | 2999 | ||
3035 | /* | 3000 | /* |
3036 | * Dynamic irq allocate and deallocation | 3001 | * Dynamic irq allocate and deallocation |
@@ -3060,7 +3025,7 @@ unsigned int create_irq_nr(unsigned int from, int node) | |||
3060 | raw_spin_unlock_irqrestore(&vector_lock, flags); | 3025 | raw_spin_unlock_irqrestore(&vector_lock, flags); |
3061 | 3026 | ||
3062 | if (ret) { | 3027 | if (ret) { |
3063 | set_irq_chip_data(irq, cfg); | 3028 | irq_set_chip_data(irq, cfg); |
3064 | irq_clear_status_flags(irq, IRQ_NOREQUEST); | 3029 | irq_clear_status_flags(irq, IRQ_NOREQUEST); |
3065 | } else { | 3030 | } else { |
3066 | free_irq_at(irq, cfg); | 3031 | free_irq_at(irq, cfg); |
@@ -3085,7 +3050,7 @@ int create_irq(void) | |||
3085 | 3050 | ||
3086 | void destroy_irq(unsigned int irq) | 3051 | void destroy_irq(unsigned int irq) |
3087 | { | 3052 | { |
3088 | struct irq_cfg *cfg = get_irq_chip_data(irq); | 3053 | struct irq_cfg *cfg = irq_get_chip_data(irq); |
3089 | unsigned long flags; | 3054 | unsigned long flags; |
3090 | 3055 | ||
3091 | irq_set_status_flags(irq, IRQ_NOREQUEST|IRQ_NOPROBE); | 3056 | irq_set_status_flags(irq, IRQ_NOREQUEST|IRQ_NOPROBE); |
@@ -3119,7 +3084,7 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, | |||
3119 | 3084 | ||
3120 | dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus()); | 3085 | dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus()); |
3121 | 3086 | ||
3122 | if (irq_remapped(get_irq_chip_data(irq))) { | 3087 | if (irq_remapped(cfg)) { |
3123 | struct irte irte; | 3088 | struct irte irte; |
3124 | int ir_index; | 3089 | int ir_index; |
3125 | u16 sub_handle; | 3090 | u16 sub_handle; |
@@ -3291,6 +3256,7 @@ static int msi_alloc_irte(struct pci_dev *dev, int irq, int nvec) | |||
3291 | 3256 | ||
3292 | static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq) | 3257 | static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq) |
3293 | { | 3258 | { |
3259 | struct irq_chip *chip = &msi_chip; | ||
3294 | struct msi_msg msg; | 3260 | struct msi_msg msg; |
3295 | int ret; | 3261 | int ret; |
3296 | 3262 | ||
@@ -3298,14 +3264,15 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq) | |||
3298 | if (ret < 0) | 3264 | if (ret < 0) |
3299 | return ret; | 3265 | return ret; |
3300 | 3266 | ||
3301 | set_irq_msi(irq, msidesc); | 3267 | irq_set_msi_desc(irq, msidesc); |
3302 | write_msi_msg(irq, &msg); | 3268 | write_msi_msg(irq, &msg); |
3303 | 3269 | ||
3304 | if (irq_remapped(get_irq_chip_data(irq))) { | 3270 | if (irq_remapped(irq_get_chip_data(irq))) { |
3305 | irq_set_status_flags(irq, IRQ_MOVE_PCNTXT); | 3271 | irq_set_status_flags(irq, IRQ_MOVE_PCNTXT); |
3306 | set_irq_chip_and_handler_name(irq, &msi_ir_chip, handle_edge_irq, "edge"); | 3272 | chip = &msi_ir_chip; |
3307 | } else | 3273 | } |
3308 | set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge"); | 3274 | |
3275 | irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge"); | ||
3309 | 3276 | ||
3310 | dev_printk(KERN_DEBUG, &dev->dev, "irq %d for MSI/MSI-X\n", irq); | 3277 | dev_printk(KERN_DEBUG, &dev->dev, "irq %d for MSI/MSI-X\n", irq); |
3311 | 3278 | ||
@@ -3423,8 +3390,8 @@ int arch_setup_dmar_msi(unsigned int irq) | |||
3423 | if (ret < 0) | 3390 | if (ret < 0) |
3424 | return ret; | 3391 | return ret; |
3425 | dmar_msi_write(irq, &msg); | 3392 | dmar_msi_write(irq, &msg); |
3426 | set_irq_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq, | 3393 | irq_set_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq, |
3427 | "edge"); | 3394 | "edge"); |
3428 | return 0; | 3395 | return 0; |
3429 | } | 3396 | } |
3430 | #endif | 3397 | #endif |
@@ -3482,6 +3449,7 @@ static struct irq_chip hpet_msi_type = { | |||
3482 | 3449 | ||
3483 | int arch_setup_hpet_msi(unsigned int irq, unsigned int id) | 3450 | int arch_setup_hpet_msi(unsigned int irq, unsigned int id) |
3484 | { | 3451 | { |
3452 | struct irq_chip *chip = &hpet_msi_type; | ||
3485 | struct msi_msg msg; | 3453 | struct msi_msg msg; |
3486 | int ret; | 3454 | int ret; |
3487 | 3455 | ||
@@ -3501,15 +3469,12 @@ int arch_setup_hpet_msi(unsigned int irq, unsigned int id) | |||
3501 | if (ret < 0) | 3469 | if (ret < 0) |
3502 | return ret; | 3470 | return ret; |
3503 | 3471 | ||
3504 | hpet_msi_write(get_irq_data(irq), &msg); | 3472 | hpet_msi_write(irq_get_handler_data(irq), &msg); |
3505 | irq_set_status_flags(irq, IRQ_MOVE_PCNTXT); | 3473 | irq_set_status_flags(irq, IRQ_MOVE_PCNTXT); |
3506 | if (irq_remapped(get_irq_chip_data(irq))) | 3474 | if (irq_remapped(irq_get_chip_data(irq))) |
3507 | set_irq_chip_and_handler_name(irq, &ir_hpet_msi_type, | 3475 | chip = &ir_hpet_msi_type; |
3508 | handle_edge_irq, "edge"); | ||
3509 | else | ||
3510 | set_irq_chip_and_handler_name(irq, &hpet_msi_type, | ||
3511 | handle_edge_irq, "edge"); | ||
3512 | 3476 | ||
3477 | irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge"); | ||
3513 | return 0; | 3478 | return 0; |
3514 | } | 3479 | } |
3515 | #endif | 3480 | #endif |
@@ -3596,7 +3561,7 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev) | |||
3596 | 3561 | ||
3597 | write_ht_irq_msg(irq, &msg); | 3562 | write_ht_irq_msg(irq, &msg); |
3598 | 3563 | ||
3599 | set_irq_chip_and_handler_name(irq, &ht_irq_chip, | 3564 | irq_set_chip_and_handler_name(irq, &ht_irq_chip, |
3600 | handle_edge_irq, "edge"); | 3565 | handle_edge_irq, "edge"); |
3601 | 3566 | ||
3602 | dev_printk(KERN_DEBUG, &dev->dev, "irq %d for HT\n", irq); | 3567 | dev_printk(KERN_DEBUG, &dev->dev, "irq %d for HT\n", irq); |
@@ -3605,7 +3570,40 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev) | |||
3605 | } | 3570 | } |
3606 | #endif /* CONFIG_HT_IRQ */ | 3571 | #endif /* CONFIG_HT_IRQ */ |
3607 | 3572 | ||
3608 | int __init io_apic_get_redir_entries (int ioapic) | 3573 | int |
3574 | io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr) | ||
3575 | { | ||
3576 | struct irq_cfg *cfg = alloc_irq_and_cfg_at(irq, node); | ||
3577 | int ret; | ||
3578 | |||
3579 | if (!cfg) | ||
3580 | return -EINVAL; | ||
3581 | ret = __add_pin_to_irq_node(cfg, node, attr->ioapic, attr->ioapic_pin); | ||
3582 | if (!ret) | ||
3583 | setup_ioapic_irq(attr->ioapic, attr->ioapic_pin, irq, cfg, | ||
3584 | attr->trigger, attr->polarity); | ||
3585 | return ret; | ||
3586 | } | ||
3587 | |||
3588 | static int io_apic_setup_irq_pin_once(unsigned int irq, int node, | ||
3589 | struct io_apic_irq_attr *attr) | ||
3590 | { | ||
3591 | unsigned int id = attr->ioapic, pin = attr->ioapic_pin; | ||
3592 | int ret; | ||
3593 | |||
3594 | /* Avoid redundant programming */ | ||
3595 | if (test_bit(pin, mp_ioapic_routing[id].pin_programmed)) { | ||
3596 | pr_debug("Pin %d-%d already programmed\n", | ||
3597 | mp_ioapics[id].apicid, pin); | ||
3598 | return 0; | ||
3599 | } | ||
3600 | ret = io_apic_setup_irq_pin(irq, node, attr); | ||
3601 | if (!ret) | ||
3602 | set_bit(pin, mp_ioapic_routing[id].pin_programmed); | ||
3603 | return ret; | ||
3604 | } | ||
3605 | |||
3606 | static int __init io_apic_get_redir_entries(int ioapic) | ||
3609 | { | 3607 | { |
3610 | union IO_APIC_reg_01 reg_01; | 3608 | union IO_APIC_reg_01 reg_01; |
3611 | unsigned long flags; | 3609 | unsigned long flags; |
@@ -3659,96 +3657,24 @@ int __init arch_probe_nr_irqs(void) | |||
3659 | } | 3657 | } |
3660 | #endif | 3658 | #endif |
3661 | 3659 | ||
3662 | static int __io_apic_set_pci_routing(struct device *dev, int irq, | 3660 | int io_apic_set_pci_routing(struct device *dev, int irq, |
3663 | struct io_apic_irq_attr *irq_attr) | 3661 | struct io_apic_irq_attr *irq_attr) |
3664 | { | 3662 | { |
3665 | struct irq_cfg *cfg; | ||
3666 | int node; | 3663 | int node; |
3667 | int ioapic, pin; | ||
3668 | int trigger, polarity; | ||
3669 | 3664 | ||
3670 | ioapic = irq_attr->ioapic; | ||
3671 | if (!IO_APIC_IRQ(irq)) { | 3665 | if (!IO_APIC_IRQ(irq)) { |
3672 | apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n", | 3666 | apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n", |
3673 | ioapic); | 3667 | irq_attr->ioapic); |
3674 | return -EINVAL; | 3668 | return -EINVAL; |
3675 | } | 3669 | } |
3676 | 3670 | ||
3677 | if (dev) | 3671 | node = dev ? dev_to_node(dev) : cpu_to_node(0); |
3678 | node = dev_to_node(dev); | ||
3679 | else | ||
3680 | node = cpu_to_node(0); | ||
3681 | |||
3682 | cfg = alloc_irq_and_cfg_at(irq, node); | ||
3683 | if (!cfg) | ||
3684 | return 0; | ||
3685 | |||
3686 | pin = irq_attr->ioapic_pin; | ||
3687 | trigger = irq_attr->trigger; | ||
3688 | polarity = irq_attr->polarity; | ||
3689 | |||
3690 | /* | ||
3691 | * IRQs < 16 are already in the irq_2_pin[] map | ||
3692 | */ | ||
3693 | if (irq >= legacy_pic->nr_legacy_irqs) { | ||
3694 | if (__add_pin_to_irq_node(cfg, node, ioapic, pin)) { | ||
3695 | printk(KERN_INFO "can not add pin %d for irq %d\n", | ||
3696 | pin, irq); | ||
3697 | return 0; | ||
3698 | } | ||
3699 | } | ||
3700 | |||
3701 | setup_ioapic_irq(ioapic, pin, irq, cfg, trigger, polarity); | ||
3702 | |||
3703 | return 0; | ||
3704 | } | ||
3705 | |||
3706 | int io_apic_set_pci_routing(struct device *dev, int irq, | ||
3707 | struct io_apic_irq_attr *irq_attr) | ||
3708 | { | ||
3709 | int ioapic, pin; | ||
3710 | /* | ||
3711 | * Avoid pin reprogramming. PRTs typically include entries | ||
3712 | * with redundant pin->gsi mappings (but unique PCI devices); | ||
3713 | * we only program the IOAPIC on the first. | ||
3714 | */ | ||
3715 | ioapic = irq_attr->ioapic; | ||
3716 | pin = irq_attr->ioapic_pin; | ||
3717 | if (test_bit(pin, mp_ioapic_routing[ioapic].pin_programmed)) { | ||
3718 | pr_debug("Pin %d-%d already programmed\n", | ||
3719 | mp_ioapics[ioapic].apicid, pin); | ||
3720 | return 0; | ||
3721 | } | ||
3722 | set_bit(pin, mp_ioapic_routing[ioapic].pin_programmed); | ||
3723 | |||
3724 | return __io_apic_set_pci_routing(dev, irq, irq_attr); | ||
3725 | } | ||
3726 | |||
3727 | u8 __init io_apic_unique_id(u8 id) | ||
3728 | { | ||
3729 | #ifdef CONFIG_X86_32 | ||
3730 | if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && | ||
3731 | !APIC_XAPIC(apic_version[boot_cpu_physical_apicid])) | ||
3732 | return io_apic_get_unique_id(nr_ioapics, id); | ||
3733 | else | ||
3734 | return id; | ||
3735 | #else | ||
3736 | int i; | ||
3737 | DECLARE_BITMAP(used, 256); | ||
3738 | 3672 | ||
3739 | bitmap_zero(used, 256); | 3673 | return io_apic_setup_irq_pin_once(irq, node, irq_attr); |
3740 | for (i = 0; i < nr_ioapics; i++) { | ||
3741 | struct mpc_ioapic *ia = &mp_ioapics[i]; | ||
3742 | __set_bit(ia->apicid, used); | ||
3743 | } | ||
3744 | if (!test_bit(id, used)) | ||
3745 | return id; | ||
3746 | return find_first_zero_bit(used, 256); | ||
3747 | #endif | ||
3748 | } | 3674 | } |
3749 | 3675 | ||
3750 | #ifdef CONFIG_X86_32 | 3676 | #ifdef CONFIG_X86_32 |
3751 | int __init io_apic_get_unique_id(int ioapic, int apic_id) | 3677 | static int __init io_apic_get_unique_id(int ioapic, int apic_id) |
3752 | { | 3678 | { |
3753 | union IO_APIC_reg_00 reg_00; | 3679 | union IO_APIC_reg_00 reg_00; |
3754 | static physid_mask_t apic_id_map = PHYSID_MASK_NONE; | 3680 | static physid_mask_t apic_id_map = PHYSID_MASK_NONE; |
@@ -3821,9 +3747,33 @@ int __init io_apic_get_unique_id(int ioapic, int apic_id) | |||
3821 | 3747 | ||
3822 | return apic_id; | 3748 | return apic_id; |
3823 | } | 3749 | } |
3750 | |||
3751 | static u8 __init io_apic_unique_id(u8 id) | ||
3752 | { | ||
3753 | if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && | ||
3754 | !APIC_XAPIC(apic_version[boot_cpu_physical_apicid])) | ||
3755 | return io_apic_get_unique_id(nr_ioapics, id); | ||
3756 | else | ||
3757 | return id; | ||
3758 | } | ||
3759 | #else | ||
3760 | static u8 __init io_apic_unique_id(u8 id) | ||
3761 | { | ||
3762 | int i; | ||
3763 | DECLARE_BITMAP(used, 256); | ||
3764 | |||
3765 | bitmap_zero(used, 256); | ||
3766 | for (i = 0; i < nr_ioapics; i++) { | ||
3767 | struct mpc_ioapic *ia = &mp_ioapics[i]; | ||
3768 | __set_bit(ia->apicid, used); | ||
3769 | } | ||
3770 | if (!test_bit(id, used)) | ||
3771 | return id; | ||
3772 | return find_first_zero_bit(used, 256); | ||
3773 | } | ||
3824 | #endif | 3774 | #endif |
3825 | 3775 | ||
3826 | int __init io_apic_get_version(int ioapic) | 3776 | static int __init io_apic_get_version(int ioapic) |
3827 | { | 3777 | { |
3828 | union IO_APIC_reg_01 reg_01; | 3778 | union IO_APIC_reg_01 reg_01; |
3829 | unsigned long flags; | 3779 | unsigned long flags; |
@@ -3868,8 +3818,8 @@ int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity) | |||
3868 | void __init setup_ioapic_dest(void) | 3818 | void __init setup_ioapic_dest(void) |
3869 | { | 3819 | { |
3870 | int pin, ioapic, irq, irq_entry; | 3820 | int pin, ioapic, irq, irq_entry; |
3871 | struct irq_desc *desc; | ||
3872 | const struct cpumask *mask; | 3821 | const struct cpumask *mask; |
3822 | struct irq_data *idata; | ||
3873 | 3823 | ||
3874 | if (skip_ioapic_setup == 1) | 3824 | if (skip_ioapic_setup == 1) |
3875 | return; | 3825 | return; |
@@ -3884,21 +3834,20 @@ void __init setup_ioapic_dest(void) | |||
3884 | if ((ioapic > 0) && (irq > 16)) | 3834 | if ((ioapic > 0) && (irq > 16)) |
3885 | continue; | 3835 | continue; |
3886 | 3836 | ||
3887 | desc = irq_to_desc(irq); | 3837 | idata = irq_get_irq_data(irq); |
3888 | 3838 | ||
3889 | /* | 3839 | /* |
3890 | * Honour affinities which have been set in early boot | 3840 | * Honour affinities which have been set in early boot |
3891 | */ | 3841 | */ |
3892 | if (desc->status & | 3842 | if (!irqd_can_balance(idata) || irqd_affinity_was_set(idata)) |
3893 | (IRQ_NO_BALANCING | IRQ_AFFINITY_SET)) | 3843 | mask = idata->affinity; |
3894 | mask = desc->irq_data.affinity; | ||
3895 | else | 3844 | else |
3896 | mask = apic->target_cpus(); | 3845 | mask = apic->target_cpus(); |
3897 | 3846 | ||
3898 | if (intr_remapping_enabled) | 3847 | if (intr_remapping_enabled) |
3899 | ir_ioapic_set_affinity(&desc->irq_data, mask, false); | 3848 | ir_ioapic_set_affinity(idata, mask, false); |
3900 | else | 3849 | else |
3901 | ioapic_set_affinity(&desc->irq_data, mask, false); | 3850 | ioapic_set_affinity(idata, mask, false); |
3902 | } | 3851 | } |
3903 | 3852 | ||
3904 | } | 3853 | } |
@@ -4002,6 +3951,9 @@ int mp_find_ioapic(u32 gsi) | |||
4002 | { | 3951 | { |
4003 | int i = 0; | 3952 | int i = 0; |
4004 | 3953 | ||
3954 | if (nr_ioapics == 0) | ||
3955 | return -1; | ||
3956 | |||
4005 | /* Find the IOAPIC that manages this GSI. */ | 3957 | /* Find the IOAPIC that manages this GSI. */ |
4006 | for (i = 0; i < nr_ioapics; i++) { | 3958 | for (i = 0; i < nr_ioapics; i++) { |
4007 | if ((gsi >= mp_gsi_routing[i].gsi_base) | 3959 | if ((gsi >= mp_gsi_routing[i].gsi_base) |
@@ -4023,10 +3975,10 @@ int mp_find_ioapic_pin(int ioapic, u32 gsi) | |||
4023 | return gsi - mp_gsi_routing[ioapic].gsi_base; | 3975 | return gsi - mp_gsi_routing[ioapic].gsi_base; |
4024 | } | 3976 | } |
4025 | 3977 | ||
4026 | static int bad_ioapic(unsigned long address) | 3978 | static __init int bad_ioapic(unsigned long address) |
4027 | { | 3979 | { |
4028 | if (nr_ioapics >= MAX_IO_APICS) { | 3980 | if (nr_ioapics >= MAX_IO_APICS) { |
4029 | printk(KERN_WARNING "WARING: Max # of I/O APICs (%d) exceeded " | 3981 | printk(KERN_WARNING "WARNING: Max # of I/O APICs (%d) exceeded " |
4030 | "(found %d), skipping\n", MAX_IO_APICS, nr_ioapics); | 3982 | "(found %d), skipping\n", MAX_IO_APICS, nr_ioapics); |
4031 | return 1; | 3983 | return 1; |
4032 | } | 3984 | } |
@@ -4083,20 +4035,16 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) | |||
4083 | /* Enable IOAPIC early just for system timer */ | 4035 | /* Enable IOAPIC early just for system timer */ |
4084 | void __init pre_init_apic_IRQ0(void) | 4036 | void __init pre_init_apic_IRQ0(void) |
4085 | { | 4037 | { |
4086 | struct irq_cfg *cfg; | 4038 | struct io_apic_irq_attr attr = { 0, 0, 0, 0 }; |
4087 | 4039 | ||
4088 | printk(KERN_INFO "Early APIC setup for system timer0\n"); | 4040 | printk(KERN_INFO "Early APIC setup for system timer0\n"); |
4089 | #ifndef CONFIG_SMP | 4041 | #ifndef CONFIG_SMP |
4090 | physid_set_mask_of_physid(boot_cpu_physical_apicid, | 4042 | physid_set_mask_of_physid(boot_cpu_physical_apicid, |
4091 | &phys_cpu_present_map); | 4043 | &phys_cpu_present_map); |
4092 | #endif | 4044 | #endif |
4093 | /* Make sure the irq descriptor is set up */ | ||
4094 | cfg = alloc_irq_and_cfg_at(0, 0); | ||
4095 | |||
4096 | setup_local_APIC(); | 4045 | setup_local_APIC(); |
4097 | 4046 | ||
4098 | add_pin_to_irq_node(cfg, 0, 0, 0); | 4047 | io_apic_setup_irq_pin(0, 0, &attr); |
4099 | set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge"); | 4048 | irq_set_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, |
4100 | 4049 | "edge"); | |
4101 | setup_ioapic_irq(0, 0, 0, cfg, 0, 0); | ||
4102 | } | 4050 | } |