* [PATCH v3 00/10] PCI: tegra194: Fix EP and Root Port corner cases
@ 2026-11-02 11:27 Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 01/10] PCI: tegra194: Propagate REFCLK select GPIO errors Manikanta Maddireddy
` (9 more replies)
0 siblings, 10 replies; 11+ messages in thread
From: Manikanta Maddireddy @ 2026-11-02 11:27 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 enable the optional core monitor clock
only after link setup and final core clock rate selection.
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 v3:
- Rebase onto the current PCI main-based stack after the DWC register-field
cleanup series. Patches 1-8 and 10 have no code changes from v2.
- Rework patch 9 and rename it to "Enable core monitor clock after link
setup". Set the core clock rate to 500 MHz before enabling it, program
the controller, train the link, select the negotiated-speed core rate,
and then enable the monitor clock.
- Propagate initial and negotiated core rate-setting errors and monitor
enable failures. Keep monitor operations out of the host initialization
callback and DLF retry path, and release the monitor during remove,
suspend and shutdown without a separate reference-state flag.
- Expand patch 9's explanation of the Boot and Power Management Processor
(BPMP) firmware voltage requirement and false frequency-monitor faults
during rate transitions.
- Retain Frank Li's Reviewed-by tags from v2 on unchanged patches 1-8
and 10.
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 reported with v2:
- 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
v2: https://lore.kernel.org/linux-pci/20261021061349.1265704-1-mmaddireddy@nvidia.com/
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: Enable core monitor clock after link setup
PCI: tegra194: Reject zero MSI interrupt number
drivers/pci/controller/dwc/pcie-tegra194.c | 239 +++++++++++++--------
1 file changed, 151 insertions(+), 88 deletions(-)
base-commit: d447e8cfe376cc0cc4db8266d01356d0b3ebb695
--
2.34.1
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v3 01/10] PCI: tegra194: Propagate REFCLK select GPIO errors
2026-11-02 11:27 [PATCH v3 00/10] PCI: tegra194: Fix EP and Root Port corner cases Manikanta Maddireddy
@ 2026-11-02 11:27 ` Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 02/10] PCI: tegra194: Check core reset deassertion Manikanta Maddireddy
` (8 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Manikanta Maddireddy @ 2026-11-02 11:27 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, Frank Li
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 V2 -> V3: None apart from rebasing.
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 62bbfcefe6fe..4490627a539a 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -1207,18 +1207,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] 11+ messages in thread
* [PATCH v3 02/10] PCI: tegra194: Check core reset deassertion
2026-11-02 11:27 [PATCH v3 00/10] PCI: tegra194: Fix EP and Root Port corner cases Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 01/10] PCI: tegra194: Propagate REFCLK select GPIO errors Manikanta Maddireddy
@ 2026-11-02 11:27 ` Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 03/10] PCI: tegra194: Fix Endpoint PERST# IRQ suspend race Manikanta Maddireddy
` (7 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Manikanta Maddireddy @ 2026-11-02 11:27 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, Frank Li
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 V2 -> V3: None apart from rebasing.
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 4490627a539a..d504d7cd3c49 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -955,6 +955,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) {
@@ -1010,7 +1011,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);
@@ -1456,10 +1462,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:
@@ -1854,7 +1866,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);
@@ -1928,6 +1944,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] 11+ messages in thread
* [PATCH v3 03/10] PCI: tegra194: Fix Endpoint PERST# IRQ suspend race
2026-11-02 11:27 [PATCH v3 00/10] PCI: tegra194: Fix EP and Root Port corner cases Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 01/10] PCI: tegra194: Propagate REFCLK select GPIO errors Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 02/10] PCI: tegra194: Check core reset deassertion Manikanta Maddireddy
@ 2026-11-02 11:27 ` Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 04/10] PCI: tegra194: Do not skip no-link Root Port remove cleanup Manikanta Maddireddy
` (6 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Manikanta Maddireddy @ 2026-11-02 11:27 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, Frank Li
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 V2 -> V3: None apart from rebasing.
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 d504d7cd3c49..7560422c5953 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -2375,19 +2375,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);
@@ -2463,10 +2474,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;
@@ -2570,10 +2579,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 = {
@@ -2582,7 +2592,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] 11+ messages in thread
* [PATCH v3 04/10] PCI: tegra194: Do not skip no-link Root Port remove cleanup
2026-11-02 11:27 [PATCH v3 00/10] PCI: tegra194: Fix EP and Root Port corner cases Manikanta Maddireddy
` (2 preceding siblings ...)
2026-11-02 11:27 ` [PATCH v3 03/10] PCI: tegra194: Fix Endpoint PERST# IRQ suspend race Manikanta Maddireddy
@ 2026-11-02 11:27 ` Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 05/10] PCI: tegra194: Check for 16 GT/s capability before programming Manikanta Maddireddy
` (5 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Manikanta Maddireddy @ 2026-11-02 11:27 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, Frank Li
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 V2 -> V3: None apart from rebasing.
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 7560422c5953..0027c0adc7a1 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -2353,19 +2353,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] 11+ messages in thread
* [PATCH v3 05/10] PCI: tegra194: Check for 16 GT/s capability before programming
2026-11-02 11:27 [PATCH v3 00/10] PCI: tegra194: Fix EP and Root Port corner cases Manikanta Maddireddy
` (3 preceding siblings ...)
2026-11-02 11:27 ` [PATCH v3 04/10] PCI: tegra194: Do not skip no-link Root Port remove cleanup Manikanta Maddireddy
@ 2026-11-02 11:27 ` Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 06/10] PCI: tegra194: Check for L1SS " Manikanta Maddireddy
` (4 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Manikanta Maddireddy @ 2026-11-02 11:27 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, Frank Li
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 V2 -> V3: None apart from rebasing.
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 0027c0adc7a1..4926fea2ee05 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -841,7 +841,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++) {
@@ -852,15 +856,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] 11+ messages in thread
* [PATCH v3 06/10] PCI: tegra194: Check for L1SS capability before programming
2026-11-02 11:27 [PATCH v3 00/10] PCI: tegra194: Fix EP and Root Port corner cases Manikanta Maddireddy
` (4 preceding siblings ...)
2026-11-02 11:27 ` [PATCH v3 05/10] PCI: tegra194: Check for 16 GT/s capability before programming Manikanta Maddireddy
@ 2026-11-02 11:27 ` Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 07/10] PCI: tegra194: Always disable Tegra234 Endpoint L1.2 Manikanta Maddireddy
` (3 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Manikanta Maddireddy @ 2026-11-02 11:27 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, Frank Li
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 V2 -> V3: None apart from rebasing.
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 4926fea2ee05..c1b666833754 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -674,37 +674,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 */
@@ -728,8 +737,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] 11+ messages in thread
* [PATCH v3 07/10] PCI: tegra194: Always disable Tegra234 Endpoint L1.2
2026-11-02 11:27 [PATCH v3 00/10] PCI: tegra194: Fix EP and Root Port corner cases Manikanta Maddireddy
` (5 preceding siblings ...)
2026-11-02 11:27 ` [PATCH v3 06/10] PCI: tegra194: Check for L1SS " Manikanta Maddireddy
@ 2026-11-02 11:27 ` Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 08/10] PCI: tegra194: Guard Endpoint PLL-off error path Manikanta Maddireddy
` (2 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Manikanta Maddireddy @ 2026-11-02 11:27 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, Frank Li
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 V2 -> V3: None apart from rebasing.
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 c1b666833754..0ae7adc16054 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -612,6 +612,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)
{
@@ -695,25 +722,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 */
@@ -1904,6 +1912,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] 11+ messages in thread
* [PATCH v3 08/10] PCI: tegra194: Guard Endpoint PLL-off error path
2026-11-02 11:27 [PATCH v3 00/10] PCI: tegra194: Fix EP and Root Port corner cases Manikanta Maddireddy
` (6 preceding siblings ...)
2026-11-02 11:27 ` [PATCH v3 07/10] PCI: tegra194: Always disable Tegra234 Endpoint L1.2 Manikanta Maddireddy
@ 2026-11-02 11:27 ` Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 09/10] PCI: tegra194: Enable core monitor clock after link setup Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 10/10] PCI: tegra194: Reject zero MSI interrupt number Manikanta Maddireddy
9 siblings, 0 replies; 11+ messages in thread
From: Manikanta Maddireddy @ 2026-11-02 11:27 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, Frank Li
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 V2 -> V3: None apart from rebasing.
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 0ae7adc16054..e08d99efd616 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -1974,7 +1974,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] 11+ messages in thread
* [PATCH v3 09/10] PCI: tegra194: Enable core monitor clock after link setup
2026-11-02 11:27 [PATCH v3 00/10] PCI: tegra194: Fix EP and Root Port corner cases Manikanta Maddireddy
` (7 preceding siblings ...)
2026-11-02 11:27 ` [PATCH v3 08/10] PCI: tegra194: Guard Endpoint PLL-off error path Manikanta Maddireddy
@ 2026-11-02 11:27 ` Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 10/10] PCI: tegra194: Reject zero MSI interrupt number Manikanta Maddireddy
9 siblings, 0 replies; 11+ messages in thread
From: Manikanta Maddireddy @ 2026-11-02 11:27 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
Commit a86ca8698c88 ("PCI: tegra194: Add core monitor clock support")
enables the monitor clock in tegra_pcie_dw_host_init(), before link
training completes and the core clock rate is adjusted for the negotiated
speed. Monitoring during these transitions can cause false frequency
monitor faults.
The existing initialization also enables the core clock before requesting
its initial rate. Boot and Power Management Processor (BPMP) firmware uses
the requested rate to determine the voltage requirement, so enabling the
clock first can leave a window where the voltage requirement does not
cover the rate needed during link training.
Monitor clock ownership is also spread across the host initialization
callback, DLF retry and teardown paths. Monitor enable failures are only
logged, while some later initialization failures can unconfigure the
controller without releasing the acquired monitor clock reference.
Use the following sequence:
1. Set the core clock rate to 500 MHz, the highest supported rate.
2. Enable the core clock only.
3. Program the PCIe registers.
4. Train the PCIe link to the target speed.
5. Set the core clock rate for the negotiated link speed.
6. Enable the monitor clock.
Requesting 500 MHz before enabling core establishes the voltage requirement
for the highest possible training speed. Once training completes, reduce
the requested rate as appropriate for the negotiated speed.
The monitor clock is a virtual clock controlling the PCIe frequency
monitor. Its rate must not be programmed separately. Enable it only after
the final core rate has been selected, avoiding monitoring faults during
configuration and training.
Move the initial core rate request into controller configuration and
propagate rate-setting errors. Enable the monitor clock after successful
Root Port initialization and at the end of resume, propagating enable
failures. Keep monitor clock operations out of the host initialization
callback and DLF retry path.
Release the monitor clock during remove, suspend and shutdown. Failures
before monitor enable unwind the controller without disabling an
unacquired monitor clock reference.
Fixes: a86ca8698c88 ("PCI: tegra194: Add core monitor clock support")
Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
---
Changes V2 -> V3:
- Rename the patch to "Enable core monitor clock after link setup".
- Request the 500 MHz core rate before enabling core so BPMP firmware
establishes the voltage requirement before link training.
- Keep the monitor disabled through register setup, link training and
negotiated core rate selection; enable it after Root Port initialization
and at the end of resume.
- Return core rate-setting errors and monitor enable failures.
- Remove the reference-state flag and common monitor-disable helper;
balance monitor operations in remove, suspend and shutdown, keeping
host initialization and DLF retry free of monitor-clock operations.
- Explain the required sequencing and the risk of false frequency-monitor
faults during clock-rate transitions.
Changes V1 -> V2: None
drivers/pci/controller/dwc/pcie-tegra194.c | 51 +++++++++++++++-------
1 file changed, 36 insertions(+), 15 deletions(-)
diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
index e08d99efd616..981cff740cd2 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -305,10 +305,11 @@ static inline u32 appl_readl(struct tegra_pcie_dw *pcie, const u32 reg)
return readl_relaxed(pcie->appl_base + reg);
}
-static void tegra_pcie_icc_set(struct tegra_pcie_dw *pcie)
+static int tegra_pcie_icc_set(struct tegra_pcie_dw *pcie)
{
struct dw_pcie *pci = &pcie->pci;
u32 val, speed, width;
+ int ret;
val = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKSTA);
@@ -323,7 +324,13 @@ static void tegra_pcie_icc_set(struct tegra_pcie_dw *pcie)
if (speed >= ARRAY_SIZE(pcie_gen_freq))
speed = 0;
- clk_set_rate(pcie->core_clk, pcie_gen_freq[speed]);
+ ret = clk_set_rate(pcie->core_clk, pcie_gen_freq[speed]);
+ if (ret) {
+ dev_err(pcie->dev, "Failed to set core clock rate: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
}
static void apply_bad_link_workaround(struct dw_pcie_rp *pp)
@@ -965,10 +972,6 @@ static int tegra_pcie_dw_host_init(struct dw_pcie_rp *pp)
dw_pcie_writel_dbi(pci, CFG_TIMER_CTRL_MAX_FUNC_NUM_OFF, val);
}
- 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");
-
return 0;
}
@@ -1045,20 +1048,19 @@ static int tegra_pcie_dw_start_link(struct dw_pcie *pci)
val &= ~PCI_DLF_EXCHANGE_ENABLE;
dw_pcie_writel_dbi(pci, offset + PCI_DLF_CAP, val);
- /*
- * core_clk_m is enabled as part of host_init callback in
- * 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);
+ ret = tegra_pcie_dw_host_init(pp);
+ if (ret)
+ return ret;
+
dw_pcie_setup_rc(pp);
retry = false;
goto retry_link;
}
- tegra_pcie_icc_set(pcie);
+ ret = tegra_pcie_icc_set(pcie);
+ if (ret)
+ return ret;
tegra_pcie_enable_interrupts(pp);
@@ -1413,6 +1415,12 @@ static int tegra_pcie_config_controller(struct tegra_pcie_dw *pcie,
goto fail_reg_en;
}
+ ret = clk_set_rate(pcie->core_clk, GEN4_CORE_CLK_FREQ);
+ if (ret) {
+ dev_err(pcie->dev, "Failed to set initial core clock rate: %d\n", ret);
+ goto fail_core_clk;
+ }
+
ret = clk_prepare_enable(pcie->core_clk);
if (ret) {
dev_err(pcie->dev, "Failed to enable core clock: %d\n", ret);
@@ -1654,7 +1662,6 @@ 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);
dw_pcie_host_deinit(&pcie->pci.pp);
tegra_pcie_dw_pme_turnoff(pcie);
tegra_pcie_unconfig_controller(pcie);
@@ -1692,6 +1699,12 @@ static int tegra_pcie_config_rp(struct tegra_pcie_dw *pcie)
goto fail_host_init;
}
+ ret = clk_prepare_enable(pcie->core_clk_m);
+ if (ret) {
+ dev_err(dev, "Failed to enable core monitor clock: %d\n", ret);
+ goto fail_host_init;
+ }
+
init_debugfs(pcie);
return ret;
@@ -2379,6 +2392,7 @@ static void tegra_pcie_dw_remove(struct platform_device *pdev)
if (pcie->of_data->mode == DW_PCIE_RC_TYPE) {
if (pcie->link_state) {
debugfs_remove_recursive(pcie->debugfs);
+ clk_disable_unprepare(pcie->core_clk_m);
tegra_pcie_deinit_controller(pcie);
pm_runtime_put_sync(pcie->dev);
pm_runtime_disable(pcie->dev);
@@ -2486,6 +2500,12 @@ static int tegra_pcie_dw_resume_noirq(struct device *dev)
if (ret < 0)
goto fail_host_init;
+ ret = clk_prepare_enable(pcie->core_clk_m);
+ if (ret) {
+ dev_err(dev, "Failed to enable core monitor clock: %d\n", ret);
+ goto fail_host_init;
+ }
+
return 0;
fail_host_init:
@@ -2530,6 +2550,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]);
+ clk_disable_unprepare(pcie->core_clk_m);
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] 11+ messages in thread
* [PATCH v3 10/10] PCI: tegra194: Reject zero MSI interrupt number
2026-11-02 11:27 [PATCH v3 00/10] PCI: tegra194: Fix EP and Root Port corner cases Manikanta Maddireddy
` (8 preceding siblings ...)
2026-11-02 11:27 ` [PATCH v3 09/10] PCI: tegra194: Enable core monitor clock after link setup Manikanta Maddireddy
@ 2026-11-02 11:27 ` Manikanta Maddireddy
9 siblings, 0 replies; 11+ messages in thread
From: Manikanta Maddireddy @ 2026-11-02 11:27 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, Frank Li
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 V2 -> V3: None apart from rebasing.
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 981cff740cd2..72158fc5c639 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -2021,7 +2021,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] 11+ messages in thread
end of thread, other threads:[~2026-11-02 11:28 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-02 11:27 [PATCH v3 00/10] PCI: tegra194: Fix EP and Root Port corner cases Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 01/10] PCI: tegra194: Propagate REFCLK select GPIO errors Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 02/10] PCI: tegra194: Check core reset deassertion Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 03/10] PCI: tegra194: Fix Endpoint PERST# IRQ suspend race Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 04/10] PCI: tegra194: Do not skip no-link Root Port remove cleanup Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 05/10] PCI: tegra194: Check for 16 GT/s capability before programming Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 06/10] PCI: tegra194: Check for L1SS " Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 07/10] PCI: tegra194: Always disable Tegra234 Endpoint L1.2 Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 08/10] PCI: tegra194: Guard Endpoint PLL-off error path Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 09/10] PCI: tegra194: Enable core monitor clock after link setup Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 10/10] PCI: tegra194: Reject zero MSI interrupt number Manikanta Maddireddy
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®