]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 16 Aug 2021 08:10:39 +0000 (10:10 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 16 Aug 2021 08:10:39 +0000 (10:10 +0200)
added patches:
pci-msi-enable-and-mask-msi-x-early.patch

queue-4.4/pci-msi-enable-and-mask-msi-x-early.patch [new file with mode: 0644]
queue-4.4/series

diff --git a/queue-4.4/pci-msi-enable-and-mask-msi-x-early.patch b/queue-4.4/pci-msi-enable-and-mask-msi-x-early.patch
new file mode 100644 (file)
index 0000000..1e4c15c
--- /dev/null
@@ -0,0 +1,105 @@
+From 438553958ba19296663c6d6583d208dfb6792830 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 29 Jul 2021 23:51:40 +0200
+Subject: PCI/MSI: Enable and mask MSI-X early
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 438553958ba19296663c6d6583d208dfb6792830 upstream.
+
+The ordering of MSI-X enable in hardware is dysfunctional:
+
+ 1) MSI-X is disabled in the control register
+ 2) Various setup functions
+ 3) pci_msi_setup_msi_irqs() is invoked which ends up accessing
+    the MSI-X table entries
+ 4) MSI-X is enabled and masked in the control register with the
+    comment that enabling is required for some hardware to access
+    the MSI-X table
+
+Step #4 obviously contradicts #3. The history of this is an issue with the
+NIU hardware. When #4 was introduced the table access actually happened in
+msix_program_entries() which was invoked after enabling and masking MSI-X.
+
+This was changed in commit d71d6432e105 ("PCI/MSI: Kill redundant call of
+irq_set_msi_desc() for MSI-X interrupts") which removed the table write
+from msix_program_entries().
+
+Interestingly enough nobody noticed and either NIU still works or it did
+not get any testing with a kernel 3.19 or later.
+
+Nevertheless this is inconsistent and there is no reason why MSI-X can't be
+enabled and masked in the control register early on, i.e. move step #4
+above to step #1. This preserves the NIU workaround and has no side effects
+on other hardware.
+
+Fixes: d71d6432e105 ("PCI/MSI: Kill redundant call of irq_set_msi_desc() for MSI-X interrupts")
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Tested-by: Marc Zyngier <maz@kernel.org>
+Reviewed-by: Ashok Raj <ashok.raj@intel.com>
+Reviewed-by: Marc Zyngier <maz@kernel.org>
+Acked-by: Bjorn Helgaas <bhelgaas@google.com>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20210729222542.344136412@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/msi.c |   26 ++++++++++++++------------
+ 1 file changed, 14 insertions(+), 12 deletions(-)
+
+--- a/drivers/pci/msi.c
++++ b/drivers/pci/msi.c
+@@ -737,18 +737,25 @@ static int msix_capability_init(struct p
+       u16 control;
+       void __iomem *base;
+-      /* Ensure MSI-X is disabled while it is set up */
+-      pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
++      /*
++       * Some devices require MSI-X to be enabled before the MSI-X
++       * registers can be accessed.  Mask all the vectors to prevent
++       * interrupts coming in before they're fully set up.
++       */
++      pci_msix_clear_and_set_ctrl(dev, 0, PCI_MSIX_FLAGS_MASKALL |
++                                  PCI_MSIX_FLAGS_ENABLE);
+       pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
+       /* Request & Map MSI-X table region */
+       base = msix_map_region(dev, msix_table_size(control));
+-      if (!base)
++      if (!base) {
+               return -ENOMEM;
++              goto out_disable;
++      }
+       ret = msix_setup_entries(dev, base, entries, nvec);
+       if (ret)
+-              return ret;
++              goto out_disable;
+       ret = pci_msi_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX);
+       if (ret)
+@@ -759,14 +766,6 @@ static int msix_capability_init(struct p
+       if (ret)
+               goto out_free;
+-      /*
+-       * Some devices require MSI-X to be enabled before we can touch the
+-       * MSI-X registers.  We need to mask all the vectors to prevent
+-       * interrupts coming in before they're fully set up.
+-       */
+-      pci_msix_clear_and_set_ctrl(dev, 0,
+-                              PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE);
+-
+       msix_program_entries(dev, entries);
+       ret = populate_msi_sysfs(dev);
+@@ -801,6 +800,9 @@ out_avail:
+ out_free:
+       free_msi_irqs(dev);
++out_disable:
++      pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
++
+       return ret;
+ }
index 2af6262081fb729b25c3d6c5711506120403540e..6eaeb8c6b215fef0bad67eeea24a4d670a916c9c 100644 (file)
@@ -3,3 +3,4 @@ i2c-dev-zero-out-array-used-for-i2c-reads-from-userspace.patch
 net-fix-memory-leak-in-ieee802154_raw_deliver.patch
 xen-events-fix-race-in-set_evtchn_to_irq.patch
 x86-tools-fix-objdump-version-check-again.patch
+pci-msi-enable-and-mask-msi-x-early.patch