diff mbox

[4/6] libnvdimm/of: Symlink platform and region devices

Message ID 20180323081209.31387-4-oohall@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Oliver O'Halloran March 23, 2018, 8:12 a.m. UTC
Add a way direct link between the region and the platform device that
creates the region.

Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
---
 drivers/nvdimm/of_nvdimm.c   | 11 +++++++++++
 drivers/nvdimm/region_devs.c | 13 +++++++++++++
 include/linux/libnvdimm.h    |  1 +
 3 files changed, 25 insertions(+)

Comments

Dan Williams March 23, 2018, 5:08 p.m. UTC | #1
On Fri, Mar 23, 2018 at 1:12 AM, Oliver O'Halloran <oohall@gmail.com> wrote:
> Add a way direct link between the region and the platform device that
> creates the region.
>

This linking would not be needed if of_nd_regions each lived on their own bus.
diff mbox

Patch

diff --git a/drivers/nvdimm/of_nvdimm.c b/drivers/nvdimm/of_nvdimm.c
index 79c28291f420..28f4ca23a690 100644
--- a/drivers/nvdimm/of_nvdimm.c
+++ b/drivers/nvdimm/of_nvdimm.c
@@ -37,6 +37,7 @@  static int of_nd_region_probe(struct platform_device *pdev)
 	struct resource temp_res;
 	struct nd_region *region;
 	struct device_node *np;
+	int rc;
 
 	np = dev_of_node(&pdev->dev);
 	if (!np)
@@ -71,6 +72,15 @@  static int of_nd_region_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, region);
 
+	/*
+	 * Add a symlink to the ndbus region object. Without this there's no
+	 * simple way to go from the platform device to the region it spawned.
+	 */
+	rc = sysfs_create_link(&pdev->dev.kobj,
+				nd_region_kobj(region), "region");
+	if (rc)
+		pr_warn("Failed to create symlink to region (rc = %d)!\n", rc);
+
 	return 0;
 }
 
@@ -78,6 +88,7 @@  static int of_nd_region_remove(struct platform_device *pdev)
 {
 	struct nd_region *r = platform_get_drvdata(pdev);
 
+	sysfs_delete_link(&pdev->dev.kobj, nd_region_kobj(r), "region");
 	nd_region_destroy(r);
 
 	return 0;
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
index 76f46fd1fae0..af09acc1d93b 100644
--- a/drivers/nvdimm/region_devs.c
+++ b/drivers/nvdimm/region_devs.c
@@ -1054,6 +1054,19 @@  struct nd_region *nvdimm_volatile_region_create(struct nvdimm_bus *nvdimm_bus,
 }
 EXPORT_SYMBOL_GPL(nvdimm_volatile_region_create);
 
+struct kobject *nd_region_kobj(struct nd_region *region)
+{
+	/*
+	 * region init is async so we need to explicitly synchronise
+	 * to prevent handing out a kobj reference before device_add()
+	 * has been run
+	 */
+	nd_synchronize();
+
+	return &region->dev.kobj;
+}
+EXPORT_SYMBOL_GPL(nd_region_kobj);
+
 /**
  * nvdimm_flush - flush any posted write queues between the cpu and pmem media
  * @nd_region: blk or interleaved pmem region
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
index df21ca176e98..a4b3663bac38 100644
--- a/include/linux/libnvdimm.h
+++ b/include/linux/libnvdimm.h
@@ -172,6 +172,7 @@  struct nvdimm_bus_descriptor *to_nd_desc(struct nvdimm_bus *nvdimm_bus);
 struct device *to_nvdimm_bus_dev(struct nvdimm_bus *nvdimm_bus);
 const char *nvdimm_name(struct nvdimm *nvdimm);
 struct kobject *nvdimm_kobj(struct nvdimm *nvdimm);
+struct kobject *nd_region_kobj(struct nd_region *region);
 unsigned long nvdimm_cmd_mask(struct nvdimm *nvdimm);
 void *nvdimm_provider_data(struct nvdimm *nvdimm);
 struct nvdimm *nvdimm_create(struct nvdimm_bus *nvdimm_bus, void *provider_data,