Message ID | 20250107143852.3692571-9-terry.bowman@amd.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Bjorn Helgaas |
Headers | show |
Series | Enable CXL PCIe port protocol error handling and logging | expand |
Terry Bowman wrote: > The CXL mem driver (cxl_mem) currently maps and caches a pointer to RAS > registers for the endpoint's Root Port. The same needs to be done for > each of the CXL Downstream Switch Ports and CXL Root Ports found between > the endpoint and CXL Host Bridge. > > Introduce cxl_init_ep_ports_aer() to be called for each CXL Port in the > sub-topology between the endpoint and the CXL Host Bridge. This function > will determine if there are CXL Downstream Switch Ports or CXL Root Ports > associated with this Port. The same check will be added in the future for > upstream switch ports. > > Move the RAS register map logic from cxl_dport_map_ras() into > cxl_dport_init_ras_reporting(). This eliminates the need for the helper > function, cxl_dport_map_ras(). > > cxl_init_ep_ports_aer() calls cxl_dport_init_ras_reporting() to map > the RAS registers for CXL Downstream Switch Ports and CXL Root Ports. > > cxl_dport_init_ras_reporting() must check for previously mapped registers > before mapping. This is required because multiple endpoints under a CXL > switch may share an upstream CXL Root Port, CXL Downstream Switch Port, > or CXL Downstream Switch Port. Ensure the RAS registers are only mapped > once. > > Signed-off-by: Terry Bowman <terry.bowman@amd.com> > Reviewed-by: Alejandro Lucero <alucerop@amd.com> > Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Reviewed-by: Ira Weiny <ira.weiny@intel.com> [snip]
On Tue, Jan 07, 2025 at 08:38:44AM -0600, Terry Bowman wrote: > +static bool dev_is_cxl_pci(struct device *dev, u32 pcie_type) > +{ > + struct pci_dev *pdev; > + > + if (!dev || !dev_is_pci(dev)) > + return false; > + > + pdev = to_pci_dev(dev); > + > + return (pci_pcie_type(pdev) == pcie_type); > +} > + > +static void cxl_init_ep_ports_aer(struct cxl_ep *ep) > +{ > + struct cxl_dport *dport = ep->dport; > + > + if (dport) { > + struct device *dport_dev = dport->dport_dev; > + > + if (dev_is_cxl_pci(dport_dev, PCI_EXP_TYPE_DOWNSTREAM) || > + dev_is_cxl_pci(dport_dev, PCI_EXP_TYPE_ROOT_PORT)) Mostly an observation - this kind of comparison seems to be coming up more. Wonder if an explicit set of APIs for these checks would be worth it to clean up the 3 or 4 different comparison variants i've seen. Either way Reviewed-by: Gregory Price <gourry@gourry.net> ~Gregory
On 2/7/2025 1:30 AM, Gregory Price wrote: > On Tue, Jan 07, 2025 at 08:38:44AM -0600, Terry Bowman wrote: >> +static bool dev_is_cxl_pci(struct device *dev, u32 pcie_type) >> +{ >> + struct pci_dev *pdev; >> + >> + if (!dev || !dev_is_pci(dev)) >> + return false; >> + >> + pdev = to_pci_dev(dev); >> + >> + return (pci_pcie_type(pdev) == pcie_type); >> +} >> + >> +static void cxl_init_ep_ports_aer(struct cxl_ep *ep) >> +{ >> + struct cxl_dport *dport = ep->dport; >> + >> + if (dport) { >> + struct device *dport_dev = dport->dport_dev; >> + >> + if (dev_is_cxl_pci(dport_dev, PCI_EXP_TYPE_DOWNSTREAM) || >> + dev_is_cxl_pci(dport_dev, PCI_EXP_TYPE_ROOT_PORT)) > Mostly an observation - this kind of comparison seems to be coming up > more. Wonder if an explicit set of APIs for these checks would be worth > it to clean up the 3 or 4 different comparison variants i've seen. > > Either way > > Reviewed-by: Gregory Price <gourry@gourry.net> > > ~Gregory Do you recommend moving dev_is_cxl_pci() to pci library as is? Thanks for 'Reviewed-by:`. Terry
On Fri, Feb 07, 2025 at 01:08:35PM -0600, Bowman, Terry wrote: > > >> + > >> + if (dev_is_cxl_pci(dport_dev, PCI_EXP_TYPE_DOWNSTREAM) || > >> + dev_is_cxl_pci(dport_dev, PCI_EXP_TYPE_ROOT_PORT)) > > Mostly an observation - this kind of comparison seems to be coming up > > more. Wonder if an explicit set of APIs for these checks would be worth > > it to clean up the 3 or 4 different comparison variants i've seen. > > > > Either way > > > > Reviewed-by: Gregory Price <gourry@gourry.net> > > > > ~Gregory > Do you recommend moving dev_is_cxl_pci() to pci library as is? Thanks for 'Reviewed-by:`. Terry I'd have to go look around and see how much the PCI_EXP_TYPE items are being used for comparison and how - I was just commenting internally on this patch set. If this set is the only place it's being used (so far) then it's probably not worth extra work yet. ~Gregory
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c index b3aac9964e0d..1af2d0a14f5d 100644 --- a/drivers/cxl/core/pci.c +++ b/drivers/cxl/core/pci.c @@ -749,18 +749,6 @@ static void cxl_dport_map_rch_aer(struct cxl_dport *dport) } } -static void cxl_dport_map_ras(struct cxl_dport *dport) -{ - struct cxl_register_map *map = &dport->reg_map; - struct device *dev = dport->dport_dev; - - if (!map->component_map.ras.valid) - dev_dbg(dev, "RAS registers not found\n"); - else if (cxl_map_component_regs(map, &dport->regs.component, - BIT(CXL_CM_CAP_CAP_ID_RAS))) - dev_dbg(dev, "Failed to map RAS capability.\n"); -} - static void cxl_disable_rch_root_ints(struct cxl_dport *dport) { void __iomem *aer_base = dport->regs.dport_aer; @@ -788,22 +776,27 @@ static void cxl_disable_rch_root_ints(struct cxl_dport *dport) /** * cxl_dport_init_ras_reporting - Setup CXL RAS report on this dport * @dport: the cxl_dport that needs to be initialized - * @host: host device for devm operations */ -void cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host) +void cxl_dport_init_ras_reporting(struct cxl_dport *dport) { - dport->reg_map.host = host; - cxl_dport_map_ras(dport); - - if (dport->rch) { - struct pci_host_bridge *host_bridge = to_pci_host_bridge(dport->dport_dev); - - if (!host_bridge->native_aer) - return; + struct device *dport_dev = dport->dport_dev; + struct pci_host_bridge *host_bridge = to_pci_host_bridge(dport_dev); + dport->reg_map.host = dport_dev; + if (dport->rch && host_bridge->native_aer) { cxl_dport_map_rch_aer(dport); cxl_disable_rch_root_ints(dport); } + + /* dport may have more than 1 downstream EP. Check if already mapped. */ + if (dport->regs.ras) + return; + + if (cxl_map_component_regs(&dport->reg_map, &dport->regs.component, + BIT(CXL_CM_CAP_CAP_ID_RAS))) { + dev_err(dport_dev, "Failed to map RAS capability.\n"); + return; + } } EXPORT_SYMBOL_NS_GPL(cxl_dport_init_ras_reporting, "CXL"); diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h index fdac3ddb8635..727429dfdaed 100644 --- a/drivers/cxl/cxl.h +++ b/drivers/cxl/cxl.h @@ -772,11 +772,9 @@ struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port, resource_size_t rcrb); #ifdef CONFIG_PCIEAER_CXL -void cxl_setup_parent_dport(struct device *host, struct cxl_dport *dport); -void cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host); +void cxl_dport_init_ras_reporting(struct cxl_dport *dport); #else -static inline void cxl_dport_init_ras_reporting(struct cxl_dport *dport, - struct device *host) { } +static inline void cxl_dport_init_ras_reporting(struct cxl_dport *dport) { } #endif struct cxl_decoder *to_cxl_decoder(struct device *dev); diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c index 2f03a4d5606e..dd39f4565be2 100644 --- a/drivers/cxl/mem.c +++ b/drivers/cxl/mem.c @@ -45,6 +45,31 @@ static int cxl_mem_dpa_show(struct seq_file *file, void *data) return 0; } +static bool dev_is_cxl_pci(struct device *dev, u32 pcie_type) +{ + struct pci_dev *pdev; + + if (!dev || !dev_is_pci(dev)) + return false; + + pdev = to_pci_dev(dev); + + return (pci_pcie_type(pdev) == pcie_type); +} + +static void cxl_init_ep_ports_aer(struct cxl_ep *ep) +{ + struct cxl_dport *dport = ep->dport; + + if (dport) { + struct device *dport_dev = dport->dport_dev; + + if (dev_is_cxl_pci(dport_dev, PCI_EXP_TYPE_DOWNSTREAM) || + dev_is_cxl_pci(dport_dev, PCI_EXP_TYPE_ROOT_PORT)) + cxl_dport_init_ras_reporting(dport); + } +} + static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd, struct cxl_dport *parent_dport) { @@ -52,6 +77,9 @@ static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd, struct cxl_port *endpoint, *iter, *down; int rc; + if (parent_dport->rch) + cxl_dport_init_ras_reporting(parent_dport); + /* * Now that the path to the root is established record all the * intervening ports in the chain. @@ -62,6 +90,7 @@ static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd, ep = cxl_ep_load(iter, cxlmd); ep->next = down; + cxl_init_ep_ports_aer(ep); } /* Note: endpoint port component registers are derived from @cxlds */ @@ -166,8 +195,6 @@ static int cxl_mem_probe(struct device *dev) else endpoint_parent = &parent_port->dev; - cxl_dport_init_ras_reporting(dport, dev); - scoped_guard(device, endpoint_parent) { if (!endpoint_parent->driver) { dev_err(dev, "CXL port topology %s not enabled\n",