Commit 2e52b625 authored by Dan Williams's avatar Dan Williams

cxl/pmem: Add support for multiple nvdimm-bridge objects

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: default avatarBen Widawsky <ben.widawsky@intel.com>
Reviewed-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
Link: https://lore.kernel.org/r/163164647007.2831228.2150246954620721526.stgit@dwillia2-desk3.amr.corp.intel.comSigned-off-by: default avatarDan Williams <dan.j.williams@intel.com>
parent 60b8f172
......@@ -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"
......@@ -20,10 +21,13 @@
* 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;
......
......@@ -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__ */
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment