This patch introduces a set of ndctl_smart_ops for the HPE1 DSM family.
The implementation calls the HPE1 DSM functions defined in [1] and
translates the results to match the existing Intel DSM-inspired
smart_ops.  This delivers health reporting parity for HPE type N
NVDIMMs, but we are planning a future patch to add reporting for some of
the additional health data defined in [1].

[1] 
https://github.com/HewlettPackard/hpe-nvm/raw/master/Documentation/NFIT_DSM_DDR4_NVDIMM-N_v84s.pdf

Cc: Dan Williams <dan.j.willi...@intel.com>
Signed-off-by: Brian Boylston <brian.boyls...@hpe.com>
---
Changes in v3:
  - Added missing bibliography to the commit message.
  - I realized that v2 wouldn't compile if HAS_SMART was not 1, so I
    changed intel_smart_ops and hpe1_smart_ops into pointers and set them
    to NULL if HAS_SMART != 1.  They are const because that seems to
    avoid compiler warnings about unused variables in cases where
    libndctl-private.h is included by something other than libndctl.c.

 ndctl/Makefile.am            |   1 +
 ndctl/lib/libndctl-hpe1.c    | 303 ++++++++++++++++++++++++++++++++++++++
 ndctl/lib/libndctl-private.h |   2 +
 ndctl/lib/libndctl.c         |   2 +
 ndctl/lib/ndctl-hpe1.h       | 335 +++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 643 insertions(+)
 create mode 100644 ndctl/lib/libndctl-hpe1.c
 create mode 100644 ndctl/lib/ndctl-hpe1.h

diff --git a/ndctl/Makefile.am b/ndctl/Makefile.am
index 04f3a63..fdec355 100644
--- a/ndctl/Makefile.am
+++ b/ndctl/Makefile.am
@@ -31,6 +31,7 @@ endif
 
 if ENABLE_SMART
 lib_libndctl_la_SOURCES += lib/libndctl-smart.c
+lib_libndctl_la_SOURCES += lib/libndctl-hpe1.c
 endif
 
 bin_PROGRAMS = ndctl
