From 817f989700fddefa56e5e443e7d138018ca6709d Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Wed, 25 Jun 2025 12:23:47 +0200 Subject: [PATCH 1/6] PCI: Rename PCIE_RESET_CONFIG_DEVICE_WAIT_MS to PCIE_RESET_CONFIG_WAIT_MS Rename PCIE_RESET_CONFIG_DEVICE_WAIT_MS to PCIE_RESET_CONFIG_WAIT_MS. Suggested-by: Bjorn Helgaas Signed-off-by: Niklas Cassel Signed-off-by: Manivannan Sadhasivam Link: https://patch.msgid.link/20250625102347.1205584-10-cassel@kernel.org --- drivers/pci/controller/plda/pcie-starfive.c | 2 +- drivers/pci/pci.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pci/controller/plda/pcie-starfive.c b/drivers/pci/controller/plda/pcie-starfive.c index e73c1b7bc8ef..3caf53c6c082 100644 --- a/drivers/pci/controller/plda/pcie-starfive.c +++ b/drivers/pci/controller/plda/pcie-starfive.c @@ -368,7 +368,7 @@ static int starfive_pcie_host_init(struct plda_pcie_rp *plda) * of 100ms following exit from a conventional reset before * sending a configuration request to the device. */ - msleep(PCIE_RESET_CONFIG_DEVICE_WAIT_MS); + msleep(PCIE_RESET_CONFIG_WAIT_MS); if (starfive_pcie_host_wait_for_link(pcie)) dev_info(dev, "port link down\n"); diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 12215ee72afb..98d6fccb383e 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -61,7 +61,7 @@ struct pcie_tlp_log; * completes before sending a Configuration Request to the device * immediately below that Port." */ -#define PCIE_RESET_CONFIG_DEVICE_WAIT_MS 100 +#define PCIE_RESET_CONFIG_WAIT_MS 100 /* Message Routing (r[2:0]); PCIe r6.0, sec 2.2.8 */ #define PCIE_MSG_TYPE_R_RC 0 From bbc6a829ad3f054181d24a56944f944002e68898 Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Wed, 25 Jun 2025 12:23:48 +0200 Subject: [PATCH 2/6] PCI: rockchip-host: Use macro PCIE_RESET_CONFIG_WAIT_MS Macro PCIE_RESET_CONFIG_DEVICE_WAIT_MS was added to pci.h in commit d5ceb9496c56 ("PCI: Add PCIE_RESET_CONFIG_DEVICE_WAIT_MS waiting time value"). Later, in commit 70a7bfb1e515 ("PCI: rockchip-host: Wait 100ms after reset before starting configuration"), PCIE_T_RRS_READY_MS was added to pci.h. These macros are duplicates, and represent the exact same delay in the PCIe specification. Since the comment above PCIE_RESET_CONFIG_WAIT_MS is strictly more correct than the comment above PCIE_T_RRS_READY_MS, change rockchip-host to use PCIE_RESET_CONFIG_WAIT_MS, and remove PCIE_T_RRS_READY_MS, as rockchip-host is the only user of this macro. Signed-off-by: Niklas Cassel Signed-off-by: Manivannan Sadhasivam Reviewed-by: Wilfred Mallawa Link: https://patch.msgid.link/20250625102347.1205584-11-cassel@kernel.org --- drivers/pci/controller/pcie-rockchip-host.c | 2 +- drivers/pci/pci.h | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/pci/controller/pcie-rockchip-host.c b/drivers/pci/controller/pcie-rockchip-host.c index b9e7a8710cf0..c11ed45c25f6 100644 --- a/drivers/pci/controller/pcie-rockchip-host.c +++ b/drivers/pci/controller/pcie-rockchip-host.c @@ -325,7 +325,7 @@ static int rockchip_pcie_host_init_port(struct rockchip_pcie *rockchip) msleep(PCIE_T_PVPERL_MS); gpiod_set_value_cansleep(rockchip->perst_gpio, 1); - msleep(PCIE_T_RRS_READY_MS); + msleep(PCIE_RESET_CONFIG_WAIT_MS); /* 500ms timeout value should be enough for Gen1/2 training */ err = readl_poll_timeout(rockchip->apb_base + PCIE_CLIENT_BASIC_STATUS1, diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 98d6fccb383e..819833e57590 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -35,13 +35,6 @@ struct pcie_tlp_log; */ #define PCIE_T_PERST_CLK_US 100 -/* - * End of conventional reset (PERST# de-asserted) to first configuration - * request (device able to respond with a "Request Retry Status" completion), - * from PCIe r6.0, sec 6.6.1. - */ -#define PCIE_T_RRS_READY_MS 100 - /* * PCIe r6.0, sec 5.3.3.2.1 * Recommends 1ms to 10ms timeout to check L2 ready. From c7eb9c5e1498882951b7583c56add0b77bfc162e Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Wed, 25 Jun 2025 12:23:49 +0200 Subject: [PATCH 3/6] 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(+) 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(); From 15b6b243cc2b1017cf89e2477aa0b4e1a306a82a Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Wed, 25 Jun 2025 12:23:50 +0200 Subject: [PATCH 4/6] 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(+) 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(); From 80dc18a0cba8dea42614f021b20a04354b213d86 Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Wed, 25 Jun 2025 12:23:51 +0200 Subject: [PATCH 5/6] 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(+) 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); From d7467bc72ce4e3f64062017d6c9ae3816e8a7b0e Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Wed, 25 Jun 2025 12:23:52 +0200 Subject: [PATCH 6/6] 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(-) 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