From: Tokunori Ikegami Date: Fri, 13 Oct 2023 06:58:33 +0000 (+0900) Subject: nvme-print-json: Add single_property printf function X-Git-Tag: v2.7~88 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=1dbcadb244165cabde017dcddb6e87b8eaa4df00;p=users%2Fsagi%2Fnvme-cli.git nvme-print-json: Add single_property printf function Signed-off-by: Tokunori Ikegami --- diff --git a/nvme-print-json.c b/nvme-print-json.c index c0fbbbd9..07a6463d 100644 --- a/nvme-print-json.c +++ b/nvme-print-json.c @@ -11,14 +11,68 @@ #include "common.h" #define ERROR_MSG_LEN 100 -#define STR_LEN 40 +#define STR_LEN 100 #define BUF_LEN 320 #define VAL_LEN 4096 #define BYTE_TO_BIT(byte) ((byte) * 8) +#define POWER_OF_TWO(exponent) (1 << (exponent)) +#define MS500_TO_SEC(time) ((time) / 2) + +#define array_add_obj(o, k) json_array_add_value_object(o, k); +#define obj_add_str(o, k, v) json_object_add_value_string(o, k, v) +#define root_add_array(k, v) json_object_add_value_array(root, k, v) +#define root_add_int_secs(k, v) obj_add_int_secs(root, k, v) +#define root_add_prix64(k, v) obj_add_prix64(root, k, v) +#define root_add_str(k, v) json_object_add_value_string(root, k, v) +#define root_add_uint(k, v) json_object_add_value_uint(root, k, v) +#define root_add_uint_0x(k, v) obj_add_uint_0x(root, k, v) +#define root_add_uint_x(k, v) obj_add_uint_x(root, k, v) static const uint8_t zero_uuid[16] = { 0 }; static struct print_ops json_print_ops; +static const char *supported = "Supported"; +static const char *not_supported = "Not Supported"; +static const char *yes = "Yes"; +static const char *no = "No"; +static const char *enabled = "Enabled"; +static const char *disabled = "Disabled"; +static const char *reserved = "Reserved"; +static const char *true_str = "True"; +static const char *false_str = "False"; + +static void obj_add_uint_x(struct json_object *o, const char *k, __u32 v) +{ + char str[STR_LEN]; + + sprintf(str, "%x", v); + obj_add_str(o, k, str); +} + +static void obj_add_uint_0x(struct json_object *o, const char *k, __u32 v) +{ + char str[STR_LEN]; + + sprintf(str, "0x%02x", v); + obj_add_str(o, k, str); +} + +static void obj_add_prix64(struct json_object *o, const char *k, uint64_t v) +{ + char str[STR_LEN]; + + sprintf(str, "%"PRIx64"", v); + obj_add_str(o, k, str); +} + +static void obj_add_int_secs(struct json_object *o, const char *k, int v) +{ + char str[STR_LEN]; + + sprintf(str, "%d secs", v); + obj_add_str(o, k, str); +} + static void json_print(struct json_object *root) { json_print_object(root, NULL); @@ -693,6 +747,255 @@ add: json_print(root); } +static void json_registers_cap(struct nvme_bar_cap *cap, struct json_object *root) +{ + char json_str[STR_LEN]; + struct json_object *cssa = json_create_array(); + struct json_object *csso = json_create_object(); + struct json_object *amsa = json_create_array(); + struct json_object *amso = json_create_object(); + + sprintf(json_str, "%"PRIx64"", *(uint64_t *)cap); + json_object_add_value_string(root, "cap", json_str); + + root_add_str("Controller Ready With Media Support (CRWMS)", + cap->crwms ? supported : not_supported); + root_add_str("Controller Ready Independent of Media Support (CRIMS)", + cap->crims ? supported : not_supported); + root_add_str("NVM Subsystem Shutdown Supported (NSSS)", + cap->nsss ? supported : not_supported); + root_add_str("Controller Memory Buffer Supported (CMBS):", + cap->cmbs ? supported : not_supported); + root_add_str("Persistent Memory Region Supported (PMRS)", + cap->pmrs ? supported : not_supported); + + sprintf(json_str, "%u bytes", 1 << (12 + cap->mpsmax)); + root_add_str("Memory Page Size Maximum (MPSMAX)", json_str); + + sprintf(json_str, "%u bytes", 1 << (12 + cap->mpsmin)); + root_add_str("Memory Page Size Minimum (MPSMIN)", json_str); + + root_add_str("Controller Power Scope (CPS)", !cap->cps ? "Not Reported" : cap->cps == 1 ? + "Controller scope" : cap->cps == 2 ? "Domain scope" : "NVM subsystem scope"); + root_add_str("Boot Partition Support (BPS)", cap->bps ? yes : no); + + root_add_array("Command Sets Supported (CSS)", cssa); + obj_add_str(csso, "NVM command set is %s", cap->css & 1 ? supported : not_supported); + obj_add_str(csso, "One or more I/O Command Sets are %s", + cap->css & 0x40 ? supported : not_supported); + obj_add_str(csso, cap->css & 0x80 ? "Only Admin Command Set" : "I/O Command Set", + supported); + array_add_obj(cssa, csso); + + root_add_str("NVM Subsystem Reset Supported (NSSRS): %s", cap->nssrs ? yes : no); + + sprintf(json_str, "%u bytes", 1 << (2 + cap->dstrd)); + root_add_str("Doorbell Stride (DSTRD)", json_str); + + root_add_uint("Timeout (TO): %u ms", cap->to * 500); + + root_add_array("Arbitration Mechanism Supported (AMS)", amsa); + obj_add_str(amso, "Weighted Round Robin with Urgent Priority Class", + cap->ams & 2 ? supported : not_supported); + array_add_obj(amsa, amso); + + root_add_str("Contiguous Queues Required (CQR)", cap->cqr ? yes : no); + root_add_uint("Maximum Queue Entries Supported (MQES)", cap->mqes + 1); +} + +static void json_registers_version(__u32 vs, struct json_object *root) +{ + char json_str[STR_LEN]; + + sprintf(json_str, "%x", vs); + root_add_str("version", json_str); + + sprintf(json_str, "%d.%d", (vs & 0xffff0000) >> 16, (vs & 0x0000ff00) >> 8); + root_add_str("NVMe specification", json_str); +} + +static void json_registers_cc_ams (__u8 ams, struct json_object *root) +{ + char json_str[STR_LEN]; + + switch (ams) { + case 0: + sprintf(json_str, "Round Robin"); + break; + case 1: + sprintf(json_str, "Weighted Round Robin with Urgent Priority Class"); + break; + case 7: + sprintf(json_str, "Vendor Specific"); + break; + default: + sprintf(json_str, "Reserved"); + break; + } + + root_add_str("Arbitration Mechanism Selected (AMS)", json_str); +} + +static void json_registers_cc_shn (__u8 shn, struct json_object *root) +{ + char json_str[STR_LEN]; + + switch (shn) { + case 0: + sprintf(json_str, "No notification; no effect"); + break; + case 1: + sprintf(json_str, "Normal shutdown notification"); + break; + case 2: + sprintf(json_str, "Abrupt shutdown notification"); + break; + default: + sprintf(json_str, "Reserved"); + break; + } + + root_add_str("Shutdown Notification (SHN)", json_str); +} + +static void json_registers_cc(__u32 cc, struct json_object *root) +{ + char json_str[STR_LEN]; + + sprintf(json_str, "%x", cc); + root_add_str("cc", json_str); + + root_add_str("Controller Ready Independent of Media Enable (CRIME)", + NVME_CC_CRIME(cc) ? enabled : disabled); + + sprintf(json_str, "%u bytes", POWER_OF_TWO(NVME_GET(cc, CC_IOCQES))); + root_add_str("I/O Completion Queue Entry Size (IOCQES): ", json_str); + + sprintf(json_str, "%u bytes", POWER_OF_TWO(NVME_GET(cc, CC_IOSQES))); + root_add_str("I/O Submission Queue Entry Size (IOSQES)", json_str); + + json_registers_cc_shn((cc & 0xc000) >> NVME_CC_SHN_SHIFT, root); + json_registers_cc_ams((cc & 0x3800) >> NVME_CC_AMS_SHIFT, root); + + sprintf(json_str, "%u bytes", POWER_OF_TWO(12 + NVME_GET(cc, CC_MPS))); + root_add_str("Memory Page Size (MPS)", json_str); + + root_add_str("I/O Command Set Selected (CSS)", (cc & 0x70) == 0x00 ? "NVM Command Set" : + (cc & 0x70) == 0x60 ? "All supported I/O Command Sets" : + (cc & 0x70) == 0x70 ? "Admin Command Set only" : reserved); + root_add_str("Enable (EN)", cc & 1 ? yes : no); +} + +static void json_registers_csts_shst(__u8 shst, struct json_object *root) +{ + char json_str[STR_LEN]; + + switch (shst) { + case 0: + sprintf(json_str, "Normal operation (no shutdown has been requested)"); + break; + case 1: + sprintf(json_str, "Shutdown processing occurring"); + break; + case 2: + sprintf(json_str, "Shutdown processing complete"); + break; + default: + sprintf(json_str, "Reserved"); + break; + } + root_add_str("Shutdown Status (SHST)", json_str); +} + +static void json_registers_csts(__u32 csts, struct json_object *root) +{ + root_add_uint_x("csts", csts); + + root_add_str("Processing Paused (PP)", csts & 0x20 ? yes : no); + root_add_str("NVM Subsystem Reset Occurred (NSSRO)", csts & 0x10 ? yes : no); + + json_registers_csts_shst((csts & 0xc) >> 2, root); + + root_add_str("Controller Fatal Status (CFS)", csts & 2 ? true_str : false_str); + root_add_str("Ready (RDY)", csts & 1 ? yes : no); +} + +static void json_registers_nssr(__u32 nssr, struct json_object *root) +{ + root_add_uint_x("nssr", nssr); + root_add_uint("NVM Subsystem Reset Control (NSSRC)", nssr); +} + +static void json_registers_crto(__u32 crto, struct json_object *root) +{ + root_add_uint_x("crto", crto); + + root_add_int_secs("CRIMT", MS500_TO_SEC(NVME_CRTO_CRIMT(crto))); + root_add_int_secs("CRWMT", MS500_TO_SEC(NVME_CRTO_CRWMT(crto))); +} + +static void json_registers_unknown(int offset, uint64_t value64, struct json_object *root) +{ + root_add_uint_0x("unknown property", offset); + root_add_str("name", nvme_register_to_string(offset)); + root_add_prix64("value", value64); +} + +static void json_single_property_human(int offset, uint64_t value64, struct json_object *root) +{ + uint32_t value32 = (uint32_t)value64; + + switch (offset) { + case NVME_REG_CAP: + json_registers_cap((struct nvme_bar_cap *)&value64, root); + break; + case NVME_REG_VS: + json_registers_version(value32, root); + break; + case NVME_REG_CC: + json_registers_cc(value32, root); + break; + case NVME_REG_CSTS: + json_registers_csts(value32, root); + break; + case NVME_REG_NSSR: + json_registers_nssr(value32, root); + break; + case NVME_REG_CRTO: + json_registers_crto(value32, root); + break; + default: + json_registers_unknown(offset, value64, root); + break; + } +} + +static void json_single_property(int offset, uint64_t value64) +{ + struct json_object *root = json_create_object(); + char json_str[STR_LEN]; + int human = json_print_ops.flags & VERBOSE; + uint32_t value32 = (uint32_t)value64; + + if (human) { + json_single_property_human(offset, value64, root); + } else { + sprintf(json_str, "0x%02x", offset); + json_object_add_value_string(root, "property", json_str); + + json_object_add_value_string(root, "name", nvme_register_to_string(offset)); + + if (nvme_is_64bit_reg(offset)) + sprintf(json_str, "%"PRIx64"", value64); + else + sprintf(json_str, "%x", value32); + + json_object_add_value_string(root, "value", json_str); + } + + json_print(root); +} + struct json_object* json_effects_log(enum nvme_csi csi, struct nvme_cmd_effects_log *effects_log) { @@ -3820,7 +4123,7 @@ static struct print_ops json_print_ops = { .secondary_ctrl_list = json_nvme_list_secondary_ctrl, .select_result = json_select_result, .self_test_log = json_self_test_log, - .single_property = NULL, + .single_property = json_single_property, .smart_log = json_smart_log, .supported_cap_config_list_log = json_supported_cap_config_log, .supported_log_pages = json_support_log, diff --git a/nvme-print-stdout.c b/nvme-print-stdout.c index 2f0c8a4b..39a59237 100644 --- a/nvme-print-stdout.c +++ b/nvme-print-stdout.c @@ -26,27 +26,6 @@ static const char dash[100] = {[0 ... 99] = '-'}; static struct print_ops stdout_print_ops; -struct nvme_bar_cap { - __u16 mqes; - __u8 cqr:1; - __u8 ams:2; - __u8 rsvd19:5; - __u8 to; - __u16 dstrd:4; - __u16 nssrs:1; - __u16 css:8; - __u16 bps:1; - __u8 cps:2; - __u8 mpsmin:4; - __u8 mpsmax:4; - __u8 pmrs:1; - __u8 cmbs:1; - __u8 nsss:1; - __u8 crwms:1; - __u8 crims:1; - __u8 rsvd61:3; -}; - static const char *subsys_key(const struct nvme_subsystem *s) { return nvme_subsystem_get_name((nvme_subsystem_t)s); @@ -1246,10 +1225,8 @@ static void stdout_registers_csts(__u32 csts) static void stdout_registers_crto(__u32 crto) { - printf("\tCRIMT : %d secs\n", - NVME_CRTO_CRIMT(crto)/2 ); - printf("\tCRWMT : %d secs\n", - NVME_CRTO_CRWMT(crto)/2 ); + printf("\tCRIMT : %d secs\n", NVME_CRTO_CRIMT(crto) / 2); + printf("\tCRWMT : %d secs\n", NVME_CRTO_CRWMT(crto) / 2); } static void stdout_registers_aqa(__u32 aqa) @@ -1612,24 +1589,18 @@ void stdout_ctrl_registers(void *bar, bool fabrics) static void stdout_single_property(int offset, uint64_t value64) { int human = stdout_print_ops.flags & VERBOSE; - - uint32_t value32; + uint32_t value32 = (uint32_t)value64; if (!human) { if (nvme_is_64bit_reg(offset)) printf("property: 0x%02x (%s), value: %"PRIx64"\n", - offset, nvme_register_to_string(offset), - value64); + offset, nvme_register_to_string(offset), value64); else printf("property: 0x%02x (%s), value: %x\n", offset, - nvme_register_to_string(offset), - (uint32_t) value64); - + nvme_register_to_string(offset), value32); return; } - value32 = (uint32_t) value64; - switch (offset) { case NVME_REG_CAP: printf("cap : %"PRIx64"\n", value64); @@ -1649,8 +1620,7 @@ static void stdout_single_property(int offset, uint64_t value64) break; case NVME_REG_NSSR: printf("nssr : %x\n", value32); - printf("\tNVM Subsystem Reset Control (NSSRC): %u\n\n", - value32); + printf("\tNVM Subsystem Reset Control (NSSRC): %u\n\n", value32); break; case NVME_REG_CRTO: printf("crto : %x\n", value32); @@ -1658,7 +1628,7 @@ static void stdout_single_property(int offset, uint64_t value64) break; default: printf("unknown property: 0x%02x (%s), value: %"PRIx64"\n", - offset, nvme_register_to_string(offset), value64); + offset, nvme_register_to_string(offset), value64); break; } } diff --git a/nvme-print.h b/nvme-print.h index c05576b7..1eee46b2 100644 --- a/nvme-print.h +++ b/nvme-print.h @@ -100,6 +100,27 @@ struct print_ops { enum nvme_print_flags flags; }; +struct nvme_bar_cap { + __u16 mqes; + __u8 cqr:1; + __u8 ams:2; + __u8 rsvd19:5; + __u8 to; + __u16 dstrd:4; + __u16 nssrs:1; + __u16 css:8; + __u16 bps:1; + __u8 cps:2; + __u8 mpsmin:4; + __u8 mpsmax:4; + __u8 pmrs:1; + __u8 cmbs:1; + __u8 nsss:1; + __u8 crwms:1; + __u8 crims:1; + __u8 rsvd61:3; +}; + #ifdef CONFIG_JSONC struct print_ops *nvme_get_json_print_ops(enum nvme_print_flags flags);