From c7eb9c5e1498882951b7583c56add0b77bfc162e Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Wed, 25 Jun 2025 12:23:49 +0200 Subject: PCI: dw-rockchip: Wait PCIE_RESET_CONFIG_WAIT_MS after link-up IRQ 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 Signed-off-by: Manivannan Sadhasivam Reviewed-by: Damien Le Moal Reviewed-by: Wilfred Mallawa Cc: Laszlo Fiat Link: https://patch.msgid.link/20250625102347.1205584-12-cassel@kernel.org --- drivers/pci/controller/dwc/pcie-dw-rockchip.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/pci/controller/dwc') 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(); -- cgit v1.2.3 From 15b6b243cc2b1017cf89e2477aa0b4e1a306a82a Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Wed, 25 Jun 2025 12:23:50 +0200 Subject: PCI: qcom: Wait PCIE_RESET_CONFIG_WAIT_MS after link-up IRQ 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 36971d6c5a9a ("PCI: qcom: Don't wait for link if we can detect Link Up"), qcom 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 36971d6c5a9a, qcom_pcie_global_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: 82a823833f4e ("PCI: qcom: Add Qualcomm PCIe controller driver") Signed-off-by: Niklas Cassel Signed-off-by: Manivannan Sadhasivam Reviewed-by: Damien Le Moal Reviewed-by: Wilfred Mallawa Link: https://patch.msgid.link/20250625102347.1205584-13-cassel@kernel.org --- drivers/pci/controller/dwc/pcie-qcom.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/pci/controller/dwc') diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index c789e3f85655..9b12f2f02042 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -1564,6 +1564,7 @@ static irqreturn_t qcom_pcie_global_irq_thread(int irq, void *data) writel_relaxed(status, pcie->parf + PARF_INT_ALL_CLEAR); if (FIELD_GET(PARF_INT_ALL_LINK_UP, status)) { + 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(); -- cgit v1.2.3 From 80dc18a0cba8dea42614f021b20a04354b213d86 Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Wed, 25 Jun 2025 12:23:51 +0200 Subject: PCI: dwc: Ensure that dw_pcie_wait_for_link() waits 100 ms after link up As per PCIe r6.0, sec 6.6.1, a Downstream Port that supports Link speeds greater than 5.0 GT/s, software must wait a minimum of 100 ms after Link training completes before sending a Configuration Request. Add this delay in dw_pcie_wait_for_link(), after the link is reported as up. The delay will only be performed in the success case where the link came up. DWC glue drivers that have a link up IRQ (drivers that set use_linkup_irq = true) do not call dw_pcie_wait_for_link(), instead they perform this delay in their threaded link up IRQ handler. Signed-off-by: Niklas Cassel Signed-off-by: Manivannan Sadhasivam Reviewed-by: Damien Le Moal Reviewed-by: Wilfred Mallawa Link: https://patch.msgid.link/20250625102347.1205584-14-cassel@kernel.org --- drivers/pci/controller/dwc/pcie-designware.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/pci/controller/dwc') diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c index 4d794964fa0f..053e9c540439 100644 --- a/drivers/pci/controller/dwc/pcie-designware.c +++ b/drivers/pci/controller/dwc/pcie-designware.c @@ -714,6 +714,14 @@ int dw_pcie_wait_for_link(struct dw_pcie *pci) return -ETIMEDOUT; } + /* + * As per PCIe r6.0, sec 6.6.1, a Downstream Port that supports Link + * speeds greater than 5.0 GT/s, software must wait a minimum of 100 ms + * after Link training completes before sending a Configuration Request. + */ + if (pci->max_link_speed > 2) + msleep(PCIE_RESET_CONFIG_WAIT_MS); + offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); val = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA); -- cgit v1.2.3 From d7467bc72ce4e3f64062017d6c9ae3816e8a7b0e Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Wed, 25 Jun 2025 12:23:52 +0200 Subject: PCI: Move link up wait time and max retries macros to pci.h Move the LINK_WAIT_SLEEP_MS and LINK_WAIT_MAX_RETRIES macros to pci.h. Prefix the macros with PCIE_ in order to avoid redefining these for drivers that already have macros named like this. No functional changes. Suggested-by: Manivannan Sadhasivam Signed-off-by: Niklas Cassel Signed-off-by: Manivannan Sadhasivam Link: https://patch.msgid.link/20250625102347.1205584-15-cassel@kernel.org --- drivers/pci/controller/dwc/pcie-designware.c | 6 +++--- drivers/pci/controller/dwc/pcie-designware.h | 4 ---- drivers/pci/pci.h | 4 ++++ 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/pci/controller/dwc') diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c index 053e9c540439..89aad5a08928 100644 --- a/drivers/pci/controller/dwc/pcie-designware.c +++ b/drivers/pci/controller/dwc/pcie-designware.c @@ -702,14 +702,14 @@ int dw_pcie_wait_for_link(struct dw_pcie *pci) int retries; /* Check if the link is up or not */ - for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) { + for (retries = 0; retries < PCIE_LINK_WAIT_MAX_RETRIES; retries++) { if (dw_pcie_link_up(pci)) break; - msleep(LINK_WAIT_SLEEP_MS); + msleep(PCIE_LINK_WAIT_SLEEP_MS); } - if (retries >= LINK_WAIT_MAX_RETRIES) { + if (retries >= PCIE_LINK_WAIT_MAX_RETRIES) { dev_info(pci->dev, "Phy link never came up\n"); return -ETIMEDOUT; } diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index ce9e18554e42..1bf1e08ab4c3 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -62,10 +62,6 @@ #define dw_pcie_cap_set(_pci, _cap) \ set_bit(DW_PCIE_CAP_ ## _cap, &(_pci)->caps) -/* Parameters for the waiting for link up routine */ -#define LINK_WAIT_MAX_RETRIES 10 -#define LINK_WAIT_SLEEP_MS 90 - /* Parameters for the waiting for iATU enabled routine */ #define LINK_WAIT_MAX_IATU_RETRIES 5 #define LINK_WAIT_IATU 9 diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 819833e57590..43cb77c27ac0 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -56,6 +56,10 @@ struct pcie_tlp_log; */ #define PCIE_RESET_CONFIG_WAIT_MS 100 +/* Parameters for the waiting for link up routine */ +#define PCIE_LINK_WAIT_MAX_RETRIES 10 +#define PCIE_LINK_WAIT_SLEEP_MS 90 + /* Message Routing (r[2:0]); PCIe r6.0, sec 2.2.8 */ #define PCIE_MSG_TYPE_R_RC 0 #define PCIE_MSG_TYPE_R_ADDR 1 -- cgit v1.2.3