]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
nvme-cli: add identify secondary controller list
authorKenneth Heitke <kenneth.heitke@intel.com>
Wed, 24 Apr 2019 23:32:20 +0000 (17:32 -0600)
committerKenneth Heitke <kenneth.heitke@intel.com>
Thu, 25 Apr 2019 20:13:25 +0000 (14:13 -0600)
Signed-off-by: Kenneth Heitke <kenneth.heitke@intel.com>
linux/nvme.h
nvme-builtin.h
nvme-ioctl.c
nvme-ioctl.h
nvme-print.c
nvme-print.h
nvme.c
nvme.h

index 68000eb8c1dc42fd6d886ed748c1f651862aa6de..a1422a7764fecd06ff86486f9959d3ad1b60f263 100644 (file)
@@ -355,6 +355,7 @@ enum {
        NVME_ID_CNS_NS_PRESENT          = 0x11,
        NVME_ID_CNS_CTRL_NS_LIST        = 0x12,
        NVME_ID_CNS_CTRL_LIST           = 0x13,
+       NVME_ID_CNS_SCNDRY_CTRL_LIST    = 0x15,
 };
 
 enum {
index 2eb34cbaca62e7ac8741e2cb4761df4f408b625d..a203a5c025f737364eaf109cf9ea79f6a58452a1 100644 (file)
@@ -68,6 +68,7 @@ COMMAND_LIST(
        ENTRY("dir-receive", "Submit a Directive Receive command, return results", dir_receive)
        ENTRY("dir-send", "Submit a Directive Send command, return results", dir_send)
        ENTRY("virt-mgmt", "Manage Flexible Resources between Primary and Secondary Controller ", virtual_mgmt)
+       ENTRY("list-secondary", "List Secondary Controllers associated with a Primary Controller", list_secondary_ctrl)
 );
 
 #endif
index 75bf9fad79c5846e2248e433f7575977110c5148..83740f225af8effb64cf82c95a89790ac4f4041b 100644 (file)
@@ -370,6 +370,11 @@ int nvme_identify_ctrl_list(int fd, __u32 nsid, __u16 cntid, void *data)
        return nvme_identify(fd, nsid, (cntid << 16) | cns, data);
 }
 
