summaryrefslogtreecommitdiffstats
path: root/nvme-print.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2021-11-20 07:04:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2021-11-20 07:04:39 +0000
commitb8210b1af6dd369a577b2ea2c2fa0f25bffaa3f4 (patch)
tree0f8475e9ba10b301bd87788e60d1759e8855e414 /nvme-print.c
parentReleasing debian version 1.15-4. (diff)
downloadnvme-cli-b8210b1af6dd369a577b2ea2c2fa0f25bffaa3f4.tar.xz
nvme-cli-b8210b1af6dd369a577b2ea2c2fa0f25bffaa3f4.zip
Merging upstream version 1.16.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rwxr-xr-xnvme-print.c548
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];