diff options
Diffstat (limited to '')
57 files changed, 12368 insertions, 8521 deletions
diff --git a/plugins/amzn/amzn-nvme.c b/plugins/amzn/amzn-nvme.c index e04aa53..d359cc3 100644 --- a/plugins/amzn/amzn-nvme.c +++ b/plugins/amzn/amzn-nvme.c @@ -28,15 +28,15 @@ static void json_amzn_id_ctrl(struct nvme_vu_id_ctrl_field *id, static void amzn_id_ctrl(__u8 *vs, struct json_object *root) { - struct nvme_vu_id_ctrl_field* id = (struct nvme_vu_id_ctrl_field *)vs; + struct nvme_vu_id_ctrl_field *id = (struct nvme_vu_id_ctrl_field *)vs; char bdev[32] = { 0 }; int len = 0; + while (len < 31) { - if (id->bdev[++len] == ' ') { + if (id->bdev[++len] == ' ') break; - } } snprintf(bdev, len+1, "%s", id->bdev); diff --git a/plugins/dera/dera-nvme.c b/plugins/dera/dera-nvme.c index 9408e50..ca4b53d 100644 --- a/plugins/dera/dera-nvme.c +++ b/plugins/dera/dera-nvme.c @@ -104,13 +104,12 @@ static int nvme_dera_get_device_status(int fd, enum dera_device_status *result) .addr = (__u64)(uintptr_t)NULL, .data_len = 0, .cdw10 = 0, - .cdw12 = 0x104, + .cdw12 = 0x104, }; err = nvme_submit_admin_passthru(fd, &cmd, NULL); - if (!err && result) { + if (!err && result) *result = cmd.result; - } return err; } @@ -130,13 +129,12 @@ static int get_status(int argc, char **argv, struct command *cmd, struct plugin err = parse_and_open(&dev, argc, argv, desc, opts); if (err) return err; - + err = nvme_get_log_simple(dev_fd(dev), 0xc0, sizeof(log), &log); - if (err) { + if (err) goto exit; - } - const char* dev_status[] = { + static const char *dev_status[] = { "Normal", "Quick Rebuilding", "Full Rebuilding", @@ -148,25 +146,22 @@ static int get_status(int argc, char **argv, struct command *cmd, struct plugin "Firmware Committing", "Over Temperature" }; - const char *volt_status[] = { + static const char *volt_status[] = { "Normal", "Initial Low", "Runtime Low", }; err = nvme_dera_get_device_status(dev_fd(dev), &state); - if (!err){ - if (state > 0 && state < 4){ + if (!err) { + if (state > 0 && state < 4) printf("device_status : %s %d%% completed\n", dev_status[state], log.rebuild_percent); - } - else{ + else printf("device_status : %s\n", dev_status[state]); - } - } - else { + } else { goto exit; } - + printf("dev_status_up : %s\n", dev_status[log.dev_status_up]); printf("cap_aged : %s\n", log.cap_aged == 1 ? "True" : "False"); printf("cap_aged_ratio : %d%%\n", log.cap_aged_ratio < 100 ? log.cap_aged_ratio : 100); @@ -188,12 +183,10 @@ static int get_status(int argc, char **argv, struct command *cmd, struct plugin printf("fw_loader_version : %.*s\n", 8, log.fw_loader_version); printf("uefi_driver_version : %.*s\n", 8, log.uefi_driver_version); - if (log.pcie_volt_status < sizeof(volt_status) / sizeof(const char *)){ + if (log.pcie_volt_status < sizeof(volt_status) / sizeof(const char *)) printf("pcie_volt_status : %s\n", volt_status[log.pcie_volt_status]); - } - else{ + else printf("pcie_volt_status : Unknown\n"); - } printf("current_pcie_volt : %d mV\n", log.current_pcie_volt[1] << 8 | log.current_pcie_volt[0]); printf("init_pcie_volt_low_cnt : %d\n", log.init_pcie_volt_low[1] << 8 | log.init_pcie_volt_low[0]); diff --git a/plugins/fdp/fdp.c b/plugins/fdp/fdp.c index 1e292e8..8539e18 100644 --- a/plugins/fdp/fdp.c +++ b/plugins/fdp/fdp.c @@ -121,7 +121,7 @@ static int fdp_usage(int argc, char **argv, struct command *cmd, struct plugin * }; struct config cfg = { - .egid = 0, + .egid = 0, .output_format = "normal", .raw_binary = false, }; @@ -192,7 +192,7 @@ static int fdp_stats(int argc, char **argv, struct command *cmd, struct plugin * }; struct config cfg = { - .egid = 0, + .egid = 0, .output_format = "normal", .raw_binary = false, }; @@ -251,8 +251,8 @@ static int fdp_events(int argc, char **argv, struct command *cmd, struct plugin }; struct config cfg = { - .egid = 0, - .host_events = false, + .egid = 0, + .host_events = false, .output_format = "normal", .raw_binary = false, }; @@ -424,9 +424,8 @@ static int fdp_update(int argc, char **argv, struct command *cmd, struct plugin } } - for (unsigned int i = 0; i < npids; i++) { + 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) { @@ -449,6 +448,7 @@ static int fdp_set_events(int argc, char **argv, struct command *cmd, struct plu const char *enable = "Enable/disable event"; const char *event_types = "Comma-separated list of event types"; const char *ph = "Placement Handle"; + const char *save = "specifies that the controller shall save the attribute"; struct nvme_dev *dev; int err = -1; @@ -458,19 +458,22 @@ static int fdp_set_events(int argc, char **argv, struct command *cmd, struct plu struct config { __u32 namespace_id; - __u16 ph; - char *event_types; - bool enable; + __u16 ph; + char *event_types; + bool enable; + bool save; }; struct config cfg = { - .enable = false, + .enable = false, + .save = 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_FLAG("save", 's', &cfg.save, save), OPT_LIST("event-types", 't', &cfg.event_types, event_types), OPT_END() }; @@ -506,14 +509,14 @@ static int fdp_set_events(int argc, char **argv, struct command *cmd, struct plu } } - for (unsigned int i = 0; i < nev; i++) { + 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, + .save = cfg.save, .nsid = cfg.namespace_id, .cdw11 = (nev << 16) | cfg.ph, .cdw12 = cfg.enable ? 0x1 : 0x0, diff --git a/plugins/huawei/huawei-nvme.c b/plugins/huawei/huawei-nvme.c index 572086c..82e190f 100644 --- a/plugins/huawei/huawei-nvme.c +++ b/plugins/huawei/huawei-nvme.c @@ -47,9 +47,9 @@ struct huawei_list_item { char node[1024]; struct nvme_id_ctrl ctrl; - unsigned nsid; + unsigned int nsid; struct nvme_id_ns ns; - unsigned block; + unsigned int block; char ns_name[NS_NAME_LEN]; char array_name[ARRAY_NAME_LEN]; bool huawei_device; @@ -98,23 +98,19 @@ static int huawei_get_nvme_info(int fd, struct huawei_list_item *item, const cha item->block = S_ISBLK(nvme_stat_info.st_mode); if (item->ns.vs[0] == 0) { - len = snprintf(item->ns_name, NS_NAME_LEN, "%s", "----"); if (len < 0) return -EINVAL; - } - else { + } else { memcpy(item->ns_name, item->ns.vs, NS_NAME_LEN); item->ns_name[NS_NAME_LEN - 1] = '\0'; } if (item->ctrl.vs[0] == 0) { - len = snprintf(item->array_name, ARRAY_NAME_LEN, "%s", "----"); - if (len < 0) + if (len < 0) return -EINVAL; - } - else { + } else { memcpy(item->array_name, item->ctrl.vs, ARRAY_NAME_LEN); item->array_name[ARRAY_NAME_LEN - 1] = '\0'; } @@ -123,9 +119,8 @@ static int huawei_get_nvme_info(int fd, struct huawei_list_item *item, const cha static void format(char *formatter, size_t fmt_sz, char *tofmt, size_t tofmtsz) { + fmt_sz = snprintf(formatter, fmt_sz, "%-*.*s", (int)tofmtsz, (int)tofmtsz, tofmt); - fmt_sz = snprintf(formatter,fmt_sz, "%-*.*s", - (int)tofmtsz, (int)tofmtsz, tofmt); /* trim() the obnoxious trailing white lines */ while (fmt_sz) { if (formatter[fmt_sz - 1] != ' ' && formatter[fmt_sz - 1] != '\0') { @@ -137,7 +132,7 @@ static void format(char *formatter, size_t fmt_sz, char *tofmt, size_t tofmtsz) } static void huawei_json_print_list_items(struct huawei_list_item *list_items, - unsigned len) + unsigned int len) { struct json_object *root; struct json_object *devices; @@ -210,8 +205,9 @@ static void huawei_print_list_item(struct huawei_list_item *list_item, struct huawei_list_element_len element_len) { __u8 lba_index; + nvme_id_ns_flbas_to_lbaf_inuse(list_item->ns.flbas, &lba_index); - unsigned long long int lba = 1ULL << list_item->ns.lbaf[lba_index].ds; + unsigned long long lba = 1ULL << list_item->ns.lbaf[lba_index].ds; double nsze = le64_to_cpu(list_item->ns.nsze) * lba; double nuse = le64_to_cpu(list_item->ns.nuse) * lba; @@ -223,8 +219,7 @@ static void huawei_print_list_item(struct huawei_list_item *list_item, char *nguid = nguid_buf; int i; - sprintf(usage,"%6.2f %2sB / %6.2f %2sB", nuse, u_suffix, - nsze, s_suffix); + sprintf(usage, "%6.2f %2sB / %6.2f %2sB", nuse, u_suffix, nsze, s_suffix); memset(nguid, 0, sizeof(nguid_buf)); for (i = 0; i < sizeof(list_item->ns.nguid); i++) @@ -247,37 +242,37 @@ static unsigned int choose_len(unsigned int old_len, unsigned int cur_len, unsig temp_len = (cur_len > default_len) ? cur_len : default_len; if (temp_len > old_len) - { return temp_len; - } return old_len; } -static unsigned int huawei_get_ns_len(struct huawei_list_item *list_items, unsigned len, unsigned default_len) +static unsigned int huawei_get_ns_len(struct huawei_list_item *list_items, unsigned int len, + unsigned int default_len) { int i; unsigned int min_len = default_len; for (i = 0 ; i < len ; i++) - min_len = choose_len(min_len , strlen(list_items->ns_name), default_len); + min_len = choose_len(min_len, strlen(list_items->ns_name), default_len); return min_len; } -static int huawei_get_array_len(struct huawei_list_item *list_items, unsigned len, unsigned default_len) +static int huawei_get_array_len(struct huawei_list_item *list_items, unsigned int len, + unsigned int default_len) { int i; int min_len = default_len; for (i = 0 ; i < len ; i++) - min_len = choose_len(min_len , strlen(list_items->array_name), default_len); + min_len = choose_len(min_len, strlen(list_items->array_name), default_len); return min_len; } -static void huawei_print_list_items(struct huawei_list_item *list_items, unsigned len) +static void huawei_print_list_items(struct huawei_list_item *list_items, unsigned int len) { - unsigned i; + unsigned int i; struct huawei_list_element_len element_len; element_len.node = 16; @@ -350,13 +345,12 @@ static int huawei_list(int argc, char **argv, struct command *command, close(fd); goto out_free_list_items; } - if (list_items[huawei_num].huawei_device == true) { + if (list_items[huawei_num].huawei_device == true) huawei_num++; - } close(fd); } - if (huawei_num > 0){ + if (huawei_num > 0) { if (fmt == JSON) huawei_json_print_list_items(list_items, huawei_num); else diff --git a/plugins/innogrit/innogrit-nvme.c b/plugins/innogrit/innogrit-nvme.c index 1771538..cd47efa 100644 --- a/plugins/innogrit/innogrit-nvme.c +++ b/plugins/innogrit/innogrit-nvme.c @@ -146,11 +146,13 @@ static int nvme_vucmd(int fd, unsigned char opcode, unsigned int cdw12, memset(&cmd, 0, sizeof(cmd)); cmd.opcode = opcode; + cmd.cdw2 = IGVSC_SIG; + cmd.cdw10 = data_len / 4; cmd.cdw12 = cdw12; cmd.cdw13 = cdw13; cmd.cdw14 = cdw14; cmd.cdw15 = cdw15; - cmd.nsid = 0; + cmd.nsid = 0xffffffff; cmd.addr = (__u64)(__u64)(uintptr_t)data; cmd.data_len = data_len; return nvme_submit_admin_passthru(fd, &cmd, NULL); @@ -198,8 +200,8 @@ static int innogrit_vsc_geteventlog(int argc, char **argv, ret = nvme_vucmd(dev_fd(dev), 0xFE, 0x82, 0x03, 0x00, 0x00, (char *)data, 4096); if (ret == -1) return ret; - - if (data[0] == 0x5A) + + if (data[0] == 0x5A) ivsctype = 1; else ivsctype = 0; @@ -227,8 +229,9 @@ static int innogrit_vsc_geteventlog(int argc, char **argv, icount++; memset(data, 0, 4096); - if (ivsctype == 1) - ret = nvme_vucmd(dev_fd(dev), 0xFE, 0x60, 0x00, 0x00, 0x00,(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), @@ -345,10 +348,10 @@ static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command, 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); + 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, @@ -403,12 +406,13 @@ static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command, for (icur = 0; icur < itotal; icur += 4096) { memset(data, 0, 4096); if (busevsc) { - if (ivsctype == 1) - ret = nvme_vucmd(dev_fd(dev), 0xFE, 0x82, 0x08, 0x00, 0x00,(char *)data, 4096); + 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); + (char *)data, 4096); } else { ret = nvme_get_nsid_log(dev_fd(dev), true, 0x07, @@ -429,12 +433,13 @@ static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command, if (ipackindex != ipackcount) { memset(data, 0, 4096); if (busevsc) { - if (ivsctype == 1) - ret = nvme_vucmd(dev_fd(dev), 0xFE, 0x82, 0x08, 0x00, 0x00,(char *)data, 4096); + 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); + (char *)data, 4096); } else { ret = nvme_get_nsid_log(dev_fd(dev), true, 0x07, diff --git a/plugins/innogrit/typedef.h b/plugins/innogrit/typedef.h index a97a008..f2a59b4 100644 --- a/plugins/innogrit/typedef.h +++ b/plugins/innogrit/typedef.h @@ -7,6 +7,7 @@ #define NVME_VSC_GET 0xE6 #define VSC_FN_GET_CDUMP 0x08 #define EVLOG_SIG 0x65766C67 +#define IGVSC_SIG 0x69677673 #define SRB_SIGNATURE 0x544952474F4E4E49ULL #define XCLEAN_LINE "\033[K" diff --git a/plugins/inspur/inspur-nvme.c b/plugins/inspur/inspur-nvme.c index 8c929aa..cda3507 100644 --- a/plugins/inspur/inspur-nvme.c +++ b/plugins/inspur/inspur-nvme.c @@ -23,215 +23,211 @@ 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)); + 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])); - } - } + 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), - (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); - } else { - nvme_show_status(err); - } - - dev_close(dev); - return err; + __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), + (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); + } else { + nvme_show_status(err); + } + + dev_close(dev); + return err; } diff --git a/plugins/intel/intel-nvme.c b/plugins/intel/intel-nvme.c index 8a29cf9..e62c85d 100644 --- a/plugins/intel/intel-nvme.c +++ b/plugins/intel/intel-nvme.c @@ -16,25 +16,25 @@ #define CREATE_CMD #include "intel-nvme.h" -struct __attribute__((packed)) nvme_additional_smart_log_item { +struct __packed nvme_additional_smart_log_item { __u8 key; __u8 _kp[2]; __u8 norm; __u8 _np; - union __attribute__((packed)) { + union __packed { __u8 raw[6]; - struct __attribute__((packed)) wear_level { + struct __packed wear_level { __le16 min; __le16 max; __le16 avg; } wear_level; - struct __attribute__((packed)) thermal_throttle { + struct __packed thermal_throttle { __u8 pct; __u32 count; } thermal_throttle; - } ; + }; __u8 _rp; -} ; +}; struct nvme_additional_smart_log { struct nvme_additional_smart_log_item program_fail_cnt; @@ -79,7 +79,7 @@ static void json_intel_id_ctrl(struct nvme_vu_id_ctrl_field *id, struct json_object *root) { json_object_add_value_int(root, "ss", id->ss); - json_object_add_value_string(root, "health", health ); + json_object_add_value_string(root, "health", health); json_object_add_value_int(root, "cls", id->cls); json_object_add_value_int(root, "nlw", id->nlw); json_object_add_value_int(root, "scap", id->scap); @@ -92,7 +92,7 @@ static void json_intel_id_ctrl(struct nvme_vu_id_ctrl_field *id, static void intel_id_ctrl(__u8 *vs, struct json_object *root) { - struct nvme_vu_id_ctrl_field* id = (struct nvme_vu_id_ctrl_field *)vs; + struct nvme_vu_id_ctrl_field *id = (struct nvme_vu_id_ctrl_field *)vs; char health[21] = { 0 }; char bl[9] = { 0 }; @@ -100,15 +100,10 @@ static void intel_id_ctrl(__u8 *vs, struct json_object *root) char mic_bl[5] = { 0 }; char mic_fw[5] = { 0 }; - - if (id->health[0]==0) - { - snprintf(health, 21, "%s", "healthy"); - } + if (id->health[0] == 0) + snprintf(health, 21, "%s", "healthy"); else - { - snprintf(health, 21, "%s", id->health); - } + snprintf(health, 21, "%s", id->health); snprintf(bl, 9, "%s", id->bl); snprintf(ww, 19, "%02X%02X%02X%02X%02X%02X%02X%02X", id->ww[7], @@ -203,57 +198,57 @@ static void show_intel_smart_log_jsn(struct nvme_additional_smart_log *smart, entry_stats = json_create_object(); json_object_add_value_int(entry_stats, "normalized", smart->retry_buffer_overflow_cnt.norm); - json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->retry_buffer_overflow_cnt.raw)); + json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->retry_buffer_overflow_cnt.raw)); json_object_add_value_object(dev_stats, "retry_buffer_overflow_count", entry_stats); entry_stats = json_create_object(); json_object_add_value_int(entry_stats, "normalized", smart->pll_lock_loss_cnt.norm); - json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->pll_lock_loss_cnt.raw)); + json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->pll_lock_loss_cnt.raw)); json_object_add_value_object(dev_stats, "pll_lock_loss_count", entry_stats); entry_stats = json_create_object(); json_object_add_value_int(entry_stats, "normalized", smart->nand_bytes_written.norm); - json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->nand_bytes_written.raw)); + json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->nand_bytes_written.raw)); json_object_add_value_object(dev_stats, "nand_bytes_written", entry_stats); entry_stats = json_create_object(); json_object_add_value_int(entry_stats, "normalized", smart->host_bytes_written.norm); - json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->host_bytes_written.raw)); + json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->host_bytes_written.raw)); json_object_add_value_object(dev_stats, "host_bytes_written", entry_stats); entry_stats = json_create_object(); json_object_add_value_int(entry_stats, "normalized", smart->host_ctx_wear_used.norm); - json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->host_ctx_wear_used.raw)); + json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->host_ctx_wear_used.raw)); json_object_add_value_object(dev_stats, "host_ctx_wear_used", entry_stats); entry_stats = json_create_object(); json_object_add_value_int(entry_stats, "normalized", smart->perf_stat_indicator.norm); - json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->perf_stat_indicator.raw)); + json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->perf_stat_indicator.raw)); json_object_add_value_object(dev_stats, "perf_stat_indicator", entry_stats); entry_stats = json_create_object(); json_object_add_value_int(entry_stats, "normalized", smart->re_alloc_sectr_cnt.norm); - json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->re_alloc_sectr_cnt.raw)); + json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->re_alloc_sectr_cnt.raw)); json_object_add_value_object(dev_stats, "re_alloc_sectr_cnt", entry_stats); entry_stats = json_create_object(); json_object_add_value_int(entry_stats, "normalized", smart->soft_ecc_err_rate.norm); - json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->soft_ecc_err_rate.raw)); + json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->soft_ecc_err_rate.raw)); json_object_add_value_object(dev_stats, "soft_ecc_err_rate", entry_stats); entry_stats = json_create_object(); json_object_add_value_int(entry_stats, "normalized", smart->unexp_power_loss.norm); - json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->unexp_power_loss.raw)); + json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->unexp_power_loss.raw)); json_object_add_value_object(dev_stats, "unexp_power_loss", entry_stats); entry_stats = json_create_object(); json_object_add_value_int(entry_stats, "normalized", smart->media_bytes_read.norm); - json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->media_bytes_read.raw)); + json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->media_bytes_read.raw)); json_object_add_value_object(dev_stats, "media_bytes_read", entry_stats); entry_stats = json_create_object(); json_object_add_value_int(entry_stats, "normalized", smart->avail_fw_downgrades.norm); - json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->avail_fw_downgrades.raw)); + json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->avail_fw_downgrades.raw)); json_object_add_value_object(dev_stats, "avail_fw_downgrades", entry_stats); json_object_add_value_object(root, "Device stats", dev_stats); @@ -337,11 +332,11 @@ static void show_intel_smart_log(struct nvme_additional_smart_log *smart, static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Get Intel vendor specific additional smart log (optionally, "\ - "for the specified namespace), and show it."; + const char *desc = + "Get Intel vendor specific additional smart log (optionally, for the specified namespace), and show it."; const char *namespace = "(optional) desired namespace"; const char *raw = "Dump output in binary format"; - const char *json= "Dump output in json format"; + const char *json = "Dump output in json format"; struct nvme_additional_smart_log smart_log; struct nvme_dev *dev; @@ -379,9 +374,9 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, dev->name); else d_raw((unsigned char *)&smart_log, sizeof(smart_log)); - } - else if (err > 0) + } else if (err > 0) { nvme_show_status(err); + } dev_close(dev); return err; } @@ -490,7 +485,7 @@ struct intel_lat_stats { __u32 data[1216]; }; -struct __attribute__((__packed__)) optane_lat_stats { +struct __packed optane_lat_stats { __u16 maj; __u16 min; __u64 data[9]; @@ -645,7 +640,7 @@ static void show_optane_lat_stats_bucket(struct optane_lat_stats *stats, set_unit_string(buffer, upper_us, fu, end_type); printf("%-*s", COL_WIDTH, buffer); - printf("%-*lu\n", COL_WIDTH, (long unsigned int)stats->data[i]); + printf("%-*lu\n", COL_WIDTH, (unsigned long)stats->data[i]); } @@ -888,6 +883,7 @@ static void json_lat_stats_v1000_0(struct optane_lat_stats *stats, int write) } struct json_object *subroot = json_create_object(); + json_object_add_value_object(root, "Average latency since last reset", subroot); json_object_add_value_uint(subroot, "value in us", stats->data[8]); @@ -900,12 +896,13 @@ static void json_lat_stats_v1000_0(struct optane_lat_stats *stats, int write) static void show_lat_stats_v1000_0(struct optane_lat_stats *stats, int write) { int i; + if (write) { for (i = 0; i < OPTANE_V1000_BUCKET_LEN - 1; i++) show_optane_lat_stats_bucket(stats, v1000_bucket.write[i], NOINF, - v1000_bucket.write[i + 1] -1, + v1000_bucket.write[i + 1] - 1, NOINF, i); show_optane_lat_stats_bucket(stats, v1000_bucket.write[i], @@ -916,7 +913,7 @@ static void show_lat_stats_v1000_0(struct optane_lat_stats *stats, int write) show_optane_lat_stats_bucket(stats, v1000_bucket.read[i], NOINF, - v1000_bucket.read[i + 1] -1, + v1000_bucket.read[i + 1] - 1, NOINF, i); show_optane_lat_stats_bucket(stats, v1000_bucket.read[i], @@ -924,7 +921,7 @@ static void show_lat_stats_v1000_0(struct optane_lat_stats *stats, int write) POSINF, i); } - printf("Average latency since last reset: %lu us\n", (long unsigned int)stats->data[8]); + printf("Average latency since last reset: %lu us\n", (unsigned long)stats->data[8]); } @@ -1035,7 +1032,7 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct const char *desc = "Get Intel Latency Statistics log and show it."; const char *raw = "Dump output in binary format"; - const char *json= "Dump output in json format"; + const char *json = "Dump output in json format"; const char *write = "Get write statistics (read default)"; struct config { @@ -1159,11 +1156,11 @@ struct intel_event_header { }; struct intel_vu_log { - struct intel_vu_version ver; - __u32 header; - __u32 size; - __u32 numcores; - __u8 reserved[4080]; + struct intel_vu_version ver; + __u32 header; + __u32 size; + __u32 numcores; + __u8 reserved[4080]; }; struct intel_vu_nlog { @@ -1197,7 +1194,7 @@ struct intel_cd_log { __u32 reserved2 : 16; } fields; __u32 entireDword; - } u; + } u; }; static void print_intel_nlog(struct intel_vu_nlog *intel_nlog) @@ -1272,7 +1269,7 @@ static int write_header(__u8 *buf, int fd, size_t amnt) return 0; } -static int read_header(struct nvme_passthru_cmd *cmd,__u8 *buf, int ioctl_fd, +static int read_header(struct nvme_passthru_cmd *cmd, __u8 *buf, int ioctl_fd, __u32 dw12, int nsid) { memset(cmd, 0, sizeof(*cmd)); @@ -1476,7 +1473,7 @@ static int get_internal_log(int argc, char **argv, struct command *command, if (err) goto out; - } else if(cfg.log == 0) { + } else if (cfg.log == 0) { /* If the user selected to read the entire nlog */ if (count > 1) cdlog.u.fields.selectNlog = i; @@ -1640,7 +1637,7 @@ static int enable_lat_stats_tracking(int argc, char **argv, break; default: printf("%d not supported.\n", option); - return EINVAL; + return -EINVAL; } dev_close(dev); return err; @@ -1697,6 +1694,7 @@ static int set_lat_stats_thresholds(int argc, char **argv, if (media_version[0] == 1000) { int thresholds[OPTANE_V1000_BUCKET_LEN] = {0}; + num = argconfig_parse_comma_sep_array(cfg.bucket_thresholds, thresholds, sizeof(thresholds)); diff --git a/plugins/memblaze/memblaze-nvme.c b/plugins/memblaze/memblaze-nvme.c index 7a4633a..c0a70ee 100644 --- a/plugins/memblaze/memblaze-nvme.c +++ b/plugins/memblaze/memblaze-nvme.c @@ -19,22 +19,22 @@ #include "memblaze-utils.h" enum { - // feature id - MB_FEAT_POWER_MGMT = 0x02, - MB_FEAT_HIGH_LATENCY = 0xE1, - // log id - GLP_ID_VU_GET_READ_LATENCY_HISTOGRAM = 0xC1, - GLP_ID_VU_GET_WRITE_LATENCY_HISTOGRAM = 0xC2, - GLP_ID_VU_GET_HIGH_LATENCY_LOG = 0xC3, - MB_FEAT_CLEAR_ERRORLOG = 0xF7, + /* feature id */ + MB_FEAT_POWER_MGMT = 0x02, + MB_FEAT_HIGH_LATENCY = 0xE1, + /* log id */ + GLP_ID_VU_GET_READ_LATENCY_HISTOGRAM = 0xC1, + GLP_ID_VU_GET_WRITE_LATENCY_HISTOGRAM = 0xC2, + GLP_ID_VU_GET_HIGH_LATENCY_LOG = 0xC3, + MB_FEAT_CLEAR_ERRORLOG = 0xF7, }; -#define LOG_PAGE_SIZE (0x1000) -#define DO_PRINT_FLAG (1) -#define NOT_PRINT_FLAG (0) -#define FID_C1_LOG_FILENAME "log_c1.csv" -#define FID_C2_LOG_FILENAME "log_c2.csv" -#define FID_C3_LOG_FILENAME "log_c3.csv" +#define LOG_PAGE_SIZE (0x1000) +#define DO_PRINT_FLAG (1) +#define NOT_PRINT_FLAG (0) +#define FID_C1_LOG_FILENAME "log_c1.csv" +#define FID_C2_LOG_FILENAME "log_c2.csv" +#define FID_C3_LOG_FILENAME "log_c3.csv" /* * Return -1 if @fw1 < @fw2 @@ -43,373 +43,370 @@ enum { */ static int compare_fw_version(const char *fw1, const char *fw2) { - while (*fw1 != '\0') { - if (*fw2 == '\0' || *fw1 > *fw2) - return 1; - if (*fw1 < *fw2) - return -1; - fw1++; - fw2++; - } - - if (*fw2 != '\0') - return -1; - - return 0; + while (*fw1 != '\0') { + if (*fw2 == '\0' || *fw1 > *fw2) + return 1; + if (*fw1 < *fw2) + return -1; + fw1++; + fw2++; + } + + if (*fw2 != '\0') + return -1; + + return 0; } /********************************************************** * input: firmware version string * output: - * 1: new intel format - * 0: old memblaze format + * 1: new intel format + * 0: old memblaze format * *******************************************************/ -#define MEMBLAZE_FORMAT (0) -#define INTEL_FORMAT (1) +#define MEMBLAZE_FORMAT (0) +#define INTEL_FORMAT (1) -// 2.13 = papaya -#define IS_PAPAYA(str) (!strcmp(str, "2.13")) -// 2.83 = raisin -#define IS_RAISIN(str) (!strcmp(str, "2.83")) -// 2.94 = kumquat -#define IS_KUMQUAT(str) (!strcmp(str, "2.94")) -// 0.60 = loquat -#define IS_LOQUAT(str) (!strcmp(str, "0.60")) +/* 2.13 = papaya */ +#define IS_PAPAYA(str) (!strcmp(str, "2.13")) +/* 2.83 = raisin */ +#define IS_RAISIN(str) (!strcmp(str, "2.83")) +/* 2.94 = kumquat */ +#define IS_KUMQUAT(str) (!strcmp(str, "2.94")) +/* 0.60 = loquat */ +#define IS_LOQUAT(str) (!strcmp(str, "0.60")) -#define STR_VER_SIZE (5) +#define STR_VER_SIZE (5) int getlogpage_format_type(char *model_name) { - int logpage_format_type = INTEL_FORMAT; - const char *boundary_model_name1 = "P"; // MEMBLAZE P7936DT0640M00 - const char *boundary_model_name2 = "P5920"; // Use INTEL_FORMAT from Raisin P5920. - if (0 == strncmp(model_name, boundary_model_name1, strlen(boundary_model_name1))) - { - if (strncmp(model_name, boundary_model_name2, strlen(boundary_model_name2)) < 0) - { - logpage_format_type = MEMBLAZE_FORMAT; - } - } - return logpage_format_type; + int logpage_format_type = INTEL_FORMAT; + const char *boundary_model_name1 = "P"; /* MEMBLAZE P7936DT0640M00 */ + const char *boundary_model_name2 = "P5920"; /* Use INTEL_FORMAT from Raisin P5920. */ + + if (!strncmp(model_name, boundary_model_name1, strlen(boundary_model_name1))) { + if (strncmp(model_name, boundary_model_name2, strlen(boundary_model_name2)) < 0) + logpage_format_type = MEMBLAZE_FORMAT; + } + return logpage_format_type; } static __u32 item_id_2_u32(struct nvme_memblaze_smart_log_item *item) { - __le32 __id = 0; - memcpy(&__id, item->id, 3); - return le32_to_cpu(__id); + __le32 __id = 0; + + memcpy(&__id, item->id, 3); + return le32_to_cpu(__id); } static __u64 raw_2_u64(const __u8 *buf, size_t len) { - __le64 val = 0; - memcpy(&val, buf, len); - return le64_to_cpu(val); + __le64 val = 0; + + memcpy(&val, buf, len); + return le64_to_cpu(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); + memcpy(nm_val, smart->itemArr[index].nmVal, NM_SIZE); + memcpy(raw_val, smart->itemArr[index].rawVal, RAW_SIZE); } static void show_memblaze_smart_log_new(struct nvme_memblaze_smart_log *s, - unsigned int nsid, const char *devname) + 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)); + 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)); - if (!nm) { - if (raw) - free(raw); - return; - } - if (!raw) { - free(nm); - return; - } + if (!nm) { + if (raw) + free(raw); + return; + } + if (!raw) { + free(nm); + return; + } - printf("%s:%s %s:%x\n", "Additional Smart Log for NVME device", devname, "namespace-id", nsid); - printf("%-34s%-11s%s\n", "key", "normalized", "raw"); + 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", "program_fail_count", *nm, int48_to_long(raw)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_PROGRAM_FAIL, nm, raw); + 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", "erase_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", "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", "wear_leveling", *nm, - "min: ", *(__u16 *)raw, ", max: ", *(__u16 *)(raw+2), ", avg: ", *(__u16 *)(raw+4)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_WEARLEVELING_COUNT, nm, raw); + 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", "end_to_end_error_detection_count", *nm, int48_to_long(raw)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_E2E_DECTECTION_COUNT, nm, raw); + 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", "crc_error_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", "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", "timed_workload_media_wear", *nm, ((float)int48_to_long(raw))/1000); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_TIMED_WORKLOAD_MEDIA_WEAR, nm, raw); + 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", "timed_workload_host_reads", *nm, int48_to_long(raw)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_TIMED_WORKLOAD_HOST_READ, nm, raw); + 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", "timed_workload_timer", *nm, int48_to_long(raw), " min"); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_TIMED_WORKLOAD_TIMER, nm, raw); + 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%% %u%%%s%"PRIu64"\n", "thermal_throttle_status", *nm, - *raw, ", cnt: ", int48_to_long(raw+1)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_THERMAL_THROTTLE_STATUS, nm, raw); + 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", "retry_buffer_overflow_count", *nm, int48_to_long(raw)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_RETRY_BUFF_OVERFLOW_COUNT, nm, raw); + 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", "pll_lock_loss_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", "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", "nand_bytes_written", *nm, "sectors: ", int48_to_long(raw)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_TOTAL_WRITE, nm, raw); + 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", "host_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", "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", "system_area_life_left", *nm, int48_to_long(raw)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_SYSTEM_AREA_LIFE_LEFT, nm, raw); + 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", "total_read", *nm, int48_to_long(raw)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_TOTAL_READ, nm, raw); + 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", "tempt_since_born", *nm, - "max: ", *(__u16 *)raw, ", min: ", *(__u16 *)(raw+2), ", curr: ", *(__u16 *)(raw+4)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_TEMPT_SINCE_BORN, nm, raw); + 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", "power_consumption", *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", "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", "tempt_since_bootup", *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", "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", "read_fail_count", *nm, int48_to_long(raw)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_READ_FAIL, nm, raw); + 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", "thermal_throttle_time", *nm, int48_to_long(raw)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_THERMAL_THROTTLE_TIME, nm, raw); + 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", "flash_media_error", *nm, int48_to_long(raw)); + get_memblaze_new_smart_info(smart, RAISIN_SI_VD_FLASH_MEDIA_ERROR, nm, raw); + printf("%-32s: %3d%% %"PRIu64"\n", "flash_media_error", *nm, int48_to_long(raw)); - free(nm); - free(raw); + free(nm); + free(raw); } static void show_memblaze_smart_log_old(struct nvme_memblaze_smart_log *smart, - unsigned int nsid, const char *devname, const char *fw_ver) + unsigned int nsid, const char *devname, const char *fw_ver) { - char fw_ver_local[STR_VER_SIZE + 1]; - struct nvme_memblaze_smart_log_item *item; - - strncpy(fw_ver_local, fw_ver, STR_VER_SIZE); - *(fw_ver_local + STR_VER_SIZE) = '\0'; - - printf("Additional Smart Log for NVME device:%s namespace-id:%x\n", devname, nsid); - - printf("Total write in GB since last factory reset : %"PRIu64"\n", - int48_to_long(smart->items[TOTAL_WRITE].rawval)); - printf("Total read in GB since last factory reset : %"PRIu64"\n", - int48_to_long(smart->items[TOTAL_READ].rawval)); - - printf("Thermal throttling status[1:HTP in progress] : %u\n", - smart->items[THERMAL_THROTTLE].thermal_throttle.on); - printf("Total thermal throttling minutes since power on : %u\n", - smart->items[THERMAL_THROTTLE].thermal_throttle.count); - - 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 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 kelvins since power on : %u\n", - le16_to_cpu(smart->items[TEMPT_SINCE_BOOTUP].temperature_p.max)); - 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 kelvins : %u\n", - le16_to_cpu(smart->items[TEMPT_SINCE_RESET].temperature.curr)); - - printf("Maximum power in watt since power on : %u\n", - le16_to_cpu(smart->items[POWER_CONSUMPTION].power.max)); - printf("Minimum power in watt since power on : %u\n", - le16_to_cpu(smart->items[POWER_CONSUMPTION].power.min)); - printf("Current power in watt : %u\n", - le16_to_cpu(smart->items[POWER_CONSUMPTION].power.curr)); - - item = &smart->items[POWER_LOSS_PROTECTION]; - if (item_id_2_u32(item) == 0xEC) - printf("Power loss protection normalized value : %u\n", - item->power_loss_protection.curr); - - item = &smart->items[WEARLEVELING_COUNT]; - if (item_id_2_u32(item) == 0xAD) { - printf("Percentage of wearleveling count left : %u\n", - le16_to_cpu(item->nmval)); - printf("Wearleveling count min erase cycle : %u\n", - le16_to_cpu(item->wearleveling_count.min)); - printf("Wearleveling count max erase cycle : %u\n", - le16_to_cpu(item->wearleveling_count.max)); - printf("Wearleveling count avg erase cycle : %u\n", - le16_to_cpu(item->wearleveling_count.avg)); - } - - item = &smart->items[HOST_WRITE]; - if (item_id_2_u32(item) == 0xF5) - printf("Total host write in GiB since device born : %llu\n", - (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval))); - - item = &smart->items[THERMAL_THROTTLE_CNT]; - if (item_id_2_u32(item) == 0xEB) - printf("Thermal throttling count since device born : %u\n", - item->thermal_throttle_cnt.cnt); - - item = &smart->items[CORRECT_PCIE_PORT0]; - if (item_id_2_u32(item) == 0xED) - printf("PCIE Correctable Error Count of Port0 : %llu\n", - (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval))); - - item = &smart->items[CORRECT_PCIE_PORT1]; - if (item_id_2_u32(item) == 0xEE) - printf("PCIE Correctable Error Count of Port1 : %llu\n", - (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval))); - - item = &smart->items[REBUILD_FAIL]; - if (item_id_2_u32(item) == 0xEF) - printf("End-to-End Error Detection Count : %llu\n", - (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval))); - - item = &smart->items[ERASE_FAIL]; - if (item_id_2_u32(item) == 0xF0) - printf("Erase Fail Count : %llu\n", - (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval))); - - item = &smart->items[PROGRAM_FAIL]; - if (item_id_2_u32(item) == 0xF1) - printf("Program Fail Count : %llu\n", - (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval))); - - item = &smart->items[READ_FAIL]; - if (item_id_2_u32(item) == 0xF2) - printf("Read Fail Count : %llu\n", - (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval))); - - 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)); - - if (!nm) { - if (raw) - free(raw); - return; + char fw_ver_local[STR_VER_SIZE + 1]; + struct nvme_memblaze_smart_log_item *item; + + strncpy(fw_ver_local, fw_ver, STR_VER_SIZE); + *(fw_ver_local + STR_VER_SIZE) = '\0'; + + printf("Additional Smart Log for NVME device:%s namespace-id:%x\n", devname, nsid); + + printf("Total write in GB since last factory reset : %"PRIu64"\n", + int48_to_long(smart->items[TOTAL_WRITE].rawval)); + printf("Total read in GB since last factory reset : %"PRIu64"\n", + int48_to_long(smart->items[TOTAL_READ].rawval)); + + printf("Thermal throttling status[1:HTP in progress] : %u\n", + smart->items[THERMAL_THROTTLE].thermal_throttle.on); + printf("Total thermal throttling minutes since power on : %u\n", + smart->items[THERMAL_THROTTLE].thermal_throttle.count); + + 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 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 kelvins since power on : %u\n", + le16_to_cpu(smart->items[TEMPT_SINCE_BOOTUP].temperature_p.max)); + printf("Minimum temperature in kelvins since power on : %u\n", + le16_to_cpu(smart->items[TEMPT_SINCE_BOOTUP].temperature_p.min)); } - if (!raw) { - free(nm); - return; + 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", + le16_to_cpu(smart->items[POWER_CONSUMPTION].power.max)); + printf("Minimum power in watt since power on : %u\n", + le16_to_cpu(smart->items[POWER_CONSUMPTION].power.min)); + printf("Current power in watt : %u\n", + le16_to_cpu(smart->items[POWER_CONSUMPTION].power.curr)); + + item = &smart->items[POWER_LOSS_PROTECTION]; + if (item_id_2_u32(item) == 0xEC) + printf("Power loss protection normalized value : %u\n", + item->power_loss_protection.curr); + + item = &smart->items[WEARLEVELING_COUNT]; + if (item_id_2_u32(item) == 0xAD) { + printf("Percentage of wearleveling count left : %u\n", + le16_to_cpu(item->nmval)); + printf("Wearleveling count min erase cycle : %u\n", + le16_to_cpu(item->wearleveling_count.min)); + printf("Wearleveling count max erase cycle : %u\n", + le16_to_cpu(item->wearleveling_count.max)); + printf("Wearleveling count avg erase cycle : %u\n", + le16_to_cpu(item->wearleveling_count.avg)); } - get_memblaze_new_smart_info(s, PROGRAM_FAIL, nm, raw); - printf("%-32s : %3d%% %"PRIu64"\n", + + item = &smart->items[HOST_WRITE]; + if (item_id_2_u32(item) == 0xF5) + printf("Total host write in GiB since device born : %llu\n", + (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval))); + + item = &smart->items[THERMAL_THROTTLE_CNT]; + if (item_id_2_u32(item) == 0xEB) + printf("Thermal throttling count since device born : %u\n", + item->thermal_throttle_cnt.cnt); + + item = &smart->items[CORRECT_PCIE_PORT0]; + if (item_id_2_u32(item) == 0xED) + printf("PCIE Correctable Error Count of Port0 : %llu\n", + (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval))); + + item = &smart->items[CORRECT_PCIE_PORT1]; + if (item_id_2_u32(item) == 0xEE) + printf("PCIE Correctable Error Count of Port1 : %llu\n", + (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval))); + + item = &smart->items[REBUILD_FAIL]; + if (item_id_2_u32(item) == 0xEF) + printf("End-to-End Error Detection Count : %llu\n", + (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval))); + + item = &smart->items[ERASE_FAIL]; + if (item_id_2_u32(item) == 0xF0) + printf("Erase Fail Count : %llu\n", + (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval))); + + item = &smart->items[PROGRAM_FAIL]; + if (item_id_2_u32(item) == 0xF1) + printf("Program Fail Count : %llu\n", + (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval))); + + item = &smart->items[READ_FAIL]; + if (item_id_2_u32(item) == 0xF2) + printf("Read Fail Count : %llu\n", + (unsigned long long)raw_2_u64(item->rawval, sizeof(item->rawval))); + + 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)); + + if (!nm) { + if (raw) + free(raw); + return; + } + if (!raw) { + free(nm); + return; + } + get_memblaze_new_smart_info(s, PROGRAM_FAIL, nm, raw); + printf("%-32s : %3d%% %"PRIu64"\n", "program_fail_count", *nm, int48_to_long(raw)); - get_memblaze_new_smart_info(s, ERASE_FAIL, nm, raw); - printf("%-32s : %3d%% %"PRIu64"\n", + get_memblaze_new_smart_info(s, ERASE_FAIL, nm, raw); + printf("%-32s : %3d%% %"PRIu64"\n", "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", + get_memblaze_new_smart_info(s, WEARLEVELING_COUNT, nm, raw); + 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(s, TOTAL_WRITE, nm, raw); - printf("%-32s : %3d%% %"PRIu64"\n", + get_memblaze_new_smart_info(s, TOTAL_WRITE, nm, raw); + printf("%-32s : %3d%% %"PRIu64"\n", "nand_bytes_written", *nm, 32*int48_to_long(raw)); - get_memblaze_new_smart_info(s, HOST_WRITE, nm, raw); - printf("%-32s : %3d%% %"PRIu64"\n", + get_memblaze_new_smart_info(s, HOST_WRITE, nm, raw); + printf("%-32s : %3d%% %"PRIu64"\n", "host_bytes_written", *nm, 32*int48_to_long(raw)); - free(nm); - free(raw); - } + free(nm); + free(raw); + } } static int show_memblaze_smart_log(int fd, __u32 nsid, const char *devname, - struct nvme_memblaze_smart_log *smart) + struct nvme_memblaze_smart_log *smart) { - struct nvme_id_ctrl ctrl; - char fw_ver[10]; - int err = 0; - - err = nvme_identify_ctrl(fd, &ctrl); - if (err) - return err; - - snprintf(fw_ver, sizeof(fw_ver), "%c.%c%c.%c%c%c%c", - ctrl.fr[0], ctrl.fr[1], ctrl.fr[2], ctrl.fr[3], - ctrl.fr[4], ctrl.fr[5], ctrl.fr[6]); - - if (getlogpage_format_type(ctrl.mn)) // Intel Format & new format - { - show_memblaze_smart_log_new(smart, nsid, devname); - } - else // Memblaze Format & old format - { - show_memblaze_smart_log_old(smart, nsid, devname, fw_ver); - } + struct nvme_id_ctrl ctrl; + char fw_ver[10]; + int err = 0; + + err = nvme_identify_ctrl(fd, &ctrl); + if (err) + return err; + + snprintf(fw_ver, sizeof(fw_ver), "%c.%c%c.%c%c%c%c", + ctrl.fr[0], ctrl.fr[1], ctrl.fr[2], ctrl.fr[3], + ctrl.fr[4], ctrl.fr[5], ctrl.fr[6]); + + if (getlogpage_format_type(ctrl.mn)) /* Intel Format & new format */ + show_memblaze_smart_log_new(smart, nsid, devname); + else /* Memblaze Format & old format */ + show_memblaze_smart_log_old(smart, nsid, devname, fw_ver); return err; } int parse_params(char *str, int number, ...) { - va_list argp; - int *param; - char *c; - int value; - - va_start(argp, number); - - while (number > 0) { - c = strtok(str, ","); - if ( c == NULL) { - printf("No enough parameters. abort...\n"); - va_end(argp); - return 1; - } - - if (isalnum((int)*c) == 0) { - printf("%s is not a valid number\n", c); - va_end(argp); - return 1; - } - value = atoi(c); - param = va_arg(argp, int *); - *param = value; - - if (str) { - str = strchr(str, ','); - if (str) { str++; } - } - number--; - } - va_end(argp); - - return 0; + va_list argp; + int *param; + char *c; + int value; + + va_start(argp, number); + + while (number > 0) { + c = strtok(str, ","); + if (!c) { + printf("No enough parameters. abort...\n"); + va_end(argp); + return 1; + } + + if (!isalnum((int)*c)) { + printf("%s is not a valid number\n", c); + va_end(argp); + return 1; + } + value = atoi(c); + param = va_arg(argp, int *); + *param = value; + + if (str) { + str = strchr(str, ','); + if (str) + str++; + } + number--; + } + va_end(argp); + + return 0; } static int mb_get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { struct nvme_memblaze_smart_log smart_log; - char *desc = "Get Memblaze vendor specific additional smart log (optionally, "\ - "for the specified namespace), and show it."; + char *desc = + "Get Memblaze vendor specific additional smart log (optionally, for the specified namespace), and show it."; const char *namespace = "(optional) desired namespace"; const char *raw = "dump output in binary format"; struct nvme_dev *dev; @@ -425,7 +422,7 @@ static int mb_get_additional_smart_log(int argc, char **argv, struct command *cm OPT_ARGS(opts) = { OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace), - OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), + OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), OPT_END() }; @@ -437,9 +434,8 @@ static int mb_get_additional_smart_log(int argc, char **argv, struct command *cm sizeof(smart_log), &smart_log); if (!err) { if (!cfg.raw_binary) - err = show_memblaze_smart_log(dev_fd(dev), - cfg.namespace_id, - dev->name, &smart_log); + err = show_memblaze_smart_log(dev_fd(dev), cfg.namespace_id, dev->name, + &smart_log); else d_raw((unsigned char *)&smart_log, sizeof(smart_log)); } @@ -452,324 +448,318 @@ static int mb_get_additional_smart_log(int argc, char **argv, struct command *cm static char *mb_feature_to_string(int feature) { - switch (feature) { - case MB_FEAT_POWER_MGMT: return "Memblaze power management"; - case MB_FEAT_HIGH_LATENCY: return "Memblaze high latency log"; - case MB_FEAT_CLEAR_ERRORLOG: return "Memblaze clear error log"; - default: return "Unknown"; - } + switch (feature) { + case MB_FEAT_POWER_MGMT: + return "Memblaze power management"; + case MB_FEAT_HIGH_LATENCY: + return "Memblaze high latency log"; + case MB_FEAT_CLEAR_ERRORLOG: + return "Memblaze clear error log"; + default: + return "Unknown"; + } } static int mb_get_powermanager_status(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Get Memblaze power management ststus\n (value 0 - 25w, 1 - 20w, 2 - 15w)"; - __u32 result; - __u32 feature_id = MB_FEAT_POWER_MGMT; - struct nvme_dev *dev; - int err; - - OPT_ARGS(opts) = { - OPT_END() - }; - - err = parse_and_open(&dev, argc, argv, desc, opts); - if (err) - return err; - - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = feature_id, - .nsid = 0, - .sel = 0, - .cdw11 = 0, - .uuidx = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - err = nvme_get_features(&args); - if (err < 0) { - perror("get-feature"); - } - if (!err) { - printf("get-feature:0x%02x (%s), %s value: %#08x\n", feature_id, - mb_feature_to_string(feature_id), - nvme_select_to_string(0), result); - } else if (err > 0) - nvme_show_status(err); - dev_close(dev); - return err; + const char *desc = "Get Memblaze power management ststus\n (value 0 - 25w, 1 - 20w, 2 - 15w)"; + __u32 result; + __u32 feature_id = MB_FEAT_POWER_MGMT; + struct nvme_dev *dev; + int err; + + OPT_ARGS(opts) = { + OPT_END() + }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; + + struct nvme_get_features_args args = { + .args_size = sizeof(args), + .fd = dev_fd(dev), + .fid = feature_id, + .nsid = 0, + .sel = 0, + .cdw11 = 0, + .uuidx = 0, + .data_len = 0, + .data = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_get_features(&args); + if (err < 0) + perror("get-feature"); + if (!err) + printf("get-feature:0x%02x (%s), %s value: %#08x\n", feature_id, + mb_feature_to_string(feature_id), nvme_select_to_string(0), result); + else if (err > 0) + nvme_show_status(err); + dev_close(dev); + return err; } static int mb_set_powermanager_status(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Set Memblaze power management status\n (value 0 - 25w, 1 - 20w, 2 - 15w)"; - const char *value = "new value of feature (required)"; - const char *save = "specifies that the controller shall save the attribute"; - struct nvme_dev *dev; - __u32 result; - int err; - - struct config { - __u32 feature_id; - __u32 value; - bool save; - }; - - struct config cfg = { - .feature_id = MB_FEAT_POWER_MGMT, - .value = 0, - .save = 0, - }; - - OPT_ARGS(opts) = { - OPT_UINT("value", 'v', &cfg.value, value), - OPT_FLAG("save", 's', &cfg.save, save), - OPT_END() - }; - - err = parse_and_open(&dev, argc, argv, desc, opts); - if (err) - return err; - - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = cfg.feature_id, - .nsid = 0, - .cdw11 = cfg.value, - .cdw12 = 0, - .save = cfg.save, - .uuidx = 0, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - err = nvme_set_features(&args); - if (err < 0) { - perror("set-feature"); - } - if (!err) { - printf("set-feature:%02x (%s), value:%#08x\n", cfg.feature_id, - mb_feature_to_string(cfg.feature_id), cfg.value); - } else if (err > 0) - nvme_show_status(err); - - dev_close(dev); - return err; + const char *desc = "Set Memblaze power management status\n (value 0 - 25w, 1 - 20w, 2 - 15w)"; + const char *value = "new value of feature (required)"; + const char *save = "specifies that the controller shall save the attribute"; + struct nvme_dev *dev; + __u32 result; + int err; + + struct config { + __u32 feature_id; + __u32 value; + bool save; + }; + + struct config cfg = { + .feature_id = MB_FEAT_POWER_MGMT, + .value = 0, + .save = 0, + }; + + OPT_ARGS(opts) = { + OPT_UINT("value", 'v', &cfg.value, value), + OPT_FLAG("save", 's', &cfg.save, save), + OPT_END() + }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; + + struct nvme_set_features_args args = { + .args_size = sizeof(args), + .fd = dev_fd(dev), + .fid = cfg.feature_id, + .nsid = 0, + .cdw11 = cfg.value, + .cdw12 = 0, + .save = cfg.save, + .uuidx = 0, + .cdw15 = 0, + .data_len = 0, + .data = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_set_features(&args); + if (err < 0) + perror("set-feature"); + if (!err) + printf("set-feature:%02x (%s), value:%#08x\n", cfg.feature_id, + mb_feature_to_string(cfg.feature_id), cfg.value); + else if (err > 0) + nvme_show_status(err); + + dev_close(dev); + return err; } -#define P2MIN (1) -#define P2MAX (5000) -#define MB_FEAT_HIGH_LATENCY_VALUE_SHIFT (15) +#define P2MIN (1) +#define P2MAX (5000) +#define MB_FEAT_HIGH_LATENCY_VALUE_SHIFT (15) static int mb_set_high_latency_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Set Memblaze high latency log\n"\ - " input parameter p1,p2\n"\ - " p1 value: 0 is disable, 1 is enable\n"\ - " p2 value: 1 .. 5000 ms"; - const char *param = "input parameters"; - int param1 = 0, param2 = 0; - struct nvme_dev *dev; - __u32 result; - int err; - - struct config { - __u32 feature_id; - char * param; - __u32 value; - }; - - struct config cfg = { - .feature_id = MB_FEAT_HIGH_LATENCY, - .param = "0,0", - .value = 0, - }; - - OPT_ARGS(opts) = { - OPT_LIST("param", 'p', &cfg.param, param), - OPT_END() - }; - - err = parse_and_open(&dev, argc, argv, desc, opts); - if (err) - return err; - - if (parse_params(cfg.param, 2, ¶m1, ¶m2)) { - printf("setfeature: invalid formats %s\n", cfg.param); - dev_close(dev); - return EINVAL; - } - if ((param1 == 1) && (param2 < P2MIN || param2 > P2MAX)) { - printf("setfeature: invalid high io latency threshold %d\n", param2); - dev_close(dev); - return EINVAL; - } - cfg.value = (param1 << MB_FEAT_HIGH_LATENCY_VALUE_SHIFT) | param2; - - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = cfg.feature_id, - .nsid = 0, - .cdw11 = cfg.value, - .cdw12 = 0, - .save = false, - .uuidx = 0, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - err = nvme_set_features(&args); - if (err < 0) { - perror("set-feature"); - } - if (!err) { - 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); - - dev_close(dev); - return err; + const char *desc = "Set Memblaze high latency log\n" + " input parameter p1,p2\n" + " p1 value: 0 is disable, 1 is enable\n" + " p2 value: 1 .. 5000 ms"; + const char *param = "input parameters"; + int param1 = 0, param2 = 0; + struct nvme_dev *dev; + __u32 result; + int err; + + struct config { + __u32 feature_id; + char *param; + __u32 value; + }; + + struct config cfg = { + .feature_id = MB_FEAT_HIGH_LATENCY, + .param = "0,0", + .value = 0, + }; + + OPT_ARGS(opts) = { + OPT_LIST("param", 'p', &cfg.param, param), + OPT_END() + }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; + + if (parse_params(cfg.param, 2, ¶m1, ¶m2)) { + printf("setfeature: invalid formats %s\n", cfg.param); + dev_close(dev); + return -EINVAL; + } + if ((param1 == 1) && (param2 < P2MIN || param2 > P2MAX)) { + printf("setfeature: invalid high io latency threshold %d\n", param2); + dev_close(dev); + return -EINVAL; + } + cfg.value = (param1 << MB_FEAT_HIGH_LATENCY_VALUE_SHIFT) | param2; + + struct nvme_set_features_args args = { + .args_size = sizeof(args), + .fd = dev_fd(dev), + .fid = cfg.feature_id, + .nsid = 0, + .cdw11 = cfg.value, + .cdw12 = 0, + .save = false, + .uuidx = 0, + .cdw15 = 0, + .data_len = 0, + .data = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_set_features(&args); + if (err < 0) + perror("set-feature"); + if (!err) + 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); + + dev_close(dev); + return err; } static int glp_high_latency_show_bar(FILE *fdi, int print) { - fPRINT_PARAM1("Memblaze High Latency Log\n"); - fPRINT_PARAM1("---------------------------------------------------------------------------------------------\n"); - fPRINT_PARAM1("Timestamp Type QID CID NSID StartLBA NumLBA Latency\n"); - fPRINT_PARAM1("---------------------------------------------------------------------------------------------\n"); - return 0; + fPRINT_PARAM1("Memblaze High Latency Log\n"); + fPRINT_PARAM1("---------------------------------------------------------------------------------------------\n"); + fPRINT_PARAM1("Timestamp Type QID CID NSID StartLBA NumLBA Latency\n"); + fPRINT_PARAM1("---------------------------------------------------------------------------------------------\n"); + return 0; } -/* High latency log page definiton +/* + * High latency log page definiton * Total 32 bytes */ -typedef struct -{ - __u8 port; - __u8 revision; - __u16 rsvd; - __u8 opcode; - __u8 sqe; - __u16 cid; - __u32 nsid; - __u32 latency; - __u64 sLBA; - __u16 numLBA; - __u16 timestampH; - __u32 timestampL; -} log_page_high_latency_t; /* total 32 bytes */ +struct log_page_high_latency { + __u8 port; + __u8 revision; + __u16 rsvd; + __u8 opcode; + __u8 sqe; + __u16 cid; + __u32 nsid; + __u32 latency; + __u64 sLBA; + __u16 numLBA; + __u16 timestampH; + __u32 timestampL; +}; /* total 32 bytes */ static int find_deadbeef(char *buf) { - if (((*(buf + 0) & 0xff) == 0xef) && ((*(buf + 1) & 0xff) == 0xbe) && \ - ((*(buf + 2) & 0xff) == 0xad) && ((*(buf + 3) & 0xff) == 0xde)) - { - return 1; - } - return 0; + if (((*(buf + 0) & 0xff) == 0xef) && ((*(buf + 1) & 0xff) == 0xbe) && + ((*(buf + 2) & 0xff) == 0xad) && ((*(buf + 3) & 0xff) == 0xde)) + return 1; + return 0; } -#define TIME_STR_SIZE (44) +#define TIME_STR_SIZE (44) static int glp_high_latency(FILE *fdi, char *buf, int buflen, int print) { - log_page_high_latency_t *logEntry; - char string[TIME_STR_SIZE]; - int i, entrySize; - __u64 timestamp; - time_t tt = 0; - struct tm *t = NULL; - int millisec = 0; - - if (find_deadbeef(buf)) return 0; - - entrySize = sizeof(log_page_high_latency_t); - for (i = 0; i < buflen; i += entrySize) - { - logEntry = (log_page_high_latency_t *)(buf + i); - - if (logEntry->latency == 0 && logEntry->revision == 0) - { - return 1; - } - - if (0 == logEntry->timestampH) // generate host time string - { - snprintf(string, sizeof(string), "%d", logEntry->timestampL); - } - else // sort - { - timestamp = logEntry->timestampH; - timestamp = timestamp << 32; - timestamp += logEntry->timestampL; - tt = timestamp / 1000; - millisec = timestamp % 1000; - t = gmtime(&tt); - snprintf(string, sizeof(string), "%4d%02d%02d--%02d:%02d:%02d.%03d UTC", - 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, millisec); - } - - if (fdi) { - fprintf(fdi, "%-32s %-7x %-6x %-6x %-8x %4x%08x %-8x %-d\n", - string, logEntry->opcode, logEntry->sqe, - logEntry->cid, logEntry->nsid, - (__u32)(logEntry->sLBA >> 32), - (__u32)logEntry->sLBA, logEntry->numLBA, - logEntry->latency); + struct log_page_high_latency *logEntry; + char string[TIME_STR_SIZE]; + int i, entrySize; + __u64 timestamp; + time_t tt = 0; + struct tm *t = NULL; + int millisec = 0; + + if (find_deadbeef(buf)) + return 0; + + entrySize = sizeof(struct log_page_high_latency); + for (i = 0; i < buflen; i += entrySize) { + logEntry = (struct log_page_high_latency *)(buf + i); + + if (logEntry->latency == 0 && logEntry->revision == 0) + return 1; + + if (!logEntry->timestampH) { /* generate host time string */ + snprintf(string, sizeof(string), "%d", logEntry->timestampL); + } else { /* sort */ + timestamp = logEntry->timestampH; + timestamp = timestamp << 32; + timestamp += logEntry->timestampL; + tt = timestamp / 1000; + millisec = timestamp % 1000; + t = gmtime(&tt); + snprintf(string, sizeof(string), "%4d%02d%02d--%02d:%02d:%02d.%03d UTC", + 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday, t->tm_hour, + t->tm_min, t->tm_sec, millisec); + } + + if (fdi) + fprintf(fdi, "%-32s %-7x %-6x %-6x %-8x %4x%08x %-8x %-d\n", + string, logEntry->opcode, logEntry->sqe, + logEntry->cid, logEntry->nsid, + (__u32)(logEntry->sLBA >> 32), + (__u32)logEntry->sLBA, logEntry->numLBA, + logEntry->latency); + if (print) + printf("%-32s %-7x %-6x %-6x %-8x %4x%08x %-8x %-d\n", + string, logEntry->opcode, logEntry->sqe, logEntry->cid, + logEntry->nsid, (__u32)(logEntry->sLBA >> 32), (__u32)logEntry->sLBA, + logEntry->numLBA, logEntry->latency); } - if (print) - { - printf("%-32s %-7x %-6x %-6x %-8x %4x%08x %-8x %-d\n", - string, logEntry->opcode, logEntry->sqe, logEntry->cid, logEntry->nsid, - (__u32)(logEntry->sLBA >> 32), (__u32)logEntry->sLBA, logEntry->numLBA, logEntry->latency); - } - } - return 1; + return 1; } static int mb_high_latency_log_print(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Get Memblaze high latency log"; - char buf[LOG_PAGE_SIZE]; - struct nvme_dev *dev; - FILE *fdi = NULL; - int err; - - OPT_ARGS(opts) = { - OPT_END() - }; + const char *desc = "Get Memblaze high latency log"; + char buf[LOG_PAGE_SIZE]; + struct nvme_dev *dev; + FILE *fdi = NULL; + int err; - err = parse_and_open(&dev, argc, argv, desc, opts); - if (err) - return err; + OPT_ARGS(opts) = { + OPT_END() + }; - fdi = fopen(FID_C3_LOG_FILENAME, "w+"); + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; - glp_high_latency_show_bar(fdi, DO_PRINT_FLAG); - err = nvme_get_log_simple(dev_fd(dev), GLP_ID_VU_GET_HIGH_LATENCY_LOG, - sizeof(buf), &buf); + fdi = fopen(FID_C3_LOG_FILENAME, "w+"); - while (1) { - if (!glp_high_latency(fdi, buf, LOG_PAGE_SIZE, DO_PRINT_FLAG)) break; - err = nvme_get_log_simple(dev_fd(dev), GLP_ID_VU_GET_HIGH_LATENCY_LOG, + glp_high_latency_show_bar(fdi, DO_PRINT_FLAG); + err = nvme_get_log_simple(dev_fd(dev), GLP_ID_VU_GET_HIGH_LATENCY_LOG, sizeof(buf), &buf); - if ( err) { - nvme_show_status(err); - break; - } - } - - if (NULL != fdi) fclose(fdi); - dev_close(dev); - return err; + + while (1) { + if (!glp_high_latency(fdi, buf, LOG_PAGE_SIZE, DO_PRINT_FLAG)) + break; + err = nvme_get_log_simple(dev_fd(dev), GLP_ID_VU_GET_HIGH_LATENCY_LOG, + sizeof(buf), &buf); + if (err) { + nvme_show_status(err); + break; + } + } + + if (fdi) + fclose(fdi); + dev_close(dev); + return err; } static int memblaze_fw_commit(int fd, int select) @@ -777,7 +767,7 @@ static int memblaze_fw_commit(int fd, int select) struct nvme_passthru_cmd cmd = { .opcode = nvme_admin_fw_commit, .cdw10 = 8, - .cdw12 = select, + .cdw12 = select, }; return nvme_submit_admin_passthru(fd, &cmd, NULL); @@ -786,9 +776,9 @@ static int memblaze_fw_commit(int fd, int select) static int mb_selective_download(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = - "This performs a selective firmware download, which allows the user to " - "select which firmware binary to update for 9200 devices. This requires a power cycle once the " - "update completes. The options available are: \n\n" + "This performs a selective firmware download, which allows the user to\n" + "select which firmware binary to update for 9200 devices. This requires a power cycle once the\n" + "update completes. The options available are:\n\n" "OOB - This updates the OOB and main firmware\n" "EEP - This updates the eeprom and main firmware\n" "ALL - This updates the eeprom, OOB, and main firmware"; @@ -796,18 +786,18 @@ static int mb_selective_download(int argc, char **argv, struct command *cmd, str const char *select = "FW Select (e.g., --select=OOB, EEP, ALL)"; int xfer = 4096; void *fw_buf; - int selectNo,fw_fd,fw_size,err,offset = 0; + int selectNo, fw_fd, fw_size, err, offset = 0; struct nvme_dev *dev; struct stat sb; int i; struct config { - char *fw; - char *select; + char *fw; + char *select; }; struct config cfg = { - .fw = "", + .fw = "", .select = "\0", }; @@ -827,15 +817,14 @@ static int mb_selective_download(int argc, char **argv, struct command *cmd, str goto out; } - for (i = 0; i < 3; i++) { + for (i = 0; i < 3; i++) cfg.select[i] = toupper(cfg.select[i]); - } - if (strncmp(cfg.select,"OOB", 3) == 0) { + if (!strncmp(cfg.select, "OOB", 3)) { selectNo = 18; - } else if (strncmp(cfg.select,"EEP", 3) == 0) { + } else if (!strncmp(cfg.select, "EEP", 3)) { selectNo = 10; - } else if (strncmp(cfg.select,"ALL", 3) == 0) { + } else if (!strncmp(cfg.select, "ALL", 3)) { selectNo = 26; } else { fprintf(stderr, "Invalid select flag\n"); @@ -895,14 +884,14 @@ static int mb_selective_download(int argc, char **argv, struct command *cmd, str nvme_show_status(err); goto out_free; } - fw_buf += xfer; + fw_buf += xfer; fw_size -= xfer; offset += xfer; } err = memblaze_fw_commit(dev_fd(dev), selectNo); - if(err == 0x10B || err == 0x20B) { + if (err == 0x10B || err == 0x20B) { err = 0; fprintf(stderr, "Update successful! Please power cycle for changes to take effect\n"); } @@ -917,198 +906,181 @@ out: } static void ioLatencyHistogramOutput(FILE *fd, int index, int start, int end, char *unit0, - char *unit1, unsigned int *pHistogram, int print) + char *unit1, unsigned int *pHistogram, int print) { - int len; - char string[64], subString0[12], subString1[12]; - - snprintf(subString0, sizeof(subString0), "%d%s", start, unit0); - if (end != 0x7FFFFFFF) - snprintf(subString1, sizeof(subString1), "%d%s", end, unit1); - else - snprintf(subString1, sizeof(subString1), "%s", "+INF"); - len = snprintf(string, sizeof(string), "%-11d %-11s %-11s %-11u\n", + int len; + char string[64], subString0[12], subString1[12]; + + snprintf(subString0, sizeof(subString0), "%d%s", start, unit0); + if (end != 0x7FFFFFFF) + snprintf(subString1, sizeof(subString1), "%d%s", end, unit1); + else + snprintf(subString1, sizeof(subString1), "%s", "+INF"); + len = snprintf(string, sizeof(string), "%-11d %-11s %-11s %-11u\n", index, subString0, subString1, - pHistogram[index]); - fwrite(string, 1, len, fd); - if (print) - printf("%s", string); + pHistogram[index]); + fwrite(string, 1, len, fd); + if (print) + printf("%s", string); } int io_latency_histogram(char *file, char *buf, int print, int logid) { - FILE *fdi = fopen(file, "w+"); - int i, index; - char unit[2][3]; - unsigned int *revision = (unsigned int *)buf; - - if (logid == GLP_ID_VU_GET_READ_LATENCY_HISTOGRAM) - { - fPRINT_PARAM1("Memblaze IO Read Command Latency Histogram\n"); - } - else if (logid == GLP_ID_VU_GET_WRITE_LATENCY_HISTOGRAM) - { - fPRINT_PARAM1("Memblaze IO Write Command Latency Histogram\n"); - } - fPRINT_PARAM2("Major Revision : %d\n", revision[1]); - fPRINT_PARAM2("Minor Revision : %d\n", revision[0]); - buf += 8; - - if (revision[1] == 1 && revision[0] == 0) - { - fPRINT_PARAM1("--------------------------------------------------\n"); - fPRINT_PARAM1("Bucket Start End Value \n"); - fPRINT_PARAM1("--------------------------------------------------\n"); - index = 0; - strcpy(unit[0], "us"); - strcpy(unit[1], "us"); - for (i = 0; i < 32; i++, index++) - { - if (i == 31) - { - strcpy(unit[1], "ms"); - ioLatencyHistogramOutput(fdi, index, i * 32, 1, unit[0], unit[1], (unsigned int *)buf, print); - } - else - { - ioLatencyHistogramOutput(fdi, index, i * 32, (i + 1) * 32, unit[0], unit[1], (unsigned int *)buf, - print); - } - } - - strcpy(unit[0], "ms"); - strcpy(unit[1], "ms"); - for (i = 1; i < 32; i++, index++) - { - ioLatencyHistogramOutput(fdi, index, i, i + 1, unit[0], unit[1], (unsigned int *)buf, print); - } - - for (i = 1; i < 32; i++, index++) - { - if (i == 31) - { - strcpy(unit[1], "s"); - ioLatencyHistogramOutput(fdi, index, i * 32, 1, unit[0], unit[1], (unsigned int *)buf, print); - } - else - { - ioLatencyHistogramOutput(fdi, index, i * 32, (i + 1) * 32, unit[0], unit[1], (unsigned int *)buf, - print); - } - } - - strcpy(unit[0], "s"); - strcpy(unit[1], "s"); - for (i = 1; i < 4; i++, index++) - { - ioLatencyHistogramOutput(fdi, index, i, i + 1, unit[0], unit[1], (unsigned int *)buf, print); - } - - ioLatencyHistogramOutput(fdi, index, i, 0x7FFFFFFF, unit[0], unit[1], (unsigned int *)buf, print); - } - else - { - fPRINT_PARAM1("Unsupported io latency histogram revision\n"); - } - - if (fdi) - fclose(fdi); - return 1; + FILE *fdi = fopen(file, "w+"); + int i, index; + char unit[2][3]; + unsigned int *revision = (unsigned int *)buf; + + if (logid == GLP_ID_VU_GET_READ_LATENCY_HISTOGRAM) + fPRINT_PARAM1("Memblaze IO Read Command Latency Histogram\n"); + else if (logid == GLP_ID_VU_GET_WRITE_LATENCY_HISTOGRAM) + fPRINT_PARAM1("Memblaze IO Write Command Latency Histogram\n"); + fPRINT_PARAM2("Major Revision : %d\n", revision[1]); + fPRINT_PARAM2("Minor Revision : %d\n", revision[0]); + buf += 8; + + if (revision[1] == 1 && revision[0] == 0) { + fPRINT_PARAM1("--------------------------------------------------\n"); + fPRINT_PARAM1("Bucket Start End Value\n"); + fPRINT_PARAM1("--------------------------------------------------\n"); + index = 0; + strcpy(unit[0], "us"); + strcpy(unit[1], "us"); + for (i = 0; i < 32; i++, index++) { + if (i == 31) { + strcpy(unit[1], "ms"); + ioLatencyHistogramOutput(fdi, index, i * 32, 1, unit[0], unit[1], + (unsigned int *)buf, print); + } else { + ioLatencyHistogramOutput(fdi, index, i * 32, (i + 1) * 32, unit[0], + unit[1], (unsigned int *)buf, print); + } + } + + strcpy(unit[0], "ms"); + strcpy(unit[1], "ms"); + for (i = 1; i < 32; i++, index++) + ioLatencyHistogramOutput(fdi, index, i, i + 1, unit[0], unit[1], (unsigned int *)buf, print); + + for (i = 1; i < 32; i++, index++) { + if (i == 31) { + strcpy(unit[1], "s"); + ioLatencyHistogramOutput(fdi, index, i * 32, 1, unit[0], unit[1], + (unsigned int *)buf, print); + } else { + ioLatencyHistogramOutput(fdi, index, i * 32, (i + 1) * 32, unit[0], + unit[1], (unsigned int *)buf, print); + } + } + + strcpy(unit[0], "s"); + strcpy(unit[1], "s"); + for (i = 1; i < 4; i++, index++) + ioLatencyHistogramOutput(fdi, index, i, i + 1, unit[0], unit[1], (unsigned int *)buf, print); + + ioLatencyHistogramOutput(fdi, index, i, 0x7FFFFFFF, unit[0], unit[1], (unsigned int *)buf, print); + } else { + fPRINT_PARAM1("Unsupported io latency histogram revision\n"); + } + + if (fdi) + fclose(fdi); + return 1; } static int mb_lat_stats_log_print(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - char stats[LOG_PAGE_SIZE]; - char f1[] = FID_C1_LOG_FILENAME; - char f2[] = FID_C2_LOG_FILENAME; - struct nvme_dev *dev; - int err; - - const char *desc = "Get Latency Statistics log and show it."; - const char *write = "Get write statistics (read default)"; - - struct config { - bool write; - }; - struct config cfg = { - .write = 0, - }; - - OPT_ARGS(opts) = { - OPT_FLAG("write", 'w', &cfg.write, write), - OPT_END() - }; - - err = parse_and_open(&dev, argc, argv, desc, opts); - if (err) - return err; - - err = nvme_get_log_simple(dev_fd(dev), cfg.write ? 0xc2 : 0xc1, - sizeof(stats), &stats); - if (!err) - io_latency_histogram(cfg.write ? f2 : f1, stats, DO_PRINT_FLAG, - cfg.write ? GLP_ID_VU_GET_WRITE_LATENCY_HISTOGRAM : GLP_ID_VU_GET_READ_LATENCY_HISTOGRAM); - else - nvme_show_status(err); - - dev_close(dev); - return err; + char stats[LOG_PAGE_SIZE]; + char f1[] = FID_C1_LOG_FILENAME; + char f2[] = FID_C2_LOG_FILENAME; + struct nvme_dev *dev; + int err; + + const char *desc = "Get Latency Statistics log and show it."; + const char *write = "Get write statistics (read default)"; + + struct config { + bool write; + }; + struct config cfg = { + .write = 0, + }; + + OPT_ARGS(opts) = { + OPT_FLAG("write", 'w', &cfg.write, write), + OPT_END() + }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; + + err = nvme_get_log_simple(dev_fd(dev), cfg.write ? 0xc2 : 0xc1, + sizeof(stats), &stats); + if (!err) + io_latency_histogram(cfg.write ? f2 : f1, stats, DO_PRINT_FLAG, + cfg.write ? GLP_ID_VU_GET_WRITE_LATENCY_HISTOGRAM : + GLP_ID_VU_GET_READ_LATENCY_HISTOGRAM); + else + nvme_show_status(err); + + dev_close(dev); + return err; } 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; - - __u32 result; - - struct config { - __u32 feature_id; - __u32 value; - int save; - }; - - struct config cfg = { - .feature_id = 0xf7, - .value = 0x534d0001, - .save = 0, - }; - - OPT_ARGS(opts) = { - OPT_END() - }; - - err = parse_and_open(&dev, argc, argv, desc, opts); - if (err) - return err; - - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = cfg.feature_id, - .nsid = 0, - .cdw11 = cfg.value, - .cdw12 = 0, - .save = cfg.save, - .uuidx = 0, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - err = nvme_set_features(&args); - if (err < 0) { - perror("set-feature"); - } - if (!err) { - printf("set-feature:%02x (%s), value:%#08x\n", cfg.feature_id, mb_feature_to_string(cfg.feature_id), cfg.value); - } else if (err > 0) - nvme_show_status(err); - - dev_close(dev); - return err; + char *desc = "Clear Memblaze devices error log."; + struct nvme_dev *dev; + int err; + + __u32 result; + + struct config { + __u32 feature_id; + __u32 value; + int save; + }; + + struct config cfg = { + .feature_id = 0xf7, + .value = 0x534d0001, + .save = 0, + }; + + OPT_ARGS(opts) = { + OPT_END() + }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; + + struct nvme_set_features_args args = { + .args_size = sizeof(args), + .fd = dev_fd(dev), + .fid = cfg.feature_id, + .nsid = 0, + .cdw11 = cfg.value, + .cdw12 = 0, + .save = cfg.save, + .uuidx = 0, + .cdw15 = 0, + .data_len = 0, + .data = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_set_features(&args); + if (err < 0) + perror("set-feature"); + if (!err) + printf("set-feature:%02x (%s), value:%#08x\n", cfg.feature_id, mb_feature_to_string(cfg.feature_id), cfg.value); + else if (err > 0) + nvme_show_status(err); + + dev_close(dev); + return err; } static int mb_set_lat_stats(int argc, char **argv, @@ -1207,7 +1179,7 @@ static int mb_set_lat_stats(int argc, char **argv, break; case True: case False: - err = nvme_set_features(&args_set); + err = nvme_set_features(&args_set); if (err > 0) { nvme_show_status(err); } else if (err < 0) { diff --git a/plugins/memblaze/memblaze-utils.h b/plugins/memblaze/memblaze-utils.h index f64a115..dd89189 100644 --- a/plugins/memblaze/memblaze-utils.h +++ b/plugins/memblaze/memblaze-utils.h @@ -2,220 +2,216 @@ #ifndef __MEMBLAZE_UTILS_H__ #define __MEMBLAZE_UTILS_H__ -#define SMART_INFO_OLD_SIZE 512 -#define SMART_INFO_NEW_SIZE 4096 +#define SMART_INFO_OLD_SIZE 512 +#define SMART_INFO_NEW_SIZE 4096 -#define ID_SIZE 3 -#define NM_SIZE 2 -#define RAW_SIZE 7 +#define ID_SIZE 3 +#define NM_SIZE 2 +#define RAW_SIZE 7 // Intel Format & new format /* Raisin Additional smart external ID */ -#define RAISIN_SI_VD_PROGRAM_FAIL_ID 0xAB -#define RAISIN_SI_VD_ERASE_FAIL_ID 0xAC -#define RAISIN_SI_VD_WEARLEVELING_COUNT_ID 0xAD -#define RAISIN_SI_VD_E2E_DECTECTION_COUNT_ID 0xB8 -#define RAISIN_SI_VD_PCIE_CRC_ERR_COUNT_ID 0xC7 -#define RAISIN_SI_VD_TIMED_WORKLOAD_MEDIA_WEAR_ID 0xE2 -#define RAISIN_SI_VD_TIMED_WORKLOAD_HOST_READ_ID 0xE3 -#define RAISIN_SI_VD_TIMED_WORKLOAD_TIMER_ID 0xE4 -#define RAISIN_SI_VD_THERMAL_THROTTLE_STATUS_ID 0xEA -#define RAISIN_SI_VD_RETRY_BUFF_OVERFLOW_COUNT_ID 0xF0 -#define RAISIN_SI_VD_PLL_LOCK_LOSS_COUNT_ID 0xF3 -#define RAISIN_SI_VD_TOTAL_WRITE_ID 0xF4 -#define RAISIN_SI_VD_HOST_WRITE_ID 0xF5 -#define RAISIN_SI_VD_SYSTEM_AREA_LIFE_LEFT_ID 0xF6 -#define RAISIN_SI_VD_TOTAL_READ_ID 0xFA -#define RAISIN_SI_VD_TEMPT_SINCE_BORN_ID 0xE7 -#define RAISIN_SI_VD_POWER_CONSUMPTION_ID 0xE8 -#define RAISIN_SI_VD_TEMPT_SINCE_BOOTUP_ID 0xAF -#define RAISIN_SI_VD_POWER_LOSS_PROTECTION_ID 0xEC -#define RAISIN_SI_VD_READ_FAIL_ID 0xF2 -#define RAISIN_SI_VD_THERMAL_THROTTLE_TIME_ID 0xEB -#define RAISIN_SI_VD_FLASH_MEDIA_ERROR_ID 0xED +#define RAISIN_SI_VD_PROGRAM_FAIL_ID 0xAB +#define RAISIN_SI_VD_ERASE_FAIL_ID 0xAC +#define RAISIN_SI_VD_WEARLEVELING_COUNT_ID 0xAD +#define RAISIN_SI_VD_E2E_DECTECTION_COUNT_ID 0xB8 +#define RAISIN_SI_VD_PCIE_CRC_ERR_COUNT_ID 0xC7 +#define RAISIN_SI_VD_TIMED_WORKLOAD_MEDIA_WEAR_ID 0xE2 +#define RAISIN_SI_VD_TIMED_WORKLOAD_HOST_READ_ID 0xE3 +#define RAISIN_SI_VD_TIMED_WORKLOAD_TIMER_ID 0xE4 +#define RAISIN_SI_VD_THERMAL_THROTTLE_STATUS_ID 0xEA +#define RAISIN_SI_VD_RETRY_BUFF_OVERFLOW_COUNT_ID 0xF0 +#define RAISIN_SI_VD_PLL_LOCK_LOSS_COUNT_ID 0xF3 +#define RAISIN_SI_VD_TOTAL_WRITE_ID 0xF4 +#define RAISIN_SI_VD_HOST_WRITE_ID 0xF5 +#define RAISIN_SI_VD_SYSTEM_AREA_LIFE_LEFT_ID 0xF6 +#define RAISIN_SI_VD_TOTAL_READ_ID 0xFA +#define RAISIN_SI_VD_TEMPT_SINCE_BORN_ID 0xE7 +#define RAISIN_SI_VD_POWER_CONSUMPTION_ID 0xE8 +#define RAISIN_SI_VD_TEMPT_SINCE_BOOTUP_ID 0xAF +#define RAISIN_SI_VD_POWER_LOSS_PROTECTION_ID 0xEC +#define RAISIN_SI_VD_READ_FAIL_ID 0xF2 +#define RAISIN_SI_VD_THERMAL_THROTTLE_TIME_ID 0xEB +#define RAISIN_SI_VD_FLASH_MEDIA_ERROR_ID 0xED /* Raisin Addtional smart internal ID */ typedef enum { - /* smart attr following intel */ - RAISIN_SI_VD_PROGRAM_FAIL = 0, /* 0xAB */ - RAISIN_SI_VD_ERASE_FAIL = 1, /* 0xAC */ - RAISIN_SI_VD_WEARLEVELING_COUNT = 2,/* 0xAD */ - RAISIN_SI_VD_E2E_DECTECTION_COUNT = 3, /* 0xB8 */ - RAISIN_SI_VD_PCIE_CRC_ERR_COUNT = 4, /* 0xC7, 2 port data in one attribute */ - RAISIN_SI_VD_TIMED_WORKLOAD_MEDIA_WEAR = 5, /* 0xE2 , unknown definition*/ - RAISIN_SI_VD_TIMED_WORKLOAD_HOST_READ = 6, /* 0xE3 , unknown definition */ - RAISIN_SI_VD_TIMED_WORKLOAD_TIMER = 7, /* 0xE4 , unknown definition */ - RAISIN_SI_VD_THERMAL_THROTTLE_STATUS = 8, /* 0xEA */ - RAISIN_SI_VD_RETRY_BUFF_OVERFLOW_COUNT = 9, /* 0xF0, unknown definition*/ - RAISIN_SI_VD_PLL_LOCK_LOSS_COUNT = 10, /* 0xF3, unknown definition*/ - RAISIN_SI_VD_TOTAL_WRITE = 11, /* 0xF4, unit is 32MiB */ - RAISIN_SI_VD_HOST_WRITE = 12, /* 0xF5, unit is 32MiB */ - RAISIN_SI_VD_SYSTEM_AREA_LIFE_LEFT = 13, /* 0xF6, unknown definition*/ - RAISIN_SI_VD_TOTAL_READ = 14, /* 0xFA, unit is 32MiB */ + /* smart attr following intel */ + RAISIN_SI_VD_PROGRAM_FAIL = 0, /* 0xAB */ + RAISIN_SI_VD_ERASE_FAIL = 1, /* 0xAC */ + RAISIN_SI_VD_WEARLEVELING_COUNT = 2,/* 0xAD */ + RAISIN_SI_VD_E2E_DECTECTION_COUNT = 3, /* 0xB8 */ + RAISIN_SI_VD_PCIE_CRC_ERR_COUNT = 4, /* 0xC7, 2 port data in one attribute */ + RAISIN_SI_VD_TIMED_WORKLOAD_MEDIA_WEAR = 5, /* 0xE2 , unknown definition*/ + RAISIN_SI_VD_TIMED_WORKLOAD_HOST_READ = 6, /* 0xE3 , unknown definition */ + RAISIN_SI_VD_TIMED_WORKLOAD_TIMER = 7, /* 0xE4 , unknown definition */ + RAISIN_SI_VD_THERMAL_THROTTLE_STATUS = 8, /* 0xEA */ + RAISIN_SI_VD_RETRY_BUFF_OVERFLOW_COUNT = 9, /* 0xF0, unknown definition*/ + RAISIN_SI_VD_PLL_LOCK_LOSS_COUNT = 10, /* 0xF3, unknown definition*/ + RAISIN_SI_VD_TOTAL_WRITE = 11, /* 0xF4, unit is 32MiB */ + RAISIN_SI_VD_HOST_WRITE = 12, /* 0xF5, unit is 32MiB */ + RAISIN_SI_VD_SYSTEM_AREA_LIFE_LEFT = 13, /* 0xF6, unknown definition*/ + RAISIN_SI_VD_TOTAL_READ = 14, /* 0xFA, unit is 32MiB */ - /* smart attr self defined */ - RAISIN_SI_VD_TEMPT_SINCE_BORN = 15, /* 0xE7 */ - RAISIN_SI_VD_POWER_CONSUMPTION = 16, /* 0xE8 */ - RAISIN_SI_VD_TEMPT_SINCE_BOOTUP = 17, /* 0xAF */ - RAISIN_SI_VD_POWER_LOSS_PROTECTION = 18, /* 0xEC */ - RAISIN_SI_VD_READ_FAIL = 19, /* 0xF2 */ - RAISIN_SI_VD_THERMAL_THROTTLE_TIME = 20, /* 0xEB */ - RAISIN_SI_VD_FLASH_MEDIA_ERROR = 21, /* 0xED */ - RAISIN_SI_VD_SMART_INFO_ITEMS_MAX, + /* smart attr self defined */ + RAISIN_SI_VD_TEMPT_SINCE_BORN = 15, /* 0xE7 */ + RAISIN_SI_VD_POWER_CONSUMPTION = 16, /* 0xE8 */ + RAISIN_SI_VD_TEMPT_SINCE_BOOTUP = 17, /* 0xAF */ + RAISIN_SI_VD_POWER_LOSS_PROTECTION = 18, /* 0xEC */ + RAISIN_SI_VD_READ_FAIL = 19, /* 0xF2 */ + RAISIN_SI_VD_THERMAL_THROTTLE_TIME = 20, /* 0xEB */ + RAISIN_SI_VD_FLASH_MEDIA_ERROR = 21, /* 0xED */ + RAISIN_SI_VD_SMART_INFO_ITEMS_MAX, } RAISIN_si_vendor_smart_item_e; // Memblaze Format & old format enum { - /*0*/TOTAL_WRITE = 0, - /*1*/TOTAL_READ, - /*2*/THERMAL_THROTTLE, - /*3*/TEMPT_SINCE_RESET, - /*4*/POWER_CONSUMPTION, - /*5*/TEMPT_SINCE_BOOTUP, - /*6*/POWER_LOSS_PROTECTION, - /*7*/WEARLEVELING_COUNT, - /*8*/HOST_WRITE, - /*9*/THERMAL_THROTTLE_CNT, - /*10*/CORRECT_PCIE_PORT0, - /*11*/CORRECT_PCIE_PORT1, - /*12*/REBUILD_FAIL, - /*13*/ERASE_FAIL, - /*14*/PROGRAM_FAIL, - /*15*/READ_FAIL, - /*16*/NR_SMART_ITEMS = RAISIN_SI_VD_SMART_INFO_ITEMS_MAX, + /*0*/TOTAL_WRITE = 0, + /*1*/TOTAL_READ, + /*2*/THERMAL_THROTTLE, + /*3*/TEMPT_SINCE_RESET, + /*4*/POWER_CONSUMPTION, + /*5*/TEMPT_SINCE_BOOTUP, + /*6*/POWER_LOSS_PROTECTION, + /*7*/WEARLEVELING_COUNT, + /*8*/HOST_WRITE, + /*9*/THERMAL_THROTTLE_CNT, + /*10*/CORRECT_PCIE_PORT0, + /*11*/CORRECT_PCIE_PORT1, + /*12*/REBUILD_FAIL, + /*13*/ERASE_FAIL, + /*14*/PROGRAM_FAIL, + /*15*/READ_FAIL, + /*16*/NR_SMART_ITEMS = RAISIN_SI_VD_SMART_INFO_ITEMS_MAX, }; // Memblaze Format & old format #pragma pack(push, 1) struct nvme_memblaze_smart_log_item { - __u8 id[3]; - union { - __u8 __nmval[2]; - __le16 nmval; - }; - union { - __u8 rawval[6]; - struct temperature { - __le16 max; - __le16 min; - __le16 curr; - } temperature; - struct power { - __le16 max; - __le16 min; - __le16 curr; - } power; - struct thermal_throttle_mb { - __u8 on; - __u32 count; - } thermal_throttle; - struct temperature_p { - __le16 max; - __le16 min; - } temperature_p; - struct power_loss_protection { - __u8 curr; - } power_loss_protection; - struct wearleveling_count { - __le16 min; - __le16 max; - __le16 avg; - } wearleveling_count; - struct thermal_throttle_cnt { - __u8 active; - __le32 cnt; - } thermal_throttle_cnt; - }; - __u8 resv; + __u8 id[3]; + union { + __u8 __nmval[2]; + __le16 nmval; + }; + union { + __u8 rawval[6]; + struct temperature { + __le16 max; + __le16 min; + __le16 curr; + } temperature; + struct power { + __le16 max; + __le16 min; + __le16 curr; + } power; + struct thermal_throttle_mb { + __u8 on; + __u32 count; + } thermal_throttle; + struct temperature_p { + __le16 max; + __le16 min; + } temperature_p; + struct power_loss_protection { + __u8 curr; + } power_loss_protection; + struct wearleveling_count { + __le16 min; + __le16 max; + __le16 avg; + } wearleveling_count; + struct thermal_throttle_cnt { + __u8 active; + __le32 cnt; + } thermal_throttle_cnt; + }; + __u8 resv; }; #pragma pack(pop) 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]; + 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]; }; // Intel Format & new format struct nvme_p4_smart_log_item { - /* Item identifier */ - __u8 id[ID_SIZE]; - /* Normalized value or percentage. In the range from 0 to 100. */ - __u8 nmVal[NM_SIZE]; - /* raw value */ - __u8 rawVal[RAW_SIZE]; + /* Item identifier */ + __u8 id[ID_SIZE]; + /* Normalized value or percentage. In the range from 0 to 100. */ + __u8 nmVal[NM_SIZE]; + /* raw value */ + __u8 rawVal[RAW_SIZE]; }; struct nvme_p4_smart_log { - struct nvme_p4_smart_log_item itemArr[NR_SMART_ITEMS]; + struct nvme_p4_smart_log_item itemArr[NR_SMART_ITEMS]; - /** - * change 512 to 4096. - * 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]; + /** + * change 512 to 4096. + * 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]; }; // base -#define DD do{ printf("=Memblaze= %s[%d]-%s():\n", __FILE__, __LINE__, __func__); }while(0) -#define DE(str) do{ printf("===ERROR!=== %s[%d]-%s():str=%s\n", __FILE__, __LINE__, __func__, \ - str); }while(0) +#define DD do{ printf("=Memblaze= %s[%d]-%s():\n", __FILE__, __LINE__, __func__); }while(0) +#define DE(str) do{ printf("===ERROR!=== %s[%d]-%s():str=%s\n", __FILE__, __LINE__, __func__, \ + str); }while(0) // integer -#define DI(i) do{ printf("=Memblaze= %s[%d]-%s():int=%d\n", __FILE__, __LINE__, __func__, \ - (int)i); } while(0) -#define DPI(prompt, i) do{ printf("=Memblaze= %s[%d]-%s():%s=%d\n", __FILE__, __LINE__, __func__, \ - prompt, i); }while(0) -#define DAI(prompt, i, arr, max) do{ printf("=Memblaze= %s[%d]-%s():%s", __FILE__, __LINE__, __func__, prompt); \ - for(i=0;i<max;i++) printf(" %d:%d", i, arr[i]); \ - printf("\n"); }while(0) +#define DI(i) do{ printf("=Memblaze= %s[%d]-%s():int=%d\n", __FILE__, __LINE__, __func__, \ + (int)i); } while(0) +#define DPI(prompt, i) do{ printf("=Memblaze= %s[%d]-%s():%s=%d\n", __FILE__, __LINE__, __func__, \ + prompt, i); }while(0) +#define DAI(prompt, i, arr, max) do{ printf("=Memblaze= %s[%d]-%s():%s", __FILE__, __LINE__, __func__, prompt); \ + for(i=0;i<max;i++) printf(" %d:%d", i, arr[i]); \ + printf("\n"); }while(0) // char -#define DC(c) do{ printf("=Memblaze= %s[%d]-%s():char=%c\n", __FILE__, __LINE__, __func__, c); \ - }while(0) -#define DPC(prompt, c) do{ printf("=Memblaze= %s[%d]-%s():%s=%c\n", __FILE__, __LINE__, __func__, \ - prompt, c); }while(0) +#define DC(c) do{ printf("=Memblaze= %s[%d]-%s():char=%c\n", __FILE__, __LINE__, __func__, c); \ + }while(0) +#define DPC(prompt, c) do{ printf("=Memblaze= %s[%d]-%s():%s=%c\n", __FILE__, __LINE__, __func__, \ + prompt, c); }while(0) // address -#define DA(add) do{ printf("=Memblaze= %s[%d]-%s():address=0x%08X\n", __FILE__, __LINE__, \ - __func__, add); }while(0) -#define DPA(prompt, add) do{ printf("=Memblaze= %s[%d]-%s():%s=0x%08X\n", __FILE__, __LINE__, __func__, \ - prompt, add); }while(0) +#define DA(add) do{ printf("=Memblaze= %s[%d]-%s():address=0x%08X\n", __FILE__, __LINE__, \ + __func__, add); }while(0) +#define DPA(prompt, add) do{ printf("=Memblaze= %s[%d]-%s():%s=0x%08X\n", __FILE__, __LINE__, __func__, \ + prompt, add); }while(0) // string -#define DS(str) do{ printf("=Memblaze= %s[%d]-%s():str=%s\n", __FILE__, __LINE__, __func__, str); \ - }while(0) -#define DPS(prompt, str) do{ printf("=Memblaze= %s[%d]-%s():%s=%s\n", __FILE__, __LINE__, __func__, \ - prompt, str); }while(0) -#define DAS(prompt, i, arr, max) do{ printf("=Memblaze= %s[%d]-%s():%s", __FILE__, __LINE__, __func__, prompt); \ - for(i=0;i<max;i++) printf(" %d:%s", i, arr[i]); \ - printf("\n"); }while(0) +#define DS(str) do{ printf("=Memblaze= %s[%d]-%s():str=%s\n", __FILE__, __LINE__, __func__, str); \ + }while(0) +#define DPS(prompt, str) do{ printf("=Memblaze= %s[%d]-%s():%s=%s\n", __FILE__, __LINE__, __func__, \ + prompt, str); }while(0) +#define DAS(prompt, i, arr, max) do{ printf("=Memblaze= %s[%d]-%s():%s", __FILE__, __LINE__, __func__, prompt); \ + for(i=0;i<max;i++) printf(" %d:%s", i, arr[i]); \ + printf("\n"); }while(0) // array -#define DR(str, k) do{ int ip; for(ip=0;ip<k;ip++) if(NULL != argv[ip]) \ - printf("=Memblaze= %s[%d]-%s():%d=%s\n", \ - __FILE__, __LINE__, __func__, ip, str[ip]); }while(0) -#define DARG do{ DPI("argc", argc); \ - int ip; for(ip=0;ip<argc;ip++) if(NULL != argv[ip]) \ - printf("=Memblaze= %s[%d]-%s():%d=%s\n", \ - __FILE__, __LINE__, __func__, ip, argv[ip]); }while(0) +#define DR(str, k) do{ int ip; for(ip=0;ip<k;ip++) if(NULL != argv[ip]) \ + printf("=Memblaze= %s[%d]-%s():%d=%s\n", \ + __FILE__, __LINE__, __func__, ip, str[ip]); }while(0) +#define DARG do{ DPI("argc", argc); \ + int ip; for(ip=0;ip<argc;ip++) if(NULL != argv[ip]) \ + printf("=Memblaze= %s[%d]-%s():%d=%s\n", \ + __FILE__, __LINE__, __func__, ip, argv[ip]); }while(0) -#define fPRINT_PARAM1(format) \ - { \ - do { \ - if (fdi) \ - fprintf(fdi, format); \ - if (print) \ - printf(format); \ - } while (0); \ - } +#define fPRINT_PARAM1(format) \ + do { \ + if (fdi) \ + fprintf(fdi, format); \ + if (print) \ + printf(format); \ + } while (0) -#define fPRINT_PARAM2(format, value) \ - { \ - do { \ - if (fdi) \ - fprintf(fdi, format, value); \ - if (print) \ - printf(format, value); \ - } while (0); \ - } +#define fPRINT_PARAM2(format, value) \ + do { \ + if (fdi) \ + fprintf(fdi, format, value); \ + if (print) \ + printf(format, value); \ + } while (0) #endif // __MEMBLAZE_UTILS_H__ diff --git a/plugins/meson.build b/plugins/meson.build index 2cf2486..38b7cde 100644 --- a/plugins/meson.build +++ b/plugins/meson.build @@ -12,6 +12,7 @@ if json_c_dep.found() 'plugins/intel/intel-nvme.c', 'plugins/memblaze/memblaze-nvme.c', 'plugins/micron/micron-nvme.c', + 'plugins/nbft/nbft-plugin.c', 'plugins/netapp/netapp-nvme.c', 'plugins/nvidia/nvidia-nvme.c', 'plugins/scaleflux/sfx-nvme.c', diff --git a/plugins/micron/micron-nvme.c b/plugins/micron/micron-nvme.c index bd5f7d7..d6fb601 100644 --- a/plugins/micron/micron-nvme.c +++ b/plugins/micron/micron-nvme.c @@ -21,10 +21,10 @@ #include "micron-nvme.h" /* Supported Vendor specific feature ids */ -#define MICRON_FEATURE_CLEAR_PCI_CORRECTABLE_ERRORS 0xC3 -#define MICRON_FEATURE_CLEAR_FW_ACTIVATION_HISTORY 0xC1 -#define MICRON_FEATURE_TELEMETRY_CONTROL_OPTION 0xCF -#define MICRON_FEATURE_SMBUS_OPTION 0xD5 +#define MICRON_FEATURE_CLEAR_PCI_CORRECTABLE_ERRORS 0xC3 +#define MICRON_FEATURE_CLEAR_FW_ACTIVATION_HISTORY 0xC1 +#define MICRON_FEATURE_TELEMETRY_CONTROL_OPTION 0xCF +#define MICRON_FEATURE_SMBUS_OPTION 0xD5 /* Supported Vendor specific log page sizes */ #define C5_log_size (((452 + 16 * 1024) / 4) * 4096) @@ -33,8 +33,8 @@ #define D0_log_size 512 #define FB_log_size 512 #define E1_log_size 256 -#define MaxLogChunk 16 * 1024 -#define CommonChunkSize 16 * 4096 +#define MaxLogChunk (16 * 1024) +#define CommonChunkSize (16 * 4096) #define min(x, y) ((x) > (y) ? (y) : (x)) #define SensorCount 8 @@ -44,10 +44,19 @@ static const char *__version_major = "1"; static const char *__version_minor = "0"; static const char *__version_patch = "14"; -/* supported models of micron plugin; new models should be added at the end +/* + * supported models of micron plugin; new models should be added at the end * before UNKNOWN_MODEL. Make sure M5410 is first in the list ! */ -typedef enum { M5410 = 0, M51AX, M51BX, M51CX, M5407, M5411, UNKNOWN_MODEL } eDriveModel; +enum eDriveModel { + M5410 = 0, + M51AX, + M51BX, + M51CX, + M5407, + M5411, + UNKNOWN_MODEL +}; #define MICRON_VENDOR_ID 0x1344 @@ -58,396 +67,398 @@ static char *fdeviceid2 = "/sys/class/misc/nvme%d/device/device"; static unsigned short vendor_id; static unsigned short device_id; -typedef struct _LogPageHeader_t { - unsigned char numDwordsInLogPageHeaderLo; - unsigned char logPageHeaderFormatVersion; - unsigned char logPageId; - unsigned char numDwordsInLogPageHeaderHi; - unsigned int numValidDwordsInPayload; - unsigned int numDwordsInEntireLogPage; -} LogPageHeader_t; +struct LogPageHeader_t { + unsigned char numDwordsInLogPageHeaderLo; + unsigned char logPageHeaderFormatVersion; + unsigned char logPageId; + unsigned char numDwordsInLogPageHeaderHi; + unsigned int numValidDwordsInPayload; + unsigned int numDwordsInEntireLogPage; +}; static void WriteData(__u8 *data, __u32 len, const char *dir, const char *file, const char *msg) { - char tempFolder[8192] = { 0 }; - FILE *fpOutFile = NULL; - sprintf(tempFolder, "%s/%s", dir, file); - if ((fpOutFile = fopen(tempFolder, "ab+")) != NULL) { - if (fwrite(data, 1, len, fpOutFile) != len) { - printf("Failed to write %s data to %s\n", msg, tempFolder); - } - fclose(fpOutFile); - } else { - printf("Failed to open %s file to write %s\n", tempFolder, msg); - } + char tempFolder[8192] = { 0 }; + FILE *fpOutFile = NULL; + + sprintf(tempFolder, "%s/%s", dir, file); + fpOutFile = fopen(tempFolder, "ab+"); + if (fpOutFile) { + if (fwrite(data, 1, len, fpOutFile) != len) + printf("Failed to write %s data to %s\n", msg, tempFolder); + fclose(fpOutFile); + } else { + printf("Failed to open %s file to write %s\n", tempFolder, msg); + } } static int ReadSysFile(const char *file, unsigned short *id) { - int ret = 0; - char idstr[32] = { '\0' }; - int fd = open(file, O_RDONLY); - - if (fd < 0) { - perror(file); - return fd; - } - - ret = read(fd, idstr, sizeof(idstr)); - close(fd); - if (ret < 0) - perror("read"); - else - *id = strtol(idstr, NULL, 16); - - return ret; + int ret = 0; + char idstr[32] = { '\0' }; + int fd = open(file, O_RDONLY); + + if (fd < 0) { + perror(file); + return fd; + } + + ret = read(fd, idstr, sizeof(idstr)); + close(fd); + if (ret < 0) + perror("read"); + else + *id = strtol(idstr, NULL, 16); + + return ret; } -static eDriveModel GetDriveModel(int idx) +static enum eDriveModel GetDriveModel(int idx) { - eDriveModel eModel = UNKNOWN_MODEL; - char path[512]; - - sprintf(path, fvendorid1, idx); - if (ReadSysFile(path, &vendor_id) < 0) { - sprintf(path, fvendorid2, idx); - ReadSysFile(path, &vendor_id); - } - sprintf(path, fdeviceid1, idx); - if (ReadSysFile(path, &device_id) < 0) { - sprintf(path, fdeviceid2, idx); - ReadSysFile(path, &device_id); - } - if (vendor_id == MICRON_VENDOR_ID) { - switch (device_id) { - case 0x5196: - case 0x51A0: - case 0x51A1: - case 0x51A2: - eModel = M51AX; - break; - case 0x51B0: - case 0x51B1: - case 0x51B2: - eModel = M51BX; - break; - case 0x51C0: - case 0x51C1: - case 0x51C2: - case 0x51C3: - eModel = M51CX; - break; - case 0x5405: - case 0x5406: - case 0x5407: - eModel = M5407; - break; - case 0x5410: - eModel = M5410; - break; - case 0x5411: - eModel = M5411; - break; - default: - break; - } - } - return eModel; + enum eDriveModel eModel = UNKNOWN_MODEL; + char path[512]; + + sprintf(path, fvendorid1, idx); + if (ReadSysFile(path, &vendor_id) < 0) { + sprintf(path, fvendorid2, idx); + ReadSysFile(path, &vendor_id); + } + sprintf(path, fdeviceid1, idx); + if (ReadSysFile(path, &device_id) < 0) { + sprintf(path, fdeviceid2, idx); + ReadSysFile(path, &device_id); + } + if (vendor_id == MICRON_VENDOR_ID) { + switch (device_id) { + case 0x5196: + fallthrough; + case 0x51A0: + fallthrough; + case 0x51A1: + fallthrough; + case 0x51A2: + eModel = M51AX; + break; + case 0x51B0: + fallthrough; + case 0x51B1: + fallthrough; + case 0x51B2: + eModel = M51BX; + break; + case 0x51C0: + fallthrough; + case 0x51C1: + fallthrough; + case 0x51C2: + fallthrough; + case 0x51C3: + eModel = M51CX; + break; + case 0x5405: + fallthrough; + case 0x5406: + fallthrough; + case 0x5407: + eModel = M5407; + break; + case 0x5410: + eModel = M5410; + break; + case 0x5411: + eModel = M5411; + break; + default: + break; + } + } + return eModel; } static int ZipAndRemoveDir(char *strDirName, char *strFileName) { - int err = 0; - char strBuffer[PATH_MAX]; - int nRet; - bool is_tgz = false; - struct stat sb; - - if (strstr(strFileName, ".tar.gz") || strstr(strFileName, ".tgz")) { - sprintf(strBuffer, "tar -zcf \"%s\" \"%s\"", strFileName, - strDirName); - is_tgz = true; - } else { - sprintf(strBuffer, "zip -r \"%s\" \"%s\" >temp.txt 2>&1", strFileName, - strDirName); - } - - err = EINVAL; - nRet = system(strBuffer); - - /* check if log file is created, if not print error message */ - if (nRet < 0 || (stat(strFileName, &sb) == -1)) { - if (is_tgz) - sprintf(strBuffer, "check if tar and gzip commands are installed"); - else - sprintf(strBuffer, "check if zip command is installed"); - - fprintf(stderr, "Failed to create log data package, %s!\n", strBuffer); - } - - sprintf(strBuffer, "rm -f -R \"%s\" >temp.txt 2>&1", strDirName); - nRet = system(strBuffer); - if (nRet < 0) - printf("Failed to remove temporary files!\n"); - - err = system("rm -f temp.txt"); - return err; + int err = 0; + char strBuffer[PATH_MAX]; + int nRet; + bool is_tgz = false; + struct stat sb; + + if (strstr(strFileName, ".tar.gz") || strstr(strFileName, ".tgz")) { + sprintf(strBuffer, "tar -zcf \"%s\" \"%s\"", strFileName, strDirName); + is_tgz = true; + } else { + sprintf(strBuffer, "zip -r \"%s\" \"%s\" >temp.txt 2>&1", strFileName, + strDirName); + } + + err = EINVAL; + nRet = system(strBuffer); + + /* check if log file is created, if not print error message */ + if (nRet < 0 || (stat(strFileName, &sb) == -1)) { + if (is_tgz) + sprintf(strBuffer, "check if tar and gzip commands are installed"); + else + sprintf(strBuffer, "check if zip command is installed"); + + fprintf(stderr, "Failed to create log data package, %s!\n", strBuffer); + } + + sprintf(strBuffer, "rm -f -R \"%s\" >temp.txt 2>&1", strDirName); + nRet = system(strBuffer); + if (nRet < 0) + printf("Failed to remove temporary files!\n"); + + err = system("rm -f temp.txt"); + return err; } static int SetupDebugDataDirectories(char *strSN, char *strFilePath, - char *strMainDirName, char *strOSDirName, - char *strCtrlDirName) + char *strMainDirName, char *strOSDirName, + char *strCtrlDirName) { - int err = 0; - char strAppend[250]; - struct stat st; - char *fileLocation = NULL; - char *fileName; - int length = 0; - int nIndex = 0; - char *strTemp = NULL; - struct stat dirStat; - int j; - int k = 0; - int i = 0; - - if (strchr(strFilePath, '/') != NULL) { - fileName = strrchr(strFilePath, '\\'); - if (fileName == NULL) { - fileName = strrchr(strFilePath, '/'); - } - - if (fileName != NULL) { - if (!strcmp(fileName, "/")) { - goto exit_status; - } - - while (strFilePath[nIndex] != '\0') { - if ('\\' == strFilePath[nIndex] && '\\' == strFilePath[nIndex + 1]) { - goto exit_status; - } - nIndex++; - } - - length = (int)strlen(strFilePath) - (int)strlen(fileName); - - if (fileName == strFilePath) { - length = 1; - } - - if ((fileLocation = (char *)malloc(length + 1)) == NULL) { - goto exit_status; - } - strncpy(fileLocation, strFilePath, length); - fileLocation[length] = '\0'; - - while (fileLocation[k] != '\0') { - if (fileLocation[k] == '\\') { - fileLocation[k] = '/'; - } - k++; - } - - length = (int)strlen(fileLocation); - - if (':' == fileLocation[length - 1]) { - if ((strTemp = (char *)malloc(length + 2)) == NULL) { - free(fileLocation); - goto exit_status; - } - strcpy(strTemp, fileLocation); - strcat(strTemp, "/"); - free(fileLocation); - - length = (int)strlen(strTemp); - if ((fileLocation = (char *)malloc(length + 1)) == NULL) { - free(strTemp); - goto exit_status; - } - - memcpy(fileLocation, strTemp, length + 1); - free(strTemp); - } - - if (stat(fileLocation, &st) != 0) { - free(fileLocation); - goto exit_status; - } - free(fileLocation); - } else { - goto exit_status; - } - } - - nIndex = 0; - for (i = 0; i < (int)strlen(strSN); i++) { - if (strSN[i] != ' ' && strSN[i] != '\n' && strSN[i] != '\t' && strSN[i] != '\r') { - strMainDirName[nIndex++] = strSN[i]; - } - } - strMainDirName[nIndex] = '\0'; - - j = 1; - while (stat(strMainDirName, &dirStat) == 0) { - strMainDirName[nIndex] = '\0'; - sprintf(strAppend, "-%d", j); - strcat(strMainDirName, strAppend); - j++; - } - - if (mkdir(strMainDirName, 0777) < 0) { - err = -1; - goto exit_status; - } - - if (strOSDirName != NULL) { - sprintf(strOSDirName, "%s/%s", strMainDirName, "OS"); - if (mkdir(strOSDirName, 0777) < 0) { - rmdir(strMainDirName); - err = -1; - goto exit_status; - } - } - if (strCtrlDirName != NULL) { - sprintf(strCtrlDirName, "%s/%s", strMainDirName, "Controller"); - if (mkdir(strCtrlDirName, 0777) < 0) { - if (strOSDirName != NULL) - rmdir(strOSDirName); - rmdir(strMainDirName); - err = -1; - } - } + int err = 0; + char strAppend[250]; + struct stat st; + char *fileLocation = NULL; + char *fileName; + int length = 0; + int nIndex = 0; + char *strTemp = NULL; + struct stat dirStat; + int j; + int k = 0; + int i = 0; + + if (strchr(strFilePath, '/')) { + fileName = strrchr(strFilePath, '\\'); + if (!fileName) + fileName = strrchr(strFilePath, '/'); + + if (fileName) { + if (!strcmp(fileName, "/")) + goto exit_status; + + while (strFilePath[nIndex] != '\0') { + if ('\\' == strFilePath[nIndex] && '\\' == strFilePath[nIndex + 1]) + goto exit_status; + nIndex++; + } + + length = (int)strlen(strFilePath) - (int)strlen(fileName); + + if (fileName == strFilePath) + length = 1; + + fileLocation = (char *)malloc(length + 1); + if (!fileLocation) + goto exit_status; + strncpy(fileLocation, strFilePath, length); + fileLocation[length] = '\0'; + + while (fileLocation[k] != '\0') { + if (fileLocation[k] == '\\') + fileLocation[k] = '/'; + k++; + } + + length = (int)strlen(fileLocation); + + if (':' == fileLocation[length - 1]) { + strTemp = (char *)malloc(length + 2); + if (!strTemp) { + free(fileLocation); + goto exit_status; + } + strcpy(strTemp, fileLocation); + strcat(strTemp, "/"); + free(fileLocation); + + length = (int)strlen(strTemp); + fileLocation = (char *)malloc(length + 1); + if (!fileLocation) { + free(strTemp); + goto exit_status; + } + + memcpy(fileLocation, strTemp, length + 1); + free(strTemp); + } + + if (stat(fileLocation, &st)) { + free(fileLocation); + goto exit_status; + } + free(fileLocation); + } else { + goto exit_status; + } + } + + nIndex = 0; + for (i = 0; i < (int)strlen(strSN); i++) { + if (strSN[i] != ' ' && strSN[i] != '\n' && strSN[i] != '\t' && strSN[i] != '\r') + strMainDirName[nIndex++] = strSN[i]; + } + strMainDirName[nIndex] = '\0'; + + j = 1; + while (!stat(strMainDirName, &dirStat)) { + strMainDirName[nIndex] = '\0'; + sprintf(strAppend, "-%d", j); + strcat(strMainDirName, strAppend); + j++; + } + + if (mkdir(strMainDirName, 0777) < 0) { + err = -1; + goto exit_status; + } + + if (strOSDirName) { + sprintf(strOSDirName, "%s/%s", strMainDirName, "OS"); + if (mkdir(strOSDirName, 0777) < 0) { + rmdir(strMainDirName); + err = -1; + goto exit_status; + } + } + if (strCtrlDirName) { + sprintf(strCtrlDirName, "%s/%s", strMainDirName, "Controller"); + if (mkdir(strCtrlDirName, 0777) < 0) { + if (strOSDirName) + rmdir(strOSDirName); + rmdir(strMainDirName); + err = -1; + } + } exit_status: - return err; + return err; } static int GetLogPageSize(int nFD, unsigned char ucLogID, int *nLogSize) { - int err = 0; - unsigned char pTmpBuf[CommonChunkSize] = { 0 }; - LogPageHeader_t *pLogHeader = NULL; - - if (ucLogID == 0xC1 || ucLogID == 0xC2 || ucLogID == 0xC4) { - err = nvme_get_log_simple(nFD, ucLogID, - CommonChunkSize, pTmpBuf); - if (err == 0) { - pLogHeader = (LogPageHeader_t *) pTmpBuf; - LogPageHeader_t *pLogHeader1 = (LogPageHeader_t *) pLogHeader; - *nLogSize = (int)(pLogHeader1->numDwordsInEntireLogPage) * 4; - if (pLogHeader1->logPageHeaderFormatVersion == 0) { - printf ("Unsupported log page format version %d of log page : 0x%X\n", - ucLogID, err); - *nLogSize = 0; - err = -1; - } - } else { - printf ("Getting size of log page : 0x%X failed with %d (ignored)!\n", - ucLogID, err); - *nLogSize = 0; - } - } - return err; + int err = 0; + unsigned char pTmpBuf[CommonChunkSize] = { 0 }; + struct LogPageHeader_t *pLogHeader = NULL; + + if (ucLogID == 0xC1 || ucLogID == 0xC2 || ucLogID == 0xC4) { + err = nvme_get_log_simple(nFD, ucLogID, CommonChunkSize, pTmpBuf); + if (!err) { + pLogHeader = (struct LogPageHeader_t *) pTmpBuf; + struct LogPageHeader_t *pLogHeader1 = (struct LogPageHeader_t *) pLogHeader; + *nLogSize = (int)(pLogHeader1->numDwordsInEntireLogPage) * 4; + if (!pLogHeader1->logPageHeaderFormatVersion) { + printf("Unsupported log page format version %d of log page : 0x%X\n", + ucLogID, err); + *nLogSize = 0; + err = -1; + } + } else { + printf("Getting size of log page : 0x%X failed with %d (ignored)!\n", + ucLogID, err); + *nLogSize = 0; + } + } + return err; } static int NVMEGetLogPage(int nFD, unsigned char ucLogID, unsigned char *pBuffer, int nBuffSize) { - int err = 0; - struct nvme_passthru_cmd cmd = { 0 }; - unsigned int uiNumDwords = (unsigned int)nBuffSize / sizeof(unsigned int); - unsigned int uiMaxChunk = uiNumDwords; - unsigned int uiNumChunks = 1; - unsigned int uiXferDwords = 0; - unsigned long long ullBytesRead = 0; - unsigned char *pTempPtr = pBuffer; - unsigned char ucOpCode = 0x02; - - if (ullBytesRead == 0 && (ucLogID == 0xE6 || ucLogID == 0xE7)) { - uiMaxChunk = 4096; - } else if (uiMaxChunk > 16 * 1024) { - uiMaxChunk = 16 * 1024; - } - - uiNumChunks = uiNumDwords / uiMaxChunk; - if (uiNumDwords % uiMaxChunk > 0) { - uiNumChunks += 1; - } - - for (unsigned int i = 0; i < uiNumChunks; i++) { - memset(&cmd, 0, sizeof(cmd)); - uiXferDwords = uiMaxChunk; - if (i == uiNumChunks - 1 && uiNumDwords % uiMaxChunk > 0) { - uiXferDwords = uiNumDwords % uiMaxChunk; - } - - cmd.opcode = ucOpCode; - cmd.cdw10 |= ucLogID; - cmd.cdw10 |= ((uiXferDwords - 1) & 0x0000FFFF) << 16; - - if (ucLogID == 0x7) { - cmd.cdw10 |= 0x80; - } - if (ullBytesRead == 0 && (ucLogID == 0xE6 || ucLogID == 0xE7)) { - cmd.cdw11 = 1; - } - if (ullBytesRead > 0 && !(ucLogID == 0xE6 || ucLogID == 0xE7)) { - unsigned long long ullOffset = ullBytesRead; - cmd.cdw12 = ullOffset & 0xFFFFFFFF; - cmd.cdw13 = (ullOffset >> 32) & 0xFFFFFFFF; - } - - cmd.addr = (__u64) (uintptr_t) pTempPtr; - cmd.nsid = 0xFFFFFFFF; - cmd.data_len = uiXferDwords * 4; - err = nvme_submit_admin_passthru(nFD, &cmd, NULL); - ullBytesRead += uiXferDwords * 4; - pTempPtr = pBuffer + ullBytesRead; - } - - return err; + int err = 0; + struct nvme_passthru_cmd cmd = { 0 }; + unsigned int uiNumDwords = (unsigned int)nBuffSize / sizeof(unsigned int); + unsigned int uiMaxChunk = uiNumDwords; + unsigned int uiNumChunks = 1; + unsigned int uiXferDwords = 0; + unsigned long long ullBytesRead = 0; + unsigned char *pTempPtr = pBuffer; + unsigned char ucOpCode = 0x02; + + if (!ullBytesRead && (ucLogID == 0xE6 || ucLogID == 0xE7)) + uiMaxChunk = 4096; + else if (uiMaxChunk > 16 * 1024) + uiMaxChunk = 16 * 1024; + + uiNumChunks = uiNumDwords / uiMaxChunk; + if (uiNumDwords % uiMaxChunk > 0) + uiNumChunks += 1; + + for (unsigned int i = 0; i < uiNumChunks; i++) { + memset(&cmd, 0, sizeof(cmd)); + uiXferDwords = uiMaxChunk; + if (i == uiNumChunks - 1 && uiNumDwords % uiMaxChunk > 0) + uiXferDwords = uiNumDwords % uiMaxChunk; + + cmd.opcode = ucOpCode; + cmd.cdw10 |= ucLogID; + cmd.cdw10 |= ((uiXferDwords - 1) & 0x0000FFFF) << 16; + + if (ucLogID == 0x7) + cmd.cdw10 |= 0x80; + if (!ullBytesRead && (ucLogID == 0xE6 || ucLogID == 0xE7)) + cmd.cdw11 = 1; + if (ullBytesRead > 0 && !(ucLogID == 0xE6 || ucLogID == 0xE7)) { + unsigned long long ullOffset = ullBytesRead; + + cmd.cdw12 = ullOffset & 0xFFFFFFFF; + cmd.cdw13 = (ullOffset >> 32) & 0xFFFFFFFF; + } + + cmd.addr = (__u64) (uintptr_t) pTempPtr; + cmd.nsid = 0xFFFFFFFF; + cmd.data_len = uiXferDwords * 4; + err = nvme_submit_admin_passthru(nFD, &cmd, NULL); + ullBytesRead += uiXferDwords * 4; + pTempPtr = pBuffer + ullBytesRead; + } + + return err; } static int NVMEResetLog(int nFD, unsigned char ucLogID, int nBufferSize, - long long llMaxSize) + long long llMaxSize) { - unsigned int *pBuffer = NULL; - int err = 0; + unsigned int *pBuffer = NULL; + int err = 0; - if ((pBuffer = (unsigned int *)calloc(1, nBufferSize)) == NULL) - return err; + pBuffer = (unsigned int *)calloc(1, nBufferSize); + if (!pBuffer) + return err; - while (err == 0 && llMaxSize > 0) { - err = NVMEGetLogPage(nFD, ucLogID, (unsigned char *)pBuffer, nBufferSize); - if (err) { - free(pBuffer); - return err; - } + while (!err && llMaxSize > 0) { + err = NVMEGetLogPage(nFD, ucLogID, (unsigned char *)pBuffer, nBufferSize); + if (err) { + free(pBuffer); + return err; + } - if (pBuffer[0] == 0xdeadbeef) - break; + if (pBuffer[0] == 0xdeadbeef) + break; - llMaxSize = llMaxSize - nBufferSize; - } + llMaxSize = llMaxSize - nBufferSize; + } - free(pBuffer); - return err; + free(pBuffer); + return err; } static int GetCommonLogPage(int nFD, unsigned char ucLogID, - unsigned char **pBuffer, int nBuffSize) + unsigned char **pBuffer, int nBuffSize) { - unsigned char *pTempPtr = NULL; - int err = 0; - pTempPtr = (unsigned char *)malloc(nBuffSize); - if (!pTempPtr) { - goto exit_status; - } - memset(pTempPtr, 0, nBuffSize); - err = nvme_get_log_simple(nFD, ucLogID, nBuffSize, pTempPtr); - *pBuffer = pTempPtr; + unsigned char *pTempPtr = NULL; + int err = 0; + + pTempPtr = (unsigned char *)malloc(nBuffSize); + if (!pTempPtr) + goto exit_status; + memset(pTempPtr, 0, nBuffSize); + err = nvme_get_log_simple(nFD, ucLogID, nBuffSize, pTempPtr); + *pBuffer = pTempPtr; exit_status: - return err; + return err; } /* @@ -456,1531 +467,1526 @@ exit_status: static int micron_parse_options(struct nvme_dev **dev, int argc, char **argv, const char *desc, struct argconfig_commandline_options *opts, - eDriveModel *modelp) + enum eDriveModel *modelp) { - int idx = 0; - int err = parse_and_open(dev, argc, argv, desc, opts); + int idx; + int err = parse_and_open(dev, argc, argv, desc, opts); - if (err) { - perror("open"); - return -1; - } + if (err) { + perror("open"); + return -1; + } - if (modelp) { - sscanf(argv[optind], "/dev/nvme%d", &idx); - *modelp = GetDriveModel(idx); - } + if (modelp) { + if (sscanf(argv[optind], "/dev/nvme%d", &idx) != 1) + idx = 0; + *modelp = GetDriveModel(idx); + } - return 0; + return 0; } static int micron_fw_commit(int fd, int select) { - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_fw_commit, - .cdw10 = 8, - .cdw12 = select, - }; - return ioctl(fd, NVME_IOCTL_ADMIN_CMD, &cmd); + struct nvme_passthru_cmd cmd = { + .opcode = nvme_admin_fw_commit, + .cdw10 = 8, + .cdw12 = select, + }; + return ioctl(fd, NVME_IOCTL_ADMIN_CMD, &cmd); } static int micron_selective_download(int argc, char **argv, - struct command *cmd, struct plugin *plugin) + struct command *cmd, struct plugin *plugin) { - const char *desc = - "This performs a selective firmware download, which allows the user to " - "select which firmware binary to update for 9200 devices. This requires " - "a power cycle once the update completes. The options available are: \n\n" - "OOB - This updates the OOB and main firmware\n" - "EEP - This updates the eeprom and main firmware\n" - "ALL - This updates the eeprom, OOB, and main firmware"; - const char *fw = "firmware file (required)"; - const char *select = "FW Select (e.g., --select=ALL)"; - int xfer = 4096; - void *fw_buf; - int selectNo, fw_fd, fw_size, err, offset = 0; - struct nvme_dev *dev; - struct stat sb; - - struct config { - char *fw; - char *select; - }; - - struct config cfg = { - .fw = "", - .select = "\0", - }; - - OPT_ARGS(opts) = { - OPT_STRING("fw", 'f', "FILE", &cfg.fw, fw), - OPT_STRING("select", 's', "flag", &cfg.select, select), - OPT_END() - }; - - err = parse_and_open(&dev, argc, argv, desc, opts); - if (err) - return err; - - if (strlen(cfg.select) != 3) { - fprintf(stderr, "Invalid select flag\n"); - dev_close(dev); - return EINVAL; - } - - for (int i = 0; i < 3; i++) { - cfg.select[i] = toupper(cfg.select[i]); - } - - if (strncmp(cfg.select, "OOB", 3) == 0) { - selectNo = 18; - } else if (strncmp(cfg.select, "EEP", 3) == 0) { - selectNo = 10; - } else if (strncmp(cfg.select, "ALL", 3) == 0) { - selectNo = 26; - } else { - fprintf(stderr, "Invalid select flag\n"); - dev_close(dev); - return EINVAL; - } - - fw_fd = open(cfg.fw, O_RDONLY); - if (fw_fd < 0) { - fprintf(stderr, "no firmware file provided\n"); - dev_close(dev); - return EINVAL; - } - - err = fstat(fw_fd, &sb); - if (err < 0) { - perror("fstat"); - err = errno; - goto out; - } - - fw_size = sb.st_size; - if (fw_size & 0x3) { - fprintf(stderr, "Invalid size:%d for f/w image\n", fw_size); - err = EINVAL; - goto out; - } - - if (posix_memalign(&fw_buf, getpagesize(), fw_size)) { - fprintf(stderr, "No memory for f/w size:%d\n", fw_size); - err = ENOMEM; - goto out; - } - - if (read(fw_fd, fw_buf, fw_size) != ((ssize_t) (fw_size))) { - err = errno; - goto out_free; - } - - while (fw_size > 0) { - xfer = min(xfer, fw_size); - - struct nvme_fw_download_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .offset = offset, - .data_len = xfer, - .data = fw_buf, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, + const char *desc = + "This performs a selective firmware download, which allows the user to\n" + "select which firmware binary to update for 9200 devices. This requires\n" + "a power cycle once the update completes. The options available are:\n\n" + "OOB - This updates the OOB and main firmware\n" + "EEP - This updates the eeprom and main firmware\n" + "ALL - This updates the eeprom, OOB, and main firmware"; + const char *fw = "firmware file (required)"; + const char *select = "FW Select (e.g., --select=ALL)"; + int xfer = 4096; + void *fw_buf; + int selectNo, fw_fd, fw_size, err, offset = 0; + struct nvme_dev *dev; + struct stat sb; + + struct config { + char *fw; + char *select; + }; + + struct config cfg = { + .fw = "", + .select = "\0", + }; + + OPT_ARGS(opts) = { + OPT_STRING("fw", 'f', "FILE", &cfg.fw, fw), + OPT_STRING("select", 's', "flag", &cfg.select, select), + OPT_END() }; - err = nvme_fw_download(&args); - if (err < 0) { - perror("fw-download"); - goto out_free; - } else if (err != 0) { - nvme_show_status(err); - goto out_free; - } - fw_buf += xfer; - fw_size -= xfer; - offset += xfer; - } - - err = micron_fw_commit(dev_fd(dev), selectNo); - - if (err == 0x10B || err == 0x20B) { - err = 0; - fprintf(stderr, - "Update successful! Power cycle for changes to take effect\n"); - } + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; + + if (strlen(cfg.select) != 3) { + fprintf(stderr, "Invalid select flag\n"); + dev_close(dev); + return -EINVAL; + } + + for (int i = 0; i < 3; i++) + cfg.select[i] = toupper(cfg.select[i]); + + if (!strncmp(cfg.select, "OOB", 3)) { + selectNo = 18; + } else if (!strncmp(cfg.select, "EEP", 3)) { + selectNo = 10; + } else if (!strncmp(cfg.select, "ALL", 3)) { + selectNo = 26; + } else { + fprintf(stderr, "Invalid select flag\n"); + dev_close(dev); + return -EINVAL; + } + + fw_fd = open(cfg.fw, O_RDONLY); + if (fw_fd < 0) { + fprintf(stderr, "no firmware file provided\n"); + dev_close(dev); + return -EINVAL; + } + + err = fstat(fw_fd, &sb); + if (err < 0) { + perror("fstat"); + err = errno; + goto out; + } + + fw_size = sb.st_size; + if (fw_size & 0x3) { + fprintf(stderr, "Invalid size:%d for f/w image\n", fw_size); + err = EINVAL; + goto out; + } + + if (posix_memalign(&fw_buf, getpagesize(), fw_size)) { + fprintf(stderr, "No memory for f/w size:%d\n", fw_size); + err = ENOMEM; + goto out; + } + + if (read(fw_fd, fw_buf, fw_size) != ((ssize_t) (fw_size))) { + err = errno; + goto out_free; + } + + while (fw_size > 0) { + xfer = min(xfer, fw_size); + + struct nvme_fw_download_args args = { + .args_size = sizeof(args), + .fd = dev_fd(dev), + .offset = offset, + .data_len = xfer, + .data = fw_buf, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + + err = nvme_fw_download(&args); + if (err < 0) { + perror("fw-download"); + goto out_free; + } else if (err) { + nvme_show_status(err); + goto out_free; + } + fw_buf += xfer; + fw_size -= xfer; + offset += xfer; + } + + err = micron_fw_commit(dev_fd(dev), selectNo); + + if (err == 0x10B || err == 0x20B) { + err = 0; + fprintf(stderr, + "Update successful! Power cycle for changes to take effect\n"); + } out_free: - free(fw_buf); + free(fw_buf); out: - close(fw_fd); - dev_close(dev); - return err; + close(fw_fd); + dev_close(dev); + return err; } static int micron_smbus_option(int argc, char **argv, - struct command *cmd, struct plugin *plugin) + struct command *cmd, struct plugin *plugin) { - __u32 result = 0; - __u32 cdw11 = 0; - const char *desc = "Enable/Disable/Get status of SMBUS option on controller"; - const char *option = "enable or disable or status"; - const char *value = "1 - hottest component temperature, 0 - composite " - "temperature (default) for enable option, 0 (current), " - "1 (default), 2 (saved) for status options"; - const char *save = "1 - persistent, 0 - non-persistent (default)"; - int fid = MICRON_FEATURE_SMBUS_OPTION; - eDriveModel model = UNKNOWN_MODEL; - struct nvme_dev *dev; - int err = 0; - - struct { - char *option; - int value; - int save; - int status; - } opt = { - .option = "disable", - .value = 0, - .save = 0, - .status = 0, - }; - - OPT_ARGS(opts) = { - OPT_STRING("option", 'o', "option", &opt.option, option), - OPT_UINT("value", 'v', &opt.value, value), - OPT_UINT("save", 's', &opt.save, save), - OPT_END() - }; - - err = micron_parse_options(&dev, argc, argv, desc, opts, &model); - if (err < 0) - return err; - - if (model != M5407 && model != M5411) { - printf ("This option is not supported for specified drive\n"); - dev_close(dev); - return err; - } - - if (!strcmp(opt.option, "enable")) { - cdw11 = opt.value << 1 | 1; - err = nvme_set_features_simple(dev_fd(dev), fid, 1, cdw11, opt.save, - &result); - if (err == 0) { - printf("successfully enabled SMBus on drive\n"); - } else { - printf("Failed to enabled SMBus on drive\n"); - } - } - else if (!strcmp(opt.option, "status")) { - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = fid, - .nsid = 1, - .sel = opt.value, - .cdw11 = 0, - .uuidx = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - err = nvme_get_features(&args); - if (err == 0) { - printf("SMBus status on the drive: %s (returns %s temperature) \n", - (result & 1) ? "enabled" : "disabled", - (result & 2) ? "hottest component" : "composite"); - } else { - printf("Failed to retrieve SMBus status on the drive\n"); - } - } - else if (!strcmp(opt.option, "disable")) { - cdw11 = opt.value << 1 | 0; - err = nvme_set_features_simple(dev_fd(dev), fid, 1, cdw11, opt.save, - &result); - if (err == 0) { - printf("Successfully disabled SMBus on drive\n"); - } else { - printf("Failed to disable SMBus on drive\n"); - } - } else { - printf("Invalid option %s, valid values are enable, disable or status\n", - opt.option); - dev_close(dev); - return -1; - } - - close(dev_fd(dev)); - return err; + __u32 result = 0; + __u32 cdw11 = 0; + const char *desc = "Enable/Disable/Get status of SMBUS option on controller"; + const char *option = "enable or disable or status"; + const char *value = + "1 - hottest component temperature, 0 - composite temperature (default) for enable option, 0 (current), 1 (default), 2 (saved) for status options"; + const char *save = "1 - persistent, 0 - non-persistent (default)"; + int fid = MICRON_FEATURE_SMBUS_OPTION; + enum eDriveModel model = UNKNOWN_MODEL; + struct nvme_dev *dev; + int err = 0; + + struct { + char *option; + int value; + int save; + int status; + } opt = { + .option = "disable", + .value = 0, + .save = 0, + .status = 0, + }; + + OPT_ARGS(opts) = { + OPT_STRING("option", 'o', "option", &opt.option, option), + OPT_UINT("value", 'v', &opt.value, value), + OPT_UINT("save", 's', &opt.save, save), + OPT_END() + }; + + err = micron_parse_options(&dev, argc, argv, desc, opts, &model); + if (err < 0) + return err; + + if (model != M5407 && model != M5411) { + printf("This option is not supported for specified drive\n"); + dev_close(dev); + return err; + } + + if (!strcmp(opt.option, "enable")) { + cdw11 = opt.value << 1 | 1; + err = nvme_set_features_simple(dev_fd(dev), fid, 1, cdw11, opt.save, + &result); + if (!err) + printf("successfully enabled SMBus on drive\n"); + else + printf("Failed to enabled SMBus on drive\n"); + } else if (!strcmp(opt.option, "status")) { + struct nvme_get_features_args args = { + .args_size = sizeof(args), + .fd = dev_fd(dev), + .fid = fid, + .nsid = 1, + .sel = opt.value, + .cdw11 = 0, + .uuidx = 0, + .data_len = 0, + .data = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + + err = nvme_get_features(&args); + if (!err) + printf("SMBus status on the drive: %s (returns %s temperature)\n", + (result & 1) ? "enabled" : "disabled", + (result & 2) ? "hottest component" : "composite"); + else + printf("Failed to retrieve SMBus status on the drive\n"); + } else if (!strcmp(opt.option, "disable")) { + cdw11 = opt.value << 1 | 0; + err = nvme_set_features_simple(dev_fd(dev), fid, 1, cdw11, opt.save, + &result); + if (!err) + printf("Successfully disabled SMBus on drive\n"); + else + printf("Failed to disable SMBus on drive\n"); + } else { + printf("Invalid option %s, valid values are enable, disable or status\n", + opt.option); + dev_close(dev); + return -1; + } + + close(dev_fd(dev)); + return err; } static int micron_temp_stats(int argc, char **argv, struct command *cmd, - struct plugin *plugin) + struct plugin *plugin) { - struct nvme_smart_log smart_log; - unsigned int temperature = 0, i = 0, err = 0; - unsigned int tempSensors[SensorCount] = { 0 }; - const char *desc = "Retrieve Micron temperature info for the given device "; - const char *fmt = "output format normal|json"; - struct format { - char *fmt; - }; - struct format cfg = { - .fmt = "normal", - }; - bool is_json = false; - struct json_object *root; - struct json_object *logPages; - struct nvme_dev *dev; - - OPT_ARGS(opts) = { - OPT_FMT("format", 'f', &cfg.fmt, fmt), - OPT_END() - }; - - err = parse_and_open(&dev, argc, argv, desc, opts); - if (err) { - printf("\nDevice not found \n");; - return -1; - } - - if (strcmp(cfg.fmt, "json") == 0) - is_json = true; - - err = nvme_get_log_smart(dev_fd(dev), 0xffffffff, false, &smart_log); - if (!err) { - temperature = ((smart_log.temperature[1] << 8) | smart_log.temperature[0]); - temperature = temperature ? temperature - 273 : 0; - for (i = 0; i < SensorCount && tempSensors[i] != 0; i++) { - tempSensors[i] = le16_to_cpu(smart_log.temp_sensor[i]); - tempSensors[i] = tempSensors[i] ? tempSensors[i] - 273 : 0; - } - if (is_json) { - struct json_object *stats = json_create_object(); - char tempstr[64] = { 0 }; - root = json_create_object(); - logPages = json_create_array(); - json_object_add_value_array(root, "Micron temperature information", logPages); - sprintf(tempstr, "%u C", temperature); - json_object_add_value_string(stats, "Current Composite Temperature", tempstr); - for (i = 0; i < SensorCount && tempSensors[i] != 0; i++) { - char sensor_str[256] = { 0 }; - char datastr[64] = { 0 }; - sprintf(sensor_str, "Temperature Sensor #%d", (i + 1)); - sprintf(datastr, "%u C", tempSensors[i]); - json_object_add_value_string(stats, sensor_str, datastr); - } - json_array_add_value_object(logPages, stats); - json_print_object(root, NULL); - printf("\n"); - json_free_object(root); - } else { - printf("Micron temperature information:\n"); - printf("%-10s : %u C\n", "Current Composite Temperature", temperature); - for (i = 0; i < SensorCount && tempSensors[i] != 0; i++) { - printf("%-10s%d : %u C\n", "Temperature Sensor #", i + 1, tempSensors[i]); - } - } - } - dev_close(dev); - return err; + struct nvme_smart_log smart_log; + unsigned int temperature = 0, i = 0, err = 0; + unsigned int tempSensors[SensorCount] = { 0 }; + const char *desc = "Retrieve Micron temperature info for the given device "; + const char *fmt = "output format normal|json"; + struct format { + char *fmt; + }; + struct format cfg = { + .fmt = "normal", + }; + bool is_json = false; + struct json_object *root; + struct json_object *logPages; + struct nvme_dev *dev; + + OPT_ARGS(opts) = { + OPT_FMT("format", 'f', &cfg.fmt, fmt), + OPT_END() + }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) { + printf("\nDevice not found\n"); + return -1; + } + + if (!strcmp(cfg.fmt, "json")) + is_json = true; + + err = nvme_get_log_smart(dev_fd(dev), 0xffffffff, false, &smart_log); + if (!err) { + temperature = ((smart_log.temperature[1] << 8) | smart_log.temperature[0]); + temperature = temperature ? temperature - 273 : 0; + for (i = 0; i < SensorCount && tempSensors[i]; i++) { + tempSensors[i] = le16_to_cpu(smart_log.temp_sensor[i]); + tempSensors[i] = tempSensors[i] ? tempSensors[i] - 273 : 0; + } + if (is_json) { + struct json_object *stats = json_create_object(); + char tempstr[64] = { 0 }; + + root = json_create_object(); + logPages = json_create_array(); + json_object_add_value_array(root, "Micron temperature information", logPages); + sprintf(tempstr, "%u C", temperature); + json_object_add_value_string(stats, "Current Composite Temperature", tempstr); + for (i = 0; i < SensorCount && tempSensors[i]; i++) { + char sensor_str[256] = { 0 }; + char datastr[64] = { 0 }; + + sprintf(sensor_str, "Temperature Sensor #%d", (i + 1)); + sprintf(datastr, "%u C", tempSensors[i]); + json_object_add_value_string(stats, sensor_str, datastr); + } + json_array_add_value_object(logPages, stats); + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); + } else { + printf("Micron temperature information:\n"); + printf("%-10s : %u C\n", "Current Composite Temperature", temperature); + for (i = 0; i < SensorCount && tempSensors[i]; i++) + printf("%-10s%d : %u C\n", "Temperature Sensor #", i + 1, tempSensors[i]); + } + } + dev_close(dev); + return err; } static int micron_pcie_stats(int argc, char **argv, - struct command *cmd, struct plugin *plugin) + struct command *cmd, struct plugin *plugin) { - int i, err = 0, bus = 0, domain = 0, device = 0, function = 0, ctrlIdx; - char strTempFile[1024], strTempFile2[1024], command[1024]; - struct nvme_dev *dev; - char *businfo = NULL; - char *devicename = NULL; - char tdevice[NAME_MAX] = { 0 }; - ssize_t sLinkSize = 0; - FILE *fp; - char correctable[8] = { 0 }; - char uncorrectable[8] = { 0 }; - struct nvme_passthru_cmd admin_cmd = { 0 }; - eDriveModel eModel = UNKNOWN_MODEL; - char *res; - bool is_json = true; - bool counters = false; - struct format { - char *fmt; - }; - const char *desc = "Retrieve PCIe event counters"; - const char *fmt = "output format json|normal"; - struct format cfg = { - .fmt = "json", - }; - struct pcie_error_counters { - __u16 receiver_error; - __u16 bad_tlp; - __u16 bad_dllp; - __u16 replay_num_rollover; - __u16 replay_timer_timeout; - __u16 advisory_non_fatal_error; - __u16 DLPES; - __u16 poisoned_tlp; - __u16 FCPC; - __u16 completion_timeout; - __u16 completion_abort; - __u16 unexpected_completion; - __u16 receiver_overflow; - __u16 malformed_tlp; - __u16 ecrc_error; - __u16 unsupported_request_error; - } pcie_error_counters = { 0 }; - - struct { - char *err; - int bit; - int val; - } pcie_correctable_errors[] = { - { "Unsupported Request Error Status (URES)", 20, + int i, err = 0, bus, domain, device, function, ctrlIdx; + char strTempFile[1024], strTempFile2[1024], command[1024]; + struct nvme_dev *dev; + char *businfo = NULL; + char *devicename = NULL; + char tdevice[NAME_MAX] = { 0 }; + ssize_t sLinkSize = 0; + FILE *fp; + char correctable[8] = { 0 }; + char uncorrectable[8] = { 0 }; + struct nvme_passthru_cmd admin_cmd = { 0 }; + enum eDriveModel eModel = UNKNOWN_MODEL; + char *res; + bool is_json = true; + bool counters = false; + struct format { + char *fmt; + }; + const char *desc = "Retrieve PCIe event counters"; + const char *fmt = "output format json|normal"; + struct format cfg = { + .fmt = "json", + }; + struct pcie_error_counters { + __u16 receiver_error; + __u16 bad_tlp; + __u16 bad_dllp; + __u16 replay_num_rollover; + __u16 replay_timer_timeout; + __u16 advisory_non_fatal_error; + __u16 DLPES; + __u16 poisoned_tlp; + __u16 FCPC; + __u16 completion_timeout; + __u16 completion_abort; + __u16 unexpected_completion; + __u16 receiver_overflow; + __u16 malformed_tlp; + __u16 ecrc_error; + __u16 unsupported_request_error; + } pcie_error_counters = { 0 }; + + struct { + char *err; + int bit; + int val; + } pcie_correctable_errors[] = { + { "Unsupported Request Error Status (URES)", 20, offsetof(struct pcie_error_counters, unsupported_request_error)}, - { "ECRC Error Status (ECRCES)", 19, + { "ECRC Error Status (ECRCES)", 19, offsetof(struct pcie_error_counters, ecrc_error)}, - { "Malformed TLP Status (MTS)", 18, + { "Malformed TLP Status (MTS)", 18, offsetof(struct pcie_error_counters, malformed_tlp)}, - { "Receiver Overflow Status (ROS)", 17, + { "Receiver Overflow Status (ROS)", 17, offsetof(struct pcie_error_counters, receiver_overflow)}, - { "Unexpected Completion Status (UCS)", 16, + { "Unexpected Completion Status (UCS)", 16, offsetof(struct pcie_error_counters, unexpected_completion)}, - { "Completer Abort Status (CAS)", 15, + { "Completer Abort Status (CAS)", 15, offsetof(struct pcie_error_counters, completion_abort)}, - { "Completion Timeout Status (CTS)", 14, + { "Completion Timeout Status (CTS)", 14, offsetof(struct pcie_error_counters, completion_timeout)}, - { "Flow Control Protocol Error Status (FCPES)", 13, + { "Flow Control Protocol Error Status (FCPES)", 13, offsetof(struct pcie_error_counters, FCPC)}, - { "Poisoned TLP Status (PTS)", 12, + { "Poisoned TLP Status (PTS)", 12, offsetof(struct pcie_error_counters, poisoned_tlp)}, - { "Data Link Protocol Error Status (DLPES)", 4, + { "Data Link Protocol Error Status (DLPES)", 4, offsetof(struct pcie_error_counters, DLPES)}, - }, - pcie_uncorrectable_errors[] = { - { "Advisory Non-Fatal Error Status (ANFES)", 13, + }, + pcie_uncorrectable_errors[] = { + { "Advisory Non-Fatal Error Status (ANFES)", 13, offsetof(struct pcie_error_counters, advisory_non_fatal_error)}, - { "Replay Timer Timeout Status (RTS)", 12, + { "Replay Timer Timeout Status (RTS)", 12, offsetof(struct pcie_error_counters, replay_timer_timeout)}, - { "REPLAY_NUM Rollover Status (RRS)", 8, + { "REPLAY_NUM Rollover Status (RRS)", 8, offsetof(struct pcie_error_counters, replay_num_rollover)}, - { "Bad DLLP Status (BDS)", 7, + { "Bad DLLP Status (BDS)", 7, offsetof(struct pcie_error_counters, bad_dllp)}, - { "Bad TLP Status (BTS)", 6, + { "Bad TLP Status (BTS)", 6, offsetof(struct pcie_error_counters, bad_tlp)}, - { "Receiver Error Status (RES)", 0, + { "Receiver Error Status (RES)", 0, offsetof(struct pcie_error_counters, receiver_error)}, - }; - - __u32 correctable_errors; - __u32 uncorrectable_errors; - - OPT_ARGS(opts) = { - OPT_FMT("format", 'f', &cfg.fmt, fmt), - OPT_END() - }; - - err = parse_and_open(&dev, argc, argv, desc, opts); - if (err) { - printf("\nDevice not found \n");; - return -1; - } - - /* pull log details based on the model name */ - sscanf(argv[optind], "/dev/nvme%d", &ctrlIdx); - if ((eModel = GetDriveModel(ctrlIdx)) == UNKNOWN_MODEL) { - printf ("Unsupported drive model for vs-pcie-stats command\n"); - goto out; - } - - if (strcmp(cfg.fmt, "normal") == 0) - is_json = false; - - if (eModel == M5407) { - admin_cmd.opcode = 0xD6; - admin_cmd.addr = (__u64)(uintptr_t)&pcie_error_counters; - admin_cmd.data_len = sizeof(pcie_error_counters); - admin_cmd.cdw10 = 1; - err = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); - if (!err) { - counters = true; - correctable_errors = 10; - uncorrectable_errors = 6; - goto print_stats; - } - } - - if (strstr(argv[optind], "/dev/nvme") && strstr(argv[optind], "n1")) { - devicename = strrchr(argv[optind], '/'); - } else if (strstr(argv[optind], "/dev/nvme")) { - devicename = strrchr(argv[optind], '/'); - sprintf(tdevice, "%s%s", devicename, "n1"); - devicename = tdevice; - } else { - printf("Invalid device specified!\n"); - goto out; - } - sprintf(strTempFile, "/sys/block/%s/device", devicename); - memset(strTempFile2, 0x0, 1024); - sLinkSize = readlink(strTempFile, strTempFile2, 1023); - if (sLinkSize < 0) { - err = -errno; - printf("Failed to read device\n"); - goto out; - } - if (strstr(strTempFile2, "../../nvme")) { - sprintf(strTempFile, "/sys/block/%s/device/device", devicename); - memset(strTempFile2, 0x0, 1024); - sLinkSize = readlink(strTempFile, strTempFile2, 1023); - if (sLinkSize < 0) { - err = -errno; - printf("Failed to read device\n"); - goto out; - } - } - businfo = strrchr(strTempFile2, '/'); - sscanf(businfo, "/%x:%x:%x.%x", &domain, &bus, &device, &function); - sprintf(command, "setpci -s %x:%x.%x ECAP_AER+10.L", bus, device, - function); - fp = popen(command, "r"); - if (fp == NULL) { - printf("Failed to retrieve error count\n"); - goto out; - } - res = fgets(correctable, sizeof(correctable), fp); - if (res == NULL) { - printf("Failed to retrieve error count\n"); - pclose(fp); - goto out; - } - pclose(fp); - - sprintf(command, "setpci -s %x:%x.%x ECAP_AER+0x4.L", bus, device, - function); - fp = popen(command, "r"); - if (fp == NULL) { - printf("Failed to retrieve error count\n"); - goto out; - } - res = fgets(uncorrectable, sizeof(uncorrectable), fp); - if (res == NULL) { - printf("Failed to retrieve error count\n"); - pclose(fp); - goto out; - } - pclose(fp); - - correctable_errors = (__u32)strtol(correctable, NULL, 16); - uncorrectable_errors = (__u32)strtol(uncorrectable, NULL, 16); + }; + + __u32 correctable_errors; + __u32 uncorrectable_errors; + + OPT_ARGS(opts) = { + OPT_FMT("format", 'f', &cfg.fmt, fmt), + OPT_END() + }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) { + printf("\nDevice not found\n"); + return -1; + } + + /* pull log details based on the model name */ + if (sscanf(argv[optind], "/dev/nvme%d", &ctrlIdx) != 1) + ctrlIdx = 0; + eModel = GetDriveModel(ctrlIdx); + if (eModel == UNKNOWN_MODEL) { + printf("Unsupported drive model for vs-pcie-stats command\n"); + goto out; + } + + if (!strcmp(cfg.fmt, "normal")) + is_json = false; + + if (eModel == M5407) { + admin_cmd.opcode = 0xD6; + admin_cmd.addr = (__u64)(uintptr_t)&pcie_error_counters; + admin_cmd.data_len = sizeof(pcie_error_counters); + admin_cmd.cdw10 = 1; + err = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); + if (!err) { + counters = true; + correctable_errors = 10; + uncorrectable_errors = 6; + goto print_stats; + } + } + + if (strstr(argv[optind], "/dev/nvme") && strstr(argv[optind], "n1")) { + devicename = strrchr(argv[optind], '/'); + } else if (strstr(argv[optind], "/dev/nvme")) { + devicename = strrchr(argv[optind], '/'); + sprintf(tdevice, "%s%s", devicename, "n1"); + devicename = tdevice; + } else { + printf("Invalid device specified!\n"); + goto out; + } + sprintf(strTempFile, "/sys/block/%s/device", devicename); + memset(strTempFile2, 0x0, 1024); + sLinkSize = readlink(strTempFile, strTempFile2, 1023); + if (sLinkSize < 0) { + err = -errno; + printf("Failed to read device\n"); + goto out; + } + if (strstr(strTempFile2, "../../nvme")) { + sprintf(strTempFile, "/sys/block/%s/device/device", devicename); + memset(strTempFile2, 0x0, 1024); + sLinkSize = readlink(strTempFile, strTempFile2, 1023); + if (sLinkSize < 0) { + err = -errno; + printf("Failed to read device\n"); + goto out; + } + } + businfo = strrchr(strTempFile2, '/'); + if (sscanf(businfo, "/%x:%x:%x.%x", &domain, &bus, &device, &function) != 4) + domain = bus = device = function = 0; + sprintf(command, "setpci -s %x:%x.%x ECAP_AER+10.L", bus, device, + function); + fp = popen(command, "r"); + if (!fp) { + printf("Failed to retrieve error count\n"); + goto out; + } + res = fgets(correctable, sizeof(correctable), fp); + if (!res) { + printf("Failed to retrieve error count\n"); + pclose(fp); + goto out; + } + pclose(fp); + + sprintf(command, "setpci -s %x:%x.%x ECAP_AER+0x4.L", bus, device, + function); + fp = popen(command, "r"); + if (!fp) { + printf("Failed to retrieve error count\n"); + goto out; + } + res = fgets(uncorrectable, sizeof(uncorrectable), fp); + if (!res) { + printf("Failed to retrieve error count\n"); + pclose(fp); + goto out; + } + pclose(fp); + + correctable_errors = (__u32)strtol(correctable, NULL, 16); + uncorrectable_errors = (__u32)strtol(uncorrectable, NULL, 16); print_stats: - if (is_json) { - - struct json_object *root = json_create_object(); - struct json_object *pcieErrors = json_create_array(); - struct json_object *stats = json_create_object(); - __u8 *pcounter = (__u8 *)&pcie_error_counters; - - json_object_add_value_array(root, "PCIE Stats", pcieErrors); - for (i = 0; i < sizeof(pcie_correctable_errors) / sizeof(pcie_correctable_errors[0]); i++) { - __u16 val = counters ? *(__u16 *)(pcounter + pcie_correctable_errors[i].val) : - (correctable_errors >> pcie_correctable_errors[i].bit) & 1; - json_object_add_value_int(stats, pcie_correctable_errors[i].err, val); - } - for (i = 0; i < sizeof(pcie_uncorrectable_errors) / sizeof(pcie_uncorrectable_errors[0]); i++) { - __u16 val = counters ? *(__u16 *)(pcounter + pcie_uncorrectable_errors[i].val) : - (uncorrectable_errors >> pcie_uncorrectable_errors[i].bit) & 1; - json_object_add_value_int(stats, pcie_uncorrectable_errors[i].err, val); - } - json_array_add_value_object(pcieErrors, stats); - json_print_object(root, NULL); - printf("\n"); - json_free_object(root); - } else if (counters == true) { - __u8 *pcounter = (__u8 *)&pcie_error_counters; - for (i = 0; i < sizeof(pcie_correctable_errors) / sizeof(pcie_correctable_errors[0]); i++) { - printf("%-42s : %-1hu\n", pcie_correctable_errors[i].err, - *(__u16 *)(pcounter + pcie_correctable_errors[i].val)); - } - for (i = 0; i < sizeof(pcie_uncorrectable_errors) / sizeof(pcie_uncorrectable_errors[0]); i++) { - printf("%-42s : %-1hu\n", pcie_uncorrectable_errors[i].err, - *(__u16 *)(pcounter + pcie_uncorrectable_errors[i].val)); - } - } else if (eModel == M5407 || eModel == M5410) { - for (i = 0; i < sizeof(pcie_correctable_errors) / sizeof(pcie_correctable_errors[0]); i++) { - printf("%-42s : %-1d\n", pcie_correctable_errors[i].err, - ((correctable_errors >> pcie_correctable_errors[i].bit) & 1)); - } - for (i = 0; i < sizeof(pcie_uncorrectable_errors) / sizeof(pcie_uncorrectable_errors[0]); i++) { - printf("%-42s : %-1d\n", pcie_uncorrectable_errors[i].err, - ((uncorrectable_errors >> pcie_uncorrectable_errors[i].bit) & 1)); - } - } else { - printf("PCIE Stats:\n"); - printf("Device correctable errors detected: %s\n", correctable); - printf("Device uncorrectable errors detected: %s\n", uncorrectable); - } + if (is_json) { + struct json_object *root = json_create_object(); + struct json_object *pcieErrors = json_create_array(); + struct json_object *stats = json_create_object(); + __u8 *pcounter = (__u8 *)&pcie_error_counters; + + json_object_add_value_array(root, "PCIE Stats", pcieErrors); + for (i = 0; i < ARRAY_SIZE(pcie_correctable_errors); i++) { + __u16 val = counters ? *(__u16 *)(pcounter + pcie_correctable_errors[i].val) : + (correctable_errors >> pcie_correctable_errors[i].bit) & 1; + json_object_add_value_int(stats, pcie_correctable_errors[i].err, val); + } + for (i = 0; i < ARRAY_SIZE(pcie_uncorrectable_errors); i++) { + __u16 val = counters ? *(__u16 *)(pcounter + pcie_uncorrectable_errors[i].val) : + (uncorrectable_errors >> pcie_uncorrectable_errors[i].bit) & 1; + json_object_add_value_int(stats, pcie_uncorrectable_errors[i].err, val); + } + json_array_add_value_object(pcieErrors, stats); + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); + } else if (counters == true) { + __u8 *pcounter = (__u8 *)&pcie_error_counters; + + for (i = 0; i < ARRAY_SIZE(pcie_correctable_errors); i++) + printf("%-42s : %-1hu\n", pcie_correctable_errors[i].err, + *(__u16 *)(pcounter + pcie_correctable_errors[i].val)); + for (i = 0; i < ARRAY_SIZE(pcie_uncorrectable_errors); i++) + printf("%-42s : %-1hu\n", pcie_uncorrectable_errors[i].err, + *(__u16 *)(pcounter + pcie_uncorrectable_errors[i].val)); + } else if (eModel == M5407 || eModel == M5410) { + for (i = 0; i < ARRAY_SIZE(pcie_correctable_errors); i++) + printf("%-42s : %-1d\n", pcie_correctable_errors[i].err, + ((correctable_errors >> pcie_correctable_errors[i].bit) & 1)); + for (i = 0; i < ARRAY_SIZE(pcie_uncorrectable_errors); i++) + printf("%-42s : %-1d\n", pcie_uncorrectable_errors[i].err, + ((uncorrectable_errors >> pcie_uncorrectable_errors[i].bit) & 1)); + } else { + printf("PCIE Stats:\n"); + printf("Device correctable errors detected: %s\n", correctable); + printf("Device uncorrectable errors detected: %s\n", uncorrectable); + } out: - dev_close(dev); - return err; + dev_close(dev); + return err; } static int micron_clear_pcie_correctable_errors(int argc, char **argv, - struct command *cmd, - struct plugin *plugin) + struct command *cmd, + struct plugin *plugin) { - int err = -EINVAL, bus = 0, domain = 0, device = 0, function = 0; - char strTempFile[1024], strTempFile2[1024], command[1024]; - struct nvme_dev *dev; - char *businfo = NULL; - char *devicename = NULL; - char tdevice[PATH_MAX] = { 0 }; - ssize_t sLinkSize = 0; - eDriveModel model = UNKNOWN_MODEL; - struct nvme_passthru_cmd admin_cmd = { 0 }; - char correctable[8] = { 0 }; - FILE *fp; - char *res; - const char *desc = "Clear PCIe Device Correctable Errors"; - __u32 result = 0; - __u8 fid = MICRON_FEATURE_CLEAR_PCI_CORRECTABLE_ERRORS; - OPT_ARGS(opts) = { - OPT_END() - }; - - err = micron_parse_options(&dev, argc, argv, desc, opts, &model); - if (err < 0) - return err; - - /* For M51CX models, PCIe errors are cleared using 0xC3 feature */ - if (model == M51CX) { - err = nvme_set_features_simple(dev_fd(dev), fid, 0, (1 << 31), false, - &result); - if (err == 0 && (err = (int)result) == 0) { - printf("Device correctable errors are cleared!\n"); - goto out; - } - } else if (model == M5407) { - admin_cmd.opcode = 0xD6; - admin_cmd.addr = 0; - admin_cmd.cdw10 = 0; - err = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); - if (err == 0) { - printf("Device correctable error counters are cleared!\n"); - goto out; - } else { - /* proceed to clear status bits using sysfs interface - printf("Error clearing PCIe correctable errors = 0x%x\n", err); */ - } - } - - if (strstr(argv[optind], "/dev/nvme") && strstr(argv[optind], "n1")) { - devicename = strrchr(argv[optind], '/'); - } else if (strstr(argv[optind], "/dev/nvme")) { - devicename = strrchr(argv[optind], '/'); - sprintf(tdevice, "%s%s", devicename, "n1"); - devicename = tdevice; - } else { - printf("Invalid device specified!\n"); - goto out; - } - err = snprintf(strTempFile, sizeof(strTempFile), - "/sys/block/%s/device", devicename); - if (err < 0) - goto out; - - memset(strTempFile2, 0x0, 1024); - sLinkSize = readlink(strTempFile, strTempFile2, 1023); - if (sLinkSize < 0) { - err = -errno; - printf("Failed to read device\n"); - goto out; - } - if (strstr(strTempFile2, "../../nvme")) { - err = snprintf(strTempFile, sizeof(strTempFile), - "/sys/block/%s/device/device", devicename); - if (err < 0) - goto out; - memset(strTempFile2, 0x0, 1024); - sLinkSize = readlink(strTempFile, strTempFile2, 1023); - if (sLinkSize < 0) { - err = -errno; - printf("Failed to read device\n"); - goto out; - } - } - businfo = strrchr(strTempFile2, '/'); - sscanf(businfo, "/%x:%x:%x.%x", &domain, &bus, &device, &function); - sprintf(command, "setpci -s %x:%x.%x ECAP_AER+0x10.L=0xffffffff", bus, - device, function); - err = -1; - fp = popen(command, "r"); - if (fp == NULL) { - printf("Failed to clear error count\n"); - goto out; - } - pclose(fp); - - sprintf(command, "setpci -s %x:%x.%x ECAP_AER+0x10.L", bus, device, - function); - fp = popen(command, "r"); - if (fp == NULL) { - printf("Failed to retrieve error count\n"); - goto out; - } - res = fgets(correctable, sizeof(correctable), fp); - if (res == NULL) { - printf("Failed to retrieve error count\n"); - pclose(fp); - goto out; - } - pclose(fp); - printf("Device correctable errors cleared!\n"); - printf("Device correctable errors detected: %s\n", correctable); - err = 0; + int err = -EINVAL, bus, domain, device, function; + char strTempFile[1024], strTempFile2[1024], command[1024]; + struct nvme_dev *dev; + char *businfo = NULL; + char *devicename = NULL; + char tdevice[PATH_MAX] = { 0 }; + ssize_t sLinkSize = 0; + enum eDriveModel model = UNKNOWN_MODEL; + struct nvme_passthru_cmd admin_cmd = { 0 }; + char correctable[8] = { 0 }; + FILE *fp; + char *res; + const char *desc = "Clear PCIe Device Correctable Errors"; + __u32 result = 0; + __u8 fid = MICRON_FEATURE_CLEAR_PCI_CORRECTABLE_ERRORS; + + OPT_ARGS(opts) = { + OPT_END() + }; + + err = micron_parse_options(&dev, argc, argv, desc, opts, &model); + if (err < 0) + return err; + + /* For M51CX models, PCIe errors are cleared using 0xC3 feature */ + if (model == M51CX) { + err = nvme_set_features_simple(dev_fd(dev), fid, 0, (1 << 31), false, + &result); + if (!err) + err = (int)result; + if (!err) { + printf("Device correctable errors are cleared!\n"); + goto out; + } + } else if (model == M5407) { + admin_cmd.opcode = 0xD6; + admin_cmd.addr = 0; + admin_cmd.cdw10 = 0; + err = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); + if (!err) { + printf("Device correctable error counters are cleared!\n"); + goto out; + } else { + /* proceed to clear status bits using sysfs interface */ + } + } + + if (strstr(argv[optind], "/dev/nvme") && strstr(argv[optind], "n1")) { + devicename = strrchr(argv[optind], '/'); + } else if (strstr(argv[optind], "/dev/nvme")) { + devicename = strrchr(argv[optind], '/'); + sprintf(tdevice, "%s%s", devicename, "n1"); + devicename = tdevice; + } else { + printf("Invalid device specified!\n"); + goto out; + } + err = snprintf(strTempFile, sizeof(strTempFile), + "/sys/block/%s/device", devicename); + if (err < 0) + goto out; + + memset(strTempFile2, 0x0, 1024); + sLinkSize = readlink(strTempFile, strTempFile2, 1023); + if (sLinkSize < 0) { + err = -errno; + printf("Failed to read device\n"); + goto out; + } + if (strstr(strTempFile2, "../../nvme")) { + err = snprintf(strTempFile, sizeof(strTempFile), + "/sys/block/%s/device/device", devicename); + if (err < 0) + goto out; + memset(strTempFile2, 0x0, 1024); + sLinkSize = readlink(strTempFile, strTempFile2, 1023); + if (sLinkSize < 0) { + err = -errno; + printf("Failed to read device\n"); + goto out; + } + } + businfo = strrchr(strTempFile2, '/'); + if (sscanf(businfo, "/%x:%x:%x.%x", &domain, &bus, &device, &function) != 4) + domain = bus = device = function = 0; + sprintf(command, "setpci -s %x:%x.%x ECAP_AER+0x10.L=0xffffffff", bus, + device, function); + err = -1; + fp = popen(command, "r"); + if (!fp) { + printf("Failed to clear error count\n"); + goto out; + } + pclose(fp); + + sprintf(command, "setpci -s %x:%x.%x ECAP_AER+0x10.L", bus, device, + function); + fp = popen(command, "r"); + if (!fp) { + printf("Failed to retrieve error count\n"); + goto out; + } + res = fgets(correctable, sizeof(correctable), fp); + if (!res) { + printf("Failed to retrieve error count\n"); + pclose(fp); + goto out; + } + pclose(fp); + printf("Device correctable errors cleared!\n"); + printf("Device correctable errors detected: %s\n", correctable); + err = 0; out: - dev_close(dev); - return err; + dev_close(dev); + return err; } static struct logpage { - const char *field; - char datastr[128]; + const char *field; + char datastr[128]; } d0_log_page[] = { - { "NAND Writes (Bytes Written)", { 0 }}, - { "Program Failure Count", { 0 }}, - { "Erase Failures", { 0 }}, - { "Bad Block Count", { 0 }}, - { "NAND XOR/RAID Recovery Trigger Events", { 0 }}, - { "NSZE Change Supported", { 0 }}, - { "Number of NSZE Modifications", { 0 }} + { "NAND Writes (Bytes Written)", { 0 }}, + { "Program Failure Count", { 0 }}, + { "Erase Failures", { 0 }}, + { "Bad Block Count", { 0 }}, + { "NAND XOR/RAID Recovery Trigger Events", { 0 }}, + { "NSZE Change Supported", { 0 }}, + { "Number of NSZE Modifications", { 0 }} }; static void init_d0_log_page(__u8 *buf, __u8 nsze) { - unsigned int logD0[D0_log_size/sizeof(int)] = { 0 }; - __u64 count_lo, count_hi, count; + unsigned int logD0[D0_log_size/sizeof(int)] = { 0 }; + __u64 count_lo, count_hi, count; - memcpy(logD0, buf, sizeof(logD0)); + memcpy(logD0, buf, sizeof(logD0)); - count = ((__u64)logD0[45] << 32) | logD0[44]; - sprintf(d0_log_page[0].datastr, "0x%"PRIx64, le64_to_cpu(count)); + count = ((__u64)logD0[45] << 32) | logD0[44]; + sprintf(d0_log_page[0].datastr, "0x%"PRIx64, le64_to_cpu(count)); - count_hi = ((__u64)logD0[39] << 32) | logD0[38]; - count_lo = ((__u64)logD0[37] << 32) | logD0[36]; - if (count_hi != 0) - sprintf(d0_log_page[1].datastr, "0x%"PRIx64"%016"PRIx64, - le64_to_cpu(count_hi), le64_to_cpu(count_lo)); - else - sprintf(d0_log_page[1].datastr, "0x%"PRIx64, le64_to_cpu(count_lo)); + count_hi = ((__u64)logD0[39] << 32) | logD0[38]; + count_lo = ((__u64)logD0[37] << 32) | logD0[36]; + if (count_hi) + sprintf(d0_log_page[1].datastr, "0x%"PRIx64"%016"PRIx64, + le64_to_cpu(count_hi), le64_to_cpu(count_lo)); + else + sprintf(d0_log_page[1].datastr, "0x%"PRIx64, le64_to_cpu(count_lo)); - count = ((__u64)logD0[25] << 32) | logD0[24]; - sprintf(d0_log_page[2].datastr, "0x%"PRIx64, le64_to_cpu(count)); + count = ((__u64)logD0[25] << 32) | logD0[24]; + sprintf(d0_log_page[2].datastr, "0x%"PRIx64, le64_to_cpu(count)); - sprintf(d0_log_page[3].datastr, "0x%x", logD0[3]); + sprintf(d0_log_page[3].datastr, "0x%x", logD0[3]); - count_lo = ((__u64)logD0[37] << 32) | logD0[36]; - count = ((__u64)logD0[25] << 32) | logD0[24]; - count = (__u64)logD0[3] - (count_lo + count); - sprintf(d0_log_page[4].datastr, "0x%"PRIx64, le64_to_cpu(count)); + count_lo = ((__u64)logD0[37] << 32) | logD0[36]; + count = ((__u64)logD0[25] << 32) | logD0[24]; + count = (__u64)logD0[3] - (count_lo + count); + sprintf(d0_log_page[4].datastr, "0x%"PRIx64, le64_to_cpu(count)); - sprintf(d0_log_page[5].datastr, "0x%x", nsze); - sprintf(d0_log_page[6].datastr, "0x%x", logD0[1]); + sprintf(d0_log_page[5].datastr, "0x%x", nsze); + sprintf(d0_log_page[6].datastr, "0x%x", logD0[1]); } /* OCP and Vendor specific log data format */ struct micron_vs_logpage { - char *field; - int size; /* FB client spec version 1.0 sizes - M5410 models */ - int size2; /* FB client spec version 0.7 sizes - M5407 models */ + char *field; + int size; /* FB client spec version 1.0 sizes - M5410 models */ + int size2; /* FB client spec version 0.7 sizes - M5407 models */ } /* Smart Health Log information as per OCP spec M51CX models */ ocp_c0_log_page[] = { - { "Physical Media Units Written", 16}, - { "Physical Media Units Read", 16 }, - { "Raw Bad User NAND Block Count", 6}, - { "Normalized Bad User NAND Block Count", 2}, - { "Raw Bad System NAND Block Count", 6}, - { "Normalized Bad System NAND Block Count", 2}, - { "XOR Recovery Count", 8}, - { "Uncorrectable Read Error Count", 8}, - { "Soft ECC Error Count", 8}, - { "SSD End to End Detected Counts", 4}, - { "SSD End to End Corrected Errors", 4}, - { "System data % life-used", 1}, - { "Refresh Count", 7}, - { "Maximum User Data Erase Count", 4}, - { "Minimum User Data Erase Count", 4}, - { "Thermal Throttling Count", 1}, - { "Thermal Throttling Status", 1}, - { "Reserved", 6}, - { "PCIe Correctable Error count", 8}, - { "Incomplete Shutdowns", 4}, - { "Reserved", 4}, - { "% Free Blocks", 1}, - { "Reserved", 7}, - { "Capacitor Health", 2}, - { "Reserved", 6}, - { "Unaligned I/O", 8}, - { "Security Version Number", 8}, - { "NUSE", 8}, - { "PLP Start Count", 16}, - { "Endurance Estimate", 16}, - { "Reserved", 302}, - { "Log Page Version", 2}, - { "Log Page GUID", 16}, + { "Physical Media Units Written", 16}, + { "Physical Media Units Read", 16 }, + { "Raw Bad User NAND Block Count", 6}, + { "Normalized Bad User NAND Block Count", 2}, + { "Raw Bad System NAND Block Count", 6}, + { "Normalized Bad System NAND Block Count", 2}, + { "XOR Recovery Count", 8}, + { "Uncorrectable Read Error Count", 8}, + { "Soft ECC Error Count", 8}, + { "SSD End to End Detected Counts", 4}, + { "SSD End to End Corrected Errors", 4}, + { "System data % life-used", 1}, + { "Refresh Count", 7}, + { "Maximum User Data Erase Count", 4}, + { "Minimum User Data Erase Count", 4}, + { "Thermal Throttling Count", 1}, + { "Thermal Throttling Status", 1}, + { "Reserved", 6}, + { "PCIe Correctable Error count", 8}, + { "Incomplete Shutdowns", 4}, + { "Reserved", 4}, + { "% Free Blocks", 1}, + { "Reserved", 7}, + { "Capacitor Health", 2}, + { "Reserved", 6}, + { "Unaligned I/O", 8}, + { "Security Version Number", 8}, + { "NUSE", 8}, + { "PLP Start Count", 16}, + { "Endurance Estimate", 16}, + { "Reserved", 302}, + { "Log Page Version", 2}, + { "Log Page GUID", 16}, }, /* Extended SMART log information */ e1_log_page[] = { - { "Reserved", 12}, - { "Grown Bad Block Count", 4}, - { "Per Block Max Erase Count", 4}, - { "Power On Minutes", 4}, - { "Reserved", 24}, - { "Write Protect Reason", 4}, - { "Reserved", 12}, - { "Drive Capacity", 8}, - { "Reserved", 8}, - { "Total Erase Count", 8}, - { "Lifetime Use Rate", 8}, - { "Erase Fail Count", 8}, - { "Reserved", 8}, - { "Reported UC Errors", 8}, - { "Reserved", 24}, - { "Program Fail Count", 16}, - { "Total Bytes Read", 16}, - { "Total Bytes Written", 16}, - { "Reserved", 16}, - { "TU Size", 4}, - { "Total Block Stripe Count", 4}, - { "Free Block Stripe Count", 4}, - { "Block Stripe Size", 8}, - { "Reserved", 16}, - { "User Block Min Erase Count", 4}, - { "User Block Avg Erase Count", 4}, - { "User Block Max Erase Count", 4}, + { "Reserved", 12}, + { "Grown Bad Block Count", 4}, + { "Per Block Max Erase Count", 4}, + { "Power On Minutes", 4}, + { "Reserved", 24}, + { "Write Protect Reason", 4}, + { "Reserved", 12}, + { "Drive Capacity", 8}, + { "Reserved", 8}, + { "Total Erase Count", 8}, + { "Lifetime Use Rate", 8}, + { "Erase Fail Count", 8}, + { "Reserved", 8}, + { "Reported UC Errors", 8}, + { "Reserved", 24}, + { "Program Fail Count", 16}, + { "Total Bytes Read", 16}, + { "Total Bytes Written", 16}, + { "Reserved", 16}, + { "TU Size", 4}, + { "Total Block Stripe Count", 4}, + { "Free Block Stripe Count", 4}, + { "Block Stripe Size", 8}, + { "Reserved", 16}, + { "User Block Min Erase Count", 4}, + { "User Block Avg Erase Count", 4}, + { "User Block Max Erase Count", 4}, }, /* Vendor Specific Health Log information */ fb_log_page[] = { - { "Physical Media Units Written - TLC", 16, 16 }, - { "Physical Media Units Written - SLC", 16, 16 }, - { "Normalized Bad User NAND Block Count", 2, 2}, - { "Raw Bad User NAND Block Count", 6, 6}, - { "XOR Recovery Count", 8, 8}, - { "Uncorrectable Read Error Count", 8, 8}, - { "SSD End to End Corrected Errors", 8, 8}, - { "SSD End to End Detected Counts", 4, 8}, - { "SSD End to End Uncorrected Counts", 4, 8}, - { "System data % life-used", 1, 1}, - { "Reserved", 0, 3}, - { "Minimum User Data Erase Count - TLC", 8, 8}, - { "Maximum User Data Erase Count - TLC", 8, 8}, - { "Average User Data Erase Count - TLC", 0, 8}, - { "Minimum User Data Erase Count - SLC", 8, 8}, - { "Maximum User Data Erase Count - SLC", 8, 8}, - { "Average User Data Erase Count - SLC", 0, 8}, - { "Normalized Program Fail Count", 2, 2}, - { "Raw Program Fail Count", 6, 6}, - { "Normalized Erase Fail Count", 2, 2}, - { "Raw Erase Fail Count", 6, 6}, - { "Pcie Correctable Error Count", 8, 8}, - { "% Free Blocks (User)", 1, 1}, - { "Reserved", 0, 3}, - { "Security Version Number", 8, 8}, - { "% Free Blocks (System)", 1, 1}, - { "Reserved", 0, 3}, - { "Dataset Management (Deallocate) Commands", 16, 16}, - { "Incomplete TRIM Data", 8, 8}, - { "% Age of Completed TRIM", 1, 2}, - { "Background Back-Pressure Gauge", 1, 1}, - { "Reserved", 0, 3}, - { "Soft ECC Error Count", 8, 8}, - { "Refresh Count", 8, 8}, - { "Normalized Bad System NAND Block Count", 2, 2}, - { "Raw Bad System NAND Block Count", 6, 6}, - { "Endurance Estimate", 16, 16}, - { "Thermal Throttling Status", 1, 1}, - { "Thermal Throttling Count", 1, 1}, - { "Unaligned I/O", 8, 8}, - { "Physical Media Units Read", 16, 16}, - { "Reserved", 279, 0}, - { "Log Page Version", 2, 0}, - { "READ CMDs exceeding threshold", 0, 4}, - { "WRITE CMDs exceeding threshold", 0, 4}, - { "TRIMs CMDs exceeding threshold", 0, 4}, - { "Reserved", 0, 4}, - { "Reserved", 0, 210}, - { "Log Page Version", 0, 2}, - { "Log Page GUID", 0, 16}, + { "Physical Media Units Written - TLC", 16, 16 }, + { "Physical Media Units Written - SLC", 16, 16 }, + { "Normalized Bad User NAND Block Count", 2, 2}, + { "Raw Bad User NAND Block Count", 6, 6}, + { "XOR Recovery Count", 8, 8}, + { "Uncorrectable Read Error Count", 8, 8}, + { "SSD End to End Corrected Errors", 8, 8}, + { "SSD End to End Detected Counts", 4, 8}, + { "SSD End to End Uncorrected Counts", 4, 8}, + { "System data % life-used", 1, 1}, + { "Reserved", 0, 3}, + { "Minimum User Data Erase Count - TLC", 8, 8}, + { "Maximum User Data Erase Count - TLC", 8, 8}, + { "Average User Data Erase Count - TLC", 0, 8}, + { "Minimum User Data Erase Count - SLC", 8, 8}, + { "Maximum User Data Erase Count - SLC", 8, 8}, + { "Average User Data Erase Count - SLC", 0, 8}, + { "Normalized Program Fail Count", 2, 2}, + { "Raw Program Fail Count", 6, 6}, + { "Normalized Erase Fail Count", 2, 2}, + { "Raw Erase Fail Count", 6, 6}, + { "Pcie Correctable Error Count", 8, 8}, + { "% Free Blocks (User)", 1, 1}, + { "Reserved", 0, 3}, + { "Security Version Number", 8, 8}, + { "% Free Blocks (System)", 1, 1}, + { "Reserved", 0, 3}, + { "Dataset Management (Deallocate) Commands", 16, 16}, + { "Incomplete TRIM Data", 8, 8}, + { "% Age of Completed TRIM", 1, 2}, + { "Background Back-Pressure Gauge", 1, 1}, + { "Reserved", 0, 3}, + { "Soft ECC Error Count", 8, 8}, + { "Refresh Count", 8, 8}, + { "Normalized Bad System NAND Block Count", 2, 2}, + { "Raw Bad System NAND Block Count", 6, 6}, + { "Endurance Estimate", 16, 16}, + { "Thermal Throttling Status", 1, 1}, + { "Thermal Throttling Count", 1, 1}, + { "Unaligned I/O", 8, 8}, + { "Physical Media Units Read", 16, 16}, + { "Reserved", 279, 0}, + { "Log Page Version", 2, 0}, + { "READ CMDs exceeding threshold", 0, 4}, + { "WRITE CMDs exceeding threshold", 0, 4}, + { "TRIMs CMDs exceeding threshold", 0, 4}, + { "Reserved", 0, 4}, + { "Reserved", 0, 210}, + { "Log Page Version", 0, 2}, + { "Log Page GUID", 0, 16}, }; -/* Common function to print Micron VS log pages */ -static void print_micron_vs_logs( - __u8 *buf, /* raw log data */ - struct micron_vs_logpage *log_page, /* format of the data */ - int field_count, /* log field count */ - struct json_object *stats, /* json object to add fields */ - __u8 spec /* ocp spec index */ -) +/* + * Common function to print Micron VS log pages + * - buf: raw log data + * - log_page: format of the data + * - field_count: log field count + * - stats: json object to add fields + * - spec: ocp spec index + */ +static void print_micron_vs_logs(__u8 *buf, struct micron_vs_logpage *log_page, int field_count, + struct json_object *stats, __u8 spec) { - __u64 lval_lo, lval_hi; - __u32 ival; - __u16 sval; - __u8 cval, lval[8] = { 0 }; - int field; - int offset = 0; - - for (field = 0; field < field_count; field++) { - char datastr[1024] = { 0 }; - char *sfield = NULL; - int size = (spec == 0) ? log_page[field].size : log_page[field].size2; - if (size == 0) continue; - sfield = log_page[field].field; - if (size == 16) { - if (strstr(sfield, "GUID")) { - sprintf(datastr, "0x%"PRIx64"%"PRIx64"", - (uint64_t)le64_to_cpu(*(uint64_t *)(&buf[offset + 8])), - (uint64_t)le64_to_cpu(*(uint64_t *)(&buf[offset]))); - } else { - lval_lo = *((__u64 *)(&buf[offset])); - lval_hi = *((__u64 *)(&buf[offset + 8])); - if (lval_hi) - sprintf(datastr, "0x%"PRIx64"%016"PRIx64"", - le64_to_cpu(lval_hi), le64_to_cpu(lval_lo)); - else - sprintf(datastr, "0x%"PRIx64"", le64_to_cpu(lval_lo)); - } - } else if (size == 8) { - lval_lo = *((__u64 *)(&buf[offset])); - sprintf(datastr, "0x%"PRIx64"", le64_to_cpu(lval_lo)); - } else if (size == 7) { - /* 7 bytes will be in little-endian format, with last byte as MSB */ - memcpy(&lval[0], &buf[offset], 7); - memcpy((void *)&lval_lo, lval, 8); - sprintf(datastr, "0x%"PRIx64"", le64_to_cpu(lval_lo)); - } else if (size == 6) { - ival = *((__u32 *)(&buf[offset])); - sval = *((__u16 *)(&buf[offset + 4])); - lval_lo = (((__u64)sval << 32) | ival); - sprintf(datastr, "0x%"PRIx64"", le64_to_cpu(lval_lo)); - } else if (size == 4) { - ival = *((__u32 *)(&buf[offset])); - sprintf(datastr, "0x%x", le32_to_cpu(ival)); - } else if (size == 2) { - sval = *((__u16 *)(&buf[offset])); - sprintf(datastr, "0x%04x", le16_to_cpu(sval)); - } else if (size == 1) { - cval = buf[offset]; - sprintf(datastr, "0x%02x", cval); - } else { - sprintf(datastr, "0"); - } - offset += size; - /* do not print reserved values */ - if (strstr(sfield, "Reserved")) - continue; - if (stats != NULL) { - json_object_add_value_string(stats, sfield, datastr); - } else { - printf("%-40s : %-4s\n", sfield, datastr); - } - } + __u64 lval_lo, lval_hi; + __u32 ival; + __u16 sval; + __u8 cval, lval[8] = { 0 }; + int field; + int offset = 0; + + for (field = 0; field < field_count; field++) { + char datastr[1024] = { 0 }; + char *sfield = NULL; + int size = !spec ? log_page[field].size : log_page[field].size2; + + if (!size) + continue; + sfield = log_page[field].field; + if (size == 16) { + if (strstr(sfield, "GUID")) { + sprintf(datastr, "0x%"PRIx64"%"PRIx64"", + (uint64_t)le64_to_cpu(*(uint64_t *)(&buf[offset + 8])), + (uint64_t)le64_to_cpu(*(uint64_t *)(&buf[offset]))); + } else { + lval_lo = *((__u64 *)(&buf[offset])); + lval_hi = *((__u64 *)(&buf[offset + 8])); + if (lval_hi) + sprintf(datastr, "0x%"PRIx64"%016"PRIx64"", + le64_to_cpu(lval_hi), le64_to_cpu(lval_lo)); + else + sprintf(datastr, "0x%"PRIx64"", le64_to_cpu(lval_lo)); + } + } else if (size == 8) { + lval_lo = *((__u64 *)(&buf[offset])); + sprintf(datastr, "0x%"PRIx64"", le64_to_cpu(lval_lo)); + } else if (size == 7) { + /* 7 bytes will be in little-endian format, with last byte as MSB */ + memcpy(&lval[0], &buf[offset], 7); + memcpy((void *)&lval_lo, lval, 8); + sprintf(datastr, "0x%"PRIx64"", le64_to_cpu(lval_lo)); + } else if (size == 6) { + ival = *((__u32 *)(&buf[offset])); + sval = *((__u16 *)(&buf[offset + 4])); + lval_lo = (((__u64)sval << 32) | ival); + sprintf(datastr, "0x%"PRIx64"", le64_to_cpu(lval_lo)); + } else if (size == 4) { + ival = *((__u32 *)(&buf[offset])); + sprintf(datastr, "0x%x", le32_to_cpu(ival)); + } else if (size == 2) { + sval = *((__u16 *)(&buf[offset])); + sprintf(datastr, "0x%04x", le16_to_cpu(sval)); + } else if (size == 1) { + cval = buf[offset]; + sprintf(datastr, "0x%02x", cval); + } else { + sprintf(datastr, "0"); + } + offset += size; + /* do not print reserved values */ + if (strstr(sfield, "Reserved")) + continue; + if (stats) + json_object_add_value_string(stats, sfield, datastr); + else + printf("%-40s : %-4s\n", sfield, datastr); + } } static void print_smart_cloud_health_log(__u8 *buf, bool is_json) { - struct json_object *root; - struct json_object *logPages; - struct json_object *stats = NULL; - int field_count = sizeof(ocp_c0_log_page)/sizeof(ocp_c0_log_page[0]); - - if (is_json) { - root = json_create_object(); - stats = json_create_object(); - logPages = json_create_array(); - json_object_add_value_array(root, "OCP SMART Cloud Health Log: 0xC0", - logPages); - } - - print_micron_vs_logs(buf, ocp_c0_log_page, field_count, stats, 0); - - if (is_json) { - json_array_add_value_object(logPages, stats); - json_print_object(root, NULL); - printf("\n"); - json_free_object(root); - } + struct json_object *root; + struct json_object *logPages; + struct json_object *stats = NULL; + int field_count = ARRAY_SIZE(ocp_c0_log_page); + + if (is_json) { + root = json_create_object(); + stats = json_create_object(); + logPages = json_create_array(); + json_object_add_value_array(root, "OCP SMART Cloud Health Log: 0xC0", + logPages); + } + + print_micron_vs_logs(buf, ocp_c0_log_page, field_count, stats, 0); + + if (is_json) { + json_array_add_value_object(logPages, stats); + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); + } } static void print_nand_stats_fb(__u8 *buf, __u8 *buf2, __u8 nsze, bool is_json, __u8 spec) { - struct json_object *root; - struct json_object *logPages; - struct json_object *stats = NULL; - int field_count = sizeof(fb_log_page)/sizeof(fb_log_page[0]); - - if (is_json) { - root = json_create_object(); - stats = json_create_object(); - logPages = json_create_array(); - json_object_add_value_array(root, "Extended Smart Log Page : 0xFB", - logPages); - } - - print_micron_vs_logs(buf, fb_log_page, field_count, stats, spec); - - /* print last three entries from D0 log page */ - if (buf2 != NULL) { - init_d0_log_page(buf2, nsze); - - if (is_json) { - for (int i = 0; i < 7; i++) { - json_object_add_value_string(stats, - d0_log_page[i].field, - d0_log_page[i].datastr); - } - } else { - for (int i = 0; i < 7; i++) { - printf("%-40s : %s\n", d0_log_page[i].field, d0_log_page[i].datastr); - } - } - } - - if (is_json) { - json_array_add_value_object(logPages, stats); - json_print_object(root, NULL); - printf("\n"); - json_free_object(root); - } + struct json_object *root; + struct json_object *logPages; + struct json_object *stats = NULL; + int field_count = ARRAY_SIZE(fb_log_page); + + if (is_json) { + root = json_create_object(); + stats = json_create_object(); + logPages = json_create_array(); + json_object_add_value_array(root, "Extended Smart Log Page : 0xFB", + logPages); + } + + print_micron_vs_logs(buf, fb_log_page, field_count, stats, spec); + + /* print last three entries from D0 log page */ + if (buf2) { + init_d0_log_page(buf2, nsze); + + if (is_json) { + for (int i = 0; i < 7; i++) + json_object_add_value_string(stats, + d0_log_page[i].field, + d0_log_page[i].datastr); + } else { + for (int i = 0; i < 7; i++) + printf("%-40s : %s\n", d0_log_page[i].field, d0_log_page[i].datastr); + } + } + + if (is_json) { + json_array_add_value_object(logPages, stats); + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); + } } static void print_nand_stats_d0(__u8 *buf, __u8 oacs, bool is_json) { - init_d0_log_page(buf, oacs); - - if (is_json) { - struct json_object *root = json_create_object(); - struct json_object *stats = json_create_object(); - struct json_object *logPages = json_create_array(); - - json_object_add_value_array(root, - "Extended Smart Log Page : 0xD0", - logPages); - - for (int i = 0; i < 7; i++) { - json_object_add_value_string(stats, - d0_log_page[i].field, - d0_log_page[i].datastr); - } - - json_array_add_value_object(logPages, stats); - json_print_object(root, NULL); - printf("\n"); - json_free_object(root); - } else { - for (int i = 0; i < 7; i++) { - printf("%-40s : %s\n", d0_log_page[i].field, d0_log_page[i].datastr); - } - } + init_d0_log_page(buf, oacs); + + if (is_json) { + struct json_object *root = json_create_object(); + struct json_object *stats = json_create_object(); + struct json_object *logPages = json_create_array(); + + json_object_add_value_array(root, + "Extended Smart Log Page : 0xD0", + logPages); + + for (int i = 0; i < 7; i++) + json_object_add_value_string(stats, + d0_log_page[i].field, + d0_log_page[i].datastr); + + json_array_add_value_object(logPages, stats); + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); + } else { + for (int i = 0; i < 7; i++) + printf("%-40s : %s\n", d0_log_page[i].field, d0_log_page[i].datastr); + } } -static bool nsze_from_oacs = false; /* read nsze for now from idd[4059] */ +static bool nsze_from_oacs; /* read nsze for now from idd[4059] */ static int micron_nand_stats(int argc, char **argv, - struct command *cmd, struct plugin *plugin) + struct command *cmd, struct plugin *plugin) { - const char *desc = "Retrieve Micron NAND stats for the given device "; - unsigned int extSmartLog[D0_log_size/sizeof(int)] = { 0 }; - unsigned int logFB[FB_log_size/sizeof(int)] = { 0 }; - eDriveModel eModel = UNKNOWN_MODEL; - struct nvme_id_ctrl ctrl; - struct nvme_dev *dev; - int err, ctrlIdx; - __u8 nsze; - bool has_d0_log = true; - bool has_fb_log = false; - bool is_json = true; - struct format { - char *fmt; - }; - const char *fmt = "output format json|normal"; - struct format cfg = { - .fmt = "json", - }; - - OPT_ARGS(opts) = { - OPT_FMT("format", 'f', &cfg.fmt, fmt), - OPT_END() - }; - - err = parse_and_open(&dev, argc, argv, desc, opts); - if (err) { - printf("\nDevice not found \n");; - return -1; - } - - if (strcmp(cfg.fmt, "normal") == 0) - is_json = false; - - err = nvme_identify_ctrl(dev_fd(dev), &ctrl); - if (err) { - printf("Error %d retrieving controller identification data\n", err); - goto out; - } - - /* pull log details based on the model name */ - sscanf(argv[optind], "/dev/nvme%d", &ctrlIdx); - eModel = GetDriveModel(ctrlIdx); - if ((eModel == UNKNOWN_MODEL) || (eModel == M51CX)) { - printf ("Unsupported drive model for vs-nand-stats command\n"); - err = -1; - goto out; - } - - err = nvme_get_log_simple(dev_fd(dev), 0xD0, D0_log_size, extSmartLog); - has_d0_log = (0 == err); - - /* should check for firmware version if this log is supported or not */ - if (eModel == M5407 || eModel == M5410) { - err = nvme_get_log_simple(dev_fd(dev), 0xFB, FB_log_size, logFB); - has_fb_log = (0 == err); - } - - nsze = (ctrl.vs[987] == 0x12); - if (nsze == 0 && nsze_from_oacs) - nsze = ((ctrl.oacs >> 3) & 0x1); - err = 0; - if (has_fb_log) { - __u8 spec = (eModel == M5410) ? 0 : 1; /* FB spec version */ - print_nand_stats_fb((__u8 *)logFB, (__u8 *)extSmartLog, nsze, is_json, spec); - } else if (has_d0_log) { - print_nand_stats_d0((__u8 *)extSmartLog, nsze, is_json); - } else { - printf("Unable to retrieve extended smart log for the drive\n"); - err = -ENOTTY; - } + const char *desc = "Retrieve Micron NAND stats for the given device "; + unsigned int extSmartLog[D0_log_size/sizeof(int)] = { 0 }; + unsigned int logFB[FB_log_size/sizeof(int)] = { 0 }; + enum eDriveModel eModel = UNKNOWN_MODEL; + struct nvme_id_ctrl ctrl; + struct nvme_dev *dev; + int err, ctrlIdx; + __u8 nsze; + bool has_d0_log = true; + bool has_fb_log = false; + bool is_json = true; + struct format { + char *fmt; + }; + const char *fmt = "output format json|normal"; + struct format cfg = { + .fmt = "json", + }; + + OPT_ARGS(opts) = { + OPT_FMT("format", 'f', &cfg.fmt, fmt), + OPT_END() + }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) { + printf("\nDevice not found\n"); + return -1; + } + + if (!strcmp(cfg.fmt, "normal")) + is_json = false; + + err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + if (err) { + printf("Error %d retrieving controller identification data\n", err); + goto out; + } + + /* pull log details based on the model name */ + if (sscanf(argv[optind], "/dev/nvme%d", &ctrlIdx) != 1) + ctrlIdx = 0; + eModel = GetDriveModel(ctrlIdx); + if ((eModel == UNKNOWN_MODEL) || (eModel == M51CX)) { + printf("Unsupported drive model for vs-nand-stats command\n"); + err = -1; + goto out; + } + + err = nvme_get_log_simple(dev_fd(dev), 0xD0, D0_log_size, extSmartLog); + has_d0_log = !err; + + /* should check for firmware version if this log is supported or not */ + if (eModel == M5407 || eModel == M5410) { + err = nvme_get_log_simple(dev_fd(dev), 0xFB, FB_log_size, logFB); + has_fb_log = !err; + } + + nsze = (ctrl.vs[987] == 0x12); + if (!nsze && nsze_from_oacs) + nsze = ((ctrl.oacs >> 3) & 0x1); + err = 0; + if (has_fb_log) { + __u8 spec = (eModel == M5410) ? 0 : 1; /* FB spec version */ + + print_nand_stats_fb((__u8 *)logFB, (__u8 *)extSmartLog, nsze, is_json, spec); + } else if (has_d0_log) { + print_nand_stats_d0((__u8 *)extSmartLog, nsze, is_json); + } else { + printf("Unable to retrieve extended smart log for the drive\n"); + err = -ENOTTY; + } out: - dev_close(dev); - if (err > 0) - nvme_show_status(err); + dev_close(dev); + if (err > 0) + nvme_show_status(err); - return err; + return err; } static void print_ext_smart_logs_e1(__u8 *buf, bool is_json) { - struct json_object *root; - struct json_object *logPages; - struct json_object *stats = NULL; - int field_count = sizeof(e1_log_page)/sizeof(e1_log_page[0]); - - if (is_json) { - root = json_create_object(); - stats = json_create_object(); - logPages = json_create_array(); - json_object_add_value_array(root, "SMART Extended Log:0xE1", logPages); - } - else { - printf("SMART Extended Log:0xE1\n"); - } - - print_micron_vs_logs(buf, e1_log_page, field_count, stats, 0); - - if (is_json) { - json_array_add_value_object(logPages, stats); - json_print_object(root, NULL); - printf("\n"); - json_free_object(root); - } + struct json_object *root; + struct json_object *logPages; + struct json_object *stats = NULL; + int field_count = ARRAY_SIZE(e1_log_page); + + if (is_json) { + root = json_create_object(); + stats = json_create_object(); + logPages = json_create_array(); + json_object_add_value_array(root, "SMART Extended Log:0xE1", logPages); + } else { + printf("SMART Extended Log:0xE1\n"); + } + + print_micron_vs_logs(buf, e1_log_page, field_count, stats, 0); + + if (is_json) { + json_array_add_value_object(logPages, stats); + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); + } } static int micron_smart_ext_log(int argc, char **argv, - struct command *cmd, struct plugin *plugin) + struct command *cmd, struct plugin *plugin) { - const char *desc = "Retrieve extended SMART logs for the given device "; - unsigned int extSmartLog[E1_log_size/sizeof(int)] = { 0 }; - eDriveModel eModel = UNKNOWN_MODEL; - int err = 0, ctrlIdx = 0; - struct nvme_dev *dev; - bool is_json = true; - struct format { - char *fmt; - }; - const char *fmt = "output format json|normal"; - struct format cfg = { - .fmt = "json", - }; - OPT_ARGS(opts) = { - OPT_FMT("format", 'f', &cfg.fmt, fmt), - OPT_END() - }; - - err = parse_and_open(&dev, argc, argv, desc, opts); - if (err) { - printf("\nDevice not found \n");; - return -1; - } - if (strcmp(cfg.fmt, "normal") == 0) - is_json = false; - - sscanf(argv[optind], "/dev/nvme%d", &ctrlIdx); - if ((eModel = GetDriveModel(ctrlIdx)) != M51CX) { - printf ("Unsupported drive model for vs-smart-ext-log command\n"); - err = -1; - goto out; - } - err = nvme_get_log_simple(dev_fd(dev), 0xE1, E1_log_size, extSmartLog); - if (!err) { - print_ext_smart_logs_e1((__u8 *)extSmartLog, is_json); - } + const char *desc = "Retrieve extended SMART logs for the given device "; + unsigned int extSmartLog[E1_log_size/sizeof(int)] = { 0 }; + enum eDriveModel eModel = UNKNOWN_MODEL; + int err = 0, ctrlIdx; + struct nvme_dev *dev; + bool is_json = true; + struct format { + char *fmt; + }; + const char *fmt = "output format json|normal"; + struct format cfg = { + .fmt = "json", + }; + OPT_ARGS(opts) = { + OPT_FMT("format", 'f', &cfg.fmt, fmt), + OPT_END() + }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) { + printf("\nDevice not found\n"); + return -1; + } + if (!strcmp(cfg.fmt, "normal")) + is_json = false; + + if (sscanf(argv[optind], "/dev/nvme%d", &ctrlIdx) != 1) + ctrlIdx = 0; + eModel = GetDriveModel(ctrlIdx); + if (eModel != M51CX) { + printf("Unsupported drive model for vs-smart-ext-log command\n"); + err = -1; + goto out; + } + err = nvme_get_log_simple(dev_fd(dev), 0xE1, E1_log_size, extSmartLog); + if (!err) + print_ext_smart_logs_e1((__u8 *)extSmartLog, is_json); out: - dev_close(dev); - if (err > 0) - nvme_show_status(err); - return err; + dev_close(dev); + if (err > 0) + nvme_show_status(err); + return err; } static void GetDriveInfo(const char *strOSDirName, int nFD, - struct nvme_id_ctrl *ctrlp) + struct nvme_id_ctrl *ctrlp) { - FILE *fpOutFile = NULL; - char tempFile[256] = { 0 }; - char strBuffer[1024] = { 0 }; - char model[41] = { 0 }; - char serial[21] = { 0 }; - char fwrev[9] = { 0 }; - char *strPDir = strdup(strOSDirName); - char *strDest = dirname(strPDir); - - sprintf(tempFile, "%s/%s", strDest, "drive-info.txt"); - fpOutFile = fopen(tempFile, "w+"); - if (!fpOutFile) { - printf("Failed to create %s\n", tempFile); - free(strPDir); - return; - } - - strncpy(model, ctrlp->mn, 40); - strncpy(serial, ctrlp->sn, 20); - strncpy(fwrev, ctrlp->fr, 8); - - sprintf(strBuffer, - "********************\nDrive Info\n********************\n"); - - fprintf(fpOutFile, "%s", strBuffer); - sprintf(strBuffer, - "%-20s : /dev/nvme%d\n%-20s : %s\n%-20s : %-20s\n%-20s : %-20s\n", - "Device Name", nFD, - "Model No", (char *)model, - "Serial No", (char *)serial, "FW-Rev", (char *)fwrev); - - fprintf(fpOutFile, "%s", strBuffer); - - sprintf(strBuffer, - "\n********************\nPCI Info\n********************\n"); - - fprintf(fpOutFile, "%s", strBuffer); - - sprintf(strBuffer, - "%-22s : %04X\n%-22s : %04X\n", - "VendorId", vendor_id, "DeviceId", device_id); - fprintf(fpOutFile, "%s", strBuffer); - fclose(fpOutFile); - free(strPDir); + FILE *fpOutFile = NULL; + char tempFile[256] = { 0 }; + char strBuffer[1024] = { 0 }; + char model[41] = { 0 }; + char serial[21] = { 0 }; + char fwrev[9] = { 0 }; + char *strPDir = strdup(strOSDirName); + char *strDest = dirname(strPDir); + + sprintf(tempFile, "%s/%s", strDest, "drive-info.txt"); + fpOutFile = fopen(tempFile, "w+"); + if (!fpOutFile) { + printf("Failed to create %s\n", tempFile); + free(strPDir); + return; + } + + strncpy(model, ctrlp->mn, 40); + strncpy(serial, ctrlp->sn, 20); + strncpy(fwrev, ctrlp->fr, 8); + + sprintf(strBuffer, + "********************\nDrive Info\n********************\n"); + + fprintf(fpOutFile, "%s", strBuffer); + sprintf(strBuffer, + "%-20s : /dev/nvme%d\n%-20s : %s\n%-20s : %-20s\n%-20s : %-20s\n", + "Device Name", nFD, + "Model No", (char *)model, + "Serial No", (char *)serial, "FW-Rev", (char *)fwrev); + + fprintf(fpOutFile, "%s", strBuffer); + + sprintf(strBuffer, + "\n********************\nPCI Info\n********************\n"); + + fprintf(fpOutFile, "%s", strBuffer); + + sprintf(strBuffer, + "%-22s : %04X\n%-22s : %04X\n", + "VendorId", vendor_id, "DeviceId", device_id); + fprintf(fpOutFile, "%s", strBuffer); + fclose(fpOutFile); + free(strPDir); } static void GetTimestampInfo(const char *strOSDirName) { - __u8 outstr[1024]; - time_t t; - struct tm *tmp; - size_t num; - char *strPDir; - char *strDest; - - t = time(NULL); - tmp = localtime(&t); - if (tmp == NULL) - return; - - num = strftime((char *)outstr, sizeof(outstr), - "Timestamp (UTC): %a, %d %b %Y %T %z", tmp); - num += sprintf((char *)(outstr + num), "\nPackage Version: 1.4"); - if (num) { - strPDir = strdup(strOSDirName); - strDest = dirname(strPDir); - WriteData(outstr, num, strDest, "timestamp_info.txt", "timestamp"); - free(strPDir); - } + __u8 outstr[1024]; + time_t t; + struct tm *tmp; + size_t num; + char *strPDir; + char *strDest; + + t = time(NULL); + tmp = localtime(&t); + if (!tmp) + return; + + num = strftime((char *)outstr, sizeof(outstr), + "Timestamp (UTC): %a, %d %b %Y %T %z", tmp); + num += sprintf((char *)(outstr + num), "\nPackage Version: 1.4"); + if (num) { + strPDir = strdup(strOSDirName); + strDest = dirname(strPDir); + WriteData(outstr, num, strDest, "timestamp_info.txt", "timestamp"); + free(strPDir); + } } static void GetCtrlIDDInfo(const char *dir, struct nvme_id_ctrl *ctrlp) { - WriteData((__u8*)ctrlp, sizeof(*ctrlp), dir, - "nvme_controller_identify_data.bin", "id-ctrl"); + WriteData((__u8 *)ctrlp, sizeof(*ctrlp), dir, + "nvme_controller_identify_data.bin", "id-ctrl"); } static void GetSmartlogData(int fd, const char *dir) { - struct nvme_smart_log smart_log; - if (nvme_get_log_smart(fd, -1, false, &smart_log) == 0) { - WriteData((__u8*)&smart_log, sizeof(smart_log), dir, - "smart_data.bin", "smart log"); - } + struct nvme_smart_log smart_log; + + if (!nvme_get_log_smart(fd, -1, false, &smart_log)) + WriteData((__u8 *)&smart_log, sizeof(smart_log), dir, + "smart_data.bin", "smart log"); } static void GetErrorlogData(int fd, int entries, const char *dir) { - int logSize = entries * sizeof(struct nvme_error_log_page); - struct nvme_error_log_page *error_log = - (struct nvme_error_log_page *)calloc(1, logSize); + int logSize = entries * sizeof(struct nvme_error_log_page); + struct nvme_error_log_page *error_log = + (struct nvme_error_log_page *)calloc(1, logSize); - if (error_log == NULL) - return; + if (!error_log) + return; - if (nvme_get_log_error(fd, entries, false, error_log) == 0) { - WriteData((__u8*)error_log, logSize, dir, - "error_information_log.bin", "error log"); - } + if (!nvme_get_log_error(fd, entries, false, error_log)) + WriteData((__u8 *)error_log, logSize, dir, + "error_information_log.bin", "error log"); - free(error_log); + free(error_log); } static void GetGenericLogs(int fd, const char *dir) { - struct nvme_self_test_log self_test_log; - struct nvme_firmware_slot fw_log; - struct nvme_cmd_effects_log effects; - struct nvme_persistent_event_log pevent_log; - void *pevent_log_info = NULL; - __u32 log_len = 0; - int err = 0 ; - bool huge = false; - - /* get self test log */ - if (nvme_get_log_device_self_test(fd, &self_test_log) == 0) { - WriteData((__u8*)&self_test_log, sizeof(self_test_log), dir, - "drive_self_test.bin", "self test log"); - } - - /* get fw slot info log */ - if (nvme_get_log_fw_slot(fd, false, &fw_log) == 0) { - WriteData((__u8*)&fw_log, sizeof(fw_log), dir, - "firmware_slot_info_log.bin", "firmware log"); - } - - /* get effects log */ - if (nvme_get_log_cmd_effects(fd, NVME_CSI_NVM, &effects) == 0) { - WriteData((__u8*)&effects, sizeof(effects), dir, - "command_effects_log.bin", "effects log"); - } - - /* get persistent event log */ - (void)nvme_get_log_persistent_event(fd, NVME_PEVENT_LOG_RELEASE_CTX, - sizeof(pevent_log), &pevent_log); - memset(&pevent_log, 0, sizeof(pevent_log)); - err = nvme_get_log_persistent_event(fd, NVME_PEVENT_LOG_EST_CTX_AND_READ, - sizeof(pevent_log), &pevent_log); - if (err) { - fprintf(stderr, "Setting persistent event log read ctx failed (ignored)!\n"); - return; - } - - log_len = le64_to_cpu(pevent_log.tll); - pevent_log_info = nvme_alloc(log_len, &huge); - if (!pevent_log_info) { - perror("could not alloc buffer for persistent event log page (ignored)!\n"); - return; - } - err = nvme_get_log_persistent_event(fd, NVME_PEVENT_LOG_READ, - log_len, pevent_log_info); - if (err == 0) { - WriteData((__u8*)pevent_log_info, log_len, dir, - "persistent_event_log.bin", "persistent event log"); - } - nvme_free(pevent_log_info, huge); - return; + struct nvme_self_test_log self_test_log; + struct nvme_firmware_slot fw_log; + struct nvme_cmd_effects_log effects; + struct nvme_persistent_event_log pevent_log; + void *pevent_log_info = NULL; + __u32 log_len = 0; + int err = 0; + bool huge = false; + + /* get self test log */ + if (!nvme_get_log_device_self_test(fd, &self_test_log)) + WriteData((__u8 *)&self_test_log, sizeof(self_test_log), dir, + "drive_self_test.bin", "self test log"); + + /* get fw slot info log */ + if (!nvme_get_log_fw_slot(fd, false, &fw_log)) + WriteData((__u8 *)&fw_log, sizeof(fw_log), dir, + "firmware_slot_info_log.bin", "firmware log"); + + /* get effects log */ + if (!nvme_get_log_cmd_effects(fd, NVME_CSI_NVM, &effects)) + WriteData((__u8 *)&effects, sizeof(effects), dir, + "command_effects_log.bin", "effects log"); + + /* get persistent event log */ + (void)nvme_get_log_persistent_event(fd, NVME_PEVENT_LOG_RELEASE_CTX, + sizeof(pevent_log), &pevent_log); + memset(&pevent_log, 0, sizeof(pevent_log)); + err = nvme_get_log_persistent_event(fd, NVME_PEVENT_LOG_EST_CTX_AND_READ, + sizeof(pevent_log), &pevent_log); + if (err) { + fprintf(stderr, "Setting persistent event log read ctx failed (ignored)!\n"); + return; + } + + log_len = le64_to_cpu(pevent_log.tll); + pevent_log_info = nvme_alloc(log_len, &huge); + if (!pevent_log_info) { + perror("could not alloc buffer for persistent event log page (ignored)!\n"); + return; + } + err = nvme_get_log_persistent_event(fd, NVME_PEVENT_LOG_READ, + log_len, pevent_log_info); + if (!err) + WriteData((__u8 *)pevent_log_info, log_len, dir, + "persistent_event_log.bin", "persistent event log"); + nvme_free(pevent_log_info, huge); } static void GetNSIDDInfo(int fd, const char *dir, int nsid) { - char file[PATH_MAX] = { 0 }; - struct nvme_id_ns ns; + char file[PATH_MAX] = { 0 }; + struct nvme_id_ns ns; - if (nvme_identify_ns(fd, nsid, &ns) == 0) { - sprintf(file, "identify_namespace_%d_data.bin", nsid); - WriteData((__u8*)&ns, sizeof(ns), dir, file, "id-ns"); - } + if (!nvme_identify_ns(fd, nsid, &ns)) { + sprintf(file, "identify_namespace_%d_data.bin", nsid); + WriteData((__u8 *)&ns, sizeof(ns), dir, file, "id-ns"); + } } static void GetOSConfig(const char *strOSDirName) { - FILE *fpOSConfig = NULL; - char strBuffer[1024]; - char strFileName[PATH_MAX]; - int i; - - struct { - char *strcmdHeader; - char *strCommand; - } cmdArray[] = { - { (char *)"SYSTEM INFORMATION", (char *)"uname -a >> %s" }, - { (char *)"LINUX KERNEL MODULE INFORMATION", (char *)"lsmod >> %s" }, - { (char *)"LINUX SYSTEM MEMORY INFORMATION", (char *)"cat /proc/meminfo >> %s" }, - { (char *)"SYSTEM INTERRUPT INFORMATION", (char *)"cat /proc/interrupts >> %s" }, - { (char *)"CPU INFORMATION", (char *)"cat /proc/cpuinfo >> %s" }, - { (char *)"IO MEMORY MAP INFORMATION", (char *)"cat /proc/iomem >> %s" }, - { (char *)"MAJOR NUMBER AND DEVICE GROUP", (char *)"cat /proc/devices >> %s" }, - { (char *)"KERNEL DMESG", (char *)"dmesg >> %s" }, - { (char *)"/VAR/LOG/MESSAGES", (char *)"cat /var/log/messages >> %s" } - }; - - sprintf(strFileName, "%s/%s", strOSDirName, "os_config.txt"); - - for (i = 0; i < 7; i++) { - fpOSConfig = fopen(strFileName, "a+"); - if (NULL != fpOSConfig) { - fprintf(fpOSConfig, - "\n\n\n\n%s\n-----------------------------------------------\n", - cmdArray[i].strcmdHeader); - fclose(fpOSConfig); - fpOSConfig = NULL; - } - snprintf(strBuffer, sizeof(strBuffer) - 1, - cmdArray[i].strCommand, strFileName); - if (system(strBuffer)) - fprintf(stderr, "Failed to send \"%s\"\n", strBuffer); - } + FILE *fpOSConfig = NULL; + char strBuffer[1024]; + char strFileName[PATH_MAX]; + int i; + + struct { + char *strcmdHeader; + char *strCommand; + } cmdArray[] = { + { (char *)"SYSTEM INFORMATION", (char *)"uname -a >> %s" }, + { (char *)"LINUX KERNEL MODULE INFORMATION", (char *)"lsmod >> %s" }, + { (char *)"LINUX SYSTEM MEMORY INFORMATION", (char *)"cat /proc/meminfo >> %s" }, + { (char *)"SYSTEM INTERRUPT INFORMATION", (char *)"cat /proc/interrupts >> %s" }, + { (char *)"CPU INFORMATION", (char *)"cat /proc/cpuinfo >> %s" }, + { (char *)"IO MEMORY MAP INFORMATION", (char *)"cat /proc/iomem >> %s" }, + { (char *)"MAJOR NUMBER AND DEVICE GROUP", (char *)"cat /proc/devices >> %s" }, + { (char *)"KERNEL DMESG", (char *)"dmesg >> %s" }, + { (char *)"/VAR/LOG/MESSAGES", (char *)"cat /var/log/messages >> %s" } + }; + + sprintf(strFileName, "%s/%s", strOSDirName, "os_config.txt"); + + for (i = 0; i < 7; i++) { + fpOSConfig = fopen(strFileName, "a+"); + if (fpOSConfig) { + fprintf(fpOSConfig, + "\n\n\n\n%s\n-----------------------------------------------\n", + cmdArray[i].strcmdHeader); + fclose(fpOSConfig); + fpOSConfig = NULL; + } + snprintf(strBuffer, sizeof(strBuffer) - 1, + cmdArray[i].strCommand, strFileName); + if (system(strBuffer)) + fprintf(stderr, "Failed to send \"%s\"\n", strBuffer); + } } static int micron_telemetry_log(int fd, __u8 type, __u8 **data, - int *logSize, int da) + int *logSize, int da) { - int err, bs = 512, offset = bs; - unsigned short data_area[4]; - unsigned char ctrl_init = (type == 0x8); - - __u8 *buffer = (unsigned char *)calloc(bs, 1); - if (buffer == NULL) - return -1; - if (ctrl_init) - err = nvme_get_log_telemetry_ctrl(fd, true, 0, bs, buffer); - else - err = nvme_get_log_telemetry_host(fd, 0, bs, buffer); - if (err != 0) { - fprintf(stderr, "Failed to get telemetry log header for 0x%X\n", type); - if (buffer != NULL) { - free(buffer); - } - return err; - } - - /* compute size of the log */ - data_area[1] = buffer[9] << 8 | buffer[8]; - data_area[2] = buffer[11] << 8 | buffer[10]; - data_area[3] = buffer[13] << 8 | buffer[12]; - data_area[0] = data_area[1] > data_area[2] ? data_area[1] : data_area[2]; - data_area[0] = data_area[3] > data_area[0] ? data_area[3] : data_area[0]; - - if (data_area[da] == 0) { - fprintf(stderr, "Requested telemetry data for 0x%X is empty\n", type); - if (buffer != NULL) { - free(buffer); - buffer = NULL; - } - return -1; - } - - *logSize = data_area[da] * bs; - offset = bs; - err = 0; - if ((buffer = (unsigned char *)realloc(buffer, (size_t)(*logSize))) != NULL) { - while (err == 0 && offset != *logSize) { - if (ctrl_init) - err = nvme_get_log_telemetry_ctrl(fd, true, 0, *logSize, buffer + offset); - else - err = nvme_get_log_telemetry_host(fd, 0, *logSize, buffer + offset); - offset += bs; - } - } - - if (err == 0 && buffer != NULL) { - *data = buffer; - } else { - fprintf(stderr, "Failed to get telemetry data for 0x%x\n", type); - if (buffer != NULL) - free(buffer); - } - - return err; + int err, bs = 512, offset = bs; + unsigned short data_area[4]; + unsigned char ctrl_init = (type == 0x8); + + __u8 *buffer = (unsigned char *)calloc(bs, 1); + + if (!buffer) + return -1; + if (ctrl_init) + err = nvme_get_log_telemetry_ctrl(fd, true, 0, bs, buffer); + else + err = nvme_get_log_telemetry_host(fd, 0, bs, buffer); + if (err) { + fprintf(stderr, "Failed to get telemetry log header for 0x%X\n", type); + if (buffer) + free(buffer); + return err; + } + + /* compute size of the log */ + data_area[1] = buffer[9] << 8 | buffer[8]; + data_area[2] = buffer[11] << 8 | buffer[10]; + data_area[3] = buffer[13] << 8 | buffer[12]; + data_area[0] = data_area[1] > data_area[2] ? data_area[1] : data_area[2]; + data_area[0] = data_area[3] > data_area[0] ? data_area[3] : data_area[0]; + + if (!data_area[da]) { + fprintf(stderr, "Requested telemetry data for 0x%X is empty\n", type); + if (buffer) { + free(buffer); + buffer = NULL; + } + return -1; + } + + *logSize = data_area[da] * bs; + offset = bs; + err = 0; + buffer = (unsigned char *)realloc(buffer, (size_t)(*logSize)); + if (buffer) { + while (!err && offset != *logSize) { + if (ctrl_init) + err = nvme_get_log_telemetry_ctrl(fd, true, 0, *logSize, buffer + offset); + else + err = nvme_get_log_telemetry_host(fd, 0, *logSize, buffer + offset); + offset += bs; + } + } + + if (!err && buffer) { + *data = buffer; + } else { + fprintf(stderr, "Failed to get telemetry data for 0x%x\n", type); + if (buffer) + free(buffer); + } + + return err; } static int GetTelemetryData(int fd, const char *dir) { - unsigned char *buffer = NULL; - int i, err, logSize = 0; - char msg[256] = {0}; - struct { - __u8 log; - char *file; - } tmap[] = { - {0x07, "nvmetelemetrylog.bin"}, - {0x08, "nvmetelemetrylog.bin"}, - }; - - for(i = 0; i < (int)(sizeof(tmap)/sizeof(tmap[0])); i++) { - err = micron_telemetry_log(fd, tmap[i].log, &buffer, &logSize, 0); - if (err == 0 && logSize > 0 && buffer != NULL) { - sprintf(msg, "telemetry log: 0x%X", tmap[i].log); - WriteData(buffer, logSize, dir, tmap[i].file, msg); - } - if (buffer) { - free(buffer); - buffer = NULL; - } - logSize = 0; - } - return err; + unsigned char *buffer = NULL; + int i, err, logSize = 0; + char msg[256] = { 0 }; + struct { + __u8 log; + char *file; + } tmap[] = { + {0x07, "nvmetelemetrylog.bin"}, + {0x08, "nvmetelemetrylog.bin"}, + }; + + for (i = 0; i < (int)(ARRAY_SIZE(tmap)); i++) { + err = micron_telemetry_log(fd, tmap[i].log, &buffer, &logSize, 0); + if (!err && logSize > 0 && buffer) { + sprintf(msg, "telemetry log: 0x%X", tmap[i].log); + WriteData(buffer, logSize, dir, tmap[i].file, msg); + } + if (buffer) { + free(buffer); + buffer = NULL; + } + logSize = 0; + } + return err; } static int GetFeatureSettings(int fd, const char *dir) { - unsigned char *bufp, buf[4096] = { 0 }; - int i, err, len, errcnt = 0; - __u32 attrVal = 0; - char msg[256] = { 0 }; - - struct features { - int id; - char *file; - } fmap[] = { - {0x01, "nvme_feature_setting_arbitration.bin"}, - {0x02, "nvme_feature_setting_pm.bin"}, - {0x03, "nvme_feature_setting_lba_range_namespace_1.bin"}, - {0x04, "nvme_feature_setting_temp_threshold.bin"}, - {0x05, "nvme_feature_setting_error_recovery.bin"}, - {0x06, "nvme_feature_setting_volatile_write_cache.bin"}, - {0x07, "nvme_feature_setting_num_queues.bin"}, - {0x08, "nvme_feature_setting_interrupt_coalescing.bin"}, - {0x09, "nvme_feature_setting_interrupt_vec_config.bin"}, - {0x0A, "nvme_feature_setting_write_atomicity.bin"}, - {0x0B, "nvme_feature_setting_async_event_config.bin"}, - {0x80, "nvme_feature_setting_sw_progress_marker.bin"}, - }; - - for (i = 0; i < (int)(sizeof(fmap)/sizeof(fmap[0])); i++) { - if (fmap[i].id == 0x03) { - len = 4096; - bufp = (unsigned char *)(&buf[0]); - } else { - len = 0; - bufp = NULL; - } + unsigned char *bufp, buf[4096] = { 0 }; + int i, err, len, errcnt = 0; + __u32 attrVal = 0; + char msg[256] = { 0 }; + + struct features { + int id; + char *file; + } fmap[] = { + {0x01, "nvme_feature_setting_arbitration.bin"}, + {0x02, "nvme_feature_setting_pm.bin"}, + {0x03, "nvme_feature_setting_lba_range_namespace_1.bin"}, + {0x04, "nvme_feature_setting_temp_threshold.bin"}, + {0x05, "nvme_feature_setting_error_recovery.bin"}, + {0x06, "nvme_feature_setting_volatile_write_cache.bin"}, + {0x07, "nvme_feature_setting_num_queues.bin"}, + {0x08, "nvme_feature_setting_interrupt_coalescing.bin"}, + {0x09, "nvme_feature_setting_interrupt_vec_config.bin"}, + {0x0A, "nvme_feature_setting_write_atomicity.bin"}, + {0x0B, "nvme_feature_setting_async_event_config.bin"}, + {0x80, "nvme_feature_setting_sw_progress_marker.bin"}, + }; + + for (i = 0; i < (int)(ARRAY_SIZE(fmap)); i++) { + if (fmap[i].id == 0x03) { + len = 4096; + bufp = (unsigned char *)(&buf[0]); + } else { + len = 0; + bufp = NULL; + } struct nvme_get_features_args args = { .args_size = sizeof(args), @@ -1995,901 +2001,882 @@ static int GetFeatureSettings(int fd, const char *dir) .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = &attrVal, }; - err = nvme_get_features(&args); - if (err == 0) { - sprintf(msg, "feature: 0x%X", fmap[i].id); - WriteData((__u8*)&attrVal, sizeof(attrVal), dir, fmap[i].file, msg); - if (bufp != NULL) { - WriteData(bufp, len, dir, fmap[i].file, msg); - } - } else { - fprintf(stderr, "Feature 0x%x data not retrieved, error %d (ignored)!\n", - fmap[i].id, err); - errcnt++; - } - } - return (int)(errcnt == sizeof(fmap)/sizeof(fmap[0])); + err = nvme_get_features(&args); + if (!err) { + sprintf(msg, "feature: 0x%X", fmap[i].id); + WriteData((__u8 *)&attrVal, sizeof(attrVal), dir, fmap[i].file, msg); + if (bufp) + WriteData(bufp, len, dir, fmap[i].file, msg); + } else { + fprintf(stderr, "Feature 0x%x data not retrieved, error %d (ignored)!\n", + fmap[i].id, err); + errcnt++; + } + } + return (int)(errcnt == ARRAY_SIZE(fmap)); } static int micron_drive_info(int argc, char **argv, struct command *cmd, - struct plugin *plugin) + struct plugin *plugin) { - const char *desc = "Get drive HW information"; - struct nvme_id_ctrl ctrl = { 0 }; - struct nvme_passthru_cmd admin_cmd = { 0 }; - struct fb_drive_info { - unsigned char hw_ver_major; - unsigned char hw_ver_minor; - unsigned char ftl_unit_size; - unsigned char bs_ver_major; - unsigned char bs_ver_minor; - } dinfo = { 0 }; - eDriveModel model = UNKNOWN_MODEL; - bool is_json = false; - struct json_object *root, *driveInfo; - struct nvme_dev *dev; - struct format { - char *fmt; - }; - int err = 0; - - const char *fmt = "output format normal"; - struct format cfg = { - .fmt = "normal", - }; - - OPT_ARGS(opts) = { - OPT_FMT("format", 'f', &cfg.fmt, fmt), - OPT_END() - }; - - err = micron_parse_options(&dev, argc, argv, desc, opts, &model); - if (err < 0) - return err; - - if (model == UNKNOWN_MODEL) { - fprintf(stderr, "ERROR : Unsupported drive for vs-drive-info cmd"); - dev_close(dev); - return -1; - } - - if (strcmp(cfg.fmt, "json") == 0) - is_json = true; - - if (model == M5407) { - admin_cmd.opcode = 0xD4, - admin_cmd.addr = (__u64) (uintptr_t) &dinfo; - admin_cmd.data_len = (__u32)sizeof(dinfo); - admin_cmd.cdw12 = 3; - err = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); - if (err) { - fprintf(stderr, "ERROR : drive-info opcode failed with 0x%x\n", err); - dev_close(dev); - return -1; - } - } else { - err = nvme_identify_ctrl(dev_fd(dev), &ctrl); - if (err) { - fprintf(stderr, "ERROR : identify_ctrl() failed with 0x%x\n", err); - dev_close(dev); - return -1; - } - dinfo.hw_ver_major = ctrl.vs[820]; - dinfo.hw_ver_minor = ctrl.vs[821]; - dinfo.ftl_unit_size = ctrl.vs[822]; - } - - if (is_json) { - struct json_object *pinfo = json_create_object(); - char tempstr[64] = { 0 }; - root = json_create_object(); - driveInfo = json_create_array(); - json_object_add_value_array(root, "Micron Drive HW Information", driveInfo); - sprintf(tempstr, "%hhu.%hhu", dinfo.hw_ver_major, dinfo.hw_ver_minor); - json_object_add_value_string(pinfo, "Drive Hardware Version", tempstr); - - if (dinfo.ftl_unit_size) { - sprintf(tempstr, "%hhu KB", dinfo.ftl_unit_size); - json_object_add_value_string(pinfo, "FTL_unit_size", tempstr); - } - - if (dinfo.bs_ver_major != 0 || dinfo.bs_ver_minor != 0) { - sprintf(tempstr, "%hhu.%hhu", dinfo.bs_ver_major, dinfo.bs_ver_minor); - json_object_add_value_string(pinfo, "Boot Spec.Version", tempstr); - } - - json_array_add_value_object(driveInfo, pinfo); - json_print_object(root, NULL); - printf("\n"); - json_free_object(root); - } else { - printf("Drive Hardware Version: %hhu.%hhu\n", - dinfo.hw_ver_major, dinfo.hw_ver_minor); - - if (dinfo.ftl_unit_size) - printf("FTL_unit_size: %hhu KB\n", dinfo.ftl_unit_size); - - if (dinfo.bs_ver_major != 0 || dinfo.bs_ver_minor != 0) { - printf("Boot Spec.Version: %hhu.%hhu\n", - dinfo.bs_ver_major, dinfo.bs_ver_minor); - } - } - - dev_close(dev); - return 0; + const char *desc = "Get drive HW information"; + struct nvme_id_ctrl ctrl = { 0 }; + struct nvme_passthru_cmd admin_cmd = { 0 }; + struct fb_drive_info { + unsigned char hw_ver_major; + unsigned char hw_ver_minor; + unsigned char ftl_unit_size; + unsigned char bs_ver_major; + unsigned char bs_ver_minor; + } dinfo = { 0 }; + enum eDriveModel model = UNKNOWN_MODEL; + bool is_json = false; + struct json_object *root, *driveInfo; + struct nvme_dev *dev; + struct format { + char *fmt; + }; + int err = 0; + + const char *fmt = "output format normal"; + struct format cfg = { + .fmt = "normal", + }; + + OPT_ARGS(opts) = { + OPT_FMT("format", 'f', &cfg.fmt, fmt), + OPT_END() + }; + + err = micron_parse_options(&dev, argc, argv, desc, opts, &model); + if (err < 0) + return err; + + if (model == UNKNOWN_MODEL) { + fprintf(stderr, "ERROR : Unsupported drive for vs-drive-info cmd"); + dev_close(dev); + return -1; + } + + if (!strcmp(cfg.fmt, "json")) + is_json = true; + + if (model == M5407) { + admin_cmd.opcode = 0xD4, + admin_cmd.addr = (__u64) (uintptr_t) &dinfo; + admin_cmd.data_len = (__u32)sizeof(dinfo); + admin_cmd.cdw12 = 3; + err = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); + if (err) { + fprintf(stderr, "ERROR : drive-info opcode failed with 0x%x\n", err); + dev_close(dev); + return -1; + } + } else { + err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + if (err) { + fprintf(stderr, "ERROR : identify_ctrl() failed with 0x%x\n", err); + dev_close(dev); + return -1; + } + dinfo.hw_ver_major = ctrl.vs[820]; + dinfo.hw_ver_minor = ctrl.vs[821]; + dinfo.ftl_unit_size = ctrl.vs[822]; + } + + if (is_json) { + struct json_object *pinfo = json_create_object(); + char tempstr[64] = { 0 }; + + root = json_create_object(); + driveInfo = json_create_array(); + json_object_add_value_array(root, "Micron Drive HW Information", driveInfo); + sprintf(tempstr, "%u.%u", dinfo.hw_ver_major, dinfo.hw_ver_minor); + json_object_add_value_string(pinfo, "Drive Hardware Version", tempstr); + + if (dinfo.ftl_unit_size) { + sprintf(tempstr, "%u KB", dinfo.ftl_unit_size); + json_object_add_value_string(pinfo, "FTL_unit_size", tempstr); + } + + if (dinfo.bs_ver_major || dinfo.bs_ver_minor) { + sprintf(tempstr, "%u.%u", dinfo.bs_ver_major, dinfo.bs_ver_minor); + json_object_add_value_string(pinfo, "Boot Spec.Version", tempstr); + } + + json_array_add_value_object(driveInfo, pinfo); + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); + } else { + printf("Drive Hardware Version: %u.%u\n", + dinfo.hw_ver_major, dinfo.hw_ver_minor); + + if (dinfo.ftl_unit_size) + printf("FTL_unit_size: %u KB\n", dinfo.ftl_unit_size); + + if (dinfo.bs_ver_major || dinfo.bs_ver_minor) + printf("Boot Spec.Version: %u.%u\n", + dinfo.bs_ver_major, dinfo.bs_ver_minor); + } + + dev_close(dev); + return 0; } static int micron_cloud_ssd_plugin_version(int argc, char **argv, - struct command *cmd, struct plugin *plugin) + struct command *cmd, struct plugin *plugin) { - printf("nvme-cli Micron cloud SSD plugin version: %s.%s\n", - __version_major, __version_minor); - return 0; + printf("nvme-cli Micron cloud SSD plugin version: %s.%s\n", + __version_major, __version_minor); + return 0; } static int micron_plugin_version(int argc, char **argv, struct command *cmd, - struct plugin *plugin) + struct plugin *plugin) { - printf("nvme-cli Micron plugin version: %s.%s.%s\n", - __version_major, __version_minor, __version_patch); - return 0; + printf("nvme-cli Micron plugin version: %s.%s.%s\n", + __version_major, __version_minor, __version_patch); + return 0; } /* Binary format of firmware activation history entry */ -struct __attribute__((__packed__)) fw_activation_history_entry { - __u8 version; - __u8 length; - __u16 rsvd1; - __le16 valid; - __le64 power_on_hour; - __le64 rsvd2; - __le64 power_cycle_count; - __u8 previous_fw[8]; - __u8 activated_fw[8]; - __u8 slot; - __u8 commit_action_type; - __le16 result; - __u8 rsvd3[14]; +struct __packed fw_activation_history_entry { + __u8 version; + __u8 length; + __u16 rsvd1; + __le16 valid; + __le64 power_on_hour; + __le64 rsvd2; + __le64 power_cycle_count; + __u8 previous_fw[8]; + __u8 activated_fw[8]; + __u8 slot; + __u8 commit_action_type; + __le16 result; + __u8 rsvd3[14]; }; - /* Binary format for firmware activation history table */ -struct __attribute__((__packed__)) micron_fw_activation_history_table { - __u8 log_page; - __u8 rsvd1[3]; - __le32 num_entries; - struct fw_activation_history_entry entries[20]; - __u8 rsvd2[2790]; - __u16 version; - __u8 GUID[16]; +struct __packed micron_fw_activation_history_table { + __u8 log_page; + __u8 rsvd1[3]; + __le32 num_entries; + struct fw_activation_history_entry entries[20]; + __u8 rsvd2[2790]; + __u16 version; + __u8 GUID[16]; }; -/* header to be printed field widths = 10 | 12 | 10 | 11 | 12 | 9 | 9 | 9 */ - -const char *fw_activation_history_table_header = "\ -__________________________________________________________________________________\n\ - | | | | | | | \n\ -Firmware | Power On | Power | Previous | New FW | Slot | Commit | Result \n\ -Activation| Hour | cycle | firmware | activated | number | Action | \n\ -Counter | | count | | | | Type | \n\ -__________|___________|_________|__________|___________|________|________|________\n"; - -static int display_fw_activate_entry ( - int entry_count, - struct fw_activation_history_entry *entry, - char *formatted_entry, - struct json_object *stats -) +static int display_fw_activate_entry(int entry_count, struct fw_activation_history_entry *entry, + char *formatted_entry, struct json_object *stats) { - time_t timestamp, hours; - char buffer[32]; - __u8 minutes, seconds; - char *ca[] = {"000b", "001b", "010b", "011b"}; - char *ptr = formatted_entry; - int index = 0, entry_size = 82; - - if ((entry->version != 1 && entry->version != 2) || entry->length != 64) { - /*fprintf(stderr, "unsupported entry ! version: %x with length: %d\n", - entry->version, entry->length); */ - return -EINVAL; - } - - sprintf(ptr, "%d", entry_count); - ptr += 10; - - timestamp = (le64_to_cpu(entry->power_on_hour) & 0x0000FFFFFFFFFFFFUL) / 1000; - hours = timestamp / 3600; - minutes = (timestamp % 3600) / 60; - seconds = (timestamp % 3600) % 60; - sprintf(ptr, "|%"PRIu64":%hhu:%hhu", (uint64_t)hours, minutes, seconds); - ptr += 12; - - sprintf(ptr, "| %"PRIu64, le64_to_cpu(entry->power_cycle_count)); - ptr += 10; - - /* firmware details */ - memset(buffer, 0, sizeof(buffer)); - memcpy(buffer, entry->previous_fw, sizeof(entry->previous_fw)); - sprintf(ptr, "| %s", buffer); - ptr += 11; - - memset(buffer, 0, sizeof(buffer)); - memcpy(buffer, entry->activated_fw, sizeof(entry->activated_fw)); - sprintf(ptr, "| %s", buffer); - ptr += 12; - - /* firmware slot and commit action*/ - sprintf(ptr, "| %d", entry->slot); - ptr += 9; - - if (entry->commit_action_type <= 3) - sprintf(ptr, "| %s", ca[entry->commit_action_type]); - else - sprintf(ptr, "| xxxb"); - ptr += 9; - - /* result */ - if (entry->result) { - sprintf(ptr, "| Fail #%d", entry->result); - } else { - sprintf(ptr, "| pass"); - } - - /* replace all null charecters with spaces */ - ptr = formatted_entry; - while (index < entry_size) { - if (ptr[index] == '\0') - ptr[index] = ' '; - index++; - } - return 0; + time_t timestamp, hours; + char buffer[32]; + __u8 minutes, seconds; + static const char * const ca[] = {"000b", "001b", "010b", "011b"}; + char *ptr = formatted_entry; + int index = 0, entry_size = 82; + + if ((entry->version != 1 && entry->version != 2) || entry->length != 64) + return -EINVAL; + + sprintf(ptr, "%d", entry_count); + ptr += 10; + + timestamp = (le64_to_cpu(entry->power_on_hour) & 0x0000FFFFFFFFFFFFUL) / 1000; + hours = timestamp / 3600; + minutes = (timestamp % 3600) / 60; + seconds = (timestamp % 3600) % 60; + sprintf(ptr, "|%"PRIu64":%u:%u", (uint64_t)hours, minutes, seconds); + ptr += 12; + + sprintf(ptr, "| %"PRIu64, le64_to_cpu(entry->power_cycle_count)); + ptr += 10; + + /* firmware details */ + memset(buffer, 0, sizeof(buffer)); + memcpy(buffer, entry->previous_fw, sizeof(entry->previous_fw)); + sprintf(ptr, "| %s", buffer); + ptr += 11; + + memset(buffer, 0, sizeof(buffer)); + memcpy(buffer, entry->activated_fw, sizeof(entry->activated_fw)); + sprintf(ptr, "| %s", buffer); + ptr += 12; + + /* firmware slot and commit action*/ + sprintf(ptr, "| %d", entry->slot); + ptr += 9; + + if (entry->commit_action_type <= 3) + sprintf(ptr, "| %s", ca[entry->commit_action_type]); + else + sprintf(ptr, "| xxxb"); + ptr += 9; + + /* result */ + if (entry->result) + sprintf(ptr, "| Fail #%d", entry->result); + else + sprintf(ptr, "| pass"); + + /* replace all null charecters with spaces */ + ptr = formatted_entry; + while (index < entry_size) { + if (ptr[index] == '\0') + ptr[index] = ' '; + index++; + } + return 0; } +static void micron_fw_activation_history_header_print(void) +{ + /* header to be printed field widths = 10 | 12 | 10 | 11 | 12 | 9 | 9 | 9 */ + printf("__________________________________________________________________________________\n"); + printf(" | | | | | | |\n"); + printf("Firmware | Power On | Power | Previous | New FW | Slot | Commit | Result\n"); + printf("Activation| Hour | cycle | firmware | activated | number | Action |\n"); + printf("Counter | | count | | | | Type |\n"); + printf("__________|___________|_________|__________|___________|________|________|________\n"); +} static int micron_fw_activation_history(int argc, char **argv, struct command *cmd, - struct plugin *plugin) + struct plugin *plugin) { - const char *desc = "Retrieve Firmware Activation history of the given drive"; - char formatted_output[100]; - int count = 0; - unsigned int logC2[C2_log_size/sizeof(int)] = { 0 }; - eDriveModel eModel = UNKNOWN_MODEL; - struct nvme_dev *dev; - struct format { - char *fmt; - }; - int err; - - const char *fmt = "output format normal"; - struct format cfg = { - .fmt = "normal", - }; - - OPT_ARGS(opts) = { - OPT_FMT("format", 'f', &cfg.fmt, fmt), - OPT_END() - }; - - err = micron_parse_options(&dev, argc, argv, desc, opts, &eModel); - if (err < 0) - return -1; - - if (strcmp(cfg.fmt, "normal") != 0) { - fprintf (stderr, "only normal format is supported currently\n"); - dev_close(dev); - return -1; - } - - /* check if product supports fw_history log */ - err = -EINVAL; - if (eModel != M51CX) { - fprintf(stderr, "Unsupported drive model for vs-fw-activate-history command\n"); - goto out; - } - - err = nvme_get_log_simple(dev_fd(dev), 0xC2, C2_log_size, logC2); - if (err) { - fprintf(stderr, "Failed to retrieve fw activation history log, error: %x\n", err); - goto out; - } - - /* check if we have atleast one entry to print */ - struct micron_fw_activation_history_table *table = - (struct micron_fw_activation_history_table *)logC2; - - /* check version and log page */ - if (table->log_page != 0xC2 || (table->version != 2 && table->version != 1)) - { - fprintf(stderr, "Unsupported fw activation history page: %x, version: %x\n", - table->log_page, table->version); - goto out; - } - - if (table->num_entries == 0) { - fprintf(stderr, "No entries were found in fw activation history log\n"); - goto out; - } - - printf("%s", fw_activation_history_table_header); - for(count = 0; count < table->num_entries; count++) { - memset(formatted_output, '\0', 100); - if (display_fw_activate_entry(count, - &table->entries[count], - formatted_output, NULL) == 0) - { - printf("%s\n", formatted_output); - } - } + const char *desc = "Retrieve Firmware Activation history of the given drive"; + char formatted_output[100]; + int count = 0; + unsigned int logC2[C2_log_size/sizeof(int)] = { 0 }; + enum eDriveModel eModel = UNKNOWN_MODEL; + struct nvme_dev *dev; + struct format { + char *fmt; + }; + int err; + + const char *fmt = "output format normal"; + struct format cfg = { + .fmt = "normal", + }; + + OPT_ARGS(opts) = { + OPT_FMT("format", 'f', &cfg.fmt, fmt), + OPT_END() + }; + + err = micron_parse_options(&dev, argc, argv, desc, opts, &eModel); + if (err < 0) + return -1; + + if (strcmp(cfg.fmt, "normal")) { + fprintf(stderr, "only normal format is supported currently\n"); + dev_close(dev); + return -1; + } + + /* check if product supports fw_history log */ + err = -EINVAL; + if (eModel != M51CX) { + fprintf(stderr, "Unsupported drive model for vs-fw-activate-history command\n"); + goto out; + } + + err = nvme_get_log_simple(dev_fd(dev), 0xC2, C2_log_size, logC2); + if (err) { + fprintf(stderr, "Failed to retrieve fw activation history log, error: %x\n", err); + goto out; + } + + /* check if we have atleast one entry to print */ + struct micron_fw_activation_history_table *table = + (struct micron_fw_activation_history_table *)logC2; + + /* check version and log page */ + if (table->log_page != 0xC2 || (table->version != 2 && table->version != 1)) { + fprintf(stderr, "Unsupported fw activation history page: %x, version: %x\n", + table->log_page, table->version); + goto out; + } + + if (!table->num_entries) { + fprintf(stderr, "No entries were found in fw activation history log\n"); + goto out; + } + + micron_fw_activation_history_header_print(); + for (count = 0; count < table->num_entries; count++) { + memset(formatted_output, '\0', 100); + if (!display_fw_activate_entry(count, &table->entries[count], formatted_output, + NULL)) + printf("%s\n", formatted_output); + } out: - dev_close(dev); - return err; + dev_close(dev); + return err; } #define MICRON_FID_LATENCY_MONITOR 0xD0 #define MICRON_LOG_LATENCY_MONITOR 0xD1 static int micron_latency_stats_track(int argc, char **argv, struct command *cmd, - struct plugin *plugin) + struct plugin *plugin) { - int err = 0; - __u32 result = 0; - const char *desc = "Enable, Disable or Get cmd latency monitoring stats"; - const char *option = "enable or disable or status, default is status"; - const char *command = "commands to monitor for - all|read|write|trim," - " default is all i.e, enabled for all commands"; - const char *thrtime = "The threshold value to use for latency monitoring in" - " milliseconds, default is 800ms"; - - int fid = MICRON_FID_LATENCY_MONITOR; - eDriveModel model = UNKNOWN_MODEL; - uint32_t command_mask = 0x7; /* 1:read 2:write 4:trim 7:all */ - uint32_t timing_mask = 0x08080800; /* R[31-24]:W[23:16]:T[15:8]:0 */ - uint32_t enable = 2; - struct nvme_dev *dev; - struct { - char *option; - char *command; - uint32_t threshold; - } opt = { - .option = "status", - .command = "all", - .threshold = 0 - }; - - OPT_ARGS(opts) = { - OPT_STRING("option", 'o', "option", &opt.option, option), - OPT_STRING("command", 'c', "command", &opt.command, command), - OPT_UINT("threshold", 't', &opt.threshold, thrtime), - OPT_END() - }; - - - err = micron_parse_options(&dev, argc, argv, desc, opts, &model); - if (err < 0) - return -1; - - if (!strcmp(opt.option, "enable")) { - enable = 1; - } else if (!strcmp(opt.option, "disable")) { - enable = 0; - } else if (strcmp(opt.option, "status")) { - printf("Invalid control option %s specified\n", opt.option); - dev_close(dev); - return -1; - } - - struct nvme_get_features_args g_args = { - .args_size = sizeof(g_args), - .fd = dev_fd(dev), - .fid = fid, - .nsid = 0, - .sel = 0, + int err = 0; + __u32 result = 0; + const char *desc = "Enable, Disable or Get cmd latency monitoring stats"; + const char *option = "enable or disable or status, default is status"; + const char *command = + "commands to monitor for - all|read|write|trim, default is all i.e, enabled for all commands"; + const char *thrtime = + "The threshold value to use for latency monitoring in milliseconds, default is 800ms"; + + int fid = MICRON_FID_LATENCY_MONITOR; + enum eDriveModel model = UNKNOWN_MODEL; + uint32_t command_mask = 0x7; /* 1:read 2:write 4:trim 7:all */ + uint32_t timing_mask = 0x08080800; /* R[31-24]:W[23:16]:T[15:8]:0 */ + uint32_t enable = 2; + struct nvme_dev *dev; + struct { + char *option; + char *command; + uint32_t threshold; + } opt = { + .option = "status", + .command = "all", + .threshold = 0 + }; + + OPT_ARGS(opts) = { + OPT_STRING("option", 'o', "option", &opt.option, option), + OPT_STRING("command", 'c', "command", &opt.command, command), + OPT_UINT("threshold", 't', &opt.threshold, thrtime), + OPT_END() + }; + + + err = micron_parse_options(&dev, argc, argv, desc, opts, &model); + if (err < 0) + return -1; + + if (!strcmp(opt.option, "enable")) { + enable = 1; + } else if (!strcmp(opt.option, "disable")) { + enable = 0; + } else if (strcmp(opt.option, "status")) { + printf("Invalid control option %s specified\n", opt.option); + dev_close(dev); + return -1; + } + + struct nvme_get_features_args g_args = { + .args_size = sizeof(g_args), + .fd = dev_fd(dev), + .fid = fid, + .nsid = 0, + .sel = 0, .cdw11 = 0, .uuidx = 0, .data_len = 0, .data = NULL, .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = &result, - }; + }; - err = nvme_get_features(&g_args); - if (err != 0) { - printf("Failed to retrieve latency monitoring feature status\n"); - dev_close(dev); - return err; - } - - /* If it is to retrieve the status only */ - if (enable == 2) { - printf("Latency Tracking Statistics is currently %s", - (result & 0xFFFF0000) ? "enabled" : "disabled"); - if ((result & 7) == 7) { - printf(" for All commands\n"); - } else if ((result & 7) > 0) { - printf(" for"); - if (result & 1) { - printf(" Read"); - } - if (result & 2) { - printf(" Write"); - } - if (result & 4) { - printf(" Trim"); - } - printf(" commands\n"); - } else if (result == 0) { - printf("\n"); - } - dev_close(dev); - return err; - } - - /* read and validate threshold values if enable option is specified */ - if (enable == 1) { - if (opt.threshold > 2550) { - printf("The maximum threshold value cannot be more than 2550 ms\n"); - dev_close(dev); - return -1; - } - /* timing mask is in terms of 10ms units, so min allowed is 10ms */ - else if ((opt.threshold % 10) != 0) { - printf("The threshold value should be multiple of 10 ms\n"); - dev_close(dev); - return -1; - } - opt.threshold /= 10; - } - - /* read-in command(s) to be monitored */ - if (!strcmp(opt.command, "read")) { - command_mask = 0x1; - timing_mask = (opt.threshold << 24); - } else if (!strcmp(opt.command, "write")) { - command_mask = 0x2; - timing_mask = (opt.threshold << 16); - } else if (!strcmp(opt.command, "trim")) { - command_mask = 0x4; - timing_mask = (opt.threshold << 8); - } else if (strcmp(opt.command, "all")) { - printf("Invalid command %s specified for option %s\n", + err = nvme_get_features(&g_args); + if (err) { + printf("Failed to retrieve latency monitoring feature status\n"); + dev_close(dev); + return err; + } + + /* If it is to retrieve the status only */ + if (enable == 2) { + printf("Latency Tracking Statistics is currently %s", + (result & 0xFFFF0000) ? "enabled" : "disabled"); + if ((result & 7) == 7) { + printf(" for All commands\n"); + } else if ((result & 7) > 0) { + printf(" for"); + if (result & 1) + printf(" Read"); + if (result & 2) + printf(" Write"); + if (result & 4) + printf(" Trim"); + printf(" commands\n"); + } else if (!result) { + printf("\n"); + } + dev_close(dev); + return err; + } + + /* read and validate threshold values if enable option is specified */ + if (enable == 1) { + if (opt.threshold > 2550) { + printf("The maximum threshold value cannot be more than 2550 ms\n"); + dev_close(dev); + return -1; + } else if (opt.threshold % 10) { + /* timing mask is in terms of 10ms units, so min allowed is 10ms */ + printf("The threshold value should be multiple of 10 ms\n"); + dev_close(dev); + return -1; + } + opt.threshold /= 10; + } + + /* read-in command(s) to be monitored */ + if (!strcmp(opt.command, "read")) { + command_mask = 0x1; + timing_mask = (opt.threshold << 24); + } else if (!strcmp(opt.command, "write")) { + command_mask = 0x2; + timing_mask = (opt.threshold << 16); + } else if (!strcmp(opt.command, "trim")) { + command_mask = 0x4; + timing_mask = (opt.threshold << 8); + } else if (strcmp(opt.command, "all")) { + printf("Invalid command %s specified for option %s\n", opt.command, opt.option); - dev_close(dev); - return -1; - } - - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = MICRON_FID_LATENCY_MONITOR, - .nsid = 0, - .cdw11 = enable, - .cdw12 = command_mask, - .save = 1, - .uuidx = 0, - .cdw13 = timing_mask, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - err = nvme_set_features(&args); - if (err == 0) { - printf("Successfully %sd latency monitoring for %s commands with %dms threshold\n", - opt.option, opt.command, opt.threshold == 0 ? 800 : opt.threshold * 10); - } else { - printf("Failed to %s latency monitoring for %s commands with %dms threshold\n", - opt.option, opt.command, opt.threshold == 0 ? 800 : opt.threshold * 10); - } - - dev_close(dev); - return err; + dev_close(dev); + return -1; + } + + struct nvme_set_features_args args = { + .args_size = sizeof(args), + .fd = dev_fd(dev), + .fid = MICRON_FID_LATENCY_MONITOR, + .nsid = 0, + .cdw11 = enable, + .cdw12 = command_mask, + .save = 1, + .uuidx = 0, + .cdw13 = timing_mask, + .cdw15 = 0, + .data_len = 0, + .data = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_set_features(&args); + if (!err) { + printf("Successfully %sd latency monitoring for %s commands with %dms threshold\n", + opt.option, opt.command, !opt.threshold ? 800 : opt.threshold * 10); + } else { + printf("Failed to %s latency monitoring for %s commands with %dms threshold\n", + opt.option, opt.command, !opt.threshold ? 800 : opt.threshold * 10); + } + + dev_close(dev); + return err; } static int micron_latency_stats_logs(int argc, char **argv, struct command *cmd, - struct plugin *plugin) + struct plugin *plugin) { #define LATENCY_LOG_ENTRIES 16 - struct latency_log_entry { - uint64_t timestamp; - uint32_t latency; - uint32_t cmdtag; + struct latency_log_entry { + uint64_t timestamp; + uint32_t latency; + uint32_t cmdtag; union { - struct { - uint32_t opcode:8; + struct { + uint32_t opcode:8; uint32_t fuse:2; uint32_t rsvd1:4; uint32_t psdt:2; uint32_t cid:16; - }; - uint32_t dw0; + }; + uint32_t dw0; }; uint32_t nsid; uint32_t slba_low; uint32_t slba_high; union { - struct { - uint32_t nlb:16; - uint32_t rsvd2:9; - uint32_t deac:1; - uint32_t prinfo:4; - uint32_t fua:1; - uint32_t lr:1; - }; - uint32_t dw12; + struct { + uint32_t nlb:16; + uint32_t rsvd2:9; + uint32_t deac:1; + uint32_t prinfo:4; + uint32_t fua:1; + uint32_t lr:1; + }; + uint32_t dw12; + }; + uint32_t dsm; + uint32_t rfu[6]; + } log[LATENCY_LOG_ENTRIES]; + enum eDriveModel model = UNKNOWN_MODEL; + struct nvme_dev *dev; + int err = -1; + const char *desc = "Display Latency tracking log information"; + + OPT_ARGS(opts) = { + OPT_END() }; - uint32_t dsm; - uint32_t rfu[6]; - } log[LATENCY_LOG_ENTRIES]; - eDriveModel model = UNKNOWN_MODEL; - struct nvme_dev *dev; - int err = -1; - const char *desc = "Display Latency tracking log information"; - OPT_ARGS(opts) = { - OPT_END() - }; - - err = micron_parse_options(&dev, argc, argv, desc, opts, &model); - if (err) - return err; - memset(&log, 0, sizeof(log)); - err = nvme_get_log_simple(dev_fd(dev), 0xD1, sizeof(log), &log); - if (err) { - if (err < 0) - printf("Unable to retrieve latency stats log the drive\n"); - dev_close(dev); - return err; - } - /* print header and each log entry */ - printf("Timestamp, Latency, CmdTag, Opcode, Fuse, Psdt,Cid, Nsid," - "Slba_L, Slba_H, Nlb, DEAC, PRINFO, FUA,LR\n"); - for (int i = 0; i < LATENCY_LOG_ENTRIES; i++) { - printf("%"PRIu64",%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u\n", - log[i].timestamp,log[i].latency, log[i].cmdtag, log[i].opcode, - log[i].fuse, log[i].psdt, log[i].cid, log[i].nsid, - log[i].slba_low, log[i].slba_high, log[i].nlb, - log[i].deac, log[i].prinfo, log[i].fua, log[i].lr); - } - printf("\n"); - dev_close(dev); - return err; + + err = micron_parse_options(&dev, argc, argv, desc, opts, &model); + if (err) + return err; + memset(&log, 0, sizeof(log)); + err = nvme_get_log_simple(dev_fd(dev), 0xD1, sizeof(log), &log); + if (err) { + if (err < 0) + printf("Unable to retrieve latency stats log the drive\n"); + dev_close(dev); + return err; + } + /* print header and each log entry */ + printf("Timestamp, Latency, CmdTag, Opcode, Fuse, Psdt, Cid, Nsid, Slba_L, Slba_H, Nlb, "); + printf("DEAC, PRINFO, FUA, LR\n"); + for (int i = 0; i < LATENCY_LOG_ENTRIES; i++) + printf("%"PRIu64",%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u\n", + log[i].timestamp, log[i].latency, log[i].cmdtag, log[i].opcode, + log[i].fuse, log[i].psdt, log[i].cid, log[i].nsid, + log[i].slba_low, log[i].slba_high, log[i].nlb, + log[i].deac, log[i].prinfo, log[i].fua, log[i].lr); + printf("\n"); + dev_close(dev); + return err; } static int micron_latency_stats_info(int argc, char **argv, struct command *cmd, - struct plugin *plugin) + struct plugin *plugin) { - const char *desc = "display command latency statistics"; - const char *command = "command to display stats - all|read|write|trim" - "default is all"; - int err = 0; - struct nvme_dev *dev; - eDriveModel model = UNKNOWN_MODEL; - #define LATENCY_BUCKET_COUNT 32 - #define LATENCY_BUCKET_RSVD 32 - struct micron_latency_stats { - uint64_t version; /* major << 32 | minior */ - uint64_t all_cmds[LATENCY_BUCKET_COUNT + LATENCY_BUCKET_RSVD]; - uint64_t read_cmds[LATENCY_BUCKET_COUNT + LATENCY_BUCKET_RSVD]; - uint64_t write_cmds[LATENCY_BUCKET_COUNT + LATENCY_BUCKET_RSVD]; - uint64_t trim_cmds[LATENCY_BUCKET_COUNT + LATENCY_BUCKET_RSVD]; - uint32_t reserved[255]; /* round up to 4K */ - } log; - - struct latency_thresholds { - uint32_t start; - uint32_t end; - char *unit; - } thresholds[LATENCY_BUCKET_COUNT] = { - {0, 50, "us"}, {50, 100, "us"}, {100, 150, "us"}, {150, 200, "us"}, - {200, 300, "us"}, {300, 400, "us"}, {400, 500, "us"}, {500, 600, "us"}, - {600, 700, "us"}, {700, 800, "us"}, {800, 900, "us"}, {900, 1000, "us"}, - {1, 5, "ms"}, {5, 10, "ms"}, {10, 20, "ms"}, {20, 50, "ms"}, {50, 100, "ms"}, - {100, 200, "ms"}, {200, 300, "ms"}, {300, 400, "ms"}, {400, 500, "ms"}, - {500, 600, "ms"}, {600, 700, "ms"}, {700, 800, "ms"}, {800, 900, "ms"}, - {900, 1000, "ms"}, {1, 2, "s"}, {2, 3, "s"}, {3, 4, "s"}, {4, 5, "s"}, - {5,8, "s"}, - {8, INT_MAX, "s"}, - }; - - struct { - char *command; - } opt = { - .command="all" - }; - - uint64_t *cmd_stats = &log.all_cmds[0]; - char *cmd_str = "All"; - - OPT_ARGS(opts) = { - OPT_STRING("command", 'c', "command", &opt.command, command), - OPT_END() - }; - - err = micron_parse_options(&dev, argc, argv, desc, opts, &model); - if (err < 0) - return err; - if (!strcmp(opt.command, "read")) { - cmd_stats = &log.read_cmds[0]; + const char *desc = "display command latency statistics"; + const char *command = "command to display stats - all|read|write|trimdefault is all"; + int err = 0; + struct nvme_dev *dev; + enum eDriveModel model = UNKNOWN_MODEL; + #define LATENCY_BUCKET_COUNT 32 + #define LATENCY_BUCKET_RSVD 32 + struct micron_latency_stats { + uint64_t version; /* major << 32 | minior */ + uint64_t all_cmds[LATENCY_BUCKET_COUNT + LATENCY_BUCKET_RSVD]; + uint64_t read_cmds[LATENCY_BUCKET_COUNT + LATENCY_BUCKET_RSVD]; + uint64_t write_cmds[LATENCY_BUCKET_COUNT + LATENCY_BUCKET_RSVD]; + uint64_t trim_cmds[LATENCY_BUCKET_COUNT + LATENCY_BUCKET_RSVD]; + uint32_t reserved[255]; /* round up to 4K */ + } log; + + struct latency_thresholds { + uint32_t start; + uint32_t end; + char *unit; + } thresholds[LATENCY_BUCKET_COUNT] = { + {0, 50, "us"}, {50, 100, "us"}, {100, 150, "us"}, {150, 200, "us"}, + {200, 300, "us"}, {300, 400, "us"}, {400, 500, "us"}, {500, 600, "us"}, + {600, 700, "us"}, {700, 800, "us"}, {800, 900, "us"}, {900, 1000, "us"}, + {1, 5, "ms"}, {5, 10, "ms"}, {10, 20, "ms"}, {20, 50, "ms"}, {50, 100, "ms"}, + {100, 200, "ms"}, {200, 300, "ms"}, {300, 400, "ms"}, {400, 500, "ms"}, + {500, 600, "ms"}, {600, 700, "ms"}, {700, 800, "ms"}, {800, 900, "ms"}, + {900, 1000, "ms"}, {1, 2, "s"}, {2, 3, "s"}, {3, 4, "s"}, {4, 5, "s"}, + {5, 8, "s"}, + {8, INT_MAX, "s"}, + }; + + struct { + char *command; + } opt = { + .command = "all" + }; + + uint64_t *cmd_stats = &log.all_cmds[0]; + char *cmd_str = "All"; + + OPT_ARGS(opts) = { + OPT_STRING("command", 'c', "command", &opt.command, command), + OPT_END() + }; + + err = micron_parse_options(&dev, argc, argv, desc, opts, &model); + if (err < 0) + return err; + if (!strcmp(opt.command, "read")) { + cmd_stats = &log.read_cmds[0]; cmd_str = "Read"; - } else if (!strcmp(opt.command, "write")) { - cmd_stats = &log.write_cmds[0]; + } else if (!strcmp(opt.command, "write")) { + cmd_stats = &log.write_cmds[0]; cmd_str = "Write"; - } else if (!strcmp(opt.command, "trim")) { - cmd_stats = &log.trim_cmds[0]; + } else if (!strcmp(opt.command, "trim")) { + cmd_stats = &log.trim_cmds[0]; cmd_str = "Trim"; - } else if (strcmp(opt.command, "all")) { - printf("Invalid command option %s to display latency stats\n", opt.command); - dev_close(dev); + } else if (strcmp(opt.command, "all")) { + printf("Invalid command option %s to display latency stats\n", opt.command); + dev_close(dev); return -1; - } - - memset(&log, 0, sizeof(log)); - err = nvme_get_log_simple(dev_fd(dev), 0xD0, sizeof(log), &log); - if (err) { - if (err < 0) - printf("Unable to retrieve latency stats log the drive\n"); - dev_close(dev); - return err; - } - printf("Micron IO %s Command Latency Statistics\n" + } + + memset(&log, 0, sizeof(log)); + err = nvme_get_log_simple(dev_fd(dev), 0xD0, sizeof(log), &log); + if (err) { + if (err < 0) + printf("Unable to retrieve latency stats log the drive\n"); + dev_close(dev); + return err; + } + printf("Micron IO %s Command Latency Statistics\n" "Major Revision : %d\nMinor Revision : %d\n", cmd_str, (int)(log.version >> 32), (int)(log.version & 0xFFFFFFFF)); - printf("=============================================\n"); - printf("Bucket Start End Command Count\n"); - printf("=============================================\n"); - - for (int b = 0; b < LATENCY_BUCKET_COUNT; b++) { - int bucket = b + 1; - char start[32] = { 0 }; - char end[32] = { 0 }; - sprintf(start, "%u%s", thresholds[b].start, thresholds[b].unit); - if (thresholds[b].end == INT_MAX) - sprintf(end, "INF"); - else - sprintf(end, "%u%s", thresholds[b].end, thresholds[b].unit); - printf("%2d %8s %8s %8"PRIu64"\n", - bucket, start, end, cmd_stats[b]); - } - dev_close(dev); - return err; + printf("=============================================\n"); + printf("Bucket Start End Command Count\n"); + printf("=============================================\n"); + + for (int b = 0; b < LATENCY_BUCKET_COUNT; b++) { + int bucket = b + 1; + char start[32] = { 0 }; + char end[32] = { 0 }; + + sprintf(start, "%u%s", thresholds[b].start, thresholds[b].unit); + if (thresholds[b].end == INT_MAX) + sprintf(end, "INF"); + else + sprintf(end, "%u%s", thresholds[b].end, thresholds[b].unit); + printf("%2d %8s %8s %8"PRIu64"\n", bucket, start, end, cmd_stats[b]); + } + dev_close(dev); + return err; } static int micron_ocp_smart_health_logs(int argc, char **argv, struct command *cmd, - struct plugin *plugin) + struct plugin *plugin) { - const char *desc = "Retrieve Smart or Extended Smart Health log for the given device "; - unsigned int logC0[C0_log_size/sizeof(int)] = { 0 }; - unsigned int logFB[FB_log_size/sizeof(int)] = { 0 }; - struct nvme_id_ctrl ctrl; - eDriveModel eModel = UNKNOWN_MODEL; - struct nvme_dev *dev; - bool is_json = true; - struct format { - char *fmt; - }; - const char *fmt = "output format normal|json"; - struct format cfg = { - .fmt = "json", - }; - int err = 0; - - OPT_ARGS(opts) = { - OPT_FMT("format", 'f', &cfg.fmt, fmt), - OPT_END() - }; - - err = micron_parse_options(&dev, argc, argv, desc, opts, &eModel); - if (err < 0) - return -1; - - if (strcmp(cfg.fmt, "normal") == 0) - is_json = false; - - /* For M5410 and M5407, this option prints 0xFB log page */ - if (eModel == M5410 || eModel == M5407) { - __u8 spec = (eModel == M5410) ? 0 : 1; - __u8 nsze; - - if ((err = nvme_identify_ctrl(dev_fd(dev), &ctrl)) == 0) - err = nvme_get_log_simple(dev_fd(dev), 0xFB, - FB_log_size, logFB); - if (err) { - if (err < 0) - printf("Unable to retrieve smart log 0xFB for the drive\n"); - goto out; - } - - nsze = (ctrl.vs[987] == 0x12); - if (nsze == 0 && nsze_from_oacs) - nsze = ((ctrl.oacs >> 3) & 0x1); - print_nand_stats_fb((__u8 *)logFB, NULL, nsze, is_json, spec); - goto out; - } - - /* check for models that support 0xC0 log */ - if (eModel != M51CX) { - printf ("Unsupported drive model for vs-smart-add-log commmand\n"); - err = -1; - goto out; - } - - err = nvme_get_log_simple(dev_fd(dev), 0xC0, C0_log_size, logC0); - if (err == 0) { - print_smart_cloud_health_log((__u8 *)logC0, is_json); - } else if (err < 0) { - printf("Unable to retrieve extended smart log 0xC0 for the drive\n"); - } + const char *desc = "Retrieve Smart or Extended Smart Health log for the given device "; + unsigned int logC0[C0_log_size/sizeof(int)] = { 0 }; + unsigned int logFB[FB_log_size/sizeof(int)] = { 0 }; + struct nvme_id_ctrl ctrl; + enum eDriveModel eModel = UNKNOWN_MODEL; + struct nvme_dev *dev; + bool is_json = true; + struct format { + char *fmt; + }; + const char *fmt = "output format normal|json"; + struct format cfg = { + .fmt = "json", + }; + int err = 0; + + OPT_ARGS(opts) = { + OPT_FMT("format", 'f', &cfg.fmt, fmt), + OPT_END() + }; + + err = micron_parse_options(&dev, argc, argv, desc, opts, &eModel); + if (err < 0) + return -1; + + if (!strcmp(cfg.fmt, "normal")) + is_json = false; + + /* For M5410 and M5407, this option prints 0xFB log page */ + if (eModel == M5410 || eModel == M5407) { + __u8 spec = (eModel == M5410) ? 0 : 1; + __u8 nsze; + + err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + if (!err) + err = nvme_get_log_simple(dev_fd(dev), 0xFB, FB_log_size, logFB); + if (err) { + if (err < 0) + printf("Unable to retrieve smart log 0xFB for the drive\n"); + goto out; + } + + nsze = (ctrl.vs[987] == 0x12); + if (!nsze && nsze_from_oacs) + nsze = ((ctrl.oacs >> 3) & 0x1); + print_nand_stats_fb((__u8 *)logFB, NULL, nsze, is_json, spec); + goto out; + } + + /* check for models that support 0xC0 log */ + if (eModel != M51CX) { + printf("Unsupported drive model for vs-smart-add-log commmand\n"); + err = -1; + goto out; + } + + err = nvme_get_log_simple(dev_fd(dev), 0xC0, C0_log_size, logC0); + if (!err) + print_smart_cloud_health_log((__u8 *)logC0, is_json); + else if (err < 0) + printf("Unable to retrieve extended smart log 0xC0 for the drive\n"); out: - dev_close(dev); - if (err > 0) - nvme_show_status(err); - return err; + dev_close(dev); + if (err > 0) + nvme_show_status(err); + return err; } static int micron_clr_fw_activation_history(int argc, char **argv, - struct command *cmd, struct plugin *plugin) + struct command *cmd, struct plugin *plugin) { - const char *desc = "Clear FW activation history"; - __u32 result = 0; - __u8 fid = MICRON_FEATURE_CLEAR_FW_ACTIVATION_HISTORY; - eDriveModel model = UNKNOWN_MODEL; - struct nvme_dev *dev; - OPT_ARGS(opts) = { - OPT_END() - }; - int err = 0; - - err = micron_parse_options(&dev, argc, argv, desc, opts, &model); - if (err < 0) - return err; - - if (model != M51CX) { - printf ("This option is not supported for specified drive\n"); - dev_close(dev); - return err; - } - - err = nvme_set_features_simple(dev_fd(dev), fid, 1 << 31, 0, 0, &result); - if (err == 0) err = (int)result; - else printf ("Failed to clear fw activation history, error = 0x%x\n", err); - - dev_close(dev); - return err; + const char *desc = "Clear FW activation history"; + __u32 result = 0; + __u8 fid = MICRON_FEATURE_CLEAR_FW_ACTIVATION_HISTORY; + enum eDriveModel model = UNKNOWN_MODEL; + struct nvme_dev *dev; + + OPT_ARGS(opts) = { + OPT_END() + }; + int err = 0; + + err = micron_parse_options(&dev, argc, argv, desc, opts, &model); + if (err < 0) + return err; + + if (model != M51CX) { + printf("This option is not supported for specified drive\n"); + dev_close(dev); + return err; + } + + err = nvme_set_features_simple(dev_fd(dev), fid, 1 << 31, 0, 0, &result); + if (!err) + err = (int)result; + else + printf("Failed to clear fw activation history, error = 0x%x\n", err); + + dev_close(dev); + return err; } static int micron_telemetry_cntrl_option(int argc, char **argv, - struct command *cmd, struct plugin *plugin) + struct command *cmd, struct plugin *plugin) { - int err = 0; - __u32 result = 0; - const char *desc = "Enable or Disable Controller telemetry log generation"; - const char *option = "enable or disable or status"; - const char *select = "select/save values: enable/disable options" - "1 - save (persistent), 0 - non-persistent and for " - "status options: 0 - current, 1 - default, 2-saved"; - int fid = MICRON_FEATURE_TELEMETRY_CONTROL_OPTION; - eDriveModel model = UNKNOWN_MODEL; - struct nvme_id_ctrl ctrl = { 0 }; - struct nvme_dev *dev; - - struct { - char *option; - int select; - } opt = { - .option = "disable", - .select= 0, - }; - - OPT_ARGS(opts) = { - OPT_STRING("option", 'o', "option", &opt.option, option), - OPT_UINT("select", 's', &opt.select, select), - OPT_END() - }; - - err = micron_parse_options(&dev, argc, argv, desc, opts, &model); - if (err < 0) - return -1; - - err = nvme_identify_ctrl(dev_fd(dev), &ctrl); - if ((ctrl.lpa & 0x8) != 0x8) { - printf("drive doesn't support host/controller generated telemetry logs\n"); - dev_close(dev); - return err; - } - - if (!strcmp(opt.option, "enable")) { - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = fid, - .nsid = 1, - .cdw11 = 1, - .cdw12 = 0, - .save = (opt.select & 0x1), - .uuidx = 0, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - err = nvme_set_features(&args); - if (err == 0) { - printf("successfully set controller telemetry option\n"); - } else { - printf("Failed to set controller telemetry option\n"); - } - } else if (!strcmp(opt.option, "disable")) { - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = fid, - .nsid = 1, - .cdw11 = 0, - .cdw12 = 0, - .save = (opt.select & 0x1), - .uuidx = 0, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - err = nvme_set_features(&args); - if (err == 0) { - printf("successfully disabled controller telemetry option\n"); - } else { - printf("Failed to disable controller telemetry option\n"); - } - } else if (!strcmp(opt.option, "status")) { - struct nvme_get_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = fid, - .nsid = 1, - .sel = opt.select & 0x3, - .cdw11 = 0, - .uuidx = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, + int err = 0; + __u32 result = 0; + const char *desc = "Enable or Disable Controller telemetry log generation"; + const char *option = "enable or disable or status"; + const char *select = + "select/save values: enable/disable options1 - save (persistent), 0 - non-persistent and for status options: 0 - current, 1 - default, 2-saved"; + int fid = MICRON_FEATURE_TELEMETRY_CONTROL_OPTION; + enum eDriveModel model = UNKNOWN_MODEL; + struct nvme_id_ctrl ctrl = { 0 }; + struct nvme_dev *dev; + + struct { + char *option; + int select; + } opt = { + .option = "disable", + .select = 0, }; - err = nvme_get_features(&args); - if (err == 0) { - printf("Controller telemetry option : %s\n", - (result) ? "enabled" : "disabled"); - } else { - printf("Failed to retrieve controller telemetry option\n"); - } - } else { - printf("invalid option %s, valid values are enable,disable or status\n", opt.option); - dev_close(dev); - return -1; - } - - dev_close(dev); - return err; + + OPT_ARGS(opts) = { + OPT_STRING("option", 'o', "option", &opt.option, option), + OPT_UINT("select", 's', &opt.select, select), + OPT_END() + }; + + err = micron_parse_options(&dev, argc, argv, desc, opts, &model); + if (err < 0) + return -1; + + err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + if ((ctrl.lpa & 0x8) != 0x8) { + printf("drive doesn't support host/controller generated telemetry logs\n"); + dev_close(dev); + return err; + } + + if (!strcmp(opt.option, "enable")) { + struct nvme_set_features_args args = { + .args_size = sizeof(args), + .fd = dev_fd(dev), + .fid = fid, + .nsid = 1, + .cdw11 = 1, + .cdw12 = 0, + .save = (opt.select & 0x1), + .uuidx = 0, + .cdw15 = 0, + .data_len = 0, + .data = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_set_features(&args); + if (!err) + printf("successfully set controller telemetry option\n"); + else + printf("Failed to set controller telemetry option\n"); + } else if (!strcmp(opt.option, "disable")) { + struct nvme_set_features_args args = { + .args_size = sizeof(args), + .fd = dev_fd(dev), + .fid = fid, + .nsid = 1, + .cdw11 = 0, + .cdw12 = 0, + .save = (opt.select & 0x1), + .uuidx = 0, + .cdw15 = 0, + .data_len = 0, + .data = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_set_features(&args); + if (!err) + printf("successfully disabled controller telemetry option\n"); + else + printf("Failed to disable controller telemetry option\n"); + } else if (!strcmp(opt.option, "status")) { + struct nvme_get_features_args args = { + .args_size = sizeof(args), + .fd = dev_fd(dev), + .fid = fid, + .nsid = 1, + .sel = opt.select & 0x3, + .cdw11 = 0, + .uuidx = 0, + .data_len = 0, + .data = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + + err = nvme_get_features(&args); + if (!err) + printf("Controller telemetry option : %s\n", + (result) ? "enabled" : "disabled"); + else + printf("Failed to retrieve controller telemetry option\n"); + } else { + printf("invalid option %s, valid values are enable,disable or status\n", + opt.option); + dev_close(dev); + return -1; + } + + dev_close(dev); + return err; } /* M51XX models log page header */ struct micron_common_log_header { - uint8_t id; - uint8_t version; - uint16_t pn; - uint32_t log_size; - uint32_t max_size; - uint32_t write_pointer; - uint32_t next_pointer; - uint32_t overwritten_bytes; - uint8_t flags; - uint8_t reserved[7]; + uint8_t id; + uint8_t version; + uint16_t pn; + uint32_t log_size; + uint32_t max_size; + uint32_t write_pointer; + uint32_t next_pointer; + uint32_t overwritten_bytes; + uint8_t flags; + uint8_t reserved[7]; }; /* helper function to retrieve logs with specific offset and max chunk size */ int nvme_get_log_lpo(int fd, __u8 log_id, __u32 lpo, __u32 chunk, - __u32 data_len, void *data) + __u32 data_len, void *data) { __u32 offset = lpo, xfer_len = data_len; void *ptr = data; @@ -2933,462 +2920,470 @@ int nvme_get_log_lpo(int fd, __u8 log_id, __u32 lpo, __u32 chunk, /* retrieves logs with common log format */ static int get_common_log(int fd, uint8_t id, uint8_t **buf, int *size) { - struct micron_common_log_header hdr = { 0 }; - int log_size = sizeof(hdr), first = 0, second = 0; - uint8_t *buffer = NULL; - int ret = -1; - int chunk = 0x4000; /* max chunk size to be used for these logs */ - - ret = nvme_get_log_simple(fd, id, sizeof(hdr), &hdr); - if (ret) { - fprintf(stderr, "pull hdr failed for %hhu with error: 0x%x\n", id, ret); - return ret; - } - - if (hdr.id != id || - hdr.log_size == 0 || - hdr.max_size == 0 || - hdr.write_pointer < sizeof(hdr)) - { - fprintf(stderr, "invalid log data for LOG: 0x%X, id: 0x%X, size: %u, " - "max: %u, wp: %u, flags: %hhu, np: %u\n", id, - hdr.id, hdr.log_size, hdr.max_size, hdr.write_pointer, - hdr.flags, hdr.next_pointer); - return 1; - } - - /* we may have just 32-bytes for some models; write to wfile if log hasn't - * yet reached its max size - */ - if (hdr.log_size == sizeof(hdr)) { - buffer = (uint8_t *)malloc(sizeof(hdr)); - if (buffer == NULL) { - fprintf(stderr, "malloc of %zu bytes failed for log: 0x%X\n", - sizeof(hdr), id); - return -ENOMEM; - } - memcpy(buffer,(uint8_t *)&hdr, sizeof(hdr)); - } else if (hdr.log_size < hdr.max_size) { - buffer = (uint8_t *)malloc(sizeof(hdr) + hdr.log_size); - if (buffer == NULL) { - fprintf(stderr, "malloc of %zu bytes failed for log: 0x%X\n", - hdr.log_size + sizeof(hdr), id); - return -ENOMEM; - } - memcpy(buffer, &hdr, sizeof(hdr)); - ret = nvme_get_log_lpo(fd, id, sizeof(hdr), chunk, hdr.log_size, - buffer + sizeof(hdr)); - if (ret == 0) { - log_size += hdr.log_size; - } - } else if (hdr.log_size >= hdr.max_size) { - /* reached maximum, to maintain, sequence we need to depend on write - * pointer to detect wrap-overs. FW doesn't yet implement the condition - * hdr.log_size > hdr.max_size; also ignore over-written log data; we - * also ignore collisions for now - */ - buffer = (uint8_t *)malloc(hdr.max_size + sizeof(hdr)); - if (buffer == NULL) { - fprintf(stderr, "malloc of %zu bytes failed for log: 0x%X\n", - hdr.max_size + sizeof(hdr), id); - return -ENOMEM; - } - memcpy(buffer, &hdr, sizeof(hdr)); - - first = hdr.max_size - hdr.write_pointer; - second = hdr.write_pointer - sizeof(hdr); - - if (first) { - ret = nvme_get_log_lpo(fd, id, hdr.write_pointer, chunk, first, - buffer + sizeof(hdr)); - if (ret) { - free(buffer); - fprintf(stderr, "failed to get log: 0x%X\n", id); - return ret; - } - log_size += first; - } - if (second) { - ret = nvme_get_log_lpo(fd, id, sizeof(hdr), chunk, second, - buffer + sizeof(hdr) + first); - if (ret) { - fprintf(stderr, "failed to get log: 0x%X\n", id); - free(buffer); + struct micron_common_log_header hdr = { 0 }; + int log_size = sizeof(hdr), first = 0, second = 0; + uint8_t *buffer = NULL; + int ret = -1; + int chunk = 0x4000; /* max chunk size to be used for these logs */ + + ret = nvme_get_log_simple(fd, id, sizeof(hdr), &hdr); + if (ret) { + fprintf(stderr, "pull hdr failed for %u with error: 0x%x\n", id, ret); return ret; - } - log_size += second; } - } - *buf = buffer; - *size = log_size; - return ret; + + if (hdr.id != id || !hdr.log_size || !hdr.max_size || + hdr.write_pointer < sizeof(hdr)) { + fprintf(stderr, + "invalid log data for LOG: 0x%X, id: 0x%X, size: %u, max: %u, wp: %u, flags: %u, np: %u\n", + id, hdr.id, hdr.log_size, hdr.max_size, hdr.write_pointer, hdr.flags, + hdr.next_pointer); + return 1; + } + + /* + * we may have just 32-bytes for some models; write to wfile if log hasn't + * yet reached its max size + */ + if (hdr.log_size == sizeof(hdr)) { + buffer = (uint8_t *)malloc(sizeof(hdr)); + if (!buffer) { + fprintf(stderr, "malloc of %zu bytes failed for log: 0x%X\n", + sizeof(hdr), id); + return -ENOMEM; + } + memcpy(buffer, (uint8_t *)&hdr, sizeof(hdr)); + } else if (hdr.log_size < hdr.max_size) { + buffer = (uint8_t *)malloc(sizeof(hdr) + hdr.log_size); + if (!buffer) { + fprintf(stderr, "malloc of %zu bytes failed for log: 0x%X\n", + hdr.log_size + sizeof(hdr), id); + return -ENOMEM; + } + memcpy(buffer, &hdr, sizeof(hdr)); + ret = nvme_get_log_lpo(fd, id, sizeof(hdr), chunk, hdr.log_size, + buffer + sizeof(hdr)); + if (!ret) + log_size += hdr.log_size; + } else if (hdr.log_size >= hdr.max_size) { + /* + * reached maximum, to maintain, sequence we need to depend on write + * pointer to detect wrap-overs. FW doesn't yet implement the condition + * hdr.log_size > hdr.max_size; also ignore over-written log data; we + * also ignore collisions for now + */ + buffer = (uint8_t *)malloc(hdr.max_size + sizeof(hdr)); + if (!buffer) { + fprintf(stderr, "malloc of %zu bytes failed for log: 0x%X\n", + hdr.max_size + sizeof(hdr), id); + return -ENOMEM; + } + memcpy(buffer, &hdr, sizeof(hdr)); + + first = hdr.max_size - hdr.write_pointer; + second = hdr.write_pointer - sizeof(hdr); + + if (first) { + ret = nvme_get_log_lpo(fd, id, hdr.write_pointer, chunk, first, + buffer + sizeof(hdr)); + if (ret) { + free(buffer); + fprintf(stderr, "failed to get log: 0x%X\n", id); + return ret; + } + log_size += first; + } + if (second) { + ret = nvme_get_log_lpo(fd, id, sizeof(hdr), chunk, second, + buffer + sizeof(hdr) + first); + if (ret) { + fprintf(stderr, "failed to get log: 0x%X\n", id); + free(buffer); + return ret; + } + log_size += second; + } + } + *buf = buffer; + *size = log_size; + return ret; } static int micron_internal_logs(int argc, char **argv, struct command *cmd, - struct plugin *plugin) + struct plugin *plugin) { - int err = -EINVAL; - int ctrlIdx, telemetry_option = 0; - char strOSDirName[1024]; - char strCtrlDirName[1024]; - char strMainDirName[256]; - unsigned int *puiIDDBuf; - unsigned int uiMask; - struct nvme_id_ctrl ctrl; - char sn[20] = { 0 }; - char msg[256] = { 0 }; - int c_logs_index = 8; /* should be current size of aVendorLogs */ - struct nvme_dev *dev; - struct { - unsigned char ucLogPage; - const char *strFileName; - int nLogSize; - int nMaxSize; - } aVendorLogs[32] = { - { 0x03, "firmware_slot_info_log.bin", 512, 0 }, - { 0xC1, "nvmelog_C1.bin", 0, 0 }, - { 0xC2, "nvmelog_C2.bin", 0, 0 }, - { 0xC4, "nvmelog_C4.bin", 0, 0 }, - { 0xC5, "nvmelog_C5.bin", C5_log_size, 0 }, - { 0xD0, "nvmelog_D0.bin", D0_log_size, 0 }, - { 0xE6, "nvmelog_E6.bin", 0, 0 }, - { 0xE7, "nvmelog_E7.bin", 0, 0 } - }, - aM51XXLogs[] = { - { 0xFB, "nvmelog_FB.bin", 4096, 0 }, /* this should be collected first for M51AX */ - { 0xD0, "nvmelog_D0.bin", 512, 0 }, - { 0x03, "firmware_slot_info_log.bin", 512, 0}, - { 0xF7, "nvmelog_F7.bin", 4096, 512 * 1024 }, - { 0xF8, "nvmelog_F8.bin", 4096, 512 * 1024 }, - { 0xF9, "nvmelog_F9.bin", 4096, 200 * 1024 * 1024 }, - { 0xFC, "nvmelog_FC.bin", 4096, 200 * 1024 * 1024 }, - { 0xFD, "nvmelog_FD.bin", 4096, 80 * 1024 * 1024 } - }, - aM51AXLogs[] = { - { 0xCA, "nvmelog_CA.bin", 512, 0 }, - { 0xFA, "nvmelog_FA.bin", 4096, 15232 }, - { 0xF6, "nvmelog_F6.bin", 4096, 512 * 1024 }, - { 0xFE, "nvmelog_FE.bin", 4096, 512 * 1024 }, - { 0xFF, "nvmelog_FF.bin", 4096, 162 * 1024 }, - { 0x04, "changed_namespace_log.bin", 4096, 0 }, - { 0x05, "command_effects_log.bin", 4096, 0 }, - { 0x06, "drive_self_test.bin", 4096, 0 } - }, - aM51BXLogs[] = { - { 0xFA, "nvmelog_FA.bin", 4096, 16376 }, - { 0xFE, "nvmelog_FE.bin", 4096, 256 * 1024 }, - { 0xFF, "nvmelog_FF.bin", 4096, 64 * 1024 }, - { 0xCA, "nvmelog_CA.bin", 512, 1024 } - }, - aM51CXLogs[] = { - { 0xE1, "nvmelog_E1.bin", 0, 0 }, - { 0xE2, "nvmelog_E2.bin", 0, 0 }, - { 0xE3, "nvmelog_E3.bin", 0, 0 }, - { 0xE4, "nvmelog_E4.bin", 0, 0 }, - { 0xE5, "nvmelog_E5.bin", 0, 0 }, - { 0xE8, "nvmelog_E8.bin", 0, 0 }, - { 0xE9, "nvmelog_E9.bin", 0, 0 }, - { 0xEA, "nvmelog_EA.bin", 0, 0 }, - }; - - eDriveModel eModel; - - const char *desc = "This retrieves the micron debug log package"; - const char *package = "Log output data file name (required)"; - const char *type = "telemetry log type - host or controller"; - const char *data_area = "telemetry log data area 1, 2 or 3"; - unsigned char *dataBuffer = NULL; - int bSize = 0; - int maxSize = 0; - - struct config { - char *type; - char *package; - int data_area; - int log; - }; - - struct config cfg = { - .type = "", - .package = "", - .data_area = -1, - .log = 0x07, - }; - - OPT_ARGS(opts) = { - OPT_STRING("type", 't', "log type", &cfg.type, type), - OPT_STRING("package", 'p', "FILE", &cfg.package, package), - OPT_UINT("data_area", 'd', &cfg.data_area, data_area), - OPT_END() - }; - - err = parse_and_open(&dev, argc, argv, desc, opts); - if (err) - return err; - - /* if telemetry type is specified, check for data area */ - if (strlen(cfg.type) != 0) { - if (!strcmp(cfg.type, "controller")) { - cfg.log = 0x08; - } else if (strcmp(cfg.type, "host")) { - printf ("telemetry type (host or controller) should be specified i.e. -t=host\n"); - goto out; - } - - if (cfg.data_area <= 0 || cfg.data_area > 3) { - printf ("data area must be selected using -d option ie --d=1,2,3\n"); - goto out; - } - telemetry_option = 1; - } else if (cfg.data_area > 0) { - printf ("data area option is valid only for telemetry option (i.e --type=host|controller)\n"); - goto out; - } - - if (strlen(cfg.package) == 0) { - if (telemetry_option) - printf ("Log data file must be specified. ie -p=logfile.bin\n"); - else - printf ("Log data file must be specified. ie -p=logfile.zip or -p=logfile.tgz|logfile.tar.gz\n"); - goto out; - } - - /* pull log details based on the model name */ - sscanf(argv[optind], "/dev/nvme%d", &ctrlIdx); - if ((eModel = GetDriveModel(ctrlIdx)) == UNKNOWN_MODEL) { - printf ("Unsupported drive model for vs-internal-log collection\n"); - goto out; - } - - err = nvme_identify_ctrl(dev_fd(dev), &ctrl); - if (err) - goto out; - - err = -EINVAL; - if (telemetry_option) { - if ((ctrl.lpa & 0x8) != 0x8) { - printf("telemetry option is not supported for specified drive\n"); - goto out; - } - int logSize = 0; __u8 *buffer = NULL; const char *dir = "."; - err = micron_telemetry_log(dev_fd(dev), cfg.log, &buffer, &logSize, + int err = -EINVAL; + int ctrlIdx, telemetry_option = 0; + char strOSDirName[1024]; + char strCtrlDirName[1024]; + char strMainDirName[256]; + unsigned int *puiIDDBuf; + unsigned int uiMask; + struct nvme_id_ctrl ctrl; + char sn[20] = { 0 }; + char msg[256] = { 0 }; + int c_logs_index = 8; /* should be current size of aVendorLogs */ + struct nvme_dev *dev; + struct { + unsigned char ucLogPage; + const char *strFileName; + int nLogSize; + int nMaxSize; + } aVendorLogs[32] = { + { 0x03, "firmware_slot_info_log.bin", 512, 0 }, + { 0xC1, "nvmelog_C1.bin", 0, 0 }, + { 0xC2, "nvmelog_C2.bin", 0, 0 }, + { 0xC4, "nvmelog_C4.bin", 0, 0 }, + { 0xC5, "nvmelog_C5.bin", C5_log_size, 0 }, + { 0xD0, "nvmelog_D0.bin", D0_log_size, 0 }, + { 0xE6, "nvmelog_E6.bin", 0, 0 }, + { 0xE7, "nvmelog_E7.bin", 0, 0 } + }, + aM51XXLogs[] = { + { 0xFB, "nvmelog_FB.bin", 4096, 0 }, /* this should be collected first for M51AX */ + { 0xD0, "nvmelog_D0.bin", 512, 0 }, + { 0x03, "firmware_slot_info_log.bin", 512, 0}, + { 0xF7, "nvmelog_F7.bin", 4096, 512 * 1024 }, + { 0xF8, "nvmelog_F8.bin", 4096, 512 * 1024 }, + { 0xF9, "nvmelog_F9.bin", 4096, 200 * 1024 * 1024 }, + { 0xFC, "nvmelog_FC.bin", 4096, 200 * 1024 * 1024 }, + { 0xFD, "nvmelog_FD.bin", 4096, 80 * 1024 * 1024 } + }, + aM51AXLogs[] = { + { 0xCA, "nvmelog_CA.bin", 512, 0 }, + { 0xFA, "nvmelog_FA.bin", 4096, 15232 }, + { 0xF6, "nvmelog_F6.bin", 4096, 512 * 1024 }, + { 0xFE, "nvmelog_FE.bin", 4096, 512 * 1024 }, + { 0xFF, "nvmelog_FF.bin", 4096, 162 * 1024 }, + { 0x04, "changed_namespace_log.bin", 4096, 0 }, + { 0x05, "command_effects_log.bin", 4096, 0 }, + { 0x06, "drive_self_test.bin", 4096, 0 } + }, + aM51BXLogs[] = { + { 0xFA, "nvmelog_FA.bin", 4096, 16376 }, + { 0xFE, "nvmelog_FE.bin", 4096, 256 * 1024 }, + { 0xFF, "nvmelog_FF.bin", 4096, 64 * 1024 }, + { 0xCA, "nvmelog_CA.bin", 512, 1024 } + }, + aM51CXLogs[] = { + { 0xE1, "nvmelog_E1.bin", 0, 0 }, + { 0xE2, "nvmelog_E2.bin", 0, 0 }, + { 0xE3, "nvmelog_E3.bin", 0, 0 }, + { 0xE4, "nvmelog_E4.bin", 0, 0 }, + { 0xE5, "nvmelog_E5.bin", 0, 0 }, + { 0xE8, "nvmelog_E8.bin", 0, 0 }, + { 0xE9, "nvmelog_E9.bin", 0, 0 }, + { 0xEA, "nvmelog_EA.bin", 0, 0 }, + }; + + enum eDriveModel eModel; + + const char *desc = "This retrieves the micron debug log package"; + const char *package = "Log output data file name (required)"; + const char *type = "telemetry log type - host or controller"; + const char *data_area = "telemetry log data area 1, 2 or 3"; + unsigned char *dataBuffer = NULL; + int bSize = 0; + int maxSize = 0; + + struct config { + char *type; + char *package; + int data_area; + int log; + }; + + struct config cfg = { + .type = "", + .package = "", + .data_area = -1, + .log = 0x07, + }; + + OPT_ARGS(opts) = { + OPT_STRING("type", 't', "log type", &cfg.type, type), + OPT_STRING("package", 'p', "FILE", &cfg.package, package), + OPT_UINT("data_area", 'd', &cfg.data_area, data_area), + OPT_END() + }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; + + /* if telemetry type is specified, check for data area */ + if (strlen(cfg.type)) { + if (!strcmp(cfg.type, "controller")) { + cfg.log = 0x08; + } else if (strcmp(cfg.type, "host")) { + printf("telemetry type (host or controller) should be specified i.e. -t=host\n"); + goto out; + } + + if (cfg.data_area <= 0 || cfg.data_area > 3) { + printf("data area must be selected using -d option ie --d=1,2,3\n"); + goto out; + } + telemetry_option = 1; + } else if (cfg.data_area > 0) { + printf("data area option is valid only for telemetry option (i.e --type=host|controller)\n"); + goto out; + } + + if (!strlen(cfg.package)) { + if (telemetry_option) + printf("Log data file must be specified. ie -p=logfile.bin\n"); + else + printf("Log data file must be specified. ie -p=logfile.zip or -p=logfile.tgz|logfile.tar.gz\n"); + goto out; + } + + /* pull log details based on the model name */ + if (sscanf(argv[optind], "/dev/nvme%d", &ctrlIdx) != 1) + ctrlIdx = 0; + eModel = GetDriveModel(ctrlIdx); + if (eModel == UNKNOWN_MODEL) { + printf("Unsupported drive model for vs-internal-log collection\n"); + goto out; + } + + err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + if (err) + goto out; + + err = -EINVAL; + if (telemetry_option) { + if ((ctrl.lpa & 0x8) != 0x8) { + printf("telemetry option is not supported for specified drive\n"); + goto out; + } + int logSize = 0; __u8 *buffer = NULL; const char *dir = "."; + + err = micron_telemetry_log(dev_fd(dev), cfg.log, &buffer, &logSize, cfg.data_area); - if (err == 0 && logSize > 0 && buffer != NULL) { - sprintf(msg, "telemetry log: 0x%X", cfg.log); - WriteData(buffer, logSize, dir, cfg.package, msg); - free(buffer); - } - goto out; - } - - printf("Preparing log package. This will take a few seconds...\n"); - - /* trim spaces out of serial number string */ - int i, j = 0; - for (i = 0; i < sizeof(ctrl.sn); i++) { - if (isblank((int)ctrl.sn[i])) - continue; - sn[j++] = ctrl.sn[i]; - } - sn[j] = '\0'; - strcpy(ctrl.sn, sn); - - SetupDebugDataDirectories(ctrl.sn, cfg.package, strMainDirName, strOSDirName, strCtrlDirName); - - GetTimestampInfo(strOSDirName); - GetCtrlIDDInfo(strCtrlDirName, &ctrl); - GetOSConfig(strOSDirName); - GetDriveInfo(strOSDirName, ctrlIdx, &ctrl); - - for (int i = 1; i <= ctrl.nn; i++) - GetNSIDDInfo(dev_fd(dev), strCtrlDirName, i); - - GetSmartlogData(dev_fd(dev), strCtrlDirName); - GetErrorlogData(dev_fd(dev), ctrl.elpe, strCtrlDirName); - GetGenericLogs(dev_fd(dev), strCtrlDirName); - /* pull if telemetry log data is supported */ - if ((ctrl.lpa & 0x8) == 0x8) - GetTelemetryData(dev_fd(dev), strCtrlDirName); - - GetFeatureSettings(dev_fd(dev), strCtrlDirName); - - if (eModel != M5410 && eModel != M5407) { - memcpy(&aVendorLogs[c_logs_index], aM51XXLogs, sizeof(aM51XXLogs)); - c_logs_index += sizeof(aM51XXLogs)/sizeof(aM51XXLogs[0]); - if (eModel == M51AX) - memcpy((char *)&aVendorLogs[c_logs_index], aM51AXLogs, sizeof(aM51AXLogs)); - else if (eModel == M51BX) - memcpy((char *)&aVendorLogs[c_logs_index], aM51BXLogs, sizeof(aM51BXLogs)); - else if (eModel == M51CX) - memcpy((char *)&aVendorLogs[c_logs_index], aM51CXLogs, sizeof(aM51CXLogs)); - } - - for (int i = 0; i < (int)(sizeof(aVendorLogs) / sizeof(aVendorLogs[0])) && - aVendorLogs[i].ucLogPage != 0; i++) { - err = -1; - switch (aVendorLogs[i].ucLogPage) { - case 0xE1: - case 0xE5: - case 0xE9: - err = 1; - break; - - case 0xE2: - case 0xE3: - case 0xE4: - case 0xE8: - case 0xEA: - err = get_common_log(dev_fd(dev), aVendorLogs[i].ucLogPage, + if (!err && logSize > 0 && buffer) { + sprintf(msg, "telemetry log: 0x%X", cfg.log); + WriteData(buffer, logSize, dir, cfg.package, msg); + free(buffer); + } + goto out; + } + + printf("Preparing log package. This will take a few seconds...\n"); + + /* trim spaces out of serial number string */ + int i, j = 0; + + for (i = 0; i < sizeof(ctrl.sn); i++) { + if (isblank((int)ctrl.sn[i])) + continue; + sn[j++] = ctrl.sn[i]; + } + sn[j] = '\0'; + strcpy(ctrl.sn, sn); + + SetupDebugDataDirectories(ctrl.sn, cfg.package, strMainDirName, strOSDirName, strCtrlDirName); + + GetTimestampInfo(strOSDirName); + GetCtrlIDDInfo(strCtrlDirName, &ctrl); + GetOSConfig(strOSDirName); + GetDriveInfo(strOSDirName, ctrlIdx, &ctrl); + + for (int i = 1; i <= ctrl.nn; i++) + GetNSIDDInfo(dev_fd(dev), strCtrlDirName, i); + + GetSmartlogData(dev_fd(dev), strCtrlDirName); + GetErrorlogData(dev_fd(dev), ctrl.elpe, strCtrlDirName); + GetGenericLogs(dev_fd(dev), strCtrlDirName); + /* pull if telemetry log data is supported */ + if ((ctrl.lpa & 0x8) == 0x8) + GetTelemetryData(dev_fd(dev), strCtrlDirName); + + GetFeatureSettings(dev_fd(dev), strCtrlDirName); + + if (eModel != M5410 && eModel != M5407) { + memcpy(&aVendorLogs[c_logs_index], aM51XXLogs, sizeof(aM51XXLogs)); + c_logs_index += ARRAY_SIZE(aM51XXLogs); + if (eModel == M51AX) + memcpy((char *)&aVendorLogs[c_logs_index], aM51AXLogs, sizeof(aM51AXLogs)); + else if (eModel == M51BX) + memcpy((char *)&aVendorLogs[c_logs_index], aM51BXLogs, sizeof(aM51BXLogs)); + else if (eModel == M51CX) + memcpy((char *)&aVendorLogs[c_logs_index], aM51CXLogs, sizeof(aM51CXLogs)); + } + + for (int i = 0; i < (int)(ARRAY_SIZE(aVendorLogs)) && aVendorLogs[i].ucLogPage; i++) { + err = -1; + switch (aVendorLogs[i].ucLogPage) { + case 0xE1: + fallthrough; + case 0xE5: + fallthrough; + case 0xE9: + err = 1; + break; + case 0xE2: + fallthrough; + case 0xE3: + fallthrough; + case 0xE4: + fallthrough; + case 0xE8: + fallthrough; + case 0xEA: + err = get_common_log(dev_fd(dev), aVendorLogs[i].ucLogPage, &dataBuffer, &bSize); - break; - - case 0xC1: - case 0xC2: - case 0xC4: - err = GetLogPageSize(dev_fd(dev), aVendorLogs[i].ucLogPage, - &bSize); - if (err == 0 && bSize > 0) - err = GetCommonLogPage(dev_fd(dev), aVendorLogs[i].ucLogPage, - &dataBuffer, bSize); - break; - - case 0xE6: - case 0xE7: - puiIDDBuf = (unsigned int *)&ctrl; - uiMask = puiIDDBuf[1015]; - if (uiMask == 0 || (aVendorLogs[i].ucLogPage == 0xE6 && uiMask == 2) || - (aVendorLogs[i].ucLogPage == 0xE7 && uiMask == 1)) { - bSize = 0; - } else { - bSize = (int)puiIDDBuf[1023]; - if (bSize % (16 * 1024)) { - bSize += (16 * 1024) - (bSize % (16 * 1024)); - } - } - if (bSize != 0 && (dataBuffer = (unsigned char *)malloc(bSize)) != NULL) { - memset(dataBuffer, 0, bSize); - if (eModel == M5410 || eModel == M5407) - err = NVMEGetLogPage(dev_fd(dev), - aVendorLogs[i].ucLogPage, dataBuffer, - bSize); - else - err = nvme_get_log_simple(dev_fd(dev), - aVendorLogs[i].ucLogPage, - bSize, dataBuffer); - } - break; - - case 0xF7: - case 0xF9: - case 0xFC: - case 0xFD: - if (eModel == M51BX) { - (void)NVMEResetLog(dev_fd(dev), aVendorLogs[i].ucLogPage, - aVendorLogs[i].nLogSize, aVendorLogs[i].nMaxSize); - } - /* fallthrough */ - default: - bSize = aVendorLogs[i].nLogSize; - dataBuffer = (unsigned char *)malloc(bSize); - if (dataBuffer == NULL) { - break; - } - memset(dataBuffer, 0, bSize); - err = nvme_get_log_simple(dev_fd(dev), aVendorLogs[i].ucLogPage, - bSize, dataBuffer); - maxSize = aVendorLogs[i].nMaxSize - bSize; - while (err == 0 && maxSize > 0 && ((unsigned int *)dataBuffer)[0] != 0xdeadbeef) { - sprintf(msg, "log 0x%x", aVendorLogs[i].ucLogPage); - WriteData(dataBuffer, bSize, strCtrlDirName, aVendorLogs[i].strFileName, msg); - err = nvme_get_log_simple(dev_fd(dev), + break; + case 0xC1: + fallthrough; + case 0xC2: + fallthrough; + case 0xC4: + err = GetLogPageSize(dev_fd(dev), aVendorLogs[i].ucLogPage, + &bSize); + if (!err && bSize > 0) + err = GetCommonLogPage(dev_fd(dev), aVendorLogs[i].ucLogPage, + &dataBuffer, bSize); + break; + case 0xE6: + fallthrough; + case 0xE7: + puiIDDBuf = (unsigned int *)&ctrl; + uiMask = puiIDDBuf[1015]; + if (!uiMask || (aVendorLogs[i].ucLogPage == 0xE6 && uiMask == 2) || + (aVendorLogs[i].ucLogPage == 0xE7 && uiMask == 1)) { + bSize = 0; + } else { + bSize = (int)puiIDDBuf[1023]; + if (bSize % (16 * 1024)) + bSize += (16 * 1024) - (bSize % (16 * 1024)); + } + dataBuffer = (unsigned char *)malloc(bSize); + if (bSize && dataBuffer) { + memset(dataBuffer, 0, bSize); + if (eModel == M5410 || eModel == M5407) + err = NVMEGetLogPage(dev_fd(dev), + aVendorLogs[i].ucLogPage, dataBuffer, + bSize); + else + err = nvme_get_log_simple(dev_fd(dev), + aVendorLogs[i].ucLogPage, + bSize, dataBuffer); + } + break; + case 0xF7: + fallthrough; + case 0xF9: + fallthrough; + case 0xFC: + fallthrough; + case 0xFD: + if (eModel == M51BX) + (void)NVMEResetLog(dev_fd(dev), aVendorLogs[i].ucLogPage, + aVendorLogs[i].nLogSize, aVendorLogs[i].nMaxSize); + fallthrough; + default: + bSize = aVendorLogs[i].nLogSize; + dataBuffer = (unsigned char *)malloc(bSize); + if (!dataBuffer) + break; + memset(dataBuffer, 0, bSize); + err = nvme_get_log_simple(dev_fd(dev), aVendorLogs[i].ucLogPage, + bSize, dataBuffer); + maxSize = aVendorLogs[i].nMaxSize - bSize; + while (!err && maxSize > 0 && ((unsigned int *)dataBuffer)[0] != 0xdeadbeef) { + sprintf(msg, "log 0x%x", aVendorLogs[i].ucLogPage); + WriteData(dataBuffer, bSize, strCtrlDirName, aVendorLogs[i].strFileName, msg); + err = nvme_get_log_simple(dev_fd(dev), aVendorLogs[i].ucLogPage, bSize, dataBuffer); - if (err || (((unsigned int *)dataBuffer)[0] == 0xdeadbeef)) - break; - maxSize -= bSize; - } - break; - } - - if (err == 0 && dataBuffer != NULL && ((unsigned int *)dataBuffer)[0] != 0xdeadbeef) { - sprintf(msg, "log 0x%x", aVendorLogs[i].ucLogPage); - WriteData(dataBuffer, bSize, strCtrlDirName, aVendorLogs[i].strFileName, msg); - } - - if (dataBuffer != NULL) { - free(dataBuffer); - dataBuffer = NULL; - } - } - - err = ZipAndRemoveDir(strMainDirName, cfg.package); + if (err || (((unsigned int *)dataBuffer)[0] == 0xdeadbeef)) + break; + maxSize -= bSize; + } + break; + } + + if (!err && dataBuffer && ((unsigned int *)dataBuffer)[0] != 0xdeadbeef) { + sprintf(msg, "log 0x%x", aVendorLogs[i].ucLogPage); + WriteData(dataBuffer, bSize, strCtrlDirName, aVendorLogs[i].strFileName, msg); + } + + if (dataBuffer) { + free(dataBuffer); + dataBuffer = NULL; + } + } + + err = ZipAndRemoveDir(strMainDirName, cfg.package); out: - dev_close(dev); - return err; + dev_close(dev); + return err; } #define MIN_LOG_SIZE 512 static int micron_logpage_dir(int argc, char **argv, struct command *cmd, - struct plugin *plugin) + struct plugin *plugin) { - int err = -1; - const char *desc = "List the supported log pages"; - eDriveModel model = UNKNOWN_MODEL; - char logbuf[MIN_LOG_SIZE]; - struct nvme_dev *dev; - int i; - - OPT_ARGS(opts) = { - OPT_END() - }; - - err = micron_parse_options(&dev, argc, argv, desc, opts, &model); - if (err < 0) - return err; - - struct nvme_supported_logs { - uint8_t log_id; - uint8_t supported; - char *desc; - } log_list[] = { - {0x00, 0, "Support Log Pages"}, - {0x01, 0, "Error Information"}, - {0x02, 0, "SMART / Health Information"}, - {0x03, 0, "Firmware Slot Information"}, - {0x04, 0, "Changed Namespace List"}, - {0x05, 0, "Commands Supported and Effects"}, - {0x06, 0, "Device Self Test"}, - {0x07, 0, "Telemetry Host-Initiated"}, - {0x08, 0, "Telemetry Controller-Initiated"}, - {0x09, 0, "Endurance Group Information"}, - {0x0A, 0, "Predictable Latency Per NVM Set"}, - {0x0B, 0, "Predictable Latency Event Aggregate"}, - {0x0C, 0, "Asymmetric Namespace Access"}, - {0x0D, 0, "Persistent Event Log"}, - {0x0E, 0, "Predictable Latency Event Aggregate"}, - {0x0F, 0, "Endurance Group Event Aggregate"}, - {0x10, 0, "Media Unit Status"}, - {0x11, 0, "Supported Capacity Configuration List"}, - {0x12, 0, "Feature Identifiers Supported and Effects"}, - {0x13, 0, "NVMe-MI Commands Supported and Effects"}, - {0x14, 0, "Command and Feature lockdown"}, - {0x15, 0, "Boot Partition"}, - {0x16, 0, "Rotational Media Information"}, - {0x70, 0, "Discovery"}, - {0x80, 0, "Reservation Notification"}, - {0x81, 0, "Sanitize Status"}, - {0xC0, 0, "SMART Cloud Health Log"}, - {0xC2, 0, "Firmware Activation History"}, - {0xC3, 0, "Latency Monitor Log"}, - }; - - printf("Supported log page list\nLog ID : Description\n"); - for (i = 0; i < sizeof(log_list)/sizeof(log_list[0]); i++) { - err = nvme_get_log_simple(dev_fd(dev), log_list[i].log_id, - MIN_LOG_SIZE, &logbuf[0]); - if (err) continue; - printf("%02Xh : %s\n", log_list[i].log_id, log_list[i].desc); - } - - return err; + int err = -1; + const char *desc = "List the supported log pages"; + enum eDriveModel model = UNKNOWN_MODEL; + char logbuf[MIN_LOG_SIZE]; + struct nvme_dev *dev; + int i; + + OPT_ARGS(opts) = { + OPT_END() + }; + + err = micron_parse_options(&dev, argc, argv, desc, opts, &model); + if (err < 0) + return err; + + struct nvme_supported_logs { + uint8_t log_id; + uint8_t supported; + char *desc; + } log_list[] = { + {0x00, 0, "Support Log Pages"}, + {0x01, 0, "Error Information"}, + {0x02, 0, "SMART / Health Information"}, + {0x03, 0, "Firmware Slot Information"}, + {0x04, 0, "Changed Namespace List"}, + {0x05, 0, "Commands Supported and Effects"}, + {0x06, 0, "Device Self Test"}, + {0x07, 0, "Telemetry Host-Initiated"}, + {0x08, 0, "Telemetry Controller-Initiated"}, + {0x09, 0, "Endurance Group Information"}, + {0x0A, 0, "Predictable Latency Per NVM Set"}, + {0x0B, 0, "Predictable Latency Event Aggregate"}, + {0x0C, 0, "Asymmetric Namespace Access"}, + {0x0D, 0, "Persistent Event Log"}, + {0x0E, 0, "Predictable Latency Event Aggregate"}, + {0x0F, 0, "Endurance Group Event Aggregate"}, + {0x10, 0, "Media Unit Status"}, + {0x11, 0, "Supported Capacity Configuration List"}, + {0x12, 0, "Feature Identifiers Supported and Effects"}, + {0x13, 0, "NVMe-MI Commands Supported and Effects"}, + {0x14, 0, "Command and Feature lockdown"}, + {0x15, 0, "Boot Partition"}, + {0x16, 0, "Rotational Media Information"}, + {0x70, 0, "Discovery"}, + {0x80, 0, "Reservation Notification"}, + {0x81, 0, "Sanitize Status"}, + {0xC0, 0, "SMART Cloud Health Log"}, + {0xC2, 0, "Firmware Activation History"}, + {0xC3, 0, "Latency Monitor Log"}, + }; + + printf("Supported log page list\nLog ID : Description\n"); + for (i = 0; i < ARRAY_SIZE(log_list); i++) { + err = nvme_get_log_simple(dev_fd(dev), log_list[i].log_id, + MIN_LOG_SIZE, &logbuf[0]); + if (err) + continue; + printf("%02Xh : %s\n", log_list[i].log_id, log_list[i].desc); + } + + return err; } diff --git a/plugins/nbft/nbft-plugin.c b/plugins/nbft/nbft-plugin.c new file mode 100644 index 0000000..e8b3fed --- /dev/null +++ b/plugins/nbft/nbft-plugin.c @@ -0,0 +1,563 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <errno.h> +#include <stdio.h> +#include <fnmatch.h> + +#include "nvme-print.h" +#include "nvme.h" +#include "nbft.h" +#include "libnvme.h" +#include "fabrics.h" + +#define CREATE_CMD +#include "nbft-plugin.h" + +static const char dash[100] = {[0 ... 98] = '-', [99] = '\0'}; + +#define PCI_SEGMENT(sbdf) ((sbdf & 0xffff0000) >> 16) +#define PCI_BUS(sbdf) ((sbdf & 0x0000ff00) >> 8) +#define PCI_DEV(sbdf) ((sbdf & 0x000000f8) >> 3) +#define PCI_FUNC(sbdf) ((sbdf & 0x00000007) >> 0) + +static const char *pci_sbdf_to_string(__u16 pci_sbdf) +{ + static char pcidev[13]; + + snprintf(pcidev, sizeof(pcidev), "%x:%x:%x.%x", + PCI_SEGMENT(pci_sbdf), + PCI_BUS(pci_sbdf), + PCI_DEV(pci_sbdf), + PCI_FUNC(pci_sbdf)); + return pcidev; +} + +static char *mac_addr_to_string(unsigned char mac_addr[6]) +{ + static char mac_string[18]; + + snprintf(mac_string, sizeof(mac_string), "%02x:%02x:%02x:%02x:%02x:%02x", + mac_addr[0], + mac_addr[1], + mac_addr[2], + mac_addr[3], + mac_addr[4], + mac_addr[5]); + return mac_string; +} + +static json_object *hfi_to_json(struct nbft_info_hfi *hfi) +{ + struct json_object *hfi_json; + + hfi_json = json_create_object(); + if (!hfi_json) + return NULL; + + if (json_object_add_value_int(hfi_json, "index", hfi->index) + || json_object_add_value_string(hfi_json, "transport", hfi->transport)) + goto fail; + + if (strcmp(hfi->transport, "tcp") == 0) { + if (json_object_add_value_string(hfi_json, "pcidev", + pci_sbdf_to_string(hfi->tcp_info.pci_sbdf)) + || json_object_add_value_string(hfi_json, "mac_addr", + mac_addr_to_string(hfi->tcp_info.mac_addr)) + || json_object_add_value_int(hfi_json, "vlan", + hfi->tcp_info.vlan) + || json_object_add_value_int(hfi_json, "ip_origin", + hfi->tcp_info.ip_origin) + || json_object_add_value_string(hfi_json, "ipaddr", + hfi->tcp_info.ipaddr) + || json_object_add_value_int(hfi_json, "subnet_mask_prefix", + hfi->tcp_info.subnet_mask_prefix) + || json_object_add_value_string(hfi_json, "gateway_ipaddr", + hfi->tcp_info.gateway_ipaddr) + || json_object_add_value_int(hfi_json, "route_metric", + hfi->tcp_info.route_metric) + || json_object_add_value_string(hfi_json, "primary_dns_ipaddr", + hfi->tcp_info.primary_dns_ipaddr) + || json_object_add_value_string(hfi_json, "secondary_dns_ipaddr", + hfi->tcp_info.secondary_dns_ipaddr) + || json_object_add_value_string(hfi_json, "dhcp_server_ipaddr", + hfi->tcp_info.dhcp_server_ipaddr) + || (hfi->tcp_info.host_name + && json_object_add_value_string(hfi_json, "host_name", + hfi->tcp_info.host_name)) + || json_object_add_value_int(hfi_json, "this_hfi_is_default_route", + hfi->tcp_info.this_hfi_is_default_route) + || json_object_add_value_int(hfi_json, "dhcp_override", + hfi->tcp_info.dhcp_override)) + goto fail; + else + return hfi_json; + } +fail: + json_free_object(hfi_json); + return NULL; +} + +static json_object *ssns_to_json(struct nbft_info_subsystem_ns *ss) +{ + struct json_object *ss_json; + struct json_object *hfi_array_json; + char json_str[40]; + char *json_str_p; + int i; + + ss_json = json_create_object(); + if (!ss_json) + return NULL; + + hfi_array_json = json_create_array(); + if (!hfi_array_json) + goto fail; + + for (i = 0; i < ss->num_hfis; i++) + if (json_array_add_value_object(hfi_array_json, + json_object_new_int(ss->hfis[i]->index))) + goto fail; + + if (json_object_add_value_int(ss_json, "index", ss->index) + || json_object_add_value_int(ss_json, "num_hfis", ss->num_hfis) + || json_object_object_add(ss_json, "hfis", hfi_array_json) + || json_object_add_value_string(ss_json, "transport", ss->transport) + || json_object_add_value_string(ss_json, "traddr", ss->traddr) + || json_object_add_value_string(ss_json, "trsvcid", ss->trsvcid) + || json_object_add_value_int(ss_json, "subsys_port_id", ss->subsys_port_id) + || json_object_add_value_int(ss_json, "nsid", ss->nsid)) + goto fail; + + memset(json_str, 0, sizeof(json_str)); + json_str_p = json_str; + + switch (ss->nid_type) { + case NBFT_INFO_NID_TYPE_EUI64: + if (json_object_add_value_string(ss_json, "nid_type", "eui64")) + goto fail; + for (i = 0; i < 8; i++) + json_str_p += sprintf(json_str_p, "%02x", ss->nid[i]); + break; + + case NBFT_INFO_NID_TYPE_NGUID: + if (json_object_add_value_string(ss_json, "nid_type", "nguid")) + goto fail; + for (i = 0; i < 16; i++) + json_str_p += sprintf(json_str_p, "%02x", ss->nid[i]); + break; + + case NBFT_INFO_NID_TYPE_NS_UUID: + if (json_object_add_value_string(ss_json, "nid_type", "uuid")) + goto fail; + nvme_uuid_to_string(ss->nid, json_str); + break; + + default: + break; + } + if (json_object_add_value_string(ss_json, "nid", json_str)) + goto fail; + + if ((ss->subsys_nqn + && json_object_add_value_string(ss_json, "subsys_nqn", ss->subsys_nqn)) + || json_object_add_value_int(ss_json, "controller_id", ss->controller_id) + || json_object_add_value_int(ss_json, "asqsz", ss->asqsz) + || (ss->dhcp_root_path_string + && json_object_add_value_string(ss_json, "dhcp_root_path_string", + ss->dhcp_root_path_string)) + || json_object_add_value_int(ss_json, "pdu_header_digest_required", + ss->pdu_header_digest_required) + || json_object_add_value_int(ss_json, "data_digest_required", + ss->data_digest_required)) + goto fail; + + return ss_json; +fail: + json_free_object(ss_json); + return NULL; +} + +static json_object *discovery_to_json(struct nbft_info_discovery *disc) +{ + struct json_object *disc_json; + + disc_json = json_create_object(); + if (!disc_json) + return NULL; + + if (json_object_add_value_int(disc_json, "index", disc->index) + || (disc->security + && json_object_add_value_int(disc_json, "security", disc->security->index)) + || (disc->hfi + && json_object_add_value_int(disc_json, "hfi", disc->hfi->index)) + || (disc->uri + && json_object_add_value_string(disc_json, "uri", disc->uri)) + || (disc->nqn + && json_object_add_value_string(disc_json, "nqn", disc->nqn))) { + json_free_object(disc_json); + return NULL; + } else + return disc_json; +} + +static const char *primary_admin_host_flag_to_str(unsigned int primary) +{ + static const char * const str[] = { + [NBFT_INFO_PRIMARY_ADMIN_HOST_FLAG_NOT_INDICATED] = "not indicated", + [NBFT_INFO_PRIMARY_ADMIN_HOST_FLAG_UNSELECTED] = "unselected", + [NBFT_INFO_PRIMARY_ADMIN_HOST_FLAG_SELECTED] = "selected", + [NBFT_INFO_PRIMARY_ADMIN_HOST_FLAG_RESERVED] = "reserved", + }; + + if (primary > NBFT_INFO_PRIMARY_ADMIN_HOST_FLAG_RESERVED) + return "INVALID"; + return str[primary]; +} + +static struct json_object *nbft_to_json(struct nbft_info *nbft, bool show_subsys, + bool show_hfi, bool show_discovery) +{ + struct json_object *nbft_json, *host_json; + + nbft_json = json_create_object(); + if (!nbft_json) + return NULL; + + if (json_object_add_value_string(nbft_json, "filename", nbft->filename)) + goto fail; + + host_json = json_create_object(); + if (!host_json) + goto fail; + if ((nbft->host.nqn + && json_object_add_value_string(host_json, "nqn", nbft->host.nqn)) + || (nbft->host.id + && json_object_add_value_string(host_json, "id", + util_uuid_to_string(nbft->host.id)))) + goto fail; + json_object_add_value_int(host_json, "host_id_configured", + nbft->host.host_id_configured); + json_object_add_value_int(host_json, "host_nqn_configured", + nbft->host.host_nqn_configured); + json_object_add_value_string(host_json, "primary_admin_host_flag", + primary_admin_host_flag_to_str(nbft->host.primary)); + if (json_object_object_add(nbft_json, "host", host_json)) { + json_free_object(host_json); + goto fail; + } + + if (show_subsys) { + struct json_object *subsys_array_json, *subsys_json; + struct nbft_info_subsystem_ns **ss; + + subsys_array_json = json_create_array(); + if (!subsys_array_json) + goto fail; + for (ss = nbft->subsystem_ns_list; ss && *ss; ss++) { + subsys_json = ssns_to_json(*ss); + if (!subsys_json) + goto fail; + if (json_object_array_add(subsys_array_json, subsys_json)) { + json_free_object(subsys_json); + goto fail; + } + } + if (json_object_object_add(nbft_json, "subsystem", subsys_array_json)) { + json_free_object(subsys_array_json); + goto fail; + } + } + if (show_hfi) { + struct json_object *hfi_array_json, *hfi_json; + struct nbft_info_hfi **hfi; + + hfi_array_json = json_create_array(); + if (!hfi_array_json) + goto fail; + for (hfi = nbft->hfi_list; hfi && *hfi; hfi++) { + hfi_json = hfi_to_json(*hfi); + if (!hfi_json) + goto fail; + if (json_object_array_add(hfi_array_json, hfi_json)) { + json_free_object(hfi_json); + goto fail; + } + } + if (json_object_object_add(nbft_json, "hfi", hfi_array_json)) { + json_free_object(hfi_array_json); + goto fail; + } + } + if (show_discovery) { + struct json_object *discovery_array_json, *discovery_json; + struct nbft_info_discovery **disc; + + discovery_array_json = json_create_array(); + if (!discovery_array_json) + goto fail; + for (disc = nbft->discovery_list; disc && *disc; disc++) { + discovery_json = discovery_to_json(*disc); + if (!discovery_json) + goto fail; + if (json_object_array_add(discovery_array_json, discovery_json)) { + json_free_object(discovery_json); + goto fail; + } + } + if (json_object_object_add(nbft_json, "discovery", discovery_array_json)) { + json_free_object(discovery_array_json); + goto fail; + } + } + return nbft_json; +fail: + json_free_object(nbft_json); + return NULL; +} + +static int json_show_nbfts(struct list_head *nbft_list, bool show_subsys, + bool show_hfi, bool show_discovery) +{ + struct json_object *nbft_json_array, *nbft_json; + struct nbft_file_entry *entry; + + nbft_json_array = json_create_array(); + if (!nbft_json_array) + return -ENOMEM; + + list_for_each(nbft_list, entry, node) { + nbft_json = nbft_to_json(entry->nbft, show_subsys, show_hfi, show_discovery); + if (!nbft_json) + goto fail; + if (json_object_array_add(nbft_json_array, nbft_json)) { + json_free_object(nbft_json); + goto fail; + } + } + + json_print_object(nbft_json_array, NULL); + printf("\n"); + json_free_object(nbft_json_array); + return 0; +fail: + json_free_object(nbft_json_array); + return -ENOMEM; +} + +static void print_nbft_hfi_info(struct nbft_info *nbft) +{ + struct nbft_info_hfi **hfi; + unsigned int ip_width = 8, gw_width = 8, dns_width = 8; + + hfi = nbft->hfi_list; + if (!hfi || !*hfi) + return; + + for (; *hfi; hfi++) { + unsigned int len; + + len = strlen((*hfi)->tcp_info.ipaddr); + if (len > ip_width) + ip_width = len; + len = strlen((*hfi)->tcp_info.gateway_ipaddr); + if (len > gw_width) + gw_width = len; + len = strlen((*hfi)->tcp_info.primary_dns_ipaddr); + if (len > dns_width) + dns_width = len; + } + + printf("\nNBFT HFIs:\n\n"); + printf("%-3.3s|%-4.4s|%-10.10s|%-17.17s|%-4.4s|%-*.*s|%-4.4s|%-*.*s|%-*.*s\n", + "Idx", "Trsp", "PCI Addr", "MAC Addr", "DHCP", + ip_width, ip_width, "IP Addr", "Mask", + gw_width, gw_width, "Gateway", dns_width, dns_width, "DNS"); + printf("%-.3s+%-.4s+%-.10s+%-.17s+%-.4s+%-.*s+%-.4s+%-.*s+%-.*s\n", + dash, dash, dash, dash, dash, ip_width, dash, dash, + gw_width, dash, dns_width, dash); + for (hfi = nbft->hfi_list; *hfi; hfi++) + printf("%-3d|%-4.4s|%-10.10s|%-17.17s|%-4.4s|%-*.*s|%-4d|%-*.*s|%-*.*s\n", + (*hfi)->index, + (*hfi)->transport, + pci_sbdf_to_string((*hfi)->tcp_info.pci_sbdf), + mac_addr_to_string((*hfi)->tcp_info.mac_addr), + (*hfi)->tcp_info.dhcp_override ? "yes" : "no", + ip_width, ip_width, (*hfi)->tcp_info.ipaddr, + (*hfi)->tcp_info.subnet_mask_prefix, + gw_width, gw_width, (*hfi)->tcp_info.gateway_ipaddr, + dns_width, dns_width, (*hfi)->tcp_info.primary_dns_ipaddr); +} + +static void print_nbft_discovery_info(struct nbft_info *nbft) +{ + struct nbft_info_discovery **disc; + unsigned int nqn_width = 20, uri_width = 12; + + disc = nbft->discovery_list; + if (!disc || !*disc) + return; + + for (; *disc; disc++) { + size_t len; + + len = strlen((*disc)->uri); + if (len > uri_width) + uri_width = len; + len = strlen((*disc)->nqn); + if (len > nqn_width) + nqn_width = len; + } + + printf("\nNBFT Discovery Controllers:\n\n"); + printf("%-3.3s|%-*.*s|%-*.*s\n", "Idx", uri_width, uri_width, "URI", + nqn_width, nqn_width, "NQN"); + printf("%-.3s+%-.*s+%-.*s\n", dash, uri_width, dash, nqn_width, dash); + for (disc = nbft->discovery_list; *disc; disc++) + printf("%-3d|%-*.*s|%-*.*s\n", (*disc)->index, + uri_width, uri_width, (*disc)->uri, + nqn_width, nqn_width, (*disc)->nqn); +} + +#define HFIS_LEN 20 +static size_t print_hfis(const struct nbft_info_subsystem_ns *ss, char buf[HFIS_LEN]) +{ + char hfi_buf[HFIS_LEN]; + size_t len, ofs; + int i; + + len = snprintf(hfi_buf, sizeof(hfi_buf), "%d", ss->hfis[0]->index); + for (i = 1; i < ss->num_hfis; i++) { + ofs = len; + len += snprintf(hfi_buf + ofs, sizeof(hfi_buf) - ofs, ",%d", + ss->hfis[i]->index); + /* + * If the list doesn't fit in HFIS_LEN characters, + * truncate and end with "..." + */ + if (len >= sizeof(hfi_buf)) { + while (ofs < sizeof(hfi_buf) - 1) + hfi_buf[ofs++] = '.'; + hfi_buf[ofs] = '\0'; + len = sizeof(hfi_buf) - 1; + break; + } + } + if (buf) + memcpy(buf, hfi_buf, len + 1); + return len; +} + + +static void print_nbft_subsys_info(struct nbft_info *nbft) +{ + struct nbft_info_subsystem_ns **ss; + unsigned int nqn_width = 20, adr_width = 8, hfi_width = 4; + + ss = nbft->subsystem_ns_list; + if (!ss || !*ss) + return; + for (; *ss; ss++) { + size_t len; + + len = strlen((*ss)->subsys_nqn); + if (len > nqn_width) + nqn_width = len; + len = strlen((*ss)->traddr); + if (len > adr_width) + adr_width = len; + len = print_hfis(*ss, NULL); + if (len > hfi_width) + hfi_width = len; + } + + printf("\nNBFT Subsystems:\n\n"); + printf("%-3.3s|%-*.*s|%-4.4s|%-*.*s|%-5.5s|%-*.*s\n", + "Idx", nqn_width, nqn_width, "NQN", + "Trsp", adr_width, adr_width, "Address", "SvcId", hfi_width, hfi_width, "HFIs"); + printf("%-.3s+%-.*s+%-.4s+%-.*s+%-.5s+%-.*s\n", + dash, nqn_width, dash, dash, adr_width, dash, dash, hfi_width, dash); + for (ss = nbft->subsystem_ns_list; *ss; ss++) { + char hfi_buf[HFIS_LEN]; + + print_hfis(*ss, hfi_buf); + printf("%-3d|%-*.*s|%-4.4s|%-*.*s|%-5.5s|%-*.*s\n", + (*ss)->index, nqn_width, nqn_width, (*ss)->subsys_nqn, + (*ss)->transport, adr_width, adr_width, (*ss)->traddr, + (*ss)->trsvcid, hfi_width, hfi_width, hfi_buf); + } +} + +static void normal_show_nbft(struct nbft_info *nbft, bool show_subsys, + bool show_hfi, bool show_discovery) +{ + printf("%s:\n", nbft->filename); + if ((!nbft->hfi_list || !*nbft->hfi_list) && + (!nbft->security_list || !*nbft->security_list) && + (!nbft->discovery_list || !*nbft->discovery_list) && + (!nbft->subsystem_ns_list || !*nbft->subsystem_ns_list)) + printf("(empty)\n"); + else { + if (show_subsys) + print_nbft_subsys_info(nbft); + if (show_hfi) + print_nbft_hfi_info(nbft); + if (show_discovery) + print_nbft_discovery_info(nbft); + } +} + +static void normal_show_nbfts(struct list_head *nbft_list, bool show_subsys, + bool show_hfi, bool show_discovery) +{ + bool not_first = false; + struct nbft_file_entry *entry; + + list_for_each(nbft_list, entry, node) { + if (not_first) + printf("\n"); + normal_show_nbft(entry->nbft, show_subsys, show_hfi, show_discovery); + not_first = true; + } +} + +int show_nbft(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + const char *desc = "Display contents of the ACPI NBFT files."; + struct list_head nbft_list; + char *format = "normal"; + char *nbft_path = NBFT_SYSFS_PATH; + enum nvme_print_flags flags; + int ret; + bool show_subsys = false, show_hfi = false, show_discovery = false; + + OPT_ARGS(opts) = { + OPT_FMT("output-format", 'o', &format, "Output format: normal|json"), + OPT_FLAG("subsystem", 's', &show_subsys, "show NBFT subsystems"), + OPT_FLAG("hfi", 'H', &show_hfi, "show NBFT HFIs"), + OPT_FLAG("discovery", 'd', &show_discovery, "show NBFT discovery controllers"), + OPT_STRING("nbft-path", 0, "STR", &nbft_path, "user-defined path for NBFT tables"), + OPT_END() + }; + + ret = argconfig_parse(argc, argv, desc, opts); + if (ret) + return ret; + + ret = flags = validate_output_format(format); + if (ret < 0) + return ret; + + if (!(show_subsys || show_hfi || show_discovery)) + show_subsys = show_hfi = show_discovery = true; + + list_head_init(&nbft_list); + ret = read_nbft_files(&nbft_list, nbft_path); + if (!ret) { + if (flags == NORMAL) + normal_show_nbfts(&nbft_list, show_subsys, show_hfi, show_discovery); + else if (flags == JSON) + ret = json_show_nbfts(&nbft_list, show_subsys, show_hfi, show_discovery); + free_nbfts(&nbft_list); + } + return ret; +} diff --git a/plugins/nbft/nbft-plugin.h b/plugins/nbft/nbft-plugin.h new file mode 100644 index 0000000..018349d --- /dev/null +++ b/plugins/nbft/nbft-plugin.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#undef CMD_INC_FILE +#define CMD_INC_FILE plugins/nbft/nbft-plugin + +#if !defined(NBFT) || defined(CMD_HEADER_MULTI_READ) +#define NBFT + +#include "cmd.h" + +PLUGIN(NAME("nbft", "ACPI NBFT table extensions", NVME_VERSION), + COMMAND_LIST( + ENTRY("show", "Show contents of ACPI NBFT tables", show_nbft) + ) +); + +#endif + +#include "define_cmd.h" diff --git a/plugins/netapp/netapp-nvme.c b/plugins/netapp/netapp-nvme.c index f5cb073..2ecdcc5 100644 --- a/plugins/netapp/netapp-nvme.c +++ b/plugins/netapp/netapp-nvme.c @@ -1,18 +1,18 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* -* Copyright (c) 2018 NetApp, Inc. -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* as published by the Free Software Foundation; either version 2 -* of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -*/ + * Copyright (c) 2018 NetApp, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ #include <stdio.h> #include <dirent.h> @@ -57,14 +57,14 @@ enum { static const char *dev_path = "/dev/"; struct smdevice_info { - unsigned nsid; + unsigned int nsid; struct nvme_id_ctrl ctrl; struct nvme_id_ns ns; char dev[265]; }; struct ontapdevice_info { - unsigned nsid; + unsigned int nsid; struct nvme_id_ctrl ctrl; struct nvme_id_ns ns; unsigned char uuid[NVME_UUID_LEN]; @@ -107,6 +107,7 @@ static void netapp_get_ns_size(char *size, unsigned long long *lba, struct nvme_id_ns *ns) { __u8 lba_index; + nvme_id_ns_flbas_to_lbaf_inuse(ns->flbas, &lba_index); *lba = 1ULL << ns->lbaf[lba_index].ds; double nsze = le64_to_cpu(ns->nsze) * (*lba); @@ -237,8 +238,8 @@ static void netapp_smdevices_print(struct smdevice_info *devices, int count, int char array_label[ARRAY_LABEL_LEN / 2 + 1]; char volume_label[VOLUME_LABEL_LEN / 2 + 1]; char nguid_str[33]; - char basestr[] = "%s, Array Name %s, Volume Name %s, NSID %d, " - "Volume ID %s, Controller %c, Access State %s, %s\n"; + char basestr[] = + "%s, Array Name %s, Volume Name %s, NSID %d, Volume ID %s, Controller %c, Access State %s, %s\n"; char columnstr[] = "%-16s %-30s %-30s %4d %32s %c %-12s %9s\n"; char *formatstr = basestr; /* default to "normal" output format */ __u8 lba_index; @@ -254,8 +255,7 @@ static void netapp_smdevices_print(struct smdevice_info *devices, int count, int "------------------------------", "----", "--------------------------------", "----", "------------", "---------"); - } - else if (format == NJSON) { + } else if (format == NJSON) { /* prepare for json output */ root = json_create_object(); json_devices = json_create_array(); @@ -263,7 +263,7 @@ static void netapp_smdevices_print(struct smdevice_info *devices, int count, int for (i = 0; i < count; i++) { nvme_id_ns_flbas_to_lbaf_inuse(devices[i].ns.flbas, &lba_index); - unsigned long long int lba = 1ULL << devices[i].ns.lbaf[lba_index].ds; + unsigned long long lba = 1ULL << devices[i].ns.lbaf[lba_index].ds; double nsze = le64_to_cpu(devices[i].ns.nsze) * lba; const char *s_suffix = suffix_si_get(&nsze); char size[128]; @@ -464,7 +464,7 @@ static int netapp_ontapdevices_get_info(int fd, struct ontapdevice_info *item, err = nvme_get_ontap_c2_log(fd, item->nsid, item->log_data, ONTAP_C2_LOG_SIZE); if (err) { fprintf(stderr, "Unable to get log page data for %s (%s)\n", - dev, err < 0 ? strerror(-err): + dev, err < 0 ? strerror(-err) : nvme_status_to_string(err, false)); return 0; } @@ -553,7 +553,7 @@ static int netapp_smdevices(int argc, char **argv, struct command *command, smdevices = calloc(num, sizeof(*smdevices)); if (!smdevices) { fprintf(stderr, "Unable to allocate memory for devices.\n"); - return ENOMEM; + return -ENOMEM; } for (i = 0; i < num; i++) { diff --git a/plugins/ocp/meson.build b/plugins/ocp/meson.build index 641239a..405ee51 100644 --- a/plugins/ocp/meson.build +++ b/plugins/ocp/meson.build @@ -3,5 +3,6 @@ sources += [ 'plugins/ocp/ocp-nvme.c', 'plugins/ocp/ocp-clear-fw-update-history.c', 'plugins/ocp/ocp-smart-extended-log.c', + 'plugins/ocp/ocp-fw-activation-history.c', ] diff --git a/plugins/ocp/ocp-clear-fw-update-history.c b/plugins/ocp/ocp-clear-fw-update-history.c index b9235b8..6b256b1 100644 --- a/plugins/ocp/ocp-clear-fw-update-history.c +++ b/plugins/ocp/ocp-clear-fw-update-history.c @@ -16,6 +16,5 @@ int ocp_clear_fw_update_history(int argc, char **argv, struct command *cmd, stru { const char *desc = "OCP Clear Firmware Update History"; - return ocp_clear_feature(argc, argv, desc, - OCP_FID_CLEAR_FW_ACTIVATION_HISTORY); + return ocp_clear_feature(argc, argv, desc, OCP_FID_CLEAR_FW_ACTIVATION_HISTORY); } diff --git a/plugins/ocp/ocp-fw-activation-history.c b/plugins/ocp/ocp-fw-activation-history.c new file mode 100644 index 0000000..b067346 --- /dev/null +++ b/plugins/ocp/ocp-fw-activation-history.c @@ -0,0 +1,223 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022 Solidigm. + * + * Author: karl.dedow@solidigm.com + */ + +#include "ocp-fw-activation-history.h" + +#include <errno.h> +#include <stdio.h> + +#include "common.h" +#include "nvme-print.h" + +#include "ocp-utils.h" + +static const unsigned char ocp_fw_activation_history_guid[16] = { + 0x6D, 0x79, 0x9a, 0x76, + 0xb4, 0xda, 0xf6, 0xa3, + 0xe2, 0x4d, 0xb2, 0x8a, + 0xac, 0xf3, 0x1c, 0xd1 +}; + +struct __packed fw_activation_history_entry { + __u8 ver_num; + __u8 entry_length; + __u16 reserved1; + __u16 activation_count; + __u64 timestamp; + __u64 reserved2; + __u64 power_cycle_count; + char previous_fw[8]; + char new_fw[8]; + __u8 slot_number; + __u8 commit_action; + __u16 result; + __u8 reserved3[14]; +}; + +struct __packed fw_activation_history { + __u8 log_id; + __u8 reserved1[3]; + __u32 valid_entries; + struct fw_activation_history_entry entries[20]; + __u8 reserved2[2790]; + __u16 log_page_version; + __u64 log_page_guid[2]; +}; + +static void ocp_fw_activation_history_normal(const struct fw_activation_history *fw_history) +{ + printf("Firmware History Log:\n"); + + printf(" %-26s%d\n", "log identifier:", fw_history->log_id); + printf(" %-26s%d\n", "valid entries:", le32_to_cpu(fw_history->valid_entries)); + + printf(" entries:\n"); + + for (int index = 0; index < fw_history->valid_entries; index++) { + const struct fw_activation_history_entry *entry = &fw_history->entries[index]; + + printf(" entry[%d]:\n", le32_to_cpu(index)); + printf(" %-22s%d\n", "version number:", entry->ver_num); + printf(" %-22s%d\n", "entry length:", entry->entry_length); + printf(" %-22s%d\n", "activation count:", + le16_to_cpu(entry->activation_count)); + printf(" %-22s%"PRIu64"\n", "timestamp:", + le64_to_cpu(entry->timestamp)); + printf(" %-22s%"PRIu64"\n", "power cycle count:", + le64_to_cpu(entry->power_cycle_count)); + printf(" %-22s%.*s\n", "previous firmware:", (int)sizeof(entry->previous_fw), + entry->previous_fw); + printf(" %-22s%.*s\n", "new firmware:", (int)sizeof(entry->new_fw), + entry->new_fw); + printf(" %-22s%d\n", "slot number:", entry->slot_number); + printf(" %-22s%d\n", "commit action type:", entry->commit_action); + printf(" %-22s%d\n", "result:", le16_to_cpu(entry->result)); + } + + printf(" %-26s%d\n", "log page version:", + le16_to_cpu(fw_history->log_page_version)); + + printf(" %-26s0x%"PRIx64"%"PRIx64"\n", "log page guid:", + le64_to_cpu(fw_history->log_page_guid[1]), + le64_to_cpu(fw_history->log_page_guid[0])); + + printf("\n"); +} + +static void ocp_fw_activation_history_json(const struct fw_activation_history *fw_history) +{ + struct json_object *root = json_create_object(); + + json_object_add_value_uint(root, "log identifier", fw_history->log_id); + json_object_add_value_uint(root, "valid entries", le32_to_cpu(fw_history->valid_entries)); + + struct json_object *entries = json_create_array(); + + for (int index = 0; index < fw_history->valid_entries; index++) { + const struct fw_activation_history_entry *entry = &fw_history->entries[index]; + struct json_object *entry_obj = json_create_object(); + + json_object_add_value_uint(entry_obj, "version number", entry->ver_num); + json_object_add_value_uint(entry_obj, "entry length", entry->entry_length); + json_object_add_value_uint(entry_obj, "activation count", + le16_to_cpu(entry->activation_count)); + json_object_add_value_uint64(entry_obj, "timestamp", + le64_to_cpu(entry->timestamp)); + json_object_add_value_uint(entry_obj, "power cycle count", + le64_to_cpu(entry->power_cycle_count)); + + struct json_object *fw = json_object_new_string_len(entry->previous_fw, + sizeof(entry->previous_fw)); + + json_object_add_value_object(entry_obj, "previous firmware", fw); + + fw = json_object_new_string_len(entry->new_fw, sizeof(entry->new_fw)); + + json_object_add_value_object(entry_obj, "new firmware", fw); + json_object_add_value_uint(entry_obj, "slot number", entry->slot_number); + json_object_add_value_uint(entry_obj, "commit action type", entry->commit_action); + json_object_add_value_uint(entry_obj, "result", le16_to_cpu(entry->result)); + + json_array_add_value_object(entries, entry_obj); + } + + json_object_add_value_array(root, "entries", entries); + + json_object_add_value_uint(root, "log page version", + le16_to_cpu(fw_history->log_page_version)); + + char guid[2 * sizeof(fw_history->log_page_guid) + 3] = { 0 }; + + sprintf(guid, "0x%"PRIx64"%"PRIx64"", + le64_to_cpu(fw_history->log_page_guid[1]), + le64_to_cpu(fw_history->log_page_guid[0])); + json_object_add_value_string(root, "log page guid", guid); + + json_print_object(root, NULL); + json_free_object(root); + + printf("\n"); +} + +int ocp_fw_activation_history_log(int argc, char **argv, struct command *cmd, + struct plugin *plugin) +{ + const __u8 log_id = 0xC2; + const char *description = "Retrieves the OCP firmware activation history log."; + + char *format = "normal"; + + OPT_ARGS(options) = { + OPT_FMT("output-format", 'o', &format, "output format : normal | json"), + OPT_END() + }; + + struct nvme_dev *dev = NULL; + int err = parse_and_open(&dev, argc, argv, description, options); + + if (err) + return err; + + int uuid_index = 0; + + /* + * Best effort attempt at uuid. Otherwise, assume no index (i.e. 0) + * Log GUID check will ensure correctness of returned data + */ + ocp_get_uuid_index(dev, &uuid_index); + + struct fw_activation_history fw_history = { 0 }; + + struct nvme_get_log_args args = { + .lpo = 0, + .result = NULL, + .log = &fw_history, + .args_size = sizeof(args), + .fd = dev_fd(dev), + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .lid = log_id, + .len = sizeof(fw_history), + .nsid = NVME_NSID_ALL, + .csi = NVME_CSI_NVM, + .lsi = NVME_LOG_LSI_NONE, + .lsp = 0, + .uuidx = uuid_index, + .rae = false, + .ot = false, + }; + + err = nvme_get_log(&args); + + if (err) + nvme_show_status(err); + + dev_close(dev); + + int guid_cmp_res = memcmp(fw_history.log_page_guid, ocp_fw_activation_history_guid, + sizeof(ocp_fw_activation_history_guid)); + + if (!err && guid_cmp_res) { + fprintf(stderr, + "Error: Unexpected data. Log page guid does not match with expected.\n"); + err = -EINVAL; + } + + if (!err) { + const enum nvme_print_flags print_flag = validate_output_format(format); + + if (print_flag == JSON) + ocp_fw_activation_history_json(&fw_history); + else if (print_flag == NORMAL) + ocp_fw_activation_history_normal(&fw_history); + else { + fprintf(stderr, "Error: Invalid output format.\n"); + err = -EINVAL; + } + } + + return err; +} diff --git a/plugins/ocp/ocp-fw-activation-history.h b/plugins/ocp/ocp-fw-activation-history.h new file mode 100644 index 0000000..a7f9058 --- /dev/null +++ b/plugins/ocp/ocp-fw-activation-history.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (c) 2022 Solidigm. + * + * Authors: karl.dedow@solidigm.com + */ + +#ifndef OCP_FIRMWARE_ACTIVATION_HISTORY_H +#define OCP_FIRMWARE_ACTIVATION_HISTORY_H + +struct command; +struct plugin; + +int ocp_fw_activation_history_log(int argc, char **argv, + struct command *cmd, struct plugin *plugin); + +#endif diff --git a/plugins/ocp/ocp-nvme.c b/plugins/ocp/ocp-nvme.c index a864363..edf75fc 100644 --- a/plugins/ocp/ocp-nvme.c +++ b/plugins/ocp/ocp-nvme.c @@ -1,9 +1,10 @@ // SPDX-License-Identifier: GPL-2.0-or-later -/* Copyright (c) 2022 Meta Platforms, Inc. +/* + * Copyright (c) 2023 Meta Platforms, Inc. * - * Authors: Arthur Shau <arthurshau@fb.com>, - * Wei Zhang <wzhang@fb.com>, - * Venkat Ramesh <venkatraghavan@fb.com> + * Authors: Arthur Shau <arthurshau@meta.com>, + * Wei Zhang <wzhang@meta.com>, + * Venkat Ramesh <venkatraghavan@meta.com> */ #include <stdio.h> #include <string.h> @@ -25,20 +26,29 @@ #include "ocp-smart-extended-log.h" #include "ocp-clear-fw-update-history.h" +#include "ocp-fw-activation-history.h" #define CREATE_CMD #include "ocp-nvme.h" #include "ocp-utils.h" -#define C0_ACTIVE_BUCKET_TIMER_INCREMENT 5 -#define C0_ACTIVE_THRESHOLD_INCREMENT 5 -#define C0_MINIMUM_WINDOW_INCREMENT 100 +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/// Latency Monitor Log -/* 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 +#define NVME_FEAT_OCP_LATENCY_MONITOR 0xC5 + +#define C3_ACTIVE_BUCKET_TIMER_INCREMENT 5 +#define C3_ACTIVE_THRESHOLD_INCREMENT 5 +#define C3_MINIMUM_WINDOW_INCREMENT 100 +#define C3_BUCKET_NUM 4 + static __u8 lat_mon_guid[C3_GUID_LENGTH] = { 0x92, 0x7a, 0xc0, 0x8c, 0xd0, 0x84, 0x6c, 0x9c, @@ -46,12 +56,12 @@ static __u8 lat_mon_guid[C3_GUID_LENGTH] = { 0x58, 0x5e, 0xd4, 0x85 }; -#define READ 0 -#define WRITE 1 -#define TRIM 2 -#define RESERVED 3 +#define READ 3 +#define WRITE 2 +#define TRIM 1 +#define RESERVED 0 -struct __attribute__((__packed__)) ssd_latency_monitor_log { +struct __packed ssd_latency_monitor_log { __u8 feature_status; /* 0x00 */ __u8 rsvd1; /* 0x01 */ __le16 active_bucket_timer; /* 0x02 */ @@ -88,24 +98,19 @@ struct __attribute__((__packed__)) ssd_latency_monitor_log { __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]; - - time_Human = time/1000; - time_ms = time % 1000; - - gmtime_r((const time_t *)&time_Human, &gmTimeInfo); - - strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &gmTimeInfo); - sprintf(ts_buf, "%s.%03ld GMT", buf, time_ms); - - return 0; -} +struct __packed feature_latency_monitor { + __u16 active_bucket_timer_threshold; + __u8 active_threshold_a; + __u8 active_threshold_b; + __u8 active_threshold_c; + __u8 active_threshold_d; + __u16 active_latency_config; + __u8 active_latency_minimum_window; + __u16 debug_log_trigger_enable; + __u8 discard_debug_log; + __u8 latency_monitor_feature_enable; + __u8 reserved[4083]; +}; static int ocp_print_C3_log_normal(struct nvme_dev *dev, struct ssd_latency_monitor_log *log_data) @@ -119,25 +124,25 @@ static int ocp_print_C3_log_normal(struct nvme_dev *dev, printf(" Feature Status 0x%x\n", log_data->feature_status); printf(" Active Bucket Timer %d min\n", - C0_ACTIVE_BUCKET_TIMER_INCREMENT * + C3_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 * + C3_ACTIVE_BUCKET_TIMER_INCREMENT * le16_to_cpu(log_data->active_bucket_timer_threshold)); printf(" Active Threshold A %d ms\n", - C0_ACTIVE_THRESHOLD_INCREMENT * + C3_ACTIVE_THRESHOLD_INCREMENT * le16_to_cpu(log_data->active_threshold_a+1)); printf(" Active Threshold B %d ms\n", - C0_ACTIVE_THRESHOLD_INCREMENT * + C3_ACTIVE_THRESHOLD_INCREMENT * le16_to_cpu(log_data->active_threshold_b+1)); printf(" Active Threshold C %d ms\n", - C0_ACTIVE_THRESHOLD_INCREMENT * + C3_ACTIVE_THRESHOLD_INCREMENT * le16_to_cpu(log_data->active_threshold_c+1)); printf(" Active Threshold D %d ms\n", - C0_ACTIVE_THRESHOLD_INCREMENT * + C3_ACTIVE_THRESHOLD_INCREMENT * le16_to_cpu(log_data->active_threshold_d+1)); printf(" Active Latency Minimum Window %d ms\n", - C0_MINIMUM_WINDOW_INCREMENT * + C3_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)); @@ -145,39 +150,55 @@ static int ocp_print_C3_log_normal(struct nvme_dev *dev, 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(" Debug Log Measured Latency %d\n", + le16_to_cpu(log_data->debug_log_measured_latency)); + if (le64_to_cpu(log_data->debug_log_latency_stamp) == -1) { + printf(" Debug Log Latency Time Stamp N/A\n"); + } else { + convert_ts(le64_to_cpu(log_data->debug_log_latency_stamp), ts_buf); + printf(" Debug Log Latency Time Stamp %s\n", ts_buf); + } + printf(" Debug Log Pointer %d\n", + le16_to_cpu(log_data->debug_log_ptr)); + printf(" Debug Counter Trigger Source %d\n", + le16_to_cpu(log_data->debug_log_counter_trigger)); + printf(" Debug Log Stamp Units %d\n", + le16_to_cpu(log_data->debug_log_stamp_units)); + printf(" Log Page Version %d\n", + le16_to_cpu(log_data->log_page_version)); + + char guid[(C3_GUID_LENGTH * 2) + 1]; + char *ptr = &guid[0]; + + for (i = C3_GUID_LENGTH - 1; i >= 0; i--) + ptr += sprintf(ptr, "%02X", log_data->log_page_guid[i]); + + printf(" Log Page GUID %s\n", guid); + printf("\n"); - printf(" Read Write Deallocate/Trim \n"); - for (i = 0; i <= 3; i++) { + printf(" Read Write Deallocate/Trim\n"); + for (i = 0; i < C3_BUCKET_NUM; 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", + for (i = 0; i < C3_BUCKET_NUM; 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++) { + for (i = 0; i < C3_BUCKET_NUM; 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) + for (j = 2; j >= 0; j--) { + if (le64_to_cpu(log_data->active_latency_timestamp[i][j]) == -1) { printf(" N/A "); - else { + } else { convert_ts(le64_to_cpu(log_data->active_latency_timestamp[i][j]), ts_buf); printf("%s ", ts_buf); } @@ -185,7 +206,16 @@ static int ocp_print_C3_log_normal(struct nvme_dev *dev, printf("\n"); } - for (i = 0; i <= 3; i++) { + for (i = 0; i < C3_BUCKET_NUM; 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-1]), + le16_to_cpu(log_data->active_measured_latency[i][WRITE-1]), + le16_to_cpu(log_data->active_measured_latency[i][TRIM-1])); + } + + printf("\n"); + for (i = 0; i < C3_BUCKET_NUM; i++) { printf(" Static Bucket Counter: Bucket %d %27d %27d %27d\n", i, le32_to_cpu(log_data->static_bucket_counter[i][READ]), @@ -193,20 +223,12 @@ static int ocp_print_C3_log_normal(struct nvme_dev *dev, 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++) { + for (i = 0; i < C3_BUCKET_NUM; 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) + for (j = 2; j >= 0; j--) { + if (le64_to_cpu(log_data->static_latency_timestamp[i][j]) == -1) { printf(" N/A "); - else { + } else { convert_ts(le64_to_cpu(log_data->static_latency_timestamp[i][j]), ts_buf); printf("%s ", ts_buf); } @@ -214,6 +236,14 @@ static int ocp_print_C3_log_normal(struct nvme_dev *dev, printf("\n"); } + for (i = 0; i < C3_BUCKET_NUM; 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-1]), + le16_to_cpu(log_data->static_measured_latency[i][WRITE-1]), + le16_to_cpu(log_data->static_measured_latency[i][TRIM-1])); + } + return 0; } @@ -224,85 +254,68 @@ static void ocp_print_C3_log_json(struct ssd_latency_monitor_log *log_data) char buf[128]; int i, j; int pos = 0; - char *operation[3] = {"Read", "Write", "Trim"}; + char *operation[3] = {"Trim", "Write", "Read"}; 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 * + C3_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 * + C3_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 * + C3_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 * + C3_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 * + C3_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 * + C3_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++) { + for (i = 0; i < C3_BUCKET_NUM; i++) { struct json_object *bucket; bucket = json_create_object(); sprintf(buf, "Active Latency Mode: Bucket %d", i); - for (j = 0; j <= 2; j++) { + for (j = 2; j >= 0; 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); - } + json_object_add_value_uint(root, "Active Latency Minimum Window", + C3_MINIMUM_WINDOW_INCREMENT * + le16_to_cpu(log_data->active_latency_min_window)); - for (i = 0; i <= 3; i++) { + for (i = 0; i < C3_BUCKET_NUM; i++) { struct json_object *bucket; bucket = json_create_object(); - sprintf(buf, "Active Measured Latency: Bucket %d", i); - for (j = 0; j <= 2; j++) { + sprintf(buf, "Active Bucket Counter: Bucket %d", i); + for (j = 2; j >= 0; j--) { json_object_add_value_uint(bucket, operation[j], - le16_to_cpu(log_data->active_measured_latency[i][j])); + le32_to_cpu(log_data->active_bucket_counter[i][j+1])); } json_object_add_value_object(root, buf, bucket); } - for (i = 0; i <= 3; i++) { + for (i = 0; i < C3_BUCKET_NUM; 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) + for (j = 2; j >= 0; j--) { + if (le64_to_cpu(log_data->active_latency_timestamp[i][j]) == -1) { json_object_add_value_string(bucket, operation[j], "NA"); - else { + } 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); } @@ -310,39 +323,42 @@ static void ocp_print_C3_log_json(struct ssd_latency_monitor_log *log_data) json_object_add_value_object(root, buf, bucket); } - for (i = 0; i <= 3; i++) { + for (i = 0; i < C3_BUCKET_NUM; i++) { struct json_object *bucket; bucket = json_create_object(); - sprintf(buf, "Static Bucket Counter: Bucket %d", i); - for (j = 0; j <= 2; j++) { + sprintf(buf, "Active Measured Latency: Bucket %d", i); + for (j = 2; j >= 0; j--) { json_object_add_value_uint(bucket, operation[j], - le32_to_cpu(log_data->static_bucket_counter[i][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++) { + json_object_add_value_uint(root, "Active Latency Stamp Units", + le16_to_cpu(log_data->active_latency_stamp_units)); + + for (i = 0; i < C3_BUCKET_NUM; i++) { struct json_object *bucket; bucket = json_create_object(); - sprintf(buf, "Static Measured Latency: Bucket %d", i); - for (j = 0; j <= 2; j++) { + sprintf(buf, "Static Bucket Counter: Bucket %d", i); + for (j = 2; j >= 0; j--) { json_object_add_value_uint(bucket, operation[j], - le16_to_cpu(log_data->static_measured_latency[i][j])); + le32_to_cpu(log_data->static_bucket_counter[i][j+1])); } json_object_add_value_object(root, buf, bucket); } - for (i = 0; i <= 3; i++) { + for (i = 0; i < C3_BUCKET_NUM; 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) + for (j = 2; j >= 0; j--) { + if (le64_to_cpu(log_data->static_latency_timestamp[i][j]) == -1) { json_object_add_value_string(bucket, operation[j], "NA"); - else { + } 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); } @@ -350,6 +366,47 @@ static void ocp_print_C3_log_json(struct ssd_latency_monitor_log *log_data) json_object_add_value_object(root, buf, bucket); } + for (i = 0; i < C3_BUCKET_NUM; i++) { + struct json_object *bucket; + + bucket = json_create_object(); + sprintf(buf, "Static Measured Latency: Bucket %d", i); + for (j = 2; j >= 0; 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); + } + + 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)); + json_object_add_value_uint(root, "Debug Log Measured Latency", + le16_to_cpu(log_data->debug_log_measured_latency)); + if (le64_to_cpu(log_data->debug_log_latency_stamp) == -1) { + json_object_add_value_string(root, "Debug Log Latency Time Stamp", "NA"); + } else { + convert_ts(le64_to_cpu(log_data->debug_log_latency_stamp), ts_buf); + json_object_add_value_string(root, "Debug Log Latency Time Stamp", ts_buf); + } + json_object_add_value_uint(root, "Debug Log Pointer", + le16_to_cpu(log_data->debug_log_ptr)); + json_object_add_value_uint(root, "Debug Counter Trigger Source", + le16_to_cpu(log_data->debug_log_counter_trigger)); + json_object_add_value_uint(root, "Debug Log Stamp Units", + le16_to_cpu(log_data->debug_log_stamp_units)); + json_object_add_value_uint(root, "Log Page Version", + le16_to_cpu(log_data->log_page_version)); + + char guid[(C3_GUID_LENGTH * 2) + 1]; + char *ptr = &guid[0]; + + for (i = C3_GUID_LENGTH - 1; i >= 0; i--) + ptr += sprintf(ptr, "%02X", log_data->log_page_guid[i]); + + json_object_add_value_string(root, "Log Page GUID", guid); + json_print_object(root, NULL); printf("\n"); @@ -381,12 +438,9 @@ static int get_c3_log_page(struct nvme_dev *dev, char *format) 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); + fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret, false), ret); - if (ret == 0) { + if (!ret) { log_data = (struct ssd_latency_monitor_log *)data; /* check log page version */ @@ -397,22 +451,22 @@ static int get_c3_log_page(struct nvme_dev *dev, char *format) goto out; } - /* check log page guid */ - /* Verify GUID matches */ + /* + * 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++) { + 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++) { + for (j = 0; j < 16; j++) fprintf(stderr, "%x", log_data->log_page_guid[j]); - } fprintf(stderr, "\n"); ret = -1; @@ -438,12 +492,6 @@ out: 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_latency_monitor_log(int argc, char **argv, struct command *command, struct plugin *plugin) @@ -480,12 +528,142 @@ static int ocp_latency_monitor_log(int argc, char **argv, return ret; } -static int clear_fw_update_history(int argc, char **argv, - struct command *cmd, struct plugin *plugin) +int ocp_set_latency_monitor_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - return ocp_clear_fw_update_history(argc, argv, cmd, plugin); + int err = -1; + struct nvme_dev *dev; + __u32 result; + struct feature_latency_monitor buf = {0,}; + __u32 nsid = NVME_NSID_ALL; + struct stat nvme_stat; + struct nvme_id_ctrl ctrl; + + const char *desc = "Set Latency Monitor feature."; + const char *active_bucket_timer_threshold = "This is the value that loads the Active Bucket Timer Threshold."; + const char *active_threshold_a = "This is the value that loads into the Active Threshold A."; + const char *active_threshold_b = "This is the value that loads into the Active Threshold B."; + const char *active_threshold_c = "This is the value that loads into the Active Threshold C."; + const char *active_threshold_d = "This is the value that loads into the Active Threshold D."; + const char *active_latency_config = "This is the value that loads into the Active Latency Configuration."; + const char *active_latency_minimum_window = "This is the value that loads into the Active Latency Minimum Window."; + const char *debug_log_trigger_enable = "This is the value that loads into the Debug Log Trigger Enable."; + const char *discard_debug_log = "Discard Debug Log."; + const char *latency_monitor_feature_enable = "Latency Monitor Feature Enable."; + + struct config { + __u16 active_bucket_timer_threshold; + __u8 active_threshold_a; + __u8 active_threshold_b; + __u8 active_threshold_c; + __u8 active_threshold_d; + __u16 active_latency_config; + __u8 active_latency_minimum_window; + __u16 debug_log_trigger_enable; + __u8 discard_debug_log; + __u8 latency_monitor_feature_enable; + }; + + struct config cfg = { + .active_bucket_timer_threshold = 0x7E0, + .active_threshold_a = 0x5, + .active_threshold_b = 0x13, + .active_threshold_c = 0x1E, + .active_threshold_d = 0x2E, + .active_latency_config = 0xFFF, + .active_latency_minimum_window = 0xA, + .debug_log_trigger_enable = 0, + .discard_debug_log = 0, + .latency_monitor_feature_enable = 0x7, + }; + + OPT_ARGS(opts) = { + OPT_UINT("active_bucket_timer_threshold", 't', &cfg.active_bucket_timer_threshold, active_bucket_timer_threshold), + OPT_UINT("active_threshold_a", 'a', &cfg.active_threshold_a, active_threshold_a), + OPT_UINT("active_threshold_b", 'b', &cfg.active_threshold_b, active_threshold_b), + OPT_UINT("active_threshold_c", 'c', &cfg.active_threshold_c, active_threshold_c), + OPT_UINT("active_threshold_d", 'd', &cfg.active_threshold_d, active_threshold_d), + OPT_UINT("active_latency_config", 'f', &cfg.active_latency_config, active_latency_config), + OPT_UINT("active_latency_minimum_window", 'w', &cfg.active_latency_minimum_window, active_latency_minimum_window), + OPT_UINT("debug_log_trigger_enable", 'r', &cfg.debug_log_trigger_enable, debug_log_trigger_enable), + OPT_UINT("discard_debug_log", 'l', &cfg.discard_debug_log, discard_debug_log), + OPT_UINT("latency_monitor_feature_enable", 'e', &cfg.latency_monitor_feature_enable, latency_monitor_feature_enable), + OPT_END() + }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; + + err = fstat(dev_fd(dev), &nvme_stat); + if (err < 0) + return err; + + if (S_ISBLK(nvme_stat.st_mode)) { + err = nvme_get_nsid(dev_fd(dev), &nsid); + if (err < 0) { + perror("invalid-namespace-id"); + return err; + } + } + + err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + if (err) + return err; + + memset(&buf, 0, sizeof(struct feature_latency_monitor)); + + buf.active_bucket_timer_threshold = cfg.active_bucket_timer_threshold; + buf.active_threshold_a = cfg.active_threshold_a; + buf.active_threshold_b = cfg.active_threshold_b; + buf.active_threshold_c = cfg.active_threshold_c; + buf.active_threshold_d = cfg.active_threshold_d; + buf.active_latency_config = cfg.active_latency_config; + buf.active_latency_minimum_window = cfg.active_latency_minimum_window; + buf.debug_log_trigger_enable = cfg.debug_log_trigger_enable; + buf.discard_debug_log = cfg.discard_debug_log; + buf.latency_monitor_feature_enable = cfg.latency_monitor_feature_enable; + + struct nvme_set_features_args args = { + .args_size = sizeof(args), + .fd = dev_fd(dev), + .fid = NVME_FEAT_OCP_LATENCY_MONITOR, + .nsid = 0, + .cdw12 = 0, + .save = 1, + .data_len = sizeof(struct feature_latency_monitor), + .data = (void *)&buf, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + + err = nvme_set_features(&args); + if (err < 0) { + perror("set-feature"); + } else if (!err) { + printf("NVME_FEAT_OCP_LATENCY_MONITOR: 0x%02x\n", NVME_FEAT_OCP_LATENCY_MONITOR); + printf("active bucket timer threshold: 0x%x\n", buf.active_bucket_timer_threshold); + printf("active threshold a: 0x%x\n", buf.active_threshold_a); + printf("active threshold b: 0x%x\n", buf.active_threshold_b); + printf("active threshold c: 0x%x\n", buf.active_threshold_c); + printf("active threshold d: 0x%x\n", buf.active_threshold_d); + printf("active latency config: 0x%x\n", buf.active_latency_config); + printf("active latency minimum window: 0x%x\n", buf.active_latency_minimum_window); + printf("debug log trigger enable: 0x%x\n", buf.debug_log_trigger_enable); + printf("discard debug log: 0x%x\n", buf.discard_debug_log); + printf("latency monitor feature enable: 0x%x\n", buf.latency_monitor_feature_enable); + } else if (err > 0) { + fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err, false), err); + } + + return err; } +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/// EOL/PLP Failure Mode + static const char *eol_plp_failure_mode_to_string(__u8 mode) { switch (mode) { @@ -524,14 +702,14 @@ static int eol_plp_failure_mode_get(struct nvme_dev *dev, const __u32 nsid, 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)); + nvme_show_result("End of Life Behavior (feature: %#0*x): %#0*x (%s: %s)", + 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); + nvme_show_error("Could not get feature: %#0*x.", fid ? 4 : 2, fid); } return err; @@ -549,7 +727,7 @@ static int eol_plp_failure_mode_set(struct nvme_dev *dev, const __u32 nsid, /* 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"); + nvme_show_error("ERROR: No OCP UUID index found"); return err; } } @@ -575,13 +753,13 @@ static int eol_plp_failure_mode_set(struct nvme_dev *dev, const __u32 nsid, if (err > 0) { nvme_show_status(err); } else if (err < 0) { - perror("Define EOL/PLP failure mode"); + nvme_show_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)); + nvme_show_result("Successfully set mode (feature: %#0*x): %#0*x (%s: %s).", + fid ? 4 : 2, fid, mode ? 10 : 8, mode, + save ? "Save" : "Not save", + eol_plp_failure_mode_to_string(mode)); } return err; @@ -590,7 +768,7 @@ static int eol_plp_failure_mode_set(struct nvme_dev *dev, const __u32 nsid, static int eol_plp_failure_mode(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Define EOL or PLP circuitry failure mode.\n"\ + 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"; @@ -637,6 +815,1074 @@ static int eol_plp_failure_mode(int argc, char **argv, struct command *cmd, return err; } +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/// Telemetry Log + +#define TELEMETRY_HEADER_SIZE 512 +#define TELEMETRY_BYTE_PER_BLOCK 512 +#define TELEMETRY_TRANSFER_SIZE 1024 +#define FILE_NAME_SIZE 2048 + +enum TELEMETRY_TYPE { + TELEMETRY_TYPE_NONE = 0, + TELEMETRY_TYPE_HOST = 7, + TELEMETRY_TYPE_CONTROLLER = 8, + TELEMETRY_TYPE_HOST_0 = 9, + TELEMETRY_TYPE_HOST_1 = 10, +}; + +struct telemetry_initiated_log { + __u8 LogIdentifier; + __u8 Reserved1[4]; + __u8 IEEE[3]; + __le16 DataArea1LastBlock; + __le16 DataArea2LastBlock; + __le16 DataArea3LastBlock; + __u8 Reserved2[368]; + __u8 DataAvailable; + __u8 DataGenerationNumber; + __u8 ReasonIdentifier[128]; +}; + +static void get_serial_number(struct nvme_id_ctrl *ctrl, char *sn) +{ + int i; + /* Remove trailing spaces from the name */ + for (i = 0; i < sizeof(ctrl->sn); i++) { + if (ctrl->sn[i] == ' ') + break; + sn[i] = ctrl->sn[i]; + } +} + +static int get_telemetry_header(struct nvme_dev *dev, __u32 ns, __u8 tele_type, + __u32 data_len, void *data, __u8 nLSP, __u8 nRAE) +{ + struct nvme_passthru_cmd cmd = { + .opcode = nvme_admin_get_log_page, + .nsid = ns, + .addr = (__u64)(uintptr_t) data, + .data_len = data_len, + }; + + __u32 numd = (data_len >> 2) - 1; + __u16 numdu = numd >> 16; + __u16 numdl = numd & 0xffff; + + cmd.cdw10 = tele_type | (nLSP & 0x0F) << 8 | (nRAE & 0x01) << 15 | (numdl & 0xFFFF) << 16; + cmd.cdw11 = numdu; + cmd.cdw12 = 0; + cmd.cdw13 = 0; + cmd.cdw14 = 0; + + return nvme_submit_admin_passthru(dev_fd(dev), &cmd, NULL); +} + +static void print_telemetry_header(struct telemetry_initiated_log *logheader, + int tele_type) +{ + if (logheader) { + unsigned int i = 0, j = 0; + + if (tele_type == TELEMETRY_TYPE_HOST) + printf("============ Telemetry Host Header ============\n"); + else + printf("========= Telemetry Controller Header =========\n"); + + printf("Log Identifier : 0x%02X\n", logheader->LogIdentifier); + printf("IEEE : 0x%02X%02X%02X\n", + logheader->IEEE[0], logheader->IEEE[1], logheader->IEEE[2]); + printf("Data Area 1 Last Block : 0x%04X\n", + le16_to_cpu(logheader->DataArea1LastBlock)); + printf("Data Area 2 Last Block : 0x%04X\n", + le16_to_cpu(logheader->DataArea2LastBlock)); + printf("Data Area 3 Last Block : 0x%04X\n", + le16_to_cpu(logheader->DataArea3LastBlock)); + printf("Data Available : 0x%02X\n", logheader->DataAvailable); + printf("Data Generation Number : 0x%02X\n", logheader->DataGenerationNumber); + printf("Reason Identifier :\n"); + + for (i = 0; i < 8; i++) { + for (j = 0; j < 16; j++) + printf("%02X ", logheader->ReasonIdentifier[127 - ((i * 16) + j)]); + printf("\n"); + } + printf("===============================================\n\n"); + } +} + +static int extract_dump_get_log(struct nvme_dev *dev, char *featurename, char *filename, char *sn, + int dumpsize, int transfersize, __u32 nsid, __u8 log_id, + __u8 lsp, __u64 offset, bool rae) +{ + int i = 0, err = 0; + + char *data = calloc(transfersize, sizeof(char)); + char filepath[FILE_NAME_SIZE] = {0,}; + int output = 0; + int total_loop_cnt = dumpsize / transfersize; + int last_xfer_size = dumpsize % transfersize; + + if (last_xfer_size) + total_loop_cnt++; + else + last_xfer_size = transfersize; + + if (filename == 0) + snprintf(filepath, FILE_NAME_SIZE, "%s_%s.bin", featurename, sn); + else + snprintf(filepath, FILE_NAME_SIZE, "%s%s_%s.bin", filename, featurename, sn); + + for (i = 0; i < total_loop_cnt; i++) { + memset(data, 0, transfersize); + + struct nvme_get_log_args args = { + .lpo = offset, + .result = NULL, + .log = (void *)data, + .args_size = sizeof(args), + .fd = dev_fd(dev), + .lid = log_id, + .len = transfersize, + .nsid = nsid, + .lsp = lsp, + .uuidx = 0, + .rae = rae, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .csi = NVME_CSI_NVM, + .ot = false, + }; + + err = nvme_get_log(&args); + if (err) { + if (i > 0) + goto close_output; + else + goto end; + } + + if (i != total_loop_cnt - 1) { + if (!i) { + output = open(filepath, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (output < 0) { + err = -13; + goto end; + } + } + if (write(output, data, transfersize) < 0) { + err = -10; + goto close_output; + } + } else { + if (write(output, data, last_xfer_size) < 0) { + err = -10; + goto close_output; + } + } + offset += transfersize; + printf("%d%%\r", (i + 1) * 100 / total_loop_cnt); + } + printf("100%%\nThe log file was saved at \"%s\"\n", filepath); + +close_output: + close(output); + +end: + free(data); + return err; +} + +static int get_telemetry_dump(struct nvme_dev *dev, char *filename, char *sn, + enum TELEMETRY_TYPE tele_type, int data_area, bool header_print) +{ + __u32 err = 0, nsid = 0; + __u8 lsp = 0, rae = 0; + char data[TELEMETRY_TRANSFER_SIZE] = { 0 }; + char *featurename = 0; + struct telemetry_initiated_log *logheader = (struct telemetry_initiated_log *)data; + __u64 offset = 0, size = 0; + char dumpname[FILE_NAME_SIZE] = { 0 }; + + if (tele_type == TELEMETRY_TYPE_HOST_0) { + featurename = "Host(0)"; + lsp = 0; + rae = 0; + tele_type = TELEMETRY_TYPE_HOST; + } else if (tele_type == TELEMETRY_TYPE_HOST_1) { + featurename = "Host(1)"; + lsp = 1; + rae = 0; + tele_type = TELEMETRY_TYPE_HOST; + } else { + featurename = "Controller"; + lsp = 0; + rae = 1; + } + + err = get_telemetry_header(dev, nsid, tele_type, TELEMETRY_HEADER_SIZE, + (void *)data, lsp, rae); + if (err) + return err; + + if (header_print) + print_telemetry_header(logheader, tele_type); + + switch (data_area) { + case 1: + offset = TELEMETRY_HEADER_SIZE; + size = le16_to_cpu(logheader->DataArea1LastBlock); + break; + case 2: + offset = TELEMETRY_HEADER_SIZE + + (le16_to_cpu(logheader->DataArea1LastBlock) * TELEMETRY_BYTE_PER_BLOCK); + size = le16_to_cpu(logheader->DataArea2LastBlock) + - le16_to_cpu(logheader->DataArea1LastBlock); + break; + case 3: + offset = TELEMETRY_HEADER_SIZE + + (le16_to_cpu(logheader->DataArea2LastBlock) * TELEMETRY_BYTE_PER_BLOCK); + size = le16_to_cpu(logheader->DataArea3LastBlock) + - le16_to_cpu(logheader->DataArea2LastBlock); + break; + default: + break; + } + + if (!size) { + printf("Telemetry %s Area %d is empty.\n", featurename, data_area); + return err; + } + + snprintf(dumpname, FILE_NAME_SIZE, + "Telemetry_%s_Area_%d", featurename, data_area); + err = extract_dump_get_log(dev, dumpname, filename, sn, size * TELEMETRY_BYTE_PER_BLOCK, + TELEMETRY_TRANSFER_SIZE, nsid, tele_type, + 0, offset, rae); + + return err; +} + +static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, + struct plugin *plugin) +{ + struct nvme_dev *dev; + int err = 0; + const char *desc = "Retrieve and save telemetry log."; + const char *type = "Telemetry Type; 'host[Create bit]' or 'controller'"; + const char *area = "Telemetry Data Area; 1 or 3"; + const char *file = "Output file name with path;\n" + "e.g. '-o ./path/name'\n'-o ./path1/path2/';\n" + "If requested path does not exist, the directory will be newly created."; + + __u32 nsid = NVME_NSID_ALL; + struct stat nvme_stat; + char sn[21] = {0,}; + struct nvme_id_ctrl ctrl; + bool is_support_telemetry_controller; + + int tele_type = 0; + int tele_area = 0; + + struct config { + char *type; + int area; + char *file; + }; + + struct config cfg = { + .type = NULL, + .area = 0, + .file = NULL, + }; + + OPT_ARGS(opts) = { + OPT_STR("telemetry_type", 't', &cfg.type, type), + OPT_INT("telemetry_data_area", 'a', &cfg.area, area), + OPT_FILE("output-file", 'o', &cfg.file, file), + OPT_END() + }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; + + err = fstat(dev_fd(dev), &nvme_stat); + if (err < 0) + return err; + + if (S_ISBLK(nvme_stat.st_mode)) { + err = nvme_get_nsid(dev_fd(dev), &nsid); + if (err < 0) + return err; + } + + err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + if (err) + return err; + + get_serial_number(&ctrl, sn); + + is_support_telemetry_controller = ((ctrl.lpa & 0x8) >> 3); + + if (!cfg.type && !cfg.area) { + tele_type = TELEMETRY_TYPE_NONE; + tele_area = 0; + } else if (cfg.type && cfg.area) { + if (!strcmp(cfg.type, "host0")) + tele_type = TELEMETRY_TYPE_HOST_0; + else if (!strcmp(cfg.type, "host1")) + tele_type = TELEMETRY_TYPE_HOST_1; + else if (!strcmp(cfg.type, "controller")) + tele_type = TELEMETRY_TYPE_CONTROLLER; + + tele_area = cfg.area; + + if ((tele_area != 1 && tele_area != 3) || + (tele_type == TELEMETRY_TYPE_CONTROLLER && tele_area != 3)) { + printf("\nUnsupported parameters entered.\n"); + printf("Possible combinations; {'host0',1}, {'host0',3}, {'host1',1}, {'host1',3}, {'controller',3}\n"); + return err; + } + } else { + printf("\nShould provide these all; 'telemetry_type' and 'telemetry_data_area'\n"); + return err; + } + + if (tele_type == TELEMETRY_TYPE_NONE) { + printf("\n-------------------------------------------------------------\n"); + /* Host 0 (lsp == 0) must be executed before Host 1 (lsp == 1). */ + printf("\nExtracting Telemetry Host 0 Dump (Data Area 1)...\n"); + + err = get_telemetry_dump(dev, cfg.file, sn, + TELEMETRY_TYPE_HOST_0, 1, true); + if (err) + fprintf(stderr, "NVMe Status: %s(%x)\n", nvme_status_to_string(err, false), err); + + printf("\n-------------------------------------------------------------\n"); + + printf("\nExtracting Telemetry Host 0 Dump (Data Area 3)...\n"); + + err = get_telemetry_dump(dev, cfg.file, sn, + TELEMETRY_TYPE_HOST_0, 3, false); + if (err) + fprintf(stderr, "NVMe Status: %s(%x)\n", nvme_status_to_string(err, false), err); + + printf("\n-------------------------------------------------------------\n"); + + printf("\nExtracting Telemetry Host 1 Dump (Data Area 1)...\n"); + + err = get_telemetry_dump(dev, cfg.file, sn, + TELEMETRY_TYPE_HOST_1, 1, true); + if (err) + fprintf(stderr, "NVMe Status: %s(%x)\n", nvme_status_to_string(err, false), err); + + printf("\n-------------------------------------------------------------\n"); + + printf("\nExtracting Telemetry Host 1 Dump (Data Area 3)...\n"); + + err = get_telemetry_dump(dev, cfg.file, sn, + TELEMETRY_TYPE_HOST_1, 3, false); + if (err) + fprintf(stderr, "NVMe Status: %s(%x)\n", nvme_status_to_string(err, false), err); + + printf("\n-------------------------------------------------------------\n"); + + printf("\nExtracting Telemetry Controller Dump (Data Area 3)...\n"); + + if (is_support_telemetry_controller == true) { + err = get_telemetry_dump(dev, cfg.file, sn, + TELEMETRY_TYPE_CONTROLLER, 3, true); + if (err) + fprintf(stderr, "NVMe Status: %s(%x)\n", nvme_status_to_string(err, false), err); + } + + printf("\n-------------------------------------------------------------\n"); + } else if (tele_type == TELEMETRY_TYPE_CONTROLLER) { + printf("Extracting Telemetry Controller Dump (Data Area %d)...\n", tele_area); + + if (is_support_telemetry_controller == true) { + err = get_telemetry_dump(dev, cfg.file, sn, tele_type, tele_area, true); + if (err) + fprintf(stderr, "NVMe Status: %s(%x)\n", nvme_status_to_string(err, false), err); + } + } else { + printf("Extracting Telemetry Host(%d) Dump (Data Area %d)...\n", + (tele_type == TELEMETRY_TYPE_HOST_0) ? 0 : 1, tele_area); + + err = get_telemetry_dump(dev, cfg.file, sn, tele_type, tele_area, true); + if (err) + fprintf(stderr, "NVMe Status: %s(%x)\n", nvme_status_to_string(err, false), err); + } + + printf("telemetry-log done.\n"); + +return err; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/// Unsupported Requirement Log Page (LID : C5h) + +/* C5 Unsupported Requirement Log Page */ +#define C5_GUID_LENGTH 16 +#define C5_UNSUPPORTED_REQS_LEN 4096 +#define C5_UNSUPPORTED_REQS_OPCODE 0xC5 +#define C5_UNSUPPORTED_REQS_LOG_VERSION 0x1 +#define C5_NUM_UNSUPPORTED_REQ_ENTRIES 253 + +static __u8 unsupported_req_guid[C5_GUID_LENGTH] = { + 0x2F, 0x72, 0x9C, 0x0E, + 0x99, 0x23, 0x2C, 0xBB, + 0x63, 0x48, 0x32, 0xD0, + 0xB7, 0x98, 0xBB, 0xC7 +}; + +/* + * struct unsupported_requirement_log - unsupported requirement list + * @unsupported_count: Number of Unsupported Requirement IDs + * @rsvd1: Reserved + * @unsupported_req_list: Unsupported Requirements lists upto 253. + * @rsvd2: Reserved + * @log_page_version: indicates the version of the mapping this log page uses. + * Shall be set to 0001h + * @log_page_guid: Shall be set to C7BB98B7D0324863BB2C23990E9C722Fh. + */ +struct __packed unsupported_requirement_log { + __le16 unsupported_count; + __u8 rsvd1[14]; + __u8 unsupported_req_list[C5_NUM_UNSUPPORTED_REQ_ENTRIES][16]; + __u8 rsvd2[14]; + __le16 log_page_version; + __u8 log_page_guid[C5_GUID_LENGTH]; +}; + +/* Function declaration for unsupported requirement log page (LID:C5h) */ +static int ocp_unsupported_requirements_log(int argc, char **argv, struct command *cmd, + struct plugin *plugin); + +static int ocp_print_C5_log_normal(struct nvme_dev *dev, + struct unsupported_requirement_log *log_data) +{ + int j; + + printf("Unsupported Requirement-C5 Log Page Data-\n"); + + printf(" Number Unsupported Req IDs : 0x%x\n", le16_to_cpu(log_data->unsupported_count)); + + for (j = 0; j < le16_to_cpu(log_data->unsupported_count); j++) + printf(" Unsupported Requirement List %d : %s\n", j, log_data->unsupported_req_list[j]); + + printf(" Log Page Version : 0x%x\n", le16_to_cpu(log_data->log_page_version)); + printf(" Log page GUID : 0x"); + for (j = C5_GUID_LENGTH - 1; j >= 0; j--) + printf("%x", log_data->log_page_guid[j]); + printf("\n"); + + return 0; +} + +static void ocp_print_C5_log_json(struct unsupported_requirement_log *log_data) +{ + int j; + struct json_object *root; + char unsup_req_list_str[40]; + char guid_buf[C5_GUID_LENGTH]; + char *guid = guid_buf; + + root = json_create_object(); + + json_object_add_value_int(root, "Number Unsupported Req IDs", le16_to_cpu(log_data->unsupported_count)); + + memset((void *)unsup_req_list_str, 0, 40); + for (j = 0; j < le16_to_cpu(log_data->unsupported_count); j++) { + sprintf((char *)unsup_req_list_str, "Unsupported Requirement List %d", j); + json_object_add_value_string(root, unsup_req_list_str, (char *)log_data->unsupported_req_list[j]); + } + + json_object_add_value_int(root, "Log Page Version", le16_to_cpu(log_data->log_page_version)); + + memset((void *)guid, 0, C5_GUID_LENGTH); + for (j = C5_GUID_LENGTH - 1; j >= 0; j--) + guid += sprintf(guid, "%02x", log_data->log_page_guid[j]); + json_object_add_value_string(root, "Log page GUID", guid_buf); + + json_print_object(root, NULL); + printf("\n"); + + json_free_object(root); +} + +static void ocp_print_c5_log_binary(struct unsupported_requirement_log *log_data) +{ + return d_raw((unsigned char *)log_data, sizeof(*log_data)); +} + +static int get_c5_log_page(struct nvme_dev *dev, char *format) +{ + int ret = 0; + int fmt = -1; + __u8 *data; + int i; + struct unsupported_requirement_log *log_data; + int j; + + fmt = validate_output_format(format); + if (fmt < 0) { + fprintf(stderr, "ERROR : OCP : invalid output format\n"); + return fmt; + } + + data = (__u8 *)malloc(sizeof(__u8) * C5_UNSUPPORTED_REQS_LEN); + if (!data) { + fprintf(stderr, "ERROR : OCP : malloc : %s\n", strerror(errno)); + return -1; + } + memset(data, 0, sizeof(__u8) * C5_UNSUPPORTED_REQS_LEN); + + ret = nvme_get_log_simple(dev_fd(dev), C5_UNSUPPORTED_REQS_OPCODE, + C5_UNSUPPORTED_REQS_LEN, data); + if (!ret) { + log_data = (struct unsupported_requirement_log *)data; + + /* check log page version */ + if (log_data->log_page_version != C5_UNSUPPORTED_REQS_LOG_VERSION) { + fprintf(stderr, "ERROR : OCP : invalid unsupported requirement version\n"); + ret = -1; + goto out; + } + + /* + * check log page guid + * Verify GUID matches + */ + for (i = 0; i < 16; i++) { + if (unsupported_req_guid[i] != log_data->log_page_guid[i]) { + fprintf(stderr, "ERROR : OCP : Unknown GUID in C5 Log Page data\n"); + fprintf(stderr, "ERROR : OCP : Expected GUID: 0x"); + for (j = 0; j < 16; j++) + fprintf(stderr, "%x", unsupported_req_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_C5_log_normal(dev, log_data); + break; + case JSON: + ocp_print_C5_log_json(log_data); + break; + case BINARY: + ocp_print_c5_log_binary(log_data); + break; + } + } else { + fprintf(stderr, "ERROR : OCP : Unable to read C3 data from buffer\n"); + } + +out: + free(data); + return ret; +} + + +static int ocp_unsupported_requirements_log(int argc, char **argv, struct command *cmd, + struct plugin *plugin) +{ + const char *desc = "Retrieve unsupported requirements 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_c5_log_page(dev, cfg.output_format); + if (ret) + fprintf(stderr, "ERROR : OCP : Failure reading the C5 Log Page, ret = %d\n", ret); + + dev_close(dev); + return ret; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/// Error Recovery Log Page(0xC1) + +#define C1_ERROR_RECOVERY_LOG_BUF_LEN 0x200 +#define C1_ERROR_RECOVERY_OPCODE 0xC1 +#define C1_ERROR_RECOVERY_VERSION 0x0002 +#define C1_GUID_LENGTH 16 +static __u8 error_recovery_guid[C1_GUID_LENGTH] = { + 0x44, 0xd9, 0x31, 0x21, + 0xfe, 0x30, 0x34, 0xae, + 0xab, 0x4d, 0xfd, 0x3d, + 0xba, 0x83, 0x19, 0x5a +}; + +/** + * struct ocp_error_recovery_log_page - Error Recovery Log Page + * @panic_reset_wait_time: Panic Reset Wait Time + * @panic_reset_action: Panic Reset Action + * @device_recover_action_1: Device Recovery Action 1 + * @panic_id: Panic ID + * @device_capabilities: Device Capabilities + * @vendor_specific_recovery_opcode: Vendor Specific Recovery Opcode + * @reserved: Reserved + * @vendor_specific_command_cdw12: Vendor Specific Command CDW12 + * @vendor_specific_command_cdw13: Vendor Specific Command CDW13 + * @vendor_specific_command_timeout: Vendor Specific Command Timeout + * @device_recover_action_2: Device Recovery Action 2 + * @device_recover_action_2_timeout: Device Recovery Action 2 Timeout + * @reserved2: Reserved + * @log_page_version: Log Page Version + * @log_page_guid: Log Page GUID + */ +struct __packed ocp_error_recovery_log_page { + __le16 panic_reset_wait_time; /* 2 bytes - 0x00 - 0x01 */ + __u8 panic_reset_action; /* 1 byte - 0x02 */ + __u8 device_recover_action_1; /* 1 byte - 0x03 */ + __le64 panic_id; /* 8 bytes - 0x04 - 0x0B */ + __le32 device_capabilities; /* 4 bytes - 0x0C - 0x0F */ + __u8 vendor_specific_recovery_opcode; /* 1 byte - 0x10 */ + __u8 reserved[0x3]; /* 3 bytes - 0x11 - 0x13 */ + __le32 vendor_specific_command_cdw12; /* 4 bytes - 0x14 - 0x17 */ + __le32 vendor_specific_command_cdw13; /* 4 bytes - 0x18 - 0x1B */ + __u8 vendor_specific_command_timeout; /* 1 byte - 0x1C */ + __u8 device_recover_action_2; /* 1 byte - 0x1D */ + __u8 device_recover_action_2_timeout; /* 1 byte - 0x1E */ + __u8 reserved2[0x1cf]; /* 463 bytes - 0x1F - 0x1ED */ + __le16 log_page_version; /* 2 bytes - 0x1EE - 0x1EF */ + __u8 log_page_guid[0x10]; /* 16 bytes - 0x1F0 - 0x1FF */ +}; + +static void ocp_print_c1_log_normal(struct ocp_error_recovery_log_page *log_data); +static void ocp_print_c1_log_json(struct ocp_error_recovery_log_page *log_data); +static void ocp_print_c1_log_binary(struct ocp_error_recovery_log_page *log_data); +static int get_c1_log_page(struct nvme_dev *dev, char *format); +static int ocp_error_recovery_log(int argc, char **argv, struct command *cmd, struct plugin *plugin); + +static void ocp_print_c1_log_normal(struct ocp_error_recovery_log_page *log_data) +{ + int i; + + printf(" Error Recovery/C1 Log Page Data\n"); + printf(" Panic Reset Wait Time : 0x%x\n", le16_to_cpu(log_data->panic_reset_wait_time)); + printf(" Panic Reset Action : 0x%x\n", log_data->panic_reset_action); + printf(" Device Recovery Action 1 : 0x%x\n", log_data->device_recover_action_1); + printf(" Panic ID : 0x%x\n", le32_to_cpu(log_data->panic_id)); + printf(" Device Capabilities : 0x%x\n", le32_to_cpu(log_data->device_capabilities)); + printf(" Vendor Specific Recovery Opcode : 0x%x\n", log_data->vendor_specific_recovery_opcode); + printf(" Vendor Specific Command CDW12 : 0x%x\n", le32_to_cpu(log_data->vendor_specific_command_cdw12)); + printf(" Vendor Specific Command CDW13 : 0x%x\n", le32_to_cpu(log_data->vendor_specific_command_cdw13)); + printf(" Vendor Specific Command Timeout : 0x%x\n", log_data->vendor_specific_command_timeout); + printf(" Device Recovery Action 2 : 0x%x\n", log_data->device_recover_action_2); + printf(" Device Recovery Action 2 Timeout : 0x%x\n", log_data->device_recover_action_2_timeout); + printf(" Log Page Version : 0x%x\n", le16_to_cpu(log_data->log_page_version)); + printf(" Log page GUID : 0x"); + for (i = C1_GUID_LENGTH - 1; i >= 0; i--) + printf("%x", log_data->log_page_guid[i]); + printf("\n"); +} + +static void ocp_print_c1_log_json(struct ocp_error_recovery_log_page *log_data) +{ + struct json_object *root; + + root = json_create_object(); + char guid[64]; + + json_object_add_value_int(root, "Panic Reset Wait Time", le16_to_cpu(log_data->panic_reset_wait_time)); + json_object_add_value_int(root, "Panic Reset Action", log_data->panic_reset_action); + json_object_add_value_int(root, "Device Recovery Action 1", log_data->device_recover_action_1); + json_object_add_value_int(root, "Panic ID", le32_to_cpu(log_data->panic_id)); + json_object_add_value_int(root, "Device Capabilities", le32_to_cpu(log_data->device_capabilities)); + json_object_add_value_int(root, "Vendor Specific Recovery Opcode", log_data->vendor_specific_recovery_opcode); + json_object_add_value_int(root, "Vendor Specific Command CDW12", le32_to_cpu(log_data->vendor_specific_command_cdw12)); + json_object_add_value_int(root, "Vendor Specific Command CDW13", le32_to_cpu(log_data->vendor_specific_command_cdw13)); + json_object_add_value_int(root, "Vendor Specific Command Timeout", log_data->vendor_specific_command_timeout); + json_object_add_value_int(root, "Device Recovery Action 2", log_data->device_recover_action_2); + json_object_add_value_int(root, "Device Recovery Action 2 Timeout", log_data->device_recover_action_2_timeout); + json_object_add_value_int(root, "Log Page Version", le16_to_cpu(log_data->log_page_version)); + + memset((void *)guid, 0, 64); + sprintf((char *)guid, "0x%"PRIx64"%"PRIx64"", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]), + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0])); + json_object_add_value_string(root, "Log page GUID", guid); + + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); +} + +static void ocp_print_c1_log_binary(struct ocp_error_recovery_log_page *log_data) +{ + return d_raw((unsigned char *)log_data, sizeof(*log_data)); +} + +static int get_c1_log_page(struct nvme_dev *dev, char *format) +{ + int ret = 0; + int fmt = -1; + __u8 *data; + int i, j; + struct ocp_error_recovery_log_page *log_data; + + fmt = validate_output_format(format); + if (fmt < 0) { + fprintf(stderr, "ERROR : OCP : invalid output format\n"); + return fmt; + } + + data = (__u8 *)malloc(sizeof(__u8) * C1_ERROR_RECOVERY_LOG_BUF_LEN); + if (!data) { + fprintf(stderr, "ERROR : OCP : malloc : %s\n", strerror(errno)); + return -1; + } + memset(data, 0, sizeof(__u8) * C1_ERROR_RECOVERY_LOG_BUF_LEN); + + ret = nvme_get_log_simple(dev_fd(dev), C1_ERROR_RECOVERY_OPCODE, C1_ERROR_RECOVERY_LOG_BUF_LEN, data); + + if (!ret) { + log_data = (struct ocp_error_recovery_log_page *)data; + + /* check log page version */ + if (log_data->log_page_version != C1_ERROR_RECOVERY_VERSION) { + fprintf(stderr, "ERROR : OCP : invalid error recovery log page version\n"); + ret = -1; + goto out; + } + + /* + * check log page guid + * Verify GUID matches + */ + for (i = 0; i < 16; i++) { + if (error_recovery_guid[i] != log_data->log_page_guid[i]) { + fprintf(stderr, "ERROR : OCP : Unknown GUID in C1 Log Page data\n"); + fprintf(stderr, "ERROR : OCP : Expected GUID: 0x"); + for (j = 0; j < 16; j++) + fprintf(stderr, "%x", error_recovery_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_c1_log_normal(log_data); + break; + case JSON: + ocp_print_c1_log_json(log_data); + break; + case BINARY: + ocp_print_c1_log_binary(log_data); + break; + } + } else { + fprintf(stderr, "ERROR : OCP : Unable to read C1 data from buffer\n"); + } + +out: + free(data); + return ret; +} + +static int ocp_error_recovery_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + const char *desc = "Retrieve C1h Error Recovery 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|binary"), + OPT_END() + }; + + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; + + ret = get_c1_log_page(dev, cfg.output_format); + if (ret) + fprintf(stderr, "ERROR : OCP : Failure reading the C1h Log Page, ret = %d\n", ret); + dev_close(dev); + return ret; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/// Device Capabilities (Log Identifier C4h) Requirements + +#define C4_DEV_CAP_REQ_LEN 0x1000 +#define C4_DEV_CAP_REQ_OPCODE 0xC4 +#define C4_DEV_CAP_REQ_VERSION 0x0001 +#define C4_GUID_LENGTH 16 +static __u8 dev_cap_req_guid[C4_GUID_LENGTH] = { + 0x97, 0x42, 0x05, 0x0d, + 0xd1, 0xe1, 0xc9, 0x98, + 0x5d, 0x49, 0x58, 0x4b, + 0x91, 0x3c, 0x05, 0xb7 +}; + +/** + * struct ocp_device_capabilities_log_page - Device Capability Log page + * @pcie_exp_port: PCI Express Ports + * @oob_management_support: OOB Management Support + * @wz_cmd_support: Write Zeroes Command Support + * @sanitize_cmd_support: Sanitize Command Support + * @dsm_cmd_support: Dataset Management Command Support + * @wu_cmd_support: Write Uncorrectable Command Support + * @fused_operation_support: Fused Operation Support + * @min_valid_dssd_pwr_state: Minimum Valid DSSD Power State + * @dssd_pwr_state_desc: DSSD Power State Descriptors + * @vendor_specific_command_timeout: Vendor Specific Command Timeout + * @reserved: Reserved + * @log_page_version: Log Page Version + * @log_page_guid: Log Page GUID + */ +struct __packed ocp_device_capabilities_log_page { + __le16 pcie_exp_port; + __le16 oob_management_support; + __le16 wz_cmd_support; + __le16 sanitize_cmd_support; + __le16 dsm_cmd_support; + __le16 wu_cmd_support; + __le16 fused_operation_support; + __le16 min_valid_dssd_pwr_state; + __u8 dssd_pwr_state_desc[128]; + __u8 reserved[3934]; + __le16 log_page_version; + __u8 log_page_guid[16]; +}; + +static void ocp_print_c4_log_normal(struct ocp_device_capabilities_log_page *log_data); +static void ocp_print_c4_log_json(struct ocp_device_capabilities_log_page *log_data); +static void ocp_print_c4_log_binary(struct ocp_device_capabilities_log_page *log_data); +static int get_c4_log_page(struct nvme_dev *dev, char *format); +static int ocp_device_capabilities_log(int argc, char **argv, struct command *cmd, struct plugin *plugin); + +static void ocp_print_c4_log_normal(struct ocp_device_capabilities_log_page *log_data) +{ + int i; + + printf(" Device Capability/C4 Log Page Data\n"); + printf(" PCI Express Ports : 0x%x\n", le16_to_cpu(log_data->pcie_exp_port)); + printf(" OOB Management Support : 0x%x\n", le16_to_cpu(log_data->oob_management_support)); + printf(" Write Zeroes Command Support : 0x%x\n", le16_to_cpu(log_data->wz_cmd_support)); + printf(" Sanitize Command Support : 0x%x\n", le16_to_cpu(log_data->sanitize_cmd_support)); + printf(" Dataset Management Command Support : 0x%x\n", le16_to_cpu(log_data->dsm_cmd_support)); + printf(" Write Uncorrectable Command Support : 0x%x\n", le16_to_cpu(log_data->wu_cmd_support)); + printf(" Fused Operation Support : 0x%x\n", le16_to_cpu(log_data->fused_operation_support)); + printf(" Minimum Valid DSSD Power State : 0x%x\n", le16_to_cpu(log_data->min_valid_dssd_pwr_state)); + printf(" DSSD Power State Descriptors : 0x"); + for (i = 0; i <= 127; i++) + printf("%x", log_data->dssd_pwr_state_desc[i]); + printf("\n"); + printf(" Log Page Version : 0x%x\n", le16_to_cpu(log_data->log_page_version)); + printf(" Log page GUID : 0x"); + for (i = C4_GUID_LENGTH - 1; i >= 0; i--) + printf("%x", log_data->log_page_guid[i]); + printf("\n"); +} + +static void ocp_print_c4_log_json(struct ocp_device_capabilities_log_page *log_data) +{ + struct json_object *root = json_create_object(); + char guid[64]; + int i; + + json_object_add_value_int(root, "PCI Express Ports", le16_to_cpu(log_data->pcie_exp_port)); + json_object_add_value_int(root, "OOB Management Support", le16_to_cpu(log_data->oob_management_support)); + json_object_add_value_int(root, "Write Zeroes Command Support", le16_to_cpu(log_data->wz_cmd_support)); + json_object_add_value_int(root, "Sanitize Command Support", le16_to_cpu(log_data->sanitize_cmd_support)); + json_object_add_value_int(root, "Dataset Management Command Support", le16_to_cpu(log_data->dsm_cmd_support)); + json_object_add_value_int(root, "Write Uncorrectable Command Support", le16_to_cpu(log_data->wu_cmd_support)); + json_object_add_value_int(root, "Fused Operation Support", le16_to_cpu(log_data->fused_operation_support)); + json_object_add_value_int(root, "Minimum Valid DSSD Power State", le16_to_cpu(log_data->min_valid_dssd_pwr_state)); + for (i = 0; i <= 127; i++) + json_object_add_value_int(root, "DSSD Power State Descriptors", log_data->dssd_pwr_state_desc[i]); + json_object_add_value_int(root, "Log Page Version", le16_to_cpu(log_data->log_page_version)); + + memset((void *)guid, 0, 64); + sprintf((char *)guid, "0x%"PRIx64"%"PRIx64"", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]), + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0])); + json_object_add_value_string(root, "Log page GUID", guid); + + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); +} + +static void ocp_print_c4_log_binary(struct ocp_device_capabilities_log_page *log_data) +{ + return d_raw((unsigned char *)log_data, sizeof(*log_data)); +} + +static int get_c4_log_page(struct nvme_dev *dev, char *format) +{ + int ret = 0; + int fmt = -1; + __u8 *data; + int i, j; + struct ocp_device_capabilities_log_page *log_data; + + fmt = validate_output_format(format); + if (fmt < 0) { + fprintf(stderr, "ERROR : OCP : invalid output format\n"); + return fmt; + } + + data = (__u8 *)malloc(sizeof(__u8) * C4_DEV_CAP_REQ_LEN); + if (!data) { + fprintf(stderr, "ERROR : OCP : malloc : %s\n", strerror(errno)); + return -1; + } + memset(data, 0, sizeof(__u8) * C4_DEV_CAP_REQ_LEN); + + ret = nvme_get_log_simple(dev_fd(dev), C4_DEV_CAP_REQ_OPCODE, C4_DEV_CAP_REQ_LEN, data); + + if (!ret) { + log_data = (struct ocp_device_capabilities_log_page *)data; + + /* check log page version */ + if (log_data->log_page_version != C4_DEV_CAP_REQ_VERSION) { + fprintf(stderr, "ERROR : OCP : invalid device capabilities log page version\n"); + ret = -1; + goto out; + } + + /* + * check log page guid + * Verify GUID matches + */ + for (i = 0; i < 16; i++) { + if (dev_cap_req_guid[i] != log_data->log_page_guid[i]) { + fprintf(stderr, "ERROR : OCP : Unknown GUID in C4 Log Page data\n"); + fprintf(stderr, "ERROR : OCP : Expected GUID: 0x"); + for (j = 0; j < 16; j++) + fprintf(stderr, "%x", dev_cap_req_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_c4_log_normal(log_data); + break; + case JSON: + ocp_print_c4_log_json(log_data); + break; + case BINARY: + ocp_print_c4_log_binary(log_data); + break; + } + } else { + fprintf(stderr, "ERROR : OCP : Unable to read C4 data from buffer\n"); + } + +out: + free(data); + return ret; +} + +static int ocp_device_capabilities_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + const char *desc = "Retrieve C4h Device Capabilities 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|binary"), + OPT_END() + }; + + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; + + ret = get_c4_log_page(dev, cfg.output_format); + if (ret) + fprintf(stderr, "ERROR : OCP : Failure reading the C4h Log Page, ret = %d\n", ret); + dev_close(dev); + return ret; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/// Misc + +static const __u8 OCP_FID_CLEAR_PCIE_CORRECTABLE_ERROR_COUNTERS = 0xC3; + +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); +} + +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 clear_pcie_corectable_error_counters(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -646,3 +1892,9 @@ static int clear_pcie_corectable_error_counters(int argc, char **argv, return ocp_clear_feature(argc, argv, desc, OCP_FID_CLEAR_PCIE_CORRECTABLE_ERROR_COUNTERS); } + +static int fw_activation_history_log(int argc, char **argv, struct command *cmd, + struct plugin *plugin) +{ + return ocp_fw_activation_history_log(argc, argv, cmd, plugin); +} diff --git a/plugins/ocp/ocp-nvme.h b/plugins/ocp/ocp-nvme.h index dc9e154..74dd0ef 100644 --- a/plugins/ocp/ocp-nvme.h +++ b/plugins/ocp/ocp-nvme.h @@ -17,9 +17,15 @@ PLUGIN(NAME("ocp", "OCP cloud SSD extensions", NVME_VERSION), COMMAND_LIST( 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("set-latency-monitor-feature", "Set Latency Monitor feature", ocp_set_latency_monitor_feature) + ENTRY("internal-log", "Retrieve and save internal device telemetry log", ocp_telemetry_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) + ENTRY("vs-fw-activate-history", "Get firmware activation history log", fw_activation_history_log) + ENTRY("unsupported-reqs-log", "Get Unsupported Requirements Log Page", ocp_unsupported_requirements_log) + ENTRY("error-recovery-log", "Retrieve Error Recovery Log Page", ocp_error_recovery_log) + ENTRY("device-capability-log", "Get Device capabilities Requirements Log Page", ocp_device_capabilities_log) ) ); diff --git a/plugins/ocp/ocp-smart-extended-log.c b/plugins/ocp/ocp-smart-extended-log.c index 37b62e9..c989d34 100644 --- a/plugins/ocp/ocp-smart-extended-log.c +++ b/plugins/ocp/ocp-smart-extended-log.c @@ -26,7 +26,7 @@ static __u8 scao_guid[C0_GUID_LENGTH] = { 0xC9, 0x14, 0xD5, 0xAF }; -typedef enum { +enum { SCAO_PMUW = 0, /* Physical media units written */ SCAO_PMUR = 16, /* Physical media units read */ SCAO_BUNBR = 32, /* Bad user nand blocks raw */ @@ -62,7 +62,7 @@ typedef enum { 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) { @@ -71,10 +71,10 @@ static void ocp_print_C0_log_normal(void *data) printf("SMART Cloud Attributes :-\n"); - printf(" Physical media units written - %"PRIu64" %"PRIu64"\n", + printf(" Physical media units written - %"PRIu64" %"PRIu64"\n", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW + 8] & 0xFFFFFFFFFFFFFFFF), (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW] & 0xFFFFFFFFFFFFFFFF)); - printf(" Physical media units read - %"PRIu64" %"PRIu64"\n", + printf(" Physical media units read - %"PRIu64" %"PRIu64"\n", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR + 8] & 0xFFFFFFFFFFFFFFFF), (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR] & 0xFFFFFFFFFFFFFFFF)); printf(" Bad user nand blocks - Raw %"PRIu64"\n", @@ -105,7 +105,7 @@ static void ocp_print_C0_log_normal(void *data) (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", + 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])); @@ -286,14 +286,12 @@ static int get_c0_log_page(int fd, char *format) 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++) { + 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++) { + for (j = 0; j < 16; j++) fprintf(stderr, "%x", data[SCAO_LPG + j]); - } fprintf(stderr, "\n"); ret = -1; diff --git a/plugins/scaleflux/sfx-nvme.c b/plugins/scaleflux/sfx-nvme.c index 4bcfbf6..01867c7 100644 --- a/plugins/scaleflux/sfx-nvme.c +++ b/plugins/scaleflux/sfx-nvme.c @@ -3,19 +3,23 @@ #include <errno.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <unistd.h> #include <linux/fs.h> #include <inttypes.h> #include <asm/byteorder.h> #include <sys/sysinfo.h> #include <sys/stat.h> -#include <unistd.h> +#include <sys/types.h> +#include <dirent.h> +#include <time.h> #include "common.h" #include "nvme.h" #include "libnvme.h" #include "plugin.h" #include "linux/types.h" +#include "nvme-wrap.h" #include "nvme-print.h" #define CREATE_CMD @@ -57,8 +61,7 @@ enum sfx_nvme_admin_opcode { nvme_admin_sfx_get_features = 0xd6, }; -struct sfx_freespace_ctx -{ +struct sfx_freespace_ctx { __u64 free_space; __u64 phy_cap; /* physical capacity, in unit of sector */ __u64 phy_space; /* physical space considering OP, in unit of sector */ @@ -66,6 +69,10 @@ struct sfx_freespace_ctx __u64 hw_used; /* hw space used in 4K */ __u64 app_written; /* app data written in 4K */ __u64 out_of_space; + __u64 map_unit; + __u64 max_user_space; + __u64 extendible_user_cap_lba_count; + __u64 friendly_change_cap_support; }; struct nvme_capacity_info { @@ -75,72 +82,73 @@ struct nvme_capacity_info { __u64 free_space; }; -struct __attribute__((packed)) nvme_additional_smart_log_item { +struct __packed nvme_additional_smart_log_item { __u8 key; __u8 _kp[2]; __u8 norm; __u8 _np; - union __attribute__((packed)) { + union __packed { __u8 raw[6]; - struct __attribute__((packed)) wear_level { + struct __packed wear_level { __le16 min; __le16 max; __le16 avg; } wear_level; - struct __attribute__((packed)) thermal_throttle { + struct __packed thermal_throttle { __u8 pct; __u32 count; } thermal_throttle; - } ; + }; __u8 _rp; -} ; +}; struct nvme_additional_smart_log { - struct nvme_additional_smart_log_item program_fail_cnt; - struct nvme_additional_smart_log_item erase_fail_cnt; - struct nvme_additional_smart_log_item wear_leveling_cnt; - struct nvme_additional_smart_log_item e2e_err_cnt; - struct nvme_additional_smart_log_item crc_err_cnt; - struct nvme_additional_smart_log_item timed_workload_media_wear; - struct nvme_additional_smart_log_item timed_workload_host_reads; - struct nvme_additional_smart_log_item timed_workload_timer; - struct nvme_additional_smart_log_item thermal_throttle_status; - struct nvme_additional_smart_log_item retry_buffer_overflow_cnt; - struct nvme_additional_smart_log_item pll_lock_loss_cnt; - struct nvme_additional_smart_log_item nand_bytes_written; - struct nvme_additional_smart_log_item host_bytes_written; - struct nvme_additional_smart_log_item raid_recover_cnt; // errors which can be recovered by RAID - struct nvme_additional_smart_log_item prog_timeout_cnt; - struct nvme_additional_smart_log_item erase_timeout_cnt; - struct nvme_additional_smart_log_item read_timeout_cnt; - struct nvme_additional_smart_log_item read_ecc_cnt;//retry cnt - struct nvme_additional_smart_log_item non_media_crc_err_cnt; - struct nvme_additional_smart_log_item compression_path_err_cnt; - struct nvme_additional_smart_log_item out_of_space_flag; - struct nvme_additional_smart_log_item physical_usage_ratio; - struct nvme_additional_smart_log_item grown_bb; //grown bad block + struct nvme_additional_smart_log_item program_fail_cnt; + struct nvme_additional_smart_log_item erase_fail_cnt; + struct nvme_additional_smart_log_item wear_leveling_cnt; + struct nvme_additional_smart_log_item e2e_err_cnt; + struct nvme_additional_smart_log_item crc_err_cnt; + struct nvme_additional_smart_log_item timed_workload_media_wear; + struct nvme_additional_smart_log_item timed_workload_host_reads; + struct nvme_additional_smart_log_item timed_workload_timer; + struct nvme_additional_smart_log_item thermal_throttle_status; + struct nvme_additional_smart_log_item retry_buffer_overflow_cnt; + struct nvme_additional_smart_log_item pll_lock_loss_cnt; + struct nvme_additional_smart_log_item nand_bytes_written; + struct nvme_additional_smart_log_item host_bytes_written; + struct nvme_additional_smart_log_item raid_recover_cnt; /* errors which can be recovered by RAID */ + struct nvme_additional_smart_log_item prog_timeout_cnt; + struct nvme_additional_smart_log_item erase_timeout_cnt; + struct nvme_additional_smart_log_item read_timeout_cnt; + struct nvme_additional_smart_log_item read_ecc_cnt; /* retry cnt */ + struct nvme_additional_smart_log_item non_media_crc_err_cnt; + struct nvme_additional_smart_log_item compression_path_err_cnt; + struct nvme_additional_smart_log_item out_of_space_flag; + struct nvme_additional_smart_log_item physical_usage_ratio; + struct nvme_additional_smart_log_item grown_bb; /* grown bad block */ }; int nvme_query_cap(int fd, __u32 nsid, __u32 data_len, void *data) { - int rc = 0; - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_query_cap_info, - .nsid = nsid, - .addr = (__u64)(uintptr_t) data, - .data_len = data_len, - }; - - rc = ioctl(fd, SFX_GET_FREESPACE, data); - return rc == 0 ? 0 : nvme_submit_admin_passthru(fd, &cmd, NULL); + int rc = 0; + struct nvme_passthru_cmd cmd = { + .opcode = nvme_admin_query_cap_info, + .nsid = nsid, + .addr = (__u64)(uintptr_t) data, + .data_len = data_len, + }; + + rc = ioctl(fd, SFX_GET_FREESPACE, data); + return rc ? nvme_submit_admin_passthru(fd, &cmd, NULL) : 0; } + int nvme_change_cap(int fd, __u32 nsid, __u64 capacity) { struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_change_cap, - .nsid = nsid, - .cdw10 = (capacity & 0xffffffff), - .cdw11 = (capacity >> 32), + .opcode = nvme_admin_change_cap, + .nsid = nsid, + .cdw10 = (capacity & 0xffffffff), + .cdw11 = (capacity >> 32), }; return nvme_submit_admin_passthru(fd, &cmd, NULL); @@ -149,10 +157,10 @@ int nvme_change_cap(int fd, __u32 nsid, __u64 capacity) int nvme_sfx_set_features(int fd, __u32 nsid, __u32 fid, __u32 value) { struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_sfx_set_features, - .nsid = nsid, - .cdw10 = fid, - .cdw11 = value, + .opcode = nvme_admin_sfx_set_features, + .nsid = nsid, + .cdw10 = fid, + .cdw11 = value, }; return nvme_submit_admin_passthru(fd, &cmd, NULL); @@ -161,16 +169,15 @@ int nvme_sfx_set_features(int fd, __u32 nsid, __u32 fid, __u32 value) int nvme_sfx_get_features(int fd, __u32 nsid, __u32 fid, __u32 *result) { int err = 0; - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_sfx_get_features, - .nsid = nsid, - .cdw10 = fid, + struct nvme_passthru_cmd cmd = { + .opcode = nvme_admin_sfx_get_features, + .nsid = nsid, + .cdw10 = fid, }; err = nvme_submit_admin_passthru(fd, &cmd, NULL); - if (!err && result) { + if (!err && result) *result = cmd.result; - } return err; } @@ -398,11 +405,11 @@ static void show_sfx_smart_log(struct nvme_additional_smart_log *smart, static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { struct nvme_additional_smart_log smart_log; - char *desc = "Get ScaleFlux vendor specific additional smart log (optionally, "\ - "for the specified namespace), and show it."; + char *desc = + "Get ScaleFlux vendor specific additional smart log (optionally, for the specified namespace), and show it."; const char *namespace = "(optional) desired namespace"; const char *raw = "dump output in binary format"; - const char *json= "Dump output in json format"; + const char *json = "Dump output in json format"; struct nvme_dev *dev; struct config { __u32 namespace_id; @@ -438,14 +445,14 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, dev->name); else d_raw((unsigned char *)&smart_log, sizeof(smart_log)); - } - else if (err > 0) + } else if (err > 0) { nvme_show_status(err); + } dev_close(dev); return err; } -struct __attribute__((__packed__)) sfx_lat_stats_vanda { +struct __packed sfx_lat_stats_vanda { __u16 maj; __u16 min; __u32 bucket_1[32]; /* 0~1ms, step 32us */ @@ -456,7 +463,7 @@ struct __attribute__((__packed__)) sfx_lat_stats_vanda { __u32 bucket_6[1]; /* 4s+, specifically 4096ms+ */ }; -struct __attribute__((__packed__)) sfx_lat_stats_myrtle { +struct __packed sfx_lat_stats_myrtle { __u16 maj; __u16 min; __u32 bucket_1[64]; /* 0us~63us, step 1us */ @@ -482,7 +489,7 @@ struct __attribute__((__packed__)) sfx_lat_stats_myrtle { }; -struct __attribute__((__packed__)) sfx_lat_status_ver { +struct __packed sfx_lat_status_ver { __u16 maj; __u16 min; }; @@ -646,23 +653,22 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct sizeof(stats), (void *)&stats); if (!err) { if ((stats.ver.maj == VANDA_MAJOR_IDX) && (stats.ver.min == VANDA_MINOR_IDX)) { - if (!cfg.raw_binary) { + if (!cfg.raw_binary) show_lat_stats_vanda(&stats.vanda, cfg.write); - } else { + else d_raw((unsigned char *)&stats.vanda, sizeof(struct sfx_lat_stats_vanda)); - } } else if ((stats.ver.maj == MYRTLE_MAJOR_IDX) && (stats.ver.min == MYRTLE_MINOR_IDX)) { - if (!cfg.raw_binary) { + if (!cfg.raw_binary) show_lat_stats_myrtle(&stats.myrtle, cfg.write); - } else { + else d_raw((unsigned char *)&stats.myrtle, sizeof(struct sfx_lat_stats_myrtle)); - } } else { printf("ScaleFlux IO %s Command Latency Statistics Invalid Version Maj %d Min %d\n", cfg.write ? "Write" : "Read", stats.ver.maj, stats.ver.min); } - } else if (err > 0) + } else if (err > 0) { nvme_show_status(err); + } dev_close(dev); return err; } @@ -697,7 +703,7 @@ static int get_bb_table(int fd, __u32 nsid, unsigned char *buf, __u64 size) { if (fd < 0 || !buf || size != 256*4096*sizeof(unsigned char)) { fprintf(stderr, "Invalid Param \r\n"); - return EINVAL; + return -EINVAL; } return sfx_nvme_get_log(fd, nsid, SFX_LOG_BBT, size, (void *)buf); @@ -731,7 +737,7 @@ static void bd_table_show(unsigned char *bd_table, __u64 table_size) remap_gbb_count = *((__u32 *)(bd_table + 4 * sizeof(__u32))); bb_elem = (__u64 *)(bd_table + 5 * sizeof(__u32)); - printf("Bad Block Table \n"); + printf("Bad Block Table\n"); printf("MF_BB_COUNT: %u\n", mf_bb_count); printf("GROWN_BB_COUNT: %u\n", grown_bb_count); printf("TOTAL_BB_COUNT: %u\n", total_bb_count); @@ -792,7 +798,7 @@ static int sfx_get_bad_block(int argc, char **argv, struct command *cmd, struct err = get_bb_table(dev_fd(dev), 0xffffffff, data_buf, buf_size); if (err < 0) { perror("get-bad-block"); - } else if (err != 0) { + } else if (err) { nvme_show_status(err); } else { bd_table_show(data_buf, buf_size); @@ -816,6 +822,7 @@ static void show_cap_info(struct sfx_freespace_ctx *ctx) printf("used provisioned capacity:%5lluGB(0x%"PRIx64")\n", IDEMA_CAP2GB(ctx->phy_space) - IDEMA_CAP2GB(ctx->free_space), (uint64_t)(ctx->phy_space - ctx->free_space)); + printf("map_unit :0x%"PRIx64"K\n", (uint64_t)(ctx->map_unit * 4)); } static int query_cap_info(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -845,11 +852,10 @@ static int query_cap_info(int argc, char **argv, struct command *cmd, struct plu } if (!err) { - if (!cfg.raw_binary) { + if (!cfg.raw_binary) show_cap_info(&ctx); - } else { + else d_raw((unsigned char *)&ctx, sizeof(ctx)); - } } dev_close(dev); return err; @@ -864,9 +870,8 @@ static int change_sanity_check(int fd, __u64 trg_in_4k, int *shrink) __u64 provisoned_cap_4k = 0; int extend = 0; - if (nvme_query_cap(fd, 0xffffffff, sizeof(freespace_ctx), &freespace_ctx)) { - return -1; - } + if (nvme_query_cap(fd, 0xffffffff, sizeof(freespace_ctx), &freespace_ctx)) + return -1; /* * capacity illegal check @@ -877,13 +882,12 @@ static int change_sanity_check(int fd, __u64 trg_in_4k, int *shrink) trg_in_4k > ((__u64)provisoned_cap_4k * 4)) { fprintf(stderr, "WARNING: Only support 1.0~4.0 x provisoned capacity!\n"); - if (trg_in_4k < provisoned_cap_4k) { + if (trg_in_4k < provisoned_cap_4k) fprintf(stderr, "WARNING: The target capacity is less than 1.0 x provisioned capacity!\n"); - } else { + else fprintf(stderr, "WARNING: The target capacity is larger than 4.0 x provisioned capacity!\n"); - } return -1; } if (trg_in_4k > ((__u64)provisoned_cap_4k*4)) { @@ -893,7 +897,7 @@ static int change_sanity_check(int fd, __u64 trg_in_4k, int *shrink) /* * check whether mem enough if extend - * */ + */ cur_in_4k = freespace_ctx.user_space >> (SFX_PAGE_SHIFT - SECTOR_SHIFT); extend = (cur_in_4k <= trg_in_4k); if (extend) { @@ -904,10 +908,9 @@ static int change_sanity_check(int fd, __u64 trg_in_4k, int *shrink) mem_need = (trg_in_4k - cur_in_4k) * 8; if (s_info.freeram <= 10 || mem_need > s_info.freeram) { fprintf(stderr, - "WARNING: Free memory is not enough! " - "Please drop cache or extend more memory and retry\n" - "WARNING: Memory needed is %"PRIu64", free memory is %"PRIu64"\n", - (uint64_t)mem_need, (uint64_t)s_info.freeram); + "WARNING: Free memory is not enough! Please drop cache or extend more memory and retry\n" + "WARNING: Memory needed is %"PRIu64", free memory is %"PRIu64"\n", + (uint64_t)mem_need, (uint64_t)s_info.freeram); return -1; } } @@ -926,6 +929,7 @@ static int change_sanity_check(int fd, __u64 trg_in_4k, int *shrink) static int sfx_confirm_change(const char *str) { unsigned char confirm; + fprintf(stderr, "WARNING: %s.\n" "Use the force [--force] option to suppress this warning.\n", str); @@ -935,7 +939,7 @@ static int sfx_confirm_change(const char *str) fprintf(stderr, "Cancled.\n"); return 0; } - fprintf(stderr, "Sending operation ... \n"); + fprintf(stderr, "Sending operation ...\n"); return 1; } @@ -993,11 +997,11 @@ static int change_cap(int argc, char **argv, struct command *cmd, struct plugin } err = nvme_change_cap(dev_fd(dev), 0xffffffff, cap_in_4k); - if (err < 0) + if (err < 0) { perror("sfx-change-cap"); - else if (err != 0) + } else if (err) { nvme_show_status(err); - else { + } else { printf("ScaleFlux change-capacity: success\n"); ioctl(dev_fd(dev), BLKRRPART); } @@ -1017,7 +1021,7 @@ static int sfx_verify_chr(int fd) if (!S_ISCHR(nvme_stat.st_mode)) { fprintf(stderr, "Error: requesting clean card on non-controller handle\n"); - return ENOTBLK; + return -ENOTBLK; } return 0; } @@ -1041,13 +1045,12 @@ static int sfx_clean_card(int fd) char *sfx_feature_to_string(int feature) { switch (feature) { - case SFX_FEAT_ATOMIC: - return "ATOMIC"; - case SFX_FEAT_UP_P_CAP: - return "UPDATE_PROVISION_CAPACITY"; - - default: - return "Unknown"; + case SFX_FEAT_ATOMIC: + return "ATOMIC"; + case SFX_FEAT_UP_P_CAP: + return "UPDATE_PROVISION_CAPACITY"; + default: + return "Unknown"; } } @@ -1093,7 +1096,7 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl if (!cfg.feature_id) { fprintf(stderr, "feature-id required param\n"); dev_close(dev); - return EINVAL; + return -EINVAL; } if (cfg.feature_id == SFX_FEAT_CLR_CARD) { @@ -1107,7 +1110,7 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl } - if (cfg.feature_id == SFX_FEAT_ATOMIC && cfg.value != 0) { + if (cfg.feature_id == SFX_FEAT_ATOMIC && cfg.value) { if (cfg.namespace_id != 0xffffffff) { err = nvme_identify_ns(dev_fd(dev), cfg.namespace_id, &ns); @@ -1125,14 +1128,14 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl if ((ns.flbas & 0xf) != 1) { printf("Please change-sector size to 4K, then retry\n"); dev_close(dev); - return EFAULT; + return -EFAULT; } } } else if (cfg.feature_id == SFX_FEAT_UP_P_CAP) { if (cfg.value <= 0) { fprintf(stderr, "Invalid Param\n"); dev_close(dev); - return EINVAL; + return -EINVAL; } /*Warning for change pacp by GB*/ @@ -1153,8 +1156,9 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl } else if (!err) { printf("ScaleFlux set-feature:%#02x (%s), value:%d\n", cfg.feature_id, sfx_feature_to_string(cfg.feature_id), cfg.value); - } else if (err > 0) + } else if (err > 0) { nvme_show_status(err); + } dev_close(dev); return err; @@ -1192,7 +1196,7 @@ static int sfx_get_feature(int argc, char **argv, struct command *cmd, struct pl if (!cfg.feature_id) { fprintf(stderr, "feature-id required param\n"); dev_close(dev); - return EINVAL; + return -EINVAL; } err = nvme_sfx_get_features(dev_fd(dev), cfg.namespace_id, @@ -1204,10 +1208,481 @@ static int sfx_get_feature(int argc, char **argv, struct command *cmd, struct pl } else if (!err) { printf("ScaleFlux get-feature:%02x (%s), value:%d\n", cfg.feature_id, sfx_feature_to_string(cfg.feature_id), result); - } else if (err > 0) + } else if (err > 0) { nvme_show_status(err); + } + + dev_close(dev); + return err; + +} + +static int nvme_parse_evtlog(void *pevent_log_info, __u32 log_len, char *output) +{ + __u32 offset = 0; + __u32 length = log_len; + __u16 fw_core; + __u64 fw_time; + __u8 code_level; + __u8 code_type; + char str_buffer[512]; + __u32 str_pos; + FILE *fd; + int err = 0; + + enum sfx_evtlog_level { + sfx_evtlog_level_warning, + sfx_evtlog_level_error, + }; + + const char *sfx_evtlog_warning[4] = { + "RESERVED", + "TOO_MANY_BB", + "LOW_SPACE", + "HIGH_TEMPERATURE" + }; + + const char *sfx_evtlog_error[14] = { + "RESERVED", + "HAS_ASSERT", + "HAS_PANIC_DUMP", + "INVALID_FORMAT_CAPACITY", + "MAT_FAILED", + "FREEZE_DUE_TO_RECOVERY_FAILED", + "RFS_BROKEN", + "MEDIA_ERR_ON_PAGE_IN", + "MEDIA_ERR_ON_MPAGE_HEADER", + "CAPACITOR_BROKEN", + "READONLY_DUE_TO_RECOVERY_FAILED", + "RD_ERR_IN_GSD_RECOVERY", + "RD_ERR_ON_PF_RECOVERY", + "MEDIA_ERR_ON_FULL_RECOVERY" + }; + + struct sfx_nvme_evtlog_info { + __u16 time_stamp[4]; + __u64 magic1; + __u8 reverse[10]; + char evt_name[32]; + __u64 magic2; + char fw_ver[24]; + char bl2_ver[32]; + __u16 code; + __u16 assert_id; + } __packed; + + struct sfx_nvme_evtlog_info *info = NULL; + + fd = fopen(output, "w+"); + if (!fd) { + fprintf(stderr, "Failed to open %s file to write\n", output); + err = ENOENT; + goto ret; + } + + while (length > 0) { + info = (struct sfx_nvme_evtlog_info *)(pevent_log_info + offset); + + if ((info->magic1 == 0x474F4C545645) && + (info->magic2 == 0x38B0B3ABA9BA)) { + + memset(str_buffer, 0, 512); + str_pos = 0; + + fw_core = info->time_stamp[3]; + snprintf(str_buffer + str_pos, 16, "[%d-", fw_core); + str_pos = strlen(str_buffer); + + fw_time = ((__u64)info->time_stamp[2] << 32) + ((__u64)info->time_stamp[1] << 16) + (__u64)info->time_stamp[0]; + convert_ts(fw_time, str_buffer + str_pos); + str_pos = strlen(str_buffer); + + strcpy(str_buffer + str_pos, "] event-log:\n"); + str_pos = strlen(str_buffer); + + snprintf(str_buffer + str_pos, 128, + " > fw_version: %s\n > bl2_version: %s\n", + info->fw_ver, info->bl2_ver); + str_pos = strlen(str_buffer); + + code_level = (info->code & 0x100) >> 8; + code_type = (info->code % 0x100); + if (code_level == sfx_evtlog_level_warning) { + snprintf(str_buffer + str_pos, 128, + " > error_str: [WARNING][%s]\n\n", + sfx_evtlog_warning[code_type]); + } else { + if (info->assert_id) + snprintf(str_buffer + str_pos, 128, + " > error_str: [ERROR][%s]\n > assert_id: %d\n\n", + sfx_evtlog_error[code_type], info->assert_id); + else + snprintf(str_buffer + str_pos, 128, + " > error_str: [ERROR][%s]\n\n", + sfx_evtlog_error[code_type]); + } + str_pos = strlen(str_buffer); + + if (fwrite(str_buffer, 1, str_pos, fd) != str_pos) { + fprintf(stderr, "Failed to write parse result to output file\n"); + goto close_fd; + } + } + + offset++; + length--; + + if (!(offset % (log_len / 100)) || (offset == log_len)) + util_spinner("Parse", (float) (offset) / (float) (log_len)); + } + + printf("\nParse-evtlog: Success\n"); + +close_fd: + fclose(fd); +ret: + return err; +} + +static int nvme_dump_evtlog(struct nvme_dev *dev, __u32 namespace_id, __u32 storage_medium, + char *file, bool parse, char *output) +{ + struct nvme_persistent_event_log *pevent; + void *pevent_log_info; + __u8 lsp_base; + __u32 offset = 0; + __u32 length = 0; + __u32 log_len; + __u32 single_len; + bool huge; + int err = 0; + FILE *fd = NULL; + struct nvme_get_log_args args = { + .args_size = sizeof(args), + .fd = dev_fd(dev), + .lid = NVME_LOG_LID_PERSISTENT_EVENT, + .nsid = namespace_id, + .lpo = NVME_LOG_LPO_NONE, + .lsp = NVME_LOG_LSP_NONE, + .lsi = NVME_LOG_LSI_NONE, + .rae = false, + .uuidx = NVME_UUID_NONE, + .csi = NVME_CSI_NVM, + .ot = false, + .len = 0, + .log = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + + if (!storage_medium) { + lsp_base = 0; + single_len = 64 * 1024 - 4; + } else { + lsp_base = 4; + single_len = 32 * 1024; + } + + pevent = calloc(sizeof(*pevent), sizeof(__u8)); + if (!pevent) { + err = -ENOMEM; + goto ret; + } + + args.lsp = lsp_base + NVME_PEVENT_LOG_RELEASE_CTX; + args.log = pevent; + args.len = sizeof(*pevent); + + err = nvme_get_log(&args); + if (err) { + fprintf(stderr, "Unable to get evtlog lsp=0x%x, ret = 0x%x\n", args.lsp, err); + goto free_pevent; + } + + args.lsp = lsp_base + NVME_PEVENT_LOG_EST_CTX_AND_READ; + err = nvme_get_log(&args); + if (err) { + fprintf(stderr, "Unable to get evtlog lsp=0x%x, ret = 0x%x\n", args.lsp, err); + goto free_pevent; + } + + log_len = le64_to_cpu(pevent->tll); + if (log_len % 4) + log_len = (log_len / 4 + 1) * 4; + + pevent_log_info = nvme_alloc(single_len, &huge); + if (!pevent_log_info) { + err = -ENOMEM; + goto free_pevent; + } + + fd = fopen(file, "wb+"); + if (!fd) { + fprintf(stderr, "Failed to open %s file to write\n", file); + err = ENOENT; + goto free; + } + + args.lsp = lsp_base + NVME_PEVENT_LOG_READ; + args.log = pevent_log_info; + length = log_len; + while (length > 0) { + args.lpo = offset; + if (length > single_len) { + args.len = single_len; + } else { + memset(args.log, 0, args.len); + args.len = length; + } + err = nvme_get_log(&args); + if (err) { + fprintf(stderr, "Unable to get evtlog offset=0x%x len 0x%x ret = 0x%x\n", offset, args.len, err); + goto close_fd; + } + + if (fwrite(args.log, 1, args.len, fd) != args.len) { + fprintf(stderr, "Failed to write evtlog to file\n"); + goto close_fd; + } + + offset += args.len; + length -= args.len; + util_spinner("Parse", (float) (offset) / (float) (log_len)); + } + + printf("\nDump-evtlog: Success\n"); + + if (parse) { + nvme_free(pevent_log_info, huge); + pevent_log_info = nvme_alloc(log_len, &huge); + if (!pevent_log_info) { + fprintf(stderr, "Failed to alloc enough memory 0x%x to parse evtlog\n", log_len); + err = -ENOMEM; + goto close_fd; + } + + fclose(fd); + fd = fopen(file, "rb"); + if (!fd) { + fprintf(stderr, "Failed to open %s file to read\n", file); + err = ENOENT; + goto free; + } + if (fread(pevent_log_info, 1, log_len, fd) != log_len) { + fprintf(stderr, "Failed to read evtlog to buffer\n"); + goto close_fd; + } + + err = nvme_parse_evtlog(pevent_log_info, log_len, output); + } + +close_fd: + fclose(fd); +free: + nvme_free(pevent_log_info, huge); +free_pevent: + free(pevent); +ret: + return err; +} + +static int sfx_dump_evtlog(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + char *desc = "dump evtlog into file and parse"; + const char *file = "evtlog file(required)"; + const char *namespace_id = "desired namespace"; + const char *storage_medium = "evtlog storage medium\n" + "0: nand(default) 1: nor"; + const char *parse = "parse error & warning evtlog from evtlog file"; + const char *output = "parse result output file"; + struct nvme_dev *dev; + int err = 0; + + struct config { + char *file; + __u32 namespace_id; + __u32 storage_medium; + bool parse; + char *output; + }; + struct config cfg = { + .file = NULL, + .namespace_id = 0xffffffff, + .storage_medium = 0, + .parse = false, + .output = NULL, + }; + + OPT_ARGS(opts) = { + OPT_FILE("file", 'f', &cfg.file, file), + OPT_UINT("namespace_id", 'n', &cfg.namespace_id, namespace_id), + OPT_UINT("storage_medium", 's', &cfg.storage_medium, storage_medium), + OPT_FLAG("parse", 'p', &cfg.parse, parse), + OPT_FILE("output", 'o', &cfg.output, output), + OPT_END() + }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + goto ret; + + if (!cfg.file) { + fprintf(stderr, "file required param\n"); + err = EINVAL; + goto close_dev; + } + + if (cfg.parse && !cfg.output) { + fprintf(stderr, "output file required if evtlog need be parsed\n"); + err = EINVAL; + goto close_dev; + } + err = nvme_dump_evtlog(dev, cfg.namespace_id, cfg.storage_medium, cfg.file, cfg.parse, cfg.output); + +close_dev: dev_close(dev); +ret: + return err; +} + +static int nvme_expand_cap(struct nvme_dev *dev, __u32 namespace_id, __u64 namespace_size, + __u64 namespace_cap, __u32 lbaf, __u32 units) +{ + struct dirent **devices; + char dev_name[32] = ""; + int i = 0; + int num = 0; + int err = 0; + + struct sfx_expand_cap_info { + __u64 namespace_size; + __u64 namespace_cap; + __u8 reserve[10]; + __u8 lbaf; + __u8 reserve1[5]; + } __packed; + + if (S_ISCHR(dev->direct.stat.st_mode)) + snprintf(dev_name, 32, "%sn%u", dev->name, namespace_id); + else + strcpy(dev_name, dev->name); + + num = scandir("/dev", &devices, nvme_namespace_filter, alphasort); + if (num <= 0) { + err = num; + goto ret; + } + + if (strcmp(dev_name, devices[num-1]->d_name)) { + fprintf(stderr, "Expand namespace not the last one\n"); + err = EINVAL; + goto free_devices; + } + + if (!units) { + namespace_size = IDEMA_CAP(namespace_size) / (1 << (lbaf * 3)); + namespace_cap = IDEMA_CAP(namespace_cap) / (1 << (lbaf * 3)); + } + + struct sfx_expand_cap_info info = { + .namespace_size = namespace_size, + .namespace_cap = namespace_cap, + .lbaf = lbaf, + }; + + struct nvme_passthru_cmd cmd = { + .opcode = nvme_admin_ns_mgmt, + .nsid = namespace_id, + .addr = (__u64)(uintptr_t)&info, + .data_len = sizeof(info), + .cdw10 = 0x0e, + }; + + err = nvme_submit_admin_passthru(dev_fd(dev), &cmd, NULL); + if (err) { + fprintf(stderr, "Create ns failed\n"); + nvme_show_status(err); + goto free_devices; + } + +free_devices: + for (i = 0; i < num; i++) + free(devices[i]); + free(devices); +ret: return err; +} + +static int sfx_expand_cap(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + char *desc = "expand capacity"; + const char *namespace_id = "desired namespace"; + const char *namespace_size = "namespace size(required)"; + const char *namespace_cap = "namespace capacity(required)"; + const char *lbaf = "LBA format to apply\n" + "0: 512(default) 1: 4096"; + const char *units = "namespace size/capacity units\n" + "0: GB(default) 1: LBA"; + struct nvme_dev *dev; + int err = 0; + + struct config { + __u32 namespace_id; + __u64 namespace_size; + __u64 namespace_cap; + __u32 lbaf; + __u32 units; + }; + struct config cfg = { + .namespace_id = 0xffffffff, + .lbaf = 0, + .units = 0, + }; + + OPT_ARGS(opts) = { + OPT_UINT("namespace_id", 'n', &cfg.namespace_id, namespace_id), + OPT_LONG("namespace_size", 's', &cfg.namespace_size, namespace_size), + OPT_LONG("namespace_cap", 'c', &cfg.namespace_cap, namespace_cap), + OPT_UINT("lbaf", 'l', &cfg.lbaf, lbaf), + OPT_UINT("units", 'u', &cfg.units, units), + OPT_END() + }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + goto ret; + if (cfg.namespace_id == 0xffffffff) { + if (S_ISCHR(dev->direct.stat.st_mode)) { + fprintf(stderr, "namespace_id or blk device required\n"); + err = EINVAL; + goto ret; + } else { + cfg.namespace_id = atoi(&dev->name[strlen(dev->name) - 1]); + } + } + + if (!cfg.namespace_size) { + fprintf(stderr, "namespace_size required param\n"); + err = EINVAL; + goto close_dev; + } + + if (!cfg.namespace_cap) { + fprintf(stderr, "namespace_cap required param\n"); + err = EINVAL; + goto close_dev; + } + + err = nvme_expand_cap(dev, cfg.namespace_id, cfg.namespace_size, cfg.namespace_cap, cfg.lbaf, cfg.units); + if (err) + goto close_dev; + + printf("%s: Success, create nsid:%d\n", cmd->name, cfg.namespace_id); + +close_dev: + dev_close(dev); +ret: + return err; } diff --git a/plugins/scaleflux/sfx-nvme.h b/plugins/scaleflux/sfx-nvme.h index 0b95d92..53e2217 100644 --- a/plugins/scaleflux/sfx-nvme.h +++ b/plugins/scaleflux/sfx-nvme.h @@ -16,6 +16,8 @@ PLUGIN(NAME("sfx", "ScaleFlux vendor specific extensions", NVME_VERSION), ENTRY("change-cap", "Dynamic change capacity", change_cap) ENTRY("set-feature", "Set a feature", sfx_set_feature) ENTRY("get-feature", "Get a feature", sfx_get_feature) + ENTRY("dump-evtlog", "dump evtlog into file and parse warning & error log", sfx_dump_evtlog) + ENTRY("expand-cap", "expand the last namespace capacity lossless", sfx_expand_cap) ) ); diff --git a/plugins/seagate/seagate-nvme.c b/plugins/seagate/seagate-nvme.c index 1bd30a5..0f4f59d 100644 --- a/plugins/seagate/seagate-nvme.c +++ b/plugins/seagate/seagate-nvme.c @@ -54,79 +54,54 @@ static char *log_pages_supp_print(__u32 pageID) switch (pageID) { case 0x01: return "ERROR_INFORMATION"; - break; case 0x02: return "SMART_INFORMATION"; - break; case 0x03: return "FW_SLOT_INFORMATION"; - break; case 0x04: return "CHANGED_NAMESPACE_LIST"; - break; case 0x05: return "COMMANDS_SUPPORTED_AND_EFFECTS"; - break; case 0x06: return "DEVICE_SELF_TEST"; - break; case 0x07: return "TELEMETRY_HOST_INITIATED"; - break; case 0x08: return "TELEMETRY_CONTROLLER_INITIATED"; - break; case 0xC0: return "VS_MEDIA_SMART_LOG"; - break; case 0xC1: return "VS_DEBUG_LOG1"; - break; case 0xC2: return "VS_SEC_ERROR_LOG_PAGE"; - break; case 0xC3: return "VS_LIFE_TIME_DRIVE_HISTORY"; - break; case 0xC4: return "VS_EXTENDED_SMART_INFO"; - break; case 0xC5: return "VS_LIST_SUPPORTED_LOG_PAGE"; - break; case 0xC6: return "VS_POWER_MONITOR_LOG_PAGE"; - break; case 0xC7: return "VS_CRITICAL_EVENT_LOG_PAGE"; - break; case 0xC8: return "VS_RECENT_DRIVE_HISTORY"; - break; case 0xC9: return "VS_SEC_ERROR_LOG_PAGE"; - break; case 0xCA: return "VS_LIFE_TIME_DRIVE_HISTORY"; - break; case 0xCB: return "VS_PCIE_ERROR_LOG_PAGE"; - break; case 0xCF: return "DRAM Supercap SMART Attributes"; - break; case 0xD6: return "VS_OEM2_WORK_LOAD"; - break; case 0xD7: return "VS_OEM2_FW_SECURITY"; - break; case 0xD8: return "VS_OEM2_REVISION"; - break; default: return "UNKNOWN"; - break; } } @@ -136,9 +111,8 @@ static int stx_is_jag_pan(char *devMN) for (int i = 0; i < STX_NUM_LEGACY_DRV; i++) { match_found = strncmp(devMN, stx_jag_pan_mn[i], strlen(stx_jag_pan_mn[i])); - if (match_found == 0) { + if (!match_found) break; - } } return match_found; @@ -157,6 +131,7 @@ static void json_log_pages_supp(log_page_map *logPageMap) for (i = 0; i < le32_to_cpu(logPageMap->NumLogPages); i++) { struct json_object *lbaf = json_create_object(); + json_object_add_value_int(lbaf, "logpage_id", le32_to_cpu(logPageMap->LogPageEntry[i].LogPageID)); json_object_add_value_string(lbaf, "logpage_name", @@ -199,9 +174,9 @@ static int log_pages_supp(int argc, char **argv, struct command *cmd, sizeof(logPageMap), &logPageMap); if (!err) { if (strcmp(cfg.output_format, "json")) { - printf ("Seagate Supported Log-pages count :%d\n", + printf("Seagate Supported Log-pages count :%d\n", le32_to_cpu(logPageMap.NumLogPages)); - printf ("%-15s %-30s\n", "LogPage-Id", "LogPage-Name"); + printf("%-15s %-30s\n", "LogPage-Id", "LogPage-Name"); for (fmt = 0; fmt < 45; fmt++) printf("-"); @@ -227,154 +202,107 @@ static int log_pages_supp(int argc, char **argv, struct command *cmd, /* EOF Command for "log-pages-supp" */ - /*************************************** -* Extended-SMART Information -***************************************/ + * Extended-SMART Information + ***************************************/ static char *print_ext_smart_id(__u8 attrId) { switch (attrId) { case VS_ATTR_ID_SOFT_READ_ERROR_RATE: return "Soft ECC error count"; - break; case VS_ATTR_ID_REALLOCATED_SECTOR_COUNT: return "Bad NAND block count"; - break; case VS_ATTR_ID_POWER_ON_HOURS: return "Power On Hours"; - break; case VS_ATTR_ID_POWER_FAIL_EVENT_COUNT: return "Power Fail Event Count"; - break; case VS_ATTR_ID_DEVICE_POWER_CYCLE_COUNT: return "Device Power Cycle Count"; - break; case VS_ATTR_ID_RAW_READ_ERROR_RATE: return "Raw Read Error Count"; - break; case VS_ATTR_ID_GROWN_BAD_BLOCK_COUNT: return "Bad NAND block count"; - break; case VS_ATTR_ID_END_2_END_CORRECTION_COUNT: return "SSD End to end correction counts"; - break; case VS_ATTR_ID_MIN_MAX_WEAR_RANGE_COUNT: return "User data erase counts"; - break; case VS_ATTR_ID_REFRESH_COUNT: return "Refresh count"; - break; case VS_ATTR_ID_BAD_BLOCK_COUNT_USER: return "User data erase fail count"; - break; case VS_ATTR_ID_BAD_BLOCK_COUNT_SYSTEM: return "System area erase fail count"; - break; case VS_ATTR_ID_THERMAL_THROTTLING_STATUS: return "Thermal throttling status and count"; - break; case VS_ATTR_ID_ALL_PCIE_CORRECTABLE_ERROR_COUNT: return "PCIe Correctable Error count"; - break; case VS_ATTR_ID_ALL_PCIE_UNCORRECTABLE_ERROR_COUNT: return "PCIe Uncorrectable Error count"; - break; case VS_ATTR_ID_INCOMPLETE_SHUTDOWN_COUNT: return "Incomplete shutdowns"; - break; case VS_ATTR_ID_GB_ERASED_LSB: return "LSB of Flash GB erased"; - break; case VS_ATTR_ID_GB_ERASED_MSB: return "MSB of Flash GB erased"; - break; case VS_ATTR_ID_LIFETIME_DEVSLEEP_EXIT_COUNT: return "LIFETIME_DEV_SLEEP_EXIT_COUNT"; - break; case VS_ATTR_ID_LIFETIME_ENTERING_PS4_COUNT: return "LIFETIME_ENTERING_PS4_COUNT"; - break; case VS_ATTR_ID_LIFETIME_ENTERING_PS3_COUNT: return "LIFETIME_ENTERING_PS3_COUNT"; - break; case VS_ATTR_ID_RETIRED_BLOCK_COUNT: return "Retired block count"; - break; case VS_ATTR_ID_PROGRAM_FAILURE_COUNT: return "Program fail count"; - break; case VS_ATTR_ID_ERASE_FAIL_COUNT: return "Erase Fail Count"; - break; case VS_ATTR_ID_AVG_ERASE_COUNT: return "System data % used"; - break; case VS_ATTR_ID_UNEXPECTED_POWER_LOSS_COUNT: return "Unexpected power loss count"; - break; case VS_ATTR_ID_WEAR_RANGE_DELTA: return "Wear range delta"; - break; case VS_ATTR_ID_SATA_INTERFACE_DOWNSHIFT_COUNT: return "PCIE_INTF_DOWNSHIFT_COUNT"; - break; case VS_ATTR_ID_END_TO_END_CRC_ERROR_COUNT: return "E2E_CRC_ERROR_COUNT"; - break; case VS_ATTR_ID_UNCORRECTABLE_READ_ERRORS: return "Uncorrectable Read Error Count"; - break; case VS_ATTR_ID_MAX_LIFE_TEMPERATURE: return "Max lifetime temperature"; - break; case VS_ATTR_ID_RAISE_ECC_CORRECTABLE_ERROR_COUNT: return "RAIS_ECC_CORRECT_ERR_COUNT"; - break; case VS_ATTR_ID_UNCORRECTABLE_RAISE_ERRORS: return "Uncorrectable RAISE error count"; - break; case VS_ATTR_ID_DRIVE_LIFE_PROTECTION_STATUS: return "DRIVE_LIFE_PROTECTION_STATUS"; - break; case VS_ATTR_ID_REMAINING_SSD_LIFE: return "Remaining SSD life"; - break; case VS_ATTR_ID_LIFETIME_WRITES_TO_FLASH_LSB: return "LSB of Physical (NAND) bytes written"; - break; case VS_ATTR_ID_LIFETIME_WRITES_TO_FLASH_MSB: return "MSB of Physical (NAND) bytes written"; - break; case VS_ATTR_ID_LIFETIME_WRITES_FROM_HOST_LSB: return "LSB of Physical (HOST) bytes written"; - break; case VS_ATTR_ID_LIFETIME_WRITES_FROM_HOST_MSB: return "MSB of Physical (HOST) bytes written"; - break; case VS_ATTR_ID_LIFETIME_READS_TO_HOST_LSB: return "LSB of Physical (NAND) bytes read"; - break; case VS_ATTR_ID_LIFETIME_READS_TO_HOST_MSB: return "MSB of Physical (NAND) bytes read"; - break; case VS_ATTR_ID_FREE_SPACE: return "Free Space"; - break; case VS_ATTR_ID_TRIM_COUNT_LSB: return "LSB of Trim count"; - break; case VS_ATTR_ID_TRIM_COUNT_MSB: return "MSB of Trim count"; - break; case VS_ATTR_ID_OP_PERCENTAGE: return "OP percentage"; - break; case VS_ATTR_ID_MAX_SOC_LIFE_TEMPERATURE: return "Max lifetime SOC temperature"; - break; default: return "Un-Known"; - } + } } static __u64 smart_attribute_vs(__u16 verNo, SmartVendorSpecific attr) @@ -451,14 +379,13 @@ static void print_smart_log(__u16 verNo, SmartVendorSpecific attr, int lastAttr) hideAttr = 1; } - if ((attr.AttributeNumber != 0) && (hideAttr != 1)) { + if ((attr.AttributeNumber) && (hideAttr != 1)) { printf("%-40s", print_ext_smart_id(attr.AttributeNumber)); printf("%-15d", attr.AttributeNumber); printf(" 0x%016"PRIx64"\n", (uint64_t)smart_attribute_vs(verNo, attr)); } if (lastAttr == 1) { - sprintf(strBuf, "%s", (print_ext_smart_id(VS_ATTR_ID_GB_ERASED_LSB) + 7)); printf("%-40s", strBuf); @@ -516,7 +443,8 @@ static void json_print_smart_log(struct json_object *root, EXTENDED_SMART_INFO_T for (index = 0; index < NUMBER_EXTENDED_SMART_ATTRIBUTES; index++) { struct json_object *lbaf = json_create_object(); - if (ExtdSMARTInfo->vendorData[index].AttributeNumber != 0) { + + if (ExtdSMARTInfo->vendorData[index].AttributeNumber) { json_object_add_value_string(lbaf, "attribute_name", print_ext_smart_id(ExtdSMARTInfo->vendorData[index].AttributeNumber)); json_object_add_value_int(lbaf, "attribute_id", ExtdSMARTInfo->vendorData[index].AttributeNumber); json_object_add_value_int(lbaf, "attribute_value", smart_attribute_vs(ExtdSMARTInfo->Version, ExtdSMARTInfo->vendorData[index])); @@ -612,8 +540,9 @@ static void json_print_smart_log(struct json_object *root, EXTENDED_SMART_INFO_T static void print_smart_log_CF(vendor_log_page_CF *pLogPageCF) { __u64 currentTemp, maxTemp; + printf("\n\nSeagate DRAM Supercap SMART Attributes :\n"); - printf("%-39s %-19s \n", "Description", "Supercap Attributes"); + printf("%-39s %-19s\n", "Description", "Supercap Attributes"); printf("%-40s", "Super-cap current temperature"); currentTemp = pLogPageCF->AttrCF.SuperCapCurrentTemperature; @@ -698,7 +627,7 @@ static void json_print_smart_log_CF(struct json_object *root, vendor_log_page_CF static void print_stx_smart_log_C0(STX_EXT_SMART_LOG_PAGE_C0 *pLogPageC0) { printf("\n\nSeagate SMART Health Attributes :\n"); - printf("%-39s %-19s \n", "Description", "Health Attributes"); + printf("%-39s %-19s\n", "Description", "Health Attributes"); printf("%-40s", "Physical Media Units Written"); printf(" 0x%016"PRIx64"%016"PRIx64"\n", le64_to_cpu(pLogPageC0->phyMediaUnitsWrt.MS__u64), @@ -986,7 +915,7 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi err = parse_and_open(&dev, argc, argv, desc, opts); if (err) { - printf ("\nDevice not found \n"); + printf("\nDevice not found\n"); return -1; } @@ -1008,12 +937,11 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi return err; } - if (stx_is_jag_pan(modelNo) == 0) { - + if (!stx_is_jag_pan(modelNo)) { err = nvme_get_log_simple(dev_fd(dev), 0xC4, sizeof(ExtdSMARTInfo), &ExtdSMARTInfo); if (!err) { if (strcmp(cfg.output_format, "json")) { - printf("%-39s %-15s %-19s \n", "Description", "Ext-Smart-Id", "Ext-Smart-Value"); + printf("%-39s %-15s %-19s\n", "Description", "Ext-Smart-Id", "Ext-Smart-Value"); for (index = 0; index < 80; index++) printf("-"); printf("\n"); @@ -1046,15 +974,15 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi json_print_object(root, NULL); json_free_object(root); } - } else if (err > 0) + } else if (err > 0) { nvme_show_status(err); + } } else { err = nvme_get_log_simple(dev_fd(dev), 0xC0, sizeof(ehExtSmart), &ehExtSmart); if (!err) { if (strcmp(cfg.output_format, "json")) { print_stx_smart_log_C0(&ehExtSmart); - } else { lbafs_ExtSmart = json_create_object(); json_print_stx_smart_log_C0(lbafs_ExtSmart, &ehExtSmart); @@ -1075,7 +1003,7 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi sizeof(ExtdSMARTInfo), &ExtdSMARTInfo); if (!err) { if (strcmp(cfg.output_format, "json")) { - printf("%-39s %-15s %-19s \n", "Description", "Ext-Smart-Id", "Ext-Smart-Value"); + printf("%-39s %-15s %-19s\n", "Description", "Ext-Smart-Id", "Ext-Smart-Value"); for (index = 0; index < 80; index++) printf("-"); printf("\n"); @@ -1105,10 +1033,12 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi json_array_add_value_object(lbafs, lbafs_DramSmart); json_print_object(root, NULL); } - } else if (!strcmp(cfg.output_format, "json")) + } else if (!strcmp(cfg.output_format, "json")) { json_print_object(root, NULL); - } else if (err > 0) + } + } else if (err > 0) { nvme_show_status(err); + } dev_close(dev); @@ -1123,8 +1053,7 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi static void json_temp_stats(__u32 temperature, __u32 PcbTemp, __u32 SocTemp, __u32 maxTemperature, __u32 MaxSocTemp, __u32 cf_err, __u32 scCurrentTemp, __u32 scMaxTem) { - struct json_object *root; - root = json_create_object(); + struct json_object *root = json_create_object(); json_object_add_value_int(root, "Current temperature", temperature); json_object_add_value_int(root, "Current PCB temperature", PcbTemp); @@ -1167,7 +1096,7 @@ static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin err = parse_and_open(&dev, argc, argv, desc, opts); if (err) { - printf ("\nDevice not found \n");; + printf("\nDevice not found\n"); return -1; } @@ -1239,19 +1168,16 @@ static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin ***************************************/ static void print_vs_pcie_error_log(pcie_error_log_page pcieErrorLog) { - __u32 correctPcieEc = 0; - __u32 uncorrectPcieEc = 0; - correctPcieEc = pcieErrorLog.BadDllpErrCnt + pcieErrorLog.BadTlpErrCnt - + pcieErrorLog.RcvrErrCnt + pcieErrorLog.ReplayTOErrCnt - + pcieErrorLog.ReplayNumRolloverErrCnt; - - uncorrectPcieEc = pcieErrorLog.FCProtocolErrCnt + pcieErrorLog.DllpProtocolErrCnt - + pcieErrorLog.CmpltnTOErrCnt + pcieErrorLog.RcvrQOverflowErrCnt - + pcieErrorLog.UnexpectedCplTlpErrCnt + pcieErrorLog.CplTlpURErrCnt - + pcieErrorLog.CplTlpCAErrCnt + pcieErrorLog.ReqCAErrCnt - + pcieErrorLog.ReqURErrCnt + pcieErrorLog.EcrcErrCnt - + pcieErrorLog.MalformedTlpErrCnt + pcieErrorLog.CplTlpPoisonedErrCnt - + pcieErrorLog.MemRdTlpPoisonedErrCnt; + __u32 correctPcieEc = pcieErrorLog.BadDllpErrCnt + pcieErrorLog.BadTlpErrCnt + + pcieErrorLog.RcvrErrCnt + pcieErrorLog.ReplayTOErrCnt + + pcieErrorLog.ReplayNumRolloverErrCnt; + __u32 uncorrectPcieEc = pcieErrorLog.FCProtocolErrCnt + pcieErrorLog.DllpProtocolErrCnt + + pcieErrorLog.CmpltnTOErrCnt + pcieErrorLog.RcvrQOverflowErrCnt + + pcieErrorLog.UnexpectedCplTlpErrCnt + pcieErrorLog.CplTlpURErrCnt + + pcieErrorLog.CplTlpCAErrCnt + pcieErrorLog.ReqCAErrCnt + + pcieErrorLog.ReqURErrCnt + pcieErrorLog.EcrcErrCnt + + pcieErrorLog.MalformedTlpErrCnt + pcieErrorLog.CplTlpPoisonedErrCnt + + pcieErrorLog.MemRdTlpPoisonedErrCnt; printf("%-45s : %u\n", "PCIe Correctable Error Count", correctPcieEc); printf("%-45s : %u\n", "PCIe Un-Correctable Error Count", uncorrectPcieEc); @@ -1279,21 +1205,17 @@ static void print_vs_pcie_error_log(pcie_error_log_page pcieErrorLog) static void json_vs_pcie_error_log(pcie_error_log_page pcieErrorLog) { - struct json_object *root; - root = json_create_object(); - __u32 correctPcieEc = 0; - __u32 uncorrectPcieEc = 0; - correctPcieEc = pcieErrorLog.BadDllpErrCnt + pcieErrorLog.BadTlpErrCnt - + pcieErrorLog.RcvrErrCnt + pcieErrorLog.ReplayTOErrCnt - + pcieErrorLog.ReplayNumRolloverErrCnt; - - uncorrectPcieEc = pcieErrorLog.FCProtocolErrCnt + pcieErrorLog.DllpProtocolErrCnt - + pcieErrorLog.CmpltnTOErrCnt + pcieErrorLog.RcvrQOverflowErrCnt - + pcieErrorLog.UnexpectedCplTlpErrCnt + pcieErrorLog.CplTlpURErrCnt - + pcieErrorLog.CplTlpCAErrCnt + pcieErrorLog.ReqCAErrCnt - + pcieErrorLog.ReqURErrCnt + pcieErrorLog.EcrcErrCnt - + pcieErrorLog.MalformedTlpErrCnt + pcieErrorLog.CplTlpPoisonedErrCnt - + pcieErrorLog.MemRdTlpPoisonedErrCnt; + struct json_object *root = json_create_object(); + __u32 correctPcieEc = pcieErrorLog.BadDllpErrCnt + pcieErrorLog.BadTlpErrCnt + + pcieErrorLog.RcvrErrCnt + pcieErrorLog.ReplayTOErrCnt + + pcieErrorLog.ReplayNumRolloverErrCnt; + __u32 uncorrectPcieEc = pcieErrorLog.FCProtocolErrCnt + pcieErrorLog.DllpProtocolErrCnt + + pcieErrorLog.CmpltnTOErrCnt + pcieErrorLog.RcvrQOverflowErrCnt + + pcieErrorLog.UnexpectedCplTlpErrCnt + pcieErrorLog.CplTlpURErrCnt + + pcieErrorLog.CplTlpCAErrCnt + pcieErrorLog.ReqCAErrCnt + + pcieErrorLog.ReqURErrCnt + pcieErrorLog.EcrcErrCnt + + pcieErrorLog.MalformedTlpErrCnt + pcieErrorLog.CplTlpPoisonedErrCnt + + pcieErrorLog.MemRdTlpPoisonedErrCnt; json_object_add_value_int(root, "PCIe Correctable Error Count", correctPcieEc); json_object_add_value_int(root, "PCIe Un-Correctable Error Count", uncorrectPcieEc); @@ -1341,7 +1263,7 @@ static int vs_pcie_error_log(int argc, char **argv, struct command *cmd, struct err = parse_and_open(&dev, argc, argv, desc, opts); if (err) { - printf ("\nDevice not found \n");; + printf("\nDevice not found\n"); return -1; } @@ -1351,13 +1273,14 @@ static int vs_pcie_error_log(int argc, char **argv, struct command *cmd, struct err = nvme_get_log_simple(dev_fd(dev), 0xCB, sizeof(pcieErrorLog), &pcieErrorLog); if (!err) { - if (strcmp(cfg.output_format, "json")) { + if (strcmp(cfg.output_format, "json")) print_vs_pcie_error_log(pcieErrorLog); - } else + else json_vs_pcie_error_log(pcieErrorLog); - } else if (err > 0) + } else if (err > 0) { nvme_show_status(err); + } dev_close(dev); return err; @@ -1384,8 +1307,8 @@ static void print_stx_vs_fw_activate_history(stx_fw_activ_history_log_page fwAct printf(" %-4d ", fwActivHis.fwActHisEnt[i].fwActivCnt); time_t t = fwActivHis.fwActHisEnt[i].timeStamp / 1000; - struct tm ts; - ts = *localtime(&t); + struct tm ts = *localtime(&t); + strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &ts); printf(" %-20s ", buf); printf("%-5" PRId64 " ", @@ -1401,7 +1324,7 @@ static void print_stx_vs_fw_activate_history(stx_fw_activ_history_log_page fwAct printf(" %-2d ", fwActivHis.fwActHisEnt[i].slotNum); printf(" 0x%02x ", fwActivHis.fwActHisEnt[i].commitActionType); - printf(" 0x%02x \n", fwActivHis.fwActHisEnt[i].result); + printf(" 0x%02x\n", fwActivHis.fwActHisEnt[i].result); } } else { printf("%s\n", "Do not have valid FW Activation History"); @@ -1410,14 +1333,13 @@ static void print_stx_vs_fw_activate_history(stx_fw_activ_history_log_page fwAct static void json_stx_vs_fw_activate_history(stx_fw_activ_history_log_page fwActivHis) { - struct json_object *root; - root = json_create_object(); + struct json_object *root = json_create_object(); __u32 i; char buf[80]; - struct json_object *historyLogPage; - historyLogPage = json_create_array(); + struct json_object *historyLogPage = json_create_array(); + json_object_add_value_array(root, "Seagate FW Activation History", historyLogPage); if (fwActivHis.numValidFwActHisEnt > 0) { @@ -1429,8 +1351,8 @@ static void json_stx_vs_fw_activate_history(stx_fw_activ_history_log_page fwActi json_object_add_value_int(lbaf, "Counter", fwActivHis.fwActHisEnt[i].fwActivCnt); time_t t = fwActivHis.fwActHisEnt[i].timeStamp / 1000; - struct tm ts; - ts = *localtime(&t); + struct tm ts = *localtime(&t); + strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &ts); printf(" %-20s ", buf); json_object_add_value_string(lbaf, "Timestamp", buf); @@ -1479,7 +1401,7 @@ static int stx_vs_fw_activate_history(int argc, char **argv, struct command *cmd err = parse_and_open(&dev, argc, argv, desc, opts); if (err < 0) { - printf ("\nDevice not found \n");; + printf("\nDevice not found\n"); return -1; } @@ -1488,13 +1410,14 @@ static int stx_vs_fw_activate_history(int argc, char **argv, struct command *cmd err = nvme_get_log_simple(dev_fd(dev), 0xC2, sizeof(fwActivHis), &fwActivHis); if (!err) { - if (strcmp(cfg.output_format, "json")) { + if (strcmp(cfg.output_format, "json")) print_stx_vs_fw_activate_history(fwActivHis); - } else + else json_stx_vs_fw_activate_history(fwActivHis); - } else if (err > 0) + } else if (err > 0) { nvme_show_status(err); + } dev_close(dev); return err; @@ -1527,7 +1450,7 @@ static int clear_fw_activate_history(int argc, char **argv, struct command *cmd, err = parse_and_open(&dev, argc, argv, desc, opts); if (err < 0) { - printf ("\nDevice not found \n"); + printf("\nDevice not found\n"); return -1; } @@ -1539,10 +1462,9 @@ static int clear_fw_activate_history(int argc, char **argv, struct command *cmd, return err; } - if (stx_is_jag_pan(modelNo) == 0) { - printf ("\nDevice does not support Clear FW Activation History \n"); + if (!stx_is_jag_pan(modelNo)) { + printf("\nDevice does not support Clear FW Activation History\n"); } else { - struct nvme_set_features_args args = { .args_size = sizeof(args), .fd = dev_fd(dev), @@ -1560,7 +1482,7 @@ static int clear_fw_activate_history(int argc, char **argv, struct command *cmd, }; err = nvme_set_features(&args); if (err) - fprintf(stderr, "%s: couldn't clear PCIe correctable errors \n", + fprintf(stderr, "%s: couldn't clear PCIe correctable errors\n", __func__); } @@ -1602,7 +1524,7 @@ static int vs_clr_pcie_correctable_errs(int argc, char **argv, struct command *c err = parse_and_open(&dev, argc, argv, desc, opts); if (err) { - printf ("\nDevice not found \n");; + printf("\nDevice not found\n"); return -1; } @@ -1615,27 +1537,27 @@ static int vs_clr_pcie_correctable_errs(int argc, char **argv, struct command *c return err; } - if (stx_is_jag_pan(modelNo) == 0) { + if (!stx_is_jag_pan(modelNo)) { err = nvme_set_features_simple(dev_fd(dev), 0xE1, 0, 0xCB, cfg.save, &result); } else { struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .fid = 0xC3, - .nsid = 0, - .cdw11 = 0x80000000, - .cdw12 = 0, - .save = 0, - .uuidx = 0, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = &result, - }; - err = nvme_set_features(&args); - if (err) - fprintf(stderr, "%s: couldn't clear PCIe correctable errors \n", __func__); + .args_size = sizeof(args), + .fd = dev_fd(dev), + .fid = 0xC3, + .nsid = 0, + .cdw11 = 0x80000000, + .cdw12 = 0, + .save = 0, + .uuidx = 0, + .cdw15 = 0, + .data_len = 0, + .data = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_set_features(&args); + if (err) + fprintf(stderr, "%s: couldn't clear PCIe correctable errors\n", __func__); } err = nvme_set_features_simple(dev_fd(dev), 0xE1, 0, 0xCB, cfg.save, &result); @@ -1651,11 +1573,11 @@ static int vs_clr_pcie_correctable_errs(int argc, char **argv, struct command *c static int get_host_tele(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Capture the Telemetry Host-Initiated Data in either " \ - "hex-dump (default) or binary format"; + const char *desc = + "Capture the Telemetry Host-Initiated Data in either hex-dump (default) or binary format"; const char *namespace_id = "desired namespace"; - const char *log_specific = "1 - controller shall capture Data representing the internal " \ - "state of the controller at the time the command is processed. " \ + const char *log_specific = "1 - controller shall capture Data representing the internal\n" + "state of the controller at the time the command is processed.\n" "0 - controller shall not update the Telemetry Host Initiated Data."; const char *raw = "output in raw format"; struct nvme_temetry_log_hdr tele_log; @@ -1706,10 +1628,11 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug d((unsigned char *)(&tele_log), sizeof(tele_log), 16, 1); } else seaget_d_raw((unsigned char *)(&tele_log), sizeof(tele_log), dump_fd); - } else if (err > 0) + } else if (err > 0) { nvme_show_status(err); - else + } else { perror("log page"); + } blkCnt = 0; @@ -1718,7 +1641,7 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug blksToGet = ((maxBlk - blkCnt) >= TELEMETRY_BLOCKS_TO_READ) ? TELEMETRY_BLOCKS_TO_READ : (maxBlk - blkCnt); - if (blksToGet == 0) { + if (!blksToGet) { dev_close(dev); return err; } @@ -1729,7 +1652,7 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug if (!log) { fprintf(stderr, "could not alloc buffer for log\n"); dev_close(dev); - return EINVAL; + return -EINVAL; } memset(log, 0, bytesToGet); @@ -1761,10 +1684,11 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug d((unsigned char *)log, bytesToGet, 16, 1); } else seaget_d_raw((unsigned char *)log, bytesToGet, dump_fd); - } else if (err > 0) + } else if (err > 0) { nvme_show_status(err); - else + } else { perror("log page"); + } blkCnt += blksToGet; @@ -1777,8 +1701,8 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Capture the Telemetry Controller-Initiated Data in either " \ - "hex-dump (default) or binary format"; + const char *desc = + "Capture the Telemetry Controller-Initiated Data in either hex-dump (default) or binary format"; const char *namespace_id = "desired namespace"; const char *raw = "output in raw format"; struct nvme_dev *dev; @@ -1826,10 +1750,11 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug d((unsigned char *)(&tele_log), sizeof(tele_log), 16, 1); } else seaget_d_raw((unsigned char *)(&tele_log), sizeof(tele_log), dump_fd); - } else if (err > 0) + } else if (err > 0) { nvme_show_status(err); - else + } else { perror("log page"); + } blkCnt = 0; @@ -1838,7 +1763,7 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug blksToGet = ((maxBlk - blkCnt) >= TELEMETRY_BLOCKS_TO_READ) ? TELEMETRY_BLOCKS_TO_READ : (maxBlk - blkCnt); - if (blksToGet == 0) + if (!blksToGet) return err; bytesToGet = (unsigned long long)blksToGet * 512; @@ -1846,7 +1771,7 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug if (!log) { fprintf(stderr, "could not alloc buffer for log\n"); - return EINVAL; + return -EINVAL; } memset(log, 0, bytesToGet); @@ -1878,10 +1803,11 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug d((unsigned char *)log, bytesToGet, 16, 1); } else seaget_d_raw((unsigned char *)log, bytesToGet, dump_fd); - } else if (err > 0) + } else if (err > 0) { nvme_show_status(err); - else + } else { perror("log page"); + } blkCnt += blksToGet; @@ -1895,21 +1821,20 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug void seaget_d_raw(unsigned char *buf, int len, int fd) { if (write(fd, (void *)buf, len) <= 0) - printf("%s: Write Failed\n", __FUNCTION__); + printf("%s: Write Failed\n", __func__); } static int vs_internal_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Capture the Telemetry Controller-Initiated Data in " \ - "binary format"; + const char *desc = "Capture the Telemetry Controller-Initiated Data in binary format"; const char *namespace_id = "desired namespace"; const char *file = "dump file"; struct nvme_dev *dev; int err, dump_fd; int flags = O_WRONLY | O_CREAT; - int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH; + int mode = 0664; struct nvme_temetry_log_hdr tele_log; __le64 offset = 0; __u16 log_id; @@ -1942,7 +1867,7 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl if (dump_fd < 0) { perror(cfg.file); dev_close(dev); - return EINVAL; + return -EINVAL; } } @@ -1954,10 +1879,11 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl offset += 512; seaget_d_raw((unsigned char *)(&tele_log), sizeof(tele_log), dump_fd); - } else if (err > 0) + } else if (err > 0) { nvme_show_status(err); - else + } else { perror("log page"); + } blkCnt = 0; @@ -1966,9 +1892,8 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl blksToGet = ((maxBlk - blkCnt) >= TELEMETRY_BLOCKS_TO_READ) ? TELEMETRY_BLOCKS_TO_READ : (maxBlk - blkCnt); - if (blksToGet == 0) { + if (!blksToGet) goto out; - } bytesToGet = (unsigned long long)blksToGet * 512; log = malloc(bytesToGet); @@ -2004,10 +1929,11 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl seaget_d_raw((unsigned char *)log, bytesToGet, dump_fd); - } else if (err > 0) + } else if (err > 0) { nvme_show_status(err); - else + } else { perror("log page"); + } blkCnt += blksToGet; @@ -2024,7 +1950,7 @@ out: /*SEAGATE-PLUGIN Version */ static int seagate_plugin_version(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - printf("Seagate-Plugin version : %d.%d \n", + printf("Seagate-Plugin version : %d.%d\n", SEAGATE_PLUGIN_VERSION_MAJOR, SEAGATE_PLUGIN_VERSION_MINOR); return 0; @@ -2034,7 +1960,7 @@ static int seagate_plugin_version(int argc, char **argv, struct command *cmd, st /*OCP SEAGATE-PLUGIN Version */ static int stx_ocp_plugin_version(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - printf("Seagate-OCP-Plugin version : %d.%d \n", + printf("Seagate-OCP-Plugin version : %d.%d\n", SEAGATE_OCP_PLUGIN_VERSION_MAJOR, SEAGATE_OCP_PLUGIN_VERSION_MINOR); return 0; diff --git a/plugins/shannon/shannon-nvme.c b/plugins/shannon/shannon-nvme.c index 424b3f7..d4db8c7 100644 --- a/plugins/shannon/shannon-nvme.c +++ b/plugins/shannon/shannon-nvme.c @@ -16,25 +16,25 @@ #define CREATE_CMD #include "shannon-nvme.h" -typedef enum { +enum { PROGRAM_FAIL_CNT, ERASE_FAIL_CNT, WEARLEVELING_COUNT, E2E_ERR_CNT, CRC_ERR_CNT, - TIME_WORKLOAD_MEDIA_WEAR, - TIME_WORKLOAD_HOST_READS, - TIME_WORKLOAD_TIMER, - THERMAL_THROTTLE, - RETRY_BUFFER_OVERFLOW, - PLL_LOCK_LOSS, + TIME_WORKLOAD_MEDIA_WEAR, + TIME_WORKLOAD_HOST_READS, + TIME_WORKLOAD_TIMER, + THERMAL_THROTTLE, + RETRY_BUFFER_OVERFLOW, + PLL_LOCK_LOSS, NAND_WRITE, HOST_WRITE, SRAM_ERROR_CNT, ADD_SMART_ITEMS, -}addtional_smart_items; +}; -#pragma pack(push,1) +#pragma pack(push, 1) struct nvme_shannon_smart_log_item { __u8 rsv1[3]; __u8 norm; @@ -45,7 +45,7 @@ struct nvme_shannon_smart_log_item { __le16 min; __le16 max; __le16 avg; - } wear_level ; + } wear_level; struct thermal_throttle { __u8 st; __u32 count; @@ -57,68 +57,67 @@ struct nvme_shannon_smart_log_item { struct nvme_shannon_smart_log { struct nvme_shannon_smart_log_item items[ADD_SMART_ITEMS]; - __u8 vend_spec_resv; + __u8 vend_spec_resv; }; -static void show_shannon_smart_log(struct nvme_shannon_smart_log *smart, - unsigned int nsid, const char *devname) +static void show_shannon_smart_log(struct nvme_shannon_smart_log *smart, unsigned int nsid, + const char *devname) { printf("Additional Smart Log for NVME device:%s namespace-id:%x\n", - devname, nsid); + devname, nsid); printf("key normalized value\n"); printf("program_fail_count : %3d%% %"PRIu64"\n", - smart->items[PROGRAM_FAIL_CNT].norm, - int48_to_long(smart->items[PROGRAM_FAIL_CNT].item_val)); + smart->items[PROGRAM_FAIL_CNT].norm, + int48_to_long(smart->items[PROGRAM_FAIL_CNT].item_val)); printf("erase_fail_count : %3d%% %"PRIu64"\n", - smart->items[ERASE_FAIL_CNT].norm, - int48_to_long(smart->items[ERASE_FAIL_CNT].item_val)); + smart->items[ERASE_FAIL_CNT].norm, + int48_to_long(smart->items[ERASE_FAIL_CNT].item_val)); printf("wear_leveling : %3d%% min: %u, max: %u, avg: %u\n", - smart->items[WEARLEVELING_COUNT].norm, - le16_to_cpu(smart->items[WEARLEVELING_COUNT].wear_level.min), - le16_to_cpu(smart->items[WEARLEVELING_COUNT].wear_level.max), - le16_to_cpu(smart->items[WEARLEVELING_COUNT].wear_level.avg)); + smart->items[WEARLEVELING_COUNT].norm, + le16_to_cpu(smart->items[WEARLEVELING_COUNT].wear_level.min), + le16_to_cpu(smart->items[WEARLEVELING_COUNT].wear_level.max), + le16_to_cpu(smart->items[WEARLEVELING_COUNT].wear_level.avg)); printf("end_to_end_error_detection_count: %3d%% %"PRIu64"\n", - smart->items[E2E_ERR_CNT].norm, - int48_to_long(smart->items[E2E_ERR_CNT].item_val)); + smart->items[E2E_ERR_CNT].norm, + int48_to_long(smart->items[E2E_ERR_CNT].item_val)); printf("crc_error_count : %3d%% %"PRIu64"\n", - smart->items[CRC_ERR_CNT].norm, - int48_to_long(smart->items[CRC_ERR_CNT].item_val)); + smart->items[CRC_ERR_CNT].norm, + int48_to_long(smart->items[CRC_ERR_CNT].item_val)); printf("timed_workload_media_wear : %3d%% %.3f%%\n", - smart->items[TIME_WORKLOAD_MEDIA_WEAR].norm, - ((float)int48_to_long(smart->items[TIME_WORKLOAD_MEDIA_WEAR].item_val)) / 1024); + smart->items[TIME_WORKLOAD_MEDIA_WEAR].norm, + ((float)int48_to_long(smart->items[TIME_WORKLOAD_MEDIA_WEAR].item_val)) / 1024); printf("timed_workload_host_reads : %3d%% %"PRIu64"%%\n", - smart->items[TIME_WORKLOAD_HOST_READS].norm, - int48_to_long(smart->items[TIME_WORKLOAD_HOST_READS].item_val)); + smart->items[TIME_WORKLOAD_HOST_READS].norm, + int48_to_long(smart->items[TIME_WORKLOAD_HOST_READS].item_val)); printf("timed_workload_timer : %3d%% %"PRIu64" min\n", - smart->items[TIME_WORKLOAD_TIMER].norm, - int48_to_long(smart->items[TIME_WORKLOAD_TIMER].item_val)); + smart->items[TIME_WORKLOAD_TIMER].norm, + int48_to_long(smart->items[TIME_WORKLOAD_TIMER].item_val)); printf("thermal_throttle_status : %3d%% CurTTSta: %u%%, TTCnt: %u\n", - smart->items[THERMAL_THROTTLE].norm, - smart->items[THERMAL_THROTTLE].thermal_throttle.st, - smart->items[THERMAL_THROTTLE].thermal_throttle.count); + smart->items[THERMAL_THROTTLE].norm, + smart->items[THERMAL_THROTTLE].thermal_throttle.st, + smart->items[THERMAL_THROTTLE].thermal_throttle.count); printf("retry_buffer_overflow_count : %3d%% %"PRIu64"\n", - smart->items[RETRY_BUFFER_OVERFLOW].norm, - int48_to_long(smart->items[RETRY_BUFFER_OVERFLOW].item_val)); + smart->items[RETRY_BUFFER_OVERFLOW].norm, + int48_to_long(smart->items[RETRY_BUFFER_OVERFLOW].item_val)); printf("pll_lock_loss_count : %3d%% %"PRIu64"\n", - smart->items[PLL_LOCK_LOSS].norm, - int48_to_long(smart->items[PLL_LOCK_LOSS].item_val)); + smart->items[PLL_LOCK_LOSS].norm, + int48_to_long(smart->items[PLL_LOCK_LOSS].item_val)); printf("nand_bytes_written : %3d%% sectors: %"PRIu64"\n", - smart->items[NAND_WRITE].norm, - int48_to_long(smart->items[NAND_WRITE].item_val)); + smart->items[NAND_WRITE].norm, + int48_to_long(smart->items[NAND_WRITE].item_val)); printf("host_bytes_written : %3d%% sectors: %"PRIu64"\n", - smart->items[HOST_WRITE].norm, - int48_to_long(smart->items[HOST_WRITE].item_val)); - printf("sram_error_count : %3d%% %"PRIu64"\n", - smart->items[RETRY_BUFFER_OVERFLOW].norm, - int48_to_long(smart->items[SRAM_ERROR_CNT].item_val)); + smart->items[HOST_WRITE].norm, + int48_to_long(smart->items[HOST_WRITE].item_val)); + printf("sram_error_count : %3d%% %"PRIu64"\n", + smart->items[RETRY_BUFFER_OVERFLOW].norm, + int48_to_long(smart->items[SRAM_ERROR_CNT].item_val)); } - static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { struct nvme_shannon_smart_log smart_log; - char *desc = "Get Shannon vendor specific additional smart log (optionally, "\ - "for the specified namespace), and show it."; + char *desc = + "Get Shannon vendor specific additional smart log (optionally, for the specified namespace), and show it."; const char *namespace = "(optional) desired namespace"; const char *raw = "dump output in binary format"; struct nvme_dev *dev; @@ -134,7 +133,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, OPT_ARGS(opts) = { OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace), - OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), + OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), OPT_END() }; @@ -145,30 +144,29 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, sizeof(smart_log), &smart_log); if (!err) { if (!cfg.raw_binary) - show_shannon_smart_log(&smart_log, cfg.namespace_id, - dev->name); + show_shannon_smart_log(&smart_log, cfg.namespace_id, dev->name); else d_raw((unsigned char *)&smart_log, sizeof(smart_log)); - } - else if (err > 0) + } else if (err > 0) { nvme_show_status(err); + } dev_close(dev); return err; } static int get_additional_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Read operating parameters of the "\ - "specified controller. Operating parameters are grouped "\ - "and identified by Feature Identifiers; each Feature "\ - "Identifier contains one or more attributes that may affect "\ - "behavior of the feature. Each Feature has three possible "\ - "settings: default, saveable, and current. If a Feature is "\ - "saveable, it may be modified by set-feature. Default values "\ - "are vendor-specific and not changeable. Use set-feature to "\ - "change saveable Features.\n\n"\ - "Available additional feature id:\n"\ - "0x02: Shannon power management\n"; + const char *desc = "Read operating parameters of the\n" + "specified controller. Operating parameters are grouped\n" + "and identified by Feature Identifiers; each Feature\n" + "Identifier contains one or more attributes that may affect\n" + "behavior of the feature. Each Feature has three possible\n" + "settings: default, saveable, and current. If a Feature is\n" + "saveable, it may be modified by set-feature. Default values\n" + "are vendor-specific and not changeable. Use set-feature to\n" + "change saveable Features.\n\n" + "Available additional feature id:\n" + "0x02: Shannon power management\n"; const char *raw = "show infos in binary format"; const char *namespace_id = "identifier of desired namespace"; const char *feature_id = "hexadecimal feature name"; @@ -194,19 +192,19 @@ static int get_additional_feature(int argc, char **argv, struct command *cmd, st struct config cfg = { .namespace_id = 1, .feature_id = 0, - .sel = 0, - .cdw11 = 0, - .data_len = 0, + .sel = 0, + .cdw11 = 0, + .data_len = 0, }; OPT_ARGS(opts) = { - OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), - OPT_UINT("feature-id", 'f', &cfg.feature_id, feature_id), - OPT_BYTE("sel", 's', &cfg.sel, sel), - OPT_UINT("data-len", 'l', &cfg.data_len, data_len), - OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), - OPT_UINT("cdw11", 'c', &cfg.cdw11, cdw11), - OPT_FLAG("human-readable",'H', &cfg.human_readable, human_readable), + OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), + OPT_UINT("feature-id", 'f', &cfg.feature_id, feature_id), + OPT_BYTE("sel", 's', &cfg.sel, sel), + OPT_UINT("data-len", 'l', &cfg.data_len, data_len), + OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), + OPT_UINT("cdw11", 'c', &cfg.cdw11, cdw11), + OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable), OPT_END() }; @@ -217,16 +215,15 @@ static int get_additional_feature(int argc, char **argv, struct command *cmd, st if (cfg.sel > 7) { fprintf(stderr, "invalid 'select' param:%d\n", cfg.sel); dev_close(dev); - return EINVAL; + return -EINVAL; } if (!cfg.feature_id) { fprintf(stderr, "feature-id required param\n"); dev_close(dev); - return EINVAL; + return -EINVAL; } if (cfg.data_len) { - if (posix_memalign(&buf, getpagesize(), cfg.data_len)) - { + if (posix_memalign(&buf, getpagesize(), cfg.data_len)) { dev_close(dev); exit(ENOMEM); } @@ -247,23 +244,7 @@ static int get_additional_feature(int argc, char **argv, struct command *cmd, st .result = &result, }; err = nvme_get_features(&args); - if (!err) { -#if 0 - printf("get-feature:0x%02x (%s), %s value: %#08x\n", cfg.feature_id, - nvme_feature_to_string(cfg.feature_id), - nvme_select_to_string(cfg.sel), result); - if (cfg.human_readable) - nvme_feature_show_fields(cfg.feature_id, result, buf); - else { - if (buf) { - if (!cfg.raw_binary) - d(buf, cfg.data_len, 16, 1); - else - d_raw(buf, cfg.data_len); - } - } -#endif - } else if (err > 0) + if (err > 0) nvme_show_status(err); if (buf) free(buf); @@ -272,17 +253,17 @@ static int get_additional_feature(int argc, char **argv, struct command *cmd, st static int set_additional_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Modify the saveable or changeable "\ - "current operating parameters of the controller. Operating "\ - "parameters are grouped and identified by Feature "\ - "Identifiers. Feature settings can be applied to the entire "\ - "controller and all associated namespaces, or to only a few "\ - "namespace(s) associated with the controller. Default values "\ - "for each Feature are vendor-specific and may not be modified."\ - "Use get-feature to determine which Features are supported by "\ - "the controller and are saveable/changeable.\n\n"\ - "Available additional feature id:\n"\ - "0x02: Shannon power management\n"; + const char *desc = "Modify the saveable or changeable\n" + "current operating parameters of the controller. Operating\n" + "parameters are grouped and identified by Feature\n" + "Identifiers. Feature settings can be applied to the entire\n" + "controller and all associated namespaces, or to only a few\n" + "namespace(s) associated with the controller. Default values\n" + "for each Feature are vendor-specific and may not be modified.\n" + "Use get-feature to determine which Features are supported by\n" + "the controller and are saveable/changeable.\n\n" + "Available additional feature id:\n" + "0x02: Shannon power management\n"; const char *namespace_id = "desired namespace"; const char *feature_id = "hex feature name (required)"; const char *data_len = "buffer length if data required"; @@ -305,21 +286,21 @@ static int set_additional_feature(int argc, char **argv, struct command *cmd, st }; struct config cfg = { - .file = "", + .file = "", .namespace_id = 0, .feature_id = 0, - .value = 0, + .value = 0, .data_len = 0, - .save = 0, + .save = 0, }; OPT_ARGS(opts) = { OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), - OPT_UINT("feature-id", 'f', &cfg.feature_id, feature_id), - OPT_UINT("value", 'v', &cfg.value, value), - OPT_UINT("data-len", 'l', &cfg.data_len, data_len), - OPT_FILE("data", 'd', &cfg.file, data), - OPT_FLAG("save", 's', &cfg.save, save), + OPT_UINT("feature-id", 'f', &cfg.feature_id, feature_id), + OPT_UINT("value", 'v', &cfg.value, value), + OPT_UINT("data-len", 'l', &cfg.data_len, data_len), + OPT_FILE("data", 'd', &cfg.file, data), + OPT_FLAG("save", 's', &cfg.save, save), OPT_END() }; @@ -330,14 +311,14 @@ static int set_additional_feature(int argc, char **argv, struct command *cmd, st if (!cfg.feature_id) { fprintf(stderr, "feature-id required param\n"); dev_close(dev); - return EINVAL; + return -EINVAL; } if (cfg.data_len) { - if (posix_memalign(&buf, getpagesize(), cfg.data_len)){ + if (posix_memalign(&buf, getpagesize(), cfg.data_len)) { fprintf(stderr, "can not allocate feature payload\n"); dev_close(dev); - return ENOMEM; + return -ENOMEM; } memset(buf, 0, cfg.data_len); } @@ -380,10 +361,6 @@ static int set_additional_feature(int argc, char **argv, struct command *cmd, st goto free; } if (!err) { -#if 0 - printf("set-feature:%02x (%s), value:%#08x\n", cfg.feature_id, - nvme_feature_to_string(cfg.feature_id), cfg.value); -#endif if (buf) d(buf, cfg.data_len, 16, 1); } else if (err > 0) diff --git a/plugins/solidigm/meson.build b/plugins/solidigm/meson.build index 526fb02..84495a1 100644 --- a/plugins/solidigm/meson.build +++ b/plugins/solidigm/meson.build @@ -1,8 +1,13 @@ sources += [ + 'plugins/solidigm/solidigm-id-ctrl.c', 'plugins/solidigm/solidigm-util.c', 'plugins/solidigm/solidigm-smart.c', 'plugins/solidigm/solidigm-garbage-collection.c', 'plugins/solidigm/solidigm-latency-tracking.c', + 'plugins/solidigm/solidigm-log-page-dir.c', 'plugins/solidigm/solidigm-telemetry.c', + 'plugins/solidigm/solidigm-internal-logs.c', + 'plugins/solidigm/solidigm-market-log.c', ] subdir('solidigm-telemetry') + diff --git a/plugins/solidigm/solidigm-garbage-collection.c b/plugins/solidigm/solidigm-garbage-collection.c index 3828b9e..b26d754 100644 --- a/plugins/solidigm/solidigm-garbage-collection.c +++ b/plugins/solidigm/solidigm-garbage-collection.c @@ -21,26 +21,27 @@ #include "solidigm-garbage-collection.h" #include "solidigm-util.h" -typedef struct __attribute__((packed)) gc_item { +struct __packed gc_item { __le32 timer_type; __le64 timestamp; -} gc_item_t; +}; #define VU_GC_MAX_ITEMS 100 -typedef struct garbage_control_collection_log { +struct garbage_control_collection_log { __le16 version_major; __le16 version_minor; - gc_item_t item[VU_GC_MAX_ITEMS]; + struct __packed gc_item item[VU_GC_MAX_ITEMS]; __u8 reserved[2892]; -} garbage_control_collection_log_t; +}; -static void vu_gc_log_show_json(garbage_control_collection_log_t *payload, const char *devname) +static void vu_gc_log_show_json(struct garbage_control_collection_log *payload, const char *devname) { struct json_object *gc_entries = json_create_array(); for (int i = 0; i < VU_GC_MAX_ITEMS; i++) { - gc_item_t item = payload->item[i]; + struct __packed gc_item item = payload->item[i]; struct json_object *entry = json_create_object(); + json_object_add_value_int(entry, "timestamp", le64_to_cpu(item.timestamp)); json_object_add_value_int(entry, "timer_type", le32_to_cpu(item.timer_type)); json_array_add_value_object(gc_entries, entry); @@ -50,7 +51,7 @@ 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(struct garbage_control_collection_log *payload, const char *devname, __u8 uuid_index) { printf("Solidigm Garbage Collection Log for NVME device:%s UUID-idx:%d\n", devname, @@ -58,7 +59,8 @@ static void vu_gc_log_show(garbage_control_collection_log_t *payload, const char printf("Timestamp Timer Type\n"); for (int i = 0; i < VU_GC_MAX_ITEMS; i++) { - gc_item_t item = payload->item[i]; + struct __packed gc_item item = payload->item[i]; + printf("%-13" PRIu64 " %d\n", le64_to_cpu(item.timestamp), le32_to_cpu(item.timer_type)); } } @@ -88,15 +90,16 @@ int solidigm_get_garbage_collection_log(int argc, char **argv, struct command *c return err; enum nvme_print_flags flags = validate_output_format(cfg.output_format); + if (flags == -EINVAL) { fprintf(stderr, "Invalid output format '%s'\n", cfg.output_format); dev_close(dev); - return EINVAL; + return -EINVAL; } uuid_index = solidigm_get_vu_uuid_index(dev); - garbage_control_collection_log_t gc_log; + struct garbage_control_collection_log gc_log; const int solidigm_vu_gc_log_id = 0xfd; struct nvme_get_log_args args = { .lpo = 0, @@ -118,15 +121,13 @@ int solidigm_get_garbage_collection_log(int argc, char **argv, struct command *c err = nvme_get_log(&args); if (!err) { - if (flags & BINARY) { + if (flags & BINARY) d_raw((unsigned char *)&gc_log, sizeof(gc_log)); - } else if (flags & JSON) { + else if (flags & JSON) vu_gc_log_show_json(&gc_log, dev->name); - } else { + else vu_gc_log_show(&gc_log, dev->name, uuid_index); - } - } - else if (err > 0) { + } else if (err > 0) { nvme_show_status(err); } diff --git a/plugins/solidigm/solidigm-id-ctrl.c b/plugins/solidigm/solidigm-id-ctrl.c new file mode 100644 index 0000000..f45e758 --- /dev/null +++ b/plugins/solidigm/solidigm-id-ctrl.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 Solidigm. + * + * Author: leonardo.da.cunha@solidigm.com + */ + +#include <inttypes.h> +#include "common.h" +#include "solidigm-id-ctrl.h" + +struct __packed nvme_vu_id_ctrl_field { /* CDR MR5 */ + __u8 rsvd1[3]; + __u8 ss; + char health[20]; + __u8 cls; + __u8 nlw; + __u8 scap; + __u8 sstat; + char bl[8]; + __u8 rsvd2[38]; + __le64 ww; + char mic_bl[4]; + char mic_fw[4]; +}; + +void sldgm_id_ctrl(uint8_t *vs, struct json_object *root) +{ + // text output aligns nicely with property name up to 10 chars + const char *str_ss = "stripeSize"; + const char *str_health = "health"; + const char *str_cls = "linkSpeed"; + const char *str_nlw = "negLnkWdth"; + const char *str_scap = "secCapab"; + const char *str_sstat = "secStatus"; + const char *str_bl = "bootLoader"; + const char *str_ww = "wwid"; + const char *str_mic_bl = "bwLimGran"; + const char *str_mic_fw = "ioLimGran"; + + struct nvme_vu_id_ctrl_field *id = (struct nvme_vu_id_ctrl_field *)vs; + + const char str_heathy[sizeof(id->health)] = "healthy"; + const char *health = id->health[0] ? id->health : str_heathy; + + if (root == NULL) { + printf("%-10s: %u\n", str_ss, id->ss); + printf("%-10s: %.*s\n", str_health, (int)sizeof(id->health), health); + printf("%-10s: %u\n", str_cls, id->cls); + printf("%-10s: %u\n", str_nlw, id->nlw); + printf("%-10s: %u\n", str_scap, id->scap); + printf("%-10s: %u\n", str_sstat, id->sstat); + printf("%-10s: %.*s\n", str_bl, (int)sizeof(id->bl), id->bl); + printf("%-10s: 0x%016"PRIx64"\n", str_ww, le64_to_cpu(id->ww)); + printf("%-10s: %.*s\n", str_mic_bl, (int)sizeof(id->mic_bl), id->mic_bl); + printf("%-10s: %.*s\n", str_mic_fw, (int)sizeof(id->mic_fw), id->mic_fw); + return; + } + + json_object_add_value_uint(root, str_ss, id->ss); + json_object_object_add(root, str_health, + json_object_new_string_len(health, sizeof(id->health))); + json_object_add_value_uint(root, str_cls, id->cls); + json_object_add_value_uint(root, str_nlw, id->nlw); + json_object_add_value_uint(root, str_scap, id->scap); + json_object_add_value_uint(root, str_sstat, id->sstat); + json_object_object_add(root, str_bl, json_object_new_string_len(id->bl, sizeof(id->bl))); + json_object_add_value_uint64(root, str_ww, le64_to_cpu(id->ww)); + json_object_object_add(root, str_mic_bl, + json_object_new_string_len(id->mic_bl, sizeof(id->mic_bl))); + json_object_object_add(root, str_mic_fw, + json_object_new_string_len(id->mic_fw, sizeof(id->mic_fw))); +} diff --git a/plugins/solidigm/solidigm-id-ctrl.h b/plugins/solidigm/solidigm-id-ctrl.h new file mode 100644 index 0000000..ed6e438 --- /dev/null +++ b/plugins/solidigm/solidigm-id-ctrl.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (c) 2023 Solidigm. + * + * Author: leonardo.da.cunha@solidigm.com + */ + +#include <inttypes.h> +#include "util/json.h" +void sldgm_id_ctrl(uint8_t *vs, struct json_object *root); diff --git a/plugins/solidigm/solidigm-internal-logs.c b/plugins/solidigm/solidigm-internal-logs.c new file mode 100644 index 0000000..4730443 --- /dev/null +++ b/plugins/solidigm/solidigm-internal-logs.c @@ -0,0 +1,597 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 Solidigm. + * + * Authors: leonardo.da.cunha@solidigm.com + * shankaralingegowda.singonahalli@solidigm.com + */ + +#include <fcntl.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <inttypes.h> +#include <linux/limits.h> + +#include "common.h" +#include "nvme.h" +#include "libnvme.h" +#include "plugin.h" +#include "nvme-print.h" + +#define DWORD_SIZE 4 + +enum log_type { + NLOG = 0, + EVENTLOG = 1, + ASSERTLOG = 2, +}; + +#pragma pack(push, internal_logs, 1) +struct version { + __u16 major; + __u16 minor; +}; + +struct event_dump_instance { + __u32 numeventdumps; + __u32 coresize; + __u32 coreoffset; + __u32 eventidoffset[16]; + __u8 eventIdValidity[16]; +}; + +struct commom_header { + struct version ver; + __u32 header_size; + __u32 log_size; + __u32 numcores; +}; + +struct event_dump_header { + struct commom_header header; + __u32 eventidsize; + struct event_dump_instance edumps[0]; +}; + +struct assert_dump_core { + __u32 coreoffset; + __u32 assertsize; + __u8 assertdumptype; + __u8 assertvalid; + __u8 reserved[2]; +}; + +struct assert_dump_header { + struct commom_header header; + struct assert_dump_core core[]; +}; + +struct nlog_dump_header_common { + struct version ver; + __u32 logselect; + __u32 totalnlogs; + __u32 nlognum; + char nlogname[4]; + __u32 nlogbytesize; + __u32 nlogprimarybuffsize; + __u32 tickspersecond; + __u32 corecount; +}; + +struct nlog_dump_header3_0 { + struct nlog_dump_header_common common; + __u32 nlogpausestatus; + __u32 selectoffsetref; + __u32 selectnlogpause; + __u32 selectaddedoffset; + __u32 nlogbufnum; + __u32 nlogbufnummax; +}; + +struct nlog_dump_header4_0 { + struct nlog_dump_header_common common; + __u64 nlogpausestatus; + __u32 selectoffsetref; + __u32 selectnlogpause; + __u32 selectaddedoffset; + __u32 nlogbufnum; + __u32 nlogbufnummax; + __u32 coreselected; + __u32 reserved[2]; +}; + +struct nlog_dump_header4_1 { + struct nlog_dump_header_common common; + __u64 nlogpausestatus; + __u32 selectoffsetref; + __u32 selectnlogpause; + __u32 selectaddedoffset; + __u32 nlogbufnum; + __u32 nlogbufnummax; + __u32 coreselected; + __u32 lpaPointer1High; + __u32 lpaPointer1Low; + __u32 lpaPointer2High; + __u32 lpaPointer2Low; +}; + +#pragma pack(pop, internal_logs) + +struct config { + __u32 namespace_id; + char *file_prefix; + char *type; + bool verbose; +}; + +static void print_nlog_header(__u8 *buffer) +{ + struct nlog_dump_header_common *nlog_header = (struct nlog_dump_header_common *) buffer; + + if (nlog_header->ver.major >= 3) { + printf("Version Major %u\n", nlog_header->ver.major); + printf("Version Minor %u\n", nlog_header->ver.minor); + printf("Log_select %u\n", nlog_header->logselect); + printf("totalnlogs %u\n", nlog_header->totalnlogs); + printf("nlognum %u\n", nlog_header->nlognum); + printf("nlogname %c%c%c%c\n", nlog_header->nlogname[3], nlog_header->nlogname[2], + nlog_header->nlogname[1], nlog_header->nlogname[0]); + printf("nlogbytesize %u\n", nlog_header->nlogbytesize); + printf("nlogprimarybuffsize %u\n", nlog_header->nlogprimarybuffsize); + printf("tickspersecond %u\n", nlog_header->tickspersecond); + printf("corecount %u\n", nlog_header->corecount); + } + if (nlog_header->ver.major >= 4) { + struct nlog_dump_header4_0 *nlog_header = (struct nlog_dump_header4_0 *) buffer; + + printf("nlogpausestatus %"PRIu64"\n", (uint64_t)nlog_header->nlogpausestatus); + printf("selectoffsetref %u\n", nlog_header->selectoffsetref); + printf("selectnlogpause %u\n", nlog_header->selectnlogpause); + printf("selectaddedoffset %u\n", nlog_header->selectaddedoffset); + printf("nlogbufnum %u\n", nlog_header->nlogbufnum); + printf("nlogbufnummax %u\n", nlog_header->nlogbufnummax); + printf("coreselected %u\n\n", nlog_header->coreselected); + } +} + +#define INTERNAL_LOG_MAX_BYTE_TRANSFER 4096 +#define INTERNAL_LOG_MAX_DWORD_TRANSFER (INTERNAL_LOG_MAX_BYTE_TRANSFER / 4) + +static int cmd_dump_repeat(struct nvme_passthru_cmd *cmd, __u32 total_dw_size, + int out_fd, int ioctl_fd, bool force_max_transfer) +{ + int err = 0; + + while (total_dw_size > 0) { + size_t dword_tfer = min(INTERNAL_LOG_MAX_DWORD_TRANSFER, total_dw_size); + + cmd->cdw10 = force_max_transfer ? INTERNAL_LOG_MAX_DWORD_TRANSFER : dword_tfer; + cmd->data_len = dword_tfer * 4; + err = nvme_submit_admin_passthru(ioctl_fd, cmd, NULL); + if (err) + return err; + + if (out_fd > 0) { + err = write(out_fd, (const void *)(uintptr_t)cmd->addr, cmd->data_len); + if (err < 0) { + perror("write failure"); + return err; + } + err = 0; + } + total_dw_size -= dword_tfer; + cmd->cdw13 += dword_tfer; + } + return err; +} + +static int write_header(__u8 *buf, int fd, size_t amnt) +{ + if (write(fd, buf, amnt) < 0) + return 1; + return 0; +} + +static int read_header(struct nvme_passthru_cmd *cmd, int ioctl_fd) +{ + memset((void *)(uintptr_t)cmd->addr, 0, INTERNAL_LOG_MAX_BYTE_TRANSFER); + return cmd_dump_repeat(cmd, INTERNAL_LOG_MAX_DWORD_TRANSFER, -1, ioctl_fd, false); +} + +static int get_serial_number(char *str, int fd) +{ + struct nvme_id_ctrl ctrl = {0}; + int err; + + err = nvme_identify_ctrl(fd, &ctrl); + if (err) + return err; + + /* Remove trailing spaces */ + for (int i = sizeof(ctrl.sn) - 1; i && ctrl.sn[i] == ' '; i--) + ctrl.sn[i] = '\0'; + sprintf(str, "%-.*s", (int)sizeof(ctrl.sn), ctrl.sn); + return err; +} + +static int dump_assert_logs(struct nvme_dev *dev, struct config cfg) +{ + __u8 buf[INTERNAL_LOG_MAX_BYTE_TRANSFER]; + __u8 head_buf[INTERNAL_LOG_MAX_BYTE_TRANSFER]; + char file_path[PATH_MAX]; + struct assert_dump_header *ad = (struct assert_dump_header *) head_buf; + struct nvme_passthru_cmd cmd = { + .opcode = 0xd2, + .nsid = cfg.namespace_id, + .addr = (unsigned long)(void *)head_buf, + .cdw12 = ASSERTLOG, + .cdw13 = 0, + }; + int output, err; + + err = read_header(&cmd, dev_fd(dev)); + if (err) + return err; + + sprintf(file_path, "%s_AssertLog.bin", cfg.file_prefix); + output = open(file_path, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (output < 0) + return -errno; + err = write_header((__u8 *)ad, output, ad->header.header_size * DWORD_SIZE); + if (err) { + perror("write failure"); + close(output); + return err; + } + cmd.addr = (unsigned long)(void *)buf; + + if (cfg.verbose) { + printf("Assert Log, cores: %d log size: %d header size: %d\n", ad->header.numcores, + ad->header.log_size * DWORD_SIZE, ad->header.header_size * DWORD_SIZE); + for (__u32 i = 0; i < ad->header.numcores; i++) + printf("core %d assert size: %d\n", i, ad->core[i].assertsize * DWORD_SIZE); + } + + for (__u32 i = 0; i < ad->header.numcores; i++) { + if (!ad->core[i].assertvalid) + continue; + cmd.cdw13 = ad->core[i].coreoffset; + err = cmd_dump_repeat(&cmd, ad->core[i].assertsize, + output, + dev_fd(dev), false); + if (err) { + close(output); + return err; + } + } + close(output); + printf("Successfully wrote log to %s\n", file_path); + return err; +} + +static int dump_event_logs(struct nvme_dev *dev, struct config cfg) +{ + __u8 buf[INTERNAL_LOG_MAX_BYTE_TRANSFER]; + __u8 head_buf[INTERNAL_LOG_MAX_BYTE_TRANSFER]; + char file_path[PATH_MAX]; + struct event_dump_header *ehdr = (struct event_dump_header *) head_buf; + struct nvme_passthru_cmd cmd = { + .opcode = 0xd2, + .nsid = cfg.namespace_id, + .addr = (unsigned long)(void *)head_buf, + .cdw12 = EVENTLOG, + .cdw13 = 0, + }; + int output; + int core_num, err; + + err = read_header(&cmd, dev_fd(dev)); + if (err) + return err; + sprintf(file_path, "%s_EventLog.bin", cfg.file_prefix); + output = open(file_path, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (output < 0) + return -errno; + err = write_header(head_buf, output, INTERNAL_LOG_MAX_BYTE_TRANSFER); + + core_num = ehdr->header.numcores; + + if (err) { + close(output); + return err; + } + cmd.addr = (unsigned long)(void *)buf; + + if (cfg.verbose) + printf("Event Log, cores: %d log size: %d\n", core_num, ehdr->header.log_size * 4); + + for (__u32 j = 0; j < core_num; j++) { + if (cfg.verbose) { + for (int k = 0 ; k < 16; k++) { + printf("core: %d event: %d ", j, k); + printf("validity: %d ", ehdr->edumps[j].eventIdValidity[k]); + printf("offset: %d\n", ehdr->edumps[j].eventidoffset[k]); + } + } + cmd.cdw13 = ehdr->edumps[j].coreoffset; + err = cmd_dump_repeat(&cmd, ehdr->edumps[j].coresize, + output, dev_fd(dev), false); + if (err) { + close(output); + return err; + } + } + close(output); + printf("Successfully wrote log to %s\n", file_path); + return err; +} + +static size_t get_nlog_header_size(struct nlog_dump_header_common *nlog_header) +{ + switch (nlog_header->ver.major) { + case 3: + return sizeof(struct nlog_dump_header3_0); + case 4: + if (nlog_header->ver.minor == 0) + return sizeof(struct nlog_dump_header4_0); + return sizeof(struct nlog_dump_header4_1); + default: + return INTERNAL_LOG_MAX_BYTE_TRANSFER; + } + +} + +/* dumps nlogs from specified core or all cores when core = -1 */ +static int dump_nlogs(struct nvme_dev *dev, struct config cfg, int core) +{ + int err = 0; + __u32 count, core_num; + __u8 buf[INTERNAL_LOG_MAX_BYTE_TRANSFER]; + char file_path[PATH_MAX]; + struct nlog_dump_header_common *nlog_header = (struct nlog_dump_header_common *)buf; + struct nvme_passthru_cmd cmd = { + .opcode = 0xd2, + .nsid = cfg.namespace_id, + .addr = (unsigned long)(void *)buf + }; + + struct dump_select { + union { + struct { + __u32 selectLog : 3; + __u32 selectCore : 2; + __u32 selectNlog : 8; + }; + __u32 raw; + }; + } log_select; + int output; + bool is_open = false; + size_t header_size = 0; + + log_select.selectCore = core < 0 ? 0 : core; + do { + log_select.selectNlog = 0; + do { + cmd.cdw13 = 0; + cmd.cdw12 = log_select.raw; + err = read_header(&cmd, dev_fd(dev)); + if (err) { + if (is_open) + close(output); + return err; + } + count = nlog_header->totalnlogs; + core_num = core < 0 ? nlog_header->corecount : 0; + if (!header_size) { + sprintf(file_path, "%s_NLog.bin", cfg.file_prefix); + output = open(file_path, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (output < 0) + return -errno; + header_size = get_nlog_header_size(nlog_header); + is_open = true; + } + err = write_header(buf, output, header_size); + if (err) + break; + if (cfg.verbose) + print_nlog_header(buf); + cmd.cdw13 = 0x400; + err = cmd_dump_repeat(&cmd, nlog_header->nlogbytesize / 4, + output, dev_fd(dev), true); + if (err) + break; + } while (++log_select.selectNlog < count); + if (err) + break; + } while (++log_select.selectCore < core_num); + if (is_open) { + close(output); + printf("Successfully wrote log to %s\n", file_path); + } + return err; +} + +enum telemetry_type { + HOSTGENOLD, + HOSTGENNEW, + CONTROLLER +}; + +static int dump_telemetry(struct nvme_dev *dev, struct config cfg, enum telemetry_type ttype) +{ + struct nvme_telemetry_log *log = NULL; + size_t log_size = 0; + int err = 0, output; + __u8 *buffer = NULL; + size_t bytes_remaining = 0; + int data_area = NVME_TELEMETRY_DA_3; + char file_path[PATH_MAX]; + char *log_name; + + switch (ttype) { + case HOSTGENNEW: + log_name = "TelemetryHostGenNew"; + break; + case HOSTGENOLD: + log_name = "TelemetryHostGenOld"; + break; + case CONTROLLER: + log_name = "TelemetryController"; + break; + default: + return -EINVAL; + } + + sprintf(file_path, "%s_%s.bin", cfg.file_prefix, log_name); + output = open(file_path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (output < 0) + return -errno; + + switch (ttype) { + case HOSTGENNEW: + err = nvme_get_new_host_telemetry(dev_fd(dev), &log, + data_area, &log_size); + break; + case HOSTGENOLD: + err = nvme_get_host_telemetry(dev_fd(dev), &log, + data_area, &log_size); + break; + case CONTROLLER: + err = nvme_get_ctrl_telemetry(dev_fd(dev), true, &log, + data_area, &log_size); + break; + } + + if (err) + goto tele_close_output; + + bytes_remaining = log_size; + buffer = (__u8 *)log; + + while (bytes_remaining) { + ssize_t bytes_written = write(output, buffer, bytes_remaining); + + if (bytes_written < 0) { + err = -errno; + goto tele_close_output; + } + bytes_remaining -= bytes_written; + buffer += bytes_written; + } + printf("Successfully wrote log to %s\n", file_path); + +tele_close_output: + free(log); + close(output); + + return err; +} + +int solidigm_get_internal_log(int argc, char **argv, struct command *command, + struct plugin *plugin) +{ + char sn_prefix[sizeof(((struct nvme_id_ctrl *)0)->sn)+1]; + int log_count = 0; + int err; + struct nvme_dev *dev; + bool all = false; + + const char *desc = "Get Debug Firmware Logs and save them."; + const char *type = + "Log type: ALL, CONTROLLERINITTELEMETRY, HOSTINITTELEMETRY, HOSTINITTELEMETRYNOGEN, NLOG, ASSERT, EVENT. Defaults to ALL."; + const char *prefix = "Output file prefix; defaults to device serial number."; + const char *verbose = "To print out verbose info."; + const char *namespace_id = "Namespace to get logs from."; + + + struct config cfg = { + .namespace_id = NVME_NSID_ALL, + .file_prefix = NULL, + .type = NULL, + }; + + OPT_ARGS(opts) = { + OPT_STR("type", 't', &cfg.type, type), + OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), + OPT_FILE("file-prefix", 'p', &cfg.file_prefix, prefix), + OPT_FLAG("verbose", 'v', &cfg.verbose, verbose), + OPT_END() + }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; + + if (!cfg.file_prefix) { + err = get_serial_number(sn_prefix, dev_fd(dev)); + if (err) + goto out_dev; + cfg.file_prefix = sn_prefix; + } + + if (!cfg.type) + cfg.type = "ALL"; + else { + for (char *p = cfg.type; *p; ++p) + *p = toupper(*p); + } + + if (!strcmp(cfg.type, "ALL")) + all = true; + if (all || !strcmp(cfg.type, "ASSERT")) { + err = dump_assert_logs(dev, cfg); + if (err == 0) + log_count++; + else if (err < 0) + perror("Assert log"); + } + if (all || !strcmp(cfg.type, "EVENT")) { + err = dump_event_logs(dev, cfg); + if (err == 0) + log_count++; + else if (err < 0) + perror("Eventt log"); + } + if (all || !strcmp(cfg.type, "NLOG")) { + err = dump_nlogs(dev, cfg, -1); + if (err == 0) + log_count++; + else if (err < 0) + perror("Nlog"); + } + if (all || !strcmp(cfg.type, "CONTROLLERINITTELEMETRY")) { + err = dump_telemetry(dev, cfg, CONTROLLER); + if (err == 0) + log_count++; + else if (err < 0) + perror("Telemetry Controller Initated"); + } + if (all || !strcmp(cfg.type, "HOSTINITTELEMETRYNOGEN")) { + err = dump_telemetry(dev, cfg, HOSTGENOLD); + if (err == 0) + log_count++; + else if (err < 0) + perror("Previously existing Telemetry Host Initated"); + } + if (all || !strcmp(cfg.type, "HOSTINITTELEMETRY")) { + err = dump_telemetry(dev, cfg, HOSTGENNEW); + if (err == 0) + log_count++; + else if (err < 0) + perror("Telemetry Host Initated"); + } + + if (log_count == 0) { + if (err > 0) + nvme_show_status(err); + } else if ((log_count > 1) || cfg.verbose) + printf("Total: %d log files with prefix: %s\n", log_count, cfg.file_prefix); +out_dev: + /* Redundant close() to make static code analysis happy */ + close(dev->direct.fd); + dev_close(dev); + return err; +} diff --git a/plugins/solidigm/solidigm-internal-logs.h b/plugins/solidigm/solidigm-internal-logs.h new file mode 100644 index 0000000..801af24 --- /dev/null +++ b/plugins/solidigm/solidigm-internal-logs.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (c) 2023 Solidigm. + * + * Author: leonardo.da.cunha@solidigm.com + */ + +int solidigm_get_internal_log(int argc, char **argv, struct command *cmd, struct plugin *plugin); diff --git a/plugins/solidigm/solidigm-latency-tracking.c b/plugins/solidigm/solidigm-latency-tracking.c index 40edcfa..481a831 100644 --- a/plugins/solidigm/solidigm-latency-tracking.c +++ b/plugins/solidigm/solidigm-latency-tracking.c @@ -94,7 +94,6 @@ static void latency_tracker_bucket_parse(const struct latency_tracker *lt, int i __u32 bucket_data = le32_to_cpu(lt->stats.data[id]); if (lt->print_flags == NORMAL) { - printf("%-*d", COL_WIDTH, id); get_time_unit_label(buffer, lower_us, true); @@ -137,12 +136,10 @@ static void latency_tracker_parse_linear(const struct latency_tracker *lt, __u32 bytes_per, __u32 us_step, bool nonzero_print) { - for (int i = (start_offset / bytes_per) - 1; - i < end_offset / bytes_per; i++) { - if (nonzero_print && lt->stats.data[i] == 0) + for (int i = (start_offset / bytes_per) - 1; i < end_offset / bytes_per; i++) { + if (nonzero_print && !lt->stats.data[i]) continue; - latency_tracker_bucket_parse(lt, i, us_step * i, - us_step * (i + 1), true); + latency_tracker_bucket_parse(lt, i, us_step * i, us_step * (i + 1), true); } } @@ -153,6 +150,7 @@ static void latency_tracker_parse_linear(const struct latency_tracker *lt, static int latency_tracker_bucket_pos2us(const struct latency_tracker *lt, int i) { __u32 base_val = 1 << lt->base_range_bits; + if (i < (base_val << 1)) return i; @@ -171,15 +169,15 @@ static int latency_tracker_bucket_pos2us(const struct latency_tracker *lt, int i * "values" : { */ static void latency_tracker_populate_json_root(const struct latency_tracker *lt, - struct json_object *root) + struct json_object *root) { struct json_object *subroot = json_create_object(); json_object_add_value_object(root, "latstats", subroot); json_object_add_value_string(subroot, "type", lt->cfg.write ? "write" : "read"); - if (lt->has_average_latency_field) { - json_object_add_value_uint64(subroot, "average_latency", le64_to_cpu(lt->stats.average_latency)); - } + if (lt->has_average_latency_field) + json_object_add_value_uint64(subroot, "average_latency", + le64_to_cpu(lt->stats.average_latency)); json_object_add_value_object(subroot, "values", lt->bucket_list); } @@ -199,13 +197,12 @@ static void latency_tracker_parse_4_0(const struct latency_tracker *lt) int lower_us = latency_tracker_bucket_pos2us(lt, i); int upper_us = latency_tracker_bucket_pos2us(lt, i + 1); - latency_tracker_bucket_parse(lt, i, lower_us, - upper_us, + latency_tracker_bucket_parse(lt, i, lower_us, upper_us, i < (lt->bucket_list_size - 1)); } } -static void print_dash_separator() +static void print_dash_separator(void) { printf("--------------------------------------------------\n"); } @@ -218,16 +215,14 @@ static void latency_tracker_pre_parse(struct latency_tracker *lt) 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) { + if (lt->has_average_latency_field) printf("Average Latency: %" PRIu64 "\n", le64_to_cpu(lt->stats.average_latency)); - } print_dash_separator(); printf("%-12s%-12s%-12s%-20s\n", "Bucket", "Start", "End", "Value"); print_dash_separator(); } - if (lt->print_flags == JSON) { + if (lt->print_flags == JSON) lt->bucket_list = json_object_new_array(); - } } static void latency_tracker_post_parse(struct latency_tracker *lt) @@ -253,11 +248,10 @@ static void latency_tracker_parse(struct latency_tracker *lt) latency_tracker_parse_3_0(lt); break; case 4: - if (version_minor >= 8){ + if (version_minor >= 8) lt->has_average_latency_field = true; - } latency_tracker_pre_parse(lt); - if (version_minor == 0){ + if (!version_minor) { lt->base_range_bits = BASE_RANGE_BITS_4_0; lt->bucket_list_size = BUCKET_LIST_SIZE_4_0; } @@ -275,7 +269,7 @@ static void latency_tracker_parse(struct latency_tracker *lt) #define LATENCY_TRACKING_FID 0xe2 #define LATENCY_TRACKING_FID_DATA_LEN 32 -static int latency_tracking_is_enable(struct latency_tracker *lt, __u32 * enabled) +static int latency_tracking_is_enable(struct latency_tracker *lt, __u32 *enabled) { struct nvme_get_features_args args_get = { .args_size = sizeof(args_get), @@ -298,13 +292,12 @@ static int latency_tracking_enable(struct latency_tracker *lt) __u32 result; int err; - if (!(lt->cfg.enable || lt->cfg.disable)){ + if (!(lt->cfg.enable || lt->cfg.disable)) return 0; - } - if (lt->cfg.enable && lt->cfg.disable){ - fprintf(stderr,"Cannot enable and disable simultaneously.\n"); - return EINVAL; + if (lt->cfg.enable && lt->cfg.disable) { + fprintf(stderr, "Cannot enable and disable simultaneously.\n"); + return -EINVAL; } struct nvme_set_features_args args_set = { @@ -345,9 +338,9 @@ static int latency_tracker_get_log(struct latency_tracker *lt) { int err; - if (lt->cfg.read && lt->cfg.write){ - fprintf(stderr,"Cannot capture read and write logs simultaneously.\n"); - return EINVAL; + if (lt->cfg.read && lt->cfg.write) { + fprintf(stderr, "Cannot capture read and write logs simultaneously.\n"); + return -EINVAL; } if (!(lt->cfg.read || lt->cfg.write)) @@ -422,31 +415,31 @@ int solidigm_get_latency_tracking_log(int argc, char **argv, struct command *cmd if (lt.print_flags == -EINVAL) { fprintf(stderr, "Invalid output format '%s'\n", lt.cfg.output_format); dev_close(dev); - return EINVAL; + return -EINVAL; } if (lt.cfg.type > 0xf) { fprintf(stderr, "Invalid Log type value '%d'\n", lt.cfg.type); dev_close(dev); - return EINVAL; + return -EINVAL; } if (lt.cfg.type && !(lt.cfg.read || lt.cfg.write)) { fprintf(stderr, "Log type option valid only when retrieving statistics\n"); dev_close(dev); - return EINVAL; + return -EINVAL; } lt.uuid_index = solidigm_get_vu_uuid_index(dev); err = latency_tracking_enable(<); - if (err){ + if (err) { dev_close(dev); return err; } err = latency_tracker_get_log(<); - if (err){ + if (err) { dev_close(dev); return err; } @@ -460,16 +453,16 @@ int solidigm_get_latency_tracking_log(int argc, char **argv, struct command *cmd if (!err) { if (lt.print_flags == JSON) { struct json_object *root = json_create_object(); - json_object_add_value_int(root,"enabled", enabled); + + json_object_add_value_int(root, "enabled", enabled); json_print_object(root, NULL); json_free_object(root); printf("\n"); } else if (lt.print_flags == BINARY) { putchar(enabled); } else { - printf( - "Latency Statistics Tracking (UUID-idx:%d, FID:0x%X) is currently %i.\n", - lt.uuid_index, LATENCY_TRACKING_FID, enabled); + printf("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-log-page-dir.c b/plugins/solidigm/solidigm-log-page-dir.c new file mode 100644 index 0000000..111a433 --- /dev/null +++ b/plugins/solidigm/solidigm-log-page-dir.c @@ -0,0 +1,300 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 Solidigm. + * + * Author: karl.dedow@solidigm.com + */ + +#include "solidigm-log-page-dir.h" + +#include <errno.h> +#include <stdio.h> +#include <unistd.h> + +#include "common.h" +#include "nvme-print.h" + +#include "plugins/ocp/ocp-utils.h" + +#define MIN_VENDOR_LID 0xC0 +#define SOLIDIGM_MAX_UUID 2 + +static const char dash[100] = {[0 ... 99] = '-'}; + +struct lid_dir { + struct __packed { + bool supported; + const char *str; + } lid[NVME_LOG_SUPPORTED_LOG_PAGES_MAX]; +}; + +static void init_lid_dir(struct lid_dir *lid_dir) +{ + static const char *unknown_str = "Unknown"; + + for (int lid = 0; lid < NVME_LOG_SUPPORTED_LOG_PAGES_MAX; lid++) { + lid_dir->lid[lid].supported = false; + lid_dir->lid[lid].str = unknown_str; + } +} + +static bool is_invalid_uuid(const struct nvme_id_uuid_list_entry entry) +{ + static const unsigned char ALL_ZERO_UUID[NVME_UUID_LEN] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + return memcmp(ALL_ZERO_UUID, entry.uuid, NVME_UUID_LEN) == 0; +} + +static bool is_solidigm_uuid(const struct nvme_id_uuid_list_entry entry) +{ + static const unsigned char SOLIDIGM_UUID[NVME_UUID_LEN] = { + 0x96, 0x19, 0x58, 0x6e, 0xc1, 0x1b, 0x43, 0xad, + 0xaa, 0xaa, 0x65, 0x41, 0x87, 0xf6, 0xbb, 0xb2 + }; + + return memcmp(SOLIDIGM_UUID, entry.uuid, NVME_UUID_LEN) == 0; +} + +static bool is_ocp_uuid(const struct nvme_id_uuid_list_entry entry) +{ + static const unsigned char OCP_UUID[NVME_UUID_LEN] = { + 0xc1, 0x94, 0xd5, 0x5b, 0xe0, 0x94, 0x47, 0x94, + 0xa2, 0x1d, 0x29, 0x99, 0x8f, 0x56, 0xbe, 0x6f + }; + + return memcmp(OCP_UUID, entry.uuid, NVME_UUID_LEN) == 0; +} + +static int get_supported_log_pages_log(struct nvme_dev *dev, int uuid_index, + struct nvme_supported_log_pages *supported) +{ + static const __u8 LID; + + memset(supported, 0, sizeof(*supported)); + struct nvme_get_log_args args = { + .lpo = 0, + .result = NULL, + .log = supported, + .args_size = sizeof(args), + .fd = dev_fd(dev), + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .lid = LID, + .len = sizeof(*supported), + .nsid = NVME_NSID_ALL, + .csi = NVME_CSI_NVM, + .lsi = NVME_LOG_LSI_NONE, + .lsp = 0, + .uuidx = uuid_index, + .rae = false, + .ot = false, + }; + + return nvme_get_log(&args); +} + +static struct lid_dir *get_standard_lids(struct nvme_supported_log_pages *supported) +{ + static struct lid_dir standard_dir = { 0 }; + + init_lid_dir(&standard_dir); + standard_dir.lid[0x00].str = "Supported Log Pages"; + standard_dir.lid[0x01].str = "Error Information"; + standard_dir.lid[0x02].str = "SMART / Health Information"; + standard_dir.lid[0x03].str = "Firmware Slot Information"; + standard_dir.lid[0x04].str = "Changed Namespace List"; + standard_dir.lid[0x05].str = "Commands Supported and Effects"; + standard_dir.lid[0x06].str = "Device Self Test"; + standard_dir.lid[0x07].str = "Telemetry Host-Initiated"; + standard_dir.lid[0x08].str = "Telemetry Controller-Initiated"; + standard_dir.lid[0x09].str = "Endurance Group Information"; + standard_dir.lid[0x0A].str = "Predictable Latency Per NVM Set"; + standard_dir.lid[0x0B].str = "Predictable Latency Event Aggregate"; + standard_dir.lid[0x0C].str = "Asymmetric Namespace Access"; + standard_dir.lid[0x0D].str = "Persistent Event Log"; + standard_dir.lid[0x0E].str = "Predictable Latency Event Aggregate"; + standard_dir.lid[0x0F].str = "Endurance Group Event Aggregate"; + standard_dir.lid[0x10].str = "Media Unit Status"; + standard_dir.lid[0x11].str = "Supported Capacity Configuration List"; + standard_dir.lid[0x12].str = "Feature Identifiers Supported and Effects"; + standard_dir.lid[0x13].str = "NVMe-MI Commands Supported and Effects"; + standard_dir.lid[0x14].str = "Command and Feature lockdown"; + standard_dir.lid[0x15].str = "Boot Partition"; + standard_dir.lid[0x16].str = "Rotational Media Information"; + standard_dir.lid[0x70].str = "Discovery"; + standard_dir.lid[0x80].str = "Reservation Notification"; + standard_dir.lid[0x81].str = "Sanitize Status"; + + for (int lid = 0; lid < NVME_LOG_SUPPORTED_LOG_PAGES_MAX; lid++) { + if (!supported->lid_support[lid] || lid >= MIN_VENDOR_LID) + continue; + + standard_dir.lid[lid].supported = true; + } + + return &standard_dir; +} + +static void update_vendor_lid_supported(struct nvme_supported_log_pages *supported, + struct lid_dir *lid_dir) +{ + for (int lid = 0; lid < NVME_LOG_SUPPORTED_LOG_PAGES_MAX; lid++) { + if (!supported->lid_support[lid] || lid < MIN_VENDOR_LID) + continue; + + lid_dir->lid[lid].supported = true; + } +} + +static struct lid_dir *get_solidigm_lids(struct nvme_supported_log_pages *supported) +{ + static struct lid_dir solidigm_dir = { 0 }; + + init_lid_dir(&solidigm_dir); + solidigm_dir.lid[0xC1].str = "Read Commands Latency Statistics"; + solidigm_dir.lid[0xC2].str = "Write Commands Latency Statistics"; + solidigm_dir.lid[0xC4].str = "Endurance Manager Statistics"; + solidigm_dir.lid[0xC5].str = "Temperature Statistics"; + solidigm_dir.lid[0xCA].str = "SMART Attributes"; + + update_vendor_lid_supported(supported, &solidigm_dir); + + return &solidigm_dir; +} + +static struct lid_dir *get_ocp_lids(struct nvme_supported_log_pages *supported) +{ + static struct lid_dir ocp_dir = { 0 }; + + init_lid_dir(&ocp_dir); + ocp_dir.lid[0xC0].str = "OCP SMART / Health Information Extended"; + ocp_dir.lid[0xC1].str = "OCP Error Recovery"; + ocp_dir.lid[0xC2].str = "OCP Firmware Activation History"; + ocp_dir.lid[0xC3].str = "OCP Latency Monitor"; + ocp_dir.lid[0xC4].str = "OCP Device Capabilities"; + ocp_dir.lid[0xC5].str = "OCP Unsupported Requirements"; + + update_vendor_lid_supported(supported, &ocp_dir); + + return &ocp_dir; +} + +static void supported_log_pages_normal(struct lid_dir *lid_dir[SOLIDIGM_MAX_UUID + 1]) +{ + printf("%-5s %-4s %-42s\n", "uuidx", "LID", "Description"); + printf("%-.5s %-.4s %-.42s\n", dash, dash, dash); + + for (int uuid_index = 0; uuid_index <= SOLIDIGM_MAX_UUID; uuid_index++) { + if (!lid_dir[uuid_index]) + continue; + + for (int lid = 0; lid < NVME_LOG_SUPPORTED_LOG_PAGES_MAX; lid++) { + if (!lid_dir[uuid_index]->lid[lid].supported) + continue; + + printf("%-5d 0x%02x %s\n", le32_to_cpu(uuid_index), le32_to_cpu(lid), + lid_dir[uuid_index]->lid[lid].str); + } + } +} + +static void supported_log_pages_json(struct lid_dir *lid_dir[SOLIDIGM_MAX_UUID + 1]) +{ + struct json_object *root = json_create_array(); + + for (int uuid_index = 0; uuid_index <= SOLIDIGM_MAX_UUID; uuid_index++) { + if (!lid_dir[uuid_index]) + continue; + + for (int lid = 0; lid < NVME_LOG_SUPPORTED_LOG_PAGES_MAX; lid++) { + if (!lid_dir[uuid_index]->lid[lid].supported) + continue; + + struct json_object *lid_obj = json_create_object(); + + json_object_add_value_uint(lid_obj, "uuidx", le32_to_cpu(uuid_index)); + json_object_add_value_uint(lid_obj, "lid", le32_to_cpu(lid)); + json_object_add_value_string(lid_obj, "description", + lid_dir[uuid_index]->lid[lid].str); + json_array_add_value_object(root, lid_obj); + } + } + + json_print_object(root, NULL); + json_free_object(root); + printf("\n"); +} + +int solidigm_get_log_page_directory_log(int argc, char **argv, struct command *cmd, + struct plugin *plugin) +{ + const int NO_UUID_INDEX = 0; + const char *description = "Retrieves list of supported log pages for each UUID index."; + char *format = "normal"; + + OPT_ARGS(options) = { + OPT_FMT("output-format", 'o', &format, "output format : normal | json"), + OPT_END() + }; + + struct nvme_dev *dev = NULL; + int err = parse_and_open(&dev, argc, argv, description, options); + + if (err) + return err; + + struct lid_dir *lid_dirs[SOLIDIGM_MAX_UUID + 1] = { 0 }; + struct nvme_id_uuid_list uuid_list = { 0 }; + struct nvme_supported_log_pages supported = { 0 }; + + err = get_supported_log_pages_log(dev, NO_UUID_INDEX, &supported); + + if (!err) { + lid_dirs[NO_UUID_INDEX] = get_standard_lids(&supported); + + // Assume VU logs are the Solidigm log pages if UUID not supported. + if (nvme_identify_uuid(dev_fd(dev), &uuid_list)) { + struct lid_dir *solidigm_lid_dir = get_solidigm_lids(&supported); + + // Transfer supported Solidigm lids to lid directory at UUID index 0 + for (int lid = 0; lid < NVME_LOG_SUPPORTED_LOG_PAGES_MAX; lid++) { + if (solidigm_lid_dir->lid[lid].supported) + lid_dirs[NO_UUID_INDEX]->lid[lid] = solidigm_lid_dir->lid[lid]; + } + } else { + for (int uuid_index = 1; uuid_index <= SOLIDIGM_MAX_UUID; uuid_index++) { + if (is_invalid_uuid(uuid_list.entry[uuid_index - 1])) + break; + else if (get_supported_log_pages_log(dev, uuid_index, &supported)) + continue; + + if (is_solidigm_uuid(uuid_list.entry[uuid_index - 1])) + lid_dirs[uuid_index] = get_solidigm_lids(&supported); + else if (is_ocp_uuid(uuid_list.entry[uuid_index - 1])) + lid_dirs[uuid_index] = get_ocp_lids(&supported); + } + } + } else { + nvme_show_status(err); + } + + if (!err) { + const enum nvme_print_flags print_flag = validate_output_format(format); + + if (print_flag == NORMAL) { + supported_log_pages_normal(lid_dirs); + } else if (print_flag == JSON) { + supported_log_pages_json(lid_dirs); + } else { + fprintf(stderr, "Error: Invalid output format specified: %s.\n", format); + err = -EINVAL; + } + } + + /* Redundant close() to make static code analysis happy */ + close(dev->direct.fd); + dev_close(dev); + return err; +} diff --git a/plugins/solidigm/solidigm-log-page-dir.h b/plugins/solidigm/solidigm-log-page-dir.h new file mode 100644 index 0000000..48777df --- /dev/null +++ b/plugins/solidigm/solidigm-log-page-dir.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (c) 2023 Solidigm. + * + * Authors: karl.dedow@solidigm.com + */ + +#ifndef SOLIDIGM_LOG_PAGE_DIRECTORY_H +#define SOLIDIGM_LOG_PAGE_DIRECTORY_H + +struct command; +struct plugin; + +int solidigm_get_log_page_directory_log(int argc, char **argv, struct command *cmd, + struct plugin *plugin); + +#endif diff --git a/plugins/solidigm/solidigm-market-log.c b/plugins/solidigm/solidigm-market-log.c new file mode 100644 index 0000000..d7d38da --- /dev/null +++ b/plugins/solidigm/solidigm-market-log.c @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 Solidigm. + * + * Authors: leonardo.da.cunha@solidigm.com + * Hardeep.Dhillon@solidigm.com + */ + +#include <fcntl.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <inttypes.h> +#include <linux/limits.h> + +#include "common.h" +#include "nvme.h" +#include "libnvme.h" +#include "plugin.h" +#include "nvme-print.h" + +#define MARKET_LOG_MAX_SIZE 512 + +int sldgm_get_market_log(int argc, char **argv, struct command *command, + struct plugin *plugin) +{ + const char *desc = "Get Solidigm Marketing Name log and show it."; + const char *raw = "dump output in binary format"; + struct nvme_dev *dev; + char log[MARKET_LOG_MAX_SIZE]; + int err; + + struct config { + bool raw_binary; + }; + + struct config cfg = { + }; + + OPT_ARGS(opts) = { + 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 = nvme_get_log_simple(dev_fd(dev), 0xdd, sizeof(log), log); + if (!err) { + if (!cfg.raw_binary) + printf("Solidigm Marketing Name Log:\n%s\n", log); + else + d_raw((unsigned char *)&log, sizeof(log)); + } else if (err > 0) + + nvme_show_status(err); + /* Redundant close() to make static code analysis happy */ + close(dev->direct.fd); + dev_close(dev); + return err; +} diff --git a/plugins/solidigm/solidigm-market-log.h b/plugins/solidigm/solidigm-market-log.h new file mode 100644 index 0000000..6f808c4 --- /dev/null +++ b/plugins/solidigm/solidigm-market-log.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (c) 2023 Solidigm. + * + * Author: hardeep.dhillon@solidigm.com + */ + +int sldgm_get_market_log(int argc, char **argv, struct command *cmd, struct plugin *plugin); diff --git a/plugins/solidigm/solidigm-nvme.c b/plugins/solidigm/solidigm-nvme.c index 0e42bd6..b0db1ea 100644 --- a/plugins/solidigm/solidigm-nvme.c +++ b/plugins/solidigm/solidigm-nvme.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (c) 2022 Solidigm. + * Copyright (c) 2022-2023 Solidigm. * * Author: leonardo.da.cunha@solidigm.com */ @@ -10,19 +10,34 @@ #define CREATE_CMD #include "solidigm-nvme.h" +#include "solidigm-id-ctrl.h" #include "solidigm-smart.h" +#include "solidigm-internal-logs.h" #include "solidigm-garbage-collection.h" #include "solidigm-latency-tracking.h" #include "solidigm-telemetry.h" +#include "solidigm-log-page-dir.h" +#include "solidigm-market-log.h" #include "plugins/ocp/ocp-clear-fw-update-history.h" #include "plugins/ocp/ocp-smart-extended-log.h" +#include "plugins/ocp/ocp-fw-activation-history.h" + +static int id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + return __id_ctrl(argc, argv, cmd, plugin, sldgm_id_ctrl); +} static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { return solidigm_get_additional_smart_log(argc, argv, cmd, plugin); } +static int get_internal_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + return solidigm_get_internal_log(argc, argv, cmd, plugin); +} + static int get_garbage_collection_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { return solidigm_get_garbage_collection_log(argc, argv, cmd, plugin); @@ -49,3 +64,21 @@ static int smart_cloud(int argc, char **argv, struct command *cmd, { return ocp_smart_add_log(argc, argv, cmd, plugin); } + +static int fw_activation_history(int argc, char **argv, struct command *cmd, + struct plugin *plugin) +{ + return ocp_fw_activation_history_log(argc, argv, cmd, plugin); +} + +static int get_log_page_directory_log(int argc, char **argv, struct command *cmd, + struct plugin *plugin) +{ + return solidigm_get_log_page_directory_log(argc, argv, cmd, plugin); +} + +static int get_market_log(int argc, char **argv, struct command *cmd, + struct plugin *plugin) +{ + return sldgm_get_market_log(argc, argv, cmd, plugin); +} diff --git a/plugins/solidigm/solidigm-nvme.h b/plugins/solidigm/solidigm-nvme.h index 1fdc6a6..69b63e5 100644 --- a/plugins/solidigm/solidigm-nvme.h +++ b/plugins/solidigm/solidigm-nvme.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (c) 2022 Solidigm. + * Copyright (c) 2022-2023 Solidigm. * * Author: leonardo.da.cunha@solidigm.com */ @@ -13,18 +13,21 @@ #include "cmd.h" -#define SOLIDIGM_PLUGIN_VERSION "0.8" +#define SOLIDIGM_PLUGIN_VERSION "0.14" PLUGIN(NAME("solidigm", "Solidigm vendor specific extensions", SOLIDIGM_PLUGIN_VERSION), COMMAND_LIST( + ENTRY("id-ctrl", "Send NVMe Identify Controller", id_ctrl) 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("vs-internal-log", "Retrieve Debug log binaries", get_internal_log) ENTRY("garbage-collect-log", "Retrieve Garbage Collection Log", get_garbage_collection_log) + ENTRY("market-log", "Retrieve Market Log", get_market_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) + ENTRY("clear-fw-activate-history", "Clear firmware update history log (redirects to ocp plug-in)", clear_fw_update_history) + ENTRY("vs-fw-activate-history", "Get firmware activation history log (redirects to ocp plug-in)", fw_activation_history) + ENTRY("log-page-directory", "Retrieve log page directory", get_log_page_directory_log) ) ); diff --git a/plugins/solidigm/solidigm-smart.c b/plugins/solidigm/solidigm-smart.c index 568d3ab..e3d468a 100644 --- a/plugins/solidigm/solidigm-smart.c +++ b/plugins/solidigm/solidigm-smart.c @@ -21,32 +21,31 @@ #include "solidigm-smart.h" #include "solidigm-util.h" -struct __attribute__((packed)) nvme_additional_smart_log_item { +struct __packed nvme_additional_smart_log_item { __u8 id; __u8 _kp[2]; __u8 normalized; __u8 _np; - union __attribute__((packed)) { + union __packed { __u8 raw[6]; - struct __attribute__((packed)) wear_level { + struct __packed wear_level { __le16 min; __le16 max; __le16 avg; } wear_level; - struct __attribute__((packed)) thermal_throttle { + struct __packed thermal_throttle { __u8 pct; __u32 count; } thermal_throttle; - } ; + }; __u8 _rp; -} ; -typedef struct nvme_additional_smart_log_item smart_log_item_t; +}; #define VU_SMART_PAGE_SIZE 512 -#define VU_SMART_MAX_ITEMS VU_SMART_PAGE_SIZE / sizeof(smart_log_item_t) -typedef struct vu_smart_log { - smart_log_item_t item[VU_SMART_MAX_ITEMS]; -} vu_smart_log_t; +#define VU_SMART_MAX_ITEMS (VU_SMART_PAGE_SIZE / sizeof(struct nvme_additional_smart_log_item)) +struct vu_smart_log { + struct nvme_additional_smart_log_item item[VU_SMART_MAX_ITEMS]; +}; static char *id_to_name(__u8 id) { @@ -110,11 +109,10 @@ static char *id_to_name(__u8 id) } } -static void smart_log_item_print(smart_log_item_t *item) +static void smart_log_item_print(struct nvme_additional_smart_log_item *item) { - if (!item->id) { + if (!item->id) return; - } printf("%#x %-45s %3d ", item->id, id_to_name(item->id), item->normalized); @@ -136,13 +134,12 @@ static void smart_log_item_print(smart_log_item_t *item) } } -static void smart_log_item_add_json(smart_log_item_t *item, struct json_object *dev_stats) +static void smart_log_item_add_json(struct nvme_additional_smart_log_item *item, struct json_object *dev_stats) { struct json_object *entry_stats = json_create_object(); - if (!item->id) { + if (!item->id) return; - } json_object_add_value_int(entry_stats, "normalized", item->normalized); @@ -162,15 +159,14 @@ static void smart_log_item_add_json(smart_log_item_t *item, struct json_object * json_object_add_value_object(dev_stats, id_to_name(item->id), entry_stats); } -static void vu_smart_log_show_json(vu_smart_log_t *payload, unsigned int nsid, const char *devname) +static void vu_smart_log_show_json(struct vu_smart_log *payload, unsigned int nsid, const char *devname) { struct json_object *dev_stats = json_create_object(); - smart_log_item_t *item = payload->item; + struct nvme_additional_smart_log_item *item = payload->item; struct json_object *root; - for (int i = 0; i < VU_SMART_MAX_ITEMS; i++) { + for (int i = 0; i < VU_SMART_MAX_ITEMS; i++) smart_log_item_add_json(&item[i], dev_stats); - } root = json_create_object(); json_object_add_value_string(root, "Solidigm SMART log", devname); @@ -180,26 +176,25 @@ 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(struct vu_smart_log *payload, unsigned int nsid, const char *devname, __u8 uuid_index) { - smart_log_item_t *item = payload->item; + struct nvme_additional_smart_log_item *item = payload->item; 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++) { + for (int i = 0; i < VU_SMART_MAX_ITEMS; i++) smart_log_item_print(&item[i]); - } } int solidigm_get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Get Solidigm vendor specific smart log (optionally, "\ - "for the specified namespace), and show it."; + const char *desc = + "Get Solidigm vendor specific smart log (optionally, for the specified namespace), and show it."; const int solidigm_vu_smart_log_id = 0xCA; - vu_smart_log_t smart_log_payload; + struct vu_smart_log smart_log_payload; enum nvme_print_flags flags; struct nvme_dev *dev; int err; @@ -254,15 +249,14 @@ int solidigm_get_additional_smart_log(int argc, char **argv, struct command *cmd err = nvme_get_log(&args); if (!err) { - if (flags & JSON) { + if (flags & JSON) vu_smart_log_show_json(&smart_log_payload, cfg.namespace_id, dev->name); - } else if (flags & BINARY) { + else if (flags & BINARY) d_raw((unsigned char *)&smart_log_payload, sizeof(smart_log_payload)); - } else { + else vu_smart_log_show(&smart_log_payload, cfg.namespace_id, 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 9946991..472284a 100644 --- a/plugins/solidigm/solidigm-telemetry.c +++ b/plugins/solidigm/solidigm-telemetry.c @@ -112,7 +112,7 @@ int solidigm_get_telemetry_log(int argc, char **argv, struct command *cmd, struc } if (cfg.cfg_file) { - char *conf_str = 0; + char *conf_str = NULL; size_t length = 0; err = read_file2buffer(cfg.cfg_file, &conf_str, &length); @@ -121,9 +121,10 @@ int solidigm_get_telemetry_log(int argc, char **argv, struct command *cmd, struc cfg.cfg_file, strerror(err)); goto close_fd; } - struct json_tokener * jstok = json_tokener_new(); + struct json_tokener *jstok = json_tokener_new(); tl.configuration = json_tokener_parse_ex(jstok, conf_str, length); + free(conf_str); if (jstok->err != json_tokener_success) { SOLIDIGM_LOG_WARNING("Parsing error on JSON configuration file %s: %s (at offset %d)", cfg.cfg_file, @@ -160,11 +161,7 @@ int solidigm_get_telemetry_log(int argc, char **argv, struct command *cmd, struc goto close_fd; } } - solidigm_telemetry_log_header_parse(&tl); - if (cfg.cfg_file) - solidigm_telemetry_log_data_areas_parse(&tl, cfg.data_area); - else - solidigm_telemetry_log_cod_parse(&tl); + solidigm_telemetry_log_data_areas_parse(&tl, cfg.data_area); json_print_object(tl.root, NULL); json_free_object(tl.root); diff --git a/plugins/solidigm/solidigm-telemetry/cod.c b/plugins/solidigm/solidigm-telemetry/cod.c index 7accc53..363822a 100644 --- a/plugins/solidigm/solidigm-telemetry/cod.c +++ b/plugins/solidigm/solidigm-telemetry/cod.c @@ -51,22 +51,20 @@ const char *oemDataMapDesc[] = { "All Time Current Max Wear Level", // 0x28 "Media Wear Remaining", // 0x29 "Total Non-Defrag Writes", // 0x2A - "Number of sectors relocated in reaction to an error" //Uid 0x2B = 43 + "Media Health Relocations" //Uid 0x2B = 43 }; -static const char * getOemDataMapDescription(__u32 id) +static const char *getOemDataMapDescription(uint32_t id) { - if (id < (sizeof(oemDataMapDesc) / sizeof(oemDataMapDesc[0]))) { + if (id < ARRAY_SIZE(oemDataMapDesc)) return oemDataMapDesc[id]; - } return "unknown"; } #define OEMSIGNATURE 0x504D4443 #pragma pack(push, cod, 1) -struct cod_header -{ +struct cod_header { uint32_t versionMajor; uint32_t versionMinor; uint32_t Signature; //!Fixed signature value (0x504D4443) for identification and validation @@ -75,8 +73,7 @@ struct cod_header uint8_t Reserved[12]; }; -struct cod_item -{ +struct cod_item { uint32_t DataFieldMapUid; //!The data field unique identifier value uint32_t reserved1 : 8; uint32_t dataFieldType : 8; @@ -90,8 +87,7 @@ struct cod_item uint8_t Reserved2[8]; }; -struct cod_map -{ +struct cod_map { struct cod_header header; struct cod_item items[]; }; @@ -100,8 +96,7 @@ struct cod_map void solidigm_telemetry_log_cod_parse(struct telemetry_log *tl) { - enum cod_field_type - { + enum cod_field_type { INTEGER, FLOAT, STRING, @@ -118,77 +113,78 @@ void solidigm_telemetry_log_cod_parse(struct telemetry_log *tl) return; if (!json_object_object_get_ex(telemetry_header, "reasonIdentifier", &reason_id)) return; - if (!json_object_object_get_ex(reason_id, "OemDataMapOffset", &COD_offset)) + if (!json_object_object_get_ex(reason_id, "oemDataMapOffset", &COD_offset)) return; - __u64 offset = json_object_get_int(COD_offset); + uint64_t offset = json_object_get_int(COD_offset); - if (offset == 0) { + if (!offset) return; - } if ((offset + sizeof(struct cod_header)) > tl->log_size) { SOLIDIGM_LOG_WARNING("Warning: COD map header out of bounds."); return; } - const struct cod_map *data = (struct cod_map *) (((__u8 *)tl->log ) + offset); + const struct cod_map *data = (struct cod_map *) (((uint8_t *)tl->log) + offset); uint32_t signature = be32_to_cpu(data->header.Signature); - if ( signature != OEMSIGNATURE){ + + if (signature != OEMSIGNATURE) { SOLIDIGM_LOG_WARNING("Warning: Unsupported COD data signature %x!", signature); return; } - if ((offset + data->header.MapSizeInBytes) > tl->log_size){ + if ((offset + data->header.MapSizeInBytes) > tl->log_size) { SOLIDIGM_LOG_WARNING("Warning: COD map data out of bounds."); return; } struct json_object *cod = json_create_object(); + json_object_object_add(tl->root, "cod", cod); - for (int i =0 ; i < data->header.EntryCount; i++) { + for (uint64_t i = 0; i < data->header.EntryCount; i++) { if ((offset + sizeof(struct cod_header) + (i + 1) * sizeof(struct cod_item)) > - tl->log_size){ - SOLIDIGM_LOG_WARNING("Warning: COD data out of bounds at item %d!", i); + tl->log_size) { + SOLIDIGM_LOG_WARNING("Warning: COD data out of bounds at item %"PRIu64"!", + i); return; } struct cod_item item = data->items[i]; - if (item.DataFieldOffset + item.DataFieldOffset > tl->log_size) { + + if (item.DataFieldOffset + item.DataFieldOffset > tl->log_size) continue; - } - if (item.dataInvalid) { + if (item.dataInvalid) continue; - } - uint8_t *val = ((uint8_t *)tl->log )+ item.DataFieldOffset; + uint8_t *val = ((uint8_t *)tl->log) + item.DataFieldOffset; const char *key = getOemDataMapDescription(item.DataFieldMapUid); - switch(item.dataFieldType){ - case(INTEGER): - if (item.issigned) { - json_object_object_add(cod, key, - json_object_new_int64(le64_to_cpu(*(uint64_t *)val))); - } else { - json_object_add_value_uint64(cod, key, le64_to_cpu(*(uint64_t *)val)); - } - break; - case(FLOAT): - json_object_add_value_float(cod, key, *(float *) val); - break; - case(STRING): - json_object_object_add(cod, key, - json_object_new_string_len((const char *)val, item.DataFieldSizeInBytes)); - break; - case(TWO_BYTE_ASCII): - json_object_object_add(cod, key, - json_object_new_string_len((const char *)val,2)); - break; - case(FOUR_BYTE_ASCII): + + switch (item.dataFieldType) { + case INTEGER: + if (item.issigned) json_object_object_add(cod, key, - json_object_new_string_len((const char *)val, 4)); - break; - default: - SOLIDIGM_LOG_WARNING("Warning: Unknown COD field type (%d)", item.DataFieldMapUid); - + json_object_new_int64(le64_to_cpu(*(uint64_t *)val))); + else + json_object_add_value_uint64(cod, key, le64_to_cpu(*(uint64_t *)val)); + break; + case FLOAT: + json_object_add_value_float(cod, key, *(float *)val); + break; + case STRING: + json_object_object_add(cod, key, + json_object_new_string_len((const char *)val, item.DataFieldSizeInBytes)); + break; + case TWO_BYTE_ASCII: + json_object_object_add(cod, key, + json_object_new_string_len((const char *)val, 2)); + break; + case FOUR_BYTE_ASCII: + json_object_object_add(cod, key, + json_object_new_string_len((const char *)val, 4)); + break; + default: + SOLIDIGM_LOG_WARNING("Warning: Unknown COD field type (%d)", item.DataFieldMapUid); + break; } } } diff --git a/plugins/solidigm/solidigm-telemetry/config.c b/plugins/solidigm/solidigm-telemetry/config.c index 5111703..cc2a8bb 100644 --- a/plugins/solidigm/solidigm-telemetry/config.c +++ b/plugins/solidigm/solidigm-telemetry/config.c @@ -4,13 +4,17 @@ * * Author: leonardo.da.cunha@solidigm.com */ -#include <stdbool.h> -#include "util/json.h" + #include <stdio.h> +#include <string.h> +#include "config.h" // max 16 bit unsigned integer nummber 65535 #define MAX_16BIT_NUM_AS_STRING_SIZE 6 +#define OBJ_NAME_PREFIX "UID_" +#define NLOG_OBJ_PREFIX OBJ_NAME_PREFIX "NLOG_" + static bool config_get_by_version(const struct json_object *obj, int version_major, int version_minor, struct json_object **value) { @@ -28,17 +32,45 @@ static bool config_get_by_version(const struct json_object *obj, int version_maj return value != NULL; } -bool solidigm_config_get_by_token_version(const struct json_object *obj, int token_id, +bool solidigm_config_get_struct_by_token_version(const struct json_object *config, int token_id, int version_major, int version_minor, struct json_object **value) { - struct json_object *token_obj = NULL; + struct json_object *token = NULL; char str_key[MAX_16BIT_NUM_AS_STRING_SIZE]; snprintf(str_key, sizeof(str_key), "%d", token_id); - if (!json_object_object_get_ex(obj, str_key, &token_obj)) + if (!json_object_object_get_ex(config, str_key, &token)) return false; - if (!config_get_by_version(token_obj, version_major, version_minor, value)) + if (!config_get_by_version(token, version_major, version_minor, value)) return false; return value != NULL; } + +const char *solidigm_config_get_nlog_obj_name(const struct json_object *config, uint32_t token) +{ + struct json_object *nlog_names = NULL; + struct json_object *obj_name; + char hex_header[STR_HEX32_SIZE]; + const char *name; + + if (!json_object_object_get_ex(config, "TELEMETRY_OBJECT_UIDS", &nlog_names)) + return NULL; + snprintf(hex_header, STR_HEX32_SIZE, "0x%08X", token); + + if (!json_object_object_get_ex(nlog_names, hex_header, &obj_name)) + return NULL; + name = json_object_get_string(obj_name); + if (strncmp(NLOG_OBJ_PREFIX, name, strlen(NLOG_OBJ_PREFIX))) + return NULL; + + return &name[strlen(OBJ_NAME_PREFIX)]; +} + +struct json_object *solidigm_config_get_nlog_formats(const struct json_object *config) +{ + struct json_object *nlog_formats = NULL; + + json_object_object_get_ex(config, "NLOG_FORMATS", &nlog_formats); + return nlog_formats; +} diff --git a/plugins/solidigm/solidigm-telemetry/config.h b/plugins/solidigm/solidigm-telemetry/config.h index 30e61ff..4e56ba3 100644 --- a/plugins/solidigm/solidigm-telemetry/config.h +++ b/plugins/solidigm/solidigm-telemetry/config.h @@ -7,7 +7,13 @@ #include <stdbool.h> #include "util/json.h" -bool solidigm_config_get_by_token_version(const struct json_object *obj, +#define STR_HEX32_SIZE sizeof("0x00000000") + +bool solidigm_config_get_struct_by_token_version(const struct json_object *obj, int key, int subkey, int subsubkey, struct json_object **value); + +const char *solidigm_config_get_nlog_obj_name(const struct json_object *config, uint32_t token); +struct json_object *solidigm_config_get_nlog_formats(const struct json_object *config); + diff --git a/plugins/solidigm/solidigm-telemetry/data-area.c b/plugins/solidigm/solidigm-telemetry/data-area.c index 2f18ea2..0cfa56c 100644 --- a/plugins/solidigm/solidigm-telemetry/data-area.c +++ b/plugins/solidigm/solidigm-telemetry/data-area.c @@ -6,25 +6,29 @@ */ #include "common.h" +#include "header.h" +#include "cod.h" #include "data-area.h" #include "config.h" +#include "nlog.h" #include <ctype.h> #define SIGNED_INT_PREFIX "int" #define BITS_IN_BYTE 8 #define MAX_WARNING_SIZE 1024 +#define MAX_ARRAY_RANK 16 static bool telemetry_log_get_value(const struct telemetry_log *tl, - uint32_t offset_bit, uint32_t size_bit, + uint64_t offset_bit, uint32_t size_bit, bool is_signed, struct json_object **val_obj) { uint32_t offset_bit_from_byte; uint32_t additional_size_byte; uint32_t offset_byte; - uint32_t val; + uint64_t val; - if (size_bit == 0) { + if (!size_bit) { char err_msg[MAX_WARNING_SIZE]; snprintf(err_msg, MAX_WARNING_SIZE, @@ -34,7 +38,7 @@ static bool telemetry_log_get_value(const struct telemetry_log *tl, return false; } additional_size_byte = (size_bit - 1) ? (size_bit - 1) / BITS_IN_BYTE : 0; - offset_byte = offset_bit / BITS_IN_BYTE; + offset_byte = (uint32_t)offset_bit / BITS_IN_BYTE; if (offset_byte > (tl->log_size - additional_size_byte)) { char err_msg[MAX_WARNING_SIZE]; @@ -47,15 +51,14 @@ static bool telemetry_log_get_value(const struct telemetry_log *tl, return false; } - offset_bit_from_byte = offset_bit - (offset_byte * BITS_IN_BYTE); + offset_bit_from_byte = (uint32_t) (offset_bit - ((uint64_t)offset_byte * BITS_IN_BYTE)); if ((size_bit + offset_bit_from_byte) > (sizeof(uint64_t) * BITS_IN_BYTE)) { char err_msg[MAX_WARNING_SIZE]; snprintf(err_msg, MAX_WARNING_SIZE, - "Value crossing 64 bit, byte aligned bounday, " - "not supported. size_bit=%u, offset_bit_from_byte=%u.", - size_bit, offset_bit_from_byte); + "Value crossing 64 bit, byte aligned bounday, not supported. size_bit=%u, offset_bit_from_byte=%u.", + size_bit, offset_bit_from_byte); *val_obj = json_object_new_string(err_msg); return false; @@ -67,7 +70,7 @@ static bool telemetry_log_get_value(const struct telemetry_log *tl, val &= (1ULL << size_bit) - 1; if (is_signed) { if (val >> (size_bit - 1)) - val |= -1ULL << size_bit; + val |= (0ULL - 1) << size_bit; *val_obj = json_object_new_int64(val); } else { *val_obj = json_object_new_uint64(val); @@ -78,23 +81,24 @@ static bool telemetry_log_get_value(const struct telemetry_log *tl, static int telemetry_log_structure_parse(const struct telemetry_log *tl, struct json_object *struct_def, - size_t parent_offset_bit, + uint64_t parent_offset_bit, struct json_object *output, struct json_object *metadata) { struct json_object *obj_arraySizeArray = NULL; struct json_object *obj = NULL; struct json_object *obj_memberList; - struct json_object *major_dimension; + struct json_object *major_dimension = NULL; struct json_object *sub_output; bool is_enumeration = false; bool has_member_list; const char *type = ""; const char *name; size_t array_rank; - size_t offset_bit; - size_t size_bit; - uint32_t linear_array_pos_bit; + uint64_t offset_bit; + uint32_t size_bit; + uint64_t linear_array_pos_bit; + uint32_t array_size_dimension[MAX_ARRAY_RANK]; if (!json_object_object_get_ex(struct_def, "name", &obj)) { SOLIDIGM_LOG_WARNING("Warning: Structure definition missing property 'name': %s", @@ -113,22 +117,22 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl, type = json_object_get_string(obj); if (!json_object_object_get_ex(struct_def, "offsetBit", &obj)) { - SOLIDIGM_LOG_WARNING("Warning: Structure definition missing " - "property 'offsetBit': %s", - json_object_to_json_string(struct_def)); + SOLIDIGM_LOG_WARNING( + "Warning: Structure definition missing property 'offsetBit': %s", + json_object_to_json_string(struct_def)); return -1; } offset_bit = json_object_get_uint64(obj); if (!json_object_object_get_ex(struct_def, "sizeBit", &obj)) { - SOLIDIGM_LOG_WARNING("Warning: Structure definition missing " - "property 'sizeBit': %s", - json_object_to_json_string(struct_def)); + SOLIDIGM_LOG_WARNING( + "Warning: Structure definition missing property 'sizeBit': %s", + json_object_to_json_string(struct_def)); return -1; } - size_bit = json_object_get_uint64(obj); + size_bit = (uint32_t)json_object_get_uint64(obj); if (json_object_object_get_ex(struct_def, "enum", &obj)) is_enumeration = json_object_get_boolean(obj); @@ -139,25 +143,30 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl, if (!json_object_object_get_ex(struct_def, "arraySize", &obj_arraySizeArray)) { - SOLIDIGM_LOG_WARNING("Warning: Structure definition missing " - "property 'arraySize': %s", - json_object_to_json_string(struct_def)); + SOLIDIGM_LOG_WARNING( + "Warning: Structure definition missing property 'arraySize': %s", + json_object_to_json_string(struct_def)); return -1; } array_rank = json_object_array_length(obj_arraySizeArray); - if (array_rank == 0) { - SOLIDIGM_LOG_WARNING("Warning: Structure property 'arraySize' " - "don't support flexible array: %s", - json_object_to_json_string(struct_def)); + if (!array_rank) { + SOLIDIGM_LOG_WARNING( + "Warning: Structure property 'arraySize' don't support flexible array: %s", + json_object_to_json_string(struct_def)); + return -1; + } + if (array_rank > MAX_ARRAY_RANK) { + SOLIDIGM_LOG_WARNING( + "Warning: Structure property 'arraySize' don't support more than %d dimensions: %s", + MAX_ARRAY_RANK, json_object_to_json_string(struct_def)); return -1; } - uint32_t array_size_dimension[array_rank]; for (size_t i = 0; i < array_rank; i++) { struct json_object *dimension = json_object_array_get_idx(obj_arraySizeArray, i); - array_size_dimension[i] = json_object_get_uint64(dimension); + array_size_dimension[i] = json_object_get_int(dimension); major_dimension = dimension; } if (array_rank > 1) { @@ -165,7 +174,7 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl, uint32_t prev_index_offset_bit = 0; struct json_object *dimension_output; - for (int i = 1; i < (array_rank - 1); i++) + for (unsigned int i = 1; i < (array_rank - 1); i++) linear_pos_per_index *= array_size_dimension[i]; dimension_output = json_create_array(); @@ -181,9 +190,9 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl, json_object_get(major_dimension); json_object_array_del_idx(obj_arraySizeArray, array_rank - 1, 1); - for (int i = 0 ; i < array_size_dimension[0]; i++) { + for (unsigned int i = 0 ; i < array_size_dimension[0]; i++) { struct json_object *sub_array = json_create_array(); - size_t offset; + uint64_t offset; offset = parent_offset_bit + prev_index_offset_bit; @@ -214,7 +223,7 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl, if (is_enumeration || !has_member_list) { bool is_signed = !strncmp(type, SIGNED_INT_PREFIX, sizeof(SIGNED_INT_PREFIX)-1); struct json_object *val_obj; - size_t offset; + uint64_t offset; offset = parent_offset_bit + offset_bit + linear_array_pos_bit; if (telemetry_log_get_value(tl, offset, size_bit, is_signed, &val_obj)) { @@ -223,10 +232,10 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl, else json_object_object_add(sub_output, name, val_obj); } else { - SOLIDIGM_LOG_WARNING("Warning: %s From property '%s', " - "array index %u, structure definition: %s", - json_object_get_string(val_obj), - name, j, json_object_to_json_string(struct_def)); + SOLIDIGM_LOG_WARNING( + "Warning: %s From property '%s', array index %u, structure definition: %s", + json_object_get_string(val_obj), name, j, + json_object_to_json_string(struct_def)); json_free_object(val_obj); } } else { @@ -241,7 +250,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++) { struct json_object *member = json_object_array_get_idx(obj_memberList, k); - size_t offset; + uint64_t offset; offset = parent_offset_bit + offset_bit + linear_array_pos_bit; telemetry_log_structure_parse(tl, member, offset, @@ -293,6 +302,27 @@ static int telemetry_log_data_area_get_offset(const struct telemetry_log *tl, return 0; } +static int telemetry_log_nlog_parse(const struct telemetry_log *tl, struct json_object *formats, + uint64_t nlog_file_offset, uint64_t nlog_size, + struct json_object *output, struct json_object *metadata) +{ + /* boundary check */ + if (tl->log_size < (nlog_file_offset + nlog_size)) { + const char *name = ""; + int media_bank = -1; + struct json_object *jobj; + + if (json_object_object_get_ex(metadata, "objName", &jobj)) + name = json_object_get_string(jobj); + if (json_object_object_get_ex(metadata, "mediaBankId", &jobj)) + media_bank = json_object_get_int(jobj); + SOLIDIGM_LOG_WARNING("%s:%d do not fit this log dump.", name, media_bank); + return -1; + } + return solidigm_nlog_parse(((char *) tl->log) + nlog_file_offset, + nlog_size, formats, metadata, output); +} + struct toc_item { uint32_t OffsetBytes; uint32_t ContentSizeBytes; @@ -319,7 +349,6 @@ struct telemetry_object_header { uint8_t Reserved[3]; }; - static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl, enum nvme_telemetry_da da, struct json_object *toc_array, @@ -331,30 +360,35 @@ static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl, char *payload; uint32_t da_offset; uint32_t da_size; + struct json_object *nlog_formats; if (telemetry_log_data_area_get_offset(tl, da, &da_offset, &da_size)) return; toc = (struct table_of_contents *)(((char *)tl->log) + da_offset); payload = (char *) tl->log; + nlog_formats = solidigm_config_get_nlog_formats(tl->configuration); for (int i = 0; i < toc->header.TableOfContentsCount; i++) { struct json_object *structure_definition = NULL; struct json_object *toc_item; uint32_t obj_offset; bool has_struct; - - if ((char *)&toc->items[i] > (((char *)toc) + da_size - sizeof(const struct toc_item))) { - SOLIDIGM_LOG_WARNING("Warning: Data Area %d, " - "Table of Contents item %d " - "crossed Data Area size.", da, i); + const char *nlog_name = NULL; + uint32_t header_offset = sizeof(const struct telemetry_object_header); + + if ((char *)&toc->items[i] > + (((char *)toc) + da_size - sizeof(const struct toc_item))) { + SOLIDIGM_LOG_WARNING( + "Warning: Data Area %d, Table of Contents item %d crossed Data Area size.", + da, i); return; } obj_offset = toc->items[i].OffsetBytes; if ((obj_offset + sizeof(const struct telemetry_object_header)) > da_size) { - SOLIDIGM_LOG_WARNING("Warning: Data Area %d, item %d " - "data, crossed Data Area size.", da, i); + SOLIDIGM_LOG_WARNING( + "Warning: Data Area %d, item %d data, crossed Data Area size.", da, i); continue; } @@ -372,53 +406,67 @@ static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl, json_object_add_value_uint(toc_item, "objectId", header->Token); json_object_add_value_uint(toc_item, "mediaBankId", header->CoreId); - has_struct = solidigm_config_get_by_token_version(tl->configuration, - header->Token, - header->versionMajor, - header->versionMinor, - &structure_definition); - - if (has_struct) { - struct json_object *tele_obj_item = json_create_object(); + has_struct = solidigm_config_get_struct_by_token_version(tl->configuration, + header->Token, + header->versionMajor, + header->versionMinor, + &structure_definition); + if (!has_struct) { + if (!nlog_formats) + continue; + nlog_name = solidigm_config_get_nlog_obj_name(tl->configuration, + header->Token); + if (!nlog_name) + continue; + } + 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); - struct json_object *parsed_struct = 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); + struct json_object *parsed_struct = json_create_object(); - json_object_add_value_object(tele_obj_item, "objectData", parsed_struct); - struct json_object *obj_hasTelemObjHdr = NULL; - uint32_t header_offset = sizeof(const struct telemetry_object_header); - uint32_t file_offset; + json_object_add_value_object(tele_obj_item, "objectData", parsed_struct); + struct json_object *obj_hasTelemObjHdr = NULL; + uint64_t object_file_offset; - if (json_object_object_get_ex(structure_definition, - "hasTelemObjHdr", - &obj_hasTelemObjHdr)) { - bool hasHeader = json_object_get_boolean(obj_hasTelemObjHdr); + if (json_object_object_get_ex(structure_definition, + "hasTelemObjHdr", + &obj_hasTelemObjHdr)) { + bool hasHeader = json_object_get_boolean(obj_hasTelemObjHdr); - if (hasHeader) - header_offset = 0; - } - - file_offset = da_offset + obj_offset + header_offset; + if (hasHeader) + header_offset = 0; + } + object_file_offset = ((uint64_t)da_offset) + obj_offset + header_offset; + if (has_struct) { telemetry_log_structure_parse(tl, structure_definition, - BITS_IN_BYTE * file_offset, - parsed_struct, toc_item); + BITS_IN_BYTE * object_file_offset, + parsed_struct, toc_item); + } else if (nlog_formats) { + json_object_object_add(toc_item, "objName", + json_object_new_string(nlog_name)); + telemetry_log_nlog_parse(tl, nlog_formats, object_file_offset, + toc->items[i].ContentSizeBytes - header_offset, + parsed_struct, toc_item); } } } -int solidigm_telemetry_log_data_areas_parse(const struct telemetry_log *tl, +int solidigm_telemetry_log_data_areas_parse(struct telemetry_log *tl, enum nvme_telemetry_da last_da) { 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); - - for (enum nvme_telemetry_da da = NVME_TELEMETRY_DA_1; da <= last_da; da++) - telemetry_log_data_area_toc_parse(tl, da, toc_array, tele_obj_array); + solidigm_telemetry_log_header_parse(tl); + solidigm_telemetry_log_cod_parse(tl); + if (tl->configuration) { + json_object_add_value_array(tl->root, "tableOfContents", toc_array); + json_object_add_value_array(tl->root, "telemetryObjects", tele_obj_array); + for (enum nvme_telemetry_da da = NVME_TELEMETRY_DA_1; da <= last_da; da++) + telemetry_log_data_area_toc_parse(tl, da, toc_array, tele_obj_array); + } return 0; } diff --git a/plugins/solidigm/solidigm-telemetry/data-area.h b/plugins/solidigm/solidigm-telemetry/data-area.h index 095eb64..6b690d8 100644 --- a/plugins/solidigm/solidigm-telemetry/data-area.h +++ b/plugins/solidigm/solidigm-telemetry/data-area.h @@ -4,8 +4,7 @@ * * Author: leonardo.da.cunha@solidigm.com */ -#include "common.h" #include "telemetry-log.h" -int solidigm_telemetry_log_data_areas_parse(const struct telemetry_log *tl, +int solidigm_telemetry_log_data_areas_parse(struct telemetry_log *tl, enum nvme_telemetry_da last_da); diff --git a/plugins/solidigm/solidigm-telemetry/header.c b/plugins/solidigm/solidigm-telemetry/header.c index d085c24..866ebff 100644 --- a/plugins/solidigm/solidigm-telemetry/header.c +++ b/plugins/solidigm/solidigm-telemetry/header.c @@ -9,8 +9,7 @@ #include "header.h" #pragma pack(push, reason_indentifier, 1) -struct reason_indentifier_1_0 -{ +struct reason_indentifier_1_0 { uint16_t versionMajor; uint16_t versionMinor; uint32_t reasonCode; //! 0 denotes no issue. All other values denote a potential issue. @@ -24,8 +23,7 @@ static_assert(sizeof(const struct reason_indentifier_1_0) == MEMBER_SIZE(struct nvme_telemetry_log, rsnident), "Size mismatch for reason_indentifier_1_0"); -struct reason_indentifier_1_1 -{ +struct reason_indentifier_1_1 { uint16_t versionMajor; uint16_t versionMinor; uint32_t reasonCode; //! 0 denotes no issue. All other values denote a potential issue. @@ -42,8 +40,7 @@ static_assert(sizeof(const struct reason_indentifier_1_1) == MEMBER_SIZE(struct nvme_telemetry_log, rsnident), "Size mismatch for reason_indentifier_1_1"); -struct reason_indentifier_1_2 -{ +struct reason_indentifier_1_2 { uint16_t versionMajor; uint16_t versionMinor; uint32_t reasonCode; //! 0 denotes no issue. All other values denote a potential issue. @@ -69,14 +66,21 @@ static void telemetry_log_reason_id_parse1_0_ext(const struct telemetry_log *tl, 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))); - json_object_object_add(reason_id, "BootloaderVersion", json_object_new_string_len(ri->BootloaderVersion, sizeof(ri->BootloaderVersion))); - json_object_object_add(reason_id, "SerialNumber", json_object_new_string_len(ri->SerialNumber, sizeof(ri->SerialNumber))); + json_object_object_add(reason_id, "firmwareVersion", + json_object_new_string_len(ri->FirmwareVersion, + sizeof(ri->FirmwareVersion))); + json_object_object_add(reason_id, "bootloaderVersion", + json_object_new_string_len(ri->BootloaderVersion, + sizeof(ri->BootloaderVersion))); + json_object_object_add(reason_id, "serialNumber", + json_object_new_string_len(ri->SerialNumber, + sizeof(ri->SerialNumber))); reserved = json_create_array(); - json_object_add_value_array(reason_id, "Reserved", reserved); - for ( int i=0; i < sizeof(ri->Reserved); i++) { + json_object_add_value_array(reason_id, "reserved", reserved); + for (int i = 0; i < sizeof(ri->Reserved); i++) { struct json_object *val = json_object_new_int(ri->Reserved[i]); + json_object_array_add(reserved, val); } } @@ -88,17 +92,27 @@ static void telemetry_log_reason_id_parse1_1_ext(const struct telemetry_log *tl, 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))); - json_object_object_add(reason_id, "BootloaderVersion", json_object_new_string_len(ri->BootloaderVersion, sizeof(ri->BootloaderVersion))); - json_object_object_add(reason_id, "SerialNumber", json_object_new_string_len(ri->SerialNumber, sizeof(ri->SerialNumber))); - json_object_add_value_uint64(reason_id, "OemDataMapOffset", le64_to_cpu(ri->OemDataMapOffset)); - json_object_add_value_uint(reason_id, "TelemetryMajorVersion", le16_to_cpu(ri->TelemetryMajorVersion)); - json_object_add_value_uint(reason_id, "TelemetryMinorVersion", le16_to_cpu(ri->TelemetryMinorVersion)); + json_object_object_add(reason_id, "firmwareVersion", + json_object_new_string_len(ri->FirmwareVersion, + sizeof(ri->FirmwareVersion))); + json_object_object_add(reason_id, "bootloaderVersion", + json_object_new_string_len(ri->BootloaderVersion, + sizeof(ri->BootloaderVersion))); + json_object_object_add(reason_id, "serialNumber", + json_object_new_string_len(ri->SerialNumber, + sizeof(ri->SerialNumber))); + json_object_add_value_uint64(reason_id, "oemDataMapOffset", + le64_to_cpu(ri->OemDataMapOffset)); + json_object_add_value_uint(reason_id, "telemetryMajorVersion", + le16_to_cpu(ri->TelemetryMajorVersion)); + json_object_add_value_uint(reason_id, "telemetryMinorVersion", + le16_to_cpu(ri->TelemetryMinorVersion)); reserved = json_create_array(); - json_object_add_value_array(reason_id, "Reserved", reserved); + json_object_add_value_array(reason_id, "reserved", reserved); for (int i = 0; i < sizeof(ri->Reserved); i++) { struct json_object *val = json_object_new_int(ri->Reserved[i]); + json_object_array_add(reserved, val); } } @@ -112,23 +126,30 @@ static void telemetry_log_reason_id_parse1_2_ext(const struct telemetry_log *tl, ri = (struct reason_indentifier_1_2 *) tl->log->rsnident; - json_object_object_add(reason_id, "SerialNumber", json_object_new_string_len(ri->SerialNumber, sizeof(ri->SerialNumber))); - json_object_add_value_uint64(reason_id, "OemDataMapOffset", le64_to_cpu(ri->OemDataMapOffset)); - json_object_add_value_uint(reason_id, "TelemetryMajorVersion", le16_to_cpu(ri->TelemetryMajorVersion)); - json_object_add_value_uint(reason_id, "TelemetryMinorVersion", le16_to_cpu(ri->TelemetryMinorVersion)); - json_object_add_value_uint(reason_id, "ProductFamilyId", ri->ProductFamilyId); + json_object_object_add(reason_id, "serialNumber", + json_object_new_string_len(ri->SerialNumber, + sizeof(ri->SerialNumber))); + json_object_add_value_uint64(reason_id, "oemDataMapOffset", + le64_to_cpu(ri->OemDataMapOffset)); + json_object_add_value_uint(reason_id, "telemetryMajorVersion", + le16_to_cpu(ri->TelemetryMajorVersion)); + json_object_add_value_uint(reason_id, "telemetryMinorVersion", + le16_to_cpu(ri->TelemetryMinorVersion)); + json_object_add_value_uint(reason_id, "productFamilyId", ri->ProductFamilyId); reserved = json_create_array(); - json_object_add_value_array(reason_id, "Reserved2", reserved); + json_object_add_value_array(reason_id, "reserved2", reserved); for (int i = 0; i < sizeof(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); + json_object_add_value_array(reason_id, "dualPortReserved", dp_reserved); for (int i = 0; i < sizeof(ri->DualPortReserved); i++) { struct json_object *val = json_object_new_int(ri->DualPortReserved[i]); + json_object_array_add(dp_reserved, val); } } @@ -137,23 +158,26 @@ static void solidigm_telemetry_log_reason_id_parse(const struct telemetry_log *t { const struct reason_indentifier_1_0 *ri1_0 = (struct reason_indentifier_1_0 *) tl->log->rsnident; - __u16 version_major = le16_to_cpu(ri1_0->versionMajor); - __u16 version_minor = le16_to_cpu(ri1_0->versionMinor); + uint16_t version_major = le16_to_cpu(ri1_0->versionMajor); + uint16_t version_minor = le16_to_cpu(ri1_0->versionMinor); json_object_add_value_uint(reason_id, "versionMajor", version_major); json_object_add_value_uint(reason_id, "versionMinor", version_minor); json_object_add_value_uint(reason_id, "reasonCode", le32_to_cpu(ri1_0->reasonCode)); - json_object_add_value_object(reason_id, "DriveStatus", json_object_new_string_len(ri1_0->DriveStatus, sizeof(ri1_0->DriveStatus))); + json_object_add_value_object(reason_id, "driveStatus", + json_object_new_string_len(ri1_0->DriveStatus, + sizeof(ri1_0->DriveStatus))); if (version_major == 1) { switch (version_minor) { - case 0: - telemetry_log_reason_id_parse1_0_ext(tl, reason_id); - break; - case 1: - telemetry_log_reason_id_parse1_1_ext(tl, reason_id); - break; - default: - telemetry_log_reason_id_parse1_2_ext(tl, reason_id); + case 0: + telemetry_log_reason_id_parse1_0_ext(tl, reason_id); + break; + case 1: + telemetry_log_reason_id_parse1_1_ext(tl, reason_id); + break; + default: + telemetry_log_reason_id_parse1_2_ext(tl, reason_id); + break; } } } diff --git a/plugins/solidigm/solidigm-telemetry/meson.build b/plugins/solidigm/solidigm-telemetry/meson.build index 53ab452..96273b7 100644 --- a/plugins/solidigm/solidigm-telemetry/meson.build +++ b/plugins/solidigm/solidigm-telemetry/meson.build @@ -3,4 +3,5 @@ sources += [ 'plugins/solidigm/solidigm-telemetry/header.c', 'plugins/solidigm/solidigm-telemetry/config.c', 'plugins/solidigm/solidigm-telemetry/data-area.c', + 'plugins/solidigm/solidigm-telemetry/nlog.c', ] diff --git a/plugins/solidigm/solidigm-telemetry/nlog.c b/plugins/solidigm/solidigm-telemetry/nlog.c new file mode 100644 index 0000000..43b8918 --- /dev/null +++ b/plugins/solidigm/solidigm-telemetry/nlog.c @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (c) 2023 Solidigm. + * + * Author: leonardo.da.cunha@solidigm.com + */ + +#include "nlog.h" +#include "config.h" +#include <string.h> +#include <math.h> +#include <stdio.h> + +#define LOG_ENTRY_HEADER_SIZE 1 +#define LOG_ENTRY_TIMESTAMP_SIZE 2 +#define LOG_ENTRY_NUM_ARGS_MAX 8 +#define LOG_ENTRY_MAX_SIZE (LOG_ENTRY_HEADER_SIZE + LOG_ENTRY_TIMESTAMP_SIZE + \ + LOG_ENTRY_NUM_ARGS_MAX) +#define NUM_ARGS_MASK ((1 << ((int)log2(LOG_ENTRY_NUM_ARGS_MAX)+1)) - 1) +#define MAX_HEADER_MISMATCH_TRACK 10 + +static int formats_find(struct json_object *formats, uint32_t val, struct json_object **format) +{ + char hex_header[STR_HEX32_SIZE]; + + snprintf(hex_header, STR_HEX32_SIZE, "0x%08X", val); + return json_object_object_get_ex(formats, hex_header, format); +} + +static uint32_t nlog_get_pos(const uint32_t *nlog, const uint32_t nlog_size, int pos) +{ + return nlog[pos % nlog_size]; +} + +static uint32_t nlog_get_events(const uint32_t *nlog, const uint32_t nlog_size, int start_offset, + struct json_object *formats, struct json_object *events, uint32_t *tail_mismatches) +{ + uint32_t event_count = 0; + int last_bad_header_pos = nlog_size + 1; // invalid nlog offset + uint32_t tail_count = 0; + + for (int i = nlog_size - start_offset - 1; i >= -start_offset; i--) { + struct json_object *format; + uint32_t header = nlog_get_pos(nlog, nlog_size, i); + uint32_t num_data; + + if (header == 0 || !formats_find(formats, header, &format)) { + if (event_count > 0) { + //check if fould circular buffer tail + if (i != (last_bad_header_pos - 1)) { + if (tail_mismatches && + (tail_count < MAX_HEADER_MISMATCH_TRACK)) + tail_mismatches[tail_count] = header; + tail_count++; + } + last_bad_header_pos = i; + } + continue; + } + num_data = header & NUM_ARGS_MASK; + if (events) { + struct json_object *event = json_object_new_array(); + struct json_object *param = json_object_new_array(); + uint32_t val = nlog_get_pos(nlog, nlog_size, i - 1); + + json_object_array_add(events, event); + json_object_array_add(event, json_object_new_int64(val)); + val = nlog_get_pos(nlog, nlog_size, i - 2); + json_object_array_add(event, json_object_new_int64(val)); + json_object_array_add(event, json_object_new_int64(header)); + json_object_array_add(event, param); + for (uint32_t j = 0; j < num_data; j++) { + val = nlog_get_pos(nlog, nlog_size, i - 3 - j); + json_object_array_add(param, json_object_new_int64(val)); + } + json_object_get(format); + json_object_array_add(event, format); + } + i -= 2 + num_data; + event_count++; + } + return tail_count; +} + +int solidigm_nlog_parse(const char *buffer, uint64_t buff_size, struct json_object *formats, + struct json_object *metadata, struct json_object *output) +{ + uint32_t smaller_tail_count = UINT32_MAX; + int best_offset = 0; + uint32_t offset_tail_mismatches[LOG_ENTRY_MAX_SIZE][MAX_HEADER_MISMATCH_TRACK]; + struct json_object *events = json_object_new_array(); + const uint32_t *nlog = (uint32_t *)buffer; + const uint32_t nlog_size = buff_size / sizeof(uint32_t); + + for (int i = 0; i < LOG_ENTRY_MAX_SIZE; i++) { + uint32_t tail_count = nlog_get_events(nlog, nlog_size, i, formats, NULL, + offset_tail_mismatches[i]); + if (tail_count < smaller_tail_count) { + best_offset = i; + smaller_tail_count = tail_count; + } + if (tail_count == 0) + break; + } + if (smaller_tail_count > 1) { + const char *name = ""; + int media_bank = -1; + char str_mismatches[(STR_HEX32_SIZE + 1) * MAX_HEADER_MISMATCH_TRACK]; + int pos = 0; + int show_mismatch_num = smaller_tail_count < MAX_HEADER_MISMATCH_TRACK ? + smaller_tail_count : MAX_HEADER_MISMATCH_TRACK; + struct json_object *jobj; + + if (json_object_object_get_ex(metadata, "objName", &jobj)) + name = json_object_get_string(jobj); + if (json_object_object_get_ex(metadata, "mediaBankId", &jobj)) + media_bank = json_object_get_int(jobj); + + for (int i = 0; i < show_mismatch_num; i++) + pos += snprintf(&str_mismatches[pos], STR_HEX32_SIZE + 1, "0x%08X ", + offset_tail_mismatches[best_offset][i]); + + SOLIDIGM_LOG_WARNING("%s:%d with %d header mismatches ( %s). Configuration file may be missing format headers.", + name, media_bank, smaller_tail_count, str_mismatches); + } + nlog_get_events(nlog, nlog_size, best_offset, formats, events, NULL); + + json_object_object_add(output, "events", events); + return 0; +} diff --git a/plugins/solidigm/solidigm-telemetry/nlog.h b/plugins/solidigm/solidigm-telemetry/nlog.h new file mode 100644 index 0000000..f33aa45 --- /dev/null +++ b/plugins/solidigm/solidigm-telemetry/nlog.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (c) 2023 Solidigm. + * + * Author: leonardo.da.cunha@solidigm.com + */ +#include "telemetry-log.h" + +int solidigm_nlog_parse(const char *buffer, uint64_t bufer_size, + struct json_object *formats, struct json_object *metadata, + struct json_object *output); diff --git a/plugins/toshiba/toshiba-nvme.c b/plugins/toshiba/toshiba-nvme.c index 5540fea..4927012 100644 --- a/plugins/toshiba/toshiba-nvme.c +++ b/plugins/toshiba/toshiba-nvme.c @@ -21,37 +21,37 @@ static const __u32 OP_SCT_STATUS = 0xE0; static const __u32 OP_SCT_COMMAND_TRANSFER = 0xE0; static const __u32 OP_SCT_DATA_TRANSFER = 0xE1; -static const __u32 DW10_SCT_STATUS_COMMAND = 0x0; +static const __u32 DW10_SCT_STATUS_COMMAND; static const __u32 DW10_SCT_COMMAND_TRANSFER = 0x1; -static const __u32 DW11_SCT_STATUS_COMMAND = 0x0; -static const __u32 DW11_SCT_COMMAND_TRANSFER = 0x0; +static const __u32 DW11_SCT_STATUS_COMMAND; +static const __u32 DW11_SCT_COMMAND_TRANSFER; static const __u16 INTERNAL_LOG_ACTION_CODE = 0xFFFB; static const __u16 CURRENT_LOG_FUNCTION_CODE = 0x0001; static const __u16 SAVED_LOG_FUNCTION_CODE = 0x0002; /* A bitmask field for supported devices */ -typedef enum { - MASK_0 = 1 << 0, - MASK_1 = 1 << 1, +enum { + MASK_0 = 1 << 0, + MASK_1 = 1 << 1, /* * Future devices can use the remaining 31 bits from this field * and should use 1 << 2, 1 << 3, etc. */ MASK_IGNORE = 0 -} DeviceMask; +}; /* Internal device codes */ -typedef enum { +enum { CODE_0 = 0x0D, CODE_1 = 0x10 -} DeviceCode; +}; -static int nvme_sct_op(int fd, __u32 opcode, __u32 cdw10, __u32 cdw11, void* data, __u32 data_len ) +static int nvme_sct_op(int fd, __u32 opcode, __u32 cdw10, __u32 cdw11, void *data, __u32 data_len) { - void *metadata = NULL; + void *metadata = NULL; const __u32 cdw2 = 0; const __u32 cdw3 = 0; const __u32 cdw12 = 0; @@ -63,26 +63,23 @@ static int nvme_sct_op(int fd, __u32 opcode, __u32 cdw10, __u32 cdw11, void* da const __u32 namespace_id = 0x0; const __u32 flags = 0; const __u32 rsvd = 0; - int err = 0; - __u32 result; - err = nvme_admin_passthru(fd, opcode, flags, rsvd, - namespace_id, cdw2, cdw3, cdw10, - cdw11, cdw12, cdw13, cdw14, cdw15, - data_len, data, metadata_len, metadata, - timeout, &result); - return err; + + return nvme_admin_passthru(fd, opcode, flags, rsvd, namespace_id, cdw2, cdw3, cdw10, cdw11, + cdw12, cdw13, cdw14, cdw15, data_len, data, metadata_len, + metadata, timeout, &result); } static int nvme_get_sct_status(int fd, __u32 device_mask) { int err; - void* data = NULL; + void *data = NULL; size_t data_len = 512; unsigned char *status; + __u32 supported = 0; if (posix_memalign(&data, getpagesize(), data_len)) - return ENOMEM; + return -ENOMEM; memset(data, 0, data_len); err = nvme_sct_op(fd, OP_SCT_STATUS, DW10_SCT_STATUS_COMMAND, DW11_SCT_STATUS_COMMAND, data, data_len); @@ -102,22 +99,19 @@ static int nvme_get_sct_status(int fd, __u32 device_mask) /* Check if device is supported */ if (device_mask != MASK_IGNORE) { - __u32 supported = 0; switch (status[1]) { case CODE_0: supported = (device_mask & MASK_0); break; - case CODE_1: supported = (device_mask & MASK_1); break; - default: break; }; - if (0 == supported) { - fprintf(stderr, "%s: command unsupported on this device: (0x%x)\n",__func__, status[1]); + if (!supported) { + fprintf(stderr, "%s: command unsupported on this device: (0x%x)\n", __func__, status[1]); err = -1; errno = EINVAL; goto end; @@ -142,7 +136,7 @@ static int nvme_sct_command_transfer_log(int fd, bool current) function_code = SAVED_LOG_FUNCTION_CODE; if (posix_memalign(&data, getpagesize(), data_len)) - return ENOMEM; + return -ENOMEM; memset(data, 0, data_len); memcpy(data, &action_code, sizeof(action_code)); @@ -153,7 +147,7 @@ static int nvme_sct_command_transfer_log(int fd, bool current) return err; } -static int nvme_sct_data_transfer(int fd, void* data, size_t data_len, size_t offset) +static int nvme_sct_data_transfer(int fd, void *data, size_t data_len, size_t offset) { __u32 dw10, dw11, lba_count = (data_len) / 512; @@ -170,7 +164,7 @@ static int nvme_sct_data_transfer(int fd, void* data, size_t data_len, size_t of return nvme_sct_op(fd, OP_SCT_DATA_TRANSFER, dw10, dw11, data, data_len); } -static int d_raw_to_fd(const unsigned char *buf, unsigned len, int fd) +static int d_raw_to_fd(const unsigned char *buf, unsigned int len, int fd) { int written = 0; int remaining = len; @@ -207,26 +201,26 @@ static void progress_runner(float progress) fprintf(stdout, " "); } - fprintf(stdout, "] %d %%\r",(int)(progress * 100.0)); + fprintf(stdout, "] %d %%\r", (int)(progress * 100.0)); fflush(stdout); } -static int nvme_get_internal_log(int fd, const char* const filename, bool current) +static int nvme_get_internal_log(int fd, const char *const filename, bool current) { int err; int o_fd = -1; - void* page_data = NULL; + void *page_data = NULL; const size_t page_sector_len = 32; const size_t page_data_len = page_sector_len * 512; /* 32 sectors per page */ - uint32_t* area1_last_page; - uint32_t* area2_last_page; - uint32_t* area3_last_page; + uint32_t *area1_last_page; + uint32_t *area2_last_page; + uint32_t *area3_last_page; uint32_t log_sectors = 0; size_t pages; - + __u32 pages_chunk; /* * By trial and error it seems that the largest transfer chunk size - * is 128 * 32 = 4k sectors = 2MB + * is 128 * 32 = 4k sectors = 2MB */ const __u32 max_pages = 128; size_t i; @@ -248,7 +242,7 @@ static int nvme_get_internal_log(int fd, const char* const filename, bool curren /* Read the header to get the last log page - offsets 8->11, 12->15, 16->19 */ err = nvme_sct_data_transfer(fd, page_data, page_data_len, 0); if (err) { - fprintf(stderr, "%s: SCT data transfer failed, page 0\n",__func__); + fprintf(stderr, "%s: SCT data transfer failed, page 0\n", __func__); goto end; } @@ -274,7 +268,7 @@ static int nvme_get_internal_log(int fd, const char* const filename, bool curren o_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (o_fd < 0) { fprintf(stderr, "%s: couldn't output file %s\n", __func__, filename); - err = EINVAL; + err = -EINVAL; goto end; } err = d_raw_to_fd(page_data, page_data_len, o_fd); @@ -286,7 +280,7 @@ static int nvme_get_internal_log(int fd, const char* const filename, bool curren /* Now read the rest */ for (i = 1; i < pages;) { - __u32 pages_chunk = max_pages; + pages_chunk = max_pages; if (pages_chunk + i >= pages) pages_chunk = pages - i; @@ -318,23 +312,21 @@ static int nvme_get_internal_log(int fd, const char* const filename, bool curren } progress = 1.0f; progress_runner(progress); - fprintf(stdout,"\n"); + fprintf(stdout, "\n"); err = nvme_get_sct_status(fd, MASK_IGNORE); if (err) { fprintf(stderr, "%s: bad SCT status\n", __func__); goto end; } end: - if (o_fd >= 0) { + if (o_fd >= 0) close(o_fd); - } - if (page_data) { + if (page_data) free(page_data); - } return err; } -static int nvme_get_internal_log_file(int fd, const char* const filename, bool current) +static int nvme_get_internal_log_file(int fd, const char *const filename, bool current) { int err; @@ -366,20 +358,20 @@ static void default_show_vendor_log_c0(struct nvme_dev *dev, __u32 nsid, { printf("Vendor Log Page Directory 0xC0 for NVME device:%s namespace-id:%x\n", dev->name, nsid); - printf("Error Log : %u \n", smart->items[ERROR_LOG_C0]); - printf("SMART Health Log : %u \n", smart->items[SMART_HEALTH_LOG_C0]); - printf("Firmware Slot Info : %u \n", smart->items[FIRMWARE_SLOT_INFO_C0]); - printf("Command Effects : %u \n", smart->items[COMMAND_EFFECTS_C0]); - printf("Device Self Test : %u \n", smart->items[DEVICE_SELF_TEST_C0]); - printf("Log Page Directory : %u \n", smart->items[LOG_PAGE_DIRECTORY_C0]); - printf("SMART Attributes : %u \n", smart->items[SMART_ATTRIBUTES_C0]); + printf("Error Log : %u\n", smart->items[ERROR_LOG_C0]); + printf("SMART Health Log : %u\n", smart->items[SMART_HEALTH_LOG_C0]); + printf("Firmware Slot Info : %u\n", smart->items[FIRMWARE_SLOT_INFO_C0]); + printf("Command Effects : %u\n", smart->items[COMMAND_EFFECTS_C0]); + printf("Device Self Test : %u\n", smart->items[DEVICE_SELF_TEST_C0]); + printf("Log Page Directory : %u\n", smart->items[LOG_PAGE_DIRECTORY_C0]); + printf("SMART Attributes : %u\n", smart->items[SMART_ATTRIBUTES_C0]); } static int nvme_get_vendor_log(struct nvme_dev *dev, __u32 namespace_id, - int log_page, const char* const filename) + int log_page, const char *const filename) { int err; - void* log = NULL; + void *log = NULL; size_t log_len = 512; if (posix_memalign(&log, getpagesize(), log_len)) { @@ -389,9 +381,8 @@ static int nvme_get_vendor_log(struct nvme_dev *dev, __u32 namespace_id, /* Check device supported */ err = nvme_get_sct_status(dev_fd(dev), MASK_0 | MASK_1); - if (err) { + if (err) goto end; - } err = nvme_get_nsid_log(dev_fd(dev), false, log_page, namespace_id, log_len, log); if (err) { @@ -405,7 +396,7 @@ static int nvme_get_vendor_log(struct nvme_dev *dev, __u32 namespace_id, if (o_fd < 0) { fprintf(stderr, "%s: couldn't output file %s\n", __func__, filename); - err = EINVAL; + err = -EINVAL; goto end; } err = d_raw_to_fd(log, log_len, o_fd); @@ -422,12 +413,11 @@ static int nvme_get_vendor_log(struct nvme_dev *dev, __u32 namespace_id, if (log_page == 0xc0) default_show_vendor_log_c0(dev, namespace_id, log); else - d(log, log_len,16,1); + d(log, log_len, 16, 1); } end: - if (log) { + if (log) free(log); - } return err; } @@ -442,7 +432,7 @@ static int vendor_log(int argc, char **argv, struct command *cmd, struct plugin struct config { __u32 namespace_id; - const char* output_file; + const char *output_file; int log; }; @@ -461,13 +451,13 @@ static int vendor_log(int argc, char **argv, struct command *cmd, struct plugin err = parse_and_open(&dev, argc, argv, desc, opts); if (err) { - fprintf(stderr,"%s: failed to parse arguments\n", __func__); - return EINVAL; + fprintf(stderr, "%s: failed to parse arguments\n", __func__); + return -EINVAL; } if ((cfg.log != 0xC0) && (cfg.log != 0xCA)) { fprintf(stderr, "%s: invalid log page 0x%x - should be 0xC0 or 0xCA\n", __func__, cfg.log); - err = EINVAL; + err = -EINVAL; goto end; } @@ -491,7 +481,7 @@ static int internal_log(int argc, char **argv, struct command *cmd, struct plugi int err; struct config { - const char* output_file; + const char *output_file; bool prev_log; }; @@ -501,15 +491,15 @@ static int internal_log(int argc, char **argv, struct command *cmd, struct plugi }; OPT_ARGS(opts) = { - OPT_FILE("output-file", 'o', &cfg.output_file, output_file), + OPT_FILE("output-file", 'o', &cfg.output_file, output_file), OPT_FLAG("prev-log", 'p', &cfg.prev_log, prev_log), OPT_END() }; err = parse_and_open(&dev, argc, argv, desc, opts); if (err) { - fprintf(stderr,"%s: failed to parse arguments\n", __func__); - return EINVAL; + fprintf(stderr, "%s: failed to parse arguments\n", __func__); + return -EINVAL; } if (cfg.prev_log) @@ -520,7 +510,7 @@ static int internal_log(int argc, char **argv, struct command *cmd, struct plugi err = nvme_get_internal_log_file(dev_fd(dev), cfg.output_file, !cfg.prev_log); if (err < 0) - fprintf(stderr, "%s: couldn't get fw log \n", __func__); + fprintf(stderr, "%s: couldn't get fw log\n", __func__); if (err > 0) nvme_show_status(err); @@ -547,8 +537,8 @@ static int clear_correctable_errors(int argc, char **argv, struct command *cmd, err = parse_and_open(&dev, argc, argv, desc, opts); if (err) { - fprintf(stderr,"%s: failed to parse arguments\n", __func__); - return EINVAL; + fprintf(stderr, "%s: failed to parse arguments\n", __func__); + return -EINVAL; } /* Check device supported */ @@ -573,7 +563,7 @@ static int clear_correctable_errors(int argc, char **argv, struct command *cmd, }; err = nvme_set_features(&args); if (err) - fprintf(stderr, "%s: couldn't clear PCIe correctable errors \n", + fprintf(stderr, "%s: couldn't clear PCIe correctable errors\n", __func__); end: if (err > 0) diff --git a/plugins/transcend/transcend-nvme.c b/plugins/transcend/transcend-nvme.c index 024351f..547fbf4 100644 --- a/plugins/transcend/transcend-nvme.c +++ b/plugins/transcend/transcend-nvme.c @@ -21,7 +21,7 @@ static int getHealthValue(int argc, char **argv, struct command *cmd, struct plu { struct nvme_smart_log smart_log; char *desc = "Get nvme health percentage."; - int percent_used = 0, healthvalue=0; + int percent_used = 0, healthvalue = 0; struct nvme_dev *dev; int result; @@ -31,59 +31,55 @@ static int getHealthValue(int argc, char **argv, struct command *cmd, struct plu result = parse_and_open(&dev, argc, argv, desc, opts); if (result) { - printf("\nDevice not found \n");; + printf("\nDevice not found\n"); return -1; } result = nvme_get_log_smart(dev_fd(dev), 0xffffffff, false, &smart_log); if (!result) { printf("Transcend NVME heath value: "); - percent_used =smart_log.percent_used; - - if(percent_used>100 || percent_used<0) - { + percent_used = smart_log.percent_used; + + if (percent_used > 100 || percent_used < 0) { printf("0%%\n"); - } - else - { + } else { healthvalue = 100 - percent_used; - printf("%d%%\n",healthvalue); + printf("%d%%\n", healthvalue); } - } dev_close(dev); return result; } - static int getBadblock(int argc, char **argv, struct command *cmd, struct plugin *plugin) { char *desc = "Get nvme bad block number."; struct nvme_dev *dev; int result; - + OPT_ARGS(opts) = { - OPT_END() }; result = parse_and_open(&dev, argc, argv, desc, opts); if (result) { - printf("\nDevice not found \n");; + printf("\nDevice not found\n"); return -1; } - unsigned char data[1]={0}; + unsigned char data[1] = {0}; struct nvme_passthru_cmd nvmecmd; - memset(&nvmecmd,0,sizeof(nvmecmd)); - nvmecmd.opcode=OP_BAD_BLOCK; - nvmecmd.cdw10=DW10_BAD_BLOCK; - nvmecmd.cdw12=DW12_BAD_BLOCK; + + memset(&nvmecmd, 0, sizeof(nvmecmd)); + nvmecmd.opcode = OP_BAD_BLOCK; + nvmecmd.cdw10 = DW10_BAD_BLOCK; + nvmecmd.cdw12 = DW12_BAD_BLOCK; nvmecmd.addr = (__u64)(uintptr_t)data; nvmecmd.data_len = 0x1; result = nvme_submit_admin_passthru(dev_fd(dev), &nvmecmd, NULL); - if(!result) { + if (!result) { int badblock = data[0]; - printf("Transcend NVME badblock count: %d\n",badblock); + + printf("Transcend NVME badblock count: %d\n", badblock); } dev_close(dev); return result; diff --git a/plugins/virtium/virtium-nvme.c b/plugins/virtium/virtium-nvme.c index c8df126..0ba4b15 100644 --- a/plugins/virtium/virtium-nvme.c +++ b/plugins/virtium/virtium-nvme.c @@ -19,7 +19,7 @@ #define CREATE_CMD #include "virtium-nvme.h" -#define MIN2(a, b) ( ((a) < (b))? (a) : (b)) +#define MIN2(a, b) (((a) < (b)) ? (a) : (b)) #define HOUR_IN_SECONDS 3600 @@ -30,26 +30,26 @@ static char vt_default_log_file_name[256]; struct vtview_log_header { - char path[256]; - char test_name[256]; - long int time_stamp; - struct nvme_id_ctrl raw_ctrl; - struct nvme_firmware_slot raw_fw; + char path[256]; + char test_name[256]; + long time_stamp; + struct nvme_id_ctrl raw_ctrl; + struct nvme_firmware_slot raw_fw; }; struct vtview_smart_log_entry { - char path[256]; - long int time_stamp; + char path[256]; + long time_stamp; struct nvme_id_ns raw_ns; struct nvme_id_ctrl raw_ctrl; struct nvme_smart_log raw_smart; }; struct vtview_save_log_settings { - double run_time_hrs; - double log_record_frequency_hrs; - const char* output_file; - const char* test_name; + double run_time_hrs; + double log_record_frequency_hrs; + const char *output_file; + const char *test_name; }; static void vt_initialize_header_buffer(struct vtview_log_header *pbuff) @@ -72,7 +72,7 @@ static void vt_convert_data_buffer_to_hex_string(const unsigned char *bufPtr, memset(output, 0, (size * 2) + 1); for (i = 0; i < size; i++) { - if(isReverted) + if (isReverted) pos = size - 1 - i; else pos = i; @@ -86,7 +86,7 @@ static void vt_convert_data_buffer_to_hex_string(const unsigned char *bufPtr, * Log file name will be generated automatically if user leave log file option blank. * Log file name will be generated as vtView-Smart-log-date-time.txt */ -static void vt_generate_vtview_log_file_name(char* fname) +static void vt_generate_vtview_log_file_name(char *fname) { time_t current; struct tm tstamp; @@ -112,17 +112,19 @@ static void vt_convert_smart_data_to_human_readable_format(struct vtview_smart_l char *curlocale; char *templocale; __u8 lba_index; + nvme_id_ns_flbas_to_lbaf_inuse(smart->raw_ns.flbas, &lba_index); curlocale = setlocale(LC_ALL, NULL); templocale = strdup(curlocale); - if (NULL == templocale) + if (!templocale) printf("Cannot malloc buffer\n"); setlocale(LC_ALL, "C"); - unsigned long long int lba = 1ULL << smart->raw_ns.lbaf[lba_index].ds; + unsigned long long lba = 1ULL << smart->raw_ns.lbaf[lba_index].ds; + capacity = le64_to_cpu(smart->raw_ns.nsze) * lba; snprintf(tempbuff, sizeof(tempbuff), "log;%s;%lu;%s;%s;%-.*s;", smart->raw_ctrl.sn, smart->time_stamp, smart->path, @@ -167,7 +169,8 @@ static void vt_convert_smart_data_to_human_readable_format(struct vtview_smart_l for (i = 0; i < 8; i++) { __s32 temp = le16_to_cpu(smart->raw_smart.temp_sensor[i]); - if (0 == temp) { + + if (!temp) { snprintf(tempbuff, sizeof(tempbuff), "Temperature_Sensor_%d;NC;", i); strcat(text, tempbuff); continue; @@ -217,7 +220,7 @@ static int vt_append_text_file(const char *text, const char *filename) FILE *f; f = fopen(filename, "a"); - if(NULL == f) { + if (!f) { printf("Cannot open %s\n", filename); return -1; } @@ -247,11 +250,11 @@ static void vt_process_string(char *str, const size_t size) { size_t i; - if (size == 0) + if (!size) return; i = size - 1; - while ((0 != i) && (' ' == str[i])) { + while (i && (' ' == str[i])) { str[i] = 0; i--; } @@ -262,11 +265,11 @@ static int vt_add_entry_to_log(const int fd, const char *path, const struct vtvi struct vtview_smart_log_entry smart; const char *filename; int ret = 0; - unsigned nsid = 0; + unsigned int nsid = 0; memset(smart.path, 0, sizeof(smart.path)); strncpy(smart.path, path, sizeof(smart.path) - 1); - if(NULL == cfg->output_file) + if (!cfg->output_file) filename = vt_default_log_file_name; else filename = cfg->output_file; @@ -301,7 +304,7 @@ static int vt_add_entry_to_log(const int fd, const char *path, const struct vtvi vt_process_string(smart.raw_ctrl.mn, sizeof(smart.raw_ctrl.mn)); ret = vt_append_log(&smart, filename); - return (ret); + return ret; } static int vt_update_vtview_log_header(const int fd, const char *path, const struct vtview_save_log_settings *cfg) @@ -318,9 +321,9 @@ static int vt_update_vtview_log_header(const int fd, const char *path, const str } strcpy(header.path, path); - if (NULL == cfg->test_name) + if (!cfg->test_name) { strcpy(header.test_name, DEFAULT_TEST_NAME); - else { + } else { if (strlen(cfg->test_name) > sizeof(header.test_name)) { printf("test name too long\n"); errno = EINVAL; @@ -329,7 +332,7 @@ static int vt_update_vtview_log_header(const int fd, const char *path, const str strcpy(header.test_name, cfg->test_name); } - if(NULL == cfg->output_file) + if (!cfg->output_file) filename = vt_default_log_file_name; else filename = cfg->output_file; @@ -353,7 +356,7 @@ static int vt_update_vtview_log_header(const int fd, const char *path, const str vt_process_string(header.raw_ctrl.mn, sizeof(header.raw_ctrl.mn)); ret = vt_append_header(&header, filename); - return (ret); + return ret; } static void vt_build_identify_lv2(unsigned int data, unsigned int start, @@ -371,13 +374,13 @@ static void vt_build_identify_lv2(unsigned int data, unsigned int start, printf(" \"bit %u\":\"%ub %s\"\n", i, temp, table[pos]); printf(" %s", table[pos + 1]); - if((end - 1) != i || !isEnd) + if ((end - 1) != i || !isEnd) printf(",\n"); else printf("\n"); } - if(isEnd) + if (isEnd) printf(" },\n"); } @@ -418,7 +421,7 @@ static void vt_build_power_state_descriptor(const struct nvme_id_ctrl *ctrl) unsigned int temp; printf("%6d", i); - buf = (unsigned char*) (&ctrl->psd[i]); + buf = (unsigned char *) (&ctrl->psd[i]); vt_convert_data_buffer_to_hex_string(&buf[0], 4, true, s); printf("%9sh", s); @@ -469,36 +472,35 @@ static void vt_build_power_state_descriptor(const struct nvme_id_ctrl *ctrl) } -static void vt_dump_hex_data(const unsigned char *pbuff, size_t pbuffsize) { - +static void vt_dump_hex_data(const unsigned char *pbuff, size_t pbuffsize) +{ char textbuf[33]; - unsigned long int i, j; + unsigned long i, j; textbuf[32] = '\0'; printf("[%08X] ", 0); for (i = 0; i < pbuffsize; i++) { printf("%02X ", pbuff[i]); - if (pbuff[i] >= ' ' && pbuff[i] <= '~') + if (pbuff[i] >= ' ' && pbuff[i] <= '~') textbuf[i % 32] = pbuff[i]; - else + else textbuf[i % 32] = '.'; - if ((((i + 1) % 8) == 0) || ((i + 1) == pbuffsize)) { + if (!(((i + 1) % 8)) || ((i + 1) == pbuffsize)) { printf(" "); - if ((i + 1) % 32 == 0) { + if (!((i + 1) % 32)) { printf(" %s\n", textbuf); - if((i + 1) != pbuffsize) - printf("[%08lX] ", (i + 1)); - } - else if (i + 1 == pbuffsize) { + if ((i + 1) != pbuffsize) + printf("[%08lX] ", (i + 1)); + } else if (i + 1 == pbuffsize) { textbuf[(i + 1) % 32] = '\0'; - if(((i + 1) % 8) == 0) + if (!((i + 1) % 8)) printf(" "); for (j = ((i + 1) % 32); j < 32; j++) { printf(" "); - if(((j + 1) % 8) == 0) + if (!((j + 1) % 8)) printf(" "); } @@ -515,174 +517,174 @@ static void vt_parse_detail_identify(const struct nvme_id_ctrl *ctrl) char s[1024] = ""; const char *CMICtable[6] = {"0 = the NVM subsystem contains only a single NVM subsystem port", - "1 = the NVM subsystem may contain more than one subsystem ports", - "0 = the NVM subsystem contains only a single controller", - "1 = the NVM subsystem may contain two or more controllers (see section 1.4.1)", - "0 = the controller is associated with a PCI Function or a Fabrics connection", - "1 = the controller is associated with an SR-IOV Virtual Function"}; + "1 = the NVM subsystem may contain more than one subsystem ports", + "0 = the NVM subsystem contains only a single controller", + "1 = the NVM subsystem may contain two or more controllers (see section 1.4.1)", + "0 = the controller is associated with a PCI Function or a Fabrics connection", + "1 = the controller is associated with an SR-IOV Virtual Function"}; const char *OAEStable[20] = {"Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "0 = does not support sending the Namespace Attribute Notices event nor the associated Changed Namespace List log page", - "1 = supports sending the Namespace Attribute Notices & the associated Changed Namespace List log page", - "0 = does not support sending Firmware Activation Notices event", - "1 = supports sending Firmware Activation Notices"}; + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "0 = does not support sending the Namespace Attribute Notices event nor the associated Changed Namespace List log page", + "1 = supports sending the Namespace Attribute Notices & the associated Changed Namespace List log page", + "0 = does not support sending Firmware Activation Notices event", + "1 = supports sending Firmware Activation Notices"}; const char *CTRATTtable[4] = {"0 = does not support a 128-bit Host Identifier", - "1 = supports a 128-bit Host Identifier", - "0 = does not support Non-Operational Power State Permissive Mode", - "1 = supports Non-Operational Power State Permissive Mode"}; + "1 = supports a 128-bit Host Identifier", + "0 = does not support Non-Operational Power State Permissive Mode", + "1 = supports Non-Operational Power State Permissive Mode"}; const char *OACStable[18] = {"0 = does not support the Security Send and Security Receive commands", - "1 = supports the Security Send and Security Receive commands", - "0 = does not support the Format NVM command", - "1 = supports the Format NVM command", - "0 = does not support the Firmware Commit and Firmware Image Download commands", - "1 = supports the Firmware Commit and Firmware Image Download commands", - "0 = does not support the Namespace Management capability", - "1 = supports the Namespace Management capability", - "0 = does not support the Device Self-test command", - "1 = supports the Device Self-test command", - "0 = does not support Directives", - "1 = supports Directive Send & Directive Receive commands", - "0 = does not support the NVMe-MI Send and NVMe-MI Receive commands", - "1 = supports the NVMe-MI Send and NVMe-MI Receive commands", - "0 = does not support the Virtualization Management command", - "1 = supports the Virtualization Management command", - "0 = does not support the Doorbell Buffer Config command", - "1 = supports the Doorbell Buffer Config command"}; + "1 = supports the Security Send and Security Receive commands", + "0 = does not support the Format NVM command", + "1 = supports the Format NVM command", + "0 = does not support the Firmware Commit and Firmware Image Download commands", + "1 = supports the Firmware Commit and Firmware Image Download commands", + "0 = does not support the Namespace Management capability", + "1 = supports the Namespace Management capability", + "0 = does not support the Device Self-test command", + "1 = supports the Device Self-test command", + "0 = does not support Directives", + "1 = supports Directive Send & Directive Receive commands", + "0 = does not support the NVMe-MI Send and NVMe-MI Receive commands", + "1 = supports the NVMe-MI Send and NVMe-MI Receive commands", + "0 = does not support the Virtualization Management command", + "1 = supports the Virtualization Management command", + "0 = does not support the Doorbell Buffer Config command", + "1 = supports the Doorbell Buffer Config command"}; const char *FRMWtable[10] = {"0 = the 1st firmware slot (slot 1) is read/write", - "1 = the 1st firmware slot (slot 1) is read only", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "0 = requires a reset for firmware to be activated", - "1 = supports firmware activation without a reset"}; + "1 = the 1st firmware slot (slot 1) is read only", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "0 = requires a reset for firmware to be activated", + "1 = supports firmware activation without a reset"}; const char *LPAtable[8] = {"0 = does not support the SMART / Health information log page on a per namespace basis", - "1 = supports the SMART / Health information log page on a per namespace basis", - "0 = does not support the Commands Supported & Effects log page", - "1 = supports the Commands Supported Effects log page", - "0 = does not support extended data for Get Log Page", - "1 = supports extended data for Get Log Page (including extended Number of Dwords and Log Page Offset fields)", - "0 = does not support the Telemetry Host-Initiated and Telemetry Controller-Initiated log pages and Telemetry Log Notices events", - "1 = supports the Telemetry Host-Initiated and Telemetry Controller-Initiated log pages and sending Telemetry Log Notices" }; + "1 = supports the SMART / Health information log page on a per namespace basis", + "0 = does not support the Commands Supported & Effects log page", + "1 = supports the Commands Supported Effects log page", + "0 = does not support extended data for Get Log Page", + "1 = supports extended data for Get Log Page (including extended Number of Dwords and Log Page Offset fields)", + "0 = does not support the Telemetry Host-Initiated and Telemetry Controller-Initiated log pages and Telemetry Log Notices events", + "1 = supports the Telemetry Host-Initiated and Telemetry Controller-Initiated log pages and sending Telemetry Log Notices"}; const char *AVSCCtable[2] = {"0 = the format of all Admin Vendor Specific Commands are vendor specific", - "1 = all Admin Vendor Specific Commands use the format defined in NVM Express specification"}; + "1 = all Admin Vendor Specific Commands use the format defined in NVM Express specification"}; const char *APSTAtable[2] = {"0 = does not support autonomous power state transitions", - "1 = supports autonomous power state transitions"}; + "1 = supports autonomous power state transitions"}; const char *DSTOtable[2] = {"0 = the NVM subsystem supports one device self-test operation per controller at a time", - "1 = the NVM subsystem supports only one device self-test operation in progress at a time"}; + "1 = the NVM subsystem supports only one device self-test operation in progress at a time"}; const char *HCTMAtable[2] = {"0 = does not support host controlled thermal management", - "1 = supports host controlled thermal management. Supports Set Features & Get Features commands with the Feature Identifier field set to 10h"}; + "1 = supports host controlled thermal management. Supports Set Features & Get Features commands with the Feature Identifier field set to 10h"}; const char *SANICAPtable[6] = {"0 = does not support the Crypto Erase sanitize operation", - "1 = supports the Crypto Erase sanitize operation", - "0 = does not support the Block Erase sanitize operation", - "1 = supports the Block Erase sanitize operation", - "0 = does not support the Overwrite sanitize operation", - "1 = supports the Overwrite sanitize operation"}; + "1 = supports the Crypto Erase sanitize operation", + "0 = does not support the Block Erase sanitize operation", + "1 = supports the Block Erase sanitize operation", + "0 = does not support the Overwrite sanitize operation", + "1 = supports the Overwrite sanitize operation"}; const char *ONCStable[14] = {"0 = does not support the Compare command", - "1 = supports the Compare command", - "0 = does not support the Write Uncorrectable command", - "1 = supports the Write Uncorrectable command", - "0 = does not support the Dataset Management command", - "1 = supports the Dataset Management command", - "0 = does not support the Write Zeroes command", - "1 = supports the Write Zeroes command", - "0 = does not support the Save field set to a non-zero value in the Set Features and the Get Features commands", - "1 = supports the Save field set to a non-zero value in the Set Features and the Get Features commands", \ - "0 = does not support reservations", - "1 = supports reservations", - "0 = does not support the Timestamp feature (refer to section 5.21.1.14)", - "1 = supports the Timestamp feature"}; + "1 = supports the Compare command", + "0 = does not support the Write Uncorrectable command", + "1 = supports the Write Uncorrectable command", + "0 = does not support the Dataset Management command", + "1 = supports the Dataset Management command", + "0 = does not support the Write Zeroes command", + "1 = supports the Write Zeroes command", + "0 = does not support the Save field set to a non-zero value in the Set Features and the Get Features commands", + "1 = supports the Save field set to a non-zero value in the Set Features and the Get Features commands", + "0 = does not support reservations", + "1 = supports reservations", + "0 = does not support the Timestamp feature (refer to section 5.21.1.14)", + "1 = supports the Timestamp feature"}; const char *FUSEStable[2] = {"0 = does not support the Compare and Write fused operation", - "1 = supports the Compare and Write fused operation"}; + "1 = supports the Compare and Write fused operation"}; const char *FNAtable[6] = {"0 = supports format on a per namespace basis", - "1 = all namespaces shall be configured with the same attributes and a format (excluding secure erase) of any namespace results in a format of all namespaces in an NVM subsystem", - "0 = any secure erase performed as part of a format results in a secure erase of a particular namespace specified", - "1 = any secure erase performed as part of a format operation results in a secure erase of all namespaces in the NVM subsystem", - "0 = cryptographic erase is not supported", - "1 = cryptographic erase is supported as part of the secure erase functionality"}; + "1 = all namespaces shall be configured with the same attributes and a format (excluding secure erase) of any namespace results in a format of all namespaces in an NVM subsystem", + "0 = any secure erase performed as part of a format results in a secure erase of a particular namespace specified", + "1 = any secure erase performed as part of a format operation results in a secure erase of all namespaces in the NVM subsystem", + "0 = cryptographic erase is not supported", + "1 = cryptographic erase is supported as part of the secure erase functionality"}; const char *VWCtable[2] = {"0 = a volatile write cache is not present", - "1 = a volatile write cache is present"}; + "1 = a volatile write cache is present"}; const char *ICSVSCCtable[2] = {"0 = the format of all NVM Vendor Specific Commands are vendor specific", - "1 = all NVM Vendor Specific Commands use the format defined in NVM Express specification"}; + "1 = all NVM Vendor Specific Commands use the format defined in NVM Express specification"}; const char *SGLSSubtable[4] = {"00b = SGLs are not supported", - "01b = SGLs are supported. There is no alignment nor granularity requirement for Data Blocks", - "10b = SGLs are supported. There is a Dword alignment and granularity requirement for Data Blocks", - "11b = Reserved"}; + "01b = SGLs are supported. There is no alignment nor granularity requirement for Data Blocks", + "10b = SGLs are supported. There is a Dword alignment and granularity requirement for Data Blocks", + "11b = Reserved"}; const char *SGLStable[42] = {"Used", - "Used", - "Used", - "Used", - "0 = does not support the Keyed SGL Data Block descriptor", - "1 = supports the Keyed SGL Data Block descriptor", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "0 = the SGL Bit Bucket descriptor is not supported", - "1 = the SGL Bit Bucket descriptor is supported", - "0 = use of a byte aligned contiguous physical buffer of metadata is not supported", - "1 = use of a byte aligned contiguous physical buffer of metadata is supported", - "0 = the SGL length shall be equal to the amount of data to be transferred", - "1 = supports commands that contain a data or metadata SGL of a length larger than the amount of data to be transferred", - "0 = use of Metadata Pointer (MPTR) that contains an address of an SGL segment containing exactly one SGL Descriptor that is Qword aligned is not supported", - "1 = use of Metadata Pointer (MPTR) that contains an address of an SGL segment containing exactly one SGL Descriptor that is Qword aligned is supported", - "0 = the Address field specifying an offset is not supported", - "1 = supports the Address field in SGL Data Block, SGL Segment, and SGL Last Segment descriptor types specifying an offset"}; + "Used", + "Used", + "Used", + "0 = does not support the Keyed SGL Data Block descriptor", + "1 = supports the Keyed SGL Data Block descriptor", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "0 = the SGL Bit Bucket descriptor is not supported", + "1 = the SGL Bit Bucket descriptor is supported", + "0 = use of a byte aligned contiguous physical buffer of metadata is not supported", + "1 = use of a byte aligned contiguous physical buffer of metadata is supported", + "0 = the SGL length shall be equal to the amount of data to be transferred", + "1 = supports commands that contain a data or metadata SGL of a length larger than the amount of data to be transferred", + "0 = use of Metadata Pointer (MPTR) that contains an address of an SGL segment containing exactly one SGL Descriptor that is Qword aligned is not supported", + "1 = use of Metadata Pointer (MPTR) that contains an address of an SGL segment containing exactly one SGL Descriptor that is Qword aligned is supported", + "0 = the Address field specifying an offset is not supported", + "1 = supports the Address field in SGL Data Block, SGL Segment, and SGL Last Segment descriptor types specifying an offset"}; buf = (unsigned char *)(ctrl); @@ -791,12 +793,12 @@ static void vt_parse_detail_identify(const struct nvme_id_ctrl *ctrl) vt_convert_data_buffer_to_hex_string(&buf[296], 16, true, s); printf(" \"Unallocated NVM Capacity\":\"%sh\",\n", s); - temp = le32_to_cpu(ctrl->rpmbs); + temp = le32_to_cpu(ctrl->rpmbs); printf(" \"Replay Protected Memory Block Support\":{\n"); vt_convert_data_buffer_to_hex_string(&buf[312], 4, true, s); printf(" \"Value\":\"%sh\",\n", s); printf(" \"Number of RPMB Units\":\"%u\",\n", (temp & 0x00000003)); - snprintf(s, sizeof(s), ((temp >> 3) & 0x00000007)? "Reserved" : "HMAC SHA-256"); + snprintf(s, sizeof(s), ((temp >> 3) & 0x00000007) ? "Reserved" : "HMAC SHA-256"); printf(" \"Authentication Method\":\"%u: %s\",\n", ((temp >> 3) & 0x00000007), s); printf(" \"Total Size\":\"%u\",\n", ((temp >> 16) & 0x000000FF)); printf(" \"Access Size\":\"%u\",\n", ((temp >> 24) & 0x000000FF)); @@ -917,18 +919,18 @@ static void vt_parse_detail_identify(const struct nvme_id_ctrl *ctrl) static int vt_save_smart_to_vtview_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { int ret, err = 0; - long int total_time = 0; - long int freq_time = 0; - long int cur_time = 0; - long int remain_time = 0; - long int start_time = 0; - long int end_time = 0; + long total_time = 0; + long freq_time = 0; + long cur_time = 0; + long remain_time = 0; + long start_time = 0; + long end_time = 0; char path[256] = ""; char *desc = "Save SMART data into log file with format that is easy to analyze (comma delimited). Maximum log file will be 4K.\n\n" "Typical usages:\n\n" - "Temperature characterization: \n" + "Temperature characterization:\n" "\tvirtium save-smart-to-vtview-log /dev/yourDevice --run-time=100 --record-frequency=0.25 --test-name=burn-in-at-(-40)\n\n" - "Endurance testing : \n" + "Endurance testing :\n" "\tvirtium save-smart-to-vtview-log /dev/yourDevice --run-time=100 --record-frequency=1 --test-name=Endurance-test-JEDEG-219-workload\n\n" "Just logging :\n" "\tvirtium save-smart-to-vtview-log /dev/yourDevice"; @@ -979,13 +981,13 @@ static int vt_save_smart_to_vtview_log(int argc, char **argv, struct command *cm if (ret) { err = EINVAL; dev_close(dev); - return (err); + return err; } total_time = cfg.run_time_hrs * (float)HOUR_IN_SECONDS; freq_time = cfg.log_record_frequency_hrs * (float)HOUR_IN_SECONDS; - if(freq_time == 0) + if (!freq_time) freq_time = 1; start_time = time(NULL); @@ -995,7 +997,7 @@ static int vt_save_smart_to_vtview_log(int argc, char **argv, struct command *cm while (1) { cur_time = time(NULL); - if(cur_time >= end_time) + if (cur_time >= end_time) break; ret = vt_add_entry_to_log(dev_fd(dev), path, &cfg); @@ -1011,7 +1013,7 @@ static int vt_save_smart_to_vtview_log(int argc, char **argv, struct command *cm } dev_close(dev); - return (err); + return err; } static int vt_show_identify(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -1037,7 +1039,7 @@ static int vt_show_identify(int argc, char **argv, struct command *cmd, struct p if (ret) { printf("Cannot read identify device\n"); dev_close(dev); - return (-1); + return -1; } vt_process_string(ctrl.sn, sizeof(ctrl.sn)); @@ -1045,5 +1047,5 @@ static int vt_show_identify(int argc, char **argv, struct command *cmd, struct p vt_parse_detail_identify(&ctrl); dev_close(dev); - return (err); + return err; } diff --git a/plugins/wdc/wdc-nvme.c b/plugins/wdc/wdc-nvme.c index 2d5d173..ec3f2b0 100644 --- a/plugins/wdc/wdc-nvme.c +++ b/plugins/wdc/wdc-nvme.c @@ -20,7 +20,7 @@ * Author: Chaitanya Kulkarni <chaitanya.kulkarni@hgst.com>, * Dong Ho <dong.ho@hgst.com>, * Jeff Lien <jeff.lien@wdc.com> - * Brandon Paupore <brandon.paupore@wdc.com> + * Brandon Paupore <brandon.paupore@wdc.com> */ #include <stdio.h> #include <string.h> @@ -51,7 +51,7 @@ #define WDC_NVME_LOG_SIZE_HDR_LEN 0x08 /* Enclosure */ -#define WDC_OPENFLEX_MI_DEVICE_MODEL "OpenFlex" +#define WDC_OPENFLEX_MI_DEVICE_MODEL "OpenFlex" #define WDC_RESULT_MORE_DATA 0x80000000 #define WDC_RESULT_NOT_AVAILABLE 0x7FFFFFFF @@ -69,40 +69,41 @@ #define WDC_NVME_SN640_DEV_ID 0x2400 #define WDC_NVME_SN640_DEV_ID_1 0x2401 #define WDC_NVME_SN640_DEV_ID_2 0x2402 -#define WDC_NVME_SN640_DEV_ID_3 0x2404 -#define WDC_NVME_ZN540_DEV_ID 0x2600 -#define WDC_NVME_SN540_DEV_ID 0x2610 +#define WDC_NVME_SN640_DEV_ID_3 0x2404 +#define WDC_NVME_ZN540_DEV_ID 0x2600 +#define WDC_NVME_SN540_DEV_ID 0x2610 #define WDC_NVME_SN650_DEV_ID 0x2700 -#define WDC_NVME_SN650_DEV_ID_1 0x2701 -#define WDC_NVME_SN650_DEV_ID_2 0x2702 -#define WDC_NVME_SN650_DEV_ID_3 0x2720 -#define WDC_NVME_SN650_DEV_ID_4 0x2721 -#define WDC_NVME_SN655_DEV_ID 0x2722 -#define WDC_NVME_SN860_DEV_ID 0x2730 -#define WDC_NVME_SN660_DEV_ID 0x2704 +#define WDC_NVME_SN650_DEV_ID_1 0x2701 +#define WDC_NVME_SN650_DEV_ID_2 0x2702 +#define WDC_NVME_SN650_DEV_ID_3 0x2720 +#define WDC_NVME_SN650_DEV_ID_4 0x2721 +#define WDC_NVME_SN655_DEV_ID 0x2722 +#define WDC_NVME_SN860_DEV_ID 0x2730 +#define WDC_NVME_SN660_DEV_ID 0x2704 /* This id's are no longer supported, delete ?? */ -#define WDC_NVME_SN550_DEV_ID 0x2708 -#define WDC_NVME_SN560_DEV_ID_1 0x2712 -#define WDC_NVME_SN560_DEV_ID_2 0x2713 -#define WDC_NVME_SN560_DEV_ID_3 0x2714 +#define WDC_NVME_SN550_DEV_ID 0x2708 +#define WDC_NVME_SN560_DEV_ID_1 0x2712 +#define WDC_NVME_SN560_DEV_ID_2 0x2713 +#define WDC_NVME_SN560_DEV_ID_3 0x2714 #define WDC_NVME_SXSLCL_DEV_ID 0x2001 #define WDC_NVME_SN520_DEV_ID 0x5003 #define WDC_NVME_SN520_DEV_ID_1 0x5004 #define WDC_NVME_SN520_DEV_ID_2 0x5005 #define WDC_NVME_SN530_DEV_ID 0x5009 +#define WDC_NVME_SN530_DEV_ID_1 0x501d #define WDC_NVME_SN720_DEV_ID 0x5002 #define WDC_NVME_SN730A_DEV_ID 0x5006 #define WDC_NVME_SN740_DEV_ID 0x5015 -#define WDC_NVME_SN740_DEV_ID_1 0x5016 -#define WDC_NVME_SN740_DEV_ID_2 0x5017 -#define WDC_NVME_SN740_DEV_ID_3 0x5025 +#define WDC_NVME_SN740_DEV_ID_1 0x5016 +#define WDC_NVME_SN740_DEV_ID_2 0x5017 +#define WDC_NVME_SN740_DEV_ID_3 0x5025 #define WDC_NVME_SN340_DEV_ID 0x500d #define WDC_NVME_ZN350_DEV_ID 0x5010 -#define WDC_NVME_ZN350_DEV_ID_1 0x5018 +#define WDC_NVME_ZN350_DEV_ID_1 0x5018 #define WDC_NVME_SN810_DEV_ID 0x5011 -#define WDC_NVME_SN820CL_DEV_ID 0x5037 +#define WDC_NVME_SN820CL_DEV_ID 0x5037 #define WDC_DRIVE_CAP_CAP_DIAG 0x0000000000000001 #define WDC_DRIVE_CAP_INTERNAL_LOG 0x0000000000000002 @@ -114,49 +115,53 @@ #define WDC_DRIVE_CAP_CLEAR_PCIE 0x0000000000000080 #define WDC_DRIVE_CAP_RESIZE 0x0000000000000100 #define WDC_DRIVE_CAP_NAND_STATS 0x0000000000000200 -#define WDC_DRIVE_CAP_DRIVE_LOG 0x0000000000000400 -#define WDC_DRIVE_CAP_CRASH_DUMP 0x0000000000000800 -#define WDC_DRIVE_CAP_PFAIL_DUMP 0x0000000000001000 -#define WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY 0x0000000000002000 -#define WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY 0x0000000000004000 -#define WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG 0x0000000000008000 -#define WDC_DRIVE_CAP_REASON_ID 0x0000000000010000 -#define WDC_DRIVE_CAP_LOG_PAGE_DIR 0x0000000000020000 -#define WDC_DRIVE_CAP_NS_RESIZE 0x0000000000040000 -#define WDC_DRIVE_CAP_INFO 0x0000000000080000 -#define WDC_DRIVE_CAP_C0_LOG_PAGE 0x0000000000100000 -#define WDC_DRIVE_CAP_TEMP_STATS 0x0000000000200000 -#define WDC_DRIVE_CAP_VUC_CLEAR_PCIE 0x0000000000400000 -#define WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE 0x0000000000800000 -#define WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C2 0x0000000001000000 +#define WDC_DRIVE_CAP_DRIVE_LOG 0x0000000000000400 +#define WDC_DRIVE_CAP_CRASH_DUMP 0x0000000000000800 +#define WDC_DRIVE_CAP_PFAIL_DUMP 0x0000000000001000 +#define WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY 0x0000000000002000 +#define WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY 0x0000000000004000 +#define WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG 0x0000000000008000 +#define WDC_DRIVE_CAP_REASON_ID 0x0000000000010000 +#define WDC_DRIVE_CAP_LOG_PAGE_DIR 0x0000000000020000 +#define WDC_DRIVE_CAP_NS_RESIZE 0x0000000000040000 +#define WDC_DRIVE_CAP_INFO 0x0000000000080000 +#define WDC_DRIVE_CAP_C0_LOG_PAGE 0x0000000000100000 +#define WDC_DRIVE_CAP_TEMP_STATS 0x0000000000200000 +#define WDC_DRIVE_CAP_VUC_CLEAR_PCIE 0x0000000000400000 +#define WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE 0x0000000000800000 +#define WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C2 0x0000000001000000 #define WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY 0x0000000002000000 -#define WDC_DRIVE_CAP_CLOUD_SSD_VERSION 0x0000000004000000 +#define WDC_DRIVE_CAP_CLOUD_SSD_VERSION 0x0000000004000000 #define WDC_DRIVE_CAP_PCIE_STATS 0x0000000008000000 -#define WDC_DRIVE_CAP_HW_REV_LOG_PAGE 0x0000000010000000 +#define WDC_DRIVE_CAP_HW_REV_LOG_PAGE 0x0000000010000000 #define WDC_DRIVE_CAP_C3_LOG_PAGE 0x0000000020000000 #define WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION 0x0000000040000000 -#define WDC_DRIVE_CAP_CLOUD_LOG_PAGE 0x0000000080000000 +#define WDC_DRIVE_CAP_CLOUD_LOG_PAGE 0x0000000080000000 -#define WDC_DRIVE_CAP_DRIVE_ESSENTIALS 0x0000000100000000 +#define WDC_DRIVE_CAP_DRIVE_ESSENTIALS 0x0000000100000000 #define WDC_DRIVE_CAP_DUI_DATA 0x0000000200000000 #define WDC_SN730B_CAP_VUC_LOG 0x0000000400000000 -#define WDC_DRIVE_CAP_DUI 0x0000000800000000 -#define WDC_DRIVE_CAP_PURGE 0x0000001000000000 -#define WDC_DRIVE_CAP_OCP_C1_LOG_PAGE 0x0000002000000000 -#define WDC_DRIVE_CAP_OCP_C4_LOG_PAGE 0x0000004000000000 -#define WDC_DRIVE_CAP_OCP_C5_LOG_PAGE 0x0000008000000000 -#define WDC_DRIVE_CAP_DEVICE_WAF 0x0000010000000000 -#define WDC_DRIVE_CAP_SMART_LOG_MASK (WDC_DRIVE_CAP_C0_LOG_PAGE | WDC_DRIVE_CAP_C1_LOG_PAGE | \ - WDC_DRIVE_CAP_CA_LOG_PAGE | WDC_DRIVE_CAP_D0_LOG_PAGE) -#define WDC_DRIVE_CAP_CLEAR_PCIE_MASK (WDC_DRIVE_CAP_CLEAR_PCIE | \ - WDC_DRIVE_CAP_VUC_CLEAR_PCIE | \ - WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE) +#define WDC_DRIVE_CAP_DUI 0x0000000800000000 +#define WDC_DRIVE_CAP_PURGE 0x0000001000000000 +#define WDC_DRIVE_CAP_OCP_C1_LOG_PAGE 0x0000002000000000 +#define WDC_DRIVE_CAP_OCP_C4_LOG_PAGE 0x0000004000000000 +#define WDC_DRIVE_CAP_OCP_C5_LOG_PAGE 0x0000008000000000 +#define WDC_DRIVE_CAP_DEVICE_WAF 0x0000010000000000 +#define WDC_DRIVE_CAP_SMART_LOG_MASK (WDC_DRIVE_CAP_C0_LOG_PAGE | \ + WDC_DRIVE_CAP_C1_LOG_PAGE | \ + WDC_DRIVE_CAP_CA_LOG_PAGE | \ + WDC_DRIVE_CAP_D0_LOG_PAGE) +#define WDC_DRIVE_CAP_CLEAR_PCIE_MASK (WDC_DRIVE_CAP_CLEAR_PCIE | \ + WDC_DRIVE_CAP_VUC_CLEAR_PCIE | \ + WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE) #define WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_MASK (WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY | \ - WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C2) + WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C2) #define WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY_MASK (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY | \ - WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY) -#define WDC_DRIVE_CAP_INTERNAL_LOG_MASK (WDC_DRIVE_CAP_INTERNAL_LOG | WDC_DRIVE_CAP_DUI | \ - WDC_DRIVE_CAP_DUI_DATA | WDC_SN730B_CAP_VUC_LOG) + WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY) +#define WDC_DRIVE_CAP_INTERNAL_LOG_MASK (WDC_DRIVE_CAP_INTERNAL_LOG | \ + WDC_DRIVE_CAP_DUI | \ + WDC_DRIVE_CAP_DUI_DATA | \ + WDC_SN730B_CAP_VUC_LOG) /* SN730 Get Log Capabilities */ #define SN730_NVME_GET_LOG_OPCODE 0xc2 #define SN730_GET_FULL_LOG_LENGTH 0x00080009 @@ -171,9 +176,9 @@ #define SN730_LOG_CHUNK_SIZE 0x1000 /* Customer ID's */ -#define WDC_CUSTOMER_ID_GN 0x0001 -#define WDC_CUSTOMER_ID_GD 0x0101 -#define WDC_CUSTOMER_ID_BD 0x1009 +#define WDC_CUSTOMER_ID_GN 0x0001 +#define WDC_CUSTOMER_ID_GD 0x0101 +#define WDC_CUSTOMER_ID_BD 0x1009 #define WDC_CUSTOMER_ID_0x1005 0x1005 @@ -182,27 +187,27 @@ #define WDC_CUSTOMER_ID_0x1304 0x1304 #define WDC_INVALID_CUSTOMER_ID -1 -#define WDC_ALL_PAGE_MASK 0xFFFF -#define WDC_C0_PAGE_MASK 0x0001 -#define WDC_C1_PAGE_MASK 0x0002 -#define WDC_CA_PAGE_MASK 0x0004 -#define WDC_D0_PAGE_MASK 0x0008 +#define WDC_ALL_PAGE_MASK 0xFFFF +#define WDC_C0_PAGE_MASK 0x0001 +#define WDC_C1_PAGE_MASK 0x0002 +#define WDC_CA_PAGE_MASK 0x0004 +#define WDC_D0_PAGE_MASK 0x0008 /* Drive Resize */ #define WDC_NVME_DRIVE_RESIZE_OPCODE 0xCC #define WDC_NVME_DRIVE_RESIZE_CMD 0x03 #define WDC_NVME_DRIVE_RESIZE_SUBCMD 0x01 -/* Namespace Resize */ -#define WDC_NVME_NAMESPACE_RESIZE_OPCODE 0xFB +/* Namespace Resize */ +#define WDC_NVME_NAMESPACE_RESIZE_OPCODE 0xFB /* Drive Info */ -#define WDC_NVME_DRIVE_INFO_OPCODE 0xC6 -#define WDC_NVME_DRIVE_INFO_CMD 0x22 -#define WDC_NVME_DRIVE_INFO_SUBCMD 0x06 +#define WDC_NVME_DRIVE_INFO_OPCODE 0xC6 +#define WDC_NVME_DRIVE_INFO_CMD 0x22 +#define WDC_NVME_DRIVE_INFO_SUBCMD 0x06 /* VS PCIE Stats */ -#define WDC_NVME_PCIE_STATS_OPCODE 0xD1 +#define WDC_NVME_PCIE_STATS_OPCODE 0xD1 /* Capture Diagnostics */ #define WDC_NVME_CAP_DIAG_HEADER_TOC_SIZE WDC_NVME_LOG_SIZE_DATA_LEN @@ -217,19 +222,19 @@ /* Capture Device Unit Info */ #define WDC_NVME_CAP_DUI_HEADER_SIZE 0x400 #define WDC_NVME_CAP_DUI_OPCODE 0xFA -#define WDC_NVME_CAP_DUI_DISABLE_IO 0x01 +#define WDC_NVME_CAP_DUI_DISABLE_IO 0x01 #define WDC_NVME_DUI_MAX_SECTION 0x3A #define WDC_NVME_DUI_MAX_SECTION_V2 0x26 #define WDC_NVME_DUI_MAX_SECTION_V3 0x23 #define WDC_NVME_DUI_MAX_DATA_AREA 0x05 -#define WDC_NVME_SN730_SECTOR_SIZE 512 +#define WDC_NVME_SN730_SECTOR_SIZE 512 -/* Telemtery types for vs-internal-log command */ -#define WDC_TELEMETRY_TYPE_NONE 0x0 -#define WDC_TELEMETRY_TYPE_HOST 0x1 -#define WDC_TELEMETRY_TYPE_CONTROLLER 0x2 -#define WDC_TELEMETRY_HEADER_LENGTH 512 -#define WDC_TELEMETRY_BLOCK_SIZE 512 +/* Telemtery types for vs-internal-log command */ +#define WDC_TELEMETRY_TYPE_NONE 0x0 +#define WDC_TELEMETRY_TYPE_HOST 0x1 +#define WDC_TELEMETRY_TYPE_CONTROLLER 0x2 +#define WDC_TELEMETRY_HEADER_LENGTH 512 +#define WDC_TELEMETRY_BLOCK_SIZE 512 /* Crash dump */ #define WDC_NVME_CRASH_DUMP_SIZE_DATA_LEN WDC_NVME_LOG_SIZE_DATA_LEN @@ -284,7 +289,7 @@ #define WDC_NVME_CLEAR_PF_CRASH_DUMP_SUBCMD 0x06 /* Clear FW Activate History */ -#define WDC_NVME_CLEAR_FW_ACT_HIST_OPCODE 0xC6 +#define WDC_NVME_CLEAR_FW_ACT_HIST_OPCODE 0xC6 #define WDC_NVME_CLEAR_FW_ACT_HIST_CMD 0x23 #define WDC_NVME_CLEAR_FW_ACT_HIST_SUBCMD 0x05 #define WDC_NVME_CLEAR_FW_ACT_HIST_VU_FID 0xC1 @@ -297,10 +302,10 @@ /* C2 Log Page */ #define WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE 0xC2 -#define WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE_C8 0xC8 +#define WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE_C8 0xC8 #define WDC_C2_LOG_BUF_LEN 0x1000 #define WDC_C2_LOG_PAGES_SUPPORTED_ID 0x08 -#define WDC_C2_CUSTOMER_ID_ID 0x15 +#define WDC_C2_CUSTOMER_ID_ID 0x15 #define WDC_C2_THERMAL_THROTTLE_STATUS_ID 0x18 #define WDC_C2_ASSERT_DUMP_PRESENT_ID 0x19 #define WDC_C2_USER_EOL_STATUS_ID 0x1A @@ -321,69 +326,72 @@ /* CA Log Page */ #define WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE 0xCA -#define WDC_FB_CA_LOG_BUF_LEN 0x80 -#define WDC_BD_CA_LOG_BUF_LEN 0xA0 /* Added 4 padding bytes to resolve build warning messages */ +#define WDC_FB_CA_LOG_BUF_LEN 0x80 +/* Added 4 padding bytes to resolve build warning messages */ +#define WDC_BD_CA_LOG_BUF_LEN 0xA0 /* C0 EOL Status Log Page */ #define WDC_NVME_GET_EOL_STATUS_LOG_OPCODE 0xC0 -#define WDC_NVME_EOL_STATUS_LOG_LEN 0x200 +#define WDC_NVME_EOL_STATUS_LOG_LEN 0x200 #define WDC_NVME_SMART_CLOUD_ATTR_LEN 0x200 /* C0 SMART Cloud Attributes Log Page*/ -#define WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID 0xC0 +#define WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID 0xC0 /* CB - FW Activate History Log Page */ -#define WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID 0xCB -#define WDC_FW_ACT_HISTORY_LOG_BUF_LEN 0x3d0 +#define WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID 0xCB +#define WDC_FW_ACT_HISTORY_LOG_BUF_LEN 0x3d0 /* C2 - FW Activation History Log Page */ -#define WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID 0xC2 -#define WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN 0x1000 -#define WDC_MAX_NUM_ACT_HIST_ENTRIES 20 -#define WDC_C2_GUID_LENGTH 16 +#define WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID 0xC2 +#define WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN 0x1000 +#define WDC_MAX_NUM_ACT_HIST_ENTRIES 20 +#define WDC_C2_GUID_LENGTH 16 /* C3 Latency Monitor Log Page */ -#define WDC_LATENCY_MON_LOG_BUF_LEN 0x200 -#define WDC_LATENCY_MON_LOG_ID 0xC3 -#define WDC_LATENCY_MON_VERSION 0x0001 - -#define WDC_C3_GUID_LENGTH 16 -static __u8 wdc_lat_mon_guid[WDC_C3_GUID_LENGTH] = { 0x92, 0x7a, 0xc0, 0x8c, 0xd0, 0x84, 0x6c, 0x9c, - 0x70, 0x43, 0xe6, 0xd4, 0x58, 0x5e, 0xd4, 0x85 }; +#define WDC_LATENCY_MON_LOG_BUF_LEN 0x200 +#define WDC_LATENCY_MON_LOG_ID 0xC3 +#define WDC_LATENCY_MON_VERSION 0x0001 + +#define WDC_C3_GUID_LENGTH 16 +static __u8 wdc_lat_mon_guid[WDC_C3_GUID_LENGTH] = { + 0x92, 0x7a, 0xc0, 0x8c, 0xd0, 0x84, 0x6c, 0x9c, + 0x70, 0x43, 0xe6, 0xd4, 0x58, 0x5e, 0xd4, 0x85 +}; /* D0 Smart Log Page */ #define WDC_NVME_GET_VU_SMART_LOG_OPCODE 0xD0 -#define WDC_NVME_VU_SMART_LOG_LEN 0x200 - -/* Log Page Directory defines */ -#define NVME_LOG_PERSISTENT_EVENT 0x0D -#define WDC_LOG_ID_C0 0xC0 -#define WDC_LOG_ID_C1 0xC1 -#define WDC_LOG_ID_C2 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE -#define WDC_LOG_ID_C3 0xC3 -#define WDC_LOG_ID_C4 0xC4 -#define WDC_LOG_ID_C5 0xC5 -#define WDC_LOG_ID_C6 0xC6 -#define WDC_LOG_ID_C8 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE_C8 -#define WDC_LOG_ID_CA WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE -#define WDC_LOG_ID_CB WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID -#define WDC_LOG_ID_D0 WDC_NVME_GET_VU_SMART_LOG_OPCODE -#define WDC_LOG_ID_D1 0xD1 -#define WDC_LOG_ID_D6 0xD6 -#define WDC_LOG_ID_D7 0xD7 -#define WDC_LOG_ID_D8 0xD8 -#define WDC_LOG_ID_DE 0xDE -#define WDC_LOG_ID_F0 0xF0 -#define WDC_LOG_ID_F1 0xF1 -#define WDC_LOG_ID_F2 0xF2 -#define WDC_LOG_ID_FA 0xFA +#define WDC_NVME_VU_SMART_LOG_LEN 0x200 + +/* Log Page Directory defines */ +#define NVME_LOG_PERSISTENT_EVENT 0x0D +#define WDC_LOG_ID_C0 0xC0 +#define WDC_LOG_ID_C1 0xC1 +#define WDC_LOG_ID_C2 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE +#define WDC_LOG_ID_C3 0xC3 +#define WDC_LOG_ID_C4 0xC4 +#define WDC_LOG_ID_C5 0xC5 +#define WDC_LOG_ID_C6 0xC6 +#define WDC_LOG_ID_C8 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE_C8 +#define WDC_LOG_ID_CA WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE +#define WDC_LOG_ID_CB WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID +#define WDC_LOG_ID_D0 WDC_NVME_GET_VU_SMART_LOG_OPCODE +#define WDC_LOG_ID_D1 0xD1 +#define WDC_LOG_ID_D6 0xD6 +#define WDC_LOG_ID_D7 0xD7 +#define WDC_LOG_ID_D8 0xD8 +#define WDC_LOG_ID_DE 0xDE +#define WDC_LOG_ID_F0 0xF0 +#define WDC_LOG_ID_F1 0xF1 +#define WDC_LOG_ID_F2 0xF2 +#define WDC_LOG_ID_FA 0xFA /* Clear PCIe Correctable Errors */ -#define WDC_NVME_CLEAR_PCIE_CORR_OPCODE WDC_NVME_CAP_DIAG_CMD_OPCODE -#define WDC_NVME_CLEAR_PCIE_CORR_CMD 0x22 -#define WDC_NVME_CLEAR_PCIE_CORR_SUBCMD 0x04 -#define WDC_NVME_CLEAR_PCIE_CORR_OPCODE_VUC 0xD2 -#define WDC_NVME_CLEAR_PCIE_CORR_FEATURE_ID 0xC3 +#define WDC_NVME_CLEAR_PCIE_CORR_OPCODE WDC_NVME_CAP_DIAG_CMD_OPCODE +#define WDC_NVME_CLEAR_PCIE_CORR_CMD 0x22 +#define WDC_NVME_CLEAR_PCIE_CORR_SUBCMD 0x04 +#define WDC_NVME_CLEAR_PCIE_CORR_OPCODE_VUC 0xD2 +#define WDC_NVME_CLEAR_PCIE_CORR_FEATURE_ID 0xC3 /* Clear Assert Dump Status */ #define WDC_NVME_CLEAR_ASSERT_DUMP_OPCODE 0xD8 #define WDC_NVME_CLEAR_ASSERT_DUMP_CMD 0x03 @@ -423,52 +431,49 @@ static __u8 wdc_lat_mon_guid[WDC_C3_GUID_LENGTH] = { 0x92, 0x7a, 0xc0, 0x8c, #define WDC_DE_DESTN_SPI 1 #define WDC_DE_DUMPTRACE_DESTINATION 6 -#define NVME_ID_CTRL_MODEL_NUMBER_SIZE 40 -#define NVME_ID_CTRL_SERIAL_NUMBER_SIZE 20 +#define NVME_ID_CTRL_MODEL_NUMBER_SIZE 40 +#define NVME_ID_CTRL_SERIAL_NUMBER_SIZE 20 /* Enclosure log */ -#define WDC_NVME_ENC_LOG_SIZE_CHUNK 0x1000 -#define WDC_NVME_ENC_NIC_LOG_SIZE 0x400000 +#define WDC_NVME_ENC_LOG_SIZE_CHUNK 0x1000 +#define WDC_NVME_ENC_NIC_LOG_SIZE 0x400000 /* Enclosure nic crash dump get-log id */ -#define WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_1 0xD1 -#define WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_2 0xD2 -#define WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_3 0xD3 -#define WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_4 0xD4 -#define WDC_ENC_CRASH_DUMP_ID 0xE4 -#define WDC_ENC_LOG_DUMP_ID 0xE2 - -typedef enum _NVME_FEATURES_SELECT -{ - FS_CURRENT = 0, - FS_DEFAULT = 1, - FS_SAVED = 2, - FS_SUPPORTED_CAPBILITIES = 3 -} NVME_FEATURES_SELECT; - -typedef enum _NVME_FEATURE_IDENTIFIERS -{ - FID_ARBITRATION = 0x01, - FID_POWER_MANAGEMENT = 0x02, - FID_LBA_RANGE_TYPE = 0x03, - FID_TEMPERATURE_THRESHOLD = 0x04, - FID_ERROR_RECOVERY = 0x05, - FID_VOLATILE_WRITE_CACHE = 0x06, - FID_NUMBER_OF_QUEUES = 0x07, - FID_INTERRUPT_COALESCING = 0x08, - FID_INTERRUPT_VECTOR_CONFIGURATION = 0x09, - FID_WRITE_ATOMICITY = 0x0A, - FID_ASYNCHRONOUS_EVENT_CONFIGURATION = 0x0B, - FID_AUTONOMOUS_POWER_STATE_TRANSITION = 0x0C, -/*Below FID's are NVM Command Set Specific*/ - FID_SOFTWARE_PROGRESS_MARKER = 0x80, - FID_HOST_IDENTIFIER = 0x81, - FID_RESERVATION_NOTIFICATION_MASK = 0x82, - FID_RESERVATION_PERSISTENCE = 0x83 -} NVME_FEATURE_IDENTIFIERS; - -typedef enum -{ +#define WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_1 0xD1 +#define WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_2 0xD2 +#define WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_3 0xD3 +#define WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_4 0xD4 +#define WDC_ENC_CRASH_DUMP_ID 0xE4 +#define WDC_ENC_LOG_DUMP_ID 0xE2 + +enum _NVME_FEATURES_SELECT { + FS_CURRENT = 0, + FS_DEFAULT = 1, + FS_SAVED = 2, + FS_SUPPORTED_CAPBILITIES = 3 +}; + +enum NVME_FEATURE_IDENTIFIERS { + FID_ARBITRATION = 0x01, + FID_POWER_MANAGEMENT = 0x02, + FID_LBA_RANGE_TYPE = 0x03, + FID_TEMPERATURE_THRESHOLD = 0x04, + FID_ERROR_RECOVERY = 0x05, + FID_VOLATILE_WRITE_CACHE = 0x06, + FID_NUMBER_OF_QUEUES = 0x07, + FID_INTERRUPT_COALESCING = 0x08, + FID_INTERRUPT_VECTOR_CONFIGURATION = 0x09, + FID_WRITE_ATOMICITY = 0x0A, + FID_ASYNCHRONOUS_EVENT_CONFIGURATION = 0x0B, + FID_AUTONOMOUS_POWER_STATE_TRANSITION = 0x0C, + /*Below FID's are NVM Command Set Specific*/ + FID_SOFTWARE_PROGRESS_MARKER = 0x80, + FID_HOST_IDENTIFIER = 0x81, + FID_RESERVATION_NOTIFICATION_MASK = 0x82, + FID_RESERVATION_PERSISTENCE = 0x83 +}; + +enum WDC_DRIVE_ESSENTIAL_TYPE { WDC_DE_TYPE_IDENTIFY = 0x1, WDC_DE_TYPE_SMARTATTRIBUTEDUMP = 0x2, WDC_DE_TYPE_EVENTLOG = 0x4, @@ -496,13 +501,12 @@ typedef enum WDC_DE_TYPE_NVME_MANF_INFO = 0x2000000, WDC_DE_TYPE_NONE = 0x1000000, WDC_DE_TYPE_ALL = 0xFFFFFFF, -} WDC_DRIVE_ESSENTIAL_TYPE; +}; #define WDC_C0_GUID_LENGTH 16 #define WDC_SCA_V1_NAND_STATS 0x1 #define WDC_SCA_V1_ALL 0xF -typedef enum -{ +enum { SCAO_V1_PMUWT = 0, /* Physical media units written TLC */ SCAO_V1_PMUWS = 16, /* Physical media units written SLC */ SCAO_V1_BUNBN = 32, /* Bad user nand blocks normalized */ @@ -528,7 +532,7 @@ typedef enum SCAO_V1_SVN = 160, /* Security Version Number */ SCAO_V1_PFBS = 168, /* Percent free blocks (System) */ SCAO_V1_DCC = 172, /* Deallocate Commands Completed */ - SCAO_V1_TNU = 188, /* Total Namespace Utilization */ + SCAO_V1_TNU = 188, /* Total Namespace Utilization */ SCAO_V1_FCC = 196, /* Format NVM Commands Completed */ SCAO_V1_BBPG = 198, /* Background Back-Pressure Gauge */ SCAO_V1_SEEC = 202, /* Soft ECC error count */ @@ -548,18 +552,19 @@ typedef enum SCAO_V1_MIVF = 302, /* Boot SSD minor version field */ SCAO_V1_PVF = 304, /* Boot SSD point version field */ SCAO_V1_EVF = 306, /* Boot SSD errata version field */ - SCAO_V1_FTLUS = 308, /* FTL Unit Size */ + SCAO_V1_FTLUS = 308, /* FTL Unit Size */ SCAO_V1_TCGOS = 312, /* TCG Ownership Status */ SCAO_V1_LPV = 494, /* Log page version - 0x0001 */ SCAO_V1_LPG = 496, /* Log page GUID */ -} SMART_CLOUD_ATTRIBUTE_OFFSETS_V1; +}; -static __u8 ext_smart_guid[WDC_C0_GUID_LENGTH] = { 0x65, 0x43, 0x88, 0x78, 0xAC, 0xD8, 0x78, 0xA1, - 0x66, 0x42, 0x1E, 0x0F, 0x92, 0xD7, 0x6D, 0xC4 }; +static __u8 ext_smart_guid[WDC_C0_GUID_LENGTH] = { + 0x65, 0x43, 0x88, 0x78, 0xAC, 0xD8, 0x78, 0xA1, + 0x66, 0x42, 0x1E, 0x0F, 0x92, 0xD7, 0x6D, 0xC4 +}; -typedef struct __attribute__((__packed__)) wdc_nvme_ext_smart_log -{ +struct __packed wdc_nvme_ext_smart_log { __u8 ext_smart_pmuwt[16]; /* 000 Physical media units written TLC */ __u8 ext_smart_pmuws[16]; /* 016 Physical media units written SLC */ __u8 ext_smart_bunbc[8]; /* 032 Bad user nand block count */ @@ -576,8 +581,8 @@ typedef struct __attribute__((__packed__)) wdc_nvme_ext_smart_log __u64 ext_smart_mnec; /* 108 Min Erase counts (SLC) */ __u64 ext_smart_mxec; /* 116 Max Erase counts (SLC) */ __u64 ext_smart_avec; /* 124 Average Erase counts (SLC) */ - __u8 ext_smart_pfc[8]; /* 132 Program fail count */ - __u8 ext_smart_efc[8]; /* 140 Erase fail count */ + __u8 ext_smart_pfc[8]; /* 132 Program fail count */ + __u8 ext_smart_efc[8]; /* 140 Erase fail count */ __u64 ext_smart_pcec; /* 148 PCIe correctable error count */ __u8 ext_smart_pfbu; /* 156 Percent free blocks (User) */ __u8 ext_smart_rsvd2[3]; /* 157 reserved */ @@ -585,17 +590,17 @@ typedef struct __attribute__((__packed__)) wdc_nvme_ext_smart_log __u8 ext_smart_pfbs; /* 168 Percent free blocks (System) */ __u8 ext_smart_rsvd3[3]; /* 169 reserved */ __u8 ext_smart_dcc[16]; /* 172 Deallocate Commands Completed */ - __u64 ext_smart_tnu; /* 188 Total Namespace Utilization */ - __u16 ext_smart_fcc; /* 196 Format NVM Commands Completed */ + __u64 ext_smart_tnu; /* 188 Total Namespace Utilization */ + __u16 ext_smart_fcc; /* 196 Format NVM Commands Completed */ __u8 ext_smart_bbpg; /* 198 Background Back-Pressure Gauge */ __u8 ext_smart_rsvd4[3]; /* 199 reserved */ __u64 ext_smart_seec; /* 202 Soft ECC error count */ __u64 ext_smart_rfsc; /* 210 Refresh count */ __u8 ext_smart_bsnbc[8]; /* 218 Bad system nand block count */ __u8 ext_smart_eest[16]; /* 226 Endurance estimate */ - __u16 ext_smart_ttc; /* 242 Thermal throttling count */ + __u16 ext_smart_ttc; /* 242 Thermal throttling count */ __u64 ext_smart_uio; /* 244 Unaligned I/O */ - __u8 ext_smart_pmur[16]; /* 252 Physical media units read */ + __u8 ext_smart_pmur[16]; /* 252 Physical media units read */ __u32 ext_smart_rtoc; /* 268 Read command timeout count */ __u32 ext_smart_wtoc; /* 272 Write command timeout count */ __u32 ext_smart_ttoc; /* 276 Trim command timeout count */ @@ -604,144 +609,141 @@ typedef struct __attribute__((__packed__)) wdc_nvme_ext_smart_log __u64 ext_smart_pscc; /* 292 Power State Change Count */ __u16 ext_smart_maj; /* 300 Boot SSD major version field */ __u16 ext_smart_min; /* 302 Boot SSD minor version field */ - __u16 ext_smart_pt; /* 304 Boot SSD point version field */ + __u16 ext_smart_pt; /* 304 Boot SSD point version field */ __u16 ext_smart_err; /* 306 Boot SSD errata version field */ - __u32 ext_smart_ftlus; /* 308 FTL Unit Size */ + __u32 ext_smart_ftlus; /* 308 FTL Unit Size */ __u32 ext_smart_tcgos; /* 312 TCG Ownership Status */ __u8 ext_smart_rsvd6[178]; /* 316 reserved */ __u16 ext_smart_lpv; /* 494 Log page version - 0x0001 */ __u8 ext_smart_lpg[16]; /* 496 Log page GUID */ -} wdc_nvme_ext_smart_log; - -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_PSCC = 200, /* Power State Change Count */ - SCAO_LPV = 494, /* Log page version */ - SCAO_LPG = 496, /* Log page GUID */ -} SMART_CLOUD_ATTRIBUTE_OFFSETS_V3; - -static __u8 scao_guid[WDC_C0_GUID_LENGTH] = { 0xC5, 0xAF, 0x10, 0x28, 0xEA, 0xBF, 0xF2, 0xA4, - 0x9C, 0x4F, 0x6F, 0x7C, 0xC9, 0x14, 0xD5, 0xAF }; - -typedef enum -{ - EOL_RBC = 76, /* Realloc Block Count */ - EOL_ECCR = 80, /* ECC Rate */ - EOL_WRA = 84, /* Write Amp */ - EOL_PLR = 88, /* Percent Life Remaining */ - EOL_RSVBC = 92, /* Reserved Block Count */ - EOL_PFC = 96, /* Program Fail Count */ - EOL_EFC = 100, /* Erase Fail Count */ - EOL_RRER = 108, /* Raw Read Error Rate */ -} EOL_LOG_PAGE_C0_OFFSETS; +}; + +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_PSCC = 200, /* Power State Change Count */ + SCAO_LPV = 494, /* Log page version */ + SCAO_LPG = 496, /* Log page GUID */ +}; + +static __u8 scao_guid[WDC_C0_GUID_LENGTH] = { + 0xC5, 0xAF, 0x10, 0x28, 0xEA, 0xBF, 0xF2, 0xA4, + 0x9C, 0x4F, 0x6F, 0x7C, 0xC9, 0x14, 0xD5, 0xAF +}; + +enum { + EOL_RBC = 76, /* Realloc Block Count */ + EOL_ECCR = 80, /* ECC Rate */ + EOL_WRA = 84, /* Write Amp */ + EOL_PLR = 88, /* Percent Life Remaining */ + EOL_RSVBC = 92, /* Reserved Block Count */ + EOL_PFC = 96, /* Program Fail Count */ + EOL_EFC = 100, /* Erase Fail Count */ + EOL_RRER = 108, /* Raw Read Error Rate */ +}; #define WDC_NVME_C6_GUID_LENGTH 16 #define WDC_NVME_GET_HW_REV_LOG_OPCODE 0xc6 #define WDC_NVME_HW_REV_LOG_PAGE_LEN 512 -typedef struct __attribute__((__packed__)) wdc_nvme_hw_rev_log -{ - __u8 hw_rev_gdr; /* 0 Global Device HW Revision */ - __u8 hw_rev_ar; /* 1 ASIC HW Revision */ - __u8 hw_rev_pbc_mc; /* 2 PCB Manufacturer Code */ - __u8 hw_rev_dram_mc; /* 3 DRAM Manufacturer Code */ - __u8 hw_rev_nand_mc; /* 4 NAND Manufacturer Code */ - __u8 hw_rev_pmic1_mc; /* 5 PMIC 1 Manufacturer Code */ - __u8 hw_rev_pmic2_mc; /* 6 PMIC 2 Manufacturer Code */ - __u8 hw_rev_c1_mc; /* 7 Other Component 1 Manf Code */ - __u8 hw_rev_c2_mc; /* 8 Other Component 2 Manf Code */ - __u8 hw_rev_c3_mc; /* 9 Other Component 3 Manf Code */ - __u8 hw_rev_c4_mc; /* 10 Other Component 4 Manf Code */ - __u8 hw_rev_c5_mc; /* 11 Other Component 5 Manf Code */ - __u8 hw_rev_c6_mc; /* 12 Other Component 6 Manf Code */ - __u8 hw_rev_c7_mc; /* 13 Other Component 7 Manf Code */ - __u8 hw_rev_c8_mc; /* 14 Other Component 8 Manf Code */ - __u8 hw_rev_c9_mc; /* 15 Other Component 9 Manf Code */ - __u8 hw_rev_rsrvd1[48]; /* 16 Reserved 48 bytes */ - __u8 hw_rev_dev_mdi[16]; /* 64 Device Manf Detailed Info */ - __u8 hw_rev_asic_di[16]; /* 80 ASIC Detailed Info */ - __u8 hw_rev_pcb_di[16]; /* 96 PCB Detailed Info */ - __u8 hw_rev_dram_di[16]; /* 112 DRAM Detailed Info */ - __u8 hw_rev_nand_di[16]; /* 128 NAND Detailed Info */ - __u8 hw_rev_pmic1_di[16]; /* 144 PMIC1 Detailed Info */ - __u8 hw_rev_pmic2_di[16]; /* 160 PMIC2 Detailed Info */ - __u8 hw_rev_c1_di[16]; /* 176 Component 1 Detailed Info */ - __u8 hw_rev_c2_di[16]; /* 192 Component 2 Detailed Info */ - __u8 hw_rev_c3_di[16]; /* 208 Component 3 Detailed Info */ - __u8 hw_rev_c4_di[16]; /* 224 Component 4 Detailed Info */ - __u8 hw_rev_c5_di[16]; /* 240 Component 5 Detailed Info */ - __u8 hw_rev_c6_di[16]; /* 256 Component 6 Detailed Info */ - __u8 hw_rev_c7_di[16]; /* 272 Component 7 Detailed Info */ - __u8 hw_rev_c8_di[16]; /* 288 Component 8 Detailed Info */ - __u8 hw_rev_c9_di[16]; /* 304 Component 9 Detailed Info */ - __u8 hw_rev_sn[32]; /* 320 Serial Number */ - __u8 hw_rev_rsrvd2[142]; /* 352 Reserved 143 bytes */ - __u16 hw_rev_version; /* 494 Log Page Version */ - __u8 hw_rev_guid[16]; /* 496 Log Page GUID */ -} wdc_nvme_hw_rev_log; - -static __u8 hw_rev_log_guid[WDC_NVME_C6_GUID_LENGTH] = { 0xAA, 0xB0, 0x05, 0xF5, 0x13, 0x5E, 0x48, 0x15, - 0xAB, 0x89, 0x05, 0xBA, 0x8B, 0xE2, 0xBF, 0x3C }; - -typedef struct __attribute__((__packed__)) _WDC_DE_VU_FILE_META_DATA -{ - __u8 fileName[WDC_DE_FILE_NAME_SIZE]; - __u16 fileID; - __u64 fileSize; -} WDC_DE_VU_FILE_META_DATA, *PWDC_DE_VU_FILE_META_DATA; - -typedef struct _WDC_DRIVE_ESSENTIALS -{ - WDC_DE_VU_FILE_META_DATA metaData; - WDC_DRIVE_ESSENTIAL_TYPE essentialType; -} WDC_DRIVE_ESSENTIALS; - -typedef struct _WDC_DE_VU_LOG_DIRECTORY -{ - WDC_DRIVE_ESSENTIALS *logEntry; /* Caller to allocate memory */ - __u32 maxNumLogEntries; /* Caller to input memory allocated */ - __u32 numOfValidLogEntries; /* API will output this value */ -} WDC_DE_VU_LOG_DIRECTORY,*PWDC_DE_VU_LOG_DIRECTORY; - -typedef struct _WDC_DE_CSA_FEATURE_ID_LIST -{ - NVME_FEATURE_IDENTIFIERS featureId; - __u8 featureName[WDC_DE_GENERIC_BUFFER_SIZE]; -} WDC_DE_CSA_FEATURE_ID_LIST; - -typedef struct tarfile_metadata { +struct __packed wdc_nvme_hw_rev_log { + __u8 hw_rev_gdr; /* 0 Global Device HW Revision */ + __u8 hw_rev_ar; /* 1 ASIC HW Revision */ + __u8 hw_rev_pbc_mc; /* 2 PCB Manufacturer Code */ + __u8 hw_rev_dram_mc; /* 3 DRAM Manufacturer Code */ + __u8 hw_rev_nand_mc; /* 4 NAND Manufacturer Code */ + __u8 hw_rev_pmic1_mc; /* 5 PMIC 1 Manufacturer Code */ + __u8 hw_rev_pmic2_mc; /* 6 PMIC 2 Manufacturer Code */ + __u8 hw_rev_c1_mc; /* 7 Other Component 1 Manf Code */ + __u8 hw_rev_c2_mc; /* 8 Other Component 2 Manf Code */ + __u8 hw_rev_c3_mc; /* 9 Other Component 3 Manf Code */ + __u8 hw_rev_c4_mc; /* 10 Other Component 4 Manf Code */ + __u8 hw_rev_c5_mc; /* 11 Other Component 5 Manf Code */ + __u8 hw_rev_c6_mc; /* 12 Other Component 6 Manf Code */ + __u8 hw_rev_c7_mc; /* 13 Other Component 7 Manf Code */ + __u8 hw_rev_c8_mc; /* 14 Other Component 8 Manf Code */ + __u8 hw_rev_c9_mc; /* 15 Other Component 9 Manf Code */ + __u8 hw_rev_rsrvd1[48]; /* 16 Reserved 48 bytes */ + __u8 hw_rev_dev_mdi[16]; /* 64 Device Manf Detailed Info */ + __u8 hw_rev_asic_di[16]; /* 80 ASIC Detailed Info */ + __u8 hw_rev_pcb_di[16]; /* 96 PCB Detailed Info */ + __u8 hw_rev_dram_di[16]; /* 112 DRAM Detailed Info */ + __u8 hw_rev_nand_di[16]; /* 128 NAND Detailed Info */ + __u8 hw_rev_pmic1_di[16]; /* 144 PMIC1 Detailed Info */ + __u8 hw_rev_pmic2_di[16]; /* 160 PMIC2 Detailed Info */ + __u8 hw_rev_c1_di[16]; /* 176 Component 1 Detailed Info */ + __u8 hw_rev_c2_di[16]; /* 192 Component 2 Detailed Info */ + __u8 hw_rev_c3_di[16]; /* 208 Component 3 Detailed Info */ + __u8 hw_rev_c4_di[16]; /* 224 Component 4 Detailed Info */ + __u8 hw_rev_c5_di[16]; /* 240 Component 5 Detailed Info */ + __u8 hw_rev_c6_di[16]; /* 256 Component 6 Detailed Info */ + __u8 hw_rev_c7_di[16]; /* 272 Component 7 Detailed Info */ + __u8 hw_rev_c8_di[16]; /* 288 Component 8 Detailed Info */ + __u8 hw_rev_c9_di[16]; /* 304 Component 9 Detailed Info */ + __u8 hw_rev_sn[32]; /* 320 Serial Number */ + __u8 hw_rev_rsrvd2[142]; /* 352 Reserved 143 bytes */ + __u16 hw_rev_version; /* 494 Log Page Version */ + __u8 hw_rev_guid[16]; /* 496 Log Page GUID */ +}; + +static __u8 hw_rev_log_guid[WDC_NVME_C6_GUID_LENGTH] = { + 0xAA, 0xB0, 0x05, 0xF5, 0x13, 0x5E, 0x48, 0x15, + 0xAB, 0x89, 0x05, 0xBA, 0x8B, 0xE2, 0xBF, 0x3C +}; + +struct __packed WDC_DE_VU_FILE_META_DATA { + __u8 fileName[WDC_DE_FILE_NAME_SIZE]; + __u16 fileID; + __u64 fileSize; +}; + +struct WDC_DRIVE_ESSENTIALS { + struct __packed WDC_DE_VU_FILE_META_DATA metaData; + enum WDC_DRIVE_ESSENTIAL_TYPE essentialType; +}; + +struct WDC_DE_VU_LOG_DIRECTORY { + struct WDC_DRIVE_ESSENTIALS *logEntry; /* Caller to allocate memory */ + __u32 maxNumLogEntries; /* Caller to input memory allocated */ + __u32 numOfValidLogEntries; /* API will output this value */ +}; + +struct WDC_DE_CSA_FEATURE_ID_LIST { + enum NVME_FEATURE_IDENTIFIERS featureId; + __u8 featureName[WDC_DE_GENERIC_BUFFER_SIZE]; +}; + +struct tarfile_metadata { char fileName[MAX_PATH_LEN]; int8_t bufferFolderPath[MAX_PATH_LEN]; char bufferFolderName[MAX_PATH_LEN]; @@ -750,107 +752,93 @@ typedef struct tarfile_metadata { char tarCmd[MAX_PATH_LEN+MAX_PATH_LEN]; char currDir[MAX_PATH_LEN]; UtilsTimeInfo timeInfo; - uint8_t* timeString[MAX_PATH_LEN]; -} tarfile_metadata; - -static WDC_DE_CSA_FEATURE_ID_LIST deFeatureIdList[] = -{ - {0x00 , "Dummy Placeholder"}, - {FID_ARBITRATION , "Arbitration"}, - {FID_POWER_MANAGEMENT , "PowerMgmnt"}, - {FID_LBA_RANGE_TYPE , "LbaRangeType"}, - {FID_TEMPERATURE_THRESHOLD , "TempThreshold"}, - {FID_ERROR_RECOVERY , "ErrorRecovery"}, - {FID_VOLATILE_WRITE_CACHE , "VolatileWriteCache"}, - {FID_NUMBER_OF_QUEUES , "NumOfQueues"}, - {FID_INTERRUPT_COALESCING , "InterruptCoalesing"}, - {FID_INTERRUPT_VECTOR_CONFIGURATION , "InterruptVectorConfig"}, - {FID_WRITE_ATOMICITY , "WriteAtomicity"}, - {FID_ASYNCHRONOUS_EVENT_CONFIGURATION , "AsynEventConfig"}, - {FID_AUTONOMOUS_POWER_STATE_TRANSITION , "AutonomousPowerState"}, + uint8_t *timeString[MAX_PATH_LEN]; }; -typedef enum _NVME_VU_DE_LOGPAGE_NAMES -{ - NVME_DE_LOGPAGE_E3 = 0x01, - NVME_DE_LOGPAGE_C0 = 0x02 -} NVME_VU_DE_LOGPAGE_NAMES; -typedef struct _NVME_VU_DE_LOGPAGE_LIST -{ - NVME_VU_DE_LOGPAGE_NAMES logPageName; +static struct WDC_DE_CSA_FEATURE_ID_LIST deFeatureIdList[] = { + {0x00, "Dummy Placeholder"}, + {FID_ARBITRATION, "Arbitration"}, + {FID_POWER_MANAGEMENT, "PowerMgmnt"}, + {FID_LBA_RANGE_TYPE, "LbaRangeType"}, + {FID_TEMPERATURE_THRESHOLD, "TempThreshold"}, + {FID_ERROR_RECOVERY, "ErrorRecovery"}, + {FID_VOLATILE_WRITE_CACHE, "VolatileWriteCache"}, + {FID_NUMBER_OF_QUEUES, "NumOfQueues"}, + {FID_INTERRUPT_COALESCING, "InterruptCoalesing"}, + {FID_INTERRUPT_VECTOR_CONFIGURATION, "InterruptVectorConfig"}, + {FID_WRITE_ATOMICITY, "WriteAtomicity"}, + {FID_ASYNCHRONOUS_EVENT_CONFIGURATION, "AsynEventConfig"}, + {FID_AUTONOMOUS_POWER_STATE_TRANSITION, "AutonomousPowerState"}, +}; + +enum NVME_VU_DE_LOGPAGE_NAMES { + NVME_DE_LOGPAGE_E3 = 0x01, + NVME_DE_LOGPAGE_C0 = 0x02 +}; + +struct NVME_VU_DE_LOGPAGE_LIST { + enum NVME_VU_DE_LOGPAGE_NAMES logPageName; __u32 logPageId; __u32 logPageLen; char logPageIdStr[5]; -} NVME_VU_DE_LOGPAGE_LIST, *PNVME_VU_DE_LOGPAGE_LIST; +}; -typedef struct _WDC_NVME_DE_VU_LOGPAGES -{ - NVME_VU_DE_LOGPAGE_NAMES vuLogPageReqd; - __u32 numOfVULogPages; -} WDC_NVME_DE_VU_LOGPAGES, *PWDC_NVME_DE_VU_LOGPAGES; +struct WDC_NVME_DE_VU_LOGPAGES { + enum NVME_VU_DE_LOGPAGE_NAMES vuLogPageReqd; + __u32 numOfVULogPages; +}; -static NVME_VU_DE_LOGPAGE_LIST deVULogPagesList[] = -{ - { NVME_DE_LOGPAGE_E3, 0xE3, 1072, "0xe3"}, - { NVME_DE_LOGPAGE_C0, 0xC0, 512, "0xc0"} +static struct NVME_VU_DE_LOGPAGE_LIST deVULogPagesList[] = { + { NVME_DE_LOGPAGE_E3, 0xE3, 1072, "0xe3"}, + { NVME_DE_LOGPAGE_C0, 0xC0, 512, "0xc0"} }; -static int wdc_get_serial_name(struct nvme_dev *dev, char *file, size_t len, - const char *suffix); -static int wdc_create_log_file(char *file, __u8 *drive_log_data, - __u32 drive_log_length); +static int wdc_get_serial_name(struct nvme_dev *dev, char *file, size_t len, const char *suffix); +static int wdc_create_log_file(char *file, __u8 *drive_log_data, __u32 drive_log_length); static int wdc_do_clear_dump(struct nvme_dev *dev, __u8 opcode, __u32 cdw12); -static int wdc_do_dump(struct nvme_dev *dev, __u32 opcode,__u32 data_len, - __u32 cdw12, char *file, __u32 xfer_size); +static int wdc_do_dump(struct nvme_dev *dev, __u32 opcode, __u32 data_len, __u32 cdw12, char *file, + __u32 xfer_size); static int wdc_do_crash_dump(struct nvme_dev *dev, char *file, int type); static int wdc_crash_dump(struct nvme_dev *dev, char *file, int type); static int wdc_get_crash_dump(int argc, char **argv, struct command *command, - struct plugin *plugin); + struct plugin *plugin); static int wdc_do_drive_log(struct nvme_dev *dev, char *file); -static int wdc_drive_log(int argc, char **argv, struct command *command, - struct plugin *plugin); -static const char* wdc_purge_mon_status_to_string(__u32 status); -static int wdc_purge(int argc, char **argv, - struct command *command, struct plugin *plugin); -static int wdc_purge_monitor(int argc, char **argv, - struct command *command, struct plugin *plugin); -static bool wdc_nvme_check_supported_log_page(nvme_root_t r, - struct nvme_dev *dev, __u8 log_id); +static int wdc_drive_log(int argc, char **argv, struct command *command, struct plugin *plugin); +static const char *wdc_purge_mon_status_to_string(__u32 status); +static int wdc_purge(int argc, char **argv, struct command *command, struct plugin *plugin); +static int wdc_purge_monitor(int argc, char **argv, struct command *command, struct plugin *plugin); +static bool wdc_nvme_check_supported_log_page(nvme_root_t r, struct nvme_dev *dev, __u8 log_id); static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct command *command, - struct plugin *plugin); + struct plugin *plugin); static int wdc_do_drive_essentials(nvme_root_t r, struct nvme_dev *dev, char *dir, char *key); static int wdc_drive_essentials(int argc, char **argv, struct command *command, - struct plugin *plugin); -static int wdc_drive_status(int argc, char **argv, struct command *command, - struct plugin *plugin); + struct plugin *plugin); +static int wdc_drive_status(int argc, char **argv, struct command *command, struct plugin *plugin); static int wdc_clear_assert_dump(int argc, char **argv, struct command *command, - struct plugin *plugin); -static int wdc_drive_resize(int argc, char **argv, - struct command *command, struct plugin *plugin); + struct plugin *plugin); +static int wdc_drive_resize(int argc, char **argv, struct command *command, struct plugin *plugin); static int wdc_do_drive_resize(struct nvme_dev *dev, uint64_t new_size); -static int wdc_namespace_resize(int argc, char **argv, - struct command *command, struct plugin *plugin); -static int wdc_do_namespace_resize(struct nvme_dev *dev, __u32 nsid, - __u32 op_option); -static int wdc_reason_identifier(int argc, char **argv, - struct command *command, struct plugin *plugin); +static int wdc_namespace_resize(int argc, char **argv, struct command *command, + struct plugin *plugin); +static int wdc_do_namespace_resize(struct nvme_dev *dev, __u32 nsid, __u32 op_option); +static int wdc_reason_identifier(int argc, char **argv, struct command *command, + struct plugin *plugin); static int wdc_do_get_reason_id(struct nvme_dev *dev, char *file, int log_id); static int wdc_save_reason_id(struct nvme_dev *dev, __u8 *rsn_ident, int size); static int wdc_clear_reason_id(struct nvme_dev *dev); static int wdc_log_page_directory(int argc, char **argv, struct command *command, - struct plugin *plugin); + struct plugin *plugin); static int wdc_do_drive_info(struct nvme_dev *dev, __u32 *result); -static int wdc_vs_drive_info(int argc, char **argv, struct command *command, - struct plugin *plugin); +static int wdc_vs_drive_info(int argc, char **argv, struct command *command, struct plugin *plugin); static int wdc_vs_temperature_stats(int argc, char **argv, struct command *command, - struct plugin *plugin); + struct plugin *plugin); static __u64 wdc_get_enc_drive_capabilities(nvme_root_t r, struct nvme_dev *dev); -static int wdc_enc_get_nic_log(struct nvme_dev *dev, __u8 log_id, - __u32 xfer_size, __u32 data_len, FILE *out); -static int wdc_enc_submit_move_data(struct nvme_dev *dev, char *cmd, int len, - int xfer_size, FILE *out, int data_id, int cdw14, int cdw15); -static bool get_dev_mgment_cbs_data(nvme_root_t r, struct nvme_dev *dev, - __u8 log_id, void **cbs_data); +static int wdc_enc_get_nic_log(struct nvme_dev *dev, __u8 log_id, __u32 xfer_size, __u32 data_len, + FILE *out); +static int wdc_enc_submit_move_data(struct nvme_dev *dev, char *cmd, int len, int xfer_size, + FILE *out, int data_id, int cdw14, int cdw15); +static bool get_dev_mgment_cbs_data(nvme_root_t r, struct nvme_dev *dev, __u8 log_id, + void **cbs_data); static __u32 wdc_get_fw_cust_id(nvme_root_t r, struct nvme_dev *dev); /* Drive log data size */ @@ -872,7 +860,7 @@ struct wdc_dui_log_section { }; /* DUI log header V2 */ -struct __attribute__((__packed__)) wdc_dui_log_section_v2 { +struct __packed wdc_dui_log_section_v2 { __le16 section_type; __le16 data_area_id; __le64 section_size; @@ -895,7 +883,7 @@ struct wdc_dui_log_hdr { __u8 log_data[40]; }; -struct __attribute__((__packed__)) wdc_dui_log_hdr_v2 { +struct __packed wdc_dui_log_hdr_v2 { __u8 telemetry_hdr[512]; __u8 hdr_version; __u8 product_id; @@ -905,7 +893,7 @@ struct __attribute__((__packed__)) wdc_dui_log_hdr_v2 { __u8 log_data[40]; }; -struct __attribute__((__packed__)) wdc_dui_log_hdr_v3 { +struct __packed wdc_dui_log_hdr_v3 { __u8 telemetry_hdr[512]; __u8 hdr_version; __u8 product_id; @@ -916,7 +904,7 @@ struct __attribute__((__packed__)) wdc_dui_log_hdr_v3 { __u8 log_data[40]; }; -struct __attribute__((__packed__)) wdc_dui_log_hdr_v4 { +struct __packed wdc_dui_log_hdr_v4 { __u8 telemetry_hdr[512]; __u8 hdr_version; __u8 product_id; @@ -928,17 +916,17 @@ struct __attribute__((__packed__)) wdc_dui_log_hdr_v4 { /* Purge monitor response */ struct wdc_nvme_purge_monitor_data { - __le16 rsvd1; - __le16 rsvd2; - __le16 first_erase_failure_cnt; - __le16 second_erase_failure_cnt; - __le16 rsvd3; - __le16 programm_failure_cnt; - __le32 rsvd4; - __le32 rsvd5; - __le32 entire_progress_total; - __le32 entire_progress_current; - __u8 rsvd6[14]; + __le16 rsvd1; + __le16 rsvd2; + __le16 first_erase_failure_cnt; + __le16 second_erase_failure_cnt; + __le16 rsvd3; + __le16 programm_failure_cnt; + __le32 rsvd4; + __le32 rsvd5; + __le32 entire_progress_total; + __le32 entire_progress_current; + __u8 rsvd6[14]; }; /* Additional Smart Log */ @@ -955,21 +943,21 @@ struct wdc_log_page_subpage_header { }; struct wdc_ssd_perf_stats { - __le64 hr_cmds; /* Host Read Commands */ - __le64 hr_blks; /* Host Read Blocks */ + __le64 hr_cmds; /* Host Read Commands */ + __le64 hr_blks; /* Host Read Blocks */ __le64 hr_ch_cmds; /* Host Read Cache Hit Commands */ __le64 hr_ch_blks; /* Host Read Cache Hit Blocks */ __le64 hr_st_cmds; /* Host Read Stalled Commands */ - __le64 hw_cmds; /* Host Write Commands */ - __le64 hw_blks; /* Host Write Blocks */ + __le64 hw_cmds; /* Host Write Commands */ + __le64 hw_blks; /* Host Write Blocks */ __le64 hw_os_cmds; /* Host Write Odd Start Commands */ __le64 hw_oe_cmds; /* Host Write Odd End Commands */ __le64 hw_st_cmds; /* Host Write Commands Stalled */ - __le64 nr_cmds; /* NAND Read Commands */ - __le64 nr_blks; /* NAND Read Blocks */ - __le64 nw_cmds; /* NAND Write Commands */ - __le64 nw_blks; /* NAND Write Blocks */ - __le64 nrbw; /* NAND Read Before Write */ + __le64 nr_cmds; /* NAND Read Commands */ + __le64 nr_blks; /* NAND Read Blocks */ + __le64 nw_cmds; /* NAND Write Commands */ + __le64 nw_blks; /* NAND Write Blocks */ + __le64 nrbw; /* NAND Read Before Write */ }; /* Additional C2 Log Page */ @@ -989,7 +977,7 @@ struct wdc_c2_cbs_data { __u8 data[]; }; -struct __attribute__((__packed__)) wdc_bd_ca_log_format { +struct __packed wdc_bd_ca_log_format { __u8 field_id; __u8 reserved1[2]; __u8 normalized_value; @@ -1005,26 +993,26 @@ struct __attribute__((__packed__)) wdc_bd_ca_log_format { #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 */ - __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 */ +struct __packed wdc_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 */ @@ -1042,56 +1030,56 @@ struct __attribute__((__packed__)) wdc_ssd_latency_monitor_log { __u8 log_page_guid[0x10]; /* 0x1F0 */ }; -struct __attribute__((__packed__)) wdc_ssd_ca_perf_stats { - __le64 nand_bytes_wr_lo; /* 0x00 - NAND Bytes Written lo */ - __le64 nand_bytes_wr_hi; /* 0x08 - NAND Bytes Written hi */ - __le64 nand_bytes_rd_lo; /* 0x10 - NAND Bytes Read lo */ - __le64 nand_bytes_rd_hi; /* 0x18 - NAND Bytes Read hi */ - __le64 nand_bad_block; /* 0x20 - NAND Bad Block Count */ - __le64 uncorr_read_count; /* 0x28 - Uncorrectable Read Count */ - __le64 ecc_error_count; /* 0x30 - Soft ECC Error Count */ - __le32 ssd_detect_count; /* 0x38 - SSD End to End Detection Count */ - __le32 ssd_correct_count; /* 0x3C - SSD End to End Correction Count */ - __u8 data_percent_used; /* 0x40 - System Data Percent Used */ - __le32 data_erase_max; /* 0x41 - User Data Erase Counts */ - __le32 data_erase_min; /* 0x45 - User Data Erase Counts */ - __le64 refresh_count; /* 0x49 - Refresh Count */ - __le64 program_fail; /* 0x51 - Program Fail Count */ - __le64 user_erase_fail; /* 0x59 - User Data Erase Fail Count */ - __le64 system_erase_fail; /* 0x61 - System Area Erase Fail Count */ - __u8 thermal_throttle_status; /* 0x69 - Thermal Throttling Status */ - __u8 thermal_throttle_count; /* 0x6A - Thermal Throttling Count */ - __le64 pcie_corr_error; /* 0x6B - pcie Correctable Error Count */ - __le32 incomplete_shutdown_count; /* 0x73 - Incomplete Shutdown Count */ - __u8 percent_free_blocks; /* 0x77 - Percent Free Blocks */ - __u8 rsvd[392]; /* 0x78 - Reserved bytes 120-511 */ +struct __packed wdc_ssd_ca_perf_stats { + __le64 nand_bytes_wr_lo; /* 0x00 - NAND Bytes Written lo */ + __le64 nand_bytes_wr_hi; /* 0x08 - NAND Bytes Written hi */ + __le64 nand_bytes_rd_lo; /* 0x10 - NAND Bytes Read lo */ + __le64 nand_bytes_rd_hi; /* 0x18 - NAND Bytes Read hi */ + __le64 nand_bad_block; /* 0x20 - NAND Bad Block Count */ + __le64 uncorr_read_count; /* 0x28 - Uncorrectable Read Count */ + __le64 ecc_error_count; /* 0x30 - Soft ECC Error Count */ + __le32 ssd_detect_count; /* 0x38 - SSD End to End Detection Count */ + __le32 ssd_correct_count; /* 0x3C - SSD End to End Correction Count */ + __u8 data_percent_used; /* 0x40 - System Data Percent Used */ + __le32 data_erase_max; /* 0x41 - User Data Erase Counts */ + __le32 data_erase_min; /* 0x45 - User Data Erase Counts */ + __le64 refresh_count; /* 0x49 - Refresh Count */ + __le64 program_fail; /* 0x51 - Program Fail Count */ + __le64 user_erase_fail; /* 0x59 - User Data Erase Fail Count */ + __le64 system_erase_fail; /* 0x61 - System Area Erase Fail Count */ + __u8 thermal_throttle_status; /* 0x69 - Thermal Throttling Status */ + __u8 thermal_throttle_count; /* 0x6A - Thermal Throttling Count */ + __le64 pcie_corr_error; /* 0x6B - pcie Correctable Error Count */ + __le32 incomplete_shutdown_count; /* 0x73 - Incomplete Shutdown Count */ + __u8 percent_free_blocks; /* 0x77 - Percent Free Blocks */ + __u8 rsvd[392]; /* 0x78 - Reserved bytes 120-511 */ }; -struct __attribute__((__packed__)) wdc_ssd_d0_smart_log { - __le32 smart_log_page_header; /* 0x00 - Smart Log Page Header */ - __le32 lifetime_realloc_erase_block_count; /* 0x04 - Lifetime reallocated erase block count */ - __le32 lifetime_power_on_hours; /* 0x08 - Lifetime power on hours */ - __le32 lifetime_uecc_count; /* 0x0C - Lifetime UECC count */ - __le32 lifetime_wrt_amp_factor; /* 0x10 - Lifetime write amplification factor */ - __le32 trailing_hr_wrt_amp_factor; /* 0x14 - Trailing hour write amplification factor */ - __le32 reserve_erase_block_count; /* 0x18 - Reserve erase block count */ - __le32 lifetime_program_fail_count; /* 0x1C - Lifetime program fail count */ - __le32 lifetime_block_erase_fail_count; /* 0x20 - Lifetime block erase fail count */ - __le32 lifetime_die_failure_count; /* 0x24 - Lifetime die failure count */ - __le32 lifetime_link_rate_downgrade_count; /* 0x28 - Lifetime link rate downgrade count */ - __le32 lifetime_clean_shutdown_count; /* 0x2C - Lifetime clean shutdown count on power loss */ - __le32 lifetime_unclean_shutdown_count; /* 0x30 - Lifetime unclean shutdowns on power loss */ - __le32 current_temp; /* 0x34 - Current temperature */ - __le32 max_recorded_temp; /* 0x38 - Max recorded temperature */ - __le32 lifetime_retired_block_count; /* 0x3C - Lifetime retired block count */ - __le32 lifetime_read_disturb_realloc_events; /* 0x40 - Lifetime read disturb reallocation events */ - __le64 lifetime_nand_writes; /* 0x44 - Lifetime NAND write Lpages */ - __le32 capacitor_health; /* 0x4C - Capacitor health */ - __le64 lifetime_user_writes; /* 0x50 - Lifetime user writes */ - __le64 lifetime_user_reads; /* 0x58 - Lifetime user reads */ - __le32 lifetime_thermal_throttle_act; /* 0x60 - Lifetime thermal throttle activations */ - __le32 percentage_pe_cycles_remaining; /* 0x64 - Percentage of P/E cycles remaining */ - __u8 rsvd[408]; /* 0x68 - 408 Reserved bytes */ +struct __packed wdc_ssd_d0_smart_log { + __le32 smart_log_page_header; /* 0x00 - Smart Log Page Header */ + __le32 lifetime_realloc_erase_block_count; /* 0x04 - Lifetime reallocated erase block count */ + __le32 lifetime_power_on_hours; /* 0x08 - Lifetime power on hours */ + __le32 lifetime_uecc_count; /* 0x0C - Lifetime UECC count */ + __le32 lifetime_wrt_amp_factor; /* 0x10 - Lifetime write amplification factor */ + __le32 trailing_hr_wrt_amp_factor; /* 0x14 - Trailing hour write amplification factor */ + __le32 reserve_erase_block_count; /* 0x18 - Reserve erase block count */ + __le32 lifetime_program_fail_count; /* 0x1C - Lifetime program fail count */ + __le32 lifetime_block_erase_fail_count; /* 0x20 - Lifetime block erase fail count */ + __le32 lifetime_die_failure_count; /* 0x24 - Lifetime die failure count */ + __le32 lifetime_link_rate_downgrade_count; /* 0x28 - Lifetime link rate downgrade count */ + __le32 lifetime_clean_shutdown_count; /* 0x2C - Lifetime clean shutdown count on power loss */ + __le32 lifetime_unclean_shutdown_count; /* 0x30 - Lifetime unclean shutdowns on power loss */ + __le32 current_temp; /* 0x34 - Current temperature */ + __le32 max_recorded_temp; /* 0x38 - Max recorded temperature */ + __le32 lifetime_retired_block_count; /* 0x3C - Lifetime retired block count */ + __le32 lifetime_read_disturb_realloc_events; /* 0x40 - Lifetime read disturb reallocation events */ + __le64 lifetime_nand_writes; /* 0x44 - Lifetime NAND write Lpages */ + __le32 capacitor_health; /* 0x4C - Capacitor health */ + __le64 lifetime_user_writes; /* 0x50 - Lifetime user writes */ + __le64 lifetime_user_reads; /* 0x58 - Lifetime user reads */ + __le32 lifetime_thermal_throttle_act; /* 0x60 - Lifetime thermal throttle activations */ + __le32 percentage_pe_cycles_remaining; /* 0x64 - Percentage of P/E cycles remaining */ + __u8 rsvd[408]; /* 0x68 - 408 Reserved bytes */ }; #define WDC_OCP_C1_GUID_LENGTH 16 @@ -1100,29 +1088,29 @@ struct __attribute__((__packed__)) wdc_ssd_d0_smart_log { #define WDC_ERROR_REC_LOG_VERSION1 0001 #define WDC_ERROR_REC_LOG_VERSION2 0002 -struct __attribute__((__packed__)) wdc_ocp_c1_error_recovery_log { - __le16 panic_reset_wait_time; /* 000 - Panic Reset Wait Time */ - __u8 panic_reset_action; /* 002 - Panic Reset Action */ - __u8 dev_recovery_action1; /* 003 - Device Recovery Action 1 */ - __le64 panic_id; /* 004 - Panic ID */ - __le32 dev_capabilities; /* 012 - Device Capabilities */ - __u8 vs_recovery_opc; /* 016 - Vendor Specific Recovery Opcode */ - __u8 rsvd1[3]; /* 017 - 3 Reserved Bytes */ - __le32 vs_cmd_cdw12; /* 020 - Vendor Specific Command CDW12 */ - __le32 vs_cmd_cdw13; /* 024 - Vendor Specific Command CDW13 */ - __u8 vs_cmd_to; /* 028 - Vendor Specific Command Timeout V2 */ - __u8 dev_recovery_action2; /* 029 - Device Recovery Action 2 V2 */ - __u8 dev_recovery_action2_to; /* 030 - Device Recovery Action 2 Timeout V2*/ - __u8 rsvd2[463]; /* 031 - 463 Reserved Bytes */ - __le16 log_page_version; /* 494 - Log Page Version */ - __u8 log_page_guid[WDC_OCP_C1_GUID_LENGTH]; /* 496 - Log Page GUID */ +struct __packed wdc_ocp_c1_error_recovery_log { + __le16 panic_reset_wait_time; /* 000 - Panic Reset Wait Time */ + __u8 panic_reset_action; /* 002 - Panic Reset Action */ + __u8 dev_recovery_action1; /* 003 - Device Recovery Action 1 */ + __le64 panic_id; /* 004 - Panic ID */ + __le32 dev_capabilities; /* 012 - Device Capabilities */ + __u8 vs_recovery_opc; /* 016 - Vendor Specific Recovery Opcode */ + __u8 rsvd1[3]; /* 017 - 3 Reserved Bytes */ + __le32 vs_cmd_cdw12; /* 020 - Vendor Specific Command CDW12 */ + __le32 vs_cmd_cdw13; /* 024 - Vendor Specific Command CDW13 */ + __u8 vs_cmd_to; /* 028 - Vendor Specific Command Timeout V2 */ + __u8 dev_recovery_action2; /* 029 - Device Recovery Action 2 V2 */ + __u8 dev_recovery_action2_to; /* 030 - Device Recovery Action 2 Timeout V2 */ + __u8 rsvd2[463]; /* 031 - 463 Reserved Bytes */ + __le16 log_page_version; /* 494 - Log Page Version */ + __u8 log_page_guid[WDC_OCP_C1_GUID_LENGTH]; /* 496 - Log Page GUID */ }; static __u8 wdc_ocp_c1_guid[WDC_OCP_C1_GUID_LENGTH] = { 0x44, 0xD9, 0x31, 0x21, 0xFE, 0x30, 0x34, 0xAE, 0xAB, 0x4D, 0xFD, 0x3D, 0xBA, 0x83, 0x19, 0x5A }; /* NAND Stats */ -struct __attribute__((__packed__)) wdc_nand_stats { +struct __packed wdc_nand_stats { __u8 nand_write_tlc[16]; __u8 nand_write_slc[16]; __le32 nand_prog_failure; @@ -1132,10 +1120,10 @@ struct __attribute__((__packed__)) wdc_nand_stats { __le64 e2e_error_counter; __le64 successful_ns_resize_event; __u8 rsvd[442]; - __u16 log_page_version; + __u16 log_page_version; }; -struct __attribute__((__packed__)) wdc_nand_stats_V3 { +struct __packed wdc_nand_stats_V3 { __u8 nand_write_tlc[16]; __u8 nand_write_slc[16]; __u8 bad_nand_block_count[8]; @@ -1144,8 +1132,8 @@ struct __attribute__((__packed__)) wdc_nand_stats_V3 { __u8 ssd_correction_counts[16]; __u8 percent_life_used; __le64 user_data_erase_counts[4]; - __u8 program_fail_count[8]; - __u8 erase_fail_count[8]; + __u8 program_fail_count[8]; + __u8 erase_fail_count[8]; __le64 correctable_error_count; __u8 percent_free_blocks_user; __le64 security_version_number; @@ -1160,53 +1148,52 @@ struct __attribute__((__packed__)) wdc_nand_stats_V3 { __le64 unaligned_IO; __u8 physical_media_units[16]; __u8 reserved[279]; - __u16 log_page_version; + __u16 log_page_version; }; -struct wdc_vs_pcie_stats -{ - __le64 unsupportedRequestErrorCount; - __le64 ecrcErrorStatusCount; - __le64 malformedTlpStatusCount; - __le64 receiverOverflowStatusCount; - __le64 unexpectedCmpltnStatusCount; - __le64 completeAbortStatusCount; - __le64 cmpltnTimoutStatusCount; - __le64 flowControlErrorStatusCount; - __le64 poisonedTlpStatusCount; - __le64 dLinkPrtclErrorStatusCount; - __le64 advsryNFatalErrStatusCount; - __le64 replayTimerToStatusCount; - __le64 replayNumRolloverStCount; - __le64 badDllpStatusCount; - __le64 badTlpStatusCount; - __le64 receiverErrStatusCount; - __u8 reserved1[384]; +struct wdc_vs_pcie_stats { + __le64 unsupportedRequestErrorCount; + __le64 ecrcErrorStatusCount; + __le64 malformedTlpStatusCount; + __le64 receiverOverflowStatusCount; + __le64 unexpectedCmpltnStatusCount; + __le64 completeAbortStatusCount; + __le64 cmpltnTimoutStatusCount; + __le64 flowControlErrorStatusCount; + __le64 poisonedTlpStatusCount; + __le64 dLinkPrtclErrorStatusCount; + __le64 advsryNFatalErrStatusCount; + __le64 replayTimerToStatusCount; + __le64 replayNumRolloverStCount; + __le64 badDllpStatusCount; + __le64 badTlpStatusCount; + __le64 receiverErrStatusCount; + __u8 reserved1[384]; }; struct wdc_fw_act_history_log_hdr { - __le32 eye_catcher; - __u8 version; - __u8 reserved1; - __u8 num_entries; - __u8 reserved2; - __le32 entry_size; - __le32 reserved3; + __le32 eye_catcher; + __u8 version; + __u8 reserved1; + __u8 num_entries; + __u8 reserved2; + __le32 entry_size; + __le32 reserved3; }; struct wdc_fw_act_history_log_entry { - __le32 entry_num; - __le32 power_cycle_count; - __le64 power_on_seconds; - __le64 previous_fw_version; - __le64 new_fw_version; - __u8 slot_number; - __u8 commit_action_type; - __le16 result; - __u8 reserved[12]; + __le32 entry_num; + __le32 power_cycle_count; + __le64 power_on_seconds; + __le64 previous_fw_version; + __le64 new_fw_version; + __u8 slot_number; + __u8 commit_action_type; + __le16 result; + __u8 reserved[12]; }; -struct __attribute__((__packed__)) wdc_fw_act_history_log_entry_c2 { +struct __packed wdc_fw_act_history_log_entry_c2 { __u8 entry_version_num; __u8 entry_len; __le16 reserved; @@ -1222,14 +1209,14 @@ struct __attribute__((__packed__)) wdc_fw_act_history_log_entry_c2 { __u8 reserved3[14]; }; -struct __attribute__((__packed__)) wdc_fw_act_history_log_format_c2 { +struct __packed wdc_fw_act_history_log_format_c2 { __u8 log_identifier; - __u8 reserved[3]; + __u8 reserved[3]; __le32 num_entries; - struct wdc_fw_act_history_log_entry_c2 entry[WDC_MAX_NUM_ACT_HIST_ENTRIES]; - __u8 reserved2[2790]; - __le16 log_page_version; - __u8 log_page_guid[WDC_C2_GUID_LENGTH]; + struct wdc_fw_act_history_log_entry_c2 entry[WDC_MAX_NUM_ACT_HIST_ENTRIES]; + __u8 reserved2[2790]; + __le16 log_page_version; + __u8 log_page_guid[WDC_C2_GUID_LENGTH]; }; #define WDC_OCP_C4_GUID_LENGTH 16 @@ -1238,24 +1225,26 @@ struct __attribute__((__packed__)) wdc_fw_act_history_log_format_c2 { #define WDC_DEV_CAP_LOG_VERSION 0001 #define WDC_OCP_C4_NUM_PS_DESCR 127 -struct __attribute__((__packed__)) wdc_ocp_C4_dev_cap_log { - __le16 num_pcie_ports; /* 0000 - Number of PCI Express Ports */ - __le16 oob_mgmt_support; /* 0002 - OOB Management Interfaces Supported */ - __le16 wrt_zeros_support; /* 0004 - Write Zeros Commmand Support */ - __le16 sanitize_support; /* 0006 - Sanitize Command Support */ - __le16 dsm_support; /* 0008 - Dataset Management Command Support */ - __le16 wrt_uncor_support; /* 0010 - Write Uncorrectable Command Support */ - __le16 fused_support; /* 0012 - Fused Operation Support */ - __le16 min_dssd_ps; /* 0014 - Minimum Valid DSSD Power State */ - __u8 rsvd1; /* 0016 - Reserved must be cleared to zero */ - __u8 dssd_ps_descr[WDC_OCP_C4_NUM_PS_DESCR];/* 0017 - DSSD Power State Descriptors */ - __u8 rsvd2[3934]; /* 0144 - Reserved must be cleared to zero */ - __le16 log_page_version; /* 4078 - Log Page Version */ - __u8 log_page_guid[WDC_OCP_C4_GUID_LENGTH]; /* 4080 - Log Page GUID */ +struct __packed wdc_ocp_C4_dev_cap_log { + __le16 num_pcie_ports; /* 0000 - Number of PCI Express Ports */ + __le16 oob_mgmt_support; /* 0002 - OOB Management Interfaces Supported */ + __le16 wrt_zeros_support; /* 0004 - Write Zeros Commmand Support */ + __le16 sanitize_support; /* 0006 - Sanitize Command Support */ + __le16 dsm_support; /* 0008 - Dataset Management Command Support */ + __le16 wrt_uncor_support; /* 0010 - Write Uncorrectable Command Support */ + __le16 fused_support; /* 0012 - Fused Operation Support */ + __le16 min_dssd_ps; /* 0014 - Minimum Valid DSSD Power State */ + __u8 rsvd1; /* 0016 - Reserved must be cleared to zero */ + __u8 dssd_ps_descr[WDC_OCP_C4_NUM_PS_DESCR];/* 0017 - DSSD Power State Descriptors */ + __u8 rsvd2[3934]; /* 0144 - Reserved must be cleared to zero */ + __le16 log_page_version; /* 4078 - Log Page Version */ + __u8 log_page_guid[WDC_OCP_C4_GUID_LENGTH]; /* 4080 - Log Page GUID */ }; -static __u8 wdc_ocp_c4_guid[WDC_OCP_C4_GUID_LENGTH] = { 0x97, 0x42, 0x05, 0x0D, 0xD1, 0xE1, 0xC9, 0x98, - 0x5D, 0x49, 0x58, 0x4B, 0x91, 0x3C, 0x05, 0xB7 }; +static __u8 wdc_ocp_c4_guid[WDC_OCP_C4_GUID_LENGTH] = { + 0x97, 0x42, 0x05, 0x0D, 0xD1, 0xE1, 0xC9, 0x98, + 0x5D, 0x49, 0x58, 0x4B, 0x91, 0x3C, 0x05, 0xB7 +}; #define WDC_OCP_C5_GUID_LENGTH 16 #define WDC_UNSUPPORTED_REQS_LOG_BUF_LEN 4096 @@ -1263,13 +1252,13 @@ static __u8 wdc_ocp_c4_guid[WDC_OCP_C4_GUID_LENGTH] = { 0x97, 0x42, 0x05, 0x0 #define WDC_UNSUPPORTED_REQS_LOG_VERSION 0001 #define WDC_NUM_UNSUPPORTED_REQ_ENTRIES 253 -struct __attribute__((__packed__)) wdc_ocp_C5_unsupported_reqs { - __le16 unsupported_count; /* 0000 - Number of Unsupported Requirement IDs */ - __u8 rsvd1[14]; /* 0002 - Reserved must be cleared to zero */ - __u8 unsupported_req_list[WDC_NUM_UNSUPPORTED_REQ_ENTRIES][16]; /* 0016 - Unsupported Requirements List */ - __u8 rsvd2[14]; /* 4064 - Reserved must be cleared to zero */ - __le16 log_page_version; /* 4078 - Log Page Version */ - __u8 log_page_guid[WDC_OCP_C5_GUID_LENGTH]; /* 4080 - Log Page GUID */ +struct __packed wdc_ocp_C5_unsupported_reqs { + __le16 unsupported_count; /* 0000 - Number of Unsupported Requirement IDs */ + __u8 rsvd1[14]; /* 0002 - Reserved must be cleared to zero */ + __u8 unsupported_req_list[WDC_NUM_UNSUPPORTED_REQ_ENTRIES][16]; /* 0016 - Unsupported Requirements List */ + __u8 rsvd2[14]; /* 4064 - Reserved must be cleared to zero */ + __le16 log_page_version; /* 4078 - Log Page Version */ + __u8 log_page_guid[WDC_OCP_C5_GUID_LENGTH]; /* 4080 - Log Page GUID */ }; static __u8 wdc_ocp_c5_guid[WDC_OCP_C5_GUID_LENGTH] = { 0x2F, 0x72, 0x9C, 0x0E, 0x99, 0x23, 0x2C, 0xBB, @@ -1322,7 +1311,7 @@ static int wdc_get_pci_ids(nvme_root_t r, struct nvme_dev *dev, fd = open(vid, O_RDONLY); if (fd < 0) { - fprintf(stderr, "ERROR : WDC : %s : Open vendor file failed\n", __func__); + fprintf(stderr, "ERROR: WDC: %s : Open vendor file failed\n", __func__); return -1; } @@ -1342,7 +1331,7 @@ static int wdc_get_pci_ids(nvme_root_t r, struct nvme_dev *dev, fd = open(did, O_RDONLY); if (fd < 0) { - fprintf(stderr, "ERROR : WDC : %s : Open device file failed\n", __func__); + fprintf(stderr, "ERROR: WDC: %s : Open device file failed\n", __func__); return -1; } @@ -1369,8 +1358,7 @@ static int wdc_get_vendor_id(struct nvme_dev *dev, uint32_t *vendor_id) memset(&ctrl, 0, sizeof(struct nvme_id_ctrl)); ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); if (ret) { - fprintf(stderr, "ERROR : WDC : nvme_identify_ctrl() failed " - "0x%x\n", ret); + fprintf(stderr, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x\n", ret); return -1; } @@ -1381,27 +1369,27 @@ static int wdc_get_vendor_id(struct nvme_dev *dev, uint32_t *vendor_id) static bool wdc_check_power_of_2(int num) { - return (num && ( !(num & (num-1)))); + return num && (!(num & (num-1))); } static int wdc_get_model_number(struct nvme_dev *dev, char *model) { - int ret,i; + int ret, i; struct nvme_id_ctrl ctrl; memset(&ctrl, 0, sizeof(struct nvme_id_ctrl)); ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); if (ret) { - fprintf(stderr, "ERROR : WDC : nvme_identify_ctrl() failed " - "0x%x\n", ret); + fprintf(stderr, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x\n", ret); return -1; } - memcpy(model,ctrl.mn,NVME_ID_CTRL_MODEL_NUMBER_SIZE); + memcpy(model, ctrl.mn, NVME_ID_CTRL_MODEL_NUMBER_SIZE); /* get rid of the padded spaces */ i = NVME_ID_CTRL_MODEL_NUMBER_SIZE-1; - while (model[i] == ' ') i--; - model[i+1]=0; + while (model[i] == ' ') + i--; + model[i+1] = 0; return ret; } @@ -1426,8 +1414,9 @@ static bool wdc_check_device(nvme_root_t r, struct nvme_dev *dev) read_vendor_id == WDC_NVME_SNDK_VID) supported = true; else - fprintf(stderr, "ERROR : WDC: unsupported WDC device, Vendor ID = 0x%x, Device ID = 0x%x\n", - read_vendor_id, read_device_id); + fprintf(stderr, + "ERROR: WDC: unsupported WDC device, Vendor ID = 0x%x, Device ID = 0x%x\n", + read_vendor_id, read_device_id); return supported; } @@ -1444,10 +1433,10 @@ static bool wdc_enc_check_model(struct nvme_dev *dev) supported = false; model[NVME_ID_CTRL_MODEL_NUMBER_SIZE] = 0; /* forced termination */ - if (strstr(model,WDC_OPENFLEX_MI_DEVICE_MODEL) != NULL) + if (strstr(model, WDC_OPENFLEX_MI_DEVICE_MODEL)) supported = true; else - fprintf(stderr, "ERROR : WDC: unsupported WDC enclosure, Model = %s\n",model); + fprintf(stderr, "ERROR: WDC: unsupported WDC enclosure, Model = %s\n", model); return supported; } @@ -1460,15 +1449,13 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev) __u32 cust_id; ret = wdc_get_pci_ids(r, dev, &read_device_id, &read_vendor_id); - if (ret < 0) - { + if (ret < 0) { if (wdc_get_vendor_id(dev, &read_vendor_id) < 0) return capabilities; } /* below check condition is added due in NVMeOF device we dont have device_id so we need to use only vendor_id*/ - if (read_device_id == -1 && read_vendor_id != -1) - { + if (read_device_id == -1 && read_vendor_id != -1) { capabilities = wdc_get_enc_drive_capabilities(r, dev); return capabilities; } @@ -1503,7 +1490,7 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev) case WDC_NVME_VID_2: switch (read_device_id) { case WDC_NVME_SN630_DEV_ID: - /* FALLTHRU */ + fallthrough; case WDC_NVME_SN630_DEV_ID_1: capabilities = (WDC_DRIVE_CAP_CAP_DIAG | WDC_DRIVE_CAP_INTERNAL_LOG | WDC_DRIVE_CAP_DRIVE_STATUS | WDC_DRIVE_CAP_CLEAR_ASSERT | @@ -1515,25 +1502,24 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev) /* verify the 0xD0 log page is supported */ if (wdc_nvme_check_supported_log_page(r, dev, - WDC_NVME_GET_VU_SMART_LOG_OPCODE) - == true) + WDC_NVME_GET_VU_SMART_LOG_OPCODE)) capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE; break; case WDC_NVME_SN640_DEV_ID: - /* FALLTHRU */ + fallthrough; case WDC_NVME_SN640_DEV_ID_1: - /* FALLTHRU */ + fallthrough; case WDC_NVME_SN640_DEV_ID_2: - /* FALLTHRU */ - case WDC_NVME_SN640_DEV_ID_3: - /* FALLTHRU */ - case WDC_NVME_SN560_DEV_ID_1: - /* FALLTHRU */ - case WDC_NVME_SN560_DEV_ID_2: - /* FALLTHRU */ - case WDC_NVME_SN560_DEV_ID_3: - /* FALLTHRU */ - case WDC_NVME_SN660_DEV_ID: + fallthrough; + case WDC_NVME_SN640_DEV_ID_3: + fallthrough; + case WDC_NVME_SN560_DEV_ID_1: + fallthrough; + case WDC_NVME_SN560_DEV_ID_2: + fallthrough; + case WDC_NVME_SN560_DEV_ID_3: + fallthrough; + case WDC_NVME_SN660_DEV_ID: /* verify the 0xC0 log page is supported */ if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID) @@ -1579,7 +1565,7 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev) cust_id = wdc_get_fw_cust_id(r, dev); if (cust_id == WDC_INVALID_CUSTOMER_ID) { - fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__); + fprintf(stderr, "%s: ERROR: WDC: invalid customer id\n", __func__); return -1; } @@ -1590,27 +1576,26 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev) else capabilities |= (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY | WDC_DRIVE_CAP_CLEAR_PCIE); - break; + break; case WDC_NVME_SN840_DEV_ID: - /* FALLTHRU */ + fallthrough; case WDC_NVME_SN840_DEV_ID_1: - /* FALLTHRU */ + fallthrough; case WDC_NVME_SN860_DEV_ID: /* verify the 0xC0 log page is supported */ if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE)) capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE; - /* FALLTHRU */ + fallthrough; case WDC_NVME_ZN540_DEV_ID: - /* FALLTHRU */ - case WDC_NVME_SN540_DEV_ID: - /* FALLTHRU */ + fallthrough; + case WDC_NVME_SN540_DEV_ID: capabilities |= (WDC_DRIVE_CAP_CAP_DIAG | WDC_DRIVE_CAP_INTERNAL_LOG | WDC_DRIVE_CAP_DRIVE_STATUS | WDC_DRIVE_CAP_CLEAR_ASSERT | WDC_DRIVE_CAP_RESIZE | WDC_DRIVE_CAP_CLEAR_PCIE | WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY | WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY | WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG | WDC_DRIVE_CAP_REASON_ID | - WDC_DRIVE_CAP_LOG_PAGE_DIR ); + WDC_DRIVE_CAP_LOG_PAGE_DIR); /* verify the 0xCA log page is supported */ if (wdc_nvme_check_supported_log_page(r, dev, @@ -1623,11 +1608,17 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev) capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE; break; case WDC_NVME_SN650_DEV_ID: + fallthrough; case WDC_NVME_SN650_DEV_ID_1: + fallthrough; case WDC_NVME_SN650_DEV_ID_2: + fallthrough; case WDC_NVME_SN650_DEV_ID_3: + fallthrough; case WDC_NVME_SN650_DEV_ID_4: + fallthrough; case WDC_NVME_SN655_DEV_ID: + fallthrough; case WDC_NVME_SN550_DEV_ID: /* verify the 0xC0 log page is supported */ if (wdc_nvme_check_supported_log_page(r, dev, @@ -1651,23 +1642,28 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev) capabilities |= WDC_DRIVE_CAP_OCP_C5_LOG_PAGE; capabilities |= (WDC_DRIVE_CAP_CAP_DIAG | WDC_DRIVE_CAP_INTERNAL_LOG | - WDC_DRIVE_CAP_DRIVE_STATUS | WDC_DRIVE_CAP_CLEAR_ASSERT | - WDC_DRIVE_CAP_RESIZE | WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY | - WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG | WDC_DRIVE_CAP_REASON_ID | - WDC_DRIVE_CAP_LOG_PAGE_DIR); + WDC_DRIVE_CAP_DRIVE_STATUS | WDC_DRIVE_CAP_CLEAR_ASSERT | + WDC_DRIVE_CAP_RESIZE | WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY | + WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG | + WDC_DRIVE_CAP_REASON_ID | WDC_DRIVE_CAP_LOG_PAGE_DIR); cust_id = wdc_get_fw_cust_id(r, dev); if (cust_id == WDC_INVALID_CUSTOMER_ID) { - fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__); + fprintf(stderr, "%s: ERROR: WDC: invalid customer id\n", __func__); return -1; } - if ((cust_id == WDC_CUSTOMER_ID_0x1004) || (cust_id == WDC_CUSTOMER_ID_0x1008) || - (cust_id == WDC_CUSTOMER_ID_0x1005) || (cust_id == WDC_CUSTOMER_ID_0x1304)) - capabilities |= (WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY | WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE | - WDC_DRIVE_CAP_INFO | WDC_DRIVE_CAP_CLOUD_SSD_VERSION); + if ((cust_id == WDC_CUSTOMER_ID_0x1004) || + (cust_id == WDC_CUSTOMER_ID_0x1008) || + (cust_id == WDC_CUSTOMER_ID_0x1005) || + (cust_id == WDC_CUSTOMER_ID_0x1304)) + capabilities |= (WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY | + WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE | + WDC_DRIVE_CAP_INFO | + WDC_DRIVE_CAP_CLOUD_SSD_VERSION); else - capabilities |= (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY | WDC_DRIVE_CAP_CLEAR_PCIE); + capabilities |= (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY | + WDC_DRIVE_CAP_CLEAR_PCIE); break; default: @@ -1680,41 +1676,54 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev) capabilities = WDC_DRIVE_CAP_DRIVE_ESSENTIALS; break; case WDC_NVME_SN520_DEV_ID: - /* FALLTHRU */ + fallthrough; case WDC_NVME_SN520_DEV_ID_1: - /* FALLTHRU */ + fallthrough; case WDC_NVME_SN520_DEV_ID_2: + fallthrough; case WDC_NVME_SN530_DEV_ID: + fallthrough; + case WDC_NVME_SN530_DEV_ID_1: + fallthrough; case WDC_NVME_SN810_DEV_ID: capabilities = WDC_DRIVE_CAP_DUI_DATA; break; case WDC_NVME_SN820CL_DEV_ID: - capabilities = WDC_DRIVE_CAP_DUI_DATA | WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION | - WDC_DRIVE_CAP_CLOUD_LOG_PAGE | WDC_DRIVE_CAP_C0_LOG_PAGE | - WDC_DRIVE_CAP_HW_REV_LOG_PAGE | WDC_DRIVE_CAP_INFO | - WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE | WDC_DRIVE_CAP_NAND_STATS | - WDC_DRIVE_CAP_DEVICE_WAF | WDC_DRIVE_CAP_TEMP_STATS; + capabilities = WDC_DRIVE_CAP_DUI_DATA | + WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION | + WDC_DRIVE_CAP_CLOUD_LOG_PAGE | WDC_DRIVE_CAP_C0_LOG_PAGE | + WDC_DRIVE_CAP_HW_REV_LOG_PAGE | WDC_DRIVE_CAP_INFO | + WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE | WDC_DRIVE_CAP_NAND_STATS | + WDC_DRIVE_CAP_DEVICE_WAF | WDC_DRIVE_CAP_TEMP_STATS; break; case WDC_NVME_SN720_DEV_ID: - capabilities = WDC_DRIVE_CAP_DUI_DATA | WDC_DRIVE_CAP_NAND_STATS | WDC_DRIVE_CAP_NS_RESIZE; + capabilities = WDC_DRIVE_CAP_DUI_DATA | WDC_DRIVE_CAP_NAND_STATS | + WDC_DRIVE_CAP_NS_RESIZE; break; case WDC_NVME_SN730A_DEV_ID: - capabilities = WDC_DRIVE_CAP_DUI | WDC_DRIVE_CAP_NAND_STATS | WDC_DRIVE_CAP_INFO | - WDC_DRIVE_CAP_TEMP_STATS | WDC_DRIVE_CAP_VUC_CLEAR_PCIE | WDC_DRIVE_CAP_PCIE_STATS; + capabilities = WDC_DRIVE_CAP_DUI | WDC_DRIVE_CAP_NAND_STATS | + WDC_DRIVE_CAP_INFO | WDC_DRIVE_CAP_TEMP_STATS | + WDC_DRIVE_CAP_VUC_CLEAR_PCIE | WDC_DRIVE_CAP_PCIE_STATS; break; - case WDC_NVME_SN740_DEV_ID: - case WDC_NVME_SN740_DEV_ID_1: - case WDC_NVME_SN740_DEV_ID_2: - case WDC_NVME_SN740_DEV_ID_3: + case WDC_NVME_SN740_DEV_ID: + fallthrough; + case WDC_NVME_SN740_DEV_ID_1: + fallthrough; + case WDC_NVME_SN740_DEV_ID_2: + fallthrough; + case WDC_NVME_SN740_DEV_ID_3: + fallthrough; case WDC_NVME_SN340_DEV_ID: capabilities = WDC_DRIVE_CAP_DUI; break; case WDC_NVME_ZN350_DEV_ID: - /* FALLTHRU */ + fallthrough; case WDC_NVME_ZN350_DEV_ID_1: - capabilities = WDC_DRIVE_CAP_DUI_DATA | WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE | WDC_DRIVE_CAP_C0_LOG_PAGE | - WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY | WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C2 | - WDC_DRIVE_CAP_INFO | WDC_DRIVE_CAP_CLOUD_SSD_VERSION | WDC_DRIVE_CAP_LOG_PAGE_DIR; + capabilities = WDC_DRIVE_CAP_DUI_DATA | WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE | + WDC_DRIVE_CAP_C0_LOG_PAGE | + WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY | + WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C2 | WDC_DRIVE_CAP_INFO | + WDC_DRIVE_CAP_CLOUD_SSD_VERSION | WDC_DRIVE_CAP_LOG_PAGE_DIR; break; default: capabilities = 0; @@ -1740,57 +1749,57 @@ static __u64 wdc_get_enc_drive_capabilities(nvme_root_t r, return capabilities; switch (read_vendor_id) { - case WDC_NVME_VID: - capabilities = (WDC_DRIVE_CAP_CAP_DIAG | WDC_DRIVE_CAP_INTERNAL_LOG | WDC_DRIVE_CAP_CLEAR_PCIE | - WDC_DRIVE_CAP_DRIVE_LOG | WDC_DRIVE_CAP_CRASH_DUMP | WDC_DRIVE_CAP_PFAIL_DUMP); + case WDC_NVME_VID: + capabilities = (WDC_DRIVE_CAP_CAP_DIAG | WDC_DRIVE_CAP_INTERNAL_LOG | WDC_DRIVE_CAP_CLEAR_PCIE | + WDC_DRIVE_CAP_DRIVE_LOG | WDC_DRIVE_CAP_CRASH_DUMP | WDC_DRIVE_CAP_PFAIL_DUMP); - /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) - capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; + /* verify the 0xCA log page is supported */ + if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) + capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; - /* verify the 0xC1 log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_ADD_LOG_OPCODE) == true) - capabilities |= WDC_DRIVE_CAP_C1_LOG_PAGE; - break; - case WDC_NVME_VID_2: - capabilities = (WDC_DRIVE_CAP_CAP_DIAG | WDC_DRIVE_CAP_INTERNAL_LOG | - WDC_DRIVE_CAP_DRIVE_STATUS | WDC_DRIVE_CAP_CLEAR_ASSERT | - WDC_DRIVE_CAP_RESIZE); + /* verify the 0xC1 log page is supported */ + if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_ADD_LOG_OPCODE) == true) + capabilities |= WDC_DRIVE_CAP_C1_LOG_PAGE; + break; + case WDC_NVME_VID_2: + capabilities = (WDC_DRIVE_CAP_CAP_DIAG | WDC_DRIVE_CAP_INTERNAL_LOG | + WDC_DRIVE_CAP_DRIVE_STATUS | WDC_DRIVE_CAP_CLEAR_ASSERT | + WDC_DRIVE_CAP_RESIZE); - /* verify the 0xC3 log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, WDC_LATENCY_MON_LOG_ID) == true) - capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE; + /* verify the 0xC3 log page is supported */ + if (wdc_nvme_check_supported_log_page(r, dev, WDC_LATENCY_MON_LOG_ID) == true) + capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE; - /* verify the 0xCB log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID) == true) - capabilities |= WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY; + /* verify the 0xCB log page is supported */ + if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID) == true) + capabilities |= WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY; - /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) - capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; + /* verify the 0xCA log page is supported */ + if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) + capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; - /* verify the 0xD0 log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true) - capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE; + /* verify the 0xD0 log page is supported */ + if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true) + capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE; - cust_id = wdc_get_fw_cust_id(r, dev); - if (cust_id == WDC_INVALID_CUSTOMER_ID) { - fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__); - return -1; - } + cust_id = wdc_get_fw_cust_id(r, dev); + if (cust_id == WDC_INVALID_CUSTOMER_ID) { + fprintf(stderr, "%s: ERROR: WDC: invalid customer id\n", __func__); + return -1; + } - if ((cust_id == WDC_CUSTOMER_ID_0x1004) || (cust_id == WDC_CUSTOMER_ID_0x1008) || - (cust_id == WDC_CUSTOMER_ID_0x1005) || (cust_id == WDC_CUSTOMER_ID_0x1304)) - capabilities |= (WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY | WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE); - else - capabilities |= (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY | WDC_DRIVE_CAP_CLEAR_PCIE); + if ((cust_id == WDC_CUSTOMER_ID_0x1004) || (cust_id == WDC_CUSTOMER_ID_0x1008) || + (cust_id == WDC_CUSTOMER_ID_0x1005) || (cust_id == WDC_CUSTOMER_ID_0x1304)) + capabilities |= (WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY | WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE); + else + capabilities |= (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY | WDC_DRIVE_CAP_CLEAR_PCIE); - break; - case WDC_NVME_SNDK_VID: - capabilities = WDC_DRIVE_CAP_DRIVE_ESSENTIALS; - break; - default: - capabilities = 0; + break; + case WDC_NVME_SNDK_VID: + capabilities = WDC_DRIVE_CAP_DRIVE_ESSENTIALS; + break; + default: + capabilities = 0; } return capabilities; @@ -1804,16 +1813,15 @@ static int wdc_get_serial_name(struct nvme_dev *dev, char *file, size_t len, int res_len = 0; char orig[PATH_MAX] = {0}; struct nvme_id_ctrl ctrl; - int ctrl_sn_len = sizeof (ctrl.sn); + int ctrl_sn_len = sizeof(ctrl.sn); - i = sizeof (ctrl.sn) - 1; + i = sizeof(ctrl.sn) - 1; strncpy(orig, file, PATH_MAX - 1); memset(file, 0, len); - memset(&ctrl, 0, sizeof (struct nvme_id_ctrl)); + memset(&ctrl, 0, sizeof(struct nvme_id_ctrl)); ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); if (ret) { - fprintf(stderr, "ERROR : WDC : nvme_identify_ctrl() failed " - "0x%x\n", ret); + fprintf(stderr, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x\n", ret); return -1; } /* Remove trailing spaces from the name */ @@ -1821,14 +1829,13 @@ static int wdc_get_serial_name(struct nvme_dev *dev, char *file, size_t len, ctrl.sn[i] = '\0'; i--; } - if (ctrl.sn[sizeof (ctrl.sn) - 1] == '\0') { + if (ctrl.sn[sizeof(ctrl.sn) - 1] == '\0') ctrl_sn_len = strlen(ctrl.sn); - } res_len = snprintf(file, len, "%s%.*s%s", orig, ctrl_sn_len, ctrl.sn, suffix); if (len <= res_len) { - fprintf(stderr, "ERROR : WDC : cannot format serial number due to data " - "of unexpected length\n"); + fprintf(stderr, + "ERROR: WDC: cannot format serial number due to data of unexpected length\n"); return -1; } @@ -1841,21 +1848,21 @@ static int wdc_create_log_file(char *file, __u8 *drive_log_data, int fd; int ret; - if (drive_log_length == 0) { - fprintf(stderr, "ERROR : WDC: invalid log file length\n"); + if (!drive_log_length) { + fprintf(stderr, "ERROR: WDC: invalid log file length\n"); return -1; } fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) { - fprintf(stderr, "ERROR : WDC: open : %s\n", strerror(errno)); + fprintf(stderr, "ERROR: WDC: open: %s\n", strerror(errno)); return -1; } while (drive_log_length > WRITE_SIZE) { ret = write(fd, drive_log_data, WRITE_SIZE); if (ret < 0) { - fprintf (stderr, "ERROR : WDC: write : %s\n", strerror(errno)); + fprintf(stderr, "ERROR: WDC: write: %s\n", strerror(errno)); close(fd); return -1; } @@ -1865,13 +1872,13 @@ static int wdc_create_log_file(char *file, __u8 *drive_log_data, ret = write(fd, drive_log_data, drive_log_length); if (ret < 0) { - fprintf(stderr, "ERROR : WDC : write : %s\n", strerror(errno)); + fprintf(stderr, "ERROR: WDC: write: %s\n", strerror(errno)); close(fd); return -1; } if (fsync(fd) < 0) { - fprintf(stderr, "ERROR : WDC : fsync : %s\n", strerror(errno)); + fprintf(stderr, "ERROR: WDC: fsync: %s\n", strerror(errno)); close(fd); return -1; } @@ -1879,104 +1886,107 @@ static int wdc_create_log_file(char *file, __u8 *drive_log_data, return 0; } -bool wdc_get_dev_mng_log_entry(__u32 log_length, - __u32 entry_id, - struct wdc_c2_log_page_header* p_log_hdr, - struct wdc_c2_log_subpage_header **p_p_found_log_entry) -{ - __u32 remaining_len = 0; - __u32 log_entry_hdr_size = sizeof(struct wdc_c2_log_subpage_header) - 1; - __u32 log_entry_size = 0; - __u32 size = 0; - bool valid_log; - __u32 current_data_offset = 0; - struct wdc_c2_log_subpage_header *p_next_log_entry = NULL; - - if (*p_p_found_log_entry == NULL) { - fprintf(stderr, "ERROR : WDC - wdc_get_dev_mng_log_entry: No ppLogEntry pointer.\n"); - return false; - } - - *p_p_found_log_entry = NULL; - - /* Ensure log data is large enough for common header */ - if (log_length < sizeof(struct wdc_c2_log_page_header)) { - fprintf(stderr, "ERROR : WDC - wdc_get_dev_mng_log_entry: \ - Buffer is not large enough for the common header. BufSize: 0x%x HdrSize: %"PRIxPTR"\n", - log_length, sizeof(struct wdc_c2_log_page_header)); - return false; - } - - /* Get pointer to first log Entry */ - size = sizeof(struct wdc_c2_log_page_header); - current_data_offset = size; - p_next_log_entry = (struct wdc_c2_log_subpage_header *)((__u8*)p_log_hdr + current_data_offset); - remaining_len = log_length - size; - valid_log = false; - - /* Walk the entire structure. Perform a sanity check to make sure this is a - standard version of the structure. This means making sure each entry looks - valid. But allow for the data to overflow the allocated - buffer (we don't want a false negative because of a FW formatting error) */ - - /* Proceed only if there is at least enough data to read an entry header */ - while (remaining_len >= log_entry_hdr_size) { - /* Get size of the next entry */ - log_entry_size = p_next_log_entry->length; - - /* If log entry size is 0 or the log entry goes past the end - of the data, we must be at the end of the data */ - if ((log_entry_size == 0) || - (log_entry_size > remaining_len)) { - fprintf(stderr, "ERROR : WDC: wdc_get_dev_mng_log_entry: \ - Detected unaligned end of the data. Data Offset: 0x%x \ - Entry Size: 0x%x, Remaining Log Length: 0x%x Entry Id: 0x%x\n", - current_data_offset, log_entry_size, remaining_len, p_next_log_entry->entry_id); - - /* Force the loop to end */ - remaining_len = 0; - } else if ((p_next_log_entry->entry_id == 0) || - (p_next_log_entry->entry_id > 200)) { - /* Invalid entry - fail the search */ - fprintf(stderr, "ERROR : WDC: wdc_get_dev_mng_log_entry: \ - Invalid entry found at offset: 0x%x Entry Size: 0x%x, \ - Remaining Log Length: 0x%x Entry Id: 0x%x\n", - current_data_offset, log_entry_size, remaining_len, p_next_log_entry->entry_id); - - /* Force the loop to end */ - remaining_len = 0; - valid_log = false; - - /* The struture is invalid, so any match that was found is invalid. */ - *p_p_found_log_entry = NULL; - } else { - /* Structure must have at least one valid entry to be considered valid */ - valid_log = true; - if (p_next_log_entry->entry_id == entry_id) { - /* A potential match. */ - *p_p_found_log_entry = p_next_log_entry; - } - - remaining_len -= log_entry_size; - - if (remaining_len > 0) { - /* Increment the offset counter */ - current_data_offset += log_entry_size; - - /* Get the next entry */ - p_next_log_entry = (struct wdc_c2_log_subpage_header *)(((__u8*)p_log_hdr) + current_data_offset); - } - } - } - - return valid_log; +bool wdc_get_dev_mng_log_entry(__u32 log_length, __u32 entry_id, + struct wdc_c2_log_page_header *p_log_hdr, + struct wdc_c2_log_subpage_header **p_p_found_log_entry) +{ + __u32 remaining_len = 0; + __u32 log_entry_hdr_size = sizeof(struct wdc_c2_log_subpage_header) - 1; + __u32 log_entry_size = 0; + __u32 size = 0; + bool valid_log; + __u32 current_data_offset = 0; + struct wdc_c2_log_subpage_header *p_next_log_entry = NULL; + + if (!*p_p_found_log_entry) { + fprintf(stderr, "ERROR: WDC - %s: No ppLogEntry pointer.\n", __func__); + return false; + } + + *p_p_found_log_entry = NULL; + + /* Ensure log data is large enough for common header */ + if (log_length < sizeof(struct wdc_c2_log_page_header)) { + fprintf(stderr, + "ERROR: WDC - %s: Buffer is not large enough for the common header. BufSize: 0x%x HdrSize: %"PRIxPTR"\n", + __func__, log_length, sizeof(struct wdc_c2_log_page_header)); + return false; + } + + /* Get pointer to first log Entry */ + size = sizeof(struct wdc_c2_log_page_header); + current_data_offset = size; + p_next_log_entry = (struct wdc_c2_log_subpage_header *)((__u8 *)p_log_hdr + current_data_offset); + remaining_len = log_length - size; + valid_log = false; + + /* + * Walk the entire structure. Perform a sanity check to make sure this is a + * standard version of the structure. This means making sure each entry looks + * valid. But allow for the data to overflow the allocated + * buffer (we don't want a false negative because of a FW formatting error) + */ + + /* Proceed only if there is at least enough data to read an entry header */ + while (remaining_len >= log_entry_hdr_size) { + /* Get size of the next entry */ + log_entry_size = p_next_log_entry->length; + + /* + * If log entry size is 0 or the log entry goes past the end + * of the data, we must be at the end of the data + */ + if (!log_entry_size || log_entry_size > remaining_len) { + fprintf(stderr, "ERROR: WDC: %s: Detected unaligned end of the data. ", + __func__); + fprintf(stderr, "Data Offset: 0x%x Entry Size: 0x%x, ", + current_data_offset, log_entry_size); + fprintf(stderr, "Remaining Log Length: 0x%x Entry Id: 0x%x\n", + remaining_len, p_next_log_entry->entry_id); + + /* Force the loop to end */ + remaining_len = 0; + } else if (!p_next_log_entry->entry_id || p_next_log_entry->entry_id > 200) { + /* Invalid entry - fail the search */ + fprintf(stderr, "ERROR: WDC: %s: Invalid entry found at offset: 0x%x ", + __func__, current_data_offset); + fprintf(stderr, "Entry Size: 0x%x, Remaining Log Length: 0x%x ", + log_entry_size, remaining_len); + fprintf(stderr, "Entry Id: 0x%x\n", p_next_log_entry->entry_id); + + /* Force the loop to end */ + remaining_len = 0; + valid_log = false; + + /* The struture is invalid, so any match that was found is invalid. */ + *p_p_found_log_entry = NULL; + } else { + /* Structure must have at least one valid entry to be considered valid */ + valid_log = true; + if (p_next_log_entry->entry_id == entry_id) + /* A potential match. */ + *p_p_found_log_entry = p_next_log_entry; + + remaining_len -= log_entry_size; + + if (remaining_len > 0) { + /* Increment the offset counter */ + current_data_offset += log_entry_size; + + /* Get the next entry */ + p_next_log_entry = (struct wdc_c2_log_subpage_header *)(((__u8 *)p_log_hdr) + current_data_offset); + } + } + } + + return valid_log; } static bool get_dev_mgment_cbs_data(nvme_root_t r, struct nvme_dev *dev, - __u8 log_id, void **cbs_data) + __u8 log_id, void **cbs_data) { int ret = -1; - void* data; + void *data; struct wdc_c2_log_page_header *hdr_ptr; struct wdc_c2_log_subpage_header *sph; __u32 length = 0; @@ -1987,17 +1997,19 @@ static bool get_dev_mgment_cbs_data(nvme_root_t r, struct nvme_dev *dev, __u32 device_id, read_vendor_id; ret = wdc_get_pci_ids(r, dev, &device_id, &read_vendor_id); - if(device_id == WDC_NVME_ZN350_DEV_ID || device_id == WDC_NVME_ZN350_DEV_ID_1) { + if (device_id == WDC_NVME_ZN350_DEV_ID || device_id == WDC_NVME_ZN350_DEV_ID_1) { lid = WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE_C8; uuid_ix = 0; - } else + } else { lid = WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE; + } - if ((data = (__u8*) malloc(sizeof (__u8) * WDC_C2_LOG_BUF_LEN)) == NULL) { - fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); + data = (__u8 *)malloc(sizeof(__u8) * WDC_C2_LOG_BUF_LEN); + if (!data) { + fprintf(stderr, "ERROR: WDC: malloc: %s\n", strerror(errno)); return false; } - memset(data, 0, sizeof (__u8) * WDC_C2_LOG_BUF_LEN); + memset(data, 0, sizeof(__u8) * WDC_C2_LOG_BUF_LEN); /* get the log page length */ struct nvme_get_log_args args_len = { @@ -2019,7 +2031,7 @@ static bool get_dev_mgment_cbs_data(nvme_root_t r, struct nvme_dev *dev, }; ret = nvme_get_log(&args_len); if (ret) { - fprintf(stderr, "ERROR : WDC : Unable to get 0x%x Log Page length, ret = 0x%x\n", lid, ret); + fprintf(stderr, "ERROR: WDC: Unable to get 0x%x Log Page length, ret = 0x%x\n", lid, ret); goto end; } @@ -2030,8 +2042,8 @@ static bool get_dev_mgment_cbs_data(nvme_root_t r, struct nvme_dev *dev, /* Log Page buffer too small, free and reallocate the necessary size */ free(data); data = calloc(length, sizeof(__u8)); - if (data == NULL) { - fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); + if (!data) { + fprintf(stderr, "ERROR: WDC: malloc: %s\n", strerror(errno)); return false; } } @@ -2057,7 +2069,7 @@ static bool get_dev_mgment_cbs_data(nvme_root_t r, struct nvme_dev *dev, ret = nvme_get_log(&args_data); if (ret) { - fprintf(stderr, "ERROR : WDC : Unable to read 0x%x Log Page data, ret = 0x%x\n", lid, ret); + fprintf(stderr, "ERROR: WDC: Unable to read 0x%x Log Page data, ret = 0x%x\n", lid, ret); goto end; } @@ -2069,8 +2081,8 @@ static bool get_dev_mgment_cbs_data(nvme_root_t r, struct nvme_dev *dev, found = wdc_get_dev_mng_log_entry(le32_to_cpu(hdr_ptr->length), log_id, hdr_ptr, &sph); if (found) { *cbs_data = calloc(le32_to_cpu(sph->length), sizeof(__u8)); - if (*cbs_data == NULL) { - fprintf(stderr, "ERROR : WDC : calloc : %s\n", strerror(errno)); + if (!*cbs_data) { + fprintf(stderr, "ERROR: WDC: calloc: %s\n", strerror(errno)); goto end; } memcpy((void *)*cbs_data, (void *)&sph->data, le32_to_cpu(sph->length)); @@ -2102,32 +2114,30 @@ static bool get_dev_mgment_cbs_data(nvme_root_t r, struct nvme_dev *dev, found = wdc_get_dev_mng_log_entry(le32_to_cpu(hdr_ptr->length), log_id, hdr_ptr, &sph); if (found) { *cbs_data = calloc(le32_to_cpu(sph->length), sizeof(__u8)); - if (*cbs_data == NULL) { - fprintf(stderr, "ERROR : WDC : calloc : %s\n", strerror(errno)); + if (!*cbs_data) { + fprintf(stderr, "ERROR: WDC: calloc: %s\n", strerror(errno)); goto end; } memcpy((void *)*cbs_data, (void *)&sph->data, le32_to_cpu(sph->length)); - } else { - /* WD version not found */ - fprintf(stderr, "ERROR : WDC : Unable to find correct version of page 0x%x, entry id = %d\n", lid, log_id); + /* WD version not found */ + fprintf(stderr, "ERROR: WDC: Unable to find correct version of page 0x%x, entry id = %d\n", lid, log_id); } } + end: free(data); return found; } -static bool wdc_nvme_check_supported_log_page(nvme_root_t r, - struct nvme_dev *dev, - __u8 log_id) +static bool wdc_nvme_check_supported_log_page(nvme_root_t r, struct nvme_dev *dev, __u8 log_id) { int i; bool found = false; struct wdc_c2_cbs_data *cbs_data = NULL; if (get_dev_mgment_cbs_data(r, dev, WDC_C2_LOG_PAGES_SUPPORTED_ID, (void *)&cbs_data)) { - if (cbs_data != NULL) { + if (cbs_data) { for (i = 0; i < le32_to_cpu(cbs_data->length); i++) { if (log_id == cbs_data->data[i]) { found = true; @@ -2137,30 +2147,31 @@ static bool wdc_nvme_check_supported_log_page(nvme_root_t r, #ifdef WDC_NVME_CLI_DEBUG if (!found) { - fprintf(stderr, "ERROR : WDC : Log Page 0x%x not supported\n", log_id); - fprintf(stderr, "WDC : Supported Log Pages:\n"); + fprintf(stderr, "ERROR: WDC: Log Page 0x%x not supported\n", log_id); + fprintf(stderr, "WDC: Supported Log Pages:\n"); /* print the supported pages */ d((__u8 *)cbs_data->data, le32_to_cpu(cbs_data->length), 16, 1); } #endif free(cbs_data); - } else - fprintf(stderr, "ERROR : WDC : cbs_data ptr = NULL\n"); - } else - fprintf(stderr, "ERROR : WDC : 0xC2 Log Page entry ID 0x%x not found\n", WDC_C2_LOG_PAGES_SUPPORTED_ID); + } else { + fprintf(stderr, "ERROR: WDC: cbs_data ptr = NULL\n"); + } + } else { + fprintf(stderr, "ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found\n", + WDC_C2_LOG_PAGES_SUPPORTED_ID); + } return found; } -static bool wdc_nvme_get_dev_status_log_data(nvme_root_t r, - struct nvme_dev *dev, - __le32 *ret_data, - __u8 log_id) +static bool wdc_nvme_get_dev_status_log_data(nvme_root_t r, struct nvme_dev *dev, __le32 *ret_data, + __u8 log_id) { __u32 *cbs_data = NULL; if (get_dev_mgment_cbs_data(r, dev, log_id, (void *)&cbs_data)) { - if (cbs_data != NULL) { + if (cbs_data) { memcpy((void *)ret_data, (void *)cbs_data, 4); free(cbs_data); @@ -2177,13 +2188,12 @@ static int wdc_do_clear_dump(struct nvme_dev *dev, __u8 opcode, __u32 cdw12) int ret; struct nvme_passthru_cmd admin_cmd; - memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); + memset(&admin_cmd, 0, sizeof(struct nvme_passthru_cmd)); admin_cmd.opcode = opcode; admin_cmd.cdw12 = cdw12; ret = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); - if (ret != 0) { - fprintf(stdout, "ERROR : WDC : Crash dump erase failed\n"); - } + if (ret) + fprintf(stdout, "ERROR: WDC: Crash dump erase failed\n"); nvme_show_status(ret); return ret; } @@ -2196,7 +2206,7 @@ static __u32 wdc_dump_length(int fd, __u32 opcode, __u32 cdw10, __u32 cdw12, __u struct nvme_passthru_cmd admin_cmd; l = (struct wdc_log_size *) buf; - memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); + memset(&admin_cmd, 0, sizeof(struct nvme_passthru_cmd)); admin_cmd.opcode = opcode; admin_cmd.addr = (__u64)(uintptr_t)buf; admin_cmd.data_len = WDC_NVME_LOG_SIZE_DATA_LEN; @@ -2204,10 +2214,10 @@ static __u32 wdc_dump_length(int fd, __u32 opcode, __u32 cdw10, __u32 cdw12, __u admin_cmd.cdw12 = cdw12; ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); - if (ret != 0) { + if (ret) { l->log_size = 0; ret = -1; - fprintf(stderr, "ERROR : WDC : reading dump length failed\n"); + fprintf(stderr, "ERROR: WDC: reading dump length failed\n"); nvme_show_status(ret); return ret; } @@ -2224,7 +2234,7 @@ static __u32 wdc_dump_length_e6(int fd, __u32 opcode, __u32 cdw10, __u32 cdw12, int ret; struct nvme_passthru_cmd admin_cmd; - memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); + memset(&admin_cmd, 0, sizeof(struct nvme_passthru_cmd)); admin_cmd.opcode = opcode; admin_cmd.addr = (__u64)(uintptr_t)dump_hdr; admin_cmd.data_len = WDC_NVME_LOG_SIZE_HDR_LEN; @@ -2232,8 +2242,8 @@ static __u32 wdc_dump_length_e6(int fd, __u32 opcode, __u32 cdw10, __u32 cdw12, admin_cmd.cdw12 = cdw12; ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); - if (ret != 0) { - fprintf(stderr, "ERROR : WDC : reading dump length failed\n"); + if (ret) { + fprintf(stderr, "ERROR: WDC: reading dump length failed\n"); nvme_show_status(ret); } @@ -2245,7 +2255,7 @@ static __u32 wdc_dump_dui_data(int fd, __u32 dataLen, __u32 offset, __u8 *dump_d int ret; struct nvme_passthru_cmd admin_cmd; - memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); + memset(&admin_cmd, 0, sizeof(struct nvme_passthru_cmd)); admin_cmd.opcode = WDC_NVME_CAP_DUI_OPCODE; admin_cmd.nsid = 0xFFFFFFFF; admin_cmd.addr = (__u64)(uintptr_t)dump_data; @@ -2259,8 +2269,8 @@ static __u32 wdc_dump_dui_data(int fd, __u32 dataLen, __u32 offset, __u8 *dump_d ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); - if (ret != 0) { - fprintf(stderr, "ERROR : WDC : reading DUI data failed\n"); + if (ret) { + fprintf(stderr, "ERROR: WDC: reading DUI data failed\n"); nvme_show_status(ret); } @@ -2273,7 +2283,7 @@ static __u32 wdc_dump_dui_data_v2(int fd, __u32 dataLen, __u64 offset, __u8 *dum struct nvme_passthru_cmd admin_cmd; __u64 offset_lo, offset_hi; - memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); + memset(&admin_cmd, 0, sizeof(struct nvme_passthru_cmd)); admin_cmd.opcode = WDC_NVME_CAP_DUI_OPCODE; admin_cmd.nsid = 0xFFFFFFFF; admin_cmd.addr = (__u64)(uintptr_t)dump_data; @@ -2290,15 +2300,15 @@ static __u32 wdc_dump_dui_data_v2(int fd, __u32 dataLen, __u64 offset, __u8 *dum admin_cmd.cdw14 = WDC_NVME_CAP_DUI_DISABLE_IO; ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); - if (ret != 0) { - fprintf(stderr, "ERROR : WDC : reading DUI data V2 failed\n"); + if (ret) { + fprintf(stderr, "ERROR: WDC: reading DUI data V2 failed\n"); nvme_show_status(ret); } return ret; } -static int wdc_do_dump(struct nvme_dev *dev, __u32 opcode,__u32 data_len, +static int wdc_do_dump(struct nvme_dev *dev, __u32 opcode, __u32 data_len, __u32 cdw12, char *file, __u32 xfer_size) { int ret = 0; @@ -2308,13 +2318,13 @@ static int wdc_do_dump(struct nvme_dev *dev, __u32 opcode,__u32 data_len, struct nvme_passthru_cmd admin_cmd; __u32 dump_length = data_len; - dump_data = (__u8 *) malloc(sizeof (__u8) * dump_length); - if (dump_data == NULL) { - fprintf(stderr, "%s: ERROR : malloc : %s\n", __func__, strerror(errno)); + dump_data = (__u8 *)malloc(sizeof(__u8) * dump_length); + if (!dump_data) { + fprintf(stderr, "%s: ERROR: malloc: %s\n", __func__, strerror(errno)); return -1; } - memset(dump_data, 0, sizeof (__u8) * dump_length); - memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); + memset(dump_data, 0, sizeof(__u8) * dump_length); + memset(&admin_cmd, 0, sizeof(struct nvme_passthru_cmd)); curr_data_offset = 0; curr_data_len = xfer_size; i = 0; @@ -2329,10 +2339,10 @@ static int wdc_do_dump(struct nvme_dev *dev, __u32 opcode,__u32 data_len, while (curr_data_offset < data_len) { ret = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); - if (ret != 0) { + if (ret) { nvme_show_status(ret); - fprintf(stderr, "%s: ERROR : WDC : Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx\n", - __func__, i, admin_cmd.data_len, curr_data_offset, (long unsigned int)admin_cmd.addr); + fprintf(stderr, "%s: ERROR: WDC: Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx\n", + __func__, i, admin_cmd.data_len, curr_data_offset, (unsigned long)admin_cmd.addr); break; } @@ -2349,7 +2359,7 @@ static int wdc_do_dump(struct nvme_dev *dev, __u32 opcode,__u32 data_len, i++; } - if (ret == 0) { + if (!ret) { nvme_show_status(ret); ret = wdc_create_log_file(file, dump_data, dump_length); } @@ -2357,7 +2367,7 @@ static int wdc_do_dump(struct nvme_dev *dev, __u32 opcode,__u32 data_len, return ret; } -static int wdc_do_dump_e6(int fd, __u32 opcode,__u32 data_len, +static int wdc_do_dump_e6(int fd, __u32 opcode, __u32 data_len, __u32 cdw12, char *file, __u32 xfer_size, __u8 *log_hdr) { int ret = 0; @@ -2366,14 +2376,14 @@ static int wdc_do_dump_e6(int fd, __u32 opcode,__u32 data_len, int i; struct nvme_passthru_cmd admin_cmd; - dump_data = (__u8 *) malloc(sizeof (__u8) * data_len); + dump_data = (__u8 *)malloc(sizeof(__u8) * data_len); - if (dump_data == NULL) { - fprintf(stderr, "%s: ERROR : malloc : %s\n", __func__, strerror(errno)); + if (!dump_data) { + fprintf(stderr, "%s: ERROR: malloc: %s\n", __func__, strerror(errno)); return -1; } - memset(dump_data, 0, sizeof (__u8) * data_len); - memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); + memset(dump_data, 0, sizeof(__u8) * data_len); + memset(&admin_cmd, 0, sizeof(struct nvme_passthru_cmd)); curr_data_offset = WDC_NVME_LOG_SIZE_HDR_LEN; i = 0; @@ -2393,10 +2403,10 @@ static int wdc_do_dump_e6(int fd, __u32 opcode,__u32 data_len, admin_cmd.cdw13 = curr_data_offset >> 2; ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); - if (ret != 0) { + if (ret) { nvme_show_status(ret); - fprintf(stderr, "%s: ERROR : WDC : Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx\n", - __func__, i, admin_cmd.data_len, curr_data_offset, (long unsigned int)admin_cmd.addr); + fprintf(stderr, "%s: ERROR: WDC: Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx\n", + __func__, i, admin_cmd.data_len, curr_data_offset, (unsigned long)admin_cmd.addr); break; } @@ -2405,13 +2415,13 @@ static int wdc_do_dump_e6(int fd, __u32 opcode,__u32 data_len, i++; } - if (ret == 0) { - fprintf(stderr, "%s: ", __func__); + if (!ret) { + fprintf(stderr, "%s: INFO: ", __func__); nvme_show_status(ret); } else { - fprintf(stderr, "%s: FAILURE: ", __func__); + fprintf(stderr, "%s: FAILURE: ", __func__); nvme_show_status(ret); - fprintf(stderr, "%s: Partial data may have been captured\n", __func__); + fprintf(stderr, "%s: Partial data may have been captured\n", __func__); snprintf(file + strlen(file), PATH_MAX, "%s", "-PARTIAL"); } @@ -2422,7 +2432,7 @@ static int wdc_do_dump_e6(int fd, __u32 opcode,__u32 data_len, } static int wdc_do_cap_telemetry_log(struct nvme_dev *dev, char *file, - __u32 bs, int type, int data_area) + __u32 bs, int type, int data_area) { struct nvme_telemetry_log *log; size_t full_size = 0; @@ -2437,11 +2447,10 @@ static int wdc_do_cap_telemetry_log(struct nvme_dev *dev, char *file, __u64 capabilities = 0; nvme_root_t r; - memset(&ctrl, 0, sizeof (struct nvme_id_ctrl)); + memset(&ctrl, 0, sizeof(struct nvme_id_ctrl)); err = nvme_identify_ctrl(dev_fd(dev), &ctrl); if (err) { - fprintf(stderr, "ERROR : WDC : nvme_identify_ctrl() failed " - "0x%x\n", err); + fprintf(stderr, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x\n", err); return err; } @@ -2460,26 +2469,23 @@ static int wdc_do_cap_telemetry_log(struct nvme_dev *dev, char *file, if ((capabilities & WDC_DRIVE_CAP_INTERNAL_LOG) == WDC_DRIVE_CAP_INTERNAL_LOG) { /* Verify the Controller Initiated Option is enabled */ err = nvme_get_features_data(dev_fd(dev), - WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, - 0, 4, buf, &result); - if (err == 0) { - if (result == 0) { + WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, + 0, 4, buf, &result); + if (!err) { + if (!result) { /* enabled */ host_gen = 0; ctrl_init = 1; - } - else { + } else { fprintf(stderr, "%s: Controller initiated option telemetry log page disabled\n", __func__); return -EINVAL; } - } - else { - fprintf(stderr, "ERROR : WDC: Get telemetry option feature failed."); + } else { + fprintf(stderr, "ERROR: WDC: Get telemetry option feature failed."); nvme_show_status(err); return -EPERM; } - } - else { + } else { host_gen = 0; ctrl_init = 1; } @@ -2502,13 +2508,13 @@ static int wdc_do_cap_telemetry_log(struct nvme_dev *dev, char *file, if (ctrl_init) err = nvme_get_ctrl_telemetry(dev_fd(dev), true, &log, - data_area, &full_size); + data_area, &full_size); else if (host_gen) err = nvme_get_new_host_telemetry(dev_fd(dev), &log, data_area, &full_size); else err = nvme_get_host_telemetry(dev_fd(dev), &log, data_area, - &full_size); + &full_size); if (err < 0) { perror("get-telemetry-log"); @@ -2520,8 +2526,8 @@ static int wdc_do_cap_telemetry_log(struct nvme_dev *dev, char *file, } /* - * Continuously pull data until the offset hits the end of the last - * block. + *Continuously pull data until the offset hits the end of the last + *block. */ data_written = 0; data_remaining = full_size; @@ -2545,7 +2551,7 @@ static int wdc_do_cap_telemetry_log(struct nvme_dev *dev, char *file, } if (fsync(output) < 0) { - fprintf(stderr, "ERROR : %s: fsync : %s\n", __func__, strerror(errno)); + fprintf(stderr, "ERROR: %s: fsync: %s\n", __func__, strerror(errno)); err = -1; } @@ -2563,9 +2569,9 @@ static int wdc_do_cap_diag(nvme_root_t r, struct nvme_dev *dev, char *file, struct wdc_e6_log_hdr *log_hdr; __u32 cap_diag_length; - log_hdr = (struct wdc_e6_log_hdr *) malloc(e6_log_hdr_size); - if (log_hdr == NULL) { - fprintf(stderr, "%s: ERROR : malloc : %s\n", __func__, strerror(errno)); + log_hdr = (struct wdc_e6_log_hdr *)malloc(e6_log_hdr_size); + if (!log_hdr) { + fprintf(stderr, "%s: ERROR: malloc: %s\n", __func__, strerror(errno)); ret = -1; goto out; } @@ -2585,401 +2591,487 @@ static int wdc_do_cap_diag(nvme_root_t r, struct nvme_dev *dev, char *file, cap_diag_length = (log_hdr->log_size[0] << 24 | log_hdr->log_size[1] << 16 | log_hdr->log_size[2] << 8 | log_hdr->log_size[3]); - if (cap_diag_length == 0) { - fprintf(stderr, "INFO : WDC : Capture Diagnostics log is empty\n"); + if (!cap_diag_length) { + fprintf(stderr, "INFO: WDC: Capture Diagnostics log is empty\n"); } else { ret = wdc_do_dump_e6(dev_fd(dev), - WDC_NVME_CAP_DIAG_OPCODE, + WDC_NVME_CAP_DIAG_OPCODE, cap_diag_length, (WDC_NVME_CAP_DIAG_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_CAP_DIAG_CMD, file, xfer_size, (__u8 *)log_hdr); - fprintf(stderr, "INFO : WDC : Capture Diagnostics log, length = 0x%x\n", cap_diag_length); + fprintf(stderr, "INFO: WDC: Capture Diagnostics log, length = 0x%x\n", cap_diag_length); } } else if ((type == WDC_TELEMETRY_TYPE_HOST) || (type == WDC_TELEMETRY_TYPE_CONTROLLER)) { /* Get the desired telemetry log page */ ret = wdc_do_cap_telemetry_log(dev, file, xfer_size, type, data_area); - } else - fprintf(stderr, "%s: ERROR : Invalid type : %d\n", __func__, type); + } else { + fprintf(stderr, "%s: ERROR: Invalid type : %d\n", __func__, type); + } out: free(log_hdr); return ret; } -static int wdc_do_cap_dui(int fd, char *file, __u32 xfer_size, int data_area, int verbose, __u64 file_size, __u64 offset) +static int wdc_do_cap_dui_v1(int fd, char *file, __u32 xfer_size, int data_area, int verbose, + struct wdc_dui_log_hdr *log_hdr, __s64 *total_size) { - int ret = 0; - __u32 dui_log_hdr_size = WDC_NVME_CAP_DUI_HEADER_SIZE; - struct wdc_dui_log_hdr *log_hdr; - struct wdc_dui_log_hdr_v3 *log_hdr_v3; - __u32 cap_dui_length; - __u64 cap_dui_length_v3; - __u64 cap_dui_length_v4; - __u8 *dump_data = NULL; + __s32 log_size = 0; + __u32 cap_dui_length = le32_to_cpu(log_hdr->log_size); + __u32 curr_data_offset = 0; __u8 *buffer_addr; - __s64 total_size = 0; + __u8 *dump_data = NULL; + bool last_xfer = false; + int err; int i; int j; - bool last_xfer = false; - int err = 0, output = 0; + int output; + int ret = 0; - log_hdr = (struct wdc_dui_log_hdr *) malloc(dui_log_hdr_size); - if (log_hdr == NULL) { - fprintf(stderr, "%s: ERROR : log header malloc failed : status %s, size 0x%x\n", - __func__, strerror(errno), dui_log_hdr_size); + if (verbose) { + fprintf(stderr, "INFO: WDC: Capture V1 Device Unit Info log, data area = %d\n", + data_area); + fprintf(stderr, "INFO: WDC: DUI Header Version = 0x%x\n", log_hdr->hdr_version); + } + + if (!cap_dui_length) { + fprintf(stderr, "INFO: WDC: Capture V1 Device Unit Info log is empty\n"); + return 0; + } + + /* parse log header for all sections up to specified data area inclusively */ + if (data_area != WDC_NVME_DUI_MAX_DATA_AREA) { + for (j = 0; j < WDC_NVME_DUI_MAX_SECTION; j++) { + if (log_hdr->log_section[j].data_area_id <= data_area && + log_hdr->log_section[j].data_area_id) { + log_size += log_hdr->log_section[j].section_size; + if (verbose) + fprintf(stderr, + "%s: Data area ID %d : section size 0x%x, total size = 0x%x\n", + __func__, log_hdr->log_section[j].data_area_id, + (unsigned int)log_hdr->log_section[j].section_size, + (unsigned int)log_size); + + } else { + if (verbose) + fprintf(stderr, "%s: break, total size = 0x%x\n", __func__, + (unsigned int)log_size); + break; + } + } + } else { + log_size = cap_dui_length; + } + + *total_size = log_size; + + dump_data = (__u8 *)malloc(sizeof(__u8) * xfer_size); + if (!dump_data) { + fprintf(stderr, "%s: ERROR: dump data V1 malloc failed : status %s, size = 0x%x\n", + __func__, strerror(errno), (unsigned int)xfer_size); return -1; } - memset(log_hdr, 0, dui_log_hdr_size); + memset(dump_data, 0, sizeof(__u8) * xfer_size); - /* get the dui telemetry and log headers */ - ret = wdc_dump_dui_data(fd, WDC_NVME_CAP_DUI_HEADER_SIZE, 0x00, (__u8 *)log_hdr, last_xfer); - if (ret != 0) { - fprintf(stderr, "%s: ERROR : WDC : Get DUI headers failed\n", __func__); - fprintf(stderr, "%s: ERROR : WDC : ", __func__); - nvme_show_status(ret); - goto out; + output = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (output < 0) { + fprintf(stderr, "%s: Failed to open output file %s: %s!\n", __func__, file, + strerror(errno)); + free(dump_data); + return output; } - /* Check the Log Header version */ - if ((log_hdr->hdr_version & 0xFF) == 0x00 || - (log_hdr->hdr_version & 0xFF) == 0x01) { - __s32 log_size = 0; - __u32 curr_data_offset = 0; + /* write the telemetry and log headers into the dump_file */ + err = write(output, (void *)log_hdr, WDC_NVME_CAP_DUI_HEADER_SIZE); + if (err != WDC_NVME_CAP_DUI_HEADER_SIZE) { + fprintf(stderr, "%s: Failed to flush header data to file!\n", __func__); + goto free_mem; + } - cap_dui_length = le32_to_cpu(log_hdr->log_size); + log_size -= WDC_NVME_CAP_DUI_HEADER_SIZE; + curr_data_offset = WDC_NVME_CAP_DUI_HEADER_SIZE; + i = 0; + buffer_addr = dump_data; - if (verbose) { - fprintf(stderr, "INFO : WDC : Capture V1 Device Unit Info log, data area = %d\n", data_area); - fprintf(stderr, "INFO : WDC : DUI Header Version = 0x%x\n", log_hdr->hdr_version); - } + for (; log_size > 0; log_size -= xfer_size) { + xfer_size = min(xfer_size, log_size); - if (cap_dui_length == 0) { - fprintf(stderr, "INFO : WDC : Capture V1 Device Unit Info log is empty\n"); - } else { - /* parse log header for all sections up to specified data area inclusively */ - if (data_area != WDC_NVME_DUI_MAX_DATA_AREA) { - for(j = 0; j < WDC_NVME_DUI_MAX_SECTION; j++) { - if (log_hdr->log_section[j].data_area_id <= data_area && - log_hdr->log_section[j].data_area_id != 0) { - log_size += log_hdr->log_section[j].section_size; - if (verbose) - fprintf(stderr, "%s: Data area ID %d : section size 0x%x, total size = 0x%x\n", - __func__, log_hdr->log_section[j].data_area_id, (unsigned int)log_hdr->log_section[j].section_size, (unsigned int)log_size); - - } - else { - if (verbose) - fprintf(stderr, "%s: break, total size = 0x%x\n", __func__, (unsigned int)log_size); - break; - } - } - } else - log_size = cap_dui_length; + if (log_size <= xfer_size) + last_xfer = true; - total_size = log_size; + ret = wdc_dump_dui_data(fd, xfer_size, curr_data_offset, buffer_addr, last_xfer); + if (ret) { + fprintf(stderr, + "%s: ERROR: WDC: Get chunk %d, size = 0x%"PRIx64", offset = 0x%x, addr = %p\n", + __func__, i, (uint64_t)log_size, curr_data_offset, buffer_addr); + fprintf(stderr, "%s: ERROR: WDC: ", __func__); + nvme_show_status(ret); + break; + } - dump_data = (__u8 *) malloc(sizeof (__u8) * xfer_size); - if (dump_data == NULL) { - fprintf(stderr, "%s: ERROR : dump data V1 malloc failed : status %s, size = 0x%x\n", - __func__, strerror(errno), (unsigned int)xfer_size); - ret = -1; - goto out; - } - memset(dump_data, 0, sizeof (__u8) * xfer_size); - - output = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0666); - if (output < 0) { - fprintf(stderr, "%s: Failed to open output file %s: %s!\n", - __func__, file, strerror(errno)); - ret = output; - goto free_mem; - } + /* write the dump data into the file */ + err = write(output, (void *)buffer_addr, xfer_size); + if (err != xfer_size) { + fprintf(stderr, + "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size = 0x%x\n", + __func__, i, err, xfer_size); + ret = -1; + goto free_mem; + } - /* write the telemetry and log headers into the dump_file */ - err = write(output, (void *)log_hdr, WDC_NVME_CAP_DUI_HEADER_SIZE); - if (err != WDC_NVME_CAP_DUI_HEADER_SIZE) { - fprintf(stderr, "%s: Failed to flush header data to file!\n", __func__); - goto free_mem; - } + curr_data_offset += xfer_size; + i++; + } - log_size -= WDC_NVME_CAP_DUI_HEADER_SIZE; - curr_data_offset = WDC_NVME_CAP_DUI_HEADER_SIZE; - i = 0; - buffer_addr = dump_data; +free_mem: + close(output); + free(dump_data); + return ret; +} - for(; log_size > 0; log_size -= xfer_size) { - xfer_size = min(xfer_size, log_size); +static int wdc_do_cap_dui_v2_v3(int fd, char *file, __u32 xfer_size, int data_area, int verbose, + struct wdc_dui_log_hdr *log_hdr, __s64 *total_size, __u64 file_size, + __u64 offset) +{ + __u64 cap_dui_length_v3; + __u64 curr_data_offset = 0; + __s64 log_size = 0; + __u64 xfer_size_long = (__u64)xfer_size; + __u8 *buffer_addr; + __u8 *dump_data = NULL; + bool last_xfer = false; + int err; + int i; + int j; + int output; + int ret = 0; + struct wdc_dui_log_hdr_v3 *log_hdr_v3 = (struct wdc_dui_log_hdr_v3 *)log_hdr; - if (log_size <= xfer_size) - last_xfer = true; + cap_dui_length_v3 = le64_to_cpu(log_hdr_v3->log_size); - ret = wdc_dump_dui_data(fd, xfer_size, curr_data_offset, buffer_addr, last_xfer); - if (ret != 0) { - fprintf(stderr, "%s: ERROR : WDC : Get chunk %d, size = 0x%"PRIx64", offset = 0x%x, addr = %p\n", - __func__, i, (uint64_t)log_size, curr_data_offset, buffer_addr); - fprintf(stderr, "%s: ERROR : WDC : ", - __func__); - nvme_show_status(ret); - break; - } + if (verbose) { + fprintf(stderr, + "INFO: WDC: Capture V2 or V3 Device Unit Info log, data area = %d\n", + data_area); - /* write the dump data into the file */ - err = write(output, (void *)buffer_addr, xfer_size); - if (err != xfer_size) { - fprintf(stderr, "%s: ERROR : WDC : Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size = 0x%x\n", - __func__, i, err, xfer_size); - goto free_mem; - } + fprintf(stderr, "INFO: WDC: DUI Header Version = 0x%x\n", + log_hdr_v3->hdr_version); + if ((log_hdr->hdr_version & 0xFF) == 0x03) + fprintf(stderr, "INFO: WDC: DUI Product ID = 0x%x/%c\n", + log_hdr_v3->product_id, log_hdr_v3->product_id); + } - curr_data_offset += xfer_size; - i++; + if (!cap_dui_length_v3) { + fprintf(stderr, "INFO: WDC: Capture V2 or V3 Device Unit Info log is empty\n"); + return 0; + } + + /* parse log header for all sections up to specified data area inclusively */ + if (data_area != WDC_NVME_DUI_MAX_DATA_AREA) { + for (j = 0; j < WDC_NVME_DUI_MAX_SECTION_V3; j++) { + if (log_hdr_v3->log_section[j].data_area_id <= data_area && + log_hdr_v3->log_section[j].data_area_id) { + log_size += log_hdr_v3->log_section[j].section_size; + if (verbose) + fprintf(stderr, + "%s: Data area ID %d : section size 0x%x, total size = 0x%"PRIx64"\n", + __func__, log_hdr_v3->log_section[j].data_area_id, + (unsigned int)log_hdr_v3->log_section[j].section_size, + (uint64_t)log_size); + } else { + if (verbose) + fprintf(stderr, "%s: break, total size = 0x%"PRIx64"\n", + __func__, (uint64_t)log_size); + break; } } + } else { + log_size = cap_dui_length_v3; } - else if (((log_hdr->hdr_version & 0xFF) == 0x02) || - ((log_hdr->hdr_version & 0xFF) == 0x03)) { /* Process Version 2 or 3 header */ - __s64 log_size = 0; - __u64 curr_data_offset = 0; - __u64 xfer_size_long = (__u64)xfer_size; - log_hdr_v3 = (struct wdc_dui_log_hdr_v3 *)log_hdr; + *total_size = log_size; - cap_dui_length_v3 = le64_to_cpu(log_hdr_v3->log_size); + if (offset >= *total_size) { + fprintf(stderr, + "%s: INFO: WDC: Offset 0x%"PRIx64" exceeds total size 0x%"PRIx64", no data retrieved\n", + __func__, (uint64_t)offset, (uint64_t)*total_size); + return -1; + } - if (verbose) { - fprintf(stderr, "INFO : WDC : Capture V2 or V3 Device Unit Info log, data area = %d\n", data_area); + dump_data = (__u8 *)malloc(sizeof(__u8) * xfer_size_long); + if (!dump_data) { + fprintf(stderr, + "%s: ERROR: dump data v3 malloc failed : status %s, size = 0x%"PRIx64"\n", + __func__, strerror(errno), (uint64_t)xfer_size_long); + return -1; + } + memset(dump_data, 0, sizeof(__u8) * xfer_size_long); - fprintf(stderr, "INFO : WDC : DUI Header Version = 0x%x\n", log_hdr_v3->hdr_version); - if ((log_hdr->hdr_version & 0xFF) == 0x03) - fprintf(stderr, "INFO : WDC : DUI Product ID = 0x%x/%c\n", log_hdr_v3->product_id, log_hdr_v3->product_id); - } + output = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (output < 0) { + fprintf(stderr, "%s: Failed to open output file %s: %s!\n", + __func__, file, strerror(errno)); + free(dump_data); + return output; + } - if (cap_dui_length_v3 == 0) { - fprintf(stderr, "INFO : WDC : Capture V2 or V3 Device Unit Info log is empty\n"); - } else { - /* parse log header for all sections up to specified data area inclusively */ - if (data_area != WDC_NVME_DUI_MAX_DATA_AREA) { - for(j = 0; j < WDC_NVME_DUI_MAX_SECTION_V3; j++) { - if (log_hdr_v3->log_section[j].data_area_id <= data_area && - log_hdr_v3->log_section[j].data_area_id != 0) { - log_size += log_hdr_v3->log_section[j].section_size; - if (verbose) - fprintf(stderr, "%s: Data area ID %d : section size 0x%x, total size = 0x%"PRIx64"\n", - __func__, log_hdr_v3->log_section[j].data_area_id, (unsigned int)log_hdr_v3->log_section[j].section_size, (uint64_t)log_size); - } - else { - if (verbose) - fprintf(stderr, "%s: break, total size = 0x%"PRIx64"\n", __func__, (uint64_t)log_size); - break; - } - } - } else - log_size = cap_dui_length_v3; + curr_data_offset = 0; - total_size = log_size; + if (file_size) { + /* Write the DUI data based on the passed in file size */ + if ((offset + file_size) > *total_size) + log_size = min((*total_size - offset), file_size); + else + log_size = min(*total_size, file_size); - if (offset >= total_size) { - fprintf(stderr, "%s: INFO : WDC : Offset 0x%"PRIx64" exceeds total size 0x%"PRIx64", no data retrieved\n", - __func__, (uint64_t)offset, (uint64_t)total_size); - goto out; - } + if (verbose) + fprintf(stderr, + "%s: INFO: WDC: Offset 0x%"PRIx64", file size 0x%"PRIx64", total size 0x%"PRIx64", log size 0x%"PRIx64"\n", + __func__, (uint64_t)offset, + (uint64_t)file_size, (uint64_t)*total_size, (uint64_t)log_size); - dump_data = (__u8 *) malloc(sizeof (__u8) * xfer_size_long); - if (dump_data == NULL) { - fprintf(stderr, "%s: ERROR : dump data v3 malloc failed : status %s, size = 0x%"PRIx64"\n", - __func__, strerror(errno), (uint64_t)xfer_size_long); - ret = -1; - goto out; - } - memset(dump_data, 0, sizeof (__u8) * xfer_size_long); - - output = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0666); - if (output < 0) { - fprintf(stderr, "%s: Failed to open output file %s: %s!\n", - __func__, file, strerror(errno)); - ret = output; - goto free_mem; - } + curr_data_offset = offset; + } - curr_data_offset = 0; + i = 0; + buffer_addr = dump_data; - if (file_size != 0) { - /* Write the DUI data based on the passed in file size */ - if ((offset + file_size) > total_size) - log_size = min((total_size - offset), file_size); - else - log_size = min(total_size, file_size); + for (; log_size > 0; log_size -= xfer_size_long) { + xfer_size_long = min(xfer_size_long, log_size); - if (verbose) - fprintf(stderr, "%s: INFO : WDC : Offset 0x%"PRIx64", file size 0x%"PRIx64", total size 0x%"PRIx64", log size 0x%"PRIx64"\n", - __func__, (uint64_t)offset, (uint64_t)file_size, (uint64_t)total_size, (uint64_t)log_size); + if (log_size <= xfer_size_long) + last_xfer = true; - curr_data_offset = offset; + ret = wdc_dump_dui_data_v2(fd, (__u32)xfer_size_long, curr_data_offset, buffer_addr, + last_xfer); + if (ret) { + fprintf(stderr, + "%s: ERROR: WDC: Get chunk %d, size = 0x%"PRIx64", offset = 0x%"PRIx64", addr = %p\n", + __func__, i, (uint64_t)*total_size, (uint64_t)curr_data_offset, + buffer_addr); + fprintf(stderr, "%s: ERROR: WDC: ", __func__); + nvme_show_status(ret); + break; + } - } + /* write the dump data into the file */ + err = write(output, (void *)buffer_addr, xfer_size_long); + if (err != xfer_size_long) { + fprintf(stderr, + "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size = 0x%"PRIx64"\n", + __func__, i, err, (uint64_t)xfer_size_long); + ret = -1; + goto free_mem; + } + + curr_data_offset += xfer_size_long; + i++; + } - i = 0; - buffer_addr = dump_data; +free_mem: + close(output); + free(dump_data); + return ret; +} - for(; log_size > 0; log_size -= xfer_size_long) { - xfer_size_long = min(xfer_size_long, log_size); +static int wdc_do_cap_dui_v4(int fd, char *file, __u32 xfer_size, int data_area, int verbose, + struct wdc_dui_log_hdr *log_hdr, __s64 *total_size, __u64 file_size, + __u64 offset) +{ + __s64 log_size = 0; + __s64 section_size_bytes = 0; + __s64 xfer_size_long = (__s64)xfer_size; + __u64 cap_dui_length_v4; + __u64 curr_data_offset = 0; + __u8 *buffer_addr; + __u8 *dump_data = NULL; + int err; + int i; + int j; + int output; + int ret = 0; + bool last_xfer = false; + struct wdc_dui_log_hdr_v4 *log_hdr_v4 = (struct wdc_dui_log_hdr_v4 *)log_hdr; - if (log_size <= xfer_size_long) - last_xfer = true; + cap_dui_length_v4 = le64_to_cpu(log_hdr_v4->log_size_sectors) * WDC_NVME_SN730_SECTOR_SIZE; - ret = wdc_dump_dui_data_v2(fd, (__u32)xfer_size_long, curr_data_offset, buffer_addr, last_xfer); - if (ret != 0) { - fprintf(stderr, "%s: ERROR : WDC : Get chunk %d, size = 0x%"PRIx64", offset = 0x%"PRIx64", addr = %p\n", - __func__, i, (uint64_t)total_size, (uint64_t)curr_data_offset, buffer_addr); - fprintf(stderr, "%s: ERROR : WDC : ", __func__); - nvme_show_status(ret); - break; - } + if (verbose) { + fprintf(stderr, "INFO: WDC: Capture V4 Device Unit Info log, data area = %d\n", data_area); + fprintf(stderr, "INFO: WDC: DUI Header Version = 0x%x\n", log_hdr_v4->hdr_version); + fprintf(stderr, "INFO: WDC: DUI Product ID = 0x%x/%c\n", log_hdr_v4->product_id, log_hdr_v4->product_id); + fprintf(stderr, "INFO: WDC: DUI log size sectors = 0x%x\n", log_hdr_v4->log_size_sectors); + fprintf(stderr, "INFO: WDC: DUI cap_dui_length = 0x%"PRIx64"\n", (uint64_t)cap_dui_length_v4); + } - /* write the dump data into the file */ - err = write(output, (void *)buffer_addr, xfer_size_long); - if (err != xfer_size_long) { - fprintf(stderr, "%s: ERROR : WDC : Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size = 0x%"PRIx64"\n", - __func__, i, err, (uint64_t)xfer_size_long); - goto free_mem; - } + if (!cap_dui_length_v4) { + fprintf(stderr, "INFO: WDC: Capture V4 Device Unit Info log is empty\n"); + return 0; + } - curr_data_offset += xfer_size_long; - i++; + /* parse log header for all sections up to specified data area inclusively */ + if (data_area != WDC_NVME_DUI_MAX_DATA_AREA) { + for (j = 0; j < WDC_NVME_DUI_MAX_SECTION; j++) { + if (log_hdr_v4->log_section[j].data_area_id <= data_area && + log_hdr_v4->log_section[j].data_area_id) { + section_size_bytes = ((__s64)log_hdr_v4->log_section[j].section_size_sectors * WDC_NVME_SN730_SECTOR_SIZE); + log_size += section_size_bytes; + if (verbose) + fprintf(stderr, + "%s: Data area ID %d : section size 0x%x sectors, section size 0x%"PRIx64" bytes, total size = 0x%"PRIx64"\n", + __func__, log_hdr_v4->log_section[j].data_area_id, + log_hdr_v4->log_section[j].section_size_sectors, + (uint64_t)section_size_bytes, (uint64_t)log_size); + } else { + if (verbose) + fprintf(stderr, "%s: break, total size = 0x%"PRIx64"\n", __func__, (uint64_t)log_size); + break; } } + } else { + log_size = cap_dui_length_v4; } - else if ((log_hdr->hdr_version & 0xFF) == 0x04) { - __s64 log_size = 0; - __u64 curr_data_offset = 0; - struct wdc_dui_log_hdr_v4 *log_hdr_v4; - log_hdr_v4 = (struct wdc_dui_log_hdr_v4 *)log_hdr; - __s64 xfer_size_long = (__s64)xfer_size; - __s64 section_size_bytes = 0; - - cap_dui_length_v4 = le64_to_cpu(log_hdr_v4->log_size_sectors) * WDC_NVME_SN730_SECTOR_SIZE; - - if (verbose) { - fprintf(stderr, "INFO : WDC : Capture V4 Device Unit Info log, data area = %d\n", data_area); - fprintf(stderr, "INFO : WDC : DUI Header Version = 0x%x\n", log_hdr_v4->hdr_version); - fprintf(stderr, "INFO : WDC : DUI Product ID = 0x%x/%c\n", log_hdr_v4->product_id, log_hdr_v4->product_id); - fprintf(stderr, "INFO : WDC : DUI log size sectors = 0x%x\n", log_hdr_v4->log_size_sectors); - fprintf(stderr, "INFO : WDC : DUI cap_dui_length = 0x%"PRIx64"\n", (uint64_t)cap_dui_length_v4); - } - if (cap_dui_length_v4 == 0) { - fprintf(stderr, "INFO : WDC : Capture V4 Device Unit Info log is empty\n"); - } else { - /* parse log header for all sections up to specified data area inclusively */ - if (data_area != WDC_NVME_DUI_MAX_DATA_AREA) { - for(j = 0; j < WDC_NVME_DUI_MAX_SECTION; j++) { - if (log_hdr_v4->log_section[j].data_area_id <= data_area && - log_hdr_v4->log_section[j].data_area_id != 0) { - section_size_bytes = ((__s64)log_hdr_v4->log_section[j].section_size_sectors * WDC_NVME_SN730_SECTOR_SIZE); - log_size += section_size_bytes; - if (verbose) - fprintf(stderr, "%s: Data area ID %d : section size 0x%x sectors, section size 0x%"PRIx64" bytes, total size = 0x%"PRIx64"\n", - __func__, log_hdr_v4->log_section[j].data_area_id, log_hdr_v4->log_section[j].section_size_sectors, (uint64_t)section_size_bytes, - (uint64_t)log_size); - } - else { - if (verbose) - fprintf(stderr, "%s: break, total size = 0x%"PRIx64"\n", __func__, (uint64_t)log_size); - break; - } - } - } else - log_size = cap_dui_length_v4; + *total_size = log_size; - total_size = log_size; + if (offset >= *total_size) { + fprintf(stderr, + "%s: INFO: WDC: Offset 0x%"PRIx64" exceeds total size 0x%"PRIx64", no data retrieved\n", + __func__, (uint64_t)offset, (uint64_t)*total_size); + return -1; + } - if (offset >= total_size) { - fprintf(stderr, "%s: INFO : WDC : Offset 0x%"PRIx64" exceeds total size 0x%"PRIx64", no data retrieved\n", - __func__, (uint64_t)offset, (uint64_t)total_size); - goto out; - } + dump_data = (__u8 *)malloc(sizeof(__u8) * xfer_size_long); + if (!dump_data) { + fprintf(stderr, "%s: ERROR: dump data V4 malloc failed : status %s, size = 0x%x\n", + __func__, strerror(errno), (unsigned int)xfer_size_long); + return -1; + } + memset(dump_data, 0, sizeof(__u8) * xfer_size_long); - dump_data = (__u8 *) malloc(sizeof (__u8) * xfer_size_long); - if (dump_data == NULL) { - fprintf(stderr, "%s: ERROR : dump data V4 malloc failed : status %s, size = 0x%x\n", - __func__, strerror(errno), (unsigned int)xfer_size_long); - ret = -1; - goto out; - } - memset(dump_data, 0, sizeof (__u8) * xfer_size_long); - - output = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0666); - if (output < 0) { - fprintf(stderr, "%s: Failed to open output file %s: %s!\n", - __func__, file, strerror(errno)); - ret = output; - goto free_mem; - } + output = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (output < 0) { + fprintf(stderr, "%s: Failed to open output file %s: %s!\n", __func__, file, + strerror(errno)); + free(dump_data); + return output; + } - curr_data_offset = 0; + curr_data_offset = 0; - if (file_size != 0) { - /* Write the DUI data based on the passed in file size */ - if ((offset + file_size) > total_size) - log_size = min((total_size - offset), file_size); - else - log_size = min(total_size, file_size); + if (file_size) { + /* Write the DUI data based on the passed in file size */ + if ((offset + file_size) > *total_size) + log_size = min((*total_size - offset), file_size); + else + log_size = min(*total_size, file_size); - if (verbose) - fprintf(stderr, "%s: INFO : WDC : Offset 0x%"PRIx64", file size 0x%"PRIx64", total size 0x%"PRIx64", log size 0x%"PRIx64"\n", - __func__, (uint64_t)offset, (uint64_t)file_size, (uint64_t)total_size, (uint64_t)log_size); + if (verbose) + fprintf(stderr, + "%s: INFO: WDC: Offset 0x%"PRIx64", file size 0x%"PRIx64", total size 0x%"PRIx64", log size 0x%"PRIx64"\n", + __func__, (uint64_t)offset, (uint64_t)file_size, + (uint64_t)*total_size, (uint64_t)log_size); - curr_data_offset = offset; + curr_data_offset = offset; + } - } + i = 0; + buffer_addr = dump_data; - i = 0; - buffer_addr = dump_data; + for (; log_size > 0; log_size -= xfer_size_long) { + xfer_size_long = min(xfer_size_long, log_size); - for(; log_size > 0; log_size -= xfer_size_long) { - xfer_size_long = min(xfer_size_long, log_size); + if (log_size <= xfer_size_long) + last_xfer = true; - if (log_size <= xfer_size_long) - last_xfer = true; + ret = wdc_dump_dui_data_v2(fd, (__u32)xfer_size_long, curr_data_offset, buffer_addr, last_xfer); + if (ret) { + fprintf(stderr, + "%s: ERROR: WDC: Get chunk %d, size = 0x%"PRIx64", offset = 0x%"PRIx64", addr = %p\n", + __func__, i, (uint64_t)log_size, (uint64_t)curr_data_offset, + buffer_addr); + fprintf(stderr, "%s: ERROR: WDC:", __func__); + nvme_show_status(ret); + break; + } - ret = wdc_dump_dui_data_v2(fd, (__u32)xfer_size_long, curr_data_offset, buffer_addr, last_xfer); - if (ret != 0) { - fprintf(stderr, "%s: ERROR : WDC : Get chunk %d, size = 0x%"PRIx64", offset = 0x%"PRIx64", addr = %p\n", - __func__, i, (uint64_t)log_size, (uint64_t)curr_data_offset, buffer_addr); - fprintf(stderr, "%s: ERROR : WDC :", __func__); - nvme_show_status(ret); - break; - } + /* write the dump data into the file */ + err = write(output, (void *)buffer_addr, xfer_size_long); + if (err != xfer_size_long) { + fprintf(stderr, + "%s: ERROR: WDC: Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size_long = 0x%"PRIx64"\n", + __func__, i, err, (uint64_t)xfer_size_long); + ret = -1; + goto free_mem; + } - /* write the dump data into the file */ - err = write(output, (void *)buffer_addr, xfer_size_long); - if (err != xfer_size_long) { - fprintf(stderr, "%s: ERROR : WDC : Failed to flush DUI data to file! chunk %d, err = 0x%x, xfer_size_long = 0x%"PRIx64"\n", - __func__, i, err, (uint64_t)xfer_size_long); - goto free_mem; - } + curr_data_offset += xfer_size_long; + i++; + } - curr_data_offset += xfer_size_long; - i++; - } - } +free_mem: + close(output); + free(dump_data); + return ret; +} + +static int wdc_do_cap_dui(int fd, char *file, __u32 xfer_size, int data_area, int verbose, + __u64 file_size, __u64 offset) +{ + int ret = 0; + __u32 dui_log_hdr_size = WDC_NVME_CAP_DUI_HEADER_SIZE; + struct wdc_dui_log_hdr *log_hdr; + __s64 total_size = 0; + bool last_xfer = false; + + log_hdr = (struct wdc_dui_log_hdr *)malloc(dui_log_hdr_size); + if (!log_hdr) { + fprintf(stderr, "%s: ERROR: log header malloc failed : status %s, size 0x%x\n", + __func__, strerror(errno), dui_log_hdr_size); + return -1; + } + memset(log_hdr, 0, dui_log_hdr_size); + + /* get the dui telemetry and log headers */ + ret = wdc_dump_dui_data(fd, WDC_NVME_CAP_DUI_HEADER_SIZE, 0x00, (__u8 *)log_hdr, last_xfer); + if (ret) { + fprintf(stderr, "%s: ERROR: WDC: Get DUI headers failed\n", __func__); + fprintf(stderr, "%s: ERROR: WDC: ", __func__); + nvme_show_status(ret); + goto out; } - else { - fprintf(stderr, "INFO : WDC : Unsupported header version = 0x%x\n", log_hdr->hdr_version); - goto out; + + /* Check the Log Header version */ + if ((log_hdr->hdr_version & 0xFF) == 0x00 || (log_hdr->hdr_version & 0xFF) == 0x01) { + ret = wdc_do_cap_dui_v1(fd, file, xfer_size, data_area, verbose, log_hdr, + &total_size); + if (ret) + goto out; + } else if ((log_hdr->hdr_version & 0xFF) == 0x02 || + (log_hdr->hdr_version & 0xFF) == 0x03) { + /* Process Version 2 or 3 header */ + ret = wdc_do_cap_dui_v2_v3(fd, file, xfer_size, data_area, verbose, log_hdr, + &total_size, file_size, offset); + if (ret) + goto out; + } else if ((log_hdr->hdr_version & 0xFF) == 0x04) { + ret = wdc_do_cap_dui_v4(fd, file, xfer_size, data_area, verbose, log_hdr, + &total_size, file_size, offset); + if (ret) + goto out; + } else { + fprintf(stderr, "INFO: WDC: Unsupported header version = 0x%x\n", + log_hdr->hdr_version); + goto out; } nvme_show_status(ret); if (verbose) - fprintf(stderr, "INFO : WDC : Capture Device Unit Info log, length = 0x%"PRIx64"\n", (uint64_t)total_size); + fprintf(stderr, "INFO: WDC: Capture Device Unit Info log, length = 0x%"PRIx64"\n", + (uint64_t)total_size); - free_mem: - close(output); - free(dump_data); - - out: +out: free(log_hdr); return ret; } @@ -3019,18 +3111,18 @@ static int wdc_cap_diag(int argc, char **argv, struct command *command, r = nvme_scan(NULL); - if (cfg.file != NULL) + if (cfg.file) strncpy(f, cfg.file, PATH_MAX - 1); - if (cfg.xfer_size != 0) + if (cfg.xfer_size) xfer_size = cfg.xfer_size; ret = wdc_get_serial_name(dev, f, PATH_MAX, "cap_diag"); if (ret) { - fprintf(stderr, "ERROR : WDC: failed to generate file name\n"); + fprintf(stderr, "ERROR: WDC: failed to generate file name\n"); goto out; } - if (cfg.file == NULL) { + if (!cfg.file) { if (strlen(f) > PATH_MAX - 5) { - fprintf(stderr, "ERROR : WDC: file name overflow\n"); + fprintf(stderr, "ERROR: WDC: file name overflow\n"); ret = -1; goto out; } @@ -3041,8 +3133,7 @@ static int wdc_cap_diag(int argc, char **argv, struct command *command, if ((capabilities & WDC_DRIVE_CAP_CAP_DIAG) == WDC_DRIVE_CAP_CAP_DIAG) ret = wdc_do_cap_diag(r, dev, f, xfer_size, 0, 0); else - fprintf(stderr, - "ERROR : WDC: unsupported device for this command\n"); + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); out: nvme_free_tree(r); dev_close(dev); @@ -3055,12 +3146,13 @@ static int wdc_do_get_sn730_log_len(int fd, uint32_t *len_buf, uint32_t subopcod uint32_t *output = NULL; struct nvme_passthru_cmd admin_cmd; - if ((output = (uint32_t*)malloc(sizeof(uint32_t))) == NULL) { - fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); + output = (uint32_t *)malloc(sizeof(uint32_t)); + if (!output) { + fprintf(stderr, "ERROR: WDC: malloc: %s\n", strerror(errno)); return -1; } - memset(output, 0, sizeof (uint32_t)); - memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); + memset(output, 0, sizeof(uint32_t)); + memset(&admin_cmd, 0, sizeof(struct nvme_passthru_cmd)); admin_cmd.data_len = 8; admin_cmd.opcode = SN730_NVME_GET_LOG_OPCODE; @@ -3069,23 +3161,24 @@ static int wdc_do_get_sn730_log_len(int fd, uint32_t *len_buf, uint32_t subopcod admin_cmd.cdw10 = SN730_LOG_CHUNK_SIZE / 4; ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); - if (ret == 0) + if (!ret) *len_buf = *output; free(output); return ret; } -static int wdc_do_get_sn730_log(int fd, void * log_buf, uint32_t offset, uint32_t subopcode) +static int wdc_do_get_sn730_log(int fd, void *log_buf, uint32_t offset, uint32_t subopcode) { int ret; uint8_t *output = NULL; struct nvme_passthru_cmd admin_cmd; - if ((output = (uint8_t*)calloc(SN730_LOG_CHUNK_SIZE, sizeof(uint8_t))) == NULL) { - fprintf(stderr, "ERROR : WDC : calloc : %s\n", strerror(errno)); + output = (uint8_t *)calloc(SN730_LOG_CHUNK_SIZE, sizeof(uint8_t)); + if (!output) { + fprintf(stderr, "ERROR: WDC: calloc: %s\n", strerror(errno)); return -1; } - memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); + memset(&admin_cmd, 0, sizeof(struct nvme_passthru_cmd)); admin_cmd.data_len = SN730_LOG_CHUNK_SIZE; admin_cmd.opcode = SN730_NVME_GET_LOG_OPCODE; admin_cmd.addr = (uintptr_t)output; @@ -3099,15 +3192,16 @@ static int wdc_do_get_sn730_log(int fd, void * log_buf, uint32_t offset, uint32_ return ret; } -static int get_sn730_log_chunks(int fd, uint8_t* log_buf, uint32_t log_len, uint32_t subopcode) +static int get_sn730_log_chunks(int fd, uint8_t *log_buf, uint32_t log_len, uint32_t subopcode) { int ret = 0; - uint8_t* chunk_buf = NULL; + uint8_t *chunk_buf = NULL; int remaining = log_len; int curr_offset = 0; - if ((chunk_buf = (uint8_t*) malloc(sizeof (uint8_t) * SN730_LOG_CHUNK_SIZE)) == NULL) { - fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); + chunk_buf = (uint8_t *)malloc(sizeof(uint8_t) * SN730_LOG_CHUNK_SIZE); + if (!chunk_buf) { + fprintf(stderr, "ERROR: WDC: malloc: %s\n", strerror(errno)); ret = -1; goto out; } @@ -3125,59 +3219,59 @@ static int get_sn730_log_chunks(int fd, uint8_t* log_buf, uint32_t log_len, uint } remaining -= SN730_LOG_CHUNK_SIZE; curr_offset += 1; - } else + } else { goto out; + } } out: free(chunk_buf); return ret; } -static int wdc_do_sn730_get_and_tar(int fd, char * outputName) +static int wdc_do_sn730_get_and_tar(int fd, char *outputName) { int ret = 0; void *retPtr; - uint8_t* full_log_buf = NULL; - uint8_t* key_log_buf = NULL; - uint8_t* core_dump_log_buf = NULL; - uint8_t* extended_log_buf = NULL; + uint8_t *full_log_buf = NULL; + uint8_t *key_log_buf = NULL; + uint8_t *core_dump_log_buf = NULL; + uint8_t *extended_log_buf = NULL; uint32_t full_log_len = 0; uint32_t key_log_len = 0; uint32_t core_dump_log_len = 0; uint32_t extended_log_len = 0; - tarfile_metadata* tarInfo = NULL; + struct tarfile_metadata *tarInfo = NULL; - tarInfo = (struct tarfile_metadata*) malloc(sizeof(tarfile_metadata)); - if (tarInfo == NULL) { - fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); + tarInfo = (struct tarfile_metadata *)malloc(sizeof(struct tarfile_metadata)); + if (!tarInfo) { + fprintf(stderr, "ERROR: WDC: malloc: %s\n", strerror(errno)); ret = -1; goto free_buf; } - memset(tarInfo, 0, sizeof(tarfile_metadata)); + memset(tarInfo, 0, sizeof(struct tarfile_metadata)); - /* Create Logs directory */ + /* Create Logs directory */ wdc_UtilsGetTime(&tarInfo->timeInfo); memset(tarInfo->timeString, 0, sizeof(tarInfo->timeString)); - wdc_UtilsSnprintf((char*)tarInfo->timeString, MAX_PATH_LEN, "%02u%02u%02u_%02u%02u%02u", + wdc_UtilsSnprintf((char *)tarInfo->timeString, MAX_PATH_LEN, "%02u%02u%02u_%02u%02u%02u", tarInfo->timeInfo.year, tarInfo->timeInfo.month, tarInfo->timeInfo.dayOfMonth, tarInfo->timeInfo.hour, tarInfo->timeInfo.minute, tarInfo->timeInfo.second); - wdc_UtilsSnprintf((char*)tarInfo->bufferFolderName, MAX_PATH_LEN, "%s", - (char*)outputName); + wdc_UtilsSnprintf((char *)tarInfo->bufferFolderName, MAX_PATH_LEN, "%s", + (char *)outputName); - retPtr = getcwd((char*)tarInfo->currDir, MAX_PATH_LEN); - if (retPtr != NULL) - wdc_UtilsSnprintf((char*)tarInfo->bufferFolderPath, MAX_PATH_LEN, "%s%s%s", + retPtr = getcwd((char *)tarInfo->currDir, MAX_PATH_LEN); + if (retPtr) { + wdc_UtilsSnprintf((char *)tarInfo->bufferFolderPath, MAX_PATH_LEN, "%s%s%s", (char *)tarInfo->currDir, WDC_DE_PATH_SEPARATOR, (char *)tarInfo->bufferFolderName); - else { - fprintf(stderr, "ERROR : WDC : get current working directory failed\n"); + } else { + fprintf(stderr, "ERROR: WDC: get current working directory failed\n"); goto free_buf; } - ret = wdc_UtilsCreateDir((char*)tarInfo->bufferFolderPath); - if (ret) - { - fprintf(stderr, "ERROR : WDC : create directory failed, ret = %d, dir = %s\n", ret, tarInfo->bufferFolderPath); + ret = wdc_UtilsCreateDir((char *)tarInfo->bufferFolderPath); + if (ret) { + fprintf(stderr, "ERROR: WDC: create directory failed, ret = %d, dir = %s\n", ret, tarInfo->bufferFolderPath); goto free_buf; } else { fprintf(stderr, "Stored log files in directory: %s\n", tarInfo->bufferFolderPath); @@ -3204,13 +3298,13 @@ static int wdc_do_sn730_get_and_tar(int fd, char * outputName) goto free_buf; } - full_log_buf = (uint8_t*) calloc(full_log_len, sizeof (uint8_t)); - key_log_buf = (uint8_t*) calloc(key_log_len, sizeof (uint8_t)); - core_dump_log_buf = (uint8_t*) calloc(core_dump_log_len, sizeof (uint8_t)); - extended_log_buf = (uint8_t*) calloc(extended_log_len, sizeof (uint8_t)); + full_log_buf = (uint8_t *) calloc(full_log_len, sizeof(uint8_t)); + key_log_buf = (uint8_t *) calloc(key_log_len, sizeof(uint8_t)); + core_dump_log_buf = (uint8_t *) calloc(core_dump_log_len, sizeof(uint8_t)); + extended_log_buf = (uint8_t *) calloc(extended_log_len, sizeof(uint8_t)); if (!full_log_buf || !key_log_buf || !core_dump_log_buf || !extended_log_buf) { - fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); + fprintf(stderr, "ERROR: WDC: malloc: %s\n", strerror(errno)); ret = -1; goto free_buf; } @@ -3244,31 +3338,31 @@ static int wdc_do_sn730_get_and_tar(int fd, char * outputName) } /* Write log files */ - wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN, "%s%s%s_%s.bin", (char*)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR, - "full_log", (char*)tarInfo->timeString); - wdc_WriteToFile(tarInfo->fileName, (char*)full_log_buf, full_log_len); + wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN, "%s%s%s_%s.bin", (char *)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR, + "full_log", (char *)tarInfo->timeString); + wdc_WriteToFile(tarInfo->fileName, (char *)full_log_buf, full_log_len); - wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN, "%s%s%s_%s.bin", (char*)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR, - "key_log", (char*)tarInfo->timeString); - wdc_WriteToFile(tarInfo->fileName, (char*)key_log_buf, key_log_len); + wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN, "%s%s%s_%s.bin", (char *)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR, + "key_log", (char *)tarInfo->timeString); + wdc_WriteToFile(tarInfo->fileName, (char *)key_log_buf, key_log_len); - wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN, "%s%s%s_%s.bin", (char*)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR, - "core_dump_log", (char*)tarInfo->timeString); - wdc_WriteToFile(tarInfo->fileName, (char*)core_dump_log_buf, core_dump_log_len); + wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN, "%s%s%s_%s.bin", (char *)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR, + "core_dump_log", (char *)tarInfo->timeString); + wdc_WriteToFile(tarInfo->fileName, (char *)core_dump_log_buf, core_dump_log_len); - wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN, "%s%s%s_%s.bin", (char*)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR, - "extended_log", (char*)tarInfo->timeString); - wdc_WriteToFile(tarInfo->fileName, (char*)extended_log_buf, extended_log_len); + wdc_UtilsSnprintf(tarInfo->fileName, MAX_PATH_LEN, "%s%s%s_%s.bin", (char *)tarInfo->bufferFolderPath, WDC_DE_PATH_SEPARATOR, + "extended_log", (char *)tarInfo->timeString); + wdc_WriteToFile(tarInfo->fileName, (char *)extended_log_buf, extended_log_len); /* Tar the log directory */ - wdc_UtilsSnprintf(tarInfo->tarFileName, sizeof(tarInfo->tarFileName), "%s%s", (char*)tarInfo->bufferFolderPath, WDC_DE_TAR_FILE_EXTN); - wdc_UtilsSnprintf(tarInfo->tarFiles, sizeof(tarInfo->tarFiles), "%s%s%s", (char*)tarInfo->bufferFolderName, WDC_DE_PATH_SEPARATOR, WDC_DE_TAR_FILES); - wdc_UtilsSnprintf(tarInfo->tarCmd, sizeof(tarInfo->tarCmd), "%s %s %s", WDC_DE_TAR_CMD, (char*)tarInfo->tarFileName, (char*)tarInfo->tarFiles); + wdc_UtilsSnprintf(tarInfo->tarFileName, sizeof(tarInfo->tarFileName), "%s%s", (char *)tarInfo->bufferFolderPath, WDC_DE_TAR_FILE_EXTN); + wdc_UtilsSnprintf(tarInfo->tarFiles, sizeof(tarInfo->tarFiles), "%s%s%s", (char *)tarInfo->bufferFolderName, WDC_DE_PATH_SEPARATOR, WDC_DE_TAR_FILES); + wdc_UtilsSnprintf(tarInfo->tarCmd, sizeof(tarInfo->tarCmd), "%s %s %s", WDC_DE_TAR_CMD, (char *)tarInfo->tarFileName, (char *)tarInfo->tarFiles); ret = system(tarInfo->tarCmd); if (ret) - fprintf(stderr, "ERROR : WDC : Tar of log data failed, ret = %d\n", ret); + fprintf(stderr, "ERROR: WDC: Tar of log data failed, ret = %d\n", ret); free_buf: free(tarInfo); @@ -3280,7 +3374,7 @@ free_buf: } static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command, - struct plugin *plugin) + struct plugin *plugin) { char *desc = "Internal Firmware Log."; char *file = "Output file pathname."; @@ -3340,20 +3434,20 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command if (!wdc_check_device(r, dev)) goto out; - if (cfg.xfer_size != 0) + if (cfg.xfer_size) { xfer_size = cfg.xfer_size; - else { - fprintf(stderr, "ERROR : WDC : Invalid length\n"); + } else { + fprintf(stderr, "ERROR: WDC: Invalid length\n"); goto out; } - if (cfg.file != NULL) { + if (cfg.file) { int verify_file; /* verify the passed in file name and path is valid before getting the dump data */ verify_file = open(cfg.file, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (verify_file < 0) { - fprintf(stderr, "ERROR : WDC: open : %s\n", strerror(errno)); + fprintf(stderr, "ERROR: WDC: open: %s\n", strerror(errno)); goto out; } close(verify_file); @@ -3361,21 +3455,21 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command } else { wdc_UtilsGetTime(&timeInfo); memset(timeStamp, 0, sizeof(timeStamp)); - wdc_UtilsSnprintf((char*)timeStamp, MAX_PATH_LEN, "%02u%02u%02u_%02u%02u%02u", + wdc_UtilsSnprintf((char *)timeStamp, MAX_PATH_LEN, "%02u%02u%02u_%02u%02u%02u", timeInfo.year, timeInfo.month, timeInfo.dayOfMonth, timeInfo.hour, timeInfo.minute, timeInfo.second); - snprintf(fileSuffix, PATH_MAX, "_internal_fw_log_%s", (char*)timeStamp); + snprintf(fileSuffix, PATH_MAX, "_internal_fw_log_%s", (char *)timeStamp); ret = wdc_get_serial_name(dev, f, PATH_MAX, fileSuffix); if (ret) { - fprintf(stderr, "ERROR : WDC: failed to generate file name\n"); + fprintf(stderr, "ERROR: WDC: failed to generate file name\n"); goto out; } } - if (cfg.file == NULL) { + if (!cfg.file) { if (strlen(f) > PATH_MAX - 5) { - fprintf(stderr, "ERROR : WDC: file name overflow\n"); + fprintf(stderr, "ERROR: WDC: file name overflow\n"); ret = -1; goto out; } @@ -3385,67 +3479,63 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command if (cfg.data_area) { if (cfg.data_area > 5 || cfg.data_area < 1) { - fprintf(stderr, "ERROR : WDC: Data area must be 1-5\n"); + fprintf(stderr, "ERROR: WDC: Data area must be 1-5\n"); ret = -1; goto out; } } - if ((cfg.type == NULL) || - (!strcmp(cfg.type, "NONE")) || - (!strcmp(cfg.type, "none"))) { + if (!cfg.type || !strcmp(cfg.type, "NONE") || !strcmp(cfg.type, "none")) { telemetry_type = WDC_TELEMETRY_TYPE_NONE; data_area = 0; - } else if ((!strcmp(cfg.type, "HOST")) || - (!strcmp(cfg.type, "host"))) { + } else if (!strcmp(cfg.type, "HOST") || !strcmp(cfg.type, "host")) { telemetry_type = WDC_TELEMETRY_TYPE_HOST; telemetry_data_area = cfg.data_area; - } else if ((!strcmp(cfg.type, "CONTROLLER")) || - (!strcmp(cfg.type, "controller"))) { + } else if (!strcmp(cfg.type, "CONTROLLER") || !strcmp(cfg.type, "controller")) { telemetry_type = WDC_TELEMETRY_TYPE_CONTROLLER; telemetry_data_area = cfg.data_area; } else { - fprintf(stderr, "ERROR : WDC: Invalid type - Must be NONE, HOST or CONTROLLER\n"); + fprintf(stderr, "ERROR: WDC: Invalid type - Must be NONE, HOST or CONTROLLER\n"); ret = -1; goto out; } capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_INTERNAL_LOG) == WDC_DRIVE_CAP_INTERNAL_LOG) { - if (telemetry_data_area == 0) + if (!telemetry_data_area) telemetry_data_area = 3; /* Set the default DA to 3 if not specified */ ret = wdc_do_cap_diag(r, dev, f, xfer_size, - telemetry_type, telemetry_data_area); + telemetry_type, telemetry_data_area); goto out; } if ((capabilities & WDC_DRIVE_CAP_DUI) == WDC_DRIVE_CAP_DUI) { if ((telemetry_type == WDC_TELEMETRY_TYPE_HOST) || (telemetry_type == WDC_TELEMETRY_TYPE_CONTROLLER)) { - if (telemetry_data_area == 0) + if (!telemetry_data_area) telemetry_data_area = 3; /* Set the default DA to 3 if not specified */ /* Get the desired telemetry log page */ ret = wdc_do_cap_telemetry_log(dev, f, xfer_size, telemetry_type, telemetry_data_area); goto out; } else { - if (cfg.data_area == 0) + if (!cfg.data_area) cfg.data_area = 1; /* FW requirement - xfer size must be 256k for data area 4 */ if (cfg.data_area >= 4) xfer_size = 0x40000; ret = wdc_do_cap_dui(dev_fd(dev), f, xfer_size, - cfg.data_area, - cfg.verbose, cfg.file_size, - cfg.offset); + cfg.data_area, + cfg.verbose, cfg.file_size, + cfg.offset); goto out; } } - if ((capabilities & WDC_DRIVE_CAP_DUI_DATA) == WDC_DRIVE_CAP_DUI_DATA){ + if ((capabilities & WDC_DRIVE_CAP_DUI_DATA) == WDC_DRIVE_CAP_DUI_DATA) { if ((telemetry_type == WDC_TELEMETRY_TYPE_HOST) || (telemetry_type == WDC_TELEMETRY_TYPE_CONTROLLER)) { - if (telemetry_data_area == 0) + if (!telemetry_data_area) telemetry_data_area = 3; /* Set the default DA to 3 if not specified */ /* Get the desired telemetry log page */ ret = wdc_do_cap_telemetry_log(dev, f, xfer_size, @@ -3458,10 +3548,10 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command goto out; } } - if ((capabilities & WDC_SN730B_CAP_VUC_LOG) == WDC_SN730B_CAP_VUC_LOG) + if ((capabilities & WDC_SN730B_CAP_VUC_LOG) == WDC_SN730B_CAP_VUC_LOG) { ret = wdc_do_sn730_get_and_tar(dev_fd(dev), f); - else { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + } else { + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; } out: @@ -3515,18 +3605,18 @@ static int wdc_do_crash_dump(struct nvme_dev *dev, char *file, int type) if (ret == -1) { if (type == WDC_NVME_PFAIL_DUMP_TYPE) - fprintf(stderr, "INFO : WDC: Pfail dump get size failed\n"); + fprintf(stderr, "INFO: WDC: Pfail dump get size failed\n"); else - fprintf(stderr, "INFO : WDC: Crash dump get size failed\n"); + fprintf(stderr, "INFO: WDC: Crash dump get size failed\n"); return -1; } - if (crash_dump_length == 0) { + if (!crash_dump_length) { if (type == WDC_NVME_PFAIL_DUMP_TYPE) - fprintf(stderr, "INFO : WDC: Pfail dump is empty\n"); + fprintf(stderr, "INFO: WDC: Pfail dump is empty\n"); else - fprintf(stderr, "INFO : WDC: Crash dump is empty\n"); + fprintf(stderr, "INFO: WDC: Crash dump is empty\n"); } else { ret = wdc_do_dump(dev, opcode, @@ -3535,7 +3625,7 @@ static int wdc_do_crash_dump(struct nvme_dev *dev, char *file, int type) file, crash_dump_length); - if (ret == 0) + if (!ret) ret = wdc_do_clear_dump(dev, WDC_NVME_CLEAR_DUMP_OPCODE, cdw12_clear); } @@ -3548,9 +3638,8 @@ static int wdc_crash_dump(struct nvme_dev *dev, char *file, int type) const char *dump_type; int ret; - if (file != NULL) { + if (file) strncpy(f, file, PATH_MAX - 1); - } if (type == WDC_NVME_PFAIL_DUMP_TYPE) dump_type = "_pfail_dump"; @@ -3559,7 +3648,7 @@ static int wdc_crash_dump(struct nvme_dev *dev, char *file, int type) ret = wdc_get_serial_name(dev, f, PATH_MAX, dump_type); if (ret) - fprintf(stderr, "ERROR : WDC : failed to generate file name\n"); + fprintf(stderr, "ERROR: WDC: failed to generate file name\n"); else ret = wdc_do_crash_dump(dev, f, type); return ret; @@ -3577,18 +3666,17 @@ static int wdc_do_drive_log(struct nvme_dev *dev, char *file) (WDC_NVME_DRIVE_LOG_SIZE_SUBCMD << WDC_NVME_SUBCMD_SHIFT | WDC_NVME_DRIVE_LOG_SIZE_CMD), &drive_log_length); - if (ret == -1) { + if (ret == -1) return -1; - } - drive_log_data = (__u8 *) malloc(sizeof (__u8) * drive_log_length); - if (drive_log_data == NULL) { - fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); + drive_log_data = (__u8 *)malloc(sizeof(__u8) * drive_log_length); + if (!drive_log_data) { + fprintf(stderr, "ERROR: WDC: malloc: %s\n", strerror(errno)); return -1; } - memset(drive_log_data, 0, sizeof (__u8) * drive_log_length); - memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); + memset(drive_log_data, 0, sizeof(__u8) * drive_log_length); + memset(&admin_cmd, 0, sizeof(struct nvme_passthru_cmd)); admin_cmd.opcode = WDC_NVME_DRIVE_LOG_OPCODE; admin_cmd.addr = (__u64)(uintptr_t)drive_log_data; admin_cmd.data_len = drive_log_length; @@ -3598,9 +3686,8 @@ static int wdc_do_drive_log(struct nvme_dev *dev, char *file) ret = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); nvme_show_status(ret); - if (ret == 0) { + if (!ret) ret = wdc_create_log_file(file, drive_log_data, drive_log_length); - } free(drive_log_data); return ret; } @@ -3641,16 +3728,15 @@ static int wdc_drive_log(int argc, char **argv, struct command *command, } capabilities = wdc_get_drive_capabilities(r, dev); - if ((capabilities & WDC_DRIVE_CAP_DRIVE_LOG) == 0) { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + if (!(capabilities & WDC_DRIVE_CAP_DRIVE_LOG)) { + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; } else { - if (cfg.file != NULL) { + if (cfg.file) strncpy(f, cfg.file, PATH_MAX - 1); - } ret = wdc_get_serial_name(dev, f, PATH_MAX, "drive_log"); if (ret) - fprintf(stderr, "ERROR : WDC : failed to generate file name\n"); + fprintf(stderr, "ERROR: WDC: failed to generate file name\n"); else ret = wdc_do_drive_log(dev, f); } @@ -3697,14 +3783,13 @@ static int wdc_get_crash_dump(int argc, char **argv, struct command *command, capabilities = wdc_get_drive_capabilities(r, dev); - if ((capabilities & WDC_DRIVE_CAP_CRASH_DUMP) == 0) { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + if (!(capabilities & WDC_DRIVE_CAP_CRASH_DUMP)) { + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; } else { ret = wdc_crash_dump(dev, cfg.file, WDC_NVME_CRASH_DUMP_TYPE); - if (ret != 0) { - fprintf(stderr, "ERROR : WDC : failed to read crash dump\n"); - } + if (ret) + fprintf(stderr, "ERROR: WDC: failed to read crash dump\n"); } nvme_free_tree(r); dev_close(dev); @@ -3746,14 +3831,13 @@ static int wdc_get_pfail_dump(int argc, char **argv, struct command *command, } capabilities = wdc_get_drive_capabilities(r, dev); - if ((capabilities & WDC_DRIVE_CAP_PFAIL_DUMP) == 0) { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + if (!(capabilities & WDC_DRIVE_CAP_PFAIL_DUMP)) { + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; } else { ret = wdc_crash_dump(dev, cfg.file, WDC_NVME_PFAIL_DUMP_TYPE); - if (ret != 0) { - fprintf(stderr, "ERROR : WDC : failed to read pfail crash dump\n"); - } + if (ret) + fprintf(stderr, "ERROR: WDC: failed to read pfail crash dump\n"); } nvme_free_tree(r); dev_close(dev); @@ -3770,7 +3854,7 @@ static void wdc_do_id_ctrl(__u8 *vs, struct json_object *root) if (root) json_object_add_value_string(root, "wdc vsn", strlen(vsn) > 1 ? vsn : "NULL"); else - printf("wdc vsn : %s\n", strlen(vsn) > 1 ? vsn : "NULL"); + printf("wdc vsn: %s\n", strlen(vsn) > 1 ? vsn : "NULL"); } static int wdc_id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -3778,7 +3862,7 @@ static int wdc_id_ctrl(int argc, char **argv, struct command *cmd, struct plugin return __id_ctrl(argc, argv, cmd, plugin, wdc_do_id_ctrl); } -static const char* wdc_purge_mon_status_to_string(__u32 status) +static const char *wdc_purge_mon_status_to_string(__u32 status) { const char *str; @@ -3793,14 +3877,12 @@ static const char* wdc_purge_mon_status_to_string(__u32 status) str = "Purge State Busy."; break; case WDC_NVME_PURGE_STATE_REQ_PWR_CYC: - str = "Purge Operation resulted in an error that requires " - "power cycle."; + str = "Purge Operation resulted in an error that requires power cycle."; break; case WDC_NVME_PURGE_STATE_PWR_CYC_PURGE: - str = "The previous purge operation was interrupted by a power " - "cycle\nor reset interruption. Other commands may be " - "rejected until\nPurge Execute is issued and " - "completed."; + str = "The previous purge operation was interrupted by a power cycle\n" + "or reset interruption. Other commands may be rejected until\n" + "Purge Execute is issued and completed."; break; default: str = "Unknown."; @@ -3836,12 +3918,12 @@ static int wdc_purge(int argc, char **argv, } capabilities = wdc_get_drive_capabilities(r, dev); - if((capabilities & WDC_DRIVE_CAP_PURGE) == 0) { + if (!(capabilities & WDC_DRIVE_CAP_PURGE)) { ret = -1; - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); } else { err_str = ""; - memset(&admin_cmd, 0, sizeof (admin_cmd)); + memset(&admin_cmd, 0, sizeof(admin_cmd)); admin_cmd.opcode = WDC_NVME_PURGE_CMD_OPCODE; ret = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, @@ -3849,14 +3931,13 @@ static int wdc_purge(int argc, char **argv, if (ret > 0) { switch (ret) { case WDC_NVME_PURGE_CMD_SEQ_ERR: - err_str = "ERROR : WDC : Cannot execute purge, " - "Purge operation is in progress.\n"; + err_str = "ERROR: WDC: Cannot execute purge, Purge operation is in progress.\n"; break; case WDC_NVME_PURGE_INT_DEV_ERR: - err_str = "ERROR : WDC : Internal Device Error.\n"; + err_str = "ERROR: WDC: Internal Device Error.\n"; break; default: - err_str = "ERROR : WDC\n"; + err_str = "ERROR: WDC\n"; } } @@ -3897,12 +3978,12 @@ static int wdc_purge_monitor(int argc, char **argv, } capabilities = wdc_get_drive_capabilities(r, dev); - if((capabilities & WDC_DRIVE_CAP_PURGE) == 0) { + if (!(capabilities & WDC_DRIVE_CAP_PURGE)) { ret = -1; - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); } else { - memset(output, 0, sizeof (output)); - memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); + memset(output, 0, sizeof(output)); + memset(&admin_cmd, 0, sizeof(struct nvme_passthru_cmd)); admin_cmd.opcode = WDC_NVME_PURGE_MONITOR_OPCODE; admin_cmd.addr = (__u64)(uintptr_t)output; admin_cmd.data_len = WDC_NVME_PURGE_MONITOR_DATA_LEN; @@ -3911,7 +3992,7 @@ static int wdc_purge_monitor(int argc, char **argv, ret = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); - if (ret == 0) { + if (!ret) { mon = (struct wdc_nvme_purge_monitor_data *) output; printf("Purge state = 0x%0x\n", admin_cmd.result); printf("%s\n", wdc_purge_mon_status_to_string(admin_cmd.result)); @@ -3932,7 +4013,7 @@ static int wdc_purge_monitor(int argc, char **argv, static void wdc_print_log_normal(struct wdc_ssd_perf_stats *perf) { - printf(" C1 Log Page Performance Statistics :- \n"); + printf(" C1 Log Page Performance Statistics :-\n"); printf(" Host Read Commands %20"PRIu64"\n", le64_to_cpu(perf->hr_cmds)); printf(" Host Read Blocks %20"PRIu64"\n", @@ -3987,9 +4068,8 @@ static void wdc_print_log_normal(struct wdc_ssd_perf_stats *perf) static void wdc_print_log_json(struct wdc_ssd_perf_stats *perf) { - struct json_object *root; + struct json_object *root = json_create_object(); - root = json_create_object(); json_object_add_value_int(root, "Host Read Commands", le64_to_cpu(perf->hr_cmds)); json_object_add_value_int(root, "Host Read Blocks", le64_to_cpu(perf->hr_blks)); json_object_add_value_int(root, "Average Read Size", @@ -4046,7 +4126,7 @@ static void wdc_print_log_json(struct wdc_ssd_perf_stats *perf) static int wdc_print_log(struct wdc_ssd_perf_stats *perf, int fmt) { if (!perf) { - fprintf(stderr, "ERROR : WDC : Invalid buffer to read perf stats\n"); + fprintf(stderr, "ERROR: WDC: Invalid buffer to read perf stats\n"); return -1; } switch (fmt) { @@ -4060,104 +4140,83 @@ static int wdc_print_log(struct wdc_ssd_perf_stats *perf, int fmt) return 0; } -static int wdc_convert_ts(time_t time, char *ts_buf) -{ - struct tm gmTimeInfo; - time_t time_Human, time_ms; - char buf[80]; - - time_Human = time/1000; - time_ms = time % 1000; - - gmtime_r((const time_t *)&time_Human, &gmTimeInfo); - - strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &gmTimeInfo); - sprintf(ts_buf, "%s.%03ld GMT", buf, time_ms); - - return 0; -} - static int wdc_print_latency_monitor_log_normal(struct nvme_dev *dev, struct wdc_ssd_latency_monitor_log *log_data) { - printf("Latency Monitor/C3 Log Page Data \n"); + printf("Latency Monitor/C3 Log Page Data\n"); printf(" Controller : %s\n", dev->name); int err = -1, i, j; struct nvme_id_ctrl ctrl; - char ts_buf[128]; + char ts_buf[128]; err = nvme_identify_ctrl(dev_fd(dev), &ctrl); - if (!err) + if (!err) { printf(" Serial Number: %-.*s\n", (int)sizeof(ctrl.sn), ctrl.sn); - else { - fprintf(stderr, "ERROR : WDC : latency monitor read id ctrl failure, err = %d\n", err); + } else { + fprintf(stderr, "ERROR: WDC: latency monitor read id ctrl failure, err = %d\n", err); return err; } - printf(" Feature Status 0x%x \n", log_data->feature_status); - printf(" Active Bucket Timer %d min \n", 5*le16_to_cpu(log_data->active_bucket_timer)); - printf(" Active Bucket Timer Threshold %d min \n", 5*le16_to_cpu(log_data->active_bucket_timer_threshold)); - printf(" Active Threshold A %d ms \n", 5*(le16_to_cpu(log_data->active_threshold_a+1))); - printf(" Active Threshold B %d ms \n", 5*(le16_to_cpu(log_data->active_threshold_b+1))); - printf(" Active Threshold C %d ms \n", 5*(le16_to_cpu(log_data->active_threshold_c+1))); - printf(" Active Threshold D %d ms \n", 5*(le16_to_cpu(log_data->active_threshold_d+1))); - printf(" Active Latency Config 0x%x \n", le16_to_cpu(log_data->active_latency_config)); - printf(" Active Latency Minimum Window %d ms \n", 100*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 Bucket Counter: Bucket %d %27d %27d %27d \n", - 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 = 3; i >= 0; i--) { - printf(" Active Measured Latency: Bucket %d %27d ms %27d ms %27d ms \n", - 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])); - } + printf(" Feature Status 0x%x\n", log_data->feature_status); + printf(" Active Bucket Timer %d min\n", 5*le16_to_cpu(log_data->active_bucket_timer)); + printf(" Active Bucket Timer Threshold %d min\n", 5*le16_to_cpu(log_data->active_bucket_timer_threshold)); + printf(" Active Threshold A %d ms\n", 5*(le16_to_cpu(log_data->active_threshold_a+1))); + printf(" Active Threshold B %d ms\n", 5*(le16_to_cpu(log_data->active_threshold_b+1))); + printf(" Active Threshold C %d ms\n", 5*(le16_to_cpu(log_data->active_threshold_c+1))); + printf(" Active Threshold D %d ms\n", 5*(le16_to_cpu(log_data->active_threshold_d+1))); + printf(" Active Latency Config 0x%x\n", le16_to_cpu(log_data->active_latency_config)); + printf(" Active Latency Minimum Window %d ms\n", 100*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 Bucket Counter: Bucket %d %27d %27d %27d\n", + 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 = 3; i >= 0; i--) + printf(" Active Measured Latency: Bucket %d %27d ms %27d ms %27d ms\n", + 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 = 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 { - wdc_convert_ts(le64_to_cpu(log_data->active_latency_timestamp[i][j]), ts_buf); - printf("%s ", ts_buf); - } + 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][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++) + printf(" Static Bucket Counter: Bucket %d %27d %27d %27d\n", + 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 = 3; i >= 0; i--) { - printf(" Static Measured Latency: Bucket %d %27d ms %27d ms %27d ms \n", - 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 = 3; i >= 0; i--) + printf(" Static Measured Latency: Bucket %d %27d ms %27d ms %27d ms\n", + 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 = 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 { - wdc_convert_ts(le64_to_cpu(log_data->static_latency_timestamp[i][j]), ts_buf); - printf("%s ", ts_buf); - } + 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"); } @@ -4168,10 +4227,9 @@ static int wdc_print_latency_monitor_log_normal(struct nvme_dev *dev, static void wdc_print_latency_monitor_log_json(struct wdc_ssd_latency_monitor_log *log_data) { int i, j; - char buf[128]; - char *operation[3] = {"Read", "Write", "Trim"}; - struct json_object *root; - root = json_create_object(); + char buf[128]; + char *operation[3] = {"Read", "Write", "Trim"}; + struct json_object *root = json_create_object(); json_object_add_value_int(root, "Feature Status", log_data->feature_status); json_object_add_value_int(root, "Active Bucket Timer", 5*le16_to_cpu(log_data->active_bucket_timer)); @@ -4232,33 +4290,32 @@ static void wdc_print_latency_monitor_log_json(struct wdc_ssd_latency_monitor_lo static void wdc_print_error_rec_log_normal(struct wdc_ocp_c1_error_recovery_log *log_data) { int j; - printf("Error Recovery/C1 Log Page Data \n"); - printf(" Panic Reset Wait Time : 0x%x \n", le16_to_cpu(log_data->panic_reset_wait_time)); - printf(" Panic Reset Action : 0x%x \n", log_data->panic_reset_action); - printf(" Device Recovery Action 1 : 0x%x \n", log_data->dev_recovery_action1); + printf("Error Recovery/C1 Log Page Data\n"); + + printf(" Panic Reset Wait Time : 0x%x\n", le16_to_cpu(log_data->panic_reset_wait_time)); + printf(" Panic Reset Action : 0x%x\n", log_data->panic_reset_action); + printf(" Device Recovery Action 1 : 0x%x\n", log_data->dev_recovery_action1); printf(" Panic ID : 0x%" PRIu64 "\n", le64_to_cpu(log_data->panic_id)); - printf(" Device Capabilities : 0x%x \n", le32_to_cpu(log_data->dev_capabilities)); - printf(" Vendor Specific Recovery Opcode : 0x%x \n", log_data->vs_recovery_opc); - printf(" Vendor Specific Command CDW12 : 0x%x \n", le32_to_cpu(log_data->vs_cmd_cdw12)); - printf(" Vendor Specific Command CDW13 : 0x%x \n", le32_to_cpu(log_data->vs_cmd_cdw13)); + printf(" Device Capabilities : 0x%x\n", le32_to_cpu(log_data->dev_capabilities)); + printf(" Vendor Specific Recovery Opcode : 0x%x\n", log_data->vs_recovery_opc); + printf(" Vendor Specific Command CDW12 : 0x%x\n", le32_to_cpu(log_data->vs_cmd_cdw12)); + printf(" Vendor Specific Command CDW13 : 0x%x\n", le32_to_cpu(log_data->vs_cmd_cdw13)); if (le16_to_cpu(log_data->log_page_version) == WDC_ERROR_REC_LOG_VERSION2) { - printf(" Vendor Specific Command Timeout : 0x%x \n", log_data->vs_cmd_to); - printf(" Device Recovery Action 2 : 0x%x \n", log_data->dev_recovery_action2); - printf(" Device Recovery Action 2 Timeout : 0x%x \n", log_data->dev_recovery_action2_to); + printf(" Vendor Specific Command Timeout : 0x%x\n", log_data->vs_cmd_to); + printf(" Device Recovery Action 2 : 0x%x\n", log_data->dev_recovery_action2); + printf(" Device Recovery Action 2 Timeout : 0x%x\n", log_data->dev_recovery_action2_to); } - printf(" Log Page Version : 0x%x \n", le16_to_cpu(log_data->log_page_version)); + printf(" Log Page Version : 0x%x\n", le16_to_cpu(log_data->log_page_version)); printf(" Log page GUID : 0x"); - for (j = 0; j < WDC_OCP_C1_GUID_LENGTH; j++) { + for (j = 0; j < WDC_OCP_C1_GUID_LENGTH; j++) printf("%x", log_data->log_page_guid[j]); - } printf("\n"); } static void wdc_print_error_rec_log_json(struct wdc_ocp_c1_error_recovery_log *log_data) { - struct json_object *root; - root = json_create_object(); + struct json_object *root = json_create_object(); json_object_add_value_int(root, "Panic Reset Wait Time", le16_to_cpu(log_data->panic_reset_wait_time)); json_object_add_value_int(root, "Panic Reset Action", log_data->panic_reset_wait_time); @@ -4276,8 +4333,10 @@ static void wdc_print_error_rec_log_json(struct wdc_ocp_c1_error_recovery_log *l json_object_add_value_int(root, "Log Page Version", le16_to_cpu(log_data->log_page_version)); char guid[40]; - memset((void*)guid, 0, 40); - sprintf((char*)guid, "0x%"PRIx64"%"PRIx64"",(uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]), + + memset((void *)guid, 0, 40); + sprintf((char *)guid, "0x%"PRIx64"%"PRIx64"", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]), (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0])); json_object_add_value_string(root, "Log page GUID", guid); @@ -4290,34 +4349,32 @@ static void wdc_print_error_rec_log_json(struct wdc_ocp_c1_error_recovery_log *l static void wdc_print_dev_cap_log_normal(struct wdc_ocp_C4_dev_cap_log *log_data) { int j; - printf("Device Capabilities/C4 Log Page Data \n"); - printf(" Number PCIE Ports : 0x%x \n", le16_to_cpu(log_data->num_pcie_ports)); - printf(" Number OOB Management Interfaces : 0x%x \n", le16_to_cpu(log_data->oob_mgmt_support)); - printf(" Write Zeros Command Support : 0x%x \n", le16_to_cpu(log_data->wrt_zeros_support)); - printf(" Sanitize Command Support : 0x%x \n", le16_to_cpu(log_data->sanitize_support)); - printf(" DSM Command Support : 0x%x \n", le16_to_cpu(log_data->dsm_support)); - printf(" Write Uncorr Command Support : 0x%x \n", le16_to_cpu(log_data->wrt_uncor_support)); - printf(" Fused Command Support : 0x%x \n", le16_to_cpu(log_data->fused_support)); - printf(" Minimum DSSD Power State : 0x%x \n", le16_to_cpu(log_data->min_dssd_ps)); + printf("Device Capabilities/C4 Log Page Data\n"); - for (j = 0; j < WDC_OCP_C4_NUM_PS_DESCR; j++) { - printf(" DSSD Power State %d Desriptor : 0x%x \n", j, log_data->dssd_ps_descr[j]); - } + printf(" Number PCIE Ports : 0x%x\n", le16_to_cpu(log_data->num_pcie_ports)); + printf(" Number OOB Management Interfaces : 0x%x\n", le16_to_cpu(log_data->oob_mgmt_support)); + printf(" Write Zeros Command Support : 0x%x\n", le16_to_cpu(log_data->wrt_zeros_support)); + printf(" Sanitize Command Support : 0x%x\n", le16_to_cpu(log_data->sanitize_support)); + printf(" DSM Command Support : 0x%x\n", le16_to_cpu(log_data->dsm_support)); + printf(" Write Uncorr Command Support : 0x%x\n", le16_to_cpu(log_data->wrt_uncor_support)); + printf(" Fused Command Support : 0x%x\n", le16_to_cpu(log_data->fused_support)); + printf(" Minimum DSSD Power State : 0x%x\n", le16_to_cpu(log_data->min_dssd_ps)); - printf(" Log Page Version : 0x%x \n", le16_to_cpu(log_data->log_page_version)); + for (j = 0; j < WDC_OCP_C4_NUM_PS_DESCR; j++) + printf(" DSSD Power State %d Desriptor : 0x%x\n", j, log_data->dssd_ps_descr[j]); + + printf(" Log Page Version : 0x%x\n", le16_to_cpu(log_data->log_page_version)); printf(" Log page GUID : 0x"); - for (j = 0; j < WDC_OCP_C4_GUID_LENGTH; j++) { + for (j = 0; j < WDC_OCP_C4_GUID_LENGTH; j++) printf("%x", log_data->log_page_guid[j]); - } printf("\n"); } static void wdc_print_dev_cap_log_json(struct wdc_ocp_C4_dev_cap_log *log_data) { int j; - struct json_object *root; - root = json_create_object(); + struct json_object *root = json_create_object(); json_object_add_value_int(root, "Number PCIE Ports", le16_to_cpu(log_data->num_pcie_ports)); json_object_add_value_int(root, "Number OOB Management Interfaces", le16_to_cpu(log_data->num_pcie_ports)); @@ -4329,6 +4386,7 @@ static void wdc_print_dev_cap_log_json(struct wdc_ocp_C4_dev_cap_log *log_data) json_object_add_value_int(root, "Minimum DSSD Power State", le16_to_cpu(log_data->num_pcie_ports)); char dssd_descr_str[40]; + memset((void *)dssd_descr_str, 0, 40); for (j = 0; j < WDC_OCP_C4_NUM_PS_DESCR; j++) { sprintf((char *)dssd_descr_str, "DSSD Power State %d Descriptor", j); @@ -4337,8 +4395,10 @@ static void wdc_print_dev_cap_log_json(struct wdc_ocp_C4_dev_cap_log *log_data) json_object_add_value_int(root, "Log Page Version", le16_to_cpu(log_data->log_page_version)); char guid[40]; - memset((void*)guid, 0, 40); - sprintf((char*)guid, "0x%"PRIx64"%"PRIx64"",(uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]), + + memset((void *)guid, 0, 40); + sprintf((char *)guid, "0x%"PRIx64"%"PRIx64"", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]), (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0])); json_object_add_value_string(root, "Log page GUID", guid); @@ -4351,41 +4411,45 @@ static void wdc_print_dev_cap_log_json(struct wdc_ocp_C4_dev_cap_log *log_data) static void wdc_print_unsupported_reqs_log_normal(struct wdc_ocp_C5_unsupported_reqs *log_data) { int j; - printf("Unsupported Requirements/C5 Log Page Data \n"); - printf(" Number Unsupported Req IDs : 0x%x \n", le16_to_cpu(log_data->unsupported_count)); + printf("Unsupported Requirements/C5 Log Page Data\n"); - for (j = 0; j < le16_to_cpu(log_data->unsupported_count); j++) { - printf(" Unsupported Requirement List %d : %s \n", j, log_data->unsupported_req_list[j]); - } + printf(" Number Unsupported Req IDs : 0x%x\n", + le16_to_cpu(log_data->unsupported_count)); + + for (j = 0; j < le16_to_cpu(log_data->unsupported_count); j++) + printf(" Unsupported Requirement List %d : %s\n", j, + log_data->unsupported_req_list[j]); - printf(" Log Page Version : 0x%x \n", le16_to_cpu(log_data->log_page_version)); + printf(" Log Page Version : 0x%x\n", le16_to_cpu(log_data->log_page_version)); printf(" Log page GUID : 0x"); - for (j = 0; j < WDC_OCP_C5_GUID_LENGTH; j++) { + for (j = 0; j < WDC_OCP_C5_GUID_LENGTH; j++) printf("%x", log_data->log_page_guid[j]); - } printf("\n"); } static void wdc_print_unsupported_reqs_log_json(struct wdc_ocp_C5_unsupported_reqs *log_data) { int j; - struct json_object *root; - root = json_create_object(); + struct json_object *root = json_create_object(); json_object_add_value_int(root, "Number Unsupported Req IDs", le16_to_cpu(log_data->unsupported_count)); char unsup_req_list_str[40]; + memset((void *)unsup_req_list_str, 0, 40); for (j = 0; j < le16_to_cpu(log_data->unsupported_count); j++) { sprintf((char *)unsup_req_list_str, "Unsupported Requirement List %d", j); json_object_add_value_string(root, unsup_req_list_str, (char *)log_data->unsupported_req_list[j]); } - json_object_add_value_int(root, "Log Page Version", le16_to_cpu(log_data->log_page_version)); + json_object_add_value_int(root, "Log Page Version", + le16_to_cpu(log_data->log_page_version)); char guid[40]; - memset((void*)guid, 0, 40); - sprintf((char*)guid, "0x%"PRIx64"%"PRIx64"",(uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]), + + memset((void *)guid, 0, 40); + sprintf((char *)guid, "0x%"PRIx64"%"PRIx64"", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]), (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0])); json_object_add_value_string(root, "Log page GUID", guid); @@ -4399,7 +4463,7 @@ static void wdc_print_fb_ca_log_normal(struct wdc_ssd_ca_perf_stats *perf) { uint64_t converted = 0; - printf(" CA Log Page Performance Statistics :- \n"); + printf(" CA Log Page Performance Statistics :-\n"); printf(" NAND Bytes Written %20"PRIu64 "%20"PRIu64"\n", le64_to_cpu(perf->nand_bytes_wr_hi), le64_to_cpu(perf->nand_bytes_wr_lo)); printf(" NAND Bytes Read %20"PRIu64 "%20"PRIu64"\n", @@ -4460,10 +4524,9 @@ static void wdc_print_fb_ca_log_normal(struct wdc_ssd_ca_perf_stats *perf) static void wdc_print_fb_ca_log_json(struct wdc_ssd_ca_perf_stats *perf) { - struct json_object *root; + struct json_object *root = json_create_object(); uint64_t converted = 0; - root = json_create_object(); json_object_add_value_int(root, "NAND Bytes Written Hi", le64_to_cpu(perf->nand_bytes_wr_hi)); json_object_add_value_int(root, "NAND Bytes Written Lo", le64_to_cpu(perf->nand_bytes_wr_lo)); json_object_add_value_int(root, "NAND Bytes Read Hi", le64_to_cpu(perf->nand_bytes_rd_hi)); @@ -4528,18 +4591,18 @@ static void wdc_print_bd_ca_log_normal(struct nvme_dev *dev, void *data) __u8 *byte_raw; if (bd_data->field_id == 0x00) { - raw = (__u64*)&bd_data->raw_value[0]; - printf("Additional Smart Log for NVME device:%s namespace-id:%x\n", - dev->name, WDC_DE_GLOBAL_NSID); + raw = (__u64 *)&bd_data->raw_value[0]; + printf("Additional Smart Log for NVME device:%s namespace-id:%x\n", dev->name, + WDC_DE_GLOBAL_NSID); printf("key normalized raw\n"); - printf("program_fail_count : %3"PRIu8"%% %"PRIu64"\n", - bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); + printf("program_fail_count : %3"PRIu8"%% %"PRIu64"\n", + bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); } else { goto invalid_id; } bd_data++; if (bd_data->field_id == 0x01) { - raw = (__u64*)&bd_data->raw_value[0]; + raw = (__u64 *)&bd_data->raw_value[0]; printf("erase_fail_count : %3"PRIu8"%% %"PRIu64"\n", bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); } else { @@ -4547,9 +4610,9 @@ static void wdc_print_bd_ca_log_normal(struct nvme_dev *dev, void *data) } bd_data++; if (bd_data->field_id == 0x02) { - word_raw1 = (__u16*)&bd_data->raw_value[1]; - word_raw2 = (__u16*)&bd_data->raw_value[3]; - word_raw3 = (__u16*)&bd_data->raw_value[5]; + word_raw1 = (__u16 *)&bd_data->raw_value[1]; + word_raw2 = (__u16 *)&bd_data->raw_value[3]; + word_raw3 = (__u16 *)&bd_data->raw_value[5]; printf("wear_leveling : %3"PRIu8"%% min: %"PRIu16", max: %"PRIu16", avg: %"PRIu16"\n", bd_data->normalized_value, le16_to_cpu(*word_raw1), @@ -4560,7 +4623,7 @@ static void wdc_print_bd_ca_log_normal(struct nvme_dev *dev, void *data) } bd_data++; if (bd_data->field_id == 0x03) { - raw = (__u64*)&bd_data->raw_value[0]; + raw = (__u64 *)&bd_data->raw_value[0]; printf("end_to_end_error_detection_count: %3"PRIu8"%% %"PRIu64"\n", bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); } else { @@ -4568,7 +4631,7 @@ static void wdc_print_bd_ca_log_normal(struct nvme_dev *dev, void *data) } bd_data++; if (bd_data->field_id == 0x04) { - raw = (__u64*)&bd_data->raw_value[0]; + raw = (__u64 *)&bd_data->raw_value[0]; printf("crc_error_count : %3"PRIu8"%% %"PRIu64"\n", bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); } else { @@ -4576,49 +4639,48 @@ static void wdc_print_bd_ca_log_normal(struct nvme_dev *dev, void *data) } bd_data++; if (bd_data->field_id == 0x05) { - raw = (__u64*)&bd_data->raw_value[0]; + raw = (__u64 *)&bd_data->raw_value[0]; printf("timed_workload_media_wear : %3"PRIu8"%% %-.3f%%\n", - bd_data->normalized_value, - safe_div_fp((*raw & 0x00FFFFFFFFFFFFFF), 1024.0)); + bd_data->normalized_value, safe_div_fp((*raw & 0x00FFFFFFFFFFFFFF), 1024.0)); } else { goto invalid_id; } bd_data++; if (bd_data->field_id == 0x06) { - raw = (__u64*)&bd_data->raw_value[0]; + raw = (__u64 *)&bd_data->raw_value[0]; printf("timed_workload_host_reads : %3"PRIu8"%% %"PRIu64"%%\n", - bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); + bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); } else { goto invalid_id; } bd_data++; if (bd_data->field_id == 0x07) { - raw = (__u64*)&bd_data->raw_value[0]; + raw = (__u64 *)&bd_data->raw_value[0]; printf("timed_workload_timer : %3"PRIu8"%% %"PRIu64"\n", - bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); + bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); } else { goto invalid_id; } bd_data++; if (bd_data->field_id == 0x08) { - byte_raw = (__u8*)&bd_data->raw_value[1]; - dword_raw = (__u32*)&bd_data->raw_value[2]; + byte_raw = (__u8 *)&bd_data->raw_value[1]; + dword_raw = (__u32 *)&bd_data->raw_value[2]; printf("thermal_throttle_status : %3"PRIu8"%% %"PRIu16"%%, cnt: %"PRIu16"\n", - bd_data->normalized_value, *byte_raw, le32_to_cpu(*dword_raw)); + bd_data->normalized_value, *byte_raw, le32_to_cpu(*dword_raw)); } else { goto invalid_id; } bd_data++; if (bd_data->field_id == 0x09) { - raw = (__u64*)&bd_data->raw_value[0]; + raw = (__u64 *)&bd_data->raw_value[0]; printf("retry_buffer_overflow_count : %3"PRIu8"%% %"PRIu64"\n", - bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); + bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); } else { goto invalid_id; } bd_data++; if (bd_data->field_id == 0x0A) { - raw = (__u64*)&bd_data->raw_value[0]; + raw = (__u64 *)&bd_data->raw_value[0]; printf("pll_lock_loss_count : %3"PRIu8"%% %"PRIu64"\n", bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); } else { @@ -4626,7 +4688,7 @@ static void wdc_print_bd_ca_log_normal(struct nvme_dev *dev, void *data) } bd_data++; if (bd_data->field_id == 0x0B) { - raw = (__u64*)&bd_data->raw_value[0]; + raw = (__u64 *)&bd_data->raw_value[0]; printf("nand_bytes_written : %3"PRIu8"%% sectors: %.f\n", bd_data->normalized_value, safe_div_fp((*raw & 0x00FFFFFFFFFFFFFF), 0xFFFF)); } else { @@ -4634,7 +4696,7 @@ static void wdc_print_bd_ca_log_normal(struct nvme_dev *dev, void *data) } bd_data++; if (bd_data->field_id == 0x0C) { - raw = (__u64*)&bd_data->raw_value[0]; + raw = (__u64 *)&bd_data->raw_value[0]; printf("host_bytes_written : %3"PRIu8"%% sectors: %.f\n", bd_data->normalized_value, safe_div_fp((*raw & 0x00FFFFFFFFFFFFFF), 0xFFFF)); } else { @@ -4643,11 +4705,11 @@ static void wdc_print_bd_ca_log_normal(struct nvme_dev *dev, void *data) goto done; - invalid_id: - printf(" Invalid Field ID = %d\n", bd_data->field_id); +invalid_id: + printf(" Invalid Field ID = %d\n", bd_data->field_id); - done: - return; +done: + return; } @@ -4658,11 +4720,10 @@ static void wdc_print_bd_ca_log_json(void *data) __u16 *word_raw; __u32 *dword_raw; __u8 *byte_raw; - struct json_object *root; + struct json_object *root = json_create_object(); - root = json_create_object(); if (bd_data->field_id == 0x00) { - raw = (__u64*)&bd_data->raw_value[0]; + raw = (__u64 *)&bd_data->raw_value[0]; json_object_add_value_int(root, "program_fail_count normalized", bd_data->normalized_value); json_object_add_value_int(root, "program_fail_count raw", @@ -4672,7 +4733,7 @@ static void wdc_print_bd_ca_log_json(void *data) } bd_data++; if (bd_data->field_id == 0x01) { - raw = (__u64*)&bd_data->raw_value[0]; + raw = (__u64 *)&bd_data->raw_value[0]; json_object_add_value_int(root, "erase_fail_count normalized", bd_data->normalized_value); json_object_add_value_int(root, "erase_fail_count raw", @@ -4682,19 +4743,19 @@ static void wdc_print_bd_ca_log_json(void *data) } bd_data++; if (bd_data->field_id == 0x02) { - word_raw = (__u16*)&bd_data->raw_value[1]; + word_raw = (__u16 *)&bd_data->raw_value[1]; json_object_add_value_int(root, "wear_leveling normalized", bd_data->normalized_value); json_object_add_value_int(root, "wear_leveling min", le16_to_cpu(*word_raw)); - word_raw = (__u16*)&bd_data->raw_value[3]; + word_raw = (__u16 *)&bd_data->raw_value[3]; json_object_add_value_int(root, "wear_leveling max", le16_to_cpu(*word_raw)); - word_raw = (__u16*)&bd_data->raw_value[5]; + word_raw = (__u16 *)&bd_data->raw_value[5]; json_object_add_value_int(root, "wear_leveling avg", le16_to_cpu(*word_raw)); } else { goto invalid_id; } bd_data++; if (bd_data->field_id == 0x03) { - raw = (__u64*)&bd_data->raw_value[0]; + raw = (__u64 *)&bd_data->raw_value[0]; json_object_add_value_int(root, "end_to_end_error_detection_count normalized", bd_data->normalized_value); json_object_add_value_int(root, "end_to_end_error_detection_count raw", @@ -4704,7 +4765,7 @@ static void wdc_print_bd_ca_log_json(void *data) } bd_data++; if (bd_data->field_id == 0x04) { - raw = (__u64*)&bd_data->raw_value[0]; + raw = (__u64 *)&bd_data->raw_value[0]; json_object_add_value_int(root, "crc_error_count normalized", bd_data->normalized_value); json_object_add_value_int(root, "crc_error_count raw", @@ -4714,7 +4775,7 @@ static void wdc_print_bd_ca_log_json(void *data) } bd_data++; if (bd_data->field_id == 0x05) { - raw = (__u64*)&bd_data->raw_value[0]; + raw = (__u64 *)&bd_data->raw_value[0]; json_object_add_value_int(root, "timed_workload_media_wear normalized", bd_data->normalized_value); json_object_add_value_double(root, "timed_workload_media_wear raw", @@ -4724,7 +4785,7 @@ static void wdc_print_bd_ca_log_json(void *data) } bd_data++; if (bd_data->field_id == 0x06) { - raw = (__u64*)&bd_data->raw_value[0]; + raw = (__u64 *)&bd_data->raw_value[0]; json_object_add_value_int(root, "timed_workload_host_reads normalized", bd_data->normalized_value); json_object_add_value_int(root, "timed_workload_host_reads raw", @@ -4734,28 +4795,28 @@ static void wdc_print_bd_ca_log_json(void *data) } bd_data++; if (bd_data->field_id == 0x07) { - raw = (__u64*)&bd_data->raw_value[0]; + raw = (__u64 *)&bd_data->raw_value[0]; json_object_add_value_int(root, "timed_workload_timer normalized", - bd_data->normalized_value); + bd_data->normalized_value); json_object_add_value_int(root, "timed_workload_timer", - le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); + le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); } else { goto invalid_id; } bd_data++; if (bd_data->field_id == 0x08) { - byte_raw = (__u8*)&bd_data->raw_value[1]; + byte_raw = (__u8 *)&bd_data->raw_value[1]; json_object_add_value_int(root, "thermal_throttle_status normalized", bd_data->normalized_value); json_object_add_value_int(root, "thermal_throttle_status", *byte_raw); - dword_raw = (__u32*)&bd_data->raw_value[2]; + dword_raw = (__u32 *)&bd_data->raw_value[2]; json_object_add_value_int(root, "thermal_throttle_cnt", le32_to_cpu(*dword_raw)); } else { goto invalid_id; } bd_data++; if (bd_data->field_id == 0x09) { - raw = (__u64*)&bd_data->raw_value[0]; + raw = (__u64 *)&bd_data->raw_value[0]; json_object_add_value_int(root, "retry_buffer_overflow_count normalized", bd_data->normalized_value); json_object_add_value_int(root, "retry_buffer_overflow_count raw", @@ -4765,7 +4826,7 @@ static void wdc_print_bd_ca_log_json(void *data) } bd_data++; if (bd_data->field_id == 0x0A) { - raw = (__u64*)&bd_data->raw_value[0]; + raw = (__u64 *)&bd_data->raw_value[0]; json_object_add_value_int(root, "pll_lock_loss_count normalized", bd_data->normalized_value); json_object_add_value_int(root, "pll_lock_loss_count raw", @@ -4775,7 +4836,7 @@ static void wdc_print_bd_ca_log_json(void *data) } bd_data++; if (bd_data->field_id == 0x0B) { - raw = (__u64*)&bd_data->raw_value[0]; + raw = (__u64 *)&bd_data->raw_value[0]; json_object_add_value_int(root, "nand_bytes_written normalized", bd_data->normalized_value); json_object_add_value_double(root, "nand_bytes_written raw", @@ -4785,7 +4846,7 @@ static void wdc_print_bd_ca_log_json(void *data) } bd_data++; if (bd_data->field_id == 0x0C) { - raw = (__u64*)&bd_data->raw_value[0]; + raw = (__u64 *)&bd_data->raw_value[0]; json_object_add_value_int(root, "host_bytes_written normalized", bd_data->normalized_value); json_object_add_value_double(root, "host_bytes_written raw", @@ -4796,10 +4857,10 @@ static void wdc_print_bd_ca_log_json(void *data) goto done; - invalid_id: +invalid_id: printf(" Invalid Field ID = %d\n", bd_data->field_id); - done: +done: json_print_object(root, NULL); printf("\n"); json_free_object(root); @@ -4810,7 +4871,7 @@ static void wdc_print_bd_ca_log_json(void *data) static void wdc_print_d0_log_normal(struct wdc_ssd_d0_smart_log *perf) { - printf(" D0 Smart Log Page Statistics :- \n"); + printf(" D0 Smart Log Page Statistics :-\n"); printf(" Lifetime Reallocated Erase Block Count %20"PRIu32"\n", (uint32_t)le32_to_cpu(perf->lifetime_realloc_erase_block_count)); printf(" Lifetime Power on Hours %20"PRIu32"\n", @@ -4819,11 +4880,11 @@ static void wdc_print_d0_log_normal(struct wdc_ssd_d0_smart_log *perf) (uint32_t)le32_to_cpu(perf->lifetime_uecc_count)); printf(" Lifetime Write Amplification Factor %20"PRIu32"\n", (uint32_t)le32_to_cpu(perf->lifetime_wrt_amp_factor)); - printf(" Trailing Hour Write Amplification Factor %20"PRIu32"\n", + printf(" Trailing Hour Write Amplification Factor %20"PRIu32"\n", (uint32_t)le32_to_cpu(perf->trailing_hr_wrt_amp_factor)); printf(" Reserve Erase Block Count %20"PRIu32"\n", (uint32_t)le32_to_cpu(perf->reserve_erase_block_count)); - printf(" Lifetime Program Fail Count %20"PRIu32"\n", + printf(" Lifetime Program Fail Count %20"PRIu32"\n", (uint32_t)le32_to_cpu(perf->lifetime_program_fail_count)); printf(" Lifetime Block Erase Fail Count %20"PRIu32"\n", (uint32_t)le32_to_cpu(perf->lifetime_block_erase_fail_count)); @@ -4835,7 +4896,7 @@ static void wdc_print_d0_log_normal(struct wdc_ssd_d0_smart_log *perf) (uint32_t)le32_to_cpu(perf->lifetime_clean_shutdown_count)); printf(" Lifetime Unclean Shutdowns on Power Loss %20"PRIu32"\n", (uint32_t)le32_to_cpu(perf->lifetime_unclean_shutdown_count)); - printf(" Current Temperature %20"PRIu32"\n", + printf(" Current Temperature %20"PRIu32"\n", (uint32_t)le32_to_cpu(perf->current_temp)); printf(" Max Recorded Temperature %20"PRIu32"\n", (uint32_t)le32_to_cpu(perf->max_recorded_temp)); @@ -4845,7 +4906,7 @@ static void wdc_print_d0_log_normal(struct wdc_ssd_d0_smart_log *perf) (uint32_t)le32_to_cpu(perf->lifetime_read_disturb_realloc_events)); printf(" Lifetime NAND Writes %20"PRIu64"\n", le64_to_cpu(perf->lifetime_nand_writes)); - printf(" Capacitor Health %20"PRIu32"%%\n", + printf(" Capacitor Health %20"PRIu32"%%\n", (uint32_t)le32_to_cpu(perf->capacitor_health)); printf(" Lifetime User Writes %20"PRIu64"\n", le64_to_cpu(perf->lifetime_user_writes)); @@ -4859,9 +4920,8 @@ static void wdc_print_d0_log_normal(struct wdc_ssd_d0_smart_log *perf) static void wdc_print_d0_log_json(struct wdc_ssd_d0_smart_log *perf) { - struct json_object *root; + struct json_object *root = json_create_object(); - root = json_create_object(); json_object_add_value_int(root, "Lifetime Reallocated Erase Block Count", le32_to_cpu(perf->lifetime_realloc_erase_block_count)); json_object_add_value_int(root, "Lifetime Power on Hours", @@ -4915,32 +4975,31 @@ static void wdc_print_d0_log_json(struct wdc_ssd_d0_smart_log *perf) static void wdc_get_commit_action_bin(__u8 commit_action_type, char *action_bin) { - switch (commit_action_type) - { - case(0): + switch (commit_action_type) { + case 0: strcpy(action_bin, "000b"); break; - case(1): + case 1: strcpy(action_bin, "001b"); - break; - case(2): + break; + case 2: strcpy(action_bin, "010b"); - break; - case(3): + break; + case 3: strcpy(action_bin, "011b"); - break; - case(4): + break; + case 4: strcpy(action_bin, "100b"); - break; - case(5): + break; + case 5: strcpy(action_bin, "101b"); - break; - case(6): + break; + case 6: strcpy(action_bin, "110b"); - break; - case(7): - strcpy(action_bin, "111b"); - break; + break; + case 7: + strcpy(action_bin, "111b"); + break; default: strcpy(action_bin, "INVALID"); } @@ -4956,17 +5015,18 @@ static void wdc_print_fw_act_history_log_normal(__u8 *data, int num_entries, __u char time_str[11]; __u16 oldestEntryIdx = 0, entryIdx = 0; char *null_fw = "--------"; + memset((void *)time_str, 0, 11); if (data[0] == WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID) { - printf(" Firmware Activate History Log \n"); + printf(" Firmware Activate History Log\n"); if (cust_id == WDC_CUSTOMER_ID_0x1005 || vendor_id == WDC_NVME_SNDK_VID) { - printf(" Power on Hour Power Cycle Previous New \n"); - printf(" Entry hh:mm:ss Count Firmware Firmware Slot Action Result \n"); + printf(" Power on Hour Power Cycle Previous New\n"); + printf(" Entry hh:mm:ss Count Firmware Firmware Slot Action Result\n"); printf(" ----- ----------------- ----------------- --------- --------- ----- ------ -------\n"); } else { - printf(" Power Cycle Previous New \n"); - printf(" Entry Timestamp Count Firmware Firmware Slot Action Result \n"); + printf(" Power Cycle Previous New\n"); + printf(" Entry Timestamp Count Firmware Firmware Slot Action Result\n"); printf(" ----- ----------------- ----------------- --------- --------- ----- ------ -------\n"); } @@ -5010,9 +5070,10 @@ static void wdc_print_fw_act_history_log_normal(__u8 *data, int num_entries, __u printf("%s", time_str); printf(" "); - } else if(vendor_id == WDC_NVME_SNDK_VID) { + } else if (vendor_id == WDC_NVME_SNDK_VID) { printf(" "); uint64_t timestamp = (0x0000FFFFFFFFFFFF & le64_to_cpu(fw_act_history_entry->entry[entryIdx].timestamp)); + memset((void *)time_str, 0, 9); sprintf((char *)time_str, "%04d:%02d:%02d", (int)((timestamp/(3600*1000))%24), (int)((timestamp/(1000*60))%60), (int)((timestamp/1000)%60)); @@ -5021,6 +5082,7 @@ static void wdc_print_fw_act_history_log_normal(__u8 *data, int num_entries, __u } else { printf(" "); uint64_t timestamp = (0x0000FFFFFFFFFFFF & le64_to_cpu(fw_act_history_entry->entry[entryIdx].timestamp)); + printf("%16"PRIu64"", timestamp); printf(" "); } @@ -5033,10 +5095,12 @@ static void wdc_print_fw_act_history_log_normal(__u8 *data, int num_entries, __u printf(" "); printf("%2"PRIu8"", (uint8_t)fw_act_history_entry->entry[entryIdx].slot_number); printf(" "); - wdc_get_commit_action_bin(fw_act_history_entry->entry[entryIdx].commit_action_type,(char *)&commit_action_bin); + wdc_get_commit_action_bin( + fw_act_history_entry->entry[entryIdx].commit_action_type, + (char *)&commit_action_bin); printf(" %s", (char *)commit_action_bin); printf(" "); - if (le16_to_cpu(fw_act_history_entry->entry[entryIdx].result) == 0) + if (!le16_to_cpu(fw_act_history_entry->entry[entryIdx].result)) printf("pass"); else printf("fail #%d", (uint16_t)le16_to_cpu(fw_act_history_entry->entry[entryIdx].result)); @@ -5046,12 +5110,10 @@ static void wdc_print_fw_act_history_log_normal(__u8 *data, int num_entries, __u if (entryIdx >= WDC_MAX_NUM_ACT_HIST_ENTRIES) entryIdx = 0; } - } - else - { - printf(" Firmware Activate History Log \n"); - printf(" Power on Hour Power Cycle Previous New \n"); - printf(" Entry hh:mm:ss Count Firmware Firmware Slot Action Result \n"); + } else { + printf(" Firmware Activate History Log\n"); + printf(" Power on Hour Power Cycle Previous New\n"); + printf(" Entry hh:mm:ss Count Firmware Firmware Slot Action Result\n"); printf(" ----- -------------- -------------------- ---------- ---------- ----- ------ -------\n"); struct wdc_fw_act_history_log_entry *fw_act_history_entry = (struct wdc_fw_act_history_log_entry *)(data + sizeof(struct wdc_fw_act_history_log_hdr)); @@ -5097,10 +5159,11 @@ static void wdc_print_fw_act_history_log_normal(__u8 *data, int num_entries, __u printf(" "); printf("%2"PRIu8"", (uint8_t)fw_act_history_entry[entryIdx].slot_number); printf(" "); - wdc_get_commit_action_bin(fw_act_history_entry[entryIdx].commit_action_type,(char *)&commit_action_bin); + wdc_get_commit_action_bin(fw_act_history_entry[entryIdx].commit_action_type, + (char *)&commit_action_bin); printf(" %s", (char *)commit_action_bin); printf(" "); - if (le16_to_cpu(fw_act_history_entry[entryIdx].result) == 0) + if (!le16_to_cpu(fw_act_history_entry[entryIdx].result)) printf("pass"); else printf("fail #%d", (uint16_t)le16_to_cpu(fw_act_history_entry[entryIdx].result)); @@ -5116,13 +5179,14 @@ static void wdc_print_fw_act_history_log_normal(__u8 *data, int num_entries, __u static void wdc_print_fw_act_history_log_json(__u8 *data, int num_entries, __u32 cust_id, __u32 vendor_id) { - struct json_object *root; + struct json_object *root = json_create_object(); int i, j; char previous_fw[9]; char new_fw[9]; char commit_action_bin[8]; char fail_str[32]; char time_str[11]; + memset((void *)previous_fw, 0, 9); memset((void *)new_fw, 0, 9); memset((void *)commit_action_bin, 0, 8); @@ -5131,8 +5195,6 @@ static void wdc_print_fw_act_history_log_json(__u8 *data, int num_entries, __u32 char *null_fw = "--------"; __u16 oldestEntryIdx = 0, entryIdx = 0; - root = json_create_object(); - if (data[0] == WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID) { struct wdc_fw_act_history_log_format_c2 *fw_act_history_entry = (struct wdc_fw_act_history_log_format_c2 *)(data); @@ -5154,14 +5216,18 @@ static void wdc_print_fw_act_history_log_json(__u8 *data, int num_entries, __u32 entryIdx = oldestEntryIdx; for (i = 0; i < num_entries; i++) { - memcpy(previous_fw, (char *)&(fw_act_history_entry->entry[entryIdx].previous_fw_version), 8); + memcpy(previous_fw, + (char *)&(fw_act_history_entry->entry[entryIdx].previous_fw_version), + 8); if (strlen((char *)&(fw_act_history_entry->entry[entryIdx].current_fw_version)) > 1) - memcpy(new_fw, (char *)&(fw_act_history_entry->entry[entryIdx].current_fw_version), 8); + memcpy(new_fw, + (char *)&(fw_act_history_entry->entry[entryIdx].current_fw_version), + 8); else memcpy(new_fw, null_fw, 8); json_object_add_value_int(root, "Entry", - le16_to_cpu(fw_act_history_entry->entry[entryIdx].fw_act_hist_entries)); + le16_to_cpu(fw_act_history_entry->entry[entryIdx].fw_act_hist_entries)); if (cust_id == WDC_CUSTOMER_ID_0x1005) { sprintf((char *)time_str, "%04d:%02d:%02d", (int)(le64_to_cpu(fw_act_history_entry->entry[entryIdx].timestamp)/3600), @@ -5172,11 +5238,13 @@ static void wdc_print_fw_act_history_log_json(__u8 *data, int num_entries, __u32 } else if (vendor_id == WDC_NVME_SNDK_VID) { uint64_t timestamp = (0x0000FFFFFFFFFFFF & le64_to_cpu(fw_act_history_entry->entry[entryIdx].timestamp)); + sprintf((char *)time_str, "%04d:%02d:%02d", (int)((timestamp/(3600*1000))%24), (int)((timestamp/(1000*60))%60), (int)((timestamp/1000)%60)); json_object_add_value_string(root, "Power on Hour", time_str); } else { uint64_t timestamp = (0x0000FFFFFFFFFFFF & le64_to_cpu(fw_act_history_entry->entry[entryIdx].timestamp)); + json_object_add_value_uint64(root, "Timestamp", timestamp); } @@ -5189,12 +5257,14 @@ static void wdc_print_fw_act_history_log_json(__u8 *data, int num_entries, __u32 json_object_add_value_int(root, "Slot", fw_act_history_entry->entry[entryIdx].slot_number); - wdc_get_commit_action_bin(fw_act_history_entry->entry[entryIdx].commit_action_type,(char *)&commit_action_bin); + wdc_get_commit_action_bin( + fw_act_history_entry->entry[entryIdx].commit_action_type, + (char *)&commit_action_bin); json_object_add_value_string(root, "Action", commit_action_bin); - if (le16_to_cpu(fw_act_history_entry->entry[entryIdx].result) == 0) + if (!le16_to_cpu(fw_act_history_entry->entry[entryIdx].result)) { json_object_add_value_string(root, "Result", "pass"); - else { + } else { sprintf((char *)fail_str, "fail #%d", (int)(le16_to_cpu(fw_act_history_entry->entry[entryIdx].result))); json_object_add_value_string(root, "Result", fail_str); } @@ -5206,8 +5276,7 @@ static void wdc_print_fw_act_history_log_json(__u8 *data, int num_entries, __u32 if (entryIdx >= WDC_MAX_NUM_ACT_HIST_ENTRIES) entryIdx = 0; } - } - else { + } else { struct wdc_fw_act_history_log_entry *fw_act_history_entry = (struct wdc_fw_act_history_log_entry *)(data + sizeof(struct wdc_fw_act_history_log_hdr)); oldestEntryIdx = WDC_MAX_NUM_ACT_HIST_ENTRIES; @@ -5226,9 +5295,11 @@ static void wdc_print_fw_act_history_log_json(__u8 *data, int num_entries, __u32 entryIdx = oldestEntryIdx; for (i = 0; i < num_entries; i++) { - memcpy(previous_fw, (char *)&(fw_act_history_entry[entryIdx].previous_fw_version), 8); + memcpy(previous_fw, + (char *)&(fw_act_history_entry[entryIdx].previous_fw_version), 8); if (strlen((char *)&(fw_act_history_entry[entryIdx].new_fw_version)) > 1) - memcpy(new_fw, (char *)&(fw_act_history_entry[entryIdx].new_fw_version), 8); + memcpy(new_fw, + (char *)&(fw_act_history_entry[entryIdx].new_fw_version), 8); else memcpy(new_fw, null_fw, 8); @@ -5249,12 +5320,13 @@ static void wdc_print_fw_act_history_log_json(__u8 *data, int num_entries, __u32 json_object_add_value_int(root, "Slot", fw_act_history_entry[entryIdx].slot_number); - wdc_get_commit_action_bin(fw_act_history_entry[entryIdx].commit_action_type,(char *)&commit_action_bin); + wdc_get_commit_action_bin(fw_act_history_entry[entryIdx].commit_action_type, + (char *)&commit_action_bin); json_object_add_value_string(root, "Action", commit_action_bin); - if (le16_to_cpu(fw_act_history_entry[entryIdx].result) == 0) + if (!le16_to_cpu(fw_act_history_entry[entryIdx].result)) { json_object_add_value_string(root, "Result", "pass"); - else { + } else { sprintf((char *)fail_str, "fail #%d", (int)(le16_to_cpu(fw_act_history_entry[entryIdx].result))); json_object_add_value_string(root, "Result", fail_str); } @@ -5276,8 +5348,9 @@ static int nvme_get_ext_smart_cloud_log(int fd, __u8 **data, int uuid_index, __u int ret, i; __u8 *log_ptr = NULL; - if ((log_ptr = (__u8*) malloc(sizeof (__u8) * WDC_NVME_SMART_CLOUD_ATTR_LEN)) == NULL) { - fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); + log_ptr = (__u8 *)malloc(sizeof(__u8) * WDC_NVME_SMART_CLOUD_ATTR_LEN); + if (!log_ptr) { + fprintf(stderr, "ERROR: WDC: malloc: %s\n", strerror(errno)); return -1; } @@ -5301,21 +5374,19 @@ static int nvme_get_ext_smart_cloud_log(int fd, __u8 **data, int uuid_index, __u }; ret = nvme_get_log(&args); - if (ret == 0) { - + if (!ret) { /* Verify GUID matches */ for (i = 0; i < WDC_C0_GUID_LENGTH; i++) { - if (ext_smart_guid[i] != *&log_ptr[SCAO_V1_LPG + i]) { - fprintf(stderr, "ERROR : WDC : Unknown GUID in C0 Log Page V1 data\n"); + if (ext_smart_guid[i] != *&log_ptr[SCAO_V1_LPG + i]) { + fprintf(stderr, "ERROR: WDC: Unknown GUID in C0 Log Page V1 data\n"); int j; - fprintf(stderr, "ERROR : WDC : Expected GUID: 0x"); - for (j = 0; j < WDC_C0_GUID_LENGTH; j++) { + + fprintf(stderr, "ERROR: WDC: Expected GUID: 0x"); + for (j = 0; j < WDC_C0_GUID_LENGTH; j++) fprintf(stderr, "%x", ext_smart_guid[j]); - } - fprintf(stderr, "\nERROR : WDC : Actual GUID: 0x"); - for (j = 0; j < WDC_C0_GUID_LENGTH; j++) { + fprintf(stderr, "\nERROR: WDC: Actual GUID: 0x"); + for (j = 0; j < WDC_C0_GUID_LENGTH; j++) fprintf(stderr, "%x", *&log_ptr[SCAO_V1_LPG + j]); - } fprintf(stderr, "\n"); ret = -1; @@ -5333,10 +5404,11 @@ static int nvme_get_ext_smart_cloud_log(int fd, __u8 **data, int uuid_index, __u static int nvme_get_hw_rev_log(int fd, __u8 **data, int uuid_index, __u32 namespace_id) { int ret, i; - wdc_nvme_hw_rev_log *log_ptr = NULL; + struct wdc_nvme_hw_rev_log *log_ptr = NULL; - if ((log_ptr = (wdc_nvme_hw_rev_log *)malloc(sizeof (__u8) * WDC_NVME_HW_REV_LOG_PAGE_LEN)) == NULL) { - fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); + log_ptr = (struct wdc_nvme_hw_rev_log *)malloc(sizeof(__u8) * WDC_NVME_HW_REV_LOG_PAGE_LEN); + if (!log_ptr) { + fprintf(stderr, "ERROR: WDC: malloc: %s\n", strerror(errno)); return -1; } @@ -5360,21 +5432,19 @@ static int nvme_get_hw_rev_log(int fd, __u8 **data, int uuid_index, __u32 namesp }; ret = nvme_get_log(&args); - if (ret == 0) { - + if (!ret) { /* Verify GUID matches */ for (i = 0; i < WDC_NVME_C6_GUID_LENGTH; i++) { - if (hw_rev_log_guid[i] != log_ptr->hw_rev_guid[i]) { - fprintf(stderr, "ERROR : WDC : Unknown GUID in HW Revision Log Page data\n"); + if (hw_rev_log_guid[i] != log_ptr->hw_rev_guid[i]) { + fprintf(stderr, "ERROR: WDC: Unknown GUID in HW Revision Log Page data\n"); int j; - fprintf(stderr, "ERROR : WDC : Expected GUID: 0x"); - for (j = 0; j < WDC_NVME_C6_GUID_LENGTH; j++) { + + fprintf(stderr, "ERROR: WDC: Expected GUID: 0x"); + for (j = 0; j < WDC_NVME_C6_GUID_LENGTH; j++) fprintf(stderr, "%x", hw_rev_log_guid[j]); - } - fprintf(stderr, "\nERROR : WDC : Actual GUID: 0x"); - for (j = 0; j < WDC_NVME_C6_GUID_LENGTH; j++) { + fprintf(stderr, "\nERROR: WDC: Actual GUID: 0x"); + for (j = 0; j < WDC_NVME_C6_GUID_LENGTH; j++) fprintf(stderr, "%x", log_ptr->hw_rev_guid[j]); - } fprintf(stderr, "\n"); ret = -1; @@ -5392,9 +5462,9 @@ static int nvme_get_hw_rev_log(int fd, __u8 **data, int uuid_index, __u32 namesp static void wdc_print_hw_rev_log_normal(void *data) { int i; - wdc_nvme_hw_rev_log *log_data = (wdc_nvme_hw_rev_log *)data; + struct wdc_nvme_hw_rev_log *log_data = (struct wdc_nvme_hw_rev_log *)data; - printf(" Hardware Revision Log:- \n"); + printf(" Hardware Revision Log:-\n"); printf(" Global Device HW Revision : %d\n", log_data->hw_rev_gdr); @@ -5541,7 +5611,7 @@ static void wdc_print_hw_rev_log_normal(void *data) printf(" 0x"); } printf("\n"); - printf(" Serial Number : 0x"); + printf(" Serial Number : 0x"); for (i = 0; i < 32; i++) { if ((i > 1) & !(i % 8)) printf(" 0x"); @@ -5549,21 +5619,19 @@ static void wdc_print_hw_rev_log_normal(void *data) } printf("\n"); - printf(" Log Page Version : %d\n", - log_data->hw_rev_version); + printf(" Log Page Version : %d\n", log_data->hw_rev_version); printf(" Log page GUID : 0x"); - printf("%"PRIx64"%"PRIx64"\n",le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[8]), - le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[0])); + printf("%"PRIx64"%"PRIx64"\n", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[8]), + le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[0])); printf("\n"); } static void wdc_print_hw_rev_log_json(void *data) { - wdc_nvme_hw_rev_log *log_data = (wdc_nvme_hw_rev_log *)data; - struct json_object *root; + struct wdc_nvme_hw_rev_log *log_data = (struct wdc_nvme_hw_rev_log *)data; + struct json_object *root = json_create_object(); char json_data[80]; - root = json_create_object(); json_object_add_value_uint(root, "Global Device HW Revision", log_data->hw_rev_gdr); json_object_add_value_uint(root, "ASIC HW Revision", @@ -5597,88 +5665,88 @@ static void wdc_print_hw_rev_log_json(void *data) json_object_add_value_uint(root, "Other Component 9 Manf Code", log_data->hw_rev_c9_mc); - memset((void*)json_data, 0, 40); - sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dev_mdi[8]), + memset((void *)json_data, 0, 40); + sprintf((char *)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dev_mdi[8]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dev_mdi[0])); json_object_add_value_string(root, "Device Manf Detailed Info", json_data); - memset((void*)json_data, 0, 40); - sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_asic_di[8]), + memset((void *)json_data, 0, 40); + sprintf((char *)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_asic_di[8]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_asic_di[0])); json_object_add_value_string(root, "ASIC Detailed Info", json_data); - memset((void*)json_data, 0, 40); - sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pcb_di[8]), + memset((void *)json_data, 0, 40); + sprintf((char *)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pcb_di[8]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pcb_di[0])); json_object_add_value_string(root, "PCB Detailed Info", json_data); - memset((void*)json_data, 0, 40); - sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dram_di[8]), + memset((void *)json_data, 0, 40); + sprintf((char *)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dram_di[8]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dram_di[0])); json_object_add_value_string(root, "DRAM Detailed Info", json_data); - memset((void*)json_data, 0, 40); - sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_nand_di[8]), + memset((void *)json_data, 0, 40); + sprintf((char *)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_nand_di[8]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_nand_di[0])); json_object_add_value_string(root, "NAND Detailed Info", json_data); - memset((void*)json_data, 0, 40); - sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic1_di[8]), + memset((void *)json_data, 0, 40); + sprintf((char *)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic1_di[8]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic1_di[0])); json_object_add_value_string(root, "PMIC 1 Detailed Info", json_data); - memset((void*)json_data, 0, 40); - sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic2_di[8]), + memset((void *)json_data, 0, 40); + sprintf((char *)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic2_di[8]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic2_di[0])); json_object_add_value_string(root, "PMIC 2 Detailed Info", json_data); - memset((void*)json_data, 0, 40); - sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c1_di[8]), + memset((void *)json_data, 0, 40); + sprintf((char *)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c1_di[8]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c1_di[0])); json_object_add_value_string(root, "Component 1 Detailed Info", json_data); - memset((void*)json_data, 0, 40); - sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c2_di[8]), + memset((void *)json_data, 0, 40); + sprintf((char *)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c2_di[8]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c2_di[0])); json_object_add_value_string(root, "Component 2 Detailed Info", json_data); - memset((void*)json_data, 0, 40); - sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c3_di[8]), + memset((void *)json_data, 0, 40); + sprintf((char *)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c3_di[8]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c3_di[0])); json_object_add_value_string(root, "Component 3 Detailed Info", json_data); - memset((void*)json_data, 0, 40); - sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c4_di[8]), + memset((void *)json_data, 0, 40); + sprintf((char *)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c4_di[8]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c4_di[0])); json_object_add_value_string(root, "Component 4 Detailed Info", json_data); - memset((void*)json_data, 0, 40); - sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c5_di[8]), + memset((void *)json_data, 0, 40); + sprintf((char *)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c5_di[8]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c5_di[0])); json_object_add_value_string(root, "Component 5 Detailed Info", json_data); - memset((void*)json_data, 0, 40); - sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c6_di[8]), + memset((void *)json_data, 0, 40); + sprintf((char *)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c6_di[8]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c6_di[0])); json_object_add_value_string(root, "Component 6 Detailed Info", json_data); - memset((void*)json_data, 0, 40); - sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c7_di[8]), + memset((void *)json_data, 0, 40); + sprintf((char *)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c7_di[8]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c7_di[0])); json_object_add_value_string(root, "Component 7 Detailed Info", json_data); - memset((void*)json_data, 0, 40); - sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c8_di[8]), + memset((void *)json_data, 0, 40); + sprintf((char *)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c8_di[8]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c8_di[0])); json_object_add_value_string(root, "Component 8 Detailed Info", json_data); - memset((void*)json_data, 0, 40); - sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c9_di[8]), + memset((void *)json_data, 0, 40); + sprintf((char *)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c9_di[8]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c9_di[0])); json_object_add_value_string(root, "Component 9 Detailed Info", json_data); - memset((void*)json_data, 0, 80); - sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"%"PRIx64"%"PRIx64"", + memset((void *)json_data, 0, 80); + sprintf((char *)json_data, "0x%"PRIx64"%"PRIx64"%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[0]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[8]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[16]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[24])); json_object_add_value_string(root, "Serial Number", json_data); @@ -5686,8 +5754,8 @@ static void wdc_print_hw_rev_log_json(void *data) json_object_add_value_uint(root, "Log Page Version", le16_to_cpu(log_data->hw_rev_version)); - memset((void*)json_data, 0, 40); - sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[8]), + memset((void *)json_data, 0, 40); + sprintf((char *)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[8]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[0])); json_object_add_value_string(root, "Log Page GUID", json_data); @@ -5699,17 +5767,17 @@ static void wdc_print_hw_rev_log_json(void *data) static void wdc_print_ext_smart_cloud_log_normal(void *data, int mask) { int i; - wdc_nvme_ext_smart_log *ext_smart_log_ptr = (wdc_nvme_ext_smart_log *)data; + struct __packed wdc_nvme_ext_smart_log * ext_smart_log_ptr = (struct __packed wdc_nvme_ext_smart_log *)data; if (mask == WDC_SCA_V1_NAND_STATS) - printf(" NAND Statistics :- \n"); + printf(" NAND Statistics :-\n"); else - printf(" SMART Cloud Attributes :- \n"); + printf(" SMART Cloud Attributes :-\n"); - printf(" Physical Media Units Written TLC (Bytes) : %s\n", + printf(" Physical Media Units Written TLC (Bytes): %s\n", uint128_t_to_string(le128_to_cpu( ext_smart_log_ptr->ext_smart_pmuwt))); - printf(" Physical Media Units Written SLC (Bytes) : %s\n", + printf(" Physical Media Units Written SLC (Bytes): %s\n", uint128_t_to_string(le128_to_cpu( ext_smart_log_ptr->ext_smart_pmuws))); printf(" Bad User NAND Block Count (Normalized) (Int) : %d\n", @@ -5759,7 +5827,7 @@ static void wdc_print_ext_smart_cloud_log_normal(void *data, int mask) le64_to_cpu(ext_smart_log_ptr->ext_smart_svn)); printf(" %% Free Blocks (System) (Int) : %d %%\n", ext_smart_log_ptr->ext_smart_pfbs); - printf(" NVMe Stats (# Data Set Management/TRIM Commands Completed) (Int) : %s\n", + printf(" NVMe Stats (# Data Set Management/TRIM Commands Completed) (Int): %s\n", uint128_t_to_string(le128_to_cpu( ext_smart_log_ptr->ext_smart_dcc))); printf(" Total Namespace Utilization (nvme0n1 NUSE) (Bytes) : %"PRIu64"\n", @@ -5827,123 +5895,127 @@ static void wdc_print_ext_smart_cloud_log_normal(void *data, int mask) static void wdc_print_ext_smart_cloud_log_json(void *data, int mask) { - wdc_nvme_ext_smart_log *ext_smart_log_ptr = (wdc_nvme_ext_smart_log *)data; - struct json_object *root; + struct __packed wdc_nvme_ext_smart_log * ext_smart_log_ptr = + (struct __packed wdc_nvme_ext_smart_log *)data; + struct json_object *root = json_create_object(); - root = json_create_object(); json_object_add_value_uint128(root, "physical_media_units_bytes_tlc", - le128_to_cpu(ext_smart_log_ptr->ext_smart_pmuwt)); + le128_to_cpu(ext_smart_log_ptr->ext_smart_pmuwt)); json_object_add_value_uint128(root, "physical_media_units_bytes_slc", - le128_to_cpu(ext_smart_log_ptr->ext_smart_pmuws)); + le128_to_cpu(ext_smart_log_ptr->ext_smart_pmuws)); json_object_add_value_uint(root, "bad_user_blocks_normalized", - le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bunbc)); + le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bunbc)); json_object_add_value_uint64(root, "bad_user_blocks_raw", - le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_bunbc & 0xFFFFFFFFFFFF0000)); + le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_bunbc & 0xFFFFFFFFFFFF0000)); json_object_add_value_uint64(root, "xor_recovery_count", - le64_to_cpu(ext_smart_log_ptr->ext_smart_xrc)); + le64_to_cpu(ext_smart_log_ptr->ext_smart_xrc)); json_object_add_value_uint64(root, "uncorrectable_read_errors", - le64_to_cpu(ext_smart_log_ptr->ext_smart_urec)); + le64_to_cpu(ext_smart_log_ptr->ext_smart_urec)); if (mask == WDC_SCA_V1_ALL) { json_object_add_value_uint64(root, "corrected_e2e_errors", - le64_to_cpu(ext_smart_log_ptr->ext_smart_eece)); + le64_to_cpu(ext_smart_log_ptr->ext_smart_eece)); json_object_add_value_uint64(root, "detected_e2e_errors", - le64_to_cpu(ext_smart_log_ptr->ext_smart_eede)); + le64_to_cpu(ext_smart_log_ptr->ext_smart_eede)); json_object_add_value_uint64(root, "uncorrected_e2e_errors", - le64_to_cpu(ext_smart_log_ptr->ext_smart_eeue)); + le64_to_cpu(ext_smart_log_ptr->ext_smart_eeue)); json_object_add_value_uint(root, "system_data_life_used_pct", - (__u8)ext_smart_log_ptr->ext_smart_sdpu); + (__u8)ext_smart_log_ptr->ext_smart_sdpu); } json_object_add_value_uint64(root, "min_slc_user_data_erase_count", - le64_to_cpu(ext_smart_log_ptr->ext_smart_mnec)); + le64_to_cpu(ext_smart_log_ptr->ext_smart_mnec)); json_object_add_value_uint64(root, "min_tlc_user_data_erase_count", - le64_to_cpu(ext_smart_log_ptr->ext_smart_mnudec)); + le64_to_cpu(ext_smart_log_ptr->ext_smart_mnudec)); json_object_add_value_uint64(root, "max_slc_user_data_erase_count", - le64_to_cpu(ext_smart_log_ptr->ext_smart_mxec)); + le64_to_cpu(ext_smart_log_ptr->ext_smart_mxec)); json_object_add_value_uint64(root, "max_tlc_user_data_erase_count", - le64_to_cpu(ext_smart_log_ptr->ext_smart_mxudec)); + le64_to_cpu(ext_smart_log_ptr->ext_smart_mxudec)); json_object_add_value_uint64(root, "avg_slc_user_data_erase_count", - le64_to_cpu(ext_smart_log_ptr->ext_smart_avec)); + le64_to_cpu(ext_smart_log_ptr->ext_smart_avec)); json_object_add_value_uint64(root, "avg_tlc_user_data_erase_count", - le64_to_cpu(ext_smart_log_ptr->ext_smart_avudec)); + le64_to_cpu(ext_smart_log_ptr->ext_smart_avudec)); json_object_add_value_uint(root, "program_fail_count_normalized", - le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_pfc)); + le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_pfc)); json_object_add_value_uint64(root, "program_fail_count_raw", - le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_pfc & 0xFFFFFFFFFFFF0000)); + le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_pfc & 0xFFFFFFFFFFFF0000)); json_object_add_value_uint(root, "erase_fail_count_normalized", - le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_efc)); + le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_efc)); json_object_add_value_uint64(root, "erase_fail_count_raw", - le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_efc & 0xFFFFFFFFFFFF0000)); + le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_efc & 0xFFFFFFFFFFFF0000)); if (mask == WDC_SCA_V1_ALL) { json_object_add_value_uint64(root, "pcie_correctable_errors", - le64_to_cpu(ext_smart_log_ptr->ext_smart_pcec)); + le64_to_cpu(ext_smart_log_ptr->ext_smart_pcec)); json_object_add_value_uint(root, "pct_free_blocks_user", - (__u8)ext_smart_log_ptr->ext_smart_pfbu); + (__u8)ext_smart_log_ptr->ext_smart_pfbu); json_object_add_value_uint64(root, "security_version", - le64_to_cpu(ext_smart_log_ptr->ext_smart_svn)); + le64_to_cpu(ext_smart_log_ptr->ext_smart_svn)); json_object_add_value_uint(root, "pct_free_blocks_system", - (__u8)ext_smart_log_ptr->ext_smart_pfbs); + (__u8)ext_smart_log_ptr->ext_smart_pfbs); json_object_add_value_uint128(root, "num_of_trim_commands", - le128_to_cpu(ext_smart_log_ptr->ext_smart_dcc)); + le128_to_cpu(ext_smart_log_ptr->ext_smart_dcc)); json_object_add_value_uint64(root, "total_nuse_bytes", - le64_to_cpu(ext_smart_log_ptr->ext_smart_tnu)); + le64_to_cpu(ext_smart_log_ptr->ext_smart_tnu)); json_object_add_value_uint(root, "num_of_format_commands", - le16_to_cpu(ext_smart_log_ptr->ext_smart_fcc)); + le16_to_cpu(ext_smart_log_ptr->ext_smart_fcc)); json_object_add_value_uint(root, "background_pressure_gauge", - (__u8)ext_smart_log_ptr->ext_smart_bbpg); + (__u8)ext_smart_log_ptr->ext_smart_bbpg); } json_object_add_value_uint64(root, "soft_ecc_error_count", - le64_to_cpu(ext_smart_log_ptr->ext_smart_seec)); - if (mask == WDC_SCA_V1_ALL) { + le64_to_cpu(ext_smart_log_ptr->ext_smart_seec)); + if (mask == WDC_SCA_V1_ALL) json_object_add_value_uint64(root, "read_refresh_count", - le64_to_cpu(ext_smart_log_ptr->ext_smart_rfsc)); - } + le64_to_cpu(ext_smart_log_ptr->ext_smart_rfsc)); json_object_add_value_uint(root, "bad_system_block_normalized", - le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bsnbc)); + le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bsnbc)); json_object_add_value_uint64(root, "bad_system_block_raw", - le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_bsnbc & 0xFFFFFFFFFFFF0000)); + le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_bsnbc & 0xFFFFFFFFFFFF0000)); json_object_add_value_uint128(root, "endurance_est_bytes", - le128_to_cpu(ext_smart_log_ptr->ext_smart_eest)); + le128_to_cpu(ext_smart_log_ptr->ext_smart_eest)); if (mask == WDC_SCA_V1_ALL) { json_object_add_value_uint(root, "num_throttling_events", - le16_to_cpu(ext_smart_log_ptr->ext_smart_ttc)); + le16_to_cpu(ext_smart_log_ptr->ext_smart_ttc)); json_object_add_value_uint64(root, "total_unaligned_io", - le64_to_cpu(ext_smart_log_ptr->ext_smart_uio)); + le64_to_cpu(ext_smart_log_ptr->ext_smart_uio)); } json_object_add_value_uint128(root, "physical_media_units_read_bytes", - le128_to_cpu(ext_smart_log_ptr->ext_smart_pmur)); + le128_to_cpu(ext_smart_log_ptr->ext_smart_pmur)); if (mask == WDC_SCA_V1_ALL) { json_object_add_value_uint(root, "num_read_timeouts", - le32_to_cpu(ext_smart_log_ptr->ext_smart_rtoc)); + le32_to_cpu(ext_smart_log_ptr->ext_smart_rtoc)); json_object_add_value_uint(root, "num_write_timeouts", - le32_to_cpu(ext_smart_log_ptr->ext_smart_wtoc)); + le32_to_cpu(ext_smart_log_ptr->ext_smart_wtoc)); json_object_add_value_uint(root, "num_trim_timeouts", - le32_to_cpu(ext_smart_log_ptr->ext_smart_ttoc)); + le32_to_cpu(ext_smart_log_ptr->ext_smart_ttoc)); json_object_add_value_uint64(root, "pcie_link_retrain_count", - le64_to_cpu(ext_smart_log_ptr->ext_smart_plrc)); + le64_to_cpu(ext_smart_log_ptr->ext_smart_plrc)); json_object_add_value_uint64(root, "active_power_state_change_count", - le64_to_cpu(ext_smart_log_ptr->ext_smart_pscc)); + le64_to_cpu(ext_smart_log_ptr->ext_smart_pscc)); } char vers_str[40]; - memset((void*)vers_str, 0, 40); - sprintf((char*)vers_str, "%d.%d.%d.%d", - le16_to_cpu(ext_smart_log_ptr->ext_smart_maj), le16_to_cpu(ext_smart_log_ptr->ext_smart_min), - le16_to_cpu(ext_smart_log_ptr->ext_smart_pt), le16_to_cpu(ext_smart_log_ptr->ext_smart_err)); + + memset((void *)vers_str, 0, 40); + sprintf((char *)vers_str, "%d.%d.%d.%d", + le16_to_cpu(ext_smart_log_ptr->ext_smart_maj), + le16_to_cpu(ext_smart_log_ptr->ext_smart_min), + le16_to_cpu(ext_smart_log_ptr->ext_smart_pt), + le16_to_cpu(ext_smart_log_ptr->ext_smart_err)); json_object_add_value_string(root, "cloud_boot_ssd_spec_ver", vers_str); - memset((void*)vers_str, 0, 40); - sprintf((char*)vers_str, "%d.%d.%d.%d", 0, 0, 0, 0); + memset((void *)vers_str, 0, 40); + sprintf((char *)vers_str, "%d.%d.%d.%d", 0, 0, 0, 0); json_object_add_value_string(root, "cloud_boot_ssd_hw_ver", vers_str); if (mask == WDC_SCA_V1_ALL) { json_object_add_value_uint(root, "ftl_unit_size", - le32_to_cpu(ext_smart_log_ptr->ext_smart_ftlus)); + le32_to_cpu(ext_smart_log_ptr->ext_smart_ftlus)); json_object_add_value_uint(root, "tcg_ownership_status", - le32_to_cpu(ext_smart_log_ptr->ext_smart_tcgos)); + le32_to_cpu(ext_smart_log_ptr->ext_smart_tcgos)); json_object_add_value_uint(root, "log_page_ver", - le16_to_cpu(ext_smart_log_ptr->ext_smart_lpv)); + le16_to_cpu(ext_smart_log_ptr->ext_smart_lpv)); char guid[40]; - memset((void*)guid, 0, 40); - sprintf((char*)guid, "0x%"PRIx64"%"PRIx64"",le64_to_cpu(*(uint64_t *)&ext_smart_log_ptr->ext_smart_lpg[8]), - le64_to_cpu(*(uint64_t *)&ext_smart_log_ptr->ext_smart_lpg[0])); + + memset((void *)guid, 0, 40); + sprintf((char *)guid, "0x%"PRIx64"%"PRIx64"", + le64_to_cpu(*(uint64_t *)&ext_smart_log_ptr->ext_smart_lpg[8]), + le64_to_cpu(*(uint64_t *)&ext_smart_log_ptr->ext_smart_lpg[0])); json_object_add_value_string(root, "log_page_guid", guid); } @@ -5954,92 +6026,92 @@ static void wdc_print_ext_smart_cloud_log_json(void *data, int mask) static void wdc_print_smart_cloud_attr_C0_normal(void *data) { - __u8 *log_data = (__u8*)data; + __u8 *log_data = (__u8 *)data; uint16_t smart_log_ver = 0; - printf(" SMART Cloud Attributes :- \n"); + printf(" SMART Cloud Attributes :-\n"); printf(" Physical media units written : %s\n", - uint128_t_to_string(le128_to_cpu(&log_data[SCAO_PMUW]))); + uint128_t_to_string(le128_to_cpu(&log_data[SCAO_PMUW]))); printf(" Physical media units read : %s\n", - uint128_t_to_string(le128_to_cpu(&log_data[SCAO_PMUR]))); + uint128_t_to_string(le128_to_cpu(&log_data[SCAO_PMUR]))); printf(" Bad user nand blocks Raw : %"PRIu64"\n", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BUNBR] & 0x0000FFFFFFFFFFFF)); + (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])); + (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)); + (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])); + (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])); + (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])); + (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])); + (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])); + (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)); + (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])); + (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])); + (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])); + (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])); + (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])); + (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])); + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UIO])); + printf(" Securqity 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])); + (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]))); + 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]))); + 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 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("%"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]); + (__u8)log_data[SCAO_EVF]); printf(" Point Version Field : %"PRIu16"\n", - (uint16_t)log_data[SCAO_PVF]); + (uint16_t)log_data[SCAO_PVF]); printf(" Minor Version Field : %"PRIu16"\n", - (uint16_t)log_data[SCAO_MIVF]); + (uint16_t)log_data[SCAO_MIVF]); printf(" Major Version Field : %d\n", - (__u8)log_data[SCAO_MAVF]); + (__u8)log_data[SCAO_MAVF]); printf(" NVMe Errata Version : %d\n", - (__u8)log_data[SCAO_NEV]); + (__u8)log_data[SCAO_NEV]); printf(" PCIe Link Retraining Count : %"PRIu64"\n", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PLRC])); + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PLRC])); } if (smart_log_ver > 3) { printf(" Power State Change Count : %"PRIu64"\n", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PSCC])); + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PSCC])); } printf("\n"); } static void wdc_print_smart_cloud_attr_C0_json(void *data) { - __u8 *log_data = (__u8*)data; - struct json_object *root; + __u8 *log_data = (__u8 *)data; + struct json_object *root = json_create_object(); uint16_t smart_log_ver = 0; - root = json_create_object(); json_object_add_value_uint128(root, "Physical media units written", le128_to_cpu(&log_data[SCAO_PMUW])); json_object_add_value_uint128(root, "Physical media units read", @@ -6065,7 +6137,7 @@ static void wdc_print_smart_cloud_attr_C0_json(void *data) 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)); + (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", @@ -6095,11 +6167,13 @@ static void wdc_print_smart_cloud_attr_C0_json(void *data) 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]), + + 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){ + 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", @@ -6113,7 +6187,7 @@ static void wdc_print_smart_cloud_attr_C0_json(void *data) json_object_add_value_uint64(root, "PCIe Link Retraining Count", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PLRC])); } - if(smart_log_ver > 3) { + if (smart_log_ver > 3) { json_object_add_value_uint64(root, "Power State Change Count", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PSCC])); } @@ -6125,9 +6199,9 @@ static void wdc_print_smart_cloud_attr_C0_json(void *data) static void wdc_print_eol_c0_normal(void *data) { - __u8 *log_data = (__u8*)data; + __u8 *log_data = (__u8 *)data; - printf(" End of Life Log Page 0xC0 :- \n"); + printf(" End of Life Log Page 0xC0 :-\n"); printf(" Realloc Block Count %"PRIu32"\n", (uint32_t)le32_to_cpu(log_data[EOL_RBC])); @@ -6148,10 +6222,8 @@ static void wdc_print_eol_c0_normal(void *data) static void wdc_print_eol_c0_json(void *data) { - __u8 *log_data = (__u8*)data; - struct json_object *root; - - root = json_create_object(); + __u8 *log_data = (__u8 *)data; + struct json_object *root = json_create_object(); json_object_add_value_uint(root, "Realloc Block Count", (uint32_t)le32_to_cpu(log_data[EOL_RBC])); @@ -6176,7 +6248,7 @@ static void wdc_print_eol_c0_json(void *data) static int wdc_print_ext_smart_cloud_log(void *data, int fmt) { if (!data) { - fprintf(stderr, "ERROR : WDC : Invalid buffer to read 0xC0 V1 log\n"); + fprintf(stderr, "ERROR: WDC: Invalid buffer to read 0xC0 V1 log\n"); return -1; } switch (fmt) { @@ -6193,7 +6265,7 @@ static int wdc_print_ext_smart_cloud_log(void *data, int fmt) static int wdc_print_c0_cloud_attr_log(void *data, int fmt) { if (!data) { - fprintf(stderr, "ERROR : WDC : Invalid buffer to read 0xC0 log\n"); + fprintf(stderr, "ERROR: WDC: Invalid buffer to read 0xC0 log\n"); return -1; } switch (fmt) { @@ -6210,7 +6282,7 @@ static int wdc_print_c0_cloud_attr_log(void *data, int fmt) static int wdc_print_c0_eol_log(void *data, int fmt) { if (!data) { - fprintf(stderr, "ERROR : WDC : Invalid buffer to read 0xC0 log\n"); + fprintf(stderr, "ERROR: WDC: Invalid buffer to read 0xC0 log\n"); return -1; } switch (fmt) { @@ -6224,199 +6296,232 @@ static int wdc_print_c0_eol_log(void *data, int fmt) return 0; } -static int wdc_get_c0_log_page(nvme_root_t r, struct nvme_dev *dev, char *format, - int uuid_index, __u32 namespace_id) +static int wdc_get_c0_log_page_sn_customer_id_0x100X(struct nvme_dev *dev, int uuid_index, + char *format, __u32 namespace_id, int fmt) +{ + int ret; + __u8 *data; + int i; + + if (!uuid_index) { + data = (__u8 *)malloc(sizeof(__u8) * WDC_NVME_SMART_CLOUD_ATTR_LEN); + if (!data) { + fprintf(stderr, "ERROR: WDC: malloc: %s\n", strerror(errno)); + return -1; + } + + if (namespace_id == NVME_NSID_ALL) { + ret = nvme_get_nsid(dev_fd(dev), &namespace_id); + if (ret < 0) + namespace_id = NVME_NSID_ALL; + } + + /* Get the 0xC0 log data */ + struct nvme_get_log_args args = { + .args_size = sizeof(args), + .fd = dev_fd(dev), + .lid = WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID, + .nsid = namespace_id, + .lpo = 0, + .lsp = NVME_LOG_LSP_NONE, + .lsi = 0, + .rae = false, + .uuidx = uuid_index, + .csi = NVME_CSI_NVM, + .ot = false, + .len = WDC_NVME_SMART_CLOUD_ATTR_LEN, + .log = data, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + ret = nvme_get_log(&args); + + if (strcmp(format, "json")) + nvme_show_status(ret); + + if (!ret) { + /* Verify GUID matches */ + for (i = 0; i < 16; i++) { + if (scao_guid[i] != data[SCAO_LPG + i]) { + fprintf(stderr, "ERROR: WDC: Unknown GUID in C0 Log Page data\n"); + int j; + + fprintf(stderr, "ERROR: WDC: Expected GUID: 0x"); + for (j = 0; j < 16; j++) + fprintf(stderr, "%x", scao_guid[j]); + fprintf(stderr, "\nERROR: WDC: Actual GUID: 0x"); + for (j = 0; j < 16; j++) + fprintf(stderr, "%x", data[SCAO_LPG + j]); + fprintf(stderr, "\n"); + + ret = -1; + break; + } + } + + if (!ret) + /* parse the data */ + wdc_print_c0_cloud_attr_log(data, fmt); + } else { + fprintf(stderr, "ERROR: WDC: Unable to read C0 Log Page data\n"); + ret = -1; + } + + free(data); + } else if (uuid_index == 1) { + data = (__u8 *)malloc(sizeof(__u8) * WDC_NVME_EOL_STATUS_LOG_LEN); + if (!data) { + fprintf(stderr, "ERROR: WDC: malloc: %s\n", strerror(errno)); + return -1; + } + + /* Get the 0xC0 log data */ + struct nvme_get_log_args args = { + .args_size = sizeof(args), + .fd = dev_fd(dev), + .lid = WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, + .nsid = NVME_NSID_ALL, + .lpo = 0, + .lsp = NVME_LOG_LSP_NONE, + .lsi = 0, + .rae = false, + .uuidx = uuid_index, + .csi = NVME_CSI_NVM, + .ot = false, + .len = WDC_NVME_EOL_STATUS_LOG_LEN, + .log = data, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + ret = nvme_get_log(&args); + + if (strcmp(format, "json")) + nvme_show_status(ret); + + if (!ret) { + /* parse the data */ + wdc_print_c0_eol_log(data, fmt); + } else { + fprintf(stderr, "ERROR: WDC: Unable to read C0 Log Page data\n"); + ret = -1; + } + + free(data); + } else { + fprintf(stderr, "ERROR: WDC: Unknown uuid index\n"); + ret = -1; + } + + return ret; +} + +static int wdc_get_c0_log_page_sn(nvme_root_t r, struct nvme_dev *dev, int uuid_index, char *format, + __u32 namespace_id, int fmt) +{ + int ret = 0; + __u32 cust_id; + __u8 *data; + + cust_id = wdc_get_fw_cust_id(r, dev); + if (cust_id == WDC_INVALID_CUSTOMER_ID) { + fprintf(stderr, "%s: ERROR: WDC: invalid customer id\n", __func__); + return -1; + } + + if ((cust_id == WDC_CUSTOMER_ID_0x1004) || (cust_id == WDC_CUSTOMER_ID_0x1008) || + (cust_id == WDC_CUSTOMER_ID_0x1005)) { + ret = wdc_get_c0_log_page_sn_customer_id_0x100X(dev, uuid_index, format, + namespace_id, fmt); + } else { + data = (__u8 *)malloc(sizeof(__u8) * WDC_NVME_EOL_STATUS_LOG_LEN); + if (!data) { + fprintf(stderr, "ERROR: WDC: malloc: %s\n", strerror(errno)); + return -1; + } + + /* Get the 0xC0 log data */ + ret = nvme_get_log_simple(dev_fd(dev), + WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, + WDC_NVME_EOL_STATUS_LOG_LEN, + data); + + if (strcmp(format, "json")) + nvme_show_status(ret); + + if (!ret) { + /* parse the data */ + wdc_print_c0_eol_log(data, fmt); + } else { + fprintf(stderr, "ERROR: WDC: Unable to read C0 Log Page data\n"); + ret = -1; + } + + free(data); + } + + return ret; +} + +static int wdc_get_c0_log_page(nvme_root_t r, struct nvme_dev *dev, char *format, int uuid_index, + __u32 namespace_id) { int ret = 0; int fmt = -1; - int i = 0; __u8 *data; - __u32 cust_id; uint32_t device_id, read_vendor_id; if (!wdc_check_device(r, dev)) return -1; fmt = validate_output_format(format); if (fmt < 0) { - fprintf(stderr, "ERROR : WDC : invalid output format\n"); + fprintf(stderr, "ERROR: WDC: invalid output format\n"); return fmt; } ret = wdc_get_pci_ids(r, dev, &device_id, &read_vendor_id); switch (device_id) { - case WDC_NVME_SN640_DEV_ID: + fallthrough; case WDC_NVME_SN640_DEV_ID_1: + fallthrough; case WDC_NVME_SN640_DEV_ID_2: + fallthrough; case WDC_NVME_SN640_DEV_ID_3: + fallthrough; case WDC_NVME_SN840_DEV_ID: + fallthrough; case WDC_NVME_SN840_DEV_ID_1: + fallthrough; case WDC_NVME_SN860_DEV_ID: + fallthrough; case WDC_NVME_SN650_DEV_ID: + fallthrough; case WDC_NVME_SN650_DEV_ID_1: + fallthrough; case WDC_NVME_SN650_DEV_ID_2: + fallthrough; case WDC_NVME_SN650_DEV_ID_3: + fallthrough; case WDC_NVME_SN650_DEV_ID_4: + fallthrough; case WDC_NVME_SN655_DEV_ID: + fallthrough; case WDC_NVME_SN560_DEV_ID_1: + fallthrough; case WDC_NVME_SN560_DEV_ID_2: + fallthrough; case WDC_NVME_SN560_DEV_ID_3: + fallthrough; case WDC_NVME_SN550_DEV_ID: - cust_id = wdc_get_fw_cust_id(r, dev); - if (cust_id == WDC_INVALID_CUSTOMER_ID) { - fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__); - return -1; - } - - if ((cust_id == WDC_CUSTOMER_ID_0x1004) || (cust_id == WDC_CUSTOMER_ID_0x1008) || (cust_id == WDC_CUSTOMER_ID_0x1005)) - { - if (uuid_index == 0) - { - if ((data = (__u8*) malloc(sizeof (__u8) * WDC_NVME_SMART_CLOUD_ATTR_LEN)) == NULL) { - fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); - return -1; - } - - if (namespace_id == NVME_NSID_ALL) { - ret = nvme_get_nsid(dev_fd(dev), - &namespace_id); - if (ret < 0) { - namespace_id = NVME_NSID_ALL; - } - } - - /* Get the 0xC0 log data */ - struct nvme_get_log_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .lid = WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID, - .nsid = namespace_id, - .lpo = 0, - .lsp = NVME_LOG_LSP_NONE, - .lsi = 0, - .rae = false, - .uuidx = uuid_index, - .csi = NVME_CSI_NVM, - .ot = false, - .len = WDC_NVME_SMART_CLOUD_ATTR_LEN, - .log = data, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; - ret = nvme_get_log(&args); - - if (strcmp(format, "json")) - nvme_show_status(ret); - - if (ret == 0) { - - /* Verify GUID matches */ - for (i=0; i<16; i++) { - if (scao_guid[i] != data[SCAO_LPG + i]) { - fprintf(stderr, "ERROR : WDC : Unknown GUID in C0 Log Page data\n"); - int j; - fprintf(stderr, "ERROR : WDC : Expected GUID: 0x"); - for (j = 0; j<16; j++) { - fprintf(stderr, "%x", scao_guid[j]); - } - fprintf(stderr, "\nERROR : WDC : Actual GUID: 0x"); - for (j = 0; j<16; j++) { - fprintf(stderr, "%x", data[SCAO_LPG + j]); - } - fprintf(stderr, "\n"); - - ret = -1; - break; - } - } - - if (ret == 0) { - - /* parse the data */ - wdc_print_c0_cloud_attr_log(data, fmt); - } - } else { - fprintf(stderr, "ERROR : WDC : Unable to read C0 Log Page data\n"); - ret = -1; - } - - free(data); - } else if (uuid_index == 1) { - - if ((data = (__u8*) malloc(sizeof (__u8) * WDC_NVME_EOL_STATUS_LOG_LEN)) == NULL) { - fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); - return -1; - } - - /* Get the 0xC0 log data */ - struct nvme_get_log_args args = { - .args_size = sizeof(args), - .fd = dev_fd(dev), - .lid = WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, - .nsid = NVME_NSID_ALL, - .lpo = 0, - .lsp = NVME_LOG_LSP_NONE, - .lsi = 0, - .rae = false, - .uuidx = uuid_index, - .csi = NVME_CSI_NVM, - .ot = false, - .len = WDC_NVME_EOL_STATUS_LOG_LEN, - .log = data, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, - }; - ret = nvme_get_log(&args); - - if (strcmp(format, "json")) - nvme_show_status(ret); - - if (ret == 0) { - /* parse the data */ - wdc_print_c0_eol_log(data, fmt); - } else { - fprintf(stderr, "ERROR : WDC : Unable to read C0 Log Page data\n"); - ret = -1; - } - - free(data); - } else { - fprintf(stderr, "ERROR : WDC : Unknown uuid index\n"); - ret = -1; - } - } - else { - if ((data = (__u8*) malloc(sizeof (__u8) * WDC_NVME_EOL_STATUS_LOG_LEN)) == NULL) { - fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); - return -1; - } - - /* Get the 0xC0 log data */ - ret = nvme_get_log_simple(dev_fd(dev), - WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, - WDC_NVME_EOL_STATUS_LOG_LEN, - data); - - if (strcmp(format, "json")) - nvme_show_status(ret); - - if (ret == 0) { - /* parse the data */ - wdc_print_c0_eol_log(data, fmt); - } else { - fprintf(stderr, "ERROR : WDC : Unable to read C0 Log Page data\n"); - ret = -1; - } - - free(data); - } + ret = wdc_get_c0_log_page_sn(r, dev, uuid_index, format, namespace_id, fmt); break; - case WDC_NVME_ZN350_DEV_ID: + fallthrough; case WDC_NVME_ZN350_DEV_ID_1: - if ((data = (__u8*) malloc(sizeof (__u8) * WDC_NVME_SMART_CLOUD_ATTR_LEN)) == NULL) { - fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); + data = (__u8 *)malloc(sizeof(__u8) * WDC_NVME_SMART_CLOUD_ATTR_LEN); + if (!data) { + fprintf(stderr, "ERROR: WDC: malloc: %s\n", strerror(errno)); return -1; } @@ -6428,17 +6533,16 @@ static int wdc_get_c0_log_page(nvme_root_t r, struct nvme_dev *dev, char *format if (strcmp(format, "json")) nvme_show_status(ret); - if (ret == 0) { + if (!ret) { /* parse the data */ wdc_print_c0_cloud_attr_log(data, fmt); } else { - fprintf(stderr, "ERROR : WDC : Unable to read C0 Log Page data\n"); + fprintf(stderr, "ERROR: WDC: Unable to read C0 Log Page data\n"); ret = -1; } free(data); break; - case WDC_NVME_SN820CL_DEV_ID: /* Get the 0xC0 Extended Smart Cloud Attribute log data */ data = NULL; @@ -6448,20 +6552,19 @@ static int wdc_get_c0_log_page(nvme_root_t r, struct nvme_dev *dev, char *format if (strcmp(format, "json")) nvme_show_status(ret); - if (ret == 0) { + if (!ret) { /* parse the data */ wdc_print_ext_smart_cloud_log(data, fmt); } else { - fprintf(stderr, "ERROR : WDC : Unable to read C0 Log Page V1 data\n"); + fprintf(stderr, "ERROR: WDC: Unable to read C0 Log Page V1 data\n"); ret = -1; } if (data) free(data); break; - default: - fprintf(stderr, "ERROR : WDC : Unknown device id - 0x%x\n", device_id); + fprintf(stderr, "ERROR: WDC: Unknown device id - 0x%x\n", device_id); ret = -1; break; @@ -6475,7 +6578,7 @@ static int wdc_print_latency_monitor_log(struct nvme_dev *dev, int fmt) { if (!log_data) { - fprintf(stderr, "ERROR : WDC : Invalid C3 log data buffer\n"); + fprintf(stderr, "ERROR: WDC: Invalid C3 log data buffer\n"); return -1; } switch (fmt) { @@ -6492,7 +6595,7 @@ static int wdc_print_latency_monitor_log(struct nvme_dev *dev, static int wdc_print_error_rec_log(struct wdc_ocp_c1_error_recovery_log *log_data, int fmt) { if (!log_data) { - fprintf(stderr, "ERROR : WDC : Invalid C1 log data buffer\n"); + fprintf(stderr, "ERROR: WDC: Invalid C1 log data buffer\n"); return -1; } switch (fmt) { @@ -6509,7 +6612,7 @@ static int wdc_print_error_rec_log(struct wdc_ocp_c1_error_recovery_log *log_dat static int wdc_print_dev_cap_log(struct wdc_ocp_C4_dev_cap_log *log_data, int fmt) { if (!log_data) { - fprintf(stderr, "ERROR : WDC : Invalid C4 log data buffer\n"); + fprintf(stderr, "ERROR: WDC: Invalid C4 log data buffer\n"); return -1; } switch (fmt) { @@ -6526,7 +6629,7 @@ static int wdc_print_dev_cap_log(struct wdc_ocp_C4_dev_cap_log *log_data, int fm static int wdc_print_unsupported_reqs_log(struct wdc_ocp_C5_unsupported_reqs *log_data, int fmt) { if (!log_data) { - fprintf(stderr, "ERROR : WDC : Invalid C5 log data buffer\n"); + fprintf(stderr, "ERROR: WDC: Invalid C5 log data buffer\n"); return -1; } switch (fmt) { @@ -6543,7 +6646,7 @@ static int wdc_print_unsupported_reqs_log(struct wdc_ocp_C5_unsupported_reqs *lo static int wdc_print_fb_ca_log(struct wdc_ssd_ca_perf_stats *perf, int fmt) { if (!perf) { - fprintf(stderr, "ERROR : WDC : Invalid buffer to read perf stats\n"); + fprintf(stderr, "ERROR: WDC: Invalid buffer to read perf stats\n"); return -1; } switch (fmt) { @@ -6560,7 +6663,7 @@ static int wdc_print_fb_ca_log(struct wdc_ssd_ca_perf_stats *perf, int fmt) static int wdc_print_bd_ca_log(struct nvme_dev *dev, void *bd_data, int fmt) { if (!bd_data) { - fprintf(stderr, "ERROR : WDC : Invalid buffer to read data\n"); + fprintf(stderr, "ERROR: WDC: Invalid buffer to read data\n"); return -1; } switch (fmt) { @@ -6571,7 +6674,7 @@ static int wdc_print_bd_ca_log(struct nvme_dev *dev, void *bd_data, int fmt) wdc_print_bd_ca_log_json(bd_data); break; default: - fprintf(stderr, "ERROR : WDC : Unknown format - %d\n", fmt); + fprintf(stderr, "ERROR: WDC: Unknown format - %d\n", fmt); return -1; } return 0; @@ -6580,7 +6683,7 @@ static int wdc_print_bd_ca_log(struct nvme_dev *dev, void *bd_data, int fmt) static int wdc_print_d0_log(struct wdc_ssd_d0_smart_log *perf, int fmt) { if (!perf) { - fprintf(stderr, "ERROR : WDC : Invalid buffer to read perf stats\n"); + fprintf(stderr, "ERROR: WDC: Invalid buffer to read perf stats\n"); return -1; } switch (fmt) { @@ -6597,7 +6700,7 @@ static int wdc_print_d0_log(struct wdc_ssd_d0_smart_log *perf, int fmt) static int wdc_print_fw_act_history_log(__u8 *data, int num_entries, int fmt, __u32 cust_id, __u32 vendor_id) { if (!data) { - fprintf(stderr, "ERROR : WDC : Invalid buffer to read fw activate history entries\n"); + fprintf(stderr, "ERROR: WDC: Invalid buffer to read fw activate history entries\n"); return -1; } @@ -6625,37 +6728,35 @@ static int wdc_get_ca_log_page(nvme_root_t r, struct nvme_dev *dev, char *format return -1; fmt = validate_output_format(format); if (fmt < 0) { - fprintf(stderr, "ERROR : WDC : invalid output format\n"); + fprintf(stderr, "ERROR: WDC: invalid output format\n"); return fmt; } /* verify the 0xCA log page is supported */ if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == false) { - fprintf(stderr, "ERROR : WDC : 0xCA Log Page not supported\n"); + fprintf(stderr, "ERROR: WDC: 0xCA Log Page not supported\n"); return -1; } /* get the FW customer id */ cust_id = wdc_get_fw_cust_id(r, dev); if (cust_id == WDC_INVALID_CUSTOMER_ID) { - fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__); + fprintf(stderr, "%s: ERROR: WDC: invalid customer id\n", __func__); return -1; } ret = wdc_get_pci_ids(r, dev, &read_device_id, &read_vendor_id); switch (read_device_id) { - case WDC_NVME_SN200_DEV_ID: - if (cust_id == WDC_CUSTOMER_ID_0x1005) { - - if ((data = (__u8*) malloc(sizeof (__u8) * WDC_FB_CA_LOG_BUF_LEN)) == NULL) { - fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); + data = (__u8 *)malloc(sizeof(__u8) * WDC_FB_CA_LOG_BUF_LEN); + if (!data) { + fprintf(stderr, "ERROR: WDC: malloc: %s\n", strerror(errno)); return -1; } - memset(data, 0, sizeof (__u8) * WDC_FB_CA_LOG_BUF_LEN); + memset(data, 0, sizeof(__u8) * WDC_FB_CA_LOG_BUF_LEN); ret = nvme_get_log_simple(dev_fd(dev), WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, @@ -6663,36 +6764,41 @@ static int wdc_get_ca_log_page(nvme_root_t r, struct nvme_dev *dev, char *format if (strcmp(format, "json")) nvme_show_status(ret); - if (ret == 0) { + if (!ret) { /* parse the data */ perf = (struct wdc_ssd_ca_perf_stats *)(data); ret = wdc_print_fb_ca_log(perf, fmt); } else { - fprintf(stderr, "ERROR : WDC : Unable to read CA Log Page data\n"); + fprintf(stderr, "ERROR: WDC: Unable to read CA Log Page data\n"); ret = -1; } } else { - fprintf(stderr, "ERROR : WDC : Unsupported Customer id, id = 0x%x\n", cust_id); + fprintf(stderr, "ERROR: WDC: Unsupported Customer id, id = 0x%x\n", cust_id); return -1; } break; - case WDC_NVME_SN640_DEV_ID: + fallthrough; case WDC_NVME_SN640_DEV_ID_1: + fallthrough; case WDC_NVME_SN640_DEV_ID_2: + fallthrough; case WDC_NVME_SN640_DEV_ID_3: + fallthrough; case WDC_NVME_SN840_DEV_ID: + fallthrough; case WDC_NVME_SN840_DEV_ID_1: + fallthrough; case WDC_NVME_SN860_DEV_ID: if (cust_id == WDC_CUSTOMER_ID_0x1005) { - - if ((data = (__u8*) malloc(sizeof (__u8) * WDC_FB_CA_LOG_BUF_LEN)) == NULL) { - fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); + data = (__u8 *)malloc(sizeof(__u8) * WDC_FB_CA_LOG_BUF_LEN); + if (!data) { + fprintf(stderr, "ERROR: WDC: malloc: %s\n", strerror(errno)); return -1; } - memset(data, 0, sizeof (__u8) * WDC_FB_CA_LOG_BUF_LEN); + memset(data, 0, sizeof(__u8) * WDC_FB_CA_LOG_BUF_LEN); ret = nvme_get_log_simple(dev_fd(dev), WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, @@ -6700,49 +6806,44 @@ static int wdc_get_ca_log_page(nvme_root_t r, struct nvme_dev *dev, char *format if (strcmp(format, "json")) nvme_show_status(ret); - if (ret == 0) { + if (!ret) { /* parse the data */ perf = (struct wdc_ssd_ca_perf_stats *)(data); ret = wdc_print_fb_ca_log(perf, fmt); } else { - fprintf(stderr, "ERROR : WDC : Unable to read CA Log Page data\n"); + fprintf(stderr, "ERROR: WDC: Unable to read CA Log Page data\n"); ret = -1; } } else if ((cust_id == WDC_CUSTOMER_ID_GN) || (cust_id == WDC_CUSTOMER_ID_GD) || (cust_id == WDC_CUSTOMER_ID_BD)) { - if ((data = (__u8*) malloc(sizeof (__u8) * WDC_BD_CA_LOG_BUF_LEN)) == NULL) { - fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); + data = (__u8 *)malloc(sizeof(__u8) * WDC_BD_CA_LOG_BUF_LEN); + if (!data) { + fprintf(stderr, "ERROR: WDC: malloc: %s\n", strerror(errno)); return -1; } - memset(data, 0, sizeof (__u8) * WDC_BD_CA_LOG_BUF_LEN); + memset(data, 0, sizeof(__u8) * WDC_BD_CA_LOG_BUF_LEN); ret = nvme_get_log_simple(dev_fd(dev), WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, WDC_BD_CA_LOG_BUF_LEN, data); if (strcmp(format, "json")) nvme_show_status(ret); - if (ret == 0) { + if (!ret) { /* parse the data */ ret = wdc_print_bd_ca_log(dev, data, fmt); } else { - fprintf(stderr, "ERROR : WDC : Unable to read CA Log Page data\n"); + fprintf(stderr, "ERROR: WDC: Unable to read CA Log Page data\n"); ret = -1; } - - break; } else { - - fprintf(stderr, "ERROR : WDC : Unsupported Customer id, id = 0x%x\n", cust_id); + fprintf(stderr, "ERROR: WDC: Unsupported Customer id, id = 0x%x\n", cust_id); return -1; } break; - default: - - fprintf(stderr, "ERROR : WDC : Log page 0xCA not supported for this device\n"); + fprintf(stderr, "ERROR: WDC: Log page 0xCA not supported for this device\n"); return -1; - break; } free(data); @@ -6767,42 +6868,42 @@ static int wdc_get_c1_log_page(nvme_root_t r, struct nvme_dev *dev, return -1; fmt = validate_output_format(format); if (fmt < 0) { - fprintf(stderr, "ERROR : WDC : invalid output format\n"); + fprintf(stderr, "ERROR: WDC: invalid output format\n"); return fmt; } if (interval < 1 || interval > 15) { - fprintf(stderr, "ERROR : WDC : interval out of range [1-15]\n"); + fprintf(stderr, "ERROR: WDC: interval out of range [1-15]\n"); return -1; } - if ((data = (__u8*) malloc(sizeof (__u8) * WDC_ADD_LOG_BUF_LEN)) == NULL) { - fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); + data = (__u8 *)malloc(sizeof(__u8) * WDC_ADD_LOG_BUF_LEN); + if (!data) { + fprintf(stderr, "ERROR: WDC: malloc: %s\n", strerror(errno)); return -1; } - memset(data, 0, sizeof (__u8) * WDC_ADD_LOG_BUF_LEN); + memset(data, 0, sizeof(__u8) * WDC_ADD_LOG_BUF_LEN); ret = nvme_get_log_simple(dev_fd(dev), WDC_NVME_ADD_LOG_OPCODE, WDC_ADD_LOG_BUF_LEN, data); if (strcmp(format, "json")) nvme_show_status(ret); - if (ret == 0) { - l = (struct wdc_log_page_header*)data; + if (!ret) { + l = (struct wdc_log_page_header *)data; total_subpages = l->num_subpages + WDC_NVME_GET_STAT_PERF_INTERVAL_LIFETIME - 1; for (i = 0, p = data + skip_cnt; i < total_subpages; i++, p += skip_cnt) { - sph = (struct wdc_log_page_subpage_header *) p; + sph = (struct wdc_log_page_subpage_header *)p; if (sph->spcode == WDC_GET_LOG_PAGE_SSD_PERFORMANCE) { if (sph->pcset == interval) { - perf = (struct wdc_ssd_perf_stats *) (p + 4); + perf = (struct wdc_ssd_perf_stats *)(p + 4); ret = wdc_print_log(perf, fmt); break; } } skip_cnt = le16_to_cpu(sph->subpage_length) + 4; } - if (ret) { - fprintf(stderr, "ERROR : WDC : Unable to read data from buffer\n"); - } + if (ret) + fprintf(stderr, "ERROR: WDC: Unable to read data from buffer\n"); } free(data); return ret; @@ -6820,15 +6921,16 @@ static int wdc_get_c3_log_page(nvme_root_t r, struct nvme_dev *dev, char *format return -1; fmt = validate_output_format(format); if (fmt < 0) { - fprintf(stderr, "ERROR : WDC : invalid output format\n"); + fprintf(stderr, "ERROR: WDC: invalid output format\n"); return fmt; } - if ((data = (__u8 *) malloc(sizeof(__u8) * WDC_LATENCY_MON_LOG_BUF_LEN)) == NULL) { - fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); + data = (__u8 *)malloc(sizeof(__u8) * WDC_LATENCY_MON_LOG_BUF_LEN); + if (!data) { + fprintf(stderr, "ERROR: WDC: malloc: %s\n", strerror(errno)); return -1; } - memset(data, 0, sizeof (__u8) * WDC_LATENCY_MON_LOG_BUF_LEN); + memset(data, 0, sizeof(__u8) * WDC_LATENCY_MON_LOG_BUF_LEN); ret = nvme_get_log_simple(dev_fd(dev), WDC_LATENCY_MON_LOG_ID, WDC_LATENCY_MON_LOG_BUF_LEN, data); @@ -6836,30 +6938,29 @@ static int wdc_get_c3_log_page(nvme_root_t r, struct nvme_dev *dev, char *format if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret, false), ret); - if (ret == 0) { - log_data = (struct wdc_ssd_latency_monitor_log*)data; + if (!ret) { + log_data = (struct wdc_ssd_latency_monitor_log *)data; /* check log page version */ if (log_data->log_page_version != WDC_LATENCY_MON_VERSION) { - fprintf(stderr, "ERROR : WDC : invalid latency monitor version\n"); + fprintf(stderr, "ERROR: WDC: invalid latency monitor version\n"); ret = -1; - goto out; + goto out; } /* check log page guid */ /* Verify GUID matches */ - for (i=0; i<16; i++) { - if (wdc_lat_mon_guid[i] != log_data->log_page_guid[i]) { - fprintf(stderr, "ERROR : WDC : Unknown GUID in C3 Log Page data\n"); + for (i = 0; i < 16; i++) { + if (wdc_lat_mon_guid[i] != log_data->log_page_guid[i]) { + fprintf(stderr, "ERROR: WDC: Unknown GUID in C3 Log Page data\n"); int j; - fprintf(stderr, "ERROR : WDC : Expected GUID: 0x"); - for (j = 0; j<16; j++) { + + fprintf(stderr, "ERROR: WDC: Expected GUID: 0x"); + for (j = 0; j < 16; j++) fprintf(stderr, "%x", wdc_lat_mon_guid[j]); - } - fprintf(stderr, "\nERROR : WDC : Actual GUID: 0x"); - for (j = 0; j<16; j++) { + fprintf(stderr, "\nERROR: WDC: Actual GUID: 0x"); + for (j = 0; j < 16; j++) fprintf(stderr, "%x", log_data->log_page_guid[j]); - } fprintf(stderr, "\n"); ret = -1; @@ -6870,7 +6971,7 @@ static int wdc_get_c3_log_page(nvme_root_t r, struct nvme_dev *dev, char *format /* parse the data */ wdc_print_latency_monitor_log(dev, log_data, fmt); } else { - fprintf(stderr, "ERROR : WDC : Unable to read C3 data from buffer\n"); + fprintf(stderr, "ERROR: WDC: Unable to read C3 data from buffer\n"); } out: @@ -6891,15 +6992,16 @@ static int wdc_get_ocp_c1_log_page(nvme_root_t r, struct nvme_dev *dev, char *fo return -1; fmt = validate_output_format(format); if (fmt < 0) { - fprintf(stderr, "ERROR : WDC : invalid output format\n"); + fprintf(stderr, "ERROR: WDC: invalid output format\n"); return fmt; } - if ((data = (__u8 *) malloc(sizeof(__u8) * WDC_ERROR_REC_LOG_BUF_LEN)) == NULL) { - fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); + data = (__u8 *)malloc(sizeof(__u8) * WDC_ERROR_REC_LOG_BUF_LEN); + if (!data) { + fprintf(stderr, "ERROR: WDC: malloc: %s\n", strerror(errno)); return -1; } - memset(data, 0, sizeof (__u8) * WDC_ERROR_REC_LOG_BUF_LEN); + memset(data, 0, sizeof(__u8) * WDC_ERROR_REC_LOG_BUF_LEN); ret = nvme_get_log_simple(dev_fd(dev), WDC_ERROR_REC_LOG_ID, WDC_ERROR_REC_LOG_BUF_LEN, data); @@ -6907,30 +7009,29 @@ static int wdc_get_ocp_c1_log_page(nvme_root_t r, struct nvme_dev *dev, char *fo if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret, false), ret); - if (ret == 0) { + if (!ret) { log_data = (struct wdc_ocp_c1_error_recovery_log *)data; /* check log page version */ if ((log_data->log_page_version != WDC_ERROR_REC_LOG_VERSION1) && - (log_data->log_page_version != WDC_ERROR_REC_LOG_VERSION2)) { - fprintf(stderr, "ERROR : WDC : invalid error recovery log version - %d\n", log_data->log_page_version); + (log_data->log_page_version != WDC_ERROR_REC_LOG_VERSION2)) { + fprintf(stderr, "ERROR: WDC: invalid error recovery log version - %d\n", log_data->log_page_version); ret = -1; goto out; } /* Verify GUID matches */ - for (i=0; i < WDC_OCP_C1_GUID_LENGTH; i++) { - if (wdc_ocp_c1_guid[i] != log_data->log_page_guid[i]) { - fprintf(stderr, "ERROR : WDC : Unknown GUID in C1 Log Page data\n"); + for (i = 0; i < WDC_OCP_C1_GUID_LENGTH; i++) { + if (wdc_ocp_c1_guid[i] != log_data->log_page_guid[i]) { + fprintf(stderr, "ERROR: WDC: Unknown GUID in C1 Log Page data\n"); int j; - fprintf(stderr, "ERROR : WDC : Expected GUID: 0x"); - for (j = 0; j<16; j++) { + + fprintf(stderr, "ERROR: WDC: Expected GUID: 0x"); + for (j = 0; j < 16; j++) fprintf(stderr, "%x", wdc_ocp_c1_guid[j]); - } - fprintf(stderr, "\nERROR : WDC : Actual GUID: 0x"); - for (j = 0; j<16; j++) { + fprintf(stderr, "\nERROR: WDC: Actual GUID: 0x"); + for (j = 0; j < 16; j++) fprintf(stderr, "%x", log_data->log_page_guid[j]); - } fprintf(stderr, "\n"); ret = -1; @@ -6941,7 +7042,7 @@ static int wdc_get_ocp_c1_log_page(nvme_root_t r, struct nvme_dev *dev, char *fo /* parse the data */ wdc_print_error_rec_log(log_data, fmt); } else { - fprintf(stderr, "ERROR : WDC : Unable to read error recovery (C1) data from buffer\n"); + fprintf(stderr, "ERROR: WDC: Unable to read error recovery (C1) data from buffer\n"); } out: @@ -6961,15 +7062,16 @@ static int wdc_get_ocp_c4_log_page(nvme_root_t r, struct nvme_dev *dev, char *fo return -1; fmt = validate_output_format(format); if (fmt < 0) { - fprintf(stderr, "ERROR : WDC : invalid output format\n"); + fprintf(stderr, "ERROR: WDC: invalid output format\n"); return fmt; } - if ((data = (__u8 *) malloc(sizeof(__u8) * WDC_DEV_CAP_LOG_BUF_LEN)) == NULL) { - fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); + data = (__u8 *)malloc(sizeof(__u8) * WDC_DEV_CAP_LOG_BUF_LEN); + if (!data) { + fprintf(stderr, "ERROR: WDC: malloc: %s\n", strerror(errno)); return -1; } - memset(data, 0, sizeof (__u8) * WDC_DEV_CAP_LOG_BUF_LEN); + memset(data, 0, sizeof(__u8) * WDC_DEV_CAP_LOG_BUF_LEN); ret = nvme_get_log_simple(dev_fd(dev), WDC_DEV_CAP_LOG_ID, WDC_DEV_CAP_LOG_BUF_LEN, data); @@ -6977,29 +7079,28 @@ static int wdc_get_ocp_c4_log_page(nvme_root_t r, struct nvme_dev *dev, char *fo if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret, false), ret); - if (ret == 0) { + if (!ret) { log_data = (struct wdc_ocp_C4_dev_cap_log *)data; /* check log page version */ if (log_data->log_page_version != WDC_DEV_CAP_LOG_VERSION) { - fprintf(stderr, "ERROR : WDC : invalid device capabilities log version - %d\n", log_data->log_page_version); + fprintf(stderr, "ERROR: WDC: invalid device capabilities log version - %d\n", log_data->log_page_version); ret = -1; goto out; } /* Verify GUID matches */ - for (i=0; i < WDC_OCP_C4_GUID_LENGTH; i++) { - if (wdc_ocp_c4_guid[i] != log_data->log_page_guid[i]) { - fprintf(stderr, "ERROR : WDC : Unknown GUID in C4 Log Page data\n"); + for (i = 0; i < WDC_OCP_C4_GUID_LENGTH; i++) { + if (wdc_ocp_c4_guid[i] != log_data->log_page_guid[i]) { + fprintf(stderr, "ERROR: WDC: Unknown GUID in C4 Log Page data\n"); int j; - fprintf(stderr, "ERROR : WDC : Expected GUID: 0x"); - for (j = 0; j<16; j++) { + + fprintf(stderr, "ERROR: WDC: Expected GUID: 0x"); + for (j = 0; j < 16; j++) fprintf(stderr, "%x", wdc_ocp_c4_guid[j]); - } - fprintf(stderr, "\nERROR : WDC : Actual GUID: 0x"); - for (j = 0; j<16; j++) { + fprintf(stderr, "\nERROR: WDC: Actual GUID: 0x"); + for (j = 0; j < 16; j++) fprintf(stderr, "%x", log_data->log_page_guid[j]); - } fprintf(stderr, "\n"); ret = -1; @@ -7010,7 +7111,7 @@ static int wdc_get_ocp_c4_log_page(nvme_root_t r, struct nvme_dev *dev, char *fo /* parse the data */ wdc_print_dev_cap_log(log_data, fmt); } else { - fprintf(stderr, "ERROR : WDC : Unable to read device capabilities (C4) data from buffer\n"); + fprintf(stderr, "ERROR: WDC: Unable to read device capabilities (C4) data from buffer\n"); } out: @@ -7030,15 +7131,16 @@ static int wdc_get_ocp_c5_log_page(nvme_root_t r, struct nvme_dev *dev, char *fo return -1; fmt = validate_output_format(format); if (fmt < 0) { - fprintf(stderr, "ERROR : WDC : invalid output format\n"); + fprintf(stderr, "ERROR: WDC: invalid output format\n"); return fmt; } - if ((data = (__u8 *) malloc(sizeof(__u8) * WDC_UNSUPPORTED_REQS_LOG_BUF_LEN)) == NULL) { - fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); + data = (__u8 *)malloc(sizeof(__u8) * WDC_UNSUPPORTED_REQS_LOG_BUF_LEN); + if (!data) { + fprintf(stderr, "ERROR: WDC: malloc: %s\n", strerror(errno)); return -1; } - memset(data, 0, sizeof (__u8) * WDC_UNSUPPORTED_REQS_LOG_BUF_LEN); + memset(data, 0, sizeof(__u8) * WDC_UNSUPPORTED_REQS_LOG_BUF_LEN); ret = nvme_get_log_simple(dev_fd(dev), WDC_UNSUPPORTED_REQS_LOG_ID, WDC_UNSUPPORTED_REQS_LOG_BUF_LEN, data); @@ -7046,29 +7148,28 @@ static int wdc_get_ocp_c5_log_page(nvme_root_t r, struct nvme_dev *dev, char *fo if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret, false), ret); - if (ret == 0) { + if (!ret) { log_data = (struct wdc_ocp_C5_unsupported_reqs *)data; /* check log page version */ if (log_data->log_page_version != WDC_UNSUPPORTED_REQS_LOG_VERSION) { - fprintf(stderr, "ERROR : WDC : invalid unsupported requirements log version - %d\n", log_data->log_page_version); + fprintf(stderr, "ERROR: WDC: invalid unsupported requirements log version - %d\n", log_data->log_page_version); ret = -1; goto out; } /* Verify GUID matches */ - for (i=0; i < WDC_OCP_C5_GUID_LENGTH; i++) { - if (wdc_ocp_c5_guid[i] != log_data->log_page_guid[i]) { - fprintf(stderr, "ERROR : WDC : Unknown GUID in C5 Log Page data\n"); + for (i = 0; i < WDC_OCP_C5_GUID_LENGTH; i++) { + if (wdc_ocp_c5_guid[i] != log_data->log_page_guid[i]) { + fprintf(stderr, "ERROR: WDC: Unknown GUID in C5 Log Page data\n"); int j; - fprintf(stderr, "ERROR : WDC : Expected GUID: 0x"); - for (j = 0; j<16; j++) { + + fprintf(stderr, "ERROR: WDC: Expected GUID: 0x"); + for (j = 0; j < 16; j++) fprintf(stderr, "%x", wdc_ocp_c5_guid[j]); - } - fprintf(stderr, "\nERROR : WDC : Actual GUID: 0x"); - for (j = 0; j<16; j++) { + fprintf(stderr, "\nERROR: WDC: Actual GUID: 0x"); + for (j = 0; j < 16; j++) fprintf(stderr, "%x", log_data->log_page_guid[j]); - } fprintf(stderr, "\n"); ret = -1; @@ -7079,7 +7180,7 @@ static int wdc_get_ocp_c5_log_page(nvme_root_t r, struct nvme_dev *dev, char *fo /* parse the data */ wdc_print_unsupported_reqs_log(log_data, fmt); } else { - fprintf(stderr, "ERROR : WDC : Unable to read unsupported requirements (C5) data from buffer\n"); + fprintf(stderr, "ERROR: WDC: Unable to read unsupported requirements (C5) data from buffer\n"); } out: @@ -7098,21 +7199,22 @@ static int wdc_get_d0_log_page(nvme_root_t r, struct nvme_dev *dev, char *format return -1; fmt = validate_output_format(format); if (fmt < 0) { - fprintf(stderr, "ERROR : WDC : invalid output format\n"); + fprintf(stderr, "ERROR: WDC: invalid output format\n"); return fmt; } /* verify the 0xD0 log page is supported */ if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == false) { - fprintf(stderr, "ERROR : WDC : 0xD0 Log Page not supported\n"); + fprintf(stderr, "ERROR: WDC: 0xD0 Log Page not supported\n"); return -1; } - if ((data = (__u8*) malloc(sizeof (__u8) * WDC_NVME_VU_SMART_LOG_LEN)) == NULL) { - fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); + data = (__u8 *)malloc(sizeof(__u8) * WDC_NVME_VU_SMART_LOG_LEN); + if (!data) { + fprintf(stderr, "ERROR: WDC: malloc: %s\n", strerror(errno)); return -1; } - memset(data, 0, sizeof (__u8) * WDC_NVME_VU_SMART_LOG_LEN); + memset(data, 0, sizeof(__u8) * WDC_NVME_VU_SMART_LOG_LEN); ret = nvme_get_log_simple(dev_fd(dev), WDC_NVME_GET_VU_SMART_LOG_OPCODE, @@ -7120,12 +7222,12 @@ static int wdc_get_d0_log_page(nvme_root_t r, struct nvme_dev *dev, char *format if (strcmp(format, "json")) nvme_show_status(ret); - if (ret == 0) { + if (!ret) { /* parse the data */ perf = (struct wdc_ssd_d0_smart_log *)(data); ret = wdc_print_d0_log(perf, fmt); } else { - fprintf(stderr, "ERROR : WDC : Unable to read D0 Log Page data\n"); + fprintf(stderr, "ERROR: WDC: Unable to read D0 Log Page data\n"); ret = -1; } @@ -7179,12 +7281,12 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command, return ret; r = nvme_scan(NULL); - if (cfg.log_page_version == 0) { + if (!cfg.log_page_version) { uuid_index = 0; } else if (cfg.log_page_version == 1) { uuid_index = 1; } else { - fprintf(stderr, "ERROR : WDC: unsupported log page version for this command\n"); + fprintf(stderr, "ERROR: WDC: unsupported log page version for this command\n"); ret = -1; goto out; } @@ -7197,69 +7299,61 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command, goto out; } - if (num == 0) - { + if (!num) { page_mask |= WDC_ALL_PAGE_MASK; - } - else - { - for (i = 0; i < num; i++) - { - if (log_page_list[i] == 0xc0) { + } else { + for (i = 0; i < num; i++) { + if (log_page_list[i] == 0xc0) page_mask |= WDC_C0_PAGE_MASK; - } - if (log_page_list[i] == 0xc1) { + if (log_page_list[i] == 0xc1) page_mask |= WDC_C1_PAGE_MASK; - } - if (log_page_list[i] == 0xca) { + if (log_page_list[i] == 0xca) page_mask |= WDC_CA_PAGE_MASK; - } - if (log_page_list[i] == 0xd0) { + if (log_page_list[i] == 0xd0) page_mask |= WDC_D0_PAGE_MASK; - } } } - if (page_mask == 0) - fprintf(stderr, "ERROR : WDC: Unknown log page mask - %s\n", cfg.log_page_mask); + if (!page_mask) + fprintf(stderr, "ERROR: WDC: Unknown log page mask - %s\n", cfg.log_page_mask); capabilities = wdc_get_drive_capabilities(r, dev); - if ((capabilities & WDC_DRIVE_CAP_SMART_LOG_MASK) == 0) { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + if (!(capabilities & WDC_DRIVE_CAP_SMART_LOG_MASK)) { + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; goto out; } if (((capabilities & WDC_DRIVE_CAP_C0_LOG_PAGE) == WDC_DRIVE_CAP_C0_LOG_PAGE) && - (page_mask & WDC_C0_PAGE_MASK)) { + (page_mask & WDC_C0_PAGE_MASK)) { /* Get 0xC0 log page if possible. */ ret = wdc_get_c0_log_page(r, dev, cfg.output_format, uuid_index, cfg.namespace_id); if (ret) - fprintf(stderr, "ERROR : WDC : Failure reading the C0 Log Page, ret = %d\n", ret); + fprintf(stderr, "ERROR: WDC: Failure reading the C0 Log Page, ret = %d\n", ret); } - if (((capabilities & (WDC_DRIVE_CAP_CA_LOG_PAGE)) == (WDC_DRIVE_CAP_CA_LOG_PAGE)) && - (page_mask & WDC_CA_PAGE_MASK)) { + if (((capabilities & (WDC_DRIVE_CAP_CA_LOG_PAGE)) == (WDC_DRIVE_CAP_CA_LOG_PAGE)) && + (page_mask & WDC_CA_PAGE_MASK)) { /* Get the CA Log Page */ ret = wdc_get_ca_log_page(r, dev, cfg.output_format); if (ret) - fprintf(stderr, "ERROR : WDC : Failure reading the CA Log Page, ret = %d\n", ret); + fprintf(stderr, "ERROR: WDC: Failure reading the CA Log Page, ret = %d\n", ret); } if (((capabilities & WDC_DRIVE_CAP_C1_LOG_PAGE) == WDC_DRIVE_CAP_C1_LOG_PAGE) && - (page_mask & WDC_C1_PAGE_MASK)) { + (page_mask & WDC_C1_PAGE_MASK)) { /* Get the C1 Log Page */ ret = wdc_get_c1_log_page(r, dev, cfg.output_format, cfg.interval); if (ret) - fprintf(stderr, "ERROR : WDC : Failure reading the C1 Log Page, ret = %d\n", ret); + fprintf(stderr, "ERROR: WDC: Failure reading the C1 Log Page, ret = %d\n", ret); } if (((capabilities & WDC_DRIVE_CAP_D0_LOG_PAGE) == WDC_DRIVE_CAP_D0_LOG_PAGE) && - (page_mask & WDC_D0_PAGE_MASK)) { + (page_mask & WDC_D0_PAGE_MASK)) { /* Get the D0 Log Page */ ret = wdc_get_d0_log_page(r, dev, cfg.output_format); if (ret) - fprintf(stderr, "ERROR : WDC : Failure reading the D0 Log Page, ret = %d\n", ret); + fprintf(stderr, "ERROR: WDC: Failure reading the D0 Log Page, ret = %d\n", ret); } out: @@ -7303,8 +7397,8 @@ static int wdc_vs_cloud_log(int argc, char **argv, struct command *command, capabilities = wdc_get_drive_capabilities(r, dev); - if ((capabilities & WDC_DRIVE_CAP_CLOUD_LOG_PAGE) == 0) { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + if (!(capabilities & WDC_DRIVE_CAP_CLOUD_LOG_PAGE)) { + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; goto out; } @@ -7316,17 +7410,17 @@ static int wdc_vs_cloud_log(int argc, char **argv, struct command *command, if (strcmp(cfg.output_format, "json")) nvme_show_status(ret); - if (ret == 0) { + if (!ret) { fmt = validate_output_format(cfg.output_format); if (fmt < 0) { - fprintf(stderr, "ERROR : WDC %s: invalid output format\n", __func__); + fprintf(stderr, "ERROR: WDC %s: invalid output format\n", __func__); ret = fmt; } /* parse the data */ wdc_print_ext_smart_cloud_log(data, fmt); } else { - fprintf(stderr, "ERROR : WDC : Unable to read C0 Log Page V1 data\n"); + fprintf(stderr, "ERROR: WDC: Unable to read C0 Log Page V1 data\n"); ret = -1; } @@ -7374,8 +7468,8 @@ static int wdc_vs_hw_rev_log(int argc, char **argv, struct command *command, capabilities = wdc_get_drive_capabilities(r, dev); - if ((capabilities & WDC_DRIVE_CAP_HW_REV_LOG_PAGE) == 0) { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + if (!(capabilities & WDC_DRIVE_CAP_HW_REV_LOG_PAGE)) { + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; goto out; } @@ -7385,16 +7479,16 @@ static int wdc_vs_hw_rev_log(int argc, char **argv, struct command *command, if (strcmp(cfg.output_format, "json")) nvme_show_status(ret); - if (ret == 0) { + if (!ret) { fmt = validate_output_format(cfg.output_format); if (fmt < 0) { - fprintf(stderr, "ERROR : WDC %s: invalid output format\n", __func__); + fprintf(stderr, "ERROR: WDC %s: invalid output format\n", __func__); ret = fmt; goto free_buf; } if (!data) { - fprintf(stderr, "ERROR : WDC : Invalid buffer to read Hardware Revision log\n"); + fprintf(stderr, "ERROR: WDC: Invalid buffer to read Hardware Revision log\n"); ret = -1; goto out; } @@ -7407,7 +7501,7 @@ static int wdc_vs_hw_rev_log(int argc, char **argv, struct command *command, break; } } else { - fprintf(stderr, "ERROR : WDC : Unable to read Hardware Revision Log Page data\n"); + fprintf(stderr, "ERROR: WDC: Unable to read Hardware Revision Log Page data\n"); ret = -1; } @@ -7433,7 +7527,7 @@ static int wdc_vs_device_waf(int argc, char **argv, struct command *command, int ret = 0; int fmt = -1; __u64 capabilities = 0; - wdc_nvme_ext_smart_log *ext_smart_log_ptr; + struct __packed wdc_nvme_ext_smart_log * ext_smart_log_ptr; long double data_units_written = 0, phys_media_units_written_tlc = 0, phys_media_units_written_slc = 0; @@ -7465,8 +7559,8 @@ static int wdc_vs_device_waf(int argc, char **argv, struct command *command, capabilities = wdc_get_drive_capabilities(r, dev); - if ((capabilities & WDC_DRIVE_CAP_DEVICE_WAF) == 0) { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + if (!(capabilities & WDC_DRIVE_CAP_DEVICE_WAF)) { + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; goto out; } @@ -7476,8 +7570,7 @@ static int wdc_vs_device_waf(int argc, char **argv, struct command *command, &smart_log); if (!ret) { data_units_written = int128_to_double(smart_log.data_units_written); - } - else if (ret > 0) { + } else if (ret > 0) { nvme_show_status(ret); ret = -1; goto out; @@ -7492,15 +7585,15 @@ static int wdc_vs_device_waf(int argc, char **argv, struct command *command, ret = nvme_get_ext_smart_cloud_log(dev_fd(dev), &data, 0, cfg.namespace_id); - if (ret == 0) { - ext_smart_log_ptr = (wdc_nvme_ext_smart_log *)data; + if (!ret) { + ext_smart_log_ptr = (struct __packed wdc_nvme_ext_smart_log *)data; phys_media_units_written_tlc = int128_to_double(ext_smart_log_ptr->ext_smart_pmuwt); phys_media_units_written_slc = int128_to_double(ext_smart_log_ptr->ext_smart_pmuws); if (data) free(data); } else { - fprintf(stderr, "ERROR : WDC %s: get smart cloud log failure\n", __func__); + fprintf(stderr, "ERROR: WDC %s: get smart cloud log failure\n", __func__); ret = -1; goto out; } @@ -7510,13 +7603,13 @@ static int wdc_vs_device_waf(int argc, char **argv, struct command *command, fmt = validate_output_format(cfg.output_format); if (fmt < 0) { - fprintf(stderr, "ERROR : WDC %s: invalid output format\n", __func__); + fprintf(stderr, "ERROR: WDC %s: invalid output format\n", __func__); ret = fmt; goto out; } - if (data_units_written == 0) { - fprintf(stderr, "ERROR : WDC %s: 0 data units written\n", __func__); + if (!data_units_written) { + fprintf(stderr, "ERROR: WDC %s: 0 data units written\n", __func__); ret = -1; goto out; } @@ -7526,11 +7619,10 @@ static int wdc_vs_device_waf(int argc, char **argv, struct command *command, (phys_media_units_written_tlc/data_units_written)); printf("Device Write Amplification Factor SLC : %4.2Lf\n", (phys_media_units_written_slc/data_units_written)); - } - else if (fmt == JSON) { - root = json_create_object(); - sprintf(tlc_waf_str, "%4.2Lf", (phys_media_units_written_tlc/data_units_written)); - sprintf(slc_waf_str, "%4.2Lf", (phys_media_units_written_slc/data_units_written)); + } else if (fmt == JSON) { + root = json_create_object(); + sprintf(tlc_waf_str, "%4.2Lf", (phys_media_units_written_tlc/data_units_written)); + sprintf(slc_waf_str, "%4.2Lf", (phys_media_units_written_slc/data_units_written)); json_object_add_value_string(root, "Device Write Amplification Factor TLC", tlc_waf_str); json_object_add_value_string(root, "Device Write Amplification Factor SLC", slc_waf_str); @@ -7576,15 +7668,15 @@ static int wdc_get_latency_monitor_log(int argc, char **argv, struct command *co r = nvme_scan(NULL); capabilities = wdc_get_drive_capabilities(r, dev); - if ((capabilities & WDC_DRIVE_CAP_C3_LOG_PAGE) == 0) { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + if (!(capabilities & WDC_DRIVE_CAP_C3_LOG_PAGE)) { + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; goto out; } ret = wdc_get_c3_log_page(r, dev, cfg.output_format); if (ret) - fprintf(stderr, "ERROR : WDC : Failure reading the Latency Monitor (C3) Log Page, ret = %d\n", ret); + fprintf(stderr, "ERROR: WDC: Failure reading the Latency Monitor (C3) Log Page, ret = %d\n", ret); out: nvme_free_tree(r); @@ -7621,15 +7713,15 @@ static int wdc_get_error_recovery_log(int argc, char **argv, struct command *com r = nvme_scan(NULL); capabilities = wdc_get_drive_capabilities(r, dev); - if ((capabilities & WDC_DRIVE_CAP_OCP_C1_LOG_PAGE) == 0) { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + if (!(capabilities & WDC_DRIVE_CAP_OCP_C1_LOG_PAGE)) { + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; goto out; } ret = wdc_get_ocp_c1_log_page(r, dev, cfg.output_format); if (ret) - fprintf(stderr, "ERROR : WDC : Failure reading the Error Recovery (C1) Log Page, ret = 0x%x\n", ret); + fprintf(stderr, "ERROR: WDC: Failure reading the Error Recovery (C1) Log Page, ret = 0x%x\n", ret); out: nvme_free_tree(r); @@ -7666,15 +7758,15 @@ static int wdc_get_dev_capabilities_log(int argc, char **argv, struct command *c r = nvme_scan(NULL); capabilities = wdc_get_drive_capabilities(r, dev); - if ((capabilities & WDC_DRIVE_CAP_OCP_C4_LOG_PAGE) == 0) { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + if (!(capabilities & WDC_DRIVE_CAP_OCP_C4_LOG_PAGE)) { + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; goto out; } ret = wdc_get_ocp_c4_log_page(r, dev, cfg.output_format); if (ret) - fprintf(stderr, "ERROR : WDC : Failure reading the Device Capabilities (C4) Log Page, ret = 0x%x\n", ret); + fprintf(stderr, "ERROR: WDC: Failure reading the Device Capabilities (C4) Log Page, ret = 0x%x\n", ret); out: nvme_free_tree(r); @@ -7711,15 +7803,15 @@ static int wdc_get_unsupported_reqs_log(int argc, char **argv, struct command *c r = nvme_scan(NULL); capabilities = wdc_get_drive_capabilities(r, dev); - if ((capabilities & WDC_DRIVE_CAP_OCP_C5_LOG_PAGE) == 0) { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + if (!(capabilities & WDC_DRIVE_CAP_OCP_C5_LOG_PAGE)) { + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; goto out; } ret = wdc_get_ocp_c5_log_page(r, dev, cfg.output_format); if (ret) - fprintf(stderr, "ERROR : WDC : Failure reading the Unsupported Requirements (C5) Log Page, ret = 0x%x\n", ret); + fprintf(stderr, "ERROR: WDC: Failure reading the Unsupported Requirements (C5) Log Page, ret = 0x%x\n", ret); out: nvme_free_tree(r); @@ -7732,7 +7824,7 @@ static int wdc_do_clear_pcie_correctable_errors(int fd) int ret; struct nvme_passthru_cmd admin_cmd; - memset(&admin_cmd, 0, sizeof (admin_cmd)); + memset(&admin_cmd, 0, sizeof(admin_cmd)); admin_cmd.opcode = WDC_NVME_CLEAR_PCIE_CORR_OPCODE; admin_cmd.cdw12 = ((WDC_NVME_CLEAR_PCIE_CORR_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_CLEAR_PCIE_CORR_CMD); @@ -7747,7 +7839,7 @@ static int wdc_do_clear_pcie_correctable_errors_vuc(int fd) int ret; struct nvme_passthru_cmd admin_cmd; - memset(&admin_cmd, 0, sizeof (admin_cmd)); + memset(&admin_cmd, 0, sizeof(admin_cmd)); admin_cmd.opcode = WDC_NVME_CLEAR_PCIE_CORR_OPCODE_VUC; ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); @@ -7792,21 +7884,18 @@ static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct comma } capabilities = wdc_get_drive_capabilities(r, dev); - if ((capabilities & WDC_DRIVE_CAP_CLEAR_PCIE_MASK) == 0) { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + if (!(capabilities & WDC_DRIVE_CAP_CLEAR_PCIE_MASK)) { + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; goto out; } - - if (capabilities & WDC_DRIVE_CAP_CLEAR_PCIE) { + + if (capabilities & WDC_DRIVE_CAP_CLEAR_PCIE) ret = wdc_do_clear_pcie_correctable_errors(dev_fd(dev)); - } - else if (capabilities & WDC_DRIVE_CAP_VUC_CLEAR_PCIE) { + else if (capabilities & WDC_DRIVE_CAP_VUC_CLEAR_PCIE) ret = wdc_do_clear_pcie_correctable_errors_vuc(dev_fd(dev)); - } - else { + else ret = wdc_do_clear_pcie_correctable_errors_fid(dev_fd(dev)); - } out: nvme_free_tree(r); @@ -7840,7 +7929,7 @@ static int wdc_drive_status(int argc, char **argv, struct command *command, r = nvme_scan(NULL); capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_DRIVE_STATUS) != WDC_DRIVE_CAP_DRIVE_STATUS) { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; goto out; } @@ -7848,7 +7937,7 @@ static int wdc_drive_status(int argc, char **argv, struct command *command, /* verify the 0xC2 Device Manageability log page is supported */ if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE) == false) { - fprintf(stderr, "ERROR : WDC : 0xC2 Log Page not supported\n"); + fprintf(stderr, "ERROR: WDC: 0xC2 Log Page not supported\n"); ret = -1; goto out; } @@ -7856,51 +7945,52 @@ static int wdc_drive_status(int argc, char **argv, struct command *command, /* Get the assert dump present status */ if (!wdc_nvme_get_dev_status_log_data(r, dev, &assert_status, WDC_C2_ASSERT_DUMP_PRESENT_ID)) - fprintf(stderr, "ERROR : WDC : Get Assert Status Failed\n"); + fprintf(stderr, "ERROR: WDC: Get Assert Status Failed\n"); /* Get the thermal throttling status */ if (!wdc_nvme_get_dev_status_log_data(r, dev, &thermal_status, WDC_C2_THERMAL_THROTTLE_STATUS_ID)) - fprintf(stderr, "ERROR : WDC : Get Thermal Throttling Status Failed\n"); + fprintf(stderr, "ERROR: WDC: Get Thermal Throttling Status Failed\n"); /* Get EOL status */ if (!wdc_nvme_get_dev_status_log_data(r, dev, &eol_status, WDC_C2_USER_EOL_STATUS_ID)) { - fprintf(stderr, "ERROR : WDC : Get User EOL Status Failed\n"); + fprintf(stderr, "ERROR: WDC: Get User EOL Status Failed\n"); eol_status = cpu_to_le32(-1); } /* Get Customer EOL state */ if (!wdc_nvme_get_dev_status_log_data(r, dev, &user_eol_state, WDC_C2_USER_EOL_STATE_ID)) - fprintf(stderr, "ERROR : WDC : Get User EOL State Failed\n"); + fprintf(stderr, "ERROR: WDC: Get User EOL State Failed\n"); /* Get System EOL state*/ if (!wdc_nvme_get_dev_status_log_data(r, dev, &system_eol_state, WDC_C2_SYSTEM_EOL_STATE_ID)) - fprintf(stderr, "ERROR : WDC : Get System EOL State Failed\n"); + fprintf(stderr, "ERROR: WDC: Get System EOL State Failed\n"); /* Get format corrupt reason*/ if (!wdc_nvme_get_dev_status_log_data(r, dev, &format_corrupt_reason, WDC_C2_FORMAT_CORRUPT_REASON_ID)) - fprintf(stderr, "ERROR : WDC : Get Format Corrupt Reason Failed\n"); + fprintf(stderr, "ERROR: WDC: Get Format Corrupt Reason Failed\n"); - printf(" Drive Status :- \n"); - if ((int)le32_to_cpu(eol_status) >= 0) { + printf(" Drive Status :-\n"); + if ((int)le32_to_cpu(eol_status) >= 0) printf(" Percent Used: %"PRIu32"%%\n", - le32_to_cpu(eol_status)); - } + le32_to_cpu(eol_status)); else printf(" Percent Used: Unknown\n"); if (system_eol_state == WDC_EOL_STATUS_NORMAL && user_eol_state == WDC_EOL_STATUS_NORMAL) printf(" Drive Life Status: Normal\n"); - else if (system_eol_state == WDC_EOL_STATUS_END_OF_LIFE || user_eol_state == WDC_EOL_STATUS_END_OF_LIFE) - printf(" Drive Life Status: End Of Life\n"); - else if (system_eol_state == WDC_EOL_STATUS_READ_ONLY || user_eol_state == WDC_EOL_STATUS_READ_ONLY) - printf(" Drive Life Status: Read Only\n"); + else if (system_eol_state == WDC_EOL_STATUS_END_OF_LIFE || + user_eol_state == WDC_EOL_STATUS_END_OF_LIFE) + printf(" Drive Life Status: End Of Life\n"); + else if (system_eol_state == WDC_EOL_STATUS_READ_ONLY || + user_eol_state == WDC_EOL_STATUS_READ_ONLY) + printf(" Drive Life Status: Read Only\n"); else printf(" Drive Life Status: Unknown : 0x%08x/0x%08x\n", - le32_to_cpu(user_eol_state), le32_to_cpu(system_eol_state)); + le32_to_cpu(user_eol_state), le32_to_cpu(system_eol_state)); if (assert_status == WDC_ASSERT_DUMP_PRESENT) printf(" Assert Dump Status: Present\n"); @@ -7955,20 +8045,20 @@ static int wdc_clear_assert_dump(int argc, char **argv, struct command *command, r = nvme_scan(NULL); capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_CLEAR_ASSERT) != WDC_DRIVE_CAP_CLEAR_ASSERT) { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; goto out; } if (!wdc_nvme_get_dev_status_log_data(r, dev, &assert_status, WDC_C2_ASSERT_DUMP_PRESENT_ID)) { - fprintf(stderr, "ERROR : WDC : Get Assert Status Failed\n"); + fprintf(stderr, "ERROR: WDC: Get Assert Status Failed\n"); ret = -1; goto out; } /* Get the assert dump present status */ if (assert_status == WDC_ASSERT_DUMP_PRESENT) { - memset(&admin_cmd, 0, sizeof (admin_cmd)); + memset(&admin_cmd, 0, sizeof(admin_cmd)); admin_cmd.opcode = WDC_NVME_CLEAR_ASSERT_DUMP_OPCODE; admin_cmd.cdw12 = ((WDC_NVME_CLEAR_ASSERT_DUMP_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_CLEAR_ASSERT_DUMP_CMD); @@ -7977,7 +8067,7 @@ static int wdc_clear_assert_dump(int argc, char **argv, struct command *command, NULL); nvme_show_status(ret); } else - fprintf(stderr, "INFO : WDC : No Assert Dump Present\n"); + fprintf(stderr, "INFO: WDC: No Assert Dump Present\n"); out: nvme_free_tree(r); @@ -7998,22 +8088,24 @@ static int wdc_get_fw_act_history(nvme_root_t r, struct nvme_dev *dev, fmt = validate_output_format(format); if (fmt < 0) { - fprintf(stderr, "ERROR : WDC : invalid output format\n"); + fprintf(stderr, "ERROR: WDC: invalid output format\n"); return fmt; } /* verify the FW Activate History log page is supported */ - if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID) == false) { - fprintf(stderr, "ERROR : WDC : %d Log Page not supported\n", WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID); + if (!wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID)) { + fprintf(stderr, "ERROR: WDC: %d Log Page not supported\n", + WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID); return -1; } - if ((data = (__u8*) malloc(sizeof (__u8) * WDC_FW_ACT_HISTORY_LOG_BUF_LEN)) == NULL) { - fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); + data = (__u8 *)malloc(sizeof(__u8) * WDC_FW_ACT_HISTORY_LOG_BUF_LEN); + if (!data) { + fprintf(stderr, "ERROR: WDC: malloc: %s\n", strerror(errno)); return -1; } - memset(data, 0, sizeof (__u8) * WDC_FW_ACT_HISTORY_LOG_BUF_LEN); + memset(data, 0, sizeof(__u8) * WDC_FW_ACT_HISTORY_LOG_BUF_LEN); ret = nvme_get_log_simple(dev_fd(dev), WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID, @@ -8022,22 +8114,25 @@ static int wdc_get_fw_act_history(nvme_root_t r, struct nvme_dev *dev, if (strcmp(format, "json")) nvme_show_status(ret); - if (ret == 0) { + if (!ret) { /* parse the data */ fw_act_history_hdr = (struct wdc_fw_act_history_log_hdr *)(data); - if ((fw_act_history_hdr->num_entries > 0) && (fw_act_history_hdr->num_entries <= WDC_MAX_NUM_ACT_HIST_ENTRIES)) - ret = wdc_print_fw_act_history_log(data, fw_act_history_hdr->num_entries, fmt, 0, 0); - else if (fw_act_history_hdr->num_entries == 0) { - fprintf(stderr, "INFO : WDC : No FW Activate History entries found.\n"); + if ((fw_act_history_hdr->num_entries > 0) && + (fw_act_history_hdr->num_entries <= WDC_MAX_NUM_ACT_HIST_ENTRIES)) { + ret = wdc_print_fw_act_history_log(data, fw_act_history_hdr->num_entries, + fmt, 0, 0); + } else if (!fw_act_history_hdr->num_entries) { + fprintf(stderr, "INFO: WDC: No FW Activate History entries found.\n"); ret = 0; - } - else { - fprintf(stderr, "ERROR : WDC : Invalid number entries found in FW Activate History Log Page - %d\n", fw_act_history_hdr->num_entries); + } else { + fprintf(stderr, + "ERROR: WDC: Invalid number entries found in FW Activate History Log Page - %d\n", + fw_act_history_hdr->num_entries); ret = -1; } } else { - fprintf(stderr, "ERROR : WDC : Unable to read FW Activate History Log Page data\n"); + fprintf(stderr, "ERROR: WDC: Unable to read FW Activate History Log Page data\n"); ret = -1; } @@ -8051,11 +8146,11 @@ static __u32 wdc_get_fw_cust_id(nvme_root_t r, struct nvme_dev *dev) __u32 cust_id = WDC_INVALID_CUSTOMER_ID; __u32 *cust_id_ptr = NULL; - if (!(get_dev_mgment_cbs_data(r, dev, WDC_C2_CUSTOMER_ID_ID, (void*)&cust_id_ptr))) { - fprintf(stderr, "%s: ERROR : WDC : 0xC2 Log Page entry ID 0x%x not found\n", __func__, WDC_C2_CUSTOMER_ID_ID); - } else { + if (!get_dev_mgment_cbs_data(r, dev, WDC_C2_CUSTOMER_ID_ID, (void *)&cust_id_ptr)) + fprintf(stderr, "%s: ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found\n", + __func__, WDC_C2_CUSTOMER_ID_ID); + else cust_id = *cust_id_ptr; - } free(cust_id_ptr); return cust_id; @@ -8077,18 +8172,19 @@ static int wdc_get_fw_act_history_C2(nvme_root_t r, struct nvme_dev *dev, fmt = validate_output_format(format); if (fmt < 0) { - fprintf(stderr, "ERROR : WDC : invalid output format\n"); + fprintf(stderr, "ERROR: WDC: invalid output format\n"); return fmt; } ret = wdc_get_pci_ids(r, dev, &device_id, &vendor_id); - if ((data = (__u8*) malloc(sizeof (__u8) * WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN)) == NULL) { - fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); + data = (__u8 *)malloc(sizeof(__u8) * WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN); + if (!data) { + fprintf(stderr, "ERROR: WDC: malloc: %s\n", strerror(errno)); return -1; } - memset(data, 0, sizeof (__u8) * WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN); + memset(data, 0, sizeof(__u8) * WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN); ret = nvme_get_log_simple(dev_fd(dev), WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID, @@ -8097,16 +8193,16 @@ static int wdc_get_fw_act_history_C2(nvme_root_t r, struct nvme_dev *dev, if (strcmp(format, "json")) nvme_show_status(ret); - if (ret == 0) { + if (!ret) { /* parse the data */ - fw_act_history_log = (struct wdc_fw_act_history_log_format_c2*)(data); + fw_act_history_log = (struct wdc_fw_act_history_log_format_c2 *)(data); tot_entries = le32_to_cpu(fw_act_history_log->num_entries); if (tot_entries > 0) { /* get the FW customer id */ cust_id = wdc_get_fw_cust_id(r, dev); if (cust_id == WDC_INVALID_CUSTOMER_ID) { - fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__); + fprintf(stderr, "%s: ERROR: WDC: invalid customer id\n", __func__); ret = -1; goto freeData; } @@ -8114,11 +8210,11 @@ static int wdc_get_fw_act_history_C2(nvme_root_t r, struct nvme_dev *dev, WDC_MAX_NUM_ACT_HIST_ENTRIES; ret = wdc_print_fw_act_history_log(data, num_entries, fmt, cust_id, vendor_id); } else { - fprintf(stderr, "INFO : WDC : No FW Activate History entries found.\n"); + fprintf(stderr, "INFO: WDC: No FW Activate History entries found.\n"); ret = 0; } } else { - fprintf(stderr, "ERROR : WDC : Unable to read FW Activate History Log Page data\n"); + fprintf(stderr, "ERROR: WDC: Unable to read FW Activate History Log Page data\n"); ret = -1; } @@ -8155,8 +8251,8 @@ static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *com r = nvme_scan(NULL); capabilities = wdc_get_drive_capabilities(r, dev); - if ((capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_MASK) == 0) { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + if (!(capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_MASK)) { + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; goto out; } @@ -8167,10 +8263,13 @@ static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *com __u8 *data; int i; - /* check for the GUID in the 0xC0 log page to determine which log page to use to */ - /* to retrieve fw activate history data */ - if ((data = (__u8*) malloc(sizeof (__u8) * WDC_NVME_SMART_CLOUD_ATTR_LEN)) == NULL) { - fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); + /* + * check for the GUID in the 0xC0 log page to determine which log page to use to + * retrieve fw activate history data + */ + data = (__u8 *)malloc(sizeof(__u8) * WDC_NVME_SMART_CLOUD_ATTR_LEN); + if (!data) { + fprintf(stderr, "ERROR: WDC: malloc: %s\n", strerror(errno)); ret = -1; goto out; } @@ -8195,35 +8294,30 @@ static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *com }; ret = nvme_get_log(&args); - if (ret == 0) { + if (!ret) { /* Verify GUID matches */ - for (i=0; i<16; i++) { - if (scao_guid[i] != data[SCAO_LPG + i]) { + for (i = 0; i < 16; i++) { + if (scao_guid[i] != data[SCAO_LPG + i]) { c0GuidMatch = false; break; } } - if (i == 16) { + if (i == 16) c0GuidMatch = true; - } } free(data); - if (c0GuidMatch) { - ret = wdc_get_fw_act_history_C2(r, dev, - cfg.output_format); - } - else { - ret = wdc_get_fw_act_history(r, dev, - cfg.output_format); - } + if (c0GuidMatch) + ret = wdc_get_fw_act_history_C2(r, dev, cfg.output_format); + else + ret = wdc_get_fw_act_history(r, dev, cfg.output_format); } else { ret = wdc_get_fw_act_history_C2(r, dev, cfg.output_format); } if (ret) - fprintf(stderr, "ERROR : WDC : Failure reading the FW Activate History, ret = %d\n", ret); + fprintf(stderr, "ERROR: WDC: Failure reading the FW Activate History, ret = %d\n", ret); out: nvme_free_tree(r); dev_close(dev); @@ -8235,7 +8329,7 @@ static int wdc_do_clear_fw_activate_history_vuc(int fd) int ret = -1; struct nvme_passthru_cmd admin_cmd; - memset(&admin_cmd, 0, sizeof (admin_cmd)); + memset(&admin_cmd, 0, sizeof(admin_cmd)); admin_cmd.opcode = WDC_NVME_CLEAR_FW_ACT_HIST_OPCODE; admin_cmd.cdw12 = ((WDC_NVME_CLEAR_FW_ACT_HIST_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_CLEAR_FW_ACT_HIST_CMD); @@ -8278,8 +8372,8 @@ static int wdc_clear_fw_activate_history(int argc, char **argv, struct command * r = nvme_scan(NULL); capabilities = wdc_get_drive_capabilities(r, dev); - if ((capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY_MASK) == 0) { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + if (!(capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY_MASK)) { + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; goto out; } @@ -8335,7 +8429,7 @@ static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct comm r = nvme_scan(NULL); capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG) != WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG) { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; goto out; } @@ -8343,7 +8437,7 @@ static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct comm /* allow only one option at a time */ if ((cfg.disable + cfg.enable + cfg.status) > 1) { - fprintf(stderr, "ERROR : WDC : Invalid option\n"); + fprintf(stderr, "ERROR: WDC: Invalid option\n"); ret = -1; goto out; } @@ -8354,18 +8448,16 @@ static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct comm 0, 1, false, &result); wdc_clear_reason_id(dev); - } - else { - if (cfg.enable) { + } else { + if (cfg.enable) { ret = nvme_set_features_simple(dev_fd(dev), WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0, 0, false, &result); - } - else if (cfg.status) { + } else if (cfg.status) { ret = nvme_get_features_simple(dev_fd(dev), WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0, &result); - if (ret == 0) { + if (!ret) { if (result) fprintf(stderr, "Controller Option Telemetry Log Page State: Disabled\n"); else @@ -8373,14 +8465,12 @@ static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct comm } else { nvme_show_status(ret); } - } - else { - fprintf(stderr, "ERROR : WDC: unsupported option for this command\n"); + } else { + fprintf(stderr, "ERROR: WDC: unsupported option for this command\n"); fprintf(stderr, "Please provide an option, -d, -e or -s\n"); ret = -1; goto out; - } - + } } out: @@ -8396,14 +8486,13 @@ static int wdc_get_serial_and_fw_rev(struct nvme_dev *dev, char *sn, char *fw_re int ret; struct nvme_id_ctrl ctrl; - i = sizeof (ctrl.sn) - 1; + i = sizeof(ctrl.sn) - 1; memset(sn, 0, WDC_SERIAL_NO_LEN); memset(fw_rev, 0, WDC_NVME_FIRMWARE_REV_LEN); - memset(&ctrl, 0, sizeof (struct nvme_id_ctrl)); + memset(&ctrl, 0, sizeof(struct nvme_id_ctrl)); ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); if (ret) { - fprintf(stderr, "ERROR : WDC : nvme_identify_ctrl() failed " - "0x%x\n", ret); + fprintf(stderr, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x\n", ret); return -1; } /* Remove trailing spaces from the name */ @@ -8424,10 +8513,10 @@ static int wdc_get_max_transfer_len(struct nvme_dev *dev, __u32 *maxTransferLen) __u32 maxTransferLenDevice = 0; - memset(&ctrl, 0, sizeof (struct nvme_id_ctrl)); + memset(&ctrl, 0, sizeof(struct nvme_id_ctrl)); ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); if (ret) { - fprintf(stderr, "ERROR : WDC : nvme_identify_ctrl() failed 0x%x\n", ret); + fprintf(stderr, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x\n", ret); return -1; } @@ -8437,57 +8526,53 @@ static int wdc_get_max_transfer_len(struct nvme_dev *dev, __u32 *maxTransferLen) return ret; } -static int wdc_de_VU_read_size(struct nvme_dev *dev, __u32 fileId, - __u16 spiDestn, __u32* logSize) +static int wdc_de_VU_read_size(struct nvme_dev *dev, __u32 fileId, __u16 spiDestn, __u32 *logSize) { int ret = WDC_STATUS_FAILURE; struct nvme_passthru_cmd cmd; - if(!dev || !logSize ) - { + if (!dev || !logSize) { ret = WDC_STATUS_INVALID_PARAMETER; goto end; } - memset(&cmd,0,sizeof(struct nvme_passthru_cmd)); + memset(&cmd, 0, sizeof(struct nvme_passthru_cmd)); cmd.opcode = WDC_DE_VU_READ_SIZE_OPCODE; cmd.nsid = WDC_DE_DEFAULT_NAMESPACE_ID; - cmd.cdw13 = fileId<<16; + cmd.cdw13 = fileId << 16; cmd.cdw14 = spiDestn; ret = nvme_submit_admin_passthru(dev_fd(dev), &cmd, NULL); if (!ret && logSize) *logSize = cmd.result; - if( ret != WDC_STATUS_SUCCESS) { - fprintf(stderr, "ERROR : WDC : VUReadSize() failed, "); + if (ret != WDC_STATUS_SUCCESS) { + fprintf(stderr, "ERROR: WDC: VUReadSize() failed, "); nvme_show_status(ret); } - end: +end: return ret; } -static int wdc_de_VU_read_buffer(struct nvme_dev *dev, __u32 fileId, - __u16 spiDestn, __u32 offsetInDwords, - __u8* dataBuffer, __u32* bufferSize) +static int wdc_de_VU_read_buffer(struct nvme_dev *dev, __u32 fileId, __u16 spiDestn, + __u32 offsetInDwords, __u8 *dataBuffer, __u32 *bufferSize) { int ret = WDC_STATUS_FAILURE; struct nvme_passthru_cmd cmd; __u32 noOfDwordExpected = 0; - if(!dev || !dataBuffer || !bufferSize) - { + if (!dev || !dataBuffer || !bufferSize) { ret = WDC_STATUS_INVALID_PARAMETER; goto end; } - memset(&cmd,0,sizeof(struct nvme_passthru_cmd)); - noOfDwordExpected = *bufferSize/sizeof(__u32); + memset(&cmd, 0, sizeof(struct nvme_passthru_cmd)); + noOfDwordExpected = *bufferSize / sizeof(__u32); cmd.opcode = WDC_DE_VU_READ_BUFFER_OPCODE; cmd.nsid = WDC_DE_DEFAULT_NAMESPACE_ID; cmd.cdw10 = noOfDwordExpected; - cmd.cdw13 = fileId<<16; + cmd.cdw13 = fileId << 16; cmd.cdw14 = spiDestn; cmd.cdw15 = offsetInDwords; @@ -8496,92 +8581,92 @@ static int wdc_de_VU_read_buffer(struct nvme_dev *dev, __u32 fileId, ret = nvme_submit_admin_passthru(dev_fd(dev), &cmd, NULL); - if( ret != WDC_STATUS_SUCCESS) { - fprintf(stderr, "ERROR : WDC : VUReadBuffer() failed, "); + if (ret != WDC_STATUS_SUCCESS) { + fprintf(stderr, "ERROR: WDC: VUReadBuffer() failed, "); nvme_show_status(ret); } - end: +end: return ret; } -static int wdc_get_log_dir_max_entries(struct nvme_dev *dev, __u32* maxNumOfEntries) +static int wdc_get_log_dir_max_entries(struct nvme_dev *dev, __u32 *maxNumOfEntries) { - int ret = WDC_STATUS_FAILURE; - __u32 headerPayloadSize = 0; - __u8* fileIdOffsetsBuffer = NULL; - __u32 fileIdOffsetsBufferSize = 0; - __u32 fileNum = 0; - __u16 fileOffset = 0; + int ret = WDC_STATUS_FAILURE; + __u32 headerPayloadSize = 0; + __u8 *fileIdOffsetsBuffer = NULL; + __u32 fileIdOffsetsBufferSize = 0; + __u32 fileNum = 0; + __u16 fileOffset = 0; - if (!dev || !maxNumOfEntries) - { + if (!dev || !maxNumOfEntries) { ret = WDC_STATUS_INVALID_PARAMETER; return ret; } /* 1.Get log directory first four bytes */ - if (WDC_STATUS_SUCCESS != (ret = wdc_de_VU_read_size(dev, 0, 5, (__u32*)&headerPayloadSize))) - { - fprintf(stderr, "ERROR : WDC : %s: Failed to get headerPayloadSize from file directory 0x%x\n", - __func__, ret); + ret = wdc_de_VU_read_size(dev, 0, 5, (__u32 *)&headerPayloadSize); + if (ret != WDC_STATUS_SUCCESS) { + fprintf(stderr, + "ERROR: WDC: %s: Failed to get headerPayloadSize from file directory 0x%x\n", + __func__, ret); return ret; } - fileIdOffsetsBufferSize = WDC_DE_FILE_HEADER_SIZE + (headerPayloadSize * WDC_DE_FILE_OFFSET_SIZE); - fileIdOffsetsBuffer = (__u8*)calloc(1, fileIdOffsetsBufferSize); + fileIdOffsetsBufferSize = + WDC_DE_FILE_HEADER_SIZE + (headerPayloadSize * WDC_DE_FILE_OFFSET_SIZE); + fileIdOffsetsBuffer = (__u8 *)calloc(1, fileIdOffsetsBufferSize); /* 2.Read to get file offsets */ - if (WDC_STATUS_SUCCESS != (ret = wdc_de_VU_read_buffer(dev, 0, 5, 0, fileIdOffsetsBuffer, &fileIdOffsetsBufferSize))) - { - fprintf(stderr, "ERROR : WDC : %s: Failed to get fileIdOffsets from file directory 0x%x\n", - __func__, ret); + ret = wdc_de_VU_read_buffer(dev, 0, 5, 0, fileIdOffsetsBuffer, &fileIdOffsetsBufferSize); + if (ret != WDC_STATUS_SUCCESS) { + fprintf(stderr, + "ERROR: WDC: %s: Failed to get fileIdOffsets from file directory 0x%x\n", + __func__, ret); goto end; } /* 3.Determine valid entries */ - for (fileNum = 0; fileNum < (headerPayloadSize - WDC_DE_FILE_HEADER_SIZE) / WDC_DE_FILE_OFFSET_SIZE; fileNum++) - { - fileOffset = (fileIdOffsetsBuffer[WDC_DE_FILE_HEADER_SIZE + (fileNum * WDC_DE_FILE_OFFSET_SIZE)] << 8) + - fileIdOffsetsBuffer[WDC_DE_FILE_HEADER_SIZE + (fileNum * WDC_DE_FILE_OFFSET_SIZE) + 1]; + for (fileNum = 0; + fileNum < (headerPayloadSize - WDC_DE_FILE_HEADER_SIZE) / WDC_DE_FILE_OFFSET_SIZE; + fileNum++) { + fileOffset = (fileIdOffsetsBuffer[WDC_DE_FILE_HEADER_SIZE + + (fileNum * WDC_DE_FILE_OFFSET_SIZE)] << 8) + + fileIdOffsetsBuffer[WDC_DE_FILE_HEADER_SIZE + + (fileNum * WDC_DE_FILE_OFFSET_SIZE) + 1]; if (!fileOffset) continue; (*maxNumOfEntries)++; } + end: free(fileIdOffsetsBuffer); return ret; } -static WDC_DRIVE_ESSENTIAL_TYPE wdc_get_essential_type(__u8 fileName[]) +static enum WDC_DRIVE_ESSENTIAL_TYPE wdc_get_essential_type(__u8 fileName[]) { - WDC_DRIVE_ESSENTIAL_TYPE essentialType = WDC_DE_TYPE_NONE; + enum WDC_DRIVE_ESSENTIAL_TYPE essentialType = WDC_DE_TYPE_NONE; - if (wdc_UtilsStrCompare((char*)fileName, WDC_DE_CORE_DUMP_FILE_NAME) == 0) - { + if (!wdc_UtilsStrCompare((char *)fileName, WDC_DE_CORE_DUMP_FILE_NAME)) essentialType = WDC_DE_TYPE_DUMPSNAPSHOT; - } - else if (wdc_UtilsStrCompare((char*)fileName, WDC_DE_EVENT_LOG_FILE_NAME) == 0) - { + else if (!wdc_UtilsStrCompare((char *)fileName, WDC_DE_EVENT_LOG_FILE_NAME)) essentialType = WDC_DE_TYPE_EVENTLOG; - } - else if (wdc_UtilsStrCompare((char*)fileName, WDC_DE_MANUFACTURING_INFO_PAGE_FILE_NAME) == 0) - { + else if (!wdc_UtilsStrCompare((char *)fileName, WDC_DE_MANUFACTURING_INFO_PAGE_FILE_NAME)) essentialType = WDC_DE_TYPE_NVME_MANF_INFO; - } return essentialType; } -static int wdc_fetch_log_directory(struct nvme_dev *dev, PWDC_DE_VU_LOG_DIRECTORY directory) +static int wdc_fetch_log_directory(struct nvme_dev *dev, struct WDC_DE_VU_LOG_DIRECTORY *directory) { - int ret = WDC_STATUS_FAILURE; - __u8 *fileOffset = NULL; - __u8 *fileDirectory = NULL; - __u32 headerSize = 0; - __u32 fileNum = 0, startIdx = 0; - __u16 fileOffsetTemp = 0; - __u32 entryId = 0; - __u32 fileDirectorySize = 0; + int ret = WDC_STATUS_FAILURE; + __u8 *fileOffset = NULL; + __u8 *fileDirectory = NULL; + __u32 headerSize = 0; + __u32 fileNum = 0, startIdx = 0; + __u16 fileOffsetTemp = 0; + __u32 entryId = 0; + __u32 fileDirectorySize = 0; if (!dev || !directory) { ret = WDC_STATUS_INVALID_PARAMETER; @@ -8589,18 +8674,17 @@ static int wdc_fetch_log_directory(struct nvme_dev *dev, PWDC_DE_VU_LOG_DIRECTOR } ret = wdc_de_VU_read_size(dev, 0, 5, &fileDirectorySize); - if (WDC_STATUS_SUCCESS != ret) { + if (ret != WDC_STATUS_SUCCESS) { fprintf(stderr, - "ERROR : WDC : %s: Failed to get filesystem directory size, ret = %d\n", + "ERROR: WDC: %s: Failed to get filesystem directory size, ret = %d\n", __func__, ret); goto end; } - fileDirectory = (__u8*)calloc(1, fileDirectorySize); + fileDirectory = (__u8 *)calloc(1, fileDirectorySize); ret = wdc_de_VU_read_buffer(dev, 0, 5, 0, fileDirectory, &fileDirectorySize); - if (WDC_STATUS_SUCCESS != ret) { - fprintf(stderr, - "ERROR : WDC : %s: Failed to get filesystem directory, ret = %d\n", + if (ret != WDC_STATUS_SUCCESS) { + fprintf(stderr, "ERROR: WDC: %s: Failed to get filesystem directory, ret = %d\n", __func__, ret); goto end; } @@ -8609,7 +8693,7 @@ static int wdc_fetch_log_directory(struct nvme_dev *dev, PWDC_DE_VU_LOG_DIRECTOR memcpy(&headerSize, fileDirectory, WDC_DE_FILE_HEADER_SIZE); /* minimum buffer for 1 entry is required */ - if (directory->maxNumLogEntries == 0) { + if (!directory->maxNumLogEntries) { ret = WDC_STATUS_INVALID_PARAMETER; goto end; } @@ -8624,34 +8708,31 @@ static int wdc_fetch_log_directory(struct nvme_dev *dev, PWDC_DE_VU_LOG_DIRECTOR memcpy(&fileOffsetTemp, fileDirectory + startIdx, sizeof(fileOffsetTemp)); fileOffset = fileDirectory + fileOffsetTemp; - if (0 == fileOffsetTemp) + if (!fileOffsetTemp) continue; - memset(&directory->logEntry[entryId], 0, sizeof(WDC_DRIVE_ESSENTIALS)); - memcpy(&directory->logEntry[entryId].metaData, fileOffset, sizeof(WDC_DE_VU_FILE_META_DATA)); + memset(&directory->logEntry[entryId], 0, sizeof(struct WDC_DRIVE_ESSENTIALS)); + memcpy(&directory->logEntry[entryId].metaData, fileOffset, sizeof(struct __packed WDC_DE_VU_FILE_META_DATA)); directory->logEntry[entryId].metaData.fileName[WDC_DE_FILE_NAME_SIZE - 1] = '\0'; - wdc_UtilsDeleteCharFromString((char*)directory->logEntry[entryId].metaData.fileName, + wdc_UtilsDeleteCharFromString((char *)directory->logEntry[entryId].metaData.fileName, WDC_DE_FILE_NAME_SIZE, ' '); - if (0 == directory->logEntry[entryId].metaData.fileID) + if (!directory->logEntry[entryId].metaData.fileID) continue; directory->logEntry[entryId].essentialType = wdc_get_essential_type(directory->logEntry[entryId].metaData.fileName); - /*fprintf(stderr, "WDC : %s: NVMe VU Log Entry %d, fileName = %s, fileSize = 0x%lx, fileId = 0x%x\n", - __func__, entryId, directory->logEntry[entryId].metaData.fileName, - (long unsigned int)directory->logEntry[entryId].metaData.fileSize, directory->logEntry[entryId].metaData.fileID); - */ entryId++; } directory->numOfValidLogEntries = entryId; + end: - if (fileDirectory != NULL) + if (fileDirectory) free(fileDirectory); return ret; } static int wdc_fetch_log_file_from_device(struct nvme_dev *dev, __u32 fileId, - __u16 spiDestn, __u64 fileSize, __u8* dataBuffer) + __u16 spiDestn, __u64 fileSize, __u8 *dataBuffer) { int ret = WDC_STATUS_FAILURE; __u32 chunckSize = WDC_DE_VU_READ_BUFFER_STANDARD_OFFSET; @@ -8659,8 +8740,7 @@ static int wdc_fetch_log_file_from_device(struct nvme_dev *dev, __u32 fileId, __u32 buffSize = 0; __u64 offsetIdx = 0; - if (!dev || !dataBuffer || !fileSize) - { + if (!dev || !dataBuffer || !fileSize) { ret = WDC_STATUS_INVALID_PARAMETER; goto end; } @@ -8671,43 +8751,40 @@ static int wdc_fetch_log_file_from_device(struct nvme_dev *dev, __u32 fileId, } /* Fetch Log File Data */ - if ((fileSize >= maximumTransferLength) || (fileSize > 0xFFFFFFFF)) - { + if ((fileSize >= maximumTransferLength) || (fileSize > 0xFFFFFFFF)) { chunckSize = WDC_DE_VU_READ_BUFFER_STANDARD_OFFSET; if (maximumTransferLength < WDC_DE_VU_READ_BUFFER_STANDARD_OFFSET) chunckSize = maximumTransferLength; buffSize = chunckSize; - for (offsetIdx = 0; (offsetIdx * chunckSize) < fileSize; offsetIdx++) - { + for (offsetIdx = 0; (offsetIdx * chunckSize) < fileSize; offsetIdx++) { if (((offsetIdx * chunckSize) + buffSize) > fileSize) buffSize = (__u32)(fileSize - (offsetIdx * chunckSize)); /* Limitation in VU read buffer - offsetIdx and bufferSize are not greater than u32 */ ret = wdc_de_VU_read_buffer(dev, fileId, spiDestn, (__u32)((offsetIdx * chunckSize) / sizeof(__u32)), dataBuffer + (offsetIdx * chunckSize), &buffSize); - if (ret != WDC_STATUS_SUCCESS) - { - fprintf(stderr, "ERROR : WDC : %s: wdc_de_VU_read_buffer failed with ret = %d, fileId = 0x%x, fileSize = 0x%lx\n", - __func__, ret, fileId, (long unsigned int)fileSize); + if (ret != WDC_STATUS_SUCCESS) { + fprintf(stderr, "ERROR: WDC: %s: wdc_de_VU_read_buffer failed with ret = %d, fileId = 0x%x, fileSize = 0x%lx\n", + __func__, ret, fileId, (unsigned long)fileSize); break; } } } else { buffSize = (__u32)fileSize; ret = wdc_de_VU_read_buffer(dev, fileId, spiDestn, - (__u32)((offsetIdx * chunckSize) / sizeof(__u32)), dataBuffer, &buffSize); - if (ret != WDC_STATUS_SUCCESS) - { - fprintf(stderr, "ERROR : WDC : %s: wdc_de_VU_read_buffer failed with ret = %d, fileId = 0x%x, fileSize = 0x%lx\n", - __func__, ret, fileId, (long unsigned int)fileSize); + (__u32)((offsetIdx * chunckSize) / sizeof(__u32)), + dataBuffer, &buffSize); + if (ret != WDC_STATUS_SUCCESS) { + fprintf(stderr, "ERROR: WDC: %s: wdc_de_VU_read_buffer failed with ret = %d, fileId = 0x%x, fileSize = 0x%lx\n", + __func__, ret, fileId, (unsigned long)fileSize); } } - end: +end: return ret; } -static int wdc_de_get_dump_trace(struct nvme_dev *dev, char * filePath, __u16 binFileNameLen, char *binFileName) +static int wdc_de_get_dump_trace(struct nvme_dev *dev, char *filePath, __u16 binFileNameLen, char *binFileName) { int ret = WDC_STATUS_FAILURE; __u8 *readBuffer = NULL; @@ -8722,8 +8799,7 @@ static int wdc_de_get_dump_trace(struct nvme_dev *dev, char * filePath, __u16 bi __u16 i = 0; __u32 maximumTransferLength = 0; - if (!dev || !binFileName || !filePath) - { + if (!dev || !binFileName || !filePath) { ret = WDC_STATUS_INVALID_PARAMETER; return ret; } @@ -8731,22 +8807,19 @@ static int wdc_de_get_dump_trace(struct nvme_dev *dev, char * filePath, __u16 bi if (wdc_get_max_transfer_len(dev, &maximumTransferLength) < 0) return WDC_STATUS_FAILURE; - do - { + do { /* Get dumptrace size */ ret = wdc_de_VU_read_size(dev, 0, WDC_DE_DUMPTRACE_DESTINATION, &dumptraceSize); - if (ret != WDC_STATUS_SUCCESS) - { - fprintf(stderr, "ERROR : WDC : %s: wdc_de_VU_read_size failed with ret = %d\n", + if (ret != WDC_STATUS_SUCCESS) { + fprintf(stderr, "ERROR: WDC: %s: wdc_de_VU_read_size failed with ret = %d\n", __func__, ret); break; } /* Make sure the size requested is greater than dword */ - if (dumptraceSize < 4) - { + if (dumptraceSize < 4) { ret = WDC_STATUS_FAILURE; - fprintf(stderr, "ERROR : WDC : %s: wdc_de_VU_read_size failed, read size is less than 4 bytes, dumptraceSize = 0x%x\n", + fprintf(stderr, "ERROR: WDC: %s: wdc_de_VU_read_size failed, read size is less than 4 bytes, dumptraceSize = 0x%x\n", __func__, dumptraceSize); break; } @@ -8766,162 +8839,232 @@ static int wdc_de_get_dump_trace(struct nvme_dev *dev, char * filePath, __u16 bi readBufferLen = chunkSize; lastPktReadBufferLen = (dumptraceSize % maxTransferLen) ? (dumptraceSize % maxTransferLen) : chunkSize; - if (readBuffer == NULL) - { - fprintf(stderr, "ERROR : WDC : %s: readBuffer calloc failed\n", __func__); + if (!readBuffer) { + fprintf(stderr, "ERROR: WDC: %s: readBuffer calloc failed\n", __func__); ret = WDC_STATUS_INSUFFICIENT_MEMORY; break; } - for (i = 0; i < chunks; i++) - { + for (i = 0; i < chunks; i++) { offset = ((i*chunkSize) / 4); /* Last loop call, Assign readBufferLen to read only left over bytes */ if (i == (chunks - 1)) - { readBufferLen = lastPktReadBufferLen; - } - ret = wdc_de_VU_read_buffer(dev, 0, WDC_DE_DUMPTRACE_DESTINATION, 0, readBuffer + offset, &readBufferLen); - if (ret != WDC_STATUS_SUCCESS) - { - fprintf(stderr, "ERROR : WDC : %s: wdc_de_VU_read_buffer failed, ret = %d on offset 0x%x\n", - __func__, ret, offset); + ret = wdc_de_VU_read_buffer(dev, 0, WDC_DE_DUMPTRACE_DESTINATION, 0, + readBuffer + offset, &readBufferLen); + if (ret != WDC_STATUS_SUCCESS) { + fprintf(stderr, + "ERROR: WDC: %s: wdc_de_VU_read_buffer failed, ret = %d on offset 0x%x\n", + __func__, ret, offset); break; } } } while (loop); - if (ret == WDC_STATUS_SUCCESS) - { - ret = wdc_WriteToFile(binFileName, (char*)readBuffer, dumptraceSize); + if (ret == WDC_STATUS_SUCCESS) { + ret = wdc_WriteToFile(binFileName, (char *)readBuffer, dumptraceSize); if (ret != WDC_STATUS_SUCCESS) - fprintf(stderr, "ERROR : WDC : %s: wdc_WriteToFile failed, ret = %d\n", __func__, ret); + fprintf(stderr, "ERROR: WDC: %s: wdc_WriteToFile failed, ret = %d\n", + __func__, ret); } else { - fprintf(stderr, "ERROR : WDC : %s: Read Buffer Loop failed, ret = %d\n", __func__, ret); + fprintf(stderr, "ERROR: WDC: %s: Read Buffer Loop failed, ret = %d\n", __func__, + ret); } if (readBuffer) - { free(readBuffer); + + return ret; +} + +int wdc_fetch_vu_file_directory(struct nvme_dev *dev, + struct WDC_DE_VU_LOG_DIRECTORY deEssentialsList, + __s8 *bufferFolderPath, __u8 *serialNo, __u8 *timeString) +{ + int ret = wdc_fetch_log_directory(dev, &deEssentialsList); + __u32 listIdx; + char *dataBuffer; + char fileName[MAX_PATH_LEN]; + + if (ret != WDC_STATUS_SUCCESS) { + fprintf(stderr, "WDC: wdc_fetch_log_directory failed, ret = %d\n", ret); + return ret; + } + + /* Get Debug Data Files */ + for (listIdx = 0; listIdx < deEssentialsList.numOfValidLogEntries; listIdx++) { + if (!deEssentialsList.logEntry[listIdx].metaData.fileSize) { + fprintf(stderr, "ERROR: WDC: File Size for %s is 0\n", + deEssentialsList.logEntry[listIdx].metaData.fileName); + ret = WDC_STATUS_FILE_SIZE_ZERO; + } else { + /* Fetch Log File Data */ + dataBuffer = (char *)calloc(1, (size_t)deEssentialsList.logEntry[listIdx].metaData.fileSize); + ret = wdc_fetch_log_file_from_device(dev, + deEssentialsList.logEntry[listIdx].metaData.fileID, + WDC_DE_DESTN_SPI, + deEssentialsList.logEntry[listIdx].metaData.fileSize, + (__u8 *)dataBuffer); + + /* Write databuffer to file */ + if (ret == WDC_STATUS_SUCCESS) { + memset(fileName, 0, sizeof(fileName)); + wdc_UtilsSnprintf(fileName, MAX_PATH_LEN, "%s%s%s_%s_%s.bin", bufferFolderPath, WDC_DE_PATH_SEPARATOR, + deEssentialsList.logEntry[listIdx].metaData.fileName, serialNo, timeString); + if (deEssentialsList.logEntry[listIdx].metaData.fileSize > 0xFFFFFFFF) { + wdc_WriteToFile(fileName, dataBuffer, 0xFFFFFFFF); + wdc_WriteToFile(fileName, dataBuffer + 0xFFFFFFFF, (__u32)(deEssentialsList.logEntry[listIdx].metaData.fileSize - 0xFFFFFFFF)); + } else { + wdc_WriteToFile(fileName, dataBuffer, (__u32)deEssentialsList.logEntry[listIdx].metaData.fileSize); + } + } else { + fprintf(stderr, "ERROR: WDC: wdc_fetch_log_file_from_device: %s failed, ret = %d\n", + deEssentialsList.logEntry[listIdx].metaData.fileName, ret); + } + free(dataBuffer); + } } return ret; } +int wdc_read_debug_directory(struct nvme_dev *dev, __s8 *bufferFolderPath, __u8 *serialNo, + __u8 *timeString) +{ + __u32 maxNumOfVUFiles = 0; + int ret = wdc_get_log_dir_max_entries(dev, &maxNumOfVUFiles); + struct WDC_DE_VU_LOG_DIRECTORY deEssentialsList; + + if (ret != WDC_STATUS_SUCCESS) { + fprintf(stderr, "WDC: wdc_get_log_dir_max_entries failed, ret = %d\n", ret); + return ret; + } + + memset(&deEssentialsList, 0, sizeof(deEssentialsList)); + deEssentialsList.logEntry = + (struct WDC_DRIVE_ESSENTIALS *)calloc(1, sizeof(struct WDC_DRIVE_ESSENTIALS) * maxNumOfVUFiles); + deEssentialsList.maxNumLogEntries = maxNumOfVUFiles; + + ret = wdc_fetch_vu_file_directory(dev, deEssentialsList, bufferFolderPath, serialNo, + timeString); + + free(deEssentialsList.logEntry); + deEssentialsList.logEntry = NULL; + + return ret; +} + static int wdc_do_drive_essentials(nvme_root_t r, struct nvme_dev *dev, char *dir, char *key) { int ret = 0; void *retPtr; - char fileName[MAX_PATH_LEN]; - __s8 bufferFolderPath[MAX_PATH_LEN]; - char bufferFolderName[MAX_PATH_LEN]; - char tarFileName[MAX_PATH_LEN]; - char tarFiles[MAX_PATH_LEN]; - char tarCmd[MAX_PATH_LEN+MAX_PATH_LEN]; - UtilsTimeInfo timeInfo; - __u8 timeString[MAX_PATH_LEN]; - __u8 serialNo[WDC_SERIAL_NO_LEN]; - __u8 firmwareRevision[WDC_NVME_FIRMWARE_REV_LEN]; - __u8 idSerialNo[WDC_SERIAL_NO_LEN]; - __u8 idFwRev[WDC_NVME_FIRMWARE_REV_LEN]; - __u8 featureIdBuff[4]; - char currDir[MAX_PATH_LEN]; - char *dataBuffer = NULL; - __u32 elogNumEntries, elogBufferSize; - __u32 dataBufferSize; - __u32 listIdx = 0; - __u32 vuLogIdx = 0; - __u32 result; - __u32 maxNumOfVUFiles = 0; + char fileName[MAX_PATH_LEN]; + __s8 bufferFolderPath[MAX_PATH_LEN]; + char bufferFolderName[MAX_PATH_LEN]; + char tarFileName[MAX_PATH_LEN]; + char tarFiles[MAX_PATH_LEN]; + char tarCmd[MAX_PATH_LEN+MAX_PATH_LEN]; + UtilsTimeInfo timeInfo; + __u8 timeString[MAX_PATH_LEN]; + __u8 serialNo[WDC_SERIAL_NO_LEN]; + __u8 firmwareRevision[WDC_NVME_FIRMWARE_REV_LEN]; + __u8 idSerialNo[WDC_SERIAL_NO_LEN]; + __u8 idFwRev[WDC_NVME_FIRMWARE_REV_LEN]; + __u8 featureIdBuff[4]; + char currDir[MAX_PATH_LEN]; + char *dataBuffer = NULL; + __u32 elogNumEntries, elogBufferSize; + __u32 dataBufferSize; + __u32 listIdx = 0; + __u32 vuLogIdx = 0; + __u32 result; struct nvme_id_ctrl ctrl; struct nvme_id_ns ns; struct nvme_error_log_page *elogBuffer; struct nvme_smart_log smart_log; struct nvme_firmware_slot fw_log; - PWDC_NVME_DE_VU_LOGPAGES vuLogInput = NULL; - WDC_DE_VU_LOG_DIRECTORY deEssentialsList; - - memset(bufferFolderPath,0,sizeof(bufferFolderPath)); - memset(bufferFolderName,0,sizeof(bufferFolderName)); - memset(tarFileName,0,sizeof(tarFileName)); - memset(tarFiles,0,sizeof(tarFiles)); - memset(tarCmd,0,sizeof(tarCmd)); - memset(&timeInfo,0,sizeof(timeInfo)); - - if (wdc_get_serial_and_fw_rev(dev, (char *)idSerialNo, (char *)idFwRev)) - { - fprintf(stderr, "ERROR : WDC : get serial # and fw revision failed\n"); + struct WDC_NVME_DE_VU_LOGPAGES *vuLogInput = NULL; + + memset(bufferFolderPath, 0, sizeof(bufferFolderPath)); + memset(bufferFolderName, 0, sizeof(bufferFolderName)); + memset(tarFileName, 0, sizeof(tarFileName)); + memset(tarFiles, 0, sizeof(tarFiles)); + memset(tarCmd, 0, sizeof(tarCmd)); + memset(&timeInfo, 0, sizeof(timeInfo)); + + if (wdc_get_serial_and_fw_rev(dev, (char *)idSerialNo, (char *)idFwRev)) { + fprintf(stderr, "ERROR: WDC: get serial # and fw revision failed\n"); return -1; - } else { - fprintf(stderr, "Get Drive Essentials Data for device serial #: %s and fw revision: %s\n", - idSerialNo, idFwRev); } - /* Create Drive Essentials directory */ + fprintf(stderr, "Get Drive Essentials Data for device serial #: %s and fw revision: %s\n", + idSerialNo, idFwRev); + + /* Create Drive Essentials directory */ wdc_UtilsGetTime(&timeInfo); memset(timeString, 0, sizeof(timeString)); - wdc_UtilsSnprintf((char*)timeString, MAX_PATH_LEN, "%02u%02u%02u_%02u%02u%02u", + wdc_UtilsSnprintf((char *)timeString, MAX_PATH_LEN, "%02u%02u%02u_%02u%02u%02u", timeInfo.year, timeInfo.month, timeInfo.dayOfMonth, timeInfo.hour, timeInfo.minute, timeInfo.second); - wdc_UtilsSnprintf((char*)serialNo,WDC_SERIAL_NO_LEN,(char*)idSerialNo); + wdc_UtilsSnprintf((char *)serialNo, WDC_SERIAL_NO_LEN, (char *)idSerialNo); /* Remove any space form serialNo */ - wdc_UtilsDeleteCharFromString((char*)serialNo, WDC_SERIAL_NO_LEN, ' '); + wdc_UtilsDeleteCharFromString((char *)serialNo, WDC_SERIAL_NO_LEN, ' '); memset(firmwareRevision, 0, sizeof(firmwareRevision)); - wdc_UtilsSnprintf((char*)firmwareRevision, WDC_NVME_FIRMWARE_REV_LEN, (char*)idFwRev); + wdc_UtilsSnprintf((char *)firmwareRevision, WDC_NVME_FIRMWARE_REV_LEN, (char *)idFwRev); /* Remove any space form FirmwareRevision */ - wdc_UtilsDeleteCharFromString((char*)firmwareRevision, WDC_NVME_FIRMWARE_REV_LEN, ' '); + wdc_UtilsDeleteCharFromString((char *)firmwareRevision, WDC_NVME_FIRMWARE_REV_LEN, ' '); - wdc_UtilsSnprintf((char*)bufferFolderName, MAX_PATH_LEN, "%s_%s_%s_%s", - "DRIVE_ESSENTIALS", (char*)serialNo, (char*)firmwareRevision, (char*)timeString); + wdc_UtilsSnprintf((char *)bufferFolderName, MAX_PATH_LEN, "%s_%s_%s_%s", + "DRIVE_ESSENTIALS", (char *)serialNo, (char *)firmwareRevision, (char *)timeString); - if (dir != NULL) { - wdc_UtilsSnprintf((char*)bufferFolderPath, MAX_PATH_LEN, "%s%s%s", + if (dir) { + wdc_UtilsSnprintf((char *)bufferFolderPath, MAX_PATH_LEN, "%s%s%s", (char *)dir, WDC_DE_PATH_SEPARATOR, (char *)bufferFolderName); } else { - retPtr = getcwd((char*)currDir, MAX_PATH_LEN); - if (retPtr != NULL) - wdc_UtilsSnprintf((char*)bufferFolderPath, MAX_PATH_LEN, "%s%s%s", + retPtr = getcwd((char *)currDir, MAX_PATH_LEN); + if (retPtr) { + wdc_UtilsSnprintf((char *)bufferFolderPath, MAX_PATH_LEN, "%s%s%s", (char *)currDir, WDC_DE_PATH_SEPARATOR, (char *)bufferFolderName); - else { - fprintf(stderr, "ERROR : WDC : get current working directory failed\n"); + } else { + fprintf(stderr, "ERROR: WDC: get current working directory failed\n"); return -1; } } - ret = wdc_UtilsCreateDir((char*)bufferFolderPath); - if (ret != 0) - { - fprintf(stderr, "ERROR : WDC : create directory failed, ret = %d, dir = %s\n", ret, bufferFolderPath); + ret = wdc_UtilsCreateDir((char *)bufferFolderPath); + if (ret) { + fprintf(stderr, "ERROR: WDC: create directory failed, ret = %d, dir = %s\n", ret, bufferFolderPath); return -1; - } else { - fprintf(stderr, "Store Drive Essentials bin files in directory: %s\n", bufferFolderPath); } + fprintf(stderr, "Store Drive Essentials bin files in directory: %s\n", bufferFolderPath); + /* Get Identify Controller Data */ - memset(&ctrl, 0, sizeof (struct nvme_id_ctrl)); + memset(&ctrl, 0, sizeof(struct nvme_id_ctrl)); ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); if (ret) { - fprintf(stderr, "ERROR : WDC : nvme_identify_ctrl() failed, ret = %d\n", ret); + fprintf(stderr, "ERROR: WDC: nvme_identify_ctrl() failed, ret = %d\n", ret); return -1; - } else { - wdc_UtilsSnprintf(fileName, MAX_PATH_LEN, "%s%s%s_%s_%s.bin", (char*)bufferFolderPath, WDC_DE_PATH_SEPARATOR, - "IdentifyController", (char*)serialNo, (char*)timeString); - wdc_WriteToFile(fileName, (char*)&ctrl, sizeof (struct nvme_id_ctrl)); } - memset(&ns, 0, sizeof (struct nvme_id_ns)); + wdc_UtilsSnprintf(fileName, MAX_PATH_LEN, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, + WDC_DE_PATH_SEPARATOR, "IdentifyController", (char *)serialNo, + (char *)timeString); + wdc_WriteToFile(fileName, (char *)&ctrl, sizeof(struct nvme_id_ctrl)); + + memset(&ns, 0, sizeof(struct nvme_id_ns)); ret = nvme_identify_ns(dev_fd(dev), 1, &ns); if (ret) { - fprintf(stderr, "ERROR : WDC : nvme_identify_ns() failed, ret = %d\n", ret); + fprintf(stderr, "ERROR: WDC: nvme_identify_ns() failed, ret = %d\n", ret); } else { - wdc_UtilsSnprintf(fileName, MAX_PATH_LEN, "%s%s%s_%s_%s.bin", (char*)bufferFolderPath, WDC_DE_PATH_SEPARATOR, - "IdentifyNamespace", (char*)serialNo, (char*)timeString); - wdc_WriteToFile(fileName, (char*)&ns, sizeof (struct nvme_id_ns)); + wdc_UtilsSnprintf(fileName, MAX_PATH_LEN, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR, + "IdentifyNamespace", (char *)serialNo, (char *)timeString); + wdc_WriteToFile(fileName, (char *)&ns, sizeof(struct nvme_id_ns)); } /* Get Log Pages (0x01, 0x02, 0x03, 0xC0 and 0xE3) */ @@ -8933,46 +9076,45 @@ static int wdc_do_drive_essentials(nvme_root_t r, struct nvme_dev *dev, ret = nvme_get_log_error(dev_fd(dev), elogNumEntries, false, elogBuffer); if (ret) { - fprintf(stderr, "ERROR : WDC : nvme_error_log() failed, ret = %d\n", ret); + fprintf(stderr, "ERROR: WDC: nvme_error_log() failed, ret = %d\n", ret); } else { - wdc_UtilsSnprintf(fileName, MAX_PATH_LEN, "%s%s%s_%s_%s.bin", (char*)bufferFolderPath, WDC_DE_PATH_SEPARATOR, - "ErrorLog", (char*)serialNo, (char*)timeString); - wdc_WriteToFile(fileName, (char*)elogBuffer, elogBufferSize); + wdc_UtilsSnprintf(fileName, MAX_PATH_LEN, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR, + "ErrorLog", (char *)serialNo, (char *)timeString); + wdc_WriteToFile(fileName, (char *)elogBuffer, elogBufferSize); } free(dataBuffer); dataBuffer = NULL; - /* Get Smart log page */ - memset(&smart_log, 0, sizeof (struct nvme_smart_log)); + /* Get Smart log page */ + memset(&smart_log, 0, sizeof(struct nvme_smart_log)); ret = nvme_get_log_smart(dev_fd(dev), NVME_NSID_ALL, false, &smart_log); if (ret) { - fprintf(stderr, "ERROR : WDC : nvme_smart_log() failed, ret = %d\n", ret); + fprintf(stderr, "ERROR: WDC: nvme_smart_log() failed, ret = %d\n", ret); } else { - wdc_UtilsSnprintf(fileName, MAX_PATH_LEN, "%s%s%s_%s_%s.bin", (char*)bufferFolderPath, WDC_DE_PATH_SEPARATOR, - "SmartLog", (char*)serialNo, (char*)timeString); - wdc_WriteToFile(fileName, (char*)&smart_log, sizeof(struct nvme_smart_log)); + wdc_UtilsSnprintf(fileName, MAX_PATH_LEN, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR, + "SmartLog", (char *)serialNo, (char *)timeString); + wdc_WriteToFile(fileName, (char *)&smart_log, sizeof(struct nvme_smart_log)); } - /* Get FW Slot log page */ - memset(&fw_log, 0, sizeof (struct nvme_firmware_slot)); + /* Get FW Slot log page */ + memset(&fw_log, 0, sizeof(struct nvme_firmware_slot)); ret = nvme_get_log_fw_slot(dev_fd(dev), false, &fw_log); if (ret) { - fprintf(stderr, "ERROR : WDC : nvme_fw_log() failed, ret = %d\n", ret); + fprintf(stderr, "ERROR: WDC: nvme_fw_log() failed, ret = %d\n", ret); } else { - wdc_UtilsSnprintf(fileName, MAX_PATH_LEN, "%s%s%s_%s_%s.bin", (char*)bufferFolderPath, WDC_DE_PATH_SEPARATOR, - "FwSLotLog", (char*)serialNo, (char*)timeString); - wdc_WriteToFile(fileName, (char*)&fw_log, sizeof(struct nvme_firmware_slot)); + wdc_UtilsSnprintf(fileName, MAX_PATH_LEN, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR, + "FwSLotLog", (char *)serialNo, (char *)timeString); + wdc_WriteToFile(fileName, (char *)&fw_log, sizeof(struct nvme_firmware_slot)); } - /* Get VU log pages */ + /* Get VU log pages */ /* define inputs for vendor unique log pages */ - vuLogInput = (PWDC_NVME_DE_VU_LOGPAGES)calloc(1, sizeof(WDC_NVME_DE_VU_LOGPAGES)); - vuLogInput->numOfVULogPages = sizeof(deVULogPagesList) / sizeof(deVULogPagesList[0]); + vuLogInput = (struct WDC_NVME_DE_VU_LOGPAGES *)calloc(1, sizeof(struct WDC_NVME_DE_VU_LOGPAGES)); + vuLogInput->numOfVULogPages = ARRAY_SIZE(deVULogPagesList); - for (vuLogIdx = 0; vuLogIdx < vuLogInput->numOfVULogPages; vuLogIdx++) - { + for (vuLogIdx = 0; vuLogIdx < vuLogInput->numOfVULogPages; vuLogIdx++) { dataBufferSize = deVULogPagesList[vuLogIdx].logPageLen; dataBuffer = calloc(1, dataBufferSize); memset(dataBuffer, 0, dataBufferSize); @@ -8981,13 +9123,13 @@ static int wdc_do_drive_essentials(nvme_root_t r, struct nvme_dev *dev, deVULogPagesList[vuLogIdx].logPageId, dataBufferSize, dataBuffer); if (ret) { - fprintf(stderr, "ERROR : WDC : nvme_get_log() for log page 0x%x failed, ret = %d\n", + fprintf(stderr, "ERROR: WDC: nvme_get_log() for log page 0x%x failed, ret = %d\n", deVULogPagesList[vuLogIdx].logPageId, ret); } else { - wdc_UtilsDeleteCharFromString((char*)deVULogPagesList[vuLogIdx].logPageIdStr, 4, ' '); - wdc_UtilsSnprintf(fileName, MAX_PATH_LEN, "%s%s%s_%s_%s_%s.bin", (char*)bufferFolderPath, WDC_DE_PATH_SEPARATOR, - "LogPage", (char*)&deVULogPagesList[vuLogIdx].logPageIdStr, (char*)serialNo, (char*)timeString); - wdc_WriteToFile(fileName, (char*)dataBuffer, dataBufferSize); + wdc_UtilsDeleteCharFromString((char *)deVULogPagesList[vuLogIdx].logPageIdStr, 4, ' '); + wdc_UtilsSnprintf(fileName, MAX_PATH_LEN, "%s%s%s_%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR, + "LogPage", (char *)&deVULogPagesList[vuLogIdx].logPageIdStr, (char *)serialNo, (char *)timeString); + wdc_WriteToFile(fileName, (char *)dataBuffer, dataBufferSize); } free(dataBuffer); @@ -8997,8 +9139,7 @@ static int wdc_do_drive_essentials(nvme_root_t r, struct nvme_dev *dev, free(vuLogInput); /* Get NVMe Features (0x01, 0x02, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C) */ - for (listIdx = 1; listIdx < (sizeof(deFeatureIdList) / sizeof(deFeatureIdList[0])); listIdx++) - { + for (listIdx = 1; listIdx < ARRAY_SIZE(deFeatureIdList); listIdx++) { memset(featureIdBuff, 0, sizeof(featureIdBuff)); /* skipping LbaRangeType as it is an optional nvme command and not supported */ if (deFeatureIdList[listIdx].featureId == FID_LBA_RANGE_TYPE) @@ -9010,95 +9151,40 @@ static int wdc_do_drive_essentials(nvme_root_t r, struct nvme_dev *dev, &featureIdBuff, &result); if (ret) { - fprintf(stderr, "ERROR : WDC : nvme_get_feature id 0x%x failed, ret = %d\n", + fprintf(stderr, "ERROR: WDC: nvme_get_feature id 0x%x failed, ret = %d\n", deFeatureIdList[listIdx].featureId, ret); } else { - wdc_UtilsSnprintf(fileName, MAX_PATH_LEN, "%s%s%s0x%x_%s_%s_%s.bin", (char*)bufferFolderPath, WDC_DE_PATH_SEPARATOR, + wdc_UtilsSnprintf(fileName, MAX_PATH_LEN, "%s%s%s0x%x_%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR, "FEATURE_ID_", deFeatureIdList[listIdx].featureId, deFeatureIdList[listIdx].featureName, serialNo, timeString); - wdc_WriteToFile(fileName, (char*)featureIdBuff, sizeof(featureIdBuff)); + wdc_WriteToFile(fileName, (char *)featureIdBuff, sizeof(featureIdBuff)); } } - /* Read Debug Directory */ - ret = wdc_get_log_dir_max_entries(dev, &maxNumOfVUFiles); - if (ret == WDC_STATUS_SUCCESS) - { - memset(&deEssentialsList, 0, sizeof(deEssentialsList)); - deEssentialsList.logEntry = (WDC_DRIVE_ESSENTIALS*)calloc(1, sizeof(WDC_DRIVE_ESSENTIALS)*maxNumOfVUFiles); - deEssentialsList.maxNumLogEntries = maxNumOfVUFiles; - - /* Fetch VU File Directory */ - ret = wdc_fetch_log_directory(dev, &deEssentialsList); - if (ret == WDC_STATUS_SUCCESS) - { - /* Get Debug Data Files */ - for (listIdx = 0; listIdx < deEssentialsList.numOfValidLogEntries; listIdx++) - { - if (0 == deEssentialsList.logEntry[listIdx].metaData.fileSize) - { - fprintf(stderr, "ERROR : WDC : File Size for %s is 0\n", - deEssentialsList.logEntry[listIdx].metaData.fileName); - ret = WDC_STATUS_FILE_SIZE_ZERO; - } else { - /* Fetch Log File Data */ - dataBuffer = (char *)calloc(1, (size_t)deEssentialsList.logEntry[listIdx].metaData.fileSize); - ret = wdc_fetch_log_file_from_device(dev, deEssentialsList.logEntry[listIdx].metaData.fileID, WDC_DE_DESTN_SPI, deEssentialsList.logEntry[listIdx].metaData.fileSize, - (__u8 *)dataBuffer); - - /* Write databuffer to file */ - if (ret == WDC_STATUS_SUCCESS) - { - memset(fileName, 0, sizeof(fileName)); - wdc_UtilsSnprintf(fileName, MAX_PATH_LEN, "%s%s%s_%s_%s.bin", bufferFolderPath, WDC_DE_PATH_SEPARATOR, - deEssentialsList.logEntry[listIdx].metaData.fileName, serialNo, timeString); - if (deEssentialsList.logEntry[listIdx].metaData.fileSize > 0xFFFFFFFF) - { - wdc_WriteToFile(fileName, dataBuffer, 0xFFFFFFFF); - wdc_WriteToFile(fileName, dataBuffer + 0xFFFFFFFF, (__u32)(deEssentialsList.logEntry[listIdx].metaData.fileSize - 0xFFFFFFFF)); - } else { - wdc_WriteToFile(fileName, dataBuffer, (__u32)deEssentialsList.logEntry[listIdx].metaData.fileSize); - } - } else { - fprintf(stderr, "ERROR : WDC : wdc_fetch_log_file_from_device: %s failed, ret = %d\n", - deEssentialsList.logEntry[listIdx].metaData.fileName, ret); - } - free(dataBuffer); - dataBuffer = NULL; - } - } - } else { - fprintf(stderr, "WDC : wdc_fetch_log_directory failed, ret = %d\n", ret); - } - - free(deEssentialsList.logEntry); - deEssentialsList.logEntry = NULL; - } else { - fprintf(stderr, "WDC : wdc_get_log_dir_max_entries failed, ret = %d\n", ret); - } + ret = wdc_read_debug_directory(dev, bufferFolderPath, serialNo, timeString); /* Get Dump Trace Data */ - wdc_UtilsSnprintf(fileName, MAX_PATH_LEN, "%s%s%s_%s_%s.bin", (char*)bufferFolderPath, WDC_DE_PATH_SEPARATOR, "dumptrace", serialNo, timeString); - if (WDC_STATUS_SUCCESS != (ret = wdc_de_get_dump_trace(dev, (char*)bufferFolderPath, 0, fileName))) - { - fprintf(stderr, "ERROR : WDC : wdc_de_get_dump_trace failed, ret = %d\n", ret); - } + wdc_UtilsSnprintf(fileName, MAX_PATH_LEN, "%s%s%s_%s_%s.bin", (char *)bufferFolderPath, WDC_DE_PATH_SEPARATOR, "dumptrace", serialNo, timeString); + ret = wdc_de_get_dump_trace(dev, (char *)bufferFolderPath, 0, fileName); + if (ret != WDC_STATUS_SUCCESS) + fprintf(stderr, "ERROR: WDC: wdc_de_get_dump_trace failed, ret = %d\n", ret); /* Tar the Drive Essentials directory */ - wdc_UtilsSnprintf(tarFileName, sizeof(tarFileName), "%s%s", (char*)bufferFolderPath, WDC_DE_TAR_FILE_EXTN); - if (dir != NULL) { - wdc_UtilsSnprintf(tarFiles, sizeof(tarFiles), "%s%s%s%s%s", - (char*)dir, WDC_DE_PATH_SEPARATOR, (char*)bufferFolderName, WDC_DE_PATH_SEPARATOR, WDC_DE_TAR_FILES); - } else { - wdc_UtilsSnprintf(tarFiles, sizeof(tarFiles), "%s%s%s", (char*)bufferFolderName, WDC_DE_PATH_SEPARATOR, WDC_DE_TAR_FILES); - } - wdc_UtilsSnprintf(tarCmd, sizeof(tarCmd), "%s %s %s", WDC_DE_TAR_CMD, (char*)tarFileName, (char*)tarFiles); + wdc_UtilsSnprintf(tarFileName, sizeof(tarFileName), "%s%s", (char *)bufferFolderPath, WDC_DE_TAR_FILE_EXTN); + if (dir) + wdc_UtilsSnprintf(tarFiles, sizeof(tarFiles), "%s%s%s%s%s", (char *)dir, + WDC_DE_PATH_SEPARATOR, (char *)bufferFolderName, + WDC_DE_PATH_SEPARATOR, WDC_DE_TAR_FILES); + else + wdc_UtilsSnprintf(tarFiles, sizeof(tarFiles), "%s%s%s", (char *)bufferFolderName, + WDC_DE_PATH_SEPARATOR, WDC_DE_TAR_FILES); + wdc_UtilsSnprintf(tarCmd, sizeof(tarCmd), "%s %s %s", WDC_DE_TAR_CMD, (char *)tarFileName, (char *)tarFiles); ret = system(tarCmd); - if (ret) { - fprintf(stderr, "ERROR : WDC : Tar of Drive Essentials data failed, ret = %d\n", ret); - } + if (ret) + fprintf(stderr, "ERROR: WDC: Tar of Drive Essentials data failed, ret = %d\n", + ret); fprintf(stderr, "Get of Drive Essentials data successful\n"); nvme_free_tree(r); @@ -9139,12 +9225,12 @@ static int wdc_drive_essentials(int argc, char **argv, struct command *command, r = nvme_scan(NULL); capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_DRIVE_ESSENTIALS) != WDC_DRIVE_CAP_DRIVE_ESSENTIALS) { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; goto out; } - if (cfg.dirName != NULL) { + if (cfg.dirName) { strncpy(d, cfg.dirName, PATH_MAX - 1); d_ptr = d; } else { @@ -9163,7 +9249,7 @@ static int wdc_do_drive_resize(struct nvme_dev *dev, uint64_t new_size) int ret; struct nvme_passthru_cmd admin_cmd; - memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); + memset(&admin_cmd, 0, sizeof(struct nvme_passthru_cmd)); admin_cmd.opcode = WDC_NVME_DRIVE_RESIZE_OPCODE; admin_cmd.cdw12 = ((WDC_NVME_DRIVE_RESIZE_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_DRIVE_RESIZE_CMD); @@ -9178,7 +9264,7 @@ static int wdc_do_namespace_resize(struct nvme_dev *dev, __u32 nsid, __u32 op_op int ret; struct nvme_passthru_cmd admin_cmd; - memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); + memset(&admin_cmd, 0, sizeof(struct nvme_passthru_cmd)); admin_cmd.opcode = WDC_NVME_NAMESPACE_RESIZE_OPCODE; admin_cmd.nsid = nsid; admin_cmd.cdw10 = op_option; @@ -9192,7 +9278,7 @@ static int wdc_do_drive_info(struct nvme_dev *dev, __u32 *result) int ret; struct nvme_passthru_cmd admin_cmd; - memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); + memset(&admin_cmd, 0, sizeof(struct nvme_passthru_cmd)); admin_cmd.opcode = WDC_NVME_DRIVE_INFO_OPCODE; admin_cmd.cdw12 = ((WDC_NVME_DRIVE_INFO_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_DRIVE_INFO_CMD); @@ -9238,7 +9324,7 @@ static int wdc_drive_resize(int argc, char **argv, if ((capabilities & WDC_DRIVE_CAP_RESIZE) == WDC_DRIVE_CAP_RESIZE) { ret = wdc_do_drive_resize(dev, cfg.size); } else { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; } @@ -9282,12 +9368,9 @@ static int wdc_namespace_resize(int argc, char **argv, if (ret) return ret; - if ((cfg.op_option != 0x1) && - (cfg.op_option != 0x2) && - (cfg.op_option != 0x3) && - (cfg.op_option != 0xF)) - { - fprintf(stderr, "ERROR : WDC: unsupported OP option parameter\n"); + if ((cfg.op_option != 0x1) && (cfg.op_option != 0x2) && (cfg.op_option != 0x3) && + (cfg.op_option != 0xF)) { + fprintf(stderr, "ERROR: WDC: unsupported OP option parameter\n"); dev_close(dev); return -1; } @@ -9299,10 +9382,10 @@ static int wdc_namespace_resize(int argc, char **argv, ret = wdc_do_namespace_resize(dev, cfg.namespace_id, cfg.op_option); - if (ret != 0) - printf("ERROR : WDC: Namespace Resize of namespace id 0x%x, op option 0x%x failed\n", cfg.namespace_id, cfg.op_option); + if (ret) + printf("ERROR: WDC: Namespace Resize of namespace id 0x%x, op option 0x%x failed\n", cfg.namespace_id, cfg.op_option); } else { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; } @@ -9350,19 +9433,20 @@ static int wdc_reason_identifier(int argc, char **argv, r = nvme_scan(NULL); - if (cfg.log_id != NVME_LOG_LID_TELEMETRY_HOST&& cfg.log_id != NVME_LOG_LID_TELEMETRY_CTRL) { - fprintf(stderr, "ERROR : WDC: Invalid Log ID. It must be 7 (Host) or 8 (Controller)\n"); + if (cfg.log_id != NVME_LOG_LID_TELEMETRY_HOST && + cfg.log_id != NVME_LOG_LID_TELEMETRY_CTRL) { + fprintf(stderr, "ERROR: WDC: Invalid Log ID. It must be 7 (Host) or 8 (Controller)\n"); ret = -1; goto close_fd; } - if (cfg.file != NULL) { + if (cfg.file) { int verify_file; /* verify the passed in file name and path is valid before getting the dump data */ verify_file = open(cfg.file, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (verify_file < 0) { - fprintf(stderr, "ERROR : WDC: open : %s\n", strerror(errno)); + fprintf(stderr, "ERROR: WDC: open: %s\n", strerror(errno)); ret = -1; goto close_fd; } @@ -9371,21 +9455,21 @@ static int wdc_reason_identifier(int argc, char **argv, } else { wdc_UtilsGetTime(&timeInfo); memset(timeStamp, 0, sizeof(timeStamp)); - wdc_UtilsSnprintf((char*)timeStamp, MAX_PATH_LEN, "%02u%02u%02u_%02u%02u%02u", + wdc_UtilsSnprintf((char *)timeStamp, MAX_PATH_LEN, "%02u%02u%02u_%02u%02u%02u", timeInfo.year, timeInfo.month, timeInfo.dayOfMonth, timeInfo.hour, timeInfo.minute, timeInfo.second); if (cfg.log_id == NVME_LOG_LID_TELEMETRY_CTRL) - snprintf(fileSuffix, PATH_MAX, "_error_reason_identifier_ctlr_%s", (char*)timeStamp); + snprintf(fileSuffix, PATH_MAX, "_error_reason_identifier_ctlr_%s", (char *)timeStamp); else - snprintf(fileSuffix, PATH_MAX, "_error_reason_identifier_host_%s", (char*)timeStamp); + snprintf(fileSuffix, PATH_MAX, "_error_reason_identifier_host_%s", (char *)timeStamp); if (wdc_get_serial_name(dev, f, PATH_MAX, fileSuffix) == -1) { - fprintf(stderr, "ERROR : WDC: failed to generate file name\n"); + fprintf(stderr, "ERROR: WDC: failed to generate file name\n"); ret = -1; goto close_fd; } if (strlen(f) > PATH_MAX - 5) { - fprintf(stderr, "ERROR : WDC: file name overflow\n"); + fprintf(stderr, "ERROR: WDC: file name overflow\n"); ret = -1; goto close_fd; } @@ -9398,13 +9482,13 @@ static int wdc_reason_identifier(int argc, char **argv, if ((capabilities & WDC_DRIVE_CAP_REASON_ID) == WDC_DRIVE_CAP_REASON_ID) { ret = wdc_do_get_reason_id(dev, f, cfg.log_id); } else { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + fprintf(stderr, "ERROR: WDC:unsupported device for this command\n"); ret = -1; } nvme_show_status(ret); - close_fd: +close_fd: dev_close(dev); nvme_free_tree(r); return ret; @@ -9413,43 +9497,76 @@ static int wdc_reason_identifier(int argc, char **argv, static const char *nvme_log_id_to_string(__u8 log_id) { switch (log_id) { - case NVME_LOG_LID_ERROR: return "Error Information Log ID"; - case NVME_LOG_LID_SMART: return "Smart/Health Information Log ID"; - case NVME_LOG_LID_FW_SLOT: return "Firmware Slot Information Log ID"; - case NVME_LOG_LID_CHANGED_NS: return "Namespace Changed Log ID"; - case NVME_LOG_LID_CMD_EFFECTS: return "Commamds Supported and Effects Log ID"; - case NVME_LOG_LID_DEVICE_SELF_TEST: return "Device Self Test Log ID"; - case NVME_LOG_LID_TELEMETRY_HOST: return "Telemetry Host Initiated Log ID"; - case NVME_LOG_LID_TELEMETRY_CTRL: return "Telemetry Controller Generated Log ID"; - case NVME_LOG_LID_ENDURANCE_GROUP: return "Endurance Group Log ID"; - case NVME_LOG_LID_ANA: return "ANA Log ID"; - case NVME_LOG_LID_PERSISTENT_EVENT: return "Persistent Event Log ID"; - case NVME_LOG_LID_DISCOVER: return "Discovery Log ID"; - case NVME_LOG_LID_RESERVATION: return "Reservation Notification Log ID"; - case NVME_LOG_LID_SANITIZE: return "Sanitize Status Log ID"; - - case WDC_LOG_ID_C0: return "WDC Vendor Unique Log ID C0"; - case WDC_LOG_ID_C1: return "WDC Vendor Unique Log ID C1"; - case WDC_LOG_ID_C2: return "WDC Vendor Unique Log ID C2"; - case WDC_LOG_ID_C3: return "WDC Vendor Unique Log ID C3"; - case WDC_LOG_ID_C4: return "WDC Vendor Unique Log ID C4"; - case WDC_LOG_ID_C5: return "WDC Vendor Unique Log ID C5"; - case WDC_LOG_ID_C6: return "WDC Vendor Unique Log ID C6"; - case WDC_LOG_ID_C8: return "WDC Vendor Unique Log ID C8"; - case WDC_LOG_ID_CA: return "WDC Vendor Unique Log ID CA"; - case WDC_LOG_ID_CB: return "WDC Vendor Unique Log ID CB"; - case WDC_LOG_ID_D0: return "WDC Vendor Unique Log ID D0"; - case WDC_LOG_ID_D1: return "WDC Vendor Unique Log ID D1"; - case WDC_LOG_ID_D6: return "WDC Vendor Unique Log ID D6"; - case WDC_LOG_ID_D7: return "WDC Vendor Unique Log ID D7"; - case WDC_LOG_ID_D8: return "WDC Vendor Unique Log ID D8"; - case WDC_LOG_ID_DE: return "WDC Vendor Unique Log ID DE"; - case WDC_LOG_ID_F0: return "WDC Vendor Unique Log ID F0"; - case WDC_LOG_ID_F1: return "WDC Vendor Unique Log ID F1"; - case WDC_LOG_ID_F2: return "WDC Vendor Unique Log ID F2"; - case WDC_LOG_ID_FA: return "WDC Vendor Unique Log ID FA"; - - default: return "Unknown Log ID"; + case NVME_LOG_LID_ERROR: + return "Error Information Log ID"; + case NVME_LOG_LID_SMART: + return "Smart/Health Information Log ID"; + case NVME_LOG_LID_FW_SLOT: + return "Firmware Slot Information Log ID"; + case NVME_LOG_LID_CHANGED_NS: + return "Namespace Changed Log ID"; + case NVME_LOG_LID_CMD_EFFECTS: + return "Commamds Supported and Effects Log ID"; + case NVME_LOG_LID_DEVICE_SELF_TEST: + return "Device Self Test Log ID"; + case NVME_LOG_LID_TELEMETRY_HOST: + return "Telemetry Host Initiated Log ID"; + case NVME_LOG_LID_TELEMETRY_CTRL: + return "Telemetry Controller Generated Log ID"; + case NVME_LOG_LID_ENDURANCE_GROUP: + return "Endurance Group Log ID"; + case NVME_LOG_LID_ANA: + return "ANA Log ID"; + case NVME_LOG_LID_PERSISTENT_EVENT: + return "Persistent Event Log ID"; + case NVME_LOG_LID_DISCOVER: + return "Discovery Log ID"; + case NVME_LOG_LID_RESERVATION: + return "Reservation Notification Log ID"; + case NVME_LOG_LID_SANITIZE: + return "Sanitize Status Log ID"; + case WDC_LOG_ID_C0: + return "WDC Vendor Unique Log ID C0"; + case WDC_LOG_ID_C1: + return "WDC Vendor Unique Log ID C1"; + case WDC_LOG_ID_C2: + return "WDC Vendor Unique Log ID C2"; + case WDC_LOG_ID_C3: + return "WDC Vendor Unique Log ID C3"; + case WDC_LOG_ID_C4: + return "WDC Vendor Unique Log ID C4"; + case WDC_LOG_ID_C5: + return "WDC Vendor Unique Log ID C5"; + case WDC_LOG_ID_C6: + return "WDC Vendor Unique Log ID C6"; + case WDC_LOG_ID_C8: + return "WDC Vendor Unique Log ID C8"; + case WDC_LOG_ID_CA: + return "WDC Vendor Unique Log ID CA"; + case WDC_LOG_ID_CB: + return "WDC Vendor Unique Log ID CB"; + case WDC_LOG_ID_D0: + return "WDC Vendor Unique Log ID D0"; + case WDC_LOG_ID_D1: + return "WDC Vendor Unique Log ID D1"; + case WDC_LOG_ID_D6: + return "WDC Vendor Unique Log ID D6"; + case WDC_LOG_ID_D7: + return "WDC Vendor Unique Log ID D7"; + case WDC_LOG_ID_D8: + return "WDC Vendor Unique Log ID D8"; + case WDC_LOG_ID_DE: + return "WDC Vendor Unique Log ID DE"; + case WDC_LOG_ID_F0: + return "WDC Vendor Unique Log ID F0"; + case WDC_LOG_ID_F1: + return "WDC Vendor Unique Log ID F1"; + case WDC_LOG_ID_F2: + return "WDC Vendor Unique Log ID F2"; + case WDC_LOG_ID_FA: + return "WDC Vendor Unique Log ID FA"; + default: + return "Unknown Log ID"; } } @@ -9462,7 +9579,7 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command nvme_root_t r; __u64 capabilities = 0; struct wdc_c2_cbs_data *cbs_data = NULL; - int i; + int i; __u8 log_id = 0; __u32 device_id, read_vendor_id; @@ -9485,7 +9602,7 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command ret = validate_output_format(cfg.output_format); if (ret < 0) { - fprintf(stderr, "%s: ERROR : WDC : invalid output format\n", __func__); + fprintf(stderr, "%s: ERROR: WDC: invalid output format\n", __func__); dev_close(dev); return ret; } @@ -9494,8 +9611,8 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command r = nvme_scan(NULL); capabilities = wdc_get_drive_capabilities(r, dev); - if ((capabilities & WDC_DRIVE_CAP_LOG_PAGE_DIR) == 0) { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + if (!(capabilities & WDC_DRIVE_CAP_LOG_PAGE_DIR)) { + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; } else { ret = wdc_get_pci_ids(r, dev, &device_id, &read_vendor_id); @@ -9503,47 +9620,52 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE_C8 : WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE; /* verify the 0xC2 Device Manageability log page is supported */ if (wdc_nvme_check_supported_log_page(r, dev, log_id) == false) { - fprintf(stderr, "%s: ERROR : WDC : 0x%x Log Page not supported\n", __func__, log_id); + fprintf(stderr, "%s: ERROR: WDC: 0x%x Log Page not supported\n", __func__, log_id); ret = -1; goto out; } if (get_dev_mgment_cbs_data(r, dev, WDC_C2_LOG_PAGES_SUPPORTED_ID, (void *)&cbs_data)) { - if (cbs_data != NULL) { + if (cbs_data) { printf("Log Page Directory\n"); /* print the supported pages */ if (!strcmp(cfg.output_format, "normal")) { - for (i = 0; i < le32_to_cpu(cbs_data->length); i++) { + for (i = 0; i < le32_to_cpu(cbs_data->length); i++) printf("0x%x - %s\n", cbs_data->data[i], - nvme_log_id_to_string(cbs_data->data[i])); - } + nvme_log_id_to_string(cbs_data->data[i])); } else if (!strcmp(cfg.output_format, "binary")) { - d((__u8 *)cbs_data->data, le32_to_cpu(cbs_data->length), 16, 1); + d((__u8 *)cbs_data->data, le32_to_cpu(cbs_data->length), 16, + 1); } else if (!strcmp(cfg.output_format, "json")) { - struct json_object *root; - root = json_create_object(); + struct json_object *root = json_create_object(); - for (i = 0; i < le32_to_cpu(cbs_data->length); i++) { - json_object_add_value_int(root, nvme_log_id_to_string(cbs_data->data[i]), - cbs_data->data[i]); - } + for (i = 0; i < le32_to_cpu(cbs_data->length); i++) + json_object_add_value_int(root, + nvme_log_id_to_string(cbs_data->data[i]), + cbs_data->data[i]); json_print_object(root, NULL); printf("\n"); json_free_object(root); - } else - fprintf(stderr, "%s: ERROR : WDC : Invalid format, format = %s\n", __func__, cfg.output_format); + } else { + fprintf(stderr, + "%s: ERROR: WDC: Invalid format, format = %s\n", + __func__, cfg.output_format); + } free(cbs_data); - } else - fprintf(stderr, "%s: ERROR : WDC : NULL_data ptr\n", __func__); - } else - fprintf(stderr, "%s: ERROR : WDC : 0xC2 Log Page entry ID 0x%x not found\n", __func__, WDC_C2_LOG_PAGES_SUPPORTED_ID); + } else { + fprintf(stderr, "%s: ERROR: WDC: NULL_data ptr\n", __func__); + } + } else { + fprintf(stderr, "%s: ERROR: WDC: 0xC2 Log Page entry ID 0x%x not found\n", + __func__, WDC_C2_LOG_PAGES_SUPPORTED_ID); + } } - out: +out: nvme_free_tree(r); dev_close(dev); return ret; @@ -9557,14 +9679,13 @@ static int wdc_get_drive_reason_id(struct nvme_dev *dev, char *drive_reason_id, struct nvme_id_ctrl ctrl; char *reason_id_str = "reason_id"; - i = sizeof (ctrl.sn) - 1; - j = sizeof (ctrl.mn) - 1; + i = sizeof(ctrl.sn) - 1; + j = sizeof(ctrl.mn) - 1; memset(drive_reason_id, 0, len); - memset(&ctrl, 0, sizeof (struct nvme_id_ctrl)); + memset(&ctrl, 0, sizeof(struct nvme_id_ctrl)); ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); if (ret) { - fprintf(stderr, "ERROR : WDC : nvme_identify_ctrl() failed " - "0x%x\n", ret); + fprintf(stderr, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x\n", ret); return -1; } /* Remove trailing spaces from the sn and mn */ @@ -9580,8 +9701,8 @@ static int wdc_get_drive_reason_id(struct nvme_dev *dev, char *drive_reason_id, res_len = snprintf(drive_reason_id, len, "%s_%s_%s", ctrl.sn, ctrl.mn, reason_id_str); if (len <= res_len) { - fprintf(stderr, "ERROR : WDC : cannot format serial number due to data " - "of unexpected length\n"); + fprintf(stderr, + "ERROR: WDC: cannot format serial number due to data of unexpected length\n"); return -1; } @@ -9597,14 +9718,14 @@ static int wdc_save_reason_id(struct nvme_dev *dev, __u8 *rsn_ident, int size) struct stat st = {0}; if (wdc_get_drive_reason_id(dev, drive_reason_id, PATH_MAX) == -1) { - fprintf(stderr, "%s: ERROR : failed to get drive reason id\n", __func__); + fprintf(stderr, "%s: ERROR: failed to get drive reason id\n", __func__); return -1; } /* make the nvmecli dir in /usr/local if it doesn't already exist */ if (stat(reason_id_path, &st) == -1) { if (mkdir(reason_id_path, 0700) < 0) { - fprintf(stderr, "%s: ERROR : failed to mkdir %s : %s\n", + fprintf(stderr, "%s: ERROR: failed to mkdir %s: %s\n", __func__, reason_id_path, strerror(errno)); return -1; } @@ -9616,7 +9737,7 @@ static int wdc_save_reason_id(struct nvme_dev *dev, __u8 *rsn_ident, int size) fprintf(stderr, "%s: reason id file = %s\n", __func__, reason_id_file); - /* save off the error reason identifier to a file in /usr/local/nvmecli */ + /* save off the error reason identifier to a file in /usr/local/nvmecli */ ret = wdc_create_log_file(reason_id_file, rsn_ident, WDC_REASON_ID_ENTRY_LEN); free(reason_id_file); @@ -9631,7 +9752,7 @@ static int wdc_clear_reason_id(struct nvme_dev *dev) char drive_reason_id[PATH_MAX] = {0}; if (wdc_get_drive_reason_id(dev, drive_reason_id, PATH_MAX) == -1) { - fprintf(stderr, "%s: ERROR : failed to get drive reason id\n", __func__); + fprintf(stderr, "%s: ERROR: failed to get drive reason id\n", __func__); return -1; } @@ -9650,7 +9771,7 @@ static int wdc_clear_reason_id(struct nvme_dev *dev) /* remove the reason id file */ ret = remove(reason_id_file); - free: +free: free(reason_id_file); return ret; @@ -9666,11 +9787,11 @@ static int wdc_dump_telemetry_hdr(struct nvme_dev *dev, int log_id, struct nvme_ ret = nvme_get_log_telemetry_ctrl(dev_fd(dev), false, 0, 512, (void *)log_hdr); - if (ret < 0) + if (ret < 0) { perror("get-telemetry-log"); - else if (ret > 0) { + } else if (ret > 0) { nvme_show_status(ret); - fprintf(stderr, "%s: ERROR : Failed to acquire telemetry header, ret = %d!\n", __func__, ret); + fprintf(stderr, "%s: ERROR: Failed to acquire telemetry header, ret = %d!\n", __func__, ret); } return ret; @@ -9683,17 +9804,17 @@ static int wdc_do_get_reason_id(struct nvme_dev *dev, char *file, int log_id) __u32 log_hdr_size = sizeof(struct nvme_telemetry_log); __u32 reason_id_size = 0; - log_hdr = (struct nvme_telemetry_log *) malloc(log_hdr_size); - if (log_hdr == NULL) { - fprintf(stderr, "%s: ERROR : malloc failed, size : 0x%x, status : %s\n", __func__, log_hdr_size, strerror(errno)); + log_hdr = (struct nvme_telemetry_log *)malloc(log_hdr_size); + if (!log_hdr) { + fprintf(stderr, "%s: ERROR: malloc failed, size : 0x%x, status: %s\n", __func__, log_hdr_size, strerror(errno)); ret = -1; goto out; } memset(log_hdr, 0, log_hdr_size); ret = wdc_dump_telemetry_hdr(dev, log_id, log_hdr); - if (ret != 0) { - fprintf(stderr, "%s: ERROR : get telemetry header failed, ret : %d\n", __func__, ret); + if (ret) { + fprintf(stderr, "%s: ERROR: get telemetry header failed, ret : %d\n", __func__, ret); ret = -1; goto out; } @@ -9718,17 +9839,16 @@ static void wdc_print_nand_stats_normal(__u16 version, void *data) __u16 temp_norm; __u64 *temp_ptr = NULL; - switch (version) - { + switch (version) { case 0: - printf(" NAND Statistics :- \n"); + printf(" NAND Statistics :-\n"); printf(" NAND Writes TLC (Bytes) %s\n", uint128_t_to_string( le128_to_cpu(nand_stats->nand_write_tlc))); printf(" NAND Writes SLC (Bytes) %s\n", uint128_t_to_string( le128_to_cpu(nand_stats->nand_write_slc))); - printf(" NAND Program Failures %"PRIu32"\n", + printf(" NAND Program Failures %"PRIu32"\n", (uint32_t)le32_to_cpu(nand_stats->nand_prog_failure)); printf(" NAND Erase Failures %"PRIu32"\n", (uint32_t)le32_to_cpu(nand_stats->nand_erase_failure)); @@ -9736,7 +9856,7 @@ static void wdc_print_nand_stats_normal(__u16 version, void *data) (uint32_t)le32_to_cpu(nand_stats->bad_block_count)); printf(" NAND XOR/RAID Recovery Trigger Events %"PRIu64"\n", le64_to_cpu(nand_stats->nand_rec_trigger_event)); - printf(" E2E Error Counter %"PRIu64"\n", + printf(" E2E Error Counter %"PRIu64"\n", le64_to_cpu(nand_stats->e2e_error_counter)); printf(" Number Successful NS Resizing Events %"PRIu64"\n", le64_to_cpu(nand_stats->successful_ns_resize_event)); @@ -9744,19 +9864,19 @@ static void wdc_print_nand_stats_normal(__u16 version, void *data) le16_to_cpu(nand_stats->log_page_version)); break; case 3: - printf(" NAND Statistics V3:- \n"); + printf(" NAND Statistics V3:-\n"); printf(" TLC Units Written %s\n", uint128_t_to_string( le128_to_cpu(nand_stats_v3->nand_write_tlc))); - printf(" SLC Units Written %s\n", + printf(" SLC Units Written %s\n", uint128_t_to_string( le128_to_cpu(nand_stats_v3->nand_write_slc))); temp_ptr = (__u64 *)nand_stats_v3->bad_nand_block_count; temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF); temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16); - printf(" Bad NAND Blocks Count - Normalized %"PRIu16"\n", + printf(" Bad NAND Blocks Count - Normalized %"PRIu16"\n", le16_to_cpu(temp_norm)); - printf(" Bad NAND Blocks Count - Raw %"PRIu64"\n", + printf(" Bad NAND Blocks Count - Raw %"PRIu64"\n", le64_to_cpu(temp_raw)); printf(" NAND XOR Recovery count %"PRIu64"\n", le64_to_cpu(nand_stats_v3->xor_recovery_count)); @@ -9781,14 +9901,14 @@ static void wdc_print_nand_stats_normal(__u16 version, void *data) temp_ptr = (__u64 *)nand_stats_v3->program_fail_count; temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF); temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16); - printf(" Program Fail Count - Normalized %"PRIu16"\n", + printf(" Program Fail Count - Normalized %"PRIu16"\n", le16_to_cpu(temp_norm)); - printf(" Program Fail Count - Raw %"PRIu64"\n", + printf(" Program Fail Count - Raw %"PRIu64"\n", le64_to_cpu(temp_raw)); temp_ptr = (__u64 *)nand_stats_v3->erase_fail_count; temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF); temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16); - printf(" Erase Fail Count - Normalized %"PRIu16"\n", + printf(" Erase Fail Count - Normalized %"PRIu16"\n", le16_to_cpu(temp_norm)); printf(" Erase Fail Count - Raw %"PRIu64"\n", le64_to_cpu(temp_raw)); @@ -9837,7 +9957,7 @@ static void wdc_print_nand_stats_normal(__u16 version, void *data) break; default: - fprintf(stderr, "WDC: Nand Stats ERROR : Invalid version\n"); + fprintf(stderr, "WDC: Nand Stats ERROR: Invalid version\n"); break; } @@ -9847,17 +9967,13 @@ static void wdc_print_nand_stats_json(__u16 version, void *data) { struct wdc_nand_stats *nand_stats = (struct wdc_nand_stats *)(data); struct wdc_nand_stats_V3 *nand_stats_v3 = (struct wdc_nand_stats_V3 *)(data); - struct json_object *root; - root = json_create_object(); + struct json_object *root = json_create_object(); __u64 temp_raw; __u16 temp_norm; __u64 *temp_ptr = NULL; - switch (version) - { - + switch (version) { case 0: - json_object_add_value_uint128(root, "NAND Writes TLC (Bytes)", le128_to_cpu(nand_stats->nand_write_tlc)); json_object_add_value_uint128(root, "NAND Writes SLC (Bytes)", @@ -9878,9 +9994,7 @@ static void wdc_print_nand_stats_json(__u16 version, void *data) json_print_object(root, NULL); printf("\n"); break; - case 3: - json_object_add_value_uint128(root, "NAND Writes TLC (Bytes)", le128_to_cpu(nand_stats_v3->nand_write_tlc)); json_object_add_value_uint128(root, "NAND Writes SLC (Bytes)", @@ -9969,11 +10083,9 @@ static void wdc_print_nand_stats_json(__u16 version, void *data) json_print_object(root, NULL); printf("\n"); break; - default: printf("%s: Invalid Stats Version = %d\n", __func__, version); break; - } json_free_object(root); @@ -9982,7 +10094,7 @@ static void wdc_print_nand_stats_json(__u16 version, void *data) static void wdc_print_pcie_stats_normal(struct wdc_vs_pcie_stats *pcie_stats) { - printf(" PCIE Statistics :- \n"); + printf(" PCIE Statistics :-\n"); printf(" Unsupported Request Error Counter %20"PRIu64"\n", le64_to_cpu(pcie_stats->unsupportedRequestErrorCount)); printf(" ECRC Error Status Counter %20"PRIu64"\n", @@ -10020,8 +10132,7 @@ static void wdc_print_pcie_stats_normal(struct wdc_vs_pcie_stats *pcie_stats) static void wdc_print_pcie_stats_json(struct wdc_vs_pcie_stats *pcie_stats) { - struct json_object *root; - root = json_create_object(); + struct json_object *root = json_create_object(); json_object_add_value_uint64(root, "Unsupported Request Error Counter", le64_to_cpu(pcie_stats->unsupportedRequestErrorCount)); @@ -10074,12 +10185,12 @@ static int wdc_do_vs_nand_stats_sn810_2(struct nvme_dev *dev, char *format) NVME_NSID_ALL); if (ret) { - fprintf(stderr, "ERROR : WDC : %s : Failed to retreive NAND stats\n", __func__); + fprintf(stderr, "ERROR: WDC: %s : Failed to retreive NAND stats\n", __func__); goto out; } else { fmt = validate_output_format(format); if (fmt < 0) { - fprintf(stderr, "ERROR : WDC : %s : invalid output format\n", __func__); + fprintf(stderr, "ERROR: WDC: %s : invalid output format\n", __func__); ret = fmt; goto out; } @@ -10108,21 +10219,22 @@ static int wdc_do_vs_nand_stats(struct nvme_dev *dev, char *format) uint8_t *output = NULL; __u16 version = 0; - if ((output = (uint8_t*)calloc(WDC_NVME_NAND_STATS_SIZE, sizeof(uint8_t))) == NULL) { - fprintf(stderr, "ERROR : WDC : calloc : %s\n", strerror(errno)); + output = (uint8_t *)calloc(WDC_NVME_NAND_STATS_SIZE, sizeof(uint8_t)); + if (!output) { + fprintf(stderr, "ERROR: WDC: calloc: %s\n", strerror(errno)); ret = -1; goto out; } ret = nvme_get_log_simple(dev_fd(dev), WDC_NVME_NAND_STATS_LOG_ID, - WDC_NVME_NAND_STATS_SIZE, (void*)output); + WDC_NVME_NAND_STATS_SIZE, (void *)output); if (ret) { - fprintf(stderr, "ERROR : WDC : %s : Failed to retreive NAND stats\n", __func__); + fprintf(stderr, "ERROR: WDC: %s : Failed to retreive NAND stats\n", __func__); goto out; } else { fmt = validate_output_format(format); if (fmt < 0) { - fprintf(stderr, "ERROR : WDC : invalid output format\n"); + fprintf(stderr, "ERROR: WDC: invalid output format\n"); ret = fmt; goto out; } @@ -10175,14 +10287,13 @@ static int wdc_vs_nand_stats(int argc, char **argv, struct command *command, r = nvme_scan(NULL); capabilities = wdc_get_drive_capabilities(r, dev); - if ((capabilities & WDC_DRIVE_CAP_NAND_STATS) == 0) { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + if (!(capabilities & WDC_DRIVE_CAP_NAND_STATS)) { + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; } else { ret = wdc_get_pci_ids(r, dev, &read_device_id, &read_vendor_id); - if (ret < 0) - { - fprintf(stderr, "ERROR : WDC: %s: failure to get pci ids, ret = %d\n", __func__, ret); + if (ret < 0) { + fprintf(stderr, "ERROR: WDC: %s: failure to get pci ids, ret = %d\n", __func__, ret); return -1; } @@ -10198,7 +10309,7 @@ static int wdc_vs_nand_stats(int argc, char **argv, struct command *command, } if (ret) - fprintf(stderr, "ERROR : WDC : Failure reading NAND statistics, ret = %d\n", ret); + fprintf(stderr, "ERROR: WDC: Failure reading NAND statistics, ret = %d\n", ret); nvme_free_tree(r); dev_close(dev); @@ -10212,7 +10323,7 @@ static int wdc_do_vs_pcie_stats(struct nvme_dev *dev, struct nvme_passthru_cmd admin_cmd; int pcie_stats_size = sizeof(struct wdc_vs_pcie_stats); - memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); + memset(&admin_cmd, 0, sizeof(struct nvme_passthru_cmd)); admin_cmd.opcode = WDC_NVME_PCIE_STATS_OPCODE; admin_cmd.addr = (__u64)(uintptr_t)pcieStatsPtr; admin_cmd.data_len = pcie_stats_size; @@ -10256,14 +10367,14 @@ static int wdc_vs_pcie_stats(int argc, char **argv, struct command *command, r = nvme_scan(NULL); fmt = validate_output_format(cfg.output_format); if (fmt < 0) { - fprintf(stderr, "ERROR : WDC : invalid output format\n"); + fprintf(stderr, "ERROR: WDC: invalid output format\n"); ret = fmt; goto out; } pcieStatsPtr = nvme_alloc(pcie_stats_size, &huge); - if (pcieStatsPtr == NULL) { - fprintf(stderr, "ERROR : WDC : PCIE Stats alloc : %s\n", strerror(errno)); + if (!pcieStatsPtr) { + fprintf(stderr, "ERROR: WDC: PCIE Stats alloc: %s\n", strerror(errno)); ret = -1; goto out; } @@ -10272,14 +10383,14 @@ static int wdc_vs_pcie_stats(int argc, char **argv, struct command *command, capabilities = wdc_get_drive_capabilities(r, dev); - if ((capabilities & WDC_DRIVE_CAP_PCIE_STATS) == 0) { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + if (!(capabilities & WDC_DRIVE_CAP_PCIE_STATS)) { + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; } else { ret = wdc_do_vs_pcie_stats(dev, pcieStatsPtr); - if (ret) - fprintf(stderr, "ERROR : WDC : Failure reading PCIE statistics, ret = 0x%x\n", ret); - else { + if (ret) { + fprintf(stderr, "ERROR: WDC: Failure reading PCIE statistics, ret = 0x%x\n", ret); + } else { /* parse the data */ switch (fmt) { case NORMAL: @@ -10322,7 +10433,7 @@ static int wdc_vs_drive_info(int argc, char **argv, char formatter[41] = { 0 }; char rev_str[16] = { 0 }; uint32_t read_device_id = -1, read_vendor_id = -1; - wdc_nvme_ext_smart_log *ext_smart_log_ptr = NULL; + struct __packed wdc_nvme_ext_smart_log * ext_smart_log_ptr = NULL; struct config { char *output_format; @@ -10343,7 +10454,7 @@ static int wdc_vs_drive_info(int argc, char **argv, fmt = validate_output_format(cfg.output_format); if (fmt < 0) { - fprintf(stderr, "ERROR : WDC %s invalid output format\n", __func__); + fprintf(stderr, "ERROR: WDC %s invalid output format\n", __func__); dev_close(dev); return fmt; } @@ -10352,7 +10463,7 @@ static int wdc_vs_drive_info(int argc, char **argv, ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); if (ret) { - fprintf(stderr, "ERROR : WDC %s: Identify Controller failed\n", __func__); + fprintf(stderr, "ERROR: WDC %s: Identify Controller failed\n", __func__); dev_close(dev); return ret; } @@ -10362,9 +10473,8 @@ static int wdc_vs_drive_info(int argc, char **argv, capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_INFO) == WDC_DRIVE_CAP_INFO) { ret = wdc_get_pci_ids(r, dev, &read_device_id, &read_vendor_id); - if (ret < 0) - { - fprintf(stderr, "ERROR : WDC: %s: failure to get pci ids, ret = %d\n", __func__, ret); + if (ret < 0) { + fprintf(stderr, "ERROR: WDC: %s: failure to get pci ids, ret = %d\n", __func__, ret); goto out; } @@ -10395,10 +10505,9 @@ static int wdc_vs_drive_info(int argc, char **argv, printf("Drive HW Revison: %4.1f\n", (.1 * rev)); printf("FTL Unit Size: 0x%x KB\n", size); printf("Customer SN: %-.*s\n", (int)sizeof(ctrl.sn), &ctrl.sn[0]); - } - else if (fmt == JSON) { - root = json_create_object(); - sprintf(rev_str, "%4.1f", (.1 * rev)); + } else if (fmt == JSON) { + root = json_create_object(); + sprintf(rev_str, "%4.1f", (.1 * rev)); json_object_add_value_string(root, "Drive HW Revison", rev_str); json_object_add_value_int(root, "FTL Unit Size", le16_to_cpu(size)); @@ -10419,12 +10528,11 @@ static int wdc_vs_drive_info(int argc, char **argv, minor_rev = ctrl.sn[13]; if (fmt == NORMAL) { - printf("Drive HW Revision: %c.%c \n", major_rev, minor_rev); + printf("Drive HW Revision: %c.%c\n", major_rev, minor_rev); printf("Customer SN: %-.*s\n", 14, &ctrl.sn[0]); - } - else if (fmt == JSON) { - root = json_create_object(); - sprintf(rev_str, "%c.%c", major_rev, minor_rev); + } else if (fmt == JSON) { + root = json_create_object(); + sprintf(rev_str, "%c.%c", major_rev, minor_rev); json_object_add_value_string(root, "Drive HW Revison", rev_str); wdc_StrFormat(formatter, sizeof(formatter), &ctrl.sn[0], 14); json_object_add_value_string(root, "Customer SN", formatter); @@ -10439,21 +10547,22 @@ static int wdc_vs_drive_info(int argc, char **argv, /* Get the Drive HW Rev from the C6 Log page */ ret = nvme_get_hw_rev_log(dev_fd(dev), &data, 0, NVME_NSID_ALL); - if (ret == 0) { - wdc_nvme_hw_rev_log *log_data = (wdc_nvme_hw_rev_log *)data; + if (!ret) { + struct wdc_nvme_hw_rev_log *log_data = (struct wdc_nvme_hw_rev_log *)data; + major_rev = log_data->hw_rev_gdr; free(data); data = NULL; } else { - fprintf(stderr, "ERROR : WDC: %s: failure to get hw revision log\n", __func__); + fprintf(stderr, "ERROR: WDC: %s: failure to get hw revision log\n", __func__); ret = -1; goto out; } /* Get the Smart C0 log page */ - if ((capabilities & WDC_DRIVE_CAP_CLOUD_LOG_PAGE) == 0) { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + if (!(capabilities & WDC_DRIVE_CAP_CLOUD_LOG_PAGE)) { + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; goto out; } @@ -10461,8 +10570,8 @@ static int wdc_vs_drive_info(int argc, char **argv, ret = nvme_get_ext_smart_cloud_log(dev_fd(dev), &data, 0, NVME_NSID_ALL); - if (ret == 0) { - ext_smart_log_ptr = (wdc_nvme_ext_smart_log *)data; + if (!ret) { + ext_smart_log_ptr = (struct __packed wdc_nvme_ext_smart_log *)data; /* Set the FTL Unit size */ ftl_unit_size = le32_to_cpu(ext_smart_log_ptr->ext_smart_ftlus); @@ -10475,7 +10584,7 @@ static int wdc_vs_drive_info(int argc, char **argv, tcg_dev_ownership = le32_to_cpu(ext_smart_log_ptr->ext_smart_tcgos); free(data); } else { - fprintf(stderr, "ERROR : WDC: %s: failure to get extended smart cloud log\n", __func__); + fprintf(stderr, "ERROR: WDC: %s: failure to get extended smart cloud log\n", __func__); ret = -1; goto out; } @@ -10486,13 +10595,12 @@ static int wdc_vs_drive_info(int argc, char **argv, printf("HyperScale Boot Version Spec: %d.%d\n", boot_spec_major, boot_spec_minor); printf("TCG Device Ownership Status: %2d\n", tcg_dev_ownership); - } - else if (fmt == JSON) { - root = json_create_object(); + } else if (fmt == JSON) { + root = json_create_object(); json_object_add_value_int(root, "Drive HW Revison", major_rev); json_object_add_value_int(root, "FTL Unit Size", ftl_unit_size); - sprintf(rev_str, "%d.%d", boot_spec_major, boot_spec_minor); + sprintf(rev_str, "%d.%d", boot_spec_major, boot_spec_minor); json_object_add_value_string(root, "HyperScale Boot Version Spec", rev_str); json_object_add_value_int(root, "TCG Device Ownership Status", tcg_dev_ownership); @@ -10504,12 +10612,12 @@ static int wdc_vs_drive_info(int argc, char **argv, break; default: - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; break; } } else { - fprintf(stderr, "ERROR : WDC: capability not supported by this device\n"); + fprintf(stderr, "ERROR: WDC: capability not supported by this device\n"); ret = -1; } @@ -10529,7 +10637,7 @@ static int wdc_vs_temperature_stats(int argc, char **argv, struct nvme_dev *dev; nvme_root_t r; uint64_t capabilities = 0; - __u32 hctm_tmt; + __u32 hctm_tmt; int temperature, temp_tmt1, temp_tmt2; int ret, fmt = -1; @@ -10553,7 +10661,7 @@ static int wdc_vs_temperature_stats(int argc, char **argv, r = nvme_scan(NULL); fmt = validate_output_format(cfg.output_format); if (fmt < 0) { - fprintf(stderr, "ERROR : WDC : invalid output format\n"); + fprintf(stderr, "ERROR: WDC: invalid output format\n"); ret = fmt; goto out; } @@ -10562,18 +10670,18 @@ static int wdc_vs_temperature_stats(int argc, char **argv, wdc_check_device(r, dev); capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_TEMP_STATS) != WDC_DRIVE_CAP_TEMP_STATS) { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); ret = -1; goto out; - } + } - /* get the temperature stats or report errors */ + /* get the temperature stats or report errors */ ret = nvme_identify_ctrl(dev_fd(dev), &id_ctrl); - if (ret != 0) + if (ret) goto out; ret = nvme_get_log_smart(dev_fd(dev), NVME_NSID_ALL, false, &smart_log); - if (ret != 0) + if (ret) goto out; /* convert from kelvins to degrees Celsius */ @@ -10581,10 +10689,10 @@ static int wdc_vs_temperature_stats(int argc, char **argv, /* retrieve HCTM Thermal Management Temperatures */ nvme_get_features_simple(dev_fd(dev), 0x10, 0, &hctm_tmt); - temp_tmt1 = ((hctm_tmt >> 16) & 0xffff) ? ((hctm_tmt >> 16) & 0xffff) - 273 : 0; - temp_tmt2 = (hctm_tmt & 0xffff) ? (hctm_tmt & 0xffff) - 273 : 0; + temp_tmt1 = ((hctm_tmt >> 16) & 0xffff) ? ((hctm_tmt >> 16) & 0xffff) - 273 : 0; + temp_tmt2 = (hctm_tmt & 0xffff) ? (hctm_tmt & 0xffff) - 273 : 0; - if (fmt == NORMAL) { + if (fmt == NORMAL) { /* print the temperature stats */ printf("Temperature Stats for NVME device:%s namespace-id:%x\n", dev->name, WDC_DE_GLOBAL_NSID); @@ -10603,10 +10711,10 @@ static int wdc_vs_temperature_stats(int argc, char **argv, printf("TMT2 Transition Counter : %"PRIu32"\n", smart_log.thm_temp2_trans_count); printf("TMT2 Total Time : %"PRIu32"\n", smart_log.thm_temp2_total_time); printf("Thermal Shutdown Threshold : 95 °C\n"); - } - else if (fmt == JSON) { - struct json_object *root; - root = json_create_object(); + } else if (fmt == JSON) { + struct json_object *root; + + root = json_create_object(); json_object_add_value_int(root, "Current Composite Temperature", le32_to_cpu(temperature)); json_object_add_value_int(root, "WCTEMP", le16_to_cpu(id_ctrl.wctemp - 273)); @@ -10627,9 +10735,9 @@ static int wdc_vs_temperature_stats(int argc, char **argv, printf("\n"); json_free_object(root); - } - else - printf("%s: Invalid format\n", __func__); + } else { + printf("%s: Invalid format\n", __func__); + } out: nvme_show_status(ret); @@ -10638,114 +10746,112 @@ out: return ret; } -static int wdc_capabilities(int argc, char **argv, - struct command *command, struct plugin *plugin) -{ - const char *desc = "Send a capabilities command."; - uint64_t capabilities = 0; - struct nvme_dev *dev; - nvme_root_t r; - int ret; - - OPT_ARGS(opts) = - { - OPT_END() - }; - - ret = parse_and_open(&dev, argc, argv, desc, opts); - if (ret) - return ret; - - /* get capabilities */ - r = nvme_scan(NULL); - wdc_check_device(r, dev); - capabilities = wdc_get_drive_capabilities(r, dev); - - /* print command and supported status */ - printf("WDC Plugin Capabilities for NVME device:%s\n", dev->name); - printf("cap-diag : %s\n", - capabilities & WDC_DRIVE_CAP_CAP_DIAG ? "Supported" : "Not Supported"); - printf("drive-log : %s\n", - capabilities & WDC_DRIVE_CAP_DRIVE_LOG ? "Supported" : "Not Supported"); - printf("get-crash-dump : %s\n", - capabilities & WDC_DRIVE_CAP_CRASH_DUMP ? "Supported" : "Not Supported"); - printf("get-pfail-dump : %s\n", - capabilities & WDC_DRIVE_CAP_PFAIL_DUMP ? "Supported" : "Not Supported"); - printf("id-ctrl : Supported\n"); - printf("purge : %s\n", - capabilities & WDC_DRIVE_CAP_PURGE ? "Supported" : "Not Supported"); - printf("purge-monitor : %s\n", - capabilities & WDC_DRIVE_CAP_PURGE ? "Supported" : "Not Supported"); - printf("vs-internal-log : %s\n", - capabilities & WDC_DRIVE_CAP_INTERNAL_LOG_MASK ? "Supported" : "Not Supported"); - printf("vs-nand-stats : %s\n", - capabilities & WDC_DRIVE_CAP_NAND_STATS ? "Supported" : "Not Supported"); - printf("vs-smart-add-log : %s\n", - capabilities & WDC_DRIVE_CAP_SMART_LOG_MASK ? "Supported" : "Not Supported"); - printf("--C0 Log Page : %s\n", - capabilities & WDC_DRIVE_CAP_C0_LOG_PAGE ? "Supported" : "Not Supported"); - printf("--C1 Log Page : %s\n", - capabilities & WDC_DRIVE_CAP_C1_LOG_PAGE ? "Supported" : "Not Supported"); - printf("--C3 Log Page : %s\n", - capabilities & WDC_DRIVE_CAP_C3_LOG_PAGE ? "Supported" : "Not Supported"); - printf("--CA Log Page : %s\n", - capabilities & WDC_DRIVE_CAP_CA_LOG_PAGE ? "Supported" : "Not Supported"); - printf("--D0 Log Page : %s\n", - capabilities & WDC_DRIVE_CAP_D0_LOG_PAGE ? "Supported" : "Not Supported"); - printf("clear-pcie-correctable-errors : %s\n", - capabilities & WDC_DRIVE_CAP_CLEAR_PCIE_MASK ? "Supported" : "Not Supported"); - printf("drive-essentials : %s\n", - capabilities & WDC_DRIVE_CAP_DRIVE_ESSENTIALS ? "Supported" : "Not Supported"); - printf("get-drive-status : %s\n", - capabilities & WDC_DRIVE_CAP_DRIVE_STATUS ? "Supported" : "Not Supported"); - printf("clear-assert-dump : %s\n", - capabilities & WDC_DRIVE_CAP_CLEAR_ASSERT ? "Supported" : "Not Supported"); - printf("drive-resize : %s\n", - capabilities & WDC_DRIVE_CAP_RESIZE ? "Supported" : "Not Supported"); - printf("vs-fw-activate-history : %s\n", - capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_MASK ? "Supported" : "Not Supported"); - printf("clear-fw-activate-history : %s\n", - capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY_MASK ? "Supported" : "Not Supported"); - printf("vs-telemetry-controller-option: %s\n", - capabilities & WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG ? "Supported" : "Not Supported"); - printf("vs-error-reason-identifier : %s\n", - capabilities & WDC_DRIVE_CAP_REASON_ID ? "Supported" : "Not Supported"); - printf("log-page-directory : %s\n", - capabilities & WDC_DRIVE_CAP_LOG_PAGE_DIR ? "Supported" : "Not Supported"); - printf("namespace-resize : %s\n", - capabilities & WDC_DRIVE_CAP_NS_RESIZE ? "Supported" : "Not Supported"); - printf("vs-drive-info : %s\n", - capabilities & WDC_DRIVE_CAP_INFO ? "Supported" : "Not Supported"); - printf("vs-temperature-stats : %s\n", - capabilities & WDC_DRIVE_CAP_TEMP_STATS ? "Supported" : "Not Supported"); - printf("cloud-SSD-plugin-version : %s\n", - capabilities & WDC_DRIVE_CAP_CLOUD_SSD_VERSION ? "Supported" : "Not Supported"); - printf("vs-pcie-stats : %s\n", - capabilities & WDC_DRIVE_CAP_PCIE_STATS ? "Supported" : "Not Supported"); - printf("get-error-recovery-log : %s\n", - capabilities & WDC_DRIVE_CAP_OCP_C1_LOG_PAGE ? "Supported" : "Not Supported"); - printf("get-dev-capabilities-log : %s\n", - capabilities & WDC_DRIVE_CAP_OCP_C4_LOG_PAGE ? "Supported" : "Not Supported"); - printf("get-unsupported-reqs-log : %s\n", - capabilities & WDC_DRIVE_CAP_OCP_C5_LOG_PAGE ? "Supported" : "Not Supported"); - printf("get-latency-monitor-log : %s\n", - capabilities & WDC_DRIVE_CAP_C3_LOG_PAGE ? "Supported" : "Not Supported"); - printf("cloud-boot-SSD-version : %s\n", - capabilities & WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION ? "Supported" : "Not Supported"); - printf("vs-cloud-log : %s\n", - capabilities & WDC_DRIVE_CAP_CLOUD_LOG_PAGE ? "Supported" : "Not Supported"); - printf("vs-hw-rev-log : %s\n", - capabilities & WDC_DRIVE_CAP_HW_REV_LOG_PAGE ? "Supported" : "Not Supported"); - printf("vs-device_waf : %s\n", - capabilities & WDC_DRIVE_CAP_DEVICE_WAF ? "Supported" : "Not Supported"); - printf("capabilities : Supported\n"); - nvme_free_tree(r); - dev_close(dev); - return 0; -} - -static int wdc_cloud_ssd_plugin_version(int argc, char **argv, - struct command *command, struct plugin *plugin) +static int wdc_capabilities(int argc, char **argv, struct command *command, struct plugin *plugin) +{ + const char *desc = "Send a capabilities command."; + uint64_t capabilities = 0; + struct nvme_dev *dev; + nvme_root_t r; + int ret; + + OPT_ARGS(opts) = { + OPT_END() + }; + + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; + + /* get capabilities */ + r = nvme_scan(NULL); + wdc_check_device(r, dev); + capabilities = wdc_get_drive_capabilities(r, dev); + + /* print command and supported status */ + printf("WDC Plugin Capabilities for NVME device:%s\n", dev->name); + printf("cap-diag : %s\n", + capabilities & WDC_DRIVE_CAP_CAP_DIAG ? "Supported" : "Not Supported"); + printf("drive-log : %s\n", + capabilities & WDC_DRIVE_CAP_DRIVE_LOG ? "Supported" : "Not Supported"); + printf("get-crash-dump : %s\n", + capabilities & WDC_DRIVE_CAP_CRASH_DUMP ? "Supported" : "Not Supported"); + printf("get-pfail-dump : %s\n", + capabilities & WDC_DRIVE_CAP_PFAIL_DUMP ? "Supported" : "Not Supported"); + printf("id-ctrl : Supported\n"); + printf("purge : %s\n", + capabilities & WDC_DRIVE_CAP_PURGE ? "Supported" : "Not Supported"); + printf("purge-monitor : %s\n", + capabilities & WDC_DRIVE_CAP_PURGE ? "Supported" : "Not Supported"); + printf("vs-internal-log : %s\n", + capabilities & WDC_DRIVE_CAP_INTERNAL_LOG_MASK ? "Supported" : "Not Supported"); + printf("vs-nand-stats : %s\n", + capabilities & WDC_DRIVE_CAP_NAND_STATS ? "Supported" : "Not Supported"); + printf("vs-smart-add-log : %s\n", + capabilities & WDC_DRIVE_CAP_SMART_LOG_MASK ? "Supported" : "Not Supported"); + printf("--C0 Log Page : %s\n", + capabilities & WDC_DRIVE_CAP_C0_LOG_PAGE ? "Supported" : "Not Supported"); + printf("--C1 Log Page : %s\n", + capabilities & WDC_DRIVE_CAP_C1_LOG_PAGE ? "Supported" : "Not Supported"); + printf("--C3 Log Page : %s\n", + capabilities & WDC_DRIVE_CAP_C3_LOG_PAGE ? "Supported" : "Not Supported"); + printf("--CA Log Page : %s\n", + capabilities & WDC_DRIVE_CAP_CA_LOG_PAGE ? "Supported" : "Not Supported"); + printf("--D0 Log Page : %s\n", + capabilities & WDC_DRIVE_CAP_D0_LOG_PAGE ? "Supported" : "Not Supported"); + printf("clear-pcie-correctable-errors : %s\n", + capabilities & WDC_DRIVE_CAP_CLEAR_PCIE_MASK ? "Supported" : "Not Supported"); + printf("drive-essentials : %s\n", + capabilities & WDC_DRIVE_CAP_DRIVE_ESSENTIALS ? "Supported" : "Not Supported"); + printf("get-drive-status : %s\n", + capabilities & WDC_DRIVE_CAP_DRIVE_STATUS ? "Supported" : "Not Supported"); + printf("clear-assert-dump : %s\n", + capabilities & WDC_DRIVE_CAP_CLEAR_ASSERT ? "Supported" : "Not Supported"); + printf("drive-resize : %s\n", + capabilities & WDC_DRIVE_CAP_RESIZE ? "Supported" : "Not Supported"); + printf("vs-fw-activate-history : %s\n", + capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_MASK ? "Supported" : "Not Supported"); + printf("clear-fw-activate-history : %s\n", + capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY_MASK ? "Supported" : "Not Supported"); + printf("vs-telemetry-controller-option: %s\n", + capabilities & WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG ? "Supported" : "Not Supported"); + printf("vs-error-reason-identifier : %s\n", + capabilities & WDC_DRIVE_CAP_REASON_ID ? "Supported" : "Not Supported"); + printf("log-page-directory : %s\n", + capabilities & WDC_DRIVE_CAP_LOG_PAGE_DIR ? "Supported" : "Not Supported"); + printf("namespace-resize : %s\n", + capabilities & WDC_DRIVE_CAP_NS_RESIZE ? "Supported" : "Not Supported"); + printf("vs-drive-info : %s\n", + capabilities & WDC_DRIVE_CAP_INFO ? "Supported" : "Not Supported"); + printf("vs-temperature-stats : %s\n", + capabilities & WDC_DRIVE_CAP_TEMP_STATS ? "Supported" : "Not Supported"); + printf("cloud-SSD-plugin-version : %s\n", + capabilities & WDC_DRIVE_CAP_CLOUD_SSD_VERSION ? "Supported" : "Not Supported"); + printf("vs-pcie-stats : %s\n", + capabilities & WDC_DRIVE_CAP_PCIE_STATS ? "Supported" : "Not Supported"); + printf("get-error-recovery-log : %s\n", + capabilities & WDC_DRIVE_CAP_OCP_C1_LOG_PAGE ? "Supported" : "Not Supported"); + printf("get-dev-capabilities-log : %s\n", + capabilities & WDC_DRIVE_CAP_OCP_C4_LOG_PAGE ? "Supported" : "Not Supported"); + printf("get-unsupported-reqs-log : %s\n", + capabilities & WDC_DRIVE_CAP_OCP_C5_LOG_PAGE ? "Supported" : "Not Supported"); + printf("get-latency-monitor-log : %s\n", + capabilities & WDC_DRIVE_CAP_C3_LOG_PAGE ? "Supported" : "Not Supported"); + printf("cloud-boot-SSD-version : %s\n", + capabilities & WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION ? "Supported" : "Not Supported"); + printf("vs-cloud-log : %s\n", + capabilities & WDC_DRIVE_CAP_CLOUD_LOG_PAGE ? "Supported" : "Not Supported"); + printf("vs-hw-rev-log : %s\n", + capabilities & WDC_DRIVE_CAP_HW_REV_LOG_PAGE ? "Supported" : "Not Supported"); + printf("vs-device_waf : %s\n", + capabilities & WDC_DRIVE_CAP_DEVICE_WAF ? "Supported" : "Not Supported"); + printf("capabilities : Supported\n"); + nvme_free_tree(r); + dev_close(dev); + return 0; +} + +static int wdc_cloud_ssd_plugin_version(int argc, char **argv, struct command *command, + struct plugin *plugin) { const char *desc = "Get Cloud SSD Plugin Version command."; uint64_t capabilities = 0; @@ -10767,10 +10873,10 @@ static int wdc_cloud_ssd_plugin_version(int argc, char **argv, capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_CLOUD_SSD_VERSION) == WDC_DRIVE_CAP_CLOUD_SSD_VERSION) { - /* print command and supported status */ - printf("WDC Cloud SSD Plugin Version: 1.0\n"); + /* print command and supported status */ + printf("WDC Cloud SSD Plugin Version: 1.0\n"); } else { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); } nvme_free_tree(r); @@ -10778,8 +10884,8 @@ static int wdc_cloud_ssd_plugin_version(int argc, char **argv, return 0; } -static int wdc_cloud_boot_SSD_version(int argc, char **argv, - struct command *command, struct plugin *plugin) +static int wdc_cloud_boot_SSD_version(int argc, char **argv, struct command *command, + struct plugin *plugin) { const char *desc = "Get Cloud Boot SSD Version command."; const char *namespace_id = "desired namespace id"; @@ -10789,7 +10895,7 @@ static int wdc_cloud_boot_SSD_version(int argc, char **argv, int ret; int major = 0, minor = 0; __u8 *data = NULL; - wdc_nvme_ext_smart_log *ext_smart_log_ptr = NULL; + struct __packed wdc_nvme_ext_smart_log * ext_smart_log_ptr = NULL; struct config { __u32 namespace_id; @@ -10818,23 +10924,22 @@ static int wdc_cloud_boot_SSD_version(int argc, char **argv, ret = nvme_get_ext_smart_cloud_log(dev_fd(dev), &data, 0, cfg.namespace_id); - ext_smart_log_ptr = (wdc_nvme_ext_smart_log *)data; - if (ret == 0) { + ext_smart_log_ptr = (struct __packed wdc_nvme_ext_smart_log *)data; + if (!ret) { major = le16_to_cpu(ext_smart_log_ptr->ext_smart_maj); minor = le16_to_cpu(ext_smart_log_ptr->ext_smart_min); - /* print the version returned from the log page */ - printf("HyperScale Boot Version: %d.%d\n", major, minor); - + /* print the version returned from the log page */ + printf("HyperScale Boot Version: %d.%d\n", major, minor); } else { - fprintf(stderr, "ERROR : WDC : Unable to read Extended Smart/C0 Log Page data\n"); + fprintf(stderr, "ERROR: WDC: Unable to read Extended Smart/C0 Log Page data\n"); ret = -1; } if (data) free(data); } else { - fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + fprintf(stderr, "ERROR: WDC: unsupported device for this command\n"); } nvme_free_tree(r); @@ -10842,8 +10947,7 @@ static int wdc_cloud_boot_SSD_version(int argc, char **argv, return ret; } -static int wdc_enc_get_log(int argc, char **argv, struct command *command, - struct plugin *plugin) +static int wdc_enc_get_log(int argc, char **argv, struct command *command, struct plugin *plugin) { char *desc = "Get Enclosure Log."; char *file = "Output file pathname."; @@ -10884,14 +10988,17 @@ static int wdc_enc_get_log(int argc, char **argv, struct command *command, } if (cfg.log_id > 0xff) { - fprintf(stderr, "Invalid log identifier: %d. Valid 0xd1, 0xd2, 0xd3, 0xd4, 0xe2, 0xe4\n", cfg.log_id); + fprintf(stderr, + "Invalid log identifier: %d. Valid 0xd1, 0xd2, 0xd3, 0xd4, 0xe2, 0xe4\n", + cfg.log_id); goto closed_fd; } - if (cfg.xfer_size != 0) { + if (cfg.xfer_size) { xfer_size = cfg.xfer_size; if (!wdc_check_power_of_2(cfg.xfer_size)) { - fprintf(stderr, "%s: ERROR : xfer-size (%d) must be a power of 2\n", __func__, cfg.xfer_size); + fprintf(stderr, "%s: ERROR: xfer-size (%d) must be a power of 2\n", + __func__, cfg.xfer_size); err = -EINVAL; goto closed_fd; } @@ -10900,28 +11007,30 @@ static int wdc_enc_get_log(int argc, char **argv, struct command *command, /* Log IDs are only for specific enclosures */ if (cfg.log_id) { xfer_size = (xfer_size) ? xfer_size : WDC_NVME_ENC_LOG_SIZE_CHUNK; - len = cfg.file==NULL?0:strlen(cfg.file); + len = !cfg.file ? 0 : strlen(cfg.file); if (len > 0) { - output_fd = fopen(cfg.file,"wb"); - if (output_fd == 0) { - fprintf(stderr, "%s: ERROR : opening:%s : %s\n", __func__,cfg.file, strerror(errno)); + output_fd = fopen(cfg.file, "wb"); + if (!output_fd) { + fprintf(stderr, "%s: ERROR: opening:%s: %s\n", __func__, cfg.file, + strerror(errno)); err = -EINVAL; goto closed_fd; } } else { output_fd = stdout; } - if (cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_1 || cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_2 - || cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_3 || cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_4) { - fprintf(stderr, "args - sz:%x logid:%x of:%s\n",xfer_size,cfg.log_id,cfg.file); - err = wdc_enc_get_nic_log(dev, cfg.log_id, - xfer_size, - WDC_NVME_ENC_NIC_LOG_SIZE, - output_fd); + if (cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_1 || + cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_2 || + cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_3 || + cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_4) { + fprintf(stderr, "args - sz:%x logid:%x of:%s\n", xfer_size, cfg.log_id, + cfg.file); + err = wdc_enc_get_nic_log(dev, cfg.log_id, xfer_size, + WDC_NVME_ENC_NIC_LOG_SIZE, output_fd); } else { - fprintf(stderr, "args - sz:%x logid:%x of:%s\n",xfer_size,cfg.log_id,cfg.file); - err = wdc_enc_submit_move_data(dev, NULL, 0, - xfer_size, output_fd, + fprintf(stderr, "args - sz:%x logid:%x of:%s\n", xfer_size, cfg.log_id, + cfg.file); + err = wdc_enc_submit_move_data(dev, NULL, 0, xfer_size, output_fd, cfg.log_id, 0, 0); } @@ -10929,7 +11038,8 @@ static int wdc_enc_get_log(int argc, char **argv, struct command *command, fprintf(stderr, "No Log/Crashdump available\n"); err = 0; } else if (err) { - fprintf(stderr, "ERROR:0x%x Failed to collect log-id:%x \n",err, cfg.log_id); + fprintf(stderr, "ERROR: 0x%x Failed to collect log-id:%x\n", err, + cfg.log_id); } } closed_fd: @@ -10950,8 +11060,8 @@ static int wdc_enc_submit_move_data(struct nvme_dev *dev, char *cmd, int len, char *buf; buf = (char *)malloc(sizeof(__u8) * xfer_size); - if (buf == NULL) { - fprintf(stderr, "%s: ERROR : malloc : %s\n", __func__, strerror(errno)); + if (!buf) { + fprintf(stderr, "%s: ERROR: malloc: %s\n", __func__, strerror(errno)); return -1; } /* send something no matter what */ @@ -10962,7 +11072,7 @@ static int wdc_enc_submit_move_data(struct nvme_dev *dev, char *cmd, int len, .opcode = WDC_NVME_ADMIN_ENC_MGMT_SND, .nsid = 0, .addr = (__u64)(uintptr_t) cmd, - .data_len = ((len + sizeof(uint32_t) - 1)/sizeof(uint32_t)) * sizeof(uint32_t), + .data_len = ((len + sizeof(uint32_t) - 1) / sizeof(uint32_t)) * sizeof(uint32_t), .cdw10 = len, .cdw12 = log_id, .cdw13 = 0, @@ -10972,36 +11082,32 @@ static int wdc_enc_submit_move_data(struct nvme_dev *dev, char *cmd, int len, clock_gettime(CLOCK_REALTIME, &time); srand(time.tv_nsec); - handle = random(); /* Handle to associate send request with receive request */ + handle = random(); /* Handle to associate send request with receive request */ nvme_cmd.cdw11 = handle; #ifdef WDC_NVME_CLI_DEBUG - unsigned char *d = (unsigned char*) nvme_cmd.addr; - unsigned char *md = (unsigned char*) nvme_cmd.metadata; - printf("NVME_ADMIN_COMMAND:\n" \ - "opcode: 0x%02x, flags: 0x%02x, rsvd: 0x%04x, nsid: 0x%08x, cdw2: 0x%08x, cdw3: 0x%08x, " \ - "metadata_len: 0x%08x, data_len: 0x%08x, cdw10: 0x%08x, cdw11: 0x%08x, cdw12: 0x%08x, " \ - "cdw13: 0x%08x, cdw14: 0x%08x, cdw15: 0x%08x, timeout_ms: 0x%08x, result: 0x%08x, " \ - "metadata: %s, " \ - "data: %s\n", \ - nvme_cmd.opcode, nvme_cmd.flags, nvme_cmd.rsvd1, nvme_cmd.nsid, nvme_cmd.cdw2, nvme_cmd.cdw3, \ - nvme_cmd.metadata_len, nvme_cmd.data_len, nvme_cmd.cdw10, nvme_cmd.cdw11, nvme_cmd.cdw12, \ - nvme_cmd.cdw13, nvme_cmd.cdw14, nvme_cmd.cdw15, nvme_cmd.timeout_ms, nvme_cmd.result, - md, \ - d); + unsigned char *d = (unsigned char *)nvme_cmd.addr; + unsigned char *md = (unsigned char *)nvme_cmd.metadata; + + printf("NVME_ADMIN_COMMAND:\n"); + printf("opcode: 0x%02x, flags: 0x%02x, rsvd: 0x%04x, nsid: 0x%08x, cdw2: 0x%08x, ", + nvme_cmd.opcode, nvme_cmd.flags, nvme_cmd.rsvd1, nvme_cmd.nsid, nvme_cmd.cdw2); + printf("cdw3: 0x%08x, metadata_len: 0x%08x, data_len: 0x%08x, cdw10: 0x%08x, " + nvme_cmd.cdw3, nvme_cmd.metadata_len, nvme_cmd.data_len, nvme_cmd.cdw10); + printf("cdw11: 0x%08x, cdw12: 0x%08x, cdw13: 0x%08x, cdw14: 0x%08x, cdw15: 0x%08x, " + nvme_cmd.cdw11, nvme_cmd.cdw12, nvme_cmd.cdw13, nvme_cmd.cdw14, nvme_cmd.cdw15); + printf("timeout_ms: 0x%08x, result: 0x%08x, metadata: %s, data: %s\n", + nvme_cmd.timeout_ms, nvme_cmd.result, md, d); #endif nvme_cmd.result = 0; err = nvme_submit_admin_passthru(dev_fd(dev), &nvme_cmd, NULL); if (nvme_status_equals(err, NVME_STATUS_TYPE_NVME, NVME_SC_INTERNAL)) { - fprintf(stderr, "%s: WARNING : WDC : No log ID:x%x available\n", - __func__, log_id); - } - else if (err != 0) { - fprintf(stderr, "%s: ERROR : WDC : NVMe Snd Mgmt\n", __func__); + fprintf(stderr, "%s: WARNING : WDC: No log ID:x%x available\n", __func__, log_id); + } else if (err) { + fprintf(stderr, "%s: ERROR: WDC: NVMe Snd Mgmt\n", __func__); nvme_show_status(err); } else { - if (nvme_cmd.result == WDC_RESULT_NOT_AVAILABLE) - { + if (nvme_cmd.result == WDC_RESULT_NOT_AVAILABLE) { free(buf); return WDC_RESULT_NOT_AVAILABLE; } @@ -11021,9 +11127,9 @@ static int wdc_enc_submit_move_data(struct nvme_dev *dev, char *cmd, int len, nvme_cmd.result = 0; /* returned result !=0 indicates more data available */ err = nvme_submit_admin_passthru(dev_fd(dev), &nvme_cmd, NULL); - if (err != 0) { + if (err) { more = 0; - fprintf(stderr, "%s: ERROR : WDC : NVMe Rcv Mgmt ", __func__); + fprintf(stderr, "%s: ERROR: WDC: NVMe Rcv Mgmt ", __func__); nvme_show_status(err); } else { more = nvme_cmd.result & WDC_RESULT_MORE_DATA; @@ -11031,7 +11137,7 @@ static int wdc_enc_submit_move_data(struct nvme_dev *dev, char *cmd, int len, fwrite(buf, response_size, 1, out); offset += response_size; if (more && (response_size & (sizeof(uint32_t)-1))) { - fprintf(stderr, "%s: ERROR : WDC : NVMe Rcv Mgmt response size:x%x not LW aligned\n", + fprintf(stderr, "%s: ERROR: WDC: NVMe Rcv Mgmt response size:x%x not LW aligned\n", __func__, response_size); } } @@ -11052,13 +11158,13 @@ static int wdc_enc_get_nic_log(struct nvme_dev *dev, __u8 log_id, __u32 xfer_siz __u32 numd; __u16 numdu, numdl; - dump_data = (__u8 *) malloc(sizeof (__u8) * dump_length); - if (dump_data == NULL) { - fprintf(stderr, "%s: ERROR : malloc : %s\n",__func__, strerror(errno)); + dump_data = (__u8 *)malloc(sizeof(__u8) * dump_length); + if (!dump_data) { + fprintf(stderr, "%s: ERROR: malloc: %s\n", __func__, strerror(errno)); return -1; } - memset(dump_data, 0, sizeof (__u8) * dump_length); - memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); + memset(dump_data, 0, sizeof(__u8) * dump_length); + memset(&admin_cmd, 0, sizeof(struct nvme_passthru_cmd)); curr_data_offset = 0; curr_data_len = xfer_size; i = 0; @@ -11075,14 +11181,16 @@ static int wdc_enc_get_nic_log(struct nvme_dev *dev, __u8 log_id, __u32 xfer_siz while (curr_data_offset < data_len) { #ifdef WDC_NVME_CLI_DEBUG - fprintf(stderr, "nsid 0x%08x addr 0x%08llx, data_len 0x%08x, cdw10 0x%08x, cdw11 0x%08x, cdw12 0x%08x, cdw13 0x%08x, cdw14 0x%08x \n", admin_cmd.nsid, admin_cmd.addr, admin_cmd.data_len, admin_cmd.cdw10, admin_cmd.cdw11, admin_cmd.cdw12, admin_cmd.cdw13, admin_cmd.cdw14); + fprintf(stderr, + "nsid 0x%08x addr 0x%08llx, data_len 0x%08x, cdw10 0x%08x, cdw11 0x%08x, cdw12 0x%08x, cdw13 0x%08x, cdw14 0x%08x\n", + admin_cmd.nsid, admin_cmd.addr, admin_cmd.data_len, admin_cmd.cdw10, + admin_cmd.cdw11, admin_cmd.cdw12, admin_cmd.cdw13, admin_cmd.cdw14); #endif - ret = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, - NULL); - if (ret != 0) { + ret = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); + if (ret) { nvme_show_status(ret); - fprintf(stderr, "%s: ERROR : WDC : Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx\n", - __func__, i, admin_cmd.data_len, curr_data_offset, (long unsigned int)admin_cmd.addr); + fprintf(stderr, "%s: ERROR: WDC: Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx\n", + __func__, i, admin_cmd.data_len, curr_data_offset, (unsigned long)admin_cmd.addr); break; } diff --git a/plugins/wdc/wdc-utils.c b/plugins/wdc/wdc-utils.c index 38e61ed..3b60772 100644 --- a/plugins/wdc/wdc-utils.c +++ b/plugins/wdc/wdc-utils.c @@ -38,7 +38,7 @@ int wdc_UtilsSnprintf(char *buffer, unsigned int sizeOfBuffer, const char *forma return res; } -void wdc_UtilsDeleteCharFromString(char* buffer, int buffSize, char charToRemove) +void wdc_UtilsDeleteCharFromString(char *buffer, int buffSize, char charToRemove) { int i = 0; int count = 0; @@ -62,7 +62,7 @@ int wdc_UtilsGetTime(PUtilsTimeInfo timeInfo) time_t currTime; struct tm currTimeInfo; - if(!timeInfo) + if (!timeInfo) return WDC_STATUS_INVALID_PARAMETER; tzset(); @@ -81,7 +81,7 @@ int wdc_UtilsGetTime(PUtilsTimeInfo timeInfo) #if defined(__GLIBC__) && !defined(__UCLIBC__) && !defined(__MUSL__) timeInfo->zone = -currTimeInfo.tm_gmtoff / 60; #else - timeInfo->zone = -1 * (timezone / SECONDS_IN_MIN); + timeInfo->zone = -1 * (timezone / SECONDS_IN_MIN); #endif return WDC_STATUS_SUCCESS; @@ -92,7 +92,7 @@ int wdc_UtilsCreateDir(char *path) int retStatus; int status = WDC_STATUS_SUCCESS; - if (!path ) + if (!path) return WDC_STATUS_INVALID_PARAMETER; retStatus = mkdir(path, 0x999); @@ -125,7 +125,7 @@ int wdc_WriteToFile(char *fileName, char *buffer, unsigned int bufferLen) status = WDC_STATUS_UNABLE_TO_WRITE_ALL_DATA; end: - if(file) + if (file) fclose(file); return status; } @@ -151,9 +151,7 @@ int wdc_UtilsStrCompare(char *pcSrc, char *pcDst) void wdc_StrFormat(char *formatter, size_t fmt_sz, char *tofmt, size_t tofmtsz) { - - fmt_sz = snprintf(formatter,fmt_sz, "%-*.*s", - (int)tofmtsz, (int)tofmtsz, tofmt); + fmt_sz = snprintf(formatter, fmt_sz, "%-*.*s", (int)tofmtsz, (int)tofmtsz, tofmt); /* trim() the obnoxious trailing white lines */ while (fmt_sz) { if (formatter[fmt_sz - 1] != ' ' && formatter[fmt_sz - 1] != '\0') { diff --git a/plugins/ymtc/ymtc-nvme.c b/plugins/ymtc/ymtc-nvme.c index d04481c..1f99a64 100644 --- a/plugins/ymtc/ymtc-nvme.c +++ b/plugins/ymtc/ymtc-nvme.c @@ -17,145 +17,145 @@ static void get_ymtc_smart_info(struct nvme_ymtc_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); + memcpy(nm_val, smart->itemArr[index].nmVal, NM_SIZE); + memcpy(raw_val, smart->itemArr[index].rawVal, RAW_SIZE); } static int show_ymtc_smart_log(struct nvme_dev *dev, __u32 nsid, struct nvme_ymtc_smart_log *smart) { - struct nvme_id_ctrl ctrl; - char fw_ver[10]; - int err = 0; - - u8 *nm = malloc(NM_SIZE * sizeof(u8)); - u8 *raw = malloc(RAW_SIZE * sizeof(u8)); - - if (!nm) { - if (raw) - free(raw); - return -1; - } - if (!raw) { - free(nm); - return -1; - } - err = nvme_identify_ctrl(dev_fd(dev), &ctrl); - if (err) { - free(nm); - free(raw); - return err; - } - - snprintf(fw_ver, sizeof(fw_ver), "%c.%c%c.%c%c%c%c", - ctrl.fr[0], ctrl.fr[1], ctrl.fr[2], ctrl.fr[3], - ctrl.fr[4], ctrl.fr[5], ctrl.fr[6]); - - /* Table Title */ - printf("Additional Smart Log for NVME device:%s namespace-id:%x\n", - dev->name, nsid); - /* Clumn Name*/ - printf("key normalized raw\n"); - /* 00 SI_VD_PROGRAM_FAIL */ - get_ymtc_smart_info(smart, SI_VD_PROGRAM_FAIL, nm, raw); - printf("program_fail_count : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw)); - /* 01 SI_VD_ERASE_FAIL */ - get_ymtc_smart_info(smart, SI_VD_ERASE_FAIL, nm, raw); - printf("erase_fail_count : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw)); - /* 02 SI_VD_WEARLEVELING_COUNT */ - get_ymtc_smart_info(smart, SI_VD_WEARLEVELING_COUNT, nm, raw); - printf("wear_leveling : %3d%% min: %u, max: %u, avg: %u\n", *nm, - *(uint16_t *)raw, *(uint16_t *)(raw+2), *(uint16_t *)(raw+4)); - /* 03 SI_VD_E2E_DECTECTION_COUNT */ - get_ymtc_smart_info(smart, SI_VD_E2E_DECTECTION_COUNT, nm, raw); - printf("end_to_end_error_detection_count: %3d%% %"PRIu64"\n", *nm, int48_to_long(raw)); - /* 04 SI_VD_PCIE_CRC_ERR_COUNT */ - get_ymtc_smart_info(smart, SI_VD_PCIE_CRC_ERR_COUNT, nm, raw); - printf("crc_error_count : %3d%% %"PRIu32"\n", *nm, *(uint32_t *)raw); - /* 08 SI_VD_THERMAL_THROTTLE_STATUS */ - get_ymtc_smart_info(smart, SI_VD_THERMAL_THROTTLE_STATUS, nm, raw); - printf("thermal_throttle_status : %3d%% %d%%, cnt: %"PRIu32"\n", *nm, - *raw, *(uint32_t *)(raw+1)); - /* 11 SI_VD_TOTAL_WRITE */ - get_ymtc_smart_info(smart, SI_VD_TOTAL_WRITE, nm, raw); - printf("nand_bytes_written : %3d%% sectors: %"PRIu64"\n", *nm, int48_to_long(raw)); - /* 12 SI_VD_HOST_WRITE */ - get_ymtc_smart_info(smart, SI_VD_HOST_WRITE, nm, raw); - printf("host_bytes_written : %3d%% sectors: %"PRIu64"\n", *nm, int48_to_long(raw)); - /* 14 SI_VD_TOTAL_READ */ - get_ymtc_smart_info(smart, SI_VD_TOTAL_READ, nm, raw); - printf("nand_bytes_read : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw)); - /* 15 SI_VD_TEMPT_SINCE_BORN */ - get_ymtc_smart_info(smart, SI_VD_TEMPT_SINCE_BORN, nm, raw); - printf("tempt_since_born : %3d%% max: %u, min: %u, curr: %u\n", *nm, - *(uint16_t *)raw-273, *(uint16_t *)(raw+2)-273, *(int16_t *)(raw+4)-273); - /* 16 SI_VD_POWER_CONSUMPTION */ - get_ymtc_smart_info(smart, SI_VD_POWER_CONSUMPTION, nm, raw); - printf("power_consumption : %3d%% max: %u, min: %u, curr: %u\n", *nm, - *(uint16_t *)raw, *(uint16_t *)(raw+2), *(uint16_t *)(raw+4)); - /* 17 SI_VD_TEMPT_SINCE_BOOTUP */ - get_ymtc_smart_info(smart, SI_VD_TEMPT_SINCE_BOOTUP, nm, raw); - printf("tempt_since_bootup : %3d%% max: %u, min: %u, curr: %u\n", *nm, - *(uint16_t *)raw-273, *(uint16_t *)(raw+2)-273, *(uint16_t *)(raw+4)-273); - /* 18 SI_VD_POWER_LOSS_PROTECTION */ - get_ymtc_smart_info(smart, SI_VD_POWER_LOSS_PROTECTION, nm, raw); - printf("power_loss_protection : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw)); - /* 19 SI_VD_READ_FAIL */ - get_ymtc_smart_info(smart, SI_VD_READ_FAIL, nm, raw); - printf("read_fail : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw)); - /* 20 SI_VD_THERMAL_THROTTLE_TIME */ - get_ymtc_smart_info(smart, SI_VD_THERMAL_THROTTLE_TIME, nm, raw); - printf("thermal_throttle_time : %3d%% %u, time: %"PRIu32"\n", *nm, - *raw, *(uint32_t *)(raw+1)); - /* 21 SI_VD_FLASH_MEDIA_ERROR */ - get_ymtc_smart_info(smart, SI_VD_FLASH_MEDIA_ERROR, nm, raw); - printf("flash_error_media_count : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw)); - - free(nm); - free(raw); - - return err; + struct nvme_id_ctrl ctrl; + char fw_ver[10]; + int err = 0; + + u8 *nm = malloc(NM_SIZE * sizeof(u8)); + u8 *raw = malloc(RAW_SIZE * sizeof(u8)); + + if (!nm) { + if (raw) + free(raw); + return -1; + } + if (!raw) { + free(nm); + return -1; + } + err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + if (err) { + free(nm); + free(raw); + return err; + } + + snprintf(fw_ver, sizeof(fw_ver), "%c.%c%c.%c%c%c%c", + ctrl.fr[0], ctrl.fr[1], ctrl.fr[2], ctrl.fr[3], + ctrl.fr[4], ctrl.fr[5], ctrl.fr[6]); + + /* Table Title */ + printf("Additional Smart Log for NVME device:%s namespace-id:%x\n", + dev->name, nsid); + /* Clumn Name*/ + printf("key normalized raw\n"); + /* 00 SI_VD_PROGRAM_FAIL */ + get_ymtc_smart_info(smart, SI_VD_PROGRAM_FAIL, nm, raw); + printf("program_fail_count : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw)); + /* 01 SI_VD_ERASE_FAIL */ + get_ymtc_smart_info(smart, SI_VD_ERASE_FAIL, nm, raw); + printf("erase_fail_count : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw)); + /* 02 SI_VD_WEARLEVELING_COUNT */ + get_ymtc_smart_info(smart, SI_VD_WEARLEVELING_COUNT, nm, raw); + printf("wear_leveling : %3d%% min: %u, max: %u, avg: %u\n", *nm, + *(uint16_t *)raw, *(uint16_t *)(raw+2), *(uint16_t *)(raw+4)); + /* 03 SI_VD_E2E_DECTECTION_COUNT */ + get_ymtc_smart_info(smart, SI_VD_E2E_DECTECTION_COUNT, nm, raw); + printf("end_to_end_error_detection_count: %3d%% %"PRIu64"\n", *nm, int48_to_long(raw)); + /* 04 SI_VD_PCIE_CRC_ERR_COUNT */ + get_ymtc_smart_info(smart, SI_VD_PCIE_CRC_ERR_COUNT, nm, raw); + printf("crc_error_count : %3d%% %"PRIu32"\n", *nm, *(uint32_t *)raw); + /* 08 SI_VD_THERMAL_THROTTLE_STATUS */ + get_ymtc_smart_info(smart, SI_VD_THERMAL_THROTTLE_STATUS, nm, raw); + printf("thermal_throttle_status : %3d%% %d%%, cnt: %"PRIu32"\n", *nm, + *raw, *(uint32_t *)(raw+1)); + /* 11 SI_VD_TOTAL_WRITE */ + get_ymtc_smart_info(smart, SI_VD_TOTAL_WRITE, nm, raw); + printf("nand_bytes_written : %3d%% sectors: %"PRIu64"\n", *nm, int48_to_long(raw)); + /* 12 SI_VD_HOST_WRITE */ + get_ymtc_smart_info(smart, SI_VD_HOST_WRITE, nm, raw); + printf("host_bytes_written : %3d%% sectors: %"PRIu64"\n", *nm, int48_to_long(raw)); + /* 14 SI_VD_TOTAL_READ */ + get_ymtc_smart_info(smart, SI_VD_TOTAL_READ, nm, raw); + printf("nand_bytes_read : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw)); + /* 15 SI_VD_TEMPT_SINCE_BORN */ + get_ymtc_smart_info(smart, SI_VD_TEMPT_SINCE_BORN, nm, raw); + printf("tempt_since_born : %3d%% max: %u, min: %u, curr: %u\n", *nm, + *(uint16_t *)raw-273, *(uint16_t *)(raw+2)-273, *(int16_t *)(raw+4)-273); + /* 16 SI_VD_POWER_CONSUMPTION */ + get_ymtc_smart_info(smart, SI_VD_POWER_CONSUMPTION, nm, raw); + printf("power_consumption : %3d%% max: %u, min: %u, curr: %u\n", *nm, + *(uint16_t *)raw, *(uint16_t *)(raw+2), *(uint16_t *)(raw+4)); + /* 17 SI_VD_TEMPT_SINCE_BOOTUP */ + get_ymtc_smart_info(smart, SI_VD_TEMPT_SINCE_BOOTUP, nm, raw); + printf("tempt_since_bootup : %3d%% max: %u, min: %u, curr: %u\n", *nm, + *(uint16_t *)raw-273, *(uint16_t *)(raw+2)-273, *(uint16_t *)(raw+4)-273); + /* 18 SI_VD_POWER_LOSS_PROTECTION */ + get_ymtc_smart_info(smart, SI_VD_POWER_LOSS_PROTECTION, nm, raw); + printf("power_loss_protection : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw)); + /* 19 SI_VD_READ_FAIL */ + get_ymtc_smart_info(smart, SI_VD_READ_FAIL, nm, raw); + printf("read_fail : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw)); + /* 20 SI_VD_THERMAL_THROTTLE_TIME */ + get_ymtc_smart_info(smart, SI_VD_THERMAL_THROTTLE_TIME, nm, raw); + printf("thermal_throttle_time : %3d%% %u, time: %"PRIu32"\n", *nm, + *raw, *(uint32_t *)(raw+1)); + /* 21 SI_VD_FLASH_MEDIA_ERROR */ + get_ymtc_smart_info(smart, SI_VD_FLASH_MEDIA_ERROR, nm, raw); + printf("flash_error_media_count : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw)); + + free(nm); + free(raw); + + return err; } static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - struct nvme_ymtc_smart_log smart_log; - char *desc = "Get Ymtc vendor specific additional smart log (optionally, "\ - "for the specified namespace), and show it."; - const char *namespace = "(optional) desired namespace"; - const char *raw = "dump output in binary format"; - struct nvme_dev *dev; - struct config { - __u32 namespace_id; - bool raw_binary; - }; - int err; - - struct config cfg = { - .namespace_id = NVME_NSID_ALL, - }; - - OPT_ARGS(opts) = { - OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace), - 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 = nvme_get_nsid_log(dev_fd(dev), false, 0xca, cfg.namespace_id, - sizeof(smart_log), &smart_log); - if (!err) { - if (!cfg.raw_binary) - err = show_ymtc_smart_log(dev, cfg.namespace_id, &smart_log); - else - d_raw((unsigned char *)&smart_log, sizeof(smart_log)); - } - if (err > 0) - nvme_show_status(err); - - dev_close(dev); - return err; + struct nvme_ymtc_smart_log smart_log; + char *desc = + "Get Ymtc vendor specific additional smart log (optionally, for the specified namespace), and show it."; + const char *namespace = "(optional) desired namespace"; + const char *raw = "dump output in binary format"; + struct nvme_dev *dev; + struct config { + __u32 namespace_id; + bool raw_binary; + }; + int err; + + struct config cfg = { + .namespace_id = NVME_NSID_ALL, + }; + + OPT_ARGS(opts) = { + OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace), + 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 = nvme_get_nsid_log(dev_fd(dev), false, 0xca, cfg.namespace_id, + sizeof(smart_log), &smart_log); + if (!err) { + if (!cfg.raw_binary) + err = show_ymtc_smart_log(dev, cfg.namespace_id, &smart_log); + else + d_raw((unsigned char *)&smart_log, sizeof(smart_log)); + } + if (err > 0) + nvme_show_status(err); + + dev_close(dev); + return err; } diff --git a/plugins/zns/zns.c b/plugins/zns/zns.c index f8809ba..5b9d013 100644 --- a/plugins/zns/zns.c +++ b/plugins/zns/zns.c @@ -49,9 +49,8 @@ static int print_zns_list_ns(nvme_ns_t ns) return err; } - if (supported) { + if (supported) nvme_show_list_item(ns); - } return err; } @@ -63,21 +62,17 @@ static int print_zns_list(nvme_root_t nvme_root) nvme_subsystem_t s; nvme_ctrl_t c; nvme_ns_t n; - nvme_for_each_host(nvme_root, h) - { - nvme_for_each_subsystem(h, s) - { - nvme_subsystem_for_each_ns(s, n) - { + + nvme_for_each_host(nvme_root, h) { + nvme_for_each_subsystem(h, s) { + nvme_subsystem_for_each_ns(s, n) { err = print_zns_list_ns(n); if (err) return err; } - nvme_subsystem_for_each_ctrl(s, c) - { - nvme_ctrl_for_each_ns(c, n) - { + nvme_subsystem_for_each_ctrl(s, c) { + nvme_ctrl_for_each_ns(c, n) { err = print_zns_list_ns(n); if (err) return err; @@ -114,9 +109,9 @@ static int list(int argc, char **argv, struct command *cmd, static int id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Send an ZNS specific Identify Controller command to "\ - "the given device and report information about the specified "\ - "controller in various formats."; + const char *desc = "Send a ZNS specific Identify Controller command to\n" + "the given device and report information about the specified\n" + "controller in various formats."; enum nvme_print_flags flags; struct nvme_zns_id_ctrl ctrl; @@ -158,9 +153,9 @@ close_fd: static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Send an ZNS specific Identify Namespace command to "\ - "the given device and report information about the specified "\ - "namespace in varios formats."; + const char *desc = "Send a ZNS specific Identify Namespace command to\n" + "the given device and report information about the specified\n" + "namespace in varios formats."; const char *vendor_specific = "dump binary vendor fields"; const char *human_readable = "show identify in readable format"; @@ -292,11 +287,11 @@ static int zns_mgmt_send(int argc, char **argv, struct command *cmd, struct plug printf("%s: Success, action:%d zone:%"PRIx64" all:%d zcapc:%u nsid:%d\n", command, zsa, (uint64_t)cfg.zslba, (int)cfg.select_all, zcapc, cfg.namespace_id); - } - else if (err > 0) + } else if (err > 0) { nvme_show_status(err); - else + } else { perror(desc); + } free: free(command); close_dev: @@ -337,8 +332,8 @@ static int get_zdes_bytes(int fd, __u32 nsid) static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Zone Management Send"; - const char *zslba = "starting LBA of the zone for this command"\ - "(for flush action, last lba to flush)"; + const char *zslba = + "starting LBA of the zone for this command(for flush action, last lba to flush)"; const char *zsaso = "Zone Send Action Specific Option"; const char *select_all = "send command to all zones"; const char *zsa = "zone send action"; @@ -356,8 +351,8 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu bool zsaso; bool select_all; __u8 zsa; - int data_len; - char *file; + int data_len; + char *file; __u32 timeout; }; @@ -394,13 +389,12 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu } if (cfg.zsa == NVME_ZNS_ZSA_SET_DESC_EXT) { - if(!cfg.data_len) { + if (!cfg.data_len) { int data_len = get_zdes_bytes(dev_fd(dev), cfg.namespace_id); if (data_len == 0) { - fprintf(stderr, - "Zone Descriptor Extensions are not supported\n"); + fprintf(stderr, "Zone Descriptor Extensions are not supported\n"); goto close_dev; } else if (data_len < 0) { err = data_len; @@ -429,8 +423,7 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu } } else { if (cfg.file || cfg.data_len) { - fprintf(stderr, - "data, data_len only valid with set extended descriptor\n"); + fprintf(stderr, "data, data_len only valid with set extended descriptor\n"); err = -EINVAL; goto close_dev; } @@ -451,10 +444,8 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu }; err = nvme_zns_mgmt_send(&args); if (!err) - printf("zone-mgmt-send: Success, action:%d zone:%"PRIx64" " - "all:%d nsid:%d\n", - cfg.zsa, (uint64_t)cfg.zslba, (int)cfg.select_all, - cfg.namespace_id); + printf("zone-mgmt-send: Success, action:%d zone:%"PRIx64" all:%d nsid:%d\n", + cfg.zsa, (uint64_t)cfg.zslba, (int)cfg.select_all, cfg.namespace_id); else if (err > 0) nvme_show_status(err); else @@ -542,7 +533,7 @@ static int open_zone(int argc, char **argv, struct command *cmd, struct plugin * err = nvme_zns_mgmt_send(&args); if (!err) printf("zns-open-zone: Success zone slba:%"PRIx64" nsid:%d\n", - (uint64_t)cfg.zslba, cfg.namespace_id); + (uint64_t)cfg.zslba, cfg.namespace_id); else nvme_show_status(err); close_dev: @@ -656,7 +647,7 @@ static int set_zone_desc(int argc, char **argv, struct command *cmd, struct plug err = nvme_zns_mgmt_send(&args); if (!err) printf("set-zone-desc: Success, zone:%"PRIx64" nsid:%d\n", - (uint64_t)cfg.zslba, cfg.namespace_id); + (uint64_t)cfg.zslba, cfg.namespace_id); else if (err > 0) nvme_show_status(err); else @@ -723,7 +714,7 @@ static int zrwa_flush_zone(int argc, char **argv, struct command *cmd, struct pl err = nvme_zns_mgmt_send(&args); if (!err) printf("zrwa-flush-zone: Success, lba:%"PRIx64" nsid:%d\n", - (uint64_t)cfg.lba, cfg.namespace_id); + (uint64_t)cfg.lba, cfg.namespace_id); else nvme_show_status(err); close_dev: @@ -737,7 +728,7 @@ static int zone_mgmt_recv(int argc, char **argv, struct command *cmd, struct plu const char *zslba = "starting LBA of the zone"; const char *zra = "Zone Receive Action"; const char *zrasf = "Zone Receive Action Specific Field(Reporting Options)"; - const char *partial = "Zone Receive Action Specific Features(Partial Report)"; + const char *partial = "Zone Receive Action Specific Features(Partial Report)"; const char *data_len = "length of data in bytes"; enum nvme_print_flags flags; @@ -816,7 +807,7 @@ static int zone_mgmt_recv(int argc, char **argv, struct command *cmd, struct plu err = nvme_zns_mgmt_recv(&args); if (!err) printf("zone-mgmt-recv: Success, action:%d zone:%"PRIx64" nsid:%d\n", - cfg.zra, (uint64_t)cfg.zslba, cfg.namespace_id); + cfg.zra, (uint64_t)cfg.zslba, cfg.namespace_id); else if (err > 0) nvme_show_status(err); else @@ -921,9 +912,8 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi if (!err) { /* get zsze field from zns id ns data - needed for offset calculation */ nvme_id_ns_flbas_to_lbaf_inuse(id_ns.flbas, &lbaf); - zsze = le64_to_cpu(id_zns.lbafe[lbaf].zsze); - } - else { + zsze = le64_to_cpu(id_zns.lbafe[lbaf].zsze); + } else { nvme_show_status(err); goto close_dev; } @@ -942,17 +932,15 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi if (err > 0) { nvme_show_status(err); goto free_buff; - } - else if (err < 0) { + } else if (err < 0) { perror("zns report-zones"); goto free_buff; } total_nr_zones = le64_to_cpu(buff->nr_zones); - if (cfg.num_descs == -1) { + if (cfg.num_descs == -1) cfg.num_descs = total_nr_zones; - } nr_zones = cfg.num_descs; if (nr_zones < nr_zones_chunks) @@ -994,15 +982,20 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi } if (!err) - nvme_show_zns_report_zones(report, nr_zones_chunks, - zdes, log_len, flags, zone_list); + nvme_show_zns_report_zones(report, nr_zones_chunks, + zdes, log_len, zone_list, flags); nr_zones_retrieved += nr_zones_chunks; offset = le64_to_cpu(report->entries[nr_zones_chunks-1].zslba) + zsze; - } + } - if (flags & JSON) - json_nvme_finish_zone_list(total_nr_zones, zone_list); + if (flags & JSON) { + struct print_ops *ops; + + ops = nvme_get_json_print_ops(flags); + if (ops) + ops->zns_finish_zone_list(total_nr_zones, zone_list); + } nvme_free(report, huge); @@ -1015,9 +1008,9 @@ close_dev: static int zone_append(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "The zone append command is used to write to a zone "\ - "using the slba of the zone, and the write will be appended from the "\ - "write pointer of the zone"; + const char *desc = "The zone append command is used to write to a zone\n" + "using the slba of the zone, and the write will be appended from the\n" + "write pointer of the zone"; const char *zslba = "starting LBA of the zone"; const char *data = "file containing data to write"; const char *metadata = "file with metadata to be written"; @@ -1116,7 +1109,7 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin meta_size = ns.lbaf[lba_index].ms; if (meta_size && !(meta_size == 8 && (cfg.prinfo & 0x8)) && - (!cfg.metadata_size || cfg.metadata_size % meta_size)) { + (!cfg.metadata_size || cfg.metadata_size % meta_size)) { fprintf(stderr, "Metadata size:%#"PRIx64" not aligned to metadata size:%#x\n", (uint64_t)cfg.metadata_size, meta_size); @@ -1125,7 +1118,7 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin } if (cfg.prinfo > 0xf) { - fprintf(stderr, "Invalid value for prinfo:%#x\n", cfg.prinfo); + fprintf(stderr, "Invalid value for prinfo:%#x\n", cfg.prinfo); errno = EINVAL; goto close_dev; } @@ -1208,7 +1201,7 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin gettimeofday(&end_time, NULL); if (cfg.latency) printf(" latency: zone append: %llu us\n", - elapsed_utime(start_time, end_time)); + elapsed_utime(start_time, end_time)); if (!err) printf("Success appended data to LBA %"PRIx64"\n", (uint64_t)result); |