Merge tag 'audit-pr-20211216' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoor...
[linux-2.6-microblaze.git] / drivers / pci / msi.c
index 12e296d..48e3f4e 100644 (file)
@@ -148,6 +148,9 @@ static noinline void pci_msi_update_mask(struct msi_desc *desc, u32 clear, u32 s
        raw_spinlock_t *lock = &desc->dev->msi_lock;
        unsigned long flags;
 
+       if (!desc->msi_attrib.can_mask)
+               return;
+
        raw_spin_lock_irqsave(lock, flags);
        desc->msi_mask &= ~clear;
        desc->msi_mask |= set;
@@ -181,7 +184,8 @@ static void pci_msix_write_vector_ctrl(struct msi_desc *desc, u32 ctrl)
 {
        void __iomem *desc_addr = pci_msix_desc_addr(desc);
 
-       writel(ctrl, desc_addr + PCI_MSIX_ENTRY_VECTOR_CTRL);
+       if (desc->msi_attrib.can_mask)
+               writel(ctrl, desc_addr + PCI_MSIX_ENTRY_VECTOR_CTRL);
 }
 
 static inline void pci_msix_mask(struct msi_desc *desc)
@@ -200,23 +204,17 @@ static inline void pci_msix_unmask(struct msi_desc *desc)
 
 static void __pci_msi_mask_desc(struct msi_desc *desc, u32 mask)
 {
-       if (pci_msi_ignore_mask || desc->msi_attrib.is_virtual)
-               return;
-
        if (desc->msi_attrib.is_msix)
                pci_msix_mask(desc);
-       else if (desc->msi_attrib.maskbit)
+       else
                pci_msi_mask(desc, mask);
 }
 
 static void __pci_msi_unmask_desc(struct msi_desc *desc, u32 mask)
 {
-       if (pci_msi_ignore_mask || desc->msi_attrib.is_virtual)
-               return;
-
        if (desc->msi_attrib.is_msix)
                pci_msix_unmask(desc);
-       else if (desc->msi_attrib.maskbit)
+       else
                pci_msi_unmask(desc, mask);
 }
 
@@ -370,6 +368,11 @@ static void free_msi_irqs(struct pci_dev *dev)
                        for (i = 0; i < entry->nvec_used; i++)
                                BUG_ON(irq_has_action(entry->irq + i));
 
+       if (dev->msi_irq_groups) {
+               msi_destroy_sysfs(&dev->dev, dev->msi_irq_groups);
+               dev->msi_irq_groups = NULL;
+       }
+
        pci_msi_teardown_msi_irqs(dev);
 
        list_for_each_entry_safe(entry, tmp, msi_list, list) {
@@ -381,11 +384,6 @@ static void free_msi_irqs(struct pci_dev *dev)
                list_del(&entry->list);
                free_msi_entry(entry);
        }
-
-       if (dev->msi_irq_groups) {
-               msi_destroy_sysfs(&dev->dev, dev->msi_irq_groups);
-               dev->msi_irq_groups = NULL;
-       }
 }
 
 static void pci_intx_for_msi(struct pci_dev *dev, int enable)
@@ -479,12 +477,16 @@ msi_setup_entry(struct pci_dev *dev, int nvec, struct irq_affinity *affd)
                goto out;
 
        pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
+       /* Lies, damned lies, and MSIs */
+       if (dev->dev_flags & PCI_DEV_FLAGS_HAS_MSI_MASKING)
+               control |= PCI_MSI_FLAGS_MASKBIT;
 
        entry->msi_attrib.is_msix       = 0;
        entry->msi_attrib.is_64         = !!(control & PCI_MSI_FLAGS_64BIT);
        entry->msi_attrib.is_virtual    = 0;
        entry->msi_attrib.entry_nr      = 0;
-       entry->msi_attrib.maskbit       = !!(control & PCI_MSI_FLAGS_MASKBIT);
+       entry->msi_attrib.can_mask      = !pci_msi_ignore_mask &&
+                                         !!(control & PCI_MSI_FLAGS_MASKBIT);
        entry->msi_attrib.default_irq   = dev->irq;     /* Save IOAPIC IRQ */
        entry->msi_attrib.multi_cap     = (control & PCI_MSI_FLAGS_QMASK) >> 1;
        entry->msi_attrib.multiple      = ilog2(__roundup_pow_of_two(nvec));
@@ -495,7 +497,7 @@ msi_setup_entry(struct pci_dev *dev, int nvec, struct irq_affinity *affd)
                entry->mask_pos = dev->msi_cap + PCI_MSI_MASK_32;
 
        /* Save the initial mask status */
-       if (entry->msi_attrib.maskbit)
+       if (entry->msi_attrib.can_mask)
                pci_read_config_dword(dev, entry->mask_pos, &entry->msi_mask);
 
 out:
@@ -639,10 +641,13 @@ static int msix_setup_entries(struct pci_dev *dev, void __iomem *base,
                entry->msi_attrib.is_virtual =
                        entry->msi_attrib.entry_nr >= vec_count;
 
+               entry->msi_attrib.can_mask      = !pci_msi_ignore_mask &&
+                                                 !entry->msi_attrib.is_virtual;
+
                entry->msi_attrib.default_irq   = dev->irq;
                entry->mask_base                = base;
 
-               if (!entry->msi_attrib.is_virtual) {
+               if (entry->msi_attrib.can_mask) {
                        addr = pci_msix_desc_addr(entry);
                        entry->msix_ctrl = readl(addr + PCI_MSIX_ENTRY_VECTOR_CTRL);
                }