From patchwork Sat Feb 29 20:22:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 11414045 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E3A921395 for ; Sat, 29 Feb 2020 20:38:19 +0000 (UTC) Received: from ml01.01.org (ml01.01.org [198.145.21.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id CA8AC20836 for ; Sat, 29 Feb 2020 20:38:19 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org CA8AC20836 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=intel.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-nvdimm-bounces@lists.01.org Received: from ml01.vlan13.01.org (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 6F26E10FC36EE; Sat, 29 Feb 2020 12:39:11 -0800 (PST) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=192.55.52.151; helo=mga17.intel.com; envelope-from=dan.j.williams@intel.com; receiver= Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 1D18410FC3593 for ; Sat, 29 Feb 2020 12:39:09 -0800 (PST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 29 Feb 2020 12:38:17 -0800 X-IronPort-AV: E=Sophos;i="5.70,501,1574150400"; d="scan'208";a="437787403" Received: from dwillia2-desk3.jf.intel.com (HELO dwillia2-desk3.amr.corp.intel.com) ([10.54.39.16]) by fmsmga005-auth.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 29 Feb 2020 12:38:16 -0800 Subject: [ndctl PATCH 24/36] ndctl/dimm: Rework dimm command status reporting From: Dan Williams To: linux-nvdimm@lists.01.org Cc: vishal.l.verma@intel.com Date: Sat, 29 Feb 2020 12:22:12 -0800 Message-ID: <158300773196.2141307.16404460619761697075.stgit@dwillia2-desk3.amr.corp.intel.com> In-Reply-To: <158300760415.2141307.14060353322051900501.stgit@dwillia2-desk3.amr.corp.intel.com> References: <158300760415.2141307.14060353322051900501.stgit@dwillia2-desk3.amr.corp.intel.com> User-Agent: StGit/0.18-3-g996c MIME-Version: 1.0 Message-ID-Hash: 3DPUFQ5Z2QCOC5QHPLDQSZ67RZWD2PDK X-Message-ID-Hash: 3DPUFQ5Z2QCOC5QHPLDQSZ67RZWD2PDK X-MailFrom: dan.j.williams@intel.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.1.1 Precedence: list List-Id: "Linux-nvdimm developer list." Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: 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 --- 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 #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 #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 +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 +#include /* * 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__ */