[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250107035708.1134954-7-ming.li@zohomail.com>
Date: Tue, 7 Jan 2025 11:57:06 +0800
From: Li Ming <ming.li@...omail.com>
To: dave@...olabs.net,
jonathan.cameron@...wei.com,
dave.jiang@...el.com,
alison.schofield@...el.com,
vishal.l.verma@...el.com,
ira.weiny@...el.com,
dan.j.williams@...el.com
Cc: linux-cxl@...r.kernel.org,
linux-kernel@...r.kernel.org,
Li Ming <ming.li@...omail.com>
Subject: [RFC PATCH 6/8] cxl/port: Enumerate dport component registers when endpoint attaching
In some hardware platform, dport's component registers are exposed only
when the dport is working on CXL mode and connecting to a CXL switch/CXL
device.
Currently, CXL subsystem will probe a dport's component registers when
the dport added to its port. In VH case, a root port's component
registers are probed during the host bridge the root port belongs to
attaching. As mentioned above, if no CXL/switch/CXL device connected to
the root port, root port component registers setup will failed.
The solution is delaying all CXL non-RCH dport component registers
enumeration until the first endpoint attaching.
Signed-off-by: Li Ming <ming.li@...omail.com>
---
drivers/cxl/core/pci.c | 8 +------
drivers/cxl/core/port.c | 53 ++++++++++++++++++++++++++---------------
drivers/cxl/cxl.h | 1 +
drivers/cxl/port.c | 20 ++++++++++------
4 files changed, 49 insertions(+), 33 deletions(-)
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index 9d58ab9d33c5..3b22f3033484 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -37,10 +37,8 @@ static int match_add_dports(struct pci_dev *pdev, void *data)
struct cxl_walk_context *ctx = data;
struct cxl_port *port = ctx->port;
int type = pci_pcie_type(pdev);
- struct cxl_register_map map;
struct cxl_dport *dport;
u32 lnkcap, port_num;
- int rc;
if (pdev->bus != ctx->bus)
return 0;
@@ -52,12 +50,8 @@ static int match_add_dports(struct pci_dev *pdev, void *data)
&lnkcap))
return 0;
- rc = cxl_find_regblock(pdev, CXL_REGLOC_RBI_COMPONENT, &map);
- if (rc)
- dev_dbg(&port->dev, "failed to find component registers\n");
-
port_num = FIELD_GET(PCI_EXP_LNKCAP_PN, lnkcap);
- dport = devm_cxl_add_dport(port, &pdev->dev, port_num, map.resource);
+ dport = devm_cxl_add_dport(port, &pdev->dev, port_num, CXL_RESOURCE_NONE);
if (IS_ERR(dport)) {
ctx->error = PTR_ERR(dport);
return PTR_ERR(dport);
diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
index b406ba64f6bc..04617ab825ee 100644
--- a/drivers/cxl/core/port.c
+++ b/drivers/cxl/core/port.c
@@ -626,6 +626,8 @@ static void unregister_port(void *_port)
lock_dev = &parent->dev;
device_lock_assert(lock_dev);
+ if (port->parent_dport && !port->parent_dport->rch)
+ cxl_register_map_reset(&port->parent_dport->reg_map);
port->dead = true;
device_unregister(&port->dev);
}
@@ -820,13 +822,39 @@ int cxl_port_setup_regs(struct cxl_port *port)
}
EXPORT_SYMBOL_NS_GPL(cxl_port_setup_regs, "CXL");
-static int cxl_dport_setup_regs(struct device *host, struct cxl_dport *dport,
- resource_size_t component_reg_phys)
+/**
+ * cxl_dport_setup_regs - probe all component registers of a cxl dport
+ * @dport: target cxl dport
+ */
+int cxl_dport_setup_regs(struct cxl_dport *dport)
{
+ resource_size_t component_reg_phys;
+ struct device *host;
int rc;
if (dev_is_platform(dport->dport_dev))
return 0;
+ /* component registers have been set up */
+ if (dport->reg_map.resource != CXL_RESOURCE_NONE)
+ return 0;
+
+ if (dport->rcrb.base) {
+ component_reg_phys = __rcrb_to_component(dport->dport_dev, &dport->rcrb,
+ CXL_RCRB_DOWNSTREAM);
+ host = NULL;
+ } else {
+ component_reg_phys = find_component_registers(dport->dport_dev);
+ host = &dport->port->dev;
+ }
+
+ if (component_reg_phys == CXL_RESOURCE_NONE) {
+ dev_warn(dport->dport_dev, "Invalid Component Registers%s",
+ dport->rcrb.base ? " in RCRB" : "");
+ return -ENXIO;
+ }
+
+ dev_dbg(dport->dport_dev, "Component Registers found for dport: %pa\n",
+ &component_reg_phys);
/*
* use @dport->dport_dev for the context for error messages during
@@ -838,6 +866,7 @@ static int cxl_dport_setup_regs(struct device *host, struct cxl_dport *dport,
dport->reg_map.host = host;
return rc;
}
+EXPORT_SYMBOL_NS_GPL(cxl_dport_setup_regs, "CXL");
DEFINE_SHOW_ATTRIBUTE(einj_cxl_available_error_type);
@@ -1176,39 +1205,25 @@ __devm_cxl_add_dport(struct cxl_port *port, struct device *dport_dev,
if (!dport)
return ERR_PTR(-ENOMEM);
+ cxl_register_map_reset(&dport->reg_map);
dport->dport_dev = dport_dev;
dport->port_id = port_id;
dport->port = port;
- if (rcrb == CXL_RESOURCE_NONE) {
- rc = cxl_dport_setup_regs(&port->dev, dport,
- component_reg_phys);
- if (rc)
- return ERR_PTR(rc);
- } else {
+ if (rcrb != CXL_RESOURCE_NONE) {
dport->rcrb.base = rcrb;
- component_reg_phys = __rcrb_to_component(dport_dev, &dport->rcrb,
- CXL_RCRB_DOWNSTREAM);
- if (component_reg_phys == CXL_RESOURCE_NONE) {
- dev_warn(dport_dev, "Invalid Component Registers in RCRB");
- return ERR_PTR(-ENXIO);
- }
/*
* RCH @dport is not ready to map until associated with its
* memdev
*/
- rc = cxl_dport_setup_regs(NULL, dport, component_reg_phys);
+ rc = cxl_dport_setup_regs(dport);
if (rc)
return ERR_PTR(rc);
dport->rch = true;
}
- if (component_reg_phys != CXL_RESOURCE_NONE)
- dev_dbg(dport_dev, "Component Registers found for dport: %pa\n",
- &component_reg_phys);
-
cond_cxl_root_lock(port);
rc = add_dport(port, dport);
cond_cxl_root_unlock(port);
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index 7763be02ef81..601818861441 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -773,6 +773,7 @@ struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port,
resource_size_t rcrb);
int cxl_port_setup_regs(struct cxl_port *port);
+int cxl_dport_setup_regs(struct cxl_dport *dport);
#ifdef CONFIG_PCIEAER_CXL
void cxl_setup_parent_dport(struct device *host, struct cxl_dport *dport);
diff --git a/drivers/cxl/port.c b/drivers/cxl/port.c
index c59f198f6cb0..ec135628edcb 100644
--- a/drivers/cxl/port.c
+++ b/drivers/cxl/port.c
@@ -100,7 +100,7 @@ static int cxl_switch_port_setup_hdm(struct cxl_port *port)
return -ENXIO;
}
-static int cxl_switch_port_setup(struct cxl_port *port)
+static int cxl_switch_port_setup(struct cxl_port *port, struct cxl_dport *dport)
{
int rc;
@@ -108,12 +108,16 @@ static int cxl_switch_port_setup(struct cxl_port *port)
if (rc)
return rc;
- return cxl_switch_port_setup_hdm(port);
+ rc = cxl_switch_port_setup_hdm(port);
+ if (rc)
+ return rc;
+
+ return cxl_dport_setup_regs(dport);
}
static int cxl_endpoint_port_probe(struct cxl_port *port)
{
- struct cxl_port *iter, *parent_port = to_cxl_port(port->dev.parent);
+ struct cxl_port *iter, *prev, *parent_port = to_cxl_port(port->dev.parent);
struct cxl_endpoint_dvsec_info info = { .port = port };
struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport_dev);
struct cxl_dev_state *cxlds = cxlmd->cxlds;
@@ -121,8 +125,10 @@ static int cxl_endpoint_port_probe(struct cxl_port *port)
struct cxl_port *root;
int rc;
- for (iter = parent_port; !is_cxl_root(iter);
- iter = to_cxl_port(iter->dev.parent)) {
+ for (iter = parent_port, prev = NULL; !is_cxl_root(iter);
+ prev = iter, iter = to_cxl_port(iter->dev.parent)) {
+ struct cxl_dport *dport = prev ? prev->parent_dport :
+ port->parent_dport;
/*
* The parent port of endpoint has been locked
* during endpoint port attaching.
@@ -131,9 +137,9 @@ static int cxl_endpoint_port_probe(struct cxl_port *port)
*/
if (iter != parent_port) {
guard(device)(&iter->dev);
- rc = cxl_switch_port_setup(iter);
+ rc = cxl_switch_port_setup(iter, dport);
} else {
- rc = cxl_switch_port_setup(iter);
+ rc = cxl_switch_port_setup(iter, dport);
}
if (rc)
return rc;
--
2.34.1
Powered by blists - more mailing lists