diff --git a/nvme-print-json.c b/nvme-print-json.c index 4ac24146a9..37e4a3bc29 100644 --- a/nvme-print-json.c +++ b/nvme-print-json.c @@ -45,7 +45,7 @@ static const uint8_t zero_uuid[16] = { 0 }; static struct print_ops json_print_ops; static struct json_object *json_r; -static void json_feature_show_fields(enum nvme_features_id fid, unsigned int result, +static void json_feature_show_fields(enum nvme_features_id fid, __u32 cdw11, unsigned int result, unsigned char *buf); static void d_json(unsigned char *buf, int len, int width, int group, struct json_object *array) @@ -1751,7 +1751,7 @@ static void json_pel_set_feature(void *pevent_log_info, __u32 offset, if (NVME_SET_FEAT_EVENT_MB_COUNT(set_feat_event->layout)) { mem_buf = (unsigned char *)(set_feat_event + 4 + dword_cnt * 4); - json_feature_show_fields(fid, cdw11, mem_buf); + json_feature_show_fields(fid, cdw11, cdw11, mem_buf); } } @@ -3589,6 +3589,69 @@ static void json_feature_show_fields_power_loss_signal(struct json_object *r, un nvme_pls_mode_to_string(NVME_GET(result, FEAT_PLS_MODE))); } +static void json_perfc_std_attr(struct json_object *r, struct nvme_std_perf_attr *std_perf) +{ + obj_add_str(r, "Random 4 KiB average read latency (R4KARL)", + nvme_perf_lat_to_string(std_perf->r4karl)); +} + +static void json_perfc_attr_id_list(struct json_object *r, struct nvme_perf_attr_id_list *id_list) +{ + int i; + char json_str[STR_LEN]; + + obj_add_str(r, "Attribute Type (ATTRTYP)", + nvme_perf_attr_type_to_string(NVME_GET(id_list->attrtyp, FEAT_PERFC_ATTRTYP))); + obj_add_uint(r, "Maximum Saveable Vendor Specific Performance Attributes (MSVSPA)", + id_list->msvspa); + obj_add_uint(r, "Unused Saveable Vendor Specific Performance Attributes (USVSPA)", + id_list->usvspa); + for (i = 0; i < ARRAY_SIZE(id_list->id_list); i++) { + sprintf(json_str, "Performance Attribute %Xh Identifier (PA%XHI)", i, i); + obj_add_str(r, json_str, util_uuid_to_string(id_list->id_list[i].id)); + } +} + +static void json_perfc_vs_attr(struct json_object *r, struct nvme_vs_perf_attr *vs_perf) +{ + obj_add_str(r, "Performance Attribute Identifier (PAID)", + memcmp(vs_perf->paid.id, zero_uuid, sizeof(zero_uuid)) ? + util_uuid_to_string(vs_perf->paid.id) : "Unused"); + obj_add_uint(r, "Attribute Length (ATTRL)", le16_to_cpu(vs_perf->attrl)); + obj_d(r, "Vendor Specific (VS)", (unsigned char *)vs_perf->vs, le16_to_cpu(vs_perf->attrl), + 16, 1); +} + +static void json_perf_characteristics(struct json_object *r, __u32 cdw11, unsigned char *buf) +{ + struct nvme_perf_characteristics *attr = (struct nvme_perf_characteristics *)buf; + __u8 attri; + bool rvspa; + + nvme_feature_decode_perf_characteristics(cdw11, &attri, &rvspa); + + obj_add_str(r, "Attribute Index (ATTRI)", nvme_attr_index_to_string(attri)); + obj_add_str(r, "Revert Vendor Specific Performance Attribute (RVSPA)", + rvspa ? "Deleted" : "Not deleted"); + + if (!attr) + return; + + switch (attri) { + case 0: + json_perfc_std_attr(r, attr->std_perf); + break; + case 0xc0: + json_perfc_attr_id_list(r, attr->id_list); + break; + case 0xc1 ... 0xff: + json_perfc_vs_attr(r, attr->vs_perf); + break; + default: + break; + } +} + static void json_host_metadata(struct json_object *r, enum nvme_features_id fid, struct nvme_host_metadata *data) { @@ -3711,7 +3774,7 @@ static void json_feature_show(enum nvme_features_id fid, int sel, unsigned int r obj_print(r); } -static void json_feature_show_fields(enum nvme_features_id fid, unsigned int result, +static void json_feature_show_fields(enum nvme_features_id fid, __u32 cdw11, unsigned int result, unsigned char *buf) { struct json_object *r; @@ -3802,6 +3865,8 @@ static void json_feature_show_fields(enum nvme_features_id fid, unsigned int res case NVME_FEAT_FID_POWER_LOSS_SIGNAL: json_feature_show_fields_power_loss_signal(r, result); break; + case NVME_FEAT_FID_PERF_CHARACTERISTICS: + json_perf_characteristics(r, cdw11, buf); case NVME_FEAT_FID_ENH_CTRL_METADATA: case NVME_FEAT_FID_CTRL_METADATA: case NVME_FEAT_FID_NS_METADATA: diff --git a/nvme-print-stdout.c b/nvme-print-stdout.c index e87c605db4..87ed3fe348 100644 --- a/nvme-print-stdout.c +++ b/nvme-print-stdout.c @@ -162,8 +162,7 @@ static void nvme_resources_free(struct nvme_resources *res) htable_subsys_clear(&res->ht_s); } -static void stdout_feature_show_fields(enum nvme_features_id fid, - unsigned int result, +static void stdout_feature_show_fields(enum nvme_features_id fid, __u32 cdw11, unsigned int result, unsigned char *buf); static void stdout_smart_log(struct nvme_smart_log *smart, unsigned int nsid, const char *devname); @@ -463,7 +462,7 @@ static void pel_set_feature_event(void *pevent_log_info, __u32 offset) cdw12 = le32_to_cpu(set_feat_event->cdw_mem[2]); stdout_persistent_event_log_fdp_events(cdw11, cdw12, mem_buf); } else { - stdout_feature_show_fields(fid, cdw11, mem_buf); + stdout_feature_show_fields(fid, cdw11, cdw11, mem_buf); } } @@ -4864,6 +4863,67 @@ static void stdout_plm_config(struct nvme_plm_config *plmcfg) printf("\tDTWIN Time Threshold :%"PRIu64"\n", le64_to_cpu(plmcfg->dtwintt)); } +static void stdout_perfc_std_attr(struct nvme_std_perf_attr *std_perf) +{ + printf("\tRandom 4 KiB average read latency (R4KARL): %s\n", + nvme_perf_lat_to_string(std_perf->r4karl)); +} + +static void stdout_perfc_attr_id_list(struct nvme_perf_attr_id_list *id_list) +{ + int i; + + printf("\tAttribute Type (ATTRTYP): %s\n", + nvme_perf_attr_type_to_string(NVME_GET(id_list->attrtyp, FEAT_PERFC_ATTRTYP))); + printf("\tMaximum Saveable Vendor Specific Performance Attributes (MSVSPA): %u\n", + id_list->msvspa); + printf("\tUnused Saveable Vendor Specific Performance Attributes (USVSPA): %u\n", + id_list->usvspa); + for (i = 0; i < ARRAY_SIZE(id_list->id_list); i++) + printf("\tPerformance Attribute %Xh Identifier (PA%XHI): %s\n", i, i, + util_uuid_to_string(id_list->id_list[i].id)); +} + +static void stdout_perfc_vs_attr(struct nvme_vs_perf_attr *vs_perf) +{ + printf("\tPerformance Attribute Identifier (PAID): %s\n", + memcmp(vs_perf->paid.id, zero_uuid, sizeof(zero_uuid)) ? + util_uuid_to_string(vs_perf->paid.id) : "Unused"); + printf("\tAttribute Length (ATTRL): %u\n", le16_to_cpu(vs_perf->attrl)); + printf("\tVendor Specific (VS)\n"); + d((unsigned char *)vs_perf->vs, le16_to_cpu(vs_perf->attrl), 16, 1); +} + +static void stdout_perf_characteristics(__u32 cdw11, unsigned char *buf) +{ + struct nvme_perf_characteristics *attr = (struct nvme_perf_characteristics *)buf; + __u8 attri; + bool rvspa; + + nvme_feature_decode_perf_characteristics(cdw11, &attri, &rvspa); + + printf("\tAttribute Index (ATTRI): %s\n", nvme_attr_index_to_string(attri)); + printf("\tRevert Vendor Specific Performance Attribute (RVSPA): %s\n", + rvspa ? "Deleted" : "Not deleted"); + + if (!attr) + return; + + switch (attri) { + case 0: + stdout_perfc_std_attr(attr->std_perf); + break; + case 0xc0: + stdout_perfc_attr_id_list(attr->id_list); + break; + case 0xc1 ... 0xff: + stdout_perfc_vs_attr(attr->vs_perf); + break; + default: + break; + } +} + static void stdout_host_metadata(enum nvme_features_id fid, struct nvme_host_metadata *data) { @@ -4894,8 +4954,7 @@ static void stdout_feature_show(enum nvme_features_id fid, int sel, unsigned int nvme_feature_to_string(fid), nvme_select_to_string(sel), result ? 10 : 8, result); } -static void stdout_feature_show_fields(enum nvme_features_id fid, - unsigned int result, +static void stdout_feature_show_fields(enum nvme_features_id fid, __u32 cdw11, unsigned int result, unsigned char *buf) { const char *async = "Send async event"; @@ -5093,6 +5152,8 @@ static void stdout_feature_show_fields(enum nvme_features_id fid, printf("\tPower Loss Signaling Mode (PLSM): %s\n", nvme_pls_mode_to_string(NVME_GET(result, FEAT_PLS_MODE))); break; + case NVME_FEAT_FID_PERF_CHARACTERISTICS: + stdout_perf_characteristics(cdw11, buf); case NVME_FEAT_FID_ENH_CTRL_METADATA: case NVME_FEAT_FID_CTRL_METADATA: case NVME_FEAT_FID_NS_METADATA: diff --git a/nvme-print.c b/nvme-print.c index 8492225e7f..058c002a83 100644 --- a/nvme-print.c +++ b/nvme-print.c @@ -1364,14 +1364,105 @@ const char *nvme_pls_mode_to_string(__u8 mode) return "Reserved"; } +const char *nvme_attr_index_to_string(__u8 index) +{ + switch (index) { + case 0: + return "Standard Performance Attribute 00h"; + case 0xc0: + return "Performance Attribute Identifier List"; + case 0xc1 ... 0xff: + return "Vendor Specific Performance Attribute"; + default: + break; + } + + return "Reserved"; +} + +const char *nvme_perf_lat_to_string(__u8 lat) +{ + switch (lat) { + case 0: + return "Not Reported"; + case 1: + return "Greater than or equal to 100 seconds"; + case 2: + return "Greater than or equal to 50 seconds and less than 100 seconds"; + case 3: + return "Greater than or equal to 10 seconds and less than 50 seconds"; + case 4: + return "Greater than or equal to 5 seconds and less than 10 seconds"; + case 5: + return "Greater than or equal to 1 second and less than 5 seconds"; + case 6: + return "Greater than or equal to 500 milliseconds and less than 1 second"; + case 7: + return "Greater than or equal to 100 milliseconds and less than 500 milliseconds"; + case 8: + return "Greater than or equal to 50 milliseconds and less than 100 milliseconds"; + case 9: + return "Greater than or equal to 10 milliseconds and less than 50 milliseconds"; + case 0xa: + return "Greater than or equal to 5 milliseconds and less than 10 milliseconds"; + case 0xb: + return "Greater than or equal to 1 millisecond and less than 5 milliseconds"; + case 0xc: + return "Greater than or equal to 500 microseconds and less than 1 millisecond"; + case 0xd: + return "Greater than or equal to 100 microseconds and less than 500 microseconds"; + case 0xe: + return "Greater than or equal to 50 microseconds and less than 100 microseconds"; + case 0xf: + return "Greater than or equal to 10 microseconds and less than 50 microseconds"; + case 0x10: + return "Greater than or equal to 5 microseconds and less than 10 microseconds"; + case 0x11: + return "Greater than or equal to 1 microsecond and less than 5 microseconds"; + case 0x12: + return "Greater than or equal to 500 nanoseconds and less than 1 microsecond"; + case 0x13: + return "Greater than or equal to 100 nanoseconds and less than 500 nanoseconds"; + case 0x14: + return "Greater than or equal to 50 nanoseconds and less than 100 nanoseconds"; + case 0x15: + return "Greater than or equal to 10 nanoseconds and less than 50 nanoseconds"; + case 0x16: + return "Greater than or equal to 5 nanoseconds and less than 10 nanoseconds"; + case 0x17: + return "Greater than or equal to 1 nanosecond and less than 5 nanoseconds"; + default: + break; + } + + return "Reserved"; +} + +const char *nvme_perf_attr_type_to_string(__u8 type) +{ + switch (type) { + case 0: + return "Current attribute"; + case 1: + return "Default attribute"; + case 2: + return "Saved attribute"; + 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); } -void nvme_feature_show_fields(enum nvme_features_id fid, unsigned int result, unsigned char *buf) +void nvme_feature_show_fields(enum nvme_features_id fid, __u32 cdw11, unsigned int result, + unsigned char *buf) { - nvme_print(show_feature_fields, NORMAL, fid, result, buf); + nvme_print(show_feature_fields, NORMAL, fid, cdw11, result, buf); } void nvme_show_lba_status(struct nvme_lba_status *list, unsigned long len, diff --git a/nvme-print.h b/nvme-print.h index ad5d4c829b..74402ea44c 100644 --- a/nvme-print.h +++ b/nvme-print.h @@ -81,7 +81,7 @@ struct print_ops { void (*zns_id_ns)(struct nvme_zns_id_ns *ns, struct nvme_id_ns *id_ns); void (*zns_report_zones)(void *report, __u32 descs, __u8 ext_size, __u32 report_size, struct json_object *zone_list); void (*show_feature)(enum nvme_features_id fid, int sel, unsigned int result); - void (*show_feature_fields)(enum nvme_features_id fid, unsigned int result, unsigned char *buf); + void (*show_feature_fields)(enum nvme_features_id fid, __u32 cdw11, unsigned int result, unsigned char *buf); void (*id_ctrl_rpmbs)(__le32 ctrl_rpmbs); void (*lba_range)(struct nvme_lba_range_type *lbrt, int nr_ranges); void (*lba_status_info)(__u32 result); @@ -249,7 +249,8 @@ void nvme_show_topology(nvme_root_t t, nvme_print_flags_t flags); void nvme_feature_show(enum nvme_features_id fid, int sel, unsigned int result); -void nvme_feature_show_fields(enum nvme_features_id fid, unsigned int result, unsigned char *buf); +void nvme_feature_show_fields(enum nvme_features_id fid, __u32 cdw11, unsigned int result, + unsigned char *buf); void nvme_directive_show(__u8 type, __u8 oper, __u16 spec, __u32 nsid, __u32 result, void *buf, __u32 len, nvme_print_flags_t flags); void nvme_show_select_result(enum nvme_features_id fid, __u32 result); @@ -322,6 +323,9 @@ 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); const char *nvme_pls_mode_to_string(__u8 mode); +const char *nvme_attr_index_to_string(__u8 index); +const char *nvme_perf_lat_to_string(__u8 lat); +const char *nvme_perf_attr_type_to_string(__u8 type); 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); diff --git a/nvme.c b/nvme.c index bb41284310..5dba68f234 100644 --- a/nvme.c +++ b/nvme.c @@ -4749,7 +4749,7 @@ static void get_feature_id_print(struct feat_cfg cfg, int err, __u32 result, if (NVME_CHECK(cfg.sel, GET_FEATURES_SEL, SUPPORTED)) nvme_show_select_result(cfg.feature_id, result); else if (verbose || !strcmp(nvme_cfg.output_format, "json")) - nvme_feature_show_fields(cfg.feature_id, result, buf); + nvme_feature_show_fields(cfg.feature_id, cfg.cdw11, result, buf); else if (buf) d(buf, cfg.data_len, 16, 1); } else if (buf) {