diff options
Diffstat (limited to 'arch/i386/kernel/io_apic.c')
-rw-r--r-- | arch/i386/kernel/io_apic.c | 81 |
1 files changed, 58 insertions, 23 deletions
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 100406b453b8..5a1252753dbb 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | #include <linux/sysdev.h> | 33 | #include <linux/sysdev.h> |
34 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
35 | #include <linux/msi.h> | ||
35 | 36 | ||
36 | #include <asm/io.h> | 37 | #include <asm/io.h> |
37 | #include <asm/smp.h> | 38 | #include <asm/smp.h> |
@@ -2455,11 +2456,8 @@ void destroy_irq(unsigned int irq) | |||
2455 | * MSI mesage composition | 2456 | * MSI mesage composition |
2456 | */ | 2457 | */ |
2457 | #ifdef CONFIG_PCI_MSI | 2458 | #ifdef CONFIG_PCI_MSI |
2458 | static int msi_msg_setup(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg) | 2459 | static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg) |
2459 | { | 2460 | { |
2460 | /* For now always this code always uses physical delivery | ||
2461 | * mode. | ||
2462 | */ | ||
2463 | int vector; | 2461 | int vector; |
2464 | unsigned dest; | 2462 | unsigned dest; |
2465 | 2463 | ||
@@ -2489,34 +2487,71 @@ static int msi_msg_setup(struct pci_dev *pdev, unsigned int irq, struct msi_msg | |||
2489 | return vector; | 2487 | return vector; |
2490 | } | 2488 | } |
2491 | 2489 | ||
2492 | static void msi_msg_teardown(unsigned int irq) | 2490 | #ifdef CONFIG_SMP |
2493 | { | 2491 | static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask) |
2494 | return; | ||
2495 | } | ||
2496 | |||
2497 | static void msi_msg_set_affinity(unsigned int irq, cpumask_t mask, struct msi_msg *msg) | ||
2498 | { | 2492 | { |
2493 | struct msi_msg msg; | ||
2494 | unsigned int dest; | ||
2495 | cpumask_t tmp; | ||
2499 | int vector; | 2496 | int vector; |
2500 | unsigned dest; | 2497 | |
2498 | cpus_and(tmp, mask, cpu_online_map); | ||
2499 | if (cpus_empty(tmp)) | ||
2500 | tmp = TARGET_CPUS; | ||
2501 | 2501 | ||
2502 | vector = assign_irq_vector(irq); | 2502 | vector = assign_irq_vector(irq); |
2503 | if (vector > 0) { | 2503 | if (vector < 0) |
2504 | dest = cpu_mask_to_apicid(mask); | 2504 | return; |
2505 | 2505 | ||
2506 | msg->data &= ~MSI_DATA_VECTOR_MASK; | 2506 | dest = cpu_mask_to_apicid(mask); |
2507 | msg->data |= MSI_DATA_VECTOR(vector); | 2507 | |
2508 | msg->address_lo &= ~MSI_ADDR_DEST_ID_MASK; | 2508 | read_msi_msg(irq, &msg); |
2509 | msg->address_lo |= MSI_ADDR_DEST_ID(dest); | 2509 | |
2510 | } | 2510 | msg.data &= ~MSI_DATA_VECTOR_MASK; |
2511 | msg.data |= MSI_DATA_VECTOR(vector); | ||
2512 | msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK; | ||
2513 | msg.address_lo |= MSI_ADDR_DEST_ID(dest); | ||
2514 | |||
2515 | write_msi_msg(irq, &msg); | ||
2516 | set_native_irq_info(irq, mask); | ||
2511 | } | 2517 | } |
2518 | #endif /* CONFIG_SMP */ | ||
2512 | 2519 | ||
2513 | struct msi_ops arch_msi_ops = { | 2520 | /* |
2514 | .needs_64bit_address = 0, | 2521 | * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices, |
2515 | .setup = msi_msg_setup, | 2522 | * which implement the MSI or MSI-X Capability Structure. |
2516 | .teardown = msi_msg_teardown, | 2523 | */ |
2517 | .target = msi_msg_set_affinity, | 2524 | static struct irq_chip msi_chip = { |
2525 | .name = "PCI-MSI", | ||
2526 | .unmask = unmask_msi_irq, | ||
2527 | .mask = mask_msi_irq, | ||
2528 | .ack = ack_ioapic_irq, | ||
2529 | #ifdef CONFIG_SMP | ||
2530 | .set_affinity = set_msi_irq_affinity, | ||
2531 | #endif | ||
2532 | .retrigger = ioapic_retrigger_irq, | ||
2518 | }; | 2533 | }; |
2519 | 2534 | ||
2535 | int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev) | ||
2536 | { | ||
2537 | struct msi_msg msg; | ||
2538 | int ret; | ||
2539 | ret = msi_compose_msg(dev, irq, &msg); | ||
2540 | if (ret < 0) | ||
2541 | return ret; | ||
2542 | |||
2543 | write_msi_msg(irq, &msg); | ||
2544 | |||
2545 | set_irq_chip_and_handler(irq, &msi_chip, handle_edge_irq); | ||
2546 | |||
2547 | return 0; | ||
2548 | } | ||
2549 | |||
2550 | void arch_teardown_msi_irq(unsigned int irq) | ||
2551 | { | ||
2552 | return; | ||
2553 | } | ||
2554 | |||
2520 | #endif /* CONFIG_PCI_MSI */ | 2555 | #endif /* CONFIG_PCI_MSI */ |
2521 | 2556 | ||
2522 | /* | 2557 | /* |