All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/4] PCI: dwc: Avoid full EP cleanup on PERST#
@ 2026-11-02 11:14 Manikanta Maddireddy
  2026-11-02 11:14 ` [PATCH v3 1/4] PCI: dwc: Reuse Endpoint resources after fundamental reset Manikanta Maddireddy
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Manikanta Maddireddy @ 2026-11-02 11:14 UTC (permalink / raw)
  To: jingoohan1, mani, lpieralisi, kwilczynski, bhelgaas, linux-pci
  Cc: robh, thierry.reding, jonathanh, vidyas, cassel, linux-kernel,
	linux-tegra, mmaddireddy

This series avoids repeating full DWC Endpoint software resource cleanup
and initialization on every PERST# cycle while still restoring reset-lost
hardware state on the following PERST# deassertion.

The current Tegra194/234 Endpoint flow runs the full DWC EP cleanup/init
sequence for each PERST# cycle. The allocation bitmaps, outbound-address
array and per-function descriptors already have allocation guards and can
be reused. Repeated full cleanup/init also removes and recreates debugfs
entries and unregisters and reprobes eDMA where present; eDMA detection
allocates managed linked-list memory retained until device detach.

Patch 1 folds initial setup and reset recovery into the existing
dw_pcie_ep_init_registers() API. It tracks successful resource setup and
uses a private helper to restore reset-lost registers on subsequent calls.
After hardware resets the iATU, cached outbound mapping state is reset so
stale bookkeeping does not hide available windows. This does not disable
or unmap live hardware windows.

Patch 2 removes the full DWC EP cleanup from Tegra PERST# deassertion,
allowing the existing initialization API to retain software resources and
restore registers. Patch 3 notifies EPFs of link down before powering off
the controller on PERST# assertion, allowing their callbacks to quiesce
work. It calls pci_epc_linkdown() directly to avoid the DWC linkdown
helper's DBI register reinitialization after REFCLK may have disappeared.
EPF callbacks can still access MMIO; the notification is not a guarantee
of register-free execution.

Patch 4 requires PCI_ENDPOINT for the Tegra194 PCIe driver because the
PERST# assertion handler now directly calls pci_epc_linkdown(), which has
no stub when endpoint support is disabled. This fixes the build failure
reported by the kernel test robot.

Hardware-dependent EPF deinitialization remains in the PERST# deassert
path where REFCLK is available and core reset has been deasserted.

This series is rebased onto the current PCI main-based patch stack,
after the DWC register-field cleanup and Tegra Endpoint/Root Port
corner-case fixes. The base commit is recorded below.

Changes in v3:
- Rebase onto the current PCI main-based patch stack.
- No code changes to patches 1-3 compared with v2.
- Add patch 4 to require PCI_ENDPOINT for the pci_epc_linkdown() call and
  fix the CONFIG_PCI_ENDPOINT=n build failure reported by the kernel test
  robot.

Changes in v2:
- Rename the outbound helper to dw_pcie_ep_reset_outbound_state() and
  clarify that it invalidates software state after hardware reset rather
  than disabling live iATU mappings.
- Fold init/reinit selection into dw_pcie_ep_init_registers(). Remove the
  separate init-or-reinit API and keep register restoration private.
- Document the reset and quiescence prerequisites and retain full
  initialization after dw_pcie_ep_cleanup() clears the resource-state flag.
- Clarify which resources are retained and avoid implying that the
  existing guarded allocations were repeated on every reset.
- Keep Tegra's existing initialization call; only remove per-reset cleanup.
- Narrow the linkdown notification's safety claim and remove unrelated
  pointer cleanup and teardown discussion from patch 3.
- Reword the resource-lifetime explanations in patches 1 and 2.

Validation reported with v2 (patches 1-3 are unchanged):
- ARM64 compilation of the DWC EP, host, core and Tegra objects passed.
- Per-patch checkpatch and whitespace checks passed.
- Verified Endpoint reset sequence multiple times.
- Verified ./pci_endpoint_test tests after Endpoint reset sequence.

v2: https://lore.kernel.org/linux-pci/20261021061903.1269605-1-mmaddireddy@nvidia.com/

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

Manikanta Maddireddy (4):
  PCI: dwc: Reuse Endpoint resources after fundamental reset
  PCI: tegra194: Avoid full Endpoint reinit on PERST#
  PCI: tegra194: Notify Endpoint functions on PERST# assert
  PCI: tegra194: Add PCI_ENDPOINT dependency

 drivers/pci/controller/dwc/Kconfig            |   1 +
 .../pci/controller/dwc/pcie-designware-ep.c   | 149 +++++++++++++-----
 drivers/pci/controller/dwc/pcie-designware.h  |   1 +
 drivers/pci/controller/dwc/pcie-tegra194.c    |   4 +-
 4 files changed, 112 insertions(+), 43 deletions(-)


base-commit: 0012b353452613344db3292f17c69ea512344949
-- 
2.34.1


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

* [PATCH v3 1/4] PCI: dwc: Reuse Endpoint resources after fundamental reset
  2026-11-02 11:14 [PATCH v3 0/4] PCI: dwc: Avoid full EP cleanup on PERST# Manikanta Maddireddy
@ 2026-11-02 11:14 ` Manikanta Maddireddy
  2026-11-02 11:35   ` sashiko-bot
  2026-11-02 11:14 ` [PATCH v3 2/4] PCI: tegra194: Avoid full Endpoint reinit on PERST# Manikanta Maddireddy
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 10+ messages in thread
From: Manikanta Maddireddy @ 2026-11-02 11:14 UTC (permalink / raw)
  To: jingoohan1, mani, lpieralisi, kwilczynski, bhelgaas, linux-pci
  Cc: robh, thierry.reding, jonathanh, vidyas, cassel, linux-kernel,
	linux-tegra, mmaddireddy

