1
0
Fork 0

Merging upstream version 2.14.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-05-22 13:00:36 +02:00
parent 0d9181726f
commit f268303a51
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
572 changed files with 4636 additions and 1730 deletions

View file

@ -1,27 +1,70 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <errno.h>
#include <fcntl.h>
#include "nvme.h"
#include "plugin.h"
#include "nvme-print.h"
#include "common.h"
#define CREATE_CMD
#include "feat-nvme.h"
#define STR(x) #x
#define TMT(n) "thermal management temperature " STR(n)
struct perfc_config {
__u32 namespace_id;
__u8 attri;
bool rvspa;
__u8 r4karl;
char *paid;
__u16 attrl;
char *vs_data;
__u8 sel;
};
struct temp_thresh_config {
__u16 tmpth;
__u8 tmpsel;
__u8 thsel;
__u8 tmpthh;
__u8 sel;
};
static const char *power_mgmt_feat = "power management feature";
static const char *sel = "[0-3]: current/default/saved/supported";
static const char *save = "Specifies that the controller shall save the attribute";
static const char *perfc_feat = "performance characteristics feature";
static const char *hctm_feat = "host controlled thermal management feature";
static const char *timestamp_feat = "timestamp feature";
static int power_mgmt_get(struct nvme_dev *dev, const __u8 fid, __u8 sel)
static int feat_get(struct nvme_dev *dev, const __u8 fid, __u32 cdw11, __u8 sel, const char *feat)
{
__u32 result;
int err;
__u32 len = 0;
_cleanup_free_ void *buf = NULL;
if (!NVME_CHECK(sel, GET_FEATURES_SEL, SUPPORTED))
nvme_get_feature_length(fid, cdw11, &len);
if (len) {
buf = nvme_alloc(len - 1);
if (!buf)
return -ENOMEM;
}
struct nvme_get_features_args args = {
.args_size = sizeof(args),
.fd = dev_fd(dev),
.fid = fid,
.sel = sel,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = &result,
.args_size = sizeof(args),
.fd = dev_fd(dev),
.fid = fid,
.sel = sel,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = &result,
.cdw11 = cdw11,
.data = buf,
.data_len = len,
};
err = nvme_get_features(&args);
@ -29,9 +72,11 @@ static int power_mgmt_get(struct nvme_dev *dev, const __u8 fid, __u8 sel)
if (NVME_CHECK(sel, GET_FEATURES_SEL, SUPPORTED))
nvme_show_select_result(fid, result);
else
nvme_feature_show_fields(fid, result, NULL);
nvme_feature_show_fields(fid, result, buf);
} else if (err > 0) {
nvme_show_status(err);
} else {
nvme_show_error("Get %s", power_mgmt_feat);
nvme_show_error("Get %s: %s", feat, nvme_strerror(errno));
}
return err;
@ -83,26 +128,343 @@ static int feat_power_mgmt(int argc, char **argv, struct command *cmd, struct pl
struct config {
__u8 ps;
__u8 wh;
bool save;
__u8 sel;
};
struct config cfg = { 0 };
NVME_ARGS(opts,
FEAT_ARGS(opts,
OPT_BYTE("ps", 'p', &cfg.ps, ps),
OPT_BYTE("wh", 'w', &cfg.wh, wh),
OPT_FLAG("save", 's', &cfg.save, save),
OPT_BYTE("sel", 'S', &cfg.sel, sel));
OPT_BYTE("wh", 'w', &cfg.wh, wh));
err = parse_and_open(&dev, argc, argv, POWER_MGMT_DESC, opts);
if (err)
return err;
if (argconfig_parse_seen(opts, "ps"))
err = power_mgmt_set(dev, fid, cfg.ps, cfg.wh, cfg.save);
err = power_mgmt_set(dev, fid, cfg.ps, cfg.wh, argconfig_parse_seen(opts, "save"));
else
err = power_mgmt_get(dev, fid, cfg.sel);
err = feat_get(dev, fid, 0, cfg.sel, power_mgmt_feat);
return err;
}
static int perfc_set(struct nvme_dev *dev, __u8 fid, __u32 cdw11, struct perfc_config *cfg,
bool save)
{
__u32 result;
int err;
_cleanup_fd_ int ffd = STDIN_FILENO;
struct nvme_perf_characteristics data = {
.attr_buf = { 0 },
};
struct nvme_set_features_args args = {
.args_size = sizeof(args),
.fd = dev_fd(dev),
.fid = fid,
.cdw11 = cdw11,
.save = save,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = &result,
.data = &data,
.data_len = sizeof(data),
};
switch (cfg->attri) {
case NVME_FEAT_PERFC_ATTRI_STD:
data.std_perf->r4karl = cfg->r4karl;
break;
case NVME_FEAT_PERFC_ATTRI_VS_MIN ... NVME_FEAT_PERFC_ATTRI_VS_MAX:
nvme_uuid_from_string(cfg->paid, data.vs_perf->paid);
data.vs_perf->attrl = cfg->attrl;
if (data.vs_perf->attrl && strlen(cfg->vs_data)) {
ffd = open(cfg->vs_data, O_RDONLY);
if (ffd < 0) {
nvme_show_error("Failed to open file %s: %s", cfg->vs_data,
strerror(errno));
return -EINVAL;
}
err = read(ffd, data.vs_perf->vs, data.vs_perf->attrl);
if (err < 0) {
nvme_show_error("failed to read data buffer from input file: %s",
strerror(errno));
return -errno;
}
}
break;
default:
break;
}
err = nvme_set_features(&args);
nvme_show_init();
if (err > 0) {
nvme_show_status(err);
} else if (err < 0) {
nvme_show_perror("Set %s", perfc_feat);
} else {
nvme_show_result("Set %s: 0x%04x (%s)", perfc_feat, args.cdw11,
save ? "Save" : "Not save");
nvme_feature_show_fields(args.fid, args.cdw11, NULL);
}
nvme_show_finish();
return err;
}
static int feat_perfc(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *namespace_id_optional = "optional namespace attached to controller";
const char *attri = "attribute index";
const char *rvspa = "revert vendor specific performance attribute";
const char *r4karl = "random 4 kib average read latency";
const char *paid = "performance attribute identifier";
const char *attrl = "attribute length";
const char *vs_data = "vendor specific data";
_cleanup_nvme_dev_ struct nvme_dev *dev = NULL;
int err;
__u8 fid = NVME_FEAT_FID_PERF_CHARACTERISTICS;
__u32 cdw11;
struct perfc_config cfg = { 0 };
FEAT_ARGS(opts,
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id_optional),
OPT_BYTE("attri", 'a', &cfg.attri, attri),
OPT_FLAG("rvspa", 'r', &cfg.rvspa, rvspa),
OPT_BYTE("r4karl", 'R', &cfg.r4karl, r4karl),
OPT_STR("paid", 'p', &cfg.paid, paid),
OPT_SHRT("attrl", 'A', &cfg.attrl, attrl),
OPT_FILE("vs-data", 'V', &cfg.vs_data, vs_data));
err = parse_and_open(&dev, argc, argv, PERFC_DESC, opts);
if (err)
return err;
cdw11 = NVME_SET(cfg.attri, FEAT_PERFC_ATTRI) | NVME_SET(cfg.rvspa, FEAT_PERFC_RVSPA);
if (argconfig_parse_seen(opts, "rvspa") || argconfig_parse_seen(opts, "r4karl") ||
argconfig_parse_seen(opts, "paid"))
err = perfc_set(dev, fid, cdw11, &cfg, argconfig_parse_seen(opts, "save"));
else
err = feat_get(dev, fid, cdw11, cfg.sel, perfc_feat);
return err;
}
static int hctm_set(struct nvme_dev *dev, const __u8 fid, __u16 tmt1, __u16 tmt2, bool save)
{
__u32 result;
int err;
struct nvme_set_features_args args = {
.args_size = sizeof(args),
.fd = dev_fd(dev),
.fid = fid,
.cdw11 = NVME_SET(tmt1, FEAT_HCTM_TMT1) | NVME_SET(tmt2, FEAT_HCTM_TMT2),
.save = save,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = &result,
};
err = nvme_set_features(&args);
nvme_show_init();
if (err > 0) {
nvme_show_status(err);
} else if (err < 0) {
nvme_show_perror("Set %s", hctm_feat);
} else {
nvme_show_result("Set %s: 0x%04x (%s)", hctm_feat, args.cdw11,
save ? "Save" : "Not save");
nvme_feature_show_fields(fid, args.cdw11, NULL);
}
nvme_show_finish();
return err;
}
static int feat_hctm(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const __u8 fid = NVME_FEAT_FID_HCTM;
_cleanup_nvme_dev_ struct nvme_dev *dev = NULL;
int err;
struct config {
__u16 tmt1;
__u16 tmt2;
__u8 sel;
};
struct config cfg = { 0 };
FEAT_ARGS(opts,
OPT_SHRT("tmt1", 't', &cfg.tmt1, TMT(1)),
OPT_SHRT("tmt2", 'T', &cfg.tmt2, TMT(2)));
err = parse_and_open(&dev, argc, argv, HCTM_DESC, opts);
if (err)
return err;
if (argconfig_parse_seen(opts, "tmt1") || argconfig_parse_seen(opts, "tmt2"))
err = hctm_set(dev, fid, cfg.tmt1, cfg.tmt2, argconfig_parse_seen(opts, "save"));
else
err = feat_get(dev, fid, 0, cfg.sel, hctm_feat);
return err;
}
static int timestamp_set(struct nvme_dev *dev, const __u8 fid, __u64 tstmp, bool save)
{
__u32 result;
int err;
struct nvme_timestamp ts;
__le64 timestamp = cpu_to_le64(tstmp);
struct nvme_set_features_args args = {
.args_size = sizeof(args),
.fd = dev_fd(dev),
.fid = fid,
.save = save,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = &result,
.data = &ts,
.data_len = sizeof(ts),
};
memcpy(ts.timestamp, &timestamp, sizeof(ts.timestamp));
err = nvme_set_features(&args);
nvme_show_init();
if (err > 0) {
nvme_show_status(err);
} else if (err < 0) {
nvme_show_perror("Set %s", timestamp_feat);
} else {
nvme_show_result("Set %s: (%s)", timestamp_feat, save ? "Save" : "Not save");
nvme_feature_show_fields(fid, args.cdw11, args.data);
}
nvme_show_finish();
return err;
}
static int feat_timestamp(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const __u8 fid = NVME_FEAT_FID_TIMESTAMP;
const char *tstmp = "timestamp";
_cleanup_nvme_dev_ struct nvme_dev *dev = NULL;
int err;
struct config {
__u64 tstmp;
__u8 sel;
};
struct config cfg = { 0 };
FEAT_ARGS(opts, OPT_LONG("tstmp", 't', &cfg.tstmp, tstmp));
err = parse_and_open(&dev, argc, argv, TIMESTAMP_DESC, opts);
if (err)
return err;
if (argconfig_parse_seen(opts, "tstmp"))
err = timestamp_set(dev, fid, cfg.tstmp, argconfig_parse_seen(opts, "save"));
else
err = feat_get(dev, fid, 0, cfg.sel, timestamp_feat);
return err;
}
static int temp_thresh_set(int fd, const __u8 fid, struct argconfig_commandline_options *opts,
struct temp_thresh_config *cfg)
{
__u32 result;
int err;
enum nvme_get_features_sel sel = NVME_GET_FEATURES_SEL_CURRENT;
__u16 tmpth;
__u8 tmpsel;
__u8 thsel;
__u8 tmpthh;
bool save = argconfig_parse_seen(opts, "save");
if (save)
sel = NVME_GET_FEATURES_SEL_SAVED;
err = nvme_get_features_temp_thresh2(fd, sel, cfg->tmpsel, cfg->thsel, &result);
if (!err) {
nvme_feature_decode_temp_threshold(result, &tmpth, &tmpsel, &thsel, &tmpthh);
if (!argconfig_parse_seen(opts, "tmpth"))
cfg->tmpth = tmpth;
if (!argconfig_parse_seen(opts, "tmpthh"))
cfg->tmpthh = tmpthh;
}
err = nvme_set_features_temp_thresh2(fd, cfg->tmpth, cfg->tmpsel, cfg->thsel, cfg->tmpthh,
save, &result);
nvme_show_init();
if (err > 0) {
nvme_show_status(err);
} else if (err < 0) {
nvme_show_perror("Set %s", timestamp_feat);
} else {
nvme_show_result("Set %s: (%s)", timestamp_feat, save ? "Save" : "Not save");
nvme_feature_show_fields(fid, NVME_SET(cfg->tmpth, FEAT_TT_TMPTH) |
NVME_SET(cfg->tmpsel, FEAT_TT_TMPSEL) |
NVME_SET(cfg->thsel, FEAT_TT_THSEL) |
NVME_SET(cfg->tmpthh, FEAT_TT_TMPTHH), NULL);
}
nvme_show_finish();
return err;
}
static int feat_temp_thresh(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const __u8 fid = NVME_FEAT_FID_TEMP_THRESH;
const char *tmpth = "temperature threshold";
const char *tmpsel = "threshold temperature select";
const char *thsel = "threshold type select";
const char *tmpthh = "temperature threshold hysteresis";
_cleanup_nvme_dev_ struct nvme_dev *dev = NULL;
int err;
struct temp_thresh_config cfg = { 0 };
FEAT_ARGS(opts,
OPT_SHRT("tmpth", 'T', &cfg.tmpth, tmpth),
OPT_BYTE("tmpsel", 'm', &cfg.tmpsel, tmpsel),
OPT_BYTE("thsel", 'H', &cfg.thsel, thsel),
OPT_BYTE("tmpthh", 'M', &cfg.tmpthh, tmpthh));
err = parse_and_open(&dev, argc, argv, TEMP_THRESH_DESC, opts);
if (err)
return err;
if (argconfig_parse_seen(opts, "tmpth") || argconfig_parse_seen(opts, "tmpthh"))
err = temp_thresh_set(dev_fd(dev), fid, opts, &cfg);
else
err = feat_get(dev, fid, NVME_SET(cfg.tmpsel, FEAT_TT_TMPSEL) |
NVME_SET(cfg.thsel, FEAT_TT_THSEL), cfg.sel, timestamp_feat);
return err;
}

