@@ -10,7 +10,8 @@ ndctl_SOURCES = ndctl.c \
../util/log.c \
builtin-list.c \
builtin-test.c \
- ../util/json.c
+ ../util/json.c \
+ util/json-msft.c
if ENABLE_SMART
ndctl_SOURCES += util/json-smart.c
@@ -349,7 +349,11 @@ int cmd_list(int argc, const char **argv, void *ctx)
if (list.health) {
struct json_object *jhealth;
- jhealth = util_dimm_health_to_json(dimm);
+ if (ndctl_dimm_get_dsm_family(dimm) == NVDIMM_FAMILY_MSFT)
+ jhealth = util_dimm_health_to_json_msft(dimm);
+ else
+ jhealth = util_dimm_health_to_json(dimm);
+
if (jhealth)
json_object_object_add(jdimm, "health",
jhealth);
@@ -1361,6 +1361,11 @@ NDCTL_EXPORT unsigned char ndctl_dimm_get_manufacturing_location(
return dimm->manufacturing_location;
}
+NDCTL_EXPORT unsigned long ndctl_dimm_get_dsm_family(struct ndctl_dimm *dimm)
+{
+ return dimm->dsm_family;
+}
+
NDCTL_EXPORT unsigned short ndctl_dimm_get_format(struct ndctl_dimm *dimm)
{
return dimm->format[0];
@@ -48,6 +48,7 @@ global:
ndctl_dimm_get_subsystem_vendor;
ndctl_dimm_get_subsystem_device;
ndctl_dimm_get_subsystem_revision;
+ ndctl_dimm_get_dsm_family;
ndctl_dimm_get_format;
ndctl_dimm_get_formats;
ndctl_dimm_get_formatN;
new file mode 100644
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016-2017 Dell, Inc.
+ * Author: Lijun Pan <Lijun.Pan@dell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ */
+
+#ifndef _NDCTL_DELL_H_
+#define _NDCTL_DELL_H_
+
+#define DEV_NAME_MAX_LENGTH 12
+#define DEV_ID_MAX_LENGTH 3
+#define DEV_ID_MAX 128
+
+/* REFER TO SPEC https://msdn.microsoft.com/en-us/library/windows/hardware/mt604741(v=vs.85).aspx */
+#define SIZE_IN_FUNC0 0
+#define SIZE_IN_FUNC1 0
+#define SIZE_IN_FUNC2 0
+#define SIZE_IN_FUNC3 0
+#define SIZE_IN_FUNC4 0
+#define SIZE_IN_FUNC5 0
+#define SIZE_IN_FUNC7 0
+#define SIZE_IN_FUNC10 0
+#define SIZE_IN_FUNC11 0
+#define SIZE_IN_FUNC12 0
+
+#define SIZE_OUT_FUNC0 4
+#define SIZE_OUT_FUNC1 50
+#define SIZE_OUT_FUNC2 12
+#define SIZE_OUT_FUNC3 19
+#define SIZE_OUT_FUNC4 12
+#define SIZE_OUT_FUNC5 6
+#define SIZE_OUT_FUNC7 8
+#define SIZE_OUT_FUNC10 5
+#define SIZE_OUT_FUNC11 13
+#define SIZE_OUT_FUNC12 11
+#define SIZE_OUT_MAX 50
+
+#define FUNC0 0
+#define FUNC1 1
+#define FUNC2 2
+#define FUNC3 3
+#define FUNC4 4
+#define FUNC5 5
+#define FUNC7 7
+#define FUNC10 10
+#define FUNC11 11
+#define FUNC12 12
+
+#endif
@@ -129,6 +129,7 @@ unsigned short ndctl_dimm_get_subsystem_device(struct ndctl_dimm *dimm);
unsigned short ndctl_dimm_get_manufacturing_date(struct ndctl_dimm *dimm);
unsigned char ndctl_dimm_get_manufacturing_location(struct ndctl_dimm *dimm);
unsigned short ndctl_dimm_get_subsystem_revision(struct ndctl_dimm *dimm);
+unsigned long ndctl_dimm_get_dsm_family(struct ndctl_dimm *dimm);
unsigned short ndctl_dimm_get_format(struct ndctl_dimm *dimm);
int ndctl_dimm_get_formats(struct ndctl_dimm *dimm);
int ndctl_dimm_get_formatN(struct ndctl_dimm *dimm, int i);
new file mode 100644
@@ -0,0 +1,125 @@
+#include <limits.h>
+#include <util/json.h>
+#include <uuid/uuid.h>
+#include <json-c/json.h>
+#include <ndctl/libndctl.h>
+#include <ccan/array_size/array_size.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/ioctl.h>
+
+#ifdef HAVE_NDCTL_H
+#include <linux/ndctl.h>
+#else
+#include <ndctl.h>
+#endif
+
+#include "ndctl-msft.h"
+
+static int call_func(int func_num, int size_in, int size_out,
+ int fd, unsigned char *payload) {
+ struct nd_cmd_pkg *pkg;
+ int error;
+ int i;
+
+ memset(payload, 0, SIZE_OUT_MAX);
+ pkg = malloc(sizeof(struct nd_cmd_pkg) + size_in + size_out);
+ if (!pkg)
+ return -ENOMEM;
+
+ pkg->nd_family = NVDIMM_FAMILY_MSFT;
+ pkg->nd_command = func_num;
+ pkg->nd_size_in = size_in;
+ pkg->nd_size_out = size_out;
+ pkg->nd_fw_size = 0;
+
+ for (i = 0; i < 9; i++)
+ pkg->nd_reserved2[i] = 0;
+
+ for (i = 0; i < size_in; i++)
+ pkg->nd_payload[i] = 0;
+
+ for (i = 0; i < size_out; i++)
+ pkg->nd_payload[i + size_in] = 0;
+
+ error = ioctl(fd, ND_IOCTL_CALL, pkg);
+
+ if (error) {
+ fprintf(stderr, "ioctl returned errno %d\n", errno);
+ free(pkg);
+ return error;
+ }
+
+ for (i = 0; i < size_out; i++)
+ payload[i] = pkg->nd_payload[i + size_in];
+
+ free(pkg);
+ return 0;
+}
+
+struct json_object *util_dimm_health_to_json_msft(struct ndctl_dimm *dimm)
+{
+
+ struct json_object *jhealth = json_object_new_object();
+ struct json_object *jobj;
+ char dev_name[DEV_NAME_MAX_LENGTH + 1];
+ unsigned char payload[SIZE_OUT_MAX];
+ char str[100];
+ int fd;
+ int error;
+ int number;
+ double temp;
+
+ memset(dev_name, 0, DEV_NAME_MAX_LENGTH + 1);
+ snprintf(dev_name, DEV_NAME_MAX_LENGTH + 1, "/dev/nmem%d", ndctl_dimm_get_id(dimm));
+ fd = open(dev_name, O_RDWR);
+ if (fd == -1) {
+ fprintf(stderr, "error opening %s errno=%d\n", dev_name, errno);
+ goto err_fd;
+ }
+
+ error = call_func(FUNC10, SIZE_IN_FUNC10, SIZE_OUT_FUNC10, fd, payload);
+ if (!error) {
+ if (!!(payload[4] & 0x0F))
+ jobj = json_object_new_string("critical");
+ else
+ jobj = json_object_new_string("ok");
+ if (jobj)
+ json_object_object_add(jhealth, "health_state", jobj);
+ }
+
+ error = call_func(FUNC11, SIZE_IN_FUNC11, SIZE_OUT_FUNC11, fd, payload);
+ if (!error) {
+ /* refer to JESD245 spec section 7.8 to calculate the temperature */
+ number = (payload[7] & 0x0F) << 4 | (payload[6] & 0xF0) >> 4;
+ temp = number + !!(payload[6] & 0x08) * 0.5 + !!(payload[6] & 0x04) * 0.25;
+ jobj = json_object_new_double(temp);
+ if (jobj)
+ json_object_object_add(jhealth, "temperature_celsius", jobj);
+
+ memset(str, 0, 100);
+ snprintf(str, 100, "%d%%", payload[10]);
+ jobj = json_object_new_string(str);
+ if (jobj)
+ json_object_object_add(jhealth, "NVM_Lifetime", jobj);
+ }
+
+ error = call_func(FUNC4, SIZE_IN_FUNC4, SIZE_OUT_FUNC4, fd, payload);
+ if (!error) {
+ if (!!(payload[4] & 0x1))
+ jobj = json_object_new_string("success");
+ else
+ jobj = json_object_new_string("failure");
+ if (jobj)
+ json_object_object_add(jhealth, "last_save_operation", jobj);
+ }
+
+ close(fd);
+ return jhealth;
+
+err_fd:
+ json_object_put(jhealth);
+
+ return NULL;
+}
@@ -29,4 +29,5 @@ static inline struct json_object *util_dimm_health_to_json(
return NULL;
}
#endif
+struct json_object *util_dimm_health_to_json_msft(struct ndctl_dimm *dimm);
#endif /* __NDCTL_JSON_H__ */