summaryrefslogtreecommitdiffstats
path: root/plugins/wdc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--plugins/wdc/wdc-nvme.c1251
-rw-r--r--plugins/wdc/wdc-nvme.h2
-rw-r--r--plugins/wdc/wdc-utils.c2
3 files changed, 502 insertions, 753 deletions
diff --git a/plugins/wdc/wdc-nvme.c b/plugins/wdc/wdc-nvme.c
index 8cbcf2e..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,
@@ -1383,6 +1359,11 @@ struct __packed wdc_fw_act_history_log_format_c2 {
__u8 log_page_guid[WDC_C2_GUID_LENGTH];
};
+static __u8 ocp_C2_guid[WDC_C2_GUID_LENGTH] = {
+ 0x6D, 0x79, 0x9A, 0x76, 0xB4, 0xDA, 0xF6, 0xA3,
+ 0xE2, 0x4D, 0xB2, 0x8A, 0xAC, 0xF3, 0x1C, 0xD1
+};
+
#define WDC_OCP_C4_GUID_LENGTH 16
#define WDC_DEV_CAP_LOG_BUF_LEN 4096
#define WDC_DEV_CAP_LOG_ID 0xC4
@@ -1726,7 +1707,6 @@ 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:
- 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 |
@@ -1743,19 +1723,12 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev)
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_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,
@@ -1816,9 +1789,7 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev)
break;
case WDC_NVME_SN840_DEV_ID:
- fallthrough;
case WDC_NVME_SN840_DEV_ID_1:
- fallthrough;
case WDC_NVME_SN860_DEV_ID:
/* verify the 0xC0 log page is supported */
if (wdc_nvme_check_supported_log_page(r, dev,
@@ -1826,7 +1797,6 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev)
capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE;
fallthrough;
case WDC_NVME_ZN540_DEV_ID:
- 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 |
@@ -1847,17 +1817,11 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev)
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,
@@ -1907,7 +1871,6 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev)
break;
case WDC_NVME_SN861_DEV_ID:
- fallthrough;
case WDC_NVME_SN861_DEV_ID_1:
capabilities |= (WDC_DRIVE_CAP_C0_LOG_PAGE |
WDC_DRIVE_CAP_C3_LOG_PAGE |
@@ -1921,6 +1884,7 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev)
WDC_DRIVE_CAP_INFO |
WDC_DRIVE_CAP_CLOUD_SSD_VERSION |
WDC_DRIVE_CAP_LOG_PAGE_DIR |
+ WDC_DRIVE_CAP_DRIVE_STATUS |
WDC_DRIVE_CAP_SET_LATENCY_MONITOR);
break;
@@ -1936,11 +1900,8 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev)
break;
case WDC_NVME_SN520_DEV_ID:
- fallthrough;
case WDC_NVME_SN520_DEV_ID_1:
- fallthrough;
case WDC_NVME_SN520_DEV_ID_2:
- fallthrough;
case WDC_NVME_SN810_DEV_ID:
capabilities = WDC_DRIVE_CAP_DUI_DATA;
break;
@@ -2010,19 +1971,14 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev)
case WDC_NVME_SN8000S_DEV_ID:
fallthrough;
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:
- 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 |
@@ -2450,23 +2406,32 @@ static bool get_dev_mgment_cbs_data(nvme_root_t r, struct nvme_dev *dev,
uuid_index = index + 1;
}
- if (!uuid_index && needs_c2_log_page_check(device_id)) {
- /* In certain devices that don't support UUID lists, there are multiple
- * definitions of the C2 logpage. In those cases, the code
- * needs to try two UUID indexes and use an identification algorithm
- * to determine which is returning the correct log page data.
- */
- uuid_ix = 1;
- }
+ if (uuid_present) {
+ /* use the uuid index found above */
+ found = get_dev_mgmt_log_page_lid_data(dev, cbs_data, lid, log_id, uuid_index);
+ } else if (device_id == WDC_NVME_ZN350_DEV_ID || device_id == WDC_NVME_ZN350_DEV_ID_1) {
+ uuid_index = 0;
+ found = get_dev_mgmt_log_page_lid_data(dev, cbs_data, lid, log_id, uuid_index);
+ } else {
+ if (!uuid_index && needs_c2_log_page_check(device_id)) {
+ /* In certain devices that don't support UUID lists, there are multiple
+ * definitions of the C2 logpage. In those cases, the code
+ * needs to try two UUID indexes and use an identification algorithm
+ * to determine which is returning the correct log page data.
+ */
+ uuid_ix = 1;
+ }
- found = get_dev_mgmt_log_page_lid_data(dev, cbs_data, lid, log_id, uuid_ix);
+ found = get_dev_mgmt_log_page_lid_data(dev, cbs_data, lid, log_id, uuid_ix);
- if (!found) {
- /* not found with uuid = 1 try with uuid = 0 */
- uuid_ix = 0;
- fprintf(stderr, "Not found, requesting log page with uuid_index %d\n", uuid_index);
+ if (!found) {
+ /* not found with uuid = 1 try with uuid = 0 */
+ uuid_ix = 0;
+ fprintf(stderr, "Not found, requesting log page with uuid_index %d\n",
+ uuid_index);
- found = get_dev_mgmt_log_page_lid_data(dev, cbs_data, lid, log_id, uuid_ix);
+ found = get_dev_mgmt_log_page_lid_data(dev, cbs_data, lid, log_id, uuid_ix);
+ }
}
return found;
@@ -3722,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;
@@ -4692,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);
@@ -4722,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);
@@ -4766,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--) {
@@ -4825,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");
@@ -4839,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));
@@ -4849,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];
@@ -5538,17 +5546,18 @@ static void wdc_print_fw_act_history_log_normal(__u8 *data, int num_entries,
char previous_fw[9];
char new_fw[9];
char commit_action_bin[8];
- char time_str[11];
+ char time_str[100];
__u16 oldestEntryIdx = 0, entryIdx = 0;
+ uint64_t timestamp;
+ __u64 timestamp_sec;
char *null_fw = "--------";
- memset((void *)time_str, 0, 11);
+ memset((void *)time_str, '\0', 100);
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 ||
- vendor_id == WDC_NVME_SNDK_VID ||
- wdc_is_sn861(device_id)) {
+ 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");
@@ -5589,48 +5598,33 @@ static void wdc_print_fw_act_history_log_normal(__u8 *data, int num_entries,
memcpy(new_fw, null_fw, 8);
printf("%5"PRIu16"", (uint16_t)le16_to_cpu(fw_act_history_entry->entry[entryIdx].fw_act_hist_entries));
+
+ timestamp = (0x0000FFFFFFFFFFFF &
+ le64_to_cpu(
+ fw_act_history_entry->entry[entryIdx].timestamp));
+ timestamp_sec = timestamp / 1000;
if (cust_id == WDC_CUSTOMER_ID_0x1005) {
printf(" ");
memset((void *)time_str, 0, 9);
- sprintf((char *)time_str, "%04d:%02d:%02d", (int)(le64_to_cpu(fw_act_history_entry->entry[entryIdx].timestamp)/3600),
- (int)((le64_to_cpu(fw_act_history_entry->entry[entryIdx].timestamp%3600)/60)),
- (int)(le64_to_cpu(fw_act_history_entry->entry[entryIdx].timestamp%60)));
+ sprintf((char *)time_str, "%"PRIu32":%u:%u",
+ (__u32)(timestamp_sec/3600),
+ (__u8)(timestamp_sec%3600/60),
+ (__u8)(timestamp_sec%60));
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));
+ sprintf((char *)time_str, "%"PRIu32":%u:%u",
+ (__u32)((timestamp_sec/3600)%24),
+ (__u8)((timestamp_sec/60)%60),
+ (__u8)(timestamp_sec%60));
printf("%s", time_str);
printf(" ");
- } else if (wdc_is_sn861(device_id)) {
- printf(" ");
- char timestamp[20];
- __u64 hour;
- __u8 min;
- __u8 sec;
- __u64 timestamp_sec;
-
- timestamp_sec =
- le64_to_cpu(fw_act_history_entry->entry[entryIdx].timestamp)
- / 1000;
- hour = timestamp_sec / 3600;
- min = (timestamp_sec % 3600) / 60;
- sec = timestamp_sec % 60;
-
- sprintf(timestamp,
- "%"PRIu64":%02"PRIu8":%02"PRIu8,
- (uint64_t)hour, min, sec);
- printf("%-11s", timestamp);
- printf(" ");
} else {
printf(" ");
- uint64_t timestamp = (0x0000FFFFFFFFFFFF & le64_to_cpu(fw_act_history_entry->entry[entryIdx].timestamp));
-
printf("%16"PRIu64"", timestamp);
printf(" ");
}
@@ -5735,13 +5729,15 @@ static void wdc_print_fw_act_history_log_json(__u8 *data, int num_entries,
char new_fw[9];
char commit_action_bin[8];
char fail_str[32];
- char time_str[11];
+ char time_str[100];
char ext_time_str[20];
+ uint64_t timestamp;
+ __u64 timestamp_sec;
memset((void *)previous_fw, 0, 9);
memset((void *)new_fw, 0, 9);
memset((void *)commit_action_bin, 0, 8);
- memset((void *)time_str, 0, 11);
+ memset((void *)time_str, '\0', 100);
memset((void *)ext_time_str, 0, 20);
memset((void *)fail_str, 0, 11);
char *null_fw = "--------";
@@ -5781,33 +5777,25 @@ static void wdc_print_fw_act_history_log_json(__u8 *data, int num_entries,
json_object_add_value_int(root, "Entry",
le16_to_cpu(fw_act_history_entry->entry[entryIdx].fw_act_hist_entries));
+ timestamp = (0x0000FFFFFFFFFFFF &
+ le64_to_cpu(
+ fw_act_history_entry->entry[entryIdx].timestamp));
+ timestamp_sec = timestamp / 1000;
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),
- (int)((le64_to_cpu(fw_act_history_entry->entry[entryIdx].timestamp%3600)/60)),
- (int)(le64_to_cpu(fw_act_history_entry->entry[entryIdx].timestamp%60)));
+ sprintf((char *)time_str, "%"PRIu32":%u:%u",
+ (__u32)(timestamp_sec/3600),
+ (__u8)(timestamp_sec%3600/60),
+ (__u8)(timestamp_sec%60));
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));
+ sprintf((char *)time_str, "%"PRIu32":%u:%u",
+ (__u32)((timestamp_sec/3600)%24),
+ (__u8)((timestamp_sec/60)%60),
+ (__u8)(timestamp_sec%60));
json_object_add_value_string(root, "Power on Hour", time_str);
- } else if (wdc_is_sn861(device_id)) {
- __u64 timestamp_sec =
- le64_to_cpu(fw_act_history_entry->entry[entryIdx].timestamp)
- / 1000;
-
- sprintf((char *)ext_time_str,
- "%"PRIu64":%02"PRIu8":%02"PRIu8,
- (uint64_t)(__u64)(timestamp_sec/3600),
- (__u8)((timestamp_sec%3600)/60),
- (__u8)(timestamp_sec%60));
- json_object_add_value_string(root, "Power on Hour", ext_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);
}
@@ -5906,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;
@@ -6587,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)
{
@@ -6825,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;
@@ -6849,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;
@@ -6863,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;
@@ -6983,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) {
@@ -6996,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;
@@ -7029,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;
@@ -7047,123 +6891,42 @@ static int wdc_get_c0_log_page(nvme_root_t r, struct nvme_dev *dev, char *format
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_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:
ret = wdc_get_c0_log_page_sn(r, dev, uuid_index, format, namespace_id, fmt);
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:
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:
- fallthrough;
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 */
@@ -7345,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;
@@ -7405,17 +7168,11 @@ static int wdc_get_ca_log_page(nvme_root_t r, struct nvme_dev *dev, char *format
}
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) {
data = (__u8 *)malloc(sizeof(__u8) * WDC_FB_CA_LOG_BUF_LEN);
@@ -7482,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;
@@ -7539,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;
@@ -7611,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;
@@ -7642,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;
}
@@ -7682,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;
@@ -7752,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;
@@ -7822,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;
@@ -7907,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;
@@ -7917,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",
@@ -7982,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));
@@ -7992,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",
@@ -8004,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);
@@ -8018,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",
@@ -8057,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",
@@ -8073,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",
@@ -8085,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");
@@ -8104,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;
@@ -8200,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)) &&
@@ -8274,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;
@@ -8345,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;
@@ -8430,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;
@@ -8987,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;
@@ -9071,9 +8848,10 @@ 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;
if (!wdc_check_device(r, dev))
return -1;
@@ -9102,29 +8880,40 @@ static int wdc_get_fw_act_history_C2(nvme_root_t r, struct nvme_dev *dev,
nvme_show_status(ret);
if (!ret) {
- /* parse the data */
+ /* Get the log page data and verify the GUID */
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 */
- if (!wdc_is_sn861(device_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__);
- ret = -1;
- goto freeData;
+ c2GuidMatch = !memcmp(ocp_C2_guid,
+ fw_act_history_log->log_page_guid,
+ WDC_C2_GUID_LENGTH);
+
+ if (c2GuidMatch) {
+ /* parse the data */
+ tot_entries = le32_to_cpu(fw_act_history_log->num_entries);
+
+ if (tot_entries > 0) {
+ /* get the FW customer id */
+ if (!wdc_is_sn861(device_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__);
+ ret = -1;
+ goto freeData;
+ }
}
+ 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, device_id);
+ } else {
+ fprintf(stderr, "INFO: WDC: No entries found.\n");
+ ret = 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, device_id);
- } else {
- fprintf(stderr, "INFO: WDC: No FW Activate History entries found.\n");
- ret = 0;
+ } else {
+ fprintf(stderr, "ERROR: WDC: Invalid C2 log page GUID\n");
+ ret = -1;
}
} else {
fprintf(stderr, "ERROR: WDC: Unable to read FW Activate History Log Page data\n");
@@ -9143,7 +8932,7 @@ static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *com
__u64 capabilities = 0;
struct nvme_dev *dev;
nvme_root_t r;
- int ret;
+ int ret = -1;
struct config {
char *output_format;
@@ -9171,61 +8960,23 @@ static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *com
}
if (capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY) {
- int uuid_index = 0;
- bool c0GuidMatch = false;
- __u8 *data;
- int i;
-
- /*
- * 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));
+ __u32 cust_fw_id = 0;
+ /* get the FW customer id */
+ cust_fw_id = wdc_get_fw_cust_id(r, dev);
+ if (cust_fw_id == WDC_INVALID_CUSTOMER_ID) {
+ fprintf(stderr, "%s: ERROR: WDC: invalid customer id\n", __func__);
ret = -1;
goto out;
}
- /* 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 = 0xFFFFFFFF,
- .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 (!ret) {
- /* Verify GUID matches */
- for (i = 0; i < 16; i++) {
- if (scao_guid[i] != data[SCAO_LPG + i]) {
- c0GuidMatch = false;
- break;
- }
- }
-
- if (i == 16)
- c0GuidMatch = true;
- }
-
- free(data);
- if (c0GuidMatch)
+ if ((cust_fw_id == WDC_CUSTOMER_ID_0x1004) ||
+ (cust_fw_id == WDC_CUSTOMER_ID_0x1008) ||
+ (cust_fw_id == WDC_CUSTOMER_ID_0x1005) ||
+ (cust_fw_id == WDC_CUSTOMER_ID_0x1304))
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 {
+ } else if (capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_C2) {
ret = wdc_get_fw_act_history_C2(r, dev, cfg.output_format);
}
@@ -9648,10 +9399,10 @@ static int wdc_fetch_log_file_from_device(struct nvme_dev *dev, __u32 fileId,
__u16 spiDestn, __u64 fileSize, __u8 *dataBuffer)
{
int ret = WDC_STATUS_FAILURE;
- __u32 chunckSize = WDC_DE_VU_READ_BUFFER_STANDARD_OFFSET;
- __u32 maximumTransferLength = 0;
- __u32 buffSize = 0;
- __u64 offsetIdx = 0;
+ __u32 chunckSize = WDC_DE_VU_READ_BUFFER_STANDARD_OFFSET;
+ __u32 maximumTransferLength = 0;
+ __u32 buffSize = 0;
+ __u64 offsetIdx = 0;
if (!dev || !dataBuffer || !fileSize) {
ret = WDC_STATUS_INVALID_PARAMETER;
@@ -9699,18 +9450,17 @@ end:
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;
- __u32 readBufferLen = 0;
- __u32 lastPktReadBufferLen = 0;
- __u32 maxTransferLen = 0;
- __u32 dumptraceSize = 0;
- __u32 chunkSize = 0;
- __u32 chunks = 0;
- __u32 offset = 0;
- __u8 loop = 0;
- __u16 i = 0;
- __u32 maximumTransferLength = 0;
+ int ret = WDC_STATUS_FAILURE;
+ __u8 *readBuffer = NULL;
+ __u32 readBufferLen = 0;
+ __u32 lastPktReadBufferLen = 0;
+ __u32 maxTransferLen = 0;
+ __u32 dumptraceSize = 0;
+ __u32 chunkSize;
+ __u32 chunks;
+ __u32 offset;
+ __u32 i;
+ __u32 maximumTransferLength = 0;
if (!dev || !binFileName || !filePath) {
ret = WDC_STATUS_INVALID_PARAMETER;
@@ -9759,7 +9509,7 @@ static int wdc_de_get_dump_trace(struct nvme_dev *dev, char *filePath, __u16 bin
}
for (i = 0; i < chunks; i++) {
- offset = ((i*chunkSize) / 4);
+ offset = (i * chunkSize) / 4;
/* Last loop call, Assign readBufferLen to read only left over bytes */
if (i == (chunks - 1))
@@ -9774,7 +9524,7 @@ static int wdc_de_get_dump_trace(struct nvme_dev *dev, char *filePath, __u16 bin
break;
}
}
- } while (loop);
+ } while (0);
if (ret == WDC_STATUS_SUCCESS) {
ret = wdc_WriteToFile(binFileName, (char *)readBuffer, dumptraceSize);
@@ -10580,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;
@@ -11240,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;
@@ -11279,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;
@@ -11403,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;
@@ -11478,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;
@@ -11678,7 +11428,6 @@ static int wdc_vs_drive_info(int argc, char **argv,
break;
case WDC_NVME_SN861_DEV_ID:
- fallthrough;
case WDC_NVME_SN861_DEV_ID_1:
data_len = sizeof(info);
num_dwords = data_len / 4;
@@ -11746,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 d3692bc..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.7.0"
+#define WDC_PLUGIN_VERSION "2.9.1"
#include "cmd.h"
PLUGIN(NAME("wdc", "Western Digital vendor specific extensions", WDC_PLUGIN_VERSION),
diff --git a/plugins/wdc/wdc-utils.c b/plugins/wdc/wdc-utils.c
index 414a06a..1b52e7c 100644
--- a/plugins/wdc/wdc-utils.c
+++ b/plugins/wdc/wdc-utils.c
@@ -192,5 +192,5 @@ bool wdc_CheckUuidListSupport(struct nvme_dev *dev, struct nvme_id_uuid_list *uu
bool wdc_UuidEqual(struct nvme_id_uuid_list_entry *entry1, struct nvme_id_uuid_list_entry *entry2)
{
- return !memcmp(entry1, entry2, NVME_UUID_LEN);
+ return !memcmp(entry1->uuid, entry2->uuid, NVME_UUID_LEN);
}