Merge tag 'irq_urgent_for_v5.16_rc6' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 19 Dec 2021 20:28:46 +0000 (12:28 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 19 Dec 2021 20:28:46 +0000 (12:28 -0800)
Pull irq fixes from Borislav Petkov:

 - Clear the PCI_MSIX_FLAGS_MASKALL bit too on the error path so that it
   is restored to its reset state

 - Mask MSI-X vectors late on the init path in order to handle
   out-of-spec Marvell NVME devices which apparently look at the MSI-X
   mask even when MSI-X is disabled

* tag 'irq_urgent_for_v5.16_rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  PCI/MSI: Clear PCI_MSIX_FLAGS_MASKALL on error
  PCI/MSI: Mask MSI-X vectors only on success

drivers/pci/msi.c

index 48e3f4e..d84cf30 100644 (file)
@@ -722,9 +722,6 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
                goto out_disable;
        }
 
-       /* 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;
@@ -751,6 +748,16 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
        /* Set MSI-X enabled bits and unmask the function */
        pci_intx_for_msi(dev, 0);
        dev->msix_enabled = 1;
+
+       /*
+        * Ensure that all table entries are masked to prevent
+        * stale entries from firing in a crash kernel.
+        *
+        * Done late to deal with a broken Marvell NVME device
+        * which takes the MSI-X mask bits into account even
+        * when MSI-X is disabled, which prevents MSI delivery.
+        */
+       msix_mask_all(base, tsize);
        pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0);
 
        pcibios_free_irq(dev);
@@ -777,7 +784,7 @@ out_free:
        free_msi_irqs(dev);
 
 out_disable:
-       pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
+       pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE, 0);
 
        return ret;
 }