PCI: aardvark: Don't rely on jiffies while holding spinlock
authorRemi Pommarel <repk@triplefau.lt>
Fri, 27 Sep 2019 08:55:02 +0000 (10:55 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 20 Jul 2021 14:17:48 +0000 (16:17 +0200)
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/host/pci-aardvark.c

index c1db09fbbe04167c548587b069cae8757a4350c5..5dbbf3d7de3667f66c9a03895cdb89d3ac2e84cd 100644 (file)
        (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
@@ -413,17 +414,16 @@ static void advk_pcie_check_pio_status(struct advk_pcie *pcie)
 static int advk_pcie_wait_pio(struct advk_pcie *pcie)
 {
        struct device *dev = &pcie->pdev->dev;
-       unsigned long timeout;
-
-       timeout = jiffies + msecs_to_jiffies(PIO_TIMEOUT_MS);
+       int i;
 
-       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");