summaryrefslogtreecommitdiffstats
path: root/plugins/wdc/wdc-nvme.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/wdc/wdc-nvme.c')
-rw-r--r--plugins/wdc/wdc-nvme.c1894
1 files changed, 1689 insertions, 205 deletions
diff --git a/plugins/wdc/wdc-nvme.c b/plugins/wdc/wdc-nvme.c
index 486ee36..5be7e11 100644
--- a/plugins/wdc/wdc-nvme.c
+++ b/plugins/wdc/wdc-nvme.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2015-2018 Western Digital Corporation or its affiliates.
*
@@ -79,6 +80,8 @@
#define WDC_NVME_SN560_DEV_ID_1 0x2712
#define WDC_NVME_SN560_DEV_ID_2 0x2713
#define WDC_NVME_SN560_DEV_ID_3 0x2714
+#define WDC_NVME_SN860_DEV_ID 0x2730
+#define WDC_NVME_SN550_DEV_ID 0x2708
#define WDC_NVME_SXSLCL_DEV_ID 0x2001
#define WDC_NVME_SN520_DEV_ID 0x5003
#define WDC_NVME_SN520_DEV_ID_1 0x5004
@@ -96,6 +99,7 @@
#define WDC_NVME_ZN350_DEV_ID 0x5010
#define WDC_NVME_ZN350_DEV_ID_1 0x5018
#define WDC_NVME_SN810_DEV_ID 0x5011
+#define WDC_NVME_SN820CL_DEV_ID 0x5037
#define WDC_DRIVE_CAP_CAP_DIAG 0x0000000000000001
#define WDC_DRIVE_CAP_INTERNAL_LOG 0x0000000000000002
@@ -125,8 +129,10 @@
#define WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY 0x0000000002000000
#define WDC_DRIVE_CAP_CLOUD_SSD_VERSION 0x0000000004000000
#define WDC_DRIVE_CAP_PCIE_STATS 0x0000000008000000
-#define WDC_DRIVE_CAP_INFO_2 0x0000000010000000
+#define WDC_DRIVE_CAP_HW_REV_LOG_PAGE 0x0000000010000000
#define WDC_DRIVE_CAP_C3_LOG_PAGE 0x0000000020000000
+#define WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION 0x0000000040000000
+#define WDC_DRIVE_CAP_CLOUD_LOG_PAGE 0x0000000080000000
#define WDC_DRIVE_CAP_DRIVE_ESSENTIALS 0x0000000100000000
#define WDC_DRIVE_CAP_DUI_DATA 0x0000000200000000
@@ -136,6 +142,7 @@
#define WDC_DRIVE_CAP_OCP_C1_LOG_PAGE 0x0000002000000000
#define WDC_DRIVE_CAP_OCP_C4_LOG_PAGE 0x0000004000000000
#define WDC_DRIVE_CAP_OCP_C5_LOG_PAGE 0x0000008000000000
+#define WDC_DRIVE_CAP_DEVICE_WAF 0x0000010000000000
#define WDC_DRIVE_CAP_SMART_LOG_MASK (WDC_DRIVE_CAP_C0_LOG_PAGE | WDC_DRIVE_CAP_C1_LOG_PAGE | \
WDC_DRIVE_CAP_CA_LOG_PAGE | WDC_DRIVE_CAP_D0_LOG_PAGE)
#define WDC_DRIVE_CAP_CLEAR_PCIE_MASK (WDC_DRIVE_CAP_CLEAR_PCIE | \
@@ -350,6 +357,7 @@ static __u8 wdc_lat_mon_guid[WDC_C3_GUID_LENGTH] = { 0x92, 0x7a, 0xc0, 0x8c,
#define WDC_LOG_ID_C0 0xC0
#define WDC_LOG_ID_C1 0xC1
#define WDC_LOG_ID_C2 WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE
+#define WDC_LOG_ID_C3 0xC3
#define WDC_LOG_ID_C4 0xC4
#define WDC_LOG_ID_C5 0xC5
#define WDC_LOG_ID_C6 0xC6
@@ -487,6 +495,121 @@ typedef enum
WDC_DE_TYPE_ALL = 0xFFFFFFF,
} WDC_DRIVE_ESSENTIAL_TYPE;
+#define WDC_C0_GUID_LENGTH 16
+#define WDC_SCA_V1_NAND_STATS 0x1
+#define WDC_SCA_V1_ALL 0xF
+typedef enum
+{
+ SCAO_V1_PMUWT = 0, /* Physical media units written TLC */
+ SCAO_V1_PMUWS = 16, /* Physical media units written SLC */
+ SCAO_V1_BUNBN = 32, /* Bad user nand blocks normalized */
+ SCAO_V1_BUNBR = 34, /* Bad user nand blocks raw */
+ SCAO_V1_XRC = 40, /* XOR recovery count */
+ SCAO_V1_UREC = 48, /* Uncorrectable read error count */
+ SCAO_V1_EECE = 56, /* End to end corrected errors */
+ SCAO_V1_EEDE = 64, /* End to end detected errors */
+ SCAO_V1_EEUE = 72, /* End to end uncorrected errors */
+ SCAO_V1_SDPU = 80, /* System data percent used */
+ SCAO_V1_MNUDEC = 84, /* Min User data erase counts (TLC) */
+ SCAO_V1_MXUDEC = 92, /* Max User data erase counts (TLC) */
+ SCAO_V1_AVUDEC = 100, /* Average User data erase counts (TLC) */
+ SCAO_V1_MNEC = 108, /* Min Erase counts (SLC) */
+ SCAO_V1_MXEC = 116, /* Max Erase counts (SLC) */
+ SCAO_V1_AVEC = 124, /* Average Erase counts (SLC) */
+ SCAO_V1_PFCN = 132, /* Program fail count normalized */
+ SCAO_V1_PFCR = 134, /* Program fail count raw */
+ SCAO_V1_EFCN = 140, /* Erase fail count normalized */
+ SCAO_V1_EFCR = 142, /* Erase fail count raw */
+ SCAO_V1_PCEC = 148, /* PCIe correctable error count */
+ SCAO_V1_PFBU = 156, /* Percent free blocks (User) */
+ SCAO_V1_SVN = 160, /* Security Version Number */
+ SCAO_V1_PFBS = 168, /* Percent free blocks (System) */
+ SCAO_V1_DCC = 172, /* Deallocate Commands Completed */
+ SCAO_V1_TNU = 188, /* Total Namespace Utilization */
+ SCAO_V1_FCC = 196, /* Format NVM Commands Completed */
+ SCAO_V1_BBPG = 198, /* Background Back-Pressure Gauge */
+ SCAO_V1_SEEC = 202, /* Soft ECC error count */
+ SCAO_V1_RFSC = 210, /* Refresh count */
+ SCAO_V1_BSNBN = 218, /* Bad system nand blocks normalized */
+ SCAO_V1_BSNBR = 220, /* Bad system nand blocks raw */
+ SCAO_V1_EEST = 226, /* Endurance estimate */
+ SCAO_V1_TTC = 242, /* Thermal throttling count */
+ SCAO_V1_UIO = 244, /* Unaligned I/O */
+ SCAO_V1_PMUR = 252, /* Physical media units read */
+ SCAO_V1_RTOC = 268, /* Read command timeout count */
+ SCAO_V1_WTOC = 272, /* Write command timeout count */
+ SCAO_V1_TTOC = 276, /* Trim command timeout count */
+ SCAO_V1_PLRC = 284, /* PCIe Link Retraining Count */
+ SCAO_V1_PSCC = 292, /* Power State Change Count */
+ SCAO_V1_MAVF = 300, /* Boot SSD major version field */
+ SCAO_V1_MIVF = 302, /* Boot SSD minor version field */
+ SCAO_V1_PVF = 304, /* Boot SSD point version field */
+ SCAO_V1_EVF = 306, /* Boot SSD errata version field */
+ SCAO_V1_FTLUS = 308, /* FTL Unit Size */
+ SCAO_V1_TCGOS = 312, /* TCG Ownership Status */
+
+ SCAO_V1_LPV = 494, /* Log page version - 0x0001 */
+ SCAO_V1_LPG = 496, /* Log page GUID */
+} SMART_CLOUD_ATTRIBUTE_OFFSETS_V1;
+
+static __u8 ext_smart_guid[WDC_C0_GUID_LENGTH] = { 0x65, 0x43, 0x88, 0x78, 0xAC, 0xD8, 0x78, 0xA1,
+ 0x66, 0x42, 0x1E, 0x0F, 0x92, 0xD7, 0x6D, 0xC4 };
+
+typedef struct __attribute__((__packed__)) wdc_nvme_ext_smart_log
+{
+ __u8 ext_smart_pmuwt[16]; /* 000 Physical media units written TLC */
+ __u8 ext_smart_pmuws[16]; /* 016 Physical media units written SLC */
+ __u8 ext_smart_bunbc[8]; /* 032 Bad user nand block count */
+ __u64 ext_smart_xrc; /* 040 XOR recovery count */
+ __u64 ext_smart_urec; /* 048 Uncorrectable read error count */
+ __u64 ext_smart_eece; /* 056 End to end corrected errors */
+ __u64 ext_smart_eede; /* 064 End to end detected errors */
+ __u64 ext_smart_eeue; /* 072 End to end uncorrected errors */
+ __u8 ext_smart_sdpu; /* 080 System data percent used */
+ __u8 ext_smart_rsvd1[3]; /* 081 reserved */
+ __u64 ext_smart_mnudec; /* 084 Min User data erase counts (TLC) */
+ __u64 ext_smart_mxudec; /* 092 Max User data erase counts (TLC) */
+ __u64 ext_smart_avudec; /* 100 Average User data erase counts (TLC) */
+ __u64 ext_smart_mnec; /* 108 Min Erase counts (SLC) */
+ __u64 ext_smart_mxec; /* 116 Max Erase counts (SLC) */
+ __u64 ext_smart_avec; /* 124 Average Erase counts (SLC) */
+ __u8 ext_smart_pfc[8]; /* 132 Program fail count */
+ __u8 ext_smart_efc[8]; /* 140 Erase fail count */
+ __u64 ext_smart_pcec; /* 148 PCIe correctable error count */
+ __u8 ext_smart_pfbu; /* 156 Percent free blocks (User) */
+ __u8 ext_smart_rsvd2[3]; /* 157 reserved */
+ __u64 ext_smart_svn; /* 160 Security Version Number */
+ __u8 ext_smart_pfbs; /* 168 Percent free blocks (System) */
+ __u8 ext_smart_rsvd3[3]; /* 169 reserved */
+ __u8 ext_smart_dcc[16]; /* 172 Deallocate Commands Completed */
+ __u64 ext_smart_tnu; /* 188 Total Namespace Utilization */
+ __u16 ext_smart_fcc; /* 196 Format NVM Commands Completed */
+ __u8 ext_smart_bbpg; /* 198 Background Back-Pressure Gauge */
+ __u8 ext_smart_rsvd4[3]; /* 199 reserved */
+ __u64 ext_smart_seec; /* 202 Soft ECC error count */
+ __u64 ext_smart_rfsc; /* 210 Refresh count */
+ __u8 ext_smart_bsnbc[8]; /* 218 Bad system nand block count */
+ __u8 ext_smart_eest[16]; /* 226 Endurance estimate */
+ __u16 ext_smart_ttc; /* 242 Thermal throttling count */
+ __u64 ext_smart_uio; /* 244 Unaligned I/O */
+ __u8 ext_smart_pmur[16]; /* 252 Physical media units read */
+ __u32 ext_smart_rtoc; /* 268 Read command timeout count */
+ __u32 ext_smart_wtoc; /* 272 Write command timeout count */
+ __u32 ext_smart_ttoc; /* 276 Trim command timeout count */
+ __u8 ext_smart_rsvd5[4]; /* 280 reserved */
+ __u64 ext_smart_plrc; /* 284 PCIe Link Retraining Count */
+ __u64 ext_smart_pscc; /* 292 Power State Change Count */
+ __u16 ext_smart_maj; /* 300 Boot SSD major version field */
+ __u16 ext_smart_min; /* 302 Boot SSD minor version field */
+ __u16 ext_smart_pt; /* 304 Boot SSD point version field */
+ __u16 ext_smart_err; /* 306 Boot SSD errata version field */
+ __u32 ext_smart_ftlus; /* 308 FTL Unit Size */
+ __u32 ext_smart_tcgos; /* 312 TCG Ownership Status */
+ __u8 ext_smart_rsvd6[178]; /* 316 reserved */
+ __u16 ext_smart_lpv; /* 494 Log page version - 0x0001 */
+ __u8 ext_smart_lpg[16]; /* 496 Log page GUID */
+} wdc_nvme_ext_smart_log;
+
typedef enum
{
SCAO_PMUW = 0, /* Physical media units written */
@@ -520,12 +643,11 @@ typedef enum
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_PLRC = 192, /* PCIe Link Retraining Count */
+ SCAO_PSCC = 200, /* Power State Change Count */
SCAO_LPV = 494, /* Log page version */
SCAO_LPG = 496, /* Log page GUID */
-} SMART_CLOUD_ATTRIBUTE_OFFSETS;
-
-#define WDC_C0_GUID_LENGTH 16
+} SMART_CLOUD_ATTRIBUTE_OFFSETS_V3;
static __u8 scao_guid[WDC_C0_GUID_LENGTH] = { 0xC5, 0xAF, 0x10, 0x28, 0xEA, 0xBF, 0xF2, 0xA4,
0x9C, 0x4F, 0x6F, 0x7C, 0xC9, 0x14, 0xD5, 0xAF };
@@ -542,6 +664,54 @@ typedef enum
EOL_RRER = 108, /* Raw Read Error Rate */
} EOL_LOG_PAGE_C0_OFFSETS;
+#define WDC_NVME_C6_GUID_LENGTH 16
+#define WDC_NVME_GET_HW_REV_LOG_OPCODE 0xc6
+#define WDC_NVME_HW_REV_LOG_PAGE_LEN 512
+
+typedef struct __attribute__((__packed__)) wdc_nvme_hw_rev_log
+{
+ __u8 hw_rev_gdr; /* 0 Global Device HW Revision */
+ __u8 hw_rev_ar; /* 1 ASIC HW Revision */
+ __u8 hw_rev_pbc_mc; /* 2 PCB Manufacturer Code */
+ __u8 hw_rev_dram_mc; /* 3 DRAM Manufacturer Code */
+ __u8 hw_rev_nand_mc; /* 4 NAND Manufacturer Code */
+ __u8 hw_rev_pmic1_mc; /* 5 PMIC 1 Manufacturer Code */
+ __u8 hw_rev_pmic2_mc; /* 6 PMIC 2 Manufacturer Code */
+ __u8 hw_rev_c1_mc; /* 7 Other Component 1 Manf Code */
+ __u8 hw_rev_c2_mc; /* 8 Other Component 2 Manf Code */
+ __u8 hw_rev_c3_mc; /* 9 Other Component 3 Manf Code */
+ __u8 hw_rev_c4_mc; /* 10 Other Component 4 Manf Code */
+ __u8 hw_rev_c5_mc; /* 11 Other Component 5 Manf Code */
+ __u8 hw_rev_c6_mc; /* 12 Other Component 6 Manf Code */
+ __u8 hw_rev_c7_mc; /* 13 Other Component 7 Manf Code */
+ __u8 hw_rev_c8_mc; /* 14 Other Component 8 Manf Code */
+ __u8 hw_rev_c9_mc; /* 15 Other Component 9 Manf Code */
+ __u8 hw_rev_rsrvd1[48]; /* 16 Reserved 48 bytes */
+ __u8 hw_rev_dev_mdi[16]; /* 64 Device Manf Detailed Info */
+ __u8 hw_rev_asic_di[16]; /* 80 ASIC Detailed Info */
+ __u8 hw_rev_pcb_di[16]; /* 96 PCB Detailed Info */
+ __u8 hw_rev_dram_di[16]; /* 112 DRAM Detailed Info */
+ __u8 hw_rev_nand_di[16]; /* 128 NAND Detailed Info */
+ __u8 hw_rev_pmic1_di[16]; /* 144 PMIC1 Detailed Info */
+ __u8 hw_rev_pmic2_di[16]; /* 160 PMIC2 Detailed Info */
+ __u8 hw_rev_c1_di[16]; /* 176 Component 1 Detailed Info */
+ __u8 hw_rev_c2_di[16]; /* 192 Component 2 Detailed Info */
+ __u8 hw_rev_c3_di[16]; /* 208 Component 3 Detailed Info */
+ __u8 hw_rev_c4_di[16]; /* 224 Component 4 Detailed Info */
+ __u8 hw_rev_c5_di[16]; /* 240 Component 5 Detailed Info */
+ __u8 hw_rev_c6_di[16]; /* 256 Component 6 Detailed Info */
+ __u8 hw_rev_c7_di[16]; /* 272 Component 7 Detailed Info */
+ __u8 hw_rev_c8_di[16]; /* 288 Component 8 Detailed Info */
+ __u8 hw_rev_c9_di[16]; /* 304 Component 9 Detailed Info */
+ __u8 hw_rev_sn[32]; /* 320 Serial Number */
+ __u8 hw_rev_rsrvd2[142]; /* 352 Reserved 143 bytes */
+ __u16 hw_rev_version; /* 494 Log Page Version */
+ __u8 hw_rev_guid[16]; /* 496 Log Page GUID */
+} wdc_nvme_hw_rev_log;
+
+static __u8 hw_rev_log_guid[WDC_NVME_C6_GUID_LENGTH] = { 0xAA, 0xB0, 0x05, 0xF5, 0x13, 0x5E, 0x48, 0x15,
+ 0xAB, 0x89, 0x05, 0xBA, 0x8B, 0xE2, 0xBF, 0x3C };
+
typedef struct __attribute__((__packed__)) _WDC_DE_VU_FILE_META_DATA
{
__u8 fileName[WDC_DE_FILE_NAME_SIZE];
@@ -1161,7 +1331,7 @@ static int wdc_get_pci_ids(nvme_root_t r, uint32_t *device_id,
fprintf(stderr, "%s: Read of pci vendor id failed\n", __func__);
return -1;
}
-
+ id[ret < 32 ? ret : 31] = '\0';
if (id[strlen(id) - 1] == '\n')
id[strlen(id) - 1] = '\0';
@@ -1181,7 +1351,7 @@ static int wdc_get_pci_ids(nvme_root_t r, uint32_t *device_id,
fprintf(stderr, "%s: Read of pci device id failed\n", __func__);
return -1;
}
-
+ id[ret < 32 ? ret : 31] = '\0';
if (id[strlen(id) - 1] == '\n')
id[strlen(id) - 1] = '\0';
@@ -1348,6 +1518,12 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, int fd) {
case WDC_NVME_SN640_DEV_ID_2:
/* FALLTHRU */
case WDC_NVME_SN640_DEV_ID_3:
+ /* FALLTHRU */
+ case WDC_NVME_SN560_DEV_ID_1:
+ /* FALLTHRU */
+ case WDC_NVME_SN560_DEV_ID_2:
+ /* FALLTHRU */
+ case WDC_NVME_SN560_DEV_ID_3:
/* verify the 0xC0 log page is supported */
if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE) == true) {
capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE;
@@ -1400,6 +1576,8 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, int fd) {
case WDC_NVME_SN840_DEV_ID:
/* FALLTHRU */
case WDC_NVME_SN840_DEV_ID_1:
+ /* FALLTHRU */
+ case WDC_NVME_SN860_DEV_ID:
/* verify the 0xC0 log page is supported */
if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE) == true) {
capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE;
@@ -1430,9 +1608,7 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, int fd) {
case WDC_NVME_SN650_DEV_ID_3:
case WDC_NVME_SN650_DEV_ID_4:
case WDC_NVME_SN655_DEV_ID:
- case WDC_NVME_SN560_DEV_ID_1:
- case WDC_NVME_SN560_DEV_ID_2:
- case WDC_NVME_SN560_DEV_ID_3:
+ case WDC_NVME_SN550_DEV_ID:
/* verify the 0xC0 log page is supported */
if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE) == true) {
capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE;
@@ -1440,7 +1616,7 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, int fd) {
capabilities |= (WDC_DRIVE_CAP_CAP_DIAG | WDC_DRIVE_CAP_INTERNAL_LOG |
WDC_DRIVE_CAP_DRIVE_STATUS | WDC_DRIVE_CAP_CLEAR_ASSERT |
- WDC_DRIVE_CAP_RESIZE | WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE |
+ WDC_DRIVE_CAP_RESIZE | WDC_DRIVE_CAP_CLEAR_PCIE |
WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY | WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY |
WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG | WDC_DRIVE_CAP_REASON_ID |
WDC_DRIVE_CAP_LOG_PAGE_DIR | WDC_DRIVE_CAP_INFO |
@@ -1470,12 +1646,19 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, int fd) {
case WDC_NVME_SN810_DEV_ID:
capabilities = WDC_DRIVE_CAP_DUI_DATA;
break;
+ case WDC_NVME_SN820CL_DEV_ID:
+ capabilities = WDC_DRIVE_CAP_DUI_DATA | WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION |
+ WDC_DRIVE_CAP_CLOUD_LOG_PAGE | WDC_DRIVE_CAP_C0_LOG_PAGE |
+ WDC_DRIVE_CAP_HW_REV_LOG_PAGE | WDC_DRIVE_CAP_INFO |
+ WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE | WDC_DRIVE_CAP_NAND_STATS |
+ WDC_DRIVE_CAP_DEVICE_WAF | WDC_DRIVE_CAP_TEMP_STATS;
+ break;
case WDC_NVME_SN720_DEV_ID:
capabilities = WDC_DRIVE_CAP_DUI_DATA | WDC_DRIVE_CAP_NAND_STATS | WDC_DRIVE_CAP_NS_RESIZE;
break;
case WDC_NVME_SN730A_DEV_ID:
- capabilities = WDC_DRIVE_CAP_DUI | WDC_DRIVE_CAP_NAND_STATS | WDC_DRIVE_CAP_INFO_2
- | WDC_DRIVE_CAP_TEMP_STATS | WDC_DRIVE_CAP_VUC_CLEAR_PCIE | WDC_DRIVE_CAP_PCIE_STATS;
+ capabilities = WDC_DRIVE_CAP_DUI | WDC_DRIVE_CAP_NAND_STATS | WDC_DRIVE_CAP_INFO |
+ WDC_DRIVE_CAP_TEMP_STATS | WDC_DRIVE_CAP_VUC_CLEAR_PCIE | WDC_DRIVE_CAP_PCIE_STATS;
break;
case WDC_NVME_SN740_DEV_ID:
case WDC_NVME_SN740_DEV_ID_1:
@@ -1628,6 +1811,7 @@ static int wdc_create_log_file(char *file, __u8 *drive_log_data,
ret = write(fd, drive_log_data, WRITE_SIZE);
if (ret < 0) {
fprintf (stderr, "ERROR : WDC: write : %s\n", strerror(errno));
+ close(fd);
return -1;
}
drive_log_data += WRITE_SIZE;
@@ -1637,11 +1821,13 @@ static int wdc_create_log_file(char *file, __u8 *drive_log_data,
ret = write(fd, drive_log_data, drive_log_length);
if (ret < 0) {
fprintf(stderr, "ERROR : WDC : write : %s\n", strerror(errno));
+ close(fd);
return -1;
}
if (fsync(fd) < 0) {
fprintf(stderr, "ERROR : WDC : fsync : %s\n", strerror(errno));
+ close(fd);
return -1;
}
close(fd);
@@ -2204,13 +2390,12 @@ static int wdc_do_cap_telemetry_log(int fd, char *file, __u32 bs, int type, int
if (err) {
fprintf(stderr, "ERROR : WDC : nvme_identify_ctrl() failed "
"0x%x\n", err);
- goto close_fd;
+ return err;
}
if (!(ctrl.lpa & 0x8)) {
fprintf(stderr, "Telemetry Host-Initiated and Telemetry Controller-Initiated log pages not supported\n");
- err = -EINVAL;
- goto close_fd;
+ return -EINVAL;
}
r = nvme_scan(NULL);
@@ -2232,15 +2417,13 @@ static int wdc_do_cap_telemetry_log(int fd, char *file, __u32 bs, int type, int
}
else {
fprintf(stderr, "%s: Controller initiated option telemetry log page disabled\n", __func__);
- err = -EINVAL;
- goto close_fd;
+ return -EINVAL;
}
}
else {
fprintf(stderr, "ERROR : WDC: Get telemetry option feature failed.");
nvme_show_status(err);
- err = -EPERM;
- goto close_fd;
+ return -EPERM;
}
}
else {
@@ -2249,22 +2432,19 @@ static int wdc_do_cap_telemetry_log(int fd, char *file, __u32 bs, int type, int
}
} else {
fprintf(stderr, "%s: Invalid type parameter; type = %d\n", __func__, type);
- err = -EINVAL;
- goto close_fd;
+ return -EINVAL;
}
if (!file) {
fprintf(stderr, "%s: Please provide an output file!\n", __func__);
- err = -EINVAL;
- goto close_fd;
+ return -EINVAL;
}
output = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (output < 0) {
fprintf(stderr, "%s: Failed to open output file %s: %s!\n",
__func__, file, strerror(errno));
- err = output;
- goto close_fd;
+ return output;
}
if (ctrl_init)
@@ -2274,9 +2454,10 @@ static int wdc_do_cap_telemetry_log(int fd, char *file, __u32 bs, int type, int
else
err = nvme_get_host_telemetry(fd, &log, data_area, &full_size);
- if (err < 0)
+ if (err < 0) {
perror("get-telemetry-log");
- else if (err > 0) {
+ goto close_output;
+ } else if (err > 0) {
nvme_show_status(err);
fprintf(stderr, "%s: Failed to acquire telemetry header!\n", __func__);
goto close_output;
@@ -2309,17 +2490,13 @@ static int wdc_do_cap_telemetry_log(int fd, char *file, __u32 bs, int type, int
if (fsync(output) < 0) {
fprintf(stderr, "ERROR : %s: fsync : %s\n", __func__, strerror(errno));
- return -1;
+ err = -1;
}
free(log);
close_output:
close(output);
-close_fd:
- close(fd);
-
return err;
-
}
static int wdc_do_cap_diag(nvme_root_t r, int fd, char *file,
@@ -2757,7 +2934,7 @@ static int wdc_cap_diag(int argc, char **argv, struct command *command,
char *size = "Data retrieval transfer size.";
char f[PATH_MAX] = {0};
__u32 xfer_size = 0;
- int fd;
+ int fd, ret = 0;
__u64 capabilities = 0;
struct config {
@@ -2776,30 +2953,40 @@ static int wdc_cap_diag(int argc, char **argv, struct command *command,
OPT_END()
};
- r = nvme_scan(NULL);
-
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0)
return fd;
+ r = nvme_scan(NULL);
+
if (cfg.file != NULL)
strncpy(f, cfg.file, PATH_MAX - 1);
if (cfg.xfer_size != 0)
xfer_size = cfg.xfer_size;
- if (wdc_get_serial_name(fd, f, PATH_MAX, "cap_diag") == -1) {
+ ret = wdc_get_serial_name(fd, f, PATH_MAX, "cap_diag");
+ if (ret) {
fprintf(stderr, "ERROR : WDC: failed to generate file name\n");
- return -1;
+ goto out;
+ }
+ if (cfg.file == NULL) {
+ if (strlen(f) > PATH_MAX - 5) {
+ fprintf(stderr, "ERROR : WDC: file name overflow\n");
+ ret = -1;
+ goto out;
+ }
+ strcat(f, ".bin");
}
- if (cfg.file == NULL)
- snprintf(f + strlen(f), PATH_MAX, "%s", ".bin");
capabilities = wdc_get_drive_capabilities(r, fd);
if ((capabilities & WDC_DRIVE_CAP_CAP_DIAG) == WDC_DRIVE_CAP_CAP_DIAG)
- return wdc_do_cap_diag(r, fd, f, xfer_size, 0, 0);
-
- fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
+ ret = wdc_do_cap_diag(r, fd, f, xfer_size, 0, 0);
+ else
+ fprintf(stderr,
+ "ERROR : WDC: unsupported device for this command\n");
+out:
nvme_free_tree(r);
- return 0;
+ close(fd);
+ return ret;
}
static int wdc_do_get_sn730_log_len(int fd, uint32_t *len_buf, uint32_t subopcode)
@@ -3047,7 +3234,7 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command
char fileSuffix[PATH_MAX] = {0};
nvme_root_t r;
__u32 xfer_size = 0;
- int fd;
+ int fd, ret = -1;
int telemetry_type = 0, telemetry_data_area = 0;
UtilsTimeInfo timeInfo;
__u8 timeStamp[MAX_PATH_LEN];
@@ -3089,16 +3276,14 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command
return fd;
r = nvme_scan(NULL);
- if (!wdc_check_device(r, fd)) {
- nvme_free_tree(r);
- return -1;
- }
+ if (!wdc_check_device(r, fd))
+ goto out;
+
if (cfg.xfer_size != 0)
xfer_size = cfg.xfer_size;
else {
fprintf(stderr, "ERROR : WDC : Invalid length\n");
- nvme_free_tree(r);
- return -1;
+ goto out;
}
if (cfg.file != NULL) {
@@ -3108,7 +3293,7 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command
verify_file = open(cfg.file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (verify_file < 0) {
fprintf(stderr, "ERROR : WDC: open : %s\n", strerror(errno));
- return -1;
+ goto out;
}
close(verify_file);
strncpy(f, cfg.file, PATH_MAX - 1);
@@ -3120,20 +3305,28 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command
timeInfo.hour, timeInfo.minute, timeInfo.second);
snprintf(fileSuffix, PATH_MAX, "_internal_fw_log_%s", (char*)timeStamp);
- if (wdc_get_serial_name(fd, f, PATH_MAX, fileSuffix) == -1) {
+ ret = wdc_get_serial_name(fd, f, PATH_MAX, fileSuffix);
+ if (ret) {
fprintf(stderr, "ERROR : WDC: failed to generate file name\n");
- return -1;
+ goto out;
}
}
- if (cfg.file == NULL)
- snprintf(f + strlen(f), PATH_MAX, "%s", ".bin");
+ if (cfg.file == NULL) {
+ if (strlen(f) > PATH_MAX - 5) {
+ fprintf(stderr, "ERROR : WDC: file name overflow\n");
+ ret = -1;
+ goto out;
+ }
+ strcat(f, ".bin");
+ }
fprintf(stderr, "%s: filename = %s\n", __func__, f);
if (cfg.data_area) {
if (cfg.data_area > 5 || cfg.data_area < 1) {
fprintf(stderr, "ERROR : WDC: Data area must be 1-5\n");
- return -1;
+ ret = -1;
+ goto out;
}
}
@@ -3152,7 +3345,8 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command
telemetry_data_area = cfg.data_area;
} else {
fprintf(stderr, "ERROR : WDC: Invalid type - Must be NONE, HOST or CONTROLLER\n");
- return -1;
+ ret = -1;
+ goto out;
}
capabilities = wdc_get_drive_capabilities(r, fd);
@@ -3160,8 +3354,9 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command
if (telemetry_data_area == 0)
telemetry_data_area = 3; /* Set the default DA to 3 if not specified */
- return wdc_do_cap_diag(r, fd, f, xfer_size,
- telemetry_type, telemetry_data_area);
+ ret = wdc_do_cap_diag(r, fd, f, xfer_size,
+ telemetry_type, telemetry_data_area);
+ goto out;
}
if ((capabilities & WDC_DRIVE_CAP_DUI) == WDC_DRIVE_CAP_DUI) {
if ((telemetry_type == WDC_TELEMETRY_TYPE_HOST) ||
@@ -3169,18 +3364,20 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command
if (telemetry_data_area == 0)
telemetry_data_area = 3; /* Set the default DA to 3 if not specified */
/* Get the desired telemetry log page */
- return wdc_do_cap_telemetry_log(fd, f, xfer_size, telemetry_type, telemetry_data_area);
- }
- else {
- if (cfg.data_area == 0) {
+ ret = wdc_do_cap_telemetry_log(fd, f, xfer_size,
+ telemetry_type, telemetry_data_area);
+ goto out;
+ } else {
+ if (cfg.data_area == 0)
cfg.data_area = 1;
- }
/* FW requirement - xfer size must be 256k for data area 4 */
if (cfg.data_area >= 4)
xfer_size = 0x40000;
- return wdc_do_cap_dui(fd, f, xfer_size, cfg.data_area,
- cfg.verbose, cfg.file_size, cfg.offset);
+ ret = wdc_do_cap_dui(fd, f, xfer_size, cfg.data_area,
+ cfg.verbose, cfg.file_size,
+ cfg.offset);
+ goto out;
}
}
if ((capabilities & WDC_DRIVE_CAP_DUI_DATA) == WDC_DRIVE_CAP_DUI_DATA){
@@ -3189,17 +3386,26 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command
if (telemetry_data_area == 0)
telemetry_data_area = 3; /* Set the default DA to 3 if not specified */
/* Get the desired telemetry log page */
- return wdc_do_cap_telemetry_log(fd, f, xfer_size, telemetry_type, telemetry_data_area);
- }
- else {
- return wdc_do_cap_dui(fd, f, xfer_size, WDC_NVME_DUI_MAX_DATA_AREA, cfg.verbose, 0, 0);
+ ret = wdc_do_cap_telemetry_log(fd, f, xfer_size,
+ telemetry_type, telemetry_data_area);
+ goto out;
+ } else {
+ ret = wdc_do_cap_dui(fd, f, xfer_size,
+ WDC_NVME_DUI_MAX_DATA_AREA,
+ cfg.verbose, 0, 0);
+ goto out;
}
}
if ((capabilities & WDC_SN730B_CAP_VUC_LOG) == WDC_SN730B_CAP_VUC_LOG)
- return wdc_do_sn730_get_and_tar(fd, f);
-
- fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
- return -1;
+ ret = wdc_do_sn730_get_and_tar(fd, f);
+ else {
+ fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
+ ret = -1;
+ }
+out:
+ nvme_free_tree(r);
+ close(fd);
+ return ret;
}
static int wdc_do_crash_dump(int fd, char *file, int type)
@@ -3277,6 +3483,7 @@ static int wdc_crash_dump(int fd, char *file, int type)
{
char f[PATH_MAX] = {0};
const char *dump_type;
+ int ret;
if (file != NULL) {
strncpy(f, file, PATH_MAX - 1);
@@ -3287,11 +3494,13 @@ static int wdc_crash_dump(int fd, char *file, int type)
else
dump_type = "_crash_dump";
- if (wdc_get_serial_name(fd, f, PATH_MAX, dump_type) == -1) {
+ ret = wdc_get_serial_name(fd, f, PATH_MAX, dump_type);
+ if (ret)
fprintf(stderr, "ERROR : WDC : failed to generate file name\n");
- return -1;
- }
- return wdc_do_crash_dump(fd, f, type);
+ else
+ ret = wdc_do_crash_dump(fd, f, type); \
+ close(fd);
+ return ret;
}
static int wdc_do_drive_log(int fd, char *file)
@@ -3365,6 +3574,7 @@ static int wdc_drive_log(int argc, char **argv, struct command *command,
if (!wdc_check_device(r, fd)) {
nvme_free_tree(r);
+ close(fd);
return -1;
}
capabilities = wdc_get_drive_capabilities(r, fd);
@@ -3376,14 +3586,14 @@ static int wdc_drive_log(int argc, char **argv, struct command *command,
if (cfg.file != NULL) {
strncpy(f, cfg.file, PATH_MAX - 1);
}
- if (wdc_get_serial_name(fd, f, PATH_MAX, "drive_log") == -1) {
+ ret = wdc_get_serial_name(fd, f, PATH_MAX, "drive_log");
+ if (ret)
fprintf(stderr, "ERROR : WDC : failed to generate file name\n");
- nvme_free_tree(r);
- return -1;
- }
- ret = wdc_do_drive_log(fd, f);
+ else
+ ret = wdc_do_drive_log(fd, f);
}
nvme_free_tree(r);
+ close(fd);
return ret;
}
@@ -3417,6 +3627,7 @@ static int wdc_get_crash_dump(int argc, char **argv, struct command *command,
if (!wdc_check_device(r, fd)) {
nvme_free_tree(r);
+ close(fd);
return -1;
}
@@ -3433,6 +3644,7 @@ static int wdc_get_crash_dump(int argc, char **argv, struct command *command,
}
}
nvme_free_tree(r);
+ close(fd);
return ret;
}
@@ -3466,6 +3678,7 @@ static int wdc_get_pfail_dump(int argc, char **argv, struct command *command,
if (!wdc_check_device(r, fd)) {
nvme_free_tree(r);
+ close(fd);
return -1;
}
@@ -3480,6 +3693,7 @@ static int wdc_get_pfail_dump(int argc, char **argv, struct command *command,
}
}
nvme_free_tree(r);
+ close(fd);
return ret;
}
@@ -3553,6 +3767,7 @@ static int wdc_purge(int argc, char **argv,
if (!wdc_check_device(r, fd)) {
nvme_free_tree(r);
+ close(fd);
return -1;
}
@@ -3584,6 +3799,7 @@ static int wdc_purge(int argc, char **argv,
nvme_show_status(ret);
}
nvme_free_tree(r);
+ close(fd);
return ret;
}
@@ -3610,6 +3826,7 @@ static int wdc_purge_monitor(int argc, char **argv,
r = nvme_scan(NULL);
if (!wdc_check_device(r, fd)) {
nvme_free_tree(r);
+ close(fd);
return -1;
}
@@ -3642,6 +3859,7 @@ static int wdc_purge_monitor(int argc, char **argv,
nvme_show_status(ret);
}
nvme_free_tree(r);
+ close(fd);
return ret;
}
@@ -4234,7 +4452,7 @@ static void wdc_print_bd_ca_log_normal(void *data)
__u8 *byte_raw;
if (bd_data->field_id == 0x00) {
- raw = (__u64*)&bd_data->raw_value[1];
+ raw = (__u64*)&bd_data->raw_value[0];
printf("Additional Smart Log for NVME device:%s namespace-id:%x\n",
devicename, WDC_DE_GLOBAL_NSID);
printf("key normalized raw\n");
@@ -4245,7 +4463,7 @@ static void wdc_print_bd_ca_log_normal(void *data)
}
bd_data++;
if (bd_data->field_id == 0x01) {
- raw = (__u64*)&bd_data->raw_value[1];
+ raw = (__u64*)&bd_data->raw_value[0];
printf("erase_fail_count : %3"PRIu8"%% %"PRIu64"\n",
bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF));
} else {
@@ -4266,7 +4484,7 @@ static void wdc_print_bd_ca_log_normal(void *data)
}
bd_data++;
if (bd_data->field_id == 0x03) {
- raw = (__u64*)&bd_data->raw_value[1];
+ raw = (__u64*)&bd_data->raw_value[0];
printf("end_to_end_error_detection_count: %3"PRIu8"%% %"PRIu64"\n",
bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF));
} else {
@@ -4274,7 +4492,7 @@ static void wdc_print_bd_ca_log_normal(void *data)
}
bd_data++;
if (bd_data->field_id == 0x04) {
- raw = (__u64*)&bd_data->raw_value[1];
+ raw = (__u64*)&bd_data->raw_value[0];
printf("crc_error_count : %3"PRIu8"%% %"PRIu64"\n",
bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF));
} else {
@@ -4282,7 +4500,7 @@ static void wdc_print_bd_ca_log_normal(void *data)
}
bd_data++;
if (bd_data->field_id == 0x05) {
- raw = (__u64*)&bd_data->raw_value[1];
+ raw = (__u64*)&bd_data->raw_value[0];
printf("timed_workload_media_wear : %3"PRIu8"%% %-.3f%%\n",
bd_data->normalized_value,
safe_div_fp((*raw & 0x00FFFFFFFFFFFFFF), 1024.0));
@@ -4291,7 +4509,7 @@ static void wdc_print_bd_ca_log_normal(void *data)
}
bd_data++;
if (bd_data->field_id == 0x06) {
- raw = (__u64*)&bd_data->raw_value[1];
+ raw = (__u64*)&bd_data->raw_value[0];
printf("timed_workload_host_reads : %3"PRIu8"%% %"PRIu64"%%\n",
bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF));
} else {
@@ -4299,7 +4517,7 @@ static void wdc_print_bd_ca_log_normal(void *data)
}
bd_data++;
if (bd_data->field_id == 0x07) {
- raw = (__u64*)&bd_data->raw_value[1];
+ raw = (__u64*)&bd_data->raw_value[0];
printf("timed_workload_timer : %3"PRIu8"%% %"PRIu64"\n",
bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF));
} else {
@@ -4316,7 +4534,7 @@ static void wdc_print_bd_ca_log_normal(void *data)
}
bd_data++;
if (bd_data->field_id == 0x09) {
- raw = (__u64*)&bd_data->raw_value[1];
+ raw = (__u64*)&bd_data->raw_value[0];
printf("retry_buffer_overflow_count : %3"PRIu8"%% %"PRIu64"\n",
bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF));
} else {
@@ -4324,7 +4542,7 @@ static void wdc_print_bd_ca_log_normal(void *data)
}
bd_data++;
if (bd_data->field_id == 0x0A) {
- raw = (__u64*)&bd_data->raw_value[1];
+ raw = (__u64*)&bd_data->raw_value[0];
printf("pll_lock_loss_count : %3"PRIu8"%% %"PRIu64"\n",
bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF));
} else {
@@ -4332,7 +4550,7 @@ static void wdc_print_bd_ca_log_normal(void *data)
}
bd_data++;
if (bd_data->field_id == 0x0B) {
- raw = (__u64*)&bd_data->raw_value[1];
+ raw = (__u64*)&bd_data->raw_value[0];
printf("nand_bytes_written : %3"PRIu8"%% sectors: %.f\n",
bd_data->normalized_value, safe_div_fp((*raw & 0x00FFFFFFFFFFFFFF), 0xFFFF));
} else {
@@ -4340,7 +4558,7 @@ static void wdc_print_bd_ca_log_normal(void *data)
}
bd_data++;
if (bd_data->field_id == 0x0C) {
- raw = (__u64*)&bd_data->raw_value[1];
+ raw = (__u64*)&bd_data->raw_value[0];
printf("host_bytes_written : %3"PRIu8"%% sectors: %.f\n",
bd_data->normalized_value, safe_div_fp((*raw & 0x00FFFFFFFFFFFFFF), 0xFFFF));
} else {
@@ -4368,7 +4586,7 @@ static void wdc_print_bd_ca_log_json(void *data)
root = json_create_object();
if (bd_data->field_id == 0x00) {
- raw = (__u64*)&bd_data->raw_value[1];
+ raw = (__u64*)&bd_data->raw_value[0];
json_object_add_value_int(root, "program_fail_count normalized",
bd_data->normalized_value);
json_object_add_value_int(root, "program_fail_count raw",
@@ -4378,7 +4596,7 @@ static void wdc_print_bd_ca_log_json(void *data)
}
bd_data++;
if (bd_data->field_id == 0x01) {
- raw = (__u64*)&bd_data->raw_value[1];
+ raw = (__u64*)&bd_data->raw_value[0];
json_object_add_value_int(root, "erase_fail_count normalized",
bd_data->normalized_value);
json_object_add_value_int(root, "erase_fail_count raw",
@@ -4400,7 +4618,7 @@ static void wdc_print_bd_ca_log_json(void *data)
}
bd_data++;
if (bd_data->field_id == 0x03) {
- raw = (__u64*)&bd_data->raw_value[1];
+ raw = (__u64*)&bd_data->raw_value[0];
json_object_add_value_int(root, "end_to_end_error_detection_count normalized",
bd_data->normalized_value);
json_object_add_value_int(root, "end_to_end_error_detection_count raw",
@@ -4410,7 +4628,7 @@ static void wdc_print_bd_ca_log_json(void *data)
}
bd_data++;
if (bd_data->field_id == 0x04) {
- raw = (__u64*)&bd_data->raw_value[1];
+ raw = (__u64*)&bd_data->raw_value[0];
json_object_add_value_int(root, "crc_error_count normalized",
bd_data->normalized_value);
json_object_add_value_int(root, "crc_error_count raw",
@@ -4420,17 +4638,17 @@ static void wdc_print_bd_ca_log_json(void *data)
}
bd_data++;
if (bd_data->field_id == 0x05) {
- raw = (__u64*)&bd_data->raw_value[1];
+ raw = (__u64*)&bd_data->raw_value[0];
json_object_add_value_int(root, "timed_workload_media_wear normalized",
bd_data->normalized_value);
- json_object_add_value_float(root, "timed_workload_media_wear raw",
+ json_object_add_value_double(root, "timed_workload_media_wear raw",
safe_div_fp((*raw & 0x00FFFFFFFFFFFFFF), 1024.0));
} else {
goto invalid_id;
}
bd_data++;
if (bd_data->field_id == 0x06) {
- raw = (__u64*)&bd_data->raw_value[1];
+ raw = (__u64*)&bd_data->raw_value[0];
json_object_add_value_int(root, "timed_workload_host_reads normalized",
bd_data->normalized_value);
json_object_add_value_int(root, "timed_workload_host_reads raw",
@@ -4440,7 +4658,7 @@ static void wdc_print_bd_ca_log_json(void *data)
}
bd_data++;
if (bd_data->field_id == 0x07) {
- raw = (__u64*)&bd_data->raw_value[1];
+ raw = (__u64*)&bd_data->raw_value[0];
json_object_add_value_int(root, "timed_workload_timer normalized",
bd_data->normalized_value);
json_object_add_value_int(root, "timed_workload_timer",
@@ -4461,7 +4679,7 @@ static void wdc_print_bd_ca_log_json(void *data)
}
bd_data++;
if (bd_data->field_id == 0x09) {
- raw = (__u64*)&bd_data->raw_value[1];
+ raw = (__u64*)&bd_data->raw_value[0];
json_object_add_value_int(root, "retry_buffer_overflow_count normalized",
bd_data->normalized_value);
json_object_add_value_int(root, "retry_buffer_overflow_count raw",
@@ -4471,7 +4689,7 @@ static void wdc_print_bd_ca_log_json(void *data)
}
bd_data++;
if (bd_data->field_id == 0x0A) {
- raw = (__u64*)&bd_data->raw_value[1];
+ raw = (__u64*)&bd_data->raw_value[0];
json_object_add_value_int(root, "pll_lock_loss_count normalized",
bd_data->normalized_value);
json_object_add_value_int(root, "pll_lock_loss_count raw",
@@ -4481,20 +4699,20 @@ static void wdc_print_bd_ca_log_json(void *data)
}
bd_data++;
if (bd_data->field_id == 0x0B) {
- raw = (__u64*)&bd_data->raw_value[1];
+ raw = (__u64*)&bd_data->raw_value[0];
json_object_add_value_int(root, "nand_bytes_written normalized",
bd_data->normalized_value);
- json_object_add_value_float(root, "nand_bytes_written raw",
+ json_object_add_value_double(root, "nand_bytes_written raw",
safe_div_fp((*raw & 0x00FFFFFFFFFFFFFF), 0xFFFF));
} else {
goto invalid_id;
}
bd_data++;
if (bd_data->field_id == 0x0C) {
- raw = (__u64*)&bd_data->raw_value[1];
+ raw = (__u64*)&bd_data->raw_value[0];
json_object_add_value_int(root, "host_bytes_written normalized",
bd_data->normalized_value);
- json_object_add_value_float(root, "host_bytes_written raw",
+ json_object_add_value_double(root, "host_bytes_written raw",
safe_div_fp((*raw & 0x00FFFFFFFFFFFFFF), 0xFFFF));
} else {
goto invalid_id;
@@ -4678,6 +4896,7 @@ static void wdc_print_fw_act_history_log_normal(__u8 *data, int num_entries, __u
struct wdc_fw_act_history_log_format_c2 *fw_act_history_entry = (struct wdc_fw_act_history_log_format_c2 *)(data);
+ oldestEntryIdx = WDC_MAX_NUM_ACT_HIST_ENTRIES;
if (num_entries == WDC_MAX_NUM_ACT_HIST_ENTRIES) {
/* find lowest/oldest entry */
for (i = 0; i < num_entries; i++) {
@@ -4761,6 +4980,7 @@ static void wdc_print_fw_act_history_log_normal(__u8 *data, int num_entries, __u
struct wdc_fw_act_history_log_entry *fw_act_history_entry = (struct wdc_fw_act_history_log_entry *)(data + sizeof(struct wdc_fw_act_history_log_hdr));
+ oldestEntryIdx = WDC_MAX_NUM_ACT_HIST_ENTRIES;
if (num_entries == WDC_MAX_NUM_ACT_HIST_ENTRIES) {
/* find lowest/oldest entry */
for (i = 0; i < num_entries; i++) {
@@ -4840,6 +5060,7 @@ static void wdc_print_fw_act_history_log_json(__u8 *data, int num_entries, __u32
if(data[0] == WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID) {
struct wdc_fw_act_history_log_format_c2 *fw_act_history_entry = (struct wdc_fw_act_history_log_format_c2 *)(data);
+ oldestEntryIdx = WDC_MAX_NUM_ACT_HIST_ENTRIES;
if (num_entries == WDC_MAX_NUM_ACT_HIST_ENTRIES) {
/* find lowest/oldest entry */
for (i = 0; i < num_entries; i++) {
@@ -4910,6 +5131,7 @@ static void wdc_print_fw_act_history_log_json(__u8 *data, int num_entries, __u32
else {
struct wdc_fw_act_history_log_entry *fw_act_history_entry = (struct wdc_fw_act_history_log_entry *)(data + sizeof(struct wdc_fw_act_history_log_hdr));
+ oldestEntryIdx = WDC_MAX_NUM_ACT_HIST_ENTRIES;
if (num_entries == WDC_MAX_NUM_ACT_HIST_ENTRIES) {
/* find lowest/oldest entry */
for (i = 0; i < num_entries; i++) {
@@ -4970,6 +5192,682 @@ static void wdc_print_fw_act_history_log_json(__u8 *data, int num_entries, __u32
json_free_object(root);
}
+static int nvme_get_ext_smart_cloud_log(int fd, __u8 **data, int uuid_index, __u32 namespace_id)
+{
+ int ret, i;
+ __u8 *log_ptr = NULL;
+
+ if ((log_ptr = (__u8*) malloc(sizeof (__u8) * WDC_NVME_SMART_CLOUD_ATTR_LEN)) == NULL) {
+ fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno));
+ return -1;
+ }
+
+ /* 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 = WDC_NVME_SMART_CLOUD_ATTR_LEN,
+ .log = log_ptr,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ ret = nvme_get_log(&args);
+
+ if (ret == 0) {
+
+ /* Verify GUID matches */
+ for (i = 0; i < WDC_C0_GUID_LENGTH; i++) {
+ if (ext_smart_guid[i] != *&log_ptr[SCAO_V1_LPG + i]) {
+ fprintf(stderr, "ERROR : WDC : Unknown GUID in C0 Log Page V1 data\n");
+ int j;
+ fprintf(stderr, "ERROR : WDC : Expected GUID: 0x");
+ for (j = 0; j < WDC_C0_GUID_LENGTH; j++) {
+ fprintf(stderr, "%x", ext_smart_guid[j]);
+ }
+ fprintf(stderr, "\nERROR : WDC : Actual GUID: 0x");
+ for (j = 0; j < WDC_C0_GUID_LENGTH; j++) {
+ fprintf(stderr, "%x", *&log_ptr[SCAO_V1_LPG + j]);
+ }
+ fprintf(stderr, "\n");
+
+ ret = -1;
+ break;
+ }
+ }
+ }
+
+ *data = log_ptr;
+
+ return ret;
+}
+
+
+static int nvme_get_hw_rev_log(int fd, __u8 **data, int uuid_index, __u32 namespace_id)
+{
+ int ret, i;
+ wdc_nvme_hw_rev_log *log_ptr = NULL;
+
+ if ((log_ptr = (wdc_nvme_hw_rev_log *)malloc(sizeof (__u8) * WDC_NVME_HW_REV_LOG_PAGE_LEN)) == NULL) {
+ fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno));
+ return -1;
+ }
+
+ /* Get the 0xC0 log data */
+ struct nvme_get_log_args args = {
+ .args_size = sizeof(args),
+ .fd = fd,
+ .lid = WDC_NVME_GET_HW_REV_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 = WDC_NVME_HW_REV_LOG_PAGE_LEN,
+ .log = log_ptr,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ ret = nvme_get_log(&args);
+
+ if (ret == 0) {
+
+ /* Verify GUID matches */
+ for (i = 0; i < WDC_NVME_C6_GUID_LENGTH; i++) {
+ if (hw_rev_log_guid[i] != log_ptr->hw_rev_guid[i]) {
+ fprintf(stderr, "ERROR : WDC : Unknown GUID in HW Revision Log Page data\n");
+ int j;
+ fprintf(stderr, "ERROR : WDC : Expected GUID: 0x");
+ for (j = 0; j < WDC_NVME_C6_GUID_LENGTH; j++) {
+ fprintf(stderr, "%x", hw_rev_log_guid[j]);
+ }
+ fprintf(stderr, "\nERROR : WDC : Actual GUID: 0x");
+ for (j = 0; j < WDC_NVME_C6_GUID_LENGTH; j++) {
+ fprintf(stderr, "%x", log_ptr->hw_rev_guid[j]);
+ }
+ fprintf(stderr, "\n");
+
+ ret = -1;
+ break;
+ }
+ }
+ }
+
+ *data = (__u8 *)log_ptr;
+
+ return ret;
+}
+
+
+static void wdc_print_hw_rev_log_normal(void *data)
+{
+ int i;
+ wdc_nvme_hw_rev_log *log_data = (wdc_nvme_hw_rev_log *)data;
+
+ printf(" Hardware Revision Log:- \n");
+
+ printf(" Global Device HW Revision : %d\n",
+ log_data->hw_rev_gdr);
+ printf(" ASIC HW Revision : %d\n",
+ log_data->hw_rev_ar);
+ printf(" PCB Manufacturer Code : %d\n",
+ log_data->hw_rev_pbc_mc);
+ printf(" DRAM Manufacturer Code : %d\n",
+ log_data->hw_rev_dram_mc);
+ printf(" NAND Manufacturer Code : %d\n",
+ log_data->hw_rev_nand_mc);
+ printf(" PMIC 1 Manufacturer Code : %d\n",
+ log_data->hw_rev_pmic1_mc);
+ printf(" PMIC 2 Manufacturer Code : %d\n",
+ log_data->hw_rev_pmic2_mc);
+ printf(" Other Component 1 Manf Code : %d\n",
+ log_data->hw_rev_c1_mc);
+ printf(" Other Component 2 Manf Code : %d\n",
+ log_data->hw_rev_c2_mc);
+ printf(" Other Component 3 Manf Code : %d\n",
+ log_data->hw_rev_c3_mc);
+ printf(" Other Component 4 Manf Code : %d\n",
+ log_data->hw_rev_c4_mc);
+ printf(" Other Component 5 Manf Code : %d\n",
+ log_data->hw_rev_c5_mc);
+ printf(" Other Component 6 Manf Code : %d\n",
+ log_data->hw_rev_c6_mc);
+ printf(" Other Component 7 Manf Code : %d\n",
+ log_data->hw_rev_c7_mc);
+ printf(" Other Component 8 Manf Code : %d\n",
+ log_data->hw_rev_c8_mc);
+ printf(" Other Component 9 Manf Code : %d\n",
+ log_data->hw_rev_c9_mc);
+
+ printf(" Device Manf Detailed Info : 0x");
+ for (i = 0; i < 16; i++) {
+ printf("%02x", log_data->hw_rev_dev_mdi[i]);
+ if (i == 7)
+ printf(" 0x");
+ }
+ printf("\n");
+ printf(" ASIC Detailed Info : 0x");
+ for (i = 0; i < 16; i++) {
+ printf("%02x", log_data->hw_rev_asic_di[i]);
+ if (i == 7)
+ printf(" 0x");
+ }
+ printf("\n");
+ printf(" PCB Detailed Info : 0x");
+ for (i = 0; i < 16; i++) {
+ printf("%02x", log_data->hw_rev_pcb_di[i]);
+ if (i == 7)
+ printf(" 0x");
+ }
+ printf("\n");
+ printf(" DRAM Detailed Info : 0x");
+ for (i = 0; i < 16; i++) {
+ printf("%02x", log_data->hw_rev_dram_di[i]);
+ if (i == 7)
+ printf(" 0x");
+ }
+ printf("\n");
+ printf(" NAND Detailed Info : 0x");
+ for (i = 0; i < 16; i++) {
+ printf("%02x", log_data->hw_rev_nand_di[i]);
+ if (i == 7)
+ printf(" 0x");
+ }
+ printf("\n");
+ printf(" PMIC 1 Detailed Info : 0x");
+ for (i = 0; i < 16; i++) {
+ printf("%02x", log_data->hw_rev_pmic1_di[i]);
+ if (i == 7)
+ printf(" 0x");
+ }
+ printf("\n");
+ printf(" PMIC 2 Detailed Info : 0x");
+ for (i = 0; i < 16; i++) {
+ printf("%02x", log_data->hw_rev_pmic2_di[i]);
+ if (i == 7)
+ printf(" 0x");
+ }
+ printf("\n");
+ printf(" Component 1 Detailed Info : 0x");
+ for (i = 0; i < 16; i++) {
+ printf("%02x", log_data->hw_rev_c1_di[i]);
+ if (i == 7)
+ printf(" 0x");
+ }
+ printf("\n");
+ printf(" Component 2 Detailed Info : 0x");
+ for (i = 0; i < 16; i++) {
+ printf("%02x", log_data->hw_rev_c2_di[i]);
+ if (i == 7)
+ printf(" 0x");
+ }
+ printf("\n");
+ printf(" Component 3 Detailed Info : 0x");
+ for (i = 0; i < 16; i++) {
+ printf("%02x", log_data->hw_rev_c3_di[i]);
+ if (i == 7)
+ printf(" 0x");
+ }
+ printf("\n");
+ printf(" Component 4 Detailed Info : 0x");
+ for (i = 0; i < 16; i++) {
+ printf("%02x", log_data->hw_rev_c4_di[i]);
+ if (i == 7)
+ printf(" 0x");
+ }
+ printf("\n");
+ printf(" Component 5 Detailed Info : 0x");
+ for (i = 0; i < 16; i++) {
+ printf("%02x", log_data->hw_rev_c5_di[i]);
+ if (i == 7)
+ printf(" 0x");
+ }
+ printf("\n");
+ printf(" Component 6 Detailed Info : 0x");
+ for (i = 0; i < 16; i++) {
+ printf("%02x", log_data->hw_rev_c6_di[i]);
+ if (i == 7)
+ printf(" 0x");
+ }
+ printf("\n");
+ printf(" Component 7 Detailed Info : 0x");
+ for (i = 0; i < 16; i++) {
+ printf("%02x", log_data->hw_rev_c7_di[i]);
+ if (i == 7)
+ printf(" 0x");
+ }
+ printf("\n");
+ printf(" Component 8 Detailed Info : 0x");
+ for (i = 0; i < 16; i++) {
+ printf("%02x", log_data->hw_rev_c8_di[i]);
+ if (i == 7)
+ printf(" 0x");
+ }
+ printf("\n");
+ printf(" Component 9 Detailed Info : 0x");
+ for (i = 0; i < 16; i++) {
+ printf("%02x", log_data->hw_rev_c9_di[i]);
+ if (i == 7)
+ printf(" 0x");
+ }
+ printf("\n");
+ printf(" Serial Number : 0x");
+ for (i = 0; i < 32; i++) {
+ if ((i > 1) & !(i % 8))
+ printf(" 0x");
+ printf("%02x", log_data->hw_rev_sn[i]);
+ }
+ printf("\n");
+
+ printf(" Log Page Version : %d\n",
+ log_data->hw_rev_version);
+ printf(" Log page GUID : 0x");
+ printf("%"PRIx64"%"PRIx64"\n",le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[8]),
+ le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[0]));
+ printf("\n");
+}
+
+static void wdc_print_hw_rev_log_json(void *data)
+{
+ wdc_nvme_hw_rev_log *log_data = (wdc_nvme_hw_rev_log *)data;
+ struct json_object *root;
+ char json_data[80];
+
+ root = json_create_object();
+ json_object_add_value_uint(root, "Global Device HW Revision",
+ log_data->hw_rev_gdr);
+ json_object_add_value_uint(root, "ASIC HW Revision",
+ log_data->hw_rev_ar);
+ json_object_add_value_uint(root, "PCB Manufacturer Code",
+ log_data->hw_rev_pbc_mc);
+ json_object_add_value_uint(root, "DRAM Manufacturer Code",
+ log_data->hw_rev_dram_mc);
+ json_object_add_value_uint(root, "NAND Manufacturer Code",
+ log_data->hw_rev_nand_mc);
+ json_object_add_value_uint(root, "PMIC 1 Manufacturer Code",
+ log_data->hw_rev_pmic1_mc);
+ json_object_add_value_uint(root, "PMIC 2 Manufacturer Code",
+ log_data->hw_rev_pmic2_mc);
+ json_object_add_value_uint(root, "Other Component 1 Manf Code",
+ log_data->hw_rev_c1_mc);
+ json_object_add_value_uint(root, "Other Component 2 Manf Code",
+ log_data->hw_rev_c2_mc);
+ json_object_add_value_uint(root, "Other Component 3 Manf Code",
+ log_data->hw_rev_c3_mc);
+ json_object_add_value_uint(root, "Other Component 4 Manf Code",
+ log_data->hw_rev_c4_mc);
+ json_object_add_value_uint(root, "Other Component 5 Manf Code",
+ log_data->hw_rev_c5_mc);
+ json_object_add_value_uint(root, "Other Component 6 Manf Code",
+ log_data->hw_rev_c6_mc);
+ json_object_add_value_uint(root, "Other Component 7 Manf Code",
+ log_data->hw_rev_c7_mc);
+ json_object_add_value_uint(root, "Other Component 8 Manf Code",
+ log_data->hw_rev_c8_mc);
+ json_object_add_value_uint(root, "Other Component 9 Manf Code",
+ log_data->hw_rev_c9_mc);
+
+ memset((void*)json_data, 0, 40);
+ sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dev_mdi[8]),
+ le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dev_mdi[0]));
+ json_object_add_value_string(root, "Device Manf Detailed Info", json_data);
+
+ memset((void*)json_data, 0, 40);
+ sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_asic_di[8]),
+ le64_to_cpu(*(uint64_t *)&log_data->hw_rev_asic_di[0]));
+ json_object_add_value_string(root, "ASIC Detailed Info", json_data);
+
+ memset((void*)json_data, 0, 40);
+ sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pcb_di[8]),
+ le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pcb_di[0]));
+ json_object_add_value_string(root, "PCB Detailed Info", json_data);
+
+ memset((void*)json_data, 0, 40);
+ sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dram_di[8]),
+ le64_to_cpu(*(uint64_t *)&log_data->hw_rev_dram_di[0]));
+ json_object_add_value_string(root, "DRAM Detailed Info", json_data);
+
+ memset((void*)json_data, 0, 40);
+ sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_nand_di[8]),
+ le64_to_cpu(*(uint64_t *)&log_data->hw_rev_nand_di[0]));
+ json_object_add_value_string(root, "NAND Detailed Info", json_data);
+
+ memset((void*)json_data, 0, 40);
+ sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic1_di[8]),
+ le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic1_di[0]));
+ json_object_add_value_string(root, "PMIC 1 Detailed Info", json_data);
+
+ memset((void*)json_data, 0, 40);
+ sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic2_di[8]),
+ le64_to_cpu(*(uint64_t *)&log_data->hw_rev_pmic2_di[0]));
+ json_object_add_value_string(root, "PMIC 2 Detailed Info", json_data);
+
+ memset((void*)json_data, 0, 40);
+ sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c1_di[8]),
+ le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c1_di[0]));
+ json_object_add_value_string(root, "Component 1 Detailed Info", json_data);
+
+ memset((void*)json_data, 0, 40);
+ sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c2_di[8]),
+ le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c2_di[0]));
+ json_object_add_value_string(root, "Component 2 Detailed Info", json_data);
+
+ memset((void*)json_data, 0, 40);
+ sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c3_di[8]),
+ le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c3_di[0]));
+ json_object_add_value_string(root, "Component 3 Detailed Info", json_data);
+
+ memset((void*)json_data, 0, 40);
+ sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c4_di[8]),
+ le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c4_di[0]));
+ json_object_add_value_string(root, "Component 4 Detailed Info", json_data);
+
+ memset((void*)json_data, 0, 40);
+ sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c5_di[8]),
+ le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c5_di[0]));
+ json_object_add_value_string(root, "Component 5 Detailed Info", json_data);
+
+ memset((void*)json_data, 0, 40);
+ sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c6_di[8]),
+ le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c6_di[0]));
+ json_object_add_value_string(root, "Component 6 Detailed Info", json_data);
+
+ memset((void*)json_data, 0, 40);
+ sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c7_di[8]),
+ le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c7_di[0]));
+ json_object_add_value_string(root, "Component 7 Detailed Info", json_data);
+
+ memset((void*)json_data, 0, 40);
+ sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c8_di[8]),
+ le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c8_di[0]));
+ json_object_add_value_string(root, "Component 8 Detailed Info", json_data);
+
+ memset((void*)json_data, 0, 40);
+ sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c9_di[8]),
+ le64_to_cpu(*(uint64_t *)&log_data->hw_rev_c9_di[0]));
+ json_object_add_value_string(root, "Component 9 Detailed Info", json_data);
+
+ memset((void*)json_data, 0, 80);
+ sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"%"PRIx64"%"PRIx64"",
+ le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[0]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[8]),
+ le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[16]), le64_to_cpu(*(uint64_t *)&log_data->hw_rev_sn[24]));
+ json_object_add_value_string(root, "Serial Number", json_data);
+
+ json_object_add_value_uint(root, "Log Page Version",
+ le16_to_cpu(log_data->hw_rev_version));
+
+ memset((void*)json_data, 0, 40);
+ sprintf((char*)json_data, "0x%"PRIx64"%"PRIx64"", le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[8]),
+ le64_to_cpu(*(uint64_t *)&log_data->hw_rev_guid[0]));
+ json_object_add_value_string(root, "Log Page GUID", json_data);
+
+ json_print_object(root, NULL);
+ printf("\n");
+ json_free_object(root);
+}
+
+static void wdc_print_ext_smart_cloud_log_normal(void *data, int mask)
+{
+ int i;
+ wdc_nvme_ext_smart_log *ext_smart_log_ptr = (wdc_nvme_ext_smart_log *)data;
+
+ if (mask == WDC_SCA_V1_NAND_STATS)
+ printf(" NAND Statistics :- \n");
+ else
+ printf(" SMART Cloud Attributes :- \n");
+
+ printf(" Physical Media Units Written TLC (Bytes) : %'.0Lf\n",
+ int128_to_double(ext_smart_log_ptr->ext_smart_pmuwt));
+ printf(" Physical Media Units Written SLC (Bytes) : %'.0Lf\n",
+ int128_to_double(ext_smart_log_ptr->ext_smart_pmuws));
+ printf(" Bad User NAND Block Count (Normalized) (Int) : %d\n",
+ le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bunbc));
+ printf(" Bad User NAND Block Count (Raw) (Int) : %"PRIu64"\n",
+ le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_bunbc & 0xFFFFFFFFFFFF0000));
+ printf(" XOR Recovery Count (Int) : %"PRIu64"\n",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_xrc));
+ printf(" Uncorrectable Read Error Count (Int) : %"PRIu64"\n",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_urec));
+ if (mask == WDC_SCA_V1_ALL) {
+ printf(" SSD End to End correction counts (Corrected Errors) (Int) : %"PRIu64"\n",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_eece));
+ printf(" SSD End to End correction counts (Detected Errors) (Int) : %"PRIu64"\n",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_eede));
+ printf(" SSD End to End correction counts (Uncorrected E2E Errors) (Int) : %"PRIu64"\n",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_eeue));
+ printf(" System Data %% life-used : %d %%\n",
+ ext_smart_log_ptr->ext_smart_sdpu);
+ }
+ printf(" User data erase counts (Minimum TLC) (Int) : %"PRIu64"\n",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_mnudec));
+ printf(" User data erase counts (Maximum TLC) (Int) : %"PRIu64"\n",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_mxudec));
+ printf(" User data erase counts (Minimum SLC) (Int) : %"PRIu64"\n",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_mnec));
+ printf(" User data erase counts (Maximum SLC) (Int) : %"PRIu64"\n",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_mxec));
+ printf(" User data erase counts (Average SLC) (Int) : %"PRIu64"\n",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_avec));
+ printf(" User data erase counts (Average TLC) (Int) : %"PRIu64"\n",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_avudec));
+ printf(" Program Fail Count (Normalized) (Int) : %d\n",
+ le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_pfc));
+ printf(" Program Fail Count (Raw) (Int) : %"PRIu64"\n",
+ le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_pfc & 0xFFFFFFFFFFFF0000));
+ printf(" Erase Fail Count (Normalized) (Int) : %d\n",
+ le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_efc));
+ printf(" Erase Fail Count (Raw) (Int) : %"PRIu64"\n",
+ le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_efc & 0xFFFFFFFFFFFF0000));
+ if (mask == WDC_SCA_V1_ALL) {
+ printf(" PCIe Correctable Error Count (Int) : %"PRIu64"\n",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_pcec));
+ printf(" %% Free Blocks (User) (Int) : %d %%\n",
+ ext_smart_log_ptr->ext_smart_pfbu);
+ printf(" Security Version Number (Int) : %"PRIu64"\n",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_svn));
+ printf(" %% Free Blocks (System) (Int) : %d %%\n",
+ ext_smart_log_ptr->ext_smart_pfbs);
+ printf(" NVMe Stats (# Data Set Management/TRIM Commands Completed) (Int) : %'.0Lf\n",
+ int128_to_double(ext_smart_log_ptr->ext_smart_dcc));
+ printf(" Total Namespace Utilization (nvme0n1 NUSE) (Bytes) : %"PRIu64"\n",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_tnu));
+ printf(" NVMe Stats (# NVMe Format Commands Completed) (Int) : %d\n",
+ le16_to_cpu(ext_smart_log_ptr->ext_smart_fcc));
+ printf(" Background Back-Pressure Gauge(%%) (Int) : %d\n",
+ ext_smart_log_ptr->ext_smart_bbpg);
+ }
+ printf(" Total # of Soft ECC Error Count (Int) : %"PRIu64"\n",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_seec));
+ if (mask == WDC_SCA_V1_ALL) {
+ printf(" Total # of Read Refresh Count (Int) : %"PRIu64"\n",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_rfsc));
+ }
+ printf(" Bad System NAND Block Count (Normalized) (Int) : %d\n",
+ le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bsnbc));
+ printf(" Bad System NAND Block Count (Raw) (Int) : %"PRIu64"\n",
+ le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_bsnbc & 0xFFFFFFFFFFFF0000));
+ printf(" Endurance Estimate (Total Writable Lifetime Bytes) (Bytes) : %'.0Lf\n",
+ int128_to_double(ext_smart_log_ptr->ext_smart_eest));
+ if (mask == WDC_SCA_V1_ALL) {
+ printf(" Thermal Throttling Status & Count (Number of thermal throttling events) (Int) : %d\n",
+ le16_to_cpu(ext_smart_log_ptr->ext_smart_ttc));
+ printf(" Total # Unaligned I/O (Int) : %"PRIu64"\n",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_uio));
+ }
+ printf(" Total Physical Media Units Read (Bytes) (Int) : %'.0Lf\n",
+ int128_to_double(ext_smart_log_ptr->ext_smart_pmur));
+ if (mask == WDC_SCA_V1_ALL) {
+ printf(" Command Timeout (# of READ Commands > 5 Seconds) (Int) : %"PRIu32"\n",
+ le32_to_cpu(ext_smart_log_ptr->ext_smart_rtoc));
+ printf(" Command Timeout (# of WRITE Commands > 5 Seconds) (Int) : %"PRIu32"\n",
+ le32_to_cpu(ext_smart_log_ptr->ext_smart_wtoc));
+ printf(" Command Timeout (# of TRIM Commands > 5 Seconds) (Int) : %"PRIu32"\n",
+ le32_to_cpu(ext_smart_log_ptr->ext_smart_ttoc));
+ printf(" Total PCIe Link Retraining Count (Int) : %"PRIu64"\n",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_plrc));
+ printf(" Active Power State Change Count (Int) : %"PRIu64"\n",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_pscc));
+ }
+ printf(" Cloud Boot SSD Spec Version (Int) : %d.%d.%d.%d\n",
+ le16_to_cpu(ext_smart_log_ptr->ext_smart_maj),
+ le16_to_cpu(ext_smart_log_ptr->ext_smart_min),
+ le16_to_cpu(ext_smart_log_ptr->ext_smart_pt),
+ le16_to_cpu(ext_smart_log_ptr->ext_smart_err));
+ printf(" Cloud Boot SSD HW Revision (Int) : %d.%d.%d.%d\n",
+ 0, 0, 0, 0);
+ if (mask == WDC_SCA_V1_ALL) {
+ printf(" FTL Unit Size : %"PRIu32"\n",
+ le32_to_cpu(ext_smart_log_ptr->ext_smart_ftlus));
+ printf(" TCG Ownership Status : %"PRIu32"\n",
+ le32_to_cpu(ext_smart_log_ptr->ext_smart_tcgos));
+ printf(" Log Page Version (Int) : %d\n",
+ le16_to_cpu(ext_smart_log_ptr->ext_smart_lpv));
+ printf(" Log page GUID (Hex) : 0x");
+ for (i = WDC_C0_GUID_LENGTH; i > 0; i--)
+ printf("%02x", ext_smart_log_ptr->ext_smart_lpg[i-1]);
+ printf("\n");
+ }
+ printf("\n");
+}
+
+static void wdc_print_ext_smart_cloud_log_json(void *data, int mask)
+{
+ wdc_nvme_ext_smart_log *ext_smart_log_ptr = (wdc_nvme_ext_smart_log *)data;
+ struct json_object *root;
+
+ root = json_create_object();
+ json_object_add_value_double(root, "physical_media_units_bytes_tlc",
+ int128_to_double(ext_smart_log_ptr->ext_smart_pmuwt));
+ json_object_add_value_double(root, "physical_media_units_bytes_slc",
+ int128_to_double(ext_smart_log_ptr->ext_smart_pmuws));
+ json_object_add_value_uint(root, "bad_user_blocks_normalized",
+ le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bunbc));
+ json_object_add_value_uint64(root, "bad_user_blocks_raw",
+ le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_bunbc & 0xFFFFFFFFFFFF0000));
+ json_object_add_value_uint64(root, "xor_recovery_count",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_xrc));
+ json_object_add_value_uint64(root, "uncorrectable_read_errors",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_urec));
+ if (mask == WDC_SCA_V1_ALL) {
+ json_object_add_value_uint64(root, "corrected_e2e_errors",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_eece));
+ json_object_add_value_uint64(root, "detected_e2e_errors",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_eede));
+ json_object_add_value_uint64(root, "uncorrected_e2e_errors",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_eeue));
+ json_object_add_value_uint(root, "system_data_life_used_pct",
+ (__u8)ext_smart_log_ptr->ext_smart_sdpu);
+ }
+ json_object_add_value_uint64(root, "min_slc_user_data_erase_count",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_mnec));
+ json_object_add_value_uint64(root, "min_tlc_user_data_erase_count",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_mnudec));
+ json_object_add_value_uint64(root, "max_slc_user_data_erase_count",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_mxec));
+ json_object_add_value_uint64(root, "max_tlc_user_data_erase_count",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_mxudec));
+ json_object_add_value_uint64(root, "avg_slc_user_data_erase_count",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_avec));
+ json_object_add_value_uint64(root, "avg_tlc_user_data_erase_count",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_avudec));
+ json_object_add_value_uint(root, "program_fail_count_normalized",
+ le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_pfc));
+ json_object_add_value_uint64(root, "program_fail_count_raw",
+ le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_pfc & 0xFFFFFFFFFFFF0000));
+ json_object_add_value_uint(root, "erase_fail_count_normalized",
+ le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_efc));
+ json_object_add_value_uint64(root, "erase_fail_count_raw",
+ le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_efc & 0xFFFFFFFFFFFF0000));
+ if (mask == WDC_SCA_V1_ALL) {
+ json_object_add_value_uint64(root, "pcie_correctable_errors",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_pcec));
+ json_object_add_value_uint(root, "pct_free_blocks_user",
+ (__u8)ext_smart_log_ptr->ext_smart_pfbu);
+ json_object_add_value_uint64(root, "security_version",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_svn));
+ json_object_add_value_uint(root, "pct_free_blocks_system",
+ (__u8)ext_smart_log_ptr->ext_smart_pfbs);
+ json_object_add_value_double(root, "num_of_trim_commands",
+ int128_to_double(ext_smart_log_ptr->ext_smart_dcc));
+ json_object_add_value_uint64(root, "total_nuse_bytes",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_tnu));
+ json_object_add_value_uint(root, "num_of_format_commands",
+ le16_to_cpu(ext_smart_log_ptr->ext_smart_fcc));
+ json_object_add_value_uint(root, "background_pressure_gauge",
+ (__u8)ext_smart_log_ptr->ext_smart_bbpg);
+ }
+ json_object_add_value_uint64(root, "soft_ecc_error_count",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_seec));
+ if (mask == WDC_SCA_V1_ALL) {
+ json_object_add_value_uint64(root, "read_refresh_count",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_rfsc));
+ }
+ json_object_add_value_uint(root, "bad_system_block_normalized",
+ le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bsnbc));
+ json_object_add_value_uint64(root, "bad_system_block_raw",
+ le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_bsnbc & 0xFFFFFFFFFFFF0000));
+ json_object_add_value_double(root, "endurance_est_bytes",
+ int128_to_double(ext_smart_log_ptr->ext_smart_eest));
+ if (mask == WDC_SCA_V1_ALL) {
+ json_object_add_value_uint(root, "num_throttling_events",
+ le16_to_cpu(ext_smart_log_ptr->ext_smart_ttc));
+ json_object_add_value_uint64(root, "total_unaligned_io",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_uio));
+ }
+ json_object_add_value_double(root, "physical_media_units_read_bytes",
+ int128_to_double(ext_smart_log_ptr->ext_smart_pmur));
+ if (mask == WDC_SCA_V1_ALL) {
+ json_object_add_value_uint(root, "num_read_timeouts",
+ le32_to_cpu(ext_smart_log_ptr->ext_smart_rtoc));
+ json_object_add_value_uint(root, "num_write_timeouts",
+ le32_to_cpu(ext_smart_log_ptr->ext_smart_wtoc));
+ json_object_add_value_uint(root, "num_trim_timeouts",
+ le32_to_cpu(ext_smart_log_ptr->ext_smart_ttoc));
+ json_object_add_value_uint64(root, "pcie_link_retrain_count",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_plrc));
+ json_object_add_value_uint64(root, "active_power_state_change_count",
+ le64_to_cpu(ext_smart_log_ptr->ext_smart_pscc));
+ }
+ char vers_str[40];
+ memset((void*)vers_str, 0, 40);
+ sprintf((char*)vers_str, "%d.%d.%d.%d",
+ le16_to_cpu(ext_smart_log_ptr->ext_smart_maj), le16_to_cpu(ext_smart_log_ptr->ext_smart_min),
+ le16_to_cpu(ext_smart_log_ptr->ext_smart_pt), le16_to_cpu(ext_smart_log_ptr->ext_smart_err));
+ json_object_add_value_string(root, "cloud_boot_ssd_spec_ver", vers_str);
+ memset((void*)vers_str, 0, 40);
+ sprintf((char*)vers_str, "%d.%d.%d.%d", 0, 0, 0, 0);
+ json_object_add_value_string(root, "cloud_boot_ssd_hw_ver", vers_str);
+
+ if (mask == WDC_SCA_V1_ALL) {
+ json_object_add_value_uint(root, "ftl_unit_size",
+ le32_to_cpu(ext_smart_log_ptr->ext_smart_ftlus));
+ json_object_add_value_uint(root, "tcg_ownership_status",
+ le32_to_cpu(ext_smart_log_ptr->ext_smart_tcgos));
+ json_object_add_value_uint(root, "log_page_ver",
+ le16_to_cpu(ext_smart_log_ptr->ext_smart_lpv));
+ char guid[40];
+ memset((void*)guid, 0, 40);
+ sprintf((char*)guid, "0x%"PRIx64"%"PRIx64"",le64_to_cpu(*(uint64_t *)&ext_smart_log_ptr->ext_smart_lpg[8]),
+ le64_to_cpu(*(uint64_t *)&ext_smart_log_ptr->ext_smart_lpg[0]));
+ json_object_add_value_string(root, "log_page_guid", guid);
+ }
+
+ json_print_object(root, NULL);
+ printf("\n");
+ json_free_object(root);
+}
+
static void wdc_print_smart_cloud_attr_C0_normal(void *data)
{
__u8 *log_data = (__u8*)data;
@@ -4977,12 +5875,8 @@ static void wdc_print_smart_cloud_attr_C0_normal(void *data)
printf(" SMART Cloud Attributes :- \n");
- printf(" Physical media units written : %"PRIu64" %"PRIu64"\n",
- (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW+8] & 0xFFFFFFFFFFFFFFFF),
- (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW] & 0xFFFFFFFFFFFFFFFF));
- printf(" Physical media units read : %"PRIu64" %"PRIu64"\n",
- (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR+8] & 0xFFFFFFFFFFFFFFFF),
- (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR] & 0xFFFFFFFFFFFFFFFF));
+ printf(" Physical media units written : %'.0Lf\n", int128_to_double(&log_data[SCAO_PMUW]));
+ printf(" Physical media units read : %'.0Lf\n", int128_to_double(&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",
@@ -5023,12 +5917,12 @@ static void wdc_print_smart_cloud_attr_C0_normal(void *data)
(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 : %.0Lf\n", int128_to_double(&log_data[SCAO_PSC]));
- printf(" Endurance estimate : %.0Lf\n", int128_to_double(&log_data[SCAO_EEST]));
+ printf(" PLP start count : %'.0Lf\n", int128_to_double(&log_data[SCAO_PSC]));
+ printf(" Endurance estimate : %'.0Lf\n", int128_to_double(&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("0x%"PRIx64"%"PRIx64"\n",(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG + 8]),
+ 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",
@@ -5044,6 +5938,10 @@ static void wdc_print_smart_cloud_attr_C0_normal(void *data)
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");
}
@@ -5054,14 +5952,10 @@ static void wdc_print_smart_cloud_attr_C0_json(void *data)
uint16_t smart_log_ver = 0;
root = json_create_object();
- json_object_add_value_uint64(root, "Physical media units written hi",
- (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW+8] & 0xFFFFFFFFFFFFFFFF));
- json_object_add_value_uint64(root, "Physical media units written lo",
- (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW] & 0xFFFFFFFFFFFFFFFF));
- json_object_add_value_uint64(root, "Physical media units read hi",
- (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR+8] & 0xFFFFFFFFFFFFFFFF));
- json_object_add_value_uint64(root, "Physical media units read lo",
- (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR] & 0xFFFFFFFFFFFFFFFF));
+ json_object_add_value_double(root, "Physical media units written",
+ int128_to_double(&log_data[SCAO_PMUW]));
+ json_object_add_value_double(root, "Physical media units read",
+ int128_to_double(&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",
@@ -5106,9 +6000,9 @@ static void wdc_print_smart_cloud_attr_C0_json(void *data)
(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_uint(root, "PLP start count",
+ json_object_add_value_double(root, "PLP start count",
int128_to_double(&log_data[SCAO_PSC]));
- json_object_add_value_uint(root, "Endurance estimate",
+ json_object_add_value_double(root, "Endurance estimate",
int128_to_double(&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);
@@ -5131,6 +6025,10 @@ static void wdc_print_smart_cloud_attr_C0_json(void *data)
json_object_add_value_uint64(root, "PCIe Link Retraining Count",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PLRC]));
}
+ if(smart_log_ver > 3) {
+ 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);
@@ -5187,6 +6085,23 @@ static void wdc_print_eol_c0_json(void *data)
json_free_object(root);
}
+static int wdc_print_ext_smart_cloud_log(void *data, int fmt)
+{
+ if (!data) {
+ fprintf(stderr, "ERROR : WDC : Invalid buffer to read 0xC0 V1 log\n");
+ return -1;
+ }
+ switch (fmt) {
+ case NORMAL:
+ wdc_print_ext_smart_cloud_log_normal(data, WDC_SCA_V1_ALL);
+ break;
+ case JSON:
+ wdc_print_ext_smart_cloud_log_json(data, WDC_SCA_V1_ALL);
+ break;
+ }
+ return 0;
+}
+
static int wdc_print_c0_cloud_attr_log(void *data, int fmt)
{
if (!data) {
@@ -5249,12 +6164,16 @@ static int wdc_get_c0_log_page(nvme_root_t r, int fd, char *format,
case WDC_NVME_SN640_DEV_ID_3:
case WDC_NVME_SN840_DEV_ID:
case WDC_NVME_SN840_DEV_ID_1:
+ case WDC_NVME_SN860_DEV_ID:
case WDC_NVME_SN650_DEV_ID:
case WDC_NVME_SN650_DEV_ID_1:
case WDC_NVME_SN650_DEV_ID_2:
case WDC_NVME_SN650_DEV_ID_3:
case WDC_NVME_SN650_DEV_ID_4:
case WDC_NVME_SN655_DEV_ID:
+ case WDC_NVME_SN560_DEV_ID_1:
+ case WDC_NVME_SN560_DEV_ID_2:
+ case WDC_NVME_SN560_DEV_ID_3:
cust_id = wdc_get_fw_cust_id(r, fd);
if (cust_id == WDC_INVALID_CUSTOMER_ID) {
fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__);
@@ -5427,9 +6346,28 @@ static int wdc_get_c0_log_page(nvme_root_t r, int fd, char *format,
free(data);
break;
+ case WDC_NVME_SN820CL_DEV_ID:
+ /* Get the 0xC0 Extended Smart Cloud Attribute log data */
+ data = NULL;
+ ret = nvme_get_ext_smart_cloud_log(fd, &data, uuid_index, namespace_id);
+
+ if (strcmp(format, "json"))
+ nvme_show_status(ret);
+
+ if (ret == 0) {
+ /* parse the data */
+ wdc_print_ext_smart_cloud_log(data, fmt);
+ } else {
+ fprintf(stderr, "ERROR : WDC : Unable to read C0 Log Page V1 data\n");
+ ret = -1;
+ }
+
+ if (data)
+ free(data);
+ break;
+
default:
fprintf(stderr, "ERROR : WDC : Unknown device id - 0x%x\n", device_id);
-
ret = -1;
break;
@@ -5649,7 +6587,7 @@ static int wdc_get_ca_log_page(nvme_root_t r, int fd, char *format)
case WDC_NVME_SN640_DEV_ID_3:
case WDC_NVME_SN840_DEV_ID:
case WDC_NVME_SN840_DEV_ID_1:
-
+ case WDC_NVME_SN860_DEV_ID:
if (cust_id == WDC_CUSTOMER_ID_0x1005) {
if ((data = (__u8*) malloc(sizeof (__u8) * WDC_FB_CA_LOG_BUF_LEN)) == NULL) {
@@ -6223,6 +7161,285 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command,
out:
nvme_free_tree(r);
+ close(fd);
+ return ret;
+}
+
+static int wdc_vs_cloud_log(int argc, char **argv, struct command *command,
+ struct plugin *plugin)
+{
+ const char *desc = "Retrieve Cloud Log Smart/Health Information";
+ const char *namespace_id = "desired namespace id";
+ int fd;
+ nvme_root_t r;
+ int ret = 0;
+ __u64 capabilities = 0;
+ __u8 *data;
+ int fmt = -1;
+
+ struct config {
+ char *output_format;
+ __u32 namespace_id;
+ };
+
+ struct config cfg = {
+ .output_format = "normal",
+ .namespace_id = NVME_NSID_ALL,
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_FMT("output-format", 'o', &cfg.output_format, "Output Format: normal|json"),
+ OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
+ OPT_END()
+ };
+
+ fd = parse_and_open(argc, argv, desc, opts);
+ if (fd < 0)
+ return fd;
+
+ r = nvme_scan(NULL);
+
+ capabilities = wdc_get_drive_capabilities(r, fd);
+
+ if ((capabilities & WDC_DRIVE_CAP_CLOUD_LOG_PAGE) == 0) {
+ fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
+ ret = -1;
+ goto out;
+ }
+
+ data = NULL;
+ ret = nvme_get_ext_smart_cloud_log(fd, &data, 0, cfg.namespace_id);
+
+ if (strcmp(cfg.output_format, "json"))
+ nvme_show_status(ret);
+
+ if (ret == 0) {
+ fmt = validate_output_format(cfg.output_format);
+ if (fmt < 0) {
+ fprintf(stderr, "ERROR : WDC %s: invalid output format\n", __func__);
+ ret = fmt;
+ }
+
+ /* parse the data */
+ wdc_print_ext_smart_cloud_log(data, fmt);
+ } else {
+ fprintf(stderr, "ERROR : WDC : Unable to read C0 Log Page V1 data\n");
+ ret = -1;
+ }
+
+ if (data)
+ free(data);
+
+out:
+ nvme_free_tree(r);
+ close(fd);
+ return ret;
+}
+
+static int wdc_vs_hw_rev_log(int argc, char **argv, struct command *command,
+ struct plugin *plugin)
+{
+ const char *desc = "Retrieve Hardware Revision Log Information";
+ const char *namespace_id = "desired namespace id";
+ int fd;
+ nvme_root_t r;
+ int ret = 0;
+ __u64 capabilities = 0;
+ __u8 *data = NULL;
+ int fmt = -1;
+
+ struct config {
+ char *output_format;
+ __u32 namespace_id;
+ };
+
+ struct config cfg = {
+ .output_format = "normal",
+ .namespace_id = NVME_NSID_ALL,
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_FMT("output-format", 'o', &cfg.output_format, "Output Format: normal|json"),
+ OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
+ OPT_END()
+ };
+
+ fd = parse_and_open(argc, argv, desc, opts);
+ if (fd < 0)
+ return fd;
+
+ r = nvme_scan(NULL);
+
+ capabilities = wdc_get_drive_capabilities(r, fd);
+
+ if ((capabilities & WDC_DRIVE_CAP_HW_REV_LOG_PAGE) == 0) {
+ fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
+ ret = -1;
+ goto out;
+ }
+
+ ret = nvme_get_hw_rev_log(fd, &data, 0, cfg.namespace_id);
+
+ if (strcmp(cfg.output_format, "json"))
+ nvme_show_status(ret);
+
+ if (ret == 0) {
+ fmt = validate_output_format(cfg.output_format);
+ if (fmt < 0) {
+ fprintf(stderr, "ERROR : WDC %s: invalid output format\n", __func__);
+ ret = fmt;
+ goto free_buf;
+ }
+
+ if (!data) {
+ fprintf(stderr, "ERROR : WDC : Invalid buffer to read Hardware Revision log\n");
+ ret = -1;
+ goto out;
+ }
+ switch (fmt) {
+ case NORMAL:
+ wdc_print_hw_rev_log_normal(data);
+ break;
+ case JSON:
+ wdc_print_hw_rev_log_json(data);
+ break;
+ }
+ } else {
+ fprintf(stderr, "ERROR : WDC : Unable to read Hardware Revision Log Page data\n");
+ ret = -1;
+ }
+
+free_buf:
+ if (data)
+ free(data);
+
+out:
+ nvme_free_tree(r);
+ close(fd);
+ return ret;
+}
+
+static int wdc_vs_device_waf(int argc, char **argv, struct command *command,
+ struct plugin *plugin)
+{
+ const char *desc = "Retrieve Device Write Amplication Factor";
+ const char *namespace_id = "desired namespace id";
+ struct nvme_smart_log smart_log;
+ __u8 *data;
+ int fd;
+ nvme_root_t r;
+ int ret = 0;
+ int fmt = -1;
+ __u64 capabilities = 0;
+ wdc_nvme_ext_smart_log *ext_smart_log_ptr;
+ long double data_units_written = 0,
+ phys_media_units_written_tlc = 0,
+ phys_media_units_written_slc = 0;
+ struct json_object *root = NULL;
+ char tlc_waf_str[32] = { 0 },
+ slc_waf_str[32] = { 0 };
+
+ struct config {
+ char *output_format;
+ __u32 namespace_id;
+ };
+
+ struct config cfg = {
+ .output_format = "normal",
+ .namespace_id = NVME_NSID_ALL,
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_FMT("output-format", 'o', &cfg.output_format, "Output Format: normal|json"),
+ OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
+ OPT_END()
+ };
+
+ fd = parse_and_open(argc, argv, desc, opts);
+ if (fd < 0)
+ return fd;
+
+ r = nvme_scan(NULL);
+
+ capabilities = wdc_get_drive_capabilities(r, fd);
+
+ if ((capabilities & WDC_DRIVE_CAP_DEVICE_WAF) == 0) {
+ fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
+ ret = -1;
+ goto out;
+ }
+
+ /* get data units written from the smart log page */
+ ret = nvme_get_log_smart(fd, cfg.namespace_id, true, &smart_log);
+ if (!ret) {
+ data_units_written = int128_to_double(smart_log.data_units_written);
+ }
+ else if (ret > 0) {
+ nvme_show_status(ret);
+ ret = -1;
+ goto out;
+ } else {
+ fprintf(stderr, "smart log: %s\n", nvme_strerror(errno));
+ ret = -1;
+ goto out;
+ }
+
+ /* get Physical Media Units Written from extended smart/C0 log page */
+ data = NULL;
+ ret = nvme_get_ext_smart_cloud_log(fd, &data, 0, cfg.namespace_id);
+
+ if (ret == 0) {
+ ext_smart_log_ptr = (wdc_nvme_ext_smart_log *)data;
+ phys_media_units_written_tlc = int128_to_double(ext_smart_log_ptr->ext_smart_pmuwt);
+ phys_media_units_written_slc = int128_to_double(ext_smart_log_ptr->ext_smart_pmuws);
+
+ if (data)
+ free(data);
+ } else {
+ fprintf(stderr, "ERROR : WDC %s: get smart cloud log failure\n", __func__);
+ ret = -1;
+ goto out;
+ }
+
+ if (strcmp(cfg.output_format, "json"))
+ nvme_show_status(ret);
+
+ fmt = validate_output_format(cfg.output_format);
+ if (fmt < 0) {
+ fprintf(stderr, "ERROR : WDC %s: invalid output format\n", __func__);
+ ret = fmt;
+ goto out;
+ }
+
+ if (data_units_written == 0) {
+ fprintf(stderr, "ERROR : WDC %s: 0 data units written\n", __func__);
+ ret = -1;
+ goto out;
+ }
+
+ if (fmt == NORMAL) {
+ printf("Device Write Amplification Factor TLC : %4.2Lf\n",
+ (phys_media_units_written_tlc/data_units_written));
+ printf("Device Write Amplification Factor SLC : %4.2Lf\n",
+ (phys_media_units_written_slc/data_units_written));
+ }
+ else if (fmt == JSON) {
+ root = json_create_object();
+ sprintf(tlc_waf_str, "%4.2Lf", (phys_media_units_written_tlc/data_units_written));
+ sprintf(slc_waf_str, "%4.2Lf", (phys_media_units_written_slc/data_units_written));
+
+ json_object_add_value_string(root, "Device Write Amplification Factor TLC", tlc_waf_str);
+ json_object_add_value_string(root, "Device Write Amplification Factor SLC", slc_waf_str);
+
+ json_print_object(root, NULL);
+ printf("\n");
+
+ json_free_object(root);
+ }
+
+out:
+ nvme_free_tree(r);
+ close(fd);
return ret;
}
@@ -6266,6 +7483,8 @@ static int wdc_get_latency_monitor_log(int argc, char **argv, struct command *co
fprintf(stderr, "ERROR : WDC : Failure reading the Latency Monitor (C3) Log Page, ret = %d\n", ret);
out:
+ nvme_free_tree(r);
+ close(fd);
return ret;
}
@@ -6309,6 +7528,8 @@ static int wdc_get_error_recovery_log(int argc, char **argv, struct command *com
fprintf(stderr, "ERROR : WDC : Failure reading the Error Recovery (C1) Log Page, ret = 0x%x\n", ret);
out:
+ nvme_free_tree(r);
+ close(fd);
return ret;
}
@@ -6352,6 +7573,8 @@ static int wdc_get_dev_capabilities_log(int argc, char **argv, struct command *c
fprintf(stderr, "ERROR : WDC : Failure reading the Device Capabilities (C4) Log Page, ret = 0x%x\n", ret);
out:
+ nvme_free_tree(r);
+ close(fd);
return ret;
}
@@ -6395,6 +7618,8 @@ static int wdc_get_unsupported_reqs_log(int argc, char **argv, struct command *c
fprintf(stderr, "ERROR : WDC : Failure reading the Unsupported Requirements (C5) Log Page, ret = 0x%x\n", ret);
out:
+ nvme_free_tree(r);
+ close(fd);
return ret;
}
@@ -6480,6 +7705,7 @@ static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct comma
out:
nvme_free_tree(r);
+ close(fd);
return ret;
}
@@ -6597,6 +7823,7 @@ static int wdc_drive_status(int argc, char **argv, struct command *command,
out:
nvme_free_tree(r);
+ close(fd);
return ret;
}
@@ -6647,6 +7874,7 @@ static int wdc_clear_assert_dump(int argc, char **argv, struct command *command,
out:
nvme_free_tree(r);
+ close(fd);
return ret;
}
@@ -6834,7 +8062,8 @@ static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *com
/* to retrieve fw activate history data */
if ((data = (__u8*) malloc(sizeof (__u8) * WDC_NVME_SMART_CLOUD_ATTR_LEN)) == NULL) {
fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno));
- return -1;
+ ret = -1;
+ goto out;
}
/* Get the 0xC0 log data */
@@ -6887,6 +8116,7 @@ static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *com
fprintf(stderr, "ERROR : WDC : Failure reading the FW Activate History, ret = %d\n", ret);
out:
nvme_free_tree(r);
+ close(fd);
return ret;
}
@@ -6944,15 +8174,14 @@ static int wdc_clear_fw_activate_history(int argc, char **argv, struct command *
goto out;
}
- if (capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY) {
+ if (capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY)
ret = wdc_do_clear_fw_activate_history_vuc(fd);
- }
- else {
+ else
ret = wdc_do_clear_fw_activate_history_fid(fd);
- }
out:
nvme_free_tree(r);
+ close(fd);
return ret;
}
@@ -7043,6 +8272,7 @@ static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct comm
out:
nvme_free_tree(r);
+ close(fd);
return ret;
}
@@ -7179,7 +8409,7 @@ static int wdc_get_log_dir_max_entries(int fd, __u32* maxNumOfEntries)
{
fprintf(stderr, "ERROR : WDC : %s: Failed to get headerPayloadSize from file directory 0x%x\n",
__func__, ret);
- goto end;
+ return ret;
}
fileIdOffsetsBufferSize = WDC_DE_FILE_HEADER_SIZE + (headerPayloadSize * WDC_DE_FILE_OFFSET_SIZE);
@@ -7201,9 +8431,8 @@ static int wdc_get_log_dir_max_entries(int fd, __u32* maxNumOfEntries)
continue;
(*maxNumOfEntries)++;
}
- end:
- if (!fileIdOffsetsBuffer)
- free(fileIdOffsetsBuffer);
+end:
+ free(fileIdOffsetsBuffer);
return ret;
}
@@ -7319,7 +8548,10 @@ static int wdc_fetch_log_file_from_device(int fd, __u32 fileId, __u16 spiDestn,
goto end;
}
- wdc_get_max_transfer_len(fd, &maximumTransferLength);
+ if (wdc_get_max_transfer_len(fd, &maximumTransferLength) < 0) {
+ ret = WDC_STATUS_FAILURE;
+ goto end;
+ }
/* Fetch Log File Data */
if ((fileSize >= maximumTransferLength) || (fileSize > 0xFFFFFFFF))
@@ -7379,7 +8611,8 @@ static int wdc_de_get_dump_trace(int fd, char * filePath, __u16 binFileNameLen,
return ret;
}
- wdc_get_max_transfer_len(fd, &maximumTransferLength);
+ if (wdc_get_max_transfer_len(fd, &maximumTransferLength) < 0)
+ return WDC_STATUS_FAILURE;
do
{
@@ -7757,7 +8990,7 @@ static int wdc_drive_essentials(int argc, char **argv, struct command *command,
char d[PATH_MAX] = {0};
char k[PATH_MAX] = {0};
char *d_ptr;
- int fd;
+ int fd, ret;
nvme_root_t r;
__u64 capabilities = 0;
@@ -7783,8 +9016,8 @@ static int wdc_drive_essentials(int argc, char **argv, struct command *command,
capabilities = wdc_get_drive_capabilities(r, fd);
if ((capabilities & WDC_DRIVE_CAP_DRIVE_ESSENTIALS) != WDC_DRIVE_CAP_DRIVE_ESSENTIALS) {
fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
- nvme_free_tree(r);
- return -1;
+ ret = -1;
+ goto out;
}
if (cfg.dirName != NULL) {
@@ -7794,7 +9027,11 @@ static int wdc_drive_essentials(int argc, char **argv, struct command *command,
d_ptr = NULL;
}
- return wdc_do_drive_essentials(r, fd, d_ptr, k);
+ ret = wdc_do_drive_essentials(r, fd, d_ptr, k);
+out:
+ nvme_free_tree(r);
+ close(fd);
+ return ret;
}
static int wdc_do_drive_resize(int fd, uint64_t new_size)
@@ -7885,6 +9122,7 @@ static int wdc_drive_resize(int argc, char **argv,
nvme_show_status(ret);
nvme_free_tree(r);
+ close(fd);
return ret;
}
@@ -7924,6 +9162,7 @@ static int wdc_namespace_resize(int argc, char **argv,
(cfg.op_option != 0xF))
{
fprintf(stderr, "ERROR : WDC: unsupported OP option parameter\n");
+ close(fd);
return -1;
}
@@ -7942,6 +9181,7 @@ static int wdc_namespace_resize(int argc, char **argv,
nvme_show_status(ret);
nvme_free_tree(r);
+ close(fd);
return ret;
}
@@ -8017,8 +9257,12 @@ static int wdc_reason_identifier(int argc, char **argv,
ret = -1;
goto close_fd;
}
-
- snprintf(f + strlen(f), PATH_MAX, "%s", ".bin");
+ if (strlen(f) > PATH_MAX - 5) {
+ fprintf(stderr, "ERROR : WDC: file name overflow\n");
+ ret = -1;
+ goto close_fd;
+ }
+ strcat(f, ".bin");
}
fprintf(stderr, "%s: filename = %s\n", __func__, f);
@@ -8060,6 +9304,7 @@ static const char *nvme_log_id_to_string(__u8 log_id)
case WDC_LOG_ID_C0: return "WDC Vendor Unique Log ID C0";
case WDC_LOG_ID_C1: return "WDC Vendor Unique Log ID C1";
case WDC_LOG_ID_C2: return "WDC Vendor Unique Log ID C2";
+ case WDC_LOG_ID_C3: return "WDC Vendor Unique Log ID C3";
case WDC_LOG_ID_C4: return "WDC Vendor Unique Log ID C4";
case WDC_LOG_ID_C5: return "WDC Vendor Unique Log ID C5";
case WDC_LOG_ID_C6: return "WDC Vendor Unique Log ID C6";
@@ -8114,6 +9359,7 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command
ret = validate_output_format(cfg.output_format);
if (ret < 0) {
fprintf(stderr, "%s: ERROR : WDC : invalid output format\n", __func__);
+ close(fd);
return ret;
}
ret = 0;
@@ -8172,6 +9418,7 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command
out:
nvme_free_tree(r);
+ close(fd);
return ret;
}
@@ -8229,7 +9476,11 @@ static int wdc_save_reason_id(int fd, __u8 *rsn_ident, int size)
/* make the nvmecli dir in /usr/local if it doesn't already exist */
if (stat(reason_id_path, &st) == -1) {
- mkdir(reason_id_path, 0700);
+ if (mkdir(reason_id_path, 0700) < 0) {
+ fprintf(stderr, "%s: ERROR : failed to mkdir %s : %s\n",
+ __func__, reason_id_path, strerror(errno));
+ return -1;
+ }
}
if (asprintf(&reason_id_file, "%s/%s%s", reason_id_path,
@@ -8472,9 +9723,9 @@ static void wdc_print_nand_stats_json(__u16 version, void *data)
case 0:
- json_object_add_value_float(root, "NAND Writes TLC (Bytes)",
+ json_object_add_value_double(root, "NAND Writes TLC (Bytes)",
int128_to_double(nand_stats->nand_write_tlc));
- json_object_add_value_float(root, "NAND Writes SLC (Bytes)",
+ json_object_add_value_double(root, "NAND Writes SLC (Bytes)",
int128_to_double(nand_stats->nand_write_slc));
json_object_add_value_uint(root, "NAND Program Failures",
le32_to_cpu(nand_stats->nand_prog_failure));
@@ -8495,9 +9746,9 @@ static void wdc_print_nand_stats_json(__u16 version, void *data)
case 3:
- json_object_add_value_float(root, "NAND Writes TLC (Bytes)",
+ json_object_add_value_double(root, "NAND Writes TLC (Bytes)",
int128_to_double(nand_stats_v3->nand_write_tlc));
- json_object_add_value_float(root, "NAND Writes SLC (Bytes)",
+ json_object_add_value_double(root, "NAND Writes SLC (Bytes)",
int128_to_double(nand_stats_v3->nand_write_slc));
temp_ptr = (__u64 *)nand_stats_v3->bad_nand_block_count;
temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF);
@@ -8548,7 +9799,7 @@ static void wdc_print_nand_stats_json(__u16 version, void *data)
le64_to_cpu(nand_stats_v3->security_version_number));
json_object_add_value_uint(root, "% Free Blocks (System)",
nand_stats_v3->percent_free_blocks_system);
- json_object_add_value_float(root, "Data Set Management Commands",
+ json_object_add_value_double(root, "Data Set Management Commands",
int128_to_double(nand_stats_v3->trim_completions));
json_object_add_value_uint64(root, "Estimate of Incomplete Trim Data",
le64_to_cpu(nand_stats_v3->trim_completions[16]));
@@ -8567,7 +9818,7 @@ static void wdc_print_nand_stats_json(__u16 version, void *data)
le16_to_cpu(temp_norm));
json_object_add_value_uint64(root, "Bad System Nand Block Count - Raw",
le64_to_cpu(temp_raw));
- json_object_add_value_float(root, "Endurance Estimate",
+ json_object_add_value_double(root, "Endurance Estimate",
int128_to_double(nand_stats_v3->endurance_estimate));
json_object_add_value_uint(root, "Thermal Throttling Status",
nand_stats_v3->thermal_throttling_st_ct[0]);
@@ -8575,7 +9826,7 @@ static void wdc_print_nand_stats_json(__u16 version, void *data)
nand_stats_v3->thermal_throttling_st_ct[1]);
json_object_add_value_uint64(root, "Unaligned I/O",
le64_to_cpu(nand_stats_v3->unaligned_IO));
- json_object_add_value_float(root, "Physical Media Units Read",
+ json_object_add_value_double(root, "Physical Media Units Read",
int128_to_double(nand_stats_v3->physical_media_units));
json_object_add_value_uint(root, "log page version",
le16_to_cpu(nand_stats_v3->log_page_version));
@@ -8677,6 +9928,43 @@ static void wdc_print_pcie_stats_json(struct wdc_vs_pcie_stats *pcie_stats)
json_free_object(root);
}
+static int wdc_do_vs_nand_stats_sn810_2(int fd, char *format)
+{
+ int ret;
+ int fmt = -1;
+ uint8_t *data = NULL;
+
+ data = NULL;
+ ret = nvme_get_ext_smart_cloud_log(fd, &data, 0, NVME_NSID_ALL);
+
+ if (ret) {
+ fprintf(stderr, "ERROR : WDC : %s : Failed to retreive NAND stats\n", __func__);
+ goto out;
+ } else {
+ fmt = validate_output_format(format);
+ if (fmt < 0) {
+ fprintf(stderr, "ERROR : WDC : %s : invalid output format\n", __func__);
+ ret = fmt;
+ goto out;
+ }
+
+ /* parse the data */
+ switch (fmt) {
+ case NORMAL:
+ wdc_print_ext_smart_cloud_log_normal(data, WDC_SCA_V1_NAND_STATS);
+ break;
+ case JSON:
+ wdc_print_ext_smart_cloud_log_json(data, WDC_SCA_V1_NAND_STATS);
+ break;
+ }
+ }
+
+out:
+ if (data)
+ free(data);
+ return ret;
+}
+
static int wdc_do_vs_nand_stats(int fd, char *format)
{
int ret;
@@ -8730,6 +10018,7 @@ static int wdc_vs_nand_stats(int argc, char **argv, struct command *command,
int ret = 0;
nvme_root_t r;
__u64 capabilities = 0;
+ uint32_t read_device_id = 0, read_vendor_id = 0;
struct config {
char *output_format;
@@ -8755,12 +10044,28 @@ static int wdc_vs_nand_stats(int argc, char **argv, struct command *command,
fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
ret = -1;
} else {
- ret = wdc_do_vs_nand_stats(fd, cfg.output_format);
- if (ret)
- fprintf(stderr, "ERROR : WDC : Failure reading NAND statistics, ret = %d\n", ret);
+ ret = wdc_get_pci_ids(r, &read_device_id, &read_vendor_id);
+ if (ret < 0)
+ {
+ fprintf(stderr, "ERROR : WDC: %s: failure to get pci ids, ret = %d\n", __func__, ret);
+ return -1;
+ }
+
+ switch (read_device_id) {
+ case WDC_NVME_SN820CL_DEV_ID:
+ ret = wdc_do_vs_nand_stats_sn810_2(fd, cfg.output_format);
+ break;
+ default:
+ ret = wdc_do_vs_nand_stats(fd, cfg.output_format);
+ break;
+ }
}
+ if (ret)
+ fprintf(stderr, "ERROR : WDC : Failure reading NAND statistics, ret = %d\n", ret);
+
nvme_free_tree(r);
+ close(fd);
return ret;
}
@@ -8856,6 +10161,7 @@ static int wdc_vs_pcie_stats(int argc, char **argv, struct command *command,
out:
nvme_free_tree(r);
+ close(fd);
return ret;
}
@@ -8872,10 +10178,15 @@ static int wdc_vs_drive_info(int argc, char **argv,
struct nvme_id_ctrl ctrl;
char vsData[32] = {0};
char major_rev = 0, minor_rev = 0;
+ __u8 *data = NULL;
+ __u32 ftl_unit_size = 0, tcg_dev_ownership = 0;
+ __u16 boot_spec_major = 0, boot_spec_minor = 0;
int fmt = -1;
struct json_object *root = NULL;
char formatter[41] = { 0 };
- char rev_str[8] = { 0 };
+ char rev_str[16] = { 0 };
+ uint32_t read_device_id = -1, read_vendor_id = -1;
+ wdc_nvme_ext_smart_log *ext_smart_log_ptr = NULL;
struct config {
char *output_format;
@@ -8897,6 +10208,7 @@ static int wdc_vs_drive_info(int argc, char **argv,
fmt = validate_output_format(cfg.output_format);
if (fmt < 0) {
fprintf(stderr, "ERROR : WDC %s invalid output format\n", __func__);
+ close(fd);
return fmt;
}
@@ -8905,6 +10217,7 @@ static int wdc_vs_drive_info(int argc, char **argv,
if (ret) {
fprintf(stderr, "ERROR : WDC %s: Identify Controller failed\n", __func__);
+ close(fd);
return ret;
}
@@ -8912,24 +10225,72 @@ static int wdc_vs_drive_info(int argc, char **argv,
wdc_check_device(r, fd);
capabilities = wdc_get_drive_capabilities(r, fd);
if ((capabilities & WDC_DRIVE_CAP_INFO) == WDC_DRIVE_CAP_INFO) {
- ret = wdc_do_drive_info(fd, &result);
+ ret = wdc_get_pci_ids(r, &read_device_id, &read_vendor_id);
+ if (ret < 0)
+ {
+ fprintf(stderr, "ERROR : WDC: %s: failure to get pci ids, ret = %d\n", __func__, ret);
+ goto out;
+ }
- if (!ret) {
- size = (__u16)((cpu_to_le32(result) & 0xffff0000) >> 16);
- rev = (double)(cpu_to_le32(result) & 0x0000ffff);
+ switch (read_device_id) {
+ case WDC_NVME_SN640_DEV_ID:
+ case WDC_NVME_SN640_DEV_ID_1:
+ case WDC_NVME_SN640_DEV_ID_2:
+ case WDC_NVME_SN640_DEV_ID_3:
+ case WDC_NVME_SN650_DEV_ID:
+ case WDC_NVME_SN650_DEV_ID_1:
+ case WDC_NVME_SN650_DEV_ID_2:
+ case WDC_NVME_SN650_DEV_ID_3:
+ case WDC_NVME_SN650_DEV_ID_4:
+ case WDC_NVME_SN655_DEV_ID:
+ case WDC_NVME_SN560_DEV_ID_1:
+ case WDC_NVME_SN560_DEV_ID_2:
+ case WDC_NVME_SN560_DEV_ID_3:
+ case WDC_NVME_SN550_DEV_ID:
+ case WDC_NVME_ZN350_DEV_ID:
+ case WDC_NVME_ZN350_DEV_ID_1:
+ ret = wdc_do_drive_info(fd, &result);
+
+ if (!ret) {
+ size = (__u16)((cpu_to_le32(result) & 0xffff0000) >> 16);
+ rev = (double)(cpu_to_le32(result) & 0x0000ffff);
+
+ if (fmt == NORMAL) {
+ printf("Drive HW Revison: %4.1f\n", (.1 * rev));
+ printf("FTL Unit Size: 0x%x KB\n", size);
+ printf("Customer SN: %-.*s\n", (int)sizeof(ctrl.sn), &ctrl.sn[0]);
+ }
+ else if (fmt == JSON) {
+ root = json_create_object();
+ sprintf(rev_str, "%4.1f", (.1 * rev));
+ json_object_add_value_string(root, "Drive HW Revison", rev_str);
+
+ json_object_add_value_int(root, "FTL Unit Size", le16_to_cpu(size));
+ wdc_StrFormat(formatter, sizeof(formatter), &ctrl.sn[0], sizeof(ctrl.sn));
+ json_object_add_value_string(root, "Customer SN", formatter);
+
+ json_print_object(root, NULL);
+ printf("\n");
+
+ json_free_object(root);
+ }
+ }
+ break;
+ case WDC_NVME_SN730A_DEV_ID:
+ memcpy(vsData, &ctrl.vs[0], 32);
+
+ major_rev = ctrl.sn[12];
+ minor_rev = ctrl.sn[13];
if (fmt == NORMAL) {
- printf("Drive HW Revison: %4.1f\n", (.1 * rev));
- printf("FTL Unit Size: 0x%x KB\n", size);
- printf("Customer SN: %-.*s\n", (int)sizeof(ctrl.sn), &ctrl.sn[0]);
+ printf("Drive HW Revision: %c.%c \n", major_rev, minor_rev);
+ printf("Customer SN: %-.*s\n", 14, &ctrl.sn[0]);
}
else if (fmt == JSON) {
root = json_create_object();
- sprintf(rev_str, "%4.1f", (.1 * rev));
+ sprintf(rev_str, "%c.%c", major_rev, minor_rev);
json_object_add_value_string(root, "Drive HW Revison", rev_str);
-
- json_object_add_value_int(root, "FTL Unit Size", le16_to_cpu(size));
- wdc_StrFormat(formatter, sizeof(formatter), &ctrl.sn[0], sizeof(ctrl.sn));
+ wdc_StrFormat(formatter, sizeof(formatter), &ctrl.sn[0], 14);
json_object_add_value_string(root, "Customer SN", formatter);
json_print_object(root, NULL);
@@ -8937,39 +10298,87 @@ static int wdc_vs_drive_info(int argc, char **argv,
json_free_object(root);
}
- }
- }
- else if ((capabilities & WDC_DRIVE_CAP_INFO_2) == WDC_DRIVE_CAP_INFO_2) {
- memcpy(vsData, &ctrl.vs[0], 32);
+ break;
+ case WDC_NVME_SN820CL_DEV_ID:
+ /* Get the Drive HW Rev from the C6 Log page */
+ ret = nvme_get_hw_rev_log(fd, &data, 0, NVME_NSID_ALL);
+ if (ret == 0) {
+ wdc_nvme_hw_rev_log *log_data = (wdc_nvme_hw_rev_log *)data;
+ major_rev = log_data->hw_rev_gdr;
- major_rev = ctrl.sn[12];
- minor_rev = ctrl.sn[13];
+ free(data);
+ data = NULL;
+ } else {
+ fprintf(stderr, "ERROR : WDC: %s: failure to get hw revision log\n", __func__);
+ ret = -1;
+ goto out;
+ }
- if (fmt == NORMAL) {
- printf("Drive HW Revision: %c.%c \n", major_rev, minor_rev);
- printf("Customer SN: %-.*s\n", 14, &ctrl.sn[0]);
- }
- else if (fmt == JSON) {
- root = json_create_object();
- sprintf(rev_str, "%c.%c", major_rev, minor_rev);
- json_object_add_value_string(root, "Drive HW Revison", rev_str);
- wdc_StrFormat(formatter, sizeof(formatter), &ctrl.sn[0], 14);
- json_object_add_value_string(root, "Customer SN", formatter);
-
- json_print_object(root, NULL);
- printf("\n");
+ /* Get the Smart C0 log page */
+ if ((capabilities & WDC_DRIVE_CAP_CLOUD_LOG_PAGE) == 0) {
+ fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
+ ret = -1;
+ goto out;
+ }
+
+ ret = nvme_get_ext_smart_cloud_log(fd, &data, 0, NVME_NSID_ALL);
- json_free_object(root);
+ if (ret == 0) {
+ ext_smart_log_ptr = (wdc_nvme_ext_smart_log *)data;
+
+ /* Set the FTL Unit size */
+ ftl_unit_size = le32_to_cpu(ext_smart_log_ptr->ext_smart_ftlus);
+
+ /* Set the Boot Spec Version */
+ boot_spec_major = le16_to_cpu(ext_smart_log_ptr->ext_smart_maj);
+ boot_spec_minor = le16_to_cpu(ext_smart_log_ptr->ext_smart_min);
+
+ /* Set the Drive Ownership Status */
+ tcg_dev_ownership = le32_to_cpu(ext_smart_log_ptr->ext_smart_tcgos);
+ free(data);
+ } else {
+ fprintf(stderr, "ERROR : WDC: %s: failure to get extended smart cloud log\n", __func__);
+ ret = -1;
+ goto out;
+ }
+
+ if (fmt == NORMAL) {
+ printf("Drive HW Revision: %2d\n", major_rev);
+ printf("FTL Unit Size: %d\n", ftl_unit_size);
+ printf("HyperScale Boot Version Spec: %d.%d\n", boot_spec_major, boot_spec_minor);
+ printf("TCG Device Ownership Status: %2d\n", tcg_dev_ownership);
+
+ }
+ else if (fmt == JSON) {
+ root = json_create_object();
+
+ json_object_add_value_int(root, "Drive HW Revison", major_rev);
+ json_object_add_value_int(root, "FTL Unit Size", ftl_unit_size);
+ sprintf(rev_str, "%d.%d", boot_spec_major, boot_spec_minor);
+ json_object_add_value_string(root, "HyperScale Boot Version Spec", rev_str);
+ json_object_add_value_int(root, "TCG Device Ownership Status", tcg_dev_ownership);
+
+ json_print_object(root, NULL);
+ printf("\n");
+
+ json_free_object(root);
+ }
+
+ break;
+ default:
+ fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
+ ret = -1;
+ break;
}
} else {
- fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
- nvme_free_tree(r);
- return -1;
+ fprintf(stderr, "ERROR : WDC: capability not supported by this device\n");
+ ret = -1;
}
-
+out:
nvme_show_status(ret);
nvme_free_tree(r);
+ close(fd);
return ret;
}
@@ -9008,7 +10417,7 @@ static int wdc_vs_temperature_stats(int argc, char **argv,
if (fmt < 0) {
fprintf(stderr, "ERROR : WDC : invalid output format\n");
ret = fmt;
- goto END;
+ goto out;
}
/* check if command is supported */
@@ -9016,17 +10425,17 @@ static int wdc_vs_temperature_stats(int argc, char **argv,
capabilities = wdc_get_drive_capabilities(r, fd);
if ((capabilities & WDC_DRIVE_CAP_TEMP_STATS) != WDC_DRIVE_CAP_TEMP_STATS) {
fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
- nvme_free_tree(r);
- return -1;
+ ret = -1;
+ goto out;
}
/* get the temperature stats or report errors */
ret = nvme_identify_ctrl(fd, &id_ctrl);
if (ret != 0)
- goto END;
+ goto out;
ret = nvme_get_log_smart(fd, NVME_NSID_ALL, false, &smart_log);
if (ret != 0)
- goto END;
+ goto out;
/* convert from Kelvin to degrees Celsius */
temperature = ((smart_log.temperature[1] << 8) | smart_log.temperature[0]) - 273;
@@ -9083,9 +10492,10 @@ static int wdc_vs_temperature_stats(int argc, char **argv,
else
printf("%s: Invalid format\n", __func__);
-END:
+out:
nvme_show_status(ret);
nvme_free_tree(r);
+ close(fd);
return ret;
}
@@ -9165,7 +10575,7 @@ static int wdc_capabilities(int argc, char **argv,
printf("namespace-resize : %s\n",
capabilities & WDC_DRIVE_CAP_NS_RESIZE ? "Supported" : "Not Supported");
printf("vs-drive-info : %s\n",
- capabilities & (WDC_DRIVE_CAP_INFO | WDC_DRIVE_CAP_INFO_2) ? "Supported" : "Not Supported");
+ capabilities & WDC_DRIVE_CAP_INFO ? "Supported" : "Not Supported");
printf("vs-temperature-stats : %s\n",
capabilities & WDC_DRIVE_CAP_TEMP_STATS ? "Supported" : "Not Supported");
printf("cloud-SSD-plugin-version : %s\n",
@@ -9178,8 +10588,19 @@ static int wdc_capabilities(int argc, char **argv,
capabilities & WDC_DRIVE_CAP_OCP_C4_LOG_PAGE ? "Supported" : "Not Supported");
printf("get-unsupported-reqs-log : %s\n",
capabilities & WDC_DRIVE_CAP_OCP_C5_LOG_PAGE ? "Supported" : "Not Supported");
- printf("capabilities : Supported\n");
+ printf("get-latency-monitor-log : %s\n",
+ capabilities & WDC_DRIVE_CAP_C3_LOG_PAGE ? "Supported" : "Not Supported");
+ printf("cloud-boot-SSD-version : %s\n",
+ capabilities & WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION ? "Supported" : "Not Supported");
+ printf("vs-cloud-log : %s\n",
+ capabilities & WDC_DRIVE_CAP_CLOUD_LOG_PAGE ? "Supported" : "Not Supported");
+ printf("vs-hw-rev-log : %s\n",
+ capabilities & WDC_DRIVE_CAP_HW_REV_LOG_PAGE ? "Supported" : "Not Supported");
+ printf("vs-device_waf : %s\n",
+ capabilities & WDC_DRIVE_CAP_DEVICE_WAF ? "Supported" : "Not Supported");
+ printf("capabilities : Supported\n");
nvme_free_tree(r);
+ close(fd);
return 0;
}
@@ -9212,9 +10633,72 @@ static int wdc_cloud_ssd_plugin_version(int argc, char **argv,
}
nvme_free_tree(r);
+ close(fd);
return 0;
}
+static int wdc_cloud_boot_SSD_version(int argc, char **argv,
+ struct command *command, struct plugin *plugin)
+{
+ const char *desc = "Get Cloud Boot SSD Version command.";
+ const char *namespace_id = "desired namespace id";
+ nvme_root_t r;
+ uint64_t capabilities = 0;
+ int fd, ret = -1;
+ int major = 0, minor = 0;
+ __u8 *data = NULL;
+ wdc_nvme_ext_smart_log *ext_smart_log_ptr = NULL;
+
+ struct config {
+ __u32 namespace_id;
+ };
+
+ struct config cfg = {
+ .namespace_id = NVME_NSID_ALL,
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
+ OPT_END()
+ };
+
+ fd = parse_and_open(argc, argv, desc, opts);
+ if (fd < 0)
+ return fd;
+
+ /* get capabilities */
+ r = nvme_scan(NULL);
+ wdc_check_device(r, fd);
+ capabilities = wdc_get_drive_capabilities(r, fd);
+
+ if ((capabilities & WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION) == WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION) {
+ /* Get the 0xC0 Smart Cloud Attribute V1 log data */
+ ret = nvme_get_ext_smart_cloud_log(fd, &data, 0, cfg.namespace_id);
+
+ ext_smart_log_ptr = (wdc_nvme_ext_smart_log *)data;
+ if (ret == 0) {
+ major = le16_to_cpu(ext_smart_log_ptr->ext_smart_maj);
+ minor = le16_to_cpu(ext_smart_log_ptr->ext_smart_min);
+
+ /* print the version returned from the log page */
+ printf("HyperScale Boot Version: %d.%d\n", major, minor);
+
+ } else {
+ fprintf(stderr, "ERROR : WDC : Unable to read Extended Smart/C0 Log Page data\n");
+ ret = -1;
+ }
+
+ if (data)
+ free(data);
+ } else {
+ fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
+ }
+
+ nvme_free_tree(r);
+ close(fd);
+ return ret;
+}
+
static int wdc_enc_get_log(int argc, char **argv, struct command *command,
struct plugin *plugin)
{
@@ -9226,7 +10710,7 @@ static int wdc_enc_get_log(int argc, char **argv, struct command *command,
int xfer_size = 0;
int fd;
int len;
- int err;
+ int err = 0;
struct config {
char *file;
@@ -9247,7 +10731,7 @@ static int wdc_enc_get_log(int argc, char **argv, struct command *command,
OPT_END()
};
- err = fd = parse_and_open(argc, argv, desc, opts);
+ fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0) {
goto ret;
}
@@ -9402,9 +10886,9 @@ static int wdc_enc_submit_move_data(int fd, char *cmd, int len, int xfer_size, F
}
}
} while (more);
- free(buf);
}
+ free(buf);
return err;
}