View file

@ -11,10 +11,22 @@
#define FEAT_PLUGIN_VERSION "1.0"
#define POWER_MGMT_DESC "Get and set power management feature"
#define PERFC_DESC "Get and set perf characteristics feature"
#define HCTM_DESC "Get and set host controlled thermal management feature"
#define TIMESTAMP_DESC "Get and set timestamp feature"
#define TEMP_THRESH_DESC "Get and set temperature threshold feature"
#define FEAT_ARGS(n, ...) \
NVME_ARGS(n, ##__VA_ARGS__, OPT_FLAG("save", 's', NULL, save), \
OPT_BYTE("sel", 'S', &cfg.sel, sel))
PLUGIN(NAME("feat", "NVMe feature extensions", FEAT_PLUGIN_VERSION),
COMMAND_LIST(
ENTRY("power-mgmt", POWER_MGMT_DESC, feat_power_mgmt)
ENTRY("perf-characteristics", PERFC_DESC, feat_perfc)
ENTRY("hctm", HCTM_DESC, feat_hctm)
ENTRY("timestamp", TIMESTAMP_DESC, feat_timestamp)
ENTRY("temp-thresh", TEMP_THRESH_DESC, feat_temp_thresh)
)
);
#endif /* !FEAT_NVME || CMD_HEADER_MULTI_READ */

View file

@ -0,0 +1,59 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2025 MangoBoost Inc.
*
* Author: Jonghyeon Kim <jonghyeon.kim@mangoboost.io>
*/
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <inttypes.h>
#include "common.h"
#include "nvme.h"
#include "libnvme.h"
#include "plugin.h"
#define CREATE_CMD
#include "mangoboost-nvme.h"
struct nvme_vu_id_ctrl_field {
__u16 json_rpc_2_0_mjr;
__u16 json_rpc_2_0_mnr;
__u16 json_rpc_2_0_ter;
__u8 reserved0[1018];
};
static void json_mangoboost_id_ctrl(struct nvme_vu_id_ctrl_field *id,
char *json_rpc_2_0_ver, struct json_object *root)
{
json_object_add_value_string(root, "json_rpc_2_0_ver",
json_rpc_2_0_ver);
}
static void mangoboost_id_ctrl(__u8 *vs, struct json_object *root)
{
struct nvme_vu_id_ctrl_field *id = (struct nvme_vu_id_ctrl_field *)vs;
char json_rpc_2_0_ver[16] = { 0 };
snprintf(json_rpc_2_0_ver, sizeof(json_rpc_2_0_ver), "0x%04x%04x%04x",
le16_to_cpu(id->json_rpc_2_0_mjr),
le16_to_cpu(id->json_rpc_2_0_mnr),
le16_to_cpu(id->json_rpc_2_0_ter));
if (root) {
json_mangoboost_id_ctrl(id, json_rpc_2_0_ver, root);
return;
}
printf("json_rpc_2_0_ver : %s\n", json_rpc_2_0_ver);
}
static int id_ctrl(int argc, char **argv, struct command *cmd,
struct plugin *plugin)
{
return __id_ctrl(argc, argv, cmd, plugin, mangoboost_id_ctrl);
}

View file

@ -0,0 +1,24 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2025 MangoBoost Inc.
*
* Author: Jonghyeon Kim <jonghyeon.kim@mangoboost.io>
*/
#undef CMD_INC_FILE
#define CMD_INC_FILE plugins/mangoboost/mangoboost-nvme
#if !defined(MANGOBOOST_NVME) || defined(CMD_HEADER_MULTI_READ)
#define MANGOBOOST_NVME
#include "cmd.h"
PLUGIN(NAME("mangoboost", "MangoBoost vendor specific extensions", NVME_VERSION),
COMMAND_LIST(
ENTRY("id-ctrl", "Send NVMe Identify Controller", id_ctrl)
)
);
#endif
#include "define_cmd.h"

View file

@ -10,6 +10,7 @@ sources += [
'plugins/innogrit/innogrit-nvme.c',
'plugins/inspur/inspur-nvme.c',
'plugins/intel/intel-nvme.c',
'plugins/mangoboost/mangoboost-nvme.c',
'plugins/memblaze/memblaze-nvme.c',
'plugins/micron/micron-nvme.c',
'plugins/nbft/nbft-plugin.c',

File diff suppressed because it is too large Load diff

View file

@ -1,11 +1,11 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) Micron, Inc 2024.
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* Copyright (c) Micron, Inc 2024.
*
* @file: micron-nvme.h
* @brief: This module contains all the constructs needed for micron nvme-cli plugin.
* @authors:Chaithanya Shoba <ashoba@micron.com>,
*/
#undef CMD_INC_FILE
#define CMD_INC_FILE plugins/micron/micron-nvme
@ -35,6 +35,15 @@ PLUGIN(NAME("micron", "Micron vendor specific extensions", NVME_VERSION),
ENTRY("vs-smart-add-log", "Retrieve extended SMART data", micron_ocp_smart_health_logs)
ENTRY("clear-fw-activate-history", "Clear FW activation history", micron_clr_fw_activation_history)
ENTRY("vs-smbus-option", "Enable/Disable SMBUS on the drive", micron_smbus_option)
ENTRY("cloud-boot-SSD-version", "Prints HyperScale Boot Version",
micron_cloud_boot_SSD_version)
ENTRY("vs-device-waf", "Reports SLC and TLC WAF ratio", micron_device_waf)
ENTRY("vs-cloud-log",
"Retrieve Extended Health Information of Hyperscale NVMe Boot SSD",
micron_cloud_log)
ENTRY("vs-work-load-log", "Retrieve Workload logs", micron_work_load_log)
ENTRY("vs-vendor-telemetry-log",
"Retrieve Vendor Telemetry logs", micron_vendor_telemetry_log)
)
);

View file

@ -9,7 +9,7 @@
#include "nvme.h"
#include "nbft.h"
#include "fabrics.h"
#include "util/logging.h"
#include "logging.h"
#define CREATE_CMD
#include "nbft-plugin.h"

View file

