PCI/MSI: Sanitize MSI-X table map handling
authorThomas Gleixner <tglx@linutronix.de>
Mon, 6 Dec 2021 22:27:54 +0000 (23:27 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Thu, 9 Dec 2021 10:52:22 +0000 (11:52 +0100)
Unmapping the MSI-X base mapping in the loops which allocate/free MSI
descriptors is daft and in the way of allowing runtime expansion of MSI-X
descriptors.

Store the mapping in struct pci_dev and free it after freeing the MSI-X
descriptors.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Link: https://lore.kernel.org/r/20211206210224.871651518@linutronix.de
drivers/pci/msi/msi.c
include/linux/pci.h

index 8926a6c8b345eea352e1e0179fb08186258a020d..465fe9e00294cd2a2aa0723acba55c2ec948de17 100644 (file)
@@ -241,14 +241,14 @@ static void free_msi_irqs(struct pci_dev *dev)
        pci_msi_teardown_msi_irqs(dev);
 
        list_for_each_entry_safe(entry, tmp, msi_list, list) {
-               if (entry->pci.msi_attrib.is_msix) {
-                       if (list_is_last(&entry->list, msi_list))
-                               iounmap(entry->pci.mask_base);
-               }
-
                list_del(&entry->list);
                free_msi_entry(entry);
        }
+
+       if (dev->msix_base) {
+               iounmap(dev->msix_base);
+               dev->msix_base = NULL;
+       }
 }
 
 static void pci_intx_for_msi(struct pci_dev *dev, int enable)
@@ -501,10 +501,6 @@ static int msix_setup_entries(struct pci_dev *dev, void __iomem *base,
        for (i = 0, curmsk = masks; i < nvec; i++) {
                entry = alloc_msi_entry(&dev->dev, 1, curmsk);
                if (!entry) {
-                       if (!i)
-                               iounmap(base);
-                       else
-                               free_msi_irqs(dev);
                        /* No enough memory. Don't try again */
                        ret = -ENOMEM;
                        goto out;
@@ -602,12 +598,14 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
                goto out_disable;
        }
 
+       dev->msix_base = base;
+
        /* Ensure that all table entries are masked. */
        msix_mask_all(base, tsize);
 
        ret = msix_setup_entries(dev, base, entries, nvec, affd);
        if (ret)
-               goto out_disable;
+               goto out_free;
 
        ret = pci_msi_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX);
        if (ret)
index 18a75c8e615cdb3ef068ff07cfe1552e2a30eeff..8cb103677f5acf9d7e55ce196a342e1b5a67a590 100644 (file)
@@ -473,6 +473,7 @@ struct pci_dev {
        u8              ptm_granularity;
 #endif
 #ifdef CONFIG_PCI_MSI
+       void __iomem    *msix_base;
        const struct attribute_group **msi_irq_groups;
 #endif
        struct pci_vpd  vpd;