linknvme:nvme-micron-temperature-stats[1]::
Retrieves temperature information of given micron device
-linknvme:nvme-micron-ocp-telemetry-log-parse[1]::
- Parse OCP Telemetry DA1 and DA2 logs.
+linknvme:nvme-ocp-internal-log[1]::
+ Retrieves and parses OCP Telemetry DA1 and DA2 logs.
linknvme:nvme-netapp-ontapdevices[1]::
Display information about ONTAP devices
'nvme-micron-selective-download',
'nvme-micron-smart-add-log',
'nvme-micron-temperature-stats',
- 'nvme-micron-ocp-telemetry-log-parse',
'nvme-netapp-ontapdevices',
'nvme-netapp-smdevices',
'nvme-ns-descs',
'nvme-ocp-smart-add-log',
'nvme-ocp-telemetry-string-log-page',
'nvme-ocp-unsupported-reqs-log-pages',
+ 'nvme-ocp-internal-log',
'nvme-persistent-event-log',
'nvme-pred-lat-event-agg-log',
'nvme-predictable-lat-log',
+++ /dev/null
-nvme-micron-ocp-telemetry-log-parse(1)
-======================================
-
-NAME
-----
-nvme-micron-ocp-telemetry-log-parse - Parses OCP Telemetry DA1 and DA2 logs.
-
-SYNOPSIS
---------
-[verse]
-'nvme micron ocp-telemetry-log-parse' <device>
- [--telemetry-log=<file> | -l <file>]
- [--string-log=<file> | -s <file>]
- [--output-file=<file> | -o <file>]
- [--format=<fmt> | -f <fmt>]
-
-DESCRIPTION
------------
-For the given NVMe device, parses the telemetry log and string log
-(in binary format) and provides the parsed data in json and normal text formats.
-
-The <device> parameter is mandatory and may be either the NVMe
-character device (ex: /dev/nvme0), or a namespace block device (ex:
-/dev/nvme0n1).
-
-This will only work on Micron devices of model numbers 51Bx. Support for new
-devices may be added subsequently. Results for any other device are undefined.
-
-OPTIONS
--------
--l <file>::
---telemetry-log=<file>::
- This option will allow the users to specify input telemetry-log file name.
-
--o <file>::
---string-log=<file>::
- This option will allow the users to specify input string-log file name.
-
--o <file>::
---output-file=<file>::
- This option will allow the users to specify the output file name.
-
--f <fmt>::
---format=<fmt>::
- Set the reporting format to 'normal', 'json'. Only one output format can be
- used at a time.
-
-EXAMPLES
---------
-* Parse nvme_host_telemetry_log.bin with nvmelog_ocp_c9.bin and output parsed
-json data into nvme_cli_telemetry_host.json
-+
-------------
-# sudo ./nvme micron ocp-telemetry-log-parse --format=json
- --string-log="nvmelog_ocp_c9.bin" --telemetry-log="nvme_host_telemetry_log.bin"
- --output-file=nvme_cli_telemetry_host.json /dev/nvme0
-------------
-
-* Parse nvme_host_telemetry_log.bin with nvmelog_ocp_c9.bin and output parsed
-text data into nvme_cli_telemetry_host_normal.txt
-+
-------------
-# sudo ./nvme micron ocp-telemetry-log-parse --format=normal
- --string-log="nvmelog_ocp_c9.bin" --telemetry-log="nvme_host_telemetry_log.bin"
- --output-file=nvme_cli_telemetry_host_normal.txt /dev/nvme0
-------------
-
-* Parse nvme_host_telemetry_log.bin with nvmelog_ocp_c9.bin and redirect parsed
-json data into nvme_cli_telemetry_host_console.json
-+
-------------
-# sudo ./nvme micron ocp-telemetry-log-parse --format=json
- --string-log="nvmelog_ocp_c9.bin" --telemetry-log="nvme_host_telemetry_log.bin"
- > nvme_cli_telemetry_host_console.txt /dev/nvme0
-------------
-
-* Parse nvme_host_telemetry_log.bin with nvmelog_ocp_c9.bin and redirect parsed
-text data into nvme_cli_telemetry_host_console.json
-+
-------------
-# sudo ./nvme micron ocp-telemetry-log-parse --format=normal
- --string-log="nvmelog_ocp_c9.bin" --telemetry-log="nvme_host_telemetry_log.bin"
- > nvme_cli_telemetry_host_console.txt /dev/nvme0
-------------
-
-NVME
-----
-Part of the nvme-user suite
--- /dev/null
+nvme-ocp-internal-log(1)
+========================
+
+NAME
+----
+nvme-ocp-internal-log - Conditionally retrieves 07h Telemetry Host-Initiated
+log, C9h OCP Strings Log from an NVMe device or from user-specified file path.
+Takes retrieved logs and decodes into human-readable output format specified by
+user.
+
+SYNOPSIS
+--------
+[verse]
+'nvme ocp internal-log' <device>
+ [--telemetry-log=<file> | -l <file>]
+ [--string-log=<file> | -s <file>]
+ [--output-file=<file> | -o <file>]
+ [--output-format=<fmt> | -f <fmt>]
+ [--data-area=<da> | -a <da>]
+ [--telemetry-type=<type> | -t <type>]
+
+DESCRIPTION
+-----------
+Conditionally retrieves 07h Telemetry Host-Initiated log, C9h OCP Strings Log
+from an NVMe device or from user-specified file path. Takes retrieved logs and
+decodes (or) parses into human-readable output format specified by user.
+
+The <device> parameter is mandatory and may be either the NVMe
+character device (ex: /dev/nvme0), or a namespace block device (ex:
+/dev/nvme0n1).
+
+This will only work on OCP compliant devices supporting this feature.
+Results for any other device are undefined.
+
+On success it returns 0, error code otherwise.
+
+OPTIONS
+-------
+-l <file>::
+--telemetry-log=<file>::
+ File name to existing Telemetry Host-Initiated raw binary data to be used.
+ If no path is specified, a live retrieval of payload on <device> will be
+ performed.
+
+-s <file>::
+--string-log=<file>::
+ File name to existing OCP String Log raw binary data to be used. If no path
+ is specified, a live retrieval of payload on <device> will be
+ performed.
+
+-o <file>::
+--output-file=<file>::
+ Filepath name to where human-readable output data will be saved to.
+
+-f <fmt>::
+--output-format=<fmt>::
+ Set the reporting format to 'normal', 'json'. Only one output format can be
+ used at a time, the default value is 'json'.
+
+-a <da>::
+--data-area=<da>::
+ Retrieves the specific data area requested. Valid inputs are 1,2. If this
+ option is not specified, the default value is 1.
+
+-t <type>::
+--telemetry-type=<type>::
+ If set to 1, controller shall capture the Telemetry Host-Initiated data
+ representing the internal state of the controller at the time the associated
+ Get Log Page command is processed. If cleared to 0, controller shall not
+ update this data.
+
+EXAMPLES
+--------
+
+* Retrieve in both OCP String Log and Telemetry Host-Initiated Log from
+device. Decode default data-area(s) in default format and output to console.
++
+----------------------------------
+# nvme ocp internal-log /dev/nvme0
+----------------------------------
+
+* Retrieve Telemetry Host-Initiated data, reads in the OCP String Log locally.
+Decode default data-area(s) in default format.
++
+--------------------------------------------------------------------
+# nvme ocp internal-log /dev/nvme0 --string-log=ocp_string_log.bin
+ --output-file=output_file.json
+--------------------------------------------------------------------
+
+* Retrieve OCP String Log, reads in the Telemetry Host-Initiated Log locally.
+Decode data-areas 1 and 2, and output in json format.
++
+---------------------------------------------------------------------
+# nvme ocp internal-log /dev/nvme0 --telemetry-log=host_telemetry.bin
+ --output-format=json --output-file=output_file.json --data-area=2
+---------------------------------------------------------------------
+
+* Reads in both OCP String Log and Telemetry Host-Initiated Log locally.
+Decode data-areas 1 and 2, and output in normal text format.
++
+------------------------------------------------------------------
+# nvme ocp internal-log /dev/nvme0 --string-log=ocp_string_log.bin
+ --telemetry-log=host_telemetry.bin --output-format=normal
+ --output-file=output_file.txt --data-area=2
+------------------------------------------------------------------
+
+NVME
+----
+Part of the nvme-user suite
local _internal_log
_internal_log=(
/dev/nvme':supply a device to use (required)'
- --telemetry_type=':Telemetry Type; host (Create bit) or controller'
- -t':alias for --telemetry_type'
- --telemetry_data_area=':Telemetry Data Area; 1 or 3'
- -a':alias for --telemetry_data_area'
+ --telemetry-type=':Telemetry Type; host or controller generated'
+ -t':alias for --telemetry-type'
+ --data-area=':Telemetry Data Area; 1 or 2'
+ -a':alias for --data-area'
--output-file=':Output file name with path'
-o':alias for --output-file'
+ --telemetry-log=':Telemetry log binary'
+ -l':alias for --telemetry-log'
+ --string-log=':String log binary'
+ -s':alias for --string-log'
+ --output-format':Output format: normal|json'
+ -f':alias for --output-format'
)
_arguments '*:: :->subcmds'
_describe -t commands "nvme ocp internal-log options" _internal_log
(*)
_files
;;
- esac
- ;;
- (micron)
- case ${words[2]} in
- (ocp-telemetry-log-parse)
- local _ocp-telemetry-log-parse
- _ocp-telemetry-log-parse=(
- /dev/nvme':supply a device to use (required)'
- --output-file=':Output file name with path'
- -o':alias for --output-file'
- --telemetry-log=':Telemetry log binary'
- -l':alias for --telemetry-log'
- --string-log=':String log binary'
- -s':alias for --string-log'
- --format':Output format: normal|json'
- -f':alias for --format'
- )
- _arguments '*:: :->subcmds'
- _describe -t commands "nvme micron ocp-telemetry-log-parse" _ocp-telemetry-log-parse
- ;;
- (*)
- _files
- ;;
esac
return
else
"vs-smbus-option")
opts+=" --option= -o --value= -v --save= -s"
;;
- "ocp-telemetry-log-parse")
- opts+=" --format= -f --telemetry-log= -l --string-log= -s \
- --output-file= -o"
- ;;
"help")
opts+=$NO_OPTS
;;
--latency_monitor_feature_enable= -e"
;;
"internal-log")
- opts+=" --telemetry_type= -t --telemetry_data_area= -a \
- --output-file= -o"
+ opts+=" --telemetry-log= -l --string-log= -s \
+ --output-file= -o --output-format= -f \
+ --data-area= -a --telemetry-type= -t"
;;
"clear-fw-activate-history")
opts+=" --no-uuid -n"
'plugins/inspur/inspur-nvme.c',
'plugins/intel/intel-nvme.c',
'plugins/memblaze/memblaze-nvme.c',
- 'plugins/micron/micron-utils.c',
- 'plugins/micron/micron-ocp-telemetry.c',
'plugins/micron/micron-nvme.c',
'plugins/nbft/nbft-plugin.c',
'plugins/netapp/netapp-nvme.c',
* @authors:Chaithanya Shoba <ashoba@micron.com>,
*/
-#include "micron-ocp-telemetry.h"
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <time.h>
+#include <string.h>
+#include <libgen.h>
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "common.h"
+#include "nvme.h"
+#include "libnvme.h"
+#include <limits.h>
+#include "linux/types.h"
+#include "nvme-print.h"
+#include "util/cleanup.h"
+#include "util/utils.h"
#define CREATE_CMD
#include "micron-nvme.h"
}
/* Smart Health Log information as per OCP spec M51CX models */
-struct micron_vs_logpage ocp_c0_log_page[] = {
+struct request_data ocp_c0_log_page[] = {
{ "Physical Media Units Written", 16},
{ "Physical Media Units Read", 16 },
{ "Raw Bad User NAND Block Count", 6},
logPages);
}
- print_micron_vs_logs(buf, ocp_c0_log_page, field_count, stats, 0, NULL);
+ generic_structure_parser(buf, ocp_c0_log_page, field_count, stats, 0, NULL);
if (is_json) {
json_array_add_value_object(logPages, stats);
logPages);
}
- print_micron_vs_logs(buf, fb_log_page, field_count, stats, spec, NULL);
+ generic_structure_parser(buf, fb_log_page, field_count, stats, spec, NULL);
/* print last three entries from D0 log page */
if (buf2) {
printf("SMART Extended Log:0xE1\n");
}
- print_micron_vs_logs(buf, e1_log_page, field_count, stats, 0, NULL);
+ generic_structure_parser(buf, e1_log_page, field_count, stats, 0, NULL);
if (is_json) {
json_array_add_value_object(logPages, stats);
return err;
}
-
-static int micron_ocp_telemetry_log_parse(int argc, char **argv,
- struct command *cmd, struct plugin *plugin)
-{
- const char *desc = "Parse OCP Telemetry DA1 and DA2 logs.";
- const char *output_fmt = "output format normal|json";
- const char *telemetry_log = "Telemetry log binary;\n 'host.bin' or 'controller.bin'";
- const char *string_log = "String log binary; 'C9.bin'";
- const char *output_file = "Output file name with path;\n"
- "e.g. '-o ./path/name'\n'-o ./path1/path2/';\n"
- "If requested path doesn't exist, the file will be newly created.";
- enum eDriveModel eModel = UNKNOWN_MODEL;
- int err = 0;
- struct nvme_dev *dev;
- struct ocp_telemetry_parse_options opt;
-
- OPT_ARGS(opts) = {
- OPT_STR("telemetry-log", 'l', &opt.telemetry_log, telemetry_log),
- OPT_STR("string-log", 's', &opt.string_log, string_log),
- OPT_FILE("output-file", 'o', &opt.output_file, output_file),
- OPT_FMT("format", 'f', &opt.output_fmt, output_fmt),
- OPT_END()
- };
-
- err = micron_parse_options(&dev, argc, argv, desc, opts, &eModel);
- if (err < 0)
- return -1;
-
- if (!opt.telemetry_log) {
- nvme_show_result("\nMissing telemetry-log.\n");
- return -1;
- } else if (!opt.string_log) {
- nvme_show_result("\nMissing string-log. Skipping adding string data.\n");
- } else if (!opt.output_fmt) {
- nvme_show_result("\nMissing format. Using default format - JSON.\n");
- }
-
- err = parse_ocp_telemetry_log(&opt);
-
- dev_close(dev);
- if (err != 0)
- nvme_show_status(err);
- return err;
-}
ENTRY("vs-smart-add-log", "Retrieve extended SMART data", micron_ocp_smart_health_logs)
ENTRY("clear-fw-activate-history", "Clear FW activation history", micron_clr_fw_activation_history)
ENTRY("vs-smbus-option", "Enable/Disable SMBUS on the drive", micron_smbus_option)
- ENTRY("ocp-telemetry-log-parse", "Parse OCP Telemetry DA1 and DA2 logs",
- micron_ocp_telemetry_log_parse)
)
);
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (c) Micron, Inc 2024.
- *
- * @file: micron-ocp-telemetry.c
- * @brief: This module contains all the constructs needed for parsing (or)
- * decoding ocp telemetry log files.
- * @author: Chaithanya Shoba <ashoba@micron.com>
- */
-
-#include "micron-ocp-telemetry.h"
-
-//global buffers
-static unsigned char *ptelemetry_buffer;
-static unsigned char *pstring_buffer;
-
-struct statistic_entry statistic_identifiers_map[] = {
- { 0x00, "Error, this entry does not exist." },
- { 0x01, "Outstanding Admin Commands" },
- { 0x02, "Host Write Bandwidth"},
- { 0x03, "GC Write Bandwidth"},
- { 0x04, "Active Namespaces"},
- { 0x05, "Internal Write Workload"},
- { 0x06, "Internal Read Workload"},
- { 0x07, "Internal Write Queue Depth"},
- { 0x08, "Internal Read Queue Depth"},
- { 0x09, "Pending Trim LBA Count"},
- { 0x0A, "Host Trim LBA Request Count"},
- { 0x0B, "Current NVMe Power State"},
- { 0x0C, "Current DSSD Power State"},
- { 0x0D, "Program Fail Count"},
- { 0x0E, "Erase Fail Count"},
- { 0x0F, "Read Disturb Writes"},
- { 0x10, "Retention Writes"},
- { 0x11, "Wear Leveling Writes"},
- { 0x12, "Read Recovery Writes"},
- { 0x13, "GC Writes"},
- { 0x14, "SRAM Correctable Count"},
- { 0x15, "DRAM Correctable Count"},
- { 0x16, "SRAM Uncorrectable Count"},
- { 0x17, "DRAM Uncorrectable Count"},
- { 0x18, "Data Integrity Error Count"},
- { 0x19, "Read Retry Error Count"},
- { 0x1A, "PERST Events Count"},
- { 0x1B, "Max Die Bad Block"},
- { 0x1C, "Max NAND Channel Bad Block"},
- { 0x1D, "Minimum NAND Channel Bad Block"}
-};
-
-struct micron_vs_logpage host_log_page_header[] = {
- { "LogIdentifier", 1 },
- { "Reserved1", 4 },
- { "IEEE OUI Identifier", 3 },
- { "Telemetry Host-Initiated Data Area 1 Last Block", 2 },
- { "Telemetry Host-Initiated Data Area 2 Last Block", 2 },
- { "Telemetry Host-Initiated Data Area 3 Last Block", 2 },
- { "Reserved2", 2 },
- { "Telemetry Host-Initiated Data Area 4 Last Block", 4 },
- { "Reserved3", 360 },
- { "Telemetry Host-Initiated Scope", 1 },
- { "Telemetry Host Initiated Generation Number", 1 },
- { "Telemetry Host-Initiated Data Available", 1 },
- { "Telemetry Controller-Initiated Data Generation Number", 1 }
-};
-
-struct micron_vs_logpage controller_log_page_header[] = {
- { "LogIdentifier", 1 },
- { "Reserved1", 4 },
- { "IEEE OUI Identifier", 3 },
- { "Telemetry Host-Initiated Data Area 1 Last Block", 2 },
- { "Telemetry Host-Initiated Data Area 2 Last Block", 2 },
- { "Telemetry Host-Initiated Data Area 3 Last Block", 2 },
- { "Reserved2", 2 },
- { "Telemetry Host-Initiated Data Area 4 Last Block", 4 },
- { "Reserved3", 361 },
- { "Telemetry Controller-Initiated Scope", 1 },
- { "Telemetry Controller-Initiated Data Available", 1 },
- { "Telemetry Controller-Initiated Data Generation Number", 1 }
-};
-
-struct micron_vs_logpage reason_identifier[] = {
- { "Error ID", 64 },
- { "File ID", 8 },
- { "Line Number", 2 },
- { "Valid Flags", 1 },
- { "Reserved", 21 },
- { "VU Reason Extension", 32 }
-};
-
-struct micron_vs_logpage ocp_header_in_da1[] = {
- { "Major Version", 2 },
- { "Minor Version", 2 },
- { "Reserved1", 4 },
- { "Timestamp", 8 },
- { "Log page GUID", 16 },
- { "Number Telemetry Profiles Supported", 1 },
- { "Telemetry Profile Selected", 1 },
- { "Reserved2", 6 },
- { "Telemetry String Log Size", 8 },
- { "Reserved3", 8 },
- { "Firmware Revision", 8 },
- { "Reserved4", 32 },
- { "Data Area 1 Statistic Start", 8 },
- { "Data Area 1 Statistic Size", 8 },
- { "Data Area 2 Statistic Start", 8 },
- { "Data Area 2 Statistic Size", 8 },
- { "Reserved5", 32 },
- { "Event FIFO 1 Data Area", 1 },
- { "Event FIFO 2 Data Area", 1 },
- { "Event FIFO 3 Data Area", 1 },
- { "Event FIFO 4 Data Area", 1 },
- { "Event FIFO 5 Data Area", 1 },
- { "Event FIFO 6 Data Area", 1 },
- { "Event FIFO 7 Data Area", 1 },
- { "Event FIFO 8 Data Area", 1 },
- { "Event FIFO 9 Data Area", 1 },
- { "Event FIFO 10 Data Area", 1 },
- { "Event FIFO 11 Data Area", 1 },
- { "Event FIFO 12 Data Area", 1 },
- { "Event FIFO 13 Data Area", 1 },
- { "Event FIFO 14 Data Area", 1 },
- { "Event FIFO 15 Data Area", 1 },
- { "Event FIFO 16 Data Area", 1 },
- { "Event FIFO 1 Start", 8 },
- { "Event FIFO 1 Size", 8 },
- { "Event FIFO 2 Start", 8 },
- { "Event FIFO 2 Size", 8 },
- { "Event FIFO 3 Start", 8 },
- { "Event FIFO 3 Size", 8 },
- { "Event FIFO 4 Start", 8 },
- { "Event FIFO 4 Size", 8 },
- { "Event FIFO 5 Start", 8 },
- { "Event FIFO 5 Size", 8 },
- { "Event FIFO 6 Start", 8 },
- { "Event FIFO 6 Size", 8 },
- { "Event FIFO 7 Start", 8 },
- { "Event FIFO 7 Size", 8 },
- { "Event FIFO 8 Start", 8 },
- { "Event FIFO 8 Size", 8 },
- { "Event FIFO 9 Start", 8 },
- { "Event FIFO 9 Size", 8 },
- { "Event FIFO 10 Start", 8 },
- { "Event FIFO 10 Size", 8 },
- { "Event FIFO 11 Start", 8 },
- { "Event FIFO 11 Size", 8 },
- { "Event FIFO 12 Start", 8 },
- { "Event FIFO 12 Size", 8 },
- { "Event FIFO 13 Start", 8 },
- { "Event FIFO 13 Size", 8 },
- { "Event FIFO 14 Start", 8 },
- { "Event FIFO 14 Size", 8 },
- { "Event FIFO 15 Start", 8 },
- { "Event FIFO 15 Size", 8 },
- { "Event FIFO 16 Start", 8 },
- { "Event FIFO 16 Size", 8 },
- { "Reserved6", 80 }
-};
-
-struct micron_vs_logpage smart[] = {
- { "Critical Warning", 1 },
- { "Composite Temperature", 2 },
- { "Available Spare", 1 },
- { "Available Spare Threshold", 1 },
- { "Percentage Used", 1 },
- { "Reserved1", 26 },
- { "Data Units Read", 16 },
- { "Data Units Written", 16 },
- { "Host Read Commands", 16 },
- { "Host Write Commands", 16 },
- { "Controller Busy Time", 16 },
- { "Power Cycles", 16 },
- { "Power On Hours", 16 },
- { "Unsafe Shutdowns", 16 },
- { "Media and Data Integrity Errors", 16 },
- { "Number of Error Information Log Entries", 16 },
- { "Warning Composite Temperature Time", 4 },
- { "Critical Composite Temperature Time", 4 },
- { "Temperature Sensor 1", 2 },
- { "Temperature Sensor 2", 2 },
- { "Temperature Sensor 3", 2 },
- { "Temperature Sensor 4", 2 },
- { "Temperature Sensor 5", 2 },
- { "Temperature Sensor 6", 2 },
- { "Temperature Sensor 7", 2 },
- { "Temperature Sensor 8", 2 },
- { "Thermal Management Temperature 1 Transition Count", 4 },
- { "Thermal Management Temperature 2 Transition Count", 4 },
- { "Total Time for Thermal Management Temperature 1", 4 },
- { "Total Time for Thermal Management Temperature 2", 4 },
- { "Reserved2", 280 }
-};
-
-struct micron_vs_logpage smart_extended[] = {
- { "Physical Media Units Written", 16 },
- { "Physical Media Units Read", 16 },
- { "Bad User NAND Blocks Raw Count", 6 },
- { "Bad User NAND Blocks Normalized Value", 2 },
- { "Bad System NAND Blocks Raw Count", 6 },
- { "Bad System NAND Blocks Normalized Value", 2 },
- { "XOR Recovery Count", 8 },
- { "Uncorrectable Read Error Count", 8 },
- { "Soft ECC Error Count", 8 },
- { "End to End Correction Counts Detected Errors", 4 },
- { "End to End Correction Counts Corrected Errors", 4 },
- { "System Data Percent Used", 1 },
- { "Refresh Counts", 7 },
- { "Maximum User Data Erase Count", 4 },
- { "Minimum User Data Erase Count", 4 },
- { "Number of thermal throttling events", 1 },
- { "Current Throttling Status", 1 },
- { "Errata Version Field", 1 },
- { "Point Version Field", 2 },
- { "Minor Version Field", 2 },
- { "Major Version Field", 1 },
- { "PCIe Correctable Error Count", 8 },
- { "Incomplete Shutdowns", 4 },
- { "Reserved1", 4 },
- { "Percent Free Blocks", 1 },
- { "Reserved2", 7 },
- { "Capacitor Health", 2 },
- { "NVMe Base Errata Version", 1 },
- { "NVMe Command Set Errata Version", 1 },
- { "Reserved3", 4 },
- { "Unaligned IO", 8 },
- { "Security Version Number", 8 },
- { "Total NUSE", 8 },
- { "PLP Start Count", 16 },
- { "Endurance Estimate", 16 },
- { "PCIe Link Retraining Count", 8 },
- { "Power State Change Count", 8 },
- { "Lowest Permitted Firmware Revision", 8 },
- { "Reserved4", 278 },
- { "Log Page Version", 2 },
- { "Log page GUID", 16 }
-};
-
-void json_add_formatted_u32_str(struct json_object *pobject, const char *msg, unsigned int pdata)
-{
- char data_str[70] = { 0 };
-
- sprintf(data_str, "0x%x", pdata);
- json_object_add_value_string(pobject, msg, data_str);
-}
-
-void json_add_formatted_var_size_str(struct json_object *pobject, const char *msg, __u8 *pdata,
- unsigned int data_size)
-{
- char description_str[256] = "";
- char temp_buffer[3] = { 0 };
-
- for (size_t i = 0; i < data_size; ++i) {
- sprintf(temp_buffer, "%02X", pdata[i]);
- strcat(description_str, temp_buffer);
- }
-
- json_object_add_value_string(pobject, msg, description_str);
-}
-
-int get_telemetry_das_offset_and_size(
- struct nvme_ocp_telemetry_common_header *ptelemetry_common_header,
- struct nvme_ocp_telemetry_offsets *ptelemetry_das_offset)
-{
- if (NULL == ptelemetry_common_header || NULL == ptelemetry_das_offset) {
- nvme_show_error("Invalid input arguments.");
- return -1;
- }
-
- if (ptelemetry_common_header->log_id == NVME_HOST_TELEMETRY_LOG)
- ptelemetry_das_offset->header_size =
- sizeof(struct nvme_ocp_telemetry_host_initiated_header);
- else if (ptelemetry_common_header->log_id == NVME_CNTRL_TELEMETRY_LOG)
- ptelemetry_das_offset->header_size =
- sizeof(struct nvme_ocp_telemetry_controller_initiated_header);
- else
- return -1;
-
- ptelemetry_das_offset->da1_start_offset = ptelemetry_das_offset->header_size;
- ptelemetry_das_offset->da1_size = ptelemetry_common_header->da1_last_block *
- OCP_TELEMETRY_DATA_BLOCK_SIZE;
-
- ptelemetry_das_offset->da2_start_offset = ptelemetry_das_offset->da1_start_offset +
- ptelemetry_das_offset->da1_size;
- ptelemetry_das_offset->da2_size =
- (ptelemetry_common_header->da2_last_block -
- ptelemetry_common_header->da1_last_block) * OCP_TELEMETRY_DATA_BLOCK_SIZE;
-
- ptelemetry_das_offset->da3_start_offset = ptelemetry_das_offset->da2_start_offset +
- ptelemetry_das_offset->da2_size;
- ptelemetry_das_offset->da3_size =
- (ptelemetry_common_header->da3_last_block -
- ptelemetry_common_header->da2_last_block) * OCP_TELEMETRY_DATA_BLOCK_SIZE;
-
- ptelemetry_das_offset->da4_start_offset = ptelemetry_das_offset->da3_start_offset +
- ptelemetry_das_offset->da3_size;
- ptelemetry_das_offset->da4_size =
- (ptelemetry_common_header->da4_last_block -
- ptelemetry_common_header->da3_last_block) * OCP_TELEMETRY_DATA_BLOCK_SIZE;
-
- return 0;
-}
-
-int get_static_id_ascii_string(int identifier, char *description)
-{
- if (pstring_buffer == NULL)
- return -1;
-
- struct nvme_ocp_telemetry_string_header *pocp_ts_header =
- (struct nvme_ocp_telemetry_string_header *)pstring_buffer;
-
- //Calculating the sizes of the tables. Note: Data is present in the form of DWORDS,
- //So multiplying with sizeof(DWORD)
- unsigned long long sits_table_size = (pocp_ts_header->sitsz) * SIZE_OF_DWORD;
-
- //Calculating number of entries present in all 3 tables
- int sits_entries = (int)sits_table_size /
- sizeof(struct nvme_ocp_statistics_identifier_string_table);
-
- for (int sits_entry = 0; sits_entry < sits_entries; sits_entry++) {
- struct nvme_ocp_statistics_identifier_string_table
- *peach_statistic_entry =
- (struct nvme_ocp_statistics_identifier_string_table *)
- (pstring_buffer + (pocp_ts_header->sits * SIZE_OF_DWORD) +
- (sits_entry *
- sizeof(struct nvme_ocp_statistics_identifier_string_table)));
-
- if (identifier == (int)peach_statistic_entry->vs_statistic_identifier) {
- char *pdescription = (char *)(pstring_buffer +
- (pocp_ts_header->ascts * SIZE_OF_DWORD) +
- (peach_statistic_entry->ascii_id_offset *
- SIZE_OF_DWORD));
-
- memcpy(description, pdescription,
- peach_statistic_entry->ascii_id_length + 1);
-
- // If ASCII string isn't found, see in our internal Map
- // for 2.5 Spec defined strings (id < 0x1D).
- if ((description == NULL) && (identifier < 0x1D))
- memcpy(description,
- statistic_identifiers_map[identifier].description,
- peach_statistic_entry->ascii_id_length + 1);
- return 0;
- }
- }
-
- return -1;
-}
-
-int get_event_id_ascii_string(int identifier, int debug_event_class, char *description)
-{
- if (pstring_buffer == NULL)
- return -1;
-
- struct nvme_ocp_telemetry_string_header *pocp_ts_header =
- (struct nvme_ocp_telemetry_string_header *)pstring_buffer;
-
- //Calculating the sizes of the tables. Note: Data is present in the form of DWORDS,
- //So multiplying with sizeof(DWORD)
- unsigned long long ests_table_size = (pocp_ts_header->estsz) * SIZE_OF_DWORD;
-
- //Calculating number of entries present in all 3 tables
- int ests_entries = (int)ests_table_size / sizeof(struct nvme_ocp_event_string_table);
-
- for (int ests_entry = 0; ests_entry < ests_entries; ests_entry++) {
- struct nvme_ocp_event_string_table *peach_event_entry =
- (struct nvme_ocp_event_string_table *)
- (pstring_buffer + (pocp_ts_header->ests * SIZE_OF_DWORD) +
- (ests_entry * sizeof(struct nvme_ocp_event_string_table)));
-
- if (identifier == (int)peach_event_entry->event_identifier &&
- debug_event_class == (int)peach_event_entry->debug_event_class) {
- char *pdescription = (char *)(pstring_buffer +
- (pocp_ts_header->ascts * SIZE_OF_DWORD) +
- (peach_event_entry->ascii_id_offset * SIZE_OF_DWORD));
-
- memcpy(description, pdescription,
- peach_event_entry->ascii_id_length + 1);
- return 0;
- }
- }
-
- return -1;
-}
-
-int get_vu_event_id_ascii_string(int identifier, int debug_event_class, char *description)
-{
- if (pstring_buffer == NULL)
- return -1;
-
- struct nvme_ocp_telemetry_string_header *pocp_ts_header =
- (struct nvme_ocp_telemetry_string_header *)pstring_buffer;
-
- //Calculating the sizes of the tables. Note: Data is present in the form of DWORDS,
- //So multiplying with sizeof(DWORD)
- unsigned long long vuests_table_size = (pocp_ts_header->vu_estsz) * SIZE_OF_DWORD;
-
- //Calculating number of entries present in all 3 tables
- int vu_ests_entries = (int)vuests_table_size /
- sizeof(struct nvme_ocp_vu_event_string_table);
-
- for (int vu_ests_entry = 0; vu_ests_entry < vu_ests_entries; vu_ests_entry++) {
- struct nvme_ocp_vu_event_string_table *peach_vu_event_entry =
- (struct nvme_ocp_vu_event_string_table *)
- (pstring_buffer + (pocp_ts_header->vu_ests * SIZE_OF_DWORD) +
- (vu_ests_entry * sizeof(struct nvme_ocp_vu_event_string_table)));
-
- if (identifier == (int)peach_vu_event_entry->vu_event_identifier &&
- debug_event_class ==
- (int)peach_vu_event_entry->debug_event_class) {
- char *pdescription = (char *)(pstring_buffer +
- (pocp_ts_header->ascts * SIZE_OF_DWORD) +
- (peach_vu_event_entry->ascii_id_offset * SIZE_OF_DWORD));
-
- memcpy(description, pdescription,
- peach_vu_event_entry->ascii_id_length + 1);
- return 0;
- }
- }
-
- return -1;
-}
-
-int parse_ocp_telemetry_string_log(int event_fifo_num, int identifier, int debug_event_class,
- enum ocp_telemetry_string_tables string_table, char *description)
-{
- if (pstring_buffer == NULL)
- return -1;
-
- if (event_fifo_num != 0) {
- struct nvme_ocp_telemetry_string_header *pocp_ts_header =
- (struct nvme_ocp_telemetry_string_header *)pstring_buffer;
-
- if (*pocp_ts_header->fifo_ascii_string[event_fifo_num-1] != '\0')
- memcpy(description, pocp_ts_header->fifo_ascii_string[event_fifo_num-1],
- 16);
- else
- description = "";
-
- return 0;
- }
-
- if (string_table == STATISTICS_IDENTIFIER_STRING)
- get_static_id_ascii_string(identifier, description);
- else if (string_table == EVENT_STRING)
- get_event_id_ascii_string(identifier, debug_event_class, description);
- else if (string_table == VU_EVENT_STRING)
- get_vu_event_id_ascii_string(identifier, debug_event_class, description);
-
- return 0;
-}
-
-void parse_time_stamp_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor,
- struct json_object *pevent_descriptor_obj, __u8 *pevent_specific_data,
- struct json_object *pevent_fifos_object, FILE *fp)
-{
- struct nvme_ocp_time_stamp_dbg_evt_class_format *ptime_stamp_event =
- (struct nvme_ocp_time_stamp_dbg_evt_class_format *) pevent_specific_data;
-
- int vu_event_id = (int)ptime_stamp_event->vu_event_identifier;
-
- unsigned int data_size = ((pevent_descriptor->event_data_size * SIZE_OF_DWORD)-
- sizeof(struct nvme_ocp_time_stamp_dbg_evt_class_format));
-
- __u8 *pdata = (__u8 *)ptime_stamp_event +
- sizeof(struct nvme_ocp_time_stamp_dbg_evt_class_format);
-
- char description_str[256] = "";
-
- parse_ocp_telemetry_string_log(0, ptime_stamp_event->vu_event_identifier,
- pevent_descriptor->debug_event_class_type,
- VU_EVENT_STRING, description_str);
-
- if (pevent_fifos_object != NULL) {
- json_add_formatted_var_size_str(pevent_descriptor_obj, STR_CLASS_SPECIFIC_DATA,
- ptime_stamp_event->time_stamp, DATA_SIZE_8);
- json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING,
- vu_event_id);
- json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING,
- description_str);
- json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA, pdata,
- data_size);
- } else {
- if (fp) {
- print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA,
- ptime_stamp_event->time_stamp, DATA_SIZE_8, fp);
- fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
- fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING, description_str);
- print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
- } else {
- print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA,
- ptime_stamp_event->time_stamp, DATA_SIZE_8, fp);
- printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
- printf("%s: %s\n", STR_VU_EVENT_STRING, description_str);
- print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
- }
- }
-}
-
-void parse_pcie_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor,
- struct json_object *pevent_descriptor_obj, __u8 *pevent_specific_data,
- struct json_object *pevent_fifos_object, FILE *fp)
-{
- struct nvme_ocp_pcie_dbg_evt_class_format *ppcie_event =
- (struct nvme_ocp_pcie_dbg_evt_class_format *) pevent_specific_data;
- int vu_event_id = (int) ppcie_event->vu_event_identifier;
- unsigned int data_size = ((pevent_descriptor->event_data_size * SIZE_OF_DWORD) -
- sizeof(struct nvme_ocp_pcie_dbg_evt_class_format));
- __u8 *pdata = (__u8 *) ppcie_event + sizeof(struct nvme_ocp_pcie_dbg_evt_class_format);
- char description_str[256] = "";
-
- parse_ocp_telemetry_string_log(0, ppcie_event->vu_event_identifier,
- pevent_descriptor->debug_event_class_type, VU_EVENT_STRING, description_str);
-
- if (pevent_fifos_object != NULL) {
- json_add_formatted_var_size_str(pevent_descriptor_obj, STR_CLASS_SPECIFIC_DATA,
- ppcie_event->pCIeDebugEventData, DATA_SIZE_4);
- json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING,
- vu_event_id);
- json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING,
- description_str);
- json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA, pdata,
- data_size);
- } else {
- if (fp) {
- print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA,
- ppcie_event->pCIeDebugEventData, DATA_SIZE_4, fp);
- fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
- fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING, description_str);
- print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
- } else {
- print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA,
- ppcie_event->pCIeDebugEventData, DATA_SIZE_4, fp);
- printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
- printf("%s: %s\n", STR_VU_EVENT_STRING, description_str);
- print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
- }
- }
-}
-
-void parse_nvme_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor,
- struct json_object *pevent_descriptor_obj, __u8 *pevent_specific_data,
- struct json_object *pevent_fifos_object, FILE *fp)
-{
- struct nvme_ocp_nvme_dbg_evt_class_format *pnvme_event =
- (struct nvme_ocp_nvme_dbg_evt_class_format *) pevent_specific_data;
- int vu_event_id = (int) pnvme_event->vu_event_identifier;
- unsigned int data_size = ((pevent_descriptor->event_data_size *
- SIZE_OF_DWORD) - sizeof(struct nvme_ocp_nvme_dbg_evt_class_format));
- __u8 *pdata = (__u8 *) pnvme_event + sizeof(struct nvme_ocp_nvme_dbg_evt_class_format);
- char description_str[256] = "";
-
- parse_ocp_telemetry_string_log(0, pnvme_event->vu_event_identifier,
- pevent_descriptor->debug_event_class_type, VU_EVENT_STRING,
- description_str);
-
- if (pevent_fifos_object != NULL) {
- json_add_formatted_var_size_str(pevent_descriptor_obj, STR_CLASS_SPECIFIC_DATA,
- pnvme_event->nvmeDebugEventData, DATA_SIZE_8);
- json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING,
- vu_event_id);
- json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING,
- description_str);
- json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA, pdata,
- data_size);
- } else {
- if (fp) {
- print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA,
- pnvme_event->nvmeDebugEventData, DATA_SIZE_8, fp);
- fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
- fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING, description_str);
- print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
- } else {
- print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA,
- pnvme_event->nvmeDebugEventData, DATA_SIZE_8, fp);
- printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
- printf("%s: %s\n", STR_VU_EVENT_STRING, description_str);
- print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
- }
- }
-}
-
-void parse_common_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor,
- struct json_object *pevent_descriptor_obj, __u8 *pevent_specific_data,
- struct json_object *pevent_fifos_object, FILE *fp)
-{
- struct nvme_ocp_common_dbg_evt_class_format *pcommon_debug_event =
- (struct nvme_ocp_common_dbg_evt_class_format *) pevent_specific_data;
- int vu_event_id = (int) pcommon_debug_event->vu_event_identifier;
- unsigned int data_size = ((pevent_descriptor->event_data_size *
- SIZE_OF_DWORD) - sizeof(struct nvme_ocp_common_dbg_evt_class_format));
- __u8 *pdata = (__u8 *) pcommon_debug_event +
- sizeof(struct nvme_ocp_common_dbg_evt_class_format);
- char description_str[256] = "";
-
- parse_ocp_telemetry_string_log(0, pcommon_debug_event->vu_event_identifier,
- pevent_descriptor->debug_event_class_type, VU_EVENT_STRING, description_str);
-
- if (pevent_fifos_object != NULL) {
- json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING,
- vu_event_id);
- json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING,
- description_str);
- json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA, pdata,
- data_size);
- } else {
- if (fp) {
- fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
- fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING, description_str);
- print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
- } else {
- printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
- printf("%s: %s\n", STR_VU_EVENT_STRING, description_str);
- print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
- }
- }
-}
-
-void parse_media_wear_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor,
- struct json_object *pevent_descriptor_obj, __u8 *pevent_specific_data,
- struct json_object *pevent_fifos_object, FILE *fp)
-{
- struct nvme_ocp_media_wear_dbg_evt_class_format *pmedia_wear_event =
- (struct nvme_ocp_media_wear_dbg_evt_class_format *) pevent_specific_data;
- int vu_event_id = (int) pmedia_wear_event->vu_event_identifier;
- unsigned int data_size = ((pevent_descriptor->event_data_size * SIZE_OF_DWORD) -
- sizeof(struct nvme_ocp_media_wear_dbg_evt_class_format));
- __u8 *pdata = (__u8 *) pmedia_wear_event +
- sizeof(struct nvme_ocp_media_wear_dbg_evt_class_format);
- char description_str[256] = "";
-
- parse_ocp_telemetry_string_log(0, pmedia_wear_event->vu_event_identifier,
- pevent_descriptor->debug_event_class_type, VU_EVENT_STRING,
- description_str);
-
- if (pevent_fifos_object != NULL) {
- json_add_formatted_var_size_str(pevent_descriptor_obj, STR_CLASS_SPECIFIC_DATA,
- pmedia_wear_event->currentMediaWear, DATA_SIZE_12);
- json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING,
- vu_event_id);
- json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING,
- description_str);
- json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA, pdata,
- data_size);
- } else {
- if (fp) {
- print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA,
- pmedia_wear_event->currentMediaWear, DATA_SIZE_12, fp);
- fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
- fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING, description_str);
- print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
- } else {
- print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA,
- pmedia_wear_event->currentMediaWear, DATA_SIZE_12, NULL);
- printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
- printf("%s: %s\n", STR_VU_EVENT_STRING, description_str);
- print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
- }
- }
-}
-
-int parse_event_fifo(unsigned int fifo_num, unsigned char *pfifo_start,
- struct json_object *pevent_fifos_object, unsigned char *pstring_buffer,
- struct nvme_ocp_telemetry_offsets *poffsets, __u64 fifo_size, FILE *fp)
-{
- if (NULL == pfifo_start || NULL == poffsets) {
- nvme_show_error("Input buffer was NULL");
- return -1;
- }
-
- int status = 0;
- unsigned int event_fifo_number = fifo_num + 1;
- char *description = (char *)malloc((40 + 1) * sizeof(char));
-
- memset(description, 0, sizeof(40));
-
- status =
- parse_ocp_telemetry_string_log(event_fifo_number, 0, 0, EVENT_STRING, description);
-
- if (status != 0) {
- nvme_show_error("Failed to get C9 String. status: %d\n", status);
- return -1;
- }
-
- char event_fifo_name[100] = {0};
-
- snprintf(event_fifo_name, sizeof(event_fifo_name), "%s%d%s%s", "EVENT FIFO ",
- event_fifo_number, " - ", description);
-
- struct json_object *pevent_fifo_array = NULL;
-
- if (pevent_fifos_object != NULL)
- pevent_fifo_array = json_create_array();
- else {
- char buffer[1024] = {0};
-
- sprintf(buffer, "%s%s\n%s", STR_LINE, event_fifo_name, STR_LINE);
- if (fp)
- fprintf(fp, "%s", buffer);
- else
- printf("%s", buffer);
- }
-
- int offset_to_move = 0;
- unsigned int event_des_size = sizeof(struct nvme_ocp_telemetry_event_descriptor);
-
- while ((fifo_size > 0) && (offset_to_move < fifo_size)) {
- struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor =
- (struct nvme_ocp_telemetry_event_descriptor *)
- (pfifo_start + offset_to_move);
-
- if (pevent_descriptor != NULL && pevent_descriptor->event_data_size >= 0) {
- //Data is present in the form of DWORDS, So multiplying with sizeof(DWORD)
- unsigned int data_size = pevent_descriptor->event_data_size *
- SIZE_OF_DWORD;
-
- __u8 *pevent_specific_data = (__u8 *)pevent_descriptor + event_des_size;
-
- char description_str[256] = "";
-
- parse_ocp_telemetry_string_log(0, pevent_descriptor->event_id,
- pevent_descriptor->debug_event_class_type, EVENT_STRING,
- description_str);
-
- struct json_object *pevent_descriptor_obj =
- ((pevent_fifos_object != NULL)?json_create_object():NULL);
-
- if (pevent_descriptor_obj != NULL) {
- json_add_formatted_u32_str(pevent_descriptor_obj,
- STR_DBG_EVENT_CLASS_TYPE,
- pevent_descriptor->debug_event_class_type);
- json_add_formatted_u32_str(pevent_descriptor_obj,
- STR_EVENT_IDENTIFIER, pevent_descriptor->event_id);
- json_object_add_value_string(pevent_descriptor_obj,
- STR_EVENT_STRING, description_str);
- json_add_formatted_u32_str(pevent_descriptor_obj,
- STR_EVENT_DATA_SIZE, pevent_descriptor->event_data_size);
-
- if (pevent_descriptor->debug_event_class_type >= 0x80)
- json_add_formatted_var_size_str(pevent_descriptor_obj,
- STR_VU_DATA, pevent_specific_data, data_size);
- } else {
- if (fp) {
- fprintf(fp, "%s: 0x%x\n", STR_DBG_EVENT_CLASS_TYPE,
- pevent_descriptor->debug_event_class_type);
- fprintf(fp, "%s: 0x%x\n", STR_EVENT_IDENTIFIER,
- pevent_descriptor->event_id);
- fprintf(fp, "%s: %s\n", STR_EVENT_STRING, description_str);
- fprintf(fp, "%s: 0x%x\n", STR_EVENT_DATA_SIZE,
- pevent_descriptor->event_data_size);
- } else {
- printf("%s: 0x%x\n", STR_DBG_EVENT_CLASS_TYPE,
- pevent_descriptor->debug_event_class_type);
- printf("%s: 0x%x\n", STR_EVENT_IDENTIFIER,
- pevent_descriptor->event_id);
- printf("%s: %s\n", STR_EVENT_STRING, description_str);
- printf("%s: 0x%x\n", STR_EVENT_DATA_SIZE,
- pevent_descriptor->event_data_size);
- }
-
- if (pevent_descriptor->debug_event_class_type >= 0x80)
- print_formatted_var_size_str(STR_VU_DATA,
- pevent_specific_data, data_size, fp);
- }
-
- switch (pevent_descriptor->debug_event_class_type) {
- case TIME_STAMP_CLASS_TYPE:
- parse_time_stamp_event(pevent_descriptor, pevent_descriptor_obj,
- pevent_specific_data, pevent_fifos_object, fp);
- break;
- case PCIE_CLASS_TYPE:
- parse_pcie_event(pevent_descriptor, pevent_descriptor_obj,
- pevent_specific_data, pevent_fifos_object, fp);
- break;
- case NVME_CLASS_TYPE:
- parse_nvme_event(pevent_descriptor, pevent_descriptor_obj,
- pevent_specific_data, pevent_fifos_object, fp);
- break;
- case RESET_CLASS_TYPE:
- case BOOT_SEQUENCE_CLASS_TYPE:
- case FIRMWARE_ASSERT_CLASS_TYPE:
- case TEMPERATURE_CLASS_TYPE:
- case MEDIA_CLASS_TYPE:
- parse_common_event(pevent_descriptor, pevent_descriptor_obj,
- pevent_specific_data, pevent_fifos_object, fp);
- break;
- case MEDIA_WEAR_CLASS_TYPE:
- parse_media_wear_event(pevent_descriptor, pevent_descriptor_obj,
- pevent_specific_data, pevent_fifos_object, fp);
- break;
- case STATISTIC_SNAPSHOT_CLASS_TYPE: {
- struct nvme_ocp_statistic_snapshot_evt_class_format
- *pStaticSnapshotEvent =
- (struct nvme_ocp_statistic_snapshot_evt_class_format *)
- pevent_specific_data;
- struct nvme_ocp_telemetry_statistic_descriptor *pstatistic_entry =
- (struct nvme_ocp_telemetry_statistic_descriptor *)
- (&pStaticSnapshotEvent->statisticDescriptorData);
-
- parse_statistic(pstatistic_entry, pevent_descriptor_obj, fp);
- break;
- }
- case RESERVED_CLASS_TYPE:
- default:
- break;
- }
-
- if (pevent_descriptor_obj != NULL && pevent_fifo_array != NULL)
- json_array_add_value_object(pevent_fifo_array, pevent_descriptor_obj);
- else {
- if (fp)
- fprintf(fp, STR_LINE2);
- else
- printf(STR_LINE2);
- }
- } else
- break;
-
- offset_to_move += (pevent_descriptor->event_data_size * SIZE_OF_DWORD + event_des_size);
- }
-
- if (pevent_fifos_object != NULL && pevent_fifo_array != NULL)
- json_object_add_value_array(pevent_fifos_object, event_fifo_name,
- pevent_fifo_array);
-
- free(description);
- return 0;
-}
-
-int parse_event_fifos(struct json_object *root, struct nvme_ocp_telemetry_offsets *poffsets,
- FILE *fp)
-{
- if (poffsets == NULL) {
- nvme_show_error("Input buffer was NULL");
- return -1;
- }
-
- struct json_object *pevent_fifos_object = NULL;
-
- if (root != NULL)
- pevent_fifos_object = json_create_object();
-
- __u8 *pda1_header_offset = ptelemetry_buffer + poffsets->da1_start_offset;//512
- __u8 *pda2_offset = ptelemetry_buffer + poffsets->da2_start_offset;
- struct nvme_ocp_header_in_da1 *pda1_header = (struct nvme_ocp_header_in_da1 *)
- pda1_header_offset;
- struct nvme_ocp_event_fifo_data event_fifo[MAX_NUM_FIFOS];
-
- for (int fifo_num = 0; fifo_num < MAX_NUM_FIFOS; fifo_num++) {
- event_fifo[fifo_num].event_fifo_num = fifo_num;
- event_fifo[fifo_num].event_fifo_da = pda1_header->event_fifo_da[fifo_num];
- event_fifo[fifo_num].event_fifo_start =
- pda1_header->fifo_offsets[fifo_num].event_fifo_start;
- event_fifo[fifo_num].event_fifo_size =
- pda1_header->fifo_offsets[fifo_num].event_fifo_size;
- }
-
- //Parse all the FIFOs DA wise
- for (int fifo_no = 0; fifo_no < MAX_NUM_FIFOS; fifo_no++) {
- if (event_fifo[fifo_no].event_fifo_da == poffsets->data_area) {
- __u64 fifo_offset =
- (event_fifo[fifo_no].event_fifo_start * SIZE_OF_DWORD);
- __u64 fifo_size =
- (event_fifo[fifo_no].event_fifo_size * SIZE_OF_DWORD);
- __u8 *pfifo_start = NULL;
-
- if (event_fifo[fifo_no].event_fifo_da == 1)
- pfifo_start = pda1_header_offset + fifo_offset;
- else if (event_fifo[fifo_no].event_fifo_da == 2)
- pfifo_start = pda2_offset + fifo_offset;
- else {
- nvme_show_error("Unsupported Data Area:[%d]", poffsets->data_area);
- return -1;
- }
-
- int status = parse_event_fifo(fifo_no, pfifo_start, pevent_fifos_object,
- pstring_buffer, poffsets, fifo_size, fp);
-
- if (status != 0) {
- nvme_show_error("Failed to parse Event FIFO. status:%d\n", status);
- return -1;
- }
- }
- }
-
- if (pevent_fifos_object != NULL && root != NULL) {
- const char *data_area = (poffsets->data_area == 1 ? STR_DA_1_EVENT_FIFO_INFO :
- STR_DA_2_EVENT_FIFO_INFO);
-
- json_object_add_value_array(root, data_area, pevent_fifos_object);
- }
-
- return 0;
-}
-
-int parse_statistic(struct nvme_ocp_telemetry_statistic_descriptor *pstatistic_entry,
- struct json_object *pstats_array, FILE *fp)
-{
- if (pstatistic_entry == NULL) {
- nvme_show_error("Input buffer was NULL");
- return -1;
- }
-
- unsigned int data_size = pstatistic_entry->statistic_data_size * SIZE_OF_DWORD;
- __u8 *pdata = (__u8 *)pstatistic_entry +
- sizeof(struct nvme_ocp_telemetry_statistic_descriptor);
- char description_str[256] = "";
-
- parse_ocp_telemetry_string_log(0, pstatistic_entry->statistic_id, 0,
- STATISTICS_IDENTIFIER_STRING, description_str);
-
- if (pstats_array != NULL) {
- struct json_object *pstatistics_object = json_create_object();
-
- json_add_formatted_u32_str(pstatistics_object, STR_STATISTICS_IDENTIFIER,
- pstatistic_entry->statistic_id);
- json_object_add_value_string(pstatistics_object, STR_STATISTICS_IDENTIFIER_STR,
- description_str);
- json_add_formatted_u32_str(pstatistics_object,
- STR_STATISTICS_INFO_BEHAVIOUR_TYPE,
- pstatistic_entry->statistic_info_behaviour_type);
- json_add_formatted_u32_str(pstatistics_object, STR_STATISTICS_INFO_RESERVED,
- pstatistic_entry->statistic_info_reserved);
- json_add_formatted_u32_str(pstatistics_object, STR_NAMESPACE_IDENTIFIER,
- pstatistic_entry->ns_info_nsid);
- json_add_formatted_u32_str(pstatistics_object, STR_NAMESPACE_INFO_VALID,
- pstatistic_entry->ns_info_ns_info_valid);
- json_add_formatted_u32_str(pstatistics_object, STR_STATISTICS_DATA_SIZE,
- pstatistic_entry->statistic_data_size);
- json_add_formatted_u32_str(pstatistics_object, STR_RESERVED,
- pstatistic_entry->reserved);
- json_add_formatted_var_size_str(pstatistics_object, STR_STATISTICS_SPECIFIC_DATA,
- pdata, data_size);
-
- if (pstatistics_object != NULL)
- json_array_add_value_object(pstats_array, pstatistics_object);
- } else {
- if (fp) {
- fprintf(fp, "%s: 0x%x\n", STR_STATISTICS_IDENTIFIER,
- pstatistic_entry->statistic_id);
- fprintf(fp, "%s: %s\n", STR_STATISTICS_IDENTIFIER_STR, description_str);
- fprintf(fp, "%s: 0x%x\n", STR_STATISTICS_INFO_BEHAVIOUR_TYPE,
- pstatistic_entry->statistic_info_behaviour_type);
- fprintf(fp, "%s: 0x%x\n", STR_STATISTICS_INFO_RESERVED,
- pstatistic_entry->statistic_info_reserved);
- fprintf(fp, "%s: 0x%x\n", STR_NAMESPACE_IDENTIFIER,
- pstatistic_entry->ns_info_nsid);
- fprintf(fp, "%s: 0x%x\n", STR_NAMESPACE_INFO_VALID,
- pstatistic_entry->ns_info_ns_info_valid);
- fprintf(fp, "%s: 0x%x\n", STR_STATISTICS_DATA_SIZE,
- pstatistic_entry->statistic_data_size);
- fprintf(fp, "%s: 0x%x\n", STR_RESERVED, pstatistic_entry->reserved);
- print_formatted_var_size_str(STR_STATISTICS_SPECIFIC_DATA, pdata,
- data_size, fp);
- fprintf(fp, STR_LINE2);
- } else {
- printf("%s: 0x%x\n", STR_STATISTICS_IDENTIFIER,
- pstatistic_entry->statistic_id);
- printf("%s: %s\n", STR_STATISTICS_IDENTIFIER_STR, description_str);
- printf("%s: 0x%x\n", STR_STATISTICS_INFO_BEHAVIOUR_TYPE,
- pstatistic_entry->statistic_info_behaviour_type);
- printf("%s: 0x%x\n", STR_STATISTICS_INFO_RESERVED,
- pstatistic_entry->statistic_info_reserved);
- printf("%s: 0x%x\n", STR_NAMESPACE_IDENTIFIER,
- pstatistic_entry->ns_info_nsid);
- printf("%s: 0x%x\n", STR_NAMESPACE_INFO_VALID,
- pstatistic_entry->ns_info_ns_info_valid);
- printf("%s: 0x%x\n", STR_STATISTICS_DATA_SIZE,
- pstatistic_entry->statistic_data_size);
- printf("%s: 0x%x\n", STR_RESERVED, pstatistic_entry->reserved);
- print_formatted_var_size_str(STR_STATISTICS_SPECIFIC_DATA, pdata,
- data_size, fp);
- printf(STR_LINE2);
- }
- }
-
- return 0;
-}
-
-int parse_statistics(struct json_object *root, struct nvme_ocp_telemetry_offsets *poffsets,
- FILE *fp)
-{
- if (poffsets == NULL) {
- nvme_show_error("Input buffer was NULL");
- return -1;
- }
-
- __u8 *pda1_ocp_header_offset = ptelemetry_buffer + poffsets->header_size;//512
- __u32 statistics_size = 0;
- __u32 stats_da_1_start_dw = 0, stats_da_1_size_dw = 0;
- __u32 stats_da_2_start_dw = 0, stats_da_2_size_dw = 0;
- __u8 *pstats_offset = NULL;
-
- if (poffsets->data_area == 1) {
- __u32 stats_da_1_start = *(__u32 *)(pda1_ocp_header_offset +
- offsetof(struct nvme_ocp_header_in_da1, da1_statistic_start));
- __u32 stats_da_1_size = *(__u32 *)(pda1_ocp_header_offset +
- offsetof(struct nvme_ocp_header_in_da1, da1_statistic_size));
-
- //Data is present in the form of DWORDS, So multiplying with sizeof(DWORD)
- stats_da_1_start_dw = (stats_da_1_start * SIZE_OF_DWORD);
- stats_da_1_size_dw = (stats_da_1_size * SIZE_OF_DWORD);
-
- pstats_offset = pda1_ocp_header_offset + stats_da_1_start_dw;
- statistics_size = stats_da_1_size_dw;
- } else if (poffsets->data_area == 2) {
- __u32 stats_da_2_start = *(__u32 *)(pda1_ocp_header_offset +
- offsetof(struct nvme_ocp_header_in_da1, da2_statistic_start));
- __u32 stats_da_2_size = *(__u32 *)(pda1_ocp_header_offset +
- offsetof(struct nvme_ocp_header_in_da1, da2_statistic_size));
-
- stats_da_2_start_dw = (stats_da_2_start * SIZE_OF_DWORD);
- stats_da_2_size_dw = (stats_da_2_size * SIZE_OF_DWORD);
-
- pstats_offset = pda1_ocp_header_offset + poffsets->da1_size + stats_da_2_start_dw;
- statistics_size = stats_da_2_size_dw;
- } else {
- nvme_show_error("Unsupported Data Area:[%d]", poffsets->data_area);
- return -1;
- }
-
- struct json_object *pstats_array = ((root != NULL) ? json_create_array() : NULL);
-
- __u32 stat_des_size = sizeof(struct nvme_ocp_telemetry_statistic_descriptor);//8
- __u32 offset_to_move = 0;
-
- while (((statistics_size > 0) && (offset_to_move < statistics_size))) {
- struct nvme_ocp_telemetry_statistic_descriptor *pstatistic_entry =
- (struct nvme_ocp_telemetry_statistic_descriptor *)
- (pstats_offset + offset_to_move);
-
- parse_statistic(pstatistic_entry, pstats_array, fp);
- offset_to_move += (pstatistic_entry->statistic_data_size * SIZE_OF_DWORD +
- stat_des_size);
- }
-
- if (root != NULL && pstats_array != NULL) {
- const char *pdata_area =
- (poffsets->data_area == 1 ? STR_DA_1_STATS : STR_DA_2_STATS);
-
- json_object_add_value_array(root, pdata_area, pstats_array);
- }
-
- return 0;
-}
-
-int print_ocp_telemetry_normal(char *output_file)
-{
- int status = 0;
-
- if (output_file != NULL) {
- FILE *fp = fopen(output_file, "w");
-
- if (fp) {
- fprintf(fp, STR_LINE);
- fprintf(fp, "%s\n", STR_LOG_PAGE_HEADER);
- fprintf(fp, STR_LINE);
- print_micron_vs_logs(ptelemetry_buffer, host_log_page_header,
- ARRAY_SIZE(host_log_page_header), NULL, 0, fp);
-
- fprintf(fp, STR_LINE);
- fprintf(fp, "%s\n", STR_REASON_IDENTIFIER);
- fprintf(fp, STR_LINE);
- __u8 *preason_identifier_offset = ptelemetry_buffer +
- offsetof(struct nvme_ocp_telemetry_host_initiated_header,
- reason_id);
-
- print_micron_vs_logs(preason_identifier_offset, reason_identifier,
- ARRAY_SIZE(reason_identifier), NULL, 0, fp);
-
- fprintf(fp, STR_LINE);
- fprintf(fp, "%s\n", STR_TELEMETRY_HOST_DATA_BLOCK_1);
- fprintf(fp, STR_LINE);
-
- //Set DA to 1 and get offsets
- struct nvme_ocp_telemetry_offsets offsets = { 0 };
-
- offsets.data_area = 1;
-
- struct nvme_ocp_telemetry_common_header *ptelemetry_common_header =
- (struct nvme_ocp_telemetry_common_header *) ptelemetry_buffer;
-
- get_telemetry_das_offset_and_size(ptelemetry_common_header, &offsets);
-
- __u8 *pda1_header_offset = ptelemetry_buffer +
- offsets.da1_start_offset;//512
-
- print_micron_vs_logs(pda1_header_offset, ocp_header_in_da1,
- ARRAY_SIZE(ocp_header_in_da1), NULL, 0, fp);
-
- fprintf(fp, STR_LINE);
- fprintf(fp, "%s\n", STR_SMART_HEALTH_INFO);
- fprintf(fp, STR_LINE);
- __u8 *pda1_smart_offset = pda1_header_offset +
- offsetof(struct nvme_ocp_header_in_da1, smart_health_info);
- //512+512 =1024
-
- print_micron_vs_logs(pda1_smart_offset, smart, ARRAY_SIZE(smart),
- NULL, 0, fp);
-
- fprintf(fp, STR_LINE);
- fprintf(fp, "%s\n", STR_SMART_HEALTH_INTO_EXTENDED);
- fprintf(fp, STR_LINE);
- __u8 *pda1_smart_ext_offset = pda1_header_offset +
- offsetof(struct nvme_ocp_header_in_da1,
- smart_health_info_extended);
-
- print_micron_vs_logs(pda1_smart_ext_offset, smart_extended,
- ARRAY_SIZE(smart_extended), NULL, 0, fp);
-
- fprintf(fp, STR_LINE);
- fprintf(fp, "%s\n", STR_DA_1_STATS);
- fprintf(fp, STR_LINE);
-
- status = parse_statistics(NULL, &offsets, fp);
- if (status != 0) {
- nvme_show_error("status: %d\n", status);
- return -1;
- }
-
- fprintf(fp, STR_LINE);
- fprintf(fp, "%s\n", STR_DA_1_EVENT_FIFO_INFO);
- fprintf(fp, STR_LINE);
- status = parse_event_fifos(NULL, &offsets, fp);
- if (status != 0) {
- nvme_show_error("status: %d\n", status);
- return -1;
- }
-
- //Set the DA to 2
- offsets.data_area = 2;
-
- fprintf(fp, STR_LINE);
- fprintf(fp, "%s\n", STR_DA_2_STATS);
- fprintf(fp, STR_LINE);
- status = parse_statistics(NULL, &offsets, fp);
-
- if (status != 0) {
- nvme_show_error("status: %d\n", status);
- return -1;
- }
-
- fprintf(fp, STR_LINE);
- fprintf(fp, "%s\n", STR_DA_2_EVENT_FIFO_INFO);
- fprintf(fp, STR_LINE);
- status = parse_event_fifos(NULL, &offsets, fp);
- if (status != 0) {
- nvme_show_error("status: %d\n", status);
- return -1;
- }
-
- fprintf(fp, STR_LINE);
-
- fclose(fp);
- } else {
- nvme_show_error("Failed to open %s file.\n", output_file);
- return -1;
- }
- } else {
- printf(STR_LINE);
- printf("%s\n", STR_LOG_PAGE_HEADER);
- printf(STR_LINE);
- print_micron_vs_logs(ptelemetry_buffer, host_log_page_header,
- ARRAY_SIZE(host_log_page_header), NULL, 0, NULL);
-
- printf(STR_LINE);
- printf("%s\n", STR_REASON_IDENTIFIER);
- printf(STR_LINE);
- __u8 *preason_identifier_offset = ptelemetry_buffer +
- offsetof(struct nvme_ocp_telemetry_host_initiated_header, reason_id);
- print_micron_vs_logs(preason_identifier_offset, reason_identifier,
- ARRAY_SIZE(reason_identifier), NULL, 0, NULL);
-
- printf(STR_LINE);
- printf("%s\n", STR_TELEMETRY_HOST_DATA_BLOCK_1);
- printf(STR_LINE);
-
- //Set DA to 1 and get offsets
- struct nvme_ocp_telemetry_offsets offsets = { 0 };
-
- offsets.data_area = 1;
-
- struct nvme_ocp_telemetry_common_header *ptelemetry_common_header =
- (struct nvme_ocp_telemetry_common_header *) ptelemetry_buffer;
-
- get_telemetry_das_offset_and_size(ptelemetry_common_header, &offsets);
-
- __u8 *pda1_header_offset = ptelemetry_buffer + offsets.da1_start_offset;//512
-
- print_micron_vs_logs(pda1_header_offset, ocp_header_in_da1,
- ARRAY_SIZE(ocp_header_in_da1), NULL, 0, NULL);
-
- printf(STR_LINE);
- printf("%s\n", STR_SMART_HEALTH_INFO);
- printf(STR_LINE);
- __u8 *pda1_smart_offset = pda1_header_offset +
- offsetof(struct nvme_ocp_header_in_da1, smart_health_info);
-
- print_micron_vs_logs(pda1_smart_offset, smart, ARRAY_SIZE(smart), NULL, 0, NULL);
-
- printf(STR_LINE);
- printf("%s\n", STR_SMART_HEALTH_INTO_EXTENDED);
- printf(STR_LINE);
- __u8 *pda1_smart_ext_offset = pda1_header_offset +
- offsetof(struct nvme_ocp_header_in_da1, smart_health_info_extended);
-
- print_micron_vs_logs(pda1_smart_ext_offset, smart_extended,
- ARRAY_SIZE(smart_extended), NULL, 0, NULL);
-
- printf(STR_LINE);
- printf("%s\n", STR_DA_1_STATS);
- printf(STR_LINE);
- status = parse_statistics(NULL, &offsets, NULL);
- if (status != 0) {
- nvme_show_error("status: %d\n", status);
- return -1;
- }
-
- printf(STR_LINE);
- printf("%s\n", STR_DA_1_EVENT_FIFO_INFO);
- printf(STR_LINE);
- status = parse_event_fifos(NULL, &offsets, NULL);
- if (status != 0) {
- nvme_show_error("status: %d\n", status);
- return -1;
- }
-
- //Set the DA to 2
- offsets.data_area = 2;
-
- printf(STR_LINE);
- printf("%s\n", STR_DA_2_STATS);
- printf(STR_LINE);
- status = parse_statistics(NULL, &offsets, NULL);
- if (status != 0) {
- nvme_show_error("status: %d\n", status);
- return -1;
- }
-
- printf(STR_LINE);
- printf("%s\n", STR_DA_2_EVENT_FIFO_INFO);
- printf(STR_LINE);
- status = parse_event_fifos(NULL, &offsets, NULL);
- if (status != 0) {
- nvme_show_error("status: %d\n", status);
- return -1;
- }
-
- printf(STR_LINE);
- }
-
- return status;
-}
-
-int print_ocp_telemetry_json(char *output_file)
-{
- int status = 0;
-
- //create json objects
- struct json_object *root, *pheader, *preason_identifier, *da1_header, *smart_obj,
- *ext_smart_obj;
-
- root = json_create_object();
-
- //Add data to root json object
-
- //"Log Page Header"
- pheader = json_create_object();
-
- print_micron_vs_logs(ptelemetry_buffer, host_log_page_header,
- ARRAY_SIZE(host_log_page_header), pheader, 0, NULL);
- json_object_add_value_object(root, STR_LOG_PAGE_HEADER, pheader);
-
- //"Reason Identifier"
- preason_identifier = json_create_object();
-
- __u8 *preason_identifier_offset = ptelemetry_buffer +
- offsetof(struct nvme_ocp_telemetry_host_initiated_header, reason_id);
-
- print_micron_vs_logs(preason_identifier_offset, reason_identifier,
- ARRAY_SIZE(reason_identifier), preason_identifier, 0, NULL);
- json_object_add_value_object(pheader, STR_REASON_IDENTIFIER, preason_identifier);
-
- struct nvme_ocp_telemetry_offsets offsets = { 0 };
-
- //Set DA to 1 and get offsets
- offsets.data_area = 1;
- struct nvme_ocp_telemetry_common_header *ptelemetry_common_header =
- (struct nvme_ocp_telemetry_common_header *) ptelemetry_buffer;
-
- get_telemetry_das_offset_and_size(ptelemetry_common_header, &offsets);
-
- //"Telemetry Host-Initiated Data Block 1"
- __u8 *pda1_header_offset = ptelemetry_buffer + offsets.da1_start_offset;//512
-
- da1_header = json_create_object();
-
- print_micron_vs_logs(pda1_header_offset, ocp_header_in_da1, ARRAY_SIZE(ocp_header_in_da1),
- da1_header, 0, NULL);
- json_object_add_value_object(root, STR_TELEMETRY_HOST_DATA_BLOCK_1, da1_header);
-
- //"SMART / Health Information Log(LID-02h)"
- __u8 *pda1_smart_offset = pda1_header_offset + offsetof(struct nvme_ocp_header_in_da1,
- smart_health_info);
- smart_obj = json_create_object();
-
- print_micron_vs_logs(pda1_smart_offset, smart, ARRAY_SIZE(smart), smart_obj, 0, NULL);
- json_object_add_value_object(da1_header, STR_SMART_HEALTH_INFO, smart_obj);
-
- //"SMART / Health Information Extended(LID-C0h)"
- __u8 *pda1_smart_ext_offset = pda1_header_offset + offsetof(struct nvme_ocp_header_in_da1,
- smart_health_info_extended);
- ext_smart_obj = json_create_object();
-
- print_micron_vs_logs(pda1_smart_ext_offset, smart_extended, ARRAY_SIZE(smart_extended),
- ext_smart_obj, 0, NULL);
- json_object_add_value_object(da1_header, STR_SMART_HEALTH_INTO_EXTENDED, ext_smart_obj);
-
- //Data Area 1 Statistics
- status = parse_statistics(root, &offsets, NULL);
- if (status != 0) {
- nvme_show_error("status: %d\n", status);
- return -1;
- }
-
- //Data Area 1 Event FIFOs
- status = parse_event_fifos(root, &offsets, NULL);
- if (status != 0) {
- nvme_show_error("status: %d\n", status, NULL);
- return -1;
- }
-
- //Set the DA to 2
- offsets.data_area = 2;
-
- //Data Area 2 Statistics
- status = parse_statistics(root, &offsets, NULL);
- if (status != 0) {
- nvme_show_error("status: %d\n", status);
- return -1;
- }
-
- //Data Area 2 Event FIFOs
- status = parse_event_fifos(root, &offsets, NULL);
- if (status != 0) {
- nvme_show_error("status: %d\n", status);
- return -1;
- }
-
- if (output_file != NULL) {
- const char *json_string = json_object_to_json_string(root);
- FILE *fp = fopen(output_file, "w");
-
- if (fp) {
- fputs(json_string, fp);
- fclose(fp);
- } else {
- nvme_show_error("Failed to open %s file.\n", output_file);
- return -1;
- }
- } else {
- //Print root json object
- json_print_object(root, NULL);
- nvme_show_result("\n");
- json_free_object(root);
- }
-
- return status;
-}
-
-int parse_ocp_telemetry_log(struct ocp_telemetry_parse_options *options)
-{
- int status = 0;
- long telemetry_buffer_size = 0;
- long string_buffer_size = 0;
- enum nvme_print_flags fmt;
- unsigned char log_id;
-
- // Read the data from the telemetry binary file
- ptelemetry_buffer =
- read_binary_file(NULL, options->telemetry_log, &telemetry_buffer_size, 1);
- if (ptelemetry_buffer == NULL) {
- nvme_show_error("Failed to read telemetry bin file.\n");
- return -1;
- }
-
- log_id = ptelemetry_buffer[0];
- if ((log_id != NVME_HOST_TELEMETRY_LOG) && (log_id != NVME_CNTRL_TELEMETRY_LOG)) {
- nvme_show_error("Invalid LogPageId [0x%02X]\n", log_id);
- return -1;
- }
-
- // Read the data from the string binary file
- pstring_buffer = read_binary_file(NULL, options->string_log, &string_buffer_size, 1);
- if (pstring_buffer == NULL) {
- nvme_show_error("Failed to read string log bin file.\n");
- return -1;
- }
-
- status = validate_output_format(options->output_fmt, &fmt);
- if (status < 0) {
- nvme_show_error("Invalid output format\n");
- return status;
- }
-
- switch (fmt) {
- case NORMAL:
- print_ocp_telemetry_normal(options->output_file);
- break;
- case JSON:
- print_ocp_telemetry_json(options->output_file);
- break;
- default:
- break;
- }
-
- return 0;
-}
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (c) Micron, Inc 2024.
- *
- * @file: micron-ocp-telemetry.h
- * @brief: This module contains all the constructs needed for parsing
- * (or) decoding ocp telemetry log files.
- * @author: Chaithanya Shoba <ashoba@micron.com>
- */
-
-#include "nvme.h"
-#include "nvme-print.h"
-#include "micron-utils.h"
-#include "common.h"
-
-#define DATA_SIZE_12 12
-#define DATA_SIZE_8 8
-#define DATA_SIZE_4 4
-#define NVME_HOST_TELEMETRY_LOG 0x07
-#define NVME_CNTRL_TELEMETRY_LOG 0x08
-#define MAX_BUFFER_32_KB 0x8000
-#define OCP_TELEMETRY_DATA_BLOCK_SIZE 512
-#define SIZE_OF_DWORD 4
-#define MAX_NUM_FIFOS 16
-#define DA1_OFFSET 512
-#define DEFAULT_ASCII_STRING_SIZE 16
-
-#define STR_LOG_PAGE_HEADER "Log Page Header"
-#define STR_REASON_IDENTIFIER "Reason Identifier"
-#define STR_TELEMETRY_HOST_DATA_BLOCK_1 "Telemetry Host-Initiated Data Block 1"
-#define STR_SMART_HEALTH_INFO "SMART / Health Information Log(LID-02h)"
-#define STR_SMART_HEALTH_INTO_EXTENDED "SMART / Health Information Extended(LID-C0h)"
-#define STR_DA_1_STATS "Data Area 1 Statistics"
-#define STR_DA_2_STATS "Data Area 2 Statistics"
-#define STR_DA_1_EVENT_FIFO_INFO "Data Area 1 Event FIFO info"
-#define STR_DA_2_EVENT_FIFO_INFO "Data Area 2 Event FIFO info"
-#define STR_STATISTICS_IDENTIFIER "Statistics Identifier"
-#define STR_STATISTICS_IDENTIFIER_STR "Statistic Identifier String"
-#define STR_STATISTICS_INFO_BEHAVIOUR_TYPE "Statistics Info Behavior Type"
-#define STR_STATISTICS_INFO_RESERVED "Statistics Info Reserved"
-#define STR_NAMESPACE_IDENTIFIER "Namespace Identifier"
-#define STR_NAMESPACE_INFO_VALID "Namespace Information Valid"
-#define STR_STATISTICS_DATA_SIZE "Statistic Data Size"
-#define STR_RESERVED "Reserved"
-#define STR_STATISTICS_SPECIFIC_DATA "Statistic Specific Data"
-#define STR_CLASS_SPECIFIC_DATA "Class Specific Data"
-#define STR_DBG_EVENT_CLASS_TYPE "Debug Event Class type"
-#define STR_EVENT_IDENTIFIER "Event Identifier"
-#define STR_EVENT_STRING "Event String"
-#define STR_EVENT_DATA_SIZE "Event Data Size"
-#define STR_VU_EVENT_STRING "VU Event String"
-#define STR_VU_EVENT_ID_STRING "VU Event Identifier"
-#define STR_VU_DATA "VU Data"
-#define STR_LINE "==============================================================================\n"
-#define STR_LINE2 "-----------------------------------------------------------------------------\n"
-
-struct __packed nvme_ocp_telemetry_reason_id
-{
- __u8 error_id[64]; // Bytes 63:00
- __u8 file_id[8]; // Bytes 71:64
- __le16 line_number; // Bytes 73:72
- __u8 valid_flags; // Bytes 74
- __u8 reserved[21]; // Bytes 95:75
- __u8 vu_reason_ext[32]; // Bytes 127:96
-};
-
-struct __packed nvme_ocp_telemetry_common_header
-{
- __u8 log_id; // Byte 00
- __le32 reserved1; // Bytes 04:01
- __u8 ieee_oui_id[3]; // Bytes 07:05
- __le16 da1_last_block; // Bytes 09:08
- __le16 da2_last_block; // Bytes 11:10
- __le16 da3_last_block; // Bytes 13:12
- __le16 reserved2; // Bytes 15:14
- __le32 da4_last_block; // Bytes 19:16
-};
-
-struct __packed nvme_ocp_telemetry_host_initiated_header
-{
- struct nvme_ocp_telemetry_common_header commonHeader; // Bytes 19:00
- __u8 reserved3[360]; // Bytes 379:20
- __u8 host_initiated_scope; // Byte 380
- __u8 host_initiated_gen_number; // Byte 381
- __u8 host_initiated_data_available; // Byte 382
- __u8 ctrl_initiated_gen_number; // Byte 383
- struct nvme_ocp_telemetry_reason_id reason_id; // Bytes 511:384
-};
-
-struct __packed nvme_ocp_telemetry_controller_initiated_header
-{
- struct nvme_ocp_telemetry_common_header commonHeader; // Bytes 19:00
- __u8 reserved3[361]; // Bytes 380:20
- __u8 ctrl_initiated_scope; // Byte 381
- __u8 ctrl_initiated_data_available; // Byte 382
- __u8 ctrl_initiated_gen_number; // Byte 383
- struct nvme_ocp_telemetry_reason_id reason_id; // Bytes 511:384
-};
-
-struct __packed nvme_ocp_telemetry_smart
-{
- __u8 critical_warning; // Byte 0
- __le16 composite_temperature; // Bytes 2:1
- __u8 available_spare; // Bytes 3
- __u8 available_spare_threshold; // Bytes 4
- __u8 percentage_used; // Bytes 5
- __u8 reserved1[26]; // Bytes 31:6
- __u8 data_units_read[16]; // Bytes 47:32
- __u8 data_units_written[16]; // Bytes 63:48
- __u8 host_read_commands[16]; // Byte 79:64
- __u8 host_write_commands[16]; // Bytes 95:80
- __u8 controller_busy_time[16]; // Bytes 111:96
- __u8 power_cycles[16]; // Bytes 127:112
- __u8 power_on_hours[16]; // Bytes 143:128
- __u8 unsafe_shutdowns[16]; // Bytes 159:144
- __u8 media_and_data_integrity_errors[16]; // Bytes 175:160
- __u8 number_of_error_information_log_entries[16]; // Bytes 191:176
- __le32 warning_composite_temperature_time; // Byte 195:192
- __le32 critical_composite_temperature_time; // Bytes 199:196
- __le16 temperature_sensor1; // Bytes 201:200
- __le16 temperature_sensor2; // Byte 203:202
- __le16 temperature_sensor3; // Byte 205:204
- __le16 temperature_sensor4; // Bytes 207:206
- __le16 temperature_sensor5; // Bytes 209:208
- __le16 temperature_sensor6; // Bytes 211:210
- __le16 temperature_sensor7; // Bytes 213:212
- __le16 temperature_sensor8; // Bytes 215:214
- __le32 thermal_management_temperature1_transition_count; // Bytes 219:216
- __le32 thermal_management_temperature2_transition_count; // Bytes 223:220
- __le32 total_time_for_thermal_management_temperature1; // Bytes 227:224
- __le32 total_time_for_thermal_management_temperature2; // Bytes 231:228
- __u8 reserved2[280]; // Bytes 511:232
-};
-
-struct __packed nvme_ocp_telemetry_smart_extended
-{
- __u8 physical_media_units_written[16]; // Bytes 15:0
- __u8 physical_media_units_read[16]; // Bytes 31:16
- __u8 bad_user_nand_blocks_raw_count[6]; // Bytes 37:32
- __le16 bad_user_nand_blocks_normalized_value; // Bytes 39:38
- __u8 bad_system_nand_blocks_raw_count[6]; // Bytes 45:40
- __le16 bad_system_nand_blocks_normalized_value; // Bytes 47:46
- __le64 xor_recovery_count; // Bytes 55:48
- __le64 uncorrectable_read_error_count; // Bytes 63:56
- __le64 soft_ecc_error_count; // Bytes 71:64
- __le32 end_to_end_correction_counts_detected_errors; // Bytes 75:72
- __le32 end_to_end_correction_counts_corrected_errors; // Bytes 79:76
- __u8 system_data_percent_used; // Byte 80
- __u8 refresh_counts[7]; // Bytes 87:81
- __le32 max_user_data_erase_count; // Bytes 91:88
- __le32 min_user_data_erase_count; // Bytes 95:92
- __u8 num_thermal_throttling_events; // Bytes 96
- __u8 current_throttling_status; // Bytes 97
- __u8 errata_version_field; // Byte 98
- __le16 point_version_field; // Byte 100:99
- __le16 minor_version_field; // Byte 102:101
- __u8 major_version_field; // Byte 103
- __le64 pcie_correctable_error_count; // Bytes 111:104
- __le32 incomplete_shutdowns; // Bytes 115:112
- __le32 reserved1; // Bytes 119:116
- __u8 percent_free_blocks; // Byte 120
- __u8 reserved2[7]; // Bytes 127:121
- __le16 capacitor_health; // Bytes 129:128
- __u8 nvme_base_errata_version; // Byte 130
- __u8 nvme_command_set_errata_version; // Byte 131
- __le32 reserved3; // Bytes 135:132
- __le64 unaligned_io; // Bytes 143:136
- __le64 security_version_number; // Bytes 151:144
- __le64 total_nuse; // Bytes 159:152
- __u8 plp_start_count[16]; // Bytes 175:160
- __u8 endurance_estimate[16]; // Bytes 191:176
- __le64 pcie_link_retraining_count; // Bytes 199:192
- __le64 power_state_change_count; // Bytes 207:200
- __le64 lowest_permitted_firmware_revision; // Bytes 215:208
- __u8 reserved4[278]; // Bytes 493:216
- __le16 log_page_version; // Bytes 495:494
- __u8 log_page_guid[16]; // Bytes 511:496
-};
-
-struct __packed nvme_ocp_event_fifo_data
-{
- __le32 event_fifo_num;
- __u8 event_fifo_da;
- __le64 event_fifo_start;
- __le64 event_fifo_size;
-};
-
-struct __packed nvme_ocp_telemetry_offsets
-{
- __le32 data_area;
- __le32 header_size;
- __le32 da1_start_offset;
- __le32 da1_size;
- __le32 da2_start_offset;
- __le32 da2_size;
- __le32 da3_start_offset;
- __le32 da3_size;
- __le32 da4_start_offset;
- __le32 da4_size;
-};
-
-struct __packed nvme_ocp_event_fifo_offsets
-{
- __le64 event_fifo_start;
- __le64 event_fifo_size;
-};
-
-struct __packed nvme_ocp_header_in_da1
-{
- __le16 major_version; // Bytes 1:0
- __le16 minor_version; // Bytes 3:2
- __le32 reserved1; // Bytes 7:4
- __le64 time_stamp; // Bytes 15:8
- __u8 log_page_guid[16]; // Bytes 31:16
- __u8 num_telemetry_profiles_supported; // Byte 32
- __u8 telemetry_profile_selected; // Byte 33
- __u8 reserved2[6]; // Bytes 39:34
- __le64 string_log_size; // Bytes 47:40
- __le64 reserved3; // Bytes 55:48
- __le64 firmware_revision; // Bytes 63:56
- __u8 reserved4[32]; // Bytes 95:64
- __le64 da1_statistic_start; // Bytes 103:96
- __le64 da1_statistic_size; // Bytes 111:104
- __le64 da2_statistic_start; // Bytes 119:112
- __le64 da2_statistic_size; // Bytes 127:120
- __u8 reserved5[32]; // Bytes 159:128
- __u8 event_fifo_da[16]; // Bytes 175:160
- struct nvme_ocp_event_fifo_offsets fifo_offsets[16]; // Bytes 431:176
- __u8 reserved6[80]; // Bytes 511:432
- struct nvme_ocp_telemetry_smart smart_health_info; // Bytes 1023:512
- struct nvme_ocp_telemetry_smart_extended smart_health_info_extended; // Bytes 1535:1024
-};
-
-struct __packed nvme_ocp_telemetry_statistic_descriptor
-{
- __le16 statistic_id; // Bytes 1:0
- __u8 statistic_info_behaviour_type : 4; // Byte 2(3:0)
- __u8 statistic_info_reserved : 4; // Byte 2(7:4)
- __u8 ns_info_nsid : 7; // Bytes 3(6:0)
- __u8 ns_info_ns_info_valid : 1; // Bytes 3(7)
- __le16 statistic_data_size; // Bytes 5:4
- __le16 reserved; // Bytes 7:6
-};
-
-struct __packed nvme_ocp_telemetry_event_descriptor
-{
- __u8 debug_event_class_type; // Byte 0
- __le16 event_id; // Bytes 2:1
- __u8 event_data_size; // Byte 3
-};
-
-struct __packed nvme_ocp_time_stamp_dbg_evt_class_format
-{
- __u8 time_stamp[DATA_SIZE_8]; // Bytes 11:4
- __le16 vu_event_identifier; // Bytes 13:12
-};
-
-struct __packed nvme_ocp_pcie_dbg_evt_class_format
-{
- __u8 pCIeDebugEventData[DATA_SIZE_4]; // Bytes 7:4
- __le16 vu_event_identifier; // Bytes 9:8
-};
-
-struct __packed nvme_ocp_nvme_dbg_evt_class_format
-{
- __u8 nvmeDebugEventData[DATA_SIZE_8]; // Bytes 11:4
- __le16 vu_event_identifier; // Bytes 13:12
-};
-
-struct __packed nvme_ocp_common_dbg_evt_class_format
-{
- __le16 vu_event_identifier; // Bytes 5:4
-};
-
-struct __packed nvme_ocp_media_wear_dbg_evt_class_format
-{
- __u8 currentMediaWear[DATA_SIZE_12]; // Bytes 15:4
- __le16 vu_event_identifier; // Bytes 17:16
-};
-
-struct __packed nvme_ocp_statistic_snapshot_evt_class_format
-{
- struct nvme_ocp_telemetry_statistic_descriptor statisticDescriptorData; // Bytes 11:10
-};
-
-struct __packed nvme_ocp_statistics_identifier_string_table
-{
- __le16 vs_statistic_identifier; //1:0
- __u8 reserved1; //2
- __u8 ascii_id_length; //3
- __le64 ascii_id_offset; //11:4
- __le32 reserved2; //15:12
-};
-
-struct __packed nvme_ocp_event_string_table
-{
- __u8 debug_event_class; //0
- __le16 event_identifier; //2:1
- __u8 ascii_id_length; //3
- __le64 ascii_id_offset; //11:4
- __le32 reserved; //15:12
-};
-
-struct __packed nvme_ocp_vu_event_string_table
-{
- __u8 debug_event_class; //0
- __le16 vu_event_identifier; //2:1
- __u8 ascii_id_length; //3
- __le64 ascii_id_offset; //11:4
- __le32 reserved; //15:12
-};
-
-struct __packed nvme_ocp_telemetry_string_header
-{
- __u8 version; //0:0
- __u8 reserved1[15]; //15:1
- __u8 guid[16]; //32:16
- __le64 string_log_size; //39:32
- __u8 reserved2[24]; //63:40
- __le64 sits; //71:64 Statistics Identifier String Table Start(SITS)
- __le64 sitsz; //79:72 Statistics Identifier String Table Size (SITSZ)
- __le64 ests; //87:80 Event String Table Start(ESTS)
- __le64 estsz; //95:88 Event String Table Size(ESTSZ)
- __le64 vu_ests; //103:96 VU Event String Table Start
- __le64 vu_estsz; //111:104 VU Event String Table Size
- __le64 ascts; //119:112 ASCII Table start
- __le64 asctsz; //127:120 ASCII Table Size
- __u8 fifo_ascii_string[16][16]; //383:128
- __u8 reserved3[48]; //431:384
-};
-
-struct __packed statistic_entry {
- int identifier;
- char *description;
-};
-
-struct __packed ocp_telemetry_parse_options {
- char *telemetry_log;
- char *string_log;
- char *output_file;
- char *output_fmt;
-};
-
-/**
- * enum ocp_telemetry_data_area - Telemetry Data Areas
- * @DATA_AREA_1: Data Area 1
- * @DATA_AREA_2: Data Area 2
- * @DATA_AREA_3: Data Area 3
- * @DATA_AREA_4: Data Area 4
- */
-enum ocp_telemetry_data_area {
- DATA_AREA_1 = 0x01,
- DATA_AREA_2 = 0x02,
- DATA_AREA_3 = 0x03,
- DATA_AREA_4 = 0x04,
-};
-
-/**
- * enum ocp_telemetry_string_tables - OCP telemetry string tables
- * @STATISTICS_IDENTIFIER_STRING: Statistic Identifier string
- * @EVENT_STRING: Event String
- * @VU_EVENT_STRING: VU Event String
- */
-enum ocp_telemetry_string_tables {
- STATISTICS_IDENTIFIER_STRING = 0,
- EVENT_STRING,
- VU_EVENT_STRING
-};
-
-/**
- * enum ocp_telemetry_debug_event_class_types - OCP Debug Event Class types
- * @RESERVED_CLASS_TYPE: Reserved class
- * @TIME_STAMP_CLASS_TYPE: Time stamp class
- * @PCIE_CLASS_TYPE: PCIe class
- * @NVME_CLASS_TYPE: NVME class
- * @RESET_CLASS_TYPE: Reset class
- * @BOOT_SEQUENCE_CLASS_TYPE: Boot Sequence class
- * @FIRMWARE_ASSERT_CLASS_TYPE: Firmware Assert class
- * @TEMPERATURE_CLASS_TYPE: Temperature class
- * @MEDIA_CLASS_TYPE: Media class
- * @MEDIA_WEAR_CLASS_TYPE: Media wear class
- * @STATISTIC_SNAPSHOT_CLASS_TYPE: Statistic snapshot class
- * @RESERVED: Reserved class
- * @VENDOR_UNIQUE_CLASS_TYPE: Vendor Unique class
- */
-enum ocp_telemetry_debug_event_class_types {
- RESERVED_CLASS_TYPE = 0x00,
- TIME_STAMP_CLASS_TYPE = 0x01,
- PCIE_CLASS_TYPE = 0x02,
- NVME_CLASS_TYPE = 0x03,
- RESET_CLASS_TYPE = 0x04,
- BOOT_SEQUENCE_CLASS_TYPE = 0x05,
- FIRMWARE_ASSERT_CLASS_TYPE = 0x06,
- TEMPERATURE_CLASS_TYPE = 0x07,
- MEDIA_CLASS_TYPE = 0x08,
- MEDIA_WEAR_CLASS_TYPE = 0x09,
- STATISTIC_SNAPSHOT_CLASS_TYPE = 0x0A,
- //RESERVED = 7Fh-0Bh,
- //VENDOR_UNIQUE_CLASS_TYPE = FFh-80h,
-};
-
-/**
- * @brief parse the ocp telemetry host or controller log binary file
- * into json or text
- *
- * @param options, input pointer for inputs like telemetry log bin file,
- * string log bin file and output file etc.
- *
- * @return 0 success
- */
-int parse_ocp_telemetry_log(struct ocp_telemetry_parse_options *options);
-
-/**
- * @brief parse the ocp telemetry string log binary file to json or text
- *
- * @param event_fifo_num, input event FIFO number
- * @param debug_event_class, input debug event class id
- * @param string_table, input string table
- * @param description, input description string
- *
- * @return 0 success
- */
-int parse_ocp_telemetry_string_log(int event_fifo_num, int identifier, int debug_event_class,
- enum ocp_telemetry_string_tables string_table, char *description);
-
-/**
- * @brief gets the telemetry datas areas, offsets and sizes information
- *
- * @param ptelemetry_common_header, input telemetry common header pointer
- * @param ptelemetry_das_offset, input telemetry offsets pointer
- *
- * @return 0 success
- */
-int get_telemetry_das_offset_and_size(
- struct nvme_ocp_telemetry_common_header *ptelemetry_common_header,
- struct nvme_ocp_telemetry_offsets *ptelemetry_das_offset);
-
-/**
- * @brief parses statistics data to text or json formats
- *
- * @param root, input time json root object pointer
- * @param ptelemetry_das_offset, input telemetry offsets pointer
- * @param fp, input file pointer
- *
- * @return 0 success
- */
-int parse_statistics(struct json_object *root, struct nvme_ocp_telemetry_offsets *pOffsets,
- FILE *fp);
-
-/**
- * @brief parses a single statistic data to text or json formats
- *
- * @param pstatistic_entry, statistic entry pointer
- * @param pstats_array, stats array pointer
- * @param fp, input file pointer
- *
- * @return 0 success
- */
-int parse_statistic(struct nvme_ocp_telemetry_statistic_descriptor *pstatistic_entry,
- struct json_object *pstats_array, FILE *fp);
-
-/**
- * @brief parses event fifos data to text or json formats
- *
- * @param root, input time json root object pointer
- * @param poffsets, input telemetry offsets pointer
- * @param fp, input file pointer
- *
- * @return 0 success
- */
-int parse_event_fifos(struct json_object *root, struct nvme_ocp_telemetry_offsets *poffsets,
- FILE *fp);
-
-/**
- * @brief parses a single event fifo data to text or json formats
- *
- * @param fifo_num, input event fifo number
- * @param pfifo_start, event fifo start pointer
- * @param pevent_fifos_object, event fifos json object pointer
- * @param ptelemetry_das_offset, input telemetry offsets pointer
- * @param fifo_size, input event fifo size
- * @param fp, input file pointer
- *
- * @return 0 success
- */
-int parse_event_fifo(unsigned int fifo_num, unsigned char *pfifo_start,
- struct json_object *pevent_fifos_object, unsigned char *pstring_buffer,
- struct nvme_ocp_telemetry_offsets *poffsets, __u64 fifo_size, FILE *fp);
-
-/**
- * @brief parses event fifos data to text or json formats
- *
- * @return 0 success
- */
-int print_ocp_telemetry_normal(char *output_file);
-
-/**
- * @brief parses event fifos data to text or json formats
- *
- * @return 0 success
- */
-int print_ocp_telemetry_json(char *output_file);
-
-/**
- * @brief gets statistic id ascii string
- *
- * @param identifier, string id
- * @param description, string description
- *
- * @return 0 success
- */
-int get_static_id_ascii_string(int identifier, char *description);
-
-/**
- * @brief gets event id ascii string
- *
- * @param identifier, string id
- * @param debug_event_class, debug event class
- * @param description, string description
- *
- * @return 0 success
- */
-int get_event_id_ascii_string(int identifier, int debug_event_class, char *description);
-
-/**
- * @brief gets vu event id ascii string
- *
- * @param identifier, string id
- * @param debug_event_class, debug event class
- * @param description, string description
- *
- * @return 0 success
- */
-int get_vu_event_id_ascii_string(int identifier, int debug_event_class, char *description);
-
-/**
- * @brief parses a time-stamp event fifo data to text or json formats
- *
- * @param pevent_descriptor, input event descriptor data
- * @param pevent_descriptor_obj, event descriptor json object pointer
- * @param pevent_specific_data, input event specific data
- * @param pevent_fifos_object, event fifos json object pointer
- * @param fp, input file pointer
- *
- * @return
- */
-void parse_time_stamp_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor,
- struct json_object *pevent_descriptor_obj, __u8 *pevent_specific_data,
- struct json_object *pevent_fifos_object, FILE *fp);
-
-/**
- * @brief parses a pcie event fifo data to text or json formats
- *
- * @param pevent_descriptor, input event descriptor data
- * @param pevent_descriptor_obj, event descriptor json object pointer
- * @param pevent_specific_data, input event specific data
- * @param pevent_fifos_object, event fifos json object pointer
- * @param fp, input file pointer
- *
- * @return
- */
-void parse_pcie_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor,
- struct json_object *pevent_descriptor_obj, __u8 *pevent_specific_data,
- struct json_object *pevent_fifos_object, FILE *fp);
-
-/**
- * @brief parses a nvme event fifo data to text or json formats
- *
- * @param pevent_descriptor, input event descriptor data
- * @param pevent_descriptor_obj, event descriptor json object pointer
- * @param pevent_specific_data, input event specific data
- * @param pevent_fifos_object, event fifos json object pointer
- * @param fp, input file pointer
- *
- * @return
- */
-void parse_nvme_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor,
- struct json_object *pevent_descriptor_obj, __u8 *pevent_specific_data,
- struct json_object *pevent_fifos_object, FILE *fp);
-
-/**
- * @brief parses common event fifo data to text or json formats
- *
- * @param pevent_descriptor, input event descriptor data
- * @param pevent_descriptor_obj, event descriptor json object pointer
- * @param pevent_specific_data, input event specific data
- * @param pevent_fifos_object, event fifos json object pointer
- * @param fp, input file pointer
- *
- * @return
- */
-void parse_common_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor,
- struct json_object *pevent_descriptor_obj, __u8 *pevent_specific_data,
- struct json_object *pevent_fifos_object, FILE *fp);
-
-/**
- * @brief parses a media-wear event fifo data to text or json formats
- *
- * @param pevent_descriptor, input event descriptor data
- * @param pevent_descriptor_obj, event descriptor json object pointer
- * @param pevent_specific_data, input event specific data
- * @param pevent_fifos_object, event fifos json object pointer
- * @param fp, input file pointer
- *
- * @return
- */
-void parse_media_wear_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor,
- struct json_object *pevent_descriptor_obj, __u8 *pevent_specific_data,
- struct json_object *pevent_fifos_object, FILE *fp);
printf(" Active Threshold D %d ms\n",
C3_ACTIVE_THRESHOLD_INCREMENT *
le16_to_cpu(log_data->active_threshold_d+1));
- printf(" Active Latency Configuration 0x%x \n",
+ printf(" Active Latency Configuration 0x%x\n",
le16_to_cpu(log_data->active_latency_config));
printf(" Active Latency Minimum Window %d ms\n",
C3_MINIMUM_WINDOW_INCREMENT *
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// Telemetry Log
+//global buffers
+static __le64 total_log_page_sz;
+static struct telemetry_str_log_format *log_data;
+
+__u8 *ptelemetry_buffer;
+__u8 *pstring_buffer;
+__u8 *pC9_string_buffer;
static void get_serial_number(struct nvme_id_ctrl *ctrl, char *sn)
{
__u32 numd = (data_len >> 2) - 1;
__u16 numdu = numd >> 16;
__u16 numdl = numd & 0xffff;
+
cmd.cdw10 = tele_type |
(nLSP & 0x0F) << 8 |
(nRAE & 0x01) << 15 |
{
if (da1) {
int i = 0;
+
if (tele_type == TELEMETRY_TYPE_HOST)
printf("============ Telemetry Host Data area 1 ============\n");
else
else
printf("========= Telemetry Controller Data Area %d Statistics =========\n",
data_area);
- while((i + 8) < buf_size) {
+ while ((i + 8) < buf_size) {
print_stats_desc(next_da_stat);
i += 8 + ((next_da_stat->size) * 4);
next_da_stat = (struct telemetry_stats_desc *)((__u64)da_stat + i);
da, index);
- while((i + 4) < buf_size) {
+ while ((i + 4) < buf_size) {
/* Print Event Data */
print_telemetry_fifo_event(next_da_fifo->class, /* Event class type */
next_da_fifo->id, /* Event ID */
return err;
}
+static int get_telemetry_log_page_data(struct nvme_dev *dev, int tele_type)
+{
+ char file_path[PATH_MAX];
+ void *telemetry_log;
+ const size_t bs = 512;
+ struct nvme_telemetry_log *hdr;
+ size_t full_size, offset = bs;
+ int err, fd;
+
+ if ((tele_type == TELEMETRY_TYPE_HOST_0) || (tele_type == TELEMETRY_TYPE_HOST_1))
+ tele_type = TELEMETRY_TYPE_HOST;
+
+ int log_id = (tele_type == TELEMETRY_TYPE_HOST ? NVME_LOG_LID_TELEMETRY_HOST :
+ NVME_LOG_LID_TELEMETRY_CTRL);
+
+ hdr = malloc(bs);
+ telemetry_log = malloc(bs);
+ if (!hdr || !telemetry_log) {
+ fprintf(stderr, "Failed to allocate %zu bytes for log: %s\n",
+ bs, strerror(errno));
+ err = -ENOMEM;
+ goto exit_status;
+ }
+ memset(hdr, 0, bs);
+
+ sprintf(file_path, DEFAULT_TELEMETRY_BIN);
+ fd = open(file_path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if (fd < 0) {
+ fprintf(stderr, "Failed to open output file %s: %s!\n",
+ file_path, strerror(errno));
+ err = fd;
+ goto exit_status;
+ }
+
+ struct nvme_get_log_args args = {
+ .lpo = 0,
+ .result = NULL,
+ .log = hdr,
+ .args_size = sizeof(args),
+ .fd = dev_fd(dev),
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .lid = log_id,
+ .len = bs,
+ .nsid = NVME_NSID_ALL,
+ .csi = NVME_CSI_NVM,
+ .lsi = NVME_LOG_LSI_NONE,
+ .lsp = NVME_LOG_TELEM_HOST_LSP_CREATE,
+ .uuidx = NVME_UUID_NONE,
+ .rae = true,
+ .ot = false,
+ };
+
+ err = nvme_get_log(&args);
+ if (err < 0)
+ nvme_show_error("Failed to fetch the log from drive.\n");
+ else if (err > 0) {
+ nvme_show_status(err);
+ nvme_show_error("Failed to fetch telemetry-header. Error:%d.\n", err);
+ goto close_fd;
+ }
+
+ err = write(fd, (void *)hdr, bs);
+ if (err != bs) {
+ nvme_show_error("Failed to write data to file.\n");
+ goto close_fd;
+ }
+
+ full_size = (le16_to_cpu(hdr->dalb3) * bs) + offset;
+
+ while (offset != full_size) {
+ args.log = telemetry_log;
+ args.lpo = offset;
+ args.lsp = NVME_LOG_LSP_NONE;
+ err = nvme_get_log(&args);
+ if (err < 0) {
+ nvme_show_error("Failed to fetch the log from drive.\n");
+ break;
+ } else if (err > 0) {
+ nvme_show_error("Failed to fetch telemetry-log.\n");
+ nvme_show_status(err);
+ break;
+ }
+
+ err = write(fd, (void *)telemetry_log, bs);
+ if (err != bs) {
+ nvme_show_error("Failed to write data to file.\n");
+ break;
+ }
+ err = 0;
+ offset += bs;
+ }
+
+close_fd:
+ close(fd);
+exit_status:
+ free(hdr);
+ free(telemetry_log);
+
+ return err;
+}
+
+static int get_c9_log_page_data(struct nvme_dev *dev, int print_data, int save_bin)
+{
+ int ret = 0, fd;
+ __u8 *header_data;
+ struct telemetry_str_log_format *log_data;
+ __le64 stat_id_str_table_ofst = 0;
+ __le64 event_str_table_ofst = 0;
+ __le64 vu_event_str_table_ofst = 0;
+ __le64 ascii_table_ofst = 0;
+ char file_path[PATH_MAX];
+
+ header_data = (__u8 *)malloc(sizeof(__u8) * C9_TELEMETRY_STR_LOG_LEN);
+ if (!header_data) {
+ fprintf(stderr, "ERROR : OCP : malloc : %s\n", strerror(errno));
+ return -1;
+ }
+ memset(header_data, 0, sizeof(__u8) * C9_TELEMETRY_STR_LOG_LEN);
+
+ ret = nvme_get_log_simple(dev_fd(dev), C9_TELEMETRY_STRING_LOG_ENABLE_OPCODE,
+ C9_TELEMETRY_STR_LOG_LEN, header_data);
+
+ if (!ret) {
+ log_data = (struct telemetry_str_log_format *)header_data;
+ if (print_data) {
+ printf("Statistics Identifier String Table Size = %lld\n",
+ log_data->sitsz);
+ printf("Event String Table Size = %lld\n", log_data->estsz);
+ printf("VU Event String Table Size = %lld\n", log_data->vu_eve_st_sz);
+ printf("ASCII Table Size = %lld\n", log_data->asctsz);
+ }
+
+ //Calculating the offset for dynamic fields.
+
+ stat_id_str_table_ofst = log_data->sits * 4;
+ event_str_table_ofst = log_data->ests * 4;
+ vu_event_str_table_ofst = log_data->vu_eve_sts * 4;
+ ascii_table_ofst = log_data->ascts * 4;
+ total_log_page_sz = C9_TELEMETRY_STR_LOG_LEN +
+ (log_data->sitsz * 4) + (log_data->estsz * 4) +
+ (log_data->vu_eve_st_sz * 4) + (log_data->asctsz * 4);
+
+ if (print_data) {
+ printf("stat_id_str_table_ofst = %lld\n", stat_id_str_table_ofst);
+ printf("event_str_table_ofst = %lld\n", event_str_table_ofst);
+ printf("vu_event_str_table_ofst = %lld\n", vu_event_str_table_ofst);
+ printf("ascii_table_ofst = %lld\n", ascii_table_ofst);
+ printf("total_log_page_sz = %lld\n", total_log_page_sz);
+ }
+
+ pC9_string_buffer = (__u8 *)malloc(sizeof(__u8) * total_log_page_sz);
+ if (!pC9_string_buffer) {
+ fprintf(stderr, "ERROR : OCP : malloc : %s\n", strerror(errno));
+ return -1;
+ }
+ memset(pC9_string_buffer, 0, sizeof(__u8) * total_log_page_sz);
+
+ ret = nvme_get_log_simple(dev_fd(dev), C9_TELEMETRY_STRING_LOG_ENABLE_OPCODE,
+ total_log_page_sz, pC9_string_buffer);
+ } else
+ fprintf(stderr, "ERROR : OCP : Unable to read C9 data.\n");
+
+ if (save_bin) {
+ sprintf(file_path, DEFAULT_STRING_BIN);
+ fd = open(file_path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if (fd < 0) {
+ fprintf(stderr, "Failed to open output file %s: %s!\n",
+ file_path, strerror(errno));
+ goto exit_status;
+ }
+
+ ret = write(fd, (void *)pC9_string_buffer, total_log_page_sz);
+ if (ret != total_log_page_sz)
+ fprintf(stderr, "Failed to flush all data to file!\n");
+
+ close(fd);
+ }
+
+exit_status:
+ free(header_data);
+ return 0;
+}
+
+int parse_ocp_telemetry_log(struct ocp_telemetry_parse_options *options)
+{
+ int status = 0;
+ long telemetry_buffer_size = 0;
+ long string_buffer_size = 0;
+ enum nvme_print_flags fmt;
+ unsigned char log_id;
+
+ if (options->telemetry_log) {
+ if (strstr((const char *)options->telemetry_log, "bin")) {
+ // Read the data from the telemetry binary file
+ ptelemetry_buffer =
+ read_binary_file(NULL, (const char *)options->telemetry_log,
+ &telemetry_buffer_size, 1);
+ if (ptelemetry_buffer == NULL) {
+ nvme_show_error("Failed to read telemetry-log.\n");
+ return -1;
+ }
+ }
+ } else {
+ nvme_show_error("telemetry-log is empty.\n");
+ return -1;
+ }
+
+ log_id = ptelemetry_buffer[0];
+ if ((log_id != NVME_LOG_LID_TELEMETRY_HOST) && (log_id != NVME_LOG_LID_TELEMETRY_CTRL)) {
+ nvme_show_error("Invalid LogPageId [0x%02X]\n", log_id);
+ return -1;
+ }
+
+ if (options->string_log) {
+ // Read the data from the string binary file
+ if (strstr((const char *)options->string_log, "bin")) {
+ pstring_buffer = read_binary_file(NULL, (const char *)options->string_log,
+ &string_buffer_size, 1);
+ if (pstring_buffer == NULL) {
+ nvme_show_error("Failed to read string-log.\n");
+ return -1;
+ }
+ }
+ } else {
+ nvme_show_error("string-log is empty.\n");
+ return -1;
+ }
+
+ status = validate_output_format(options->output_format, &fmt);
+ if (status < 0) {
+ nvme_show_error("Invalid output format\n");
+ return status;
+ }
+
+ switch (fmt) {
+ case NORMAL:
+ print_ocp_telemetry_normal(options);
+ break;
+ case JSON:
+ print_ocp_telemetry_json(options);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
static int ocp_telemetry_log(int argc, char **argv, struct command *cmd,
struct plugin *plugin)
{
- struct nvme_dev *dev;
- int err = 0;
- const char *desc = "Retrieve and save telemetry log.";
- const char *type = "Telemetry Type; 'host[Create bit]' or 'controller'";
- const char *area = "Telemetry Data Area; 1 or 3";
- const char *file = "Output file name with path;\n"
+ const char *desc = "Retrieve and parse OCP Telemetry log.";
+ const char *telemetry_log = "Telemetry log binary;\n 'host.bin' or 'controller.bin'";
+ const char *string_log = "String log binary; 'C9.bin'";
+ const char *output_file = "Output file name with path;\n"
"e.g. '-o ./path/name'\n'-o ./path1/path2/';\n"
"If requested path does not exist, the directory will be newly created.";
+ const char *output_format = "output format normal|json";
+ const char *data_area = "Telemetry Data Area; 1 or 2;\n"
+ "e.g. '-a 1 for Data Area 1.'\n'-a 2 for Data Areas 1 and 2.';\n";
+ const char *telemetry_type = "Telemetry Type; 'host' or 'controller'";
+ struct nvme_dev *dev;
+ int err = 0;
__u32 nsid = NVME_NSID_ALL;
struct stat nvme_stat;
char sn[21] = {0,};
struct nvme_id_ctrl ctrl;
bool is_support_telemetry_controller;
-
+ struct ocp_telemetry_parse_options opt;
int tele_type = 0;
int tele_area = 0;
- struct config {
- char *type;
- int area;
- char *file;
- };
-
- struct config cfg = {
- .type = NULL,
- .area = 0,
- .file = NULL,
- };
-
OPT_ARGS(opts) = {
- OPT_STR("telemetry_type", 't', &cfg.type, type),
- OPT_INT("telemetry_data_area", 'a', &cfg.area, area),
- OPT_FILE("output-file", 'o', &cfg.file, file),
+ OPT_STR("telemetry-log", 'l', &opt.telemetry_log, telemetry_log),
+ OPT_STR("string-log", 's', &opt.string_log, string_log),
+ OPT_FILE("output-file", 'o', &opt.output_file, output_file),
+ OPT_FMT("output-format", 'f', &opt.output_format, output_format),
+ OPT_INT("data-area", 'a', &opt.data_area, data_area),
+ OPT_STR("telemetry-type", 't', &opt.telemetry_type, telemetry_type),
OPT_END()
};
is_support_telemetry_controller = ((ctrl.lpa & 0x8) >> 3);
- if (!cfg.type && !cfg.area) {
- tele_type = TELEMETRY_TYPE_NONE;
- tele_area = 0;
- } else if (cfg.type && cfg.area) {
- if (!strcmp(cfg.type, "host0"))
+ if (!opt.data_area) {
+ nvme_show_result("Missing data-area. Using default data area 1.\n");
+ opt.data_area = DATA_AREA_1;//Default data area 1
+ } else if (opt.data_area != 1 && opt.data_area != 2) {
+ nvme_show_result("Invalid data-area specified. Please specify 1 or 2.\n");
+ goto out;
+ }
+
+ tele_area = opt.data_area;
+
+ if (opt.telemetry_type) {
+ if (!strcmp(opt.telemetry_type, "host0"))
tele_type = TELEMETRY_TYPE_HOST_0;
- else if (!strcmp(cfg.type, "host1"))
+ else if (!strcmp(opt.telemetry_type, "host1"))
tele_type = TELEMETRY_TYPE_HOST_1;
- else if (!strcmp(cfg.type, "controller"))
+ else if (!strcmp(opt.telemetry_type, "host"))
+ tele_type = TELEMETRY_TYPE_HOST;
+ else if (!strcmp(opt.telemetry_type, "controller"))
tele_type = TELEMETRY_TYPE_CONTROLLER;
+ else {
+ nvme_show_error("telemetry-type should be host or controller.\n");
+ goto out;
+ }
+ } else {
+ tele_type = TELEMETRY_TYPE_HOST; //Default Type - Host
+ nvme_show_result("Missing telemetry-type. Using default - host.\n");
+ }
- tele_area = cfg.area;
+ if (!opt.telemetry_log) {
+ nvme_show_result("\nMissing telemetry-log. Fetching from drive...\n");
+ err = get_telemetry_log_page_data(dev, tele_type);//Pull Telemetry log
+ if (err) {
+ nvme_show_error("Failed to fetch telemetry-log from the drive.\n");
+ goto out;
+ }
+ nvme_show_result("telemetry.bin generated. Proceeding with next steps.\n");
+ opt.telemetry_log = DEFAULT_TELEMETRY_BIN;
+ }
- if ((tele_area != 1 && tele_area != 3) ||
- (tele_type == TELEMETRY_TYPE_CONTROLLER && tele_area != 3)) {
- printf("\nUnsupported parameters entered.\n");
- printf("Possible combinations; {'host0',1}, {'host0',3}, {'host1',1}, {'host1',3}, {'controller',3}\n");
- return err;
+ if (!opt.string_log) {
+ nvme_show_result("Missing string-log. Fetching from drive...\n");
+ err = get_c9_log_page_data(dev, 0, 1); //Pull String log
+ if (err) {
+ nvme_show_error("Failed to fetch string-log from the drive.\n");
+ goto out;
}
- } else {
- printf("\nShould provide these all; 'telemetry_type' and 'telemetry_data_area'\n");
- return err;
+ nvme_show_result("string.bin generated. Proceeding with next steps.\n");
+ opt.string_log = DEFAULT_STRING_BIN;
}
- if (tele_type == TELEMETRY_TYPE_NONE) {
+ if (!opt.output_format) {
+ nvme_show_result("Missing format. Using default format - JSON.\n");
+ opt.output_format = DEFAULT_OUTPUT_FORMAT_JSON;
+ }
+
+ switch (tele_type) {
+ case TELEMETRY_TYPE_HOST: {
+ printf("Extracting Telemetry Host Dump (Data Area %d)...\n", tele_area);
+ err = parse_ocp_telemetry_log(&opt);
+ if (err)
+ nvme_show_result("Status:(%x)\n", err);
+ }
+ break;
+ case TELEMETRY_TYPE_CONTROLLER: {
+ printf("Extracting Telemetry Controller Dump (Data Area %d)...\n", tele_area);
+ if (is_support_telemetry_controller == true) {
+ err = parse_ocp_telemetry_log(&opt);
+ if (err)
+ nvme_show_result("Status:(%x)\n", err);
+ }
+ }
+ break;
+ case TELEMETRY_TYPE_NONE: {
printf("\n-------------------------------------------------------------\n");
/* Host 0 (lsp == 0) must be executed before Host 1 (lsp == 1). */
printf("\nExtracting Telemetry Host 0 Dump (Data Area 1)...\n");
- err = get_telemetry_dump(dev, cfg.file, sn,
+ err = get_telemetry_dump(dev, opt.output_file, sn,
TELEMETRY_TYPE_HOST_0, 1, true);
if (err)
fprintf(stderr, "NVMe Status: %s(%x)\n", nvme_status_to_string(err, false), err);
printf("\nExtracting Telemetry Host 0 Dump (Data Area 3)...\n");
- err = get_telemetry_dump(dev, cfg.file, sn,
+ err = get_telemetry_dump(dev, opt.output_file, sn,
TELEMETRY_TYPE_HOST_0, 3, false);
if (err)
fprintf(stderr, "NVMe Status: %s(%x)\n", nvme_status_to_string(err, false), err);
printf("\nExtracting Telemetry Host 1 Dump (Data Area 1)...\n");
- err = get_telemetry_dump(dev, cfg.file, sn,
+ err = get_telemetry_dump(dev, opt.output_file, sn,
TELEMETRY_TYPE_HOST_1, 1, true);
if (err)
fprintf(stderr, "NVMe Status: %s(%x)\n", nvme_status_to_string(err, false), err);
printf("\nExtracting Telemetry Host 1 Dump (Data Area 3)...\n");
- err = get_telemetry_dump(dev, cfg.file, sn,
+ err = get_telemetry_dump(dev, opt.output_file, sn,
TELEMETRY_TYPE_HOST_1, 3, false);
if (err)
fprintf(stderr, "NVMe Status: %s(%x)\n", nvme_status_to_string(err, false), err);
printf("\nExtracting Telemetry Controller Dump (Data Area 3)...\n");
if (is_support_telemetry_controller == true) {
- err = get_telemetry_dump(dev, cfg.file, sn,
+ err = get_telemetry_dump(dev, opt.output_file, sn,
TELEMETRY_TYPE_CONTROLLER, 3, true);
if (err)
fprintf(stderr, "NVMe Status: %s(%x)\n", nvme_status_to_string(err, false), err);
}
printf("\n-------------------------------------------------------------\n");
- } else if (tele_type == TELEMETRY_TYPE_CONTROLLER) {
- printf("Extracting Telemetry Controller Dump (Data Area %d)...\n", tele_area);
-
- if (is_support_telemetry_controller == true) {
- err = get_telemetry_dump(dev, cfg.file, sn, tele_type, tele_area, true);
- if (err)
- fprintf(stderr, "NVMe Status: %s(%x)\n", nvme_status_to_string(err, false), err);
- }
- } else {
+ }
+ break;
+ case TELEMETRY_TYPE_HOST_0:
+ case TELEMETRY_TYPE_HOST_1:
+ default: {
printf("Extracting Telemetry Host(%d) Dump (Data Area %d)...\n",
(tele_type == TELEMETRY_TYPE_HOST_0) ? 0 : 1, tele_area);
- err = get_telemetry_dump(dev, cfg.file, sn, tele_type, tele_area, true);
+ err = get_telemetry_dump(dev, opt.output_file, sn, tele_type, tele_area, true);
if (err)
fprintf(stderr, "NVMe Status: %s(%x)\n", nvme_status_to_string(err, false), err);
}
+ break;
+ }
- printf("telemetry-log done.\n");
-
+ printf("ocp internal-log command completed.\n");
+out:
+ dev_close(dev);
return err;
}
///////////////////////////////////////////////////////////////////////////////
/// Telemetry String Log Format Log Page (LID : C9h)
-/* C9 Telemetry String Log Format Log Page */
-#define C9_GUID_LENGTH 16
-#define C9_TELEMETRY_STRING_LOG_ENABLE_OPCODE 0xC9
-#define C9_TELEMETRY_STR_LOG_LEN 432
-#define C9_TELEMETRY_STR_LOG_SIST_OFST 431
-
-/**
- * struct telemetry_str_log_format - Telemetry String Log Format
- * @log_page_version: indicates the version of the mapping this log page uses
- * Shall be set to 01h.
- * @reserved1: Reserved.
- * @log_page_guid: Shall be set to B13A83691A8F408B9EA495940057AA44h.
- * @sls: Shall be set to the number of DWORDS in the String Log.
- * @reserved2: reserved.
- * @sits: shall be set to the number of DWORDS in the Statistics
- * Identifier String Table
- * @ests: Shall be set to the number of DWORDS from byte 0 of this
- * log page to the start of the Event String Table
- * @estsz: shall be set to the number of DWORDS in the Event String Table
- * @vu_eve_sts: Shall be set to the number of DWORDS from byte 0 of this
- * log page to the start of the VU Event String Table
- * @vu_eve_st_sz: shall be set to the number of DWORDS in the VU Event String Table
- * @ascts: the number of DWORDS from byte 0 of this log page until the ASCII Table Starts.
- * @asctsz: the number of DWORDS in the ASCII Table
- * @fifo1: FIFO 0 ASCII String
- * @fifo2: FIFO 1 ASCII String
- * @fifo3: FIFO 2 ASCII String
- * @fifo4: FIFO 3 ASCII String
- * @fif05: FIFO 4 ASCII String
- * @fifo6: FIFO 5 ASCII String
- * @fifo7: FIFO 6 ASCII String
- * @fifo8: FIFO 7 ASCII String
- * @fifo9: FIFO 8 ASCII String
- * @fifo10: FIFO 9 ASCII String
- * @fif011: FIFO 10 ASCII String
- * @fif012: FIFO 11 ASCII String
- * @fifo13: FIFO 12 ASCII String
- * @fif014: FIFO 13 ASCII String
- * @fif015: FIFO 14 ASCII String
- * @fif016: FIFO 15 ASCII String
- * @reserved3: reserved
- */
-struct __attribute__((__packed__)) telemetry_str_log_format {
- __u8 log_page_version;
- __u8 reserved1[15];
- __u8 log_page_guid[C9_GUID_LENGTH];
- __le64 sls;
- __u8 reserved2[24];
- __le64 sits;
- __le64 sitsz;
- __le64 ests;
- __le64 estsz;
- __le64 vu_eve_sts;
- __le64 vu_eve_st_sz;
- __le64 ascts;
- __le64 asctsz;
- __u8 fifo1[16];
- __u8 fifo2[16];
- __u8 fifo3[16];
- __u8 fifo4[16];
- __u8 fifo5[16];
- __u8 fifo6[16];
- __u8 fifo7[16];
- __u8 fifo8[16];
- __u8 fifo9[16];
- __u8 fifo10[16];
- __u8 fifo11[16];
- __u8 fifo12[16];
- __u8 fifo13[16];
- __u8 fifo14[16];
- __u8 fifo15[16];
- __u8 fifo16[16];
- __u8 reserved3[48];
-};
-
-/*
- * struct statistics_id_str_table_entry - Statistics Identifier String Table Entry
- * @vs_si: Shall be set the Vendor Unique Statistic Identifier number.
- * @reserved1: Reserved
- * @ascii_id_len: Shall be set the number of ASCII Characters that are valid.
- * @ascii_id_ofst: Shall be set to the offset from DWORD 0/Byte 0 of the Start
- * of the ASCII Table to the first character of the string for
- * this Statistic Identifier string..
- * @reserved2 reserved
- */
-struct __attribute__((__packed__)) statistics_id_str_table_entry {
- __le16 vs_si;
- __u8 reserved1;
- __u8 ascii_id_len;
- __le64 ascii_id_ofst;
- __le32 reserved2;
-};
-
-/*
- * struct event_id_str_table_entry - Event Identifier String Table Entry
- * @deb_eve_class: Shall be set the Debug Class.
- * @ei: Shall be set to the Event Identifier
- * @ascii_id_len: Shall be set the number of ASCII Characters that are valid.
- * @ascii_id_ofst: This is the offset from DWORD 0/ Byte 0 of the start of the
- * ASCII table to the ASCII data for this identifier
- * @reserved2 reserved
- */
-struct __attribute__((__packed__)) event_id_str_table_entry {
- __u8 deb_eve_class;
- __le16 ei;
- __u8 ascii_id_len;
- __le64 ascii_id_ofst;
- __le32 reserved2;
-};
-
-/*
- * struct vu_event_id_str_table_entry - VU Event Identifier String Table Entry
- * @deb_eve_class: Shall be set the Debug Class.
- * @vu_ei: Shall be set to the VU Event Identifier
- * @ascii_id_len: Shall be set the number of ASCII Characters that are valid.
- * @ascii_id_ofst: This is the offset from DWORD 0/ Byte 0 of the start of the
- * ASCII table to the ASCII data for this identifier
- * @reserved reserved
- */
-struct __attribute__((__packed__)) vu_event_id_str_table_entry {
- __u8 deb_eve_class;
- __le16 vu_ei;
- __u8 ascii_id_len;
- __le64 ascii_id_ofst;
- __le32 reserved;
-};
-
/* Function declaration for Telemetry String Log Format (LID:C9h) */
static int ocp_telemetry_str_log_format(int argc, char **argv, struct command *cmd,
struct plugin *plugin);
-static int ocp_print_C9_log_normal(struct telemetry_str_log_format *log_data,__u8 *log_data_buf)
+static int ocp_print_C9_log_normal(struct telemetry_str_log_format *log_data, __u8 *log_data_buf)
{
//calculating the index value for array
__le64 stat_id_index = (log_data->sitsz * 4) / 16;
return 0;
}
-static int ocp_print_C9_log_json(struct telemetry_str_log_format *log_data,__u8 *log_data_buf)
+static int ocp_print_C9_log_json(struct telemetry_str_log_format *log_data, __u8 *log_data_buf)
{
struct json_object *root = json_create_object();
char res_arr[48];
return 0;
}
-static void ocp_print_c9_log_binary(__u8 *log_data_buf,int total_log_page_size)
+static void ocp_print_c9_log_binary(__u8 *log_data_buf, int total_log_page_size)
{
return d_raw((unsigned char *)log_data_buf, total_log_page_size);
}
static int get_c9_log_page(struct nvme_dev *dev, char *format)
{
+
int ret = 0;
- __u8 *header_data;
- struct telemetry_str_log_format *log_data;
+
nvme_print_flags_t fmt;
- __u8 *full_log_buf_data = NULL;
- __le64 stat_id_str_table_ofst = 0;
- __le64 event_str_table_ofst = 0;
- __le64 vu_event_str_table_ofst = 0;
- __le64 ascii_table_ofst = 0;
- __le64 total_log_page_sz = 0;
ret = validate_output_format(format, &fmt);
if (ret < 0) {
return ret;
}
- header_data = (__u8 *)malloc(sizeof(__u8) * C9_TELEMETRY_STR_LOG_LEN);
- if (!header_data) {
- fprintf(stderr, "ERROR : OCP : malloc : %s\n", strerror(errno));
- return -1;
- }
- memset(header_data, 0, sizeof(__u8) * C9_TELEMETRY_STR_LOG_LEN);
-
- ret = nvme_get_log_simple(dev_fd(dev), C9_TELEMETRY_STRING_LOG_ENABLE_OPCODE,
- C9_TELEMETRY_STR_LOG_LEN, header_data);
+ get_c9_log_page_data(dev, 1, 0);
if (!ret) {
- log_data = (struct telemetry_str_log_format *)header_data;
- printf("Statistics Identifier String Table Size = %lld\n",log_data->sitsz);
- printf("Event String Table Size = %lld\n",log_data->estsz);
- printf("VU Event String Table Size = %lld\n",log_data->vu_eve_st_sz);
- printf("ASCII Table Size = %lld\n",log_data->asctsz);
-
- //Calculating the offset for dynamic fields.
-
- stat_id_str_table_ofst = log_data->sits * 4;
- event_str_table_ofst = log_data->ests * 4;
- vu_event_str_table_ofst = log_data->vu_eve_sts * 4;
- ascii_table_ofst = log_data->ascts * 4;
- total_log_page_sz = C9_TELEMETRY_STR_LOG_LEN +
- (log_data->sitsz * 4) + (log_data->estsz * 4) +
- (log_data->vu_eve_st_sz * 4) + (log_data->asctsz * 4);
-
-
-
- printf("stat_id_str_table_ofst = %lld\n",stat_id_str_table_ofst);
- printf("event_str_table_ofst = %lld\n",event_str_table_ofst);
- printf("vu_event_str_table_ofst = %lld\n",vu_event_str_table_ofst);
- printf("ascii_table_ofst = %lld\n",ascii_table_ofst);
- printf("total_log_page_sz = %lld\n",total_log_page_sz);
-
- full_log_buf_data = (__u8 *)malloc(sizeof(__u8) * total_log_page_sz);
- if (!full_log_buf_data) {
- fprintf(stderr, "ERROR : OCP : malloc : %s\n", strerror(errno));
- return -1;
- }
- memset(full_log_buf_data, 0, sizeof(__u8) * total_log_page_sz);
-
- ret = nvme_get_log_simple(dev_fd(dev), C9_TELEMETRY_STRING_LOG_ENABLE_OPCODE,
- total_log_page_sz, full_log_buf_data);
-
- if (!ret) {
- switch (fmt) {
- case NORMAL:
- ocp_print_C9_log_normal(log_data,full_log_buf_data);
- break;
- case JSON:
- ocp_print_C9_log_json(log_data,full_log_buf_data);
- break;
- case BINARY:
- ocp_print_c9_log_binary(full_log_buf_data,total_log_page_sz);
- break;
- default:
- fprintf(stderr, "unhandled output format\n");
- break;
- }
- } else{
- fprintf(stderr, "ERROR : OCP : Unable to read C9 data from buffer\n");
+ switch (fmt) {
+ case NORMAL:
+ ocp_print_C9_log_normal(log_data, pC9_string_buffer);
+ break;
+ case JSON:
+ ocp_print_C9_log_json(log_data, pC9_string_buffer);
+ break;
+ case BINARY:
+ ocp_print_c9_log_binary(pC9_string_buffer, total_log_page_sz);
+ break;
+ default:
+ fprintf(stderr, "unhandled output format\n");
+ break;
}
- } else {
+ } else
fprintf(stderr, "ERROR : OCP : Unable to read C9 data from buffer\n");
- }
-
- free(header_data);
- free(full_log_buf_data);
return ret;
}
__u32 size = size_dw * 4;
char time_str[40];
uint64_t timestamp = 0;
+
memset((void *)time_str, '\0', 40);
if (class_type) {
break;
}
}
+
+struct statistic_entry statistic_identifiers_map[] = {
+ { 0x00, "Error, this entry does not exist." },
+ { 0x01, "Outstanding Admin Commands" },
+ { 0x02, "Host Write Bandwidth"},
+ { 0x03, "GC Write Bandwidth"},
+ { 0x04, "Active Namespaces"},
+ { 0x05, "Internal Write Workload"},
+ { 0x06, "Internal Read Workload"},
+ { 0x07, "Internal Write Queue Depth"},
+ { 0x08, "Internal Read Queue Depth"},
+ { 0x09, "Pending Trim LBA Count"},
+ { 0x0A, "Host Trim LBA Request Count"},
+ { 0x0B, "Current NVMe Power State"},
+ { 0x0C, "Current DSSD Power State"},
+ { 0x0D, "Program Fail Count"},
+ { 0x0E, "Erase Fail Count"},
+ { 0x0F, "Read Disturb Writes"},
+ { 0x10, "Retention Writes"},
+ { 0x11, "Wear Leveling Writes"},
+ { 0x12, "Read Recovery Writes"},
+ { 0x13, "GC Writes"},
+ { 0x14, "SRAM Correctable Count"},
+ { 0x15, "DRAM Correctable Count"},
+ { 0x16, "SRAM Uncorrectable Count"},
+ { 0x17, "DRAM Uncorrectable Count"},
+ { 0x18, "Data Integrity Error Count"},
+ { 0x19, "Read Retry Error Count"},
+ { 0x1A, "PERST Events Count"},
+ { 0x1B, "Max Die Bad Block"},
+ { 0x1C, "Max NAND Channel Bad Block"},
+ { 0x1D, "Minimum NAND Channel Bad Block"}
+};
+
+struct request_data host_log_page_header[] = {
+ { "LogIdentifier", 1 },
+ { "Reserved1", 4 },
+ { "IEEE OUI Identifier", 3 },
+ { "Telemetry Host-Initiated Data Area 1 Last Block", 2 },
+ { "Telemetry Host-Initiated Data Area 2 Last Block", 2 },
+ { "Telemetry Host-Initiated Data Area 3 Last Block", 2 },
+ { "Reserved2", 2 },
+ { "Telemetry Host-Initiated Data Area 4 Last Block", 4 },
+ { "Reserved3", 360 },
+ { "Telemetry Host-Initiated Scope", 1 },
+ { "Telemetry Host Initiated Generation Number", 1 },
+ { "Telemetry Host-Initiated Data Available", 1 },
+ { "Telemetry Controller-Initiated Data Generation Number", 1 }
+};
+
+struct request_data controller_log_page_header[] = {
+ { "LogIdentifier", 1 },
+ { "Reserved1", 4 },
+ { "IEEE OUI Identifier", 3 },
+ { "Telemetry Host-Initiated Data Area 1 Last Block", 2 },
+ { "Telemetry Host-Initiated Data Area 2 Last Block", 2 },
+ { "Telemetry Host-Initiated Data Area 3 Last Block", 2 },
+ { "Reserved2", 2 },
+ { "Telemetry Host-Initiated Data Area 4 Last Block", 4 },
+ { "Reserved3", 361 },
+ { "Telemetry Controller-Initiated Scope", 1 },
+ { "Telemetry Controller-Initiated Data Available", 1 },
+ { "Telemetry Controller-Initiated Data Generation Number", 1 }
+};
+
+struct request_data reason_identifier[] = {
+ { "Error ID", 64 },
+ { "File ID", 8 },
+ { "Line Number", 2 },
+ { "Valid Flags", 1 },
+ { "Reserved", 21 },
+ { "VU Reason Extension", 32 }
+};
+
+struct request_data ocp_header_in_da1[] = {
+ { "Major Version", 2 },
+ { "Minor Version", 2 },
+ { "Reserved1", 4 },
+ { "Timestamp", 8 },
+ { "Log page GUID", 16 },
+ { "Number Telemetry Profiles Supported", 1 },
+ { "Telemetry Profile Selected", 1 },
+ { "Reserved2", 6 },
+ { "Telemetry String Log Size", 8 },
+ { "Reserved3", 8 },
+ { "Firmware Revision", 8 },
+ { "Reserved4", 32 },
+ { "Data Area 1 Statistic Start", 8 },
+ { "Data Area 1 Statistic Size", 8 },
+ { "Data Area 2 Statistic Start", 8 },
+ { "Data Area 2 Statistic Size", 8 },
+ { "Reserved5", 32 },
+ { "Event FIFO 1 Data Area", 1 },
+ { "Event FIFO 2 Data Area", 1 },
+ { "Event FIFO 3 Data Area", 1 },
+ { "Event FIFO 4 Data Area", 1 },
+ { "Event FIFO 5 Data Area", 1 },
+ { "Event FIFO 6 Data Area", 1 },
+ { "Event FIFO 7 Data Area", 1 },
+ { "Event FIFO 8 Data Area", 1 },
+ { "Event FIFO 9 Data Area", 1 },
+ { "Event FIFO 10 Data Area", 1 },
+ { "Event FIFO 11 Data Area", 1 },
+ { "Event FIFO 12 Data Area", 1 },
+ { "Event FIFO 13 Data Area", 1 },
+ { "Event FIFO 14 Data Area", 1 },
+ { "Event FIFO 15 Data Area", 1 },
+ { "Event FIFO 16 Data Area", 1 },
+ { "Event FIFO 1 Start", 8 },
+ { "Event FIFO 1 Size", 8 },
+ { "Event FIFO 2 Start", 8 },
+ { "Event FIFO 2 Size", 8 },
+ { "Event FIFO 3 Start", 8 },
+ { "Event FIFO 3 Size", 8 },
+ { "Event FIFO 4 Start", 8 },
+ { "Event FIFO 4 Size", 8 },
+ { "Event FIFO 5 Start", 8 },
+ { "Event FIFO 5 Size", 8 },
+ { "Event FIFO 6 Start", 8 },
+ { "Event FIFO 6 Size", 8 },
+ { "Event FIFO 7 Start", 8 },
+ { "Event FIFO 7 Size", 8 },
+ { "Event FIFO 8 Start", 8 },
+ { "Event FIFO 8 Size", 8 },
+ { "Event FIFO 9 Start", 8 },
+ { "Event FIFO 9 Size", 8 },
+ { "Event FIFO 10 Start", 8 },
+ { "Event FIFO 10 Size", 8 },
+ { "Event FIFO 11 Start", 8 },
+ { "Event FIFO 11 Size", 8 },
+ { "Event FIFO 12 Start", 8 },
+ { "Event FIFO 12 Size", 8 },
+ { "Event FIFO 13 Start", 8 },
+ { "Event FIFO 13 Size", 8 },
+ { "Event FIFO 14 Start", 8 },
+ { "Event FIFO 14 Size", 8 },
+ { "Event FIFO 15 Start", 8 },
+ { "Event FIFO 15 Size", 8 },
+ { "Event FIFO 16 Start", 8 },
+ { "Event FIFO 16 Size", 8 },
+ { "Reserved6", 80 }
+};
+
+struct request_data smart[] = {
+ { "Critical Warning", 1 },
+ { "Composite Temperature", 2 },
+ { "Available Spare", 1 },
+ { "Available Spare Threshold", 1 },
+ { "Percentage Used", 1 },
+ { "Reserved1", 26 },
+ { "Data Units Read", 16 },
+ { "Data Units Written", 16 },
+ { "Host Read Commands", 16 },
+ { "Host Write Commands", 16 },
+ { "Controller Busy Time", 16 },
+ { "Power Cycles", 16 },
+ { "Power On Hours", 16 },
+ { "Unsafe Shutdowns", 16 },
+ { "Media and Data Integrity Errors", 16 },
+ { "Number of Error Information Log Entries", 16 },
+ { "Warning Composite Temperature Time", 4 },
+ { "Critical Composite Temperature Time", 4 },
+ { "Temperature Sensor 1", 2 },
+ { "Temperature Sensor 2", 2 },
+ { "Temperature Sensor 3", 2 },
+ { "Temperature Sensor 4", 2 },
+ { "Temperature Sensor 5", 2 },
+ { "Temperature Sensor 6", 2 },
+ { "Temperature Sensor 7", 2 },
+ { "Temperature Sensor 8", 2 },
+ { "Thermal Management Temperature 1 Transition Count", 4 },
+ { "Thermal Management Temperature 2 Transition Count", 4 },
+ { "Total Time for Thermal Management Temperature 1", 4 },
+ { "Total Time for Thermal Management Temperature 2", 4 },
+ { "Reserved2", 280 }
+};
+
+struct request_data smart_extended[] = {
+ { "Physical Media Units Written", 16 },
+ { "Physical Media Units Read", 16 },
+ { "Bad User NAND Blocks Raw Count", 6 },
+ { "Bad User NAND Blocks Normalized Value", 2 },
+ { "Bad System NAND Blocks Raw Count", 6 },
+ { "Bad System NAND Blocks Normalized Value", 2 },
+ { "XOR Recovery Count", 8 },
+ { "Uncorrectable Read Error Count", 8 },
+ { "Soft ECC Error Count", 8 },
+ { "End to End Correction Counts Detected Errors", 4 },
+ { "End to End Correction Counts Corrected Errors", 4 },
+ { "System Data Percent Used", 1 },
+ { "Refresh Counts", 7 },
+ { "Maximum User Data Erase Count", 4 },
+ { "Minimum User Data Erase Count", 4 },
+ { "Number of thermal throttling events", 1 },
+ { "Current Throttling Status", 1 },
+ { "Errata Version Field", 1 },
+ { "Point Version Field", 2 },
+ { "Minor Version Field", 2 },
+ { "Major Version Field", 1 },
+ { "PCIe Correctable Error Count", 8 },
+ { "Incomplete Shutdowns", 4 },
+ { "Reserved1", 4 },
+ { "Percent Free Blocks", 1 },
+ { "Reserved2", 7 },
+ { "Capacitor Health", 2 },
+ { "NVMe Base Errata Version", 1 },
+ { "NVMe Command Set Errata Version", 1 },
+ { "Reserved3", 4 },
+ { "Unaligned IO", 8 },
+ { "Security Version Number", 8 },
+ { "Total NUSE", 8 },
+ { "PLP Start Count", 16 },
+ { "Endurance Estimate", 16 },
+ { "PCIe Link Retraining Count", 8 },
+ { "Power State Change Count", 8 },
+ { "Lowest Permitted Firmware Revision", 8 },
+ { "Reserved4", 278 },
+ { "Log Page Version", 2 },
+ { "Log page GUID", 16 }
+};
+
+void json_add_formatted_u32_str(struct json_object *pobject, const char *msg, unsigned int pdata)
+{
+ char data_str[70] = { 0 };
+
+ sprintf(data_str, "0x%x", pdata);
+ json_object_add_value_string(pobject, msg, data_str);
+}
+
+void json_add_formatted_var_size_str(struct json_object *pobject, const char *msg, __u8 *pdata,
+ unsigned int data_size)
+{
+ char description_str[256] = "";
+ char temp_buffer[3] = { 0 };
+
+ for (size_t i = 0; i < data_size; ++i) {
+ sprintf(temp_buffer, "%02X", pdata[i]);
+ strcat(description_str, temp_buffer);
+ }
+
+ json_object_add_value_string(pobject, msg, description_str);
+}
+
+int get_telemetry_das_offset_and_size(
+ struct nvme_ocp_telemetry_common_header *ptelemetry_common_header,
+ struct nvme_ocp_telemetry_offsets *ptelemetry_das_offset)
+{
+ if (NULL == ptelemetry_common_header || NULL == ptelemetry_das_offset) {
+ nvme_show_error("Invalid input arguments.");
+ return -1;
+ }
+
+ if (ptelemetry_common_header->log_id == NVME_LOG_LID_TELEMETRY_HOST)
+ ptelemetry_das_offset->header_size =
+ sizeof(struct nvme_ocp_telemetry_host_initiated_header);
+ else if (ptelemetry_common_header->log_id == NVME_LOG_LID_TELEMETRY_CTRL)
+ ptelemetry_das_offset->header_size =
+ sizeof(struct nvme_ocp_telemetry_controller_initiated_header);
+ else
+ return -1;
+
+ ptelemetry_das_offset->da1_start_offset = ptelemetry_das_offset->header_size;
+ ptelemetry_das_offset->da1_size = ptelemetry_common_header->da1_last_block *
+ OCP_TELEMETRY_DATA_BLOCK_SIZE;
+
+ ptelemetry_das_offset->da2_start_offset = ptelemetry_das_offset->da1_start_offset +
+ ptelemetry_das_offset->da1_size;
+ ptelemetry_das_offset->da2_size =
+ (ptelemetry_common_header->da2_last_block -
+ ptelemetry_common_header->da1_last_block) * OCP_TELEMETRY_DATA_BLOCK_SIZE;
+
+ ptelemetry_das_offset->da3_start_offset = ptelemetry_das_offset->da2_start_offset +
+ ptelemetry_das_offset->da2_size;
+ ptelemetry_das_offset->da3_size =
+ (ptelemetry_common_header->da3_last_block -
+ ptelemetry_common_header->da2_last_block) * OCP_TELEMETRY_DATA_BLOCK_SIZE;
+
+ ptelemetry_das_offset->da4_start_offset = ptelemetry_das_offset->da3_start_offset +
+ ptelemetry_das_offset->da3_size;
+ ptelemetry_das_offset->da4_size =
+ (ptelemetry_common_header->da4_last_block -
+ ptelemetry_common_header->da3_last_block) * OCP_TELEMETRY_DATA_BLOCK_SIZE;
+
+ return 0;
+}
+
+int get_static_id_ascii_string(int identifier, char *description)
+{
+ if (pstring_buffer == NULL)
+ return -1;
+
+ struct nvme_ocp_telemetry_string_header *pocp_ts_header =
+ (struct nvme_ocp_telemetry_string_header *)pstring_buffer;
+
+ //Calculating the sizes of the tables. Note: Data is present in the form of DWORDS,
+ //So multiplying with sizeof(DWORD)
+ unsigned long long sits_table_size = (pocp_ts_header->sitsz) * SIZE_OF_DWORD;
+
+ //Calculating number of entries present in all 3 tables
+ int sits_entries = (int)sits_table_size /
+ sizeof(struct nvme_ocp_statistics_identifier_string_table);
+
+ for (int sits_entry = 0; sits_entry < sits_entries; sits_entry++) {
+ struct nvme_ocp_statistics_identifier_string_table
+ *peach_statistic_entry =
+ (struct nvme_ocp_statistics_identifier_string_table *)
+ (pstring_buffer + (pocp_ts_header->sits * SIZE_OF_DWORD) +
+ (sits_entry *
+ sizeof(struct nvme_ocp_statistics_identifier_string_table)));
+
+ if (identifier == (int)peach_statistic_entry->vs_statistic_identifier) {
+ char *pdescription = (char *)(pstring_buffer +
+ (pocp_ts_header->ascts * SIZE_OF_DWORD) +
+ (peach_statistic_entry->ascii_id_offset *
+ SIZE_OF_DWORD));
+
+ memcpy(description, pdescription,
+ peach_statistic_entry->ascii_id_length + 1);
+
+ // If ASCII string isn't found, see in our internal Map
+ // for 2.5 Spec defined strings (id < 0x1D).
+ if ((description == NULL) && (identifier < 0x1D))
+ memcpy(description,
+ statistic_identifiers_map[identifier].description,
+ peach_statistic_entry->ascii_id_length + 1);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+int get_event_id_ascii_string(int identifier, int debug_event_class, char *description)
+{
+ if (pstring_buffer == NULL)
+ return -1;
+
+ struct nvme_ocp_telemetry_string_header *pocp_ts_header =
+ (struct nvme_ocp_telemetry_string_header *)pstring_buffer;
+
+ //Calculating the sizes of the tables. Note: Data is present in the form of DWORDS,
+ //So multiplying with sizeof(DWORD)
+ unsigned long long ests_table_size = (pocp_ts_header->estsz) * SIZE_OF_DWORD;
+
+ //Calculating number of entries present in all 3 tables
+ int ests_entries = (int)ests_table_size / sizeof(struct nvme_ocp_event_string_table);
+
+ for (int ests_entry = 0; ests_entry < ests_entries; ests_entry++) {
+ struct nvme_ocp_event_string_table *peach_event_entry =
+ (struct nvme_ocp_event_string_table *)
+ (pstring_buffer + (pocp_ts_header->ests * SIZE_OF_DWORD) +
+ (ests_entry * sizeof(struct nvme_ocp_event_string_table)));
+
+ if (identifier == (int)peach_event_entry->event_identifier &&
+ debug_event_class == (int)peach_event_entry->debug_event_class) {
+ char *pdescription = (char *)(pstring_buffer +
+ (pocp_ts_header->ascts * SIZE_OF_DWORD) +
+ (peach_event_entry->ascii_id_offset * SIZE_OF_DWORD));
+
+ memcpy(description, pdescription,
+ peach_event_entry->ascii_id_length + 1);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+int get_vu_event_id_ascii_string(int identifier, int debug_event_class, char *description)
+{
+ if (pstring_buffer == NULL)
+ return -1;
+
+ struct nvme_ocp_telemetry_string_header *pocp_ts_header =
+ (struct nvme_ocp_telemetry_string_header *)pstring_buffer;
+
+ //Calculating the sizes of the tables. Note: Data is present in the form of DWORDS,
+ //So multiplying with sizeof(DWORD)
+ unsigned long long vuests_table_size = (pocp_ts_header->vu_estsz) * SIZE_OF_DWORD;
+
+ //Calculating number of entries present in all 3 tables
+ int vu_ests_entries = (int)vuests_table_size /
+ sizeof(struct nvme_ocp_vu_event_string_table);
+
+ for (int vu_ests_entry = 0; vu_ests_entry < vu_ests_entries; vu_ests_entry++) {
+ struct nvme_ocp_vu_event_string_table *peach_vu_event_entry =
+ (struct nvme_ocp_vu_event_string_table *)
+ (pstring_buffer + (pocp_ts_header->vu_ests * SIZE_OF_DWORD) +
+ (vu_ests_entry * sizeof(struct nvme_ocp_vu_event_string_table)));
+
+ if (identifier == (int)peach_vu_event_entry->vu_event_identifier &&
+ debug_event_class ==
+ (int)peach_vu_event_entry->debug_event_class) {
+ char *pdescription = (char *)(pstring_buffer +
+ (pocp_ts_header->ascts * SIZE_OF_DWORD) +
+ (peach_vu_event_entry->ascii_id_offset * SIZE_OF_DWORD));
+
+ memcpy(description, pdescription,
+ peach_vu_event_entry->ascii_id_length + 1);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+int parse_ocp_telemetry_string_log(int event_fifo_num, int identifier, int debug_event_class,
+ enum ocp_telemetry_string_tables string_table, char *description)
+{
+ if (pstring_buffer == NULL)
+ return -1;
+
+ if (event_fifo_num != 0) {
+ struct nvme_ocp_telemetry_string_header *pocp_ts_header =
+ (struct nvme_ocp_telemetry_string_header *)pstring_buffer;
+
+ if (*pocp_ts_header->fifo_ascii_string[event_fifo_num-1] != '\0')
+ memcpy(description, pocp_ts_header->fifo_ascii_string[event_fifo_num-1],
+ 16);
+ else
+ description = "";
+
+ return 0;
+ }
+
+ if (string_table == STATISTICS_IDENTIFIER_STRING)
+ get_static_id_ascii_string(identifier, description);
+ else if (string_table == EVENT_STRING)
+ get_event_id_ascii_string(identifier, debug_event_class, description);
+ else if (string_table == VU_EVENT_STRING)
+ get_vu_event_id_ascii_string(identifier, debug_event_class, description);
+
+ return 0;
+}
+
+void parse_time_stamp_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor,
+ struct json_object *pevent_descriptor_obj, __u8 *pevent_specific_data,
+ struct json_object *pevent_fifos_object, FILE *fp)
+{
+ struct nvme_ocp_time_stamp_dbg_evt_class_format *ptime_stamp_event =
+ (struct nvme_ocp_time_stamp_dbg_evt_class_format *) pevent_specific_data;
+
+ int vu_event_id = (int)ptime_stamp_event->vu_event_identifier;
+
+ unsigned int data_size = ((pevent_descriptor->event_data_size * SIZE_OF_DWORD)-
+ sizeof(struct nvme_ocp_time_stamp_dbg_evt_class_format));
+
+ __u8 *pdata = (__u8 *)ptime_stamp_event +
+ sizeof(struct nvme_ocp_time_stamp_dbg_evt_class_format);
+
+ char description_str[256] = "";
+
+ parse_ocp_telemetry_string_log(0, ptime_stamp_event->vu_event_identifier,
+ pevent_descriptor->debug_event_class_type,
+ VU_EVENT_STRING, description_str);
+
+ if (pevent_fifos_object != NULL) {
+ json_add_formatted_var_size_str(pevent_descriptor_obj, STR_CLASS_SPECIFIC_DATA,
+ ptime_stamp_event->time_stamp, DATA_SIZE_8);
+ json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING,
+ vu_event_id);
+ json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING,
+ description_str);
+ json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA, pdata,
+ data_size);
+ } else {
+ if (fp) {
+ print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA,
+ ptime_stamp_event->time_stamp, DATA_SIZE_8, fp);
+ fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
+ fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING, description_str);
+ print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
+ } else {
+ print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA,
+ ptime_stamp_event->time_stamp, DATA_SIZE_8, fp);
+ printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
+ printf("%s: %s\n", STR_VU_EVENT_STRING, description_str);
+ print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
+ }
+ }
+}
+
+void parse_pcie_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor,
+ struct json_object *pevent_descriptor_obj, __u8 *pevent_specific_data,
+ struct json_object *pevent_fifos_object, FILE *fp)
+{
+ struct nvme_ocp_pcie_dbg_evt_class_format *ppcie_event =
+ (struct nvme_ocp_pcie_dbg_evt_class_format *) pevent_specific_data;
+ int vu_event_id = (int) ppcie_event->vu_event_identifier;
+ unsigned int data_size = ((pevent_descriptor->event_data_size * SIZE_OF_DWORD) -
+ sizeof(struct nvme_ocp_pcie_dbg_evt_class_format));
+ __u8 *pdata = (__u8 *) ppcie_event + sizeof(struct nvme_ocp_pcie_dbg_evt_class_format);
+ char description_str[256] = "";
+
+ parse_ocp_telemetry_string_log(0, ppcie_event->vu_event_identifier,
+ pevent_descriptor->debug_event_class_type, VU_EVENT_STRING, description_str);
+
+ if (pevent_fifos_object != NULL) {
+ json_add_formatted_var_size_str(pevent_descriptor_obj, STR_CLASS_SPECIFIC_DATA,
+ ppcie_event->pCIeDebugEventData, DATA_SIZE_4);
+ json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING,
+ vu_event_id);
+ json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING,
+ description_str);
+ json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA, pdata,
+ data_size);
+ } else {
+ if (fp) {
+ print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA,
+ ppcie_event->pCIeDebugEventData, DATA_SIZE_4, fp);
+ fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
+ fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING, description_str);
+ print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
+ } else {
+ print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA,
+ ppcie_event->pCIeDebugEventData, DATA_SIZE_4, fp);
+ printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
+ printf("%s: %s\n", STR_VU_EVENT_STRING, description_str);
+ print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
+ }
+ }
+}
+
+void parse_nvme_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor,
+ struct json_object *pevent_descriptor_obj, __u8 *pevent_specific_data,
+ struct json_object *pevent_fifos_object, FILE *fp)
+{
+ struct nvme_ocp_nvme_dbg_evt_class_format *pnvme_event =
+ (struct nvme_ocp_nvme_dbg_evt_class_format *) pevent_specific_data;
+ int vu_event_id = (int) pnvme_event->vu_event_identifier;
+ unsigned int data_size = ((pevent_descriptor->event_data_size *
+ SIZE_OF_DWORD) - sizeof(struct nvme_ocp_nvme_dbg_evt_class_format));
+ __u8 *pdata = (__u8 *) pnvme_event + sizeof(struct nvme_ocp_nvme_dbg_evt_class_format);
+ char description_str[256] = "";
+
+ parse_ocp_telemetry_string_log(0, pnvme_event->vu_event_identifier,
+ pevent_descriptor->debug_event_class_type, VU_EVENT_STRING,
+ description_str);
+
+ if (pevent_fifos_object != NULL) {
+ json_add_formatted_var_size_str(pevent_descriptor_obj, STR_CLASS_SPECIFIC_DATA,
+ pnvme_event->nvmeDebugEventData, DATA_SIZE_8);
+ json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING,
+ vu_event_id);
+ json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING,
+ description_str);
+ json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA, pdata,
+ data_size);
+ } else {
+ if (fp) {
+ print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA,
+ pnvme_event->nvmeDebugEventData, DATA_SIZE_8, fp);
+ fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
+ fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING, description_str);
+ print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
+ } else {
+ print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA,
+ pnvme_event->nvmeDebugEventData, DATA_SIZE_8, fp);
+ printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
+ printf("%s: %s\n", STR_VU_EVENT_STRING, description_str);
+ print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
+ }
+ }
+}
+
+void parse_common_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor,
+ struct json_object *pevent_descriptor_obj, __u8 *pevent_specific_data,
+ struct json_object *pevent_fifos_object, FILE *fp)
+{
+ struct nvme_ocp_common_dbg_evt_class_format *pcommon_debug_event =
+ (struct nvme_ocp_common_dbg_evt_class_format *) pevent_specific_data;
+ int vu_event_id = (int) pcommon_debug_event->vu_event_identifier;
+ unsigned int data_size = ((pevent_descriptor->event_data_size *
+ SIZE_OF_DWORD) - sizeof(struct nvme_ocp_common_dbg_evt_class_format));
+ __u8 *pdata = (__u8 *) pcommon_debug_event +
+ sizeof(struct nvme_ocp_common_dbg_evt_class_format);
+ char description_str[256] = "";
+
+ parse_ocp_telemetry_string_log(0, pcommon_debug_event->vu_event_identifier,
+ pevent_descriptor->debug_event_class_type, VU_EVENT_STRING, description_str);
+
+ if (pevent_fifos_object != NULL) {
+ json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING,
+ vu_event_id);
+ json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING,
+ description_str);
+ json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA, pdata,
+ data_size);
+ } else {
+ if (fp) {
+ fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
+ fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING, description_str);
+ print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
+ } else {
+ printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
+ printf("%s: %s\n", STR_VU_EVENT_STRING, description_str);
+ print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
+ }
+ }
+}
+
+void parse_media_wear_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor,
+ struct json_object *pevent_descriptor_obj, __u8 *pevent_specific_data,
+ struct json_object *pevent_fifos_object, FILE *fp)
+{
+ struct nvme_ocp_media_wear_dbg_evt_class_format *pmedia_wear_event =
+ (struct nvme_ocp_media_wear_dbg_evt_class_format *) pevent_specific_data;
+ int vu_event_id = (int) pmedia_wear_event->vu_event_identifier;
+ unsigned int data_size = ((pevent_descriptor->event_data_size * SIZE_OF_DWORD) -
+ sizeof(struct nvme_ocp_media_wear_dbg_evt_class_format));
+ __u8 *pdata = (__u8 *) pmedia_wear_event +
+ sizeof(struct nvme_ocp_media_wear_dbg_evt_class_format);
+ char description_str[256] = "";
+
+ parse_ocp_telemetry_string_log(0, pmedia_wear_event->vu_event_identifier,
+ pevent_descriptor->debug_event_class_type, VU_EVENT_STRING,
+ description_str);
+
+ if (pevent_fifos_object != NULL) {
+ json_add_formatted_var_size_str(pevent_descriptor_obj, STR_CLASS_SPECIFIC_DATA,
+ pmedia_wear_event->currentMediaWear, DATA_SIZE_12);
+ json_add_formatted_u32_str(pevent_descriptor_obj, STR_VU_EVENT_ID_STRING,
+ vu_event_id);
+ json_object_add_value_string(pevent_descriptor_obj, STR_VU_EVENT_STRING,
+ description_str);
+ json_add_formatted_var_size_str(pevent_descriptor_obj, STR_VU_DATA, pdata,
+ data_size);
+ } else {
+ if (fp) {
+ print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA,
+ pmedia_wear_event->currentMediaWear, DATA_SIZE_12, fp);
+ fprintf(fp, "%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
+ fprintf(fp, "%s: %s\n", STR_VU_EVENT_STRING, description_str);
+ print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
+ } else {
+ print_formatted_var_size_str(STR_CLASS_SPECIFIC_DATA,
+ pmedia_wear_event->currentMediaWear, DATA_SIZE_12, NULL);
+ printf("%s: 0x%x\n", STR_VU_EVENT_ID_STRING, vu_event_id);
+ printf("%s: %s\n", STR_VU_EVENT_STRING, description_str);
+ print_formatted_var_size_str(STR_VU_DATA, pdata, data_size, fp);
+ }
+ }
+}
+
+int parse_event_fifo(unsigned int fifo_num, unsigned char *pfifo_start,
+ struct json_object *pevent_fifos_object, unsigned char *pstring_buffer,
+ struct nvme_ocp_telemetry_offsets *poffsets, __u64 fifo_size, FILE *fp)
+{
+ if (NULL == pfifo_start || NULL == poffsets) {
+ nvme_show_error("Input buffer was NULL");
+ return -1;
+ }
+
+ int status = 0;
+ unsigned int event_fifo_number = fifo_num + 1;
+ char *description = (char *)malloc((40 + 1) * sizeof(char));
+
+ memset(description, 0, sizeof(40));
+
+ status =
+ parse_ocp_telemetry_string_log(event_fifo_number, 0, 0, EVENT_STRING, description);
+
+ if (status != 0) {
+ nvme_show_error("Failed to get C9 String. status: %d\n", status);
+ return -1;
+ }
+
+ char event_fifo_name[100] = {0};
+
+ snprintf(event_fifo_name, sizeof(event_fifo_name), "%s%d%s%s", "EVENT FIFO ",
+ event_fifo_number, " - ", description);
+
+ struct json_object *pevent_fifo_array = NULL;
+
+ if (pevent_fifos_object != NULL)
+ pevent_fifo_array = json_create_array();
+ else {
+ char buffer[1024] = {0};
+
+ sprintf(buffer, "%s%s\n%s", STR_LINE, event_fifo_name, STR_LINE);
+ if (fp)
+ fprintf(fp, "%s", buffer);
+ else
+ printf("%s", buffer);
+ }
+
+ int offset_to_move = 0;
+ unsigned int event_des_size = sizeof(struct nvme_ocp_telemetry_event_descriptor);
+
+ while ((fifo_size > 0) && (offset_to_move < fifo_size)) {
+ struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor =
+ (struct nvme_ocp_telemetry_event_descriptor *)
+ (pfifo_start + offset_to_move);
+
+ if (pevent_descriptor != NULL && pevent_descriptor->event_data_size >= 0) {
+ //Data is present in the form of DWORDS, So multiplying with sizeof(DWORD)
+ unsigned int data_size = pevent_descriptor->event_data_size *
+ SIZE_OF_DWORD;
+
+ __u8 *pevent_specific_data = (__u8 *)pevent_descriptor + event_des_size;
+
+ char description_str[256] = "";
+
+ parse_ocp_telemetry_string_log(0, pevent_descriptor->event_id,
+ pevent_descriptor->debug_event_class_type, EVENT_STRING,
+ description_str);
+
+ struct json_object *pevent_descriptor_obj =
+ ((pevent_fifos_object != NULL)?json_create_object():NULL);
+
+ if (pevent_descriptor_obj != NULL) {
+ json_add_formatted_u32_str(pevent_descriptor_obj,
+ STR_DBG_EVENT_CLASS_TYPE,
+ pevent_descriptor->debug_event_class_type);
+ json_add_formatted_u32_str(pevent_descriptor_obj,
+ STR_EVENT_IDENTIFIER, pevent_descriptor->event_id);
+ json_object_add_value_string(pevent_descriptor_obj,
+ STR_EVENT_STRING, description_str);
+ json_add_formatted_u32_str(pevent_descriptor_obj,
+ STR_EVENT_DATA_SIZE, pevent_descriptor->event_data_size);
+
+ if (pevent_descriptor->debug_event_class_type >= 0x80)
+ json_add_formatted_var_size_str(pevent_descriptor_obj,
+ STR_VU_DATA, pevent_specific_data, data_size);
+ } else {
+ if (fp) {
+ fprintf(fp, "%s: 0x%x\n", STR_DBG_EVENT_CLASS_TYPE,
+ pevent_descriptor->debug_event_class_type);
+ fprintf(fp, "%s: 0x%x\n", STR_EVENT_IDENTIFIER,
+ pevent_descriptor->event_id);
+ fprintf(fp, "%s: %s\n", STR_EVENT_STRING, description_str);
+ fprintf(fp, "%s: 0x%x\n", STR_EVENT_DATA_SIZE,
+ pevent_descriptor->event_data_size);
+ } else {
+ printf("%s: 0x%x\n", STR_DBG_EVENT_CLASS_TYPE,
+ pevent_descriptor->debug_event_class_type);
+ printf("%s: 0x%x\n", STR_EVENT_IDENTIFIER,
+ pevent_descriptor->event_id);
+ printf("%s: %s\n", STR_EVENT_STRING, description_str);
+ printf("%s: 0x%x\n", STR_EVENT_DATA_SIZE,
+ pevent_descriptor->event_data_size);
+ }
+
+ if (pevent_descriptor->debug_event_class_type >= 0x80)
+ print_formatted_var_size_str(STR_VU_DATA,
+ pevent_specific_data, data_size, fp);
+ }
+
+ switch (pevent_descriptor->debug_event_class_type) {
+ case TIME_STAMP_CLASS_TYPE:
+ parse_time_stamp_event(pevent_descriptor, pevent_descriptor_obj,
+ pevent_specific_data, pevent_fifos_object, fp);
+ break;
+ case PCIE_CLASS_TYPE:
+ parse_pcie_event(pevent_descriptor, pevent_descriptor_obj,
+ pevent_specific_data, pevent_fifos_object, fp);
+ break;
+ case NVME_CLASS_TYPE:
+ parse_nvme_event(pevent_descriptor, pevent_descriptor_obj,
+ pevent_specific_data, pevent_fifos_object, fp);
+ break;
+ case RESET_CLASS_TYPE:
+ case BOOT_SEQUENCE_CLASS_TYPE:
+ case FIRMWARE_ASSERT_CLASS_TYPE:
+ case TEMPERATURE_CLASS_TYPE:
+ case MEDIA_CLASS_TYPE:
+ parse_common_event(pevent_descriptor, pevent_descriptor_obj,
+ pevent_specific_data, pevent_fifos_object, fp);
+ break;
+ case MEDIA_WEAR_CLASS_TYPE:
+ parse_media_wear_event(pevent_descriptor, pevent_descriptor_obj,
+ pevent_specific_data, pevent_fifos_object, fp);
+ break;
+ case STATISTIC_SNAPSHOT_CLASS_TYPE: {
+ struct nvme_ocp_statistic_snapshot_evt_class_format
+ *pStaticSnapshotEvent =
+ (struct nvme_ocp_statistic_snapshot_evt_class_format *)
+ pevent_specific_data;
+ struct nvme_ocp_telemetry_statistic_descriptor *pstatistic_entry =
+ (struct nvme_ocp_telemetry_statistic_descriptor *)
+ (&pStaticSnapshotEvent->statisticDescriptorData);
+
+ parse_statistic(pstatistic_entry, pevent_descriptor_obj, fp);
+ break;
+ }
+ case RESERVED_CLASS_TYPE:
+ default:
+ break;
+ }
+
+ if (pevent_descriptor_obj != NULL && pevent_fifo_array != NULL)
+ json_array_add_value_object(pevent_fifo_array, pevent_descriptor_obj);
+ else {
+ if (fp)
+ fprintf(fp, STR_LINE2);
+ else
+ printf(STR_LINE2);
+ }
+ } else
+ break;
+
+ offset_to_move += (pevent_descriptor->event_data_size * SIZE_OF_DWORD + event_des_size);
+ }
+
+ if (pevent_fifos_object != NULL && pevent_fifo_array != NULL)
+ json_object_add_value_array(pevent_fifos_object, event_fifo_name,
+ pevent_fifo_array);
+
+ free(description);
+ return 0;
+}
+
+int parse_event_fifos(struct json_object *root, struct nvme_ocp_telemetry_offsets *poffsets,
+ FILE *fp)
+{
+ if (poffsets == NULL) {
+ nvme_show_error("Input buffer was NULL");
+ return -1;
+ }
+
+ struct json_object *pevent_fifos_object = NULL;
+
+ if (root != NULL)
+ pevent_fifos_object = json_create_object();
+
+ __u8 *pda1_header_offset = ptelemetry_buffer + poffsets->da1_start_offset;//512
+ __u8 *pda2_offset = ptelemetry_buffer + poffsets->da2_start_offset;
+ struct nvme_ocp_header_in_da1 *pda1_header = (struct nvme_ocp_header_in_da1 *)
+ pda1_header_offset;
+ struct nvme_ocp_event_fifo_data event_fifo[MAX_NUM_FIFOS];
+
+ for (int fifo_num = 0; fifo_num < MAX_NUM_FIFOS; fifo_num++) {
+ event_fifo[fifo_num].event_fifo_num = fifo_num;
+ event_fifo[fifo_num].event_fifo_da = pda1_header->event_fifo_da[fifo_num];
+ event_fifo[fifo_num].event_fifo_start =
+ pda1_header->fifo_offsets[fifo_num].event_fifo_start;
+ event_fifo[fifo_num].event_fifo_size =
+ pda1_header->fifo_offsets[fifo_num].event_fifo_size;
+ }
+
+ //Parse all the FIFOs DA wise
+ for (int fifo_no = 0; fifo_no < MAX_NUM_FIFOS; fifo_no++) {
+ if (event_fifo[fifo_no].event_fifo_da == poffsets->data_area) {
+ __u64 fifo_offset =
+ (event_fifo[fifo_no].event_fifo_start * SIZE_OF_DWORD);
+ __u64 fifo_size =
+ (event_fifo[fifo_no].event_fifo_size * SIZE_OF_DWORD);
+ __u8 *pfifo_start = NULL;
+
+ if (event_fifo[fifo_no].event_fifo_da == 1)
+ pfifo_start = pda1_header_offset + fifo_offset;
+ else if (event_fifo[fifo_no].event_fifo_da == 2)
+ pfifo_start = pda2_offset + fifo_offset;
+ else {
+ nvme_show_error("Unsupported Data Area:[%d]", poffsets->data_area);
+ return -1;
+ }
+
+ int status = parse_event_fifo(fifo_no, pfifo_start, pevent_fifos_object,
+ pstring_buffer, poffsets, fifo_size, fp);
+
+ if (status != 0) {
+ nvme_show_error("Failed to parse Event FIFO. status:%d\n", status);
+ return -1;
+ }
+ }
+ }
+
+ if (pevent_fifos_object != NULL && root != NULL) {
+ const char *data_area = (poffsets->data_area == 1 ? STR_DA_1_EVENT_FIFO_INFO :
+ STR_DA_2_EVENT_FIFO_INFO);
+
+ json_object_add_value_array(root, data_area, pevent_fifos_object);
+ }
+
+ return 0;
+}
+
+int parse_statistic(struct nvme_ocp_telemetry_statistic_descriptor *pstatistic_entry,
+ struct json_object *pstats_array, FILE *fp)
+{
+ if (pstatistic_entry == NULL) {
+ nvme_show_error("Input buffer was NULL");
+ return -1;
+ }
+
+ unsigned int data_size = pstatistic_entry->statistic_data_size * SIZE_OF_DWORD;
+ __u8 *pdata = (__u8 *)pstatistic_entry +
+ sizeof(struct nvme_ocp_telemetry_statistic_descriptor);
+ char description_str[256] = "";
+
+ parse_ocp_telemetry_string_log(0, pstatistic_entry->statistic_id, 0,
+ STATISTICS_IDENTIFIER_STRING, description_str);
+
+ if (pstats_array != NULL) {
+ struct json_object *pstatistics_object = json_create_object();
+
+ json_add_formatted_u32_str(pstatistics_object, STR_STATISTICS_IDENTIFIER,
+ pstatistic_entry->statistic_id);
+ json_object_add_value_string(pstatistics_object, STR_STATISTICS_IDENTIFIER_STR,
+ description_str);
+ json_add_formatted_u32_str(pstatistics_object,
+ STR_STATISTICS_INFO_BEHAVIOUR_TYPE,
+ pstatistic_entry->statistic_info_behaviour_type);
+ json_add_formatted_u32_str(pstatistics_object, STR_STATISTICS_INFO_RESERVED,
+ pstatistic_entry->statistic_info_reserved);
+ json_add_formatted_u32_str(pstatistics_object, STR_NAMESPACE_IDENTIFIER,
+ pstatistic_entry->ns_info_nsid);
+ json_add_formatted_u32_str(pstatistics_object, STR_NAMESPACE_INFO_VALID,
+ pstatistic_entry->ns_info_ns_info_valid);
+ json_add_formatted_u32_str(pstatistics_object, STR_STATISTICS_DATA_SIZE,
+ pstatistic_entry->statistic_data_size);
+ json_add_formatted_u32_str(pstatistics_object, STR_RESERVED,
+ pstatistic_entry->reserved);
+ json_add_formatted_var_size_str(pstatistics_object, STR_STATISTICS_SPECIFIC_DATA,
+ pdata, data_size);
+
+ if (pstatistics_object != NULL)
+ json_array_add_value_object(pstats_array, pstatistics_object);
+ } else {
+ if (fp) {
+ fprintf(fp, "%s: 0x%x\n", STR_STATISTICS_IDENTIFIER,
+ pstatistic_entry->statistic_id);
+ fprintf(fp, "%s: %s\n", STR_STATISTICS_IDENTIFIER_STR, description_str);
+ fprintf(fp, "%s: 0x%x\n", STR_STATISTICS_INFO_BEHAVIOUR_TYPE,
+ pstatistic_entry->statistic_info_behaviour_type);
+ fprintf(fp, "%s: 0x%x\n", STR_STATISTICS_INFO_RESERVED,
+ pstatistic_entry->statistic_info_reserved);
+ fprintf(fp, "%s: 0x%x\n", STR_NAMESPACE_IDENTIFIER,
+ pstatistic_entry->ns_info_nsid);
+ fprintf(fp, "%s: 0x%x\n", STR_NAMESPACE_INFO_VALID,
+ pstatistic_entry->ns_info_ns_info_valid);
+ fprintf(fp, "%s: 0x%x\n", STR_STATISTICS_DATA_SIZE,
+ pstatistic_entry->statistic_data_size);
+ fprintf(fp, "%s: 0x%x\n", STR_RESERVED, pstatistic_entry->reserved);
+ print_formatted_var_size_str(STR_STATISTICS_SPECIFIC_DATA, pdata,
+ data_size, fp);
+ fprintf(fp, STR_LINE2);
+ } else {
+ printf("%s: 0x%x\n", STR_STATISTICS_IDENTIFIER,
+ pstatistic_entry->statistic_id);
+ printf("%s: %s\n", STR_STATISTICS_IDENTIFIER_STR, description_str);
+ printf("%s: 0x%x\n", STR_STATISTICS_INFO_BEHAVIOUR_TYPE,
+ pstatistic_entry->statistic_info_behaviour_type);
+ printf("%s: 0x%x\n", STR_STATISTICS_INFO_RESERVED,
+ pstatistic_entry->statistic_info_reserved);
+ printf("%s: 0x%x\n", STR_NAMESPACE_IDENTIFIER,
+ pstatistic_entry->ns_info_nsid);
+ printf("%s: 0x%x\n", STR_NAMESPACE_INFO_VALID,
+ pstatistic_entry->ns_info_ns_info_valid);
+ printf("%s: 0x%x\n", STR_STATISTICS_DATA_SIZE,
+ pstatistic_entry->statistic_data_size);
+ printf("%s: 0x%x\n", STR_RESERVED, pstatistic_entry->reserved);
+ print_formatted_var_size_str(STR_STATISTICS_SPECIFIC_DATA, pdata,
+ data_size, fp);
+ printf(STR_LINE2);
+ }
+ }
+
+ return 0;
+}
+
+int parse_statistics(struct json_object *root, struct nvme_ocp_telemetry_offsets *poffsets,
+ FILE *fp)
+{
+ if (poffsets == NULL) {
+ nvme_show_error("Input buffer was NULL");
+ return -1;
+ }
+
+ __u8 *pda1_ocp_header_offset = ptelemetry_buffer + poffsets->header_size;//512
+ __u32 statistics_size = 0;
+ __u32 stats_da_1_start_dw = 0, stats_da_1_size_dw = 0;
+ __u32 stats_da_2_start_dw = 0, stats_da_2_size_dw = 0;
+ __u8 *pstats_offset = NULL;
+
+ if (poffsets->data_area == 1) {
+ __u32 stats_da_1_start = *(__u32 *)(pda1_ocp_header_offset +
+ offsetof(struct nvme_ocp_header_in_da1, da1_statistic_start));
+ __u32 stats_da_1_size = *(__u32 *)(pda1_ocp_header_offset +
+ offsetof(struct nvme_ocp_header_in_da1, da1_statistic_size));
+
+ //Data is present in the form of DWORDS, So multiplying with sizeof(DWORD)
+ stats_da_1_start_dw = (stats_da_1_start * SIZE_OF_DWORD);
+ stats_da_1_size_dw = (stats_da_1_size * SIZE_OF_DWORD);
+
+ pstats_offset = pda1_ocp_header_offset + stats_da_1_start_dw;
+ statistics_size = stats_da_1_size_dw;
+ } else if (poffsets->data_area == 2) {
+ __u32 stats_da_2_start = *(__u32 *)(pda1_ocp_header_offset +
+ offsetof(struct nvme_ocp_header_in_da1, da2_statistic_start));
+ __u32 stats_da_2_size = *(__u32 *)(pda1_ocp_header_offset +
+ offsetof(struct nvme_ocp_header_in_da1, da2_statistic_size));
+
+ stats_da_2_start_dw = (stats_da_2_start * SIZE_OF_DWORD);
+ stats_da_2_size_dw = (stats_da_2_size * SIZE_OF_DWORD);
+
+ pstats_offset = pda1_ocp_header_offset + poffsets->da1_size + stats_da_2_start_dw;
+ statistics_size = stats_da_2_size_dw;
+ } else {
+ nvme_show_error("Unsupported Data Area:[%d]", poffsets->data_area);
+ return -1;
+ }
+
+ struct json_object *pstats_array = ((root != NULL) ? json_create_array() : NULL);
+
+ __u32 stat_des_size = sizeof(struct nvme_ocp_telemetry_statistic_descriptor);//8
+ __u32 offset_to_move = 0;
+
+ while (((statistics_size > 0) && (offset_to_move < statistics_size))) {
+ struct nvme_ocp_telemetry_statistic_descriptor *pstatistic_entry =
+ (struct nvme_ocp_telemetry_statistic_descriptor *)
+ (pstats_offset + offset_to_move);
+
+ parse_statistic(pstatistic_entry, pstats_array, fp);
+ offset_to_move += (pstatistic_entry->statistic_data_size * SIZE_OF_DWORD +
+ stat_des_size);
+ }
+
+ if (root != NULL && pstats_array != NULL) {
+ const char *pdata_area =
+ (poffsets->data_area == 1 ? STR_DA_1_STATS : STR_DA_2_STATS);
+
+ json_object_add_value_array(root, pdata_area, pstats_array);
+ }
+
+ return 0;
+}
+
+int print_ocp_telemetry_normal(struct ocp_telemetry_parse_options *options)
+{
+ int status = 0;
+
+ if (options->output_file != NULL) {
+ FILE *fp = fopen(options->output_file, "w");
+
+ if (fp) {
+ fprintf(fp, STR_LINE);
+ fprintf(fp, "%s\n", STR_LOG_PAGE_HEADER);
+ fprintf(fp, STR_LINE);
+ if (!strcmp(options->telemetry_type, "host"))
+ generic_structure_parser(ptelemetry_buffer, host_log_page_header,
+ ARRAY_SIZE(host_log_page_header), NULL, 0, fp);
+ else if (!strcmp(options->telemetry_type, "controller"))
+ generic_structure_parser(ptelemetry_buffer,
+ controller_log_page_header,
+ ARRAY_SIZE(controller_log_page_header), NULL, 0, fp);
+ fprintf(fp, STR_LINE);
+ fprintf(fp, "%s\n", STR_REASON_IDENTIFIER);
+ fprintf(fp, STR_LINE);
+ __u8 *preason_identifier_offset = ptelemetry_buffer +
+ offsetof(struct nvme_ocp_telemetry_host_initiated_header,
+ reason_id);
+
+ generic_structure_parser(preason_identifier_offset, reason_identifier,
+ ARRAY_SIZE(reason_identifier), NULL, 0, fp);
+
+ fprintf(fp, STR_LINE);
+ fprintf(fp, "%s\n", STR_TELEMETRY_HOST_DATA_BLOCK_1);
+ fprintf(fp, STR_LINE);
+
+ //Set DA to 1 and get offsets
+ struct nvme_ocp_telemetry_offsets offsets = { 0 };
+
+ offsets.data_area = 1;// Default DA - DA1
+
+ struct nvme_ocp_telemetry_common_header *ptelemetry_common_header =
+ (struct nvme_ocp_telemetry_common_header *) ptelemetry_buffer;
+
+ get_telemetry_das_offset_and_size(ptelemetry_common_header, &offsets);
+
+ __u8 *pda1_header_offset = ptelemetry_buffer +
+ offsets.da1_start_offset;//512
+
+ generic_structure_parser(pda1_header_offset, ocp_header_in_da1,
+ ARRAY_SIZE(ocp_header_in_da1), NULL, 0, fp);
+
+ fprintf(fp, STR_LINE);
+ fprintf(fp, "%s\n", STR_SMART_HEALTH_INFO);
+ fprintf(fp, STR_LINE);
+ __u8 *pda1_smart_offset = pda1_header_offset +
+ offsetof(struct nvme_ocp_header_in_da1, smart_health_info);
+ //512+512 =1024
+
+ generic_structure_parser(pda1_smart_offset, smart, ARRAY_SIZE(smart),
+ NULL, 0, fp);
+
+ fprintf(fp, STR_LINE);
+ fprintf(fp, "%s\n", STR_SMART_HEALTH_INTO_EXTENDED);
+ fprintf(fp, STR_LINE);
+ __u8 *pda1_smart_ext_offset = pda1_header_offset +
+ offsetof(struct nvme_ocp_header_in_da1,
+ smart_health_info_extended);
+
+ generic_structure_parser(pda1_smart_ext_offset, smart_extended,
+ ARRAY_SIZE(smart_extended), NULL, 0, fp);
+
+ fprintf(fp, STR_LINE);
+ fprintf(fp, "%s\n", STR_DA_1_STATS);
+ fprintf(fp, STR_LINE);
+
+ status = parse_statistics(NULL, &offsets, fp);
+ if (status != 0) {
+ nvme_show_error("status: %d\n", status);
+ return -1;
+ }
+
+ fprintf(fp, STR_LINE);
+ fprintf(fp, "%s\n", STR_DA_1_EVENT_FIFO_INFO);
+ fprintf(fp, STR_LINE);
+ status = parse_event_fifos(NULL, &offsets, fp);
+ if (status != 0) {
+ nvme_show_error("status: %d\n", status);
+ return -1;
+ }
+
+ //Set the DA to 2
+ if (options->data_area == 2) {
+ offsets.data_area = 2;
+ fprintf(fp, STR_LINE);
+ fprintf(fp, "%s\n", STR_DA_2_STATS);
+ fprintf(fp, STR_LINE);
+ status = parse_statistics(NULL, &offsets, fp);
+
+ if (status != 0) {
+ nvme_show_error("status: %d\n", status);
+ return -1;
+ }
+
+ fprintf(fp, STR_LINE);
+ fprintf(fp, "%s\n", STR_DA_2_EVENT_FIFO_INFO);
+ fprintf(fp, STR_LINE);
+ status = parse_event_fifos(NULL, &offsets, fp);
+ if (status != 0) {
+ nvme_show_error("status: %d\n", status);
+ return -1;
+ }
+ }
+
+ fprintf(fp, STR_LINE);
+ fclose(fp);
+ } else {
+ nvme_show_error("Failed to open %s file.\n", options->output_file);
+ return -1;
+ }
+ } else {
+ printf(STR_LINE);
+ printf("%s\n", STR_LOG_PAGE_HEADER);
+ printf(STR_LINE);
+ if (!strcmp(options->telemetry_type, "host"))
+ generic_structure_parser(ptelemetry_buffer, host_log_page_header,
+ ARRAY_SIZE(host_log_page_header), NULL, 0, NULL);
+ else if (!strcmp(options->telemetry_type, "controller"))
+ generic_structure_parser(ptelemetry_buffer, controller_log_page_header,
+ ARRAY_SIZE(controller_log_page_header), NULL, 0, NULL);
+
+ printf(STR_LINE);
+ printf("%s\n", STR_REASON_IDENTIFIER);
+ printf(STR_LINE);
+ __u8 *preason_identifier_offset = ptelemetry_buffer +
+ offsetof(struct nvme_ocp_telemetry_host_initiated_header, reason_id);
+ generic_structure_parser(preason_identifier_offset, reason_identifier,
+ ARRAY_SIZE(reason_identifier), NULL, 0, NULL);
+
+ printf(STR_LINE);
+ printf("%s\n", STR_TELEMETRY_HOST_DATA_BLOCK_1);
+ printf(STR_LINE);
+
+ //Set DA to 1 and get offsets
+ struct nvme_ocp_telemetry_offsets offsets = { 0 };
+
+ offsets.data_area = 1;
+
+ struct nvme_ocp_telemetry_common_header *ptelemetry_common_header =
+ (struct nvme_ocp_telemetry_common_header *) ptelemetry_buffer;
+
+ get_telemetry_das_offset_and_size(ptelemetry_common_header, &offsets);
+
+ __u8 *pda1_header_offset = ptelemetry_buffer + offsets.da1_start_offset;//512
+
+ generic_structure_parser(pda1_header_offset, ocp_header_in_da1,
+ ARRAY_SIZE(ocp_header_in_da1), NULL, 0, NULL);
+
+ printf(STR_LINE);
+ printf("%s\n", STR_SMART_HEALTH_INFO);
+ printf(STR_LINE);
+ __u8 *pda1_smart_offset = pda1_header_offset +
+ offsetof(struct nvme_ocp_header_in_da1, smart_health_info);
+
+ generic_structure_parser(pda1_smart_offset, smart, ARRAY_SIZE(smart), NULL, 0,
+ NULL);
+
+ printf(STR_LINE);
+ printf("%s\n", STR_SMART_HEALTH_INTO_EXTENDED);
+ printf(STR_LINE);
+ __u8 *pda1_smart_ext_offset = pda1_header_offset +
+ offsetof(struct nvme_ocp_header_in_da1, smart_health_info_extended);
+
+ generic_structure_parser(pda1_smart_ext_offset, smart_extended,
+ ARRAY_SIZE(smart_extended), NULL, 0, NULL);
+
+ printf(STR_LINE);
+ printf("%s\n", STR_DA_1_STATS);
+ printf(STR_LINE);
+ status = parse_statistics(NULL, &offsets, NULL);
+ if (status != 0) {
+ nvme_show_error("status: %d\n", status);
+ return -1;
+ }
+
+ printf(STR_LINE);
+ printf("%s\n", STR_DA_1_EVENT_FIFO_INFO);
+ printf(STR_LINE);
+ status = parse_event_fifos(NULL, &offsets, NULL);
+ if (status != 0) {
+ nvme_show_error("status: %d\n", status);
+ return -1;
+ }
+
+ //Set the DA to 2
+ if (options->data_area == 2) {
+ offsets.data_area = 2;
+ printf(STR_LINE);
+ printf("%s\n", STR_DA_2_STATS);
+ printf(STR_LINE);
+ status = parse_statistics(NULL, &offsets, NULL);
+ if (status != 0) {
+ nvme_show_error("status: %d\n", status);
+ return -1;
+ }
+
+ printf(STR_LINE);
+ printf("%s\n", STR_DA_2_EVENT_FIFO_INFO);
+ printf(STR_LINE);
+ status = parse_event_fifos(NULL, &offsets, NULL);
+ if (status != 0) {
+ nvme_show_error("status: %d\n", status);
+ return -1;
+ }
+ }
+
+ printf(STR_LINE);
+ }
+
+ return status;
+}
+
+int print_ocp_telemetry_json(struct ocp_telemetry_parse_options *options)
+{
+ int status = 0;
+
+ //create json objects
+ struct json_object *root, *pheader, *preason_identifier, *da1_header, *smart_obj,
+ *ext_smart_obj;
+
+ root = json_create_object();
+
+ //Add data to root json object
+
+ //"Log Page Header"
+ pheader = json_create_object();
+
+ generic_structure_parser(ptelemetry_buffer, host_log_page_header,
+ ARRAY_SIZE(host_log_page_header), pheader, 0, NULL);
+ json_object_add_value_object(root, STR_LOG_PAGE_HEADER, pheader);
+
+ //"Reason Identifier"
+ preason_identifier = json_create_object();
+
+ __u8 *preason_identifier_offset = ptelemetry_buffer +
+ offsetof(struct nvme_ocp_telemetry_host_initiated_header, reason_id);
+
+ generic_structure_parser(preason_identifier_offset, reason_identifier,
+ ARRAY_SIZE(reason_identifier), preason_identifier, 0, NULL);
+ json_object_add_value_object(pheader, STR_REASON_IDENTIFIER, preason_identifier);
+
+ struct nvme_ocp_telemetry_offsets offsets = { 0 };
+
+ //Set DA to 1 and get offsets
+ offsets.data_area = 1;
+ struct nvme_ocp_telemetry_common_header *ptelemetry_common_header =
+ (struct nvme_ocp_telemetry_common_header *) ptelemetry_buffer;
+
+ get_telemetry_das_offset_and_size(ptelemetry_common_header, &offsets);
+
+ //"Telemetry Host-Initiated Data Block 1"
+ __u8 *pda1_header_offset = ptelemetry_buffer + offsets.da1_start_offset;//512
+
+ da1_header = json_create_object();
+
+ generic_structure_parser(pda1_header_offset, ocp_header_in_da1,
+ ARRAY_SIZE(ocp_header_in_da1), da1_header, 0, NULL);
+ json_object_add_value_object(root, STR_TELEMETRY_HOST_DATA_BLOCK_1, da1_header);
+
+ //"SMART / Health Information Log(LID-02h)"
+ __u8 *pda1_smart_offset = pda1_header_offset + offsetof(struct nvme_ocp_header_in_da1,
+ smart_health_info);
+ smart_obj = json_create_object();
+
+ generic_structure_parser(pda1_smart_offset, smart, ARRAY_SIZE(smart), smart_obj, 0, NULL);
+ json_object_add_value_object(da1_header, STR_SMART_HEALTH_INFO, smart_obj);
+
+ //"SMART / Health Information Extended(LID-C0h)"
+ __u8 *pda1_smart_ext_offset = pda1_header_offset + offsetof(struct nvme_ocp_header_in_da1,
+ smart_health_info_extended);
+ ext_smart_obj = json_create_object();
+
+ generic_structure_parser(pda1_smart_ext_offset, smart_extended, ARRAY_SIZE(smart_extended),
+ ext_smart_obj, 0, NULL);
+ json_object_add_value_object(da1_header, STR_SMART_HEALTH_INTO_EXTENDED, ext_smart_obj);
+
+ //Data Area 1 Statistics
+ status = parse_statistics(root, &offsets, NULL);
+ if (status != 0) {
+ nvme_show_error("status: %d\n", status);
+ return -1;
+ }
+
+ //Data Area 1 Event FIFOs
+ status = parse_event_fifos(root, &offsets, NULL);
+ if (status != 0) {
+ nvme_show_error("status: %d\n", status, NULL);
+ return -1;
+ }
+
+ if (options->data_area == 2) {
+ //Set the DA to 2
+ offsets.data_area = 2;
+ //Data Area 2 Statistics
+ status = parse_statistics(root, &offsets, NULL);
+ if (status != 0) {
+ nvme_show_error("status: %d\n", status);
+ return -1;
+ }
+
+ //Data Area 2 Event FIFOs
+ status = parse_event_fifos(root, &offsets, NULL);
+ if (status != 0) {
+ nvme_show_error("status: %d\n", status);
+ return -1;
+ }
+ }
+
+ if (options->output_file != NULL) {
+ const char *json_string = json_object_to_json_string(root);
+ FILE *fp = fopen(options->output_file, "w");
+
+ if (fp) {
+ fputs(json_string, fp);
+ fclose(fp);
+ } else {
+ nvme_show_error("Failed to open %s file.\n", options->output_file);
+ return -1;
+ }
+ } else {
+ //Print root json object
+ json_print_object(root, NULL);
+ nvme_show_result("\n");
+ json_free_object(root);
+ }
+
+ return status;
+}
* Authors: Jeff Lien <jeff.lien@wdc.com>,
*/
+#include "nvme.h"
+#include "nvme-print.h"
+#include "util/utils.h"
+#include "common.h"
+
+extern __u8 *ptelemetry_buffer;
+extern __u8 *pstring_buffer;
+
/*****************************************************************************
* Telemetry Statistics ID's and Strings
*****************************************************************************/
__u8 smart_health_info_extended[512];
};
+#define DATA_SIZE_12 12
+#define DATA_SIZE_8 8
+#define DATA_SIZE_4 4
+#define MAX_BUFFER_32_KB 0x8000
+#define OCP_TELEMETRY_DATA_BLOCK_SIZE 512
+#define SIZE_OF_DWORD 4
+#define MAX_NUM_FIFOS 16
+#define DA1_OFFSET 512
+#define DEFAULT_ASCII_STRING_SIZE 16
+
+#define DEFAULT_TELEMETRY_BIN "telemetry.bin"
+#define DEFAULT_STRING_BIN "string.bin"
+#define DEFAULT_OUTPUT_FORMAT_JSON "json"
+
+/* C9 Telemetry String Log Format Log Page */
+#define C9_GUID_LENGTH 16
+#define C9_TELEMETRY_STRING_LOG_ENABLE_OPCODE 0xC9
+#define C9_TELEMETRY_STR_LOG_LEN 432
+#define C9_TELEMETRY_STR_LOG_SIST_OFST 431
+
+#define STR_LOG_PAGE_HEADER "Log Page Header"
+#define STR_REASON_IDENTIFIER "Reason Identifier"
+#define STR_TELEMETRY_HOST_DATA_BLOCK_1 "Telemetry Host-Initiated Data Block 1"
+#define STR_SMART_HEALTH_INFO "SMART / Health Information Log(LID-02h)"
+#define STR_SMART_HEALTH_INTO_EXTENDED "SMART / Health Information Extended(LID-C0h)"
+#define STR_DA_1_STATS "Data Area 1 Statistics"
+#define STR_DA_2_STATS "Data Area 2 Statistics"
+#define STR_DA_1_EVENT_FIFO_INFO "Data Area 1 Event FIFO info"
+#define STR_DA_2_EVENT_FIFO_INFO "Data Area 2 Event FIFO info"
+#define STR_STATISTICS_IDENTIFIER "Statistics Identifier"
+#define STR_STATISTICS_IDENTIFIER_STR "Statistic Identifier String"
+#define STR_STATISTICS_INFO_BEHAVIOUR_TYPE "Statistics Info Behavior Type"
+#define STR_STATISTICS_INFO_RESERVED "Statistics Info Reserved"
+#define STR_NAMESPACE_IDENTIFIER "Namespace Identifier"
+#define STR_NAMESPACE_INFO_VALID "Namespace Information Valid"
+#define STR_STATISTICS_DATA_SIZE "Statistic Data Size"
+#define STR_RESERVED "Reserved"
+#define STR_STATISTICS_SPECIFIC_DATA "Statistic Specific Data"
+#define STR_CLASS_SPECIFIC_DATA "Class Specific Data"
+#define STR_DBG_EVENT_CLASS_TYPE "Debug Event Class type"
+#define STR_EVENT_IDENTIFIER "Event Identifier"
+#define STR_EVENT_STRING "Event String"
+#define STR_EVENT_DATA_SIZE "Event Data Size"
+#define STR_VU_EVENT_STRING "VU Event String"
+#define STR_VU_EVENT_ID_STRING "VU Event Identifier"
+#define STR_VU_DATA "VU Data"
+#define STR_LINE "==============================================================================\n"
+#define STR_LINE2 "-----------------------------------------------------------------------------\n"
+
+/**
+ * enum ocp_telemetry_data_area - Telemetry Data Areas
+ * @DATA_AREA_1: Data Area 1
+ * @DATA_AREA_2: Data Area 2
+ * @DATA_AREA_3: Data Area 3
+ * @DATA_AREA_4: Data Area 4
+ */
+enum ocp_telemetry_data_area {
+ DATA_AREA_1 = 0x01,
+ DATA_AREA_2 = 0x02,
+ DATA_AREA_3 = 0x03,
+ DATA_AREA_4 = 0x04,
+};
+
+/**
+ * enum ocp_telemetry_string_tables - OCP telemetry string tables
+ * @STATISTICS_IDENTIFIER_STRING: Statistic Identifier string
+ * @EVENT_STRING: Event String
+ * @VU_EVENT_STRING: VU Event String
+ */
+enum ocp_telemetry_string_tables {
+ STATISTICS_IDENTIFIER_STRING = 0,
+ EVENT_STRING,
+ VU_EVENT_STRING
+};
+
+/**
+ * enum ocp_telemetry_debug_event_class_types - OCP Debug Event Class types
+ * @RESERVED_CLASS_TYPE: Reserved class
+ * @TIME_STAMP_CLASS_TYPE: Time stamp class
+ * @PCIE_CLASS_TYPE: PCIe class
+ * @NVME_CLASS_TYPE: NVME class
+ * @RESET_CLASS_TYPE: Reset class
+ * @BOOT_SEQUENCE_CLASS_TYPE: Boot Sequence class
+ * @FIRMWARE_ASSERT_CLASS_TYPE: Firmware Assert class
+ * @TEMPERATURE_CLASS_TYPE: Temperature class
+ * @MEDIA_CLASS_TYPE: Media class
+ * @MEDIA_WEAR_CLASS_TYPE: Media wear class
+ * @STATISTIC_SNAPSHOT_CLASS_TYPE: Statistic snapshot class
+ * @RESERVED: Reserved class
+ * @VENDOR_UNIQUE_CLASS_TYPE: Vendor Unique class
+ */
+enum ocp_telemetry_debug_event_class_types {
+ RESERVED_CLASS_TYPE = 0x00,
+ TIME_STAMP_CLASS_TYPE = 0x01,
+ PCIE_CLASS_TYPE = 0x02,
+ NVME_CLASS_TYPE = 0x03,
+ RESET_CLASS_TYPE = 0x04,
+ BOOT_SEQUENCE_CLASS_TYPE = 0x05,
+ FIRMWARE_ASSERT_CLASS_TYPE = 0x06,
+ TEMPERATURE_CLASS_TYPE = 0x07,
+ MEDIA_CLASS_TYPE = 0x08,
+ MEDIA_WEAR_CLASS_TYPE = 0x09,
+ STATISTIC_SNAPSHOT_CLASS_TYPE = 0x0A,
+ //RESERVED = 7Fh-0Bh,
+ //VENDOR_UNIQUE_CLASS_TYPE = FFh-80h,
+};
+
+/**
+ * struct telemetry_str_log_format - Telemetry String Log Format
+ * @log_page_version: indicates the version of the mapping this log page uses
+ * Shall be set to 01h.
+ * @reserved1: Reserved.
+ * @log_page_guid: Shall be set to B13A83691A8F408B9EA495940057AA44h.
+ * @sls: Shall be set to the number of DWORDS in the String Log.
+ * @reserved2: reserved.
+ * @sits: shall be set to the number of DWORDS in the Statistics
+ * Identifier String Table
+ * @ests: Shall be set to the number of DWORDS from byte 0 of this
+ * log page to the start of the Event String Table
+ * @estsz: shall be set to the number of DWORDS in the Event String Table
+ * @vu_eve_sts: Shall be set to the number of DWORDS from byte 0 of this
+ * log page to the start of the VU Event String Table
+ * @vu_eve_st_sz: shall be set to the number of DWORDS in the VU Event String Table
+ * @ascts: the number of DWORDS from byte 0 of this log page until the
+ * ASCII Table Starts.
+ * @asctsz: the number of DWORDS in the ASCII Table
+ * @fifo1: FIFO 0 ASCII String
+ * @fifo2: FIFO 1 ASCII String
+ * @fifo3: FIFO 2 ASCII String
+ * @fifo4: FIFO 3 ASCII String
+ * @fif05: FIFO 4 ASCII String
+ * @fifo6: FIFO 5 ASCII String
+ * @fifo7: FIFO 6 ASCII String
+ * @fifo8: FIFO 7 ASCII String
+ * @fifo9: FIFO 8 ASCII String
+ * @fifo10: FIFO 9 ASCII String
+ * @fif011: FIFO 10 ASCII String
+ * @fif012: FIFO 11 ASCII String
+ * @fifo13: FIFO 12 ASCII String
+ * @fif014: FIFO 13 ASCII String
+ * @fif015: FIFO 14 ASCII String
+ * @fif016: FIFO 15 ASCII String
+ * @reserved3: reserved
+ */
+struct __packed telemetry_str_log_format {
+ __u8 log_page_version;
+ __u8 reserved1[15];
+ __u8 log_page_guid[C9_GUID_LENGTH];
+ __le64 sls;
+ __u8 reserved2[24];
+ __le64 sits;
+ __le64 sitsz;
+ __le64 ests;
+ __le64 estsz;
+ __le64 vu_eve_sts;
+ __le64 vu_eve_st_sz;
+ __le64 ascts;
+ __le64 asctsz;
+ __u8 fifo1[16];
+ __u8 fifo2[16];
+ __u8 fifo3[16];
+ __u8 fifo4[16];
+ __u8 fifo5[16];
+ __u8 fifo6[16];
+ __u8 fifo7[16];
+ __u8 fifo8[16];
+ __u8 fifo9[16];
+ __u8 fifo10[16];
+ __u8 fifo11[16];
+ __u8 fifo12[16];
+ __u8 fifo13[16];
+ __u8 fifo14[16];
+ __u8 fifo15[16];
+ __u8 fifo16[16];
+ __u8 reserved3[48];
+};
+
+/*
+ * struct statistics_id_str_table_entry - Statistics Identifier String Table Entry
+ * @vs_si: Shall be set the Vendor Unique Statistic Identifier number.
+ * @reserved1: Reserved
+ * @ascii_id_len: Shall be set the number of ASCII Characters that are valid.
+ * @ascii_id_ofst: Shall be set to the offset from DWORD 0/Byte 0 of the Start
+ * of the ASCII Table to the first character of the string for
+ * this Statistic Identifier string..
+ * @reserved2 reserved
+ */
+struct __packed statistics_id_str_table_entry {
+ __le16 vs_si;
+ __u8 reserved1;
+ __u8 ascii_id_len;
+ __le64 ascii_id_ofst;
+ __le32 reserved2;
+};
+
+/*
+ * struct event_id_str_table_entry - Event Identifier String Table Entry
+ * @deb_eve_class: Shall be set the Debug Class.
+ * @ei: Shall be set to the Event Identifier
+ * @ascii_id_len: Shall be set the number of ASCII Characters that are valid.
+ * @ascii_id_ofst: This is the offset from DWORD 0/ Byte 0 of the start of the
+ * ASCII table to the ASCII data for this identifier
+ * @reserved2 reserved
+ */
+struct __packed event_id_str_table_entry {
+ __u8 deb_eve_class;
+ __le16 ei;
+ __u8 ascii_id_len;
+ __le64 ascii_id_ofst;
+ __le32 reserved2;
+};
+
+/*
+ * struct vu_event_id_str_table_entry - VU Event Identifier String Table Entry
+ * @deb_eve_class: Shall be set the Debug Class.
+ * @vu_ei: Shall be set to the VU Event Identifier
+ * @ascii_id_len: Shall be set the number of ASCII Characters that are valid.
+ * @ascii_id_ofst: This is the offset from DWORD 0/ Byte 0 of the start of the
+ * ASCII table to the ASCII data for this identifier
+ * @reserved reserved
+ */
+struct __packed vu_event_id_str_table_entry {
+ __u8 deb_eve_class;
+ __le16 vu_ei;
+ __u8 ascii_id_len;
+ __le64 ascii_id_ofst;
+ __le32 reserved;
+};
+
+
+struct __packed ocp_telemetry_parse_options {
+ char *telemetry_log;
+ char *string_log;
+ char *output_file;
+ char *output_format;
+ int data_area;
+ char *telemetry_type;
+};
+
+struct __packed nvme_ocp_telemetry_reason_id
+{
+ __u8 error_id[64]; // Bytes 63:00
+ __u8 file_id[8]; // Bytes 71:64
+ __le16 line_number; // Bytes 73:72
+ __u8 valid_flags; // Bytes 74
+ __u8 reserved[21]; // Bytes 95:75
+ __u8 vu_reason_ext[32]; // Bytes 127:96
+};
+
+struct __packed nvme_ocp_telemetry_common_header
+{
+ __u8 log_id; // Byte 00
+ __le32 reserved1; // Bytes 04:01
+ __u8 ieee_oui_id[3]; // Bytes 07:05
+ __le16 da1_last_block; // Bytes 09:08
+ __le16 da2_last_block; // Bytes 11:10
+ __le16 da3_last_block; // Bytes 13:12
+ __le16 reserved2; // Bytes 15:14
+ __le32 da4_last_block; // Bytes 19:16
+};
+
+struct __packed nvme_ocp_telemetry_host_initiated_header
+{
+ struct nvme_ocp_telemetry_common_header commonHeader; // Bytes 19:00
+ __u8 reserved3[360]; // Bytes 379:20
+ __u8 host_initiated_scope; // Byte 380
+ __u8 host_initiated_gen_number; // Byte 381
+ __u8 host_initiated_data_available; // Byte 382
+ __u8 ctrl_initiated_gen_number; // Byte 383
+ struct nvme_ocp_telemetry_reason_id reason_id; // Bytes 511:384
+};
+
+struct __packed nvme_ocp_telemetry_controller_initiated_header
+{
+ struct nvme_ocp_telemetry_common_header commonHeader; // Bytes 19:00
+ __u8 reserved3[361]; // Bytes 380:20
+ __u8 ctrl_initiated_scope; // Byte 381
+ __u8 ctrl_initiated_data_available; // Byte 382
+ __u8 ctrl_initiated_gen_number; // Byte 383
+ struct nvme_ocp_telemetry_reason_id reason_id; // Bytes 511:384
+};
+
+struct __packed nvme_ocp_telemetry_smart
+{
+ __u8 critical_warning; // Byte 0
+ __le16 composite_temperature; // Bytes 2:1
+ __u8 available_spare; // Bytes 3
+ __u8 available_spare_threshold; // Bytes 4
+ __u8 percentage_used; // Bytes 5
+ __u8 reserved1[26]; // Bytes 31:6
+ __u8 data_units_read[16]; // Bytes 47:32
+ __u8 data_units_written[16]; // Bytes 63:48
+ __u8 host_read_commands[16]; // Byte 79:64
+ __u8 host_write_commands[16]; // Bytes 95:80
+ __u8 controller_busy_time[16]; // Bytes 111:96
+ __u8 power_cycles[16]; // Bytes 127:112
+ __u8 power_on_hours[16]; // Bytes 143:128
+ __u8 unsafe_shutdowns[16]; // Bytes 159:144
+ __u8 media_and_data_integrity_errors[16]; // Bytes 175:160
+ __u8 number_of_error_information_log_entries[16]; // Bytes 191:176
+ __le32 warning_composite_temperature_time; // Byte 195:192
+ __le32 critical_composite_temperature_time; // Bytes 199:196
+ __le16 temperature_sensor1; // Bytes 201:200
+ __le16 temperature_sensor2; // Byte 203:202
+ __le16 temperature_sensor3; // Byte 205:204
+ __le16 temperature_sensor4; // Bytes 207:206
+ __le16 temperature_sensor5; // Bytes 209:208
+ __le16 temperature_sensor6; // Bytes 211:210
+ __le16 temperature_sensor7; // Bytes 213:212
+ __le16 temperature_sensor8; // Bytes 215:214
+ __le32 thermal_management_temperature1_transition_count; // Bytes 219:216
+ __le32 thermal_management_temperature2_transition_count; // Bytes 223:220
+ __le32 total_time_for_thermal_management_temperature1; // Bytes 227:224
+ __le32 total_time_for_thermal_management_temperature2; // Bytes 231:228
+ __u8 reserved2[280]; // Bytes 511:232
+};
+
+struct __packed nvme_ocp_telemetry_smart_extended
+{
+ __u8 physical_media_units_written[16]; // Bytes 15:0
+ __u8 physical_media_units_read[16]; // Bytes 31:16
+ __u8 bad_user_nand_blocks_raw_count[6]; // Bytes 37:32
+ __le16 bad_user_nand_blocks_normalized_value; // Bytes 39:38
+ __u8 bad_system_nand_blocks_raw_count[6]; // Bytes 45:40
+ __le16 bad_system_nand_blocks_normalized_value; // Bytes 47:46
+ __le64 xor_recovery_count; // Bytes 55:48
+ __le64 uncorrectable_read_error_count; // Bytes 63:56
+ __le64 soft_ecc_error_count; // Bytes 71:64
+ __le32 end_to_end_correction_counts_detected_errors; // Bytes 75:72
+ __le32 end_to_end_correction_counts_corrected_errors; // Bytes 79:76
+ __u8 system_data_percent_used; // Byte 80
+ __u8 refresh_counts[7]; // Bytes 87:81
+ __le32 max_user_data_erase_count; // Bytes 91:88
+ __le32 min_user_data_erase_count; // Bytes 95:92
+ __u8 num_thermal_throttling_events; // Bytes 96
+ __u8 current_throttling_status; // Bytes 97
+ __u8 errata_version_field; // Byte 98
+ __le16 point_version_field; // Byte 100:99
+ __le16 minor_version_field; // Byte 102:101
+ __u8 major_version_field; // Byte 103
+ __le64 pcie_correctable_error_count; // Bytes 111:104
+ __le32 incomplete_shutdowns; // Bytes 115:112
+ __le32 reserved1; // Bytes 119:116
+ __u8 percent_free_blocks; // Byte 120
+ __u8 reserved2[7]; // Bytes 127:121
+ __le16 capacitor_health; // Bytes 129:128
+ __u8 nvme_base_errata_version; // Byte 130
+ __u8 nvme_command_set_errata_version; // Byte 131
+ __le32 reserved3; // Bytes 135:132
+ __le64 unaligned_io; // Bytes 143:136
+ __le64 security_version_number; // Bytes 151:144
+ __le64 total_nuse; // Bytes 159:152
+ __u8 plp_start_count[16]; // Bytes 175:160
+ __u8 endurance_estimate[16]; // Bytes 191:176
+ __le64 pcie_link_retraining_count; // Bytes 199:192
+ __le64 power_state_change_count; // Bytes 207:200
+ __le64 lowest_permitted_firmware_revision; // Bytes 215:208
+ __u8 reserved4[278]; // Bytes 493:216
+ __le16 log_page_version; // Bytes 495:494
+ __u8 log_page_guid[16]; // Bytes 511:496
+};
+
+struct __packed nvme_ocp_event_fifo_data
+{
+ __le32 event_fifo_num;
+ __u8 event_fifo_da;
+ __le64 event_fifo_start;
+ __le64 event_fifo_size;
+};
+
+struct __packed nvme_ocp_telemetry_offsets
+{
+ __le32 data_area;
+ __le32 header_size;
+ __le32 da1_start_offset;
+ __le32 da1_size;
+ __le32 da2_start_offset;
+ __le32 da2_size;
+ __le32 da3_start_offset;
+ __le32 da3_size;
+ __le32 da4_start_offset;
+ __le32 da4_size;
+};
+
+struct __packed nvme_ocp_event_fifo_offsets
+{
+ __le64 event_fifo_start;
+ __le64 event_fifo_size;
+};
+
+struct __packed nvme_ocp_header_in_da1
+{
+ __le16 major_version; // Bytes 1:0
+ __le16 minor_version; // Bytes 3:2
+ __le32 reserved1; // Bytes 7:4
+ __le64 time_stamp; // Bytes 15:8
+ __u8 log_page_guid[16]; // Bytes 31:16
+ __u8 num_telemetry_profiles_supported; // Byte 32
+ __u8 telemetry_profile_selected; // Byte 33
+ __u8 reserved2[6]; // Bytes 39:34
+ __le64 string_log_size; // Bytes 47:40
+ __le64 reserved3; // Bytes 55:48
+ __le64 firmware_revision; // Bytes 63:56
+ __u8 reserved4[32]; // Bytes 95:64
+ __le64 da1_statistic_start; // Bytes 103:96
+ __le64 da1_statistic_size; // Bytes 111:104
+ __le64 da2_statistic_start; // Bytes 119:112
+ __le64 da2_statistic_size; // Bytes 127:120
+ __u8 reserved5[32]; // Bytes 159:128
+ __u8 event_fifo_da[16]; // Bytes 175:160
+ struct nvme_ocp_event_fifo_offsets fifo_offsets[16]; // Bytes 431:176
+ __u8 reserved6[80]; // Bytes 511:432
+ struct nvme_ocp_telemetry_smart smart_health_info; // Bytes 1023:512
+ struct nvme_ocp_telemetry_smart_extended smart_health_info_extended; // Bytes 1535:1024
+};
+
+struct __packed nvme_ocp_telemetry_statistic_descriptor
+{
+ __le16 statistic_id; // Bytes 1:0
+ __u8 statistic_info_behaviour_type : 4; // Byte 2(3:0)
+ __u8 statistic_info_reserved : 4; // Byte 2(7:4)
+ __u8 ns_info_nsid : 7; // Bytes 3(6:0)
+ __u8 ns_info_ns_info_valid : 1; // Bytes 3(7)
+ __le16 statistic_data_size; // Bytes 5:4
+ __le16 reserved; // Bytes 7:6
+};
+
+struct __packed nvme_ocp_telemetry_event_descriptor
+{
+ __u8 debug_event_class_type; // Byte 0
+ __le16 event_id; // Bytes 2:1
+ __u8 event_data_size; // Byte 3
+};
+
+struct __packed nvme_ocp_time_stamp_dbg_evt_class_format
+{
+ __u8 time_stamp[DATA_SIZE_8]; // Bytes 11:4
+ __le16 vu_event_identifier; // Bytes 13:12
+};
+
+struct __packed nvme_ocp_pcie_dbg_evt_class_format
+{
+ __u8 pCIeDebugEventData[DATA_SIZE_4]; // Bytes 7:4
+ __le16 vu_event_identifier; // Bytes 9:8
+};
+
+struct __packed nvme_ocp_nvme_dbg_evt_class_format
+{
+ __u8 nvmeDebugEventData[DATA_SIZE_8]; // Bytes 11:4
+ __le16 vu_event_identifier; // Bytes 13:12
+};
+
+struct __packed nvme_ocp_common_dbg_evt_class_format
+{
+ __le16 vu_event_identifier; // Bytes 5:4
+};
+
+struct __packed nvme_ocp_media_wear_dbg_evt_class_format
+{
+ __u8 currentMediaWear[DATA_SIZE_12]; // Bytes 15:4
+ __le16 vu_event_identifier; // Bytes 17:16
+};
+
+struct __packed nvme_ocp_statistic_snapshot_evt_class_format
+{
+ struct nvme_ocp_telemetry_statistic_descriptor statisticDescriptorData; // Bytes 11:10
+};
+
+struct __packed nvme_ocp_statistics_identifier_string_table
+{
+ __le16 vs_statistic_identifier; //1:0
+ __u8 reserved1; //2
+ __u8 ascii_id_length; //3
+ __le64 ascii_id_offset; //11:4
+ __le32 reserved2; //15:12
+};
+
+struct __packed nvme_ocp_event_string_table
+{
+ __u8 debug_event_class; //0
+ __le16 event_identifier; //2:1
+ __u8 ascii_id_length; //3
+ __le64 ascii_id_offset; //11:4
+ __le32 reserved; //15:12
+};
+
+struct __packed nvme_ocp_vu_event_string_table
+{
+ __u8 debug_event_class; //0
+ __le16 vu_event_identifier; //2:1
+ __u8 ascii_id_length; //3
+ __le64 ascii_id_offset; //11:4
+ __le32 reserved; //15:12
+};
+
+struct __packed nvme_ocp_telemetry_string_header
+{
+ __u8 version; //0:0
+ __u8 reserved1[15]; //15:1
+ __u8 guid[16]; //32:16
+ __le64 string_log_size; //39:32
+ __u8 reserved2[24]; //63:40
+ __le64 sits; //71:64 Statistics Identifier String Table Start(SITS)
+ __le64 sitsz; //79:72 Statistics Identifier String Table Size (SITSZ)
+ __le64 ests; //87:80 Event String Table Start(ESTS)
+ __le64 estsz; //95:88 Event String Table Size(ESTSZ)
+ __le64 vu_ests; //103:96 VU Event String Table Start
+ __le64 vu_estsz; //111:104 VU Event String Table Size
+ __le64 ascts; //119:112 ASCII Table start
+ __le64 asctsz; //127:120 ASCII Table Size
+ __u8 fifo_ascii_string[16][16]; //383:128
+ __u8 reserved3[48]; //431:384
+};
+
+struct __packed statistic_entry {
+ int identifier;
+ char *description;
+};
/************************************************************
* Telemetry Parsing Function Prototypes
{
return ARGSTR(telemetry_media_wear_event_id_str, event_id);
}
+
+/**
+ * @brief parse the ocp telemetry host or controller log binary file
+ * into json or text
+ *
+ * @param options, input pointer for inputs like telemetry log bin file,
+ * string log bin file and output file etc.
+ *
+ * @return 0 success
+ */
+int parse_ocp_telemetry_log(struct ocp_telemetry_parse_options *options);
+
+/**
+ * @brief parse the ocp telemetry string log binary file to json or text
+ *
+ * @param event_fifo_num, input event FIFO number
+ * @param debug_event_class, input debug event class id
+ * @param string_table, input string table
+ * @param description, input description string
+ *
+ * @return 0 success
+ */
+int parse_ocp_telemetry_string_log(int event_fifo_num, int identifier, int debug_event_class,
+ enum ocp_telemetry_string_tables string_table, char *description);
+
+/**
+ * @brief gets the telemetry datas areas, offsets and sizes information
+ *
+ * @param ptelemetry_common_header, input telemetry common header pointer
+ * @param ptelemetry_das_offset, input telemetry offsets pointer
+ *
+ * @return 0 success
+ */
+int get_telemetry_das_offset_and_size(
+ struct nvme_ocp_telemetry_common_header *ptelemetry_common_header,
+ struct nvme_ocp_telemetry_offsets *ptelemetry_das_offset);
+
+/**
+ * @brief parses statistics data to text or json formats
+ *
+ * @param root, input time json root object pointer
+ * @param ptelemetry_das_offset, input telemetry offsets pointer
+ * @param fp, input file pointer
+ *
+ * @return 0 success
+ */
+int parse_statistics(struct json_object *root, struct nvme_ocp_telemetry_offsets *pOffsets,
+ FILE *fp);
+
+/**
+ * @brief parses a single statistic data to text or json formats
+ *
+ * @param pstatistic_entry, statistic entry pointer
+ * @param pstats_array, stats array pointer
+ * @param fp, input file pointer
+ *
+ * @return 0 success
+ */
+int parse_statistic(struct nvme_ocp_telemetry_statistic_descriptor *pstatistic_entry,
+ struct json_object *pstats_array, FILE *fp);
+
+/**
+ * @brief parses event fifos data to text or json formats
+ *
+ * @param root, input time json root object pointer
+ * @param poffsets, input telemetry offsets pointer
+ * @param fp, input file pointer
+ *
+ * @return 0 success
+ */
+int parse_event_fifos(struct json_object *root, struct nvme_ocp_telemetry_offsets *poffsets,
+ FILE *fp);
+
+/**
+ * @brief parses a single event fifo data to text or json formats
+ *
+ * @param fifo_num, input event fifo number
+ * @param pfifo_start, event fifo start pointer
+ * @param pevent_fifos_object, event fifos json object pointer
+ * @param ptelemetry_das_offset, input telemetry offsets pointer
+ * @param fifo_size, input event fifo size
+ * @param fp, input file pointer
+ *
+ * @return 0 success
+ */
+int parse_event_fifo(unsigned int fifo_num, unsigned char *pfifo_start,
+ struct json_object *pevent_fifos_object, unsigned char *pstring_buffer,
+ struct nvme_ocp_telemetry_offsets *poffsets, __u64 fifo_size, FILE *fp);
+
+/**
+ * @brief parses event fifos data to text or json formats
+ *
+ * @return 0 success
+ */
+int print_ocp_telemetry_normal(struct ocp_telemetry_parse_options *options);
+
+/**
+ * @brief parses event fifos data to text or json formats
+ *
+ * @return 0 success
+ */
+int print_ocp_telemetry_json(struct ocp_telemetry_parse_options *options);
+
+/**
+ * @brief gets statistic id ascii string
+ *
+ * @param identifier, string id
+ * @param description, string description
+ *
+ * @return 0 success
+ */
+int get_static_id_ascii_string(int identifier, char *description);
+
+/**
+ * @brief gets event id ascii string
+ *
+ * @param identifier, string id
+ * @param debug_event_class, debug event class
+ * @param description, string description
+ *
+ * @return 0 success
+ */
+int get_event_id_ascii_string(int identifier, int debug_event_class, char *description);
+
+/**
+ * @brief gets vu event id ascii string
+ *
+ * @param identifier, string id
+ * @param debug_event_class, debug event class
+ * @param description, string description
+ *
+ * @return 0 success
+ */
+int get_vu_event_id_ascii_string(int identifier, int debug_event_class, char *description);
+
+/**
+ * @brief parses a time-stamp event fifo data to text or json formats
+ *
+ * @param pevent_descriptor, input event descriptor data
+ * @param pevent_descriptor_obj, event descriptor json object pointer
+ * @param pevent_specific_data, input event specific data
+ * @param pevent_fifos_object, event fifos json object pointer
+ * @param fp, input file pointer
+ *
+ * @return
+ */
+void parse_time_stamp_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor,
+ struct json_object *pevent_descriptor_obj, __u8 *pevent_specific_data,
+ struct json_object *pevent_fifos_object, FILE *fp);
+
+/**
+ * @brief parses a pcie event fifo data to text or json formats
+ *
+ * @param pevent_descriptor, input event descriptor data
+ * @param pevent_descriptor_obj, event descriptor json object pointer
+ * @param pevent_specific_data, input event specific data
+ * @param pevent_fifos_object, event fifos json object pointer
+ * @param fp, input file pointer
+ *
+ * @return
+ */
+void parse_pcie_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor,
+ struct json_object *pevent_descriptor_obj, __u8 *pevent_specific_data,
+ struct json_object *pevent_fifos_object, FILE *fp);
+
+/**
+ * @brief parses a nvme event fifo data to text or json formats
+ *
+ * @param pevent_descriptor, input event descriptor data
+ * @param pevent_descriptor_obj, event descriptor json object pointer
+ * @param pevent_specific_data, input event specific data
+ * @param pevent_fifos_object, event fifos json object pointer
+ * @param fp, input file pointer
+ *
+ * @return
+ */
+void parse_nvme_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor,
+ struct json_object *pevent_descriptor_obj, __u8 *pevent_specific_data,
+ struct json_object *pevent_fifos_object, FILE *fp);
+
+/**
+ * @brief parses common event fifo data to text or json formats
+ *
+ * @param pevent_descriptor, input event descriptor data
+ * @param pevent_descriptor_obj, event descriptor json object pointer
+ * @param pevent_specific_data, input event specific data
+ * @param pevent_fifos_object, event fifos json object pointer
+ * @param fp, input file pointer
+ *
+ * @return
+ */
+void parse_common_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor,
+ struct json_object *pevent_descriptor_obj, __u8 *pevent_specific_data,
+ struct json_object *pevent_fifos_object, FILE *fp);
+
+/**
+ * @brief parses a media-wear event fifo data to text or json formats
+ *
+ * @param pevent_descriptor, input event descriptor data
+ * @param pevent_descriptor_obj, event descriptor json object pointer
+ * @param pevent_specific_data, input event specific data
+ * @param pevent_fifos_object, event fifos json object pointer
+ * @param fp, input file pointer
+ *
+ * @return
+ */
+void parse_media_wear_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descriptor,
+ struct json_object *pevent_descriptor_obj, __u8 *pevent_specific_data,
+ struct json_object *pevent_fifos_object, FILE *fp);
'util/mem.c',
'util/suffix.c',
'util/types.c',
+ 'util/utils.c'
]
if json_c_dep.found()
* Copyright (c) Micron, Inc 2024.
*
* @file: micron-utils.h
- * @brief: This module contains all the utilities needed for micron nvme plugin
- * and other micron modules.
+ * @brief: This module contains all the utilities needed for other modules.
* @author: Chaithanya Shoba <ashoba@micron.com>
*/
-#include "micron-utils.h"
+#include "utils.h"
int hex_to_int(char c)
{
sprintf(datastr, "%s", description_str);
}
-void print_micron_vs_logs(__u8 *buf, struct micron_vs_logpage *log_page, int field_count,
+void generic_structure_parser(__u8 *buf, struct request_data *req_data, int field_count,
struct json_object *stats, __u8 spec, FILE *fp)
{
int offset = 0;
for (int field = 0; field < field_count; field++) {
char datastr[1024] = { 0 };
- char *sfield = log_page[field].field;
- int size = !spec ? log_page[field].size : log_page[field].size2;
+ char *sfield = req_data[field].field;
+ int size = !spec ? req_data[field].size : req_data[field].size2;
if (!size || sfield == NULL)
continue;
* Copyright (c) Micron, Inc 2024.
*
* @file: micron-utils.h
- * @brief: This module contains all the utilities needed for micron nvme plugin
- * and other micron modules.
+ * @brief: This module contains all the utilities needed for other modules.
* @author: Chaithanya Shoba <ashoba@micron.com>
*/
#include "nvme-print.h"
#include "util/cleanup.h"
-/* OCP and Vendor specific log data format */
-struct __packed micron_vs_logpage {
+/*Request data format*/
+struct __packed request_data {
char *field;
- int size; /* FB client spec version 1.0 sizes - M5410 models */
- int size2; /* FB client spec version 0.7 sizes - M5407 models */
+ int size;
+ int size2;
};
enum field_size {
int retry_count);
/**
- * @brief prints Micron VS log pages
+ * @brief prints generic structure parser
*
* @param buf, input raw log data
* @param log_page, input format of the data
*
* @return 0 success
*/
-void print_micron_vs_logs(__u8 *buf, struct micron_vs_logpage *log_page, int field_count,
+void generic_structure_parser(__u8 *buf, struct request_data *req_data, int field_count,
struct json_object *stats, __u8 spec, FILE *fp);
/**