mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2 00/10] PCI: tegra194: Fix EP and Root Port corner cases
@ 2026-10-21  6:13 Manikanta Maddireddy
  2026-10-21  6:13 ` [PATCH v2 01/10] PCI: tegra194: Propagate REFCLK select GPIO errors Manikanta Maddireddy
                   ` (9 more replies)
  0 siblings, 10 replies; 21+ messages in thread
From: Manikanta Maddireddy @ 2026-10-21  6:13 UTC (permalink / raw)
  To: lpieralisi, kwilczynski, mani, bhelgaas, linux-pci
  Cc: robh, thierry.reding, jonathanh, kishon, Frank.Li, vidyas,
	cassel, den, marco.crivellari, andriy.shevchenko, linux-tegra,
	linux-kernel, mmaddireddy

This series fixes a set of independent Tegra194/Tegra234 PCIe controller
issues found while testing Root Port and Endpoint flows.

The Root Port fixes tighten probe/remove and suspend/resume error handling:
propagate optional GPIO failures, check reset deassertion, avoid skipping
cleanup when no link came up, and balance the optional core monitor clock
on failures.

The Endpoint fixes cover PERST# IRQ suspend handling, PHY/PLL error
unwinds, capability checks before programming optional PCIe extended
capabilities, hiding Tegra234 EP L1.2 advertisement for the documented
hardware limitation, and rejecting invalid MSI interrupt number zero.

The patches are ordered from low-level error handling toward Endpoint
capability checks and MSI validation. MSI-X enablement, MSI-X doorbell
changes and fixed MSI-X table handling are deferred; MSI-X remains
disabled in the Tegra EPC features.

Changes in v2:
- Expand the PERST# suspend-race explanation to describe how an IRQ thread
  can enable the endpoint after the original state check. Explain how
  disable_irq() drains that thread and preserves the existing suspend
  policy, and add a synchronization comment.
- Split the MSI-only zero check out of the former MSI/MSI-X patch, with a
  focused title and commit message. Treat it as defensive validation and
  omit the Fixes tag from that patch.
- Drop all MSI-X changes and the fixed MSI-X table patch (v1 patch 11),
  reducing the series from eleven patches to ten.
- Adapt register names to the preceding DWC register-field cleanup series.

Validation:
- ARM64 compilation of the Tegra driver passed.
- Checkpatch and whitespace checks passed.
- Tegra PCIe EP link up with pci-epf-test driver.
- pci_endpoint_test
  - pci_ep_bar.BAR0.BAR_TEST
  - pci_ep_basic.CONSECUTIVE_BAR_TEST
  - pci_ep_basic.LEGACY_IRQ_TEST
  - pci_ep_basic.MSI_TEST
  - pci_ep_data_transfer.memcpy.READ_TEST
  - pci_ep_data_transfer.memcpy.WRITE_TEST
  - pci_ep_data_transfer.memcpy.COPY_TEST

v1: https://lore.kernel.org/linux-pci/20260923072237.1139013-1-mmaddireddy@nvidia.com/

Manikanta Maddireddy (10):
  PCI: tegra194: Propagate REFCLK select GPIO errors
  PCI: tegra194: Check core reset deassertion
  PCI: tegra194: Fix Endpoint PERST# IRQ suspend race
  PCI: tegra194: Do not skip no-link Root Port remove cleanup
  PCI: tegra194: Check for 16 GT/s capability before programming
  PCI: tegra194: Check for L1SS capability before programming
  PCI: tegra194: Always disable Tegra234 Endpoint L1.2
  PCI: tegra194: Guard Endpoint PLL-off error path
  PCI: tegra194: Balance core monitor clock on failures
  PCI: tegra194: Reject zero MSI interrupt number

 drivers/pci/controller/dwc/pcie-tegra194.c | 221 +++++++++++++--------
 1 file changed, 142 insertions(+), 79 deletions(-)

-- 
2.34.1


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

* [PATCH v2 01/10] PCI: tegra194: Propagate REFCLK select GPIO errors
  2026-10-21  6:13 [PATCH v2 00/10] PCI: tegra194: Fix EP and Root Port corner cases Manikanta Maddireddy
@ 2026-10-21  6:13 ` Manikanta Maddireddy
  2026-10-21 15:14   ` Frank Li
  2026-10-21  6:13 ` [PATCH v2 02/10] PCI: tegra194: Check core reset deassertion Manikanta Maddireddy
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 21+ messages in thread
From: Manikanta Maddireddy @ 2026-10-21  6:13 UTC (permalink / raw)
  To: lpieralisi, kwilczynski, mani, bhelgaas, linux-pci
  Cc: robh, thierry.reding, jonathanh, kishon, Frank.Li, vidyas,
	cassel, den, marco.crivellari, andriy.shevchenko, linux-tegra,
	linux-kernel, mmaddireddy

devm_gpiod_get_optional() returns NULL only when the optional GPIO is
absent. Other error pointers, including -EPROBE_DEFER, describe real
failures and should not be converted to NULL.

Return dev_err_probe() errors for nvidia,refclk-select so probe does not
continue without a GPIO that exists but is not ready or could not be
requested.

Fixes: c57247f940e8 ("PCI: tegra: Add support for PCIe endpoint mode in Tegra194")
Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
---
Changes V1 -> V2: None

 drivers/pci/controller/dwc/pcie-tegra194.c | 15 +++------------
 1 file changed, 3 insertions(+), 12 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
index 9b349b3430f1..6104a22d930e 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -1206,18 +1206,9 @@ static int tegra_pcie_dw_parse_dt(struct tegra_pcie_dw *pcie)
 	pcie->pex_refclk_sel_gpiod = devm_gpiod_get_optional(pcie->dev,
 							     "nvidia,refclk-select",
 							     GPIOD_OUT_HIGH);
-	if (IS_ERR(pcie->pex_refclk_sel_gpiod)) {
-		int err = PTR_ERR(pcie->pex_refclk_sel_gpiod);
-		const char *level = KERN_ERR;
-
-		if (err == -EPROBE_DEFER)
-			level = KERN_DEBUG;
-
-		dev_printk(level, pcie->dev,
-			   dev_fmt("Failed to get REFCLK select GPIOs: %d\n"),
-			   err);
-		pcie->pex_refclk_sel_gpiod = NULL;
-	}
+	if (IS_ERR(pcie->pex_refclk_sel_gpiod))
+		return dev_err_probe(pcie->dev, PTR_ERR(pcie->pex_refclk_sel_gpiod),
+				     "Failed to get REFCLK select GPIO\n");
 
 	return 0;
 }
-- 
2.34.1


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

* [PATCH v2 02/10] PCI: tegra194: Check core reset deassertion
  2026-10-21  6:13 [PATCH v2 00/10] PCI: tegra194: Fix EP and Root Port corner cases Manikanta Maddireddy
  2026-10-21  6:13 ` [PATCH v2 01/10] PCI: tegra194: Propagate REFCLK select GPIO errors Manikanta Maddireddy
@ 2026-10-21  6:13 ` Manikanta Maddireddy
  2026-10-21 15:16   ` Frank Li
  2026-10-21  6:13 ` [PATCH v2 03/10] PCI: tegra194: Fix Endpoint PERST# IRQ suspend race Manikanta Maddireddy
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 21+ messages in thread
From: Manikanta Maddireddy @ 2026-10-21  6:13 UTC (permalink / raw)
  To: lpieralisi, kwilczynski, mani, bhelgaas, linux-pci
  Cc: robh, thierry.reding, jonathanh, kishon, Frank.Li, vidyas,
	cassel, den, marco.crivellari, andriy.shevchenko, linux-tegra,
	linux-kernel, mmaddireddy

Several paths access DBI registers after deasserting the controller core
reset. If reset_control_deassert() fails, those DBI accesses can trigger a
CBB timeout, or setup can return success with the core still in reset.

Check core reset deassertion in Root Port setup, the DLF retry path and the
Endpoint PERST# deassert path. Unwind before DBI access when deassertion
fails.

Fixes: 56e15a238d92 ("PCI: tegra: Add Tegra194 PCIe support")
Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
---
Changes V1 -> V2: None

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

diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
index 6104a22d930e..89dbef83dd9e 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -954,6 +954,7 @@ static int tegra_pcie_dw_start_link(struct dw_pcie *pci)
 	struct tegra_pcie_dw *pcie = to_tegra_pcie(pci);
 	struct dw_pcie_rp *pp = &pci->pp;
 	u32 val, offset, tmp;
+	int ret;
 	bool retry = true;
 
 	if (pcie->of_data->mode == DW_PCIE_EP_TYPE) {
@@ -1009,7 +1010,12 @@ static int tegra_pcie_dw_start_link(struct dw_pcie *pci)
 		appl_writel(pcie, val, APPL_CTRL);
 
 		reset_control_assert(pcie->core_rst);
-		reset_control_deassert(pcie->core_rst);
+		ret = reset_control_deassert(pcie->core_rst);
+		if (ret) {
+			dev_err(pci->dev, "Failed to deassert core reset: %d\n",
+				ret);
+			return ret;
+		}
 
 		offset = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_DLF);
 		val = dw_pcie_readl_dbi(pci, offset + PCI_DLF_CAP);
@@ -1455,10 +1461,16 @@ static int tegra_pcie_config_controller(struct tegra_pcie_dw *pcie,
 		    pcie->atu_dma_res->start & APPL_CFG_IATU_DMA_BASE_ADDR_MASK,
 		    APPL_CFG_IATU_DMA_BASE_ADDR);
 
-	reset_control_deassert(pcie->core_rst);
+	ret = reset_control_deassert(pcie->core_rst);
+	if (ret) {
+		dev_err(pcie->dev, "Failed to deassert core reset: %d\n", ret);
+		goto fail_core_rst;
+	}
 
 	return ret;
 
+fail_core_rst:
+	tegra_pcie_disable_phy(pcie);
 fail_phy:
 	reset_control_assert(pcie->core_apb_rst);
 fail_core_apb_rst:
@@ -1853,7 +1865,11 @@ static void pex_ep_event_pex_rst_deassert(struct tegra_pcie_dw *pcie)
 	      LTR_NOSNOOP_MSG_REQ;
 	appl_writel(pcie, val, APPL_LTR_MSG_1);
 
-	reset_control_deassert(pcie->core_rst);
+	ret = reset_control_deassert(pcie->core_rst);
+	if (ret) {
+		dev_err(dev, "Failed to deassert core reset: %d\n", ret);
+		goto fail_core_rst;
+	}
 
 	/* Perform cleanup that requires refclk and core reset deasserted */
 	pci_epc_deinit_notify(pcie->pci.ep.epc);
@@ -1927,6 +1943,7 @@ static void pex_ep_event_pex_rst_deassert(struct tegra_pcie_dw *pcie)
 
 fail_init_complete:
 	reset_control_assert(pcie->core_rst);
+fail_core_rst:
 	tegra_pcie_disable_phy(pcie);
 fail_phy:
 	reset_control_assert(pcie->core_apb_rst);
-- 
2.34.1


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

* [PATCH v2 03/10] PCI: tegra194: Fix Endpoint PERST# IRQ suspend race
  2026-10-21  6:13 [PATCH v2 00/10] PCI: tegra194: Fix EP and Root Port corner cases Manikanta Maddireddy
  2026-10-21  6:13 ` [PATCH v2 01/10] PCI: tegra194: Propagate REFCLK select GPIO errors Manikanta Maddireddy
  2026-10-21  6:13 ` [PATCH v2 02/10] PCI: tegra194: Check core reset deassertion Manikanta Maddireddy
@ 2026-10-21  6:13 ` Manikanta Maddireddy
  2026-10-21 15:19   ` Frank Li
  2026-10-21  6:13 ` [PATCH v2 04/10] PCI: tegra194: Do not skip no-link Root Port remove cleanup Manikanta Maddireddy
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 21+ messages in thread
From: Manikanta Maddireddy @ 2026-10-21  6:13 UTC (permalink / raw)
  To: lpieralisi, kwilczynski, mani, bhelgaas, linux-pci
  Cc: robh, thierry.reding, jonathanh, kishon, Frank.Li, vidyas,
	cassel, den, marco.crivellari, andriy.shevchenko, linux-tegra,
	linux-kernel, mmaddireddy

