diff mbox series

[RFC,v2,07/28] cxl/core: Move target population locking to caller

Message ID 20211022183709.1199701-8-ben.widawsky@intel.com
State New, archived
Headers show
Series CXL Region Creation / HDM decoder programming | expand

Commit Message

Ben Widawsky Oct. 22, 2021, 6:36 p.m. UTC
A CXL port driver which would be responsible for adding decoders will
want to do so during probe. Unfortunately, the device lock is held
during probe. Making this change allows for a new lock-free variant of
cxl_decoder_add which will be used by the port driver.

Signed-off-by: Ben Widawsky <ben.widawsky@intel.com>
---
 drivers/cxl/core/bus.c | 29 ++++++++++++-----------------
 1 file changed, 12 insertions(+), 17 deletions(-)

Comments

Dan Williams Oct. 29, 2021, 11:03 p.m. UTC | #1
On Fri, Oct 22, 2021 at 11:37 AM Ben Widawsky <ben.widawsky@intel.com> wrote:
>
> A CXL port driver which would be responsible for adding decoders will
> want to do so during probe.

"In preparation for a port driver that enumerates a descendant port +
decoder hierarchy, arrange for an unlocked version of
cxl_decoder_add(). Otherwise a port-driver that adds a child decoder
will deadlock on the device_lock() in ->probe()."

...although when I write it that way I would expect to see
cxl_decoder_add_locked() in this patch.

The port driver patch is big enough already, so pulling the API
addition into this patch would be my preference.
diff mbox series

Patch

diff --git a/drivers/cxl/core/bus.c b/drivers/cxl/core/bus.c
index 5564a71773e2..5f2bde47a5c2 100644
--- a/drivers/cxl/core/bus.c
+++ b/drivers/cxl/core/bus.c
@@ -478,25 +478,18 @@  static int decoder_populate_targets(struct cxl_decoder *cxld,
 	if (!target_map)
 		return 0;
 
-	device_lock(&port->dev);
-	if (list_empty(&port->dports)) {
-		rc = -EINVAL;
-		goto out_unlock;
-	}
+	device_lock_assert(&port->dev);
+	if (list_empty(&port->dports))
+		return -EINVAL;
 
 	for (i = 0; i < cxld->nr_targets; i++) {
 		struct cxl_dport *dport = find_dport(port, target_map[i]);
 
-		if (!dport) {
-			rc = -ENXIO;
-			goto out_unlock;
-		}
+		if (!dport)
+			return -ENXIO;
 		cxld->target[i] = dport;
 	}
 
-out_unlock:
-	device_unlock(&port->dev);
-
 	return rc;
 }
 
@@ -548,7 +541,7 @@  int cxl_decoder_add(struct cxl_decoder *cxld, int *target_map)
 {
 	struct cxl_port *port;
 	struct device *dev;
-	int rc;
+	int rc = 0;
 
 	if (WARN_ON_ONCE(!cxld))
 		return -EINVAL;
@@ -562,11 +555,13 @@  int cxl_decoder_add(struct cxl_decoder *cxld, int *target_map)
 	dev = &cxld->dev;
 
 	port = to_cxl_port(cxld->dev.parent);
-	if (!is_endpoint_decoder(dev)) {
+
+	device_lock(&port->dev);
+	if (!is_endpoint_decoder(dev))
 		rc = decoder_populate_targets(cxld, port, target_map);
-		if (rc)
-			return rc;
-	}
+	device_unlock(&port->dev);
+	if (rc)
+		return rc;
 
 	rc = dev_set_name(dev, "decoder%d.%d", port->id, cxld->id);
 	if (rc)