From d1fdc1ace53e85dfa6793f424f01b92ac3ae2e1e Mon Sep 17 00:00:00 2001 From: "da Cunha, Leonardo" Date: Thu, 14 Jul 2022 22:11:19 -0400 Subject: [PATCH] Added parsing for Solidigm telemetry observable data. --- plugins/solidigm/meson.build | 2 + .../solidigm/solidigm-garbage-collection.c | 2 +- plugins/solidigm/solidigm-nvme.c | 6 + plugins/solidigm/solidigm-nvme.h | 3 +- plugins/solidigm/solidigm-smart.c | 2 - plugins/solidigm/solidigm-telemetry.c | 95 +++++++++ plugins/solidigm/solidigm-telemetry.h | 8 + plugins/solidigm/solidigm-telemetry/cod.c | 192 ++++++++++++++++++ plugins/solidigm/solidigm-telemetry/cod.h | 9 + .../solidigm/solidigm-telemetry/meson.build | 4 + .../solidigm/solidigm-telemetry/reason-id.c | 132 ++++++++++++ .../solidigm/solidigm-telemetry/reason-id.h | 9 + .../solidigm-telemetry/telemetry-log.h | 20 ++ 13 files changed, 480 insertions(+), 4 deletions(-) create mode 100644 plugins/solidigm/solidigm-telemetry.c create mode 100644 plugins/solidigm/solidigm-telemetry.h create mode 100644 plugins/solidigm/solidigm-telemetry/cod.c create mode 100644 plugins/solidigm/solidigm-telemetry/cod.h create mode 100644 plugins/solidigm/solidigm-telemetry/meson.build create mode 100644 plugins/solidigm/solidigm-telemetry/reason-id.c create mode 100644 plugins/solidigm/solidigm-telemetry/reason-id.h create mode 100644 plugins/solidigm/solidigm-telemetry/telemetry-log.h diff --git a/plugins/solidigm/meson.build b/plugins/solidigm/meson.build index fb0f6a99..bca13bbe 100644 --- a/plugins/solidigm/meson.build +++ b/plugins/solidigm/meson.build @@ -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') diff --git a/plugins/solidigm/solidigm-garbage-collection.c b/plugins/solidigm/solidigm-garbage-collection.c index 4e05ec3b..b81e9add 100644 --- a/plugins/solidigm/solidigm-garbage-collection.c +++ b/plugins/solidigm/solidigm-garbage-collection.c @@ -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; diff --git a/plugins/solidigm/solidigm-nvme.c b/plugins/solidigm/solidigm-nvme.c index 3eb3cc91..684648ad 100644 --- a/plugins/solidigm/solidigm-nvme.c +++ b/plugins/solidigm/solidigm-nvme.c @@ -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 diff --git a/plugins/solidigm/solidigm-nvme.h b/plugins/solidigm/solidigm-nvme.h index 9fc8b451..a1f48f63 100644 --- a/plugins/solidigm/solidigm-nvme.h +++ b/plugins/solidigm/solidigm-nvme.h @@ -13,13 +13,14 @@ #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) ) ); diff --git a/plugins/solidigm/solidigm-smart.c b/plugins/solidigm/solidigm-smart.c index 65340349..4acbf847 100644 --- a/plugins/solidigm/solidigm-smart.c +++ b/plugins/solidigm/solidigm-smart.c @@ -10,8 +10,6 @@ #include #include #include -#include -#include #include "common.h" #include "nvme.h" diff --git a/plugins/solidigm/solidigm-telemetry.c b/plugins/solidigm/solidigm-telemetry.c new file mode 100644 index 00000000..49bccf9e --- /dev/null +++ b/plugins/solidigm/solidigm-telemetry.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022 Solidigm. + * + * Author: leonardo.da.cunha@solidigm.com + */ + +#include +#include +#include +#include +#include + +#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 index 00000000..971ee2ac --- /dev/null +++ b/plugins/solidigm/solidigm-telemetry.h @@ -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 index 00000000..518c53eb --- /dev/null +++ b/plugins/solidigm/solidigm-telemetry/cod.c @@ -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 index 00000000..f8ffb415 --- /dev/null +++ b/plugins/solidigm/solidigm-telemetry/cod.h @@ -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 index 00000000..5fd56034 --- /dev/null +++ b/plugins/solidigm/solidigm-telemetry/meson.build @@ -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 index 00000000..9007b891 --- /dev/null +++ b/plugins/solidigm/solidigm-telemetry/reason-id.c @@ -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 index 00000000..d47d186d --- /dev/null +++ b/plugins/solidigm/solidigm-telemetry/reason-id.h @@ -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 index 00000000..1b18a7e7 --- /dev/null +++ b/plugins/solidigm/solidigm-telemetry/telemetry-log.h @@ -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 -- 2.50.1