[PATCH 3/3] nvme: Update several detail information in pel code
wenxiong at linux.vnet.ibm.com
wenxiong at linux.vnet.ibm.com
Mon Apr 26 18:52:18 BST 2021
From: Wen Xiong <root at ltczz405-lp1.aus.stglabs.ibm.com>
Update several detail information in pel:
- Add ascii format in firmware field
Old Firmware Revision: 3617604718875264338 (REV.SP42)
- Add ascii format in timestamp field
The Previous Timestamp is : 1619458220931 (Mon Apr 26 13:30:20 2021 EDT)
- ADD additional Information for hardware error
- Nicely output format
Persistent Event Entries:
EVENT Number : 0
Event Type Revision : 1
Event Header Length : 21
Controller Identifier : 65
Event Timestamp is : 564569411648175 (Fri Jun 29 00:34:08 19860 EDT)
Vendor Specific Information Length: 0
Event Length : 16
EVENT Type : Timestamp Change Event(0x3)
Signed-off-by: Wen Xiong <wenxiong at linux.vnet.ibm.com>
---
linux/nvme.h | 5 +-
nvme-print.c | 180 +++++++++++++++++++++++++++++++++++----------------
2 files changed, 127 insertions(+), 58 deletions(-)
diff --git a/linux/nvme.h b/linux/nvme.h
index fed06bf..2319638 100644
--- a/linux/nvme.h
+++ b/linux/nvme.h
@@ -839,7 +839,7 @@ struct nvme_persistent_event_entry_head {
__u8 ehl;
__u8 rsvd3;
__le16 ctrl_id;
- __le64 etimestamp;
+ __u8 etimestamp[8];
__u8 rsvd14[6];
__le16 vsil;
__le16 el;
@@ -878,7 +878,8 @@ enum nvme_persistent_event_types {
NVME_SANITIZE_START_EVENT = 0x09,
NVME_SANITIZE_COMPLETION_EVENT = 0x0a,
NVME_SET_FEATURE_EVENT = 0x0b,
- NVME_THERMAL_EXCURSION_EVENT = 0x0d
+ NVME_TELEMETRY_CRT_EVENT = 0x0c,
+ NVME_THERMAL_EXCURSION_EVENT = 0x0d,
};
enum nvme_persistent_event_log_actions {
diff --git a/nvme-print.c b/nvme-print.c
index 389c321..fe3b5a2 100755
--- a/nvme-print.c
+++ b/nvme-print.c
@@ -1003,6 +1003,26 @@ void nvme_show_predictable_latency_event_agg_log(
}
}
+const char *nvme_pel_event_to_string(int type)
+{
+ switch (type) {
+ case NVME_SMART_HEALTH_EVENT: return "SMART/Health Log Snapshot Event(0x1)";
+ case NVME_FW_COMMIT_EVENT: return "Firmware Commit Event(0x2)";
+ case NVME_TIMESTAMP_EVENT: return "Timestamp Change Event(0x3)";
+ case NVME_POWER_ON_RESET_EVENT: return "Power-on or Reset Event(0x4)";
+ case NVME_NSS_HW_ERROR_EVENT: return "NVM Subsystem Hardware Error Event(0x5)";
+ case NVME_CHANGE_NS_EVENT: return "Change Namespace Event(0x6)";
+ case NVME_FORMAT_START_EVENT: return "Format NVM Start Event(0x7)";
+ case NVME_FORMAT_COMPLETION_EVENT: return "Format NVM Completion Event(0x8)";
+ case NVME_SANITIZE_START_EVENT: return "Sanitize Start Event(0x9)";
+ case NVME_SANITIZE_COMPLETION_EVENT: return "Sanitize Completion Event(0xa)";
+ case NVME_SET_FEATURE_EVENT: return "Set Feature Event(0xb)";
+ case NVME_TELEMETRY_CRT_EVENT: return "Telemetry Crt Event(0xc)";
+ case NVME_THERMAL_EXCURSION_EVENT: return "Thermal Excursion Event(0xd)";
+ default: return NULL;
+ }
+}
+
static const char *nvme_show_nss_hw_error(__u16 error_code)
{
switch (error_code) {
@@ -1031,6 +1051,30 @@ static const char *nvme_show_nss_hw_error(__u16 error_code)
}
}
+uint64_t int64_to_long(__u8 *data)
+{
+ int i;
+ uint64_t result = 0;
+
+ for (i = 0; i < 8; i++) {
+ result *= 256;
+ result += data[7 - i];
+ }
+ return result;
+}
+
+static const char *persistent_event_show_ts(__u8 *ts)
+{
+ struct tm *tm;
+ static char buffer[32];
+ time_t timestamp = int64_to_long(ts) / 1000;
+ char *ptr = &buffer[0];
+
+ tm = localtime(×tamp);
+ strftime(ptr, sizeof(buffer), "%c %Z", tm);
+ return buffer;
+}
+
void json_persistent_event_log(__u32 event_type, void *pevent_log_info, __u32 size)
{
struct json_object *root;
@@ -1038,7 +1082,7 @@ void json_persistent_event_log(__u32 event_type, void *pevent_log_info, __u32 si
struct json_object *valid;
__u32 offset, por_info_len, por_info_list;
__u64 *fw_rev;
- char key[128];
+ char key[128], str[128];
struct nvme_smart_log *smart_event;
struct nvme_fw_commit_event *fw_commit_event;
struct nvme_time_stamp_change_event *ts_change_event;
@@ -1126,20 +1170,24 @@ void json_persistent_event_log(__u32 event_type, void *pevent_log_info, __u32 si
valid_attrs = json_create_object();
- json_object_add_value_uint(valid_attrs, "event_type",
- pevent_entry_head->etype);
+ json_object_add_value_uint(valid_attrs, "event_number",
+ i);
json_object_add_value_uint(valid_attrs, "event_type_rev",
pevent_entry_head->etype_rev);
json_object_add_value_uint(valid_attrs, "event_header_len",
pevent_entry_head->ehl);
json_object_add_value_uint(valid_attrs, "ctrl_id",
le16_to_cpu(pevent_entry_head->ctrl_id));
- json_object_add_value_uint(valid_attrs, "event_time_stamp",
- le64_to_cpu(pevent_entry_head->etimestamp));
+ sprintf(str, "%"PRIu64" (%s)",
+ int64_to_long(pevent_entry_head->etimestamp),
+ persistent_event_show_ts(pevent_entry_head->etimestamp));
+ json_object_add_value_string(valid_attrs, "event_time_stamp", str);
json_object_add_value_uint(valid_attrs, "vu_info_len",
le16_to_cpu(pevent_entry_head->vsil));
json_object_add_value_uint(valid_attrs, "event_len",
le16_to_cpu(pevent_entry_head->el));
+ json_object_add_value_string(valid_attrs, "event_type",
+ nvme_pel_event_to_string(pevent_entry_head->etype));
offset += pevent_entry_head->ehl + 3;
@@ -1217,10 +1265,12 @@ void json_persistent_event_log(__u32 event_type, void *pevent_log_info, __u32 si
break;
case NVME_FW_COMMIT_EVENT:
fw_commit_event = pevent_log_info + offset;
- json_object_add_value_uint(valid_attrs, "old_fw_rev",
- le64_to_cpu(fw_commit_event->old_fw_rev));
- json_object_add_value_uint(valid_attrs, "new_fw_rev",
- le64_to_cpu(fw_commit_event->new_fw_rev));
+ sprintf(str, "%"PRIu64" (%s)", le64_to_cpu(fw_commit_event->old_fw_rev),
+ fw_to_string(fw_commit_event->old_fw_rev));
+ json_object_add_value_string(valid_attrs, "old_fw_rev", str);
+ sprintf(str, "%"PRIu64" (%s)", le64_to_cpu(fw_commit_event->new_fw_rev),
+ fw_to_string(fw_commit_event->new_fw_rev));
+ json_object_add_value_string(valid_attrs, "new_fw_rev", str);
json_object_add_value_uint(valid_attrs, "fw_commit_action",
fw_commit_event->fw_commit_action);
json_object_add_value_uint(valid_attrs, "fw_slot",
@@ -1235,8 +1285,10 @@ void json_persistent_event_log(__u32 event_type, void *pevent_log_info, __u32 si
break;
case NVME_TIMESTAMP_EVENT:
ts_change_event = pevent_log_info + offset;
- json_object_add_value_uint(valid_attrs, "prev_ts",
- le64_to_cpu(ts_change_event->previous_timestamp));
+ sprintf(str, "%"PRIu64" (%s)",
+ int64_to_long(ts_change_event->previous_timestamp),
+ persistent_event_show_ts(ts_change_event->previous_timestamp));
+ json_object_add_value_string(valid_attrs, "prev_ts", str);
json_object_add_value_uint(valid_attrs,
"ml_secs_since_reset",
le64_to_cpu(ts_change_event->ml_secs_since_reset));
@@ -1248,8 +1300,9 @@ void json_persistent_event_log(__u32 event_type, void *pevent_log_info, __u32 si
por_info_list = por_info_len / sizeof(*por_event);
fw_rev = pevent_log_info + offset;
- json_object_add_value_uint(valid_attrs, "fw_rev",
- le64_to_cpu(*fw_rev));
+ sprintf(str, "%"PRIu64" (%s)", le64_to_cpu(*fw_rev),
+ fw_to_string(*fw_rev));
+ json_object_add_value_string(valid_attrs, "fw_rev", str);
for (int i = 0; i < por_info_list; i++) {
por_event = pevent_log_info + offset +
sizeof(*fw_rev) + i * sizeof(*por_event);
@@ -1263,8 +1316,10 @@ void json_persistent_event_log(__u32 event_type, void *pevent_log_info, __u32 si
le32_to_cpu(por_event->ctrl_power_cycle));
json_object_add_value_uint(valid_attrs, "power_on_ml_secs",
le64_to_cpu(por_event->power_on_ml_seconds));
- json_object_add_value_uint(valid_attrs, "ctrl_time_stamp",
- le64_to_cpu(por_event->ctrl_time_stamp));
+ sprintf(str, "%"PRIu64" (%s)",
+ int64_to_long(por_event->ctrl_time_stamp),
+ persistent_event_show_ts(por_event->ctrl_time_stamp));
+ json_object_add_value_string(valid_attrs, "ctrl_time_stamp", str);
}
break;
case NVME_NSS_HW_ERROR_EVENT:
@@ -1358,10 +1413,11 @@ void nvme_show_persistent_event_log(__u32 event_type, void *pevent_log_info,
__u8 action, __u32 size, const char *devname,
enum nvme_print_flags flags)
{
- __u32 offset, por_info_len, por_info_list;
+ __u32 offset, por_info_len, por_info_list, add_info_len;
__u64 *fw_rev;
int fid, cdw11, dword_cnt;
unsigned char *mem_buf = NULL;
+ bool found = false;
struct nvme_smart_log *smart_event;
struct nvme_fw_commit_event *fw_commit_event;
struct nvme_time_stamp_change_event *ts_change_event;
@@ -1388,31 +1444,31 @@ void nvme_show_persistent_event_log(__u32 event_type, void *pevent_log_info,
printf("Action for Persistent Event Log: %u\n", action);
if (size >= offset) {
pevent_log_head = pevent_log_info;
- printf("Log Identifier: %u\n", pevent_log_head->log_id);
- printf("Total Number of Events: %u\n",
+ printf("Log Identifier : 0x%x\n", pevent_log_head->log_id);
+ printf("Total Number of Events : %u\n",
le32_to_cpu(pevent_log_head->tnev));
- printf("Total Log Length : %"PRIu64"\n",
+ printf("Total Log Length : %"PRIu64"\n",
le64_to_cpu(pevent_log_head->tll));
- printf("Log Revision: %u\n", pevent_log_head->log_rev);
- printf("Log Header Length: %u\n", pevent_log_head->head_len);
- printf("Timestamp: %"PRIu64"\n",
+ printf("Log Revision : %u\n", pevent_log_head->log_rev);
+ printf("Log Header Length : %u\n", pevent_log_head->head_len);
+ printf("Timestamp : %"PRIu64"\n",
le64_to_cpu(pevent_log_head->timestamp));
- printf("Power On Hours (POH): %'.0Lf\n",
+ printf("Power On Hours (POH) : %'.0Lf\n",
int128_to_double(pevent_log_head->poh));
- printf("Power Cycle Count: %"PRIu64"\n",
+ printf("Power Cycle Count : %"PRIu64"\n",
le64_to_cpu(pevent_log_head->pcc));
- printf("PCI Vendor ID (VID): %u\n",
+ printf("PCI Vendor ID (VID) : 0x%x\n",
le16_to_cpu(pevent_log_head->vid));
- printf("PCI Subsystem Vendor ID (SSVID): %u\n",
+ printf("PCI Sub Vendor ID (SSVID): 0x%x\n",
le16_to_cpu(pevent_log_head->ssvid));
- printf("Serial Number (SN): %-.*s\n",
+ printf("Serial Number (SN) : %-.*s\n",
(int)sizeof(pevent_log_head->sn), pevent_log_head->sn);
- printf("Model Number (MN): %-.*s\n",
+ printf("Model Number (MN) : %-.*s\n",
(int)sizeof(pevent_log_head->mn), pevent_log_head->mn);
printf("NVM Subsystem NVMe Qualified Name (SUBNQN): %-.*s\n",
(int)sizeof(pevent_log_head->subnqn),
pevent_log_head->subnqn);
- printf("Supported Events Bitmap: ");
+ printf("Supported Events Bitmap:\n");
for (int i = 0; i < 32; i++) {
if (pevent_log_head->supp_event_bm[i] == 0)
continue;
@@ -1442,34 +1498,38 @@ void nvme_show_persistent_event_log(__u32 event_type, void *pevent_log_info,
offset += pevent_entry_head->ehl + 3;
offset += le16_to_cpu(pevent_entry_head->el);
continue;
- }
+ } else
+ found = true;
- printf("Event Type: %u\n", pevent_entry_head->etype);
- printf("Event Type Revision: %u\n", pevent_entry_head->etype_rev);
- printf("Event Header Length: %u\n", pevent_entry_head->ehl);
- printf("Controller Identifier: %u\n",
+ printf("EVENT Number : %d\n", i);
+ printf("Event Type Revision : %u\n", pevent_entry_head->etype_rev);
+ printf("Event Header Length : %u\n", pevent_entry_head->ehl);
+ printf("Controller Identifier : %u\n",
le16_to_cpu(pevent_entry_head->ctrl_id));
- printf("Event Timestamp: %"PRIu64"\n",
- le64_to_cpu(pevent_entry_head->etimestamp));
+ printf("Event Timestamp is : %"PRIu64" (%s)\n",
+ int64_to_long(pevent_entry_head->etimestamp),
+ persistent_event_show_ts(pevent_entry_head->etimestamp));
printf("Vendor Specific Information Length: %u\n",
le16_to_cpu(pevent_entry_head->vsil));
- printf("Event Length: %u\n", le16_to_cpu(pevent_entry_head->el));
+ printf("Event Length : %u\n", le16_to_cpu(pevent_entry_head->el));
+ printf("EVENT Type : %s\n",
+ nvme_pel_event_to_string(pevent_entry_head->etype));
offset += pevent_entry_head->ehl + 3;
switch (pevent_entry_head->etype) {
case NVME_SMART_HEALTH_EVENT:
smart_event = pevent_log_info + offset;
- printf("Smart Health Event: \n");
nvme_show_smart_log(smart_event, NVME_NSID_ALL, devname, flags);
break;
case NVME_FW_COMMIT_EVENT:
fw_commit_event = pevent_log_info + offset;
- printf("FW Commit Event: \n");
- printf("Old Firmware Revision: %"PRIu64"\n",
- le64_to_cpu(fw_commit_event->old_fw_rev));
- printf("New Firmware Revision: %"PRIu64"\n",
- le64_to_cpu(fw_commit_event->new_fw_rev));
+ printf("Old Firmware Revision: %"PRIu64" (%s)\n",
+ le64_to_cpu(fw_commit_event->old_fw_rev),
+ fw_to_string(fw_commit_event->old_fw_rev));
+ printf("New Firmware Revision: %"PRIu64" (%s)\n",
+ le64_to_cpu(fw_commit_event->new_fw_rev),
+ fw_to_string(fw_commit_event->new_fw_rev));
printf("FW Commit Action: %u\n",
fw_commit_event->fw_commit_action);
printf("FW Slot: %u\n", fw_commit_event->fw_slot);
@@ -1482,9 +1542,9 @@ void nvme_show_persistent_event_log(__u32 event_type, void *pevent_log_info,
break;
case NVME_TIMESTAMP_EVENT:
ts_change_event = pevent_log_info + offset;
- printf("Time Stamp Change Event: \n");
- printf("Previous Timestamp: %"PRIu64"\n",
- le64_to_cpu(ts_change_event->previous_timestamp));
+ printf("The Previous Timestamp is : %"PRIu64" (%s)\n",
+ int64_to_long(ts_change_event->previous_timestamp),
+ persistent_event_show_ts(ts_change_event->previous_timestamp));
printf("Milliseconds Since Reset: %"PRIu64"\n",
le64_to_cpu(ts_change_event->ml_secs_since_reset));
break;
@@ -1494,9 +1554,10 @@ void nvme_show_persistent_event_log(__u32 event_type, void *pevent_log_info,
por_info_list = por_info_len / sizeof(*por_event);
- printf("Power On Reset Event: \n");
fw_rev = pevent_log_info + offset;
- printf("Firmware Revision: %"PRIu64"\n", le64_to_cpu(*fw_rev));
+ printf("Firmware Revision: %"PRIu64 "", le64_to_cpu(*fw_rev));
+ printf("(%-.*s)\n",
+ (int)sizeof(*fw_rev), fw_to_string(*fw_rev));
printf("Reset Information List: \n");
for (int i = 0; i < por_info_list; i++) {
@@ -1511,8 +1572,9 @@ void nvme_show_persistent_event_log(__u32 event_type, void *pevent_log_info,
le32_to_cpu(por_event->ctrl_power_cycle));
printf("Power on milliseconds: %"PRIu64"\n",
le64_to_cpu(por_event->power_on_ml_seconds));
- printf("Controller Timestamp: %"PRIu64"\n",
- le64_to_cpu(por_event->ctrl_time_stamp));
+ printf("Controller Timestamp is : %"PRIu64" (%s)\n",
+ int64_to_long(por_event->ctrl_time_stamp),
+ persistent_event_show_ts(por_event->ctrl_time_stamp));
}
break;
case NVME_NSS_HW_ERROR_EVENT:
@@ -1520,10 +1582,16 @@ void nvme_show_persistent_event_log(__u32 event_type, void *pevent_log_info,
printf("NVM Subsystem Hardware Error Event Code: %u, %s\n",
le16_to_cpu(nss_hw_err_event->nss_hw_err_event_code),
nvme_show_nss_hw_error(nss_hw_err_event->nss_hw_err_event_code));
+ add_info_len = (le16_to_cpu(pevent_entry_head->el) -
+ le16_to_cpu(pevent_entry_head->vsil) - 4);
+ if (add_info_len != 0) {
+ printf("Additional Hardware error Information :\n");
+ d((unsigned char *)(nss_hw_err_event + 4), add_info_len, 16, 1);
+ }
+
break;
case NVME_CHANGE_NS_EVENT:
ns_event = pevent_log_info + offset;
- printf("Change Namespace Event: \n");
printf("Namespace Management CDW10: %u\n",
le32_to_cpu(ns_event->nsmgt_cdw10));
printf("Namespace Size: %"PRIu64"\n",
@@ -1542,7 +1610,6 @@ void nvme_show_persistent_event_log(__u32 event_type, void *pevent_log_info,
break;
case NVME_FORMAT_START_EVENT:
format_start_event = pevent_log_info + offset;
- printf("Format NVM Start Event: \n");
printf("Namespace Identifier: %u\n",
le32_to_cpu(format_start_event->nsid));
printf("Format NVM Attributes: %u\n",
@@ -1552,7 +1619,6 @@ void nvme_show_persistent_event_log(__u32 event_type, void *pevent_log_info,
break;
case NVME_FORMAT_COMPLETION_EVENT:
format_cmpln_event = pevent_log_info + offset;
- printf("Format NVM Completion Event: \n");
printf("Namespace Identifier: %u\n",
le32_to_cpu(format_cmpln_event->nsid));
printf("Smallest Format Progress Indicator: %u\n",
@@ -1566,7 +1632,6 @@ void nvme_show_persistent_event_log(__u32 event_type, void *pevent_log_info,
break;
case NVME_SANITIZE_START_EVENT:
sanitize_start_event = pevent_log_info + offset;
- printf("Sanitize Start Event: \n");
printf("SANICAP: %u\n", sanitize_start_event->sani_cap);
printf("Sanitize CDW10: %u\n",
le32_to_cpu(sanitize_start_event->sani_cdw10));
@@ -1575,7 +1640,6 @@ void nvme_show_persistent_event_log(__u32 event_type, void *pevent_log_info,
break;
case NVME_SANITIZE_COMPLETION_EVENT:
sanitize_cmpln_event = pevent_log_info + offset;
- printf("Sanitize Completion Event: \n");
printf("Sanitize Progress: %u\n",
le16_to_cpu(sanitize_cmpln_event->sani_prog));
printf("Sanitize Status: %u\n",
@@ -1599,7 +1663,6 @@ void nvme_show_persistent_event_log(__u32 event_type, void *pevent_log_info,
break;
case NVME_THERMAL_EXCURSION_EVENT:
thermal_exc_event = pevent_log_info + offset;
- printf("Thermal Excursion Event: \n");
printf("Over Temperature: %u\n", thermal_exc_event->over_temp);
printf("Threshold: %u\n", thermal_exc_event->threshold);
break;
@@ -1609,6 +1672,11 @@ void nvme_show_persistent_event_log(__u32 event_type, void *pevent_log_info,
offset += le16_to_cpu(pevent_entry_head->el);
printf("\n");
}
+ if (event_type != 0 && !found && nvme_pel_event_to_string(event_type))
+ printf("Current PEL: No %s\n", nvme_pel_event_to_string(event_type));
+ else
+ printf("Current PEL: Not support 0x%x event in PEL\n", event_type);
+
}
void json_endurance_group_event_agg_log(
--
2.27.0
More information about the Linux-nvme
mailing list