diff options
Diffstat (limited to 'nvme-print.c')
-rwxr-xr-x | nvme-print.c | 548 |
1 files changed, 517 insertions, 31 deletions
diff --git a/nvme-print.c b/nvme-print.c index 1d2fb0c..f631b34 100755 --- a/nvme-print.c +++ b/nvme-print.c @@ -1105,6 +1105,10 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) json_object_add_value_string(root, "sn", sn); json_object_add_value_string(root, "mn", mn); json_object_add_value_string(root, "subnqn", subnqn); + json_object_add_value_uint(root, "gen_number", + le16_to_cpu(pevent_log_head->gen_number)); + json_object_add_value_uint(root, "rci", + le32_to_cpu(pevent_log_head->rci)); for (int i = 0; i < 32; i++) { if (pevent_log_head->supp_event_bm[i] == 0) continue; @@ -1355,6 +1359,25 @@ void json_persistent_event_log(void *pevent_log_info, __u32 size) json_free_object(root); } +static void nvme_show_persistent_event_log_rci(__le32 pel_header_rci) +{ + __u32 rci = le32_to_cpu(pel_header_rci); + __u32 rsvd19 = (rci & 0xfff80000) >> 19; + __u8 rce = (rci & 0x40000) >> 18; + __u8 rcpit = (rci & 0x30000) >> 16; + __u16 rcpid = rci & 0xffff; + + if(rsvd19) + printf(" [31:19] : %#x\tReserved\n", rsvd19); + printf("\tReporting Context Exists (RCE): %s(%u)\n", + rce ? "true" : "false", rce); + printf("\tReporting Context Port Identifier Type (RCPIT): %u(%s)\n", rcpit, + (rcpit == 0x00) ? "Does not already exist" : + (rcpit == 0x01) ? "NVM subsystem port" : + (rcpit == 0x10) ? "NVMe-MI port" : "Reserved"); + printf("\tReporting Context Port Identifier (RCPID): %#x\n\n", rcpid); +} + void nvme_show_persistent_event_log(void *pevent_log_info, __u8 action, __u32 size, const char *devname, enum nvme_print_flags flags) @@ -1375,6 +1398,7 @@ void nvme_show_persistent_event_log(void *pevent_log_info, struct nvme_persistent_event_log_head *pevent_log_head; struct nvme_persistent_event_entry_head *pevent_entry_head; + int human = flags & VERBOSE; if (flags & BINARY) return d_raw((unsigned char *)pevent_log_info, size); if (flags & JSON) @@ -1410,6 +1434,12 @@ void nvme_show_persistent_event_log(void *pevent_log_info, printf("NVM Subsystem NVMe Qualified Name (SUBNQN): %-.*s\n", (int)sizeof(pevent_log_head->subnqn), pevent_log_head->subnqn); + printf("Generation Number: %u\n", + le16_to_cpu(pevent_log_head->gen_number)); + printf("Reporting Context Information (RCI): %u\n", + le32_to_cpu(pevent_log_head->rci)); + if(human) + nvme_show_persistent_event_log_rci(pevent_log_head->rci); printf("Supported Events Bitmap: "); for (int i = 0; i < 32; i++) { if (pevent_log_head->supp_event_bm[i] == 0) @@ -1795,6 +1825,117 @@ void nvme_show_resv_notif_log(struct nvme_resv_notif_log *resv, le32_to_cpu(resv->nsid)); } +static void json_boot_part_log(void *bp_log) +{ + struct nvme_boot_part_hdr *hdr; + struct json_object *root; + + hdr = bp_log; + root = json_create_object(); + + json_object_add_value_uint(root, "count", hdr->lid); + json_object_add_value_uint(root, "abpid", + (le32_to_cpu(hdr->bpinfo) >> 31) & 0x1); + json_object_add_value_uint(root, "bpsz", + le32_to_cpu(hdr->bpinfo) & 0x7fff); + + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); +} + +static void json_fid_support_effects_log(struct nvme_fid_support_effects *fid_log) +{ + struct json_object *root; + struct json_object *fids; + struct json_object *fids_list; + unsigned int fid; + char key[128]; + __u32 fid_support; + + root = json_create_object(); + fids_list = json_create_array(); + for (fid = 0; fid < 256; fid++) { + fid_support = le32_to_cpu(fid_log->fid_support[fid]); + if (fid_support & NVME_FID_EFFECTS_FSUPP) { + fids = json_create_object(); + sprintf(key, "fid_%u", fid); + json_object_add_value_uint(fids, key, fid_support); + json_array_add_value_object(fids_list, fids); + } + } + + json_object_add_value_object(root, "fid_support", fids_list); + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); +} + +void nvme_show_boot_part_log(void *bp_log, const char *devname, + __u32 size, enum nvme_print_flags flags) +{ + struct nvme_boot_part_hdr *hdr; + if (flags & BINARY) + return d_raw((unsigned char *)bp_log, size); + if (flags & JSON) + return json_boot_part_log(bp_log); + + hdr = bp_log; + printf("Boot Partition Log for device: %s\n", devname); + printf("Log ID: %u\n", hdr->lid); + printf("Boot Partition Size: %u KiB\n", le32_to_cpu(hdr->bpinfo) & 0x7fff); + printf("Active BPID: %u\n", (le32_to_cpu(hdr->bpinfo) >> 31) & 0x1); +} + +static void nvme_show_fid_support_effects_log_human(__u32 fid_support) +{ + const char *set = "+"; + const char *clr = "-"; + __u16 fsp; + + printf(" FSUPP+"); + printf(" UDCC%s", (fid_support & NVME_FID_EFFECTS_UDCC) ? set : clr); + printf(" NCC%s", (fid_support & NVME_FID_EFFECTS_NCC) ? set : clr); + printf(" NIC%s", (fid_support & NVME_FID_EFFECTS_NIC) ? set : clr); + printf(" CCC%s", (fid_support & NVME_FID_EFFECTS_CCC) ? set : clr); + printf(" USS%s", (fid_support & NVME_FID_EFFECTS_UUID_SEL) ? set : clr); + + fsp = (fid_support >> NVME_FID_SCOPE_SHIFT) & NVME_FID_SCOPE_MASK; + + printf(" NAMESPACE SCOPE%s", (fsp & NVME_FID_SCOPE_NS) ? set : clr); + printf(" CONTROLLER SCOPE%s", (fsp & NVME_FID_SCOPE_CTRL) ? set : clr); + printf(" NVM SET SCOPE%s", (fsp & NVME_FID_SCOPE_NVM_SET) ? set : clr); + printf(" ENDURANCE GROUP SCOPE%s", (fsp & NVME_FID_SCOPE_ENDGRP) ? set : clr); + printf(" DOMAIN SCOPE%s", (fsp & NVME_FID_SCOPE_DOMAIN) ? set : clr); + printf(" NVM Subsystem SCOPE%s", (fsp & NVME_FID_SCOPE_NSS) ? set : clr); +} + +void nvme_show_fid_support_effects_log(struct nvme_fid_support_effects *fid_log, + const char *devname, enum nvme_print_flags flags) +{ + __u32 fid_effect; + int i, human = flags & VERBOSE; + + if (flags & BINARY) + return d_raw((unsigned char *)fid_log, sizeof(*fid_log)); + if (flags & JSON) + return json_fid_support_effects_log(fid_log); + + printf("FID Supports Effects Log for device: %s\n", devname); + printf("Admin Command Set\n"); + for (i = 0; i < 256; i++) { + fid_effect = le32_to_cpu(fid_log->fid_support[i]); + if (fid_effect & NVME_FID_EFFECTS_FSUPP) { + printf("FID %02x -> Support Effects Log: %08x", i, + fid_effect); + if (human) + nvme_show_fid_support_effects_log_human(fid_effect); + else + printf("\n"); + } + } +} + static void nvme_show_subsystem(struct nvme_subsystem *s) { int i; @@ -2609,6 +2750,28 @@ void nvme_show_relatives(const char *name) free(path); } +void d_json(unsigned char *buf, int len, int width, int group, + struct json_object *array) +{ + int i, line_done = 0; + char ascii[32 + 1]; + assert(width < sizeof(ascii)); + + for (i = 0; i < len; i++) { + line_done = 0; + ascii[i % width] = (buf[i] >= '!' && buf[i] <= '~') ? buf[i] : '.'; + if (((i + 1) % width) == 0) { + ascii[i % width + 1] = '\0'; + json_array_add_value_string(array, ascii); + line_done = 1; + } + } + if (!line_done) { + ascii[i % width + 1] = '\0'; + json_array_add_value_string(array, ascii); + } +} + void d(unsigned char *buf, int len, int width, int group) { int i, offset = 0, line_done = 0; @@ -3592,6 +3755,88 @@ void nvme_show_id_ns(struct nvme_id_ns *ns, unsigned int nsid, } } +static void nvme_show_cmd_set_independent_id_ns_nsfeat(__u8 nsfeat) +{ + __u8 rsvd5 = (nsfeat & 0xE0) >> 5; + __u8 rmedia = (nsfeat & 0x10) >> 4; + __u8 uidreuse = (nsfeat & 0x8) >> 3; + __u8 rsvd0 = (nsfeat & 0x7); + if (rsvd5) + printf(" [7:5] : %#x\tReserved\n", rsvd5); + printf(" [4:4] : %#x\tNamespace %sstore data on rotational media\n", + rmedia, rmedia ? "" : "does not "); + printf(" [3:3] : %#x\tNGUID and EUI64 fields if non-zero, %sReused\n", + uidreuse, uidreuse ? "Never " : ""); + if (rsvd0) + printf(" [2:0] : %#x\tReserved\n", rsvd0); + printf("\n"); +} + +static void nvme_show_cmd_set_independent_id_ns_nstat(__u8 nstat) +{ + __u8 rsvd1 = (nstat & 0xfe) >> 1; + __u8 nrdy = nstat & 0x1; + if (rsvd1) + printf(" [7:1] : %#x\tReserved\n", rsvd1); + printf(" [0:0] : %#x\tName space is %sready\n", + nrdy, nrdy ? "" : "not "); + printf("\n"); +} + +static void json_nvme_cmd_set_independent_id_ns( + struct nvme_cmd_set_independent_id_ns *ns) +{ + struct json_object *root; + root = json_create_object(); + + json_object_add_value_int(root, "nsfeat", ns->nsfeat); + json_object_add_value_int(root, "nmic", ns->nmic); + json_object_add_value_int(root, "rescap", ns->rescap); + json_object_add_value_int(root, "fpi", ns->fpi); + json_object_add_value_int(root, "anagrpid", le32_to_cpu(ns->anagrpid)); + json_object_add_value_int(root, "nsattr", ns->nsattr); + json_object_add_value_int(root, "nvmsetid", le16_to_cpu(ns->nvmsetid)); + json_object_add_value_int(root, "endgid", le16_to_cpu(ns->endgid)); + json_object_add_value_int(root, "nstat", ns->nstat); + + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); +} + +void nvme_show_cmd_set_independent_id_ns( + struct nvme_cmd_set_independent_id_ns *ns, unsigned int nsid, + enum nvme_print_flags flags) +{ + int human = flags & VERBOSE; + + if (flags & BINARY) + return d_raw((unsigned char *)ns, sizeof(*ns)); + if (flags & JSON) + return json_nvme_cmd_set_independent_id_ns(ns); + + printf("NVME Identify Command Set Idependent Namespace %d:\n", nsid); + printf("nsfeat : %#x\n", ns->nsfeat); + if (human) + nvme_show_cmd_set_independent_id_ns_nsfeat(ns->nsfeat); + printf("nmic : %#x\n", ns->nmic); + if (human) + nvme_show_id_ns_nmic(ns->nmic); + printf("rescap : %#x\n", ns->rescap); + if (human) + nvme_show_id_ns_rescap(ns->rescap); + printf("fpi : %#x\n", ns->fpi); + if (human) + nvme_show_id_ns_fpi(ns->fpi); + printf("anagrpid: %u\n", le32_to_cpu(ns->anagrpid)); + printf("nsattr : %u\n", ns->nsattr); + printf("nvmsetid: %d\n", le16_to_cpu(ns->nvmsetid)); + printf("endgid : %d\n", le16_to_cpu(ns->endgid)); + + printf("nstat : %#x\n", ns->nstat); + if (human) + nvme_show_cmd_set_independent_id_ns_nstat(ns->nstat); +} static void json_nvme_id_ns_descs(void *data) { @@ -4059,6 +4304,12 @@ void json_nvme_zns_id_ns(struct nvme_zns_id_ns *ns, json_object_add_value_int(root, "mor", le32_to_cpu(ns->mor)); json_object_add_value_int(root, "rrl", le32_to_cpu(ns->rrl)); json_object_add_value_int(root, "frl", le32_to_cpu(ns->frl)); + json_object_add_value_int(root, "rrl1", le32_to_cpu(ns->rrl1)); + json_object_add_value_int(root, "rrl2", le32_to_cpu(ns->rrl2)); + json_object_add_value_int(root, "rrl3", le32_to_cpu(ns->rrl3)); + json_object_add_value_int(root, "frl1", le32_to_cpu(ns->frl1)); + json_object_add_value_int(root, "frl2", le32_to_cpu(ns->frl2)); + json_object_add_value_int(root, "frl3", le32_to_cpu(ns->frl3)); lbafs = json_create_array(); json_object_add_value_array(root, "lbafe", lbafs); @@ -4104,6 +4355,16 @@ static void show_nvme_id_ns_zoned_ozcs(__le16 ns_ozcs) razb, razb ? "Yes" : "No"); } +static void nvme_show_zns_id_ns_recommandeded_limit(__le32 ns_rl, int human, + const char *target_limit) +{ + unsigned int recommandeded_limit = le32_to_cpu(ns_rl); + if (!recommandeded_limit && human) + printf("%s : Not Reported\n", target_limit); + else + printf("%s : %u\n", target_limit, recommandeded_limit); +} + void nvme_show_zns_id_ns(struct nvme_zns_id_ns *ns, struct nvme_id_ns *id_ns, unsigned long flags) { @@ -4152,15 +4413,14 @@ void nvme_show_zns_id_ns(struct nvme_zns_id_ns *ns, printf("mor : %#x\n", le32_to_cpu(ns->mor)); } - if (!le32_to_cpu(ns->rrl) && human) - printf("rrl : Not Reported\n"); - else - printf("rrl : %d\n", le32_to_cpu(ns->rrl)); - - if (!le32_to_cpu(ns->frl) && human) - printf("frl : Not Reported\n"); - else - printf("frl : %d\n", le32_to_cpu(ns->frl)); + nvme_show_zns_id_ns_recommandeded_limit(ns->rrl, human, "rrl "); + nvme_show_zns_id_ns_recommandeded_limit(ns->frl, human, "frl "); + nvme_show_zns_id_ns_recommandeded_limit(ns->rrl1, human, "rrl1"); + nvme_show_zns_id_ns_recommandeded_limit(ns->rrl2, human, "rrl2"); + nvme_show_zns_id_ns_recommandeded_limit(ns->rrl3, human, "rrl3"); + nvme_show_zns_id_ns_recommandeded_limit(ns->frl, human, "frl1"); + nvme_show_zns_id_ns_recommandeded_limit(ns->frl, human, "frl2"); + nvme_show_zns_id_ns_recommandeded_limit(ns->frl, human, "frl3"); for (i = 0; i <= id_ns->nlbaf; i++){ if (human) @@ -4238,7 +4498,7 @@ void nvme_show_zns_changed(struct nvme_zns_changed_zone_log *log, printf("zid %03d: %"PRIu64"\n", i, (uint64_t)le64_to_cpu(log->zid[i])); } -char *zone_type_to_string(__u8 cond) +static char *zone_type_to_string(__u8 cond) { switch (cond) { case NVME_ZONE_TYPE_SEQWRITE_REQ: @@ -4248,7 +4508,7 @@ char *zone_type_to_string(__u8 cond) } } -char *zone_state_to_string(__u8 state) +static char *zone_state_to_string(__u8 state) { switch (state) { case NVME_ZNS_ZS_EMPTY: @@ -4270,13 +4530,82 @@ char *zone_state_to_string(__u8 state) } } +static void json_nvme_zns_report_zones(void *report, __u32 descs, + __u8 ext_size, __u32 report_size, __u64 nr_zones) { + struct json_object *root; + struct json_object *zone_list; + struct json_object *zone; + struct json_object *ext_data; + struct nvme_zone_report *r = report; + struct nvme_zns_desc *desc; + int i; + + root = json_create_object(); + zone_list = json_create_array(); + + + json_object_add_value_uint(root, "nr_zones", nr_zones); + + for (i = 0; i < descs; i++) { + desc = (struct nvme_zns_desc *) + (report + sizeof(*r) + i * (sizeof(*desc) + ext_size)); + zone = json_create_object(); + + json_object_add_value_uint(zone, "slba", le64_to_cpu(desc->zslba)); + json_object_add_value_uint(zone, "wp", le64_to_cpu(desc->wp)); + json_object_add_value_uint(zone, "cap", le64_to_cpu(desc->zcap)); + json_object_add_value_string(zone, "state", + zone_state_to_string(desc->zs >> 4)); + json_object_add_value_string(zone, "type", + zone_type_to_string(desc->zt)); + json_object_add_value_uint(zone, "attrs", desc->za); + json_object_add_value_uint(zone, "attrs", desc->zai); + + if (ext_size) { + if (desc->za & NVME_ZNS_ZA_ZDEV) { + ext_data = json_create_array(); + d_json((unsigned char *)desc + sizeof(*desc), + ext_size, 16, 1, ext_data); + json_object_add_value_array(zone, "ext_data", + ext_data); + } else { + json_object_add_value_string(zone, "ext_data", "Not valid"); + } + } + + json_array_add_value_object(zone_list, zone); + } + + json_object_add_value_array(root, "zone_list", zone_list); + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); +} + +static void nvme_show_zns_report_zone_attributes(__u8 za, __u8 zai) +{ + const char *const recommanded_limit[4] = {"","1","2","3"}; + printf("Attrs: Zone Descriptor Extension is %sVaild\n", + (za & NVME_ZNS_ZA_ZDEV)? "" : "Not "); + if(za & NVME_ZNS_ZA_RZR) { + printf(" Reset Zone Recommended with Reset Recommended Limit%s\n", + recommanded_limit[(zai&0xd)>>2]); + } + if (za & NVME_ZNS_ZA_FZR) { + printf(" Finish Zone Recommended with Finish Recommended Limit%s\n", + recommanded_limit[zai&0x3]); + } + if (za & NVME_ZNS_ZA_ZFC) { + printf(" Zone Finished by Controller\n"); + } +} + void nvme_show_zns_report_zones(void *report, __u32 descs, __u8 ext_size, __u32 report_size, unsigned long flags) { struct nvme_zone_report *r = report; struct nvme_zns_desc *desc; - int i; - + int i, verbose = flags & VERBOSE; __u64 nr_zones = le64_to_cpu(r->nr_zones); if (nr_zones < descs) @@ -4284,24 +4613,31 @@ void nvme_show_zns_report_zones(void *report, __u32 descs, if (flags & BINARY) return d_raw((unsigned char *)report, report_size); + else if (flags & JSON) + return json_nvme_zns_report_zones(report, descs, + ext_size, report_size, nr_zones); - printf("nr_zones: %"PRIu64"\n", (uint64_t)le64_to_cpu(r->nr_zones)); for (i = 0; i < descs; i++) { desc = (struct nvme_zns_desc *) (report + sizeof(*r) + i * (sizeof(*desc) + ext_size)); - printf("SLBA: 0x%-8"PRIx64" WP: 0x%-8"PRIx64" Cap: 0x%-8"PRIx64" State: %-12s Type: %-14s Attrs: 0x%-x\n", - (uint64_t)le64_to_cpu(desc->zslba), (uint64_t)le64_to_cpu(desc->wp), - (uint64_t)le64_to_cpu(desc->zcap), zone_state_to_string(desc->zs >> 4), - zone_type_to_string(desc->zt), desc->za); + if(verbose) { + printf("SLBA: %#-10"PRIx64" WP: %#-10"PRIx64" Cap: %#-10"PRIx64" State: %-12s Type: %-14s\n", + (uint64_t)le64_to_cpu(desc->zslba), (uint64_t)le64_to_cpu(desc->wp), + (uint64_t)le64_to_cpu(desc->zcap), zone_state_to_string(desc->zs >> 4), + zone_type_to_string(desc->zt)); + nvme_show_zns_report_zone_attributes(desc->za, desc->zai); + } + else { + printf("SLBA: %#-10"PRIx64" WP: %#-10"PRIx64" Cap: %#-10"PRIx64" State: %#-4x Type: %#-4x Attrs: %#-4x AttrsInfo: %#-4x\n", + (uint64_t)le64_to_cpu(desc->zslba), (uint64_t)le64_to_cpu(desc->wp), + (uint64_t)le64_to_cpu(desc->zcap), desc->zs, desc->zt, + desc->za, desc->zai); + } - if (ext_size) { + if (ext_size && (desc->za & NVME_ZNS_ZA_ZDEV)) { printf("Extension Data: "); - if (desc->za & NVME_ZNS_ZA_ZDEV) { - d((unsigned char *)desc + sizeof(*desc), ext_size, 16, 1); - printf("..\n"); - } else { - printf(" Not valid\n"); - } + d((unsigned char *)desc + sizeof(*desc), ext_size, 16, 1); + printf("..\n"); } } } @@ -4819,6 +5155,47 @@ void nvme_show_id_domain_list(struct nvme_id_domain_list *id_dom, } } +static void json_nvme_endurance_group_list(struct nvme_endurance_group_list *endgrp_list) +{ + struct json_object *root; + struct json_object *valid_attrs; + struct json_object *valid; + int i; + + root = json_create_object(); + valid = json_create_array(); + + json_object_add_value_uint(root, "num_endgrp_id", + le16_to_cpu(endgrp_list->num)); + + for (i = 0; i < min(le16_to_cpu(endgrp_list->num), 2047); i++) { + valid_attrs = json_create_object(); + json_object_add_value_uint(valid_attrs, "endgrp_id", + le16_to_cpu(endgrp_list->identifier[i])); + json_array_add_value_object(valid, valid_attrs); + } + + json_object_add_value_array(root, "endgrp_list", valid); + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); +} + +void nvme_show_endurance_group_list(struct nvme_endurance_group_list *endgrp_list, + enum nvme_print_flags flags) +{ + int i; + __u16 num = le16_to_cpu(endgrp_list->num); + + if (flags & JSON) + return json_nvme_endurance_group_list(endgrp_list); + + printf("num of endurance group ids: %u\n", num); + for (i = 0; i < min(num, 2047); i++) { + printf("[%4u]:%#x\n", i, le16_to_cpu(endgrp_list->identifier[i])); + } +} + static const char *nvme_trtype_to_string(__u8 trtype) { switch (trtype) { @@ -5039,6 +5416,101 @@ void nvme_show_effects_log(struct nvme_effects_log_page *effects, } } +const char *nvme_log_to_string(__u8 lid) +{ + switch (lid) { + case NVME_LOG_SUPPORTED_PAGES: return "Supported Log Pages"; + case NVME_LOG_ERROR: return "Error Information"; + case NVME_LOG_SMART: return "SMART Information"; + case NVME_LOG_FW_SLOT: return "Firmware Slot Information"; + case NVME_LOG_CHANGED_NS: return "Changed Namespace List"; + case NVME_LOG_CMD_EFFECTS: return "Commands Supported and Effects"; + case NVME_LOG_DEVICE_SELF_TEST: return "Device Self-test"; + case NVME_LOG_TELEMETRY_HOST: return "Telemetry Host-Initiated"; + case NVME_LOG_TELEMETRY_CTRL: return "Telemetry Controller-Initiated"; + case NVME_LOG_ENDURANCE_GROUP: return "Endurance Group Information"; + case NVME_LOG_PRELAT_PER_NVMSET: return "Predictable Latency Per NVM Set"; + case NVME_LOG_ANA: return "Asymmetric Namespace Access"; + case NVME_LOG_PRELAT_EVENT_AGG: return "Predictable Latency Event Aggregate"; + case NVME_LOG_PERSISTENT_EVENT: return "Persistent Event Log"; + case NVME_LOG_LBA_STATUS: return "LBA Status Information"; + case NVME_LOG_ENDURANCE_GROUP_EVENT_AGG: return "Endurance Group Event Aggregate"; + case NVME_LOG_BOOT_PARTITION: return "Boot Partition"; + case NVME_LOG_FID_SUPPORT_EFFECTS: return "FID Supported and Effects"; + case NVME_LOG_DISC: return "Discovery"; + case NVME_LOG_RESERVATION: return "Reservation Notification"; + case NVME_LOG_SANITIZE: return "Sanitize Status"; + case NVME_LOG_ZONE_CHANGED_LIST: return "Host Identifier"; + default: return "Unknown"; + } +} + +static void nvme_show_support_log_human(__u32 support, __u8 lid) +{ + const char *set = "supported"; + const char *clr = "not supported"; + + printf(" LSUPP is %s\n", (support & 0x1) ? set : clr); + printf(" IOS is %s\n", ((support >> 0x1) & 0x1) ? set : clr); + if (lid == NVME_LOG_PERSISTENT_EVENT) { + printf(" Establish Context and Read 512 Bytes of Header is %s\n", + ((support >> 0x16) & 0x1) ? set : clr); + } +} + +static void json_support_log(struct nvme_support_log_pages *support_log) +{ + struct json_object *root; + struct json_object *valid; + struct json_object *valid_attrs; + unsigned int lid; + char key[128]; + __u32 support; + + root = json_create_object(); + valid = json_create_object(); + + for (lid = 0; lid < 256; lid++) { + support = le32_to_cpu(support_log->lid_support[lid]); + if (support & 0x1) { + valid_attrs = json_create_object(); + sprintf(key, "lid_0x%x ", lid); + json_object_add_value_uint(valid_attrs, key, support); + json_array_add_value_object(valid, valid_attrs); + } + } + + json_object_add_value_object(root, "supported_logs", valid); + json_print_object(root, NULL); + printf("\n"); + json_free_object(root); +} + +void nvme_show_supported_log(struct nvme_support_log_pages *support_log, + const char *devname, enum nvme_print_flags flags) +{ + int lid, human = flags & VERBOSE; + __u32 support = 0; + + if (flags & BINARY) + return d_raw((unsigned char *)support_log, sizeof(*support_log)); + else if (flags & JSON) + return json_support_log(support_log); + + printf("Support Log Pages Deatils for %s:\n", devname); + for (lid = 0; lid < 256; lid++) { + support = le32_to_cpu(support_log->lid_support[lid]); + if (support & 0x1) { + printf("LID 0x%x (%s), supports 0x%x\n", lid, nvme_log_to_string(lid), + support); + if (human) + nvme_show_support_log_human(support, lid); + else + printf("\n"); + } + } +} + uint64_t int48_to_long(__u8 *data) { int i; @@ -5417,6 +5889,7 @@ const char *nvme_feature_to_string(enum nvme_feat feature) case NVME_FEAT_SANITIZE: return "Sanitize"; case NVME_MI_FEAT_CTRL_METADATA:return "MI Controller Metadata"; case NVME_MI_FEAT_NS_METADATA: return "MI Namespace Metadata"; + case NVME_FEAT_SPINUP_CONTROL: return "Spinup Control"; } /* * We don't use the "default:" statement to let the compiler warning if @@ -6079,6 +6552,7 @@ void nvme_feature_show_fields(enum nvme_feat fid, unsigned int result, break; case NVME_FEAT_ASYNC_EVENT: printf("\tZone Descriptor Changed Notices: %s\n", ((result >> 27) & 0x1) ? "Send async event":"Do not send async event"); + printf("\tDiscovery Log Page Change Notices: %s\n", ((result & 0x80000000) >> 31) ? "Send async event":"Do not send async event"); printf("\tEndurance Group Event Aggregate Log Change Notices: %s\n", ((result & 0x00004000) >> 14) ? "Send async event":"Do not send async event"); printf("\tLBA Status Information Notices : %s\n", ((result & 0x00002000) >> 13) ? "Send async event":"Do not send async event"); printf("\tPredictable Latency Event Aggregate Log Change Notices: %s\n", ((result & 0x00001000) >> 12) ? "Send async event":"Do not send async event"); @@ -6149,11 +6623,13 @@ void nvme_feature_show_fields(enum nvme_feat fid, unsigned int result, printf("\tNon-Operational Power State Permissive Mode Enable (NOPPME): %s\n", (result & 1) ? "True" : "False"); break; case NVME_FEAT_HOST_BEHAVIOR: - printf("\tHost Behavior Support: %s\n", (buf[0] & 0x1) ? "True" : "False"); + printf("\tHost Behavior Support Advanced Command Retry Enable (ACRE): %s\n", (buf[0] == 1) ? "True" : "False"); + printf("\tHost Behavior Support Extended Telemetry Data Area 4 Supported (ETDAS): %s\n", (buf[1] == 1) ? "True" : "False"); + printf("\tHost Behavior Support LBA Format Extension Enable (LBAFEE): %s\n", (buf[2] == 1) ? "True" : "False"); break; case NVME_FEAT_SANITIZE: - printf("\tNo-Deallocate Response Mode (NODRM) : %u\n", result & 0x1); - break; + printf("\tNo-Deallocate Response Mode (NODRM) : %u\n", result & 0x1); + break; case NVME_FEAT_RRL: printf("\tRead Recovery Level (RRL): %u\n", result & 0xf); break; @@ -6161,6 +6637,9 @@ void nvme_feature_show_fields(enum nvme_feat fid, unsigned int result, case NVME_MI_FEAT_NS_METADATA: nvme_show_mi_host_metadata(fid, (struct nvme_mi_host_metadata *)buf); break; + case NVME_FEAT_SPINUP_CONTROL: + printf("\tSpinup control feature Enabled: %s\n", (result & 1) ? "True" : "False"); + break; } } @@ -6270,6 +6749,10 @@ static void nvme_show_details_ns(struct nvme_namespace *n, bool ctrl) char usage[128]; char format[128]; + char generic[128]; + + int instance; + int head_instance; if (!n->ctrl) return; @@ -6279,7 +6762,10 @@ static void nvme_show_details_ns(struct nvme_namespace *n, bool ctrl) sprintf(format,"%3.0f %2sB + %2d B", (double)lba, l_suffix, le16_to_cpu(n->ns.lbaf[(n->ns.flbas & 0x0f)].ms)); - printf("%-12s %-8d %-26s %-16s ", n->name, n->nsid, usage, format); + sscanf(n->name, "nvme%dn%d", &instance, &head_instance); + sprintf(generic, "ng%dn%d", instance, head_instance); + + printf("%-12s %-16s %-8d %-26s %-16s ", n->name, generic, n->nsid, usage, format); if (ctrl) printf("%s", n->ctrl->name); @@ -6351,8 +6837,8 @@ static void nvme_show_detailed_list(struct nvme_topology *t) } printf("\nNVM Express Namespaces\n\n"); - printf("%-12s %-8s %-26s %-16s %-16s\n", "Device", "NSID", "Usage", "Format", "Controllers"); - printf("%-.12s %-.8s %-.26s %-.16s %-.16s\n", dash, dash, dash, dash, dash); + printf("%-12s %-12s %-8s %-26s %-16s %-16s\n", "Device", "Generic", "NSID", "Usage", "Format", "Controllers"); + printf("%-.12s %-.12s %-.8s %-.26s %-.16s %-.16s\n", dash, dash, dash, dash, dash, dash); for (i = 0; i < t->nr_subsystems; i++) { struct nvme_subsystem *s = &t->subsystems[i]; |