Merge tag 'irqchip-fixes-5.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorThomas Gleixner <tglx@linutronix.de>
Sun, 14 Nov 2021 12:59:05 +0000 (13:59 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Sun, 14 Nov 2021 12:59:05 +0000 (13:59 +0100)
Pull irqchip fixes from Marc Zyngier:

  - Address an issue with the SiFive PLIC being unable to EOI
    a masked interrupt

  - Move the disable/enable methods in the CSky mpintc to
    mask/unmask

  - Fix a regression in the OF irq code where an interrupt-controller
    property in the same node as an interrupt-map property would get
    ignored

Link: https://lore.kernel.org/all/20211112173459.4015233-1-maz@kernel.org
drivers/pci/msi.c
drivers/pci/quirks.c
include/linux/msi.h
include/linux/pci.h
kernel/irq/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);
                }
index aedb78c..003950c 100644 (file)
@@ -5851,3 +5851,9 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_PERICOM, 0x2303,
                         pci_fixup_pericom_acs_store_forward);
 DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_PERICOM, 0x2303,
                         pci_fixup_pericom_acs_store_forward);
+
+static void nvidia_ion_ahci_fixup(struct pci_dev *pdev)
+{
+       pdev->dev_flags |= PCI_DEV_FLAGS_HAS_MSI_MASKING;
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, 0x0ab8, nvidia_ion_ahci_fixup);
index 49cf6eb..e616f94 100644 (file)
@@ -148,7 +148,7 @@ struct msi_desc {
                                u8      is_msix         : 1;
                                u8      multiple        : 3;
                                u8      multi_cap       : 3;
-                               u8      maskbit         : 1;
+                               u8      can_mask        : 1;
                                u8      is_64           : 1;
                                u8      is_virtual      : 1;
                                u16     entry_nr;
index c8afbee..d0dba7f 100644 (file)
@@ -233,6 +233,8 @@ enum pci_dev_flags {
        PCI_DEV_FLAGS_NO_FLR_RESET = (__force pci_dev_flags_t) (1 << 10),
        /* Don't use Relaxed Ordering for TLPs directed at this device */
        PCI_DEV_FLAGS_NO_RELAXED_ORDERING = (__force pci_dev_flags_t) (1 << 11),
+       /* Device does honor MSI masking despite saying otherwise */
+       PCI_DEV_FLAGS_HAS_MSI_MASKING = (__force pci_dev_flags_t) (1 << 12),
 };
 
 enum pci_irq_reroute_variant {
index 6a5ecee..7f350ae 100644 (file)
@@ -529,10 +529,10 @@ static bool msi_check_reservation_mode(struct irq_domain *domain,
 
        /*
         * Checking the first MSI descriptor is sufficient. MSIX supports
-        * masking and MSI does so when the maskbit is set.
+        * masking and MSI does so when the can_mask attribute is set.
         */
        desc = first_msi_entry(dev);
-       return desc->msi_attrib.is_msix || desc->msi_attrib.maskbit;
+       return desc->msi_attrib.is_msix || desc->msi_attrib.can_mask;
 }
 
 int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,