[PATCH 5.14 18/23] staging: mt7621-pci: fix hang when nothing is connected to pcie ports

From: Greg Kroah-Hartman
Date: Fri Sep 10 2021 - 08:31:20 EST


From: Sergio Paracuellos <sergio.paracuellos@xxxxxxxxx>

commit 7d761b084b3c785e1fbbe707fbdf7baba905c6ad upstream.

When nothing is connected to pcie ports, each port is set to reset state.
When this occurs, next access result in a hang on boot as follows:

mt7621-pci 1e140000.pcie: pcie0 no card, disable it (RST & CLK)
mt7621-pci 1e140000.pcie: pcie1 no card, disable it (RST & CLK)
mt7621-pci 1e140000.pcie: pcie2 no card, disable it (RST & CLK)
[ HANGS HERE ]

Fix this just detecting 'nothing is connected state' to avoid next accesses
to pcie port related configuration registers.

Fixes: b99cc3a2b6b6 ("staging: mt7621-pci: avoid custom 'map_irq' function")
Cc: stable <stable@xxxxxxxxxxxxxxx>
Reported-by: DENG Qingfang <dqfext@xxxxxxxxx>
Signed-off-by: Sergio Paracuellos <sergio.paracuellos@xxxxxxxxx>
Link: https://lore.kernel.org/r/20210823170803.2108-1-sergio.paracuellos@xxxxxxxxx
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
---
drivers/staging/mt7621-pci/pci-mt7621.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)

--- a/drivers/staging/mt7621-pci/pci-mt7621.c
+++ b/drivers/staging/mt7621-pci/pci-mt7621.c
@@ -56,6 +56,7 @@
#define PCIE_BAR_ENABLE BIT(0)
#define PCIE_PORT_INT_EN(x) BIT(20 + (x))
#define PCIE_PORT_LINKUP BIT(0)
+#define PCIE_PORT_CNT 3

#define PERST_DELAY_MS 100

@@ -388,10 +389,11 @@ static void mt7621_pcie_reset_ep_deasser
msleep(PERST_DELAY_MS);
}

-static void mt7621_pcie_init_ports(struct mt7621_pcie *pcie)
+static int mt7621_pcie_init_ports(struct mt7621_pcie *pcie)
{
struct device *dev = pcie->dev;
struct mt7621_pcie_port *port, *tmp;
+ u8 num_disabled = 0;
int err;

mt7621_pcie_reset_assert(pcie);
@@ -423,6 +425,7 @@ static void mt7621_pcie_init_ports(struc
slot);
mt7621_control_assert(port);
port->enabled = false;
+ num_disabled++;

if (slot == 0) {
tmp = port;
@@ -433,6 +436,8 @@ static void mt7621_pcie_init_ports(struc
phy_power_off(tmp->phy);
}
}
+
+ return (num_disabled != PCIE_PORT_CNT) ? 0 : -ENODEV;
}

static void mt7621_pcie_enable_port(struct mt7621_pcie_port *port)
@@ -540,7 +545,11 @@ static int mt7621_pci_probe(struct platf
return err;
}

- mt7621_pcie_init_ports(pcie);
+ err = mt7621_pcie_init_ports(pcie);
+ if (err) {
+ dev_err(dev, "Nothing connected in virtual bridges\n");
+ return 0;
+ }

err = mt7621_pcie_enable_ports(bridge);
if (err) {