diff options
Diffstat (limited to 'plugins/wdc')
-rw-r--r-- | plugins/wdc/wdc-nvme.c | 924 | ||||
-rw-r--r-- | plugins/wdc/wdc-nvme.h | 2 |
2 files changed, 379 insertions, 547 deletions
diff --git a/plugins/wdc/wdc-nvme.c b/plugins/wdc/wdc-nvme.c index 7525055..fa4157d 100644 --- a/plugins/wdc/wdc-nvme.c +++ b/plugins/wdc/wdc-nvme.c @@ -681,44 +681,6 @@ struct __packed wdc_nvme_ext_smart_log { __u8 ext_smart_lpg[16]; /* 496 Log page GUID */ }; -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 */ -}; - struct ocp_bad_nand_block_count { __u64 raw : 48; __u16 normalized : 16; @@ -766,8 +728,9 @@ struct ocp_cloud_smart_log { __u8 percent_free_blocks; __u8 rsvd121[7]; __u16 capacitor_health; - __u8 nvme_errata_ver; - __u8 rsvd131[5]; + __u8 nvme_base_errata_ver; + __u8 nvme_cmd_set_errata_ver; + __u8 rsvd132[4]; __u64 unaligned_io; __u64 security_version_number; __u64 total_nuse; @@ -775,7 +738,8 @@ struct ocp_cloud_smart_log { __u8 endurance_estimate[16]; __u64 pcie_link_retraining_cnt; __u64 power_state_change_cnt; - __u8 rsvd208[286]; + char lowest_permitted_fw_rev[8]; + __u8 rsvd216[278]; __u16 log_page_version; __u8 log_page_guid[16]; }; @@ -1004,6 +968,13 @@ static int wdc_enc_submit_move_data(struct nvme_dev *dev, char *cmd, int len, in 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); +static int wdc_print_c0_cloud_attr_log(void *data, + int fmt, + struct nvme_dev *dev); +static int wdc_print_c0_eol_log(void *data, int fmt); +static void wdc_show_cloud_smart_log_normal(struct ocp_cloud_smart_log *log, + struct nvme_dev *dev); +static void wdc_show_cloud_smart_log_json(struct ocp_cloud_smart_log *log); /* Drive log data size */ struct wdc_log_size { @@ -1148,14 +1119,14 @@ struct __packed wdc_bd_ca_log_format { __u8 raw_value[8]; }; -#define LATENCY_LOG_BUCKET_READ 3 -#define LATENCY_LOG_BUCKET_WRITE 2 -#define LATENCY_LOG_BUCKET_TRIM 1 -#define LATENCY_LOG_BUCKET_RESERVED 0 +#define WDC_LATENCY_LOG_BUCKET_READ 3 +#define WDC_LATENCY_LOG_BUCKET_WRITE 2 +#define WDC_LATENCY_LOG_BUCKET_TRIM 1 +#define WDC_LATENCY_LOG_BUCKET_RESERVED 0 -#define LATENCY_LOG_MEASURED_LAT_READ 2 -#define LATENCY_LOG_MEASURED_LAT_WRITE 1 -#define LATENCY_LOG_MEASURED_LAT_TRIM 0 +#define WDC_LATENCY_LOG_MEASURED_LAT_READ 2 +#define WDC_LATENCY_LOG_MEASURED_LAT_WRITE 1 +#define WDC_LATENCY_LOG_MEASURED_LAT_TRIM 0 struct __packed wdc_ssd_latency_monitor_log { __u8 feature_status; /* 0x00 */ @@ -1180,8 +1151,9 @@ struct __packed wdc_ssd_latency_monitor_log { __le64 static_latency_timestamp[4][3]; /* 0x130 - 0x18F */ __le16 static_measured_latency[4][3]; /* 0x190 - 0x1A7 */ __le16 static_latency_stamp_units; /* 0x1A8 */ - __u8 rsvd4[0x16]; /* 0x1AA */ + __u8 rsvd4[10]; /* 0x1AA */ + __u8 debug_telemetry_log_size[12]; /* 0x1B4 */ __le16 debug_log_trigger_enable; /* 0x1C0 */ __le16 debug_log_measured_latency; /* 0x1C2 */ __le64 debug_log_latency_stamp; /* 0x1C4 */ @@ -1249,25 +1221,29 @@ struct __packed wdc_ssd_d0_smart_log { #define WDC_OCP_C1_GUID_LENGTH 16 #define WDC_ERROR_REC_LOG_BUF_LEN 512 #define WDC_ERROR_REC_LOG_ID 0xC1 -#define WDC_ERROR_REC_LOG_VERSION1 0001 -#define WDC_ERROR_REC_LOG_VERSION2 0002 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 */ + __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 panic_count; /* 031 - Number of panics encountered */ + __le64 prev_panic_ids[4]; /* 032 - 063 Previous Panic ID's */ + __u8 rsvd2[430]; /* 064 - 493 Reserved Bytes */ + /* 430 reserved bytes aligns with the rest */ + /* of the data structure. The size of 463 */ + /* bytes mentioned in the OCP spec */ + /* (version 2.5) would not fit here. */ + __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, @@ -3711,7 +3687,7 @@ free_buf: static int dump_internal_logs(struct nvme_dev *dev, char *dir_name, int verbose) { - char file_path[128]; + char file_path[PATH_MAX]; void *telemetry_log; const size_t bs = 512; struct nvme_telemetry_log *hdr; @@ -4681,20 +4657,30 @@ static int wdc_print_latency_monitor_log_normal(struct nvme_dev *dev, 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)); + if (le16_to_cpu(log_data->log_page_version) >= 4) + printf(" Debug Telemetry Log Size %"PRIu64"\n", + le64_to_cpu(*(uint64_t *)log_data->debug_telemetry_log_size)); + printf(" Debug Log Trigger Enable %d\n", + le16_to_cpu(log_data->debug_log_trigger_enable)); + printf(" Log Page Version %d\n", + le16_to_cpu(log_data->log_page_version)); + printf(" Log page GUID 0x"); + for (j = 0; j < WDC_C3_GUID_LENGTH; j++) + printf("%x", log_data->log_page_guid[j]); + printf("\n"); 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])); + i, le32_to_cpu(log_data->active_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_READ]), + le32_to_cpu(log_data->active_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_WRITE]), + le32_to_cpu(log_data->active_bucket_counter[i][WDC_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])); + 3-i, le16_to_cpu(log_data->active_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_READ]), + le16_to_cpu(log_data->active_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_WRITE]), + le16_to_cpu(log_data->active_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_TRIM])); for (i = 3; i >= 0; i--) { printf(" Active Latency Time Stamp: Bucket %d ", 3-i); @@ -4711,15 +4697,15 @@ static int wdc_print_latency_monitor_log_normal(struct nvme_dev *dev, for (i = 0; i <= 3; i++) printf(" Static Bucket Counter: Bucket %d %27d %27d %27d\n", - i, le32_to_cpu(log_data->static_bucket_counter[i][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])); + i, le32_to_cpu(log_data->static_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_READ]), + le32_to_cpu(log_data->static_bucket_counter[i][WDC_LATENCY_LOG_BUCKET_WRITE]), + le32_to_cpu(log_data->static_bucket_counter[i][WDC_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])); + 3-i, le16_to_cpu(log_data->static_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_READ]), + le16_to_cpu(log_data->static_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_WRITE]), + le16_to_cpu(log_data->static_measured_latency[i][WDC_LATENCY_LOG_MEASURED_LAT_TRIM])); for (i = 3; i >= 0; i--) { printf(" Static Latency Time Stamp: Bucket %d ", 3-i); @@ -4755,7 +4741,22 @@ static void wdc_print_latency_monitor_log_json(struct wdc_ssd_latency_monitor_lo json_object_add_value_int(root, "Active Lantency Minimum Window", 100*log_data->active_latency_min_window); json_object_add_value_int(root, "Active Latency Stamp Units", le16_to_cpu(log_data->active_latency_stamp_units)); json_object_add_value_int(root, "Static Latency Stamp Units", le16_to_cpu(log_data->static_latency_stamp_units)); - json_object_add_value_int(root, "Debug Log Trigger Enable", le16_to_cpu(log_data->debug_log_trigger_enable)); + if (le16_to_cpu(log_data->log_page_version) >= 4) { + json_object_add_value_int(root, "Debug Telemetry Log Size", + le64_to_cpu(*(uint64_t *)log_data->debug_telemetry_log_size)); + } + json_object_add_value_int(root, "Debug Log Trigger Enable", + le16_to_cpu(log_data->debug_log_trigger_enable)); + json_object_add_value_int(root, "Log Page Version", + le16_to_cpu(log_data->log_page_version)); + + char guid[40]; + + memset((void *)guid, 0, 40); + sprintf((char *)guid, "0x%"PRIx64"%"PRIx64"", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]), + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0])); + json_object_add_value_string(root, "Log page GUID", guid); for (i = 0; i <= 3; i++) { for (j = 2; j >= 0; j--) { @@ -4814,13 +4815,20 @@ static void wdc_print_error_rec_log_normal(struct wdc_ocp_c1_error_recovery_log 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) { + if (le16_to_cpu(log_data->log_page_version) >= 2) { printf(" Vendor Specific Command Timeout : 0x%x\n", log_data->vs_cmd_to); printf(" Device Recovery Action 2 : 0x%x\n", log_data->dev_recovery_action2); printf(" Device Recovery Action 2 Timeout : 0x%x\n", log_data->dev_recovery_action2_to); } - printf(" Log Page Version : 0x%x\n", le16_to_cpu(log_data->log_page_version)); - printf(" Log page GUID : 0x"); + if (le16_to_cpu(log_data->log_page_version) >= 3) { + printf(" Panic Count : 0x%x\n", log_data->panic_count); + for (j = 0; j < 4; j++) + printf(" Previous Panic ID N-%d : 0x%"PRIx64"\n", + j+1, le64_to_cpu(log_data->prev_panic_ids[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_C1_GUID_LENGTH; j++) printf("%x", log_data->log_page_guid[j]); printf("\n"); @@ -4828,6 +4836,8 @@ static void wdc_print_error_rec_log_normal(struct wdc_ocp_c1_error_recovery_log static void wdc_print_error_rec_log_json(struct wdc_ocp_c1_error_recovery_log *log_data) { + int j; + char buf[128]; 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)); @@ -4838,12 +4848,21 @@ static void wdc_print_error_rec_log_json(struct wdc_ocp_c1_error_recovery_log *l json_object_add_value_int(root, "Vendor Specific Recovery Opcode", log_data->vs_recovery_opc); json_object_add_value_int(root, "Vendor Specific Command CDW12", le32_to_cpu(log_data->vs_cmd_cdw12)); json_object_add_value_int(root, "Vendor Specific Command CDW13", le32_to_cpu(log_data->vs_cmd_cdw13)); - if (le16_to_cpu(log_data->log_page_version) == WDC_ERROR_REC_LOG_VERSION2) { + if (le16_to_cpu(log_data->log_page_version) >= 2) { json_object_add_value_int(root, "Vendor Specific Command Timeout", log_data->vs_cmd_to); json_object_add_value_int(root, "Device Recovery Action 2", log_data->dev_recovery_action2); json_object_add_value_int(root, "Device Recovery Action 2 Timeout", log_data->dev_recovery_action2_to); } - json_object_add_value_int(root, "Log Page Version", le16_to_cpu(log_data->log_page_version)); + if (le16_to_cpu(log_data->log_page_version) >= 3) { + json_object_add_value_int(root, "Panic Count", log_data->panic_count); + for (j = 0; j < 4; j++) { + sprintf(buf, "Previous Panic ID N-%d", j+1); + json_object_add_value_int(root, buf, + le64_to_cpu(log_data->prev_panic_ids[j])); + } + } + json_object_add_value_int(root, "Log Page Version", + le16_to_cpu(log_data->log_page_version)); char guid[40]; @@ -5875,6 +5894,141 @@ static void wdc_print_fw_act_history_log_json(__u8 *data, int num_entries, json_free_object(root); } +static int nvme_get_print_ocp_cloud_smart_log(struct nvme_dev *dev, + int uuid_index, + __u32 namespace_id, + int fmt) +{ + struct ocp_cloud_smart_log *log_ptr = NULL; + int ret, i; + __u32 length = WDC_NVME_SMART_CLOUD_ATTR_LEN; + int fd = dev_fd(dev); + + log_ptr = (struct ocp_cloud_smart_log *)malloc(sizeof(__u8) * length); + if (!log_ptr) { + fprintf(stderr, "ERROR: WDC: malloc: %s\n", strerror(errno)); + return -1; + } + + if (namespace_id == NVME_NSID_ALL) { + ret = nvme_get_nsid(fd, &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 = fd, + .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 = length, + .log = log_ptr, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + ret = nvme_get_log(&args); + + if (fmt == JSON) + nvme_show_status(ret); + + if (!ret) { + /* Verify GUID matches */ + for (i = 0; i < 16; i++) { + if (scao_guid[i] != log_ptr->log_page_guid[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", log_ptr->log_page_guid[j]); + fprintf(stderr, "\n"); + + ret = -1; + break; + } + } + + if (!ret) + /* parse the data */ + wdc_print_c0_cloud_attr_log(log_ptr, fmt, dev); + } else { + fprintf(stderr, "ERROR: WDC: Unable to read C0 Log Page data\n"); + ret = -1; + } + + free(log_ptr); + return ret; +} + +static int nvme_get_print_c0_eol_log(struct nvme_dev *dev, + int uuid_index, + __u32 namespace_id, + int fmt) +{ + void *log_ptr = NULL; + int ret; + __u32 length = WDC_NVME_EOL_STATUS_LOG_LEN; + int fd = dev_fd(dev); + + log_ptr = (void *)malloc(sizeof(__u8) * length); + if (!log_ptr) { + fprintf(stderr, "ERROR: WDC: malloc: %s\n", strerror(errno)); + return -1; + } + + if (namespace_id == NVME_NSID_ALL) { + ret = nvme_get_nsid(fd, &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 = fd, + .lid = WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, + .nsid = namespace_id, + .lpo = 0, + .lsp = NVME_LOG_LSP_NONE, + .lsi = 0, + .rae = false, + .uuidx = uuid_index, + .csi = NVME_CSI_NVM, + .ot = false, + .len = length, + .log = log_ptr, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, + }; + ret = nvme_get_log(&args); + + if (fmt == JSON) + nvme_show_status(ret); + + if (!ret) { + /* parse the data */ + wdc_print_c0_eol_log(log_ptr, fmt); + } else { + fprintf(stderr, "ERROR: WDC: Unable to read C0 Log Page data "); + fprintf(stderr, "with uuid index %d\n", uuid_index); + ret = -1; + } + + free(log_ptr); + return ret; +} + static int nvme_get_ext_smart_cloud_log(int fd, __u8 **data, int uuid_index, __u32 namespace_id) { int ret, i; @@ -6556,177 +6710,6 @@ static void wdc_print_ext_smart_cloud_log_json(void *data, int mask) json_free_object(root); } -static void wdc_print_smart_cloud_attr_C0_normal(void *data) -{ - __u8 *log_data = (__u8 *)data; - uint16_t smart_log_ver = 0; - - printf(" SMART Cloud Attributes :-\n"); - - printf(" Physical media units written : %s\n", - 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]))); - printf(" Bad user nand blocks Raw : %"PRIu64"\n", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BUNBR] & 0x0000FFFFFFFFFFFF)); - printf(" Bad user nand blocks Normalized : %d\n", - (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BUNBN])); - printf(" Bad system nand blocks Raw : %"PRIu64"\n", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BSNBR] & 0x0000FFFFFFFFFFFF)); - printf(" Bad system nand blocks Normalized : %d\n", - (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BSNBN])); - printf(" XOR recovery count : %"PRIu64"\n", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_XRC])); - printf(" Uncorrectable read error count : %"PRIu64"\n", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UREC])); - printf(" Soft ecc error count : %"PRIu64"\n", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SEEC])); - printf(" End to end corrected errors : %"PRIu32"\n", - (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EECE])); - printf(" End to end detected errors : %"PRIu32"\n", - (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EEDC])); - printf(" System data percent used : %d\n", (__u8)log_data[SCAO_SDPU]); - printf(" Refresh counts : %"PRIu64"\n", - (uint64_t)(le64_to_cpu(*(uint64_t *)&log_data[SCAO_RFSC]) & 0x00FFFFFFFFFFFFFF)); - printf(" Max User data erase counts : %"PRIu32"\n", - (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MXUDEC])); - printf(" Min User data erase counts : %"PRIu32"\n", - (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MNUDEC])); - printf(" Number of Thermal throttling events : %d\n", (__u8)log_data[SCAO_NTTE]); - printf(" Current throttling status : 0x%x\n", (__u8)log_data[SCAO_CTS]); - printf(" PCIe correctable error count : %"PRIu64"\n", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PCEC])); - printf(" Incomplete shutdowns : %"PRIu32"\n", - (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_ICS])); - printf(" Percent free blocks : %d\n", (__u8)log_data[SCAO_PFB]); - printf(" Capacitor health : %"PRIu16"\n", - (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_CPH])); - printf(" Unaligned I/O : %"PRIu64"\n", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UIO])); - printf(" Security Version Number : %"PRIu64"\n", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SVN])); - printf(" NUSE Namespace utilization : %"PRIu64"\n", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_NUSE])); - printf(" PLP start count : %s\n", - uint128_t_to_string(le128_to_cpu(&log_data[SCAO_PSC]))); - printf(" Endurance estimate : %s\n", - uint128_t_to_string(le128_to_cpu(&log_data[SCAO_EEST]))); - smart_log_ver = (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_LPV]); - printf(" Log page version : %"PRIu16"\n", smart_log_ver); - printf(" Log page GUID : 0x"); - printf("%"PRIx64"%"PRIx64"\n", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG + 8]), - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG])); - if (smart_log_ver > 2) { - printf(" Errata Version Field : %d\n", - (__u8)log_data[SCAO_EVF]); - printf(" Point Version Field : %"PRIu16"\n", - (uint16_t)log_data[SCAO_PVF]); - printf(" Minor Version Field : %"PRIu16"\n", - (uint16_t)log_data[SCAO_MIVF]); - printf(" Major Version Field : %d\n", - (__u8)log_data[SCAO_MAVF]); - printf(" NVMe Errata Version : %d\n", - (__u8)log_data[SCAO_NEV]); - printf(" PCIe Link Retraining Count : %"PRIu64"\n", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PLRC])); - } - if (smart_log_ver > 3) { - printf(" Power State Change Count : %"PRIu64"\n", - (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 = json_create_object(); - uint16_t smart_log_ver = 0; - - 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", - le128_to_cpu(&log_data[SCAO_PMUR])); - json_object_add_value_uint64(root, "Bad user nand blocks - Raw", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BUNBR] & 0x0000FFFFFFFFFFFF)); - json_object_add_value_uint(root, "Bad user nand blocks - Normalized", - (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BUNBN])); - json_object_add_value_uint64(root, "Bad system nand blocks - Raw", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BSNBR] & 0x0000FFFFFFFFFFFF)); - json_object_add_value_uint(root, "Bad system nand blocks - Normalized", - (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BSNBN])); - json_object_add_value_uint64(root, "XOR recovery count", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_XRC])); - json_object_add_value_uint64(root, "Uncorrectable read error count", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UREC])); - json_object_add_value_uint64(root, "Soft ecc error count", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SEEC])); - json_object_add_value_uint(root, "End to end corrected errors", - (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EECE])); - json_object_add_value_uint(root, "End to end detected errors", - (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EEDC])); - json_object_add_value_uint(root, "System data percent used", - (__u8)log_data[SCAO_SDPU]); - json_object_add_value_uint64(root, "Refresh counts", - (uint64_t)(le64_to_cpu(*(uint64_t *)&log_data[SCAO_RFSC]) & 0x00FFFFFFFFFFFFFF)); - json_object_add_value_uint(root, "Max User data erase counts", - (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MXUDEC])); - json_object_add_value_uint(root, "Min User data erase counts", - (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MNUDEC])); - json_object_add_value_uint(root, "Number of Thermal throttling events", - (__u8)log_data[SCAO_NTTE]); - json_object_add_value_uint(root, "Current throttling status", - (__u8)log_data[SCAO_CTS]); - json_object_add_value_uint64(root, "PCIe correctable error count", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PCEC])); - json_object_add_value_uint(root, "Incomplete shutdowns", - (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_ICS])); - json_object_add_value_uint(root, "Percent free blocks", - (__u8)log_data[SCAO_PFB]); - json_object_add_value_uint(root, "Capacitor health", - (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_CPH])); - json_object_add_value_uint64(root, "Unaligned I/O", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UIO])); - json_object_add_value_uint64(root, "Security Version Number", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SVN])); - json_object_add_value_uint64(root, "NUSE - Namespace utilization", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_NUSE])); - json_object_add_value_uint128(root, "PLP start count", - le128_to_cpu(&log_data[SCAO_PSC])); - json_object_add_value_uint128(root, "Endurance estimate", - le128_to_cpu(&log_data[SCAO_EEST])); - smart_log_ver = (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_LPV]); - json_object_add_value_uint(root, "Log page version", smart_log_ver); - char guid[40]; - - memset((void *)guid, 0, 40); - sprintf((char *)guid, "0x%"PRIx64"%"PRIx64"", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG + 8]), - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG])); - json_object_add_value_string(root, "Log page GUID", guid); - if (smart_log_ver > 2) { - json_object_add_value_uint(root, "Errata Version Field", - (__u8)log_data[SCAO_EVF]); - json_object_add_value_uint(root, "Point Version Field", - (uint16_t)log_data[SCAO_PVF]); - json_object_add_value_uint(root, "Minor Version Field", - (uint16_t)log_data[SCAO_MIVF]); - json_object_add_value_uint(root, "Major Version Field", - (__u8)log_data[SCAO_MAVF]); - json_object_add_value_uint(root, "NVMe Errata Version", - (__u8)log_data[SCAO_NEV]); - json_object_add_value_uint64(root, "PCIe Link Retraining Count", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PLRC])); - } - 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])); - } - json_print_object(root, NULL); - printf("\n"); - json_free_object(root); -} static void wdc_print_eol_c0_normal(void *data) { @@ -6794,18 +6777,26 @@ static int wdc_print_ext_smart_cloud_log(void *data, int fmt) return 0; } -static int wdc_print_c0_cloud_attr_log(void *data, int fmt) +static int wdc_print_c0_cloud_attr_log(void *data, + int fmt, + struct nvme_dev *dev) { + struct ocp_cloud_smart_log *log = (struct ocp_cloud_smart_log *)data; + if (!data) { fprintf(stderr, "ERROR: WDC: Invalid buffer to read 0xC0 log\n"); return -1; } + switch (fmt) { + case BINARY: + d_raw((unsigned char *)log, sizeof(struct ocp_cloud_smart_log)); + break; case NORMAL: - wdc_print_smart_cloud_attr_C0_normal(data); + wdc_show_cloud_smart_log_normal(log, dev); break; case JSON: - wdc_print_smart_cloud_attr_C0_json(data); + wdc_show_cloud_smart_log_json(log); break; } return 0; @@ -6818,6 +6809,9 @@ static int wdc_print_c0_eol_log(void *data, int fmt) return -1; } switch (fmt) { + case BINARY: + d_raw((unsigned char *)data, WDC_NVME_EOL_STATUS_LOG_LEN); + break; case NORMAL: wdc_print_eol_c0_normal(data); break; @@ -6832,113 +6826,17 @@ static int wdc_get_c0_log_page_sn_customer_id_0x100X(struct nvme_dev *dev, int u 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); + ret = nvme_get_print_ocp_cloud_smart_log(dev, + uuid_index, + namespace_id, + fmt); } 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); + ret = nvme_get_print_c0_eol_log(dev, + uuid_index, + namespace_id, + fmt); } else { fprintf(stderr, "ERROR: WDC: Unknown uuid index\n"); ret = -1; @@ -6952,7 +6850,6 @@ static int wdc_get_c0_log_page_sn(nvme_root_t r, struct nvme_dev *dev, int uuid_ { int ret = 0; __u32 cust_id; - __u8 *data; cust_id = wdc_get_fw_cust_id(r, dev); if (cust_id == WDC_INVALID_CUSTOMER_ID) { @@ -6965,30 +6862,10 @@ static int wdc_get_c0_log_page_sn(nvme_root_t r, struct nvme_dev *dev, int uuid_ 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); + ret = nvme_get_print_c0_eol_log(dev, + 0, + namespace_id, + fmt); } return ret; @@ -6998,11 +6875,9 @@ static int wdc_get_c0_log_page(nvme_root_t r, struct nvme_dev *dev, char *format __u32 namespace_id) { uint32_t device_id, read_vendor_id; - enum nvme_print_flags fmt; + nvme_print_flags_t fmt; int ret; __u8 *data; - __u8 log_id; - __u32 length; if (!wdc_check_device(r, dev)) return -1; @@ -7035,86 +6910,23 @@ static int wdc_get_c0_log_page(nvme_root_t r, struct nvme_dev *dev, char *format case WDC_NVME_SN650_DEV_ID_4: case WDC_NVME_SN655_DEV_ID: if (uuid_index == 0) { - log_id = WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID; - length = WDC_NVME_SMART_CLOUD_ATTR_LEN; - } else { - log_id = WDC_NVME_GET_EOL_STATUS_LOG_OPCODE; - length = WDC_NVME_EOL_STATUS_LOG_LEN; - } - - data = (__u8 *)malloc(sizeof(__u8) * length); - 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 = 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 = length, - .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 */ - if (uuid_index == 0) - wdc_print_c0_cloud_attr_log(data, fmt); - else - wdc_print_c0_eol_log(data, fmt); + ret = nvme_get_print_ocp_cloud_smart_log(dev, + uuid_index, + namespace_id, + fmt); } else { - fprintf(stderr, "ERROR: WDC: Unable to read C0 Log Page data "); - fprintf(stderr, "with uuid index %d\n", uuid_index); - ret = -1; + ret = nvme_get_print_c0_eol_log(dev, + uuid_index, + namespace_id, + fmt); } - free(data); break; case WDC_NVME_ZN350_DEV_ID: case WDC_NVME_ZN350_DEV_ID_1: - data = (__u8 *)malloc(sizeof(__u8) * WDC_NVME_SMART_CLOUD_ATTR_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_SMART_CLOUD_ATTR_LOG_ID, - WDC_NVME_SMART_CLOUD_ATTR_LEN, data); - - if (strcmp(format, "json")) - nvme_show_status(ret); - - 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); + ret = nvme_get_print_ocp_cloud_smart_log(dev, + 0, + NVME_NSID_ALL, + fmt); break; case WDC_NVME_SN820CL_DEV_ID: /* Get the 0xC0 Extended Smart Cloud Attribute log data */ @@ -7296,7 +7108,7 @@ static int wdc_get_ca_log_page(nvme_root_t r, struct nvme_dev *dev, char *format { uint32_t read_device_id, read_vendor_id; struct wdc_ssd_ca_perf_stats *perf; - enum nvme_print_flags fmt; + nvme_print_flags_t fmt; __u32 cust_id; __u8 *data; int ret; @@ -7427,7 +7239,7 @@ static int wdc_get_c1_log_page(nvme_root_t r, struct nvme_dev *dev, struct wdc_log_page_subpage_header *sph; struct wdc_ssd_perf_stats *perf; struct wdc_log_page_header *l; - enum nvme_print_flags fmt; + nvme_print_flags_t fmt; int total_subpages; int skip_cnt = 4; __u8 *data; @@ -7484,7 +7296,7 @@ static int wdc_get_c1_log_page(nvme_root_t r, struct nvme_dev *dev, static int wdc_get_c3_log_page(nvme_root_t r, struct nvme_dev *dev, char *format) { struct wdc_ssd_latency_monitor_log *log_data; - enum nvme_print_flags fmt; + nvme_print_flags_t fmt; __u8 *data; int ret; int i; @@ -7556,7 +7368,7 @@ out: static int wdc_get_ocp_c1_log_page(nvme_root_t r, struct nvme_dev *dev, char *format) { struct wdc_ocp_c1_error_recovery_log *log_data; - enum nvme_print_flags fmt; + nvme_print_flags_t fmt; __u8 *data; int ret; int i; @@ -7587,9 +7399,10 @@ static int wdc_get_ocp_c1_log_page(nvme_root_t r, struct nvme_dev *dev, char *fo 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); + if ((log_data->log_page_version < 1) || + (log_data->log_page_version > 3)) { + fprintf(stderr, "ERROR: WDC: invalid error recovery log version - %d\n", + log_data->log_page_version); ret = -1; goto out; } @@ -7627,7 +7440,7 @@ out: static int wdc_get_ocp_c4_log_page(nvme_root_t r, struct nvme_dev *dev, char *format) { struct wdc_ocp_C4_dev_cap_log *log_data; - enum nvme_print_flags fmt; + nvme_print_flags_t fmt; __u8 *data; int ret; int i; @@ -7697,7 +7510,7 @@ out: static int wdc_get_ocp_c5_log_page(nvme_root_t r, struct nvme_dev *dev, char *format) { struct wdc_ocp_C5_unsupported_reqs *log_data; - enum nvme_print_flags fmt; + nvme_print_flags_t fmt; int ret; __u8 *data; int i; @@ -7767,7 +7580,7 @@ out: static int wdc_get_d0_log_page(nvme_root_t r, struct nvme_dev *dev, char *format) { struct wdc_ssd_d0_smart_log *perf; - enum nvme_print_flags fmt; + nvme_print_flags_t fmt; int ret = 0; __u8 *data; @@ -7852,7 +7665,7 @@ static const char *stringify_cloud_smart_log_thermal_status(__u8 status) return "unrecognized"; } -static void show_cloud_smart_log_json(struct ocp_cloud_smart_log *log) +static void wdc_show_cloud_smart_log_json(struct ocp_cloud_smart_log *log) { struct json_object *root; struct json_object *bad_user_nand_blocks; @@ -7862,6 +7675,8 @@ static void show_cloud_smart_log_json(struct ocp_cloud_smart_log *log) struct json_object *thermal_status; struct json_object *dssd_specific_ver; char buf[2 * sizeof(log->log_page_guid) + 3]; + char lowest_fr[sizeof(log->lowest_permitted_fw_rev) + 1]; + uint16_t smart_log_ver = (uint16_t)le16_to_cpu(log->log_page_version); bad_user_nand_blocks = json_create_object(); json_object_add_value_uint(bad_user_nand_blocks, "normalized", @@ -7927,7 +7742,8 @@ static void show_cloud_smart_log_json(struct ocp_cloud_smart_log *log) json_object_add_value_object(root, "user_data_erase_counts", user_data_erase_counts); json_object_add_value_object(root, "thermal_status", thermal_status); - json_object_add_value_object(root, "dssd_specific_ver", + if (smart_log_ver >= 3) + json_object_add_value_object(root, "dssd_specific_ver", dssd_specific_ver); json_object_add_value_uint(root, "pcie_correctable_error_count", le64_to_cpu(log->pcie_correctable_error_count)); @@ -7937,8 +7753,18 @@ static void show_cloud_smart_log_json(struct ocp_cloud_smart_log *log) log->percent_free_blocks); json_object_add_value_uint(root, "capacitor_health", le16_to_cpu(log->capacitor_health)); - sprintf(buf, "%c", log->nvme_errata_ver); - json_object_add_value_string(root, "nvme_errata_version", buf); + if (smart_log_ver >= 3) { + if (smart_log_ver >= 4) { + sprintf(buf, "%c", log->nvme_base_errata_ver); + json_object_add_value_string(root, "nvme_base_errata_version", buf); + sprintf(buf, "%c", log->nvme_cmd_set_errata_ver); + json_object_add_value_string(root, "nvme_cmd_set_errata_version", buf); + } else { + sprintf(buf, "%c", log->nvme_base_errata_ver); + json_object_add_value_string(root, "nvme_errata_version", buf); + } + } + json_object_add_value_uint(root, "unaligned_io", le64_to_cpu(log->unaligned_io)); json_object_add_value_uint(root, "security_version_number", @@ -7949,12 +7775,22 @@ static void show_cloud_smart_log_json(struct ocp_cloud_smart_log *log) le_to_float(log->plp_start_count, 16)); json_object_add_value_uint64(root, "endurance_estimate", le_to_float(log->endurance_estimate, 16)); - json_object_add_value_uint(root, "pcie_link_retraining_count", - le64_to_cpu(log->pcie_link_retraining_cnt)); - json_object_add_value_uint(root, "power_state_change_count", - le64_to_cpu(log->power_state_change_cnt)); + if (smart_log_ver >= 3) { + json_object_add_value_uint(root, "pcie_link_retraining_count", + le64_to_cpu(log->pcie_link_retraining_cnt)); + json_object_add_value_uint(root, "power_state_change_count", + le64_to_cpu(log->power_state_change_cnt)); + if (smart_log_ver >= 4) { + snprintf(lowest_fr, sizeof(lowest_fr), "%-.*s", + (int)sizeof(log->lowest_permitted_fw_rev), + log->lowest_permitted_fw_rev); + json_object_add_value_string(root, "lowest_permitted_fw_rev", lowest_fr); + } else + json_object_add_value_uint128(root, "hardware_revision", + le128_to_cpu((__u8 *)&log->lowest_permitted_fw_rev[0])); + } json_object_add_value_uint(root, "log_page_version", - le16_to_cpu(log->log_page_version)); + smart_log_ver); stringify_log_page_guid(log->log_page_guid, buf); json_object_add_value_string(root, "log_page_guid", buf); @@ -7963,11 +7799,13 @@ static void show_cloud_smart_log_json(struct ocp_cloud_smart_log *log) json_free_object(root); } -static void show_cloud_smart_log_normal(struct ocp_cloud_smart_log *log, struct nvme_dev *dev) +static void wdc_show_cloud_smart_log_normal(struct ocp_cloud_smart_log *log, + struct nvme_dev *dev) { char buf[2 * sizeof(log->log_page_guid) + 3]; + uint16_t smart_log_ver = (uint16_t)le16_to_cpu(log->log_page_version); - printf("Smart Extended Log for NVME device:%s\n", dev->name); + printf("SMART Cloud Attributes for NVMe device : %s\n", dev->name); printf("Physical Media Units Written : %'.0Lf\n", le_to_float(log->physical_media_units_written, 16)); printf("Physical Media Units Read : %'.0Lf\n", @@ -8002,14 +7840,16 @@ static void show_cloud_smart_log_normal(struct ocp_cloud_smart_log *log, struct stringify_cloud_smart_log_thermal_status(log->thermal_status.current_status)); printf("Thermal Throttling Status (Number of Events) : %" PRIu8 "\n", log->thermal_status.num_events); - printf("NVMe Major Version : %" PRIu8 "\n", - log->dssd_specific_ver.major_ver); - printf(" Minor Version : %" PRIu16 "\n", - le16_to_cpu(log->dssd_specific_ver.minor_ver)); - printf(" Point Version : %" PRIu16 "\n", - le16_to_cpu(log->dssd_specific_ver.point_ver)); - printf(" Errata Version : %" PRIu8 "\n", - log->dssd_specific_ver.errata_ver); + if (smart_log_ver >= 3) { + printf("NVMe Major Version : %" PRIu8 "\n", + log->dssd_specific_ver.major_ver); + printf(" Minor Version : %" PRIu16 "\n", + le16_to_cpu(log->dssd_specific_ver.minor_ver)); + printf(" Point Version : %" PRIu16 "\n", + le16_to_cpu(log->dssd_specific_ver.point_ver)); + printf(" Errata Version : %" PRIu8 "\n", + log->dssd_specific_ver.errata_ver); + } printf("PCIe Correctable Error Count : %" PRIu64 "\n", le64_to_cpu(log->pcie_correctable_error_count)); printf("Incomplete Shutdowns : %" PRIu32 "\n", @@ -8018,8 +7858,17 @@ static void show_cloud_smart_log_normal(struct ocp_cloud_smart_log *log, struct log->percent_free_blocks); printf("Capacitor Health : %" PRIu16 "%%\n", le16_to_cpu(log->capacitor_health)); - printf("NVMe Errata Version : %c\n", - log->nvme_errata_ver); + if (smart_log_ver >= 3) { + if (smart_log_ver >= 4) { + printf("NVMe Base Errata Version : %c\n", + log->nvme_base_errata_ver); + printf("NVMe Command Set Errata Version : %c\n", + log->nvme_cmd_set_errata_ver); + } else { + printf("NVMe Errata Version : %c\n", + log->nvme_base_errata_ver); + } + } printf("Unaligned IO : %" PRIu64 "\n", le64_to_cpu(log->unaligned_io)); printf("Security Version Number : %" PRIu64 "\n", @@ -8030,12 +7879,22 @@ static void show_cloud_smart_log_normal(struct ocp_cloud_smart_log *log, struct le_to_float(log->plp_start_count, 16)); printf("Endurance Estimate : %'.0Lf\n", le_to_float(log->endurance_estimate, 16)); - printf("PCIe Link Retraining Count : %" PRIu64 "\n", - le64_to_cpu(log->pcie_link_retraining_cnt)); - printf("Power State Change Count : %" PRIu64 "\n", - le64_to_cpu(log->power_state_change_cnt)); + if (smart_log_ver >= 3) { + printf("PCIe Link Retraining Count : %" PRIu64 "\n", + le64_to_cpu(log->pcie_link_retraining_cnt)); + printf("Power State Change Count : %" PRIu64 "\n", + le64_to_cpu(log->power_state_change_cnt)); + if (smart_log_ver >= 4) + printf("Lowest Permitted FW Revision : %-.*s\n", + (int)sizeof(log->lowest_permitted_fw_rev), + log->lowest_permitted_fw_rev); + else + printf("Hardware Revision : %s\n", + uint128_t_to_string(le128_to_cpu( + (__u8 *)&log->lowest_permitted_fw_rev[0]))); + } printf("Log Page Version : %" PRIu16 "\n", - le16_to_cpu(log->log_page_version)); + smart_log_ver); stringify_log_page_guid(log->log_page_guid, buf); printf("Log Page GUID : %s\n", buf); printf("\n\n"); @@ -8049,7 +7908,7 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command, const char *log_page_version = "Log Page Version: 0 = vendor, 1 = WDC"; const char *log_page_mask = "Log Page Mask, comma separated list: 0xC0, 0xC1, 0xCA, 0xD0"; const char *namespace_id = "desired namespace id"; - enum nvme_print_flags fmt; + nvme_print_flags_t fmt; struct nvme_dev *dev; nvme_root_t r; int ret = 0; @@ -8145,43 +8004,16 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command, "ERROR: WDC: Failure reading the C0 Log Page, ret = %d\n", ret); } else { - struct ocp_cloud_smart_log log; - char buf[2 * sizeof(log.log_page_guid) + 3]; - ret = validate_output_format(cfg.output_format, &fmt); if (ret < 0) { fprintf(stderr, "Invalid output format: %s\n", cfg.output_format); goto out; } - ret = nvme_get_log_simple(dev_fd(dev), - WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID, - sizeof(log), &log); - if (!ret) { - char *ptr = buf; - int i; - __u8 *guid = log.log_page_guid; - - memset(buf, 0, sizeof(char) * 19); - - ptr += sprintf(ptr, "0x"); - for (i = 0; i < 16; i++) - ptr += sprintf(ptr, "%x", guid[15 - i]); - if (strcmp(buf, "0xafd514c97c6f4f9ca4f2bfea2810afc5")) - fprintf(stderr, "Invalid GUID: %s\n", buf); - else { - if (fmt == BINARY) - d_raw((unsigned char *)&log, sizeof(log)); - else if (fmt == JSON) - show_cloud_smart_log_json(&log); - else - show_cloud_smart_log_normal(&log, dev); - } - } else if (ret > 0) { - nvme_show_status(ret); - } else { - perror("vs-smart-add-log"); - } + ret = nvme_get_print_ocp_cloud_smart_log(dev, + 0, + NVME_NSID_ALL, + fmt); } } if (((capabilities & (WDC_DRIVE_CAP_CA_LOG_PAGE)) == (WDC_DRIVE_CAP_CA_LOG_PAGE)) && @@ -8219,7 +8051,7 @@ static int wdc_vs_cloud_log(int argc, char **argv, struct command *command, { const char *desc = "Retrieve Cloud Log Smart/Health Information"; const char *namespace_id = "desired namespace id"; - enum nvme_print_flags fmt; + nvme_print_flags_t fmt; __u64 capabilities = 0; struct nvme_dev *dev; nvme_root_t r; @@ -8290,7 +8122,7 @@ static int wdc_vs_hw_rev_log(int argc, char **argv, struct command *command, { const char *desc = "Retrieve Hardware Revision Log Information"; const char *namespace_id = "desired namespace id"; - enum nvme_print_flags fmt; + nvme_print_flags_t fmt; __u64 capabilities = 0; struct nvme_dev *dev; int ret; @@ -8375,7 +8207,7 @@ static int wdc_vs_device_waf(int argc, char **argv, struct command *command, const char *desc = "Retrieve Device Write Amplication Factor"; const char *namespace_id = "desired namespace id"; struct nvme_smart_log smart_log; - enum nvme_print_flags fmt; + nvme_print_flags_t fmt; struct nvme_dev *dev; __u8 *data; nvme_root_t r; @@ -8932,7 +8764,7 @@ static int wdc_get_fw_act_history(nvme_root_t r, struct nvme_dev *dev, char *format) { struct wdc_fw_act_history_log_hdr *fw_act_history_hdr; - enum nvme_print_flags fmt; + nvme_print_flags_t fmt; int ret; __u8 *data; @@ -9016,7 +8848,7 @@ static int wdc_get_fw_act_history_C2(nvme_root_t r, struct nvme_dev *dev, __u32 tot_entries = 0, num_entries = 0; __u32 vendor_id = 0, device_id = 0; __u32 cust_id = 0; - enum nvme_print_flags fmt; + nvme_print_flags_t fmt; __u8 *data; int ret; bool c2GuidMatch = false; @@ -10498,7 +10330,7 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command struct plugin *plugin) { const char *desc = "Retrieve Log Page Directory."; - enum nvme_print_flags fmt; + nvme_print_flags_t fmt; struct nvme_dev *dev; int ret = 0; nvme_root_t r; @@ -11158,7 +10990,7 @@ static void wdc_print_pcie_stats_json(struct wdc_vs_pcie_stats *pcie_stats) static int wdc_do_vs_nand_stats_sn810_2(struct nvme_dev *dev, char *format) { - enum nvme_print_flags fmt; + nvme_print_flags_t fmt; uint8_t *data = NULL; int ret; @@ -11197,7 +11029,7 @@ out: static int wdc_do_vs_nand_stats(struct nvme_dev *dev, char *format) { - enum nvme_print_flags fmt; + nvme_print_flags_t fmt; uint8_t *output = NULL; __u16 version = 0; int ret; @@ -11321,7 +11153,7 @@ static int wdc_vs_pcie_stats(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Retrieve PCIE statistics."; - enum nvme_print_flags fmt; + nvme_print_flags_t fmt; struct nvme_dev *dev; nvme_root_t r; int ret; @@ -11396,7 +11228,7 @@ static int wdc_vs_drive_info(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Send a vs-drive-info command."; - enum nvme_print_flags fmt; + nvme_print_flags_t fmt; nvme_root_t r; uint64_t capabilities = 0; struct nvme_dev *dev; @@ -11663,7 +11495,7 @@ static int wdc_vs_temperature_stats(int argc, char **argv, const char *desc = "Send a vs-temperature-stats command."; struct nvme_smart_log smart_log; struct nvme_id_ctrl id_ctrl; - enum nvme_print_flags fmt; + nvme_print_flags_t fmt; struct nvme_dev *dev; nvme_root_t r; uint64_t capabilities = 0; diff --git a/plugins/wdc/wdc-nvme.h b/plugins/wdc/wdc-nvme.h index 65d2de3..a18da16 100644 --- a/plugins/wdc/wdc-nvme.h +++ b/plugins/wdc/wdc-nvme.h @@ -5,7 +5,7 @@ #if !defined(WDC_NVME) || defined(CMD_HEADER_MULTI_READ) #define WDC_NVME -#define WDC_PLUGIN_VERSION "2.8.1" +#define WDC_PLUGIN_VERSION "2.9.1" #include "cmd.h" PLUGIN(NAME("wdc", "Western Digital vendor specific extensions", WDC_PLUGIN_VERSION), |