]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - arch/i386/kernel/io_apic.c
[PATCH] msi: refactor and move the msi irq_chip into the arch code
[net-next-2.6.git] / arch / i386 / kernel / io_apic.c
index 100406b453b8051e7897e9e71cf43b7b6f0afaca..5a1252753dbb8b9d866a27a244aa8ed48da3b17d 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/module.h>
 #include <linux/sysdev.h>
 #include <linux/pci.h>
+#include <linux/msi.h>
 
 #include <asm/io.h>
 #include <asm/smp.h>
@@ -2455,11 +2456,8 @@ void destroy_irq(unsigned int irq)
  * MSI mesage composition
  */
 #ifdef CONFIG_PCI_MSI
-static int msi_msg_setup(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
+static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
 {
-       /* For now always this code always uses physical delivery
-        * mode.
-        */
        int vector;
        unsigned dest;
 
@@ -2489,34 +2487,71 @@ static int msi_msg_setup(struct pci_dev *pdev, unsigned int irq, struct msi_msg
        return vector;
 }
 
-static void msi_msg_teardown(unsigned int irq)
-{
-       return;
-}
-
-static void msi_msg_set_affinity(unsigned int irq, cpumask_t mask, struct msi_msg *msg)
+#ifdef CONFIG_SMP
+static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
 {
+       struct msi_msg msg;
+       unsigned int dest;
+       cpumask_t tmp;
        int vector;
-       unsigned dest;
+
+       cpus_and(tmp, mask, cpu_online_map);
+       if (cpus_empty(tmp))
+               tmp = TARGET_CPUS;
 
        vector = assign_irq_vector(irq);
-       if (vector > 0) {
-               dest = cpu_mask_to_apicid(mask);
+       if (vector < 0)
+               return;
 
-               msg->data &= ~MSI_DATA_VECTOR_MASK;
-               msg->data |= MSI_DATA_VECTOR(vector);
-               msg->address_lo &= ~MSI_ADDR_DEST_ID_MASK;
-               msg->address_lo |= MSI_ADDR_DEST_ID(dest);
-       }
+       dest = cpu_mask_to_apicid(mask);
+
+       read_msi_msg(irq, &msg);
+
+       msg.data &= ~MSI_DATA_VECTOR_MASK;
+       msg.data |= MSI_DATA_VECTOR(vector);
+       msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
+       msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+
+       write_msi_msg(irq, &msg);
+       set_native_irq_info(irq, mask);
 }
+#endif /* CONFIG_SMP */
 
-struct msi_ops arch_msi_ops = {
-       .needs_64bit_address = 0,
-       .setup = msi_msg_setup,
-       .teardown = msi_msg_teardown,
-       .target = msi_msg_set_affinity,
+/*
+ * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
+ * which implement the MSI or MSI-X Capability Structure.
+ */
+static struct irq_chip msi_chip = {
+       .name           = "PCI-MSI",
+       .unmask         = unmask_msi_irq,
+       .mask           = mask_msi_irq,
+       .ack            = ack_ioapic_irq,
+#ifdef CONFIG_SMP
+       .set_affinity   = set_msi_irq_affinity,
+#endif
+       .retrigger      = ioapic_retrigger_irq,
 };
 
+int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev)
+{
+       struct msi_msg msg;
+       int ret;
+       ret = msi_compose_msg(dev, irq, &msg);
+       if (ret < 0)
+               return ret;
+
+       write_msi_msg(irq, &msg);
+
+       set_irq_chip_and_handler(irq, &msi_chip, handle_edge_irq);
+
+       return 0;
+}
+
+void arch_teardown_msi_irq(unsigned int irq)
+{
+       return;
+}
+
 #endif /* CONFIG_PCI_MSI */
 
 /*