diff options
author | Yinghai Lu <yhlu.kernel@gmail.com> | 2008-08-19 23:50:27 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-10-16 10:52:53 -0400 |
commit | 199751d715bba5b469ea22adadc68a4166bfa4f5 (patch) | |
tree | bc7edd6d16d75637fbe00d906636c1c879acedc8 | |
parent | 0f978f4505e96227a89b3c9447552aca983c6b57 (diff) |
x86: make 32 bit to use sparse_irq
but actually irq still needs to be less than NR_IRQS, because
interrupt[NR_IRQS] in entry.S.
need to enable per_cpu vector...
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | arch/x86/Kconfig | 2 | ||||
-rw-r--r-- | arch/x86/kernel/io_apic_32.c | 63 | ||||
-rw-r--r-- | arch/x86/kernel/irq_32.c | 37 | ||||
-rw-r--r-- | arch/x86/kernel/irqinit_32.c | 7 |
4 files changed, 79 insertions, 30 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 3e0eaaa1a339..b157e94637bf 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -34,7 +34,7 @@ config X86 | |||
34 | select HAVE_GENERIC_DMA_COHERENT if X86_32 | 34 | select HAVE_GENERIC_DMA_COHERENT if X86_32 |
35 | select HAVE_EFFICIENT_UNALIGNED_ACCESS | 35 | select HAVE_EFFICIENT_UNALIGNED_ACCESS |
36 | select HAVE_DYN_ARRAY | 36 | select HAVE_DYN_ARRAY |
37 | select HAVE_SPARSE_IRQ if X86_64 | 37 | select HAVE_SPARSE_IRQ |
38 | 38 | ||
39 | config ARCH_DEFCONFIG | 39 | config ARCH_DEFCONFIG |
40 | string | 40 | string |
diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c index 59d2e8a273e3..66c0a91362a7 100644 --- a/arch/x86/kernel/io_apic_32.c +++ b/arch/x86/kernel/io_apic_32.c | |||
@@ -595,7 +595,6 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask) | |||
595 | struct irq_pin_list *entry; | 595 | struct irq_pin_list *entry; |
596 | unsigned int apicid_value; | 596 | unsigned int apicid_value; |
597 | cpumask_t tmp; | 597 | cpumask_t tmp; |
598 | struct irq_desc *desc; | ||
599 | 598 | ||
600 | 599 | ||
601 | cfg = irq_cfg(irq); | 600 | cfg = irq_cfg(irq); |
@@ -620,8 +619,7 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask) | |||
620 | break; | 619 | break; |
621 | entry = entry->next; | 620 | entry = entry->next; |
622 | } | 621 | } |
623 | desc = irq_to_desc(irq); | 622 | irq_to_desc(irq)->affinity = cpumask; |
624 | desc->affinity = cpumask; | ||
625 | spin_unlock_irqrestore(&ioapic_lock, flags); | 623 | spin_unlock_irqrestore(&ioapic_lock, flags); |
626 | } | 624 | } |
627 | 625 | ||
@@ -1055,8 +1053,6 @@ static int __assign_irq_vector(int irq) | |||
1055 | int vector, offset; | 1053 | int vector, offset; |
1056 | struct irq_cfg *cfg; | 1054 | struct irq_cfg *cfg; |
1057 | 1055 | ||
1058 | BUG_ON((unsigned)irq >= nr_irqs); | ||
1059 | |||
1060 | cfg = irq_cfg(irq); | 1056 | cfg = irq_cfg(irq); |
1061 | if (cfg->vector > 0) | 1057 | if (cfg->vector > 0) |
1062 | return cfg->vector; | 1058 | return cfg->vector; |
@@ -1103,7 +1099,12 @@ static void ioapic_register_intr(int irq, int vector, unsigned long trigger) | |||
1103 | { | 1099 | { |
1104 | struct irq_desc *desc; | 1100 | struct irq_desc *desc; |
1105 | 1101 | ||
1106 | desc = irq_to_desc(irq); | 1102 | /* first time to use this irq_desc */ |
1103 | if (irq < 16) | ||
1104 | desc = irq_to_desc(irq); | ||
1105 | else | ||
1106 | desc = irq_to_desc_alloc(irq); | ||
1107 | |||
1107 | if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) || | 1108 | if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) || |
1108 | trigger == IOAPIC_LEVEL) { | 1109 | trigger == IOAPIC_LEVEL) { |
1109 | desc->status |= IRQ_LEVEL; | 1110 | desc->status |= IRQ_LEVEL; |
@@ -2330,16 +2331,19 @@ device_initcall(ioapic_init_sysfs); | |||
2330 | /* | 2331 | /* |
2331 | * Dynamic irq allocate and deallocation | 2332 | * Dynamic irq allocate and deallocation |
2332 | */ | 2333 | */ |
2333 | int create_irq(void) | 2334 | unsigned int create_irq_nr(unsigned int irq_want) |
2334 | { | 2335 | { |
2335 | /* Allocate an unused irq */ | 2336 | /* Allocate an unused irq */ |
2336 | int irq, new, vector = 0; | 2337 | unsigned int irq, new, vector = 0; |
2337 | unsigned long flags; | 2338 | unsigned long flags; |
2338 | struct irq_cfg *cfg_new; | 2339 | struct irq_cfg *cfg_new; |
2339 | 2340 | ||
2340 | irq = -ENOSPC; | 2341 | /* only can use bus/dev/fn.. when per_cpu vector is used */ |
2342 | irq_want = nr_irqs - 1; | ||
2343 | |||
2344 | irq = 0; | ||
2341 | spin_lock_irqsave(&vector_lock, flags); | 2345 | spin_lock_irqsave(&vector_lock, flags); |
2342 | for (new = (nr_irqs - 1); new >= 0; new--) { | 2346 | for (new = (nr_irqs - 1); new > 0; new--) { |
2343 | if (platform_legacy_irq(new)) | 2347 | if (platform_legacy_irq(new)) |
2344 | continue; | 2348 | continue; |
2345 | cfg_new = irq_cfg(new); | 2349 | cfg_new = irq_cfg(new); |
@@ -2354,13 +2358,18 @@ int create_irq(void) | |||
2354 | } | 2358 | } |
2355 | spin_unlock_irqrestore(&vector_lock, flags); | 2359 | spin_unlock_irqrestore(&vector_lock, flags); |
2356 | 2360 | ||
2357 | if (irq >= 0) { | 2361 | if (irq > 0) { |
2358 | set_intr_gate(vector, interrupt[irq]); | 2362 | set_intr_gate(vector, interrupt[irq]); |
2359 | dynamic_irq_init(irq); | 2363 | dynamic_irq_init(irq); |
2360 | } | 2364 | } |
2361 | return irq; | 2365 | return irq; |
2362 | } | 2366 | } |
2363 | 2367 | ||
2368 | int create_irq(void) | ||
2369 | { | ||
2370 | return create_irq_nr(nr_irqs - 1); | ||
2371 | } | ||
2372 | |||
2364 | void destroy_irq(unsigned int irq) | 2373 | void destroy_irq(unsigned int irq) |
2365 | { | 2374 | { |
2366 | unsigned long flags; | 2375 | unsigned long flags; |
@@ -2415,7 +2424,6 @@ static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask) | |||
2415 | unsigned int dest; | 2424 | unsigned int dest; |
2416 | cpumask_t tmp; | 2425 | cpumask_t tmp; |
2417 | int vector; | 2426 | int vector; |
2418 | struct irq_desc *desc; | ||
2419 | 2427 | ||
2420 | cpus_and(tmp, mask, cpu_online_map); | 2428 | cpus_and(tmp, mask, cpu_online_map); |
2421 | if (cpus_empty(tmp)) | 2429 | if (cpus_empty(tmp)) |
@@ -2435,8 +2443,7 @@ static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask) | |||
2435 | msg.address_lo |= MSI_ADDR_DEST_ID(dest); | 2443 | msg.address_lo |= MSI_ADDR_DEST_ID(dest); |
2436 | 2444 | ||
2437 | write_msi_msg(irq, &msg); | 2445 | write_msi_msg(irq, &msg); |
2438 | desc = irq_to_desc(irq); | 2446 | irq_to_desc(irq)->affinity = mask; |
2439 | desc->affinity = mask; | ||
2440 | } | 2447 | } |
2441 | #endif /* CONFIG_SMP */ | 2448 | #endif /* CONFIG_SMP */ |
2442 | 2449 | ||
@@ -2455,13 +2462,31 @@ static struct irq_chip msi_chip = { | |||
2455 | .retrigger = ioapic_retrigger_irq, | 2462 | .retrigger = ioapic_retrigger_irq, |
2456 | }; | 2463 | }; |
2457 | 2464 | ||
2465 | static unsigned int build_irq_for_pci_dev(struct pci_dev *dev) | ||
2466 | { | ||
2467 | unsigned int irq; | ||
2468 | |||
2469 | irq = dev->bus->number; | ||
2470 | irq <<= 8; | ||
2471 | irq |= dev->devfn; | ||
2472 | irq <<= 12; | ||
2473 | |||
2474 | return irq; | ||
2475 | } | ||
2476 | |||
2458 | int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) | 2477 | int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) |
2459 | { | 2478 | { |
2460 | struct msi_msg msg; | 2479 | struct msi_msg msg; |
2461 | int irq, ret; | 2480 | int irq, ret; |
2462 | irq = create_irq(); | 2481 | |
2463 | if (irq < 0) | 2482 | unsigned int irq_want; |
2464 | return irq; | 2483 | |
2484 | irq_want = build_irq_for_pci_dev(dev) + 0x100; | ||
2485 | |||
2486 | irq = create_irq_nr(irq_want); | ||
2487 | |||
2488 | if (irq == 0) | ||
2489 | return -1; | ||
2465 | 2490 | ||
2466 | ret = msi_compose_msg(dev, irq, &msg); | 2491 | ret = msi_compose_msg(dev, irq, &msg); |
2467 | if (ret < 0) { | 2492 | if (ret < 0) { |
@@ -2510,7 +2535,6 @@ static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask) | |||
2510 | { | 2535 | { |
2511 | unsigned int dest; | 2536 | unsigned int dest; |
2512 | cpumask_t tmp; | 2537 | cpumask_t tmp; |
2513 | struct irq_desc *desc; | ||
2514 | 2538 | ||
2515 | cpus_and(tmp, mask, cpu_online_map); | 2539 | cpus_and(tmp, mask, cpu_online_map); |
2516 | if (cpus_empty(tmp)) | 2540 | if (cpus_empty(tmp)) |
@@ -2521,8 +2545,7 @@ static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask) | |||
2521 | dest = cpu_mask_to_apicid(mask); | 2545 | dest = cpu_mask_to_apicid(mask); |
2522 | 2546 | ||
2523 | target_ht_irq(irq, dest); | 2547 | target_ht_irq(irq, dest); |
2524 | desc = irq_to_desc(irq); | 2548 | irq_to_desc(irq)->affinity = mask; |
2525 | desc->affinity = mask; | ||
2526 | } | 2549 | } |
2527 | #endif | 2550 | #endif |
2528 | 2551 | ||
diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c index 576c5df6cad8..0a57e39159a8 100644 --- a/arch/x86/kernel/irq_32.c +++ b/arch/x86/kernel/irq_32.c | |||
@@ -224,9 +224,10 @@ unsigned int do_IRQ(struct pt_regs *regs) | |||
224 | struct pt_regs *old_regs; | 224 | struct pt_regs *old_regs; |
225 | /* high bit used in ret_from_ code */ | 225 | /* high bit used in ret_from_ code */ |
226 | int overflow, irq = ~regs->orig_ax; | 226 | int overflow, irq = ~regs->orig_ax; |
227 | struct irq_desc *desc = irq_to_desc(irq); | 227 | struct irq_desc *desc; |
228 | 228 | ||
229 | if (unlikely((unsigned)irq >= nr_irqs)) { | 229 | desc = irq_to_desc(irq); |
230 | if (unlikely(!desc)) { | ||
230 | printk(KERN_EMERG "%s: cannot handle IRQ %d\n", | 231 | printk(KERN_EMERG "%s: cannot handle IRQ %d\n", |
231 | __func__, irq); | 232 | __func__, irq); |
232 | BUG(); | 233 | BUG(); |
@@ -263,6 +264,24 @@ int show_interrupts(struct seq_file *p, void *v) | |||
263 | int i = *(loff_t *) v, j; | 264 | int i = *(loff_t *) v, j; |
264 | struct irqaction * action; | 265 | struct irqaction * action; |
265 | unsigned long flags; | 266 | unsigned long flags; |
267 | unsigned int entries; | ||
268 | struct irq_desc *desc; | ||
269 | int tail = 0; | ||
270 | |||
271 | #ifdef CONFIG_HAVE_SPARSE_IRQ | ||
272 | desc = (struct irq_desc *)v; | ||
273 | entries = -1U; | ||
274 | i = desc->irq; | ||
275 | if (!desc->next) | ||
276 | tail = 1; | ||
277 | #else | ||
278 | entries = nr_irqs - 1; | ||
279 | i = *(loff_t *) v; | ||
280 | if (i == nr_irqs) | ||
281 | tail = 1; | ||
282 | else | ||
283 | desc = irq_to_desc(i); | ||
284 | #endif | ||
266 | 285 | ||
267 | if (i == 0) { | 286 | if (i == 0) { |
268 | seq_printf(p, " "); | 287 | seq_printf(p, " "); |
@@ -271,9 +290,8 @@ int show_interrupts(struct seq_file *p, void *v) | |||
271 | seq_putc(p, '\n'); | 290 | seq_putc(p, '\n'); |
272 | } | 291 | } |
273 | 292 | ||
274 | if (i < nr_irqs) { | 293 | if (i <= entries) { |
275 | unsigned any_count = 0; | 294 | unsigned any_count = 0; |
276 | struct irq_desc *desc = irq_to_desc(i); | ||
277 | 295 | ||
278 | spin_lock_irqsave(&desc->lock, flags); | 296 | spin_lock_irqsave(&desc->lock, flags); |
279 | #ifndef CONFIG_SMP | 297 | #ifndef CONFIG_SMP |
@@ -285,7 +303,7 @@ int show_interrupts(struct seq_file *p, void *v) | |||
285 | action = desc->action; | 303 | action = desc->action; |
286 | if (!action && !any_count) | 304 | if (!action && !any_count) |
287 | goto skip; | 305 | goto skip; |
288 | seq_printf(p, "%3d: ",i); | 306 | seq_printf(p, "%#x: ",i); |
289 | #ifndef CONFIG_SMP | 307 | #ifndef CONFIG_SMP |
290 | seq_printf(p, "%10u ", kstat_irqs(i)); | 308 | seq_printf(p, "%10u ", kstat_irqs(i)); |
291 | #else | 309 | #else |
@@ -304,7 +322,9 @@ int show_interrupts(struct seq_file *p, void *v) | |||
304 | seq_putc(p, '\n'); | 322 | seq_putc(p, '\n'); |
305 | skip: | 323 | skip: |
306 | spin_unlock_irqrestore(&desc->lock, flags); | 324 | spin_unlock_irqrestore(&desc->lock, flags); |
307 | } else if (i == nr_irqs) { | 325 | } |
326 | |||
327 | if (tail) { | ||
308 | seq_printf(p, "NMI: "); | 328 | seq_printf(p, "NMI: "); |
309 | for_each_online_cpu(j) | 329 | for_each_online_cpu(j) |
310 | seq_printf(p, "%10u ", nmi_count(j)); | 330 | seq_printf(p, "%10u ", nmi_count(j)); |
@@ -396,15 +416,14 @@ void fixup_irqs(cpumask_t map) | |||
396 | { | 416 | { |
397 | unsigned int irq; | 417 | unsigned int irq; |
398 | static int warned; | 418 | static int warned; |
419 | struct irq_desc *desc; | ||
399 | 420 | ||
400 | for (irq = 0; irq < nr_irqs; irq++) { | 421 | for_each_irq_desc(irq, desc) { |
401 | cpumask_t mask; | 422 | cpumask_t mask; |
402 | struct irq_desc *desc; | ||
403 | 423 | ||
404 | if (irq == 2) | 424 | if (irq == 2) |
405 | continue; | 425 | continue; |
406 | 426 | ||
407 | desc = irq_to_desc(irq); | ||
408 | cpus_and(mask, desc->affinity, map); | 427 | cpus_and(mask, desc->affinity, map); |
409 | if (any_online_cpu(mask) == NR_CPUS) { | 428 | if (any_online_cpu(mask) == NR_CPUS) { |
410 | printk("Breaking affinity for irq %i\n", irq); | 429 | printk("Breaking affinity for irq %i\n", irq); |
diff --git a/arch/x86/kernel/irqinit_32.c b/arch/x86/kernel/irqinit_32.c index 65c1c9507707..ded09ac2642e 100644 --- a/arch/x86/kernel/irqinit_32.c +++ b/arch/x86/kernel/irqinit_32.c | |||
@@ -69,6 +69,13 @@ void __init init_ISA_irqs (void) | |||
69 | * 16 old-style INTA-cycle interrupts: | 69 | * 16 old-style INTA-cycle interrupts: |
70 | */ | 70 | */ |
71 | for (i = 0; i < 16; i++) { | 71 | for (i = 0; i < 16; i++) { |
72 | /* first time call this irq_desc */ | ||
73 | struct irq_desc *desc = irq_to_desc_alloc(i); | ||
74 | |||
75 | desc->status = IRQ_DISABLED; | ||
76 | desc->action = NULL; | ||
77 | desc->depth = 1; | ||
78 | |||
72 | set_irq_chip_and_handler_name(i, &i8259A_chip, | 79 | set_irq_chip_and_handler_name(i, &i8259A_chip, |
73 | handle_level_irq, "XT"); | 80 | handle_level_irq, "XT"); |
74 | } | 81 | } |