From: Greg Kroah-Hartman Date: Mon, 19 Jul 2021 13:05:52 +0000 (+0200) Subject: 4.19-stable patches X-Git-Tag: v5.13.4~35 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2b3dee2a5b0a4ec975fd9aeda8c9b8cc6e36a6ae;p=thirdparty%2Fkernel%2Fstable-queue.git 4.19-stable patches added patches: pci-aardvark-don-t-rely-on-jiffies-while-holding-spinlock.patch pci-aardvark-fix-kernel-panic-during-pio-transfer.patch --- 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 index 00000000000..23a7ea8485e --- /dev/null +++ b/queue-4.19/pci-aardvark-don-t-rely-on-jiffies-while-holding-spinlock.patch @@ -0,0 +1,59 @@ +From 7fbcb5da811be7d47468417c7795405058abb3da Mon Sep 17 00:00:00 2001 +From: Remi Pommarel +Date: Fri, 27 Sep 2019 10:55:02 +0200 +Subject: PCI: aardvark: Don't rely on jiffies while holding spinlock + +From: Remi Pommarel + +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 +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Andrew Murray +Acked-by: Thomas Petazzoni +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..3ad5ca795e0 --- /dev/null +++ b/queue-4.19/pci-aardvark-fix-kernel-panic-during-pio-transfer.patch @@ -0,0 +1,150 @@ +From f18139966d072dab8e4398c95ce955a9742e04f7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +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 + +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 +Signed-off-by: Lorenzo Pieralisi +Signed-off-by: Bjorn Helgaas +Reviewed-by: Marek Behún +Cc: stable@vger.kernel.org # 7fbcb5da811b ("PCI: aardvark: Don't rely on jiffies while holding spinlock") +Signed-off-by: Greg Kroah-Hartman +--- + 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); diff --git a/queue-4.19/series b/queue-4.19/series index 5104caebaeb..e253977c4b1 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -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