__u8 vs[1024];
};
+struct nvme_pri_ctrl_caps {
+ __le16 cntlid;
+ __le16 portid;
+ __u8 crt;
+ __u8 rsvd5[27];
+ __le32 vqfrt;
+ __le32 vqrfa;
+ __le16 vqrfap;
+ __le16 vqprt;
+ __le16 vqfrsm;
+ __le16 vqgran;
+ __u8 rsvd48[16];
+ __le32 vifrt;
+ __le32 virfa;
+ __u16 virfap;
+ __u16 viprt;
+ __u16 vifrsm;
+ __u16 vigran;
+ __u8 rsvd80[4016];
+};
+
enum {
NVME_CTRL_ONCS_COMPARE = 1 << 0,
NVME_CTRL_ONCS_WRITE_UNCORRECTABLE = 1 << 1,
NVME_ID_CNS_NS_PRESENT = 0x11,
NVME_ID_CNS_CTRL_NS_LIST = 0x12,
NVME_ID_CNS_CTRL_LIST = 0x13,
+ NVME_ID_CNS_PRIMARY_CTRL_CAPS = 0x14,
NVME_ID_CNS_SCNDRY_CTRL_LIST = 0x15,
NVME_ID_CNS_NS_GRANULARITY = 0x16,
NVME_ID_CNS_UUID_LIST = 0x17,
__le16 identifier[2047];
};
+struct nvme_primary_ctrl_caps {
+ __le16 cntlid; /* Controller Identifier */
+ __le16 portid; /* Port Identifier */
+ __u8 crt; /* Controller Resource Types */
+ __u8 rsvd5[27];
+ __le32 vqfrt; /* VQ Resources Flexible Total */
+ __le32 vqrfa; /* VQ Resources Flexible Assigned */
+ __le16 vqrfap; /* VQ Resources Flexible Allocated to Primary */
+ __le16 vqprt; /* VQ Resources Private Total */
+ __le16 vqfrsm; /* VQ Resources Flexible Secondary Maximum */
+ __le16 vqgran; /* VQ Flexible Resource Preferred Granularity */
+ __u8 rsvd48[16];
+ __le32 vifrt; /* VI Resources Flexible Total */
+ __le32 virfa; /* VI Resources Flexible Assigned */
+ __u16 virfap; /* VI Resources Flexible Allocated to Primary */
+ __u16 viprt; /* VI Resources Private Total */
+ __u16 vifrsm; /* VI Resources Flexible Secondary Maximum */
+ __u16 vigran; /* VI Flexible Resource Preferred Granularity */
+ __u8 rsvd80[4016];
+};
+
struct nvme_secondary_controller_entry {
__le16 scid; /* Secondary Controller Identifier */
__le16 pcid; /* Primary Controller Identifier */
ENTRY("list-ns", "Send NVMe Identify List, display structure", list_ns)
ENTRY("list-ctrl", "Send NVMe Identify Controller List, display structure", list_ctrl)
ENTRY("nvm-id-ctrl", "Send NVMe Identify Controller NVM Command Set, display structure", nvm_id_ctrl)
+ ENTRY("primary-ctrl-caps", "Send NVMe Identify Primary Controller Capabilities", primary_ctrl_caps)
ENTRY("list-secondary", "List Secondary Controllers associated with a Primary Controller", list_secondary_ctrl)
ENTRY("ns-descs", "Send NVMe Namespace Descriptor List, display structure", ns_descs)
ENTRY("id-nvmset", "Send NVMe Identify NVM Set List, display structure", id_nvmset)
return nvme_identify(fd, nsid, (cntid << 16) | cns, data);
}
+int nvme_identify_primary_ctrl_caps(int fd, void *data)
+{
+ return nvme_identify(fd, 0, NVME_ID_CNS_PRIMARY_CTRL_CAPS, 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_nvmset(int fd, __u16 nvmset_id, void *data);
int nvme_identify_uuid(int fd, void *data);
+int nvme_identify_primary_ctrl_caps(int fd, void *data);
int nvme_identify_secondary_ctrl_list(int fd, __u32 nsid, __u16 cntid, void *data);
int nvme_identify_ns_granularity(int fd, void *data);
int nvme_identify_ctrl_nvm(int fd, void *data);
}
}
+static void nvme_show_primary_ctrl_caps_crt(__u8 crt)
+{
+ __u8 rsvd = (crt & 0xFC) >> 2;
+ __u8 vi = (crt & 0x2) >> 1;
+ __u8 vq = (crt & 0x1) >> 0;
+
+ if (rsvd)
+ printf(" [7:2] : %#x\tReserved\n", rsvd);
+ printf(" [1:1] %#x\tVI Resources are %ssupported\n", vi, vi ? "" : "not ");
+ printf(" [1:1] %#x\tVQ Resources are %ssupported\n", vq, vq ? "" : "not ");
+}
+
+void nvme_show_primary_ctrl_caps(const struct nvme_primary_ctrl_caps *caps,
+ enum nvme_print_flags flags)
+{
+ int human = flags & VERBOSE;
+
+ if (flags & BINARY)
+ return d_raw((unsigned char *)caps, sizeof(*caps));
+
+ printf("NVME Identify Primary Controller Capabilities:\n");
+ printf("cntlid : %#x\n", le16_to_cpu(caps->cntlid));
+ printf("portid : %#x\n", le16_to_cpu(caps->portid));
+ printf("crt : %#x\n", caps->crt);
+ if (human)
+ nvme_show_primary_ctrl_caps_crt(caps->crt);
+ printf("vqfrt : %d\n", le32_to_cpu(caps->vqfrt));
+ printf("vqrfa : %d\n", le32_to_cpu(caps->vqrfa));
+ printf("vqrfap : %d\n", le16_to_cpu(caps->vqrfap));
+ printf("vqprt : %d\n", le16_to_cpu(caps->vqprt));
+ printf("vqfrsm : %d\n", le16_to_cpu(caps->vqfrsm));
+ printf("vqgran : %d\n", le16_to_cpu(caps->vqgran));
+ printf("vifrt : %d\n", le32_to_cpu(caps->vifrt));
+ printf("virfa : %d\n", le32_to_cpu(caps->virfa));
+ printf("virfap : %d\n", le16_to_cpu(caps->virfap));
+ printf("viprt : %d\n", le16_to_cpu(caps->viprt));
+ printf("vifrsm : %d\n", le16_to_cpu(caps->vifrsm));
+ printf("vigran : %d\n", le16_to_cpu(caps->vigran));
+}
+
+
static void json_nvme_list_secondary_ctrl(const struct nvme_secondary_controllers_list *sc_list,
__u32 count)
{
enum nvme_print_flags flags);
void nvme_show_id_nvmset(struct nvme_id_nvmset *nvmset, unsigned nvmset_id,
enum nvme_print_flags flags);
+void nvme_show_primary_ctrl_caps(const struct nvme_primary_ctrl_caps *caps,
+ enum nvme_print_flags flags);
void nvme_show_list_secondary_ctrl(const struct nvme_secondary_controllers_list *sc_list,
__u32 count, enum nvme_print_flags flags);
void nvme_show_id_ns_granularity_list(const struct nvme_id_ns_granularity_list *glist,
return nvme_status_to_errno(err, false);
}
+static int primary_ctrl_caps(int argc, char **argv, struct command *cmd, struct plugin *plugin)
+{
+ const char *desc = "Send an Identify Primary Controller Capabilities "\
+ "command to the given device and report the information in a "\
+ "human-redable or binary format.";
+ const char *raw = "show capabilities in binary format";
+ const char *human_readable = "show capabilities in readable format";
+
+ enum nvme_print_flags flags = NORMAL;
+ struct nvme_primary_ctrl_caps caps;
+ int err, fd;
+
+ struct config {
+ int raw_binary;
+ int human_readable;
+ char *output_format;
+ };
+
+ struct config cfg = {
+ .output_format = "normal",
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
+ OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
+ OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable),
+ OPT_END()
+ };
+
+ err = fd = parse_and_open(argc, argv, desc, opts);
+ if (fd < 0)
+ goto ret;
+
+ err = flags = validate_output_format(cfg.output_format);
+ if (flags < 0)
+ goto close_fd;
+ if (cfg.raw_binary)
+ flags = BINARY;
+ if (cfg.human_readable)
+ flags |= VERBOSE;
+
+ err = nvme_identify_primary_ctrl_caps(fd, &caps);
+ if (!err)
+ nvme_show_primary_ctrl_caps(&caps, flags);
+ else if (err >0)
+ nvme_show_status(err);
+ else
+ perror("identify primary controller capabilities");
+close_fd:
+ close(fd);
+ret:
+ return nvme_status_to_errno(err, false);
+}
+
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 "\