From: Minwoo Im Date: Sat, 6 Apr 2019 21:01:17 +0000 (+0900) Subject: nvme: Support raw_binary and json format for show-regs X-Git-Tag: v1.8~5^2~1 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=6317d3841e984533f055c77166c9e170f979df37;p=users%2Fsagi%2Fnvme-cli.git nvme: Support raw_binary and json format for show-regs Somebody might want to compare entire controller registers in a raw binary format to check controller status or some of configurations. It also can be needed to print out JSON format for easily parsing. This patch introduces JSON and RAW_BINARY print format with a general --output-format argument. This will have "normal" value by default, and also support "json" and "binary". We don't care about whether the given "fabrics" argument in json_ctrl_registers() because all the reserved registers and fields are to be returned as 0x0 as specified in NVMe-oF "Property Definitions" section. Signed-off-by: Minwoo Im --- diff --git a/nvme-print.c b/nvme-print.c index cfe88e3b..b42c3448 100644 --- a/nvme-print.c +++ b/nvme-print.c @@ -3075,6 +3075,48 @@ static inline __u64 mmio_read64(void *addr) return le32_to_cpu(*p) | ((uint64_t)le32_to_cpu(*(p + 1)) << 32); } +void json_ctrl_registers(void *bar) +{ + uint64_t cap, asq, acq, bpmbl; + uint32_t vs, intms, intmc, cc, csts, nssr, aqa, cmbsz, cmbloc, + bpinfo, bprsel; + struct json_object *root; + + cap = mmio_read64(bar + NVME_REG_CAP); + vs = mmio_read32(bar + NVME_REG_VS); + intms = mmio_read32(bar + NVME_REG_INTMS); + intmc = mmio_read32(bar + NVME_REG_INTMC); + cc = mmio_read32(bar + NVME_REG_CC); + csts = mmio_read32(bar + NVME_REG_CSTS); + nssr = mmio_read32(bar + NVME_REG_NSSR); + aqa = mmio_read32(bar + NVME_REG_AQA); + asq = mmio_read64(bar + NVME_REG_ASQ); + acq = mmio_read64(bar + NVME_REG_ACQ); + cmbloc = mmio_read32(bar + NVME_REG_CMBLOC); + cmbsz = mmio_read32(bar + NVME_REG_CMBSZ); + bpinfo = mmio_read32(bar + NVME_REG_BPINFO); + bprsel = mmio_read32(bar + NVME_REG_BPRSEL); + bpmbl = mmio_read64(bar + NVME_REG_BPMBL); + + root = json_create_object(); + json_object_add_value_uint(root, "cap", cap); + json_object_add_value_int(root, "vs", vs); + json_object_add_value_int(root, "intms", intms); + json_object_add_value_int(root, "intmc", intmc); + json_object_add_value_int(root, "cc", cc); + json_object_add_value_int(root, "csts", csts); + json_object_add_value_int(root, "nssr", nssr); + json_object_add_value_int(root, "aqa", aqa); + json_object_add_value_uint(root, "asq", asq); + json_object_add_value_uint(root, "acq", acq); + json_object_add_value_int(root, "cmbloc", cmbloc); + json_object_add_value_int(root, "cmbsz", cmbsz); + json_object_add_value_int(root, "bpinfo", bpinfo); + json_object_add_value_int(root, "bprsel", bprsel); + json_object_add_value_uint(root, "bpmbl", bpmbl); + json_print_object(root, NULL); +} + void show_ctrl_registers(void *bar, unsigned int mode, bool fabrics) { uint64_t cap, asq, acq, bpmbl; diff --git a/nvme-print.h b/nvme-print.h index 20443082..e4dc9187 100644 --- a/nvme-print.h +++ b/nvme-print.h @@ -64,6 +64,7 @@ void json_nvme_id_ns_descs(void *data); void json_print_nvme_subsystem_list(struct subsys_list_item *slist, int n); void json_self_test_log(struct nvme_self_test_log *self_test, const char *devname); void json_nvme_id_nvmset(struct nvme_id_nvmset *nvmset, const char *devname); +void json_ctrl_registers(void *bar); #endif diff --git a/nvme.c b/nvme.c index dca029ad..90265038 100644 --- a/nvme.c +++ b/nvme.c @@ -2879,21 +2879,26 @@ static int show_registers(int argc, char **argv, struct command *cmd, struct plu { const char *desc = "Reads and shows the defined NVMe controller registers "\ "in binary or human-readable format"; - const char *human_readable = "show info in readable format"; + const char *human_readable = "show info in readable format in case of "\ + "output_format == normal"; void *bar; - int fd, err; + int fd, err, fmt; bool fabrics = true; + const int reg_size = 0x50; /* 00h to 4Fh */ struct config { int human_readable; + char *output_format; }; struct config cfg = { .human_readable = 0, + .output_format = "normal", }; const struct argconfig_commandline_options command_line_options[] = { {"human-readable", 'H', "", CFG_NONE, &cfg.human_readable, no_argument, human_readable}, + {"output-format", 'o', "FMT", CFG_STRING, &cfg.output_format, required_argument, output_format}, {NULL} }; @@ -2901,6 +2906,20 @@ static int show_registers(int argc, char **argv, struct command *cmd, struct plu if (fd < 0) return fd; + fmt = validate_output_format(cfg.output_format); + if (fmt < 0) { + fprintf(stderr, "Invalid argument --output-format=%s\n", + cfg.output_format); + err = -fmt; + goto close_fd; + } + + if (cfg.human_readable && fmt != NORMAL) { + fprintf(stderr, "Only --output-format=normal supports -H\n"); + err = EINVAL; + goto close_fd; + } + err = nvme_get_properties(fd, &bar); if (err) { bar = get_registers(); @@ -2912,7 +2931,13 @@ static int show_registers(int argc, char **argv, struct command *cmd, struct plu err = ENODEV; goto close_fd; } - show_ctrl_registers(bar, cfg.human_readable ? HUMAN : 0, fabrics); + + if (fmt == BINARY) + d_raw((unsigned char *) bar, reg_size); + else if (fmt == JSON) + json_ctrl_registers(bar); + else + show_ctrl_registers(bar, cfg.human_readable ? HUMAN : 0, fabrics); if (fabrics) free(bar);