diff options
Diffstat (limited to '')
-rw-r--r-- | plugins/fdp/fdp.c | 537 | ||||
-rw-r--r-- | plugins/fdp/fdp.h | 24 | ||||
-rw-r--r-- | plugins/inspur/inspur-nvme.c | 235 | ||||
-rw-r--r-- | plugins/inspur/inspur-nvme.h | 18 | ||||
-rw-r--r-- | plugins/inspur/inspur-utils.h | 175 | ||||
-rw-r--r-- | plugins/memblaze/memblaze-nvme.c | 203 | ||||
-rw-r--r-- | plugins/memblaze/memblaze-nvme.h | 7 | ||||
-rw-r--r-- | plugins/memblaze/memblaze-utils.h | 13 | ||||
-rw-r--r-- | plugins/meson.build | 4 | ||||
-rw-r--r-- | plugins/micron/micron-nvme.c | 1 | ||||
-rw-r--r-- | plugins/ocp/meson.build | 6 | ||||
-rw-r--r-- | plugins/ocp/ocp-clear-fw-update-history.c | 73 | ||||
-rw-r--r-- | plugins/ocp/ocp-clear-fw-update-history.h | 9 | ||||
-rw-r--r-- | plugins/ocp/ocp-nvme.c | 7 | ||||
-rw-r--r-- | plugins/ocp/ocp-nvme.h | 11 | ||||
-rw-r--r-- | plugins/ocp/ocp-utils.c | 30 | ||||
-rw-r--r-- | plugins/ocp/ocp-utils.h | 18 | ||||
-rw-r--r-- | plugins/scaleflux/sfx-nvme.c | 2 | ||||
-rw-r--r-- | plugins/solidigm/solidigm-nvme.c | 9 | ||||
-rw-r--r-- | plugins/solidigm/solidigm-nvme.h | 5 |
20 files changed, 1229 insertions, 158 deletions
diff --git a/plugins/fdp/fdp.c b/plugins/fdp/fdp.c new file mode 100644 index 0000000..9fef271 --- /dev/null +++ b/plugins/fdp/fdp.c @@ -0,0 +1,537 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <fcntl.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <inttypes.h> +#include <linux/fs.h> +#include <sys/stat.h> + +#include "common.h" +#include "nvme.h" +#include "libnvme.h" +#include "nvme-print.h" + +#define CREATE_CMD +#include "fdp.h" + +static int fdp_configs(int argc, char **argv, struct command *cmd, + struct plugin *plugin) +{ + const char *desc = "Get Flexible Data Placement Configurations"; + const char *egid = "Endurance group identifier"; + const char *human_readable = "show log in readable format"; + const char *raw = "use binary output"; + + enum nvme_print_flags flags; + struct nvme_dev *dev; + struct nvme_fdp_config_log hdr; + void *log = NULL; + int err; + + struct config { + __u16 egid; + char *output_format; + bool human_readable; + bool raw_binary; + }; + + struct config cfg = { + .egid = 0, + .output_format = "normal", + .raw_binary = false, + }; + + OPT_ARGS(opts) = { + OPT_UINT("endgrp-id", 'e', &cfg.egid, egid), + OPT_FMT("output-format", 'o', &cfg.output_format, output_format), + OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), + OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable), + OPT_END() + }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; + + err = flags = validate_output_format(cfg.output_format); + if (flags < 0) + goto out; + + if (cfg.raw_binary) + flags = BINARY; + + if (cfg.human_readable) + flags |= VERBOSE; + + if (!cfg.egid) { + fprintf(stderr, "endurance group identifier required\n"); + err = -EINVAL; + goto out; + } + + err = nvme_get_log_fdp_configurations(dev->direct.fd, cfg.egid, 0, + sizeof(hdr), &hdr); + if (err) { + nvme_show_status(errno); + goto out; + } + + log = malloc(hdr.size); + if (!log) { + err = -ENOMEM; + goto out; + } + + err = nvme_get_log_fdp_configurations(dev->direct.fd, cfg.egid, 0, + hdr.size, log); + if (err) { + nvme_show_status(errno); + goto out; + } + + nvme_show_fdp_configs(log, hdr.size, flags); + +out: + dev_close(dev); + free(log); + + return err; +} + +static int fdp_usage(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + const char *desc = "Get Flexible Data Placement Reclaim Unit Handle Usage"; + const char *egid = "Endurance group identifier"; + const char *raw = "use binary output"; + + enum nvme_print_flags flags; + struct nvme_dev *dev; + struct nvme_fdp_ruhu_log hdr; + size_t len; + void *log = NULL; + int err; + + struct config { + __u16 egid; + char *output_format; + bool raw_binary; + }; + + struct config cfg = { + .egid = 0, + .output_format = "normal", + .raw_binary = false, + }; + + OPT_ARGS(opts) = { + OPT_UINT("endgrp-id", 'e', &cfg.egid, egid), + OPT_FMT("output-format", 'o', &cfg.output_format, output_format), + OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), + OPT_END() + }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; + + err = flags = validate_output_format(cfg.output_format); + if (flags < 0) + goto out; + + if (cfg.raw_binary) + flags = BINARY; + + err = nvme_get_log_reclaim_unit_handle_usage(dev->direct.fd, cfg.egid, + 0, sizeof(hdr), &hdr); + if (err) { + nvme_show_status(err); + goto out; + } + + len = sizeof(hdr) + le16_to_cpu(hdr.nruh) * sizeof(struct nvme_fdp_ruhu_desc); + log = malloc(len); + if (!log) { + err = -ENOMEM; + goto out; + } + + err = nvme_get_log_reclaim_unit_handle_usage(dev->direct.fd, cfg.egid, + 0, len, log); + if (err) { + nvme_show_status(err); + goto out; + } + + nvme_show_fdp_usage(log, len, flags); + +out: + dev_close(dev); + free(log); + + return err; +} + +static int fdp_stats(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + const char *desc = "Get Flexible Data Placement Statistics"; + const char *egid = "Endurance group identifier"; + const char *raw = "use binary output"; + + enum nvme_print_flags flags; + struct nvme_dev *dev; + struct nvme_fdp_stats_log stats; + int err; + + struct config { + __u16 egid; + char *output_format; + bool raw_binary; + }; + + struct config cfg = { + .egid = 0, + .output_format = "normal", + .raw_binary = false, + }; + + OPT_ARGS(opts) = { + OPT_UINT("endgrp-id", 'e', &cfg.egid, egid), + OPT_FMT("output-format", 'o', &cfg.output_format, output_format), + OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), + OPT_END() + }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; + + err = flags = validate_output_format(cfg.output_format); + if (flags < 0) + goto out; + + if (cfg.raw_binary) + flags = BINARY; + + memset(&stats, 0x0, sizeof(stats)); + + err = nvme_get_log_fdp_stats(dev->direct.fd, cfg.egid, 0, sizeof(stats), &stats); + if (err) { + nvme_show_status(err); + goto out; + } + + nvme_show_fdp_stats(&stats, flags); + +out: + dev_close(dev); + + return err; +} + +static int fdp_events(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + const char *desc = "Get Flexible Data Placement Events"; + const char *egid = "Endurance group identifier"; + const char *host_events = "Get host events"; + const char *raw = "use binary output"; + + enum nvme_print_flags flags; + struct nvme_dev *dev; + struct nvme_fdp_events_log events; + int err; + + struct config { + __u16 egid; + bool host_events; + char *output_format; + bool raw_binary; + }; + + struct config cfg = { + .egid = 0, + .host_events = false, + .output_format = "normal", + .raw_binary = false, + }; + + OPT_ARGS(opts) = { + OPT_UINT("endgrp-id", 'e', &cfg.egid, egid), + OPT_FLAG("host-events", 'E', &cfg.host_events, host_events), + OPT_FMT("output-format", 'o', &cfg.output_format, output_format), + OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), + OPT_END() + }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; + + err = flags = validate_output_format(cfg.output_format); + if (flags < 0) + goto out; + + if (cfg.raw_binary) + flags = BINARY; + + memset(&events, 0x0, sizeof(events)); + + err = nvme_get_log_fdp_events(dev->direct.fd, cfg.egid, + cfg.host_events, 0, sizeof(events), &events); + if (err) { + nvme_show_status(err); + goto out; + } + + nvme_show_fdp_events(&events, flags); + +out: + dev_close(dev); + + return err; +} + +static int fdp_status(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + const char *desc = "Reclaim Unit Handle Status"; + const char *namespace_id = "Namespace identifier"; + const char *raw = "use binary output"; + + enum nvme_print_flags flags; + struct nvme_dev *dev; + struct nvme_fdp_ruh_status hdr; + size_t len; + void *buf = NULL; + int err = -1; + + struct config { + __u32 namespace_id; + char *output_format; + bool raw_binary; + }; + + struct config cfg = { + .output_format = "normal", + .raw_binary = false, + }; + + OPT_ARGS(opts) = { + OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), + OPT_FMT("output-format", 'o', &cfg.output_format, output_format), + OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), + OPT_END() + }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; + + err = flags = validate_output_format(cfg.output_format); + if (flags < 0) + goto out; + + if (cfg.raw_binary) + flags = BINARY; + + if (!cfg.namespace_id) { + err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + if (err < 0) { + perror("get-namespace-id"); + goto out; + } + } + + err = nvme_fdp_reclaim_unit_handle_status(dev_fd(dev), + cfg.namespace_id, sizeof(hdr), &hdr); + if (err) { + nvme_show_status(err); + goto out; + } + + len = le16_to_cpu(hdr.nruhsd) * sizeof(struct nvme_fdp_ruh_status_desc); + buf = malloc(len); + if (!buf) { + err = -ENOMEM; + goto out; + } + + err = nvme_fdp_reclaim_unit_handle_status(dev_fd(dev), + cfg.namespace_id, len, buf); + if (err) { + nvme_show_status(err); + goto out; + } + + nvme_show_fdp_ruh_status(buf, len, flags); + +out: + free(buf); + dev_close(dev); + + return err; +} + +static int fdp_update(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + const char *desc = "Reclaim Unit Handle Update"; + const char *namespace_id = "Namespace identifier"; + const char *_pids = "Comma-separated list of placement identifiers to update"; + + struct nvme_dev *dev; + unsigned short pids[256]; + __u16 buf[256]; + int npids; + int err = -1; + + struct config { + __u32 namespace_id; + char *pids; + }; + + struct config cfg = { + .pids = "", + }; + + OPT_ARGS(opts) = { + OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), + OPT_LIST("pids", 'p', &cfg.pids, _pids), + OPT_END() + }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; + + npids = argconfig_parse_comma_sep_array_short(cfg.pids, pids, ARRAY_SIZE(pids)); + if (npids < 0) { + perror("could not parse pids"); + err = -EINVAL; + goto out; + } else if (npids == 0) { + fprintf(stderr, "no placement identifiers set\n"); + err = -EINVAL; + goto out; + } + + if (!cfg.namespace_id) { + err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + if (err < 0) { + perror("get-namespace-id"); + goto out; + } + } + + for (unsigned int i = 0; i < npids; i++) { + buf[i] = cpu_to_le16(pids[i]); + } + + err = nvme_fdp_reclaim_unit_handle_update(dev_fd(dev), cfg.namespace_id, npids, buf); + if (err) { + nvme_show_status(err); + goto out; + } + + printf("update: Success\n"); + +out: + dev_close(dev); + + return err; +} + +static int fdp_set_events(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + const char *desc = "Enable or disable FDP events"; + const char *namespace_id = "Namespace identifier"; + const char *enable = "Enable/disable event"; + const char *event_types = "Comma-separated list of event types"; + const char *ph = "Placement Handle"; + + struct nvme_dev *dev; + int err = -1; + unsigned short evts[255]; + int nev; + __u8 buf[255]; + + struct config { + __u32 namespace_id; + __u16 ph; + char *event_types; + bool enable; + }; + + struct config cfg = { + .enable = false, + }; + + OPT_ARGS(opts) = { + OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), + OPT_SHRT("placement-handle", 'p', &cfg.ph, ph), + OPT_FLAG("enable", 'e', &cfg.enable, enable), + OPT_LIST("event-types", 't', &cfg.event_types, event_types), + OPT_END() + }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; + + nev = argconfig_parse_comma_sep_array_short(cfg.event_types, evts, ARRAY_SIZE(evts)); + if (nev < 0) { + perror("could not parse event types"); + err = -EINVAL; + goto out; + } else if (nev == 0) { + fprintf(stderr, "no event types set\n"); + err = -EINVAL; + goto out; + } else if (nev > 255) { + fprintf(stderr, "too many event types (max 255)\n"); + err = -EINVAL; + goto out; + } + + if (!cfg.namespace_id) { + err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); + if (err < 0) { + if (errno != ENOTTY) { + fprintf(stderr, "get-namespace-id: %s\n", nvme_strerror(errno)); + goto out; + } + + cfg.namespace_id = NVME_NSID_ALL; + } + } + + for (unsigned int i = 0; i < nev; i++) { + buf[i] = (__u8)evts[i]; + } + + struct nvme_set_features_args args = { + .args_size = sizeof(args), + .fd = dev_fd(dev), + .fid = NVME_FEAT_FID_FDP_EVENTS, + .nsid = cfg.namespace_id, + .cdw11 = (nev << 16) | cfg.ph, + .cdw12 = cfg.enable ? 0x1 : 0x0, + .data_len = sizeof(buf), + .data = buf, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + + err = nvme_set_features(&args); + if (err) { + nvme_show_status(err); + goto out; + } + + printf("set-events: Success\n"); + +out: + dev_close(dev); + + return err; +} diff --git a/plugins/fdp/fdp.h b/plugins/fdp/fdp.h new file mode 100644 index 0000000..f162b32 --- /dev/null +++ b/plugins/fdp/fdp.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#undef CMD_INC_FILE +#define CMD_INC_FILE plugins/fdp/fdp + +#if !defined(FDP_NVME) || defined(CMD_HEADER_MULTI_READ) +#define FDP_NVME + +#include "cmd.h" + +PLUGIN(NAME("fdp", "Manage Flexible Data Placement enabled devices", NVME_VERSION), + COMMAND_LIST( + ENTRY("configs", "List configurations", fdp_configs) + ENTRY("usage", "Show reclaim unit handle usage", fdp_usage) + ENTRY("stats", "Show statistics", fdp_stats) + ENTRY("events", "List events affecting reclaim units and media usage", fdp_events) + ENTRY("status", "Show reclaim unit handle status", fdp_status) + ENTRY("update", "Update a reclaim unit handle", fdp_update) + ENTRY("set-events", "Enabled or disable events", fdp_set_events) + ) +); + +#endif + +#include "define_cmd.h" diff --git a/plugins/inspur/inspur-nvme.c b/plugins/inspur/inspur-nvme.c new file mode 100644 index 0000000..9d7bb4d --- /dev/null +++ b/plugins/inspur/inspur-nvme.c @@ -0,0 +1,235 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <inttypes.h> +#include <errno.h> +#include <limits.h> +#include <fcntl.h> +#include <unistd.h> +#include <dirent.h> +#include <sys/stat.h> + +#include "common.h" +#include "nvme.h" +#include "libnvme.h" +#include "plugin.h" +#include "nvme-print.h" +#include "util/suffix.h" + +#define CREATE_CMD +#include "inspur-nvme.h" +#include "inspur-utils.h" + +void show_r1_vendor_log(r1_cli_vendor_log_t *vendorlog) +{ + int i = 0; + + if (vendorlog->device_state == 0) { + printf("device_state : [healthy]\n"); + } else { + printf("device_state : [warning]\n"); + } + + printf("commit id : %s\n", vendorlog->commit_id); + printf("mcu data id(mcu) : 0x%x\n", le32_to_cpu(vendorlog->mcu_data_id)); + printf("power_info(mcu) : %u mW\n", le32_to_cpu(vendorlog->power_info)); + printf("voltage_info(mcu) : %u mV\n", le32_to_cpu(vendorlog->voltage_info)); + printf("current_info(mcu) : %u mA\n", le32_to_cpu(vendorlog->current_info)); + printf("history max_power(mcu) : %u mW\n", le32_to_cpu(vendorlog->max_power)); + printf("disk_max_temper(mcu) : %d C\n", le32_to_cpu(vendorlog->disk_max_temper) - 273); + printf("disk_overtemper_cout(mcu) : %u\n", le32_to_cpu(vendorlog->disk_overtemper_cout)); + printf("ctrl_max_temper(mcu) : %d C\n", le32_to_cpu(vendorlog->ctrl_max_temper) - 273); + printf("ctrl_overtemper_cout(mcu) : %u\n", le32_to_cpu(vendorlog->ctrl_overtemper_cout)); + printf("nand_max_temper(mcu) : %d C\n", le32_to_cpu(vendorlog->nand_max_temper) - 273); + printf("nand_overtemper_cout(mcu) : %u\n", le32_to_cpu(vendorlog->nand_overtemper_cout)); + + for (i = 0; i < 4; i++) { + printf("temperature[%d](mcu) : %d C\n", i, le32_to_cpu(vendorlog->current_temp[i]) - 273); + } + + printf("CAP Time from 32v to 27v(mcu) : %u ms\n", le32_to_cpu(vendorlog->cap_transtime.cap_trans_time1)); + printf("CAP Time from 27v to 10v(mcu) : %u ms\n", le32_to_cpu(vendorlog->cap_transtime.cap_trans_time2)); + printf("cap_health_state(mcu) : %u\n", le32_to_cpu(vendorlog->cap_health_state)); + printf("warning bit(mcu) : 0x%x%08x\n", le32_to_cpu(vendorlog->detail_warning[1]), + le32_to_cpu(vendorlog->detail_warning[0])); + printf("-->high_format_fail : %x\n", vendorlog->detail_warning_bit.high_format_fail); + printf("-->low_format_fail : %x\n", vendorlog->detail_warning_bit.low_format_fail); + printf("-->current sensor : %x\n", vendorlog->detail_warning_bit.self_test_fail1); + printf("-->nand temp sensor : %x\n", vendorlog->detail_warning_bit.self_test_fail2); + printf("-->board temp sensor : %x\n", vendorlog->detail_warning_bit.self_test_fail3); + printf("-->cntl temp sensor : %x\n", vendorlog->detail_warning_bit.self_test_fail4); + printf("-->cap_timer_test_fail : %x\n", vendorlog->detail_warning_bit.capacitance_test_fail); + printf("-->readOnly_after_rebuild : %x\n", vendorlog->detail_warning_bit.readOnly_after_rebuild); + printf("-->firmware_loss : %x\n", vendorlog->detail_warning_bit.firmware_loss); + printf("-->cap_self_test : %x\n", vendorlog->detail_warning_bit.cap_unsupply); + printf("-->spare_space_warning : %x\n", vendorlog->detail_warning_bit.spare_space_warning); + printf("-->lifetime_warning : %x\n", vendorlog->detail_warning_bit.lifetime_warning); + printf("-->temp_high_warning : %x\n", vendorlog->detail_warning_bit.temp_high_warning); + printf("-->temp_low_warning : %x\n", vendorlog->detail_warning_bit.temp_low_warning); + printf("-->mcu_disable(mcu) : %x\n", vendorlog->detail_warning_bit.mcu_disable); + printf("warning history bit(mcu) : 0x%x%08x\n", le32_to_cpu(vendorlog->detail_warning_his[1]), + le32_to_cpu(vendorlog->detail_warning_his[0])); + printf("-->high_format_fail : %x\n", vendorlog->detail_warning_his_bit.high_format_fail); + printf("-->low_format_fail : %x\n", vendorlog->detail_warning_his_bit.low_format_fail); + printf("-->current sensor : %x\n", vendorlog->detail_warning_his_bit.self_test_fail1); + printf("-->nand temp sensor : %x\n", vendorlog->detail_warning_his_bit.self_test_fail2); + printf("-->board temp sensor : %x\n", vendorlog->detail_warning_his_bit.self_test_fail3); + printf("-->cntl temp sensor : %x\n", vendorlog->detail_warning_his_bit.self_test_fail4); + printf("-->cap_timer_test_fail : %x\n", vendorlog->detail_warning_his_bit.capacitance_test_fail); + printf("-->readOnly_after_rebuild : %x\n", vendorlog->detail_warning_his_bit.readOnly_after_rebuild); + printf("-->firmware_loss : %x\n", vendorlog->detail_warning_his_bit.firmware_loss); + printf("-->cap_self_test : %x\n", vendorlog->detail_warning_his_bit.cap_unsupply); + printf("-->spare_space_warning : %x\n", vendorlog->detail_warning_his_bit.spare_space_warning); + printf("-->lifetime_warning : %x\n", vendorlog->detail_warning_his_bit.lifetime_warning); + printf("-->temp_high_warning : %x\n", vendorlog->detail_warning_his_bit.temp_high_warning); + printf("-->temp_low_warning : %x\n", vendorlog->detail_warning_his_bit.temp_low_warning); + printf("-->mcu_disable(mcu) : %x\n", vendorlog->detail_warning_his_bit.mcu_disable); + + for (i = 0; i < 4; i++) { + printf("[%d]nand_bytes_written : %" PRIu64 " GB\n", i, le64_to_cpu(vendorlog->nand_bytes_written[i])); + } + + for (i = 0; i < 4; i++) { + printf("[%d]io_apptag_err : %u\n", i, le32_to_cpu(vendorlog->io_err[i].io_apptag_err)); + printf("[%d]io_guard_err : %u\n", i, le32_to_cpu(vendorlog->io_err[i].io_guard_err)); + printf("[%d]io_reftag_err : %u\n", i, le32_to_cpu(vendorlog->io_err[i].io_reftag_err)); + printf("[%d]io_read_fail_cout : %u\n", i, le32_to_cpu(vendorlog->io_err[i].io_read_fail_cout)); + printf("[%d]io_write_fail_cout : %u\n", i, le32_to_cpu(vendorlog->io_err[i].io_write_fail_cout)); + printf("[%d]io_dma_disable_err : %u\n", i, le32_to_cpu(vendorlog->io_err[i].io_dma_disable_err)); + printf("[%d]io_dma_fatal_err : %u\n", i, le32_to_cpu(vendorlog->io_err[i].io_dma_fatal_err)); + printf("[%d]io_dma_linkdown_err : %u\n", i, le32_to_cpu(vendorlog->io_err[i].io_dma_linkdown_err)); + printf("[%d]io_dma_timeout_err : %u\n", i, le32_to_cpu(vendorlog->io_err[i].io_dma_timeout_err)); + printf("[%d]lba_err[0] : %u\n", i, le32_to_cpu(vendorlog->io_err[i].lba_err[0])); + printf("[%d]lba_err[1] : %u\n", i, le32_to_cpu(vendorlog->io_err[i].lba_err[1])); + printf("[%d]lba_err[2] : %u\n", i, le32_to_cpu(vendorlog->io_err[i].lba_err[2])); + printf("[%d]lba_err[3] : %u\n", i, le32_to_cpu(vendorlog->io_err[i].lba_err[3])); + printf("[%d]lba_err[4] : %u\n", i, le32_to_cpu(vendorlog->io_err[i].lba_err[4])); + printf("[%d]lba_err[5] : %u\n", i, le32_to_cpu(vendorlog->io_err[i].lba_err[5])); + } + + printf("temp_throttle_per : %u\n", le32_to_cpu(vendorlog->temp_throttle_per)); + printf("port0_flreset_cnt : %" PRIu64 "\n", le64_to_cpu(vendorlog->port0_fundamental_reset_cnt)); + printf("port0_hot_reset_cnt : %" PRIu64 "\n", le64_to_cpu(vendorlog->port0_hot_reset_cnt)); + printf("port0_func_reset_cnt : %" PRIu64 "\n", le64_to_cpu(vendorlog->port0_func_reset_cnt)); + printf("port0_linkdown_cnt : %" PRIu64 "\n", le64_to_cpu(vendorlog->port0_linkdown_cnt)); + printf("port0_ctrl_reset_cnt : %" PRIu64 "\n", le64_to_cpu(vendorlog->port0_ctrl_reset_cnt)); + printf("ces_RcvErr_cnt : %u\n", le32_to_cpu(vendorlog->ces_RcvErr_cnt)); + printf("ces_BadTlp_cnt : %u\n", le32_to_cpu(vendorlog->ces_BadTlp_cnt)); + printf("ces_BadDllp_cnt : %u\n", le32_to_cpu(vendorlog->ces_BadDllp_cnt)); + printf("ces_Rplyover_cnt : %u\n", le32_to_cpu(vendorlog->ces_Rplyover_cnt)); + printf("ces_RplyTo_cnt : %u\n", le32_to_cpu(vendorlog->ces_RplyTo_cnt)); + printf("ces_Hlo_cnt : %u\n", le32_to_cpu(vendorlog->ces_Hlo_cnt)); + printf("scan doorbell err cnt : %u\n", le32_to_cpu(vendorlog->scan_db_err_cnt)); + printf("doorbell interrupt err cnt : %u\n", le32_to_cpu(vendorlog->db_int_err_cnt)); + + printf("------------ncm-----------------------\n"); + for (i = 0; i < 4; i++) { + printf("------------part%d-----------------------\n", i); + printf("[%d]nand_rd_unc_count : %u\n", i, + le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].nand_rd_unc_cnt)); + printf("[%d]nand_rd_srr_count : %u\n", i, + le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].nand_rd_srr_cnt)); + printf("[%d]nand_rd_sdecode_count : %u\n", i, + le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].nand_rd_soft_decode_cnt)); + printf("[%d]nand_rd_rb_fail_count : %u\n", i, + le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].nand_rd_rebuild_fail_cnt)); + printf("[%d]nand_prg_fail_count : %u\n", i, + le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].nand_prg_fail_cnt)); + printf("[%d]nand_eras_fail_count : %u\n", i, + le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].nand_eras_fail_cnt)); + printf("[%d]nand_rd_count : %" PRIu64 "\n", i, + le64_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].nand_rd_cnt)); + printf("[%d]nand_prg_count : %" PRIu64 "\n", i, + le64_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].nand_prg_cnt)); + printf("[%d]nand_eras_count : %" PRIu64 "\n", i, + le64_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].nand_eras_cnt)); + printf("[%d]BE_scan_unc_count : %u\n", i, + le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].BE_scan_unc_cnt)); + printf("[%d]rebuild_req_cnt : %u\n", i, + le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].rebuild_req_cnt)); + printf("[%d]retry_req_cnt : %u\n", i, + le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].retry_req_cnt)); + printf("[%d]retry_success_cnt : %u\n", i, + le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].retry_success_cnt)); + printf("[%d]prg_badblk_num : %u\n", i, + le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].prg_badblk_num)); + printf("[%d]eras_badblk_num : %u\n", i, + le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].eras_badblk_num)); + printf("[%d]read_badblk_num : %u\n", i, + le32_to_cpu(vendorlog->vendor_log_nandctl_cnt[i].unc_badblk_num)); + } + + printf("[%d]temp_ctrl_limit_count : %u\n", i, le32_to_cpu(vendorlog->temp_ctrl_limit_cnt)); + printf("[%d]temp_ctrl_stop_count : %u\n", i, le32_to_cpu(vendorlog->temp_ctrl_stop_cnt)); + printf("------------wlm-----------------------\n"); + for (i = 0; i < 4; i++) { + printf("------------part%d-----------------------\n", i); + printf("[%d]fbb_count : %u\n", i, + le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].fbb_count)); + printf("[%d]ebb_count : %u\n", i, + le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].ebb_count)); + printf("[%d]lbb_count : %u\n", i, + le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].lbb_count)); + printf("[%d]gc_read_count : %u\n", i, + le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].gc_read_count)); + printf("[%d]gc_write_count : %u\n", i, + le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].gc_write_count)); + printf("[%d]gc_write_fail_count : %u\n", i, + le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].gc_write_fail_count)); + printf("[%d]force_gc_count : %u\n", i, + le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].force_gc_count)); + printf("[%d]avg_pe_count : %u\n", i, + le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].avg_pe_count)); + printf("[%d]max_pe_count : %u\n", i, + le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].max_pe_count)); + printf("[%d]free_blk_num1 : %u\n", i, + le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].free_blk_num1)); + printf("[%d]free_blk_num2 : %u\n", i, + le32_to_cpu(vendorlog->wearlvl_vendor_log_count[i].free_blk_num2)); + } + + printf("------------lkm-----------------------\n"); + printf("[%d]e2e_check_err_count1 : %u\n", i, le32_to_cpu(vendorlog->e2e_check_err_cnt1)); + printf("[%d]e2e_check_err_count2 : %u\n", i, le32_to_cpu(vendorlog->e2e_check_err_cnt2)); + printf("[%d]e2e_check_err_count3 : %u\n", i, le32_to_cpu(vendorlog->e2e_check_err_cnt3)); + printf("[%d]e2e_check_err_count4 : %u\n", i, le32_to_cpu(vendorlog->e2e_check_err_cnt4)); +} + +void show_r1_media_err_log(r1_cli_vendor_log_t *vendorlog) +{ + int i, j; + + for (i = 0; i < 4; i++) { + printf("DM%d read err lba:\n", i); + for (j = 0; j < 10; j++) { + printf("[%d]lba : %" PRIu64 "\n", j, le64_to_cpu(vendorlog->media_err[i].lba_err[j])); + } + } +} + +static int nvme_get_vendor_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + __u8 local_mem[BYTE_OF_4K]; + char *desc = "Get the Inspur vendor log"; + struct nvme_dev *dev; + int err; + + OPT_ARGS(opts) = { OPT_END() }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + 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); + 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); + } else { + nvme_show_status(err); + } + + dev_close(dev); + return err; +} diff --git a/plugins/inspur/inspur-nvme.h b/plugins/inspur/inspur-nvme.h new file mode 100644 index 0000000..14a5e76 --- /dev/null +++ b/plugins/inspur/inspur-nvme.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#undef CMD_INC_FILE +#define CMD_INC_FILE plugins/inspur/inspur-nvme + +#if !defined(INSPUR_NVME) || defined(CMD_HEADER_MULTI_READ) +#define INSPUR_NVME + +#include "cmd.h" + +PLUGIN(NAME("inspur", "Inspur vendor specific extensions", NVME_VERSION), + COMMAND_LIST( + ENTRY("nvme-vendor-log", "Retrieve Inspur Vendor Log, show it", nvme_get_vendor_log) + ) +); + +#endif + +#include "define_cmd.h" diff --git a/plugins/inspur/inspur-utils.h b/plugins/inspur/inspur-utils.h new file mode 100644 index 0000000..d411bf0 --- /dev/null +++ b/plugins/inspur/inspur-utils.h @@ -0,0 +1,175 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef __INSPUR_UTILS_H__ +#define __INSPUR_UTILS_H__ + +#define BYTE_OF_64K 65536UL +#define BYTE_OF_32K 32768UL +#define BYTE_OF_16K 16384UL +#define BYTE_OF_4K 4096UL +#define BYTE_OF_512 512UL +#define BYTE_OF_256 256UL +#define BYTE_OF_128 128UL + +/* Inspur specific LOG_PAGE_ID */ +typedef enum { + VENDOR_SMART_LOG_PAGE = 0xc0, +} vendor_sepc_log_page_id_e; + +#pragma pack(push, 1) +typedef struct r1_am_cap_transtime { + __u32 cap_trans_time1 : 16; + __u32 cap_trans_time2 : 16; +} r1_cap_transtime_t; + +typedef struct vendor_warning_bit { + __u32 high_format_fail : 1; + __u32 low_format_fail : 1; + __u32 rebuild_fail1 : 1; + __u32 rebuild_fail2 : 1; + __u32 rebuild_fail3 : 1; + __u32 rebuild_fail4 : 1; + __u32 rebuild_fail5 : 1; + __u32 rebuild_fail6 : 1; + __u32 self_test_fail1 : 1; + __u32 self_test_fail2 : 1; + __u32 self_test_fail3 : 1; + __u32 self_test_fail4 : 1; + __u32 internal_err1 : 1; + __u32 internal_err2 : 1; + __u32 internal_err3 : 1; + __u32 internal_err4 : 1; + __u32 internal_err5 : 1; + __u32 internal_err6 : 1; + __u32 internal_err7 : 1; + __u32 internal_err8 : 1; + __u32 internal_err9 : 1; + __u32 internal_err10 : 1; + __u32 internal_err11 : 1; + __u32 internal_err12 : 1; + __u32 internal_err13 : 1; + __u32 internal_err14 : 1; + __u32 internal_err15 : 1; + __u32 internal_err16 : 1; + __u32 capacitance_test_fail : 1; + __u32 IO_read_fail : 1; + __u32 IO_write_fail : 1; + __u32 readOnly_after_rebuild : 1; + __u32 firmware_loss : 1; + __u32 cap_unsupply : 1; + __u32 spare_space_warning : 1; + __u32 lifetime_warning : 1; + __u32 temp_high_warning : 1; + __u32 temp_low_warning : 1; + __u32 mcu_disable : 1; + __u32 rsv : 25; +} vendor_warning_str; + +typedef struct r1_vendor_log_ncm_cout { + __u32 nand_rd_unc_cnt; + __u32 nand_rd_srr_cnt; + __u32 nand_rd_soft_decode_cnt; + __u32 nand_rd_rebuild_fail_cnt; + __u32 nand_prg_fail_cnt; + __u32 nand_eras_fail_cnt; + __u64 nand_rd_cnt; + __u64 nand_prg_cnt; + __u64 nand_eras_cnt; + __u32 BE_scan_unc_cnt; + __u32 rebuild_req_cnt; + __u16 retry_req_cnt; + __u16 retry_success_cnt; + __u32 prg_badblk_num; + __u32 eras_badblk_num; + __u32 unc_badblk_num; +} r1_vendor_log_nandctl_count_t; + +typedef struct r1_wearlvl_vendor_log_count { + __u32 fbb_count; + __u32 ebb_count; + __u32 lbb_count; + __u32 gc_read_count; + __u32 gc_write_count; + __u32 gc_write_fail_count; + __u32 force_gc_count; + __u32 avg_pe_count; + __u32 max_pe_count; + __u32 free_blk_num1; + __u32 free_blk_num2; +} r1_wearlvl_vendor_log_count_t; + +typedef struct vendor_media_err { + __u64 lba_err[10]; +} vendor_media_err_t; + +typedef struct r1_vendor_log_io_err { + __u32 io_guard_err; + __u32 io_apptag_err; + __u32 io_reftag_err; + __u32 io_dma_linkdown_err; + __u32 io_dma_disable_err; + __u32 io_dma_timeout_err; + __u32 io_dma_fatal_err; + __u32 io_write_fail_cout; + __u32 io_read_fail_cout; + __u32 lba_err[6]; +} r1_vendor_log_io_err_t; + +typedef struct r1_vendor_log_s { + __u32 max_power; + __u32 disk_max_temper; + __u32 disk_overtemper_cout; + __u32 ctrl_max_temper; + __u32 ctrl_overtemper_cout; + r1_cap_transtime_t cap_transtime; + __u32 cap_health_state; + __u32 device_state; + r1_vendor_log_io_err_t io_err[4]; + union { + vendor_warning_str detail_warning_bit; + __u32 detail_warning[2]; + }; + union { + vendor_warning_str detail_warning_his_bit; + __u32 detail_warning_his[2]; + }; + __u32 ddr_bit_err_cout; + __u32 temp_throttle_per; + __u64 port0_fundamental_reset_cnt; + __u64 port0_hot_reset_cnt; + __u64 port0_func_reset_cnt; + __u64 port0_linkdown_cnt; + __u64 port0_ctrl_reset_cnt; + __u64 nand_bytes_written[4]; + __u32 power_info; + __u32 voltage_info; + __u32 current_info; + __u32 current_temp[4]; + __u32 nand_max_temper; + __u32 nand_overtemper_cout; + __u32 mcu_data_id; + __u8 commit_id[16]; + __u32 ces_RcvErr_cnt; + __u32 ces_BadTlp_cnt; + __u32 ces_BadDllp_cnt; + __u32 ces_Rplyover_cnt; + __u32 ces_RplyTo_cnt; + __u32 ces_Hlo_cnt; + __u32 scan_db_err_cnt; + __u32 db_int_err_cnt; + __u8 rsvFE[56]; + r1_vendor_log_nandctl_count_t vendor_log_nandctl_cnt[4]; + __u32 temp_ctrl_limit_cnt; + __u32 temp_ctrl_stop_cnt; + __u8 rsvncm[216]; + r1_wearlvl_vendor_log_count_t wearlvl_vendor_log_count[4]; + __u8 rsvwlm[512 - sizeof(r1_wearlvl_vendor_log_count_t) * 4 % 512]; + __u32 e2e_check_err_cnt1; + __u32 e2e_check_err_cnt2; + __u32 e2e_check_err_cnt3; + __u32 e2e_check_err_cnt4; + vendor_media_err_t media_err[4]; + __u8 rsvlkm[176]; +} r1_cli_vendor_log_t; +#pragma pack(pop) + +#endif // __INSPUR_UTILS_H__ diff --git a/plugins/memblaze/memblaze-nvme.c b/plugins/memblaze/memblaze-nvme.c index 6fdd675..fb46841 100644 --- a/plugins/memblaze/memblaze-nvme.c +++ b/plugins/memblaze/memblaze-nvme.c @@ -3,10 +3,12 @@ #include <errno.h> #include <stdio.h> #include <stdlib.h> +#include <sys/stat.h> #include <unistd.h> #include <time.h> #include "nvme.h" +#include "common.h" #include "libnvme.h" #include "plugin.h" #include "linux/types.h" @@ -105,51 +107,7 @@ static __u64 raw_2_u64(const __u8 *buf, size_t len) return le64_to_cpu(val); } -#define STRN2_01 "Additional Smart Log for NVME device" -#define STRN2_02 "namespace-id" -#define STRN1_01 "key" -#define STRN1_02 "normalized" -#define STRN1_03 "raw" -#define STR00_01 "program_fail_count" -#define STR01_01 "erase_fail_count" -#define STR02_01 "wear_leveling" -#define STR02_03 "min: " -#define STR02_04 ", max: " -#define STR02_05 ", avg: " -#define STR03_01 "end_to_end_error_detection_count" -#define STR04_01 "crc_error_count" -#define STR05_01 "timed_workload_media_wear" -#define STR06_01 "timed_workload_host_reads" -#define STR07_01 "timed_workload_timer" -#define STR07_02 " min" -#define STR08_01 "thermal_throttle_status" -#define STR08_02 ", cnt: " -#define STR09_01 "retry_buffer_overflow_count" -#define STR10_01 "pll_lock_loss_count" -#define STR11_01 "nand_bytes_written" -#define STR11_03 "sectors: " -#define STR12_01 "host_bytes_written" -#define STR12_03 "sectors: " -#define STR13_01 "system_area_life_left" -#define STR14_01 "total_read" -#define STR15_01 "tempt_since_born" -#define STR15_03 "max: " -#define STR15_04 ", min: " -#define STR15_05 ", curr: " -#define STR16_01 "power_consumption" -#define STR16_03 "max: " -#define STR16_04 ", min: " -#define STR16_05 ", curr: " -#define STR17_01 "tempt_since_bootup" -#define STR17_03 "max: " -#define STR17_04 ", min: " -#define STR17_05 ", curr: " -#define STR18_01 "power_loss_protection" -#define STR19_01 "read_fail_count" -#define STR20_01 "thermal_throttle_time" -#define STR21_01 "flash_media_error" - -static void get_memblaze_new_smart_info(struct nvme_p4_smart_log *smart, int index, u8 *nm_val, u8 *raw_val) +static void get_memblaze_new_smart_info(struct nvme_p4_smart_log *smart, int index, __u8 *nm_val, __u8 *raw_val) { memcpy(nm_val, smart->itemArr[index].nmVal, NM_SIZE); memcpy(raw_val, smart->itemArr[index].rawVal, RAW_SIZE); @@ -159,8 +117,8 @@ static void show_memblaze_smart_log_new(struct nvme_memblaze_smart_log *s, unsigned int nsid, const char *devname) { struct nvme_p4_smart_log *smart = (struct nvme_p4_smart_log *)s; - u8 *nm = malloc(NM_SIZE * sizeof(u8)); - u8 *raw = malloc(RAW_SIZE * sizeof(u8)); + __u8 *nm = malloc(NM_SIZE * sizeof(__u8)); + __u8 *raw = malloc(RAW_SIZE * sizeof(__u8)); if (!nm) { if (raw) @@ -171,79 +129,77 @@ static void show_memblaze_smart_log_new(struct nvme_memblaze_smart_log *s, free(nm); return; } - /* Table Title */ - printf("%s:%s %s:%x\n", STRN2_01, devname, STRN2_02, nsid); - /* Clumn Name*/ - printf("%-34s%-11s%s\n", STRN1_01, STRN1_02, STRN1_03); - /* 00 RAISIN_SI_VD_PROGRAM_FAIL */ + + printf("%s:%s %s:%x\n", "Additional Smart Log for NVME device", devname, "namespace-id", nsid); + printf("%-34s%-11s%s\n", "key", "normalized", "raw"); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_PROGRAM_FAIL, nm, raw); - printf("%-32s: %3d%% %"PRIu64"\n", STR00_01, *nm, int48_to_long(raw)); - /* 01 RAISIN_SI_VD_ERASE_FAIL */ + printf("%-32s: %3d%% %"PRIu64"\n", "program_fail_count", *nm, int48_to_long(raw)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_ERASE_FAIL, nm, raw); - printf("%-32s: %3d%% %"PRIu64"\n", STR01_01, *nm, int48_to_long(raw)); - /* 02 RAISIN_SI_VD_WEARLEVELING_COUNT */ + printf("%-32s: %3d%% %"PRIu64"\n", "erase_fail_count", *nm, int48_to_long(raw)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_WEARLEVELING_COUNT, nm, raw); - printf("%-31s : %3d%% %s%u%s%u%s%u\n", STR02_01, *nm, - STR02_03, *raw, STR02_04, *(raw+2), STR02_05, *(raw+4)); - /* 03 RAISIN_SI_VD_E2E_DECTECTION_COUNT */ + printf("%-31s : %3d%% %s%u%s%u%s%u\n", "wear_leveling", *nm, + "min: ", *(__u16 *)raw, ", max: ", *(__u16 *)(raw+2), ", avg: ", *(__u16 *)(raw+4)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_E2E_DECTECTION_COUNT, nm, raw); - printf("%-31s: %3d%% %"PRIu64"\n", STR03_01, *nm, int48_to_long(raw)); - /* 04 RAISIN_SI_VD_PCIE_CRC_ERR_COUNT */ + printf("%-31s: %3d%% %"PRIu64"\n", "end_to_end_error_detection_count", *nm, int48_to_long(raw)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_PCIE_CRC_ERR_COUNT, nm, raw); - printf("%-32s: %3d%% %"PRIu64"\n", STR04_01, *nm, int48_to_long(raw)); - /* 05 RAISIN_SI_VD_TIMED_WORKLOAD_MEDIA_WEAR */ + printf("%-32s: %3d%% %"PRIu64"\n", "crc_error_count", *nm, int48_to_long(raw)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_TIMED_WORKLOAD_MEDIA_WEAR, nm, raw); - printf("%-32s: %3d%% %.3f%%\n", STR05_01, *nm, ((float)int48_to_long(raw))/1000); - /* 06 RAISIN_SI_VD_TIMED_WORKLOAD_HOST_READ */ + printf("%-32s: %3d%% %.3f%%\n", "timed_workload_media_wear", *nm, ((float)int48_to_long(raw))/1000); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_TIMED_WORKLOAD_HOST_READ, nm, raw); - printf("%-32s: %3d%% %"PRIu64"%%\n", STR06_01, *nm, int48_to_long(raw)); - /* 07 RAISIN_SI_VD_TIMED_WORKLOAD_TIMER */ + printf("%-32s: %3d%% %"PRIu64"%%\n", "timed_workload_host_reads", *nm, int48_to_long(raw)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_TIMED_WORKLOAD_TIMER, nm, raw); - printf("%-32s: %3d%% %"PRIu64"%s\n", STR07_01, *nm, int48_to_long(raw), STR07_02); - /* 08 RAISIN_SI_VD_THERMAL_THROTTLE_STATUS */ + printf("%-32s: %3d%% %"PRIu64"%s\n", "timed_workload_timer", *nm, int48_to_long(raw), " min"); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_THERMAL_THROTTLE_STATUS, nm, raw); - printf("%-32s: %3d%% %"PRIu64"%%%s%"PRIu64"\n", STR08_01, *nm, - int48_to_long(raw), STR08_02, int48_to_long(raw+1)); - /* 09 RAISIN_SI_VD_RETRY_BUFF_OVERFLOW_COUNT */ + printf("%-32s: %3d%% %u%%%s%"PRIu64"\n", "thermal_throttle_status", *nm, + *raw, ", cnt: ", int48_to_long(raw+1)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_RETRY_BUFF_OVERFLOW_COUNT, nm, raw); - printf("%-32s: %3d%% %"PRIu64"\n", STR09_01, *nm, int48_to_long(raw)); - /* 10 RAISIN_SI_VD_PLL_LOCK_LOSS_COUNT */ + printf("%-32s: %3d%% %"PRIu64"\n", "retry_buffer_overflow_count", *nm, int48_to_long(raw)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_PLL_LOCK_LOSS_COUNT, nm, raw); - printf("%-32s: %3d%% %"PRIu64"\n", STR10_01, *nm, int48_to_long(raw)); - /* 11 RAISIN_SI_VD_TOTAL_WRITE */ + printf("%-32s: %3d%% %"PRIu64"\n", "pll_lock_loss_count", *nm, int48_to_long(raw)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_TOTAL_WRITE, nm, raw); - printf("%-32s: %3d%% %s%"PRIu64"\n", STR11_01, *nm, STR11_03, int48_to_long(raw)); - /* 12 RAISIN_SI_VD_HOST_WRITE */ + printf("%-32s: %3d%% %s%"PRIu64"\n", "nand_bytes_written", *nm, "sectors: ", int48_to_long(raw)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_HOST_WRITE, nm, raw); - printf("%-32s: %3d%% %s%"PRIu64"\n", STR12_01, *nm, STR12_03, int48_to_long(raw)); - /* 13 RAISIN_SI_VD_SYSTEM_AREA_LIFE_LEFT */ + printf("%-32s: %3d%% %s%"PRIu64"\n", "host_bytes_written", *nm, "sectors: ", int48_to_long(raw)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_SYSTEM_AREA_LIFE_LEFT, nm, raw); - printf("%-32s: %3d%% %"PRIu64"\n", STR13_01, *nm, int48_to_long(raw)); - /* 14 RAISIN_SI_VD_TOTAL_READ */ + printf("%-32s: %3d%% %"PRIu64"\n", "system_area_life_left", *nm, int48_to_long(raw)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_TOTAL_READ, nm, raw); - printf("%-32s: %3d%% %"PRIu64"\n", STR14_01, *nm, int48_to_long(raw)); - /* 15 RAISIN_SI_VD_TEMPT_SINCE_BORN */ + printf("%-32s: %3d%% %"PRIu64"\n", "total_read", *nm, int48_to_long(raw)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_TEMPT_SINCE_BORN, nm, raw); - printf("%-32s: %3d%% %s%u%s%u%s%u\n", STR15_01, *nm, - STR15_03, *raw, STR15_04, *(raw+2), STR15_05, *(raw+4)); - /* 16 RAISIN_SI_VD_POWER_CONSUMPTION */ + printf("%-32s: %3d%% %s%u%s%u%s%u\n", "tempt_since_born", *nm, + "max: ", *(__u16 *)raw, ", min: ", *(__u16 *)(raw+2), ", curr: ", *(__u16 *)(raw+4)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_POWER_CONSUMPTION, nm, raw); - printf("%-32s: %3d%% %s%u%s%u%s%u\n", STR16_01, *nm, - STR16_03, *raw, STR16_04, *(raw+2), STR16_05, *(raw+4)); - /* 17 RAISIN_SI_VD_TEMPT_SINCE_BOOTUP */ + printf("%-32s: %3d%% %s%u%s%u%s%u\n", "power_consumption", *nm, + "max: ", *(__u16 *)raw, ", min: ", *(__u16 *)(raw+2), ", curr: ", *(__u16 *)(raw+4)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_TEMPT_SINCE_BOOTUP, nm, raw); - printf("%-32s: %3d%% %s%u%s%u%s%u\n", STR17_01, *nm, STR17_03, *raw, - STR17_04, *(raw+2), STR17_05, *(raw+4)); - /* 18 RAISIN_SI_VD_POWER_LOSS_PROTECTION */ - /* 19 RAISIN_SI_VD_READ_FAIL */ + printf("%-32s: %3d%% %s%u%s%u%s%u\n", "tempt_since_bootup", *nm, "max: ", *(__u16 *)raw, + ", min: ", *(__u16 *)(raw+2), ", curr: ", *(__u16 *)(raw+4)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_READ_FAIL, nm, raw); - printf("%-32s: %3d%% %"PRIu64"\n", STR19_01, *nm, int48_to_long(raw)); - /* 20 RAISIN_SI_VD_THERMAL_THROTTLE_TIME */ + printf("%-32s: %3d%% %"PRIu64"\n", "read_fail_count", *nm, int48_to_long(raw)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_THERMAL_THROTTLE_TIME, nm, raw); - printf("%-32s: %3d%% %"PRIu64"\n", STR20_01, *nm, int48_to_long(raw)); - /* 21 RAISIN_SI_VD_FLASH_MEDIA_ERROR */ + printf("%-32s: %3d%% %"PRIu64"\n", "thermal_throttle_time", *nm, int48_to_long(raw)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_FLASH_MEDIA_ERROR, nm, raw); - printf("%-32s: %3d%% %"PRIu64"\n", STR21_01, *nm, int48_to_long(raw)); + printf("%-32s: %3d%% %"PRIu64"\n", "flash_media_error", *nm, int48_to_long(raw)); free(nm); free(raw); @@ -349,8 +305,8 @@ static void show_memblaze_smart_log_old(struct nvme_memblaze_smart_log *smart, if ( IS_PAPAYA(fw_ver_local) ) { struct nvme_p4_smart_log *s = (struct nvme_p4_smart_log *)smart; - u8 *nm = malloc(NM_SIZE * sizeof(u8)); - u8 *raw = malloc(RAW_SIZE * sizeof(u8)); + __u8 *nm = malloc(NM_SIZE * sizeof(__u8)); + __u8 *raw = malloc(RAW_SIZE * sizeof(__u8)); if (!nm) { if (raw) @@ -361,26 +317,25 @@ static void show_memblaze_smart_log_old(struct nvme_memblaze_smart_log *smart, free(nm); return; } - /* 00 RAISIN_SI_VD_PROGRAM_FAIL */ get_memblaze_new_smart_info(s, PROGRAM_FAIL, nm, raw); printf("%-32s : %3d%% %"PRIu64"\n", - STR00_01, *nm, int48_to_long(raw)); - /* 01 RAISIN_SI_VD_ERASE_FAIL */ + "program_fail_count", *nm, int48_to_long(raw)); + get_memblaze_new_smart_info(s, ERASE_FAIL, nm, raw); printf("%-32s : %3d%% %"PRIu64"\n", - STR01_01, *nm, int48_to_long(raw)); - /* 02 RAISIN_SI_VD_WEARLEVELING_COUNT */ + "erase_fail_count", *nm, int48_to_long(raw)); + get_memblaze_new_smart_info(s, WEARLEVELING_COUNT, nm, raw); printf("%-31s : %3d%% %s%u%s%u%s%u\n", - STR02_01, *nm, STR02_03, *raw, STR02_04, *(raw+2), STR02_05, *(raw+4)); - /* 11 RAISIN_SI_VD_TOTAL_WRITE */ + "wear_leveling", *nm, "min: ", *(__u16 *)raw, ", max: ", *(__u16 *)(raw+2), ", avg: ", *(__u16 *)(raw+4)); + get_memblaze_new_smart_info(s, TOTAL_WRITE, nm, raw); printf("%-32s : %3d%% %"PRIu64"\n", - STR11_01, *nm, 32*int48_to_long(raw)); - /* 12 RAISIN_SI_VD_HOST_WRITE */ + "nand_bytes_written", *nm, 32*int48_to_long(raw)); + get_memblaze_new_smart_info(s, HOST_WRITE, nm, raw); printf("%-32s : %3d%% %"PRIu64"\n", - STR12_01, *nm, 32*int48_to_long(raw)); + "host_bytes_written", *nm, 32*int48_to_long(raw)); free(nm); free(raw); @@ -602,7 +557,7 @@ static int mb_set_powermanager_status(int argc, char **argv, struct command *cmd printf("set-feature:%02x (%s), value:%#08x\n", cfg.feature_id, mb_feature_to_string(cfg.feature_id), cfg.value); } else if (err > 0) - nvme_show_status(err); + nvme_show_status(err); dev_close(dev); return err; @@ -679,7 +634,7 @@ static int mb_set_high_latency_log(int argc, char **argv, struct command *cmd, s printf("set-feature:0x%02X (%s), value:%#08x\n", cfg.feature_id, mb_feature_to_string(cfg.feature_id), cfg.value); } else if (err > 0) - nvme_show_status(err); + nvme_show_status(err); dev_close(dev); return err; @@ -817,7 +772,6 @@ static int mb_high_latency_log_print(int argc, char **argv, struct command *cmd, return err; } - static int memblaze_fw_commit(int fd, int select) { struct nvme_passthru_cmd cmd = { @@ -1095,22 +1049,18 @@ static int mb_lat_stats_log_print(int argc, char **argv, struct command *cmd, st io_latency_histogram(cfg.write ? f2 : f1, stats, DO_PRINT_FLAG, cfg.write ? GLP_ID_VU_GET_WRITE_LATENCY_HISTOGRAM : GLP_ID_VU_GET_READ_LATENCY_HISTOGRAM); else - nvme_show_status(err); + nvme_show_status(err); dev_close(dev); return err; } -#define OP 0xFC -#define FID 0x68 static int memblaze_clear_error_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { char *desc = "Clear Memblaze devices error log."; struct nvme_dev *dev; int err; - //const char *value = "new value of feature (required)"; - //const char *save = "specifies that the controller shall save the attribute"; __u32 result; struct config { @@ -1157,20 +1107,6 @@ static int memblaze_clear_error_log(int argc, char **argv, struct command *cmd, } else if (err > 0) nvme_show_status(err); -/* - struct nvme_admin_cmd admin_cmd = { - .opcode = OP, - .cdw10 = FID, - }; - - err = nvme_submit_admin_passthru(fd, &admin_cmd); - - if (!err) { - printf("OP(0x%2X) FID(0x%2X) Clear error log success.\n", OP, FID); - } else { - printf("NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); - }; -*/ dev_close(dev); return err; } @@ -1289,4 +1225,3 @@ static int mb_set_lat_stats(int argc, char **argv, dev_close(dev); return err; } - diff --git a/plugins/memblaze/memblaze-nvme.h b/plugins/memblaze/memblaze-nvme.h index 87314c6..e214ca6 100644 --- a/plugins/memblaze/memblaze-nvme.h +++ b/plugins/memblaze/memblaze-nvme.h @@ -6,12 +6,6 @@ #define MEMBLAZE_NVME #include "cmd.h" -#include "common.h" - -#include <ctype.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> PLUGIN(NAME("memblaze", "Memblaze vendor specific extensions", NVME_VERSION), COMMAND_LIST( @@ -30,4 +24,3 @@ PLUGIN(NAME("memblaze", "Memblaze vendor specific extensions", NVME_VERSION), #endif #include "define_cmd.h" - diff --git a/plugins/memblaze/memblaze-utils.h b/plugins/memblaze/memblaze-utils.h index 84263f3..f64a115 100644 --- a/plugins/memblaze/memblaze-utils.h +++ b/plugins/memblaze/memblaze-utils.h @@ -9,8 +9,6 @@ #define NM_SIZE 2 #define RAW_SIZE 7 -typedef unsigned char u8; - // Intel Format & new format /* Raisin Additional smart external ID */ #define RAISIN_SI_VD_PROGRAM_FAIL_ID 0xAB @@ -135,18 +133,18 @@ struct nvme_memblaze_smart_log_item { struct nvme_memblaze_smart_log { struct nvme_memblaze_smart_log_item items[NR_SMART_ITEMS]; - u8 resv[SMART_INFO_OLD_SIZE - sizeof(struct nvme_memblaze_smart_log_item) * NR_SMART_ITEMS]; + __u8 resv[SMART_INFO_OLD_SIZE - sizeof(struct nvme_memblaze_smart_log_item) * NR_SMART_ITEMS]; }; // Intel Format & new format struct nvme_p4_smart_log_item { /* Item identifier */ - u8 id[ID_SIZE]; + __u8 id[ID_SIZE]; /* Normalized value or percentage. In the range from 0 to 100. */ - u8 nmVal[NM_SIZE]; + __u8 nmVal[NM_SIZE]; /* raw value */ - u8 rawVal[RAW_SIZE]; + __u8 rawVal[RAW_SIZE]; }; struct nvme_p4_smart_log @@ -158,7 +156,7 @@ struct nvme_p4_smart_log * because micron's getlogpage request,the size of many commands have changed to 4k. * request size > user malloc size,casuing parameters that are closed in momery are dirty. */ - u8 resv[SMART_INFO_NEW_SIZE - sizeof(struct nvme_p4_smart_log_item) * NR_SMART_ITEMS]; + __u8 resv[SMART_INFO_NEW_SIZE - sizeof(struct nvme_p4_smart_log_item) * NR_SMART_ITEMS]; }; // base @@ -221,4 +219,3 @@ struct nvme_p4_smart_log } #endif // __MEMBLAZE_UTILS_H__ - diff --git a/plugins/meson.build b/plugins/meson.build index b3af39b..c92b208 100644 --- a/plugins/meson.build +++ b/plugins/meson.build @@ -22,6 +22,8 @@ sources += [ 'plugins/wdc/wdc-nvme.c', 'plugins/ymtc/ymtc-nvme.c', 'plugins/zns/zns.c', - 'plugins/ocp/ocp-nvme.c', + 'plugins/inspur/inspur-nvme.c', + 'plugins/fdp/fdp.c', ] subdir('solidigm') +subdir('ocp') diff --git a/plugins/micron/micron-nvme.c b/plugins/micron/micron-nvme.c index e6f3a8c..3c0904c 100644 --- a/plugins/micron/micron-nvme.c +++ b/plugins/micron/micron-nvme.c @@ -3168,7 +3168,6 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, if (telemetry_option) { if ((ctrl.lpa & 0x8) != 0x8) { printf("telemetry option is not supported for specified drive\n"); - dev_close(dev); goto out; } int logSize = 0; __u8 *buffer = NULL; const char *dir = "."; diff --git a/plugins/ocp/meson.build b/plugins/ocp/meson.build new file mode 100644 index 0000000..a4e5d20 --- /dev/null +++ b/plugins/ocp/meson.build @@ -0,0 +1,6 @@ +sources += [ + 'plugins/ocp/ocp-utils.c', + 'plugins/ocp/ocp-nvme.c', + 'plugins/ocp/ocp-clear-fw-update-history.c', +] + diff --git a/plugins/ocp/ocp-clear-fw-update-history.c b/plugins/ocp/ocp-clear-fw-update-history.c new file mode 100644 index 0000000..fef09cf --- /dev/null +++ b/plugins/ocp/ocp-clear-fw-update-history.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022 Solidigm. + * + * Authors: haro.panosyan@solidigm.com + * leonardo.da.cunha@solidigm.com + */ + +#include <unistd.h> +#include "ocp-utils.h" +#include "nvme-print.h" + +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; +} diff --git a/plugins/ocp/ocp-clear-fw-update-history.h b/plugins/ocp/ocp-clear-fw-update-history.h new file mode 100644 index 0000000..25fb6b1 --- /dev/null +++ b/plugins/ocp/ocp-clear-fw-update-history.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (c) 2022 Solidigm. + * + * Authors: haro.panosyan@solidigm.com + * leonardo.da.cunha@solidigm.com + */ + +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 5cbf6cb..14a5f30 100644 --- a/plugins/ocp/ocp-nvme.c +++ b/plugins/ocp/ocp-nvme.c @@ -22,6 +22,7 @@ #include "linux/types.h" #include "util/types.h" #include "nvme-print.h" +#include "ocp-clear-fw-update-history.h" #define CREATE_CMD #include "ocp-nvme.h" @@ -765,3 +766,9 @@ static int ocp_latency_monitor_log(int argc, char **argv, struct command *comman dev_close(dev); return ret; } + +static int clear_fw_update_history(int argc, char **argv, struct command *cmd, + struct plugin *plugin) +{ + return ocp_clear_fw_update_history(argc, argv, cmd, plugin); +} diff --git a/plugins/ocp/ocp-nvme.h b/plugins/ocp/ocp-nvme.h index 3e3f437..c20646a 100644 --- a/plugins/ocp/ocp-nvme.h +++ b/plugins/ocp/ocp-nvme.h @@ -14,10 +14,13 @@ #include "cmd.h" PLUGIN(NAME("ocp", "OCP cloud SSD extensions", NVME_VERSION), - COMMAND_LIST( - ENTRY("smart-add-log", "Retrieve extended SMART Information", ocp_smart_add_log) - ENTRY("latency-monitor-log", "Get Latency Monitor Log Page", ocp_latency_monitor_log) - ) + 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) + ) ); #endif diff --git a/plugins/ocp/ocp-utils.c b/plugins/ocp/ocp-utils.c new file mode 100644 index 0000000..9294c05 --- /dev/null +++ b/plugins/ocp/ocp-utils.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022 Solidigm. + * + * Author: leonardo.da.cunha@solidigm.com + */ + +#include "ocp-utils.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 }; + +int ocp_get_uuid_index(struct nvme_dev *dev, int *index) +{ + struct nvme_id_uuid_list uuid_list; + int err = nvme_identify_uuid(dev_fd(dev), &uuid_list); + + *index = 0; + if (err) + return err; + + for (int i = 0; i < NVME_ID_UUID_LIST_MAX; i++) { + if (memcmp(ocp_uuid, &uuid_list.entry[i].uuid, NVME_UUID_LEN) == 0) { + *index = i + 1; + break; + } + } + return err; +} diff --git a/plugins/ocp/ocp-utils.h b/plugins/ocp/ocp-utils.h new file mode 100644 index 0000000..44d0af4 --- /dev/null +++ b/plugins/ocp/ocp-utils.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (c) 2022 Solidigm. + * + * Author: leonardo.da.cunha@solidigm.com + */ + +#include "nvme.h" + +/** + * ocp_get_uuid_index() - Get OCP UUID index + * @dev: nvme device + * @index: integer ponter to here to save the index + * @result: The command completion result from CQE dword0 + * + * 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); diff --git a/plugins/scaleflux/sfx-nvme.c b/plugins/scaleflux/sfx-nvme.c index a776664..4bcfbf6 100644 --- a/plugins/scaleflux/sfx-nvme.c +++ b/plugins/scaleflux/sfx-nvme.c @@ -659,7 +659,7 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct } } else { printf("ScaleFlux IO %s Command Latency Statistics Invalid Version Maj %d Min %d\n", - write ? "Write" : "Read", stats.ver.maj, stats.ver.min); + cfg.write ? "Write" : "Read", stats.ver.maj, stats.ver.min); } } else if (err > 0) nvme_show_status(err); diff --git a/plugins/solidigm/solidigm-nvme.c b/plugins/solidigm/solidigm-nvme.c index 684648a..b547035 100644 --- a/plugins/solidigm/solidigm-nvme.c +++ b/plugins/solidigm/solidigm-nvme.c @@ -14,6 +14,7 @@ #include "solidigm-garbage-collection.h" #include "solidigm-latency-tracking.h" #include "solidigm-telemetry.h" +#include "plugins/ocp/ocp-clear-fw-update-history.h" static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { @@ -33,4 +34,10 @@ static int get_latency_tracking_log(int argc, char **argv, struct command *cmd, static int get_telemetry_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { return solidigm_get_telemetry_log(argc, argv, cmd, plugin); -}
\ No newline at end of file +} + +static int clear_fw_update_history(int argc, char **argv, struct command *cmd, + struct plugin *plugin) +{ + return ocp_clear_fw_update_history(argc, argv, cmd, plugin); +} diff --git a/plugins/solidigm/solidigm-nvme.h b/plugins/solidigm/solidigm-nvme.h index ed48400..778dbf9 100644 --- a/plugins/solidigm/solidigm-nvme.h +++ b/plugins/solidigm/solidigm-nvme.h @@ -13,7 +13,7 @@ #include "cmd.h" -#define SOLIDIGM_PLUGIN_VERSION "0.6" +#define SOLIDIGM_PLUGIN_VERSION "0.7" PLUGIN(NAME("solidigm", "Solidigm vendor specific extensions", SOLIDIGM_PLUGIN_VERSION), COMMAND_LIST( @@ -21,6 +21,9 @@ PLUGIN(NAME("solidigm", "Solidigm vendor specific extensions", SOLIDIGM_PLUGIN_V 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) + ENTRY("clear-fw-activate-history", + "Clear firmware update history log (redirects to ocp plug-in)", + clear_fw_update_history) ) ); |