6.16-stable review patch. If anyone has any objections, please let me know.
------------------
From: Niklas Cassel cassel@kernel.org
[ Upstream commit c7eb9c5e1498882951b7583c56add0b77bfc162e ]
Per PCIe r6.0, sec 6.6.1, software must generally wait a minimum of 100ms (PCIE_RESET_CONFIG_WAIT_MS) after Link training completes before sending a Configuration Request.
Prior to ec9fd499b9c6 ("PCI: dw-rockchip: Don't wait for link since we can detect Link Up"), dw-rockchip used dw_pcie_wait_for_link(), which waited between 0 and 90ms after the link came up before we enumerate the bus, and this was apparently enough for most devices.
After ec9fd499b9c6, rockchip_pcie_rc_sys_irq_thread() started enumeration immediately when handling the link-up IRQ, and devices (e.g., Laszlo Fiat's PLEXTOR PX-256M8PeGN NVMe SSD) may not be ready to handle config requests yet.
Delay PCIE_RESET_CONFIG_WAIT_MS after the link-up IRQ before starting enumeration.
Fixes: 0e898eb8df4e ("PCI: rockchip-dwc: Add Rockchip RK356X host controller driver") Signed-off-by: Niklas Cassel cassel@kernel.org Signed-off-by: Manivannan Sadhasivam mani@kernel.org Reviewed-by: Damien Le Moal dlemoal@kernel.org Reviewed-by: Wilfred Mallawa wilfred.mallawa@wdc.com Cc: Laszlo Fiat laszlo.fiat@proton.me Link: https://patch.msgid.link/20250625102347.1205584-12-cassel@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pci/controller/dwc/pcie-dw-rockchip.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c index 93171a392879..108d30637920 100644 --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c @@ -458,6 +458,7 @@ static irqreturn_t rockchip_pcie_rc_sys_irq_thread(int irq, void *arg)
if (reg & PCIE_RDLH_LINK_UP_CHGED) { if (rockchip_pcie_link_up(pci)) { + msleep(PCIE_RESET_CONFIG_WAIT_MS); dev_dbg(dev, "Received Link up event. Starting enumeration!\n"); /* Rescan the bus to enumerate endpoint devices */ pci_lock_rescan_remove();