diff --git a/ndctl/lib/libndctl-hpe1.c b/ndctl/lib/libndctl-hpe1.c
new file mode 100644
index 0000000..48d8e02
--- /dev/null
+++ b/ndctl/lib/libndctl-hpe1.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2016 Hewlett Packard Enterprise Development LP
+ * Copyright (c) 2016, Intel Corporation.
+ *
+ * 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.
+ */
+#include <stdlib.h>
+#include <limits.h>
+#include <util/log.h>
+#include <ndctl/libndctl.h>
+#include "libndctl-private.h"
+
+#include "ndctl-hpe1.h"
+
+#define CMD_HPE1(_c) ((struct ndn_pkg_hpe1 *)((_c)->cmd_buf))
+#define CMD_HPE1_SMART(_c) \
+       ((struct ndn_hpe1_smart_data *)(CMD_HPE1(_c)->u.smart.data))
+#define CMD_HPE1_SMART_THRESH(_c) \
+       ((struct ndn_hpe1_smart_threshold_data *)(CMD_HPE1(_c)->u.thresh.data))
+
+static struct ndctl_cmd *hpe1_dimm_cmd_new_smart(struct ndctl_dimm *dimm)
+{
+       struct ndctl_bus *bus = ndctl_dimm_get_bus(dimm);
+       struct ndctl_ctx *ctx = ndctl_bus_get_ctx(bus);
+       struct ndctl_cmd *cmd;
+       size_t size;
+       struct ndn_pkg_hpe1 *hpe1;
+
+       if (!ndctl_dimm_is_cmd_supported(dimm, ND_CMD_CALL)) {
+               dbg(ctx, "unsupported cmd\n");
+               return NULL;
+       }
+
+       size = sizeof(*cmd) + sizeof(struct ndn_pkg_hpe1);
+       cmd = calloc(1, size);
+       if (!cmd)
+               return NULL;
+
+       cmd->dimm = dimm;
+       ndctl_cmd_ref(cmd);
+       cmd->type = ND_CMD_CALL;
+       cmd->size = size;
+       cmd->status = 1;
+
+       hpe1 = CMD_HPE1(cmd);
+       hpe1->gen.nd_family = NVDIMM_FAMILY_HPE1;
+       hpe1->gen.nd_command = NDN_HPE1_CMD_SMART;
+       hpe1->gen.nd_fw_size = 0;
+       hpe1->gen.nd_size_in = offsetof(struct ndn_hpe1_smart, status);
+       hpe1->gen.nd_size_out = sizeof(hpe1->u.smart);
+       hpe1->u.smart.status = 3;
+
+       hpe1->u.smart.in_valid_flags = 0;
+       hpe1->u.smart.in_valid_flags |= NDN_HPE1_SMART_HEALTH_VALID;
+       hpe1->u.smart.in_valid_flags |= NDN_HPE1_SMART_TEMP_VALID;
+       hpe1->u.smart.in_valid_flags |= NDN_HPE1_SMART_SPARES_VALID;
+       hpe1->u.smart.in_valid_flags |= NDN_HPE1_SMART_ALARM_VALID;
+       hpe1->u.smart.in_valid_flags |= NDN_HPE1_SMART_USED_VALID;
+       hpe1->u.smart.in_valid_flags |= NDN_HPE1_SMART_SHUTDOWN_VALID;
+       hpe1->u.smart.in_valid_flags |= NDN_HPE1_SMART_VENDOR_VALID;
+
+       cmd->firmware_status = &hpe1->u.smart.status;
+
+       return cmd;
+}
+
+static int hpe1_smart_valid(struct ndctl_cmd *cmd)
+{
+       if (cmd->type != ND_CMD_CALL ||
+           cmd->size != sizeof(*cmd) + sizeof(struct ndn_pkg_hpe1) ||
+           CMD_HPE1(cmd)->gen.nd_family != NVDIMM_FAMILY_HPE1 ||
+           CMD_HPE1(cmd)->gen.nd_command != NDN_HPE1_CMD_SMART ||
+           cmd->status != 0)
+               return cmd->status < 0 ? cmd->status : -EINVAL;
+       return 0;
+}
+
+static unsigned int hpe1_cmd_smart_get_flags(struct ndctl_cmd *cmd)
+{
+       unsigned int hpe1flags;
+       unsigned int flags;
+
+       if (hpe1_smart_valid(cmd) < 0)
+               return UINT_MAX;
+
+       hpe1flags = CMD_HPE1_SMART(cmd)->out_valid_flags;
+       flags = 0;
+       if (hpe1flags & NDN_HPE1_SMART_HEALTH_VALID)
+               flags |= ND_SMART_HEALTH_VALID;
+       if (hpe1flags & NDN_HPE1_SMART_TEMP_VALID)
+               flags |= ND_SMART_TEMP_VALID ;
+       if (hpe1flags & NDN_HPE1_SMART_SPARES_VALID)
+               flags |= ND_SMART_SPARES_VALID;
+       if (hpe1flags & NDN_HPE1_SMART_ALARM_VALID)
+               flags |= ND_SMART_ALARM_VALID;
+       if (hpe1flags & NDN_HPE1_SMART_USED_VALID)
+               flags |= ND_SMART_USED_VALID;
+       if (hpe1flags & NDN_HPE1_SMART_SHUTDOWN_VALID)
+               flags |= ND_SMART_SHUTDOWN_VALID;
+       if (hpe1flags & NDN_HPE1_SMART_VENDOR_VALID)
+               flags |= ND_SMART_VENDOR_VALID;
+
+       return flags;
+}
+
+static unsigned int hpe1_cmd_smart_get_health(struct ndctl_cmd *cmd)
+{
+       unsigned char hpe1health;
+       unsigned int health;
+
+       if (hpe1_smart_valid(cmd) < 0)
+               return UINT_MAX;
+
+       hpe1health = CMD_HPE1_SMART(cmd)->stat_summary;
+       health = 0;
+       if (hpe1health & NDN_HPE1_SMART_NONCRIT_HEALTH)
+               health |= ND_SMART_NON_CRITICAL_HEALTH;;
+       if (hpe1health & NDN_HPE1_SMART_CRITICAL_HEALTH)
+               health |= ND_SMART_CRITICAL_HEALTH;
+       if (hpe1health & NDN_HPE1_SMART_FATAL_HEALTH)
+               health |= ND_SMART_FATAL_HEALTH;
+
+       return health;
+}
+
+static unsigned int hpe1_cmd_smart_get_temperature(struct ndctl_cmd *cmd)
+{
+       if (hpe1_smart_valid(cmd) < 0)
+               return UINT_MAX;
+
+       return CMD_HPE1_SMART(cmd)->curr_temp;
+}
+
+static unsigned int hpe1_cmd_smart_get_spares(struct ndctl_cmd *cmd)
+{
+       if (hpe1_smart_valid(cmd) < 0)
+               return UINT_MAX;
+
+       return CMD_HPE1_SMART(cmd)->spare_blocks;
+}
+
+static unsigned int hpe1_cmd_smart_get_alarm_flags(struct ndctl_cmd *cmd)
+{
+       unsigned int hpe1flags;
+       unsigned int flags;
+
+       if (hpe1_smart_valid(cmd) < 0)
+               return UINT_MAX;
+
+       hpe1flags = CMD_HPE1_SMART(cmd)->alarm_trips;
+       flags = 0;
+       if (hpe1flags & NDN_HPE1_SMART_TEMP_TRIP)
+               flags |= ND_SMART_TEMP_TRIP;
+       if (hpe1flags & NDN_HPE1_SMART_SPARE_TRIP)
+               flags |= ND_SMART_SPARE_TRIP;
+
+       return flags;
+}
+
+static unsigned int hpe1_cmd_smart_get_life_used(struct ndctl_cmd *cmd)
+{
+       if (hpe1_smart_valid(cmd) < 0)
+               return UINT_MAX;
+
+       return CMD_HPE1_SMART(cmd)->device_life;
+}
+
+static unsigned int hpe1_cmd_smart_get_shutdown_state(struct ndctl_cmd *cmd)
+{
+       unsigned int shutdown;
+
+       if (hpe1_smart_valid(cmd) < 0)
+               return UINT_MAX;
+
+       shutdown = CMD_HPE1_SMART(cmd)->last_shutdown_stat;
+       if (shutdown == NDN_HPE1_SMART_LASTSAVEGOOD)
+               return 0;
+       else
+               return 1;
+}
+
+static unsigned int hpe1_cmd_smart_get_vendor_size(struct ndctl_cmd *cmd)
+{
+       if (hpe1_smart_valid(cmd) < 0)
+               return UINT_MAX;
+
+       return CMD_HPE1_SMART(cmd)->vndr_spec_data_size;
+}
+
+static unsigned char *hpe1_cmd_smart_get_vendor_data(struct ndctl_cmd *cmd)
+{
+       if (hpe1_smart_valid(cmd) < 0)
+               return NULL;
+
+       return CMD_HPE1_SMART(cmd)->vnd_spec_data;
+}
+
+
+static struct ndctl_cmd *hpe1_dimm_cmd_new_smart_threshold(struct ndctl_dimm 
*dimm)
+{
+       struct ndctl_bus *bus = ndctl_dimm_get_bus(dimm);
+       struct ndctl_ctx *ctx = ndctl_bus_get_ctx(bus);
+       struct ndctl_cmd *cmd;
+       size_t size;
+       struct ndn_pkg_hpe1 *hpe1;
+
+       if (!ndctl_dimm_is_cmd_supported(dimm, ND_CMD_CALL)) {
+               dbg(ctx, "unsupported cmd\n");
+               return NULL;
+       }
+
+       size = sizeof(*cmd) + sizeof(struct ndn_pkg_hpe1);
+       cmd = calloc(1, size);
+       if (!cmd)
+               return NULL;
+
+       cmd->dimm = dimm;
+       ndctl_cmd_ref(cmd);
+       cmd->type = ND_CMD_CALL;
+       cmd->size = size;
+       cmd->status = 1;
+
+       hpe1 = CMD_HPE1(cmd);
+       hpe1->gen.nd_family = NVDIMM_FAMILY_HPE1;
+       hpe1->gen.nd_command = NDN_HPE1_CMD_SMART_THRESHOLD;
+       hpe1->gen.nd_fw_size = 0;
+       hpe1->gen.nd_size_in = offsetof(struct ndn_hpe1_smart_threshold, 
status);
+       hpe1->gen.nd_size_out = sizeof(hpe1->u.smart);
+       hpe1->u.thresh.status = 3;
+
+       cmd->firmware_status = &hpe1->u.thresh.status;
+
+       return cmd;
+}
+
+static int hpe1_smart_threshold_valid(struct ndctl_cmd *cmd)
+{
+       if (cmd->type != ND_CMD_CALL ||
+           cmd->size != sizeof(*cmd) + sizeof(struct ndn_pkg_hpe1) ||
+           CMD_HPE1(cmd)->gen.nd_family != NVDIMM_FAMILY_HPE1 ||
+           CMD_HPE1(cmd)->gen.nd_command != NDN_HPE1_CMD_SMART_THRESHOLD ||
+           cmd->status != 0)
+               return cmd->status < 0 ? cmd->status : -EINVAL;
+       return 0;
+}
+
+static unsigned int hpe1_cmd_smart_threshold_get_alarm_control(struct 
ndctl_cmd *cmd)
+{
+       unsigned int hpe1flags;
+       unsigned int flags;
+
+       if (hpe1_smart_threshold_valid(cmd) < 0)
+               return UINT_MAX;
+
+       hpe1flags = CMD_HPE1_SMART_THRESH(cmd)->threshold_alarm_ctl;
+       flags = 0;
+       if (hpe1flags & NDN_HPE1_SMART_TEMP_TRIP)
+               flags |= ND_SMART_TEMP_TRIP;
+       if (hpe1flags & NDN_HPE1_SMART_SPARE_TRIP)
+               flags |= ND_SMART_SPARE_TRIP;
+
+       return flags;
+}
+
+static unsigned int hpe1_cmd_smart_threshold_get_temperature(struct ndctl_cmd 
*cmd)
+{
+       if (hpe1_smart_threshold_valid(cmd) < 0)
+               return UINT_MAX;
+
+       return CMD_HPE1_SMART_THRESH(cmd)->temp_threshold;
+}
+
+static unsigned int hpe1_cmd_smart_threshold_get_spares(struct ndctl_cmd *cmd)
+{
+       if (hpe1_smart_threshold_valid(cmd) < 0)
+               return UINT_MAX;
+
+       return CMD_HPE1_SMART_THRESH(cmd)->spare_block_threshold;
+}
+
+struct ndctl_smart_ops * const hpe1_smart_ops = &(struct ndctl_smart_ops) {
+       .new_smart = hpe1_dimm_cmd_new_smart,
+       .smart_get_flags = hpe1_cmd_smart_get_flags,
+       .smart_get_health = hpe1_cmd_smart_get_health,
+       .smart_get_temperature = hpe1_cmd_smart_get_temperature,
+       .smart_get_spares = hpe1_cmd_smart_get_spares,
+       .smart_get_alarm_flags = hpe1_cmd_smart_get_alarm_flags,
+       .smart_get_life_used = hpe1_cmd_smart_get_life_used,
+       .smart_get_shutdown_state = hpe1_cmd_smart_get_shutdown_state,
+       .smart_get_vendor_size = hpe1_cmd_smart_get_vendor_size,
+       .smart_get_vendor_data = hpe1_cmd_smart_get_vendor_data,
+       .new_smart_threshold = hpe1_dimm_cmd_new_smart_threshold,
+       .smart_threshold_get_alarm_control = 
hpe1_cmd_smart_threshold_get_alarm_control,
+       .smart_threshold_get_temperature = 
hpe1_cmd_smart_threshold_get_temperature,
+       .smart_threshold_get_spares = hpe1_cmd_smart_threshold_get_spares,
+};
diff --git a/ndctl/lib/libndctl-private.h b/ndctl/lib/libndctl-private.h
index 5ff4fec..4363f23 100644
--- a/ndctl/lib/libndctl-private.h
+++ b/ndctl/lib/libndctl-private.h
@@ -220,8 +220,10 @@ struct ndctl_smart_ops {
 
 #if HAS_SMART == 1
 struct ndctl_smart_ops * const intel_smart_ops;
+struct ndctl_smart_ops * const hpe1_smart_ops;
 #else
 static struct ndctl_smart_ops * const intel_smart_ops = NULL;
+static struct ndctl_smart_ops * const hpe1_smart_ops = NULL;
 #endif
 
 /* internal library helpers for conditionally defined command numbers */
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
index 7a847fa..a935747 100644
--- a/ndctl/lib/libndctl.c
+++ b/ndctl/lib/libndctl.c
@@ -1244,6 +1244,8 @@ static int add_dimm(void *parent, int id, const char 
*dimm_base)
        sprintf(path, "%s/nfit/family", dimm_base);
        if (sysfs_read_attr(ctx, path, buf) == 0)
                dimm->dsm_family = strtoul(buf, NULL, 0);
+       if (dimm->dsm_family == NVDIMM_FAMILY_HPE1)
+               dimm->smart_ops = hpe1_smart_ops;
 
        dimm->formats = formats;
        sprintf(path, "%s/nfit/format", dimm_base);
diff --git a/ndctl/lib/ndctl-hpe1.h b/ndctl/lib/ndctl-hpe1.h
new file mode 100644
index 0000000..0d41aab
--- /dev/null
+++ b/ndctl/lib/ndctl-hpe1.h
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2016 Hewlett Packard Enterprise Development LP
+ * Copyright (c) 2014-2015, Intel Corporation.
+ *
+ * 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_HPE1_H__
+#define __NDCTL_HPE1_H__
+
+enum {
+       NDN_HPE1_CMD_QUERY = 0,
+
+       /* non-root commands */
+       NDN_HPE1_CMD_SMART = 1,
+       NDN_HPE1_CMD_SMART_THRESHOLD = 2,
+       NDN_HPE1_CMD_GET_CONFIG_SIZE = 4,
+       NDN_HPE1_CMD_GET_CONFIG_DATA = 5,
+       NDN_HPE1_CMD_SET_CONFIG_DATA = 6,
+       NDN_HPE1_CMD_GET_IDENT = 10,
+       NDN_HPE1_CMD_GET_ES_IDENT = 11,
+       NDN_HPE1_CMD_GET_LAST_BACKUP = 12,
+       NDN_HPE1_CMD_SET_LIFE_THRESHOLD = 13,
+       NDN_HPE1_CMD_ERRINJ_QUERY = 18,
+       NDN_HPE1_CMD_ERRINJ_INJECT = 19,
+       NDN_HPE1_CMD_ERRINJ_STATUS = 20,
+};
+
+/* NDN_HPE1_CMD_SMART */
+struct ndn_hpe1_smart {
+       __u32 in_valid_flags;
+       __u32 status;
+       __u8 data[124];
+} __attribute__((packed));
+
+/* ndn_hpe1_smart.in_valid_flags / ndn_hpe1_smart_data.out_valid_flags */
+#define NDN_HPE1_SMART_HEALTH_VALID    (1 << 0)
+#define NDN_HPE1_SMART_TEMP_VALID      (1 << 1)
+#define NDN_HPE1_SMART_SPARES_VALID    (1 << 2)
+#define NDN_HPE1_SMART_ALARM_VALID     (1 << 3)
+#define NDN_HPE1_SMART_USED_VALID      (1 << 4)
+#define NDN_HPE1_SMART_SHUTDOWN_VALID  (1 << 5)
+#define NDN_HPE1_SMART_STATS_VALID     (1 << 6)
+#define NDN_HPE1_SMART_DETAIL_VALID    (1 << 7)
+#define NDN_HPE1_SMART_ENERGY_VALID    (1 << 8)
+#define NDN_HPE1_SMART_VENDOR_VALID    (1 << 9)
+#define NDN_HPE1_SMART_NOTIFIED                (1 << 31)
+
+/* ndn_hpe1_smart_data.stat_summary */
+#define NDN_HPE1_SMART_NONCRIT_HEALTH  (1 << 0)
+#define NDN_HPE1_SMART_CRITICAL_HEALTH (1 << 1)
+#define NDN_HPE1_SMART_FATAL_HEALTH    (1 << 2)
+
+/* ndn_hpe1_smart_data.alarm_trips */
+#define NDN_HPE1_SMART_TEMP_TRIP       (1 << 0)
+#define NDN_HPE1_SMART_SPARE_TRIP      (1 << 1)
+#define NDN_HPE1_SMART_LIFEWARN_TRIP   (1 << 2)
+#define NDN_HPE1_SMART_LIFEERR_TRIP    (1 << 3)
+#define NDN_HPE1_SMART_ESLIFEWARN_TRIP (1 << 4)
+#define NDN_HPE1_SMART_ESLIFEERR_TRIP  (1 << 5)
+#define NDN_HPE1_SMART_ESTEMPWARN_TRIP (1 << 6)
+#define NDN_HPE1_SMART_ESTEMPERR_TRIP  (1 << 7)
+
+/* ndn_hpe1_smart_data.last_shutdown_stat */
+#define NDN_HPE1_SMART_LASTSAVEGOOD    (1 << 1)
+
+/* ndn_hpe1_smart_data.mod_hlth_stat */
+#define NDN_HPE1_SMART_ES_FAILURE      (1 << 0)
+#define NDN_HPE1_SMART_CTLR_FAILURE    (1 << 1)
+#define NDN_HPE1_SMART_UE_TRIP         (1 << 2)
+#define NDN_HPE1_SMART_CE_TRIP         (1 << 3)
+#define NDN_HPE1_SMART_SAVE_FAILED     (1 << 4)
+#define NDN_HPE1_SMART_RESTORE_FAILED  (1 << 5)
+#define NDN_HPE1_SMART_ARM_FAILED      (1 << 6)
+#define NDN_HPE1_SMART_ERASE_FAILED    (1 << 7)
+#define NDN_HPE1_SMART_CONFIG_ERROR    (1 << 8)
+#define NDN_HPE1_SMART_FW_ERROR                (1 << 9)
+#define NDN_HPE1_SMART_VENDOR_ERROR    (1 << 10)
+
+struct ndn_hpe1_smart_data {
+       __u32   out_valid_flags;
+       __u8    stat_summary;
+       __u16   curr_temp;
+       __u8    spare_blocks;
+       __u16   alarm_trips;
+       __u8    device_life;
+       __u8    last_shutdown_stat;
+       __u16   last_save_op_dur;
+       __u16   last_restore_op_dur;
+       __u16   last_erase_op_dur;
+       __u16   res1;
+       __u32   save_ops;
+       __u32   restore_ops;
+       __u32   erase_ops;
+       __u32   life_save_ops;
+       __u32   life_restore_ops;
+       __u32   life_erase_ops;
+       __u32   life_mod_pwr_cycles;
+       __u32   mod_hlth_stat;
+       __u32   energy_src_check;
+       __u8    energy_src_life_percent;
+       __u16   energy_src_curr_temp;
+       __u8    res2;
+       __u16   energy_src_total_runtime;
+       __u16   vndr_spec_data_size;
+       __u8    vnd_spec_data[60];
+} __attribute__((packed));
+
+/* NDN_HPE1_CMD_SMART_THRESHOLD */
+struct ndn_hpe1_smart_threshold {
+       __u32 status;
+       __u8 data[32];
+} __attribute__((packed));
+
+struct ndn_hpe1_smart_threshold_data {
+       __u16   threshold_alarm_ctl;
+       __u16   temp_threshold;
+       __u8    spare_block_threshold;
+       __u8    res1[3];
+       __u8    dev_lifewarn_threshold;
+       __u8    dev_lifeerr_threshold;
+       __u8    res2[6];
+       __u8    es_lifewarn_threshold;
+       __u8    es_lifeerr_threshold;
+       __u8    es_tempwarn_threshold;
+       __u8    es_temperr_threshold;
+       __u8    res3[4];
+       __u64   res4;
+} __attribute__((packed));
+
+/* NDN_HPE1_CMD_GET_CONFIG_SIZE */
+struct ndn_hpe1_get_config_size {
+       __u32 status;
+       __u32 config_size;
+       __u32 max_xfer;
+} __attribute__((packed));
+
+/* NDN_HPE1_CMD_GET_CONFIG_DATA */
+struct ndn_hpe1_get_config_data_hdr {
+       __u32 in_offset;
+       __u32 in_length;
+       __u32 status;
+       __u8 out_buf[0];
+} __attribute__((packed));
+
+/* NDN_HPE1_CMD_SET_CONFIG_DATA */
+struct ndn_hpe1_set_config_hdr {
+       __u32 in_offset;
+       __u32 in_length;
+       __u8 in_buf[0];
+} __attribute__((packed));
+
+
+/* ndn_hpe1_get_id.sup_backup_trigger */
+#define NDN_HPE1_BKUP_SUPPORT_CKE      (1 << 0)
+#define NDN_HPE1_BKUP_SUPPORT_EXTERNAL (1 << 1)
+#define NDN_HPE1_BKUP_SUPPORT_12V      (1 << 2)
+#define NDN_HPE1_BKUP_SUPPORT_I2C      (1 << 3)
+#define NDN_HPE1_BKUP_SUPPORT_SAVEN    (1 << 4)
+
+/* NDN_HPE1_CMD_GET_IDENT */
+struct ndn_hpe1_get_id {
+       __u32   status;
+       __u8    spec_rev;
+       __u8    num_stnd_pages;
+       __u32   hw_rev;
+       __u8    sup_backup_trigger;
+       __u16   max_op_retries;
+       __u8    __res1[3];
+       __u32   backup_op_timeout;
+       __u32   restore_op_timeout;
+       __u32   erase_op_timeout;
+       __u32   arm_op_timeout;
+       __u32   fw_op_timeout;
+       __u32   region_block_size;
+       __u16   min_op_temp;
+       __u16   max_op_temp;
+       __u8    curr_fw_slot;
+       __u8    res2[1];
+       __u16   num_fw_slots;
+       __u8    fw_slot_revision[0];
+} __attribute__((packed));
+
+/* ndn_hpe1_get_energy_src_id.attr */
+#define NDN_HPE1_ES_ATTR_BUILTIN       (1 << 0)
+#define NDN_HPE1_ES_ATTR_TETHERED      (1 << 1)
+#define NDN_HPE1_ES_ATTR_SHARED                (1 << 2)
+
+/* ndn_hpe1_get_energy_src_id.tech */
+#define NDN_HPE1_ES_TECH_UNDEFINED     (1 << 0)
+#define NDN_HPE1_ES_TECH_SUPERCAP      (1 << 1)
+#define NDN_HPE1_ES_TECH_BATTERY       (1 << 2)
+#define NDN_HPE1_ES_TECH_HYBRIDCAP     (1 << 3)
+
+/* NDN_HPE1_CMD_GET_ES_IDENT */
+struct ndn_hpe1_get_energy_src_id {
+       __u32   status;
+       __u8    energy_src_policy;
+       __u8    attr;
+       __u8    tech;
+       __u8    reserved;
+       __u16   hw_rev;
+       __u16   fw_rev;
+       __u32   charge_timeout;
+       __u16   min_op_temp;
+       __u16   max_op_temp;
+} __attribute__((packed));
+
+/* ndn_hpe1_last_backup_info.last_backup_initiation */
+#define NDN_HPE1_LASTBKUP_SAVEN                (1 << 0)
+#define NDN_HPE1_LASTBKUP_EXTERNAL     (1 << 1)
+#define NDN_HPE1_LASTBKUP_CKE          (1 << 2)
+#define NDN_HPE1_LASTBKUP_FW           (1 << 3)
+#define NDN_HPE1_LASTBKUP_RESETN       (1 << 4)
+
+/* ndn_hpe1_last_backup_info.ctlr_backup_stat */
+#define NDN_HPE1_LASTBKUP_GTG          (1 << 0)
+#define NDN_HPE1_LASTBKUP_SDRAM_FAULT  (1 << 1)
+#define NDN_HPE1_LASTBKUP_GEN_FAULT    (1 << 2)
+
+/* NDN_HPE1_CMD_GET_LAST_BACKUP */
+struct ndn_hpe1_get_last_backup {
+       __u32   status;
+       __u32   last_backup_info;
+} __attribute__((packed));
+
+struct ndn_hpe1_last_backup_info {
+       __u8    backup_image;
+       __u8    backup_cmplt_stat;
+       __u8    last_backup_initiation;
+       __u8    ctlr_backup_stat;
+} __attribute__((packed));
+
+
+/* NDN_HPE1_CMD_SET_LIFE_THRESHOLD */
+struct ndn_hpe1_set_lifetime_threshold {
+       __u8    in_nvm_lifetime_warn_threshold;
+       __u32   status;
+} __attribute__((packed));
+
+
+/* ndn_hpe1_inj_err.in_err_typ
+ * ndn_hpe1_get_inj_err_status.err_inj_type
+ * log2(ndn_hpe1_query_err_inj_cap.err_inj_cap)
+ */
+enum {
+       NDN_HPE1_EINJ_DEV_NONCRIT = 1,
+       NDN_HPE1_EINJ_DEV_CRIT = 2,
+       NDN_HPE1_EINJ_DEV_FATAL = 3,
+       NDN_HPE1_EINJ_UE_BACKUP = 4,
+       NDN_HPE1_EINJ_UE_RESTORE = 5,
+       NDN_HPE1_EINJ_UE_ERASE = 6,
+       NDN_HPE1_EINJ_UE_ARM = 7,
+       NDN_HPE1_EINJ_BADBLOCK = 8,
+       NDN_HPE1_EINJ_ES_FAULT = 9,
+       NDN_HPE1_EINJ_ES_LOWCHARGE = 10,
+       NDN_HPE1_EINJ_ES_TEMPWARN = 11,
+       NDN_HPE1_EINJ_ES_TEMPERR = 12,
+       NDN_HPE1_EINJ_ES_LIFEWARN = 13,
+       NDN_HPE1_EINJ_ES_LIFEERR = 14,
+       NDN_HPE1_EINJ_DEV_LIFEWARN = 15,
+       NDN_HPE1_EINJ_DEV_LIFEERR = 16,
+       NDN_HPE1_EINJ_FWUPDATE_ERR = 17,
+       NDN_HPE1_EINJ_CTRL_ERR = 18,
+};
+
+/* ndn_hpe1_inj_err.in_options / ndn_hpe1_get_inj_err_status.err_inj_opt */
+enum {
+       NDN_HPE1_EINJ_OPT_SINGLE = 0,
+       NDN_HPE1_EINJ_OPT_PERSISTENT = 1,
+       NDN_HPE1_EINJ_OPT_CLEAR = 2,
+};
+
+/* ndn_hpe1_get_inj_err_status.err_inj_stat_info */
+enum {
+       NDN_HPE1_EINJ_STAT_NONE = 0,
+       NDN_HPE1_EINJ_STAT_INJECTED = 1,
+       NDN_HPE1_EINJ_STAT_PENDING = 2,
+};
+
+/* NDN_HPE1_CMD_ERRINJ_QUERY */
+struct ndn_hpe1_query_err_inj_cap {
+       __u32   status;
+       __u8    err_inj_cap[32];
+} __attribute__((packed));
+
+
+/* NDN_HPE1_CMD_ERRINJ_INJECT */
+struct ndn_hpe1_inj_err {
+       __u8    in_err_typ;
+       __u8    in_options;
+       __u32   status;
+} __attribute__((packed));
+
+/* NDN_HPE1_CMD_ERRINJ_STATUS */
+struct ndn_hpe1_get_inj_err_status {
+       __u32   status;
+       __u8    err_inj_stat_info;
+       __u8    err_inj_type;
+       __u8    err_inj_opt;
+} __attribute__((packed));
+
+union ndn_hpe1_cmd {
+       __u64                                   query;
+       struct ndn_hpe1_smart                   smart;
+       struct ndn_hpe1_smart_threshold         thresh;
+       struct ndn_hpe1_get_config_size         get_size;
+       struct ndn_hpe1_get_config_data_hdr     get_data;
+       struct ndn_hpe1_get_id                  get_id;
+       struct ndn_hpe1_get_energy_src_id       get_energy_src_id;
+       struct ndn_hpe1_get_last_backup         get_last_backup;
+       struct ndn_hpe1_last_backup_info        last_backup_info;
+       struct ndn_hpe1_set_lifetime_threshold  set_life_thresh;
+       struct ndn_hpe1_query_err_inj_cap       err_cap;
+       struct ndn_hpe1_inj_err                 inj_err;
+       struct ndn_hpe1_get_inj_err_status      inj_err_stat;
+
+       unsigned char                           buf[128];
+};
+
+struct ndn_pkg_hpe1 {
+       struct nd_cmd_pkg gen;
+       union ndn_hpe1_cmd u;
+} __attribute__((packed));
+
+#define NDN_IOCTL_HPE1_PASSTHRU                _IOWR(ND_IOCTL, ND_CMD_CALL, \
+                                       struct ndn_pkg_hpe1)
+
+#endif /* __NDCTL_HPE1_H__ */
-- 
2.8.3

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

Reply via email to