]> www.infradead.org Git - users/hch/nvme-cli.git/commitdiff
Add function to list power descriptor, and show vendor specific log
authorQuyen Truong <quyen.truong@virtium.com>
Tue, 17 Mar 2020 04:43:59 +0000 (11:43 +0700)
committerKeith Busch <kbusch@kernel.org>
Tue, 17 Mar 2020 15:47:12 +0000 (09:47 -0600)
Fix spelling mistake

plugins/virtium/virtium-nvme.c

index 5d5f7bb406eda300c7eefc773f1d95c6b5338828..47b0fdc9ad1ddf9210fc3dc08f27da0d98b28cb9 100644 (file)
@@ -121,11 +121,25 @@ static void vt_convert_smart_data_to_human_readable_format(struct vtview_smart_l
        char tempbuff[1024] = "";
        int i;
        int temperature = ((smart->raw_smart.temperature[1] << 8) | smart->raw_smart.temperature[0]) - 273;
+       double capacity;
+       char *curlocale;
+       char *templocale;
+
+       curlocale = setlocale(LC_ALL, NULL);
+       templocale = strdup(curlocale);
+
+       if (NULL == templocale)
+               printf("Cannot malloc buffer\n");
+
+       setlocale(LC_ALL, "C");
+
+       long long int lba = 1 << smart->raw_ns.lbaf[(smart->raw_ns.flbas & 0x0f)].ds;
+       capacity = le64_to_cpu(smart->raw_ns.nsze) * lba;
 
        snprintf(tempbuff, sizeof(tempbuff), "log;%s;%lu;%s;%s;%-.*s;", smart->raw_ctrl.sn, smart->time_stamp, smart->path,
-       smart->raw_ctrl.mn, (int)sizeof(smart->raw_ctrl.fr), smart->raw_ctrl.fr);
+               smart->raw_ctrl.mn, (int)sizeof(smart->raw_ctrl.fr), smart->raw_ctrl.fr);
        strcpy(text, tempbuff);
-       snprintf(tempbuff, sizeof(tempbuff), "Capacity;%f;", (double)le64_to_cpu(smart->raw_ns.nsze) / 1000000000);
+       snprintf(tempbuff, sizeof(tempbuff), "Capacity;%lf;", capacity / 1000000000);
        strcat(text, tempbuff);
        snprintf(tempbuff, sizeof(tempbuff), "Critical_Warning;%u;", smart->raw_smart.critical_warning);
        strcat(text, tempbuff);