A fundamental reset clears DWC Endpoint registers but does not end the
lifetime of the bound driver. Each full cleanup/init cycle removes and
recreates debugfs entries and, when eDMA is present, unregisters and
reprobes the DMA controller. eDMA detection also allocates managed DMA
linked-list memory that is retained until device detach. The
inbound/outbound allocation bitmaps, outbound-address array and
per-function descriptors already have allocation guards and can be
reused.

Track successful resource initialization in dw_pcie_ep_init_registers().
On later calls, restore the platform-specific registers, BAR defaults,
PTM and non-sticky registers without repeating resource setup. Keep the
register restoration helper private and use the existing public API for
both initial setup and reset recovery. Clear the initialization flag on
full cleanup so a later call performs resource setup again.

Invalidate the outbound window bitmap, address array and MSI iATU cache
after hardware has reset the iATU. This resets software bookkeeping; it
does not disable or unmap live hardware windows. Document that reset
recovery requires the hardware reset and quiesced EPF activity.

Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
---
Changes V2 -> V3:
- No code changes from v2; rebased onto the current PCI main-based stack.

Changes V1 -> V2:
- Fold init/reinit selection into dw_pcie_ep_init_registers() instead of
  adding a separate init-or-reinit API.
- Keep the register restoration helper private and remove its public
  declarations, export and disabled-config stub.
- Rename the outbound helper to dw_pcie_ep_reset_outbound_state() and
  explain that it resets software bookkeeping after hardware reset.
- Document reset-recovery prerequisites and clarify resource lifetimes.
- Update the title and commit message to describe resource reuse.

 .../pci/controller/dwc/pcie-designware-ep.c   | 149 +++++++++++++-----
 drivers/pci/controller/dwc/pcie-designware.h  |   1 +
 2 files changed, 108 insertions(+), 42 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 630ba172280c..be0a997416f5 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -1155,6 +1155,32 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
 }
 EXPORT_SYMBOL_GPL(dw_pcie_ep_raise_msix_irq);
 
+static void dw_pcie_ep_clear_msi_iatu(struct dw_pcie_ep *ep)
+{
+	ep->msi_iatu_mapped = false;
+	ep->msi_iatu_mapped_offset = 0;
+	ep->msi_msg_addr = 0;
+	ep->msi_map_size = 0;
+}
+
+/*
+ * Reset only the software bookkeeping for outbound windows after hardware
+ * has reset the iATU. This does not disable or unmap live hardware windows.
+ */
+static void dw_pcie_ep_reset_outbound_state(struct dw_pcie_ep *ep)
+{
+	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+
+	if (ep->ob_window_map)
+		bitmap_zero(ep->ob_window_map, pci->num_ob_windows);
+
+	if (ep->outbound_addr)
+		memset(ep->outbound_addr, 0,
+		       pci->num_ob_windows * sizeof(*ep->outbound_addr));
+
+	dw_pcie_ep_clear_msi_iatu(ep);
+}
+
 /**
  * dw_pcie_ep_cleanup - Cleanup DWC EP resources after fundamental reset
  * @ep: DWC EP device
@@ -1169,11 +1195,12 @@ void dw_pcie_ep_cleanup(struct dw_pcie_ep *ep)
 
 	if (ep->msi_iatu_mapped) {
 		dw_pcie_ep_unmap_addr(ep->epc, 0, 0, ep->msi_mem_phys);
-		ep->msi_iatu_mapped = false;
+		dw_pcie_ep_clear_msi_iatu(ep);
 	}
 
 	dwc_pcie_debugfs_deinit(pci);
 	dw_pcie_edma_remove(pci);
+	ep->resources_initialized = false;
 }
 EXPORT_SYMBOL_GPL(dw_pcie_ep_cleanup);
 
@@ -1310,13 +1337,84 @@ static void dw_pcie_ep_disable_bars(struct dw_pcie_ep *ep)
 	}
 }
 
+static void dw_pcie_ep_init_ptm(struct dw_pcie_ep *ep)
+{
+	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+	u32 ptm_cap_base, reg;
+
+	/*
+	 * PCIe r6.0, section 7.9.15 states that for endpoints that support
+	 * PTM, this capability structure is required in exactly one
+	 * function, which controls the PTM behavior of all PTM capable
+	 * functions. This indicates the PTM capability structure
+	 * represents controller-level registers rather than per-function
+	 * registers.
+	 *
+	 * Therefore, PTM capability registers are configured using the
+	 * standard DBI accessors, instead of func_no indexed per-function
+	 * accessors.
+	 */
+	ptm_cap_base = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_PTM);
+
+	/*
+	 * PTM responder capability can be disabled only after disabling
+	 * PTM root capability.
+	 */
+	if (ptm_cap_base) {
+		dw_pcie_dbi_ro_wr_en(pci);
+		reg = dw_pcie_readl_dbi(pci, ptm_cap_base + PCI_PTM_CAP);
+		reg &= ~PCI_PTM_CAP_ROOT;
+		dw_pcie_writel_dbi(pci, ptm_cap_base + PCI_PTM_CAP, reg);
+
+		reg = dw_pcie_readl_dbi(pci, ptm_cap_base + PCI_PTM_CAP);
+		reg &= ~(PCI_PTM_CAP_RES | PCI_PTM_GRANULARITY_MASK);
+		dw_pcie_writel_dbi(pci, ptm_cap_base + PCI_PTM_CAP, reg);
+		dw_pcie_dbi_ro_wr_dis(pci);
+	}
+}
+
+/**
+ * dw_pcie_ep_reinit_registers - Reinitialize DWC EP reset-lost registers
+ * @ep: DWC EP device
+ *
+ * Restore the EP registers lost after a fundamental reset without repeating
+ * software resource setup. Hardware must already have reset the iATU; this
+ * helper invalidates software iATU state but does not disable live windows.
+ */
+static int dw_pcie_ep_reinit_registers(struct dw_pcie_ep *ep)
+{
+	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+	int ret;
+
+	dw_pcie_ep_reset_outbound_state(ep);
+
+	if (ep->ops->init) {
+		ret = ep->ops->init(ep);
+		if (ret)
+			return ret;
+	}
+
+	dw_pcie_ep_disable_bars(ep);
+	dw_pcie_ep_init_ptm(ep);
+	dw_pcie_ep_init_non_sticky_registers(pci);
+
+	return 0;
+}
+
 /**
  * dw_pcie_ep_init_registers - Initialize DWC EP specific registers
  * @ep: DWC EP device
  *
  * Initialize the registers (CSRs) specific to DWC EP. This API should be called
  * only when the endpoint receives an active refclk (either from host or
- * generated locally).
+ * generated locally). The caller must quiesce EPF activity and ensure that
+ * hardware has reset the outbound iATU before calling this API after a
+ * fundamental reset. Cached outbound mappings are invalidated without
+ * disabling live hardware windows.
+ *
+ * The first successful call sets up the DWC EP software resources. Later
+ * calls restore reset-lost registers while retaining those resources until
+ * dw_pcie_ep_cleanup() or dw_pcie_ep_deinit().
  */
 int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep)
 {
@@ -1324,7 +1422,6 @@ int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep)
 	struct dw_pcie_ep_func *ep_func;
 	struct device *dev = pci->dev;
 	struct pci_epc *epc = ep->epc;
