]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
Added a human-readable format option to id-ctrl and id-ns. This will
authorJon Derrick <jonathan.derrick@intel.com>
Tue, 12 May 2015 16:09:04 +0000 (10:09 -0600)
committerJon Derrick <jonathan.derrick@intel.com>
Tue, 12 May 2015 16:09:04 +0000 (10:09 -0600)
partially decode several relevant bitfields in the ID Controller and
Namespace commands. Reserved fields are displayed if not 0.

Signed-off-by: Jon Derrick <jonathan.derrick@intel.com>
Documentation/nvme-id-ctrl.1
Documentation/nvme-id-ctrl.txt
Documentation/nvme-id-ns.1
Documentation/nvme-id-ns.txt
nvme.c

index ac2151bafa40f4ff0984d439bac20020b28cca61..1b4ff52e374d7a72cec98b459618c79cb55190df 100644 (file)
@@ -1,13 +1,13 @@
 '\" t
 .\"     Title: nvme-id-ctrl
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.76.1 <http://docbook.sf.net/>
-.\"      Date: 02/02/2015
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\"      Date: 05/11/2015
 .\"    Manual: \ \&
 .\"    Source: \ \&
 .\"  Language: English
 .\"
-.TH "NVME\-ID\-CTRL" "1" "02/02/2015" "\ \&" "\ \&"
+.TH "NVME\-ID\-CTRL" "1" "05/11/2015" "\ \&" "\ \&"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -45,13 +45,18 @@ On success, the structure may be returned in one of several ways depending on th
 .PP
 \-b, \-\-raw\-binary
 .RS 4
-Print the raw buffer to stdout\&. Structure is not parsed by program\&. This overrides the vendor specific option\&.
+Print the raw buffer to stdout\&. Structure is not parsed by program\&. This overrides the vendor specific and human readable options\&.
 .RE
 .PP
 \-v, \-\-vendor\-specific
 .RS 4
 In addition to parsing known fields, this option will dump the vendor specific region of the structure in hex with ascii interpretation\&.
 .RE
+.PP
+\-H, \-\-human\-readable
+.RS 4
+This option will parse and format many of the bitfields into human\-readable formats\&.
+.RE
 .SH "EXAMPLES"
 .sp
 .RS 4
index ecde3e4f75e5a58f6020d71b705ab6df70835262..89b5a768c49436316dea6a84fa9ab2823b0bd86a 100644 (file)
@@ -27,7 +27,7 @@ OPTIONS
 -b::
 --raw-binary::
        Print the raw buffer to stdout. Structure is not parsed by
-       program. This overrides the vendor specific option.
+       program. This overrides the vendor specific and human readable options.
 
 -v::
 --vendor-specific::
@@ -35,6 +35,12 @@ OPTIONS
        the vendor specific region of the structure in hex with ascii
        interpretation.
 
+-H::
+--human-readable::
+       This option will parse and format many of the bitfields
+       into human-readable formats.
+
+
 EXAMPLES
 --------
 * Has the program interpret the returned buffer and display the known
index f347024bf715135994b9f20b49a0a29942840bd3..f9b6a4fb85629062e862b999e16b37bdffd1caef 100644 (file)
@@ -1,13 +1,13 @@
 '\" t
 .\"     Title: nvme-id-ns
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.76.1 <http://docbook.sf.net/>
-.\"      Date: 02/02/2015
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\"      Date: 05/11/2015
 .\"    Manual: \ \&
 .\"    Source: \ \&
 .\"  Language: English
 .\"
-.TH "NVME\-ID\-NS" "1" "02/02/2015" "\ \&" "\ \&"
+.TH "NVME\-ID\-NS" "1" "05/11/2015" "\ \&" "\ \&"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -51,13 +51,18 @@ Retrieve the identify namespace structure for the given nsid\&. This is required
 .PP
 \-b, \-\-raw\-binary
 .RS 4
-Print the raw buffer to stdout\&. Structure is not parsed by program\&. This overrides the vendor specific option\&.
+Print the raw buffer to stdout\&. Structure is not parsed by program\&. This overrides the vendor specific and human readable options\&.
 .RE
 .PP
 \-v, \-\-vendor\-specific
 .RS 4
 In addition to parsing known fields, this option will dump the vendor specific region of the structure in hex with ascii interpretation\&.
 .RE
+.PP
+\-H, \-\-human\-readable
+.RS 4
+This option will parse and format many of the bitfields into human\-readable formats\&.
+.RE
 .SH "EXAMPLES"
 .sp
 .RS 4
