diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-11-09 08:09:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-11-09 08:09:59 +0000 |
commit | 3a023e2f691f3679889da0d63f377704e395e58a (patch) | |
tree | 90bcede47e76472c15225259d858ceb7987c9ff1 /plugins/ocp | |
parent | Releasing debian version 2.10.2-1. (diff) | |
download | nvme-cli-3a023e2f691f3679889da0d63f377704e395e58a.tar.xz nvme-cli-3a023e2f691f3679889da0d63f377704e395e58a.zip |
Merging upstream version 2.11.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'plugins/ocp')
-rw-r--r-- | plugins/ocp/meson.build | 9 | ||||
-rw-r--r-- | plugins/ocp/ocp-fw-activation-history.c | 129 | ||||
-rw-r--r-- | plugins/ocp/ocp-fw-activation-history.h | 32 | ||||
-rw-r--r-- | plugins/ocp/ocp-hardware-component-log.c | 288 | ||||
-rw-r--r-- | plugins/ocp/ocp-hardware-component-log.h | 64 | ||||
-rw-r--r-- | plugins/ocp/ocp-nvme.c | 1809 | ||||
-rw-r--r-- | plugins/ocp/ocp-nvme.h | 200 | ||||
-rw-r--r-- | plugins/ocp/ocp-print-binary.c | 54 | ||||
-rw-r--r-- | plugins/ocp/ocp-print-json.c | 851 | ||||
-rw-r--r-- | plugins/ocp/ocp-print-stdout.c | 710 | ||||
-rw-r--r-- | plugins/ocp/ocp-print.c | 81 | ||||
-rw-r--r-- | plugins/ocp/ocp-print.h | 51 | ||||
-rw-r--r-- | plugins/ocp/ocp-smart-extended-log.c | 239 | ||||
-rw-r--r-- | plugins/ocp/ocp-smart-extended-log.h | 40 | ||||
-rw-r--r-- | plugins/ocp/ocp-telemetry-decode.c | 471 | ||||
-rw-r--r-- | plugins/ocp/ocp-telemetry-decode.h | 32 |
16 files changed, 2983 insertions, 2077 deletions
diff --git a/plugins/ocp/meson.build b/plugins/ocp/meson.build index 7835444..55b9966 100644 --- a/plugins/ocp/meson.build +++ b/plugins/ocp/meson.build @@ -5,5 +5,14 @@ sources += [ 'plugins/ocp/ocp-smart-extended-log.c', 'plugins/ocp/ocp-fw-activation-history.c', 'plugins/ocp/ocp-telemetry-decode.c', + 'plugins/ocp/ocp-hardware-component-log.c', + 'plugins/ocp/ocp-print.c', + 'plugins/ocp/ocp-print-stdout.c', + 'plugins/ocp/ocp-print-binary.c', ] +if json_c_dep.found() + sources += [ + 'plugins/ocp/ocp-print-json.c', + ] +endif diff --git a/plugins/ocp/ocp-fw-activation-history.c b/plugins/ocp/ocp-fw-activation-history.c index 543042f..79c03b2 100644 --- a/plugins/ocp/ocp-fw-activation-history.c +++ b/plugins/ocp/ocp-fw-activation-history.c @@ -14,135 +14,15 @@ #include "nvme-print.h" #include "ocp-utils.h" +#include "ocp-print.h" -static const unsigned char ocp_fw_activation_history_guid[16] = { +static const unsigned char ocp_fw_activation_history_guid[GUID_LEN] = { 0x6D, 0x79, 0x9a, 0x76, 0xb4, 0xda, 0xf6, 0xa3, 0xe2, 0x4d, 0xb2, 0x8a, 0xac, 0xf3, 0x1c, 0xd1 }; -struct __packed fw_activation_history_entry { - __u8 ver_num; - __u8 entry_length; - __u16 reserved1; - __u16 activation_count; - __u64 timestamp; - __u64 reserved2; - __u64 power_cycle_count; - char previous_fw[8]; - char new_fw[8]; - __u8 slot_number; - __u8 commit_action; - __u16 result; - __u8 reserved3[14]; -}; - -struct __packed fw_activation_history { - __u8 log_id; - __u8 reserved1[3]; - __u32 valid_entries; - struct fw_activation_history_entry entries[20]; - __u8 reserved2[2790]; - __u16 log_page_version; - __u64 log_page_guid[2]; -}; - -static void ocp_fw_activation_history_normal(const struct fw_activation_history *fw_history) -{ - printf("Firmware History Log:\n"); - - printf(" %-26s%d\n", "log identifier:", fw_history->log_id); - printf(" %-26s%d\n", "valid entries:", le32_to_cpu(fw_history->valid_entries)); - - printf(" entries:\n"); - - for (int index = 0; index < fw_history->valid_entries; index++) { - const struct fw_activation_history_entry *entry = &fw_history->entries[index]; - - printf(" entry[%d]:\n", le32_to_cpu(index)); - printf(" %-22s%d\n", "version number:", entry->ver_num); - printf(" %-22s%d\n", "entry length:", entry->entry_length); - printf(" %-22s%d\n", "activation count:", - le16_to_cpu(entry->activation_count)); - printf(" %-22s%"PRIu64"\n", "timestamp:", - (0x0000FFFFFFFFFFFF & le64_to_cpu(entry->timestamp))); - printf(" %-22s%"PRIu64"\n", "power cycle count:", - le64_to_cpu(entry->power_cycle_count)); - printf(" %-22s%.*s\n", "previous firmware:", (int)sizeof(entry->previous_fw), - entry->previous_fw); - printf(" %-22s%.*s\n", "new firmware:", (int)sizeof(entry->new_fw), - entry->new_fw); - printf(" %-22s%d\n", "slot number:", entry->slot_number); - printf(" %-22s%d\n", "commit action type:", entry->commit_action); - printf(" %-22s%d\n", "result:", le16_to_cpu(entry->result)); - } - - printf(" %-26s%d\n", "log page version:", - le16_to_cpu(fw_history->log_page_version)); - - printf(" %-26s0x%"PRIx64"%"PRIx64"\n", "log page guid:", - le64_to_cpu(fw_history->log_page_guid[1]), - le64_to_cpu(fw_history->log_page_guid[0])); - - printf("\n"); -} - -static void ocp_fw_activation_history_json(const struct fw_activation_history *fw_history) -{ - struct json_object *root = json_create_object(); - - json_object_add_value_uint(root, "log identifier", fw_history->log_id); - json_object_add_value_uint(root, "valid entries", le32_to_cpu(fw_history->valid_entries)); - - struct json_object *entries = json_create_array(); - - for (int index = 0; index < fw_history->valid_entries; index++) { - const struct fw_activation_history_entry *entry = &fw_history->entries[index]; - struct json_object *entry_obj = json_create_object(); - - json_object_add_value_uint(entry_obj, "version number", entry->ver_num); - json_object_add_value_uint(entry_obj, "entry length", entry->entry_length); - json_object_add_value_uint(entry_obj, "activation count", - le16_to_cpu(entry->activation_count)); - json_object_add_value_uint64(entry_obj, "timestamp", - (0x0000FFFFFFFFFFFF & le64_to_cpu(entry->timestamp))); - json_object_add_value_uint(entry_obj, "power cycle count", - le64_to_cpu(entry->power_cycle_count)); - - struct json_object *fw = json_object_new_string_len(entry->previous_fw, - sizeof(entry->previous_fw)); - - json_object_add_value_object(entry_obj, "previous firmware", fw); - - fw = json_object_new_string_len(entry->new_fw, sizeof(entry->new_fw)); - - json_object_add_value_object(entry_obj, "new firmware", fw); - json_object_add_value_uint(entry_obj, "slot number", entry->slot_number); - json_object_add_value_uint(entry_obj, "commit action type", entry->commit_action); - json_object_add_value_uint(entry_obj, "result", le16_to_cpu(entry->result)); - - json_array_add_value_object(entries, entry_obj); - } - - json_object_add_value_array(root, "entries", entries); - - json_object_add_value_uint(root, "log page version", - le16_to_cpu(fw_history->log_page_version)); - - char guid[2 * sizeof(fw_history->log_page_guid) + 3] = { 0 }; - - sprintf(guid, "0x%"PRIx64"%"PRIx64"", - le64_to_cpu(fw_history->log_page_guid[1]), - le64_to_cpu(fw_history->log_page_guid[0])); - json_object_add_value_string(root, "log page guid", guid); - - json_print_object(root, NULL); - json_free_object(root); - - printf("\n"); -} - int ocp_fw_activation_history_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { @@ -215,10 +95,7 @@ int ocp_fw_activation_history_log(int argc, char **argv, struct command *cmd, return err; } - if (print_flag == JSON) - ocp_fw_activation_history_json(&fw_history); - else if (print_flag == NORMAL) - ocp_fw_activation_history_normal(&fw_history); + ocp_fw_act_history(&fw_history, print_flag); } return err; diff --git a/plugins/ocp/ocp-fw-activation-history.h b/plugins/ocp/ocp-fw-activation-history.h index a7f9058..15733a3 100644 --- a/plugins/ocp/ocp-fw-activation-history.h +++ b/plugins/ocp/ocp-fw-activation-history.h @@ -4,6 +4,8 @@ * * Authors: karl.dedow@solidigm.com */ +#include "common.h" +#include "linux/types.h" #ifndef OCP_FIRMWARE_ACTIVATION_HISTORY_H #define OCP_FIRMWARE_ACTIVATION_HISTORY_H @@ -11,7 +13,33 @@ struct command; struct plugin; -int ocp_fw_activation_history_log(int argc, char **argv, - struct command *cmd, struct plugin *plugin); +struct __packed fw_activation_history_entry { + __u8 ver_num; + __u8 entry_length; + __le16 reserved1; + __le16 activation_count; + __le64 timestamp; + __le64 reserved2; + __le64 power_cycle_count; + char previous_fw[8]; + char new_fw[8]; + __u8 slot_number; + __u8 commit_action; + __le16 result; + __u8 reserved3[14]; +}; + +struct __packed fw_activation_history { + __u8 log_id; + __u8 reserved1[3]; + __le32 valid_entries; + struct fw_activation_history_entry entries[20]; + __u8 reserved2[2790]; + __le16 log_page_version; + __le64 log_page_guid[2]; +}; + +int ocp_fw_activation_history_log(int argc, char **argv, struct command *cmd, + struct plugin *plugin); #endif diff --git a/plugins/ocp/ocp-hardware-component-log.c b/plugins/ocp/ocp-hardware-component-log.c new file mode 100644 index 0000000..73f1452 --- /dev/null +++ b/plugins/ocp/ocp-hardware-component-log.c @@ -0,0 +1,288 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2024 + */ +#include <stdio.h> +#include <errno.h> + +#include "common.h" +#include "util/types.h" +#include "util/logging.h" +#include "nvme-print.h" +#include "ocp-hardware-component-log.h" +#include "ocp-print.h" + +//#define HWCOMP_DUMMY + +#define print_info_array(...) \ + do { \ + if (log_level >= LOG_INFO) \ + print_array(__VA_ARGS__); \ + } while (false) + +#define print_info_error(...) \ + do { \ + if (log_level >= LOG_INFO) \ + fprintf(stderr, __VA_ARGS__); \ + } while (false) + +#ifdef HWCOMP_DUMMY +static __u8 hwcomp_dummy[] = { + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xdc, 0x57, 0x0f, 0x9f, 0xb9, 0x31, 0x6b, 0xb7, + 0xd0, 0x4e, 0xcd, 0x30, 0x1f, 0x82, 0xb6, 0xbc, + 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 +}; +#endif /* HWCOMP_DUMMY */ + +const char *hwcomp_id_to_string(__u32 id) +{ + switch (id) { + case HWCOMP_ID_ASIC: + return "Controller ASIC component"; + case HWCOMP_ID_NAND: + return "NAND Component"; + case HWCOMP_ID_DRAM: + return "DRAM Component"; + case HWCOMP_ID_PMIC: + return "PMIC Component"; + case HWCOMP_ID_PCB: + return "PCB Component"; + case HWCOMP_ID_CAP: + return "capacitor component"; + case HWCOMP_ID_REG: + return "registor component"; + case HWCOMP_ID_CASE: + return "case component"; + case HWCOMP_ID_SN: + return "Device Serial Number"; + case HWCOMP_ID_COUNTRY: + return "Country of Origin"; + case HWCOMP_ID_HW_REV: + return "Global Device Hardware Revision"; + case HWCOMP_ID_VENDOR ... HWCOMP_ID_MAX: + return "Vendor Unique Component"; + case HWCOMP_ID_RSVD: + default: + break; + } + + return "Reserved"; +} + +static int get_hwcomp_log_data(struct nvme_dev *dev, struct hwcomp_log *log) +{ + int ret = 0; + size_t desc_offset = offsetof(struct hwcomp_log, desc); + struct nvme_get_log_args args = { + .lpo = desc_offset, + .args_size = sizeof(args), + .fd = dev_fd(dev), + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .lid = LID_HWCOMP, + .nsid = NVME_NSID_ALL, + }; + +#ifdef HWCOMP_DUMMY + memcpy(log, hwcomp_dummy, desc_offset); +#else /* HWCOMP_DUMMY */ + ret = nvme_get_log_simple(dev_fd(dev), LID_HWCOMP, desc_offset, log); + if (ret) { + print_info_error("error: ocp: failed to get log simple (hwcomp: %02X, ret: %d)\n", + LID_HWCOMP, ret); + return ret; + } +#endif /* HWCOMP_DUMMY */ + + print_info("id: %02Xh\n", LID_HWCOMP); + print_info("version: %04Xh\n", log->ver); + print_info_array("guid", log->guid, ARRAY_SIZE(log->guid)); + print_info("size: %s\n", uint128_t_to_string(le128_to_cpu(log->size))); + + args.len = uint128_t_to_double(le128_to_cpu(log->size)) * sizeof(__le32); + log->desc = calloc(1, args.len); + if (!log->desc) { + fprintf(stderr, "error: ocp: calloc: %s\n", strerror(errno)); + return -1; + } + + args.log = log->desc, + +#ifdef HWCOMP_DUMMY + memcpy(log->desc, &hwcomp_dummy[desc_offset], args.len); +#else /* HWCOMP_DUMMY */ + ret = nvme_get_log_page(dev_fd(dev), NVME_LOG_PAGE_PDU_SIZE, &args); + if (ret) { + print_info_error("error: ocp: failed to get log page (hwcomp: %02X, ret: %d)\n", + LID_HWCOMP, ret); + return ret; + } +#endif /* HWCOMP_DUMMY */ + + return ret; +} + +static int get_hwcomp_log(struct nvme_dev *dev, __u32 id, bool list) +{ + _cleanup_free_ __u8 *desc = NULL; + + int ret; + nvme_print_flags_t fmt; + struct hwcomp_log log = { + .desc = (struct hwcomp_desc *)desc, + }; + + ret = validate_output_format(nvme_cfg.output_format, &fmt); + if (ret < 0) { + fprintf(stderr, "error: ocp: invalid output format\n"); + return ret; + } + + ret = get_hwcomp_log_data(dev, &log); + if (ret) { + print_info_error("error: ocp: failed get hwcomp log: %02X data, ret: %d\n", + LID_HWCOMP, ret); + return ret; + } + + ocp_show_hwcomp_log(&log, id, list, fmt); + + return 0; +} + +int ocp_hwcomp_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + int ret = 0; + const char *desc = "retrieve hardware component log"; + struct config { + __u64 id; + bool list; + } cfg = { 0 }; + const char *id_desc = "component identifier"; + const char *list_desc = "list component descriptions"; + + OPT_VALS(id) = { + VAL_LONG("asic", HWCOMP_ID_ASIC), + VAL_LONG("nand", HWCOMP_ID_NAND), + VAL_LONG("dram", HWCOMP_ID_DRAM), + VAL_LONG("pmic", HWCOMP_ID_PMIC), + VAL_LONG("pcb", HWCOMP_ID_PCB), + VAL_LONG("cap", HWCOMP_ID_CAP), + VAL_LONG("reg", HWCOMP_ID_REG), + VAL_LONG("case", HWCOMP_ID_CASE), + VAL_LONG("sn", HWCOMP_ID_SN), + VAL_LONG("country", HWCOMP_ID_COUNTRY), + VAL_LONG("hw-rev", HWCOMP_ID_HW_REV), + VAL_LONG("vendor", HWCOMP_ID_VENDOR), + VAL_END() + }; + + NVME_ARGS(opts, OPT_LONG("comp-id", 'i', &cfg.id, id_desc, id), + OPT_FLAG("list", 'l', &cfg.list, list_desc)); + + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; + + ret = get_hwcomp_log(dev, cfg.id, cfg.list); + if (ret) + fprintf(stderr, "error: ocp: failed to get hwcomp log: %02X, ret: %d\n", LID_HWCOMP, + ret); + + return ret; +} diff --git a/plugins/ocp/ocp-hardware-component-log.h b/plugins/ocp/ocp-hardware-component-log.h new file mode 100644 index 0000000..f5e5162 --- /dev/null +++ b/plugins/ocp/ocp-hardware-component-log.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (c) 2024 + */ +#include "cmd.h" +#include "common.h" +#include "ocp-nvme.h" + +#ifndef OCP_HARDWARE_COMPONENT_LOG_H +#define OCP_HARDWARE_COMPONENT_LOG_H + +#define LID_HWCOMP 0xc6 +#define HWCOMP_RSVD2_LEN 14 +#define HWCOMP_SIZE_LEN 16 +#define HWCOMP_RSVD48_LEN 16 + +struct __packed hwcomp_desc { + __le64 date_lot_size; + __le64 add_info_size; + __le32 id; + __le64 mfg; + __le64 rev; + __le64 mfg_code; +}; + +struct __packed hwcomp_log { + __le16 ver; + __u8 rsvd2[HWCOMP_RSVD2_LEN]; + __u8 guid[GUID_LEN]; + __u8 size[HWCOMP_SIZE_LEN]; + __u8 rsvd48[HWCOMP_RSVD48_LEN]; + struct hwcomp_desc *desc; +}; + +struct hwcomp_desc_entry { + struct hwcomp_desc *desc; + __u64 date_lot_size; + __u8 *date_lot_code; + __u64 add_info_size; + __u8 *add_info; + __u64 desc_size; +}; + +enum hwcomp_id { + HWCOMP_ID_RSVD, + HWCOMP_ID_ASIC, + HWCOMP_ID_NAND, + HWCOMP_ID_DRAM, + HWCOMP_ID_PMIC, + HWCOMP_ID_PCB, + HWCOMP_ID_CAP, + HWCOMP_ID_REG, + HWCOMP_ID_CASE, + HWCOMP_ID_SN, + HWCOMP_ID_COUNTRY, + HWCOMP_ID_HW_REV, + HWCOMP_ID_VENDOR = 0x8000, + HWCOMP_ID_MAX = 0xffff, +}; + +int ocp_hwcomp_log(int argc, char **argv, struct command *cmd, struct plugin *plugin); +const char *hwcomp_id_to_string(__u32 id); + +#endif /* OCP_HARDWARE_COMPONENT_LOG_H */ diff --git a/plugins/ocp/ocp-nvme.c b/plugins/ocp/ocp-nvme.c index 91f4083..6f05750 100644 --- a/plugins/ocp/ocp-nvme.c +++ b/plugins/ocp/ocp-nvme.c @@ -22,6 +22,7 @@ #include "plugin.h" #include "linux/types.h" #include "util/types.h" +#include "util/logging.h" #include "nvme-print.h" #include "nvme-wrap.h" @@ -29,6 +30,8 @@ #include "ocp-clear-features.h" #include "ocp-fw-activation-history.h" #include "ocp-telemetry-decode.h" +#include "ocp-hardware-component-log.h" +#include "ocp-print.h" #define CREATE_CMD #include "ocp-nvme.h" @@ -42,76 +45,29 @@ #define C3_LATENCY_MON_LOG_BUF_LEN 0x200 #define C3_LATENCY_MON_OPCODE 0xC3 -#define C3_LATENCY_MON_VERSION 0x0001 -#define C3_GUID_LENGTH 16 #define NVME_FEAT_OCP_LATENCY_MONITOR 0xC5 -#define C3_ACTIVE_BUCKET_TIMER_INCREMENT 5 -#define C3_ACTIVE_THRESHOLD_INCREMENT 5 -#define C3_MINIMUM_WINDOW_INCREMENT 100 -#define C3_BUCKET_NUM 4 - -static __u8 lat_mon_guid[C3_GUID_LENGTH] = { +static __u8 lat_mon_guid[GUID_LEN] = { 0x92, 0x7a, 0xc0, 0x8c, 0xd0, 0x84, 0x6c, 0x9c, 0x70, 0x43, 0xe6, 0xd4, 0x58, 0x5e, 0xd4, 0x85 }; -#define READ 3 -#define WRITE 2 -#define TRIM 1 #define RESERVED 0 -struct __packed ssd_latency_monitor_log { - __u8 feature_status; /* 0x00 */ - __u8 rsvd1; /* 0x01 */ - __le16 active_bucket_timer; /* 0x02 */ - __le16 active_bucket_timer_threshold; /* 0x04 */ - __u8 active_threshold_a; /* 0x06 */ - __u8 active_threshold_b; /* 0x07 */ - __u8 active_threshold_c; /* 0x08 */ - __u8 active_threshold_d; /* 0x09 */ - __le16 active_latency_config; /* 0x0A */ - __u8 active_latency_min_window; /* 0x0C */ - __u8 rsvd2[0x13]; /* 0x0D */ - - __le32 active_bucket_counter[4][4]; /* 0x20 - 0x5F */ - __le64 active_latency_timestamp[4][3]; /* 0x60 - 0xBF */ - __le16 active_measured_latency[4][3]; /* 0xC0 - 0xD7 */ - __le16 active_latency_stamp_units; /* 0xD8 */ - __u8 rsvd3[0x16]; /* 0xDA */ - - __le32 static_bucket_counter[4][4]; /* 0x0F0 - 0x12F */ - __le64 static_latency_timestamp[4][3]; /* 0x130 - 0x18F */ - __le16 static_measured_latency[4][3]; /* 0x190 - 0x1A7 */ - __le16 static_latency_stamp_units; /* 0x1A8 */ - __u8 rsvd4[0x16]; /* 0x1AA */ - - __le16 debug_log_trigger_enable; /* 0x1C0 */ - __le16 debug_log_measured_latency; /* 0x1C2 */ - __le64 debug_log_latency_stamp; /* 0x1C4 */ - __le16 debug_log_ptr; /* 0x1CC */ - __le16 debug_log_counter_trigger; /* 0x1CE */ - __u8 debug_log_stamp_units; /* 0x1D0 */ - __u8 rsvd5[0x1D]; /* 0x1D1 */ - - __le16 log_page_version; /* 0x1EE */ - __u8 log_page_guid[0x10]; /* 0x1F0 */ -}; - struct __packed feature_latency_monitor { - __u16 active_bucket_timer_threshold; - __u8 active_threshold_a; - __u8 active_threshold_b; - __u8 active_threshold_c; - __u8 active_threshold_d; - __u16 active_latency_config; - __u8 active_latency_minimum_window; - __u16 debug_log_trigger_enable; - __u8 discard_debug_log; - __u8 latency_monitor_feature_enable; - __u8 reserved[4083]; + __le16 active_bucket_timer_threshold; + __u8 active_threshold_a; + __u8 active_threshold_b; + __u8 active_threshold_c; + __u8 active_threshold_d; + __le16 active_latency_config; + __u8 active_latency_minimum_window; + __le16 debug_log_trigger_enable; + __u8 discard_debug_log; + __u8 latency_monitor_feature_enable; + __u8 reserved[4083]; }; struct erri_entry { @@ -194,6 +150,11 @@ struct erri_config { __u16 nrtdp; }; +struct ieee1667_get_cq_entry { + __u32 enabled:3; + __u32 rsvd3:29; +}; + static const char *sel = "[0-3]: current/default/saved/supported"; static const char *no_uuid = "Skip UUID index search (UUID index not required for OCP 1.0)"; const char *data = "Error injection data structure entries"; @@ -201,288 +162,6 @@ const char *number = "Number of valid error injection data entries"; static const char *type = "Error injection type"; static const char *nrtdp = "Number of reads to trigger device panic"; -static int ocp_print_C3_log_normal(struct nvme_dev *dev, - struct ssd_latency_monitor_log *log_data) -{ - char ts_buf[128]; - int i, j; - - printf("-Latency Monitor/C3 Log Page Data-\n"); - printf(" Controller : %s\n", dev->name); - printf(" Feature Status 0x%x\n", - log_data->feature_status); - printf(" Active Bucket Timer %d min\n", - C3_ACTIVE_BUCKET_TIMER_INCREMENT * - le16_to_cpu(log_data->active_bucket_timer)); - printf(" Active Bucket Timer Threshold %d min\n", - C3_ACTIVE_BUCKET_TIMER_INCREMENT * - le16_to_cpu(log_data->active_bucket_timer_threshold)); - printf(" Active Threshold A %d ms\n", - C3_ACTIVE_THRESHOLD_INCREMENT * - le16_to_cpu(log_data->active_threshold_a+1)); - printf(" Active Threshold B %d ms\n", - C3_ACTIVE_THRESHOLD_INCREMENT * - le16_to_cpu(log_data->active_threshold_b+1)); - printf(" Active Threshold C %d ms\n", - C3_ACTIVE_THRESHOLD_INCREMENT * - le16_to_cpu(log_data->active_threshold_c+1)); - 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", - le16_to_cpu(log_data->active_latency_config)); - printf(" Active Latency Minimum Window %d ms\n", - C3_MINIMUM_WINDOW_INCREMENT * - le16_to_cpu(log_data->active_latency_min_window)); - printf(" Active Latency Stamp Units %d\n", - le16_to_cpu(log_data->active_latency_stamp_units)); - printf(" Static Latency Stamp Units %d\n", - le16_to_cpu(log_data->static_latency_stamp_units)); - printf(" Debug Log Trigger Enable %d\n", - le16_to_cpu(log_data->debug_log_trigger_enable)); - printf(" Debug Log Measured Latency %d\n", - le16_to_cpu(log_data->debug_log_measured_latency)); - if (le64_to_cpu(log_data->debug_log_latency_stamp) == -1) { - printf(" Debug Log Latency Time Stamp N/A\n"); - } else { - convert_ts(le64_to_cpu(log_data->debug_log_latency_stamp), ts_buf); - printf(" Debug Log Latency Time Stamp %s\n", ts_buf); - } - printf(" Debug Log Pointer %d\n", - le16_to_cpu(log_data->debug_log_ptr)); - printf(" Debug Counter Trigger Source %d\n", - le16_to_cpu(log_data->debug_log_counter_trigger)); - printf(" Debug Log Stamp Units %d\n", - le16_to_cpu(log_data->debug_log_stamp_units)); - printf(" Log Page Version %d\n", - le16_to_cpu(log_data->log_page_version)); - - char guid[(C3_GUID_LENGTH * 2) + 1]; - char *ptr = &guid[0]; - - for (i = C3_GUID_LENGTH - 1; i >= 0; i--) - ptr += sprintf(ptr, "%02X", log_data->log_page_guid[i]); - - printf(" Log Page GUID %s\n", guid); - printf("\n"); - - printf(" Read Write Deallocate/Trim\n"); - for (i = 0; i < C3_BUCKET_NUM; i++) { - printf(" Active Bucket Counter: Bucket %d %27d %27d %27d\n", - i, - le32_to_cpu(log_data->active_bucket_counter[i][READ]), - le32_to_cpu(log_data->active_bucket_counter[i][WRITE]), - le32_to_cpu(log_data->active_bucket_counter[i][TRIM])); - } - - for (i = 0; i < C3_BUCKET_NUM; i++) { - printf(" Active Latency Time Stamp: Bucket %d ", i); - for (j = 2; j >= 0; j--) { - if (le64_to_cpu(log_data->active_latency_timestamp[3-i][j]) == -1) { - printf(" N/A "); - } else { - convert_ts(le64_to_cpu(log_data->active_latency_timestamp[3-i][j]), ts_buf); - printf("%s ", ts_buf); - } - } - printf("\n"); - } - - for (i = 0; i < C3_BUCKET_NUM; i++) { - printf(" Active Measured Latency: Bucket %d %27d ms %27d ms %27d ms\n", - i, - le16_to_cpu(log_data->active_measured_latency[3-i][READ-1]), - le16_to_cpu(log_data->active_measured_latency[3-i][WRITE-1]), - le16_to_cpu(log_data->active_measured_latency[3-i][TRIM-1])); - } - - printf("\n"); - for (i = 0; i < C3_BUCKET_NUM; i++) { - printf(" Static Bucket Counter: Bucket %d %27d %27d %27d\n", - i, - le32_to_cpu(log_data->static_bucket_counter[i][READ]), - le32_to_cpu(log_data->static_bucket_counter[i][WRITE]), - le32_to_cpu(log_data->static_bucket_counter[i][TRIM])); - } - - for (i = 0; i < C3_BUCKET_NUM; i++) { - printf(" Static Latency Time Stamp: Bucket %d ", i); - for (j = 2; j >= 0; j--) { - if (le64_to_cpu(log_data->static_latency_timestamp[3-i][j]) == -1) { - printf(" N/A "); - } else { - convert_ts(le64_to_cpu(log_data->static_latency_timestamp[3-i][j]), ts_buf); - printf("%s ", ts_buf); - } - } - printf("\n"); - } - - for (i = 0; i < C3_BUCKET_NUM; i++) { - printf(" Static Measured Latency: Bucket %d %27d ms %27d ms %27d ms\n", - i, - le16_to_cpu(log_data->static_measured_latency[3-i][READ-1]), - le16_to_cpu(log_data->static_measured_latency[3-i][WRITE-1]), - le16_to_cpu(log_data->static_measured_latency[3-i][TRIM-1])); - } - - return 0; -} - -static void ocp_print_C3_log_json(struct ssd_latency_monitor_log *log_data) -{ - struct json_object *root; - char ts_buf[128]; - char buf[128]; - int i, j; - char *operation[3] = {"Trim", "Write", "Read"}; - - root = json_create_object(); - - json_object_add_value_uint(root, "Feature Status", - log_data->feature_status); - json_object_add_value_uint(root, "Active Bucket Timer", - C3_ACTIVE_BUCKET_TIMER_INCREMENT * - le16_to_cpu(log_data->active_bucket_timer)); - json_object_add_value_uint(root, "Active Bucket Timer Threshold", - C3_ACTIVE_BUCKET_TIMER_INCREMENT * - le16_to_cpu(log_data->active_bucket_timer_threshold)); - json_object_add_value_uint(root, "Active Threshold A", - C3_ACTIVE_THRESHOLD_INCREMENT * - le16_to_cpu(log_data->active_threshold_a + 1)); - json_object_add_value_uint(root, "Active Threshold B", - C3_ACTIVE_THRESHOLD_INCREMENT * - le16_to_cpu(log_data->active_threshold_b + 1)); - json_object_add_value_uint(root, "Active Threshold C", - C3_ACTIVE_THRESHOLD_INCREMENT * - le16_to_cpu(log_data->active_threshold_c + 1)); - json_object_add_value_uint(root, "Active Threshold D", - C3_ACTIVE_THRESHOLD_INCREMENT * - le16_to_cpu(log_data->active_threshold_d + 1)); - json_object_add_value_uint(root, "Active Latency Configuration", - le16_to_cpu(log_data->active_latency_config)); - json_object_add_value_uint(root, "Active Latency Minimum Window", - C3_MINIMUM_WINDOW_INCREMENT * - le16_to_cpu(log_data->active_latency_min_window)); - - for (i = 0; i < C3_BUCKET_NUM; i++) { - struct json_object *bucket; - - bucket = json_create_object(); - sprintf(buf, "Active Bucket Counter: Bucket %d", i); - for (j = 2; j >= 0; j--) { - json_object_add_value_uint(bucket, operation[j], - le32_to_cpu(log_data->active_bucket_counter[i][j+1])); - } - json_object_add_value_object(root, buf, bucket); - } - - for (i = 0; i < C3_BUCKET_NUM; i++) { - struct json_object *bucket; - - bucket = json_create_object(); - sprintf(buf, "Active Latency Time Stamp: Bucket %d", i); - for (j = 2; j >= 0; j--) { - if (le64_to_cpu(log_data->active_latency_timestamp[3-i][j]) == -1) { - json_object_add_value_string(bucket, operation[j], "NA"); - } else { - convert_ts(le64_to_cpu(log_data->active_latency_timestamp[3-i][j]), ts_buf); - json_object_add_value_string(bucket, operation[j], ts_buf); - } - } - json_object_add_value_object(root, buf, bucket); - } - - for (i = 0; i < C3_BUCKET_NUM; i++) { - struct json_object *bucket; - - bucket = json_create_object(); - sprintf(buf, "Active Measured Latency: Bucket %d", i); - for (j = 2; j >= 0; j--) { - json_object_add_value_uint(bucket, operation[j], - le16_to_cpu(log_data->active_measured_latency[3-i][j])); - } - json_object_add_value_object(root, buf, bucket); - } - - json_object_add_value_uint(root, "Active Latency Stamp Units", - le16_to_cpu(log_data->active_latency_stamp_units)); - - for (i = 0; i < C3_BUCKET_NUM; i++) { - struct json_object *bucket; - - bucket = json_create_object(); - sprintf(buf, "Static Bucket Counter: Bucket %d", i); - for (j = 2; j >= 0; j--) { - json_object_add_value_uint(bucket, operation[j], - le32_to_cpu(log_data->static_bucket_counter[i][j+1])); - } - json_object_add_value_object(root, buf, bucket); - } - - for (i = 0; i < C3_BUCKET_NUM; i++) { - struct json_object *bucket; - - bucket = json_create_object(); - sprintf(buf, "Static Latency Time Stamp: Bucket %d", i); - for (j = 2; j >= 0; j--) { - if (le64_to_cpu(log_data->static_latency_timestamp[3-i][j]) == -1) { - json_object_add_value_string(bucket, operation[j], "NA"); - } else { - convert_ts(le64_to_cpu(log_data->static_latency_timestamp[3-i][j]), ts_buf); - json_object_add_value_string(bucket, operation[j], ts_buf); - } - } - json_object_add_value_object(root, buf, bucket); - } - - for (i = 0; i < C3_BUCKET_NUM; i++) { - struct json_object *bucket; - - bucket = json_create_object(); - sprintf(buf, "Static Measured Latency: Bucket %d", i); - for (j = 2; j >= 0; j--) { - json_object_add_value_uint(bucket, operation[j], - le16_to_cpu(log_data->static_measured_latency[3-i][j])); - } - json_object_add_value_object(root, buf, bucket); - } - - json_object_add_value_uint(root, "Static Latency Stamp Units", - le16_to_cpu(log_data->static_latency_stamp_units)); - json_object_add_value_uint(root, "Debug Log Trigger Enable", - le16_to_cpu(log_data->debug_log_trigger_enable)); - json_object_add_value_uint(root, "Debug Log Measured Latency", - le16_to_cpu(log_data->debug_log_measured_latency)); - if (le64_to_cpu(log_data->debug_log_latency_stamp) == -1) { - json_object_add_value_string(root, "Debug Log Latency Time Stamp", "NA"); - } else { - convert_ts(le64_to_cpu(log_data->debug_log_latency_stamp), ts_buf); - json_object_add_value_string(root, "Debug Log Latency Time Stamp", ts_buf); - } - json_object_add_value_uint(root, "Debug Log Pointer", - le16_to_cpu(log_data->debug_log_ptr)); - json_object_add_value_uint(root, "Debug Counter Trigger Source", - le16_to_cpu(log_data->debug_log_counter_trigger)); - json_object_add_value_uint(root, "Debug Log Stamp Units", - le16_to_cpu(log_data->debug_log_stamp_units)); - json_object_add_value_uint(root, "Log Page Version", - le16_to_cpu(log_data->log_page_version)); - - char guid[(C3_GUID_LENGTH * 2) + 1]; - char *ptr = &guid[0]; - - for (i = C3_GUID_LENGTH - 1; i >= 0; i--) - ptr += sprintf(ptr, "%02X", log_data->log_page_guid[i]); - - json_object_add_value_string(root, "Log Page GUID", guid); - - json_print_object(root, NULL); - printf("\n"); - - json_free_object(root); -} - static int get_c3_log_page(struct nvme_dev *dev, char *format) { struct ssd_latency_monitor_log *log_data; @@ -513,14 +192,6 @@ static int get_c3_log_page(struct nvme_dev *dev, char *format) if (!ret) { log_data = (struct ssd_latency_monitor_log *)data; - /* check log page version */ - if (log_data->log_page_version != C3_LATENCY_MON_VERSION) { - fprintf(stderr, - "ERROR : OCP : invalid latency monitor version\n"); - ret = -1; - goto out; - } - /* * check log page guid * Verify GUID matches @@ -532,32 +203,20 @@ static int get_c3_log_page(struct nvme_dev *dev, char *format) fprintf(stderr, "ERROR : OCP : Unknown GUID in C3 Log Page data\n"); fprintf(stderr, "ERROR : OCP : Expected GUID: 0x"); for (j = 0; j < 16; j++) - fprintf(stderr, "%x", lat_mon_guid[j]); + fprintf(stderr, "%02x", lat_mon_guid[j]); fprintf(stderr, "\nERROR : OCP : Actual GUID: 0x"); for (j = 0; j < 16; j++) - fprintf(stderr, "%x", log_data->log_page_guid[j]); + fprintf(stderr, "%02x", log_data->log_page_guid[j]); fprintf(stderr, "\n"); ret = -1; goto out; } } - - switch (fmt) { - case NORMAL: - ocp_print_C3_log_normal(dev, log_data); - break; - case JSON: - ocp_print_C3_log_json(log_data); - break; - default: - fprintf(stderr, "unhandled output format\n"); - - } + ocp_c3_log(dev, log_data, fmt); } else { - fprintf(stderr, - "ERROR : OCP : Unable to read C3 data from buffer\n"); + fprintf(stderr, "ERROR : OCP : Unable to read C3 data from buffer\n"); } out: @@ -606,7 +265,7 @@ int ocp_set_latency_monitor_feature(int argc, char **argv, struct command *cmd, int err = -1; struct nvme_dev *dev; __u32 result; - struct feature_latency_monitor buf = {0,}; + struct feature_latency_monitor buf = { 0 }; __u32 nsid = NVME_NSID_ALL; struct stat nvme_stat; struct nvme_id_ctrl ctrl; @@ -683,16 +342,14 @@ int ocp_set_latency_monitor_feature(int argc, char **argv, struct command *cmd, if (err) return err; - memset(&buf, 0, sizeof(struct feature_latency_monitor)); - - buf.active_bucket_timer_threshold = cfg.active_bucket_timer_threshold; + buf.active_bucket_timer_threshold = cpu_to_le16(cfg.active_bucket_timer_threshold); buf.active_threshold_a = cfg.active_threshold_a; buf.active_threshold_b = cfg.active_threshold_b; buf.active_threshold_c = cfg.active_threshold_c; buf.active_threshold_d = cfg.active_threshold_d; - buf.active_latency_config = cfg.active_latency_config; + buf.active_latency_config = cpu_to_le16(cfg.active_latency_config); buf.active_latency_minimum_window = cfg.active_latency_minimum_window; - buf.debug_log_trigger_enable = cfg.debug_log_trigger_enable; + buf.debug_log_trigger_enable = cpu_to_le16(cfg.debug_log_trigger_enable); buf.discard_debug_log = cfg.discard_debug_log; buf.latency_monitor_feature_enable = cfg.latency_monitor_feature_enable; @@ -714,14 +371,16 @@ int ocp_set_latency_monitor_feature(int argc, char **argv, struct command *cmd, perror("set-feature"); } else if (!err) { printf("NVME_FEAT_OCP_LATENCY_MONITOR: 0x%02x\n", NVME_FEAT_OCP_LATENCY_MONITOR); - printf("active bucket timer threshold: 0x%x\n", buf.active_bucket_timer_threshold); + printf("active bucket timer threshold: 0x%x\n", + le16_to_cpu(buf.active_bucket_timer_threshold)); printf("active threshold a: 0x%x\n", buf.active_threshold_a); printf("active threshold b: 0x%x\n", buf.active_threshold_b); printf("active threshold c: 0x%x\n", buf.active_threshold_c); printf("active threshold d: 0x%x\n", buf.active_threshold_d); - printf("active latency config: 0x%x\n", buf.active_latency_config); + printf("active latency config: 0x%x\n", le16_to_cpu(buf.active_latency_config)); printf("active latency minimum window: 0x%x\n", buf.active_latency_minimum_window); - printf("debug log trigger enable: 0x%x\n", buf.debug_log_trigger_enable); + printf("debug log trigger enable: 0x%x\n", + le16_to_cpu(buf.debug_log_trigger_enable)); printf("discard debug log: 0x%x\n", buf.discard_debug_log); printf("latency monitor feature enable: 0x%x\n", buf.latency_monitor_feature_enable); } else if (err > 0) { @@ -912,6 +571,7 @@ __u8 *pC9_string_buffer; static void get_serial_number(struct nvme_id_ctrl *ctrl, char *sn) { int i; + /* Remove trailing spaces from the name */ for (i = 0; i < sizeof(ctrl->sn); i++) { if (ctrl->sn[i] == ' ') @@ -920,8 +580,7 @@ static void get_serial_number(struct nvme_id_ctrl *ctrl, char *sn) } } -static void print_telemetry_header(struct telemetry_initiated_log *logheader, - int tele_type) +static void print_telemetry_header(struct telemetry_initiated_log *logheader, int tele_type) { if (logheader) { unsigned int i = 0, j = 0; @@ -973,16 +632,14 @@ static int get_telemetry_data(struct nvme_dev *dev, __u32 ns, __u8 tele_type, __u16 numdu = numd >> 16; __u16 numdl = numd & 0xffff; - cmd.cdw10 = tele_type | - (nLSP & 0x0F) << 8 | - (nRAE & 0x01) << 15 | - (numdl & 0xFFFF) << 16; + cmd.cdw10 = tele_type | (nLSP & 0x0F) << 8 | (nRAE & 0x01) << 15 | (numdl & 0xFFFF) << 16; cmd.cdw11 = numdu; cmd.cdw12 = (__u32)(0x00000000FFFFFFFF & offset); cmd.cdw13 = (__u32)((0xFFFFFFFF00000000 & offset) >> 8); cmd.cdw14 = 0; return nvme_submit_admin_passthru(dev_fd(dev), &cmd, NULL); } + static void print_telemetry_data_area_1(struct telemetry_data_area_1 *da1, int tele_type) { @@ -1004,19 +661,19 @@ static void print_telemetry_data_area_1(struct telemetry_data_area_1 *da1, da1->no_of_tps_supp); printf("Telemetry Profile Selected (TPS) : 0x%x\n", da1->tps); - printf("Telemetry String Log Size (SLS) : 0x%lx\n", - le64_to_cpu(da1->sls)); + printf("Telemetry String Log Size (SLS) : 0x%"PRIx64"\n", + le64_to_cpu(da1->sls)); printf("Firmware Revision : "); for (i = 0; i < 8; i++) printf("%c", (char)da1->fw_revision[i]); printf("\n"); - printf("Data Area 1 Statistic Start : 0x%lx\n", + printf("Data Area 1 Statistic Start : 0x%"PRIx64"\n", le64_to_cpu(da1->da1_stat_start)); - printf("Data Area 1 Statistic Size : 0x%lx\n", + printf("Data Area 1 Statistic Size : 0x%"PRIx64"\n", le64_to_cpu(da1->da1_stat_size)); - printf("Data Area 2 Statistic Start : 0x%lx\n", + printf("Data Area 2 Statistic Start : 0x%"PRIx64"\n", le64_to_cpu(da1->da2_stat_start)); - printf("Data Area 2 Statistic Size : 0x%lx\n", + printf("Data Area 2 Statistic Size : 0x%"PRIx64"\n", le64_to_cpu(da1->da2_stat_size)); for (i = 0; i < 16; i++) { printf("Event FIFO %d Data Area : 0x%x\n", @@ -1041,10 +698,9 @@ static void print_telemetry_data_area_1(struct telemetry_data_area_1 *da1, printf("===============================================\n\n"); } } -static void print_telemetry_da_stat(struct telemetry_stats_desc *da_stat, - int tele_type, - __u16 buf_size, - __u8 data_area) + +static void print_telemetry_da_stat(struct telemetry_stats_desc *da_stat, int tele_type, + __u16 buf_size, __u8 data_area) { if (da_stat) { unsigned int i = 0; @@ -1052,14 +708,14 @@ static void print_telemetry_da_stat(struct telemetry_stats_desc *da_stat, if (tele_type == TELEMETRY_TYPE_HOST) printf("============ Telemetry Host Data Area %d Statistics ============\n", - data_area); + data_area); else printf("========= Telemetry Controller Data Area %d Statistics =========\n", - data_area); + data_area); 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); + next_da_stat = (struct telemetry_stats_desc *)((void *)da_stat + i); if ((next_da_stat->id == 0) && (next_da_stat->size == 0)) break; @@ -1068,13 +724,13 @@ static void print_telemetry_da_stat(struct telemetry_stats_desc *da_stat, } } static void print_telemetry_da_fifo(struct telemetry_event_desc *da_fifo, - __le64 buf_size, + __u64 buf_size, int tele_type, int da, int index) { if (da_fifo) { - unsigned int i = 0; + __u64 i = 0; struct telemetry_event_desc *next_da_fifo = da_fifo; if (tele_type == TELEMETRY_TYPE_HOST) @@ -1084,8 +740,11 @@ static void print_telemetry_da_fifo(struct telemetry_event_desc *da_fifo, printf("====== Telemetry Controller Data area %d Event FIFO %d ======\n", da, index); - while ((i + 4) < buf_size) { + /* break if last entry */ + if (next_da_fifo->class == 0) + break; + /* Print Event Data */ print_telemetry_fifo_event(next_da_fifo->class, /* Event class type */ next_da_fifo->id, /* Event ID */ @@ -1093,7 +752,7 @@ static void print_telemetry_da_fifo(struct telemetry_event_desc *da_fifo, (__u8 *)&next_da_fifo->data); /* Event data */ i += (4 + (next_da_fifo->size * 4)); - next_da_fifo = (struct telemetry_event_desc *)((__u64)da_fifo + i); + next_da_fifo = (struct telemetry_event_desc *)((void *)da_fifo + i); } printf("===============================================\n\n"); } @@ -1183,8 +842,8 @@ static int get_telemetry_dump(struct nvme_dev *dev, char *filename, char *sn, enum TELEMETRY_TYPE tele_type, int data_area, bool header_print) { __u32 err = 0, nsid = 0; - __le64 da1_sz = 512, m_512_sz = 0, da1_off = 0, m_512_off = 0, diff = 0, - temp_sz = 0, temp_ofst = 0; + __u64 da1_sz = 512, m_512_sz = 0, da1_off = 0, m_512_off = 0, diff = 0, temp_sz = 0, + temp_ofst = 0; __u8 lsp = 0, rae = 0, flag = 0; __u8 data[TELEMETRY_HEADER_SIZE] = { 0 }; unsigned int i = 0; @@ -1212,8 +871,8 @@ static int get_telemetry_dump(struct nvme_dev *dev, char *filename, char *sn, } /* Get the telemetry header */ - err = get_telemetry_data(dev, nsid, tele_type, TELEMETRY_HEADER_SIZE, - (void *)data, lsp, rae, 0); + err = get_telemetry_data(dev, nsid, tele_type, TELEMETRY_HEADER_SIZE, (void *)data, lsp, + rae, 0); if (err) { printf("get_telemetry_header failed, err: %d.\n", err); return err; @@ -1223,8 +882,8 @@ static int get_telemetry_dump(struct nvme_dev *dev, char *filename, char *sn, print_telemetry_header(logheader, tele_type); /* Get the telemetry data */ - err = get_telemetry_data(dev, nsid, tele_type, TELEMETRY_DATA_SIZE, - (void *)data1, lsp, rae, 512); + err = get_telemetry_data(dev, nsid, tele_type, TELEMETRY_DATA_SIZE, (void *)data1, lsp, + rae, 512); if (err) { printf("get_telemetry_data failed for type: 0x%x, err: %d.\n", tele_type, err); return err; @@ -1235,26 +894,26 @@ static int get_telemetry_dump(struct nvme_dev *dev, char *filename, char *sn, /* Print the Data Area 1 Stats */ if (da1->da1_stat_size != 0) { diff = 0; - da1_sz = (da1->da1_stat_size) * 4; - m_512_sz = (da1->da1_stat_size) * 4; - da1_off = (da1->da1_stat_start) * 4; - m_512_off = (da1->da1_stat_start) * 4; - temp_sz = (da1->da1_stat_size) * 4; - temp_ofst = (da1->da1_stat_start) * 4; + da1_sz = le64_to_cpu(da1->da1_stat_size) * 4; + m_512_sz = le64_to_cpu(da1->da1_stat_size) * 4; + da1_off = le64_to_cpu(da1->da1_stat_start) * 4; + m_512_off = le64_to_cpu(da1->da1_stat_start) * 4; + temp_sz = le64_to_cpu(da1->da1_stat_size) * 4; + temp_ofst = le64_to_cpu(da1->da1_stat_start) * 4; flag = 0; if ((da1_off % 512) > 0) { - m_512_off = (__le64) ((da1_off / 512)); + m_512_off = (da1_off / 512); da1_off = m_512_off * 512; diff = temp_ofst - da1_off; flag = 1; } - if (da1_sz < 512) + if (da1_sz < 512) { da1_sz = 512; - else if ((da1_sz % 512) > 0) { + } else if ((da1_sz % 512) > 0) { if (flag == 0) { - m_512_sz = (__le64) ((da1_sz / 512) + 1); + m_512_sz = (da1_sz / 512) + 1; da1_sz = m_512_sz * 512; } else { if (diff < 512) @@ -1262,48 +921,48 @@ static int get_telemetry_dump(struct nvme_dev *dev, char *filename, char *sn, else diff = (diff / 512) * 512; - m_512_sz = (__le64) ((da1_sz / 512) + 1 + diff + 1); + m_512_sz = (da1_sz / 512) + 1 + diff + 1; da1_sz = m_512_sz * 512; } } char *da1_stat = calloc(da1_sz, sizeof(char)); - err = get_telemetry_data(dev, nsid, tele_type, da1_sz, - (void *)da1_stat, lsp, rae, da1_off); + err = get_telemetry_data(dev, nsid, tele_type, da1_sz, (void *)da1_stat, lsp, rae, + da1_off); if (err) { printf("get_telemetry_data da1 stats failed, err: %d.\n", err); return err; } - print_telemetry_da_stat((void *)(da1_stat + (temp_ofst - da1_off)), - tele_type, (da1->da1_stat_size) * 4, 1); + print_telemetry_da_stat((void *)(da1_stat + (temp_ofst - da1_off)), tele_type, + le64_to_cpu(da1->da1_stat_size) * 4, 1); } /* Print the Data Area 1 Event FIFO's */ for (i = 0; i < 16 ; i++) { if ((da1->event_fifo_da[i] == 1) && (da1->event_fifos[i].size != 0)) { diff = 0; - da1_sz = da1->event_fifos[i].size * 4; - m_512_sz = da1->event_fifos[i].size * 4; - da1_off = da1->event_fifos[i].start * 4; - m_512_off = da1->event_fifos[i].start * 4; - temp_sz = da1->event_fifos[i].size * 4; - temp_ofst = da1->event_fifos[i].start * 4; + da1_sz = le64_to_cpu(da1->event_fifos[i].size) * 4; + m_512_sz = le64_to_cpu(da1->event_fifos[i].size) * 4; + da1_off = le64_to_cpu(da1->event_fifos[i].start) * 4; + m_512_off = le64_to_cpu(da1->event_fifos[i].start) * 4; + temp_sz = le64_to_cpu(da1->event_fifos[i].size) * 4; + temp_ofst = le64_to_cpu(da1->event_fifos[i].start) * 4; flag = 0; if ((da1_off % 512) > 0) { - m_512_off = (__le64) ((da1_off / 512)); + m_512_off = ((da1_off / 512)); da1_off = m_512_off * 512; diff = temp_ofst - da1_off; flag = 1; } - if (da1_sz < 512) + if (da1_sz < 512) { da1_sz = 512; - else if ((da1_sz % 512) > 0) { + } else if ((da1_sz % 512) > 0) { if (flag == 0) { - m_512_sz = (__le64) ((da1_sz / 512) + 1); + m_512_sz = (da1_sz / 512) + 1; da1_sz = m_512_sz * 512; } else { if (diff < 512) @@ -1311,121 +970,115 @@ static int get_telemetry_dump(struct nvme_dev *dev, char *filename, char *sn, else diff = (diff / 512) * 512; - m_512_sz = (__le64) ((da1_sz / 512) + 1 + diff + 1); + m_512_sz = (da1_sz / 512) + 1 + diff + 1; da1_sz = m_512_sz * 512; } } char *da1_fifo = calloc(da1_sz, sizeof(char)); + printf("Get DA 1 FIFO addr: %p, offset 0x%"PRIx64"\n", da1_fifo, + (uint64_t)da1_off); err = get_telemetry_data(dev, nsid, tele_type, - (da1->event_fifos[i].size) * 4, - (void *)da1_fifo, lsp, rae, da1_off); + le64_to_cpu(da1->event_fifos[i].size) * 4, + (void *)da1_fifo, lsp, rae, da1_off); if (err) { printf("get_telemetry_data da1 event fifos failed, err: %d.\n", - err); + err); return err; } - print_telemetry_da_fifo((void *)(da1_fifo + (temp_ofst - da1_off)), - temp_sz, - tele_type, - da1->event_fifo_da[i], - i); + print_telemetry_da_fifo((void *)(da1_fifo + (temp_ofst - da1_off)), temp_sz, + tele_type, le64_to_cpu(da1->event_fifo_da[i]), i); } } /* Print the Data Area 2 Stats */ if (da1->da2_stat_size != 0) { - da1_off = (da1->da2_stat_start) * 4; - temp_ofst = (da1->da2_stat_start) * 4; - da1_sz = (da1->da2_stat_size) * 4; + da1_off = le64_to_cpu(da1->da2_stat_start) * 4; + temp_ofst = le64_to_cpu(da1->da2_stat_start) * 4; + da1_sz = le64_to_cpu(da1->da2_stat_size) * 4; diff = 0; flag = 0; if (da1->da2_stat_start == 0) { - da1_off = 512 + (logheader->DataArea1LastBlock * 512); + da1_off = 512 + (le16_to_cpu(logheader->DataArea1LastBlock) * 512); temp_ofst = 512 + (le16_to_cpu(logheader->DataArea1LastBlock) * 512); if ((da1_off % 512) == 0) { - m_512_off = (__le64) (((da1_off) / 512)); + m_512_off = ((da1_off) / 512); da1_off = m_512_off * 512; diff = temp_ofst - da1_off; flag = 1; } } else { - if (((da1_off * 4) % 512) > 0) { - m_512_off = (__le64) ((((da1->da2_stat_start) * 4) / 512)); + m_512_off = ((le64_to_cpu(da1->da2_stat_start) * 4) / 512); da1_off = m_512_off * 512; - diff = ((da1->da2_stat_start) * 4) - da1_off; + diff = (le64_to_cpu(da1->da2_stat_start) * 4) - da1_off; flag = 1; } } - if (da1_sz < 512) + if (da1_sz < 512) { da1_sz = 512; - else if ((da1_sz % 512) > 0) { + } else if ((da1_sz % 512) > 0) { if (flag == 0) { - m_512_sz = (__le64) ((da1->da2_stat_size / 512) + 1); + m_512_sz = (le64_to_cpu(da1->da2_stat_size) / 512) + 1; da1_sz = m_512_sz * 512; } else { if (diff < 512) diff = 1; else diff = (diff / 512) * 512; - m_512_sz = (__le64) ((da1->da2_stat_size / 512) + 1 + diff + 1); + m_512_sz = (le64_to_cpu(da1->da2_stat_size) / 512) + 1 + diff + 1; da1_sz = m_512_sz * 512; } } char *da2_stat = calloc(da1_sz, sizeof(char)); - err = get_telemetry_data(dev, nsid, tele_type, da1_sz, - (void *)da2_stat, lsp, rae, da1_off); + err = get_telemetry_data(dev, nsid, tele_type, da1_sz, (void *)da2_stat, lsp, rae, + da1_off); if (err) { printf("get_telemetry_data da2 stats failed, err: %d.\n", err); return err; } - print_telemetry_da_stat((void *)(da2_stat + (temp_ofst - da1_off)), - tele_type, - (da1->da2_stat_size) * 4, - 2); + print_telemetry_da_stat((void *)(da2_stat + (temp_ofst - da1_off)), tele_type, + le64_to_cpu(da1->da2_stat_size) * 4, 2); } /* Print the Data Area 2 Event FIFO's */ for (i = 0; i < 16 ; i++) { if ((da1->event_fifo_da[i] == 2) && (da1->event_fifos[i].size != 0)) { diff = 0; - da1_sz = da1->event_fifos[i].size * 4; - m_512_sz = da1->event_fifos[i].size * 4; - da1_off = da1->event_fifos[i].start * 4; - m_512_off = da1->event_fifos[i].start * 4; - temp_sz = da1->event_fifos[i].size * 4; - temp_ofst = da1->event_fifos[i].start * 4; + da1_sz = le64_to_cpu(da1->event_fifos[i].size) * 4; + m_512_sz = le64_to_cpu(da1->event_fifos[i].size) * 4; + da1_off = le64_to_cpu(da1->event_fifos[i].start) * 4; + m_512_off = le64_to_cpu(da1->event_fifos[i].start) * 4; + temp_sz = le64_to_cpu(da1->event_fifos[i].size) * 4; + temp_ofst = le64_to_cpu(da1->event_fifos[i].start) * 4; flag = 0; if ((da1_off % 512) > 0) { - m_512_off = (__le64) ((da1_off / 512)); + m_512_off = ((da1_off / 512)); da1_off = m_512_off * 512; diff = temp_ofst - da1_off; flag = 1; } - if (da1_sz < 512) + if (da1_sz < 512) { da1_sz = 512; - else if ((da1_sz % 512) > 0) { + } else if ((da1_sz % 512) > 0) { if (flag == 0) { - m_512_sz = (__le64) ((da1_sz / 512) + 1); + m_512_sz = (da1_sz / 512) + 1; da1_sz = m_512_sz * 512; - } - - else { + } else { if (diff < 512) diff = 1; else diff = (diff / 512) * 512; - m_512_sz = (__le64) ((da1_sz / 512) + 1 + diff + 1); + m_512_sz = (da1_sz / 512) + 1 + diff + 1; da1_sz = m_512_sz * 512; } } @@ -1433,18 +1086,15 @@ static int get_telemetry_dump(struct nvme_dev *dev, char *filename, char *sn, char *da1_fifo = calloc(da1_sz, sizeof(char)); err = get_telemetry_data(dev, nsid, tele_type, - (da1->event_fifos[i].size) * 4, - (void *)da1_fifo, lsp, rae, da1_off); + le64_to_cpu(da1->event_fifos[i].size) * 4, + (void *)da1_fifo, lsp, rae, da1_off); if (err) { printf("get_telemetry_data da2 event fifos failed, err: %d.\n", - err); + err); return err; } - print_telemetry_da_fifo((void *)(da1_fifo + (temp_ofst - da1_off)), - temp_sz, - tele_type, - da1->event_fifo_da[i], - i); + print_telemetry_da_fifo((void *)(da1_fifo + (temp_ofst - da1_off)), temp_sz, + tele_type, le64_to_cpu(da1->event_fifo_da[i]), i); } } @@ -1452,20 +1102,20 @@ static int get_telemetry_dump(struct nvme_dev *dev, char *filename, char *sn, switch (data_area) { case 1: - offset = TELEMETRY_HEADER_SIZE; - size = le16_to_cpu(logheader->DataArea1LastBlock); + offset = TELEMETRY_HEADER_SIZE; + size = le16_to_cpu(logheader->DataArea1LastBlock); break; case 2: - offset = TELEMETRY_HEADER_SIZE - + (le16_to_cpu(logheader->DataArea1LastBlock) * TELEMETRY_BYTE_PER_BLOCK); - size = le16_to_cpu(logheader->DataArea2LastBlock) - - le16_to_cpu(logheader->DataArea1LastBlock); + offset = TELEMETRY_HEADER_SIZE + + (le16_to_cpu(logheader->DataArea1LastBlock) * TELEMETRY_BYTE_PER_BLOCK); + size = le16_to_cpu(logheader->DataArea2LastBlock) - + le16_to_cpu(logheader->DataArea1LastBlock); break; case 3: - offset = TELEMETRY_HEADER_SIZE - + (le16_to_cpu(logheader->DataArea2LastBlock) * TELEMETRY_BYTE_PER_BLOCK); - size = le16_to_cpu(logheader->DataArea3LastBlock) - - le16_to_cpu(logheader->DataArea2LastBlock); + offset = TELEMETRY_HEADER_SIZE + + (le16_to_cpu(logheader->DataArea2LastBlock) * TELEMETRY_BYTE_PER_BLOCK); + size = le16_to_cpu(logheader->DataArea3LastBlock) - + le16_to_cpu(logheader->DataArea2LastBlock); break; default: break; @@ -1476,11 +1126,9 @@ static int get_telemetry_dump(struct nvme_dev *dev, char *filename, char *sn, return err; } - snprintf(dumpname, FILE_NAME_SIZE, - "Telemetry_%s_Area_%d", featurename, data_area); + snprintf(dumpname, FILE_NAME_SIZE, "Telemetry_%s_Area_%d", featurename, data_area); err = extract_dump_get_log(dev, dumpname, filename, sn, size * TELEMETRY_BYTE_PER_BLOCK, - TELEMETRY_TRANSFER_SIZE, nsid, tele_type, - 0, offset, rae); + TELEMETRY_TRANSFER_SIZE, nsid, tele_type, 0, offset, rae); return err; } @@ -1588,13 +1236,15 @@ exit_status: static int get_c9_log_page_data(struct nvme_dev *dev, int print_data, int save_bin) { - int ret = 0, fd; + int ret = 0; __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]; + _cleanup_fd_ int fd = STDIN_FILENO; + header_data = (__u8 *)malloc(sizeof(__u8) * C9_TELEMETRY_STR_LOG_LEN); if (!header_data) { fprintf(stderr, "ERROR : OCP : malloc : %s\n", strerror(errno)); @@ -1608,29 +1258,34 @@ static int get_c9_log_page_data(struct nvme_dev *dev, int print_data, int save_b 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); + printf("Statistics Identifier String Table Size = %"PRIu64"\n", + le64_to_cpu(log_data->sitsz)); + printf("Event String Table Size = %"PRIu64"\n", + le64_to_cpu(log_data->estsz)); + printf("VU Event String Table Size = %"PRIu64"\n", + le64_to_cpu(log_data->vu_eve_st_sz)); + printf("ASCII Table Size = %"PRIu64"\n", le64_to_cpu(log_data->asctsz)); } - //Calculating the offset for dynamic fields. + /* 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); + (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); + printf("stat_id_str_table_ofst = %"PRIu64"\n", + le64_to_cpu(stat_id_str_table_ofst)); + printf("event_str_table_ofst = %"PRIu64"\n", + le64_to_cpu(event_str_table_ofst)); + printf("vu_event_str_table_ofst = %"PRIu64"\n", + le64_to_cpu(vu_event_str_table_ofst)); + printf("ascii_table_ofst = %"PRIu64"\n", le64_to_cpu(ascii_table_ofst)); + printf("total_log_page_sz = %"PRIu64"\n", le64_to_cpu(total_log_page_sz)); } pC9_string_buffer = (__u8 *)malloc(sizeof(__u8) * total_log_page_sz); @@ -1642,26 +1297,24 @@ static int get_c9_log_page_data(struct nvme_dev *dev, int print_data, int save_b ret = nvme_get_log_simple(dev_fd(dev), C9_TELEMETRY_STRING_LOG_ENABLE_OPCODE, total_log_page_sz, pC9_string_buffer); - } else + } 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; + fprintf(stderr, "Failed to open output file %s: %s!\n", file_path, + strerror(errno)); + return fd; } 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: return 0; } @@ -1716,22 +1369,12 @@ int parse_ocp_telemetry_log(struct ocp_telemetry_parse_options *options) return status; } - switch (fmt) { - case NORMAL: - print_ocp_telemetry_normal(options); - break; - case JSON: - print_ocp_telemetry_json(options); - break; - default: - break; - } + ocp_show_telemetry_log(options, fmt); return 0; } -static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, - struct plugin *plugin) +static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Retrieve and parse OCP Telemetry log."; const char *telemetry_log = "Telemetry log binary;\n 'host.bin' or 'controller.bin'"; @@ -1769,6 +1412,9 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, if (err) return err; + if (opt.telemetry_type == 0) + opt.telemetry_type = "host"; + err = fstat(dev_fd(dev), &nvme_stat); if (err < 0) return err; @@ -1812,6 +1458,7 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, } } else { tele_type = TELEMETRY_TYPE_HOST; //Default Type - Host + opt.telemetry_type = "host"; nvme_show_result("Missing telemetry-type. Using default - host.\n"); } @@ -1843,23 +1490,21 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, } switch (tele_type) { - case TELEMETRY_TYPE_HOST: { + 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: { + 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: { + 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"); @@ -1867,7 +1512,8 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, 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); + fprintf(stderr, "NVMe Status: %s(%x)\n", nvme_status_to_string(err, false), + err); printf("\n-------------------------------------------------------------\n"); @@ -1876,7 +1522,8 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, 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); + fprintf(stderr, "NVMe Status: %s(%x)\n", nvme_status_to_string(err, false), + err); printf("\n-------------------------------------------------------------\n"); @@ -1885,7 +1532,8 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, 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); + fprintf(stderr, "NVMe Status: %s(%x)\n", nvme_status_to_string(err, false), + err); printf("\n-------------------------------------------------------------\n"); @@ -1894,7 +1542,8 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, 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); + fprintf(stderr, "NVMe Status: %s(%x)\n", nvme_status_to_string(err, false), + err); printf("\n-------------------------------------------------------------\n"); @@ -1908,19 +1557,18 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, } printf("\n-------------------------------------------------------------\n"); - } - break; + break; case TELEMETRY_TYPE_HOST_0: case TELEMETRY_TYPE_HOST_1: - default: { + 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, 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; + fprintf(stderr, "NVMe Status: %s(%x)\n", nvme_status_to_string(err, false), + err); + break; } printf("ocp internal-log command completed.\n"); @@ -1929,7 +1577,6 @@ out: return err; } - /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// @@ -1937,99 +1584,20 @@ out: /// Unsupported Requirement Log Page (LID : C5h) /* C5 Unsupported Requirement Log Page */ -#define C5_GUID_LENGTH 16 #define C5_UNSUPPORTED_REQS_LEN 4096 #define C5_UNSUPPORTED_REQS_OPCODE 0xC5 -#define C5_UNSUPPORTED_REQS_LOG_VERSION 0x1 -#define C5_NUM_UNSUPPORTED_REQ_ENTRIES 253 -static __u8 unsupported_req_guid[C5_GUID_LENGTH] = { +static __u8 unsupported_req_guid[GUID_LEN] = { 0x2F, 0x72, 0x9C, 0x0E, 0x99, 0x23, 0x2C, 0xBB, 0x63, 0x48, 0x32, 0xD0, 0xB7, 0x98, 0xBB, 0xC7 }; -/* - * struct unsupported_requirement_log - unsupported requirement list - * @unsupported_count: Number of Unsupported Requirement IDs - * @rsvd1: Reserved - * @unsupported_req_list: Unsupported Requirements lists upto 253. - * @rsvd2: Reserved - * @log_page_version: indicates the version of the mapping this log page uses. - * Shall be set to 0001h - * @log_page_guid: Shall be set to C7BB98B7D0324863BB2C23990E9C722Fh. - */ -struct __packed unsupported_requirement_log { - __le16 unsupported_count; - __u8 rsvd1[14]; - __u8 unsupported_req_list[C5_NUM_UNSUPPORTED_REQ_ENTRIES][16]; - __u8 rsvd2[14]; - __le16 log_page_version; - __u8 log_page_guid[C5_GUID_LENGTH]; -}; - /* Function declaration for unsupported requirement log page (LID:C5h) */ static int ocp_unsupported_requirements_log(int argc, char **argv, struct command *cmd, struct plugin *plugin); -static int ocp_print_C5_log_normal(struct nvme_dev *dev, - struct unsupported_requirement_log *log_data) -{ - int j; - - printf("Unsupported Requirement-C5 Log Page Data-\n"); - - printf(" Number Unsupported Req IDs : 0x%x\n", le16_to_cpu(log_data->unsupported_count)); - - for (j = 0; j < le16_to_cpu(log_data->unsupported_count); j++) - printf(" Unsupported Requirement List %d : %s\n", j, log_data->unsupported_req_list[j]); - - printf(" Log Page Version : 0x%x\n", le16_to_cpu(log_data->log_page_version)); - printf(" Log page GUID : 0x"); - for (j = C5_GUID_LENGTH - 1; j >= 0; j--) - printf("%x", log_data->log_page_guid[j]); - printf("\n"); - - return 0; -} - -static void ocp_print_C5_log_json(struct unsupported_requirement_log *log_data) -{ - int j; - struct json_object *root; - char unsup_req_list_str[40]; - char guid_buf[C5_GUID_LENGTH]; - char *guid = guid_buf; - - root = json_create_object(); - - json_object_add_value_int(root, "Number Unsupported Req IDs", le16_to_cpu(log_data->unsupported_count)); - - memset((void *)unsup_req_list_str, 0, 40); - for (j = 0; j < le16_to_cpu(log_data->unsupported_count); j++) { - sprintf((char *)unsup_req_list_str, "Unsupported Requirement List %d", j); - json_object_add_value_string(root, unsup_req_list_str, (char *)log_data->unsupported_req_list[j]); - } - - json_object_add_value_int(root, "Log Page Version", le16_to_cpu(log_data->log_page_version)); - - memset((void *)guid, 0, C5_GUID_LENGTH); - for (j = C5_GUID_LENGTH - 1; j >= 0; j--) - guid += sprintf(guid, "%02x", log_data->log_page_guid[j]); - json_object_add_value_string(root, "Log page GUID", guid_buf); - - json_print_object(root, NULL); - printf("\n"); - - json_free_object(root); -} - -static void ocp_print_c5_log_binary(struct unsupported_requirement_log *log_data) -{ - return d_raw((unsigned char *)log_data, sizeof(*log_data)); -} - static int get_c5_log_page(struct nvme_dev *dev, char *format) { nvme_print_flags_t fmt; @@ -2057,13 +1625,6 @@ static int get_c5_log_page(struct nvme_dev *dev, char *format) if (!ret) { log_data = (struct unsupported_requirement_log *)data; - /* check log page version */ - if (log_data->log_page_version != C5_UNSUPPORTED_REQS_LOG_VERSION) { - fprintf(stderr, "ERROR : OCP : invalid unsupported requirement version\n"); - ret = -1; - goto out; - } - /* * check log page guid * Verify GUID matches @@ -2073,30 +1634,17 @@ static int get_c5_log_page(struct nvme_dev *dev, char *format) fprintf(stderr, "ERROR : OCP : Unknown GUID in C5 Log Page data\n"); fprintf(stderr, "ERROR : OCP : Expected GUID: 0x"); for (j = 0; j < 16; j++) - fprintf(stderr, "%x", unsupported_req_guid[j]); + fprintf(stderr, "%02x", unsupported_req_guid[j]); fprintf(stderr, "\nERROR : OCP : Actual GUID: 0x"); for (j = 0; j < 16; j++) - fprintf(stderr, "%x", log_data->log_page_guid[j]); + fprintf(stderr, "%02x", log_data->log_page_guid[j]); fprintf(stderr, "\n"); ret = -1; goto out; } } - - switch (fmt) { - case NORMAL: - ocp_print_C5_log_normal(dev, log_data); - break; - case JSON: - ocp_print_C5_log_json(log_data); - break; - case BINARY: - ocp_print_c5_log_binary(log_data); - break; - default: - break; - } + ocp_c5_log(dev, log_data, fmt); } else { fprintf(stderr, "ERROR : OCP : Unable to read C3 data from buffer\n"); } @@ -2146,115 +1694,17 @@ static int ocp_unsupported_requirements_log(int argc, char **argv, struct comman #define C1_ERROR_RECOVERY_LOG_BUF_LEN 0x200 #define C1_ERROR_RECOVERY_OPCODE 0xC1 -#define C1_ERROR_RECOVERY_VERSION 0x0002 -#define C1_GUID_LENGTH 16 -static __u8 error_recovery_guid[C1_GUID_LENGTH] = { + +static __u8 error_recovery_guid[GUID_LEN] = { 0x44, 0xd9, 0x31, 0x21, 0xfe, 0x30, 0x34, 0xae, 0xab, 0x4d, 0xfd, 0x3d, 0xba, 0x83, 0x19, 0x5a }; -/** - * struct ocp_error_recovery_log_page - Error Recovery Log Page - * @panic_reset_wait_time: Panic Reset Wait Time - * @panic_reset_action: Panic Reset Action - * @device_recover_action_1: Device Recovery Action 1 - * @panic_id: Panic ID - * @device_capabilities: Device Capabilities - * @vendor_specific_recovery_opcode: Vendor Specific Recovery Opcode - * @reserved: Reserved - * @vendor_specific_command_cdw12: Vendor Specific Command CDW12 - * @vendor_specific_command_cdw13: Vendor Specific Command CDW13 - * @vendor_specific_command_timeout: Vendor Specific Command Timeout - * @device_recover_action_2: Device Recovery Action 2 - * @device_recover_action_2_timeout: Device Recovery Action 2 Timeout - * @reserved2: Reserved - * @log_page_version: Log Page Version - * @log_page_guid: Log Page GUID - */ -struct __packed ocp_error_recovery_log_page { - __le16 panic_reset_wait_time; /* 2 bytes - 0x00 - 0x01 */ - __u8 panic_reset_action; /* 1 byte - 0x02 */ - __u8 device_recover_action_1; /* 1 byte - 0x03 */ - __le64 panic_id; /* 8 bytes - 0x04 - 0x0B */ - __le32 device_capabilities; /* 4 bytes - 0x0C - 0x0F */ - __u8 vendor_specific_recovery_opcode; /* 1 byte - 0x10 */ - __u8 reserved[0x3]; /* 3 bytes - 0x11 - 0x13 */ - __le32 vendor_specific_command_cdw12; /* 4 bytes - 0x14 - 0x17 */ - __le32 vendor_specific_command_cdw13; /* 4 bytes - 0x18 - 0x1B */ - __u8 vendor_specific_command_timeout; /* 1 byte - 0x1C */ - __u8 device_recover_action_2; /* 1 byte - 0x1D */ - __u8 device_recover_action_2_timeout; /* 1 byte - 0x1E */ - __u8 reserved2[0x1cf]; /* 463 bytes - 0x1F - 0x1ED */ - __le16 log_page_version; /* 2 bytes - 0x1EE - 0x1EF */ - __u8 log_page_guid[0x10]; /* 16 bytes - 0x1F0 - 0x1FF */ -}; - -static void ocp_print_c1_log_normal(struct ocp_error_recovery_log_page *log_data); -static void ocp_print_c1_log_json(struct ocp_error_recovery_log_page *log_data); -static void ocp_print_c1_log_binary(struct ocp_error_recovery_log_page *log_data); static int get_c1_log_page(struct nvme_dev *dev, char *format); static int ocp_error_recovery_log(int argc, char **argv, struct command *cmd, struct plugin *plugin); -static void ocp_print_c1_log_normal(struct ocp_error_recovery_log_page *log_data) -{ - int i; - - printf(" Error Recovery/C1 Log Page Data\n"); - printf(" Panic Reset Wait Time : 0x%x\n", le16_to_cpu(log_data->panic_reset_wait_time)); - printf(" Panic Reset Action : 0x%x\n", log_data->panic_reset_action); - printf(" Device Recovery Action 1 : 0x%x\n", log_data->device_recover_action_1); - printf(" Panic ID : 0x%x\n", le32_to_cpu(log_data->panic_id)); - printf(" Device Capabilities : 0x%x\n", le32_to_cpu(log_data->device_capabilities)); - printf(" Vendor Specific Recovery Opcode : 0x%x\n", log_data->vendor_specific_recovery_opcode); - printf(" Vendor Specific Command CDW12 : 0x%x\n", le32_to_cpu(log_data->vendor_specific_command_cdw12)); - printf(" Vendor Specific Command CDW13 : 0x%x\n", le32_to_cpu(log_data->vendor_specific_command_cdw13)); - printf(" Vendor Specific Command Timeout : 0x%x\n", log_data->vendor_specific_command_timeout); - printf(" Device Recovery Action 2 : 0x%x\n", log_data->device_recover_action_2); - printf(" Device Recovery Action 2 Timeout : 0x%x\n", log_data->device_recover_action_2_timeout); - printf(" Log Page Version : 0x%x\n", le16_to_cpu(log_data->log_page_version)); - printf(" Log page GUID : 0x"); - for (i = C1_GUID_LENGTH - 1; i >= 0; i--) - printf("%x", log_data->log_page_guid[i]); - printf("\n"); -} - -static void ocp_print_c1_log_json(struct ocp_error_recovery_log_page *log_data) -{ - struct json_object *root; - - root = json_create_object(); - char guid[64]; - - json_object_add_value_int(root, "Panic Reset Wait Time", le16_to_cpu(log_data->panic_reset_wait_time)); - json_object_add_value_int(root, "Panic Reset Action", log_data->panic_reset_action); - json_object_add_value_int(root, "Device Recovery Action 1", log_data->device_recover_action_1); - json_object_add_value_int(root, "Panic ID", le32_to_cpu(log_data->panic_id)); - json_object_add_value_int(root, "Device Capabilities", le32_to_cpu(log_data->device_capabilities)); - json_object_add_value_int(root, "Vendor Specific Recovery Opcode", log_data->vendor_specific_recovery_opcode); - json_object_add_value_int(root, "Vendor Specific Command CDW12", le32_to_cpu(log_data->vendor_specific_command_cdw12)); - json_object_add_value_int(root, "Vendor Specific Command CDW13", le32_to_cpu(log_data->vendor_specific_command_cdw13)); - json_object_add_value_int(root, "Vendor Specific Command Timeout", log_data->vendor_specific_command_timeout); - json_object_add_value_int(root, "Device Recovery Action 2", log_data->device_recover_action_2); - json_object_add_value_int(root, "Device Recovery Action 2 Timeout", log_data->device_recover_action_2_timeout); - json_object_add_value_int(root, "Log Page Version", le16_to_cpu(log_data->log_page_version)); - - memset((void *)guid, 0, 64); - sprintf((char *)guid, "0x%"PRIx64"%"PRIx64"", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]), - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0])); - json_object_add_value_string(root, "Log page GUID", guid); - - json_print_object(root, NULL); - printf("\n"); - json_free_object(root); -} - -static void ocp_print_c1_log_binary(struct ocp_error_recovery_log_page *log_data) -{ - return d_raw((unsigned char *)log_data, sizeof(*log_data)); -} - static int get_c1_log_page(struct nvme_dev *dev, char *format) { struct ocp_error_recovery_log_page *log_data; @@ -2281,13 +1731,6 @@ static int get_c1_log_page(struct nvme_dev *dev, char *format) if (!ret) { log_data = (struct ocp_error_recovery_log_page *)data; - /* check log page version */ - if (log_data->log_page_version != C1_ERROR_RECOVERY_VERSION) { - fprintf(stderr, "ERROR : OCP : invalid error recovery log page version\n"); - ret = -1; - goto out; - } - /* * check log page guid * Verify GUID matches @@ -2297,30 +1740,17 @@ static int get_c1_log_page(struct nvme_dev *dev, char *format) fprintf(stderr, "ERROR : OCP : Unknown GUID in C1 Log Page data\n"); fprintf(stderr, "ERROR : OCP : Expected GUID: 0x"); for (j = 0; j < 16; j++) - fprintf(stderr, "%x", error_recovery_guid[j]); + fprintf(stderr, "%02x", error_recovery_guid[j]); fprintf(stderr, "\nERROR : OCP : Actual GUID: 0x"); for (j = 0; j < 16; j++) - fprintf(stderr, "%x", log_data->log_page_guid[j]); + fprintf(stderr, "%02x", log_data->log_page_guid[j]); fprintf(stderr, "\n"); ret = -1; goto out; } } - - switch (fmt) { - case NORMAL: - ocp_print_c1_log_normal(log_data); - break; - case JSON: - ocp_print_c1_log_json(log_data); - break; - case BINARY: - ocp_print_c1_log_binary(log_data); - break; - default: - break; - } + ocp_c1_log(log_data, fmt); } else { fprintf(stderr, "ERROR : OCP : Unable to read C1 data from buffer\n"); } @@ -2368,109 +1798,16 @@ static int ocp_error_recovery_log(int argc, char **argv, struct command *cmd, st #define C4_DEV_CAP_REQ_LEN 0x1000 #define C4_DEV_CAP_REQ_OPCODE 0xC4 -#define C4_DEV_CAP_REQ_VERSION 0x0001 -#define C4_GUID_LENGTH 16 -static __u8 dev_cap_req_guid[C4_GUID_LENGTH] = { +static __u8 dev_cap_req_guid[GUID_LEN] = { 0x97, 0x42, 0x05, 0x0d, 0xd1, 0xe1, 0xc9, 0x98, 0x5d, 0x49, 0x58, 0x4b, 0x91, 0x3c, 0x05, 0xb7 }; -/** - * struct ocp_device_capabilities_log_page - Device Capability Log page - * @pcie_exp_port: PCI Express Ports - * @oob_management_support: OOB Management Support - * @wz_cmd_support: Write Zeroes Command Support - * @sanitize_cmd_support: Sanitize Command Support - * @dsm_cmd_support: Dataset Management Command Support - * @wu_cmd_support: Write Uncorrectable Command Support - * @fused_operation_support: Fused Operation Support - * @min_valid_dssd_pwr_state: Minimum Valid DSSD Power State - * @dssd_pwr_state_desc: DSSD Power State Descriptors - * @vendor_specific_command_timeout: Vendor Specific Command Timeout - * @reserved: Reserved - * @log_page_version: Log Page Version - * @log_page_guid: Log Page GUID - */ -struct __packed ocp_device_capabilities_log_page { - __le16 pcie_exp_port; - __le16 oob_management_support; - __le16 wz_cmd_support; - __le16 sanitize_cmd_support; - __le16 dsm_cmd_support; - __le16 wu_cmd_support; - __le16 fused_operation_support; - __le16 min_valid_dssd_pwr_state; - __u8 dssd_pwr_state_desc[128]; - __u8 reserved[3934]; - __le16 log_page_version; - __u8 log_page_guid[16]; -}; - -static void ocp_print_c4_log_normal(struct ocp_device_capabilities_log_page *log_data); -static void ocp_print_c4_log_json(struct ocp_device_capabilities_log_page *log_data); -static void ocp_print_c4_log_binary(struct ocp_device_capabilities_log_page *log_data); static int get_c4_log_page(struct nvme_dev *dev, char *format); static int ocp_device_capabilities_log(int argc, char **argv, struct command *cmd, struct plugin *plugin); -static void ocp_print_c4_log_normal(struct ocp_device_capabilities_log_page *log_data) -{ - int i; - - printf(" Device Capability/C4 Log Page Data\n"); - printf(" PCI Express Ports : 0x%x\n", le16_to_cpu(log_data->pcie_exp_port)); - printf(" OOB Management Support : 0x%x\n", le16_to_cpu(log_data->oob_management_support)); - printf(" Write Zeroes Command Support : 0x%x\n", le16_to_cpu(log_data->wz_cmd_support)); - printf(" Sanitize Command Support : 0x%x\n", le16_to_cpu(log_data->sanitize_cmd_support)); - printf(" Dataset Management Command Support : 0x%x\n", le16_to_cpu(log_data->dsm_cmd_support)); - printf(" Write Uncorrectable Command Support : 0x%x\n", le16_to_cpu(log_data->wu_cmd_support)); - printf(" Fused Operation Support : 0x%x\n", le16_to_cpu(log_data->fused_operation_support)); - printf(" Minimum Valid DSSD Power State : 0x%x\n", le16_to_cpu(log_data->min_valid_dssd_pwr_state)); - printf(" DSSD Power State Descriptors : 0x"); - for (i = 0; i <= 127; i++) - printf("%x", log_data->dssd_pwr_state_desc[i]); - printf("\n"); - printf(" Log Page Version : 0x%x\n", le16_to_cpu(log_data->log_page_version)); - printf(" Log page GUID : 0x"); - for (i = C4_GUID_LENGTH - 1; i >= 0; i--) - printf("%x", log_data->log_page_guid[i]); - printf("\n"); -} - -static void ocp_print_c4_log_json(struct ocp_device_capabilities_log_page *log_data) -{ - struct json_object *root = json_create_object(); - char guid[64]; - int i; - - json_object_add_value_int(root, "PCI Express Ports", le16_to_cpu(log_data->pcie_exp_port)); - json_object_add_value_int(root, "OOB Management Support", le16_to_cpu(log_data->oob_management_support)); - json_object_add_value_int(root, "Write Zeroes Command Support", le16_to_cpu(log_data->wz_cmd_support)); - json_object_add_value_int(root, "Sanitize Command Support", le16_to_cpu(log_data->sanitize_cmd_support)); - json_object_add_value_int(root, "Dataset Management Command Support", le16_to_cpu(log_data->dsm_cmd_support)); - json_object_add_value_int(root, "Write Uncorrectable Command Support", le16_to_cpu(log_data->wu_cmd_support)); - json_object_add_value_int(root, "Fused Operation Support", le16_to_cpu(log_data->fused_operation_support)); - json_object_add_value_int(root, "Minimum Valid DSSD Power State", le16_to_cpu(log_data->min_valid_dssd_pwr_state)); - for (i = 0; i <= 127; i++) - json_object_add_value_int(root, "DSSD Power State Descriptors", log_data->dssd_pwr_state_desc[i]); - json_object_add_value_int(root, "Log Page Version", le16_to_cpu(log_data->log_page_version)); - - memset((void *)guid, 0, 64); - sprintf((char *)guid, "0x%"PRIx64"%"PRIx64"", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]), - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0])); - json_object_add_value_string(root, "Log page GUID", guid); - - json_print_object(root, NULL); - printf("\n"); - json_free_object(root); -} - -static void ocp_print_c4_log_binary(struct ocp_device_capabilities_log_page *log_data) -{ - return d_raw((unsigned char *)log_data, sizeof(*log_data)); -} - static int get_c4_log_page(struct nvme_dev *dev, char *format) { struct ocp_device_capabilities_log_page *log_data; @@ -2497,13 +1834,6 @@ static int get_c4_log_page(struct nvme_dev *dev, char *format) if (!ret) { log_data = (struct ocp_device_capabilities_log_page *)data; - /* check log page version */ - if (log_data->log_page_version != C4_DEV_CAP_REQ_VERSION) { - fprintf(stderr, "ERROR : OCP : invalid device capabilities log page version\n"); - ret = -1; - goto out; - } - /* * check log page guid * Verify GUID matches @@ -2513,30 +1843,17 @@ static int get_c4_log_page(struct nvme_dev *dev, char *format) fprintf(stderr, "ERROR : OCP : Unknown GUID in C4 Log Page data\n"); fprintf(stderr, "ERROR : OCP : Expected GUID: 0x"); for (j = 0; j < 16; j++) - fprintf(stderr, "%x", dev_cap_req_guid[j]); + fprintf(stderr, "%02x", dev_cap_req_guid[j]); fprintf(stderr, "\nERROR : OCP : Actual GUID: 0x"); for (j = 0; j < 16; j++) - fprintf(stderr, "%x", log_data->log_page_guid[j]); + fprintf(stderr, "%02x", log_data->log_page_guid[j]); fprintf(stderr, "\n"); ret = -1; goto out; } } - - switch (fmt) { - case NORMAL: - ocp_print_c4_log_normal(log_data); - break; - case JSON: - ocp_print_c4_log_json(log_data); - break; - case BINARY: - ocp_print_c4_log_binary(log_data); - break; - default: - break; - } + ocp_c4_log(log_data, fmt); } else { fprintf(stderr, "ERROR : OCP : Unable to read C4 data from buffer\n"); } @@ -3141,457 +2458,9 @@ static int get_dssd_async_event_config(int argc, char **argv, struct command *cm 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) -{ - //calculating the index value for array - __le64 stat_id_index = (log_data->sitsz * 4) / 16; - __le64 eve_id_index = (log_data->estsz * 4) / 16; - __le64 vu_eve_index = (log_data->vu_eve_st_sz * 4) / 16; - __le64 ascii_table_index = (log_data->asctsz * 4); - //Calculating the offset for dynamic fields. - __le64 stat_id_str_table_ofst = log_data->sits * 4; - __le64 event_str_table_ofst = log_data->ests * 4; - __le64 vu_event_str_table_ofst = log_data->vu_eve_sts * 4; - __le64 ascii_table_ofst = log_data->ascts * 4; - struct statistics_id_str_table_entry stat_id_str_table_arr[stat_id_index]; - struct event_id_str_table_entry event_id_str_table_arr[eve_id_index]; - struct vu_event_id_str_table_entry vu_event_id_str_table_arr[vu_eve_index]; - int j; - - printf(" Log Page Version : 0x%x\n", log_data->log_page_version); - - printf(" Reserved : "); - for (j = 0; j < 15; j++) - printf("%d", log_data->reserved1[j]); - printf("\n"); - - printf(" Log page GUID : 0x"); - for (j = C9_GUID_LENGTH - 1; j >= 0; j--) - printf("%x", log_data->log_page_guid[j]); - printf("\n"); - - printf(" Telemetry String Log Size : 0x%lx\n", le64_to_cpu(log_data->sls)); - - printf(" Reserved : "); - for (j = 0; j < 24; j++) - printf("%d", log_data->reserved2[j]); - printf("\n"); - - printf(" Statistics Identifier String Table Start : 0x%lx\n", le64_to_cpu(log_data->sits)); - printf(" Statistics Identifier String Table Size : 0x%lx\n", le64_to_cpu(log_data->sitsz)); - printf(" Event String Table Start : 0x%lx\n", le64_to_cpu(log_data->ests)); - printf(" Event String Table Size : 0x%lx\n", le64_to_cpu(log_data->estsz)); - printf(" VU Event String Table Start : 0x%lx\n", le64_to_cpu(log_data->vu_eve_sts)); - printf(" VU Event String Table Size : 0x%lx\n", le64_to_cpu(log_data->vu_eve_st_sz)); - printf(" ASCII Table Start : 0x%lx\n", le64_to_cpu(log_data->ascts)); - printf(" ASCII Table Size : 0x%lx\n", le64_to_cpu(log_data->asctsz)); - - printf(" FIFO 1 ASCII String\n"); - printf(" index value ascii_val\n"); - for (j = 0; j < 16; j++) - printf(" %d %d %c \n", j, log_data->fifo1[j], log_data->fifo1[j]); - - printf(" FIFO 2 ASCII String\n"); - printf(" index value ascii_val\n"); - for (j = 0; j < 16; j++) - printf(" %d %d %c \n", j, log_data->fifo2[j], log_data->fifo2[j]); - - printf(" FIFO 3 ASCII String\n"); - printf(" index value ascii_val\n"); - for (j = 0; j < 16; j++) - printf(" %d %d %c \n", j, log_data->fifo3[j], log_data->fifo3[j]); - - printf(" FIFO 4 ASCII String\n"); - printf(" index value ascii_val\n"); - for (j = 0; j < 16; j++) - printf(" %d %d %c \n", j, log_data->fifo4[j], log_data->fifo4[j]); - - printf(" FIFO 5 ASCII String\n"); - printf(" index value ascii_val\n"); - for (j = 0; j < 16; j++) - printf(" %d %d %c \n", j, log_data->fifo5[j], log_data->fifo5[j]); - - printf(" FIFO 6 ASCII String\n"); - printf(" index value ascii_val\n"); - for (j = 0; j < 16; j++) - printf(" %d %d %c \n", j, log_data->fifo6[j], log_data->fifo6[j]); - - printf(" FIFO 7 ASCII String\n"); - printf(" index value ascii_val\n"); - for (j = 0; j < 16; j++) - printf(" %d %d %c \n", j, log_data->fifo7[j], log_data->fifo7[j]); - - printf(" FIFO 8 ASCII String\n"); - printf(" index value ascii_val\n"); - for (j = 0; j < 16; j++) - printf(" %d %d %c \n", j, log_data->fifo8[j], log_data->fifo8[j]); - - printf(" FIFO 9 ASCII String\n"); - printf(" index value ascii_val\n"); - for (j = 0; j < 16; j++) - printf(" %d %d %c \n", j, log_data->fifo9[j], log_data->fifo9[j]); - - printf(" FIFO 10 ASCII String\n"); - printf(" index value ascii_val\n"); - for (j = 0; j < 16; j++) - printf(" %d %d %c \n", j, log_data->fifo10[j], log_data->fifo10[j]); - - printf(" FIFO 11 ASCII String\n"); - printf(" index value ascii_val\n"); - for (j = 0; j < 16; j++) - printf(" %d %d %c \n", j, log_data->fifo11[j], log_data->fifo11[j]); - - printf(" FIFO 12 ASCII String\n"); - printf(" index value ascii_val\n"); - for (j = 0; j < 16; j++) - printf(" %d %d %c \n", j, log_data->fifo12[j], log_data->fifo12[j]); - - printf(" FIFO 13 ASCII String\n"); - printf(" index value ascii_val\n"); - for (j = 0; j < 16; j++) - printf(" %d %d %c \n", j, log_data->fifo13[j], log_data->fifo13[j]); - - printf(" FIFO 14 ASCII String\n"); - printf(" index value ascii_val\n"); - for (j = 0; j < 16; j++) - printf(" %d %d %c \n", j, log_data->fifo14[j], log_data->fifo14[j]); - - printf(" FIFO 15 ASCII String\n"); - printf(" index value ascii_val\n"); - for (j = 0; j < 16; j++) - printf(" %d %d %c \n", j, log_data->fifo15[j], log_data->fifo16[j]); - - printf(" FIFO 16 ASCII String\n"); - printf(" index value ascii_val\n"); - for (j = 0; j < 16; j++) - printf(" %d %d %c \n", j, log_data->fifo16[j], log_data->fifo16[j]); - - printf(" Reserved : "); - for (j = 0; j < 48; j++) - printf("%d", log_data->reserved3[j]); - printf("\n"); - - - if (log_data->sitsz != 0) { - memcpy(stat_id_str_table_arr, - (__u8 *)log_data_buf + stat_id_str_table_ofst, - (log_data->sitsz * 4)); - printf(" Statistics Identifier String Table\n"); - for (j = 0; j < stat_id_index; j++) { - printf(" Vendor Specific Statistic Identifier : 0x%x\n", - le16_to_cpu(stat_id_str_table_arr[j].vs_si)); - printf(" Reserved : 0x%x\n", - stat_id_str_table_arr[j].reserved1); - printf(" ASCII ID Length : 0x%x\n", - stat_id_str_table_arr[j].ascii_id_len); - printf(" ASCII ID offset : 0x%lx\n", - le64_to_cpu(stat_id_str_table_arr[j].ascii_id_ofst)); - printf(" Reserved : 0x%x\n", - stat_id_str_table_arr[j].reserved2); - } - } - - - if (log_data->estsz != 0) { - memcpy(event_id_str_table_arr, (__u8 *)log_data_buf + - event_str_table_ofst, (log_data->estsz * 4)); - printf(" Event Identifier String Table Entry\n"); - for (j = 0; j < eve_id_index; j++) { - printf(" Debug Event Class : 0x%x\n", - event_id_str_table_arr[j].deb_eve_class); - printf(" Event Identifier : 0x%x\n", - le16_to_cpu(event_id_str_table_arr[j].ei)); - printf(" ASCII ID Length : 0x%x\n", - event_id_str_table_arr[j].ascii_id_len); - printf(" ASCII ID offset : 0x%lx\n", - le64_to_cpu(event_id_str_table_arr[j].ascii_id_ofst)); - printf(" Reserved : 0x%x\n", - event_id_str_table_arr[j].reserved2); - - } - } - - if (log_data->vu_eve_st_sz != 0) { - memcpy(vu_event_id_str_table_arr, (__u8 *)log_data_buf + - vu_event_str_table_ofst, (log_data->vu_eve_st_sz * 4)); - printf(" VU Event Identifier String Table Entry\n"); - for (j = 0; j < vu_eve_index; j++) { - printf(" Debug Event Class : 0x%x\n", - vu_event_id_str_table_arr[j].deb_eve_class); - printf(" VU Event Identifier : 0x%x\n", - le16_to_cpu(vu_event_id_str_table_arr[j].vu_ei)); - printf(" ASCII ID Length : 0x%x\n", - vu_event_id_str_table_arr[j].ascii_id_len); - printf(" ASCII ID offset : 0x%lx\n", - le64_to_cpu(vu_event_id_str_table_arr[j].ascii_id_ofst)); - printf(" Reserved : 0x%x\n", - vu_event_id_str_table_arr[j].reserved); - - } - } - - if (log_data->asctsz != 0) { - printf(" ASCII Table\n"); - printf(" Byte Data_Byte ASCII_Character\n"); - for (j = 0; j < ascii_table_index; j++) - printf(" %lld %d %c\n", - ascii_table_ofst+j, log_data_buf[ascii_table_ofst + j], - (char)log_data_buf[ascii_table_ofst + j]); - } - - return 0; -} - -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]; - char *res = res_arr; - char guid_buf[C9_GUID_LENGTH]; - char *guid = guid_buf; - char fifo_arr[16]; - char *fifo = fifo_arr; - char buf[128]; - //calculating the index value for array - __le64 stat_id_index = (log_data->sitsz * 4) / 16; - __le64 eve_id_index = (log_data->estsz * 4) / 16; - __le64 vu_eve_index = (log_data->vu_eve_st_sz * 4) / 16; - __le64 ascii_table_index = (log_data->asctsz * 4); - //Calculating the offset for dynamic fields. - __le64 stat_id_str_table_ofst = log_data->sits * 4; - __le64 event_str_table_ofst = log_data->ests * 4; - __le64 vu_event_str_table_ofst = log_data->vu_eve_sts * 4; - __le64 ascii_table_ofst = log_data->ascts * 4; - struct statistics_id_str_table_entry stat_id_str_table_arr[stat_id_index]; - struct event_id_str_table_entry event_id_str_table_arr[eve_id_index]; - struct vu_event_id_str_table_entry vu_event_id_str_table_arr[vu_eve_index]; - __u8 ascii_table_info_arr[ascii_table_index]; - char ascii_buf[ascii_table_index]; - char *ascii = ascii_buf; - int j; - - json_object_add_value_int(root, "Log Page Version", le16_to_cpu(log_data->log_page_version)); - - memset((__u8 *)res, 0, 15); - for (j = 0; j < 15; j++) - res += sprintf(res, "%d", log_data->reserved1[j]); - json_object_add_value_string(root, "Reserved", res_arr); - - memset((void *)guid, 0, C9_GUID_LENGTH); - for (j = C9_GUID_LENGTH - 1; j >= 0; j--) - guid += sprintf(guid, "%02x", log_data->log_page_guid[j]); - json_object_add_value_string(root, "Log page GUID", guid_buf); - - json_object_add_value_int(root, "Telemetry String Log Size", le64_to_cpu(log_data->sls)); - - memset((__u8 *)res, 0, 24); - for (j = 0; j < 24; j++) - res += sprintf(res, "%d", log_data->reserved2[j]); - json_object_add_value_string(root, "Reserved", res_arr); - - json_object_add_value_int(root, "Statistics Identifier String Table Start", le64_to_cpu(log_data->sits)); - json_object_add_value_int(root, "Event String Table Start", le64_to_cpu(log_data->ests)); - json_object_add_value_int(root, "Event String Table Size", le64_to_cpu(log_data->estsz)); - json_object_add_value_int(root, "VU Event String Table Start", le64_to_cpu(log_data->vu_eve_sts)); - json_object_add_value_int(root, "VU Event String Table Size", le64_to_cpu(log_data->vu_eve_st_sz)); - json_object_add_value_int(root, "ASCII Table Start", le64_to_cpu(log_data->ascts)); - json_object_add_value_int(root, "ASCII Table Size", le64_to_cpu(log_data->asctsz)); - - memset((void *)fifo, 0, 16); - for (j = 0; j < 16; j++) - fifo += sprintf(fifo, "%c", log_data->fifo1[j]); - json_object_add_value_string(root, "FIFO 1 ASCII String", fifo_arr); - - memset((void *)fifo, 0, 16); - for (j = 0; j < 16; j++) - fifo += sprintf(fifo, "%c", log_data->fifo2[j]); - json_object_add_value_string(root, "FIFO 2 ASCII String", fifo_arr); - - memset((void *)fifo, 0, 16); - for (j = 0; j < 16; j++) - fifo += sprintf(fifo, "%c", log_data->fifo3[j]); - json_object_add_value_string(root, "FIFO 3 ASCII String", fifo_arr); - - memset((void *)fifo, 0, 16); - for (j = 0; j < 16; j++) - fifo += sprintf(fifo, "%c", log_data->fifo4[j]); - json_object_add_value_string(root, "FIFO 4 ASCII String", fifo_arr); - - memset((void *)fifo, 0, 16); - for (j = 0; j < 16; j++) - fifo += sprintf(fifo, "%c", log_data->fifo5[j]); - json_object_add_value_string(root, "FIFO 5 ASCII String", fifo_arr); - - memset((void *)fifo, 0, 16); - for (j = 0; j < 16; j++) - fifo += sprintf(fifo, "%c", log_data->fifo6[j]); - json_object_add_value_string(root, "FIFO 6 ASCII String", fifo_arr); - - memset((void *)fifo, 0, 16); - for (j = 0; j < 16; j++) - fifo += sprintf(fifo, "%c", log_data->fifo7[j]); - json_object_add_value_string(root, "FIFO 7 ASCII String", fifo_arr); - - memset((void *)fifo, 0, 16); - for (j = 0; j < 16; j++) - fifo += sprintf(fifo, "%c", log_data->fifo8[j]); - json_object_add_value_string(root, "FIFO 8 ASCII String", fifo_arr); - - memset((void *)fifo, 0, 16); - for (j = 0; j < 16; j++) - fifo += sprintf(fifo, "%c", log_data->fifo9[j]); - json_object_add_value_string(root, "FIFO 9 ASCII String", fifo_arr); - - memset((void *)fifo, 0, 16); - for (j = 0; j < 16; j++) - fifo += sprintf(fifo, "%c", log_data->fifo10[j]); - json_object_add_value_string(root, "FIFO 10 ASCII String", fifo_arr); - - memset((void *)fifo, 0, 16); - for (j = 0; j < 16; j++) - fifo += sprintf(fifo, "%c", log_data->fifo11[j]); - json_object_add_value_string(root, "FIFO 11 ASCII String", fifo_arr); - - memset((void *)fifo, 0, 16); - for (j = 0; j < 16; j++) - fifo += sprintf(fifo, "%c", log_data->fifo12[j]); - json_object_add_value_string(root, "FIFO 12 ASCII String", fifo_arr); - - memset((void *)fifo, 0, 16); - for (j = 0; j < 16; j++) - fifo += sprintf(fifo, "%c", log_data->fifo13[j]); - json_object_add_value_string(root, "FIFO 13 ASCII String", fifo_arr); - - memset((void *)fifo, 0, 16); - for (j = 0; j < 16; j++) - fifo += sprintf(fifo, "%c", log_data->fifo14[j]); - json_object_add_value_string(root, "FIFO 14 ASCII String", fifo_arr); - - memset((void *)fifo, 0, 16); - for (j = 0; j < 16; j++) - fifo += sprintf(fifo, "%c", log_data->fifo15[j]); - json_object_add_value_string(root, "FIFO 15 ASCII String", fifo_arr); - - memset((void *)fifo, 0, 16); - for (j = 0; j < 16; j++) - fifo += sprintf(fifo, "%c", log_data->fifo16[j]); - json_object_add_value_string(root, "FIFO 16 ASCII String", fifo_arr); - - memset((__u8 *)res, 0, 48); - for (j = 0; j < 48; j++) - res += sprintf(res, "%d", log_data->reserved3[j]); - json_object_add_value_string(root, "Reserved", res_arr); - - if (log_data->sitsz != 0) { - - memcpy(stat_id_str_table_arr, - (__u8 *)log_data_buf + stat_id_str_table_ofst, - (log_data->sitsz * 4)); - struct json_object *stat_table = json_create_object(); - - for (j = 0; j < stat_id_index; j++) { - struct json_object *entry = json_create_object(); - - json_object_add_value_uint(entry, "Vendor Specific Statistic Identifier", - le16_to_cpu(stat_id_str_table_arr[j].vs_si)); - json_object_add_value_uint(entry, "Reserved", - le64_to_cpu(stat_id_str_table_arr[j].reserved1)); - json_object_add_value_uint(entry, "ASCII ID Length", - le64_to_cpu(stat_id_str_table_arr[j].ascii_id_len)); - json_object_add_value_uint(entry, "ASCII ID offset", - le64_to_cpu(stat_id_str_table_arr[j].ascii_id_ofst)); - json_object_add_value_uint(entry, "Reserved2", - le64_to_cpu(stat_id_str_table_arr[j].reserved2)); - sprintf(buf, "Statistics Identifier String Table %d", j); - json_object_add_value_object(stat_table, buf, entry); - } - - json_object_add_value_object(root, - "Statistics Identifier String Table", stat_table); - } - - if (log_data->estsz != 0) { - struct json_object *eve_table = json_create_object(); - - memcpy(event_id_str_table_arr, - (__u8 *)log_data_buf + event_str_table_ofst, - (log_data->estsz * 4)); - for (j = 0; j < eve_id_index; j++) { - struct json_object *entry = json_create_object(); - - json_object_add_value_int(entry, "Debug Event Class", - le16_to_cpu(event_id_str_table_arr[j].deb_eve_class)); - json_object_add_value_int(entry, "Event Identifier", - le16_to_cpu(event_id_str_table_arr[j].ei)); - json_object_add_value_int(entry, "ASCII ID Length", - le64_to_cpu(event_id_str_table_arr[j].ascii_id_len)); - json_object_add_value_int(entry, "ASCII ID offset", - le64_to_cpu(event_id_str_table_arr[j].ascii_id_ofst)); - json_object_add_value_int(entry, "Reserved", - le64_to_cpu(event_id_str_table_arr[j].reserved2)); - sprintf(buf, "Event Identifier String Table Entry %d", j); - json_object_add_value_object(eve_table, buf, entry); - } - json_object_add_value_object(root, - "Event Identifier String Table Entry", - eve_table); - } - - if (log_data->vu_eve_st_sz != 0) { - struct json_object *vu_eve_table = json_create_object(); - - memcpy(vu_event_id_str_table_arr, - (__u8 *)log_data_buf + vu_event_str_table_ofst, - (log_data->vu_eve_st_sz * 4)); - for (j = 0; j < vu_eve_index; j++) { - struct json_object *entry = json_create_object(); - - json_object_add_value_int(entry, "Debug Event Class", - le16_to_cpu(vu_event_id_str_table_arr[j].deb_eve_class)); - json_object_add_value_int(entry, "VU Event Identifier", - le16_to_cpu(vu_event_id_str_table_arr[j].vu_ei)); - json_object_add_value_int(entry, "ASCII ID Length", - le64_to_cpu(vu_event_id_str_table_arr[j].ascii_id_len)); - json_object_add_value_int(entry, "ASCII ID offset", - le64_to_cpu(vu_event_id_str_table_arr[j].ascii_id_ofst)); - json_object_add_value_int(entry, "Reserved", - le64_to_cpu(vu_event_id_str_table_arr[j].reserved)); - sprintf(buf, "VU Event Identifier String Table Entry %d", j); - json_object_add_value_object(vu_eve_table, buf, entry); - } - json_object_add_value_object(root, - "VU Event Identifier String Table Entry", - vu_eve_table); - } - - if (log_data->asctsz != 0) { - memcpy(ascii_table_info_arr, - (__u8 *)log_data_buf + ascii_table_ofst, - (log_data->asctsz * 4)); - memset((void *)ascii, 0, ascii_table_index); - for (j = 0; j < ascii_table_index; j++) - ascii += sprintf(ascii, "%c", ascii_table_info_arr[j]); - json_object_add_value_string(root, "ASCII Table", ascii_buf); - } - - json_print_object(root, NULL); - printf("\n"); - json_free_object(root); - - return 0; -} - -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; - nvme_print_flags_t fmt; ret = validate_output_format(format, &fmt); @@ -3600,25 +2469,13 @@ static int get_c9_log_page(struct nvme_dev *dev, char *format) return ret; } - get_c9_log_page_data(dev, 1, 0); - + ret = get_c9_log_page_data(dev, 1, 0); if (!ret) { - 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 + ocp_c9_log(log_data, pC9_string_buffer, total_log_page_sz, fmt); + } else { fprintf(stderr, "ERROR : OCP : Unable to read C9 data from buffer\n"); + } + free(header_data); return ret; } @@ -3663,174 +2520,20 @@ static int ocp_telemetry_str_log_format(int argc, char **argv, struct command *c /// TCG Configuration Log Page (LID : C7h) /* C7 TCG Configuration Log Page */ -#define C7_GUID_LENGTH 16 #define C7_TCG_CONFIGURATION_LEN 512 #define C7_TCG_CONFIGURATION_OPCODE 0xC7 -#define C7_TCG_CONFIGURATION_LOG_VERSION 0x1 -static __u8 tcg_configuration_guid[C7_GUID_LENGTH] = { +static __u8 tcg_configuration_guid[GUID_LEN] = { 0x06, 0x40, 0x24, 0xBD, 0x7E, 0xE0, 0xE6, 0x83, 0xC0, 0x47, 0x54, 0xFA, 0x9D, 0x2A, 0xE0, 0x54 }; -/* - * struct tcg_configuration_log - TCG Configuration Log Page Structure - * @state: state - * @rsvd1: Reserved1 - * @locking_sp_act_count: Locking SP Activation Count - * @type_rev_count: Tper Revert Count - * @locking_sp_rev_count: Locking SP Revert Count. - * @no_of_locking_obj: Number of Locking Objects - * @no_of_single_um_locking_obj: Number of Single User Mode Locking Objects - * @no_of_range_prov_locking_obj: Number of Range Provisioned Locking Objects - * @no_of_ns_prov_locking_obj: Number of Namespace Provisioned Locking Objects - * @no_of_read_lock_locking_obj: Number of Read Locked Locking Objects - * @no_of_write_lock_locking_obj: Number of Write Locked Locking Objects - * @no_of_read_unlock_locking_obj: Number of Read Unlocked Locking Objects - * @no_of_read_unlock_locking_obj: Number of Write Unlocked Locking Objects - * @rsvd2: Reserved2 - * @sid_auth_try_count: SID Authentication Try Count - * @sid_auth_try_limit: SID Authentication Try Limit - * @pro_tcg_rc: Programmatic TCG Reset Count - * @pro_rlc: Programmatic Reset Lock Count - * @tcg_ec: TCG Error Count - * @rsvd3: Reserved3 - * @log_page_version: Log Page Version - */ -struct __packed tcg_configuration_log { - __u8 state; - __u8 rsvd1[3]; - __u8 locking_sp_act_count; - __u8 type_rev_count; - __u8 locking_sp_rev_count; - __u8 no_of_locking_obj; - __u8 no_of_single_um_locking_obj; - __u8 no_of_range_prov_locking_obj; - __u8 no_of_ns_prov_locking_obj; - __u8 no_of_read_lock_locking_obj; - __u8 no_of_write_lock_locking_obj; - __u8 no_of_read_unlock_locking_obj; - __u8 no_of_write_unlock_locking_obj; - __u8 rsvd2; - __u32 sid_auth_try_count; - __u32 sid_auth_try_limit; - __u32 pro_tcg_rc; - __u32 pro_rlc; - __u32 tcg_ec; - __u8 rsvd3[458]; - __le16 log_page_version; - __u8 log_page_guid[C7_GUID_LENGTH]; - -}; - /* Function declaration for TCG Configuration log page (LID:C7h) */ static int ocp_tcg_configuration_log(int argc, char **argv, struct command *cmd, struct plugin *plugin); -static int ocp_print_C7_log_normal(struct nvme_dev *dev, - struct tcg_configuration_log *log_data) -{ - int j; - - printf("TCG Configuration C7 Log Page Data-\n"); - - printf(" State : 0x%x\n", log_data->state); - printf(" Reserved1 : 0x"); - for (j = 0; j < 3; j++) - printf("%d", log_data->rsvd1[j]); - printf("\n"); - printf(" Locking SP Activation Count : 0x%x\n", log_data->locking_sp_act_count); - printf(" Tper Revert Count : 0x%x\n", log_data->type_rev_count); - printf(" Locking SP Revert Count : 0x%x\n", log_data->locking_sp_rev_count); - printf(" Number of Locking Objects : 0x%x\n", log_data->no_of_locking_obj); - printf(" Number of Single User Mode Locking Objects : 0x%x\n", log_data->no_of_single_um_locking_obj); - printf(" Number of Range Provisioned Locking Objects : 0x%x\n", log_data->no_of_range_prov_locking_obj); - printf(" Number of Namespace Provisioned Locking Objects : 0x%x\n", log_data->no_of_ns_prov_locking_obj); - printf(" Number of Read Locked Locking Objects : 0x%x\n", log_data->no_of_read_lock_locking_obj); - printf(" Number of Write Locked Locking Objects : 0x%x\n", log_data->no_of_write_lock_locking_obj); - printf(" Number of Read Unlocked Locking Objects : 0x%x\n", log_data->no_of_read_unlock_locking_obj); - printf(" Number of Write Unlocked Locking Objects : 0x%x\n", log_data->no_of_write_unlock_locking_obj); - printf(" Reserved2 : 0x%x\n", log_data->rsvd2); - - printf(" SID Authentication Try Count : 0x%x\n", le32_to_cpu(log_data->sid_auth_try_count)); - printf(" SID Authentication Try Limit : 0x%x\n", le32_to_cpu(log_data->sid_auth_try_limit)); - printf(" Programmatic TCG Reset Count : 0x%x\n", le32_to_cpu(log_data->pro_tcg_rc)); - printf(" Programmatic Reset Lock Count : 0x%x\n", le32_to_cpu(log_data->pro_rlc)); - printf(" TCG Error Count : 0x%x\n", le32_to_cpu(log_data->tcg_ec)); - - printf(" Reserved3 : 0x"); - for (j = 0; j < 458; j++) - printf("%d", log_data->rsvd3[j]); - printf("\n"); - - printf(" Log Page Version : 0x%x\n", le16_to_cpu(log_data->log_page_version)); - printf(" Log page GUID : 0x"); - for (j = C7_GUID_LENGTH - 1; j >= 0; j--) - printf("%x", log_data->log_page_guid[j]); - printf("\n"); - - return 0; -} - -static void ocp_print_C7_log_json(struct tcg_configuration_log *log_data) -{ - int j; - struct json_object *root; - char guid_buf[C7_GUID_LENGTH]; - char *guid = guid_buf; - char res_arr[458]; - char *res = res_arr; - - root = json_create_object(); - - json_object_add_value_int(root, "State", le16_to_cpu(log_data->state)); - memset((__u8 *)res, 0, 3); - for (j = 0; j < 3; j++) - res += sprintf(res, "%d", log_data->rsvd1[j]); - json_object_add_value_string(root, "Reserved1", res_arr); - json_object_add_value_int(root, "Locking SP Activation Count", le16_to_cpu(log_data->locking_sp_act_count)); - json_object_add_value_int(root, "Tper Revert Count", le16_to_cpu(log_data->locking_sp_rev_count)); - json_object_add_value_int(root, "Number of Locking Objects", le16_to_cpu(log_data->no_of_locking_obj)); - json_object_add_value_int(root, "Number of Single User Mode Locking Objects", le16_to_cpu(log_data->no_of_single_um_locking_obj)); - json_object_add_value_int(root, "Number of Range Provisioned Locking Objects", le16_to_cpu(log_data->no_of_range_prov_locking_obj)); - json_object_add_value_int(root, "Number of Namespace Provisioned Locking Objects", le16_to_cpu(log_data->no_of_ns_prov_locking_obj)); - json_object_add_value_int(root, "Number of Read Locked Locking Objects", le16_to_cpu(log_data->no_of_read_lock_locking_obj)); - json_object_add_value_int(root, "Number of Write Locked Locking Objects", le16_to_cpu(log_data->no_of_write_lock_locking_obj)); - json_object_add_value_int(root, "Number of Read Unlocked Locking Objects", le16_to_cpu(log_data->no_of_read_unlock_locking_obj)); - json_object_add_value_int(root, "Number of Write Unlocked Locking Objects", le16_to_cpu(log_data->no_of_write_unlock_locking_obj)); - json_object_add_value_int(root, "Reserved2", le16_to_cpu(log_data->rsvd2)); - - json_object_add_value_int(root, "SID Authentication Try Count", le16_to_cpu(log_data->sid_auth_try_count)); - json_object_add_value_int(root, "SID Authentication Try Limit", le16_to_cpu(log_data->sid_auth_try_limit)); - json_object_add_value_int(root, "Programmatic TCG Reset Count", le16_to_cpu(log_data->pro_tcg_rc)); - json_object_add_value_int(root, "Programmatic Reset Lock Count", le16_to_cpu(log_data->pro_rlc)); - json_object_add_value_int(root, "TCG Error Count", le16_to_cpu(log_data->tcg_ec)); - - memset((__u8 *)res, 0, 458); - for (j = 0; j < 458; j++) - res += sprintf(res, "%d", log_data->rsvd3[j]); - json_object_add_value_string(root, "Reserved3", res_arr); - - json_object_add_value_int(root, "Log Page Version", le16_to_cpu(log_data->log_page_version)); - - memset((void *)guid, 0, C7_GUID_LENGTH); - for (j = C7_GUID_LENGTH - 1; j >= 0; j--) - guid += sprintf(guid, "%02x", log_data->log_page_guid[j]); - json_object_add_value_string(root, "Log page GUID", guid_buf); - - json_print_object(root, NULL); - printf("\n"); - - json_free_object(root); -} - -static void ocp_print_c7_log_binary(struct tcg_configuration_log *log_data) -{ - return d_raw((unsigned char *)log_data, sizeof(*log_data)); -} - static int get_c7_log_page(struct nvme_dev *dev, char *format) { nvme_print_flags_t fmt; @@ -3858,13 +2561,6 @@ static int get_c7_log_page(struct nvme_dev *dev, char *format) if (!ret) { log_data = (struct tcg_configuration_log *)data; - /* check log page version */ - if (log_data->log_page_version != C7_TCG_CONFIGURATION_LOG_VERSION) { - fprintf(stderr, "ERROR : OCP : invalid TCG Configuration Log Page version\n"); - ret = -1; - goto out; - } - /* * check log page guid * Verify GUID matches @@ -3874,30 +2570,17 @@ static int get_c7_log_page(struct nvme_dev *dev, char *format) fprintf(stderr, "ERROR : OCP : Unknown GUID in C7 Log Page data\n"); fprintf(stderr, "ERROR : OCP : Expected GUID: 0x"); for (j = 0; j < 16; j++) - fprintf(stderr, "%x", tcg_configuration_guid[j]); + fprintf(stderr, "%02x", tcg_configuration_guid[j]); fprintf(stderr, "\nERROR : OCP : Actual GUID: 0x"); for (j = 0; j < 16; j++) - fprintf(stderr, "%x", log_data->log_page_guid[j]); + fprintf(stderr, "%02x", log_data->log_page_guid[j]); fprintf(stderr, "\n"); ret = -1; goto out; } } - - switch (fmt) { - case NORMAL: - ocp_print_C7_log_normal(dev, log_data); - break; - case JSON: - ocp_print_C7_log_json(log_data); - break; - case BINARY: - ocp_print_c7_log_binary(log_data); - break; - default: - break; - } + ocp_c7_log(dev, log_data, fmt); } else { fprintf(stderr, "ERROR : OCP : Unable to read C7 data from buffer\n"); } @@ -3907,7 +2590,6 @@ out: return ret; } - static int ocp_tcg_configuration_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { @@ -4143,3 +2825,72 @@ static int set_error_injection(int argc, char **argv, struct command *cmd, struc return error_injection_set(dev, &cfg, !argconfig_parse_seen(opts, "no-uuid")); } + +static int enable_ieee1667_silo_get(struct nvme_dev *dev, const __u8 sel, bool uuid) +{ + struct ieee1667_get_cq_entry cq_entry; + int err; + const __u8 fid = 0xc4; + + struct nvme_get_features_args args = { + .result = (__u32 *)&cq_entry, + .args_size = sizeof(args), + .fd = dev_fd(dev), + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .sel = sel, + .fid = fid, + }; + + if (uuid) { + /* OCP 2.0 requires UUID index support */ + err = ocp_get_uuid_index(dev, &args.uuidx); + if (err || !args.uuidx) { + nvme_show_error("ERROR: No OCP UUID index found"); + return err; + } + } + + err = nvme_cli_get_features(dev, &args); + if (!err) { + if (sel == NVME_GET_FEATURES_SEL_SUPPORTED) + nvme_show_select_result(fid, *args.result); + else + nvme_show_result("IEEE1667 Sifo Enabled (feature: 0x%02x): 0x%0x (%s: %s)", + fid, cq_entry.enabled, nvme_select_to_string(sel), + cq_entry.enabled ? "enabled" : "disabled"); + } else { + nvme_show_error("Could not get feature: 0x%02x.", fid); + } + + return err; +} + +static int get_enable_ieee1667_silo(int argc, char **argv, struct command *cmd, + struct plugin *plugin) +{ + const char *desc = "return set of enable IEEE1667 silo"; + int err; + struct config { + __u8 sel; + }; + struct config cfg = { 0 }; + + _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; + + OPT_ARGS(opts) = { + OPT_BYTE("sel", 's', &cfg.sel, sel), + OPT_FLAG("no-uuid", 'n', NULL, no_uuid), + OPT_END() + }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; + + return enable_ieee1667_silo_get(dev, cfg.sel, !argconfig_parse_seen(opts, "no-uuid")); +} + +static int hwcomp_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + return ocp_hwcomp_log(argc, argv, cmd, plugin); +} diff --git a/plugins/ocp/ocp-nvme.h b/plugins/ocp/ocp-nvme.h index 16d929d..04acbfc 100644 --- a/plugins/ocp/ocp-nvme.h +++ b/plugins/ocp/ocp-nvme.h @@ -11,7 +11,7 @@ #if !defined(OCP_NVME) || defined(CMD_HEADER_MULTI_READ) #define OCP_NVME -#define OCP_PLUGIN_VERSION "2.9.0" +#define OCP_PLUGIN_VERSION "2.9.2" #include "cmd.h" PLUGIN(NAME("ocp", "OCP cloud SSD extensions", OCP_PLUGIN_VERSION), @@ -38,9 +38,207 @@ PLUGIN(NAME("ocp", "OCP cloud SSD extensions", OCP_PLUGIN_VERSION), ENTRY("tcg-configuration-log", "Retrieve TCG Configuration Log Page", ocp_tcg_configuration_log) ENTRY("get-error-injection", "Return set of error injection", get_error_injection) ENTRY("set-error-injection", "Inject error conditions", set_error_injection) + ENTRY("get-enable-ieee1667-silo", "return set of enable IEEE1667 silo", + get_enable_ieee1667_silo) + ENTRY("hardware-component-log", "retrieve hardware component log", hwcomp_log) ) ); #endif #include "define_cmd.h" + +#ifndef OCP_NVME_H +#define OCP_NVME_H +struct __packed ssd_latency_monitor_log { + __u8 feature_status; /* 0x00 */ + __u8 rsvd1; /* 0x01 */ + __le16 active_bucket_timer; /* 0x02 */ + __le16 active_bucket_timer_threshold; /* 0x04 */ + __u8 active_threshold_a; /* 0x06 */ + __u8 active_threshold_b; /* 0x07 */ + __u8 active_threshold_c; /* 0x08 */ + __u8 active_threshold_d; /* 0x09 */ + __le16 active_latency_config; /* 0x0A */ + __u8 active_latency_min_window; /* 0x0C */ + __u8 rsvd2[0x13]; /* 0x0D */ + + __le32 active_bucket_counter[4][4]; /* 0x20 - 0x5F */ + __le64 active_latency_timestamp[4][3]; /* 0x60 - 0xBF */ + __le16 active_measured_latency[4][3]; /* 0xC0 - 0xD7 */ + __le16 active_latency_stamp_units; /* 0xD8 */ + __u8 rsvd3[0x16]; /* 0xDA */ + + __le32 static_bucket_counter[4][4]; /* 0x0F0 - 0x12F */ + __le64 static_latency_timestamp[4][3]; /* 0x130 - 0x18F */ + __le16 static_measured_latency[4][3]; /* 0x190 - 0x1A7 */ + __le16 static_latency_stamp_units; /* 0x1A8 */ + __u8 rsvd4[0x16]; /* 0x1AA */ + + __le16 debug_log_trigger_enable; /* 0x1C0 */ + __le16 debug_log_measured_latency; /* 0x1C2 */ + __le64 debug_log_latency_stamp; /* 0x1C4 */ + __le16 debug_log_ptr; /* 0x1CC */ + __le16 debug_log_counter_trigger; /* 0x1CE */ + __u8 debug_log_stamp_units; /* 0x1D0 */ + __u8 rsvd5[0x1D]; /* 0x1D1 */ + + __le16 log_page_version; /* 0x1EE */ + __u8 log_page_guid[0x10]; /* 0x1F0 */ +}; + +#define GUID_LEN 16 + +#define C3_ACTIVE_BUCKET_TIMER_INCREMENT 5 +#define C3_ACTIVE_THRESHOLD_INCREMENT 5 +#define C3_MINIMUM_WINDOW_INCREMENT 100 +#define C3_BUCKET_NUM 4 + +#define READ 3 +#define WRITE 2 +#define TRIM 1 + +#define C5_NUM_UNSUPPORTED_REQ_ENTRIES 253 + +/* + * struct unsupported_requirement_log - unsupported requirement list + * @unsupported_count: Number of Unsupported Requirement IDs + * @rsvd1: Reserved + * @unsupported_req_list: Unsupported Requirements lists up to 253. + * @rsvd2: Reserved + * @log_page_version: indicates the version of the mapping this log page uses. + * Shall be set to 0001h + * @log_page_guid: Shall be set to C7BB98B7D0324863BB2C23990E9C722Fh. + */ +struct __packed unsupported_requirement_log { + __le16 unsupported_count; + __u8 rsvd1[14]; + __u8 unsupported_req_list[C5_NUM_UNSUPPORTED_REQ_ENTRIES][16]; + __u8 rsvd2[14]; + __le16 log_page_version; + __u8 log_page_guid[GUID_LEN]; +}; + +#define C1_PREV_PANIC_IDS_LENGTH 4 + +/** + * struct ocp_error_recovery_log_page - Error Recovery Log Page + * @panic_reset_wait_time: Panic Reset Wait Time + * @panic_reset_action: Panic Reset Action + * @device_recover_action_1: Device Recovery Action 1 + * @panic_id: Panic ID + * @device_capabilities: Device Capabilities + * @vendor_specific_recovery_opcode: Vendor Specific Recovery Opcode + * @reserved: Reserved + * @vendor_specific_command_cdw12: Vendor Specific Command CDW12 + * @vendor_specific_command_cdw13: Vendor Specific Command CDW13 + * @vendor_specific_command_timeout: Vendor Specific Command Timeout + * @device_recover_action_2: Device Recovery Action 2 + * @device_recover_action_2_timeout: Device Recovery Action 2 Timeout + * @panic_count: Panic Count + * @prev_panic_id: Previous Panic IDs + * @reserved2: Reserved + * @log_page_version: Log Page Version + * @log_page_guid: Log Page GUID + */ +struct __packed ocp_error_recovery_log_page { + __le16 panic_reset_wait_time; /* 2 bytes - 0x00 - 0x01 */ + __u8 panic_reset_action; /* 1 byte - 0x02 */ + __u8 device_recover_action_1; /* 1 byte - 0x03 */ + __le64 panic_id; /* 8 bytes - 0x04 - 0x0B */ + __le32 device_capabilities; /* 4 bytes - 0x0C - 0x0F */ + __u8 vendor_specific_recovery_opcode; /* 1 byte - 0x10 */ + __u8 reserved[0x3]; /* 3 bytes - 0x11 - 0x13 */ + __le32 vendor_specific_command_cdw12; /* 4 bytes - 0x14 - 0x17 */ + __le32 vendor_specific_command_cdw13; /* 4 bytes - 0x18 - 0x1B */ + __u8 vendor_specific_command_timeout; /* 1 byte - 0x1C */ + __u8 device_recover_action_2; /* 1 byte - 0x1D */ + __u8 device_recover_action_2_timeout; /* 1 byte - 0x1E */ + __u8 panic_count; /* 1 byte - 0x1F */ + __le64 prev_panic_id[C1_PREV_PANIC_IDS_LENGTH]; /* 32 bytes - 0x20 - 0x3F */ + __u8 reserved2[0x1ae]; /* 430 bytes - 0x40 - 0x1ED */ + __le16 log_page_version; /* 2 bytes - 0x1EE - 0x1EF */ + __u8 log_page_guid[GUID_LEN]; /* 16 bytes - 0x1F0 - 0x1FF */ +}; + +/** + * struct ocp_device_capabilities_log_page - Device Capability Log page + * @pcie_exp_port: PCI Express Ports + * @oob_management_support: OOB Management Support + * @wz_cmd_support: Write Zeroes Command Support + * @sanitize_cmd_support: Sanitize Command Support + * @dsm_cmd_support: Dataset Management Command Support + * @wu_cmd_support: Write Uncorrectable Command Support + * @fused_operation_support: Fused Operation Support + * @min_valid_dssd_pwr_state: Minimum Valid DSSD Power State + * @dssd_pwr_state_desc: DSSD Power State Descriptors + * @vendor_specific_command_timeout: Vendor Specific Command Timeout + * @reserved: Reserved + * @log_page_version: Log Page Version + * @log_page_guid: Log Page GUID + */ +struct __packed ocp_device_capabilities_log_page { + __le16 pcie_exp_port; + __le16 oob_management_support; + __le16 wz_cmd_support; + __le16 sanitize_cmd_support; + __le16 dsm_cmd_support; + __le16 wu_cmd_support; + __le16 fused_operation_support; + __le16 min_valid_dssd_pwr_state; + __u8 dssd_pwr_state_desc[128]; + __u8 reserved[3934]; + __le16 log_page_version; + __u8 log_page_guid[GUID_LEN]; +}; + +/* + * struct tcg_configuration_log - TCG Configuration Log Page Structure + * @state: state + * @rsvd1: Reserved1 + * @locking_sp_act_count: Locking SP Activation Count + * @type_rev_count: Tper Revert Count + * @locking_sp_rev_count: Locking SP Revert Count. + * @no_of_locking_obj: Number of Locking Objects + * @no_of_single_um_locking_obj: Number of Single User Mode Locking Objects + * @no_of_range_prov_locking_obj: Number of Range Provisioned Locking Objects + * @no_of_ns_prov_locking_obj: Number of Namespace Provisioned Locking Objects + * @no_of_read_lock_locking_obj: Number of Read Locked Locking Objects + * @no_of_write_lock_locking_obj: Number of Write Locked Locking Objects + * @no_of_read_unlock_locking_obj: Number of Read Unlocked Locking Objects + * @no_of_read_unlock_locking_obj: Number of Write Unlocked Locking Objects + * @rsvd2: Reserved2 + * @sid_auth_try_count: SID Authentication Try Count + * @sid_auth_try_limit: SID Authentication Try Limit + * @pro_tcg_rc: Programmatic TCG Reset Count + * @pro_rlc: Programmatic Reset Lock Count + * @tcg_ec: TCG Error Count + * @rsvd3: Reserved3 + * @log_page_version: Log Page Version + */ +struct __packed tcg_configuration_log { + __u8 state; + __u8 rsvd1[3]; + __u8 locking_sp_act_count; + __u8 type_rev_count; + __u8 locking_sp_rev_count; + __u8 no_of_locking_obj; + __u8 no_of_single_um_locking_obj; + __u8 no_of_range_prov_locking_obj; + __u8 no_of_ns_prov_locking_obj; + __u8 no_of_read_lock_locking_obj; + __u8 no_of_write_lock_locking_obj; + __u8 no_of_read_unlock_locking_obj; + __u8 no_of_write_unlock_locking_obj; + __u8 rsvd2; + __le32 sid_auth_try_count; + __le32 sid_auth_try_limit; + __le32 pro_tcg_rc; + __le32 pro_rlc; + __le32 tcg_ec; + __u8 rsvd3[458]; + __le16 log_page_version; + __u8 log_page_guid[GUID_LEN]; + +}; +#endif /* OCP_NVME_H */ diff --git a/plugins/ocp/ocp-print-binary.c b/plugins/ocp/ocp-print-binary.c new file mode 100644 index 0000000..64e1246 --- /dev/null +++ b/plugins/ocp/ocp-print-binary.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "util/types.h" +#include "nvme-print.h" +#include "ocp-print.h" +#include "ocp-hardware-component-log.h" + +static void binary_hwcomp_log(struct hwcomp_log *log, __u32 id, bool list) +{ + long double desc_len = uint128_t_to_double(le128_to_cpu(log->size)) * sizeof(__le32); + + d_raw((unsigned char *)log, offsetof(struct hwcomp_log, desc) + desc_len); +} + +static void binary_c5_log(struct nvme_dev *dev, struct unsupported_requirement_log *log_data) +{ + d_raw((unsigned char *)log_data, sizeof(*log_data)); +} + +static void binary_c1_log(struct ocp_error_recovery_log_page *log_data) +{ + d_raw((unsigned char *)log_data, sizeof(*log_data)); +} + +static void binary_c4_log(struct ocp_device_capabilities_log_page *log_data) +{ + d_raw((unsigned char *)log_data, sizeof(*log_data)); +} + +static void binary_c9_log(struct telemetry_str_log_format *log_data, __u8 *log_data_buf, + int total_log_page_size) +{ + d_raw((unsigned char *)log_data_buf, total_log_page_size); +} + +static void binary_c7_log(struct nvme_dev *dev, struct tcg_configuration_log *log_data) +{ + d_raw((unsigned char *)log_data, sizeof(*log_data)); +} + +static struct ocp_print_ops binary_print_ops = { + .hwcomp_log = binary_hwcomp_log, + .c5_log = binary_c5_log, + .c1_log = binary_c1_log, + .c4_log = binary_c4_log, + .c9_log = binary_c9_log, + .c7_log = binary_c7_log, +}; + +struct ocp_print_ops *ocp_get_binary_print_ops(nvme_print_flags_t flags) +{ + binary_print_ops.flags = flags; + return &binary_print_ops; +} diff --git a/plugins/ocp/ocp-print-json.c b/plugins/ocp/ocp-print-json.c new file mode 100644 index 0000000..a600628 --- /dev/null +++ b/plugins/ocp/ocp-print-json.c @@ -0,0 +1,851 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include "util/types.h" +#include "common.h" +#include "nvme-print.h" +#include "ocp-print.h" +#include "ocp-hardware-component-log.h" +#include "ocp-fw-activation-history.h" +#include "ocp-smart-extended-log.h" +#include "ocp-telemetry-decode.h" +#include "ocp-nvme.h" + +static void print_hwcomp_desc_json(struct hwcomp_desc_entry *e, struct json_object *r) +{ + obj_add_str(r, "Description", hwcomp_id_to_string(le32_to_cpu(e->desc->id))); + obj_add_nprix64(r, "Date/Lot Size", e->date_lot_size); + obj_add_nprix64(r, "Additional Information Size", e->add_info_size); + obj_add_uint_0nx(r, "Identifier", le32_to_cpu(e->desc->id), 8); + obj_add_0nprix64(r, "Manufacture", le64_to_cpu(e->desc->mfg), 16); + obj_add_0nprix64(r, "Revision", le64_to_cpu(e->desc->rev), 16); + obj_add_0nprix64(r, "Manufacture Code", le64_to_cpu(e->desc->mfg_code), 16); + obj_add_byte_array(r, "Date/Lot Code", e->date_lot_code, e->date_lot_size); + obj_add_byte_array(r, "Additional Information", e->add_info, e->add_info_size); +} + +static void print_hwcomp_desc_list_json(struct json_object *r, struct hwcomp_desc_entry *e, + bool list, int num) +{ + _cleanup_free_ char *k = NULL; + + if (asprintf(&k, "Component %d", num) < 0) + return; + + if (list) { + obj_add_str(r, k, hwcomp_id_to_string(le32_to_cpu(e->desc->id))); + return; + } + + print_hwcomp_desc_json(e, obj_create_array_obj(r, k)); +} + +static void print_hwcomp_descs_json(struct hwcomp_desc *desc, long double log_size, __u32 id, + bool list, struct json_object *r) +{ + size_t date_lot_code_offset = sizeof(struct hwcomp_desc); + struct hwcomp_desc_entry e = { desc }; + int num = 1; + + while (log_size > 0) { + e.date_lot_size = le64_to_cpu(e.desc->date_lot_size) * sizeof(__le32); + e.date_lot_code = e.date_lot_size ? + (__u8 *)e.desc + date_lot_code_offset : NULL; + e.add_info_size = le64_to_cpu(e.desc->add_info_size) * sizeof(__le32); + e.add_info = e.add_info_size ? e.date_lot_code ? + e.date_lot_code + e.date_lot_size : + (__u8 *)e.desc + date_lot_code_offset : NULL; + if (!id || id == le32_to_cpu(e.desc->id)) + print_hwcomp_desc_list_json(r, &e, list, num++); + e.desc_size = date_lot_code_offset + e.date_lot_size + e.add_info_size; + e.desc = (struct hwcomp_desc *)((__u8 *)e.desc + e.desc_size); + log_size -= e.desc_size; + } +} + +static void json_hwcomp_log(struct hwcomp_log *log, __u32 id, bool list) +{ + struct json_object *r = json_create_object(); + + long double log_size = uint128_t_to_double(le128_to_cpu(log->size)) * sizeof(__le32); + + obj_add_uint_02x(r, "Log Identifier", LID_HWCOMP); + obj_add_uint_0x(r, "Log Page Version", le16_to_cpu(log->ver)); + obj_add_byte_array(r, "Reserved2", log->rsvd2, ARRAY_SIZE(log->rsvd2)); + obj_add_byte_array(r, "Log page GUID", log->guid, ARRAY_SIZE(log->guid)); + obj_add_nprix64(r, "Hardware Component Log Size", (unsigned long long)log_size); + obj_add_byte_array(r, "Reserved48", log->rsvd48, ARRAY_SIZE(log->rsvd48)); + print_hwcomp_descs_json(log->desc, log_size, id, list, + obj_create_array_obj(r, "Component Descriptions")); + + json_print(r); +} + +static void json_fw_activation_history(const struct fw_activation_history *fw_history) +{ + struct json_object *root = json_create_object(); + + json_object_add_value_uint(root, "log identifier", fw_history->log_id); + json_object_add_value_uint(root, "valid entries", le32_to_cpu(fw_history->valid_entries)); + + struct json_object *entries = json_create_array(); + + for (int index = 0; index < le32_to_cpu(fw_history->valid_entries); index++) { + const struct fw_activation_history_entry *entry = &fw_history->entries[index]; + struct json_object *entry_obj = json_create_object(); + + json_object_add_value_uint(entry_obj, "version number", entry->ver_num); + json_object_add_value_uint(entry_obj, "entry length", entry->entry_length); + json_object_add_value_uint(entry_obj, "activation count", + le16_to_cpu(entry->activation_count)); + json_object_add_value_uint64(entry_obj, "timestamp", + (0x0000FFFFFFFFFFFF & le64_to_cpu(entry->timestamp))); + json_object_add_value_uint(entry_obj, "power cycle count", + le64_to_cpu(entry->power_cycle_count)); + + struct json_object *fw = json_object_new_string_len(entry->previous_fw, + sizeof(entry->previous_fw)); + + json_object_add_value_object(entry_obj, "previous firmware", fw); + + fw = json_object_new_string_len(entry->new_fw, sizeof(entry->new_fw)); + + json_object_add_value_object(entry_obj, "new firmware", fw); + json_object_add_value_uint(entry_obj, "slot number", entry->slot_number); + json_object_add_value_uint(entry_obj, "commit action type", entry->commit_action); + json_object_add_value_uint(entry_obj, "result", le16_to_cpu(entry->result)); + + json_array_add_value_object(entries, entry_obj); + } + + json_object_add_value_array(root, "entries", entries); + + json_object_add_value_uint(root, "log page version", + le16_to_cpu(fw_history->log_page_version)); + + char guid[2 * sizeof(fw_history->log_page_guid) + 3] = { 0 }; + + sprintf(guid, "0x%"PRIx64"%"PRIx64"", + le64_to_cpu(fw_history->log_page_guid[1]), + le64_to_cpu(fw_history->log_page_guid[0])); + json_object_add_value_string(root, "log page guid", guid); + + json_print_object(root, NULL); + json_free_object(root); + + printf("\n"); +} + +static void json_smart_extended_log(void *data) +{ + struct json_object *root; + struct json_object *pmuw; + struct json_object *pmur; + uint16_t smart_log_ver = 0; + __u8 *log_data = data; + char guid[40]; + + root = json_create_object(); + pmuw = json_create_object(); + pmur = json_create_object(); + + json_object_add_value_uint64(pmuw, "hi", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW + 8] & 0xFFFFFFFFFFFFFFFF)); + json_object_add_value_uint64(pmuw, "lo", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW] & 0xFFFFFFFFFFFFFFFF)); + json_object_add_value_object(root, "Physical media units written", pmuw); + json_object_add_value_uint64(pmur, "hi", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR + 8] & 0xFFFFFFFFFFFFFFFF)); + json_object_add_value_uint64(pmur, "lo", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR] & 0xFFFFFFFFFFFFFFFF)); + json_object_add_value_object(root, "Physical media units read", pmur); + json_object_add_value_uint64(root, "Bad user nand blocks - Raw", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BUNBR] & 0x0000FFFFFFFFFFFF)); + json_object_add_value_uint(root, "Bad user nand blocks - Normalized", + (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BUNBN])); + json_object_add_value_uint64(root, "Bad system nand blocks - Raw", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BSNBR] & 0x0000FFFFFFFFFFFF)); + json_object_add_value_uint(root, "Bad system nand blocks - Normalized", + (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BSNBN])); + json_object_add_value_uint64(root, "XOR recovery count", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_XRC])); + json_object_add_value_uint64(root, "Uncorrectable read error count", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UREC])); + json_object_add_value_uint64(root, "Soft ecc error count", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SEEC])); + json_object_add_value_uint(root, "End to end detected errors", + (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EEDC])); + json_object_add_value_uint(root, "End to end corrected errors", + (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EECE])); + json_object_add_value_uint(root, "System data percent used", + (__u8)log_data[SCAO_SDPU]); + json_object_add_value_uint64(root, "Refresh counts", + (uint64_t)(le64_to_cpu(*(uint64_t *)&log_data[SCAO_RFSC]) & 0x00FFFFFFFFFFFFFF)); + json_object_add_value_uint(root, "Max User data erase counts", + (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MXUDEC])); + json_object_add_value_uint(root, "Min User data erase counts", + (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MNUDEC])); + json_object_add_value_uint(root, "Number of Thermal throttling events", + (__u8)log_data[SCAO_NTTE]); + json_object_add_value_uint(root, "Current throttling status", + (__u8)log_data[SCAO_CTS]); + json_object_add_value_uint64(root, "PCIe correctable error count", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PCEC])); + json_object_add_value_uint(root, "Incomplete shutdowns", + (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_ICS])); + json_object_add_value_uint(root, "Percent free blocks", + (__u8)log_data[SCAO_PFB]); + json_object_add_value_uint(root, "Capacitor health", + (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_CPH])); + json_object_add_value_uint64(root, "Unaligned I/O", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UIO])); + json_object_add_value_uint64(root, "Security Version Number", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SVN])); + json_object_add_value_uint64(root, "NUSE - Namespace utilization", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_NUSE])); + json_object_add_value_uint128(root, "PLP start count", + le128_to_cpu(&log_data[SCAO_PSC])); + json_object_add_value_uint128(root, "Endurance estimate", + le128_to_cpu(&log_data[SCAO_EEST])); + smart_log_ver = (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_LPV]); + + json_object_add_value_uint(root, "Log page version", smart_log_ver); + + memset((void *)guid, 0, 40); + sprintf((char *)guid, "0x%"PRIx64"%"PRIx64"", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG + 8]), + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG])); + json_object_add_value_string(root, "Log page GUID", guid); + + switch (smart_log_ver) { + case 0 ... 1: + break; + default: + case 4: + json_object_add_value_uint(root, "NVMe Command Set Errata Version", + (__u8)log_data[SCAO_NCSEV]); + json_object_add_value_uint(root, "Lowest Permitted Firmware Revision", + le64_to_cpu(*(uint64_t *)&log_data[SCAO_PSCC])); + fallthrough; + case 2 ... 3: + json_object_add_value_uint(root, "Errata Version Field", + (__u8)log_data[SCAO_EVF]); + json_object_add_value_uint(root, "Point Version Field", + le16_to_cpu(*(uint16_t *)&log_data[SCAO_PVF])); + json_object_add_value_uint(root, "Minor Version Field", + le16_to_cpu(*(uint16_t *)&log_data[SCAO_MIVF])); + json_object_add_value_uint(root, "Major Version Field", + (__u8)log_data[SCAO_MAVF]); + json_object_add_value_uint(root, "NVMe Base Errata Version", + (__u8)log_data[SCAO_NBEV]); + json_object_add_value_uint(root, "PCIe Link Retraining Count", + le64_to_cpu(*(uint64_t *)&log_data[SCAO_PLRC])); + json_object_add_value_uint(root, "Power State Change Count", + le64_to_cpu(*(uint64_t *)&log_data[SCAO_PSCC])); + } + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); +} + +static void json_telemetry_log(struct ocp_telemetry_parse_options *options) +{ + print_ocp_telemetry_json(options); +} + +static void json_c3_log(struct nvme_dev *dev, struct ssd_latency_monitor_log *log_data) +{ + struct json_object *root; + char ts_buf[128]; + char buf[128]; + int i, j; + char *operation[3] = {"Trim", "Write", "Read"}; + + root = json_create_object(); + + json_object_add_value_uint(root, "Feature Status", + log_data->feature_status); + json_object_add_value_uint(root, "Active Bucket Timer", + C3_ACTIVE_BUCKET_TIMER_INCREMENT * + le16_to_cpu(log_data->active_bucket_timer)); + json_object_add_value_uint(root, "Active Bucket Timer Threshold", + C3_ACTIVE_BUCKET_TIMER_INCREMENT * + le16_to_cpu(log_data->active_bucket_timer_threshold)); + json_object_add_value_uint(root, "Active Threshold A", + C3_ACTIVE_THRESHOLD_INCREMENT * + le16_to_cpu(log_data->active_threshold_a + 1)); + json_object_add_value_uint(root, "Active Threshold B", + C3_ACTIVE_THRESHOLD_INCREMENT * + le16_to_cpu(log_data->active_threshold_b + 1)); + json_object_add_value_uint(root, "Active Threshold C", + C3_ACTIVE_THRESHOLD_INCREMENT * + le16_to_cpu(log_data->active_threshold_c + 1)); + json_object_add_value_uint(root, "Active Threshold D", + C3_ACTIVE_THRESHOLD_INCREMENT * + le16_to_cpu(log_data->active_threshold_d + 1)); + json_object_add_value_uint(root, "Active Latency Configuration", + le16_to_cpu(log_data->active_latency_config)); + json_object_add_value_uint(root, "Active Latency Minimum Window", + C3_MINIMUM_WINDOW_INCREMENT * + le16_to_cpu(log_data->active_latency_min_window)); + + for (i = 0; i < C3_BUCKET_NUM; i++) { + struct json_object *bucket; + + bucket = json_create_object(); + sprintf(buf, "Active Bucket Counter: Bucket %d", i); + for (j = 2; j >= 0; j--) { + json_object_add_value_uint(bucket, operation[j], + le32_to_cpu(log_data->active_bucket_counter[i][j+1])); + } + json_object_add_value_object(root, buf, bucket); + } + + for (i = 0; i < C3_BUCKET_NUM; i++) { + struct json_object *bucket; + + bucket = json_create_object(); + sprintf(buf, "Active Latency Time Stamp: Bucket %d", i); + for (j = 2; j >= 0; j--) { + if (le64_to_cpu(log_data->active_latency_timestamp[3-i][j]) == -1) { + json_object_add_value_string(bucket, operation[j], "NA"); + } else { + convert_ts(le64_to_cpu(log_data->active_latency_timestamp[3-i][j]), + ts_buf); + json_object_add_value_string(bucket, operation[j], ts_buf); + } + } + json_object_add_value_object(root, buf, bucket); + } + + for (i = 0; i < C3_BUCKET_NUM; i++) { + struct json_object *bucket; + + bucket = json_create_object(); + sprintf(buf, "Active Measured Latency: Bucket %d", i); + for (j = 2; j >= 0; j--) { + json_object_add_value_uint(bucket, operation[j], + le16_to_cpu(log_data->active_measured_latency[3-i][j])); + } + json_object_add_value_object(root, buf, bucket); + } + + json_object_add_value_uint(root, "Active Latency Stamp Units", + le16_to_cpu(log_data->active_latency_stamp_units)); + + for (i = 0; i < C3_BUCKET_NUM; i++) { + struct json_object *bucket; + + bucket = json_create_object(); + sprintf(buf, "Static Bucket Counter: Bucket %d", i); + for (j = 2; j >= 0; j--) { + json_object_add_value_uint(bucket, operation[j], + le32_to_cpu(log_data->static_bucket_counter[i][j+1])); + } + json_object_add_value_object(root, buf, bucket); + } + + for (i = 0; i < C3_BUCKET_NUM; i++) { + struct json_object *bucket; + + bucket = json_create_object(); + sprintf(buf, "Static Latency Time Stamp: Bucket %d", i); + for (j = 2; j >= 0; j--) { + if (le64_to_cpu(log_data->static_latency_timestamp[3-i][j]) == -1) { + json_object_add_value_string(bucket, operation[j], "NA"); + } else { + convert_ts(le64_to_cpu(log_data->static_latency_timestamp[3-i][j]), + ts_buf); + json_object_add_value_string(bucket, operation[j], ts_buf); + } + } + json_object_add_value_object(root, buf, bucket); + } + + for (i = 0; i < C3_BUCKET_NUM; i++) { + struct json_object *bucket; + + bucket = json_create_object(); + sprintf(buf, "Static Measured Latency: Bucket %d", i); + for (j = 2; j >= 0; j--) { + json_object_add_value_uint(bucket, operation[j], + le16_to_cpu(log_data->static_measured_latency[3-i][j])); + } + json_object_add_value_object(root, buf, bucket); + } + + json_object_add_value_uint(root, "Static Latency Stamp Units", + le16_to_cpu(log_data->static_latency_stamp_units)); + json_object_add_value_uint(root, "Debug Log Trigger Enable", + le16_to_cpu(log_data->debug_log_trigger_enable)); + json_object_add_value_uint(root, "Debug Log Measured Latency", + le16_to_cpu(log_data->debug_log_measured_latency)); + if (le64_to_cpu(log_data->debug_log_latency_stamp) == -1) { + json_object_add_value_string(root, "Debug Log Latency Time Stamp", "NA"); + } else { + convert_ts(le64_to_cpu(log_data->debug_log_latency_stamp), ts_buf); + json_object_add_value_string(root, "Debug Log Latency Time Stamp", ts_buf); + } + json_object_add_value_uint(root, "Debug Log Pointer", + le16_to_cpu(log_data->debug_log_ptr)); + json_object_add_value_uint(root, "Debug Counter Trigger Source", + le16_to_cpu(log_data->debug_log_counter_trigger)); + json_object_add_value_uint(root, "Debug Log Stamp Units", + le16_to_cpu(log_data->debug_log_stamp_units)); + json_object_add_value_uint(root, "Log Page Version", + le16_to_cpu(log_data->log_page_version)); + + char guid[(GUID_LEN * 2) + 1]; + char *ptr = &guid[0]; + + for (i = GUID_LEN - 1; i >= 0; i--) + ptr += sprintf(ptr, "%02X", log_data->log_page_guid[i]); + + json_object_add_value_string(root, "Log Page GUID", guid); + + json_print_object(root, NULL); + printf("\n"); + + json_free_object(root); +} + +static void json_c5_log(struct nvme_dev *dev, struct unsupported_requirement_log *log_data) +{ + int j; + struct json_object *root; + char unsup_req_list_str[40]; + char guid_buf[GUID_LEN]; + char *guid = guid_buf; + + root = json_create_object(); + + json_object_add_value_int(root, "Number Unsupported Req IDs", + le16_to_cpu(log_data->unsupported_count)); + + memset((void *)unsup_req_list_str, 0, 40); + for (j = 0; j < le16_to_cpu(log_data->unsupported_count); j++) { + sprintf((char *)unsup_req_list_str, "Unsupported Requirement List %d", j); + json_object_add_value_string(root, unsup_req_list_str, + (char *)log_data->unsupported_req_list[j]); + } + + json_object_add_value_int(root, "Log Page Version", + le16_to_cpu(log_data->log_page_version)); + + memset((void *)guid, 0, GUID_LEN); + for (j = GUID_LEN - 1; j >= 0; j--) + guid += sprintf(guid, "%02x", log_data->log_page_guid[j]); + json_object_add_value_string(root, "Log page GUID", guid_buf); + + json_print_object(root, NULL); + printf("\n"); + + json_free_object(root); +} + +static void json_c1_log(struct ocp_error_recovery_log_page *log_data) +{ + struct json_object *root; + + root = json_create_object(); + char guid[64]; + + json_object_add_value_int(root, "Panic Reset Wait Time", + le16_to_cpu(log_data->panic_reset_wait_time)); + json_object_add_value_int(root, "Panic Reset Action", log_data->panic_reset_action); + json_object_add_value_int(root, "Device Recovery Action 1", + log_data->device_recover_action_1); + json_object_add_value_int(root, "Panic ID", le32_to_cpu(log_data->panic_id)); + json_object_add_value_int(root, "Device Capabilities", + le32_to_cpu(log_data->device_capabilities)); + json_object_add_value_int(root, "Vendor Specific Recovery Opcode", + log_data->vendor_specific_recovery_opcode); + json_object_add_value_int(root, "Vendor Specific Command CDW12", + le32_to_cpu(log_data->vendor_specific_command_cdw12)); + json_object_add_value_int(root, "Vendor Specific Command CDW13", + le32_to_cpu(log_data->vendor_specific_command_cdw13)); + json_object_add_value_int(root, "Vendor Specific Command Timeout", + log_data->vendor_specific_command_timeout); + json_object_add_value_int(root, "Device Recovery Action 2", + log_data->device_recover_action_2); + json_object_add_value_int(root, "Device Recovery Action 2 Timeout", + log_data->device_recover_action_2_timeout); + json_object_add_value_int(root, "Log Page Version", + le16_to_cpu(log_data->log_page_version)); + + memset((void *)guid, 0, 64); + sprintf((char *)guid, "0x%"PRIx64"%"PRIx64"", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]), + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0])); + json_object_add_value_string(root, "Log page GUID", guid); + + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); +} + +static void json_c4_log(struct ocp_device_capabilities_log_page *log_data) +{ + struct json_object *root = json_create_object(); + char guid[64]; + int i; + + json_object_add_value_int(root, "PCI Express Ports", le16_to_cpu(log_data->pcie_exp_port)); + json_object_add_value_int(root, "OOB Management Support", + le16_to_cpu(log_data->oob_management_support)); + json_object_add_value_int(root, "Write Zeroes Command Support", + le16_to_cpu(log_data->wz_cmd_support)); + json_object_add_value_int(root, "Sanitize Command Support", + le16_to_cpu(log_data->sanitize_cmd_support)); + json_object_add_value_int(root, "Dataset Management Command Support", + le16_to_cpu(log_data->dsm_cmd_support)); + json_object_add_value_int(root, "Write Uncorrectable Command Support", + le16_to_cpu(log_data->wu_cmd_support)); + json_object_add_value_int(root, "Fused Operation Support", + le16_to_cpu(log_data->fused_operation_support)); + json_object_add_value_int(root, "Minimum Valid DSSD Power State", + le16_to_cpu(log_data->min_valid_dssd_pwr_state)); + for (i = 0; i <= 127; i++) + json_object_add_value_int(root, "DSSD Power State Descriptors", + log_data->dssd_pwr_state_desc[i]); + json_object_add_value_int(root, "Log Page Version", + le16_to_cpu(log_data->log_page_version)); + + memset((void *)guid, 0, 64); + sprintf((char *)guid, "0x%"PRIx64"%"PRIx64"", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[8]), + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data->log_page_guid[0])); + json_object_add_value_string(root, "Log page GUID", guid); + + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); +} + +static void json_c9_log(struct telemetry_str_log_format *log_data, __u8 *log_data_buf, + int total_log_page_size) +{ + struct json_object *root = json_create_object(); + char res_arr[48]; + char *res = res_arr; + char guid_buf[GUID_LEN]; + char *guid = guid_buf; + char fifo_arr[16]; + char *fifo = fifo_arr; + char buf[128]; + //calculating the index value for array + __le64 stat_id_index = (log_data->sitsz * 4) / 16; + __le64 eve_id_index = (log_data->estsz * 4) / 16; + __le64 vu_eve_index = (log_data->vu_eve_st_sz * 4) / 16; + __le64 ascii_table_index = (log_data->asctsz * 4); + //Calculating the offset for dynamic fields. + __le64 stat_id_str_table_ofst = log_data->sits * 4; + __le64 event_str_table_ofst = log_data->ests * 4; + __le64 vu_event_str_table_ofst = log_data->vu_eve_sts * 4; + __le64 ascii_table_ofst = log_data->ascts * 4; + struct statistics_id_str_table_entry stat_id_str_table_arr[stat_id_index]; + struct event_id_str_table_entry event_id_str_table_arr[eve_id_index]; + struct vu_event_id_str_table_entry vu_event_id_str_table_arr[vu_eve_index]; + __u8 ascii_table_info_arr[ascii_table_index]; + char ascii_buf[ascii_table_index]; + char *ascii = ascii_buf; + int j; + + json_object_add_value_int(root, "Log Page Version", + le16_to_cpu(log_data->log_page_version)); + + memset((__u8 *)res, 0, 15); + for (j = 0; j < 15; j++) + res += sprintf(res, "%d", log_data->reserved1[j]); + json_object_add_value_string(root, "Reserved", res_arr); + + memset((void *)guid, 0, GUID_LEN); + for (j = GUID_LEN - 1; j >= 0; j--) + guid += sprintf(guid, "%02x", log_data->log_page_guid[j]); + json_object_add_value_string(root, "Log page GUID", guid_buf); + + json_object_add_value_int(root, "Telemetry String Log Size", le64_to_cpu(log_data->sls)); + + memset((__u8 *)res, 0, 24); + for (j = 0; j < 24; j++) + res += sprintf(res, "%d", log_data->reserved2[j]); + json_object_add_value_string(root, "Reserved", res_arr); + + json_object_add_value_int(root, "Statistics Identifier String Table Start", + le64_to_cpu(log_data->sits)); + json_object_add_value_int(root, "Event String Table Start", le64_to_cpu(log_data->ests)); + json_object_add_value_int(root, "Event String Table Size", le64_to_cpu(log_data->estsz)); + json_object_add_value_int(root, "VU Event String Table Start", + le64_to_cpu(log_data->vu_eve_sts)); + json_object_add_value_int(root, "VU Event String Table Size", + le64_to_cpu(log_data->vu_eve_st_sz)); + json_object_add_value_int(root, "ASCII Table Start", + le64_to_cpu(log_data->ascts)); + json_object_add_value_int(root, "ASCII Table Size", + le64_to_cpu(log_data->asctsz)); + + memset((void *)fifo, 0, 16); + for (j = 0; j < 16; j++) + fifo += sprintf(fifo, "%c", log_data->fifo1[j]); + json_object_add_value_string(root, "FIFO 1 ASCII String", fifo_arr); + + memset((void *)fifo, 0, 16); + for (j = 0; j < 16; j++) + fifo += sprintf(fifo, "%c", log_data->fifo2[j]); + json_object_add_value_string(root, "FIFO 2 ASCII String", fifo_arr); + + memset((void *)fifo, 0, 16); + for (j = 0; j < 16; j++) + fifo += sprintf(fifo, "%c", log_data->fifo3[j]); + json_object_add_value_string(root, "FIFO 3 ASCII String", fifo_arr); + + memset((void *)fifo, 0, 16); + for (j = 0; j < 16; j++) + fifo += sprintf(fifo, "%c", log_data->fifo4[j]); + json_object_add_value_string(root, "FIFO 4 ASCII String", fifo_arr); + + memset((void *)fifo, 0, 16); + for (j = 0; j < 16; j++) + fifo += sprintf(fifo, "%c", log_data->fifo5[j]); + json_object_add_value_string(root, "FIFO 5 ASCII String", fifo_arr); + + memset((void *)fifo, 0, 16); + for (j = 0; j < 16; j++) + fifo += sprintf(fifo, "%c", log_data->fifo6[j]); + json_object_add_value_string(root, "FIFO 6 ASCII String", fifo_arr); + + memset((void *)fifo, 0, 16); + for (j = 0; j < 16; j++) + fifo += sprintf(fifo, "%c", log_data->fifo7[j]); + json_object_add_value_string(root, "FIFO 7 ASCII String", fifo_arr); + + memset((void *)fifo, 0, 16); + for (j = 0; j < 16; j++) + fifo += sprintf(fifo, "%c", log_data->fifo8[j]); + json_object_add_value_string(root, "FIFO 8 ASCII String", fifo_arr); + + memset((void *)fifo, 0, 16); + for (j = 0; j < 16; j++) + fifo += sprintf(fifo, "%c", log_data->fifo9[j]); + json_object_add_value_string(root, "FIFO 9 ASCII String", fifo_arr); + + memset((void *)fifo, 0, 16); + for (j = 0; j < 16; j++) + fifo += sprintf(fifo, "%c", log_data->fifo10[j]); + json_object_add_value_string(root, "FIFO 10 ASCII String", fifo_arr); + + memset((void *)fifo, 0, 16); + for (j = 0; j < 16; j++) + fifo += sprintf(fifo, "%c", log_data->fifo11[j]); + json_object_add_value_string(root, "FIFO 11 ASCII String", fifo_arr); + + memset((void *)fifo, 0, 16); + for (j = 0; j < 16; j++) + fifo += sprintf(fifo, "%c", log_data->fifo12[j]); + json_object_add_value_string(root, "FIFO 12 ASCII String", fifo_arr); + + memset((void *)fifo, 0, 16); + for (j = 0; j < 16; j++) + fifo += sprintf(fifo, "%c", log_data->fifo13[j]); + json_object_add_value_string(root, "FIFO 13 ASCII String", fifo_arr); + + memset((void *)fifo, 0, 16); + for (j = 0; j < 16; j++) + fifo += sprintf(fifo, "%c", log_data->fifo14[j]); + json_object_add_value_string(root, "FIFO 14 ASCII String", fifo_arr); + + memset((void *)fifo, 0, 16); + for (j = 0; j < 16; j++) + fifo += sprintf(fifo, "%c", log_data->fifo15[j]); + json_object_add_value_string(root, "FIFO 15 ASCII String", fifo_arr); + + memset((void *)fifo, 0, 16); + for (j = 0; j < 16; j++) + fifo += sprintf(fifo, "%c", log_data->fifo16[j]); + json_object_add_value_string(root, "FIFO 16 ASCII String", fifo_arr); + + memset((__u8 *)res, 0, 48); + for (j = 0; j < 48; j++) + res += sprintf(res, "%d", log_data->reserved3[j]); + json_object_add_value_string(root, "Reserved", res_arr); + + if (log_data->sitsz != 0) { + + memcpy(stat_id_str_table_arr, + (__u8 *)log_data_buf + stat_id_str_table_ofst, + (log_data->sitsz * 4)); + struct json_object *stat_table = json_create_object(); + + for (j = 0; j < stat_id_index; j++) { + struct json_object *entry = json_create_object(); + + json_object_add_value_uint(entry, "Vendor Specific Statistic Identifier", + le16_to_cpu(stat_id_str_table_arr[j].vs_si)); + json_object_add_value_uint(entry, "Reserved", + le64_to_cpu(stat_id_str_table_arr[j].reserved1)); + json_object_add_value_uint(entry, "ASCII ID Length", + le64_to_cpu(stat_id_str_table_arr[j].ascii_id_len)); + json_object_add_value_uint(entry, "ASCII ID offset", + le64_to_cpu(stat_id_str_table_arr[j].ascii_id_ofst)); + json_object_add_value_uint(entry, "Reserved2", + le64_to_cpu(stat_id_str_table_arr[j].reserved2)); + sprintf(buf, "Statistics Identifier String Table %d", j); + json_object_add_value_object(stat_table, buf, entry); + } + + json_object_add_value_object(root, + "Statistics Identifier String Table", stat_table); + } + + if (log_data->estsz != 0) { + struct json_object *eve_table = json_create_object(); + + memcpy(event_id_str_table_arr, + (__u8 *)log_data_buf + event_str_table_ofst, + (log_data->estsz * 4)); + for (j = 0; j < eve_id_index; j++) { + struct json_object *entry = json_create_object(); + + json_object_add_value_int(entry, "Debug Event Class", + le16_to_cpu(event_id_str_table_arr[j].deb_eve_class)); + json_object_add_value_int(entry, "Event Identifier", + le16_to_cpu(event_id_str_table_arr[j].ei)); + json_object_add_value_int(entry, "ASCII ID Length", + le64_to_cpu(event_id_str_table_arr[j].ascii_id_len)); + json_object_add_value_int(entry, "ASCII ID offset", + le64_to_cpu(event_id_str_table_arr[j].ascii_id_ofst)); + json_object_add_value_int(entry, "Reserved", + le64_to_cpu(event_id_str_table_arr[j].reserved2)); + sprintf(buf, "Event Identifier String Table Entry %d", j); + json_object_add_value_object(eve_table, buf, entry); + } + json_object_add_value_object(root, + "Event Identifier String Table Entry", + eve_table); + } + + if (log_data->vu_eve_st_sz != 0) { + struct json_object *vu_eve_table = json_create_object(); + + memcpy(vu_event_id_str_table_arr, + (__u8 *)log_data_buf + vu_event_str_table_ofst, + (log_data->vu_eve_st_sz * 4)); + for (j = 0; j < vu_eve_index; j++) { + struct json_object *entry = json_create_object(); + + json_object_add_value_int(entry, "Debug Event Class", + le16_to_cpu(vu_event_id_str_table_arr[j].deb_eve_class)); + json_object_add_value_int(entry, "VU Event Identifier", + le16_to_cpu(vu_event_id_str_table_arr[j].vu_ei)); + json_object_add_value_int(entry, "ASCII ID Length", + le64_to_cpu(vu_event_id_str_table_arr[j].ascii_id_len)); + json_object_add_value_int(entry, "ASCII ID offset", + le64_to_cpu(vu_event_id_str_table_arr[j].ascii_id_ofst)); + json_object_add_value_int(entry, "Reserved", + le64_to_cpu(vu_event_id_str_table_arr[j].reserved)); + sprintf(buf, "VU Event Identifier String Table Entry %d", j); + json_object_add_value_object(vu_eve_table, buf, entry); + } + json_object_add_value_object(root, + "VU Event Identifier String Table Entry", + vu_eve_table); + } + + if (log_data->asctsz != 0) { + memcpy(ascii_table_info_arr, + (__u8 *)log_data_buf + ascii_table_ofst, + (log_data->asctsz * 4)); + memset((void *)ascii, 0, ascii_table_index); + for (j = 0; j < ascii_table_index; j++) + ascii += sprintf(ascii, "%c", ascii_table_info_arr[j]); + json_object_add_value_string(root, "ASCII Table", ascii_buf); + } + + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); +} + +static void json_c7_log(struct nvme_dev *dev, struct tcg_configuration_log *log_data) +{ + int j; + struct json_object *root; + char guid_buf[GUID_LEN]; + char *guid = guid_buf; + char res_arr[458]; + char *res = res_arr; + + root = json_create_object(); + + json_object_add_value_int(root, "State", log_data->state); + memset((__u8 *)res, 0, 3); + for (j = 0; j < 3; j++) + res += sprintf(res, "%d", log_data->rsvd1[j]); + json_object_add_value_string(root, "Reserved1", res_arr); + json_object_add_value_int(root, "Locking SP Activation Count", + log_data->locking_sp_act_count); + json_object_add_value_int(root, "Tper Revert Count", + log_data->locking_sp_rev_count); + json_object_add_value_int(root, "Number of Locking Objects", + log_data->no_of_locking_obj); + json_object_add_value_int(root, "Number of Single User Mode Locking Objects", + log_data->no_of_single_um_locking_obj); + json_object_add_value_int(root, "Number of Range Provisioned Locking Objects", + log_data->no_of_range_prov_locking_obj); + json_object_add_value_int(root, "Number of Namespace Provisioned Locking Objects", + log_data->no_of_ns_prov_locking_obj); + json_object_add_value_int(root, "Number of Read Locked Locking Objects", + log_data->no_of_read_lock_locking_obj); + json_object_add_value_int(root, "Number of Write Locked Locking Objects", + log_data->no_of_write_lock_locking_obj); + json_object_add_value_int(root, "Number of Read Unlocked Locking Objects", + log_data->no_of_read_unlock_locking_obj); + json_object_add_value_int(root, "Number of Write Unlocked Locking Objects", + log_data->no_of_write_unlock_locking_obj); + json_object_add_value_int(root, "Reserved2", log_data->rsvd2); + + json_object_add_value_int(root, "SID Authentication Try Count", + le32_to_cpu(log_data->sid_auth_try_count)); + json_object_add_value_int(root, "SID Authentication Try Limit", + le32_to_cpu(log_data->sid_auth_try_limit)); + json_object_add_value_int(root, "Programmatic TCG Reset Count", + le32_to_cpu(log_data->pro_tcg_rc)); + json_object_add_value_int(root, "Programmatic Reset Lock Count", + le32_to_cpu(log_data->pro_rlc)); + json_object_add_value_int(root, "TCG Error Count", le32_to_cpu(log_data->tcg_ec)); + + memset((__u8 *)res, 0, 458); + for (j = 0; j < 458; j++) + res += sprintf(res, "%d", log_data->rsvd3[j]); + json_object_add_value_string(root, "Reserved3", res_arr); + + json_object_add_value_int(root, "Log Page Version", + le16_to_cpu(log_data->log_page_version)); + + memset((void *)guid, 0, GUID_LEN); + for (j = GUID_LEN - 1; j >= 0; j--) + guid += sprintf(guid, "%02x", log_data->log_page_guid[j]); + json_object_add_value_string(root, "Log page GUID", guid_buf); + + json_print_object(root, NULL); + printf("\n"); + + json_free_object(root); +} + +static struct ocp_print_ops json_print_ops = { + .hwcomp_log = json_hwcomp_log, + .fw_act_history = json_fw_activation_history, + .smart_extended_log = json_smart_extended_log, + .telemetry_log = json_telemetry_log, + .c3_log = json_c3_log, + .c5_log = json_c5_log, + .c1_log = json_c1_log, + .c4_log = json_c4_log, + .c9_log = json_c9_log, + .c7_log = json_c7_log, +}; + +struct ocp_print_ops *ocp_get_json_print_ops(nvme_print_flags_t flags) +{ + json_print_ops.flags = flags; + return &json_print_ops; +} diff --git a/plugins/ocp/ocp-print-stdout.c b/plugins/ocp/ocp-print-stdout.c new file mode 100644 index 0000000..e48c171 --- /dev/null +++ b/plugins/ocp/ocp-print-stdout.c @@ -0,0 +1,710 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include "util/types.h" +#include "common.h" +#include "nvme-print.h" +#include "ocp-print.h" +#include "ocp-hardware-component-log.h" +#include "ocp-fw-activation-history.h" +#include "ocp-smart-extended-log.h" +#include "ocp-telemetry-decode.h" +#include "ocp-nvme.h" + +static void print_hwcomp_desc(struct hwcomp_desc_entry *e, bool list, int num) +{ + printf(" Component %d: %s\n", num, hwcomp_id_to_string(le32_to_cpu(e->desc->id))); + + if (list) + return; + + printf(" Date/Lot Size: 0x%"PRIx64"\n", (uint64_t)e->date_lot_size); + printf(" Additional Information Size: 0x%"PRIx64"\n", (uint64_t)e->add_info_size); + printf(" Identifier: 0x%08x\n", le32_to_cpu(e->desc->id)); + printf(" Manufacture: 0x%016"PRIx64"\n", le64_to_cpu(e->desc->mfg)); + printf(" Revision: 0x%016"PRIx64"\n", le64_to_cpu(e->desc->rev)); + printf(" Manufacture Code: 0x%016"PRIx64"\n", le64_to_cpu(e->desc->mfg_code)); + print_array(" Date/Lot Code", e->date_lot_code, e->date_lot_size); + print_array(" Additional Information", e->add_info, e->add_info_size); +} + +static void stdout_hwcomp_log(struct hwcomp_log *log, __u32 id, bool list) +{ + size_t date_lot_code_offset = sizeof(struct hwcomp_desc); + int num = 1; + struct hwcomp_desc_entry e = { log->desc }; + + long double log_size = uint128_t_to_double(le128_to_cpu(log->size)) * sizeof(__le32); + + printf("Log Identifier: 0x%02xh\n", LID_HWCOMP); + printf("Log Page Version: 0x%x\n", le16_to_cpu(log->ver)); + print_array("Reserved2", log->rsvd2, ARRAY_SIZE(log->rsvd2)); + print_array("Log page GUID", log->guid, ARRAY_SIZE(log->guid)); + printf("Hardware Component Log Size: 0x%"PRIx64"\n", (uint64_t)log_size); + print_array("Reserved48", log->rsvd48, ARRAY_SIZE(log->rsvd48)); + printf("Component Descriptions\n"); + while (log_size > 0) { + e.date_lot_size = le64_to_cpu(e.desc->date_lot_size) * sizeof(__le32); + e.date_lot_code = e.date_lot_size ? (__u8 *)e.desc + date_lot_code_offset : NULL; + e.add_info_size = le64_to_cpu(e.desc->add_info_size) * sizeof(__le32); + e.add_info = e.add_info_size ? e.date_lot_code ? e.date_lot_code + e.date_lot_size : + (__u8 *)e.desc + date_lot_code_offset : NULL; + if (!id || id == le32_to_cpu(e.desc->id)) + print_hwcomp_desc(&e, list, num++); + e.desc_size = date_lot_code_offset + e.date_lot_size + e.add_info_size; + e.desc = (struct hwcomp_desc *)((__u8 *)e.desc + e.desc_size); + log_size -= e.desc_size; + } +} + +static void stdout_fw_activation_history(const struct fw_activation_history *fw_history) +{ + printf("Firmware History Log:\n"); + + printf(" %-26s%d\n", "log identifier:", fw_history->log_id); + printf(" %-26s%d\n", "valid entries:", le32_to_cpu(fw_history->valid_entries)); + + printf(" entries:\n"); + + for (int index = 0; index < le32_to_cpu(fw_history->valid_entries); index++) { + const struct fw_activation_history_entry *entry = &fw_history->entries[index]; + + printf(" entry[%d]:\n", index); + printf(" %-22s%d\n", "version number:", entry->ver_num); + printf(" %-22s%d\n", "entry length:", entry->entry_length); + printf(" %-22s%d\n", "activation count:", + le16_to_cpu(entry->activation_count)); + printf(" %-22s%"PRIu64"\n", "timestamp:", + (0x0000FFFFFFFFFFFF & le64_to_cpu(entry->timestamp))); + printf(" %-22s%"PRIu64"\n", "power cycle count:", + le64_to_cpu(entry->power_cycle_count)); + printf(" %-22s%.*s\n", "previous firmware:", (int)sizeof(entry->previous_fw), + entry->previous_fw); + printf(" %-22s%.*s\n", "new firmware:", (int)sizeof(entry->new_fw), + entry->new_fw); + printf(" %-22s%d\n", "slot number:", entry->slot_number); + printf(" %-22s%d\n", "commit action type:", entry->commit_action); + printf(" %-22s%d\n", "result:", le16_to_cpu(entry->result)); + } + + printf(" %-26s%d\n", "log page version:", + le16_to_cpu(fw_history->log_page_version)); + + printf(" %-26s0x%"PRIx64"%"PRIx64"\n", "log page guid:", + le64_to_cpu(fw_history->log_page_guid[1]), + le64_to_cpu(fw_history->log_page_guid[0])); + + printf("\n"); +} + +static void stdout_smart_extended_log(void *data) +{ + uint16_t smart_log_ver = 0; + __u8 *log_data = data; + + printf("SMART Cloud Attributes :-\n"); + + printf(" Physical media units written - %"PRIu64" %"PRIu64"\n", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW + 8] & 0xFFFFFFFFFFFFFFFF), + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW] & 0xFFFFFFFFFFFFFFFF)); + printf(" Physical media units read - %"PRIu64" %"PRIu64"\n", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR + 8] & 0xFFFFFFFFFFFFFFFF), + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR] & 0xFFFFFFFFFFFFFFFF)); + printf(" Bad user nand blocks - Raw %"PRIu64"\n", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BUNBR] & 0x0000FFFFFFFFFFFF)); + printf(" Bad user nand blocks - Normalized %d\n", + (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BUNBN])); + printf(" Bad system nand blocks - Raw %"PRIu64"\n", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BSNBR] & 0x0000FFFFFFFFFFFF)); + printf(" Bad system nand blocks - Normalized %d\n", + (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BSNBN])); + printf(" XOR recovery count %"PRIu64"\n", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_XRC])); + printf(" Uncorrectable read error count %"PRIu64"\n", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UREC])); + printf(" Soft ecc error count %"PRIu64"\n", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SEEC])); + printf(" End to end detected errors %"PRIu32"\n", + (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EEDC])); + printf(" End to end corrected errors %"PRIu32"\n", + (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EECE])); + printf(" System data percent used %d\n", + (__u8)log_data[SCAO_SDPU]); + printf(" Refresh counts %"PRIu64"\n", + (uint64_t)(le64_to_cpu(*(uint64_t *)&log_data[SCAO_RFSC]) & 0x00FFFFFFFFFFFFFF)); + printf(" Max User data erase counts %"PRIu32"\n", + (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MXUDEC])); + printf(" Min User data erase counts %"PRIu32"\n", + (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MNUDEC])); + printf(" Number of Thermal throttling events %d\n", + (__u8)log_data[SCAO_NTTE]); + printf(" Current throttling status 0x%x\n", + (__u8)log_data[SCAO_CTS]); + printf(" PCIe correctable error count %"PRIu64"\n", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PCEC])); + printf(" Incomplete shutdowns %"PRIu32"\n", + (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_ICS])); + printf(" Percent free blocks %d\n", + (__u8)log_data[SCAO_PFB]); + printf(" Capacitor health %"PRIu16"\n", + (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_CPH])); + printf(" NVMe base errata version %c\n", + (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_CPH])); + printf(" NVMe command set errata version %c\n", + (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_CPH])); + printf(" Unaligned I/O %"PRIu64"\n", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UIO])); + printf(" Security Version Number %"PRIu64"\n", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SVN])); + printf(" NUSE - Namespace utilization %"PRIu64"\n", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_NUSE])); + printf(" PLP start count %s\n", + uint128_t_to_string(le128_to_cpu(&log_data[SCAO_PSC]))); + printf(" Endurance estimate %s\n", + uint128_t_to_string(le128_to_cpu(&log_data[SCAO_EEST]))); + smart_log_ver = (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_LPV]); + printf(" Log page version %"PRIu16"\n", smart_log_ver); + printf(" Log page GUID 0x"); + printf("%"PRIx64"%"PRIx64"\n", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG + 8]), + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG])); + switch (smart_log_ver) { + case 0 ... 1: + break; + default: + case 4: + printf(" NVMe Command Set Errata Version %d\n", + (__u8)log_data[SCAO_NCSEV]); + printf(" Lowest Permitted Firmware Revision %"PRIu64"\n", + le64_to_cpu(*(uint64_t *)&log_data[SCAO_PSCC])); + fallthrough; + case 2 ... 3: + printf(" Errata Version Field %d\n", + (__u8)log_data[SCAO_EVF]); + printf(" Point Version Field %"PRIu16"\n", + le16_to_cpu(*(uint16_t *)&log_data[SCAO_PVF])); + printf(" Minor Version Field %"PRIu16"\n", + le16_to_cpu(*(uint16_t *)&log_data[SCAO_MIVF])); + printf(" Major Version Field %d\n", + (__u8)log_data[SCAO_MAVF]); + printf(" NVMe Base Errata Version %d\n", + (__u8)log_data[SCAO_NBEV]); + printf(" PCIe Link Retraining Count %"PRIu64"\n", + (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PLRC])); + printf(" Power State Change Count %"PRIu64"\n", + le64_to_cpu(*(uint64_t *)&log_data[SCAO_PSCC])); + } + printf("\n"); +} + +static void stdout_telemetry_log(struct ocp_telemetry_parse_options *options) +{ +#ifdef CONFIG_JSONC + print_ocp_telemetry_normal(options); +#endif /* CONFIG_JSONC */ +} + +static void stdout_c3_log(struct nvme_dev *dev, struct ssd_latency_monitor_log *log_data) +{ + char ts_buf[128]; + int i, j; + + printf("-Latency Monitor/C3 Log Page Data-\n"); + printf(" Controller : %s\n", dev->name); + printf(" Feature Status 0x%x\n", + log_data->feature_status); + printf(" Active Bucket Timer %d min\n", + C3_ACTIVE_BUCKET_TIMER_INCREMENT * + le16_to_cpu(log_data->active_bucket_timer)); + printf(" Active Bucket Timer Threshold %d min\n", + C3_ACTIVE_BUCKET_TIMER_INCREMENT * + le16_to_cpu(log_data->active_bucket_timer_threshold)); + printf(" Active Threshold A %d ms\n", + C3_ACTIVE_THRESHOLD_INCREMENT * + le16_to_cpu(log_data->active_threshold_a+1)); + printf(" Active Threshold B %d ms\n", + C3_ACTIVE_THRESHOLD_INCREMENT * + le16_to_cpu(log_data->active_threshold_b+1)); + printf(" Active Threshold C %d ms\n", + C3_ACTIVE_THRESHOLD_INCREMENT * + le16_to_cpu(log_data->active_threshold_c+1)); + 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", + le16_to_cpu(log_data->active_latency_config)); + printf(" Active Latency Minimum Window %d ms\n", + C3_MINIMUM_WINDOW_INCREMENT * + le16_to_cpu(log_data->active_latency_min_window)); + printf(" Active Latency Stamp Units %d\n", + le16_to_cpu(log_data->active_latency_stamp_units)); + printf(" Static Latency Stamp Units %d\n", + le16_to_cpu(log_data->static_latency_stamp_units)); + printf(" Debug Log Trigger Enable %d\n", + le16_to_cpu(log_data->debug_log_trigger_enable)); + printf(" Debug Log Measured Latency %d\n", + le16_to_cpu(log_data->debug_log_measured_latency)); + if (le64_to_cpu(log_data->debug_log_latency_stamp) == -1) { + printf(" Debug Log Latency Time Stamp N/A\n"); + } else { + convert_ts(le64_to_cpu(log_data->debug_log_latency_stamp), ts_buf); + printf(" Debug Log Latency Time Stamp %s\n", ts_buf); + } + printf(" Debug Log Pointer %d\n", + le16_to_cpu(log_data->debug_log_ptr)); + printf(" Debug Counter Trigger Source %d\n", + le16_to_cpu(log_data->debug_log_counter_trigger)); + printf(" Debug Log Stamp Units %d\n", + le16_to_cpu(log_data->debug_log_stamp_units)); + printf(" Log Page Version %d\n", + le16_to_cpu(log_data->log_page_version)); + + char guid[(GUID_LEN * 2) + 1]; + char *ptr = &guid[0]; + + for (i = GUID_LEN - 1; i >= 0; i--) + ptr += sprintf(ptr, "%02X", log_data->log_page_guid[i]); + + printf(" Log Page GUID %s\n", guid); + printf("\n"); + + printf("%64s%92s%119s\n", "Read", "Write", "Deallocate/Trim"); + for (i = 0; i < C3_BUCKET_NUM; i++) { + printf(" Active Bucket Counter: Bucket %d %27d %27d %27d\n", + i, + le32_to_cpu(log_data->active_bucket_counter[i][READ]), + le32_to_cpu(log_data->active_bucket_counter[i][WRITE]), + le32_to_cpu(log_data->active_bucket_counter[i][TRIM])); + } + + for (i = 0; i < C3_BUCKET_NUM; i++) { + printf(" Active Latency Time Stamp: Bucket %d ", i); + for (j = 2; j >= 0; j--) { + if (le64_to_cpu(log_data->active_latency_timestamp[3-i][j]) == -1) { + printf(" N/A "); + } else { + convert_ts(le64_to_cpu(log_data->active_latency_timestamp[3-i][j]), + ts_buf); + printf("%s ", ts_buf); + } + } + printf("\n"); + } + + for (i = 0; i < C3_BUCKET_NUM; i++) { + printf(" Active Measured Latency: Bucket %d %27d ms %27d ms %27d ms\n", + i, + le16_to_cpu(log_data->active_measured_latency[3-i][READ-1]), + le16_to_cpu(log_data->active_measured_latency[3-i][WRITE-1]), + le16_to_cpu(log_data->active_measured_latency[3-i][TRIM-1])); + } + + printf("\n"); + for (i = 0; i < C3_BUCKET_NUM; i++) { + printf(" Static Bucket Counter: Bucket %d %27d %27d %27d\n", + i, + le32_to_cpu(log_data->static_bucket_counter[i][READ]), + le32_to_cpu(log_data->static_bucket_counter[i][WRITE]), + le32_to_cpu(log_data->static_bucket_counter[i][TRIM])); + } + + for (i = 0; i < C3_BUCKET_NUM; i++) { + printf(" Static Latency Time Stamp: Bucket %d ", i); + for (j = 2; j >= 0; j--) { + if (le64_to_cpu(log_data->static_latency_timestamp[3-i][j]) == -1) { + printf(" N/A "); + } else { + convert_ts(le64_to_cpu(log_data->static_latency_timestamp[3-i][j]), + ts_buf); + printf("%s ", ts_buf); + } + } + printf("\n"); + } + + for (i = 0; i < C3_BUCKET_NUM; i++) { + printf(" Static Measured Latency: Bucket %d %27d ms %27d ms %27d ms\n", + i, + le16_to_cpu(log_data->static_measured_latency[3-i][READ-1]), + le16_to_cpu(log_data->static_measured_latency[3-i][WRITE-1]), + le16_to_cpu(log_data->static_measured_latency[3-i][TRIM-1])); + } +} + +static void stdout_c5_log(struct nvme_dev *dev, struct unsupported_requirement_log *log_data) +{ + int j; + + printf("Unsupported Requirement-C5 Log Page Data-\n"); + + printf(" Number Unsupported Req IDs : 0x%x\n", + le16_to_cpu(log_data->unsupported_count)); + + for (j = 0; j < le16_to_cpu(log_data->unsupported_count); j++) + printf(" Unsupported Requirement List %d : %s\n", j, + log_data->unsupported_req_list[j]); + + printf(" Log Page Version : 0x%x\n", + le16_to_cpu(log_data->log_page_version)); + printf(" Log page GUID : 0x"); + for (j = GUID_LEN - 1; j >= 0; j--) + printf("%02x", log_data->log_page_guid[j]); + printf("\n"); +} + +static void stdout_c1_log(struct ocp_error_recovery_log_page *log_data) +{ + int i; + + printf(" Error Recovery/C1 Log Page Data\n"); + printf(" Panic Reset Wait Time : 0x%x\n", + le16_to_cpu(log_data->panic_reset_wait_time)); + printf(" Panic Reset Action : 0x%x\n", log_data->panic_reset_action); + printf(" Device Recovery Action 1 : 0x%x\n", log_data->device_recover_action_1); + printf(" Panic ID : 0x%x\n", le32_to_cpu(log_data->panic_id)); + printf(" Device Capabilities : 0x%x\n", + le32_to_cpu(log_data->device_capabilities)); + printf(" Vendor Specific Recovery Opcode : 0x%x\n", + log_data->vendor_specific_recovery_opcode); + printf(" Vendor Specific Command CDW12 : 0x%x\n", + le32_to_cpu(log_data->vendor_specific_command_cdw12)); + printf(" Vendor Specific Command CDW13 : 0x%x\n", + le32_to_cpu(log_data->vendor_specific_command_cdw13)); + printf(" Vendor Specific Command Timeout : 0x%x\n", + log_data->vendor_specific_command_timeout); + printf(" Device Recovery Action 2 : 0x%x\n", + log_data->device_recover_action_2); + printf(" Device Recovery Action 2 Timeout : 0x%x\n", + log_data->device_recover_action_2_timeout); + printf(" Panic Count : 0x%x\n", log_data->panic_count); + printf(" Previous Panic IDs:"); + for (i = 0; i < C1_PREV_PANIC_IDS_LENGTH; i++) + printf("%s Panic ID N-%d : 0x%"PRIx64"\n", i ? " " : "", i + 1, + le64_to_cpu(log_data->prev_panic_id[i])); + printf(" Log Page Version : 0x%x\n", + le16_to_cpu(log_data->log_page_version)); + printf(" Log page GUID : 0x"); + for (i = GUID_LEN - 1; i >= 0; i--) + printf("%02x", log_data->log_page_guid[i]); + printf("\n"); +} + +static void stdout_c4_log(struct ocp_device_capabilities_log_page *log_data) +{ + int i; + + printf(" Device Capability/C4 Log Page Data\n"); + printf(" PCI Express Ports : 0x%x\n", + le16_to_cpu(log_data->pcie_exp_port)); + printf(" OOB Management Support : 0x%x\n", + le16_to_cpu(log_data->oob_management_support)); + printf(" Write Zeroes Command Support : 0x%x\n", + le16_to_cpu(log_data->wz_cmd_support)); + printf(" Sanitize Command Support : 0x%x\n", + le16_to_cpu(log_data->sanitize_cmd_support)); + printf(" Dataset Management Command Support : 0x%x\n", + le16_to_cpu(log_data->dsm_cmd_support)); + printf(" Write Uncorrectable Command Support : 0x%x\n", + le16_to_cpu(log_data->wu_cmd_support)); + printf(" Fused Operation Support : 0x%x\n", + le16_to_cpu(log_data->fused_operation_support)); + printf(" Minimum Valid DSSD Power State : 0x%x\n", + le16_to_cpu(log_data->min_valid_dssd_pwr_state)); + printf(" DSSD Power State Descriptors : 0x"); + for (i = 0; i <= 127; i++) + printf("%x", log_data->dssd_pwr_state_desc[i]); + printf("\n"); + printf(" Log Page Version : 0x%x\n", + le16_to_cpu(log_data->log_page_version)); + printf(" Log page GUID : 0x"); + for (i = GUID_LEN - 1; i >= 0; i--) + printf("%02x", log_data->log_page_guid[i]); + printf("\n"); +} + +static void stdout_c9_log(struct telemetry_str_log_format *log_data, __u8 *log_data_buf, + int total_log_page_size) +{ + //calculating the index value for array + __le64 stat_id_index = (log_data->sitsz * 4) / 16; + __le64 eve_id_index = (log_data->estsz * 4) / 16; + __le64 vu_eve_index = (log_data->vu_eve_st_sz * 4) / 16; + __le64 ascii_table_index = (log_data->asctsz * 4); + //Calculating the offset for dynamic fields. + __le64 stat_id_str_table_ofst = log_data->sits * 4; + __le64 event_str_table_ofst = log_data->ests * 4; + __le64 vu_event_str_table_ofst = log_data->vu_eve_sts * 4; + __le64 ascii_table_ofst = log_data->ascts * 4; + struct statistics_id_str_table_entry stat_id_str_table_arr[stat_id_index]; + struct event_id_str_table_entry event_id_str_table_arr[eve_id_index]; + struct vu_event_id_str_table_entry vu_event_id_str_table_arr[vu_eve_index]; + int j; + + printf(" Log Page Version : 0x%x\n", + log_data->log_page_version); + + printf(" Reserved : "); + for (j = 0; j < 15; j++) + printf("%d", log_data->reserved1[j]); + printf("\n"); + + printf(" Log page GUID : 0x"); + for (j = GUID_LEN - 1; j >= 0; j--) + printf("%02x", log_data->log_page_guid[j]); + printf("\n"); + + printf(" Telemetry String Log Size : 0x%"PRIx64"\n", + le64_to_cpu(log_data->sls)); + + printf(" Reserved : "); + for (j = 0; j < 24; j++) + printf("%d", log_data->reserved2[j]); + printf("\n"); + + printf(" Statistics Identifier String Table Start : 0x%"PRIx64"\n", + le64_to_cpu(log_data->sits)); + printf(" Statistics Identifier String Table Size : 0x%"PRIx64"\n", + le64_to_cpu(log_data->sitsz)); + printf(" Event String Table Start : 0x%"PRIx64"\n", + le64_to_cpu(log_data->ests)); + printf(" Event String Table Size : 0x%"PRIx64"\n", + le64_to_cpu(log_data->estsz)); + printf(" VU Event String Table Start : 0x%"PRIx64"\n", + le64_to_cpu(log_data->vu_eve_sts)); + printf(" VU Event String Table Size : 0x%"PRIx64"\n", + le64_to_cpu(log_data->vu_eve_st_sz)); + printf(" ASCII Table Start : 0x%"PRIx64"\n", + le64_to_cpu(log_data->ascts)); + printf(" ASCII Table Size : 0x%"PRIx64"\n", + le64_to_cpu(log_data->asctsz)); + + printf(" FIFO 1 ASCII String\n"); + printf(" index value ascii_val\n"); + for (j = 0; j < 16; j++) + printf(" %d %d %c\n", j, log_data->fifo1[j], + log_data->fifo1[j]); + + printf(" FIFO 2 ASCII String\n"); + printf(" index value ascii_val\n"); + for (j = 0; j < 16; j++) + printf(" %d %d %c\n", j, log_data->fifo2[j], + log_data->fifo2[j]); + + printf(" FIFO 3 ASCII String\n"); + printf(" index value ascii_val\n"); + for (j = 0; j < 16; j++) + printf(" %d %d %c\n", j, log_data->fifo3[j], + log_data->fifo3[j]); + + printf(" FIFO 4 ASCII String\n"); + printf(" index value ascii_val\n"); + for (j = 0; j < 16; j++) + printf(" %d %d %c\n", j, log_data->fifo4[j], log_data->fifo4[j]); + + printf(" FIFO 5 ASCII String\n"); + printf(" index value ascii_val\n"); + for (j = 0; j < 16; j++) + printf(" %d %d %c\n", j, log_data->fifo5[j], log_data->fifo5[j]); + + printf(" FIFO 6 ASCII String\n"); + printf(" index value ascii_val\n"); + for (j = 0; j < 16; j++) + printf(" %d %d %c\n", j, log_data->fifo6[j], log_data->fifo6[j]); + + printf(" FIFO 7 ASCII String\n"); + printf(" index value ascii_val\n"); + for (j = 0; j < 16; j++) + printf(" %d %d %c\n", j, log_data->fifo7[j], log_data->fifo7[j]); + + printf(" FIFO 8 ASCII String\n"); + printf(" index value ascii_val\n"); + for (j = 0; j < 16; j++) + printf(" %d %d %c\n", j, log_data->fifo8[j], log_data->fifo8[j]); + + printf(" FIFO 9 ASCII String\n"); + printf(" index value ascii_val\n"); + for (j = 0; j < 16; j++) + printf(" %d %d %c\n", j, log_data->fifo9[j], log_data->fifo9[j]); + + printf(" FIFO 10 ASCII String\n"); + printf(" index value ascii_val\n"); + for (j = 0; j < 16; j++) + printf(" %d %d %c\n", j, log_data->fifo10[j], log_data->fifo10[j]); + + printf(" FIFO 11 ASCII String\n"); + printf(" index value ascii_val\n"); + for (j = 0; j < 16; j++) + printf(" %d %d %c\n", j, log_data->fifo11[j], log_data->fifo11[j]); + + printf(" FIFO 12 ASCII String\n"); + printf(" index value ascii_val\n"); + for (j = 0; j < 16; j++) + printf(" %d %d %c\n", j, log_data->fifo12[j], log_data->fifo12[j]); + + printf(" FIFO 13 ASCII String\n"); + printf(" index value ascii_val\n"); + for (j = 0; j < 16; j++) + printf(" %d %d %c\n", j, log_data->fifo13[j], log_data->fifo13[j]); + + printf(" FIFO 14 ASCII String\n"); + printf(" index value ascii_val\n"); + for (j = 0; j < 16; j++) + printf(" %d %d %c\n", j, log_data->fifo14[j], log_data->fifo14[j]); + + printf(" FIFO 15 ASCII String\n"); + printf(" index value ascii_val\n"); + for (j = 0; j < 16; j++) + printf(" %d %d %c\n", j, log_data->fifo15[j], log_data->fifo16[j]); + + printf(" FIFO 16 ASCII String\n"); + printf(" index value ascii_val\n"); + for (j = 0; j < 16; j++) + printf(" %d %d %c\n", j, log_data->fifo16[j], log_data->fifo16[j]); + + printf(" Reserved : "); + for (j = 0; j < 48; j++) + printf("%d", log_data->reserved3[j]); + printf("\n"); + + if (log_data->sitsz != 0) { + memcpy(stat_id_str_table_arr, (__u8 *)log_data_buf + stat_id_str_table_ofst, + (log_data->sitsz * 4)); + printf(" Statistics Identifier String Table\n"); + for (j = 0; j < stat_id_index; j++) { + printf(" Vendor Specific Statistic Identifier : 0x%x\n", + le16_to_cpu(stat_id_str_table_arr[j].vs_si)); + printf(" Reserved : 0x%x\n", + stat_id_str_table_arr[j].reserved1); + printf(" ASCII ID Length : 0x%x\n", + stat_id_str_table_arr[j].ascii_id_len); + printf(" ASCII ID offset : 0x%"PRIx64"\n", + le64_to_cpu(stat_id_str_table_arr[j].ascii_id_ofst)); + printf(" Reserved : 0x%x\n", + stat_id_str_table_arr[j].reserved2); + } + } + + if (log_data->estsz != 0) { + memcpy(event_id_str_table_arr, (__u8 *)log_data_buf + event_str_table_ofst, + (log_data->estsz * 4)); + printf(" Event Identifier String Table Entry\n"); + for (j = 0; j < eve_id_index; j++) { + printf(" Debug Event Class : 0x%x\n", + event_id_str_table_arr[j].deb_eve_class); + printf(" Event Identifier : 0x%x\n", + le16_to_cpu(event_id_str_table_arr[j].ei)); + printf(" ASCII ID Length : 0x%x\n", + event_id_str_table_arr[j].ascii_id_len); + printf(" ASCII ID offset : 0x%"PRIx64"\n", + le64_to_cpu(event_id_str_table_arr[j].ascii_id_ofst)); + printf(" Reserved : 0x%x\n", + event_id_str_table_arr[j].reserved2); + + } + } + + if (log_data->vu_eve_st_sz != 0) { + memcpy(vu_event_id_str_table_arr, (__u8 *)log_data_buf + vu_event_str_table_ofst, + (log_data->vu_eve_st_sz * 4)); + printf(" VU Event Identifier String Table Entry\n"); + for (j = 0; j < vu_eve_index; j++) { + printf(" Debug Event Class : 0x%x\n", + vu_event_id_str_table_arr[j].deb_eve_class); + printf(" VU Event Identifier : 0x%x\n", + le16_to_cpu(vu_event_id_str_table_arr[j].vu_ei)); + printf(" ASCII ID Length : 0x%x\n", + vu_event_id_str_table_arr[j].ascii_id_len); + printf(" ASCII ID offset : 0x%"PRIx64"\n", + le64_to_cpu(vu_event_id_str_table_arr[j].ascii_id_ofst)); + printf(" Reserved : 0x%x\n", + vu_event_id_str_table_arr[j].reserved); + } + } + + if (log_data->asctsz != 0) { + printf(" ASCII Table\n"); + printf(" Byte Data_Byte ASCII_Character\n"); + for (j = 0; j < ascii_table_index; j++) + printf(" %"PRIu64" %d %c\n", + le64_to_cpu(ascii_table_ofst + j), + log_data_buf[ascii_table_ofst + j], + (char)log_data_buf[ascii_table_ofst + j]); + } +} + +static void stdout_c7_log(struct nvme_dev *dev, struct tcg_configuration_log *log_data) +{ + int j; + + printf("TCG Configuration C7 Log Page Data-\n"); + + printf(" State : 0x%x\n", + log_data->state); + printf(" Reserved1 : 0x"); + for (j = 0; j < 3; j++) + printf("%d", log_data->rsvd1[j]); + printf("\n"); + printf(" Locking SP Activation Count : 0x%x\n", + log_data->locking_sp_act_count); + printf(" Tper Revert Count : 0x%x\n", + log_data->type_rev_count); + printf(" Locking SP Revert Count : 0x%x\n", + log_data->locking_sp_rev_count); + printf(" Number of Locking Objects : 0x%x\n", + log_data->no_of_locking_obj); + printf(" Number of Single User Mode Locking Objects : 0x%x\n", + log_data->no_of_single_um_locking_obj); + printf(" Number of Range Provisioned Locking Objects : 0x%x\n", + log_data->no_of_range_prov_locking_obj); + printf(" Number of Namespace Provisioned Locking Objects : 0x%x\n", + log_data->no_of_ns_prov_locking_obj); + printf(" Number of Read Locked Locking Objects : 0x%x\n", + log_data->no_of_read_lock_locking_obj); + printf(" Number of Write Locked Locking Objects : 0x%x\n", + log_data->no_of_write_lock_locking_obj); + printf(" Number of Read Unlocked Locking Objects : 0x%x\n", + log_data->no_of_read_unlock_locking_obj); + printf(" Number of Write Unlocked Locking Objects : 0x%x\n", + log_data->no_of_write_unlock_locking_obj); + printf(" Reserved2 : 0x%x\n", + log_data->rsvd2); + + printf(" SID Authentication Try Count : 0x%x\n", + le32_to_cpu(log_data->sid_auth_try_count)); + printf(" SID Authentication Try Limit : 0x%x\n", + le32_to_cpu(log_data->sid_auth_try_limit)); + printf(" Programmatic TCG Reset Count : 0x%x\n", + le32_to_cpu(log_data->pro_tcg_rc)); + printf(" Programmatic Reset Lock Count : 0x%x\n", + le32_to_cpu(log_data->pro_rlc)); + printf(" TCG Error Count : 0x%x\n", + le32_to_cpu(log_data->tcg_ec)); + + printf(" Reserved3 : 0x"); + for (j = 0; j < 458; j++) + printf("%d", log_data->rsvd3[j]); + printf("\n"); + + printf(" Log Page Version : 0x%x\n", + le16_to_cpu(log_data->log_page_version)); + printf(" Log page GUID : 0x"); + for (j = GUID_LEN - 1; j >= 0; j--) + printf("%02x", log_data->log_page_guid[j]); + printf("\n"); +} + +static struct ocp_print_ops stdout_print_ops = { + .hwcomp_log = stdout_hwcomp_log, + .fw_act_history = stdout_fw_activation_history, + .smart_extended_log = stdout_smart_extended_log, + .telemetry_log = stdout_telemetry_log, + .c3_log = stdout_c3_log, + .c5_log = stdout_c5_log, + .c1_log = stdout_c1_log, + .c4_log = stdout_c4_log, + .c9_log = stdout_c9_log, + .c7_log = stdout_c7_log, +}; + +struct ocp_print_ops *ocp_get_stdout_print_ops(nvme_print_flags_t flags) +{ + stdout_print_ops.flags = flags; + return &stdout_print_ops; +} diff --git a/plugins/ocp/ocp-print.c b/plugins/ocp/ocp-print.c new file mode 100644 index 0000000..916c653 --- /dev/null +++ b/plugins/ocp/ocp-print.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include "nvme-print.h" +#include "ocp-print.h" +#include "ocp-hardware-component-log.h" + +#define ocp_print(name, flags, ...) \ + do { \ + struct ocp_print_ops *ops = ocp_print_ops(flags); \ + if (ops && ops->name) \ + ops->name(__VA_ARGS__); \ + else \ + fprintf(stderr, "unhandled output format\n"); \ + } while (false) + +static struct ocp_print_ops *ocp_print_ops(nvme_print_flags_t flags) +{ + struct ocp_print_ops *ops = NULL; + + if (flags & JSON || nvme_is_output_format_json()) + ops = ocp_get_json_print_ops(flags); + else if (flags & BINARY) + ops = ocp_get_binary_print_ops(flags); + else + ops = ocp_get_stdout_print_ops(flags); + + return ops; +} + +void ocp_show_hwcomp_log(struct hwcomp_log *log, __u32 id, bool list, nvme_print_flags_t flags) +{ + ocp_print(hwcomp_log, flags, log, id, list); +} + +void ocp_fw_act_history(const struct fw_activation_history *fw_history, nvme_print_flags_t flags) +{ + ocp_print(fw_act_history, flags, fw_history); +} + +void ocp_smart_extended_log(void *data, nvme_print_flags_t flags) +{ + ocp_print(smart_extended_log, flags, data); +} + +void ocp_show_telemetry_log(struct ocp_telemetry_parse_options *options, nvme_print_flags_t flags) +{ + ocp_print(telemetry_log, flags, options); +} + +void ocp_c3_log(struct nvme_dev *dev, struct ssd_latency_monitor_log *log_data, + nvme_print_flags_t flags) +{ + ocp_print(c3_log, flags, dev, log_data); +} + +void ocp_c5_log(struct nvme_dev *dev, struct unsupported_requirement_log *log_data, + nvme_print_flags_t flags) +{ + ocp_print(c5_log, flags, dev, log_data); +} + +void ocp_c1_log(struct ocp_error_recovery_log_page *log_data, nvme_print_flags_t flags) +{ + ocp_print(c1_log, flags, log_data); +} + +void ocp_c4_log(struct ocp_device_capabilities_log_page *log_data, nvme_print_flags_t flags) +{ + ocp_print(c4_log, flags, log_data); +} + +void ocp_c9_log(struct telemetry_str_log_format *log_data, __u8 *log_data_buf, + int total_log_page_size, nvme_print_flags_t flags) +{ + ocp_print(c9_log, flags, log_data, log_data_buf, total_log_page_size); +} + +void ocp_c7_log(struct nvme_dev *dev, struct tcg_configuration_log *log_data, + nvme_print_flags_t flags) +{ + ocp_print(c7_log, flags, dev, log_data); +} diff --git a/plugins/ocp/ocp-print.h b/plugins/ocp/ocp-print.h new file mode 100644 index 0000000..85655b9 --- /dev/null +++ b/plugins/ocp/ocp-print.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef OCP_PRINT_H +#define OCP_PRINT_H + +#include "ocp-hardware-component-log.h" +#include "ocp-fw-activation-history.h" +#include "ocp-telemetry-decode.h" +#include "ocp-nvme.h" + +struct ocp_print_ops { + void (*hwcomp_log)(struct hwcomp_log *log, __u32 id, bool list); + void (*fw_act_history)(const struct fw_activation_history *fw_history); + void (*smart_extended_log)(void *data); + void (*telemetry_log)(struct ocp_telemetry_parse_options *options); + void (*c3_log)(struct nvme_dev *dev, struct ssd_latency_monitor_log *log_data); + void (*c5_log)(struct nvme_dev *dev, struct unsupported_requirement_log *log_data); + void (*c1_log)(struct ocp_error_recovery_log_page *log_data); + void (*c4_log)(struct ocp_device_capabilities_log_page *log_data); + void (*c9_log)(struct telemetry_str_log_format *log_data, __u8 *log_data_buf, + int total_log_page_size); + void (*c7_log)(struct nvme_dev *dev, struct tcg_configuration_log *log_data); + nvme_print_flags_t flags; +}; + +struct ocp_print_ops *ocp_get_stdout_print_ops(nvme_print_flags_t flags); +struct ocp_print_ops *ocp_get_binary_print_ops(nvme_print_flags_t flags); + +#ifdef CONFIG_JSONC +struct ocp_print_ops *ocp_get_json_print_ops(nvme_print_flags_t flags); +#else /* !CONFIG_JSONC */ +static inline struct ocp_print_ops *ocp_get_json_print_ops(nvme_print_flags_t flags) +{ + return NULL; +} +#endif /* !CONFIG_JSONC */ + +void ocp_show_hwcomp_log(struct hwcomp_log *log, __u32 id, bool list, nvme_print_flags_t flags); +void ocp_fw_act_history(const struct fw_activation_history *fw_history, nvme_print_flags_t flags); +void ocp_smart_extended_log(void *data, nvme_print_flags_t flags); +void ocp_show_telemetry_log(struct ocp_telemetry_parse_options *options, nvme_print_flags_t flags); +void ocp_c3_log(struct nvme_dev *dev, struct ssd_latency_monitor_log *log_data, + nvme_print_flags_t flags); +void ocp_c5_log(struct nvme_dev *dev, struct unsupported_requirement_log *log_data, + nvme_print_flags_t flags); +void ocp_c1_log(struct ocp_error_recovery_log_page *log_data, nvme_print_flags_t flags); +void ocp_c4_log(struct ocp_device_capabilities_log_page *log_data, nvme_print_flags_t flags); +void ocp_c9_log(struct telemetry_str_log_format *log_data, __u8 *log_data_buf, + int total_log_page_size, nvme_print_flags_t flags); +void ocp_c7_log(struct nvme_dev *dev, struct tcg_configuration_log *log_data, + nvme_print_flags_t flags); +#endif /* OCP_PRINT_H */ diff --git a/plugins/ocp/ocp-smart-extended-log.c b/plugins/ocp/ocp-smart-extended-log.c index 6a524d3..5f84191 100644 --- a/plugins/ocp/ocp-smart-extended-log.c +++ b/plugins/ocp/ocp-smart-extended-log.c @@ -13,243 +13,19 @@ #include "common.h" #include "nvme-print.h" +#include "ocp-print.h" /* C0 SCAO Log Page */ #define C0_SMART_CLOUD_ATTR_LEN 0x200 #define C0_SMART_CLOUD_ATTR_OPCODE 0xC0 -#define C0_GUID_LENGTH 16 -static __u8 scao_guid[C0_GUID_LENGTH] = { +static __u8 scao_guid[GUID_LEN] = { 0xC5, 0xAF, 0x10, 0x28, 0xEA, 0xBF, 0xF2, 0xA4, 0x9C, 0x4F, 0x6F, 0x7C, 0xC9, 0x14, 0xD5, 0xAF }; -enum { - SCAO_PMUW = 0, /* Physical media units written */ - SCAO_PMUR = 16, /* Physical media units read */ - SCAO_BUNBR = 32, /* Bad user nand blocks raw */ - SCAO_BUNBN = 38, /* Bad user nand blocks normalized */ - SCAO_BSNBR = 40, /* Bad system nand blocks raw */ - SCAO_BSNBN = 46, /* Bad system nand blocks normalized */ - SCAO_XRC = 48, /* XOR recovery count */ - SCAO_UREC = 56, /* Uncorrectable read error count */ - SCAO_SEEC = 64, /* Soft ecc error count */ - SCAO_EEDC = 72, /* End to end detected errors */ - SCAO_EECE = 76, /* End to end corrected errors */ - SCAO_SDPU = 80, /* System data percent used */ - SCAO_RFSC = 81, /* Refresh counts */ - SCAO_MXUDEC = 88, /* Max User data erase counts */ - SCAO_MNUDEC = 92, /* Min User data erase counts */ - SCAO_NTTE = 96, /* Number of Thermal throttling events */ - SCAO_CTS = 97, /* Current throttling status */ - SCAO_EVF = 98, /* Errata Version Field */ - SCAO_PVF = 99, /* Point Version Field */ - SCAO_MIVF = 101, /* Minor Version Field */ - SCAO_MAVF = 103, /* Major Version Field */ - SCAO_PCEC = 104, /* PCIe correctable error count */ - SCAO_ICS = 112, /* Incomplete shutdowns */ - SCAO_PFB = 120, /* Percent free blocks */ - SCAO_CPH = 128, /* Capacitor health */ - SCAO_NEV = 130, /* NVMe Errata Version */ - SCAO_UIO = 136, /* Unaligned I/O */ - SCAO_SVN = 144, /* Security Version Number */ - SCAO_NUSE = 152, /* NUSE - Namespace utilization */ - SCAO_PSC = 160, /* PLP start count */ - SCAO_EEST = 176, /* Endurance estimate */ - SCAO_PLRC = 192, /* PCIe Link Retraining Count */ - SCAO_PSCC = 200, /* Power State Change Count */ - SCAO_LPV = 494, /* Log page version */ - SCAO_LPG = 496, /* Log page GUID */ -}; - -static void ocp_print_C0_log_normal(void *data) -{ - uint16_t smart_log_ver = 0; - __u8 *log_data = data; - - printf("SMART Cloud Attributes :-\n"); - - printf(" Physical media units written - %"PRIu64" %"PRIu64"\n", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW + 8] & 0xFFFFFFFFFFFFFFFF), - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW] & 0xFFFFFFFFFFFFFFFF)); - printf(" Physical media units read - %"PRIu64" %"PRIu64"\n", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR + 8] & 0xFFFFFFFFFFFFFFFF), - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR] & 0xFFFFFFFFFFFFFFFF)); - printf(" Bad user nand blocks - Raw %"PRIu64"\n", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BUNBR] & 0x0000FFFFFFFFFFFF)); - printf(" Bad user nand blocks - Normalized %d\n", - (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BUNBN])); - printf(" Bad system nand blocks - Raw %"PRIu64"\n", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BSNBR] & 0x0000FFFFFFFFFFFF)); - printf(" Bad system nand blocks - Normalized %d\n", - (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BSNBN])); - printf(" XOR recovery count %"PRIu64"\n", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_XRC])); - printf(" Uncorrectable read error count %"PRIu64"\n", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UREC])); - printf(" Soft ecc error count %"PRIu64"\n", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SEEC])); - printf(" End to end detected errors %"PRIu32"\n", - (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EEDC])); - printf(" End to end corrected errors %"PRIu32"\n", - (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EECE])); - printf(" System data percent used %d\n", - (__u8)log_data[SCAO_SDPU]); - printf(" Refresh counts %"PRIu64"\n", - (uint64_t)(le64_to_cpu(*(uint64_t *)&log_data[SCAO_RFSC]) & 0x00FFFFFFFFFFFFFF)); - printf(" Max User data erase counts %"PRIu32"\n", - (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MXUDEC])); - printf(" Min User data erase counts %"PRIu32"\n", - (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MNUDEC])); - printf(" Number of Thermal throttling events %d\n", - (__u8)log_data[SCAO_NTTE]); - printf(" Current throttling status 0x%x\n", - (__u8)log_data[SCAO_CTS]); - printf(" PCIe correctable error count %"PRIu64"\n", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PCEC])); - printf(" Incomplete shutdowns %"PRIu32"\n", - (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_ICS])); - printf(" Percent free blocks %d\n", - (__u8)log_data[SCAO_PFB]); - printf(" Capacitor health %"PRIu16"\n", - (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_CPH])); - printf(" Unaligned I/O %"PRIu64"\n", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UIO])); - printf(" Security Version Number %"PRIu64"\n", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SVN])); - printf(" NUSE - Namespace utilization %"PRIu64"\n", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_NUSE])); - printf(" PLP start count %s\n", - uint128_t_to_string(le128_to_cpu(&log_data[SCAO_PSC]))); - printf(" Endurance estimate %s\n", - uint128_t_to_string(le128_to_cpu(&log_data[SCAO_EEST]))); - smart_log_ver = (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_LPV]); - printf(" Log page version %"PRIu16"\n", smart_log_ver); - printf(" Log page GUID 0x"); - printf("%"PRIx64"%"PRIx64"\n", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG + 8]), - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG])); - if (smart_log_ver > 2) { - printf(" Errata Version Field %d\n", - (__u8)log_data[SCAO_EVF]); - printf(" Point Version Field %"PRIu16"\n", - le16_to_cpu(*(uint16_t *)&log_data[SCAO_PVF])); - printf(" Minor Version Field %"PRIu16"\n", - le16_to_cpu(*(uint16_t *)&log_data[SCAO_MIVF])); - printf(" Major Version Field %d\n", - (__u8)log_data[SCAO_MAVF]); - printf(" NVMe Errata Version %d\n", - (__u8)log_data[SCAO_NEV]); - printf(" PCIe Link Retraining Count %"PRIu64"\n", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PLRC])); - printf(" Power State Change Count %"PRIu64"\n", - le64_to_cpu(*(uint64_t *)&log_data[SCAO_PSCC])); - } - printf("\n"); -} - -static void ocp_print_C0_log_json(void *data) -{ - struct json_object *root; - struct json_object *pmuw; - struct json_object *pmur; - uint16_t smart_log_ver = 0; - __u8 *log_data = data; - char guid[40]; - - root = json_create_object(); - pmuw = json_create_object(); - pmur = json_create_object(); - - json_object_add_value_uint64(pmuw, "hi", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW + 8] & 0xFFFFFFFFFFFFFFFF)); - json_object_add_value_uint64(pmuw, "lo", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW] & 0xFFFFFFFFFFFFFFFF)); - json_object_add_value_object(root, "Physical media units written", pmuw); - json_object_add_value_uint64(pmur, "hi", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR + 8] & 0xFFFFFFFFFFFFFFFF)); - json_object_add_value_uint64(pmur, "lo", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR] & 0xFFFFFFFFFFFFFFFF)); - json_object_add_value_object(root, "Physical media units read", pmur); - json_object_add_value_uint64(root, "Bad user nand blocks - Raw", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BUNBR] & 0x0000FFFFFFFFFFFF)); - json_object_add_value_uint(root, "Bad user nand blocks - Normalized", - (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BUNBN])); - json_object_add_value_uint64(root, "Bad system nand blocks - Raw", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BSNBR] & 0x0000FFFFFFFFFFFF)); - json_object_add_value_uint(root, "Bad system nand blocks - Normalized", - (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BSNBN])); - json_object_add_value_uint64(root, "XOR recovery count", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_XRC])); - json_object_add_value_uint64(root, "Uncorrectable read error count", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UREC])); - json_object_add_value_uint64(root, "Soft ecc error count", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SEEC])); - json_object_add_value_uint(root, "End to end detected errors", - (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EEDC])); - json_object_add_value_uint(root, "End to end corrected errors", - (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EECE])); - json_object_add_value_uint(root, "System data percent used", - (__u8)log_data[SCAO_SDPU]); - json_object_add_value_uint64(root, "Refresh counts", - (uint64_t)(le64_to_cpu(*(uint64_t *)&log_data[SCAO_RFSC]) & 0x00FFFFFFFFFFFFFF)); - json_object_add_value_uint(root, "Max User data erase counts", - (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MXUDEC])); - json_object_add_value_uint(root, "Min User data erase counts", - (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MNUDEC])); - json_object_add_value_uint(root, "Number of Thermal throttling events", - (__u8)log_data[SCAO_NTTE]); - json_object_add_value_uint(root, "Current throttling status", - (__u8)log_data[SCAO_CTS]); - json_object_add_value_uint64(root, "PCIe correctable error count", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PCEC])); - json_object_add_value_uint(root, "Incomplete shutdowns", - (uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_ICS])); - json_object_add_value_uint(root, "Percent free blocks", - (__u8)log_data[SCAO_PFB]); - json_object_add_value_uint(root, "Capacitor health", - (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_CPH])); - json_object_add_value_uint64(root, "Unaligned I/O", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UIO])); - json_object_add_value_uint64(root, "Security Version Number", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SVN])); - json_object_add_value_uint64(root, "NUSE - Namespace utilization", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_NUSE])); - json_object_add_value_uint128(root, "PLP start count", - le128_to_cpu(&log_data[SCAO_PSC])); - json_object_add_value_uint128(root, "Endurance estimate", - le128_to_cpu(&log_data[SCAO_EEST])); - smart_log_ver = (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_LPV]); - - json_object_add_value_uint(root, "Log page version", smart_log_ver); - - memset((void *)guid, 0, 40); - sprintf((char *)guid, "0x%"PRIx64"%"PRIx64"", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG + 8]), - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG])); - json_object_add_value_string(root, "Log page GUID", guid); - - if (smart_log_ver > 2) { - json_object_add_value_uint(root, "Errata Version Field", - (__u8)log_data[SCAO_EVF]); - json_object_add_value_uint(root, "Point Version Field", - le16_to_cpu(*(uint16_t *)&log_data[SCAO_PVF])); - json_object_add_value_uint(root, "Minor Version Field", - le16_to_cpu(*(uint16_t *)&log_data[SCAO_MIVF])); - json_object_add_value_uint(root, "Major Version Field", - (__u8)log_data[SCAO_MAVF]); - json_object_add_value_uint(root, "NVMe Errata Version", - (__u8)log_data[SCAO_NEV]); - json_object_add_value_uint(root, "PCIe Link Retraining Count", - (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PLRC])); - json_object_add_value_uint(root, "Power State Change Count", - le64_to_cpu(*(uint64_t *)&log_data[SCAO_PSCC])); - } - json_print_object(root, NULL); - printf("\n"); - json_free_object(root); -} - static int get_c0_log_page(int fd, char *format) { nvme_print_flags_t fmt; @@ -300,16 +76,7 @@ static int get_c0_log_page(int fd, char *format) } /* print the data */ - switch (fmt) { - case NORMAL: - ocp_print_C0_log_normal(data); - break; - case JSON: - ocp_print_C0_log_json(data); - break; - default: - break; - } + ocp_smart_extended_log(data, fmt); } else { fprintf(stderr, "ERROR : OCP : Unable to read C0 data from buffer\n"); } diff --git a/plugins/ocp/ocp-smart-extended-log.h b/plugins/ocp/ocp-smart-extended-log.h index 42c1f98..3e64b1b 100644 --- a/plugins/ocp/ocp-smart-extended-log.h +++ b/plugins/ocp/ocp-smart-extended-log.h @@ -12,6 +12,46 @@ struct command; struct plugin; +enum { + SCAO_PMUW = 0, /* Physical media units written */ + SCAO_PMUR = 16, /* Physical media units read */ + SCAO_BUNBR = 32, /* Bad user nand blocks raw */ + SCAO_BUNBN = 38, /* Bad user nand blocks normalized */ + SCAO_BSNBR = 40, /* Bad system nand blocks raw */ + SCAO_BSNBN = 46, /* Bad system nand blocks normalized */ + SCAO_XRC = 48, /* XOR recovery count */ + SCAO_UREC = 56, /* Uncorrectable read error count */ + SCAO_SEEC = 64, /* Soft ecc error count */ + SCAO_EEDC = 72, /* End to end detected errors */ + SCAO_EECE = 76, /* End to end corrected errors */ + SCAO_SDPU = 80, /* System data percent used */ + SCAO_RFSC = 81, /* Refresh counts */ + SCAO_MXUDEC = 88, /* Max User data erase counts */ + SCAO_MNUDEC = 92, /* Min User data erase counts */ + SCAO_NTTE = 96, /* Number of Thermal throttling events */ + SCAO_CTS = 97, /* Current throttling status */ + SCAO_EVF = 98, /* Errata Version Field */ + SCAO_PVF = 99, /* Point Version Field */ + SCAO_MIVF = 101, /* Minor Version Field */ + SCAO_MAVF = 103, /* Major Version Field */ + SCAO_PCEC = 104, /* PCIe correctable error count */ + SCAO_ICS = 112, /* Incomplete shutdowns */ + SCAO_PFB = 120, /* Percent free blocks */ + SCAO_CPH = 128, /* Capacitor health */ + SCAO_NBEV = 130, /* NVMe Base Errata Version */ + SCAO_NCSEV = 131, /* NVMe Command Set Errata Version */ + SCAO_UIO = 136, /* Unaligned I/O */ + SCAO_SVN = 144, /* Security Version Number */ + SCAO_NUSE = 152, /* NUSE - Namespace utilization */ + SCAO_PSC = 160, /* PLP start count */ + SCAO_EEST = 176, /* Endurance estimate */ + SCAO_PLRC = 192, /* PCIe Link Retraining Count */ + SCAO_PSCC = 200, /* Power State Change Count */ + SCAO_LPFR = 208, /* Lowest Permitted Firmware Revision */ + SCAO_LPV = 494, /* Log page version */ + SCAO_LPG = 496, /* Log page GUID */ +}; + int ocp_smart_add_log(int argc, char **argv, struct command *cmd, struct plugin *plugin); diff --git a/plugins/ocp/ocp-telemetry-decode.c b/plugins/ocp/ocp-telemetry-decode.c index 11963be..1a6ebe3 100644 --- a/plugins/ocp/ocp-telemetry-decode.c +++ b/plugins/ocp/ocp-telemetry-decode.c @@ -64,6 +64,7 @@ void print_telemetry_fifo_event(__u8 class_type, if (class_type) { class_str = telemetry_event_class_to_string(class_type); printf("Event Class : %s\n", class_str); + printf(" Size : 0x%02x\n", size); } switch (class_type) { @@ -75,9 +76,8 @@ void print_telemetry_fifo_event(__u8 class_type, (int)((le64_to_cpu(timestamp%3600)/60)), (int)(le64_to_cpu(timestamp%60))); - printf(" Event ID : 0x%02x %s\n", id, telemetry_ts_event_to_string(id)); + printf(" Event ID : 0x%04x %s\n", id, telemetry_ts_event_to_string(id)); printf(" Timestamp : %s\n", time_str); - printf(" Size : %d\n", size); if (size > 8) { printf(" VU Data : 0x"); for (j = 8; j < size; j++) @@ -87,7 +87,7 @@ void print_telemetry_fifo_event(__u8 class_type, break; case TELEMETRY_PCIE_CLASS: - printf(" Event ID : 0x%02x %s\n", + printf(" Event ID : 0x%04x %s\n", id, telemetry_pcie_event_id_to_string(id)); printf(" State : 0x%02x %s\n", data[0], telemetry_pcie_state_data_to_string(data[0])); @@ -104,7 +104,7 @@ void print_telemetry_fifo_event(__u8 class_type, break; case TELEMETRY_NVME_CLASS: - printf(" Event ID : 0x%02x %s\n", + printf(" Event ID : 0x%04x %s\n", id, telemetry_nvme_event_id_to_string(id)); if ((id == ADMIN_QUEUE_NONZERO_STATUS) || (id == IO_QUEUE_NONZERO_STATUS)) { @@ -128,46 +128,46 @@ void print_telemetry_fifo_event(__u8 class_type, le32_to_cpu(csts_reg_data)); } if (size > 8) - print_vu_event_data(size, (__u8 *)&data[8]); + print_vu_event_data((size-8), (__u8 *)&data[8]); break; case TELEMETRY_RESET_CLASS: - printf(" Event ID : 0x%02x %s\n", + printf(" Event ID : 0x%04x %s\n", id, telemetry_reset_event_id_to_string(id)); if (size) print_vu_event_data(size, data); break; case TELEMETRY_BOOT_SEQ_CLASS: - printf(" Event ID : 0x%02x %s\n", + printf(" Event ID : 0x%04x %s\n", id, telemetry_boot_seq_event_id_to_string(id)); if (size) print_vu_event_data(size, data); break; case TELEMETRY_FW_ASSERT_CLASS: - printf(" Event ID : 0x%02x %s\n", + printf(" Event ID : 0x%04x %s\n", id, telemetry_fw_assert_event_id_to_string(id)); if (size) print_vu_event_data(size, data); break; case TELEMETRY_TEMPERATURE_CLASS: - printf(" Event ID : 0x%02x %s\n", + printf(" Event ID : 0x%04x %s\n", id, telemetry_temperature_event_id_to_string(id)); if (size) print_vu_event_data(size, data); break; case TELEMETRY_MEDIA_DBG_CLASS: - printf(" Event ID : 0x%02x %s\n", + printf(" Event ID : 0x%04x %s\n", id, telemetry_media_debug_event_id_to_string(id)); if (size) print_vu_event_data(size, data); break; case TELEMETRY_MEDIA_WEAR_CLASS: - printf(" Event ID : 0x%02x %s\n", + printf(" Event ID : 0x%04x %s\n", id, telemetry_media_debug_event_id_to_string(id)); __u32 host_tb_written = *(__u32 *)&data[0]; __u32 media_tb_written = *(__u32 *)&data[4]; @@ -181,7 +181,7 @@ void print_telemetry_fifo_event(__u8 class_type, le16_to_cpu(media_tb_erased)); if (size > 12) - print_vu_event_data(size, (__u8 *)&data[12]); + print_vu_event_data((size-12), (__u8 *)&data[12]); break; case TELEMETRY_STAT_SNAPSHOT_CLASS: @@ -280,7 +280,7 @@ struct request_data ocp_header_in_da1[] = { { "Minor Version", 2 }, { "Reserved1", 4 }, { "Timestamp", 8 }, - { "Log page GUID", 16 }, + { "Log page GUID", GUID_LEN }, { "Number Telemetry Profiles Supported", 1 }, { "Telemetry Profile Selected", 1 }, { "Reserved2", 6 }, @@ -419,9 +419,10 @@ struct request_data smart_extended[] = { { "Lowest Permitted Firmware Revision", 8 }, { "Reserved4", 278 }, { "Log Page Version", 2 }, - { "Log page GUID", 16 } + { "Log page GUID", GUID_LEN } }; +#ifdef CONFIG_JSONC void json_add_formatted_u32_str(struct json_object *pobject, const char *msg, unsigned int pdata) { char data_str[70] = { 0 }; @@ -443,6 +444,7 @@ void json_add_formatted_var_size_str(struct json_object *pobject, const char *ms json_object_add_value_string(pobject, msg, description_str); } +#endif /* CONFIG_JSONC */ int get_telemetry_das_offset_and_size( struct nvme_ocp_telemetry_common_header *ptelemetry_common_header, @@ -636,49 +638,67 @@ int parse_ocp_telemetry_string_log(int event_fifo_num, int identifier, int debug return 0; } +#ifdef CONFIG_JSONC 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); - + struct nvme_ocp_common_dbg_evt_class_vu_data *ptime_stamp_event_vu_data = NULL; + __u16 vu_event_id = 0; + __u8 *pdata = NULL; 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); + unsigned int vu_data_size = 0; + bool vu_data_present = false; + + if ((pevent_descriptor->event_data_size * SIZE_OF_DWORD) > + sizeof(struct nvme_ocp_time_stamp_dbg_evt_class_format)) { + vu_data_present = true; + vu_data_size = + ((pevent_descriptor->event_data_size * SIZE_OF_DWORD) - + (sizeof(struct nvme_ocp_time_stamp_dbg_evt_class_format) + + SIZE_OF_VU_EVENT_ID)); + + ptime_stamp_event_vu_data = + (struct nvme_ocp_common_dbg_evt_class_vu_data *)((__u64)ptime_stamp_event + + sizeof(struct nvme_ocp_time_stamp_dbg_evt_class_format)); + vu_event_id = le16_to_cpu(ptime_stamp_event_vu_data->vu_event_identifier); + pdata = (__u8 *)&(ptime_stamp_event_vu_data->data); + + parse_ocp_telemetry_string_log(0, vu_event_id, + 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); + if (vu_data_present) { + 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, + vu_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); + if (vu_data_present) { + 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, vu_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); + if (vu_data_present) { + 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, vu_data_size, fp); + } } } } @@ -689,37 +709,60 @@ void parse_pcie_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descrip { 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); + struct nvme_ocp_common_dbg_evt_class_vu_data *ppcie_event_vu_data = NULL; + __u16 vu_event_id = 0; + __u8 *pdata = NULL; 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); + unsigned int vu_data_size = 0; + bool vu_data_present = false; + + if ((pevent_descriptor->event_data_size * SIZE_OF_DWORD) > + sizeof(struct nvme_ocp_pcie_dbg_evt_class_format)) { + vu_data_present = true; + vu_data_size = + ((pevent_descriptor->event_data_size * SIZE_OF_DWORD) - + (sizeof(struct nvme_ocp_pcie_dbg_evt_class_format) + + SIZE_OF_VU_EVENT_ID)); + + ppcie_event_vu_data = + (struct nvme_ocp_common_dbg_evt_class_vu_data *)((__u64)ppcie_event + + sizeof(struct nvme_ocp_pcie_dbg_evt_class_format)); + vu_event_id = le16_to_cpu(ppcie_event_vu_data->vu_event_identifier); + pdata = (__u8 *)&(ppcie_event_vu_data->data); + + parse_ocp_telemetry_string_log(0, vu_event_id, + 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); + if (vu_data_present) { + 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, + vu_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); + if (vu_data_present) { + 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, vu_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); + if (vu_data_present) { + 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, vu_data_size, fp); + } } } } @@ -730,38 +773,61 @@ void parse_nvme_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descrip { 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); + struct nvme_ocp_common_dbg_evt_class_vu_data *pnvme_event_vu_data = NULL; + __u16 vu_event_id = 0; + __u8 *pdata = NULL; 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); + unsigned int vu_data_size = 0; + bool vu_data_present = false; + + if ((pevent_descriptor->event_data_size * SIZE_OF_DWORD) > + sizeof(struct nvme_ocp_nvme_dbg_evt_class_format)) { + vu_data_present = true; + vu_data_size = + ((pevent_descriptor->event_data_size * SIZE_OF_DWORD) - + (sizeof(struct nvme_ocp_nvme_dbg_evt_class_format) + + SIZE_OF_VU_EVENT_ID)); + pnvme_event_vu_data = + (struct nvme_ocp_common_dbg_evt_class_vu_data *)((__u64)pnvme_event + + sizeof(struct nvme_ocp_nvme_dbg_evt_class_format)); + + vu_event_id = le16_to_cpu(pnvme_event_vu_data->vu_event_identifier); + pdata = (__u8 *)&(pnvme_event_vu_data->data); + + parse_ocp_telemetry_string_log(0, vu_event_id, + 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); + pnvme_event->nvmeDebugEventData, DATA_SIZE_8); + if (vu_data_present) { + 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, + vu_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); + if (vu_data_present) { + 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, vu_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); + if (vu_data_present) { + 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, vu_data_size, fp); + } } } } @@ -770,34 +836,38 @@ void parse_common_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descr 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); + if (pevent_specific_data) { + struct nvme_ocp_common_dbg_evt_class_vu_data *pcommon_debug_event_vu_data = + (struct nvme_ocp_common_dbg_evt_class_vu_data *) pevent_specific_data; + + __u16 vu_event_id = le16_to_cpu(pcommon_debug_event_vu_data->vu_event_identifier); + char description_str[256] = ""; + __u8 *pdata = (__u8 *)&(pcommon_debug_event_vu_data->data); + + unsigned int vu_data_size = ((pevent_descriptor->event_data_size * + SIZE_OF_DWORD) - SIZE_OF_VU_EVENT_ID); + + parse_ocp_telemetry_string_log(0, vu_event_id, + 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, + vu_data_size); } 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); + 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, vu_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, vu_data_size, fp); + } } } } @@ -808,39 +878,62 @@ void parse_media_wear_event(struct nvme_ocp_telemetry_event_descriptor *pevent_d { 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] = ""; + struct nvme_ocp_common_dbg_evt_class_vu_data *pmedia_wear_event_vu_data = NULL; - parse_ocp_telemetry_string_log(0, pmedia_wear_event->vu_event_identifier, - pevent_descriptor->debug_event_class_type, VU_EVENT_STRING, - description_str); + __u16 vu_event_id = 0; + __u8 *pdata = NULL; + char description_str[256] = ""; + unsigned int vu_data_size = 0; + bool vu_data_present = false; + + if ((pevent_descriptor->event_data_size * SIZE_OF_DWORD) > + sizeof(struct nvme_ocp_media_wear_dbg_evt_class_format)) { + vu_data_present = true; + vu_data_size = + ((pevent_descriptor->event_data_size * SIZE_OF_DWORD) - + (sizeof(struct nvme_ocp_media_wear_dbg_evt_class_format) + + SIZE_OF_VU_EVENT_ID)); + + pmedia_wear_event_vu_data = + (struct nvme_ocp_common_dbg_evt_class_vu_data *)((__u64)pmedia_wear_event + + sizeof(struct nvme_ocp_media_wear_dbg_evt_class_format)); + vu_event_id = le16_to_cpu(pmedia_wear_event_vu_data->vu_event_identifier); + pdata = (__u8 *)&(pmedia_wear_event_vu_data->data); + + parse_ocp_telemetry_string_log(0, vu_event_id, + 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); + if (vu_data_present) { + 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, + vu_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); + if (vu_data_present) { + 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, vu_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); + if (vu_data_present) { + 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, vu_data_size, fp); + } } } } @@ -895,16 +988,27 @@ int parse_event_fifo(unsigned int fifo_num, unsigned char *pfifo_start, (struct nvme_ocp_telemetry_event_descriptor *) (pfifo_start + offset_to_move); + /* check if at the end of the list */ + if (pevent_descriptor->debug_event_class_type == RESERVED_CLASS_TYPE) + break; + if (pevent_descriptor != NULL && pevent_descriptor->event_data_size >= 0) { - //Data is present in the form of DWORDS, So multiplying with sizeof(DWORD) + /* 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; - + __u8 *pevent_specific_data = NULL; + __u16 event_id = 0; char description_str[256] = ""; - parse_ocp_telemetry_string_log(0, pevent_descriptor->event_id, + if (pevent_descriptor != NULL && pevent_descriptor->event_data_size > 0) + pevent_specific_data = (__u8 *)pevent_descriptor + event_des_size; + + event_id = le16_to_cpu(pevent_descriptor->event_id); + + parse_ocp_telemetry_string_log(0, event_id, pevent_descriptor->debug_event_class_type, EVENT_STRING, description_str); @@ -916,7 +1020,7 @@ int parse_event_fifo(unsigned int fifo_num, unsigned char *pfifo_start, 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); + STR_EVENT_IDENTIFIER, event_id); json_object_add_value_string(pevent_descriptor_obj, STR_EVENT_STRING, description_str); json_add_formatted_u32_str(pevent_descriptor_obj, @@ -930,18 +1034,18 @@ int parse_event_fifo(unsigned int fifo_num, unsigned char *pfifo_start, 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); + 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); + pevent_descriptor->debug_event_class_type); printf("%s: 0x%x\n", STR_EVENT_IDENTIFIER, - pevent_descriptor->event_id); + 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); + pevent_descriptor->event_data_size); } if (pevent_descriptor->debug_event_class_type >= 0x80) @@ -951,28 +1055,43 @@ int parse_event_fifo(unsigned int fifo_num, unsigned char *pfifo_start, 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); + 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); + 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); + 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); + 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); + 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 @@ -989,20 +1108,22 @@ int parse_event_fifo(unsigned int fifo_num, unsigned char *pfifo_start, 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; + 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); + offset_to_move += (pevent_descriptor->event_data_size * SIZE_OF_DWORD + + event_des_size); } if (pevent_fifos_object != NULL && pevent_fifo_array != NULL) @@ -1241,9 +1362,16 @@ int print_ocp_telemetry_normal(struct ocp_telemetry_parse_options *options) 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); + if (!strcmp(options->telemetry_type, "host")) { + if ((ptelemetry_buffer == NULL) || + (ARRAY_SIZE(host_log_page_header) == 0)) + printf("skip generic_structure_parser\n"); + else + 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, @@ -1350,9 +1478,15 @@ int print_ocp_telemetry_normal(struct ocp_telemetry_parse_options *options) 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); + if (!strcmp(options->telemetry_type, "host")) { + if ((ptelemetry_buffer == NULL) || + (ARRAY_SIZE(host_log_page_header) == 0)) + printf("skip generic_structure_parser\n"); + else { + 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); @@ -1363,7 +1497,7 @@ int print_ocp_telemetry_normal(struct ocp_telemetry_parse_options *options) __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); + ARRAY_SIZE(reason_identifier), NULL, 0, NULL); printf(STR_LINE); printf("%s\n", STR_TELEMETRY_HOST_DATA_BLOCK_1); @@ -1382,7 +1516,7 @@ int print_ocp_telemetry_normal(struct ocp_telemetry_parse_options *options) __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); + ARRAY_SIZE(ocp_header_in_da1), NULL, 0, NULL); printf(STR_LINE); printf("%s\n", STR_SMART_HEALTH_INFO); @@ -1391,7 +1525,7 @@ int print_ocp_telemetry_normal(struct ocp_telemetry_parse_options *options) offsetof(struct nvme_ocp_header_in_da1, smart_health_info); generic_structure_parser(pda1_smart_offset, smart, ARRAY_SIZE(smart), NULL, 0, - NULL); + NULL); printf(STR_LINE); printf("%s\n", STR_SMART_HEALTH_INTO_EXTENDED); @@ -1400,7 +1534,7 @@ int print_ocp_telemetry_normal(struct ocp_telemetry_parse_options *options) 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); + ARRAY_SIZE(smart_extended), NULL, 0, NULL); printf(STR_LINE); printf("%s\n", STR_DA_1_STATS); @@ -1564,3 +1698,4 @@ int print_ocp_telemetry_json(struct ocp_telemetry_parse_options *options) return status; } +#endif /* CONFIG_JSONC */ diff --git a/plugins/ocp/ocp-telemetry-decode.h b/plugins/ocp/ocp-telemetry-decode.h index ed31a6c..ce7de75 100644 --- a/plugins/ocp/ocp-telemetry-decode.h +++ b/plugins/ocp/ocp-telemetry-decode.h @@ -3,11 +3,14 @@ * * Authors: Jeff Lien <jeff.lien@wdc.com>, */ +#ifndef OCP_TELEMETRY_DECODE_H +#define OCP_TELEMETRY_DECODE_H #include "nvme.h" #include "nvme-print.h" #include "util/utils.h" #include "common.h" +#include "ocp-nvme.h" extern __u8 *ptelemetry_buffer; extern __u8 *pstring_buffer; @@ -382,7 +385,7 @@ struct telemetry_stats_desc { __u8 data[]; }; -struct telemetry_event_desc { +struct __packed telemetry_event_desc { __u8 class; __le16 id; __u8 size; @@ -399,7 +402,7 @@ struct telemetry_data_area_1 { __le16 minor_version; __u8 reserved1[4]; __le64 timestamp; - __u8 log_page_guid[16]; + __u8 log_page_guid[GUID_LEN]; __u8 no_of_tps_supp; __u8 tps; __u8 reserved2[6]; @@ -428,13 +431,13 @@ struct telemetry_data_area_1 { #define MAX_NUM_FIFOS 16 #define DA1_OFFSET 512 #define DEFAULT_ASCII_STRING_SIZE 16 +#define SIZE_OF_VU_EVENT_ID 2 #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 @@ -566,7 +569,7 @@ enum ocp_telemetry_debug_event_class_types { struct __packed telemetry_str_log_format { __u8 log_page_version; __u8 reserved1[15]; - __u8 log_page_guid[C9_GUID_LENGTH]; + __u8 log_page_guid[GUID_LEN]; __le64 sls; __u8 reserved2[24]; __le64 sits; @@ -778,7 +781,7 @@ struct __packed nvme_ocp_telemetry_smart_extended __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 + __u8 log_page_guid[GUID_LEN]; // Bytes 511:496 }; struct __packed nvme_ocp_event_fifo_data @@ -815,7 +818,7 @@ struct __packed nvme_ocp_header_in_da1 __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 log_page_guid[GUID_LEN]; // Bytes 31:16 __u8 num_telemetry_profiles_supported; // Byte 32 __u8 telemetry_profile_selected; // Byte 33 __u8 reserved2[6]; // Bytes 39:34 @@ -856,30 +859,28 @@ struct __packed nvme_ocp_telemetry_event_descriptor 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 +struct __packed nvme_ocp_media_wear_dbg_evt_class_format { - __le16 vu_event_identifier; // Bytes 5:4 + __u8 currentMediaWear[DATA_SIZE_12]; // Bytes 15:4 + }; -struct __packed nvme_ocp_media_wear_dbg_evt_class_format +struct __packed nvme_ocp_common_dbg_evt_class_vu_data { - __u8 currentMediaWear[DATA_SIZE_12]; // Bytes 15:4 - __le16 vu_event_identifier; // Bytes 17:16 + __le16 vu_event_identifier; // Bytes 5:4 + __u8 data[]; // Bytes N:6 }; struct __packed nvme_ocp_statistic_snapshot_evt_class_format @@ -918,7 +919,7 @@ struct __packed nvme_ocp_telemetry_string_header { __u8 version; //0:0 __u8 reserved1[15]; //15:1 - __u8 guid[16]; //32:16 + __u8 guid[GUID_LEN]; //32:16 __le64 string_log_size; //39:32 __u8 reserved2[24]; //63:40 __le64 sits; //71:64 Statistics Identifier String Table Start(SITS) @@ -1226,3 +1227,4 @@ void parse_common_event(struct nvme_ocp_telemetry_event_descriptor *pevent_descr 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); +#endif /* OCP_TELEMETRY_DECODE_H */ |