-	u32 ptm_cap_base, reg;
 	u8 hdr_type;
 	u8 func_no;
 	void *addr;
@@ -1339,6 +1436,9 @@ int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep)
 		return -EIO;
 	}
 
+	if (ep->resources_initialized)
+		return dw_pcie_ep_reinit_registers(ep);
+
 	dw_pcie_version_detect(pci);
 
 	dw_pcie_iatu_detect(pci);
@@ -1389,47 +1489,12 @@ int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep)
 		list_add_tail(&ep_func->list, &ep->func_list);
 	}
 
-	if (ep->ops->init) {
-		ret = ep->ops->init(ep);
-		if (ret)
-			goto err_remove_edma;
-	}
-
-	dw_pcie_ep_disable_bars(ep);
-
-	/*
-	 * PCIe r6.0, section 7.9.15 states that for endpoints that support
-	 * PTM, this capability structure is required in exactly one
-	 * function, which controls the PTM behavior of all PTM capable
-	 * functions. This indicates the PTM capability structure
-	 * represents controller-level registers rather than per-function
-	 * registers.
-	 *
-	 * Therefore, PTM capability registers are configured using the
-	 * standard DBI accessors, instead of func_no indexed per-function
-	 * accessors.
-	 */
-	ptm_cap_base = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_PTM);
-
-	/*
-	 * PTM responder capability can be disabled only after disabling
-	 * PTM root capability.
-	 */
-	if (ptm_cap_base) {
-		dw_pcie_dbi_ro_wr_en(pci);
-		reg = dw_pcie_readl_dbi(pci, ptm_cap_base + PCI_PTM_CAP);
-		reg &= ~PCI_PTM_CAP_ROOT;
-		dw_pcie_writel_dbi(pci, ptm_cap_base + PCI_PTM_CAP, reg);
-
-		reg = dw_pcie_readl_dbi(pci, ptm_cap_base + PCI_PTM_CAP);
-		reg &= ~(PCI_PTM_CAP_RES | PCI_PTM_GRANULARITY_MASK);
-		dw_pcie_writel_dbi(pci, ptm_cap_base + PCI_PTM_CAP, reg);
-		dw_pcie_dbi_ro_wr_dis(pci);
-	}
-
-	dw_pcie_ep_init_non_sticky_registers(pci);
+	ret = dw_pcie_ep_reinit_registers(ep);
+	if (ret)
+		goto err_remove_edma;
 
 	dwc_pcie_debugfs_init(pci, DW_PCIE_EP_TYPE);
