Inter-revision diff: patch 9

Comparing v6 (message) to v4 (message)

--- v6
+++ v4
@@ -1,125 +1,144 @@
 From: Robert Richter <rrichter@amd.com>
 
-Just moving code to reorder functions to later share cxl_get_chbs()
-with add_host_bridge_uport().
+CXL RAS capabilities must be enabled and accessible as soon as the CXL
+endpoint is detected in the PCI hierarchy and bound to the cxl_pci
+driver. This needs to be independent of other modules such as cxl_port
+or cxl_mem.
 
-This makes changes in the next patch visible. No other changes at all.
+CXL RAS capabilities reside in the Component Registers. For an RCH
+this is determined by probing RCRB which is implemented very late once
+the CXL Memory Device is created.
+
+Change this by moving the RCRB probe to the cxl_pci driver. Do this by
+using a new introduced function cxl_pci_find_port() similar to
+cxl_mem_find_port() to determine the involved dport by the endpoint's
+PCI handle. Plug this into the existing cxl_pci_setup_regs() function
+to setup Component Registers. Probe the RCRB in case the Component
+Registers cannot be located through the CXL Register Locator
+capability.
+
+This unifies code and early sets up the Component Registers at the
+same time for both, VH and RCH mode. Only the cxl_pci driver is
+involved for this. This allows an early mapping of the CXL RAS
+capability registers.
 
 Signed-off-by: Robert Richter <rrichter@amd.com>
 Signed-off-by: Terry Bowman <terry.bowman@amd.com>
-Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
 ---
- drivers/cxl/acpi.c | 90 +++++++++++++++++++++++-----------------------
- 1 file changed, 45 insertions(+), 45 deletions(-)
+ drivers/cxl/core/port.c |  7 +++++++
+ drivers/cxl/cxl.h       |  2 ++
+ drivers/cxl/mem.c       | 12 ------------
+ drivers/cxl/pci.c       | 37 ++++++++++++++++++++++++++++++++++++-
+ 4 files changed, 45 insertions(+), 13 deletions(-)
 
-diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c
-index 70cd9ac73a8b..0c975ee684b0 100644
---- a/drivers/cxl/acpi.c
-+++ b/drivers/cxl/acpi.c
-@@ -327,51 +327,6 @@ __mock struct acpi_device *to_cxl_host_bridge(struct device *host,
- 	return NULL;
+diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
+index 66f567480238..eff91f141fde 100644
+--- a/drivers/cxl/core/port.c
++++ b/drivers/cxl/core/port.c
+@@ -1477,6 +1477,13 @@ int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd)
  }
+ EXPORT_SYMBOL_NS_GPL(devm_cxl_enumerate_ports, CXL);
  
--/*
-- * A host bridge is a dport to a CFMWS decode and it is a uport to the
-- * dport (PCIe Root Ports) in the host bridge.
-- */
--static int add_host_bridge_uport(struct device *match, void *arg)
--{
--	struct cxl_port *root_port = arg;
--	struct device *host = root_port->dev.parent;
--	struct acpi_device *hb = to_cxl_host_bridge(host, match);
--	struct acpi_pci_root *pci_root;
--	struct cxl_dport *dport;
--	struct cxl_port *port;
--	struct device *bridge;
--	int rc;
--
--	if (!hb)
--		return 0;
--
--	pci_root = acpi_pci_find_root(hb->handle);
--	bridge = pci_root->bus->bridge;
--	dport = cxl_find_dport_by_dev(root_port, bridge);
--	if (!dport) {
--		dev_dbg(host, "host bridge expected and not found\n");
--		return 0;
++struct cxl_port *cxl_pci_find_port(struct pci_dev *pdev,
++				   struct cxl_dport **dport)
++{
++	return find_cxl_port(pdev->dev.parent, dport);
++}
++EXPORT_SYMBOL_NS_GPL(cxl_pci_find_port, CXL);
++
+ struct cxl_port *cxl_mem_find_port(struct cxl_memdev *cxlmd,
+ 				   struct cxl_dport **dport)
+ {
+diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
+index 1c6fe53e9dc7..e5ae5f4e6669 100644
+--- a/drivers/cxl/cxl.h
++++ b/drivers/cxl/cxl.h
+@@ -670,6 +670,8 @@ struct cxl_port *find_cxl_root(struct cxl_port *port);
+ int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd);
+ void cxl_bus_rescan(void);
+ void cxl_bus_drain(void);
++struct cxl_port *cxl_pci_find_port(struct pci_dev *pdev,
++				   struct cxl_dport **dport);
+ struct cxl_port *cxl_mem_find_port(struct cxl_memdev *cxlmd,
+ 				   struct cxl_dport **dport);
+ bool schedule_cxl_memdev_detach(struct cxl_memdev *cxlmd);
+diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
+index 7ecdaa7f9315..0643852444f3 100644
+--- a/drivers/cxl/mem.c
++++ b/drivers/cxl/mem.c
+@@ -65,18 +65,6 @@ static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd,
+ 		ep->next = down;
+ 	}
+ 
+-	/*
+-	 * The component registers for an RCD might come from the
+-	 * host-bridge RCRB if they are not already mapped via the
+-	 * typical register locator mechanism.
+-	 */
+-	if (parent_dport->rch &&
+-	    cxlds->component_reg_phys == CXL_RESOURCE_NONE) {
+-		cxlds->component_reg_phys =
+-			cxl_probe_rcrb(&cxlmd->dev, parent_dport->rcrb.base,
+-				       NULL, CXL_RCRB_UPSTREAM);
 -	}
 -
--	if (dport->rch) {
--		dev_info(bridge, "host supports CXL (restricted)\n");
--		return 0;
--	}
--
--	rc = devm_cxl_register_pci_bus(host, bridge, pci_root->bus);
--	if (rc)
--		return rc;
--
--	port = devm_cxl_add_port(host, bridge, dport->component_reg_phys,
--				 dport);
--	if (IS_ERR(port))
--		return PTR_ERR(port);
--
--	dev_info(bridge, "host supports CXL\n");
--
--	return 0;
--}
--
- /* Note, @dev is used by mock_acpi_table_parse_cedt() */
- struct cxl_chbs_context {
- 	struct device *dev;
-@@ -467,6 +422,51 @@ static int add_host_bridge_dport(struct device *match, void *arg)
+ 	endpoint = devm_cxl_add_port(host, &cxlmd->dev,
+ 				     cxlds->component_reg_phys,
+ 				     parent_dport);
+diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
+index 945ca0304d68..54c486cd65dd 100644
+--- a/drivers/cxl/pci.c
++++ b/drivers/cxl/pci.c
+@@ -274,13 +274,48 @@ static int cxl_pci_setup_mailbox(struct cxl_dev_state *cxlds)
  	return 0;
  }
  