index aa65d4c2b8f27bbd5d6eeb4bb127272dbd6020bd..6d27ec26c435076113f196e07ec501a608798d53 100644 (file)
@@ -38,7 +38,7 @@ OPTIONS
 -b::
 --raw-binary::
        Print the raw buffer to stdout. Structure is not parsed by
-       program. This overrides the vendor specific option.
+       program. This overrides the vendor specific and human readable options.
 
 -v::
 --vendor-specific::
@@ -46,6 +46,12 @@ OPTIONS
        the vendor specific region of the structure in hex with ascii
        interpretation.
 
+-H::
+--human-readable::
+       This option will parse and format many of the bitfields
+       into human-readable formats.
+
+
 EXAMPLES
 --------
 * Has the program interpret the returned buffer and display the known
diff --git a/nvme.c b/nvme.c
index cfedcd5c566db7f9cf9a853f59a652361431d6ff..c4bb36957883041aab108653ca28d033daa556a1 100644 (file)
--- a/nvme.c
+++ b/nvme.c
@@ -182,7 +182,7 @@ static void show_nvme_resv_report(struct nvme_reservation_status *status)
 
        regctl = status->regctl[0] | (status->regctl[1] << 8);
 
-       printf("\nNVME Reservatation status:\n\n");
+       printf("\nNVME Reservation status:\n\n");
        printf("gen       : %d\n", le32toh(status->gen));
        printf("regctl    : %d\n", regctl);
        printf("rtype     : %d\n", status->rtype);
@@ -397,7 +397,244 @@ static void d(unsigned char *buf, int len, int width, int group)
        fprintf(stdout, "\n");
 }
 
