Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=314e77b3eec57001eaff82b82920150175b74e09
Commit:     314e77b3eec57001eaff82b82920150175b74e09
Parent:     4aa9bc955d61fdf03b5f9cee67db188fe1ffa8b7
Author:     Michael Ellerman <[EMAIL PROTECTED]>
AuthorDate: Thu Apr 5 17:19:12 2007 +1000
Committer:  Greg Kroah-Hartman <[EMAIL PROTECTED]>
CommitDate: Wed May 2 19:02:37 2007 -0700

    MSI: Remove dev->first_msi_irq
    
    Now that we keep a list of msi descriptors, we don't need first_msi_irq
    in the pci dev.
    
    If we somehow have zero MSIs configured list_entry() will give us weird
    oopes or nice memory corruption bugs. So be paranoid. Add BUG_ONs and also
    a check in pci_msi_check_device() to make sure nvec > 0.
    
    Signed-off-by: Michael Ellerman <[EMAIL PROTECTED]>
    Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>
---
 drivers/pci/msi.c   |   31 ++++++++++++++++++++-----------
 include/linux/pci.h |    1 -
 2 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 434c718..7a44ba4 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -269,7 +269,8 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
                msi_set_mask_bit(entry->irq, entry->msi_attrib.masked);
        }
 
-       entry = get_irq_msi(dev->first_msi_irq);
+       BUG_ON(list_empty(&dev->msi_list));
+       entry = list_entry(dev->msi_list.next, struct msi_desc, list);
        pos = entry->msi_attrib.pos;
        pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control);
        control &= ~PCI_MSIX_FLAGS_MASKALL;
@@ -341,7 +342,6 @@ static int msi_capability_init(struct pci_dev *dev)
        }
        entry->irq = irq;
        list_add(&entry->list, &dev->msi_list);
-       dev->first_msi_irq = irq;
        set_irq_msi(irq, entry);
 
        /* Set MSI enabled bits  */
@@ -433,7 +433,6 @@ static int msix_capability_init(struct pci_dev *dev,
                        avail = -EBUSY;
                return avail;
        }
-       dev->first_msi_irq = entries[0].vector;
        /* Set MSI-X enabled bits */
        pci_intx(dev, 0);               /* disable intx */
        msix_set_enable(dev, 1);
@@ -461,6 +460,14 @@ static int pci_msi_check_device(struct pci_dev* dev, int 
nvec, int type)
        if (!pci_msi_enable || !dev || dev->no_msi)
                return -EINVAL;
 
+       /*
+        * You can't ask to have 0 or less MSIs configured.
+        *  a) it's stupid ..
+        *  b) the list manipulation code assumes nvec >= 1.
+        */
+       if (nvec < 1)
+               return -ERANGE;
+
        /* Any bridge which does NOT route MSI transactions from it's
         * secondary bus to it's primary bus must set NO_MSI flag on
         * the secondary pci_bus.
@@ -525,18 +532,17 @@ void pci_disable_msi(struct pci_dev* dev)
        pci_intx(dev, 1);               /* enable intx */
        dev->msi_enabled = 0;
 
-       entry = get_irq_msi(dev->first_msi_irq);
-       if (!entry || !entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) {
+       BUG_ON(list_empty(&dev->msi_list));
+       entry = list_entry(dev->msi_list.next, struct msi_desc, list);
+       if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) {
                return;
        }
 
        default_irq = entry->msi_attrib.default_irq;
-       msi_free_irq(dev, dev->first_msi_irq);
+       msi_free_irq(dev, entry->irq);
 
        /* Restore dev->irq to its default pin-assertion irq */
        dev->irq = default_irq;
-
-       dev->first_msi_irq = 0;
 }
 EXPORT_SYMBOL(pci_disable_msi);
 
@@ -634,7 +640,6 @@ static void msix_free_all_irqs(struct pci_dev *dev)
 
        list_for_each_entry(entry, &dev->msi_list, list)
                msi_free_irq(dev, entry->irq);
-       dev->first_msi_irq = 0;
 }
 
 void pci_disable_msix(struct pci_dev* dev)
@@ -664,8 +669,12 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev)
        if (!pci_msi_enable || !dev)
                return;
 
-       if (dev->msi_enabled)
-               msi_free_irq(dev, dev->first_msi_irq);
+       if (dev->msi_enabled) {
+               struct msi_desc *entry;
+               BUG_ON(list_empty(&dev->msi_list));
+               entry = list_entry(dev->msi_list.next, struct msi_desc, list);
+               msi_free_irq(dev, entry->irq);
+       }
 
        if (dev->msix_enabled)
                msix_free_all_irqs(dev);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index d43097d..a15569b 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -189,7 +189,6 @@ struct pci_dev {
        int rom_attr_enabled;           /* has display of the rom attribute 
been enabled? */
        struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file 
for resources */
 #ifdef CONFIG_PCI_MSI
-       unsigned int first_msi_irq;
        struct list_head msi_list;
 #endif
 };
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to