Skip to content

Commit 7f8faf9

Browse files
committed
cxl/mem: Enumerate port targets before adding endpoints
The port scanning algorithm in devm_cxl_enumerate_ports() walks up the topology and adds cxl_port objects starting from the root down to the endpoint. When those ports are initially created they know all their dports, but they do not know the downstream cxl_port instance that represents the next descendant in the topology. Rework create_endpoint() into devm_cxl_add_endpoint() that enumerates the downstream cxl_port topology into each port's 'struct cxl_ep' record for each endpoint it that the port is an ancestor. Reviewed-by: Jonathan Cameron <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Dan Williams <[email protected]>
1 parent 538831f commit 7f8faf9

File tree

3 files changed

+47
-29
lines changed

3 files changed

+47
-29
lines changed

drivers/cxl/core/port.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,6 +1087,47 @@ static struct cxl_ep *cxl_ep_load(struct cxl_port *port,
10871087
return xa_load(&port->endpoints, (unsigned long)&cxlmd->dev);
10881088
}
10891089

1090+
int devm_cxl_add_endpoint(struct cxl_memdev *cxlmd,
1091+
struct cxl_dport *parent_dport)
1092+
{
1093+
struct cxl_port *parent_port = parent_dport->port;
1094+
struct cxl_dev_state *cxlds = cxlmd->cxlds;
1095+
struct cxl_port *endpoint, *iter, *down;
1096+
int rc;
1097+
1098+
/*
1099+
* Now that the path to the root is established record all the
1100+
* intervening ports in the chain.
1101+
*/
1102+
for (iter = parent_port, down = NULL; !is_cxl_root(iter);
1103+
down = iter, iter = to_cxl_port(iter->dev.parent)) {
1104+
struct cxl_ep *ep;
1105+
1106+
ep = cxl_ep_load(iter, cxlmd);
1107+
ep->next = down;
1108+
}
1109+
1110+
endpoint = devm_cxl_add_port(&parent_port->dev, &cxlmd->dev,
1111+
cxlds->component_reg_phys, parent_dport);
1112+
if (IS_ERR(endpoint))
1113+
return PTR_ERR(endpoint);
1114+
1115+
dev_dbg(&cxlmd->dev, "add: %s\n", dev_name(&endpoint->dev));
1116+
1117+
rc = cxl_endpoint_autoremove(cxlmd, endpoint);
1118+
if (rc)
1119+
return rc;
1120+
1121+
if (!endpoint->dev.driver) {
1122+
dev_err(&cxlmd->dev, "%s failed probe\n",
1123+
dev_name(&endpoint->dev));
1124+
return -ENXIO;
1125+
}
1126+
1127+
return 0;
1128+
}
1129+
EXPORT_SYMBOL_NS_GPL(devm_cxl_add_endpoint, CXL);
1130+
10901131
static void cxl_detach_ep(void *data)
10911132
{
10921133
struct cxl_memdev *cxlmd = data;

drivers/cxl/cxl.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,10 +385,13 @@ struct cxl_dport {
385385
* struct cxl_ep - track an endpoint's interest in a port
386386
* @ep: device that hosts a generic CXL endpoint (expander or accelerator)
387387
* @dport: which dport routes to this endpoint on @port
388+
* @next: cxl switch port across the link attached to @dport NULL if
389+
* attached to an endpoint
388390
*/
389391
struct cxl_ep {
390392
struct device *ep;
391393
struct cxl_dport *dport;
394+
struct cxl_port *next;
392395
};
393396

394397
/*
@@ -411,6 +414,8 @@ struct pci_bus *cxl_port_to_pci_bus(struct cxl_port *port);
411414
struct cxl_port *devm_cxl_add_port(struct device *host, struct device *uport,
412415
resource_size_t component_reg_phys,
413416
struct cxl_dport *parent_dport);
417+
int devm_cxl_add_endpoint(struct cxl_memdev *cxlmd,
418+
struct cxl_dport *parent_dport);
414419
struct cxl_port *find_cxl_root(struct device *dev);
415420
int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd);
416421
int cxl_bus_rescan(void);

drivers/cxl/mem.c

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -25,34 +25,6 @@
2525
* in higher level operations.
2626
*/
2727

28-
static int create_endpoint(struct cxl_memdev *cxlmd,
29-
struct cxl_dport *parent_dport)
30-
{
31-
struct cxl_port *parent_port = parent_dport->port;
32-
struct cxl_dev_state *cxlds = cxlmd->cxlds;
33-
struct cxl_port *endpoint;
34-
int rc;
35-
36-
endpoint = devm_cxl_add_port(&parent_port->dev, &cxlmd->dev,
37-
cxlds->component_reg_phys, parent_dport);
38-
if (IS_ERR(endpoint))
39-
return PTR_ERR(endpoint);
40-
41-
dev_dbg(&cxlmd->dev, "add: %s\n", dev_name(&endpoint->dev));
42-
43-
rc = cxl_endpoint_autoremove(cxlmd, endpoint);
44-
if (rc)
45-
return rc;
46-
47-
if (!endpoint->dev.driver) {
48-
dev_err(&cxlmd->dev, "%s failed probe\n",
49-
dev_name(&endpoint->dev));
50-
return -ENXIO;
51-
}
52-
53-
return 0;
54-
}
55-
5628
static void enable_suspend(void *data)
5729
{
5830
cxl_mem_active_dec();
@@ -116,7 +88,7 @@ static int cxl_mem_probe(struct device *dev)
11688
goto unlock;
11789
}
11890

119-
rc = create_endpoint(cxlmd, dport);
91+
rc = devm_cxl_add_endpoint(cxlmd, dport);
12092
unlock:
12193
device_unlock(&parent_port->dev);
12294
put_device(&parent_port->dev);

0 commit comments

Comments
 (0)