-static void show_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, int vs)
+static void show_nvme_id_ctrl_cmic(__u8 cmic)
+{
+       __u8 rsvd = (cmic & 0xF8) >> 3;
+       __u8 sriov = (cmic & 0x4) >> 2;
+       __u8 mctl = (cmic & 0x2) >> 1;
+       __u8 mp = cmic & 0x1;
+       if (rsvd)
+               printf("  [7:3] : %#x\tReserved\n", rsvd);
+       printf("  [2:2] : %#x\t%s\n", sriov, sriov ? "SR-IOV" : "PCI");
+       printf("  [1:1] : %#x\t%s Controller\n",
+               mctl, mctl ? "Multi" : "Single");
+       printf("  [0:0] : %#x\t%s Port\n", mp, mp ? "Multi" : "Single");
+       printf("\n");
+}
+
+static void show_nvme_id_ctrl_oaes(__le32 oaes)
+{
+       __le32 rsvd0 = (oaes & 0xFFFFFE00) >> 9;
+       __le32 nace = (oaes & 0x100) >> 8;
+       __le32 rsvd1 = oaes & 0xFF;
+       if (rsvd0)
+               printf(" [31:9] : %#x\tReserved\n", rsvd0);
+       printf("  [8:8] : %#x\tNamespace Attribute Changed Event %sSupported\n",
+               nace, nace ? "" : "Not ");
+       if (rsvd1)
+               printf("  [7:0] : %#x\tReserved\n", rsvd1);
+       printf("\n");
+}
+
+static void show_nvme_id_ctrl_oacs(__le16 oacs)
+{
+       __le16 rsvd = (oacs & 0xFFF0) >> 4;
+       __le16 nsm = (oacs & 0x8) >> 3;
+       __le16 fwc = (oacs & 0x4) >> 2;
+       __le16 fmt = (oacs & 0x2) >> 1;
+       __le16 sec = oacs & 0x1;
+       if (rsvd)
+               printf(" [15:4] : %#x\tReserved\n", rsvd);
+       printf("  [3:3] : %#x\tNS Management and Attachment %sSupported\n",
+               nsm, nsm ? "" : "Not ");
+       printf("  [2:2] : %#x\tFW Commit and Download %sSupported\n",
+               fwc, fwc ? "" : "Not ");
+       printf("  [1:1] : %#x\tFormat NVM %sSupported\n",
+               fmt, fmt ? "" : "Not ");
+       printf("  [0:0] : %#x\tSec. Send and Receive %sSupported\n",
+               sec, sec ? "" : "Not ");
+       printf("\n");
+}
+
+static void show_nvme_id_ctrl_frmw(__u8 frmw)
+{
+       __u8 rsvd = (frmw & 0xE0) >> 5;
+       __u8 fawr = (frmw & 0x10) >> 4;
+       __u8 nfws = (frmw & 0xE) >> 1;
+       __u8 s1ro = frmw & 0x1;
+       if (rsvd)
+               printf("  [7:5] : %#x\tReserved\n", rsvd);
+       printf("  [4:4] : %#x\tFirmware Activate Without Reset %sSupported\n",
+               fawr, fawr ? "" : "Not ");
+       printf("  [3:1] : %#x\tNumber of Firmware Slots\n", nfws);
+       printf("  [0:0] : %#x\tFirmware Slot 1 Read%s\n",
+               s1ro, s1ro ? "-Only" : "/Write");
+       printf("\n");
+}
+
+static void show_nvme_id_ctrl_lpa(__u8 lpa)
+{
+       __u8 rsvd = (lpa & 0xFC) >> 2;
+       __u8 celp = (lpa & 0x2) >> 1;
+       __u8 smlp = lpa & 0x1;
+       if (rsvd)
+               printf("  [7:2] : %#x\tReserved\n", rsvd);
+       printf("  [1:1] : %#x\tCommand Effects Log Page %sSupported\n",
+               celp, celp ? "" : "Not ");
+       printf("  [0:0] : %#x\tSMART/Health Log Page per NS %sSupported\n",
+               smlp, smlp ? "" : "Not ");
+       printf("\n");
+}
+
+static void show_nvme_id_ctrl_avscc(__u8 avscc)
+{
+       __u8 rsvd = (avscc & 0xFE) >> 1;
+       __u8 fmt = avscc & 0x1;
+       if (rsvd)
+               printf("  [7:1] : %#x\tReserved\n", rsvd);
+       printf("  [0:0] : %#x\tAdmin Vendor Specific Commands uses %s Format\n",
+               fmt, fmt ? "NVMe" : "Vendor Specific");
+       printf("\n");
+}
+
+static void show_nvme_id_ctrl_apsta(__u8 apsta)
+{
+       __u8 rsvd = (apsta & 0xFE) >> 1;
+       __u8 apst = apsta & 0x1;
+       if (rsvd)
+               printf("  [7:1] : %#x\tReserved\n", rsvd);
+       printf("  [0:0] : %#x\tAutonomous Power State Transitions %sSupported\n",
+               apst, apst ? "" : "Not ");
+       printf("\n");
+}
+
+static void show_nvme_id_ctrl_rpmbs(__le32 rpmbs)
+{
+       __le32 asz = (rpmbs & 0xFF000000) >> 24;
+       __le32 tsz = (rpmbs & 0xFF0000) >> 16;
+       __le32 rsvd = (rpmbs & 0xFFC0) >> 6;
+       __le32 auth = (rpmbs & 0x38) >> 3;
+       __le32 rpmb = rpmbs & 0x3;
+       printf(" [31:24]: %#x\tAccess Size\n", asz);
+       printf(" [23:16]: %#x\tTotal Size\n", tsz);
+       if (rsvd)
+               printf(" [15:6] : %#x\tReserved\n", rsvd);
+       printf("  [5:3] : %#x\tAuthentication Method\n", auth);
+       printf("  [2:0] : %#x\tNumber of RPMB Units\n", rpmb);
+       printf("\n");
+}
+
+static void show_nvme_id_ctrl_sqes(__u8 sqes)
+{
+       __u8 msqes = (sqes & 0xF0) >> 4;
+       __u8 rsqes = sqes & 0xF;
+       printf("  [7:4] : %#x\tMax SQ Entry Size (%d)\n", msqes, 1 << msqes);
+       printf("  [3:0] : %#x\tMin SQ Entry Size (%d)\n", rsqes, 1 << rsqes);
+       printf("\n");
+}
+
+static void show_nvme_id_ctrl_cqes(__u8 cqes)
+{
+       __u8 mcqes = (cqes & 0xF0) >> 4;
+       __u8 rcqes = cqes & 0xF;
+       printf("  [7:4] : %#x\tMax CQ Entry Size (%d)\n", mcqes, 1 << mcqes);
+       printf("  [3:0] : %#x\tMin CQ Entry Size (%d)\n", rcqes, 1 << rcqes);
+       printf("\n");
+}
+
+static void show_nvme_id_ctrl_oncs(__le16 oncs)
+{
+       __le16 rsvd = (oncs & 0xFFC0) >> 6;
+       __le16 resv = (oncs & 0x20) >> 5;
+       __le16 save = (oncs & 0x10) >> 4;
+       __le16 wzro = (oncs & 0x8) >> 3;
+       __le16 dsms = (oncs & 0x4) >> 2;
+       __le16 wunc = (oncs & 0x2) >> 1;
+       __le16 cmp = oncs & 0x1;
+       if (rsvd)
+               printf(" [15:6] : %#x\tReserved\n", rsvd);
+       printf("  [5:5] : %#x\tReservations %sSupported\n",
+               resv, resv ? "" : "Not ");
+       printf("  [4:4] : %#x\tSave and Select %sSupported\n",
+               save, save ? "" : "Not ");
+       printf("  [3:3] : %#x\tWrite Zeroes %sSupported\n",
+               wzro, wzro ? "" : "Not ");
+       printf("  [2:2] : %#x\tData Set Management %sSupported\n",
+               dsms, dsms ? "" : "Not ");
+       printf("  [1:1] : %#x\tWrite Uncorrectable %sSupported\n",
+               wunc, wunc ? "" : "Not ");
+       printf("  [0:0] : %#x\tCompare %sSupported\n",
+               cmp, cmp ? "" : "Not ");
+       printf("\n");
+}
+
+static void show_nvme_id_ctrl_fuses(__le16 fuses)
+{
+       __le16 rsvd = (fuses & 0xFE) >> 1;
+       __le16 cmpw = fuses & 0x1;
+       if (rsvd)
+               printf(" [15:1] : %#x\tReserved\n", rsvd);
+       printf("  [0:0] : %#x\tFused Compare and Write %sSupported\n",
+               cmpw, cmpw ? "" : "Not ");
+       printf("\n");
+}
+
+static void show_nvme_id_ctrl_fna(__u8 fna)
+{
+       __u8 rsvd = (fna & 0xF8) >> 3;
+       __u8 cese = (fna & 0x4) >> 2;
+       __u8 cens = (fna & 0x2) >> 1;
+       __u8 fmns = fna & 0x1;
+       if (rsvd)
+               printf("  [7:3] : %#x\tReserved\n", rsvd);
+       printf("  [2:2] : %#x\tCrypto Erase %sSupported as part of Secure Erase\n",
+               cese, cese ? "" : "Not ");
+       printf("  [1:1] : %#x\tCrypto Erase Applies to %s Namespace(s)\n",
+               cens, cens ? "All" : "Single");
+       printf("  [0:0] : %#x\tFormat Applies to %s Namespace(s)\n",
+               fmns, fmns ? "All" : "Single");
+       printf("\n");
+}
+
+static void show_nvme_id_ctrl_vwc(__u8 vwc)
+{
+       __u8 rsvd = (vwc & 0xFE) >> 1;
+       __u8 vwcp = vwc & 0x1;
+       if (rsvd)
+               printf("  [7:3] : %#x\tReserved\n", rsvd);
+       printf("  [0:0] : %#x\tVolatile Write Cache %sPresent\n",
+               vwcp, vwcp ? "" : "Not ");
+       printf("\n");
+}
+
+static void show_nvme_id_ctrl_nvscc(__u8 nvscc)
+{
+       __u8 rsvd = (nvscc & 0xFE) >> 1;
+       __u8 fmt = nvscc & 0x1;
+       if (rsvd)
+               printf("  [7:1] : %#x\tReserved\n", rsvd);
+       printf("  [0:0] : %#x\tNVM Vendor Specific Commands uses %s Format\n",
+               fmt, fmt ? "NVMe" : "Vendor Specific");
+       printf("\n");
+}
+
+static void show_nvme_id_ctrl_sgls(__le32 sgls)
+{
+       __le32 rsvd0 = (sgls & 0xFFF80000) >> 19;
+       __le32 sglltb = (sgls & 0x40000) >> 18;
+       __le32 bacmdb = (sgls & 0x20000) >> 17;
+       __le32 bbs = (sgls & 0x10000) >> 16;
+       __le32 rsvd1 = (sgls & 0xFFFE) >> 1;
+       __le32 sglsp = sgls & 0x1;
+       if (rsvd0)
+               printf(" [31:19]: %#x\tReserved\n", rsvd0);
+       if (sglsp || (!sglsp && sglltb))
+               printf(" [18:18]: %#x\tSGL Length Larger than Buffer %sSupported\n",
+                       sglltb, sglltb ? "" : "Not ");
+       if (sglsp || (!sglsp && bacmdb))
+               printf(" [17:17]: %#x\tByte-Aligned Contig. MD Buffer %sSupported\n",
+                       bacmdb, bacmdb ? "" : "Not ");
+       if (sglsp || (!sglsp && bbs))
+               printf(" [16:16]: %#x\tSGL Bit-Bucket %sSupported\n",
+                       bbs, bbs ? "" : "Not ");
+       if (rsvd1)
+               printf(" [15:1] : %#x\tReserved\n", rsvd1);
+       printf("  [0:0] : %#x\tScatter-Gather Lists %sSupported\n",
+               sglsp, sglsp ? "" : "Not ");
+       printf("\n");
+}
+
+static void show_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, int vs, int human)
 {
        int i;
        char sn[sizeof(ctrl->sn) + 1];
@@ -422,20 +659,35 @@ static void show_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, int vs)
        printf("ieee    : %02x%02x%02x\n",
                ctrl->ieee[0], ctrl->ieee[1], ctrl->ieee[2]);
        printf("cmic    : %#x\n", ctrl->cmic);
