diff --git a/src/nvme/api-types.h b/src/nvme/api-types.h index 007befb65..af82652cb 100644 --- a/src/nvme/api-types.h +++ b/src/nvme/api-types.h @@ -86,38 +86,6 @@ struct nvme_get_log_args { bool ot; }; -/** - * struct nvme_set_features_args - Arguments for the NVMe Admin Set Feature command - * @result: The command completion result from CQE dword0 - * @data: User address of feature data, if applicable - * @args_size: Size of &struct nvme_set_features_args - * @timeout: Timeout in ms - * @nsid: Namespace ID, if applicable - * @cdw11: Value to set the feature to - * @cdw12: Feature specific command dword12 field - * @cdw13: Feature specific command dword13 field - * @cdw15: Feature specific command dword15 field - * @data_len: Length of feature data, if applicable, in bytes - * @save: Save value across power states - * @uuidx: UUID Index for differentiating vendor specific encoding - * @fid: Feature identifier - */ -struct nvme_set_features_args { - __u32 *result; - void *data; - int args_size; - __u32 timeout; - __u32 nsid; - __u32 cdw11; - __u32 cdw12; - __u32 cdw13; - __u32 cdw15; - __u32 data_len; - bool save; - __u8 uuidx; - __u8 fid; -}; - /** * struct nvme_get_features_args - Arguments for the NVMe Admin Get Feature command * @args_size: Size of &struct nvme_get_features_args diff --git a/src/nvme/fabrics.c b/src/nvme/fabrics.c index 3515c4f92..aa8d33273 100644 --- a/src/nvme/fabrics.c +++ b/src/nvme/fabrics.c @@ -1225,7 +1225,6 @@ int nvmf_get_discovery_log(nvme_ctrl_t c, struct nvmf_discovery_log **logp, struct nvme_get_discovery_args args = { .c = c, .max_retries = max_retries, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .lsp = NVMF_LOG_DISC_LSP_NONE, }; @@ -1604,7 +1603,6 @@ static int nvmf_dim(nvme_ctrl_t c, enum nvmf_dim_tas tas, __u8 trtype, struct nvme_dim_args args = { .args_size = sizeof(args), .result = result, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .tas = tas }; diff --git a/src/nvme/ioctl.c b/src/nvme/ioctl.c index c555bbbed..46ffe81d0 100644 --- a/src/nvme/ioctl.c +++ b/src/nvme/ioctl.c @@ -30,6 +30,7 @@ #include "util.h" #include "log.h" #include "private.h" +#include "linux.h" static int nvme_verify_chr(nvme_link_t l) { @@ -97,6 +98,9 @@ int nvme_submit_passthru64(nvme_link_t l, unsigned long ioctl_cmd, struct nvme_passthru_cmd64 *cmd, __u64 *result) { + if (cmd->timeout_ms == NVME_DEFAULT_IOCTL_TIMEOUT) + cmd->timeout_ms = nvme_link_get_timeout(l); + int err = ioctl(l->fd, ioctl_cmd, cmd); if (err >= 0 && result) @@ -110,6 +114,9 @@ __attribute__((weak)) int nvme_submit_passthru(nvme_link_t l, unsigned long ioctl_cmd, struct nvme_passthru_cmd *cmd, __u32 *result) { + if (cmd->timeout_ms == NVME_DEFAULT_IOCTL_TIMEOUT) + cmd->timeout_ms = nvme_link_get_timeout(l); + int err = ioctl(l->fd, ioctl_cmd, cmd); if (err >= 0 && result) @@ -635,325 +642,6 @@ int nvme_get_ana_log_atomic(nvme_link_t l, bool rae, bool rgo, return -EAGAIN; } -int nvme_set_features(nvme_link_t l, struct nvme_set_features_args *args) -{ - __u32 cdw10 = NVME_SET(args->fid, FEATURES_CDW10_FID) | - NVME_SET(!!args->save, SET_FEATURES_CDW10_SAVE); - __u32 cdw14 = NVME_SET(args->uuidx, FEATURES_CDW14_UUID); - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_admin_set_features, - .nsid = args->nsid, - .addr = (__u64)(uintptr_t)args->data, - .data_len = args->data_len, - .cdw10 = cdw10, - .cdw11 = args->cdw11, - .cdw12 = args->cdw12, - .cdw13 = args->cdw13, - .cdw14 = cdw14, - .cdw15 = args->cdw15, - .timeout_ms = args->timeout, - }; - if (args->args_size < sizeof(*args)) - return -EINVAL; - - return nvme_submit_admin_passthru(l, &cmd, args->result); -} - -static int __nvme_set_features(nvme_link_t l, __u8 fid, __u32 cdw11, bool save, - __u32 *result) -{ - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fid = fid, - .nsid = NVME_NSID_NONE, - .cdw11 = cdw11, - .cdw12 = 0, - .save = save, - .uuidx = NVME_UUID_NONE, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - return nvme_set_features(l, &args); -} - -int nvme_set_features_arbitration(nvme_link_t l, __u8 ab, __u8 lpw, __u8 mpw, - __u8 hpw, bool save, __u32 *result) -{ - __u32 value = NVME_SET(ab, FEAT_ARBITRATION_BURST) | - NVME_SET(lpw, FEAT_ARBITRATION_LPW) | - NVME_SET(mpw, FEAT_ARBITRATION_MPW) | - NVME_SET(hpw, FEAT_ARBITRATION_HPW); - - return __nvme_set_features(l, NVME_FEAT_FID_ARBITRATION, value, save, - result); -} - -int nvme_set_features_power_mgmt(nvme_link_t l, __u8 ps, __u8 wh, bool save, - __u32 *result) -{ - __u32 value = NVME_SET(ps, FEAT_PWRMGMT_PS) | - NVME_SET(wh, FEAT_PWRMGMT_WH); - - return __nvme_set_features(l, NVME_FEAT_FID_POWER_MGMT, value, save, - result); -} - -int nvme_set_features_lba_range(nvme_link_t l, __u32 nsid, __u8 nr_ranges, bool save, - struct nvme_lba_range_type *data, __u32 *result) -{ - return nvme_set_features_data( - l, NVME_FEAT_FID_LBA_RANGE, nsid, nr_ranges - 1, save, - sizeof(*data), data, result); -} - -int nvme_set_features_temp_thresh(nvme_link_t l, __u16 tmpth, __u8 tmpsel, - enum nvme_feat_tmpthresh_thsel thsel, __u8 tmpthh, - bool save, __u32 *result) -{ - __u32 value = NVME_SET(tmpth, FEAT_TT_TMPTH) | - NVME_SET(tmpsel, FEAT_TT_TMPSEL) | - NVME_SET(thsel, FEAT_TT_THSEL) | - NVME_SET(tmpthh, FEAT_TT_TMPTHH); - - return __nvme_set_features(l, NVME_FEAT_FID_TEMP_THRESH, value, save, - result); -} - -int nvme_set_features_err_recovery(nvme_link_t l, __u32 nsid, __u16 tler, bool dulbe, - bool save, __u32 *result) -{ - __u32 value = NVME_SET(tler, FEAT_ERROR_RECOVERY_TLER) | - NVME_SET(!!dulbe, FEAT_ERROR_RECOVERY_DULBE); - - return nvme_set_features_simple( - l, NVME_FEAT_FID_ERR_RECOVERY, nsid, value, save, result); -} - -int nvme_set_features_volatile_wc(nvme_link_t l, bool wce, bool save, __u32 *result) -{ - __u32 value = NVME_SET(!!wce, FEAT_VWC_WCE); - - return __nvme_set_features(l, NVME_FEAT_FID_VOLATILE_WC, value, save, - result); -} - -int nvme_set_features_irq_coalesce(nvme_link_t l, __u8 thr, __u8 time, bool save, - __u32 *result) -{ - __u32 value = NVME_SET(thr, FEAT_IRQC_THR) | - NVME_SET(time, FEAT_IRQC_TIME); - - return __nvme_set_features(l, NVME_FEAT_FID_IRQ_COALESCE, value, save, - result); -} - -int nvme_set_features_irq_config(nvme_link_t l, __u16 iv, bool cd, bool save, - __u32 *result) -{ - __u32 value = NVME_SET(iv, FEAT_ICFG_IV) | - NVME_SET(!!cd, FEAT_ICFG_CD); - - return __nvme_set_features(l, NVME_FEAT_FID_IRQ_CONFIG, value, save, - result); -} - -int nvme_set_features_write_atomic(nvme_link_t l, bool dn, bool save, __u32 *result) -{ - __u32 value = NVME_SET(!!dn, FEAT_WA_DN); - - return __nvme_set_features(l, NVME_FEAT_FID_WRITE_ATOMIC, value, save, - result); -} - -int nvme_set_features_async_event(nvme_link_t l, __u32 events, - bool save, __u32 *result) -{ - return __nvme_set_features(l, NVME_FEAT_FID_ASYNC_EVENT, events, save, - result); -} - -int nvme_set_features_auto_pst(nvme_link_t l, bool apste, bool save, - struct nvme_feat_auto_pst *apst, __u32 *result) -{ - return nvme_set_features_data(l, NVME_FEAT_FID_AUTO_PST, - NVME_NSID_NONE, NVME_SET(!!apste, FEAT_APST_APSTE), save, - sizeof(*apst), apst, result); -} - -int nvme_set_features_timestamp(nvme_link_t l, bool save, __u64 timestamp) -{ - __le64 t = cpu_to_le64(timestamp); - struct nvme_timestamp ts = {}; - memcpy(ts.timestamp, &t, sizeof(ts.timestamp)); - - return nvme_set_features_data(l, NVME_FEAT_FID_TIMESTAMP, - NVME_NSID_NONE, 0, save, sizeof(ts), &ts, NULL); -} - -int nvme_set_features_hctm(nvme_link_t l, __u16 tmt2, __u16 tmt1, - bool save, __u32 *result) -{ - __u32 value = NVME_SET(tmt2, FEAT_HCTM_TMT2) | - NVME_SET(tmt1, FEAT_HCTM_TMT1); - - return __nvme_set_features(l, NVME_FEAT_FID_HCTM, value, save, - result); -} - -int nvme_set_features_nopsc(nvme_link_t l, bool noppme, bool save, __u32 *result) -{ - __u32 value = NVME_SET(noppme, FEAT_NOPS_NOPPME); - - return __nvme_set_features(l, NVME_FEAT_FID_NOPSC, value, save, - result); -} - -int nvme_set_features_rrl(nvme_link_t l, __u8 rrl, __u16 nvmsetid, - bool save, __u32 *result) -{ - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fid = NVME_FEAT_FID_RRL, - .nsid = NVME_NSID_NONE, - .cdw11 = nvmsetid, - .cdw12 = rrl, - .save = save, - .uuidx = NVME_UUID_NONE, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - - return nvme_set_features(l, &args); -} - -int nvme_set_features_plm_config(nvme_link_t l, bool plm, __u16 nvmsetid, bool save, - struct nvme_plm_config *data, __u32 *result) -{ - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fid = NVME_FEAT_FID_PLM_CONFIG, - .nsid = NVME_NSID_NONE, - .cdw11 = nvmsetid, - .cdw12 = !!plm, - .save = save, - .uuidx = NVME_UUID_NONE, - .cdw15 = 0, - .data_len = sizeof(*data), - .data = data, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - - return nvme_set_features(l, &args); -} - -int nvme_set_features_plm_window(nvme_link_t l, enum nvme_feat_plm_window_select sel, - __u16 nvmsetid, bool save, __u32 *result) -{ - __u32 cdw12 = NVME_SET(sel, FEAT_PLMW_WS); - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fid = NVME_FEAT_FID_PLM_WINDOW, - .nsid = NVME_NSID_NONE, - .cdw11 = nvmsetid, - .cdw12 = cdw12, - .save = save, - .uuidx = NVME_UUID_NONE, - .cdw15 = 0, - .data_len = 0, - .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - - return nvme_set_features(l, &args); -} - -int nvme_set_features_lba_sts_interval(nvme_link_t l, __u16 lsiri, __u16 lsipi, - bool save, __u32 *result) -{ - __u32 value = NVME_SET(lsiri, FEAT_LBAS_LSIRI) | - NVME_SET(lsipi, FEAT_LBAS_LSIPI); - - return __nvme_set_features(l, NVME_FEAT_FID_LBA_STS_INTERVAL, value, - save, result); -} - -int nvme_set_features_host_behavior(nvme_link_t l, bool save, - struct nvme_feat_host_behavior *data) -{ - return nvme_set_features_data(l, NVME_FEAT_FID_HOST_BEHAVIOR, - NVME_NSID_NONE, 0, false, sizeof(*data), data, NULL); -} - -int nvme_set_features_sanitize(nvme_link_t l, bool nodrm, bool save, __u32 *result) -{ - return __nvme_set_features(l, NVME_FEAT_FID_SANITIZE, !!nodrm, save, - result); -} - -int nvme_set_features_endurance_evt_cfg(nvme_link_t l, __u16 endgid, __u8 egwarn, - bool save, __u32 *result) -{ - __u32 value = endgid | egwarn << 16; - - return __nvme_set_features(l, NVME_FEAT_FID_ENDURANCE_EVT_CFG, value, - save, result); -} - -int nvme_set_features_sw_progress(nvme_link_t l, __u8 pbslc, bool save, - __u32 *result) -{ - return __nvme_set_features(l, NVME_FEAT_FID_SW_PROGRESS, pbslc, save, - result); -} - -int nvme_set_features_host_id(nvme_link_t l, bool exhid, bool save, __u8 *hostid) -{ - __u32 len = exhid ? 16 : 8; - __u32 value = !!exhid; - - return nvme_set_features_data(l, NVME_FEAT_FID_HOST_ID, - NVME_NSID_NONE, value, save, len, hostid, NULL); -} - -int nvme_set_features_resv_mask(nvme_link_t l, __u32 nsid, __u32 mask, bool save, - __u32 *result) -{ - return nvme_set_features_simple( - l, NVME_FEAT_FID_RESV_MASK, nsid, mask, save, result); -} - -int nvme_set_features_resv_persist(nvme_link_t l, __u32 nsid, bool ptpl, bool save, - __u32 *result) -{ - return nvme_set_features_simple( - l, NVME_FEAT_FID_RESV_PERSIST, nsid, !!ptpl, save, result); -} - -int nvme_set_features_write_protect(nvme_link_t l, __u32 nsid, - enum nvme_feat_nswpcfg_state state, - bool save, __u32 *result) -{ - return nvme_set_features_simple( - l, NVME_FEAT_FID_WRITE_PROTECT, nsid, state, false, result); -} - -int nvme_set_features_iocs_profile(nvme_link_t l, __u16 iocsi, bool save) -{ - __u32 value = NVME_SET(iocsi, FEAT_IOCSP_IOCSCI); - - return __nvme_set_features(l, NVME_FEAT_FID_IOCS_PROFILE, value, - save, NULL); -} - int nvme_get_features(nvme_link_t l, struct nvme_get_features_args *args) { __u32 cdw10 = NVME_SET(args->fid, FEATURES_CDW10_FID) | @@ -989,7 +677,6 @@ static int __nvme_get_features(nvme_link_t l, enum nvme_features_id fid, .uuidx = NVME_UUID_NONE, .data_len = 0, .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = result, }; @@ -1020,7 +707,6 @@ int nvme_get_features_lba_range(nvme_link_t l, enum nvme_get_features_sel sel, .uuidx = NVME_UUID_NONE, .data = data, .data_len = sizeof(*data), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = result, }; @@ -1039,7 +725,6 @@ int nvme_get_features_temp_thresh(nvme_link_t l, enum nvme_get_features_sel sel, .uuidx = NVME_UUID_NONE, .data_len = 0, .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = result, }; @@ -1056,7 +741,6 @@ int nvme_get_features_err_recovery(nvme_link_t l, enum nvme_get_features_sel sel .nsid = nsid, .sel = sel, .uuidx = NVME_UUID_NONE, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = result, }; @@ -1094,7 +778,6 @@ int nvme_get_features_irq_config(nvme_link_t l, enum nvme_get_features_sel sel, .uuidx = NVME_UUID_NONE, .data_len = 0, .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = result, }; @@ -1126,7 +809,6 @@ int nvme_get_features_auto_pst(nvme_link_t l, enum nvme_get_features_sel sel, .uuidx = NVME_UUID_NONE, .data_len = sizeof(*apst), .data = apst, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = result, }; @@ -1145,7 +827,6 @@ int nvme_get_features_host_mem_buf(nvme_link_t l, enum nvme_get_features_sel sel .uuidx = NVME_UUID_NONE, .data = attrs, .data_len = sizeof(*attrs), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = result, }; @@ -1164,7 +845,6 @@ int nvme_get_features_timestamp(nvme_link_t l, enum nvme_get_features_sel sel, .uuidx = NVME_UUID_NONE, .data_len = sizeof(*ts), .data = ts, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = NULL, }; @@ -1204,7 +884,6 @@ int nvme_get_features_plm_config(nvme_link_t l, enum nvme_get_features_sel sel, .uuidx = NVME_UUID_NONE, .data_len = sizeof(*data), .data = data, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = result, }; @@ -1223,7 +902,6 @@ int nvme_get_features_plm_window(nvme_link_t l, enum nvme_get_features_sel sel, .uuidx = NVME_UUID_NONE, .data_len = 0, .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = result, }; @@ -1250,7 +928,6 @@ int nvme_get_features_host_behavior(nvme_link_t l, enum nvme_get_features_sel se .uuidx = NVME_UUID_NONE, .data_len = sizeof(*data), .data = data, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = result, }; @@ -1275,7 +952,6 @@ int nvme_get_features_endurance_event_cfg(nvme_link_t l, enum nvme_get_features_ .uuidx = NVME_UUID_NONE, .data_len = 0, .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = result, }; @@ -1300,7 +976,6 @@ int nvme_get_features_host_id(nvme_link_t l, enum nvme_get_features_sel sel, .uuidx = NVME_UUID_NONE, .data_len = len, .data = hostid, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = NULL, }; @@ -1316,7 +991,6 @@ int nvme_get_features_resv_mask(nvme_link_t l, enum nvme_get_features_sel sel, .nsid = nsid, .sel = sel, .uuidx = NVME_UUID_NONE, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = result, }; @@ -1332,7 +1006,6 @@ int nvme_get_features_resv_persist(nvme_link_t l, enum nvme_get_features_sel sel .nsid = nsid, .sel = sel, .uuidx = NVME_UUID_NONE, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = result, }; @@ -1352,7 +1025,6 @@ int nvme_get_features_write_protect(nvme_link_t l, __u32 nsid, .uuidx = NVME_UUID_NONE, .data_len = 0, .data = NULL, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = result, }; @@ -1454,7 +1126,6 @@ int nvme_directive_send_id_endir(nvme_link_t l, __u32 nsid, bool endir, .cdw12 = cdw12, .data_len = sizeof(*id), .data = id, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = NULL, }; @@ -2195,24 +1866,6 @@ int nvme_lm_migration_recv(nvme_link_t l, struct nvme_lm_migration_recv_args *ar return nvme_submit_admin_passthru(l, &cmd, args->result); } -int nvme_lm_set_features_ctrl_data_queue(nvme_link_t l, __u16 cdqid, __u32 hp, __u32 tpt, bool etpt, - __u32 *result) -{ - struct nvme_set_features_args args = { - .args_size = sizeof(args), - .fid = NVME_FEAT_FID_CTRL_DATA_QUEUE, - .nsid = NVME_NSID_NONE, - .cdw11 = cdqid | NVME_SET(etpt, LM_CTRL_DATA_QUEUE_ETPT), - .cdw12 = hp, - .cdw13 = tpt, - .save = false, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = result, - }; - - return nvme_set_features(l, &args); -} - int nvme_lm_get_features_ctrl_data_queue(nvme_link_t l, __u16 cdqid, struct nvme_lm_ctrl_data_queue_fid_data *data, __u32 *result) @@ -2224,7 +1877,6 @@ int nvme_lm_get_features_ctrl_data_queue(nvme_link_t l, __u16 cdqid, .cdw11 = cdqid, .data = data, .data_len = sizeof(*data), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = result, }; diff --git a/src/nvme/ioctl.h b/src/nvme/ioctl.h index 9e0720d4b..7a2a726be 100644 --- a/src/nvme/ioctl.h +++ b/src/nvme/ioctl.h @@ -10,8 +10,10 @@ #ifndef _LIBNVME_IOCTL_H #define _LIBNVME_IOCTL_H +#include #include #include +#include #include #include @@ -2208,66 +2210,104 @@ static inline int nvme_get_log_lockdown(nvme_link_t l, /** * nvme_set_features() - Set a feature attribute * @l: Link handle - * @args: &struct nvme_set_features_args argument structure + * @nsid: Namespace ID, if applicable + * @cdw11: Value to set the feature to + * @cdw12: Feature specific command dword12 field + * @cdw13: Feature specific command dword13 field + * @cdw15: Feature specific command dword15 field + * @fid: Feature identifier + * @sv: Save value across power states + * @uidx: UUID Index for differentiating vendor specific encoding + * @data: User address of feature data, if applicable + * @data_len: Length of feature data, if applicable, in bytes + * @result: The command completion result from CQE dword0 * * 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_set_features(nvme_link_t l, struct nvme_set_features_args *args); +static inline int nvme_set_features(nvme_link_t l, __u32 nsid, __u32 cdw11, + __u32 cdw12, __u32 cdw13, __u32 cdw15, + __u8 fid, bool sv, __u8 uidx, void *data, + __u32 data_len, __u32 *result) +{ + __u32 cdw10 = NVME_SET(fid, FEATURES_CDW10_FID) | + NVME_SET(!!sv, SET_FEATURES_CDW10_SAVE); + __u32 cdw14 = NVME_SET(uidx, FEATURES_CDW14_UUID); + + struct nvme_passthru_cmd cmd = { + .opcode = nvme_admin_set_features, + .nsid = nsid, + .addr = (__u64)(uintptr_t)data, + .data_len = data_len, + .cdw10 = cdw10, + .cdw11 = cdw11, + .cdw12 = cdw12, + .cdw13 = cdw13, + .cdw14 = cdw14, + .cdw15 = cdw15, + }; + + return nvme_submit_admin_passthru(l, &cmd, result); +} /** - * nvme_set_features_data() - Helper function for @nvme_set_features() + * __nvme_set_features() - Internal helper function for @nvme_set_features() * @l: Link handle + * @cdw11: Value to set the feature to * @fid: Feature identifier + * @sv: Save value across power states + * @result: The command completion result from CQE dword0 + * + * Return: The nvme command status if a response was received (see + * &enum nvme_status_field) or -1 with errno set otherwise. + */ +static int __nvme_set_features(nvme_link_t l, __u32 cdw11, __u8 fid, bool sv, + __u32 *result) +{ + return nvme_set_features(l, NVME_NSID_NONE, cdw11, 0, 0, 0, fid, sv, + NVME_UUID_NONE, NULL, 0, result); +} + +/** + * nvme_set_features_data() - Helper function for @nvme_set_features() + * @l: Link handle * @nsid: Namespace ID, if applicable * @cdw11: Value to set the feature to - * @save: Save value across power states - * @data_len: Length of feature data, if applicable, in bytes + * @fid: Feature identifier + * @sv: Save value across power states * @data: User address of feature data, if applicable + * @data_len: Length of feature data, if applicable, in bytes * @result: The command completion result from CQE dword0 * * Return: 0 on success, the nvme command status if a response was * received (see &enum nvme_status_field) or a negative error otherwise. */ -static inline int nvme_set_features_data(nvme_link_t l, __u8 fid, __u32 nsid, - __u32 cdw11, bool save, __u32 data_len, void *data, - __u32 *result) +static inline int nvme_set_features_data(nvme_link_t l, __u32 nsid, __u32 cdw11, + __u8 fid, bool sv, void *data, + __u32 data_len, __u32 *result) { - struct nvme_set_features_args args = { - .result = result, - .data = data, - .args_size = sizeof(args), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .nsid = nsid, - .cdw11 = cdw11, - .cdw12 = 0, - .cdw13 = 0, - .cdw15 = 0, - .data_len = data_len, - .save = save, - .uuidx = NVME_UUID_NONE, - .fid = fid, - }; - return nvme_set_features(l, &args); + return nvme_set_features(l, nsid, cdw11, 0, 0, 0, fid, sv, + NVME_UUID_NONE, data, data_len, result); } /** * nvme_set_features_simple() - Helper function for @nvme_set_features() * @l: Link handle - * @fid: Feature identifier * @nsid: Namespace ID, if applicable * @cdw11: Value to set the feature to - * @save: Save value across power states + * @fid: Feature identifier + * @sv: Save value across power states * @result: The command completion result from CQE dword0 * * Return: 0 on success, the nvme command status if a response was * received (see &enum nvme_status_field) or a negative error otherwise. */ -static inline int nvme_set_features_simple(nvme_link_t l, __u8 fid, __u32 nsid, - __u32 cdw11, bool save, __u32 *result) +static inline int nvme_set_features_simple(nvme_link_t l, __u32 nsid, + __u32 cdw11, __u8 fid, bool sv, + __u32 *result) { - return nvme_set_features_data(l, fid, nsid, cdw11, save, 0, NULL, - result); + return nvme_set_features_data(l, nsid, cdw11, fid, sv, NULL, 0, + result); } /** @@ -2277,43 +2317,64 @@ static inline int nvme_set_features_simple(nvme_link_t l, __u8 fid, __u32 nsid, * @lpw: Low Priority Weight * @mpw: Medium Priority Weight * @hpw: High Priority Weight - * @save: Save value across power states + * @sv: Save value across power states * @result: The command completion result from CQE dword0 * * 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_set_features_arbitration(nvme_link_t l, __u8 ab, __u8 lpw, __u8 mpw, - __u8 hpw, bool save, __u32 *result); +static inline int nvme_set_features_arbitration(nvme_link_t l, __u8 ab, __u8 lpw, __u8 mpw, + __u8 hpw, bool sv, __u32 *result) +{ + __u32 value = NVME_SET(ab, FEAT_ARBITRATION_BURST) | + NVME_SET(lpw, FEAT_ARBITRATION_LPW) | + NVME_SET(mpw, FEAT_ARBITRATION_MPW) | + NVME_SET(hpw, FEAT_ARBITRATION_HPW); + + return __nvme_set_features(l, value, NVME_FEAT_FID_ARBITRATION, sv, + result); +} /** * nvme_set_features_power_mgmt() - Set power management feature * @l: Link handle * @ps: Power State * @wh: Workload Hint - * @save: Save value across power states + * @sv: Save value across power states * @result: The command completion result from CQE dword0 * * 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_set_features_power_mgmt(nvme_link_t l, __u8 ps, __u8 wh, bool save, - __u32 *result); +static inline int nvme_set_features_power_mgmt(nvme_link_t l, __u8 ps, __u8 wh, bool sv, + __u32 *result) +{ + __u32 value = NVME_SET(ps, FEAT_PWRMGMT_PS) | + NVME_SET(wh, FEAT_PWRMGMT_WH); + + return __nvme_set_features(l, value, NVME_FEAT_FID_POWER_MGMT, sv, + result); +} /** * nvme_set_features_lba_range() - Set LBA range feature * @l: Link handle * @nsid: Namespace ID - * @nr_ranges: Number of ranges in @data - * @save: Save value across power states + * @num: Number of ranges in @data + * @sv: Save value across power states * @data: User address of feature data * @result: The command completion result from CQE dword0 * * 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_set_features_lba_range(nvme_link_t l, __u32 nsid, __u8 nr_ranges, bool save, - struct nvme_lba_range_type *data, __u32 *result); +static inline int nvme_set_features_lba_range(nvme_link_t l, __u32 nsid, __u8 num, bool sv, + struct nvme_lba_range_type *data, __u32 *result) +{ + return nvme_set_features_data(l, nsid, num - 1, + NVME_FEAT_FID_LBA_RANGE, sv, data, + sizeof(*data), result); +} /** * nvme_set_features_temp_thresh() - Set temperature threshold feature @@ -2322,15 +2383,24 @@ int nvme_set_features_lba_range(nvme_link_t l, __u32 nsid, __u8 nr_ranges, bool * @tmpsel: Threshold Temperature Select * @thsel: Threshold Type Select * @tmpthh: Temperature Threshold Hysteresis - * @save: Save value across power states + * @sv: Save value across power states * @result: The command completion result from CQE dword0 * * 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_set_features_temp_thresh(nvme_link_t l, __u16 tmpth, __u8 tmpsel, - enum nvme_feat_tmpthresh_thsel thsel, __u8 tmpthh, - bool save, __u32 *result); +static inline int nvme_set_features_temp_thresh(nvme_link_t l, __u16 tmpth, __u8 tmpsel, + enum nvme_feat_tmpthresh_thsel thsel, + __u8 tmpthh, bool sv, __u32 *result) +{ + __u32 value = NVME_SET(tmpth, FEAT_TT_TMPTH) | + NVME_SET(tmpsel, FEAT_TT_TMPSEL) | + NVME_SET(thsel, FEAT_TT_THSEL) | + NVME_SET(tmpthh, FEAT_TT_TMPTHH); + + return __nvme_set_features(l, value, NVME_FEAT_FID_TEMP_THRESH, sv, + result); +} /** * nvme_set_features_err_recovery() - Set error recovery feature @@ -2338,308 +2408,439 @@ int nvme_set_features_temp_thresh(nvme_link_t l, __u16 tmpth, __u8 tmpsel, * @nsid: Namespace ID * @tler: Time-limited error recovery value * @dulbe: Deallocated or Unwritten Logical Block Error Enable - * @save: Save value across power states + * @sv: Save value across power states * @result: The command completion result from CQE dword0 * * 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_set_features_err_recovery(nvme_link_t l, __u32 nsid, __u16 tler, - bool dulbe, bool save, __u32 *result); +static inline int nvme_set_features_err_recovery(nvme_link_t l, __u32 nsid, __u16 tler, + bool dulbe, bool sv, __u32 *result) +{ + __u32 value = NVME_SET(tler, FEAT_ERROR_RECOVERY_TLER) | + NVME_SET(!!dulbe, FEAT_ERROR_RECOVERY_DULBE); + + return nvme_set_features_simple(l, nsid, value, NVME_FEAT_FID_ERR_RECOVERY, + sv, result); +} /** * nvme_set_features_volatile_wc() - Set volatile write cache feature * @l: Link handle * @wce: Write cache enable - * @save: Save value across power states + * @sv: Save value across power states * @result: The command completion result from CQE dword0 * * 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_set_features_volatile_wc(nvme_link_t l, bool wce, bool save, - __u32 *result); +static inline int nvme_set_features_volatile_wc(nvme_link_t l, bool wce, bool sv, + __u32 *result) +{ + __u32 value = NVME_SET(!!wce, FEAT_VWC_WCE); + return __nvme_set_features(l, value, NVME_FEAT_FID_VOLATILE_WC, sv, + result); +} /** * nvme_set_features_irq_coalesce() - Set IRQ coalesce feature * @l: Link handle * @thr: Aggregation Threshold * @time: Aggregation Time - * @save: Save value across power states + * @sv: Save value across power states * @result: The command completion result from CQE dword0 * * 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_set_features_irq_coalesce(nvme_link_t l, __u8 thr, __u8 time, - bool save, __u32 *result); +static inline int nvme_set_features_irq_coalesce(nvme_link_t l, __u8 thr, __u8 time, + bool sv, __u32 *result) +{ + __u32 value = NVME_SET(thr, FEAT_IRQC_THR) | + NVME_SET(time, FEAT_IRQC_TIME); + + return __nvme_set_features(l, value, NVME_FEAT_FID_IRQ_COALESCE, sv, + result); +} /** * nvme_set_features_irq_config() - Set IRQ config feature * @l: Link handle * @iv: Interrupt Vector * @cd: Coalescing Disable - * @save: Save value across power states + * @sv: Save value across power states * @result: The command completion result from CQE dword0 * * 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_set_features_irq_config(nvme_link_t l, __u16 iv, bool cd, bool save, - __u32 *result); +static inline int nvme_set_features_irq_config(nvme_link_t l, __u16 iv, bool cd, bool sv, + __u32 *result) +{ + __u32 value = NVME_SET(iv, FEAT_ICFG_IV) | + NVME_SET(!!cd, FEAT_ICFG_CD); + + return __nvme_set_features(l, value, NVME_FEAT_FID_IRQ_CONFIG, sv, + result); +} /** * nvme_set_features_write_atomic() - Set write atomic feature * @l: Link handle * @dn: Disable Normal - * @save: Save value across power states + * @sv: Save value across power states * @result: The command completion result from CQE dword0 * * 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_set_features_write_atomic(nvme_link_t l, bool dn, bool save, - __u32 *result); +static inline int nvme_set_features_write_atomic(nvme_link_t l, bool dn, bool sv, + __u32 *result) +{ + __u32 value = NVME_SET(!!dn, FEAT_WA_DN); + + return __nvme_set_features(l, value, NVME_FEAT_FID_WRITE_ATOMIC, sv, + result); +} /** * nvme_set_features_async_event() - Set asynchronous event feature * @l: Link handle * @events: Events to enable - * @save: Save value across power states + * @sv: Save value across power states * @result: The command completion result from CQE dword0 * * 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_set_features_async_event(nvme_link_t l, __u32 events, bool save, - __u32 *result); +static inline int nvme_set_features_async_event(nvme_link_t l, __u32 events, bool sv, + __u32 *result) +{ + return __nvme_set_features(l, events, NVME_FEAT_FID_ASYNC_EVENT, sv, + result); +} /** * nvme_set_features_auto_pst() - Set autonomous power state feature * @l: Link handle * @apste: Autonomous Power State Transition Enable * @apst: Autonomous Power State Transition - * @save: Save value across power states + * @sv: Save value across power states * @result: The command completion result from CQE dword0 * * 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_set_features_auto_pst(nvme_link_t l, bool apste, bool save, - struct nvme_feat_auto_pst *apst, - __u32 *result); +static inline int nvme_set_features_auto_pst(nvme_link_t l, bool apste, + struct nvme_feat_auto_pst *apst, bool sv, + __u32 *result) +{ + return nvme_set_features_data(l, NVME_NSID_NONE, + NVME_SET(!!apste, FEAT_APST_APSTE), + NVME_FEAT_FID_AUTO_PST, sv, apst, + sizeof(*apst), result); +} /** * nvme_set_features_timestamp() - Set timestamp feature * @l: Link handle - * @save: Save value across power states - * @timestamp: The current timestamp value to assign to this feature + * @tstmp: The current timestamp value to assign to this feature + * @sv: Save value across power states * * 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_set_features_timestamp(nvme_link_t l, bool save, __u64 timestamp); +static inline int nvme_set_features_timestamp(nvme_link_t l, __u64 tstmp, bool sv) +{ + __le64 t = htole64(tstmp); + struct nvme_timestamp ts = {}; + + memcpy(ts.timestamp, &t, sizeof(ts.timestamp)); + return nvme_set_features_data(l, NVME_NSID_NONE, 0, NVME_FEAT_FID_TIMESTAMP, + sv, &ts, sizeof(ts), NULL); +} /** * nvme_set_features_hctm() - Set thermal management feature * @l: Link handle * @tmt2: Thermal Management Temperature 2 * @tmt1: Thermal Management Temperature 1 - * @save: Save value across power states + * @sv: Save value across power states * @result: The command completion result from CQE dword0 * * 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_set_features_hctm(nvme_link_t l, __u16 tmt2, __u16 tmt1, bool save, - __u32 *result); +static inline int nvme_set_features_hctm(nvme_link_t l, __u16 tmt2, __u16 tmt1, bool sv, + __u32 *result) +{ + __u32 value = NVME_SET(tmt2, FEAT_HCTM_TMT2) | + NVME_SET(tmt1, FEAT_HCTM_TMT1); + + return __nvme_set_features(l, value, NVME_FEAT_FID_HCTM, sv, + result); +} /** * nvme_set_features_nopsc() - Set non-operational power state feature * @l: Link handle * @noppme: Non-Operational Power State Permissive Mode Enable - * @save: Save value across power states + * @sv: Save value across power states * @result: The command completion result from CQE dword0 * * 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_set_features_nopsc(nvme_link_t l, bool noppme, bool save, __u32 *result); +static inline int nvme_set_features_nopsc(nvme_link_t l, bool noppme, bool sv, __u32 *result) +{ + __u32 value = NVME_SET(noppme, FEAT_NOPS_NOPPME); + + return __nvme_set_features(l, value, NVME_FEAT_FID_NOPSC, sv, + result); +} /** * nvme_set_features_rrl() - Set read recovery level feature * @l: Link handle - * @rrl: Read recovery level setting * @nvmsetid: NVM set id - * @save: Save value across power states + * @rrl: Read recovery level setting + * @sv: Save value across power states * @result: The command completion result from CQE dword0 * * 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_set_features_rrl(nvme_link_t l, __u8 rrl, __u16 nvmsetid, bool save, - __u32 *result); +static inline int nvme_set_features_rrl(nvme_link_t l, __u16 nvmsetid, __u8 rrl, bool sv, + __u32 *result) +{ + return nvme_set_features(l, NVME_NSID_NONE, nvmsetid, rrl, 0, 0, + NVME_FEAT_FID_RRL, sv, NVME_UUID_NONE, + NULL, 0, result); +} /** * nvme_set_features_plm_config() - Set predictable latency feature * @l: Link handle - * @enable: Predictable Latency Enable * @nvmsetid: NVM Set Identifier - * @save: Save value across power states + * @lpe: Predictable Latency Enable + * @sv: Save value across power states * @data: Pointer to structure nvme_plm_config * @result: The command completion result from CQE dword0 * * 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_set_features_plm_config(nvme_link_t l, bool enable, __u16 nvmsetid, - bool save, struct nvme_plm_config *data, - __u32 *result); +static inline int nvme_set_features_plm_config(nvme_link_t l, __u16 nvmsetid, bool lpe, + bool sv, struct nvme_plm_config *data, + __u32 *result) +{ + return nvme_set_features(l, NVME_NSID_NONE, nvmsetid, !!lpe, 0, 0, + NVME_FEAT_FID_PLM_CONFIG, sv, + NVME_UUID_NONE, data, sizeof(*data), + result); +} /** * nvme_set_features_plm_window() - Set window select feature * @l: Link handle - * @sel: Window Select * @nvmsetid: NVM Set Identifier - * @save: Save value across power states + * @wsel: Window Select + * @sv: Save value across power states * @result: The command completion result from CQE dword0 * * 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_set_features_plm_window(nvme_link_t l, enum nvme_feat_plm_window_select sel, - __u16 nvmsetid, bool save, __u32 *result); +static inline int nvme_set_features_plm_window(nvme_link_t l, __u16 nvmsetid, + enum nvme_feat_plm_window_select wsel, + bool sv, __u32 *result) +{ + return nvme_set_features(l, NVME_NSID_NONE, nvmsetid, + NVME_SET(wsel, FEAT_PLMW_WS), 0, 0, + NVME_FEAT_FID_PLM_WINDOW, sv, + NVME_UUID_NONE, NULL, 0, result); +} /** * nvme_set_features_lba_sts_interval() - Set LBA status information feature * @l: Link handle - * @save: Save value across power states * @lsiri: LBA Status Information Report Interval * @lsipi: LBA Status Information Poll Interval + * @sv: Save value across power states * @result: The command completion result from CQE dword0 * * 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_set_features_lba_sts_interval(nvme_link_t l, __u16 lsiri, __u16 lsipi, - bool save, __u32 *result); +static inline int nvme_set_features_lba_sts_interval(nvme_link_t l, __u16 lsiri, __u16 lsipi, + bool sv, __u32 *result) +{ + __u32 value = NVME_SET(lsiri, FEAT_LBAS_LSIRI) | + NVME_SET(lsipi, FEAT_LBAS_LSIPI); + + return __nvme_set_features(l, value, NVME_FEAT_FID_LBA_STS_INTERVAL, + sv, result); +} /** * nvme_set_features_host_behavior() - Set host behavior feature * @l: Link handle - * @save: Save value across power states + * @sv: Save value across power states * @data: Pointer to structure nvme_feat_host_behavior * * 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_set_features_host_behavior(nvme_link_t l, bool save, - struct nvme_feat_host_behavior *data); +static inline int nvme_set_features_host_behavior(nvme_link_t l, bool sv, + struct nvme_feat_host_behavior *data) +{ + return nvme_set_features_data(l, NVME_NSID_NONE, 0, + NVME_FEAT_FID_HOST_BEHAVIOR, + sv, data, sizeof(*data), NULL); +} /** * nvme_set_features_sanitize() - Set sanitize feature * @l: Link handle * @nodrm: No-Deallocate Response Mode - * @save: Save value across power states + * @sv: Save value across power states * @result: The command completion result from CQE dword0 * * 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_set_features_sanitize(nvme_link_t l, bool nodrm, bool save, __u32 *result); +static inline int nvme_set_features_sanitize(nvme_link_t l, bool nodrm, bool sv, __u32 *result) +{ + return __nvme_set_features(l, !!nodrm, NVME_FEAT_FID_SANITIZE, sv, + result); +} /** * nvme_set_features_endurance_evt_cfg() - Set endurance event config feature * @l: Link handle * @endgid: Endurance Group Identifier - * @egwarn: Flags to enable warning, see &enum nvme_eg_critical_warning_flags - * @save: Save value across power states + * @egcw: Flags to enable warning, see &enum nvme_eg_critical_warning_flags + * @sv: Save value across power states * @result: The command completion result from CQE dword0 * * 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_set_features_endurance_evt_cfg(nvme_link_t l, __u16 endgid, __u8 egwarn, - bool save, __u32 *result); +static inline int nvme_set_features_endurance_evt_cfg(nvme_link_t l, __u16 endgid, __u8 egcw, + bool sv, __u32 *result) +{ + __u32 value = endgid | egcw << 16; + + return __nvme_set_features(l, value, NVME_FEAT_FID_ENDURANCE_EVT_CFG, + sv, result); +} /** * nvme_set_features_sw_progress() - Set pre-boot software load count feature * @l: Link handle * @pbslc: Pre-boot Software Load Count - * @save: Save value across power states + * @sv: Save value across power states * @result: The command completion result from CQE dword0 * * 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_set_features_sw_progress(nvme_link_t l, __u8 pbslc, bool save, - __u32 *result); +static inline int nvme_set_features_sw_progress(nvme_link_t l, __u8 pbslc, bool sv, + __u32 *result) +{ + return __nvme_set_features(l, pbslc, NVME_FEAT_FID_SW_PROGRESS, sv, + result); +} /** * nvme_set_features_host_id() - Set enable extended host identifiers feature * @l: Link handle * @exhid: Enable Extended Host Identifier - * @save: Save value across power states + * @sv: Save value across power states * @hostid: Host ID to set * * 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_set_features_host_id(nvme_link_t l, bool exhid, bool save, __u8 *hostid); +static inline int nvme_set_features_host_id(nvme_link_t l, bool exhid, bool sv, __u8 *hostid) +{ + __u32 len = exhid ? 16 : 8; + __u32 value = !!exhid; + + return nvme_set_features_data(l, NVME_NSID_NONE, value, NVME_FEAT_FID_HOST_ID, + sv, hostid, len, NULL); +} /** * nvme_set_features_resv_mask() - Set reservation notification mask feature * @l: Link handle * @nsid: Namespace ID * @mask: Reservation Notification Mask Field - * @save: Save value across power states + * @sv: Save value across power states * @result: The command completion result from CQE dword0 * * 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_set_features_resv_mask(nvme_link_t l, __u32 nsid, __u32 mask, bool save, - __u32 *result); +static inline int nvme_set_features_resv_mask(nvme_link_t l, __u32 nsid, __u32 mask, bool sv, + __u32 *result) +{ + return nvme_set_features_simple(l, nsid, mask, NVME_FEAT_FID_RESV_MASK, sv, result); +} /** * nvme_set_features_resv_persist() - Set persist through power loss feature * @l: Link handle * @nsid: Namespace ID * @ptpl: Persist Through Power Loss - * @save: Save value across power states + * @sv: Save value across power states * @result: The command completion result from CQE dword0 * * 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_set_features_resv_persist(nvme_link_t l, __u32 nsid, bool ptpl, bool save, - __u32 *result); +static inline int nvme_set_features_resv_persist(nvme_link_t l, __u32 nsid, bool ptpl, bool sv, + __u32 *result) +{ + return nvme_set_features_simple(l, nsid, !!ptpl, + NVME_FEAT_FID_RESV_PERSIST, sv, result); +} /** * nvme_set_features_write_protect() - Set write protect feature * @l: Link handle * @nsid: Namespace ID - * @state: Write Protection State - * @save: Save value across power states + * @wps: Write Protection State + * @sv: Save value across power states * @result: The command completion result from CQE dword0 * * 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_set_features_write_protect(nvme_link_t l, __u32 nsid, - enum nvme_feat_nswpcfg_state state, - bool save, __u32 *result); +static inline int nvme_set_features_write_protect(nvme_link_t l, __u32 nsid, + enum nvme_feat_nswpcfg_state wps, + bool sv, __u32 *result) +{ + return nvme_set_features_simple(l, nsid, wps, + NVME_FEAT_FID_WRITE_PROTECT, sv, result); +} /** * nvme_set_features_iocs_profile() - Set I/O command set profile feature * @l: Link handle - * @iocsi: I/O Command Set Combination Index - * @save: Save value across power states + * @iocsci: I/O Command Set Combination Index + * @sv: Save value across power states * * 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_set_features_iocs_profile(nvme_link_t l, __u16 iocsi, bool save); +static inline int nvme_set_features_iocs_profile(nvme_link_t l, __u16 iocsci, bool sv) +{ + __u32 value = NVME_SET(iocsci, FEAT_IOCSP_IOCSCI); + + return __nvme_set_features(l, value, NVME_FEAT_FID_IOCS_PROFILE, + sv, NULL); +} /** * nvme_get_features() - Retrieve a feature attribute @@ -2670,7 +2871,6 @@ static inline int nvme_get_features_data(nvme_link_t l, enum nvme_features_id fi .result = result, .data = data, .args_size = sizeof(args), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .nsid = nsid, .sel = NVME_GET_FEATURES_SEL_CURRENT, .cdw11 = 0, @@ -3454,7 +3654,6 @@ static inline int nvme_directive_send_stream_release_identifier(nvme_link_t l, .result = NULL, .data = NULL, .args_size = sizeof(args), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .nsid = nsid, .doper = NVME_DIRECTIVE_SEND_STREAMS_DOPER_RELEASE_IDENTIFIER, .dtype = NVME_DIRECTIVE_DTYPE_STREAMS, @@ -3480,7 +3679,6 @@ static inline int nvme_directive_send_stream_release_resource(nvme_link_t l, __u .result = NULL, .data = NULL, .args_size = sizeof(args), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .nsid = nsid, .doper = NVME_DIRECTIVE_SEND_STREAMS_DOPER_RELEASE_RESOURCE, .dtype = NVME_DIRECTIVE_DTYPE_STREAMS, @@ -3518,7 +3716,6 @@ static inline int nvme_directive_recv_identify_parameters(nvme_link_t l, __u32 n .result = NULL, .data = id, .args_size = sizeof(args), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .nsid = nsid, .doper = NVME_DIRECTIVE_RECEIVE_IDENTIFY_DOPER_PARAM, .dtype = NVME_DIRECTIVE_DTYPE_IDENTIFY, @@ -3546,7 +3743,6 @@ static inline int nvme_directive_recv_stream_parameters(nvme_link_t l, __u32 nsi .result = NULL, .data = parms, .args_size = sizeof(args), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .nsid = nsid, .doper = NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_PARAM, .dtype = NVME_DIRECTIVE_DTYPE_STREAMS, @@ -3581,7 +3777,6 @@ static inline int nvme_directive_recv_stream_status(nvme_link_t l, __u32 nsid, .result = NULL, .data = id, .args_size = sizeof(args), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .nsid = nsid, .doper = NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_STATUS, .dtype = NVME_DIRECTIVE_DTYPE_STREAMS, @@ -3610,7 +3805,6 @@ static inline int nvme_directive_recv_stream_allocate(nvme_link_t l, __u32 nsid, .result = result, .data = NULL, .args_size = sizeof(args), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .nsid = nsid, .doper = NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_RESOURCE, .dtype = NVME_DIRECTIVE_DTYPE_STREAMS, @@ -3956,7 +4150,6 @@ static inline int nvme_fdp_reclaim_unit_handle_status(nvme_link_t l, __u32 nsid, .args_size = sizeof(args), .nsid = nsid, .data_len = data_len, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .mos = 0, .mo = NVME_IO_MGMT_RECV_RUH_STATUS, }; @@ -3992,7 +4185,6 @@ static inline int nvme_fdp_reclaim_unit_handle_update(nvme_link_t l, __u32 nsid, .args_size = sizeof(args), .nsid = nsid, .data_len = (__u32)(npids * sizeof(__u16)), - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .mos = (__u16)(npids - 1), .mo = NVME_IO_MGMT_SEND_RUH_UPDATE, }; @@ -4031,7 +4223,6 @@ int nvme_zns_mgmt_recv(nvme_link_t l, struct nvme_zns_mgmt_recv_args *args); * @partial: Partial report requested * @data_len: Length of the data buffer * @data: Userspace address of the report zones data - * @timeout: timeout in ms * @result: The command completion result from CQE dword0 * * Return: 0 on success, the nvme command status if a response was @@ -4040,15 +4231,13 @@ int nvme_zns_mgmt_recv(nvme_link_t l, struct nvme_zns_mgmt_recv_args *args); static inline int nvme_zns_report_zones(nvme_link_t l, __u32 nsid, __u64 slba, enum nvme_zns_report_options opts, bool extended, bool partial, - __u32 data_len, void *data, - __u32 timeout, __u32 *result) + __u32 data_len, void *data, __u32 *result) { struct nvme_zns_mgmt_recv_args args = { .slba = slba, .result = result, .data = data, .args_size = sizeof(args), - .timeout = timeout, .nsid = nsid, .zra = extended ? NVME_ZNS_ZRA_EXTENDED_REPORT_ZONES : NVME_ZNS_ZRA_REPORT_ZONES, @@ -4132,8 +4321,14 @@ int nvme_lm_migration_recv(nvme_link_t l, struct nvme_lm_migration_recv_args *ar * 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_lm_set_features_ctrl_data_queue(nvme_link_t l, __u16 cdqid, __u32 hp, __u32 tpt, bool etpt, - __u32 *result); +static inline int nvme_lm_set_features_ctrl_data_queue(nvme_link_t l, __u16 cdqid, __u32 hp, + __u32 tpt, bool etpt, __u32 *result) +{ + return nvme_set_features(l, NVME_NSID_NONE, + cdqid | NVME_SET(etpt, LM_CTRL_DATA_QUEUE_ETPT), + hp, tpt, 0, NVME_FEAT_FID_CTRL_DATA_QUEUE, false, + NVME_UUID_NONE, NULL, 0, result); +} /** * nvme_lm_get_features_ctrl_data_queue - Get Controller Data Queue feature diff --git a/src/nvme/linux.c b/src/nvme/linux.c index c4e616b6c..57abcec15 100644 --- a/src/nvme/linux.c +++ b/src/nvme/linux.c @@ -94,6 +94,7 @@ nvme_link_t __nvme_create_link(nvme_root_t r) return NULL; l->root = r; + l->timeout = NVME_DEFAULT_IOCTL_TIMEOUT; return l; } @@ -184,6 +185,16 @@ const char *nvme_link_get_name(nvme_link_t l) return l->name; } +__u32 nvme_link_get_timeout(nvme_link_t l) +{ + return l->timeout; +} + +void nvme_link_set_timeout(nvme_link_t l, __u32 timeout) +{ + l->timeout = timeout; +} + int nvme_fw_download_seq(nvme_link_t l, __u32 size, __u32 xfer, __u32 offset, void *buf) { @@ -363,7 +374,6 @@ int nvme_get_lba_status_log(nvme_link_t l, bool rae, struct nvme_lba_status_log .lsp = NVME_LOG_LSP_NONE, .lsi = NVME_LOG_LSI_NONE, .uuidx = NVME_UUID_NONE, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, .result = NULL, .csi = NVME_CSI_NVM, .rae = rae, diff --git a/src/nvme/linux.h b/src/nvme/linux.h index c750cddc5..7b04bf07b 100644 --- a/src/nvme/linux.h +++ b/src/nvme/linux.h @@ -251,6 +251,21 @@ bool nvme_link_is_mi(nvme_link_t l); */ const char *nvme_link_get_name(nvme_link_t l); +/** + * nvme_link_get_timeout - Return the command timeout of the device link handle + * @l: Link handle + * + * Return: Command timeout [ms] + */ +__u32 nvme_link_get_timeout(nvme_link_t l); + +/** + * nvme_link_set_timeout - Set the command timeout of the device link handle + * @l: Link handle + * @timeout: Timeout in ms + */ +void nvme_link_set_timeout(nvme_link_t l, __u32 timeout); + /** * enum nvme_hmac_alg - HMAC algorithm * @NVME_HMAC_ALG_NONE: No HMAC algorithm diff --git a/src/nvme/private.h b/src/nvme/private.h index 6162aa9aa..b0fbc0349 100644 --- a/src/nvme/private.h +++ b/src/nvme/private.h @@ -52,6 +52,7 @@ struct nvme_link { struct list_node ep_entry; struct nvme_log *log; + __u32 timeout; }; struct nvme_path { diff --git a/test/ioctl/features.c b/test/ioctl/features.c index 40aacc738..cb78e46ef 100644 --- a/test/ioctl/features.c +++ b/test/ioctl/features.c @@ -7,6 +7,7 @@ #include "mock.h" #include "util.h" +#include #define TEST_FD 0xFD #define TEST_TIMEOUT 1234 @@ -28,21 +29,6 @@ static void test_set_features(void) { uint32_t result = 0; uint8_t data[256]; - struct nvme_set_features_args args = { - .result = &result, - .data = data, - .args_size = sizeof(args), - .timeout = TEST_TIMEOUT, - .nsid = TEST_NSID, - .cdw11 = TEST_CDW11, - .cdw12 = TEST_CDW12, - .cdw13 = TEST_CDW13, - .cdw15 = TEST_CDW15, - .data_len = sizeof(data), - .save = true, - .uuidx = TEST_UUIDX, - .fid = TEST_FID, - }; struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_set_features, .nsid = TEST_NSID, @@ -55,14 +41,15 @@ static void test_set_features(void) .cdw13 = TEST_CDW13, .cdw14 = TEST_UUIDX, .cdw15 = TEST_CDW15, - .timeout_ms = TEST_TIMEOUT, .result = TEST_RESULT, }; int err; arbitrary(data, sizeof(data)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features(test_link, &args); + err = nvme_set_features(test_link, TEST_NSID, TEST_CDW11, TEST_CDW12, TEST_CDW13, + TEST_CDW15, TEST_FID, true, TEST_UUIDX, data, sizeof(data), + &result); end_mock_cmds(); check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, @@ -126,8 +113,8 @@ static void test_set_features_data(void) arbitrary(data, sizeof(data)); set_mock_admin_cmds(&mock_admin_cmd, 1); err = nvme_set_features_data( - test_link, TEST_FID, TEST_NSID, TEST_CDW11, false, - sizeof(data), data, &result); + test_link, TEST_NSID, TEST_CDW11, TEST_FID, false, + data, sizeof(data), &result); end_mock_cmds(); check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, @@ -174,7 +161,7 @@ static void test_set_features_simple(void) set_mock_admin_cmds(&mock_admin_cmd, 1); err = nvme_set_features_simple( - test_link, TEST_FID, TEST_NSID, TEST_CDW11, true, &result); + test_link, TEST_NSID, TEST_CDW11, TEST_FID, true, &result); end_mock_cmds(); check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, @@ -651,7 +638,7 @@ static void test_set_auto_pst(void) arbitrary(&apst, sizeof(apst)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_auto_pst(test_link, true, false, &apst, &result); + err = nvme_set_features_auto_pst(test_link, true, &apst, false, &result); end_mock_cmds(); check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, @@ -724,7 +711,7 @@ static void test_set_timestamp(void) int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_timestamp(test_link, true, timestamp); + err = nvme_set_features_timestamp(test_link, timestamp, true); end_mock_cmds(); check(err == 0, "set features returned error %d", err); } @@ -857,7 +844,7 @@ static void test_set_rrl(void) int err; set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_rrl(test_link, RRL, NVMSETID, false, &result); + err = nvme_set_features_rrl(test_link, NVMSETID, RRL, false, &result); end_mock_cmds(); check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, @@ -903,7 +890,7 @@ static void test_set_plm_config(void) arbitrary(&config, sizeof(config)); set_mock_admin_cmds(&mock_admin_cmd, 1); err = nvme_set_features_plm_config( - test_link, true, NVMSETID, true, &config, &result); + test_link, NVMSETID, true, true, &config, &result); end_mock_cmds(); check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, @@ -952,7 +939,7 @@ static void test_set_plm_window(void) set_mock_admin_cmds(&mock_admin_cmd, 1); err = nvme_set_features_plm_window( - test_link, SEL, NVMSETID, false, &result); + test_link, NVMSETID, SEL, false, &result); end_mock_cmds(); check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, @@ -1024,17 +1011,18 @@ static void test_set_host_behavior(void) { /* nvme_set_features_host_behavior() ignores SAVE */ struct nvme_feat_host_behavior behavior; + bool save = true; struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_set_features, .in_data = &behavior, .data_len = sizeof(behavior), - .cdw10 = NVME_FEAT_FID_HOST_BEHAVIOR, + .cdw10 = NVME_FEAT_FID_HOST_BEHAVIOR | (!!save << 31), }; int err; arbitrary(&behavior, sizeof(behavior)); set_mock_admin_cmds(&mock_admin_cmd, 1); - err = nvme_set_features_host_behavior(test_link, true, &behavior); + err = nvme_set_features_host_behavior(test_link, save, &behavior); end_mock_cmds(); check(err == 0, "set features returned error %d", err); } @@ -1389,10 +1377,11 @@ static void test_set_write_protect(void) /* nvme_set_features_write_protect() ignores SAVE */ enum nvme_feat_nswpcfg_state STATE = NVME_FEAT_NS_WRITE_PROTECT_PERMANENT; + bool save = true; struct mock_cmd mock_admin_cmd = { .opcode = nvme_admin_set_features, .nsid = TEST_NSID, - .cdw10 = NVME_FEAT_FID_WRITE_PROTECT, + .cdw10 = NVME_FEAT_FID_WRITE_PROTECT | (!!save << 31), .cdw11 = STATE, .result = TEST_RESULT, }; @@ -1401,7 +1390,7 @@ static void test_set_write_protect(void) set_mock_admin_cmds(&mock_admin_cmd, 1); err = nvme_set_features_write_protect( - test_link, TEST_NSID, STATE, true, &result); + test_link, TEST_NSID, STATE, save, &result); end_mock_cmds(); check(err == 0, "set features returned error %d", err); check(result == TEST_RESULT, diff --git a/test/ioctl/zns.c b/test/ioctl/zns.c index 53d69bf39..72edc555a 100644 --- a/test/ioctl/zns.c +++ b/test/ioctl/zns.c @@ -60,7 +60,6 @@ static void test_zns_report_zones(void) { __u8 expected_data[8], data[8] = {}; __u32 result = 0; - uint32_t timeout = 1234; bool extended = true; bool partial = true; enum nvme_zns_report_options opts = NVME_ZNS_ZRAS_REPORT_CLOSED; @@ -75,7 +74,6 @@ static void test_zns_report_zones(void) (!!partial << 16), .data_len = sizeof(expected_data), .out_data = &expected_data, - .timeout_ms = timeout, }; int err; @@ -84,7 +82,7 @@ static void test_zns_report_zones(void) set_mock_io_cmds(&mock_io_cmd, 1); err = nvme_zns_report_zones(test_link, TEST_NSID, TEST_SLBA, opts, extended, partial, sizeof(data), &data, - timeout, &result); + &result); end_mock_cmds(); check(err == 0, "returned error %d", err); check(result == 0, "returned result %u", result); diff --git a/test/mi.c b/test/mi.c index 6c754a3a7..8fd80d4e2 100644 --- a/test/mi.c +++ b/test/mi.c @@ -1069,7 +1069,6 @@ static int test_admin_set_features_cb(struct nvme_mi_ep *ep, static void test_set_features(nvme_mi_ep_t ep) { - struct nvme_set_features_args args = { 0 }; struct nvme_timestamp tstamp = { 0 }; nvme_link_t link; uint32_t res; @@ -1083,16 +1082,10 @@ static void test_set_features(nvme_mi_ep_t ep) for (i = 0; i < sizeof(tstamp.timestamp); i++) tstamp.timestamp[i] = i; - args.args_size = sizeof(args); - args.fid = NVME_FEAT_FID_TIMESTAMP; - args.save = 1; - args.result = &res; - args.data = &tstamp; - args.data_len = sizeof(tstamp); - - rc = nvme_set_features(link, &args); + rc = nvme_set_features(link, 0, 0, 0, 0, 0, NVME_FEAT_FID_TIMESTAMP, + 1, 0, &tstamp, sizeof(tstamp), &res); assert(rc == 0); - assert(args.data_len == 8); + assert(sizeof(tstamp) == 8); } enum ns_type { diff --git a/test/zns.c b/test/zns.c index 5d76555a8..e73a24384 100644 --- a/test/zns.c +++ b/test/zns.c @@ -48,8 +48,7 @@ static void show_zns_properties(nvme_ns_t n) if (nvme_zns_report_zones(nvme_ns_get_link(n), nvme_ns_get_nsid(n), 0, NVME_ZNS_ZRAS_REPORT_ALL, false, - true, 0x1000, (void *)zr, - NVME_DEFAULT_IOCTL_TIMEOUT, &result)) { + true, 0x1000, (void *)zr, &result)) { fprintf(stderr, "failed to report zones, result %x\n", le32_to_cpu(result)); free(zr);