Add logic to map CXL PCIe upstream switch port (USP) RAS registers. Introduce 'struct cxl_regs' member into 'struct cxl_port' to store a pointer to the upstream port's mapped RAS registers. The upstream port may have multiple downstream endpoints. Before mapping AER registers check if the registers are already mapped. Signed-off-by: Terry Bowman <terry.bowman@xxxxxxx> --- drivers/cxl/core/pci.c | 17 +++++++++++++++++ drivers/cxl/cxl.h | 4 ++++ drivers/cxl/mem.c | 3 +++ 3 files changed, 24 insertions(+) diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c index 0bb61e39cf8f..53ca773557f3 100644 --- a/drivers/cxl/core/pci.c +++ b/drivers/cxl/core/pci.c @@ -773,6 +773,23 @@ static void cxl_disable_rch_root_ints(struct cxl_dport *dport) writel(aer_cmd, aer_base + PCI_ERR_ROOT_COMMAND); } +void cxl_uport_init_ras_reporting(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_ras_reporting, CXL); + /** * cxl_dport_init_ras_reporting - Setup CXL RAS report on this dport * @dport: the cxl_dport that needs to be initialized diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h index 787688e81602..ded6a343c05e 100644 --- a/drivers/cxl/cxl.h +++ b/drivers/cxl/cxl.h @@ -592,6 +592,7 @@ struct cxl_dax_region { * @parent_dport: dport that points to this port in the parent * @decoder_ida: allocator for decoder ids * @reg_map: component and ras register mapping parameters + * @uport_regs: mapped component registers * @nr_dports: number of entries in @dports * @hdm_end: track last allocated HDM decoder instance for allocation ordering * @commit_end: cursor to track highest committed decoder for commit ordering @@ -612,6 +613,7 @@ struct cxl_port { struct cxl_dport *parent_dport; struct ida decoder_ida; struct cxl_register_map reg_map; + struct cxl_component_regs uport_regs; int nr_dports; int hdm_end; int commit_end; @@ -763,8 +765,10 @@ struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port, #ifdef CONFIG_PCIEAER_CXL void cxl_dport_init_ras_reporting(struct cxl_dport *dport); +void cxl_uport_init_ras_reporting(struct cxl_port *port); #else static inline void cxl_dport_init_ras_reporting(struct cxl_dport *dport) { } +static inline void cxl_uport_init_ras_reporting(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 240d54b22a8c..067fd6389562 100644 --- a/drivers/cxl/mem.c +++ b/drivers/cxl/mem.c @@ -66,6 +66,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_ras_reporting(dport); + + if (dev_is_cxl_pci(dport->port->uport_dev, PCI_EXP_TYPE_UPSTREAM)) + cxl_uport_init_ras_reporting(dport->port); } static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd, -- 2.34.1