+int nvme_identify_secondary_ctrl_list(int fd, __u32 nsid, __u16 cntid, void *data)
+{
+       return nvme_identify(fd, nsid, (cntid << 16) | NVME_ID_CNS_SCNDRY_CTRL_LIST, data);
+}
+
 int nvme_identify_ns_descs(int fd, __u32 nsid, void *data)
 {
 
index c82149c7aa7626a6aa54e7cb58a8d1d742d0abd7..f4553e0bd264d8b24b57d553bcb1a6a7b0b6dcd8 100644 (file)
@@ -75,6 +75,7 @@ int nvme_identify_ns_list(int fd, __u32 nsid, bool all, void *data);
 int nvme_identify_ctrl_list(int fd, __u32 nsid, __u16 cntid, void *data);
 int nvme_identify_ns_descs(int fd, __u32 nsid, void *data);
 int nvme_identify_nvmset(int fd, __u16 nvmset_id, void *data);
+int nvme_identify_secondary_ctrl_list(int fd, __u32 nsid, __u16 cntid, void *data);
 int nvme_get_log13(int fd, __u32 nsid, __u8 log_id, __u8 lsp, __u64 lpo,
                   __u16 group_id, bool rae, __u32 data_len, void *data);
 int nvme_get_log(int fd, __u32 nsid, __u8 log_id, bool rae,
index 8b01c08aa757f0504686596bd6c3caf6f67fed75..5ef29323e5af7d30e8fcf09098adba9b23f8c17c 100644 (file)
@@ -7,6 +7,7 @@
 #include "json.h"
 #include "nvme-models.h"
 #include "suffix.h"
+#include "common.h"
 
 static const char *nvme_ana_state_to_string(enum nvme_ana_state state)
 {
@@ -1144,6 +1145,69 @@ void json_nvme_id_nvmset(struct nvme_id_nvmset *nvmset, const char *devname)
        json_free_object(root);
 }
 
+void show_nvme_list_secondary_ctrl(const struct nvme_secondary_controllers_list *sc_list, __u32 count)
+{
+       int i;
+       __u16 num = le16_to_cpu(sc_list->num);
+       __u32 entries = min(num, count);
+
+       static const char * const state_desc[] = { "Offline", "Online" };
+       const struct nvme_secondary_controller_entry *sc_entry = &sc_list->sc_entry[0];
+
+       printf("Identify Secondary Controller List:\n");
+       printf("   NUMID       : Number of Identifiers           : %d\n", num);
+
+       for (i = 0; i < entries; i++) {
+               printf("   SCEntry[%-3d]:\n", i);
+               printf("................\n");
+               printf("     SCID      : Secondary Controller Identifier : 0x%.04x\n",
+                               le16_to_cpu(sc_entry[i].scid));
+               printf("     PCID      : Primary Controller Identifier   : 0x%.04x\n",
+                               le16_to_cpu(sc_entry[i].pcid));
+               printf("     SCS       : Secondary Controller State      : 0x%.04x (%s)\n",
+                               le16_to_cpu(sc_entry[i].scs),
+                               state_desc[le16_to_cpu(sc_entry[i].scs) & 0x1]);
+               printf("     VFN       : Virtual Function Number         : 0x%.04x\n",
+                               le16_to_cpu(sc_entry[i].vfn));
+               printf("     NVQ       : Num VQ Flex Resources Assigned  : 0x%.04x\n",
+                               le16_to_cpu(sc_entry[i].nvq));
+               printf("     NVI       : Num VI Flex Resources Assigned  : 0x%.04x\n",
+                               le16_to_cpu(sc_entry[i].nvi));
+       }
+}
+
+void json_nvme_list_secondary_ctrl(const struct nvme_secondary_controllers_list *sc_list, __u32 count)
+{
+       int i;
+       struct json_object *root;
+       struct json_array *entries;
+       __u32 nent = min(le16_to_cpu(sc_list->num), count);
+       const struct nvme_secondary_controller_entry *sc_entry = &sc_list->sc_entry[0];
+
+       root = json_create_object();
+
+       json_object_add_value_int(root, "num", nent);
+
+       entries = json_create_array();
+       for (i = 0; i < nent; i++) {
+               struct json_object *entry = json_create_object();
+
+               json_object_add_value_int(entry, "secondary-controller-identifier", le16_to_cpu(sc_entry[i].scid));
+               json_object_add_value_int(entry, "primary-controller-identifier", le16_to_cpu(sc_entry[i].pcid));
+               json_object_add_value_int(entry, "secondary-controller-state",  le16_to_cpu(sc_entry[i].scs));
+               json_object_add_value_int(entry, "virtual-function-number",  le16_to_cpu(sc_entry[i].vfn));
+               json_object_add_value_int(entry, "num-virtual-queues",  le16_to_cpu(sc_entry[i].nvq));
+               json_object_add_value_int(entry, "num-virtual-interrupts",  le16_to_cpu(sc_entry[i].nvi));
+               json_array_add_value_object(entries, entry);
+       }
+
+       json_object_add_value_array(root, "secondary-controllers", entries);
+
+       json_print_object(root, NULL);
+       printf("\n");
+       json_free_object(root);
+}
+
 void show_error_log(struct nvme_error_log_page *err_log, int entries, const char *devname)
 {
        int i;
index e4dc9187c59d9dc72a1a89b71ecc2b61e7cb9db1..4c2af7b5fe303724f6b0c5a61e2fbaa9e22ef9b5 100644 (file)
@@ -38,6 +38,7 @@ void show_nvme_id_ns_descs(void *data);
 void show_list_items(struct list_item *list_items, unsigned len);
 void show_nvme_subsystem_list(struct subsys_list_item *slist, int n);
 void show_nvme_id_nvmset(struct nvme_id_nvmset *nvmset);
+void show_nvme_list_secondary_ctrl(const struct nvme_secondary_controllers_list *sc_list, __u32 count);
 
 void nvme_feature_show_fields(__u32 fid, unsigned int result, unsigned char *buf);
 void nvme_directive_show_fields(__u8 dtype, __u8 doper, unsigned int result, unsigned char *buf);
@@ -65,6 +66,6 @@ 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);
-
+void json_nvme_list_secondary_ctrl(const struct nvme_secondary_controllers_list *sc_list, __u32 count);
 
 #endif
diff --git a/nvme.c b/nvme.c
index 102d5e9f0ab3c9d7fdc5ed0b4d4bb95c9e74ed28..52d50aba25454b4e931c2d1e099deb32acbac0de 100644 (file)
--- a/nvme.c
+++ b/nvme.c
@@ -2268,6 +2268,84 @@ static int virtual_mgmt(int argc, char **argv, struct command *cmd, struct plugi
 
 }
 
+static int list_secondary_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin)
+{
+       const char *desc = "Show secondary controller list associated with the primary controller "\
+               "of the given device.";
+       const char *controller = "lowest controller identifier to display";
+       const char *namespace_id = "optional namespace attached to controller";
+       const char *num_entries = "number of entries to retrieve";
+       int err, fmt, fd;
+       struct nvme_secondary_controllers_list *sc_list;
+
+       _Static_assert(sizeof(struct nvme_secondary_controller_entry) != NVME_IDENTIFY_DATA_SIZE, "bad structure size");
+
+       struct config {
+               __u16 cntid;
+               __u32 num_entries;
+               __u32 namespace_id;
+               char *output_format;
+       };
+
+       struct config cfg = {
+               .cntid = 0,
+               .namespace_id = 0,
+               .output_format = "normal",
+               .num_entries = ARRAY_SIZE(sc_list->sc_entry),
+       };
+
+       const struct argconfig_commandline_options command_line_options[] = {
+               {"cntid",         'c', "NUM", CFG_SHORT,    &cfg.cntid,         required_argument, controller},
+               {"namespace-id",  'n', "NUM", CFG_POSITIVE, &cfg.namespace_id,  required_argument, namespace_id},
+               {"num-entries",   'e', "NUM", CFG_POSITIVE, &cfg.num_entries,   required_argument, num_entries},
+               {"output-format", 'o', "FMT", CFG_STRING,   &cfg.output_format, required_argument, output_format},
+               {NULL}
+       };
+
+       fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg));
+       if (fd < 0)
+               return fd;
+
+       fmt = validate_output_format(cfg.output_format);
+       if (fmt < 0) {
+               err = fmt;
+               goto close_fd;
+       }
+
+       if (!cfg.num_entries) {
+               fprintf(stderr, "non-zero num-entries is required param\n");
+               err = -EINVAL;
+               goto close_fd;
+       }
+
+       if (posix_memalign((void *)&sc_list, getpagesize(), sizeof(*sc_list))) {
+               fprintf(stderr, "can not allocate controller list payload\n");
+               err = -ENOMEM;
+               goto close_fd;
+       }
+
+       err = nvme_identify_secondary_ctrl_list(fd, cfg.namespace_id, cfg.cntid, sc_list);
+       if (!err) {
+               if (fmt == BINARY)
+                       d_raw((unsigned char *)sc_list, sizeof(*sc_list));
+               else if (fmt == JSON)
+                       json_nvme_list_secondary_ctrl(sc_list, cfg.num_entries);
+               else
+                       show_nvme_list_secondary_ctrl(sc_list, cfg.num_entries);
+       } else if (err > 0)
+               fprintf(stderr, "NVMe Status:%s(%x) cntid:%d\n",
+                       nvme_status_to_string(err), err, cfg.cntid);
+       else
+               perror("id secondary controller list");
+
+       free(sc_list);
+
+close_fd:
+       close(fd);
+
+       return err;
+}
+
 static int device_self_test(int argc, char **argv, struct command *cmd, struct plugin *plugin)
 {
        const char *desc  = "Implementing the device self-test feature"\
diff --git a/nvme.h b/nvme.h
index 685d179943536ad098648e8a8a5718a5c32f15b6..71e2f4d2bbf00f95480301a2a7a40a9f8e89a8d3 100644 (file)
--- a/nvme.h
+++ b/nvme.h
@@ -87,6 +87,23 @@ struct nvme_controller_list {
        __le16 identifier[];
 };
 
+struct nvme_secondary_controller_entry {
+       __le16 scid;    /* Secondary Controller Identifier */
+       __le16 pcid;    /* Primary Controller Identifier */
+       __u8   scs;     /* Secondary Controller State */
+       __u8   rsvd5[3];
+       __le16 vfn;     /* Virtual Function Number */
+       __le16 nvq;     /* Number of VQ Flexible Resources Assigned */
+       __le16 nvi;     /* Number of VI Flexible Resources Assigned */
+       __u8   rsvd14[18];
+};
+
+struct nvme_secondary_controllers_list {
+       __u8   num;
+       __u8   rsvd[31];
+       struct nvme_secondary_controller_entry sc_entry[127];
+};
+
 struct nvme_bar_cap {
        __u16   mqes;
        __u8    ams_cqr;