@@ -164,7 +178,7 @@ static void vt_convert_smart_data_to_human_readable_format(struct vtview_smart_l
 
        for (i = 0; i < 8; i++) {
                __s32 temp = le16_to_cpu(smart->raw_smart.temp_sensor[i]);
-               if(0 == temp) {
+               if (0 == temp) {
                        snprintf(tempbuff, sizeof(tempbuff), "Temperature_Sensor_%d;NC;", i);
                        strcat(text, tempbuff);
                        continue;
@@ -182,8 +196,11 @@ static void vt_convert_smart_data_to_human_readable_format(struct vtview_smart_l
        snprintf(tempbuff, sizeof(tempbuff), "Thermal_Management_T2_Total_Time;%u;", le32_to_cpu(smart->raw_smart.thm_temp2_total_time));
        strcat(text, tempbuff);
 
-       snprintf(tempbuff, sizeof(tempbuff), "Reversed_1;%d;\n", 0);
+       snprintf(tempbuff, sizeof(tempbuff), "NandWrites;%d;\n", 0);
        strcat(text, tempbuff);
+
+       setlocale(LC_ALL, templocale);
+       free(templocale);
 }
 
 static void vt_header_to_string(const struct vtview_log_header *header, char *text)
@@ -268,7 +285,7 @@ static int vt_add_entry_to_log(const int fd, const char *path, const struct vtvi
        smart.time_stamp = time(NULL);
        nsid = nvme_get_nsid(fd);
 
-       if (nsid <= 0)  {
+       if (nsid <= 0) {
                printf("Cannot read namespace-id\n");
                return -1;
        }
@@ -364,215 +381,308 @@ static void vt_build_identify_lv2(unsigned int data, unsigned int start,
                printf("    },\n");
 }
 
-static void vt_parse_detail_identify(const struct nvme_id_ctrl *ctrl)
+static void vt_build_power_state_descriptor(const struct nvme_id_ctrl *ctrl)
 {
+       unsigned int i;
        unsigned char *buf;
-       unsigned int temp, pos;
-       char s[1024] = "";
-
-       const char *CMICtable[6] =  {
-                               "0 = the NVM subsystem contains only a single NVM subsystem port",
-                               "1 = the NVM subsystem may contain more than one subsystem ports",
-                               "0 = the NVM subsystem contains only a single controller",
-                               "1 = the NVM subsystem may contain two or more controllers (see section 1.4.1)",
-                               "0 = the controller is associated with a PCI Function or a Fabrics connection",
-                               "1 = the controller is associated with an SR-IOV Virtual Function"
-       };
-
-       const char *OAEStable[18] = {
-                               "Reversed",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "0 = does not support sending the Namespace Attribute Notices event nor the associated Changed Namespace List log page",
-                               "1 = supports sending the Namespace Attribute Notices  & the associated Changed Namespace List log page",
-                               "0 = does not support sending sending Firmware Activation Notices event",
-                               "1 = supports sending Firmware Activation Notices"
-       };
-
-       const char *CTRATTtable[4] =  {
-                               "0 = does not support a 128-bit Host Identifier",
-                               "1 = supports a 128-bit Host Identifier",
-                               "0 = does not support Non-Operational Power State Permissive Mode",
-                               "1 = supports Non-Operational Power State Permissive Mode"
-       };
-
-       const char *OACStable[18] =  {
-                               "0 = does not support the Security Send and Security Receive commands",
-                               "1 = supports the Security Send and Security Receive commands",
-                               "0 = does not support the Format NVM command",
-                               "1 = supports the Format NVM command",
-                               "0 = does not support the Firmware Commit and Firmware Image Download commands",
-                               "1 = supports the Firmware Commit and Firmware Image Download commands",
-                               "0 = does not support the Namespace Management capability",
-                               "1 = supports the Namespace Management capability",
-                               "0 = does not support the Device Self-test command",
-                               "1 = supports the Device Self-test command",
-                               "0 = does not support Directives",
-                               "1 = supports Directive Send & Directive Receive commands",
-                               "0 = does not support the NVMe-MI Send and NVMe-MI Receive commands",
-                               "1 = supports the NVMe-MI Send and NVMe-MI Receive commands",
-                               "0 = does not support the Virtualization Management command",
-                               "1 = supports the Virtualization Management command",
-                               "0 = does not support the Doorbell Buffer Config command",
-                               "1 = supports the Doorbell Buffer Config command"
-       };
-
-       const char *FRMWtable[10] = {
-                               "0 = the 1st firmware slot (slot 1) is read/write",
-                               "1 = the 1st firmware slot (slot 1) is read only",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "0 = requires a reset for firmware to be activated",
-                               "1 = supports firmware activation without a reset"
-       };
-
-       const char *LPAtable[8] =  {
-                               "0 = does not support the SMART / Health information log page on a per namespace basis",
-                               "1 = supports the SMART / Health information log page on a per namespace basis",
-                               "0 = does not support the Commands Supported & Effects log page",
-                               "1 = supports the Commands Supported Effects log page",
-                               "0 = does not support extended data for Get Log Page",
-                               "1 = supports extended data for Get Log Page (including extended Number of Dwords and Log Page Offset fields)",
-                               "0 = does not support the Telemetry Host-Initiated and Telemetry Controller-Initiated log pages and Telemetry Log Notices events",
-                               "1 = supports the Telemetry Host-Initiated and Telemetry Controller-Initiated log pages and sending Telemetry Log Notices"
-       };
-
-       const char *AVSCCtable[2] = {
-                               "0 = the format of all Admin Vendor Specific Commands are vendor specific",
-                               "1 = all Admin Vendor Specific Commands use the format defined in NVM Express specification"
-       };
-
-       const char *APSTAtable[2] = {
-                               "0 = does not support autonomous power state transitions",
-                               "1 = supports autonomous power state transitions"
-       };
-
-       const char *DSTOtable[2] =  {
-                               "0 = the NVM subsystem supports one device self-test operation per controller at a time",
-                               "1 = the NVM subsystem supports only one device self-test operation in progress at a time"
-       };
-
-       const char *HCTMAtable[2] = {
-                               "0 = does not support host controlled thermal management",
-                               "1 = supports host controlled thermal management. Supports Set Features & Get Features commands with the Feature Identifier field set to 10h"
-       };
 
-       const char *SANICAPtable[6] =  {
-                               "0 = does not support the Crypto Erase sanitize operation",
-                               "1 = supports the Crypto Erase sanitize operation",
-                               "0 = does not support the Block Erase sanitize operation",
-                               "1 = supports the Block Erase sanitize operation",
-                               "0 = does not support the Overwrite sanitize operation",
-                               "1 = supports the Overwrite sanitize operation"
-       };
-
-       const char *ONCStable[14] =  {
-                               "0 = does not support the Compare command",
-                               "1 = supports the Compare command",
-                               "0 = does not support the Write Uncorrectable command",
-                               "1 = supports the Write Uncorrectable command",
-                               "0 = does not support the Dataset Management command",
-                               "1 = supports the Dataset Management command",
-                               "0 = does not support the Write Zeroes command",
-                               "1 = supports the Write Zeroes command",
-                               "0 = does not support the Save field set to a non-zero value in the Set Features and the Get Features commands",
-                               "1 = supports the Save field set to a non-zero value in the Set Features and the Get Features commands",
-                               "0 = does not support reservations",
-                               "1 = supports reservations",
-                               "0 = does not support the Timestamp feature (refer to section 5.21.1.14)",
-                               "1 = supports the Timestamp feature"
-       };
-
-       const char *FUSEStable[2] =  {
-                               "0 =  does not support the Compare and Write fused operation",
-                               "1 =  supports the Compare and Write fused operation"
-       };
+       printf("{\n");
+       printf("\"Power State Descriptors\":{\n");
+       printf("    \"NOPS\":\"Non-Operational State,\"\n");
+       printf("    \"MPS\":\"Max Power Scale (0: in 0.01 Watts; 1: in 0.0001 Watts),\"\n");
+       printf("    \"ENLAT\":\"Entry Latency in microseconds,\"\n");
+       printf("    \"RWL\":\"Relative Write Latency,\"\n");
+       printf("    \"RRL\":\"Relative Read Latency,\"\n");
+       printf("    \"IPS\":\"Idle Power Scale (00b: Not reported; 01b: 0.0001 W; 10b: 0.01 W; 11b: Reserved),\"\n");
+       printf("    \"APS\":\"Active Power Scale (00b: Not reported; 01b: 0.0001 W; 10b: 0.01 W; 11b: Reserved),\"\n");
+       printf("    \"ACTP\":\"Active Power,\"\n");
+       printf("    \"MP\":\"Maximum Power,\"\n");
+       printf("    \"EXLAT\":\"Exit Latency in microsecond,\"\n");
+       printf("    \"RWT\":\"Relative Write Throughput,\"\n");
+       printf("    \"RRT\":\"Relative Read Throughput,\"\n");
+       printf("    \"IDLP\":\"Idle Power,\"\n");
+       printf("    \"APW\":\"Active Power Workload,\"\n");
+       printf("    \"Ofs\":\"BYTE Offset,\"\n");
+
+       printf("    \"Power State Descriptors\":\"\n");
+
+       printf("%6s%10s%5s%4s%6s%10s%10s%10s%4s%4s%4s%4s%10s%4s%6s%10s%4s%5s%6s\n", "Entry", "0fs 00-03", "NOPS", "MPS", "MP", "ENLAT", "EXLAT", "0fs 12-15",
+                       "RWL", "RWT", "RRL", "RRT", "0fs 16-19", "IPS", "IDLP", "0fs 20-23", "APS", "APW", "ACTP");
+
+
+       printf("%6s%10s%5s%4s%6s%10s%10s%10s%4s%4s%4s%4s%10s%4s%6s%10s%4s%5s%6s\n", "=====", "=========", "====", "===", "=====", "=========", "=========",
+                       "=========", "===", "===", "===", "===", "=========", "===", "=====", "=========", "===", "====", "=====");
+
+       for (i = 0; i < 32; i++) {
+               char s[100];
+               unsigned int temp;
+
+               printf("%6d", i);
+               buf = (unsigned char*) (&ctrl->psd[i]);
+               vt_convert_data_buffer_to_hex_string(&buf[0], 4, true, s);
+               printf("%9sh", s);
+
+               temp = ctrl->psd[i].flags;
+               printf("%4ub", ((unsigned char)temp & 0x02));
+               printf("%3ub", ((unsigned char)temp & 0x01));
+               vt_convert_data_buffer_to_hex_string(&buf[0], 2, true, s);
+               printf("%5sh", s);
+
+               vt_convert_data_buffer_to_hex_string(&buf[4], 4, true, s);
+               printf("%9sh", s);
+               vt_convert_data_buffer_to_hex_string(&buf[8], 4, true, s);
+               printf("%9sh", s);
+               vt_convert_data_buffer_to_hex_string(&buf[12], 4, true, s);
+               printf("%9sh", s);
+               vt_convert_data_buffer_to_hex_string(&buf[15], 1, true, s);
+               printf("%3sh", s);
+               vt_convert_data_buffer_to_hex_string(&buf[14], 1, true, s);
+               printf("%3sh", s);
+               vt_convert_data_buffer_to_hex_string(&buf[13], 1, true, s);
+               printf("%3sh", s);
+               vt_convert_data_buffer_to_hex_string(&buf[12], 1, true, s);
+               printf("%3sh", s);
+               vt_convert_data_buffer_to_hex_string(&buf[16], 4, true, s);
+               printf("%9sh", s);
+
+               temp = ctrl->psd[i].idle_scale;
+               snprintf(s, sizeof(s), "%u%u", (((unsigned char)temp >> 6) & 0x01), (((unsigned char)temp >> 7) & 0x01));
+               printf("%3sb", s);
+
+               vt_convert_data_buffer_to_hex_string(&buf[16], 2, true, s);
+               printf("%5sh", s);
+               vt_convert_data_buffer_to_hex_string(&buf[20], 4, true, s);
+               printf("%9sh", s);
+
+               temp = ctrl->psd[i].active_work_scale;
+               snprintf(s, sizeof(s), "%u%u", (((unsigned char)temp >> 6) & 0x01), (((unsigned char)temp >> 7) & 0x01));
+               printf("%3sb", s);
+               snprintf(s, sizeof(s), "%u%u%u", (((unsigned char)temp) & 0x01), (((unsigned char)temp >> 1) & 0x01), (((unsigned char)temp >> 2) & 0x01));
+               printf("%4sb", s);
+
+               vt_convert_data_buffer_to_hex_string(&buf[20], 2, true, s);
+               printf("%5sh", s);
+               printf("\n");
+       }
 
-       const char *FNAtable[6] =  {
-                               "0 = supports format on a per namespace basis",
-                               "1 = all namespaces shall be configured with the same attributes and a format (excluding secure erase) of any namespace results in a format of all namespaces in an NVM subsystem",
-                               "0 = any secure erase performed as part of a format results in a secure erase of a particular namespace specified",
-                               "1 = any secure erase performed as part of a format operation results in a secure erase of all namespaces in the NVM subsystem",
-                               "0 = cryptographic erase is not supported",
-                               "1 = cryptographic erase is supported as part of the secure erase functionality"
-       };
+       printf("    \"}\n}\n");
 
-       const char *VWCtable[2] =  {
-                               "0 = a volatile write cache is not present",
-                               "1 = a volatile write cache is present"
-       };
+}
 
-       const char *NVSCCtable[2] =  {
-                               "0 = the format of all NVM Vendor Specific Commands are vendor specific",
-                               "1 = all NVM Vendor Specific Commands use the format defined in NVM Express specification"
-       };
+static void vt_dump_hex_data(const unsigned char *pbuff, size_t pbuffsize) {
+
+       char textbuf[33];
+       unsigned long int i, j;
+
+       textbuf[32] = '\0';
+       printf("[%08X] ", 0);
+       for (i = 0; i < pbuffsize; i++) {
+               printf("%02X ", pbuff[i]);
+
+               if (pbuff[i] >= ' ' && pbuff[i] <= '~') 
+                       textbuf[i % 32] = pbuff[i];
+               else 
+                       textbuf[i % 32] = '.';
+
+               if ((((i + 1) % 8) == 0) || ((i + 1) == pbuffsize)) {
+                       printf(" ");
+                       if ((i + 1) % 32 == 0) {
+                               printf(" %s\n", textbuf);
+                               if((i + 1) != pbuffsize)
+                                   printf("[%08lX] ", (i + 1));
+                       } 
+                       else if (i + 1 == pbuffsize) {
+                               textbuf[(i + 1) % 32] = '\0';
+                               if(((i + 1) % 8) == 0)
+                                       printf(" ");
+
+                               for (j = ((i + 1) % 32); j < 32; j++) {
+                                       printf("   ");
+                                       if(((j + 1) % 8) == 0)
+                                               printf(" ");
+                               }
+
+                               printf("%s\n", textbuf);
+                       }
+               }
+       }
+}
 
-       const char *SGLSSubtable[4] =  {
-                               "00b = SGLs are not supported"
-                               "01b = SGLs are supported. There is no alignment nor granularity requirement for Data Blocks",
-                               "10b = SGLs are supported. There is a Dword alignment and granularity requirement for Data Blocks",
-                               "11b = Reserved"
-       };
+static void vt_parse_detail_identify(const struct nvme_id_ctrl *ctrl)
+{
+       unsigned char *buf;
+       unsigned int temp, pos;
+       char s[1024] = "";
 
-       const char *SGLStable[42] =  {
-                               "Used"
-                               "Used",
-                               "Used",
-                               "Used",
-                               "0 = does not support the Keyed SGL Data Block descriptor",
-                               "1 = supports the Keyed SGL Data Block descriptor",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "Reserved",
-                               "0 = the SGL Bit Bucket descriptor is not supported",
-                               "1 = the SGL Bit Bucket descriptor is supported",
-                               "0 = use of a byte aligned contiguous physical buffer of metadata is not supported",
-                               "1 = use of a byte aligned contiguous physical buffer of metadata is supported",
-                               "0 = the SGL length shall be equal to the amount of data to be transferred",
-                               "1 = supports commands that contain a data or metadata SGL of a length larger than the amount of data to be transferred",
-                               "0 = use of Metadata Pointer (MPTR) that contains an address of an SGL segment containing exactly one SGL Descriptor that is Qword aligned is not supported",
-                               "1 = use of Metadata Pointer (MPTR) that contains an address of an SGL segment containing exactly one SGL Descriptor that is Qword aligned is supported",
-                               "0 = the Address field specifying an offset is not supported",
-                               "1 = supports the Address field in SGL Data Block, SGL Segment, and SGL Last Segment descriptor types specifying an offset"
-       };
+       const char *CMICtable[6] = {"0 = the NVM subsystem contains only a single NVM subsystem port",
+                                                               "1 = the NVM subsystem may contain more than one subsystem ports",
+                                                               "0 = the NVM subsystem contains only a single controller",
+                                                               "1 = the NVM subsystem may contain two or more controllers (see section 1.4.1)",
+                                                               "0 = the controller is associated with a PCI Function or a Fabrics connection",
+                                                               "1 = the controller is associated with an SR-IOV Virtual Function"};
+
+       const char *OAEStable[20] = {"Reserved",
+                                                                "Reserved",
+                                                                "Reserved",
+                                                                "Reserved",
+                                                                "Reserved",
+                                                                "Reserved",
+                                                                "Reserved",
+                                                                "Reserved",
+                                                                "Reserved",
+                                                                "Reserved",
+                                                                "Reserved",
+                                                                "Reserved",
+                                                                "Reserved",
+                                                                "Reserved",
+                                                                "Reserved",
+                                                                "Reserved",
+                                                                "0 = does not support sending the Namespace Attribute Notices event nor the associated Changed Namespace List log page",
+                                                                "1 = supports sending the Namespace Attribute Notices  & the associated Changed Namespace List log page",
+                                                                "0 = does not support sending Firmware Activation Notices event",
+                                                                "1 = supports sending Firmware Activation Notices"};
+
+       const char *CTRATTtable[4] = {"0 = does not support a 128-bit Host Identifier",
+                                                                 "1 = supports a 128-bit Host Identifier",
+                                                                 "0 = does not support Non-Operational Power State Permissive Mode",
+                                                                 "1 = supports Non-Operational Power State Permissive Mode"};
+
+       const char *OACStable[18] = {"0 = does not support the Security Send and Security Receive commands",
+                                                                "1 = supports the Security Send and Security Receive commands",
+                                                                "0 = does not support the Format NVM command",
+                                                                "1 = supports the Format NVM command",
+                                                                "0 = does not support the Firmware Commit and Firmware Image Download commands",
+                                                                "1 = supports the Firmware Commit and Firmware Image Download commands",
+                                                                "0 = does not support the Namespace Management capability",
+                                                                "1 = supports the Namespace Management capability",
+                                                                "0 = does not support the Device Self-test command",
+                                                                "1 = supports the Device Self-test command",
+                                                                "0 = does not support Directives",
+                                                                "1 = supports Directive Send & Directive Receive commands",
+                                                                "0 = does not support the NVMe-MI Send and NVMe-MI Receive commands",
+                                                                "1 = supports the NVMe-MI Send and NVMe-MI Receive commands",
+                                                                "0 = does not support the Virtualization Management command",
+                                                                "1 = supports the Virtualization Management command",
+                                                                "0 = does not support the Doorbell Buffer Config command",
+                                                                "1 = supports the Doorbell Buffer Config command"};
+
+       const char *FRMWtable[10] = {"0 = the 1st firmware slot (slot 1) is read/write",
+                                                                "1 = the 1st firmware slot (slot 1) is read only",
+                                                                "Reserved",
+                                                                "Reserved",
+                                                                "Reserved",
+                                                                "Reserved",
+                                                                "Reserved",
+                                                                "Reserved",
+                                                                "0 = requires a reset for firmware to be activated",
+                                                                "1 = supports firmware activation without a reset"};
+
+       const char *LPAtable[8] = {"0 = does not support the SMART / Health information log page on a per namespace basis",
+                                                          "1 = supports the SMART / Health information log page on a per namespace basis",
+                                                          "0 = does not support the Commands Supported & Effects log page",
+                                                          "1 = supports the Commands Supported Effects log page",
+                                                          "0 = does not support extended data for Get Log Page",
+                                                          "1 = supports extended data for Get Log Page (including extended Number of Dwords and Log Page Offset fields)",
+                                                          "0 = does not support the Telemetry Host-Initiated and Telemetry Controller-Initiated log pages and Telemetry Log Notices events",
+                                                          "1 = supports the Telemetry Host-Initiated and Telemetry Controller-Initiated log pages and sending Telemetry Log Notices"                                                      };
+
+       const char *AVSCCtable[2] = {"0 = the format of all Admin Vendor Specific Commands are vendor specific",
+                                                                "1 = all Admin Vendor Specific Commands use the format defined in NVM Express specification"};
+
+       const char *APSTAtable[2] = {"0 = does not support autonomous power state transitions",
+                                                                "1 = supports autonomous power state transitions"};
+
+       const char *DSTOtable[2] =  {"0 = the NVM subsystem supports one device self-test operation per controller at a time",
+                                                                "1 = the NVM subsystem supports only one device self-test operation in progress at a time"};
+
+       const char *HCTMAtable[2] = {"0 = does not support host controlled thermal management",
+                                                                "1 = supports host controlled thermal management. Supports Set Features & Get Features commands with the Feature Identifier field set to 10h"};
+
+       const char *SANICAPtable[6] =  {"0 = does not support the Crypto Erase sanitize operation",
+                                                                       "1 = supports the Crypto Erase sanitize operation",
+                                                                       "0 = does not support the Block Erase sanitize operation",
+                                                                       "1 = supports the Block Erase sanitize operation",
+                                                                       "0 = does not support the Overwrite sanitize operation",
+                                                                       "1 = supports the Overwrite sanitize operation"};
+
+       const char *ONCStable[14] =  {"0 = does not support the Compare command",
+                                                                 "1 = supports the Compare command",
+                                                                 "0 = does not support the Write Uncorrectable command",
+                                                                 "1 = supports the Write Uncorrectable command",
+                                                                 "0 = does not support the Dataset Management command",
+                                                                 "1 = supports the Dataset Management command",
+                                                                 "0 = does not support the Write Zeroes command",
+                                                                 "1 = supports the Write Zeroes command",
+                                                                 "0 = does not support the Save field set to a non-zero value in the Set Features and the Get Features commands",
+                                                                 "1 = supports the Save field set to a non-zero value in the Set Features and the Get Features commands", \
+                                                                 "0 = does not support reservations",
+                                                                 "1 = supports reservations",
+                                                                 "0 = does not support the Timestamp feature (refer to section 5.21.1.14)",
+                                                                 "1 = supports the Timestamp feature"};
+
+       const char *FUSEStable[2] = {"0 =  does not support the Compare and Write fused operation",
+                                                                "1 =  supports the Compare and Write fused operation"};
+
+       const char *FNAtable[6] = {"0 = supports format on a per namespace basis",
+                                                          "1 = all namespaces shall be configured with the same attributes and a format (excluding secure erase) of any namespace results in a format of all namespaces in an NVM subsystem",
+                                                          "0 = any secure erase performed as part of a format results in a secure erase of a particular namespace specified",
+                                                          "1 = any secure erase performed as part of a format operation results in a secure erase of all namespaces in the NVM subsystem",
+                                                          "0 = cryptographic erase is not supported",
+                                                          "1 = cryptographic erase is supported as part of the secure erase functionality"};
+
+       const char *VWCtable[2] = {"0 = a volatile write cache is not present",
+                                                          "1 = a volatile write cache is present"};
+
+       const char *NVSCCtable[2] = {"0 = the format of all NVM Vendor Specific Commands are vendor specific",
+                                                                "1 = all NVM Vendor Specific Commands use the format defined in NVM Express specification"};
+
+       const char *SGLSSubtable[4] =  {"00b = SGLs are not supported",
+                                                                       "01b = SGLs are supported. There is no alignment nor granularity requirement for Data Blocks",
+                                                                       "10b = SGLs are supported. There is a Dword alignment and granularity requirement for Data Blocks",
+                                                                       "11b = Reserved"};
+
+       const char *SGLStable[42] =  {"Used",
+                                                                 "Used",
+                                                                 "Used",
+                                                                 "Used",
+                                                                 "0 = does not support the Keyed SGL Data Block descriptor",
+                                                                 "1 = supports the Keyed SGL Data Block descriptor",
+                                                                 "Reserved",
+                                                                 "Reserved",
+                                                                 "Reserved",
+                                                                 "Reserved",
+                                                                 "Reserved",
+                                                                 "Reserved",
+                                                                 "Reserved",
+                                                                 "Reserved",
+                                                                 "Reserved",
+                                                                 "Reserved",
+                                                                 "Reserved",
+                                                                 "Reserved",
+                                                                 "Reserved",
+                                                                 "Reserved",
+                                                                 "Reserved",
+                                                                 "Reserved",
+                                                                 "Reserved",
+                                                                 "Reserved",
+                                                                 "Reserved",
+                                                                 "Reserved",
+                                                                 "Reserved",
+                                                                 "Reserved",
+                                                                 "Reserved",
+                                                                 "Reserved",
+                                                                 "Reserved",
+                                                                 "Reserved",
+                                                                 "0 = the SGL Bit Bucket descriptor is not supported",
+                                                                 "1 = the SGL Bit Bucket descriptor is supported",
+                                                                 "0 = use of a byte aligned contiguous physical buffer of metadata is not supported",
+                                                                 "1 = use of a byte aligned contiguous physical buffer of metadata is supported",
+                                                                 "0 = the SGL length shall be equal to the amount of data to be transferred",
+                                                                 "1 = supports commands that contain a data or metadata SGL of a length larger than the amount of data to be transferred",
+                                                                 "0 = use of Metadata Pointer (MPTR) that contains an address of an SGL segment containing exactly one SGL Descriptor that is Qword aligned is not supported",
+                                                                 "1 = use of Metadata Pointer (MPTR) that contains an address of an SGL segment containing exactly one SGL Descriptor that is Qword aligned is supported",
+                                                                 "0 = the Address field specifying an offset is not supported",
+                                     "1 = supports the Address field in SGL Data Block, SGL Segment, and SGL Last Segment descriptor types specifying an offset"};
 
        buf = (unsigned char *)(ctrl);
 
@@ -593,7 +703,7 @@ static void vt_parse_detail_identify(const struct nvme_id_ctrl *ctrl)
        printf("    \"Controller Multi-Path I/O and Namespace Sharing Capabilities\":{\n");
        vt_convert_data_buffer_to_hex_string(&buf[76], 1, true, s);
        printf("        \"Value\":\"%sh\",\n", s);
-       vt_build_identify_lv2(temp, 0, 2, CMICtable, true);
+       vt_build_identify_lv2(temp, 0, 3, CMICtable, true);
 
        vt_convert_data_buffer_to_hex_string(&buf[77], 1, true, s);
        printf("    \"Maximum Data Transfer Size\":\"%sh\",\n", s);
@@ -681,7 +791,7 @@ static void vt_parse_detail_identify(const struct nvme_id_ctrl *ctrl)
        vt_convert_data_buffer_to_hex_string(&buf[296], 16, true, s);
        printf("    \"Unallocated NVM Capacity\":\"%sh\",\n", s);
 
-       temp = le32_to_cpu(ctrl->rpmbs);
+       temp = le32_to_cpu(ctrl->rpmbs); 
        printf("    \"Replay Protected Memory Block Support\":{\n");
        vt_convert_data_buffer_to_hex_string(&buf[312], 4, true, s);
        printf("        \"Value\":\"%sh\",\n", s);
@@ -717,7 +827,7 @@ static void vt_parse_detail_identify(const struct nvme_id_ctrl *ctrl)
        vt_convert_data_buffer_to_hex_string(&buf[326], 2, true, s);
        printf("    \"Maximum Thermal Management Temperature\":\"%sh\",\n", s);
 
-       temp = le32_to_cpu(ctrl->sanicap);
+       temp = le16_to_cpu(ctrl->sanicap);
        printf("    \"Sanitize Capabilities\":{\n");
        vt_convert_data_buffer_to_hex_string(&buf[328], 2, true, s);
        printf("        \"Value\":\"%sh\",\n", s);
@@ -751,7 +861,7 @@ static void vt_parse_detail_identify(const struct nvme_id_ctrl *ctrl)
        vt_build_identify_lv2(temp, 0, 7, ONCStable, true);
 
        temp = le16_to_cpu(ctrl->fuses);
-       printf("    \"Optional NVM Command Support\":{\n");
+       printf("    \"Fused Operation Support\":{\n");
        vt_convert_data_buffer_to_hex_string(&buf[522], 2, true, s);
        printf("        \"Value\":\"%sh\",\n", s);
        vt_build_identify_lv2(temp, 0, 1, FUSEStable, true);
@@ -774,7 +884,7 @@ static void vt_parse_detail_identify(const struct nvme_id_ctrl *ctrl)
        printf("    \"Atomic Write Unit Power Fail\":\"%sh\",\n", s);
 
        temp = ctrl->nvscc;
-       printf("    \"VNVM Vendor Specific Command Configuration\":{\n");
+       printf("    \"NVM Vendor Specific Command Configuration\":{\n");
        vt_convert_data_buffer_to_hex_string(&buf[530], 1, true, s);
        printf("        \"Value\":\"%sh\",\n", s);
        vt_build_identify_lv2(temp, 0, 1, NVSCCtable, true);
@@ -793,7 +903,15 @@ static void vt_parse_detail_identify(const struct nvme_id_ctrl *ctrl)
 
        vt_convert_data_buffer_to_hex_string(&buf[768], 256, false, s);
        printf("    \"NVM Subsystem NVMe Qualified Name\":\"%s\",\n", s);
-       printf("}\n");
+       printf("}\n\n");
+
+       vt_build_power_state_descriptor(ctrl);
+
+
+       printf("\n{\n");
+       printf("\"Vendor Specific\":\"\n");
+       vt_dump_hex_data(&buf[3072], 1024);
+       printf("\"}\n");
 }
 
 static int vt_save_smart_to_vtview_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@@ -823,7 +941,7 @@ static int vt_save_smart_to_vtview_log(int argc, char **argv, struct command *cm
 
        struct vtview_save_log_settings cfg = {
                .run_time_hrs = 20,
-               .log_record_frequency_hrs = 0.25,
+               .log_record_frequency_hrs = 10,
                .output_file = NULL,
                .test_name = NULL,
        };
@@ -838,15 +956,15 @@ static int vt_save_smart_to_vtview_log(int argc, char **argv, struct command *cm
 
        vt_generate_vtview_log_file_name(vt_default_log_file_name);
 
+       if (argc >= 2)
+               strcpy(path, argv[1]);
+
        fd = parse_and_open(argc, argv, desc, opts);
-       if (fd < 0)  {
+       if (fd < 0) {
                printf("Error parse and open (fd = %d)\n", fd);
                return (fd);
        }
 
-       printf("argc: %d\n", argc);
-       strcpy(path, argv[1]);
-
        printf("Running...\n");
        printf("Collecting data for device %s\n", path);
        printf("Running for %lf hour(s)\n", cfg.run_time_hrs);
@@ -905,7 +1023,7 @@ static int vt_show_identify(int argc, char **argv, struct command *cmd, struct p
        };
 
        fd = parse_and_open(argc, argv, desc, opts);
-       if (fd < 0)  {
+       if (fd < 0) {
                printf("Error parse and open (fd = %d)\n", fd);
                return (fd);
        }