+	ep->resources_initialized = true;
 
 	return 0;
 
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index 09fb802174ee..f40d488cd561 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -521,6 +521,7 @@ struct dw_pcie_ep {
 	unsigned long		*ob_window_map;
 	void __iomem		*msi_mem;
 	phys_addr_t		msi_mem_phys;
+	bool			resources_initialized;
 
 	/* MSI outbound iATU state */
 	bool			msi_iatu_mapped;
-- 
2.34.1


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

* [PATCH v3 2/4] PCI: tegra194: Avoid full Endpoint reinit on PERST#
  2026-11-02 11:14 [PATCH v3 0/4] PCI: dwc: Avoid full EP cleanup on PERST# Manikanta Maddireddy
  2026-11-02 11:14 ` [PATCH v3 1/4] PCI: dwc: Reuse Endpoint resources after fundamental reset Manikanta Maddireddy
@ 2026-11-02 11:14 ` Manikanta Maddireddy
  2026-11-02 11:41   ` sashiko-bot
  2026-11-02 11:14 ` [PATCH v3 3/4] PCI: tegra194: Notify Endpoint functions on PERST# assert Manikanta Maddireddy
  2026-11-02 11:14 ` [PATCH v3 4/4] PCI: tegra194: Add PCI_ENDPOINT dependency Manikanta Maddireddy
  3 siblings, 1 reply; 10+ messages in thread
From: Manikanta Maddireddy @ 2026-11-02 11:14 UTC (permalink / raw)
  To: jingoohan1, mani, lpieralisi, kwilczynski, bhelgaas, linux-pci
  Cc: robh, thierry.reding, jonathanh, vidyas, cassel, linux-kernel,
	linux-tegra, mmaddireddy

Tegra194 and Tegra234 lose controller register state across PERST#, but
the driver remains bound. The common DWC initialization path now
restores those registers while preserving its software resources. Tegra
therefore no longer needs to call dw_pcie_ep_cleanup() on each PERST#
cycle.

Remove the per-reset dw_pcie_ep_cleanup() call. The existing
dw_pcie_ep_init_registers() entry point now restores reset-lost
registers after the first initialization while retaining software
resources until final driver teardown. The allocation guards already
reuse the bitmaps, address array and per-function descriptors; this
change also avoids repeating the full debugfs/eDMA teardown and setup.

Keep the EPF deinit notification in the PERST# deassert path after
REFCLK is available and core reset has been deasserted, because EPF
deinit callbacks can clear BARs and need register access. The final
dw_pcie_ep_deinit() during driver removal still performs full cleanup.

Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
---
Changes V2 -> V3:
- No code changes from v2; rebased onto the current PCI main-based stack.

Changes V1 -> V2:
- Keep the existing dw_pcie_ep_init_registers() call now that it handles
  both initial setup and reset recovery; only remove per-reset cleanup.
- Clarify the retained resource lifetimes and shorten the opening
  paragraph to focus on the Tegra change.

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

diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
index 72158fc5c639..08d6f4c5220f 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -1909,7 +1909,6 @@ static void pex_ep_event_pex_rst_deassert(struct tegra_pcie_dw *pcie)
 
 	/* Perform cleanup that requires refclk and core reset deasserted */
 	pci_epc_deinit_notify(pcie->pci.ep.epc);
-	dw_pcie_ep_cleanup(&pcie->pci.ep);
 
 	val = dw_pcie_readl_dbi(pci, LINK_WIDTH_SPEED_CTRL);
 	val &= ~SPEED_CHANGE;
-- 
2.34.1


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

* [PATCH v3 3/4] PCI: tegra194: Notify Endpoint functions on PERST# assert
  2026-11-02 11:14 [PATCH v3 0/4] PCI: dwc: Avoid full EP cleanup on PERST# Manikanta Maddireddy
  2026-11-02 11:14 ` [PATCH v3 1/4] PCI: dwc: Reuse Endpoint resources after fundamental reset Manikanta Maddireddy
  2026-11-02 11:14 ` [PATCH v3 2/4] PCI: tegra194: Avoid full Endpoint reinit on PERST# Manikanta Maddireddy
@ 2026-11-02 11:14 ` Manikanta Maddireddy
  2026-11-02 11:38   ` sashiko-bot
  2026-11-02 11:14 ` [PATCH v3 4/4] PCI: tegra194: Add PCI_ENDPOINT dependency Manikanta Maddireddy
  3 siblings, 1 reply; 10+ messages in thread
From: Manikanta Maddireddy @ 2026-11-02 11:14 UTC (permalink / raw)
  To: jingoohan1, mani, lpieralisi, kwilczynski, bhelgaas, linux-pci
  Cc: robh, thierry.reding, jonathanh, vidyas, cassel, linux-kernel,
	linux-tegra, mmaddireddy

Tegra powers down the Endpoint controller when the host asserts PERST#.
Notify EPF drivers of link down before disabling the controller so their
link_down callbacks can quiesce outstanding work. For example,
pci_epf_test_link_down() synchronously cancels its command worker.
Without this notification, the worker can remain active after the
controller is powered down and while EPC resources are later removed.

Call pci_epc_linkdown() directly instead of dw_pcie_ep_linkdown(), which
also reinitializes non-sticky DWC registers through DBI when the host
may already have withdrawn REFCLK. The direct notification avoids that
common DWC register reinitialization. It does not guarantee that EPF
callbacks are register-free: they can access MMIO and must tolerate the
hardware state at PERST# assertion, including unavailable DBI access.

Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
---
Changes V2 -> V3:
- No code changes from v2; rebased onto the current PCI main-based stack.

Changes V1 -> V2:
- Clarify that the direct notification avoids common DWC DBI register
  reinitialization, but EPF callbacks may still access hardware.
- Add a comment explaining why dw_pcie_ep_linkdown() is not used.
- Drop the unrelated pci_epc_deinit_notify() pointer cleanup.
- Remove unrelated teardown and deferred-deinit discussion from the
  commit message.

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

diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
index 08d6f4c5220f..df679509677d 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -1740,6 +1740,9 @@ static void pex_ep_event_pex_rst_assert(struct tegra_pcie_dw *pcie)
 	if (ret)
 		dev_info(pcie->dev, "LTSSM state: 0x%x detect timeout: %d\n", val, ret);
 
+	/* Avoid the DBI register reinitialization in dw_pcie_ep_linkdown(). */
+	pci_epc_linkdown(pcie->pci.ep.epc);
+
 	/*
 	 * Deassert LTSSM state to stop the state toggling between
 	 * Polling and Detect.
-- 
2.34.1


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

* [PATCH v3 4/4] PCI: tegra194: Add PCI_ENDPOINT dependency
  2026-11-02 11:14 [PATCH v3 0/4] PCI: dwc: Avoid full EP cleanup on PERST# Manikanta Maddireddy
                   ` (2 preceding siblings ...)
  2026-11-02 11:14 ` [PATCH v3 3/4] PCI: tegra194: Notify Endpoint functions on PERST# assert Manikanta Maddireddy
@ 2026-11-02 11:14 ` Manikanta Maddireddy
  2026-11-02 11:31   ` sashiko-bot
  2026-11-02 15:20   ` Niklas Cassel
  3 siblings, 2 replies; 10+ messages in thread
From: Manikanta Maddireddy @ 2026-11-02 11:14 UTC (permalink / raw)
  To: jingoohan1, mani, lpieralisi, kwilczynski, bhelgaas, linux-pci
  Cc: robh, thierry.reding, jonathanh, vidyas, cassel, linux-kernel,
	linux-tegra, mmaddireddy, kernel test robot

The PERST# assertion handler now calls pci_epc_linkdown() to notify
Endpoint functions before powering down the controller. This function
is only declared when CONFIG_PCI_ENDPOINT is enabled and has no stub
when endpoint support is disabled.

Add a PCI_ENDPOINT dependency to ensure that the endpoint framework is
available whenever the Tegra194 PCIe driver is built.

Fixes: bf644226574e ("PCI: tegra194: Notify Endpoint functions on PERST# assert")
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202610230923.2lf3BsLs-lkp@intel.com/
Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
---
Changes V2 -> V3:
- New patch in v3: require PCI_ENDPOINT for pci_epc_linkdown(), added to
  the PERST# assertion handler, to be declared when the driver is built.

 drivers/pci/controller/dwc/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig
index 0a0d56fcf0ac..704134684900 100644
--- a/drivers/pci/controller/dwc/Kconfig
+++ b/drivers/pci/controller/dwc/Kconfig
@@ -245,6 +245,7 @@ config PCIE_TEGRA194_HOST
 	tristate "NVIDIA Tegra194 (and later) PCIe controller (host mode)"
 	depends on (ARCH_TEGRA && ARM64) || COMPILE_TEST
 	depends on PCI_MSI
+	depends on PCI_ENDPOINT
 	select PCIE_DW_HOST
 	select PHY_TEGRA194_P2U
 	select PCIE_TEGRA194
-- 
2.34.1


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

* Re: [PATCH v3 4/4] PCI: tegra194: Add PCI_ENDPOINT dependency
  2026-11-02 11:14 ` [PATCH v3 4/4] PCI: tegra194: Add PCI_ENDPOINT dependency Manikanta Maddireddy
@ 2026-11-02 11:31   ` sashiko-bot
  2026-11-02 15:20   ` Niklas Cassel
  1 sibling, 0 replies; 10+ messages in thread
From: sashiko-bot @ 2026-11-02 11:31 UTC (permalink / raw)
  To: Manikanta Maddireddy, linux-pci

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] PCI: tegra194: host Kconfig depends on PCI_ENDPOINT instead of EPC stub
--

commit b82fa7e55a14cc1575d1ffe0c356f50c758354e7
Author: Manikanta Maddireddy <mmaddireddy@nvidia.com>

PCI: tegra194: Add PCI_ENDPOINT dependency

This commit adds a PCI_ENDPOINT dependency to PCIE_TEGRA194_HOST in Kconfig so
that pci_epc_linkdown(), called from the PERST# assertion handler, is declared
when building the Tegra194 PCIe driver.

Closes: https://lore.kernel.org/oe-kbuild-all/202610230923.2lf3BsLs-lkp@intel.com/

> diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig
> index 0a0d56fcf0ac9..7041346849002 100644
> --- a/drivers/pci/controller/dwc/Kconfig
> +++ b/drivers/pci/controller/dwc/Kconfig
> @@ -245,6 +245,7 @@ config PCIE_TEGRA194_HOST
>  	tristate "NVIDIA Tegra194 (and later) PCIe controller (host mode)"
>  	depends on (ARCH_TEGRA && ARM64) || COMPILE_TEST
>  	depends on PCI_MSI
> +	depends on PCI_ENDPOINT

[Severity: Medium]
Does adding a PCI_ENDPOINT dependency to PCIE_TEGRA194_HOST disable Root
Complex support on existing host-only configurations where CONFIG_PCI_ENDPOINT
is not enabled (such as during olddefconfig), or force host-only kernels to
build the unused PCI Endpoint framework?

In drivers/pci/controller/dwc/Kconfig, Tegra194 PCIe support is split into
PCIE_TEGRA194_HOST and PCIE_TEGRA194_EP, where PCIE_TEGRA194_EP already
depends on PCI_ENDPOINT, and none of the other dual-mode DesignWare host
Kconfig symbols depend on PCI_ENDPOINT.

In drivers/pci/controller/dwc/pcie-tegra194.c, pex_ep_event_pex_rst_deassert()
already calls pci_epc_deinit_notify() and pci_epc_init_notify()
unconditionally, and those build when CONFIG_PCI_ENDPOINT=n because commit
473b2cf9c4d1 ("PCI: endpoint: Introduce 'epc_deinit' event and notify the EPF
drivers") added static inline no-op stubs in include/linux/pci-epc.h:

#ifdef CONFIG_PCI_ENDPOINT
void pci_epc_init_notify(struct pci_epc *epc);
void pci_epc_deinit_notify(struct pci_epc *epc);
#else
static inline void pci_epc_init_notify(struct pci_epc *epc)
{
}

static inline void pci_epc_deinit_notify(struct pci_epc *epc)
{
}
#endif /* CONFIG_PCI_ENDPOINT */

Would it be better to provide a matching static inline no-op stub for
pci_epc_linkdown() under #ifdef CONFIG_PCI_ENDPOINT in
include/linux/pci-epc.h, ordered before or squashed into commit 9fcf1c9f540e
("PCI: tegra194: Notify Endpoint functions on PERST# assert") (referenced in
the commit message via the stale SHA bf644226574e) so that host-only configs
and git bisect are not broken?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261102111450.4010818-1-mmaddireddy@nvidia.com?part=4

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

* Re: [PATCH v3 1/4] PCI: dwc: Reuse Endpoint resources after fundamental reset
  2026-11-02 11:14 ` [PATCH v3 1/4] PCI: dwc: Reuse Endpoint resources after fundamental reset Manikanta Maddireddy
@ 2026-11-02 11:35   ` sashiko-bot
  0 siblings, 0 replies; 10+ messages in thread
From: sashiko-bot @ 2026-11-02 11:35 UTC (permalink / raw)
  To: Manikanta Maddireddy, linux-pci

> A fundamental reset clears DWC Endpoint registers but does not end the
> lifetime of the bound driver. Each full cleanup/init cycle removes and
> recreates debugfs entries and, when eDMA is present, unregisters and
> reprobes the DMA controller. eDMA detection also allocates managed DMA
> linked-list memory that is retained until device detach. The
> inbound/outbound allocation bitmaps, outbound-address array and
> per-function descriptors already have allocation guards and can be
> reused.
> 
> Track successful resource initialization in dw_pcie_ep_init_registers().
> On later calls, restore the platform-specific registers, BAR defaults,
> PTM and non-sticky registers without repeating resource setup. Keep the
> register restoration helper private and use the existing public API for
> both initial setup and reset recovery. Clear the initialization flag on
> full cleanup so a later call performs resource setup again.
> 
> Invalidate the outbound window bitmap, address array and MSI iATU cache
> after hardware has reset the iATU. This resets software bookkeeping; it
> does not disable or unmap live hardware windows. Document that reset
> recovery requires the hardware reset and quiesced EPF activity.
> 
> Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>

Sashiko has reviewed this patch and found no issues.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261102111450.4010818-1-mmaddireddy@nvidia.com?part=1


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

* Re: [PATCH v3 3/4] PCI: tegra194: Notify Endpoint functions on PERST# assert
  2026-11-02 11:14 ` [PATCH v3 3/4] PCI: tegra194: Notify Endpoint functions on PERST# assert Manikanta Maddireddy
@ 2026-11-02 11:38   ` sashiko-bot
  0 siblings, 0 replies; 10+ messages in thread
From: sashiko-bot @ 2026-11-02 11:38 UTC (permalink / raw)
  To: Manikanta Maddireddy, linux-pci

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] PCI: tegra194: missing IRQ sync in pex_ep_event_pex_rst_assert()
- [High] PCI: tegra194: deadlock between pex_ep_event_pex_rst_assert() and pci_epc_stop()
--

