From fda7c1dc401d96345f77defcee4375607d571147 Mon Sep 17 00:00:00 2001 From: Steven Seungcheol Lee Date: Tue, 10 Feb 2026 17:28:14 +0900 Subject: [PATCH] mi: Add ISH bit (admin command cflags) Add ish bit for mi admin commands that access media Spec NVM-Express-Management-Interface-Specification -Revision-2.1-2025.08.01-Ratified Figure 136: NVMe Admin Command Request Description Command Flags (CFLGS): Bit 2 : Ignore Shutdown (ISH) This bit shall have no effect on the value of the CSTS.SHST field. (193 page from spec) If an NVMe Admin Command does not require access to media, then the ISH bit shall have no effect on the processing of that NVMe Admin Command. spec NVM-Express-Base-Specification-Revision-2.3-2025.08.01-Ratified Figure 84: Admin Commands Permitted to Return a Status Code of Admin Command Media Not Ready From Figure 84, we can assume that below Admin commands access media Capacity Management, Device Self-test, Firmware Commit, Firmware Image Download, Get LBA Status, Get Log Page, Namespace Attachment, Namespace Management, Format NVM, Sanitize, Sanitize Namespace, Security Receive, Security Send, Vendor Specific Signed-off-by: Steven Seungcheol Lee Reported-by: Hojin Ahn --- libnvme/src/nvme/ioctl.h | 20 +++++- libnvme/src/nvme/linux.c | 27 ++++--- libnvme/src/nvme/linux.h | 13 ++-- libnvme/src/nvme/mi.c | 3 +- nvme.c | 152 ++++++++++++++++++++++++++++++++++++--- 5 files changed, 191 insertions(+), 24 deletions(-) diff --git a/libnvme/src/nvme/ioctl.h b/libnvme/src/nvme/ioctl.h index 9f27307584..f52e404c91 100644 --- a/libnvme/src/nvme/ioctl.h +++ b/libnvme/src/nvme/ioctl.h @@ -52,7 +52,7 @@ /** * struct nvme_passthru_cmd - nvme passthrough command structure * @opcode: Operation code, see &enum nvme_io_opcodes and &enum nvme_admin_opcodes - * @flags: Not supported: intended for command flags (eg: SGL, FUSE) + * @flags: Supported only for NVMe-MI * @rsvd1: Reserved for future use * @nsid: Namespace Identifier, or Fabrics type * @cdw2: Command Dword 2 (no spec defined use) @@ -440,6 +440,8 @@ enum nvme_cmd_dword_fields { NVME_COPY_CDW15_LBAT_MASK = 0xffff, NVME_COPY_CDW15_LBATM_SHIFT = 16, NVME_COPY_CDW15_LBATM_MASK = 0xffff, + NVME_MI_ADMIN_CFLAGS_ISH_SHIFT = 2, + NVME_MI_ADMIN_CFLAGS_ISH_MASK = 0x1, }; #define NVME_FIELD_ENCODE(value, shift, mask) \ @@ -7082,4 +7084,20 @@ nvme_get_features_simple(struct nvme_transport_handle *hdl, __u8 fid, *result = cmd.result; return err; } + +/** + * nvme_init_mi_cmd_flags() - Initialize command flags for NVMe-MI + * @cmd: Passthru command to use + * @ish: Ignore Shutdown (for NVMe-MI command) + * + * Initializes the passthru command flags + */ +static inline void +nvme_init_mi_cmd_flags(struct nvme_passthru_cmd *cmd, bool ish) +{ + cmd->flags = NVME_FIELD_ENCODE(ish, + NVME_MI_ADMIN_CFLAGS_ISH_SHIFT, + NVME_MI_ADMIN_CFLAGS_ISH_MASK); +} + #endif /* _LIBNVME_IOCTL_H */ diff --git a/libnvme/src/nvme/linux.c b/libnvme/src/nvme/linux.c index 2c80512a78..ec52f0d94b 100644 --- a/libnvme/src/nvme/linux.c +++ b/libnvme/src/nvme/linux.c @@ -229,13 +229,17 @@ bool nvme_transport_handle_is_mi(struct nvme_transport_handle *hdl) return hdl->type == NVME_TRANSPORT_HANDLE_TYPE_MI; } -int nvme_fw_download_seq(struct nvme_transport_handle *hdl, __u32 size, - __u32 xfer, __u32 offset, void *buf) +int nvme_fw_download_seq(struct nvme_transport_handle *hdl, bool ish, + __u32 size, __u32 xfer, __u32 offset, void *buf) { struct nvme_passthru_cmd cmd; void *data = buf; int err = 0; + if (ish && nvme_transport_handle_is_mi(hdl)) { + nvme_init_mi_cmd_flags(&cmd, ish); + } + while (size > 0) { err = nvme_init_fw_download(&cmd, data, MIN(xfer, size), offset); if (err) @@ -525,13 +529,16 @@ int nvme_get_lba_status_log(struct nvme_transport_handle *hdl, bool rae, struct return 0; } -static int nvme_ns_attachment(struct nvme_transport_handle *hdl, __u32 nsid, - __u16 num_ctrls, __u16 *ctrlist, bool attach) +static int nvme_ns_attachment(struct nvme_transport_handle *hdl, bool ish, + __u32 nsid, __u16 num_ctrls, __u16 *ctrlist, bool attach) { struct nvme_ctrl_list cntlist = { 0 }; struct nvme_passthru_cmd cmd; nvme_init_ctrl_list(&cntlist, num_ctrls, ctrlist); + if (ish && nvme_transport_handle_is_mi(hdl)) + nvme_init_mi_cmd_flags(&cmd, ish); + if (attach) nvme_init_ns_attach_ctrls(&cmd, nsid, &cntlist); else @@ -540,16 +547,16 @@ static int nvme_ns_attachment(struct nvme_transport_handle *hdl, __u32 nsid, return nvme_submit_admin_passthru(hdl, &cmd); } -int nvme_namespace_attach_ctrls(struct nvme_transport_handle *hdl, __u32 nsid, - __u16 num_ctrls, __u16 *ctrlist) +int nvme_namespace_attach_ctrls(struct nvme_transport_handle *hdl, bool ish, + __u32 nsid, __u16 num_ctrls, __u16 *ctrlist) { - return nvme_ns_attachment(hdl, nsid, num_ctrls, ctrlist, true); + return nvme_ns_attachment(hdl, ish, nsid, num_ctrls, ctrlist, true); } -int nvme_namespace_detach_ctrls(struct nvme_transport_handle *hdl, __u32 nsid, - __u16 num_ctrls, __u16 *ctrlist) +int nvme_namespace_detach_ctrls(struct nvme_transport_handle *hdl, bool ish, + __u32 nsid, __u16 num_ctrls, __u16 *ctrlist) { - return nvme_ns_attachment(hdl, nsid, num_ctrls, ctrlist, false); + return nvme_ns_attachment(hdl, ish, nsid, num_ctrls, ctrlist, false); } size_t nvme_get_ana_log_len_from_id_ctrl(const struct nvme_id_ctrl *id_ctrl, diff --git a/libnvme/src/nvme/linux.h b/libnvme/src/nvme/linux.h index 45c2e6da07..10e2205034 100644 --- a/libnvme/src/nvme/linux.h +++ b/libnvme/src/nvme/linux.h @@ -24,6 +24,7 @@ /** * nvme_fw_download_seq() - Firmware download sequence * @hdl: Transport handle + * @ish: Ignore Shutdown (for NVMe-MI command) * @size: Total size of the firmware image to transfer * @xfer: Maximum size to send with each partial transfer * @offset: Starting offset to send with this firmware download @@ -32,8 +33,8 @@ * Return: 0 on success, the nvme command status if a response was * received (see &enum nvme_status_field) or a negative error otherwise. */ -int nvme_fw_download_seq(struct nvme_transport_handle *hdl, __u32 size, __u32 xfer, __u32 offset, - void *buf); +int nvme_fw_download_seq(struct nvme_transport_handle *hdl, bool ish, + __u32 size, __u32 xfer, __u32 offset, void *buf); /** * nvme_set_etdas() - Set the Extended Telemetry Data Area 4 Supported bit @@ -193,6 +194,7 @@ int nvme_get_lba_status_log(struct nvme_transport_handle *hdl, bool rae, struct /** * nvme_namespace_attach_ctrls() - Attach namespace to controller(s) * @hdl: Transport handle + * @ish: Ignore Shutdown (for NVMe-MI command) * @nsid: Namespace ID to attach * @num_ctrls: Number of controllers in ctrlist * @ctrlist: List of controller IDs to perform the attach action @@ -200,11 +202,13 @@ int nvme_get_lba_status_log(struct nvme_transport_handle *hdl, bool rae, struct * Return: 0 on success, the nvme command status if a response was * received (see &enum nvme_status_field) or a negative error otherwise. */ -int nvme_namespace_attach_ctrls(struct nvme_transport_handle *hdl, __u32 nsid, __u16 num_ctrls, __u16 *ctrlist); +int nvme_namespace_attach_ctrls(struct nvme_transport_handle *hdl, bool ish, + __u32 nsid, __u16 num_ctrls, __u16 *ctrlist); /** * nvme_namespace_detach_ctrls() - Detach namespace from controller(s) * @hdl: Transport handle + * @ish: Ignore Shutdown (for NVMe-MI command) * @nsid: Namespace ID to detach * @num_ctrls: Number of controllers in ctrlist * @ctrlist: List of controller IDs to perform the detach action @@ -212,7 +216,8 @@ int nvme_namespace_attach_ctrls(struct nvme_transport_handle *hdl, __u32 nsid, _ * Return: 0 on success, the nvme command status if a response was * received (see &enum nvme_status_field) or a negative error otherwise. */ -int nvme_namespace_detach_ctrls(struct nvme_transport_handle *hdl, __u32 nsid, __u16 num_ctrls, __u16 *ctrlist); +int nvme_namespace_detach_ctrls(struct nvme_transport_handle *hdl, bool ish, + __u32 nsid, __u16 num_ctrls, __u16 *ctrlist); /** * nvme_open() - Open an nvme controller or namespace device diff --git a/libnvme/src/nvme/mi.c b/libnvme/src/nvme/mi.c index 215471e2e7..4c74922f99 100644 --- a/libnvme/src/nvme/mi.c +++ b/libnvme/src/nvme/mi.c @@ -896,6 +896,7 @@ int nvme_mi_admin_admin_passthru(struct nvme_transport_handle *hdl, } nvme_mi_admin_init_req(hdl->ep, &req, &req_hdr, hdl->id, cmd->opcode); + req_hdr.flags = cmd->flags; req_hdr.cdw1 = cpu_to_le32(cmd->nsid); req_hdr.cdw2 = cpu_to_le32(cmd->cdw2); req_hdr.cdw3 = cpu_to_le32(cmd->cdw3); @@ -909,7 +910,7 @@ int nvme_mi_admin_admin_passthru(struct nvme_transport_handle *hdl, if (cmd->data_len != 0) { req_hdr.dlen = cpu_to_le32(cmd->data_len); /* Bit 0 set to 1 means DLEN contains a value */ - req_hdr.flags = 0x1; + req_hdr.flags |= 0x1; } if (has_write_data) { diff --git a/nvme.c b/nvme.c index f55a0b5953..56271e3688 100644 --- a/nvme.c +++ b/nvme.c @@ -258,6 +258,7 @@ static const char *nssd = "NSSD=0x64 register offset"; static const char *pmrctl = "PMRCTL=0xe04 register offset"; static const char *pmrmscl = "PMRMSCL=0xe14 register offset"; static const char *pmrmscu = "PMRMSCU=0xe18 register offset"; +static const char *ish = "Ignore Shutdown (for NVMe-MI command)"; struct nvme_config nvme_cfg = { .output_format = "normal", @@ -2305,6 +2306,7 @@ static int get_log(int argc, char **argv, struct command *acmd, struct plugin *p nvme_print_flags_t flags; struct config { + bool ish; __u32 namespace_id; __u8 log_id; __u32 log_len; @@ -2321,6 +2323,7 @@ static int get_log(int argc, char **argv, struct command *acmd, struct plugin *p }; struct config cfg = { + .ish = false, .namespace_id = NVME_NSID_ALL, .log_id = 0xff, .log_len = 0, @@ -2383,6 +2386,7 @@ static int get_log(int argc, char **argv, struct command *acmd, struct plugin *p }; NVME_ARGS(opts, + OPT_FLAG("ish", 'I', &cfg.ish, ish), OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_desired), OPT_BYTE("log-id", 'i', &cfg.log_id, log_id, log_name), OPT_UINT("log-len", 'l', &cfg.log_len, log_len), @@ -2452,6 +2456,12 @@ static int get_log(int argc, char **argv, struct command *acmd, struct plugin *p }; nvme_init_get_log(&cmd, cfg.namespace_id, cfg.log_id, cfg.csi, log, cfg.log_len); + if (cfg.ish) { + if (nvme_transport_handle_is_mi(hdl)) + nvme_init_mi_cmd_flags(&cmd, ish); + else + printf("ISH is supported only for NVMe-MI\n"); + } cmd.cdw10 |= NVME_FIELD_ENCODE(cfg.lsp, NVME_LOG_CDW10_LSP_SHIFT, NVME_LOG_CDW10_LSP_MASK); @@ -2945,14 +2955,17 @@ static int delete_ns(int argc, char **argv, struct command *acmd, struct plugin int err; struct config { + bool ish; __u32 namespace_id; }; struct config cfg = { + .ish = false, .namespace_id = 0, }; NVME_ARGS(opts, + OPT_FLAG("ish", 'I', &cfg.ish, ish), OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id)); err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); @@ -2974,6 +2987,12 @@ static int delete_ns(int argc, char **argv, struct command *acmd, struct plugin } nvme_init_ns_mgmt_delete(&cmd, cfg.namespace_id); + if (cfg.ish) { + if (nvme_transport_handle_is_mi(hdl)) + nvme_init_mi_cmd_flags(&cmd, ish); + else + printf("ISH is supported only for NVMe-MI\n"); + } err = nvme_submit_admin_passthru(hdl, &cmd); ns_mgmt_show_status(hdl, err, acmd->name, cfg.namespace_id); @@ -2995,18 +3014,21 @@ static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, s const char *cont = "optional comma-sep controller id list"; struct config { + bool ish; __u32 nsid; char *cntlist; }; struct config cfg = { + .ish = false, .nsid = 0, .cntlist = "", }; NVME_ARGS(opts, - OPT_UINT("namespace-id", 'n', &cfg.nsid, namespace_id), - OPT_LIST("controllers", 'c', &cfg.cntlist, cont)); + OPT_FLAG("ish", 'I', &cfg.ish, ish), + OPT_UINT("namespace-id", 'n', &cfg.nsid, namespace_id), + OPT_LIST("controllers", 'c', &cfg.cntlist, cont)); err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts); if (err) @@ -3059,6 +3081,12 @@ static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, s else nvme_init_ns_detach_ctrls(&cmd, cfg.nsid, cntlist); + if (cfg.ish) { + if (nvme_transport_handle_is_mi(hdl)) + nvme_init_mi_cmd_flags(&cmd, ish); + else + printf("ISH is supported only for NVMe-MI\n"); + } err = nvme_submit_admin_passthru(hdl, &cmd); ns_mgmt_show_status(hdl, err, acmd->name, cfg.nsid); @@ -3210,6 +3238,7 @@ static int create_ns(int argc, char **argv, struct command *acmd, struct plugin __u32 nsid; struct config { + bool ish; __u64 nsze; __u64 ncap; __u8 flbas; @@ -3232,6 +3261,7 @@ static int create_ns(int argc, char **argv, struct command *acmd, struct plugin }; struct config cfg = { + .ish = false, .nsze = 0, .ncap = 0, .flbas = 0xff, @@ -3254,6 +3284,7 @@ static int create_ns(int argc, char **argv, struct command *acmd, struct plugin }; NVME_ARGS(opts, + OPT_FLAG("ish", 'I', &cfg.ish, ish), OPT_SUFFIX("nsze", 's', &cfg.nsze, nsze), OPT_SUFFIX("ncap", 'c', &cfg.ncap, ncap), OPT_BYTE("flbas", 'f', &cfg.flbas, flbas), @@ -3417,6 +3448,12 @@ static int create_ns(int argc, char **argv, struct command *acmd, struct plugin data->phndl[i] = cpu_to_le16(phndl[i]); nvme_init_ns_mgmt_create(&cmd, cfg.csi, data); + if (cfg.ish) { + if (nvme_transport_handle_is_mi(hdl)) + nvme_init_mi_cmd_flags(&cmd, ish); + else + printf("ISH is supported only for NVMe-MI\n"); + } err = nvme_submit_admin_passthru(hdl, &cmd); nsid = cmd.result; ns_mgmt_show_status(hdl, err, acmd->name, nsid); @@ -4581,12 +4618,19 @@ static int wait_self_test(struct nvme_transport_handle *hdl) return 0; } -static void abort_self_test(struct nvme_transport_handle *hdl, __u32 nsid) +static void abort_self_test(struct nvme_transport_handle *hdl, bool ish, + __u32 nsid) { struct nvme_passthru_cmd cmd; int err; nvme_init_dev_self_test(&cmd, nsid, NVME_DST_STC_ABORT); + if (ish) { + if (nvme_transport_handle_is_mi(hdl)) + nvme_init_mi_cmd_flags(&cmd, ish); + else + printf("ISH is supported only for NVMe-MI\n"); + } err = nvme_submit_admin_passthru(hdl, &cmd); if (err) { nvme_show_err("Device self-test", err); @@ -4619,18 +4663,21 @@ static int device_self_test(int argc, char **argv, struct command *acmd, struct int err; struct config { + bool ish; __u32 namespace_id; __u8 stc; bool wait; }; struct config cfg = { + .ish = false, .namespace_id = NVME_NSID_ALL, .stc = NVME_ST_CODE_RESERVED, .wait = false, }; NVME_ARGS(opts, + OPT_FLAG("ish", 'I', &cfg.ish, ish), OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), OPT_BYTE("self-test-code", 's', &cfg.stc, self_test_code), OPT_FLAG("wait", 'w', &cfg.wait, wait)); @@ -4671,6 +4718,12 @@ static int device_self_test(int argc, char **argv, struct command *acmd, struct } nvme_init_dev_self_test(&cmd, cfg.namespace_id, cfg.stc); + if (cfg.ish) { + if (nvme_transport_handle_is_mi(hdl)) + nvme_init_mi_cmd_flags(&cmd, ish); + else + printf("ISH is supported only for NVMe-MI\n"); + } err = nvme_submit_admin_passthru(hdl, &cmd); if (err) { nvme_show_err("Device self-test", err); @@ -4691,7 +4744,7 @@ static int device_self_test(int argc, char **argv, struct command *acmd, struct check_abort: if (err == -EINTR) - abort_self_test(hdl, cfg.namespace_id); + abort_self_test(hdl, cfg.ish, cfg.namespace_id); return err; } @@ -4978,7 +5031,7 @@ static int get_feature(int argc, char **argv, struct command *acmd, * be aborted. */ static int fw_download_single(struct nvme_transport_handle *hdl, void *fw_buf, - unsigned int fw_len, uint32_t offset, + bool ish, unsigned int fw_len, uint32_t offset, uint32_t len, bool progress, bool ignore_ovr) { const unsigned int max_retries = 3; @@ -4991,6 +5044,9 @@ static int fw_download_single(struct nvme_transport_handle *hdl, void *fw_buf, offset, fw_len, (int)(100 * offset / fw_len)); } + if (nvme_transport_handle_is_mi(hdl)) + nvme_init_mi_cmd_flags(&cmd, ish); + for (try = 0; try < max_retries; try++) { if (try > 0) { fprintf(stderr, "retrying offset %x (%u/%u)\n", @@ -5090,6 +5146,7 @@ static int fw_download(int argc, char **argv, struct command *acmd, struct plugi struct config { char *fw; + bool ish; __u32 xfer; __u32 offset; bool progress; @@ -5098,6 +5155,7 @@ static int fw_download(int argc, char **argv, struct command *acmd, struct plugi struct config cfg = { .fw = "", + .ish = false, .xfer = 0, .offset = 0, .progress = false, @@ -5106,6 +5164,7 @@ static int fw_download(int argc, char **argv, struct command *acmd, struct plugi NVME_ARGS(opts, OPT_FILE("fw", 'f', &cfg.fw, fw), + OPT_FLAG("ish", 'I', &cfg.ish, ish), OPT_UINT("xfer", 'x', &cfg.xfer, xfer), OPT_UINT("offset", 'O', &cfg.offset, offset), OPT_FLAG("progress", 'p', &cfg.progress, progress), @@ -5169,10 +5228,14 @@ static int fw_download(int argc, char **argv, struct command *acmd, struct plugi return err; } + if (cfg.ish && !nvme_transport_handle_is_mi(hdl)) { + printf("ISH is supported only for NVMe-MI\n"); + } + for (pos = 0; pos < fw_size; pos += cfg.xfer) { cfg.xfer = min(cfg.xfer, fw_size - pos); - err = fw_download_single(hdl, fw_buf + pos, fw_size, + err = fw_download_single(hdl, fw_buf + pos, cfg.ish, fw_size, cfg.offset + pos, cfg.xfer, cfg.progress, cfg.ignore_ovr); if (err) @@ -5282,18 +5345,21 @@ static int fw_commit(int argc, char **argv, struct command *acmd, struct plugin nvme_print_flags_t flags; struct config { + bool ish; __u8 slot; __u8 action; __u8 bpid; }; struct config cfg = { + .ish = false, .slot = 0, .action = 0, .bpid = 0, }; NVME_ARGS(opts, + OPT_FLAG("ish", 'I', &cfg.ish, ish), OPT_BYTE("slot", 's', &cfg.slot, slot), OPT_BYTE("action", 'a', &cfg.action, action), OPT_BYTE("bpid", 'b', &cfg.bpid, bpid)); @@ -5322,6 +5388,12 @@ static int fw_commit(int argc, char **argv, struct command *acmd, struct plugin } nvme_init_fw_commit(&cmd, cfg.slot, cfg.action, cfg.bpid); + if (cfg.ish) { + if (nvme_transport_handle_is_mi(hdl)) + nvme_init_mi_cmd_flags(&cmd, ish); + else + printf("ISH is supported only for NVMe-MI\n"); + } err = nvme_submit_admin_passthru(hdl, &cmd); if (err) { fw_commit_err(err, cfg.action, cfg.slot, cfg.bpid); @@ -5451,6 +5523,7 @@ static int sanitize_cmd(int argc, char **argv, struct command *acmd, struct plug int err; struct config { + bool ish; bool no_dealloc; bool oipbp; __u8 owpass; @@ -5461,6 +5534,7 @@ static int sanitize_cmd(int argc, char **argv, struct command *acmd, struct plug }; struct config cfg = { + .ish = false, .no_dealloc = false, .oipbp = false, .owpass = 0, @@ -5480,6 +5554,7 @@ static int sanitize_cmd(int argc, char **argv, struct command *acmd, struct plug }; NVME_ARGS(opts, + OPT_FLAG("ish", 'I', &cfg.ish, ish), OPT_FLAG("no-dealloc", 'd', &cfg.no_dealloc, no_dealloc_desc), OPT_FLAG("oipbp", 'i', &cfg.oipbp, oipbp_desc), OPT_BYTE("owpass", 'n', &cfg.owpass, owpass_desc), @@ -5533,7 +5608,13 @@ static int sanitize_cmd(int argc, char **argv, struct command *acmd, struct plug } nvme_init_sanitize_nvm(&cmd, cfg.sanact, cfg.ause, cfg.owpass, - cfg.oipbp, cfg.no_dealloc, cfg.emvs, cfg.ovrpat); + cfg.oipbp, cfg.no_dealloc, cfg.emvs, cfg.ovrpat); + if (cfg.ish) { + if (nvme_transport_handle_is_mi(hdl)) + nvme_init_mi_cmd_flags(&cmd, ish); + else + printf("ISH is supported only for NVMe-MI\n"); + } err = nvme_submit_admin_passthru(hdl, &cmd); if (err) { nvme_show_err("sanitize", err); @@ -5562,12 +5643,14 @@ static int sanitize_ns_cmd(int argc, char **argv, struct command *acmd, int err; struct config { + bool ish; bool ause; __u8 sanact; bool emvs; }; struct config cfg = { + .ish = false, .ause = false, .sanact = 0, .emvs = false, @@ -5583,6 +5666,7 @@ static int sanitize_ns_cmd(int argc, char **argv, struct command *acmd, }; NVME_ARGS(opts, + OPT_FLAG("ish", 'I', &cfg.ish, ish), OPT_FLAG("ause", 'u', &cfg.ause, ause_desc), OPT_BYTE("sanact", 'a', &cfg.sanact, sanact_desc, sanact), OPT_FLAG("emvs", 'e', &cfg.emvs, emvs_desc)); @@ -5620,6 +5704,12 @@ static int sanitize_ns_cmd(int argc, char **argv, struct command *acmd, } nvme_init_sanitize_ns(&cmd, cfg.sanact, cfg.ause, cfg.emvs); + if (cfg.ish) { + if (nvme_transport_handle_is_mi(hdl)) + nvme_init_mi_cmd_flags(&cmd, ish); + else + printf("ISH is supported only for NVMe-MI\n"); + } err = nvme_submit_admin_passthru(hdl, &cmd); if (err) { nvme_show_admin_cmd_err("sanitize ns", &cmd, err); @@ -6496,6 +6586,7 @@ static int format_cmd(int argc, char **argv, struct command *acmd, struct plugin int err, i; struct config { + bool ish; __u32 namespace_id; __u8 lbaf; __u8 ses; @@ -6508,6 +6599,7 @@ static int format_cmd(int argc, char **argv, struct command *acmd, struct plugin }; struct config cfg = { + .ish = false, .namespace_id = 0, .lbaf = 0xff, .ses = 0, @@ -6523,6 +6615,7 @@ static int format_cmd(int argc, char **argv, struct command *acmd, struct plugin timeout_ms = nvme_cfg.timeout; NVME_ARGS(opts, + OPT_FLAG("ish", 'I', &cfg.ish, ish), OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id_desired), OPT_BYTE("lbaf", 'l', &cfg.lbaf, lbaf), OPT_BYTE("ses", 's', &cfg.ses, ses), @@ -6678,6 +6771,12 @@ static int format_cmd(int argc, char **argv, struct command *acmd, struct plugin nvme_init_format_nvm(&cmd, cfg.namespace_id, cfg.lbaf, cfg.mset, cfg.pi, cfg.pil, cfg.ses); cmd.timeout_ms = timeout_ms; + if (cfg.ish) { + if (nvme_transport_handle_is_mi(hdl)) + nvme_init_mi_cmd_flags(&cmd, ish); + else + printf("ISH is supported only for NVMe-MI\n"); + } err = nvme_submit_admin_passthru(hdl, &cmd); if (err) { nvme_show_err("format", err); @@ -6899,6 +6998,7 @@ static int sec_send(int argc, char **argv, struct command *acmd, struct plugin * nvme_print_flags_t flags; struct config { + bool ish; __u32 namespace_id; char *file; __u8 nssf; @@ -6908,6 +7008,7 @@ static int sec_send(int argc, char **argv, struct command *acmd, struct plugin * }; struct config cfg = { + .ish = false, .namespace_id = 0, .file = "", .nssf = 0, @@ -6917,6 +7018,7 @@ static int sec_send(int argc, char **argv, struct command *acmd, struct plugin * }; NVME_ARGS(opts, + OPT_FLAG("ish", 'I', &cfg.ish, ish), OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_desired), OPT_FILE("file", 'f', &cfg.file, file), OPT_BYTE("nssf", 'N', &cfg.nssf, nssf), @@ -6973,7 +7075,13 @@ static int sec_send(int argc, char **argv, struct command *acmd, struct plugin * } nvme_init_security_send(&cmd, cfg.namespace_id, cfg.nssf, cfg.spsp, - cfg.secp, cfg.tl, sec_buf, cfg.tl); + cfg.secp, cfg.tl, sec_buf, cfg.tl); + if (cfg.ish) { + if (nvme_transport_handle_is_mi(hdl)) + nvme_init_mi_cmd_flags(&cmd, ish); + else + printf("ISH is supported only for NVMe-MI\n"); + } err = nvme_submit_admin_passthru(hdl, &cmd); if (err) { nvme_show_err("security-send", err); @@ -8664,6 +8772,7 @@ static int sec_recv(int argc, char **argv, struct command *acmd, struct plugin * int err; struct config { + bool ish; __u32 namespace_id; __u32 size; __u8 nssf; @@ -8674,6 +8783,7 @@ static int sec_recv(int argc, char **argv, struct command *acmd, struct plugin * }; struct config cfg = { + .ish = false, .namespace_id = 0, .size = 0, .nssf = 0, @@ -8684,6 +8794,7 @@ static int sec_recv(int argc, char **argv, struct command *acmd, struct plugin * }; NVME_ARGS(opts, + OPT_FLAG("ish", 'I', &cfg.ish, ish), OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_desired), OPT_UINT("size", 'x', &cfg.size, size), OPT_BYTE("nssf", 'N', &cfg.nssf, nssf), @@ -8708,6 +8819,13 @@ static int sec_recv(int argc, char **argv, struct command *acmd, struct plugin * return -ENOMEM; } + if (cfg.ish) { + if (nvme_transport_handle_is_mi(hdl)) + nvme_init_mi_cmd_flags(&cmd, ish); + else + printf("ISH is supported only for NVMe-MI\n"); + } + nvme_init_security_receive(&cmd, cfg.namespace_id, cfg.nssf, cfg.spsp, cfg.secp, cfg.al, sec_buf, cfg.size); err = nvme_submit_admin_passthru(hdl, &cmd); @@ -8747,6 +8865,7 @@ static int get_lba_status(int argc, char **argv, struct command *acmd, int err; struct config { + bool ish; __u32 namespace_id; __u64 slba; __u32 mndw; @@ -8755,6 +8874,7 @@ static int get_lba_status(int argc, char **argv, struct command *acmd, }; struct config cfg = { + .ish = false, .namespace_id = 0, .slba = 0, .mndw = 0, @@ -8763,6 +8883,7 @@ static int get_lba_status(int argc, char **argv, struct command *acmd, }; NVME_ARGS(opts, + OPT_FLAG("ish", 'I', &cfg.ish, ish), OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_desired), OPT_SUFFIX("start-lba", 's', &cfg.slba, slba), OPT_UINT("max-dw", 'm', &cfg.mndw, mndw), @@ -8791,6 +8912,12 @@ static int get_lba_status(int argc, char **argv, struct command *acmd, nvme_init_get_lba_status(&cmd, cfg.namespace_id, cfg.slba, cfg.mndw, cfg.atype, cfg.rl, buf); + if (cfg.ish) { + if (nvme_transport_handle_is_mi(hdl)) + nvme_init_mi_cmd_flags(&cmd, ish); + else + printf("ISH is supported only for NVMe-MI\n"); + } err = nvme_submit_admin_passthru(hdl, &cmd); if (err) { nvme_show_err("get lba status", err); @@ -8822,6 +8949,7 @@ static int capacity_mgmt(int argc, char **argv, struct command *acmd, struct plu nvme_print_flags_t flags; struct config { + bool ish; __u8 operation; __u16 element_id; __u32 dw11; @@ -8829,6 +8957,7 @@ static int capacity_mgmt(int argc, char **argv, struct command *acmd, struct plu }; struct config cfg = { + .ish = false, .operation = 0xff, .element_id = 0xffff, .dw11 = 0, @@ -8836,6 +8965,7 @@ static int capacity_mgmt(int argc, char **argv, struct command *acmd, struct plu }; NVME_ARGS(opts, + OPT_FLAG("ish", 'I', &cfg.ish, ish), OPT_BYTE("operation", 'O', &cfg.operation, operation), OPT_SHRT("element-id", 'i', &cfg.element_id, element_id), OPT_UINT("cap-lower", 'l', &cfg.dw11, cap_lower), @@ -8859,6 +8989,12 @@ static int capacity_mgmt(int argc, char **argv, struct command *acmd, struct plu nvme_init_capacity_mgmt(&cmd, cfg.operation, cfg.element_id, (__u64)cfg.dw12 << 32 | cfg.dw11); + if (cfg.ish) { + if (nvme_transport_handle_is_mi(hdl)) + nvme_init_mi_cmd_flags(&cmd, ish); + else + printf("ISH is supported only for NVMe-MI\n"); + } err = nvme_submit_admin_passthru(hdl, &cmd); if (err) { nvme_show_err("capacity management", err);