[PATCH v3 15/18] PCI: rcar-gen4: Route Root Port PME and bandwidth notifications

From: Koichiro Den

Date: Tue Oct 06 2026 - 04:49:10 EST


The Root Port's PME and link bandwidth notifications are reported in
PCIEINTSTS0 and routed to intreq_pcim_sub, the interrupt shared with the
integrated MSI receiver and the reset requests. Dispatch these
notifications to the virtual Root Port IRQ from the "msi" IRQ handler
after handling any pending iMSI-RX interrupts. This keeps Root Port
service handling out of the path between the reset-request check and
the iMSI-RX status reads. The existing dispatcher rechecks reset requests
before invoking the port services.

Enable the sources only while the Root Port IRQ is unmasked, and clear
the MSI-form latches in irq_ack together with the AER one. On an R-Car
S4 with the GIC ITS as MSI parent, a notification from a link retrain
now reaches the bandwidth controller service, which clears LnkSta.LBMS.

Reviewed-by: Marek Vasut <marek.vasut+renesas@xxxxxxxxxxx>
Signed-off-by: Koichiro Den <den@xxxxxxxxxxxxx>
---
Changes in v3:
- Return IRQ_HANDLED or IRQ_NONE without a ternary operator. (Marek)
- Add Marek's R-b tag, as the change from v2 is trivial.

v2: https://lore.kernel.org/r/20260928165230.3397664-15-den@xxxxxxxxxxxxx/

drivers/pci/controller/dwc/pcie-rcar-gen4.c | 30 ++++++++++++++++-----
1 file changed, 23 insertions(+), 7 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-rcar-gen4.c b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
index db0d5362eaed..040a51f7acb8 100644
--- a/drivers/pci/controller/dwc/pcie-rcar-gen4.c
+++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
@@ -66,6 +66,16 @@
#define AER_RC_ERR_INT BIT(27)
#define RP_AER_MASK (AER_RC_ERR_MSI | AER_RC_ERR_INT)

+/* Root Port notifications routed to intreq_pcim_sub ("msi") */
+#define BW_MGT_MSI BIT(23)
+#define BW_MGT_INT BIT(22)
+#define LINK_AUTO_BW_MSI BIT(21)
+#define LINK_AUTO_BW_INT BIT(20)
+#define PME_MSI BIT(12)
+#define PME_INT BIT(10)
+#define RP_SUB_MASK (BW_MGT_MSI | BW_MGT_INT | LINK_AUTO_BW_MSI | \
+ LINK_AUTO_BW_INT | PME_MSI | PME_INT)
+
/* PCIe DMA Interrupt Status Enable */
#define PCIEDMAINTSTSEN 0x0314
#define PCIEDMAINTSTSEN_INIT GENMASK(15, 0)
@@ -75,7 +85,8 @@

/* PCIe Interrupt Status 0 Clear */
#define PCIEINTSTS0CLR 0x0340
-#define RP_LATCHED_MASK AER_RC_ERR_MSI
+#define RP_LATCHED_MASK (AER_RC_ERR_MSI | BW_MGT_MSI | LINK_AUTO_BW_MSI | \
+ PME_MSI)

/* Port Logic Registers 89 */
#define PRTLGC89 0x0b70
@@ -136,7 +147,7 @@ struct rcar_gen4_pcie {
struct platform_device *pdev;
struct reset_control *perst;
const struct rcar_gen4_pcie_drvdata *drvdata;
- /* intreq_pcim_sub ("msi"): iMSI-RX and other controller notifications */
+ /* intreq_pcim_sub ("msi"): iMSI-RX, reset requests, Root Port PME/bandwidth */
int msi_irq;
struct work_struct link_down_work;
/* Allow Root Port event handling after enumeration and until teardown. */
@@ -579,7 +590,7 @@ static void rcar_gen4_pcie_app_irq_sync_locked(struct rcar_gen4_pcie *rcar)
lockdep_assert_held(&rcar->app_lock);

val = readl(rcar->base + PCIEINTSTS0EN);
- val &= ~(MSI_CTRL_INT | RP_AER_MASK);
+ val &= ~(MSI_CTRL_INT | RP_AER_MASK | RP_SUB_MASK);
/*
* Note that rcar->rp_events_armed is not checked here because device
* removal may still need iMSI-RX interrupts after Root Port events have
@@ -589,6 +600,8 @@ static void rcar_gen4_pcie_app_irq_sync_locked(struct rcar_gen4_pcie *rcar)
val |= MSI_CTRL_INT;
if (rp_events && rcar->rp_irq_enabled && rcar->aer_irq > 0)
val |= RP_AER_MASK;
+ if (rp_events && rcar->rp_irq_enabled)
+ val |= RP_SUB_MASK;
writel(val, rcar->base + PCIEINTSTS0EN);

val = readl(rcar->base + PCIERSTSTSEN);
@@ -737,12 +750,15 @@ static irqreturn_t rcar_gen4_pcie_msi_irq_handler(int irq, void *data)

status = readl(rcar->base + PCIEINTSTS0) &
readl(rcar->base + PCIEINTSTS0EN);
- if (!(status & MSI_CTRL_INT))
- return IRQ_NONE;
+ if (status & MSI_CTRL_INT)
+ dw_handle_msi_irq(&rcar->dw.pp);
+ if (status & RP_SUB_MASK)
+ rcar_gen4_pcie_rp_irq_dispatch(rcar);

- dw_handle_msi_irq(&rcar->dw.pp);
+ if (status & (MSI_CTRL_INT | RP_SUB_MASK))
+ return IRQ_HANDLED;

- return IRQ_HANDLED;
+ return IRQ_NONE;
}

static int rcar_gen4_pcie_msi_irq_init(struct rcar_gen4_pcie *rcar)
--
2.51.0