Endpoint system suspend is allowed only while the endpoint is disabled.
Checking ep_state before disabling the PERST# IRQ leaves a window in which
PERST# deassertion starts the threaded handler after the check. The
handler can enable the controller, clocks and PHYs before disable_irq()
returns, but suspend still succeeds based on the earlier disabled state.
The system then proceeds into suspend with an active endpoint that should
have caused the suspend callback to reject the transition.

Disable the PERST# IRQ before checking ep_state. disable_irq() waits for
an already-running threaded handler to finish, so the state check sees
its completed transition and no new handler can enable the endpoint.
Re-enable the IRQ immediately if the endpoint is enabled and reject
suspend. Otherwise, keep it disabled until the normal resume callback.
This also balances the IRQ disable when another device aborts suspend
and PM rolls back through .resume without calling .resume_early.

This preserves the existing policy that PERST# is not serviced while the
endpoint is suspended. It serializes the software state check with the
IRQ thread; it does not make PERST# a wakeup source or guarantee delivery
of transitions during suspension.

Wrap the PM ops pointer with pm_sleep_ptr() so the callbacks are used
only when system sleep is enabled.

Fixes: c76f8eae7d46 ("PCI: tegra194: Allow system suspend when the Endpoint link is not up")
Link: https://lore.kernel.org/r/20260324190755.1094879-10-mmaddireddy@nvidia.com
Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
---
Changes V1 -> V2:
- Expand the commit message to explain the active-endpoint suspend race,
  IRQ-thread synchronization and suspend rollback handling.
- Clarify that PERST# is not serviced while the endpoint is suspended.
- Add a comment explaining why the IRQ thread is drained before checking
  endpoint state.

 drivers/pci/controller/dwc/pcie-tegra194.c | 34 ++++++++++++++--------
 1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
