From: Sergio Paracuellos <sergio.paracuellos@xxxxxxxxx> [ Upstream commit 5fcded5e857cf66c9592e4be28c4dab4520c9177 ] Pcie phy for pcie0 and pcie1 is shared using a dual ported one. Current code was assuming that if nothing is connected in pcie0 it won't be also nothing connected in pcie1. This assumtion is wrong for some devices such us 'Mikrotik rbm33g' and 'ZyXEL LTE3301-PLUS' where only connecting a card to the second bus on the phy is possible. For such devices kernel hangs in the same point because of the wrong poweroff of the phy getting the following trace: mt7621-pci-phy 1e149000.pcie-phy: PHY for 0xbe149000 (dual port = 1) mt7621-pci-phy 1e14a000.pcie-phy: PHY for 0xbe14a000 (dual port = 0) mt7621-pci-phy 1e149000.pcie-phy: Xtal is 40MHz mt7621-pci-phy 1e14a000.pcie-phy: Xtal is 40MHz mt7621-pci 1e140000.pcie: pcie0 no card, disable it (RST & CLK) [hangs] The wrong assumption is located in the 'mt7621_pcie_init_ports' function where we are just making a power off of the phy for slots 0 and 2 if nothing is connected in them. Hence, only poweroff the phy if nothing is connected in both slot 0 and slot 1 avoiding the kernel to hang. Fixes: 5737cfe87a9c ("staging: mt7621-pci: avoid to poweroff the phy for slot one") Signed-off-by: Sergio Paracuellos <sergio.paracuellos@xxxxxxxxx> Link: https://lore.kernel.org/r/20200409111652.30964-1-sergio.paracuellos@xxxxxxxxx Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> --- drivers/staging/mt7621-pci/pci-mt7621.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/staging/mt7621-pci/pci-mt7621.c b/drivers/staging/mt7621-pci/pci-mt7621.c index f58e3a51fc71..b9d460a9c041 100644 --- a/drivers/staging/mt7621-pci/pci-mt7621.c +++ b/drivers/staging/mt7621-pci/pci-mt7621.c @@ -502,17 +502,25 @@ static void mt7621_pcie_init_ports(struct mt7621_pcie *pcie) mt7621_pcie_reset_ep_deassert(pcie); + tmp = NULL; list_for_each_entry(port, &pcie->ports, list) { u32 slot = port->slot; if (!mt7621_pcie_port_is_linkup(port)) { dev_err(dev, "pcie%d no card, disable it (RST & CLK)\n", slot); - if (slot != 1) - phy_power_off(port->phy); mt7621_control_assert(port); mt7621_pcie_port_clk_disable(port); port->enabled = false; + + if (slot == 0) { + tmp = port; + continue; + } + + if (slot == 1 && tmp && !tmp->enabled) + phy_power_off(tmp->phy); + } } } -- 2.25.1