All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2/2] PCI: qcom: Add support for retraining the link due to link down event
  2025-02-21 17:23 [PATCH 0/2] PCI: Add support for handling link down event from host bridge drivers Manivannan Sadhasivam
@ 2025-02-21 17:23 ` Manivannan Sadhasivam
  0 siblings, 0 replies; 2+ messages in thread
From: Manivannan Sadhasivam @ 2025-02-21 17:23 UTC (permalink / raw)
  To: lpieralisi, kw, bhelgaas
  Cc: linux-pci, linux-arm-msm, linux-kernel, dingwei, cassel,
	Manivannan Sadhasivam

The PCIe link can go down under circumstances such as the device removed
from the bus, reset condition, etc... When that happens, the link needs to
be retrained back to make it operational again. Currently, the driver is
not handling the link down event, due to which the users have to restart
the machine to make PCIe link operational again. So fix it by detecting the
link down event and adding support to retraining the link.

Since the Qcom PCIe controllers report the link down event through the
'global' IRQ, enable the link down event by setting PARF_INT_ALL_LINK_DOWN
bit in PARF_INT_ALL_MASK register.

Then in the case of the event, call pci_host_bridge_handle_link_down() API
in the handler to let the PCI core handle the link down condition.

The API will internally call, 'pci_ops::retrain_link()' callback to retrain
the link in a platform specific way. So implement the callback to retrain
the link by first resetting the PCIe core, followed by reinitializing the
resources and then finally starting the link again. The PCI core will
finally rescan the bus to enumerate the devices.

Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
---
 drivers/pci/controller/dwc/pcie-qcom.c | 90 +++++++++++++++++++++++++-
 1 file changed, 88 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c
index e4d3366ead1f..ebc58e88161e 100644
--- a/drivers/pci/controller/dwc/pcie-qcom.c
+++ b/drivers/pci/controller/dwc/pcie-qcom.c
@@ -55,6 +55,7 @@
 #define PARF_INT_ALL_STATUS			0x224
 #define PARF_INT_ALL_CLEAR			0x228
 #define PARF_INT_ALL_MASK			0x22c
+#define PARF_STATUS				0x230
 #define PARF_SID_OFFSET				0x234
 #define PARF_BDF_TRANSLATE_CFG			0x24c
 #define PARF_DBI_BASE_ADDR_V2			0x350
@@ -130,8 +131,11 @@
 
 /* PARF_LTSSM register fields */
 #define LTSSM_EN				BIT(8)
+#define SW_CLEAR_FLUSH_MODE			BIT(10)
+#define FLUSH_MODE				BIT(11)
 
 /* PARF_INT_ALL_{STATUS/CLEAR/MASK} register fields */
+#define PARF_INT_ALL_LINK_DOWN			BIT(1)
 #define PARF_INT_ALL_LINK_UP			BIT(13)
 #define PARF_INT_MSI_DEV_0_7			GENMASK(30, 23)
 
@@ -145,6 +149,9 @@
 /* PARF_BDF_TO_SID_CFG fields */
 #define BDF_TO_SID_BYPASS			BIT(0)
 
+/* PARF_STATUS fields */
+#define FLUSH_COMPLETED				BIT(8)
+
 /* ELBI_SYS_CTRL register fields */
 #define ELBI_SYS_CTRL_LT_ENABLE			BIT(0)
 
@@ -169,6 +176,7 @@
 						PCIE_CAP_SLOT_POWER_LIMIT_SCALE)
 
 #define PERST_DELAY_US				1000
+#define FLUSH_TIMEOUT_US			100
 
 #define QCOM_PCIE_CRC8_POLYNOMIAL		(BIT(2) | BIT(1) | BIT(0))
 
@@ -239,6 +247,7 @@ union qcom_pcie_resources {
 };
 
 struct qcom_pcie;
+static struct pci_ops qcom_pcie_bridge_ops;
 
 struct qcom_pcie_ops {
 	int (*get_resources)(struct qcom_pcie *pcie);
@@ -274,6 +283,7 @@ struct qcom_pcie {
 	struct icc_path *icc_cpu;
 	const struct qcom_pcie_cfg *cfg;
 	struct dentry *debugfs;
+	int global_irq;
 	bool suspended;
 	bool use_pm_opp;
 };
@@ -1263,6 +1273,8 @@ static int qcom_pcie_host_init(struct dw_pcie_rp *pp)
 			goto err_assert_reset;
 	}
 
+	pp->bridge->ops = &qcom_pcie_bridge_ops;
+
 	return 0;
 
 err_assert_reset:
@@ -1300,6 +1312,75 @@ static const struct dw_pcie_host_ops qcom_pcie_dw_ops = {
 	.post_init	= qcom_pcie_host_post_init,
 };
 
+static int qcom_pcie_retrain_link(struct pci_bus *bus)
+{
+	struct dw_pcie_rp *pp = bus->sysdata;
+	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+	struct qcom_pcie *pcie = to_qcom_pcie(pci);
+	struct device *dev = pcie->pci->dev;
+	u32 val;
+	int ret;
+
+	/* Wait for the pending transactions to be completed */
+	ret = readl_relaxed_poll_timeout(pcie->parf + PARF_STATUS, val,
+					 val & FLUSH_COMPLETED, 10,
+					 FLUSH_TIMEOUT_US);
+	if (ret) {
+		dev_err(dev, "Flush completion failed: %d\n", ret);
+		goto err_host_deinit;
+	}
+
+	/* Clear the FLUSH_MODE to allow the core to be reset */
+	val = readl(pcie->parf + PARF_LTSSM);
+	val |= SW_CLEAR_FLUSH_MODE;
+	writel(val, pcie->parf + PARF_LTSSM);
+
+	/* Wait for the FLUSH_MODE to clear */
+	ret = readl_relaxed_poll_timeout(pcie->parf + PARF_LTSSM, val,
+					 !(val & FLUSH_MODE), 10,
+					 FLUSH_TIMEOUT_US);
+	if (ret) {
+		dev_err(dev, "Flush mode clear failed: %d\n", ret);
+		goto err_host_deinit;
+	}
+
+	qcom_pcie_host_deinit(pp);
+
+	ret = qcom_pcie_host_init(pp);
+	if (ret) {
+		dev_err(dev, "Host init failed\n");
+		return ret;
+	}
+
+	ret = dw_pcie_setup_rc(pp);
+	if (ret)
+		goto err_host_deinit;
+
+	/*
+	 * Re-enable global IRQ events as the PARF_INT_ALL_MASK register is
+	 * non-sticky.
+	 */
+	if (pcie->global_irq)
+		writel_relaxed(PARF_INT_ALL_LINK_UP | PARF_INT_ALL_LINK_DOWN |
+			       PARF_INT_MSI_DEV_0_7, pcie->parf + PARF_INT_ALL_MASK);
+
+	qcom_pcie_start_link(pci);
+
+	return 0;
+
+err_host_deinit:
+	qcom_pcie_host_deinit(pp);
+
+	return ret;
+}
+
+static struct pci_ops qcom_pcie_bridge_ops = {
+	.map_bus = dw_pcie_own_conf_map_bus,
+	.read = pci_generic_config_read,
+	.write = pci_generic_config_write,
+	.retrain_link = qcom_pcie_retrain_link,
+};
+
 /* Qcom IP rev.: 2.1.0	Synopsys IP rev.: 4.01a */
 static const struct qcom_pcie_ops ops_2_1_0 = {
 	.get_resources = qcom_pcie_get_resources_2_1_0,
@@ -1571,6 +1652,9 @@ static irqreturn_t qcom_pcie_global_irq_thread(int irq, void *data)
 		pci_unlock_rescan_remove();
 
 		qcom_pcie_icc_opp_update(pcie);
+	} else if (FIELD_GET(PARF_INT_ALL_LINK_DOWN, status)) {
+		dev_dbg(dev, "Received Link down event\n");
+		pci_host_bridge_handle_link_down(pp->bridge);
 	} else {
 		dev_WARN_ONCE(dev, 1, "Received unknown event. INT_STATUS: 0x%08x\n",
 			      status);
@@ -1732,8 +1816,10 @@ static int qcom_pcie_probe(struct platform_device *pdev)
 			goto err_host_deinit;
 		}
 
-		writel_relaxed(PARF_INT_ALL_LINK_UP | PARF_INT_MSI_DEV_0_7,
-			       pcie->parf + PARF_INT_ALL_MASK);
+		writel_relaxed(PARF_INT_ALL_LINK_UP | PARF_INT_ALL_LINK_DOWN |
+			       PARF_INT_MSI_DEV_0_7, pcie->parf + PARF_INT_ALL_MASK);
+
+		pcie->global_irq = irq;
 	}
 
 	qcom_pcie_icc_opp_update(pcie);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH 2/2] PCI: qcom: Add support for retraining the link due to link down event
@ 2025-03-03 21:56 kernel test robot
  0 siblings, 0 replies; 2+ messages in thread
From: kernel test robot @ 2025-03-03 21:56 UTC (permalink / raw)
  To: oe-kbuild; +Cc: lkp, Dan Carpenter

BCC: lkp@intel.com
CC: oe-kbuild-all@lists.linux.dev
In-Reply-To: <20250221172309.120009-3-manivannan.sadhasivam@linaro.org>
References: <20250221172309.120009-3-manivannan.sadhasivam@linaro.org>
TO: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
TO: lpieralisi@kernel.org
TO: kw@linux.com
TO: bhelgaas@google.com
CC: linux-pci@vger.kernel.org
CC: linux-arm-msm@vger.kernel.org
CC: linux-kernel@vger.kernel.org
CC: dingwei@marvell.com
CC: cassel@kernel.org
CC: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>

Hi Manivannan,

kernel test robot noticed the following build warnings:

[auto build test WARNING on pci/next]
[also build test WARNING on pci/for-linus linus/master v6.14-rc5 next-20250303]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Manivannan-Sadhasivam/PCI-Add-pci_host_bridge_handle_link_down-API-to-handle-the-PCI-link-down-event/20250222-012526
base:   https://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git next
patch link:    https://lore.kernel.org/r/20250221172309.120009-3-manivannan.sadhasivam%40linaro.org
patch subject: [PATCH 2/2] PCI: qcom: Add support for retraining the link due to link down event
:::::: branch date: 10 days ago
:::::: commit date: 10 days ago
config: sparc64-randconfig-r071-20250303 (https://download.01.org/0day-ci/archive/20250304/202503040526.4JdFuLaA-lkp@intel.com/config)
compiler: sparc64-linux-gcc (GCC) 14.2.0

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Reported-by: Dan Carpenter <error27@gmail.com>
| Closes: https://lore.kernel.org/r/202503040526.4JdFuLaA-lkp@intel.com/

smatch warnings:
drivers/pci/controller/dwc/pcie-qcom.c:1352 qcom_pcie_retrain_link() warn: missing unwind goto?

vim +1352 drivers/pci/controller/dwc/pcie-qcom.c

82a823833f4e37 drivers/pci/host/pcie-qcom.c           Stanimir Varbanov     2015-12-18  1314  
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1315  static int qcom_pcie_retrain_link(struct pci_bus *bus)
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1316  {
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1317  	struct dw_pcie_rp *pp = bus->sysdata;
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1318  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1319  	struct qcom_pcie *pcie = to_qcom_pcie(pci);
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1320  	struct device *dev = pcie->pci->dev;
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1321  	u32 val;
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1322  	int ret;
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1323  
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1324  	/* Wait for the pending transactions to be completed */
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1325  	ret = readl_relaxed_poll_timeout(pcie->parf + PARF_STATUS, val,
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1326  					 val & FLUSH_COMPLETED, 10,
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1327  					 FLUSH_TIMEOUT_US);
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1328  	if (ret) {
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1329  		dev_err(dev, "Flush completion failed: %d\n", ret);
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1330  		goto err_host_deinit;
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1331  	}
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1332  
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1333  	/* Clear the FLUSH_MODE to allow the core to be reset */
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1334  	val = readl(pcie->parf + PARF_LTSSM);
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1335  	val |= SW_CLEAR_FLUSH_MODE;
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1336  	writel(val, pcie->parf + PARF_LTSSM);
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1337  
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1338  	/* Wait for the FLUSH_MODE to clear */
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1339  	ret = readl_relaxed_poll_timeout(pcie->parf + PARF_LTSSM, val,
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1340  					 !(val & FLUSH_MODE), 10,
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1341  					 FLUSH_TIMEOUT_US);
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1342  	if (ret) {
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1343  		dev_err(dev, "Flush mode clear failed: %d\n", ret);
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1344  		goto err_host_deinit;
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1345  	}
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1346  
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1347  	qcom_pcie_host_deinit(pp);
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1348  
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1349  	ret = qcom_pcie_host_init(pp);
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1350  	if (ret) {
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1351  		dev_err(dev, "Host init failed\n");
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21 @1352  		return ret;
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1353  	}
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1354  
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1355  	ret = dw_pcie_setup_rc(pp);
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1356  	if (ret)
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1357  		goto err_host_deinit;
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1358  
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1359  	/*
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1360  	 * Re-enable global IRQ events as the PARF_INT_ALL_MASK register is
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1361  	 * non-sticky.
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1362  	 */
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1363  	if (pcie->global_irq)
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1364  		writel_relaxed(PARF_INT_ALL_LINK_UP | PARF_INT_ALL_LINK_DOWN |
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1365  			       PARF_INT_MSI_DEV_0_7, pcie->parf + PARF_INT_ALL_MASK);
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1366  
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1367  	qcom_pcie_start_link(pci);
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1368  
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1369  	return 0;
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1370  
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1371  err_host_deinit:
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1372  	qcom_pcie_host_deinit(pp);
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1373  
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1374  	return ret;
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1375  }
6d1377b2f82331 drivers/pci/controller/dwc/pcie-qcom.c Manivannan Sadhasivam 2025-02-21  1376  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2025-03-03 21:56 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-03 21:56 [PATCH 2/2] PCI: qcom: Add support for retraining the link due to link down event kernel test robot
  -- strict thread matches above, loose matches on Subject: below --
2025-02-21 17:23 [PATCH 0/2] PCI: Add support for handling link down event from host bridge drivers Manivannan Sadhasivam
2025-02-21 17:23 ` [PATCH 2/2] PCI: qcom: Add support for retraining the link due to link down event Manivannan Sadhasivam

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.