index 89dbef83dd9e..0f895c766a71 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -2374,19 +2374,30 @@ static int tegra_pcie_dw_suspend(struct device *dev)
 {
 	struct tegra_pcie_dw *pcie = dev_get_drvdata(dev);
 
-	if (pcie->of_data->mode == DW_PCIE_EP_TYPE) {
-		if (pcie->ep_state == EP_STATE_ENABLED) {
-			dev_err(dev, "Tegra PCIe is in EP mode, suspend not allowed\n");
-			return -EPERM;
-		}
-
-		disable_irq(pcie->pex_rst_irq);
+	if (pcie->of_data->mode != DW_PCIE_EP_TYPE)
 		return 0;
+
+	/* Drain the PERST# thread before checking whether the endpoint is idle. */
+	disable_irq(pcie->pex_rst_irq);
+	if (pcie->ep_state == EP_STATE_ENABLED) {
+		enable_irq(pcie->pex_rst_irq);
+		dev_err(dev, "Tegra PCIe is in EP mode, suspend not allowed\n");
+		return -EPERM;
 	}
 
 	return 0;
 }
 
+static int tegra_pcie_dw_resume(struct device *dev)
+{
+	struct tegra_pcie_dw *pcie = dev_get_drvdata(dev);
+
+	if (pcie->of_data->mode == DW_PCIE_EP_TYPE)
+		enable_irq(pcie->pex_rst_irq);
+
+	return 0;
+}
+
 static int tegra_pcie_dw_suspend_late(struct device *dev)
 {
 	struct tegra_pcie_dw *pcie = dev_get_drvdata(dev);
@@ -2462,10 +2473,8 @@ static int tegra_pcie_dw_resume_early(struct device *dev)
 	struct tegra_pcie_dw *pcie = dev_get_drvdata(dev);
 	u32 val;
 
-	if (pcie->of_data->mode == DW_PCIE_EP_TYPE) {
-		enable_irq(pcie->pex_rst_irq);
+	if (pcie->of_data->mode == DW_PCIE_EP_TYPE)
 		return 0;
-	}
 
 	if (!pcie->link_state)
 		return 0;
@@ -2569,10 +2578,11 @@ static const struct of_device_id tegra_pcie_dw_of_match[] = {
 
 static const struct dev_pm_ops tegra_pcie_dw_pm_ops = {
 	.suspend = tegra_pcie_dw_suspend,
+	.resume = tegra_pcie_dw_resume,
 	.suspend_late = tegra_pcie_dw_suspend_late,
+	.resume_early = tegra_pcie_dw_resume_early,
 	.suspend_noirq = tegra_pcie_dw_suspend_noirq,
 	.resume_noirq = tegra_pcie_dw_resume_noirq,
-	.resume_early = tegra_pcie_dw_resume_early,
 };
 
 static struct platform_driver tegra_pcie_dw_driver = {
@@ -2581,7 +2591,7 @@ static struct platform_driver tegra_pcie_dw_driver = {
 	.shutdown = tegra_pcie_dw_shutdown,
 	.driver = {
 		.name	= "tegra194-pcie",
-		.pm = &tegra_pcie_dw_pm_ops,
+		.pm = pm_sleep_ptr(&tegra_pcie_dw_pm_ops),
 		.of_match_table = tegra_pcie_dw_of_match,
 	},
 };
-- 
2.34.1


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

* [PATCH v2 04/10] PCI: tegra194: Do not skip no-link Root Port remove cleanup
  2026-10-21  6:13 [PATCH v2 00/10] PCI: tegra194: Fix EP and Root Port corner cases Manikanta Maddireddy
                   ` (2 preceding siblings ...)
  2026-10-21  6:13 ` [PATCH v2 03/10] PCI: tegra194: Fix Endpoint PERST# IRQ suspend race Manikanta Maddireddy
@ 2026-10-21  6:13 ` Manikanta Maddireddy
  2026-10-21 15:22   ` Frank Li
  2026-10-21  6:13 ` [PATCH v2 05/10] PCI: tegra194: Check for 16 GT/s capability before programming Manikanta Maddireddy
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 21+ messages in thread
From: Manikanta Maddireddy @ 2026-10-21  6:13 UTC (permalink / raw)
  To: lpieralisi, kwilczynski, mani, bhelgaas, linux-pci
  Cc: robh, thierry.reding, jonathanh, kishon, Frank.Li, vidyas,
	cassel, den, marco.crivellari, andriy.shevchenko, linux-tegra,
	linux-kernel, mmaddireddy

tegra_pcie_config_rp() deinitializes the controller and disables runtime PM
when link training fails, then probe treats -ENOMEDIUM as success so the
driver can remain bound without a link.

remove() returned immediately when the Root Port link was down. That skips
common cleanup such as tegra_bpmp_put() and deasserting the refclk-select
GPIO. Keep link-dependent controller teardown conditional, but always run
common remove cleanup.

Fixes: 56e15a238d92 ("PCI: tegra: Add Tegra194 PCIe support")
Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
---
Changes V1 -> V2: None

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

diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
index 0f895c766a71..fb8084cef38b 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -2352,19 +2352,19 @@ static void tegra_pcie_dw_remove(struct platform_device *pdev)
 	struct dw_pcie_ep *ep = &pcie->pci.ep;
 
 	if (pcie->of_data->mode == DW_PCIE_RC_TYPE) {
-		if (!pcie->link_state)
-			return;
-
-		debugfs_remove_recursive(pcie->debugfs);
-		tegra_pcie_deinit_controller(pcie);
-		pm_runtime_put_sync(pcie->dev);
+		if (pcie->link_state) {
+			debugfs_remove_recursive(pcie->debugfs);
+			tegra_pcie_deinit_controller(pcie);
+			pm_runtime_put_sync(pcie->dev);
+			pm_runtime_disable(pcie->dev);
+		}
 	} else {
 		disable_irq(pcie->pex_rst_irq);
 		pex_ep_event_pex_rst_assert(pcie);
 		dw_pcie_ep_deinit(ep);
+		pm_runtime_disable(pcie->dev);
 	}
 
-	pm_runtime_disable(pcie->dev);
 	tegra_bpmp_put(pcie->bpmp);
 	if (pcie->pex_refclk_sel_gpiod)
 		gpiod_set_value(pcie->pex_refclk_sel_gpiod, 0);
-- 
2.34.1


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

* [PATCH v2 05/10] PCI: tegra194: Check for 16 GT/s capability before programming
  2026-10-21  6:13 [PATCH v2 00/10] PCI: tegra194: Fix EP and Root Port corner cases Manikanta Maddireddy
                   ` (3 preceding siblings ...)
  2026-10-21  6:13 ` [PATCH v2 04/10] PCI: tegra194: Do not skip no-link Root Port remove cleanup Manikanta Maddireddy
@ 2026-10-21  6:13 ` Manikanta Maddireddy
  2026-10-21 15:24   ` Frank Li
  2026-10-21  6:13 ` [PATCH v2 06/10] PCI: tegra194: Check for L1SS " Manikanta Maddireddy
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 21+ messages in thread
From: Manikanta Maddireddy @ 2026-10-21  6:13 UTC (permalink / raw)
  To: lpieralisi, kwilczynski, mani, bhelgaas, linux-pci
  Cc: robh, thierry.reding, jonathanh, kishon, Frank.Li, vidyas,
	cassel, den, marco.crivellari, andriy.shevchenko, linux-tegra,
	linux-kernel, mmaddireddy

config_gen3_gen4_eq_presets() added PCI_PL_16GT_LE_CTRL to the result of
dw_pcie_find_ext_capability() without checking whether the 16 GT/s
capability exists. If the capability is absent, the code writes lane
presets at an unrelated configuration offset.

Look up the capability once before the lane loop and skip the 16 GT/s lane
equivalent control programming when it is absent.

Fixes: 56e15a238d92 ("PCI: tegra: Add Tegra194 PCIe support")
Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
---
Changes V1 -> V2: None

 drivers/pci/controller/dwc/pcie-tegra194.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
index fb8084cef38b..14031cfaee8b 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -840,7 +840,11 @@ static void tegra_pcie_enable_interrupts(struct dw_pcie_rp *pp)
 static void config_gen3_gen4_eq_presets(struct tegra_pcie_dw *pcie)
 {
 	struct dw_pcie *pci = &pcie->pci;
-	u32 val, offset, i;
+	u32 pl16g, val, i;
+
+	pl16g = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_PL_16GT);
+	if (pl16g)
+		pl16g += PCI_PL_16GT_LE_CTRL;
 
 	/* Program init preset */
 	for (i = 0; i < pcie->num_lanes; i++) {
@@ -851,15 +855,15 @@ static void config_gen3_gen4_eq_presets(struct tegra_pcie_dw *pcie)
 			     GEN3_GEN4_EQ_PRESET_INIT);
 		dw_pcie_writew_dbi(pci, CAP_SPCIE_CAP_OFF + (i * 2), val);
 
-		offset = dw_pcie_find_ext_capability(pci,
-						     PCI_EXT_CAP_ID_PL_16GT) +
-				PCI_PL_16GT_LE_CTRL;
-		val = dw_pcie_readb_dbi(pci, offset + i);
+		if (!pl16g)
+			continue;
+
+		val = dw_pcie_readb_dbi(pci, pl16g + i);
 		FIELD_MODIFY(PCI_PL_16GT_LE_CTRL_DSP_TX_PRESET_MASK, &val,
 			     GEN3_GEN4_EQ_PRESET_INIT);
 		FIELD_MODIFY(PCI_PL_16GT_LE_CTRL_USP_TX_PRESET_MASK, &val,
 			     GEN3_GEN4_EQ_PRESET_INIT);
-		dw_pcie_writeb_dbi(pci, offset + i, val);
+		dw_pcie_writeb_dbi(pci, pl16g + i, val);
 	}
 
 	val = dw_pcie_readl_dbi(pci, GEN3_CTRL);
-- 
2.34.1


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

* [PATCH v2 06/10] PCI: tegra194: Check for L1SS capability before programming
  2026-10-21  6:13 [PATCH v2 00/10] PCI: tegra194: Fix EP and Root Port corner cases Manikanta Maddireddy
                   ` (4 preceding siblings ...)
  2026-10-21  6:13 ` [PATCH v2 05/10] PCI: tegra194: Check for 16 GT/s capability before programming Manikanta Maddireddy
@ 2026-10-21  6:13 ` Manikanta Maddireddy
  2026-10-21 15:28   ` Frank Li
  2026-10-21  6:13 ` [PATCH v2 07/10] PCI: tegra194: Always disable Tegra234 Endpoint L1.2 Manikanta Maddireddy
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 21+ messages in thread
From: Manikanta Maddireddy @ 2026-10-21  6:13 UTC (permalink / raw)
  To: lpieralisi, kwilczynski, mani, bhelgaas, linux-pci
  Cc: robh, thierry.reding, jonathanh, kishon, Frank.Li, vidyas,
	cassel, den, marco.crivellari, andriy.shevchenko, linux-tegra,
	linux-kernel, mmaddireddy

init_host_aspm() programs the L1 PM Substates capability without checking
whether the controller advertises it. If the capability is absent, the
code writes offsets from zero instead of L1SS registers.

Check for the L1SS capability before programming L1SS-specific fields.
Keep RAS-DES discovery, ASPM counter enablement and AFR latency
programming outside that guard because they do not depend on L1SS.
Only create the ASPM counter debugfs file when the RAS-DES capability is
present.

Fixes: 56e15a238d92 ("PCI: tegra: Add Tegra194 PCIe support")
Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
---
Changes V1 -> V2:
- Use RAS_DES_EVENT_COUNTER_CONTROL to match the preceding DWC register
  renames. No functional changes.

 drivers/pci/controller/dwc/pcie-tegra194.c | 72 ++++++++++++----------
 1 file changed, 41 insertions(+), 31 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
index 14031cfaee8b..7c349478556d 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -673,37 +673,46 @@ static void init_host_aspm(struct tegra_pcie_dw *pcie)
 
 	pcie->ras_des_cap = dw_pcie_find_ext_capability(&pcie->pci,
 							PCI_EXT_CAP_ID_VNDR);
-
-	/* Enable ASPM counters */
-	val = FIELD_PREP(EVENT_COUNTER_ENABLE_MASK, EVENT_COUNTER_ENABLE_ALL);
-	val |= FIELD_PREP(EVENT_COUNTER_GROUP_SEL_MASK, EVENT_COUNTER_GROUP_5);
-	dw_pcie_writel_dbi(pci, pcie->ras_des_cap +
-			   RAS_DES_EVENT_COUNTER_CONTROL, val);
-
-	/* Program T_cmrt and T_pwr_on values */
-	val = dw_pcie_readl_dbi(pci, l1ss + PCI_L1SS_CAP);
-	FIELD_MODIFY(PCI_L1SS_CAP_CM_RESTORE_TIME, &val, pcie->aspm_cmrt);
-	FIELD_MODIFY(PCI_L1SS_CAP_P_PWR_ON_VALUE, &val, pcie->aspm_pwr_on_t);
-	dw_pcie_writel_dbi(pci, l1ss + PCI_L1SS_CAP, val);
-
-	if (pcie->supports_clkreq)
-		pci->l1ss_support = true;
-
-	/*
-	 * Disable L1.2 capability advertisement for Tegra234 Endpoint mode.
-	 * Tegra234 has a hardware bug where during L1.2 exit, the UPHY PLL is
-	 * powered up immediately without waiting for REFCLK to stabilize. This
-	 * causes the PLL to fail to lock to the correct frequency, resulting in
-	 * PCIe link loss. Since there is no hardware fix available, we prevent
-	 * the Endpoint from advertising L1.2 support by clearing the L1.2 bits
-	 * in the L1 PM Substates Capabilities register. This ensures the host
-	 * will not attempt to enter L1.2 state with this Endpoint.
-	 */
-	if (pcie->of_data->disable_l1_2 &&
-	    pcie->of_data->mode == DW_PCIE_EP_TYPE) {
+	if (pcie->ras_des_cap) {
+		/* Enable ASPM counters */
+		val = FIELD_PREP(EVENT_COUNTER_ENABLE_MASK,
+				 EVENT_COUNTER_ENABLE_ALL);
+		val |= FIELD_PREP(EVENT_COUNTER_GROUP_SEL_MASK,
+				  EVENT_COUNTER_GROUP_5);
+		dw_pcie_writel_dbi(pci, pcie->ras_des_cap +
+				   RAS_DES_EVENT_COUNTER_CONTROL, val);
+	}
+
+	if (l1ss) {
+		/* Program T_cmrt and T_pwr_on values */
 		val = dw_pcie_readl_dbi(pci, l1ss + PCI_L1SS_CAP);
-		val &= ~(PCI_L1SS_CAP_PCIPM_L1_2 | PCI_L1SS_CAP_ASPM_L1_2);
+		FIELD_MODIFY(PCI_L1SS_CAP_CM_RESTORE_TIME, &val,
+			     pcie->aspm_cmrt);
+		FIELD_MODIFY(PCI_L1SS_CAP_P_PWR_ON_VALUE, &val,
+			     pcie->aspm_pwr_on_t);
 		dw_pcie_writel_dbi(pci, l1ss + PCI_L1SS_CAP, val);
+
+		if (pcie->supports_clkreq)
+			pci->l1ss_support = true;
+
+		/*
+		 * Disable L1.2 capability advertisement for Tegra234 Endpoint
+		 * mode. Tegra234 has a hardware bug where during L1.2 exit,
+		 * the UPHY PLL is powered up immediately without waiting for
+		 * REFCLK to stabilize. This causes the PLL to fail to lock to
+		 * the correct frequency, resulting in PCIe link loss. Since
+		 * there is no hardware fix available, prevent the Endpoint
+		 * from advertising L1.2 support by clearing the L1.2 bits in
+		 * the L1 PM Substates Capabilities register. This ensures the
+		 * host will not attempt to enter L1.2 with this Endpoint.
+		 */
+		if (pcie->of_data->disable_l1_2 &&
+		    pcie->of_data->mode == DW_PCIE_EP_TYPE) {
+			val = dw_pcie_readl_dbi(pci, l1ss + PCI_L1SS_CAP);
+			val &= ~(PCI_L1SS_CAP_PCIPM_L1_2 |
+				 PCI_L1SS_CAP_ASPM_L1_2);
+			dw_pcie_writel_dbi(pci, l1ss + PCI_L1SS_CAP, val);
+		}
 	}
 
 	/* Program L0s and L1 entrance latencies */
@@ -727,8 +736,9 @@ static void init_debugfs(struct tegra_pcie_dw *pcie)
 
 	pcie->debugfs = debugfs_create_dir(name, NULL);
 
-	debugfs_create_devm_seqfile(dev, "aspm_state_cnt", pcie->debugfs,
-				    aspm_state_cnt);
+	if (pcie->ras_des_cap)
+		debugfs_create_devm_seqfile(dev, "aspm_state_cnt", pcie->debugfs,
+					    aspm_state_cnt);
 }
 #else
 static inline void init_host_aspm(struct tegra_pcie_dw *pcie) { return; }
-- 
2.34.1


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

* [PATCH v2 07/10] PCI: tegra194: Always disable Tegra234 Endpoint L1.2
  2026-10-21  6:13 [PATCH v2 00/10] PCI: tegra194: Fix EP and Root Port corner cases Manikanta Maddireddy
                   ` (5 preceding siblings ...)
  2026-10-21  6:13 ` [PATCH v2 06/10] PCI: tegra194: Check for L1SS " Manikanta Maddireddy
@ 2026-10-21  6:13 ` Manikanta Maddireddy
  2026-10-21 15:32   ` Frank Li
  2026-10-21  6:13 ` [PATCH v2 08/10] PCI: tegra194: Guard Endpoint PLL-off error path Manikanta Maddireddy
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 21+ messages in thread
From: Manikanta Maddireddy @ 2026-10-21  6:13 UTC (permalink / raw)
  To: lpieralisi, kwilczynski, mani, bhelgaas, linux-pci
  Cc: robh, thierry.reding, jonathanh, kishon, Frank.Li, vidyas,
	cassel, den, marco.crivellari, andriy.shevchenko, linux-tegra,
	linux-kernel, mmaddireddy

Tegra234 Endpoint mode must not advertise L1.2 because exiting L1.2 can
bring the link down. That hardware workaround is required regardless of
whether the endpoint kernel is built with CONFIG_PCIEASPM.

Move the L1.2 capability masking out of init_host_aspm(), which is compiled
out when CONFIG_PCIEASPM is disabled, and apply it from the common
initialization paths.

Fixes: f59df1d9e6bd ("PCI: tegra194: Disable L1.2 capability of Tegra234 EP")
Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
---
Changes V1 -> V2: None

 drivers/pci/controller/dwc/pcie-tegra194.c | 47 +++++++++++++---------
 1 file changed, 28 insertions(+), 19 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
index 7c349478556d..0e6224b6751d 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -611,6 +611,33 @@ static struct pci_ops tegra_pci_ops = {
 	.write = tegra_pcie_dw_wr_own_conf,
 };
 
+/*
+ * Disable L1.2 capability advertisement for Tegra234 Endpoint mode.
+ * Tegra234 has a hardware bug where during L1.2 exit, the UPHY PLL is
+ * powered up immediately without waiting for REFCLK to stabilize. This causes
+ * the PLL to fail to lock to the correct frequency, resulting in PCIe link
+ * loss. Since there is no hardware fix available, prevent the Endpoint from
+ * advertising L1.2 support so the host will not attempt to enter L1.2 with
+ * this Endpoint.
+ */
+static void tegra_pcie_disable_ep_l1_2(struct tegra_pcie_dw *pcie)
+{
+	struct dw_pcie *pci = &pcie->pci;
+	u32 l1ss, val;
+
+	if (!pcie->of_data->disable_l1_2 ||
+	    pcie->of_data->mode != DW_PCIE_EP_TYPE)
+		return;
+
+	l1ss = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_L1SS);
+	if (!l1ss)
+		return;
+
+	val = dw_pcie_readl_dbi(pci, l1ss + PCI_L1SS_CAP);
+	val &= ~(PCI_L1SS_CAP_PCIPM_L1_2 | PCI_L1SS_CAP_ASPM_L1_2);
+	dw_pcie_writel_dbi(pci, l1ss + PCI_L1SS_CAP, val);
+}
+
 #if defined(CONFIG_PCIEASPM)
 static inline u32 event_counter_prog(struct tegra_pcie_dw *pcie, u32 event)
 {
@@ -694,25 +721,6 @@ static void init_host_aspm(struct tegra_pcie_dw *pcie)
 
 		if (pcie->supports_clkreq)
 			pci->l1ss_support = true;
-
-		/*
-		 * Disable L1.2 capability advertisement for Tegra234 Endpoint
-		 * mode. Tegra234 has a hardware bug where during L1.2 exit,
-		 * the UPHY PLL is powered up immediately without waiting for
-		 * REFCLK to stabilize. This causes the PLL to fail to lock to
-		 * the correct frequency, resulting in PCIe link loss. Since
-		 * there is no hardware fix available, prevent the Endpoint
-		 * from advertising L1.2 support by clearing the L1.2 bits in
-		 * the L1 PM Substates Capabilities register. This ensures the
-		 * host will not attempt to enter L1.2 with this Endpoint.
-		 */
-		if (pcie->of_data->disable_l1_2 &&
-		    pcie->of_data->mode == DW_PCIE_EP_TYPE) {
-			val = dw_pcie_readl_dbi(pci, l1ss + PCI_L1SS_CAP);
-			val &= ~(PCI_L1SS_CAP_PCIPM_L1_2 |
-				 PCI_L1SS_CAP_ASPM_L1_2);
-			dw_pcie_writel_dbi(pci, l1ss + PCI_L1SS_CAP, val);
-		}
 	}
 
 	/* Program L0s and L1 entrance latencies */
@@ -1903,6 +1911,7 @@ static void pex_ep_event_pex_rst_deassert(struct tegra_pcie_dw *pcie)
 	config_gen3_gen4_eq_presets(pcie);
 
 	init_host_aspm(pcie);
+	tegra_pcie_disable_ep_l1_2(pcie);
 
 	if (!pcie->of_data->has_l1ss_exit_fix) {
 		val = dw_pcie_readl_dbi(pci, GEN3_CTRL);
-- 
2.34.1


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

* [PATCH v2 08/10] PCI: tegra194: Guard Endpoint PLL-off error path
  2026-10-21  6:13 [PATCH v2 00/10] PCI: tegra194: Fix EP and Root Port corner cases Manikanta Maddireddy
                   ` (6 preceding siblings ...)
  2026-10-21  6:13 ` [PATCH v2 07/10] PCI: tegra194: Always disable Tegra234 Endpoint L1.2 Manikanta Maddireddy
@ 2026-10-21  6:13 ` Manikanta Maddireddy
  2026-10-21 15:36   ` Frank Li
  2026-10-21  6:13 ` [PATCH v2 09/10] PCI: tegra194: Balance core monitor clock on failures Manikanta Maddireddy
  2026-10-21  6:13 ` [PATCH v2 10/10] PCI: tegra194: Reject zero MSI interrupt number Manikanta Maddireddy
  9 siblings, 1 reply; 21+ messages in thread
From: Manikanta Maddireddy @ 2026-10-21  6:13 UTC (permalink / raw)
  To: lpieralisi, kwilczynski, mani, bhelgaas, linux-pci
  Cc: robh, thierry.reding, jonathanh, kishon, Frank.Li, vidyas,
	cassel, den, marco.crivellari, andriy.shevchenko, linux-tegra,
	linux-kernel, mmaddireddy

The Endpoint PERST# deassert path initializes the external-refclk PLL only
when enable_ext_refclk is set, but the error unwind always sent the PLL-off
request.

Guard the PLL-off request with enable_ext_refclk so Tegra234 Endpoint
configurations that did not enable the PLL do not send a spurious BPMP
PLL-off command.

Fixes: a54e19073718 ("PCI: tegra194: Add Tegra234 PCIe support")
Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
---
Changes V1 -> V2: None

 drivers/pci/controller/dwc/pcie-tegra194.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
index 0e6224b6751d..de14a23f9a4d 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -1973,7 +1973,8 @@ static void pex_ep_event_pex_rst_deassert(struct tegra_pcie_dw *pcie)
 fail_core_apb_rst:
 	clk_disable_unprepare(pcie->core_clk);
 fail_core_clk_enable:
-	tegra_pcie_bpmp_set_pll_state(pcie, false);
+	if (pcie->enable_ext_refclk)
+		tegra_pcie_bpmp_set_pll_state(pcie, false);
 fail_pll_init:
 	tegra_pcie_bpmp_set_ctrl_state(pcie, false);
 fail_set_ctrl_state:
-- 
2.34.1


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

* [PATCH v2 09/10] PCI: tegra194: Balance core monitor clock on failures
  2026-10-21  6:13 [PATCH v2 00/10] PCI: tegra194: Fix EP and Root Port corner cases Manikanta Maddireddy
                   ` (7 preceding siblings ...)
  2026-10-21  6:13 ` [PATCH v2 08/10] PCI: tegra194: Guard Endpoint PLL-off error path Manikanta Maddireddy
@ 2026-10-21  6:13 ` Manikanta Maddireddy
  2026-10-21 15:43   ` Frank Li
  2026-10-21  6:13 ` [PATCH v2 10/10] PCI: tegra194: Reject zero MSI interrupt number Manikanta Maddireddy
  9 siblings, 1 reply; 21+ messages in thread
From: Manikanta Maddireddy @ 2026-10-21  6:13 UTC (permalink / raw)
  To: lpieralisi, kwilczynski, mani, bhelgaas, linux-pci
  Cc: robh, thierry.reding, jonathanh, kishon, Frank.Li, vidyas,
	cassel, den, marco.crivellari, andriy.shevchenko, linux-tegra,
	linux-kernel, mmaddireddy

tegra_pcie_dw_host_init() enables core_clk_m, but failure paths that leave
after the host init callback can unconfigure the controller without
disabling that clock. The enable error is also only logged, so later
cleanup can try to disable a clock that was never enabled.

Track the monitor clock state, return enable failures, and use a common
helper on retry, remove, suspend, shutdown and host-init failure paths so
the clock is disabled exactly when it was enabled.

Fixes: a86ca8698c88 ("PCI: tegra194: Add core monitor clock support")
Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
---
Changes V1 -> V2: None

 drivers/pci/controller/dwc/pcie-tegra194.c | 33 ++++++++++++++++++----
 1 file changed, 27 insertions(+), 6 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
index de14a23f9a4d..632ecab3c8ea 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -246,6 +246,7 @@ struct tegra_pcie_dw {
 	void __iomem *appl_base;
 	struct clk *core_clk;
 	struct clk *core_clk_m;
+	bool core_clk_m_enabled;
 	struct reset_control *core_apb_rst;
 	struct reset_control *core_rst;
 	struct dw_pcie pci;
@@ -855,6 +856,15 @@ static void tegra_pcie_enable_interrupts(struct dw_pcie_rp *pp)
 		tegra_pcie_enable_msi_interrupts(pp);
 }
 
+static void tegra_pcie_disable_core_clk_m(struct tegra_pcie_dw *pcie)
+{
+	if (!pcie->core_clk_m_enabled)
+		return;
+
+	clk_disable_unprepare(pcie->core_clk_m);
+	pcie->core_clk_m_enabled = false;
+}
+
 static void config_gen3_gen4_eq_presets(struct tegra_pcie_dw *pcie)
 {
 	struct dw_pcie *pci = &pcie->pci;
@@ -914,6 +924,7 @@ static int tegra_pcie_dw_host_init(struct dw_pcie_rp *pp)
 	struct tegra_pcie_dw *pcie = to_tegra_pcie(pci);
 	u32 val;
 	u16 val_16;
+	int ret;
 
 	pp->bridge->ops = &tegra_pci_ops;
 
@@ -965,8 +976,12 @@ static int tegra_pcie_dw_host_init(struct dw_pcie_rp *pp)
 	}
 
 	clk_set_rate(pcie->core_clk, GEN4_CORE_CLK_FREQ);
-	if (clk_prepare_enable(pcie->core_clk_m))
-		dev_err(pci->dev, "Failed to enable core monitor clock\n");
+	ret = clk_prepare_enable(pcie->core_clk_m);
+	if (ret) {
+		dev_err(pci->dev, "Failed to enable core monitor clock: %d\n", ret);
+		return ret;
+	}
+	pcie->core_clk_m_enabled = true;
 
 	return 0;
 }
@@ -1049,8 +1064,11 @@ static int tegra_pcie_dw_start_link(struct dw_pcie *pci)
 		 * dw_pcie_host_init(). Disable the clock since below
 		 * tegra_pcie_dw_host_init() will enable it again.
 		 */
-		clk_disable_unprepare(pcie->core_clk_m);
-		tegra_pcie_dw_host_init(pp);
+		tegra_pcie_disable_core_clk_m(pcie);
+		ret = tegra_pcie_dw_host_init(pp);
+		if (ret)
+			return ret;
+
 		dw_pcie_setup_rc(pp);
 
 		retry = false;
@@ -1565,6 +1583,7 @@ static int tegra_pcie_init_controller(struct tegra_pcie_dw *pcie)
 	return 0;
 
 fail_host_init:
+	tegra_pcie_disable_core_clk_m(pcie);
 	tegra_pcie_unconfig_controller(pcie);
 	return ret;
 }
@@ -1653,7 +1672,7 @@ static void tegra_pcie_dw_pme_turnoff(struct tegra_pcie_dw *pcie)
 
 static void tegra_pcie_deinit_controller(struct tegra_pcie_dw *pcie)
 {
-	clk_disable_unprepare(pcie->core_clk_m);
+	tegra_pcie_disable_core_clk_m(pcie);
 	dw_pcie_host_deinit(&pcie->pci.pp);
 	tegra_pcie_dw_pme_turnoff(pcie);
 	tegra_pcie_unconfig_controller(pcie);
@@ -2451,7 +2470,7 @@ static int tegra_pcie_dw_suspend_noirq(struct device *dev)
 	if (!pcie->link_state)
 		return 0;
 
-	clk_disable_unprepare(pcie->core_clk_m);
+	tegra_pcie_disable_core_clk_m(pcie);
 	tegra_pcie_dw_pme_turnoff(pcie);
 	tegra_pcie_unconfig_controller(pcie);
 
@@ -2488,6 +2507,7 @@ static int tegra_pcie_dw_resume_noirq(struct device *dev)
 	return 0;
 
 fail_host_init:
+	tegra_pcie_disable_core_clk_m(pcie);
 	tegra_pcie_unconfig_controller(pcie);
 	return ret;
 }
@@ -2529,6 +2549,7 @@ static void tegra_pcie_dw_shutdown(struct platform_device *pdev)
 		if (IS_ENABLED(CONFIG_PCI_MSI))
 			disable_irq(pcie->pci.pp.msi_irq[0]);
 
+		tegra_pcie_disable_core_clk_m(pcie);
 		tegra_pcie_dw_pme_turnoff(pcie);
 		tegra_pcie_unconfig_controller(pcie);
 		pm_runtime_put_sync(pcie->dev);
-- 
2.34.1


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

* [PATCH v2 10/10] PCI: tegra194: Reject zero MSI interrupt number
  2026-10-21  6:13 [PATCH v2 00/10] PCI: tegra194: Fix EP and Root Port corner cases Manikanta Maddireddy
                   ` (8 preceding siblings ...)
  2026-10-21  6:13 ` [PATCH v2 09/10] PCI: tegra194: Balance core monitor clock on failures Manikanta Maddireddy
@ 2026-10-21  6:13 ` Manikanta Maddireddy
  2026-10-21 15:44   ` Frank Li
  9 siblings, 1 reply; 21+ messages in thread
From: Manikanta Maddireddy @ 2026-10-21  6:13 UTC (permalink / raw)
  To: lpieralisi, kwilczynski, mani, bhelgaas, linux-pci
  Cc: robh, thierry.reding, jonathanh, kishon, Frank.Li, vidyas,
	cassel, den, marco.crivellari, andriy.shevchenko, linux-tegra,
	linux-kernel, mmaddireddy

Reject interrupt number zero before computing BIT(irq - 1). The endpoint
IRQ API uses interrupt numbers in the range 1-N, and existing EPF drivers
already follow that convention. This is defensive validation rather than
a correction to the MSI numbering used by those drivers.

Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
---
Changes V1 -> V2:
- Retain only MSI interrupt-number-zero validation from v1 patch 10.
- Rewrite the title and commit message around defensive MSI validation,
  and remove the Fixes tag.

 drivers/pci/controller/dwc/pcie-tegra194.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
index 632ecab3c8ea..0f49ea6df8bc 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -2026,7 +2026,7 @@ static int tegra_pcie_ep_raise_intx_irq(struct tegra_pcie_dw *pcie, u16 irq)
 
 static int tegra_pcie_ep_raise_msi_irq(struct tegra_pcie_dw *pcie, u16 irq)
 {
-	if (unlikely(irq > 32))
+	if (unlikely(!irq || irq > 32))
 		return -EINVAL;
 
 	appl_writel(pcie, BIT(irq - 1), APPL_MSI_CTRL_1);
-- 
2.34.1


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

* Re: [PATCH v2 01/10] PCI: tegra194: Propagate REFCLK select GPIO errors
  2026-10-21  6:13 ` [PATCH v2 01/10] PCI: tegra194: Propagate REFCLK select GPIO errors Manikanta Maddireddy
@ 2026-10-21 15:14   ` Frank Li
  0 siblings, 0 replies; 21+ messages in thread
From: Frank Li @ 2026-10-21 15:14 UTC (permalink / raw)
  To: Manikanta Maddireddy
  Cc: lpieralisi, kwilczynski, mani, bhelgaas, linux-pci, robh,
	thierry.reding, jonathanh, kishon, Frank.Li, vidyas, cassel, den,
	marco.crivellari, andriy.shevchenko, linux-tegra, linux-kernel

On Wed, Oct 21, 2026 at 11:43:40AM +0530, Manikanta Maddireddy wrote:
> devm_gpiod_get_optional() returns NULL only when the optional GPIO is
> absent. Other error pointers, including -EPROBE_DEFER, describe real
> failures and should not be converted to NULL.
>
> Return dev_err_probe() errors for nvidia,refclk-select so probe does not
> continue without a GPIO that exists but is not ready or could not be
> requested.
>
> Fixes: c57247f940e8 ("PCI: tegra: Add support for PCIe endpoint mode in Tegra194")
> Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

> Changes V1 -> V2: None
>
>  drivers/pci/controller/dwc/pcie-tegra194.c | 15 +++------------
>  1 file changed, 3 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
> index 9b349b3430f1..6104a22d930e 100644
> --- a/drivers/pci/controller/dwc/pcie-tegra194.c
> +++ b/drivers/pci/controller/dwc/pcie-tegra194.c
> @@ -1206,18 +1206,9 @@ static int tegra_pcie_dw_parse_dt(struct tegra_pcie_dw *pcie)
>  	pcie->pex_refclk_sel_gpiod = devm_gpiod_get_optional(pcie->dev,
>  							     "nvidia,refclk-select",
>  							     GPIOD_OUT_HIGH);
> -	if (IS_ERR(pcie->pex_refclk_sel_gpiod)) {
> -		int err = PTR_ERR(pcie->pex_refclk_sel_gpiod);
> -		const char *level = KERN_ERR;
> -
> -		if (err == -EPROBE_DEFER)
> -			level = KERN_DEBUG;
> -
> -		dev_printk(level, pcie->dev,
> -			   dev_fmt("Failed to get REFCLK select GPIOs: %d\n"),
> -			   err);
> -		pcie->pex_refclk_sel_gpiod = NULL;
> -	}
> +	if (IS_ERR(pcie->pex_refclk_sel_gpiod))
> +		return dev_err_probe(pcie->dev, PTR_ERR(pcie->pex_refclk_sel_gpiod),
> +				     "Failed to get REFCLK select GPIO\n");
>
>  	return 0;
>  }
> --
> 2.34.1
>

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

* Re: [PATCH v2 02/10] PCI: tegra194: Check core reset deassertion
  2026-10-21  6:13 ` [PATCH v2 02/10] PCI: tegra194: Check core reset deassertion Manikanta Maddireddy
@ 2026-10-21 15:16   ` Frank Li
  0 siblings, 0 replies; 21+ messages in thread
From: Frank Li @ 2026-10-21 15:16 UTC (permalink / raw)
  To: Manikanta Maddireddy
  Cc: lpieralisi, kwilczynski, mani, bhelgaas, linux-pci, robh,
	thierry.reding, jonathanh, kishon, Frank.Li, vidyas, cassel, den,
	marco.crivellari, andriy.shevchenko, linux-tegra, linux-kernel

On Wed, Oct 21, 2026 at 11:43:41AM +0530, Manikanta Maddireddy wrote:
> Several paths access DBI registers after deasserting the controller core
> reset. If reset_control_deassert() fails, those DBI accesses can trigger a
> CBB timeout, or setup can return success with the core still in reset.
>
> Check core reset deassertion in Root Port setup, the DLF retry path and the
> Endpoint PERST# deassert path. Unwind before DBI access when deassertion
> fails.
>
> Fixes: 56e15a238d92 ("PCI: tegra: Add Tegra194 PCIe support")
> Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

> Changes V1 -> V2: None
>
>  drivers/pci/controller/dwc/pcie-tegra194.c | 23 +++++++++++++++++++---
>  1 file changed, 20 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
> index 6104a22d930e..89dbef83dd9e 100644
> --- a/drivers/pci/controller/dwc/pcie-tegra194.c
> +++ b/drivers/pci/controller/dwc/pcie-tegra194.c
> @@ -954,6 +954,7 @@ static int tegra_pcie_dw_start_link(struct dw_pcie *pci)
>  	struct tegra_pcie_dw *pcie = to_tegra_pcie(pci);
>  	struct dw_pcie_rp *pp = &pci->pp;
>  	u32 val, offset, tmp;
> +	int ret;
>  	bool retry = true;
>
>  	if (pcie->of_data->mode == DW_PCIE_EP_TYPE) {
> @@ -1009,7 +1010,12 @@ static int tegra_pcie_dw_start_link(struct dw_pcie *pci)
>  		appl_writel(pcie, val, APPL_CTRL);
>
>  		reset_control_assert(pcie->core_rst);
> -		reset_control_deassert(pcie->core_rst);
> +		ret = reset_control_deassert(pcie->core_rst);
> +		if (ret) {
> +			dev_err(pci->dev, "Failed to deassert core reset: %d\n",
> +				ret);
> +			return ret;
> +		}
>
>  		offset = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_DLF);
>  		val = dw_pcie_readl_dbi(pci, offset + PCI_DLF_CAP);
> @@ -1455,10 +1461,16 @@ static int tegra_pcie_config_controller(struct tegra_pcie_dw *pcie,
>  		    pcie->atu_dma_res->start & APPL_CFG_IATU_DMA_BASE_ADDR_MASK,
>  		    APPL_CFG_IATU_DMA_BASE_ADDR);
>
> -	reset_control_deassert(pcie->core_rst);
> +	ret = reset_control_deassert(pcie->core_rst);
> +	if (ret) {
> +		dev_err(pcie->dev, "Failed to deassert core reset: %d\n", ret);
> +		goto fail_core_rst;
> +	}
>
>  	return ret;
>
> +fail_core_rst:
> +	tegra_pcie_disable_phy(pcie);
>  fail_phy:
>  	reset_control_assert(pcie->core_apb_rst);
>  fail_core_apb_rst:
> @@ -1853,7 +1865,11 @@ static void pex_ep_event_pex_rst_deassert(struct tegra_pcie_dw *pcie)
>  	      LTR_NOSNOOP_MSG_REQ;
>  	appl_writel(pcie, val, APPL_LTR_MSG_1);
>
> -	reset_control_deassert(pcie->core_rst);
> +	ret = reset_control_deassert(pcie->core_rst);
> +	if (ret) {
> +		dev_err(dev, "Failed to deassert core reset: %d\n", ret);
> +		goto fail_core_rst;
> +	}
>
>  	/* Perform cleanup that requires refclk and core reset deasserted */
>  	pci_epc_deinit_notify(pcie->pci.ep.epc);
> @@ -1927,6 +1943,7 @@ static void pex_ep_event_pex_rst_deassert(struct tegra_pcie_dw *pcie)
>
>  fail_init_complete:
>  	reset_control_assert(pcie->core_rst);
> +fail_core_rst:
>  	tegra_pcie_disable_phy(pcie);
>  fail_phy:
>  	reset_control_assert(pcie->core_apb_rst);
> --
> 2.34.1
>

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

* Re: [PATCH v2 03/10] PCI: tegra194: Fix Endpoint PERST# IRQ suspend race
  2026-10-21  6:13 ` [PATCH v2 03/10] PCI: tegra194: Fix Endpoint PERST# IRQ suspend race Manikanta Maddireddy
@ 2026-10-21 15:19   ` Frank Li
  0 siblings, 0 replies; 21+ messages in thread
From: Frank Li @ 2026-10-21 15:19 UTC (permalink / raw)
  To: Manikanta Maddireddy
  Cc: lpieralisi, kwilczynski, mani, bhelgaas, linux-pci, robh,
	thierry.reding, jonathanh, kishon, Frank.Li, vidyas, cassel, den,
	marco.crivellari, andriy.shevchenko, linux-tegra, linux-kernel

On Wed, Oct 21, 2026 at 11:43:42AM +0530, Manikanta Maddireddy wrote:
> Endpoint system suspend is allowed only while the endpoint is disabled.
> Checking ep_state before disabling the PERST# IRQ leaves a window in which
> PERST# deassertion starts the threaded handler after the check. The
> handler can enable the controller, clocks and PHYs before disable_irq()
> returns, but suspend still succeeds based on the earlier disabled state.
> The system then proceeds into suspend with an active endpoint that should
> have caused the suspend callback to reject the transition.
>
> Disable the PERST# IRQ before checking ep_state. disable_irq() waits for
> an already-running threaded handler to finish, so the state check sees
> its completed transition and no new handler can enable the endpoint.
> Re-enable the IRQ immediately if the endpoint is enabled and reject
> suspend. Otherwise, keep it disabled until the normal resume callback.
> This also balances the IRQ disable when another device aborts suspend
> and PM rolls back through .resume without calling .resume_early.
>
> This preserves the existing policy that PERST# is not serviced while the
> endpoint is suspended. It serializes the software state check with the
> IRQ thread; it does not make PERST# a wakeup source or guarantee delivery
> of transitions during suspension.
>
> Wrap the PM ops pointer with pm_sleep_ptr() so the callbacks are used
> only when system sleep is enabled.
>
> Fixes: c76f8eae7d46 ("PCI: tegra194: Allow system suspend when the Endpoint link is not up")
> Link: https://lore.kernel.org/r/20260324190755.1094879-10-mmaddireddy@nvidia.com
> Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

> Changes V1 -> V2:
> - Expand the commit message to explain the active-endpoint suspend race,
>   IRQ-thread synchronization and suspend rollback handling.
> - Clarify that PERST# is not serviced while the endpoint is suspended.
> - Add a comment explaining why the IRQ thread is drained before checking
>   endpoint state.
>
>  drivers/pci/controller/dwc/pcie-tegra194.c | 34 ++++++++++++++--------
>  1 file changed, 22 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
> index 89dbef83dd9e..0f895c766a71 100644
> --- a/drivers/pci/controller/dwc/pcie-tegra194.c
> +++ b/drivers/pci/controller/dwc/pcie-tegra194.c
> @@ -2374,19 +2374,30 @@ static int tegra_pcie_dw_suspend(struct device *dev)
>  {
>  	struct tegra_pcie_dw *pcie = dev_get_drvdata(dev);
>
> -	if (pcie->of_data->mode == DW_PCIE_EP_TYPE) {
> -		if (pcie->ep_state == EP_STATE_ENABLED) {
> -			dev_err(dev, "Tegra PCIe is in EP mode, suspend not allowed\n");
> -			return -EPERM;
> -		}
> -
> -		disable_irq(pcie->pex_rst_irq);
> +	if (pcie->of_data->mode != DW_PCIE_EP_TYPE)
>  		return 0;
> +
> +	/* Drain the PERST# thread before checking whether the endpoint is idle. */
> +	disable_irq(pcie->pex_rst_irq);
> +	if (pcie->ep_state == EP_STATE_ENABLED) {
> +		enable_irq(pcie->pex_rst_irq);
> +		dev_err(dev, "Tegra PCIe is in EP mode, suspend not allowed\n");
> +		return -EPERM;
>  	}
>
>  	return 0;
>  }
>
> +static int tegra_pcie_dw_resume(struct device *dev)
> +{
> +	struct tegra_pcie_dw *pcie = dev_get_drvdata(dev);
> +
> +	if (pcie->of_data->mode == DW_PCIE_EP_TYPE)
> +		enable_irq(pcie->pex_rst_irq);
> +
> +	return 0;
> +}
> +
>  static int tegra_pcie_dw_suspend_late(struct device *dev)
>  {
>  	struct tegra_pcie_dw *pcie = dev_get_drvdata(dev);
> @@ -2462,10 +2473,8 @@ static int tegra_pcie_dw_resume_early(struct device *dev)
>  	struct tegra_pcie_dw *pcie = dev_get_drvdata(dev);
>  	u32 val;
>
> -	if (pcie->of_data->mode == DW_PCIE_EP_TYPE) {
> -		enable_irq(pcie->pex_rst_irq);
> +	if (pcie->of_data->mode == DW_PCIE_EP_TYPE)
>  		return 0;
> -	}
>
>  	if (!pcie->link_state)
>  		return 0;
> @@ -2569,10 +2578,11 @@ static const struct of_device_id tegra_pcie_dw_of_match[] = {
>
>  static const struct dev_pm_ops tegra_pcie_dw_pm_ops = {
>  	.suspend = tegra_pcie_dw_suspend,
> +	.resume = tegra_pcie_dw_resume,
>  	.suspend_late = tegra_pcie_dw_suspend_late,
> +	.resume_early = tegra_pcie_dw_resume_early,
>  	.suspend_noirq = tegra_pcie_dw_suspend_noirq,
>  	.resume_noirq = tegra_pcie_dw_resume_noirq,
> -	.resume_early = tegra_pcie_dw_resume_early,
>  };
>
>  static struct platform_driver tegra_pcie_dw_driver = {
> @@ -2581,7 +2591,7 @@ static struct platform_driver tegra_pcie_dw_driver = {
>  	.shutdown = tegra_pcie_dw_shutdown,
>  	.driver = {
>  		.name	= "tegra194-pcie",
> -		.pm = &tegra_pcie_dw_pm_ops,
> +		.pm = pm_sleep_ptr(&tegra_pcie_dw_pm_ops),
>  		.of_match_table = tegra_pcie_dw_of_match,
>  	},
>  };
> --
> 2.34.1
>

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

* Re: [PATCH v2 04/10] PCI: tegra194: Do not skip no-link Root Port remove cleanup
  2026-10-21  6:13 ` [PATCH v2 04/10] PCI: tegra194: Do not skip no-link Root Port remove cleanup Manikanta Maddireddy
@ 2026-10-21 15:22   ` Frank Li
  0 siblings, 0 replies; 21+ messages in thread
From: Frank Li @ 2026-10-21 15:22 UTC (permalink / raw)
  To: Manikanta Maddireddy
  Cc: lpieralisi, kwilczynski, mani, bhelgaas, linux-pci, robh,
	thierry.reding, jonathanh, kishon, Frank.Li, vidyas, cassel, den,
	marco.crivellari, andriy.shevchenko, linux-tegra, linux-kernel

On Wed, Oct 21, 2026 at 11:43:43AM +0530, Manikanta Maddireddy wrote:
> tegra_pcie_config_rp() deinitializes the controller and disables runtime PM
> when link training fails, then probe treats -ENOMEDIUM as success so the
> driver can remain bound without a link.
>
> remove() returned immediately when the Root Port link was down. That skips
> common cleanup such as tegra_bpmp_put() and deasserting the refclk-select
> GPIO. Keep link-dependent controller teardown conditional, but always run
> common remove cleanup.
>
> Fixes: 56e15a238d92 ("PCI: tegra: Add Tegra194 PCIe support")
> Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

> Changes V1 -> V2: None
>
>  drivers/pci/controller/dwc/pcie-tegra194.c | 14 +++++++-------
>  1 file changed, 7 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
> index 0f895c766a71..fb8084cef38b 100644
> --- a/drivers/pci/controller/dwc/pcie-tegra194.c
> +++ b/drivers/pci/controller/dwc/pcie-tegra194.c
> @@ -2352,19 +2352,19 @@ static void tegra_pcie_dw_remove(struct platform_device *pdev)
>  	struct dw_pcie_ep *ep = &pcie->pci.ep;
>
>  	if (pcie->of_data->mode == DW_PCIE_RC_TYPE) {
> -		if (!pcie->link_state)
> -			return;
> -
> -		debugfs_remove_recursive(pcie->debugfs);
> -		tegra_pcie_deinit_controller(pcie);
> -		pm_runtime_put_sync(pcie->dev);
> +		if (pcie->link_state) {
> +			debugfs_remove_recursive(pcie->debugfs);
> +			tegra_pcie_deinit_controller(pcie);
> +			pm_runtime_put_sync(pcie->dev);
> +			pm_runtime_disable(pcie->dev);
> +		}
>  	} else {
>  		disable_irq(pcie->pex_rst_irq);
>  		pex_ep_event_pex_rst_assert(pcie);
>  		dw_pcie_ep_deinit(ep);
> +		pm_runtime_disable(pcie->dev);
>  	}
>
> -	pm_runtime_disable(pcie->dev);
>  	tegra_bpmp_put(pcie->bpmp);
>  	if (pcie->pex_refclk_sel_gpiod)
>  		gpiod_set_value(pcie->pex_refclk_sel_gpiod, 0);
> --
> 2.34.1
>

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

* Re: [PATCH v2 05/10] PCI: tegra194: Check for 16 GT/s capability before programming
  2026-10-21  6:13 ` [PATCH v2 05/10] PCI: tegra194: Check for 16 GT/s capability before programming Manikanta Maddireddy
@ 2026-10-21 15:24   ` Frank Li
  0 siblings, 0 replies; 21+ messages in thread
From: Frank Li @ 2026-10-21 15:24 UTC (permalink / raw)
  To: Manikanta Maddireddy
  Cc: lpieralisi, kwilczynski, mani, bhelgaas, linux-pci, robh,
	thierry.reding, jonathanh, kishon, Frank.Li, vidyas, cassel, den,
	marco.crivellari, andriy.shevchenko, linux-tegra, linux-kernel

On Wed, Oct 21, 2026 at 11:43:44AM +0530, Manikanta Maddireddy wrote:
> config_gen3_gen4_eq_presets() added PCI_PL_16GT_LE_CTRL to the result of
> dw_pcie_find_ext_capability() without checking whether the 16 GT/s
> capability exists. If the capability is absent, the code writes lane
> presets at an unrelated configuration offset.
>
> Look up the capability once before the lane loop and skip the 16 GT/s lane
> equivalent control programming when it is absent.
>
> Fixes: 56e15a238d92 ("PCI: tegra: Add Tegra194 PCIe support")
> Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

> Changes V1 -> V2: None
>
>  drivers/pci/controller/dwc/pcie-tegra194.c | 16 ++++++++++------
>  1 file changed, 10 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
> index fb8084cef38b..14031cfaee8b 100644
> --- a/drivers/pci/controller/dwc/pcie-tegra194.c
> +++ b/drivers/pci/controller/dwc/pcie-tegra194.c
> @@ -840,7 +840,11 @@ static void tegra_pcie_enable_interrupts(struct dw_pcie_rp *pp)
>  static void config_gen3_gen4_eq_presets(struct tegra_pcie_dw *pcie)
>  {
>  	struct dw_pcie *pci = &pcie->pci;
> -	u32 val, offset, i;
> +	u32 pl16g, val, i;
> +
> +	pl16g = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_PL_16GT);
> +	if (pl16g)
> +		pl16g += PCI_PL_16GT_LE_CTRL;
>
>  	/* Program init preset */
>  	for (i = 0; i < pcie->num_lanes; i++) {
> @@ -851,15 +855,15 @@ static void config_gen3_gen4_eq_presets(struct tegra_pcie_dw *pcie)
>  			     GEN3_GEN4_EQ_PRESET_INIT);
>  		dw_pcie_writew_dbi(pci, CAP_SPCIE_CAP_OFF + (i * 2), val);
>
> -		offset = dw_pcie_find_ext_capability(pci,
> -						     PCI_EXT_CAP_ID_PL_16GT) +
> -				PCI_PL_16GT_LE_CTRL;
> -		val = dw_pcie_readb_dbi(pci, offset + i);
> +		if (!pl16g)
> +			continue;
> +
> +		val = dw_pcie_readb_dbi(pci, pl16g + i);
>  		FIELD_MODIFY(PCI_PL_16GT_LE_CTRL_DSP_TX_PRESET_MASK, &val,
>  			     GEN3_GEN4_EQ_PRESET_INIT);
>  		FIELD_MODIFY(PCI_PL_16GT_LE_CTRL_USP_TX_PRESET_MASK, &val,
>  			     GEN3_GEN4_EQ_PRESET_INIT);
> -		dw_pcie_writeb_dbi(pci, offset + i, val);
> +		dw_pcie_writeb_dbi(pci, pl16g + i, val);
>  	}
>
>  	val = dw_pcie_readl_dbi(pci, GEN3_CTRL);
> --
> 2.34.1
>

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

* Re: [PATCH v2 06/10] PCI: tegra194: Check for L1SS capability before programming
  2026-10-21  6:13 ` [PATCH v2 06/10] PCI: tegra194: Check for L1SS " Manikanta Maddireddy
@ 2026-10-21 15:28   ` Frank Li
  0 siblings, 0 replies; 21+ messages in thread
From: Frank Li @ 2026-10-21 15:28 UTC (permalink / raw)
  To: Manikanta Maddireddy
  Cc: lpieralisi, kwilczynski, mani, bhelgaas, linux-pci, robh,
	thierry.reding, jonathanh, kishon, Frank.Li, vidyas, cassel, den,
	marco.crivellari, andriy.shevchenko, linux-tegra, linux-kernel

On Wed, Oct 21, 2026 at 11:43:45AM +0530, Manikanta Maddireddy wrote:
> init_host_aspm() programs the L1 PM Substates capability without checking
> whether the controller advertises it. If the capability is absent, the
> code writes offsets from zero instead of L1SS registers.
>
> Check for the L1SS capability before programming L1SS-specific fields.
> Keep RAS-DES discovery, ASPM counter enablement and AFR latency
> programming outside that guard because they do not depend on L1SS.
> Only create the ASPM counter debugfs file when the RAS-DES capability is
> present.
>
> Fixes: 56e15a238d92 ("PCI: tegra: Add Tegra194 PCIe support")
> Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

> Changes V1 -> V2:
> - Use RAS_DES_EVENT_COUNTER_CONTROL to match the preceding DWC register
>   renames. No functional changes.
>
>  drivers/pci/controller/dwc/pcie-tegra194.c | 72 ++++++++++++----------
>  1 file changed, 41 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
> index 14031cfaee8b..7c349478556d 100644
> --- a/drivers/pci/controller/dwc/pcie-tegra194.c
> +++ b/drivers/pci/controller/dwc/pcie-tegra194.c
> @@ -673,37 +673,46 @@ static void init_host_aspm(struct tegra_pcie_dw *pcie)
>
>  	pcie->ras_des_cap = dw_pcie_find_ext_capability(&pcie->pci,
>  							PCI_EXT_CAP_ID_VNDR);
> -
> -	/* Enable ASPM counters */
> -	val = FIELD_PREP(EVENT_COUNTER_ENABLE_MASK, EVENT_COUNTER_ENABLE_ALL);
> -	val |= FIELD_PREP(EVENT_COUNTER_GROUP_SEL_MASK, EVENT_COUNTER_GROUP_5);
> -	dw_pcie_writel_dbi(pci, pcie->ras_des_cap +
> -			   RAS_DES_EVENT_COUNTER_CONTROL, val);
> -
> -	/* Program T_cmrt and T_pwr_on values */
> -	val = dw_pcie_readl_dbi(pci, l1ss + PCI_L1SS_CAP);
> -	FIELD_MODIFY(PCI_L1SS_CAP_CM_RESTORE_TIME, &val, pcie->aspm_cmrt);
> -	FIELD_MODIFY(PCI_L1SS_CAP_P_PWR_ON_VALUE, &val, pcie->aspm_pwr_on_t);
> -	dw_pcie_writel_dbi(pci, l1ss + PCI_L1SS_CAP, val);
> -
> -	if (pcie->supports_clkreq)
> -		pci->l1ss_support = true;
> -
> -	/*
> -	 * Disable L1.2 capability advertisement for Tegra234 Endpoint mode.
> -	 * Tegra234 has a hardware bug where during L1.2 exit, the UPHY PLL is
> -	 * powered up immediately without waiting for REFCLK to stabilize. This
> -	 * causes the PLL to fail to lock to the correct frequency, resulting in
> -	 * PCIe link loss. Since there is no hardware fix available, we prevent
> -	 * the Endpoint from advertising L1.2 support by clearing the L1.2 bits
> -	 * in the L1 PM Substates Capabilities register. This ensures the host
> -	 * will not attempt to enter L1.2 state with this Endpoint.
> -	 */
> -	if (pcie->of_data->disable_l1_2 &&
> -	    pcie->of_data->mode == DW_PCIE_EP_TYPE) {
> +	if (pcie->ras_des_cap) {
> +		/* Enable ASPM counters */
> +		val = FIELD_PREP(EVENT_COUNTER_ENABLE_MASK,
> +				 EVENT_COUNTER_ENABLE_ALL);
> +		val |= FIELD_PREP(EVENT_COUNTER_GROUP_SEL_MASK,
> +				  EVENT_COUNTER_GROUP_5);
> +		dw_pcie_writel_dbi(pci, pcie->ras_des_cap +
> +				   RAS_DES_EVENT_COUNTER_CONTROL, val);
> +	}
> +
> +	if (l1ss) {
> +		/* Program T_cmrt and T_pwr_on values */
>  		val = dw_pcie_readl_dbi(pci, l1ss + PCI_L1SS_CAP);
> -		val &= ~(PCI_L1SS_CAP_PCIPM_L1_2 | PCI_L1SS_CAP_ASPM_L1_2);
> +		FIELD_MODIFY(PCI_L1SS_CAP_CM_RESTORE_TIME, &val,
> +			     pcie->aspm_cmrt);
> +		FIELD_MODIFY(PCI_L1SS_CAP_P_PWR_ON_VALUE, &val,
> +			     pcie->aspm_pwr_on_t);
>  		dw_pcie_writel_dbi(pci, l1ss + PCI_L1SS_CAP, val);
> +
> +		if (pcie->supports_clkreq)
> +			pci->l1ss_support = true;
> +
> +		/*
> +		 * Disable L1.2 capability advertisement for Tegra234 Endpoint
> +		 * mode. Tegra234 has a hardware bug where during L1.2 exit,
> +		 * the UPHY PLL is powered up immediately without waiting for
> +		 * REFCLK to stabilize. This causes the PLL to fail to lock to
> +		 * the correct frequency, resulting in PCIe link loss. Since
> +		 * there is no hardware fix available, prevent the Endpoint
> +		 * from advertising L1.2 support by clearing the L1.2 bits in
> +		 * the L1 PM Substates Capabilities register. This ensures the
> +		 * host will not attempt to enter L1.2 with this Endpoint.
> +		 */
> +		if (pcie->of_data->disable_l1_2 &&
> +		    pcie->of_data->mode == DW_PCIE_EP_TYPE) {
> +			val = dw_pcie_readl_dbi(pci, l1ss + PCI_L1SS_CAP);
> +			val &= ~(PCI_L1SS_CAP_PCIPM_L1_2 |
> +				 PCI_L1SS_CAP_ASPM_L1_2);
> +			dw_pcie_writel_dbi(pci, l1ss + PCI_L1SS_CAP, val);
> +		}
>  	}
>
>  	/* Program L0s and L1 entrance latencies */
> @@ -727,8 +736,9 @@ static void init_debugfs(struct tegra_pcie_dw *pcie)
>
>  	pcie->debugfs = debugfs_create_dir(name, NULL);
>
> -	debugfs_create_devm_seqfile(dev, "aspm_state_cnt", pcie->debugfs,
> -				    aspm_state_cnt);
> +	if (pcie->ras_des_cap)
> +		debugfs_create_devm_seqfile(dev, "aspm_state_cnt", pcie->debugfs,
> +					    aspm_state_cnt);
>  }
>  #else
>  static inline void init_host_aspm(struct tegra_pcie_dw *pcie) { return; }
> --
> 2.34.1
>

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

* Re: [PATCH v2 07/10] PCI: tegra194: Always disable Tegra234 Endpoint L1.2
  2026-10-21  6:13 ` [PATCH v2 07/10] PCI: tegra194: Always disable Tegra234 Endpoint L1.2 Manikanta Maddireddy
@ 2026-10-21 15:32   ` Frank Li
  0 siblings, 0 replies; 21+ messages in thread
From: Frank Li @ 2026-10-21 15:32 UTC (permalink / raw)
  To: Manikanta Maddireddy
  Cc: lpieralisi, kwilczynski, mani, bhelgaas, linux-pci, robh,
	thierry.reding, jonathanh, kishon, Frank.Li, vidyas, cassel, den,
	marco.crivellari, andriy.shevchenko, linux-tegra, linux-kernel

On Wed, Oct 21, 2026 at 11:43:46AM +0530, Manikanta Maddireddy wrote:
> Tegra234 Endpoint mode must not advertise L1.2 because exiting L1.2 can
> bring the link down. That hardware workaround is required regardless of
> whether the endpoint kernel is built with CONFIG_PCIEASPM.
>
> Move the L1.2 capability masking out of init_host_aspm(), which is compiled
> out when CONFIG_PCIEASPM is disabled, and apply it from the common
> initialization paths.
>
> Fixes: f59df1d9e6bd ("PCI: tegra194: Disable L1.2 capability of Tegra234 EP")
> Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

> Changes V1 -> V2: None
>
>  drivers/pci/controller/dwc/pcie-tegra194.c | 47 +++++++++++++---------
>  1 file changed, 28 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
> index 7c349478556d..0e6224b6751d 100644
> --- a/drivers/pci/controller/dwc/pcie-tegra194.c
> +++ b/drivers/pci/controller/dwc/pcie-tegra194.c
> @@ -611,6 +611,33 @@ static struct pci_ops tegra_pci_ops = {
>  	.write = tegra_pcie_dw_wr_own_conf,
>  };
>
> +/*
> + * Disable L1.2 capability advertisement for Tegra234 Endpoint mode.
> + * Tegra234 has a hardware bug where during L1.2 exit, the UPHY PLL is
> + * powered up immediately without waiting for REFCLK to stabilize. This causes
> + * the PLL to fail to lock to the correct frequency, resulting in PCIe link
> + * loss. Since there is no hardware fix available, prevent the Endpoint from
> + * advertising L1.2 support so the host will not attempt to enter L1.2 with
> + * this Endpoint.
> + */
> +static void tegra_pcie_disable_ep_l1_2(struct tegra_pcie_dw *pcie)
> +{
> +	struct dw_pcie *pci = &pcie->pci;
> +	u32 l1ss, val;
> +
> +	if (!pcie->of_data->disable_l1_2 ||
> +	    pcie->of_data->mode != DW_PCIE_EP_TYPE)
> +		return;
> +
> +	l1ss = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_L1SS);
> +	if (!l1ss)
> +		return;
> +
> +	val = dw_pcie_readl_dbi(pci, l1ss + PCI_L1SS_CAP);
> +	val &= ~(PCI_L1SS_CAP_PCIPM_L1_2 | PCI_L1SS_CAP_ASPM_L1_2);
> +	dw_pcie_writel_dbi(pci, l1ss + PCI_L1SS_CAP, val);
> +}
> +
>  #if defined(CONFIG_PCIEASPM)
>  static inline u32 event_counter_prog(struct tegra_pcie_dw *pcie, u32 event)
>  {
> @@ -694,25 +721,6 @@ static void init_host_aspm(struct tegra_pcie_dw *pcie)
>
>  		if (pcie->supports_clkreq)
>  			pci->l1ss_support = true;
> -
> -		/*
> -		 * Disable L1.2 capability advertisement for Tegra234 Endpoint
> -		 * mode. Tegra234 has a hardware bug where during L1.2 exit,
> -		 * the UPHY PLL is powered up immediately without waiting for
> -		 * REFCLK to stabilize. This causes the PLL to fail to lock to
> -		 * the correct frequency, resulting in PCIe link loss. Since
> -		 * there is no hardware fix available, prevent the Endpoint
> -		 * from advertising L1.2 support by clearing the L1.2 bits in
> -		 * the L1 PM Substates Capabilities register. This ensures the
> -		 * host will not attempt to enter L1.2 with this Endpoint.
> -		 */
> -		if (pcie->of_data->disable_l1_2 &&
> -		    pcie->of_data->mode == DW_PCIE_EP_TYPE) {
> -			val = dw_pcie_readl_dbi(pci, l1ss + PCI_L1SS_CAP);
> -			val &= ~(PCI_L1SS_CAP_PCIPM_L1_2 |
> -				 PCI_L1SS_CAP_ASPM_L1_2);
> -			dw_pcie_writel_dbi(pci, l1ss + PCI_L1SS_CAP, val);
> -		}
>  	}
>
>  	/* Program L0s and L1 entrance latencies */
> @@ -1903,6 +1911,7 @@ static void pex_ep_event_pex_rst_deassert(struct tegra_pcie_dw *pcie)
>  	config_gen3_gen4_eq_presets(pcie);
>
>  	init_host_aspm(pcie);
> +	tegra_pcie_disable_ep_l1_2(pcie);
>
>  	if (!pcie->of_data->has_l1ss_exit_fix) {
>  		val = dw_pcie_readl_dbi(pci, GEN3_CTRL);
> --
> 2.34.1
>

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

* Re: [PATCH v2 08/10] PCI: tegra194: Guard Endpoint PLL-off error path
  2026-10-21  6:13 ` [PATCH v2 08/10] PCI: tegra194: Guard Endpoint PLL-off error path Manikanta Maddireddy
@ 2026-10-21 15:36   ` Frank Li
  0 siblings, 0 replies; 21+ messages in thread
From: Frank Li @ 2026-10-21 15:36 UTC (permalink / raw)
  To: Manikanta Maddireddy
  Cc: lpieralisi, kwilczynski, mani, bhelgaas, linux-pci, robh,
	thierry.reding, jonathanh, kishon, Frank.Li, vidyas, cassel, den,
	marco.crivellari, andriy.shevchenko, linux-tegra, linux-kernel

On Wed, Oct 21, 2026 at 11:43:47AM +0530, Manikanta Maddireddy wrote:
> The Endpoint PERST# deassert path initializes the external-refclk PLL only
> when enable_ext_refclk is set, but the error unwind always sent the PLL-off
> request.
>
> Guard the PLL-off request with enable_ext_refclk so Tegra234 Endpoint
> configurations that did not enable the PLL do not send a spurious BPMP
> PLL-off command.
>
> Fixes: a54e19073718 ("PCI: tegra194: Add Tegra234 PCIe support")
> Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

> Changes V1 -> V2: None
>
>  drivers/pci/controller/dwc/pcie-tegra194.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
> index 0e6224b6751d..de14a23f9a4d 100644
> --- a/drivers/pci/controller/dwc/pcie-tegra194.c
> +++ b/drivers/pci/controller/dwc/pcie-tegra194.c
> @@ -1973,7 +1973,8 @@ static void pex_ep_event_pex_rst_deassert(struct tegra_pcie_dw *pcie)
>  fail_core_apb_rst:
>  	clk_disable_unprepare(pcie->core_clk);
>  fail_core_clk_enable:
> -	tegra_pcie_bpmp_set_pll_state(pcie, false);
> +	if (pcie->enable_ext_refclk)
> +		tegra_pcie_bpmp_set_pll_state(pcie, false);
>  fail_pll_init:
>  	tegra_pcie_bpmp_set_ctrl_state(pcie, false);
>  fail_set_ctrl_state:
> --
> 2.34.1
>

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

* Re: [PATCH v2 09/10] PCI: tegra194: Balance core monitor clock on failures
  2026-10-21  6:13 ` [PATCH v2 09/10] PCI: tegra194: Balance core monitor clock on failures Manikanta Maddireddy
@ 2026-10-21 15:43   ` Frank Li
  0 siblings, 0 replies; 21+ messages in thread
From: Frank Li @ 2026-10-21 15:43 UTC (permalink / raw)
  To: Manikanta Maddireddy
  Cc: lpieralisi, kwilczynski, mani, bhelgaas, linux-pci, robh,
	thierry.reding, jonathanh, kishon, Frank.Li, vidyas, cassel, den,
	marco.crivellari, andriy.shevchenko, linux-tegra, linux-kernel

On Wed, Oct 21, 2026 at 11:43:48AM +0530, Manikanta Maddireddy wrote:
> tegra_pcie_dw_host_init() enables core_clk_m, but failure paths that leave
> after the host init callback can unconfigure the controller without
> disabling that clock. The enable error is also only logged, so later
> cleanup can try to disable a clock that was never enabled.
>
> Track the monitor clock state, return enable failures, and use a common
> helper on retry, remove, suspend, shutdown and host-init failure paths so
> the clock is disabled exactly when it was enabled.

Feel like checking core_clk_m_enabled for clock is not good desgin. Do you
disable clock when linkdown?

Frank

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

* Re: [PATCH v2 10/10] PCI: tegra194: Reject zero MSI interrupt number
  2026-10-21  6:13 ` [PATCH v2 10/10] PCI: tegra194: Reject zero MSI interrupt number Manikanta Maddireddy
@ 2026-10-21 15:44   ` Frank Li
  0 siblings, 0 replies; 21+ messages in thread
From: Frank Li @ 2026-10-21 15:44 UTC (permalink / raw)
  To: Manikanta Maddireddy
  Cc: lpieralisi, kwilczynski, mani, bhelgaas, linux-pci, robh,
	thierry.reding, jonathanh, kishon, Frank.Li, vidyas, cassel, den,
	marco.crivellari, andriy.shevchenko, linux-tegra, linux-kernel

On Wed, Oct 21, 2026 at 11:43:49AM +0530, Manikanta Maddireddy wrote:
> Reject interrupt number zero before computing BIT(irq - 1). The endpoint
> IRQ API uses interrupt numbers in the range 1-N, and existing EPF drivers
> already follow that convention. This is defensive validation rather than
> a correction to the MSI numbering used by those drivers.
>
> Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

> Changes V1 -> V2:
> - Retain only MSI interrupt-number-zero validation from v1 patch 10.
> - Rewrite the title and commit message around defensive MSI validation,
>   and remove the Fixes tag.
>
>  drivers/pci/controller/dwc/pcie-tegra194.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
> index 632ecab3c8ea..0f49ea6df8bc 100644
> --- a/drivers/pci/controller/dwc/pcie-tegra194.c
> +++ b/drivers/pci/controller/dwc/pcie-tegra194.c
> @@ -2026,7 +2026,7 @@ static int tegra_pcie_ep_raise_intx_irq(struct tegra_pcie_dw *pcie, u16 irq)
>
>  static int tegra_pcie_ep_raise_msi_irq(struct tegra_pcie_dw *pcie, u16 irq)
>  {
> -	if (unlikely(irq > 32))
> +	if (unlikely(!irq || irq > 32))
>  		return -EINVAL;
>
>  	appl_writel(pcie, BIT(irq - 1), APPL_MSI_CTRL_1);
> --
> 2.34.1
>

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

end of thread, other threads:[~2026-10-21 15:44 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-21  6:13 [PATCH v2 00/10] PCI: tegra194: Fix EP and Root Port corner cases Manikanta Maddireddy
2026-10-21  6:13 ` [PATCH v2 01/10] PCI: tegra194: Propagate REFCLK select GPIO errors Manikanta Maddireddy
2026-10-21 15:14   ` Frank Li
2026-10-21  6:13 ` [PATCH v2 02/10] PCI: tegra194: Check core reset deassertion Manikanta Maddireddy
2026-10-21 15:16   ` Frank Li
2026-10-21  6:13 ` [PATCH v2 03/10] PCI: tegra194: Fix Endpoint PERST# IRQ suspend race Manikanta Maddireddy
2026-10-21 15:19   ` Frank Li
2026-10-21  6:13 ` [PATCH v2 04/10] PCI: tegra194: Do not skip no-link Root Port remove cleanup Manikanta Maddireddy
2026-10-21 15:22   ` Frank Li
2026-10-21  6:13 ` [PATCH v2 05/10] PCI: tegra194: Check for 16 GT/s capability before programming Manikanta Maddireddy
2026-10-21 15:24   ` Frank Li
2026-10-21  6:13 ` [PATCH v2 06/10] PCI: tegra194: Check for L1SS " Manikanta Maddireddy
2026-10-21 15:28   ` Frank Li
2026-10-21  6:13 ` [PATCH v2 07/10] PCI: tegra194: Always disable Tegra234 Endpoint L1.2 Manikanta Maddireddy
2026-10-21 15:32   ` Frank Li
2026-10-21  6:13 ` [PATCH v2 08/10] PCI: tegra194: Guard Endpoint PLL-off error path Manikanta Maddireddy
2026-10-21 15:36   ` Frank Li
2026-10-21  6:13 ` [PATCH v2 09/10] PCI: tegra194: Balance core monitor clock on failures Manikanta Maddireddy
2026-10-21 15:43   ` Frank Li
2026-10-21  6:13 ` [PATCH v2 10/10] PCI: tegra194: Reject zero MSI interrupt number Manikanta Maddireddy
2026-10-21 15:44   ` Frank Li

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®