Merging upstream version 2.14.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
0d9181726f
commit
f268303a51
572 changed files with 4636 additions and 1730 deletions
|
@ -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, ×tamp, 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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
59
plugins/mangoboost/mangoboost-nvme.c
Normal file
59
plugins/mangoboost/mangoboost-nvme.c
Normal 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);
|
||||
}
|
24
plugins/mangoboost/mangoboost-nvme.h
Normal file
24
plugins/mangoboost/mangoboost-nvme.h
Normal 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"
|
|
@ -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
|
@ -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)
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue