diff mbox series

[V2,6/9] PCI: tegra194: Refactor LTSSM state polling on surprise down

Message ID 20220926115038.24727-7-vidyas@nvidia.com (mailing list archive)
State Superseded
Delegated to: Lorenzo Pieralisi
Headers show
Series Enhancements to pcie-tegra194 driver | expand

Commit Message

Vidya Sagar Sept. 26, 2022, 11:50 a.m. UTC
On surprise down LTSSM state transisition from L0 -> Recovery.RcvrLock ->
Recovery.RcvrSpeed -> Gen1 Recovery.RcvrLock -> Detect.
Recovery.RcvrLock and Recovery.RcvrSpeed time is 24 msec and 48 msec
respectively. It takes ~96 msec to move from L0 to detect state, hence,
increase the poll time to 120 msec. Disable the LTSSM state after it moves
to detect to avoid LTSSM toggle between polling and detect.

Signed-off-by: Vidya Sagar <vidyas@nvidia.com>
---
V2:
* None

 drivers/pci/controller/dwc/pcie-tegra194.c | 69 ++++++++++++++--------
 1 file changed, 46 insertions(+), 23 deletions(-)

Comments

Bjorn Helgaas Sept. 26, 2022, 6:16 p.m. UTC | #1
On Mon, Sep 26, 2022 at 05:20:35PM +0530, Vidya Sagar wrote:
> On surprise down LTSSM state transisition from L0 -> Recovery.RcvrLock ->
> Recovery.RcvrSpeed -> Gen1 Recovery.RcvrLock -> Detect.
> Recovery.RcvrLock and Recovery.RcvrSpeed time is 24 msec and 48 msec
> respectively. It takes ~96 msec to move from L0 to detect state, hence,
> increase the poll time to 120 msec. Disable the LTSSM state after it moves
> to detect to avoid LTSSM toggle between polling and detect.

s/transisition/transition/

>  		err = readl_poll_timeout_atomic(pcie->appl_base + APPL_DEBUG,
>  						data,
>  						((data &
> -						APPL_DEBUG_LTSSM_STATE_MASK) >>
> -						APPL_DEBUG_LTSSM_STATE_SHIFT) ==
> -						LTSSM_STATE_PRE_DETECT,
> -						1, LTSSM_TIMEOUT);
> +						APPL_DEBUG_LTSSM_STATE_MASK) ==
> +						LTSSM_STATE_DETECT_QUIET) ||
> +						((data &
> +						APPL_DEBUG_LTSSM_STATE_MASK) ==
> +						LTSSM_STATE_DETECT_ACT) ||
> +						((data &
> +						APPL_DEBUG_LTSSM_STATE_MASK) ==
> +						LTSSM_STATE_PRE_DETECT_QUIET) ||
> +						((data &
> +						APPL_DEBUG_LTSSM_STATE_MASK) ==
> +						LTSSM_STATE_DETECT_WAIT),
> +						LTSSM_DELAY, LTSSM_TIMEOUT);

I know we usually line up the function parameters with that opening
paren, but I think overall it would be nicer to drop a couple of the
leading tabs so these don't wrap so awkwardly.

> +	ret = readl_poll_timeout(pcie->appl_base + APPL_DEBUG, val,
> +				 ((val & APPL_DEBUG_LTSSM_STATE_MASK) ==
> +				 LTSSM_STATE_DETECT_QUIET) ||
> +				 ((val & APPL_DEBUG_LTSSM_STATE_MASK) ==
> +				 LTSSM_STATE_DETECT_ACT) ||
> +				 ((val & APPL_DEBUG_LTSSM_STATE_MASK) ==
> +				 LTSSM_STATE_PRE_DETECT_QUIET) ||
> +				 ((val & APPL_DEBUG_LTSSM_STATE_MASK) ==
> +				 LTSSM_STATE_DETECT_WAIT) ||
> +				 ((val & APPL_DEBUG_LTSSM_STATE_MASK) ==
> +				 LTSSM_STATE_L2_IDLE),
> +				 LTSSM_DELAY, LTSSM_TIMEOUT);

Ditto.
diff mbox series

Patch

diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
index 4ba2a17d92d2..702c55deb747 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -140,7 +140,11 @@ 
 #define APPL_DEBUG_PM_LINKST_IN_L0		0x11
 #define APPL_DEBUG_LTSSM_STATE_MASK		GENMASK(8, 3)
 #define APPL_DEBUG_LTSSM_STATE_SHIFT		3
-#define LTSSM_STATE_PRE_DETECT			5
+#define LTSSM_STATE_DETECT_QUIET		0x00
+#define LTSSM_STATE_DETECT_ACT			0x08
+#define LTSSM_STATE_PRE_DETECT_QUIET		0x28
+#define LTSSM_STATE_DETECT_WAIT			0x30
+#define LTSSM_STATE_L2_IDLE			0xa8
 
 #define APPL_RADM_STATUS			0xE4
 #define APPL_PM_XMT_TURNOFF_STATE		BIT(0)