+       if (human)
+               show_nvme_id_ctrl_cmic(ctrl->cmic);
        printf("mdts    : %d\n", ctrl->mdts);
        printf("cntlid  : %x\n", ctrl->cntlid);
        printf("ver     : %x\n", ctrl->ver);
        printf("rtd3r   : %x\n", ctrl->rtd3r);
        printf("rtd3e   : %x\n", ctrl->rtd3e);
+       printf("oaes    : %#x\n", ctrl->oaes);
+       if (human)
+               show_nvme_id_ctrl_oaes(ctrl->oaes);
        printf("oacs    : %#x\n", ctrl->oacs);
+       if (human)
+               show_nvme_id_ctrl_oacs(ctrl->oacs);
        printf("acl     : %d\n", ctrl->acl);
        printf("aerl    : %d\n", ctrl->aerl);
        printf("frmw    : %#x\n", ctrl->frmw);
+       if (human)
+               show_nvme_id_ctrl_frmw(ctrl->frmw);
        printf("lpa     : %#x\n", ctrl->lpa);
+       if (human)
+               show_nvme_id_ctrl_lpa(ctrl->lpa);
        printf("elpe    : %d\n", ctrl->elpe);
        printf("npss    : %d\n", ctrl->npss);
        printf("avscc   : %#x\n", ctrl->avscc);
