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 RAS registers check if the registers are already mapped. Introduce a mutex for synchronizing accesses to the cached RAS mapping. Signed-off-by: Terry Bowman <terry.bowman@xxxxxxx> Reviewed-by: Gregory Price <gourry@xxxxxxxxxx> --- drivers/cxl/core/pci.c | 19 ++++++++++++++++++- drivers/cxl/cxl.h | 4 ++++ drivers/cxl/mem.c | 8 ++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c index c142d7890bfa..4af39abbfab3 100644 --- a/drivers/cxl/core/pci.c +++ b/drivers/cxl/core/pci.c @@ -781,6 +781,24 @@ 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. */ + mutex_lock(&ras_init_mutex); + if (port->uport_regs.ras) { + mutex_unlock(&ras_init_mutex); + 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"); + mutex_unlock(&ras_init_mutex); +} +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 @@ -807,7 +825,6 @@ void cxl_dport_init_ras_reporting(struct cxl_dport *dport) BIT(CXL_CM_CAP_CAP_ID_RAS))) dev_err(dport_dev, "Failed to map RAS capability\n"); mutex_unlock(&ras_init_mutex); - } EXPORT_SYMBOL_NS_GPL(cxl_dport_init_ras_reporting, "CXL"); diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h index 82d0a8555a11..49f29a3ef68e 100644 --- a/drivers/cxl/cxl.h +++ b/drivers/cxl/cxl.h @@ -581,6 +581,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 @@ -602,6 +603,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; @@ -755,8 +757,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 8c1144bbc058..541cabca434e 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