The build currently spews many errors of the form:

hyperv.c: In function ‘alloc_hyperv_cmd’:
hyperv.c:61:25: warning: taking address of packed member of ‘struct 
nd_hyperv_health_info’ may result in an unaligned pointer value 
[-Waddress-of-packed-member]
   61 |  cmd->firmware_status = &hyperv->u.health_info.status;

Move the status reporting from passing an unaligned pointer to a new
->get_firmware_status() operation.

Link: https://github.com/pmem/ndctl/issues/131
Signed-off-by: Dan Williams <[email protected]>
---
 ndctl/lib/ars.c       |   28 +++++++++++++++++++------
 ndctl/lib/hpe1.c      |   17 +++++++++++----
 ndctl/lib/hyperv.c    |    7 +++++-
 ndctl/lib/intel.c     |   56 +++++++++++++++++++++++++++++++++++--------------
 ndctl/lib/libndctl.c  |   39 ++++++++++++++++++++++++++--------
 ndctl/lib/msft.c      |    8 +++++--
 ndctl/lib/nfit.c      |   36 +++++++++++++++++++++-----------
 ndctl/lib/private.h   |    7 ++++--
 ndctl/libndctl-nfit.h |   11 ++++++++++
 9 files changed, 157 insertions(+), 52 deletions(-)

diff --git a/ndctl/lib/ars.c b/ndctl/lib/ars.c
index d91a99d00d10..44871b2afde2 100644
--- a/ndctl/lib/ars.c
+++ b/ndctl/lib/ars.c
@@ -15,6 +15,22 @@
 #include <ndctl/libndctl.h>
 #include "private.h"
 
