diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2023-12-24 07:51:48 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2023-12-24 07:51:48 +0000 |
commit | 8d843cc9cc0e989d3929f204f77223cd08730c7a (patch) | |
tree | 1fcba17d10325d9d7ccb68b2eb48cd9bbba6a534 /src/nvme/ioctl.c | |
parent | Releasing debian version 1.5-3. (diff) | |
download | libnvme-8d843cc9cc0e989d3929f204f77223cd08730c7a.tar.xz libnvme-8d843cc9cc0e989d3929f204f77223cd08730c7a.zip |
Merging upstream version 1.7.1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/nvme/ioctl.c')
-rw-r--r-- | src/nvme/ioctl.c | 272 |
1 files changed, 230 insertions, 42 deletions
diff --git a/src/nvme/ioctl.c b/src/nvme/ioctl.c index b9710b3..9090b7e 100644 --- a/src/nvme/ioctl.c +++ b/src/nvme/ioctl.c @@ -13,9 +13,11 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <inttypes.h> #include <sys/ioctl.h> #include <sys/stat.h> +#include <sys/time.h> #include <ccan/build_assert/build_assert.h> #include <ccan/endian/endian.h> @@ -23,6 +25,8 @@ #include "ioctl.h" #include "util.h" +static bool nvme_debug; + static int nvme_verify_chr(int fd) { static struct stat nvme_stat; @@ -86,13 +90,62 @@ static int nvme_submit_passthru64(int fd, unsigned long ioctl_cmd, return err; } +static void nvme_show_command(struct nvme_passthru_cmd *cmd, int err, struct timeval start, + struct timeval end) +{ + printf("opcode : %02x\n", cmd->opcode); + printf("flags : %02x\n", cmd->flags); + printf("rsvd1 : %04x\n", cmd->rsvd1); + printf("nsid : %08x\n", cmd->nsid); + printf("cdw2 : %08x\n", cmd->cdw2); + printf("cdw3 : %08x\n", cmd->cdw3); + printf("data_len : %08x\n", cmd->data_len); + printf("metadata_len : %08x\n", cmd->metadata_len); + printf("addr : %"PRIx64"\n", (uint64_t)(uintptr_t)cmd->addr); + printf("metadata : %"PRIx64"\n", (uint64_t)(uintptr_t)cmd->metadata); + printf("cdw10 : %08x\n", cmd->cdw10); + printf("cdw11 : %08x\n", cmd->cdw11); + printf("cdw12 : %08x\n", cmd->cdw12); + printf("cdw13 : %08x\n", cmd->cdw13); + printf("cdw14 : %08x\n", cmd->cdw14); + printf("cdw15 : %08x\n", cmd->cdw15); + printf("timeout_ms : %08x\n", cmd->timeout_ms); + printf("result : %08x\n", cmd->result); + printf("err : %d\n", err); + printf("latency : %lu us\n", + (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec)); +} + +void nvme_set_debug(bool debug) +{ + nvme_debug = debug; +} + +bool nvme_get_debug(void) +{ + return nvme_debug; +} + static int nvme_submit_passthru(int fd, unsigned long ioctl_cmd, struct nvme_passthru_cmd *cmd, __u32 *result) { - int err = ioctl(fd, ioctl_cmd, cmd); + struct timeval start; + struct timeval end; + int err; + + if (nvme_get_debug()) + gettimeofday(&start, NULL); + + err = ioctl(fd, ioctl_cmd, cmd); + + if (nvme_get_debug()) { + gettimeofday(&end, NULL); + nvme_show_command(cmd, err, start, end); + } if (err >= 0 && result) *result = cmd->result; + return err; } @@ -532,16 +585,18 @@ int nvme_set_features_power_mgmt(int fd, __u8 ps, __u8 wh, bool save, __u32 *result) { __u32 value = NVME_SET(ps, FEAT_PWRMGMT_PS) | - NVME_SET(wh, FEAT_PWRMGMT_PS); + NVME_SET(wh, FEAT_PWRMGMT_WH); return __nvme_set_features(fd, NVME_FEAT_FID_POWER_MGMT, value, save, result); } -int nvme_set_features_lba_range(int fd, __u32 nsid, __u32 nr_ranges, bool save, +int nvme_set_features_lba_range(int fd, __u32 nsid, __u8 nr_ranges, bool save, struct nvme_lba_range_type *data, __u32 *result) { - return -1; + return nvme_set_features_data( + fd, NVME_FEAT_FID_LBA_RANGE, nsid, nr_ranges - 1, save, + sizeof(*data), data, result); } int nvme_set_features_temp_thresh(int fd, __u16 tmpth, __u8 tmpsel, @@ -562,8 +617,8 @@ int nvme_set_features_err_recovery(int fd, __u32 nsid, __u16 tler, bool dulbe, __u32 value = NVME_SET(tler, FEAT_ERROR_RECOVERY_TLER) | NVME_SET(!!dulbe, FEAT_ERROR_RECOVERY_DULBE); - return __nvme_set_features(fd, NVME_FEAT_FID_ERR_RECOVERY, value, save, - result); + return nvme_set_features_simple( + fd, NVME_FEAT_FID_ERR_RECOVERY, nsid, value, save, result); } int nvme_set_features_volatile_wc(int fd, bool wce, bool save, __u32 *result) @@ -577,8 +632,8 @@ int nvme_set_features_volatile_wc(int fd, bool wce, bool save, __u32 *result) int nvme_set_features_irq_coalesce(int fd, __u8 thr, __u8 time, bool save, __u32 *result) { - __u32 value = NVME_SET(thr, FEAT_IRQC_TIME) | - NVME_SET(time, FEAT_IRQC_THR); + __u32 value = NVME_SET(thr, FEAT_IRQC_THR) | + NVME_SET(time, FEAT_IRQC_TIME); return __nvme_set_features(fd, NVME_FEAT_FID_IRQ_COALESCE, value, save, result); @@ -612,19 +667,31 @@ int nvme_set_features_async_event(int fd, __u32 events, int nvme_set_features_auto_pst(int fd, bool apste, bool save, struct nvme_feat_auto_pst *apst, __u32 *result) { - __u32 value = NVME_SET(!!apste, FEAT_APST_APSTE); + struct nvme_set_features_args args = { + .args_size = sizeof(args), + .fd = fd, + .fid = NVME_FEAT_FID_AUTO_PST, + .nsid = NVME_NSID_NONE, + .cdw11 = NVME_SET(!!apste, FEAT_APST_APSTE), + .save = save, + .uuidx = NVME_UUID_NONE, + .data = apst, + .data_len = sizeof(*apst), + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = result, + }; - return __nvme_set_features(fd, NVME_FEAT_FID_AUTO_PST, value, save, - result); + return nvme_set_features(&args); } int nvme_set_features_timestamp(int fd, bool save, __u64 timestamp) { __le64 t = cpu_to_le64(timestamp); - struct nvme_timestamp ts; + struct nvme_timestamp ts = {}; struct nvme_set_features_args args = { .args_size = sizeof(args), .fd = fd, + .fid = NVME_FEAT_FID_TIMESTAMP, .nsid = NVME_NSID_NONE, .cdw11 = 0, .cdw12 = 0, @@ -694,8 +761,8 @@ int nvme_set_features_plm_config(int fd, bool plm, __u16 nvmsetid, bool save, .save = save, .uuidx = NVME_UUID_NONE, .cdw15 = 0, - .data_len = 0, - .data = NULL, + .data_len = sizeof(*data), + .data = data, .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = result, }; @@ -746,7 +813,7 @@ int nvme_set_features_host_behavior(int fd, bool save, .nsid = NVME_NSID_NONE, .cdw11 = 0, .cdw12 = 0, - .save = save, + .save = false, .uuidx = NVME_UUID_NONE, .cdw15 = 0, .data_len = sizeof(*data), @@ -780,7 +847,7 @@ int nvme_set_features_sw_progress(int fd, __u8 pbslc, bool save, result); } -int nvme_set_features_host_id(int fd, bool save, bool exhid, __u8 *hostid) +int nvme_set_features_host_id(int fd, bool exhid, bool save, __u8 *hostid) { __u32 len = exhid ? 16 : 8; __u32 value = !!exhid; @@ -809,20 +876,42 @@ int nvme_set_features_resv_mask(int fd, __u32 mask, bool save, __u32 *result) result); } +int nvme_set_features_resv_mask2(int fd, __u32 nsid, __u32 mask, bool save, + __u32 *result) +{ + return nvme_set_features_simple( + fd, NVME_FEAT_FID_RESV_MASK, nsid, mask, save, result); +} + int nvme_set_features_resv_persist(int fd, bool ptpl, bool save, __u32 *result) { return __nvme_set_features(fd, NVME_FEAT_FID_RESV_PERSIST, !!ptpl, save, result); } +int nvme_set_features_resv_persist2(int fd, __u32 nsid, bool ptpl, bool save, + __u32 *result) +{ + return nvme_set_features_simple( + fd, NVME_FEAT_FID_RESV_PERSIST, nsid, !!ptpl, save, result); +} + int nvme_set_features_write_protect(int fd, enum nvme_feat_nswpcfg_state state, bool save, __u32 *result) { return __nvme_set_features(fd, NVME_FEAT_FID_WRITE_PROTECT, state, - save, result); + false, result); +} + +int nvme_set_features_write_protect2(int fd, __u32 nsid, + enum nvme_feat_nswpcfg_state state, + bool save, __u32 *result) +{ + return nvme_set_features_simple( + fd, NVME_FEAT_FID_WRITE_PROTECT, nsid, state, false, result); } -int nvme_set_features_iocs_profile(int fd, __u8 iocsi, bool save) +int nvme_set_features_iocs_profile(int fd, __u16 iocsi, bool save) { __u32 value = NVME_SET(iocsi, FEAT_IOCSP_IOCSCI); @@ -898,8 +987,28 @@ int nvme_get_features_lba_range(int fd, enum nvme_get_features_sel sel, .sel = sel, .cdw11 = 0, .uuidx = NVME_UUID_NONE, - .data_len = 0, - .data = NULL, + .data_len = sizeof(*data), + .data = data, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = result, + }; + + return nvme_get_features(&args); +} + +int nvme_get_features_lba_range2(int fd, enum nvme_get_features_sel sel, + __u32 nsid, struct nvme_lba_range_type *data, + __u32 *result) +{ + struct nvme_get_features_args args = { + .args_size = sizeof(args), + .fd = fd, + .fid = NVME_FEAT_FID_LBA_RANGE, + .nsid = nsid, + .sel = sel, + .uuidx = NVME_UUID_NONE, + .data = data, + .data_len = sizeof(*data), .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = result, }; @@ -920,6 +1029,24 @@ int nvme_get_features_err_recovery(int fd, enum nvme_get_features_sel sel, result); } +int nvme_get_features_err_recovery2(int fd, enum nvme_get_features_sel sel, + __u32 nsid, __u32 *result) +{ + + struct nvme_get_features_args args = { + .args_size = sizeof(args), + .fd = fd, + .fid = NVME_FEAT_FID_ERR_RECOVERY, + .nsid = nsid, + .sel = sel, + .uuidx = NVME_UUID_NONE, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = result, + }; + + return nvme_get_features(&args); +} + int nvme_get_features_volatile_wc(int fd, enum nvme_get_features_sel sel, __u32 *result) { @@ -945,7 +1072,7 @@ int nvme_get_features_irq_config(int fd, enum nvme_get_features_sel sel, struct nvme_get_features_args args = { .args_size = sizeof(args), .fd = fd, - .fid = NVME_FEAT_FID_LBA_RANGE, + .fid = NVME_FEAT_FID_IRQ_CONFIG, .nsid = NVME_NSID_NONE, .sel = sel, .cdw11 = iv, @@ -978,13 +1105,13 @@ int nvme_get_features_auto_pst(int fd, enum nvme_get_features_sel sel, struct nvme_get_features_args args = { .args_size = sizeof(args), .fd = fd, - .fid = NVME_FEAT_FID_LBA_RANGE, + .fid = NVME_FEAT_FID_AUTO_PST, .nsid = NVME_NSID_NONE, .sel = sel, .cdw11 = 0, .uuidx = NVME_UUID_NONE, - .data_len = 0, - .data = NULL, + .data_len = sizeof(*apst), + .data = apst, .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = result, }; @@ -998,6 +1125,26 @@ int nvme_get_features_host_mem_buf(int fd, enum nvme_get_features_sel sel, return __nvme_get_features(fd, NVME_FEAT_FID_HOST_MEM_BUF, sel, result); } +int nvme_get_features_host_mem_buf2(int fd, enum nvme_get_features_sel sel, + struct nvme_host_mem_buf_attrs *attrs, + __u32 *result) +{ + struct nvme_get_features_args args = { + .args_size = sizeof(args), + .fd = fd, + .fid = NVME_FEAT_FID_HOST_MEM_BUF, + .nsid = NVME_NSID_NONE, + .sel = sel, + .uuidx = NVME_UUID_NONE, + .data = attrs, + .data_len = sizeof(*attrs), + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = result, + }; + + return nvme_get_features(&args); +} + int nvme_get_features_timestamp(int fd, enum nvme_get_features_sel sel, struct nvme_timestamp *ts) { @@ -1050,8 +1197,8 @@ int nvme_get_features_plm_config(int fd, enum nvme_get_features_sel sel, .sel = sel, .cdw11 = nvmsetid, .uuidx = NVME_UUID_NONE, - .data_len = 0, - .data = NULL, + .data_len = sizeof(*data), + .data = data, .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = result, }; @@ -1098,8 +1245,8 @@ int nvme_get_features_host_behavior(int fd, enum nvme_get_features_sel sel, .sel = sel, .cdw11 = 0, .uuidx = NVME_UUID_NONE, - .data_len = 0, - .data = NULL, + .data_len = sizeof(*data), + .data = data, .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = result, }; @@ -1122,7 +1269,7 @@ int nvme_get_features_endurance_event_cfg(int fd, enum nvme_get_features_sel sel .fid = NVME_FEAT_FID_ENDURANCE_EVT_CFG, .nsid = NVME_NSID_NONE, .sel = sel, - .cdw11 = 0, + .cdw11 = endgid, .uuidx = NVME_UUID_NONE, .data_len = 0, .data = NULL, @@ -1165,12 +1312,46 @@ int nvme_get_features_resv_mask(int fd, enum nvme_get_features_sel sel, return __nvme_get_features(fd, NVME_FEAT_FID_RESV_MASK, sel, result); } +int nvme_get_features_resv_mask2(int fd, enum nvme_get_features_sel sel, + __u32 nsid, __u32 *result) +{ + struct nvme_get_features_args args = { + .args_size = sizeof(args), + .fd = fd, + .fid = NVME_FEAT_FID_RESV_MASK, + .nsid = nsid, + .sel = sel, + .uuidx = NVME_UUID_NONE, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = result, + }; + + return nvme_get_features(&args); +} + int nvme_get_features_resv_persist(int fd, enum nvme_get_features_sel sel, __u32 *result) { return __nvme_get_features(fd, NVME_FEAT_FID_RESV_PERSIST, sel, result); } +int nvme_get_features_resv_persist2(int fd, enum nvme_get_features_sel sel, + __u32 nsid, __u32 *result) +{ + struct nvme_get_features_args args = { + .args_size = sizeof(args), + .fd = fd, + .fid = NVME_FEAT_FID_RESV_PERSIST, + .nsid = nsid, + .sel = sel, + .uuidx = NVME_UUID_NONE, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = result, + }; + + return nvme_get_features(&args); +} + int nvme_get_features_write_protect(int fd, __u32 nsid, enum nvme_get_features_sel sel, __u32 *result) @@ -1387,6 +1568,7 @@ int nvme_get_lba_status(struct nvme_get_lba_status_args *args) .opcode = nvme_admin_get_lba_status, .nsid = args->nsid, .addr = (__u64)(uintptr_t)args->lbas, + .data_len = (args->mndw + 1) << 2, .cdw10 = cdw10, .cdw11 = cdw11, .cdw12 = cdw12, @@ -1655,33 +1837,35 @@ static int nvme_set_var_size_tags(__u32 *cmd_dw2, __u32 *cmd_dw3, __u32 *cmd_dw1 __u8 pif, __u8 sts, __u64 reftag, __u64 storage_tag) { __u32 cdw2 = 0, cdw3 = 0, cdw14; + beint64_t be_reftag = cpu_to_be64(reftag); + beint64_t be_storage_tag = cpu_to_be64(storage_tag); switch (pif) { /* 16b Protection Information */ case 0: - cdw14 = reftag & 0xffffffff; - cdw14 |= ((storage_tag << (32 - sts)) & 0xffffffff); + cdw14 = be_reftag & 0xffffffff; + cdw14 |= ((be_storage_tag << (32 - sts)) & 0xffffffff); break; /* 32b Protection Information */ case 1: - cdw14 = reftag & 0xffffffff; - cdw3 = reftag >> 32; - cdw14 |= ((storage_tag << (80 - sts)) & 0xffff0000); + cdw14 = be_reftag & 0xffffffff; + cdw3 = be_reftag >> 32; + cdw14 |= ((be_storage_tag << (80 - sts)) & 0xffff0000); if (sts >= 48) - cdw3 |= ((storage_tag >> (sts - 48)) & 0xffffffff); + cdw3 |= ((be_storage_tag >> (sts - 48)) & 0xffffffff); else - cdw3 |= ((storage_tag << (48 - sts)) & 0xffffffff); - cdw2 = (storage_tag >> (sts - 16)) & 0xffff; + cdw3 |= ((be_storage_tag << (48 - sts)) & 0xffffffff); + cdw2 = (be_storage_tag >> (sts - 16)) & 0xffff; break; /* 64b Protection Information */ case 2: - cdw14 = reftag & 0xffffffff; - cdw3 = (reftag >> 32) & 0xffff; - cdw14 |= ((storage_tag << (48 - sts)) & 0xffffffff); + cdw14 = be_reftag & 0xffffffff; + cdw3 = (be_reftag >> 32) & 0xffff; + cdw14 |= ((be_storage_tag << (48 - sts)) & 0xffffffff); if (sts >= 16) - cdw3 |= ((storage_tag >> (sts - 16)) & 0xffff); + cdw3 |= ((be_storage_tag >> (sts - 16)) & 0xffff); else - cdw3 |= ((storage_tag << (16 - sts)) & 0xffff); + cdw3 |= ((be_storage_tag << (16 - sts)) & 0xffff); break; default: perror("Unsupported Protection Information Format"); @@ -1793,6 +1977,10 @@ int nvme_copy(struct nvme_copy_args *args) if (args->format == 1) data_len = args->nr * sizeof(struct nvme_copy_range_f1); + else if (args->format == 2) + data_len = args->nr * sizeof(struct nvme_copy_range_f2); + else if (args->format == 3) + data_len = args->nr * sizeof(struct nvme_copy_range_f3); else data_len = args->nr * sizeof(struct nvme_copy_range); |