commit 9fcf1c9f540e3e347bfaf4edb431bb510324fd09
Author: Manikanta Maddireddy <mmaddireddy@nvidia.com>

PCI: tegra194: Notify Endpoint functions on PERST# assert

This commit calls pci_epc_linkdown() from pex_ep_event_pex_rst_assert()
before powering down the Tegra194 PCIe endpoint controller on PERST#
assertion so endpoint function drivers can stop outstanding work.

> diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
> index 8cb907dbf6356..8dede9531956d 100644
> --- a/drivers/pci/controller/dwc/pcie-tegra194.c
> +++ b/drivers/pci/controller/dwc/pcie-tegra194.c
> @@ -1704,6 +1704,9 @@ static void pex_ep_event_pex_rst_assert(struct tegra_pcie_dw *pcie)
>  	if (ret)
>  		dev_info(pcie->dev, "LTSSM state: 0x%x detect timeout: %d\n", val, ret);
>  
> +	/* Avoid the DBI register reinitialization in dw_pcie_ep_linkdown(). */
> +	pci_epc_linkdown(pcie->pci.ep.epc);

[Severity: High]
Can calling pci_epc_linkdown() here race with a pending or running
tegra_pcie_ep_irq_thread() on pcie->pci.pp.irq?

In endpoint mode, tegra_pcie_ep_hard_irq() and tegra_pcie_ep_irq_thread()
run on pcie->pci.pp.irq, while tegra_pcie_ep_pex_rst_irq() runs on the
separate GPIO interrupt pcie->pex_rst_irq:

