* [PATCH v2 0/2] pci: AMD: Add Versal2 CPM6 PCIe host controller support
@ 2026-07-28 20:20 Sai Krishna Musham
2026-07-28 20:20 ` [PATCH v2 1/2] dt-bindings: pci: Add CPM6 support to AMD MDB PCIe binding Sai Krishna Musham
2026-07-28 20:20 ` [PATCH v2 2/2] pci: AMD: Add CPM6 host controller support to AMD MDB PCIe driver Sai Krishna Musham
0 siblings, 2 replies; 5+ messages in thread
From: Sai Krishna Musham @ 2026-07-28 20:20 UTC (permalink / raw)
To: bhelgaas, lpieralisi, kw, mani, robh, krzk+dt, conor+dt, cassel
Cc: linux-pci, devicetree, linux-kernel, michal.simek,
bharat.kumar.gogada, thippeswamy.havalige, sai.krishna.musham,
pranav.sanwal
Add support for the AMD Versal2 CPM6 PCIe host controller to the
AMD MDB PCIe driver.
Update the device-tree bindings, and add the CPM6 specific driver register
layout and interrupt handling while preserving MDB5 behavior.
Sai Krishna Musham (2):
dt-bindings: pci: Add CPM6 support to AMD MDB PCIe binding
pci: AMD: Add CPM6 host controller support to AMD MDB PCIe driver
.../bindings/pci/amd,versal2-mdb-host.yaml | 111 +++++-
.../devicetree/bindings/pci/snps,dw-pcie.yaml | 2 +
drivers/pci/controller/dwc/pcie-amd-mdb.c | 351 +++++++++++++++---
3 files changed, 407 insertions(+), 57 deletions(-)
base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
--
2.44.4
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 1/2] dt-bindings: pci: Add CPM6 support to AMD MDB PCIe binding
2026-07-28 20:20 [PATCH v2 0/2] pci: AMD: Add Versal2 CPM6 PCIe host controller support Sai Krishna Musham
@ 2026-07-28 20:20 ` Sai Krishna Musham
2026-07-28 20:26 ` sashiko-bot
2026-07-28 20:20 ` [PATCH v2 2/2] pci: AMD: Add CPM6 host controller support to AMD MDB PCIe driver Sai Krishna Musham
1 sibling, 1 reply; 5+ messages in thread
From: Sai Krishna Musham @ 2026-07-28 20:20 UTC (permalink / raw)
To: bhelgaas, lpieralisi, kw, mani, robh, krzk+dt, conor+dt, cassel
Cc: linux-pci, devicetree, linux-kernel, michal.simek,
bharat.kumar.gogada, thippeswamy.havalige, sai.krishna.musham,
pranav.sanwal
The AMD CPM6 PCIe controller is based on the Synopsys DesignWare PCIe IP.
Add "intr" to snps,dw-pcie.yaml vendor-specific reg-names for the
per-controller interrupt register region used by CPM6.
Update amd,versal2-mdb-host.yaml with separate register definitions:
- MDB5: 4 regions (slcr, config, dbi, atu)
- CPM6: 5 regions (slcr, config, dbi, atu, intr)
Signed-off-by: Sai Krishna Musham <sai.krishna.musham@amd.com>
---
Changes in v2:
- Update the CPM6 device tree binding and example.
v1 https://lore.kernel.org/all/20260402180006.486229-2-sai.krishna.musham@amd.com/
---
.../bindings/pci/amd,versal2-mdb-host.yaml | 111 ++++++++++++++++--
.../devicetree/bindings/pci/snps,dw-pcie.yaml | 2 +
2 files changed, 102 insertions(+), 11 deletions(-)
diff --git a/Documentation/devicetree/bindings/pci/amd,versal2-mdb-host.yaml b/Documentation/devicetree/bindings/pci/amd,versal2-mdb-host.yaml
index 406c15e1dee1..d22de24b41ca 100644
--- a/Documentation/devicetree/bindings/pci/amd,versal2-mdb-host.yaml
+++ b/Documentation/devicetree/bindings/pci/amd,versal2-mdb-host.yaml
@@ -12,24 +12,65 @@ maintainers:
allOf:
- $ref: /schemas/pci/pci-host-bridge.yaml#
- $ref: /schemas/pci/snps,dw-pcie.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: amd,versal2-mdb-host
+ then:
+ properties:
+ reg:
+ items:
+ - description: MDB System Level Control and Status Register (SLCR) Base
+ - description: configuration region
+ - description: data bus interface
+ - description: address translation unit register
+ reg-names:
+ items:
+ - const: slcr
+ - const: config
+ - const: dbi
+ - const: atu
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - amd,versal2-cpm6-host
+ - amd,versal2-cpm6-host1
+ then:
+ properties:
+ reg:
+ minItems: 4
+ items:
+ - description: MDB System Level Control and Status Register (SLCR) Base
+ - description: configuration region
+ - description: data bus interface
+ - description: address translation unit register
+ - description: CPM6 PCIe error and event interrupt registers
+ reg-names:
+ minItems: 4
+ items:
+ - const: slcr
+ - const: config
+ - const: dbi
+ - const: atu
+ - const: intr
properties:
compatible:
- const: amd,versal2-mdb-host
+ enum:
+ - amd,versal2-mdb-host
+ - amd,versal2-cpm6-host
+ - amd,versal2-cpm6-host1
reg:
- items:
- - description: MDB System Level Control and Status Register (SLCR) Base
- - description: configuration region
- - description: data bus interface
- - description: address translation unit register
+ minItems: 4
+ maxItems: 5
reg-names:
- items:
- - const: slcr
- - const: config
- - const: dbi
- - const: atu
+ minItems: 4
+ maxItems: 5
ranges:
maxItems: 2
@@ -141,3 +182,51 @@ examples:
};
};
};
+
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/gpio/gpio.h>
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ pcie@fcdd0000 {
+ compatible = "amd,versal2-cpm6-host";
+ reg = <0x0 0xfcdd0000 0x0 0x1000>,
+ <0x6 0x100000 0x0 0xff00000>,
+ <0x6 0x0 0x0 0x100000>,
+ <0x0 0xfc280000 0x0 0x4000>,
+ <0x0 0xfc840000 0x0 0x1000>;
+ reg-names = "slcr", "config", "dbi", "atu", "intr";
+ ranges = <0x2000000 0x00 0xe0000000 0x00 0xe0000000 0x00 0x8000000>,
+ <0x43000000 0x80 0x00 0x80 0x00 0x20 0x00>;
+ interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pcie_intc_1 0>,
+ <0 0 0 2 &pcie_intc_1 1>,
+ <0 0 0 3 &pcie_intc_1 2>,
+ <0 0 0 4 &pcie_intc_1 3>;
+ msi-map = <0x0 &gic_its 0x00 0x10000>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ device_type = "pci";
+
+ pcie@0,0 {
+ device_type = "pci";
+ reg = <0x0 0x0 0x0 0x0 0x0>;
+ reset-gpios = <&gpio1 40 GPIO_ACTIVE_LOW>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges;
+ };
+
+ pcie_intc_1: interrupt-controller {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml b/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
index b3216141881c..21f86609ddb6 100644
--- a/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
@@ -117,6 +117,8 @@ properties:
enum: [ ecam ]
- description: AMD MDB PCIe SLCR region
const: slcr
+ - description: AMD CPM6 PCIe error and event interrupt registers
+ const: intr
allOf:
- contains:
enum: [ dbi, ctrl ]
--
2.44.4
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 2/2] pci: AMD: Add CPM6 host controller support to AMD MDB PCIe driver
2026-07-28 20:20 [PATCH v2 0/2] pci: AMD: Add Versal2 CPM6 PCIe host controller support Sai Krishna Musham
2026-07-28 20:20 ` [PATCH v2 1/2] dt-bindings: pci: Add CPM6 support to AMD MDB PCIe binding Sai Krishna Musham
@ 2026-07-28 20:20 ` Sai Krishna Musham
2026-07-28 20:33 ` sashiko-bot
1 sibling, 1 reply; 5+ messages in thread
From: Sai Krishna Musham @ 2026-07-28 20:20 UTC (permalink / raw)
To: bhelgaas, lpieralisi, kw, mani, robh, krzk+dt, conor+dt, cassel
Cc: linux-pci, devicetree, linux-kernel, michal.simek,
bharat.kumar.gogada, thippeswamy.havalige, sai.krishna.musham,
pranav.sanwal
Extend the AMD MDB PCIe driver to support AMD Versal2 CPM6 variants
(amd,versal2-cpm6-host and amd,versal2-cpm6-host1). Like MDB5, CPM6 is
based on the Synopsys DesignWare PCIe controller and reuses the existing
DesignWare host support; only the interrupt architecture differs:
- The per-controller interrupt registers (MISC_EVENT, PCIE_ERR) are in a
dedicated "intr" region instead of the shared SLCR
- The aggregation layer (MERGED, PS_MISC) is shared and sticky; it
requires an explicit W1C-clear after servicing to prevent IRQ storms
- The completion timeout is reported via PCIE_ERR instead of MISC_EVENT
Add variant-specific register layout and implement aggregator clearing
that, after every interrupt pass, clears this host's contribution from
the MERGED register and the corresponding bit in the PS_MISC severity
register.
Signed-off-by: Sai Krishna Musham <sai.krishna.musham@amd.com>
---
Changes in v2:
- Add CPM6 host controller interrupt support.
v1 https://lore.kernel.org/all/20260402180006.486229-3-sai.krishna.musham@amd.com/
---
drivers/pci/controller/dwc/pcie-amd-mdb.c | 351 +++++++++++++++++++---
1 file changed, 305 insertions(+), 46 deletions(-)
diff --git a/drivers/pci/controller/dwc/pcie-amd-mdb.c b/drivers/pci/controller/dwc/pcie-amd-mdb.c
index dee295f281a3..dbf36ce9902c 100644
--- a/drivers/pci/controller/dwc/pcie-amd-mdb.c
+++ b/drivers/pci/controller/dwc/pcie-amd-mdb.c
@@ -21,6 +21,23 @@
#include "../../pci.h"
#include "pcie-designware.h"
+/*
+ * On CPM6 the per-controller PCIe interrupt registers (MISC_EVENT and
+ * PCIE_ERR) live in a dedicated region ("intr"), separate from the CPM SLCR
+ * region ("slcr") that holds the MERGED and PS severity registers they feed
+ * into. Each has a sticky W1C STATUS, a read-only MASK, and write-1
+ * ENABLE/DISABLE register.
+ */
+#define AMD_CPM6_PCIE_ERR_STATUS 0x500
+#define AMD_CPM6_PCIE_ERR_MASK 0x504
+#define AMD_CPM6_PCIE_ERR_ENABLE 0x508
+#define AMD_CPM6_PCIE_ERR_DISABLE 0x50C
+
+#define AMD_CPM6_MISC_EVENT_STATUS 0x514
+#define AMD_CPM6_MISC_EVENT_MASK 0x518
+#define AMD_CPM6_MISC_EVENT_ENABLE 0x51C
+#define AMD_CPM6_MISC_EVENT_DISABLE 0x520
+
#define AMD_MDB_TLP_IR_STATUS_MISC 0x4C0
#define AMD_MDB_TLP_IR_MASK_MISC 0x4C4
#define AMD_MDB_TLP_IR_ENABLE_MISC 0x4C8
@@ -30,7 +47,22 @@
#define AMD_MDB_PCIE_INTR_INTX_ASSERT(x) BIT((x) * 2)
-/* Interrupt registers definitions. */
+#define AMD_CPM6_MERGED_STATUS 0x648
+
+/* MERGED input bits for the MISC_EVENT/PCIE_ERR sources this driver handles. */
+#define AMD_CPM6_MERGED_PCIE_ERR_HOST0 13
+#define AMD_CPM6_MERGED_MISC_EVENT_HOST0 14
+#define AMD_CPM6_MERGED_PCIE_ERR_HOST1 16
+#define AMD_CPM6_MERGED_MISC_EVENT_HOST1 17
+
+/*
+ * The PS_MISC severity register feeds the misc/OR GIC line. The MERGED
+ * aggregator appears as bit 21 within it.
+ */
+#define AMD_CPM6_PS_MISC_IR_STATUS 0x340
+#define AMD_CPM6_PS_IR_MERGED BIT(21)
+
+/* MDB5 interrupt register definitions. */
#define AMD_MDB_PCIE_INTR_CMPL_TIMEOUT 15
#define AMD_MDB_PCIE_INTR_INTX 16
#define AMD_MDB_PCIE_INTR_PM_PME_RCVD 24
@@ -39,6 +71,9 @@
#define AMD_MDB_PCIE_INTR_NONFATAL 27
#define AMD_MDB_PCIE_INTR_FATAL 28
+/* Completion timeout lives in PCIE_ERR_STATUS; give it a dedicated hwirq. */
+#define AMD_CPM6_PCIE_ERR_CMPL_RADM 20
+
#define IMR(x) BIT(AMD_MDB_PCIE_INTR_ ##x)
#define AMD_MDB_PCIE_IMR_ALL_MASK \
( \
@@ -51,10 +86,58 @@
AMD_MDB_TLP_PCIE_INTX_MASK \
)
+/* CPM6 hwirq mapping (hwirq == MISC_EVENT status bit). */
+#define AMD_CPM6_PCIE_INTR_FATAL 17
+#define AMD_CPM6_PCIE_INTR_NONFATAL 18
+#define AMD_CPM6_PCIE_INTR_MISC_CORRECTABLE 19
+#define AMD_CPM6_PCIE_INTR_PME_TO_ACK_RCVD 20
+#define AMD_CPM6_PCIE_INTR_PM_PME_RCVD 21
+#define AMD_CPM6_PCIE_INTR_INTX 22
+
+#define AMD_CPM6_MISC_EVENT_MASK_ALL \
+ ( \
+ BIT(AMD_CPM6_PCIE_INTR_FATAL) | \
+ BIT(AMD_CPM6_PCIE_INTR_NONFATAL) | \
+ BIT(AMD_CPM6_PCIE_INTR_MISC_CORRECTABLE) |\
+ BIT(AMD_CPM6_PCIE_INTR_PME_TO_ACK_RCVD) |\
+ BIT(AMD_CPM6_PCIE_INTR_PM_PME_RCVD) | \
+ BIT(AMD_CPM6_PCIE_INTR_INTX) \
+ )
+
+/* Sources handled in the PCIE_ERR register. */
+#define AMD_CPM6_PCIE_ERR_MASK_ALL BIT(AMD_CPM6_PCIE_ERR_CMPL_RADM)
+
+enum amd_mdb_pcie_version {
+ MDB5,
+ CPM6,
+ CPM6_HOST1,
+};
+
+struct amd_mdb_intr_cause {
+ const char *sym;
+ const char *str;
+};
+
+struct amd_mdb_pcie_variant {
+ enum amd_mdb_pcie_version version;
+ u32 misc_status_reg;
+ u32 misc_mask_reg;
+ u32 misc_enable_reg;
+ u32 misc_disable_reg;
+ u32 misc_mask_all;
+ u32 intx_hwirq;
+ u32 intx_mask;
+};
+
/**
* struct amd_mdb_pcie - PCIe port information
* @pci: DesignWare PCIe controller structure
* @slcr: MDB System Level Control and Status Register (SLCR) base
+ * @intr_base: Per-controller interrupt register base. On CPM6 this maps the
+ * "intr" region holding the MISC_EVENT/PCIE_ERR registers; on MDB5
+ * the interrupt registers live in the SLCR block, so it aliases
+ * @slcr.
+ * @variant: Interrupt layout data for the matched platform compatible
* @intx_domain: INTx IRQ domain pointer
* @mdb_domain: MDB IRQ domain pointer
* @perst_gpio: GPIO descriptor for PERST# signal handling
@@ -63,12 +146,62 @@
struct amd_mdb_pcie {
struct dw_pcie pci;
void __iomem *slcr;
+ void __iomem *intr_base;
+ const struct amd_mdb_pcie_variant *variant;
struct irq_domain *intx_domain;
struct irq_domain *mdb_domain;
struct gpio_desc *perst_gpio;
int intx_irq;
};
+#define _IC(x, s)[AMD_MDB_PCIE_INTR_ ## x] = { __stringify(x), s }
+
+static const struct amd_mdb_intr_cause mdb5_intr_cause[32] = {
+ _IC(CMPL_TIMEOUT, "Completion timeout"),
+ _IC(PM_PME_RCVD, "PM_PME message received"),
+ _IC(PME_TO_ACK_RCVD, "PME_TO_ACK message received"),
+ _IC(MISC_CORRECTABLE, "Correctable error message"),
+ _IC(NONFATAL, "Non fatal error message"),
+ _IC(FATAL, "Fatal error message"),
+};
+
+#define _IC6(x, s)[AMD_CPM6_PCIE_INTR_ ## x] = { __stringify(x), s }
+
+static const struct amd_mdb_intr_cause cpm6_intr_cause[32] = {
+ _IC6(PM_PME_RCVD, "PM_PME message received"),
+ _IC6(PME_TO_ACK_RCVD, "PME_TO_ACK message received"),
+ _IC6(MISC_CORRECTABLE, "Correctable error message"),
+ _IC6(NONFATAL, "Non fatal error message"),
+ _IC6(FATAL, "Fatal error message"),
+};
+
+static void amd_mdb_pcie_clear_aggregators(struct amd_mdb_pcie *pcie)
+{
+ u32 merged_mask;
+
+ if (pcie->variant->version == MDB5)
+ return;
+
+ /*
+ * Clear this host's serviced contributions (MISC_EVENT0 and PCIE_ERR)
+ * from MERGED.
+ */
+ merged_mask = pcie->variant->version == CPM6 ?
+ BIT(AMD_CPM6_MERGED_MISC_EVENT_HOST0) |
+ BIT(AMD_CPM6_MERGED_PCIE_ERR_HOST0) :
+ BIT(AMD_CPM6_MERGED_MISC_EVENT_HOST1) |
+ BIT(AMD_CPM6_MERGED_PCIE_ERR_HOST1);
+
+ writel_relaxed(merged_mask, pcie->slcr + AMD_CPM6_MERGED_STATUS);
+
+ /*
+ * Clear MERGED in the PS_MISC severity register so the misc GIC line
+ * de-asserts.
+ */
+ writel_relaxed(AMD_CPM6_PS_IR_MERGED,
+ pcie->slcr + AMD_CPM6_PS_MISC_IR_STATUS);
+}
+
static const struct dw_pcie_host_ops amd_mdb_pcie_host_ops = {
};
@@ -81,14 +214,17 @@ static void amd_mdb_intx_irq_mask(struct irq_data *data)
u32 val;
raw_spin_lock_irqsave(&port->lock, flags);
- val = FIELD_PREP(AMD_MDB_TLP_PCIE_INTX_MASK,
- AMD_MDB_PCIE_INTR_INTX_ASSERT(data->hwirq));
+ if (pcie->variant->version == MDB5)
+ val = FIELD_PREP(AMD_MDB_TLP_PCIE_INTX_MASK,
+ AMD_MDB_PCIE_INTR_INTX_ASSERT(data->hwirq));
+ else
+ val = pcie->variant->intx_mask;
/*
* Writing '1' to a bit in AMD_MDB_TLP_IR_DISABLE_MISC disables that
* interrupt, writing '0' has no effect.
*/
- writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_DISABLE_MISC);
+ writel_relaxed(val, pcie->intr_base + pcie->variant->misc_disable_reg);
raw_spin_unlock_irqrestore(&port->lock, flags);
}
@@ -101,14 +237,17 @@ static void amd_mdb_intx_irq_unmask(struct irq_data *data)
u32 val;
raw_spin_lock_irqsave(&port->lock, flags);
- val = FIELD_PREP(AMD_MDB_TLP_PCIE_INTX_MASK,
- AMD_MDB_PCIE_INTR_INTX_ASSERT(data->hwirq));
+ if (pcie->variant->version == MDB5)
+ val = FIELD_PREP(AMD_MDB_TLP_PCIE_INTX_MASK,
+ AMD_MDB_PCIE_INTR_INTX_ASSERT(data->hwirq));
+ else
+ val = pcie->variant->intx_mask;
/*
* Writing '1' to a bit in AMD_MDB_TLP_IR_ENABLE_MISC enables that
* interrupt, writing '0' has no effect.
*/
- writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_ENABLE_MISC);
+ writel_relaxed(val, pcie->intr_base + pcie->variant->misc_enable_reg);
raw_spin_unlock_irqrestore(&port->lock, flags);
}
@@ -148,42 +287,34 @@ static irqreturn_t dw_pcie_rp_intx(int irq, void *args)
unsigned long val;
int i, int_status;
- val = readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC);
- int_status = FIELD_GET(AMD_MDB_TLP_PCIE_INTX_MASK, val);
+ val = readl_relaxed(pcie->intr_base + pcie->variant->misc_status_reg);
- for (i = 0; i < PCI_NUM_INTX; i++) {
- if (int_status & AMD_MDB_PCIE_INTR_INTX_ASSERT(i))
+ if (pcie->variant->version == MDB5) {
+ int_status = FIELD_GET(AMD_MDB_TLP_PCIE_INTX_MASK, val);
+ for (i = 0; i < PCI_NUM_INTX; i++) {
+ if (int_status & AMD_MDB_PCIE_INTR_INTX_ASSERT(i))
+ generic_handle_domain_irq(pcie->intx_domain, i);
+ }
+ } else {
+ /* CPM6 exposes only aggregate INTx indication, not per-line status. */
+ if (!(val & pcie->variant->intx_mask))
+ return IRQ_NONE;
+ for (i = 0; i < PCI_NUM_INTX; i++)
generic_handle_domain_irq(pcie->intx_domain, i);
}
return IRQ_HANDLED;
}
-#define _IC(x, s)[AMD_MDB_PCIE_INTR_ ## x] = { __stringify(x), s }
-
-static const struct {
- const char *sym;
- const char *str;
-} intr_cause[32] = {
- _IC(CMPL_TIMEOUT, "Completion timeout"),
- _IC(PM_PME_RCVD, "PM_PME message received"),
- _IC(PME_TO_ACK_RCVD, "PME_TO_ACK message received"),
- _IC(MISC_CORRECTABLE, "Correctable error message"),
- _IC(NONFATAL, "Non fatal error message"),
- _IC(FATAL, "Fatal error message"),
-};
-
static void amd_mdb_event_irq_mask(struct irq_data *d)
{
struct amd_mdb_pcie *pcie = irq_data_get_irq_chip_data(d);
struct dw_pcie *pci = &pcie->pci;
struct dw_pcie_rp *port = &pci->pp;
unsigned long flags;
- u32 val;
raw_spin_lock_irqsave(&port->lock, flags);
- val = BIT(d->hwirq);
- writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_DISABLE_MISC);
+ writel_relaxed(BIT(d->hwirq), pcie->intr_base + pcie->variant->misc_disable_reg);
raw_spin_unlock_irqrestore(&port->lock, flags);
}
@@ -193,11 +324,9 @@ static void amd_mdb_event_irq_unmask(struct irq_data *d)
struct dw_pcie *pci = &pcie->pci;
struct dw_pcie_rp *port = &pci->pp;
unsigned long flags;
- u32 val;
raw_spin_lock_irqsave(&port->lock, flags);
- val = BIT(d->hwirq);
- writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_ENABLE_MISC);
+ writel_relaxed(BIT(d->hwirq), pcie->intr_base + pcie->variant->misc_enable_reg);
raw_spin_unlock_irqrestore(&port->lock, flags);
}
@@ -226,13 +355,39 @@ static irqreturn_t amd_mdb_pcie_event(int irq, void *args)
{
struct amd_mdb_pcie *pcie = args;
unsigned long val;
+ u32 ev_raw, err;
int i;
- val = readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC);
- val &= ~readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_MASK_MISC);
+ ev_raw = readl_relaxed(pcie->intr_base + pcie->variant->misc_status_reg);
+ val = ev_raw;
+ val &= ~readl_relaxed(pcie->intr_base + pcie->variant->misc_mask_reg);
+
+ if (pcie->variant->version == MDB5) {
+ for_each_set_bit(i, &val, 32)
+ generic_handle_domain_irq(pcie->mdb_domain, i);
+ writel_relaxed(val, pcie->intr_base + pcie->variant->misc_status_reg);
+ return IRQ_HANDLED;
+ }
+
+ val &= pcie->variant->misc_mask_all;
+
for_each_set_bit(i, &val, 32)
generic_handle_domain_irq(pcie->mdb_domain, i);
- writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC);
+
+ /* Clear handled + any unhandled sticky bits to avoid IRQ storms. */
+ writel_relaxed(ev_raw, pcie->intr_base + pcie->variant->misc_status_reg);
+
+ /* On CPM6 the completion timeout is reported via the PCIE_ERR register. */
+ err = readl_relaxed(pcie->intr_base + AMD_CPM6_PCIE_ERR_STATUS);
+ err &= ~readl_relaxed(pcie->intr_base + AMD_CPM6_PCIE_ERR_MASK);
+ err &= AMD_CPM6_PCIE_ERR_MASK_ALL;
+ if (err) {
+ dev_warn(pcie->pci.dev, "Completion timeout\n");
+ writel_relaxed(err, pcie->intr_base + AMD_CPM6_PCIE_ERR_STATUS);
+ }
+
+ /* Aggregation bits are sticky; clear them each pass or the level IRQ re-fires. */
+ amd_mdb_pcie_clear_aggregators(pcie);
return IRQ_HANDLED;
}
@@ -245,29 +400,67 @@ static void amd_mdb_pcie_free_irq_domains(struct amd_mdb_pcie *pcie)
}
if (pcie->mdb_domain) {
+ const struct amd_mdb_intr_cause *intr_cause =
+ pcie->variant->version == MDB5 ?
+ mdb5_intr_cause : cpm6_intr_cause;
+ int i, irq;
+
+ for (i = 0; i < ARRAY_SIZE(mdb5_intr_cause); i++) {
+ if (!intr_cause[i].str)
+ continue;
+ irq = irq_find_mapping(pcie->mdb_domain, i);
+ if (irq) {
+ disable_irq(irq);
+ free_irq(irq, pcie);
+ irq_dispose_mapping(irq);
+ }
+ }
+ irq = irq_find_mapping(pcie->mdb_domain,
+ pcie->variant->intx_hwirq);
+ if (irq) {
+ disable_irq(irq);
+ free_irq(irq, pcie);
+ irq_dispose_mapping(irq);
+ }
+
irq_domain_remove(pcie->mdb_domain);
pcie->mdb_domain = NULL;
}
}
-static int amd_mdb_pcie_init_port(struct amd_mdb_pcie *pcie)
+static void amd_mdb_pcie_init_port(struct amd_mdb_pcie *pcie)
{
- unsigned long val;
+ u32 misc_mask_all;
+ u32 val;
+
+ misc_mask_all = pcie->variant->misc_mask_all;
/* Disable all TLP interrupts. */
- writel_relaxed(AMD_MDB_PCIE_IMR_ALL_MASK,
- pcie->slcr + AMD_MDB_TLP_IR_DISABLE_MISC);
+ writel_relaxed(misc_mask_all,
+ pcie->intr_base + pcie->variant->misc_disable_reg);
+
+ if (pcie->variant->version != MDB5)
+ writel_relaxed(AMD_CPM6_PCIE_ERR_MASK_ALL,
+ pcie->intr_base + AMD_CPM6_PCIE_ERR_DISABLE);
/* Clear pending TLP interrupts. */
- val = readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC);
- val &= AMD_MDB_PCIE_IMR_ALL_MASK;
- writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC);
+ val = readl_relaxed(pcie->intr_base + pcie->variant->misc_status_reg) &
+ misc_mask_all;
+ writel_relaxed(val, pcie->intr_base + pcie->variant->misc_status_reg);
+
+ if (pcie->variant->version != MDB5) {
+ val = readl_relaxed(pcie->intr_base + AMD_CPM6_PCIE_ERR_STATUS) &
+ AMD_CPM6_PCIE_ERR_MASK_ALL;
+ writel_relaxed(val, pcie->intr_base + AMD_CPM6_PCIE_ERR_STATUS);
+ }
/* Enable all TLP interrupts. */
- writel_relaxed(AMD_MDB_PCIE_IMR_ALL_MASK,
- pcie->slcr + AMD_MDB_TLP_IR_ENABLE_MISC);
+ writel_relaxed(misc_mask_all,
+ pcie->intr_base + pcie->variant->misc_enable_reg);
- return 0;
+ if (pcie->variant->version != MDB5)
+ writel_relaxed(AMD_CPM6_PCIE_ERR_MASK_ALL,
+ pcie->intr_base + AMD_CPM6_PCIE_ERR_ENABLE);
}
/**
@@ -327,10 +520,13 @@ static int amd_mdb_pcie_init_irq_domains(struct amd_mdb_pcie *pcie,
static irqreturn_t amd_mdb_pcie_intr_handler(int irq, void *args)
{
struct amd_mdb_pcie *pcie = args;
+ const struct amd_mdb_intr_cause *intr_cause;
struct device *dev;
struct irq_data *d;
dev = pcie->pci.dev;
+ intr_cause = pcie->variant->version == MDB5 ?
+ mdb5_intr_cause : cpm6_intr_cause;
/*
* In the future, error reporting will be hooked to the AER subsystem.
@@ -351,15 +547,19 @@ static int amd_mdb_setup_irq(struct amd_mdb_pcie *pcie,
struct dw_pcie *pci = &pcie->pci;
struct dw_pcie_rp *pp = &pci->pp;
struct device *dev = &pdev->dev;
+ const struct amd_mdb_intr_cause *intr_cause;
int i, irq, err;
+ intr_cause = pcie->variant->version == MDB5 ?
+ mdb5_intr_cause : cpm6_intr_cause;
+
amd_mdb_pcie_init_port(pcie);
pp->irq = platform_get_irq(pdev, 0);
if (pp->irq < 0)
return pp->irq;
- for (i = 0; i < ARRAY_SIZE(intr_cause); i++) {
+ for (i = 0; i < ARRAY_SIZE(mdb5_intr_cause); i++) {
if (!intr_cause[i].str)
continue;
@@ -379,7 +579,7 @@ static int amd_mdb_setup_irq(struct amd_mdb_pcie *pcie,
}
pcie->intx_irq = irq_create_mapping(pcie->mdb_domain,
- AMD_MDB_PCIE_INTR_INTX);
+ pcie->variant->intx_hwirq);
if (!pcie->intx_irq) {
dev_err(dev, "Failed to map INTx interrupt\n");
return -ENXIO;
@@ -439,6 +639,20 @@ static int amd_mdb_add_pcie_port(struct amd_mdb_pcie *pcie,
if (IS_ERR(pcie->slcr))
return PTR_ERR(pcie->slcr);
+ /*
+ * On MDB5 all interrupt registers live in the SLCR block, so the
+ * interrupt-register base simply aliases @slcr. CPM6 moves the
+ * MISC_EVENT/PCIE_ERR registers into a separate per-controller region
+ * mapped by name as "intr".
+ */
+ if (pcie->variant->version == MDB5) {
+ pcie->intr_base = pcie->slcr;
+ } else {
+ pcie->intr_base = devm_platform_ioremap_resource_byname(pdev, "intr");
+ if (IS_ERR(pcie->intr_base))
+ return PTR_ERR(pcie->intr_base);
+ }
+
err = amd_mdb_pcie_init_irq_domains(pcie, pdev);
if (err)
return err;
@@ -483,6 +697,9 @@ static int amd_mdb_pcie_probe(struct platform_device *pdev)
pci = &pcie->pci;
pci->dev = dev;
+ pcie->variant = of_device_get_match_data(dev);
+ if (!pcie->variant)
+ return -EINVAL;
platform_set_drvdata(pdev, pcie);
@@ -514,9 +731,51 @@ static void amd_mdb_pcie_shutdown(struct platform_device *pdev)
gpiod_set_value_cansleep(pcie->perst_gpio, 1);
}
+static const struct amd_mdb_pcie_variant cpm6_host = {
+ .version = CPM6,
+ .misc_status_reg = AMD_CPM6_MISC_EVENT_STATUS,
+ .misc_mask_reg = AMD_CPM6_MISC_EVENT_MASK,
+ .misc_enable_reg = AMD_CPM6_MISC_EVENT_ENABLE,
+ .misc_disable_reg = AMD_CPM6_MISC_EVENT_DISABLE,
+ .misc_mask_all = AMD_CPM6_MISC_EVENT_MASK_ALL,
+ .intx_hwirq = AMD_CPM6_PCIE_INTR_INTX,
+ .intx_mask = BIT(AMD_CPM6_PCIE_INTR_INTX),
+};
+
+static const struct amd_mdb_pcie_variant cpm6_host1 = {
+ .version = CPM6_HOST1,
+ .misc_status_reg = AMD_CPM6_MISC_EVENT_STATUS,
+ .misc_mask_reg = AMD_CPM6_MISC_EVENT_MASK,
+ .misc_enable_reg = AMD_CPM6_MISC_EVENT_ENABLE,
+ .misc_disable_reg = AMD_CPM6_MISC_EVENT_DISABLE,
+ .misc_mask_all = AMD_CPM6_MISC_EVENT_MASK_ALL,
+ .intx_hwirq = AMD_CPM6_PCIE_INTR_INTX,
+ .intx_mask = BIT(AMD_CPM6_PCIE_INTR_INTX),
+};
+
+static const struct amd_mdb_pcie_variant mdb5_host = {
+ .version = MDB5,
+ .misc_status_reg = AMD_MDB_TLP_IR_STATUS_MISC,
+ .misc_mask_reg = AMD_MDB_TLP_IR_MASK_MISC,
+ .misc_enable_reg = AMD_MDB_TLP_IR_ENABLE_MISC,
+ .misc_disable_reg = AMD_MDB_TLP_IR_DISABLE_MISC,
+ .misc_mask_all = AMD_MDB_PCIE_IMR_ALL_MASK,
+ .intx_hwirq = AMD_MDB_PCIE_INTR_INTX,
+ .intx_mask = AMD_MDB_TLP_PCIE_INTX_MASK,
+};
+
static const struct of_device_id amd_mdb_pcie_of_match[] = {
{
.compatible = "amd,versal2-mdb-host",
+ .data = &mdb5_host,
+ },
+ {
+ .compatible = "amd,versal2-cpm6-host",
+ .data = &cpm6_host,
+ },
+ {
+ .compatible = "amd,versal2-cpm6-host1",
+ .data = &cpm6_host1,
},
{},
};
--
2.44.4
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2 1/2] dt-bindings: pci: Add CPM6 support to AMD MDB PCIe binding
2026-07-28 20:20 ` [PATCH v2 1/2] dt-bindings: pci: Add CPM6 support to AMD MDB PCIe binding Sai Krishna Musham
@ 2026-07-28 20:26 ` sashiko-bot
0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-07-28 20:26 UTC (permalink / raw)
To: Sai Krishna Musham; +Cc: robh, conor+dt, devicetree, linux-pci
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The conditional blocks for 'amd,versal2-mdb-host' and 'amd,versal2-cpm6-host' fail to enforce the strict number of register regions, allowing incomplete or invalid device trees to silently pass schema validation.
--
--- Patch [1]: [PATCH v2 1/2] dt-bindings: pci: Add CPM6 support to AMD MDB PCIe binding ---
commit b6d71a08cf4101b94f4ec914fe86d18c5cd2b7fa
Author: Sai Krishna Musham <sai.krishna.musham@amd.com>
dt-bindings: pci: Add CPM6 support to AMD MDB PCIe binding
The AMD CPM6 PCIe controller is based on the Synopsys DesignWare PCIe IP.
This adds "intr" to the vendor-specific reg-names for the per-controller
interrupt register region and updates the amd,versal2-mdb-host.yaml with
separate register definitions for MDB5 and CPM6.
Link: https://lore.kernel.org/all/20260402180006.486229-2-sai.krishna.musham@amd.com/
> diff --git a/Documentation/devicetree/bindings/pci/amd,versal2-mdb-host.yaml b/Documentation/devicetree/bindings/pci/amd,versal2-mdb-host.yaml
> index 406c15e1dee1b..d22de24b41cae 100644
> --- a/Documentation/devicetree/bindings/pci/amd,versal2-mdb-host.yaml
> +++ b/Documentation/devicetree/bindings/pci/amd,versal2-mdb-host.yaml
[ ... ]
> + - if:
> + properties:
> + compatible:
> + contains:
> + const: amd,versal2-mdb-host
> + then:
> + properties:
> + reg:
> + items:
> + - description: MDB System Level Control and Status Register (SLCR) Base
> + - description: configuration region
> + - description: data bus interface
> + - description: address translation unit register
> + reg-names:
> + items:
> + - const: slcr
> + - const: config
> + - const: dbi
> + - const: atu
[Severity: Medium]
Since the global maxItems for reg and reg-names is increased to 5 in this
patch, does this conditional block for amd,versal2-mdb-host need to explicitly
specify maxItems: 4?
Without it, could a device tree with an invalid 5th region silently pass
schema validation for MDB5?
> + - if:
> + properties:
> + compatible:
> + contains:
> + enum:
> + - amd,versal2-cpm6-host
> + - amd,versal2-cpm6-host1
> + then:
> + properties:
> + reg:
> + minItems: 4
> + items:
> + - description: MDB System Level Control and Status Register (SLCR) Base
> + - description: configuration region
> + - description: data bus interface
> + - description: address translation unit register
> + - description: CPM6 PCIe error and event interrupt registers
> + reg-names:
> + minItems: 4
> + items:
> + - const: slcr
> + - const: config
> + - const: dbi
> + - const: atu
> + - const: intr
[Severity: Medium]
Does setting minItems: 4 here inadvertently make the 5th CPM6-specific region
(intr) optional?
If CPM6 always requires all 5 regions, should minItems: 4 be removed so that
validation enforces the full array length?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260728202044.1785986-1-sai.krishna.musham@amd.com?part=1
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2 2/2] pci: AMD: Add CPM6 host controller support to AMD MDB PCIe driver
2026-07-28 20:20 ` [PATCH v2 2/2] pci: AMD: Add CPM6 host controller support to AMD MDB PCIe driver Sai Krishna Musham
@ 2026-07-28 20:33 ` sashiko-bot
0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-07-28 20:33 UTC (permalink / raw)
To: Sai Krishna Musham; +Cc: devicetree, linux-pci, robh, conor+dt
Thank you for your contribution! Sashiko AI review found 8 potential issue(s) to consider:
New issues:
- [High] Double-free and Use-After-Free of devm-managed interrupts on probe failure.
- [High] Masking a single virtual INTx line on CPM6 unconditionally disables the aggregate hardware INTx interrupt, breaking other devices.
- [High] Unhandled bits in `AMD_CPM6_PCIE_ERR_STATUS` are never cleared, leading to an unrecoverable infinite IRQ storm.
- [High] Exclusive ioremap of the shared `slcr` region will cause the second CPM6 host controller to fail probing.
- [High] Uncoordinated W1C clearing of the shared sticky aggregator bit causes lost interrupts for the other host.
Pre-existing issues:
- [High] INTxB, INTxC, and INTxD interrupts on MDB5 are silently dropped because their hardware IRQs are never mapped.
- [High] Use-After-Free of irq_domain triggered by concurrent hardware interrupt during probe error path.
- [High] Clearing sticky W1C status registers at the end of the interrupt handler creates a race condition that loses concurrent edges.
--
--- Patch [2]: [PATCH v2 2/2] pci: AMD: Add CPM6 host controller support to AMD MDB PCIe driver ---
commit 72da33718ab9f6a5d8466cccef118aefc6c26f76
Author: Sai Krishna Musham <sai.krishna.musham@amd.com>
Subject: pci: AMD: Add CPM6 host controller support to AMD MDB PCIe driver
This patch extends the AMD MDB PCIe driver to support AMD Versal2 CPM6
variants. It adds variant-specific register layouts and implements a shared
aggregator clearing mechanism for the new interrupt architecture.
Link: https://lore.kernel.org/all/20260402180006.486229-3-sai.krishna.musham@amd.com/
> diff --git a/drivers/pci/controller/dwc/pcie-amd-mdb.c b/drivers/pci/controller/dwc/pcie-amd-mdb.c
> index dee295f281a30..dbf36ce9902c8 100644
> --- a/drivers/pci/controller/dwc/pcie-amd-mdb.c
> +++ b/drivers/pci/controller/dwc/pcie-amd-mdb.c
[ ... ]
> @@ -148,42 +287,34 @@ static void amd_mdb_pcie_clear_aggregators(struct amd_mdb_pcie *pcie)
> writel_relaxed(merged_mask, pcie->slcr + AMD_CPM6_MERGED_STATUS);
>
> /*
> * Clear MERGED in the PS_MISC severity register so the misc GIC line
> * de-asserts.
> */
> writel_relaxed(AMD_CPM6_PS_IR_MERGED,
> pcie->slcr + AMD_CPM6_PS_MISC_IR_STATUS);
> }
[Severity: High]
Does blindly clearing the shared sticky aggregator bit drop concurrent
interrupts from the other host controller?
The commit mentions this aggregator is shared between controllers. If Host 0
clears this W1C bit while Host 1 has a pending unserviced interrupt in the
MERGED register, Host 1's edge might be swallowed and never serviced.
Does this need coordinated locking to ensure it is only cleared when no
other hosts have pending interrupts?
[ ... ]
> @@ -213,11 +237,15 @@ static void amd_mdb_intx_irq_mask(struct irq_data *data)
> if (pcie->variant->version == MDB5)
> val = FIELD_PREP(AMD_MDB_TLP_PCIE_INTX_MASK,
> AMD_MDB_PCIE_INTR_INTX_ASSERT(data->hwirq));
> else
> val = pcie->variant->intx_mask;
>
> /*
> * Writing '1' to a bit in AMD_MDB_TLP_IR_DISABLE_MISC disables that
> * interrupt, writing '0' has no effect.
> */
> - writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_DISABLE_MISC);
> + writel_relaxed(val, pcie->intr_base + pcie->variant->misc_disable_reg);
[Severity: High]
Will masking a single virtual INTx line on CPM6 unconditionally disable the
aggregate hardware INTx interrupt?
On CPM6, there appears to be only a single aggregate INTx hardware interrupt
bit. If an endpoint driver unbinds or calls disable_irq() on INTA, this
unconditionally writes the intx_mask bit to the disable register.
Does this disable the hardware aggregate interrupt completely, potentially
starving other endpoint devices relying on INTB, INTC, or INTD?
[ ... ]
> @@ -354,16 +375,19 @@ static irqreturn_t amd_mdb_pcie_event(int irq, void *args)
> ev_raw = readl_relaxed(pcie->intr_base + pcie->variant->misc_status_reg);
> val = ev_raw;
> val &= ~readl_relaxed(pcie->intr_base + pcie->variant->misc_mask_reg);
>
> if (pcie->variant->version == MDB5) {
> for_each_set_bit(i, &val, 32)
> generic_handle_domain_irq(pcie->mdb_domain, i);
[Severity: High]
This is a pre-existing issue, but are INTxB, INTxC, and INTxD interrupts
silently dropped on MDB5?
When an INTx occurs, amd_mdb_pcie_event() extracts the asserted bit and
calls generic_handle_domain_irq(). However, amd_mdb_setup_irq() only
creates a mapping for the single intx_hwirq (INTxA).
Bits corresponding to INTxB, INTxC, and INTxD are never mapped, so
generic_handle_domain_irq() will return -EINVAL and the interrupts will be
lost.
> writel_relaxed(val, pcie->intr_base + pcie->variant->misc_status_reg);
> return IRQ_HANDLED;
> }
>
> val &= pcie->variant->misc_mask_all;
>
> for_each_set_bit(i, &val, 32)
> generic_handle_domain_irq(pcie->mdb_domain, i);
>
> /* Clear handled + any unhandled sticky bits to avoid IRQ storms. */
> - writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC);
> + writel_relaxed(ev_raw, pcie->intr_base + pcie->variant->misc_status_reg);
[Severity: High]
This isn't a bug introduced by this patch, but does clearing the sticky W1C
status register at the end of the interrupt handler create a race condition?
If a second edge of the same interrupt type occurs during the handling
phase, writing ev_raw back to the W1C register at the very end will clear
the new edge without it ever being processed.
Should the status register be ACKed before handling the events so that new
edges can latch correctly?
> + /* On CPM6 the completion timeout is reported via the PCIE_ERR register. */
> + err = readl_relaxed(pcie->intr_base + AMD_CPM6_PCIE_ERR_STATUS);
> + err &= ~readl_relaxed(pcie->intr_base + AMD_CPM6_PCIE_ERR_MASK);
> + err &= AMD_CPM6_PCIE_ERR_MASK_ALL;
> + if (err) {
> + dev_warn(pcie->pci.dev, "Completion timeout\n");
> + writel_relaxed(err, pcie->intr_base + AMD_CPM6_PCIE_ERR_STATUS);
> + }
[Severity: High]
Are unhandled bits in the PCIE_ERR_STATUS register masked out and never
cleared?
The driver masks the read value with AMD_CPM6_PCIE_ERR_MASK_ALL and only
writes back the known bits to the W1C register. If any unhandled bit is
set, it remains uncleared.
Since this register feeds into the sticky MERGED aggregator, will this cause
the hardware to immediately re-assert the main parent interrupt and create
an unrecoverable IRQ storm?
[ ... ]
> @@ -400,10 +421,30 @@ static void amd_mdb_pcie_free_irq_domains(struct amd_mdb_pcie *pcie)
> + const struct amd_mdb_intr_cause *intr_cause =
> + pcie->variant->version == MDB5 ?
> + mdb5_intr_cause : cpm6_intr_cause;
> + int i, irq;
> +
> + for (i = 0; i < ARRAY_SIZE(mdb5_intr_cause); i++) {
> + if (!intr_cause[i].str)
> + continue;
> + irq = irq_find_mapping(pcie->mdb_domain, i);
> + if (irq) {
> + disable_irq(irq);
> + free_irq(irq, pcie);
> + irq_dispose_mapping(irq);
> + }
> + }
[Severity: High]
Is it safe to manually call free_irq() on an interrupt allocated with
devm_request_irq()?
In amd_mdb_setup_irq(), these interrupts are allocated under devres
management. On probe failure, this error path manually frees them. When the
driver unbinds, devres will attempt to free the same IRQs again.
Can this cause a double-free on a disposed virtual IRQ mapping?
[ ... ]
> irq_domain_remove(pcie->mdb_domain);
> pcie->mdb_domain = NULL;
[Severity: High]
This is a pre-existing issue, but can this lead to a use-after-free of the
irq_domain if a hardware interrupt arrives concurrently?
The error path destroys and frees pcie->mdb_domain, but fails to disable
the main event interrupt first. If an interrupt fires concurrently,
amd_mdb_pcie_event() might dereference the freed domain pointer to dispatch
child interrupts.
[ ... ]
> @@ -639,12 +660,26 @@ static int amd_mdb_add_pcie_port(struct amd_mdb_pcie *pcie,
> pcie->slcr = devm_platform_ioremap_resource_byname(pdev, "slcr");
> if (IS_ERR(pcie->slcr))
> return PTR_ERR(pcie->slcr);
[Severity: High]
Will an exclusive ioremap of the shared slcr region cause the second CPM6
host controller to fail probing?
The commit message notes the aggregation layer is shared between the two
controllers. Requesting exclusive access to the memory region here means the
first device claims it, and the second device might fail to probe with a
resource conflict.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260728202044.1785986-1-sai.krishna.musham@amd.com?part=2
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-07-28 20:33 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-28 20:20 [PATCH v2 0/2] pci: AMD: Add Versal2 CPM6 PCIe host controller support Sai Krishna Musham
2026-07-28 20:20 ` [PATCH v2 1/2] dt-bindings: pci: Add CPM6 support to AMD MDB PCIe binding Sai Krishna Musham
2026-07-28 20:26 ` sashiko-bot
2026-07-28 20:20 ` [PATCH v2 2/2] pci: AMD: Add CPM6 host controller support to AMD MDB PCIe driver Sai Krishna Musham
2026-07-28 20:33 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox