summaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2022-07-14 18:28:04 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2022-07-16 15:12:07 +0000
commit589986012c4b3ab68e299a2eadca18f90080113b (patch)
treef29a53b04a1950cdddae69344bccb3f0146fa728 /plugins
parentReleasing debian version 1.16-4. (diff)
downloadnvme-cli-589986012c4b3ab68e299a2eadca18f90080113b.tar.xz
nvme-cli-589986012c4b3ab68e299a2eadca18f90080113b.zip
Merging upstream version 2.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'plugins')
-rw-r--r--plugins/amzn/amzn-nvme.c8
-rw-r--r--plugins/dera/dera-nvme.c17
-rw-r--r--plugins/huawei/huawei-nvme.c22
-rw-r--r--plugins/intel/intel-nvme.c238
-rw-r--r--plugins/lnvm/lnvm-nvme.c436
-rw-r--r--plugins/lnvm/lnvm-nvme.h27
-rw-r--r--plugins/memblaze/memblaze-nvme.c225
-rw-r--r--plugins/meson.build21
-rw-r--r--plugins/micron/micron-nvme.c688
-rw-r--r--plugins/micron/micron-nvme.h7
-rw-r--r--plugins/netapp/netapp-nvme.c67
-rw-r--r--plugins/nvidia/nvidia-nvme.c8
-rw-r--r--plugins/ocp/ocp-nvme.c788
-rw-r--r--plugins/ocp/ocp-nvme.h25
-rw-r--r--plugins/scaleflux/sfx-nvme.c78
-rw-r--r--plugins/seagate/seagate-nvme.c140
-rw-r--r--plugins/shannon/shannon-nvme.c73
-rw-r--r--plugins/shannon/shannon-nvme.h8
-rw-r--r--plugins/toshiba/toshiba-nvme.c40
-rw-r--r--plugins/transcend/transcend-nvme.c10
-rw-r--r--plugins/virtium/virtium-nvme.c29
-rw-r--r--plugins/wdc/wdc-nvme.c2499
-rw-r--r--plugins/wdc/wdc-nvme.h5
-rw-r--r--plugins/ymtc/ymtc-nvme.c18
-rw-r--r--plugins/zns/zns.c461
-rw-r--r--plugins/zns/zns.h29
26 files changed, 4086 insertions, 1881 deletions
diff --git a/plugins/amzn/amzn-nvme.c b/plugins/amzn/amzn-nvme.c
index 47a2d82..cd7d555 100644
--- a/plugins/amzn/amzn-nvme.c
+++ b/plugins/amzn/amzn-nvme.c
@@ -5,17 +5,11 @@
#include <unistd.h>
#include <inttypes.h>
-#include "linux/nvme_ioctl.h"
-
#include "common.h"
#include "nvme.h"
-#include "nvme-print.h"
-#include "nvme-ioctl.h"
+#include "libnvme.h"
#include "plugin.h"
-#include "argconfig.h"
-#include "suffix.h"
-
#define CREATE_CMD
#include "amzn-nvme.h"
diff --git a/plugins/dera/dera-nvme.c b/plugins/dera/dera-nvme.c
index be78930..f36fc67 100644
--- a/plugins/dera/dera-nvme.c
+++ b/plugins/dera/dera-nvme.c
@@ -10,12 +10,10 @@
#include <sys/time.h>
#include "nvme.h"
-#include "nvme-print.h"
-#include "nvme-ioctl.h"
+#include "libnvme.h"
#include "plugin.h"
-
-#include "argconfig.h"
-#include "suffix.h"
+#include "linux/types.h"
+#include "nvme-print.h"
#define CREATE_CMD
#include "dera-nvme.h"
@@ -108,7 +106,7 @@ static int nvme_dera_get_device_status(int fd, enum dera_device_status *result)
.cdw12 = 0x104,
};
- err = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, &cmd);
+ err = nvme_submit_admin_passthru(fd, &cmd, NULL);
if (!err && result) {
*result = cmd.result;
}
@@ -131,8 +129,7 @@ static int get_status(int argc, char **argv, struct command *cmd, struct plugin
if (fd < 0)
return fd;
- err = nvme_get_log(fd, 0xffffffff, 0xc0, false, NVME_NO_LOG_LSP,
- sizeof(log), &log);
+ err = nvme_get_log_simple(fd, 0xc0, sizeof(log), &log);
if (err) {
goto exit;
}
@@ -189,7 +186,7 @@ static int get_status(int argc, char **argv, struct command *cmd, struct plugin
printf("fw_loader_version : %.*s\n", 8, log.fw_loader_version);
printf("uefi_driver_version : %.*s\n", 8, log.uefi_driver_version);
- if (log.pcie_volt_status >= 0 && log.pcie_volt_status <= sizeof(volt_status) / sizeof(const char *)){
+ if (log.pcie_volt_status <= sizeof(volt_status) / sizeof(const char *)){
printf("pcie_volt_status : %s\n", volt_status[log.pcie_volt_status]);
}
else{
@@ -205,7 +202,7 @@ static int get_status(int argc, char **argv, struct command *cmd, struct plugin
exit:
if (err > 0)
- fprintf(stderr, "\nNVMe status:%s(0x%x)\n", nvme_status_to_string(err), err);
+ nvme_show_status(err);
return err;
}
diff --git a/plugins/huawei/huawei-nvme.c b/plugins/huawei/huawei-nvme.c
index b39d861..116025b 100644
--- a/plugins/huawei/huawei-nvme.c
+++ b/plugins/huawei/huawei-nvme.c
@@ -26,16 +26,12 @@
#include <sys/stat.h>
-#include "linux/nvme_ioctl.h"
-
+#include "common.h"
#include "nvme.h"
-#include "nvme-print.h"
-#include "nvme-ioctl.h"
+#include "libnvme.h"
#include "plugin.h"
-#include "argconfig.h"
-#include "suffix.h"
-#include <sys/ioctl.h>
+#include "util/suffix.h"
#define CREATE_CMD
#include "huawei-nvme.h"
@@ -50,7 +46,7 @@
struct huawei_list_item {
char node[1024];
struct nvme_id_ctrl ctrl;
- int nsid;
+ unsigned nsid;
struct nvme_id_ns ns;
unsigned block;
char ns_name[NS_NAME_LEN];
@@ -87,8 +83,8 @@ static int huawei_get_nvme_info(int fd, struct huawei_list_item *item, const cha
}
item->huawei_device = true;
- item->nsid = nvme_get_nsid(fd);
- err = nvme_identify_ns(fd, item->nsid, 0, &item->ns);
+ err = nvme_get_nsid(fd, &item->nsid);
+ err = nvme_identify_ns(fd, item->nsid, &item->ns);
if (err)
return err;
@@ -211,7 +207,9 @@ static void huawei_print_list_head(struct huawei_list_element_len element_len)
static void huawei_print_list_item(struct huawei_list_item list_item,
struct huawei_list_element_len element_len)
{
- long long int lba = 1 << list_item.ns.lbaf[(list_item.ns.flbas & 0x0f)].ds;
+ __u8 lba_index;
+ nvme_id_ns_flbas_to_lbaf_inuse(list_item.ns.flbas, &lba_index);
+ long long int lba = 1 << list_item.ns.lbaf[lba_index].ds;
double nsze = le64_to_cpu(list_item.ns.nsze) * lba;
double nuse = le64_to_cpu(list_item.ns.nuse) * lba;
@@ -320,7 +318,7 @@ static int huawei_list(int argc, char **argv, struct command *command,
if (fmt != JSON && fmt != NORMAL)
return -EINVAL;
- n = scandir("/dev", &devices, scan_namespace_filter, alphasort);
+ n = scandir("/dev", &devices, nvme_namespace_filter, alphasort);
if (n <= 0)
return n;
diff --git a/plugins/intel/intel-nvme.c b/plugins/intel/intel-nvme.c
index aaa40ad..80d218c 100644
--- a/plugins/intel/intel-nvme.c
+++ b/plugins/intel/intel-nvme.c
@@ -5,16 +5,12 @@
#include <unistd.h>
#include <inttypes.h>
-#include "linux/nvme_ioctl.h"
-
#include "common.h"
#include "nvme.h"
-#include "nvme-print.h"
-#include "nvme-ioctl.h"
+#include "libnvme.h"
#include "plugin.h"
-
-#include "argconfig.h"
-#include "suffix.h"
+#include "linux/types.h"
+#include "nvme-print.h"
#define CREATE_CMD
#include "intel-nvme.h"
@@ -351,8 +347,8 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
struct config {
__u32 namespace_id;
- int raw_binary;
- int json;
+ bool raw_binary;
+ bool json;
};
struct config cfg = {
@@ -370,8 +366,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
if (fd < 0)
return fd;
- err = nvme_get_log(fd, cfg.namespace_id, 0xca, false,
- NVME_NO_LOG_LSP, sizeof(smart_log), &smart_log);
+ err = nvme_get_log_simple(fd, 0xca, sizeof(smart_log), &smart_log);
if (!err) {
if (cfg.json)
show_intel_smart_log_jsn(&smart_log, cfg.namespace_id, devicename);
@@ -381,8 +376,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
d_raw((unsigned char *)&smart_log, sizeof(smart_log));
}
else if (err > 0)
- fprintf(stderr, "NVMe Status:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
return err;
}
@@ -395,7 +389,7 @@ static int get_market_log(int argc, char **argv, struct command *cmd, struct plu
int err, fd;
struct config {
- int raw_binary;
+ bool raw_binary;
};
struct config cfg = {
@@ -410,16 +404,14 @@ static int get_market_log(int argc, char **argv, struct command *cmd, struct plu
if (fd < 0)
return fd;
- err = nvme_get_log(fd, NVME_NSID_ALL, 0xdd, false,
- NVME_NO_LOG_LSP, sizeof(log), log);
+ err = nvme_get_log_simple(fd, 0xdd, sizeof(log), log);
if (!err) {
if (!cfg.raw_binary)
printf("Intel Marketing Name Log:\n%s\n", log);
else
d_raw((unsigned char *)&log, sizeof(log));
} else if (err > 0)
- fprintf(stderr, "NVMe Status:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
return err;
}
@@ -457,7 +449,7 @@ static int get_temp_stats_log(int argc, char **argv, struct command *cmd, struct
const char *desc = "Get Temperature Statistics log and show it.";
const char *raw = "dump output in binary format";
struct config {
- int raw_binary;
+ bool raw_binary;
};
struct config cfg = {
@@ -472,16 +464,14 @@ static int get_temp_stats_log(int argc, char **argv, struct command *cmd, struct
if (fd < 0)
return fd;
- err = nvme_get_log(fd, NVME_NSID_ALL, 0xc5, false,
- NVME_NO_LOG_LSP, sizeof(stats), &stats);
+ err = nvme_get_log_simple(fd, 0xc5, sizeof(stats), &stats);
if (!err) {
if (!cfg.raw_binary)
show_temp_stats(&stats);
else
d_raw((unsigned char *)&stats, sizeof(stats));
} else if (err > 0)
- fprintf(stderr, "NVMe Status:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
return err;
}
@@ -497,10 +487,13 @@ struct __attribute__((__packed__)) optane_lat_stats {
__u64 data[9];
};
-#define MEDIA_MAJOR_IDX 0
-#define MEDIA_MINOR_IDX 1
-#define MEDIA_MAX_LEN 2
-#define OPTANE_V1000_BUCKET_LEN 8
+#define MEDIA_MAJOR_IDX 0
+#define MEDIA_MINOR_IDX 1
+#define MEDIA_MAX_LEN 2
+#define OPTANE_V1000_BUCKET_LEN 8
+#define OPTANE_V1000_BUCKET_LEN 8
+#define NAND_LAT_STATS_LEN 4868
+
static struct intel_lat_stats stats;
static struct optane_lat_stats v1000_stats;
@@ -529,7 +522,7 @@ enum FormatUnit {
#define US_IN_S 1000000
#define US_IN_MS 1000
-static const enum FormatUnit get_seconds_magnitude(__u32 microseconds)
+static enum FormatUnit get_seconds_magnitude(__u32 microseconds)
{
if (microseconds > US_IN_S)
return S;
@@ -539,7 +532,7 @@ static const enum FormatUnit get_seconds_magnitude(__u32 microseconds)
return US;
}
-static const float convert_seconds(__u32 microseconds)
+static float convert_seconds(__u32 microseconds)
{
float divisor = 1.0;
@@ -567,13 +560,15 @@ enum inf_bound_type {
* either of "-INF" or "+INF", respectively.
*/
static void set_unit_string(char *buffer, __u32 microseconds,
- enum FormatUnit unit, enum inf_bound_type bound_type)
+ enum FormatUnit unit,
+ enum inf_bound_type bound_type)
{
+ char *string;
+
if (bound_type != NOINF) {
- snprintf(buffer, 5, "%s", bound_type ? "+INF" : "-INF");
+ snprintf(buffer, BUFSIZE, "%s", bound_type ? "+INF" : "-INF");
return;
}
- char *string;
switch (unit) {
case US:
@@ -589,8 +584,9 @@ static void set_unit_string(char *buffer, __u32 microseconds,
string = "_s";
break;
}
- snprintf(buffer, 11, "%4.2f%s",
- convert_seconds(microseconds), string);
+
+ snprintf(buffer, BUFSIZE, "%4.2f%s", convert_seconds(microseconds),
+ string);
}
static void init_buffer(char *buffer, size_t size)
@@ -660,12 +656,11 @@ static void show_lat_stats_linear(struct intel_lat_stats *stats,
/*
* For 4.0-4.5 revision.
*/
+#define LATENCY_STATS_V4_BASE_BITS 6
+#define LATENCY_STATS_V4_BASE_VAL (1 << LATENCY_STATS_V4_BASE_BITS)
+
static int lat_stats_log_scale(int i)
{
- static const int LATENCY_STATS_V4_BASE_BITS = 6;
- static const int LATENCY_STATS_V4_BASE_VAL = (
- 1 << LATENCY_STATS_V4_BASE_BITS);
-
// if (i < 128)
if (i < (LATENCY_STATS_V4_BASE_VAL << 1))
return i;
@@ -715,8 +710,7 @@ static void json_add_bucket(struct intel_lat_stats *stats,
init_buffer(buffer, BUFSIZE);
- json_object_add_value_object(bucket_list,
- "bucket", bucket);
+ json_object_array_add(bucket_list, bucket);
json_object_add_value_int(bucket, "id", id);
set_unit_string(buffer, lower_us,
@@ -739,8 +733,7 @@ static void json_add_bucket_optane(struct json_object *bucket_list, __u32 id,
init_buffer(buffer, BUFSIZE);
- json_object_add_value_object(bucket_list,
- "bucket", bucket);
+ json_object_array_add(bucket_list, bucket);
json_object_add_value_int(bucket, "id", id);
set_unit_string(buffer, lower_us,
@@ -775,7 +768,7 @@ static void json_lat_stats_3_0(struct intel_lat_stats *stats,
int write)
{
struct json_object *root = json_create_object();
- struct json_object *bucket_list = json_create_object();
+ struct json_object *bucket_list = json_object_new_array();
lat_stats_make_json_root(root, bucket_list, write);
@@ -794,7 +787,7 @@ static void json_lat_stats_4_0(struct intel_lat_stats *stats,
int write)
{
struct json_object *root = json_create_object();
- struct json_object *bucket_list = json_create_object();
+ struct json_object *bucket_list = json_object_new_array();
lat_stats_make_json_root(root, bucket_list, write);
@@ -847,11 +840,11 @@ static void show_lat_stats_4_0(struct intel_lat_stats *stats)
}
}
-static void jason_lat_stats_v1000_0(struct optane_lat_stats *stats, int write)
+static void json_lat_stats_v1000_0(struct optane_lat_stats *stats, int write)
{
int i;
struct json_object *root = json_create_object();
- struct json_object *bucket_list = json_create_object();
+ struct json_object *bucket_list = json_object_new_array();
lat_stats_make_json_root(root, bucket_list, write);
@@ -951,7 +944,7 @@ static void json_lat_stats(int write)
case 1000:
switch (media_version[MEDIA_MINOR_IDX]) {
case 0:
- jason_lat_stats_v1000_0(&v1000_stats, write);
+ json_lat_stats_v1000_0(&v1000_stats, write);
break;
default:
printf("Unsupported minor revision (%u.%u)\n",
@@ -998,6 +991,7 @@ static void show_lat_stats(int write)
case 3:
case 4:
case 5:
+ case 6:
show_lat_stats_4_0(&stats);
break;
default:
@@ -1028,6 +1022,7 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct
{
int err, fd;
+ __u8 data[NAND_LAT_STATS_LEN];
const char *desc = "Get Intel Latency Statistics log and show it.";
const char *raw = "Dump output in binary format";
@@ -1035,9 +1030,9 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct
const char *write = "Get write statistics (read default)";
struct config {
- int raw_binary;
- int json;
- int write;
+ bool raw_binary;
+ bool json;
+ bool write;
};
struct config cfg = {
@@ -1054,10 +1049,15 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct
if (fd < 0)
return fd;
- /* Query maj and minor version first */
- err = nvme_get_log(fd, NVME_NSID_ALL, cfg.write ? 0xc2 : 0xc1,
- false, NVME_NO_LOG_LSP, sizeof(media_version),
- media_version);
+ /* For optate, latency stats are deleted every time their LID is pulled.
+ * Therefore, we query the longest lat_stats log page first.
+ */
+ err = nvme_get_log_simple(fd, cfg.write ? 0xc2 : 0xc1,
+ sizeof(data), &data);
+
+ media_version[0] = (data[1] << 8) | data[0];
+ media_version[1] = (data[3] << 8) | data[2];
+
if (err)
goto close_fd;
@@ -1065,11 +1065,23 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct
__u32 thresholds[OPTANE_V1000_BUCKET_LEN] = {0};
__u32 result;
- err = nvme_get_feature(fd, 0, 0xf7, 0, cfg.write ? 0x1 : 0x0, 0,
- sizeof(thresholds), thresholds, &result);
+ struct nvme_get_features_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .fid = 0xf7,
+ .nsid = 0,
+ .sel = 0,
+ .cdw11 = cfg.write ? 0x1 : 0x0,
+ .uuidx = 0,
+ .data_len = sizeof(thresholds),
+ .data = thresholds,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+ err = nvme_get_features(&args);
if (err) {
- fprintf(stderr, "Quering thresholds failed. NVMe Status:%s(%x)\n",
- nvme_status_to_string(err), err);
+ fprintf(stderr, "Quering thresholds failed. ");
+ nvme_show_status(err);
goto close_fd;
}
@@ -1083,13 +1095,14 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct
}
- err = nvme_get_log(fd, NVME_NSID_ALL, cfg.write ? 0xc2 : 0xc1,
- false, NVME_NO_LOG_LSP, sizeof(v1000_stats),
- &v1000_stats);
+ /* Move counter values to optate stats struct which has a
+ * smaller size
+ */
+ memcpy(&v1000_stats, (struct optane_lat_stats *)data,
+ sizeof(struct optane_lat_stats));
} else {
- err = nvme_get_log(fd, NVME_NSID_ALL, cfg.write ? 0xc2 : 0xc1,
- false, NVME_NO_LOG_LSP, sizeof(stats),
- &stats);
+ memcpy(&stats, (struct intel_lat_stats *)data,
+ sizeof(struct intel_lat_stats));
}
if (!err) {
@@ -1097,11 +1110,16 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct
json_lat_stats(cfg.write);
else if (!cfg.raw_binary)
show_lat_stats(cfg.write);
- else
- d_raw((unsigned char *)&stats, sizeof(stats));
+ else {
+ if (media_version[0] == 1000)
+ d_raw((unsigned char *)&v1000_stats,
+ sizeof(v1000_stats));
+ else
+ d_raw((unsigned char *)&stats,
+ sizeof(stats));
+ }
} else if (err > 0)
- fprintf(stderr, "NVMe Status:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
close_fd:
close(fd);
return err;
@@ -1213,7 +1231,7 @@ static int read_entire_cmd(struct nvme_passthru_cmd *cmd, int total_size,
dword_tfer = min(max_tfer, total_size);
while (total_size > 0) {
- err = nvme_submit_admin_passthru(ioctl_fd, cmd);
+ err = nvme_submit_admin_passthru(ioctl_fd, cmd, NULL);
if (err) {
fprintf(stderr,
"failed on cmd.data_len %u cmd.cdw13 %u cmd.cdw12 %x cmd.cdw10 %u err %x remaining size %d\n",
@@ -1478,8 +1496,7 @@ static int get_internal_log(int argc, char **argv, struct command *command,
err = 0;
out:
if (err > 0) {
- fprintf(stderr, "NVMe Status:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
} else if (err < 0) {
perror("intel log");
err = EIO;
@@ -1518,8 +1535,8 @@ static int enable_lat_stats_tracking(int argc, char **argv,
};
const struct argconfig_commandline_options command_line_options[] = {
- {"enable", 'e', "", CFG_NONE, &cfg.enable, no_argument, enable_desc},
- {"disable", 'd', "", CFG_NONE, &cfg.disable, no_argument, disable_desc},
+ {"enable", 'e', "", CFG_FLAG, &cfg.enable, no_argument, enable_desc},
+ {"disable", 'd', "", CFG_FLAG, &cfg.disable, no_argument, disable_desc},
{NULL}
};
@@ -1540,10 +1557,40 @@ static int enable_lat_stats_tracking(int argc, char **argv,
if (fd < 0)
return fd;
+
+ struct nvme_get_features_args args_get = {
+ .args_size = sizeof(args_get),
+ .fd = fd,
+ .fid = fid,
+ .nsid = nsid,
+ .sel = sel,
+ .cdw11 = cdw11,
+ .uuidx = 0,
+ .data_len = data_len,
+ .data = buf,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+
+ struct nvme_set_features_args args_set = {
+ .args_size = sizeof(args_set),
+ .fd = fd,
+ .fid = fid,
+ .nsid = nsid,
+ .cdw11 = option,
+ .cdw12 = cdw12,
+ .save = save,
+ .uuidx = 0,
+ .cdw15 = 0,
+ .data_len = data_len,
+ .data = buf,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+
switch (option) {
case None:
- err = nvme_get_feature(fd, nsid, fid, sel, cdw11, 0, data_len, buf,
- &result);
+ err = nvme_get_features(&args_get);
if (!err) {
printf(
"Latency Statistics Tracking (FID 0x%X) is currently (%i).\n",
@@ -1555,11 +1602,9 @@ static int enable_lat_stats_tracking(int argc, char **argv,
break;
case True:
case False:
- err = nvme_set_feature(fd, nsid, fid, option, cdw12, save, 0,
- data_len, buf, &result);
+ err = nvme_set_features(&args_set);
if (err > 0) {
- fprintf(stderr, "NVMe Status:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
} else if (err < 0) {
perror("Enable latency tracking");
fprintf(stderr, "Command failed while parsing.\n");
@@ -1590,12 +1635,12 @@ static int set_lat_stats_thresholds(int argc, char **argv,
__u32 result;
struct config {
- int write;
+ bool write;
char *bucket_thresholds;
};
struct config cfg = {
- .write = 0,
+ .write = false,
.bucket_thresholds = "",
};
@@ -1615,12 +1660,11 @@ static int set_lat_stats_thresholds(int argc, char **argv,
* valid buckets a user is allowed to modify. Read or write doesn't
* matter
*/
- err = nvme_get_log(fd, NVME_NSID_ALL, 0xc2,
- false, NVME_NO_LOG_LSP, sizeof(media_version),
- media_version);
+ err = nvme_get_log_simple(fd, 0xc2,
+ sizeof(media_version), media_version);
if (err) {
- fprintf(stderr, "Querying media version failed. NVMe Status:%s(%x)\n",
- nvme_status_to_string(err), err);
+ fprintf(stderr, "Querying media version failed. ");
+ nvme_show_status(err);
goto close_fd;
}
@@ -1635,13 +1679,25 @@ static int set_lat_stats_thresholds(int argc, char **argv,
}
- err = nvme_set_feature(fd, nsid, fid, cfg.write ? 0x1 : 0x0,
- cdw12, save, 0, OPTANE_V1000_BUCKET_LEN,
- thresholds, &result);
+ struct nvme_set_features_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .fid = fid,
+ .nsid = nsid,
+ .cdw11 = cfg.write ? 0x1 : 0x0,
+ .cdw12 = cdw12,
+ .save = save,
+ .uuidx = 0,
+ .cdw15 = 0,
+ .data_len = sizeof(thresholds),
+ .data = thresholds,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+ err = nvme_set_features(&args);
if (err > 0) {
- fprintf(stderr, "NVMe Status:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
} else if (err < 0) {
perror("Enable latency tracking");
fprintf(stderr, "Command failed while parsing.\n");
diff --git a/plugins/lnvm/lnvm-nvme.c b/plugins/lnvm/lnvm-nvme.c
deleted file mode 100644
index 3678176..0000000
--- a/plugins/lnvm/lnvm-nvme.c
+++ /dev/null
@@ -1,436 +0,0 @@
-#include <stdio.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "nvme.h"
-#include "nvme-print.h"
-#include "nvme-ioctl.h"
-#include "plugin.h"
-
-#include "nvme-lightnvm.h"
-
-#include "argconfig.h"
-#include "suffix.h"
-
-#define CREATE_CMD
-#include "lnvm-nvme.h"
-
-static int lnvm_init(int argc, char **argv, struct command *cmd, struct plugin *plugin)
-{
- const char *desc = "Initialize LightNVM device. A LightNVM/Open-Channel SSD"\
- " must have a media manager associated before it can"\
- " be exposed to the user. The default is to initialize"
- " the general media manager on top of the device.\n\n"
- "Example:"
- " lnvm-init -d nvme0n1";
- const char *devname = "identifier of desired device. e.g. nvme0n1.";
- const char *mmtype = "media manager to initialize on top of device. Default: gennvm.";
- int ret;
-
- struct config {
- char *devname;
- char *mmtype;
- };
-
- struct config cfg = {
- .devname = "",
- .mmtype = "gennvm",
- };
-
- OPT_ARGS(opts) = {
- OPT_STRING("device-name", 'd', "DEVICE", &cfg.devname, devname),
- OPT_STRING("mediamgr-name", 'm', "MM", &cfg.mmtype, mmtype),
- OPT_END()
- };
-
- ret = argconfig_parse(argc, argv, desc, opts);
- if (ret < 0)
- return ret;
-
- if (!strlen(cfg.devname)) {
- fprintf(stderr, "device name missing\n");
- return -EINVAL;
- }
-
- return lnvm_do_init(cfg.devname, cfg.mmtype);
-}
-
-static int lnvm_list(int argc, char **argv, struct command *cmd, struct plugin *plugin)
-{
- const char *desc = "List all devices registered with LightNVM.";
- int ret;
-
- OPT_ARGS(opts) = {
- OPT_END()
- };
-
- ret = argconfig_parse(argc, argv, desc, opts);
- if (ret < 0)
- return ret;
-
- return lnvm_do_list_devices();
-}
-
-static int lnvm_info(int argc, char **argv, struct command *cmd, struct plugin *plugin)
-{
- const char *desc = "Show general information and registered target types with LightNVM";
- int ret;
-
- OPT_ARGS(opts) = {
- OPT_END()
- };
-
- ret = argconfig_parse(argc, argv, desc, opts);
- if (ret < 0)
- return ret;
-
- return lnvm_do_info();
-}
-
-static int lnvm_id_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin)
-{
- const char *desc = "Send an Identify Geometry command to the "\
- "given LightNVM device, returns properties of the specified "\
- "namespace in either human-readable or binary format.";
- const char *raw_binary = "show infos in binary format";
- const char *human_readable = "show infos in readable format";
- const char *namespace_id = "identifier of desired namespace. default: 1";
- unsigned int flags = 0;
- int fd;
-
- struct config {
- __u32 namespace_id;
- int raw_binary;
- int human_readable;
- };
-
- struct config cfg = {
- .namespace_id = 1,
- };
-
- OPT_ARGS(opts) = {
- OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
- OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_binary),
- OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable),
- OPT_END()
- };
-
- fd = parse_and_open(argc, argv, desc, opts);
- if (fd < 0)
- return fd;
-
- if (cfg.human_readable)
- flags |= VERBOSE;
- else if (cfg.raw_binary)
- flags |= BINARY;
-
- return lnvm_do_id_ns(fd, cfg.namespace_id, flags);
-}
-
-static int lnvm_chunk_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
-{
- const char *desc = "Retrieve the chunk information log for the "\
- "specified given LightNVM device, returns in either "\
- "human-readable or binary format.\n"\
- "This will request Geometry first to get the "\
- "num_grp,num_pu,num_chk first to figure out the total size "\
- "of the log pages."\
- ;
- const char *output_format = "Output format: normal|binary";
- const char *human_readable = "Print normal in readable format";
- int err, fmt, fd;
- struct nvme_nvm_id20 geo;
- struct nvme_nvm_chunk_desc *chunk_log;
- __u32 nsid;
- __u32 data_len;
- unsigned int flags = 0;
-
- struct config {
- char *output_format;
- int human_readable;
- };
-
- struct config cfg = {
- .output_format = "normal",
- };
-
- OPT_ARGS(opts) = {
- OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
- OPT_FLAG("human-readable",'H', &cfg.human_readable, human_readable),
- OPT_END()
- };
-
- fd = parse_and_open(argc, argv, desc, opts);
- if (fd < 0)
- return fd;
-
- fmt = validate_output_format(cfg.output_format);
- if (fmt < 0) {
- err = fmt;
- goto close;
- }
-
- if (fmt == BINARY)
- flags |= BINARY;
- else if (cfg.human_readable)
- flags |= VERBOSE;
-
- nsid = nvme_get_nsid(fd);
-
- /*
- * It needs to figure out how many bytes will be requested by this
- * subcommand by the (num_grp * num_pu * num_chk) from the Geometry.
- */
- err = lnvm_get_identity(fd, nsid, (struct nvme_nvm_id *) &geo);
- if (err)
- goto close;
-
- data_len = (geo.num_grp * geo.num_pu * geo.num_chk) *
- sizeof(struct nvme_nvm_chunk_desc);
- chunk_log = malloc(data_len);
- if (!chunk_log) {
- fprintf(stderr, "cound not alloc for chunk log %dbytes\n",
- data_len);
- err = -ENOMEM;
- goto close;
- }
-
- err = lnvm_do_chunk_log(fd, nsid, data_len, chunk_log, flags);
- if (err)
- fprintf(stderr, "get log page for chunk information failed\n");
-
- free(chunk_log);
-close:
- close(fd);
- return err;
-}
-
-static int lnvm_create_tgt(int argc, char **argv, struct command *cmd, struct plugin *plugin)
-{
- const char *desc = "Instantiate a target on top of a LightNVM enabled device.";
- const char *devname = "identifier of desired device. e.g. nvme0n1.";
- const char *tgtname = "target name of the device to initialize. e.g. target0.";
- const char *tgttype = "identifier of target type. e.g. pblk.";
- const char *lun_begin = "Define begin of luns to use for target.";
- const char *lun_end = "Define set of luns to use for target.";
- const char *over_prov = "Define over-provision percentage for target.";
- const char *flag_factory = "Create target in factory mode";
- int flags;
- int ret;
-
- struct config {
- char *devname;
- char *tgtname;
- char *tgttype;
- __u32 lun_begin;
- __u32 lun_end;
- __u32 over_prov;
-
- /* flags */
- __u32 factory;
- };
-
- struct config cfg = {
- .devname = "",
- .tgtname = "",
- .tgttype = "",
- .lun_begin = -1,
- .lun_end = -1,
- .over_prov = -1,
- .factory = 0,
- };
-
- OPT_ARGS(opts) = {
- OPT_STRING("device-name", 'd', "DEVICE", &cfg.devname, devname),
- OPT_STRING("target-name", 'n', "TARGET", &cfg.tgtname, tgtname),
- OPT_STRING("target-type", 't', "TARGETTYPE", &cfg.tgttype, tgttype),
- OPT_UINT("lun-begin", 'b', &cfg.lun_begin, lun_begin),
- OPT_UINT("lun-end", 'e', &cfg.lun_end, lun_end),
- OPT_UINT("over-prov", 'o', &cfg.over_prov, over_prov),
- OPT_FLAG("factory", 'f', &cfg.factory, flag_factory),
- OPT_END()
- };
-
- ret = argconfig_parse(argc, argv, desc, opts);
- if (ret < 0)
- return ret;
-
- if (!strlen(cfg.devname)) {
- fprintf(stderr, "device name missing\n");
- return -EINVAL;
- }
- if (!strlen(cfg.tgtname)) {
- fprintf(stderr, "target name missing\n");
- return -EINVAL;
- }
- if (!strlen(cfg.tgttype)) {
- fprintf(stderr, "target type missing\n");
- return -EINVAL;
- }
-
- flags = 0;
- if (cfg.factory)
- flags |= NVM_TARGET_FACTORY;
-
- return lnvm_do_create_tgt(cfg.devname, cfg.tgtname, cfg.tgttype, cfg.lun_begin, cfg.lun_end, cfg.over_prov, flags);
-}
-
-static int lnvm_remove_tgt(int argc, char **argv, struct command *cmd, struct plugin *plugin)
-{
- const char *desc = "Remove an initialized LightNVM target.";
- const char *tgtname = "target name of the device to remove. e.g. target0.";
- int ret;
-
- struct config {
- char *tgtname;
- };
-
- struct config cfg = {
- .tgtname = "",
- };
-
- OPT_ARGS(opts) = {
- OPT_STRING("target-name", 'n', "TARGET", &cfg.tgtname, tgtname),
- OPT_END()
- };
-
- ret = argconfig_parse(argc, argv, desc, opts);
- if (ret < 0)
- return ret;
-
- if (!strlen(cfg.tgtname)) {
- fprintf(stderr, "target name missing\n");
- return -EINVAL;
- }
-
- return lnvm_do_remove_tgt(cfg.tgtname);
-}
-
-static int lnvm_factory_init(int argc, char **argv, struct command *cmd, struct plugin *plugin)
-{
- const char *desc = "Factory initialize a LightNVM enabled device.";
- const char *devname = "identifier of desired device. e.g. nvme0n1.";
- const char *erase_only_marked = "only erase marked blocks. default: all blocks.";
- const char *host_marks = "remove host side blocks list. default: keep.";
- const char *bb_marks = "remove grown bad blocks list. default: keep";
- int ret;
-
- struct config {
- char *devname;
- int erase_only_marked;
- int clear_host_marks;
- int clear_bb_marks;
- };
-
- struct config cfg = {
- .devname = "",
- };
-
- OPT_ARGS(opts) = {
- OPT_STRING("device-name", 'd', "DEVICE", &cfg.devname, devname),
- OPT_FLAG("erase-only-marked", 'e', &cfg.erase_only_marked, erase_only_marked),
- OPT_FLAG("clear-host-side-blks", 's', &cfg.clear_host_marks, host_marks),
- OPT_FLAG("clear-bb-blks", 'b', &cfg.clear_bb_marks, bb_marks),
- OPT_END()
- };
-
- ret = argconfig_parse(argc, argv, desc, opts);
- if (ret < 0)
- return ret;
-
- if (!strlen(cfg.devname)) {
- fprintf(stderr, "device name missing\n");
- return -EINVAL;
- }
-
- return lnvm_do_factory_init(cfg.devname, cfg.erase_only_marked,
- cfg.clear_host_marks, cfg.clear_bb_marks);
-}
-
-static int lnvm_get_bbtbl(int argc, char **argv, struct command *cmd, struct plugin *plugin)
-{
- const char *desc = "Receive bad block table from a LightNVM compatible"\
- " device.";
- const char *namespace = "(optional) desired namespace";
- const char *ch = "channel identifier";
- const char *lun = "lun identifier (within a channel)";
- const char *raw_binary = "show infos in binary format";
- unsigned int fd, flags = 0;
-
- struct config {
- __u32 namespace_id;
- __u16 lunid;
- __u16 chid;
- int raw_binary;
- };
-
- struct config cfg = {
- .namespace_id = 1,
- .lunid = 0,
- .chid = 0,
- };
-
- OPT_ARGS(opts) = {
- OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace),
- OPT_SHRT("channel-id", 'c', &cfg.chid, ch),
- OPT_SHRT("lun-id", 'l', &cfg.lunid, lun),
- OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_binary),
- OPT_END()
- };
-
- fd = parse_and_open(argc, argv, desc, opts);
-
- if (cfg.raw_binary)
- flags |= BINARY;
-
- return lnvm_do_get_bbtbl(fd, cfg.namespace_id, cfg.lunid, cfg.chid, flags);
-}
-
-static int lnvm_set_bbtbl(int argc, char **argv, struct command *cmd, struct plugin *plugin)
-{
- const char *desc = "Update bad block table on a LightNVM compatible"\
- " device.";
- const char *namespace = "(optional) desired namespace";
- const char *ch = "channel identifier";
- const char *lun = "lun identifier (within a channel)";
- const char *pln = "plane identifier (within a lun)";
- const char *blk = "block identifier (within a plane)";
- const char *value = "value to update the specific block to.";
- int fd;
-
- struct config {
- __u32 namespace_id;
- __u16 lunid;
- __u16 chid;
- __u16 plnid;
- __u16 blkid;
- __u16 value;
- };
-
- struct config cfg = {
- .namespace_id = 1,
- .lunid = 0,
- .chid = 0,
- .plnid = 0,
- .blkid = 0,
- .value = 0,
- };
-
- OPT_ARGS(opts) = {
- OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace),
- OPT_SHRT("channel-id", 'c', &cfg.chid, ch),
- OPT_SHRT("lun-id", 'l', &cfg.lunid, lun),
- OPT_SHRT("plane-id", 'p', &cfg.plnid, pln),
- OPT_SHRT("block-id", 'b', &cfg.blkid, blk),
- OPT_SHRT("value", 'v', &cfg.value, value),
- OPT_END()
- };
-
- fd = parse_and_open(argc, argv, desc, opts);
-
- printf("Updating: Ch.: %u LUN: %u Plane: %u Block: %u -> %u\n",
- cfg.chid, cfg.lunid, cfg.plnid, cfg.blkid, cfg.value);
- return lnvm_do_set_bbtbl(fd, cfg.namespace_id, cfg.chid, cfg.lunid,
- cfg.plnid, cfg.blkid, cfg.value);
-}
diff --git a/plugins/lnvm/lnvm-nvme.h b/plugins/lnvm/lnvm-nvme.h
deleted file mode 100644
index 18dffe1..0000000
--- a/plugins/lnvm/lnvm-nvme.h
+++ /dev/null
@@ -1,27 +0,0 @@
-
-#undef CMD_INC_FILE
-#define CMD_INC_FILE plugins/lnvm/lnvm-nvme
-
-#if !defined(LNVM_NVME) || defined(CMD_HEADER_MULTI_READ)
-#define LNVM_NVME
-
-#include "cmd.h"
-
-PLUGIN(NAME("lnvm", "LightNVM specific extensions", NVME_VERSION),
- COMMAND_LIST(
- ENTRY("list", "List available LightNVM devices", lnvm_list)
- ENTRY("info", "List general information and available target engines", lnvm_info)
- ENTRY("id-ns", "List geometry for LightNVM device", lnvm_id_ns, "geometry")
- ENTRY("chunk-log", "Chunk Information Log Page", lnvm_chunk_log)
- ENTRY("init", "Initialize media manager on LightNVM device", lnvm_init)
- ENTRY("create", "Create target on top of a LightNVM device", lnvm_create_tgt)
- ENTRY("remove", "Remove target from device", lnvm_remove_tgt)
- ENTRY("factory", "Reset device to factory state", lnvm_factory_init)
- ENTRY("diag-bbtbl", "Diagnose bad block table", lnvm_get_bbtbl)
- ENTRY("diag-set-bbtbl", "Update bad block table", lnvm_set_bbtbl)
- )
-);
-
-#endif
-
-#include "define_cmd.h"
diff --git a/plugins/memblaze/memblaze-nvme.c b/plugins/memblaze/memblaze-nvme.c
index e3807f1..c0f4d66 100644
--- a/plugins/memblaze/memblaze-nvme.c
+++ b/plugins/memblaze/memblaze-nvme.c
@@ -5,15 +5,11 @@
#include <unistd.h>
#include <time.h>
-#include "linux/nvme_ioctl.h"
-
#include "nvme.h"
-#include "nvme-print.h"
-#include "nvme-ioctl.h"
+#include "libnvme.h"
#include "plugin.h"
-
-#include "argconfig.h"
-#include "suffix.h"
+#include "linux/types.h"
+#include "nvme-print.h"
#define CREATE_CMD
#include "memblaze-nvme.h"
@@ -79,22 +75,19 @@ static int compare_fw_version(const char *fw1, const char *fw2)
#define STR_VER_SIZE (5)
-int getlogpage_format_type(char *fw_ver)
+int getlogpage_format_type(char *model_name)
{
- char fw_ver_local[STR_VER_SIZE];
- strncpy(fw_ver_local, fw_ver, STR_VER_SIZE);
- *(fw_ver_local + STR_VER_SIZE - 1) = '\0';
- if ( IS_RAISIN(fw_ver_local)
- || IS_KUMQUAT(fw_ver_local)
- || IS_LOQUAT(fw_ver_local)
- )
- {
- return INTEL_FORMAT;
- }
- else
+ int logpage_format_type = INTEL_FORMAT;
+ const char *boundary_model_name1 = "P"; // MEMBLAZE P7936DT0640M00
+ const char *boundary_model_name2 = "P5920"; // Use INTEL_FORMAT from Raisin P5920.
+ if (0 == strncmp(model_name, boundary_model_name1, strlen(boundary_model_name1)))
{
- return MEMBLAZE_FORMAT;
+ if (strncmp(model_name, boundary_model_name2, strlen(boundary_model_name2)) < 0)
+ {
+ logpage_format_type = MEMBLAZE_FORMAT;
+ }
}
+ return logpage_format_type;
}
static __u32 item_id_2_u32(struct nvme_memblaze_smart_log_item *item)
@@ -232,8 +225,6 @@ static void show_memblaze_smart_log_new(struct nvme_memblaze_smart_log *s,
printf("%-32s: %3d%% %s%u%s%u%s%u\n", STR17_01, *nm, STR17_03, *raw,
STR17_04, *(raw+2), STR17_05, *(raw+4));
/* 18 RAISIN_SI_VD_POWER_LOSS_PROTECTION */
- get_memblaze_new_smart_info(smart, RAISIN_SI_VD_POWER_LOSS_PROTECTION, nm, raw);
- printf("%-32s: %3d%% %"PRIu64"\n", STR18_01, *nm, int48_to_long(raw));
/* 19 RAISIN_SI_VD_READ_FAIL */
get_memblaze_new_smart_info(smart, RAISIN_SI_VD_READ_FAIL, nm, raw);
printf("%-32s: %3d%% %"PRIu64"\n", STR19_01, *nm, int48_to_long(raw));
@@ -392,7 +383,7 @@ static int show_memblaze_smart_log(int fd, __u32 nsid, const char *devname,
ctrl.fr[0], ctrl.fr[1], ctrl.fr[2], ctrl.fr[3],
ctrl.fr[4], ctrl.fr[5], ctrl.fr[6]);
- if (getlogpage_format_type(fw_ver)) // Intel Format & new format
+ if (getlogpage_format_type(ctrl.mn)) // Intel Format & new format
{
show_memblaze_smart_log_new(smart, nsid, devname);
}
@@ -419,7 +410,7 @@ int parse_params(char *str, int number, ...)
exit(EINVAL);
}
- if (isalnum(*c) == 0) {
+ if (isalnum((int)*c) == 0) {
printf("%s is not a valid number\n", c);
return 1;
}
@@ -448,7 +439,7 @@ static int mb_get_additional_smart_log(int argc, char **argv, struct command *cm
const char *raw = "dump output in binary format";
struct config {
__u32 namespace_id;
- int raw_binary;
+ bool raw_binary;
};
struct config cfg = {
@@ -465,8 +456,8 @@ static int mb_get_additional_smart_log(int argc, char **argv, struct command *cm
if (fd < 0)
return fd;
- err = nvme_get_log(fd, cfg.namespace_id, 0xca, false,
- NVME_NO_LOG_LSP, sizeof(smart_log), &smart_log);
+ err = nvme_get_nsid_log(fd, false, 0xca, cfg.namespace_id,
+ sizeof(smart_log), &smart_log);
if (!err) {
if (!cfg.raw_binary)
err = show_memblaze_smart_log(fd, cfg.namespace_id, devicename, &smart_log);
@@ -474,7 +465,7 @@ static int mb_get_additional_smart_log(int argc, char **argv, struct command *cm
d_raw((unsigned char *)&smart_log, sizeof(smart_log));
}
if (err > 0)
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
+ nvme_show_status(err);
return err;
}
@@ -503,7 +494,20 @@ static int mb_get_powermanager_status(int argc, char **argv, struct command *cmd
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0) return fd;
- err = nvme_get_feature(fd, 0, feature_id, 0, 0, 0, 0, NULL, &result);
+ struct nvme_get_features_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .fid = feature_id,
+ .nsid = 0,
+ .sel = 0,
+ .cdw11 = 0,
+ .uuidx = 0,
+ .data_len = 0,
+ .data = NULL,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+ err = nvme_get_features(&args);
if (err < 0) {
perror("get-feature");
}
@@ -512,7 +516,7 @@ static int mb_get_powermanager_status(int argc, char **argv, struct command *cmd
mb_feature_to_string(feature_id),
nvme_select_to_string(0), result);
} else if (err > 0)
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
+ nvme_show_status(err);
return err;
}
@@ -527,7 +531,7 @@ static int mb_set_powermanager_status(int argc, char **argv, struct command *cmd
struct config {
__u32 feature_id;
__u32 value;
- int save;
+ bool save;
};
struct config cfg = {
@@ -545,7 +549,22 @@ static int mb_set_powermanager_status(int argc, char **argv, struct command *cmd
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0) return fd;
- err = nvme_set_feature(fd, 0, cfg.feature_id, cfg.value, 0, cfg.save, 0, 0, NULL, &result);
+ struct nvme_set_features_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .fid = cfg.feature_id,
+ .nsid = 0,
+ .cdw11 = cfg.value,
+ .cdw12 = 0,
+ .save = cfg.save,
+ .uuidx = 0,
+ .cdw15 = 0,
+ .data_len = 0,
+ .data = NULL,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+ err = nvme_set_features(&args);
if (err < 0) {
perror("set-feature");
}
@@ -553,7 +572,7 @@ static int mb_set_powermanager_status(int argc, char **argv, struct command *cmd
printf("set-feature:%02x (%s), value:%#08x\n", cfg.feature_id,
mb_feature_to_string(cfg.feature_id), cfg.value);
} else if (err > 0)
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
+ nvme_show_status(err);
return err;
}
@@ -602,7 +621,22 @@ static int mb_set_high_latency_log(int argc, char **argv, struct command *cmd, s
}
cfg.value = (param1 << MB_FEAT_HIGH_LATENCY_VALUE_SHIFT) | param2;
- err = nvme_set_feature(fd, 0, cfg.feature_id, cfg.value, 0, 0, 0, 0, NULL, &result);
+ struct nvme_set_features_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .fid = cfg.feature_id,
+ .nsid = 0,
+ .cdw11 = cfg.value,
+ .cdw12 = 0,
+ .save = false,
+ .uuidx = 0,
+ .cdw15 = 0,
+ .data_len = 0,
+ .data = NULL,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+ err = nvme_set_features(&args);
if (err < 0) {
perror("set-feature");
}
@@ -610,7 +644,7 @@ static int mb_set_high_latency_log(int argc, char **argv, struct command *cmd, s
printf("set-feature:0x%02X (%s), value:%#08x\n", cfg.feature_id,
mb_feature_to_string(cfg.feature_id), cfg.value);
} else if (err > 0)
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
+ nvme_show_status(err);
return err;
}
@@ -721,13 +755,13 @@ static int mb_high_latency_log_print(int argc, char **argv, struct command *cmd,
if (fd < 0) return fd;
glp_high_latency_show_bar(fdi, DO_PRINT_FLAG);
- err = nvme_get_log(fd, NVME_NSID_ALL, GLP_ID_VU_GET_HIGH_LATENCY_LOG, 0, NVME_NO_LOG_LSP, sizeof(buf), &buf);
+ err = nvme_get_log_simple(fd, GLP_ID_VU_GET_HIGH_LATENCY_LOG, sizeof(buf), &buf);
- while ( 1) {
+ while (1) {
if (!glp_high_latency(fdi, buf, LOG_PAGE_SIZE, DO_PRINT_FLAG)) break;
- err = nvme_get_log(fd, NVME_NSID_ALL, GLP_ID_VU_GET_HIGH_LATENCY_LOG, 0, NVME_NO_LOG_LSP, sizeof(buf), &buf);
+ err = nvme_get_log_simple(fd, GLP_ID_VU_GET_HIGH_LATENCY_LOG, sizeof(buf), &buf);
if ( err) {
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
+ nvme_show_status(err);
break;
}
}
@@ -739,13 +773,13 @@ static int mb_high_latency_log_print(int argc, char **argv, struct command *cmd,
static int memblaze_fw_commit(int fd, int select)
{
- struct nvme_admin_cmd cmd = {
- .opcode = nvme_admin_activate_fw,
+ struct nvme_passthru_cmd cmd = {
+ .opcode = nvme_admin_fw_commit,
.cdw10 = 8,
.cdw12 = select,
};
- return nvme_submit_admin_passthru(fd, &cmd);
+ return nvme_submit_admin_passthru(fd, &cmd, NULL);
}
static int mb_selective_download(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -839,13 +873,21 @@ static int mb_selective_download(int argc, char **argv, struct command *cmd, str
while (fw_size > 0) {
xfer = min(xfer, fw_size);
- err = nvme_fw_download(fd, offset, xfer, fw_buf);
+ struct nvme_fw_download_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .offset = offset,
+ .data_len = xfer,
+ .data = fw_buf,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ err = nvme_fw_download(&args);
if (err < 0) {
perror("fw-download");
goto out;
} else if (err != 0) {
- fprintf(stderr, "NVME Admin command error:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
goto out;
}
fw_buf += xfer;
@@ -980,7 +1022,7 @@ static int mb_lat_stats_log_print(int argc, char **argv, struct command *cmd, st
const char *write = "Get write statistics (read default)";
struct config {
- int write;
+ bool write;
};
struct config cfg = {
.write = 0,
@@ -994,12 +1036,12 @@ static int mb_lat_stats_log_print(int argc, char **argv, struct command *cmd, st
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0) return fd;
- err = nvme_get_log(fd, NVME_NSID_ALL, cfg.write ? 0xc2 : 0xc1, false, NVME_NO_LOG_LSP, sizeof(stats), &stats);
+ err = nvme_get_log_simple(fd, cfg.write ? 0xc2 : 0xc1, sizeof(stats), &stats);
if (!err)
io_latency_histogram(cfg.write ? f2 : f1, stats, DO_PRINT_FLAG,
cfg.write ? GLP_ID_VU_GET_WRITE_LATENCY_HISTOGRAM : GLP_ID_VU_GET_READ_LATENCY_HISTOGRAM);
else
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
+ nvme_show_status(err);
close(fd);
return err;
@@ -1009,8 +1051,8 @@ static int mb_lat_stats_log_print(int argc, char **argv, struct command *cmd, st
#define FID 0x68
static int memblaze_clear_error_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
- int err, fd;
- char *desc = "Clear Memblaze devices error log.";
+ int err, fd;
+ char *desc = "Clear Memblaze devices error log.";
//const char *value = "new value of feature (required)";
//const char *save = "specifies that the controller shall save the attribute";
@@ -1028,24 +1070,38 @@ static int memblaze_clear_error_log(int argc, char **argv, struct command *cmd,
.save = 0,
};
- OPT_ARGS(opts) = {
- OPT_END()
- };
-
- fd = parse_and_open(argc, argv, desc, opts);
- if (fd < 0)
- return fd;
-
-
+ OPT_ARGS(opts) = {
+ OPT_END()
+ };
- err = nvme_set_feature(fd, 0, cfg.feature_id, cfg.value, 0, cfg.save, 0, 0, NULL, &result);
+ fd = parse_and_open(argc, argv, desc, opts);
+ if (fd < 0)
+ return fd;
+
+ struct nvme_set_features_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .fid = cfg.feature_id,
+ .nsid = 0,
+ .cdw11 = cfg.value,
+ .cdw12 = 0,
+ .save = cfg.save,
+ .uuidx = 0,
+ .cdw15 = 0,
+ .data_len = 0,
+ .data = NULL,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+ err = nvme_set_features(&args);
if (err < 0) {
perror("set-feature");
}
if (!err) {
printf("set-feature:%02x (%s), value:%#08x\n", cfg.feature_id, mb_feature_to_string(cfg.feature_id), cfg.value);
} else if (err > 0)
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
+ nvme_show_status(err);
+
/*
struct nvme_admin_cmd admin_cmd = {
.opcode = OP,
@@ -1060,7 +1116,7 @@ static int memblaze_clear_error_log(int argc, char **argv, struct command *cmd,
printf("NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
};
*/
- return err;
+ return err;
}
static int mb_set_lat_stats(int argc, char **argv,
@@ -1092,8 +1148,8 @@ static int mb_set_lat_stats(int argc, char **argv,
};
const struct argconfig_commandline_options command_line_options[] = {
- {"enable", 'e', "", CFG_NONE, &cfg.enable, no_argument, enable_desc},
- {"disable", 'd', "", CFG_NONE, &cfg.disable, no_argument, disable_desc},
+ {"enable", 'e', "", CFG_FLAG, &cfg.enable, no_argument, enable_desc},
+ {"disable", 'd', "", CFG_FLAG, &cfg.disable, no_argument, disable_desc},
{NULL}
};
@@ -1111,12 +1167,41 @@ static int mb_set_lat_stats(int argc, char **argv,
else if (cfg.enable || cfg.disable)
option = cfg.enable;
+ struct nvme_get_features_args args_get = {
+ .args_size = sizeof(args_get),
+ .fd = fd,
+ .fid = fid,
+ .nsid = nsid,
+ .sel = sel,
+ .cdw11 = cdw11,
+ .uuidx = 0,
+ .data_len = data_len,
+ .data = buf,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+
+ struct nvme_set_features_args args_set = {
+ .args_size = sizeof(args_set),
+ .fd = fd,
+ .fid = fid,
+ .nsid = nsid,
+ .cdw11 = option,
+ .cdw12 = cdw12,
+ .save = save,
+ .uuidx = 0,
+ .cdw15 = 0,
+ .data_len = data_len,
+ .data = buf,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+
if (fd < 0)
return fd;
switch (option) {
case None:
- err = nvme_get_feature(fd, nsid, fid, sel, cdw11, 0, data_len, buf,
- &result);
+ err = nvme_get_features(&args_get);
if (!err) {
printf(
"Latency Statistics Tracking (FID 0x%X) is currently (%i).\n",
@@ -1128,17 +1213,15 @@ static int mb_set_lat_stats(int argc, char **argv,
break;
case True:
case False:
- err = nvme_set_feature(fd, nsid, fid, option, cdw12, save, 0,
- data_len, buf, &result);
+ err = nvme_set_features(&args_set);
if (err > 0) {
- fprintf(stderr, "NVMe Status:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
} else if (err < 0) {
perror("Enable latency tracking");
fprintf(stderr, "Command failed while parsing.\n");
} else {
printf("Successfully set enable bit for FID (0x%X) to %i.\n",
- fid, option);
+ 0xe2, option);
}
break;
default:
diff --git a/plugins/meson.build b/plugins/meson.build
new file mode 100644
index 0000000..6f21362
--- /dev/null
+++ b/plugins/meson.build
@@ -0,0 +1,21 @@
+sources += [
+ 'plugins/amzn/amzn-nvme.c',
+ 'plugins/dera/dera-nvme.c',
+ 'plugins/huawei/huawei-nvme.c',
+ 'plugins/intel/intel-nvme.c',
+ 'plugins/memblaze/memblaze-nvme.c',
+ 'plugins/micron/micron-nvme.c',
+ 'plugins/netapp/netapp-nvme.c',
+ 'plugins/nvidia/nvidia-nvme.c',
+ 'plugins/scaleflux/sfx-nvme.c',
+ 'plugins/seagate/seagate-nvme.c',
+ 'plugins/shannon/shannon-nvme.c',
+ 'plugins/toshiba/toshiba-nvme.c',
+ 'plugins/transcend/transcend-nvme.c',
+ 'plugins/virtium/virtium-nvme.c',
+ 'plugins/wdc/wdc-utils.c',
+ 'plugins/wdc/wdc-nvme.c',
+ 'plugins/ymtc/ymtc-nvme.c',
+ 'plugins/zns/zns.c',
+ 'plugins/ocp/ocp-nvme.c',
+]
diff --git a/plugins/micron/micron-nvme.c b/plugins/micron/micron-nvme.c
index 840682d..d333c4c 100644
--- a/plugins/micron/micron-nvme.c
+++ b/plugins/micron/micron-nvme.c
@@ -9,12 +9,13 @@
#include <string.h>
#include <libgen.h>
#include <sys/stat.h>
+#include "common.h"
#include "nvme.h"
-#include "nvme-print.h"
-#include "nvme-status.h"
-#include "nvme-ioctl.h"
-#include <sys/ioctl.h>
+#include "libnvme.h"
#include <limits.h>
+#include "linux/types.h"
+#include "nvme-print.h"
+
#define CREATE_CMD
#include "micron-nvme.h"
@@ -30,6 +31,7 @@
#define C2_log_size 4096
#define D0_log_size 512
#define FB_log_size 512
+#define E1_log_size 256
#define MaxLogChunk 16 * 1024
#define CommonChunkSize 16 * 4096
@@ -39,7 +41,7 @@
/* Plugin version major_number.minor_number.patch */
static const char *__version_major = "1";
static const char *__version_minor = "0";
-static const char *__version_patch = "6";
+static const char *__version_patch = "8";
/* supported models of micron plugin; new models should be added at the end
* before UNKNOWN_MODEL. Make sure M5410 is first in the list !
@@ -66,7 +68,7 @@ typedef struct _LogPageHeader_t {
static void WriteData(__u8 *data, __u32 len, const char *dir, const char *file, const char *msg)
{
- char tempFolder[PATH_MAX] = { 0 };
+ char tempFolder[8192] = { 0 };
FILE *fpOutFile = NULL;
sprintf(tempFolder, "%s/%s", dir, file);
if ((fpOutFile = fopen(tempFolder, "ab+")) != NULL) {
@@ -115,6 +117,7 @@ static eDriveModel GetDriveModel(int idx)
}
if (vendor_id == MICRON_VENDOR_ID) {
switch (device_id) {
+ case 0x5196:
case 0x51A0:
case 0x51A1:
case 0x51A2:
@@ -311,8 +314,8 @@ static int GetLogPageSize(int nFD, unsigned char ucLogID, int *nLogSize)
LogPageHeader_t *pLogHeader = NULL;
if (ucLogID == 0xC1 || ucLogID == 0xC2 || ucLogID == 0xC4) {
- err = nvme_get_log(nFD, NVME_NSID_ALL, ucLogID, false, NVME_NO_LOG_LSP,
- CommonChunkSize, pTmpBuf);
+ err = nvme_get_log_simple(nFD, ucLogID,
+ CommonChunkSize, pTmpBuf);
if (err == 0) {
pLogHeader = (LogPageHeader_t *) pTmpBuf;
LogPageHeader_t *pLogHeader1 = (LogPageHeader_t *) pLogHeader;
@@ -334,7 +337,7 @@ static int GetLogPageSize(int nFD, unsigned char ucLogID, int *nLogSize)
static int NVMEGetLogPage(int nFD, unsigned char ucLogID, unsigned char *pBuffer, int nBuffSize)
{
int err = 0;
- struct nvme_admin_cmd cmd = { 0 };
+ struct nvme_passthru_cmd cmd = { 0 };
unsigned int uiNumDwords = (unsigned int)nBuffSize / sizeof(unsigned int);
unsigned int uiMaxChunk = uiNumDwords;
unsigned int uiNumChunks = 1;
@@ -380,7 +383,7 @@ static int NVMEGetLogPage(int nFD, unsigned char ucLogID, unsigned char *pBuffer
cmd.addr = (__u64) (uintptr_t) pTempPtr;
cmd.nsid = 0xFFFFFFFF;
cmd.data_len = uiXferDwords * 4;
- err = nvme_submit_passthru(nFD, NVME_IOCTL_ADMIN_CMD, &cmd);
+ err = nvme_submit_admin_passthru(nFD, &cmd, NULL);
ullBytesRead += uiXferDwords * 4;
pTempPtr = pBuffer + ullBytesRead;
}
@@ -422,8 +425,7 @@ static int GetCommonLogPage(int nFD, unsigned char ucLogID,
goto exit_status;
}
memset(pTempPtr, 0, nBuffSize);
- err = nvme_get_log(nFD, NVME_NSID_ALL, ucLogID, false, NVME_NO_LOG_LSP,
- nBuffSize, pTempPtr);
+ err = nvme_get_log_simple(nFD, ucLogID, nBuffSize, pTempPtr);
*pBuffer = pTempPtr;
exit_status:
@@ -454,8 +456,8 @@ static int micron_parse_options(int argc, char **argv, const char *desc,
static int micron_fw_commit(int fd, int select)
{
- struct nvme_admin_cmd cmd = {
- .opcode = nvme_admin_activate_fw,
+ struct nvme_passthru_cmd cmd = {
+ .opcode = nvme_admin_fw_commit,
.cdw10 = 8,
.cdw12 = select,
};
@@ -554,13 +556,21 @@ static int micron_selective_download(int argc, char **argv,
while (fw_size > 0) {
xfer = min(xfer, fw_size);
- err = nvme_fw_download(fd, offset, xfer, fw_buf);
+ struct nvme_fw_download_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .offset = offset,
+ .data_len = xfer,
+ .data = fw_buf,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ err = nvme_fw_download(&args);
if (err < 0) {
perror("fw-download");
goto out;
} else if (err != 0) {
- fprintf(stderr, "NVME Admin command error:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
goto out;
}
fw_buf += xfer;
@@ -584,7 +594,6 @@ static int micron_smbus_option(int argc, char **argv,
struct command *cmd, struct plugin *plugin)
{
__u32 result = 0;
- __u32 cdw10 = 0;
__u32 cdw11 = 0;
const char *desc = "Enable/Disable/Get status of SMBUS option on controller";
const char *option = "enable or disable or status";
@@ -627,7 +636,7 @@ static int micron_smbus_option(int argc, char **argv,
if (!strcmp(opt.option, "enable")) {
cdw11 = opt.value << 1 | 1;
- err = nvme_set_feature(fd, 1, fid, cdw11, 0, opt.save, 0, 0, 0, &result);
+ err = nvme_set_features_simple(fd, fid, 1, cdw11, opt.save, &result);
if (err == 0) {
printf("successfully enabled SMBus on drive\n");
} else {
@@ -635,8 +644,20 @@ static int micron_smbus_option(int argc, char **argv,
}
}
else if (!strcmp(opt.option, "status")) {
- cdw10 = opt.value;
- err = nvme_get_feature(fd, 1, fid, cdw10, 0, 0, 0, 0, &result);
+ struct nvme_get_features_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .fid = fid,
+ .nsid = 1,
+ .sel = opt.value,
+ .cdw11 = 0,
+ .uuidx = 0,
+ .data_len = 0,
+ .data = NULL,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+ err = nvme_get_features(&args);
if (err == 0) {
printf("SMBus status on the drive: %s (returns %s temperature) \n",
(result & 1) ? "enabled" : "disabled",
@@ -647,7 +668,7 @@ static int micron_smbus_option(int argc, char **argv,
}
else if (!strcmp(opt.option, "disable")) {
cdw11 = opt.value << 1 | 0;
- err = nvme_set_feature(fd, 1, fid, cdw11, 0, opt.save, 0, 0, 0, &result);
+ err = nvme_set_features_simple(fd, fid, 1, cdw11, opt.save, &result);
if (err == 0) {
printf("Successfully disabled SMBus on drive\n");
} else {
@@ -698,7 +719,7 @@ static int micron_temp_stats(int argc, char **argv, struct command *cmd,
if (strcmp(cfg.fmt, "json") == 0)
is_json = true;
- err = nvme_smart_log(fd, 0xffffffff, &smart_log);
+ err = nvme_get_log_smart(fd, 0xffffffff, false, &smart_log);
if (!err) {
temperature = ((smart_log.temperature[1] << 8) | smart_log.temperature[0]);
temperature = temperature ? temperature - 273 : 0;
@@ -933,11 +954,11 @@ static int micron_clear_pcie_correctable_errors(int argc, char **argv,
/* For M51CX models, PCIe errors are cleared using 0xC3 feature */
if (model == M51CX) {
- err = nvme_set_feature(fd, 0, fid, (1 << 31), 0, 0, 0, 0, 0, &result);
+ err = nvme_set_features_simple(fd, fid, 0, (1 << 31), false, &result);
if (err == 0 && (err = (int)result) == 0)
printf("Device correctable errors cleared!\n");
- else if (err > 0)
- nvme_show_status(err);
+ else if (err > 0)
+ nvme_show_status(err);
else
printf("Error clearing Device correctable errors = 0x%x\n", err);
goto out;
@@ -1098,6 +1119,36 @@ ocp_c0_log_page[] = {
{ "Log Page Version", 2},
{ "Log Page GUID", 16},
},
+/* Extended SMART log information */
+e1_log_page[] = {
+ { "Reserved", 12},
+ { "Grown Bad Block Count", 4},
+ { "Per Block Max Erase Count", 4},
+ { "Power On Minutes", 4},
+ { "Reserved", 24},
+ { "Write Protect Reason", 4},
+ { "Reserved", 12},
+ { "Drive Capacity", 8},
+ { "Reserved", 8},
+ { "Total Erase Count", 8},
+ { "Lifetime Use Rate", 8},
+ { "Erase Fail Count", 8},
+ { "Reserved", 8},
+ { "Reported UC Errors", 8},
+ { "Reserved", 24},
+ { "Program Fail Count", 16},
+ { "Total Bytes Read", 16},
+ { "Total Bytes Written", 16},
+ { "Reserved", 16},
+ { "TU Size", 4},
+ { "Total Block Stripe Count", 4},
+ { "Free Block Stripe Count", 4},
+ { "Block Stripe Size", 8},
+ { "Reserved", 16},
+ { "User Block Min Erase Count", 4},
+ { "User Block Avg Erase Count", 4},
+ { "User Block Max Erase Count", 4},
+},
/* Vendor Specific Health Log information */
fb_log_page[] = {
{ "Physical Media Units Written - TLC", 16, 16 },
@@ -1137,8 +1188,8 @@ fb_log_page[] = {
{ "Normalized Bad System NAND Block Count", 2, 2},
{ "Raw Bad System NAND Block Count", 6, 6},
{ "Endurance Estimate", 16, 16},
- { "Thermal Throttling Count", 1, 1},
{ "Thermal Throttling Status", 1, 1},
+ { "Thermal Throttling Count", 1, 1},
{ "Unaligned I/O", 8, 8},
{ "Physical Media Units Read", 16, 16},
{ "Reserved", 279, 0},
@@ -1272,13 +1323,13 @@ static void print_nand_stats_fb(__u8 *buf, __u8 *buf2, __u8 nsze, bool is_json,
init_d0_log_page(buf2, nsze);
if (is_json) {
- for (int i = 0; i < 7; i++) {
+ for (int i = 4; i < 7; i++) {
json_object_add_value_string(stats,
- d0_log_page[i].field,
- d0_log_page[i].datastr);
+ d0_log_page[i].field,
+ d0_log_page[i].datastr);
}
} else {
- for (int i = 0; i < 7; i++) {
+ for (int i = 4; i < 7; i++) {
printf("%-40s : %s\n", d0_log_page[i].field, d0_log_page[i].datastr);
}
}
@@ -1367,42 +1418,115 @@ static int micron_nand_stats(int argc, char **argv,
/* pull log details based on the model name */
sscanf(argv[optind], "/dev/nvme%d", &ctrlIdx);
- if ((eModel = GetDriveModel(ctrlIdx)) == UNKNOWN_MODEL) {
+ eModel = GetDriveModel(ctrlIdx);
+ if ((eModel == UNKNOWN_MODEL) || (eModel == M51CX)) {
printf ("Unsupported drive model for vs-nand-stats command\n");
- err = -1;
+ err = -1;
goto out;
}
- err = nvme_get_log(fd, NVME_NSID_ALL, 0xD0, false, NVME_NO_LOG_LSP,
- D0_log_size, extSmartLog);
+ err = nvme_get_log_simple(fd, 0xD0, D0_log_size, extSmartLog);
has_d0_log = (0 == err);
/* should check for firmware version if this log is supported or not */
- if (eModel != M5407 && eModel != M5410) {
- err = nvme_get_log(fd, NVME_NSID_ALL, 0xFB, false, NVME_NO_LOG_LSP,
- FB_log_size, logFB);
+ if (eModel == M5407 || eModel == M5410) {
+ err = nvme_get_log_simple(fd, 0xFB, FB_log_size, logFB);
has_fb_log = (0 == err);
}
nsze = (ctrl.vs[987] == 0x12);
-
if (nsze == 0 && nsze_from_oacs)
nsze = ((ctrl.oacs >> 3) & 0x1);
-
+ err = 0;
if (has_fb_log) {
__u8 spec = (eModel == M5410) ? 0 : 1; /* FB spec version */
print_nand_stats_fb((__u8 *)logFB, (__u8 *)extSmartLog, nsze, is_json, spec);
} else if (has_d0_log) {
print_nand_stats_d0((__u8 *)extSmartLog, nsze, is_json);
- err = 0;
+ } else {
+ printf("Unable to retrieve extended smart log for the drive\n");
+ err = -ENOTTY;
}
out:
close(fd);
if (err > 0)
- nvme_show_status(err);
- return nvme_status_to_errno(err, false);
+ nvme_show_status(err);
+
+ return err;
}
+static void print_ext_smart_logs_e1(__u8 *buf, bool is_json)
+{
+ struct json_object *root;
+ struct json_object *logPages;
+ struct json_object *stats = NULL;
+ int field_count = sizeof(e1_log_page)/sizeof(e1_log_page[0]);
+
+ if (is_json) {
+ root = json_create_object();
+ stats = json_create_object();
+ logPages = json_create_array();
+ json_object_add_value_array(root, "SMART Extended Log:0xE1", logPages);
+ }
+ else {
+ printf("SMART Extended Log:0xE1\n");
+ }
+
+ print_micron_vs_logs(buf, e1_log_page, field_count, stats, 0);
+
+ if (is_json) {
+ json_array_add_value_object(logPages, stats);
+ json_print_object(root, NULL);
+ printf("\n");
+ json_free_object(root);
+ }
+}
+
+static int micron_smart_ext_log(int argc, char **argv,
+ struct command *cmd, struct plugin *plugin)
+{
+ const char *desc = "Retrieve extended SMART logs for the given device ";
+ unsigned int extSmartLog[E1_log_size/sizeof(int)] = { 0 };
+ eDriveModel eModel = UNKNOWN_MODEL;
+ int fd = 0, err = 0, ctrlIdx = 0;
+ bool is_json = true;
+ struct format {
+ char *fmt;
+ };
+ const char *fmt = "output format json|normal";
+ struct format cfg = {
+ .fmt = "json",
+ };
+ OPT_ARGS(opts) = {
+ OPT_FMT("format", 'f', &cfg.fmt, fmt),
+ OPT_END()
+ };
+
+ fd = parse_and_open(argc, argv, desc, opts);
+ if (fd < 0) {
+ printf("\nDevice not found \n");;
+ return -1;
+ }
+ if (strcmp(cfg.fmt, "normal") == 0)
+ is_json = false;
+
+ sscanf(argv[optind], "/dev/nvme%d", &ctrlIdx);
+ if ((eModel = GetDriveModel(ctrlIdx)) != M51CX) {
+ printf ("Unsupported drive model for vs-smart-ext-log command\n");
+ err = -1;
+ goto out;
+ }
+ err = nvme_get_log_simple(fd, 0xE1, E1_log_size, extSmartLog);
+ if (!err) {
+ print_ext_smart_logs_e1((__u8 *)extSmartLog, is_json);
+ }
+
+out:
+ close(fd);
+ if (err > 0)
+ nvme_show_status(err);
+ return err;
+}
static void GetDriveInfo(const char *strOSDirName, int nFD,
struct nvme_id_ctrl *ctrlp)
@@ -1487,7 +1611,7 @@ static void GetCtrlIDDInfo(const char *dir, struct nvme_id_ctrl *ctrlp)
static void GetSmartlogData(int fd, const char *dir)
{
struct nvme_smart_log smart_log;
- if (nvme_smart_log(fd, -1, &smart_log) == 0) {
+ if (nvme_get_log_smart(fd, -1, false, &smart_log) == 0) {
WriteData((__u8*)&smart_log, sizeof(smart_log), dir,
"smart_data.bin", "smart log");
}
@@ -1502,7 +1626,7 @@ static void GetErrorlogData(int fd, int entries, const char *dir)
if (error_log == NULL)
return;
- if (nvme_error_log(fd, entries, error_log) == 0) {
+ if (nvme_get_log_error(fd, entries, false, error_log) == 0) {
WriteData((__u8*)error_log, logSize, dir,
"error_information_log.bin", "error log");
}
@@ -1513,50 +1637,50 @@ static void GetErrorlogData(int fd, int entries, const char *dir)
static void GetGenericLogs(int fd, const char *dir)
{
struct nvme_self_test_log self_test_log;
- struct nvme_firmware_log_page fw_log;
- struct nvme_effects_log_page effects;
- struct nvme_persistent_event_log_head pevent_log_head;
+ struct nvme_firmware_slot fw_log;
+ struct nvme_cmd_effects_log effects;
+ struct nvme_persistent_event_log pevent_log;
void *pevent_log_info = NULL;
__u32 log_len = 0;
int err = 0 ;
bool huge = false;
/* get self test log */
- if (nvme_self_test_log(fd, sizeof(self_test_log), &self_test_log) == 0) {
+ if (nvme_get_log_device_self_test(fd, &self_test_log) == 0) {
WriteData((__u8*)&self_test_log, sizeof(self_test_log), dir,
"drive_self_test.bin", "self test log");
}
/* get fw slot info log */
- if (nvme_fw_log(fd, &fw_log) == 0) {
+ if (nvme_get_log_fw_slot(fd, 1, &fw_log) == 0) {
WriteData((__u8*)&fw_log, sizeof(fw_log), dir,
"firmware_slot_info_log.bin", "firmware log");
}
/* get effects log */
- if (nvme_effects_log(fd, &effects) == 0) {
+ if (nvme_get_log_cmd_effects(fd, NVME_CSI_NVM, &effects) == 0) {
WriteData((__u8*)&effects, sizeof(effects), dir,
"command_effects_log.bin", "effects log");
}
-
+
/* get persistent event log */
- (void)nvme_persistent_event_log(fd, NVME_PEVENT_LOG_RELEASE_CTX,
- sizeof(pevent_log_head), &pevent_log_head);
- memset(&pevent_log_head, 0, sizeof(pevent_log_head));
- err = nvme_persistent_event_log(fd, NVME_PEVENT_LOG_EST_CTX_AND_READ,
- sizeof(pevent_log_head), &pevent_log_head);
+ (void)nvme_get_log_persistent_event(fd, NVME_PEVENT_LOG_RELEASE_CTX,
+ sizeof(pevent_log), &pevent_log);
+ memset(&pevent_log, 0, sizeof(pevent_log));
+ err = nvme_get_log_persistent_event(fd, NVME_PEVENT_LOG_EST_CTX_AND_READ,
+ sizeof(pevent_log), &pevent_log);
if (err) {
- fprintf(stderr, "Setting persistent event log read ctx failed (ignored)!\n");
+ fprintf(stderr, "Failed to set persistent event log read context");
return;
}
- log_len = le64_to_cpu(pevent_log_head.tll);
+ log_len = le64_to_cpu(pevent_log.tll);
pevent_log_info = nvme_alloc(log_len, &huge);
if (!pevent_log_info) {
- perror("could not alloc buffer for persistent event log page (ignored)!\n");
+ perror("could not alloc buffer for persistent event log page\n");
return;
}
- err = nvme_persistent_event_log(fd, NVME_PEVENT_LOG_READ,
+ err = nvme_get_log_persistent_event(fd, NVME_PEVENT_LOG_READ,
log_len, pevent_log_info);
if (err == 0) {
WriteData((__u8*)pevent_log_info, log_len, dir,
@@ -1571,7 +1695,7 @@ static void GetNSIDDInfo(int fd, const char *dir, int nsid)
char file[PATH_MAX] = { 0 };
struct nvme_id_ns ns;
- if (nvme_identify_ns(fd, nsid, 0, &ns) == 0) {
+ if (nvme_identify_ns(fd, nsid, &ns) == 0) {
sprintf(file, "identify_namespace_%d_data.bin", nsid);
WriteData((__u8*)&ns, sizeof(ns), dir, file, "id-ns");
}
@@ -1617,7 +1741,7 @@ static void GetOSConfig(const char *strOSDirName)
}
}
-static int micron_telemetry_log(int fd, __u8 gen, __u8 type, __u8 **data,
+static int micron_telemetry_log(int fd, __u8 type, __u8 **data,
int *logSize, int da)
{
int err, bs = 512, offset = bs;
@@ -1627,7 +1751,10 @@ static int micron_telemetry_log(int fd, __u8 gen, __u8 type, __u8 **data,
__u8 *buffer = (unsigned char *)calloc(bs, 1);
if (buffer == NULL)
return -1;
- err = nvme_get_telemetry_log(fd, buffer, gen, ctrl_init, bs, 0);
+ if (ctrl_init)
+ err = nvme_get_log_telemetry_ctrl(fd, true, 0, bs, buffer);
+ else
+ err = nvme_get_log_telemetry_host(fd, 0, bs, buffer);
if (err != 0) {
fprintf(stderr, "Failed to get telemetry log header for 0x%X\n", type);
if (buffer != NULL) {
@@ -1657,7 +1784,10 @@ static int micron_telemetry_log(int fd, __u8 gen, __u8 type, __u8 **data,
err = 0;
if ((buffer = (unsigned char *)realloc(buffer, (size_t)(*logSize))) != NULL) {
while (err == 0 && offset != *logSize) {
- err = nvme_get_telemetry_log(fd, buffer + offset, gen, ctrl_init, bs, offset);
+ if (ctrl_init)
+ err = nvme_get_log_telemetry_ctrl(fd, true, 0, *logSize, buffer + offset);
+ else
+ err = nvme_get_log_telemetry_host(fd, 0, *logSize, buffer + offset);
offset += bs;
}
}
@@ -1687,8 +1817,7 @@ static int GetTelemetryData(int fd, const char *dir)
};
for(i = 0; i < (int)(sizeof(tmap)/sizeof(tmap[0])); i++) {
- err = micron_telemetry_log(fd, (tmap[i].log == 0x07),
- tmap[i].log, &buffer, &logSize, 0);
+ err = micron_telemetry_log(fd, tmap[i].log, &buffer, &logSize, 0);
if (err == 0 && logSize > 0 && buffer != NULL) {
sprintf(msg, "telemetry log: 0x%X", tmap[i].log);
WriteData(buffer, logSize, dir, tmap[i].file, msg);
@@ -1735,7 +1864,20 @@ static int GetFeatureSettings(int fd, const char *dir)
bufp = NULL;
}
- err = nvme_get_feature(fd, 1, fmap[i].id, 0, 0x0, 0, len, bufp, &attrVal);
+ struct nvme_get_features_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .fid = fmap[i].id,
+ .nsid = 1,
+ .sel = 0,
+ .cdw11 = 0x0,
+ .uuidx = 0,
+ .data_len = len,
+ .data = bufp,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &attrVal,
+ };
+ err = nvme_get_features(&args);
if (err == 0) {
sprintf(msg, "feature: 0x%X", fmap[i].id);
WriteData((__u8*)&attrVal, sizeof(attrVal), dir, fmap[i].file, msg);
@@ -1743,7 +1885,7 @@ static int GetFeatureSettings(int fd, const char *dir)
WriteData(bufp, len, dir, fmap[i].file, msg);
}
} else {
- fprintf(stderr, "Feature 0x%x data not retrieved, error %d (ignored)!\n",
+ printf("Feature 0x%x data not retrieved, error %d (ignored)!\n",
fmap[i].id, err);
errcnt++;
}
@@ -1757,7 +1899,7 @@ static int micron_drive_info(int argc, char **argv, struct command *cmd,
const char *desc = "Get drive HW information";
int fd, err = 0;
struct nvme_id_ctrl ctrl = { 0 };
- struct nvme_admin_cmd admin_cmd = { 0 };
+ struct nvme_passthru_cmd admin_cmd = { 0 };
struct fb_drive_info {
unsigned char hw_ver_major;
unsigned char hw_ver_minor;
@@ -1794,11 +1936,11 @@ static int micron_drive_info(int argc, char **argv, struct command *cmd,
is_json = true;
if (model == M5407) {
- admin_cmd.opcode = 0xDA,
+ admin_cmd.opcode = 0xD4,
admin_cmd.addr = (__u64) (uintptr_t) &dinfo;
admin_cmd.data_len = (__u32)sizeof(dinfo);
admin_cmd.cdw12 = 3;
- err = ioctl(fd, NVME_IOCTL_ADMIN_CMD, &admin_cmd);
+ err = nvme_submit_admin_passthru(fd, &admin_cmd, NULL);
if (err) {
fprintf(stderr, "ERROR : drive-info opcode failed with 0x%x\n", err);
return -1;
@@ -2025,7 +2167,7 @@ static int micron_fw_activation_history(int argc, char **argv, struct command *c
goto out;
}
- err = nvme_get_log(fd, NVME_NSID_ALL, 0xC2, false, NVME_NO_LOG_LSP, C2_log_size, logC2);
+ err = nvme_get_log_simple(fd, 0xC2, C2_log_size, logC2);
if (err) {
fprintf(stderr, "Failed to retrieve fw activation history log, error: %x\n", err);
goto out;
@@ -2063,11 +2205,320 @@ out:
return err;
}
-static int micron_error_reason(int argc, char **argv, struct command *cmd,
+#define MICRON_FID_LATENCY_MONITOR 0xD0
+#define MICRON_LOG_LATENCY_MONITOR 0xD1
+
+static int micron_latency_stats_track(int argc, char **argv, struct command *cmd,
struct plugin *plugin)
{
- printf("This command is not implemented for the drive\n");
- return 0;
+ int err = 0;
+ __u32 result = 0;
+ const char *desc = "Enable, Disable or Get cmd latency monitoring stats";
+ const char *option = "enable or disable or status, default is status";
+ const char *command = "commands to monitor for - all|read|write|trim,"
+ " default is all i.e, enabled for all commands";
+ const char *thrtime = "The threshold value to use for latency monitoring in"
+ " milliseconds, default is 800ms";
+
+ int fd = 0;
+ int fid = MICRON_FID_LATENCY_MONITOR;
+ eDriveModel model = UNKNOWN_MODEL;
+ uint32_t command_mask = 0x7; /* 1:read 2:write 4:trim 7:all */
+ uint32_t timing_mask = 0x08080800; /* R[31-24]:W[23:16]:T[15:8]:0 */
+ uint32_t enable = 2;
+ struct {
+ char *option;
+ char *command;
+ uint32_t threshold;
+ } opt = {
+ .option = "status",
+ .command = "all",
+ .threshold = 0
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_STRING("option", 'o', "option", &opt.option, option),
+ OPT_STRING("command", 'c', "command", &opt.command, command),
+ OPT_UINT("threshold", 't', &opt.threshold, thrtime),
+ OPT_END()
+ };
+
+
+ if ((fd = micron_parse_options(argc, argv, desc, opts, &model)) < 0) {
+ return -1;
+ }
+
+ if (!strcmp(opt.option, "enable")) {
+ enable = 1;
+ } else if (!strcmp(opt.option, "disable")) {
+ enable = 0;
+ } else if (strcmp(opt.option, "status")) {
+ printf("Invalid control option %s specified\n", opt.option);
+ return -1;
+ }
+
+ struct nvme_get_features_args g_args = {
+ .args_size = sizeof(g_args),
+ .fd = fd,
+ .fid = fid,
+ .nsid = 0,
+ .sel = 0,
+ .cdw11 = 0,
+ .uuidx = 0,
+ .data_len = 0,
+ .data = NULL,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+
+ err = nvme_get_features(&g_args);
+ if (err != 0) {
+ printf("Failed to retrieve latency monitoring feature status\n");
+ return err;
+ }
+
+ /* If it is to retrieve the status only */
+ if (enable == 2) {
+ printf("Latency Tracking Statistics is currently %s",
+ (result & 0xFFFF0000) ? "enabled" : "disabled");
+ if ((result & 7) == 7) {
+ printf(" for All commands\n");
+ } else if ((result & 7) > 0) {
+ printf(" for");
+ if (result & 1) {
+ printf(" Read");
+ }
+ if (result & 2) {
+ printf(" Write");
+ }
+ if (result & 4) {
+ printf(" Trim");
+ }
+ printf(" commands\n");
+ } else if (result == 0) {
+ printf("\n");
+ }
+ return err;
+ }
+
+ /* read and validate threshold values if enable option is specified */
+ if (enable == 1) {
+ if (opt.threshold > 2550) {
+ printf("The maximum threshold value cannot be more than 2550 ms\n");
+ return -1;
+ }
+ /* timing mask is in terms of 10ms units, so min allowed is 10ms */
+ else if ((opt.threshold % 10) != 0) {
+ printf("The threshold value should be multiple of 10 ms\n");
+ return -1;
+ }
+ opt.threshold /= 10;
+ }
+
+ /* read-in command(s) to be monitored */
+ if (!strcmp(opt.command, "read")) {
+ command_mask = 0x1;
+ timing_mask = (opt.threshold << 24);
+ } else if (!strcmp(opt.command, "write")) {
+ command_mask = 0x2;
+ timing_mask = (opt.threshold << 16);
+ } else if (!strcmp(opt.command, "read")) {
+ command_mask = 0x4;
+ timing_mask = (opt.threshold << 8);
+ } else if (strcmp(opt.command, "all")) {
+ printf("Invalid command %s specified for option %s\n",
+ opt.command, opt.option);
+ return -1;
+ }
+
+ struct nvme_set_features_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .fid = MICRON_FID_LATENCY_MONITOR,
+ .nsid = 0,
+ .cdw11 = enable,
+ .cdw12 = command_mask,
+ .save = 1,
+ .uuidx = 0,
+ .cdw13 = timing_mask,
+ .cdw15 = 0,
+ .data_len = 0,
+ .data = NULL,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+ err = nvme_set_features(&args);
+ if (err == 0) {
+ printf("Successfully %sed latency monitoring for %s commands\n",
+ opt.option, opt.command);
+ } else {
+ printf("Failed to %s latency monitoring for %s commands\n",
+ opt.option, opt.command);
+ }
+
+ close(fd);
+ return err;
+}
+
+
+static int micron_latency_stats_logs(int argc, char **argv, struct command *cmd,
+ struct plugin *plugin)
+{
+#define LATENCY_LOG_ENTRIES 16
+ struct latency_log_entry {
+ uint64_t timestamp;
+ uint32_t latency;
+ uint32_t cmdtag;
+ union {
+ struct {
+ uint32_t opcode:8;
+ uint32_t fuse:2;
+ uint32_t rsvd1:4;
+ uint32_t psdt:2;
+ uint32_t cid:16;
+ };
+ uint32_t dw0;
+ };
+ uint32_t nsid;
+ uint32_t slba_low;
+ uint32_t slba_high;
+ union {
+ struct {
+ uint32_t nlb:16;
+ uint32_t rsvd2:9;
+ uint32_t deac:1;
+ uint32_t prinfo:4;
+ uint32_t fua:1;
+ uint32_t lr:1;
+ };
+ uint32_t dw12;
+ };
+ uint32_t dsm;
+ uint32_t rfu[6];
+ } log[LATENCY_LOG_ENTRIES];
+ eDriveModel model = UNKNOWN_MODEL;
+ int err = -1;
+ int fd = -1;
+ const char *desc = "Display Latency tracking log information";
+ OPT_ARGS(opts) = {
+ OPT_END()
+ };
+
+ if ((fd = micron_parse_options(argc, argv, desc, opts, &model)) < 0)
+ return err;
+ memset(&log, 0, sizeof(log));
+ err = nvme_get_log_simple(fd, 0xD1, sizeof(log), &log);
+ if (err) {
+ if (err < 0)
+ printf("Unable to retrieve latency stats log the drive\n");
+ return err;
+ }
+ /* print header and each log entry */
+ printf("Timestamp, Latency, CmdTag, Opcode, Fuse, Psdt,Cid, Nsid,"
+ "Slba_L, Slba_H, Nlb, DEAC, PRINFO, FUA,LR\n");
+ for (int i = 0; i < LATENCY_LOG_ENTRIES; i++) {
+ printf("%"PRIu64",%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u\n",
+ log[i].timestamp,log[i].latency, log[i].cmdtag, log[i].opcode,
+ log[i].fuse, log[i].psdt, log[i].cid, log[i].nsid,
+ log[i].slba_low, log[i].slba_high, log[i].nlb,
+ log[i].deac, log[i].prinfo, log[i].fua, log[i].lr);
+ }
+ printf("\n");
+ return err;
+}
+
+static int micron_latency_stats_info(int argc, char **argv, struct command *cmd,
+ struct plugin *plugin)
+{
+ const char *desc = "display command latency statistics";
+ const char *command = "command to display stats - all|read|write|trim"
+ "default is all";
+ int err = 0;
+ int fd = -1;
+ eDriveModel model = UNKNOWN_MODEL;
+ #define LATENCY_BUCKET_COUNT 32
+ struct micron_latency_stats {
+ uint64_t version; /* major << 32 | minior */
+ uint64_t all_cmds[LATENCY_BUCKET_COUNT];
+ uint64_t read_cmds[LATENCY_BUCKET_COUNT];
+ uint64_t write_cmds[LATENCY_BUCKET_COUNT];
+ uint64_t trim_cmds[LATENCY_BUCKET_COUNT];
+ uint32_t reserved[765]; /* round up to 4K */
+ } log;
+
+ struct latency_thresholds {
+ uint32_t start;
+ uint32_t end;
+ char *unit;
+ } thresholds[LATENCY_BUCKET_COUNT] = {
+ {0, 50, "us"}, {50, 100, "us"}, {100, 150, "us"}, {150, 200, "us"},
+ {200, 300, "us"}, {300, 400, "us"}, {400, 500, "us"}, {500, 600, "us"},
+ {600, 700, "us"}, {700, 800, "us"}, {800, 900, "us"}, {900, 1000, "us"},
+ {1, 5, "ms"}, {5, 10, "ms"}, {10, 20, "ms"}, {20, 50, "ms"}, {50, 100, "ms"},
+ {100, 200, "ms"}, {200, 300, "ms"}, {300, 400, "ms"}, {400, 500, "ms"},
+ {500, 600, "ms"}, {600, 700, "ms"}, {700, 800, "ms"}, {800, 900, "ms"},
+ {900, 1000, "ms"}, {1, 2, "s"}, {2, 3, "s"}, {3, 4, "s"}, {4, 5, "s"},
+ {5,8, "s"},
+ {8, INT_MAX, "s"},
+ };
+
+ struct {
+ char *command;
+ } opt = {
+ .command="all"
+ };
+
+ uint64_t *cmd_stats = &log.all_cmds[0];
+ char *cmd_str = "All";
+
+ OPT_ARGS(opts) = {
+ OPT_STRING("command", 'c', "command", &opt.command, command),
+ OPT_END()
+ };
+
+ if ((fd = micron_parse_options(argc, argv, desc, opts, &model)) < 0)
+ return err;
+ if (!strcmp(opt.command, "read")) {
+ cmd_stats = &log.read_cmds[0];
+ cmd_str = "Read";
+ } else if (!strcmp(opt.command, "write")) {
+ cmd_stats = &log.write_cmds[0];
+ cmd_str = "Write";
+ } else if (!strcmp(opt.command, "trim")) {
+ cmd_stats = &log.trim_cmds[0];
+ cmd_str = "Trim";
+ } else if (strcmp(opt.command, "all")) {
+ printf("Invalid command option %s to display latency stats\n", opt.command);
+ return -1;
+ }
+
+ memset(&log, 0, sizeof(log));
+ err = nvme_get_log_simple(fd, 0xD0, sizeof(log), &log);
+ if (err) {
+ if (err < 0)
+ printf("Unable to retrieve latency stats log the drive\n");
+ return err;
+ }
+ printf("Micron IO %s Command Latency Statistics\n"
+ "Major Revision : %d\nMinor Revision : %d\n",
+ cmd_str, (int)(log.version >> 32), (int)(log.version & 0xFFFFFFFF));
+ printf("=============================================\n");
+ printf("Bucket Start End Command Count\n");
+ printf("=============================================\n");
+
+ for (int b = 0; b < LATENCY_BUCKET_COUNT; b++) {
+ int bucket = b + 1;
+ char start[32] = { 0 };
+ char end[32] = { 0 };
+ sprintf(start, "%u%s", thresholds[b].start, thresholds[b].unit);
+ if (thresholds[b].end == INT_MAX)
+ sprintf(end, "INF");
+ else
+ sprintf(end, "%u%s", thresholds[b].end, thresholds[b].unit);
+ printf("%2d %8s %8s %8"PRIu64"\n",
+ bucket, start, end, cmd_stats[b]);
+ }
+ return err;
}
static int micron_ocp_smart_health_logs(int argc, char **argv, struct command *cmd,
@@ -2106,8 +2557,8 @@ static int micron_ocp_smart_health_logs(int argc, char **argv, struct command *c
__u8 nsze;
if ((err = nvme_identify_ctrl(fd, &ctrl)) == 0)
- err = nvme_get_log(fd, NVME_NSID_ALL, 0xFB, false, NVME_NO_LOG_LSP,
- FB_log_size, logFB);
+ err = nvme_get_log_simple(fd, 0xFB,
+ FB_log_size, logFB);
if (err) {
if (err < 0)
printf("Unable to retrieve smart log 0xFB for the drive\n");
@@ -2128,8 +2579,7 @@ static int micron_ocp_smart_health_logs(int argc, char **argv, struct command *c
goto out;
}
- err = nvme_get_log(fd, NVME_NSID_ALL, 0xC0, false, NVME_NO_LOG_LSP,
- C0_log_size, logC0);
+ err = nvme_get_log_simple(fd, 0xC0, C0_log_size, logC0);
if (err == 0) {
print_smart_cloud_health_log((__u8 *)logC0, is_json);
} else if (err < 0) {
@@ -2138,8 +2588,8 @@ static int micron_ocp_smart_health_logs(int argc, char **argv, struct command *c
out:
close(fd);
if (err > 0)
- nvme_show_status(err);
- return nvme_status_to_errno(err, false);
+ nvme_show_status(err);
+ return err;
}
static int micron_clr_fw_activation_history(int argc, char **argv,
@@ -2163,8 +2613,7 @@ static int micron_clr_fw_activation_history(int argc, char **argv,
return err;
}
- //err = nvme_set_feature(fd, 1, fid, cdw11, 0, opt.save, 0, 0, &result);
- err = nvme_set_feature(fd, 1, fid, 0, 0, 0, 0, 0, 0, &result);
+ err = nvme_set_features_simple(fd, fid, 1, 0, 0, &result);
if (err == 0) err = (int)result;
return err;
}
@@ -2210,22 +2659,64 @@ static int micron_telemetry_cntrl_option(int argc, char **argv,
}
if (!strcmp(opt.option, "enable")) {
- err = nvme_set_feature(fd, 1, fid, 1, 0, (opt.select & 0x1), 0, 0, 0, &result);
+ struct nvme_set_features_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .fid = fid,
+ .nsid = 1,
+ .cdw11 = 1,
+ .cdw12 = 0,
+ .save = (opt.select & 0x1),
+ .uuidx = 0,
+ .cdw15 = 0,
+ .data_len = 0,
+ .data = NULL,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+ err = nvme_set_features(&args);
if (err == 0) {
printf("successfully set controller telemetry option\n");
} else {
printf("Failed to set controller telemetry option\n");
}
} else if (!strcmp(opt.option, "disable")) {
- err = nvme_set_feature(fd, 1, fid, 0, 0, (opt.select & 0x1), 0, 0, 0, &result);
+ struct nvme_set_features_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .fid = fid,
+ .nsid = 1,
+ .cdw11 = 0,
+ .cdw12 = 0,
+ .save = (opt.select & 0x1),
+ .uuidx = 0,
+ .cdw15 = 0,
+ .data_len = 0,
+ .data = NULL,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+ err = nvme_set_features(&args);
if (err == 0) {
printf("successfully disabled controller telemetry option\n");
} else {
printf("Failed to disable controller telemetry option\n");
}
} else if (!strcmp(opt.option, "status")) {
- opt.select &= 0x3;
- err = nvme_get_feature(fd, 1, fid, opt.select, 0, 0, 0, 0, &result);
+ struct nvme_get_features_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .fid = fid,
+ .nsid = 1,
+ .sel = opt.select & 0x3,
+ .cdw11 = 0,
+ .uuidx = 0,
+ .data_len = 0,
+ .data = NULL,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+ err = nvme_get_features(&args);
if (err == 0) {
printf("Controller telemetry option : %s\n",
(result) ? "enabled" : "disabled");
@@ -2385,7 +2876,7 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd,
goto out;
}
int logSize = 0; __u8 *buffer = NULL; const char *dir = ".";
- err = micron_telemetry_log(fd, 0, cfg.log, &buffer, &logSize, cfg.data_area);
+ err = micron_telemetry_log(fd, cfg.log, &buffer, &logSize, cfg.data_area);
if (err == 0 && logSize > 0 && buffer != NULL) {
sprintf(msg, "telemetry log: 0x%X", cfg.log);
WriteData(buffer, logSize, dir, cfg.package, msg);
@@ -2397,10 +2888,10 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd,
printf("Preparing log package. This will take a few seconds...\n");
- // trim spaces out of serial number string */
+ /* trim spaces out of serial number string */
int i, j = 0;
for (i = 0; i < sizeof(ctrl.sn); i++) {
- if (isblank(ctrl.sn[i]))
+ if (isblank((int)ctrl.sn[i]))
continue;
sn[j++] = ctrl.sn[i];
}
@@ -2420,8 +2911,7 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd,
GetSmartlogData(fd, strCtrlDirName);
GetErrorlogData(fd, ctrl.elpe, strCtrlDirName);
GetGenericLogs(fd, strCtrlDirName);
-
- // pull if telemetry log data is supported
+ /* pull if telemetry log data is supported */
if ((ctrl.lpa & 0x8) == 0x8)
GetTelemetryData(fd, strCtrlDirName);
@@ -2465,8 +2955,8 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd,
if (eModel == M5410 || eModel == M5407)
err = NVMEGetLogPage(fd, aVendorLogs[i].ucLogPage, dataBuffer, bSize);
else
- err = nvme_get_log(fd, NVME_NSID_ALL, aVendorLogs[i].ucLogPage,
- false, NVME_NO_LOG_LSP, bSize, dataBuffer);
+ err = nvme_get_log_simple(fd, aVendorLogs[i].ucLogPage,
+ bSize, dataBuffer);
}
break;
@@ -2484,14 +2974,14 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd,
break;
}
memset(dataBuffer, 0, bSize);
- err = nvme_get_log(fd, NVME_NSID_ALL, aVendorLogs[i].ucLogPage,
- false, NVME_NO_LOG_LSP, bSize, dataBuffer);
+ err = nvme_get_log_simple(fd, aVendorLogs[i].ucLogPage,
+ bSize, dataBuffer);
maxSize = aVendorLogs[i].nMaxSize - bSize;
while (err == 0 && maxSize > 0 && ((unsigned int *)dataBuffer)[0] != 0xdeadbeef) {
sprintf(msg, "log 0x%x", aVendorLogs[i].ucLogPage);
WriteData(dataBuffer, bSize, strCtrlDirName, aVendorLogs[i].strFileName, msg);
- err = nvme_get_log(fd, NVME_NSID_ALL, aVendorLogs[i].ucLogPage,
- false, NVME_NO_LOG_LSP, bSize, dataBuffer);
+ err = nvme_get_log_simple(fd, aVendorLogs[i].ucLogPage,
+ bSize, dataBuffer);
if (err || (((unsigned int *)dataBuffer)[0] == 0xdeadbeef))
break;
maxSize -= bSize;
diff --git a/plugins/micron/micron-nvme.h b/plugins/micron/micron-nvme.h
index be80544..c1b224e 100644
--- a/plugins/micron/micron-nvme.h
+++ b/plugins/micron/micron-nvme.h
@@ -13,14 +13,17 @@ PLUGIN(NAME("micron", "Micron vendor specific extensions", NVME_VERSION),
ENTRY("vs-pcie-stats", "Retrieve Micron PCIe error stats", micron_pcie_stats)
ENTRY("clear-pcie-correctable-errors", "Clear correctable PCIe errors", micron_clear_pcie_correctable_errors)
ENTRY("vs-internal-log", "Retrieve Micron logs", micron_internal_logs)
- ENTRY("vs-telemetry-controller-option", "Enable/Disable controller telemetry log generation", micron_telemetry_cntrl_option)
+ ENTRY("vs-telemetry-controller-option", "Enable/Disable controller telemetry log generation", micron_telemetry_cntrl_option)
ENTRY("vs-nand-stats", "Retrieve NAND Stats", micron_nand_stats)
+ ENTRY("vs-smart-ext-log", "Retrieve extended SMART logs", micron_smart_ext_log)
ENTRY("vs-drive-info", "Retrieve Drive information", micron_drive_info)
ENTRY("plugin-version", "Display plugin version info", micron_plugin_version)
ENTRY("cloud-SSD-plugin-version", "Display plugin version info", micron_cloud_ssd_plugin_version)
ENTRY("log-page-directory", "Retrieve log page directory", micron_logpage_dir)
ENTRY("vs-fw-activate-history", "Display FW activation history", micron_fw_activation_history)
- ENTRY("vs-error-reason-identifier", "Retrieve Error reason", micron_error_reason)
+ ENTRY("latency-tracking", "Latency monitoring feature control", micron_latency_stats_track)
+ ENTRY("latency-stats", "Latency information for tracked commands", micron_latency_stats_info)
+ ENTRY("latency-logs", "Latency log details tracked by drive", micron_latency_stats_logs)
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)
diff --git a/plugins/netapp/netapp-nvme.c b/plugins/netapp/netapp-nvme.c
index 15c3923..9630442 100644
--- a/plugins/netapp/netapp-nvme.c
+++ b/plugins/netapp/netapp-nvme.c
@@ -21,12 +21,13 @@
#include <unistd.h>
#include <errno.h>
#include <string.h>
-#include <sys/ioctl.h>
+#include <uuid/uuid.h>
+#include "common.h"
#include "nvme.h"
-#include "nvme-ioctl.h"
+#include "libnvme.h"
-#include "suffix.h"
+#include "util/suffix.h"
#define CREATE_CMD
#include "netapp-nvme.h"
@@ -56,17 +57,17 @@ enum {
static const char *dev_path = "/dev/";
struct smdevice_info {
- int nsid;
+ unsigned nsid;
struct nvme_id_ctrl ctrl;
struct nvme_id_ns ns;
char dev[265];
};
struct ontapdevice_info {
- int nsid;
+ unsigned nsid;
struct nvme_id_ctrl ctrl;
struct nvme_id_ns ns;
- char nsdesc[4096];
+ uuid_t uuid;
unsigned char log_data[ONTAP_C2_LOG_SIZE];
char dev[265];
};
@@ -105,24 +106,15 @@ static void netapp_nguid_to_str(char *str, __u8 *nguid)
static void netapp_get_ns_size(char *size, long long *lba,
struct nvme_id_ns *ns)
{
- *lba = 1 << ns->lbaf[(ns->flbas & 0x0F)].ds;
+ __u8 lba_index;
+ nvme_id_ns_flbas_to_lbaf_inuse(ns->flbas, &lba_index);
+ *lba = 1 << ns->lbaf[lba_index].ds;
double nsze = le64_to_cpu(ns->nsze) * (*lba);
const char *s_suffix = suffix_si_get(&nsze);
sprintf(size, "%.2f%sB", nsze, s_suffix);
}
-static void netapp_uuid_to_str(char *str, void *data)
-{
-#ifdef LIBUUID
- uuid_t uuid;
- struct nvme_ns_id_desc *desc = data;
-
- memcpy(uuid, data + sizeof(*desc), 16);
- uuid_unparse_lower(uuid, str);
-#endif
-}
-
static void ontap_labels_to_str(char *dst, char *src, int count)
{
int i;
@@ -249,6 +241,7 @@ static void netapp_smdevices_print(struct smdevice_info *devices, int count, int
"Volume ID %s, Controller %c, Access State %s, %s\n";
char columnstr[] = "%-16s %-30s %-30s %4d %32s %c %-12s %9s\n";
char *formatstr = basestr; /* default to "normal" output format */
+ __u8 lba_index;
if (format == NCOLUMN) {
/* for column output, change output string and print column headers */
@@ -265,11 +258,12 @@ static void netapp_smdevices_print(struct smdevice_info *devices, int count, int
else if (format == NJSON) {
/* prepare for json output */
root = json_create_object();
- json_devices = json_create_object();
+ json_devices = json_create_array();
}
for (i = 0; i < count; i++) {
- long long int lba = 1 << devices[i].ns.lbaf[(devices[i].ns.flbas & 0x0F)].ds;
+ nvme_id_ns_flbas_to_lbaf_inuse(devices[i].ns.flbas, &lba_index);
+ long long int lba = 1 << devices[i].ns.lbaf[lba_index].ds;
double nsze = le64_to_cpu(devices[i].ns.nsze) * lba;
const char *s_suffix = suffix_si_get(&nsze);
char size[128];
@@ -296,6 +290,8 @@ static void netapp_smdevices_print(struct smdevice_info *devices, int count, int
/* complete the json output */
json_object_add_value_array(root, "SMdevices", json_devices);
json_print_object(root, NULL);
+ printf("\n");
+ json_free_object(root);
}
}
@@ -331,13 +327,13 @@ static void netapp_ontapdevices_print(struct ontapdevice_info *devices,
} else if (format == NJSON) {
/* prepare for json output */
root = json_create_object();
- json_devices = json_create_object();
+ json_devices = json_create_array();
}
for (i = 0; i < count; i++) {
netapp_get_ns_size(size, &lba, &devices[i].ns);
- netapp_uuid_to_str(uuid_str, devices[i].nsdesc);
+ uuid_unparse_lower(devices[i].uuid, uuid_str);
netapp_get_ontap_labels(vsname, nspath, devices[i].log_data);
if (format == NJSON) {
@@ -354,16 +350,18 @@ static void netapp_ontapdevices_print(struct ontapdevice_info *devices,
/* complete the json output */
json_object_add_value_array(root, "ONTAPdevices", json_devices);
json_print_object(root, NULL);
+ printf("\n");
+ json_free_object(root);
}
}
static int nvme_get_ontap_c2_log(int fd, __u32 nsid, void *buf, __u32 buflen)
{
- struct nvme_admin_cmd get_log;
+ struct nvme_passthru_cmd get_log;
int err;
memset(buf, 0, buflen);
- memset(&get_log, 0, sizeof(struct nvme_admin_cmd));
+ memset(&get_log, 0, sizeof(struct nvme_passthru_cmd));
get_log.opcode = nvme_admin_get_log_page;
get_log.nsid = nsid;
@@ -378,7 +376,7 @@ static int nvme_get_ontap_c2_log(int fd, __u32 nsid, void *buf, __u32 buflen)
get_log.cdw10 |= ONTAP_C2_LOG_NSINFO_LSP << 8;
get_log.cdw11 = numdu;
- err = nvme_submit_admin_passthru(fd, &get_log);
+ err = nvme_submit_admin_passthru(fd, &get_log, NULL);
if (err) {
fprintf(stderr, "ioctl error %0x\n", err);
return 1;
@@ -402,8 +400,8 @@ static int netapp_smdevices_get_info(int fd, struct smdevice_info *item,
if (strncmp("NetApp E-Series", item->ctrl.mn, 15) != 0)
return 0; /* not the right model of controller */
- item->nsid = nvme_get_nsid(fd);
- err = nvme_identify_ns(fd, item->nsid, 0, &item->ns);
+ err = nvme_get_nsid(fd, &item->nsid);
+ err = nvme_identify_ns(fd, item->nsid, &item->ns);
if (err) {
fprintf(stderr, "Unable to identify namespace for %s (%s)\n",
dev, strerror(err));
@@ -418,6 +416,7 @@ static int netapp_ontapdevices_get_info(int fd, struct ontapdevice_info *item,
const char *dev)
{
int err;
+ void *nsdescs;
err = nvme_identify_ctrl(fd, &item->ctrl);
if (err) {
@@ -430,22 +429,30 @@ static int netapp_ontapdevices_get_info(int fd, struct ontapdevice_info *item,
/* not the right controller model */
return 0;
- item->nsid = nvme_get_nsid(fd);
+ err = nvme_get_nsid(fd, &item->nsid);
- err = nvme_identify_ns(fd, item->nsid, 0, &item->ns);
+ err = nvme_identify_ns(fd, item->nsid, &item->ns);
if (err) {
fprintf(stderr, "Unable to identify namespace for %s (%s)\n",
dev, strerror(err));
return 0;
}
- err = nvme_identify_ns_descs(fd, item->nsid, item->nsdesc);
+ if (posix_memalign(&nsdescs, getpagesize(), 0x1000)) {
+ fprintf(stderr, "Cannot allocate controller list payload\n");
+ return 0;
+ }
+
+ err = nvme_identify_ns_descs(fd, item->nsid, nsdescs);
if (err) {
fprintf(stderr, "Unable to identify namespace descriptor for %s (%s)\n",
dev, strerror(err));
return 0;
}
+ memcpy(item->uuid, nsdescs + sizeof(struct nvme_ns_id_desc), sizeof(item->uuid));
+ free(nsdescs);
+
err = nvme_get_ontap_c2_log(fd, item->nsid, item->log_data, ONTAP_C2_LOG_SIZE);
if (err) {
fprintf(stderr, "Unable to get log page data for %s (%s)\n",
diff --git a/plugins/nvidia/nvidia-nvme.c b/plugins/nvidia/nvidia-nvme.c
index cdf51ab..8ddd16f 100644
--- a/plugins/nvidia/nvidia-nvme.c
+++ b/plugins/nvidia/nvidia-nvme.c
@@ -5,17 +5,11 @@
#include <unistd.h>
#include <inttypes.h>
-#include "linux/nvme_ioctl.h"
-
#include "common.h"
#include "nvme.h"
-#include "nvme-print.h"
-#include "nvme-ioctl.h"
+#include "libnvme.h"
#include "plugin.h"
-#include "argconfig.h"
-#include "suffix.h"
-
#define CREATE_CMD
#include "nvidia-nvme.h"
diff --git a/plugins/ocp/ocp-nvme.c b/plugins/ocp/ocp-nvme.c
new file mode 100644
index 0000000..6b7fc9d
--- /dev/null
+++ b/plugins/ocp/ocp-nvme.c
@@ -0,0 +1,788 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2022 Meta Platforms, Inc.
+ *
+ * Authors: Arthur Shau <arthurshau@fb.com>,
+ * Wei Zhang <wzhang@fb.com>,
+ * Venkat Ramesh <venkatraghavan@fb.com>
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "nvme.h"
+#include "libnvme.h"
+#include "plugin.h"
+#include "linux/types.h"
+#include "nvme-print.h"
+
+#define CREATE_CMD
+#include "ocp-nvme.h"
+
+/* C0 SCAO Log Page */
+#define C0_SMART_CLOUD_ATTR_LEN 0x200
+#define C0_SMART_CLOUD_ATTR_OPCODE 0xC0
+#define C0_GUID_LENGTH 16
+#define C0_ACTIVE_BUCKET_TIMER_INCREMENT 5
+#define C0_ACTIVE_THRESHOLD_INCREMENT 5
+#define C0_MINIMUM_WINDOW_INCREMENT 100
+
+static __u8 scao_guid[C0_GUID_LENGTH] = { 0xC5, 0xAF, 0x10, 0x28, 0xEA, 0xBF,
+ 0xF2, 0xA4, 0x9C, 0x4F, 0x6F, 0x7C, 0xC9, 0x14, 0xD5, 0xAF };
+
+/* C3 Latency Monitor Log Page */
+#define C3_LATENCY_MON_LOG_BUF_LEN 0x200
+#define C3_LATENCY_MON_OPCODE 0xC3
+#define C3_LATENCY_MON_VERSION 0x0001
+#define C3_GUID_LENGTH 16
+static __u8 lat_mon_guid[C3_GUID_LENGTH] = { 0x92, 0x7a, 0xc0, 0x8c, 0xd0, 0x84,
+ 0x6c, 0x9c, 0x70, 0x43, 0xe6, 0xd4, 0x58, 0x5e, 0xd4, 0x85 };
+
+#define READ 0
+#define WRITE 1
+#define TRIM 2
+#define RESERVED 3
+
+typedef enum {
+ SCAO_PMUW = 0, /* Physical media units written */
+ SCAO_PMUR = 16, /* Physical media units read */
+ SCAO_BUNBR = 32, /* Bad user nand blocks raw */
+ SCAO_BUNBN = 38, /* Bad user nand blocks normalized */
+ SCAO_BSNBR = 40, /* Bad system nand blocks raw */
+ SCAO_BSNBN = 46, /* Bad system nand blocks normalized */
+ SCAO_XRC = 48, /* XOR recovery count */
+ SCAO_UREC = 56, /* Uncorrectable read error count */
+ SCAO_SEEC = 64, /* Soft ecc error count */
+ SCAO_EECE = 72, /* End to end corrected errors */
+ SCAO_EEDC = 76, /* End to end detected errors */
+ SCAO_SDPU = 80, /* System data percent used */
+ SCAO_RFSC = 81, /* Refresh counts */
+ SCAO_MXUDEC = 88, /* Max User data erase counts */
+ SCAO_MNUDEC = 92, /* Min User data erase counts */
+ SCAO_NTTE = 96, /* Number of Thermal throttling events */
+ SCAO_CTS = 97, /* Current throttling status */
+ SCAO_EVF = 98, /* Errata Version Field */
+ SCAO_PVF = 99, /* Point Version Field */
+ SCAO_MIVF = 101, /* Minor Version Field */
+ SCAO_MAVF = 103, /* Major Version Field */
+ SCAO_PCEC = 104, /* PCIe correctable error count */
+ SCAO_ICS = 112, /* Incomplete shutdowns */
+ SCAO_PFB = 120, /* Percent free blocks */
+ SCAO_CPH = 128, /* Capacitor health */
+ SCAO_NEV = 130, /* NVMe Errata Version */
+ SCAO_UIO = 136, /* Unaligned I/O */
+ SCAO_SVN = 144, /* Security Version Number */
+ SCAO_NUSE = 152, /* NUSE - Namespace utilization */
+ SCAO_PSC = 160, /* PLP start count */
+ SCAO_EEST = 176, /* Endurance estimate */
+ SCAO_PLRC = 192, /* PCIe Link Retraining Count */
+ SCAO_LPV = 494, /* Log page version */
+ SCAO_LPG = 496, /* Log page GUID */
+} SMART_CLOUD_ATTRIBUTE_OFFSETS;
+
+struct __attribute__((__packed__)) ssd_latency_monitor_log {
+ __u8 feature_status; /* 0x00 */
+ __u8 rsvd1; /* 0x01 */
+ __le16 active_bucket_timer; /* 0x02 */
+ __le16 active_bucket_timer_threshold; /* 0x04 */
+ __u8 active_threshold_a; /* 0x06 */
+ __u8 active_threshold_b; /* 0x07 */
+ __u8 active_threshold_c; /* 0x08 */
+ __u8 active_threshold_d; /* 0x09 */
+ __le16 active_latency_config; /* 0x0A */
+ __u8 active_latency_min_window; /* 0x0C */
+ __u8 rsvd2[0x13]; /* 0x0D */
+
+ __le32 active_bucket_counter[4][4] ; /* 0x20 - 0x5F */
+ __le64 active_latency_timestamp[4][3]; /* 0x60 - 0xBF */
+ __le16 active_measured_latency[4][3]; /* 0xC0 - 0xD7 */
+ __le16 active_latency_stamp_units; /* 0xD8 */
+ __u8 rsvd3[0x16]; /* 0xDA */
+
+ __le32 static_bucket_counter[4][4] ; /* 0xF0 - 0x12F */
+ __le64 static_latency_timestamp[4][3]; /* 0x130 - 0x18F */
+ __le16 static_measured_latency[4][3]; /* 0x190 - 0x1A7 */
+ __le16 static_latency_stamp_units; /* 0x1A8 */
+ __u8 rsvd4[0x16]; /* 0x1AA */
+
+ __le16 debug_log_trigger_enable; /* 0x1C0 */
+ __le16 debug_log_measured_latency; /* 0x1C2 */
+ __le64 debug_log_latency_stamp; /* 0x1C4 */
+ __le16 debug_log_ptr; /* 0x1CC */
+ __le16 debug_log_counter_trigger; /* 0x1CE */
+ __u8 debug_log_stamp_units; /* 0x1D0 */
+ __u8 rsvd5[0x1D]; /* 0x1D1 */
+
+ __le16 log_page_version; /* 0x1EE */
+ __u8 log_page_guid[0x10]; /* 0x1F0 */
+};
+
+static long double int128_to_double(__u8 *data)
+{
+ int i;
+ long double result = 0;
+
+ for (i = 0; i < 16; i++) {
+ result *= 256;
+ result += data[15 - i];
+ }
+ return result;
+}
+
+static int convert_ts(time_t time, char *ts_buf)
+{
+ struct tm gmTimeInfo;
+ time_t time_Human, time_ms;
+ char buf[80];
+
+ time_Human = time/1000;
+ time_ms = time % 1000;
+
+ gmtime_r((const time_t *)&time_Human, &gmTimeInfo);
+
+ strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &gmTimeInfo);
+ sprintf(ts_buf, "%s.%03ld GMT", buf, time_ms);
+
+ return 0;
+}
+
+static void ocp_print_C0_log_normal(void *data)
+{
+ __u8 *log_data = (__u8*)data;
+ uint16_t smart_log_ver = 0;
+
+ printf("SMART Cloud Attributes :- \n");
+
+ printf(" Physical media units written - %"PRIu64" %"PRIu64"\n",
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW+8] & 0xFFFFFFFFFFFFFFFF),
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW] & 0xFFFFFFFFFFFFFFFF));
+ printf(" Physical media units read - %"PRIu64" %"PRIu64"\n",
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR+8] & 0xFFFFFFFFFFFFFFFF),
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR] & 0xFFFFFFFFFFFFFFFF));
+ printf(" Bad user nand blocks - Raw %"PRIu64"\n",
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BUNBR] & 0x0000FFFFFFFFFFFF));
+ printf(" Bad user nand blocks - Normalized %d\n",
+ (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BUNBN]));
+ printf(" Bad system nand blocks - Raw %"PRIu64"\n",
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BSNBR] & 0x0000FFFFFFFFFFFF));
+ printf(" Bad system nand blocks - Normalized %d\n",
+ (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BSNBN]));
+ printf(" XOR recovery count %"PRIu64"\n",
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_XRC]));
+ printf(" Uncorrectable read error count %"PRIu64"\n",
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UREC]));
+ printf(" Soft ecc error count %"PRIu64"\n",
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SEEC]));
+ printf(" End to end corrected errors %"PRIu32"\n",
+ (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EECE]));
+ printf(" End to end detected errors %"PRIu32"\n",
+ (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EEDC]));
+ printf(" System data percent used %d\n",
+ (__u8)log_data[SCAO_SDPU]);
+ printf(" Refresh counts %"PRIu64"\n",
+ (uint64_t)(le64_to_cpu(*(uint64_t *)&log_data[SCAO_RFSC])& 0x00FFFFFFFFFFFFFF));
+ printf(" Max User data erase counts %"PRIu32"\n",
+ (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MXUDEC]));
+ printf(" Min User data erase counts %"PRIu32"\n",
+ (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MNUDEC]));
+ printf(" Number of Thermal throttling events %d\n",
+ (__u8)log_data[SCAO_NTTE]);
+ printf(" Current throttling status 0x%x\n",
+ (__u8)log_data[SCAO_CTS]);
+ printf(" PCIe correctable error count %"PRIu64"\n",
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PCEC]));
+ printf(" Incomplete shutdowns %"PRIu32"\n",
+ (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_ICS]));
+ printf(" Percent free blocks %d\n",
+ (__u8)log_data[SCAO_PFB]);
+ printf(" Capacitor health %"PRIu16"\n",
+ (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_CPH]));
+ printf(" Unaligned I/O %"PRIu64"\n",
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UIO]));
+ printf(" Security Version Number %"PRIu64"\n",
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SVN]));
+ printf(" NUSE - Namespace utilization %"PRIu64"\n",
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_NUSE]));
+ printf(" PLP start count %.0Lf\n",
+ int128_to_double(&log_data[SCAO_PSC]));
+ printf(" Endurance estimate %.0Lf\n",
+ int128_to_double(&log_data[SCAO_EEST]));
+ smart_log_ver = (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_LPV]);
+ printf(" Log page version %"PRIu16"\n",smart_log_ver);
+ printf(" Log page GUID 0x");
+ printf("%"PRIx64"%"PRIx64"\n",(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG + 8]),
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG]));
+ if(smart_log_ver > 2) {
+ printf(" Errata Version Field %d\n",
+ (__u8)log_data[SCAO_EVF]);
+ printf(" Point Version Field %"PRIu16"\n",
+ (uint16_t)log_data[SCAO_PVF]);
+ printf(" Minor Version Field %"PRIu16"\n",
+ (uint16_t)log_data[SCAO_MIVF]);
+ printf(" Major Version Field %d\n",
+ (__u8)log_data[SCAO_MAVF]);
+ printf(" NVMe Errata Version %d\n",
+ (__u8)log_data[SCAO_NEV]);
+ printf(" PCIe Link Retraining Count %"PRIu64"\n",
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PLRC]));
+ }
+ printf("\n");
+}
+
+static void ocp_print_C0_log_json(void *data)
+{
+ __u8 *log_data = (__u8*)data;
+ struct json_object *root;
+ struct json_object *pmuw;
+ struct json_object *pmur;
+ uint16_t smart_log_ver = 0;
+
+ root = json_create_object();
+ pmuw = json_create_object();
+ pmur = json_create_object();
+
+ json_object_add_value_uint64(pmuw, "hi",
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW+8] & 0xFFFFFFFFFFFFFFFF));
+ json_object_add_value_uint64(pmuw, "lo",
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW] & 0xFFFFFFFFFFFFFFFF));
+ json_object_add_value_object(root, "Physical media units written", pmuw);
+ json_object_add_value_uint64(pmur, "hi",
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR+8] & 0xFFFFFFFFFFFFFFFF));
+ json_object_add_value_uint64(pmur, "lo",
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR] & 0xFFFFFFFFFFFFFFFF));
+ json_object_add_value_object(root, "Physical media units read", pmur);
+ json_object_add_value_uint64(root, "Bad user nand blocks - Raw",
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BUNBR] & 0x0000FFFFFFFFFFFF));
+ json_object_add_value_uint(root, "Bad user nand blocks - Normalized",
+ (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BUNBN]));
+ json_object_add_value_uint64(root, "Bad system nand blocks - Raw",
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BSNBR] & 0x0000FFFFFFFFFFFF));
+ json_object_add_value_uint(root, "Bad system nand blocks - Normalized",
+ (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BSNBN]));
+ json_object_add_value_uint64(root, "XOR recovery count",
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_XRC]));
+ json_object_add_value_uint64(root, "Uncorrectable read error count",
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UREC]));
+ json_object_add_value_uint64(root, "Soft ecc error count",
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SEEC]));
+ json_object_add_value_uint(root, "End to end corrected errors",
+ (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EECE]));
+ json_object_add_value_uint(root, "End to end detected errors",
+ (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EEDC]));
+ json_object_add_value_uint(root, "System data percent used",
+ (__u8)log_data[SCAO_SDPU]);
+ json_object_add_value_uint64(root, "Refresh counts",
+ (uint64_t)(le64_to_cpu(*(uint64_t *)&log_data[SCAO_RFSC])& 0x00FFFFFFFFFFFFFF));
+ json_object_add_value_uint(root, "Max User data erase counts",
+ (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MXUDEC]));
+ json_object_add_value_uint(root, "Min User data erase counts",
+ (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MNUDEC]));
+ json_object_add_value_uint(root, "Number of Thermal throttling events",
+ (__u8)log_data[SCAO_NTTE]);
+ json_object_add_value_uint(root, "Current throttling status",
+ (__u8)log_data[SCAO_CTS]);
+ json_object_add_value_uint64(root, "PCIe correctable error count",
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PCEC]));
+ json_object_add_value_uint(root, "Incomplete shutdowns",
+ (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_ICS]));
+ json_object_add_value_uint(root, "Percent free blocks",
+ (__u8)log_data[SCAO_PFB]);
+ json_object_add_value_uint(root, "Capacitor health",
+ (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_CPH]));
+ json_object_add_value_uint64(root, "Unaligned I/O",
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UIO]));
+ json_object_add_value_uint64(root, "Security Version Number",
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SVN]));
+ json_object_add_value_uint64(root, "NUSE - Namespace utilization",
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_NUSE]));
+ json_object_add_value_uint(root, "PLP start count",
+ int128_to_double(&log_data[SCAO_PSC]));
+ json_object_add_value_uint64(root, "Endurance estimate",
+ int128_to_double(&log_data[SCAO_EEST]));
+ smart_log_ver = (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_LPV]);
+ json_object_add_value_uint(root, "Log page version", smart_log_ver);
+ char guid[40];
+ memset((void*)guid, 0, 40);
+ sprintf((char*)guid, "0x%"PRIx64"%"PRIx64"",(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG + 8]),
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG]));
+ json_object_add_value_string(root, "Log page GUID", guid);
+ if(smart_log_ver > 2){
+ json_object_add_value_uint(root, "Errata Version Field",
+ (__u8)log_data[SCAO_EVF]);
+ json_object_add_value_uint(root, "Point Version Field",
+ (uint16_t)log_data[SCAO_PVF]);
+ json_object_add_value_uint(root, "Minor Version Field",
+ (uint16_t)log_data[SCAO_MIVF]);
+ json_object_add_value_uint(root, "Major Version Field",
+ (__u8)log_data[SCAO_MAVF]);
+ json_object_add_value_uint(root, "NVMe Errata Version",
+ (__u8)log_data[SCAO_NEV]);
+ json_object_add_value_uint(root, "PCIe Link Retraining Count",
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PLRC]));
+ }
+ json_print_object(root, NULL);
+ printf("\n");
+ json_free_object(root);
+}
+
+static int get_c0_log_page(int fd, char *format)
+{
+ int ret = 0;
+ int fmt = -1;
+ __u8 *data;
+ int i;
+
+ fmt = validate_output_format(format);
+ if (fmt < 0) {
+ fprintf(stderr, "ERROR : OCP : invalid output format\n");
+ return fmt;
+ }
+
+ if ((data = (__u8 *) malloc(sizeof(__u8) * C0_SMART_CLOUD_ATTR_LEN)) == NULL) {
+ fprintf(stderr, "ERROR : OCP : malloc : %s\n", strerror(errno));
+ return -1;
+ }
+ memset(data, 0, sizeof (__u8) * C0_SMART_CLOUD_ATTR_LEN);
+
+ ret = nvme_get_log_simple(fd, C0_SMART_CLOUD_ATTR_OPCODE,
+ C0_SMART_CLOUD_ATTR_LEN, data);
+
+ if (strcmp(format, "json"))
+ fprintf(stderr, "NVMe Status:%s(%x)\n",
+ nvme_status_to_string(ret, false), ret);
+
+ if (ret == 0) {
+
+ /* check log page guid */
+ /* Verify GUID matches */
+ for (i=0; i<16; i++) {
+ if (scao_guid[i] != data[SCAO_LPG + i]) {
+ fprintf(stderr, "ERROR : OCP : Unknown GUID in C0 Log Page data\n");
+ int j;
+ fprintf(stderr, "ERROR : OCP : Expected GUID: 0x");
+ for (j = 0; j<16; j++) {
+ fprintf(stderr, "%x", scao_guid[j]);
+ }
+ fprintf(stderr, "\nERROR : OCP : Actual GUID: 0x");
+ for (j = 0; j<16; j++) {
+ fprintf(stderr, "%x", data[SCAO_LPG + j]);
+ }
+ fprintf(stderr, "\n");
+
+ ret = -1;
+ goto out;
+ }
+ }
+
+ /* print the data */
+ if (!data) {
+ fprintf(stderr, "ERROR : OCP : Invalid buffer to read 0xC0 log\n");
+ ret = -1;
+ goto out;
+ }
+ switch (fmt) {
+ case NORMAL:
+ ocp_print_C0_log_normal(data);
+ break;
+ case JSON:
+ ocp_print_C0_log_json(data);
+ break;
+ }
+ } else {
+ fprintf(stderr, "ERROR : OCP : Unable to read C0 data from buffer\n");
+ }
+
+out:
+ free(data);
+ return ret;
+}
+
+static int ocp_smart_add_log(int argc, char **argv, struct command *cmd,
+ struct plugin *plugin)
+{
+ const char *desc = "Retrieve latency monitor log data.";
+ int fd;
+ int ret = 0;
+
+ struct config {
+ char *output_format;
+ };
+
+ struct config cfg = {
+ .output_format = "normal",
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_FMT("output-format", 'o', &cfg.output_format, "output Format: normal|json"),
+ OPT_END()
+ };
+
+ fd = parse_and_open(argc, argv, desc, opts);
+ if (fd < 0)
+ return fd;
+
+ ret = get_c0_log_page(fd, cfg.output_format);
+ if (ret)
+ fprintf(stderr, "ERROR : OCP : Failure reading the C0 Log Page, ret = %d\n",
+ ret);
+
+ return ret;
+}
+
+static int ocp_print_C3_log_normal(int fd, struct ssd_latency_monitor_log *log_data)
+{
+ printf("-Latency Monitor/C3 Log Page Data- \n");
+ printf(" Controller : %s\n", devicename);
+ int i, j;
+ int pos = 0;
+ char ts_buf[128];
+
+ printf(" Feature Status 0x%x \n",
+ log_data->feature_status);
+ printf(" Active Bucket Timer %d min \n",
+ C0_ACTIVE_BUCKET_TIMER_INCREMENT *
+ le16_to_cpu(log_data->active_bucket_timer));
+ printf(" Active Bucket Timer Threshold %d min \n",
+ C0_ACTIVE_BUCKET_TIMER_INCREMENT *
+ le16_to_cpu(log_data->active_bucket_timer_threshold));
+ printf(" Active Threshold A %d ms \n",
+ C0_ACTIVE_THRESHOLD_INCREMENT *
+ le16_to_cpu(log_data->active_threshold_a+1));
+ printf(" Active Threshold B %d ms \n",
+ C0_ACTIVE_THRESHOLD_INCREMENT *
+ le16_to_cpu(log_data->active_threshold_b+1));
+ printf(" Active Threshold C %d ms \n",
+ C0_ACTIVE_THRESHOLD_INCREMENT *
+ le16_to_cpu(log_data->active_threshold_c+1));
+ printf(" Active Threshold D %d ms \n",
+ C0_ACTIVE_THRESHOLD_INCREMENT *
+ le16_to_cpu(log_data->active_threshold_d+1));
+ printf(" Active Latency Minimum Window %d ms \n",
+ C0_MINIMUM_WINDOW_INCREMENT *
+ le16_to_cpu(log_data->active_latency_min_window));
+ printf(" Active Latency Stamp Units %d \n",
+ le16_to_cpu(log_data->active_latency_stamp_units));
+ printf(" Static Latency Stamp Units %d \n",
+ le16_to_cpu(log_data->static_latency_stamp_units));
+ printf(" Debug Log Trigger Enable %d \n",
+ le16_to_cpu(log_data->debug_log_trigger_enable));
+
+ printf(" Read Write Deallocate/Trim \n");
+ for (i = 0; i <= 3; i++) {
+ printf(" Active Latency Mode: Bucket %d %27d %27d %27d \n",
+ i,
+ log_data->active_latency_config & (1 << pos),
+ log_data->active_latency_config & (1 << pos),
+ log_data->active_latency_config & (1 << pos));
+ }
+ printf("\n");
+ for (i = 0; i <= 3; i++) {
+ printf(" Active Bucket Counter: Bucket %d %27d %27d %27d \n",
+ i,
+ le32_to_cpu(log_data->active_bucket_counter[i][READ]),
+ le32_to_cpu(log_data->active_bucket_counter[i][WRITE]),
+ le32_to_cpu(log_data->active_bucket_counter[i][TRIM]));
+ }
+
+ for (i = 0; i <= 3; i++) {
+ printf(" Active Measured Latency: Bucket %d %27d ms %27d ms %27d ms \n",
+ i,
+ le16_to_cpu(log_data->active_measured_latency[i][READ]),
+ le16_to_cpu(log_data->active_measured_latency[i][WRITE]),
+ le16_to_cpu(log_data->active_measured_latency[i][TRIM]));
+ }
+
+ for (i = 0; i <= 3; i++) {
+ printf(" Active Latency Time Stamp: Bucket %d ", i);
+ for (j = 0; j <= 2; j++) {
+ if (le64_to_cpu(log_data->active_latency_timestamp[i][j]) == -1)
+ printf(" N/A ");
+ else {
+ convert_ts(le64_to_cpu(log_data->active_latency_timestamp[i][j]), ts_buf);
+ printf("%s ", ts_buf);
+ }
+ }
+ printf("\n");
+ }
+
+ for (i = 0; i <= 3; i++) {
+ printf(" Static Bucket Counter: Bucket %d %27d %27d %27d \n",
+ i,
+ le32_to_cpu(log_data->static_bucket_counter[i][READ]),
+ le32_to_cpu(log_data->static_bucket_counter[i][WRITE]),
+ le32_to_cpu(log_data->static_bucket_counter[i][TRIM]));
+ }
+
+ for (i = 0; i <= 3; i++) {
+ printf(" Static Measured Latency: Bucket %d %27d ms %27d ms %27d ms \n",
+ i,
+ le16_to_cpu(log_data->static_measured_latency[i][READ]),
+ le16_to_cpu(log_data->static_measured_latency[i][WRITE]),
+ le16_to_cpu(log_data->static_measured_latency[i][TRIM]));
+ }
+
+ for (i = 0; i <= 3; i++) {
+ printf(" Static Latency Time Stamp: Bucket %d ", i);
+ for (j = 0; j <= 2; j++) {
+ if (le64_to_cpu(log_data->static_latency_timestamp[i][j]) == -1)
+ printf(" N/A ");
+ else {
+ convert_ts(le64_to_cpu(log_data->static_latency_timestamp[i][j]), ts_buf);
+ printf("%s ", ts_buf);
+ }
+ }
+ printf("\n");
+ }
+
+ return 0;
+}
+
+static void ocp_print_C3_log_json(struct ssd_latency_monitor_log *log_data)
+{
+ int i, j;
+ int pos = 0;
+ char buf[128];
+ char ts_buf[128];
+ char *operation[3] = {"Read", "Write", "Trim"};
+ struct json_object *root;
+ root = json_create_object();
+
+ json_object_add_value_uint(root, "Feature Status",
+ log_data->feature_status);
+ json_object_add_value_uint(root, "Active Bucket Timer",
+ C0_ACTIVE_BUCKET_TIMER_INCREMENT *
+ le16_to_cpu(log_data->active_bucket_timer));
+ json_object_add_value_uint(root, "Active Bucket Timer Threshold",
+ C0_ACTIVE_BUCKET_TIMER_INCREMENT *
+ le16_to_cpu(log_data->active_bucket_timer_threshold));
+ json_object_add_value_uint(root, "Active Threshold A",
+ C0_ACTIVE_THRESHOLD_INCREMENT *
+ le16_to_cpu(log_data->active_threshold_a+1));
+ json_object_add_value_uint(root, "Active Threshold B",
+ C0_ACTIVE_THRESHOLD_INCREMENT *
+ le16_to_cpu(log_data->active_threshold_b+1));
+ json_object_add_value_uint(root, "Active Threshold C",
+ C0_ACTIVE_THRESHOLD_INCREMENT *
+ le16_to_cpu(log_data->active_threshold_c+1));
+ json_object_add_value_uint(root, "Active Threshold D",
+ C0_ACTIVE_THRESHOLD_INCREMENT *
+ le16_to_cpu(log_data->active_threshold_d+1));
+ json_object_add_value_uint(root, "Active Lantency Minimum Window",
+ C0_MINIMUM_WINDOW_INCREMENT *
+ le16_to_cpu(log_data->active_latency_min_window));
+ json_object_add_value_uint(root, "Active Latency Stamp Units",
+ le16_to_cpu(log_data->active_latency_stamp_units));
+ json_object_add_value_uint(root, "Static Latency Stamp Units",
+ le16_to_cpu(log_data->static_latency_stamp_units));
+ json_object_add_value_uint(root, "Debug Log Trigger Enable",
+ le16_to_cpu(log_data->debug_log_trigger_enable));
+
+ for (i = 0; i <= 3; i++) {
+ struct json_object *bucket;
+ bucket = json_create_object();
+ sprintf(buf, "Active Latency Mode: Bucket %d", i);
+ for (j = 0; j <= 2; j++) {
+ json_object_add_value_uint(bucket, operation[j],
+ log_data->active_latency_config & (1 << pos));
+ }
+ json_object_add_value_object(root, buf, bucket);
+ }
+ for (i = 0; i <= 3; i++) {
+ struct json_object *bucket;
+ bucket = json_create_object();
+ sprintf(buf, "Active Bucket Counter: Bucket %d", i);
+ for (j = 0; j <= 2; j++) {
+ json_object_add_value_uint(bucket, operation[j],
+ le32_to_cpu(log_data->active_bucket_counter[i][j]));
+ }
+ json_object_add_value_object(root, buf, bucket);
+ }
+ for (i = 0; i <= 3; i++) {
+ struct json_object *bucket;
+ bucket = json_create_object();
+ sprintf(buf, "Active Measured Latency: Bucket %d", i);
+ for (j = 0; j <= 2; j++) {
+ json_object_add_value_uint(bucket, operation[j],
+ le16_to_cpu(log_data->active_measured_latency[i][j]));
+ }
+ json_object_add_value_object(root, buf, bucket);
+ }
+ for (i = 0; i <= 3; i++) {
+ struct json_object *bucket;
+ bucket = json_create_object();
+ sprintf(buf, "Active Latency Time Stamp: Bucket %d", i);
+ for (j = 0; j <= 2; j++) {
+ if (le64_to_cpu(log_data->active_latency_timestamp[i][j]) == -1)
+ json_object_add_value_string(bucket, operation[j], "NA");
+ else {
+ convert_ts(le64_to_cpu(log_data->active_latency_timestamp[i][j]), ts_buf);
+ json_object_add_value_string(bucket, operation[j], ts_buf);
+ }
+ }
+ json_object_add_value_object(root, buf, bucket);
+ }
+ for (i = 0; i <= 3; i++) {
+ struct json_object *bucket;
+ bucket = json_create_object();
+ sprintf(buf, "Static Bucket Counter: Bucket %d", i);
+ for (j = 0; j <= 2; j++) {
+ json_object_add_value_uint(bucket, operation[j],
+ le32_to_cpu(log_data->static_bucket_counter[i][j]));
+ }
+ json_object_add_value_object(root, buf, bucket);
+ }
+ for (i = 0; i <= 3; i++) {
+ struct json_object *bucket;
+ bucket = json_create_object();
+ sprintf(buf, "Static Measured Latency: Bucket %d", i);
+ for (j = 0; j <= 2; j++) {
+ json_object_add_value_uint(bucket, operation[j],
+ le16_to_cpu(log_data->static_measured_latency[i][j]));
+ }
+ json_object_add_value_object(root, buf, bucket);
+ }
+ for (i = 0; i <= 3; i++) {
+ struct json_object *bucket;
+ bucket = json_create_object();
+ sprintf(buf, "Static Latency Time Stamp: Bucket %d", i);
+ for (j = 0; j <= 2; j++) {
+ if (le64_to_cpu(log_data->static_latency_timestamp[i][j]) == -1)
+ json_object_add_value_string(bucket, operation[j], "NA");
+ else {
+ convert_ts(le64_to_cpu(log_data->static_latency_timestamp[i][j]), ts_buf);
+ json_object_add_value_string(bucket, operation[j], ts_buf);
+ }
+ }
+ json_object_add_value_object(root, buf, bucket);
+ }
+
+ json_print_object(root, NULL);
+ printf("\n");
+
+ json_free_object(root);
+}
+
+static int get_c3_log_page(int fd, char *format)
+{
+ int ret = 0;
+ int fmt = -1;
+ __u8 *data;
+ int i;
+ struct ssd_latency_monitor_log *log_data;
+
+ fmt = validate_output_format(format);
+ if (fmt < 0) {
+ fprintf(stderr, "ERROR : OCP : invalid output format\n");
+ return fmt;
+ }
+
+ if ((data = (__u8 *) malloc(sizeof(__u8) * C3_LATENCY_MON_LOG_BUF_LEN)) == NULL) {
+ fprintf(stderr, "ERROR : OCP : malloc : %s\n", strerror(errno));
+ return -1;
+ }
+ memset(data, 0, sizeof (__u8) * C3_LATENCY_MON_LOG_BUF_LEN);
+
+ ret = nvme_get_log_simple(fd, C3_LATENCY_MON_OPCODE,
+ C3_LATENCY_MON_LOG_BUF_LEN, data);
+
+ if (strcmp(format, "json"))
+ fprintf(stderr,
+ "NVMe Status:%s(%x)\n",
+ nvme_status_to_string(ret, false),
+ ret);
+
+ if (ret == 0) {
+ log_data = (struct ssd_latency_monitor_log*)data;
+
+ /* check log page version */
+ if (log_data->log_page_version != C3_LATENCY_MON_VERSION) {
+ fprintf(stderr,
+ "ERROR : OCP : invalid latency monitor version\n");
+ ret = -1;
+ goto out;
+ }
+
+ /* check log page guid */
+ /* Verify GUID matches */
+ for (i=0; i<16; i++) {
+ if (lat_mon_guid[i] != log_data->log_page_guid[i]) {
+ fprintf(stderr,"ERROR : OCP : Unknown GUID in C3 Log Page data\n");
+ int j;
+ fprintf(stderr, "ERROR : OCP : Expected GUID: 0x");
+ for (j = 0; j<16; j++) {
+ fprintf(stderr, "%x", lat_mon_guid[j]);
+ }
+ fprintf(stderr, "\nERROR : OCP : Actual GUID: 0x");
+ for (j = 0; j<16; j++) {
+ fprintf(stderr, "%x", log_data->log_page_guid[j]);
+ }
+ fprintf(stderr, "\n");
+
+ ret = -1;
+ goto out;
+ }
+ }
+
+ /* print the data */
+ if (!log_data) {
+ fprintf(stderr,
+ "ERROR : OCP : Invalid C3 log data buffer\n");
+ ret = -1;
+ goto out;
+ }
+ switch (fmt) {
+ case NORMAL:
+ ocp_print_C3_log_normal(fd, log_data);
+ break;
+ case JSON:
+ ocp_print_C3_log_json(log_data);
+ break;
+ }
+ } else {
+ fprintf(stderr,
+ "ERROR : OCP : Unable to read C3 data from buffer\n");
+ }
+
+out:
+ free(data);
+ return ret;
+}
+
+static int ocp_latency_monitor_log(int argc, char **argv, struct command *command,
+ struct plugin *plugin)
+{
+ const char *desc = "Retrieve latency monitor log data.";
+ int fd;
+ int ret = 0;
+
+ struct config {
+ char *output_format;
+ };
+
+ struct config cfg = {
+ .output_format = "normal",
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_FMT("output-format", 'o', &cfg.output_format,
+ "output Format: normal|json"),
+ OPT_END()
+ };
+
+ fd = parse_and_open(argc, argv, desc, opts);
+ if (fd < 0)
+ return fd;
+
+ ret = get_c3_log_page(fd, cfg.output_format);
+ if (ret)
+ fprintf(stderr,
+ "ERROR : OCP : Failure reading the C3 Log Page, ret = %d\n",
+ ret);
+
+ return ret;
+}
diff --git a/plugins/ocp/ocp-nvme.h b/plugins/ocp/ocp-nvme.h
new file mode 100644
index 0000000..19378cd
--- /dev/null
+++ b/plugins/ocp/ocp-nvme.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2022 Meta Platforms, Inc.
+ *
+ * Authors: Arthur Shau <arthurshau@fb.com>,
+ * Wei Zhang <wzhang@fb.com>,
+ * Venkat Ramesh <venkatraghavan@fb.com>
+ */
+#undef CMD_INC_FILE
+#define CMD_INC_FILE plugins/ocp/ocp-nvme
+
+#if !defined(OCP_NVME) || defined(CMD_HEADER_MULTI_READ)
+#define OCP_NVME
+
+#include "cmd.h"
+
+PLUGIN(NAME("ocp", "OCP cloud SSD extensions", NVME_VERSION),
+ COMMAND_LIST(
+ ENTRY("smart-add-log", "Retrieve extended SMART Information", ocp_smart_add_log)
+ ENTRY("latency-monitor-log", "Get Latency Monitor Log Page", ocp_latency_monitor_log)
+ )
+);
+
+#endif
+
+#include "define_cmd.h"
diff --git a/plugins/scaleflux/sfx-nvme.c b/plugins/scaleflux/sfx-nvme.c
index df7f9a3..a6aaad5 100644
--- a/plugins/scaleflux/sfx-nvme.c
+++ b/plugins/scaleflux/sfx-nvme.c
@@ -6,21 +6,16 @@
#include <linux/fs.h>
#include <inttypes.h>
#include <asm/byteorder.h>
-#include <sys/ioctl.h>
#include <sys/sysinfo.h>
#include <sys/stat.h>
#include <unistd.h>
-#include "linux/nvme_ioctl.h"
-
+#include "common.h"
#include "nvme.h"
-#include "nvme-print.h"
-#include "nvme-ioctl.h"
-#include "nvme-status.h"
+#include "libnvme.h"
#include "plugin.h"
-
-#include "argconfig.h"
-#include "suffix.h"
+#include "linux/types.h"
+#include "nvme-print.h"
#define CREATE_CMD
#include "sfx-nvme.h"
@@ -114,38 +109,38 @@ struct nvme_additional_smart_log {
int nvme_change_cap(int fd, __u32 nsid, __u64 capacity)
{
- struct nvme_admin_cmd cmd = {
+ struct nvme_passthru_cmd cmd = {
.opcode = nvme_admin_change_cap,
.nsid = nsid,
.cdw10 = (capacity & 0xffffffff),
.cdw11 = (capacity >> 32),
};
- return nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD,&cmd);
+ return nvme_submit_admin_passthru(fd, &cmd, NULL);
}
int nvme_sfx_set_features(int fd, __u32 nsid, __u32 fid, __u32 value)
{
- struct nvme_admin_cmd cmd = {
+ struct nvme_passthru_cmd cmd = {
.opcode = nvme_admin_sfx_set_features,
.nsid = nsid,
.cdw10 = fid,
.cdw11 = value,
};
- return nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD,&cmd);
+ return nvme_submit_admin_passthru(fd, &cmd, NULL);
}
int nvme_sfx_get_features(int fd, __u32 nsid, __u32 fid, __u32 *result)
{
int err = 0;
- struct nvme_admin_cmd cmd = {
+ struct nvme_passthru_cmd cmd = {
.opcode = nvme_admin_sfx_get_features,
.nsid = nsid,
.cdw10 = fid,
};
- err = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD,&cmd);
+ err = nvme_submit_admin_passthru(fd, &cmd, NULL);
if (!err && result) {
*result = cmd.result;
}
@@ -343,8 +338,8 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
const char *json= "Dump output in json format";
struct config {
__u32 namespace_id;
- int raw_binary;
- int json;
+ bool raw_binary;
+ bool json;
};
struct config cfg = {
@@ -361,7 +356,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
fd = parse_and_open(argc, argv, desc, opts);
- err = nvme_get_log(fd, cfg.namespace_id, 0xca, false, NVME_NO_LOG_LSP,
+ err = nvme_get_nsid_log(fd, false, 0xca, cfg.namespace_id,
sizeof(smart_log), (void *)&smart_log);
if (!err) {
if (cfg.json)
@@ -372,8 +367,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
d_raw((unsigned char *)&smart_log, sizeof(smart_log));
}
else if (err > 0)
- fprintf(stderr, "NVMe Status:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
return err;
}
@@ -428,8 +422,8 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct
const char *raw = "dump output in binary format";
const char *write = "Get write statistics (read default)";
struct config {
- int raw_binary;
- int write;
+ bool raw_binary;
+ bool write;
};
struct config cfg = {
@@ -443,22 +437,20 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct
fd = parse_and_open(argc, argv, desc, opts);
- err = nvme_get_log(fd, 0xffffffff, cfg.write ? 0xc3 : 0xc1, false, NVME_NO_LOG_LSP,
- sizeof(stats), (void *)&stats);
+ err = nvme_get_log_simple(fd, cfg.write ? 0xc3 : 0xc1, sizeof(stats), (void *)&stats);
if (!err) {
if (!cfg.raw_binary)
show_lat_stats(&stats, cfg.write);
else
d_raw((unsigned char *)&stats, sizeof(stats));
} else if (err > 0)
- fprintf(stderr, "NVMe Status:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
return err;
}
int sfx_nvme_get_log(int fd, __u32 nsid, __u8 log_id, __u32 data_len, void *data)
{
- struct nvme_admin_cmd cmd = {
+ struct nvme_passthru_cmd cmd = {
.opcode = nvme_admin_get_log_page,
.nsid = nsid,
.addr = (__u64)(uintptr_t) data,
@@ -470,7 +462,7 @@ int sfx_nvme_get_log(int fd, __u32 nsid, __u8 log_id, __u32 data_len, void *data
cmd.cdw10 = log_id | (numdl << 16);
cmd.cdw11 = numdu;
- return nvme_submit_admin_passthru(fd, &cmd);
+ return nvme_submit_admin_passthru(fd, &cmd, NULL);
}
/**
@@ -583,8 +575,7 @@ static int sfx_get_bad_block(int argc, char **argv, struct command *cmd, struct
if (err < 0) {
perror("get-bad-block");
} else if (err != 0) {
- fprintf(stderr, "NVMe IO command error:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
} else {
bd_table_show(data_buf, buf_size);
printf("ScaleFlux get bad block table: success\n");
@@ -616,8 +607,8 @@ static int query_cap_info(int argc, char **argv, struct command *cmd, struct plu
const char *raw = "dump output in binary format";
const char *json= "Dump output in json format";
struct config {
- int raw_binary;
- int json;
+ bool raw_binary;
+ bool json;
};
struct config cfg;
@@ -745,9 +736,9 @@ static int change_cap(int argc, char **argv, struct command *cmd, struct plugin
struct config {
__u64 cap_in_byte;
__u32 capacity_in_gb;
- int raw_binary;
- int json;
- int force;
+ bool raw_binary;
+ bool json;
+ bool force;
};
struct config cfg = {
@@ -790,8 +781,7 @@ static int change_cap(int argc, char **argv, struct command *cmd, struct plugin
if (err < 0)
perror("sfx-change-cap");
else if (err != 0)
- fprintf(stderr, "NVMe IO command error:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
else {
printf("ScaleFlux change-capacity: success\n");
ioctl(fd, BLKRRPART);
@@ -863,7 +853,7 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl
__u32 namespace_id;
__u32 feature_id;
__u32 value;
- __u32 force;
+ bool force;
};
struct config cfg = {
.namespace_id = 1,
@@ -902,14 +892,12 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl
if (cfg.feature_id == SFX_FEAT_ATOMIC && cfg.value != 0) {
if (cfg.namespace_id != 0xffffffff) {
- err = nvme_identify_ns(fd, cfg.namespace_id, 0, &ns);
+ err = nvme_identify_ns(fd, cfg.namespace_id, &ns);
if (err) {
if (err < 0)
perror("identify-namespace");
else
- fprintf(stderr,
- "NVMe Admin command error:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
return err;
}
/*
@@ -941,8 +929,7 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl
printf("ScaleFlux set-feature:%#02x (%s), value:%d\n", cfg.feature_id,
sfx_feature_to_string(cfg.feature_id), cfg.value);
} else if (err > 0)
- fprintf(stderr, "NVMe Status:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
return err;
}
@@ -990,8 +977,7 @@ static int sfx_get_feature(int argc, char **argv, struct command *cmd, struct pl
printf("ScaleFlux get-feature:%02x (%s), value:%d\n", cfg.feature_id,
sfx_feature_to_string(cfg.feature_id), result);
} else if (err > 0)
- fprintf(stderr, "NVMe Status:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
return err;
diff --git a/plugins/seagate/seagate-nvme.c b/plugins/seagate/seagate-nvme.c
index 9512cda..5f6ce90 100644
--- a/plugins/seagate/seagate-nvme.c
+++ b/plugins/seagate/seagate-nvme.c
@@ -26,16 +26,14 @@
#include <stdlib.h>
#include <unistd.h>
#include <inttypes.h>
-#include <sys/ioctl.h>
#include <sys/stat.h>
#include <ctype.h>
-#include "linux/nvme_ioctl.h"
+#include "common.h"
#include "nvme.h"
-#include "nvme-print.h"
-#include "nvme-ioctl.h"
+#include "libnvme.h"
#include "plugin.h"
-#include "argconfig.h"
-#include "suffix.h"
+#include "linux/types.h"
+#include "nvme-print.h"
#define CREATE_CMD
@@ -176,8 +174,7 @@ static int log_pages_supp(int argc, char **argv, struct command *cmd,
};
fd = parse_and_open(argc, argv, desc, opts);
- err = nvme_get_log(fd, 1, 0xc5, false, NVME_NO_LOG_LSP,
- sizeof(logPageMap), &logPageMap);
+ err = nvme_get_log_simple(fd, 0xc5, sizeof(logPageMap), &logPageMap);
if (!err) {
if (strcmp(cfg.output_format,"json")) {
printf ("Seagate Supported Log-pages count :%d\n",
@@ -201,8 +198,7 @@ static int log_pages_supp(int argc, char **argv, struct command *cmd,
}
if (err > 0)
- fprintf(stderr, "NVMe Status:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
return err;
}
@@ -739,8 +735,7 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi
if (strcmp(cfg.output_format,"json"))
printf("Seagate Extended SMART Information :\n");
- err = nvme_get_log(fd, 1, 0xC4, false, NVME_NO_LOG_LSP,
- sizeof(ExtdSMARTInfo), &ExtdSMARTInfo);
+ err = nvme_get_log_simple(fd, 0xC4, sizeof(ExtdSMARTInfo), &ExtdSMARTInfo);
if (!err) {
if (strcmp(cfg.output_format,"json")) {
printf("%-39s %-15s %-19s \n", "Description", "Ext-Smart-Id", "Ext-Smart-Value");
@@ -762,8 +757,7 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi
* Next get Log Page 0xCF
*/
- err = nvme_get_log(fd, 1, 0xCF, false, NVME_NO_LOG_LSP,
- sizeof(logPageCF), &logPageCF);
+ err = nvme_get_log_simple(fd, 0xCF, sizeof(logPageCF), &logPageCF);
if (!err) {
if(strcmp(cfg.output_format,"json")) {
/*printf("Seagate DRAM Supercap SMART Attributes :\n");*/
@@ -778,8 +772,7 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi
} else if (!strcmp(cfg.output_format, "json"))
json_print_object(root, NULL);
} else if (err > 0)
- fprintf(stderr, "NVMe Status:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
return err;
}
@@ -844,7 +837,7 @@ static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin
if(strcmp(cfg.output_format,"json"))
printf("Seagate Temperature Stats Information :\n");
/*STEP-1 : Get Current Temperature from SMART */
- err = nvme_smart_log(fd, 0xffffffff, &smart_log);
+ err = nvme_get_log_smart(fd, 0xffffffff, true, &smart_log);
if (!err) {
temperature = ((smart_log.temperature[1] << 8) | smart_log.temperature[0]);
temperature = temperature ? temperature - 273 : 0;
@@ -860,8 +853,7 @@ static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin
}
/* STEP-2 : Get Max temperature form Ext SMART-id 194 */
- err = nvme_get_log(fd, 1, 0xC4, false, NVME_NO_LOG_LSP,
- sizeof(ExtdSMARTInfo), &ExtdSMARTInfo);
+ err = nvme_get_log_simple(fd, 0xC4, sizeof(ExtdSMARTInfo), &ExtdSMARTInfo);
if (!err) {
for(index = 0; index < NUMBER_EXTENDED_SMART_ATTRIBUTES; index++) {
if (ExtdSMARTInfo.vendorData[index].AttributeNumber == VS_ATTR_ID_MAX_LIFE_TEMPERATURE) {
@@ -880,11 +872,9 @@ static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin
}
}
else if (err > 0)
- fprintf(stderr, "NVMe Status:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
- cf_err = nvme_get_log(fd, 1, 0xCF, false, NVME_NO_LOG_LSP,
- sizeof(ExtdSMARTInfo), &logPageCF);
+ cf_err = nvme_get_log_simple(fd, 0xCF, sizeof(ExtdSMARTInfo), &logPageCF);
if(!cf_err) {
scCurrentTemp = logPageCF.AttrCF.SuperCapCurrentTemperature;
@@ -1013,8 +1003,7 @@ static int vs_pcie_error_log(int argc, char **argv, struct command *cmd, struct
if(strcmp(cfg.output_format,"json"))
printf("Seagate PCIe error counters Information :\n");
- err = nvme_get_log(fd, 1, 0xCB, false, NVME_NO_LOG_LSP,
- sizeof(pcieErrorLog), &pcieErrorLog);
+ err = nvme_get_log_simple(fd, 0xCB, sizeof(pcieErrorLog), &pcieErrorLog);
if (!err) {
if(strcmp(cfg.output_format,"json")) {
print_vs_pcie_error_log(pcieErrorLog);
@@ -1022,7 +1011,7 @@ static int vs_pcie_error_log(int argc, char **argv, struct command *cmd, struct
json_vs_pcie_error_log(pcieErrorLog);
} else if (err > 0)
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
+ nvme_show_status(err);
return err;
}
@@ -1034,10 +1023,9 @@ static int vs_clr_pcie_correctable_errs(int argc, char **argv, struct command *c
const char *save = "specifies that the controller shall save the attribute";
int err, fd;
__u32 result;
- void *buf = NULL;
struct config {
- int save;
+ bool save;
};
struct config cfg = {
@@ -1051,7 +1039,7 @@ static int vs_clr_pcie_correctable_errs(int argc, char **argv, struct command *c
fd = parse_and_open(argc, argv, desc, opts);
- err = nvme_set_feature(fd, 0, 0xE1, 0xCB, 0, cfg.save, 0, 0, buf, &result);
+ err = nvme_set_features_simple(fd, 0xE1, 0, 0xCB, cfg.save, &result);
if (err < 0) {
perror("set-feature");
@@ -1080,7 +1068,7 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug
struct config {
__u32 namespace_id;
__u32 log_id;
- int raw_binary;
+ bool raw_binary;
};
struct config cfg = {
@@ -1101,8 +1089,7 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug
dump_fd = STDOUT_FILENO;
cfg.log_id = (cfg.log_id << 8) | 0x07;
- err = nvme_get_log13(fd, cfg.namespace_id, cfg.log_id,
- NVME_NO_LOG_LSP, offset, 0, false,
+ err = nvme_get_nsid_log(fd, false, cfg.log_id, cfg.namespace_id,
sizeof(tele_log), (void *)(&tele_log));
if (!err) {
maxBlk = tele_log.tele_data_area3;
@@ -1119,8 +1106,7 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug
} else
seaget_d_raw((unsigned char *)(&tele_log), sizeof(tele_log), dump_fd);
} else if (err > 0)
- fprintf(stderr, "NVMe Status:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
else
perror("log page");
@@ -1141,9 +1127,24 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug
memset(log, 0, blksToGet * 512);
- err = nvme_get_log13(fd, cfg.namespace_id, cfg.log_id,
- NVME_NO_LOG_LSP, offset, 0, false,
- blksToGet * 512, (void *)log);
+ struct nvme_get_log_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .lid = cfg.log_id,
+ .nsid = cfg.namespace_id,
+ .lpo = offset,
+ .lsp = 0,
+ .lsi = 0,
+ .rae = true,
+ .uuidx = 0,
+ .csi = NVME_CSI_NVM,
+ .ot = false,
+ .len = blksToGet * 512,
+ .log = (void *)log,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ err = nvme_get_log(&args);
if (!err) {
offset += blksToGet * 512;
@@ -1154,8 +1155,7 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug
} else
seaget_d_raw((unsigned char *)log, blksToGet * 512, dump_fd);
} else if (err > 0)
- fprintf(stderr, "NVMe Status:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
else
perror("log page");
@@ -1182,7 +1182,7 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug
struct config {
__u32 namespace_id;
- int raw_binary;
+ bool raw_binary;
};
struct config cfg = {
@@ -1202,8 +1202,7 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug
dump_fd = STDOUT_FILENO;
log_id = 0x08;
- err = nvme_get_log13(fd, cfg.namespace_id, log_id,
- NVME_NO_LOG_LSP, offset, 0, false,
+ err = nvme_get_nsid_log(fd, false, log_id, cfg.namespace_id,
sizeof(tele_log), (void *)(&tele_log));
if (!err) {
maxBlk = tele_log.tele_data_area3;
@@ -1219,8 +1218,7 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug
} else
seaget_d_raw((unsigned char *)(&tele_log), sizeof(tele_log), dump_fd);
} else if (err > 0)
- fprintf(stderr, "NVMe Status:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
else
perror("log page");
@@ -1241,9 +1239,24 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug
memset(log, 0, blksToGet * 512);
- err = nvme_get_log13(fd, cfg.namespace_id, log_id,
- NVME_NO_LOG_LSP, offset, 0, false,
- blksToGet * 512, (void *)log);
+ struct nvme_get_log_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .lid = log_id,
+ .nsid = cfg.namespace_id,
+ .lpo = offset,
+ .lsp = 0,
+ .lsi = 0,
+ .rae = true,
+ .uuidx = 0,
+ .csi = NVME_CSI_NVM,
+ .ot = false,
+ .len = blksToGet * 512,
+ .log = (void *)log,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ err = nvme_get_log(&args);
if (!err) {
offset += blksToGet * 512;
@@ -1254,8 +1267,7 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug
} else
seaget_d_raw((unsigned char *)log, blksToGet * 512, dump_fd);
} else if (err > 0)
- fprintf(stderr, "NVMe Status:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
else
perror("log page");
@@ -1327,8 +1339,7 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl
}
log_id = 0x08;
- err = nvme_get_log13(fd, cfg.namespace_id, log_id,
- NVME_NO_LOG_LSP, offset, 0, false,
+ err = nvme_get_nsid_log(fd, false, log_id, cfg.namespace_id,
sizeof(tele_log), (void *)(&tele_log));
if (!err) {
maxBlk = tele_log.tele_data_area3;
@@ -1340,8 +1351,7 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl
*/
seaget_d_raw((unsigned char *)(&tele_log), sizeof(tele_log), dump_fd);
} else if (err > 0)
- fprintf(stderr, "NVMe Status:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
else
perror("log page");
@@ -1363,17 +1373,31 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl
memset(log, 0, blksToGet * 512);
- err = nvme_get_log13(fd, cfg.namespace_id, log_id,
- NVME_NO_LOG_LSP, offset, 0, false,
- blksToGet * 512, (void *)log);
+ struct nvme_get_log_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .lid = log_id,
+ .nsid = cfg.namespace_id,
+ .lpo = offset,
+ .lsp = 0,
+ .lsi = 0,
+ .rae = true,
+ .uuidx = 0,
+ .csi = NVME_CSI_NVM,
+ .ot = false,
+ .len = blksToGet * 512,
+ .log = (void *)log,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ err = nvme_get_log(&args);
if (!err) {
offset += blksToGet * 512;
seaget_d_raw((unsigned char *)log, blksToGet * 512, dump_fd);
} else if (err > 0)
- fprintf(stderr, "NVMe Status:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
else
perror("log page");
diff --git a/plugins/shannon/shannon-nvme.c b/plugins/shannon/shannon-nvme.c
index 1909e45..d79b119 100644
--- a/plugins/shannon/shannon-nvme.c
+++ b/plugins/shannon/shannon-nvme.c
@@ -5,16 +5,12 @@
#include <unistd.h>
#include <inttypes.h>
-#include "linux/nvme_ioctl.h"
-
#include "common.h"
#include "nvme.h"
-#include "nvme-print.h"
-#include "nvme-ioctl.h"
+#include "libnvme.h"
#include "plugin.h"
-
-#include "argconfig.h"
-#include "suffix.h"
+#include "linux/types.h"
+#include "nvme-print.h"
#define CREATE_CMD
#include "shannon-nvme.h"
@@ -127,7 +123,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
const char *raw = "dump output in binary format";
struct config {
__u32 namespace_id;
- int raw_binary;
+ bool raw_binary;
};
struct config cfg = {
@@ -141,8 +137,8 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
};
fd = parse_and_open(argc, argv, desc, opts);
- err = nvme_get_log(fd, cfg.namespace_id, 0xca, false,
- NVME_NO_LOG_LSP, sizeof(smart_log), &smart_log);
+ err = nvme_get_nsid_log(fd, false, 0xca, cfg.namespace_id,
+ sizeof(smart_log), &smart_log);
if (!err) {
if (!cfg.raw_binary)
show_shannon_smart_log(&smart_log, cfg.namespace_id, devicename);
@@ -150,8 +146,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
d_raw((unsigned char *)&smart_log, sizeof(smart_log));
}
else if (err > 0)
- fprintf(stderr, "NVMe Status:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
return err;
}
@@ -181,17 +176,17 @@ static int get_additional_feature(int argc, char **argv, struct command *cmd, st
struct config {
__u32 namespace_id;
- enum nvme_feat feature_id;
+ enum nvme_features_id feature_id;
__u8 sel;
__u32 cdw11;
__u32 data_len;
- int raw_binary;
- int human_readable;
+ bool raw_binary;
+ bool human_readable;
};
struct config cfg = {
.namespace_id = 1,
- .feature_id = NVME_FEAT_NONE,
+ .feature_id = 0,
.sel = 0,
.cdw11 = 0,
.data_len = 0,
@@ -231,9 +226,22 @@ static int get_additional_feature(int argc, char **argv, struct command *cmd, st
memset(buf, 0, cfg.data_len);
}
- err = nvme_get_feature(fd, cfg.namespace_id, cfg.feature_id, cfg.sel, cfg.cdw11, 0,
- cfg.data_len, buf, &result);
+ struct nvme_get_features_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .fid = cfg.feature_id,
+ .nsid = cfg.namespace_id,
+ .sel = cfg.sel,
+ .cdw11 = cfg.cdw11,
+ .uuidx = 0,
+ .data_len = cfg.data_len,
+ .data = buf,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+ err = nvme_get_features(&args);
if (!err) {
+#if 0
printf("get-feature:0x%02x (%s), %s value: %#08x\n", cfg.feature_id,
nvme_feature_to_string(cfg.feature_id),
nvme_select_to_string(cfg.sel), result);
@@ -247,9 +255,9 @@ static int get_additional_feature(int argc, char **argv, struct command *cmd, st
d_raw(buf, cfg.data_len);
}
}
+#endif
} else if (err > 0)
- fprintf(stderr, "NVMe Status:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
if (buf)
free(buf);
return err;
@@ -285,7 +293,7 @@ static int set_additional_feature(int argc, char **argv, struct command *cmd, st
__u32 feature_id;
__u32 value;
__u32 data_len;
- int save;
+ bool save;
};
struct config cfg = {
@@ -343,20 +351,35 @@ static int set_additional_feature(int argc, char **argv, struct command *cmd, st
}
}
- err = nvme_set_feature(fd, cfg.namespace_id, cfg.feature_id, cfg.value,
- 0, cfg.save, 0, cfg.data_len, buf, &result);
+ struct nvme_set_features_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .fid = cfg.feature_id,
+ .nsid = cfg.namespace_id,
+ .cdw11 = cfg.value,
+ .cdw12 = 0,
+ .save = cfg.save,
+ .uuidx = 0,
+ .cdw15 = 0,
+ .data_len = cfg.data_len,
+ .data = buf,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+ err = nvme_set_features(&args);
if (err < 0) {
perror("set-feature");
goto free;
}
if (!err) {
+#if 0
printf("set-feature:%02x (%s), value:%#08x\n", cfg.feature_id,
nvme_feature_to_string(cfg.feature_id), cfg.value);
+#endif
if (buf)
d(buf, cfg.data_len, 16, 1);
} else if (err > 0)
- fprintf(stderr, "NVMe Status:%s(%x)\n",
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
free:
if (buf)
diff --git a/plugins/shannon/shannon-nvme.h b/plugins/shannon/shannon-nvme.h
index db25828..46fc697 100644
--- a/plugins/shannon/shannon-nvme.h
+++ b/plugins/shannon/shannon-nvme.h
@@ -9,10 +9,10 @@
PLUGIN(NAME("shannon", "Shannon vendor specific extensions", NVME_VERSION),
COMMAND_LIST(
ENTRY("smart-log-add", "Retrieve Shannon SMART Log, show it", get_additional_smart_log)
- ENTRY("get-feature-add", "Get Shannon feature and show the resulting value", get_additional_feature)
- ENTRY("set-feature-add", "Set a Shannon feature and show the resulting value", set_additional_feature)
- ENTRY("id-ctrl", "Shannon NVMe Identify Controller", shannon_id_ctrl)
- )
+ ENTRY("set-additioal-feature", "Set additional Shannon feature", set_additional_feature)
+ ENTRY("get-additional-feature", "Get additional Shannon feature", get_additional_feature)
+ ENTRY("id-ctrl", "Retrieve Shannon ctrl id, show it", shannon_id_ctrl)
+ )
);
#endif
diff --git a/plugins/toshiba/toshiba-nvme.c b/plugins/toshiba/toshiba-nvme.c
index cba1af8..fd2e9c1 100644
--- a/plugins/toshiba/toshiba-nvme.c
+++ b/plugins/toshiba/toshiba-nvme.c
@@ -7,13 +7,11 @@
#include <inttypes.h>
#include <stdbool.h>
-#include "linux/nvme_ioctl.h"
#include "nvme.h"
-#include "nvme-print.h"
-#include "nvme-ioctl.h"
+#include "libnvme.h"
#include "plugin.h"
-#include "argconfig.h"
-#include "suffix.h"
+#include "linux/types.h"
+#include "nvme-print.h"
#define CREATE_CMD
#include "toshiba-nvme.h"
@@ -67,7 +65,7 @@ static int nvme_sct_op(int fd, __u32 opcode, __u32 cdw10, __u32 cdw11, void* da
int err = 0;
__u32 result;
- err = nvme_passthru(fd, NVME_IOCTL_ADMIN_CMD, opcode, flags, rsvd,
+ err = nvme_admin_passthru(fd, opcode, flags, rsvd,
namespace_id, cdw2, cdw3, cdw10,
cdw11, cdw12, cdw13, cdw14, cdw15,
data_len, data, metadata_len, metadata,
@@ -392,8 +390,7 @@ static int nvme_get_vendor_log(int fd, __u32 namespace_id, int log_page,
if (err) {
goto end;
}
- err = nvme_get_log(fd, namespace_id, log_page, false,
- NVME_NO_LOG_LSP, log_len, log);
+ err = nvme_get_nsid_log(fd, false, log_page, namespace_id, log_len, log);
if (err) {
fprintf(stderr, "%s: couldn't get log 0x%x\n", __func__,
log_page);
@@ -476,7 +473,7 @@ static int vendor_log(int argc, char **argv, struct command *cmd, struct plugin
fprintf(stderr, "%s: couldn't get vendor log 0x%x\n", __func__, cfg.log);
end:
if (err > 0)
- fprintf(stderr, "%s: NVMe Status:%s(%x)\n", __func__, nvme_status_to_string(err), err);
+ nvme_show_status(err);
return err;
}
@@ -518,8 +515,8 @@ static int internal_log(int argc, char **argv, struct command *cmd, struct plugi
if (err < 0)
fprintf(stderr, "%s: couldn't get fw log \n", __func__);
if (err > 0)
- fprintf(stderr, "%s: NVMe Status:%s(%x)\n", __func__,
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
+
return err;
}
@@ -550,14 +547,27 @@ static int clear_correctable_errors(int argc, char **argv, struct command *cmd,
if (err)
goto end;
- err = nvme_set_feature(fd, namespace_id, feature_id, value, cdw12, save,
- 0, 0, NULL, &result);
+ struct nvme_set_features_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .fid = feature_id,
+ .nsid = namespace_id,
+ .cdw11 = value,
+ .cdw12 = cdw12,
+ .save = save,
+ .uuidx = 0,
+ .cdw15 = 0,
+ .data_len = 0,
+ .data = NULL,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+ err = nvme_set_features(&args);
if (err)
fprintf(stderr, "%s: couldn't clear PCIe correctable errors \n",
__func__);
end:
if (err > 0)
- fprintf(stderr, "%s: NVMe Status:%s(%x)\n", __func__,
- nvme_status_to_string(err), err);
+ nvme_show_status(err);
return err;
}
diff --git a/plugins/transcend/transcend-nvme.c b/plugins/transcend/transcend-nvme.c
index dbb56be..85d3cac 100644
--- a/plugins/transcend/transcend-nvme.c
+++ b/plugins/transcend/transcend-nvme.c
@@ -5,13 +5,9 @@
#include <unistd.h>
#include <inttypes.h>
-#include "linux/nvme_ioctl.h"
#include "nvme.h"
-#include "nvme-print.h"
-#include "nvme-ioctl.h"
+#include "libnvme.h"
#include "plugin.h"
-#include "argconfig.h"
-#include "suffix.h"
#define CREATE_CMD
#include "transcend-nvme.h"
@@ -37,7 +33,7 @@ static int getHealthValue(int argc, char **argv, struct command *cmd, struct plu
printf("\nDevice not found \n");;
return -1;
}
- result = nvme_smart_log(fd, 0xffffffff, &smart_log);
+ result = nvme_get_log_smart(fd, 0xffffffff, true, &smart_log);
if (!result) {
printf("Transcend NVME heath value: ");
percent_used =smart_log.percent_used;
@@ -82,7 +78,7 @@ static int getBadblock(int argc, char **argv, struct command *cmd, struct plugin
nvmecmd.cdw12=DW12_BAD_BLOCK;
nvmecmd.addr = (__u64)(uintptr_t)data;
nvmecmd.data_len = 0x1;
- result = nvme_submit_admin_passthru(fd,&nvmecmd);
+ result = nvme_submit_admin_passthru(fd, &nvmecmd, NULL);
if(!result) {
int badblock = data[0];
printf("Transcend NVME badblock count: %d\n",badblock);
diff --git a/plugins/virtium/virtium-nvme.c b/plugins/virtium/virtium-nvme.c
index a194a5f..7c2ebec 100644
--- a/plugins/virtium/virtium-nvme.c
+++ b/plugins/virtium/virtium-nvme.c
@@ -9,13 +9,10 @@
#include <time.h>
#include <locale.h>
-#include "linux/nvme_ioctl.h"
+#include "common.h"
#include "nvme.h"
-#include "nvme-print.h"
-#include "nvme-ioctl.h"
+#include "libnvme.h"
#include "plugin.h"
-#include "argconfig.h"
-#include "suffix.h"
#define CREATE_CMD
#include "virtium-nvme.h"
@@ -35,7 +32,7 @@ struct vtview_log_header {
char test_name[256];
long int time_stamp;
struct nvme_id_ctrl raw_ctrl;
- struct nvme_firmware_log_page raw_fw;
+ struct nvme_firmware_slot raw_fw;
};
struct vtview_smart_log_entry {
@@ -124,6 +121,8 @@ static void vt_convert_smart_data_to_human_readable_format(struct vtview_smart_l
double capacity;
char *curlocale;
char *templocale;
+ __u8 lba_index;
+ nvme_id_ns_flbas_to_lbaf_inuse(smart->raw_ns.flbas, &lba_index);
curlocale = setlocale(LC_ALL, NULL);
templocale = strdup(curlocale);
@@ -133,7 +132,7 @@ static void vt_convert_smart_data_to_human_readable_format(struct vtview_smart_l
setlocale(LC_ALL, "C");
- long long int lba = 1 << smart->raw_ns.lbaf[(smart->raw_ns.flbas & 0x0f)].ds;
+ long long int lba = 1 << smart->raw_ns.lbaf[lba_index].ds;
capacity = le64_to_cpu(smart->raw_ns.nsze) * lba;
snprintf(tempbuff, sizeof(tempbuff), "log;%s;%lu;%s;%s;%-.*s;", smart->raw_ctrl.sn, smart->time_stamp, smart->path,
@@ -273,7 +272,7 @@ static int vt_add_entry_to_log(const int fd, const char *path, const struct vtvi
struct vtview_smart_log_entry smart;
char filename[256] = "";
int ret = 0;
- int nsid = 0;
+ unsigned nsid = 0;
memset(smart.path, 0, sizeof(smart.path));
strcpy(smart.path, path);
@@ -283,14 +282,14 @@ static int vt_add_entry_to_log(const int fd, const char *path, const struct vtvi
strcpy(filename, cfg->output_file);
smart.time_stamp = time(NULL);
- nsid = nvme_get_nsid(fd);
+ ret = nvme_get_nsid(fd, &nsid);
- if (nsid <= 0) {
+ if (ret < 0) {
printf("Cannot read namespace-id\n");
return -1;
}
- ret = nvme_identify_ns(fd, nsid, 0, &smart.raw_ns);
+ ret = nvme_identify_ns(fd, nsid, &smart.raw_ns);
if (ret) {
printf("Cannot read namespace identify\n");
return -1;
@@ -302,7 +301,7 @@ static int vt_add_entry_to_log(const int fd, const char *path, const struct vtvi
return -1;
}
- ret = nvme_smart_log(fd, NVME_NSID_ALL, &smart.raw_smart);
+ ret = nvme_get_log_smart(fd, NVME_NSID_ALL, true, &smart.raw_smart);
if (ret) {
printf("Cannot read device SMART log\n");
return -1;
@@ -343,7 +342,7 @@ static int vt_update_vtview_log_header(const int fd, const char *path, const str
return -1;
}
- ret = nvme_fw_log(fd, &header.raw_fw);
+ ret = nvme_get_log_fw_slot(fd, true, &header.raw_fw);
if (ret) {
printf("Cannot read device firmware log\n");
return -1;
@@ -445,7 +444,7 @@ static void vt_build_power_state_descriptor(const struct nvme_id_ctrl *ctrl)
vt_convert_data_buffer_to_hex_string(&buf[16], 4, true, s);
printf("%9sh", s);
- temp = ctrl->psd[i].idle_scale;
+ temp = ctrl->psd[i].ips;
snprintf(s, sizeof(s), "%u%u", (((unsigned char)temp >> 6) & 0x01), (((unsigned char)temp >> 7) & 0x01));
printf("%3sb", s);
@@ -454,7 +453,7 @@ static void vt_build_power_state_descriptor(const struct nvme_id_ctrl *ctrl)
vt_convert_data_buffer_to_hex_string(&buf[20], 4, true, s);
printf("%9sh", s);
- temp = ctrl->psd[i].active_work_scale;
+ temp = ctrl->psd[i].apws;
snprintf(s, sizeof(s), "%u%u", (((unsigned char)temp >> 6) & 0x01), (((unsigned char)temp >> 7) & 0x01));
printf("%3sb", s);
snprintf(s, sizeof(s), "%u%u%u", (((unsigned char)temp) & 0x01), (((unsigned char)temp >> 1) & 0x01), (((unsigned char)temp >> 2) & 0x01));
diff --git a/plugins/wdc/wdc-nvme.c b/plugins/wdc/wdc-nvme.c
index d5e17b8..486ee36 100644
--- a/plugins/wdc/wdc-nvme.c
+++ b/plugins/wdc/wdc-nvme.c
@@ -30,18 +30,13 @@
#include <fcntl.h>
#include <unistd.h>
-#include "linux/nvme_ioctl.h"
-
#include "common.h"
#include "nvme.h"
-#include "nvme-print.h"
-#include "nvme-ioctl.h"
+#include "libnvme.h"
#include "plugin.h"
-#include "nvme-status.h"
+#include "linux/types.h"
+#include "nvme-print.h"
-#include "argconfig.h"
-#include "suffix.h"
-#include <sys/ioctl.h>
#define CREATE_CMD
#include "wdc-nvme.h"
#include "wdc-utils.h"
@@ -80,19 +75,27 @@
#define WDC_NVME_SN650_DEV_ID_2 0x2702
#define WDC_NVME_SN650_DEV_ID_3 0x2720
#define WDC_NVME_SN650_DEV_ID_4 0x2721
-#define WDC_NVME_SN450_DEV_ID_1 0x2712
-#define WDC_NVME_SN450_DEV_ID_2 0x2713
+#define WDC_NVME_SN655_DEV_ID 0x2722
+#define WDC_NVME_SN560_DEV_ID_1 0x2712
+#define WDC_NVME_SN560_DEV_ID_2 0x2713
+#define WDC_NVME_SN560_DEV_ID_3 0x2714
#define WDC_NVME_SXSLCL_DEV_ID 0x2001
#define WDC_NVME_SN520_DEV_ID 0x5003
#define WDC_NVME_SN520_DEV_ID_1 0x5004
#define WDC_NVME_SN520_DEV_ID_2 0x5005
+#define WDC_NVME_SN530_DEV_ID 0x5009
#define WDC_NVME_SN720_DEV_ID 0x5002
#define WDC_NVME_SN730A_DEV_ID 0x5006
#define WDC_NVME_SN730B_DEV_ID 0x3714
#define WDC_NVME_SN730B_DEV_ID_1 0x3734
+#define WDC_NVME_SN740_DEV_ID 0x5015
+#define WDC_NVME_SN740_DEV_ID_1 0x5016
+#define WDC_NVME_SN740_DEV_ID_2 0x5017
+#define WDC_NVME_SN740_DEV_ID_3 0x5025
#define WDC_NVME_SN340_DEV_ID 0x500d
#define WDC_NVME_ZN350_DEV_ID 0x5010
#define WDC_NVME_ZN350_DEV_ID_1 0x5018
+#define WDC_NVME_SN810_DEV_ID 0x5011
#define WDC_DRIVE_CAP_CAP_DIAG 0x0000000000000001
#define WDC_DRIVE_CAP_INTERNAL_LOG 0x0000000000000002
@@ -129,7 +132,10 @@
#define WDC_DRIVE_CAP_DUI_DATA 0x0000000200000000
#define WDC_SN730B_CAP_VUC_LOG 0x0000000400000000
#define WDC_DRIVE_CAP_DUI 0x0000000800000000
-#define WDC_DRIVE_CAP_PURGE 0x0000001000000000
+#define WDC_DRIVE_CAP_PURGE 0x0000001000000000
+#define WDC_DRIVE_CAP_OCP_C1_LOG_PAGE 0x0000002000000000
+#define WDC_DRIVE_CAP_OCP_C4_LOG_PAGE 0x0000004000000000
+#define WDC_DRIVE_CAP_OCP_C5_LOG_PAGE 0x0000008000000000
#define WDC_DRIVE_CAP_SMART_LOG_MASK (WDC_DRIVE_CAP_C0_LOG_PAGE | WDC_DRIVE_CAP_C1_LOG_PAGE | \
WDC_DRIVE_CAP_CA_LOG_PAGE | WDC_DRIVE_CAP_D0_LOG_PAGE)
#define WDC_DRIVE_CAP_CLEAR_PCIE_MASK (WDC_DRIVE_CAP_CLEAR_PCIE | \
@@ -164,6 +170,7 @@
#define WDC_CUSTOMER_ID_0x1004 0x1004
#define WDC_CUSTOMER_ID_0x1008 0x1008
#define WDC_CUSTOMER_ID_0x1304 0x1304
+#define WDC_INVALID_CUSTOMER_ID -1
#define WDC_ALL_PAGE_MASK 0xFFFF
#define WDC_C0_PAGE_MASK 0x0001
@@ -305,7 +312,7 @@
/* CA Log Page */
#define WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE 0xCA
#define WDC_FB_CA_LOG_BUF_LEN 0x80
-#define WDC_BD_CA_LOG_BUF_LEN 0x9C
+#define WDC_BD_CA_LOG_BUF_LEN 0xA0 /* Added 4 padding bytes to resolve build warning messages */
/* C0 EOL Status Log Page */
#define WDC_NVME_GET_EOL_STATUS_LOG_OPCODE 0xC0
@@ -323,6 +330,7 @@
#define WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID 0xC2
#define WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN 0x1000
#define WDC_MAX_NUM_ACT_HIST_ENTRIES 20
+#define WDC_C2_GUID_LENGTH 16
/* C3 Latency Monitor Log Page */
#define WDC_LATENCY_MON_LOG_BUF_LEN 0x200
@@ -512,14 +520,14 @@ typedef enum
SCAO_NUSE = 152, /* NUSE - Namespace utilization */
SCAO_PSC = 160, /* PLP start count */
SCAO_EEST = 176, /* Endurance estimate */
- SCAO_PLRC = 192, /* PCIe Link Retraining Count */
+ SCAO_PLRC = 192, /* PCIe Link Retraining Count */
SCAO_LPV = 494, /* Log page version */
SCAO_LPG = 496, /* Log page GUID */
} SMART_CLOUD_ATTRIBUTE_OFFSETS;
-#define WDC_C2_GUID_LENGTH 16
+#define WDC_C0_GUID_LENGTH 16
-static __u8 scao_guid[WDC_C2_GUID_LENGTH] = { 0xC5, 0xAF, 0x10, 0x28, 0xEA, 0xBF, 0xF2, 0xA4,
+static __u8 scao_guid[WDC_C0_GUID_LENGTH] = { 0xC5, 0xAF, 0x10, 0x28, 0xEA, 0xBF, 0xF2, 0xA4,
0x9C, 0x4F, 0x6F, 0x7C, 0xC9, 0x14, 0xD5, 0xAF };
typedef enum
@@ -632,10 +640,10 @@ 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(int fd, __u8 log_id);
+static bool wdc_nvme_check_supported_log_page(nvme_root_t r, int fd, __u8 log_id);
static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct command *command,
struct plugin *plugin);
-static int wdc_do_drive_essentials(int fd, char *dir, char *key);
+static int wdc_do_drive_essentials(nvme_root_t r, int fd, char *dir, char *key);
static int wdc_drive_essentials(int argc, char **argv, struct command *command,
struct plugin *plugin);
static int wdc_drive_status(int argc, char **argv, struct command *command,
@@ -653,7 +661,6 @@ static int wdc_reason_identifier(int argc, char **argv,
static int wdc_do_get_reason_id(int fd, char *file, int log_id);
static int wdc_save_reason_id(int fd, __u8 *rsn_ident, int size);
static int wdc_clear_reason_id(int fd);
-static int wdc_dump_telemetry_hdr(int fd, int log_id, struct nvme_telemetry_log_page_hdr *log_hdr);
static int wdc_log_page_directory(int argc, char **argv, struct command *command,
struct plugin *plugin);
static int wdc_do_drive_info(int fd, __u32 *result);
@@ -661,10 +668,11 @@ static int wdc_vs_drive_info(int argc, char **argv, struct command *command,
struct plugin *plugin);
static int wdc_vs_temperature_stats(int argc, char **argv, struct command *command,
struct plugin *plugin);
-static __u64 wdc_get_enc_drive_capabilities(int fd);
+static __u64 wdc_get_enc_drive_capabilities(nvme_root_t r, int fd);
static int wdc_enc_get_nic_log(int fd, __u8 log_id, __u32 xfer_size, __u32 data_len, FILE *out);
static int wdc_enc_submit_move_data(int fd, char *cmd, int len, int xfer_size, FILE *out, int data_id, int cdw14, int cdw15);
-static bool get_dev_mgment_cbs_data(int fd, __u8 log_id, void **cbs_data);
+static bool get_dev_mgment_cbs_data(nvme_root_t r, int fd, __u8 log_id, void **cbs_data);
+static __u32 wdc_get_fw_cust_id(nvme_root_t r, int fd);
/* Drive log data size */
struct wdc_log_size {
@@ -802,12 +810,11 @@ struct wdc_c2_cbs_data {
__u8 data[];
};
-struct wdc_bd_ca_log_format {
+struct __attribute__((__packed__)) wdc_bd_ca_log_format {
__u8 field_id;
__u8 reserved1[2];
__u8 normalized_value;
- __u8 reserved2;
- __u8 raw_value[7];
+ __u8 raw_value[8];
};
#define READ 0
@@ -904,6 +911,32 @@ struct __attribute__((__packed__)) wdc_ssd_d0_smart_log {
__u8 rsvd[408]; /* 0x68 - 408 Reserved bytes */
};
+#define WDC_OCP_C1_GUID_LENGTH 16
+#define WDC_ERROR_REC_LOG_BUF_LEN 512
+#define WDC_ERROR_REC_LOG_ID 0xC1
+#define WDC_ERROR_REC_LOG_VERSION 0002
+
+struct __attribute__((__packed__)) wdc_ocp_c1_error_recovery_log {
+ __le16 panic_reset_wait_time; /* 000 - Panic Reset Wait Time */
+ __u8 panic_reset_action; /* 002 - Panic Reset Action */
+ __u8 dev_recovery_action1; /* 003 - Device Recovery Action 1 */
+ __le64 panic_id; /* 004 - Panic ID */
+ __le32 dev_capabilities; /* 012 - Device Capabilities */
+ __u8 vs_recovery_opc; /* 016 - Vendor Specific Recovery Opcode */
+ __u8 rsvd1[3]; /* 017 - 3 Reserved Bytes */
+ __le32 vs_cmd_cdw12; /* 020 - Vendor Specific Command CDW12 */
+ __le32 vs_cmd_cdw13; /* 024 - Vendor Specific Command CDW13 */
+ __u8 vs_cmd_to; /* 028 - Vendor Specific Command Timeout */
+ __u8 dev_recovery_action2; /* 029 - Device Recovery Action 2 */
+ __u8 dev_recovery_action2_to; /* 030 - Device Recovery Action 2 Timeout */
+ __u8 rsvd2[463]; /* 031 - 463 Reserved Bytes */
+ __le16 log_page_version; /* 494 - Log Page Version */
+ __u8 log_page_guid[WDC_OCP_C1_GUID_LENGTH]; /* 496 - Log Page GUID */
+};
+
+static __u8 wdc_ocp_c1_guid[WDC_OCP_C1_GUID_LENGTH] = { 0x44, 0xD9, 0x31, 0x21, 0xFE, 0x30, 0x34, 0xAE,
+ 0xAB, 0x4D, 0xFD, 0x3D, 0xBA, 0x83, 0x19, 0x5A };
+
/* NAND Stats */
struct __attribute__((__packed__)) wdc_nand_stats {
__u8 nand_write_tlc[16];
@@ -1015,6 +1048,49 @@ struct __attribute__((__packed__)) wdc_fw_act_history_log_format_c2 {
__u8 log_page_guid[WDC_C2_GUID_LENGTH];
};
+#define WDC_OCP_C4_GUID_LENGTH 16
+#define WDC_DEV_CAP_LOG_BUF_LEN 4096
+#define WDC_DEV_CAP_LOG_ID 0xC4
+#define WDC_DEV_CAP_LOG_VERSION 0001
+#define WDC_OCP_C4_NUM_PS_DESCR 127
+
+struct __attribute__((__packed__)) wdc_ocp_C4_dev_cap_log {
+ __le16 num_pcie_ports; /* 0000 - Number of PCI Express Ports */
+ __le16 oob_mgmt_support; /* 0002 - OOB Management Interfaces Supported */
+ __le16 wrt_zeros_support; /* 0004 - Write Zeros Commmand Support */
+ __le16 sanitize_support; /* 0006 - Sanitize Command Support */
+ __le16 dsm_support; /* 0008 - Dataset Management Command Support */
+ __le16 wrt_uncor_support; /* 0010 - Write Uncorrectable Command Support */
+ __le16 fused_support; /* 0012 - Fused Operation Support */
+ __le16 min_dssd_ps; /* 0014 - Minimum Valid DSSD Power State */
+ __u8 rsvd1; /* 0016 - Reserved must be cleared to zero */
+ __u8 dssd_ps_descr[WDC_OCP_C4_NUM_PS_DESCR];/* 0017 - DSSD Power State Descriptors */
+ __u8 rsvd2[3934]; /* 0144 - Reserved must be cleared to zero */
+ __le16 log_page_version; /* 4078 - Log Page Version */
+ __u8 log_page_guid[WDC_OCP_C4_GUID_LENGTH]; /* 4080 - Log Page GUID */
+};
+
+static __u8 wdc_ocp_c4_guid[WDC_OCP_C4_GUID_LENGTH] = { 0x97, 0x42, 0x05, 0x0D, 0xD1, 0xE1, 0xC9, 0x98,
+ 0x5D, 0x49, 0x58, 0x4B, 0x91, 0x3C, 0x05, 0xB7 };
+
+#define WDC_OCP_C5_GUID_LENGTH 16
+#define WDC_UNSUPPORTED_REQS_LOG_BUF_LEN 4096
+#define WDC_UNSUPPORTED_REQS_LOG_ID 0xC5
+#define WDC_UNSUPPORTED_REQS_LOG_VERSION 0001
+#define WDC_NUM_UNSUPPORTED_REQ_ENTRIES 253
+
+struct __attribute__((__packed__)) wdc_ocp_C5_unsupported_reqs {
+ __le16 unsupported_count; /* 0000 - Number of Unsupported Requirement IDs */
+ __u8 rsvd1[14]; /* 0002 - Reserved must be cleared to zero */
+ __u8 unsupported_req_list[WDC_NUM_UNSUPPORTED_REQ_ENTRIES][16]; /* 0016 - Unsupported Requirements List */
+ __u8 rsvd2[14]; /* 4064 - Reserved must be cleared to zero */
+ __le16 log_page_version; /* 4078 - Log Page Version */
+ __u8 log_page_guid[WDC_OCP_C5_GUID_LENGTH]; /* 4080 - Log Page GUID */
+};
+
+static __u8 wdc_ocp_c5_guid[WDC_OCP_C5_GUID_LENGTH] = { 0x2F, 0x72, 0x9C, 0x0E, 0x99, 0x23, 0x2C, 0xBB,
+ 0x63, 0x48, 0x32, 0xD0, 0xB7, 0x98, 0xBB, 0xC7 };
+
#define WDC_REASON_INDEX_MAX 16
#define WDC_REASON_ID_ENTRY_LEN 128
#define WDC_REASON_ID_PATH_NAME "/usr/local/nvmecli"
@@ -1043,80 +1119,74 @@ static long double int128_to_double(__u8 *data)
return result;
}
-static int wdc_get_pci_ids(uint32_t *device_id, uint32_t *vendor_id)
+static int wdc_get_pci_ids(nvme_root_t r, uint32_t *device_id,
+ uint32_t *vendor_id)
{
- int fd, ret = -1;
- char *block, path[512], *id;
-
- id = calloc(1, 32);
- if (!id) {
- fprintf(stderr, "ERROR : WDC : %s : calloc failed\n", __func__);
- return -1;
- }
-
- block = nvme_char_from_block((char *)devicename);
+ char vid[256], did[256], id[32];
+ nvme_ctrl_t c = NULL;
+ nvme_ns_t n = NULL;
+ int fd, ret;
- /* read the vendor ID from sys fs */
- sprintf(path, "/sys/class/nvme/%s/device/vendor", block);
+ c = nvme_scan_ctrl(r, devicename);
+ if (c) {
+ snprintf(vid, sizeof(vid), "%s/device/vendor",
+ nvme_ctrl_get_sysfs_dir(c));
+ snprintf(did, sizeof(did), "%s/device/device",
+ nvme_ctrl_get_sysfs_dir(c));
+ nvme_free_ctrl(c);
+ } else {
+ n = nvme_scan_namespace(devicename);
+ if (!n) {
+ fprintf(stderr, "Unable to find %s\n", devicename);
+ return -1;
+ }
- fd = open(path, O_RDONLY);
- if (fd < 0) {
- sprintf(path, "/sys/class/misc/%s/device/vendor", block);
- fd = open(path, O_RDONLY);
+ snprintf(vid, sizeof(vid), "%s/device/device/vendor",
+ nvme_ns_get_sysfs_dir(n));
+ snprintf(did, sizeof(did), "%s/device/device/device",
+ nvme_ns_get_sysfs_dir(n));
+ nvme_free_ns(n);
}
+
+ fd = open(vid, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "ERROR : WDC : %s : Open vendor file failed\n", __func__);
- ret = -1;
- goto free_id;
+ return -1;
}
ret = read(fd, id, 32);
+ close(fd);
+
if (ret < 0) {
fprintf(stderr, "%s: Read of pci vendor id failed\n", __func__);
- ret = -1;
- goto close_fd;
- } else {
- if (id[strlen(id) - 1] == '\n')
- id[strlen(id) - 1] = '\0';
-
- /* convert the device id string to an int */
- *vendor_id = (int)strtol(&id[2], NULL, 16);
- ret = 0;
+ return -1;
}
- /* read the device ID from sys fs */
- sprintf(path, "/sys/class/nvme/%s/device/device", block);
+ if (id[strlen(id) - 1] == '\n')
+ id[strlen(id) - 1] = '\0';
- fd = open(path, O_RDONLY);
- if (fd < 0) {
- sprintf(path, "/sys/class/misc/%s/device/device", block);
- fd = open(path, O_RDONLY);
- }
+ *vendor_id = strtol(id, NULL, 0);
+ ret = 0;
+
+ fd = open(did, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "ERROR : WDC : %s : Open device file failed\n", __func__);
- ret = -1;
- goto close_fd;
+ return -1;
}
ret = read(fd, id, 32);
+ close(fd);
+
if (ret < 0) {
fprintf(stderr, "%s: Read of pci device id failed\n", __func__);
- ret = -1;
- } else {
- if (id[strlen(id) - 1] == '\n')
- id[strlen(id) - 1] = '\0';
-
- /* convert the device id string to an int */
- *device_id = strtol(&id[2], NULL, 16);
- ret = 0;
+ return -1;
}
-close_fd:
- close(fd);
-free_id:
- free(block);
- free(id);
- return ret;
+ if (id[strlen(id) - 1] == '\n')
+ id[strlen(id) - 1] = '\0';
+
+ *device_id = strtol(id, NULL, 0);
+ return 0;
}
static int wdc_get_vendor_id(int fd, uint32_t *vendor_id)
@@ -1164,13 +1234,13 @@ static int wdc_get_model_number(int fd, char *model)
return ret;
}
-static bool wdc_check_device(int fd)
+static bool wdc_check_device(nvme_root_t r, int fd)
{
int ret;
bool supported;
uint32_t read_device_id = -1, read_vendor_id = -1;
- ret = wdc_get_pci_ids(&read_device_id, &read_vendor_id);
+ ret = wdc_get_pci_ids(r, &read_device_id, &read_vendor_id);
if (ret < 0) {
/* Use the identify nvme command to get vendor id due to NVMeOF device. */
if (wdc_get_vendor_id(fd, &read_vendor_id) < 0)
@@ -1210,14 +1280,13 @@ static bool wdc_enc_check_model(int fd)
return supported;
}
-static __u64 wdc_get_drive_capabilities(int fd) {
+static __u64 wdc_get_drive_capabilities(nvme_root_t r, int fd) {
int ret;
uint32_t read_device_id = -1, read_vendor_id = -1;
__u64 capabilities = 0;
- __u8 *data;
- __u32 *cust_id;
+ __u32 cust_id;
- ret = wdc_get_pci_ids(&read_device_id, &read_vendor_id);
+ ret = wdc_get_pci_ids(r, &read_device_id, &read_vendor_id);
if (ret < 0)
{
if (wdc_get_vendor_id(fd, &read_vendor_id) < 0)
@@ -1227,7 +1296,7 @@ static __u64 wdc_get_drive_capabilities(int fd) {
/* below check condition is added due in NVMeOF device we dont have device_id so we need to use only vendor_id*/
if (read_device_id == -1 && read_vendor_id != -1)
{
- capabilities = wdc_get_enc_drive_capabilities(fd);
+ capabilities = wdc_get_enc_drive_capabilities(r, fd);
return capabilities;
}
@@ -1245,11 +1314,11 @@ static __u64 wdc_get_drive_capabilities(int fd) {
WDC_DRIVE_CAP_PURGE);
/* verify the 0xCA log page is supported */
- if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true)
+ if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true)
capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE;
/* verify the 0xC1 log page is supported */
- if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_ADD_LOG_OPCODE) == true)
+ if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_ADD_LOG_OPCODE) == true)
capabilities |= WDC_DRIVE_CAP_C1_LOG_PAGE;
break;
default:
@@ -1265,11 +1334,11 @@ static __u64 wdc_get_drive_capabilities(int fd) {
WDC_DRIVE_CAP_DRIVE_STATUS | WDC_DRIVE_CAP_CLEAR_ASSERT |
WDC_DRIVE_CAP_RESIZE | WDC_DRIVE_CAP_CLEAR_PCIE);
/* verify the 0xCA log page is supported */
- if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true)
+ if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true)
capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE;
/* verify the 0xD0 log page is supported */
- if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true)
+ if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true)
capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE;
break;
case WDC_NVME_SN640_DEV_ID:
@@ -1280,7 +1349,7 @@ static __u64 wdc_get_drive_capabilities(int fd) {
/* FALLTHRU */
case WDC_NVME_SN640_DEV_ID_3:
/* verify the 0xC0 log page is supported */
- if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE) == true) {
+ if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE) == true) {
capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE;
}
@@ -1290,27 +1359,38 @@ static __u64 wdc_get_drive_capabilities(int fd) {
WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG | WDC_DRIVE_CAP_REASON_ID |
WDC_DRIVE_CAP_LOG_PAGE_DIR);
- /* verify the 0xC3 log page is supported */
- if (wdc_nvme_check_supported_log_page(fd, WDC_LATENCY_MON_OPCODE) == true)
+ /* verify the 0xC1 (OCP Error Recovery) log page is supported */
+ if (wdc_nvme_check_supported_log_page(r, fd, WDC_ERROR_REC_LOG_ID) == true)
+ 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, fd, WDC_LATENCY_MON_OPCODE) == true)
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, fd, WDC_DEV_CAP_LOG_ID) == true)
+ capabilities |= WDC_DRIVE_CAP_OCP_C4_LOG_PAGE;
+
+ /* verify the 0xC5 (OCP Unsupported Requirments) log page is supported */
+ if (wdc_nvme_check_supported_log_page(r, fd, WDC_UNSUPPORTED_REQS_LOG_ID) == true)
+ capabilities |= WDC_DRIVE_CAP_OCP_C5_LOG_PAGE;
+
/* verify the 0xCA log page is supported */
- if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true)
+ if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true)
capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE;
/* verify the 0xD0 log page is supported */
- if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true)
+ if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true)
capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE;
- if (!get_dev_mgment_cbs_data(fd, WDC_C2_CUSTOMER_ID_ID, (void*)&data)) {
- fprintf(stderr, "%s: ERROR : WDC : 0xC2 Log Page entry ID 0x%x not found\n", __func__, WDC_C2_CUSTOMER_ID_ID);
+ cust_id = wdc_get_fw_cust_id(r, fd);
+ if (cust_id == WDC_INVALID_CUSTOMER_ID) {
+ fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__);
return -1;
}
- cust_id = (__u32*)data;
-
- if ((*cust_id == WDC_CUSTOMER_ID_0x1004) || (*cust_id == WDC_CUSTOMER_ID_0x1008) ||
- (*cust_id == WDC_CUSTOMER_ID_0x1005) || (*cust_id == WDC_CUSTOMER_ID_0x1304))
+ if ((cust_id == WDC_CUSTOMER_ID_0x1004) || (cust_id == WDC_CUSTOMER_ID_0x1008) ||
+ (cust_id == WDC_CUSTOMER_ID_0x1005) || (cust_id == WDC_CUSTOMER_ID_0x1304))
capabilities |= (WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY | WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE |
WDC_DRIVE_CAP_INFO | WDC_DRIVE_CAP_CLOUD_SSD_VERSION);
else
@@ -1321,7 +1401,7 @@ static __u64 wdc_get_drive_capabilities(int fd) {
/* FALLTHRU */
case WDC_NVME_SN840_DEV_ID_1:
/* verify the 0xC0 log page is supported */
- if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE) == true) {
+ if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE) == true) {
capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE;
}
/* FALLTHRU */
@@ -1337,11 +1417,11 @@ static __u64 wdc_get_drive_capabilities(int fd) {
WDC_DRIVE_CAP_LOG_PAGE_DIR );
/* verify the 0xCA log page is supported */
- if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true)
+ if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true)
capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE;
/* verify the 0xD0 log page is supported */
- if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true)
+ if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true)
capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE;
break;
case WDC_NVME_SN650_DEV_ID:
@@ -1349,17 +1429,19 @@ static __u64 wdc_get_drive_capabilities(int fd) {
case WDC_NVME_SN650_DEV_ID_2:
case WDC_NVME_SN650_DEV_ID_3:
case WDC_NVME_SN650_DEV_ID_4:
- case WDC_NVME_SN450_DEV_ID_1:
- case WDC_NVME_SN450_DEV_ID_2:
+ case WDC_NVME_SN655_DEV_ID:
+ case WDC_NVME_SN560_DEV_ID_1:
+ case WDC_NVME_SN560_DEV_ID_2:
+ case WDC_NVME_SN560_DEV_ID_3:
/* verify the 0xC0 log page is supported */
- if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE) == true) {
+ if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE) == true) {
capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE;
}
capabilities |= (WDC_DRIVE_CAP_CAP_DIAG | WDC_DRIVE_CAP_INTERNAL_LOG |
WDC_DRIVE_CAP_DRIVE_STATUS | WDC_DRIVE_CAP_CLEAR_ASSERT |
WDC_DRIVE_CAP_RESIZE | WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE |
- WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY | WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY |
+ WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY | WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY |
WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG | WDC_DRIVE_CAP_REASON_ID |
WDC_DRIVE_CAP_LOG_PAGE_DIR | WDC_DRIVE_CAP_INFO |
WDC_DRIVE_CAP_CLOUD_SSD_VERSION);
@@ -1384,6 +1466,8 @@ static __u64 wdc_get_drive_capabilities(int fd) {
case WDC_NVME_SN520_DEV_ID_1:
/* FALLTHRU */
case WDC_NVME_SN520_DEV_ID_2:
+ case WDC_NVME_SN530_DEV_ID:
+ case WDC_NVME_SN810_DEV_ID:
capabilities = WDC_DRIVE_CAP_DUI_DATA;
break;
case WDC_NVME_SN720_DEV_ID:
@@ -1393,6 +1477,10 @@ static __u64 wdc_get_drive_capabilities(int fd) {
capabilities = WDC_DRIVE_CAP_DUI | WDC_DRIVE_CAP_NAND_STATS | WDC_DRIVE_CAP_INFO_2
| WDC_DRIVE_CAP_TEMP_STATS | WDC_DRIVE_CAP_VUC_CLEAR_PCIE | WDC_DRIVE_CAP_PCIE_STATS;
break;
+ case WDC_NVME_SN740_DEV_ID:
+ case WDC_NVME_SN740_DEV_ID_1:
+ case WDC_NVME_SN740_DEV_ID_2:
+ case WDC_NVME_SN740_DEV_ID_3:
case WDC_NVME_SN340_DEV_ID:
capabilities = WDC_DRIVE_CAP_DUI;
break;
@@ -1414,12 +1502,11 @@ static __u64 wdc_get_drive_capabilities(int fd) {
return capabilities;
}
-static __u64 wdc_get_enc_drive_capabilities(int fd) {
+static __u64 wdc_get_enc_drive_capabilities(nvme_root_t r, int fd) {
int ret;
uint32_t read_vendor_id;
__u64 capabilities = 0;
- __u8 *data;
- __u32 *cust_id;
+ __u32 cust_id;
ret = wdc_get_vendor_id(fd, &read_vendor_id);
if (ret < 0)
@@ -1431,11 +1518,11 @@ static __u64 wdc_get_enc_drive_capabilities(int fd) {
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(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true)
+ if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true)
capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE;
/* verify the 0xC1 log page is supported */
- if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_ADD_LOG_OPCODE) == true)
+ if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_ADD_LOG_OPCODE) == true)
capabilities |= WDC_DRIVE_CAP_C1_LOG_PAGE;
break;
case WDC_NVME_VID_2:
@@ -1444,30 +1531,29 @@ static __u64 wdc_get_enc_drive_capabilities(int fd) {
WDC_DRIVE_CAP_RESIZE);
/* verify the 0xC3 log page is supported */
- if (wdc_nvme_check_supported_log_page(fd, WDC_LATENCY_MON_OPCODE) == true)
+ if (wdc_nvme_check_supported_log_page(r, fd, WDC_LATENCY_MON_OPCODE) == true)
capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE;
/* verify the 0xCB log page is supported */
- if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID) == true)
+ if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID) == true)
capabilities |= WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY;
/* verify the 0xCA log page is supported */
- if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true)
+ if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true)
capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE;
/* verify the 0xD0 log page is supported */
- if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true)
+ if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true)
capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE;
- if (!get_dev_mgment_cbs_data(fd, WDC_C2_CUSTOMER_ID_ID, (void*)&data)) {
- fprintf(stderr, "%s: ERROR : WDC : 0xC2 Log Page entry ID 0x%x not found\n", __func__, WDC_C2_CUSTOMER_ID_ID);
+ cust_id = wdc_get_fw_cust_id(r, fd);
+ if (cust_id == WDC_INVALID_CUSTOMER_ID) {
+ fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__);
return -1;
}
- cust_id = (__u32*)data;
-
- if ((*cust_id == WDC_CUSTOMER_ID_0x1004) || (*cust_id == WDC_CUSTOMER_ID_0x1008) ||
- (*cust_id == WDC_CUSTOMER_ID_0x1005) || (*cust_id == WDC_CUSTOMER_ID_0x1304))
+ if ((cust_id == WDC_CUSTOMER_ID_0x1004) || (cust_id == WDC_CUSTOMER_ID_0x1008) ||
+ (cust_id == WDC_CUSTOMER_ID_0x1005) || (cust_id == WDC_CUSTOMER_ID_0x1304))
capabilities |= (WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY | WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE);
else
capabilities |= (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY | WDC_DRIVE_CAP_CLEAR_PCIE);
@@ -1655,10 +1741,10 @@ bool wdc_get_dev_mng_log_entry(__u32 log_length,
return valid_log;
}
-static bool get_dev_mgment_cbs_data(int fd, __u8 log_id, void **cbs_data)
+static bool get_dev_mgment_cbs_data(nvme_root_t r, int fd, __u8 log_id, void **cbs_data)
{
int ret = -1;
- __u8* data;
+ void* data;
struct wdc_c2_log_page_header *hdr_ptr;
struct wdc_c2_log_subpage_header *sph;
__u32 length = 0;
@@ -1668,10 +1754,10 @@ static bool get_dev_mgment_cbs_data(int fd, __u8 log_id, void **cbs_data)
*cbs_data = NULL;
__u32 device_id, read_vendor_id;
- ret = wdc_get_pci_ids(&device_id, &read_vendor_id);
+ ret = wdc_get_pci_ids(r, &device_id, &read_vendor_id);
if(device_id == WDC_NVME_ZN350_DEV_ID || device_id == WDC_NVME_ZN350_DEV_ID_1) {
lid = WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE_C8;
- uuid_ix = 0;
+ uuid_ix = 0;
} else
lid = WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE;
@@ -1682,18 +1768,36 @@ static bool get_dev_mgment_cbs_data(int fd, __u8 log_id, void **cbs_data)
memset(data, 0, sizeof (__u8) * WDC_C2_LOG_BUF_LEN);
/* get the log page length */
- ret = nvme_get_log14(fd, 0xFFFFFFFF, lid, NVME_NO_LOG_LSP, 0, 0, false, uuid_ix, 0, false, WDC_C2_LOG_BUF_LEN, data);
+ struct nvme_get_log_args args_len = {
+ .args_size = sizeof(args_len),
+ .fd = fd,
+ .lid = lid,
+ .nsid = 0xFFFFFFFF,
+ .lpo = 0,
+ .lsp = NVME_LOG_LSP_NONE,
+ .lsi = 0,
+ .rae = false,
+ .uuidx = uuid_ix,
+ .csi = NVME_CSI_NVM,
+ .ot = false,
+ .len = WDC_C2_LOG_BUF_LEN,
+ .log = data,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ ret = nvme_get_log(&args_len);
if (ret) {
fprintf(stderr, "ERROR : WDC : Unable to get 0x%x Log Page length, ret = 0x%x\n", lid, ret);
goto end;
}
hdr_ptr = (struct wdc_c2_log_page_header *)data;
+ length = le32_to_cpu(hdr_ptr->length);
- if (le32_to_cpu(hdr_ptr->length) > WDC_C2_LOG_BUF_LEN) {
+ if (length > WDC_C2_LOG_BUF_LEN) {
/* Log Page buffer too small, free and reallocate the necessary size */
free(data);
- data = calloc(le32_to_cpu(hdr_ptr->length), sizeof(__u8));
+ data = calloc(length, sizeof(__u8));
if (data == NULL) {
fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno));
return false;
@@ -1701,7 +1805,25 @@ static bool get_dev_mgment_cbs_data(int fd, __u8 log_id, void **cbs_data)
}
/* get the log page data */
- ret = nvme_get_log14(fd, 0xFFFFFFFF, lid, NVME_NO_LOG_LSP, 0, 0, false, uuid_ix, 0, false, le32_to_cpu(hdr_ptr->length), data);
+ struct nvme_get_log_args args_data = {
+ .args_size = sizeof(args_data),
+ .fd = fd,
+ .lid = lid,
+ .nsid = 0xFFFFFFFF,
+ .lpo = 0,
+ .lsp = NVME_LOG_LSP_NONE,
+ .lsi = 0,
+ .rae = false,
+ .uuidx = uuid_ix,
+ .csi = NVME_CSI_NVM,
+ .ot = false,
+ .len = length,
+ .log = data,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ ret = nvme_get_log(&args_data);
+
if (ret) {
fprintf(stderr, "ERROR : WDC : Unable to read 0x%x Log Page data, ret = 0x%x\n", lid, ret);
goto end;
@@ -1712,20 +1834,48 @@ static bool get_dev_mgment_cbs_data(int fd, __u8 log_id, void **cbs_data)
length = sizeof(struct wdc_c2_log_page_header);
hdr_ptr = (struct wdc_c2_log_page_header *)data;
sph = (struct wdc_c2_log_subpage_header *)(data + length);
- found = wdc_get_dev_mng_log_entry(hdr_ptr->length, log_id, hdr_ptr, &sph);
-
+ found = wdc_get_dev_mng_log_entry(le32_to_cpu(hdr_ptr->length), log_id, hdr_ptr, &sph);
if (found) {
- *cbs_data = (void *)&sph->data;
+ *cbs_data = calloc(le32_to_cpu(sph->length), sizeof(__u8));
+ if (*cbs_data == NULL) {
+ fprintf(stderr, "ERROR : WDC : calloc : %s\n", strerror(errno));
+ goto end;
+ }
+ memcpy((void *)*cbs_data, (void *)&sph->data, le32_to_cpu(sph->length));
} else {
/* not found with uuid = 1 try with uuid = 0 */
uuid_ix = 0;
/* get the log page data */
- ret = nvme_get_log14(fd, 0xFFFFFFFF, lid, NVME_NO_LOG_LSP, 0, 0, false, uuid_ix, 0, false, le32_to_cpu(hdr_ptr->length), data);
+ struct nvme_get_log_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .lid = lid,
+ .nsid = 0xFFFFFFFF,
+ .lpo = 0,
+ .lsp = NVME_LOG_LSP_NONE,
+ .lsi = 0,
+ .rae = false,
+ .uuidx = uuid_ix,
+ .csi = NVME_CSI_NVM,
+ .ot = false,
+ .len = le32_to_cpu(hdr_ptr->length),
+ .log = data,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ ret = nvme_get_log(&args);
+
hdr_ptr = (struct wdc_c2_log_page_header *)data;
sph = (struct wdc_c2_log_subpage_header *)(data + length);
- found = wdc_get_dev_mng_log_entry(hdr_ptr->length, log_id, hdr_ptr, &sph);
+ found = wdc_get_dev_mng_log_entry(le32_to_cpu(hdr_ptr->length), log_id, hdr_ptr, &sph);
if (found) {
- *cbs_data = (void *)&sph->data;
+ *cbs_data = calloc(le32_to_cpu(sph->length), sizeof(__u8));
+ if (*cbs_data == NULL) {
+ fprintf(stderr, "ERROR : WDC : calloc : %s\n", strerror(errno));
+ goto end;
+ }
+ memcpy((void *)*cbs_data, (void *)&sph->data, le32_to_cpu(sph->length));
+
} else {
/* WD version not found */
fprintf(stderr, "ERROR : WDC : Unable to find correct version of page 0x%x, entry id = %d\n", lid, log_id);
@@ -1736,13 +1886,13 @@ end:
return found;
}
-static bool wdc_nvme_check_supported_log_page(int fd, __u8 log_id)
+static bool wdc_nvme_check_supported_log_page(nvme_root_t r, int fd, __u8 log_id)
{
int i;
bool found = false;
struct wdc_c2_cbs_data *cbs_data = NULL;
- if (get_dev_mgment_cbs_data(fd, WDC_C2_LOG_PAGES_SUPPORTED_ID, (void *)&cbs_data)) {
+ if (get_dev_mgment_cbs_data(r, fd, WDC_C2_LOG_PAGES_SUPPORTED_ID, (void *)&cbs_data)) {
if (cbs_data != NULL) {
for (i = 0; i < le32_to_cpu(cbs_data->length); i++) {
if (log_id == cbs_data->data[i]) {
@@ -1759,6 +1909,7 @@ static bool wdc_nvme_check_supported_log_page(int fd, __u8 log_id)
d((__u8 *)cbs_data->data, le32_to_cpu(cbs_data->length), 16, 1);
}
#endif
+ free(cbs_data);
} else
fprintf(stderr, "ERROR : WDC : cbs_data ptr = NULL\n");
} else
@@ -1767,14 +1918,16 @@ static bool wdc_nvme_check_supported_log_page(int fd, __u8 log_id)
return found;
}
-static bool wdc_nvme_get_dev_status_log_data(int fd, __le32 *ret_data,
+static bool wdc_nvme_get_dev_status_log_data(nvme_root_t r, int fd, __le32 *ret_data,
__u8 log_id)
{
__u32 *cbs_data = NULL;
- if (get_dev_mgment_cbs_data(fd, log_id, (void *)&cbs_data)) {
+ if (get_dev_mgment_cbs_data(r, fd, log_id, (void *)&cbs_data)) {
if (cbs_data != NULL) {
memcpy((void *)ret_data, (void *)cbs_data, 4);
+ free(cbs_data);
+
return true;
}
}
@@ -1786,16 +1939,16 @@ static bool wdc_nvme_get_dev_status_log_data(int fd, __le32 *ret_data,
static int wdc_do_clear_dump(int fd, __u8 opcode, __u32 cdw12)
{
int ret;
- struct nvme_admin_cmd admin_cmd;
+ struct nvme_passthru_cmd admin_cmd;
- memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd));
+ memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd));
admin_cmd.opcode = opcode;
admin_cmd.cdw12 = cdw12;
- ret = nvme_submit_admin_passthru(fd, &admin_cmd);
+ ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL);
if (ret != 0) {
fprintf(stdout, "ERROR : WDC : Crash dump erase failed\n");
}
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
return ret;
}
@@ -1804,22 +1957,22 @@ static __u32 wdc_dump_length(int fd, __u32 opcode, __u32 cdw10, __u32 cdw12, __u
int ret;
__u8 buf[WDC_NVME_LOG_SIZE_DATA_LEN] = {0};
struct wdc_log_size *l;
- struct nvme_admin_cmd admin_cmd;
+ struct nvme_passthru_cmd admin_cmd;
l = (struct wdc_log_size *) buf;
- memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd));
+ memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd));
admin_cmd.opcode = opcode;
admin_cmd.addr = (__u64)(uintptr_t)buf;
admin_cmd.data_len = WDC_NVME_LOG_SIZE_DATA_LEN;
admin_cmd.cdw10 = cdw10;
admin_cmd.cdw12 = cdw12;
- ret = nvme_submit_admin_passthru(fd, &admin_cmd);
+ ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL);
if (ret != 0) {
l->log_size = 0;
ret = -1;
fprintf(stderr, "ERROR : WDC : reading dump length failed\n");
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
return ret;
}
@@ -1833,19 +1986,19 @@ static __u32 wdc_dump_length(int fd, __u32 opcode, __u32 cdw10, __u32 cdw12, __u
static __u32 wdc_dump_length_e6(int fd, __u32 opcode, __u32 cdw10, __u32 cdw12, struct wdc_e6_log_hdr *dump_hdr)
{
int ret;
- struct nvme_admin_cmd admin_cmd;
+ struct nvme_passthru_cmd admin_cmd;
- memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd));
+ memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd));
admin_cmd.opcode = opcode;
admin_cmd.addr = (__u64)(uintptr_t)dump_hdr;
admin_cmd.data_len = WDC_NVME_LOG_SIZE_HDR_LEN;
admin_cmd.cdw10 = cdw10;
admin_cmd.cdw12 = cdw12;
- ret = nvme_submit_admin_passthru(fd, &admin_cmd);
+ ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL);
if (ret != 0) {
fprintf(stderr, "ERROR : WDC : reading dump length failed\n");
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
}
return ret;
@@ -1854,9 +2007,9 @@ static __u32 wdc_dump_length_e6(int fd, __u32 opcode, __u32 cdw10, __u32 cdw12,
static __u32 wdc_dump_dui_data(int fd, __u32 dataLen, __u32 offset, __u8 *dump_data, bool last_xfer)
{
int ret;
- struct nvme_admin_cmd admin_cmd;
+ struct nvme_passthru_cmd admin_cmd;
- memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd));
+ memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd));
admin_cmd.opcode = WDC_NVME_CAP_DUI_OPCODE;
admin_cmd.nsid = 0xFFFFFFFF;
admin_cmd.addr = (__u64)(uintptr_t)dump_data;
@@ -1869,10 +2022,10 @@ static __u32 wdc_dump_dui_data(int fd, __u32 dataLen, __u32 offset, __u8 *dump_d
admin_cmd.cdw14 = WDC_NVME_CAP_DUI_DISABLE_IO;
- ret = nvme_submit_admin_passthru(fd, &admin_cmd);
+ ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL);
if (ret != 0) {
fprintf(stderr, "ERROR : WDC : reading DUI data failed\n");
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
}
return ret;
@@ -1881,10 +2034,10 @@ static __u32 wdc_dump_dui_data(int fd, __u32 dataLen, __u32 offset, __u8 *dump_d
static __u32 wdc_dump_dui_data_v2(int fd, __u32 dataLen, __u64 offset, __u8 *dump_data, bool last_xfer)
{
int ret;
- struct nvme_admin_cmd admin_cmd;
+ struct nvme_passthru_cmd admin_cmd;
__u64 offset_lo, offset_hi;
- memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd));
+ memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd));
admin_cmd.opcode = WDC_NVME_CAP_DUI_OPCODE;
admin_cmd.nsid = 0xFFFFFFFF;
admin_cmd.addr = (__u64)(uintptr_t)dump_data;
@@ -1900,10 +2053,10 @@ static __u32 wdc_dump_dui_data_v2(int fd, __u32 dataLen, __u64 offset, __u8 *dum
else
admin_cmd.cdw14 = WDC_NVME_CAP_DUI_DISABLE_IO;
- ret = nvme_submit_admin_passthru(fd, &admin_cmd);
+ ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL);
if (ret != 0) {
fprintf(stderr, "ERROR : WDC : reading DUI data V2 failed\n");
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
}
return ret;
@@ -1916,7 +2069,7 @@ static int wdc_do_dump(int fd, __u32 opcode,__u32 data_len,
__u8 *dump_data;
__u32 curr_data_offset, curr_data_len;
int i;
- struct nvme_admin_cmd admin_cmd;
+ struct nvme_passthru_cmd admin_cmd;
__u32 dump_length = data_len;
dump_data = (__u8 *) malloc(sizeof (__u8) * dump_length);
@@ -1925,7 +2078,7 @@ static int wdc_do_dump(int fd, __u32 opcode,__u32 data_len,
return -1;
}
memset(dump_data, 0, sizeof (__u8) * dump_length);
- memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd));
+ memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd));
curr_data_offset = 0;
curr_data_len = xfer_size;
i = 0;
@@ -1938,10 +2091,9 @@ static int wdc_do_dump(int fd, __u32 opcode,__u32 data_len,
admin_cmd.cdw13 = curr_data_offset;
while (curr_data_offset < data_len) {
- ret = nvme_submit_admin_passthru(fd, &admin_cmd);
+ ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL);
if (ret != 0) {
- fprintf(stderr, "%s: ERROR : WDC : NVMe Status:%s(%x)\n",
- __func__, nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
fprintf(stderr, "%s: ERROR : WDC : Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx\n",
__func__, i, admin_cmd.data_len, curr_data_offset, (long unsigned int)admin_cmd.addr);
break;
@@ -1961,7 +2113,7 @@ static int wdc_do_dump(int fd, __u32 opcode,__u32 data_len,
}
if (ret == 0) {
- fprintf(stderr, "%s: NVMe Status:%s(%x)\n", __func__, nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
ret = wdc_create_log_file(file, dump_data, dump_length);
}
free(dump_data);
@@ -1975,7 +2127,7 @@ static int wdc_do_dump_e6(int fd, __u32 opcode,__u32 data_len,
__u8 *dump_data;
__u32 curr_data_offset, log_size;
int i;
- struct nvme_admin_cmd admin_cmd;
+ struct nvme_passthru_cmd admin_cmd;
dump_data = (__u8 *) malloc(sizeof (__u8) * data_len);
@@ -1984,7 +2136,7 @@ static int wdc_do_dump_e6(int fd, __u32 opcode,__u32 data_len,
return -1;
}
memset(dump_data, 0, sizeof (__u8) * data_len);
- memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd));
+ memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd));
curr_data_offset = WDC_NVME_LOG_SIZE_HDR_LEN;
i = 0;
@@ -2003,9 +2155,9 @@ static int wdc_do_dump_e6(int fd, __u32 opcode,__u32 data_len,
admin_cmd.cdw10 = xfer_size >> 2;
admin_cmd.cdw13 = curr_data_offset >> 2;
- ret = nvme_submit_admin_passthru(fd, &admin_cmd);
+ ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL);
if (ret != 0) {
- fprintf(stderr, "%s: ERROR : WDC : NVMe Status:%s(%x)\n", __func__, nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
fprintf(stderr, "%s: ERROR : WDC : Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx\n",
__func__, i, admin_cmd.data_len, curr_data_offset, (long unsigned int)admin_cmd.addr);
break;
@@ -2017,9 +2169,11 @@ static int wdc_do_dump_e6(int fd, __u32 opcode,__u32 data_len,
}
if (ret == 0) {
- fprintf(stderr, "%s: NVMe Status:%s(%x)\n", __func__, nvme_status_to_string(ret), ret);
+ fprintf(stderr, "%s: ", __func__);
+ nvme_show_status(ret);
} else {
- fprintf(stderr, "%s: FAILURE: NVMe Status:%s(%x)\n", __func__, nvme_status_to_string(ret), ret);
+ fprintf(stderr, "%s: FAILURE: ", __func__);
+ nvme_show_status(ret);
fprintf(stderr, "%s: Partial data may have been captured\n", __func__);
snprintf(file + strlen(file), PATH_MAX, "%s", "-PARTIAL");
}
@@ -2032,40 +2186,66 @@ static int wdc_do_dump_e6(int fd, __u32 opcode,__u32 data_len,
static int wdc_do_cap_telemetry_log(int fd, char *file, __u32 bs, int type, int data_area)
{
- struct nvme_telemetry_log_page_hdr *hdr;
- struct nvme_id_ctrl ctrl;
- size_t full_size, offset = WDC_TELEMETRY_HEADER_LENGTH;
+ struct nvme_telemetry_log *log;
+ size_t full_size = 0;
int err = 0, output;
- void *page_log;
__u32 host_gen = 1;
int ctrl_init = 0;
__u32 result;
void *buf = NULL;
+ __u8 *data_ptr = NULL;
+ int data_written = 0, data_remaining = 0;
+ struct nvme_id_ctrl ctrl;
+ __u64 capabilities = 0;
+ nvme_root_t r;
+ memset(&ctrl, 0, sizeof (struct nvme_id_ctrl));
+ err = nvme_identify_ctrl(fd, &ctrl);
+ if (err) {
+ fprintf(stderr, "ERROR : WDC : nvme_identify_ctrl() failed "
+ "0x%x\n", err);
+ goto close_fd;
+ }
+
+ if (!(ctrl.lpa & 0x8)) {
+ fprintf(stderr, "Telemetry Host-Initiated and Telemetry Controller-Initiated log pages not supported\n");
+ err = -EINVAL;
+ goto close_fd;
+ }
+
+ r = nvme_scan(NULL);
+ capabilities = wdc_get_drive_capabilities(r, fd);
if (type == WDC_TELEMETRY_TYPE_HOST) {
host_gen = 1;
ctrl_init = 0;
} else if (type == WDC_TELEMETRY_TYPE_CONTROLLER) {
- /* Verify the Controller Initiated Option is enabled */
- err = nvme_get_feature(fd, 0, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0, 0,
- 0, 4, buf, &result);
- if (err == 0) {
- if (result == 0) {
- /* enabled */
- host_gen = 0;
- ctrl_init = 1;
+ if ((capabilities & WDC_DRIVE_CAP_INTERNAL_LOG) == WDC_DRIVE_CAP_INTERNAL_LOG) {
+ /* Verify the Controller Initiated Option is enabled */
+ err = nvme_get_features_data(fd, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0,
+ 4, buf, &result);
+ if (err == 0) {
+ if (result == 0) {
+ /* enabled */
+ host_gen = 0;
+ ctrl_init = 1;
+ }
+ else {
+ fprintf(stderr, "%s: Controller initiated option telemetry log page disabled\n", __func__);
+ err = -EINVAL;
+ goto close_fd;
+ }
}
else {
- fprintf(stderr, "%s: Controller initiated option telemetry log page disabled\n", __func__);
- err = -EINVAL;
+ fprintf(stderr, "ERROR : WDC: Get telemetry option feature failed.");
+ nvme_show_status(err);
+ err = -EPERM;
goto close_fd;
}
- } else {
- fprintf(stderr, "ERROR : WDC: Get telemetry option feature failed. NVMe Status:%s(%x)\n",
- nvme_status_to_string(err), err);
- err = -EPERM;
- goto close_fd;
+ }
+ else {
+ host_gen = 0;
+ ctrl_init = 1;
}
} else {
fprintf(stderr, "%s: Invalid type parameter; type = %d\n", __func__, type);
@@ -2079,25 +2259,21 @@ static int wdc_do_cap_telemetry_log(int fd, char *file, __u32 bs, int type, int
goto close_fd;
}
- hdr = malloc(bs);
- page_log = malloc(bs);
- if (!hdr || !page_log) {
- fprintf(stderr, "%s: Failed to allocate 0x%x bytes for log: %s\n",
- __func__, bs, strerror(errno));
- err = -ENOMEM;
- goto free_mem;
- }
- memset(hdr, 0, bs);
-
output = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (output < 0) {
fprintf(stderr, "%s: Failed to open output file %s: %s!\n",
__func__, file, strerror(errno));
err = output;
- goto free_mem;
+ goto close_fd;
}
- err = nvme_get_telemetry_log(fd, hdr, host_gen, ctrl_init, WDC_TELEMETRY_HEADER_LENGTH, 0);
+ if (ctrl_init)
+ err = nvme_get_ctrl_telemetry(fd, true, &log, data_area, &full_size);
+ else if (host_gen)
+ err = nvme_get_new_host_telemetry(fd, &log, data_area, &full_size);
+ else
+ err = nvme_get_host_telemetry(fd, &log, data_area, &full_size);
+
if (err < 0)
perror("get-telemetry-log");
else if (err > 0) {
@@ -2106,102 +2282,39 @@ static int wdc_do_cap_telemetry_log(int fd, char *file, __u32 bs, int type, int
goto close_output;
}
- err = write(output, (void *) hdr, WDC_TELEMETRY_HEADER_LENGTH);
- if (err != WDC_TELEMETRY_HEADER_LENGTH) {
- fprintf(stderr, "%s: Failed to flush header data to file!, err = %d\n", __func__, err);
- goto close_output;
- }
-
- switch (data_area) {
- case 1:
- full_size = (le16_to_cpu(hdr->dalb1) * WDC_TELEMETRY_BLOCK_SIZE) + WDC_TELEMETRY_HEADER_LENGTH;
- break;
- case 2:
- full_size = (le16_to_cpu(hdr->dalb2) * WDC_TELEMETRY_BLOCK_SIZE) + WDC_TELEMETRY_HEADER_LENGTH;
- break;
- case 3:
- full_size = (le16_to_cpu(hdr->dalb3) * WDC_TELEMETRY_BLOCK_SIZE) + WDC_TELEMETRY_HEADER_LENGTH;
- break;
- case 4:
- err = nvme_identify_ctrl(fd, &ctrl);
- if (err) {
- perror("identify-ctrl");
- goto close_output;
- }
-
- if (posix_memalign(&buf, getpagesize(), get_feat_buf_len(NVME_FEAT_HOST_BEHAVIOR))) {
- fprintf(stderr, "can not allocate feature payload\n");
- errno = ENOMEM;
- err = -1;
- goto close_output;
- }
- memset(buf, 0, get_feat_buf_len(NVME_FEAT_HOST_BEHAVIOR));
-
- err = nvme_get_feature(fd, NVME_NSID_ALL, NVME_FEAT_HOST_BEHAVIOR, 0, 0,
- 0, get_feat_buf_len(NVME_FEAT_HOST_BEHAVIOR), buf, &result);
- if (err > 0) {
- nvme_show_status(err);
- } else if (err < 0) {
- perror("get-feature");
- } else {
- if ((ctrl.lpa & 0x40)) {
- if (((unsigned char *)buf)[1] == 1)
- full_size = (le32_to_cpu(hdr->dalb4) * WDC_TELEMETRY_BLOCK_SIZE) + WDC_TELEMETRY_HEADER_LENGTH;
- else {
- fprintf(stderr, "Data area 4 unsupported, Host Behavior Support ETDAS not set to 1\n");
- errno = EINVAL;
- err = -1;
- }
- } else {
- fprintf(stderr, "Data area 4 unsupported, bit 6 of Log Page Attributes not set\n");
- errno = EINVAL;
- err = -1;
- }
- }
- free(buf);
- if (err)
- goto close_output;
- break;
- default:
- fprintf(stderr, "%s: Invalid data area requested, data area = %d\n", __func__, data_area);
- err = -EINVAL;
- goto close_output;
- }
-
/*
* Continuously pull data until the offset hits the end of the last
* block.
*/
- while (offset < full_size) {
- if ((full_size - offset) < bs)
- bs = (full_size - offset);
+ data_written = 0;
+ data_remaining = full_size;
+ data_ptr = (__u8 *)log;
+ while (data_remaining) {
+ data_written = write(output, data_ptr, data_remaining);
- err = nvme_get_telemetry_log(fd, page_log, 0, ctrl_init, bs, offset);
- if (err < 0) {
- perror("get-telemetry-log");
+ if (data_written < 0) {
+ data_remaining = data_written;
break;
- } else if (err > 0) {
- nvme_show_status(err);
- fprintf(stderr, "%s: Failed to acquire full telemetry log!\n", __func__);
- nvme_show_status(err);
+ } else if (data_written <= data_remaining) {
+ data_remaining -= data_written;
+ data_ptr += data_written;
+ } else {
+ /* Unexpected overwrite */
+ fprintf(stderr, "Failure: Unexpected telemetry log overwrite - data_remaining = 0x%x, data_written = 0x%x\n",
+ data_remaining, data_written);
break;
}
+ }
- err = write(output, (void *) page_log, bs);
- if (err != bs) {
- fprintf(stderr, "%s: Failed to flush telemetry data to file!, err = %d\n", __func__, err);
- break;
- }
- err = 0;
- offset += bs;
+ if (fsync(output) < 0) {
+ fprintf(stderr, "ERROR : %s: fsync : %s\n", __func__, strerror(errno));
+ return -1;
}
+ free(log);
close_output:
close(output);
-free_mem:
- free(hdr);
- free(page_log);
close_fd:
close(fd);
@@ -2209,7 +2322,8 @@ close_fd:
}
-static int wdc_do_cap_diag(int fd, char *file, __u32 xfer_size, int type, int data_area)
+static int wdc_do_cap_diag(nvme_root_t r, int fd, char *file,
+ __u32 xfer_size, int type, int data_area)
{
int ret = -1;
__u32 e6_log_hdr_size = WDC_NVME_CAP_DIAG_HEADER_TOC_SIZE;
@@ -2287,7 +2401,8 @@ static int wdc_do_cap_dui(int fd, char *file, __u32 xfer_size, int data_area, in
ret = wdc_dump_dui_data(fd, WDC_NVME_CAP_DUI_HEADER_SIZE, 0x00, (__u8 *)log_hdr, last_xfer);
if (ret != 0) {
fprintf(stderr, "%s: ERROR : WDC : Get DUI headers failed\n", __func__);
- fprintf(stderr, "%s: ERROR : WDC : NVMe Status:%s(%x)\n", __func__, nvme_status_to_string(ret), ret);
+ fprintf(stderr, "%s: ERROR : WDC : ", __func__);
+ nvme_show_status(ret);
goto out;
}
@@ -2368,7 +2483,9 @@ static int wdc_do_cap_dui(int fd, char *file, __u32 xfer_size, int data_area, in
if (ret != 0) {
fprintf(stderr, "%s: ERROR : WDC : Get chunk %d, size = 0x%"PRIx64", offset = 0x%x, addr = %p\n",
__func__, i, (uint64_t)log_size, curr_data_offset, buffer_addr);
- fprintf(stderr, "%s: ERROR : WDC : NVMe Status:%s(%x)\n", __func__, nvme_status_to_string(ret), ret);
+ fprintf(stderr, "%s: ERROR : WDC : ",
+ __func__);
+ nvme_show_status(ret);
break;
}
@@ -2480,7 +2597,8 @@ static int wdc_do_cap_dui(int fd, char *file, __u32 xfer_size, int data_area, in
if (ret != 0) {
fprintf(stderr, "%s: ERROR : WDC : Get chunk %d, size = 0x%"PRIx64", offset = 0x%"PRIx64", addr = %p\n",
__func__, i, (uint64_t)total_size, (uint64_t)curr_data_offset, buffer_addr);
- fprintf(stderr, "%s: ERROR : WDC : NVMe Status:%s(%x)\n", __func__, nvme_status_to_string(ret), ret);
+ fprintf(stderr, "%s: ERROR : WDC : ", __func__);
+ nvme_show_status(ret);
break;
}
@@ -2594,7 +2712,8 @@ static int wdc_do_cap_dui(int fd, char *file, __u32 xfer_size, int data_area, in
if (ret != 0) {
fprintf(stderr, "%s: ERROR : WDC : Get chunk %d, size = 0x%"PRIx64", offset = 0x%"PRIx64", addr = %p\n",
__func__, i, (uint64_t)log_size, (uint64_t)curr_data_offset, buffer_addr);
- fprintf(stderr, "%s: ERROR : WDC : NVMe Status:%s(%x)\n", __func__, nvme_status_to_string(ret), ret);
+ fprintf(stderr, "%s: ERROR : WDC :", __func__);
+ nvme_show_status(ret);
break;
}
@@ -2616,8 +2735,7 @@ static int wdc_do_cap_dui(int fd, char *file, __u32 xfer_size, int data_area, in
goto out;
}
-
- fprintf(stderr, "%s: NVMe Status:%s(%x)\n", __func__, nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
if (verbose)
fprintf(stderr, "INFO : WDC : Capture Device Unit Info log, length = 0x%"PRIx64"\n", (uint64_t)total_size);
@@ -2633,6 +2751,7 @@ static int wdc_do_cap_dui(int fd, char *file, __u32 xfer_size, int data_area, in
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.";
@@ -2657,6 +2776,8 @@ static int wdc_cap_diag(int argc, char **argv, struct command *command,
OPT_END()
};
+ r = nvme_scan(NULL);
+
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0)
return fd;
@@ -2672,11 +2793,12 @@ static int wdc_cap_diag(int argc, char **argv, struct command *command,
if (cfg.file == NULL)
snprintf(f + strlen(f), PATH_MAX, "%s", ".bin");
- capabilities = wdc_get_drive_capabilities(fd);
+ capabilities = wdc_get_drive_capabilities(r, fd);
if ((capabilities & WDC_DRIVE_CAP_CAP_DIAG) == WDC_DRIVE_CAP_CAP_DIAG)
- return wdc_do_cap_diag(fd, f, xfer_size, 0, 0);
+ return wdc_do_cap_diag(r, fd, f, xfer_size, 0, 0);
fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
+ nvme_free_tree(r);
return 0;
}
@@ -2684,14 +2806,14 @@ static int wdc_do_get_sn730_log_len(int fd, uint32_t *len_buf, uint32_t subopcod
{
int ret;
uint32_t *output = NULL;
- struct nvme_admin_cmd admin_cmd;
+ struct nvme_passthru_cmd admin_cmd;
if ((output = (uint32_t*)malloc(sizeof(uint32_t))) == NULL) {
fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno));
return -1;
}
memset(output, 0, sizeof (uint32_t));
- memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd));
+ memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd));
admin_cmd.data_len = 8;
admin_cmd.opcode = SN730_NVME_GET_LOG_OPCODE;
@@ -2699,7 +2821,7 @@ static int wdc_do_get_sn730_log_len(int fd, uint32_t *len_buf, uint32_t subopcod
admin_cmd.cdw12 = subopcode;
admin_cmd.cdw10 = SN730_LOG_CHUNK_SIZE / 4;
- ret = nvme_submit_admin_passthru(fd, &admin_cmd);
+ ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL);
if (ret == 0)
*len_buf = *output;
free(output);
@@ -2710,13 +2832,13 @@ static int wdc_do_get_sn730_log(int fd, void * log_buf, uint32_t offset, uint32_
{
int ret;
uint8_t *output = NULL;
- struct nvme_admin_cmd admin_cmd;
+ struct nvme_passthru_cmd admin_cmd;
if ((output = (uint8_t*)calloc(SN730_LOG_CHUNK_SIZE, sizeof(uint8_t))) == NULL) {
fprintf(stderr, "ERROR : WDC : calloc : %s\n", strerror(errno));
return -1;
}
- memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd));
+ memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd));
admin_cmd.data_len = SN730_LOG_CHUNK_SIZE;
admin_cmd.opcode = SN730_NVME_GET_LOG_OPCODE;
admin_cmd.addr = (uintptr_t)output;
@@ -2724,7 +2846,7 @@ static int wdc_do_get_sn730_log(int fd, void * log_buf, uint32_t offset, uint32_
admin_cmd.cdw13 = offset;
admin_cmd.cdw10 = SN730_LOG_CHUNK_SIZE / 4;
- ret = nvme_submit_admin_passthru(fd, &admin_cmd);
+ ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL);
if (!ret)
memcpy(log_buf, output, SN730_LOG_CHUNK_SIZE);
return ret;
@@ -2816,22 +2938,22 @@ static int wdc_do_sn730_get_and_tar(int fd, char * outputName)
ret = wdc_do_get_sn730_log_len(fd, &full_log_len, SN730_GET_FULL_LOG_LENGTH);
if (ret) {
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
goto free_buf;
}
ret = wdc_do_get_sn730_log_len(fd, &key_log_len, SN730_GET_KEY_LOG_LENGTH);
if (ret) {
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
goto free_buf;
}
ret = wdc_do_get_sn730_log_len(fd, &core_dump_log_len, SN730_GET_COREDUMP_LOG_LENGTH);
if (ret) {
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
goto free_buf;
}
ret = wdc_do_get_sn730_log_len(fd, &extended_log_len, SN730_GET_EXTENDED_LOG_LENGTH);
if (ret) {
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
goto free_buf;
}
@@ -2849,28 +2971,28 @@ static int wdc_do_sn730_get_and_tar(int fd, char * outputName)
/* Get the full log */
ret = get_sn730_log_chunks(fd, full_log_buf, full_log_len, SN730_GET_FULL_LOG_SUBOPCODE);
if (ret) {
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
goto free_buf;
}
/* Get the key log */
ret = get_sn730_log_chunks(fd, key_log_buf, key_log_len, SN730_GET_KEY_LOG_SUBOPCODE);
if (ret) {
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
goto free_buf;
}
/* Get the core dump log */
ret = get_sn730_log_chunks(fd, core_dump_log_buf, core_dump_log_len, SN730_GET_CORE_LOG_SUBOPCODE);
if (ret) {
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
goto free_buf;
}
/* Get the extended log */
ret = get_sn730_log_chunks(fd, extended_log_buf, extended_log_len, SN730_GET_EXTEND_LOG_SUBOPCODE);
if (ret) {
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
goto free_buf;
}
@@ -2919,10 +3041,11 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command
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 SN640 and SN840 devices.";
+ 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.";
char f[PATH_MAX] = {0};
char fileSuffix[PATH_MAX] = {0};
+ nvme_root_t r;
__u32 xfer_size = 0;
int fd;
int telemetry_type = 0, telemetry_data_area = 0;
@@ -2937,7 +3060,7 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command
__u64 file_size;
__u64 offset;
char *type;
- int verbose;
+ bool verbose;
};
struct config cfg = {
@@ -2947,7 +3070,7 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command
.file_size = 0,
.offset = 0,
.type = NULL,
- .verbose = 0,
+ .verbose = false,
};
OPT_ARGS(opts) = {
@@ -2965,12 +3088,16 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command
if (fd < 0)
return fd;
- if (!wdc_check_device(fd))
+ r = nvme_scan(NULL);
+ if (!wdc_check_device(r, fd)) {
+ nvme_free_tree(r);
return -1;
+ }
if (cfg.xfer_size != 0)
xfer_size = cfg.xfer_size;
else {
fprintf(stderr, "ERROR : WDC : Invalid length\n");
+ nvme_free_tree(r);
return -1;
}
@@ -3010,43 +3137,64 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command
}
}
- capabilities = wdc_get_drive_capabilities(fd);
+ if ((cfg.type == NULL) ||
+ (!strcmp(cfg.type, "NONE")) ||
+ (!strcmp(cfg.type, "none"))) {
+ telemetry_type = WDC_TELEMETRY_TYPE_NONE;
+ data_area = 0;
+ } else if ((!strcmp(cfg.type, "HOST")) ||
+ (!strcmp(cfg.type, "host"))) {
+ telemetry_type = WDC_TELEMETRY_TYPE_HOST;
+ telemetry_data_area = cfg.data_area;
+ } else if ((!strcmp(cfg.type, "CONTROLLER")) ||
+ (!strcmp(cfg.type, "controller"))) {
+ telemetry_type = WDC_TELEMETRY_TYPE_CONTROLLER;
+ telemetry_data_area = cfg.data_area;
+ } else {
+ fprintf(stderr, "ERROR : WDC: Invalid type - Must be NONE, HOST or CONTROLLER\n");
+ return -1;
+ }
+
+ capabilities = wdc_get_drive_capabilities(r, fd);
if ((capabilities & WDC_DRIVE_CAP_INTERNAL_LOG) == WDC_DRIVE_CAP_INTERNAL_LOG) {
- if (cfg.data_area == 0)
- cfg.data_area = 3; /* Set the default DA to 3 if not specified */
-
- if ((cfg.type == NULL) ||
- (!strcmp(cfg.type, "NONE")) ||
- (!strcmp(cfg.type, "none"))) {
- telemetry_type = WDC_TELEMETRY_TYPE_NONE;
- data_area = 0;
- } else if ((!strcmp(cfg.type, "HOST")) ||
- (!strcmp(cfg.type, "host"))) {
- telemetry_type = WDC_TELEMETRY_TYPE_HOST;
- telemetry_data_area = cfg.data_area;
- } else if ((!strcmp(cfg.type, "CONTROLLER")) ||
- (!strcmp(cfg.type, "controller"))) {
- telemetry_type = WDC_TELEMETRY_TYPE_CONTROLLER;
- telemetry_data_area = cfg.data_area;
- } else {
- fprintf(stderr, "ERROR : WDC: Invalid type - Must be NONE, HOST or CONTROLLER\n");
- return -1;
- }
+ if (telemetry_data_area == 0)
+ telemetry_data_area = 3; /* Set the default DA to 3 if not specified */
- return wdc_do_cap_diag(fd, f, xfer_size, telemetry_type, telemetry_data_area);
+ return wdc_do_cap_diag(r, fd, f, xfer_size,
+ telemetry_type, telemetry_data_area);
}
if ((capabilities & WDC_DRIVE_CAP_DUI) == WDC_DRIVE_CAP_DUI) {
- if (cfg.data_area == 0) {
- cfg.data_area = 1;
+ if ((telemetry_type == WDC_TELEMETRY_TYPE_HOST) ||
+ (telemetry_type == WDC_TELEMETRY_TYPE_CONTROLLER)) {
+ if (telemetry_data_area == 0)
+ telemetry_data_area = 3; /* Set the default DA to 3 if not specified */
+ /* Get the desired telemetry log page */
+ return wdc_do_cap_telemetry_log(fd, f, xfer_size, telemetry_type, telemetry_data_area);
}
+ else {
+ if (cfg.data_area == 0) {
+ cfg.data_area = 1;
+ }
- /* FW requirement - xfer size must be 256k for data area 4 */
- if (cfg.data_area >= 4)
- xfer_size = 0x40000;
- return wdc_do_cap_dui(fd, f, xfer_size, cfg.data_area, cfg.verbose, cfg.file_size, cfg.offset);
+ /* FW requirement - xfer size must be 256k for data area 4 */
+ if (cfg.data_area >= 4)
+ xfer_size = 0x40000;
+ return wdc_do_cap_dui(fd, f, xfer_size, cfg.data_area,
+ cfg.verbose, cfg.file_size, cfg.offset);
+ }
+ }
+ if ((capabilities & WDC_DRIVE_CAP_DUI_DATA) == WDC_DRIVE_CAP_DUI_DATA){
+ if ((telemetry_type == WDC_TELEMETRY_TYPE_HOST) ||
+ (telemetry_type == WDC_TELEMETRY_TYPE_CONTROLLER)) {
+ if (telemetry_data_area == 0)
+ telemetry_data_area = 3; /* Set the default DA to 3 if not specified */
+ /* Get the desired telemetry log page */
+ return wdc_do_cap_telemetry_log(fd, f, xfer_size, telemetry_type, telemetry_data_area);
+ }
+ else {
+ return wdc_do_cap_dui(fd, f, xfer_size, WDC_NVME_DUI_MAX_DATA_AREA, cfg.verbose, 0, 0);
+ }
}
- if ((capabilities & WDC_DRIVE_CAP_DUI_DATA) == WDC_DRIVE_CAP_DUI_DATA)
- return wdc_do_cap_dui(fd, f, xfer_size, WDC_NVME_DUI_MAX_DATA_AREA, cfg.verbose, 0, 0);
if ((capabilities & WDC_SN730B_CAP_VUC_LOG) == WDC_SN730B_CAP_VUC_LOG)
return wdc_do_sn730_get_and_tar(fd, f);
@@ -3151,7 +3299,7 @@ static int wdc_do_drive_log(int fd, char *file)
int ret;
__u8 *drive_log_data;
__u32 drive_log_length;
- struct nvme_admin_cmd admin_cmd;
+ struct nvme_passthru_cmd admin_cmd;
ret = wdc_dump_length(fd, WDC_NVME_DRIVE_LOG_SIZE_OPCODE,
WDC_NVME_DRIVE_LOG_SIZE_NDT,
@@ -3169,7 +3317,7 @@ static int wdc_do_drive_log(int fd, char *file)
}
memset(drive_log_data, 0, sizeof (__u8) * drive_log_length);
- memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd));
+ memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd));
admin_cmd.opcode = WDC_NVME_DRIVE_LOG_OPCODE;
admin_cmd.addr = (__u64)(uintptr_t)drive_log_data;
admin_cmd.data_len = drive_log_length;
@@ -3177,9 +3325,8 @@ static int wdc_do_drive_log(int fd, char *file)
admin_cmd.cdw12 = ((WDC_NVME_DRIVE_LOG_SUBCMD <<
WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_DRIVE_LOG_SIZE_CMD);
- ret = nvme_submit_admin_passthru(fd, &admin_cmd);
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret),
- ret);
+ ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL);
+ nvme_show_status(ret);
if (ret == 0) {
ret = wdc_create_log_file(file, drive_log_data, drive_log_length);
}
@@ -3195,6 +3342,7 @@ static int wdc_drive_log(int argc, char **argv, struct command *command,
char f[PATH_MAX] = {0};
int fd;
int ret;
+ nvme_root_t r;
__u64 capabilities = 0;
struct config {
char *file;
@@ -3213,9 +3361,13 @@ static int wdc_drive_log(int argc, char **argv, struct command *command,
if (fd < 0)
return fd;
- if (!wdc_check_device(fd))
+ r = nvme_scan(NULL);
+
+ if (!wdc_check_device(r, fd)) {
+ nvme_free_tree(r);
return -1;
- capabilities = wdc_get_drive_capabilities(fd);
+ }
+ capabilities = wdc_get_drive_capabilities(r, fd);
if ((capabilities & WDC_DRIVE_CAP_DRIVE_LOG) == 0) {
fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
@@ -3226,10 +3378,12 @@ static int wdc_drive_log(int argc, char **argv, struct command *command,
}
if (wdc_get_serial_name(fd, f, PATH_MAX, "drive_log") == -1) {
fprintf(stderr, "ERROR : WDC : failed to generate file name\n");
+ nvme_free_tree(r);
return -1;
}
ret = wdc_do_drive_log(fd, f);
}
+ nvme_free_tree(r);
return ret;
}
@@ -3239,6 +3393,7 @@ static int wdc_get_crash_dump(int argc, char **argv, struct command *command,
const char *desc = "Get Crash Dump.";
const char *file = "Output file pathname.";
int fd, ret;
+ nvme_root_t r;
__u64 capabilities = 0;
struct config {
@@ -3258,10 +3413,15 @@ static int wdc_get_crash_dump(int argc, char **argv, struct command *command,
if (fd < 0)
return fd;
- if (!wdc_check_device(fd))
+ r = nvme_scan(NULL);
+
+ if (!wdc_check_device(r, fd)) {
+ nvme_free_tree(r);
return -1;
- capabilities = wdc_get_drive_capabilities(fd);
+ }
+
+ capabilities = wdc_get_drive_capabilities(r, fd);
if ((capabilities & WDC_DRIVE_CAP_CRASH_DUMP) == 0) {
fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
@@ -3272,6 +3432,7 @@ static int wdc_get_crash_dump(int argc, char **argv, struct command *command,
fprintf(stderr, "ERROR : WDC : failed to read crash dump\n");
}
}
+ nvme_free_tree(r);
return ret;
}
@@ -3282,6 +3443,7 @@ static int wdc_get_pfail_dump(int argc, char **argv, struct command *command,
char *file = "Output file pathname.";
int fd;
int ret;
+ nvme_root_t r;
__u64 capabilities = 0;
struct config {
char *file;
@@ -3300,10 +3462,14 @@ static int wdc_get_pfail_dump(int argc, char **argv, struct command *command,
if (fd < 0)
return fd;
- if (!wdc_check_device(fd))
+ r = nvme_scan(NULL);
+
+ if (!wdc_check_device(r, fd)) {
+ nvme_free_tree(r);
return -1;
+ }
- capabilities = wdc_get_drive_capabilities(fd);
+ capabilities = wdc_get_drive_capabilities(r, fd);
if ((capabilities & WDC_DRIVE_CAP_PFAIL_DUMP) == 0) {
fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
ret = -1;
@@ -3313,7 +3479,7 @@ static int wdc_get_pfail_dump(int argc, char **argv, struct command *command,
fprintf(stderr, "ERROR : WDC : failed to read pfail crash dump\n");
}
}
-
+ nvme_free_tree(r);
return ret;
}
@@ -3371,6 +3537,7 @@ static int wdc_purge(int argc, char **argv,
const char *desc = "Send a Purge command.";
char *err_str;
int fd, ret;
+ nvme_root_t r;
struct nvme_passthru_cmd admin_cmd;
__u64 capabilities = 0;
@@ -3382,10 +3549,14 @@ static int wdc_purge(int argc, char **argv,
if (fd < 0)
return fd;
- if (!wdc_check_device(fd))
+ r = nvme_scan(NULL);
+
+ if (!wdc_check_device(r, fd)) {
+ nvme_free_tree(r);
return -1;
+ }
- capabilities = wdc_get_drive_capabilities(fd);
+ capabilities = wdc_get_drive_capabilities(r, fd);
if((capabilities & WDC_DRIVE_CAP_PURGE) == 0) {
ret = -1;
fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
@@ -3394,7 +3565,7 @@ static int wdc_purge(int argc, char **argv,
memset(&admin_cmd, 0, sizeof (admin_cmd));
admin_cmd.opcode = WDC_NVME_PURGE_CMD_OPCODE;
- ret = nvme_submit_admin_passthru(fd, &admin_cmd);
+ ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL);
if (ret > 0) {
switch (ret) {
case WDC_NVME_PURGE_CMD_SEQ_ERR:
@@ -3410,8 +3581,9 @@ static int wdc_purge(int argc, char **argv,
}
fprintf(stderr, "%s", err_str);
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
}
+ nvme_free_tree(r);
return ret;
}
@@ -3420,11 +3592,12 @@ static int wdc_purge_monitor(int argc, char **argv,
{
const char *desc = "Send a Purge Monitor command.";
int fd, ret;
+ nvme_root_t r;
__u8 output[WDC_NVME_PURGE_MONITOR_DATA_LEN];
double progress_percent;
struct nvme_passthru_cmd admin_cmd;
struct wdc_nvme_purge_monitor_data *mon;
- __u64 capabilities = 0;
+ __u64 capabilities;
OPT_ARGS(opts) = {
OPT_END()
@@ -3434,23 +3607,26 @@ static int wdc_purge_monitor(int argc, char **argv,
if (fd < 0)
return fd;
- if (!wdc_check_device(fd))
+ r = nvme_scan(NULL);
+ if (!wdc_check_device(r, fd)) {
+ nvme_free_tree(r);
return -1;
+ }
- capabilities = wdc_get_drive_capabilities(fd);
+ capabilities = wdc_get_drive_capabilities(r, fd);
if((capabilities & WDC_DRIVE_CAP_PURGE) == 0) {
ret = -1;
fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
} else {
memset(output, 0, sizeof (output));
- memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd));
+ memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd));
admin_cmd.opcode = WDC_NVME_PURGE_MONITOR_OPCODE;
admin_cmd.addr = (__u64)(uintptr_t)output;
admin_cmd.data_len = WDC_NVME_PURGE_MONITOR_DATA_LEN;
admin_cmd.cdw10 = WDC_NVME_PURGE_MONITOR_CMD_CDW10;
admin_cmd.timeout_ms = WDC_NVME_PURGE_MONITOR_TIMEOUT;
- ret = nvme_submit_admin_passthru(fd, &admin_cmd);
+ ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL);
if (ret == 0) {
mon = (struct wdc_nvme_purge_monitor_data *) output;
printf("Purge state = 0x%0x\n", admin_cmd.result);
@@ -3463,8 +3639,9 @@ static int wdc_purge_monitor(int argc, char **argv,
}
}
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
}
+ nvme_free_tree(r);
return ret;
}
@@ -3762,6 +3939,168 @@ static void wdc_print_latency_monitor_log_json(struct wdc_ssd_latency_monitor_lo
json_free_object(root);
}
+static void wdc_print_error_rec_log_normal(int fd, struct wdc_ocp_c1_error_recovery_log *log_data)
+{
+ int j;
+ printf("Error Recovery/C1 Log Page Data \n");
+
+ printf(" Panic Reset Wait Time : 0x%x \n", le16_to_cpu(log_data->panic_reset_wait_time));
+ printf(" Panic Reset Action : 0x%x \n", log_data->panic_reset_action);
+ printf(" Device Recovery Action 1 : 0x%x \n", log_data->dev_recovery_action1);
+ printf(" Panic ID : 0x%lx \n", le64_to_cpu(log_data->panic_id));
+ printf(" Device Capabilities : 0x%x \n", le32_to_cpu(log_data->dev_capabilities));
+ printf(" Vendor Specific Recovery Opcode : 0x%x \n", log_data->vs_recovery_opc);
+ printf(" Vendor Specific Command CDW12 : 0x%x \n", le32_to_cpu(log_data->vs_cmd_cdw12));
+ printf(" Vendor Specific Command CDW13 : 0x%x \n", le32_to_cpu(log_data->vs_cmd_cdw13));
+ printf(" Vendor Specific Command Timeout : 0x%x \n", log_data->vs_cmd_to);
+ printf(" Device Recovery Action 2 : 0x%x \n", log_data->dev_recovery_action2);
+ printf(" Device Recovery Action 2 Timeout : 0x%x \n", log_data->dev_recovery_action2_to);
+ printf(" Log Page Version : 0x%x \n", le16_to_cpu(log_data->log_page_version));
+ printf(" Log page GUID : 0x");
+ for (j = 0; j < WDC_OCP_C1_GUID_LENGTH; j++) {
+ printf("%x", log_data->log_page_guid[j]);
+ }
+ printf("\n");
+}
+
+static void wdc_print_error_rec_log_json(struct wdc_ocp_c1_error_recovery_log *log_data)
+{
+ struct json_object *root;
+ root = json_create_object();
+
+ json_object_add_value_int(root, "Panic Reset Wait Time", le16_to_cpu(log_data->panic_reset_wait_time));
+ json_object_add_value_int(root, "Panic Reset Action", log_data->panic_reset_wait_time);
+ json_object_add_value_int(root, "Device Recovery Action 1", log_data->dev_recovery_action1);
+ json_object_add_value_int(root, "Panic ID", le64_to_cpu(log_data->panic_id));
+ json_object_add_value_int(root, "Device Capabilities", le32_to_cpu(log_data->dev_capabilities));
+ json_object_add_value_int(root, "Vendor Specific Recovery Opcode", log_data->vs_recovery_opc);
+ json_object_add_value_int(root, "Vendor Specific Command CDW12", le32_to_cpu(log_data->vs_cmd_cdw12));
+ json_object_add_value_int(root, "Vendor Specific Command CDW13", le32_to_cpu(log_data->vs_cmd_cdw13));
+ json_object_add_value_int(root, "Vendor Specific Command Timeout", log_data->vs_cmd_to);
+ json_object_add_value_int(root, "Device Recovery Action 2", log_data->dev_recovery_action2);
+ json_object_add_value_int(root, "Device Recovery Action 2 Timeout", log_data->dev_recovery_action2_to);
+ json_object_add_value_int(root, "Log Page Version", le16_to_cpu(log_data->log_page_version));
+
+ char guid[40];
+ memset((void*)guid, 0, 40);
+ sprintf((char*)guid, "0x%"PRIx64"%"PRIx64"",(uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]),
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0]));
+ json_object_add_value_string(root, "Log page GUID", guid);
+
+ json_print_object(root, NULL);
+ printf("\n");
+
+ json_free_object(root);
+}
+
+static void wdc_print_dev_cap_log_normal(int fd, struct wdc_ocp_C4_dev_cap_log *log_data)
+{
+ int j;
+ printf("Device Capabilities/C4 Log Page Data \n");
+
+ printf(" Number PCIE Ports : 0x%x \n", le16_to_cpu(log_data->num_pcie_ports));
+ printf(" Number OOB Management Interfaces : 0x%x \n", le16_to_cpu(log_data->oob_mgmt_support));
+ printf(" Write Zeros Command Support : 0x%x \n", le16_to_cpu(log_data->wrt_zeros_support));
+ printf(" Sanitize Command Support : 0x%x \n", le16_to_cpu(log_data->sanitize_support));
+ printf(" DSM Command Support : 0x%x \n", le16_to_cpu(log_data->dsm_support));
+ printf(" Write Uncorr Command Support : 0x%x \n", le16_to_cpu(log_data->wrt_uncor_support));
+ printf(" Fused Command Support : 0x%x \n", le16_to_cpu(log_data->fused_support));
+ printf(" Minimum DSSD Power State : 0x%x \n", le16_to_cpu(log_data->min_dssd_ps));
+
+ for (j = 0; j < WDC_OCP_C4_NUM_PS_DESCR; j++) {
+ printf(" DSSD Power State %d Desriptor : 0x%x \n", j, log_data->dssd_ps_descr[j]);
+ }
+
+ printf(" Log Page Version : 0x%x \n", le16_to_cpu(log_data->log_page_version));
+ printf(" Log page GUID : 0x");
+ for (j = 0; j < WDC_OCP_C4_GUID_LENGTH; j++) {
+ printf("%x", log_data->log_page_guid[j]);
+ }
+ printf("\n");
+}
+
+static void wdc_print_dev_cap_log_json(struct wdc_ocp_C4_dev_cap_log *log_data)
+{
+ int j;
+ struct json_object *root;
+ root = json_create_object();
+
+ json_object_add_value_int(root, "Number PCIE Ports", le16_to_cpu(log_data->num_pcie_ports));
+ json_object_add_value_int(root, "Number OOB Management Interfaces", le16_to_cpu(log_data->num_pcie_ports));
+ json_object_add_value_int(root, "Write Zeros Command Support", le16_to_cpu(log_data->num_pcie_ports));
+ json_object_add_value_int(root, "Sanitize Command Support", le16_to_cpu(log_data->num_pcie_ports));
+ json_object_add_value_int(root, "DSM Command Support", le16_to_cpu(log_data->num_pcie_ports));
+ json_object_add_value_int(root, "Write Uncorr Command Support", le16_to_cpu(log_data->num_pcie_ports));
+ json_object_add_value_int(root, "Fused Command Support", le16_to_cpu(log_data->num_pcie_ports));
+ json_object_add_value_int(root, "Minimum DSSD Power State", le16_to_cpu(log_data->num_pcie_ports));
+
+ char dssd_descr_str[40];
+ memset((void *)dssd_descr_str, 0, 40);
+ for (j = 0; j < WDC_OCP_C4_NUM_PS_DESCR; j++) {
+ sprintf((char *)dssd_descr_str, "DSSD Power State %d Descriptor", j);
+ json_object_add_value_int(root, dssd_descr_str, log_data->dssd_ps_descr[j]);
+ }
+
+ json_object_add_value_int(root, "Log Page Version", le16_to_cpu(log_data->log_page_version));
+ char guid[40];
+ memset((void*)guid, 0, 40);
+ sprintf((char*)guid, "0x%"PRIx64"%"PRIx64"",(uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]),
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0]));
+ json_object_add_value_string(root, "Log page GUID", guid);
+
+ json_print_object(root, NULL);
+ printf("\n");
+
+ json_free_object(root);
+}
+
+static void wdc_print_unsupported_reqs_log_normal(int fd, struct wdc_ocp_C5_unsupported_reqs *log_data)
+{
+ int j;
+ printf("Unsupported Requirements/C5 Log Page Data \n");
+
+ printf(" Number Unsupported Req IDs : 0x%x \n", le16_to_cpu(log_data->unsupported_count));
+
+ for (j = 0; j < le16_to_cpu(log_data->unsupported_count); j++) {
+ printf(" Unsupported Requirement List %d : %s \n", j, log_data->unsupported_req_list[j]);
+ }
+
+ printf(" Log Page Version : 0x%x \n", le16_to_cpu(log_data->log_page_version));
+ printf(" Log page GUID : 0x");
+ for (j = 0; j < WDC_OCP_C5_GUID_LENGTH; j++) {
+ printf("%x", log_data->log_page_guid[j]);
+ }
+ printf("\n");
+}
+
+static void wdc_print_unsupported_reqs_log_json(struct wdc_ocp_C5_unsupported_reqs *log_data)
+{
+ int j;
+ struct json_object *root;
+ root = json_create_object();
+
+ json_object_add_value_int(root, "Number Unsupported Req IDs", le16_to_cpu(log_data->unsupported_count));
+
+ char unsup_req_list_str[40];
+ memset((void *)unsup_req_list_str, 0, 40);
+ 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]);
+ }
+
+ json_object_add_value_int(root, "Log Page Version", le16_to_cpu(log_data->log_page_version));
+ char guid[40];
+ memset((void*)guid, 0, 40);
+ sprintf((char*)guid, "0x%"PRIx64"%"PRIx64"",(uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]),
+ (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0]));
+ json_object_add_value_string(root, "Log page GUID", guid);
+
+ json_print_object(root, NULL);
+ printf("\n");
+
+ json_free_object(root);
+}
+
static void wdc_print_fb_ca_log_normal(struct wdc_ssd_ca_perf_stats *perf)
{
uint64_t converted = 0;
@@ -3895,7 +4234,7 @@ static void wdc_print_bd_ca_log_normal(void *data)
__u8 *byte_raw;
if (bd_data->field_id == 0x00) {
- raw = (__u64*)bd_data->raw_value;
+ raw = (__u64*)&bd_data->raw_value[1];
printf("Additional Smart Log for NVME device:%s namespace-id:%x\n",
devicename, WDC_DE_GLOBAL_NSID);
printf("key normalized raw\n");
@@ -3906,7 +4245,7 @@ static void wdc_print_bd_ca_log_normal(void *data)
}
bd_data++;
if (bd_data->field_id == 0x01) {
- raw = (__u64*)bd_data->raw_value;
+ raw = (__u64*)&bd_data->raw_value[1];
printf("erase_fail_count : %3"PRIu8"%% %"PRIu64"\n",
bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF));
} else {
@@ -3914,9 +4253,9 @@ static void wdc_print_bd_ca_log_normal(void *data)
}
bd_data++;
if (bd_data->field_id == 0x02) {
- word_raw1 = (__u16*)bd_data->raw_value;
- word_raw2 = (__u16*)&bd_data->raw_value[2];
- word_raw3 = (__u16*)&bd_data->raw_value[4];
+ word_raw1 = (__u16*)&bd_data->raw_value[1];
+ word_raw2 = (__u16*)&bd_data->raw_value[3];
+ word_raw3 = (__u16*)&bd_data->raw_value[5];
printf("wear_leveling : %3"PRIu8"%% min: %"PRIu16", max: %"PRIu16", avg: %"PRIu16"\n",
bd_data->normalized_value,
le16_to_cpu(*word_raw1),
@@ -3927,7 +4266,7 @@ static void wdc_print_bd_ca_log_normal(void *data)
}
bd_data++;
if (bd_data->field_id == 0x03) {
- raw = (__u64*)bd_data->raw_value;
+ raw = (__u64*)&bd_data->raw_value[1];
printf("end_to_end_error_detection_count: %3"PRIu8"%% %"PRIu64"\n",
bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF));
} else {
@@ -3935,7 +4274,7 @@ static void wdc_print_bd_ca_log_normal(void *data)
}
bd_data++;
if (bd_data->field_id == 0x04) {
- raw = (__u64*)bd_data->raw_value;
+ raw = (__u64*)&bd_data->raw_value[1];
printf("crc_error_count : %3"PRIu8"%% %"PRIu64"\n",
bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF));
} else {
@@ -3943,7 +4282,7 @@ static void wdc_print_bd_ca_log_normal(void *data)
}
bd_data++;
if (bd_data->field_id == 0x05) {
- raw = (__u64*)bd_data->raw_value;
+ raw = (__u64*)&bd_data->raw_value[1];
printf("timed_workload_media_wear : %3"PRIu8"%% %-.3f%%\n",
bd_data->normalized_value,
safe_div_fp((*raw & 0x00FFFFFFFFFFFFFF), 1024.0));
@@ -3952,7 +4291,7 @@ static void wdc_print_bd_ca_log_normal(void *data)
}
bd_data++;
if (bd_data->field_id == 0x06) {
- raw = (__u64*)bd_data->raw_value;
+ raw = (__u64*)&bd_data->raw_value[1];
printf("timed_workload_host_reads : %3"PRIu8"%% %"PRIu64"%%\n",
bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF));
} else {
@@ -3960,7 +4299,7 @@ static void wdc_print_bd_ca_log_normal(void *data)
}
bd_data++;
if (bd_data->field_id == 0x07) {
- raw = (__u64*)bd_data->raw_value;
+ raw = (__u64*)&bd_data->raw_value[1];
printf("timed_workload_timer : %3"PRIu8"%% %"PRIu64"\n",
bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF));
} else {
@@ -3968,8 +4307,8 @@ static void wdc_print_bd_ca_log_normal(void *data)
}
bd_data++;
if (bd_data->field_id == 0x08) {
- byte_raw = (__u8*)bd_data->raw_value;
- dword_raw = (__u32*)&bd_data->raw_value[1];
+ byte_raw = (__u8*)&bd_data->raw_value[1];
+ dword_raw = (__u32*)&bd_data->raw_value[2];
printf("thermal_throttle_status : %3"PRIu8"%% %"PRIu16"%%, cnt: %"PRIu16"\n",
bd_data->normalized_value, *byte_raw, le32_to_cpu(*dword_raw));
} else {
@@ -3977,7 +4316,7 @@ static void wdc_print_bd_ca_log_normal(void *data)
}
bd_data++;
if (bd_data->field_id == 0x09) {
- raw = (__u64*)bd_data->raw_value;
+ raw = (__u64*)&bd_data->raw_value[1];
printf("retry_buffer_overflow_count : %3"PRIu8"%% %"PRIu64"\n",
bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF));
} else {
@@ -3985,7 +4324,7 @@ static void wdc_print_bd_ca_log_normal(void *data)
}
bd_data++;
if (bd_data->field_id == 0x0A) {
- raw = (__u64*)bd_data->raw_value;
+ raw = (__u64*)&bd_data->raw_value[1];
printf("pll_lock_loss_count : %3"PRIu8"%% %"PRIu64"\n",
bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF));
} else {
@@ -3993,19 +4332,17 @@ static void wdc_print_bd_ca_log_normal(void *data)
}
bd_data++;
if (bd_data->field_id == 0x0B) {
- raw = (__u64*)bd_data->raw_value;
+ raw = (__u64*)&bd_data->raw_value[1];
printf("nand_bytes_written : %3"PRIu8"%% sectors: %.f\n",
bd_data->normalized_value, safe_div_fp((*raw & 0x00FFFFFFFFFFFFFF), 0xFFFF));
- raw = (__u64*)bd_data->raw_value;
} else {
goto invalid_id;
}
bd_data++;
if (bd_data->field_id == 0x0C) {
- raw = (__u64*)bd_data->raw_value;
+ raw = (__u64*)&bd_data->raw_value[1];
printf("host_bytes_written : %3"PRIu8"%% sectors: %.f\n",
bd_data->normalized_value, safe_div_fp((*raw & 0x00FFFFFFFFFFFFFF), 0xFFFF));
- raw = (__u64*)bd_data->raw_value;
} else {
goto invalid_id;
}
@@ -4031,71 +4368,81 @@ static void wdc_print_bd_ca_log_json(void *data)
root = json_create_object();
if (bd_data->field_id == 0x00) {
- raw = (__u64*)bd_data->raw_value;
- json_object_add_value_int(root, "program_fail_count",
- le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF));
- json_object_add_value_int(root, "normalized",
+ raw = (__u64*)&bd_data->raw_value[1];
+ json_object_add_value_int(root, "program_fail_count normalized",
bd_data->normalized_value);
+ json_object_add_value_int(root, "program_fail_count raw",
+ le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF));
} else {
goto invalid_id;
}
bd_data++;
if (bd_data->field_id == 0x01) {
- raw = (__u64*)bd_data->raw_value;
- json_object_add_value_int(root, "erase_fail_count",
- le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF));
- json_object_add_value_int(root, "normalized",
+ raw = (__u64*)&bd_data->raw_value[1];
+ json_object_add_value_int(root, "erase_fail_count normalized",
bd_data->normalized_value);
+ json_object_add_value_int(root, "erase_fail_count raw",
+ le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF));
} else {
goto invalid_id;
}
bd_data++;
if (bd_data->field_id == 0x02) {
- word_raw = (__u16*)bd_data->raw_value;
- json_object_add_value_int(root, "min", le16_to_cpu(*word_raw));
- word_raw = (__u16*)&bd_data->raw_value[2];
- json_object_add_value_int(root, "max", le16_to_cpu(*word_raw));
- word_raw = (__u16*)&bd_data->raw_value[4];
- json_object_add_value_int(root, "avg", le16_to_cpu(*word_raw));
- json_object_add_value_int(root, "wear_leveling-normalized", bd_data->normalized_value);
+ word_raw = (__u16*)&bd_data->raw_value[1];
+ json_object_add_value_int(root, "wear_leveling normalized", bd_data->normalized_value);
+ json_object_add_value_int(root, "wear_leveling min", le16_to_cpu(*word_raw));
+ word_raw = (__u16*)&bd_data->raw_value[3];
+ json_object_add_value_int(root, "wear_leveling max", le16_to_cpu(*word_raw));
+ word_raw = (__u16*)&bd_data->raw_value[5];
+ json_object_add_value_int(root, "wear_leveling avg", le16_to_cpu(*word_raw));
} else {
goto invalid_id;
}
bd_data++;
if (bd_data->field_id == 0x03) {
- raw = (__u64*)bd_data->raw_value;
- json_object_add_value_int(root, "end_to_end_error_detection_count",
+ raw = (__u64*)&bd_data->raw_value[1];
+ json_object_add_value_int(root, "end_to_end_error_detection_count normalized",
+ bd_data->normalized_value);
+ json_object_add_value_int(root, "end_to_end_error_detection_count raw",
le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF));
} else {
goto invalid_id;
}
bd_data++;
if (bd_data->field_id == 0x04) {
- raw = (__u64*)bd_data->raw_value;
- json_object_add_value_int(root, "crc_error_count",
+ raw = (__u64*)&bd_data->raw_value[1];
+ json_object_add_value_int(root, "crc_error_count normalized",
+ bd_data->normalized_value);
+ json_object_add_value_int(root, "crc_error_count raw",
le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF));
} else {
goto invalid_id;
}
bd_data++;
if (bd_data->field_id == 0x05) {
- raw = (__u64*)bd_data->raw_value;
- json_object_add_value_float(root, "timed_workload_media_wear",
+ raw = (__u64*)&bd_data->raw_value[1];
+ json_object_add_value_int(root, "timed_workload_media_wear normalized",
+ bd_data->normalized_value);
+ json_object_add_value_float(root, "timed_workload_media_wear raw",
safe_div_fp((*raw & 0x00FFFFFFFFFFFFFF), 1024.0));
} else {
goto invalid_id;
}
bd_data++;
if (bd_data->field_id == 0x06) {
- raw = (__u64*)bd_data->raw_value;
- json_object_add_value_int(root, "timed_workload_host_reads",
+ raw = (__u64*)&bd_data->raw_value[1];
+ json_object_add_value_int(root, "timed_workload_host_reads normalized",
+ bd_data->normalized_value);
+ json_object_add_value_int(root, "timed_workload_host_reads raw",
le64_to_cpu(*raw & 0x00000000000000FF));
} else {
goto invalid_id;
}
bd_data++;
if (bd_data->field_id == 0x07) {
- raw = (__u64*)bd_data->raw_value;
+ raw = (__u64*)&bd_data->raw_value[1];
+ json_object_add_value_int(root, "timed_workload_timer normalized",
+ bd_data->normalized_value);
json_object_add_value_int(root, "timed_workload_timer",
le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF));
} else {
@@ -4103,54 +4450,67 @@ static void wdc_print_bd_ca_log_json(void *data)
}
bd_data++;
if (bd_data->field_id == 0x08) {
- byte_raw = (__u8*)bd_data->raw_value;
+ byte_raw = (__u8*)&bd_data->raw_value[1];
+ json_object_add_value_int(root, "thermal_throttle_status normalized",
+ bd_data->normalized_value);
json_object_add_value_int(root, "thermal_throttle_status", *byte_raw);
- dword_raw = (__u32*)&bd_data->raw_value[1];
- json_object_add_value_int(root, "cnt", le32_to_cpu(*dword_raw));
+ dword_raw = (__u32*)&bd_data->raw_value[2];
+ json_object_add_value_int(root, "thermal_throttle_cnt", le32_to_cpu(*dword_raw));
} else {
goto invalid_id;
}
bd_data++;
if (bd_data->field_id == 0x09) {
- raw = (__u64*)bd_data->raw_value;
- json_object_add_value_int(root, "retry_buffer_overflow_count",
+ raw = (__u64*)&bd_data->raw_value[1];
+ json_object_add_value_int(root, "retry_buffer_overflow_count normalized",
+ bd_data->normalized_value);
+ json_object_add_value_int(root, "retry_buffer_overflow_count raw",
le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF));
} else {
goto invalid_id;
}
bd_data++;
if (bd_data->field_id == 0x0A) {
- raw = (__u64*)bd_data->raw_value;
- json_object_add_value_int(root, "pll_lock_loss_count",
+ raw = (__u64*)&bd_data->raw_value[1];
+ json_object_add_value_int(root, "pll_lock_loss_count normalized",
+ bd_data->normalized_value);
+ json_object_add_value_int(root, "pll_lock_loss_count raw",
le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF));
} else {
goto invalid_id;
}
bd_data++;
if (bd_data->field_id == 0x0B) {
- raw = (__u64*)bd_data->raw_value;
- json_object_add_value_float(root, "nand_bytes_written",
+ raw = (__u64*)&bd_data->raw_value[1];
+ json_object_add_value_int(root, "nand_bytes_written normalized",
+ bd_data->normalized_value);
+ json_object_add_value_float(root, "nand_bytes_written raw",
safe_div_fp((*raw & 0x00FFFFFFFFFFFFFF), 0xFFFF));
} else {
goto invalid_id;
}
bd_data++;
if (bd_data->field_id == 0x0C) {
- raw = (__u64*)bd_data->raw_value;
- json_object_add_value_float(root, "host_bytes_written",
+ raw = (__u64*)&bd_data->raw_value[1];
+ json_object_add_value_int(root, "host_bytes_written normalized",
+ bd_data->normalized_value);
+ json_object_add_value_float(root, "host_bytes_written raw",
safe_div_fp((*raw & 0x00FFFFFFFFFFFFFF), 0xFFFF));
- raw = (__u64*)bd_data->raw_value;
} else {
goto invalid_id;
}
goto done;
- invalid_id:
- printf(" Invalid Field ID = %d\n", bd_data->field_id);
+ invalid_id:
+ printf(" Invalid Field ID = %d\n", bd_data->field_id);
- done:
- return;
+ done:
+ json_print_object(root, NULL);
+ printf("\n");
+ json_free_object(root);
+
+ return;
}
@@ -4617,77 +4977,71 @@ static void wdc_print_smart_cloud_attr_C0_normal(void *data)
printf(" SMART Cloud Attributes :- \n");
- printf(" Physical media units written - %"PRIu64" %"PRIu64"\n",
+ printf(" Physical media units written : %"PRIu64" %"PRIu64"\n",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW+8] & 0xFFFFFFFFFFFFFFFF),
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW] & 0xFFFFFFFFFFFFFFFF));
- printf(" Physical media units read - %"PRIu64" %"PRIu64"\n",
+ printf(" Physical media units read : %"PRIu64" %"PRIu64"\n",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR+8] & 0xFFFFFFFFFFFFFFFF),
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR] & 0xFFFFFFFFFFFFFFFF));
- printf(" Bad user nand blocks - Raw %"PRIu64"\n",
+ printf(" Bad user nand blocks Raw : %"PRIu64"\n",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BUNBR] & 0x0000FFFFFFFFFFFF));
- printf(" Bad user nand blocks - Normalized %d\n",
+ printf(" Bad user nand blocks Normalized : %d\n",
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BUNBN]));
- printf(" Bad system nand blocks - Raw %"PRIu64"\n",
+ printf(" Bad system nand blocks Raw : %"PRIu64"\n",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BSNBR] & 0x0000FFFFFFFFFFFF));
- printf(" Bad system nand blocks - Normalized %d\n",
+ printf(" Bad system nand blocks Normalized : %d\n",
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BSNBN]));
- printf(" XOR recovery count %"PRIu64"\n",
+ printf(" XOR recovery count : %"PRIu64"\n",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_XRC]));
- printf(" Uncorrectable read error count %"PRIu64"\n",
+ printf(" Uncorrectable read error count : %"PRIu64"\n",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UREC]));
- printf(" Soft ecc error count %"PRIu64"\n",
+ printf(" Soft ecc error count : %"PRIu64"\n",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SEEC]));
- printf(" End to end corrected errors %"PRIu32"\n",
+ printf(" End to end corrected errors : %"PRIu32"\n",
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EECE]));
- printf(" End to end detected errors %"PRIu32"\n",
+ printf(" End to end detected errors : %"PRIu32"\n",
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EEDC]));
- printf(" System data percent used %d\n",
- (__u8)log_data[SCAO_SDPU]);
- printf(" Refresh counts %"PRIu64"\n",
+ printf(" System data percent used : %d\n", (__u8)log_data[SCAO_SDPU]);
+ printf(" Refresh counts : %"PRIu64"\n",
(uint64_t)(le64_to_cpu(*(uint64_t *)&log_data[SCAO_RFSC])& 0x00FFFFFFFFFFFFFF));
- printf(" Max User data erase counts %"PRIu32"\n",
+ printf(" Max User data erase counts : %"PRIu32"\n",
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MXUDEC]));
- printf(" Min User data erase counts %"PRIu32"\n",
+ printf(" Min User data erase counts : %"PRIu32"\n",
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MNUDEC]));
- printf(" Number of Thermal throttling events %d\n",
- (__u8)log_data[SCAO_NTTE]);
- printf(" Current throttling status 0x%x\n",
- (__u8)log_data[SCAO_CTS]);
- printf(" PCIe correctable error count %"PRIu64"\n",
+ printf(" Number of Thermal throttling events : %d\n", (__u8)log_data[SCAO_NTTE]);
+ printf(" Current throttling status : 0x%x\n", (__u8)log_data[SCAO_CTS]);
+ printf(" PCIe correctable error count : %"PRIu64"\n",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PCEC]));
- printf(" Incomplete shutdowns %"PRIu32"\n",
+ printf(" Incomplete shutdowns : %"PRIu32"\n",
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_ICS]));
- printf(" Percent free blocks %d\n",
- (__u8)log_data[SCAO_PFB]);
- printf(" Capacitor health %"PRIu16"\n",
+ printf(" Percent free blocks : %d\n", (__u8)log_data[SCAO_PFB]);
+ printf(" Capacitor health : %"PRIu16"\n",
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_CPH]));
- printf(" Unaligned I/O %"PRIu64"\n",
+ printf(" Unaligned I/O : %"PRIu64"\n",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UIO]));
- printf(" Security Version Number %"PRIu64"\n",
+ printf(" Security Version Number : %"PRIu64"\n",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SVN]));
- printf(" NUSE - Namespace utilization %"PRIu64"\n",
+ printf(" NUSE Namespace utilization : %"PRIu64"\n",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_NUSE]));
- printf(" PLP start count %.0Lf\n",
- int128_to_double(&log_data[SCAO_PSC]));
- printf(" Endurance estimate %.0Lf\n",
- int128_to_double(&log_data[SCAO_EEST]));
+ printf(" PLP start count : %.0Lf\n", int128_to_double(&log_data[SCAO_PSC]));
+ printf(" Endurance estimate : %.0Lf\n", int128_to_double(&log_data[SCAO_EEST]));
smart_log_ver = (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_LPV]);
- printf(" Log page version %"PRIu16"\n",smart_log_ver);
- printf(" Log page GUID 0x");
+ printf(" Log page version : %"PRIu16"\n",smart_log_ver);
+ printf(" Log page GUID : 0x");
printf("0x%"PRIx64"%"PRIx64"\n",(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG + 8]),
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG]));
if(smart_log_ver > 2) {
- printf(" Errata Version Field %d\n",
+ printf(" Errata Version Field : %d\n",
(__u8)log_data[SCAO_EVF]);
- printf(" Point Version Field %"PRIu16"\n",
+ printf(" Point Version Field : %"PRIu16"\n",
(uint16_t)log_data[SCAO_PVF]);
- printf(" Minor Version Field %"PRIu16"\n",
+ printf(" Minor Version Field : %"PRIu16"\n",
(uint16_t)log_data[SCAO_MIVF]);
- printf(" Major Version Field %d\n",
+ printf(" Major Version Field : %d\n",
(__u8)log_data[SCAO_MAVF]);
- printf(" NVMe Errata Version %d\n",
+ printf(" NVMe Errata Version : %d\n",
(__u8)log_data[SCAO_NEV]);
- printf(" PCIe Link Retraining Count %"PRIu64"\n",
+ printf(" PCIe Link Retraining Count : %"PRIu64"\n",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PLRC]));
}
printf("\n");
@@ -4700,27 +5054,27 @@ static void wdc_print_smart_cloud_attr_C0_json(void *data)
uint16_t smart_log_ver = 0;
root = json_create_object();
- json_object_add_value_int(root, "Physical media units written hi",
+ json_object_add_value_uint64(root, "Physical media units written hi",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW+8] & 0xFFFFFFFFFFFFFFFF));
- json_object_add_value_int(root, "Physical media units written lo",
+ json_object_add_value_uint64(root, "Physical media units written lo",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW] & 0xFFFFFFFFFFFFFFFF));
- json_object_add_value_int(root, "Physical media units read hi",
+ json_object_add_value_uint64(root, "Physical media units read hi",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR+8] & 0xFFFFFFFFFFFFFFFF));
- json_object_add_value_int(root, "Physical media units read lo",
+ json_object_add_value_uint64(root, "Physical media units read lo",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR] & 0xFFFFFFFFFFFFFFFF));
- json_object_add_value_uint(root, "Bad user nand blocks - Raw",
+ json_object_add_value_uint64(root, "Bad user nand blocks - Raw",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BUNBR] & 0x0000FFFFFFFFFFFF));
json_object_add_value_uint(root, "Bad user nand blocks - Normalized",
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BUNBN]));
- json_object_add_value_uint(root, "Bad system nand blocks - Raw",
+ json_object_add_value_uint64(root, "Bad system nand blocks - Raw",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BSNBR] & 0x0000FFFFFFFFFFFF));
json_object_add_value_uint(root, "Bad system nand blocks - Normalized",
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BSNBN]));
- json_object_add_value_uint(root, "XOR recovery count",
+ json_object_add_value_uint64(root, "XOR recovery count",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_XRC]));
- json_object_add_value_uint(root, "Uncorrectable read error count",
+ json_object_add_value_uint64(root, "Uncorrectable read error count",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UREC]));
- json_object_add_value_uint(root, "Soft ecc error count",
+ json_object_add_value_uint64(root, "Soft ecc error count",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SEEC]));
json_object_add_value_uint(root, "End to end corrected errors",
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EECE]));
@@ -4728,7 +5082,7 @@ static void wdc_print_smart_cloud_attr_C0_json(void *data)
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EEDC]));
json_object_add_value_uint(root, "System data percent used",
(__u8)log_data[SCAO_SDPU]);
- json_object_add_value_uint(root, "Refresh counts",
+ json_object_add_value_uint64(root, "Refresh counts",
(uint64_t)(le64_to_cpu(*(uint64_t *)&log_data[SCAO_RFSC])& 0x00FFFFFFFFFFFFFF));
json_object_add_value_uint(root, "Max User data erase counts",
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MXUDEC]));
@@ -4738,7 +5092,7 @@ static void wdc_print_smart_cloud_attr_C0_json(void *data)
(__u8)log_data[SCAO_NTTE]);
json_object_add_value_uint(root, "Current throttling status",
(__u8)log_data[SCAO_CTS]);
- json_object_add_value_uint(root, "PCIe correctable error count",
+ json_object_add_value_uint64(root, "PCIe correctable error count",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PCEC]));
json_object_add_value_uint(root, "Incomplete shutdowns",
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_ICS]));
@@ -4746,11 +5100,11 @@ static void wdc_print_smart_cloud_attr_C0_json(void *data)
(__u8)log_data[SCAO_PFB]);
json_object_add_value_uint(root, "Capacitor health",
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_CPH]));
- json_object_add_value_uint(root, "Unaligned I/O",
+ json_object_add_value_uint64(root, "Unaligned I/O",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UIO]));
- json_object_add_value_uint(root, "Security Version Number",
+ json_object_add_value_uint64(root, "Security Version Number",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SVN]));
- json_object_add_value_uint(root, "NUSE - Namespace utilization",
+ json_object_add_value_uint64(root, "NUSE - Namespace utilization",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_NUSE]));
json_object_add_value_uint(root, "PLP start count",
int128_to_double(&log_data[SCAO_PSC]));
@@ -4774,7 +5128,7 @@ static void wdc_print_smart_cloud_attr_C0_json(void *data)
(__u8)log_data[SCAO_MAVF]);
json_object_add_value_uint(root, "NVMe Errata Version",
(__u8)log_data[SCAO_NEV]);
- json_object_add_value_uint(root, "PCIe Link Retraining Count",
+ json_object_add_value_uint64(root, "PCIe Link Retraining Count",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PLRC]));
}
json_print_object(root, NULL);
@@ -4867,16 +5221,17 @@ static int wdc_print_c0_eol_log(void *data, int fmt)
return 0;
}
-static int wdc_get_c0_log_page(int fd, char *format, int uuid_index, __u32 namespace_id)
+static int wdc_get_c0_log_page(nvme_root_t r, int fd, char *format,
+ int uuid_index, __u32 namespace_id)
{
int ret = 0;
int fmt = -1;
int i = 0;
__u8 *data;
- __u32 *cust_id;
+ __u32 cust_id;
uint32_t device_id, read_vendor_id;
- if (!wdc_check_device(fd))
+ if (!wdc_check_device(r, fd))
return -1;
fmt = validate_output_format(format);
if (fmt < 0) {
@@ -4884,7 +5239,7 @@ static int wdc_get_c0_log_page(int fd, char *format, int uuid_index, __u32 names
return fmt;
}
- ret = wdc_get_pci_ids(&device_id, &read_vendor_id);
+ ret = wdc_get_pci_ids(r, &device_id, &read_vendor_id);
switch (device_id) {
@@ -4894,15 +5249,19 @@ static int wdc_get_c0_log_page(int fd, char *format, int uuid_index, __u32 names
case WDC_NVME_SN640_DEV_ID_3:
case WDC_NVME_SN840_DEV_ID:
case WDC_NVME_SN840_DEV_ID_1:
- if (!get_dev_mgment_cbs_data(fd, WDC_C2_CUSTOMER_ID_ID, (void*)&data)) {
- fprintf(stderr, "%s: ERROR : WDC : 0xC2 Log Page entry ID 0x%x not found\n", __func__, WDC_C2_CUSTOMER_ID_ID);
+ case WDC_NVME_SN650_DEV_ID:
+ case WDC_NVME_SN650_DEV_ID_1:
+ case WDC_NVME_SN650_DEV_ID_2:
+ case WDC_NVME_SN650_DEV_ID_3:
+ case WDC_NVME_SN650_DEV_ID_4:
+ case WDC_NVME_SN655_DEV_ID:
+ cust_id = wdc_get_fw_cust_id(r, fd);
+ if (cust_id == WDC_INVALID_CUSTOMER_ID) {
+ fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__);
return -1;
}
- cust_id = (__u32*)data;
-
- if ((*cust_id == WDC_CUSTOMER_ID_0x1004) || (*cust_id == WDC_CUSTOMER_ID_0x1008) ||
- (*cust_id == WDC_CUSTOMER_ID_0x1005) || (*cust_id == WDC_CUSTOMER_ID_0x1304))
+ if ((cust_id == WDC_CUSTOMER_ID_0x1004) || (cust_id == WDC_CUSTOMER_ID_0x1008) || (cust_id == WDC_CUSTOMER_ID_0x1005))
{
if (uuid_index == 0)
{
@@ -4912,18 +5271,34 @@ static int wdc_get_c0_log_page(int fd, char *format, int uuid_index, __u32 names
}
if (namespace_id == NVME_NSID_ALL) {
- ret = namespace_id = nvme_get_nsid(fd);
+ ret = nvme_get_nsid(fd, &namespace_id);
if (ret < 0) {
namespace_id = NVME_NSID_ALL;
}
}
/* Get the 0xC0 log data */
- ret = nvme_get_log14(fd, namespace_id, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE,
- NVME_NO_LOG_LSP, 0, 0, false, uuid_index, 0, false, WDC_NVME_SMART_CLOUD_ATTR_LEN, data);
+ struct nvme_get_log_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .lid = WDC_NVME_GET_EOL_STATUS_LOG_OPCODE,
+ .nsid = namespace_id,
+ .lpo = 0,
+ .lsp = NVME_LOG_LSP_NONE,
+ .lsi = 0,
+ .rae = false,
+ .uuidx = uuid_index,
+ .csi = NVME_CSI_NVM,
+ .ot = false,
+ .len = WDC_NVME_SMART_CLOUD_ATTR_LEN,
+ .log = data,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ ret = nvme_get_log(&args);
if (strcmp(format, "json"))
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
if (ret == 0) {
@@ -4966,11 +5341,27 @@ static int wdc_get_c0_log_page(int fd, char *format, int uuid_index, __u32 names
}
/* Get the 0xC0 log data */
- ret = nvme_get_log14(fd, NVME_NSID_ALL, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE,
- NVME_NO_LOG_LSP, 0, 0, false, uuid_index, 0, false, WDC_NVME_EOL_STATUS_LOG_LEN, data);
+ struct nvme_get_log_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .lid = WDC_NVME_GET_EOL_STATUS_LOG_OPCODE,
+ .nsid = NVME_NSID_ALL,
+ .lpo = 0,
+ .lsp = NVME_LOG_LSP_NONE,
+ .lsi = 0,
+ .rae = false,
+ .uuidx = uuid_index,
+ .csi = NVME_CSI_NVM,
+ .ot = false,
+ .len = WDC_NVME_EOL_STATUS_LOG_LEN,
+ .log = data,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ ret = nvme_get_log(&args);
if (strcmp(format, "json"))
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
if (ret == 0) {
/* parse the data */
@@ -4993,11 +5384,11 @@ static int wdc_get_c0_log_page(int fd, char *format, int uuid_index, __u32 names
}
/* Get the 0xC0 log data */
- ret = nvme_get_log(fd, NVME_NSID_ALL, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE,
- false, NVME_NO_LOG_LSP, WDC_NVME_EOL_STATUS_LOG_LEN, data);
+ ret = nvme_get_log_simple(fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE,
+ WDC_NVME_EOL_STATUS_LOG_LEN, data);
if (strcmp(format, "json"))
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
if (ret == 0) {
/* parse the data */
@@ -5019,11 +5410,11 @@ static int wdc_get_c0_log_page(int fd, char *format, int uuid_index, __u32 names
}
/* Get the 0xC0 log data */
- ret = nvme_get_log(fd, NVME_NSID_ALL, WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_OPCODE,
- false, NVME_NO_LOG_LSP, WDC_NVME_SMART_CLOUD_ATTR_LEN, data);
+ ret = nvme_get_log_simple(fd, WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_OPCODE,
+ WDC_NVME_SMART_CLOUD_ATTR_LEN, data);
if (strcmp(format, "json"))
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
if (ret == 0) {
/* parse the data */
@@ -5064,6 +5455,57 @@ static int wdc_print_latency_monitor_log(int fd, struct wdc_ssd_latency_monitor_
return 0;
}
+static int wdc_print_error_rec_log(int fd, struct wdc_ocp_c1_error_recovery_log *log_data, int fmt)
+{
+ if (!log_data) {
+ fprintf(stderr, "ERROR : WDC : Invalid C1 log data buffer\n");
+ return -1;
+ }
+ switch (fmt) {
+ case NORMAL:
+ wdc_print_error_rec_log_normal(fd, log_data);
+ break;
+ case JSON:
+ wdc_print_error_rec_log_json(log_data);
+ break;
+ }
+ return 0;
+}
+
+static int wdc_print_dev_cap_log(int fd, struct wdc_ocp_C4_dev_cap_log *log_data, int fmt)
+{
+ if (!log_data) {
+ fprintf(stderr, "ERROR : WDC : Invalid C4 log data buffer\n");
+ return -1;
+ }
+ switch (fmt) {
+ case NORMAL:
+ wdc_print_dev_cap_log_normal(fd, log_data);
+ break;
+ case JSON:
+ wdc_print_dev_cap_log_json(log_data);
+ break;
+ }
+ return 0;
+}
+
+static int wdc_print_unsupported_reqs_log(int fd, struct wdc_ocp_C5_unsupported_reqs *log_data, int fmt)
+{
+ if (!log_data) {
+ fprintf(stderr, "ERROR : WDC : Invalid C5 log data buffer\n");
+ return -1;
+ }
+ switch (fmt) {
+ case NORMAL:
+ wdc_print_unsupported_reqs_log_normal(fd, log_data);
+ break;
+ case JSON:
+ wdc_print_unsupported_reqs_log_json(log_data);
+ break;
+ }
+ return 0;
+}
+
static int wdc_print_fb_ca_log(struct wdc_ssd_ca_perf_stats *perf, int fmt)
{
if (!perf) {
@@ -5094,6 +5536,9 @@ static int wdc_print_bd_ca_log(void *bd_data, int fmt)
case JSON:
wdc_print_bd_ca_log_json(bd_data);
break;
+ default:
+ fprintf(stderr, "ERROR : WDC : Unknown format - %d\n", fmt);
+ return -1;
}
return 0;
}
@@ -5133,16 +5578,16 @@ static int wdc_print_fw_act_history_log(__u8 *data, int num_entries, int fmt, __
return 0;
}
-static int wdc_get_ca_log_page(int fd, char *format)
+static int wdc_get_ca_log_page(nvme_root_t r, int fd, char *format)
{
int ret = 0;
int fmt = -1;
__u8 *data;
- __u32 *cust_id;
struct wdc_ssd_ca_perf_stats *perf;
uint32_t read_device_id, read_vendor_id;
+ __u32 cust_id;
- if (!wdc_check_device(fd))
+ if (!wdc_check_device(r, fd))
return -1;
fmt = validate_output_format(format);
if (fmt < 0) {
@@ -5151,25 +5596,25 @@ static int wdc_get_ca_log_page(int fd, char *format)
}
/* verify the 0xCA log page is supported */
- if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == false) {
+ if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == false) {
fprintf(stderr, "ERROR : WDC : 0xCA Log Page not supported\n");
return -1;
}
- if (!get_dev_mgment_cbs_data(fd, WDC_C2_CUSTOMER_ID_ID, (void*)&data)) {
- fprintf(stderr, "%s: ERROR : WDC : 0xC2 Log Page entry ID 0x%x not found\n", __func__, WDC_C2_CUSTOMER_ID_ID);
+ /* get the FW customer id */
+ cust_id = wdc_get_fw_cust_id(r, fd);
+ if (cust_id == WDC_INVALID_CUSTOMER_ID) {
+ fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__);
return -1;
}
- ret = wdc_get_pci_ids(&read_device_id, &read_vendor_id);
-
- cust_id = (__u32*)data;
+ ret = wdc_get_pci_ids(r, &read_device_id, &read_vendor_id);
switch (read_device_id) {
case WDC_NVME_SN200_DEV_ID:
- if (*cust_id == WDC_CUSTOMER_ID_0x1005) {
+ if (cust_id == WDC_CUSTOMER_ID_0x1005) {
if ((data = (__u8*) malloc(sizeof (__u8) * WDC_FB_CA_LOG_BUF_LEN)) == NULL) {
fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno));
@@ -5178,10 +5623,10 @@ static int wdc_get_ca_log_page(int fd, char *format)
memset(data, 0, sizeof (__u8) * WDC_FB_CA_LOG_BUF_LEN);
- ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE,
- false, NVME_NO_LOG_LSP, WDC_FB_CA_LOG_BUF_LEN, data);
+ ret = nvme_get_log_simple(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE,
+ WDC_FB_CA_LOG_BUF_LEN, data);
if (strcmp(format, "json"))
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
if (ret == 0) {
/* parse the data */
@@ -5193,7 +5638,7 @@ static int wdc_get_ca_log_page(int fd, char *format)
}
} else {
- fprintf(stderr, "ERROR : WDC : Unsupported Customer id, id = 0x%x\n", *cust_id);
+ fprintf(stderr, "ERROR : WDC : Unsupported Customer id, id = 0x%x\n", cust_id);
return -1;
}
break;
@@ -5205,7 +5650,7 @@ static int wdc_get_ca_log_page(int fd, char *format)
case WDC_NVME_SN840_DEV_ID:
case WDC_NVME_SN840_DEV_ID_1:
- if (*cust_id == WDC_CUSTOMER_ID_0x1005) {
+ if (cust_id == WDC_CUSTOMER_ID_0x1005) {
if ((data = (__u8*) malloc(sizeof (__u8) * WDC_FB_CA_LOG_BUF_LEN)) == NULL) {
fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno));
@@ -5214,10 +5659,10 @@ static int wdc_get_ca_log_page(int fd, char *format)
memset(data, 0, sizeof (__u8) * WDC_FB_CA_LOG_BUF_LEN);
- ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE,
- false, NVME_NO_LOG_LSP, WDC_FB_CA_LOG_BUF_LEN, data);
+ ret = nvme_get_log_simple(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE,
+ WDC_FB_CA_LOG_BUF_LEN, data);
if (strcmp(format, "json"))
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
if (ret == 0) {
/* parse the data */
@@ -5227,19 +5672,18 @@ static int wdc_get_ca_log_page(int fd, char *format)
fprintf(stderr, "ERROR : WDC : Unable to read CA Log Page data\n");
ret = -1;
}
- } else if ((*cust_id == WDC_CUSTOMER_ID_GN) || (*cust_id == WDC_CUSTOMER_ID_GD) ||
- (*cust_id == WDC_CUSTOMER_ID_BD)) {
-
+ } else if ((cust_id == WDC_CUSTOMER_ID_GN) || (cust_id == WDC_CUSTOMER_ID_GD) ||
+ (cust_id == WDC_CUSTOMER_ID_BD)) {
if ((data = (__u8*) malloc(sizeof (__u8) * WDC_BD_CA_LOG_BUF_LEN)) == NULL) {
fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno));
return -1;
}
memset(data, 0, sizeof (__u8) * WDC_BD_CA_LOG_BUF_LEN);
- ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE,
- false, NVME_NO_LOG_LSP, WDC_BD_CA_LOG_BUF_LEN, data);
+ ret = nvme_get_log_simple(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE,
+ WDC_BD_CA_LOG_BUF_LEN, data);
if (strcmp(format, "json"))
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
if (ret == 0) {
/* parse the data */
@@ -5252,7 +5696,7 @@ static int wdc_get_ca_log_page(int fd, char *format)
break;
} else {
- fprintf(stderr, "ERROR : WDC : Unsupported Customer id, id = 0x%x\n", *cust_id);
+ fprintf(stderr, "ERROR : WDC : Unsupported Customer id, id = 0x%x\n", cust_id);
return -1;
}
break;
@@ -5268,7 +5712,8 @@ static int wdc_get_ca_log_page(int fd, char *format)
return ret;
}
-static int wdc_get_c1_log_page(int fd, char *format, uint8_t interval)
+static int wdc_get_c1_log_page(nvme_root_t r, int fd,
+ char *format, uint8_t interval)
{
int ret = 0;
int fmt = -1;
@@ -5281,7 +5726,7 @@ static int wdc_get_c1_log_page(int fd, char *format, uint8_t interval)
struct wdc_log_page_subpage_header *sph;
struct wdc_ssd_perf_stats *perf;
- if (!wdc_check_device(fd))
+ if (!wdc_check_device(r, fd))
return -1;
fmt = validate_output_format(format);
if (fmt < 0) {
@@ -5300,10 +5745,10 @@ static int wdc_get_c1_log_page(int fd, char *format, uint8_t interval)
}
memset(data, 0, sizeof (__u8) * WDC_ADD_LOG_BUF_LEN);
- ret = nvme_get_log(fd, 0x01, WDC_NVME_ADD_LOG_OPCODE, false,
- NVME_NO_LOG_LSP, WDC_ADD_LOG_BUF_LEN, data);
+ ret = nvme_get_log_simple(fd, WDC_NVME_ADD_LOG_OPCODE,
+ WDC_ADD_LOG_BUF_LEN, data);
if (strcmp(format, "json"))
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
if (ret == 0) {
l = (struct wdc_log_page_header*)data;
total_subpages = l->num_subpages + WDC_NVME_GET_STAT_PERF_INTERVAL_LIFETIME - 1;
@@ -5326,7 +5771,7 @@ static int wdc_get_c1_log_page(int fd, char *format, uint8_t interval)
return ret;
}
-static int wdc_get_c3_log_page(int fd, char *format)
+static int wdc_get_c3_log_page(nvme_root_t r, int fd, char *format)
{
int ret = 0;
int fmt = -1;
@@ -5334,7 +5779,7 @@ static int wdc_get_c3_log_page(int fd, char *format)
int i;
struct wdc_ssd_latency_monitor_log *log_data;
- if (!wdc_check_device(fd))
+ if (!wdc_check_device(r, fd))
return -1;
fmt = validate_output_format(format);
if (fmt < 0) {
@@ -5348,12 +5793,11 @@ static int wdc_get_c3_log_page(int fd, char *format)
}
memset(data, 0, sizeof (__u8) * WDC_LATENCY_MON_LOG_BUF_LEN);
- ret = nvme_get_log14(fd, NVME_NSID_ALL, WDC_LATENCY_MON_OPCODE,
- NVME_NO_LOG_LSP, NVME_NO_LOG_LPO, 0, 0,
- 0, 0, 0, WDC_LATENCY_MON_LOG_BUF_LEN, data);
+ ret = nvme_get_log_simple(fd, WDC_LATENCY_MON_OPCODE,
+ WDC_LATENCY_MON_LOG_BUF_LEN, data);
if (strcmp(format, "json"))
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret, false), ret);
if (ret == 0) {
log_data = (struct wdc_ssd_latency_monitor_log*)data;
@@ -5386,7 +5830,7 @@ static int wdc_get_c3_log_page(int fd, char *format)
}
}
- /* parse the data */
+ /* parse the data */
wdc_print_latency_monitor_log(fd, log_data, fmt);
} else {
fprintf(stderr, "ERROR : WDC : Unable to read C3 data from buffer\n");
@@ -5395,16 +5839,224 @@ static int wdc_get_c3_log_page(int fd, char *format)
out:
free(data);
return ret;
+
}
-static int wdc_get_d0_log_page(int fd, char *format)
+static int wdc_get_ocp_c1_log_page(nvme_root_t r, int fd, char *format)
+{
+ int ret = 0;
+ int fmt = -1;
+ __u8 *data;
+ int i;
+ struct wdc_ocp_c1_error_recovery_log *log_data;
+
+ if (!wdc_check_device(r, fd))
+ return -1;
+ fmt = validate_output_format(format);
+ if (fmt < 0) {
+ fprintf(stderr, "ERROR : WDC : invalid output format\n");
+ return fmt;
+ }
+
+ if ((data = (__u8 *) malloc(sizeof(__u8) * WDC_ERROR_REC_LOG_BUF_LEN)) == NULL) {
+ fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno));
+ return -1;
+ }
+ memset(data, 0, sizeof (__u8) * WDC_ERROR_REC_LOG_BUF_LEN);
+
+ ret = nvme_get_log_simple(fd, WDC_ERROR_REC_LOG_ID,
+ WDC_ERROR_REC_LOG_BUF_LEN, data);
+
+ if (strcmp(format, "json"))
+ fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret, false), ret);
+
+ if (ret == 0) {
+ log_data = (struct wdc_ocp_c1_error_recovery_log *)data;
+
+ /* check log page version */
+ if (log_data->log_page_version != WDC_ERROR_REC_LOG_VERSION) {
+ fprintf(stderr, "ERROR : WDC : invalid error recovery log version - %d\n", log_data->log_page_version);
+ ret = -1;
+ goto out;
+ }
+
+ /* Verify GUID matches */
+ for (i=0; i < WDC_OCP_C1_GUID_LENGTH; i++) {
+ if (wdc_ocp_c1_guid[i] != log_data->log_page_guid[i]) {
+ fprintf(stderr, "ERROR : WDC : Unknown GUID in C1 Log Page data\n");
+ int j;
+ fprintf(stderr, "ERROR : WDC : Expected GUID: 0x");
+ for (j = 0; j<16; j++) {
+ fprintf(stderr, "%x", wdc_ocp_c1_guid[j]);
+ }
+ fprintf(stderr, "\nERROR : WDC : Actual GUID: 0x");
+ for (j = 0; j<16; j++) {
+ fprintf(stderr, "%x", log_data->log_page_guid[j]);
+ }
+ fprintf(stderr, "\n");
+
+ ret = -1;
+ goto out;
+ }
+ }
+
+ /* parse the data */
+ wdc_print_error_rec_log(fd, log_data, fmt);
+ } else {
+ fprintf(stderr, "ERROR : WDC : Unable to read error recovery (C1) data from buffer\n");
+ }
+
+out:
+ free(data);
+ return ret;
+}
+
+static int wdc_get_ocp_c4_log_page(nvme_root_t r, int fd, char *format)
+{
+ int ret = 0;
+ int fmt = -1;
+ __u8 *data;
+ int i;
+ struct wdc_ocp_C4_dev_cap_log *log_data;
+
+ if (!wdc_check_device(r, fd))
+ return -1;
+ fmt = validate_output_format(format);
+ if (fmt < 0) {
+ fprintf(stderr, "ERROR : WDC : invalid output format\n");
+ return fmt;
+ }
+
+ if ((data = (__u8 *) malloc(sizeof(__u8) * WDC_DEV_CAP_LOG_BUF_LEN)) == NULL) {
+ fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno));
+ return -1;
+ }
+ memset(data, 0, sizeof (__u8) * WDC_DEV_CAP_LOG_BUF_LEN);
+
+ ret = nvme_get_log_simple(fd, WDC_DEV_CAP_LOG_ID,
+ WDC_DEV_CAP_LOG_BUF_LEN, data);
+
+ if (strcmp(format, "json"))
+ fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret, false), ret);
+
+ if (ret == 0) {
+ log_data = (struct wdc_ocp_C4_dev_cap_log *)data;
+
+ /* check log page version */
+ if (log_data->log_page_version != WDC_DEV_CAP_LOG_VERSION) {
+ fprintf(stderr, "ERROR : WDC : invalid device capabilities log version - %d\n", log_data->log_page_version);
+ ret = -1;
+ goto out;
+ }
+
+ /* Verify GUID matches */
+ for (i=0; i < WDC_OCP_C4_GUID_LENGTH; i++) {
+ if (wdc_ocp_c4_guid[i] != log_data->log_page_guid[i]) {
+ fprintf(stderr, "ERROR : WDC : Unknown GUID in C4 Log Page data\n");
+ int j;
+ fprintf(stderr, "ERROR : WDC : Expected GUID: 0x");
+ for (j = 0; j<16; j++) {
+ fprintf(stderr, "%x", wdc_ocp_c1_guid[j]);
+ }
+ fprintf(stderr, "\nERROR : WDC : Actual GUID: 0x");
+ for (j = 0; j<16; j++) {
+ fprintf(stderr, "%x", log_data->log_page_guid[j]);
+ }
+ fprintf(stderr, "\n");
+
+ ret = -1;
+ goto out;
+ }
+ }
+
+ /* parse the data */
+ wdc_print_dev_cap_log(fd, log_data, fmt);
+ } else {
+ fprintf(stderr, "ERROR : WDC : Unable to read device capabilities (C4) data from buffer\n");
+ }
+
+out:
+ free(data);
+ return ret;
+}
+
+static int wdc_get_ocp_c5_log_page(nvme_root_t r, int fd, char *format)
+{
+ int ret = 0;
+ int fmt = -1;
+ __u8 *data;
+ int i;
+ struct wdc_ocp_C5_unsupported_reqs *log_data;
+
+ if (!wdc_check_device(r, fd))
+ return -1;
+ fmt = validate_output_format(format);
+ if (fmt < 0) {
+ fprintf(stderr, "ERROR : WDC : invalid output format\n");
+ return fmt;
+ }
+
+ if ((data = (__u8 *) malloc(sizeof(__u8) * WDC_UNSUPPORTED_REQS_LOG_BUF_LEN)) == NULL) {
+ fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno));
+ return -1;
+ }
+ memset(data, 0, sizeof (__u8) * WDC_UNSUPPORTED_REQS_LOG_BUF_LEN);
+
+ ret = nvme_get_log_simple(fd, WDC_UNSUPPORTED_REQS_LOG_ID,
+ WDC_UNSUPPORTED_REQS_LOG_BUF_LEN, data);
+
+ if (strcmp(format, "json"))
+ fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret, false), ret);
+
+ if (ret == 0) {
+ log_data = (struct wdc_ocp_C5_unsupported_reqs *)data;
+
+ /* 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);
+ ret = -1;
+ goto out;
+ }
+
+ /* Verify GUID matches */
+ for (i=0; i < WDC_OCP_C5_GUID_LENGTH; i++) {
+ if (wdc_ocp_c5_guid[i] != log_data->log_page_guid[i]) {
+ fprintf(stderr, "ERROR : WDC : Unknown GUID in C5 Log Page data\n");
+ int j;
+ fprintf(stderr, "ERROR : WDC : Expected GUID: 0x");
+ for (j = 0; j<16; j++) {
+ fprintf(stderr, "%x", wdc_ocp_c1_guid[j]);
+ }
+ fprintf(stderr, "\nERROR : WDC : Actual GUID: 0x");
+ for (j = 0; j<16; j++) {
+ fprintf(stderr, "%x", log_data->log_page_guid[j]);
+ }
+ fprintf(stderr, "\n");
+
+ ret = -1;
+ goto out;
+ }
+ }
+
+ /* parse the data */
+ wdc_print_unsupported_reqs_log(fd, log_data, fmt);
+ } else {
+ fprintf(stderr, "ERROR : WDC : Unable to read unsupported requirements (C5) data from buffer\n");
+ }
+
+out:
+ free(data);
+ return ret;
+}
+
+static int wdc_get_d0_log_page(nvme_root_t r, int fd, char *format)
{
int ret = 0;
int fmt = -1;
__u8 *data;
struct wdc_ssd_d0_smart_log *perf;
- if (!wdc_check_device(fd))
+ if (!wdc_check_device(r, fd))
return -1;
fmt = validate_output_format(format);
if (fmt < 0) {
@@ -5413,7 +6065,7 @@ static int wdc_get_d0_log_page(int fd, char *format)
}
/* verify the 0xD0 log page is supported */
- if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == false) {
+ if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == false) {
fprintf(stderr, "ERROR : WDC : 0xD0 Log Page not supported\n");
return -1;
}
@@ -5424,10 +6076,10 @@ static int wdc_get_d0_log_page(int fd, char *format)
}
memset(data, 0, sizeof (__u8) * WDC_NVME_VU_SMART_LOG_LEN);
- ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_VU_SMART_LOG_OPCODE,
- false, NVME_NO_LOG_LSP, WDC_NVME_VU_SMART_LOG_LEN, data);
+ ret = nvme_get_log_simple(fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE,
+ WDC_NVME_VU_SMART_LOG_LEN, data);
if (strcmp(format, "json"))
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
if (ret == 0) {
/* parse the data */
@@ -5451,6 +6103,7 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command,
const char *log_page_version = "Log Page Version: 0 = vendor, 1 = WDC";
const char *log_page_mask = "Log Page Mask, comma separated list: 0xC0, 0xC1, 0xCA, 0xD0";
const char *namespace_id = "desired namespace id";
+ nvme_root_t r;
int ret = 0;
int uuid_index = 0;
int page_mask = 0, num, i;
@@ -5486,6 +6139,7 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command,
if (fd < 0)
return fd;
+ r = nvme_scan(NULL);
if (cfg.log_page_version == 0) {
uuid_index = 0;
} else if (cfg.log_page_version == 1) {
@@ -5530,7 +6184,7 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command,
fprintf(stderr, "ERROR : WDC: Unknown log page mask - %s\n", cfg.log_page_mask);
- capabilities = wdc_get_drive_capabilities(fd);
+ capabilities = wdc_get_drive_capabilities(r, fd);
if ((capabilities & WDC_DRIVE_CAP_SMART_LOG_MASK) == 0) {
fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
@@ -5541,34 +6195,34 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command,
if (((capabilities & WDC_DRIVE_CAP_C0_LOG_PAGE) == WDC_DRIVE_CAP_C0_LOG_PAGE) &&
(page_mask & WDC_C0_PAGE_MASK)) {
/* Get 0xC0 log page if possible. */
- ret = wdc_get_c0_log_page(fd, cfg.output_format, uuid_index, cfg.namespace_id);
+ ret = wdc_get_c0_log_page(r, fd, cfg.output_format, uuid_index, cfg.namespace_id);
if (ret)
fprintf(stderr, "ERROR : WDC : Failure reading the C0 Log Page, ret = %d\n", ret);
}
if (((capabilities & (WDC_DRIVE_CAP_CA_LOG_PAGE)) == (WDC_DRIVE_CAP_CA_LOG_PAGE)) &&
(page_mask & WDC_CA_PAGE_MASK)) {
/* Get the CA Log Page */
- ret = wdc_get_ca_log_page(fd, cfg.output_format);
+ ret = wdc_get_ca_log_page(r, fd, cfg.output_format);
if (ret)
fprintf(stderr, "ERROR : WDC : Failure reading the CA Log Page, ret = %d\n", ret);
}
if (((capabilities & WDC_DRIVE_CAP_C1_LOG_PAGE) == WDC_DRIVE_CAP_C1_LOG_PAGE) &&
(page_mask & WDC_C1_PAGE_MASK)) {
/* Get the C1 Log Page */
- ret = wdc_get_c1_log_page(fd, cfg.output_format, cfg.interval);
+ ret = wdc_get_c1_log_page(r, fd, cfg.output_format, cfg.interval);
if (ret)
fprintf(stderr, "ERROR : WDC : Failure reading the C1 Log Page, ret = %d\n", ret);
}
if (((capabilities & WDC_DRIVE_CAP_D0_LOG_PAGE) == WDC_DRIVE_CAP_D0_LOG_PAGE) &&
(page_mask & WDC_D0_PAGE_MASK)) {
/* Get the D0 Log Page */
- ret = wdc_get_d0_log_page(fd, cfg.output_format);
+ ret = wdc_get_d0_log_page(r, fd, cfg.output_format);
if (ret)
fprintf(stderr, "ERROR : WDC : Failure reading the D0 Log Page, ret = %d\n", ret);
}
out:
-
+ nvme_free_tree(r);
return ret;
}
@@ -5576,6 +6230,7 @@ static int wdc_get_latency_monitor_log(int argc, char **argv, struct command *co
struct plugin *plugin)
{
const char *desc = "Retrieve latency monitor log data.";
+ nvme_root_t r;
int fd;
int ret = 0;
__u64 capabilities = 0;
@@ -5597,7 +6252,8 @@ static int wdc_get_latency_monitor_log(int argc, char **argv, struct command *co
if (fd < 0)
return fd;
- capabilities = wdc_get_drive_capabilities(fd);
+ r = nvme_scan(NULL);
+ capabilities = wdc_get_drive_capabilities(r, fd);
if ((capabilities & WDC_DRIVE_CAP_C3_LOG_PAGE) == 0) {
fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
@@ -5605,12 +6261,140 @@ static int wdc_get_latency_monitor_log(int argc, char **argv, struct command *co
goto out;
}
- ret = wdc_get_c3_log_page(fd, cfg.output_format);
+ ret = wdc_get_c3_log_page(r, fd, cfg.output_format);
+ if (ret)
+ fprintf(stderr, "ERROR : WDC : Failure reading the Latency Monitor (C3) Log Page, ret = %d\n", ret);
+
+out:
+ return ret;
+}
+
+static int wdc_get_error_recovery_log(int argc, char **argv, struct command *command,
+ struct plugin *plugin)
+{
+ const char *desc = "Retrieve error recovery log data.";
+ nvme_root_t r;
+ int fd;
+ int ret = 0;
+ __u64 capabilities = 0;
+
+ struct config {
+ char *output_format;
+ };
+
+ struct config cfg = {
+ .output_format = "normal",
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_FMT("output-format", 'o', &cfg.output_format, "Output Format: normal|json"),
+ OPT_END()
+ };
+
+ fd = parse_and_open(argc, argv, desc, opts);
+ if (fd < 0)
+ return fd;
+
+ r = nvme_scan(NULL);
+ capabilities = wdc_get_drive_capabilities(r, fd);
+
+ if ((capabilities & WDC_DRIVE_CAP_OCP_C1_LOG_PAGE) == 0) {
+ fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
+ ret = -1;
+ goto out;
+ }
+
+ ret = wdc_get_ocp_c1_log_page(r, fd, cfg.output_format);
if (ret)
- fprintf(stderr, "ERROR : WDC : Failure reading the C3 Log Page, ret = %d\n", ret);
+ fprintf(stderr, "ERROR : WDC : Failure reading the Error Recovery (C1) Log Page, ret = 0x%x\n", ret);
out:
+ return ret;
+}
+
+static int wdc_get_dev_capabilities_log(int argc, char **argv, struct command *command,
+ struct plugin *plugin)
+{
+ const char *desc = "Retrieve device capabilities log data.";
+ nvme_root_t r;
+ int fd;
+ int ret = 0;
+ __u64 capabilities = 0;
+
+ struct config {
+ char *output_format;
+ };
+
+ struct config cfg = {
+ .output_format = "normal",
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_FMT("output-format", 'o', &cfg.output_format, "Output Format: normal|json"),
+ OPT_END()
+ };
+
+ fd = parse_and_open(argc, argv, desc, opts);
+ if (fd < 0)
+ return fd;
+
+ r = nvme_scan(NULL);
+ capabilities = wdc_get_drive_capabilities(r, fd);
+
+ if ((capabilities & WDC_DRIVE_CAP_OCP_C4_LOG_PAGE) == 0) {
+ fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
+ ret = -1;
+ goto out;
+ }
+
+ ret = wdc_get_ocp_c4_log_page(r, fd, cfg.output_format);
+ if (ret)
+ fprintf(stderr, "ERROR : WDC : Failure reading the Device Capabilities (C4) Log Page, ret = 0x%x\n", ret);
+out:
+ return ret;
+}
+
+static int wdc_get_unsupported_reqs_log(int argc, char **argv, struct command *command,
+ struct plugin *plugin)
+{
+ const char *desc = "Retrieve unsupported requirements log data.";
+ nvme_root_t r;
+ int fd;
+ int ret = 0;
+ __u64 capabilities = 0;
+
+ struct config {
+ char *output_format;
+ };
+
+ struct config cfg = {
+ .output_format = "normal",
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_FMT("output-format", 'o', &cfg.output_format, "Output Format: normal|json"),
+ OPT_END()
+ };
+
+ fd = parse_and_open(argc, argv, desc, opts);
+ if (fd < 0)
+ return fd;
+
+ r = nvme_scan(NULL);
+ capabilities = wdc_get_drive_capabilities(r, fd);
+
+ if ((capabilities & WDC_DRIVE_CAP_OCP_C5_LOG_PAGE) == 0) {
+ fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
+ ret = -1;
+ goto out;
+ }
+
+ ret = wdc_get_ocp_c5_log_page(r, fd, cfg.output_format);
+ if (ret)
+ fprintf(stderr, "ERROR : WDC : Failure reading the Unsupported Requirements (C5) Log Page, ret = 0x%x\n", ret);
+
+out:
return ret;
}
@@ -5624,8 +6408,8 @@ static int wdc_do_clear_pcie_correctable_errors(int fd)
admin_cmd.cdw12 = ((WDC_NVME_CLEAR_PCIE_CORR_SUBCMD << WDC_NVME_SUBCMD_SHIFT) |
WDC_NVME_CLEAR_PCIE_CORR_CMD);
- ret = nvme_submit_admin_passthru(fd, &admin_cmd);
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL);
+ nvme_show_status(ret);
return ret;
}
@@ -5637,8 +6421,8 @@ static int wdc_do_clear_pcie_correctable_errors_vuc(int fd)
memset(&admin_cmd, 0, sizeof (admin_cmd));
admin_cmd.opcode = WDC_NVME_CLEAR_PCIE_CORR_OPCODE_VUC;
- ret = nvme_submit_admin_passthru(fd, &admin_cmd);
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL);
+ nvme_show_status(ret);
return ret;
}
@@ -5648,10 +6432,10 @@ static int wdc_do_clear_pcie_correctable_errors_fid(int fd)
__u32 result;
__u32 value = 1 << 31; /* Bit 31 - clear PCIe correctable count */
- ret = nvme_set_feature(fd, 0, WDC_NVME_CLEAR_PCIE_CORR_FEATURE_ID, value,
- 0, 0, 0, 0, NULL, &result);
+ ret = nvme_set_features_simple(fd, WDC_NVME_CLEAR_PCIE_CORR_FEATURE_ID, 0, value,
+ false, &result);
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
return ret;
}
@@ -5660,6 +6444,7 @@ static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct comma
{
char *desc = "Clear PCIE Correctable Errors.";
int fd, ret;
+ nvme_root_t r;
__u64 capabilities = 0;
OPT_ARGS(opts) = {
@@ -5670,12 +6455,13 @@ static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct comma
if (fd < 0)
return fd;
- if (!wdc_check_device(fd)) {
+ r = nvme_scan(NULL);
+ if (!wdc_check_device(r, fd)) {
ret = -1;
goto out;
}
- capabilities = wdc_get_drive_capabilities(fd);
+ capabilities = wdc_get_drive_capabilities(r, fd);
if ((capabilities & WDC_DRIVE_CAP_CLEAR_PCIE_MASK) == 0) {
fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
ret = -1;
@@ -5693,6 +6479,7 @@ static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct comma
}
out:
+ nvme_free_tree(r);
return ret;
}
@@ -5702,6 +6489,7 @@ static int wdc_drive_status(int argc, char **argv, struct command *command,
char *desc = "Get Drive Status.";
int fd;
int ret = 0;
+ nvme_root_t r;
__le32 system_eol_state;
__le32 user_eol_state;
__le32 format_corrupt_reason = cpu_to_le32(0xFFFFFFFF);
@@ -5718,7 +6506,8 @@ static int wdc_drive_status(int argc, char **argv, struct command *command,
if (fd < 0)
return fd;
- capabilities = wdc_get_drive_capabilities(fd);
+ r = nvme_scan(NULL);
+ capabilities = wdc_get_drive_capabilities(r, fd);
if ((capabilities & WDC_DRIVE_CAP_DRIVE_STATUS) != WDC_DRIVE_CAP_DRIVE_STATUS) {
fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
ret = -1;
@@ -5726,46 +6515,46 @@ static int wdc_drive_status(int argc, char **argv, struct command *command,
}
/* verify the 0xC2 Device Manageability log page is supported */
- if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE) == false) {
+ if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE) == false) {
fprintf(stderr, "ERROR : WDC : 0xC2 Log Page not supported\n");
ret = -1;
goto out;
}
/* Get the assert dump present status */
- if (!wdc_nvme_get_dev_status_log_data(fd, &assert_status,
+ if (!wdc_nvme_get_dev_status_log_data(r, fd, &assert_status,
WDC_C2_ASSERT_DUMP_PRESENT_ID))
fprintf(stderr, "ERROR : WDC : Get Assert Status Failed\n");
/* Get the thermal throttling status */
- if (!wdc_nvme_get_dev_status_log_data(fd, &thermal_status,
+ if (!wdc_nvme_get_dev_status_log_data(r, fd, &thermal_status,
WDC_C2_THERMAL_THROTTLE_STATUS_ID))
fprintf(stderr, "ERROR : WDC : Get Thermal Throttling Status Failed\n");
/* Get EOL status */
- if (!wdc_nvme_get_dev_status_log_data(fd, &eol_status,
+ if (!wdc_nvme_get_dev_status_log_data(r, fd, &eol_status,
WDC_C2_USER_EOL_STATUS_ID)) {
fprintf(stderr, "ERROR : WDC : Get User EOL Status Failed\n");
eol_status = cpu_to_le32(-1);
}
/* Get Customer EOL state */
- if (!wdc_nvme_get_dev_status_log_data(fd, &user_eol_state,
+ if (!wdc_nvme_get_dev_status_log_data(r, fd, &user_eol_state,
WDC_C2_USER_EOL_STATE_ID))
fprintf(stderr, "ERROR : WDC : Get User EOL State Failed\n");
/* Get System EOL state*/
- if (!wdc_nvme_get_dev_status_log_data(fd, &system_eol_state,
+ if (!wdc_nvme_get_dev_status_log_data(r, fd, &system_eol_state,
WDC_C2_SYSTEM_EOL_STATE_ID))
fprintf(stderr, "ERROR : WDC : Get System EOL State Failed\n");
/* Get format corrupt reason*/
- if (!wdc_nvme_get_dev_status_log_data(fd, &format_corrupt_reason,
+ if (!wdc_nvme_get_dev_status_log_data(r, fd, &format_corrupt_reason,
WDC_C2_FORMAT_CORRUPT_REASON_ID))
fprintf(stderr, "ERROR : WDC : Get Format Corrupt Reason Failed\n");
printf(" Drive Status :- \n");
- if (le32_to_cpu(eol_status) >= 0) {
+ if ((int)le32_to_cpu(eol_status) >= 0) {
printf(" Percent Used: %"PRIu32"%%\n",
le32_to_cpu(eol_status));
}
@@ -5807,6 +6596,7 @@ static int wdc_drive_status(int argc, char **argv, struct command *command,
printf(" Format Corrupt Reason: Unknown : 0x%08x\n", le32_to_cpu(format_corrupt_reason));
out:
+ nvme_free_tree(r);
return ret;
}
@@ -5816,6 +6606,7 @@ static int wdc_clear_assert_dump(int argc, char **argv, struct command *command,
char *desc = "Clear Assert Dump Present Status.";
int fd;
int ret = -1;
+ nvme_root_t r;
__le32 assert_status = cpu_to_le32(0xFFFFFFFF);
__u64 capabilities = 0;
struct nvme_passthru_cmd admin_cmd;
@@ -5828,13 +6619,14 @@ static int wdc_clear_assert_dump(int argc, char **argv, struct command *command,
if (fd < 0)
return fd;
- capabilities = wdc_get_drive_capabilities(fd);
+ r = nvme_scan(NULL);
+ capabilities = wdc_get_drive_capabilities(r, fd);
if ((capabilities & WDC_DRIVE_CAP_CLEAR_ASSERT) != WDC_DRIVE_CAP_CLEAR_ASSERT) {
fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
ret = -1;
goto out;
}
- if (!wdc_nvme_get_dev_status_log_data(fd, &assert_status,
+ if (!wdc_nvme_get_dev_status_log_data(r, fd, &assert_status,
WDC_C2_ASSERT_DUMP_PRESENT_ID)) {
fprintf(stderr, "ERROR : WDC : Get Assert Status Failed\n");
ret = -1;
@@ -5848,23 +6640,24 @@ static int wdc_clear_assert_dump(int argc, char **argv, struct command *command,
admin_cmd.cdw12 = ((WDC_NVME_CLEAR_ASSERT_DUMP_SUBCMD << WDC_NVME_SUBCMD_SHIFT) |
WDC_NVME_CLEAR_ASSERT_DUMP_CMD);
- ret = nvme_submit_admin_passthru(fd, &admin_cmd);
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL);
+ nvme_show_status(ret);
} else
fprintf(stderr, "INFO : WDC : No Assert Dump Present\n");
out:
+ nvme_free_tree(r);
return ret;
}
-static int wdc_get_fw_act_history(int fd, char *format)
+static int wdc_get_fw_act_history(nvme_root_t r, int fd, char *format)
{
int ret = 0;
int fmt = -1;
__u8 *data;
struct wdc_fw_act_history_log_hdr *fw_act_history_hdr;
- if (!wdc_check_device(fd))
+ if (!wdc_check_device(r, fd))
return -1;
fmt = validate_output_format(format);
@@ -5874,7 +6667,7 @@ static int wdc_get_fw_act_history(int fd, char *format)
}
/* verify the FW Activate History log page is supported */
- if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID) == false) {
+ if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID) == false) {
fprintf(stderr, "ERROR : WDC : %d Log Page not supported\n", WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID);
return -1;
}
@@ -5886,11 +6679,11 @@ static int wdc_get_fw_act_history(int fd, char *format)
memset(data, 0, sizeof (__u8) * WDC_FW_ACT_HISTORY_LOG_BUF_LEN);
- ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID,
- false, NVME_NO_LOG_LSP, WDC_FW_ACT_HISTORY_LOG_BUF_LEN, data);
+ ret = nvme_get_log_simple(fd, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID,
+ WDC_FW_ACT_HISTORY_LOG_BUF_LEN, data);
if (strcmp(format, "json"))
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
if (ret == 0) {
/* parse the data */
@@ -5915,17 +6708,33 @@ static int wdc_get_fw_act_history(int fd, char *format)
return ret;
}
-static int wdc_get_fw_act_history_C2(int fd, char *format)
+static __u32 wdc_get_fw_cust_id(nvme_root_t r, int fd)
+{
+
+ __u32 cust_id = WDC_INVALID_CUSTOMER_ID;
+ __u32 *cust_id_ptr = NULL;
+
+ if (!(get_dev_mgment_cbs_data(r, fd, WDC_C2_CUSTOMER_ID_ID, (void*)&cust_id_ptr))) {
+ fprintf(stderr, "%s: ERROR : WDC : 0xC2 Log Page entry ID 0x%x not found\n", __func__, WDC_C2_CUSTOMER_ID_ID);
+ } else {
+ cust_id = *cust_id_ptr;
+ }
+
+ free(cust_id_ptr);
+ return cust_id;
+}
+
+static int wdc_get_fw_act_history_C2(nvme_root_t r, int fd, char *format)
{
int ret = 0;
int fmt = -1;
__u8 *data;
- __u32 *cust_id;
+ __u32 cust_id;
struct wdc_fw_act_history_log_format_c2 *fw_act_history_log;
__u32 tot_entries = 0, num_entries = 0;
__u32 vendor_id = 0, device_id = 0;
- if (!wdc_check_device(fd))
+ if (!wdc_check_device(r, fd))
return -1;
fmt = validate_output_format(format);
@@ -5933,7 +6742,8 @@ static int wdc_get_fw_act_history_C2(int fd, char *format)
fprintf(stderr, "ERROR : WDC : invalid output format\n");
return fmt;
}
- ret = wdc_get_pci_ids(&device_id, &vendor_id);
+
+ ret = wdc_get_pci_ids(r, &device_id, &vendor_id);
if ((data = (__u8*) malloc(sizeof (__u8) * WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN)) == NULL) {
fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno));
@@ -5942,11 +6752,11 @@ static int wdc_get_fw_act_history_C2(int fd, char *format)
memset(data, 0, sizeof (__u8) * WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN);
- ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID,
- false, NVME_NO_LOG_LSP, WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN, data);
+ ret = nvme_get_log_simple(fd, WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID,
+ WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN, data);
if (strcmp(format, "json"))
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
if (ret == 0) {
/* parse the data */
@@ -5955,14 +6765,15 @@ static int wdc_get_fw_act_history_C2(int fd, char *format)
if (tot_entries > 0) {
/* get the FW customer id */
- if (!get_dev_mgment_cbs_data(fd, WDC_C2_CUSTOMER_ID_ID, (void*)&cust_id)) {
- fprintf(stderr, "%s: ERROR : WDC : 0xC2 Log Page entry ID 0x%x not found\n", __func__, WDC_C2_CUSTOMER_ID_ID);
+ cust_id = wdc_get_fw_cust_id(r, fd);
+ if (cust_id == WDC_INVALID_CUSTOMER_ID) {
+ fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__);
ret = -1;
goto freeData;
}
num_entries = (tot_entries < WDC_MAX_NUM_ACT_HIST_ENTRIES) ? tot_entries :
WDC_MAX_NUM_ACT_HIST_ENTRIES;
- ret = wdc_print_fw_act_history_log(data, num_entries, fmt, *cust_id, vendor_id);
+ ret = wdc_print_fw_act_history_log(data, num_entries, fmt, cust_id, vendor_id);
} else {
fprintf(stderr, "INFO : WDC : No FW Activate History entries found.\n");
ret = 0;
@@ -5982,6 +6793,7 @@ static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *com
{
int fd;
int ret = 0;
+ nvme_root_t r;
__u64 capabilities = 0;
const char *desc = "Retrieve FW activate history table.";
@@ -6004,7 +6816,8 @@ static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *com
if (fd < 0)
return fd;
- capabilities = wdc_get_drive_capabilities(fd);
+ r = nvme_scan(NULL);
+ capabilities = wdc_get_drive_capabilities(r, fd);
if ((capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_MASK) == 0) {
fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
ret = -1;
@@ -6025,8 +6838,24 @@ static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *com
}
/* Get the 0xC0 log data */
- ret = nvme_get_log14(fd, 0xFFFFFFFF, WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_OPCODE,
- NVME_NO_LOG_LSP, 0, 0, false, uuid_index, 0, false, WDC_NVME_SMART_CLOUD_ATTR_LEN, data);
+ struct nvme_get_log_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .lid = WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_OPCODE,
+ .nsid = 0xFFFFFFFF,
+ .lpo = 0,
+ .lsp = NVME_LOG_LSP_NONE,
+ .lsi = 0,
+ .rae = false,
+ .uuidx = uuid_index,
+ .csi = NVME_CSI_NVM,
+ .ot = false,
+ .len = WDC_NVME_SMART_CLOUD_ATTR_LEN,
+ .log = data,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ ret = nvme_get_log(&args);
if (ret == 0) {
/* Verify GUID matches */
@@ -6043,19 +6872,21 @@ static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *com
}
free(data);
- if (c0GuidMatch) {
- ret = wdc_get_fw_act_history_C2(fd, cfg.output_format);
- }
- else {
- ret = wdc_get_fw_act_history(fd, cfg.output_format);
- }
+ if (c0GuidMatch) {
+ ret = wdc_get_fw_act_history_C2(r, fd,
+ cfg.output_format);
+ }
+ else {
+ ret = wdc_get_fw_act_history(r, fd, cfg.output_format);
+ }
} else {
- ret = wdc_get_fw_act_history_C2(fd, cfg.output_format);
+ ret = wdc_get_fw_act_history_C2(r, fd, cfg.output_format);
}
if (ret)
fprintf(stderr, "ERROR : WDC : Failure reading the FW Activate History, ret = %d\n", ret);
out:
+ nvme_free_tree(r);
return ret;
}
@@ -6069,8 +6900,8 @@ static int wdc_do_clear_fw_activate_history_vuc(int fd)
admin_cmd.cdw12 = ((WDC_NVME_CLEAR_FW_ACT_HIST_SUBCMD << WDC_NVME_SUBCMD_SHIFT) |
WDC_NVME_CLEAR_FW_ACT_HIST_CMD);
- ret = nvme_submit_admin_passthru(fd, &admin_cmd);
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL);
+ nvme_show_status(ret);
return ret;
}
@@ -6081,10 +6912,10 @@ static int wdc_do_clear_fw_activate_history_fid(int fd)
__u32 result;
__u32 value = 1 << 31; /* Bit 31 - Clear Firmware Update History Log */
- ret = nvme_set_feature(fd, 0, WDC_NVME_CLEAR_FW_ACT_HIST_VU_FID, value,
- 0, 0, 0, 0, NULL, &result);
+ ret = nvme_set_features_simple(fd, WDC_NVME_CLEAR_FW_ACT_HIST_VU_FID, 0, value,
+ false, &result);
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
return ret;
}
@@ -6094,6 +6925,7 @@ static int wdc_clear_fw_activate_history(int argc, char **argv, struct command *
char *desc = "Clear FW activate history table.";
int fd;
int ret = -1;
+ nvme_root_t r;
__u64 capabilities = 0;
OPT_ARGS(opts) = {
@@ -6104,7 +6936,8 @@ static int wdc_clear_fw_activate_history(int argc, char **argv, struct command *
if (fd < 0)
return fd;
- capabilities = wdc_get_drive_capabilities(fd);
+ r = nvme_scan(NULL);
+ capabilities = wdc_get_drive_capabilities(r, fd);
if ((capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY_MASK) == 0) {
fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
ret = -1;
@@ -6119,6 +6952,7 @@ static int wdc_clear_fw_activate_history(int argc, char **argv, struct command *
}
out:
+ nvme_free_tree(r);
return ret;
}
@@ -6131,21 +6965,21 @@ static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct comm
char *status = "Displays the current state of the controller initiated log page.";
int fd;
int ret = -1;
+ nvme_root_t r;
__u64 capabilities = 0;
__u32 result;
- void *buf = NULL;
struct config {
- int disable;
- int enable;
- int status;
+ bool disable;
+ bool enable;
+ bool status;
};
struct config cfg = {
- .disable = 0,
- .enable = 0,
- .status = 0,
+ .disable = false,
+ .enable = false,
+ .status = false,
};
OPT_ARGS(opts) = {
@@ -6159,7 +6993,8 @@ static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct comm
if (fd < 0)
return fd;
- capabilities = wdc_get_drive_capabilities(fd);
+ r = nvme_scan(NULL);
+ capabilities = wdc_get_drive_capabilities(r, fd);
if ((capabilities & WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG) != WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG) {
fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
ret = -1;
@@ -6175,26 +7010,26 @@ static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct comm
}
if (cfg.disable) {
- ret = nvme_set_feature(fd, 0, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 1,
- 0, 0, 0, 0, buf, &result);
+ ret = nvme_set_features_simple(fd, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0, 1,
+ false, &result);
wdc_clear_reason_id(fd);
}
else {
if (cfg.enable) {
- ret = nvme_set_feature(fd, 0, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0,
- 0, 0, 0, 0, buf, &result);
+ ret = nvme_set_features_simple(fd, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0, 0,
+ false, &result);
}
else if (cfg.status) {
- ret = nvme_get_feature(fd, 0, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0, 0,
- 0, 4, buf, &result);
+ ret = nvme_get_features_simple(fd, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0,
+ &result);
if (ret == 0) {
if (result)
fprintf(stderr, "Controller Option Telemetry Log Page State: Disabled\n");
else
fprintf(stderr, "Controller Option Telemetry Log Page State: Enabled\n");
} else {
- fprintf(stderr, "ERROR : WDC: NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
}
}
else {
@@ -6207,6 +7042,7 @@ static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct comm
}
out:
+ nvme_free_tree(r);
return ret;
}
@@ -6261,7 +7097,7 @@ static int wdc_get_max_transfer_len(int fd, __u32 *maxTransferLen)
static int wdc_de_VU_read_size(int fd, __u32 fileId, __u16 spiDestn, __u32* logSize)
{
int ret = WDC_STATUS_FAILURE;
- struct nvme_admin_cmd cmd;
+ struct nvme_passthru_cmd cmd;
if(!fd || !logSize )
{
@@ -6269,18 +7105,20 @@ static int wdc_de_VU_read_size(int fd, __u32 fileId, __u16 spiDestn, __u32* logS
goto end;
}
- memset(&cmd,0,sizeof(struct nvme_admin_cmd));
+ memset(&cmd,0,sizeof(struct nvme_passthru_cmd));
cmd.opcode = WDC_DE_VU_READ_SIZE_OPCODE;
cmd.nsid = WDC_DE_DEFAULT_NAMESPACE_ID;
cmd.cdw13 = fileId<<16;
cmd.cdw14 = spiDestn;
- ret = nvme_submit_admin_passthru(fd, &cmd);
+ ret = nvme_submit_admin_passthru(fd, &cmd, NULL);
if (!ret && logSize)
*logSize = cmd.result;
- if( ret != WDC_STATUS_SUCCESS)
- fprintf(stderr, "ERROR : WDC : VUReadSize() failed, status:%s(0x%x)\n", nvme_status_to_string(ret), ret);
+ if( ret != WDC_STATUS_SUCCESS) {
+ fprintf(stderr, "ERROR : WDC : VUReadSize() failed, ");
+ nvme_show_status(ret);
+ }
end:
return ret;
@@ -6289,7 +7127,7 @@ static int wdc_de_VU_read_size(int fd, __u32 fileId, __u16 spiDestn, __u32* logS
static int wdc_de_VU_read_buffer(int fd, __u32 fileId, __u16 spiDestn, __u32 offsetInDwords, __u8* dataBuffer, __u32* bufferSize)
{
int ret = WDC_STATUS_FAILURE;
- struct nvme_admin_cmd cmd;
+ struct nvme_passthru_cmd cmd;
__u32 noOfDwordExpected = 0;
if(!fd || !dataBuffer || !bufferSize)
@@ -6298,7 +7136,7 @@ static int wdc_de_VU_read_buffer(int fd, __u32 fileId, __u16 spiDestn, __u32 off
goto end;
}
- memset(&cmd,0,sizeof(struct nvme_admin_cmd));
+ memset(&cmd,0,sizeof(struct nvme_passthru_cmd));
noOfDwordExpected = *bufferSize/sizeof(__u32);
cmd.opcode = WDC_DE_VU_READ_BUFFER_OPCODE;
cmd.nsid = WDC_DE_DEFAULT_NAMESPACE_ID;
@@ -6310,10 +7148,12 @@ static int wdc_de_VU_read_buffer(int fd, __u32 fileId, __u16 spiDestn, __u32 off
cmd.addr = (__u64)(__u64)(uintptr_t)dataBuffer;
cmd.data_len = *bufferSize;
- ret = nvme_submit_admin_passthru(fd, &cmd);
+ ret = nvme_submit_admin_passthru(fd, &cmd, NULL);
- if( ret != WDC_STATUS_SUCCESS)
- fprintf(stderr, "ERROR : WDC : VUReadBuffer() failed, status:%s(0x%x)\n", nvme_status_to_string(ret), ret);
+ if( ret != WDC_STATUS_SUCCESS) {
+ fprintf(stderr, "ERROR : WDC : VUReadBuffer() failed, ");
+ nvme_show_status(ret);
+ }
end:
return ret;
@@ -6620,7 +7460,7 @@ static int wdc_de_get_dump_trace(int fd, char * filePath, __u16 binFileNameLen,
return ret;
}
-static int wdc_do_drive_essentials(int fd, char *dir, char *key)
+static int wdc_do_drive_essentials(nvme_root_t r, int fd, char *dir, char *key)
{
int ret = 0;
void *retPtr;
@@ -6649,7 +7489,7 @@ static int wdc_do_drive_essentials(int fd, char *dir, char *key)
struct nvme_id_ns ns;
struct nvme_error_log_page *elogBuffer;
struct nvme_smart_log smart_log;
- struct nvme_firmware_log_page fw_log;
+ struct nvme_firmware_slot fw_log;
PWDC_NVME_DE_VU_LOGPAGES vuLogInput = NULL;
WDC_DE_VU_LOG_DIRECTORY deEssentialsList;
@@ -6725,7 +7565,7 @@ static int wdc_do_drive_essentials(int fd, char *dir, char *key)
}
memset(&ns, 0, sizeof (struct nvme_id_ns));
- ret = nvme_identify_ns(fd, 1, 0, &ns);
+ ret = nvme_identify_ns(fd, 1, &ns);
if (ret) {
fprintf(stderr, "ERROR : WDC : nvme_identify_ns() failed, ret = %d\n", ret);
} else {
@@ -6740,7 +7580,7 @@ static int wdc_do_drive_essentials(int fd, char *dir, char *key)
dataBuffer = calloc(1, elogBufferSize);
elogBuffer = (struct nvme_error_log_page *)dataBuffer;
- ret = nvme_error_log(fd, elogNumEntries, elogBuffer);
+ ret = nvme_get_log_error(fd, elogNumEntries, false, elogBuffer);
if (ret) {
fprintf(stderr, "ERROR : WDC : nvme_error_log() failed, ret = %d\n", ret);
} else {
@@ -6754,7 +7594,7 @@ static int wdc_do_drive_essentials(int fd, char *dir, char *key)
/* Get Smart log page */
memset(&smart_log, 0, sizeof (struct nvme_smart_log));
- ret = nvme_smart_log(fd, NVME_NSID_ALL, &smart_log);
+ ret = nvme_get_log_smart(fd, NVME_NSID_ALL, false, &smart_log);
if (ret) {
fprintf(stderr, "ERROR : WDC : nvme_smart_log() failed, ret = %d\n", ret);
} else {
@@ -6764,14 +7604,14 @@ static int wdc_do_drive_essentials(int fd, char *dir, char *key)
}
/* Get FW Slot log page */
- memset(&fw_log, 0, sizeof (struct nvme_firmware_log_page));
- ret = nvme_fw_log(fd, &fw_log);
+ memset(&fw_log, 0, sizeof (struct nvme_firmware_slot));
+ ret = nvme_get_log_fw_slot(fd, true, &fw_log);
if (ret) {
fprintf(stderr, "ERROR : WDC : nvme_fw_log() failed, ret = %d\n", ret);
} else {
wdc_UtilsSnprintf(fileName, MAX_PATH_LEN, "%s%s%s_%s_%s.bin", (char*)bufferFolderPath, WDC_DE_PATH_SEPARATOR,
"FwSLotLog", (char*)serialNo, (char*)timeString);
- wdc_WriteToFile(fileName, (char*)&fw_log, sizeof(struct nvme_firmware_log_page));
+ wdc_WriteToFile(fileName, (char*)&fw_log, sizeof(struct nvme_firmware_slot));
}
/* Get VU log pages */
@@ -6785,8 +7625,8 @@ static int wdc_do_drive_essentials(int fd, char *dir, char *key)
dataBuffer = calloc(1, dataBufferSize);
memset(dataBuffer, 0, dataBufferSize);
- ret = nvme_get_log(fd, WDC_DE_GLOBAL_NSID, deVULogPagesList[vuLogIdx].logPageId,
- false, NVME_NO_LOG_LSP, dataBufferSize, dataBuffer);
+ ret = nvme_get_log_simple(fd, deVULogPagesList[vuLogIdx].logPageId,
+ dataBufferSize, dataBuffer);
if (ret) {
fprintf(stderr, "ERROR : WDC : nvme_get_log() for log page 0x%x failed, ret = %d\n",
deVULogPagesList[vuLogIdx].logPageId, ret);
@@ -6810,8 +7650,8 @@ static int wdc_do_drive_essentials(int fd, char *dir, char *key)
/* skipping LbaRangeType as it is an optional nvme command and not supported */
if (deFeatureIdList[listIdx].featureId == FID_LBA_RANGE_TYPE)
continue;
- ret = nvme_get_feature(fd, WDC_DE_GLOBAL_NSID, deFeatureIdList[listIdx].featureId, FS_CURRENT, 0,
- 0, sizeof(featureIdBuff), &featureIdBuff, &result);
+ ret = nvme_get_features_data(fd, deFeatureIdList[listIdx].featureId, WDC_DE_GLOBAL_NSID,
+ sizeof(featureIdBuff), &featureIdBuff, &result);
if (ret) {
fprintf(stderr, "ERROR : WDC : nvme_get_feature id 0x%x failed, ret = %d\n",
@@ -6905,6 +7745,7 @@ static int wdc_do_drive_essentials(int fd, char *dir, char *key)
}
fprintf(stderr, "Get of Drive Essentials data successful\n");
+ nvme_free_tree(r);
return 0;
}
@@ -6917,6 +7758,7 @@ static int wdc_drive_essentials(int argc, char **argv, struct command *command,
char k[PATH_MAX] = {0};
char *d_ptr;
int fd;
+ nvme_root_t r;
__u64 capabilities = 0;
struct config {
@@ -6937,9 +7779,11 @@ static int wdc_drive_essentials(int argc, char **argv, struct command *command,
if (fd < 0)
return fd;
- capabilities = wdc_get_drive_capabilities(fd);
+ r = nvme_scan(NULL);
+ capabilities = wdc_get_drive_capabilities(r, fd);
if ((capabilities & WDC_DRIVE_CAP_DRIVE_ESSENTIALS) != WDC_DRIVE_CAP_DRIVE_ESSENTIALS) {
fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
+ nvme_free_tree(r);
return -1;
}
@@ -6950,49 +7794,49 @@ static int wdc_drive_essentials(int argc, char **argv, struct command *command,
d_ptr = NULL;
}
- return wdc_do_drive_essentials(fd, d_ptr, k);
+ return wdc_do_drive_essentials(r, fd, d_ptr, k);
}
static int wdc_do_drive_resize(int fd, uint64_t new_size)
{
int ret;
- struct nvme_admin_cmd admin_cmd;
+ struct nvme_passthru_cmd admin_cmd;
- memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd));
+ memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd));
admin_cmd.opcode = WDC_NVME_DRIVE_RESIZE_OPCODE;
admin_cmd.cdw12 = ((WDC_NVME_DRIVE_RESIZE_SUBCMD << WDC_NVME_SUBCMD_SHIFT) |
WDC_NVME_DRIVE_RESIZE_CMD);
admin_cmd.cdw13 = new_size;
- ret = nvme_submit_admin_passthru(fd, &admin_cmd);
+ ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL);
return ret;
}
static int wdc_do_namespace_resize(int fd, __u32 nsid, __u32 op_option)
{
int ret;
- struct nvme_admin_cmd admin_cmd;
+ struct nvme_passthru_cmd admin_cmd;
- memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd));
+ memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd));
admin_cmd.opcode = WDC_NVME_NAMESPACE_RESIZE_OPCODE;
admin_cmd.nsid = nsid;
admin_cmd.cdw10 = op_option;
- ret = nvme_submit_admin_passthru(fd, &admin_cmd);
+ ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL);
return ret;
}
static int wdc_do_drive_info(int fd, __u32 *result)
{
int ret;
- struct nvme_admin_cmd admin_cmd;
+ struct nvme_passthru_cmd admin_cmd;
- memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd));
+ memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd));
admin_cmd.opcode = WDC_NVME_DRIVE_INFO_OPCODE;
admin_cmd.cdw12 = ((WDC_NVME_DRIVE_INFO_SUBCMD << WDC_NVME_SUBCMD_SHIFT) |
WDC_NVME_DRIVE_INFO_CMD);
- ret = nvme_submit_admin_passthru(fd, &admin_cmd);
+ ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL);
if (!ret && result)
*result = admin_cmd.result;
@@ -7005,6 +7849,7 @@ static int wdc_drive_resize(int argc, char **argv,
{
const char *desc = "Send a Resize command.";
const char *size = "The new size (in GB) to resize the drive to.";
+ nvme_root_t r;
uint64_t capabilities = 0;
int fd, ret;
@@ -7025,8 +7870,9 @@ static int wdc_drive_resize(int argc, char **argv,
if (fd < 0)
return fd;
- wdc_check_device(fd);
- capabilities = wdc_get_drive_capabilities(fd);
+ r = nvme_scan(NULL);
+ wdc_check_device(r, fd);
+ capabilities = wdc_get_drive_capabilities(r, fd);
if ((capabilities & WDC_DRIVE_CAP_RESIZE) == WDC_DRIVE_CAP_RESIZE) {
ret = wdc_do_drive_resize(fd, cfg.size);
} else {
@@ -7037,7 +7883,8 @@ static int wdc_drive_resize(int argc, char **argv,
if (!ret)
printf("New size: %" PRIu64 " GB\n", cfg.size);
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
+ nvme_free_tree(r);
return ret;
}
@@ -7047,6 +7894,7 @@ static int wdc_namespace_resize(int argc, char **argv,
const char *desc = "Send a Namespace Resize command.";
const char *namespace_id = "The namespace id to resize.";
const char *op_option = "The over provisioning option to set for namespace.";
+ nvme_root_t r;
uint64_t capabilities = 0;
int fd, ret;
@@ -7079,8 +7927,9 @@ static int wdc_namespace_resize(int argc, char **argv,
return -1;
}
- wdc_check_device(fd);
- capabilities = wdc_get_drive_capabilities(fd);
+ r = nvme_scan(NULL);
+ wdc_check_device(r, fd);
+ capabilities = wdc_get_drive_capabilities(r, fd);
if ((capabilities & WDC_DRIVE_CAP_NS_RESIZE) == WDC_DRIVE_CAP_NS_RESIZE) {
ret = wdc_do_namespace_resize(fd, cfg.namespace_id, cfg.op_option);
@@ -7091,7 +7940,8 @@ static int wdc_namespace_resize(int argc, char **argv,
ret = -1;
}
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
+ nvme_free_tree(r);
return ret;
}
@@ -7101,6 +7951,7 @@ static int wdc_reason_identifier(int argc, char **argv,
const char *desc = "Retrieve telemetry log reason identifier.";
const char *log_id = "Log ID to retrieve - host - 7 or controller - 8";
const char *fname = "File name to save raw binary identifier";
+ nvme_root_t r;
int fd;
int ret;
uint64_t capabilities = 0;
@@ -7130,7 +7981,9 @@ static int wdc_reason_identifier(int argc, char **argv,
if (fd < 0)
return fd;
- if (cfg.log_id != NVME_LOG_TELEMETRY_HOST && cfg.log_id != NVME_LOG_TELEMETRY_CTRL) {
+ r = nvme_scan(NULL);
+
+ if (cfg.log_id != NVME_LOG_LID_TELEMETRY_HOST&& cfg.log_id != NVME_LOG_LID_TELEMETRY_CTRL) {
fprintf(stderr, "ERROR : WDC: Invalid Log ID. It must be 7 (Host) or 8 (Controller)\n");
ret = -1;
goto close_fd;
@@ -7154,7 +8007,7 @@ static int wdc_reason_identifier(int argc, char **argv,
wdc_UtilsSnprintf((char*)timeStamp, MAX_PATH_LEN, "%02u%02u%02u_%02u%02u%02u",
timeInfo.year, timeInfo.month, timeInfo.dayOfMonth,
timeInfo.hour, timeInfo.minute, timeInfo.second);
- if (cfg.log_id == NVME_LOG_TELEMETRY_CTRL)
+ if (cfg.log_id == NVME_LOG_LID_TELEMETRY_CTRL)
snprintf(fileSuffix, PATH_MAX, "_error_reason_identifier_ctlr_%s", (char*)timeStamp);
else
snprintf(fileSuffix, PATH_MAX, "_error_reason_identifier_host_%s", (char*)timeStamp);
@@ -7170,7 +8023,7 @@ static int wdc_reason_identifier(int argc, char **argv,
fprintf(stderr, "%s: filename = %s\n", __func__, f);
- capabilities = wdc_get_drive_capabilities(fd);
+ capabilities = wdc_get_drive_capabilities(r, fd);
if ((capabilities & WDC_DRIVE_CAP_REASON_ID) == WDC_DRIVE_CAP_REASON_ID) {
ret = wdc_do_get_reason_id(fd, f, cfg.log_id);
} else {
@@ -7178,50 +8031,51 @@ static int wdc_reason_identifier(int argc, char **argv,
ret = -1;
}
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
close_fd:
- close(fd);
- return ret;
+ close(fd);
+ nvme_free_tree(r);
+ return ret;
}
static const char *nvme_log_id_to_string(__u8 log_id)
{
switch (log_id) {
- case NVME_LOG_ERROR: return "Error Information Log ID";
- case NVME_LOG_SMART: return "Smart/Health Information Log ID";
- case NVME_LOG_FW_SLOT: return "Firmware Slot Information Log ID";
- case NVME_LOG_CHANGED_NS: return "Namespace Changed Log ID";
- case NVME_LOG_CMD_EFFECTS: return "Commamds Supported and Effects Log ID";
- case NVME_LOG_DEVICE_SELF_TEST: return "Device Self Test Log ID";
- case NVME_LOG_TELEMETRY_HOST: return "Telemetry Host Initiated Log ID";
- case NVME_LOG_TELEMETRY_CTRL: return "Telemetry Controller Generated Log ID";
- case NVME_LOG_ENDURANCE_GROUP: return "Endurance Group Log ID";
- case NVME_LOG_ANA: return "ANA Log ID";
- case NVME_LOG_PERSISTENT_EVENT: return "Persistent Event Log ID";
- case NVME_LOG_DISC: return "Discovery Log ID";
- case NVME_LOG_RESERVATION: return "Reservation Notification Log ID";
- case NVME_LOG_SANITIZE: return "Sanitize Status Log ID";
-
- case WDC_LOG_ID_C0: return "WDC Vendor Unique Log ID";
- case WDC_LOG_ID_C1: return "WDC Vendor Unique Log ID";
- case WDC_LOG_ID_C2: return "WDC Vendor Unique Log ID";
- case WDC_LOG_ID_C4: return "WDC Vendor Unique Log ID";
- case WDC_LOG_ID_C5: return "WDC Vendor Unique Log ID";
- case WDC_LOG_ID_C6: return "WDC Vendor Unique Log ID";
- case WDC_LOG_ID_C8: return "WDC Vendor Unique Log ID";
- case WDC_LOG_ID_CA: return "WDC Vendor Unique Log ID";
- case WDC_LOG_ID_CB: return "WDC Vendor Unique Log ID";
- case WDC_LOG_ID_D0: return "WDC Vendor Unique Log ID";
- case WDC_LOG_ID_D1: return "WDC Vendor Unique Log ID";
- case WDC_LOG_ID_D6: return "WDC Vendor Unique Log ID";
- case WDC_LOG_ID_D7: return "WDC Vendor Unique Log ID";
- case WDC_LOG_ID_D8: return "WDC Vendor Unique Log ID";
- case WDC_LOG_ID_DE: return "WDC Vendor Unique Log ID";
- case WDC_LOG_ID_F0: return "WDC Vendor Unique Log ID";
- case WDC_LOG_ID_F1: return "WDC Vendor Unique Log ID";
- case WDC_LOG_ID_F2: return "WDC Vendor Unique Log ID";
- case WDC_LOG_ID_FA: return "WDC Vendor Unique Log ID";
+ case NVME_LOG_LID_ERROR: return "Error Information Log ID";
+ case NVME_LOG_LID_SMART: return "Smart/Health Information Log ID";
+ case NVME_LOG_LID_FW_SLOT: return "Firmware Slot Information Log ID";
+ case NVME_LOG_LID_CHANGED_NS: return "Namespace Changed Log ID";
+ case NVME_LOG_LID_CMD_EFFECTS: return "Commamds Supported and Effects Log ID";
+ case NVME_LOG_LID_DEVICE_SELF_TEST: return "Device Self Test Log ID";
+ case NVME_LOG_LID_TELEMETRY_HOST: return "Telemetry Host Initiated Log ID";
+ case NVME_LOG_LID_TELEMETRY_CTRL: return "Telemetry Controller Generated Log ID";
+ case NVME_LOG_LID_ENDURANCE_GROUP: return "Endurance Group Log ID";
+ case NVME_LOG_LID_ANA: return "ANA Log ID";
+ case NVME_LOG_LID_PERSISTENT_EVENT: return "Persistent Event Log ID";
+ case NVME_LOG_LID_DISCOVER: return "Discovery Log ID";
+ case NVME_LOG_LID_RESERVATION: return "Reservation Notification Log ID";
+ case NVME_LOG_LID_SANITIZE: return "Sanitize Status Log ID";
+
+ case WDC_LOG_ID_C0: return "WDC Vendor Unique Log ID C0";
+ case WDC_LOG_ID_C1: return "WDC Vendor Unique Log ID C1";
+ case WDC_LOG_ID_C2: return "WDC Vendor Unique Log ID C2";
+ case WDC_LOG_ID_C4: return "WDC Vendor Unique Log ID C4";
+ case WDC_LOG_ID_C5: return "WDC Vendor Unique Log ID C5";
+ case WDC_LOG_ID_C6: return "WDC Vendor Unique Log ID C6";
+ case WDC_LOG_ID_C8: return "WDC Vendor Unique Log ID C8";
+ case WDC_LOG_ID_CA: return "WDC Vendor Unique Log ID CA";
+ case WDC_LOG_ID_CB: return "WDC Vendor Unique Log ID CB";
+ case WDC_LOG_ID_D0: return "WDC Vendor Unique Log ID D0";
+ case WDC_LOG_ID_D1: return "WDC Vendor Unique Log ID D1";
+ case WDC_LOG_ID_D6: return "WDC Vendor Unique Log ID D6";
+ case WDC_LOG_ID_D7: return "WDC Vendor Unique Log ID D7";
+ case WDC_LOG_ID_D8: return "WDC Vendor Unique Log ID D8";
+ case WDC_LOG_ID_DE: return "WDC Vendor Unique Log ID DE";
+ case WDC_LOG_ID_F0: return "WDC Vendor Unique Log ID F0";
+ case WDC_LOG_ID_F1: return "WDC Vendor Unique Log ID F1";
+ case WDC_LOG_ID_F2: return "WDC Vendor Unique Log ID F2";
+ case WDC_LOG_ID_FA: return "WDC Vendor Unique Log ID FA";
default: return "Unknown Log ID";
}
@@ -7233,9 +8087,10 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command
const char *desc = "Retrieve Log Page Directory.";
int fd;
int ret = 0;
+ nvme_root_t r;
__u64 capabilities = 0;
struct wdc_c2_cbs_data *cbs_data = NULL;
- int i;
+ int i;
__u8 log_id = 0;
__u32 device_id, read_vendor_id;
@@ -7261,25 +8116,26 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command
fprintf(stderr, "%s: ERROR : WDC : invalid output format\n", __func__);
return ret;
}
+ ret = 0;
- capabilities = wdc_get_drive_capabilities(fd);
+ r = nvme_scan(NULL);
+ capabilities = wdc_get_drive_capabilities(r, fd);
if ((capabilities & WDC_DRIVE_CAP_LOG_PAGE_DIR) == 0) {
fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
ret = -1;
- }
- else {
- ret = wdc_get_pci_ids(&device_id, &read_vendor_id);
+ } else {
+ ret = wdc_get_pci_ids(r, &device_id, &read_vendor_id);
log_id = (device_id == WDC_NVME_ZN350_DEV_ID || device_id == WDC_NVME_ZN350_DEV_ID_1) ?
WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE_C8 : WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE;
/* verify the 0xC2 Device Manageability log page is supported */
- if (wdc_nvme_check_supported_log_page(fd, log_id) == false) {
+ if (wdc_nvme_check_supported_log_page(r, fd, log_id) == false) {
fprintf(stderr, "%s: ERROR : WDC : 0x%x Log Page not supported\n", __func__, log_id);
ret = -1;
goto out;
}
- if (get_dev_mgment_cbs_data(fd, WDC_C2_LOG_PAGES_SUPPORTED_ID, (void *)&cbs_data)) {
+ if (get_dev_mgment_cbs_data(r, fd, WDC_C2_LOG_PAGES_SUPPORTED_ID, (void *)&cbs_data)) {
if (cbs_data != NULL) {
printf("Log Page Directory\n");
/* print the supported pages */
@@ -7304,6 +8160,8 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command
json_free_object(root);
} else
fprintf(stderr, "%s: ERROR : WDC : Invalid format, format = %s\n", __func__, cfg.output_format);
+
+ free(cbs_data);
} else
fprintf(stderr, "%s: ERROR : WDC : NULL_data ptr\n", __func__);
} else
@@ -7313,6 +8171,7 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command
}
out:
+ nvme_free_tree(r);
return ret;
}
@@ -7419,14 +8278,33 @@ static int wdc_clear_reason_id(int fd)
return ret;
}
+static int wdc_dump_telemetry_hdr(int fd, int log_id, struct nvme_telemetry_log *log_hdr)
+{
+ int ret = 0;
+
+ if (log_id == NVME_LOG_LID_TELEMETRY_HOST)
+ ret = nvme_get_log_create_telemetry_host(fd, log_hdr);
+ else
+ ret = nvme_get_log_telemetry_ctrl(fd, false, 0, 512, (void *)log_hdr);
+
+ if (ret < 0)
+ perror("get-telemetry-log");
+ else if (ret > 0) {
+ nvme_show_status(ret);
+ fprintf(stderr, "%s: ERROR : Failed to acquire telemetry header, ret = %d!\n", __func__, ret);
+ }
+
+ return ret;
+}
+
static int wdc_do_get_reason_id(int fd, char *file, int log_id)
{
int ret;
- struct nvme_telemetry_log_page_hdr *log_hdr;
- __u32 log_hdr_size = sizeof(struct nvme_telemetry_log_page_hdr);
+ struct nvme_telemetry_log *log_hdr;
+ __u32 log_hdr_size = sizeof(struct nvme_telemetry_log);
__u32 reason_id_size = 0;
- log_hdr = (struct nvme_telemetry_log_page_hdr *) malloc(log_hdr_size);
+ log_hdr = (struct nvme_telemetry_log *) malloc(log_hdr_size);
if (log_hdr == NULL) {
fprintf(stderr, "%s: ERROR : malloc failed, size : 0x%x, status : %s\n", __func__, log_hdr_size, strerror(errno));
ret = -1;
@@ -7443,7 +8321,7 @@ static int wdc_do_get_reason_id(int fd, char *file, int log_id)
reason_id_size = sizeof(log_hdr->rsnident);
- if (log_id == NVME_LOG_TELEMETRY_CTRL)
+ if (log_id == NVME_LOG_LID_TELEMETRY_CTRL)
wdc_save_reason_id(fd, log_hdr->rsnident, reason_id_size);
ret = wdc_create_log_file(file, (__u8 *)log_hdr->rsnident, reason_id_size);
@@ -7453,27 +8331,6 @@ out:
return ret;
}
-static int wdc_dump_telemetry_hdr(int fd, int log_id, struct nvme_telemetry_log_page_hdr *log_hdr)
-{
- int ret = 0;
- int host_gen = 0, ctrl_init = 0;
-
- if (log_id == NVME_LOG_TELEMETRY_HOST)
- host_gen = 1;
- else
- ctrl_init = 1;
-
- ret = nvme_get_telemetry_log(fd, log_hdr, host_gen, ctrl_init, 512, 0);
- if (ret < 0)
- perror("get-telemetry-log");
- else if (ret > 0) {
- nvme_show_status(ret);
- fprintf(stderr, "%s: ERROR : Failed to acquire telemetry header, ret = %d!\n", __func__, ret);
- }
-
- return ret;
-}
-
static void wdc_print_nand_stats_normal(__u16 version, void *data)
{
struct wdc_nand_stats *nand_stats = (struct wdc_nand_stats *)(data);
@@ -7625,11 +8482,11 @@ static void wdc_print_nand_stats_json(__u16 version, void *data)
le32_to_cpu(nand_stats->nand_erase_failure));
json_object_add_value_uint(root, "Bad Block Count",
le32_to_cpu(nand_stats->bad_block_count));
- json_object_add_value_uint(root, "NAND XOR/RAID Recovery Trigger Events",
+ json_object_add_value_uint64(root, "NAND XOR/RAID Recovery Trigger Events",
le64_to_cpu(nand_stats->nand_rec_trigger_event));
- json_object_add_value_uint(root, "E2E Error Counter",
+ json_object_add_value_uint64(root, "E2E Error Counter",
le64_to_cpu(nand_stats->e2e_error_counter));
- json_object_add_value_uint(root, "Number Successful NS Resizing Events",
+ json_object_add_value_uint64(root, "Number Successful NS Resizing Events",
le64_to_cpu(nand_stats->successful_ns_resize_event));
json_print_object(root, NULL);
@@ -7647,13 +8504,13 @@ static void wdc_print_nand_stats_json(__u16 version, void *data)
temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
json_object_add_value_uint(root, "Bad NAND Blocks Count - Normalized",
le16_to_cpu(temp_norm));
- json_object_add_value_uint(root, "Bad NAND Blocks Count - Raw",
+ json_object_add_value_uint64(root, "Bad NAND Blocks Count - Raw",
le64_to_cpu(temp_raw));
- json_object_add_value_uint(root, "NAND XOR Recovery count",
+ json_object_add_value_uint64(root, "NAND XOR Recovery count",
le64_to_cpu(nand_stats_v3->xor_recovery_count));
- json_object_add_value_uint(root, "UECC Read Error count",
+ json_object_add_value_uint64(root, "UECC Read Error count",
le64_to_cpu(nand_stats_v3->uecc_read_error_count));
- json_object_add_value_uint(root, "SSD End to End corrected errors",
+ json_object_add_value_uint64(root, "SSD End to End corrected errors",
le64_to_cpu(nand_stats_v3->ssd_correction_counts[0]));
json_object_add_value_uint(root, "SSD End to End detected errors",
le32_to_cpu(nand_stats_v3->ssd_correction_counts[8]));
@@ -7661,54 +8518,54 @@ static void wdc_print_nand_stats_json(__u16 version, void *data)
le32_to_cpu(nand_stats_v3->ssd_correction_counts[12]));
json_object_add_value_uint(root, "System data % life-used",
nand_stats_v3->percent_life_used);
- json_object_add_value_uint(root, "User Data Erase Counts - SLC Min",
+ json_object_add_value_uint64(root, "User Data Erase Counts - SLC Min",
le64_to_cpu(nand_stats_v3->user_data_erase_counts[0]));
- json_object_add_value_uint(root, "User Data Erase Counts - SLC Max",
+ json_object_add_value_uint64(root, "User Data Erase Counts - SLC Max",
le64_to_cpu(nand_stats_v3->user_data_erase_counts[1]));
- json_object_add_value_uint(root, "User Data Erase Counts - TLC Min",
+ json_object_add_value_uint64(root, "User Data Erase Counts - TLC Min",
le64_to_cpu(nand_stats_v3->user_data_erase_counts[2]));
- json_object_add_value_uint(root, "User Data Erase Counts - TLC Max",
+ json_object_add_value_uint64(root, "User Data Erase Counts - TLC Max",
le64_to_cpu(nand_stats_v3->user_data_erase_counts[3]));
temp_ptr = (__u64 *)nand_stats_v3->program_fail_count;
temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
json_object_add_value_uint(root, "Program Fail Count - Normalized",
le16_to_cpu(temp_norm));
- json_object_add_value_uint(root, "Program Fail Count - Raw",
+ json_object_add_value_uint64(root, "Program Fail Count - Raw",
le64_to_cpu(temp_raw));
temp_ptr = (__u64 *)nand_stats_v3->erase_fail_count;
temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
json_object_add_value_uint(root, "Erase Fail Count - Normalized",
le16_to_cpu(temp_norm));
- json_object_add_value_uint(root, "Erase Fail Count - Raw",
+ json_object_add_value_uint64(root, "Erase Fail Count - Raw",
le64_to_cpu(temp_raw));
json_object_add_value_uint(root, "PCIe Correctable Error Count",
le16_to_cpu(nand_stats_v3->correctable_error_count));
json_object_add_value_uint(root, "% Free Blocks (User)",
nand_stats_v3->percent_free_blocks_user);
- json_object_add_value_uint(root, "Security Version Number",
+ json_object_add_value_uint64(root, "Security Version Number",
le64_to_cpu(nand_stats_v3->security_version_number));
json_object_add_value_uint(root, "% Free Blocks (System)",
nand_stats_v3->percent_free_blocks_system);
json_object_add_value_float(root, "Data Set Management Commands",
int128_to_double(nand_stats_v3->trim_completions));
- json_object_add_value_uint(root, "Estimate of Incomplete Trim Data",
+ json_object_add_value_uint64(root, "Estimate of Incomplete Trim Data",
le64_to_cpu(nand_stats_v3->trim_completions[16]));
json_object_add_value_uint(root, "%% of completed trim",
nand_stats_v3->trim_completions[24]);
json_object_add_value_uint(root, "Background Back-Pressure-Guage",
nand_stats_v3->back_pressure_guage);
- json_object_add_value_uint(root, "Soft ECC Error Count",
+ json_object_add_value_uint64(root, "Soft ECC Error Count",
le64_to_cpu(nand_stats_v3->soft_ecc_error_count));
- json_object_add_value_uint(root, "Refresh Count",
+ json_object_add_value_uint64(root, "Refresh Count",
le64_to_cpu(nand_stats_v3->refresh_count));
temp_ptr = (__u64 *)nand_stats_v3->bad_sys_nand_block_count;
temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16);
json_object_add_value_uint(root, "Bad System Nand Block Count - Normalized",
le16_to_cpu(temp_norm));
- json_object_add_value_uint(root, "Bad System Nand Block Count - Raw",
+ json_object_add_value_uint64(root, "Bad System Nand Block Count - Raw",
le64_to_cpu(temp_raw));
json_object_add_value_float(root, "Endurance Estimate",
int128_to_double(nand_stats_v3->endurance_estimate));
@@ -7716,7 +8573,7 @@ static void wdc_print_nand_stats_json(__u16 version, void *data)
nand_stats_v3->thermal_throttling_st_ct[0]);
json_object_add_value_uint(root, "Thermal Throttling Count",
nand_stats_v3->thermal_throttling_st_ct[1]);
- json_object_add_value_uint(root, "Unaligned I/O",
+ json_object_add_value_uint64(root, "Unaligned I/O",
le64_to_cpu(nand_stats_v3->unaligned_IO));
json_object_add_value_float(root, "Physical Media Units Read",
int128_to_double(nand_stats_v3->physical_media_units));
@@ -7780,38 +8637,38 @@ static void wdc_print_pcie_stats_json(struct wdc_vs_pcie_stats *pcie_stats)
struct json_object *root;
root = json_create_object();
- json_object_add_value_uint(root, "Unsupported Request Error Counter",
+ json_object_add_value_uint64(root, "Unsupported Request Error Counter",
le64_to_cpu(pcie_stats->unsupportedRequestErrorCount));
- json_object_add_value_uint(root, "ECRC Error Status Counter",
+ json_object_add_value_uint64(root, "ECRC Error Status Counter",
le64_to_cpu(pcie_stats->ecrcErrorStatusCount));
- json_object_add_value_uint(root, "Malformed TLP Status Counter",
+ json_object_add_value_uint64(root, "Malformed TLP Status Counter",
le64_to_cpu(pcie_stats->malformedTlpStatusCount));
- json_object_add_value_uint(root, "Receiver Overflow Status Counter",
+ json_object_add_value_uint64(root, "Receiver Overflow Status Counter",
le64_to_cpu(pcie_stats->receiverOverflowStatusCount));
- json_object_add_value_uint(root, "Unexpected Completion Status Counter",
+ json_object_add_value_uint64(root, "Unexpected Completion Status Counter",
le64_to_cpu(pcie_stats->unexpectedCmpltnStatusCount));
- json_object_add_value_uint(root, "Complete Abort Status Counter",
+ json_object_add_value_uint64(root, "Complete Abort Status Counter",
le64_to_cpu(pcie_stats->completeAbortStatusCount));
- json_object_add_value_uint(root, "Completion Timeout Status Counter",
+ json_object_add_value_uint64(root, "Completion Timeout Status Counter",
le64_to_cpu(pcie_stats->cmpltnTimoutStatusCount));
- json_object_add_value_uint(root, "Flow Control Error Status Counter",
+ json_object_add_value_uint64(root, "Flow Control Error Status Counter",
le64_to_cpu(pcie_stats->flowControlErrorStatusCount));
- json_object_add_value_uint(root, "Poisoned TLP Status Counter",
+ json_object_add_value_uint64(root, "Poisoned TLP Status Counter",
le64_to_cpu(pcie_stats->poisonedTlpStatusCount));
- json_object_add_value_uint(root, "Dlink Protocol Error Status Counter",
+ json_object_add_value_uint64(root, "Dlink Protocol Error Status Counter",
le64_to_cpu(pcie_stats->dLinkPrtclErrorStatusCount));
- json_object_add_value_uint(root, "Advisory Non Fatal Error Status Counter",
+ json_object_add_value_uint64(root, "Advisory Non Fatal Error Status Counter",
le64_to_cpu(pcie_stats->advsryNFatalErrStatusCount));
- json_object_add_value_uint(root, "Replay Timer TO Status Counter",
+ json_object_add_value_uint64(root, "Replay Timer TO Status Counter",
le64_to_cpu(pcie_stats->replayTimerToStatusCount));
- json_object_add_value_uint(root, "Replay Number Rollover Status Counter",
+ json_object_add_value_uint64(root, "Replay Number Rollover Status Counter",
le64_to_cpu(pcie_stats->replayNumRolloverStCount));
- json_object_add_value_uint(root, "Bad DLLP Status Counter",
+ json_object_add_value_uint64(root, "Bad DLLP Status Counter",
le64_to_cpu(pcie_stats->badDllpStatusCount));
- json_object_add_value_uint(root, "Bad TLP Status Counter",
+ json_object_add_value_uint64(root, "Bad TLP Status Counter",
le64_to_cpu(pcie_stats->badTlpStatusCount));
- json_object_add_value_uint(root, "Receiver Error Status Counter",
+ json_object_add_value_uint64(root, "Receiver Error Status Counter",
le64_to_cpu(pcie_stats->receiverErrStatusCount));
json_print_object(root, NULL);
@@ -7833,8 +8690,8 @@ static int wdc_do_vs_nand_stats(int fd, char *format)
goto out;
}
- ret = nvme_get_log(fd, 0xFFFFFFFF, WDC_NVME_NAND_STATS_LOG_ID,
- false, NVME_NO_LOG_LSP, WDC_NVME_NAND_STATS_SIZE, (void*)output);
+ ret = nvme_get_log_simple(fd, WDC_NVME_NAND_STATS_LOG_ID,
+ WDC_NVME_NAND_STATS_SIZE, (void*)output);
if (ret) {
fprintf(stderr, "ERROR : WDC : %s : Failed to retreive NAND stats\n", __func__);
goto out;
@@ -7871,6 +8728,7 @@ static int wdc_vs_nand_stats(int argc, char **argv, struct command *command,
int fd;
int ret = 0;
+ nvme_root_t r;
__u64 capabilities = 0;
struct config {
@@ -7890,7 +8748,8 @@ static int wdc_vs_nand_stats(int argc, char **argv, struct command *command,
if (fd < 0)
return fd;
- capabilities = wdc_get_drive_capabilities(fd);
+ r = nvme_scan(NULL);
+ capabilities = wdc_get_drive_capabilities(r, fd);
if ((capabilities & WDC_DRIVE_CAP_NAND_STATS) == 0) {
fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
@@ -7901,6 +8760,7 @@ static int wdc_vs_nand_stats(int argc, char **argv, struct command *command,
fprintf(stderr, "ERROR : WDC : Failure reading NAND statistics, ret = %d\n", ret);
}
+ nvme_free_tree(r);
return ret;
}
@@ -7908,15 +8768,15 @@ static int wdc_do_vs_pcie_stats(int fd,
struct wdc_vs_pcie_stats *pcieStatsPtr)
{
int ret;
- struct nvme_admin_cmd admin_cmd;
+ struct nvme_passthru_cmd admin_cmd;
int pcie_stats_size = sizeof(struct wdc_vs_pcie_stats);
- memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd));
+ memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd));
admin_cmd.opcode = WDC_NVME_PCIE_STATS_OPCODE;
admin_cmd.addr = (__u64)(uintptr_t)pcieStatsPtr;
admin_cmd.data_len = pcie_stats_size;
- ret = nvme_submit_admin_passthru(fd, &admin_cmd);
+ ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL);
return ret;
}
@@ -7928,6 +8788,7 @@ static int wdc_vs_pcie_stats(int argc, char **argv, struct command *command,
int fd;
int ret = 0;
+ nvme_root_t r;
__u64 capabilities = 0;
int fmt = -1;
struct wdc_vs_pcie_stats *pcieStatsPtr = NULL;
@@ -7951,6 +8812,8 @@ static int wdc_vs_pcie_stats(int argc, char **argv, struct command *command,
if (fd < 0)
return fd;
+
+ r = nvme_scan(NULL);
fmt = validate_output_format(cfg.output_format);
if (fmt < 0) {
fprintf(stderr, "ERROR : WDC : invalid output format\n");
@@ -7967,7 +8830,7 @@ static int wdc_vs_pcie_stats(int argc, char **argv, struct command *command,
memset((void *)pcieStatsPtr, 0, pcie_stats_size);
- capabilities = wdc_get_drive_capabilities(fd);
+ capabilities = wdc_get_drive_capabilities(r, fd);
if ((capabilities & WDC_DRIVE_CAP_PCIE_STATS) == 0) {
fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
@@ -7992,6 +8855,7 @@ static int wdc_vs_pcie_stats(int argc, char **argv, struct command *command,
nvme_free(pcieStatsPtr, huge);
out:
+ nvme_free_tree(r);
return ret;
}
@@ -7999,6 +8863,7 @@ static int wdc_vs_drive_info(int argc, char **argv,
struct command *command, struct plugin *plugin)
{
const char *desc = "Send a vs-drive-info command.";
+ nvme_root_t r;
uint64_t capabilities = 0;
int fd, ret;
__le32 result;
@@ -8043,8 +8908,9 @@ static int wdc_vs_drive_info(int argc, char **argv,
return ret;
}
- wdc_check_device(fd);
- capabilities = wdc_get_drive_capabilities(fd);
+ r = nvme_scan(NULL);
+ wdc_check_device(r, fd);
+ capabilities = wdc_get_drive_capabilities(r, fd);
if ((capabilities & WDC_DRIVE_CAP_INFO) == WDC_DRIVE_CAP_INFO) {
ret = wdc_do_drive_info(fd, &result);
@@ -8097,11 +8963,13 @@ static int wdc_vs_drive_info(int argc, char **argv,
}
} else {
fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
+ nvme_free_tree(r);
return -1;
}
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
+ nvme_free_tree(r);
return ret;
}
@@ -8111,6 +8979,7 @@ static int wdc_vs_temperature_stats(int argc, char **argv,
const char *desc = "Send a vs-temperature-stats command.";
struct nvme_smart_log smart_log;
struct nvme_id_ctrl id_ctrl;
+ nvme_root_t r;
uint64_t capabilities = 0;
__u32 hctm_tmt;
int fd, ret;
@@ -8134,6 +9003,7 @@ static int wdc_vs_temperature_stats(int argc, char **argv,
if (fd < 0)
return fd;
+ r = nvme_scan(NULL);
fmt = validate_output_format(cfg.output_format);
if (fmt < 0) {
fprintf(stderr, "ERROR : WDC : invalid output format\n");
@@ -8142,10 +9012,11 @@ static int wdc_vs_temperature_stats(int argc, char **argv,
}
/* check if command is supported */
- wdc_check_device(fd);
- capabilities = wdc_get_drive_capabilities(fd);
+ wdc_check_device(r, fd);
+ capabilities = wdc_get_drive_capabilities(r, fd);
if ((capabilities & WDC_DRIVE_CAP_TEMP_STATS) != WDC_DRIVE_CAP_TEMP_STATS) {
fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
+ nvme_free_tree(r);
return -1;
}
@@ -8153,7 +9024,7 @@ static int wdc_vs_temperature_stats(int argc, char **argv,
ret = nvme_identify_ctrl(fd, &id_ctrl);
if (ret != 0)
goto END;
- ret = nvme_smart_log(fd, NVME_NSID_ALL, &smart_log);
+ ret = nvme_get_log_smart(fd, NVME_NSID_ALL, false, &smart_log);
if (ret != 0)
goto END;
@@ -8161,7 +9032,7 @@ static int wdc_vs_temperature_stats(int argc, char **argv,
temperature = ((smart_log.temperature[1] << 8) | smart_log.temperature[0]) - 273;
/* retrieve HCTM Thermal Management Temperatures */
- nvme_get_feature(fd, 0, 0x10, 0, 0, 0, 0, 0, &hctm_tmt);
+ nvme_get_features_simple(fd, 0x10, 0, &hctm_tmt);
temp_tmt1 = ((hctm_tmt >> 16) & 0xffff) ? ((hctm_tmt >> 16) & 0xffff) - 273 : 0;
temp_tmt2 = (hctm_tmt & 0xffff) ? (hctm_tmt & 0xffff) - 273 : 0;
@@ -8213,7 +9084,8 @@ static int wdc_vs_temperature_stats(int argc, char **argv,
printf("%s: Invalid format\n", __func__);
END:
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ nvme_show_status(ret);
+ nvme_free_tree(r);
return ret;
}
@@ -8221,6 +9093,7 @@ static int wdc_capabilities(int argc, char **argv,
struct command *command, struct plugin *plugin)
{
const char *desc = "Send a capabilities command.";
+ nvme_root_t r;
uint64_t capabilities = 0;
int fd;
@@ -8234,8 +9107,9 @@ static int wdc_capabilities(int argc, char **argv,
return fd;
/* get capabilities */
- wdc_check_device(fd);
- capabilities = wdc_get_drive_capabilities(fd);
+ r = nvme_scan(NULL);
+ wdc_check_device(r, fd);
+ capabilities = wdc_get_drive_capabilities(r, fd);
/* print command and supported status */
printf("WDC Plugin Capabilities for NVME device:%s\n", devicename);
@@ -8298,29 +9172,37 @@ static int wdc_capabilities(int argc, char **argv,
capabilities & WDC_DRIVE_CAP_CLOUD_SSD_VERSION ? "Supported" : "Not Supported");
printf("vs-pcie-stats : %s\n",
capabilities & WDC_DRIVE_CAP_PCIE_STATS ? "Supported" : "Not Supported");
+ printf("get-error-recovery-log : %s\n",
+ capabilities & WDC_DRIVE_CAP_OCP_C1_LOG_PAGE ? "Supported" : "Not Supported");
+ printf("get-dev-capabilities-log : %s\n",
+ capabilities & WDC_DRIVE_CAP_OCP_C4_LOG_PAGE ? "Supported" : "Not Supported");
+ printf("get-unsupported-reqs-log : %s\n",
+ capabilities & WDC_DRIVE_CAP_OCP_C5_LOG_PAGE ? "Supported" : "Not Supported");
printf("capabilities : Supported\n");
+ nvme_free_tree(r);
return 0;
}
static int wdc_cloud_ssd_plugin_version(int argc, char **argv,
struct command *command, struct plugin *plugin)
{
- const char *desc = "Get Cloud SSD Plugin Version command.";
- uint64_t capabilities = 0;
- int fd;
+ const char *desc = "Get Cloud SSD Plugin Version command.";
+ nvme_root_t r;
+ uint64_t capabilities = 0;
+ int fd;
- OPT_ARGS(opts) =
- {
- OPT_END()
- };
+ OPT_ARGS(opts) = {
+ OPT_END()
+ };
- fd = parse_and_open(argc, argv, desc, opts);
- if (fd < 0)
- return fd;
+ fd = parse_and_open(argc, argv, desc, opts);
+ if (fd < 0)
+ return fd;
- /* get capabilities */
- wdc_check_device(fd);
- capabilities = wdc_get_drive_capabilities(fd);
+ /* get capabilities */
+ r = nvme_scan(NULL);
+ wdc_check_device(r, fd);
+ capabilities = wdc_get_drive_capabilities(r, fd);
if ((capabilities & WDC_DRIVE_CAP_CLOUD_SSD_VERSION) == WDC_DRIVE_CAP_CLOUD_SSD_VERSION) {
/* print command and supported status */
@@ -8329,7 +9211,8 @@ static int wdc_cloud_ssd_plugin_version(int argc, char **argv,
fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
}
- return 0;
+ nvme_free_tree(r);
+ return 0;
}
static int wdc_enc_get_log(int argc, char **argv, struct command *command,
@@ -8421,7 +9304,7 @@ static int wdc_enc_get_log(int argc, char **argv, struct command *command,
closed_fd:
close(fd);
ret:
- return nvme_status_to_errno(err, false);
+ return err;
}
static int wdc_enc_submit_move_data(int fd, char *cmd, int len, int xfer_size, FILE *out, int log_id, int cdw14, int cdw15)
@@ -8442,7 +9325,7 @@ static int wdc_enc_submit_move_data(int fd, char *cmd, int len, int xfer_size, F
cmd = (len) ? cmd : buf;
len = (len) ? len : 0x20;
- struct nvme_admin_cmd nvme_cmd = {
+ struct nvme_passthru_cmd nvme_cmd = {
.opcode = WDC_NVME_ADMIN_ENC_MGMT_SND,
.nsid = 0,
.addr = (__u64)(uintptr_t) cmd,
@@ -8475,14 +9358,14 @@ static int wdc_enc_submit_move_data(int fd, char *cmd, int len, int xfer_size, F
d);
#endif
nvme_cmd.result = 0;
- err = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, &nvme_cmd);
+ err = nvme_submit_admin_passthru(fd, &nvme_cmd, NULL);
if (err == NVME_SC_INTERNAL) {
fprintf(stderr, "%s: WARNING : WDC : No log ID:x%x available\n",
__func__, log_id);
}
else if (err != 0) {
- fprintf(stderr, "%s: ERROR : WDC : NVMe Snd Mgmt Status:%s(x%x)\n",
- __func__, nvme_status_to_string(err), err );
+ fprintf(stderr, "%s: ERROR : WDC : NVMe Snd Mgmt\n", __func__);
+ nvme_show_status(err);
} else {
if (nvme_cmd.result == WDC_RESULT_NOT_AVAILABLE)
{
@@ -8503,11 +9386,11 @@ static int wdc_enc_submit_move_data(int fd, char *cmd, int len, int xfer_size, F
nvme_cmd.cdw14 = cdw14;
nvme_cmd.cdw15 = cdw15;
nvme_cmd.result = 0; /* returned result !=0 indicates more data available */
- err = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, &nvme_cmd);
+ err = nvme_submit_admin_passthru(fd, &nvme_cmd, NULL);
if (err != 0) {
more = 0;
- fprintf(stderr, "%s: ERROR : WDC : NVMe Rcv Mgmt Status:%s(x%x)\n",
- __func__, nvme_status_to_string(err), err);
+ fprintf(stderr, "%s: ERROR : WDC : NVMe Rcv Mgmt ", __func__);
+ nvme_show_status(err);
} else {
more = nvme_cmd.result & WDC_RESULT_MORE_DATA;
response_size = nvme_cmd.result & ~WDC_RESULT_MORE_DATA;
@@ -8529,8 +9412,8 @@ static int wdc_enc_get_nic_log(int fd, __u8 log_id, __u32 xfer_size, __u32 data_
{
__u8 *dump_data;
__u32 curr_data_offset, curr_data_len;
- int i, ret;
- struct nvme_admin_cmd admin_cmd;
+ int i, ret = -1;
+ struct nvme_passthru_cmd admin_cmd;
__u32 dump_length = data_len;
__u32 numd;
__u16 numdu, numdl;
@@ -8541,7 +9424,7 @@ static int wdc_enc_get_nic_log(int fd, __u8 log_id, __u32 xfer_size, __u32 data_
return -1;
}
memset(dump_data, 0, sizeof (__u8) * dump_length);
- memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd));
+ memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd));
curr_data_offset = 0;
curr_data_len = xfer_size;
i = 0;
@@ -8560,9 +9443,9 @@ static int wdc_enc_get_nic_log(int fd, __u8 log_id, __u32 xfer_size, __u32 data_
#ifdef WDC_NVME_CLI_DEBUG
fprintf(stderr, "nsid 0x%08x addr 0x%08llx, data_len 0x%08x, cdw10 0x%08x, cdw11 0x%08x, cdw12 0x%08x, cdw13 0x%08x, cdw14 0x%08x \n", admin_cmd.nsid, admin_cmd.addr, admin_cmd.data_len, admin_cmd.cdw10, admin_cmd.cdw11, admin_cmd.cdw12, admin_cmd.cdw13, admin_cmd.cdw14);
#endif
- ret = nvme_submit_admin_passthru(fd, &admin_cmd);
- if (ret !=0 ) {
- fprintf(stderr, "%s: ERROR : WDC : NVMe Status:%s(%x)\n",__func__, nvme_status_to_string(ret), ret);
+ ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL);
+ if (ret != 0) {
+ nvme_show_status(ret);
fprintf(stderr, "%s: ERROR : WDC : Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx\n",
__func__, i, admin_cmd.data_len, curr_data_offset, (long unsigned int)admin_cmd.addr);
break;
diff --git a/plugins/wdc/wdc-nvme.h b/plugins/wdc/wdc-nvme.h
index e046007..da21692 100644
--- a/plugins/wdc/wdc-nvme.h
+++ b/plugins/wdc/wdc-nvme.h
@@ -4,7 +4,7 @@
#if !defined(WDC_NVME) || defined(CMD_HEADER_MULTI_READ)
#define WDC_NVME
-#define WDC_PLUGIN_VERSION "1.15.4"
+#define WDC_PLUGIN_VERSION "1.16.4"
#include "cmd.h"
PLUGIN(NAME("wdc", "Western Digital vendor specific extensions", WDC_PLUGIN_VERSION),
@@ -37,6 +37,9 @@ PLUGIN(NAME("wdc", "Western Digital vendor specific extensions", WDC_PLUGIN_VERS
ENTRY("cloud-SSD-plugin-version", "WDC Cloud SSD Plugin Version", wdc_cloud_ssd_plugin_version)
ENTRY("vs-pcie-stats", "WDC VS PCIE Statistics", wdc_vs_pcie_stats)
ENTRY("get-latency-monitor-log", "WDC Get Latency Monitor Log Page", wdc_get_latency_monitor_log)
+ ENTRY("get-error-recovery-log", "WDC Get Error Recovery Log Page", wdc_get_error_recovery_log)
+ ENTRY("get-dev-capabilities-log", "WDC Get Device Capabilities Log Page", wdc_get_dev_capabilities_log)
+ ENTRY("get-unsupported-reqs-log", "WDC Get Unsupported Requirements Log Page", wdc_get_unsupported_reqs_log)
)
);
diff --git a/plugins/ymtc/ymtc-nvme.c b/plugins/ymtc/ymtc-nvme.c
index 91e52be..dd5f004 100644
--- a/plugins/ymtc/ymtc-nvme.c
+++ b/plugins/ymtc/ymtc-nvme.c
@@ -4,15 +4,11 @@
#include <stdlib.h>
#include <unistd.h>
-#include "linux/nvme_ioctl.h"
-
#include "nvme.h"
-#include "nvme-print.h"
-#include "nvme-ioctl.h"
+#include "libnvme.h"
#include "plugin.h"
-
-#include "argconfig.h"
-#include "suffix.h"
+#include "linux/types.h"
+#include "nvme-print.h"
#define CREATE_CMD
#include "ymtc-nvme.h"
@@ -116,7 +112,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
const char *raw = "dump output in binary format";
struct config {
__u32 namespace_id;
- int raw_binary;
+ bool raw_binary;
};
struct config cfg = {
@@ -133,8 +129,8 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
if (fd < 0)
return fd;
- err = nvme_get_log(fd, cfg.namespace_id, 0xca, false,
- NVME_NO_LOG_LSP, sizeof(smart_log), &smart_log);
+ err = nvme_get_nsid_log(fd, false, 0xca, cfg.namespace_id,
+ sizeof(smart_log), &smart_log);
if (!err) {
if (!cfg.raw_binary)
err = show_ymtc_smart_log(fd, cfg.namespace_id, devicename, &smart_log);
@@ -142,7 +138,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
d_raw((unsigned char *)&smart_log, sizeof(smart_log));
}
if (err > 0)
- fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
+ nvme_show_status(err);
return err;
}
diff --git a/plugins/zns/zns.c b/plugins/zns/zns.c
index 2f765b6..56e53af 100644
--- a/plugins/zns/zns.c
+++ b/plugins/zns/zns.c
@@ -7,15 +7,110 @@
#include <linux/fs.h>
#include <sys/stat.h>
+#include "common.h"
#include "nvme.h"
-#include "nvme-ioctl.h"
+#include "libnvme.h"
#include "nvme-print.h"
-#include "nvme-status.h"
#define CREATE_CMD
#include "zns.h"
static const char *namespace_id = "Namespace identifier to use";
+static const char dash[100] = { [0 ... 99] = '-' };
+
+static int detect_zns(nvme_ns_t ns, int *out_supported)
+{
+ int err = 0;
+ char *zoned;
+
+ *out_supported = 0;
+
+ zoned = nvme_get_attr(nvme_ns_get_sysfs_dir(ns), "queue/zoned");
+ if (!zoned) {
+ *out_supported = 0;
+ return err;
+ }
+
+ *out_supported = strcmp("host-managed", zoned) == 0;
+ free(zoned);
+
+ return err;
+}
+
+static int print_zns_list_ns(nvme_ns_t ns)
+{
+ int supported;
+ int err = 0;
+
+ err = detect_zns(ns, &supported);
+ if (err) {
+ perror("Failed to enumerate namespace");
+ return err;
+ }
+
+ if (supported) {
+ nvme_show_list_item(ns);
+ }
+
+ return err;
+}
+
+static int print_zns_list(nvme_root_t nvme_root)
+{
+ int err = 0;
+ nvme_host_t h;
+ nvme_subsystem_t s;
+ nvme_ctrl_t c;
+ nvme_ns_t n;
+ nvme_for_each_host(nvme_root, h)
+ {
+ nvme_for_each_subsystem(h, s)
+ {
+ nvme_subsystem_for_each_ns(s, n)
+ {
+ err = print_zns_list_ns(n);
+ if (err)
+ return err;
+ }
+
+ nvme_subsystem_for_each_ctrl(s, c)
+ {
+ nvme_ctrl_for_each_ns(c, n)
+ {
+ err = print_zns_list_ns(n);
+ if (err)
+ return err;
+ }
+ }
+ }
+ }
+
+ return err;
+}
+
+static int list(int argc, char **argv, struct command *cmd,
+ struct plugin *plugin)
+{
+ int err = 0;
+ nvme_root_t nvme_root;
+
+ printf("%-21s %-20s %-40s %-9s %-26s %-16s %-8s\n", "Node", "SN",
+ "Model", "Namespace", "Usage", "Format", "FW Rev");
+ printf("%-.21s %-.20s %-.40s %-.9s %-.26s %-.16s %-.8s\n", dash, dash,
+ dash, dash, dash, dash, dash);
+
+ nvme_root = nvme_scan(NULL);
+ if (nvme_root) {
+ err = print_zns_list(nvme_root);
+ } else {
+ fprintf(stderr, "Failed to scan nvme subsystems\n");
+ err = -errno;
+ }
+
+ nvme_free_tree(nvme_root);
+
+ return err;
+}
static int id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
@@ -57,7 +152,7 @@ static int id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *pl
perror("zns identify controller");
close_fd:
close(fd);
- return nvme_status_to_errno(err, false);
+ return err;
}
static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -76,8 +171,8 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug
struct config {
char *output_format;
__u32 namespace_id;
- int human_readable;
- int vendor_specific;
+ bool human_readable;
+ bool vendor_specific;
};
struct config cfg = {
@@ -105,14 +200,14 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug
flags |= VERBOSE;
if (!cfg.namespace_id) {
- err = cfg.namespace_id = nvme_get_nsid(fd);
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
perror("get-namespace-id");
goto close_fd;
}
}
- err = nvme_identify_ns(fd, cfg.namespace_id, false, &id_ns);
+ err = nvme_identify_ns(fd, cfg.namespace_id, &id_ns);
if (err) {
nvme_show_status(err);
goto close_fd;
@@ -127,18 +222,6 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug
perror("zns identify namespace");
close_fd:
close(fd);
- return nvme_status_to_errno(err, false);
-}
-
-static int __zns_mgmt_send(int fd, __u32 namespace_id, __u64 zslba,
- bool select_all, __u32 timeout, enum nvme_zns_send_action zsa,
- __u32 data_len, void *buf)
-{
- int err;
-
- err = nvme_zns_mgmt_send(fd, namespace_id, zslba, select_all, timeout, zsa,
- data_len, buf);
- close(fd);
return err;
}
@@ -149,8 +232,9 @@ static int zns_mgmt_send(int argc, char **argv, struct command *cmd, struct plug
const char *select_all = "send command to all zones";
const char *timeout = "timeout value, in milliseconds";
- int err, fd;
+ int err, fd, zcapc = 0;
char *command;
+ __u32 result;
struct config {
__u64 zslba;
@@ -171,26 +255,42 @@ static int zns_mgmt_send(int argc, char **argv, struct command *cmd, struct plug
err = fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0)
- return errno;
+ goto ret;
err = asprintf(&command, "%s-%s", plugin->name, cmd->name);
if (err < 0)
goto close_fd;
if (!cfg.namespace_id) {
- err = cfg.namespace_id = nvme_get_nsid(fd);
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
perror("get-namespace-id");
goto free;
}
}
- err = __zns_mgmt_send(fd, cfg.namespace_id, cfg.zslba,
- cfg.select_all, cfg.timeout, zsa, 0, NULL);
- if (!err)
- printf("%s: Success, action:%d zone:%"PRIx64" all:%d nsid:%d\n",
+ struct nvme_zns_mgmt_send_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .nsid = cfg.namespace_id,
+ .slba = cfg.zslba,
+ .zsa = zsa,
+ .select_all = cfg.select_all,
+ .zsaso = 0,
+ .data_len = 0,
+ .data = NULL,
+ .timeout = cfg.timeout,
+ .result = &result,
+ };
+ err = nvme_zns_mgmt_send(&args);
+ if (!err) {
+ if (zsa == NVME_ZNS_ZSA_RESET)
+ zcapc = result & 0x1;
+
+ printf("%s: Success, action:%d zone:%"PRIx64" all:%d zcapc:%u nsid:%d\n",
command, zsa, (uint64_t)cfg.zslba, (int)cfg.select_all,
- cfg.namespace_id);
+ zcapc, cfg.namespace_id);
+ }
else if (err > 0)
nvme_show_status(err);
else
@@ -199,7 +299,8 @@ free:
free(command);
close_fd:
close(fd);
- return nvme_status_to_errno(err, false);
+ret:
+ return err;
}
static int get_zdes_bytes(int fd, __u32 nsid)
@@ -209,7 +310,7 @@ static int get_zdes_bytes(int fd, __u32 nsid)
__u8 lbaf;
int err;
- err = nvme_identify_ns(fd, nsid, false, &id_ns);
+ err = nvme_identify_ns(fd, nsid, &id_ns);
if (err > 0) {
nvme_show_status(err);
return -1;
@@ -227,14 +328,16 @@ static int get_zdes_bytes(int fd, __u32 nsid)
return -1;
}
- lbaf = id_ns.flbas & NVME_NS_FLBAS_LBA_MASK;
+ nvme_id_ns_flbas_to_lbaf_inuse(id_ns.flbas, &lbaf);
return ns.lbafe[lbaf].zdes << 6;
}
static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Zone Management Send";
- const char *zslba = "starting LBA of the zone for this command";
+ const char *zslba = "starting LBA of the zone for this command"\
+ "(for flush action, last lba to flush)";
+ const char *zsaso = "Zone Send Action Specific Option";
const char *select_all = "send command to all zones";
const char *zsa = "zone send action";
const char *data_len = "buffer length if data required";
@@ -247,6 +350,7 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu
struct config {
__u64 zslba;
__u32 namespace_id;
+ bool zsaso;
bool select_all;
__u8 zsa;
int data_len;
@@ -259,6 +363,7 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu
OPT_ARGS(opts) = {
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
OPT_SUFFIX("start-lba", 's', &cfg.zslba, zslba),
+ OPT_FLAG("zsaso", 'o', &cfg.zsaso, zsaso),
OPT_FLAG("select-all", 'a', &cfg.select_all, select_all),
OPT_BYTE("zsa", 'z', &cfg.zsa, zsa),
OPT_UINT("data-len", 'l', &cfg.data_len, data_len),
@@ -272,7 +377,7 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu
return errno;
if (!cfg.namespace_id) {
- err = cfg.namespace_id = nvme_get_nsid(fd);
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
perror("get-namespace-id");
goto close_fd;
@@ -287,15 +392,17 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu
if (cfg.zsa == NVME_ZNS_ZSA_SET_DESC_EXT) {
if(!cfg.data_len) {
- cfg.data_len = get_zdes_bytes(fd, cfg.namespace_id);
- if (!cfg.data_len || cfg.data_len < 0) {
+ int data_len = get_zdes_bytes(fd, cfg.namespace_id);
+
+ if (data_len == 0) {
fprintf(stderr,
"Zone Descriptor Extensions are not supported\n");
goto close_fd;
- } else if (cfg.data_len < 0) {
- err = cfg.data_len;
+ } else if (data_len < 0) {
+ err = data_len;
goto close_fd;
}
+ cfg.data_len = data_len;
}
if (posix_memalign(&buf, getpagesize(), cfg.data_len)) {
fprintf(stderr, "can not allocate feature payload\n");
@@ -325,8 +432,20 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu
}
}
- err = __zns_mgmt_send(fd, cfg.namespace_id, cfg.zslba, cfg.select_all,
- cfg.timeout, cfg.zsa, cfg.data_len, buf);
+ struct nvme_zns_mgmt_send_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .nsid = cfg.namespace_id,
+ .slba = cfg.zslba,
+ .zsa = cfg.zsa,
+ .select_all = cfg.select_all,
+ .zsaso = cfg.zsaso,
+ .data_len = cfg.data_len,
+ .data = buf,
+ .timeout = cfg.timeout,
+ .result = NULL,
+ };
+ err = nvme_zns_mgmt_send(&args);
if (!err)
printf("zone-mgmt-send: Success, action:%d zone:%"PRIx64" "
"all:%d nsid:%d\n",
@@ -344,7 +463,7 @@ free:
free(buf);
close_fd:
close(fd);
- return nvme_status_to_errno(err, false);
+ return err;
}
static int close_zone(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -364,8 +483,67 @@ static int finish_zone(int argc, char **argv, struct command *cmd, struct plugin
static int open_zone(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Open zones\n";
+ const char *zslba = "starting LBA of the zone for this command";
+ const char *zrwaa = "Allocate Zone Random Write Area to zone";
+ const char *select_all = "send command to all zones";
+ const char *timeout = "timeout value, in milliseconds";
+
+ int err, fd;
+
+ struct config {
+ __u64 zslba;
+ __u32 namespace_id;
+ bool zrwaa;
+ bool select_all;
+ __u32 timeout;
+ };
+
+ struct config cfg = {
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
+ OPT_SUFFIX("start-lba", 's', &cfg.zslba, zslba),
+ OPT_FLAG("zrwaa", 'r', &cfg.zrwaa, zrwaa),
+ OPT_FLAG("select-all", 'a', &cfg.select_all, select_all),
+ OPT_UINT("timeout", 't', &cfg.timeout, timeout),
+ OPT_END()
+ };
+
+ fd = parse_and_open(argc, argv, desc, opts);
+ if (fd < 0)
+ return errno;
+
+ if (!cfg.namespace_id) {
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
+ if (err < 0) {
+ perror("get-namespace-id");
+ goto close_fd;
+ }
+ }
- return zns_mgmt_send(argc, argv, cmd, plugin, desc, NVME_ZNS_ZSA_OPEN);
+ struct nvme_zns_mgmt_send_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .nsid = cfg.namespace_id,
+ .slba = cfg.zslba,
+ .zsa = NVME_ZNS_ZSA_OPEN,
+ .select_all = cfg.select_all,
+ .zsaso = cfg.zrwaa,
+ .data_len = 0,
+ .data = NULL,
+ .timeout = cfg.timeout,
+ .result = NULL,
+ };
+ err = nvme_zns_mgmt_send(&args);
+ if (!err)
+ printf("zns-open-zone: Success zone slba:%"PRIx64" nsid:%d\n",
+ (uint64_t)cfg.zslba, cfg.namespace_id);
+ else
+ nvme_show_status(err);
+close_fd:
+ close(fd);
+ return err;
}
static int reset_zone(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -386,15 +564,17 @@ static int set_zone_desc(int argc, char **argv, struct command *cmd, struct plug
{
const char *desc = "Set Zone Descriptor Extension\n";
const char *zslba = "starting LBA of the zone for this command";
+ const char *zrwaa = "Allocate Zone Random Write Area to zone";
const char *data = "optional file for zone extention data (default stdin)";
const char *timeout = "timeout value, in milliseconds";
int fd, ffd = STDIN_FILENO, err;
void *buf = NULL;
- __u32 data_len;
+ int data_len;
struct config {
__u64 zslba;
+ bool zrwaa;
__u32 namespace_id;
char *file;
__u32 timeout;
@@ -405,6 +585,7 @@ static int set_zone_desc(int argc, char **argv, struct command *cmd, struct plug
OPT_ARGS(opts) = {
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
OPT_SUFFIX("start-lba", 's', &cfg.zslba, zslba),
+ OPT_FLAG("zrwaa", 'r', &cfg.zrwaa, zrwaa),
OPT_FILE("data", 'd', &cfg.file, data),
OPT_UINT("timeout", 't', &cfg.timeout, timeout),
OPT_END()
@@ -415,7 +596,7 @@ static int set_zone_desc(int argc, char **argv, struct command *cmd, struct plug
return errno;
if (!cfg.namespace_id) {
- err = cfg.namespace_id = nvme_get_nsid(fd);
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
perror("get-namespace-id");
goto close_fd;
@@ -454,8 +635,20 @@ static int set_zone_desc(int argc, char **argv, struct command *cmd, struct plug
goto close_ffd;
}
- err = __zns_mgmt_send(fd, cfg.namespace_id, cfg.zslba, 0, cfg.timeout,
- NVME_ZNS_ZSA_SET_DESC_EXT, data_len, buf);
+ struct nvme_zns_mgmt_send_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .nsid = cfg.namespace_id,
+ .slba = cfg.zslba,
+ .zsa = NVME_ZNS_ZSA_SET_DESC_EXT,
+ .select_all = 0,
+ .zsaso = cfg.zrwaa,
+ .data_len = data_len,
+ .data = buf,
+ .timeout = cfg.timeout,
+ .result = NULL,
+ };
+ err = nvme_zns_mgmt_send(&args);
if (!err)
printf("set-zone-desc: Success, zone:%"PRIx64" nsid:%d\n",
(uint64_t)cfg.zslba, cfg.namespace_id);
@@ -470,7 +663,67 @@ free:
free(buf);
close_fd:
close(fd);
- return nvme_status_to_errno(err, false);
+ return err;
+}
+
+
+static int zrwa_flush_zone(int argc, char **argv, struct command *cmd, struct plugin *plugin)
+{
+ const char *desc = "Flush Explicit ZRWA Range";
+ const char *slba = "LBA to flush up to";
+ const char *timeout = "timeout value, in milliseconds";
+
+ int err, fd;
+
+ struct config {
+ __u64 lba;
+ __u32 namespace_id;
+ __u32 timeout;
+ };
+
+ struct config cfg = {};
+
+ OPT_ARGS(opts) = {
+ OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
+ OPT_SUFFIX("lba", 'l', &cfg.lba, slba),
+ OPT_UINT("timeout", 't', &cfg.timeout, timeout),
+ OPT_END()
+ };
+
+ fd = parse_and_open(argc, argv, desc, opts);
+ if (fd < 0)
+ return errno;
+
+ if (!cfg.namespace_id) {
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
+ if (err < 0) {
+ perror("get-namespace-id");
+ goto close_fd;
+ }
+ }
+
+ struct nvme_zns_mgmt_send_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .nsid = cfg.namespace_id,
+ .slba = cfg.lba,
+ .zsa = NVME_ZNS_ZSA_ZRWA_FLUSH,
+ .select_all = 0,
+ .zsaso = 0,
+ .data_len = 0,
+ .data = NULL,
+ .timeout = cfg.timeout,
+ .result = NULL,
+ };
+ err = nvme_zns_mgmt_send(&args);
+ if (!err)
+ printf("zrwa-flush-zone: Success, lba:%"PRIx64" nsid:%d\n",
+ (uint64_t)cfg.lba, cfg.namespace_id);
+ else
+ nvme_show_status(err);
+close_fd:
+ close(fd);
+ return err;
}
static int zone_mgmt_recv(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -520,7 +773,7 @@ static int zone_mgmt_recv(int argc, char **argv, struct command *cmd, struct plu
goto close_fd;
if (!cfg.namespace_id) {
- err = cfg.namespace_id = nvme_get_nsid(fd);
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
perror("get-namespace-id");
goto close_fd;
@@ -541,8 +794,20 @@ static int zone_mgmt_recv(int argc, char **argv, struct command *cmd, struct plu
}
}
- err = nvme_zns_mgmt_recv(fd, cfg.namespace_id, cfg.zslba, cfg.zra,
- cfg.zrasf, cfg.partial, cfg.data_len, data);
+ struct nvme_zns_mgmt_recv_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .nsid = cfg.namespace_id,
+ .slba = cfg.zslba,
+ .zra = cfg.zra,
+ .zrasf = cfg.zrasf,
+ .zras_feat = cfg.partial,
+ .data_len = cfg.data_len,
+ .data = data,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ err = nvme_zns_mgmt_recv(&args);
if (!err)
printf("zone-mgmt-recv: Success, action:%d zone:%"PRIx64" nsid:%d\n",
cfg.zra, (uint64_t)cfg.zslba, cfg.namespace_id);
@@ -554,7 +819,7 @@ static int zone_mgmt_recv(int argc, char **argv, struct command *cmd, struct plu
free(data);
close_fd:
close(fd);
- return nvme_status_to_errno(err, false);
+ return err;
}
static int report_zones(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -584,6 +849,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
struct nvme_id_ns id_ns;
uint8_t lbaf;
__le64 zsze;
+ struct json_object *zone_list = 0;
struct config {
char *output_format;
@@ -591,7 +857,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
__u32 namespace_id;
int num_descs;
int state;
- int verbose;
+ bool verbose;
bool extended;
bool partial;
};
@@ -624,7 +890,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
flags |= VERBOSE;
if (!cfg.namespace_id) {
- err = cfg.namespace_id = nvme_get_nsid(fd);
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
perror("get-namespace-id");
goto close_fd;
@@ -639,7 +905,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
}
}
- err = nvme_identify_ns(fd, cfg.namespace_id, false, &id_ns);
+ err = nvme_identify_ns(fd, cfg.namespace_id, &id_ns);
if (err) {
nvme_show_status(err);
goto close_fd;
@@ -648,7 +914,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
err = nvme_zns_identify_ns(fd, cfg.namespace_id, &id_zns);
if (!err) {
/* get zsze field from zns id ns data - needed for offset calculation */
- lbaf = id_ns.flbas & NVME_NS_FLBAS_LBA_MASK;
+ nvme_id_ns_flbas_to_lbaf_inuse(id_ns.flbas, &lbaf);
zsze = le64_to_cpu(id_zns.lbafe[lbaf].zsze);
}
else {
@@ -664,7 +930,9 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
}
err = nvme_zns_report_zones(fd, cfg.namespace_id, 0,
- 0, cfg.state, 0, log_len, buff);
+ cfg.state, false, false,
+ log_len, buff,
+ NVME_DEFAULT_IOCTL_TIMEOUT, NULL);
if (err > 0) {
nvme_show_status(err);
goto free_buff;
@@ -695,7 +963,10 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
}
offset = cfg.zslba;
- printf("nr_zones: %"PRIu64"\n", (uint64_t)le64_to_cpu(total_nr_zones));
+ if (flags & JSON)
+ zone_list = json_create_array();
+ else
+ printf("nr_zones: %"PRIu64"\n", (uint64_t)le64_to_cpu(total_nr_zones));
while (nr_zones_retrieved < nr_zones) {
if (nr_zones_retrieved >= nr_zones)
@@ -707,27 +978,32 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
}
err = nvme_zns_report_zones(fd, cfg.namespace_id, offset,
- cfg.extended, cfg.state, cfg.partial, log_len, report);
+ cfg.state, cfg.extended,
+ cfg.partial, log_len, report,
+ NVME_DEFAULT_IOCTL_TIMEOUT, NULL);
if (err > 0) {
nvme_show_status(err);
break;
}
if (!err)
- nvme_show_zns_report_zones(report, nr_zones_chunks, zdes,
- log_len, flags);
+ nvme_show_zns_report_zones(report, nr_zones_chunks,
+ zdes, log_len, flags, zone_list);
nr_zones_retrieved += nr_zones_chunks;
offset = (nr_zones_retrieved * zsze);
}
+ if (flags & JSON)
+ json_nvme_finish_zone_list(total_nr_zones, zone_list);
+
nvme_free(report, huge);
free_buff:
free(buff);
close_fd:
close(fd);
- return nvme_status_to_errno(err, false);
+ return err;
}
static int zone_append(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -754,6 +1030,7 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin
void *buf = NULL, *mbuf = NULL;
__u16 nblocks, control = 0;
__u64 result;
+ __u8 lba_index;
struct timeval start_time, end_time;
struct nvme_id_ns ns;
@@ -764,15 +1041,15 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin
__u64 zslba;
__u64 data_size;
__u64 metadata_size;
- int limited_retry;
- int fua;
+ bool limited_retry;
+ bool fua;
__u32 namespace_id;
__u32 ref_tag;
__u16 lbat;
__u16 lbatm;
__u8 prinfo;
- int piremap;
- int latency;
+ bool piremap;
+ bool latency;
};
struct config cfg = {};
@@ -806,49 +1083,50 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin
}
if (!cfg.namespace_id) {
- err = cfg.namespace_id = nvme_get_nsid(fd);
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
perror("get-namespace-id");
goto close_fd;
}
}
- err = nvme_identify_ns(fd, cfg.namespace_id, false, &ns);
+ err = nvme_identify_ns(fd, cfg.namespace_id, &ns);
if (err) {
nvme_show_status(err);
goto close_fd;
}
- lba_size = 1 << ns.lbaf[(ns.flbas & 0x0f)].ds;
+ nvme_id_ns_flbas_to_lbaf_inuse(ns.flbas, &lba_index);
+ lba_size = 1 << ns.lbaf[lba_index].ds;
if (cfg.data_size & (lba_size - 1)) {
fprintf(stderr,
"Data size:%#"PRIx64" not aligned to lba size:%#x\n",
(uint64_t)cfg.data_size, lba_size);
errno = EINVAL;
- goto close_ns;
+ goto close_fd;
}
- meta_size = ns.lbaf[(ns.flbas & 0x0f)].ms;
+ meta_size = ns.lbaf[lba_index].ms;
if (meta_size && !(meta_size == 8 && (cfg.prinfo & 0x8)) &&
(!cfg.metadata_size || cfg.metadata_size % meta_size)) {
fprintf(stderr,
"Metadata size:%#"PRIx64" not aligned to metadata size:%#x\n",
(uint64_t)cfg.metadata_size, meta_size);
errno = EINVAL;
- goto close_ns;
+ goto close_fd;
}
if (cfg.prinfo > 0xf) {
fprintf(stderr, "Invalid value for prinfo:%#x\n", cfg.prinfo);
errno = EINVAL;
- goto close_ns;
+ goto close_fd;
}
if (cfg.data) {
dfd = open(cfg.data, O_RDONLY);
if (dfd < 0) {
perror(cfg.data);
- goto close_ns;
+ goto close_fd;
}
}
@@ -870,7 +1148,7 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin
if (mfd < 0) {
perror(cfg.metadata);
err = -1;
- goto close_dfd;
+ goto free_data;
}
}
@@ -893,17 +1171,32 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin
nblocks = (cfg.data_size / lba_size) - 1;
control |= (cfg.prinfo << 10);
if (cfg.limited_retry)
- control |= NVME_RW_LR;
+ control |= NVME_IO_LR;
if (cfg.fua)
- control |= NVME_RW_FUA;
+ control |= NVME_IO_FUA;
if (cfg.piremap)
- control |= NVME_RW_PIREMAP;
+ control |= NVME_IO_ZNS_APPEND_PIREMAP;
+
+ struct nvme_zns_append_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .nsid = cfg.namespace_id,
+ .zslba = cfg.zslba,
+ .nlb = nblocks,
+ .control = control,
+ .ilbrt = cfg.ref_tag,
+ .lbat = cfg.lbat,
+ .lbatm = cfg.lbatm,
+ .data_len = cfg.data_size,
+ .data = buf,
+ .metadata_len = cfg.metadata_size,
+ .metadata = mbuf,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
gettimeofday(&start_time, NULL);
- err = nvme_zns_append(fd, cfg.namespace_id, cfg.zslba, nblocks,
- control, cfg.ref_tag, cfg.lbat, cfg.lbatm,
- cfg.data_size, buf, cfg.metadata_size, mbuf,
- &result);
+ err = nvme_zns_append(&args);
gettimeofday(&end_time, NULL);
if (cfg.latency)
printf(" latency: zone append: %llu us\n",
@@ -926,10 +1219,9 @@ free_data:
close_dfd:
if (cfg.data)
close(dfd);
-close_ns:
close_fd:
close(fd);
- return nvme_status_to_errno(err, false);
+ return err;
}
static int changed_zone_list(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -967,15 +1259,14 @@ static int changed_zone_list(int argc, char **argv, struct command *cmd, struct
goto close_fd;
if (!cfg.namespace_id) {
- err = cfg.namespace_id = nvme_get_nsid(fd);
+ err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
perror("get-namespace-id");
goto close_fd;
}
}
- err = nvme_get_log(fd, cfg.namespace_id, NVME_LOG_ZONE_CHANGED_LIST,
- cfg.rae, NVME_NO_LOG_LSP, sizeof(log), &log);
+ err = nvme_get_log_zns_changed_zones(fd, cfg.namespace_id, cfg.rae, &log);
if (!err)
nvme_show_zns_changed(&log, flags);
else if (err > 0)
@@ -985,5 +1276,5 @@ static int changed_zone_list(int argc, char **argv, struct command *cmd, struct
close_fd:
close(fd);
- return nvme_status_to_errno(err, false);
+ return err;
}
diff --git a/plugins/zns/zns.h b/plugins/zns/zns.h
index 61063f7..1bdd4d9 100644
--- a/plugins/zns/zns.h
+++ b/plugins/zns/zns.h
@@ -8,23 +8,24 @@
PLUGIN(NAME("zns", "Zoned Namespace Command Set", NVME_VERSION),
COMMAND_LIST(
- ENTRY("id-ctrl", "Retrieve ZNS controller identification", id_ctrl)
- ENTRY("id-ns", "Retrieve ZNS namespace identification", id_ns)
- ENTRY("zone-mgmt-recv", "Sends the zone management receive command", zone_mgmt_recv)
- ENTRY("zone-mgmt-send", "Sends the zone management send command", zone_mgmt_send)
- ENTRY("report-zones", "Retrieve the Report Zones report", report_zones)
- ENTRY("close-zone", "Closes one or more zones", close_zone)
- ENTRY("finish-zone", "Finishes one or more zones", finish_zone)
- ENTRY("open-zone", "Opens one or more zones", open_zone)
- ENTRY("reset-zone", "Resets one or more zones", reset_zone)
- ENTRY("offline-zone", "Offlines one or more zones", offline_zone)
- ENTRY("set-zone-desc", "Attaches zone descriptor extension data", set_zone_desc)
- ENTRY("zone-append", "Writes data and metadata (if applicable), appended to the end of the requested zone", zone_append)
- ENTRY("changed-zone-list", "Retrieves the changed zone list log", changed_zone_list)
+ ENTRY("list", "List all NVMe devices with Zoned Namespace Command Set support", list)
+ ENTRY("id-ctrl", "Send NVMe Identify Zoned Namespace Controller, display structure", id_ctrl)
+ ENTRY("id-ns", "Send NVMe Identify Zoned Namespace Namespace, display structure", id_ns)
+ ENTRY("report-zones", "Report zones associated to a Zoned Namespace", report_zones)
+ ENTRY("reset-zone", "Reset one or more zones", reset_zone)
+ ENTRY("close-zone", "Close one or more zones", close_zone)
+ ENTRY("finish-zone", "Finishe one or more zones", finish_zone)
+ ENTRY("open-zone", "Open one or more zones", open_zone)
+ ENTRY("offline-zone", "Offline one or more zones", offline_zone)
+ ENTRY("set-zone-desc", "Attach zone descriptor extension data to a zone", set_zone_desc)
+ ENTRY("zrwa-flush-zone", "Flush LBAs associated with a ZRWA to a zone.", zrwa_flush_zone)
+ ENTRY("changed-zone-list", "Retrieve the changed zone list log", changed_zone_list)
+ ENTRY("zone-mgmt-recv", "Send the zone management receive command", zone_mgmt_recv)
+ ENTRY("zone-mgmt-send", "Send the zone management send command", zone_mgmt_send)
+ ENTRY("zone-append", "Append data and metadata (if applicable) to a zone", zone_append)
)
);
#endif
#include "define_cmd.h"
-