From fb32fdeba1f428a3f6c30c8951e82f2a2eec23a8 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 12 Aug 2021 14:01:09 +0200 Subject: Merging upstream version 1.15. Signed-off-by: Daniel Baumann --- plugins/wdc/wdc-nvme.c | 205 ++++++++++++++++++++++++++++-------------------- plugins/wdc/wdc-nvme.h | 3 +- plugins/wdc/wdc-utils.c | 4 + 3 files changed, 127 insertions(+), 85 deletions(-) (limited to 'plugins/wdc') diff --git a/plugins/wdc/wdc-nvme.c b/plugins/wdc/wdc-nvme.c index f7a5b31..4468344 100644 --- a/plugins/wdc/wdc-nvme.c +++ b/plugins/wdc/wdc-nvme.c @@ -79,6 +79,8 @@ #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_SN450_DEV_ID_1 0x2712 +#define WDC_NVME_SN450_DEV_ID_2 0x2713 #define WDC_NVME_SXSLCL_DEV_ID 0x2001 #define WDC_NVME_SN520_DEV_ID 0x5003 #define WDC_NVME_SN520_DEV_ID_1 0x5004 @@ -125,6 +127,7 @@ #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_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 | \ @@ -954,7 +957,7 @@ struct __attribute__((__packed__)) wdc_fw_act_history_log_format_c2 { __u8 log_identifier; __u8 reserved[3]; __le32 num_entries; - struct wdc_fw_act_history_log_entry_c2 entry[20]; + 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]; @@ -1181,11 +1184,13 @@ static __u64 wdc_get_drive_capabilities(int fd) { switch (read_device_id) { case WDC_NVME_SN100_DEV_ID: capabilities = (WDC_DRIVE_CAP_CAP_DIAG | WDC_DRIVE_CAP_INTERNAL_LOG | WDC_DRIVE_CAP_C1_LOG_PAGE | - WDC_DRIVE_CAP_DRIVE_LOG | WDC_DRIVE_CAP_CRASH_DUMP | WDC_DRIVE_CAP_PFAIL_DUMP); + WDC_DRIVE_CAP_DRIVE_LOG | WDC_DRIVE_CAP_CRASH_DUMP | WDC_DRIVE_CAP_PFAIL_DUMP | + WDC_DRIVE_CAP_PURGE); break; case WDC_NVME_SN200_DEV_ID: 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); + WDC_DRIVE_CAP_DRIVE_LOG | WDC_DRIVE_CAP_CRASH_DUMP | WDC_DRIVE_CAP_PFAIL_DUMP | + WDC_DRIVE_CAP_PURGE); /* verify the 0xCA log page is supported */ if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) @@ -1287,6 +1292,8 @@ static __u64 wdc_get_drive_capabilities(int fd) { case WDC_NVME_SN650_DEV_ID_1: case WDC_NVME_SN650_DEV_ID_2: case WDC_NVME_SN650_DEV_ID_3: + case WDC_NVME_SN450_DEV_ID_1: + case WDC_NVME_SN450_DEV_ID_2: /* verify the 0xC0 log page is supported */ if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE) == true) { capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE; @@ -1614,7 +1621,7 @@ static bool get_dev_mgment_cbs_data(int fd, __u8 log_id, void **cbs_data) memset(data, 0, sizeof (__u8) * WDC_C2_LOG_BUF_LEN); /* get the log page length */ - ret = nvme_get_log14(fd, 0xFFFFFFFF, lid, NVME_NO_LOG_LSP, 0, 0, false, uuid_ix, WDC_C2_LOG_BUF_LEN, data); + ret = nvme_get_log14(fd, 0xFFFFFFFF, lid, NVME_NO_LOG_LSP, 0, 0, false, uuid_ix, 0, false, WDC_C2_LOG_BUF_LEN, data); if (ret) { fprintf(stderr, "ERROR : WDC : Unable to get 0x%x Log Page length, ret = 0x%x\n", lid, ret); goto end; @@ -1633,7 +1640,7 @@ static bool get_dev_mgment_cbs_data(int fd, __u8 log_id, void **cbs_data) } /* get the log page data */ - ret = nvme_get_log14(fd, 0xFFFFFFFF, lid, NVME_NO_LOG_LSP, 0, 0, false, uuid_ix, le32_to_cpu(hdr_ptr->length), data); + ret = nvme_get_log14(fd, 0xFFFFFFFF, lid, NVME_NO_LOG_LSP, 0, 0, false, uuid_ix, 0, false, le32_to_cpu(hdr_ptr->length), data); if (ret) { fprintf(stderr, "ERROR : WDC : Unable to read 0x%x Log Page data, ret = 0x%x\n", lid, ret); goto end; @@ -1652,7 +1659,7 @@ static bool get_dev_mgment_cbs_data(int fd, __u8 log_id, void **cbs_data) /* not found with uuid = 1 try with uuid = 0 */ uuid_ix = 0; /* get the log page data */ - ret = nvme_get_log14(fd, 0xFFFFFFFF, lid, NVME_NO_LOG_LSP, 0, 0, false, uuid_ix, le32_to_cpu(hdr_ptr->length), data); + ret = nvme_get_log14(fd, 0xFFFFFFFF, lid, NVME_NO_LOG_LSP, 0, 0, false, uuid_ix, 0, false, le32_to_cpu(hdr_ptr->length), data); hdr_ptr = (struct wdc_c2_log_page_header *)data; sph = (struct wdc_c2_log_subpage_header *)(data + length); found = wdc_get_dev_mng_log_entry(hdr_ptr->length, log_id, hdr_ptr, &sph); @@ -1980,7 +1987,7 @@ static int wdc_do_cap_telemetry_log(int fd, char *file, __u32 bs, int type, int } else if (type == WDC_TELEMETRY_TYPE_CONTROLLER) { /* Verify the Controller Initiated Option is enabled */ err = nvme_get_feature(fd, 0, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0, 0, - 4, buf, &result); + 0, 4, buf, &result); if (err == 0) { if (result == 0) { /* enabled */ @@ -3263,15 +3270,12 @@ static int wdc_purge(int argc, char **argv, char *err_str; int fd, ret; struct nvme_passthru_cmd admin_cmd; + __u64 capabilities = 0; OPT_ARGS(opts) = { OPT_END() }; - err_str = ""; - memset(&admin_cmd, 0, sizeof (admin_cmd)); - admin_cmd.opcode = WDC_NVME_PURGE_CMD_OPCODE; - fd = parse_and_open(argc, argv, desc, opts); if (fd < 0) return fd; @@ -3279,23 +3283,33 @@ static int wdc_purge(int argc, char **argv, if (!wdc_check_device(fd)) return -1; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); - 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"; - break; - case WDC_NVME_PURGE_INT_DEV_ERR: - err_str = "ERROR : WDC : Internal Device Error.\n"; - break; - default: - err_str = "ERROR : WDC\n"; + capabilities = wdc_get_drive_capabilities(fd); + if((capabilities & WDC_DRIVE_CAP_PURGE) == 0) { + ret = -1; + fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + } else { + err_str = ""; + memset(&admin_cmd, 0, sizeof (admin_cmd)); + admin_cmd.opcode = WDC_NVME_PURGE_CMD_OPCODE; + + ret = nvme_submit_admin_passthru(fd, &admin_cmd); + 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"; + break; + case WDC_NVME_PURGE_INT_DEV_ERR: + err_str = "ERROR : WDC : Internal Device Error.\n"; + break; + default: + err_str = "ERROR : WDC\n"; + } } - } - fprintf(stderr, "%s", err_str); - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + fprintf(stderr, "%s", err_str); + fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + } return ret; } @@ -3308,19 +3322,12 @@ static int wdc_purge_monitor(int argc, char **argv, double progress_percent; struct nvme_passthru_cmd admin_cmd; struct wdc_nvme_purge_monitor_data *mon; + __u64 capabilities = 0; OPT_ARGS(opts) = { OPT_END() }; - memset(output, 0, sizeof (output)); - memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); - admin_cmd.opcode = WDC_NVME_PURGE_MONITOR_OPCODE; - admin_cmd.addr = (__u64)(uintptr_t)output; - admin_cmd.data_len = WDC_NVME_PURGE_MONITOR_DATA_LEN; - admin_cmd.cdw10 = WDC_NVME_PURGE_MONITOR_CMD_CDW10; - admin_cmd.timeout_ms = WDC_NVME_PURGE_MONITOR_TIMEOUT; - fd = parse_and_open(argc, argv, desc, opts); if (fd < 0) return fd; @@ -3328,20 +3335,34 @@ static int wdc_purge_monitor(int argc, char **argv, if (!wdc_check_device(fd)) return -1; - ret = nvme_submit_admin_passthru(fd, &admin_cmd); - if (ret == 0) { - 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)); - if (admin_cmd.result == WDC_NVME_PURGE_STATE_BUSY) { - progress_percent = - ((double)le32_to_cpu(mon->entire_progress_current) * 100) / - le32_to_cpu(mon->entire_progress_total); - printf("Purge Progress = %f%%\n", progress_percent); + capabilities = wdc_get_drive_capabilities(fd); + if((capabilities & WDC_DRIVE_CAP_PURGE) == 0) { + ret = -1; + fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); + } else { + memset(output, 0, sizeof (output)); + memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd)); + admin_cmd.opcode = WDC_NVME_PURGE_MONITOR_OPCODE; + admin_cmd.addr = (__u64)(uintptr_t)output; + admin_cmd.data_len = WDC_NVME_PURGE_MONITOR_DATA_LEN; + admin_cmd.cdw10 = WDC_NVME_PURGE_MONITOR_CMD_CDW10; + admin_cmd.timeout_ms = WDC_NVME_PURGE_MONITOR_TIMEOUT; + + ret = nvme_submit_admin_passthru(fd, &admin_cmd); + if (ret == 0) { + 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)); + if (admin_cmd.result == WDC_NVME_PURGE_STATE_BUSY) { + progress_percent = + ((double)le32_to_cpu(mon->entire_progress_current) * 100) / + le32_to_cpu(mon->entire_progress_total); + printf("Purge Progress = %f%%\n", progress_percent); + } } - } - fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); + } return ret; } @@ -4006,9 +4027,9 @@ static void wdc_get_commit_action_bin(__u8 commit_action_type, char *action_bin) } -static void wdc_print_fw_act_history_log_normal(__u8 *data, int num_entries, __u32 cust_id) +static void wdc_print_fw_act_history_log_normal(__u8 *data, int num_entries, __u32 cust_id, __u32 vendor_id) { - int i; + int i, j; char previous_fw[9]; char new_fw[9]; char commit_action_bin[8]; @@ -4019,7 +4040,7 @@ static void wdc_print_fw_act_history_log_normal(__u8 *data, int num_entries, __u if (data[0] == WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID) { printf(" Firmware Activate History Log \n"); - if (cust_id == WDC_CUSTOMER_ID_0x1005) { + 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(" ----- ----------------- ----------------- --------- --------- ----- ------ -------\n"); @@ -4028,14 +4049,16 @@ static void wdc_print_fw_act_history_log_normal(__u8 *data, int num_entries, __u printf(" Entry Timestamp Count Firmware Firmware Slot Action Result \n"); printf(" ----- ----------------- ----------------- --------- --------- ----- ------ -------\n"); } + struct wdc_fw_act_history_log_format_c2 *fw_act_history_entry = (struct wdc_fw_act_history_log_format_c2 *)(data); if (num_entries == WDC_MAX_NUM_ACT_HIST_ENTRIES) { /* find lowest/oldest entry */ for (i = 0; i < num_entries; i++) { + j = (i+1 == WDC_MAX_NUM_ACT_HIST_ENTRIES) ? 0 : i+1; if (le16_to_cpu(fw_act_history_entry->entry[i].fw_act_hist_entries) > - le16_to_cpu(fw_act_history_entry->entry[i+1].fw_act_hist_entries)) { - oldestEntryIdx = i+1; + le16_to_cpu(fw_act_history_entry->entry[j].fw_act_hist_entries)) { + oldestEntryIdx = j; break; } } @@ -4066,6 +4089,14 @@ 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) { + 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)); + printf("%s", time_str); + printf(" "); } else { printf(" "); uint64_t timestamp = (0x0000FFFFFFFFFFFF & le64_to_cpu(fw_act_history_entry->entry[entryIdx].timestamp)); @@ -4161,10 +4192,10 @@ 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) +static void wdc_print_fw_act_history_log_json(__u8 *data, int num_entries, __u32 cust_id, __u32 vendor_id) { struct json_object *root; - int i; + int i, j; char previous_fw[9]; char new_fw[9]; char commit_action_bin[8]; @@ -4186,9 +4217,10 @@ static void wdc_print_fw_act_history_log_json(__u8 *data, int num_entries, __u32 if (num_entries == WDC_MAX_NUM_ACT_HIST_ENTRIES) { /* find lowest/oldest entry */ for (i = 0; i < num_entries; i++) { + j = (i+1 == WDC_MAX_NUM_ACT_HIST_ENTRIES) ? 0 : i+1; if (le16_to_cpu(fw_act_history_entry->entry[i].fw_act_hist_entries) > - le16_to_cpu(fw_act_history_entry->entry[i+1].fw_act_hist_entries)) { - oldestEntryIdx = i+1; + le16_to_cpu(fw_act_history_entry->entry[j].fw_act_hist_entries)) { + oldestEntryIdx = j; break; } } @@ -4215,6 +4247,11 @@ static void wdc_print_fw_act_history_log_json(__u8 *data, int num_entries, __u32 json_object_add_value_string(root, "Power on Hour", time_str); + } 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_int(root, "Timestamp", timestamp); @@ -4369,7 +4406,7 @@ static void wdc_print_smart_cloud_attr_C0_normal(void *data) smart_log_ver = (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_LPV]); printf(" Log page version %"PRIu16"\n",smart_log_ver); printf(" Log page GUID 0x"); - printf("%lX%lX\n",(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG + 8]), + printf("0x%"PRIx64"%"PRIx64"\n",(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG + 8]), (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG])); if(smart_log_ver > 2) { printf(" Errata Version Field %d\n", @@ -4451,9 +4488,8 @@ static void wdc_print_smart_cloud_attr_C0_json(void *data) json_object_add_value_uint(root, "Log page version", smart_log_ver); char guid[40]; memset((void*)guid, 0, 40); - sprintf((char*)guid, "0x%lX%lX",(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG + 8]), + 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])); - printf("GUID string:%s", guid); json_object_add_value_string(root, "Log page GUID", guid); if(smart_log_ver > 2){ json_object_add_value_uint(root, "Errata Version Field", @@ -4605,7 +4641,7 @@ static int wdc_get_c0_log_page(int fd, char *format, int uuid_index) /* Get the 0xC0 log data */ ret = nvme_get_log14(fd, 0xFFFFFFFF, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, - NVME_NO_LOG_LSP, 0, 0, false, uuid_index, WDC_NVME_SMART_CLOUD_ATTR_LEN, data); + NVME_NO_LOG_LSP, 0, 0, false, uuid_index, 0, false, WDC_NVME_SMART_CLOUD_ATTR_LEN, data); if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); @@ -4652,7 +4688,7 @@ static int wdc_get_c0_log_page(int fd, char *format, int uuid_index) /* Get the 0xC0 log data */ ret = nvme_get_log14(fd, 0xFFFFFFFF, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, - NVME_NO_LOG_LSP, 0, 0, false, uuid_index, WDC_NVME_EOL_STATUS_LOG_LEN, data); + NVME_NO_LOG_LSP, 0, 0, false, uuid_index, 0, false, WDC_NVME_EOL_STATUS_LOG_LEN, data); if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); @@ -4783,7 +4819,7 @@ static int wdc_print_d0_log(struct wdc_ssd_d0_smart_log *perf, int fmt) return 0; } -static int wdc_print_fw_act_history_log(__u8 *data, int num_entries, int fmt, __u32 cust_id) +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"); @@ -4792,10 +4828,10 @@ static int wdc_print_fw_act_history_log(__u8 *data, int num_entries, int fmt, __ switch (fmt) { case NORMAL: - wdc_print_fw_act_history_log_normal(data, num_entries, cust_id); + wdc_print_fw_act_history_log_normal(data, num_entries, cust_id, vendor_id); break; case JSON: - wdc_print_fw_act_history_log_json(data, num_entries, cust_id); + wdc_print_fw_act_history_log_json(data, num_entries, cust_id, vendor_id); break; } return 0; @@ -5200,7 +5236,7 @@ static int wdc_do_clear_pcie_correctable_errors_fid(int fd) __u32 value = 1 << 31; /* Bit 31 - clear PCIe correctable count */ ret = nvme_set_feature(fd, 0, WDC_NVME_CLEAR_PCIE_CORR_FEATURE_ID, value, - 0, 0, 0, NULL, &result); + 0, 0, 0, 0, NULL, &result); fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); return ret; @@ -5448,7 +5484,7 @@ static int wdc_get_fw_act_history(int fd, char *format) 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); + 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"); ret = 0; @@ -5473,7 +5509,8 @@ static int wdc_get_fw_act_history_C2(int fd, char *format) __u8 *data; __u32 *cust_id; struct wdc_fw_act_history_log_format_c2 *fw_act_history_log; - __u32 num_entries = 0; + __u32 tot_entries = 0, num_entries = 0; + __u32 vendor_id = 0, device_id = 0; if (!wdc_check_device(fd)) return -1; @@ -5483,6 +5520,7 @@ static int wdc_get_fw_act_history_C2(int fd, char *format) fprintf(stderr, "ERROR : WDC : invalid output format\n"); return fmt; } + ret = wdc_get_pci_ids(&device_id, &vendor_id); if ((data = (__u8*) malloc(sizeof (__u8) * WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN)) == NULL) { fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); @@ -5500,25 +5538,22 @@ static int wdc_get_fw_act_history_C2(int fd, char *format) if (ret == 0) { /* parse the data */ fw_act_history_log = (struct wdc_fw_act_history_log_format_c2*)(data); - num_entries = le32_to_cpu(fw_act_history_log->num_entries); + tot_entries = le32_to_cpu(fw_act_history_log->num_entries); - if ((num_entries > 0) && (num_entries <= WDC_MAX_NUM_ACT_HIST_ENTRIES)) { + if (tot_entries > 0) { /* get the FW customer id */ if (!get_dev_mgment_cbs_data(fd, WDC_C2_CUSTOMER_ID_ID, (void*)&cust_id)) { fprintf(stderr, "%s: ERROR : WDC : 0xC2 Log Page entry ID 0x%x not found\n", __func__, WDC_C2_CUSTOMER_ID_ID); ret = -1; goto freeData; } - - ret = wdc_print_fw_act_history_log(data, num_entries, fmt, *cust_id); - } else if (num_entries == 0) { + num_entries = (tot_entries < WDC_MAX_NUM_ACT_HIST_ENTRIES) ? tot_entries : + WDC_MAX_NUM_ACT_HIST_ENTRIES; + ret = wdc_print_fw_act_history_log(data, num_entries, fmt, *cust_id, vendor_id); + } else { 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", num_entries); - ret = -1; - } } else { fprintf(stderr, "ERROR : WDC : Unable to read FW Activate History Log Page data\n"); ret = -1; @@ -5578,7 +5613,7 @@ static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *com /* Get the 0xC0 log data */ ret = nvme_get_log14(fd, 0xFFFFFFFF, WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_OPCODE, - NVME_NO_LOG_LSP, 0, 0, false, uuid_index, WDC_NVME_SMART_CLOUD_ATTR_LEN, data); + NVME_NO_LOG_LSP, 0, 0, false, uuid_index, 0, false, WDC_NVME_SMART_CLOUD_ATTR_LEN, data); if (ret == 0) { /* Verify GUID matches */ @@ -5634,7 +5669,7 @@ static int wdc_do_clear_fw_activate_history_fid(int fd) __u32 value = 1 << 31; /* Bit 31 - Clear Firmware Update History Log */ ret = nvme_set_feature(fd, 0, WDC_NVME_CLEAR_FW_ACT_HIST_VU_FID, value, - 0, 0, 0, NULL, &result); + 0, 0, 0, 0, NULL, &result); fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret); return ret; @@ -5728,18 +5763,18 @@ static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct comm if (cfg.disable) { ret = nvme_set_feature(fd, 0, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 1, - 0, 0, 0, buf, &result); + 0, 0, 0, 0, buf, &result); wdc_clear_reason_id(fd); } else { if (cfg.enable) { ret = nvme_set_feature(fd, 0, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0, - 0, 0, 0, buf, &result); + 0, 0, 0, 0, buf, &result); } else if (cfg.status) { ret = nvme_get_feature(fd, 0, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0, 0, - 4, buf, &result); + 0, 4, buf, &result); if (ret == 0) { if (result) fprintf(stderr, "Controller Option Telemetry Log Page State: Disabled\n"); @@ -6363,7 +6398,7 @@ static int wdc_do_drive_essentials(int fd, char *dir, char *key) if (deFeatureIdList[listIdx].featureId == FID_LBA_RANGE_TYPE) continue; ret = nvme_get_feature(fd, WDC_DE_GLOBAL_NSID, deFeatureIdList[listIdx].featureId, FS_CURRENT, 0, - sizeof(featureIdBuff), &featureIdBuff, &result); + 0, sizeof(featureIdBuff), &featureIdBuff, &result); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_get_feature id 0x%x failed, ret = %d\n", @@ -7713,7 +7748,7 @@ static int wdc_vs_temperature_stats(int argc, char **argv, temperature = ((smart_log.temperature[1] << 8) | smart_log.temperature[0]) - 273; /* retrieve HCTM Thermal Management Temperatures */ - nvme_get_feature(fd, 0, 0x10, 0, 0, 0, 0, &hctm_tmt); + nvme_get_feature(fd, 0, 0x10, 0, 0, 0, 0, 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; @@ -7800,8 +7835,10 @@ static int wdc_capabilities(int argc, char **argv, printf("get-pfail-dump : %s\n", capabilities & WDC_DRIVE_CAP_PFAIL_DUMP ? "Supported" : "Not Supported"); printf("id-ctrl : Supported\n"); - printf("purge : Supported\n"); - printf("purge-monitor : 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", diff --git a/plugins/wdc/wdc-nvme.h b/plugins/wdc/wdc-nvme.h index de6affa..29ff6a0 100644 --- a/plugins/wdc/wdc-nvme.h +++ b/plugins/wdc/wdc-nvme.h @@ -4,9 +4,10 @@ #if !defined(WDC_NVME) || defined(CMD_HEADER_MULTI_READ) #define WDC_NVME +#define WDC_PLUGIN_VERSION "1.14.1" #include "cmd.h" -PLUGIN(NAME("wdc", "Western Digital vendor specific extensions"), +PLUGIN(NAME("wdc", "Western Digital vendor specific extensions", WDC_PLUGIN_VERSION), COMMAND_LIST( ENTRY("cap-diag", "WDC Capture-Diagnostics", wdc_cap_diag) ENTRY("drive-log", "WDC Drive Log", wdc_drive_log) diff --git a/plugins/wdc/wdc-utils.c b/plugins/wdc/wdc-utils.c index 2740181..52c427b 100644 --- a/plugins/wdc/wdc-utils.c +++ b/plugins/wdc/wdc-utils.c @@ -77,7 +77,11 @@ int wdc_UtilsGetTime(PUtilsTimeInfo timeInfo) timeInfo->second = currTimeInfo.tm_sec; timeInfo->msecs = 0; timeInfo->isDST = currTimeInfo.tm_isdst; +#if defined(__GLIBC__) && !defined(__UCLIBC__) && !defined(__MUSL__) timeInfo->zone = -currTimeInfo.tm_gmtoff / 60; +#else + timeInfo->zone = -1 * (timezone / SECONDS_IN_MIN); +#endif return WDC_STATUS_SUCCESS; } -- cgit v1.2.3