diff mbox

[ndctl,1/2] ndctl: add ndctl_dimm_get_unique_id() api

Message ID 146171504515.32030.1423804537625453932.stgit@dwillia2-desk3.amr.corp.intel.com (mailing list archive)
State Accepted
Commit af8ee17ca31d
Headers show

Commit Message

Dan Williams April 26, 2016, 11:57 p.m. UTC
ACPI 6.1 defines a common format for identifying a DIMM.  See section
5.2.25.9 "NVDIMM representation format".  If the kernel supports this
identifier it can be read from dimmX/nfit/id and retrieved via this api.
If the kernel does not export a dimm id this api returns NULL.

Cc: Toshi Kani <toshi.kani@hpe.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 lib/libndctl.c          |   38 +++++++++++++++++++++++++++++++-------
 lib/libndctl.sym        |    1 +
 lib/ndctl/libndctl.h.in |    1 +
 3 files changed, 33 insertions(+), 7 deletions(-)
diff mbox

Patch

diff --git a/lib/libndctl.c b/lib/libndctl.c
index 58b7fa9d6666..d33081cce8ed 100644
--- a/lib/libndctl.c
+++ b/lib/libndctl.c
@@ -129,6 +129,7 @@  struct ndctl_dimm {
 	unsigned short device_id;
 	unsigned short revision_id;
 	unsigned long dsm_mask;
+	char *unique_id;
 	char *dimm_path;
 	char *dimm_buf;
 	int buf_len;
@@ -587,6 +588,18 @@  static void free_region(struct ndctl_region *region)
 	free(region);
 }
 
+static void free_dimm(struct ndctl_dimm *dimm)
+{
+	if (!dimm)
+		return;
+	free(dimm->unique_id);
+	free(dimm->dimm_buf);
+	free(dimm->dimm_path);
+	if (dimm->module)
+		kmod_module_unref(dimm->module);
+	free(dimm);
+}
+
 static void free_bus(struct ndctl_bus *bus, struct list_head *head)
 {
 	struct ndctl_dimm *dimm, *_d;
@@ -594,10 +607,7 @@  static void free_bus(struct ndctl_bus *bus, struct list_head *head)
 
 	list_for_each_safe(&bus->dimms, dimm, _d, list) {
 		list_del_from(&bus->dimms, &dimm->list);
-		free(dimm->dimm_path);
-		free(dimm->dimm_buf);
-		kmod_module_unref(dimm->module);
-		free(dimm);
+		free_dimm(dimm);
 	}
 	list_for_each_safe(&bus->regions, region, _r, list)
 		free_region(region);
@@ -1245,6 +1255,17 @@  static int add_dimm(void *parent, int id, const char *dimm_base)
 	if (!ndctl_bus_has_nfit(bus))
 		goto out;
 
+	/*
+	 * 'unique_id' may not be available on older kernels, so don't
+	 * fail if the read fails.
+	 */
+	sprintf(path, "%s/nfit/id", dimm_base);
+	if (sysfs_read_attr(ctx, path, buf) == 0) {
+		dimm->unique_id = strdup(buf);
+		if (!dimm->unique_id)
+			goto err_read;
+	}
+
 	sprintf(path, "%s/nfit/handle", dimm_base);
 	if (sysfs_read_attr(ctx, path, buf) < 0)
 		goto err_read;
@@ -1293,9 +1314,7 @@  static int add_dimm(void *parent, int id, const char *dimm_base)
 	return 0;
 
  err_read:
-	free(dimm->dimm_buf);
-	free(dimm->dimm_path);
-	free(dimm);
+	free_dimm(dimm);
  err_dimm:
 	free(path);
 	return rc;
@@ -1381,6 +1400,11 @@  NDCTL_EXPORT unsigned int ndctl_dimm_get_id(struct ndctl_dimm *dimm)
 	return dimm->id;
 }
 
+NDCTL_EXPORT const char *ndctl_dimm_get_unique_id(struct ndctl_dimm *dimm)
+{
+	return dimm->unique_id;
+}
+
 NDCTL_EXPORT unsigned int ndctl_dimm_get_serial(struct ndctl_dimm *dimm)
 {
 	return dimm->serial;
diff --git a/lib/libndctl.sym b/lib/libndctl.sym
index 17a9085dd092..06dd50a6bb15 100644
--- a/lib/libndctl.sym
+++ b/lib/libndctl.sym
@@ -47,6 +47,7 @@  global:
 	ndctl_dimm_get_minor;
 	ndctl_dimm_get_serial;
 	ndctl_dimm_get_id;
+	ndctl_dimm_get_unique_id;
 	ndctl_dimm_get_devname;
 	ndctl_dimm_get_cmd_name;
 	ndctl_dimm_has_errors;
diff --git a/lib/ndctl/libndctl.h.in b/lib/ndctl/libndctl.h.in
index 4b0b25fb7cba..29845eb88843 100644
--- a/lib/ndctl/libndctl.h.in
+++ b/lib/ndctl/libndctl.h.in
@@ -126,6 +126,7 @@  int ndctl_dimm_get_formatN(struct ndctl_dimm *dimm, int i);
 unsigned int ndctl_dimm_get_major(struct ndctl_dimm *dimm);
 unsigned int ndctl_dimm_get_minor(struct ndctl_dimm *dimm);
 unsigned int ndctl_dimm_get_id(struct ndctl_dimm *dimm);
+const char *ndctl_dimm_get_unique_id(struct ndctl_dimm *dimm);
 unsigned int ndctl_dimm_get_serial(struct ndctl_dimm *dimm);
 const char *ndctl_dimm_get_cmd_name(struct ndctl_dimm *dimm, int cmd);
 int ndctl_dimm_is_cmd_supported(struct ndctl_dimm *dimm, int cmd);