summaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2023-04-07 12:43:34 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2023-04-07 12:43:34 +0000
commit8e1dcd44fcad7826e5f8fa6c5caa6c23989518d9 (patch)
tree8a5e1e9d02b2562d57d57ef88e26d4778ebeeab3 /plugins
parentReleasing debian version 2.4+really2.3-2. (diff)
downloadnvme-cli-8e1dcd44fcad7826e5f8fa6c5caa6c23989518d9.tar.xz
nvme-cli-8e1dcd44fcad7826e5f8fa6c5caa6c23989518d9.zip
Merging upstream version 2.4+really2.4.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--plugins/fdp/fdp.c3
-rw-r--r--plugins/innogrit/innogrit-nvme.c107
-rw-r--r--plugins/inspur/inspur-nvme.c4
-rw-r--r--plugins/intel/intel-nvme.c2
-rw-r--r--plugins/memblaze/memblaze-nvme.c14
-rw-r--r--plugins/meson.build56
-rw-r--r--plugins/micron/micron-nvme.c2
-rw-r--r--plugins/ocp/meson.build1
-rw-r--r--plugins/ocp/ocp-clear-fw-update-history.c56
-rw-r--r--plugins/ocp/ocp-clear-fw-update-history.h3
-rw-r--r--plugins/ocp/ocp-nvme.c1276
-rw-r--r--plugins/ocp/ocp-nvme.h12
-rw-r--r--plugins/ocp/ocp-smart-extended-log.c352
-rw-r--r--plugins/ocp/ocp-smart-extended-log.h18
-rw-r--r--plugins/ocp/ocp-utils.c69
-rw-r--r--plugins/ocp/ocp-utils.h2
-rw-r--r--plugins/solidigm/meson.build1
-rw-r--r--plugins/solidigm/solidigm-garbage-collection.c32
-rw-r--r--plugins/solidigm/solidigm-latency-tracking.c22
-rw-r--r--plugins/solidigm/solidigm-nvme.c10
-rw-r--r--plugins/solidigm/solidigm-nvme.h3
-rw-r--r--plugins/solidigm/solidigm-smart.c34
-rw-r--r--plugins/solidigm/solidigm-telemetry.c2
-rw-r--r--plugins/solidigm/solidigm-telemetry/cod.c8
-rw-r--r--plugins/solidigm/solidigm-telemetry/config.c12
-rw-r--r--plugins/solidigm/solidigm-telemetry/config.h5
-rw-r--r--plugins/solidigm/solidigm-telemetry/data-area.c48
-rw-r--r--plugins/solidigm/solidigm-telemetry/header.c32
-rw-r--r--plugins/solidigm/solidigm-telemetry/telemetry-log.h6
-rw-r--r--plugins/solidigm/solidigm-util.c20
-rw-r--r--plugins/solidigm/solidigm-util.h10
-rw-r--r--plugins/wdc/wdc-nvme.c88
-rw-r--r--plugins/wdc/wdc-nvme.h2
33 files changed, 1355 insertions, 957 deletions
diff --git a/plugins/fdp/fdp.c b/plugins/fdp/fdp.c
index 9fef271..1e292e8 100644
--- a/plugins/fdp/fdp.c
+++ b/plugins/fdp/fdp.c
@@ -350,7 +350,8 @@ static int fdp_status(int argc, char **argv, struct command *cmd, struct plugin
goto out;
}
- len = le16_to_cpu(hdr.nruhsd) * sizeof(struct nvme_fdp_ruh_status_desc);
+ len = sizeof(struct nvme_fdp_ruh_status) +
+ le16_to_cpu(hdr.nruhsd) * sizeof(struct nvme_fdp_ruh_status_desc);
buf = malloc(len);
if (!buf) {
err = -ENOMEM;
diff --git a/plugins/innogrit/innogrit-nvme.c b/plugins/innogrit/innogrit-nvme.c
index b5d40dd..1771538 100644
--- a/plugins/innogrit/innogrit-nvme.c
+++ b/plugins/innogrit/innogrit-nvme.c
@@ -162,7 +162,7 @@ static int innogrit_vsc_geteventlog(int argc, char **argv,
{
time_t timep;
struct tm *logtime;
- int icount, ioffset16k, iblock;
+ int icount, ioffset16k, iblock, ivsctype;
char currentdir[128], filename[512];
unsigned char data[4096], data16k[SIZE_16K], zerob[32];
unsigned int *pcheckdata;
@@ -195,6 +195,15 @@ static int innogrit_vsc_geteventlog(int argc, char **argv,
if (getcwd(currentdir, 128) == NULL)
return -1;
+ ret = nvme_vucmd(dev_fd(dev), 0xFE, 0x82, 0x03, 0x00, 0x00, (char *)data, 4096);
+ if (ret == -1)
+ return ret;
+
+ if (data[0] == 0x5A)
+ ivsctype = 1;
+ else
+ ivsctype = 0;
+
time(&timep);
logtime = localtime(&timep);
sprintf(filename, "%s/eventlog_%02d%02d-%02d%02d%02d.elog", currentdir, logtime->tm_mon+1,
@@ -218,10 +227,13 @@ static int innogrit_vsc_geteventlog(int argc, char **argv,
icount++;
memset(data, 0, 4096);
- ret = nvme_vucmd(dev_fd(dev), NVME_VSC_GET_EVENT_LOG, 0, 0,
- (SRB_SIGNATURE >> 32),
- (SRB_SIGNATURE & 0xFFFFFFFF),
- (char *)data, 4096);
+ if (ivsctype == 1)
+ ret = nvme_vucmd(dev_fd(dev), 0xFE, 0x60, 0x00, 0x00, 0x00,(char *)data, 4096);
+ else
+ ret = nvme_vucmd(dev_fd(dev), NVME_VSC_GET_EVENT_LOG, 0, 0,
+ (SRB_SIGNATURE >> 32),
+ (SRB_SIGNATURE & 0xFFFFFFFF),
+ (char *)data, 4096);
if (ret == -1)
return ret;
@@ -302,7 +314,7 @@ static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command,
time_t timep;
struct tm *logtime;
char currentdir[128], filename[512], fname[128];
- unsigned int itotal, icur;
+ unsigned int itotal, icur, ivsctype;
unsigned char data[4096];
struct cdumpinfo cdumpinfo;
unsigned char busevsc = false;
@@ -326,29 +338,44 @@ static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command,
time(&timep);
logtime = localtime(&timep);
+ ivsctype = 0;
ipackindex = 0;
memset(data, 0, 4096);
- if (nvme_vucmd(dev_fd(dev), NVME_VSC_GET, VSC_FN_GET_CDUMP, 0x00,
- (SRB_SIGNATURE >> 32), (SRB_SIGNATURE & 0xFFFFFFFF),
- (char *)data, 4096) == 0) {
- memcpy(&cdumpinfo, &data[3072], sizeof(cdumpinfo));
- if (cdumpinfo.sig == 0x5a5b5c5d) {
- busevsc = true;
- ipackcount = cdumpinfo.ipackcount;
- if (ipackcount == 0) {
- itotal = 0;
- } else {
- itotal = cdumpinfo.cdumppack[ipackindex].ilenth;
- memset(fwvera, 0, sizeof(fwvera));
- memcpy(fwvera, cdumpinfo.cdumppack[ipackindex].fwver, 8);
- sprintf(fname, "cdump_%02d%02d-%02d%02d%02d_%d_%s.cdp", logtime->tm_mon+1,
- logtime->tm_mday, logtime->tm_hour, logtime->tm_min, logtime->tm_sec,
- ipackindex, fwvera);
- sprintf(filename, "%s/%s", currentdir, fname);
- }
+
+ ret = nvme_vucmd(dev_fd(dev), 0xFE, 0x82, 0x03, 0x00, 0x00, (char *)data, 4096);
+ if (ret == -1)
+ return ret;
+
+ if (data[0] == 0x5A) {
+ ivsctype = 1;
+ ret = nvme_vucmd(dev_fd(dev), 0xFE, 0x82, 0x08, 0x00, 0x00,(char *)data, 4096);
+ } else {
+ ivsctype = 0;
+ ret = nvme_vucmd(dev_fd(dev), NVME_VSC_GET, VSC_FN_GET_CDUMP, 0x00,
+ (SRB_SIGNATURE >> 32), (SRB_SIGNATURE & 0xFFFFFFFF),
+ (char *)data, 4096);
+ }
+ if (ret == -1)
+ return ret;
+
+ memcpy(&cdumpinfo, &data[3072], sizeof(cdumpinfo));
+ if (cdumpinfo.sig == 0x5a5b5c5d) {
+ busevsc = true;
+ ipackcount = cdumpinfo.ipackcount;
+ if (ipackcount == 0) {
+ itotal = 0;
+ } else {
+ itotal = cdumpinfo.cdumppack[ipackindex].ilenth;
+ memset(fwvera, 0, sizeof(fwvera));
+ memcpy(fwvera, cdumpinfo.cdumppack[ipackindex].fwver, 8);
+ sprintf(fname, "cdump_%02d%02d-%02d%02d%02d_%d_%s.cdp", logtime->tm_mon+1,
+ logtime->tm_mday, logtime->tm_hour, logtime->tm_min, logtime->tm_sec,
+ ipackindex, fwvera);
+ sprintf(filename, "%s/%s", currentdir, fname);
}
}
+
if (busevsc == false) {
memset(data, 0, 4096);
ret = nvme_get_nsid_log(dev_fd(dev), true, 0x07,
@@ -375,16 +402,18 @@ static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command,
setfilecontent(filename, data, strlen((char *)data));
for (icur = 0; icur < itotal; icur += 4096) {
memset(data, 0, 4096);
- if (busevsc)
- ret = nvme_vucmd(dev_fd(dev), NVME_VSC_GET,
- VSC_FN_GET_CDUMP, 0x00,
- (SRB_SIGNATURE >> 32),
- (SRB_SIGNATURE & 0xFFFFFFFF),
- (char *)data, 4096);
- else
+ if (busevsc) {
+ if (ivsctype == 1)
+ ret = nvme_vucmd(dev_fd(dev), 0xFE, 0x82, 0x08, 0x00, 0x00,(char *)data, 4096);
+ else
+ ret = nvme_vucmd(dev_fd(dev), NVME_VSC_GET, VSC_FN_GET_CDUMP, 0x00,
+ (SRB_SIGNATURE >> 32), (SRB_SIGNATURE & 0xFFFFFFFF),
+ (char *)data, 4096);
+ } else {
ret = nvme_get_nsid_log(dev_fd(dev), true,
0x07,
NVME_NSID_ALL, 4096, data);
+ }
if (ret != 0)
return ret;
@@ -399,17 +428,19 @@ static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command,
ipackindex++;
if (ipackindex != ipackcount) {
memset(data, 0, 4096);
- if (busevsc)
- ret = nvme_vucmd(dev_fd(dev), NVME_VSC_GET,
- VSC_FN_GET_CDUMP, 0x00,
- (SRB_SIGNATURE >> 32),
- (SRB_SIGNATURE & 0xFFFFFFFF),
- (char *)data, 4096);
- else
+ if (busevsc) {
+ if (ivsctype == 1)
+ ret = nvme_vucmd(dev_fd(dev), 0xFE, 0x82, 0x08, 0x00, 0x00,(char *)data, 4096);
+ else
+ ret = nvme_vucmd(dev_fd(dev), NVME_VSC_GET, VSC_FN_GET_CDUMP, 0x00,
+ (SRB_SIGNATURE >> 32), (SRB_SIGNATURE & 0xFFFFFFFF),
+ (char *)data, 4096);
+ } else {
ret = nvme_get_nsid_log(dev_fd(dev), true,
0x07,
NVME_NSID_ALL, 4096,
data);
+ }
if (ret != 0)
return ret;
diff --git a/plugins/inspur/inspur-nvme.c b/plugins/inspur/inspur-nvme.c
index 9d7bb4d..8c929aa 100644
--- a/plugins/inspur/inspur-nvme.c
+++ b/plugins/inspur/inspur-nvme.c
@@ -222,7 +222,9 @@ static int nvme_get_vendor_log(int argc, char **argv, struct command *cmd, struc
return err;
memset(local_mem, 0, BYTE_OF_4K);
- err = nvme_get_log_simple(dev_fd(dev), VENDOR_SMART_LOG_PAGE, sizeof(r1_cli_vendor_log_t), local_mem);
+ err = nvme_get_log_simple(dev_fd(dev),
+ (enum nvme_cmd_get_log_lid)VENDOR_SMART_LOG_PAGE,
+ sizeof(r1_cli_vendor_log_t), local_mem);
if (!err) {
show_r1_vendor_log((r1_cli_vendor_log_t *)local_mem);
show_r1_media_err_log((r1_cli_vendor_log_t *)local_mem);
diff --git a/plugins/intel/intel-nvme.c b/plugins/intel/intel-nvme.c
index f660b84..8a29cf9 100644
--- a/plugins/intel/intel-nvme.c
+++ b/plugins/intel/intel-nvme.c
@@ -1558,7 +1558,7 @@ static int enable_lat_stats_tracking(int argc, char **argv,
.disable = false,
};
- const struct argconfig_commandline_options command_line_options[] = {
+ struct argconfig_commandline_options command_line_options[] = {
{"enable", 'e', "", CFG_FLAG, &cfg.enable, no_argument, enable_desc},
{"disable", 'd', "", CFG_FLAG, &cfg.disable, no_argument, disable_desc},
{NULL}
diff --git a/plugins/memblaze/memblaze-nvme.c b/plugins/memblaze/memblaze-nvme.c
index fb46841..7a4633a 100644
--- a/plugins/memblaze/memblaze-nvme.c
+++ b/plugins/memblaze/memblaze-nvme.c
@@ -226,17 +226,17 @@ static void show_memblaze_smart_log_old(struct nvme_memblaze_smart_log *smart,
printf("Total thermal throttling minutes since power on : %u\n",
smart->items[THERMAL_THROTTLE].thermal_throttle.count);
- printf("Maximum temperature in Kelvin since last factory reset : %u\n",
+ printf("Maximum temperature in kelvins since last factory reset : %u\n",
le16_to_cpu(smart->items[TEMPT_SINCE_RESET].temperature.max));
- printf("Minimum temperature in Kelvin since last factory reset : %u\n",
+ printf("Minimum temperature in kelvins since last factory reset : %u\n",
le16_to_cpu(smart->items[TEMPT_SINCE_RESET].temperature.min));
if (compare_fw_version(fw_ver, "0.09.0300") != 0) {
- printf("Maximum temperature in Kelvin since power on : %u\n",
+ printf("Maximum temperature in kelvins since power on : %u\n",
le16_to_cpu(smart->items[TEMPT_SINCE_BOOTUP].temperature_p.max));
- printf("Minimum temperature in Kelvin since power on : %u\n",
+ printf("Minimum temperature in kelvins since power on : %u\n",
le16_to_cpu(smart->items[TEMPT_SINCE_BOOTUP].temperature_p.min));
}
- printf("Current temperature in Kelvin : %u\n",
+ printf("Current temperature in kelvins : %u\n",
le16_to_cpu(smart->items[TEMPT_SINCE_RESET].temperature.curr));
printf("Maximum power in watt since power on : %u\n",
@@ -707,7 +707,7 @@ static int glp_high_latency(FILE *fdi, char *buf, int buflen, int print)
}
else // sort
{
- timestamp = logEntry->timestampH - 1;
+ timestamp = logEntry->timestampH;
timestamp = timestamp << 32;
timestamp += logEntry->timestampL;
tt = timestamp / 1000;
@@ -1140,7 +1140,7 @@ static int mb_set_lat_stats(int argc, char **argv,
.disable = false,
};
- const struct argconfig_commandline_options command_line_options[] = {
+ struct argconfig_commandline_options command_line_options[] = {
{"enable", 'e', "", CFG_FLAG, &cfg.enable, no_argument, enable_desc},
{"disable", 'd', "", CFG_FLAG, &cfg.disable, no_argument, disable_desc},
{NULL}
diff --git a/plugins/meson.build b/plugins/meson.build
index c92b208..2cf2486 100644
--- a/plugins/meson.build
+++ b/plugins/meson.build
@@ -1,29 +1,31 @@
# SPDX-License-Identifier: GPL-2.0-or-later
-sources += [
- 'plugins/amzn/amzn-nvme.c',
- 'plugins/dell/dell-nvme.c',
- 'plugins/dera/dera-nvme.c',
- 'plugins/huawei/huawei-nvme.c',
- 'plugins/intel/intel-nvme.c',
- 'plugins/innogrit/innogrit-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/solidigm/solidigm-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/inspur/inspur-nvme.c',
- 'plugins/fdp/fdp.c',
-]
-subdir('solidigm')
-subdir('ocp')
+if json_c_dep.found()
+ sources += [
+ 'plugins/amzn/amzn-nvme.c',
+ 'plugins/dell/dell-nvme.c',
+ 'plugins/dera/dera-nvme.c',
+ 'plugins/fdp/fdp.c',
+ 'plugins/huawei/huawei-nvme.c',
+ 'plugins/innogrit/innogrit-nvme.c',
+ 'plugins/inspur/inspur-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/solidigm/solidigm-nvme.c',
+ 'plugins/toshiba/toshiba-nvme.c',
+ 'plugins/transcend/transcend-nvme.c',
+ 'plugins/virtium/virtium-nvme.c',
+ 'plugins/wdc/wdc-nvme.c',
+ 'plugins/wdc/wdc-utils.c',
+ 'plugins/ymtc/ymtc-nvme.c',
+ 'plugins/zns/zns.c',
+ ]
+ subdir('solidigm')
+ subdir('ocp')
+endif
diff --git a/plugins/micron/micron-nvme.c b/plugins/micron/micron-nvme.c
index 3c0904c..bd5f7d7 100644
--- a/plugins/micron/micron-nvme.c
+++ b/plugins/micron/micron-nvme.c
@@ -455,7 +455,7 @@ exit_status:
*/
static int micron_parse_options(struct nvme_dev **dev, int argc, char **argv,
const char *desc,
- const struct argconfig_commandline_options *opts,
+ struct argconfig_commandline_options *opts,
eDriveModel *modelp)
{
int idx = 0;
diff --git a/plugins/ocp/meson.build b/plugins/ocp/meson.build
index a4e5d20..641239a 100644
--- a/plugins/ocp/meson.build
+++ b/plugins/ocp/meson.build
@@ -2,5 +2,6 @@ sources += [
'plugins/ocp/ocp-utils.c',
'plugins/ocp/ocp-nvme.c',
'plugins/ocp/ocp-clear-fw-update-history.c',
+ 'plugins/ocp/ocp-smart-extended-log.c',
]
diff --git a/plugins/ocp/ocp-clear-fw-update-history.c b/plugins/ocp/ocp-clear-fw-update-history.c
index fef09cf..b9235b8 100644
--- a/plugins/ocp/ocp-clear-fw-update-history.c
+++ b/plugins/ocp/ocp-clear-fw-update-history.c
@@ -15,59 +15,7 @@ static const __u8 OCP_FID_CLEAR_FW_ACTIVATION_HISTORY = 0xC1;
int ocp_clear_fw_update_history(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "OCP Clear Firmware Update History";
- __u32 result = 0;
- __u32 clear_fw_history = 1 << 31;
- struct nvme_dev *dev;
- int uuid_index = 0;
- bool no_uuid = false;
- int err;
- OPT_ARGS(opts) = {
- OPT_FLAG("no-uuid", 'n', &no_uuid,
- "Skip UUID index search (UUID index not required for OCP 1.0)"),
- OPT_END()
- };
-
- err = parse_and_open(&dev, argc, argv, desc, opts);
- if (err)
- return err;
- if (no_uuid == false) {
- // OCP 2.0 requires UUID index support
- err = ocp_get_uuid_index(dev, &uuid_index);
- if (err || uuid_index == 0) {
- fprintf(stderr, "ERROR: No OCP UUID index found\n");
- goto close_dev;
- }
- }
-
- struct nvme_set_features_args args = {
- .result = &result,
- .data = NULL,
- .args_size = sizeof(args),
- .fd = dev_fd(dev),
- .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
- .nsid = 0,
- .cdw11 = clear_fw_history,
- .cdw12 = 0,
- .cdw13 = 0,
- .cdw15 = 0,
- .data_len = 0,
- .save = 0,
- .uuidx = uuid_index,
- .fid = OCP_FID_CLEAR_FW_ACTIVATION_HISTORY,
- };
-
- err = nvme_set_features(&args);
-
- if (err == 0)
- printf("Success : %s\n", desc);
- else if (err > 0)
- nvme_show_status(err);
- else
- printf("Fail : %s\n", desc);
-close_dev:
- /* Redundant close() to make static code analysis happy */
- close(dev->direct.fd);
- dev_close(dev);
- return err;
+ return ocp_clear_feature(argc, argv, desc,
+ OCP_FID_CLEAR_FW_ACTIVATION_HISTORY);
}
diff --git a/plugins/ocp/ocp-clear-fw-update-history.h b/plugins/ocp/ocp-clear-fw-update-history.h
index 25fb6b1..cd0844c 100644
--- a/plugins/ocp/ocp-clear-fw-update-history.h
+++ b/plugins/ocp/ocp-clear-fw-update-history.h
@@ -6,4 +6,5 @@
* leonardo.da.cunha@solidigm.com
*/
-int ocp_clear_fw_update_history(int argc, char **argv, struct command *cmd, struct plugin *plugin);
+int ocp_clear_fw_update_history(int argc, char **argv,
+ struct command *cmd, struct plugin *plugin);
diff --git a/plugins/ocp/ocp-nvme.c b/plugins/ocp/ocp-nvme.c
index 14a5f30..a864363 100644
--- a/plugins/ocp/ocp-nvme.c
+++ b/plugins/ocp/ocp-nvme.c
@@ -3,7 +3,7 @@
*
* Authors: Arthur Shau <arthurshau@fb.com>,
* Wei Zhang <wzhang@fb.com>,
- * Venkat Ramesh <venkatraghavan@fb.com>
+ * Venkat Ramesh <venkatraghavan@fb.com>
*/
#include <stdio.h>
#include <string.h>
@@ -22,753 +22,627 @@
#include "linux/types.h"
#include "util/types.h"
#include "nvme-print.h"
+
+#include "ocp-smart-extended-log.h"
#include "ocp-clear-fw-update-history.h"
#define CREATE_CMD
#include "ocp-nvme.h"
+#include "ocp-utils.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 };
+#define C0_ACTIVE_BUCKET_TIMER_INCREMENT 5
+#define C0_ACTIVE_THRESHOLD_INCREMENT 5
+#define C0_MINIMUM_WINDOW_INCREMENT 100
/* 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;
+#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
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 */
+ __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]; /* 0x0F0 - 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 const __u8 OCP_FID_CLEAR_PCIE_CORRECTABLE_ERROR_COUNTERS = 0xC3;
+
static int convert_ts(time_t time, char *ts_buf)
{
- struct tm gmTimeInfo;
- time_t time_Human, time_ms;
- char buf[80];
+ struct tm gmTimeInfo;
+ time_t time_Human, time_ms;
+ char buf[80];
- time_Human = time/1000;
- time_ms = time % 1000;
+ time_Human = time/1000;
+ time_ms = time % 1000;
- gmtime_r((const time_t *)&time_Human, &gmTimeInfo);
+ 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);
+ strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &gmTimeInfo);
+ sprintf(ts_buf, "%s.%03ld GMT", buf, time_ms);
- return 0;
+ return 0;
}
-static void ocp_print_C0_log_normal(void *data)
+static int ocp_print_C3_log_normal(struct nvme_dev *dev,
+ struct ssd_latency_monitor_log *log_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 %s\n",
- uint128_t_to_string(le128_to_cpu(&log_data[SCAO_PSC])));
- printf(" Endurance estimate %s\n",
- uint128_t_to_string(le128_to_cpu(&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");
+ char ts_buf[128];
+ int i, j;
+ int pos = 0;
+
+ printf("-Latency Monitor/C3 Log Page Data-\n");
+ printf(" Controller : %s\n", dev->name);
+ 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_C0_log_json(void *data)
+static void ocp_print_C3_log_json(struct ssd_latency_monitor_log *log_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_uint128(root, "PLP start count",
- le128_to_cpu(&log_data[SCAO_PSC]));
- json_object_add_value_uint128(root, "Endurance estimate",
- le128_to_cpu(&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);
+ struct json_object *root;
+ char ts_buf[128];
+ char buf[128];
+ int i, j;
+ int pos = 0;
+ char *operation[3] = {"Read", "Write", "Trim"};
+
+ 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_c0_log_page(int fd, char *format)
+static int get_c3_log_page(struct nvme_dev *dev, 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 */
- 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");
- }
+ struct ssd_latency_monitor_log *log_data;
+ 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;
+ }
+
+ data = malloc(sizeof(__u8) * C3_LATENCY_MON_LOG_BUF_LEN);
+ if (!data) {
+ 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(dev_fd(dev), 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]) {
+ int j;
+
+ fprintf(stderr, "ERROR : OCP : Unknown GUID in C3 Log Page data\n");
+ 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;
+ }
+ }
+
+ switch (fmt) {
+ case NORMAL:
+ ocp_print_C3_log_normal(dev, 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;
+ free(data);
+ return ret;
+}
+
+static int smart_add_log(int argc, char **argv, struct command *cmd,
+ struct plugin *plugin)
+{
+ return ocp_smart_add_log(argc, argv, cmd, plugin);
}
-static int ocp_smart_add_log(int argc, char **argv, struct command *cmd,
- struct plugin *plugin)
+static int ocp_latency_monitor_log(int argc, char **argv,
+ struct command *command,
+ struct plugin *plugin)
{
- const char *desc = "Retrieve latency monitor log data.";
+ const char *desc = "Retrieve latency monitor log data.";
struct nvme_dev *dev;
- 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()
- };
-
- ret = parse_and_open(&dev, argc, argv, desc, opts);
- if (ret)
- return ret;
-
- ret = get_c0_log_page(dev_fd(dev), cfg.output_format);
- if (ret)
- fprintf(stderr, "ERROR : OCP : Failure reading the C0 Log Page, ret = %d\n",
- ret);
- dev_close(dev);
- return ret;
+ 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()
+ };
+
+ ret = parse_and_open(&dev, argc, argv, desc, opts);
+ if (ret)
+ return ret;
+
+ ret = get_c3_log_page(dev, cfg.output_format);
+ if (ret)
+ fprintf(stderr,
+ "ERROR : OCP : Failure reading the C3 Log Page, ret = %d\n",
+ ret);
+
+ dev_close(dev);
+ return ret;
}
-static int ocp_print_C3_log_normal(struct nvme_dev *dev,
- struct ssd_latency_monitor_log *log_data)
+static int clear_fw_update_history(int argc, char **argv,
+ struct command *cmd, struct plugin *plugin)
{
- printf("-Latency Monitor/C3 Log Page Data- \n");
- printf(" Controller : %s\n", dev->name);
- 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;
+ return ocp_clear_fw_update_history(argc, argv, cmd, plugin);
}
-static void ocp_print_C3_log_json(struct ssd_latency_monitor_log *log_data)
+static const char *eol_plp_failure_mode_to_string(__u8 mode)
{
- 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);
+ switch (mode) {
+ case 1:
+ return "Read only mode (ROM)";
+ case 2:
+ return "Write through mode (WTM)";
+ case 3:
+ return "Normal mode";
+ default:
+ break;
+ }
+
+ return "Reserved";
}
-static int get_c3_log_page(struct nvme_dev *dev, char *format)
+static int eol_plp_failure_mode_get(struct nvme_dev *dev, const __u32 nsid,
+ const __u8 fid, __u8 sel)
{
- 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(dev_fd(dev), 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;
- }
- }
-
- switch (fmt) {
- case NORMAL:
- ocp_print_C3_log_normal(dev, 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");
- }
+ __u32 result;
+ int err;
+
+ struct nvme_get_features_args args = {
+ .args_size = sizeof(args),
+ .fd = dev_fd(dev),
+ .fid = fid,
+ .nsid = nsid,
+ .sel = sel,
+ .cdw11 = 0,
+ .uuidx = 0,
+ .data_len = 0,
+ .data = NULL,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+
+ err = nvme_get_features(&args);
+ if (!err) {
+ printf("End of Life Behavior (feature: %#0*x): %#0*x (%s: %s)\n",
+ fid ? 4 : 2, fid, result ? 10 : 8, result,
+ nvme_select_to_string(sel),
+ eol_plp_failure_mode_to_string(result));
+ if (sel == NVME_GET_FEATURES_SEL_SUPPORTED)
+ nvme_show_select_result(result);
+ } else {
+ printf("Could not get feature: %#0*x.\n", fid ? 4 : 2, fid);
+ }
+
+ return err;
+}
-out:
- free(data);
- return ret;
+static int eol_plp_failure_mode_set(struct nvme_dev *dev, const __u32 nsid,
+ const __u8 fid, __u8 mode, bool save,
+ bool uuid)
+{
+ __u32 result;
+ int err;
+ int uuid_index = 0;
+
+ if (uuid) {
+ /* OCP 2.0 requires UUID index support */
+ err = ocp_get_uuid_index(dev, &uuid_index);
+ if (err || !uuid_index) {
+ fprintf(stderr, "ERROR: No OCP UUID index found\n");
+ return err;
+ }
+ }
+
+
+ struct nvme_set_features_args args = {
+ .args_size = sizeof(args),
+ .fd = dev_fd(dev),
+ .fid = fid,
+ .nsid = nsid,
+ .cdw11 = mode << 30,
+ .cdw12 = 0,
+ .save = save,
+ .uuidx = uuid_index,
+ .cdw15 = 0,
+ .data_len = 0,
+ .data = NULL,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+
+ err = nvme_set_features(&args);
+ if (err > 0) {
+ nvme_show_status(err);
+ } else if (err < 0) {
+ perror("Define EOL/PLP failure mode");
+ fprintf(stderr, "Command failed while parsing.\n");
+ } else {
+ printf("Successfully set mode (feature: %#0*x): %#0*x (%s: %s).\n",
+ fid ? 4 : 2, fid, mode ? 10 : 8, mode,
+ save ? "Save" : "Not save",
+ eol_plp_failure_mode_to_string(mode));
+ }
+
+ return err;
}
-static int ocp_latency_monitor_log(int argc, char **argv, struct command *command,
- struct plugin *plugin)
+static int eol_plp_failure_mode(int argc, char **argv, struct command *cmd,
+ struct plugin *plugin)
{
- const char *desc = "Retrieve latency monitor log data.";
+ const char *desc = "Define EOL or PLP circuitry failure mode.\n"\
+ "No argument prints current mode.";
+ const char *mode = "[0-3]: default/rom/wtm/normal";
+ const char *save = "Specifies that the controller shall save the attribute";
+ const char *sel = "[0-3,8]: current/default/saved/supported/changed";
+ const __u32 nsid = 0;
+ const __u8 fid = 0xc2;
struct nvme_dev *dev;
- 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()
- };
-
- ret = parse_and_open(&dev, argc, argv, desc, opts);
- if (ret)
- return ret;
-
- ret = get_c3_log_page(dev, cfg.output_format);
- if (ret)
- fprintf(stderr,
- "ERROR : OCP : Failure reading the C3 Log Page, ret = %d\n",
- ret);
- dev_close(dev);
- return ret;
+ int err;
+
+ struct config {
+ __u8 mode;
+ bool save;
+ __u8 sel;
+ };
+
+ struct config cfg = {
+ .mode = 0,
+ .save = false,
+ .sel = 0,
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_BYTE("mode", 'm', &cfg.mode, mode),
+ OPT_FLAG("save", 's', &cfg.save, save),
+ OPT_BYTE("sel", 'S', &cfg.sel, sel),
+ OPT_FLAG("no-uuid", 'n', NULL,
+ "Skip UUID index search (UUID index not required for OCP 1.0)"),
+ OPT_END()
+ };
+
+ err = parse_and_open(&dev, argc, argv, desc, opts);
+ if (err)
+ return err;
+
+ if (argconfig_parse_seen(opts, "mode"))
+ err = eol_plp_failure_mode_set(dev, nsid, fid, cfg.mode,
+ cfg.save,
+ !argconfig_parse_seen(opts, "no-uuid"));
+ else
+ err = eol_plp_failure_mode_get(dev, nsid, fid, cfg.sel);
+
+ dev_close(dev);
+
+ return err;
}
-static int clear_fw_update_history(int argc, char **argv, struct command *cmd,
- struct plugin *plugin)
+static int clear_pcie_corectable_error_counters(int argc, char **argv,
+ struct command *cmd,
+ struct plugin *plugin)
{
- return ocp_clear_fw_update_history(argc, argv, cmd, plugin);
+ const char *desc = "OCP Clear PCIe Correctable Error Counters";
+
+ return ocp_clear_feature(argc, argv, desc,
+ OCP_FID_CLEAR_PCIE_CORRECTABLE_ERROR_COUNTERS);
}
diff --git a/plugins/ocp/ocp-nvme.h b/plugins/ocp/ocp-nvme.h
index c20646a..dc9e154 100644
--- a/plugins/ocp/ocp-nvme.h
+++ b/plugins/ocp/ocp-nvme.h
@@ -3,7 +3,7 @@
*
* Authors: Arthur Shau <arthurshau@fb.com>,
* Wei Zhang <wzhang@fb.com>,
- * Venkat Ramesh <venkatraghavan@fb.com>
+ * Venkat Ramesh <venkatraghavan@fb.com>
*/
#undef CMD_INC_FILE
#define CMD_INC_FILE plugins/ocp/ocp-nvme
@@ -15,11 +15,11 @@
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)
- ENTRY("clear-fw-activate-history", "Clear firmware update history log",
- clear_fw_update_history)
+ ENTRY("smart-add-log", "Retrieve extended SMART Information", smart_add_log)
+ ENTRY("latency-monitor-log", "Get Latency Monitor Log Page", ocp_latency_monitor_log)
+ ENTRY("clear-fw-activate-history", "Clear firmware update history log", clear_fw_update_history)
+ ENTRY("eol-plp-failure-mode", "Define EOL or PLP circuitry failure mode.", eol_plp_failure_mode)
+ ENTRY("clear-pcie-correctable-error-counters", "Clear PCIe correctable error counters", clear_pcie_corectable_error_counters)
)
);
diff --git a/plugins/ocp/ocp-smart-extended-log.c b/plugins/ocp/ocp-smart-extended-log.c
new file mode 100644
index 0000000..37b62e9
--- /dev/null
+++ b/plugins/ocp/ocp-smart-extended-log.c
@@ -0,0 +1,352 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Copyright (c) 2022 Meta Platforms, Inc.
+ *
+ * Authors: Arthur Shau <arthurshau@fb.com>,
+ * Wei Zhang <wzhang@fb.com>,
+ * Venkat Ramesh <venkatraghavan@fb.com>
+ */
+
+#include "ocp-smart-extended-log.h"
+
+#include <errno.h>
+#include <stdio.h>
+
+#include "common.h"
+#include "nvme-print.h"
+
+/* C0 SCAO Log Page */
+#define C0_SMART_CLOUD_ATTR_LEN 0x200
+#define C0_SMART_CLOUD_ATTR_OPCODE 0xC0
+#define C0_GUID_LENGTH 16
+
+static __u8 scao_guid[C0_GUID_LENGTH] = {
+ 0xC5, 0xAF, 0x10, 0x28,
+ 0xEA, 0xBF, 0xF2, 0xA4,
+ 0x9C, 0x4F, 0x6F, 0x7C,
+ 0xC9, 0x14, 0xD5, 0xAF
+};
+
+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_EEDC = 72, /* End to end detected errors */
+ SCAO_EECE = 76, /* End to end corrected 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_PSCC = 200, /* Power State Change Count */
+ SCAO_LPV = 494, /* Log page version */
+ SCAO_LPG = 496, /* Log page GUID */
+} SMART_CLOUD_ATTRIBUTE_OFFSETS;
+
+static void ocp_print_C0_log_normal(void *data)
+{
+ uint16_t smart_log_ver = 0;
+ __u8 *log_data = data;
+
+ 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 detected errors %"PRIu32"\n",
+ (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EEDC]));
+ printf(" End to end corrected errors %"PRIu32"\n",
+ (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EECE]));
+ 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 %s\n",
+ uint128_t_to_string(le128_to_cpu(&log_data[SCAO_PSC])));
+ printf(" Endurance estimate %s\n",
+ uint128_t_to_string(le128_to_cpu(&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",
+ le16_to_cpu(*(uint16_t *)&log_data[SCAO_PVF]));
+ printf(" Minor Version Field %"PRIu16"\n",
+ le16_to_cpu(*(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(" Power State Change Count %"PRIu64"\n",
+ le64_to_cpu(*(uint64_t *)&log_data[SCAO_PSCC]));
+ }
+ printf("\n");
+}
+
+static void ocp_print_C0_log_json(void *data)
+{
+ struct json_object *root;
+ struct json_object *pmuw;
+ struct json_object *pmur;
+ uint16_t smart_log_ver = 0;
+ __u8 *log_data = data;
+ char guid[40];
+
+ 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 detected errors",
+ (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EEDC]));
+ 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, "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_uint128(root, "PLP start count",
+ le128_to_cpu(&log_data[SCAO_PSC]));
+ json_object_add_value_uint128(root, "Endurance estimate",
+ le128_to_cpu(&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);
+
+ 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",
+ le16_to_cpu(*(uint16_t *)&log_data[SCAO_PVF]));
+ json_object_add_value_uint(root, "Minor Version Field",
+ le16_to_cpu(*(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_object_add_value_uint(root, "Power State Change Count",
+ le64_to_cpu(*(uint64_t *)&log_data[SCAO_PSCC]));
+ }
+ json_print_object(root, NULL);
+ printf("\n");
+ json_free_object(root);
+}
+
+static int get_c0_log_page(int fd, char *format)
+{
+ __u8 *data;
+ int i;
+ int ret = 0;
+ int fmt = -1;
+
+ fmt = validate_output_format(format);
+ if (fmt < 0) {
+ fprintf(stderr, "ERROR : OCP : invalid output format\n");
+ return fmt;
+ }
+
+ data = malloc(sizeof(__u8) * C0_SMART_CLOUD_ATTR_LEN);
+ if (!data) {
+ 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]) {
+ int j;
+
+ fprintf(stderr, "ERROR : OCP : Unknown GUID in C0 Log Page data\n");
+ 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 */
+ 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;
+}
+
+int ocp_smart_add_log(int argc, char **argv, struct command *cmd,
+ struct plugin *plugin)
+{
+ const char *desc = "Retrieve the extended SMART health data.";
+ struct nvme_dev *dev;
+ 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()
+ };
+
+ ret = parse_and_open(&dev, argc, argv, desc, opts);
+ if (ret)
+ return ret;
+
+ ret = get_c0_log_page(dev_fd(dev), cfg.output_format);
+ if (ret)
+ fprintf(stderr, "ERROR : OCP : Failure reading the C0 Log Page, ret = %d\n",
+ ret);
+ dev_close(dev);
+ return ret;
+}
diff --git a/plugins/ocp/ocp-smart-extended-log.h b/plugins/ocp/ocp-smart-extended-log.h
new file mode 100644
index 0000000..42c1f98
--- /dev/null
+++ b/plugins/ocp/ocp-smart-extended-log.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* Copyright (c) 2022 Meta Platforms, Inc.
+ *
+ * Authors: Arthur Shau <arthurshau@fb.com>,
+ * Wei Zhang <wzhang@fb.com>,
+ * Venkat Ramesh <venkatraghavan@fb.com>
+ */
+
+#ifndef OCP_SMART_EXTENDED_LOG_H
+#define OCP_SMART_EXTENDED_LOG_H
+
+struct command;
+struct plugin;
+
+int ocp_smart_add_log(int argc, char **argv, struct command *cmd,
+ struct plugin *plugin);
+
+#endif
diff --git a/plugins/ocp/ocp-utils.c b/plugins/ocp/ocp-utils.c
index 9294c05..a37a58c 100644
--- a/plugins/ocp/ocp-utils.c
+++ b/plugins/ocp/ocp-utils.c
@@ -5,11 +5,13 @@
* Author: leonardo.da.cunha@solidigm.com
*/
+#include <unistd.h>
#include "ocp-utils.h"
+#include "nvme-print.h"
const unsigned char ocp_uuid[NVME_UUID_LEN] = {
- 0x6f, 0xbe, 0x56, 0x8f, 0x99, 0x29, 0x1d, 0xa2, 0x94, 0x47,
- 0x94, 0xe0, 0x5b, 0xd5, 0x94, 0xc1 };
+ 0xc1, 0x94, 0xd5, 0x5b, 0xe0, 0x94, 0x47, 0x94, 0xa2, 0x1d,
+ 0x29, 0x99, 0x8f, 0x56, 0xbe, 0x6f };
int ocp_get_uuid_index(struct nvme_dev *dev, int *index)
{
@@ -28,3 +30,66 @@ int ocp_get_uuid_index(struct nvme_dev *dev, int *index)
}
return err;
}
+
+int ocp_clear_feature(int argc, char **argv, const char *desc, const __u8 fid)
+{
+ __u32 result = 0;
+ __u32 clear = 1 << 31;
+ struct nvme_dev *dev;
+ int uuid_index = 0;
+ bool uuid = true;
+ int err;
+
+ OPT_ARGS(opts) = {
+ OPT_FLAG("no-uuid", 'n', NULL,
+ "Skip UUID index search (UUID index not required for OCP 1.0)"),
+ OPT_END()
+ };
+
+ err = parse_and_open(&dev, argc, argv, desc, opts);
+ if (err)
+ return err;
+
+ if (opts[0].seen)
+ uuid = false;
+
+ if (uuid) {
+ /* OCP 2.0 requires UUID index support */
+ err = ocp_get_uuid_index(dev, &uuid_index);
+ if (err || !uuid_index) {
+ fprintf(stderr, "ERROR: No OCP UUID index found\n");
+ goto close_dev;
+ }
+ }
+
+ struct nvme_set_features_args args = {
+ .result = &result,
+ .data = NULL,
+ .args_size = sizeof(args),
+ .fd = dev_fd(dev),
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .nsid = 0,
+ .cdw11 = clear,
+ .cdw12 = 0,
+ .cdw13 = 0,
+ .cdw15 = 0,
+ .data_len = 0,
+ .save = 0,
+ .uuidx = uuid_index,
+ .fid = fid,
+ };
+
+ err = nvme_set_features(&args);
+
+ if (err == 0)
+ printf("Success : %s\n", desc);
+ else if (err > 0)
+ nvme_show_status(err);
+ else
+ printf("Fail : %s\n", desc);
+close_dev:
+ /* Redundant close() to make static code analysis happy */
+ close(dev->direct.fd);
+ dev_close(dev);
+ return err;
+}
diff --git a/plugins/ocp/ocp-utils.h b/plugins/ocp/ocp-utils.h
index 44d0af4..a962169 100644
--- a/plugins/ocp/ocp-utils.h
+++ b/plugins/ocp/ocp-utils.h
@@ -16,3 +16,5 @@
* Return: Zero if nvme device has UUID list log page, or result of get uuid list otherwise.
*/
int ocp_get_uuid_index(struct nvme_dev *dev, int *index);
+
+int ocp_clear_feature(int argc, char **argv, const char *desc, const __u8 fid);
diff --git a/plugins/solidigm/meson.build b/plugins/solidigm/meson.build
index bca13bb..526fb02 100644
--- a/plugins/solidigm/meson.build
+++ b/plugins/solidigm/meson.build
@@ -1,4 +1,5 @@
sources += [
+ 'plugins/solidigm/solidigm-util.c',
'plugins/solidigm/solidigm-smart.c',
'plugins/solidigm/solidigm-garbage-collection.c',
'plugins/solidigm/solidigm-latency-tracking.c',
diff --git a/plugins/solidigm/solidigm-garbage-collection.c b/plugins/solidigm/solidigm-garbage-collection.c
index 8e2eccc..3828b9e 100644
--- a/plugins/solidigm/solidigm-garbage-collection.c
+++ b/plugins/solidigm/solidigm-garbage-collection.c
@@ -19,6 +19,7 @@
#include "linux/types.h"
#include "nvme-print.h"
#include "solidigm-garbage-collection.h"
+#include "solidigm-util.h"
typedef struct __attribute__((packed)) gc_item {
__le32 timer_type;
@@ -49,9 +50,11 @@ static void vu_gc_log_show_json(garbage_control_collection_log_t *payload, const
json_free_object(gc_entries);
}
-static void vu_gc_log_show(garbage_control_collection_log_t *payload, const char *devname)
+static void vu_gc_log_show(garbage_control_collection_log_t *payload, const char *devname,
+ __u8 uuid_index)
{
- printf("Solidigm Garbage Collection Log for NVME device: %s\n", devname);
+ printf("Solidigm Garbage Collection Log for NVME device:%s UUID-idx:%d\n", devname,
+ uuid_index);
printf("Timestamp Timer Type\n");
for (int i = 0; i < VU_GC_MAX_ITEMS; i++) {
@@ -65,6 +68,7 @@ int solidigm_get_garbage_collection_log(int argc, char **argv, struct command *c
const char *desc = "Get and parse Solidigm vendor specific garbage collection event log.";
struct nvme_dev *dev;
int err;
+ __u8 uuid_index;
struct config {
char *output_format;
@@ -90,18 +94,36 @@ int solidigm_get_garbage_collection_log(int argc, char **argv, struct command *c
return EINVAL;
}
+ uuid_index = solidigm_get_vu_uuid_index(dev);
+
garbage_control_collection_log_t gc_log;
const int solidigm_vu_gc_log_id = 0xfd;
+ struct nvme_get_log_args args = {
+ .lpo = 0,
+ .result = NULL,
+ .log = &gc_log,
+ .args_size = sizeof(args),
+ .fd = dev_fd(dev),
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .lid = solidigm_vu_gc_log_id,
+ .len = sizeof(gc_log),
+ .nsid = NVME_NSID_ALL,
+ .csi = NVME_CSI_NVM,
+ .lsi = NVME_LOG_LSI_NONE,
+ .lsp = NVME_LOG_LSP_NONE,
+ .uuidx = uuid_index,
+ .rae = false,
+ .ot = false,
+ };
- err = nvme_get_log_simple(dev_fd(dev), solidigm_vu_gc_log_id,
- sizeof(gc_log), &gc_log);
+ err = nvme_get_log(&args);
if (!err) {
if (flags & BINARY) {
d_raw((unsigned char *)&gc_log, sizeof(gc_log));
} else if (flags & JSON) {
vu_gc_log_show_json(&gc_log, dev->name);
} else {
- vu_gc_log_show(&gc_log, dev->name);
+ vu_gc_log_show(&gc_log, dev->name, uuid_index);
}
}
else if (err > 0) {
diff --git a/plugins/solidigm/solidigm-latency-tracking.c b/plugins/solidigm/solidigm-latency-tracking.c
index 1013ae8..40edcfa 100644
--- a/plugins/solidigm/solidigm-latency-tracking.c
+++ b/plugins/solidigm/solidigm-latency-tracking.c
@@ -17,6 +17,7 @@
#include "plugin.h"
#include "linux/types.h"
#include "nvme-print.h"
+#include "solidigm-util.h"
#define BUCKET_LIST_SIZE_4_0 152
#define BUCKET_LIST_SIZE_4_1 1216
@@ -42,6 +43,7 @@ struct config {
struct latency_tracker {
int fd;
+ __u8 uuid_index;
struct config cfg;
enum nvme_print_flags print_flags;
struct latency_statistics stats;
@@ -213,6 +215,7 @@ static void latency_tracker_pre_parse(struct latency_tracker *lt)
if (lt->print_flags == NORMAL) {
printf("Solidigm IO %s Command Latency Tracking Statistics type %d\n",
lt->cfg.write ? "Write" : "Read", lt->cfg.type);
+ printf("UUID-idx: %d\n", lt->uuid_index);
printf("Major Revision: %u\nMinor Revision: %u\n",
le16_to_cpu(lt->stats.version_major), le16_to_cpu(lt->stats.version_minor));
if (lt->has_average_latency_field) {
@@ -276,12 +279,12 @@ static int latency_tracking_is_enable(struct latency_tracker *lt, __u32 * enable
{
struct nvme_get_features_args args_get = {
.args_size = sizeof(args_get),
- .fd = lt->fd,
+ .fd = lt->fd,
+ .uuidx = lt->uuid_index,
.fid = LATENCY_TRACKING_FID,
.nsid = 0,
.sel = 0,
.cdw11 = 0,
- .uuidx = 0,
.data_len = LATENCY_TRACKING_FID_DATA_LEN,
.data = NULL,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
@@ -307,12 +310,12 @@ static int latency_tracking_enable(struct latency_tracker *lt)
struct nvme_set_features_args args_set = {
.args_size = sizeof(args_set),
.fd = lt->fd,
+ .uuidx = lt->uuid_index,
.fid = LATENCY_TRACKING_FID,
.nsid = 0,
.cdw11 = lt->cfg.enable,
.cdw12 = 0,
.save = 0,
- .uuidx = 0,
.cdw15 = 0,
.data_len = LATENCY_TRACKING_FID_DATA_LEN,
.data = NULL,
@@ -328,8 +331,8 @@ static int latency_tracking_enable(struct latency_tracker *lt)
fprintf(stderr, "Command failed while parsing.\n");
} else {
if (lt->print_flags == NORMAL) {
- printf("Successfully set enable bit for FID (0x%X) to %i.\n",
- LATENCY_TRACKING_FID, lt->cfg.enable);
+ printf("Successfully set enable bit for UUID-idx:%d FID:0x%X, to %i.\n",
+ lt->uuid_index, LATENCY_TRACKING_FID, lt->cfg.enable);
}
}
return err;
@@ -356,6 +359,7 @@ static int latency_tracker_get_log(struct latency_tracker *lt)
.log = &lt->stats,
.args_size = sizeof(args),
.fd = lt->fd,
+ .uuidx = lt->uuid_index,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.lid = lt->cfg.write ? WRITE_LOG_ID : READ_LOG_ID,
.len = sizeof(lt->stats),
@@ -363,7 +367,6 @@ static int latency_tracker_get_log(struct latency_tracker *lt)
.csi = NVME_CSI_NVM,
.lsi = NVME_LOG_LSI_NONE,
.lsp = lt->cfg.type,
- .uuidx = NVME_UUID_NONE,
.rae = false,
.ot = false,
};
@@ -390,6 +393,7 @@ int solidigm_get_latency_tracking_log(int argc, char **argv, struct command *cmd
int err;
struct latency_tracker lt = {
+ .uuid_index = 0,
.cfg = {
.output_format = "normal",
},
@@ -433,6 +437,8 @@ int solidigm_get_latency_tracking_log(int argc, char **argv, struct command *cmd
return EINVAL;
}
+ lt.uuid_index = solidigm_get_vu_uuid_index(dev);
+
err = latency_tracking_enable(&lt);
if (err){
dev_close(dev);
@@ -462,8 +468,8 @@ int solidigm_get_latency_tracking_log(int argc, char **argv, struct command *cmd
putchar(enabled);
} else {
printf(
- "Latency Statistics Tracking (FID 0x%X) is currently (%i).\n",
- LATENCY_TRACKING_FID, enabled);
+ "Latency Statistics Tracking (UUID-idx:%d, FID:0x%X) is currently %i.\n",
+ lt.uuid_index, LATENCY_TRACKING_FID, enabled);
}
} else {
fprintf(stderr, "Could not read feature id 0xE2.\n");
diff --git a/plugins/solidigm/solidigm-nvme.c b/plugins/solidigm/solidigm-nvme.c
index b547035..0e42bd6 100644
--- a/plugins/solidigm/solidigm-nvme.c
+++ b/plugins/solidigm/solidigm-nvme.c
@@ -14,7 +14,9 @@
#include "solidigm-garbage-collection.h"
#include "solidigm-latency-tracking.h"
#include "solidigm-telemetry.h"
+
#include "plugins/ocp/ocp-clear-fw-update-history.h"
+#include "plugins/ocp/ocp-smart-extended-log.h"
static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
@@ -37,7 +39,13 @@ static int get_telemetry_log(int argc, char **argv, struct command *cmd, struct
}
static int clear_fw_update_history(int argc, char **argv, struct command *cmd,
- struct plugin *plugin)
+ struct plugin *plugin)
{
return ocp_clear_fw_update_history(argc, argv, cmd, plugin);
}
+
+static int smart_cloud(int argc, char **argv, struct command *cmd,
+ struct plugin *plugin)
+{
+ return ocp_smart_add_log(argc, argv, cmd, plugin);
+}
diff --git a/plugins/solidigm/solidigm-nvme.h b/plugins/solidigm/solidigm-nvme.h
index 778dbf9..1fdc6a6 100644
--- a/plugins/solidigm/solidigm-nvme.h
+++ b/plugins/solidigm/solidigm-nvme.h
@@ -13,11 +13,12 @@
#include "cmd.h"
-#define SOLIDIGM_PLUGIN_VERSION "0.7"
+#define SOLIDIGM_PLUGIN_VERSION "0.8"
PLUGIN(NAME("solidigm", "Solidigm vendor specific extensions", SOLIDIGM_PLUGIN_VERSION),
COMMAND_LIST(
ENTRY("smart-log-add", "Retrieve Solidigm SMART Log", get_additional_smart_log)
+ ENTRY("vs-smart-add-log", "Get SMART / health extended log (redirects to ocp plug-in)", smart_cloud)
ENTRY("garbage-collect-log", "Retrieve Garbage Collection Log", get_garbage_collection_log)
ENTRY("latency-tracking-log", "Enable/Retrieve Latency tracking Log", get_latency_tracking_log)
ENTRY("parse-telemetry-log", "Parse Telemetry Log binary", get_telemetry_log)
diff --git a/plugins/solidigm/solidigm-smart.c b/plugins/solidigm/solidigm-smart.c
index 77c26ac..568d3ab 100644
--- a/plugins/solidigm/solidigm-smart.c
+++ b/plugins/solidigm/solidigm-smart.c
@@ -19,6 +19,7 @@
#include "nvme-print.h"
#include "solidigm-smart.h"
+#include "solidigm-util.h"
struct __attribute__((packed)) nvme_additional_smart_log_item {
__u8 id;
@@ -179,12 +180,13 @@ static void vu_smart_log_show_json(vu_smart_log_t *payload, unsigned int nsid, c
json_free_object(root);
}
-static void vu_smart_log_show(vu_smart_log_t *payload, unsigned int nsid, const char *devname)
+static void vu_smart_log_show(vu_smart_log_t *payload, unsigned int nsid, const char *devname,
+ __u8 uuid_index)
{
smart_log_item_t *item = payload->item;
- printf("Additional Smart Log for NVME device:%s namespace-id:%x\n",
- devname, nsid);
+ printf("Additional Smart Log for NVMe device:%s namespace-id:%x UUID-idx:%d\n",
+ devname, nsid, uuid_index);
printf("ID KEY Normalized Raw\n");
for (int i = 0; i < VU_SMART_MAX_ITEMS; i++) {
@@ -201,6 +203,7 @@ int solidigm_get_additional_smart_log(int argc, char **argv, struct command *cmd
enum nvme_print_flags flags;
struct nvme_dev *dev;
int err;
+ __u8 uuid_index;
struct config {
__u32 namespace_id;
@@ -229,8 +232,27 @@ int solidigm_get_additional_smart_log(int argc, char **argv, struct command *cmd
return flags;
}
- err = nvme_get_log_simple(dev_fd(dev), solidigm_vu_smart_log_id,
- sizeof(smart_log_payload), &smart_log_payload);
+ uuid_index = solidigm_get_vu_uuid_index(dev);
+
+ struct nvme_get_log_args args = {
+ .lpo = 0,
+ .result = NULL,
+ .log = &smart_log_payload,
+ .args_size = sizeof(args),
+ .fd = dev_fd(dev),
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .lid = solidigm_vu_smart_log_id,
+ .len = sizeof(smart_log_payload),
+ .nsid = NVME_NSID_ALL,
+ .csi = NVME_CSI_NVM,
+ .lsi = NVME_LOG_LSI_NONE,
+ .lsp = NVME_LOG_LSP_NONE,
+ .uuidx = uuid_index,
+ .rae = false,
+ .ot = false,
+ };
+
+ err = nvme_get_log(&args);
if (!err) {
if (flags & JSON) {
vu_smart_log_show_json(&smart_log_payload,
@@ -239,7 +261,7 @@ int solidigm_get_additional_smart_log(int argc, char **argv, struct command *cmd
d_raw((unsigned char *)&smart_log_payload, sizeof(smart_log_payload));
} else {
vu_smart_log_show(&smart_log_payload, cfg.namespace_id,
- dev->name);
+ dev->name, uuid_index);
}
} else if (err > 0) {
nvme_show_status(err);
diff --git a/plugins/solidigm/solidigm-telemetry.c b/plugins/solidigm/solidigm-telemetry.c
index 84a4e2a..9946991 100644
--- a/plugins/solidigm/solidigm-telemetry.c
+++ b/plugins/solidigm/solidigm-telemetry.c
@@ -121,7 +121,7 @@ int solidigm_get_telemetry_log(int argc, char **argv, struct command *cmd, struc
cfg.cfg_file, strerror(err));
goto close_fd;
}
- json_tokener * jstok = json_tokener_new();
+ struct json_tokener * jstok = json_tokener_new();
tl.configuration = json_tokener_parse_ex(jstok, conf_str, length);
if (jstok->err != json_tokener_success) {
diff --git a/plugins/solidigm/solidigm-telemetry/cod.c b/plugins/solidigm/solidigm-telemetry/cod.c
index be5685b..7accc53 100644
--- a/plugins/solidigm/solidigm-telemetry/cod.c
+++ b/plugins/solidigm/solidigm-telemetry/cod.c
@@ -110,9 +110,9 @@ void solidigm_telemetry_log_cod_parse(struct telemetry_log *tl)
UNKNOWN = 0xFF,
};
- json_object *telemetry_header = NULL;
- json_object *COD_offset = NULL;
- json_object *reason_id = NULL;
+ struct json_object *telemetry_header = NULL;
+ struct json_object *COD_offset = NULL;
+ struct json_object *reason_id = NULL;
if (!json_object_object_get_ex(tl->root, "telemetryHeader", &telemetry_header))
return;
@@ -144,7 +144,7 @@ void solidigm_telemetry_log_cod_parse(struct telemetry_log *tl)
return;
}
- json_object *cod = json_create_object();
+ struct json_object *cod = json_create_object();
json_object_object_add(tl->root, "cod", cod);
for (int i =0 ; i < data->header.EntryCount; i++) {
diff --git a/plugins/solidigm/solidigm-telemetry/config.c b/plugins/solidigm/solidigm-telemetry/config.c
index 781d786..5111703 100644
--- a/plugins/solidigm/solidigm-telemetry/config.c
+++ b/plugins/solidigm/solidigm-telemetry/config.c
@@ -11,15 +11,15 @@
// max 16 bit unsigned integer nummber 65535
#define MAX_16BIT_NUM_AS_STRING_SIZE 6
-static bool config_get_by_version(const json_object *obj, int version_major,
- int version_minor, json_object **value)
+static bool config_get_by_version(const struct json_object *obj, int version_major,
+ int version_minor, struct json_object **value)
{
char str_key[MAX_16BIT_NUM_AS_STRING_SIZE];
char str_subkey[MAX_16BIT_NUM_AS_STRING_SIZE];
snprintf(str_key, sizeof(str_key), "%d", version_major);
snprintf(str_subkey, sizeof(str_subkey), "%d", version_minor);
- json_object *major_obj = NULL;
+ struct json_object *major_obj = NULL;
if (!json_object_object_get_ex(obj, str_key, &major_obj))
return false;
@@ -28,11 +28,11 @@ static bool config_get_by_version(const json_object *obj, int version_major,
return value != NULL;
}
-bool solidigm_config_get_by_token_version(const json_object *obj, int token_id,
+bool solidigm_config_get_by_token_version(const struct json_object *obj, int token_id,
int version_major, int version_minor,
- json_object **value)
+ struct json_object **value)
{
- json_object *token_obj = NULL;
+ struct json_object *token_obj = NULL;
char str_key[MAX_16BIT_NUM_AS_STRING_SIZE];
snprintf(str_key, sizeof(str_key), "%d", token_id);
diff --git a/plugins/solidigm/solidigm-telemetry/config.h b/plugins/solidigm/solidigm-telemetry/config.h
index bea84fb..30e61ff 100644
--- a/plugins/solidigm/solidigm-telemetry/config.h
+++ b/plugins/solidigm/solidigm-telemetry/config.h
@@ -7,4 +7,7 @@
#include <stdbool.h>
#include "util/json.h"
-bool solidigm_config_get_by_token_version(const json_object *obj, int key, int subkey, int subsubkey, json_object **value);
+bool solidigm_config_get_by_token_version(const struct json_object *obj,
+ int key, int subkey,
+ int subsubkey,
+ struct json_object **value);
diff --git a/plugins/solidigm/solidigm-telemetry/data-area.c b/plugins/solidigm/solidigm-telemetry/data-area.c
index 7233e8f..2f18ea2 100644
--- a/plugins/solidigm/solidigm-telemetry/data-area.c
+++ b/plugins/solidigm/solidigm-telemetry/data-area.c
@@ -17,7 +17,7 @@
static bool telemetry_log_get_value(const struct telemetry_log *tl,
uint32_t offset_bit, uint32_t size_bit,
- bool is_signed, json_object **val_obj)
+ bool is_signed, struct json_object **val_obj)
{
uint32_t offset_bit_from_byte;
uint32_t additional_size_byte;
@@ -77,16 +77,16 @@ static bool telemetry_log_get_value(const struct telemetry_log *tl,
}
static int telemetry_log_structure_parse(const struct telemetry_log *tl,
- json_object *struct_def,
+ struct json_object *struct_def,
size_t parent_offset_bit,
- json_object *output,
- json_object *metadata)
+ struct json_object *output,
+ struct json_object *metadata)
{
- json_object *obj_arraySizeArray = NULL;
- json_object *obj = NULL;
- json_object *obj_memberList;
- json_object *major_dimension;
- json_object *sub_output;
+ struct json_object *obj_arraySizeArray = NULL;
+ struct json_object *obj = NULL;
+ struct json_object *obj_memberList;
+ struct json_object *major_dimension;
+ struct json_object *sub_output;
bool is_enumeration = false;
bool has_member_list;
const char *type = "";
@@ -155,7 +155,7 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl,
uint32_t array_size_dimension[array_rank];
for (size_t i = 0; i < array_rank; i++) {
- json_object *dimension = json_object_array_get_idx(obj_arraySizeArray, i);
+ struct json_object *dimension = json_object_array_get_idx(obj_arraySizeArray, i);
array_size_dimension[i] = json_object_get_uint64(dimension);
major_dimension = dimension;
@@ -163,7 +163,7 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl,
if (array_rank > 1) {
uint32_t linear_pos_per_index = array_size_dimension[0];
uint32_t prev_index_offset_bit = 0;
- json_object *dimension_output;
+ struct json_object *dimension_output;
for (int i = 1; i < (array_rank - 1); i++)
linear_pos_per_index *= array_size_dimension[i];
@@ -182,7 +182,7 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl,
json_object_array_del_idx(obj_arraySizeArray, array_rank - 1, 1);
for (int i = 0 ; i < array_size_dimension[0]; i++) {
- json_object *sub_array = json_create_array();
+ struct json_object *sub_array = json_create_array();
size_t offset;
offset = parent_offset_bit + prev_index_offset_bit;
@@ -213,7 +213,7 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl,
for (uint32_t j = 0; j < array_size_dimension[0]; j++) {
if (is_enumeration || !has_member_list) {
bool is_signed = !strncmp(type, SIGNED_INT_PREFIX, sizeof(SIGNED_INT_PREFIX)-1);
- json_object *val_obj;
+ struct json_object *val_obj;
size_t offset;
offset = parent_offset_bit + offset_bit + linear_array_pos_bit;
@@ -230,7 +230,7 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl,
json_free_object(val_obj);
}
} else {
- json_object *sub_sub_output = json_object_new_object();
+ struct json_object *sub_sub_output = json_create_object();
int num_members;
if (array_size_dimension[0] > 1)
@@ -240,7 +240,7 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl,
num_members = json_object_array_length(obj_memberList);
for (int k = 0; k < num_members; k++) {
- json_object *member = json_object_array_get_idx(obj_memberList, k);
+ struct json_object *member = json_object_array_get_idx(obj_memberList, k);
size_t offset;
offset = parent_offset_bit + offset_bit + linear_array_pos_bit;
@@ -322,8 +322,8 @@ struct telemetry_object_header {
static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl,
enum nvme_telemetry_da da,
- json_object *toc_array,
- json_object *tele_obj_array)
+ struct json_object *toc_array,
+ struct json_object *tele_obj_array)
{
const struct telemetry_object_header *header;
@@ -339,8 +339,8 @@ static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl,
payload = (char *) tl->log;
for (int i = 0; i < toc->header.TableOfContentsCount; i++) {
- json_object *structure_definition = NULL;
- json_object *toc_item;
+ struct json_object *structure_definition = NULL;
+ struct json_object *toc_item;
uint32_t obj_offset;
bool has_struct;
@@ -379,15 +379,15 @@ static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl,
&structure_definition);
if (has_struct) {
- json_object *tele_obj_item = json_create_object();
+ struct json_object *tele_obj_item = json_create_object();
json_object_array_add(tele_obj_array, tele_obj_item);
json_object_get(toc_item);
json_object_add_value_object(tele_obj_item, "metadata", toc_item);
- json_object *parsed_struct = json_object_new_object();
+ struct json_object *parsed_struct = json_create_object();
json_object_add_value_object(tele_obj_item, "objectData", parsed_struct);
- json_object *obj_hasTelemObjHdr = NULL;
+ struct json_object *obj_hasTelemObjHdr = NULL;
uint32_t header_offset = sizeof(const struct telemetry_object_header);
uint32_t file_offset;
@@ -411,8 +411,8 @@ static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl,
int solidigm_telemetry_log_data_areas_parse(const struct telemetry_log *tl,
enum nvme_telemetry_da last_da)
{
- json_object *tele_obj_array = json_create_array();
- json_object *toc_array = json_create_array();
+ struct json_object *tele_obj_array = json_create_array();
+ struct json_object *toc_array = json_create_array();
json_object_add_value_array(tl->root, "tableOfContents", toc_array);
json_object_add_value_array(tl->root, "telemetryObjects", tele_obj_array);
diff --git a/plugins/solidigm/solidigm-telemetry/header.c b/plugins/solidigm/solidigm-telemetry/header.c
index 72b2d97..d085c24 100644
--- a/plugins/solidigm/solidigm-telemetry/header.c
+++ b/plugins/solidigm/solidigm-telemetry/header.c
@@ -63,10 +63,10 @@ static_assert(sizeof(const struct reason_indentifier_1_2) ==
#pragma pack(pop, reason_indentifier)
static void telemetry_log_reason_id_parse1_0_ext(const struct telemetry_log *tl,
- json_object *reason_id)
+ struct json_object *reason_id)
{
const struct reason_indentifier_1_0 *ri;
- json_object *reserved;
+ struct json_object *reserved;
ri = (struct reason_indentifier_1_0 *) tl->log->rsnident;
json_object_object_add(reason_id, "FirmwareVersion", json_object_new_string_len(ri->FirmwareVersion, sizeof(ri->FirmwareVersion)));
@@ -76,16 +76,16 @@ static void telemetry_log_reason_id_parse1_0_ext(const struct telemetry_log *tl,
reserved = json_create_array();
json_object_add_value_array(reason_id, "Reserved", reserved);
for ( int i=0; i < sizeof(ri->Reserved); i++) {
- json_object *val = json_object_new_int(ri->Reserved[i]);
+ struct json_object *val = json_object_new_int(ri->Reserved[i]);
json_object_array_add(reserved, val);
}
}
static void telemetry_log_reason_id_parse1_1_ext(const struct telemetry_log *tl,
- json_object *reason_id)
+ struct json_object *reason_id)
{
const struct reason_indentifier_1_1 *ri;
- json_object *reserved;
+ struct json_object *reserved;
ri = (struct reason_indentifier_1_1 *) tl->log->rsnident;
json_object_object_add(reason_id, "FirmwareVersion", json_object_new_string_len(ri->FirmwareVersion, sizeof(ri->FirmwareVersion)));
@@ -98,17 +98,17 @@ static void telemetry_log_reason_id_parse1_1_ext(const struct telemetry_log *tl,
reserved = json_create_array();
json_object_add_value_array(reason_id, "Reserved", reserved);
for (int i = 0; i < sizeof(ri->Reserved); i++) {
- json_object *val = json_object_new_int(ri->Reserved[i]);
+ struct json_object *val = json_object_new_int(ri->Reserved[i]);
json_object_array_add(reserved, val);
}
}
static void telemetry_log_reason_id_parse1_2_ext(const struct telemetry_log *tl,
- json_object *reason_id)
+ struct json_object *reason_id)
{
const struct reason_indentifier_1_2 *ri;
- json_object *dp_reserved;
- json_object *reserved;
+ struct json_object *dp_reserved;
+ struct json_object *reserved;
ri = (struct reason_indentifier_1_2 *) tl->log->rsnident;
@@ -121,19 +121,19 @@ static void telemetry_log_reason_id_parse1_2_ext(const struct telemetry_log *tl,
reserved = json_create_array();
json_object_add_value_array(reason_id, "Reserved2", reserved);
for (int i = 0; i < sizeof(ri->Reserved2); i++) {
- json_object *val = json_object_new_int(ri->Reserved2[i]);
+ struct json_object *val = json_object_new_int(ri->Reserved2[i]);
json_object_array_add(reserved, val);
}
dp_reserved = json_create_array();
json_object_add_value_array(reason_id, "DualPortReserved", dp_reserved);
for (int i = 0; i < sizeof(ri->DualPortReserved); i++) {
- json_object *val = json_object_new_int(ri->DualPortReserved[i]);
+ struct json_object *val = json_object_new_int(ri->DualPortReserved[i]);
json_object_array_add(dp_reserved, val);
}
}
-static void solidigm_telemetry_log_reason_id_parse(const struct telemetry_log *tl, json_object *reason_id)
+static void solidigm_telemetry_log_reason_id_parse(const struct telemetry_log *tl, struct json_object *reason_id)
{
const struct reason_indentifier_1_0 *ri1_0 =
(struct reason_indentifier_1_0 *) tl->log->rsnident;
@@ -161,9 +161,9 @@ static void solidigm_telemetry_log_reason_id_parse(const struct telemetry_log *t
bool solidigm_telemetry_log_header_parse(const struct telemetry_log *tl)
{
const struct nvme_telemetry_log *log;
- json_object *ieee_oui_id;
- json_object *reason_id;
- json_object *header;
+ struct json_object *ieee_oui_id;
+ struct json_object *reason_id;
+ struct json_object *header;
if (tl->log_size < sizeof(const struct nvme_telemetry_log)) {
SOLIDIGM_LOG_WARNING("Telemetry log too short.");
@@ -180,7 +180,7 @@ bool solidigm_telemetry_log_header_parse(const struct telemetry_log *tl)
json_object_object_add(header, "ieeeOuiIdentifier", ieee_oui_id);
for (int i = 0; i < sizeof(log->ieee); i++) {
- json_object *val = json_object_new_int(log->ieee[i]);
+ struct json_object *val = json_object_new_int(log->ieee[i]);
json_object_array_add(ieee_oui_id, val);
}
diff --git a/plugins/solidigm/solidigm-telemetry/telemetry-log.h b/plugins/solidigm/solidigm-telemetry/telemetry-log.h
index ef4ec5d..e9eff73 100644
--- a/plugins/solidigm/solidigm-telemetry/telemetry-log.h
+++ b/plugins/solidigm/solidigm-telemetry/telemetry-log.h
@@ -24,8 +24,8 @@
struct telemetry_log {
struct nvme_telemetry_log *log;
size_t log_size;
- json_object *root;
- json_object *configuration;
+ struct json_object *root;
+ struct json_object *configuration;
};
-#endif /* _SOLIDIGM_TELEMETRY_LOG_H */ \ No newline at end of file
+#endif /* _SOLIDIGM_TELEMETRY_LOG_H */
diff --git a/plugins/solidigm/solidigm-util.c b/plugins/solidigm/solidigm-util.c
new file mode 100644
index 0000000..0171a49
--- /dev/null
+++ b/plugins/solidigm/solidigm-util.c
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 Solidigm.
+ *
+ * Author: leonardo.da.cunha@solidigm.com
+ */
+
+#include "plugins/ocp/ocp-utils.h"
+#include "solidigm-util.h"
+
+__u8 solidigm_get_vu_uuid_index(struct nvme_dev *dev)
+{
+ int ocp_uuid_index = 0;
+
+ if (ocp_get_uuid_index(dev, &ocp_uuid_index) == 0)
+ if (ocp_uuid_index == 2)
+ return 1;
+
+ return 0;
+}
diff --git a/plugins/solidigm/solidigm-util.h b/plugins/solidigm/solidigm-util.h
new file mode 100644
index 0000000..3a18501
--- /dev/null
+++ b/plugins/solidigm/solidigm-util.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2023 Solidigm.
+ *
+ * Author: leonardo.da.cunha@solidigm.com
+ */
+
+#include "nvme.h"
+
+__u8 solidigm_get_vu_uuid_index(struct nvme_dev *dev);
diff --git a/plugins/wdc/wdc-nvme.c b/plugins/wdc/wdc-nvme.c
index cf185be..2d5d173 100644
--- a/plugins/wdc/wdc-nvme.c
+++ b/plugins/wdc/wdc-nvme.c
@@ -996,10 +996,14 @@ struct __attribute__((__packed__)) wdc_bd_ca_log_format {
__u8 raw_value[8];
};
-#define READ 0
-#define WRITE 1
-#define TRIM 2
-#define RESERVED 3
+#define LATENCY_LOG_BUCKET_READ 3
+#define LATENCY_LOG_BUCKET_WRITE 2
+#define LATENCY_LOG_BUCKET_TRIM 1
+#define LATENCY_LOG_BUCKET_RESERVED 0
+
+#define LATENCY_LOG_MEASURED_LAT_READ 2
+#define LATENCY_LOG_MEASURED_LAT_WRITE 1
+#define LATENCY_LOG_MEASURED_LAT_TRIM 0
struct __attribute__((__packed__)) wdc_ssd_latency_monitor_log {
__u8 feature_status; /* 0x00 */
@@ -1014,7 +1018,7 @@ struct __attribute__((__packed__)) wdc_ssd_latency_monitor_log {
__u8 active_latency_min_window; /* 0x0C */
__u8 rsvd2[0x13]; /* 0x0D */
- __le32 active_bucket_counter[4][4] ; /* 0x20 - 0x5F */
+ __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 */
@@ -4106,19 +4110,21 @@ static int wdc_print_latency_monitor_log_normal(struct nvme_dev *dev,
printf(" Read Write Deallocate/Trim \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]));
+ i, le32_to_cpu(log_data->active_bucket_counter[i][LATENCY_LOG_BUCKET_READ]),
+ le32_to_cpu(log_data->active_bucket_counter[i][LATENCY_LOG_BUCKET_WRITE]),
+ le32_to_cpu(log_data->active_bucket_counter[i][LATENCY_LOG_BUCKET_TRIM]));
}
- for (i = 0; i <= 3; i++) {
+ for (i = 3; i >= 0; 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]));
+ 3-i, le16_to_cpu(log_data->active_measured_latency[i][LATENCY_LOG_MEASURED_LAT_READ]),
+ le16_to_cpu(log_data->active_measured_latency[i][LATENCY_LOG_MEASURED_LAT_WRITE]),
+ le16_to_cpu(log_data->active_measured_latency[i][LATENCY_LOG_MEASURED_LAT_TRIM]));
}
- for (i = 0; i <= 3; i++) {
- printf(" Active Latency Time Stamp: Bucket %d ", i);
- for (j = 0; j <= 2; j++) {
+ for (i = 3; i >= 0; i--) {
+ printf(" Active Latency Time Stamp: Bucket %d ", 3-i);
+ for (j = 2; j >= 0; j--) {
if (le64_to_cpu(log_data->active_latency_timestamp[i][j]) == -1)
printf(" N/A ");
else {
@@ -4131,19 +4137,21 @@ static int wdc_print_latency_monitor_log_normal(struct nvme_dev *dev,
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]));
+ i, le32_to_cpu(log_data->static_bucket_counter[i][LATENCY_LOG_BUCKET_READ]),
+ le32_to_cpu(log_data->static_bucket_counter[i][LATENCY_LOG_BUCKET_WRITE]),
+ le32_to_cpu(log_data->static_bucket_counter[i][LATENCY_LOG_BUCKET_TRIM]));
}
- for (i = 0; i <= 3; i++) {
+ for (i = 3; i >= 0; 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]));
+ 3-i, le16_to_cpu(log_data->static_measured_latency[i][LATENCY_LOG_MEASURED_LAT_READ]),
+ le16_to_cpu(log_data->static_measured_latency[i][LATENCY_LOG_MEASURED_LAT_WRITE]),
+ le16_to_cpu(log_data->static_measured_latency[i][LATENCY_LOG_MEASURED_LAT_TRIM]));
}
- for (i = 0; i <= 3; i++) {
- printf(" Static Latency Time Stamp: Bucket %d ", i);
- for (j = 0; j <= 2; j++) {
+ for (i = 3; i >= 0; i--) {
+ printf(" Static Latency Time Stamp: Bucket %d ", 3-i);
+ for (j = 2; j >= 0; j--) {
if (le64_to_cpu(log_data->static_latency_timestamp[i][j]) == -1)
printf(" N/A ");
else {
@@ -4179,38 +4187,38 @@ static void wdc_print_latency_monitor_log_json(struct wdc_ssd_latency_monitor_lo
json_object_add_value_int(root, "Debug Log Trigger Enable", le16_to_cpu(log_data->debug_log_trigger_enable));
for (i = 0; i <= 3; i++) {
- for (j = 0; j <= 2; j++) {
- sprintf(buf, "Active Bucket Counter: Bucket %d %s", i, operation[j]);
- json_object_add_value_int(root, buf, le32_to_cpu(log_data->active_bucket_counter[i][j]));
+ for (j = 2; j >= 0; j--) {
+ sprintf(buf, "Active Bucket Counter: Bucket %d %s", i, operation[2-j]);
+ json_object_add_value_int(root, buf, le32_to_cpu(log_data->active_bucket_counter[i][j+1]));
}
}
- for (i = 0; i <= 3; i++) {
- for (j = 0; j <= 2; j++) {
- sprintf(buf, "Active Measured Latency: Bucket %d %s", i, operation[j]);
+ for (i = 3; i >= 0; i--) {
+ for (j = 2; j >= 0; j--) {
+ sprintf(buf, "Active Measured Latency: Bucket %d %s", 3-i, operation[2-j]);
json_object_add_value_int(root, buf, le16_to_cpu(log_data->active_measured_latency[i][j]));
}
}
- for (i = 0; i <= 3; i++) {
- for (j = 0; j <= 2; j++) {
- sprintf(buf, "Active Latency Time Stamp: Bucket %d %s", i, operation[j]);
+ for (i = 3; i >= 0; i--) {
+ for (j = 2; j >= 0; j--) {
+ sprintf(buf, "Active Latency Time Stamp: Bucket %d %s", 3-i, operation[2-j]);
json_object_add_value_int(root, buf, le64_to_cpu(log_data->active_latency_timestamp[i][j]));
}
}
for (i = 0; i <= 3; i++) {
- for (j = 0; j <= 2; j++) {
- sprintf(buf, "Static Bucket Counter: Bucket %d %s", i, operation[j]);
- json_object_add_value_int(root, buf, le32_to_cpu(log_data->static_bucket_counter[i][j]));
+ for (j = 2; j >= 0; j--) {
+ sprintf(buf, "Static Bucket Counter: Bucket %d %s", i, operation[2-j]);
+ json_object_add_value_int(root, buf, le32_to_cpu(log_data->static_bucket_counter[i][j+1]));
}
}
- for (i = 0; i <= 3; i++) {
- for (j = 0; j <= 2; j++) {
- sprintf(buf, "Static Measured Latency: Bucket %d %s", i, operation[j]);
+ for (i = 3; i >= 0; i--) {
+ for (j = 2; j >= 0; j--) {
+ sprintf(buf, "Static Measured Latency: Bucket %d %s", 3-i, operation[2-j]);
json_object_add_value_int(root, buf, le16_to_cpu(log_data->static_measured_latency[i][j]));
}
}
- for (i = 0; i <= 3; i++) {
- for (j = 0; j <= 2; j++) {
- sprintf(buf, "Static Latency Time Stamp: Bucket %d %s", i, operation[j]);
+ for (i = 3; i >= 0; i--) {
+ for (j = 2; j >= 0; j--) {
+ sprintf(buf, "Static Latency Time Stamp: Bucket %d %s", 3-i, operation[2-j]);
json_object_add_value_int(root, buf, le64_to_cpu(log_data->static_latency_timestamp[i][j]));
}
}
@@ -10568,7 +10576,7 @@ static int wdc_vs_temperature_stats(int argc, char **argv,
if (ret != 0)
goto out;
- /* convert from Kelvin to degrees Celsius */
+ /* convert from kelvins to degrees Celsius */
temperature = ((smart_log.temperature[1] << 8) | smart_log.temperature[0]) - 273;
/* retrieve HCTM Thermal Management Temperatures */
diff --git a/plugins/wdc/wdc-nvme.h b/plugins/wdc/wdc-nvme.h
index 242cf9a..cdd9615 100644
--- a/plugins/wdc/wdc-nvme.h
+++ b/plugins/wdc/wdc-nvme.h
@@ -5,7 +5,7 @@
#if !defined(WDC_NVME) || defined(CMD_HEADER_MULTI_READ)
#define WDC_NVME
-#define WDC_PLUGIN_VERSION "2.1.2"
+#define WDC_PLUGIN_VERSION "2.3.1"
#include "cmd.h"
PLUGIN(NAME("wdc", "Western Digital vendor specific extensions", WDC_PLUGIN_VERSION),