]> www.infradead.org Git - users/hch/nvme-cli.git/commitdiff
nvme: Support raw_binary and json format for show-regs
authorMinwoo Im <minwoo.im.dev@gmail.com>
Sat, 6 Apr 2019 21:01:17 +0000 (06:01 +0900)
committerMinwoo Im <minwoo.im.dev@gmail.com>
Sat, 6 Apr 2019 21:06:54 +0000 (06:06 +0900)
  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 <minwoo.im.dev@gmail.com>
nvme-print.c
nvme-print.h
nvme.c

index cfe88e3bdc9f169fe6c28cb098a40c886e6f9fa7..b42c3448bbfff3bffe3cae282f7ddbf9d11e6a88 100644 (file)
@@ -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;
index 20443082ce401f67d34ae9ecab45d0f260a95629..e4dc9187c59d9dc72a1a89b71ecc2b61e7cb9db1 100644 (file)
@@ -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 dca029adb7de20ec2b30d303e7f4e6e21eeb5628..9026503888dd9b7c6921aa093c4b4c66bb54e104 100644 (file)
--- 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);