]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
Added parsing for Solidigm telemetry observable data.
authorda Cunha, Leonardo <leonardo.da.cunha@solidigmtechnology.com>
Fri, 15 Jul 2022 02:11:19 +0000 (22:11 -0400)
committerda Cunha, Leonardo <leonardo.da.cunha@solidigmtechnology.com>
Fri, 26 Aug 2022 18:59:29 +0000 (14:59 -0400)
13 files changed:
plugins/solidigm/meson.build
plugins/solidigm/solidigm-garbage-collection.c
plugins/solidigm/solidigm-nvme.c
plugins/solidigm/solidigm-nvme.h
plugins/solidigm/solidigm-smart.c
plugins/solidigm/solidigm-telemetry.c [new file with mode: 0644]
plugins/solidigm/solidigm-telemetry.h [new file with mode: 0644]
plugins/solidigm/solidigm-telemetry/cod.c [new file with mode: 0644]
plugins/solidigm/solidigm-telemetry/cod.h [new file with mode: 0644]
plugins/solidigm/solidigm-telemetry/meson.build [new file with mode: 0644]
plugins/solidigm/solidigm-telemetry/reason-id.c [new file with mode: 0644]
plugins/solidigm/solidigm-telemetry/reason-id.h [new file with mode: 0644]
plugins/solidigm/solidigm-telemetry/telemetry-log.h [new file with mode: 0644]

index fb0f6a995e43cf5d12653b42a0f8c9177d00b2a0..bca13bbe421e9f36151e8d76b031892d32b1c420 100644 (file)
@@ -2,4 +2,6 @@ sources += [
   'plugins/solidigm/solidigm-smart.c',
   'plugins/solidigm/solidigm-garbage-collection.c',
   'plugins/solidigm/solidigm-latency-tracking.c',
+  'plugins/solidigm/solidigm-telemetry.c',
 ]