+static u32 get_ars_command_status(struct ndctl_cmd *cmd)
+{
+       switch (cmd->type) {
+       case ND_CMD_ARS_CAP:
+               return cmd->ars_cap->status;
+       case ND_CMD_ARS_START:
+               return cmd->ars_start->status;
+       case ND_CMD_ARS_STATUS:
+               return cmd->ars_status->status;
+       case ND_CMD_CLEAR_ERROR:
+               return cmd->clear_err->status;
+       }
+
+       return -1U;
+}
+
 NDCTL_EXPORT struct ndctl_cmd *ndctl_bus_cmd_new_ars_cap(struct ndctl_bus *bus,
                unsigned long long address, unsigned long long len)
 {
@@ -35,9 +51,9 @@ NDCTL_EXPORT struct ndctl_cmd 
*ndctl_bus_cmd_new_ars_cap(struct ndctl_bus *bus,
        cmd->bus = bus;
        ndctl_cmd_ref(cmd);
        cmd->type = ND_CMD_ARS_CAP;
+       cmd->get_firmware_status = get_ars_command_status;
        cmd->size = size;
        cmd->status = 1;
-       cmd->firmware_status = &cmd->ars_cap->status;
        cmd->ars_cap->address = address;
        cmd->ars_cap->length = len;
 
@@ -55,7 +71,7 @@ static bool __validate_ars_cap(struct ndctl_cmd *ars_cap)
 {
        if (ars_cap->type != ND_CMD_ARS_CAP || ars_cap->status != 0)
                return false;
-       if ((*ars_cap->firmware_status & ARS_STATUS_MASK) != 0)
+       if ((ars_cap->get_firmware_status(ars_cap) & ARS_STATUS_MASK) != 0)
                return false;
        return validate_clear_error(ars_cap);
 }
@@ -84,7 +100,7 @@ NDCTL_EXPORT struct ndctl_cmd 
*ndctl_bus_cmd_new_ars_start(struct ndctl_cmd *ars
        if (!validate_ars_cap(ctx, ars_cap))
                return NULL;
 
-       if (!(*ars_cap->firmware_status >> ARS_EXT_STATUS_SHIFT & type)) {
+       if (!(ars_cap->get_firmware_status(ars_cap) >> ARS_EXT_STATUS_SHIFT & 
type)) {
                dbg(ctx, "ars_cap does not show requested type as supported\n");
                return NULL;
        }
@@ -97,9 +113,9 @@ NDCTL_EXPORT struct ndctl_cmd 
*ndctl_bus_cmd_new_ars_start(struct ndctl_cmd *ars
        cmd->bus = bus;
        ndctl_cmd_ref(cmd);
        cmd->type = ND_CMD_ARS_START;
+       cmd->get_firmware_status = get_ars_command_status;
        cmd->size = size;
        cmd->status = 1;
-       cmd->firmware_status = &cmd->ars_start->status;
        cmd->ars_start->address = ars_cap->ars_cap->address;
        cmd->ars_start->length = ars_cap->ars_cap->length;
        cmd->ars_start->type = type;
@@ -145,9 +161,9 @@ NDCTL_EXPORT struct ndctl_cmd 
*ndctl_bus_cmd_new_ars_status(struct ndctl_cmd *ar
        cmd->bus = bus;
        ndctl_cmd_ref(cmd);
        cmd->type = ND_CMD_ARS_STATUS;
+       cmd->get_firmware_status = get_ars_command_status;
        cmd->size = size;
        cmd->status = 1;
-       cmd->firmware_status = &cmd->ars_status->status;
        cmd->ars_status->out_length = ars_cap_cmd->max_ars_out;
 
        return cmd;
@@ -325,9 +341,9 @@ NDCTL_EXPORT struct ndctl_cmd 
*ndctl_bus_cmd_new_clear_error(
        ndctl_cmd_ref(clear_err);
        clear_err->bus = bus;
        clear_err->type = ND_CMD_CLEAR_ERROR;
+       clear_err->get_firmware_status = get_ars_command_status;
        clear_err->size = size;
        clear_err->status = 1;
-       clear_err->firmware_status = &clear_err->clear_err->status;
        clear_err->clear_err->address = address;
        clear_err->clear_err->length = len;
 
diff --git a/ndctl/lib/hpe1.c b/ndctl/lib/hpe1.c
index b26120e1d3e0..b5ee02608d31 100644
--- a/ndctl/lib/hpe1.c
+++ b/ndctl/lib/hpe1.c
@@ -23,6 +23,17 @@
 #define CMD_HPE1_SMART(_c) (CMD_HPE1(_c)->u.smart.data)
 #define CMD_HPE1_SMART_THRESH(_c) (CMD_HPE1(_c)->u.thresh.data)
 
+static u32 hpe1_get_firmware_status(struct ndctl_cmd *cmd)
+{
+       switch (cmd->hpe1->gen.nd_command) {
+       case NDN_HPE1_CMD_SMART:
+               return cmd->hpe1->u.smart.status;
+       case NDN_HPE1_CMD_SMART_THRESHOLD:
+               return cmd->hpe1->u.thresh.status;
+       }
+       return -1U;
+}
+
 static struct ndctl_cmd *hpe1_dimm_cmd_new_smart(struct ndctl_dimm *dimm)
 {
        struct ndctl_bus *bus = ndctl_dimm_get_bus(dimm);
@@ -60,6 +71,7 @@ static struct ndctl_cmd *hpe1_dimm_cmd_new_smart(struct 
ndctl_dimm *dimm)
        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;
+       cmd->get_firmware_status = hpe1_get_firmware_status;
 
        hpe1->u.smart.in_valid_flags = 0;
        hpe1->u.smart.in_valid_flags |= NDN_HPE1_SMART_HEALTH_VALID;
@@ -70,8 +82,6 @@ static struct ndctl_cmd *hpe1_dimm_cmd_new_smart(struct 
ndctl_dimm *dimm)
        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;
 }
 
@@ -285,8 +295,7 @@ static struct ndctl_cmd 
*hpe1_dimm_cmd_new_smart_threshold(struct ndctl_dimm *di
        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;
+       cmd->get_firmware_status = hpe1_get_firmware_status;
 
        return cmd;
 }
diff --git a/ndctl/lib/hyperv.c b/ndctl/lib/hyperv.c
index 9b4fe122af2c..ba1b12111804 100644
--- a/ndctl/lib/hyperv.c
+++ b/ndctl/lib/hyperv.c
@@ -9,6 +9,11 @@
 #include "private.h"
 #include "hyperv.h"
 
+static u32 hyperv_get_firmware_status(struct ndctl_cmd *cmd)
+{
+       return cmd->hyperv->u.status;
+}
+
 static bool hyperv_cmd_is_supported(struct ndctl_dimm *dimm, int cmd)
 {
        /*
@@ -50,6 +55,7 @@ static struct ndctl_cmd *alloc_hyperv_cmd(struct ndctl_dimm 
*dimm,
 
        cmd->dimm = dimm;
        cmd->type = ND_CMD_CALL;
+       cmd->get_firmware_status = hyperv_get_firmware_status;
        cmd->size = size;
        cmd->status = 1;
 
@@ -58,7 +64,6 @@ static struct ndctl_cmd *alloc_hyperv_cmd(struct ndctl_dimm 
*dimm,
        hyperv->gen.nd_command = command;
        hyperv->gen.nd_size_out = sizeof(hyperv->u.health_info);
 
-       cmd->firmware_status = &hyperv->u.health_info.status;
        return cmd;
 }
 
diff --git a/ndctl/lib/intel.c b/ndctl/lib/intel.c
index d684bac03fec..ebcefd8b5ad2 100644
--- a/ndctl/lib/intel.c
+++ b/ndctl/lib/intel.c
@@ -16,13 +16,49 @@
 #include <ndctl/libndctl.h>
 #include "private.h"
 
+static unsigned int intel_cmd_get_firmware_status(struct ndctl_cmd *cmd)
+{
+       struct nd_pkg_intel *intel = cmd->intel;
+
+       switch (intel->gen.nd_command) {
+       case ND_INTEL_SMART:
+               return intel->smart.status;
+       case ND_INTEL_SMART_THRESHOLD:
+               return intel->thresh.status;
+       case ND_INTEL_SMART_SET_THRESHOLD:
+               return intel->set_thresh.status;
+       case ND_INTEL_SMART_INJECT:
+               return intel->inject.status;
+       case ND_INTEL_FW_GET_INFO:
+               return intel->info.status;
+       case ND_INTEL_FW_START_UPDATE:
+               return intel->start.status;
+       case ND_INTEL_FW_SEND_DATA: {
+                   struct nd_intel_fw_send_data *send = &intel->send;
+                   u32 status;
+
+                   /* the last dword after the payload is reserved for status 
*/
+                   memcpy(&status, ((void *) send) + sizeof(*send) + 
send->length,
+                                   sizeof(status));
+                   return status;
+       }
+       case ND_INTEL_FW_FINISH_UPDATE:
+               return intel->finish.status;
+       case ND_INTEL_FW_FINISH_STATUS_QUERY:
+               return intel->fquery.status;
+       case ND_INTEL_ENABLE_LSS_STATUS:
+               return intel->lss.status;
+       }
+       return -1U;
+}
+
 static int intel_cmd_xlat_firmware_status(struct ndctl_cmd *cmd)
 {
        struct nd_pkg_intel *pkg = cmd->intel;
        unsigned int status, ext_status;
 
-       status = (*cmd->firmware_status) & ND_INTEL_STATUS_MASK;
-       ext_status = (*cmd->firmware_status) & ND_INTEL_STATUS_EXTEND_MASK;
+       status = cmd->get_firmware_status(cmd) & ND_INTEL_STATUS_MASK;
+       ext_status = cmd->get_firmware_status(cmd) & 
ND_INTEL_STATUS_EXTEND_MASK;
 
        /* Common statuses */
        switch (status) {
@@ -91,6 +127,7 @@ static struct ndctl_cmd *alloc_intel_cmd(struct ndctl_dimm 
*dimm,
        cmd->type = ND_CMD_CALL;
        cmd->size = size;
        cmd->status = 1;
+       cmd->get_firmware_status = intel_cmd_get_firmware_status;
 
        *(cmd->intel) = (struct nd_pkg_intel) {
                .gen = {
@@ -114,7 +151,6 @@ static struct ndctl_cmd *intel_dimm_cmd_new_smart(struct 
ndctl_dimm *dimm)
                        0, sizeof(cmd->intel->smart));
        if (!cmd)
                return NULL;
-       cmd->firmware_status = &cmd->intel->smart.status;
 
        return cmd;
 }
@@ -269,7 +305,6 @@ static struct ndctl_cmd *intel_dimm_cmd_new_smart_threshold(
                        0, sizeof(cmd->intel->thresh));
        if (!cmd)
                return NULL;
-       cmd->firmware_status = &cmd->intel->thresh.status;
 
        return cmd;
 }
@@ -299,7 +334,6 @@ static struct ndctl_cmd 
*intel_dimm_cmd_new_smart_set_threshold(
        set_thresh->spares = thresh->spares;
        set_thresh->media_temperature = thresh->media_temperature;
        set_thresh->ctrl_temperature = thresh->ctrl_temperature;
-       cmd->firmware_status = &set_thresh->status;
 
        return cmd;
 }
@@ -360,7 +394,6 @@ static struct ndctl_cmd *intel_new_smart_inject(struct 
ndctl_dimm *dimm)
                        offsetof(struct nd_intel_smart_inject, status), 4);
        if (!cmd)
                return NULL;
-       cmd->firmware_status = &cmd->intel->inject.status;
 
        return cmd;
 }
@@ -468,7 +501,6 @@ static struct ndctl_cmd 
*intel_dimm_cmd_new_fw_get_info(struct ndctl_dimm *dimm)
        if (!cmd)
                return NULL;
 
-       cmd->firmware_status = &cmd->intel->info.status;
        return cmd;
 }
 
@@ -540,7 +572,6 @@ static struct ndctl_cmd *intel_dimm_cmd_new_fw_start(struct 
ndctl_dimm *dimm)
        if (!cmd)
                return NULL;
 
-       cmd->firmware_status = &cmd->intel->start.status;
        return cmd;
 }
 
@@ -583,9 +614,6 @@ static struct ndctl_cmd *intel_dimm_cmd_new_fw_send(struct 
ndctl_cmd *start,
        cmd->intel->send.offset = offset;
        cmd->intel->send.length = len;
        memcpy(cmd->intel->send.data, data, len);
-       /* the last dword is reserved for status */
-       cmd->firmware_status =
-               (unsigned int *)(&cmd->intel->send.data[0] + len);
        return cmd;
 }
 
@@ -602,7 +630,6 @@ static struct ndctl_cmd 
*intel_dimm_cmd_new_fw_finish(struct ndctl_cmd *start)
 
        cmd->intel->finish.context = start->intel->start.context;
        cmd->intel->finish.ctrl_flags = 0;
-       cmd->firmware_status = &cmd->intel->finish.status;
        return cmd;
 }
 
@@ -619,7 +646,6 @@ static struct ndctl_cmd *intel_dimm_cmd_new_fw_abort(struct 
ndctl_cmd *start)
 
        cmd->intel->finish.context = start->intel->start.context;
        cmd->intel->finish.ctrl_flags = 1;
-       cmd->firmware_status = &cmd->intel->finish.status;
        return cmd;
 }
 
@@ -636,7 +662,6 @@ intel_dimm_cmd_new_fw_finish_query(struct ndctl_cmd *start)
                return NULL;
 
        cmd->intel->fquery.context = start->intel->start.context;
-       cmd->firmware_status = &cmd->intel->fquery.status;
        return cmd;
 }
 
