diff options
Diffstat (limited to 'arch/x86/kernel/io_apic_32.c')
-rw-r--r-- | arch/x86/kernel/io_apic_32.c | 63 |
1 files changed, 43 insertions, 20 deletions
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 | ||