@@ -209,7 +213,8 @@ 
 #define PME_ACK_DELAY		100   /* 100 us */
 #define PME_ACK_TIMEOUT		10000 /* 10 ms */
 
-#define LTSSM_TIMEOUT 50000	/* 50ms */
+#define LTSSM_DELAY		10000	/* 10 ms */
+#define LTSSM_TIMEOUT		120000	/* 120 ms */
 
 #define GEN3_GEN4_EQ_PRESET_INIT	5
 
@@ -1606,23 +1611,31 @@  static void tegra_pcie_dw_pme_turnoff(struct tegra_pcie_dw *pcie)
 		data &= ~APPL_PINMUX_PEX_RST;
 		appl_writel(pcie, data, APPL_PINMUX);
 
-		/*
-		 * Some cards do not go to detect state even after de-asserting
-		 * PERST#. So, de-assert LTSSM to bring link to detect state.
-		 */
-		data = readl(pcie->appl_base + APPL_CTRL);
-		data &= ~APPL_CTRL_LTSSM_EN;
-		writel(data, pcie->appl_base + APPL_CTRL);
-
 		err = readl_poll_timeout_atomic(pcie->appl_base + APPL_DEBUG,
 						data,
 						((data &
-						APPL_DEBUG_LTSSM_STATE_MASK) >>
-						APPL_DEBUG_LTSSM_STATE_SHIFT) ==
-						LTSSM_STATE_PRE_DETECT,
-						1, LTSSM_TIMEOUT);
+						APPL_DEBUG_LTSSM_STATE_MASK) ==
+						LTSSM_STATE_DETECT_QUIET) ||
+						((data &
+						APPL_DEBUG_LTSSM_STATE_MASK) ==
+						LTSSM_STATE_DETECT_ACT) ||
+						((data &
+						APPL_DEBUG_LTSSM_STATE_MASK) ==
+						LTSSM_STATE_PRE_DETECT_QUIET) ||
+						((data &
+						APPL_DEBUG_LTSSM_STATE_MASK) ==
+						LTSSM_STATE_DETECT_WAIT),
+						LTSSM_DELAY, LTSSM_TIMEOUT);
 		if (err)
 			dev_info(pcie->dev, "Link didn't go to detect state\n");
+
+		/*
+		 * Deassert LTSSM state to stop the state toggling between
+		 * polling and detect.
+		 */
+		data = readl(pcie->appl_base + APPL_CTRL);
+		data &= ~APPL_CTRL_LTSSM_EN;
+		writel(data, pcie->appl_base + APPL_CTRL);
 	}
 	/*
 	 * DBI registers may not be accessible after this as PLL-E would be
@@ -1698,19 +1711,29 @@  static void pex_ep_event_pex_rst_assert(struct tegra_pcie_dw *pcie)
 	if (pcie->ep_state == EP_STATE_DISABLED)
 		return;
 
-	/* Disable LTSSM */
+	ret = readl_poll_timeout(pcie->appl_base + APPL_DEBUG, val,
+				 ((val & APPL_DEBUG_LTSSM_STATE_MASK) ==
+				 LTSSM_STATE_DETECT_QUIET) ||
+				 ((val & APPL_DEBUG_LTSSM_STATE_MASK) ==
+				 LTSSM_STATE_DETECT_ACT) ||
+				 ((val & APPL_DEBUG_LTSSM_STATE_MASK) ==
+				 LTSSM_STATE_PRE_DETECT_QUIET) ||
+				 ((val & APPL_DEBUG_LTSSM_STATE_MASK) ==
+				 LTSSM_STATE_DETECT_WAIT) ||
+				 ((val & APPL_DEBUG_LTSSM_STATE_MASK) ==
+				 LTSSM_STATE_L2_IDLE),
+				 LTSSM_DELAY, LTSSM_TIMEOUT);
+	if (ret)
+		dev_err(pcie->dev, "LTSSM state: 0x%x timeout: %d\n", val, ret);
+
+	/*
+	 * Deassert LTSSM state to stop the state toggling between
+	 * polling and detect.
+	 */
 	val = appl_readl(pcie, APPL_CTRL);
 	val &= ~APPL_CTRL_LTSSM_EN;
 	appl_writel(pcie, val, APPL_CTRL);
 
-	ret = readl_poll_timeout(pcie->appl_base + APPL_DEBUG, val,
-				 ((val & APPL_DEBUG_LTSSM_STATE_MASK) >>
-				 APPL_DEBUG_LTSSM_STATE_SHIFT) ==
-				 LTSSM_STATE_PRE_DETECT,
-				 1, LTSSM_TIMEOUT);
-	if (ret)
-		dev_err(pcie->dev, "Failed to go Detect state: %d\n", ret);
-
 	reset_control_assert(pcie->core_rst);
 
 	tegra_pcie_disable_phy(pcie);