+       if (human)
+               show_nvme_id_ctrl_avscc(ctrl->avscc);
        printf("apsta   : %#x\n", ctrl->apsta);
+       if (human)
+               show_nvme_id_ctrl_apsta(ctrl->apsta);
        printf("wctemp  : %d\n", ctrl->wctemp);
        printf("cctemp  : %d\n", ctrl->cctemp);
        printf("mtfa    : %d\n", ctrl->mtfa);
@@ -443,18 +695,36 @@ static void show_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, int vs)
        printf("tnvmcap : %.0Lf\n", int128_to_double(ctrl->tnvmcap));
        printf("unvmcap : %.0Lf\n", int128_to_double(ctrl->unvmcap));
        printf("rpmbs   : %#x\n", ctrl->rpmbs);
+       if (human)
+               show_nvme_id_ctrl_rpmbs(ctrl->rpmbs);
        printf("sqes    : %#x\n", ctrl->sqes);
+       if (human)
+               show_nvme_id_ctrl_sqes(ctrl->sqes);
        printf("cqes    : %#x\n", ctrl->cqes);
+       if (human)
+               show_nvme_id_ctrl_cqes(ctrl->cqes);
        printf("nn      : %d\n", ctrl->nn);
        printf("oncs    : %#x\n", ctrl->oncs);
+       if (human)
+               show_nvme_id_ctrl_oncs(ctrl->oncs);
        printf("fuses   : %#x\n", ctrl->fuses);
+       if (human)
+               show_nvme_id_ctrl_fuses(ctrl->fuses);
        printf("fna     : %#x\n", ctrl->fna);
+       if (human)
+               show_nvme_id_ctrl_fna(ctrl->fna);
        printf("vwc     : %#x\n", ctrl->vwc);
+       if (human)
+               show_nvme_id_ctrl_vwc(ctrl->vwc);
        printf("awun    : %d\n", ctrl->awun);
        printf("awupf   : %d\n", ctrl->awupf);
        printf("nvscc   : %d\n", ctrl->nvscc);
+       if (human)
+               show_nvme_id_ctrl_nvscc(ctrl->nvscc);
        printf("acwu    : %d\n", ctrl->acwu);
        printf("sgls    : %d\n", ctrl->sgls);
+       if (human)
+               show_nvme_id_ctrl_sgls(ctrl->sgls);
 
        for (i = 0; i <= ctrl->npss; i++) {
                printf("ps %4d : mp:%d flags:%x enlat:%d exlat:%d rrt:%d rrl:%d\n"
@@ -472,6 +742,7 @@ static void show_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, int vs)
        }
 }
 
+
 static void show_lba_range(struct nvme_lba_range_type *lbrt, int nr_ranges)
 {
        int i, j;
@@ -488,7 +759,143 @@ static void show_lba_range(struct nvme_lba_range_type *lbrt, int nr_ranges)
        }
 }
 
