From 6b3e5f65d8eff76a61a645601d97d0e671d6480d Mon Sep 17 00:00:00 2001 From: Tokunori Ikegami Date: Sun, 12 Jan 2025 00:21:58 +0900 Subject: [PATCH] nvme-print-stdout: add NVMe 2.1 identify power state descriptor fields Since power loss signaling function introduced by NVMe 2.1. Signed-off-by: Tokunori Ikegami --- nvme-print-stdout.c | 70 ++++++++++++++++++++++++++++++++++++++++++++- nvme-print.c | 36 +++++++++++++++++++++++ nvme-print.h | 1 + 3 files changed, 106 insertions(+), 1 deletion(-) diff --git a/nvme-print-stdout.c b/nvme-print-stdout.c index 484696a23e..46fa461d95 100644 --- a/nvme-print-stdout.c +++ b/nvme-print-stdout.c @@ -3020,6 +3020,72 @@ static void print_ps_power_and_scale(__le16 ctr_power, __u8 scale) } } +static void print_epfrt(__u8 epfrt, __u8 epfr_fqv_ts) +{ + const char *desc = "emergency power fail recovery time"; + int width = 12 + strlen(desc); + char value[STR_LEN] = { 0 }; + + switch (epfrt) { + case 0: + snprintf(value, sizeof(value), "-"); + break; + case 1 ... 99: + snprintf(value, sizeof(value), "%d (unit: %s)", epfrt, + nvme_time_scale_to_string(epfr_fqv_ts & 0xf)); + break; + default: + snprintf(value, sizeof(value), "reserved"); + break; + } + + printf("%*s: %s\n", width, desc, value); +} + +static void print_fqvt(__u8 fqvt, __u8 epfr_fqv_ts) +{ + const char *desc = "forced quiescence vault time"; + int width = 12 + strlen(desc); + char value[STR_LEN] = { 0 }; + + switch (fqvt) { + case 0: + snprintf(value, sizeof(value), "-"); + break; + case 1 ... 99: + snprintf(value, sizeof(value), "%d (unit: %s)", fqvt, + nvme_time_scale_to_string(epfr_fqv_ts >> 4)); + break; + default: + snprintf(value, sizeof(value), "reserved"); + break; + } + + printf("%*s: %s\n", width, desc, value); +} + +static void print_epfvt(__u8 epfvt, __u8 epfvts) +{ + const char *desc = "emergency power fail vault time"; + int width = 12 + strlen(desc); + char value[STR_LEN] = { 0 }; + + switch (epfvt) { + case 0: + snprintf(value, sizeof(value), "-"); + break; + case 1 ... 99: + snprintf(value, sizeof(value), "%d (unit: %s)", epfvt, + nvme_time_scale_to_string(epfvts & 0xf)); + break; + default: + snprintf(value, sizeof(value), "reserved"); + break; + } + + printf("%*s: %s\n", width, desc, value); +} + static void stdout_id_ctrl_power(struct nvme_id_ctrl *ctrl) { int i; @@ -3051,7 +3117,9 @@ static void stdout_id_ctrl_power(struct nvme_id_ctrl *ctrl) printf("\n active_power_workload:"); print_psd_workload(ctrl->psd[i].apws); printf("\n"); - + print_epfrt(ctrl->psd[i].epfrt, ctrl->psd[i].epfr_fqv_ts); + print_fqvt(ctrl->psd[i].fqvt, ctrl->psd[i].epfr_fqv_ts); + print_epfvt(ctrl->psd[i].epfvt, ctrl->psd[i].epfvts); } } diff --git a/nvme-print.c b/nvme-print.c index 303ffd8545..77311e6cf5 100644 --- a/nvme-print.c +++ b/nvme-print.c @@ -1313,6 +1313,42 @@ const char *nvme_register_symbol_to_string(int offset) return "unknown"; } +const char *nvme_time_scale_to_string(__u8 ts) +{ + switch (ts) { + case 0: + return "1 microsecond"; + case 1: + return "10 microseconds"; + case 2: + return "100 microseconds"; + case 3: + return "1 millisecond"; + case 4: + return "10 milliseconds"; + case 5: + return "100 milliseconds"; + case 6: + return "1 second"; + case 7: + return "10 seconds"; + case 8: + return "100 seconds"; + case 9: + return "1,000 seconds"; + case 0xa: + return "10,000 seconds"; + case 0xb: + return "100,000 seconds"; + case 0xc: + return "1,000,000 seconds"; + default: + break; + } + + return "Reserved"; +} + void nvme_feature_show(enum nvme_features_id fid, int sel, unsigned int result) { nvme_print(show_feature, NORMAL, fid, sel, result); diff --git a/nvme-print.h b/nvme-print.h index 00f19947c8..b88149a94c 100644 --- a/nvme-print.h +++ b/nvme-print.h @@ -311,6 +311,7 @@ const char *nvme_ns_wp_cfg_to_string(enum nvme_ns_write_protect_cfg state); const char *nvme_pel_rci_rcpit_to_string(enum nvme_pel_rci_rcpit rcpit); const char *nvme_pel_ehai_pit_to_string(enum nvme_pel_ehai_pit pit); const char *nvme_ssi_state_to_string(__u8 state); +const char *nvme_time_scale_to_string(__u8 ts); void nvme_dev_full_path(nvme_ns_t n, char *path, size_t len); void nvme_generic_full_path(nvme_ns_t n, char *path, size_t len);