+subdir('solidigm-telemetry')
index 4e05ec3be4fe6074caad001dd635d8ab7c77ddc2..b81e9add08a6ed14b20b6c721c94d3f009ef8b2a 100644 (file)
@@ -87,7 +87,7 @@ int solidigm_get_garbage_collection_log(int argc, char **argv, struct command *c
        if (flags == -EINVAL) {
                fprintf(stderr, "Invalid output format '%s'\n", cfg.output_format);
                dev_close(dev);
-               return flags;
+               return EINVAL;
        }
 
        garbage_control_collection_log_t gc_log;
index 3eb3cc913991751a2ba4eb62c7d4fe5ed4523485..684648ad06a1651da9a4f5e24fabe8af142e495f 100644 (file)
@@ -13,6 +13,7 @@
 #include "solidigm-smart.h"
 #include "solidigm-garbage-collection.h"
 #include "solidigm-latency-tracking.h"
+#include "solidigm-telemetry.h"
 
 static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
 {
@@ -27,4 +28,9 @@ static int get_garbage_collection_log(int argc, char **argv, struct command *cmd
 static int get_latency_tracking_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
 {
        return solidigm_get_latency_tracking_log(argc, argv, cmd, plugin);
+}
+
+static int get_telemetry_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
+{
+       return solidigm_get_telemetry_log(argc, argv, cmd, plugin);
 }
\ No newline at end of file
index 9fc8b4518e510bc7b7713998d1bb98596ff08147..a1f48f631a32011cc171c96941fd15f4ccf677d5 100644 (file)
 
 #include "cmd.h"
 
-#define SOLIDIGM_PLUGIN_VERSION "0.4"
+#define SOLIDIGM_PLUGIN_VERSION "0.5"
 
 PLUGIN(NAME("solidigm", "Solidigm vendor specific extensions", SOLIDIGM_PLUGIN_VERSION),
        COMMAND_LIST(
                ENTRY("smart-log-add", "Retrieve Solidigm SMART Log", get_additional_smart_log)
                ENTRY("garbage-collect-log", "Retrieve Garbage Collection Log", get_garbage_collection_log)
                ENTRY("latency-tracking-log", "Enable/Retrieve Latency tracking Log", get_latency_tracking_log)
+               ENTRY("parse-telemetry-log", "Parse Telemetry Log binary", get_telemetry_log)
        )
 );
 
index 65340349a0c7445de93452c120b3fca276c70cc9..4acbf847ef18bf9723ce8867ae8750602f2ff0d7 100644 (file)
@@ -10,8 +10,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include <inttypes.h>
-#include <endian.h>
 
 #include "common.h"
 #include "nvme.h"
diff --git a/plugins/solidigm/solidigm-telemetry.c b/plugins/solidigm/solidigm-telemetry.c
new file mode 100644 (file)
index 0000000..49bccf9
--- /dev/null
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2022 Solidigm.
+ *
+ * Author: leonardo.da.cunha@solidigm.com
+ */
+
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "nvme.h"
+#include "libnvme.h"
+#include "plugin.h"
+#include "nvme-print.h"
+#include "solidigm-telemetry.h"
+#include "solidigm-telemetry/telemetry-log.h"
+#include "solidigm-telemetry/cod.h"
+#include "solidigm-telemetry/reason-id.h"
+
+struct config {
+       __u32 host_gen;
+       bool ctrl_init;
+       int     data_area;
+};
+
+int solidigm_get_telemetry_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
+{
+       const char *desc = "Parse Solidigm Telemetry log";
+       const char *hgen = "Controls when to generate new host initiated report. Default value '1' generates new host initiated report, value '0' causes retrieval of existing log.";
+       const char *cgen = "Gather report generated by the controller.";
+       const char *dgen = "Pick which telemetry data area to report. Default is 3 to fetch areas 1-3. Valid options are 1, 2, 3, 4.";
+       struct nvme_dev *dev;
+
+       struct telemetry_log tl = {
+               .root = json_create_object(),
+       };
+
+       struct config cfg = {
+               .host_gen       = 1,
+               .ctrl_init      = false,
+               .data_area      = 3,
+       };
+
+       OPT_ARGS(opts) = {
+               OPT_UINT("host-generate",   'g', &cfg.host_gen,  hgen),
+               OPT_FLAG("controller-init", 'c', &cfg.ctrl_init, cgen),
+               OPT_UINT("data-area",       'd', &cfg.data_area, dgen),
+               OPT_END()
+       };
+
+       int err = parse_and_open(&dev, argc, argv, desc, opts);
+       if (err)
+               goto ret;
+
+       if (cfg.host_gen > 1) {
+               fprintf(stderr, "Invalid host-generate value '%d'\n", cfg.host_gen);
+               err = EINVAL;
+               goto close_fd;
+       }
+       
+       if (cfg.ctrl_init)
+               err = nvme_get_ctrl_telemetry(dev_fd(dev), true, &tl.log, cfg.data_area, &tl.log_size);
+       else if (cfg.host_gen)
+               err = nvme_get_new_host_telemetry(dev_fd(dev), &tl.log, cfg.data_area, &tl.log_size);
+       else
+               err = nvme_get_host_telemetry(dev_fd(dev), &tl.log, cfg.data_area, &tl.log_size);
+
+       if (err < 0) {
+               fprintf(stderr, "get-telemetry-log: %s\n",
+                       nvme_strerror(errno));
+               goto close_fd;
+       } else if (err > 0) {
+               nvme_show_status(err);
+               fprintf(stderr, "Failed to acquire telemetry log %d!\n", err);
+               goto close_fd;
+       }
+
+       solidigm_telemetry_log_reason_id_parse(&tl);
+       solidigm_telemetry_log_cod_parse(&tl);
+       
+       json_print_object(tl.root, NULL);
+       json_free_object(tl.root);
+       printf("\n");
+
+       free(tl.log);
+
+close_fd:
+       dev_close(dev);
+ret:
+       return err;
+}
\ No newline at end of file
diff --git a/plugins/solidigm/solidigm-telemetry.h b/plugins/solidigm/solidigm-telemetry.h
new file mode 100644 (file)
index 0000000..971ee2a
--- /dev/null
@@ -0,0 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2022 Solidigm.
+ *
+ * Author: leonardo.da.cunha@solidigm.com
+ */
+
+int solidigm_get_telemetry_log(int argc, char **argv, struct command *cmd, struct plugin *plugin);
diff --git a/plugins/solidigm/solidigm-telemetry/cod.c b/plugins/solidigm/solidigm-telemetry/cod.c
new file mode 100644 (file)
index 0000000..518c53e
--- /dev/null
@@ -0,0 +1,192 @@
+// SPDX-License-Identifier: MIT-0
+/*
+ * Copyright (c) 2022 Solidigm.
+ *
+ * Author: leonardo.da.cunha@solidigm.com
+ */
+#include "common.h"
+#include "cod.h"
+
+const char *oemDataMapDesc[] = {
+       "Media Read Count", //Uid 0x00
+       "Host Read count",  //Uid 0x01
+       "Media Write Count",  //Uid 0x02
+       "Host Write Count",  //Uid 0x03
+       "Device Model", // 0x04
+       "Serial Number", // 0x05
+       "Firmware Revision", // 0x06
+       "Drive Status", // 0x07
+       "Minimum Temperature", // 0x08
+       "Maximum Temperature", // 0x09
+       "Power Loss Protection Status", // 0x0a
+       "Lifetime Unsafe Shutdown Count", // 0x0b
+       "Lifetime Power Cycle Count", // 0x0c
+       "Minimum Read Latency", // 0x0d
+       "Maximum Read Latency", // 0x0e
+       "Average Read Latency", // 0x0f
+       "Minimum Write Latency", // 0x10
+       "Maximum Write Latency", // 0x11
+       "Average Write Latency", // 0x12
+       "Grown Defects Count", // 0x13
+       "DQS Recovery Count", // 0x14
+       "Program Fail Count", // 0x15
+       "Erase Fail Count",  // 0x16
+       "Defrag Writes in Progress Count",  // 0x17
+       "Total Defrag Writes Count",  // 0x18
+       "Max Die Offline Number",  // 0x19
+       "Current Die Offline Number",  // 0x1A
+       "XOR Enable Status",  // 0x1B
+       "Media Life Used",  // 0x1C
+       "Uncorrectable Error Count",  // 0x1D
+       "Current Wear Range Delta", // 0x1E
+       "Read Errors Corrected by XOR", // 0x1F
+       "Background Data Refresh", // 0x20
+       "Pmic Vin History Data 1 Min", // 0x21
+       "Pmic Vin History Data 1 Max", // 0x22
+       "Pmic Vin History Data 1 Avg", // 0x23
+       "Pmic Vin History Data 2 Min", // 0x24
+       "Pmic Vin History Data 2 Max", // 0x25
+       "Pmic Vin History Data 2 Avg", // 0x26
+       "Pmic Vin History Data Total Readings", // 0x27
+       "All Time Current Max Wear Level", // 0x28
+       "Media Wear Remaining", // 0x29
+       "Total Non-Defrag Writes",  // 0x2A
+       "Number of sectors relocated in reaction to an error" //Uid 0x2B = 43
+};
+
+static const char * getOemDataMapDescription(__u32 id)
+{
+       if (id < (sizeof(oemDataMapDesc) / sizeof(oemDataMapDesc[0]))) {
+               return oemDataMapDesc[id];
+       }
+       return "unknown";
+}
+
+#define OEMSIGNATURE 0x504D4443
+
+#pragma pack(push, cod, 1)
+struct cod_header
+{
+       uint32_t versionMajor;
+       uint32_t versionMinor;
+       uint32_t Signature;      //!Fixed signature value (0x504D4443) for identification and validation
+       uint32_t MapSizeInBytes; //!Total size of the map data structure in bytes
+       uint32_t EntryCount;     //!Total number of entries in the entry list
+       uint8_t Reserved[12];
+};
+
+struct cod_item
+{
+       uint32_t DataFieldMapUid;       //!The data field unique identifier value
+       uint32_t reserved1 : 8;
+       uint32_t dataFieldType : 8;
+       uint32_t issigned : 1;
+       uint32_t bigEndian : 1;
+       uint32_t dataInvalid : 1;
+       uint32_t reserved2 : 13;
+       uint32_t DataFieldSizeInBytes;
+       uint8_t Reserved1[4];
+       uint64_t DataFieldOffset;
+       uint8_t Reserved2[8];
+};
+
+struct cod_map
+{
+       struct cod_header header;
+       struct cod_item items[];
+};
+
+#pragma pack(pop, cod)
+
+void solidigm_telemetry_log_cod_parse(struct telemetry_log *tl)
+{
+       enum cod_field_type
+       {
+               INTEGER,
+               FLOAT,
+               STRING,
+               TWO_BYTE_ASCII,
+               FOUR_BYTE_ASCII,
+
+               UNKNOWN = 0xFF,
+       };
+       json_object *COD_offset = NULL;
+       json_object *reason_id = NULL;
+       if (!json_object_object_get_ex(tl->root, "reason_identifier", &reason_id)) {
+                       return;
+       }
+       if  (!json_object_object_get_ex(reason_id, "OemDataMapOffset", &COD_offset)) {
+                       return;
+       }
+
+       __u64 offset = json_object_get_int(COD_offset);
+
+       if  (offset ==  0) {
+               return;
+       }
+
+       if ((offset + sizeof(struct cod_header)) > tl->log_size) {
+               fprintf(stderr, "COD map header out of bounds.\n");
+               return;
+       }
+
+       const struct cod_map *data = (struct cod_map *) (((__u8 *)tl->log ) + offset);
+
+       uint32_t signature = be32_to_cpu(data->header.Signature);
+       if ( signature != OEMSIGNATURE){
+               fprintf(stderr, "Unsupported COD data signature %x!\n", signature);
+               return;
+       }
+       if ((offset + data->header.MapSizeInBytes) > tl->log_size){
+               fprintf(stderr, "COD map data out of bounds.\n");
+               return;
+       }
+
+       json_object *cod = json_create_object();
+       json_object_object_add(tl->root, "cod", cod);
+
+       for (int i =0 ; i < data->header.EntryCount; i++) {
+               if ((offset + sizeof(struct cod_header) + (i + 1) * sizeof(struct cod_item)) >
+               tl->log_size){
+                       fprintf(stderr, "COD data out of bounds at item %d!\n", i);
+                       return;
+               }
+               struct cod_item item = data->items[i];
+               if (item.DataFieldOffset + item.DataFieldOffset > tl->log_size) {
+                       continue;
+               }
+               if (item.dataInvalid) {
+                       continue;
+               }
+               uint8_t *val = ((uint8_t *)tl->log )+ item.DataFieldOffset;
+               const char *key =  getOemDataMapDescription(item.DataFieldMapUid);
+               switch(item.dataFieldType){
+                       case(INTEGER):
+                               if (item.issigned) {
+                                       json_object_object_add(cod, key, 
+                                               json_object_new_int64(le64_to_cpu(*(uint64_t *)val)));
+                               } else {
+                                       json_object_add_value_uint64(cod, key, le64_to_cpu(*(uint64_t *)val));
+                               }
+                               break;
+                       case(FLOAT):
+                               json_object_add_value_float(cod, key, *(float *) val);
+                               break;
+                       case(STRING):
+                               json_object_object_add(cod, key, 
+                                       json_object_new_string_len((const char *)val, item.DataFieldSizeInBytes));
+                               break;
+                       case(TWO_BYTE_ASCII):
+                               json_object_object_add(cod, key, 
+                                       json_object_new_string_len((const char *)val,2));
+                               break;
+                       case(FOUR_BYTE_ASCII):
+                               json_object_object_add(cod, key, 
+                                       json_object_new_string_len((const char *)val, 4));
+                               break;
+                       default:
+                               fprintf(stderr,"Unknown COD field type (%d)\n", item.DataFieldMapUid);
+                               
+               }
+       }
+}
diff --git a/plugins/solidigm/solidigm-telemetry/cod.h b/plugins/solidigm/solidigm-telemetry/cod.h
new file mode 100644 (file)
index 0000000..f8ffb41
--- /dev/null
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: MIT-0
+/*
+ * Copyright (c) 2022 Solidigm.
+ *
+ * Author: leonardo.da.cunha@solidigm.com
+ */
+
+#include "telemetry-log.h"
+void solidigm_telemetry_log_cod_parse(struct telemetry_log *tl);
diff --git a/plugins/solidigm/solidigm-telemetry/meson.build b/plugins/solidigm/solidigm-telemetry/meson.build
new file mode 100644 (file)
index 0000000..5fd5603
--- /dev/null
@@ -0,0 +1,4 @@
+sources += [
+  'plugins/solidigm/solidigm-telemetry/cod.c',
+  'plugins/solidigm/solidigm-telemetry/reason-id.c',
+]
diff --git a/plugins/solidigm/solidigm-telemetry/reason-id.c b/plugins/solidigm/solidigm-telemetry/reason-id.c
new file mode 100644 (file)
index 0000000..9007b89
--- /dev/null
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: MIT-0
+/*
+ * Copyright (c) 2022 Solidigm.
+ *
+ * Author: leonardo.da.cunha@solidigm.com
+ */
+
+#include "common.h"
+#include "reason-id.h"
+
+#pragma pack(push, reason_indentifier, 1)
+struct reason_indentifier_1_0
+{
+       uint16_t versionMajor;
+       uint16_t versionMinor;
+       uint32_t reasonCode;        //! 0 denotes no issue. All other values denote a potential issue.
+       char DriveStatus[20];       //! Drive Status String (for example: "Healthy", "*BAD_CONTEXT_2020")
+       char FirmwareVersion[12];   //! Similar to IdentifyController.FR
+       char BootloaderVersion[12]; //! Bootloader version string
+       char SerialNumber[20];      //! Device serial number    
+       uint8_t Reserved[56];       //! Reserved for future usage
+};
+
+struct reason_indentifier_1_1
+{
+       uint16_t versionMajor;
+       uint16_t versionMinor;
+       uint32_t reasonCode;        //! 0 denotes no issue. All other values denote a potential issue.
+       char DriveStatus[20];       //! Drive Status String (for example: "Healthy", "*BAD_CONTEXT_2020")
+       char FirmwareVersion[12];   //! Similar to IdentifyController.FR
+       char BootloaderVersion[12]; //! Bootloader version string
+       char SerialNumber[20];      //! Device serial number
+       uint64_t OemDataMapOffset;      //! Customer Data Map Object Log Offset
+       uint8_t TelemetryMajorVersion; //! Shadow of version in TOC
+       uint8_t TelemetryMinorVersion; //! Shadow of version in TOC
+       uint8_t Reserved[46];       //! Reserved for future usage
+};
+
+struct reason_indentifier_1_2
+{
+       uint16_t versionMajor;
+       uint16_t versionMinor;
+       uint32_t reasonCode;        //! 0 denotes no issue. All other values denote a potential issue.
+       char DriveStatus[20];       //! Drive Status String (for example: "Healthy", "*BAD_CONTEXT_2020")
+       uint8_t Reserved1[24];          //! pad over Fields removed from version 1.1
+       char SerialNumber[20];      //! Device serial number            
+       uint64_t OemDataMapOffset;      //! Customer Data Map Object Log Offset
+       uint8_t TelemetryMajorVersion; //! Shadow of version in TOC
+       uint8_t TelemetryMinorVersion; //! Shadow of version in TOC
+       uint8_t ProductFamilyId;
+       uint8_t Reserved2[5];       //! Reserved for future usage
+       uint8_t DualPortReserved[40];  //! Reserved for dual port
+};
+#pragma pack(pop, reason_indentifier)
+
+static void telemetry_log_reason_id_parse1_0_ext(struct telemetry_log *tl, json_object *reason_id)
+{
+       const struct reason_indentifier_1_0 *ri = (struct reason_indentifier_1_0 *) tl->log->rsnident;
+       json_object_object_add(reason_id, "FirmwareVersion", json_object_new_string_len(ri->FirmwareVersion, sizeof(ri->FirmwareVersion)));
+       json_object_object_add(reason_id, "BootloaderVersion", json_object_new_string_len(ri->BootloaderVersion, sizeof(ri->BootloaderVersion)));
+       json_object_object_add(reason_id, "SerialNumber", json_object_new_string_len(ri->SerialNumber, sizeof(ri->SerialNumber)));
+       json_object *reserved = json_create_array();
+       json_object_add_value_array(reason_id, "Reserved", reserved);
+       for ( int i=0; i < sizeof(ri->Reserved); i++) {
+               json_object *val = json_object_new_int(ri->Reserved[i]);
+               json_object_array_add(reserved, val);
+       }
+}
+
+static void telemetry_log_reason_id_parse1_1_ext(struct telemetry_log *tl, json_object *reason_id)
+{
+       const struct reason_indentifier_1_1 *ri = (struct reason_indentifier_1_1 *) tl->log->rsnident;
+       json_object_object_add(reason_id, "FirmwareVersion", json_object_new_string_len(ri->FirmwareVersion, sizeof(ri->FirmwareVersion)));
+       json_object_object_add(reason_id, "BootloaderVersion", json_object_new_string_len(ri->BootloaderVersion, sizeof(ri->BootloaderVersion)));
+       json_object_object_add(reason_id, "SerialNumber", json_object_new_string_len(ri->SerialNumber, sizeof(ri->SerialNumber)));
+       json_object_add_value_uint64(reason_id, "OemDataMapOffset", le64_to_cpu(ri->OemDataMapOffset));
+       json_object_add_value_uint(reason_id, "TelemetryMajorVersion", le16_to_cpu(ri->TelemetryMajorVersion));
+       json_object_add_value_uint(reason_id, "TelemetryMinorVersion", le16_to_cpu(ri->TelemetryMinorVersion));
+       json_object *reserved = json_create_array();
+       json_object_add_value_array(reason_id, "Reserved", reserved);
+       for ( int i=0; i < sizeof(ri->Reserved); i++) {
+               json_object *val = json_object_new_int(ri->Reserved[i]);
+               json_object_array_add(reserved, val);
+       }
+}
+
+static void telemetry_log_reason_id_parse1_2_ext(struct telemetry_log *tl, json_object *reason_id)
+{
+       const struct reason_indentifier_1_2 *ri = (struct reason_indentifier_1_2 *) tl->log->rsnident;
+       json_object_object_add(reason_id, "SerialNumber", json_object_new_string_len(ri->SerialNumber, sizeof(ri->SerialNumber)));
+       json_object_add_value_uint64(reason_id, "OemDataMapOffset", le64_to_cpu(ri->OemDataMapOffset));
+       json_object_add_value_uint(reason_id, "TelemetryMajorVersion", le16_to_cpu(ri->TelemetryMajorVersion));
+       json_object_add_value_uint(reason_id, "TelemetryMinorVersion", le16_to_cpu(ri->TelemetryMinorVersion));
+       json_object_add_value_uint(reason_id, "ProductFamilyId", ri->ProductFamilyId);
+       json_object *reserved = json_create_array();
+       json_object_add_value_array(reason_id, "Reserved2", reserved);
+       for ( int i=0; i < sizeof(ri->Reserved2); i++) {
+               json_object *val = json_object_new_int(ri->Reserved2[i]);
+               json_object_array_add(reserved, val);
+       }
+       json_object *dp_reserved = json_create_array();
+       json_object_add_value_array(reason_id, "DualPortReserved", dp_reserved);
+       for ( int i=0; i < sizeof(ri->DualPortReserved); i++) {
+               json_object *val =  json_object_new_int(ri->DualPortReserved[i]);
+               json_object_array_add(dp_reserved, val);
+       }
+}
+
+void solidigm_telemetry_log_reason_id_parse(struct telemetry_log *tl)
+{
+       json_object *reason_id = json_create_object();
+       struct reason_indentifier_1_0 * ri1_0 = (struct reason_indentifier_1_0 *) tl->log->rsnident;
+       __u16 version_major = le16_to_cpu(ri1_0->versionMajor);
+       __u16 version_minor = le16_to_cpu(ri1_0->versionMinor);
+       json_object_add_value_object(tl->root, "reason_identifier", reason_id);
+       json_object_add_value_uint(reason_id, "versionMajor", version_major);
+       json_object_add_value_uint(reason_id, "versionMinor", version_minor);
+       json_object_add_value_uint(reason_id, "reasonCode", le32_to_cpu(ri1_0->reasonCode));
+       json_object_object_add(reason_id, "DriveStatus", json_object_new_string_len(ri1_0->DriveStatus, sizeof(ri1_0->DriveStatus)));
+       if (version_major == 1) {
+               switch (version_minor){
+                       case 0:
+                               telemetry_log_reason_id_parse1_0_ext(tl, reason_id);
+                               break;
+                       case 1:
+                               telemetry_log_reason_id_parse1_1_ext(tl, reason_id);
+                               break;
+                       default:
+                               telemetry_log_reason_id_parse1_2_ext(tl, reason_id);
+               }
+       }
+}
diff --git a/plugins/solidigm/solidigm-telemetry/reason-id.h b/plugins/solidigm/solidigm-telemetry/reason-id.h
new file mode 100644 (file)
index 0000000..d47d186
--- /dev/null
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: MIT-0
+/*
+ * Copyright (c) 2022 Solidigm.
+ *
+ * Author: leonardo.da.cunha@solidigm.com
+ */
+
+#include "telemetry-log.h"
+void solidigm_telemetry_log_reason_id_parse(struct telemetry_log *tl);
diff --git a/plugins/solidigm/solidigm-telemetry/telemetry-log.h b/plugins/solidigm/solidigm-telemetry/telemetry-log.h
new file mode 100644 (file)
index 0000000..1b18a7e
--- /dev/null
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: MIT-0
+/*
+ * Copyright (c) 2022 Solidigm.
+ *
+ * Author: leonardo.da.cunha@solidigm.com
+ */
+
+#ifndef _SOLIDIGM_TELEMETRY_LOG_H
+#define _SOLIDIGM_TELEMETRY_LOG_H
+
+#include "libnvme.h"
+#include "util/json.h"
+
+struct telemetry_log {
+       struct nvme_telemetry_log *log;
+       size_t log_size;
+       json_object *root;
+};
+
+#endif /* _SOLIDIGM_TELEMETRY_LOG_H */
\ No newline at end of file