@@ -704,7 +729,7 @@ intel_cmd_fw_xlat_extend_firmware_status(struct ndctl_cmd 
*cmd,
 static enum ND_FW_STATUS
 intel_cmd_fw_xlat_firmware_status(struct ndctl_cmd *cmd)
 {
-       unsigned int status = *cmd->firmware_status;
+       unsigned int status = intel_cmd_get_firmware_status(cmd);
 
        switch (status & ND_INTEL_STATUS_MASK) {
        case ND_INTEL_STATUS_SUCCESS:
@@ -742,7 +767,6 @@ intel_dimm_cmd_new_lss(struct ndctl_dimm *dimm)
                return NULL;
 
        cmd->intel->lss.enable = 1;
-       cmd->firmware_status = &cmd->intel->lss.status;
        return cmd;
 }
 
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
index 9ad1b7091dc0..97fd98545440 100644
--- a/ndctl/lib/libndctl.c
+++ b/ndctl/lib/libndctl.c
@@ -2506,6 +2506,23 @@ static struct nd_cmd_vendor_tail *to_vendor_tail(struct 
ndctl_cmd *cmd)
        return tail;
 }
 
+static u32 cmd_get_firmware_status(struct ndctl_cmd *cmd)
+{
+       switch (cmd->type) {
+       case ND_CMD_VENDOR:
+               return to_vendor_tail(cmd)->status;
+       case ND_CMD_GET_CONFIG_SIZE:
+               return cmd->get_size->status;
+       case ND_CMD_GET_CONFIG_DATA:
+               return cmd->get_data->status;
+       case ND_CMD_SET_CONFIG_DATA:
+               return *(u32 *) (cmd->cmd_buf
+                               + sizeof(struct nd_cmd_set_config_hdr)
+                               + cmd->iter.max_xfer);
+       }
+       return -1U;
+}
+
 NDCTL_EXPORT struct ndctl_cmd *ndctl_dimm_cmd_new_vendor_specific(
                struct ndctl_dimm *dimm, unsigned int opcode, size_t input_size,
                size_t output_size)
@@ -2535,7 +2552,7 @@ NDCTL_EXPORT struct ndctl_cmd 
*ndctl_dimm_cmd_new_vendor_specific(
        cmd->status = 1;
        cmd->vendor->opcode = opcode;
        cmd->vendor->in_length = input_size;
-       cmd->firmware_status = &to_vendor_tail(cmd)->status;
+       cmd->get_firmware_status = cmd_get_firmware_status;
        to_vendor_tail(cmd)->out_length = output_size;
 
        return cmd;
@@ -2600,7 +2617,7 @@ NDCTL_EXPORT struct ndctl_cmd 
*ndctl_dimm_cmd_new_cfg_size(struct ndctl_dimm *di
        cmd->type = ND_CMD_GET_CONFIG_SIZE;
        cmd->size = size;
        cmd->status = 1;
-       cmd->firmware_status = &cmd->get_size->status;
+       cmd->get_firmware_status = cmd_get_firmware_status;
 
        return cmd;
 }
@@ -2641,7 +2658,7 @@ NDCTL_EXPORT struct ndctl_cmd 
*ndctl_dimm_cmd_new_cfg_read(struct ndctl_cmd *cfg
        cmd->status = 1;
        cmd->get_data->in_offset = 0;
        cmd->get_data->in_length = cfg_size->get_size->max_xfer;
-       cmd->firmware_status = &cmd->get_data->status;
+       cmd->get_firmware_status = cmd_get_firmware_status;
        cmd->iter.init_offset = 0;
        cmd->iter.offset = &cmd->get_data->in_offset;
        cmd->iter.xfer = &cmd->get_data->in_length;
@@ -2728,8 +2745,7 @@ NDCTL_EXPORT struct ndctl_cmd 
*ndctl_dimm_cmd_new_cfg_write(struct ndctl_cmd *cf
        cmd->status = 1;
        cmd->set_data->in_offset = cfg_read->iter.init_offset;
        cmd->set_data->in_length = cfg_read->iter.max_xfer;
-       cmd->firmware_status = (u32 *) (cmd->cmd_buf
-               + sizeof(struct nd_cmd_set_config_hdr) + 
cfg_read->iter.max_xfer);
+       cmd->get_firmware_status = cmd_get_firmware_status;
        cmd->iter.init_offset = cfg_read->iter.init_offset;
        cmd->iter.offset = &cmd->set_data->in_offset;
        cmd->iter.xfer = &cmd->set_data->in_length;
@@ -2936,7 +2952,7 @@ static int do_cmd(int fd, int ioctl_cmd, struct ndctl_cmd 
*cmd)
                dbg(ctx, "bus: %d dimm: %#x cmd: %s%s%s status: %d fw: %d 
(%s)\n",
                                bus->id, dimm ? ndctl_dimm_get_handle(dimm) : 0,
                                name, sub_name ? ":" : "", sub_name ? sub_name 
: "",
-                               rc, *(cmd->firmware_status), rc < 0 ?
+                               rc, cmd->get_firmware_status(cmd), rc < 0 ?
                                strerror(errno) : "success");
                if (rc < 0)
                        return -errno;
@@ -2960,7 +2976,7 @@ static int do_cmd(int fd, int ioctl_cmd, struct ndctl_cmd 
*cmd)
                if (iter->dir == READ)
                        memcpy(iter->total_buf + offset, iter->data,
                                        *(cmd->iter.xfer) - rc);
-               if (*(cmd->firmware_status) || rc) {
+               if (cmd->get_firmware_status(cmd) || rc) {
                        rc = offset + *(cmd->iter.xfer) - rc;
                        break;
                }
@@ -2970,7 +2986,7 @@ static int do_cmd(int fd, int ioctl_cmd, struct ndctl_cmd 
*cmd)
                        bus->id, dimm ? ndctl_dimm_get_handle(dimm) : 0,
                        name, sub_name ? ":" : "", sub_name ? sub_name : "",
                        iter->total_xfer, iter->max_xfer, rc,
-                       *(cmd->firmware_status),
+                       cmd->get_firmware_status(cmd),
                        rc < 0 ? strerror(errno) : "success");
 
        return rc;
@@ -2986,6 +3002,11 @@ NDCTL_EXPORT int ndctl_cmd_submit(struct ndctl_cmd *cmd)
        struct ndctl_bus *bus = cmd_to_bus(cmd);
        struct ndctl_ctx *ctx = ndctl_bus_get_ctx(bus);
 
+       if (!cmd->get_firmware_status) {
+               err(ctx, "missing status retrieval\n");
+               return -EINVAL;
+       }
+
        if (ioctl_cmd == 0) {
                rc = -EINVAL;
                goto out;
@@ -3054,7 +3075,7 @@ NDCTL_EXPORT int ndctl_cmd_get_status(struct ndctl_cmd 
*cmd)
 
 NDCTL_EXPORT unsigned int ndctl_cmd_get_firmware_status(struct ndctl_cmd *cmd)
 {
-       return *(cmd->firmware_status);
+       return cmd->get_firmware_status(cmd);
 }
 
 NDCTL_EXPORT const char *ndctl_region_get_devname(struct ndctl_region *region)
diff --git a/ndctl/lib/msft.c b/ndctl/lib/msft.c
index 19453cd86143..c060b1f2609e 100644
--- a/ndctl/lib/msft.c
+++ b/ndctl/lib/msft.c
@@ -22,6 +22,11 @@
 #define CMD_MSFT(_c) ((_c)->msft)
 #define CMD_MSFT_SMART(_c) (CMD_MSFT(_c)->u.smart.data)
 
+static u32 msft_get_firmware_status(struct ndctl_cmd *cmd)
+{
+       return cmd->msft->u.smart.status;
+}
+
 static struct ndctl_cmd *msft_dimm_cmd_new_smart(struct ndctl_dimm *dimm)
 {
        struct ndctl_bus *bus = ndctl_dimm_get_bus(dimm);
@@ -58,8 +63,7 @@ static struct ndctl_cmd *msft_dimm_cmd_new_smart(struct 
ndctl_dimm *dimm)
        msft->gen.nd_size_in = offsetof(struct ndn_msft_smart, status);
        msft->gen.nd_size_out = sizeof(msft->u.smart);
        msft->u.smart.status = 0;
-
-       cmd->firmware_status = &msft->u.smart.status;
+       cmd->get_firmware_status = msft_get_firmware_status;
 
        return cmd;
 }
diff --git a/ndctl/lib/nfit.c b/ndctl/lib/nfit.c
index b10edb1943e8..f9fbe73f7446 100644
--- a/ndctl/lib/nfit.c
+++ b/ndctl/lib/nfit.c
@@ -15,6 +15,24 @@
 #include "private.h"
 #include <ndctl/libndctl-nfit.h>
 
+static u32 bus_get_firmware_status(struct ndctl_cmd *cmd)
+{
+       struct nd_cmd_bus *cmd_bus = cmd->cmd_bus;
+
+       switch (cmd_bus->gen.nd_command) {
+       case NFIT_CMD_TRANSLATE_SPA:
+               return cmd_bus->xlat_spa.status;
+       case NFIT_CMD_ARS_INJECT_SET:
+               return cmd_bus->err_inj.status;
+       case NFIT_CMD_ARS_INJECT_CLEAR:
+               return cmd_bus->err_inj_clr.status;
+       case NFIT_CMD_ARS_INJECT_GET:
+               return cmd_bus->err_inj_stat.status;
+       }
+
+       return -1U;
+}
+
 /**
  * ndctl_bus_is_nfit_cmd_supported - ask nfit command is supported on @bus.
  * @bus: ndctl_bus instance
@@ -54,15 +72,15 @@ static struct ndctl_cmd 
*ndctl_bus_cmd_new_translate_spa(struct ndctl_bus *bus)
        cmd->bus = bus;
        ndctl_cmd_ref(cmd);
        cmd->type = ND_CMD_CALL;
+       cmd->get_firmware_status = bus_get_firmware_status;
        cmd->size = size;
        cmd->status = 1;
-       pkg = (struct nd_cmd_pkg *)&cmd->cmd_buf[0];
+       pkg = &cmd->cmd_bus->gen;
        pkg->nd_command = NFIT_CMD_TRANSLATE_SPA;
        pkg->nd_size_in = sizeof(unsigned long long);
        pkg->nd_size_out = spa_length;
        pkg->nd_fw_size = spa_length;
-       translate_spa = (struct nd_cmd_translate_spa *)&pkg->nd_payload[0];
-       cmd->firmware_status = &translate_spa->status;
+       translate_spa = &cmd->cmd_bus->xlat_spa;
        translate_spa->translate_length = spa_length;
 
        return cmd;
@@ -146,7 +164,6 @@ int ndctl_bus_nfit_translate_spa(struct ndctl_bus *bus,
 
 struct ndctl_cmd *ndctl_bus_cmd_new_err_inj(struct ndctl_bus *bus)
 {
-       struct nd_cmd_ars_err_inj *err_inj;
        size_t size, cmd_length;
        struct nd_cmd_pkg *pkg;
        struct ndctl_cmd *cmd;
@@ -160,6 +177,7 @@ struct ndctl_cmd *ndctl_bus_cmd_new_err_inj(struct 
ndctl_bus *bus)
        cmd->bus = bus;
        ndctl_cmd_ref(cmd);
        cmd->type = ND_CMD_CALL;
+       cmd->get_firmware_status = bus_get_firmware_status;
        cmd->size = size;
        cmd->status = 1;
        pkg = (struct nd_cmd_pkg *)&cmd->cmd_buf[0];
@@ -167,15 +185,12 @@ struct ndctl_cmd *ndctl_bus_cmd_new_err_inj(struct 
ndctl_bus *bus)
        pkg->nd_size_in = offsetof(struct nd_cmd_ars_err_inj, status);
        pkg->nd_size_out = cmd_length - pkg->nd_size_in;
        pkg->nd_fw_size = pkg->nd_size_out;
-       err_inj = (struct nd_cmd_ars_err_inj *)&pkg->nd_payload[0];
-       cmd->firmware_status = &err_inj->status;
 
        return cmd;
 }
 
 struct ndctl_cmd *ndctl_bus_cmd_new_err_inj_clr(struct ndctl_bus *bus)
 {
-       struct nd_cmd_ars_err_inj_clr *err_inj_clr;
        size_t size, cmd_length;
        struct nd_cmd_pkg *pkg;
        struct ndctl_cmd *cmd;
@@ -189,6 +204,7 @@ struct ndctl_cmd *ndctl_bus_cmd_new_err_inj_clr(struct 
ndctl_bus *bus)
        cmd->bus = bus;
        ndctl_cmd_ref(cmd);
        cmd->type = ND_CMD_CALL;
+       cmd->get_firmware_status = bus_get_firmware_status;
        cmd->size = size;
        cmd->status = 1;
        pkg = (struct nd_cmd_pkg *)&cmd->cmd_buf[0];
@@ -196,8 +212,6 @@ struct ndctl_cmd *ndctl_bus_cmd_new_err_inj_clr(struct 
ndctl_bus *bus)
        pkg->nd_size_in = offsetof(struct nd_cmd_ars_err_inj_clr, status);
        pkg->nd_size_out = cmd_length - pkg->nd_size_in;
        pkg->nd_fw_size = pkg->nd_size_out;
-       err_inj_clr = (struct nd_cmd_ars_err_inj_clr *)&pkg->nd_payload[0];
-       cmd->firmware_status = &err_inj_clr->status;
 
        return cmd;
 }
@@ -205,7 +219,6 @@ struct ndctl_cmd *ndctl_bus_cmd_new_err_inj_clr(struct 
ndctl_bus *bus)
 struct ndctl_cmd *ndctl_bus_cmd_new_err_inj_stat(struct ndctl_bus *bus,
        u32 buf_size)
 {
-       struct nd_cmd_ars_err_inj_stat *err_inj_stat;
        size_t size, cmd_length;
        struct nd_cmd_pkg *pkg;
        struct ndctl_cmd *cmd;
@@ -220,6 +233,7 @@ struct ndctl_cmd *ndctl_bus_cmd_new_err_inj_stat(struct 
ndctl_bus *bus,
        cmd->bus = bus;
        ndctl_cmd_ref(cmd);
        cmd->type = ND_CMD_CALL;
+       cmd->get_firmware_status = bus_get_firmware_status;
        cmd->size = size;
        cmd->status = 1;
        pkg = (struct nd_cmd_pkg *)&cmd->cmd_buf[0];
@@ -227,8 +241,6 @@ struct ndctl_cmd *ndctl_bus_cmd_new_err_inj_stat(struct 
ndctl_bus *bus,
        pkg->nd_size_in = 0;
        pkg->nd_size_out = cmd_length + buf_size;
        pkg->nd_fw_size = pkg->nd_size_out;
-       err_inj_stat = (struct nd_cmd_ars_err_inj_stat *)&pkg->nd_payload[0];
-       cmd->firmware_status = &err_inj_stat->status;
 
        return cmd;
 }
diff --git a/ndctl/lib/private.h b/ndctl/lib/private.h
index 16bf8f953828..3c121bd00437 100644
--- a/ndctl/lib/private.h
+++ b/ndctl/lib/private.h
@@ -32,6 +32,7 @@
 #include "hpe1.h"
 #include "msft.h"
 #include "hyperv.h"
+#include "libndctl-nfit.h"
 
 struct nvdimm_data {
        struct ndctl_cmd *cmd_read;
@@ -233,7 +234,7 @@ struct ndctl_namespace {
  * @type: cmd number
  * @size: total size of the ndctl_cmd allocation
  * @status: negative if failed, 0 if success, > 0 if never submitted
- * @firmware_status: NFIT command output status code
+ * @get_firmware_status: per command firmware status field retrieval
  * @iter: iterator for multi-xfer commands
  * @source: source cmd of an inherited iter.total_buf
  *
@@ -250,7 +251,7 @@ struct ndctl_cmd {
        int type;
        int size;
        int status;
-       u32 *firmware_status;
+       u32 (*get_firmware_status)(struct ndctl_cmd *cmd);
        struct ndctl_cmd_iter {
                u32 init_offset;
                u32 *offset;
@@ -268,6 +269,7 @@ struct ndctl_cmd {
                struct nd_cmd_ars_status ars_status[0];
                struct nd_cmd_clear_error clear_err[0];
                struct nd_cmd_pkg pkg[0];
+               struct nd_cmd_bus cmd_bus[0];
                struct ndn_pkg_hpe1 hpe1[0];
                struct ndn_pkg_msft msft[0];
                struct nd_pkg_hyperv hyperv[0];
@@ -341,6 +343,7 @@ struct ndctl_dimm_ops {
        struct ndctl_cmd *(*new_ack_shutdown_count)(struct ndctl_dimm *);
        int (*fw_update_supported)(struct ndctl_dimm *);
        int (*xlat_firmware_status)(struct ndctl_cmd *);
+       u32 (*get_firmware_status)(struct ndctl_cmd *);
 };
 
 extern struct ndctl_dimm_ops * const intel_dimm_ops;
diff --git a/ndctl/libndctl-nfit.h b/ndctl/libndctl-nfit.h
index d5335c23d28b..8c4f72dfa7ec 100644
--- a/ndctl/libndctl-nfit.h
+++ b/ndctl/libndctl-nfit.h
@@ -17,6 +17,7 @@
 #define __LIBNDCTL_NFIT_H__
 
 #include <linux/types.h>
+#include <ndctl/ndctl.h>
 
 /*
  * libndctl-nfit.h : definitions for NFIT related commands/functions.
@@ -87,6 +88,16 @@ struct nd_cmd_ars_err_inj_stat {
        } __attribute__((packed)) record[0];
 } __attribute__((packed));
 
+struct nd_cmd_bus {
+       struct nd_cmd_pkg gen;
+       union {
+               struct nd_cmd_ars_err_inj_stat err_inj_stat;
+               struct nd_cmd_ars_err_inj_clr err_inj_clr;
+               struct nd_cmd_ars_err_inj err_inj;
+               struct nd_cmd_translate_spa xlat_spa;
+       };
+};
+
 int ndctl_bus_is_nfit_cmd_supported(struct ndctl_bus *bus, int cmd);
 
 #endif /* __LIBNDCTL_NFIT_H__ */
_______________________________________________
Linux-nvdimm mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to