drivers/pci/controller/dwc/pcie-tegra194.c:tegra_pcie_ep_hard_irq() {
	...
			if (link_status & APPL_LINK_STATUS_RDLH_LINK_UP) {
				dev_dbg(pcie->dev, "Link is up with Host\n");
				set_bit(0, &pcie->link_status);
				return IRQ_WAKE_THREAD;
			}
	...
}

drivers/pci/controller/dwc/pcie-tegra194.c:tegra_pcie_ep_irq_thread() {
	...
	if (test_and_clear_bit(0, &pcie->link_status))
		dw_pcie_ep_linkup(ep);

	tegra_pcie_icc_set(pcie);
	...
}

If tegra_pcie_ep_hard_irq() fires just before PERST# assertion (or before
APPL_CTRL_LTSSM_EN is cleared), sets bit 0 in pcie->link_status, and wakes
tegra_pcie_ep_irq_thread(), pex_ep_event_pex_rst_assert() calls
pci_epc_linkdown() without disabling LTSSM or controller interrupts first,
without calling synchronize_irq(pcie->pci.pp.irq), and without clearing
bit 0 of pcie->link_status.

Wouldn't tegra_pcie_ep_irq_thread() then observe bit 0 set in
pcie->link_status and call dw_pcie_ep_linkup() -> pci_epc_linkup() after
pci_epc_linkdown() has already returned, re-arming endpoint function
workers (such as epf_test->cmd_handler) right before the controller is
powered down, as well as reading DBI registers in tegra_pcie_icc_set()
while pex_ep_event_pex_rst_assert() asserts resets and disables clocks?

