summaryrefslogtreecommitdiffstats
path: root/nvme-print.c
diff options
context:
space:
mode:
Diffstat (limited to 'nvme-print.c')
-rwxr-xr-xnvme-print.c642
1 files changed, 536 insertions, 106 deletions
diff --git a/nvme-print.c b/nvme-print.c
index b01a842..1d2fb0c 100755
--- a/nvme-print.c
+++ b/nvme-print.c
@@ -11,6 +11,13 @@
#include "util/suffix.h"
#include "common.h"
+#define ABSOLUTE_ZERO_CELSIUS -273
+
+static inline long kelvin_to_celsius(long t)
+{
+ return t + ABSOLUTE_ZERO_CELSIUS;
+}
+
static const uint8_t zero_uuid[16] = { 0 };
static const uint8_t invalid_uuid[16] = {[0 ... 15] = 0xff };
static const char dash[100] = {[0 ... 99] = '-'};
@@ -97,16 +104,12 @@ const char *nvme_cmd_to_string(int admin, __u8 opcode)
return "Unknown";
}
-static const char *fw_to_string(__u64 fw)
+static char *fw_to_string(__u8 fw[])
{
- static char ret[9];
- char *c = (char *)&fw;
- int i;
+ static char frs[9];
- for (i = 0; i < 8; i++)
- ret[i] = c[i] >= '!' && c[i] <= '~' ? c[i] : '.';
- ret[i] = '\0';
- return ret;
+ snprintf(frs, sizeof(frs), "%-.*s", 8, fw);
+ return frs;
}
static const char *get_sanitize_log_sstat_status_str(__u16 status)
@@ -216,6 +219,8 @@ static void json_nvme_id_ctrl(struct nvme_id_ctrl *ctrl,
long double tnvmcap = int128_to_double(ctrl->tnvmcap);
long double unvmcap = int128_to_double(ctrl->unvmcap);
+ long double megcap = int128_to_double(ctrl->megcap);
+ long double maxdna = int128_to_double(ctrl->maxdna);
char sn[sizeof(ctrl->sn) + 1], mn[sizeof(ctrl->mn) + 1],
fr[sizeof(ctrl->fr) + 1], subnqn[sizeof(ctrl->subnqn) + 1];
@@ -249,6 +254,9 @@ static void json_nvme_id_ctrl(struct nvme_id_ctrl *ctrl,
json_object_add_value_int(root, "crdt1", le16_to_cpu(ctrl->crdt1));
json_object_add_value_int(root, "crdt2", le16_to_cpu(ctrl->crdt2));
json_object_add_value_int(root, "crdt3", le16_to_cpu(ctrl->crdt3));
+ json_object_add_value_int(root, "nvmsr", ctrl->nvmsr);
+ json_object_add_value_int(root, "vwci", ctrl->vwci);
+ json_object_add_value_int(root, "mec", ctrl->mec);
json_object_add_value_int(root, "oacs", le16_to_cpu(ctrl->oacs));
json_object_add_value_int(root, "acl", ctrl->acl);
json_object_add_value_int(root, "aerl", ctrl->aerl);
@@ -285,6 +293,8 @@ static void json_nvme_id_ctrl(struct nvme_id_ctrl *ctrl,
le32_to_cpu(ctrl->anagrpmax));
json_object_add_value_int(root, "nanagrpid",
le32_to_cpu(ctrl->nanagrpid));
+ json_object_add_value_int(root, "domainid", le16_to_cpu(ctrl->domainid));
+ json_object_add_value_float(root, "megcap", megcap);
json_object_add_value_int(root, "sqes", ctrl->sqes);
json_object_add_value_int(root, "cqes", ctrl->cqes);
json_object_add_value_int(root, "maxcmd", le16_to_cpu(ctrl->maxcmd));
@@ -298,7 +308,10 @@ static void json_nvme_id_ctrl(struct nvme_id_ctrl *ctrl,
json_object_add_value_int(root, "icsvscc", ctrl->icsvscc);
json_object_add_value_int(root, "nwpc", ctrl->nwpc);
json_object_add_value_int(root, "acwu", le16_to_cpu(ctrl->acwu));
+ json_object_add_value_int(root, "ocfs", le16_to_cpu(ctrl->ocfs));
json_object_add_value_int(root, "sgls", le32_to_cpu(ctrl->sgls));
+ json_object_add_value_float(root, "maxdna", maxdna);
+ json_object_add_value_int(root, "maxcna", le32_to_cpu(ctrl->maxcna));
if (strlen(subnqn))
json_object_add_value_string(root, "subnqn", subnqn);
@@ -471,27 +484,26 @@ static void json_nvme_resv_report(struct nvme_reservation_status *status,
static void json_fw_log(struct nvme_firmware_log_page *fw_log, const char *devname)
{
+ int i;
struct json_object *root;
struct json_object *fwsi;
char fmt[21];
- char str[32];
- int i;
root = json_create_object();
fwsi = json_create_object();
json_object_add_value_int(fwsi, "Active Firmware Slot (afi)",
fw_log->afi);
+
for (i = 0; i < 7; i++) {
- if (fw_log->frs[i]) {
+ if (strcmp(fw_to_string(fw_log->frs[i]), "\0")) {
snprintf(fmt, sizeof(fmt), "Firmware Rev Slot %d",
i + 1);
- snprintf(str, sizeof(str), "%"PRIu64" (%s)",
- (uint64_t)fw_log->frs[i],
- fw_to_string(fw_log->frs[i]));
- json_object_add_value_string(fwsi, fmt, str);
+ json_object_add_value_string(fwsi, fmt,
+ fw_to_string(fw_log->frs[i]));
}
}
+
json_object_add_value_object(root, devname, fwsi);
json_print_object(root, NULL);
@@ -1882,6 +1894,9 @@ static void nvme_show_registers_cap(struct nvme_bar_cap *cap)
(cap->bps_css_nssrs_dstrd & 0x0020) ? "Supported" : "Not Supported");
printf("\t One or more I/O Command Sets are %s\n",
(cap->bps_css_nssrs_dstrd & 0x0800) ? "Supported" : "Not Supported");
+ printf("\t %s\n",
+ (cap->bps_css_nssrs_dstrd & 0x1000) ? "Only Admin Command Set Supported" :
+ "I/O Command Set is Supported");
printf("\tNVM Subsystem Reset Supported (NSSRS): %s\n",
(cap->bps_css_nssrs_dstrd & 0x0010) ? "Yes":"No");
printf("\tDoorbell Stride (DSTRD): %u bytes\n",
@@ -2089,11 +2104,6 @@ static void nvme_show_registers_bpinfo_brs(__u8 brs)
static void nvme_show_registers_bpinfo(__u32 bpinfo)
{
- if (bpinfo == 0) {
- printf("\tBoot Partition feature is not supported\n\n");
- return;
- }
-
printf("\tActive Boot Partition ID (ABPID): %u\n",
(bpinfo & 0x80000000) >> 31);
nvme_show_registers_bpinfo_brs((bpinfo & 0x03000000) >> 24);
@@ -2103,11 +2113,6 @@ static void nvme_show_registers_bpinfo(__u32 bpinfo)
static void nvme_show_registers_bprsel(__u32 bprsel)
{
- if (bprsel == 0) {
- printf("\tBoot Partition feature is not supported\n\n");
- return;
- }
-
printf("\tBoot Partition Identifier (BPID): %u\n",
(bprsel & 0x80000000) >> 31);
printf("\tBoot Partition Read Offset (BPROF): %x\n",
@@ -2118,10 +2123,6 @@ static void nvme_show_registers_bprsel(__u32 bprsel)
static void nvme_show_registers_bpmbl(uint64_t bpmbl)
{
- if (bpmbl == 0) {
- printf("\tBoot Partition feature is not supported\n\n");
- return;
- }
printf("\tBoot Partition Memory Buffer Base Address (BMBBA): %"PRIx64"\n",
bpmbl);
@@ -2714,46 +2715,61 @@ static void nvme_show_id_ctrl_cmic(__u8 cmic)
static void nvme_show_id_ctrl_oaes(__le32 ctrl_oaes)
{
__u32 oaes = le32_to_cpu(ctrl_oaes);
- __u32 rsvd0 = (oaes & 0xF0000000) >> 28;
+ __u32 disc = (oaes >> 31) & 0x1;
+ __u32 rsvd0 = (oaes & 0x70000000) >> 28;
__u32 zicn = (oaes & 0x08000000) >> 27;
- __u32 rsvd1 = (oaes & 0x07FF8000) >> 15;
- __u32 nace = (oaes & 0x100) >> 8;
- __u32 fan = (oaes & 0x200) >> 9;
- __u32 anacn = (oaes & 0x800) >> 11;
- __u32 plealcn = (oaes & 0x1000) >> 12;
- __u32 lbasin = (oaes & 0x2000) >> 13;
+ __u32 rsvd1 = (oaes & 0x07FF0000) >> 16;
+ __u32 normal_shn = (oaes >> 15) & 0x1;
__u32 egealpcn = (oaes & 0x4000) >> 14;
- __u32 rsvd2 = oaes & 0xFF;
+ __u32 lbasin = (oaes & 0x2000) >> 13;
+ __u32 plealcn = (oaes & 0x1000) >> 12;
+ __u32 anacn = (oaes & 0x800) >> 11;
+ __u32 rsvd2 = (oaes >> 10) & 0x1;
+ __u32 fan = (oaes & 0x200) >> 9;
+ __u32 nace = (oaes & 0x100) >> 8;
+ __u32 rsvd3 = oaes & 0xFF;
+ printf(" [31:31] : %#x\tDiscovery Log Change Notice %sSupported\n",
+ disc, disc ? "" : "Not ");
if (rsvd0)
- printf(" [31:28] : %#x\tReserved\n", rsvd0);
- printf("[27:27] : %#x\tZone Descriptor Changed Notices %sSupported\n",
+ printf(" [30:28] : %#x\tReserved\n", rsvd0);
+ printf(" [27:27] : %#x\tZone Descriptor Changed Notices %sSupported\n",
zicn, zicn ? "" : "Not ");
if (rsvd1)
- printf(" [26:15] : %#x\tReserved\n", rsvd1);
- printf("[14:14] : %#x\tEndurance Group Event Aggregate Log Page"\
+ printf(" [26:16] : %#x\tReserved\n", rsvd1);
+ printf(" [15:15] : %#x\tNormal NSS Shutdown Event %sSupported\n",
+ normal_shn, normal_shn ? "" : "Not ");
+ printf(" [14:14] : %#x\tEndurance Group Event Aggregate Log Page"\
" Change Notice %sSupported\n",
egealpcn, egealpcn ? "" : "Not ");
- printf("[13:13] : %#x\tLBA Status Information Notices %sSupported\n",
+ printf(" [13:13] : %#x\tLBA Status Information Notices %sSupported\n",
lbasin, lbasin ? "" : "Not ");
- printf("[12:12] : %#x\tPredictable Latency Event Aggregate Log Change"\
+ printf(" [12:12] : %#x\tPredictable Latency Event Aggregate Log Change"\
" Notices %sSupported\n",
plealcn, plealcn ? "" : "Not ");
- printf("[11:11] : %#x\tAsymmetric Namespace Access Change Notices"\
+ printf(" [11:11] : %#x\tAsymmetric Namespace Access Change Notices"\
" %sSupported\n", anacn, anacn ? "" : "Not ");
+ if (rsvd2)
+ printf(" [10:10] : %#x\tReserved\n", rsvd2);
printf(" [9:9] : %#x\tFirmware Activation Notices %sSupported\n",
fan, fan ? "" : "Not ");
printf(" [8:8] : %#x\tNamespace Attribute Changed Event %sSupported\n",
nace, nace ? "" : "Not ");
- if (rsvd2)
- printf(" [7:0] : %#x\tReserved\n", rsvd1);
+ if (rsvd3)
+ printf(" [7:0] : %#x\tReserved\n", rsvd3);
printf("\n");
}
static void nvme_show_id_ctrl_ctratt(__le32 ctrl_ctratt)
{
__u32 ctratt = le32_to_cpu(ctrl_ctratt);
- __u32 rsvd = ctratt >> 10;
+ __u32 rsvd = ctratt >> 16;
+ __u32 elbas = (ctratt >> 15) & 0x1;
+ __u32 delnvmset = (ctratt >> 14) & 0x1;
+ __u32 delegrp = (ctratt >> 13) & 0x1;
+ __u32 vcap = (ctratt >> 12) & 0x1;
+ __u32 fcap = (ctratt >> 11) & 0x1;
+ __u32 mds = (ctratt >> 10) & 0x1;
__u32 hostid128 = (ctratt & NVME_CTRL_CTRATT_128_ID) >> 0;
__u32 psp = (ctratt & NVME_CTRL_CTRATT_NON_OP_PSP) >> 1;
__u32 sets = (ctratt & NVME_CTRL_CTRATT_NVM_SETS) >> 2;
@@ -2766,8 +2782,19 @@ static void nvme_show_id_ctrl_ctratt(__le32 ctrl_ctratt)
__u32 rsvd8 = (ctratt & 0x00000100) >> 8;
if (rsvd)
- printf(" [31:10] : %#x\tReserved\n", rsvd);
-
+ printf(" [31:16] : %#x\tReserved\n", rsvd);
+ printf(" [15:15] : %#x\tExtended LBA Formats %sSupported\n",
+ elbas, elbas ? "" : "Not ");
+ printf(" [14:14] : %#x\tDelete NVM Set %sSupported\n",
+ delnvmset, delnvmset ? "" : "Not ");
+ printf(" [13:13] : %#x\tDelete Endurance Group %sSupported\n",
+ delegrp, delegrp ? "" : "Not ");
+ printf(" [12:12] : %#x\tVariable Capacity Management %sSupported\n",
+ vcap, vcap ? "" : "Not ");
+ printf(" [11:11] : %#x\tFixed Capacity Management %sSupported\n",
+ fcap, fcap ? "" : "Not ");
+ printf(" [10:10] : %#x\tMulti Domain Subsystem %sSupported\n",
+ mds, mds ? "" : "Not ");
printf(" [9:9] : %#x\tUUID List %sSupported\n",
uuidlist, uuidlist ? "" : "Not ");
if (rsvd8)
@@ -2807,10 +2834,54 @@ static void nvme_show_id_ctrl_cntrltype(__u8 cntrltype)
printf(" [1:0] : %#x\t%s\n", cntrltype, type[cntrl]);
}
+static void nvme_show_id_ctrl_nvmsr(__u8 nvmsr)
+{
+ __u8 rsvd = (nvmsr >> 2) & 0xfc;
+ __u8 nvmee = (nvmsr >> 1) & 0x1;
+ __u8 nvmesd = nvmsr & 0x1;
+
+ if (rsvd)
+ printf(" [7:2] : %#x\tReserved\n", rsvd);
+ printf(" [1:1] : %#x\tNVM subsystem %spart of an Enclosure\n",
+ nvmee, nvmee ? "" : "Not ");
+ printf(" [0:0] : %#x\tNVM subsystem %spart of an Storage Device\n",
+ nvmesd, nvmesd ? "" : "Not ");
+ printf("\n");
+}
+
+static void nvme_show_id_ctrl_vwci(__u8 vwci)
+{
+ __u8 vwcrv = (vwci >> 7) & 0x1;
+ __u8 vwcr = vwci & 0xfe;
+
+ printf(" [7:7] : %#x\tVPD Write Cycles Remaining field is %svalid.\n",
+ vwcrv, vwcrv ? "" : "Not ");
+ printf(" [6:0] : %#x\tVPD Write Cycles Remaining \n", vwcr);
+ printf("\n");
+
+}
+
+static void nvme_show_id_ctrl_mec(__u8 mec)
+{
+ __u8 rsvd = (mec >> 2) & 0xfc;
+ __u8 pcieme = (mec >> 1) & 0x1;
+ __u8 smbusme = mec & 0x1;
+
+ if (rsvd)
+ printf(" [7:2] : %#x\tReserved\n", rsvd);
+ printf(" [1:1] : %#x\tNVM subsystem %scontains a Management Endpoint"\
+ " on a PCIe port\n", pcieme, pcieme ? "" : "Not ");
+ printf(" [0:0] : %#x\tNVM subsystem %scontains a Management Endpoint"\
+ " on an SMBus/I2C port\n", smbusme, smbusme ? "" : "Not ");
+ printf("\n");
+
+}
+
static void nvme_show_id_ctrl_oacs(__le16 ctrl_oacs)
{
__u16 oacs = le16_to_cpu(ctrl_oacs);
- __u16 rsvd = (oacs & 0xFC00) >> 10;
+ __u16 rsvd = (oacs & 0xF800) >> 11;
+ __u16 lock = (oacs >> 10) & 0x1;
__u16 glbas = (oacs & 0x200) >> 9;
__u16 dbc = (oacs & 0x100) >> 8;
__u16 vir = (oacs & 0x80) >> 7;
@@ -2823,7 +2894,9 @@ static void nvme_show_id_ctrl_oacs(__le16 ctrl_oacs)
__u16 sec = oacs & 0x1;
if (rsvd)
- printf(" [15:9] : %#x\tReserved\n", rsvd);
+ printf(" [15:11] : %#x\tReserved\n", rsvd);
+ printf(" [10:10] : %#x\tLockdown Command and Feature %sSupported\n",
+ lock, lock ? "" : "Not ");
printf(" [9:9] : %#x\tGet LBA Status Capability %sSupported\n",
glbas, glbas ? "" : "Not ");
printf(" [8:8] : %#x\tDoorbell Buffer Config %sSupported\n",
@@ -2849,13 +2922,16 @@ static void nvme_show_id_ctrl_oacs(__le16 ctrl_oacs)
static void nvme_show_id_ctrl_frmw(__u8 frmw)
{
- __u8 rsvd = (frmw & 0xE0) >> 5;
+ __u8 rsvd = (frmw & 0xC0) >> 6;
+ __u8 smud = (frmw >> 5) & 0x1;
__u8 fawr = (frmw & 0x10) >> 4;
__u8 nfws = (frmw & 0xE) >> 1;
__u8 s1ro = frmw & 0x1;
if (rsvd)
- printf(" [7:5] : %#x\tReserved\n", rsvd);
+ printf(" [7:6] : %#x\tReserved\n", rsvd);
+ printf(" [5:5] : %#x\tMultiple FW or Boot Update Detection %sSupported\n",
+ smud, smud ? "" : "Not ");
printf(" [4:4] : %#x\tFirmware Activate Without Reset %sSupported\n",
fawr, fawr ? "" : "Not ");
printf(" [3:1] : %#x\tNumber of Firmware Slots\n", nfws);
@@ -2866,7 +2942,9 @@ static void nvme_show_id_ctrl_frmw(__u8 frmw)
static void nvme_show_id_ctrl_lpa(__u8 lpa)
{
- __u8 rsvd = (lpa & 0xE0) >> 5;
+ __u8 rsvd = (lpa & 0x80) >> 7;
+ __u8 tel = (lpa >> 6) & 0x1;
+ __u8 lid_sup = (lpa >> 5) & 0x1;
__u8 persevnt = (lpa & 0x10) >> 4;
__u8 telem = (lpa & 0x8) >> 3;
__u8 ed = (lpa & 0x4) >> 2;
@@ -2874,7 +2952,11 @@ static void nvme_show_id_ctrl_lpa(__u8 lpa)
__u8 smlp = lpa & 0x1;
if (rsvd)
- printf(" [7:4] : %#x\tReserved\n", rsvd);
+ printf(" [7:7] : %#x\tReserved\n", rsvd);
+ printf(" [6:6] : %#x\tTelemetry Log Data Area 4 %sSupported\n",
+ tel, tel ? "" : "Not ");
+ printf(" [5:5] : %#x\tLID 0x0, Scope of each command in LID 0x5, "\
+ "0x12, 0x13 %sSupported\n", lid_sup, lid_sup ? "" : "Not ");
printf(" [4:4] : %#x\tPersistent Event log %sSupported\n",
persevnt, persevnt ? "" : "Not ");
printf(" [3:3] : %#x\tTelemetry host/controller initiated log page %sSupported\n",
@@ -2910,6 +2992,20 @@ static void nvme_show_id_ctrl_apsta(__u8 apsta)
printf("\n");
}
+static void nvme_show_id_ctrl_wctemp(__le16 wctemp)
+{
+ printf(" [16:0] : %ld C (%u Kelvin)\tWarning temperature (WCTEMP)\n",
+ kelvin_to_celsius(le16_to_cpu(wctemp)), le16_to_cpu(wctemp));
+ printf("\n");
+}
+
+static void nvme_show_id_ctrl_cctemp(__le16 cctemp)
+{
+ printf(" [16:0] : %ld C (%u Kelvin)\tCritical temperature (CCTEMP)\n",
+ kelvin_to_celsius(le16_to_cpu(cctemp)), le16_to_cpu(cctemp));
+ printf("\n");
+}
+
void nvme_show_id_ctrl_rpmbs(__le32 ctrl_rpmbs)
{
__u32 rpmbs = le32_to_cpu(ctrl_rpmbs);
@@ -3072,12 +3168,15 @@ static void nvme_show_id_ctrl_fuses(__le16 ctrl_fuses)
static void nvme_show_id_ctrl_fna(__u8 fna)
{
- __u8 rsvd = (fna & 0xF8) >> 3;
+ __u8 rsvd = (fna & 0xF0) >> 4;
+ __u8 bcnsid = (fna & 0x8) >> 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(" [7:4] : %#x\tReserved\n", rsvd);
+ printf(" [3:3] : %#x\tFormatNVM Broadcast NSID (FFFFFFFFh) %sSupported\n",
+ bcnsid, bcnsid ? "Not " : "");
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",
@@ -3138,6 +3237,21 @@ static void nvme_show_id_ctrl_nwpc(__u8 nwpc)
printf("\n");
}
+static void nvme_show_id_ctrl_ocfs(__le16 ctrl_ocfs)
+{
+ __u16 ocfs = le16_to_cpu(ctrl_ocfs);
+ __u16 rsvd = (ocfs & 0xfffc) >> 2;
+ __u8 copy_fmt_1 = (ocfs >> 1) & 0x1;
+ __u8 copy_fmt_0 = ocfs & 0x1;
+ if (rsvd)
+ printf(" [15:2] : %#x\tReserved\n", rsvd);
+ printf(" [1:1] : %#x\tController Copy Format 1h %sSupported\n",
+ copy_fmt_1, copy_fmt_1 ? "" : "Not ");
+ printf(" [0:0] : %#x\tController Copy Format 0h %sSupported\n",
+ copy_fmt_0, copy_fmt_0 ? "" : "Not ");
+ printf("\n");
+}
+
static void nvme_show_id_ctrl_sgls(__le32 ctrl_sgls)
{
__u32 sgls = le32_to_cpu(ctrl_sgls);
@@ -3148,7 +3262,8 @@ static void nvme_show_id_ctrl_sgls(__le32 ctrl_sgls)
__u32 sglltb = (sgls & 0x40000) >> 18;
__u32 bacmdb = (sgls & 0x20000) >> 17;
__u32 bbs = (sgls & 0x10000) >> 16;
- __u32 rsvd1 = (sgls & 0xFFF8) >> 3;
+ __u32 sdt = (sgls >> 8) & 0xff;
+ __u32 rsvd1 = (sgls & 0xF8) >> 3;
__u32 key = (sgls & 0x4) >> 2;
__u32 sglsp = sgls & 0x3;
@@ -3173,8 +3288,9 @@ static void nvme_show_id_ctrl_sgls(__le32 ctrl_sgls)
if (sglsp || (!sglsp && bbs))
printf(" [16:16]: %#x\tSGL Bit-Bucket %sSupported\n",
bbs, bbs ? "" : "Not ");
+ printf(" [15:8] : %#x\tSGL Descriptor Threshold\n", sdt);
if (rsvd1)
- printf(" [15:3] : %#x\tReserved\n", rsvd1);
+ printf(" [7:3] : %#x\tReserved\n", rsvd1);
if (sglsp || (!sglsp && key))
printf(" [2:2] : %#x\tKeyed SGL Data Block descriptor %sSupported\n",
key, key ? "" : "Not ");
@@ -3702,7 +3818,7 @@ static void nvme_show_id_ctrl_power(struct nvme_id_ctrl *ctrl)
void __nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, enum nvme_print_flags flags,
void (*vendor_show)(__u8 *vs, struct json_object *root))
{
- int human = flags & VERBOSE, vs = flags & VS;
+ bool human = flags & VERBOSE, vs = flags & VS;
if (flags & BINARY)
return d_raw((unsigned char *)ctrl, sizeof(*ctrl));
@@ -3740,6 +3856,15 @@ void __nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, enum nvme_print_flags flags,
printf("crdt1 : %u\n", le16_to_cpu(ctrl->crdt1));
printf("crdt2 : %u\n", le16_to_cpu(ctrl->crdt2));
printf("crdt3 : %u\n", le16_to_cpu(ctrl->crdt3));
+ printf("nvmsr : %u\n", ctrl->nvmsr);
+ if (human)
+ nvme_show_id_ctrl_nvmsr(ctrl->nvmsr);
+ printf("vwci : %u\n", ctrl->vwci);
+ if (human)
+ nvme_show_id_ctrl_vwci(ctrl->vwci);
+ printf("mec : %u\n", ctrl->mec);
+ if (human)
+ nvme_show_id_ctrl_mec(ctrl->vwci);
printf("oacs : %#x\n", le16_to_cpu(ctrl->oacs));
if (human)
@@ -3761,7 +3886,11 @@ void __nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, enum nvme_print_flags flags,
if (human)
nvme_show_id_ctrl_apsta(ctrl->apsta);
printf("wctemp : %d\n", le16_to_cpu(ctrl->wctemp));
+ if (human)
+ nvme_show_id_ctrl_wctemp(ctrl->wctemp);
printf("cctemp : %d\n", le16_to_cpu(ctrl->cctemp));
+ if (human)
+ nvme_show_id_ctrl_cctemp(ctrl->cctemp);
printf("mtfa : %d\n", le16_to_cpu(ctrl->mtfa));
printf("hmpre : %d\n", le32_to_cpu(ctrl->hmpre));
printf("hmmin : %d\n", le32_to_cpu(ctrl->hmmin));
@@ -3793,6 +3922,8 @@ void __nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, enum nvme_print_flags flags,
printf("anagrpmax : %d\n", ctrl->anagrpmax);
printf("nanagrpid : %d\n", le32_to_cpu(ctrl->nanagrpid));
printf("pels : %d\n", le32_to_cpu(ctrl->pels));
+ printf("domainid : %d\n", le16_to_cpu(ctrl->domainid));
+ printf("megcap : %.0Lf\n", int128_to_double(ctrl->megcap));
printf("sqes : %#x\n", ctrl->sqes);
if (human)
nvme_show_id_ctrl_sqes(ctrl->sqes);
@@ -3822,10 +3953,15 @@ void __nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, enum nvme_print_flags flags,
if (human)
nvme_show_id_ctrl_nwpc(ctrl->nwpc);
printf("acwu : %d\n", le16_to_cpu(ctrl->acwu));
+ printf("ocfs : %#x\n", le16_to_cpu(ctrl->ocfs));
+ if (human)
+ nvme_show_id_ctrl_ocfs(ctrl->ocfs);
printf("sgls : %#x\n", le32_to_cpu(ctrl->sgls));
if (human)
nvme_show_id_ctrl_sgls(ctrl->sgls);
printf("mnan : %d\n", le32_to_cpu(ctrl->mnan));
+ printf("maxdna : %.0Lf\n", int128_to_double(ctrl->maxdna));
+ printf("maxcna : %d\n", le32_to_cpu(ctrl->maxcna));
printf("subnqn : %-.*s\n", (int)sizeof(ctrl->subnqn), ctrl->subnqn);
printf("ioccsz : %d\n", le32_to_cpu(ctrl->ioccsz));
printf("iorcsz : %d\n", le32_to_cpu(ctrl->iorcsz));
@@ -3861,8 +3997,8 @@ static void json_nvme_id_ctrl_nvm(struct nvme_id_ctrl_nvm *ctrl_nvm)
json_object_add_value_uint(root, "wzsl", ctrl_nvm->wzsl);
json_object_add_value_uint(root, "wusl", ctrl_nvm->wusl);
json_object_add_value_uint(root, "dmrl", ctrl_nvm->dmrl);
- json_object_add_value_uint(root, "dmrsl", ctrl_nvm->dmrsl);
- json_object_add_value_uint(root, "dmsl", ctrl_nvm->dmsl);
+ json_object_add_value_uint(root, "dmrsl", le32_to_cpu(ctrl_nvm->dmrsl));
+ json_object_add_value_uint(root, "dmsl", le64_to_cpu(ctrl_nvm->dmsl));
json_print_object(root, NULL);
printf("\n");
@@ -4044,6 +4180,42 @@ void nvme_show_zns_id_ns(struct nvme_zns_id_ns *ns,
}
}
+static void json_nvme_list_ns(__u32 *ns_list)
+{
+ struct json_object *root;
+ struct json_object *valid_attrs;
+ struct json_object *valid;
+ int i;
+
+ root = json_create_object();
+ valid = json_create_array();
+
+ for (i = 0; i < 1024; i++) {
+ if (ns_list[i]) {
+ valid_attrs = json_create_object();
+ json_object_add_value_uint(valid_attrs, "nsid",
+ le32_to_cpu(ns_list[i]));
+ json_array_add_value_object(valid, valid_attrs);
+ }
+ }
+ json_object_add_value_array(root, "nsid_list", valid);
+ json_print_object(root, NULL);
+ printf("\n");
+ json_free_object(root);
+}
+
+void nvme_show_list_ns(__u32 *ns_list, enum nvme_print_flags flags)
+{
+ int i;
+ if (flags & JSON)
+ return json_nvme_list_ns(ns_list);
+
+ for (i = 0; i < 1024; i++) {
+ if (ns_list[i])
+ printf("[%4u]:%#x\n", i, le32_to_cpu(ns_list[i]));
+ }
+}
+
void nvme_show_zns_changed(struct nvme_zns_changed_zone_log *log,
unsigned long flags)
{
@@ -4134,6 +4306,48 @@ void nvme_show_zns_report_zones(void *report, __u32 descs,
}
}
+static void json_nvme_list_ctrl(struct nvme_controller_list *ctrl_list, __u16 num)
+{
+ 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_ctrl",
+ le16_to_cpu(ctrl_list->num));
+
+ for (i = 0; i < min(num, 2047); i++) {
+
+ valid_attrs = json_create_object();
+ json_object_add_value_uint(valid_attrs, "ctrl_id",
+ le16_to_cpu(ctrl_list->identifier[i]));
+ json_array_add_value_object(valid, valid_attrs);
+ }
+
+ json_object_add_value_array(root, "ctrl_list", valid);
+ json_print_object(root, NULL);
+ printf("\n");
+ json_free_object(root);
+}
+
+void nvme_show_list_ctrl(struct nvme_controller_list *ctrl_list,
+ enum nvme_print_flags flags)
+{
+ int i;
+ __u16 num = le16_to_cpu(ctrl_list->num);
+
+ if (flags & JSON)
+ return json_nvme_list_ctrl(ctrl_list, num);
+
+ printf("num of ctrls present: %u\n", num);
+ for (i = 0; i < min(num, 2047); i++) {
+ printf("[%4u]:%#x\n", i, le16_to_cpu(ctrl_list->identifier[i]));
+ }
+}
+
static void json_nvme_id_nvmset(struct nvme_id_nvmset *nvmset)
{
__u32 nent = nvmset->nid;
@@ -4188,7 +4402,7 @@ void nvme_show_id_nvmset(struct nvme_id_nvmset *nvmset, unsigned nvmset_id,
printf(".................\n");
printf("nvmset_id : %d\n",
le16_to_cpu(nvmset->ent[i].id));
- printf("enduracne_group_id : %d\n",
+ printf("endurance_group_id : %d\n",
le16_to_cpu(nvmset->ent[i].endurance_group_id));
printf("random_4k_read_typical : %u\n",
le32_to_cpu(nvmset->ent[i].random_4k_read_typical));
@@ -4487,14 +4701,122 @@ void nvme_show_id_uuid_list(const struct nvme_id_uuid_list *uuid_list,
}
}
-void nvme_show_id_iocs(struct nvme_id_iocs *iocs)
+static void nvme_show_iocs_vector(__u64 iocs_vec)
+{
+ __u64 rsvd3 = iocs_vec >> 3;
+ __u8 zns_cmd_set = (iocs_vec >> 2) & 0x1;
+ __u8 kv_cmd_set = (iocs_vec >> 1) & 0x1;
+ __u8 nvm_cmd_set = iocs_vec & 0x1;
+
+ if (rsvd3)
+ printf(" [63:3] : %"PRIx64"\tReserved3\n", le64_to_cpu(rsvd3));
+ printf(" [2:2] : %#x\tZNS Command Set %sSelected\n",
+ zns_cmd_set, zns_cmd_set ? "" : "not ");
+ printf(" [1:1] : %#x\tKV Command Set %sSelected\n",
+ kv_cmd_set, kv_cmd_set ? "" : "not ");
+ printf(" [0:0] : %#x\tNVM Command Set %sSelected\n",
+ nvm_cmd_set, nvm_cmd_set ? "" : "not ");
+ printf("\n");
+}
+
+static void json_id_iocs(struct nvme_id_iocs *iocs)
{
- __u16 i;
+ struct json_object *root;
+ struct json_object *entries;
+ int i;
+
+ root = json_create_object();
+ entries = json_create_array();
- for (i = 0; i < 512; i++)
- if (iocs->iocs[i])
- printf("I/O Command Set Combination[%u]:%"PRIx64"\n", i,
+ for (i = 0; i < NVME_NUM_IOCS_COMBINATIONS; i++) {
+ if (iocs->iocs[i]) {
+ struct json_object *entry = json_create_object();
+ json_object_add_value_uint(entry, "iocs",
+ le64_to_cpu(iocs->iocs[i]));
+ json_array_add_value_object(entries, entry);
+ }
+ }
+
+ json_object_add_value_array(root, "iocs_list", entries);
+ json_print_object(root, NULL);
+ printf("\n");
+ json_free_object(root);
+
+}
+
+void nvme_show_id_iocs(struct nvme_id_iocs *iocs, enum nvme_print_flags flags)
+{
+ if (flags & BINARY)
+ return d_raw((unsigned char *)iocs, sizeof(*iocs));
+ else if (flags & JSON)
+ return json_id_iocs(iocs);
+
+ bool human = flags & VERBOSE;
+ int i;
+
+ for (i = 0; i < NVME_NUM_IOCS_COMBINATIONS; i++) {
+ if (iocs->iocs[i]) {
+ printf("I/O Command Set Combination[%u]: %"PRIx64"\n", i,
(uint64_t)le64_to_cpu(iocs->iocs[i]));
+ if (human)
+ nvme_show_iocs_vector(le64_to_cpu(iocs->iocs[i]));
+ }
+ }
+}
+
+static void json_id_domain_list(struct nvme_id_domain_list *id_dom)
+{
+ struct json_object *root;
+ struct json_object *entries;
+ struct json_object *entry;
+ int i;
+ long double dom_cap, unalloc_dom_cap, max_egrp_dom_cap;
+
+ root = json_create_object();
+ entries = json_create_array();
+
+ json_object_add_value_uint(root, "num_dom_entries", id_dom->num_entries);
+
+ for (i = 0; i < id_dom->num_entries; i++) {
+ entry = json_create_object();
+ dom_cap = int128_to_double(id_dom->domain_attr[i].dom_cap);
+ unalloc_dom_cap = int128_to_double(id_dom->domain_attr[i].unalloc_dom_cap);
+ max_egrp_dom_cap = int128_to_double(id_dom->domain_attr[i].max_egrp_dom_cap);
+
+ json_object_add_value_uint(entry, "dom_id", le16_to_cpu(id_dom->domain_attr[i].dom_id));
+ json_object_add_value_float(entry, "dom_cap", dom_cap);
+ json_object_add_value_float(entry, "unalloc_dom_cap", unalloc_dom_cap);
+ json_object_add_value_float(entry, "max_egrp_dom_cap", max_egrp_dom_cap);
+
+ json_array_add_value_object(entries, entry);
+ }
+
+ json_object_add_value_array(root, "domain_list", entries);
+ json_print_object(root, NULL);
+ printf("\n");
+ json_free_object(root);
+}
+
+void nvme_show_id_domain_list(struct nvme_id_domain_list *id_dom,
+ enum nvme_print_flags flags)
+{
+ int i;
+ if (flags & BINARY)
+ return d_raw((unsigned char *)id_dom, sizeof(*id_dom));
+ else if (flags & JSON)
+ return json_id_domain_list(id_dom);
+
+ printf("Number of Domain Entires: %u\n", id_dom->num_entries);
+ for (i = 0; i < id_dom->num_entries; i++) {
+ printf("Domain Id for Attr Entry[%u]: %u\n", i,
+ le16_to_cpu(id_dom->domain_attr[i].dom_id));
+ printf("Domain Capacity for Attr Entry[%u]: %.0Lf\\n", i,
+ int128_to_double(id_dom->domain_attr[i].dom_cap));
+ printf("Unallocated Domain Capacity for Attr Entry[%u]: %.0Lf\n", i,
+ int128_to_double(id_dom->domain_attr[i].unalloc_dom_cap));
+ printf("Max Endurange Group Domain Capacity for Attr Entry[%u]: %.0Lf\n", i,
+ int128_to_double(id_dom->domain_attr[i].max_egrp_dom_cap));
+ }
}
static const char *nvme_trtype_to_string(__u8 trtype)
@@ -4620,7 +4942,6 @@ void nvme_show_fw_log(struct nvme_firmware_log_page *fw_log,
const char *devname, enum nvme_print_flags flags)
{
int i;
-
if (flags & BINARY)
return d_raw((unsigned char *)fw_log, sizeof(*fw_log));
if (flags & JSON)
@@ -4629,10 +4950,8 @@ void nvme_show_fw_log(struct nvme_firmware_log_page *fw_log,
printf("Firmware Log for device:%s\n", devname);
printf("afi : %#x\n", fw_log->afi);
for (i = 0; i < 7; i++) {
- if (fw_log->frs[i])
- printf("frs%d : %#016"PRIx64" (%s)\n", i + 1,
- (uint64_t)fw_log->frs[i],
- fw_to_string(fw_log->frs[i]));
+ if (strcmp(fw_to_string(fw_log->frs[i]), "\0"))
+ printf("frs%d : %s\n", i + 1, fw_to_string(fw_log->frs[i]));
}
}
@@ -4771,10 +5090,9 @@ void nvme_show_endurance_log(struct nvme_endurance_group_log *endurance_log,
void nvme_show_smart_log(struct nvme_smart_log *smart, unsigned int nsid,
const char *devname, enum nvme_print_flags flags)
{
- /* convert temperature from Kelvin to Celsius */
- int temperature = ((smart->temperature[1] << 8) |
- smart->temperature[0]) - 273;
- int i, human = flags & VERBOSE;
+ __u16 temperature = smart->temperature[1] << 8 | smart->temperature[0];
+ int i;
+ bool human = flags & VERBOSE;
if (flags & BINARY)
return d_raw((unsigned char *)smart, sizeof(*smart));
@@ -4794,8 +5112,8 @@ void nvme_show_smart_log(struct nvme_smart_log *smart, unsigned int nsid,
printf(" Persistent Mem. RO[5] : %d\n", (smart->critical_warning & 0x20) >> 5);
}
- printf("temperature : %d C\n",
- temperature);
+ printf("temperature : %ld C (%u Kelvin)\n",
+ kelvin_to_celsius(temperature), temperature);
printf("available_spare : %u%%\n",
smart->avail_spare);
printf("available_spare_threshold : %u%%\n",
@@ -4833,8 +5151,8 @@ void nvme_show_smart_log(struct nvme_smart_log *smart, unsigned int nsid,
if (temp == 0)
continue;
- printf("Temperature Sensor %d : %d C\n", i + 1,
- temp - 273);
+ printf("Temperature Sensor %d : %ld C (%u Kelvin)\n",
+ i + 1, kelvin_to_celsius(temp), temp);
}
printf("Thermal Management T1 Trans Count : %u\n",
le32_to_cpu(smart->thm_temp1_trans_count));
@@ -5030,11 +5348,9 @@ void nvme_show_sanitize_log(struct nvme_sanitize_log_page *sanitize,
__u16 status = le16_to_cpu(sanitize->status) & NVME_SANITIZE_LOG_STATUS_MASK;
if (flags & BINARY)
- d_raw((unsigned char *)sanitize, sizeof(*sanitize));
- else if (flags & JSON) {
- json_sanitize_log(sanitize, devname);
- return;
- }
+ return d_raw((unsigned char *)sanitize, sizeof(*sanitize));
+ else if (flags & JSON)
+ return json_sanitize_log(sanitize, devname);
printf("Sanitize Progress (SPROG) : %u",
le16_to_cpu(sanitize->progress));
@@ -5088,7 +5404,7 @@ const char *nvme_feature_to_string(enum nvme_feat feature)
case NVME_FEAT_PLM_CONFIG: return "Predicatable Latency Mode Config";
case NVME_FEAT_PLM_WINDOW: return "Predicatable Latency Mode Window";
case NVME_LBA_STATUS_INFO: return "LBA Status Infomation Attributes";
- case NVME_FEAT_ENDURANCE: return "Enduarance Event Group Configuration";
+ case NVME_FEAT_ENDURANCE: return "Enduarance Event Group Configuration";
case NVME_FEAT_IOCS_PROFILE: return "I/O Command Set Profile";
case NVME_FEAT_SW_PROGRESS: return "Software Progress";
case NVME_FEAT_HOST_ID: return "Host Identifier";
@@ -5099,6 +5415,8 @@ const char *nvme_feature_to_string(enum nvme_feat feature)
case NVME_FEAT_HCTM: return "Host Controlled Thermal Management";
case NVME_FEAT_HOST_BEHAVIOR: return "Host Behavior";
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";
}
/*
* We don't use the "default:" statement to let the compiler warning if
@@ -5209,6 +5527,10 @@ const char *nvme_status_to_string(__u16 status)
return "SANITIZE_FAILED: The most recent sanitize operation failed and no recovery actions has been successfully completed";
case NVME_SC_SANITIZE_IN_PROGRESS:
return "SANITIZE_IN_PROGRESS: The requested function is prohibited while a sanitize operation is in progress";
+ case NVME_SC_SGL_DATA_BLK_GRAN_INVALID:
+ return "NVME_SC_SGL_DATA_BLK_GRAN_INVALID: Address alignment or Length granularity for an SGL Data Block descriptor is invalid";
+ case NVME_SC_CMD_NOT_SUP_QUEUE_IN_CMB:
+ return "NVME_SC_CMD_NOT_SUP_QUEUE_IN_CMB: does not support submission of the command to a SQ or completion to a CQ in the CMB";
case NVME_SC_IOCS_NOT_SUPPORTED:
return "IOCS_NOT_SUPPORTED: The I/O command set is not supported";
case NVME_SC_IOCS_NOT_ENABLED:
@@ -5217,12 +5539,18 @@ const char *nvme_status_to_string(__u16 status)
return "IOCS_COMBINATION_REJECTED: The I/O command set combination is rejected";
case NVME_SC_INVALID_IOCS:
return "INVALID_IOCS: the I/O command set is invalid";
+ case NVME_SC_ID_UNAVAILABLE:
+ return "NVME_SC_ID_UNAVAILABLE: The number of Endurance Groups or NVM Sets supported has been exceeded.";
case NVME_SC_LBA_RANGE:
return "LBA_RANGE: The command references a LBA that exceeds the size of the namespace";
case NVME_SC_NS_WRITE_PROTECTED:
return "NS_WRITE_PROTECTED: The command is prohibited while the namespace is write protected by the host.";
case NVME_SC_TRANSIENT_TRANSPORT:
return "TRANSIENT_TRANSPORT: A transient transport error was detected.";
+ case NVME_SC_PROHIBITED_BY_CMD_AND_FEAT:
+ return "NVME_SC_PROHIBITED_BY_CMD_AND_FEAT: command was aborted due to execution being prohibited by the Command and Feature Lockdown";
+ case NVME_SC_ADMIN_CMD_MEDIA_NOT_READY:
+ return "NVME_SC_ADMIN_CMD_MEDIA_NOT_READY: Admin command requires access to media and the media is not ready";
case NVME_SC_CAP_EXCEEDED:
return "CAP_EXCEEDED: The execution of the command has caused the capacity of the namespace to be exceeded";
case NVME_SC_NS_NOT_READY:
@@ -5319,6 +5647,12 @@ const char *nvme_status_to_string(__u16 status)
return "ANA_INVALID_GROUP_ID: The specified ANA Group Identifier (ANAGRPID) is not supported in the submitted command.";
case NVME_SC_ANA_ATTACH_FAIL:
return "ANA_ATTACH_FAIL: The controller is not attached to the namespace as a result of an ANA condition";
+ case NVME_SC_INSUFFICIENT_CAP:
+ return "NVME_SC_INSUFFICIENT_CAP: Requested operation requires more free space than is currently available";
+ case NVME_SC_NS_ATTACHMENT_LIMIT_EXCEEDED:
+ return "NVME_SC_NS_ATTACHMENT_LIMIT_EXCEEDED: Attaching the ns to a controller causes max number of ns attachments allowed to be exceeded";
+ case NVME_SC_PROHIBIT_CMD_EXEC_NOT_SUPPORTED:
+ return "NVME_SC_PROHIBIT_CMD_EXEC_NOT_SUPPORTED: Prohibition of Command Execution Not Supported";
case NVME_SC_BAD_ATTRIBUTES:
return "BAD_ATTRIBUTES: Bad attributes were given";
case NVME_SC_INVALID_PI:
@@ -5343,6 +5677,8 @@ const char *nvme_status_to_string(__u16 status)
return "ACCESS_DENIED: Access to the namespace and/or LBA range is denied due to lack of access rights";
case NVME_SC_UNWRITTEN_BLOCK:
return "UNWRITTEN_BLOCK: The command failed due to an attempt to read from an LBA range containing a deallocated or unwritten logical block";
+ case NVME_SC_STORAGE_TAG_CHECK:
+ return "NVME_SC_STORAGE_TAG_CHECK: command was aborted due to an end-to-end storage tag check failure";
case NVME_SC_INTERNAL_PATH_ERROR:
return "INTERNAL_PATH_ERROT: The command was not completed as the result of a controller internal error";
case NVME_SC_ANA_PERSISTENT_LOSS:
@@ -5396,8 +5732,8 @@ void nvme_show_lba_range(struct nvme_lba_range_type *lbrt, int nr_ranges)
((lbrt[i].attributes & 0x0002) >> 1) ?
"LBA range should be hidden from the OS/EFI/BIOS" :
"LBA range should be visible from the OS/EFI/BIOS");
- printf("\tslba : %#"PRIx64"\n", (uint64_t)(lbrt[i].slba));
- printf("\tnlb : %#"PRIx64"\n", (uint64_t)(lbrt[i].nlb));
+ printf("\tslba : %#"PRIx64"\n", le64_to_cpu(lbrt[i].slba));
+ printf("\tnlb : %#"PRIx64"\n", le64_to_cpu(lbrt[i].nlb));
printf("\tguid : ");
for (j = 0; j < 16; j++)
printf("%02x", lbrt[i].guid[j]);
@@ -5451,9 +5787,9 @@ static void nvme_show_auto_pst(struct nvme_auto_pst *apst)
printf("\tEntry[%2d] \n", i);
printf("\t.................\n");
printf("\tIdle Time Prior to Transition (ITPT): %u ms\n",
- (apst[i].data & 0xffffff00) >> 8);
+ (le32_to_cpu(apst[i].data) & 0xffffff00) >> 8);
printf("\tIdle Transition Power State (ITPS): %u\n",
- (apst[i].data & 0x000000f8) >> 3);
+ (le32_to_cpu(apst[i].data) & 0x000000f8) >> 3);
printf("\t.................\n");
}
}
@@ -5493,6 +5829,22 @@ static void nvme_show_host_mem_buffer(struct nvme_host_mem_buffer *hmb)
le32_to_cpu(hmb->hsize));
}
+static const char *nvme_show_ns_write_protect_config(__u8 state)
+{
+ switch (state) {
+ case NVME_NS_NO_WRITE_PROTECT:
+ return "No Write Protect";
+ case NVME_NS_WRITE_PROTECT:
+ return "Write Protect";
+ case NVME_NS_WRITE_PROTECT_POWER_CYCLE:
+ return "Write Protect Until Power Cycle";
+ case NVME_NS_WRITE_PROTECT_PERMANENT:
+ return "Permanent Write Protect";
+ default:
+ return "Reserved";
+ }
+}
+
static void nvme_directive_show_fields(__u8 dtype, __u8 doper,
unsigned int result, unsigned char *buf)
{
@@ -5592,7 +5944,8 @@ static const char *nvme_plm_window(__u32 plm)
}
}
-void nvme_show_lba_status_info(__u32 result) {
+void nvme_show_lba_status_info(__u32 result)
+{
printf("\tLBA Status Information Poll Interval (LSIPI) : %u\n", (result >> 16) & 0xffff);
printf("\tLBA Status Information Report Interval (LSIRI): %u\n", result & 0xffff);
}
@@ -5605,15 +5958,75 @@ static void nvme_show_plm_config(struct nvme_plm_config *plmcfg)
printf("\tDTWIN Time Threshold :%"PRIu64"\n", le64_to_cpu(plmcfg->dtwin_time_thresh));
}
-void nvme_feature_show_fields(enum nvme_feat fid, unsigned int result, unsigned char *buf)
+static char* nvme_show_mi_host_metadata_type_to_string(enum nvme_feat fid, __u8 type)
+{
+ switch (fid) {
+ case NVME_MI_FEAT_CTRL_METADATA:
+ switch (type) {
+ case NVME_MI_CTRL_METADATA_OS_CTRL_NAME:
+ return "Operating System Controller Name";
+ case NVME_MI_CTRL_METADATA_OS_DRIVER_NAME:
+ return "Operating System Driver Name";
+ case NVME_MI_CTRL_METADATA_OS_DRIVER_VER:
+ return "Operating System Driver Version";
+ case NVME_MI_CTRL_METADATA_PRE_BOOT_CTRL_NAME:
+ return "Pre-boot Controller Name";
+ case NVME_MI_CTRL_METADATA_PRE_BOOT_DRIVER_NAME:
+ return "Pre-boot Driver Name";
+ case NVME_MI_CTRL_METADATA_PRE_BOOT_DRIVER_VER:
+ return "Pre-boot Driver Version";
+ default:
+ return "Unknown Controller Type";
+ }
+ case NVME_MI_FEAT_NS_METADATA:
+ switch (type) {
+ case NVME_MI_NS_METADATA_OS_NS_NAME:
+ return "Operating System Namespace Name";
+ case NVME_MI_NS_METADATA_PRE_BOOT_NS_NAME:
+ return "Pre-boot Namespace Name";
+ default:
+ return "Unknown Namespace Type";
+ }
+ default:
+ return "Unknown Feature";
+ }
+}
+
+static void nvme_show_mi_host_metadata(enum nvme_feat fid,
+ struct nvme_mi_host_metadata *data)
+{
+ struct nvme_mi_host_metadata_element_desc *desc = &data->descs[0];
+ int i;
+ char val[4096];
+ __u16 len;
+
+ printf("\tNum Metadata Element Descriptors: %d\n", data->ndesc);
+ for (i = 0; i < data->ndesc; i++) {
+ len = le16_to_cpu(desc->len);
+ strncpy(val, (char *)desc->val, min(sizeof(val) - 1, len));
+
+ printf("\tElement[%-3d]:\n", i);
+ printf("\t\tType : 0x%02x (%s)\n", desc->type,
+ nvme_show_mi_host_metadata_type_to_string(fid, desc->type));
+ printf("\t\tRevision : %d\n", desc->rev);
+ printf("\t\tLength : %d\n", len);
+ printf("\t\tValue : %s\n", val);
+
+ desc = (struct nvme_mi_host_metadata_element_desc *)
+ &desc->val[desc->len];
+ }
+}
+
+void nvme_feature_show_fields(enum nvme_feat fid, unsigned int result,
+ unsigned char *buf)
{
__u8 field;
uint64_t ull;
switch (fid) {
- case NVME_FEAT_NONE:
- printf("\tFeature Identifier Reserved\n");
- break;
+ case NVME_FEAT_NONE:
+ printf("\tFeature Identifier Reserved\n");
+ break;
case NVME_FEAT_ARBITRATION:
printf("\tHigh Priority Weight (HPW): %u\n", ((result & 0xff000000) >> 24) + 1);
printf("\tMedium Priority Weight (MPW): %u\n", ((result & 0x00ff0000) >> 16) + 1);
@@ -5639,7 +6052,8 @@ void nvme_feature_show_fields(enum nvme_feat fid, unsigned int result, unsigned
printf("\tThreshold Type Select (THSEL): %u - %s\n", field, nvme_feature_temp_type_to_string(field));
field = (result & 0x000f0000) >> 16;
printf("\tThreshold Temperature Select (TMPSEL): %u - %s\n", field, nvme_feature_temp_sel_to_string(field));
- printf("\tTemperature Threshold (TMPTH): %d C\n", (result & 0x0000ffff) - 273);
+ printf("\tTemperature Threshold (TMPTH): %ld C (%u Kelvin)\n",
+ kelvin_to_celsius(result & 0x0000ffff), result & 0x0000ffff);
break;
case NVME_FEAT_ERR_RECOVERY:
printf("\tDeallocated or Unwritten Logical Block Error Enable (DULBE): %s\n", ((result & 0x00010000) >> 16) ? "Enabled":"Disabled");
@@ -5664,6 +6078,7 @@ void nvme_feature_show_fields(enum nvme_feat fid, unsigned int result, unsigned
printf("\tDisable Normal (DN): %s\n", (result & 0x00000001) ? "True":"False");
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("\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");
@@ -5694,10 +6109,10 @@ void nvme_feature_show_fields(enum nvme_feat fid, unsigned int result, unsigned
case NVME_LBA_STATUS_INFO:
nvme_show_lba_status_info(result);
break;
- case NVME_FEAT_ENDURANCE:
- printf("\tEndurance Group Identifier (ENDGID): %u\n", result & 0xffff);
- printf("\tEndurance Group Critical Warnings : %u\n", (result >> 16) & 0xff);
- break;
+ case NVME_FEAT_ENDURANCE:
+ printf("\tEndurance Group Identifier (ENDGID): %u\n", result & 0xffff);
+ printf("\tEndurance Group Critical Warnings : %u\n", (result >> 16) & 0xff);
+ break;
case NVME_FEAT_IOCS_PROFILE:
printf("\tI/O Command Set Comination Index(IOCSCI): %u\n", result & 0x1ff);
break;
@@ -5716,14 +6131,16 @@ void nvme_feature_show_fields(enum nvme_feat fid, unsigned int result, unsigned
printf("\tPersist Through Power Loss (PTPL): %s\n", (result & 0x00000001) ? "True":"False");
break;
case NVME_FEAT_WRITE_PROTECT:
- printf("\tNamespace Write Protect: %s\n", result != NVME_NS_NO_WRITE_PROTECT ? "True" : "False");
+ printf("\tNamespace Write Protect state: %s\n", nvme_show_ns_write_protect_config(result & 0x7));
break;
case NVME_FEAT_TIMESTAMP:
nvme_show_timestamp((struct nvme_timestamp *)buf);
break;
case NVME_FEAT_HCTM:
- printf("\tThermal Management Temperature 1 (TMT1) : %u Kelvin\n", (result >> 16));
- printf("\tThermal Management Temperature 2 (TMT2) : %u Kelvin\n", (result & 0x0000ffff));
+ printf("\tThermal Management Temperature 1 (TMT1) : %u Kelvin (%ld C)\n",
+ result >> 16, kelvin_to_celsius(result >> 16));
+ printf("\tThermal Management Temperature 2 (TMT2) : %u Kelvin (%ld C)\n",
+ result & 0x0000ffff, kelvin_to_celsius(result & 0x0000ffff));
break;
case NVME_FEAT_KATO:
printf("\tKeep Alive Timeout (KATO) in milliseconds: %u\n", result);
@@ -5740,6 +6157,10 @@ void nvme_feature_show_fields(enum nvme_feat fid, unsigned int result, unsigned
case NVME_FEAT_RRL:
printf("\tRead Recovery Level (RRL): %u\n", result & 0xf);
break;
+ case NVME_MI_FEAT_CTRL_METADATA:
+ case NVME_MI_FEAT_NS_METADATA:
+ nvme_show_mi_host_metadata(fid, (struct nvme_mi_host_metadata *)buf);
+ break;
}
}
@@ -5751,8 +6172,8 @@ void nvme_show_lba_status(struct nvme_lba_status *list, unsigned long len,
if (flags & BINARY)
return d_raw((unsigned char *)list, len);
- printf("Number of LBA Status Descriptors(NLSD): %" PRIu64 "\n",
- le64_to_cpu(list->nlsd));
+ printf("Number of LBA Status Descriptors(NLSD): %" PRIu32 "\n",
+ le32_to_cpu(list->nlsd));
printf("Completion Condition(CMPC): %u\n", list->cmpc);
switch (list->cmpc) {
@@ -5791,6 +6212,9 @@ static void nvme_show_list_item(struct nvme_namespace *n)
struct stat st;
int ret;
+ if (!n->ctrl)
+ return;
+
sprintf(path, "%s%s", n->ctrl->path, n->name);
ret = stat(path, &st);
if (ret < 0)
@@ -5847,6 +6271,9 @@ static void nvme_show_details_ns(struct nvme_namespace *n, bool ctrl)
char usage[128];
char format[128];
+ if (!n->ctrl)
+ return;
+
sprintf(usage,"%6.2f %2sB / %6.2f %2sB", nuse, u_suffix,
nsze, s_suffix);
sprintf(format,"%3.0f %2sB + %2d B", (double)lba, l_suffix,
@@ -6063,6 +6490,9 @@ static void json_simple_ns(struct nvme_namespace *n, struct json_object *devices
char *devnode;
struct stat st;
+ if (!n->ctrl)
+ return;
+
if (asprintf(&devnode, "%s%s", n->ctrl->path, n->name) < 0)
return;