-static void show_nvme_id_ns(struct nvme_id_ns *ns, int id, int vs)
+static void show_nvme_id_ns_nsfeat(__u8 nsfeat)
+{
+       __u8 rsvd = (nsfeat & 0xF8) >> 3;
+       __u8 dulbe = (nsfeat & 0x4) >> 2;
+       __u8 na = (nsfeat & 0x2) >> 1;
+       __u8 thin = nsfeat & 0x1;
+       if (rsvd)
+               printf("  [7:3] : %#x\tReserved\n", rsvd);
+       printf("  [2:2] : %#x\tDeallocated or Unwritten Logical Block error %sSupported\n",
+               dulbe, dulbe ? "" : "Not ");
+       printf("  [1:1] : %#x\tNamespace uses %s\n",
+               na, na ? "NAWUN, NAWUPF, and NACWU" : "AWUN, AWUPF, and ACWU");
+       printf("  [0:0] : %#x\tThin Provisioning %sSupported\n",
+               thin, thin ? "" : "Not ");
+       printf("\n");
+}
+
+static void show_nvme_id_ns_flbas(__u8 flbas)
+{
+       __u8 rsvd = (flbas & 0xE0) >> 5;
+       __u8 mdedata = (flbas & 0x10) >> 4;
+       __u8 lbaf = flbas & 0xF;
+       if (rsvd)
+               printf("  [7:5] : %#x\tReserved\n", rsvd);
+       printf("  [4:4] : %#x\tMetadata Transferred %s\n",
+               mdedata, mdedata ? "at End of Data LBA" : "in Separate Contiguous Buffer");
+       printf("  [3:0] : %#x\tCurrent LBA Format Selected\n", lbaf);
+       printf("\n");
+}
+
+static void show_nvme_id_ns_mc(__u8 mc)
+{
+       __u8 rsvd = (mc & 0xFC) >> 2;
+       __u8 mdp = (mc & 0x2) >> 1;
+       __u8 extdlba = mc & 0x1;
+       if (rsvd)
+               printf("  [7:2] : %#x\tReserved\n", rsvd);
+       printf("  [1:1] : %#x\tMetadata Pointer %sSupported\n",
+               mdp, mdp ? "" : "Not ");
+       printf("  [0:0] : %#x\tMetadata as Part of Extended Data LBA %sSupported\n",
+               extdlba, extdlba ? "" : "Not ");
+       printf("\n");
+}
+
+static void show_nvme_id_ns_dpc(__u8 dpc)
+{
+       __u8 rsvd = (dpc & 0xE0) >> 5;
+       __u8 pil8 = (dpc & 0x10) >> 4;
+       __u8 pif8 = (dpc & 0x8) >> 3;
+       __u8 pit3 = (dpc & 0x4) >> 2;
+       __u8 pit2 = (dpc & 0x2) >> 1;
+       __u8 pit1 = dpc & 0x1;
+       if (rsvd)
+               printf("  [7:5] : %#x\tReserved\n", rsvd);
+       printf("  [4:4] : %#x\tProtection Information Transferred as Last 8 Bytes of Metadata %sSupported\n",
+               pil8, pil8 ? "" : "Not ");
+       printf("  [3:3] : %#x\tProtection Information Transferred as First 8 Bytes of Metadata %sSupported\n",
+               pif8, pif8 ? "" : "Not ");
+       printf("  [2:2] : %#x\tProtection Information Type 3 %sSupported\n",
+               pit3, pit3 ? "" : "Not ");
+       printf("  [1:1] : %#x\tProtection Information Type 2 %sSupported\n",
+               pit2, pit2 ? "" : "Not ");
+       printf("  [0:0] : %#x\tProtection Information Type 1 %sSupported\n",
+               pit1, pit1 ? "" : "Not ");
+       printf("\n");
+}
+
+static void show_nvme_id_ns_dps(__u8 dps)
+{
+       __u8 rsvd = (dps & 0xF0) >> 4;
+       __u8 pif8 = (dps & 0x8) >> 3;
+       __u8 pit = dps & 0x7;
+       if (rsvd)
+               printf("  [7:4] : %#x\tReserved\n", rsvd);
+       printf("  [3:3] : %#x\tProtection Information is Transferred as %s 8 Bytes of Metadata\n",
+               pif8, pif8 ? "First" : "Last");
+       printf("  [2:0] : %#x\tProtection Information %s\n", pit,
+               pit == 3 ? "Type 3 Enabled" :
+               pit == 2 ? "Type 2 Enabled" :
+               pit == 1 ? "Type 1 Enabled" :
+               pit == 0 ? "Disabled" : "Reserved Enabled");
+       printf("\n");
+}
+
+static void show_nvme_id_ns_nmic(__u8 nmic)
+{
+       __u8 rsvd = (nmic & 0xFE) >> 1;
+       __u8 mp = nmic & 0x1;
+       if (rsvd)
+               printf("  [7:1] : %#x\tReserved\n", rsvd);
+       printf("  [0:0] : %#x\tNamespace Multipath %sCapable\n",
+               mp, mp ? "" : "Not ");
+       printf("\n");
+}
+
+static void show_nvme_id_ns_rescap(__u8 rescap)
+{
+       __u8 rsvd = (rescap & 0x80) >> 7;
+       __u8 eaar = (rescap & 0x40) >> 6;
+       __u8 wear = (rescap & 0x20) >> 5;
+       __u8 earo = (rescap & 0x10) >> 4;
+       __u8 wero = (rescap & 0x8) >> 3;
+       __u8 ea = (rescap & 0x4) >> 2;
+       __u8 we = (rescap & 0x2) >> 1;
+       __u8 ptpl = rescap & 0x1;
+       if (rsvd)
+               printf("  [7:7] : %#x\tReserved\n", rsvd);
+       printf("  [6:6] : %#x\tExclusive Access - All Registrants %sSupported\n",
+               eaar, eaar ? "" : "Not ");
+       printf("  [5:5] : %#x\tWrite Exclusive - All Registrants %sSupported\n",
+               wear, wear ? "" : "Not ");
+       printf("  [4:4] : %#x\tExclusive Access - Registrants Only %sSupported\n",
+               earo, earo ? "" : "Not ");
+       printf("  [3:3] : %#x\tWrite Exclusive - Registrants Only %sSupported\n",
+               wero, wero ? "" : "Not ");
+       printf("  [2:2] : %#x\tExclusive Access %sSupported\n",
+               ea, ea ? "" : "Not ");
+       printf("  [1:1] : %#x\tWrite Exclusive %sSupported\n",
+               we, we ? "" : "Not ");
+       printf("  [0:0] : %#x\tPersist Through Power Loss %sSupported\n",
+               ptpl, ptpl ? "" : "Not ");
+       printf("\n");
+}
+
+static void show_nvme_id_ns_fpi(__u8 fpi)
+{
+       __u8 fpis = (fpi & 0x80) >> 7;
+       __u8 fpii = fpi & 0x7F;
+       printf("  [7:7] : %#x\tFormat Progress Indicator %sSupported\n",
+               fpis, fpis ? "" : "Not ");
+       if (fpis || (!fpis && fpii))
+       printf("  [6:0] : %#x\tFormat Progress Indicator (Remaining %d%%)\n",
+               fpii, 100 - fpii);
+       printf("\n");
+}
+
+static void show_nvme_id_ns(struct nvme_id_ns *ns, int id, int vs, int human)
 {
        int i;
 
@@ -497,14 +904,30 @@ static void show_nvme_id_ns(struct nvme_id_ns *ns, int id, int vs)
        printf("ncap    : %#llx\n", ns->ncap);
        printf("nuse    : %#llx\n", ns->nuse);
        printf("nsfeat  : %#x\n", ns->nsfeat);
+       if (human)
+               show_nvme_id_ns_nsfeat(ns->nsfeat);
        printf("nlbaf   : %d\n", ns->nlbaf);
        printf("flbas   : %#x\n", ns->flbas);
+       if (human)
+               show_nvme_id_ns_flbas(ns->flbas);
        printf("mc      : %#x\n", ns->mc);
+       if (human)
+               show_nvme_id_ns_mc(ns->mc);
        printf("dpc     : %#x\n", ns->dpc);
+       if (human)
+               show_nvme_id_ns_dpc(ns->dpc);
        printf("dps     : %#x\n", ns->dps);
+       if (human)
+               show_nvme_id_ns_dps(ns->dps);
        printf("nmic    : %#x\n", ns->nmic);
+       if (human)
+               show_nvme_id_ns_nmic(ns->nmic);
        printf("rescap  : %#x\n", ns->rescap);
+       if (human)
+               show_nvme_id_ns_rescap(ns->rescap);
        printf("fpi     : %#x\n", ns->fpi);
+       if (human)
+               show_nvme_id_ns_fpi(ns->fpi);
        printf("nawun   : %d\n", ns->nawun);
        printf("nawupf  : %d\n", ns->nawupf);
        printf("nacwu   : %d\n", ns->nacwu);
@@ -524,9 +947,18 @@ static void show_nvme_id_ns(struct nvme_id_ns *ns, int id, int vs)
        printf("\n");
 
        for (i = 0; i <= ns->nlbaf; i++) {
-               printf("lbaf %2d : ms:%-3d ds:%-2d rp:%#x %s\n", i,
-                       ns->lbaf[i].ms, ns->lbaf[i].ds, ns->lbaf[i].rp,
-                       i == (ns->flbas & 0xf) ? "(in use)" : "");
+               if (human)
+                       printf("LBA Format %2d : Metadata Size: %-3d bytes - "
+                               "Data Size: %-2d bytes - Relative Performance: %#x %s %s\n", i,
+                               ns->lbaf[i].ms, 1 << ns->lbaf[i].ds, ns->lbaf[i].rp,
+                               ns->lbaf[i].rp == 3 ? "Degraded" :
+                               ns->lbaf[i].rp == 2 ? "Good" :
+                               ns->lbaf[i].rp == 1 ? "Better" : "Best",
+                               i == (ns->flbas & 0xf) ? "(in use)" : "");
+               else
+                       printf("lbaf %2d : ms:%-3d ds:%-2d rp:%#x %s\n", i,
+                               ns->lbaf[i].ms, ns->lbaf[i].ds, ns->lbaf[i].rp,
+                               i == (ns->flbas & 0xf) ? "(in use)" : "");
        }
        if (vs) {
                printf("vs[]:");
@@ -934,6 +1366,7 @@ static int id_ctrl(int argc, char **argv)
        struct config {
                __u8  vendor_specific;
                __u8  raw_binary;
+               __u8  human_readable;
        };
        struct config cfg;
 
@@ -945,6 +1378,8 @@ static int id_ctrl(int argc, char **argv)
                {"v",               "", CFG_NONE, &defaults.vendor_specific, no_argument,       NULL},
                {"raw-binary",      "", CFG_NONE, &defaults.raw_binary,      no_argument,       NULL},
                {"b",               "", CFG_NONE, &defaults.raw_binary,      no_argument,       NULL},
+               {"human-readable",  "", CFG_NONE, &defaults.human_readable,  no_argument,       NULL},
+               {"H",               "", CFG_NONE, &defaults.human_readable,  no_argument,       NULL},
                {0}
        };
        argconfig_parse(argc, argv, "id_ctrl", command_line_options,
@@ -956,7 +1391,7 @@ static int id_ctrl(int argc, char **argv)
                if (cfg.raw_binary)
                        d_raw((unsigned char *)&ctrl, sizeof(ctrl));
                else
-                       show_nvme_id_ctrl(&ctrl, cfg.vendor_specific);
+                       show_nvme_id_ctrl(&ctrl, cfg.vendor_specific, cfg.human_readable);
        }
        else if (err > 0)
                fprintf(stderr, "NVMe Status: %s\n", nvme_status_to_string(err));
@@ -973,6 +1408,7 @@ static int id_ns(int argc, char **argv)
                __u32 namespace_id;
                __u8  vendor_specific;
                __u8  raw_binary;
+               __u8  human_readable;
        };
        struct config cfg;
 