-+/*
-+ * A host bridge is a dport to a CFMWS decode and it is a uport to the
-+ * dport (PCIe Root Ports) in the host bridge.
-+ */
-+static int add_host_bridge_uport(struct device *match, void *arg)
++/* Extract RCRB, use same function interface as cxl_find_regblock(). */
++static int cxl_rcrb_get_comp_regs(struct pci_dev *pdev,
++				  enum cxl_regloc_type type,
++				  struct cxl_register_map *map)
 +{
-+	struct cxl_port *root_port = arg;
-+	struct device *host = root_port->dev.parent;
-+	struct acpi_device *hb = to_cxl_host_bridge(host, match);
-+	struct acpi_pci_root *pci_root;
 +	struct cxl_dport *dport;
-+	struct cxl_port *port;
-+	struct device *bridge;
-+	int rc;
++	resource_size_t component_reg_phys;
 +
-+	if (!hb)
-+		return 0;
++	memset(map, 0, sizeof(*map));
++	map->dev = &pdev->dev;
++	map->resource = CXL_RESOURCE_NONE;
 +
-+	pci_root = acpi_pci_find_root(hb->handle);
-+	bridge = pci_root->bus->bridge;
-+	dport = cxl_find_dport_by_dev(root_port, bridge);
-+	if (!dport) {
-+		dev_dbg(host, "host bridge expected and not found\n");
-+		return 0;
-+	}
++	if (type != CXL_REGLOC_RBI_COMPONENT)
++		return -ENODEV;
 +
-+	if (dport->rch) {
-+		dev_info(bridge, "host supports CXL (restricted)\n");
-+		return 0;
-+	}
++	if (!cxl_pci_find_port(pdev, &dport) || !dport->rch)
++		return -ENXIO;
 +
-+	rc = devm_cxl_register_pci_bus(host, bridge, pci_root->bus);
-+	if (rc)
-+		return rc;
++	component_reg_phys = cxl_probe_rcrb(&pdev->dev, dport->rcrb.base,
++					    NULL, CXL_RCRB_UPSTREAM);
++	if (component_reg_phys == CXL_RESOURCE_NONE)
++		return -ENXIO;
 +
-+	port = devm_cxl_add_port(host, bridge, dport->component_reg_phys,
-+				 dport);
-+	if (IS_ERR(port))
-+		return PTR_ERR(port);
-+
-+	dev_info(bridge, "host supports CXL\n");
++	map->resource = component_reg_phys;
++	map->reg_type = type;
++	map->max_size = CXL_COMPONENT_REG_BLOCK_SIZE;
 +
 +	return 0;
 +}
 +
- static int add_root_nvdimm_bridge(struct device *match, void *data)
+ static int cxl_pci_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type,
+ 			      struct cxl_register_map *map)
  {
- 	struct cxl_decoder *cxld;
+ 	int rc;
+ 
++	/*
++	 * If the Register Locator DVSEC does not contain the
++	 * Component Registers, try to extract them from the RCRB if
++	 * it is an RCH.
++	 */
+ 	rc = cxl_find_regblock(pdev, type, map);
+-	if (rc)
++	if (rc && cxl_rcrb_get_comp_regs(pdev, type, map))
+ 		return rc;
+ 
+ 	return cxl_setup_regs(map);
 -- 
 2.34.1
 
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help