Add logic to map CXL PCIe Upstream Switch Port (USP) RAS registers. Introduce 'struct cxl_regs' member into 'struct cxl_port' to cache a pointer to the CXL Upstream Port's mapped RAS registers. Also, introduce cxl_uport_init_ras_reporting() to perform the USP RAS register mapping. This is similar to the existing cxl_dport_init_ras_reporting() but for USP devices. The USP 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 | 15 +++++++++++++++ drivers/cxl/cxl.h | 4 ++++ drivers/cxl/mem.c | 8 ++++++++ 3 files changed, 27 insertions(+) diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c index 8540d1fd2e25..08073bbe2697 100644 --- a/drivers/cxl/core/pci.c +++ b/drivers/cxl/core/pci.c @@ -773,6 +773,21 @@ 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) + 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 51acca3415b4..0cf8d2cfcd8b 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; @@ -764,8 +766,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 0ae89c9da71e..0ce71af8ce22 100644 --- a/drivers/cxl/mem.c +++ b/drivers/cxl/mem.c @@ -60,6 +60,7 @@ static bool dev_is_cxl_pci(struct device *dev, u32 pcie_type) static void cxl_init_ep_ports_aer(struct cxl_ep *ep) { struct cxl_dport *dport = ep->dport; + struct cxl_port *port = ep->next; if (dport) { struct device *dport_dev = dport->dport_dev; @@ -68,6 +69,13 @@ static void cxl_init_ep_ports_aer(struct cxl_ep *ep) dev_is_cxl_pci(dport_dev, PCI_EXP_TYPE_ROOT_PORT)) cxl_dport_init_ras_reporting(dport); } + + if (port) { + struct device *uport_dev = port->uport_dev; + + if (dev_is_cxl_pci(uport_dev, PCI_EXP_TYPE_UPSTREAM)) + cxl_uport_init_ras_reporting(port); + } } static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd, -- 2.34.1