aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cxl/core/port.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2022-02-01 12:24:30 -0800
committerDan Williams <dan.j.williams@intel.com>2022-02-08 22:57:30 -0800
commitd17d0540a0dbf109210f7b57a37571e2978da0fa (patch)
treed7f969f8c73c1134c480484ebb13a72a2950769e /drivers/cxl/core/port.c
parentcxl/core: Generalize dport enumeration in the core (diff)
downloadlinux-dev-d17d0540a0dbf109210f7b57a37571e2978da0fa.tar.xz
linux-dev-d17d0540a0dbf109210f7b57a37571e2978da0fa.zip
cxl/core/hdm: Add CXL standard decoder enumeration to the core
Unlike the decoder enumeration for "root decoders" described by platform firmware, standard decoders can be enumerated from the component registers space once the base address has been identified (via PCI, ACPI, or another mechanism). Add common infrastructure for HDM (Host-managed-Device-Memory) Decoder enumeration and share it between host-bridge, upstream switch port, and cxl_test defined decoders. The locking model for switch level decoders is to hold the port lock over the enumeration. This facilitates moving the dport and decoder enumeration to a 'port' driver. For now, the only enumerator of decoder resources is the cxl_acpi root driver. Co-developed-by: Ben Widawsky <ben.widawsky@intel.com> Signed-off-by: Ben Widawsky <ben.widawsky@intel.com> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Link: https://lore.kernel.org/r/164374688404.395335.9239248252443123526.stgit@dwillia2-desk3.amr.corp.intel.com Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/cxl/core/port.c')
-rw-r--r--drivers/cxl/core/port.c57
1 files changed, 45 insertions, 12 deletions
diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
index fee9c7affef4..4dfb9df9e648 100644
--- a/drivers/cxl/core/port.c
+++ b/drivers/cxl/core/port.c
@@ -594,16 +594,15 @@ EXPORT_SYMBOL_NS_GPL(devm_cxl_add_dport, CXL);
static int decoder_populate_targets(struct cxl_decoder *cxld,
struct cxl_port *port, int *target_map)
{
- int rc = 0, i;
+ int i, rc = 0;
if (!target_map)
return 0;
- cxl_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;
write_seqlock(&cxld->target_lock);
for (i = 0; i < cxld->nr_targets; i++) {
@@ -617,9 +616,6 @@ static int decoder_populate_targets(struct cxl_decoder *cxld,
}
write_sequnlock(&cxld->target_lock);
-out_unlock:
- cxl_device_unlock(&port->dev);
-
return rc;
}
@@ -721,7 +717,7 @@ struct cxl_decoder *cxl_switch_decoder_alloc(struct cxl_port *port,
EXPORT_SYMBOL_NS_GPL(cxl_switch_decoder_alloc, CXL);
/**
- * cxl_decoder_add - Add a decoder with targets
+ * cxl_decoder_add_locked - Add a decoder with targets
* @cxld: The cxl decoder allocated by cxl_decoder_alloc()
* @target_map: A list of downstream ports that this decoder can direct memory
* traffic to. These numbers should correspond with the port number
@@ -731,12 +727,15 @@ EXPORT_SYMBOL_NS_GPL(cxl_switch_decoder_alloc, CXL);
* is an endpoint device. A more awkward example is a hostbridge whose root
* ports get hot added (technically possible, though unlikely).
*
- * Context: Process context. Takes and releases the cxld's device lock.
+ * This is the locked variant of cxl_decoder_add().
+ *
+ * Context: Process context. Expects the device lock of the port that owns the
+ * @cxld to be held.
*
* Return: Negative error code if the decoder wasn't properly configured; else
* returns 0.
*/
-int cxl_decoder_add(struct cxl_decoder *cxld, int *target_map)
+int cxl_decoder_add_locked(struct cxl_decoder *cxld, int *target_map)
{
struct cxl_port *port;
struct device *dev;
@@ -770,6 +769,40 @@ int cxl_decoder_add(struct cxl_decoder *cxld, int *target_map)
return device_add(dev);
}
+EXPORT_SYMBOL_NS_GPL(cxl_decoder_add_locked, CXL);
+
+/**
+ * cxl_decoder_add - Add a decoder with targets
+ * @cxld: The cxl decoder allocated by cxl_decoder_alloc()
+ * @target_map: A list of downstream ports that this decoder can direct memory
+ * traffic to. These numbers should correspond with the port number
+ * in the PCIe Link Capabilities structure.
+ *
+ * This is the unlocked variant of cxl_decoder_add_locked().
+ * See cxl_decoder_add_locked().
+ *
+ * Context: Process context. Takes and releases the device lock of the port that
+ * owns the @cxld.
+ */
+int cxl_decoder_add(struct cxl_decoder *cxld, int *target_map)
+{
+ struct cxl_port *port;
+ int rc;
+
+ if (WARN_ON_ONCE(!cxld))
+ return -EINVAL;
+
+ if (WARN_ON_ONCE(IS_ERR(cxld)))
+ return PTR_ERR(cxld);
+
+ port = to_cxl_port(cxld->dev.parent);
+
+ cxl_device_lock(&port->dev);
+ rc = cxl_decoder_add_locked(cxld, target_map);
+ cxl_device_unlock(&port->dev);
+
+ return rc;
+}
EXPORT_SYMBOL_NS_GPL(cxl_decoder_add, CXL);
static void cxld_unregister(void *dev)