@@ -987,6 +1423,8 @@ static int id_ns(int argc, char **argv)
                {"v",               "",     CFG_NONE,     &defaults.vendor_specific, no_argument,       NULL},
                {"raw-binary",      "",     CFG_NONE,     &defaults.raw_binary,      no_argument,       NULL},
                {"b",               "",     CFG_NONE,     &defaults.raw_binary,      no_argument,       NULL},
+               {"human-readable",  "", CFG_NONE, &defaults.human_readable,  no_argument,       NULL},
+               {"H",               "", CFG_NONE, &defaults.human_readable,  no_argument,       NULL},
                {0}
        };
        argconfig_parse(argc, argv, "id_ns", command_line_options,
@@ -1011,7 +1449,7 @@ static int id_ns(int argc, char **argv)
                if (cfg.raw_binary)
                        d_raw((unsigned char *)&ns, sizeof(ns));
                else
-                       show_nvme_id_ns(&ns, cfg.namespace_id, cfg.vendor_specific);
+                       show_nvme_id_ns(&ns, cfg.namespace_id, cfg.vendor_specific, cfg.human_readable);
        }
        else if (err > 0)
                fprintf(stderr, "NVMe Status: %s NSID:%d\n", nvme_status_to_string(err),
@@ -2246,7 +2684,7 @@ static int nvme_passthru(int argc, char **argv, int ioctl_cmd)
        };
 
        memset(&cmd, 0, sizeof(cmd));
-       argconfig_parse(argc, argv, "nvme_passthrou", command_line_options,
+       argconfig_parse(argc, argv, "nvme_passthru", command_line_options,
                        &defaults, &cfg, sizeof(cfg));
 
        cmd.cdw2         = cfg.cdw2;