Skip to content

Commit

Permalink
cxl/mem: Enumerate port targets before adding endpoints
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
djbw committed Jul 22, 2022
1 parent 538831f commit 7f8faf9
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 29 deletions.
41 changes: 41 additions & 0 deletions drivers/cxl/core/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -1087,6 +1087,47 @@ static struct cxl_ep *cxl_ep_load(struct cxl_port *port,
return xa_load(&port->endpoints, (unsigned long)&cxlmd->dev);
}

int devm_cxl_add_endpoint(struct cxl_memdev *cxlmd,
struct cxl_dport *parent_dport)
{
struct cxl_port *parent_port = parent_dport->port;
struct cxl_dev_state *cxlds = cxlmd->cxlds;
struct cxl_port *endpoint, *iter, *down;
int rc;

/*
* Now that the path to the root is established record all the
* intervening ports in the chain.
*/
for (iter = parent_port, down = NULL; !is_cxl_root(iter);
down = iter, iter = to_cxl_port(iter->dev.parent)) {
struct cxl_ep *ep;

ep = cxl_ep_load(iter, cxlmd);
ep->next = down;
}

endpoint = devm_cxl_add_port(&parent_port->dev, &cxlmd->dev,
cxlds->component_reg_phys, parent_dport);
if (IS_ERR(endpoint))
return PTR_ERR(endpoint);

dev_dbg(&cxlmd->dev, "add: %s\n", dev_name(&endpoint->dev));

rc = cxl_endpoint_autoremove(cxlmd, endpoint);
if (rc)
return rc;

if (!endpoint->dev.driver) {
dev_err(&cxlmd->dev, "%s failed probe\n",
dev_name(&endpoint->dev));
return -ENXIO;
}

return 0;
}
EXPORT_SYMBOL_NS_GPL(devm_cxl_add_endpoint, CXL);

static void cxl_detach_ep(void *data)
{
struct cxl_memdev *cxlmd = data;
Expand Down
5 changes: 5 additions & 0 deletions drivers/cxl/cxl.h
Original file line number Diff line number Diff line change
Expand Up @@ -385,10 +385,13 @@ struct cxl_dport {
* struct cxl_ep - track an endpoint's interest in a port
* @ep: device that hosts a generic CXL endpoint (expander or accelerator)
* @dport: which dport routes to this endpoint on @port
* @next: cxl switch port across the link attached to @dport NULL if
* attached to an endpoint
*/
struct cxl_ep {
struct device *ep;
struct cxl_dport *dport;
struct cxl_port *next;
};

/*
Expand All @@ -411,6 +414,8 @@ struct pci_bus *cxl_port_to_pci_bus(struct cxl_port *port);
struct cxl_port *devm_cxl_add_port(struct device *host, struct device *uport,
resource_size_t component_reg_phys,
struct cxl_dport *parent_dport);
int devm_cxl_add_endpoint(struct cxl_memdev *cxlmd,
struct cxl_dport *parent_dport);
struct cxl_port *find_cxl_root(struct device *dev);
int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd);
int cxl_bus_rescan(void);
Expand Down
30 changes: 1 addition & 29 deletions drivers/cxl/mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,34 +25,6 @@
* in higher level operations.
*/

static int create_endpoint(struct cxl_memdev *cxlmd,
struct cxl_dport *parent_dport)
{
struct cxl_port *parent_port = parent_dport->port;
struct cxl_dev_state *cxlds = cxlmd->cxlds;
struct cxl_port *endpoint;
int rc;

endpoint = devm_cxl_add_port(&parent_port->dev, &cxlmd->dev,
cxlds->component_reg_phys, parent_dport);
if (IS_ERR(endpoint))
return PTR_ERR(endpoint);

dev_dbg(&cxlmd->dev, "add: %s\n", dev_name(&endpoint->dev));

rc = cxl_endpoint_autoremove(cxlmd, endpoint);
if (rc)
return rc;

if (!endpoint->dev.driver) {
dev_err(&cxlmd->dev, "%s failed probe\n",
dev_name(&endpoint->dev));
return -ENXIO;
}

return 0;
}

static void enable_suspend(void *data)
{
cxl_mem_active_dec();
Expand Down Expand Up @@ -116,7 +88,7 @@ static int cxl_mem_probe(struct device *dev)
goto unlock;
}

rc = create_endpoint(cxlmd, dport);
rc = devm_cxl_add_endpoint(cxlmd, dport);
unlock:
device_unlock(&parent_port->dev);
put_device(&parent_port->dev);
Expand Down

0 comments on commit 7f8faf9

Please sign in to comment.