MSI: arch must connect the irq and the msi_desc
authorMichael Ellerman <michael@ellerman.id.au>
Wed, 18 Apr 2007 09:39:21 +0000 (19:39 +1000)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 3 May 2007 02:02:38 +0000 (19:02 -0700)
set_irq_msi() currently connects an irq_desc to an msi_desc. The archs call
it at some point in their setup routine, and then the generic code sets up the
reverse mapping from the msi_desc back to the irq.

set_irq_msi() should do both connections, making it the one and only call
required to connect an irq with it's MSI desc and vice versa.

The arch code MUST call set_irq_msi(), and it must do so only once it's sure
it's not going to fail the irq allocation.

Given that there's no need for the arch to return the irq anymore, the return
value from the arch setup routine just becomes 0 for success and anything else
for failure.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
arch/i386/kernel/io_apic.c
arch/ia64/sn/kernel/msi_sn.c
arch/sparc64/kernel/pci.c
arch/sparc64/kernel/pci_sun4v.c
arch/x86_64/kernel/io_apic.c
drivers/pci/msi.c
kernel/irq/chip.c

index b3ab8ffebd27fc05ca5f96bbfe2b8bf419b32ca8..89d85d244926d2db60a3f69a9575eaa47f9d9f16 100644 (file)
@@ -2611,19 +2611,19 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
        if (irq < 0)
                return irq;
 
-       set_irq_msi(irq, desc);
        ret = msi_compose_msg(dev, irq, &msg);
        if (ret < 0) {
                destroy_irq(irq);
                return ret;
        }
 
+       set_irq_msi(irq, desc);
        write_msi_msg(irq, &msg);
 
        set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq,
                                      "edge");
 
-       return irq;
+       return 0;
 }
 
 void arch_teardown_msi_irq(unsigned int irq)
index 49873aa4a37dcb2e1705e70081dfb7e9c11d291d..83f190ffe35078dd062266727c20025d00b3a7fa 100644 (file)
@@ -87,7 +87,6 @@ int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry)
        if (irq < 0)
                return irq;
 
-       set_irq_msi(irq, entry);
        /*
         * Set up the vector plumbing.  Let the prom (via sn_intr_alloc)
         * decide which cpu to direct this msi at by default.
@@ -144,10 +143,11 @@ int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry)
         */
        msg.data = 0x100 + irq;
 
+       set_irq_msi(irq, entry);
        write_msi_msg(irq, &msg);
        set_irq_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq);
 
-       return irq;
+       return 0;
 }
 
 #ifdef CONFIG_SMP
index 023af41ad68d99845dc9a4a1f5644d492282d63c..9a549547cb2b768348da36869a9f8890152d45d6 100644 (file)
@@ -1092,10 +1092,10 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
                return -EINVAL;
 
        err = p->setup_msi_irq(&virt_irq, pdev, desc);
-       if (err < 0)
+       if (err)
                return err;
 
-       return virt_irq;
+       return 0;
 }
 
 void arch_teardown_msi_irq(unsigned int virt_irq)
index 94295c21932942fdd634285351c7b2b5e0551ee6..1ccf4c9a9a4330b4b40cfd21bb50e116ebf744af 100644 (file)
@@ -1169,8 +1169,6 @@ static int pci_sun4v_setup_msi_irq(unsigned int *virt_irq_p,
        if (!devino)
                goto out_err;
 
-       set_irq_msi(*virt_irq_p, entry);
-
        msiqid = ((devino - pbm->msiq_first_devino) +
                  pbm->msiq_first);
 
@@ -1204,6 +1202,8 @@ static int pci_sun4v_setup_msi_irq(unsigned int *virt_irq_p,
                msg.address_lo = pbm->msi32_start;
        }
        msg.data = msi_num;
+
+       set_irq_msi(*virt_irq_p, entry);
        write_msi_msg(*virt_irq_p, &msg);
 
        irq_install_pre_handler(*virt_irq_p,
index c6a5bc7e8118d0cb206b2185a330e925773195cc..b7d2b76b92d4f395948d9e93d78cb4728dcf909f 100644 (file)
@@ -1983,18 +1983,18 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
        if (irq < 0)
                return irq;
 
-       set_irq_msi(irq, desc);
        ret = msi_compose_msg(dev, irq, &msg);
        if (ret < 0) {
                destroy_irq(irq);
                return ret;
        }
 
+       set_irq_msi(irq, desc);
        write_msi_msg(irq, &msg);
 
        set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
 
-       return irq;
+       return 0;
 }
 
 void arch_teardown_msi_irq(unsigned int irq)
index 7a44ba46748129f5ed4ad78aaf3ad4b0eadcae51..88362f1bd9cfceaf9575215c96865e314e3bed8a 100644 (file)
@@ -297,7 +297,7 @@ void pci_restore_msi_state(struct pci_dev *dev)
 static int msi_capability_init(struct pci_dev *dev)
 {
        struct msi_desc *entry;
-       int pos, irq;
+       int pos, ret;
        u16 control;
 
        msi_set_enable(dev, 0); /* Ensure msi is disabled as I set it up */
@@ -335,21 +335,19 @@ static int msi_capability_init(struct pci_dev *dev)
                        maskbits);
        }
        /* Configure MSI capability structure */
-       irq = arch_setup_msi_irq(dev, entry);
-       if (irq < 0) {
+       ret = arch_setup_msi_irq(dev, entry);
+       if (ret) {
                kfree(entry);
-               return irq;
+               return ret;
        }
-       entry->irq = irq;
        list_add(&entry->list, &dev->msi_list);
-       set_irq_msi(irq, entry);
 
        /* Set MSI enabled bits  */
        pci_intx(dev, 0);               /* disable intx */
        msi_set_enable(dev, 1);
        dev->msi_enabled = 1;
 
-       dev->irq = irq;
+       dev->irq = entry->irq;
        return 0;
 }
 
@@ -367,7 +365,7 @@ static int msix_capability_init(struct pci_dev *dev,
                                struct msix_entry *entries, int nvec)
 {
        struct msi_desc *entry;
-       int irq, pos, i, j, nr_entries;
+       int irq, pos, i, j, nr_entries, ret;
        unsigned long phys_addr;
        u32 table_offset;
        u16 control;
@@ -407,16 +405,13 @@ static int msix_capability_init(struct pci_dev *dev,
                entry->mask_base = base;
 
                /* Configure MSI-X capability structure */
-               irq = arch_setup_msi_irq(dev, entry);
-               if (irq < 0) {
+               ret = arch_setup_msi_irq(dev, entry);
+               if (ret) {
                        kfree(entry);
                        break;
                }
-               entry->irq = irq;
-               entries[i].vector = irq;
+               entries[i].vector = entry->irq;
                list_add(&entry->list, &dev->msi_list);
-
-               set_irq_msi(irq, entry);
        }
        if (i != nvec) {
                int avail = i - 1;
index 0133f4f9e9f0c71633ccff2d4029f479148d0af9..615ce97c6cfd8393e85dbc4fb3b23f0cce762bcb 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <linux/irq.h>
+#include <linux/msi.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
@@ -185,6 +186,8 @@ int set_irq_msi(unsigned int irq, struct msi_desc *entry)
        desc = irq_desc + irq;
        spin_lock_irqsave(&desc->lock, flags);
        desc->msi_desc = entry;
+       if (entry)
+               entry->irq = irq;
        spin_unlock_irqrestore(&desc->lock, flags);
        return 0;
 }