@ -75,6 +75,81 @@ close_dev:
return err;
}
int get_ocp_error_counters(int argc, char **argv, struct command *cmd,
struct plugin *plugin)
{
const char *desc = "Define Issue Get Feature cmd (FID: 0xC3) Clear PCIe Corr Err Counters";
const char *sel = "[0-3]: current/default/saved/supported/";
const char *nsid = "Byte[04-07]: Namespace Identifier Valid/Invalid/Inactive";
const char *no_uuid = "Do not try to automatically detect UUID index";
_cleanup_nvme_dev_ struct nvme_dev *dev = NULL;
__u32 result;
int err;
bool uuid;
__u8 uuid_index = 0;
struct config {
__u8 sel;
__u32 nsid;
};
struct config cfg = {
.sel = 0,
.nsid = 0,
};
OPT_ARGS(opts) = {
OPT_BYTE("sel", 's', &cfg.sel, sel),
OPT_UINT("namespace-id", 'n', &cfg.nsid, nsid),
OPT_FLAG("no-uuid", 'u', NULL, no_uuid),
OPT_END()
};
err = parse_and_open(&dev, argc, argv, desc, opts);
if (err)
return err;
uuid = !argconfig_parse_seen(opts, "no-uuid");
if (uuid) {
/* OCP 2.0 requires UUID index support */
err = ocp_get_uuid_index(dev, &uuid_index);
if (err || !uuid_index) {
nvme_show_error("ERROR: No OCP UUID index found");
return err;
}
}
struct nvme_get_features_args args = {
.args_size = sizeof(args),
.fd = dev_fd(dev),
.fid = OCP_FID_CPCIE,
.nsid = cfg.nsid,
.sel = cfg.sel,
.cdw11 = 0,
.uuidx = uuid_index,
.data_len = 0,
.data = NULL,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = &result,
};
err = nvme_get_features(&args);
if (!err) {
printf("get-feature:0xC3 %s value: %#08x\n",
nvme_select_to_string(cfg.sel), result);
if (cfg.sel == NVME_GET_FEATURES_SEL_SUPPORTED)
nvme_show_select_result(0xC3, result);
} else {
nvme_show_error("Could not get feature: 0xC3");
}
return err;
}
int ocp_clear_fw_update_history(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "OCP Clear Firmware Update History";

View file

@ -10,3 +10,6 @@ int ocp_clear_fw_update_history(int argc, char **argv, struct command *cmd, stru
int ocp_clear_pcie_correctable_errors(int argc, char **argv, struct command *cmd,
struct plugin *plugin);
int get_ocp_error_counters(int argc, char **argv, struct command *cmd,
struct plugin *plugin);

View file

@ -7,7 +7,7 @@
#include "common.h"
#include "util/types.h"
#include "util/logging.h"
#include "logging.h"
#include "nvme-print.h"
#include "ocp-hardware-component-log.h"
#include "ocp-print.h"

View file

@ -22,7 +22,7 @@
#include "plugin.h"
#include "linux/types.h"
#include "util/types.h"
#include "util/logging.h"
#include "logging.h"
#include "nvme-print.h"
#include "nvme-wrap.h"
@ -423,6 +423,80 @@ int ocp_set_latency_monitor_feature(int argc, char **argv, struct command *cmd,
return err;
}
static int ocp_get_latency_monitor_feature(int argc, char **argv, struct command *cmd,
struct plugin *plugin)
{
const char *desc = "Define Issue Get Feature command (FID: 0xC5) Latency Monitor";
const char *sel = "[0-3]: current/default/saved/supported/";
const char *nsid = "Byte[04-07]: Namespace Identifier Valid/Invalid/Inactive";
_cleanup_nvme_dev_ struct nvme_dev *dev = NULL;
__u32 result;
int err;
bool uuid;
__u8 uuid_index = 0;
struct config {
__u8 sel;
__u32 nsid;
};
struct config cfg = {
.sel = 0,
.nsid = 0,
};
OPT_ARGS(opts) = {
OPT_BYTE("sel", 's', &cfg.sel, sel),
OPT_UINT("namespace-id", 'n', &cfg.nsid, nsid),
OPT_FLAG("no-uuid", 'u', NULL, no_uuid),
OPT_END()
};
err = parse_and_open(&dev, argc, argv, desc, opts);
if (err)
return err;
uuid = !argconfig_parse_seen(opts, "no-uuid");
if (uuid) {
/* OCP 2.0 requires UUID index support */
err = ocp_get_uuid_index(dev, &uuid_index);
if (err || !uuid_index) {
nvme_show_error("ERROR: No OCP UUID index found");
return err;
}
}
struct nvme_get_features_args args = {
.args_size = sizeof(args),
.fd = dev_fd(dev),
.fid = OCP_FID_LM,
.nsid = cfg.nsid,
.sel = cfg.sel,
.cdw11 = 0,
.uuidx = uuid_index,
.data_len = 0,
.data = NULL,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = &result,
};
err = nvme_get_features(&args);
if (!err) {
printf("get-feature:0xC5 %s value: %#08x\n",
nvme_select_to_string(cfg.sel), result);
if (cfg.sel == NVME_GET_FEATURES_SEL_SUPPORTED)
nvme_show_select_result(0xC5, result);
} else {
nvme_show_error("Could not get feature: 0xC5");
}
return err;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
@ -1948,6 +2022,85 @@ static int ocp_set_telemetry_profile_feature(int argc, char **argv, struct comma
return err;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// DSSD Power State (Feature Identifier C8h) Get Feature
static int ocp_get_telemetry_profile_feature(int argc, char **argv, struct command *cmd,
struct plugin *plugin)
{
const char *desc = "Define Issue Get Feature command (FID: 0xC8) Latency Monitor";
const char *sel = "[0-3]: current/default/saved/supported/";
const char *nsid = "Byte[04-07]: Namespace Identifier Valid/Invalid/Inactive";
_cleanup_nvme_dev_ struct nvme_dev *dev = NULL;
__u32 result;
int err;
bool uuid;
__u8 uuid_index = 0;
struct config {
__u8 sel;
__u32 nsid;
};
struct config cfg = {
.sel = 0,
.nsid = 0,
};
OPT_ARGS(opts) = {
OPT_BYTE("sel", 's', &cfg.sel, sel),
OPT_UINT("namespace-id", 'n', &cfg.nsid, nsid),
OPT_FLAG("no-uuid", 'u', NULL, no_uuid),
OPT_END()
};
err = parse_and_open(&dev, argc, argv, desc, opts);
if (err)
return err;
uuid = !argconfig_parse_seen(opts, "no-uuid");
if (uuid) {
/* OCP 2.0 requires UUID index support */
err = ocp_get_uuid_index(dev, &uuid_index);
if (err || !uuid_index) {
nvme_show_error("ERROR: No OCP UUID index found");
return err;
}
}
struct nvme_get_features_args args = {
.args_size = sizeof(args),
.fd = dev_fd(dev),
.fid = OCP_FID_TEL_CFG,
.nsid = cfg.nsid,
.sel = cfg.sel,
.cdw11 = 0,
.uuidx = uuid_index,
.data_len = 0,
.data = NULL,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = &result,
};
err = nvme_get_features(&args);
if (!err) {
printf("get-feature:0xC8 %s value: %#08x\n",
nvme_select_to_string(cfg.sel), result);
if (cfg.sel == NVME_GET_FEATURES_SEL_SUPPORTED)
nvme_show_select_result(0xC8, result);
} else {
nvme_show_error("Could not get feature: 0xC8");
}
return err;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
@ -2612,6 +2765,12 @@ static int clear_pcie_correctable_error_counters(int argc, char **argv, struct c
return ocp_clear_pcie_correctable_errors(argc, argv, cmd, plugin);
}
static int get_clear_pcie_correctable_error_counters(int argc, char **argv, struct command *cmd,
struct plugin *plugin)
{
return get_ocp_error_counters(argc, argv, cmd, plugin);
}
static int fw_activation_history_log(int argc, char **argv, struct command *cmd,
struct plugin *plugin)
{

View file

@ -42,6 +42,12 @@ PLUGIN(NAME("ocp", "OCP cloud SSD extensions", OCP_PLUGIN_VERSION),
get_enable_ieee1667_silo)
ENTRY("set-enable-ieee1667-silo", "enable IEEE1667 silo", set_enable_ieee1667_silo)
ENTRY("hardware-component-log", "retrieve hardware component log", hwcomp_log)
ENTRY("get-latency-monitor", "Get Latency Monitor Feature",
ocp_get_latency_monitor_feature)
ENTRY("get-clear-pcie-correctable-errors", "Clear PCIe correctable error counters",
get_clear_pcie_correctable_error_counters)
ENTRY("get-telemetry-profile", "Get Telemetry Profile Feature",
ocp_get_telemetry_profile_feature)
)
);

View file

@ -321,7 +321,7 @@ static void stdout_c3_log(struct nvme_dev *dev, struct ssd_latency_monitor_log *
printf(" Log Page GUID %s\n", guid);
printf("\n");
printf("%64s%92s%119s\n", "Read", "Write", "Deallocate/Trim");
printf("%64s %27s %27s\n", "Read", "Write", "Deallocate/Trim");
for (i = 0; i < C3_BUCKET_NUM; i++) {
printf(" Active Bucket Counter: Bucket %d %27d %27d %27d\n",
i,

View file

@ -1027,17 +1027,22 @@ int parse_event_fifo(unsigned int fifo_num, unsigned char *pfifo_start,
if (pevent_descriptor->debug_event_class_type == RESERVED_CLASS_TYPE)
break;
if (pevent_descriptor != NULL && pevent_descriptor->event_data_size >= 0) {
__u8 *pevent_specific_data = NULL;
__u16 event_id = 0;
char description_str[256] = "";
unsigned int data_size = 0;
if (pevent_descriptor != NULL &&
pevent_descriptor->event_data_size >= 0 &&
pevent_descriptor->debug_event_class_type !=
STATISTIC_SNAPSHOT_CLASS_TYPE) {
event_des_size = sizeof(struct nvme_ocp_telemetry_event_descriptor);
/* Data is present in the form of DWORDS,
* So multiplying with sizeof(DWORD)
*/
unsigned int data_size = pevent_descriptor->event_data_size *
data_size = pevent_descriptor->event_data_size *
SIZE_OF_DWORD;
__u8 *pevent_specific_data = NULL;
__u16 event_id = 0;
char description_str[256] = "";
if (pevent_descriptor != NULL && pevent_descriptor->event_data_size > 0)
pevent_specific_data = (__u8 *)pevent_descriptor + event_des_size;
@ -1128,18 +1133,6 @@ int parse_event_fifo(unsigned int fifo_num, unsigned char *pfifo_start,
pevent_fifos_object,
fp);
break;
case STATISTIC_SNAPSHOT_CLASS_TYPE: {
struct nvme_ocp_statistic_snapshot_evt_class_format
*pStaticSnapshotEvent =
(struct nvme_ocp_statistic_snapshot_evt_class_format *)
pevent_specific_data;
struct nvme_ocp_telemetry_statistic_descriptor *pstatistic_entry =
(struct nvme_ocp_telemetry_statistic_descriptor *)
(&pStaticSnapshotEvent->statisticDescriptorData);
parse_statistic(pstatistic_entry, pevent_descriptor_obj, fp);
break;
}
case RESERVED_CLASS_TYPE:
default:
break;
@ -1154,11 +1147,67 @@ int parse_event_fifo(unsigned int fifo_num, unsigned char *pfifo_start,
else
printf(STR_LINE2);
}
} else
break;
} else if ((pevent_descriptor != NULL) &&
(pevent_descriptor->debug_event_class_type ==
STATISTIC_SNAPSHOT_CLASS_TYPE)) {
parse_ocp_telemetry_string_log(0, event_id,
pevent_descriptor->debug_event_class_type, EVENT_STRING,
description_str);
offset_to_move += (pevent_descriptor->event_data_size * SIZE_OF_DWORD +
event_des_size);
struct json_object *pevent_descriptor_obj =
((pevent_fifos_object != NULL) ? json_create_object() : NULL);
if (pevent_descriptor_obj != NULL) {
json_add_formatted_u32_str(pevent_descriptor_obj,
STR_DBG_EVENT_CLASS_TYPE,
pevent_descriptor->debug_event_class_type);
json_object_add_value_string(pevent_descriptor_obj,
STR_EVENT_STRING, description_str);
} else {
if (fp) {
fprintf(fp, "%s: 0x%x\n", STR_DBG_EVENT_CLASS_TYPE,
pevent_descriptor->debug_event_class_type);
fprintf(fp, "%s: %s\n", STR_EVENT_STRING, description_str);
} else {
printf("%s: 0x%x\n", STR_DBG_EVENT_CLASS_TYPE,
pevent_descriptor->debug_event_class_type);
printf("%s: %s\n", STR_EVENT_STRING, description_str);
}
}
struct nvme_ocp_statistic_snapshot_evt_class_format
*pStaticSnapshotEvent =
(struct nvme_ocp_statistic_snapshot_evt_class_format *)
pevent_descriptor;
event_des_size =
sizeof(struct nvme_ocp_statistic_snapshot_evt_class_format);
data_size =
(le16_to_cpu((unsigned int)pStaticSnapshotEvent->stat_data_size) *
SIZE_OF_DWORD);
if (pStaticSnapshotEvent != NULL &&
pStaticSnapshotEvent->stat_data_size > 0) {
__u8 *pstatistic_entry =
(__u8 *)pStaticSnapshotEvent +
sizeof(struct nvme_ocp_telemetry_event_descriptor);
parse_statistic(
(struct nvme_ocp_telemetry_statistic_descriptor *)
pstatistic_entry,
pevent_descriptor_obj,
fp);
}
} else {
if (fp)
fprintf(fp, "Unknown or null event class %p\n", pevent_descriptor);
else
printf("Unknown or null event class %p\n", pevent_descriptor);
break;
}
offset_to_move += (data_size + event_des_size);
}
if (pevent_fifos_object != NULL && pevent_fifo_array != NULL)
@ -1243,11 +1292,10 @@ int parse_statistic(struct nvme_ocp_telemetry_statistic_descriptor *pstatistic_e
return -1;
}
if (pstatistic_entry->statistic_id == STATISTICS_RESERVED_ID)
if (le16_to_cpu(pstatistic_entry->statistic_id) == STATISTICS_RESERVED_ID)
/* End of statistics entries, return -1 to stop processing the buffer */
return -1;
unsigned int data_size = pstatistic_entry->statistic_data_size * SIZE_OF_DWORD;
__u8 *pdata = (__u8 *)pstatistic_entry +
sizeof(struct nvme_ocp_telemetry_statistic_descriptor);

View file

@ -1102,7 +1102,13 @@ struct __packed nvme_ocp_common_dbg_evt_class_vu_data
struct __packed nvme_ocp_statistic_snapshot_evt_class_format
{
struct nvme_ocp_telemetry_statistic_descriptor statisticDescriptorData; // Bytes 11:10
__u8 debug_event_class_type; // Byte 0
__u8 reserved1[3]; // Bytes 3:1
__le16 stat_id; // Bytes 5:4
__u8 stat_info; // Byte 6
__u8 namespace_info; // Byte 7
__le16 stat_data_size; // Bytes 9:8
__le16 nsid; // Bytes 11:10
};
struct __packed nvme_ocp_statistics_identifier_string_table

View file

@ -130,7 +130,7 @@ static int sed_opal_revert(int argc, char **argv, struct command *cmd,
return err;
err = sedopal_cmd_revert(dev->direct.fd);
if ((err != 0) && (err != -EOPNOTSUPP))
if ((err != 0) && (err != -EOPNOTSUPP) && (err != EPERM))
fprintf(stderr, "revert: SED error - %s\n",
sedopal_error_to_text(err));
@ -190,7 +190,7 @@ static int sed_opal_password(int argc, char **argv, struct command *cmd,
return err;
err = sedopal_cmd_password(dev->direct.fd);
if (err != 0)
if ((err != 0) && (err != EPERM))
fprintf(stderr, "password: SED error - %s\n",
sedopal_error_to_text(err));

View file

@ -127,11 +127,15 @@ char *sedopal_get_password(char *prompt)
return NULL;
len = strlen(pass);
if (len < SEDOPAL_MIN_PASSWORD_LEN)
if (len < SEDOPAL_MIN_PASSWORD_LEN) {
fprintf(stderr, "Error: password is not long enough\n");
return NULL;
}
if (len > SEDOPAL_MAX_PASSWORD_LEN)
if (len > SEDOPAL_MAX_PASSWORD_LEN) {
fprintf(stderr, "Error: password is too long\n");
return NULL;
}
return pass;
}
@ -425,8 +429,12 @@ static int sedopal_revert_psid(int fd)
rc = sedopal_set_key(&key);
if (rc == 0) {
rc = ioctl(fd, IOC_OPAL_PSID_REVERT_TPR, &key);
if (rc != 0)
fprintf(stderr, "PSID_REVERT_TPR rc %d\n", rc);
if (rc != 0) {
if (rc == EPERM)
fprintf(stderr, "Error: incorrect password\n");
else
fprintf(stderr, "PSID_REVERT_TPR rc %d\n", rc);
}
}
return rc;
@ -457,6 +465,7 @@ int sedopal_cmd_revert(int fd)
#ifdef IOC_OPAL_REVERT_LSP
struct opal_revert_lsp revert_lsp;
uint8_t locking_state;
char *revert = "LSP";
locking_state = sedopal_locking_state(fd);
@ -481,6 +490,7 @@ int sedopal_cmd_revert(int fd)
rc = ioctl(fd, IOC_OPAL_REVERT_LSP, &revert_lsp);
if (rc == 0) {
revert = "TPER";
/*
* TPER must also be reverted.
*/
@ -488,12 +498,20 @@ int sedopal_cmd_revert(int fd)
if (rc != 0)
fprintf(stderr, "Error: revert TPR - %d\n", rc);
}
if (rc != 0) {
if (rc == EPERM)
fprintf(stderr, "Error: incorrect password\n");
else
fprintf(stderr, "Error: revert %s - %d\n",
revert, rc);
}
#else
rc = -EOPNOTSUPP;
#endif
}
if (rc != 0)
if ((rc != 0) && (rc != EPERM))
fprintf(stderr, "Error: failed reverting drive - %d\n", rc);
return rc;
@ -533,7 +551,10 @@ int sedopal_cmd_password(int fd)
*/
rc = ioctl(fd, IOC_OPAL_SET_PW, &new_pw);
if (rc != 0) {
fprintf(stderr, "Error: failed setting password - %d\n", rc);
if (rc == EPERM)
fprintf(stderr, "Error: incorrect password\n");
else
fprintf(stderr, "Error: setting password - %d\n", rc);
return rc;
}
@ -542,8 +563,12 @@ int sedopal_cmd_password(int fd)
* set sid password
*/
rc = ioctl(fd, IOC_OPAL_SET_SID_PW, &new_pw);
if (rc != 0)
fprintf(stderr, "Error: failed setting SID password - %d\n", rc);
if (rc != 0) {
if (rc == EPERM)
fprintf(stderr, "Error: incorrect password\n");
else
fprintf(stderr, "Error: setting SID pw - %d\n", rc);
}
#endif
return rc;

View file

@ -110,10 +110,12 @@ static struct lid_dir *get_solidigm_lids(struct nvme_supported_log_pages *suppor
solidigm_dir.lid[0xDD].str = "VU Marketing Description Log Page";
solidigm_dir.lid[0xEF].str = "Performance Rating and LBA Access Histogram";
solidigm_dir.lid[0xF2].str = "Get Power Usage Log Page";
solidigm_dir.lid[0xF4].str = "Nand Statistics Log Page";
solidigm_dir.lid[0xF5].str = "Nand Defects Count Log Page";
solidigm_dir.lid[0xF6].str = "Vt Histo Get Log Page";
solidigm_dir.lid[0xF9].str = "Workload Tracker Get Log Page";
solidigm_dir.lid[0xFD].str = "Garbage Control Collection Log Page";
solidigm_dir.lid[0xFE].str = "Latency Outlier Log Page";
solidigm_dir.lid[0xFE].str = "Latency Outlier / SK SMART Log Page";
update_vendor_lid_supported(supported, &solidigm_dir);
@ -131,6 +133,9 @@ static struct lid_dir *get_ocp_lids(struct nvme_supported_log_pages *supported)
ocp_dir.lid[0xC3].str = "OCP Latency Monitor";
ocp_dir.lid[0xC4].str = "OCP Device Capabilities";
ocp_dir.lid[0xC5].str = "OCP Unsupported Requirements";
ocp_dir.lid[0xC6].str = "OCP Hardware Component";
ocp_dir.lid[0xC7].str = "OCP TCG Configuration";
ocp_dir.lid[0xC9].str = "OCP Telemetry String Log";
update_vendor_lid_supported(supported, &ocp_dir);
@ -188,10 +193,11 @@ int solidigm_get_log_page_directory_log(int argc, char **argv, struct command *c
{
const int NO_UUID_INDEX = 0;
const char *description = "Retrieves list of supported log pages for each UUID index.";
char *format = "normal";
OPT_ARGS(options) = {
OPT_FMT("output-format", 'o', &format, "output format : normal | json"),
OPT_FMT("output-format", 'o', &nvme_cfg.output_format,
"output format : normal | json"),
OPT_INCR("verbose", 'v', &nvme_cfg.verbose, verbose),
OPT_END()
};
@ -244,9 +250,10 @@ int solidigm_get_log_page_directory_log(int argc, char **argv, struct command *c
if (!err) {
nvme_print_flags_t print_flag;
err = validate_output_format(format, &print_flag);
if (err < 0) {
fprintf(stderr, "Error: Invalid output format specified: %s.\n", format);
err = validate_output_format(nvme_cfg.output_format, &print_flag);
if (err) {
nvme_show_error("Error: Invalid output format specified: %s.\n",
nvme_cfg.output_format);
return err;
}

View file

@ -18,7 +18,9 @@
#include "libnvme.h"
#include "plugin.h"
#include "nvme-print.h"
#include "solidigm-util.h"
#define MARKET_LOG_LID 0xDD
#define MARKET_LOG_MAX_SIZE 512
int sldgm_get_market_log(int argc, char **argv, struct command *command,
@ -26,19 +28,15 @@ int sldgm_get_market_log(int argc, char **argv, struct command *command,
{
const char *desc = "Get Solidigm Marketing Name log and show it.";
const char *raw = "dump output in binary format";
struct nvme_dev *dev;
_cleanup_nvme_dev_ struct nvme_dev *dev = NULL;
char log[MARKET_LOG_MAX_SIZE];
int err;
struct config {
bool raw_binary;
};
struct config cfg = {
};
__u8 uuid_idx;
bool raw_binary = false;
OPT_ARGS(opts) = {
OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
OPT_FLAG("raw-binary", 'b', &raw_binary, raw),
OPT_INCR("verbose", 'v', &nvme_cfg.verbose, verbose),
OPT_END()
};
@ -46,17 +44,35 @@ int sldgm_get_market_log(int argc, char **argv, struct command *command,
if (err)
return err;
err = nvme_get_log_simple(dev_fd(dev), 0xdd, sizeof(log), log);
if (!err) {
if (!cfg.raw_binary)
printf("Solidigm Marketing Name Log:\n%s\n", log);
else
d_raw((unsigned char *)&log, sizeof(log));
} else if (err > 0)
sldgm_get_uuid_index(dev, &uuid_idx);
struct nvme_get_log_args args = {
.lpo = 0,
.result = NULL,
.log = log,
.args_size = sizeof(args),
.fd = dev_fd(dev),
.uuidx = uuid_idx,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.lid = MARKET_LOG_LID,
.len = sizeof(log),
.nsid = NVME_NSID_ALL,
.csi = NVME_CSI_NVM,
.lsi = NVME_LOG_LSI_NONE,
.lsp = NVME_LOG_LSP_NONE,
.rae = false,
.ot = false,
};
err = nvme_get_log(&args);
if (err) {
nvme_show_status(err);
return err;
}
if (!raw_binary)
printf("Solidigm Marketing Name Log:\n%s\n", log);
else
d_raw((unsigned char *)&log, sizeof(log));
nvme_show_status(err);
/* Redundant close() to make static code analysis happy */
close(dev->direct.fd);
dev_close(dev);
return err;
}

View file

@ -13,7 +13,7 @@
#include "cmd.h"
#define SOLIDIGM_PLUGIN_VERSION "1.11"
#define SOLIDIGM_PLUGIN_VERSION "1.12"
PLUGIN(NAME("solidigm", "Solidigm vendor specific extensions", SOLIDIGM_PLUGIN_VERSION),
COMMAND_LIST(

View file

@ -197,11 +197,11 @@ struct workloadLog { // Full WL Log Structure
struct wltracker {
int fd;
__u8 uuid_index;
struct workloadLog workload_log;
size_t poll_count;
bool show_wall_timestamp;
__u64 us_epoch_ssd_delta;
unsigned int verbose;
__u64 start_time_us;
__u64 run_time_us;
bool disable;
@ -229,7 +229,7 @@ static void wltracker_print_field_names(struct wltracker *wlt)
if (wlt->show_wall_timestamp)
printf("%-*s", (int)sizeof("YYYY-MM-DD-hh:mm:ss.uuuuuu"), "wall-time");
if (wlt->verbose > 1)
if (nvme_cfg.verbose > 1)
printf("%s", "entry# ");
printf("\n");
@ -250,7 +250,7 @@ static void wltracker_print_header(struct wltracker *wlt)
printf("%-24s %s\n", "Tracker Type:", trk_types[log->config.contentGroup]);
printf("%-24s %u\n", "Total log page entries:", le32_to_cpu(log->workloadLogCount));
printf("%-24s %u\n", "Trigger count:", log->triggeredEvents);
if (wlt->verbose > 1)
if (nvme_cfg.verbose > 1)
printf("%-24s %ld\n", "Poll count:", wlt->poll_count);
if (wlt->poll_count != 0)
wltracker_print_field_names(wlt);
@ -275,12 +275,12 @@ int wltracker_config(struct wltracker *wlt, union WorkloadLogEnable *we)
{
struct nvme_set_features_args args = {
.args_size = sizeof(args),
.fd = wlt->fd,
.fd = wlt->fd,
.fid = FID,
.cdw11 = we->dword,
.uuidx = wlt->uuid_index,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
};
return nvme_set_features(&args);
}
@ -294,7 +294,18 @@ static int wltracker_show_newer_entries(struct wltracker *wlt)
__u64 timestamp = 0;
union WorkloadLogEnable workloadEnable;
int err = nvme_get_log_simple(wlt->fd, LID, sizeof(struct workloadLog), log);
struct nvme_get_log_args args = {
.lpo = 0,
.result = NULL,
.log = log,
.args_size = sizeof(args),
.fd = wlt->fd,
.uuidx = wlt->uuid_index,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.lid = LID,
.len = sizeof(*log),
};
int err = nvme_get_log(&args);
if (err > 0) {
nvme_show_status(err);
@ -303,7 +314,7 @@ static int wltracker_show_newer_entries(struct wltracker *wlt)
if (err < 0)
return err;
if (wlt->verbose)
if (nvme_cfg.verbose)
wltracker_print_header(wlt);
cnt = log->workloadLogCount;
@ -331,7 +342,7 @@ static int wltracker_show_newer_entries(struct wltracker *wlt)
// retrieve fresh timestamp to reconstruct wall time
union WorkloadLogEnable we = log->config;
if (wlt->verbose > 1) {
if (nvme_cfg.verbose > 1) {
printf("Temporarily enabling tracker to find current timestamp\n");
printf("Original config value: 0x%08x\n", we.dword);
}
@ -339,7 +350,7 @@ static int wltracker_show_newer_entries(struct wltracker *wlt)
we.triggerEnable = false;
we.sampleTime = 1;
if (wlt->verbose > 1)
if (nvme_cfg.verbose > 1)
printf("Modified config value: 0x%08x\n", we.dword);
err = wltracker_config(wlt, &we);
@ -357,7 +368,7 @@ static int wltracker_show_newer_entries(struct wltracker *wlt)
we = log->config;
we.triggerEnable = false;
err = wltracker_config(wlt, &we);
if (wlt->verbose > 1)
if (nvme_cfg.verbose > 1)
printf("Restored config value: 0x%08x\n",
we.dword);
}
@ -395,7 +406,7 @@ static int wltracker_show_newer_entries(struct wltracker *wlt)
(uint64_t)(epoch_ts_us % 1000000ULL));
}
if (wlt->verbose > 1)
if (nvme_cfg.verbose > 1)
printf("%-*i", (int)sizeof("entry#"), i);
printf("\n");
@ -431,7 +442,7 @@ static int wltracker_show_newer_entries(struct wltracker *wlt)
void wltracker_run_time_update(struct wltracker *wlt)
{
wlt->run_time_us = micros() - wlt->start_time_us;
if (wlt->verbose > 0)
if (nvme_cfg.verbose > 0)
printf("run_time: %lluus\n", wlt->run_time_us);
}
@ -527,6 +538,7 @@ int sldgm_get_workload_tracker(int argc, char **argv, struct command *cmd, struc
join_options(sample_options, samplet, ARRAY_SIZE(samplet));
OPT_ARGS(opts) = {
OPT_BYTE("uuid-index", 'U', &wlt.uuid_index, "specify uuid index"),
OPT_FLAG("enable", 'e', &cfg.enable, "tracker enable"),
OPT_FLAG("disable", 'd', &cfg.disable, "tracker disable"),
OPT_STRING("sample-time", 's', sample_options, &cfg.sample_time, sample_interval),
@ -542,7 +554,7 @@ int sldgm_get_workload_tracker(int argc, char **argv, struct command *cmd, struc
"Trigger on delta to stop sampling"),
OPT_FLAG("trigger-on-latency", 'L', &cfg.trigger_on_latency,
"Use latency tracker to trigger stop sampling"),
OPT_INCR("verbose", 'v', &wlt.verbose, "Increase logging verbosity"),
OPT_INCR("verbose", 'v', &nvme_cfg.verbose, "Increase logging verbosity"),
OPT_END()
};
@ -550,6 +562,11 @@ int sldgm_get_workload_tracker(int argc, char **argv, struct command *cmd, struc
if (err)
return err;
if (wlt.uuid_index > 127) {
nvme_show_error("invalid uuid index param: %u", wlt.uuid_index);
return -1;
}
wlt.fd = dev_fd(dev);
if ((cfg.flush_frequency < 1) || (cfg.flush_frequency > MAX_WORKLOAD_LOG_ENTRIES)) {
@ -598,8 +615,15 @@ int sldgm_get_workload_tracker(int argc, char **argv, struct command *cmd, struc
we.triggerEnable = true;
we.triggerDelta = cfg.trigger_on_delta;
we.triggerSynchronous = !cfg.trigger_on_latency;
err = nvme_set_features_data(wlt.fd, 0xf5, 0, cfg.trigger_treshold, 0, 0, NULL,
NULL);
struct nvme_set_features_args args = {
.args_size = sizeof(args),
.fd = wlt.fd,
.fid = 0xf5,
.cdw11 = cfg.trigger_treshold,
.uuidx = wlt.uuid_index,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
};
err = nvme_set_features(&args);
if (err < 0) {
nvme_show_error("Trigger Threshold set-feature: %s", nvme_strerror(errno));
return err;
@ -651,7 +675,7 @@ int sldgm_get_workload_tracker(int argc, char **argv, struct command *cmd, struc
if (interval > elapsed) {
__u64 period_us = min(next_sample_us - wlt.run_time_us,
stop_time_us - wlt.run_time_us);
if (wlt.verbose > 1)
if (nvme_cfg.verbose > 1)
printf("Sleeping %lluus..\n", period_us);
usleep(period_us);
wltracker_run_time_update(&wlt);
@ -666,7 +690,7 @@ int sldgm_get_workload_tracker(int argc, char **argv, struct command *cmd, struc
if (cfg.disable) {
union WorkloadLogEnable we2 = wlt.workload_log.config;
if (wlt.verbose > 1)
if (nvme_cfg.verbose > 1)
printf("Original config value: 0x%08x\n", we2.dword);
we2.trackerEnable = false;
@ -679,7 +703,7 @@ int sldgm_get_workload_tracker(int argc, char **argv, struct command *cmd, struc
nvme_show_status(err);
return err;
}
if (wlt.verbose > 1)
if (nvme_cfg.verbose > 1)
printf("Modified config value: 0x%08x\n", we2.dword);
printf("Tracker disabled\n");
return 0;

View file

@ -524,24 +524,16 @@ enum NVME_FEATURE_IDENTIFIERS {
};
/* WDC UUID value */
const uint8_t WDC_UUID[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0xb9, 0x8c, 0x52, 0x0c, 0x4c,
0x5a, 0x15, 0xab, 0xe6, 0x33, 0x29, 0x9a, 0x70, 0xdf, 0xd0
static const __u8 WDC_UUID[NVME_UUID_LEN] = {
0x2d, 0xb9, 0x8c, 0x52, 0x0c, 0x4c, 0x5a, 0x15,
0xab, 0xe6, 0x33, 0x29, 0x9a, 0x70, 0xdf, 0xd0
};
/* WDC_UUID value for SN640_3 devices */
const uint8_t WDC_UUID_SN640_3[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22
};
/* UUID field with value of 0 indicates end of UUID List*/
const uint8_t UUID_END[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
static const __u8 WDC_UUID_SN640_3[NVME_UUID_LEN] = {
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22
};
enum WDC_DRIVE_ESSENTIAL_TYPE {
@ -930,20 +922,24 @@ struct __packed feature_latency_monitor {
};
static int wdc_get_serial_name(struct nvme_dev *dev, char *file, size_t len, const char *suffix);
static int wdc_create_log_file(char *file, __u8 *drive_log_data, __u32 drive_log_length);
static int wdc_create_log_file(const char *file, const __u8 *drive_log_data,
__u32 drive_log_length);
static int wdc_do_clear_dump(struct nvme_dev *dev, __u8 opcode, __u32 cdw12);
static int wdc_do_dump(struct nvme_dev *dev, __u32 opcode, __u32 data_len, __u32 cdw12, char *file,
__u32 xfer_size);
static int wdc_do_dump(struct nvme_dev *dev, __u32 opcode, __u32 data_len, __u32 cdw12,
const char *file, __u32 xfer_size);
static int wdc_do_crash_dump(struct nvme_dev *dev, char *file, int type);
static int wdc_crash_dump(struct nvme_dev *dev, char *file, int type);
static int wdc_crash_dump(struct nvme_dev *dev, const char *file, int type);
static int wdc_get_crash_dump(int argc, char **argv, struct command *command,
struct plugin *plugin);
static int wdc_do_drive_log(struct nvme_dev *dev, char *file);
static int wdc_do_drive_log(struct nvme_dev *dev, const char *file);
static int wdc_drive_log(int argc, char **argv, struct command *command, struct plugin *plugin);
static const char *wdc_purge_mon_status_to_string(__u32 status);
static int wdc_purge(int argc, char **argv, struct command *command, struct plugin *plugin);
static int wdc_purge_monitor(int argc, char **argv, struct command *command, struct plugin *plugin);
static bool wdc_nvme_check_supported_log_page(nvme_root_t r, struct nvme_dev *dev, __u8 log_id);
static bool wdc_nvme_check_supported_log_page(nvme_root_t r,
struct nvme_dev *dev,
__u8 log_id,
__u8 uuid_index);
static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct command *command,
struct plugin *plugin);
static int wdc_do_drive_essentials(nvme_root_t r, struct nvme_dev *dev, char *dir, char *key);
@ -959,7 +955,7 @@ static int wdc_namespace_resize(int argc, char **argv, struct command *command,
static int wdc_do_namespace_resize(struct nvme_dev *dev, __u32 nsid, __u32 op_option);
static int wdc_reason_identifier(int argc, char **argv, struct command *command,
struct plugin *plugin);
static int wdc_do_get_reason_id(struct nvme_dev *dev, char *file, int log_id);
static int wdc_do_get_reason_id(struct nvme_dev *dev, const char *file, int log_id);
static int wdc_save_reason_id(struct nvme_dev *dev, __u8 *rsn_ident, int size);
static int wdc_clear_reason_id(struct nvme_dev *dev);
static int wdc_log_page_directory(int argc, char **argv, struct command *command,
@ -1580,6 +1576,11 @@ static bool wdc_is_sn650_e1l(__u32 device_id)
return false;
}
static bool wdc_is_zn350(__u32 device_id)
{
return (device_id == WDC_NVME_ZN350_DEV_ID ||
device_id == WDC_NVME_ZN350_DEV_ID_1);
}
static bool needs_c2_log_page_check(__u32 device_id)
{
if ((wdc_is_sn640(device_id)) ||
@ -1699,12 +1700,12 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev)
/* verify the 0xCA log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE))
WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, 0))
capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE;
/* verify the 0xC1 log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_NVME_ADD_LOG_OPCODE))
WDC_NVME_ADD_LOG_OPCODE, 0))
capabilities |= WDC_DRIVE_CAP_C1_LOG_PAGE;
break;
@ -1722,12 +1723,12 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev)
WDC_DRIVE_CAP_RESIZE | WDC_DRIVE_CAP_CLEAR_PCIE);
/* verify the 0xCA log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE))
WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, 0))
capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE;
/* verify the 0xD0 log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_NVME_GET_VU_SMART_LOG_OPCODE))
WDC_NVME_GET_VU_SMART_LOG_OPCODE, 0))
capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE;
break;
@ -1741,7 +1742,7 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev)
case WDC_NVME_SN660_DEV_ID:
/* verify the 0xC0 log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID)
WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID, 0)
== true) {
capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE;
}
@ -1754,32 +1755,32 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev)
/* verify the 0xC1 (OCP Error Recovery) log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_ERROR_REC_LOG_ID))
WDC_ERROR_REC_LOG_ID, 0))
capabilities |= WDC_DRIVE_CAP_OCP_C1_LOG_PAGE;
/* verify the 0xC3 (OCP Latency Monitor) log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_LATENCY_MON_LOG_ID))
WDC_LATENCY_MON_LOG_ID, 0))
capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE;
/* verify the 0xC4 (OCP Device Capabilities) log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_DEV_CAP_LOG_ID))
WDC_DEV_CAP_LOG_ID, 0))
capabilities |= WDC_DRIVE_CAP_OCP_C4_LOG_PAGE;
/* verify the 0xC5 (OCP Unsupported Requirements) log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_UNSUPPORTED_REQS_LOG_ID))
WDC_UNSUPPORTED_REQS_LOG_ID, 0))
capabilities |= WDC_DRIVE_CAP_OCP_C5_LOG_PAGE;
/* verify the 0xCA log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE))
WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, 0))
capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE;
/* verify the 0xD0 log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_NVME_GET_VU_SMART_LOG_OPCODE))
WDC_NVME_GET_VU_SMART_LOG_OPCODE, 0))
capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE;
cust_id = wdc_get_fw_cust_id(r, dev);
@ -1802,7 +1803,7 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev)
case WDC_NVME_SN860_DEV_ID:
/* verify the 0xC0 log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_NVME_GET_EOL_STATUS_LOG_OPCODE))
WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, 0))
capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE;
fallthrough;
case WDC_NVME_ZN540_DEV_ID:
@ -1816,12 +1817,12 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev)
/* verify the 0xCA log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE))
WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, 0))
capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE;
/* verify the 0xD0 log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_NVME_GET_VU_SMART_LOG_OPCODE))
WDC_NVME_GET_VU_SMART_LOG_OPCODE, 0))
capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE;
break;
@ -1835,23 +1836,27 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev)
case WDC_NVME_SN550_DEV_ID:
/* verify the 0xC0 log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID))
WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID, 0))
capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE;
/* verify the 0xC1 (OCP Error Recovery) log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev, WDC_ERROR_REC_LOG_ID))
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_ERROR_REC_LOG_ID, 0))
capabilities |= WDC_DRIVE_CAP_OCP_C1_LOG_PAGE;
/* verify the 0xC3 (OCP Latency Monitor) log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev, WDC_LATENCY_MON_LOG_ID))
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_LATENCY_MON_LOG_ID, 0))
capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE;
/* verify the 0xC4 (OCP Device Capabilities) log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev, WDC_DEV_CAP_LOG_ID))
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_DEV_CAP_LOG_ID, 0))
capabilities |= WDC_DRIVE_CAP_OCP_C4_LOG_PAGE;
/* verify the 0xC5 (OCP Unsupported Requirements) log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev, WDC_UNSUPPORTED_REQS_LOG_ID))
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_UNSUPPORTED_REQS_LOG_ID, 0))
capabilities |= WDC_DRIVE_CAP_OCP_C5_LOG_PAGE;
capabilities |= (WDC_DRIVE_CAP_CAP_DIAG | WDC_DRIVE_CAP_INTERNAL_LOG |
@ -2050,11 +2055,13 @@ static __u64 wdc_get_enc_drive_capabilities(nvme_root_t r,
WDC_DRIVE_CAP_DRIVE_LOG | WDC_DRIVE_CAP_CRASH_DUMP | WDC_DRIVE_CAP_PFAIL_DUMP);
/* verify the 0xCA log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true)
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, 0) == true)
capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE;
/* verify the 0xC1 log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_ADD_LOG_OPCODE) == true)
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_NVME_ADD_LOG_OPCODE, 0) == true)
capabilities |= WDC_DRIVE_CAP_C1_LOG_PAGE;
break;
case WDC_NVME_VID_2:
@ -2063,19 +2070,23 @@ static __u64 wdc_get_enc_drive_capabilities(nvme_root_t r,
WDC_DRIVE_CAP_RESIZE);
/* verify the 0xC3 log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev, WDC_LATENCY_MON_LOG_ID) == true)
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_LATENCY_MON_LOG_ID, 0) == true)
capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE;
/* verify the 0xCB log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID) == true)
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID, 0) == true)
capabilities |= WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY;
/* verify the 0xCA log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true)
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, 0) == true)
capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE;
/* verify the 0xD0 log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true)
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_NVME_GET_VU_SMART_LOG_OPCODE, 0) == true)
capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE;
cust_id = wdc_get_fw_cust_id(r, dev);
@ -2138,8 +2149,8 @@ static int wdc_get_serial_name(struct nvme_dev *dev, char *file, size_t len,
return 0;
}
static int wdc_create_log_file(char *file, __u8 *drive_log_data,
__u32 drive_log_length)
static int wdc_create_log_file(const char *file, const __u8 *drive_log_data,
__u32 drive_log_length)
{
int fd;
int ret;
@ -2655,12 +2666,12 @@ static bool get_dev_mgment_data(nvme_root_t r, struct nvme_dev *dev,
void **data)
{
bool found = false;
*data = NULL;
__u32 device_id = 0, vendor_id = 0;
bool uuid_present = false;
int index = 0, uuid_index = 0;
int uuid_index = 0;
struct nvme_id_uuid_list uuid_list;
*data = NULL;
/* The wdc_get_pci_ids function could fail when drives are connected
* via a PCIe switch. Therefore, the return code is intentionally
* being ignored. The device_id and vendor_id variables have been
@ -2669,45 +2680,22 @@ static bool get_dev_mgment_data(nvme_root_t r, struct nvme_dev *dev,
*/
wdc_get_pci_ids(r, dev, &device_id, &vendor_id);
typedef struct nvme_id_uuid_list_entry *uuid_list_entry;
memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
if (wdc_CheckUuidListSupport(dev, &uuid_list)) {
uuid_list_entry uuid_list_entry_ptr = (uuid_list_entry)&uuid_list.entry[0];
uuid_index = nvme_uuid_find(&uuid_list, WDC_UUID);
if (uuid_index < 0 && wdc_is_sn640_3(device_id))
uuid_index = nvme_uuid_find(&uuid_list, WDC_UUID_SN640_3);
while (index <= NVME_ID_UUID_LIST_MAX &&
!wdc_UuidEqual(uuid_list_entry_ptr, (uuid_list_entry)UUID_END)) {
if (wdc_UuidEqual(uuid_list_entry_ptr,
(uuid_list_entry)WDC_UUID)) {
uuid_present = true;
break;
} else if (wdc_UuidEqual(uuid_list_entry_ptr,
(uuid_list_entry)WDC_UUID_SN640_3) &&
wdc_is_sn640_3(device_id)) {
uuid_present = true;
break;
}
index++;
uuid_list_entry_ptr = (uuid_list_entry)&uuid_list.entry[index];
}
if (uuid_present)
uuid_index = index + 1;
}
if (uuid_present) {
/* use the uuid index found above */
found = get_dev_mgmt_log_page_data(dev, data, uuid_index);
} else {
if (!uuid_index && needs_c2_log_page_check(device_id)) {
/* In certain devices that don't support UUID lists, there are multiple
* definitions of the C2 logpage. In those cases, the code
* needs to try two UUID indexes and use an identification algorithm
* to determine which is returning the correct log page data.
*/
uuid_index = 1;
}
if (uuid_index > 0)
found = get_dev_mgmt_log_page_data(dev, data, uuid_index);
} else if (needs_c2_log_page_check(device_id)) {
/* In certain devices that don't support UUID lists, there are multiple
* definitions of the C2 logpage. In those cases, the code
* needs to try two UUID indexes and use an identification algorithm
* to determine which is returning the correct log page data.
*/
uuid_index = 1;
found = get_dev_mgmt_log_page_data(dev, data, uuid_index);
if (!found) {
@ -2727,14 +2715,13 @@ static bool get_dev_mgment_cbs_data(nvme_root_t r, struct nvme_dev *dev,
__u8 log_id, void **cbs_data)
{
bool found = false;
__u8 uuid_ix = 0;
__u8 lid = 0;
*cbs_data = NULL;
__u32 device_id = 0, vendor_id = 0;
bool uuid_present = false;
int index = 0, uuid_index = 0;
int uuid_index = 0;
struct nvme_id_uuid_list uuid_list;
*cbs_data = NULL;
/* The wdc_get_pci_ids function could fail when drives are connected
* via a PCIe switch. Therefore, the return code is intentionally
* being ignored. The device_id and vendor_id variables have been
@ -2745,93 +2732,129 @@ static bool get_dev_mgment_cbs_data(nvme_root_t r, struct nvme_dev *dev,
lid = WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID;
typedef struct nvme_id_uuid_list_entry *uuid_list_entry;
memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
if (wdc_CheckUuidListSupport(dev, &uuid_list)) {
uuid_list_entry uuid_list_entry_ptr = (uuid_list_entry)&uuid_list.entry[0];
uuid_index = nvme_uuid_find(&uuid_list, WDC_UUID);
if (uuid_index < 0 && wdc_is_sn640_3(device_id))
uuid_index = nvme_uuid_find(&uuid_list, WDC_UUID_SN640_3);
while (index <= NVME_ID_UUID_LIST_MAX &&
!wdc_UuidEqual(uuid_list_entry_ptr, (uuid_list_entry)UUID_END)) {
if (uuid_index < 0)
found = get_dev_mgmt_log_page_lid_data(dev, cbs_data, lid,
log_id, uuid_index);
if (wdc_UuidEqual(uuid_list_entry_ptr,
(uuid_list_entry)WDC_UUID)) {
uuid_present = true;
break;
} else if (wdc_UuidEqual(uuid_list_entry_ptr,
(uuid_list_entry)WDC_UUID_SN640_3) &&
wdc_is_sn640_3(device_id)) {
uuid_present = true;
break;
}
index++;
uuid_list_entry_ptr = (uuid_list_entry)&uuid_list.entry[index];
}
if (uuid_present)
uuid_index = index + 1;
}
if (uuid_present) {
/* use the uuid index found above */
found = get_dev_mgmt_log_page_lid_data(dev, cbs_data, lid, log_id, uuid_index);
} else if (device_id == WDC_NVME_ZN350_DEV_ID || device_id == WDC_NVME_ZN350_DEV_ID_1) {
} else if (wdc_is_zn350(device_id)) {
uuid_index = 0;
found = get_dev_mgmt_log_page_lid_data(dev, cbs_data, lid, log_id, uuid_index);
} else {
if (!uuid_index && needs_c2_log_page_check(device_id)) {
/* In certain devices that don't support UUID lists, there are multiple
* definitions of the C2 logpage. In those cases, the code
* needs to try two UUID indexes and use an identification algorithm
* to determine which is returning the correct log page data.
*/
uuid_ix = 1;
}
found = get_dev_mgmt_log_page_lid_data(dev, cbs_data, lid, log_id, uuid_ix);
} else if (needs_c2_log_page_check(device_id)) {
/* In certain devices that don't support UUID lists, there are multiple
* definitions of the C2 logpage. In those cases, the code
* needs to try two UUID indexes and use an identification algorithm
* to determine which is returning the correct log page data.
*/
uuid_index = 1;
found = get_dev_mgmt_log_page_lid_data(dev, cbs_data, lid, log_id, uuid_index);
if (!found) {
/* not found with uuid = 1 try with uuid = 0 */
uuid_ix = 0;
uuid_index = 0;
fprintf(stderr, "Not found, requesting log page with uuid_index %d\n",
uuid_index);
found = get_dev_mgmt_log_page_lid_data(dev, cbs_data, lid, log_id, uuid_ix);
found = get_dev_mgmt_log_page_lid_data(dev, cbs_data, lid, log_id,
uuid_index);
}
}
return found;
}
static bool wdc_nvme_check_supported_log_page(nvme_root_t r, struct nvme_dev *dev, __u8 log_id)
static int wdc_get_supported_log_pages(struct nvme_dev *dev,
struct nvme_supported_log_pages *supported,
int uuid_index)
{
memset(supported, 0, sizeof(*supported));
struct nvme_get_log_args args = {
.lpo = 0,
.result = NULL,
.log = supported,
.args_size = sizeof(args),
.fd = dev_fd(dev),
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.lid = NVME_LOG_LID_SUPPORTED_LOG_PAGES,
.len = sizeof(*supported),
.nsid = NVME_NSID_ALL,
.csi = NVME_CSI_NVM,
.lsi = NVME_LOG_LSI_NONE,
.lsp = 0,
.uuidx = uuid_index,
.rae = false,
.ot = false,
};
return nvme_get_log(&args);
}
static bool wdc_nvme_check_supported_log_page(nvme_root_t r,
struct nvme_dev *dev,
__u8 log_id,
__u8 uuid_index)
{
int i;
bool found = false;
int err = -1;
struct wdc_c2_cbs_data *cbs_data = NULL;
if (get_dev_mgment_cbs_data(r, dev, WDC_C2_LOG_PAGES_SUPPORTED_ID, (void *)&cbs_data)) {
if (cbs_data) {
for (i = 0; i < le32_to_cpu(cbs_data->length); i++) {
if (log_id == cbs_data->data[i]) {
found = true;
break;
_cleanup_free_ struct nvme_supported_log_pages *supports = NULL;
/* Check log page id 0 (supported log pages) first */
supports = nvme_alloc(sizeof(*supports));
if (!supports)
return -ENOMEM;
err = wdc_get_supported_log_pages(dev,
supports,
uuid_index);
if (!err) {
/* Check support log page list for support */
if (supports->lid_support[log_id])
/* Support for Log Page found in supported log pages */
found = true;
}
/* if not found in the supported log pages (log id 0),
* check the WDC C2 log page
*/
if (!found) {
if (get_dev_mgment_cbs_data(r,
dev,
WDC_C2_LOG_PAGES_SUPPORTED_ID,
(void *)&cbs_data)) {
if (cbs_data) {
for (i = 0; i < le32_to_cpu(cbs_data->length); i++) {
if (log_id == cbs_data->data[i]) {
found = true;
break;
}
}
}
#ifdef WDC_NVME_CLI_DEBUG
if (!found) {
fprintf(stderr, "ERROR: WDC: Log Page 0x%x not supported\n", log_id);
fprintf(stderr, "WDC: Supported Log Pages:\n");
/* print the supported pages */
d((__u8 *)cbs_data->data, le32_to_cpu(cbs_data->length), 16, 1);
}
if (!found) {
fprintf(stderr, "ERROR: WDC: Log Page 0x%x not supported\n",
log_id);
fprintf(stderr, "WDC: Supported Log Pages:\n");
/* print the supported pages */
d((__u8 *)cbs_data->data, le32_to_cpu(cbs_data->length),
16, 1);
}
#endif
free(cbs_data);
free(cbs_data);
} else {
fprintf(stderr, "ERROR: WDC: cbs_data ptr = NULL\n");
}
} else {
fprintf(stderr, "ERROR: WDC: cbs_data ptr = NULL\n");
fprintf(stderr, "ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found\n",
WDC_C2_LOG_PAGES_SUPPORTED_ID);
}
} else {
fprintf(stderr, "ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found\n",
WDC_C2_LOG_PAGES_SUPPORTED_ID);
}
return found;
@ -2997,7 +3020,7 @@ static __u32 wdc_dump_dui_data_v2(int fd, __u32 dataLen, __u64 offset, __u8 *dum
}
static int wdc_do_dump(struct nvme_dev *dev, __u32 opcode, __u32 data_len,
__u32 cdw12, char *file, __u32 xfer_size)
__u32 cdw12, const char *file, __u32 xfer_size)
{
int ret = 0;
__u8 *dump_data;
@ -3056,7 +3079,7 @@ static int wdc_do_dump(struct nvme_dev *dev, __u32 opcode, __u32 data_len,
}
static int wdc_do_dump_e6(int fd, __u32 opcode, __u32 data_len,
__u32 cdw12, char *file, __u32 xfer_size, __u8 *log_hdr)
__u32 cdw12, char *file, __u32 xfer_size, __u8 *log_hdr)
{
int ret = 0;
__u8 *dump_data;
@ -3130,8 +3153,8 @@ static int wdc_do_dump_e6(int fd, __u32 opcode, __u32 data_len,
return ret;
}
static int wdc_do_cap_telemetry_log(struct nvme_dev *dev, char *file,
__u32 bs, int type, int data_area)
static int wdc_do_cap_telemetry_log(struct nvme_dev *dev, const char *file,
__u32 bs, int type, int data_area)
{
struct nvme_telemetry_log *log;
size_t full_size = 0;
@ -3773,9 +3796,9 @@ static int wdc_cap_diag(int argc, char **argv, struct command *command,
struct plugin *plugin)
{
nvme_root_t r;
char *desc = "Capture Diagnostics Log.";
char *file = "Output file pathname.";
char *size = "Data retrieval transfer size.";
const char *desc = "Capture Diagnostics Log.";
const char *file = "Output file pathname.";
const char *size = "Data retrieval transfer size.";
__u64 capabilities = 0;
char f[PATH_MAX] = {0};
struct nvme_dev *dev;
@ -4066,7 +4089,7 @@ free_buf:
return ret;
}
static int dump_internal_logs(struct nvme_dev *dev, char *dir_name, int verbose)
static int dump_internal_logs(struct nvme_dev *dev, const char *dir_name, int verbose)
{
char file_path[PATH_MAX];
void *telemetry_log;
@ -4165,14 +4188,17 @@ free_mem:
static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command,
struct plugin *plugin)
{
char *desc = "Internal Firmware Log.";
char *file = "Output file pathname.";
char *size = "Data retrieval transfer size.";
char *data_area = "Data area to retrieve up to. Currently only supported on the SN340, SN640, SN730, and SN840 devices.";
char *file_size = "Output file size. Currently only supported on the SN340 device.";
char *offset = "Output file data offset. Currently only supported on the SN340 device.";
char *type = "Telemetry type - NONE, HOST, or CONTROLLER. Currently only supported on the SN530, SN640, SN730, SN740, SN810, SN840 and ZN350 devices.";
char *verbose = "Display more debug messages.";
const char *desc = "Internal Firmware Log.";
const char *file = "Output file pathname.";
const char *size = "Data retrieval transfer size.";
const char *data_area =
"Data area to retrieve up to. Currently only supported on the SN340, SN640, SN730, and SN840 devices.";
const char *file_size = "Output file size. Currently only supported on the SN340 device.";
const char *offset =
"Output file data offset. Currently only supported on the SN340 device.";
const char *type =
"Telemetry type - NONE, HOST, or CONTROLLER Currently only supported on the SN530, SN640, SN730, SN740, SN810, SN840 and ZN350 devices.";
const char *verbose = "Display more debug messages.";
char f[PATH_MAX] = {0};
char fb[PATH_MAX/2] = {0};
char fileSuffix[PATH_MAX] = {0};
@ -4502,7 +4528,7 @@ static int wdc_do_crash_dump(struct nvme_dev *dev, char *file, int type)
return ret;
}
static int wdc_crash_dump(struct nvme_dev *dev, char *file, int type)
static int wdc_crash_dump(struct nvme_dev *dev, const char *file, int type)
{
char f[PATH_MAX] = {0};
const char *dump_type;
@ -4524,7 +4550,7 @@ static int wdc_crash_dump(struct nvme_dev *dev, char *file, int type)
return ret;
}
static int wdc_do_drive_log(struct nvme_dev *dev, char *file)
static int wdc_do_drive_log(struct nvme_dev *dev, const char *file)
{
int ret;
__u8 *drive_log_data;
@ -4669,8 +4695,8 @@ static int wdc_get_crash_dump(int argc, char **argv, struct command *command,
static int wdc_get_pfail_dump(int argc, char **argv, struct command *command,
struct plugin *plugin)
{
char *desc = "Get Pfail Crash Dump.";
char *file = "Output file pathname.";
const char *desc = "Get Pfail Crash Dump.";
const char *file = "Output file pathname.";
__u64 capabilities = 0;
struct nvme_dev *dev;
struct config {
@ -5108,7 +5134,7 @@ static void wdc_print_latency_monitor_log_json(struct wdc_ssd_latency_monitor_lo
{
int i, j;
char buf[128];
char *operation[3] = {"Read", "Write", "Trim"};
const char *operation[3] = {"Read", "Write", "Trim"};
struct json_object *root = json_create_object();
json_object_add_value_int(root, "Feature Status", log_data->feature_status);
@ -5348,9 +5374,9 @@ static void wdc_print_unsupported_reqs_log_json(struct wdc_ocp_C5_unsupported_re
json_object_add_value_int(root, "Number Unsupported Req IDs", le16_to_cpu(log_data->unsupported_count));
char unsup_req_list_str[40];
char unsup_req_list_str[41];
memset((void *)unsup_req_list_str, 0, 40);
memset((void *)unsup_req_list_str, 0, 41);
for (j = 0; j < le16_to_cpu(log_data->unsupported_count); j++) {
sprintf((char *)unsup_req_list_str, "Unsupported Requirement List %d", j);
json_object_add_value_string(root, unsup_req_list_str, (char *)log_data->unsupported_req_list[j]);
@ -5931,7 +5957,7 @@ static void wdc_print_fw_act_history_log_normal(__u8 *data, int num_entries,
__u16 oldestEntryIdx = 0, entryIdx = 0;
uint64_t timestamp;
__u64 timestamp_sec;
char *null_fw = "--------";
const char *null_fw = "--------";
memset((void *)time_str, '\0', 100);
@ -7504,7 +7530,8 @@ static int wdc_get_ca_log_page(nvme_root_t r, struct nvme_dev *dev, char *format
}
/* verify the 0xCA log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == false) {
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, 0) == false) {
fprintf(stderr, "ERROR: WDC: 0xCA Log Page not supported\n");
return -1;
}
@ -7924,7 +7951,9 @@ static int wdc_get_ocp_c5_log_page(nvme_root_t r, struct nvme_dev *dev, char *fo
/* check log page version */
if (log_data->log_page_version != WDC_UNSUPPORTED_REQS_LOG_VERSION) {
fprintf(stderr, "ERROR: WDC: invalid unsupported requirements log version - %d\n", log_data->log_page_version);
fprintf(stderr, "ERROR: WDC: invalid 0xC5 log page version\n");
fprintf(stderr, "ERROR: WDC: log page version: %d\n",
log_data->log_page_version);
ret = -1;
goto out;
}
@ -7976,7 +8005,8 @@ static int wdc_get_d0_log_page(nvme_root_t r, struct nvme_dev *dev, char *format
}
/* verify the 0xD0 log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == false) {
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_NVME_GET_VU_SMART_LOG_OPCODE, 0) == false) {
fprintf(stderr, "ERROR: WDC: 0xD0 Log Page not supported\n");
return -1;
}
@ -8930,7 +8960,7 @@ static int wdc_do_clear_pcie_correctable_errors_fid(int fd)
static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct command *command,
struct plugin *plugin)
{
char *desc = "Clear PCIE Correctable Errors.";
const char *desc = "Clear PCIE Correctable Errors.";
__u64 capabilities = 0;
struct nvme_dev *dev;
nvme_root_t r;
@ -8973,9 +9003,10 @@ out:
static int wdc_drive_status(int argc, char **argv, struct command *command,
struct plugin *plugin)
{
char *desc = "Get Drive Status.";
const char *desc = "Get Drive Status.";
struct nvme_dev *dev;
int ret = 0;
int uuid_index;
nvme_root_t r;
void *dev_mng_log = NULL;
__u32 system_eol_state;
@ -8985,6 +9016,7 @@ static int wdc_drive_status(int argc, char **argv, struct command *command,
__u32 assert_status = 0xFFFFFFFF;
__u32 thermal_status = 0xFFFFFFFF;
__u64 capabilities = 0;
struct nvme_id_uuid_list uuid_list;
OPT_ARGS(opts) = {
OPT_END()
@ -9002,10 +9034,23 @@ static int wdc_drive_status(int argc, char **argv, struct command *command,
goto out;
}
uuid_index = 0;
/* Find the WDC UUID index */
memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
if (wdc_CheckUuidListSupport(dev, &uuid_list))
uuid_index = nvme_uuid_find(&uuid_list, WDC_UUID);
/* WD UUID not found, use default uuid index - 0 */
if (uuid_index < 0)
uuid_index = 0;
/* verify the 0xC2 Device Manageability log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev,
WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID) == false) {
fprintf(stderr, "ERROR: WDC: 0xC2 Log Page not supported\n");
WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID,
uuid_index) == false) {
fprintf(stderr, "ERROR: WDC: 0xC2 Log Page not supported, uuid_index: %d\n",
uuid_index);
ret = -1;
goto out;
}
@ -9101,7 +9146,7 @@ out:
static int wdc_clear_assert_dump(int argc, char **argv, struct command *command,
struct plugin *plugin)
{
char *desc = "Clear Assert Dump Present Status.";
const char *desc = "Clear Assert Dump Present Status.";
struct nvme_dev *dev;
int ret = -1;
nvme_root_t r;
@ -9168,7 +9213,8 @@ static int wdc_get_fw_act_history(nvme_root_t r, struct nvme_dev *dev,
}
/* verify the FW Activate History log page is supported */
if (!wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID)) {
if (!wdc_nvme_check_supported_log_page(r, dev,
WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID, 0)) {
fprintf(stderr, "ERROR: WDC: %d Log Page not supported\n",
WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID);
return -1;
@ -9410,7 +9456,7 @@ static int wdc_do_clear_fw_activate_history_fid(int fd)
static int wdc_clear_fw_activate_history(int argc, char **argv, struct command *command,
struct plugin *plugin)
{
char *desc = "Clear FW activate history table.";
const char *desc = "Clear FW activate history table.";
__u64 capabilities = 0;
struct nvme_dev *dev;
nvme_root_t r;
@ -9446,10 +9492,10 @@ out:
static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct command *command,
struct plugin *plugin)
{
char *desc = "Disable/Enable Controller Option of the Telemetry Log Page.";
char *disable = "Disable controller option of the telemetry log page.";
char *enable = "Enable controller option of the telemetry log page.";
char *status = "Displays the current state of the controller initiated log page.";
const char *desc = "Disable/Enable Controller Option of the Telemetry Log Page.";
const char *disable = "Disable controller option of the telemetry log page.";
const char *enable = "Enable controller option of the telemetry log page.";
const char *status = "Displays the current state of the controller initiated log page.";
__u64 capabilities = 0;
struct nvme_dev *dev;
nvme_root_t r;
@ -9838,7 +9884,8 @@ end:
return ret;
}
static int wdc_de_get_dump_trace(struct nvme_dev *dev, char *filePath, __u16 binFileNameLen, char *binFileName)
static int wdc_de_get_dump_trace(struct nvme_dev *dev, const char *filePath, __u16 binFileNameLen,
const char *binFileName)
{
int ret = WDC_STATUS_FAILURE;
__u8 *readBuffer = NULL;
@ -10247,8 +10294,8 @@ static int wdc_do_drive_essentials(nvme_root_t r, struct nvme_dev *dev,
static int wdc_drive_essentials(int argc, char **argv, struct command *command,
struct plugin *plugin)
{
char *desc = "Capture Drive Essentials.";
char *dirName = "Output directory pathname.";
const char *desc = "Capture Drive Essentials.";
const char *dirName = "Output directory pathname.";
char d[PATH_MAX] = {0};
char k[PATH_MAX] = {0};
__u64 capabilities = 0;
@ -10262,7 +10309,7 @@ static int wdc_drive_essentials(int argc, char **argv, struct command *command,
};
struct config cfg = {
.dirName = NULL,
.dirName = NULL,
};
OPT_ARGS(opts) = {
@ -10726,7 +10773,7 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command
nvme_root_t r;
__u64 capabilities = 0;
struct wdc_c2_cbs_data *cbs_data = NULL;
int i;
int i, uuid_index = 0;
__u8 log_id = 0;
__u32 device_id, read_vendor_id;
bool uuid_supported = false;
@ -10763,7 +10810,6 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command
fprintf(stderr, "ERROR: WDC: unsupported device for this command\n");
ret = -1;
} else {
memset(&uuid_list, 0, sizeof(struct nvme_id_uuid_list));
if (wdc_CheckUuidListSupport(dev, &uuid_list))
uuid_supported = true;
@ -10775,16 +10821,21 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command
ret = wdc_get_pci_ids(r, dev, &device_id, &read_vendor_id);
log_id = (device_id == WDC_NVME_ZN350_DEV_ID ||
device_id == WDC_NVME_ZN350_DEV_ID_1) ?
log_id = wdc_is_zn350(device_id) ?
WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID_C8 :
WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_ID;
if (!wdc_is_sn861(device_id)) {
if (uuid_supported)
uuid_index = nvme_uuid_find(&uuid_list, WDC_UUID);
/* WD UUID not found, use default uuid index - 0 */
if (uuid_index < 0)
uuid_index = 0;
/* verify the 0xC2 Device Manageability log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev, log_id) == false) {
fprintf(stderr,
"%s: ERROR: WDC: 0x%x Log Page not supported\n",
if (!wdc_nvme_check_supported_log_page(r, dev, log_id, uuid_index)) {
fprintf(stderr, "%s: ERROR: WDC: 0x%x Log Page not supported\n",
__func__, log_id);
ret = -1;
goto out;
@ -10881,7 +10932,7 @@ static int wdc_get_drive_reason_id(struct nvme_dev *dev, char *drive_reason_id,
int ret;
int res_len = 0;
struct nvme_id_ctrl ctrl;
char *reason_id_str = "reason_id";
const char *reason_id_str = "reason_id";
i = sizeof(ctrl.sn) - 1;
j = sizeof(ctrl.mn) - 1;
@ -11001,7 +11052,7 @@ static int wdc_dump_telemetry_hdr(struct nvme_dev *dev, int log_id, struct nvme_
return ret;
}
static int wdc_do_get_reason_id(struct nvme_dev *dev, char *file, int log_id)
static int wdc_do_get_reason_id(struct nvme_dev *dev, const char *file, int log_id)
{
int ret;
struct nvme_telemetry_log *log_hdr;
@ -12205,10 +12256,10 @@ static int wdc_cloud_boot_SSD_version(int argc, char **argv, struct command *com
static int wdc_enc_get_log(int argc, char **argv, struct command *command, struct plugin *plugin)
{
char *desc = "Get Enclosure Log.";
char *file = "Output file pathname.";
char *size = "Data retrieval transfer size.";
char *log = "Enclosure Log Page ID.";
const char *desc = "Get Enclosure Log.";
const char *file = "Output file pathname.";
const char *size = "Data retrieval transfer size.";
const char *log = "Enclosure Log Page ID.";
struct nvme_dev *dev;
FILE *output_fd;
int xfer_size = 0;
@ -12821,5 +12872,8 @@ bool run_wdc_nvme_check_supported_log_page(nvme_root_t r,
struct nvme_dev *dev,
__u8 log_id)
{
return wdc_nvme_check_supported_log_page(r, dev, log_id);
return wdc_nvme_check_supported_log_page(r,
dev,
log_id,
0);
}

View file

@ -5,7 +5,7 @@
#if !defined(WDC_NVME) || defined(CMD_HEADER_MULTI_READ)
#define WDC_NVME
#define WDC_PLUGIN_VERSION "2.12.0"
#define WDC_PLUGIN_VERSION "2.13.0"
#include "cmd.h"
PLUGIN(NAME("wdc", "Western Digital vendor specific extensions", WDC_PLUGIN_VERSION),

View file

@ -90,7 +90,7 @@ int wdc_UtilsGetTime(PUtilsTimeInfo timeInfo)
return WDC_STATUS_SUCCESS;
}
int wdc_UtilsCreateDir(char *path)
int wdc_UtilsCreateDir(const char *path)
{
int retStatus;
int status = WDC_STATUS_SUCCESS;
@ -111,7 +111,7 @@ int wdc_UtilsCreateDir(char *path)
return status;
}
int wdc_WriteToFile(char *fileName, char *buffer, unsigned int bufferLen)
int wdc_WriteToFile(const char *fileName, const char *buffer, unsigned int bufferLen)
{
int status = WDC_STATUS_SUCCESS;
FILE *file;
@ -143,7 +143,7 @@ end:
* 1 if the pcSrc string is lexically higher than pcDst or
* -1 if the pcSrc string is lexically lower than pcDst.
*/
int wdc_UtilsStrCompare(char *pcSrc, char *pcDst)
int wdc_UtilsStrCompare(const char *pcSrc, const char *pcDst)
{
while ((toupper(*pcSrc) == toupper(*pcDst)) && (*pcSrc != '\0')) {
pcSrc++;
@ -189,8 +189,3 @@ bool wdc_CheckUuidListSupport(struct nvme_dev *dev, struct nvme_id_uuid_list *uu
return false;
}
bool wdc_UuidEqual(struct nvme_id_uuid_list_entry *entry1, struct nvme_id_uuid_list_entry *entry2)
{
return !memcmp(entry1->uuid, entry2->uuid, NVME_UUID_LEN);
}

View file

@ -73,9 +73,8 @@ typedef struct _UtilsTimeInfo
int wdc_UtilsSnprintf(char *buffer, unsigned int sizeOfBuffer, const char *format, ...);
void wdc_UtilsDeleteCharFromString(char* buffer, int buffSize, char charToRemove);
int wdc_UtilsGetTime(PUtilsTimeInfo timeInfo);
int wdc_UtilsStrCompare(char *pcSrc, char *pcDst);
int wdc_UtilsCreateDir(char *path);
int wdc_WriteToFile(char *fileName, char *buffer, unsigned int bufferLen);
int wdc_UtilsStrCompare(const char *pcSrc, const char *pcDst);
int wdc_UtilsCreateDir(const char *path);
int wdc_WriteToFile(const char *fileName, const char *buffer, unsigned int bufferLen);
void wdc_StrFormat(char *formatter, size_t fmt_sz, char *tofmt, size_t tofmtsz);
bool wdc_CheckUuidListSupport(struct nvme_dev *dev, struct nvme_id_uuid_list *uuid_list);
bool wdc_UuidEqual(struct nvme_id_uuid_list_entry *entry1, struct nvme_id_uuid_list_entry *entry2);