]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.19-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 19 Jul 2021 13:05:52 +0000 (15:05 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 19 Jul 2021 13:05:52 +0000 (15:05 +0200)
added patches:
pci-aardvark-don-t-rely-on-jiffies-while-holding-spinlock.patch
pci-aardvark-fix-kernel-panic-during-pio-transfer.patch

queue-4.19/pci-aardvark-don-t-rely-on-jiffies-while-holding-spinlock.patch [new file with mode: 0644]
queue-4.19/pci-aardvark-fix-kernel-panic-during-pio-transfer.patch [new file with mode: 0644]
queue-4.19/series

diff --git a/queue-4.19/pci-aardvark-don-t-rely-on-jiffies-while-holding-spinlock.patch b/queue-4.19/pci-aardvark-don-t-rely-on-jiffies-while-holding-spinlock.patch
new file mode 100644 (file)
index 0000000..23a7ea8
--- /dev/null
@@ -0,0 +1,59 @@
+From 7fbcb5da811be7d47468417c7795405058abb3da Mon Sep 17 00:00:00 2001
+From: Remi Pommarel <repk@triplefau.lt>
+Date: Fri, 27 Sep 2019 10:55:02 +0200
+Subject: PCI: aardvark: Don't rely on jiffies while holding spinlock
+
+From: Remi Pommarel <repk@triplefau.lt>
+
+commit 7fbcb5da811be7d47468417c7795405058abb3da upstream.
+
+advk_pcie_wait_pio() can be called while holding a spinlock (from
+pci_bus_read_config_dword()), then depends on jiffies in order to
+timeout while polling on PIO state registers. In the case the PIO
+transaction failed, the timeout will never happen and will also cause
+the cpu to stall.
+
+This decrements a variable and wait instead of using jiffies.
+
+Signed-off-by: Remi Pommarel <repk@triplefau.lt>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Andrew Murray <andrew.murray@arm.com>
+Acked-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c |   10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -166,7 +166,8 @@
+       (PCIE_CONF_BUS(bus) | PCIE_CONF_DEV(PCI_SLOT(devfn))    | \
+        PCIE_CONF_FUNC(PCI_FUNC(devfn)) | PCIE_CONF_REG(where))
+-#define PIO_TIMEOUT_MS                        1
++#define PIO_RETRY_CNT                 500
++#define PIO_RETRY_DELAY                       2 /* 2 us*/
+ #define LINK_WAIT_MAX_RETRIES         10
+ #define LINK_WAIT_USLEEP_MIN          90000
+@@ -369,17 +370,16 @@ static void advk_pcie_check_pio_status(s
+ static int advk_pcie_wait_pio(struct advk_pcie *pcie)
+ {
+       struct device *dev = &pcie->pdev->dev;
+-      unsigned long timeout;
++      int i;
+-      timeout = jiffies + msecs_to_jiffies(PIO_TIMEOUT_MS);
+-
+-      while (time_before(jiffies, timeout)) {
++      for (i = 0; i < PIO_RETRY_CNT; i++) {
+               u32 start, isr;
+               start = advk_readl(pcie, PIO_START);
+               isr = advk_readl(pcie, PIO_ISR);
+               if (!start && isr)
+                       return 0;
++              udelay(PIO_RETRY_DELAY);
+       }
+       dev_err(dev, "config read/write timed out\n");
diff --git a/queue-4.19/pci-aardvark-fix-kernel-panic-during-pio-transfer.patch b/queue-4.19/pci-aardvark-fix-kernel-panic-during-pio-transfer.patch
new file mode 100644 (file)
index 0000000..3ad5ca7
--- /dev/null
@@ -0,0 +1,150 @@
+From f18139966d072dab8e4398c95ce955a9742e04f7 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Tue, 8 Jun 2021 22:36:55 +0200
+Subject: PCI: aardvark: Fix kernel panic during PIO transfer
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+commit f18139966d072dab8e4398c95ce955a9742e04f7 upstream.
+
+Trying to start a new PIO transfer by writing value 0 in PIO_START register
+when previous transfer has not yet completed (which is indicated by value 1
+in PIO_START) causes an External Abort on CPU, which results in kernel
+panic:
+
+    SError Interrupt on CPU0, code 0xbf000002 -- SError
+    Kernel panic - not syncing: Asynchronous SError Interrupt
+
+To prevent kernel panic, it is required to reject a new PIO transfer when
+previous one has not finished yet.
+
+If previous PIO transfer is not finished yet, the kernel may issue a new
+PIO request only if the previous PIO transfer timed out.
+
+In the past the root cause of this issue was incorrectly identified (as it
+often happens during link retraining or after link down event) and special
+hack was implemented in Trusted Firmware to catch all SError events in EL3,
+to ignore errors with code 0xbf000002 and not forwarding any other errors
+to kernel and instead throw panic from EL3 Trusted Firmware handler.
+
+Links to discussion and patches about this issue:
+https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/commit/?id=3c7dcdac5c50
+https://lore.kernel.org/linux-pci/20190316161243.29517-1-repk@triplefau.lt/
+https://lore.kernel.org/linux-pci/971be151d24312cc533989a64bd454b4@www.loen.fr/
+https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/1541
+
+But the real cause was the fact that during link retraining or after link
+down event the PIO transfer may take longer time, up to the 1.44s until it
+times out. This increased probability that a new PIO transfer would be
+issued by kernel while previous one has not finished yet.
+
+After applying this change into the kernel, it is possible to revert the
+mentioned TF-A hack and SError events do not have to be caught in TF-A EL3.
+
+Link: https://lore.kernel.org/r/20210608203655.31228-1-pali@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Marek Behún <kabel@kernel.org>
+Cc: stable@vger.kernel.org # 7fbcb5da811b ("PCI: aardvark: Don't rely on jiffies while holding spinlock")
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-aardvark.c |   49 +++++++++++++++++++++++++++-------
+ 1 file changed, 40 insertions(+), 9 deletions(-)
+
+--- a/drivers/pci/controller/pci-aardvark.c
++++ b/drivers/pci/controller/pci-aardvark.c
+@@ -382,7 +382,7 @@ static int advk_pcie_wait_pio(struct adv
+               udelay(PIO_RETRY_DELAY);
+       }
+-      dev_err(dev, "config read/write timed out\n");
++      dev_err(dev, "PIO read/write transfer time out\n");
+       return -ETIMEDOUT;
+ }
+@@ -395,6 +395,35 @@ static bool advk_pcie_valid_device(struc
+       return true;
+ }
++static bool advk_pcie_pio_is_running(struct advk_pcie *pcie)
++{
++      struct device *dev = &pcie->pdev->dev;
++
++      /*
++       * Trying to start a new PIO transfer when previous has not completed
++       * cause External Abort on CPU which results in kernel panic:
++       *
++       *     SError Interrupt on CPU0, code 0xbf000002 -- SError
++       *     Kernel panic - not syncing: Asynchronous SError Interrupt
++       *
++       * Functions advk_pcie_rd_conf() and advk_pcie_wr_conf() are protected
++       * by raw_spin_lock_irqsave() at pci_lock_config() level to prevent
++       * concurrent calls at the same time. But because PIO transfer may take
++       * about 1.5s when link is down or card is disconnected, it means that
++       * advk_pcie_wait_pio() does not always have to wait for completion.
++       *
++       * Some versions of ARM Trusted Firmware handles this External Abort at
++       * EL3 level and mask it to prevent kernel panic. Relevant TF-A commit:
++       * https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/commit/?id=3c7dcdac5c50
++       */
++      if (advk_readl(pcie, PIO_START)) {
++              dev_err(dev, "Previous PIO read/write transfer is still running\n");
++              return true;
++      }
++
++      return false;
++}
++
+ static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn,
+                            int where, int size, u32 *val)
+ {
+@@ -407,9 +436,10 @@ static int advk_pcie_rd_conf(struct pci_
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       }
+-      /* Start PIO */
+-      advk_writel(pcie, 0, PIO_START);
+-      advk_writel(pcie, 1, PIO_ISR);
++      if (advk_pcie_pio_is_running(pcie)) {
++              *val = 0xffffffff;
++              return PCIBIOS_SET_FAILED;
++      }
+       /* Program the control register */
+       reg = advk_readl(pcie, PIO_CTRL);
+@@ -428,7 +458,8 @@ static int advk_pcie_rd_conf(struct pci_
+       /* Program the data strobe */
+       advk_writel(pcie, 0xf, PIO_WR_DATA_STRB);
+-      /* Start the transfer */
++      /* Clear PIO DONE ISR and start the transfer */
++      advk_writel(pcie, 1, PIO_ISR);
+       advk_writel(pcie, 1, PIO_START);
+       ret = advk_pcie_wait_pio(pcie);
+@@ -462,9 +493,8 @@ static int advk_pcie_wr_conf(struct pci_
+       if (where % size)
+               return PCIBIOS_SET_FAILED;
+-      /* Start PIO */
+-      advk_writel(pcie, 0, PIO_START);
+-      advk_writel(pcie, 1, PIO_ISR);
++      if (advk_pcie_pio_is_running(pcie))
++              return PCIBIOS_SET_FAILED;
+       /* Program the control register */
+       reg = advk_readl(pcie, PIO_CTRL);
+@@ -491,7 +521,8 @@ static int advk_pcie_wr_conf(struct pci_
+       /* Program the data strobe */
+       advk_writel(pcie, data_strobe, PIO_WR_DATA_STRB);
+-      /* Start the transfer */
++      /* Clear PIO DONE ISR and start the transfer */
++      advk_writel(pcie, 1, PIO_ISR);
+       advk_writel(pcie, 1, PIO_START);
+       ret = advk_pcie_wait_pio(pcie);
index 5104caebaebe5e7ab97852f1eb9b98bfb9579a06..e253977c4b1e47dee12816d72125b753b9fbfb78 100644 (file)
@@ -318,3 +318,5 @@ kvm-x86-use-guest-maxphyaddr-from-cpuid.0x8000_0008-iff-tdp-is-enabled.patch
 kvm-x86-disable-hardware-breakpoints-unconditionally-before-kvm_x86-run.patch
 scsi-core-fix-bad-pointer-dereference-when-ehandler-kthread-is-invalid.patch
 tracing-do-not-reference-char-as-a-string-in-histograms.patch
+pci-aardvark-don-t-rely-on-jiffies-while-holding-spinlock.patch
+pci-aardvark-fix-kernel-panic-during-pio-transfer.patch