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 {
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
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)
{
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,
#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)
{
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;
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);
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
}
+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"\
__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;