cxl/pmem: Add support for multiple nvdimm-bridge objects
authorDan Williams <dan.j.williams@intel.com>
Tue, 14 Sep 2021 19:08:40 +0000 (12:08 -0700)
committerDan Williams <dan.j.williams@intel.com>
Tue, 21 Sep 2021 20:47:10 +0000 (13:47 -0700)
In preparation for a mocked unit test environment for CXL objects, allow
for multiple unique nvdimm-bridge objects.

For now, just allow multiple bridges to be registered. Later, when there
are multiple present, further updates are needed to
cxl_find_nvdimm_bridge() to identify which bridge is associated with
which CXL hierarchy for nvdimm registration.

Note that this does change the kernel device-name for the bridge object.
User space should not have any attachment to the device name at this
point as it is still early days in the CXL driver development.

Acked-by: Ben Widawsky <ben.widawsky@intel.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Link: https://lore.kernel.org/r/163164647007.2831228.2150246954620721526.stgit@dwillia2-desk3.amr.corp.intel.com
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
drivers/cxl/core/pmem.c
drivers/cxl/cxl.h
drivers/cxl/pmem.c

index d24570f5b8ba06d7342de38d156ee385993dace9..9e56be3994f1062b641a34234a4fa4a4e352f1f6 100644 (file)
@@ -2,6 +2,7 @@
 /* Copyright(c) 2020 Intel Corporation. */
 #include <linux/device.h>
 #include <linux/slab.h>
+#include <linux/idr.h>
 #include <cxlmem.h>
 #include <cxl.h>
 #include "core.h"
  * operations, for example, namespace label access commands.
  */
 
+static DEFINE_IDA(cxl_nvdimm_bridge_ida);
+
 static void cxl_nvdimm_bridge_release(struct device *dev)
 {
        struct cxl_nvdimm_bridge *cxl_nvb = to_cxl_nvdimm_bridge(dev);
 
+       ida_free(&cxl_nvdimm_bridge_ida, cxl_nvb->id);
        kfree(cxl_nvb);
 }
 
@@ -47,16 +51,38 @@ struct cxl_nvdimm_bridge *to_cxl_nvdimm_bridge(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(to_cxl_nvdimm_bridge);
 
+static int match_nvdimm_bridge(struct device *dev, const void *data)
+{
+       return dev->type == &cxl_nvdimm_bridge_type;
+}
+
+struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(void)
+{
+       struct device *dev;
+
+       dev = bus_find_device(&cxl_bus_type, NULL, NULL, match_nvdimm_bridge);
+       if (!dev)
+               return NULL;
+       return to_cxl_nvdimm_bridge(dev);
+}
+EXPORT_SYMBOL_GPL(cxl_find_nvdimm_bridge);
+
 static struct cxl_nvdimm_bridge *
 cxl_nvdimm_bridge_alloc(struct cxl_port *port)
 {
        struct cxl_nvdimm_bridge *cxl_nvb;
        struct device *dev;
+       int rc;
 
        cxl_nvb = kzalloc(sizeof(*cxl_nvb), GFP_KERNEL);
        if (!cxl_nvb)
                return ERR_PTR(-ENOMEM);
 
+       rc = ida_alloc(&cxl_nvdimm_bridge_ida, GFP_KERNEL);
+       if (rc < 0)
+               goto err;
+       cxl_nvb->id = rc;
+
        dev = &cxl_nvb->dev;
        cxl_nvb->port = port;
        cxl_nvb->state = CXL_NVB_NEW;
@@ -67,6 +93,10 @@ cxl_nvdimm_bridge_alloc(struct cxl_port *port)
        dev->type = &cxl_nvdimm_bridge_type;
 
        return cxl_nvb;
+
+err:
+       kfree(cxl_nvb);
+       return ERR_PTR(rc);
 }
 
 static void unregister_nvb(void *_cxl_nvb)
@@ -119,7 +149,7 @@ struct cxl_nvdimm_bridge *devm_cxl_add_nvdimm_bridge(struct device *host,
                return cxl_nvb;
 
        dev = &cxl_nvb->dev;
-       rc = dev_set_name(dev, "nvdimm-bridge");
+       rc = dev_set_name(dev, "nvdimm-bridge%d", cxl_nvb->id);
        if (rc)
                goto err;
 
index 53927f9fa77e460392c84eb86ab53da0337e72ea..1b2e816e061ee1b9df78c627c6eb8ae1ffbeaaee 100644 (file)
@@ -211,6 +211,7 @@ enum cxl_nvdimm_brige_state {
 };
 
 struct cxl_nvdimm_bridge {
+       int id;
        struct device dev;
        struct cxl_port *port;
        struct nvdimm_bus *nvdimm_bus;
@@ -323,4 +324,5 @@ struct cxl_nvdimm_bridge *devm_cxl_add_nvdimm_bridge(struct device *host,
 struct cxl_nvdimm *to_cxl_nvdimm(struct device *dev);
 bool is_cxl_nvdimm(struct device *dev);
 int devm_cxl_add_nvdimm(struct device *host, struct cxl_memdev *cxlmd);
+struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(void);
 #endif /* __CXL_H__ */
index bc1466b0e9998119deaa337f4bc5fd9d8ac36a3e..5ccf9aa6b3aebbfe8c2dc60a2fa34b69d7483eef 100644 (file)
@@ -29,21 +29,6 @@ static void unregister_nvdimm(void *nvdimm)
        nvdimm_delete(nvdimm);
 }
 
-static int match_nvdimm_bridge(struct device *dev, const void *data)
-{
-       return strcmp(dev_name(dev), "nvdimm-bridge") == 0;
-}
-
-static struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(void)
-{
-       struct device *dev;
-
-       dev = bus_find_device(&cxl_bus_type, NULL, NULL, match_nvdimm_bridge);
-       if (!dev)
-               return NULL;
-       return to_cxl_nvdimm_bridge(dev);
-}
-
 static int cxl_nvdimm_probe(struct device *dev)
 {
        struct cxl_nvdimm *cxl_nvd = to_cxl_nvdimm(dev);