aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/io_apic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/io_apic.c')
-rw-r--r--arch/i386/kernel/io_apic.c81
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
2458static int msi_msg_setup(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg) 2459static 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
2492static void msi_msg_teardown(unsigned int irq) 2490#ifdef CONFIG_SMP
2493{ 2491static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
2494 return;
2495}
2496
2497static 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
2513struct 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, 2524static 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
2535int 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
2550void 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/*