[PATCH 10/15] cxl/pci: Map CXL PCIe upstream port RAS registers

Terry Bowman
2024-10-08T22:18:58Z

RAS registers are mapped for CXL root ports and CXL downstream but
not for CXL upstream switch ports. CXL upstream switch ports' mapped
RAS registers are required for handling and logging protocol errors.

Introduce 'struct cxl_regs' member into 'struct cxl_port' to store a
pointer to the upstream port's mapped RAS registers.

Map the the CXL upstream switch port's RAS register block.

The upstream port may be have multiple downstream endpoints. Before
mapping AER registers check if the registers are already mapped.

Signed-off-by: Terry Bowman <terry.bowman@amd.com>
---
drivers/cxl/core/pci.c | 17 +++++++++++++++++
drivers/cxl/cxl.h | 2 ++
drivers/cxl/mem.c | 3 +++
3 files changed, 22 insertions(+)

diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index 6f7bcdb389bf..be181358a775 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -816,6 +816,23 @@ static void cxl_disable_rch_root_ints(struct cxl_dport *dport)
}
}

+void cxl_uport_init_aer(struct cxl_port *port)
+{
+ /* uport may have more than 1 downstream EP. Check if already mapped. */
+ if (port->uport_regs.ras) {
+ dev_warn(&port->dev, "RAS is already mapped\n");
+ return;
+ }
+
+ port->reg_map.host = &port->dev;
+ if (cxl_map_component_regs(&port->reg_map, &port->uport_regs,
+ BIT(CXL_CM_CAP_CAP_ID_RAS))) {
+ dev_err(&port->dev, "Failed to map RAS capability.\n");
+ return;
+ }
+}
+EXPORT_SYMBOL_NS_GPL(cxl_uport_init_aer, CXL);
+
void cxl_dport_init_aer(struct cxl_dport *dport)
{
struct device *dport_dev = dport->dport_dev;
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index cb9e05e2912b..7a5f2c33223e 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -764,8 +764,10 @@ struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port,

#ifdef CONFIG_PCIEAER_CXL
void cxl_dport_init_aer(struct cxl_dport *dport);
+void cxl_uport_init_aer(struct cxl_port *port);
#else
static inline void cxl_dport_init_aer(struct cxl_dport *dport) { }
+static inline void cxl_uport_init_aer(struct cxl_port *port) { }
#endif

struct cxl_decoder *to_cxl_decoder(struct device *dev);
diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
index b7204f010785..82b1383fb6f3 100644
--- a/drivers/cxl/mem.c
+++ b/drivers/cxl/mem.c
@@ -67,6 +67,9 @@ static void cxl_init_ep_ports_aer(struct cxl_ep *ep)
if (dev_is_cxl_pci(dport->dport_dev, PCI_EXP_TYPE_DOWNSTREAM) ||
dev_is_cxl_pci(dport->dport_dev, PCI_EXP_TYPE_ROOT_PORT))
cxl_dport_init_aer(dport);
+
+ if (dev_is_cxl_pci(dport->port->uport_dev, PCI_EXP_TYPE_UPSTREAM))
+ cxl_uport_init_aer(dport->port);
}

static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd,
--
2.34.1