[Severity: High]
Also, could calling pci_epc_linkdown() inside the pex_rst_irq threaded
handler deadlock against pci_epc_stop()?

When userspace stops the endpoint controller through configfs,
pci_epc_start_store() -> pci_epc_stop() holds epc->lock across
epc->ops->stop(epc):

drivers/pci/endpoint/pci-epc-core.c:pci_epc_stop() {
	...
	mutex_lock(&epc->lock);
	epc->ops->stop(epc);
	mutex_unlock(&epc->lock);
}

And epc->ops->stop() calls dw_pcie_ep_stop() -> dw_pcie_stop_link() ->
tegra_pcie_dw_stop_link(), which waits for the pex_rst_irq handler to
finish:

drivers/pci/controller/dwc/pcie-tegra194.c:tegra_pcie_dw_stop_link() {
	struct tegra_pcie_dw *pcie = to_tegra_pcie(pci);

	if (pcie->of_data->mode == DW_PCIE_EP_TYPE)
		disable_irq(pcie->pex_rst_irq);
}

Meanwhile, if tegra_pcie_ep_pex_rst_irq() -> pex_ep_event_pex_rst_assert()
is running concurrently and calls pci_epc_linkdown(), endpoint function
link_down callbacks can synchronously wait on or invoke operations that
acquire epc->lock. For example, pci_epf_test_link_down() calls:

drivers/pci/endpoint/functions/pci-epf-test.c:pci_epf_test_link_down() {
	...
	cancel_delayed_work_sync(&epf_test->cmd_handler);
	...
}

while pci_epf_test_cmd_handler() calls pci_epc_map_addr(),
pci_epc_unmap_addr(), pci_epc_raise_irq(), and pci_epc_set_bar(), all of
which take mutex_lock(&epc->lock) (and pci_epf_mhi_link_down() directly
calls mhi_ep_power_down() -> mhi_ep_abort_transfer() ->
mhi_ep_free_host_cfg() -> pci_epf_mhi_unmap_free() ->
pci_epc_unmap_addr()).

Doesn't this create a lock inversion between epc->lock and
disable_irq(pcie->pex_rst_irq)?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261102111450.4010818-1-mmaddireddy@nvidia.com?part=3

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

* Re: [PATCH v3 2/4] PCI: tegra194: Avoid full Endpoint reinit on PERST#
  2026-11-02 11:14 ` [PATCH v3 2/4] PCI: tegra194: Avoid full Endpoint reinit on PERST# Manikanta Maddireddy
@ 2026-11-02 11:41   ` sashiko-bot
  0 siblings, 0 replies; 10+ messages in thread
From: sashiko-bot @ 2026-11-02 11:41 UTC (permalink / raw)
  To: Manikanta Maddireddy, linux-pci

> Tegra194 and Tegra234 lose controller register state across PERST#, but
> the driver remains bound. The common DWC initialization path now
> restores those registers while preserving its software resources. Tegra
> therefore no longer needs to call dw_pcie_ep_cleanup() on each PERST#
> cycle.
> 
> Remove the per-reset dw_pcie_ep_cleanup() call. The existing
> dw_pcie_ep_init_registers() entry point now restores reset-lost
> registers after the first initialization while retaining software
> resources until final driver teardown. The allocation guards already
> reuse the bitmaps, address array and per-function descriptors; this
> change also avoids repeating the full debugfs/eDMA teardown and setup.
> 
> Keep the EPF deinit notification in the PERST# deassert path after
> REFCLK is available and core reset has been deasserted, because EPF
> deinit callbacks can clear BARs and need register access. The final
> dw_pcie_ep_deinit() during driver removal still performs full cleanup.
> 
> Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>

Sashiko has reviewed this patch and found no issues.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261102111450.4010818-1-mmaddireddy@nvidia.com?part=2


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

* Re: [PATCH v3 4/4] PCI: tegra194: Add PCI_ENDPOINT dependency
  2026-11-02 11:14 ` [PATCH v3 4/4] PCI: tegra194: Add PCI_ENDPOINT dependency Manikanta Maddireddy
  2026-11-02 11:31   ` sashiko-bot
@ 2026-11-02 15:20   ` Niklas Cassel
  1 sibling, 0 replies; 10+ messages in thread
From: Niklas Cassel @ 2026-11-02 15:20 UTC (permalink / raw)
  To: Manikanta Maddireddy
  Cc: jingoohan1, mani, lpieralisi, kwilczynski, bhelgaas, linux-pci,
	robh, thierry.reding, jonathanh, vidyas, linux-kernel,
	linux-tegra, kernel test robot

Hello Manikanta,

On Mon, Nov 02, 2026 at 04:44:50PM +0530, Manikanta Maddireddy wrote:
> The PERST# assertion handler now calls pci_epc_linkdown() to notify
> Endpoint functions before powering down the controller. This function
> is only declared when CONFIG_PCI_ENDPOINT is enabled and has no stub
> when endpoint support is disabled.
> 
> Add a PCI_ENDPOINT dependency to ensure that the endpoint framework is
> available whenever the Tegra194 PCIe driver is built.
> 
> Fixes: bf644226574e ("PCI: tegra194: Notify Endpoint functions on PERST# assert")

Where is this SHA1? I can't seem to find it in the PCI tree.


> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202610230923.2lf3BsLs-lkp@intel.com/
> Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
> ---
> Changes V2 -> V3:
> - New patch in v3: require PCI_ENDPOINT for pci_epc_linkdown(), added to
>   the PERST# assertion handler, to be declared when the driver is built.
> 
>  drivers/pci/controller/dwc/Kconfig | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig
> index 0a0d56fcf0ac..704134684900 100644
> --- a/drivers/pci/controller/dwc/Kconfig
> +++ b/drivers/pci/controller/dwc/Kconfig
> @@ -245,6 +245,7 @@ config PCIE_TEGRA194_HOST
>  	tristate "NVIDIA Tegra194 (and later) PCIe controller (host mode)"
>  	depends on (ARCH_TEGRA && ARM64) || COMPILE_TEST
>  	depends on PCI_MSI
> +	depends on PCI_ENDPOINT

This looks wrong to me.

If you look at:
include/linux/pci-epc.h

you can see that there are stubs already for e.g.:
pci_epc_init_notify() and pci_epc_deinit_notify().

$ git grep pci_epc_init_notify
drivers/pci/controller/cadence/pcie-cadence-ep.c:       pci_epc_init_notify(epc);
drivers/pci/controller/dwc/pci-dra7xx.c:        pci_epc_init_notify(ep->epc);
drivers/pci/controller/dwc/pci-imx6.c:  pci_epc_init_notify(ep->epc);
drivers/pci/controller/dwc/pci-keystone.c:              pci_epc_init_notify(pci->ep.epc);
drivers/pci/controller/dwc/pci-layerscape-ep.c: pci_epc_init_notify(pci->ep.epc);
drivers/pci/controller/dwc/pcie-artpec6.c:              pci_epc_init_notify(pci->ep.epc);
drivers/pci/controller/dwc/pcie-designware-plat.c:              pci_epc_init_notify(pci->ep.epc);
drivers/pci/controller/dwc/pcie-dw-rockchip.c:  pci_epc_init_notify(rockchip->pci.ep.epc);
drivers/pci/controller/dwc/pcie-keembay.c:              pci_epc_init_notify(pci->ep.epc);
drivers/pci/controller/dwc/pcie-qcom-ep.c:      pci_epc_init_notify(pcie_ep->pci.ep.epc);
drivers/pci/controller/dwc/pcie-rcar-gen4.c:    pci_epc_init_notify(ep->epc);
drivers/pci/controller/dwc/pcie-stm32-ep.c:     pci_epc_init_notify(ep->epc);
drivers/pci/controller/dwc/pcie-tegra194.c:     pci_epc_init_notify(ep->epc);
drivers/pci/controller/dwc/pcie-uniphier-ep.c:  pci_epc_init_notify(priv->pci.ep.epc);
drivers/pci/controller/pcie-rcar-ep.c:  pci_epc_init_notify(epc);
drivers/pci/controller/pcie-rockchip-ep.c:      pci_epc_init_notify(epc);
drivers/pci/endpoint/pci-epc-core.c: * pci_epc_init_notify() - Notify the EPF device that EPC device initialization
drivers/pci/endpoint/pci-epc-core.c:void pci_epc_init_notify(struct pci_epc *epc)
drivers/pci/endpoint/pci-epc-core.c:EXPORT_SYMBOL_GPL(pci_epc_init_notify);
include/linux/pci-epc.h:void pci_epc_init_notify(struct pci_epc *epc);
include/linux/pci-epc.h:static inline void pci_epc_init_notify(struct pci_epc *epc)

I suggest that you just add a stub for pci_epc_linkdown().


Kind regards,
Niklas

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

end of thread, other threads:[~2026-11-02 15:20 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-02 11:14 [PATCH v3 0/4] PCI: dwc: Avoid full EP cleanup on PERST# Manikanta Maddireddy
2026-11-02 11:14 ` [PATCH v3 1/4] PCI: dwc: Reuse Endpoint resources after fundamental reset Manikanta Maddireddy
2026-11-02 11:35   ` sashiko-bot
2026-11-02 11:14 ` [PATCH v3 2/4] PCI: tegra194: Avoid full Endpoint reinit on PERST# Manikanta Maddireddy
2026-11-02 11:41   ` sashiko-bot
2026-11-02 11:14 ` [PATCH v3 3/4] PCI: tegra194: Notify Endpoint functions on PERST# assert Manikanta Maddireddy
2026-11-02 11:38   ` sashiko-bot
2026-11-02 11:14 ` [PATCH v3 4/4] PCI: tegra194: Add PCI_ENDPOINT dependency Manikanta Maddireddy
2026-11-02 11:31   ` sashiko-bot
2026-11-02 15:20   ` Niklas Cassel

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.