From 36a20972ec71d4f109646f3c208e5e487dc3be93 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Fri, 27 Feb 2026 10:35:51 +0100 Subject: [PATCH 01/29] src: use standard lookup for libnvme include The libnvme.h header is not a local header file, thus use the standard lookup <> for external headers. Signed-off-by: Daniel Wagner --- nvme-print-json.c | 3 ++- nvme-print-stdout.c | 3 ++- nvme-print.c | 3 ++- nvme-rpmb.c | 3 ++- plugins/amzn/amzn-nvme.c | 3 ++- plugins/dapustor/dapustor-nvme.c | 3 ++- plugins/dell/dell-nvme.c | 3 ++- plugins/dera/dera-nvme.c | 3 ++- plugins/fdp/fdp.c | 3 ++- plugins/huawei/huawei-nvme.c | 3 ++- plugins/innogrit/innogrit-nvme.c | 3 ++- plugins/inspur/inspur-nvme.c | 3 ++- plugins/intel/intel-nvme.c | 3 ++- plugins/lm/lm-nvme.c | 3 ++- plugins/lm/lm-print.h | 3 ++- plugins/mangoboost/mangoboost-nvme.c | 3 ++- plugins/memblaze/memblaze-nvme.c | 3 ++- plugins/micron/micron-nvme.c | 4 +++- plugins/nbft/nbft-plugin.c | 1 + plugins/netapp/netapp-nvme.c | 3 ++- plugins/nvidia/nvidia-nvme.c | 3 ++- plugins/ocp/ocp-fw-activation-history.h | 1 + plugins/ocp/ocp-nvme.c | 3 ++- plugins/ocp/ocp-telemetry-decode.c | 2 +- plugins/sandisk/sandisk-nvme.c | 3 ++- plugins/sandisk/sandisk-utils.c | 4 +++- plugins/scaleflux/sfx-nvme.c | 3 ++- plugins/seagate/seagate-nvme.c | 3 ++- plugins/sed/sed.c | 3 ++- plugins/shannon/shannon-nvme.c | 2 +- plugins/solidigm/solidigm-garbage-collection.c | 3 ++- plugins/solidigm/solidigm-internal-logs.c | 3 ++- plugins/solidigm/solidigm-latency-tracking.c | 3 ++- plugins/solidigm/solidigm-market-log.c | 3 ++- plugins/solidigm/solidigm-smart.c | 3 ++- plugins/solidigm/solidigm-telemetry.c | 3 ++- plugins/solidigm/solidigm-telemetry/telemetry-log.h | 3 ++- plugins/ssstc/ssstc-nvme.c | 3 ++- plugins/toshiba/toshiba-nvme.c | 3 ++- plugins/transcend/transcend-nvme.c | 3 ++- plugins/virtium/virtium-nvme.c | 3 ++- plugins/wdc/wdc-nvme.c | 3 ++- plugins/wdc/wdc-utils.c | 4 +++- plugins/ymtc/ymtc-nvme.c | 3 ++- plugins/zns/zns.c | 3 ++- 45 files changed, 89 insertions(+), 43 deletions(-) diff --git a/nvme-print-json.c b/nvme-print-json.c index da7dc8a0f4..d75e19f654 100644 --- a/nvme-print-json.c +++ b/nvme-print-json.c @@ -8,13 +8,14 @@ #include #include +#include + #include "nvme-print.h" #include "util/json.h" #include "logging.h" #include "nvme.h" #include "common.h" -#include "libnvme.h" #define ERROR_MSG_LEN 100 #define NAME_LEN 128 diff --git a/nvme-print-stdout.c b/nvme-print-stdout.c index ddc33f9587..5142f92f51 100644 --- a/nvme-print-stdout.c +++ b/nvme-print-stdout.c @@ -14,8 +14,9 @@ #include #include +#include + #include "nvme.h" -#include "libnvme.h" #include "nvme-print.h" #include "nvme-models.h" #include "util/suffix.h" diff --git a/nvme-print.c b/nvme-print.c index b388ff0880..b4d9273f2b 100644 --- a/nvme-print.c +++ b/nvme-print.c @@ -8,8 +8,9 @@ #include #include +#include + #include "nvme.h" -#include "libnvme.h" #include "nvme-print.h" #include "nvme-models.h" #include "util/suffix.h" diff --git a/nvme-rpmb.c b/nvme-rpmb.c index 963ebc7f2f..9583dbf0a1 100644 --- a/nvme-rpmb.c +++ b/nvme-rpmb.c @@ -29,9 +29,10 @@ #include #include +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "nvme-print.h" #define CREATE_CMD diff --git a/plugins/amzn/amzn-nvme.c b/plugins/amzn/amzn-nvme.c index fdb48b2a71..13851e3295 100644 --- a/plugins/amzn/amzn-nvme.c +++ b/plugins/amzn/amzn-nvme.c @@ -6,9 +6,10 @@ #include #include +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "plugin.h" #include "nvme-print.h" diff --git a/plugins/dapustor/dapustor-nvme.c b/plugins/dapustor/dapustor-nvme.c index 894c9f7d17..d2b3cc3439 100644 --- a/plugins/dapustor/dapustor-nvme.c +++ b/plugins/dapustor/dapustor-nvme.c @@ -11,9 +11,10 @@ #include +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "plugin.h" #include "nvme-print.h" diff --git a/plugins/dell/dell-nvme.c b/plugins/dell/dell-nvme.c index d77138eb2c..73d40cfa81 100644 --- a/plugins/dell/dell-nvme.c +++ b/plugins/dell/dell-nvme.c @@ -7,9 +7,10 @@ #include #include +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "plugin.h" #define CREATE_CMD diff --git a/plugins/dera/dera-nvme.c b/plugins/dera/dera-nvme.c index 8db1847012..4634e878fd 100644 --- a/plugins/dera/dera-nvme.c +++ b/plugins/dera/dera-nvme.c @@ -10,8 +10,9 @@ #include #include +#include + #include "nvme.h" -#include "libnvme.h" #include "plugin.h" #include "linux/types.h" #include "nvme-print.h" diff --git a/plugins/fdp/fdp.c b/plugins/fdp/fdp.c index 208a6878f6..896a4ee24e 100644 --- a/plugins/fdp/fdp.c +++ b/plugins/fdp/fdp.c @@ -9,9 +9,10 @@ #include #include +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "nvme-print.h" #define CREATE_CMD diff --git a/plugins/huawei/huawei-nvme.c b/plugins/huawei/huawei-nvme.c index 54066324ac..65f3fc73c6 100644 --- a/plugins/huawei/huawei-nvme.c +++ b/plugins/huawei/huawei-nvme.c @@ -27,9 +27,10 @@ #include +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "plugin.h" #include "util/suffix.h" diff --git a/plugins/innogrit/innogrit-nvme.c b/plugins/innogrit/innogrit-nvme.c index 957a2fc9d4..2c130c4cd0 100644 --- a/plugins/innogrit/innogrit-nvme.c +++ b/plugins/innogrit/innogrit-nvme.c @@ -7,9 +7,10 @@ #include #include +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "nvme-print.h" #include "typedef.h" #include "util/cleanup.h" diff --git a/plugins/inspur/inspur-nvme.c b/plugins/inspur/inspur-nvme.c index b4bf161e14..7681a8ee63 100644 --- a/plugins/inspur/inspur-nvme.c +++ b/plugins/inspur/inspur-nvme.c @@ -10,9 +10,10 @@ #include #include +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "plugin.h" #include "nvme-print.h" #include "util/suffix.h" diff --git a/plugins/intel/intel-nvme.c b/plugins/intel/intel-nvme.c index 3c8a92e395..3e5bb5ef63 100644 --- a/plugins/intel/intel-nvme.c +++ b/plugins/intel/intel-nvme.c @@ -6,9 +6,10 @@ #include #include +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "plugin.h" #include "linux/types.h" #include "nvme-print.h" diff --git a/plugins/lm/lm-nvme.c b/plugins/lm/lm-nvme.c index a30f9bd424..b4b565cda4 100644 --- a/plugins/lm/lm-nvme.c +++ b/plugins/lm/lm-nvme.c @@ -23,10 +23,11 @@ #include #include +#include + #include "common.h" #include "nvme.h" #include "nvme-print.h" -#include "libnvme.h" #include "plugin.h" #include "linux/types.h" #include "util/cleanup.h" diff --git a/plugins/lm/lm-print.h b/plugins/lm/lm-print.h index 8a647021f6..b3f8ece85f 100644 --- a/plugins/lm/lm-print.h +++ b/plugins/lm/lm-print.h @@ -2,8 +2,9 @@ #ifndef LM_PRINT_H #define LM_PRINT_H +#include + #include "nvme.h" -#include "libnvme.h" struct lm_print_ops { void (*controller_state_data)(struct nvme_lm_controller_state_data *data, size_t len, diff --git a/plugins/mangoboost/mangoboost-nvme.c b/plugins/mangoboost/mangoboost-nvme.c index 8d64386208..aa45268819 100644 --- a/plugins/mangoboost/mangoboost-nvme.c +++ b/plugins/mangoboost/mangoboost-nvme.c @@ -12,9 +12,10 @@ #include #include +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "plugin.h" #define CREATE_CMD diff --git a/plugins/memblaze/memblaze-nvme.c b/plugins/memblaze/memblaze-nvme.c index ba6b45aa13..fd93cc6f76 100644 --- a/plugins/memblaze/memblaze-nvme.c +++ b/plugins/memblaze/memblaze-nvme.c @@ -7,9 +7,10 @@ #include #include +#include + #include "nvme.h" #include "common.h" -#include "libnvme.h" #include "plugin.h" #include "linux/types.h" #include "nvme-print.h" diff --git a/plugins/micron/micron-nvme.c b/plugins/micron/micron-nvme.c index f3224385c4..1d74b459a6 100644 --- a/plugins/micron/micron-nvme.c +++ b/plugins/micron/micron-nvme.c @@ -23,9 +23,11 @@ #include #include #include + +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include #include "linux/types.h" #include "nvme-print.h" diff --git a/plugins/nbft/nbft-plugin.c b/plugins/nbft/nbft-plugin.c index 41ae9103f9..d652d2044e 100644 --- a/plugins/nbft/nbft-plugin.c +++ b/plugins/nbft/nbft-plugin.c @@ -5,6 +5,7 @@ #include #include + #include "nvme-print.h" #include "nvme.h" #include "fabrics.h" diff --git a/plugins/netapp/netapp-nvme.c b/plugins/netapp/netapp-nvme.c index 5eb21b25d4..e3e78b2bec 100644 --- a/plugins/netapp/netapp-nvme.c +++ b/plugins/netapp/netapp-nvme.c @@ -24,9 +24,10 @@ #include #include +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "util/suffix.h" diff --git a/plugins/nvidia/nvidia-nvme.c b/plugins/nvidia/nvidia-nvme.c index e4e3d9b6fb..0568e85e99 100644 --- a/plugins/nvidia/nvidia-nvme.c +++ b/plugins/nvidia/nvidia-nvme.c @@ -6,9 +6,10 @@ #include #include +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "plugin.h" #define CREATE_CMD diff --git a/plugins/ocp/ocp-fw-activation-history.h b/plugins/ocp/ocp-fw-activation-history.h index 89a86f65da..f5c5277ad7 100644 --- a/plugins/ocp/ocp-fw-activation-history.h +++ b/plugins/ocp/ocp-fw-activation-history.h @@ -5,6 +5,7 @@ * Authors: karl.dedow@solidigm.com */ #include + #include "common.h" #include "linux/types.h" diff --git a/plugins/ocp/ocp-nvme.c b/plugins/ocp/ocp-nvme.c index e646142709..2ec2d98b7c 100644 --- a/plugins/ocp/ocp-nvme.c +++ b/plugins/ocp/ocp-nvme.c @@ -16,9 +16,10 @@ #include #include +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "plugin.h" #include "linux/types.h" #include "util/types.h" diff --git a/plugins/ocp/ocp-telemetry-decode.c b/plugins/ocp/ocp-telemetry-decode.c index f1c1e50d9a..62738c8b45 100644 --- a/plugins/ocp/ocp-telemetry-decode.c +++ b/plugins/ocp/ocp-telemetry-decode.c @@ -3,10 +3,10 @@ * * Authors: Jeff Lien , */ +#include #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "plugin.h" #include "linux/types.h" #include "util/types.h" diff --git a/plugins/sandisk/sandisk-nvme.c b/plugins/sandisk/sandisk-nvme.c index 76dd84d901..806cbcd83a 100644 --- a/plugins/sandisk/sandisk-nvme.c +++ b/plugins/sandisk/sandisk-nvme.c @@ -14,9 +14,10 @@ #include #include +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "plugin.h" #include "linux/types.h" #include "util/cleanup.h" diff --git a/plugins/sandisk/sandisk-utils.c b/plugins/sandisk/sandisk-utils.c index 4efc687080..df4e576e7b 100644 --- a/plugins/sandisk/sandisk-utils.c +++ b/plugins/sandisk/sandisk-utils.c @@ -11,9 +11,11 @@ #include #include #include + +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "nvme-print.h" #include "sandisk-utils.h" #include "plugins/wdc/wdc-nvme-cmds.h" diff --git a/plugins/scaleflux/sfx-nvme.c b/plugins/scaleflux/sfx-nvme.c index ff8c3aa003..2635e02fea 100644 --- a/plugins/scaleflux/sfx-nvme.c +++ b/plugins/scaleflux/sfx-nvme.c @@ -14,9 +14,10 @@ #include #include +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "plugin.h" #include "linux/types.h" #include "nvme-print.h" diff --git a/plugins/seagate/seagate-nvme.c b/plugins/seagate/seagate-nvme.c index 740171cf4a..02c7a68bc8 100644 --- a/plugins/seagate/seagate-nvme.c +++ b/plugins/seagate/seagate-nvme.c @@ -32,9 +32,10 @@ #include #include #include +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "plugin.h" #include "linux/types.h" #include "nvme-print.h" diff --git a/plugins/sed/sed.c b/plugins/sed/sed.c index 9cfbebd764..5a3d828f82 100644 --- a/plugins/sed/sed.c +++ b/plugins/sed/sed.c @@ -9,9 +9,10 @@ #include #include +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "nvme-print.h" #include "sedopal_cmd.h" #include diff --git a/plugins/shannon/shannon-nvme.c b/plugins/shannon/shannon-nvme.c index 8882b4ce72..13af395908 100644 --- a/plugins/shannon/shannon-nvme.c +++ b/plugins/shannon/shannon-nvme.c @@ -5,10 +5,10 @@ #include #include #include +#include #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "plugin.h" #include "linux/types.h" #include "nvme-print.h" diff --git a/plugins/solidigm/solidigm-garbage-collection.c b/plugins/solidigm/solidigm-garbage-collection.c index f3d39bdb4b..5d9c7b8f5c 100644 --- a/plugins/solidigm/solidigm-garbage-collection.c +++ b/plugins/solidigm/solidigm-garbage-collection.c @@ -12,9 +12,10 @@ #include #include +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "plugin.h" #include "linux/types.h" #include "nvme-print.h" diff --git a/plugins/solidigm/solidigm-internal-logs.c b/plugins/solidigm/solidigm-internal-logs.c index be1b0e4e6b..f18bf6bdc1 100644 --- a/plugins/solidigm/solidigm-internal-logs.c +++ b/plugins/solidigm/solidigm-internal-logs.c @@ -15,9 +15,10 @@ #include #include +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "plugin.h" #include "nvme-print.h" #include "solidigm-util.h" diff --git a/plugins/solidigm/solidigm-latency-tracking.c b/plugins/solidigm/solidigm-latency-tracking.c index e6baff174f..5987da5192 100644 --- a/plugins/solidigm/solidigm-latency-tracking.c +++ b/plugins/solidigm/solidigm-latency-tracking.c @@ -11,9 +11,10 @@ #include #include +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "plugin.h" #include "linux/types.h" #include "nvme-print.h" diff --git a/plugins/solidigm/solidigm-market-log.c b/plugins/solidigm/solidigm-market-log.c index cd6efdeef9..39b33daffe 100644 --- a/plugins/solidigm/solidigm-market-log.c +++ b/plugins/solidigm/solidigm-market-log.c @@ -13,9 +13,10 @@ #include #include +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "plugin.h" #include "nvme-print.h" #include "solidigm-util.h" diff --git a/plugins/solidigm/solidigm-smart.c b/plugins/solidigm/solidigm-smart.c index aeebad3c27..d8e5fa7e82 100644 --- a/plugins/solidigm/solidigm-smart.c +++ b/plugins/solidigm/solidigm-smart.c @@ -11,9 +11,10 @@ #include #include +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "plugin.h" #include "linux/types.h" #include "nvme-print.h" diff --git a/plugins/solidigm/solidigm-telemetry.c b/plugins/solidigm/solidigm-telemetry.c index ee8f430816..13d2b302e5 100644 --- a/plugins/solidigm/solidigm-telemetry.c +++ b/plugins/solidigm/solidigm-telemetry.c @@ -11,9 +11,10 @@ #include #include +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "plugin.h" #include "nvme-print.h" #include "solidigm-telemetry.h" diff --git a/plugins/solidigm/solidigm-telemetry/telemetry-log.h b/plugins/solidigm/solidigm-telemetry/telemetry-log.h index f09a81b9be..7da5547382 100644 --- a/plugins/solidigm/solidigm-telemetry/telemetry-log.h +++ b/plugins/solidigm/solidigm-telemetry/telemetry-log.h @@ -8,7 +8,8 @@ #ifndef _SOLIDIGM_TELEMETRY_LOG_H #define _SOLIDIGM_TELEMETRY_LOG_H -#include "libnvme.h" +#include + #include "util/json.h" #include #include diff --git a/plugins/ssstc/ssstc-nvme.c b/plugins/ssstc/ssstc-nvme.c index 0a2468b9d6..f35275327d 100644 --- a/plugins/ssstc/ssstc-nvme.c +++ b/plugins/ssstc/ssstc-nvme.c @@ -6,9 +6,10 @@ #include #include +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "plugin.h" #include "linux/types.h" #include "nvme-print.h" diff --git a/plugins/toshiba/toshiba-nvme.c b/plugins/toshiba/toshiba-nvme.c index 2b0fd926aa..87569793c3 100644 --- a/plugins/toshiba/toshiba-nvme.c +++ b/plugins/toshiba/toshiba-nvme.c @@ -8,8 +8,9 @@ #include #include +#include + #include "nvme.h" -#include "libnvme.h" #include "plugin.h" #include "linux/types.h" #include "nvme-print.h" diff --git a/plugins/transcend/transcend-nvme.c b/plugins/transcend/transcend-nvme.c index e62115fc27..3c36f2434a 100644 --- a/plugins/transcend/transcend-nvme.c +++ b/plugins/transcend/transcend-nvme.c @@ -6,8 +6,9 @@ #include #include +#include + #include "nvme.h" -#include "libnvme.h" #include "plugin.h" #define CREATE_CMD diff --git a/plugins/virtium/virtium-nvme.c b/plugins/virtium/virtium-nvme.c index f3fc93251c..1e8e5e5d4b 100644 --- a/plugins/virtium/virtium-nvme.c +++ b/plugins/virtium/virtium-nvme.c @@ -10,9 +10,10 @@ #include #include +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "plugin.h" #include "util/types.h" diff --git a/plugins/wdc/wdc-nvme.c b/plugins/wdc/wdc-nvme.c index bbccb470f0..c5d65147e6 100644 --- a/plugins/wdc/wdc-nvme.c +++ b/plugins/wdc/wdc-nvme.c @@ -31,9 +31,10 @@ #include #include +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "plugin.h" #include "linux/types.h" #include "util/cleanup.h" diff --git a/plugins/wdc/wdc-utils.c b/plugins/wdc/wdc-utils.c index 9fb708e0d7..7e257d355d 100644 --- a/plugins/wdc/wdc-utils.c +++ b/plugins/wdc/wdc-utils.c @@ -24,8 +24,10 @@ #include #include #include + +#include + #include "nvme.h" -#include "libnvme.h" #include "nvme-print.h" #include "wdc-utils.h" diff --git a/plugins/ymtc/ymtc-nvme.c b/plugins/ymtc/ymtc-nvme.c index b461e7371d..9e65ccadf7 100644 --- a/plugins/ymtc/ymtc-nvme.c +++ b/plugins/ymtc/ymtc-nvme.c @@ -5,8 +5,9 @@ #include #include +#include + #include "nvme.h" -#include "libnvme.h" #include "plugin.h" #include "linux/types.h" #include "nvme-print.h" diff --git a/plugins/zns/zns.c b/plugins/zns/zns.c index 9c1c1155ae..4fdfc160c6 100644 --- a/plugins/zns/zns.c +++ b/plugins/zns/zns.c @@ -9,9 +9,10 @@ #include #include +#include + #include "common.h" #include "nvme.h" -#include "libnvme.h" #include "nvme-print.h" #include "util/cleanup.h" From 747030b3b27793291e1e75b58c0ba1c263e91d12 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 25 Feb 2026 19:23:19 +0100 Subject: [PATCH 02/29] ioctl: use correct defines for set_features field encode Use the set feature defines instead of the identify. Signed-off-by: Daniel Wagner --- libnvme/src/nvme/ioctl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libnvme/src/nvme/ioctl.h b/libnvme/src/nvme/ioctl.h index f52e404c91..69d317cdc7 100644 --- a/libnvme/src/nvme/ioctl.h +++ b/libnvme/src/nvme/ioctl.h @@ -6970,8 +6970,8 @@ nvme_set_features(struct nvme_transport_handle *hdl, __u32 nsid, __u8 fid, cmd.cdw12 = cdw12; cmd.cdw13 = cdw13; cmd.cdw14 = NVME_FIELD_ENCODE(uidx, - NVME_IDENTIFY_CDW14_UUID_SHIFT, - NVME_IDENTIFY_CDW14_UUID_MASK); + NVME_SET_FEATURES_CDW14_UUID_SHIFT, + NVME_SET_FEATURES_CDW14_UUID_MASK); cmd.cdw15 = cdw15; cmd.data_len = len; cmd.addr = (__u64)(uintptr_t)data; From 960c1bc8005b91409fb81160e022d306e050cfe1 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Tue, 3 Mar 2026 16:57:49 +0100 Subject: [PATCH 03/29] test: add header include test Add a simple test which ensures that all headers are self contained and don't have an undocumented dependency. Signed-off-by: Daniel Wagner --- libnvme/test/meson.build | 27 +++++++++++++++++++++++++++ libnvme/test/test-header.c.in | 11 +++++++++++ 2 files changed, 38 insertions(+) create mode 100644 libnvme/test/test-header.c.in diff --git a/libnvme/test/meson.build b/libnvme/test/meson.build index 5b21e8f557..f33641b4ab 100644 --- a/libnvme/test/meson.build +++ b/libnvme/test/meson.build @@ -176,3 +176,30 @@ if openssl_dep.found() dependencies: openssl_dep, ) endif + +foreach hdr : [ + 'fabrics', + 'filters', + 'ioctl', + 'linux', + 'log', + 'mi', + 'nbft', + 'tree', + 'types', + 'util', +] + hdr_conf = configuration_data() + hdr_conf.set('HDR', hdr) + src = configure_file( + input: 'test-header.c.in', + output: 'test-header-' + hdr + '.c', + configuration: hdr_conf, + ) + exe = executable( + 'test-header-' + hdr, + src, + dependencies: [libnvme_dep], + ) + test('libnvme - header/' + hdr, exe) +endforeach diff --git a/libnvme/test/test-header.c.in b/libnvme/test/test-header.c.in new file mode 100644 index 0000000000..73864bda3b --- /dev/null +++ b/libnvme/test/test-header.c.in @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/* + * Verify that is self-sufficient: it can be included + * as the very first (and only) header without any prior includes. + */ +#include + +int main(void) +{ + return 0; +} From 2a1fb44ceba68626c3fbe0f42c666a2d9acfcfed Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 25 Feb 2026 19:50:23 +0100 Subject: [PATCH 04/29] libnvme: include main headers where possible Unify the header includes. Use the libnvme.h or/and libnvme-mi.h everywhere instead indiviual headers. This makes the refactoring of the headers simpler (splitting them into smaller ones). Signed-off-by: Daniel Wagner --- libnvme/libnvme/nvme.i | 7 +------ libnvme/src/nvme/fabrics.c | 9 +++------ libnvme/src/nvme/filters.c | 3 ++- libnvme/src/nvme/ioctl.c | 3 ++- libnvme/src/nvme/json.c | 5 ++--- libnvme/src/nvme/linux.c | 9 ++++----- libnvme/src/nvme/log.c | 6 ++++-- libnvme/src/nvme/mi-mctp.c | 5 +++-- libnvme/src/nvme/mi.c | 6 +++--- libnvme/src/nvme/nbft.c | 4 ++-- libnvme/src/nvme/no-json.c | 2 +- libnvme/src/nvme/tree.c | 11 +++-------- libnvme/src/nvme/util.c | 3 ++- libnvme/test/ioctl/logs.c | 2 -- libnvme/test/ioctl/misc.c | 3 +-- libnvme/test/ioctl/mock.c | 5 +++-- libnvme/test/ioctl/zns.c | 3 +-- libnvme/test/mi-mctp.c | 6 ++++-- libnvme/test/mi.c | 6 +++--- libnvme/test/nbft/nbft-dump.c | 3 ++- libnvme/test/test-util.c | 3 +-- libnvme/test/test.c | 4 ++-- libnvme/test/zns.c | 3 ++- 23 files changed, 51 insertions(+), 60 deletions(-) diff --git a/libnvme/libnvme/nvme.i b/libnvme/libnvme/nvme.i index e658ebafa0..8fc2a3989b 100644 --- a/libnvme/libnvme/nvme.i +++ b/libnvme/libnvme/nvme.i @@ -28,13 +28,8 @@ %{ #include #include - #include "nvme/tree.h" - #include "nvme/fabrics.h" + #include #include "nvme/private.h" - #include "nvme/log.h" - #include "nvme/ioctl.h" - #include "nvme/types.h" - #include "nvme/nbft.h" static int connect_err = 0; static int discover_err = 0; diff --git a/libnvme/src/nvme/fabrics.c b/libnvme/src/nvme/fabrics.c index ac5775df8f..ab58bd7e15 100644 --- a/libnvme/src/nvme/fabrics.c +++ b/libnvme/src/nvme/fabrics.c @@ -33,15 +33,12 @@ #include #include +#include + #include "cleanup.h" -#include "fabrics.h" -#include "linux.h" -#include "ioctl.h" -#include "nbft.h" -#include "nvme/tree.h" -#include "util.h" #include "log.h" #include "private.h" +#include "util.h" #define NVMF_HOSTID_SIZE 37 diff --git a/libnvme/src/nvme/filters.c b/libnvme/src/nvme/filters.c index 4a8829db17..3aa351bcbd 100644 --- a/libnvme/src/nvme/filters.c +++ b/libnvme/src/nvme/filters.c @@ -10,7 +10,8 @@ #include #include -#include "filters.h" +#include + #include "private.h" int nvme_namespace_filter(const struct dirent *d) diff --git a/libnvme/src/nvme/ioctl.c b/libnvme/src/nvme/ioctl.c index 0ad051a359..91769d738b 100644 --- a/libnvme/src/nvme/ioctl.c +++ b/libnvme/src/nvme/ioctl.c @@ -26,7 +26,8 @@ #include #include -#include "ioctl.h" +#include + #include "private.h" static int nvme_verify_chr(struct nvme_transport_handle *hdl) diff --git a/libnvme/src/nvme/json.c b/libnvme/src/nvme/json.c index 674eaebf4a..b0276ed9f7 100644 --- a/libnvme/src/nvme/json.c +++ b/libnvme/src/nvme/json.c @@ -14,11 +14,10 @@ #include +#include + #include "cleanup.h" -#include "fabrics.h" -#include "log.h" #include "private.h" -#include "linux.h" #define JSON_UPDATE_INT_OPTION(c, k, a, o) \ if (!strcmp(# a, k ) && !c->a) c->a = json_object_get_int(o); diff --git a/libnvme/src/nvme/linux.c b/libnvme/src/nvme/linux.c index a4f0bb2b9e..7ee594a8c4 100644 --- a/libnvme/src/nvme/linux.c +++ b/libnvme/src/nvme/linux.c @@ -33,13 +33,12 @@ #include +#include + +#include "crc32.h" +#include "base64.h" #include "cleanup.h" -#include "linux.h" -#include "tree.h" -#include "log.h" #include "private.h" -#include "base64.h" -#include "crc32.h" void nvme_set_dry_run(struct nvme_global_ctx *ctx, bool enable) { diff --git a/libnvme/src/nvme/log.c b/libnvme/src/nvme/log.c index 3bb3e93775..80cf4fab19 100644 --- a/libnvme/src/nvme/log.c +++ b/libnvme/src/nvme/log.c @@ -15,10 +15,12 @@ #include #include #include + +#include + +#include "cleanup.h" #define LOG_FUNCNAME 1 #include "private.h" -#include "log.h" -#include "cleanup.h" #ifndef LOG_CLOCK #define LOG_CLOCK CLOCK_MONOTONIC diff --git a/libnvme/src/nvme/mi-mctp.c b/libnvme/src/nvme/mi-mctp.c index 492b924cf9..3553a3f1d9 100644 --- a/libnvme/src/nvme/mi-mctp.c +++ b/libnvme/src/nvme/mi-mctp.c @@ -34,9 +34,10 @@ #define MCTP_DBUS_IFACE_ENDPOINT "xyz.openbmc_project.MCTP.Endpoint" #endif +#include +#include + #include "private.h" -#include "log.h" -#include "mi.h" #if !defined(AF_MCTP) diff --git a/libnvme/src/nvme/mi.c b/libnvme/src/nvme/mi.c index 4c74922f99..00eb2de228 100644 --- a/libnvme/src/nvme/mi.c +++ b/libnvme/src/nvme/mi.c @@ -17,9 +17,9 @@ #include #include -#include "log.h" -#include "mi.h" -#include "linux.h" +#include +#include + #include "private.h" #define NUM_ENABLES (256u) diff --git a/libnvme/src/nvme/nbft.c b/libnvme/src/nvme/nbft.c index 9eb5e53db3..a9d9321c1f 100644 --- a/libnvme/src/nvme/nbft.c +++ b/libnvme/src/nvme/nbft.c @@ -13,9 +13,9 @@ #include #include +#include + #include "private.h" -#include "nbft.h" -#include "log.h" #define MIN(a, b) (((a) < (b)) ? (a) : (b)) diff --git a/libnvme/src/nvme/no-json.c b/libnvme/src/nvme/no-json.c index 3427f42bda..0dc36cf694 100644 --- a/libnvme/src/nvme/no-json.c +++ b/libnvme/src/nvme/no-json.c @@ -6,7 +6,7 @@ * Authors: Daniel Wagner */ -#include "tree.h" +#include #include diff --git a/libnvme/src/nvme/tree.c b/libnvme/src/nvme/tree.c index 987faf5c57..9ed3375e3b 100644 --- a/libnvme/src/nvme/tree.c +++ b/libnvme/src/nvme/tree.c @@ -25,16 +25,11 @@ #include #include +#include + #include "cleanup.h" -#include "ioctl.h" -#include "linux.h" -#include "filters.h" -#include "tree.h" -#include "filters.h" -#include "util.h" -#include "fabrics.h" -#include "log.h" #include "private.h" +#include "util.h" /** * struct candidate_args - Used to look for a controller matching these parameters diff --git a/libnvme/src/nvme/util.c b/libnvme/src/nvme/util.c index 13d22af9c1..5379101801 100644 --- a/libnvme/src/nvme/util.c +++ b/libnvme/src/nvme/util.c @@ -25,10 +25,11 @@ #include #include +#include + #include "cleanup.h" #include "private.h" #include "util.h" -#include "log.h" /* The bionic libc implementation doesn't define LINE_MAX */ #ifndef LINE_MAX diff --git a/libnvme/test/ioctl/logs.c b/libnvme/test/ioctl/logs.c index a641470d24..b048a3df98 100644 --- a/libnvme/test/ioctl/logs.c +++ b/libnvme/test/ioctl/logs.c @@ -4,8 +4,6 @@ #include "mock.h" #include "util.h" -#include -#include #define TEST_FD 0xFD #define TEST_NSID 0x12345678 diff --git a/libnvme/test/ioctl/misc.c b/libnvme/test/ioctl/misc.c index 7ac6519d86..dcd82fe6fb 100644 --- a/libnvme/test/ioctl/misc.c +++ b/libnvme/test/ioctl/misc.c @@ -4,8 +4,7 @@ #include "mock.h" #include "util.h" -#include -#include + #include #include diff --git a/libnvme/test/ioctl/mock.c b/libnvme/test/ioctl/mock.c index d6ff12ee7e..0333b53b01 100644 --- a/libnvme/test/ioctl/mock.c +++ b/libnvme/test/ioctl/mock.c @@ -7,8 +7,9 @@ #include #include -#include -#include +#include + +#include "nvme/private.h" #include "mock.h" #include "util.h" diff --git a/libnvme/test/ioctl/zns.c b/libnvme/test/ioctl/zns.c index 56ababbc9a..6214543d19 100644 --- a/libnvme/test/ioctl/zns.c +++ b/libnvme/test/ioctl/zns.c @@ -4,8 +4,7 @@ #include "mock.h" #include "util.h" -#include -#include + #include #define TEST_FD 0xFD diff --git a/libnvme/test/mi-mctp.c b/libnvme/test/mi-mctp.c index ce283da71e..87fade097a 100644 --- a/libnvme/test/mi-mctp.c +++ b/libnvme/test/mi-mctp.c @@ -18,9 +18,11 @@ #include #include -#include "libnvme-mi.h" -#include "nvme/linux.h" +#include +#include + #include "nvme/private.h" + #include "utils.h" #if HAVE_LINUX_MCTP_H diff --git a/libnvme/test/mi.c b/libnvme/test/mi.c index 8effe1b4f1..010f93797a 100644 --- a/libnvme/test/mi.c +++ b/libnvme/test/mi.c @@ -13,12 +13,12 @@ #include #include +#include +#include + /* we define a custom transport, so need the internal headers */ -#include "nvme/linux.h" #include "nvme/private.h" -#include "libnvme-mi.h" - #include "utils.h" typedef int (*test_submit_cb)(struct nvme_mi_ep *ep, diff --git a/libnvme/test/nbft/nbft-dump.c b/libnvme/test/nbft/nbft-dump.c index 1d6cc124fb..23b8c213a3 100644 --- a/libnvme/test/nbft/nbft-dump.c +++ b/libnvme/test/nbft/nbft-dump.c @@ -9,7 +9,8 @@ #include #include #include -#include "libnvme.h" + +#include static void print_hex(unsigned char *buf, int len) { diff --git a/libnvme/test/test-util.c b/libnvme/test/test-util.c index 77469059f7..6b22ebfa00 100644 --- a/libnvme/test/test-util.c +++ b/libnvme/test/test-util.c @@ -20,8 +20,7 @@ #include #include -#include "nvme/log.c" /* to resolve __nvme_msg() */ -#include "nvme/util.c" +#include static size_t safe_strlen(const char *p) { return p ? strlen(p) : strlen("null"); diff --git a/libnvme/test/test.c b/libnvme/test/test.c index 0b24c1db4c..59f0a581df 100644 --- a/libnvme/test/test.c +++ b/libnvme/test/test.c @@ -15,8 +15,8 @@ * program exists successfully; an ungraceful exit means a bug exists * somewhere. */ -#include "nvme/ioctl.h" -#include "nvme/tree.h" +#include + #include #include #include diff --git a/libnvme/test/zns.c b/libnvme/test/zns.c index 76a8d36eef..6221140f47 100644 --- a/libnvme/test/zns.c +++ b/libnvme/test/zns.c @@ -9,7 +9,8 @@ /* * Search out for ZNS type namespaces, and if found, report their properties. */ -#include "nvme/tree.h" +#include + #include #include #include From 6794c3ca7ce781bb0fc0433cdd9487d6086abbca Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 25 Feb 2026 19:52:38 +0100 Subject: [PATCH 05/29] libnvme: drop a few unused headers clang reports these are unused, thus remove them from the include list. Signed-off-by: Daniel Wagner --- libnvme/src/nvme/base64.c | 1 - libnvme/src/nvme/fabrics.c | 1 - libnvme/src/nvme/ioctl.c | 1 - libnvme/src/nvme/json.c | 2 -- 4 files changed, 5 deletions(-) diff --git a/libnvme/src/nvme/base64.c b/libnvme/src/nvme/base64.c index 0163fa1702..c02b5fe0b1 100644 --- a/libnvme/src/nvme/base64.c +++ b/libnvme/src/nvme/base64.c @@ -8,7 +8,6 @@ */ #include -#include #include #include #include diff --git a/libnvme/src/nvme/fabrics.c b/libnvme/src/nvme/fabrics.c index ab58bd7e15..490383d63a 100644 --- a/libnvme/src/nvme/fabrics.c +++ b/libnvme/src/nvme/fabrics.c @@ -7,7 +7,6 @@ * Chaitanya Kulkarni */ -#include #include #include #include diff --git a/libnvme/src/nvme/ioctl.c b/libnvme/src/nvme/ioctl.c index 91769d738b..861c1a81fc 100644 --- a/libnvme/src/nvme/ioctl.c +++ b/libnvme/src/nvme/ioctl.c @@ -12,7 +12,6 @@ #include #endif #include -#include #include #include #include diff --git a/libnvme/src/nvme/json.c b/libnvme/src/nvme/json.c index b0276ed9f7..84d0b94d6c 100644 --- a/libnvme/src/nvme/json.c +++ b/libnvme/src/nvme/json.c @@ -6,8 +6,6 @@ * Authors: Hannes Reinecke */ -#include -#include #include #include #include From d3a745a7864e63f0ddc6460b1968db9201a3b26b Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Fri, 27 Feb 2026 12:00:12 +0100 Subject: [PATCH 06/29] nvme: use nvme_ns_rescan instead open coding Use nvme_ns_rescan which wraps the IOCTL. This in preparation to make the low level code private in libnvme. Signed-off-by: Daniel Wagner --- nvme.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/nvme.c b/nvme.c index deeb804794..dbd62fc14a 100644 --- a/nvme.c +++ b/nvme.c @@ -6808,8 +6808,7 @@ static int format_cmd(int argc, char **argv, struct command *acmd, struct plugin printf("Success formatting namespace:%x\n", cfg.namespace_id); if (nvme_transport_handle_is_direct(hdl) && cfg.lbaf != prev_lbaf) { if (nvme_transport_handle_is_chardev(hdl)) { - if (ioctl(nvme_transport_handle_get_fd(hdl), - NVME_IOCTL_RESCAN) < 0) { + if (nvme_ns_rescan(hdl) < 0) { nvme_show_error("failed to rescan namespaces"); return -errno; } From e7d034005e10431c8e19e4d1e4581d5bc9cea080 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Fri, 27 Feb 2026 12:02:44 +0100 Subject: [PATCH 07/29] ioctl: make IOCTL defines private Don't expose these low level defines anymore. The library should provide all necessary functions/helpers. Signed-off-by: Daniel Wagner --- libnvme/src/nvme/ioctl.h | 11 ----------- libnvme/src/nvme/private.h | 12 ++++++++++++ 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/libnvme/src/nvme/ioctl.h b/libnvme/src/nvme/ioctl.h index 69d317cdc7..267c1b506b 100644 --- a/libnvme/src/nvme/ioctl.h +++ b/libnvme/src/nvme/ioctl.h @@ -135,17 +135,6 @@ struct nvme_uring_cmd { __u32 rsvd2; }; -#define NVME_IOCTL_ID _IO('N', 0x40) -#define NVME_IOCTL_RESET _IO('N', 0x44) -#define NVME_IOCTL_SUBSYS_RESET _IO('N', 0x45) -#define NVME_IOCTL_RESCAN _IO('N', 0x46) - -/* io_uring async commands: */ -#define NVME_URING_CMD_IO _IOWR('N', 0x80, struct nvme_uring_cmd) -#define NVME_URING_CMD_IO_VEC _IOWR('N', 0x81, struct nvme_uring_cmd) -#define NVME_URING_CMD_ADMIN _IOWR('N', 0x82, struct nvme_uring_cmd) -#define NVME_URING_CMD_ADMIN_VEC _IOWR('N', 0x83, struct nvme_uring_cmd) - #endif /* _UAPI_LINUX_NVME_IOCTL_H */ #endif /* _LINUX_NVME_IOCTL_H */ diff --git a/libnvme/src/nvme/private.h b/libnvme/src/nvme/private.h index cff50fb896..b7c5ccf81e 100644 --- a/libnvme/src/nvme/private.h +++ b/libnvme/src/nvme/private.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -69,11 +70,22 @@ struct linux_passthru_cmd64 { __u64 result; }; +#define NVME_IOCTL_ID _IO('N', 0x40) +#define NVME_IOCTL_RESET _IO('N', 0x44) +#define NVME_IOCTL_SUBSYS_RESET _IO('N', 0x45) +#define NVME_IOCTL_RESCAN _IO('N', 0x46) + #define NVME_IOCTL_ADMIN_CMD _IOWR('N', 0x41, struct linux_passthru_cmd32) #define NVME_IOCTL_IO_CMD _IOWR('N', 0x43, struct linux_passthru_cmd32) #define NVME_IOCTL_ADMIN64_CMD _IOWR('N', 0x47, struct linux_passthru_cmd64) #define NVME_IOCTL_IO64_CMD _IOWR('N', 0x48, struct linux_passthru_cmd64) +/* io_uring async commands: */ +#define NVME_URING_CMD_IO _IOWR('N', 0x80, struct nvme_uring_cmd) +#define NVME_URING_CMD_IO_VEC _IOWR('N', 0x81, struct nvme_uring_cmd) +#define NVME_URING_CMD_ADMIN _IOWR('N', 0x82, struct nvme_uring_cmd) +#define NVME_URING_CMD_ADMIN_VEC _IOWR('N', 0x83, struct nvme_uring_cmd) + struct nvme_log { int fd; int level; From 156651d0bdf79be79dca4fc1a2497138cf9aa828 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Fri, 27 Feb 2026 12:05:10 +0100 Subject: [PATCH 08/29] ioctl: always define the passthru data structs These data structs are libnvme APIs and just match the Linux APIs. libnvme should not expose directly the Linux data structs. Signed-off-by: Daniel Wagner --- libnvme/src/nvme/ioctl.h | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/libnvme/src/nvme/ioctl.h b/libnvme/src/nvme/ioctl.h index 267c1b506b..1aa4353ab8 100644 --- a/libnvme/src/nvme/ioctl.h +++ b/libnvme/src/nvme/ioctl.h @@ -19,16 +19,6 @@ #include -/* - * We can not always count on the kernel UAPI being installed. Use the same - * 'ifdef' guard to avoid double definitions just in case. - */ -#ifndef _UAPI_LINUX_NVME_IOCTL_H -#define _UAPI_LINUX_NVME_IOCTL_H - -#ifndef _LINUX_NVME_IOCTL_H -#define _LINUX_NVME_IOCTL_H - /** * DOC: ioctl.h * @@ -135,10 +125,6 @@ struct nvme_uring_cmd { __u32 rsvd2; }; -#endif /* _UAPI_LINUX_NVME_IOCTL_H */ - -#endif /* _LINUX_NVME_IOCTL_H */ - enum nvme_cmd_dword_fields { NVME_DEVICE_SELF_TEST_CDW10_STC_SHIFT = 0, NVME_DEVICE_SELF_TEST_CDW10_STC_MASK = 0xf, From dd0a2ee0ccb5638a9df2623fb1c1606e17737f58 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Fri, 27 Feb 2026 12:09:44 +0100 Subject: [PATCH 09/29] cmds: move command function to their own header Split the ioctl APIs from the commands API. While at it, also remove a few of the unnecessary header dependencies. The aim here is to make the ioctl header as small as possible. This will make any porting attempts simpler. Signed-off-by: Daniel Wagner --- libnvme/src/libnvme-mi.h | 1 + libnvme/src/libnvme.h | 1 + libnvme/src/meson.build | 1 + libnvme/src/nvme/cmds.h | 6911 ++++++++++++++++++++++++++++++++++ libnvme/src/nvme/ioctl.h | 6893 +-------------------------------- libnvme/src/nvme/linux.c | 2 + libnvme/src/nvme/mi-mctp.c | 1 + libnvme/test/mi-mctp.c | 2 +- nvme.c | 1 + plugins/scaleflux/sfx-nvme.c | 1 + 10 files changed, 6923 insertions(+), 6891 deletions(-) create mode 100644 libnvme/src/nvme/cmds.h diff --git a/libnvme/src/libnvme-mi.h b/libnvme/src/libnvme-mi.h index 225270efce..206b1f7981 100644 --- a/libnvme/src/libnvme-mi.h +++ b/libnvme/src/libnvme-mi.h @@ -14,6 +14,7 @@ extern "C" { #endif #include +#include #include #include diff --git a/libnvme/src/libnvme.h b/libnvme/src/libnvme.h index 47ae117e2e..f7f52d0adb 100644 --- a/libnvme/src/libnvme.h +++ b/libnvme/src/libnvme.h @@ -15,6 +15,7 @@ extern "C" { #endif #include +#include #include #include #include diff --git a/libnvme/src/meson.build b/libnvme/src/meson.build index 40798e15ce..25a5f1fd31 100644 --- a/libnvme/src/meson.build +++ b/libnvme/src/meson.build @@ -100,6 +100,7 @@ install_headers( 'nvme/filters.h', 'nvme/ioctl.h', 'nvme/linux.h', + 'nvme/cmds.h', 'nvme/log.h', 'nvme/nbft.h', 'nvme/tree.h', diff --git a/libnvme/src/nvme/cmds.h b/libnvme/src/nvme/cmds.h new file mode 100644 index 0000000000..28a29200a1 --- /dev/null +++ b/libnvme/src/nvme/cmds.h @@ -0,0 +1,6911 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * This file is part of libnvme. + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + * + * Authors: Keith Busch + * Chaitanya Kulkarni + * Daniel Wagner + */ + +#pragma once + +#include +#include + +#include +#include +#include + +enum nvme_cmd_dword_fields { + NVME_DEVICE_SELF_TEST_CDW10_STC_SHIFT = 0, + NVME_DEVICE_SELF_TEST_CDW10_STC_MASK = 0xf, + NVME_DIRECTIVE_CDW11_DOPER_SHIFT = 0, + NVME_DIRECTIVE_CDW11_DTYPE_SHIFT = 8, + NVME_DIRECTIVE_CDW11_DPSEC_SHIFT = 16, + NVME_DIRECTIVE_CDW11_DOPER_MASK = 0xff, + NVME_DIRECTIVE_CDW11_DTYPE_MASK = 0xff, + NVME_DIRECTIVE_CDW11_DPSEC_MASK = 0xffff, + NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_ENDIR_SHIFT = 0, + NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_DTYPE_SHIFT = 1, + NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_ENDIR_MASK = 0x1, + NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_DTYPE_MASK = 0x1, + NVME_FW_COMMIT_CDW10_FS_SHIFT = 0, + NVME_FW_COMMIT_CDW10_CA_SHIFT = 3, + NVME_FW_COMMIT_CDW10_BPID_SHIFT = 31, + NVME_FW_COMMIT_CDW10_FS_MASK = 0x7, + NVME_FW_COMMIT_CDW10_CA_MASK = 0x7, + NVME_FW_COMMIT_CDW10_BPID_MASK = 0x1, + NVME_GET_FEATURES_CDW10_SEL_SHIFT = 8, + NVME_GET_FEATURES_CDW10_SEL_MASK = 0x7, + NVME_GET_FEATURES_CDW10_FID_SHIFT = 0, + NVME_GET_FEATURES_CDW10_FID_MASK = 0xff, + NVME_GET_FEATURES_CDW14_UUID_SHIFT = 0, + NVME_GET_FEATURES_CDW14_UUID_MASK = 0x7f, + NVME_SET_FEATURES_CDW10_SV_SHIFT = 31, + NVME_SET_FEATURES_CDW10_SV_MASK = 0x1, + NVME_SET_FEATURES_CDW10_FID_SHIFT = 0, + NVME_SET_FEATURES_CDW10_FID_MASK = 0xff, + NVME_SET_FEATURES_CDW11_NUM_SHIFT = 0, + NVME_SET_FEATURES_CDW11_NUM_MASK = 0x3f, + NVME_SET_FEATURES_CDW14_UUID_SHIFT = 0, + NVME_SET_FEATURES_CDW14_UUID_MASK = 0x7f, + NVME_LOG_CDW10_LID_SHIFT = 0, + NVME_LOG_CDW10_LSP_SHIFT = 8, + NVME_LOG_CDW10_RAE_SHIFT = 15, + NVME_LOG_CDW10_NUMDL_SHIFT = 16, + NVME_LOG_CDW11_NUMDU_SHIFT = 0, + NVME_LOG_CDW11_LSI_SHIFT = 16, + NVME_LOG_CDW14_UUID_SHIFT = 0, + NVME_LOG_CDW14_CSI_SHIFT = 24, + NVME_LOG_CDW14_OT_SHIFT = 23, + NVME_LOG_CDW10_LID_MASK = 0xff, + NVME_LOG_CDW10_LSP_MASK = 0x7f, + NVME_LOG_CDW10_RAE_MASK = 0x1, + NVME_LOG_CDW10_NUMDL_MASK = 0xffff, + NVME_LOG_CDW11_NUMDU_MASK = 0xffff, + NVME_LOG_CDW11_LSI_MASK = 0xffff, + NVME_LOG_CDW14_UUID_MASK = 0x7f, + NVME_LOG_CDW14_CSI_MASK = 0xff, + NVME_LOG_CDW14_OT_MASK = 0x1, + NVME_IDENTIFY_CDW10_CNS_SHIFT = 0, + NVME_IDENTIFY_CDW10_CNTID_SHIFT = 16, + NVME_IDENTIFY_CDW11_CNSSPECID_SHIFT = 0, + NVME_IDENTIFY_CDW11_FIDX_SHIFT = 0, + NVME_IDENTIFY_CDW11_DOMID_SHIFT = 0, + NVME_IDENTIFY_CDW11_ENGGID_SHIFT = 0, + NVME_IDENTIFY_CDW14_UUID_SHIFT = 0, + NVME_IDENTIFY_CDW11_CSI_SHIFT = 24, + NVME_IDENTIFY_CDW10_CNS_MASK = 0xff, + NVME_IDENTIFY_CDW10_CNTID_MASK = 0xffff, + NVME_IDENTIFY_CDW11_CNSSPECID_MASK = 0xffff, + NVME_IDENTIFY_CDW11_FIDX_MASK = 0xffff, + NVME_IDENTIFY_CDW11_DOMID_MASK = 0xffff, + NVME_IDENTIFY_CDW11_ENGGID_MASK = 0xffff, + NVME_IDENTIFY_CDW14_UUID_MASK = 0x7f, + NVME_IDENTIFY_CDW11_CSI_MASK = 0xff, + NVME_NAMESPACE_ATTACH_CDW10_SEL_SHIFT = 0, + NVME_NAMESPACE_ATTACH_CDW10_SEL_MASK = 0xf, + NVME_NAMESPACE_MGMT_CDW10_SEL_SHIFT = 0, + NVME_NAMESPACE_MGMT_CDW10_SEL_MASK = 0xf, + NVME_NAMESPACE_MGMT_CDW11_CSI_SHIFT = 24, + NVME_NAMESPACE_MGMT_CDW11_CSI_MASK = 0xff, + NVME_VIRT_MGMT_CDW10_ACT_SHIFT = 0, + NVME_VIRT_MGMT_CDW10_RT_SHIFT = 8, + NVME_VIRT_MGMT_CDW10_CNTLID_SHIFT = 16, + NVME_VIRT_MGMT_CDW11_NR_SHIFT = 0, + NVME_VIRT_MGMT_CDW10_ACT_MASK = 0xf, + NVME_VIRT_MGMT_CDW10_RT_MASK = 0x7, + NVME_VIRT_MGMT_CDW10_CNTLID_MASK = 0xffff, + NVME_VIRT_MGMT_CDW11_NR_MASK = 0xffff, + NVME_FORMAT_CDW10_LBAFL_SHIFT = 0, + NVME_FORMAT_CDW10_MSET_SHIFT = 4, + NVME_FORMAT_CDW10_PI_SHIFT = 5, + NVME_FORMAT_CDW10_PIL_SHIFT = 8, + NVME_FORMAT_CDW10_SES_SHIFT = 9, + NVME_FORMAT_CDW10_LBAFU_SHIFT = 12, + NVME_FORMAT_CDW10_LBAFL_MASK = 0xf, + NVME_FORMAT_CDW10_MSET_MASK = 0x1, + NVME_FORMAT_CDW10_PI_MASK = 0x7, + NVME_FORMAT_CDW10_PIL_MASK = 0x1, + NVME_FORMAT_CDW10_SES_MASK = 0x7, + NVME_FORMAT_CDW10_LBAFU_MASK = 0x3, + NVME_SANITIZE_CDW10_SANACT_SHIFT = 0, + NVME_SANITIZE_CDW10_AUSE_SHIFT = 3, + NVME_SANITIZE_CDW10_OWPASS_SHIFT = 4, + NVME_SANITIZE_CDW10_OIPBP_SHIFT = 8, + NVME_SANITIZE_CDW10_NDAS_SHIFT = 9, + NVME_SANITIZE_CDW10_EMVS_SHIFT = 10, + NVME_SANITIZE_CDW10_SANACT_MASK = 0x7, + NVME_SANITIZE_CDW10_AUSE_MASK = 0x1, + NVME_SANITIZE_CDW10_OWPASS_MASK = 0xf, + NVME_SANITIZE_CDW10_OIPBP_MASK = 0x1, + NVME_SANITIZE_CDW10_NDAS_MASK = 0x1, + NVME_SANITIZE_CDW10_EMVS_MASK = 0x1, + NVME_SECURITY_NSSF_SHIFT = 0, + NVME_SECURITY_SPSP0_SHIFT = 8, + NVME_SECURITY_SPSP1_SHIFT = 16, + NVME_SECURITY_SECP_SHIFT = 24, + NVME_SECURITY_NSSF_MASK = 0xff, + NVME_SECURITY_SPSP0_MASK = 0xff, + NVME_SECURITY_SPSP1_MASK = 0xff, + NVME_SECURITY_SECP_MASK = 0xffff, + NVME_GET_LBA_STATUS_CDW13_RL_SHIFT = 0, + NVME_GET_LBA_STATUS_CDW13_ATYPE_SHIFT = 24, + NVME_GET_LBA_STATUS_CDW13_RL_MASK = 0xffff, + NVME_GET_LBA_STATUS_CDW13_ATYPE_MASK = 0xff, + NVME_ZNS_MGMT_SEND_ZM_SHIFT = 16, + NVME_ZNS_MGMT_SEND_ZM_MASK = 0xff, + NVME_ZNS_MGMT_SEND_ZSASO_SHIFT = 9, + NVME_ZNS_MGMT_SEND_ZSASO_MASK = 0x1, + NVME_ZNS_MGMT_SEND_SEL_SHIFT = 8, + NVME_ZNS_MGMT_SEND_SEL_MASK = 0x1, + NVME_ZNS_MGMT_SEND_ZSA_SHIFT = 0, + NVME_ZNS_MGMT_SEND_ZSA_MASK = 0xff, + NVME_ZNS_MGMT_RECV_ZRASPF_SHIFT = 16, + NVME_ZNS_MGMT_RECV_ZRASPF_MASK = 0x1, + NVME_ZNS_MGMT_RECV_ZRAS_SHIFT = 8, + NVME_ZNS_MGMT_RECV_ZRAS_MASK = 0xff, + NVME_ZNS_MGMT_RECV_ZRA_SHIFT = 0, + NVME_ZNS_MGMT_RECV_ZRA_MASK = 0xff, + NVME_DIM_TAS_SHIFT = 0, + NVME_DIM_TAS_MASK = 0xf, + NVME_DSM_CDW10_NR_SHIFT = 0, + NVME_DSM_CDW10_NR_MASK = 0xff, + NVME_DSM_CDW11_IDR_SHIFT = 0, + NVME_DSM_CDW11_IDR_MASK = 0x1, + NVME_DSM_CDW11_IDW_SHIFT = 1, + NVME_DSM_CDW11_IDW_MASK = 0x1, + NVME_DSM_CDW11_AD_SHIFT = 2, + NVME_DSM_CDW11_AD_MASK = 0x1, + NVME_CAPACITY_MGMT_CDW10_OPER_SHIFT = 0, + NVME_CAPACITY_MGMT_CDW10_OPER_MASK = 0xf, + NVME_CAPACITY_MGMT_CDW10_ELID_SHIFT = 16, + NVME_CAPACITY_MGMT_CDW10_ELID_MASK = 0xffff, + NVME_CAPACITY_MGMT_CDW11_CAPL_SHIFT = 0, + NVME_CAPACITY_MGMT_CDW11_CAPL_MASK = 0xffffffff, + NVME_CAPACITY_MGMT_CDW12_CAPU_SHIFT = 0, + NVME_CAPACITY_MGMT_CDW12_CAPU_MASK = 0xffffffff, + NVME_LOCKDOWN_CDW10_SCP_SHIFT = 0, + NVME_LOCKDOWN_CDW10_SCP_MASK = 0xf, + NVME_LOCKDOWN_CDW10_PRHBT_SHIFT = 4, + NVME_LOCKDOWN_CDW10_PRHBT_MASK = 0x1, + NVME_LOCKDOWN_CDW10_IFC_SHIFT = 5, + NVME_LOCKDOWN_CDW10_IFC_MASK = 0x3, + NVME_LOCKDOWN_CDW10_OFI_SHIFT = 8, + NVME_LOCKDOWN_CDW10_OFI_MASK = 0xff, + NVME_LOCKDOWN_CDW14_UIDX_SHIFT = 0, + NVME_LOCKDOWN_CDW14_UIDX_MASK = 0x3f, + NVME_RESV_ACQUIRE_CDW10_RACQA_SHIFT = 0, + NVME_RESV_ACQUIRE_CDW10_RACQA_MASK = 0x7, + NVME_RESV_ACQUIRE_CDW10_IEKEY_SHIFT = 3, + NVME_RESV_ACQUIRE_CDW10_IEKEY_MASK = 0x1, + NVME_RESV_ACQUIRE_CDW10_DISNSRS_SHIFT = 4, + NVME_RESV_ACQUIRE_CDW10_DISNSRS_MASK = 0x1, + NVME_RESV_ACQUIRE_CDW10_RTYPE_SHIFT = 8, + NVME_RESV_ACQUIRE_CDW10_RTYPE_MASK = 0xff, + NVME_RESV_REGISTER_CDW10_RREGA_SHIFT = 0, + NVME_RESV_REGISTER_CDW10_RREGA_MASK = 0x7, + NVME_RESV_REGISTER_CDW10_IEKEY_SHIFT = 3, + NVME_RESV_REGISTER_CDW10_IEKEY_MASK = 0x1, + NVME_RESV_REGISTER_CDW10_DISNSRS_SHIFT = 4, + NVME_RESV_REGISTER_CDW10_DISNSRS_MASK = 0x1, + NVME_RESV_REGISTER_CDW10_CPTPL_SHIFT = 30, + NVME_RESV_REGISTER_CDW10_CPTPL_MASK = 0x3, + NVME_RESV_RELEASE_CDW10_RRELA_SHIFT = 0, + NVME_RESV_RELEASE_CDW10_RRELA_MASK = 0x7, + NVME_RESV_RELEASE_CDW10_IEKEY_SHIFT = 3, + NVME_RESV_RELEASE_CDW10_IEKEY_MASK = 0x1, + NVME_RESV_RELEASE_CDW10_DISNSRS_SHIFT = 4, + NVME_RESV_RELEASE_CDW10_DISNSRS_MASK = 0x1, + NVME_RESV_RELEASE_CDW10_RTYPE_SHIFT = 8, + NVME_RESV_RELEASE_CDW10_RTYPE_MASK = 0xff, + NVME_RESV_REPORT_CDW11_EDS_SHIFT = 0, + NVME_RESV_REPORT_CDW11_EDS_MASK = 0x1, + NVME_RESV_REPORT_CDW11_DISNSRS_SHIFT = 1, + NVME_RESV_REPORT_CDW11_DISNSRS_MASK = 0x1, + NVME_IO_MGMT_RECV_CDW10_MO_SHIFT = 0, + NVME_IO_MGMT_RECV_CDW10_MO_MASK = 0xff, + NVME_IO_MGMT_RECV_CDW10_MOS_SHIFT = 16, + NVME_IO_MGMT_RECV_CDW10_MOS_MASK = 0xffff, + NVME_IO_MGMT_SEND_CDW10_MO_SHIFT = 0, + NVME_IO_MGMT_SEND_CDW10_MO_MASK = 0xff, + NVME_IO_MGMT_SEND_CDW10_MOS_SHIFT = 16, + NVME_IO_MGMT_SEND_CDW10_MOS_MASK = 0xffff, + NVME_IOCS_COMMON_CDW2_ELBTU_SHIFT = 0, + NVME_IOCS_COMMON_CDW2_ELBTU_MASK = 0xffff, + NVME_IOCS_COMMON_CDW3_ELBTU_SHIFT = 0, + NVME_IOCS_COMMON_CDW3_ELBTU_MASK = 0xffffffff, + NVME_IOCS_COMMON_CDW10_SLBAL_SHIFT = 0, + NVME_IOCS_COMMON_CDW10_SLBAL_MASK = 0xffffffff, + NVME_IOCS_COMMON_CDW11_SLBAU_SHIFT = 0, + NVME_IOCS_COMMON_CDW11_SLBAU_MASK = 0xffffffff, + NVME_IOCS_COMMON_CDW12_NLB_SHIFT = 0, + NVME_IOCS_COMMON_CDW12_NLB_MASK = 0xffff, + NVME_IOCS_COMMON_CDW12_CETYPE_SHIFT = 16, + NVME_IOCS_COMMON_CDW12_CETYPE_MASK = 0xf, + NVME_IOCS_COMMON_CDW12_DTYPE_SHIFT = 20, + NVME_IOCS_COMMON_CDW12_DTYPE_MASK = 0xf, + NVME_IOCS_COMMON_CDW12_STC_SHIFT = 24, + NVME_IOCS_COMMON_CDW12_STC_MASK = 0x1, + NVME_IOCS_COMMON_CDW12_DEAC_SHIFT = 25, + NVME_IOCS_COMMON_CDW12_DEAC_MASK = 0x1, + NVME_IOCS_COMMON_CDW12_PIREMAP_SHIFT = 25, + NVME_IOCS_COMMON_CDW12_PIREMAP_MASK = 0x1, + NVME_IOCS_COMMON_CDW12_PRINFO_SHIFT = 26, + NVME_IOCS_COMMON_CDW12_PRINFO_MASK = 0xf, + NVME_IOCS_COMMON_CDW12_FUA_SHIFT = 30, + NVME_IOCS_COMMON_CDW12_FUA_MASK = 0x1, + NVME_IOCS_COMMON_CDW12_LR_SHIFT = 31, + NVME_IOCS_COMMON_CDW12_LR_MASK = 0x1, + NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT = + NVME_IOCS_COMMON_CDW12_CETYPE_SHIFT, + NVME_IOCS_COMMON_CDW12_CONTROL_MASK = + (NVME_VAL(IOCS_COMMON_CDW12_CETYPE) | + NVME_VAL(IOCS_COMMON_CDW12_DTYPE) | + NVME_VAL(IOCS_COMMON_CDW12_STC) | + NVME_VAL(IOCS_COMMON_CDW12_DEAC) | + NVME_VAL(IOCS_COMMON_CDW12_PRINFO) | + NVME_VAL(IOCS_COMMON_CDW12_FUA) | + NVME_VAL(IOCS_COMMON_CDW12_LR)) >> + NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT, + NVME_IOCS_COMMON_CDW13_DSM_AF_SHIFT = 0, + NVME_IOCS_COMMON_CDW13_DSM_AF_MASK = 0xf, + NVME_IOCS_COMMON_CDW13_DSM_AL_SHIFT = 4, + NVME_IOCS_COMMON_CDW13_DSM_AL_MASK = 0x3, + NVME_IOCS_COMMON_CDW13_DSM_SEQREQ_SHIFT = 6, + NVME_IOCS_COMMON_CDW13_DSM_SEQREQ_MASK = 0x1, + NVME_IOCS_COMMON_CDW13_DSM_INCPRS_SHIFT = 7, + NVME_IOCS_COMMON_CDW13_DSM_INCPRS_MASK = 0x1, + NVME_IOCS_COMMON_CDW13_DSM_SHIFT = + NVME_IOCS_COMMON_CDW13_DSM_AF_SHIFT, + NVME_IOCS_COMMON_CDW13_DSM_MASK = + (NVME_VAL(IOCS_COMMON_CDW13_DSM_AF) | + NVME_VAL(IOCS_COMMON_CDW13_DSM_AL) | + NVME_VAL(IOCS_COMMON_CDW13_DSM_SEQREQ) | + NVME_VAL(IOCS_COMMON_CDW13_DSM_INCPRS)) >> + NVME_IOCS_COMMON_CDW13_DSM_SHIFT, + NVME_IOCS_COMMON_CDW13_CEV_SHIFT = 0, + NVME_IOCS_COMMON_CDW13_CEV_MASK = 0xffff, + NVME_IOCS_COMMON_CDW13_DSPEC_SHIFT = 16, + NVME_IOCS_COMMON_CDW13_DSPEC_MASK = 0xffff, + NVME_IOCS_COMMON_CDW14_ELBTL_SHIFT = 0, + NVME_IOCS_COMMON_CDW14_ELBTL_MASK = 0xffffffff, + NVME_IOCS_COMMON_CDW15_ELBAT_SHIFT = 0, + NVME_IOCS_COMMON_CDW15_ELBAT_MASK = 0xffff, + NVME_IOCS_COMMON_CDW15_ELBATM_SHIFT = 16, + NVME_IOCS_COMMON_CDW15_ELBATM_MASK = 0xffff, + NVME_COPY_CDW3_LBTU_SHIFT = 0, + NVME_COPY_CDW3_LBTU_MASK = 0xffffffff, + NVME_COPY_CDW10_SDLBAL_SHIFT = 0, + NVME_COPY_CDW10_SDLBAL_MASK = 0xffffffff, + NVME_COPY_CDW11_SDLBAU_SHIFT = 0, + NVME_COPY_CDW11_SDLBAU_MASK = 0xffffffff, + NVME_COPY_CDW12_NR_SHIFT = 0, + NVME_COPY_CDW12_NR_MASK = 0xff, + NVME_COPY_CDW12_DESFMT_SHIFT = 8, + NVME_COPY_CDW12_DESFMT_MASK = 0xf, + NVME_COPY_CDW12_PRINFOR_SHIFT = 12, + NVME_COPY_CDW12_PRINFOR_MASK = 0xf, + NVME_COPY_CDW12_CETYPE_SHIFT = 16, + NVME_COPY_CDW12_CETYPE_MASK = 0xf, + NVME_COPY_CDW12_DTYPE_SHIFT = 20, + NVME_COPY_CDW12_DTYPE_MASK = 0xf, + NVME_COPY_CDW12_STCW_SHIFT = 24, + NVME_COPY_CDW12_STCW_MASK = 0x1, + NVME_COPY_CDW12_STCR_SHIFT = 25, + NVME_COPY_CDW12_STCR_MASK = 0x1, + NVME_COPY_CDW12_PRINFOW_SHIFT = 26, + NVME_COPY_CDW12_PRINFOW_MASK = 0xf, + NVME_COPY_CDW12_FUA_SHIFT = 30, + NVME_COPY_CDW12_FUA_MASK = 0x1, + NVME_COPY_CDW12_LR_SHIFT = 31, + NVME_COPY_CDW12_LR_MASK = 0x1, + NVME_COPY_CDW14_LBTL_SHIFT = 0, + NVME_COPY_CDW14_LBTL_MASK = 0xffffffff, + NVME_COPY_CDW15_LBAT_SHIFT = 0, + 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) \ + (((__u32)(value) & (mask)) << (shift)) + +#define NVME_FIELD_DECODE(value, shift, mask) \ + (((value) >> (shift)) & (mask)) + +/** + * nvme_init_identify() - Initialize passthru command for + * NVMe Identify + * @cmd: Command data structure to initialize + * @nsid: Namespace identifier + * @csi: Command Set Identifier + * @cns: The Controller or Namespace structure, + * see @enum nvme_identify_cns + * @data: User space destination address to transfer the data + * @len: Length of provided user buffer to hold the data in bytes + * + * Prepare the @cmd data structure for the NVMe Identify command. + */ +static inline void +nvme_init_identify(struct nvme_passthru_cmd *cmd, + __u32 nsid, enum nvme_csi csi, enum nvme_identify_cns cns, + void *data, __u32 len) +{ + __u32 cdw10 = NVME_FIELD_ENCODE(cns, + NVME_IDENTIFY_CDW10_CNS_SHIFT, + NVME_IDENTIFY_CDW10_CNS_MASK); + __u32 cdw11 = NVME_FIELD_ENCODE(csi, + NVME_IDENTIFY_CDW11_CSI_SHIFT, + NVME_IDENTIFY_CDW11_CSI_MASK); + + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_identify; + cmd->nsid = nsid; + cmd->cdw10 = cdw10; + cmd->cdw11 = cdw11; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; +} + +/** + * nvme_init_identify_ns() - Initialize passthru command for + * NVMe Identify Namespace data structure + * @cmd: Command data structure to initialize + * @nsid: Namespace identifier + * @id: User space destination address to transfer the data + * + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_NS. + */ +static inline void +nvme_init_identify_ns(struct nvme_passthru_cmd *cmd, + __u32 nsid, struct nvme_id_ns *id) +{ + nvme_init_identify(cmd, nsid, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_NS, + id, sizeof(*id)); +} + +/** + * nvme_init_identify_ctrl() - Initialize passthru command for + * NVMe Identify Controller data structure + * @cmd: Command data structure to initialize + * @id: User space destination address to transfer the data, + * + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_CTRL. + */ +static inline void +nvme_init_identify_ctrl(struct nvme_passthru_cmd *cmd, struct nvme_id_ctrl *id) +{ + nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_CTRL, + id, sizeof(*id)); +} + +/** + * nvme_init_identify_active_ns_list() - Initialize passthru command for + * Active Namespaces ID list + * @cmd: Command data structure to initialize + * @nsid: Namespace identifier + * @list: User space destination address to transfer the data + * + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_NS_ACTIVE_LIST. + */ +static inline void +nvme_init_identify_active_ns_list(struct nvme_passthru_cmd *cmd, + __u32 nsid, struct nvme_ns_list *list) +{ + nvme_init_identify(cmd, nsid, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_NS_ACTIVE_LIST, + list, sizeof(*list)); +} + +/** + * nvme_init_identify_ns_descs_list() - Initialize passthru command for + * Namespace Descriptor list + * @cmd: Command data structure to initialize + * @nsid: The namespace id to retrieve descriptors + * @descs: User space destination address to transfer the data + * + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_NS_DESC_LIST. + */ +static inline void +nvme_init_identify_ns_descs_list(struct nvme_passthru_cmd *cmd, + __u32 nsid, struct nvme_ns_id_desc *descs) +{ + nvme_init_identify(cmd, nsid, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_NS_DESC_LIST, + descs, NVME_IDENTIFY_DATA_SIZE); +} + +/** + * nvme_init_identify_nvmset_list() - Initialize passthru command for + * NVM Set List data structure + * @cmd: Command data structure to initialize + * @nsid: Namespace identifier + * @nvmsetid: NVM Set Identifier + * @nvmset: User space destination address to transfer the data + * + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_NS_ACTIVE_LIST. + */ +static inline void +nvme_init_identify_nvmset_list(struct nvme_passthru_cmd *cmd, + __u32 nsid, __u16 nvmsetid, struct nvme_id_nvmset_list *nvmset) +{ + nvme_init_identify(cmd, nsid, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_NVMSET_LIST, + nvmset, sizeof(*nvmset)); + cmd->cdw11 |= NVME_FIELD_ENCODE(nvmsetid, + NVME_IDENTIFY_CDW11_CNSSPECID_SHIFT, + NVME_IDENTIFY_CDW11_CNSSPECID_MASK); +} + +/** + * nvme_init_identify_csi_ns() - Initialize passthru command for + * I/O Command Set specific Identify Namespace data structure + * @cmd: Command data structure to initialize + * @nsid: Namespace identifier + * @csi: Command Set Identifier + * @uidx: UUID Index for differentiating vendor specific encoding + * @data: User space destination address to transfer the data + * + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_CSI_NS. + */ +static inline void +nvme_init_identify_csi_ns(struct nvme_passthru_cmd *cmd, + __u32 nsid, enum nvme_csi csi, __u8 uidx, void *data) +{ + nvme_init_identify(cmd, nsid, csi, + NVME_IDENTIFY_CNS_CSI_NS, + data, NVME_IDENTIFY_DATA_SIZE); + cmd->cdw14 |= NVME_FIELD_ENCODE(uidx, + NVME_IDENTIFY_CDW14_UUID_SHIFT, + NVME_IDENTIFY_CDW14_UUID_MASK); +} + +/** + * nvme_init_identify_csi_ctrl() - Initialize passthru command for + * I/O Command Set specific Identify Controller data structure + * @cmd: Command data structure to initialize + * @csi: Command Set Identifier + * @data: User space destination address to transfer the data + * + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_CSI_CTRL. + */ +static inline void +nvme_init_identify_csi_ctrl(struct nvme_passthru_cmd *cmd, + enum nvme_csi csi, void *data) +{ + nvme_init_identify(cmd, NVME_NSID_NONE, csi, + NVME_IDENTIFY_CNS_CSI_CTRL, + data, NVME_IDENTIFY_DATA_SIZE); +} + +/** + * nvme_init_identify_csi_active_ns_list() - Initialize passthru command + * for Active namespace ID list + * @cmd: Command data structure to initialize + * @nsid: Return namespaces greater than this identifier + * @csi: Command Set Identifier + * @ns_list: User space destination address to transfer the data + * + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_CSI_NS_ACTIVE_LIST. + */ +static inline void +nvme_init_identify_csi_active_ns_list(struct nvme_passthru_cmd *cmd, + __u32 nsid, enum nvme_csi csi, struct nvme_ns_list *ns_list) +{ + nvme_init_identify(cmd, nsid, csi, + NVME_IDENTIFY_CNS_CSI_NS_ACTIVE_LIST, + ns_list, sizeof(*ns_list)); +} + +/** + * nvme_init_identify_csi_independent_identify_id_ns() -Initialize passthru + * command for I/O Command Set Independent Identify Namespace data structure + * @cmd: Command data structure to initialize + * @nsid: Return namespaces greater than this identifier + * @ns: I/O Command Set Independent Identify Namespace data + * structure + * + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_CSI_INDEPENDENT_ID_NS. + */ +static inline void +nvme_init_identify_csi_independent_identify_id_ns(struct nvme_passthru_cmd *cmd, + __u32 nsid, struct nvme_id_independent_id_ns *ns) +{ + nvme_init_identify(cmd, nsid, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_CSI_INDEPENDENT_ID_NS, + ns, sizeof(*ns)); +} + +/** + * nvme_init_identify_ns_user_data_format() - Initialize passthru command + * for Identify namespace user data format + * @cmd: Command data structure to initialize + * @csi: Command Set Identifier + * @fidx: Format Index + * @uidx: UUID selection, if supported + * @data: User space destination address to transfer the data + * + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_NS_USER_DATA_FORMAT. + */ +static inline void +nvme_init_identify_ns_user_data_format(struct nvme_passthru_cmd *cmd, + enum nvme_csi csi, __u16 fidx, __u8 uidx, void *data) +{ + nvme_init_identify(cmd, NVME_NSID_NONE, csi, + NVME_IDENTIFY_CNS_NS_USER_DATA_FORMAT, + data, NVME_IDENTIFY_DATA_SIZE); + cmd->cdw11 |= NVME_FIELD_ENCODE(fidx, + NVME_IDENTIFY_CDW11_FIDX_SHIFT, + NVME_IDENTIFY_CDW11_FIDX_MASK); + cmd->cdw14 |= NVME_FIELD_ENCODE(uidx, + NVME_IDENTIFY_CDW14_UUID_SHIFT, + NVME_IDENTIFY_CDW14_UUID_MASK); +} + +/** + * nvme_init_identify_csi_ns_user_data_format() - Initialize passthru + * command for Identify namespace user data format + * @cmd: Command data structure to initialize + * @csi: Command Set Identifier + * @fidx: Format Index + * @uidx: UUID selection, if supported + * @data: User space destination address to transfer the data + * + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_CSI_NS_USER_DATA_FORMAT. + */ +static inline void +nvme_init_identify_csi_ns_user_data_format(struct nvme_passthru_cmd *cmd, + enum nvme_csi csi, __u16 fidx, __u8 uidx, void *data) +{ + nvme_init_identify(cmd, NVME_NSID_NONE, csi, + NVME_IDENTIFY_CNS_CSI_NS_USER_DATA_FORMAT, + data, NVME_IDENTIFY_DATA_SIZE); + cmd->cdw11 |= NVME_FIELD_ENCODE(fidx, + NVME_IDENTIFY_CDW11_FIDX_SHIFT, + NVME_IDENTIFY_CDW11_FIDX_MASK); + cmd->cdw14 |= NVME_FIELD_ENCODE(uidx, + NVME_IDENTIFY_CDW14_UUID_SHIFT, + NVME_IDENTIFY_CDW14_UUID_MASK); +} + +/** + * nvme_init_identify_allocated_ns_list() - Initialize passthru command + * for Allocated namespace ID list + * @cmd: Command data structure to initialize + * @nsid: Return namespaces greater than this identifier + * @ns_list: User space destination address to transfer the data + * + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_ALLOCATED_NS_LIST. + */ +static inline void +nvme_init_identify_allocated_ns_list(struct nvme_passthru_cmd *cmd, + __u32 nsid, struct nvme_ns_list *ns_list) +{ + nvme_init_identify(cmd, nsid, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_ALLOCATED_NS_LIST, + ns_list, sizeof(*ns_list)); +} + +/** + * nvme_init_identify_allocated_ns() - Initialize passthru command + * for allocated Namespace ID list + * @cmd: Command data structure to initialize + * @nsid: Namespace to identify + * @ns: User space destination address to transfer the data + * + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_ALLOCATED_NS. + */ +static inline void +nvme_init_identify_allocated_ns(struct nvme_passthru_cmd *cmd, + __u32 nsid, struct nvme_id_ns *ns) +{ + nvme_init_identify(cmd, nsid, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_ALLOCATED_NS, + ns, sizeof(*ns)); +} + +/** + * nvme_init_identify_ns_ctrl_list() - Initialize passhtru command + * for Controller List + * @cmd: Command data structure to initialize + * @nsid: Return controllers that are attached to this nsid + * @cntid: Starting CNTLID to return in the list + * @cntlist: User space destination address to transfer the data + * + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_NS_CTRL_LIST. + */ +static inline void +nvme_init_identify_ns_ctrl_list(struct nvme_passthru_cmd *cmd, + __u32 nsid, __u16 cntid, struct nvme_ctrl_list *cntlist) +{ + nvme_init_identify(cmd, nsid, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_NS_CTRL_LIST, + cntlist, sizeof(*cntlist)); + cmd->cdw10 |= NVME_FIELD_ENCODE(cntid, + NVME_IDENTIFY_CDW10_CNTID_SHIFT, + NVME_IDENTIFY_CDW10_CNTID_MASK); +} + +/** + * nvme_init_identify_ctrl_list() - Initialize passthru command for + * Controller List of controllers + * @cmd: Command data structure to initialize + * @cntid: Starting CNTLID to return in the list + * @cntlist: User space destination address to transfer the data + * + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_CTRL_LIST. + */ +static inline void +nvme_init_identify_ctrl_list(struct nvme_passthru_cmd *cmd, + __u16 cntid, struct nvme_ctrl_list *cntlist) +{ + nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_CTRL_LIST, + cntlist, sizeof(*cntlist)); + cmd->cdw10 |= NVME_FIELD_ENCODE(cntid, + NVME_IDENTIFY_CDW10_CNTID_SHIFT, + NVME_IDENTIFY_CDW10_CNTID_MASK); +} + +/** + * nvme_init_identify_primary_ctrl_cap() - Initialize passthru command + * for Primary Controller Capabilities data + * @cmd: Command data structure to initialize + * @cntid: Return controllers starting at this identifier + * @cap: User space destination buffer address to transfer the data + * + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_PRIMARY_CTRL_CAP. + */ +static inline void +nvme_init_identify_primary_ctrl_cap(struct nvme_passthru_cmd *cmd, + __u16 cntid, struct nvme_primary_ctrl_cap *cap) +{ + nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_PRIMARY_CTRL_CAP, + cap, sizeof(*cap)); + cmd->cdw10 |= NVME_FIELD_ENCODE(cntid, + NVME_IDENTIFY_CDW10_CNTID_SHIFT, + NVME_IDENTIFY_CDW10_CNTID_MASK); +} + +/** + * nvme_init_identify_secondary_ctrl_list() - Initialize passhru command + * for Secondary Controller list + * @cmd: Command data structure to initialize + * @cntid: Return controllers starting at this identifier + * @sc_list: User space destination address to transfer the data + * + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_SECONDARY_CTRL_LIST. + */ +static inline void +nvme_init_identify_secondary_ctrl_list(struct nvme_passthru_cmd *cmd, + __u16 cntid, struct nvme_secondary_ctrl_list *sc_list) +{ + nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_SECONDARY_CTRL_LIST, + sc_list, sizeof(*sc_list)); + cmd->cdw10 |= NVME_FIELD_ENCODE(cntid, + NVME_IDENTIFY_CDW10_CNTID_SHIFT, + NVME_IDENTIFY_CDW10_CNTID_MASK); +} + + +/** + * nvme_init_identify_ns_granularity() - Initialize passthru command for + * Namespace Granularity list + * @cmd: Command data structure to initialize + * @gr_list: User space destination address to transfer the data + * + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_SECONDARY_CTRL_LIST. + */ +static inline void +nvme_init_identify_ns_granularity(struct nvme_passthru_cmd *cmd, + struct nvme_id_ns_granularity_list *gr_list) +{ + nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_NS_GRANULARITY, + gr_list, sizeof(*gr_list)); +} + +/** + * nvme_init_identify_uuid_list() - Initialize passthru command for + * UUID list + * @cmd: Command data structure to initialize + * @uuid_list: User space destination address to transfer the data + * + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_UUID_LIST. + */ +static inline void +nvme_init_identify_uuid_list(struct nvme_passthru_cmd *cmd, + struct nvme_id_uuid_list *uuid_list) +{ + nvme_init_identify(cmd, NVME_UUID_NONE, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_UUID_LIST, + uuid_list, sizeof(*uuid_list)); +} + +/** + * nvme_init_identify_domain_list() - Initialize passthru command for + * Domain list + * @cmd: Command data structure to initialize + * @domid: Domain ID + * @list: User space destination address to transfer data + * + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_DOMAIN_LIST. + */ +static inline void +nvme_init_identify_domain_list(struct nvme_passthru_cmd *cmd, + __u16 domid, struct nvme_id_domain_list *list) +{ + nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_DOMAIN_LIST, + list, sizeof(*list)); + cmd->cdw11 |= NVME_FIELD_ENCODE(domid, + NVME_IDENTIFY_CDW11_DOMID_SHIFT, + NVME_IDENTIFY_CDW11_DOMID_MASK); +} + +/** + * nvme_init_identify_endurance_group_id() - Initialize passthru command for + * Endurance group list + * @cmd: Command data structure to initialize + * @enggid: Endurance group identifier + * @list: Array of endurance group identifiers + * + * 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 void +nvme_init_identify_endurance_group_id(struct nvme_passthru_cmd *cmd, + __u16 enggid, struct nvme_id_endurance_group_list *list) +{ + nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_ENDURANCE_GROUP_ID, + list, sizeof(*list)); + cmd->cdw11 |= NVME_FIELD_ENCODE(enggid, + NVME_IDENTIFY_CDW11_ENGGID_SHIFT, + NVME_IDENTIFY_CDW11_ENGGID_MASK); +} + +/** + * nvme_init_identify_csi_allocated_ns_list() - Initialize passthru command for + * I/O Command Set specific Allocated Namespace Id list + * @cmd: Command data structure to initialize + * @nsid: Return namespaces greater than this identifier + * @csi: Command Set Identifier + * @ns_list: User space destination address to transfer the data + * + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_CSI_ALLOCATED_NS_LIST. + */ +static inline void +nvme_init_identify_csi_allocated_ns_list(struct nvme_passthru_cmd *cmd, + __u32 nsid, enum nvme_csi csi, struct nvme_ns_list *ns_list) +{ + nvme_init_identify(cmd, nsid, csi, + NVME_IDENTIFY_CNS_CSI_ALLOCATED_NS_LIST, + ns_list, sizeof(*ns_list)); +} + +/** + * nvme_init_identify_csi_id_ns_data_structure() - Initialize passthru command + * for I/O Command Set specific Identify Namespace data structure + * @cmd: Command data structure to initialize + * @nsid: Return namespaces greater than this identifier + * @csi: Command Set Identifier + * @data: User space destination address to transfer the data + * + * Initializes the passthru command buffer for the Identify command with + * CNS value %NVME_IDENTIFY_CNS_CSI_ID_NS_DATA_STRUCTURE. + */ +static inline void +nvme_init_identify_csi_id_ns_data_structure(struct nvme_passthru_cmd *cmd, + __u32 nsid, enum nvme_csi csi, void *data) +{ + nvme_init_identify(cmd, nsid, csi, + NVME_IDENTIFY_CNS_CSI_ID_NS_DATA_STRUCTURE, + data, NVME_IDENTIFY_DATA_SIZE); +} + +/** + * nvme_init_identify_command_set_structure() - Initialize passthru command for + * I/O Command Set data structure + * @cmd: Command data structure to initialize + * @cntid: Controller ID + * @iocs: User space destination address to transfer the data + * + * Retrieves list of the controller's supported io command set vectors. See + * &struct nvme_id_iocs. + * + * 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 void +nvme_init_identify_command_set_structure(struct nvme_passthru_cmd *cmd, + __u16 cntid, struct nvme_id_iocs *iocs) +{ + nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM, + NVME_IDENTIFY_CNS_COMMAND_SET_STRUCTURE, + iocs, sizeof(*iocs)); + cmd->cdw10 |= NVME_FIELD_ENCODE(cntid, + NVME_IDENTIFY_CDW10_CNTID_SHIFT, + NVME_IDENTIFY_CDW10_CNTID_MASK); +} + +/** + * nvme_init_zns_identify_ns() - Initialize passthru command for + * ZNS identify namespace data + * @cmd: Command data structure to initialize + * @nsid: Namespace to identify + * @data: User space destination address to transfer the data + */ +static inline void +nvme_init_zns_identify_ns(struct nvme_passthru_cmd *cmd, + __u32 nsid, struct nvme_zns_id_ns *data) +{ + nvme_init_identify(cmd, nsid, NVME_CSI_ZNS, + NVME_IDENTIFY_CNS_CSI_NS, + data, sizeof(*data)); +} + +/** + * nvme_init_zns_identify_ctrl() - Initialize passthru command for + * ZNS identify controller data + * @cmd: Command data structure to initialize + * @id: User space destination address to transfer the data + */ +static inline void +nvme_init_zns_identify_ctrl(struct nvme_passthru_cmd *cmd, + struct nvme_zns_id_ctrl *id) +{ + nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_ZNS, + NVME_IDENTIFY_CNS_CSI_CTRL, + id, sizeof(*id)); +} + +/** + * nvme_get_log() - Get log page data + * @hdl: Transport handle + * @cmd: Passthru command + * @rae: Retain asynchronous events + * @xfer_len: Max log transfer size per request to split the total. + * + * 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_get_log(struct nvme_transport_handle *hdl, + struct nvme_passthru_cmd *cmd, bool rae, + __u32 xfer_len); + +/** + * nvme_init_get_log_lpo() - Initializes passthru command with a + * Log Page Offset + * @cmd: Passthru command + * @lpo: Log Page Offset to set + */ +static inline void +nvme_init_get_log_lpo(struct nvme_passthru_cmd *cmd, __u64 lpo) +{ + cmd->cdw12 = lpo & 0xffffffff; + cmd->cdw13 = lpo >> 32; +} + +/** + * nvme_init_get_log() - Initialize passthru command for + * NVMe Admin Get Log + * @cmd: Passthru command to use + * @nsid: Namespace identifier, if applicable + * @lid: Log Page Identifier, see &enum nvme_cmd_get_log_lid + * @csi: Command set identifier, see &enum nvme_csi for known values + * @data: User space destination address to transfer the data + * @len: Length of provided user buffer to hold the log data in bytes + */ +static inline void +nvme_init_get_log(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_cmd_get_log_lid lid, enum nvme_csi csi, + void *data, __u32 len) +{ + __u32 numd = (len >> 2) - 1; + __u16 numdu = numd >> 16; + __u16 numdl = numd & 0xffff; + __u32 cdw10 = NVME_FIELD_ENCODE(lid, + NVME_LOG_CDW10_LID_SHIFT, + NVME_LOG_CDW10_LID_MASK) | + NVME_FIELD_ENCODE(numdl, + NVME_LOG_CDW10_NUMDL_SHIFT, + NVME_LOG_CDW10_NUMDL_MASK); + __u32 cdw11 = NVME_FIELD_ENCODE(numdu, + NVME_LOG_CDW11_NUMDU_SHIFT, + NVME_LOG_CDW11_NUMDU_MASK); + __u32 cdw14 = NVME_FIELD_ENCODE(csi, + NVME_LOG_CDW14_CSI_SHIFT, + NVME_LOG_CDW14_CSI_MASK); + + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_get_log_page; + cmd->nsid = nsid; + cmd->cdw10 = cdw10; + cmd->cdw11 = cdw11; + cmd->cdw14 = cdw14; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; +} + +/** + * nvme_init_get_log_supported_log_pages() - Initialize passthru command for + * Supported Log Pages + * @cmd: Passthru command to use + * @csi: Command set identifier, see &enum nvme_csi for known values + * @log: Array of LID supported and Effects data structures + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_SUPPORTED_LOG_PAGES. + */ +static inline void +nvme_init_get_log_supported_log_pages(struct nvme_passthru_cmd *cmd, + enum nvme_csi csi, struct nvme_supported_log_pages *log) +{ + nvme_init_get_log(cmd, NVME_NSID_ALL, NVME_LOG_LID_SUPPORTED_LOG_PAGES, + csi, log, sizeof(*log)); +} + +/** + * nvme_init_get_log_error() - Initialize passthru command for Error Information + * @cmd: Passthru command to use + * @nr_entries: Number of error log entries allocated + * @err_log: Array of error logs of size 'entries' + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_ERROR. + */ +static inline void +nvme_init_get_log_error(struct nvme_passthru_cmd *cmd, unsigned int nr_entries, + struct nvme_error_log_page *err_log) +{ + nvme_init_get_log(cmd, NVME_NSID_ALL, NVME_LOG_LID_ERROR, + NVME_CSI_NVM, err_log, sizeof(*err_log) * nr_entries); +} + +/** + * nvme_init_get_log_smart() - Initialize passthru command for + * SMART / Health Information + * @cmd: Passthru command to use + * @nsid: Optional namespace identifier + * @smart_log: User address to store the smart log + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_SMART. + */ +static inline void +nvme_init_get_log_smart(struct nvme_passthru_cmd *cmd, __u32 nsid, + struct nvme_smart_log *smart_log) +{ + nvme_init_get_log(cmd, nsid, NVME_LOG_LID_SMART, NVME_CSI_NVM, + smart_log, sizeof(*smart_log)); +} + +/** + * nvme_init_get_log_fw_slot() - Initialize passthru command for + * Firmware Slot Information + * @cmd: Passthru command to use + * @fw_log: User address to store the log page + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_SMART. + */ +static inline void +nvme_init_get_log_fw_slot(struct nvme_passthru_cmd *cmd, + struct nvme_firmware_slot *fw_log) +{ + nvme_init_get_log(cmd, NVME_NSID_ALL, NVME_LOG_LID_FW_SLOT, + NVME_CSI_NVM, fw_log, sizeof(*fw_log)); +} + +/** + * nvme_init_get_log_changed_ns() - Initialize passthru command for + * Changed Attached Namespace List + * @cmd: Passthru command to use + * @ns_log: User address to store the log page + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_CHANGED_NS. + */ +static inline void +nvme_init_get_log_changed_ns(struct nvme_passthru_cmd *cmd, + struct nvme_ns_list *ns_log) +{ + nvme_init_get_log(cmd, NVME_NSID_ALL, NVME_LOG_LID_CHANGED_NS, + NVME_CSI_NVM, ns_log, sizeof(*ns_log)); +} + + +/** + * nvme_init_get_log_cmd_effects() - Initialize passthru command for + * Commands Supported and Effects + * @cmd: Passthru command to use + * @csi: Command Set Identifier + * @effects_log:User address to store the effects log + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_CMD_EFFECTS. + */ +static inline void +nvme_init_get_log_cmd_effects(struct nvme_passthru_cmd *cmd, + enum nvme_csi csi, struct nvme_cmd_effects_log *effects_log) +{ + nvme_init_get_log(cmd, NVME_NSID_ALL, NVME_LOG_LID_CMD_EFFECTS, csi, + effects_log, sizeof(*effects_log)); +} + +/** + * nvme_init_get_log_device_self_test() - Initialize passthru command for + * Device Self-test + * @cmd: Passthru command to use + * @log: Userspace address of the log payload + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_DEVICE_SELF_TEST. + */ +static inline void +nvme_init_get_log_device_self_test(struct nvme_passthru_cmd *cmd, + struct nvme_self_test_log *log) +{ + nvme_init_get_log(cmd, NVME_NSID_ALL, NVME_LOG_LID_DEVICE_SELF_TEST, + NVME_CSI_NVM, log, sizeof(*log)); +} + +/** + * nvme_init_get_log_telemetry_host() - Initialize passthru command for + * Telemetry Host-Initiated + * @cmd: Passthru command to use + * @lpo: Offset into the telemetry data + * @log: User address for log page data + * @len: Length of provided user buffer to hold the log data in bytes + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_TELEMETRY_HOST. + */ +static inline void +nvme_init_get_log_telemetry_host(struct nvme_passthru_cmd *cmd, __u64 lpo, + void *log, __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, NVME_LOG_LID_TELEMETRY_HOST, + NVME_CSI_NVM, log, len); + cmd->cdw10 |= NVME_FIELD_ENCODE(NVME_LOG_TELEM_HOST_LSP_RETAIN, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); + nvme_init_get_log_lpo(cmd, lpo); +} + +/** + * nvme_init_get_log_create_telemetry_host_mcda() - Initialize passthru + * command for Create Telemetry Host-Initiated + * @cmd: Passthru command to use + * @mcda: Maximum Created Data Area + * @log: Userspace address of the log payload + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_TELEMETRY_HOST and + * LSP value %NVME_LOG_TELEM_HOST_LSP_CREATE. + */ +static inline void +nvme_init_get_log_create_telemetry_host_mcda(struct nvme_passthru_cmd *cmd, + enum nvme_telemetry_da mcda, struct nvme_telemetry_log *log) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, NVME_LOG_LID_TELEMETRY_HOST, + NVME_CSI_NVM, log, sizeof(*log)); + cmd->cdw10 |= NVME_FIELD_ENCODE( + mcda << 1 | NVME_LOG_TELEM_HOST_LSP_CREATE, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); +} + +/** + * nvme_init_get_log_create_telemetry_host() - Initialize passthru command for + * Create Telemetry Host-Initiated + * @cmd: Passthru command to use + * @log: Userspace address of the log payload + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_TELEMETRY_HOST and + * LSP value %NVME_LOG_TELEM_HOST_LSP_CREATE. + */ +static inline void +nvme_init_get_log_create_telemetry_host(struct nvme_passthru_cmd *cmd, + struct nvme_telemetry_log *log) +{ + nvme_init_get_log_create_telemetry_host_mcda(cmd, + NVME_TELEMETRY_DA_CTRL_DETERMINE, log); +} + +/** + * nvme_init_get_log_telemetry_ctrl() - Initialize passthru command for + * Telemetry Controller-Initiated + * @cmd: Passthru command to use + * @lpo: Offset into the telemetry data + * @log: User address for log page data + * @len: Length of provided user buffer to hold the log data in bytes + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_TELEMETRY_CTRL. + */ +static inline void +nvme_init_get_log_telemetry_ctrl(struct nvme_passthru_cmd *cmd, + __u64 lpo, void *log, __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, NVME_LOG_LID_TELEMETRY_CTRL, + NVME_CSI_NVM, log, len); + nvme_init_get_log_lpo(cmd, lpo); +} + +/** + * nvme_init_get_log_endurance_group() - Initialize passthru command for + * Endurance Group Information + * @cmd: Passthru command to use + * @endgid: Starting group identifier to return in the list + * @log: User address to store the endurance log + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_ENDURANCE_GROUP. + */ +static inline void +nvme_init_get_log_endurance_group(struct nvme_passthru_cmd *cmd, __u16 endgid, + struct nvme_endurance_group_log *log) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, NVME_LOG_LID_ENDURANCE_GROUP, + NVME_CSI_NVM, log, sizeof(*log)); + cmd->cdw11 |= NVME_FIELD_ENCODE(endgid, + NVME_LOG_CDW11_LSI_SHIFT, + NVME_LOG_CDW11_LSI_MASK); +} + +/** + * nvme_init_get_log_predictable_lat_nvmset() - Initialize passthru command for + * Predictable Latency Per NVM Set + * @cmd: Passthru command to use + * @nvmsetid: NVM set id + * @log: User address to store the predictable latency log + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_PREDICTABLE_LAT_NVMSET. + */ +static inline void +nvme_init_get_log_predictable_lat_nvmset(struct nvme_passthru_cmd *cmd, + __u16 nvmsetid, struct nvme_nvmset_predictable_lat_log *log) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_PREDICTABLE_LAT_NVMSET, NVME_CSI_NVM, + log, sizeof(*log)); + cmd->cdw11 |= NVME_FIELD_ENCODE(nvmsetid, + NVME_LOG_CDW11_LSI_SHIFT, + NVME_LOG_CDW11_LSI_MASK); +} + +/** + * nvme_init_get_log_predictable_lat_event() - Initialize passthru command for + * Predictable Latency Event Aggregate + * @cmd: Passthru command to use + * @lpo: Offset into the predictable latency event + * @log: User address for log page data + * @len: Length of provided user buffer to hold the log data in bytes + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_PREDICTABLE_LAT_AGG. + */ +static inline void +nvme_init_get_log_predictable_lat_event(struct nvme_passthru_cmd *cmd, + __u64 lpo, void *log, __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_PREDICTABLE_LAT_AGG, NVME_CSI_NVM, + log, len); + cmd->cdw12 = lpo & 0xffffffff; + cmd->cdw13 = lpo >> 32; +} + +/** + * nvme_init_get_log_ana() - Initialize passthru command for + * Asymmetric Namespace Access + * @cmd: Passthru command to use + * @lsp: Log specific, see &enum nvme_get_log_ana_lsp + * @lpo: Offset to the start of the log page + * @log: User address to store the ana log + * @len: The allocated length of the log page + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_ANA. + */ +static inline void +nvme_init_get_log_ana(struct nvme_passthru_cmd *cmd, + enum nvme_log_ana_lsp lsp, __u64 lpo, void *log, __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_ANA, NVME_CSI_NVM, + log, len); + cmd->cdw10 |= NVME_FIELD_ENCODE(lsp, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); + cmd->cdw12 = lpo & 0xffffffff; + cmd->cdw13 = lpo >> 32; +} + +/** + * nvme_init_get_log_ana_groups() - Initialize passthru command for + * Asymmetric Namespace Access groups + * @cmd: Passthru command to use + * @log: User address to store the ana group log + * @len: The allocated length of the log page + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_ANA and LSP value %NVME_LOG_ANA_LSP_RGO_GROUPS_ONLY + */ +static inline void +nvme_init_get_log_ana_groups(struct nvme_passthru_cmd *cmd, + struct nvme_ana_log *log, __u32 len) +{ + nvme_init_get_log_ana(cmd, NVME_LOG_ANA_LSP_RGO_GROUPS_ONLY, + 0, log, len); +} + +/** + * nvme_init_get_log_persistent_event() - Initialize passthru command for + * Persistent Event Log + * @cmd: Passthru command to use + * @action: Action the controller should take during processing this command + * @pevent_log: User address to store the persistent event log + * @len: Size of @pevent_log + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_PERSISTENT_EVENT + */ +static inline void +nvme_init_get_log_persistent_event(struct nvme_passthru_cmd *cmd, + enum nvme_pevent_log_action action, + void *pevent_log, __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_ALL, + NVME_LOG_LID_PERSISTENT_EVENT, NVME_CSI_NVM, + pevent_log, len); + cmd->cdw10 |= NVME_FIELD_ENCODE(action, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); +} + +/** + * nvme_init_get_log_lba_status() - Initialize passthru command for + * Retrieve LBA Status + * @cmd: Passthru command to use + * @lpo: Offset to the start of the log page + * @log: User address to store the log page + * @len: The allocated length of the log page + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_LBA_STATUS + */ +static inline void +nvme_init_get_log_lba_status(struct nvme_passthru_cmd *cmd, + __u64 lpo, void *log, __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_LBA_STATUS, NVME_CSI_NVM, + log, len); + cmd->cdw12 = lpo & 0xffffffff; + cmd->cdw13 = lpo >> 32; +} + +/** + * nvme_init_get_log_endurance_grp_evt() - Initialize passthru command for + * Endurance Group Event Aggregate + * @cmd: Passthru command to use + * @lpo: Offset to the start of the log page + * @log: User address to store the log page + * @len: The allocated length of the log page + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_ENDURANCE_GRP_EVT + */ +static inline void +nvme_init_get_log_endurance_grp_evt(struct nvme_passthru_cmd *cmd, + __u64 lpo, void *log, __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_ENDURANCE_GRP_EVT, NVME_CSI_NVM, + log, len); + nvme_init_get_log_lpo(cmd, lpo); +} + +/** + * nvme_init_get_log_media_unit_stat() - Initialize passthru command for + * Media Unit Status + * @cmd: Passthru command to use + * @domid: Domain Identifier selection, if supported + * @mus: User address to store the Media Unit statistics log + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_MEDIA_UNIT_STATUS + */ +static inline void +nvme_init_get_log_media_unit_stat(struct nvme_passthru_cmd *cmd, + __u16 domid, struct nvme_media_unit_stat_log *mus) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_MEDIA_UNIT_STATUS, NVME_CSI_NVM, + mus, sizeof(*mus)); + cmd->cdw11 |= NVME_FIELD_ENCODE(domid, + NVME_LOG_CDW11_LSI_SHIFT, + NVME_LOG_CDW11_LSI_MASK); +} + +/** + * nvme_init_get_log_support_cap_config_list() - Initialize passthru command for + * Supported Capacity Configuration List + * @cmd: Passthru command to use + * @domid: Domain Identifier selection, if supported + * @cap: User address to store supported capabilities config list + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_SUPPORTED_CAP_CONFIG_LIST + */ +static inline void +nvme_init_get_log_support_cap_config_list(struct nvme_passthru_cmd *cmd, + __u16 domid, struct nvme_supported_cap_config_list_log *cap) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_SUPPORTED_CAP_CONFIG_LIST, NVME_CSI_NVM, + cap, sizeof(*cap)); + cmd->cdw11 |= NVME_FIELD_ENCODE(domid, + NVME_LOG_CDW11_LSI_SHIFT, + NVME_LOG_CDW11_LSI_MASK); +} + +/** + * nvme_init_get_log_fid_supported_effects() - Initialize passthru command for + * Feature Identifiers Supported and Effects + * @cmd: Passthru command to use + * @csi: Command set identifier, see &enum nvme_csi for known values + * @log: FID Supported and Effects data structure + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_FID_SUPPORTED_EFFECTS + */ +static inline void +nvme_init_get_log_fid_supported_effects(struct nvme_passthru_cmd *cmd, + enum nvme_csi csi, struct nvme_fid_supported_effects_log *log) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_FID_SUPPORTED_EFFECTS, csi, + log, sizeof(*log)); +} + +/** + * nvme_init_get_log_mi_cmd_supported_effects() - Initialize passthru command + * for MI Commands Supported by the controller + * @cmd: Passthru command to use + * @log: MI Command Supported and Effects data structure + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_MI_CMD_SUPPORTED_EFFECTS + */ +static inline void +nvme_init_get_log_mi_cmd_supported_effects(struct nvme_passthru_cmd *cmd, + struct nvme_mi_cmd_supported_effects_log *log) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_MI_CMD_SUPPORTED_EFFECTS, NVME_CSI_NVM, + log, sizeof(*log)); +} + +/** + * nvme_init_get_log_lockdown() - Initialize passthru command for + * Command and Feature Lockdown + * @cmd: Passthru command to use + * @cnscp: Contents and Scope of Command and Feature Identifier + * Lists + * @lockdown_log: Buffer to store the lockdown log + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_CMD_AND_FEAT_LOCKDOWN + */ +static inline void +nvme_init_get_log_lockdown(struct nvme_passthru_cmd *cmd, + __u8 cnscp, struct nvme_lockdown_log *lockdown_log) +{ + nvme_init_get_log(cmd, NVME_NSID_ALL, + NVME_LOG_LID_CMD_AND_FEAT_LOCKDOWN, NVME_CSI_NVM, + lockdown_log, sizeof(*lockdown_log)); + cmd->cdw10 |= NVME_FIELD_ENCODE(cnscp, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); +} + +/** + * nvme_init_get_log_boot_partition() - Initialize passthru command for + * Boot Partition + * @cmd: Passthru command to use + * @lsp: The log specified field of LID + * @part: User address to store the log page + * @len: The allocated size, minimum + * struct nvme_boot_partition + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_BOOT_PARTITION + */ +static inline void +nvme_init_get_log_boot_partition(struct nvme_passthru_cmd *cmd, + __u8 lsp, struct nvme_boot_partition *part, __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_BOOT_PARTITION, NVME_CSI_NVM, + part, len); + cmd->cdw10 |= NVME_FIELD_ENCODE(lsp, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); +} + +/** + * nvme_init_get_log_rotational_media_info() - Initialize passthru command for + * Rotational Media Information Log + * @cmd: Passthru command to use + * @endgid: Endurance Group Identifier + * @log: User address to store the log page + * @len: The allocated length of the log page + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_ROTATIONAL_MEDIA_INFO + */ +static inline void +nvme_init_get_log_rotational_media_info(struct nvme_passthru_cmd *cmd, + __u16 endgid, struct nvme_rotational_media_info_log *log, + __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_ROTATIONAL_MEDIA_INFO, NVME_CSI_NVM, + log, len); + cmd->cdw11 |= NVME_FIELD_ENCODE(endgid, + NVME_LOG_CDW11_LSI_SHIFT, + NVME_LOG_CDW11_LSI_MASK); +} + +/** + * nvme_init_get_log_dispersed_ns_participating_nss() - Initialize passthru + * command for Dispersed Namespace Participating NVM Subsystems + * @cmd: Passthru command to use + * @nsid: Namespace Identifier + * @log: User address to store the log page + * @len: The allocated length of the log page + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_DISPERSED_NS_PARTICIPATING_NSS + */ +static inline void +nvme_init_get_log_dispersed_ns_participating_nss(struct nvme_passthru_cmd *cmd, + __u32 nsid, struct nvme_dispersed_ns_participating_nss_log *log, + __u32 len) +{ + nvme_init_get_log(cmd, nsid, + NVME_LOG_LID_DISPERSED_NS_PARTICIPATING_NSS, NVME_CSI_NVM, + log, len); +} + +/** + * nvme_init_get_log_mgmt_addr_list() - Initialize passthru command for + * Management Address List + * @cmd: Passthru command to use + * @log: User address to store the log page + * @len: The allocated length of the log page + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_MGMT_ADDR_LIST + */ +static inline void +nvme_init_get_log_mgmt_addr_list(struct nvme_passthru_cmd *cmd, + struct nvme_mgmt_addr_list_log *log, __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_ALL, + NVME_LOG_LID_MGMT_ADDR_LIST, NVME_CSI_NVM, + log, len); +} + +/** + * nvme_init_get_log_phy_rx_eom() - Initialize passthru command for + * Physical Interface Receiver Eye Opening Measurement + * @cmd: Passthru command to use + * @lsp: Log specific, controls action and measurement quality + * @controller: Target controller ID + * @log: User address to store the log page + * @len: The allocated size, minimum + * struct nvme_phy_rx_eom_log + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_PHY_RX_EOM + */ +static inline void +nvme_init_get_log_phy_rx_eom(struct nvme_passthru_cmd *cmd, + __u8 lsp, __u16 controller, struct nvme_phy_rx_eom_log *log, + __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_PHY_RX_EOM, NVME_CSI_NVM, + log, len); + cmd->cdw10 |= NVME_FIELD_ENCODE(lsp, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); + cmd->cdw11 |= NVME_FIELD_ENCODE(controller, + NVME_LOG_CDW11_LSI_SHIFT, + NVME_LOG_CDW11_LSI_MASK); +} + +/** + * nvme_init_get_log_reachability_groups() - Initialize passthru command for + * Retrieve Reachability Groups + * @cmd: Passthru command to use + * @rgo: Return groups only + * @log: User address to store the log page + * @len: The allocated length of the log page + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_REACHABILITY_GROUPS + */ +static inline void +nvme_init_get_log_reachability_groups(struct nvme_passthru_cmd *cmd, + bool rgo, struct nvme_reachability_groups_log *log, __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_ALL, + NVME_LOG_LID_REACHABILITY_GROUPS, NVME_CSI_NVM, + log, len); + cmd->cdw10 |= NVME_FIELD_ENCODE((__u8)rgo, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); +} + +/** + * nvme_init_get_log_reachability_associations() - Initialize passthru command + * for Reachability Associations Log + * @cmd: Passthru command to use + * @rao: Return associations only + * @log: User address to store the log page + * @len: The allocated length of the log page + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_REACHABILITY_ASSOCIATIONS + */ +static inline void +nvme_init_get_log_reachability_associations(struct nvme_passthru_cmd *cmd, + bool rao, struct nvme_reachability_associations_log *log, + __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_ALL, + NVME_LOG_LID_REACHABILITY_ASSOCIATIONS, NVME_CSI_NVM, + log, len); + cmd->cdw10 |= NVME_FIELD_ENCODE((__u8)rao, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); +} + +/** + * nvme_init_get_log_changed_alloc_ns() - Initialize passthru command for + * Changed Allocated Namespace List + * @cmd: Passthru command to use + * @log: User address to store the log page + * @len: The allocated length of the log page + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_CHANGED_ALLOC_NS + */ +static inline void +nvme_init_get_log_changed_alloc_ns(struct nvme_passthru_cmd *cmd, + struct nvme_ns_list *log, __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_ALL, + NVME_LOG_LID_CHANGED_ALLOC_NS, NVME_CSI_NVM, + log, len); +} + +/** + * nvme_init_get_log_fdp_configurations() - Initialize passthru command for + * Flexible Data Placement Configurations + * @cmd: Passthru command to use + * @egid: Endurance group identifier + * @lpo: Offset into log page + * @log: Log page data buffer + * @len: Length (in bytes) of provided user buffer to hold the log data + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_FDP_CONFIGS + */ +static inline void +nvme_init_get_log_fdp_configurations(struct nvme_passthru_cmd *cmd, + __u16 egid, __u64 lpo, void *log, __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_FDP_CONFIGS, NVME_CSI_NVM, + log, len); + cmd->cdw11 |= NVME_FIELD_ENCODE(egid, + NVME_LOG_CDW11_LSI_SHIFT, + NVME_LOG_CDW11_LSI_MASK); + nvme_init_get_log_lpo(cmd, lpo); +} + +/** + * nvme_init_get_log_reclaim_unit_handle_usage() - Initialize passthru + * command for Reclaim Unit Handle Usage + * @cmd: Passthru command to use + * @egid: Endurance group identifier + * @lpo: Offset into log page + * @log: Log page data buffer + * @len: Length (in bytes) of provided user buffer to hold the log data + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_RUH_USAGE + */ +static inline void +nvme_init_get_log_reclaim_unit_handle_usage(struct nvme_passthru_cmd *cmd, + __u16 egid, __u64 lpo, void *log, __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_FDP_RUH_USAGE, NVME_CSI_NVM, + log, len); + cmd->cdw11 |= NVME_FIELD_ENCODE(egid, + NVME_LOG_CDW11_LSI_SHIFT, + NVME_LOG_CDW11_LSI_MASK); + nvme_init_get_log_lpo(cmd, lpo); +} + +/** + * nvme_init_get_log_fdp_stats() - Initialize passthru command for + * Get Flexible Data Placement Statistics + * @cmd: Passthru command to use + * @egid: Endurance group identifier + * @lpo: Offset into log page + * @log: Log page data buffer + * @len: Length (in bytes) of provided user buffer to hold the log data + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_FDP_STATS + */ +static inline +void nvme_init_get_log_fdp_stats(struct nvme_passthru_cmd *cmd, + __u16 egid, __u64 lpo, void *log, __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_FDP_STATS, NVME_CSI_NVM, + log, len); + cmd->cdw11 |= NVME_FIELD_ENCODE(egid, + NVME_LOG_CDW11_LSI_SHIFT, + NVME_LOG_CDW11_LSI_MASK); + nvme_init_get_log_lpo(cmd, lpo); +} + +/** + * nvme_init_get_log_fdp_events() - Initialize passthru command for + * Flexible Data Placement Events + * @cmd: Passthru command to use + * @host_events: Whether to report host or controller events + * @egid: Endurance group identifier + * @lpo: Offset into log page + * @log: Log page data buffer + * @len: Length (in bytes) of provided user buffer to hold + * the log data + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_FDP_EVENTS + */ +static inline void +nvme_init_get_log_fdp_events(struct nvme_passthru_cmd *cmd, + bool host_events, __u16 egid, __u64 lpo, void *log, __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_FDP_EVENTS, NVME_CSI_NVM, + log, len); + cmd->cdw10 |= NVME_FIELD_ENCODE((__u8)(host_events ? 0x1 : 0x0), + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); + cmd->cdw11 |= NVME_FIELD_ENCODE(egid, + NVME_LOG_CDW11_LSI_SHIFT, + NVME_LOG_CDW11_LSI_MASK); + nvme_init_get_log_lpo(cmd, lpo); +} + + +/** + * nvme_init_get_log_discovery() - Initialize passthru command for Discovery + * @cmd: Passthru command to use + * @lpo: Offset of this log to retrieve + * @log: User address to store the discovery log + * @len: The allocated size for this portion of the log + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_DISCOVERY + */ +static inline void +nvme_init_get_log_discovery(struct nvme_passthru_cmd *cmd, + __u64 lpo, void *log, __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_NONE, + NVME_LOG_LID_DISCOVERY, NVME_CSI_NVM, + log, len); + nvme_init_get_log_lpo(cmd, lpo); +} + +/** + * nvme_init_get_log_host_discovery() - Initialize passthru command for + * Host Discover + * @cmd: Passthru command to use + * @allhoste: All host entries + * @log: User address to store the log page + * @len: The allocated length of the log page + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_HOST_DISCOVERY + */ +static inline void +nvme_init_get_log_host_discovery(struct nvme_passthru_cmd *cmd, + bool allhoste, struct nvme_host_discover_log *log, __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_ALL, + NVME_LOG_LID_HOST_DISCOVERY, NVME_CSI_NVM, + log, len); + cmd->cdw10 |= NVME_FIELD_ENCODE((__u8)allhoste, + NVME_LOG_CDW10_LSP_SHIFT, + NVME_LOG_CDW10_LSP_MASK); +} + +/** + * nvme_init_get_log_ave_discovery() - Initialize passthru command for + * AVE Discovery + * @cmd: Passthru command to use + * @log: User address to store the log page + * @len: The allocated length of the log page + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_AVE_DISCOVERY + */ +static inline void +nvme_init_get_log_ave_discovery(struct nvme_passthru_cmd *cmd, + struct nvme_ave_discover_log *log, __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_ALL, + NVME_LOG_LID_AVE_DISCOVERY, NVME_CSI_NVM, + log, len); +} + +/** + * nvme_init_get_log_pull_model_ddc_req() - Initialize passthru command for + * Pull Model DDC Request + * @cmd: Passthru command to use + * @log: User address to store the log page + * @len: The allocated length of the log page + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_PULL_MODEL_DDC_REQ + */ +static inline void +nvme_init_get_log_pull_model_ddc_req(struct nvme_passthru_cmd *cmd, + struct nvme_pull_model_ddc_req_log *log, __u32 len) +{ + nvme_init_get_log(cmd, NVME_NSID_ALL, + NVME_LOG_LID_PULL_MODEL_DDC_REQ, NVME_CSI_NVM, + log, len); +} + +/** + * nvme_init_get_log_reservation() - Initialize passthru command for + * Reservation Notification + * @cmd: Passthru command to use + * @log: User address to store the reservation log + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_RESERVATION + */ +static inline void +nvme_init_get_log_reservation(struct nvme_passthru_cmd *cmd, + struct nvme_resv_notification_log *log) +{ + nvme_init_get_log(cmd, NVME_NSID_ALL, + NVME_LOG_LID_RESERVATION, NVME_CSI_NVM, + log, sizeof(*log)); +} + +/** + * nvme_init_get_log_sanitize() - Initialize passthru command for + * Sanitize Status + * @cmd: Passthru command to use + * @log: User address to store the sanitize log + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_SANITIZE + */ +static inline void +nvme_init_get_log_sanitize(struct nvme_passthru_cmd *cmd, + struct nvme_sanitize_log_page *log) +{ + nvme_init_get_log(cmd, NVME_NSID_ALL, + NVME_LOG_LID_SANITIZE, NVME_CSI_NVM, + log, sizeof(*log)); +} + +/** + * nvme_init_get_log_zns_changed_zones() - Initialize passthru command for + * list of zones that have changed + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @log: User address to store the changed zone log + * + * Initializes the passthru command buffer for the Get Log command with + * LID value %NVME_LOG_LID_ZNS_CHANGED_ZONES + */ +static inline void +nvme_init_get_log_zns_changed_zones(struct nvme_passthru_cmd *cmd, + __u32 nsid, struct nvme_zns_changed_zone_log *log) +{ + nvme_init_get_log(cmd, nsid, + NVME_LOG_LID_ZNS_CHANGED_ZONES, NVME_CSI_ZNS, + log, sizeof(*log)); +} + +/** + * nvme_get_ana_log_atomic() - Retrieve Asymmetric Namespace Access + * log page atomically + * @hdl: Transport handle + * @rae: Whether to retain asynchronous events + * @rgo: Whether to retrieve ANA groups only (no NSIDs) + * @log: Pointer to a buffer to receive the ANA log page + * @len: Input: the length of the log page buffer. + * Output: the actual length of the ANA log page. + * @retries: The maximum number of times to retry on log page changes + * + * See &struct nvme_ana_log for the definition of the returned structure. + * + * Return: If successful, returns 0 and sets *len to the actual log page length. + * If unsuccessful, returns the nvme command status if a response was received + * (see &enum nvme_status_field) or -1 with errno set otherwise. + * Sets errno = EINVAL if retries == 0. + * Sets errno = EAGAIN if unable to read the log page atomically + * because chgcnt changed during each of the retries attempts. + * Sets errno = ENOSPC if the full log page does not fit in the provided buffer. + */ +int +nvme_get_ana_log_atomic(struct nvme_transport_handle *hdl, bool rae, bool rgo, + struct nvme_ana_log *log, __u32 *len, unsigned int retries); + +/** + * nvme_init_set_features() - Initialize passthru command for + * Set Features + * @cmd: Passthru command to use + * @fid: Feature identifier + * @sv: Save value across power states + */ +static inline void +nvme_init_set_features(struct nvme_passthru_cmd *cmd, __u8 fid, bool sv) +{ + __u32 cdw10 = NVME_FIELD_ENCODE(fid, + NVME_SET_FEATURES_CDW10_FID_SHIFT, + NVME_SET_FEATURES_CDW10_FID_MASK) | + NVME_FIELD_ENCODE(sv, + NVME_SET_FEATURES_CDW10_SV_SHIFT, + NVME_SET_FEATURES_CDW10_SV_MASK); + + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_set_features; + cmd->cdw10 = cdw10; +} + +/** + * nvme_init_set_features_arbitration() -Initialize passthru command for + * Arbitration Features + * @cmd: Passthru command to use + * @sv: Save value across power states + * @ab: Arbitration Burst + * @lpw: Low Priority Weight + * @mpw: Medium Priority Weight + * @hpw: High Priority Weight + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_ARBRITARTION + */ +static inline void +nvme_init_set_features_arbitration(struct nvme_passthru_cmd *cmd, + bool sv, __u8 ab, __u8 lpw, __u8 mpw, __u8 hpw) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_ARBITRATION, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(ab, + NVME_FEAT_ARBITRATION_BURST_SHIFT, + NVME_FEAT_ARBITRATION_BURST_MASK) | + NVME_FIELD_ENCODE(lpw, + NVME_FEAT_ARBITRATION_LPW_SHIFT, + NVME_FEAT_ARBITRATION_LPW_MASK) | + NVME_FIELD_ENCODE(mpw, + NVME_FEAT_ARBITRATION_MPW_SHIFT, + NVME_FEAT_ARBITRATION_MPW_MASK) | + NVME_FIELD_ENCODE(hpw, + NVME_FEAT_ARBITRATION_HPW_SHIFT, + NVME_FEAT_ARBITRATION_HPW_MASK); +} + +/** + * nvme_init_set_features_power_mgmt() - Initialize passthru command for + * Power Management + * @cmd: Passthru command to use + * @sv: Save value across power states + * @ps: Power State + * @wh: Workload Hint + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_PWRMGMT_PS + */ +static inline void +nvme_init_set_features_power_mgmt(struct nvme_passthru_cmd *cmd, + bool sv, __u8 ps, __u8 wh) +{ + + nvme_init_set_features(cmd, NVME_FEAT_FID_POWER_MGMT, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(ps, + NVME_FEAT_PWRMGMT_PS_SHIFT, + NVME_FEAT_PWRMGMT_PS_MASK) | + NVME_FIELD_ENCODE(wh, + NVME_FEAT_PWRMGMT_WH_SHIFT, + NVME_FEAT_PWRMGMT_WH_MASK); +} + +/** + * nvme_init_set_features_lba_range() - Initialize passthru command for + * LBA Range + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @sv: Save value across power states + * @num: Number of ranges in @data + * @data: User address of feature data + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_LBA_RANGE + */ +static inline void +nvme_init_set_features_lba_range(struct nvme_passthru_cmd *cmd, + __u32 nsid, bool sv, __u8 num, + struct nvme_lba_range_type *data) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_LBA_RANGE, sv); + cmd->nsid = nsid; + cmd->cdw11 = NVME_FIELD_ENCODE(num - 1, + NVME_SET_FEATURES_CDW11_NUM_SHIFT, + NVME_SET_FEATURES_CDW11_NUM_MASK); + cmd->data_len = sizeof(*data); + cmd->addr = (__u64)(uintptr_t)data; +} + +/** + * nvme_init_set_features_temp_thresh() - Initialize passthru command for + * Temperature Threshold + * @cmd: Passthru command to use + * @sv: Save value across power states + * @tmpth: Temperature Threshold + * @tmpsel: Threshold Temperature Select + * @thsel: Threshold Type Select + * @tmpthh: Temperature Threshold Hysteresis + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_TEMP_THRESH + */ +static inline void +nvme_init_set_features_temp_thresh(struct nvme_passthru_cmd *cmd, + bool sv, __u16 tmpth, __u8 tmpsel, + enum nvme_feat_tmpthresh_thsel thsel, __u8 tmpthh) +{ + + nvme_init_set_features(cmd, NVME_FEAT_FID_TEMP_THRESH, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(tmpth, + NVME_FEAT_TT_TMPTH_SHIFT, + NVME_FEAT_TT_TMPTH_MASK) | + NVME_FIELD_ENCODE(tmpsel, + NVME_FEAT_TT_TMPSEL_SHIFT, + NVME_FEAT_TT_TMPSEL_MASK) | + NVME_FIELD_ENCODE(thsel, + NVME_FEAT_TT_THSEL_SHIFT, + NVME_FEAT_TT_THSEL_MASK) | + NVME_FIELD_ENCODE(tmpthh, + NVME_FEAT_TT_TMPTHH_SHIFT, + NVME_FEAT_TT_TMPTHH_MASK); +} + +/** + * nvme_init_set_features_err_recovery() - Initialize passthru command for + * Error Recovery + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @sv: Save value across power states + * @tler: Time-limited error recovery value + * @dulbe: Deallocated or Unwritten Logical Block Error Enable + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_ERR_RECOVERY + */ +static inline void +nvme_init_set_features_err_recovery(struct nvme_passthru_cmd *cmd, + __u32 nsid, bool sv, __u16 tler, bool dulbe) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_ERR_RECOVERY, sv); + cmd->nsid = nsid; + cmd->cdw11 = NVME_FIELD_ENCODE(tler, + NVME_FEAT_ERROR_RECOVERY_TLER_SHIFT, + NVME_FEAT_ERROR_RECOVERY_TLER_MASK) | + NVME_FIELD_ENCODE(dulbe, + NVME_FEAT_ERROR_RECOVERY_DULBE_SHIFT, + NVME_FEAT_ERROR_RECOVERY_DULBE_MASK); +} + +/** + * nvme_init_set_features_volatile_wc() - Initialize passthru command for + * Volatile Write Cache + * @cmd: Passthru command to use + * @sv: Save value across power states + * @wce: Write cache enable + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_VOLATILE_WC + */ +static inline void +nvme_init_set_features_volatile_wc(struct nvme_passthru_cmd *cmd, + bool sv, bool wce) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_VOLATILE_WC, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(wce, + NVME_FEAT_VWC_WCE_SHIFT, + NVME_FEAT_VWC_WCE_MASK); +} + +/** + * nvme_init_set_features_irq_coalesce() - Initialize passthru command for + * IRQ Coalescing + * @cmd: Passthru command to use + * @sv: Save value across power states + * @thr: Aggregation Threshold + * @time: Aggregation Time + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_IRQ_COALESCE + */ +static inline void +nvme_init_set_features_irq_coalesce(struct nvme_passthru_cmd *cmd, + bool sv, __u8 thr, __u8 time) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_IRQ_COALESCE, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(thr, + NVME_FEAT_IRQC_THR_SHIFT, + NVME_FEAT_IRQC_THR_MASK) | + NVME_FIELD_ENCODE(time, + NVME_FEAT_IRQC_TIME_SHIFT, + NVME_FEAT_IRQC_TIME_MASK); +} + +/** + * nvme_init_set_features_irq_config() - Initialize passthru command for + * IRQ Config + * @cmd: Passthru command to use + * @sv: Save value across power states + * @iv: Interrupt Vector + * @cd: Coalescing Disable + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_IRQ_CONFIG + */ +static inline void +nvme_init_set_features_irq_config(struct nvme_passthru_cmd *cmd, + bool sv, __u16 iv, bool cd) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_IRQ_CONFIG, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(iv, + NVME_FEAT_ICFG_IV_SHIFT, + NVME_FEAT_ICFG_IV_MASK) | + NVME_FIELD_ENCODE(cd, + NVME_FEAT_ICFG_CD_SHIFT, + NVME_FEAT_ICFG_CD_MASK); +} + +/** + * nvme_init_set_features_write_atomic() - Initialize passthru command for + * Write Atomic + * @cmd: Passthru command to use + * @sv: Save value across power states + * @dn: Disable Normal + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_WRITE_ATOMIC + */ +static inline void +nvme_init_set_features_write_atomic(struct nvme_passthru_cmd *cmd, + bool sv, bool dn) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_WRITE_ATOMIC, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(dn, + NVME_FEAT_WA_DN_SHIFT, + NVME_FEAT_WA_DN_MASK); +} + +/** + * nvme_init_set_features_async_event() - Initialize passthru command for + * Asynchronous Event Configuration + * @cmd: Passthru command to use + * @sv: Save value across power states + * @events: Events to enable + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_ASYNC_EVENT + */ +static inline void +nvme_init_set_features_async_event(struct nvme_passthru_cmd *cmd, + bool sv, __u32 events) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_ASYNC_EVENT, sv); + cmd->cdw11 = events; +} + +/** + * nvme_init_set_features_auto_pst() - Initialize passthru command for + * Autonomous Power State Transition + * @cmd: Passthru command to use + * @sv: Save value across power states + * @apste: Autonomous Power State Transition Enable + * @apst: Autonomous Power State Transition data buffer + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_AUTO_PST + */ +static inline void +nvme_init_set_features_auto_pst(struct nvme_passthru_cmd *cmd, + bool sv, bool apste, struct nvme_feat_auto_pst *apst) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_AUTO_PST, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(apste, + NVME_FEAT_APST_APSTE_SHIFT, + NVME_FEAT_APST_APSTE_MASK); + cmd->data_len = sizeof(*apst); + cmd->addr = (__u64)(uintptr_t)apst; +} + +/** + * nvme_init_set_features_timestamp() - Initialize passthru command for + * Timestamp + * @cmd: Passthru command to use + * @sv: Save value across power states + * @tstmp: The current timestamp value to assign to this feature + * @ts: Timestamp data buffer (populated by this function) + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_TIMESTAMP. The caller must provide a valid + * buffer via @ts, which this function will populate. + */ +static inline void +nvme_init_set_features_timestamp(struct nvme_passthru_cmd *cmd, + bool sv, __u64 tstmp, struct nvme_timestamp *ts) +{ + __le64 t = htole64(tstmp); + + memcpy(ts, &t, sizeof(__le64)); + + nvme_init_set_features(cmd, NVME_FEAT_FID_TIMESTAMP, sv); + cmd->data_len = sizeof(*ts); + cmd->addr = (__u64)(uintptr_t)ts; +} + +/** + * nvme_init_set_features_hctm() - Initialize passthru command for + * Host Controlled Thermal Management + * @cmd: Passthru command to use + * @sv: Save value across power states + * @tmt2: Thermal Management Temperature 2 + * @tmt1: Thermal Management Temperature 1 + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_HCTM + */ +static inline void +nvme_init_set_features_hctm(struct nvme_passthru_cmd *cmd, + bool sv, __u16 tmt2, __u16 tmt1) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_HCTM, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(tmt2, + NVME_FEAT_HCTM_TMT2_SHIFT, + NVME_FEAT_HCTM_TMT2_MASK) | + NVME_FIELD_ENCODE(tmt1, + NVME_FEAT_HCTM_TMT1_SHIFT, + NVME_FEAT_HCTM_TMT1_MASK); +} + +/** + * nvme_init_set_features_nopsc() - Initialize passthru command for + * Non-Operational Power State Config + * @cmd: Passthru command to use + * @sv: Save value across power states + * @noppme: Non-Operational Power State Permissive Mode Enable + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_NOPSC + */ +static inline void +nvme_init_set_features_nopsc(struct nvme_passthru_cmd *cmd, + bool sv, bool noppme) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_NOPSC, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(noppme, + NVME_FEAT_NOPS_NOPPME_SHIFT, + NVME_FEAT_NOPS_NOPPME_MASK); +} + +/** + * nvme_init_set_features_rrl() - Initialize passthru command for + * Read Recovery Level + * @cmd: Passthru command to use + * @sv: Save value across power states + * @nvmsetid: NVM set id + * @rrl: Read recovery level setting + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_RRL + */ +static inline void +nvme_init_set_features_rrl(struct nvme_passthru_cmd *cmd, + bool sv, __u16 nvmsetid, __u8 rrl) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_RRL, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(nvmsetid, + NVME_FEAT_RRL_NVMSETID_SHIFT, + NVME_FEAT_RRL_NVMSETID_MASK); + cmd->cdw12 = NVME_FIELD_ENCODE(rrl, + NVME_FEAT_RRL_RRL_SHIFT, + NVME_FEAT_RRL_RRL_MASK); +} + +/** + * nvme_init_set_features_plm_config() - Initialize passthru command for + * Predictable Latency Mode Config + * @cmd: Passthru command to use + * @sv: Save value across power states + * @nvmsetid: NVM Set Identifier + * @lpe: Predictable Latency Enable + * @data: Pointer to structure nvme_plm_config + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_PLM_CONFIG + */ +static inline void +nvme_init_set_features_plm_config(struct nvme_passthru_cmd *cmd, + bool sv, __u16 nvmsetid, bool lpe, struct nvme_plm_config *data) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_PLM_CONFIG, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(nvmsetid, + NVME_FEAT_PLM_NVMSETID_SHIFT, + NVME_FEAT_PLM_NVMSETID_MASK); + cmd->cdw12 = NVME_FIELD_ENCODE(lpe, + NVME_FEAT_PLM_LPE_SHIFT, + NVME_FEAT_PLM_LPE_MASK); + cmd->data_len = sizeof(*data); + cmd->addr = (__u64)(uintptr_t)data; +} + +/** + * nvme_init_set_features_plm_window() - Initialize passthru command for + * Predictable Latency Mode Window + * @cmd: Passthru command to use + * @sv: Save value across power states + * @nvmsetid: NVM Set Identifier + * @wsel: Window Select + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_PLM_WINDOW + */ +static inline void +nvme_init_set_features_plm_window(struct nvme_passthru_cmd *cmd, + bool sv, __u16 nvmsetid, + enum nvme_feat_plm_window_select wsel) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_PLM_WINDOW, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(nvmsetid, + NVME_FEAT_PLM_NVMSETID_SHIFT, + NVME_FEAT_PLM_NVMSETID_MASK); + cmd->cdw12 = NVME_FIELD_ENCODE(wsel, + NVME_FEAT_PLMW_WS_SHIFT, + NVME_FEAT_PLMW_WS_MASK); +} + +/** + * nvme_init_set_features_lba_sts_interval() - Initialize passthru command for + * LBA Status Information Interval + * @cmd: Passthru command to use + * @sv: Save value across power states + * @lsiri: LBA Status Information Report Interval + * @lsipi: LBA Status Information Poll Interval + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_LBA_STS_INTERVAL + */ +static inline void +nvme_init_set_features_lba_sts_interval(struct nvme_passthru_cmd *cmd, + bool sv, __u16 lsiri, __u16 lsipi) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_LBA_STS_INTERVAL, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(lsiri, + NVME_FEAT_LBAS_LSIRI_SHIFT, + NVME_FEAT_LBAS_LSIRI_MASK) | + NVME_FIELD_ENCODE(lsipi, + NVME_FEAT_LBAS_LSIPI_SHIFT, + NVME_FEAT_LBAS_LSIPI_MASK); +} + +/** + * nvme_init_set_features_host_behavior() - Initialize passthru command for + * Host Behavior + * @cmd: Passthru command to use + * @sv: Save value across power states + * @data: Pointer to structure nvme_feat_host_behavior + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_HOST_BEHAVIOR + */ +static inline void +nvme_init_set_features_host_behavior(struct nvme_passthru_cmd *cmd, + bool sv, struct nvme_feat_host_behavior *data) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_HOST_BEHAVIOR, sv); + cmd->data_len = sizeof(*data); + cmd->addr = (__u64)(uintptr_t)data; +} + +/** + * nvme_init_set_features_sanitize() - Initialize passthru command for + * Sanitize + * @cmd: Passthru command to use + * @sv: Save value across power states + * @nodrm: No-Deallocate Response Mode + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_SANITIZE + */ +static inline void +nvme_init_set_features_sanitize(struct nvme_passthru_cmd *cmd, + bool sv, bool nodrm) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_SANITIZE, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(nodrm, + NVME_FEAT_SANITIZE_NODRM_SHIFT, + NVME_FEAT_SANITIZE_NODRM_MASK); +} + +/** + * nvme_init_set_features_endurance_evt_cfg() - Initialize passthru command for + * Endurance Group Event Configuration + * @cmd: Passthru command to use + * @sv: Save value across power states + * @endgid: Endurance Group Identifier + * @egcw: Flags to enable warning, + * see &enum nvme_eg_critical_warning_flags + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_ENDURANCE_EVT_CFG + */ +static inline void +nvme_init_set_features_endurance_evt_cfg(struct nvme_passthru_cmd *cmd, + bool sv, __u16 endgid, __u8 egcw) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_ENDURANCE_EVT_CFG, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(endgid, + NVME_FEAT_EG_ENDGID_SHIFT, + NVME_FEAT_EG_ENDGID_MASK) | + NVME_FIELD_ENCODE(egcw, + NVME_FEAT_EG_EGCW_SHIFT, + NVME_FEAT_EG_EGCW_MASK); +} + +/** + * nvme_init_set_features_sw_progress() - Initialize passthru command for + * Software Pogress Marker + * @cmd: Passthru command to use + * @sv: Save value across power states + * @pbslc: Pre-boot Software Load Count + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_SW_PROGRESS + */ +static inline void +nvme_init_set_features_sw_progress(struct nvme_passthru_cmd *cmd, + bool sv, __u8 pbslc) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_SW_PROGRESS, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(pbslc, + NVME_FEAT_SPM_PBSLC_SHIFT, + NVME_FEAT_SPM_PBSLC_MASK); +} + +/** + * nvme_init_set_features_host_id() - Initialize passthru command for + * Host Identifier + * @cmd: Passthru command to use + * @sv: Save value across power states + * @exhid: Enable Extended Host Identifier + * @hostid: Host ID buffer to set + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_HOST_ID. + */ +static inline void +nvme_init_set_features_host_id(struct nvme_passthru_cmd *cmd, + bool sv, bool exhid, __u8 *hostid) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_HOST_ID, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(exhid, + NVME_FEAT_HOSTID_EXHID_SHIFT, + NVME_FEAT_HOSTID_EXHID_MASK); + cmd->data_len = exhid ? 16 : 8; + cmd->addr = (__u64)(uintptr_t)hostid; +} + +/** + * nvme_init_set_features_resv_mask() - Initialize passthru command for + * Reservation Notification Mask + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @sv: Save value across power states + * @mask: Reservation Notification Mask Field + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_RESV_MASK + */ +static inline void +nvme_init_set_features_resv_mask(struct nvme_passthru_cmd *cmd, __u32 nsid, + bool sv, __u32 mask) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_RESV_MASK, sv); + cmd->nsid = nsid; + cmd->cdw11 = mask; +} + +/** + * nvme_init_set_features_resv_persist() - Initialize passthru command for + * Reservation Persistence + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @sv: Save value across power states + * @ptpl: Persist Through Power Loss + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_RESV_PERSIST + */ +static inline void +nvme_init_set_features_resv_persist(struct nvme_passthru_cmd *cmd, __u32 nsid, + bool sv, bool ptpl) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_RESV_PERSIST, sv); + cmd->nsid = nsid; + cmd->cdw11 = NVME_FIELD_ENCODE(ptpl, + NVME_FEAT_RESP_PTPL_SHIFT, + NVME_FEAT_RESP_PTPL_MASK); +} + +/** + * nvme_init_set_features_write_protect() - Initialize passthru command for + * Write Protect + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @sv: Save value across power states + * @wps: Write Protection State + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_WRITE_PROTECT + */ +static inline void +nvme_init_set_features_write_protect(struct nvme_passthru_cmd *cmd, __u32 nsid, + bool sv, enum nvme_feat_nswpcfg_state wps) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_WRITE_PROTECT, sv); + cmd->nsid = nsid; + cmd->cdw11 = NVME_FIELD_ENCODE(wps, + NVME_FEAT_WP_WPS_SHIFT, + NVME_FEAT_WP_WPS_MASK); +} + +/** + * nvme_init_set_features_iocs_profile() - Initialize passthru command for + * I/O Command Set Profile + * @cmd: Passthru command to use + * @sv: Save value across power states + * @iocsci: I/O Command Set Combination Index + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_IOCS_PROFILE + */ +static inline void +nvme_init_set_features_iocs_profile(struct nvme_passthru_cmd *cmd, + bool sv, __u16 iocsci) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_IOCS_PROFILE, sv); + cmd->cdw11 = NVME_FIELD_ENCODE(iocsci, + NVME_FEAT_IOCSP_IOCSCI_SHIFT, + NVME_FEAT_IOCSP_IOCSCI_MASK); +} + +/** + * nvme_init_get_features() - Initialize passthru command for + * Get Features + * @cmd: Passthru command to use + * @fid: Feature identifier, see &enum nvme_features_id + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + */ +static inline void +nvme_init_get_features(struct nvme_passthru_cmd *cmd, __u8 fid, + enum nvme_get_features_sel sel) +{ + __u32 cdw10 = NVME_FIELD_ENCODE(fid, + NVME_GET_FEATURES_CDW10_FID_SHIFT, + NVME_GET_FEATURES_CDW10_FID_MASK) | + NVME_FIELD_ENCODE(sel, + NVME_GET_FEATURES_CDW10_SEL_SHIFT, + NVME_GET_FEATURES_CDW10_SEL_MASK); + + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_get_features; + cmd->cdw10 = cdw10; +} + +/** + * nvme_init_get_features_arbitration() - Initialize passthru command for + * Get Features - Arbitration + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_ARBITRATION + */ +static inline void +nvme_init_get_features_arbitration(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_ARBITRATION, sel); +} + +/** + * nvme_init_get_features_power_mgmt() - Initialize passthru command for + * Get Features - Power Management + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_POWER_MGMT + */ +static inline void +nvme_init_get_features_power_mgmt(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_POWER_MGMT, sel); +} + +/** + * nvme_init_get_features_lba_range() - Initialize passthru command for + * Get Features - LBA Range + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * @lrt: Buffer to receive LBA Range Type data structure + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_LBA_RANGE + */ +static inline void +nvme_init_get_features_lba_range(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_get_features_sel sel, struct nvme_lba_range_type *lrt) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_LBA_RANGE, sel); + cmd->nsid = nsid; + cmd->data_len = sizeof(*lrt); + cmd->addr = (__u64)(uintptr_t)lrt; +} + +/** + * nvme_init_get_features_temp_thresh() - Initialize passthru command for + * Get Features - Temperature Threshold + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * @tmpsel: Threshold Temperature Select + * @thsel: Threshold Type Select + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_TEMP_THRESH + */ +static inline void +nvme_init_get_features_temp_thresh(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel, + __u8 tmpsel, enum nvme_feat_tmpthresh_thsel thsel) +{ + + nvme_init_get_features(cmd, NVME_FEAT_FID_TEMP_THRESH, sel); + cmd->cdw11 = NVME_FIELD_ENCODE(tmpsel, + NVME_FEAT_TT_TMPSEL_SHIFT, + NVME_FEAT_TT_TMPSEL_MASK) | + NVME_FIELD_ENCODE(thsel, + NVME_FEAT_TT_THSEL_SHIFT, + NVME_FEAT_TT_THSEL_MASK); +} + +/** + * nvme_init_get_features_err_recovery() - Initialize passthru command for + * Get Features - Error Recovery + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_ERR_RECOVERY + */ +static inline void +nvme_init_get_features_err_recovery(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_ERR_RECOVERY, sel); + cmd->nsid = nsid; +} + +/** + * nvme_init_get_features_volatile_wc() - Initialize passthru command for + * Get Features - Volatile Write Cache + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_VOLATILE_WC + */ +static inline void +nvme_init_get_features_volatile_wc(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_VOLATILE_WC, sel); +} + +/** + * nvme_init_get_features_num_queues() - Initialize passthru command for + * Get Features - Number of Queues + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_NUM_QUEUES + */ +static inline void +nvme_init_get_features_num_queues(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_NUM_QUEUES, sel); +} + +/** + * nvme_init_get_features_irq_coalesce() - Initialize passthru command for + * Get Features - IRQ Coalesce + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_IRQ_COALESCE + */ +static inline void +nvme_init_get_features_irq_coalesce(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_IRQ_COALESCE, sel); +} + +/** + * nvme_init_get_features_irq_config() - Initialize passthru command for + * Get Features - IRQ Config + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * @iv: Interrupt Vector + * @cd: Coalescing Disable + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_IRQ_CONFIG + */ +static inline void +nvme_init_get_features_irq_config(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel, + __u16 iv, bool cd) +{ + __u32 cdw11 = NVME_FIELD_ENCODE(iv, + NVME_FEAT_ICFG_IV_SHIFT, + NVME_FEAT_ICFG_IV_MASK) | + NVME_FIELD_ENCODE(cd, + NVME_FEAT_ICFG_CD_SHIFT, + NVME_FEAT_ICFG_CD_MASK); + + nvme_init_get_features(cmd, NVME_FEAT_FID_IRQ_CONFIG, sel); + cmd->cdw11 = cdw11; +} + +/** + * nvme_init_get_features_write_atomic() - Initialize passthru command for + * Get Features - Write Atomic + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_WRITE_ATOMIC + */ +static inline void +nvme_init_get_features_write_atomic(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_WRITE_ATOMIC, sel); +} + +/** + * nvme_init_get_features_async_event() - Initialize passthru command for + * Get Features - Asynchronous Event Configuration + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_ASYNC_EVENT + */ +static inline void +nvme_init_get_features_async_event(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_ASYNC_EVENT, sel); +} + +/** + * nvme_init_get_features_auto_pst() - Initialize passthru command for + * Get Features - Autonomous Power State Transition + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * @apst: Autonomous Power State Transition data buffer + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_AUTO_PST + */ +static inline void +nvme_init_get_features_auto_pst(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel, struct nvme_feat_auto_pst *apst) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_AUTO_PST, sel); + cmd->data_len = sizeof(*apst); + cmd->addr = (__u64)(uintptr_t)apst; +} + +/** + * nvme_init_get_features_host_mem_buf() - Initialize passthru command for + * Get Features - Host Memory Buffer + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * @attrs: Buffer for returned Host Memory Buffer Attributes + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_HOST_MEM_BUF + */ +static inline void +nvme_init_get_features_host_mem_buf(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel, + struct nvme_host_mem_buf_attrs *attrs) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_HOST_MEM_BUF, sel); + cmd->data_len = sizeof(*attrs); + cmd->addr = (__u64)(uintptr_t)attrs; +} + +/** + * nvme_init_get_features_timestamp() - Initialize passthru command for + * Get Features - Timestamp + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * @ts: Current timestamp buffer + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_TIMESTAMP + */ +static inline void +nvme_init_get_features_timestamp(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel, struct nvme_timestamp *ts) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_TIMESTAMP, sel); + cmd->data_len = sizeof(*ts); + cmd->addr = (__u64)(uintptr_t)ts; +} + +/** + * nvme_init_get_features_kato() - Initialize passthru command for + * Get Features - Keep Alive Timeout + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_KATO + */ +static inline void +nvme_init_get_features_kato(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_KATO, sel); +} + +/** + * nvme_init_get_features_hctm() - Initialize passthru command for + * Get Features - Host Controlled Thermal Management + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_HCTM + */ +static inline void +nvme_init_get_features_hctm(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_HCTM, sel); +} + +/** + * nvme_init_get_features_nopsc() - Initialize passthru command for + * Get Features - Non-Operational Power State Config + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_NOPSC + */ +static inline void +nvme_init_get_features_nopsc(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_NOPSC, sel); +} + +/** + * nvme_init_get_features_rrl() - Initialize passthru command for + * Get Features - Read Recovery Level + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_RRL + */ +static inline void +nvme_init_get_features_rrl(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_RRL, sel); +} + +/** + * nvme_init_get_features_plm_config() - Initialize passthru command for + * Get Features - Predictable Latency Mode Config + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * @nvmsetid: NVM set id + * @plmc: Buffer for returned Predictable Latency Mode Config + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_PLM_CONFIG + */ +static inline void +nvme_init_get_features_plm_config(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel, __u16 nvmsetid, + struct nvme_plm_config *plmc) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_PLM_CONFIG, sel); + cmd->cdw11 = NVME_FIELD_ENCODE(nvmsetid, + NVME_FEAT_PLM_NVMSETID_SHIFT, + NVME_FEAT_PLM_NVMSETID_MASK); + cmd->data_len = sizeof(*plmc); + cmd->addr = (__u64)(uintptr_t)plmc; +} + +/** + * nvme_init_get_features_plm_window() - Initialize passthru command for + * Get Features - Predictable Latency Mode Window + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * @nvmsetid: NVM set id + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_PLM_WINDOW + */ +static inline void +nvme_init_get_features_plm_window(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel, __u16 nvmsetid) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_PLM_WINDOW, sel); + cmd->cdw11 = NVME_FIELD_ENCODE(nvmsetid, + NVME_FEAT_PLM_NVMSETID_SHIFT, + NVME_FEAT_PLM_NVMSETID_MASK); +} + +/** + * nvme_init_get_features_lba_sts_interval() - Initialize passthru command for + * Get Features - LBA Status Information Interval + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_LBA_STS_INTERVAL + */ +static inline void +nvme_init_get_features_lba_sts_interval(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_LBA_STS_INTERVAL, sel); +} + +/** + * nvme_init_get_features_host_behavior() - Initialize passthru command for + * Get Features - Host Behavior + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * @fhb: Pointer to structure nvme_feat_host_behavior + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_HOST_BEHAVIOR + */ +static inline void +nvme_init_get_features_host_behavior(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel, + struct nvme_feat_host_behavior *fhb) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_HOST_BEHAVIOR, sel); + cmd->data_len = sizeof(*fhb); + cmd->addr = (__u64)(uintptr_t)fhb; +} + +/** + * nvme_init_get_features_sanitize() - Initialize passthru command for + * Get Features - Sanitize + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_SANITIZE + */ +static inline void +nvme_init_get_features_sanitize(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_SANITIZE, sel); +} + +/** + * nvme_init_get_features_endurance_event_cfg() - Initialize passthru command + * for Get Features - Endurance Group Event Configuration + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * @endgid: Endurance Group Identifier + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_ENDURANCE_EVT_CFG + */ +static inline void +nvme_init_get_features_endurance_event_cfg(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel, __u16 endgid) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_ENDURANCE_EVT_CFG, sel); + cmd->cdw11 = NVME_FIELD_ENCODE(endgid, + NVME_FEAT_EG_ENDGID_SHIFT, + NVME_FEAT_EG_ENDGID_MASK); +} + +/** + * nvme_init_get_features_sw_progress() - Initialize passthru command for + * Get Features - Software Progress + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_SW_PROGRESS + */ +static inline void +nvme_init_get_features_sw_progress(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_SW_PROGRESS, sel); +} + +/** + * nvme_init_get_features_host_id() - Initialize passthru command for + * Get Features - Host Identifier + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * @exhid: Enable Extended Host Identifier + * @hostid: Buffer for returned host ID + * @len: Length of @hostid + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_HOST_ID + */ +static inline void +nvme_init_get_features_host_id(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel, bool exhid, + void *hostid, __u32 len) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_HOST_ID, sel); + cmd->cdw11 = NVME_FIELD_ENCODE(exhid, + NVME_FEAT_HOSTID_EXHID_SHIFT, + NVME_FEAT_HOSTID_EXHID_MASK); + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)hostid; +} + +/** + * nvme_init_get_features_resv_mask() - Initialize passthru command for + * Get Features - Reservation Notification Mask + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_RESV_MASK + */ +static inline void +nvme_init_get_features_resv_mask(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_RESV_MASK, sel); + cmd->nsid = nsid; +} + +/** + * nvme_init_get_features_resv_persist() - Initialize passthru command for + * Get Features - Reservation Persistence + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_RESV_PERSIST + */ +static inline void +nvme_init_get_features_resv_persist(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_RESV_PERSIST, sel); + cmd->nsid = nsid; +} + +/** + * nvme_init_get_features_write_protect() - Initialize passthru command for + * Get Features - Write Protect + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_WRITE_PROTECT + */ +static inline void +nvme_init_get_features_write_protect(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_WRITE_PROTECT, sel); + cmd->nsid = nsid; +} + +/** + * nvme_init_get_features_iocs_profile() - Initialize passthru command for + * Get Features - I/O Command Set Profile + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_IOCS_PROFILE + */ +static inline void +nvme_init_get_features_iocs_profile(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_IOCS_PROFILE, sel); +} + +/** + * nvme_init_format_nvm() - Initialize passthru command for Format NVM + * @cmd: Passthru command to use + * @nsid: Namespace ID to format + * @lbaf: Logical block address format + * @mset: Metadata settings (extended or separated) + * @pi: Protection information type + * @pil: Protection information location (beginning or end) + * @ses: Secure erase settings + * + * Initializes the passthru command buffer for the Format NVM command. + */ +static inline void +nvme_init_format_nvm(struct nvme_passthru_cmd *cmd, __u32 nsid, __u8 lbaf, + enum nvme_cmd_format_mset mset, enum nvme_cmd_format_pi pi, + enum nvme_cmd_format_pil pil, enum nvme_cmd_format_ses ses) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_format_nvm; + cmd->nsid = nsid; + cmd->cdw10 = NVME_FIELD_ENCODE(lbaf, + NVME_FORMAT_CDW10_LBAFL_SHIFT, + NVME_FORMAT_CDW10_LBAFL_MASK) | + NVME_FIELD_ENCODE(mset, + NVME_FORMAT_CDW10_MSET_SHIFT, + NVME_FORMAT_CDW10_MSET_MASK) | + NVME_FIELD_ENCODE(pi, + NVME_FORMAT_CDW10_PI_SHIFT, + NVME_FORMAT_CDW10_PI_MASK) | + NVME_FIELD_ENCODE(pil, + NVME_FORMAT_CDW10_PIL_SHIFT, + NVME_FORMAT_CDW10_PIL_MASK) | + NVME_FIELD_ENCODE(ses, + NVME_FORMAT_CDW10_SES_SHIFT, + NVME_FORMAT_CDW10_SES_MASK) | + NVME_FIELD_ENCODE((lbaf >> 4), + NVME_FORMAT_CDW10_LBAFU_SHIFT, + NVME_FORMAT_CDW10_LBAFU_MASK); +} + +/** + * nvme_init_ns_mgmt() - Initialize passthru command for Namespace Management + * @cmd: Passthru command to use + * @nsid: Namespace identifier + * @sel: Type of management operation to perform + * @csi: Command Set Identifier + * @data: Host Software Specified Fields buffer + * + * Initializes the passthru command buffer for the Namespace Management command. + */ +static inline void +nvme_init_ns_mgmt(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_ns_mgmt_sel sel, __u8 csi, + struct nvme_ns_mgmt_host_sw_specified *data) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_ns_mgmt; + cmd->nsid = nsid; + cmd->data_len = data ? sizeof(*data) : 0; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = NVME_FIELD_ENCODE(sel, + NVME_NAMESPACE_MGMT_CDW10_SEL_SHIFT, + NVME_NAMESPACE_MGMT_CDW10_SEL_MASK); + cmd->cdw11 = NVME_FIELD_ENCODE(csi, + NVME_NAMESPACE_MGMT_CDW11_CSI_SHIFT, + NVME_NAMESPACE_MGMT_CDW11_CSI_MASK); +} + +/** + * nvme_init_ns_mgmt_create() - Initialize passthru command to create a + * non attached namespace + * @cmd: Passthru command to use + * @csi: Command Set Identifier + * @data: Host Software Specified Fields buffer that defines NS + * creation parameters + * + * Initializes the passthru command buffer for the Namespace Management - Create + * command. The command uses NVME_NSID_NONE as the target NSID. + */ +static inline void +nvme_init_ns_mgmt_create(struct nvme_passthru_cmd *cmd, __u8 csi, + struct nvme_ns_mgmt_host_sw_specified *data) +{ + nvme_init_ns_mgmt(cmd, NVME_NSID_NONE, NVME_NS_MGMT_SEL_CREATE, + csi, data); +} + +/** + * nvme_init_ns_mgmt_delete() - Initialize passthru command to delete a + * non attached namespace + * @cmd: Passthru command to use + * @nsid: Namespace identifier to delete + * + * Initializes the passthru command buffer for the Namespace Management - Delete + * command (NVME_NS_MGMT_SEL_DELETE). The command uses the provided @nsid as + * the target NSID. + */ +static inline void +nvme_init_ns_mgmt_delete(struct nvme_passthru_cmd *cmd, __u32 nsid) +{ + nvme_init_ns_mgmt(cmd, nsid, NVME_NS_MGMT_SEL_DELETE, + NVME_CSI_NVM, NULL); +} + +/** + * nvme_init_ns_attach() - Initialize passthru command for + * Namespace Attach/Detach + * @cmd: Passthru command to use + * @nsid: Namespace ID to execute attach selection + * @sel: Attachment selection, see &enum nvme_ns_attach_sel + * @ctrlist: Controller list buffer to modify attachment state of nsid + * + * Initializes the passthru command buffer for the Namespace Attach/Detach + * command. + */ +static inline void +nvme_init_ns_attach(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_ns_attach_sel sel, struct nvme_ctrl_list *ctrlist) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_ns_attach; + cmd->nsid = nsid; + cmd->data_len = sizeof(*ctrlist); + cmd->addr = (__u64)(uintptr_t)ctrlist; + cmd->cdw10 = NVME_FIELD_ENCODE(sel, + NVME_NAMESPACE_ATTACH_CDW10_SEL_SHIFT, + NVME_NAMESPACE_ATTACH_CDW10_SEL_MASK); +} + +/** + * nvme_init_ns_attach_ctrls() - Initialize passthru command to attach + * namespace to controllers + * @cmd: Passthru command to use + * @nsid: Namespace ID to attach + * @ctrlist: Controller list buffer to modify attachment state of nsid + * + * Initializes the passthru command buffer for the Namespace Attach command + * (NVME_NS_ATTACH_SEL_CTRL_ATTACH). + */ +static inline void +nvme_init_ns_attach_ctrls(struct nvme_passthru_cmd *cmd, __u32 nsid, + struct nvme_ctrl_list *ctrlist) +{ + nvme_init_ns_attach(cmd, nsid, NVME_NS_ATTACH_SEL_CTRL_ATTACH, + ctrlist); +} + +/** + * nvme_init_ns_detach_ctrls() - Initialize passthru command to detach + * namespace from controllers + * @cmd: Passthru command to use + * @nsid: Namespace ID to detach + * @ctrlist: Controller list buffer to modify attachment state of nsid + * + * Initializes the passthru command buffer for the Namespace Detach command + * (NVME_NS_ATTACH_SEL_CTRL_DEATTACH). + */ +static inline void +nvme_init_ns_detach_ctrls(struct nvme_passthru_cmd *cmd, __u32 nsid, + struct nvme_ctrl_list *ctrlist) +{ + nvme_init_ns_attach(cmd, nsid, NVME_NS_ATTACH_SEL_CTRL_DEATTACH, + ctrlist); +} + +/** + * nvme_init_fw_download() - Initialize passthru command to download part or + * all of a firmware image to the controller + * @cmd: Passthru command to use + * @data: Userspace address of the firmware data buffer + * @len: Length of data in this command in bytes + * @offset: Offset in the firmware data + * + * Initializes the passthru command buffer for the Firmware Image + * Download command. + * + * Note: Caller must ensure data_len and offset are DWord-aligned (0x4). + * + * Returns: 0 on success, or error code if arguments are invalid. + */ +static inline int +nvme_init_fw_download(struct nvme_passthru_cmd *cmd, void *data, + __u32 len, __u32 offset) +{ + if (len & 0x3 || !len) + return -EINVAL; + + if (offset & 0x3) + return -EINVAL; + + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_fw_download; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = (len >> 2) - 1; + cmd->cdw11 = offset >> 2; + + return 0; +} + +/** + * nvme_init_fw_commit() - Initialize passthru command to commit firmware + * using the specified action + * @cmd: Passthru command to use + * @fs: Firmware slot to commit the downloaded image + * @ca: Action to use for the firmware image, + * see &enum nvme_fw_commit_ca + * @bpid: Set to true to select the boot partition id + * + * Initializes the passthru command buffer for the Firmware Commit command. + */ +static inline void +nvme_init_fw_commit(struct nvme_passthru_cmd *cmd, __u8 fs, + enum nvme_fw_commit_ca ca, bool bpid) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_fw_commit; + cmd->cdw10 = NVME_FIELD_ENCODE(fs, + NVME_FW_COMMIT_CDW10_FS_SHIFT, + NVME_FW_COMMIT_CDW10_FS_MASK) | + NVME_FIELD_ENCODE(ca, + NVME_FW_COMMIT_CDW10_CA_SHIFT, + NVME_FW_COMMIT_CDW10_CA_MASK) | + NVME_FIELD_ENCODE(bpid, + NVME_FW_COMMIT_CDW10_BPID_SHIFT, + NVME_FW_COMMIT_CDW10_BPID_MASK); +} + +/** + * nvme_init_security_send() - Initialize passthru command for Security Send + * @cmd: Passthru command to use + * @nsid: Namespace ID to issue security command on + * @nssf: NVMe Security Specific field + * @spsp: Security Protocol Specific field + * @secp: Security Protocol + * @tl: Protocol specific transfer length + * @data: Security data payload buffer to send + * @len: Data length of the payload in bytes + * + * Initializes the passthru command buffer for the Security Send command. + */ +static inline void +nvme_init_security_send(struct nvme_passthru_cmd *cmd, __u32 nsid, __u8 nssf, + __u16 spsp, __u8 secp, __u32 tl, void *data, __u32 len) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_security_send; + cmd->nsid = nsid; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = NVME_FIELD_ENCODE(secp, + NVME_SECURITY_SECP_SHIFT, + NVME_SECURITY_SECP_MASK) | + NVME_FIELD_ENCODE(spsp, + NVME_SECURITY_SPSP0_SHIFT, + NVME_SECURITY_SPSP0_MASK) | + NVME_FIELD_ENCODE(spsp >> 8, + NVME_SECURITY_SPSP1_SHIFT, + NVME_SECURITY_SPSP1_MASK) | + NVME_FIELD_ENCODE(nssf, + NVME_SECURITY_NSSF_SHIFT, + NVME_SECURITY_NSSF_MASK); + cmd->cdw11 = tl; +} + +/** + * nvme_init_security_receive() - Initialize passthru command for + * Security Receive + * @cmd: Passthru command to use + * @nsid: Namespace ID to issue security command on + * @nssf: NVMe Security Specific field + * @spsp: Security Protocol Specific field + * @secp: Security Protocol + * @al: Protocol specific allocation length + * @data: Security data payload buffer to receive data into + * @len: Data length of the payload in bytes (must match @al) + * + * Initializes the passthru command buffer for the Security Receive command. + */ +static inline void +nvme_init_security_receive(struct nvme_passthru_cmd *cmd, __u32 nsid, __u8 nssf, + __u16 spsp, __u8 secp, __u32 al, void *data, __u32 len) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_security_recv; + cmd->nsid = nsid; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = NVME_FIELD_ENCODE(secp, + NVME_SECURITY_SECP_SHIFT, + NVME_SECURITY_SECP_MASK) | + NVME_FIELD_ENCODE(spsp, + NVME_SECURITY_SPSP0_SHIFT, + NVME_SECURITY_SPSP0_MASK) | + NVME_FIELD_ENCODE(spsp >> 8, + NVME_SECURITY_SPSP1_SHIFT, + NVME_SECURITY_SPSP1_MASK) | + NVME_FIELD_ENCODE(nssf, + NVME_SECURITY_NSSF_SHIFT, + NVME_SECURITY_NSSF_MASK); + cmd->cdw11 = al; +} + +/** + * nvme_init_get_lba_status() - Initialize passthru command to retrieve + * information on possibly unrecoverable LBAs + * @cmd: Passthru command to use + * @nsid: Namespace ID to retrieve LBA status + * @slba: Starting logical block address to check statuses + * @mndw: Maximum number of dwords to return + * @atype: Action type mechanism to determine LBA status descriptors to + * return, see &enum nvme_lba_status_atype + * @rl: Range length from slba to perform the action + * @lbas: Data payload buffer to return status descriptors + * + * Initializes the passthru command buffer for the Get LBA Status command. + */ +static inline void +nvme_init_get_lba_status(struct nvme_passthru_cmd *cmd, __u32 nsid, __u64 slba, + __u32 mndw, enum nvme_lba_status_atype atype, __u16 rl, + struct nvme_lba_status *lbas) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_get_lba_status; + cmd->nsid = nsid; + cmd->data_len = (mndw + 1) << 2; + cmd->addr = (__u64)(uintptr_t)lbas; + cmd->cdw10 = slba & 0xffffffff; + cmd->cdw11 = slba >> 32; + cmd->cdw12 = mndw; + cmd->cdw13 = NVME_FIELD_ENCODE(rl, + NVME_GET_LBA_STATUS_CDW13_RL_SHIFT, + NVME_GET_LBA_STATUS_CDW13_RL_MASK) | + NVME_FIELD_ENCODE(atype, + NVME_GET_LBA_STATUS_CDW13_ATYPE_SHIFT, + NVME_GET_LBA_STATUS_CDW13_ATYPE_MASK); +} + +/** + * nvme_init_directive_send() - Initialize passthru command for Directive Send + * @cmd: Passthru command to use + * @nsid: Namespace ID, if applicable + * @doper: Directive send operation, see &enum nvme_directive_send_doper + * @dtype: Directive type, see &enum nvme_directive_dtype + * @dspec: Directive specific field + * @data: Data payload buffer to be send + * @len: Length of data payload in bytes + * + * Initializes the passthru command buffer for the Directive Send command. + */ +static inline void +nvme_init_directive_send(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_directive_send_doper doper, + enum nvme_directive_dtype dtype, __u16 dspec, + void *data, __u32 len) +{ + + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_directive_send; + cmd->nsid = nsid; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = len ? (len >> 2) - 1 : 0; + cmd->cdw11 = NVME_FIELD_ENCODE(doper, + NVME_DIRECTIVE_CDW11_DOPER_SHIFT, + NVME_DIRECTIVE_CDW11_DOPER_MASK) | + NVME_FIELD_ENCODE(dtype, + NVME_DIRECTIVE_CDW11_DTYPE_SHIFT, + NVME_DIRECTIVE_CDW11_DTYPE_MASK) | + NVME_FIELD_ENCODE(dspec, + NVME_DIRECTIVE_CDW11_DPSEC_SHIFT, + NVME_DIRECTIVE_CDW11_DPSEC_MASK); +} + +/** + * nvme_init_directive_send_id_endir() - Initialize passthru command for + * Directive Send Enable Directive + * @cmd: Passthru command to use + * @nsid: Namespace Identifier + * @endir: Enable Directive + * @dtype: Directive Type + * @id: Pointer to structure nvme_id_directives + * + * Initializes the passthru command buffer for the Directive Send - Identify + * (Enable Directive) command. + */ +static inline void +nvme_init_directive_send_id_endir(struct nvme_passthru_cmd *cmd, __u32 nsid, + bool endir, enum nvme_directive_dtype dtype, + struct nvme_id_directives *id) +{ + nvme_init_directive_send(cmd, nsid, + NVME_DIRECTIVE_SEND_IDENTIFY_DOPER_ENDIR, + NVME_DIRECTIVE_DTYPE_IDENTIFY, 0, id, sizeof(*id)); + cmd->cdw12 = NVME_FIELD_ENCODE(dtype, + NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_DTYPE_SHIFT, + NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_DTYPE_MASK) | + NVME_FIELD_ENCODE(endir, + NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_ENDIR_SHIFT, + NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_ENDIR_MASK); +} + +/** + * nvme_init_directive_send_stream_release_identifier() - Initialize passthru + * command for Directive Send Stream release identifier + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @stream_id: Stream identifier + * + * Initializes the passthru command buffer for the Directive Send - Stream + * Release Identifier command. + */ +static inline void +nvme_init_directive_send_stream_release_identifier( + struct nvme_passthru_cmd *cmd, + __u32 nsid, __u16 stream_id) +{ + nvme_init_directive_send(cmd, nsid, + NVME_DIRECTIVE_SEND_STREAMS_DOPER_RELEASE_IDENTIFIER, + NVME_DIRECTIVE_DTYPE_STREAMS, stream_id, NULL, 0); +} + +/** + * nvme_init_directive_send_stream_release_resource() - Initialize passthru + * command for Directive Send Stream release resources + * @cmd: Passthru command to use + * @nsid: Namespace ID + * + * Initializes the passthru command buffer for the Directive Send - Stream + * Release Resource command. + */ +static inline void +nvme_init_directive_send_stream_release_resource(struct nvme_passthru_cmd *cmd, + __u32 nsid) +{ + nvme_init_directive_send(cmd, nsid, + NVME_DIRECTIVE_SEND_STREAMS_DOPER_RELEASE_RESOURCE, + NVME_DIRECTIVE_DTYPE_STREAMS, 0, NULL, 0); +} + +/** + * nvme_init_directive_recv() - Initialize passthru command for + * Directive Receive + * @cmd: Passthru command to use + * @nsid: Namespace ID, if applicable + * @doper: Directive receive operation, + * see &enum nvme_directive_receive_doper + * @dtype: Directive type, see &enum nvme_directive_dtype + * @dspec: Directive specific field + * @data: Userspace address of data payload buffer + * @len: Length of data payload in bytes + * + * Initializes the passthru command buffer for the Directive Receive command. + */ +static inline void +nvme_init_directive_recv(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_directive_receive_doper doper, + enum nvme_directive_dtype dtype, __u16 dspec, + void *data, __u32 len) +{ + + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_directive_recv; + cmd->nsid = nsid; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = len ? (len >> 2) - 1 : 0; + cmd->cdw11 = NVME_FIELD_ENCODE(doper, + NVME_DIRECTIVE_CDW11_DOPER_SHIFT, + NVME_DIRECTIVE_CDW11_DOPER_MASK) | + NVME_FIELD_ENCODE(dtype, + NVME_DIRECTIVE_CDW11_DTYPE_SHIFT, + NVME_DIRECTIVE_CDW11_DTYPE_MASK) | + NVME_FIELD_ENCODE(dspec, + NVME_DIRECTIVE_CDW11_DPSEC_SHIFT, + NVME_DIRECTIVE_CDW11_DPSEC_MASK); +} + +/** + * nvme_init_directive_recv_identify_parameters() - Initialize passthru command + * for Directive Receive Identify Parameters + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @id: Identify parameters buffer + * + * Initializes the passthru command buffer for the Directive Receive - Identify + * Parameters command. + */ +static inline void +nvme_init_directive_recv_identify_parameters(struct nvme_passthru_cmd *cmd, + __u32 nsid, struct nvme_id_directives *id) +{ + nvme_init_directive_recv(cmd, nsid, + NVME_DIRECTIVE_RECEIVE_IDENTIFY_DOPER_PARAM, + NVME_DIRECTIVE_DTYPE_IDENTIFY, 0, id, sizeof(*id)); +} + +/** + * nvme_init_directive_recv_stream_parameters() - Initialize passthru command + * for Directive Receive Stream Parameters + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @parms: Streams directive parameters buffer + * + * Initializes the passthru command buffer for the Directive Receive - Stream + * Parameters command. + */ +static inline void +nvme_init_directive_recv_stream_parameters(struct nvme_passthru_cmd *cmd, + __u32 nsid, struct nvme_streams_directive_params *parms) +{ + nvme_init_directive_recv(cmd, nsid, + NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_PARAM, + NVME_DIRECTIVE_DTYPE_STREAMS, 0, parms, sizeof(*parms)); +} + +/** + * nvme_init_directive_recv_stream_status() - Initialize passthru command for + * Directive Receive Stream Status + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @nr_entries: Number of streams to receive + * @id: Stream status buffer + * + * Initializes the passthru command buffer for the Directive Receive - Stream + * Status command. + * + * Return: 0 on success, or error code if arguments are invalid. + */ +static inline int +nvme_init_directive_recv_stream_status(struct nvme_passthru_cmd *cmd, + __u32 nsid, unsigned int nr_entries, + struct nvme_streams_directive_status *id) +{ + if (nr_entries > NVME_STREAM_ID_MAX) + return -EINVAL; + + nvme_init_directive_recv(cmd, nsid, + NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_STATUS, + NVME_DIRECTIVE_DTYPE_STREAMS, 0, id, + (__u32)(sizeof(*id) + nr_entries * sizeof(__le16))); + + return 0; +} + +/** + * nvme_init_directive_recv_stream_allocate() - Initialize passthru command for + * Directive Receive Stream Allocate + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @nsr: Namespace Streams Requested + * + * Initializes the passthru command buffer for the Directive Receive - Stream + * Allocate command. + */ +static inline void +nvme_init_directive_recv_stream_allocate(struct nvme_passthru_cmd *cmd, + __u32 nsid, __u16 nsr) +{ + nvme_init_directive_recv(cmd, nsid, + NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_RESOURCE, + NVME_DIRECTIVE_DTYPE_STREAMS, 0, NULL, 0); + cmd->cdw12 = nsr; +} + +/** + * nvme_init_capacity_mgmt() - Initialize passthru command for + * Capacity Management + * @cmd: Passthru command to use + * @oper: Operation to be performed by the controller + * @elid: Value specific to the value of the Operation field + * @cap: Capacity in bytes of the Endurance Group or NVM Set to + * be created + * + * Initializes the passthru command buffer for the Capacity Management command. + */ +static inline void +nvme_init_capacity_mgmt(struct nvme_passthru_cmd *cmd, + __u8 oper, __u16 elid, __u64 cap) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_capacity_mgmt; + cmd->cdw10 = NVME_FIELD_ENCODE(oper, + NVME_CAPACITY_MGMT_CDW10_OPER_SHIFT, + NVME_CAPACITY_MGMT_CDW10_OPER_MASK) | + NVME_FIELD_ENCODE(elid, + NVME_CAPACITY_MGMT_CDW10_ELID_SHIFT, + NVME_CAPACITY_MGMT_CDW10_ELID_MASK); + cmd->cdw11 = NVME_FIELD_ENCODE(cap, + NVME_CAPACITY_MGMT_CDW11_CAPL_SHIFT, + NVME_CAPACITY_MGMT_CDW11_CAPL_MASK); + cmd->cdw12 = NVME_FIELD_ENCODE(cap >> 32, + NVME_CAPACITY_MGMT_CDW12_CAPU_SHIFT, + NVME_CAPACITY_MGMT_CDW12_CAPU_MASK); +} + + /** + * nvme_init_lockdown() - Initialize passthru command for Lockdown + * @cmd: Passthru command to use + * @scp: Scope of the command + * @prhbt: Prohibit or allow the command opcode or Set Features command + * @ifc: Affected interface + * @ofi: Opcode or Feature Identifier + * @uidx: UUID Index if controller supports this id selection method + * + * Initializes the passthru command buffer for the Lockdown command. + */ +static inline void +nvme_init_lockdown(struct nvme_passthru_cmd *cmd, __u8 scp, __u8 prhbt, + __u8 ifc, __u8 ofi, __u8 uidx) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_lockdown; + cmd->cdw10 = NVME_FIELD_ENCODE(ofi, + NVME_LOCKDOWN_CDW10_OFI_SHIFT, + NVME_LOCKDOWN_CDW10_OFI_MASK) | + NVME_FIELD_ENCODE(ifc, + NVME_LOCKDOWN_CDW10_IFC_SHIFT, + NVME_LOCKDOWN_CDW10_IFC_MASK) | + NVME_FIELD_ENCODE(prhbt, + NVME_LOCKDOWN_CDW10_PRHBT_SHIFT, + NVME_LOCKDOWN_CDW10_PRHBT_MASK) | + NVME_FIELD_ENCODE(scp, + NVME_LOCKDOWN_CDW10_SCP_SHIFT, + NVME_LOCKDOWN_CDW10_SCP_MASK); + cmd->cdw14 = NVME_FIELD_ENCODE(uidx, + NVME_LOCKDOWN_CDW14_UIDX_SHIFT, + NVME_LOCKDOWN_CDW14_UIDX_MASK); +} + +/** + * nvme_init_set_property() - Initialize passthru command to set + * controller property + * @cmd: Passthru command to use + * @offset: Property offset from the base to set + * @value: The value to set the property + * + * Initializes the passthru command buffer for the Fabrics Set Property command. + * This is an NVMe-over-Fabrics specific command. + */ +static inline void +nvme_init_set_property(struct nvme_passthru_cmd *cmd, __u32 offset, __u64 value) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_fabrics; + cmd->nsid = nvme_fabrics_type_property_set; + cmd->cdw10 = nvme_is_64bit_reg(offset); + cmd->cdw11 = (__u32)offset; + cmd->cdw12 = (__u32)(value & 0xffffffff); + cmd->cdw13 = (__u32)(value >> 32); +} + +/** + * nvme_init_get_property() - Initialize passthru command to get + * a controller property + * @cmd: Passthru command to use + * @offset: Property offset from the base to retrieve + * + * Initializes the passthru command buffer for the Fabrics Get Property command. + * This is an NVMe-over-Fabrics specific command. + */ +static inline void +nvme_init_get_property(struct nvme_passthru_cmd *cmd, __u32 offset) +{ + + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_fabrics; + cmd->nsid = nvme_fabrics_type_property_get; + cmd->cdw10 = nvme_is_64bit_reg(offset); + cmd->cdw11 = (__u32)offset; +} + +/** + * nvme_init_sanitize_nvm() - Initialize passthru command to start a + * sanitize operation + * @cmd: Passthru command to use + * @sanact: Sanitize action, see &enum nvme_sanitize_sanact + * @ause: Set to allow unrestricted sanitize exit + * @owpass: Overwrite pass count + * @oipbp: Set to overwrite invert pattern between passes + * @ndas: Set to not deallocate blocks after sanitizing + * @emvs: Set to enter media verification state + * @ovrpat: Overwrite pattern + * + * Initializes the passthru command buffer for the Sanitize NVM command. + */ +static inline void +nvme_init_sanitize_nvm(struct nvme_passthru_cmd *cmd, + enum nvme_sanitize_sanact sanact, bool ause, __u8 owpass, + bool oipbp, bool ndas, bool emvs, __u32 ovrpat) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_sanitize_nvm; + cmd->cdw10 = NVME_FIELD_ENCODE(sanact, + NVME_SANITIZE_CDW10_SANACT_SHIFT, + NVME_SANITIZE_CDW10_SANACT_MASK) | + NVME_FIELD_ENCODE(ause, + NVME_SANITIZE_CDW10_AUSE_SHIFT, + NVME_SANITIZE_CDW10_AUSE_MASK) | + NVME_FIELD_ENCODE(owpass, + NVME_SANITIZE_CDW10_OWPASS_SHIFT, + NVME_SANITIZE_CDW10_OWPASS_MASK) | + NVME_FIELD_ENCODE(oipbp, + NVME_SANITIZE_CDW10_OIPBP_SHIFT, + NVME_SANITIZE_CDW10_OIPBP_MASK) | + NVME_FIELD_ENCODE(ndas, + NVME_SANITIZE_CDW10_NDAS_SHIFT, + NVME_SANITIZE_CDW10_NDAS_MASK) | + NVME_FIELD_ENCODE(emvs, + NVME_SANITIZE_CDW10_EMVS_SHIFT, + NVME_SANITIZE_CDW10_EMVS_MASK); + cmd->cdw11 = ovrpat; +} + +/** + * nvme_init_sanitize_ns() - Initialize passthru command to start a + * sanitize namespace operation + * @cmd: Passthru command to use + * @sanact: Sanitize action, see &enum nvme_sanitize_sanact + * @ause: Set to allow unrestricted sanitize exit + * @emvs: Set to enter media verification state + * + * Initializes the passthru command buffer for the Sanitize namespace command. + */ +static inline void +nvme_init_sanitize_ns(struct nvme_passthru_cmd *cmd, + enum nvme_sanitize_sanact sanact, bool ause, bool emvs) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_sanitize_ns; + cmd->cdw10 = NVME_FIELD_ENCODE(sanact, + NVME_SANITIZE_CDW10_SANACT_SHIFT, + NVME_SANITIZE_CDW10_SANACT_MASK) | + NVME_FIELD_ENCODE(ause, + NVME_SANITIZE_CDW10_AUSE_SHIFT, + NVME_SANITIZE_CDW10_AUSE_MASK) | + NVME_FIELD_ENCODE(emvs, + NVME_SANITIZE_CDW10_EMVS_SHIFT, + NVME_SANITIZE_CDW10_EMVS_MASK); +} + +/** + * nvme_init_dev_self_test() - Initialize passthru command to start or + * abort a self test + * @cmd: Passthru command to use + * @nsid: Namespace ID to test + * @stc: Self test code, see &enum nvme_dst_stc + * + * Initializes the passthru command buffer for the Device Self-test command. + */ +static inline void +nvme_init_dev_self_test(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_dst_stc stc) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_dev_self_test; + cmd->nsid = nsid; + cmd->cdw10 = NVME_FIELD_ENCODE(stc, + NVME_DEVICE_SELF_TEST_CDW10_STC_SHIFT, + NVME_DEVICE_SELF_TEST_CDW10_STC_MASK); +} + +/** + * nvme_init_virtual_mgmt() - Initialize passthru command for + * Virtualization Resource Management + * @cmd: Passthru command to use + * @act: Virtual resource action, see &enum nvme_virt_mgmt_act + * @rt: Resource type to modify, see &enum nvme_virt_mgmt_rt + * @cntlid: Controller id for which resources are bing modified + * @nr: Number of resources being allocated or assigned + * + * Initializes the passthru command buffer for the Virtualization + * Management command. + */ +static inline void +nvme_init_virtual_mgmt(struct nvme_passthru_cmd *cmd, + enum nvme_virt_mgmt_act act, enum nvme_virt_mgmt_rt rt, + __u16 cntlid, __u16 nr) +{ + memset(cmd, 0, sizeof(*cmd)); + cmd->opcode = nvme_admin_virtual_mgmt; + cmd->cdw10 = NVME_FIELD_ENCODE(act, + NVME_VIRT_MGMT_CDW10_ACT_SHIFT, + NVME_VIRT_MGMT_CDW10_ACT_MASK) | + NVME_FIELD_ENCODE(rt, + NVME_VIRT_MGMT_CDW10_RT_SHIFT, + NVME_VIRT_MGMT_CDW10_RT_MASK) | + NVME_FIELD_ENCODE(cntlid, + NVME_VIRT_MGMT_CDW10_CNTLID_SHIFT, + NVME_VIRT_MGMT_CDW10_CNTLID_MASK); + cmd->cdw11 = NVME_FIELD_ENCODE(nr, + NVME_VIRT_MGMT_CDW11_NR_SHIFT, + NVME_VIRT_MGMT_CDW11_NR_MASK); +} + +/** + * nvme_flush() - Send an nvme flush command + * @hdl: Transport handle + * @nsid: Namespace identifier + * + * The Flush command requests that the contents of volatile write cache be made + * non-volatile. + * + * 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_flush(struct nvme_transport_handle *hdl, __u32 nsid) +{ + struct nvme_passthru_cmd cmd = {}; + + cmd.opcode = nvme_cmd_flush; + cmd.nsid = nsid; + + return nvme_submit_io_passthru(hdl, &cmd); +} + +/** + * nvme_init_dsm() - Initialize passthru command for + * NVMEe I/O Data Set Management + * @cmd: Passthru command to use + * @nsid: Namespace identifier + * @nr: Number of block ranges in the data set management attributes + * @idr: DSM Integral Dataset for Read attribute + * @idw: DSM Integral Dataset for Write attribute + * @ad: DSM Deallocate attribute + * @data: User space destination address to transfer the data + * @len: Length of provided user buffer to hold the log data in bytes + */ +static inline void +nvme_init_dsm(struct nvme_passthru_cmd *cmd, + __u32 nsid, __u16 nr, __u8 idr, __u8 idw, __u8 ad, void *data, + __u32 len) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_cmd_dsm; + cmd->nsid = nsid; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = NVME_FIELD_ENCODE(nr - 1, + NVME_DSM_CDW10_NR_SHIFT, + NVME_DSM_CDW10_NR_MASK); + cmd->cdw11 = NVME_FIELD_ENCODE(idr, + NVME_DSM_CDW11_IDR_SHIFT, + NVME_DSM_CDW11_IDR_MASK) | + NVME_FIELD_ENCODE(idw, + NVME_DSM_CDW11_IDW_SHIFT, + NVME_DSM_CDW11_IDW_MASK) | + NVME_FIELD_ENCODE(ad, + NVME_DSM_CDW11_AD_SHIFT, + NVME_DSM_CDW11_AD_MASK); +} + +/** + * nvme_init_var_size_tags() - Initialize Command Dword fields + * for Extended LBA based on Variable Sized Tags + * @cmd: Passthru command to use + * @pif: Protection information format, determines tag placement + * @sts: Storage tag size in bits + * @reftag: Expected Initial Logical Block Reference Tag (EILBRT) + * @storage_tag: Expected Logical Block Storage Tag (ELBST) + * + * Initializes the passthru command buffer fields cdw2, cdw3, and cdw14 + * for commands supporting Extended LBA. This logic is usually called from + * the command-specific init function (like nvme_init_zns_append). + */ +static inline int +nvme_init_var_size_tags(struct nvme_passthru_cmd *cmd, + __u8 pif, __u8 sts, __u64 reftag, __u64 storage_tag) +{ + __u32 cdw2 = 0, cdw3 = 0, cdw14 = 0; + + switch (pif) { + case NVME_NVM_PIF_16B_GUARD: + cdw14 = NVME_FIELD_ENCODE(reftag, + NVME_IOCS_COMMON_CDW14_ELBTL_SHIFT, + NVME_IOCS_COMMON_CDW14_ELBTL_MASK); + cdw14 |= NVME_FIELD_ENCODE(storage_tag << (32 - sts), + NVME_IOCS_COMMON_CDW14_ELBTL_SHIFT, + NVME_IOCS_COMMON_CDW14_ELBTL_MASK); + break; + case NVME_NVM_PIF_32B_GUARD: + cdw14 = NVME_FIELD_ENCODE(reftag, + NVME_IOCS_COMMON_CDW14_ELBTL_SHIFT, + NVME_IOCS_COMMON_CDW14_ELBTL_MASK); + cdw3 = NVME_FIELD_ENCODE(reftag >> 32, + NVME_IOCS_COMMON_CDW3_ELBTU_SHIFT, + NVME_IOCS_COMMON_CDW3_ELBTU_MASK); + cdw14 |= NVME_FIELD_ENCODE( + (storage_tag << (80 - sts)) & 0xffff0000, + NVME_IOCS_COMMON_CDW14_ELBTL_SHIFT, + NVME_IOCS_COMMON_CDW14_ELBTL_MASK); + if (sts >= 48) + cdw3 |= NVME_FIELD_ENCODE(storage_tag >> (sts - 48), + NVME_IOCS_COMMON_CDW3_ELBTU_SHIFT, + NVME_IOCS_COMMON_CDW3_ELBTU_MASK); + else + cdw3 |= NVME_FIELD_ENCODE(storage_tag << (48 - sts), + NVME_IOCS_COMMON_CDW3_ELBTU_SHIFT, + NVME_IOCS_COMMON_CDW3_ELBTU_MASK); + cdw2 = NVME_FIELD_ENCODE(storage_tag >> (sts - 16), + NVME_IOCS_COMMON_CDW2_ELBTU_SHIFT, + NVME_IOCS_COMMON_CDW2_ELBTU_MASK); + break; + case NVME_NVM_PIF_64B_GUARD: + cdw14 = NVME_FIELD_ENCODE(reftag, + NVME_IOCS_COMMON_CDW14_ELBTL_SHIFT, + NVME_IOCS_COMMON_CDW14_ELBTL_MASK); + cdw3 = NVME_FIELD_ENCODE((reftag >> 32) & 0xffff, + NVME_IOCS_COMMON_CDW3_ELBTU_SHIFT, + NVME_IOCS_COMMON_CDW3_ELBTU_MASK); + cdw14 |= NVME_FIELD_ENCODE(storage_tag << (48 - sts), + NVME_IOCS_COMMON_CDW14_ELBTL_SHIFT, + NVME_IOCS_COMMON_CDW14_ELBTL_MASK); + if (sts >= 16) + cdw3 |= NVME_FIELD_ENCODE( + (storage_tag >> (sts - 16)) & 0xffff, + NVME_IOCS_COMMON_CDW3_ELBTU_SHIFT, + NVME_IOCS_COMMON_CDW3_ELBTU_MASK); + else + cdw3 |= NVME_FIELD_ENCODE( + (storage_tag << (16 - sts)) & 0xffff, + NVME_IOCS_COMMON_CDW3_ELBTU_SHIFT, + NVME_IOCS_COMMON_CDW3_ELBTU_MASK); + break; + default: + return -EINVAL; + } + + cmd->cdw2 = cdw2; + cmd->cdw3 = cdw3; + cmd->cdw14 = cdw14; + + return 0; +} + +/** + * nvme_init_app_tag() - Initialize Command Dword fields for + * Logical Block Application Tag/Mask + * @cmd: Passthru command to use + * @lbat: Logical block application tag + * @lbatm: Logical block application tag mask + */ +static inline void +nvme_init_app_tag(struct nvme_passthru_cmd *cmd, + __u16 lbat, __u16 lbatm) +{ + cmd->cdw15 = NVME_FIELD_ENCODE(lbat, + NVME_IOCS_COMMON_CDW15_ELBAT_SHIFT, + NVME_IOCS_COMMON_CDW15_ELBAT_MASK) | + NVME_FIELD_ENCODE(lbatm, + NVME_IOCS_COMMON_CDW15_ELBATM_SHIFT, + NVME_IOCS_COMMON_CDW15_ELBATM_MASK); +} + +/** + * nvme_init_io() - Initialize passthru command for a generic user I/O command + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @opcode: Opcode to execute + * @slba: Starting logical block + * @data: Pointer to user address of the data buffer + * @data_len: Length of user buffer, @data, in bytes + * @metadata: Pointer to user address of the metadata buffer + * @metadata_len:Length of user buffer, @metadata, in bytes + * + * Initializes the passthru command buffer for a generic NVM I/O command. + * Note: If @elbas is true, the caller must ensure the definition/logic for + * nvme_init_set_var_size_tags is available and that the return value from + * that function is checked for error. + */ +static inline void +nvme_init_io(struct nvme_passthru_cmd *cmd, __u8 opcode, __u32 nsid, __u64 slba, + void *data, __u32 data_len, void *metadata, __u32 metadata_len) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = opcode; + cmd->nsid = nsid; + cmd->metadata = (__u64)(uintptr_t)metadata; + cmd->addr = (__u64)(uintptr_t)data; + cmd->metadata_len = metadata_len; + cmd->data_len = data_len; + cmd->cdw10 = NVME_FIELD_ENCODE(slba, + NVME_IOCS_COMMON_CDW10_SLBAL_SHIFT, + NVME_IOCS_COMMON_CDW10_SLBAL_MASK); + cmd->cdw11 = NVME_FIELD_ENCODE(slba >> 32, + NVME_IOCS_COMMON_CDW11_SLBAU_SHIFT, + NVME_IOCS_COMMON_CDW11_SLBAU_MASK); +} + +/** + * nvme_init_read() - Initialize passthru command for a user read command + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @slba: Starting logical block + * @nlb: Number of logical blocks (0-based) + * @control: Upper 16 bits of cdw12 + * @dsm: Data set management attributes (CETYPE is zero), + * see &enum nvme_io_dsm_flags + * @cev: Command Extension Value (CETYPE is non-zero) + * @data: Pointer to user address of the data buffer + * @data_len: Length of user buffer, @data, in bytes + * @metadata: Pointer to user address of the metadata buffer + * @metadata_len:Length of user buffer, @metadata, in bytes + * + * Initializes the passthru command buffer for the Read command. + * Note: Assumes a macro or separate function exists to translate the combined + * NLB/control/prinfo fields into cdw12/cdw13. This transformation assumes + * the parameters are used for a generic nvme_init_io wrapper. + */ +static inline void +nvme_init_read(struct nvme_passthru_cmd *cmd, __u32 nsid, __u64 slba, + __u16 nlb, __u16 control, __u8 dsm, __u16 cev, + void *data, __u32 data_len, void *metadata, __u32 metadata_len) +{ + nvme_init_io(cmd, nvme_cmd_read, nsid, slba, + data, data_len, metadata, metadata_len); + cmd->cdw12 = NVME_FIELD_ENCODE(nlb, + NVME_IOCS_COMMON_CDW12_NLB_SHIFT, + NVME_IOCS_COMMON_CDW12_NLB_MASK) | + NVME_FIELD_ENCODE(control, + NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT, + NVME_IOCS_COMMON_CDW12_CONTROL_MASK); + cmd->cdw13 = NVME_FIELD_ENCODE(dsm, + NVME_IOCS_COMMON_CDW13_DSM_SHIFT, + NVME_IOCS_COMMON_CDW13_DSM_MASK) | + NVME_FIELD_ENCODE(cev, + NVME_IOCS_COMMON_CDW13_CEV_SHIFT, + NVME_IOCS_COMMON_CDW13_CEV_MASK); +} + +/** + * nvme_init_write() - Initialize passthru command for a user write command + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @slba: Starting logical block + * @nlb: Number of logical blocks (0-based) + * @control: Upper 16 bits of cdw12 + * @dspec: Directive specific value + * @dsm: Data set management attributes (CETYPE is zero), + * see &enum nvme_io_dsm_flags + * @cev: Command Extension Value (CETYPE is non-zero) + * @data: Pointer to user address of the data buffer + * @data_len: Length of user buffer, @data, in bytes + * @metadata: Pointer to user address of the metadata buffer + * @metadata_len:Length of user buffer, @metadata, in bytes + * + * Initializes the passthru command buffer for the Write command. + */ +static inline void +nvme_init_write(struct nvme_passthru_cmd *cmd, __u32 nsid, __u64 slba, + __u16 nlb, __u16 control, __u16 dspec, __u8 dsm, __u8 cev, + void *data, __u32 data_len, void *metadata, __u32 metadata_len) +{ + nvme_init_io(cmd, nvme_cmd_write, nsid, slba, + data, data_len, metadata, metadata_len); + cmd->cdw12 = NVME_FIELD_ENCODE(nlb, + NVME_IOCS_COMMON_CDW12_NLB_SHIFT, + NVME_IOCS_COMMON_CDW12_NLB_MASK) | + NVME_FIELD_ENCODE(control, + NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT, + NVME_IOCS_COMMON_CDW12_CONTROL_MASK); + cmd->cdw13 = NVME_FIELD_ENCODE(dspec, + NVME_IOCS_COMMON_CDW13_DSPEC_SHIFT, + NVME_IOCS_COMMON_CDW13_DSPEC_MASK) | + NVME_FIELD_ENCODE(dsm, + NVME_IOCS_COMMON_CDW13_DSM_SHIFT, + NVME_IOCS_COMMON_CDW13_DSM_MASK) | + NVME_FIELD_ENCODE(cev, + NVME_IOCS_COMMON_CDW13_CEV_SHIFT, + NVME_IOCS_COMMON_CDW13_CEV_MASK); +} +/** + * nvme_init_compare() - Initialize passthru command for a user compare command + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @slba: Starting logical block + * @nlb: Number of logical blocks (0-based) + * @control: Command control flags, see &enum nvme_io_control_flags. + * @cev: Command Extension Value (CETYPE is non-zero) + * @data: Pointer to user address of the data buffer + * @data_len: Length of user buffer, @data, in bytes + * @metadata: Pointer to user address of the metadata buffer + * @metadata_len:Length of user buffer, @metadata, in bytes + * + * Initializes the passthru command buffer for the Compare command. + */ +static inline void +nvme_init_compare(struct nvme_passthru_cmd *cmd, __u32 nsid, __u64 slba, + __u16 nlb, __u16 control, __u8 cev, void *data, __u32 data_len, + void *metadata, __u32 metadata_len) +{ + nvme_init_io(cmd, nvme_cmd_compare, nsid, slba, + data, data_len, metadata, metadata_len); + cmd->cdw12 = NVME_FIELD_ENCODE(nlb, + NVME_IOCS_COMMON_CDW12_NLB_SHIFT, + NVME_IOCS_COMMON_CDW12_NLB_MASK) | + NVME_FIELD_ENCODE(control, + NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT, + NVME_IOCS_COMMON_CDW12_CONTROL_MASK); + cmd->cdw13 = NVME_FIELD_ENCODE(cev, + NVME_IOCS_COMMON_CDW13_CEV_SHIFT, + NVME_IOCS_COMMON_CDW13_CEV_MASK); +} + +/** + * nvme_init_write_zeros() - Initialize passthru command for a + * write zeroes command + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @slba: Starting logical block + * @nlb: Number of logical blocks (0-based) + * @control: Upper 16 bits of cdw12 + * @dspec: Directive specific value + * @dsm: Data set management attributes (CETYPE is zero), + * see &enum nvme_io_dsm_flags + * @cev: Command Extension Value (CETYPE is non-zero) + * + * Initializes the passthru command buffer for the Write Zeroes command. + * Note: Write Zeroes command does not transfer data or metadata. + */ +static inline void +nvme_init_write_zeros(struct nvme_passthru_cmd *cmd, __u32 nsid, __u64 slba, + __u16 nlb, __u16 control, __u16 dspec, __u8 dsm, __u8 cev) +{ + nvme_init_io(cmd, nvme_cmd_write_zeroes, nsid, slba, NULL, 0, NULL, 0); + cmd->cdw12 = NVME_FIELD_ENCODE(nlb, + NVME_IOCS_COMMON_CDW12_NLB_SHIFT, + NVME_IOCS_COMMON_CDW12_NLB_MASK) | + NVME_FIELD_ENCODE(control, + NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT, + NVME_IOCS_COMMON_CDW12_CONTROL_MASK); + cmd->cdw13 = NVME_FIELD_ENCODE(dspec, + NVME_IOCS_COMMON_CDW13_DSPEC_SHIFT, + NVME_IOCS_COMMON_CDW13_DSPEC_MASK) | + NVME_FIELD_ENCODE(dsm, + NVME_IOCS_COMMON_CDW13_DSM_SHIFT, + NVME_IOCS_COMMON_CDW13_DSM_MASK) | + NVME_FIELD_ENCODE(cev, + NVME_IOCS_COMMON_CDW13_CEV_SHIFT, + NVME_IOCS_COMMON_CDW13_CEV_MASK); +} + +/** + * nvme_init_write_uncorrectable() - Initialize passthru command for a + * write uncorrectable command + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @slba: Starting logical block + * @nlb: Number of logical blocks (0-based) + * @control: Upper 16 bits of cdw12 + * @dspec: Directive specific value + * + * Initializes the passthru command buffer for the Write Uncorrectable command. + * Note: This command transfers no data or metadata. + */ +static inline void +nvme_init_write_uncorrectable(struct nvme_passthru_cmd *cmd, __u32 nsid, + __u64 slba, __u16 nlb, __u16 control, __u16 dspec) +{ + nvme_init_io(cmd, nvme_cmd_write_uncor, nsid, slba, NULL, 0, NULL, 0); + cmd->cdw12 = NVME_FIELD_ENCODE(nlb, + NVME_IOCS_COMMON_CDW12_NLB_SHIFT, + NVME_IOCS_COMMON_CDW12_NLB_MASK) | + NVME_FIELD_ENCODE(control, + NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT, + NVME_IOCS_COMMON_CDW12_CONTROL_MASK); + cmd->cdw13 = NVME_FIELD_ENCODE(dspec, + NVME_IOCS_COMMON_CDW13_DSPEC_SHIFT, + NVME_IOCS_COMMON_CDW13_DSPEC_MASK); +} + +/** + * nvme_init_verify() - Initialize passthru command for a verify command + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @slba: Starting logical block + * @nlb: Number of logical blocks (0-based) + * @control: Upper 16 bits of cdw12 + * @cev: Command Extension Value (CETYPE is non-zero) + * @data: Pointer to user address of the data buffer + * @data_len: Length of user buffer, @data, in bytes + * @metadata: Pointer to user address of the metadata buffer + * @metadata_len:Length of user buffer, @metadata, in bytes + * + * Initializes the passthru command buffer for the Verify command. + * Note: Verify command transfers data or metadata to the controller to perform + * the verification but not back to the host. + */ +static inline void +nvme_init_verify(struct nvme_passthru_cmd *cmd, __u32 nsid, __u64 slba, + __u16 nlb, __u16 control, __u8 cev, void *data, __u32 data_len, + void *metadata, __u32 metadata_len) +{ + nvme_init_io(cmd, nvme_cmd_verify, nsid, slba, + data, data_len, metadata, metadata_len); + cmd->cdw12 = NVME_FIELD_ENCODE(nlb, + NVME_IOCS_COMMON_CDW12_NLB_SHIFT, + NVME_IOCS_COMMON_CDW12_NLB_MASK) | + NVME_FIELD_ENCODE(control, + NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT, + NVME_IOCS_COMMON_CDW12_CONTROL_MASK); + cmd->cdw13 = NVME_FIELD_ENCODE(cev, + NVME_IOCS_COMMON_CDW13_CEV_SHIFT, + NVME_IOCS_COMMON_CDW13_CEV_MASK); +} + +/** + * nvme_init_copy() - Initialize passthru command for Copy command + * @cmd: Passthru command to use + * @nsid: Namespace identifier + * @sdlba: Start destination LBA + * @nr: Number of ranges (1-based, 0-based in command) + * @desfmt: Descriptor format + * @prinfor: Protection information field for read + * @prinfow: Protection information field for write + * @cetype: Command Extension Type + * @dtype: Directive Type + * @stcw: Storage Tag Check Write + * @stcr: Storage Tag Check Read + * @fua: Force unit access + * @lr: Limited retry + * @cev: Command Extension Value + * @dspec: Directive specific value + * @cpydsc: Range description buffer + * + * Initializes the passthru command buffer for the Copy command by calculating + * the data length and calling the generic I/O initializer. + */ +static inline void +nvme_init_copy(struct nvme_passthru_cmd *cmd, __u32 nsid, __u64 sdlba, + __u16 nr, __u8 desfmt, __u8 prinfor, __u8 prinfow, + __u8 cetype, __u8 dtype, bool stcw, bool stcr, bool fua, + bool lr, __u16 cev, __u16 dspec, void *cpydsc) +{ + __u32 data_len; + + switch (desfmt) { + case 1: + data_len = nr * sizeof(struct nvme_copy_range_f1); + break; + case 2: + data_len = nr * sizeof(struct nvme_copy_range_f2); + break; + case 3: + data_len = nr * sizeof(struct nvme_copy_range_f3); + break; + default: + data_len = nr * sizeof(struct nvme_copy_range); + break; + } + + nvme_init_io(cmd, nvme_cmd_copy, nsid, sdlba, cpydsc, + data_len, NULL, 0); + cmd->cdw12 = NVME_FIELD_ENCODE(nr - 1, + NVME_COPY_CDW12_NR_SHIFT, + NVME_COPY_CDW12_NR_MASK) | + NVME_FIELD_ENCODE(desfmt, + NVME_COPY_CDW12_DESFMT_SHIFT, + NVME_COPY_CDW12_DESFMT_MASK) | + NVME_FIELD_ENCODE(prinfor, + NVME_COPY_CDW12_PRINFOR_SHIFT, + NVME_COPY_CDW12_PRINFOR_MASK) | + NVME_FIELD_ENCODE(cetype, + NVME_COPY_CDW12_CETYPE_SHIFT, + NVME_COPY_CDW12_CETYPE_MASK) | + NVME_FIELD_ENCODE(dtype, + NVME_COPY_CDW12_DTYPE_SHIFT, + NVME_COPY_CDW12_DTYPE_MASK) | + NVME_FIELD_ENCODE(stcw, + NVME_COPY_CDW12_STCW_SHIFT, + NVME_COPY_CDW12_STCW_MASK) | + NVME_FIELD_ENCODE(stcr, + NVME_COPY_CDW12_STCR_SHIFT, + NVME_COPY_CDW12_STCR_MASK) | + NVME_FIELD_ENCODE(prinfow, + NVME_COPY_CDW12_PRINFOW_SHIFT, + NVME_COPY_CDW12_PRINFOW_MASK) | + NVME_FIELD_ENCODE(fua, + NVME_COPY_CDW12_FUA_SHIFT, + NVME_COPY_CDW12_FUA_MASK) | + NVME_FIELD_ENCODE(lr, + NVME_COPY_CDW12_LR_SHIFT, + NVME_COPY_CDW12_LR_MASK); + cmd->cdw13 = NVME_FIELD_ENCODE(cev, + NVME_IOCS_COMMON_CDW13_CEV_SHIFT, + NVME_IOCS_COMMON_CDW13_CEV_MASK) | + NVME_FIELD_ENCODE(dspec, + NVME_IOCS_COMMON_CDW13_DSPEC_SHIFT, + NVME_IOCS_COMMON_CDW13_DSPEC_MASK); +} + +/** + * nvme_init_resv_acquire() - Initialize passthru command for + * Reservation Acquire + * @cmd: Passthru command to use + * @nsid: Namespace identifier + * @racqa: The action that is performed by the command, + * see &enum nvme_resv_racqa + * @iekey: Set to ignore the existing key + * @disnsrs: Disperse Namespace Reservation Support + * @rtype: The type of reservation to be create, see &enum nvme_resv_rtype + * @crkey: The current reservation key associated with the host + * @prkey: Preempt Reservation Key + * @payload: Data payload buffer to hold crkey and prkey + * + * Initializes the passthru command buffer for the Reservation Acquire command. + */ +static inline void +nvme_init_resv_acquire(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_resv_racqa racqa, bool iekey, bool disnsrs, + enum nvme_resv_rtype rtype, __u64 crkey, __u64 prkey, + __le64 *payload) +{ + memset(cmd, 0, sizeof(*cmd)); + + payload[0] = htole64(crkey); + payload[1] = htole64(prkey); + + cmd->opcode = nvme_cmd_resv_acquire; + cmd->nsid = nsid; + cmd->data_len = 2 * sizeof(__le64); + cmd->addr = (__u64)(uintptr_t)payload; + cmd->cdw10 = NVME_FIELD_ENCODE(racqa, + NVME_RESV_ACQUIRE_CDW10_RACQA_SHIFT, + NVME_RESV_ACQUIRE_CDW10_RACQA_MASK) | + NVME_FIELD_ENCODE(iekey, + NVME_RESV_ACQUIRE_CDW10_IEKEY_SHIFT, + NVME_RESV_ACQUIRE_CDW10_IEKEY_MASK) | + NVME_FIELD_ENCODE(disnsrs, + NVME_RESV_ACQUIRE_CDW10_DISNSRS_SHIFT, + NVME_RESV_ACQUIRE_CDW10_DISNSRS_MASK) | + NVME_FIELD_ENCODE(rtype, + NVME_RESV_ACQUIRE_CDW10_RTYPE_SHIFT, + NVME_RESV_ACQUIRE_CDW10_RTYPE_MASK); +} + +/** + * nvme_init_resv_register() - Initialize passthru command for + * Reservation Register + * @cmd: Passthru command to use + * @nsid: Namespace identifier + * @rrega: The registration action, see &enum nvme_resv_rrega + * @iekey: Set to ignore the existing key + * @disnsrs: Disperse Namespace Reservation Support + * @cptpl: Change persist through power loss, see &enum nvme_resv_cptpl + * @crkey: The current reservation key associated with the host + * @nrkey: The new reservation key to be register if action is register or + * replace + * @payload: Data payload buffer to hold crkey and nrkey + * + * Initializes the passthru command buffer for the Reservation Register command. + */ +static inline void +nvme_init_resv_register(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_resv_rrega rrega, bool iekey, bool disnsrs, + enum nvme_resv_cptpl cptpl, __u64 crkey, __u64 nrkey, + __le64 *payload) +{ + memset(cmd, 0, sizeof(*cmd)); + + payload[0] = htole64(crkey); + payload[1] = htole64(nrkey); + + cmd->opcode = nvme_cmd_resv_register; + cmd->nsid = nsid; + cmd->data_len = 2 * sizeof(__le64); + cmd->addr = (__u64)(uintptr_t)payload; + cmd->cdw10 = NVME_FIELD_ENCODE(rrega, + NVME_RESV_REGISTER_CDW10_RREGA_SHIFT, + NVME_RESV_REGISTER_CDW10_RREGA_MASK) | + NVME_FIELD_ENCODE(iekey, + NVME_RESV_REGISTER_CDW10_IEKEY_SHIFT, + NVME_RESV_REGISTER_CDW10_IEKEY_MASK) | + NVME_FIELD_ENCODE(disnsrs, + NVME_RESV_REGISTER_CDW10_DISNSRS_SHIFT, + NVME_RESV_REGISTER_CDW10_DISNSRS_MASK) | + NVME_FIELD_ENCODE(cptpl, + NVME_RESV_REGISTER_CDW10_CPTPL_SHIFT, + NVME_RESV_REGISTER_CDW10_CPTPL_MASK); +} + +/** + * nvme_init_resv_release() - Initialize passthru command for + * Reservation Release + * @cmd: Passthru command to use + * @nsid: Namespace identifier + * @rrela: Reservation release action, see &enum nvme_resv_rrela + * @iekey: Set to ignore the existing key + * @disnsrs: Disperse Namespace Reservation Support + * @rtype: The type of reservation to be create, see &enum nvme_resv_rtype + * @crkey: The current reservation key to release + * @payload: Data payload buffer to hold crkey + * + * Initializes the passthru command buffer for the Reservation Release command. + */ +static inline void +nvme_init_resv_release(struct nvme_passthru_cmd *cmd, __u32 nsid, + enum nvme_resv_rrela rrela, bool iekey, bool disnsrs, + enum nvme_resv_rtype rtype, __u64 crkey, __le64 *payload) +{ + memset(cmd, 0, sizeof(*cmd)); + + payload[0] = htole64(crkey); + + cmd->opcode = nvme_cmd_resv_release; + cmd->nsid = nsid; + cmd->data_len = sizeof(__le64); + cmd->addr = (__u64)(uintptr_t)payload; + cmd->cdw10 = NVME_FIELD_ENCODE(rrela, + NVME_RESV_RELEASE_CDW10_RRELA_SHIFT, + NVME_RESV_RELEASE_CDW10_RRELA_MASK) | + NVME_FIELD_ENCODE(iekey, + NVME_RESV_RELEASE_CDW10_IEKEY_SHIFT, + NVME_RESV_RELEASE_CDW10_IEKEY_MASK) | + NVME_FIELD_ENCODE(disnsrs, + NVME_RESV_RELEASE_CDW10_DISNSRS_SHIFT, + NVME_RESV_RELEASE_CDW10_DISNSRS_MASK) | + NVME_FIELD_ENCODE(rtype, + NVME_RESV_RELEASE_CDW10_RTYPE_SHIFT, + NVME_RESV_RELEASE_CDW10_RTYPE_MASK); +} + +/** + * nvme_init_resv_report() - Initialize passthru command for + * Reservation Report + * @cmd: Passthru command to use + * @nsid: Namespace identifier + * @eds: Request extended Data Structure + * @disnsrs: Disperse Namespace Reservation Support + * @report: The user space destination address to store the reservation + * report buffer + * @len: Number of bytes to request transferred with this command + * + * Initializes the passthru command buffer for the Reservation Report command. + */ +static inline void +nvme_init_resv_report(struct nvme_passthru_cmd *cmd, __u32 nsid, + bool eds, bool disnsrs, struct nvme_resv_status *report, + __u32 len) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_cmd_resv_report; + cmd->nsid = nsid; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)report; + cmd->cdw10 = (len >> 2) - 1; + cmd->cdw11 = NVME_FIELD_ENCODE(eds, + NVME_RESV_REPORT_CDW11_EDS_SHIFT, + NVME_RESV_REPORT_CDW11_EDS_MASK) | + NVME_FIELD_ENCODE(disnsrs, + NVME_RESV_REPORT_CDW11_DISNSRS_SHIFT, + NVME_RESV_REPORT_CDW11_DISNSRS_MASK); +} + +/** + * nvme_init_io_mgmt_recv() - Initialize passthru command for + * I/O Management Receive command + * @cmd: Passthru command to use + * @nsid: Namespace identifier + * @mo: Management Operation + * @mos: Management Operation Specific + * @data: Userspace address of the data buffer + * @len: Length of @data + * + * Initializes the passthru command buffer for the I/O Management + * Receive command. + */ +static inline void +nvme_init_io_mgmt_recv(struct nvme_passthru_cmd *cmd, __u32 nsid, + __u8 mo, __u16 mos, void *data, __u32 len) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_cmd_io_mgmt_recv; + cmd->nsid = nsid; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = NVME_FIELD_ENCODE(mo, + NVME_IO_MGMT_RECV_CDW10_MO_SHIFT, + NVME_IO_MGMT_RECV_CDW10_MO_MASK) | + NVME_FIELD_ENCODE(mos, + NVME_IO_MGMT_RECV_CDW10_MOS_SHIFT, + NVME_IO_MGMT_RECV_CDW10_MOS_MASK); + cmd->cdw11 = (len >> 2) - 1; +} + +/** + * nvme_init_fdp_reclaim_unit_handle_status() - Initialize passthru command + * to get reclaim unit handle status + * @cmd: Passthru command to use + * @nsid: Namespace identifier + * @data: Response buffer + * @len: Length of response buffer + * + * Initializes the passthru command buffer for the I/O Management Receive - + * Reclaim Unit Handle Status command. + */ +static inline void +nvme_init_fdp_reclaim_unit_handle_status(struct nvme_passthru_cmd *cmd, + __u32 nsid, void *data, __u32 len) +{ + nvme_init_io_mgmt_recv(cmd, nsid, NVME_IO_MGMT_RECV_RUH_STATUS, 0, + data, len); +} + +/** + * nvme_init_io_mgmt_send() - Initialize passthru command for + * I/O Management Send command + * @cmd: Passthru command to use + * @nsid: Namespace identifier + * @mo: Management Operation + * @mos: Management Operation Specific + * @data: Userspace address of the data buffer + * @len: Length of @data + * + * Initializes the passthru command buffer for the I/O Management Send command. + */ +static inline void +nvme_init_io_mgmt_send(struct nvme_passthru_cmd *cmd, __u32 nsid, + __u8 mo, __u16 mos, void *data, __u32 len) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_cmd_io_mgmt_send; + cmd->nsid = nsid; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = NVME_FIELD_ENCODE(mo, + NVME_IO_MGMT_SEND_CDW10_MO_SHIFT, + NVME_IO_MGMT_SEND_CDW10_MO_MASK) | + NVME_FIELD_ENCODE(mos, + NVME_IO_MGMT_SEND_CDW10_MOS_SHIFT, + NVME_IO_MGMT_SEND_CDW10_MOS_MASK); +} + +/** + * nvme_init_fdp_reclaim_unit_handle_update() - Initialize passthru command to + * update a list of reclaim unit handles + * @cmd: Passthru command to use + * @nsid: Namespace identifier + * @pids: List of placement identifiers buffer + * @npids: Number of placement identifiers + * + * Initializes the passthru command buffer for the I/O Management Send - + * Reclaim Unit Handle Update command. + */ +static inline void +nvme_init_fdp_reclaim_unit_handle_update(struct nvme_passthru_cmd *cmd, + __u32 nsid, void *pids, unsigned int npids) +{ + __u16 mos = npids - 1; /* MOS = NPI - 1 */ + __u32 len = npids * sizeof(__u16); + + nvme_init_io_mgmt_send(cmd, nsid, NVME_IO_MGMT_SEND_RUH_UPDATE, + mos, pids, len); +} + +/** + * nvme_init_zns_mgmt_send() - Initialize passthru command for + * ZNS management send command + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @slba: Starting logical block address + * @zsa: Zone send action + * @selall: Select all flag + * @zsaso: Zone Send Action Specific Option + * @zm: Zone Management + * @data: Userspace address of the data buffer + * @len: Length of @data + * + * Initializes the passthru command buffer for the ZNS Management Send command. + */ +static inline void +nvme_init_zns_mgmt_send(struct nvme_passthru_cmd *cmd, __u32 nsid, + __u64 slba, enum nvme_zns_send_action zsa, bool selall, + __u8 zsaso, __u8 zm, void *data, __u32 len) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_zns_cmd_mgmt_send; + cmd->nsid = nsid; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = slba & 0xffffffff; + cmd->cdw11 = slba >> 32; + cmd->cdw13 = NVME_FIELD_ENCODE(zsa, + NVME_ZNS_MGMT_SEND_ZSA_SHIFT, + NVME_ZNS_MGMT_SEND_ZSA_MASK) | + NVME_FIELD_ENCODE(selall, + NVME_ZNS_MGMT_SEND_SEL_SHIFT, + NVME_ZNS_MGMT_SEND_SEL_MASK) | + NVME_FIELD_ENCODE(zsaso, + NVME_ZNS_MGMT_SEND_ZSASO_SHIFT, + NVME_ZNS_MGMT_SEND_ZSASO_MASK) | + NVME_FIELD_ENCODE(zm, + NVME_ZNS_MGMT_SEND_ZM_SHIFT, + NVME_ZNS_MGMT_SEND_ZM_MASK); +} + +/** + * nvme_init_zns_mgmt_recv() - Initialize passthru command for + * ZNS management receive command + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @slba: Starting logical block address + * @zra: zone receive action + * @zras: Zone receive action specific field + * @zraspf: Zone receive action specific features + * @data: Userspace address of the data buffer + * @len: Length of @data + * + * Initializes the passthru command buffer for the ZNS Management + * Receive command. + */ +static inline void +nvme_init_zns_mgmt_recv(struct nvme_passthru_cmd *cmd, __u32 nsid, + __u64 slba, enum nvme_zns_recv_action zra, __u16 zras, + bool zraspf, void *data, __u32 len) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_zns_cmd_mgmt_recv; + cmd->nsid = nsid; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = slba & 0xffffffff; + cmd->cdw11 = slba >> 32; + cmd->cdw12 = (len >> 2) - 1; + cmd->cdw13 = NVME_FIELD_ENCODE(zra, + NVME_ZNS_MGMT_RECV_ZRA_SHIFT, + NVME_ZNS_MGMT_RECV_ZRA_MASK) | + NVME_FIELD_ENCODE(zras, + NVME_ZNS_MGMT_RECV_ZRAS_SHIFT, + NVME_ZNS_MGMT_RECV_ZRAS_MASK) | + NVME_FIELD_ENCODE(zraspf, + NVME_ZNS_MGMT_RECV_ZRASPF_SHIFT, + NVME_ZNS_MGMT_RECV_ZRASPF_MASK); +} + +/** + * nvme_init_zns_report_zones() - Initialize passthru command to return + * the list of zones + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @slba: Starting LBA + * @opts: Reporting options + * @extended: Extended report + * @partial: Partial report requested + * @data: Userspace address of the report zones data buffer + * @len: Length of the data buffer + * + * Initializes the passthru command buffer for the ZNS Management Receive - + * Report Zones command. + */ +static inline void +nvme_init_zns_report_zones(struct nvme_passthru_cmd *cmd, __u32 nsid, + __u64 slba, enum nvme_zns_report_options opts, + bool extended, bool partial, + void *data, __u32 len) +{ + enum nvme_zns_recv_action zra = extended ? + NVME_ZNS_ZRA_EXTENDED_REPORT_ZONES : NVME_ZNS_ZRA_REPORT_ZONES; + __u16 zras = (__u16)opts; + bool zraspf = partial; /* ZRASPF is Partial Report Requested */ + + nvme_init_zns_mgmt_recv(cmd, nsid, slba, zra, zras, zraspf, data, len); +} + +/** + * nvme_init_zns_append() - Initialize passthru command to append data to a zone + * @cmd: Passthru command to use + * @nsid: Namespace ID + * @zslba: Zone start logical block address + * @nlb: Number of logical blocks + * @control: Upper 16 bits of cdw12 + * @cev: Command Extension Value + * @dspec: Directive Specific + * @data: Userspace address of the data buffer + * @data_len: Length of @data + * @metadata: Userspace address of the metadata buffer + * @metadata_len: Length of @metadata + * + * Initializes the passthru command buffer for the ZNS Append command. + */ +static inline void +nvme_init_zns_append(struct nvme_passthru_cmd *cmd, __u32 nsid, + __u64 zslba, __u16 nlb, __u16 control, __u16 cev, __u16 dspec, + void *data, __u32 data_len, void *metadata, __u32 metadata_len) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_zns_cmd_append; + cmd->nsid = nsid; + cmd->metadata = (__u64)(uintptr_t)metadata; + cmd->addr = (__u64)(uintptr_t)data; + cmd->metadata_len = metadata_len; + cmd->data_len = data_len; + cmd->cdw10 = NVME_FIELD_ENCODE(zslba, + NVME_IOCS_COMMON_CDW10_SLBAL_SHIFT, + NVME_IOCS_COMMON_CDW10_SLBAL_MASK); + cmd->cdw11 = NVME_FIELD_ENCODE(zslba >> 32, + NVME_IOCS_COMMON_CDW11_SLBAU_SHIFT, + NVME_IOCS_COMMON_CDW11_SLBAU_MASK); + cmd->cdw12 = NVME_FIELD_ENCODE(nlb, + NVME_IOCS_COMMON_CDW12_NLB_SHIFT, + NVME_IOCS_COMMON_CDW12_NLB_MASK) | + NVME_FIELD_ENCODE(control, + NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT, + NVME_IOCS_COMMON_CDW12_CONTROL_MASK); + cmd->cdw13 = NVME_FIELD_ENCODE(dspec, + NVME_IOCS_COMMON_CDW13_DSPEC_SHIFT, + NVME_IOCS_COMMON_CDW13_DSPEC_MASK); + if (control & NVME_IOCS_COMMON_CDW12_CETYPE_MASK) + cmd->cdw13 |= NVME_FIELD_ENCODE(cev, + NVME_IOCS_COMMON_CDW13_CEV_SHIFT, + NVME_IOCS_COMMON_CDW13_CEV_MASK); +} + +/** + * nvme_init_dim_send() - Initialize passthru command for + * Discovery Information Management (DIM) Send + * @cmd: Passthru command to use + * @tas: Task field of the Command Dword 10 (cdw10) + * @data: Pointer to the DIM data buffer + * @len: Length of @data + * + * Initializes the passthru command buffer for the Discovery Information + * Management Send command. + */ +static inline void +nvme_init_dim_send(struct nvme_passthru_cmd *cmd, + __u8 tas, void *data, __u32 len) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_discovery_info_mgmt; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = NVME_FIELD_ENCODE(tas, + NVME_DIM_TAS_SHIFT, + NVME_DIM_TAS_MASK); + +} + +/** + * nvme_init_lm_cdq_create() - Initialize passthru command for + * Controller Data Queue create - Controller Data Queue command + * @cmd: Passthru command to use + * @mos: Management Operation Specific (MOS): This field is + * specific to the SEL type + * @cntlid: Controller ID: For Create CDQ, specifies the target + * migratable controller + * @cdqsize: For Create CDQ, specifies the size of CDQ, in dwords - 4 byte + * @data: Pointer to data buffer + * + * Initializes the passthru command buffer for the Controller Data Queue + * command. Note: The result CDQID is returned in the CQE dword0, which the + * submission function must handle. + */ +static inline void +nvme_init_lm_cdq_create(struct nvme_passthru_cmd *cmd, + __u16 mos, __u16 cntlid, __u32 cdqsize, void *data) +{ + __u16 cqs; + + memset(cmd, 0, sizeof(*cmd)); + + cqs = NVME_FIELD_ENCODE(cntlid, + NVME_LM_CREATE_CDQ_CNTLID_SHIFT, + NVME_LM_CREATE_CDQ_CNTLID_MASK); + + cmd->opcode = nvme_admin_ctrl_data_queue; + cmd->data_len = cdqsize << 2; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = NVME_FIELD_ENCODE(NVME_LM_SEL_CREATE_CDQ, + NVME_LM_CDQ_SEL_SHIFT, + NVME_LM_CDQ_SEL_MASK) | + NVME_FIELD_ENCODE(mos, + NVME_LM_CDQ_MOS_SHIFT, + NVME_LM_CDQ_MOS_MASK); + cmd->cdw11 = NVME_FIELD_ENCODE(NVME_LM_CREATE_CDQ_PC, + NVME_LM_CREATE_CDQ_PC_SHIFT, + NVME_LM_CREATE_CDQ_PC_MASK) | + NVME_FIELD_ENCODE(cqs, + NVME_LM_CQS_SHIFT, + NVME_LM_CQS_MASK); + cmd->cdw12 = cdqsize; +} + +/** + * nvme_init_lm_cdq_delete() - Initialize passthru command for + * Controller Data Queue delete - Controller Data Queue command + * @cmd: Passthru command to use + * @mos: Management Operation Specific (MOS): This field is + * specific to the SEL type + * @cdqid: Controller Data Queue ID (CDQID): For Delete CDQ, this + * field is the CDQID to delete. + * + * Initializes the passthru command buffer for the Controller Data Queue delete + * command. + */ +static inline void +nvme_init_lm_cdq_delete(struct nvme_passthru_cmd *cmd, + __u16 mos, __u16 cdqid) +{ + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_ctrl_data_queue; + cmd->cdw10 = NVME_FIELD_ENCODE(NVME_LM_SEL_DELETE_CDQ, + NVME_LM_CDQ_SEL_SHIFT, + NVME_LM_CDQ_SEL_MASK) | + NVME_FIELD_ENCODE(mos, + NVME_LM_CDQ_MOS_SHIFT, + NVME_LM_CDQ_MOS_MASK); + cmd->cdw11 = NVME_FIELD_ENCODE(cdqid, + NVME_LM_DELETE_CDQ_CDQID_SHIFT, + NVME_LM_DELETE_CDQ_CDQID_MASK); +} + +/** + * nvme_init_lm_track_send() - Initialize passthru command for + * Track Send command + * @cmd: Passthru command to use + * @sel: Select (SEL): This field specifies the type of + * management operation to perform + * @mos: Management Operation Specific (MOS): This field + * is specific to the SEL type + * @cdqid: Controller Data Queue ID (CDQID) + * + * Initializes the passthru command buffer for the Track Send command. + */ +static inline void +nvme_init_lm_track_send(struct nvme_passthru_cmd *cmd, + __u8 sel, __u16 mos, __u16 cdqid) +{ + + memset(cmd, 0, sizeof(*cmd)); + cmd->opcode = nvme_admin_track_send; + cmd->cdw10 = NVME_FIELD_ENCODE(sel, + NVME_LM_TRACK_SEND_SEL_SHIFT, + NVME_LM_TRACK_SEND_SEL_MASK) | + NVME_FIELD_ENCODE(mos, + NVME_LM_TRACK_SEND_MOS_SHIFT, + NVME_LM_TRACK_SEND_MOS_MASK); + cmd->cdw11 = cdqid; +} + +/** + * nvme_init_lm_migration_send() - Initialize passthru command for + * Migration Send command + * @cmd: Passthru command to use + * @sel: Select (SEL): This field specifies the type of management + * operation to perform. + * @mos: Management Operation Specific (MOS): This field is specific + * to the SEL type + * @cntlid: Controller ID: This field specifies the identifier of the + * controller to which the operation is performed. + * @stype: Suspend Type (STYPE): This field specifies the type of suspend. + * @dudmq: Delete User Data Migration Queue (DUDMQ): If set, the migration + * queue is deleted is deleted as part of the Suspend operation. + * @csvi: Controller State Version Index (CSVI) + * @csuuidi: Controller State UUID Index (CSUUIDI) + * @cso: Offset: This field specifies the offset, in bytes, within + * the data available to be returned and specifies the starting + * point for that data for what is actually returned to the host. + * @uidx: UUID Index (UIDX) + * @data: Pointer to data buffer + * @len: Length of @data + * + * Initializes the passthru command buffer for the Migration Send command. + */ +static inline void +nvme_init_lm_migration_send(struct nvme_passthru_cmd *cmd, + __u16 sel, __u16 mos, __u16 cntlid, __u8 stype, bool dudmq, + __u8 csvi, __u16 csuuidi, __u64 cso, __u8 uidx, + void *data, __u32 len) +{ + __u32 cdw10 = NVME_FIELD_ENCODE(sel, + NVME_LM_MIGRATION_SEND_SEL_SHIFT, + NVME_LM_MIGRATION_SEND_SEL_MASK) | + NVME_FIELD_ENCODE(mos, + NVME_LM_MIGRATION_SEND_MOS_SHIFT, + NVME_LM_MIGRATION_SEND_MOS_MASK); + __u32 cdw11 = 0; + __u32 cdw14 = NVME_FIELD_ENCODE(uidx, + NVME_LM_MIGRATION_SEND_UIDX_SHIFT, + NVME_LM_MIGRATION_SEND_UIDX_MASK); + + if (sel == NVME_LM_SEL_SUSPEND) { + cdw11 = NVME_FIELD_ENCODE(stype, + NVME_LM_STYPE_SHIFT, + NVME_LM_STYPE_MASK) | + NVME_FIELD_ENCODE(cntlid, + NVME_LM_SUSPEND_CNTLID_SHIFT, + NVME_LM_SUSPEND_CNTLID_MASK); + if (dudmq) + cdw11 |= NVME_LM_DUDMQ; + } else if (sel == NVME_LM_SEL_RESUME) { + cdw11 = NVME_FIELD_ENCODE(cntlid, + NVME_LM_RESUME_CNTLID_SHIFT, + NVME_LM_RESUME_CNTLID_MASK); + } else if (sel == NVME_LM_SEL_SET_CONTROLLER_STATE) { + cdw11 = NVME_FIELD_ENCODE(csuuidi, + NVME_LM_SET_CONTROLLER_STATE_CSUUIDI_SHIFT, + NVME_LM_SET_CONTROLLER_STATE_CSUUIDI_MASK) | + NVME_FIELD_ENCODE(csvi, + NVME_LM_SET_CONTROLLER_STATE_CSVI_SHIFT, + NVME_LM_SET_CONTROLLER_STATE_CSVI_MASK) | + NVME_FIELD_ENCODE(cntlid, + NVME_LM_SET_CONTROLLER_STATE_CNTLID_SHIFT, + NVME_LM_SET_CONTROLLER_STATE_CNTLID_MASK); + } + + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_migration_send; + cmd->data_len = len; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = cdw10; + cmd->cdw11 = cdw11; + cmd->cdw12 = (__u32)cso; + cmd->cdw13 = (__u32)(cso >> 32); + cmd->cdw14 = cdw14; + cmd->cdw15 = len / sizeof(__u32); +} + +/** + * nvme_init_lm_migration_recv() - Initialize passthru command for + * Migration Receive command + * @cmd: Passthru command to use + * @offset: Offset: This field specifies the offset, in bytes, within + * the data available to be returned and specifies the starting + * point for that data for what is actually returned to the host. + * @mos: Management Operation Specific (MOS): This field is specific to + * the SEL type + * @cntlid: Controller ID: This field specifies the identifier of the + * controller to which the operation is performed. + * @csuuidi: Controller State UUID Index (CSUUIDI) + * @sel: Select (SEL): This field specifies the type of management + * operation to perform + * @uidx: UUID Index (UIDX) + * @csuidxp: Controller State UUID Index Parameter (CSUIDXP) + * @data: Pointer to data buffer + * @len: Length of @data + * + * Initializes the passthru command buffer for the Migration Receive command. + */ +static inline void +nvme_init_lm_migration_recv(struct nvme_passthru_cmd *cmd, + __u64 offset, __u16 mos, __u16 cntlid, __u16 csuuidi, __u8 sel, + __u8 uidx, __u8 csuidxp, void *data, __u32 len) +{ + __u32 cdw11 = 0; + __u32 data_len = 0; + + if (sel == NVME_LM_SEL_GET_CONTROLLER_STATE) { + cdw11 = NVME_FIELD_ENCODE(csuidxp, + NVME_LM_GET_CONTROLLER_STATE_CSUIDXP_SHIFT, + NVME_LM_GET_CONTROLLER_STATE_CSUIDXP_MASK) | + NVME_FIELD_ENCODE(csuuidi, + NVME_LM_GET_CONTROLLER_STATE_CSUUIDI_SHIFT, + NVME_LM_GET_CONTROLLER_STATE_CSUUIDI_MASK) | + NVME_FIELD_ENCODE(cntlid, + NVME_LM_GET_CONTROLLER_STATE_CNTLID_SHIFT, + NVME_LM_GET_CONTROLLER_STATE_CNTLID_MASK); + data_len = len; + } + + memset(cmd, 0, sizeof(*cmd)); + + cmd->opcode = nvme_admin_migration_receive; + cmd->data_len = data_len; + cmd->addr = (__u64)(uintptr_t)data; + cmd->cdw10 = NVME_FIELD_ENCODE(sel, + NVME_LM_MIGRATION_RECV_SEL_SHIFT, + NVME_LM_MIGRATION_RECV_SEL_MASK) | + NVME_FIELD_ENCODE(mos, + NVME_LM_MIGRATION_RECV_MOS_SHIFT, + NVME_LM_MIGRATION_RECV_MOS_MASK); + cmd->cdw11 = cdw11; + cmd->cdw12 = (__u32)offset; + cmd->cdw13 = (__u32)(offset >> 32); + cmd->cdw14 = NVME_FIELD_ENCODE(uidx, + NVME_LM_MIGRATION_RECV_UIDX_SHIFT, + NVME_LM_MIGRATION_RECV_UIDX_MASK); + cmd->cdw15 = len ? (__u32)((len - 1) / sizeof(__u32)) : 0; +} + +/** + * nvme_init_lm_set_features_ctrl_data_queue() - Initialize passthru command for + * Set Controller Data Queue feature + * @cmd: Passthru command to use + * @cdqid: Controller Data Queue ID (CDQID) + * @hp: Head Pointer (passed in cdw12) + * @tpt: Tail Pointer Trigger (passed in cdw13) + * @etpt: Enable Tail Pointer Trigger + * + * Initializes the passthru command buffer for the Set Features command with + * FID value %NVME_FEAT_FID_CTRL_DATA_QUEUE. + */ +static inline void +nvme_init_lm_set_features_ctrl_data_queue(struct nvme_passthru_cmd *cmd, + __u16 cdqid, __u32 hp, __u32 tpt, bool etpt) +{ + nvme_init_set_features(cmd, NVME_FEAT_FID_CTRL_DATA_QUEUE, false); + cmd->cdw11 = cdqid | + NVME_FIELD_ENCODE(etpt, + NVME_LM_CTRL_DATA_QUEUE_ETPT_SHIFT, + NVME_LM_CTRL_DATA_QUEUE_ETPT_MASK); + cmd->cdw12 = hp; + cmd->cdw13 = tpt; +} + +/** + * nvme_init_lm_get_features_ctrl_data_queue() - Initialize passthru command for + * Get Controller Data Queue feature + * @cmd: Passthru command to use + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * @cdqid: Controller Data Queue ID (CDQID) + * @qfd: Get Controller Data Queue feature data buffer + * + * Initializes the passthru command buffer for the Get Features command with + * FID value %NVME_FEAT_FID_CTRL_DATA_QUEUE. + */ +static inline void +nvme_init_lm_get_features_ctrl_data_queue(struct nvme_passthru_cmd *cmd, + enum nvme_get_features_sel sel, __u16 cdqid, + struct nvme_lm_ctrl_data_queue_fid_data *qfd) +{ + nvme_init_get_features(cmd, NVME_FEAT_FID_CTRL_DATA_QUEUE, sel); + cmd->data_len = sizeof(*qfd); + cmd->addr = (__u64)(uintptr_t)qfd; + cmd->cdw11 = cdqid; +} + +/** + * nvme_identify() - Submit a generic Identify command + * @hdl: Transport handle for the controller. + * @nsid: Namespace ID (if applicable to the requested CNS). + * @csi: Command Set Identifier. + * @cns: Identify Controller or Namespace Structure (CNS) value, + * specifying the type of data to be returned. + * @data: Pointer to the buffer where the identification data will + * be stored. + * @len: Length of the data buffer in bytes. + * + * The generic wrapper for submitting an Identify command, allowing the host + * to specify any combination of Identify parameters. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_identify(struct nvme_transport_handle *hdl, __u32 nsid, enum nvme_csi csi, + enum nvme_identify_cns cns, void *data, __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_identify(&cmd, nsid, csi, cns, data, len); + + return nvme_submit_admin_passthru(hdl, &cmd); +} +/** + * nvme_identify_ctrl() - Submit an Identify Controller command + * @hdl: Transport handle for the controller. + * @id: Pointer to the buffer (&struct nvme_id_ctrl) where the + * controller identification data will be stored upon + * successful completion. + * + * Submits the Identify Controller command to retrieve the controller's + * capabilities and configuration data. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_identify_ctrl(struct nvme_transport_handle *hdl, + struct nvme_id_ctrl *id) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_identify_ctrl(&cmd, id); + + return nvme_submit_admin_passthru(hdl, &cmd); +} + +/** + * nvme_identify_active_ns_list() - Submit an Identify Active Namespace + * List command + * @hdl: Transport handle for the controller. + * @nsid: The Namespace ID to query + * @ns_list: Pointer to the buffer (&struct nvme_ns_list) where the + * active namespace list will be stored. + * + * Submits the Identify command to retrieve a list of active Namespace IDs. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_identify_active_ns_list(struct nvme_transport_handle *hdl, + __u32 nsid, struct nvme_ns_list *ns_list) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_identify_active_ns_list(&cmd, nsid, ns_list); + + return nvme_submit_admin_passthru(hdl, &cmd); +} + +/** + * nvme_identify_ns() - Submit an Identify Namespace command + * @hdl: Transport handle for the controller. + * @nsid: The Namespace ID to identify. + * @ns: Pointer to the buffer (&struct nvme_id_ns) where the namespace + * identification data will be stored. + * + * Submits the Identify command to retrieve the Namespace Identification + * data structure for a specified namespace. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ + +static inline int +nvme_identify_ns(struct nvme_transport_handle *hdl, + __u32 nsid, struct nvme_id_ns *ns) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_identify_ns(&cmd, nsid, ns); + + return nvme_submit_admin_passthru(hdl, &cmd); +} + +/** + * nvme_identify_csi_ns() - Submit a CSI-specific Identify Namespace command + * @hdl: Transport handle for the controller. + * @nsid: The Namespace ID to identify. + * @csi: The Command Set Identifier + * @uidx: The UUID Index for the command. + * @id_ns: Pointer to the buffer (@struct nvme_nvm_id_ns) where the + * CSI-specific namespace identification data will be stored. + * + * Submits the Identify command to retrieve Namespace Identification data + * specific to a Command Set Identifier (CSI). + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_identify_csi_ns(struct nvme_transport_handle *hdl, __u32 nsid, + enum nvme_csi csi, __u8 uidx, struct nvme_nvm_id_ns *id_ns) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_identify_csi_ns(&cmd, nsid, csi, uidx, id_ns); + + return nvme_submit_admin_passthru(hdl, &cmd); +} + +/** + * nvme_identify_uuid_list() - Submit an Identify UUID List command + * @hdl: Transport handle for the controller. + * @uuid_list: Pointer to the buffer (&struct nvme_id_uuid_list) where the + * UUID list will be stored. + * + * Submits the Identify command to retrieve a list of UUIDs associated + * with the controller. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_identify_uuid_list(struct nvme_transport_handle *hdl, + struct nvme_id_uuid_list *uuid_list) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_identify_uuid_list(&cmd, uuid_list); + + return nvme_submit_admin_passthru(hdl, &cmd); +} + +/** + * nvme_identify_csi_ns_user_data_format() - Submit an Identify CSI Namespace + * User Data Format command + * @hdl: Transport handle for the controller. + * @csi: Command Set Identifier. + * @fidx: Format Index, specifying which format entry to return. + * @uidx: The UUID Index for the command. + * @data: Pointer to the buffer where the format data will be stored. + * + * Submits the Identify command to retrieve a CSI-specific Namespace User + * Data Format data structure. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_identify_csi_ns_user_data_format(struct nvme_transport_handle *hdl, + enum nvme_csi csi, __u16 fidx, __u8 uidx, void *data) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_identify_csi_ns_user_data_format(&cmd, csi, fidx, uidx, data); + + return nvme_submit_admin_passthru(hdl, &cmd); +} + +/** + * nvme_identify_ns_granularity() - Submit an Identify Namespace Granularity + * List command + * @hdl: Transport handle for the controller. + * @gr_list: Pointer to the buffer (&struct nvme_id_ns_granularity_list) + * where the granularity list will be stored. + * + * Submits the Identify command to retrieve the Namespace Granularity List. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_identify_ns_granularity(struct nvme_transport_handle *hdl, + struct nvme_id_ns_granularity_list *gr_list) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_identify_ns_granularity(&cmd, gr_list); + + return nvme_submit_admin_passthru(hdl, &cmd); +} + +/** + * nvme_identify_ns_descs_list() - Submit an Identify Namespace ID Descriptor + * List command + * @hdl: Transport handle for the controller. + * @nsid: The Namespace ID to query. + * @descs: Pointer to the buffer (&struct nvme_ns_id_desc) where the + * descriptor list will be stored. + * + * Submits the Identify command to retrieve the Namespace ID Descriptor List + * for a specified namespace. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_identify_ns_descs_list(struct nvme_transport_handle *hdl, + __u32 nsid, struct nvme_ns_id_desc *descs) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_identify_ns_descs_list(&cmd, nsid, descs); + + return nvme_submit_admin_passthru(hdl, &cmd); +} + +/** + * nvme_zns_identify_ns() - Submit a ZNS-specific Identify Namespace command + * @hdl: Transport handle for the controller. + * @nsid: The Namespace ID to identify. + * @data: Pointer to the buffer (&struct nvme_zns_id_ns) where the ZNS + * namespace identification data will be stored. + * + * Submits the Identify command to retrieve the Zoned Namespace (ZNS) + * specific identification data structure for a specified namespace. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_zns_identify_ns(struct nvme_transport_handle *hdl, + __u32 nsid, struct nvme_zns_id_ns *data) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_zns_identify_ns(&cmd, nsid, data); + + return nvme_submit_admin_passthru(hdl, &cmd); +} + +/** + * nvme_get_log_simple() - Retrieve a log page using default parameters + * @hdl: Transport handle for the controller. + * @lid: Log Identifier, specifying the log page to retrieve + * (@enum nvme_cmd_get_log_lid). + * @data: Pointer to the buffer where the log page data will be stored. + * @len: Length of the data buffer in bytes. + * + * Submits the Get Log Page command using the common settings: + * NVME\_NSID\_ALL, Retain Asynchronous Event (RAE) set to false, + * and assuming the NVM Command Set. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_simple(struct nvme_transport_handle *hdl, + enum nvme_cmd_get_log_lid lid, void *data, __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log(&cmd, NVME_NSID_ALL, lid, NVME_CSI_NVM, data, len); + + return nvme_get_log(hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE); +} + +/** + * nvme_get_log_supported_log_pages() - Retrieve the Supported Log Pages + * Log Page + * @hdl: Transport handle for the controller. + * @log: Pointer to the buffer (@struct nvme_supported_log_pages) where + * the log page data will be stored. + * + * Submits the Get Log Page command specifically for the Supported Log Pages + * Log. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_supported_log_pages(struct nvme_transport_handle *hdl, + struct nvme_supported_log_pages *log) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_SUPPORTED_LOG_PAGES, + NVME_CSI_NVM, log, sizeof(*log)); + + return nvme_get_log(hdl, &cmd, false, sizeof(*log)); +} + + +/** + * nvme_get_log_error() - Retrieve the Error Information Log Page + * @hdl: Transport handle for the controller. + * @nsid: Namespace ID to request the log for (usually NVME_NSID_ALL). + * @nr_entries: The maximum number of error log entries to retrieve. + * @err_log: Pointer to the buffer (array of @struct nvme_error_log_page) + * where the log page data will be stored. + * + * This log page describes extended error information for a command that + * completed with error, or may report an error that is not specific to a + * particular command. The total size requested is determined by + * @nr_entries * sizeof(@struct nvme_error_log_page). + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_error(struct nvme_transport_handle *hdl, __u32 nsid, + unsigned int nr_entries, struct nvme_error_log_page *err_log) +{ + struct nvme_passthru_cmd cmd; + size_t len = sizeof(*err_log) * nr_entries; + + nvme_init_get_log(&cmd, nsid, NVME_LOG_LID_ERROR, + NVME_CSI_NVM, err_log, len); + + return nvme_get_log(hdl, &cmd, false, len); +} + +/** + * nvme_get_log_fw_slot() - Retrieve the Firmware Slot Information Log Page + * @hdl: Transport handle for the controller. + * @nsid: Namespace ID to request the log for (use NVME_NSID_ALL). + * @fw_log: Pointer to the buffer (@struct nvme_firmware_slot) where the log + * page data will be stored. + * + * This log page describes the firmware revision stored in each firmware slot + * supported. The firmware revision is indicated as an ASCII string. The log + * page also indicates the active slot number. + * + * This command is typically issued for the controller scope, thus using + * NVME_NSID_ALL. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_fw_slot(struct nvme_transport_handle *hdl, __u32 nsid, + struct nvme_firmware_slot *fw_log) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log(&cmd, nsid, NVME_LOG_LID_FW_SLOT, + NVME_CSI_NVM, fw_log, sizeof(*fw_log)); + + return nvme_get_log(hdl, &cmd, false, sizeof(*fw_log)); +} + +/** + * nvme_get_log_changed_ns_list() - Retrieve the Namespace Change Log Page + * @hdl: Transport handle for the controller. + * @nsid: Namespace ID to request the log for (use NVME_NSID_ALL). + * @ns_log: Pointer to the buffer (@struct nvme_ns_list) where the log + * page data will be stored. + * + * This log page describes namespaces attached to this controller that have + * changed since the last time the namespace was identified, been added, or + * deleted. + * + * This command is typically issued for the controller scope, thus using + * NVME_NSID_ALL. The Retain Asynchronous Event (RAE) is true to retain + * asynchronous events associated with the log page + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_changed_ns_list(struct nvme_transport_handle *hdl, __u32 nsid, + struct nvme_ns_list *ns_log) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log(&cmd, nsid, NVME_LOG_LID_CHANGED_NS, + NVME_CSI_NVM, ns_log, sizeof(*ns_log)); + + return nvme_get_log(hdl, &cmd, true, sizeof(*ns_log)); +} + +/** + * nvme_get_log_cmd_effects() - Retrieve the Command Effects Log Page + * @hdl: Transport handle for the controller. + * @csi: Command Set Identifier for the requested log page. + * @effects_log:Pointer to the buffer (@struct nvme_cmd_effects_log) where the + * log page data will be stored. + * + * This log page describes the commands that the controller supports and the + * effects of those commands on the state of the NVM subsystem. + * + * It automatically sets the Log Identifier (LID) and Retain Asynchronous + * Event (RAE) to false. This command is typically issued for the controller + * scope, thus using NVME_NSID_ALL. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_cmd_effects(struct nvme_transport_handle *hdl, + enum nvme_csi csi, struct nvme_cmd_effects_log *effects_log) +{ + struct nvme_passthru_cmd cmd; + size_t len = sizeof(*effects_log); + + nvme_init_get_log_cmd_effects(&cmd, csi, effects_log); + + return nvme_get_log(hdl, &cmd, false, len); +} + +/** + * nvme_get_log_device_self_test() - Retrieve the Device Self-Test Log Page + * @hdl: Transport handle for the controller. + * @log: Pointer to the buffer (@struct nvme_self_test_log) where the log + * page data will be stored. + * + * This log page indicates the status of an in-progress self-test and the + * percent complete of that operation, and the results of the previous 20 + * self-test operations. + * + * It automatically sets the Log Identifier (LID) and Retain Asynchronous + * Event (RAE) to false. This command is typically issued for the controller + * scope, thus using NVME_NSID_ALL. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_device_self_test(struct nvme_transport_handle *hdl, + struct nvme_self_test_log *log) +{ + struct nvme_passthru_cmd cmd; + size_t len = sizeof(*log); + + nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_DEVICE_SELF_TEST, + NVME_CSI_NVM, log, len); + + return nvme_get_log(hdl, &cmd, false, len); +} + +/** + * nvme_get_log_create_telemetry_host_mcda() - Create the Host Initiated + * Telemetry Log + * @hdl: Transport handle for the controller. + * @mcda: Maximum Created Data Area. Specifies the maximum amount of data + * that may be returned by the controller. + * @log: Pointer to the buffer (@struct nvme_telemetry_log) where the log + * page data will be stored. + * + * Submits the Get Log Page command to initiate the creation of a Host Initiated + * Telemetry Log. It sets the Log Identifier (LID) to Telemetry Host and + * includes the Maximum Created Data Area (MCDA) in the Log Specific Parameter + * (LSP) field along with the Create bit. + * + * It automatically sets Retain Asynchronous Event (RAE) to false. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_create_telemetry_host_mcda(struct nvme_transport_handle *hdl, + enum nvme_telemetry_da mcda, struct nvme_telemetry_log *log) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_create_telemetry_host_mcda(&cmd, mcda, log); + + return nvme_get_log(hdl, &cmd, false, sizeof(*log)); +} + +/** + * nvme_get_log_create_telemetry_host() - Create the Host Initiated Telemetry + * Log (Controller Determined Size) + * @hdl: Transport handle for the controller. + * @log: Pointer to the buffer (@struct nvme_telemetry_log) where the log + * page data will be stored. + * + * Submits the Get Log Page command to initiate the creation of a Host Initiated + * Telemetry Log. This is a convenience wrapper that automatically uses the + * Controller Determined size for the Maximum Created Data Area (MCDA). + * + * It automatically sets Retain Asynchronous Event (RAE) to false. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_create_telemetry_host(struct nvme_transport_handle *hdl, + struct nvme_telemetry_log *log) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_create_telemetry_host(&cmd, log); + + return nvme_get_log(hdl, &cmd, false, sizeof(*log)); +} + +/** + * nvme_get_log_telemetry_host() - Retrieve the Host-Initiated + * Telemetry Log Page (Retain) + * @hdl: Transport handle for the controller. + * @lpo: Offset (in bytes) into the telemetry data to start the + * retrieval. + * @log: Pointer to the buffer where the log page data will be stored. + * @len: Length of the buffer provided in @log. + * + * Submits the Get Log Page command to retrieve a previously captured + * Host-Initiated Telemetry Log, starting at a specified offset (@lpo). The Log + * Specific Parameter (LSP) field is set to indicate the capture should be + * retained (not deleted after read). + * + * It automatically sets the Log Identifier (LID) and Retain Asynchronous Event + * (RAE) to false. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_telemetry_host(struct nvme_transport_handle *hdl, + __u64 lpo, void *log, __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_telemetry_host(&cmd, lpo, log, len); + + return nvme_get_log(hdl, &cmd, false, len); +} + +/** + * nvme_get_log_telemetry_ctrl() - Retrieve the Controller-Initiated + * Telemetry Log Page + * @hdl: Transport handle for the controller. + * @rae: Retain asynchronous events + * @lpo: Offset (in bytes) into the telemetry data to start the + * retrieval. + * @log: Pointer to the buffer where the log page data will be stored. + * @len: Length of the buffer provided in @log. + * + * Submits the Get Log Page command specifically for the Controller-Initiated + * Telemetry Log, allowing retrieval of data starting at a specified offset + * (@lpo). + * + * It automatically sets the Log Identifier (LID). + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_telemetry_ctrl(struct nvme_transport_handle *hdl, bool rae, + __u64 lpo, void *log, __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_telemetry_ctrl(&cmd, lpo, log, len); + + return nvme_get_log(hdl, &cmd, rae, len); +} + +/** + * nvme_get_log_endurance_group() - Retrieve the Endurance Group Log Page + * @hdl: Transport handle for the controller. + * @endgid: Starting Endurance Group Identifier (ENDGID) to return in + * the list. + * @log: Pointer to the buffer (@struct nvme_endurance_group_log) where + * the log page data will be stored. + * + * This log page indicates if an Endurance Group Event has occurred for a + * particular Endurance Group. The ENDGID is placed in the Log Specific + * Identifier (LSI) field of the Get Log Page command. + * + * It automatically sets the Log Identifier (LID) and Retain Asynchronous + * Event (RAE) to false. This command is typically issued for the controller + * scope, thus using NVME_NSID_NONE. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_endurance_group(struct nvme_transport_handle *hdl, + __u16 endgid, struct nvme_endurance_group_log *log) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_endurance_group(&cmd, endgid, log); + + return nvme_get_log(hdl, &cmd, false, sizeof(*log)); +} + +/** + * nvme_get_log_predictable_lat_nvmset() - Retrieve the Predictable Latency + * Per NVM Set Log Page + * @hdl: Transport handle for the controller. + * @nvmsetid: The NVM Set Identifier (NVMSETID) for which to retrieve the log. + * @log: Pointer to the buffer (@struct nvme_nvmset_predictable_lat_log) + * where the log page data will be stored. + * + * Submits the Get Log Page command specifically for the Predictable Latency Per + * NVM Set Log. The NVMSETID is placed in the Log Specific Identifier (LSI) + * field of the command. + * + * It automatically sets the Log Identifier (LID) and Retain Asynchronous + * Event (RAE) to false. This command is typically issued for the controller + * scope, thus using NVME_NSID_NONE. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_predictable_lat_nvmset(struct nvme_transport_handle *hdl, + __u16 nvmsetid, struct nvme_nvmset_predictable_lat_log *log) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_predictable_lat_nvmset(&cmd, nvmsetid, log); + + return nvme_get_log(hdl, &cmd, false, sizeof(*log)); +} + +/** + * nvme_get_log_predictable_lat_event() - Retrieve the Predictable Latency Event + * Aggregate Log Page + * @hdl: Transport handle for the controller. + * @rae: Retain asynchronous events + * @lpo: Offset (in bytes) into the log page data to start the retrieval. + * @log: Pointer to the buffer where the log page data will be stored. + * @len: Length of the buffer provided in @log. + * + * Submits the Get Log Page command specifically for the Predictable Latency + * Event Aggregate Log, allowing retrieval of data starting at a specified + * offset (@lpo). + * + * It automatically sets the Log Identifier (LID) to + * NVME_LOG_LID_PREDICTABLE_LAT_AGG. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_predictable_lat_event(struct nvme_transport_handle *hdl, + bool rae, __u64 lpo, void *log, __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_predictable_lat_event(&cmd, lpo, log, len); + + return nvme_get_log(hdl, &cmd, rae, len); +} + +/** + * nvme_get_log_fdp_configurations() - Retrieve the Flexible Data Placement + * (FDP) Configurations Log Page + * @hdl: Transport handle for the controller. + * @egid: Endurance Group Identifier (EGID) to return in the + * list (used in LSI). + * @lpo: Offset (in bytes) into the log page data to start the retrieval. + * @log: Pointer to the buffer where the log page data will be stored. + * @len: Length of the buffer provided in @log. + * + * Submits the Get Log Page command specifically for the FDP Configurations Log. + * The EGID is placed in the Log Specific Identifier (LSI) field. + * + * It automatically sets the Log Identifier (LID) and Retain Asynchronous + * Event (RAE) to false. This command is typically issued for the controller + * scope, thus using NVME_NSID_NONE. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_fdp_configurations(struct nvme_transport_handle *hdl, + __u16 egid, __u64 lpo, void *log, __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_fdp_configurations(&cmd, egid, lpo, log, len); + + return nvme_get_log(hdl, &cmd, false, len); +} + +/** + * nvme_get_log_reclaim_unit_handle_usage() - Retrieve the FDP Reclaim Unit + * Handle (RUH) Usage Log Page + * @hdl: Transport handle for the controller. + * @egid: Endurance Group Identifier (EGID) (used in LSI). + * @lpo: Offset (in bytes) into the log page data to start the retrieval. + * @log: Pointer to the buffer where the log page data will be stored. + * @len: Length of the buffer provided in @log. + * + * Submits the Get Log Page command specifically for the FDP Reclaim Unit Handle + * Usage Log. The EGID is placed in the Log Specific Identifier (LSI) field. + * + * It automatically sets the Log Identifier (LID) and Retain Asynchronous + * Event (RAE) to false. This command is typically issued for the controller + * scope, thus using NVME_NSID_NONE. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_reclaim_unit_handle_usage(struct nvme_transport_handle *hdl, + __u16 egid, __u64 lpo, void *log, __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_reclaim_unit_handle_usage(&cmd, egid, lpo, log, len); + + return nvme_get_log(hdl, &cmd, false, len); +} + +/** + * nvme_get_log_fdp_stats() - Retrieve the Flexible Data Placement (FDP) + * Statistics Log Page + * @hdl: Transport handle for the controller. + * @egid: Endurance Group Identifier (EGID) (used in LSI). + * @lpo: Offset (in bytes) into the log page data to start the retrieval. + * @log: Pointer to the buffer where the log page data will be stored. + * @len: Length of the buffer provided in @log. + * + * Submits the Get Log Page command specifically for the FDP Statistics Log. + * The EGID is placed in the Log Specific Identifier (LSI) field. + * + * It automatically sets the Log Identifier (LID) and Retain Asynchronous + * Event (RAE) to false. This command is typically issued for the controller + * scope, thus using NVME_NSID_NONE. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_fdp_stats(struct nvme_transport_handle *hdl, + __u16 egid, __u64 lpo, void *log, __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_fdp_stats(&cmd, egid, lpo, log, len); + + return nvme_get_log(hdl, &cmd, false, len); +} + +/** + * nvme_get_log_fdp_events() - Retrieve the Flexible Data Placement (FDP) + * Events Log Page + * @hdl: Transport handle for the controller. + * @egid: Endurance Group Identifier (EGID) (used in LSI). + * @host_events:Whether to report host-initiated events (true) or + * controller-initiated events (false). + * @lpo: Offset (in bytes) into the log page data to start the retrieval. + * @log: Pointer to the buffer where the log page data will be stored. + * @len: Length of the buffer provided in @log. + * + * Submits the Get Log Page command specifically for the FDP Events Log. + * The EGID is placed in the Log Specific Identifier (LSI) field, and the + * @host_events flag is used to set the Log Specific Parameter (LSP) field. + * + * It automatically sets the Log Identifier (LID) and Retain Asynchronous + * Event (RAE) to false. This command is typically issued for the controller + * scope, thus using NVME_NSID_NONE. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_fdp_events(struct nvme_transport_handle *hdl, + __u16 egid, bool host_events, __u64 lpo, void *log, __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_fdp_events(&cmd, egid, host_events, lpo, log, len); + + return nvme_get_log(hdl, &cmd, false, len); +} + +/** + * nvme_get_log_ana() - Retrieve the Asymmetric Namespace Access (ANA) Log Page + * @hdl: Transport handle for the controller. + * @rae: Retain asynchronous events + * @lsp: Log specific parameter, see &enum nvme_get_log_ana_lsp. + * @lpo: Offset (in bytes) into the log page data to start the retrieval. + * @log: Pointer to the buffer where the log page data will be stored. + * @len: Length of the buffer provided in @log. + * + * This log consists of a header describing the log and descriptors containing + * the ANA information for groups that contain namespaces attached to the + * controller. The @lsp parameter is placed in the Log Specific Parameter field + * of the command. + * + * See &struct nvme_ana_log for the definition of the returned structure. + * + * It automatically sets the Log Identifier (LID) to NVME_LOG_LID_ANA. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_ana(struct nvme_transport_handle *hdl, bool rae, + enum nvme_log_ana_lsp lsp, __u64 lpo, void *log, __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_ana(&cmd, lsp, lpo, log, len); + + return nvme_get_log(hdl, &cmd, rae, len); +} + +/** + * nvme_get_log_ana_groups() - Retrieve the Asymmetric Namespace Access (ANA) + * Groups Only Log Page + * @hdl: Transport handle for the controller. + * @rae: Retain asynchronous events + * @log: Pointer to the buffer (@struct nvme_ana_log) where the log page + * data will be stored. + * @len: Length of the buffer provided in @log. + * + * This function retrieves only the ANA Group Descriptors by setting the Log + * Specific Parameter (LSP) field to NVME_LOG_ANA_LSP_RGO_GROUPS_ONLY. It is a + * convenience wrapper around nvme_get_log_ana, using a Log Page Offset (LPO) of + * 0. + * + * See &struct nvme_ana_log for the definition of the returned structure. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_ana_groups(struct nvme_transport_handle *hdl, bool rae, + struct nvme_ana_log *log, __u32 len) +{ + return nvme_get_log_ana(hdl, rae, NVME_LOG_ANA_LSP_RGO_GROUPS_ONLY, + 0, log, len); +} + +/** + * nvme_get_log_lba_status() - Retrieve the LBA Status Log Page + * @hdl: Transport handle for the controller. + * @rae: Retain asynchronous events + * @lpo: Offset (in bytes) into the log page data to start the retrieval. + * @log: Pointer to the buffer where the log page data will be stored. + * @len: Length of the buffer provided in @log. + * + * Submits the Get Log Page command specifically for the LBA Status Log. + * + * It automatically sets the Log Identifier (LID) to NVME_LOG_LID_LBA_STATUS. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_lba_status(struct nvme_transport_handle *hdl, + bool rae, __u64 lpo, void *log, __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_lba_status(&cmd, lpo, log, len); + + return nvme_get_log(hdl, &cmd, rae, len); +} + +/** + * nvme_get_log_endurance_grp_evt() - Retrieve the Endurance Group Event + * Aggregate Log Page + * @hdl: Transport handle for the controller. + * @rae: Retain asynchronous events + * @lpo: Offset (in bytes) into the log page data to start the retrieval. + * @log: Pointer to the buffer where the log page data will be stored. + * @len: Length of the buffer provided in @log. + * + * Submits the Get Log Page command specifically for the Endurance Group Event + * Aggregate Log, allowing retrieval of data starting at a specified offset + * (@lpo). + * + * It automatically sets the Log Identifier (LID) to + * NVME_LOG_LID_ENDURANCE_GRP_EVT. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_endurance_grp_evt(struct nvme_transport_handle *hdl, + bool rae, __u64 lpo, void *log, __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_endurance_grp_evt(&cmd, lpo, log, len); + + return nvme_get_log(hdl, &cmd, rae, len); +} + +/** + * nvme_get_log_fid_supported_effects() - Retrieve the Feature Identifiers + * Supported and Effects Log Page + * @hdl: Transport handle for the controller. + * @csi: Command set identifier, see &enum nvme_csi for known values + * @log: Pointer to the buffer (@struct nvme_fid_supported_effects_log) + * where the log page data will be stored. + * + * Submits the Get Log Page command specifically for the Feature Identifiers + * Supported and Effects Log. It automatically sets the Log Identifier (LID). + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_fid_supported_effects(struct nvme_transport_handle *hdl, + enum nvme_csi csi, struct nvme_fid_supported_effects_log *log) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_fid_supported_effects(&cmd, csi, log); + + return nvme_get_log(hdl, &cmd, false, sizeof(*log)); +} + +/** + * nvme_get_log_mi_cmd_supported_effects() - Retrieve the Management Interface + * (MI) Commands Supported and Effects Log Page + * @hdl: Transport handle for the controller. + * @log: Pointer to the buffer + * (@struct nvme_mi_cmd_supported_effects_log) where the log page + * data will be stored. + * + * Submits the Get Log Page command specifically for the MI Commands Supported + * and Effects Log. It automatically sets the Log Identifier (LID). This command + * is typically issued with a namespace ID of 0xFFFFFFFF (NVME_NSID_NONE). + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_mi_cmd_supported_effects(struct nvme_transport_handle *hdl, + struct nvme_mi_cmd_supported_effects_log *log) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_mi_cmd_supported_effects(&cmd, log); + + return nvme_get_log(hdl, &cmd, false, sizeof(*log)); +} + +/** + * nvme_get_log_boot_partition() - Retrieve the Boot Partition Log Page + * @hdl: Transport handle for the controller. + * @lsp: The Log Specific Parameter (LSP) field for this Log + * Identifier (LID). + * @part: Pointer to the buffer (@struct nvme_boot_partition) where + * the log page data will be stored. + * @len: Length of the buffer provided in @part. + * + * Submits the Get Log Page command specifically for the Boot Partition Log. + * The LSP field is set based on the @lsp parameter. + * + * It automatically sets the Log Identifier (LID) to + * NVME_LOG_LID_BOOT_PARTITION. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_boot_partition(struct nvme_transport_handle *hdl, + __u8 lsp, struct nvme_boot_partition *part, __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_boot_partition(&cmd, lsp, part, len); + + return nvme_get_log(hdl, &cmd, false, len); +} + +/** + * nvme_get_log_rotational_media_info() - Retrieve the Rotational Media + * Information Log Page + * @hdl: Transport handle for the controller. + * @endgid: The Endurance Group Identifier (ENDGID) to retrieve the + * log for (used in LSI). + * @log: Pointer to the buffer (@struct nvme_rotational_media_info_log) + * where the log page data will be stored. + * @len: Length of the buffer provided in @log. + * + * Submits the Get Log Page command specifically for the Rotational Media + * Information Log. The ENDGID is placed in the Log Specific Identifier (LSI) + * field of the command. + * + * It automatically sets the Log Identifier (LID) and Retain Asynchronous + * Event (RAE) to false. This command is typically issued for the controller + * scope, thus using NVME_NSID_NONE. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_rotational_media_info(struct nvme_transport_handle *hdl, + __u16 endgid, struct nvme_rotational_media_info_log *log, + __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_rotational_media_info(&cmd, endgid, log, len); + + return nvme_get_log(hdl, &cmd, false, len); +} + +/** + * nvme_get_log_dispersed_ns_participating_nss() - Retrieve the Dispersed + * Namespace Participating NVM Subsystems Log Page + * @hdl: Transport handle for the controller. + * @nsid: Namespace ID to request the log for. + * @log: Pointer to the buffer + * (@struct nvme_dispersed_ns_participating_nss_log) + * where the log page data will be stored. + * @len: Length of the buffer provided in @log. + * + * Submits the Get Log Page command specifically for the Dispersed Namespace + * Participating NVM Subsystems Log. It automatically sets the Log Identifier + * (LID) and Retain Asynchronous Event (RAE) to false. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_dispersed_ns_participating_nss(struct nvme_transport_handle *hdl, + __u32 nsid, struct nvme_dispersed_ns_participating_nss_log *log, + __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_dispersed_ns_participating_nss(&cmd, nsid, log, len); + + return nvme_get_log(hdl, &cmd, false, len); +} + +/** + * nvme_get_log_mgmt_addr_list() - Retrieve the Management Address List Log Page + * @hdl: Transport handle for the controller. + * @log: Pointer to the buffer (@struct nvme_mgmt_addr_list_log) where + * the log page data will be stored. + * @len: Length of the buffer provided in @log. + * + * Submits the Get Log Page command specifically for the Management Address List + Log. + * + * It automatically sets the Log Identifier (LID) to + * NVME_LOG_LID_MGMT_ADDR_LIST, Retain Asynchronous Event (RAE) to false, and + * uses NVME_NSID_NONE. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_mgmt_addr_list(struct nvme_transport_handle *hdl, + struct nvme_mgmt_addr_list_log *log, __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_mgmt_addr_list(&cmd, log, len); + + return nvme_get_log(hdl, &cmd, false, len); +} + +/** + * nvme_get_log_phy_rx_eom() - Retrieve the Physical Interface Receiver Eye + * Opening Measurement Log Page + * @hdl: Transport handle for the controller. + * @lsp: Log Specific Parameter (LSP), which controls the action + * and measurement quality. + * @controller: Target Controller ID (used in LSI). + * @log: Pointer to the buffer (@struct nvme_phy_rx_eom_log) where + * the log page data will be stored. + * @len: Length of the buffer provided in @log. + * + * Submits the Get Log Page command specifically for the Physical Interface + * Receiver Eye Opening Measurement Log. The Controller ID is placed in the + * Log Specific Identifier (LSI) field. + * + * It automatically sets the Log Identifier (LID) to NVME_LOG_LID_PHY_RX_EOM, + * and Retain Asynchronous Event (RAE) to false. This command is typically + * issued for the controller scope, thus using NVME_NSID_NONE. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_phy_rx_eom(struct nvme_transport_handle *hdl, + __u8 lsp, __u16 controller, struct nvme_phy_rx_eom_log *log, + __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_phy_rx_eom(&cmd, lsp, controller, log, len); + + return nvme_get_log(hdl, &cmd, false, len); +} + +/** + * nvme_get_log_reachability_groups() - Retrieve the Reachability Groups + * Log Page + * @hdl: Transport handle for the controller. + * @nsid: Namespace ID to request the log for. + * @rgo: Return Groups Only. Set to true to return only the Reachability + * Group Descriptors. + * @log: Pointer to the buffer (@struct nvme_reachability_groups_log) + * where the log page data will be stored. + * @len: Length of the buffer provided in @log. + * + * Submits the Get Log Page command specifically for the Reachability Groups + * Log. The @rgo parameter is placed in the Log Specific Parameter (LSP) field. + * + * It automatically sets the Log Identifier (LID) to + * NVME_LOG_LID_REACHABILITY_GROUPS. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_reachability_groups(struct nvme_transport_handle *hdl, + __u32 nsid, bool rgo, struct nvme_reachability_groups_log *log, + __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_reachability_groups(&cmd, rgo, log, len); + + return nvme_get_log(hdl, &cmd, false, len); +} + +/** + * nvme_get_log_reachability_associations() - Retrieve the Reachability + * Associations Log Page + * @hdl: Transport handle for the controller. + * @rae: Retain asynchronous events + * @rao: Return Associations Only. Set to true to return only the + * Reachability Association Descriptors. + * @log: Pointer to the buffer + * (@struct nvme_reachability_associations_log) where the log + * page data will be stored. + * @len: Length of the buffer provided in @log. + * + * Submits the Get Log Page command specifically for the Reachability + * Associations Log. The @rao parameter is placed in the Log Specific Parameter + * (LSP) field. + * + * It automatically sets the Log Identifier (LID) to + * NVME_LOG_LID_REACHABILITY_ASSOCIATIONS. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_reachability_associations(struct nvme_transport_handle *hdl, + bool rae, bool rao, + struct nvme_reachability_associations_log *log, __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_reachability_associations(&cmd, rao, log, len); + + return nvme_get_log(hdl, &cmd, rae, len); +} + +/** + * nvme_get_log_changed_alloc_ns_list() - Retrieve the Changed Allocated + * Namespace List Log Page + * @hdl: Transport handle for the controller. + * @log: Pointer to the buffer (@struct nvme_ns_list) where the log page + * data will be stored. + * @len: Length of the buffer provided in @log. + * + * Submits the Get Log Page command specifically for the Changed Allocated + * Namespace List Log. + * + * It automatically sets the Log Identifier (LID) to + * NVME_LOG_LID_CHANGED_ALLOC_NS_LIST. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_changed_alloc_ns_list(struct nvme_transport_handle *hdl, + struct nvme_ns_list *log, __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_changed_ns(&cmd, log); + + return nvme_get_log(hdl, &cmd, true, len); +} + +/** + * nvme_get_log_discovery() - Retrieve the Discovery Log Page + * @hdl: Transport handle for the controller. + * @lpo: Offset (in bytes) into the log page data to start the retrieval. + * @log: Pointer to the buffer where the log page data will be stored. + * @len: Length of the buffer provided in @log. + * + * Submits the Get Log Page command specifically for the Discovery Log. + * Supported only by NVMe-oF Discovery controllers, returning discovery records. + * + * It automatically sets the Log Identifier (LID) to NVME_LOG_LID_DISCOVERY. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_discovery(struct nvme_transport_handle *hdl, + __u64 lpo, __u32 len, void *log) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_discovery(&cmd, lpo, log, len); + + return nvme_get_log(hdl, &cmd, false, len); +} + +/** + * nvme_get_log_host_discovery() - Retrieve the Host Discovery Log Page + * @hdl: Transport handle for the controller. + * @rae: Retain asynchronous events + * @allhoste: All Host Entries. Set to true to report all host entries. + * @log: Pointer to the buffer (@struct nvme_host_discover_log) + * where the log page data will be stored. + * @len: Length of the buffer provided in @log. + * + * Submits the Get Log Page command specifically for the Host Discovery Log. + * The @allhoste parameter is placed in the Log Specific Parameter (LSP) field. + * + * It automatically sets the Log Identifier (LID) to + * NVME_LOG_LID_HOST_DISCOVERY. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_host_discovery(struct nvme_transport_handle *hdl, + bool rae, bool allhoste, + struct nvme_host_discover_log *log, __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_host_discovery(&cmd, allhoste, log, len); + + return nvme_get_log(hdl, &cmd, false, len); +} + +/** + * nvme_get_log_ave_discovery() - Retrieve the Asynchronous Event + * Group (AVE) Discovery Log Page + * @hdl: Transport handle for the controller. + * @rae: Retain asynchronous events + * @log: Pointer to the buffer (@struct nvme_ave_discover_log) where + * the log page data will be stored. + * @len: Length of the buffer provided in @log. + * + * Submits the Get Log Page command specifically for the Asynchronous Event + * Group (AVE) Discovery Log. It automatically sets the Log Identifier (LID). + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_ave_discovery(struct nvme_transport_handle *hdl, + bool rae, struct nvme_ave_discover_log *log, __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_ave_discovery(&cmd, log, len); + + return nvme_get_log(hdl, &cmd, rae, len); +} + +/** + * nvme_get_log_pull_model_ddc_req() - Retrieve the Pull Model DDC Request + * Log Page + * @hdl: Transport handle for the controller. + * @rae: Retain asynchronous events + * @log: Pointer to the buffer (@struct nvme_pull_model_ddc_req_log) + * where the log page data will be stored. + * @len: Length of the buffer provided in @log. + * + * Submits the Get Log Page command specifically for the Pull Model DDC Request + * Log. It automatically sets the Log Identifier (LID). + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_pull_model_ddc_req(struct nvme_transport_handle *hdl, + bool rae, struct nvme_pull_model_ddc_req_log *log, __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_pull_model_ddc_req(&cmd, log, len); + + return nvme_get_log(hdl, &cmd, rae, len); +} + +/** + * nvme_get_log_media_unit_stat() - Retrieve the Media Unit Status Log Page + * @hdl: Transport handle for the controller. + * @domid: The Domain Identifier (DOMID) selection, if supported + * (used in LSI). + * @mus: Pointer to the buffer (@struct nvme_media_unit_stat_log) + * where the log page data will be stored. + * + * Submits the Get Log Page command specifically for the Media Unit Status Log. + * The DOMID is placed in the Log Specific Identifier (LSI) field of the + * command. + * + * It automatically sets the Log Identifier (LID) to + * NVME_LOG_LID_MEDIA_UNIT_STATUS, and Retain Asynchronous Event (RAE) to false. + * This command is typically issued for the controller scope, thus using + * NVME_NSID_NONE. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_media_unit_stat(struct nvme_transport_handle *hdl, + __u16 domid, struct nvme_media_unit_stat_log *mus) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_media_unit_stat(&cmd, domid, mus); + + return nvme_get_log(hdl, &cmd, false, sizeof(*mus)); +} + +/** + * nvme_get_log_support_cap_config_list() - Retrieve the Supported Capacity + * Configuration List Log Page + * @hdl: Transport handle for the controller. + * @domid: The Domain Identifier (DOMID) selection, if + * supported (used in LSI). + * @cap: Pointer to the buffer + * (@struct nvme_supported_cap_config_list_log) where the log + * page data will be stored. + * + * Submits the Get Log Page command specifically for the Supported Capacity + * Configuration List Log. The DOMID is placed in the Log Specific Identifier + * (LSI) field of the command. + * + * It automatically sets the Log Identifier (LID) to + * NVME_LOG_LID_SUPPORTED_CAP_CONFIG_LIST, and Retain Asynchronous Event (RAE) + * to false. This command is typically issued for the controller scope, thus + * using NVME_NSID_NONE. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_support_cap_config_list(struct nvme_transport_handle *hdl, + __u16 domid, struct nvme_supported_cap_config_list_log *cap) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_support_cap_config_list(&cmd, domid, cap); + + return nvme_get_log(hdl, &cmd, false, sizeof(*cap)); +} + +/** + * nvme_get_log_reservation() - Retrieve the Reservation Notification Log Page + * @hdl: Transport handle for the controller. + * @log: Pointer to the buffer (@struct nvme_resv_notification_log) + * where the log page data will be stored. + * + * Submits the Get Log Page command specifically for the Reservation + * Notification Log. It automatically sets the Log Identifier (LID). + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_reservation(struct nvme_transport_handle *hdl, + struct nvme_resv_notification_log *log) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_reservation(&cmd, log); + + return nvme_get_log(hdl, &cmd, false, sizeof(*log)); +} + +/** + * nvme_get_log_sanitize() - Retrieve the Sanitize Status Log Page + * @hdl: Transport handle for the controller. + * @rae: Retain asynchronous events + * @log: Pointer to the buffer (@struct nvme_sanitize_log_page) + * where the log page data will be stored. + * + * Submits the Get Log Page command specifically for the Sanitize Status Log. + * The log page reports sanitize operation time estimates and information about + * the most recent sanitize operation. + * + * It automatically sets the Log Identifier (LID) to NVME_LOG_LID_SANITIZE. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_sanitize(struct nvme_transport_handle *hdl, + bool rae, struct nvme_sanitize_log_page *log) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_sanitize(&cmd, log); + + return nvme_get_log(hdl, &cmd, rae, sizeof(*log)); +} + +/** + * nvme_get_log_zns_changed_zones() - Retrieve the ZNS Changed Zones Log Page + * @hdl: Transport handle for the controller. + * @nsid: Namespace ID to request the log for. + * @rae: Retain asynchronous events + * @log: Pointer to the buffer (@struct nvme_zns_changed_zone_log) + * where the log page data will be stored. + * + * Submits the Get Log Page command specifically for the ZNS Changed Zones Log. + * This log lists zones that have changed state due to an exceptional event. + * + * It automatically sets the Log Identifier (LID) to + * NVME_LOG_LID_ZNS_CHANGED_ZONES. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_zns_changed_zones(struct nvme_transport_handle *hdl, + __u32 nsid, bool rae, struct nvme_zns_changed_zone_log *log) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_zns_changed_zones(&cmd, nsid, log); + + return nvme_get_log(hdl, &cmd, rae, sizeof(*log)); +} + +/** + * nvme_get_log_persistent_event() - Retrieve the Persistent Event Log Page + * @hdl: Transport handle for the controller. + * @action: Action the controller should take during processing this + * command, see &enum nvme_pevent_log_action (used in LSP). + * @pevent_log: Pointer to the buffer where the log page data will be stored. + * @len: Length of the buffer provided in @pevent_log. + * + * Submits the Get Log Page command specifically for the Persistent Event Log. + * The @action parameter is placed in the Log Specific Parameter (LSP) field. + * + * It automatically sets the Log Identifier (LID) to + * NVME_LOG_LID_PERSISTENT_EVENT and Retain Asynchronous Event (RAE) to false. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_persistent_event(struct nvme_transport_handle *hdl, + enum nvme_pevent_log_action action, void *pevent_log, __u32 len) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_persistent_event(&cmd, action, pevent_log, len); + + /* + * Call the generic log execution function. + * The data length is determined by the 'len' parameter. + */ + return nvme_get_log(hdl, &cmd, false, len); +} + +/** + * nvme_get_log_lockdown() - Retrieve the Command and Feature Lockdown Log Page + * @hdl: Transport handle for the controller. + * @cnscp: Contents and Scope (CNSCP) of Command and Feature + * Identifier Lists (used in LSP). + * @log: Pointer to the buffer (@struct nvme_lockdown_log) where the log + * page data will be stored. + * + * Submits the Get Log Page command specifically for the Command and Feature + * Lockdown Log. The @cnscp parameter is placed in the Log Specific Parameter + * (LSP) field. + * + * It automatically sets the Log Identifier (LID) to + * NVME_LOG_LID_CMD_AND_FEAT_LOCKDOWN and Retain Asynchronous Event (RAE) to + * false. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_lockdown(struct nvme_transport_handle *hdl, + __u8 cnscp, struct nvme_lockdown_log *log) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_lockdown(&cmd, cnscp, log); + + return nvme_get_log(hdl, &cmd, false, sizeof(*log)); +} + +/** + * nvme_get_log_smart() - Retrieve the SMART / Health Information Log Page + * @hdl: Transport handle for the controller. + * @nsid: Namespace ID to request the log for. + * @smart_log: Pointer to the buffer (@struct nvme_smart_log) where the log + * page data will be stored. + * + * Submits the Get Log Page command specifically for the SMART / Health + * Information Log. It automatically sets the Log Identifier (LID) and + * Retain Asynchronous Event (RAE) to false. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_log_smart(struct nvme_transport_handle *hdl, + __u32 nsid, struct nvme_smart_log *smart_log) +{ + struct nvme_passthru_cmd cmd; + + nvme_init_get_log_smart(&cmd, nsid, smart_log); + + return nvme_get_log(hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE); +} + +/** + * nvme_set_features() - Submit a generic Set Features command + * @hdl: Transport handle for the controller. + * @nsid: Namespace ID sto apply the feature to. + * @fid: Feature Identifier (FID) to be set. + * @sv: Save Value (SV): If true, the feature value persists + * across power states. + * @cdw11: Command Dword 11 parameter (feature-specific). + * @cdw12: Command Dword 12 parameter (feature-specific). + * @cdw13: Command Dword 13 parameter (feature-specific). + * @uidx: UUID Index (UIDX) for the command, encoded into cdw14 + * @cdw15: Command Dword 15 parameter (feature-specific). + * @data: Pointer to the data buffer to transfer (if applicable). + * @len: Length of the data buffer in bytes. + * @result: The command completion result (CQE dword0) on success. + * + * Submits the Set Features command, allowing all standard command + * fields (cdw11-cdw15) and data buffer fields to be specified directly. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_set_features(struct nvme_transport_handle *hdl, __u32 nsid, __u8 fid, + bool sv, __u32 cdw11, __u32 cdw12, __u32 cdw13, __u8 uidx, + __u32 cdw15, void *data, __u32 len, __u64 *result) +{ + struct nvme_passthru_cmd cmd; + int err; + + nvme_init_set_features(&cmd, fid, sv); + cmd.nsid = nsid; + cmd.cdw11 = cdw11; + cmd.cdw12 = cdw12; + cmd.cdw13 = cdw13; + cmd.cdw14 = NVME_FIELD_ENCODE(uidx, + NVME_SET_FEATURES_CDW14_UUID_SHIFT, + NVME_SET_FEATURES_CDW14_UUID_MASK); + cmd.cdw15 = cdw15; + cmd.data_len = len; + cmd.addr = (__u64)(uintptr_t)data; + + err = nvme_submit_admin_passthru(hdl, &cmd); + if (result) + *result = cmd.result; + return err; +} + +/** + * nvme_set_features_simple() - Submit a Set Features command using only cdw11 + * @hdl: Transport handle for the controller. + * @nsid: Namespace ID to apply the feature to. + * @fid: Feature Identifier (FID) to be set. + * @sv: Save Value (SV): If true, the feature value persists across + * power states. + * @cdw11: Command Dword 11 parameter (feature-specific value). + * @result: The command completion result (CQE dword0) on success. + * + * Submits the Set Features command for features that only require + * parameters in cdw11. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_set_features_simple(struct nvme_transport_handle *hdl, + __u32 nsid, __u8 fid, bool sv, __u32 cdw11, __u64 *result) +{ + struct nvme_passthru_cmd cmd; + int err; + + nvme_init_set_features(&cmd, fid, sv); + cmd.nsid = nsid; + cmd.cdw11 = cdw11; + + err = nvme_submit_admin_passthru(hdl, &cmd); + if (result) + *result = cmd.result; + return err; +} + +/** + * nvme_get_features() - Submit a Get Features command + * @hdl: Transport handle for the controller. + * @nsid: Namespace ID, if applicable + * @fid: Feature identifier, see &enum nvme_features_id + * @sel: Select which type of attribute to return, + * see &enum nvme_get_features_sel + * @cdw11: Feature specific command dword11 field + * @uidx: UUID Index for differentiating vendor specific encoding + * @data: User address of feature data, if applicable + * @len: Length of feature data, if applicable, in bytes + * @result: The command completion result (CQE dword0) on success. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_features(struct nvme_transport_handle *hdl, __u32 nsid, + __u8 fid, enum nvme_get_features_sel sel, + __u32 cdw11, __u8 uidx, void *data, + __u32 len, __u64 *result) +{ + struct nvme_passthru_cmd cmd; + int err; + + nvme_init_get_features(&cmd, fid, sel); + + cmd.nsid = nsid; + cmd.cdw11 = cdw11; + cmd.cdw14 = NVME_FIELD_ENCODE(uidx, + NVME_GET_FEATURES_CDW14_UUID_SHIFT, + NVME_GET_FEATURES_CDW14_UUID_MASK); + cmd.data_len = len; + cmd.addr = (__u64)(uintptr_t)data; + + err = nvme_submit_admin_passthru(hdl, &cmd); + if (result) + *result = cmd.result; + return err; +} + +/** + * nvme_get_features_simple() - Submit a simple Get Features command + * @hdl: Transport handle for the controller. + * @fid: Feature Identifier (FID) to be retrieved. + * @sel: Select (SEL), specifying which feature value + * to return (&struct nvme_get_features_sel). + * @result: The command completion result (CQE dword0) on success. + * + * Submits the Get Features command for features that only require parameters in + * the CQE dword0 and do not need any parameters in cdw11 through cdw15. + * + * Return: 0 on success, the NVMe command status on error, or a negative + * errno otherwise. + */ +static inline int +nvme_get_features_simple(struct nvme_transport_handle *hdl, __u8 fid, + enum nvme_get_features_sel sel, __u64 *result) +{ + struct nvme_passthru_cmd cmd; + int err; + + nvme_init_get_features(&cmd, fid, sel); + + err = nvme_submit_admin_passthru(hdl, &cmd); + if (result) + *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); +} + diff --git a/libnvme/src/nvme/ioctl.h b/libnvme/src/nvme/ioctl.h index 1aa4353ab8..a596d3dd14 100644 --- a/libnvme/src/nvme/ioctl.h +++ b/libnvme/src/nvme/ioctl.h @@ -7,17 +7,9 @@ * Chaitanya Kulkarni */ -#ifndef _LIBNVME_IOCTL_H -#define _LIBNVME_IOCTL_H +#pragma once -#include -#include -#include -#include -#include -#include - -#include +#include /** * DOC: ioctl.h @@ -125,305 +117,7 @@ struct nvme_uring_cmd { __u32 rsvd2; }; -enum nvme_cmd_dword_fields { - NVME_DEVICE_SELF_TEST_CDW10_STC_SHIFT = 0, - NVME_DEVICE_SELF_TEST_CDW10_STC_MASK = 0xf, - NVME_DIRECTIVE_CDW11_DOPER_SHIFT = 0, - NVME_DIRECTIVE_CDW11_DTYPE_SHIFT = 8, - NVME_DIRECTIVE_CDW11_DPSEC_SHIFT = 16, - NVME_DIRECTIVE_CDW11_DOPER_MASK = 0xff, - NVME_DIRECTIVE_CDW11_DTYPE_MASK = 0xff, - NVME_DIRECTIVE_CDW11_DPSEC_MASK = 0xffff, - NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_ENDIR_SHIFT = 0, - NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_DTYPE_SHIFT = 1, - NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_ENDIR_MASK = 0x1, - NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_DTYPE_MASK = 0x1, - NVME_FW_COMMIT_CDW10_FS_SHIFT = 0, - NVME_FW_COMMIT_CDW10_CA_SHIFT = 3, - NVME_FW_COMMIT_CDW10_BPID_SHIFT = 31, - NVME_FW_COMMIT_CDW10_FS_MASK = 0x7, - NVME_FW_COMMIT_CDW10_CA_MASK = 0x7, - NVME_FW_COMMIT_CDW10_BPID_MASK = 0x1, - NVME_GET_FEATURES_CDW10_SEL_SHIFT = 8, - NVME_GET_FEATURES_CDW10_SEL_MASK = 0x7, - NVME_GET_FEATURES_CDW10_FID_SHIFT = 0, - NVME_GET_FEATURES_CDW10_FID_MASK = 0xff, - NVME_GET_FEATURES_CDW14_UUID_SHIFT = 0, - NVME_GET_FEATURES_CDW14_UUID_MASK = 0x7f, - NVME_SET_FEATURES_CDW10_SV_SHIFT = 31, - NVME_SET_FEATURES_CDW10_SV_MASK = 0x1, - NVME_SET_FEATURES_CDW10_FID_SHIFT = 0, - NVME_SET_FEATURES_CDW10_FID_MASK = 0xff, - NVME_SET_FEATURES_CDW11_NUM_SHIFT = 0, - NVME_SET_FEATURES_CDW11_NUM_MASK = 0x3f, - NVME_SET_FEATURES_CDW14_UUID_SHIFT = 0, - NVME_SET_FEATURES_CDW14_UUID_MASK = 0x7f, - NVME_LOG_CDW10_LID_SHIFT = 0, - NVME_LOG_CDW10_LSP_SHIFT = 8, - NVME_LOG_CDW10_RAE_SHIFT = 15, - NVME_LOG_CDW10_NUMDL_SHIFT = 16, - NVME_LOG_CDW11_NUMDU_SHIFT = 0, - NVME_LOG_CDW11_LSI_SHIFT = 16, - NVME_LOG_CDW14_UUID_SHIFT = 0, - NVME_LOG_CDW14_CSI_SHIFT = 24, - NVME_LOG_CDW14_OT_SHIFT = 23, - NVME_LOG_CDW10_LID_MASK = 0xff, - NVME_LOG_CDW10_LSP_MASK = 0x7f, - NVME_LOG_CDW10_RAE_MASK = 0x1, - NVME_LOG_CDW10_NUMDL_MASK = 0xffff, - NVME_LOG_CDW11_NUMDU_MASK = 0xffff, - NVME_LOG_CDW11_LSI_MASK = 0xffff, - NVME_LOG_CDW14_UUID_MASK = 0x7f, - NVME_LOG_CDW14_CSI_MASK = 0xff, - NVME_LOG_CDW14_OT_MASK = 0x1, - NVME_IDENTIFY_CDW10_CNS_SHIFT = 0, - NVME_IDENTIFY_CDW10_CNTID_SHIFT = 16, - NVME_IDENTIFY_CDW11_CNSSPECID_SHIFT = 0, - NVME_IDENTIFY_CDW11_FIDX_SHIFT = 0, - NVME_IDENTIFY_CDW11_DOMID_SHIFT = 0, - NVME_IDENTIFY_CDW11_ENGGID_SHIFT = 0, - NVME_IDENTIFY_CDW14_UUID_SHIFT = 0, - NVME_IDENTIFY_CDW11_CSI_SHIFT = 24, - NVME_IDENTIFY_CDW10_CNS_MASK = 0xff, - NVME_IDENTIFY_CDW10_CNTID_MASK = 0xffff, - NVME_IDENTIFY_CDW11_CNSSPECID_MASK = 0xffff, - NVME_IDENTIFY_CDW11_FIDX_MASK = 0xffff, - NVME_IDENTIFY_CDW11_DOMID_MASK = 0xffff, - NVME_IDENTIFY_CDW11_ENGGID_MASK = 0xffff, - NVME_IDENTIFY_CDW14_UUID_MASK = 0x7f, - NVME_IDENTIFY_CDW11_CSI_MASK = 0xff, - NVME_NAMESPACE_ATTACH_CDW10_SEL_SHIFT = 0, - NVME_NAMESPACE_ATTACH_CDW10_SEL_MASK = 0xf, - NVME_NAMESPACE_MGMT_CDW10_SEL_SHIFT = 0, - NVME_NAMESPACE_MGMT_CDW10_SEL_MASK = 0xf, - NVME_NAMESPACE_MGMT_CDW11_CSI_SHIFT = 24, - NVME_NAMESPACE_MGMT_CDW11_CSI_MASK = 0xff, - NVME_VIRT_MGMT_CDW10_ACT_SHIFT = 0, - NVME_VIRT_MGMT_CDW10_RT_SHIFT = 8, - NVME_VIRT_MGMT_CDW10_CNTLID_SHIFT = 16, - NVME_VIRT_MGMT_CDW11_NR_SHIFT = 0, - NVME_VIRT_MGMT_CDW10_ACT_MASK = 0xf, - NVME_VIRT_MGMT_CDW10_RT_MASK = 0x7, - NVME_VIRT_MGMT_CDW10_CNTLID_MASK = 0xffff, - NVME_VIRT_MGMT_CDW11_NR_MASK = 0xffff, - NVME_FORMAT_CDW10_LBAFL_SHIFT = 0, - NVME_FORMAT_CDW10_MSET_SHIFT = 4, - NVME_FORMAT_CDW10_PI_SHIFT = 5, - NVME_FORMAT_CDW10_PIL_SHIFT = 8, - NVME_FORMAT_CDW10_SES_SHIFT = 9, - NVME_FORMAT_CDW10_LBAFU_SHIFT = 12, - NVME_FORMAT_CDW10_LBAFL_MASK = 0xf, - NVME_FORMAT_CDW10_MSET_MASK = 0x1, - NVME_FORMAT_CDW10_PI_MASK = 0x7, - NVME_FORMAT_CDW10_PIL_MASK = 0x1, - NVME_FORMAT_CDW10_SES_MASK = 0x7, - NVME_FORMAT_CDW10_LBAFU_MASK = 0x3, - NVME_SANITIZE_CDW10_SANACT_SHIFT = 0, - NVME_SANITIZE_CDW10_AUSE_SHIFT = 3, - NVME_SANITIZE_CDW10_OWPASS_SHIFT = 4, - NVME_SANITIZE_CDW10_OIPBP_SHIFT = 8, - NVME_SANITIZE_CDW10_NDAS_SHIFT = 9, - NVME_SANITIZE_CDW10_EMVS_SHIFT = 10, - NVME_SANITIZE_CDW10_SANACT_MASK = 0x7, - NVME_SANITIZE_CDW10_AUSE_MASK = 0x1, - NVME_SANITIZE_CDW10_OWPASS_MASK = 0xf, - NVME_SANITIZE_CDW10_OIPBP_MASK = 0x1, - NVME_SANITIZE_CDW10_NDAS_MASK = 0x1, - NVME_SANITIZE_CDW10_EMVS_MASK = 0x1, - NVME_SECURITY_NSSF_SHIFT = 0, - NVME_SECURITY_SPSP0_SHIFT = 8, - NVME_SECURITY_SPSP1_SHIFT = 16, - NVME_SECURITY_SECP_SHIFT = 24, - NVME_SECURITY_NSSF_MASK = 0xff, - NVME_SECURITY_SPSP0_MASK = 0xff, - NVME_SECURITY_SPSP1_MASK = 0xff, - NVME_SECURITY_SECP_MASK = 0xffff, - NVME_GET_LBA_STATUS_CDW13_RL_SHIFT = 0, - NVME_GET_LBA_STATUS_CDW13_ATYPE_SHIFT = 24, - NVME_GET_LBA_STATUS_CDW13_RL_MASK = 0xffff, - NVME_GET_LBA_STATUS_CDW13_ATYPE_MASK = 0xff, - NVME_ZNS_MGMT_SEND_ZM_SHIFT = 16, - NVME_ZNS_MGMT_SEND_ZM_MASK = 0xff, - NVME_ZNS_MGMT_SEND_ZSASO_SHIFT = 9, - NVME_ZNS_MGMT_SEND_ZSASO_MASK = 0x1, - NVME_ZNS_MGMT_SEND_SEL_SHIFT = 8, - NVME_ZNS_MGMT_SEND_SEL_MASK = 0x1, - NVME_ZNS_MGMT_SEND_ZSA_SHIFT = 0, - NVME_ZNS_MGMT_SEND_ZSA_MASK = 0xff, - NVME_ZNS_MGMT_RECV_ZRASPF_SHIFT = 16, - NVME_ZNS_MGMT_RECV_ZRASPF_MASK = 0x1, - NVME_ZNS_MGMT_RECV_ZRAS_SHIFT = 8, - NVME_ZNS_MGMT_RECV_ZRAS_MASK = 0xff, - NVME_ZNS_MGMT_RECV_ZRA_SHIFT = 0, - NVME_ZNS_MGMT_RECV_ZRA_MASK = 0xff, - NVME_DIM_TAS_SHIFT = 0, - NVME_DIM_TAS_MASK = 0xf, - NVME_DSM_CDW10_NR_SHIFT = 0, - NVME_DSM_CDW10_NR_MASK = 0xff, - NVME_DSM_CDW11_IDR_SHIFT = 0, - NVME_DSM_CDW11_IDR_MASK = 0x1, - NVME_DSM_CDW11_IDW_SHIFT = 1, - NVME_DSM_CDW11_IDW_MASK = 0x1, - NVME_DSM_CDW11_AD_SHIFT = 2, - NVME_DSM_CDW11_AD_MASK = 0x1, - NVME_CAPACITY_MGMT_CDW10_OPER_SHIFT = 0, - NVME_CAPACITY_MGMT_CDW10_OPER_MASK = 0xf, - NVME_CAPACITY_MGMT_CDW10_ELID_SHIFT = 16, - NVME_CAPACITY_MGMT_CDW10_ELID_MASK = 0xffff, - NVME_CAPACITY_MGMT_CDW11_CAPL_SHIFT = 0, - NVME_CAPACITY_MGMT_CDW11_CAPL_MASK = 0xffffffff, - NVME_CAPACITY_MGMT_CDW12_CAPU_SHIFT = 0, - NVME_CAPACITY_MGMT_CDW12_CAPU_MASK = 0xffffffff, - NVME_LOCKDOWN_CDW10_SCP_SHIFT = 0, - NVME_LOCKDOWN_CDW10_SCP_MASK = 0xf, - NVME_LOCKDOWN_CDW10_PRHBT_SHIFT = 4, - NVME_LOCKDOWN_CDW10_PRHBT_MASK = 0x1, - NVME_LOCKDOWN_CDW10_IFC_SHIFT = 5, - NVME_LOCKDOWN_CDW10_IFC_MASK = 0x3, - NVME_LOCKDOWN_CDW10_OFI_SHIFT = 8, - NVME_LOCKDOWN_CDW10_OFI_MASK = 0xff, - NVME_LOCKDOWN_CDW14_UIDX_SHIFT = 0, - NVME_LOCKDOWN_CDW14_UIDX_MASK = 0x3f, - NVME_RESV_ACQUIRE_CDW10_RACQA_SHIFT = 0, - NVME_RESV_ACQUIRE_CDW10_RACQA_MASK = 0x7, - NVME_RESV_ACQUIRE_CDW10_IEKEY_SHIFT = 3, - NVME_RESV_ACQUIRE_CDW10_IEKEY_MASK = 0x1, - NVME_RESV_ACQUIRE_CDW10_DISNSRS_SHIFT = 4, - NVME_RESV_ACQUIRE_CDW10_DISNSRS_MASK = 0x1, - NVME_RESV_ACQUIRE_CDW10_RTYPE_SHIFT = 8, - NVME_RESV_ACQUIRE_CDW10_RTYPE_MASK = 0xff, - NVME_RESV_REGISTER_CDW10_RREGA_SHIFT = 0, - NVME_RESV_REGISTER_CDW10_RREGA_MASK = 0x7, - NVME_RESV_REGISTER_CDW10_IEKEY_SHIFT = 3, - NVME_RESV_REGISTER_CDW10_IEKEY_MASK = 0x1, - NVME_RESV_REGISTER_CDW10_DISNSRS_SHIFT = 4, - NVME_RESV_REGISTER_CDW10_DISNSRS_MASK = 0x1, - NVME_RESV_REGISTER_CDW10_CPTPL_SHIFT = 30, - NVME_RESV_REGISTER_CDW10_CPTPL_MASK = 0x3, - NVME_RESV_RELEASE_CDW10_RRELA_SHIFT = 0, - NVME_RESV_RELEASE_CDW10_RRELA_MASK = 0x7, - NVME_RESV_RELEASE_CDW10_IEKEY_SHIFT = 3, - NVME_RESV_RELEASE_CDW10_IEKEY_MASK = 0x1, - NVME_RESV_RELEASE_CDW10_DISNSRS_SHIFT = 4, - NVME_RESV_RELEASE_CDW10_DISNSRS_MASK = 0x1, - NVME_RESV_RELEASE_CDW10_RTYPE_SHIFT = 8, - NVME_RESV_RELEASE_CDW10_RTYPE_MASK = 0xff, - NVME_RESV_REPORT_CDW11_EDS_SHIFT = 0, - NVME_RESV_REPORT_CDW11_EDS_MASK = 0x1, - NVME_RESV_REPORT_CDW11_DISNSRS_SHIFT = 1, - NVME_RESV_REPORT_CDW11_DISNSRS_MASK = 0x1, - NVME_IO_MGMT_RECV_CDW10_MO_SHIFT = 0, - NVME_IO_MGMT_RECV_CDW10_MO_MASK = 0xff, - NVME_IO_MGMT_RECV_CDW10_MOS_SHIFT = 16, - NVME_IO_MGMT_RECV_CDW10_MOS_MASK = 0xffff, - NVME_IO_MGMT_SEND_CDW10_MO_SHIFT = 0, - NVME_IO_MGMT_SEND_CDW10_MO_MASK = 0xff, - NVME_IO_MGMT_SEND_CDW10_MOS_SHIFT = 16, - NVME_IO_MGMT_SEND_CDW10_MOS_MASK = 0xffff, - NVME_IOCS_COMMON_CDW2_ELBTU_SHIFT = 0, - NVME_IOCS_COMMON_CDW2_ELBTU_MASK = 0xffff, - NVME_IOCS_COMMON_CDW3_ELBTU_SHIFT = 0, - NVME_IOCS_COMMON_CDW3_ELBTU_MASK = 0xffffffff, - NVME_IOCS_COMMON_CDW10_SLBAL_SHIFT = 0, - NVME_IOCS_COMMON_CDW10_SLBAL_MASK = 0xffffffff, - NVME_IOCS_COMMON_CDW11_SLBAU_SHIFT = 0, - NVME_IOCS_COMMON_CDW11_SLBAU_MASK = 0xffffffff, - NVME_IOCS_COMMON_CDW12_NLB_SHIFT = 0, - NVME_IOCS_COMMON_CDW12_NLB_MASK = 0xffff, - NVME_IOCS_COMMON_CDW12_CETYPE_SHIFT = 16, - NVME_IOCS_COMMON_CDW12_CETYPE_MASK = 0xf, - NVME_IOCS_COMMON_CDW12_DTYPE_SHIFT = 20, - NVME_IOCS_COMMON_CDW12_DTYPE_MASK = 0xf, - NVME_IOCS_COMMON_CDW12_STC_SHIFT = 24, - NVME_IOCS_COMMON_CDW12_STC_MASK = 0x1, - NVME_IOCS_COMMON_CDW12_DEAC_SHIFT = 25, - NVME_IOCS_COMMON_CDW12_DEAC_MASK = 0x1, - NVME_IOCS_COMMON_CDW12_PIREMAP_SHIFT = 25, - NVME_IOCS_COMMON_CDW12_PIREMAP_MASK = 0x1, - NVME_IOCS_COMMON_CDW12_PRINFO_SHIFT = 26, - NVME_IOCS_COMMON_CDW12_PRINFO_MASK = 0xf, - NVME_IOCS_COMMON_CDW12_FUA_SHIFT = 30, - NVME_IOCS_COMMON_CDW12_FUA_MASK = 0x1, - NVME_IOCS_COMMON_CDW12_LR_SHIFT = 31, - NVME_IOCS_COMMON_CDW12_LR_MASK = 0x1, - NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT = - NVME_IOCS_COMMON_CDW12_CETYPE_SHIFT, - NVME_IOCS_COMMON_CDW12_CONTROL_MASK = - (NVME_VAL(IOCS_COMMON_CDW12_CETYPE) | - NVME_VAL(IOCS_COMMON_CDW12_DTYPE) | - NVME_VAL(IOCS_COMMON_CDW12_STC) | - NVME_VAL(IOCS_COMMON_CDW12_DEAC) | - NVME_VAL(IOCS_COMMON_CDW12_PRINFO) | - NVME_VAL(IOCS_COMMON_CDW12_FUA) | - NVME_VAL(IOCS_COMMON_CDW12_LR)) >> - NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT, - NVME_IOCS_COMMON_CDW13_DSM_AF_SHIFT = 0, - NVME_IOCS_COMMON_CDW13_DSM_AF_MASK = 0xf, - NVME_IOCS_COMMON_CDW13_DSM_AL_SHIFT = 4, - NVME_IOCS_COMMON_CDW13_DSM_AL_MASK = 0x3, - NVME_IOCS_COMMON_CDW13_DSM_SEQREQ_SHIFT = 6, - NVME_IOCS_COMMON_CDW13_DSM_SEQREQ_MASK = 0x1, - NVME_IOCS_COMMON_CDW13_DSM_INCPRS_SHIFT = 7, - NVME_IOCS_COMMON_CDW13_DSM_INCPRS_MASK = 0x1, - NVME_IOCS_COMMON_CDW13_DSM_SHIFT = - NVME_IOCS_COMMON_CDW13_DSM_AF_SHIFT, - NVME_IOCS_COMMON_CDW13_DSM_MASK = - (NVME_VAL(IOCS_COMMON_CDW13_DSM_AF) | - NVME_VAL(IOCS_COMMON_CDW13_DSM_AL) | - NVME_VAL(IOCS_COMMON_CDW13_DSM_SEQREQ) | - NVME_VAL(IOCS_COMMON_CDW13_DSM_INCPRS)) >> - NVME_IOCS_COMMON_CDW13_DSM_SHIFT, - NVME_IOCS_COMMON_CDW13_CEV_SHIFT = 0, - NVME_IOCS_COMMON_CDW13_CEV_MASK = 0xffff, - NVME_IOCS_COMMON_CDW13_DSPEC_SHIFT = 16, - NVME_IOCS_COMMON_CDW13_DSPEC_MASK = 0xffff, - NVME_IOCS_COMMON_CDW14_ELBTL_SHIFT = 0, - NVME_IOCS_COMMON_CDW14_ELBTL_MASK = 0xffffffff, - NVME_IOCS_COMMON_CDW15_ELBAT_SHIFT = 0, - NVME_IOCS_COMMON_CDW15_ELBAT_MASK = 0xffff, - NVME_IOCS_COMMON_CDW15_ELBATM_SHIFT = 16, - NVME_IOCS_COMMON_CDW15_ELBATM_MASK = 0xffff, - NVME_COPY_CDW3_LBTU_SHIFT = 0, - NVME_COPY_CDW3_LBTU_MASK = 0xffffffff, - NVME_COPY_CDW10_SDLBAL_SHIFT = 0, - NVME_COPY_CDW10_SDLBAL_MASK = 0xffffffff, - NVME_COPY_CDW11_SDLBAU_SHIFT = 0, - NVME_COPY_CDW11_SDLBAU_MASK = 0xffffffff, - NVME_COPY_CDW12_NR_SHIFT = 0, - NVME_COPY_CDW12_NR_MASK = 0xff, - NVME_COPY_CDW12_DESFMT_SHIFT = 8, - NVME_COPY_CDW12_DESFMT_MASK = 0xf, - NVME_COPY_CDW12_PRINFOR_SHIFT = 12, - NVME_COPY_CDW12_PRINFOR_MASK = 0xf, - NVME_COPY_CDW12_CETYPE_SHIFT = 16, - NVME_COPY_CDW12_CETYPE_MASK = 0xf, - NVME_COPY_CDW12_DTYPE_SHIFT = 20, - NVME_COPY_CDW12_DTYPE_MASK = 0xf, - NVME_COPY_CDW12_STCW_SHIFT = 24, - NVME_COPY_CDW12_STCW_MASK = 0x1, - NVME_COPY_CDW12_STCR_SHIFT = 25, - NVME_COPY_CDW12_STCR_MASK = 0x1, - NVME_COPY_CDW12_PRINFOW_SHIFT = 26, - NVME_COPY_CDW12_PRINFOW_MASK = 0xf, - NVME_COPY_CDW12_FUA_SHIFT = 30, - NVME_COPY_CDW12_FUA_MASK = 0x1, - NVME_COPY_CDW12_LR_SHIFT = 31, - NVME_COPY_CDW12_LR_MASK = 0x1, - NVME_COPY_CDW14_LBTL_SHIFT = 0, - NVME_COPY_CDW14_LBTL_MASK = 0xffffffff, - NVME_COPY_CDW15_LBAT_SHIFT = 0, - 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) \ - (((__u32)(value) & (mask)) << (shift)) - -#define NVME_FIELD_DECODE(value, shift, mask) \ - (((value) >> (shift)) & (mask)) +struct nvme_transport_handle; /** * nvme_submit_admin_passthru() - Submit an nvme passthrough admin command @@ -495,6584 +189,3 @@ int nvme_ns_rescan(struct nvme_transport_handle *hdl); * Return: 0 if @nsid was set successfully or -1 with errno set otherwise. */ int nvme_get_nsid(struct nvme_transport_handle *hdl, __u32 *nsid); - -/** - * nvme_init_identify() - Initialize passthru command for - * NVMe Identify - * @cmd: Command data structure to initialize - * @nsid: Namespace identifier - * @csi: Command Set Identifier - * @cns: The Controller or Namespace structure, - * see @enum nvme_identify_cns - * @data: User space destination address to transfer the data - * @len: Length of provided user buffer to hold the data in bytes - * - * Prepare the @cmd data structure for the NVMe Identify command. - */ -static inline void -nvme_init_identify(struct nvme_passthru_cmd *cmd, - __u32 nsid, enum nvme_csi csi, enum nvme_identify_cns cns, - void *data, __u32 len) -{ - __u32 cdw10 = NVME_FIELD_ENCODE(cns, - NVME_IDENTIFY_CDW10_CNS_SHIFT, - NVME_IDENTIFY_CDW10_CNS_MASK); - __u32 cdw11 = NVME_FIELD_ENCODE(csi, - NVME_IDENTIFY_CDW11_CSI_SHIFT, - NVME_IDENTIFY_CDW11_CSI_MASK); - - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_admin_identify; - cmd->nsid = nsid; - cmd->cdw10 = cdw10; - cmd->cdw11 = cdw11; - cmd->data_len = len; - cmd->addr = (__u64)(uintptr_t)data; -} - -/** - * nvme_init_identify_ns() - Initialize passthru command for - * NVMe Identify Namespace data structure - * @cmd: Command data structure to initialize - * @nsid: Namespace identifier - * @id: User space destination address to transfer the data - * - * Initializes the passthru command buffer for the Identify command with - * CNS value %NVME_IDENTIFY_CNS_NS. - */ -static inline void -nvme_init_identify_ns(struct nvme_passthru_cmd *cmd, - __u32 nsid, struct nvme_id_ns *id) -{ - nvme_init_identify(cmd, nsid, NVME_CSI_NVM, - NVME_IDENTIFY_CNS_NS, - id, sizeof(*id)); -} - -/** - * nvme_init_identify_ctrl() - Initialize passthru command for - * NVMe Identify Controller data structure - * @cmd: Command data structure to initialize - * @id: User space destination address to transfer the data, - * - * Initializes the passthru command buffer for the Identify command with - * CNS value %NVME_IDENTIFY_CNS_CTRL. - */ -static inline void -nvme_init_identify_ctrl(struct nvme_passthru_cmd *cmd, struct nvme_id_ctrl *id) -{ - nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM, - NVME_IDENTIFY_CNS_CTRL, - id, sizeof(*id)); -} - -/** - * nvme_init_identify_active_ns_list() - Initialize passthru command for - * Active Namespaces ID list - * @cmd: Command data structure to initialize - * @nsid: Namespace identifier - * @list: User space destination address to transfer the data - * - * Initializes the passthru command buffer for the Identify command with - * CNS value %NVME_IDENTIFY_CNS_NS_ACTIVE_LIST. - */ -static inline void -nvme_init_identify_active_ns_list(struct nvme_passthru_cmd *cmd, - __u32 nsid, struct nvme_ns_list *list) -{ - nvme_init_identify(cmd, nsid, NVME_CSI_NVM, - NVME_IDENTIFY_CNS_NS_ACTIVE_LIST, - list, sizeof(*list)); -} - -/** - * nvme_init_identify_ns_descs_list() - Initialize passthru command for - * Namespace Descriptor list - * @cmd: Command data structure to initialize - * @nsid: The namespace id to retrieve descriptors - * @descs: User space destination address to transfer the data - * - * Initializes the passthru command buffer for the Identify command with - * CNS value %NVME_IDENTIFY_CNS_NS_DESC_LIST. - */ -static inline void -nvme_init_identify_ns_descs_list(struct nvme_passthru_cmd *cmd, - __u32 nsid, struct nvme_ns_id_desc *descs) -{ - nvme_init_identify(cmd, nsid, NVME_CSI_NVM, - NVME_IDENTIFY_CNS_NS_DESC_LIST, - descs, NVME_IDENTIFY_DATA_SIZE); -} - -/** - * nvme_init_identify_nvmset_list() - Initialize passthru command for - * NVM Set List data structure - * @cmd: Command data structure to initialize - * @nsid: Namespace identifier - * @nvmsetid: NVM Set Identifier - * @nvmset: User space destination address to transfer the data - * - * Initializes the passthru command buffer for the Identify command with - * CNS value %NVME_IDENTIFY_CNS_NS_ACTIVE_LIST. - */ -static inline void -nvme_init_identify_nvmset_list(struct nvme_passthru_cmd *cmd, - __u32 nsid, __u16 nvmsetid, struct nvme_id_nvmset_list *nvmset) -{ - nvme_init_identify(cmd, nsid, NVME_CSI_NVM, - NVME_IDENTIFY_CNS_NVMSET_LIST, - nvmset, sizeof(*nvmset)); - cmd->cdw11 |= NVME_FIELD_ENCODE(nvmsetid, - NVME_IDENTIFY_CDW11_CNSSPECID_SHIFT, - NVME_IDENTIFY_CDW11_CNSSPECID_MASK); -} - -/** - * nvme_init_identify_csi_ns() - Initialize passthru command for - * I/O Command Set specific Identify Namespace data structure - * @cmd: Command data structure to initialize - * @nsid: Namespace identifier - * @csi: Command Set Identifier - * @uidx: UUID Index for differentiating vendor specific encoding - * @data: User space destination address to transfer the data - * - * Initializes the passthru command buffer for the Identify command with - * CNS value %NVME_IDENTIFY_CNS_CSI_NS. - */ -static inline void -nvme_init_identify_csi_ns(struct nvme_passthru_cmd *cmd, - __u32 nsid, enum nvme_csi csi, __u8 uidx, void *data) -{ - nvme_init_identify(cmd, nsid, csi, - NVME_IDENTIFY_CNS_CSI_NS, - data, NVME_IDENTIFY_DATA_SIZE); - cmd->cdw14 |= NVME_FIELD_ENCODE(uidx, - NVME_IDENTIFY_CDW14_UUID_SHIFT, - NVME_IDENTIFY_CDW14_UUID_MASK); -} - -/** - * nvme_init_identify_csi_ctrl() - Initialize passthru command for - * I/O Command Set specific Identify Controller data structure - * @cmd: Command data structure to initialize - * @csi: Command Set Identifier - * @data: User space destination address to transfer the data - * - * Initializes the passthru command buffer for the Identify command with - * CNS value %NVME_IDENTIFY_CNS_CSI_CTRL. - */ -static inline void -nvme_init_identify_csi_ctrl(struct nvme_passthru_cmd *cmd, - enum nvme_csi csi, void *data) -{ - nvme_init_identify(cmd, NVME_NSID_NONE, csi, - NVME_IDENTIFY_CNS_CSI_CTRL, - data, NVME_IDENTIFY_DATA_SIZE); -} - -/** - * nvme_init_identify_csi_active_ns_list() - Initialize passthru command - * for Active namespace ID list - * @cmd: Command data structure to initialize - * @nsid: Return namespaces greater than this identifier - * @csi: Command Set Identifier - * @ns_list: User space destination address to transfer the data - * - * Initializes the passthru command buffer for the Identify command with - * CNS value %NVME_IDENTIFY_CNS_CSI_NS_ACTIVE_LIST. - */ -static inline void -nvme_init_identify_csi_active_ns_list(struct nvme_passthru_cmd *cmd, - __u32 nsid, enum nvme_csi csi, struct nvme_ns_list *ns_list) -{ - nvme_init_identify(cmd, nsid, csi, - NVME_IDENTIFY_CNS_CSI_NS_ACTIVE_LIST, - ns_list, sizeof(*ns_list)); -} - -/** - * nvme_init_identify_csi_independent_identify_id_ns() -Initialize passthru - * command for I/O Command Set Independent Identify Namespace data structure - * @cmd: Command data structure to initialize - * @nsid: Return namespaces greater than this identifier - * @ns: I/O Command Set Independent Identify Namespace data - * structure - * - * Initializes the passthru command buffer for the Identify command with - * CNS value %NVME_IDENTIFY_CNS_CSI_INDEPENDENT_ID_NS. - */ -static inline void -nvme_init_identify_csi_independent_identify_id_ns(struct nvme_passthru_cmd *cmd, - __u32 nsid, struct nvme_id_independent_id_ns *ns) -{ - nvme_init_identify(cmd, nsid, NVME_CSI_NVM, - NVME_IDENTIFY_CNS_CSI_INDEPENDENT_ID_NS, - ns, sizeof(*ns)); -} - -/** - * nvme_init_identify_ns_user_data_format() - Initialize passthru command - * for Identify namespace user data format - * @cmd: Command data structure to initialize - * @csi: Command Set Identifier - * @fidx: Format Index - * @uidx: UUID selection, if supported - * @data: User space destination address to transfer the data - * - * Initializes the passthru command buffer for the Identify command with - * CNS value %NVME_IDENTIFY_CNS_NS_USER_DATA_FORMAT. - */ -static inline void -nvme_init_identify_ns_user_data_format(struct nvme_passthru_cmd *cmd, - enum nvme_csi csi, __u16 fidx, __u8 uidx, void *data) -{ - nvme_init_identify(cmd, NVME_NSID_NONE, csi, - NVME_IDENTIFY_CNS_NS_USER_DATA_FORMAT, - data, NVME_IDENTIFY_DATA_SIZE); - cmd->cdw11 |= NVME_FIELD_ENCODE(fidx, - NVME_IDENTIFY_CDW11_FIDX_SHIFT, - NVME_IDENTIFY_CDW11_FIDX_MASK); - cmd->cdw14 |= NVME_FIELD_ENCODE(uidx, - NVME_IDENTIFY_CDW14_UUID_SHIFT, - NVME_IDENTIFY_CDW14_UUID_MASK); -} - -/** - * nvme_init_identify_csi_ns_user_data_format() - Initialize passthru - * command for Identify namespace user data format - * @cmd: Command data structure to initialize - * @csi: Command Set Identifier - * @fidx: Format Index - * @uidx: UUID selection, if supported - * @data: User space destination address to transfer the data - * - * Initializes the passthru command buffer for the Identify command with - * CNS value %NVME_IDENTIFY_CNS_CSI_NS_USER_DATA_FORMAT. - */ -static inline void -nvme_init_identify_csi_ns_user_data_format(struct nvme_passthru_cmd *cmd, - enum nvme_csi csi, __u16 fidx, __u8 uidx, void *data) -{ - nvme_init_identify(cmd, NVME_NSID_NONE, csi, - NVME_IDENTIFY_CNS_CSI_NS_USER_DATA_FORMAT, - data, NVME_IDENTIFY_DATA_SIZE); - cmd->cdw11 |= NVME_FIELD_ENCODE(fidx, - NVME_IDENTIFY_CDW11_FIDX_SHIFT, - NVME_IDENTIFY_CDW11_FIDX_MASK); - cmd->cdw14 |= NVME_FIELD_ENCODE(uidx, - NVME_IDENTIFY_CDW14_UUID_SHIFT, - NVME_IDENTIFY_CDW14_UUID_MASK); -} - -/** - * nvme_init_identify_allocated_ns_list() - Initialize passthru command - * for Allocated namespace ID list - * @cmd: Command data structure to initialize - * @nsid: Return namespaces greater than this identifier - * @ns_list: User space destination address to transfer the data - * - * Initializes the passthru command buffer for the Identify command with - * CNS value %NVME_IDENTIFY_CNS_ALLOCATED_NS_LIST. - */ -static inline void -nvme_init_identify_allocated_ns_list(struct nvme_passthru_cmd *cmd, - __u32 nsid, struct nvme_ns_list *ns_list) -{ - nvme_init_identify(cmd, nsid, NVME_CSI_NVM, - NVME_IDENTIFY_CNS_ALLOCATED_NS_LIST, - ns_list, sizeof(*ns_list)); -} - -/** - * nvme_init_identify_allocated_ns() - Initialize passthru command - * for allocated Namespace ID list - * @cmd: Command data structure to initialize - * @nsid: Namespace to identify - * @ns: User space destination address to transfer the data - * - * Initializes the passthru command buffer for the Identify command with - * CNS value %NVME_IDENTIFY_CNS_ALLOCATED_NS. - */ -static inline void -nvme_init_identify_allocated_ns(struct nvme_passthru_cmd *cmd, - __u32 nsid, struct nvme_id_ns *ns) -{ - nvme_init_identify(cmd, nsid, NVME_CSI_NVM, - NVME_IDENTIFY_CNS_ALLOCATED_NS, - ns, sizeof(*ns)); -} - -/** - * nvme_init_identify_ns_ctrl_list() - Initialize passhtru command - * for Controller List - * @cmd: Command data structure to initialize - * @nsid: Return controllers that are attached to this nsid - * @cntid: Starting CNTLID to return in the list - * @cntlist: User space destination address to transfer the data - * - * Initializes the passthru command buffer for the Identify command with - * CNS value %NVME_IDENTIFY_CNS_NS_CTRL_LIST. - */ -static inline void -nvme_init_identify_ns_ctrl_list(struct nvme_passthru_cmd *cmd, - __u32 nsid, __u16 cntid, struct nvme_ctrl_list *cntlist) -{ - nvme_init_identify(cmd, nsid, NVME_CSI_NVM, - NVME_IDENTIFY_CNS_NS_CTRL_LIST, - cntlist, sizeof(*cntlist)); - cmd->cdw10 |= NVME_FIELD_ENCODE(cntid, - NVME_IDENTIFY_CDW10_CNTID_SHIFT, - NVME_IDENTIFY_CDW10_CNTID_MASK); -} - -/** - * nvme_init_identify_ctrl_list() - Initialize passthru command for - * Controller List of controllers - * @cmd: Command data structure to initialize - * @cntid: Starting CNTLID to return in the list - * @cntlist: User space destination address to transfer the data - * - * Initializes the passthru command buffer for the Identify command with - * CNS value %NVME_IDENTIFY_CNS_CTRL_LIST. - */ -static inline void -nvme_init_identify_ctrl_list(struct nvme_passthru_cmd *cmd, - __u16 cntid, struct nvme_ctrl_list *cntlist) -{ - nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM, - NVME_IDENTIFY_CNS_CTRL_LIST, - cntlist, sizeof(*cntlist)); - cmd->cdw10 |= NVME_FIELD_ENCODE(cntid, - NVME_IDENTIFY_CDW10_CNTID_SHIFT, - NVME_IDENTIFY_CDW10_CNTID_MASK); -} - -/** - * nvme_init_identify_primary_ctrl_cap() - Initialize passthru command - * for Primary Controller Capabilities data - * @cmd: Command data structure to initialize - * @cntid: Return controllers starting at this identifier - * @cap: User space destination buffer address to transfer the data - * - * Initializes the passthru command buffer for the Identify command with - * CNS value %NVME_IDENTIFY_CNS_PRIMARY_CTRL_CAP. - */ -static inline void -nvme_init_identify_primary_ctrl_cap(struct nvme_passthru_cmd *cmd, - __u16 cntid, struct nvme_primary_ctrl_cap *cap) -{ - nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM, - NVME_IDENTIFY_CNS_PRIMARY_CTRL_CAP, - cap, sizeof(*cap)); - cmd->cdw10 |= NVME_FIELD_ENCODE(cntid, - NVME_IDENTIFY_CDW10_CNTID_SHIFT, - NVME_IDENTIFY_CDW10_CNTID_MASK); -} - -/** - * nvme_init_identify_secondary_ctrl_list() - Initialize passhru command - * for Secondary Controller list - * @cmd: Command data structure to initialize - * @cntid: Return controllers starting at this identifier - * @sc_list: User space destination address to transfer the data - * - * Initializes the passthru command buffer for the Identify command with - * CNS value %NVME_IDENTIFY_CNS_SECONDARY_CTRL_LIST. - */ -static inline void -nvme_init_identify_secondary_ctrl_list(struct nvme_passthru_cmd *cmd, - __u16 cntid, struct nvme_secondary_ctrl_list *sc_list) -{ - nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM, - NVME_IDENTIFY_CNS_SECONDARY_CTRL_LIST, - sc_list, sizeof(*sc_list)); - cmd->cdw10 |= NVME_FIELD_ENCODE(cntid, - NVME_IDENTIFY_CDW10_CNTID_SHIFT, - NVME_IDENTIFY_CDW10_CNTID_MASK); -} - - -/** - * nvme_init_identify_ns_granularity() - Initialize passthru command for - * Namespace Granularity list - * @cmd: Command data structure to initialize - * @gr_list: User space destination address to transfer the data - * - * Initializes the passthru command buffer for the Identify command with - * CNS value %NVME_IDENTIFY_CNS_SECONDARY_CTRL_LIST. - */ -static inline void -nvme_init_identify_ns_granularity(struct nvme_passthru_cmd *cmd, - struct nvme_id_ns_granularity_list *gr_list) -{ - nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM, - NVME_IDENTIFY_CNS_NS_GRANULARITY, - gr_list, sizeof(*gr_list)); -} - -/** - * nvme_init_identify_uuid_list() - Initialize passthru command for - * UUID list - * @cmd: Command data structure to initialize - * @uuid_list: User space destination address to transfer the data - * - * Initializes the passthru command buffer for the Identify command with - * CNS value %NVME_IDENTIFY_CNS_UUID_LIST. - */ -static inline void -nvme_init_identify_uuid_list(struct nvme_passthru_cmd *cmd, - struct nvme_id_uuid_list *uuid_list) -{ - nvme_init_identify(cmd, NVME_UUID_NONE, NVME_CSI_NVM, - NVME_IDENTIFY_CNS_UUID_LIST, - uuid_list, sizeof(*uuid_list)); -} - -/** - * nvme_init_identify_domain_list() - Initialize passthru command for - * Domain list - * @cmd: Command data structure to initialize - * @domid: Domain ID - * @list: User space destination address to transfer data - * - * Initializes the passthru command buffer for the Identify command with - * CNS value %NVME_IDENTIFY_CNS_DOMAIN_LIST. - */ -static inline void -nvme_init_identify_domain_list(struct nvme_passthru_cmd *cmd, - __u16 domid, struct nvme_id_domain_list *list) -{ - nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM, - NVME_IDENTIFY_CNS_DOMAIN_LIST, - list, sizeof(*list)); - cmd->cdw11 |= NVME_FIELD_ENCODE(domid, - NVME_IDENTIFY_CDW11_DOMID_SHIFT, - NVME_IDENTIFY_CDW11_DOMID_MASK); -} - -/** - * nvme_init_identify_endurance_group_id() - Initialize passthru command for - * Endurance group list - * @cmd: Command data structure to initialize - * @enggid: Endurance group identifier - * @list: Array of endurance group identifiers - * - * 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 void -nvme_init_identify_endurance_group_id(struct nvme_passthru_cmd *cmd, - __u16 enggid, struct nvme_id_endurance_group_list *list) -{ - nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM, - NVME_IDENTIFY_CNS_ENDURANCE_GROUP_ID, - list, sizeof(*list)); - cmd->cdw11 |= NVME_FIELD_ENCODE(enggid, - NVME_IDENTIFY_CDW11_ENGGID_SHIFT, - NVME_IDENTIFY_CDW11_ENGGID_MASK); -} - -/** - * nvme_init_identify_csi_allocated_ns_list() - Initialize passthru command for - * I/O Command Set specific Allocated Namespace Id list - * @cmd: Command data structure to initialize - * @nsid: Return namespaces greater than this identifier - * @csi: Command Set Identifier - * @ns_list: User space destination address to transfer the data - * - * Initializes the passthru command buffer for the Identify command with - * CNS value %NVME_IDENTIFY_CNS_CSI_ALLOCATED_NS_LIST. - */ -static inline void -nvme_init_identify_csi_allocated_ns_list(struct nvme_passthru_cmd *cmd, - __u32 nsid, enum nvme_csi csi, struct nvme_ns_list *ns_list) -{ - nvme_init_identify(cmd, nsid, csi, - NVME_IDENTIFY_CNS_CSI_ALLOCATED_NS_LIST, - ns_list, sizeof(*ns_list)); -} - -/** - * nvme_init_identify_csi_id_ns_data_structure() - Initialize passthru command for - * I/O Command Set specific Identify Namespace data structure - * @cmd: Command data structure to initialize - * @nsid: Return namespaces greater than this identifier - * @csi: Command Set Identifier - * @data: User space destination address to transfer the data - * - * Initializes the passthru command buffer for the Identify command with - * CNS value %NVME_IDENTIFY_CNS_CSI_ID_NS_DATA_STRUCTURE. - */ -static inline void -nvme_init_identify_csi_id_ns_data_structure(struct nvme_passthru_cmd *cmd, - __u32 nsid, enum nvme_csi csi, void *data) -{ - nvme_init_identify(cmd, nsid, csi, - NVME_IDENTIFY_CNS_CSI_ID_NS_DATA_STRUCTURE, - data, NVME_IDENTIFY_DATA_SIZE); -} - -/** - * nvme_init_identify_command_set_structure() - Initialize passthru command for - * I/O Command Set data structure - * @cmd: Command data structure to initialize - * @cntid: Controller ID - * @iocs: User space destination address to transfer the data - * - * Retrieves list of the controller's supported io command set vectors. See - * &struct nvme_id_iocs. - * - * 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 void -nvme_init_identify_command_set_structure(struct nvme_passthru_cmd *cmd, - __u16 cntid, struct nvme_id_iocs *iocs) -{ - nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_NVM, - NVME_IDENTIFY_CNS_COMMAND_SET_STRUCTURE, - iocs, sizeof(*iocs)); - cmd->cdw10 |= NVME_FIELD_ENCODE(cntid, - NVME_IDENTIFY_CDW10_CNTID_SHIFT, - NVME_IDENTIFY_CDW10_CNTID_MASK); -} - -/** - * nvme_init_zns_identify_ns() - Initialize passthru command for - * ZNS identify namespace data - * @cmd: Command data structure to initialize - * @nsid: Namespace to identify - * @data: User space destination address to transfer the data - */ -static inline void -nvme_init_zns_identify_ns(struct nvme_passthru_cmd *cmd, - __u32 nsid, struct nvme_zns_id_ns *data) -{ - nvme_init_identify(cmd, nsid, NVME_CSI_ZNS, - NVME_IDENTIFY_CNS_CSI_NS, - data, sizeof(*data)); -} - -/** - * nvme_init_zns_identify_ctrl() - Initialize passthru command for - * ZNS identify controller data - * @cmd: Command data structure to initialize - * @id: User space destination address to transfer the data - */ -static inline void -nvme_init_zns_identify_ctrl(struct nvme_passthru_cmd *cmd, - struct nvme_zns_id_ctrl *id) -{ - nvme_init_identify(cmd, NVME_NSID_NONE, NVME_CSI_ZNS, - NVME_IDENTIFY_CNS_CSI_CTRL, - id, sizeof(*id)); -} - -/** - * nvme_get_log() - Get log page data - * @hdl: Transport handle - * @cmd: Passthru command - * @rae: Retain asynchronous events - * @xfer_len: Max log transfer size per request to split the total. - * - * 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_get_log(struct nvme_transport_handle *hdl, - struct nvme_passthru_cmd *cmd, bool rae, - __u32 xfer_len); - -/** - * nvme_init_get_log_lpo() - Initializes passthru command with a - * Log Page Offset - * @cmd: Passthru command - * @lpo: Log Page Offset to set set - */ -static inline void -nvme_init_get_log_lpo(struct nvme_passthru_cmd *cmd, __u64 lpo) -{ - cmd->cdw12 = lpo & 0xffffffff; - cmd->cdw13 = lpo >> 32; -} - -/** - * nvme_init_get_log() - Initialize passthru command for - * NVMe Admin Get Log - * @cmd: Passthru command to use - * @nsid: Namespace identifier, if applicable - * @lid: Log Page Identifier, see &enum nvme_cmd_get_log_lid - * @csi: Command set identifier, see &enum nvme_csi for known values - * @data: User space destination address to transfer the data - * @len: Length of provided user buffer to hold the log data in bytes - */ -static inline void -nvme_init_get_log(struct nvme_passthru_cmd *cmd, __u32 nsid, - enum nvme_cmd_get_log_lid lid, enum nvme_csi csi, - void *data, __u32 len) -{ - __u32 numd = (len >> 2) - 1; - __u16 numdu = numd >> 16; - __u16 numdl = numd & 0xffff; - __u32 cdw10 = NVME_FIELD_ENCODE(lid, - NVME_LOG_CDW10_LID_SHIFT, - NVME_LOG_CDW10_LID_MASK) | - NVME_FIELD_ENCODE(numdl, - NVME_LOG_CDW10_NUMDL_SHIFT, - NVME_LOG_CDW10_NUMDL_MASK); - __u32 cdw11 = NVME_FIELD_ENCODE(numdu, - NVME_LOG_CDW11_NUMDU_SHIFT, - NVME_LOG_CDW11_NUMDU_MASK); - __u32 cdw14 = NVME_FIELD_ENCODE(csi, - NVME_LOG_CDW14_CSI_SHIFT, - NVME_LOG_CDW14_CSI_MASK); - - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_admin_get_log_page; - cmd->nsid = nsid; - cmd->cdw10 = cdw10; - cmd->cdw11 = cdw11; - cmd->cdw14 = cdw14; - cmd->data_len = len; - cmd->addr = (__u64)(uintptr_t)data; -} - -/** - * nvme_init_get_log_supported_log_pages() - Initialize passthru command for - * Supported Log Pages - * @cmd: Passthru command to use - * @csi: Command set identifier, see &enum nvme_csi for known values - * @log: Array of LID supported and Effects data structures - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_SUPPORTED_LOG_PAGES. - */ -static inline void -nvme_init_get_log_supported_log_pages(struct nvme_passthru_cmd *cmd, - enum nvme_csi csi, struct nvme_supported_log_pages *log) -{ - nvme_init_get_log(cmd, NVME_NSID_ALL, NVME_LOG_LID_SUPPORTED_LOG_PAGES, - csi, log, sizeof(*log)); -} - -/** - * nvme_init_get_log_error() - Initialize passthru command for Error Information - * @cmd: Passthru command to use - * @nr_entries: Number of error log entries allocated - * @err_log: Array of error logs of size 'entries' - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_ERROR. - */ -static inline void -nvme_init_get_log_error(struct nvme_passthru_cmd *cmd, unsigned int nr_entries, - struct nvme_error_log_page *err_log) -{ - nvme_init_get_log(cmd, NVME_NSID_ALL, NVME_LOG_LID_ERROR, - NVME_CSI_NVM, err_log, sizeof(*err_log) * nr_entries); -} - -/** - * nvme_init_get_log_smart() - Initialize passthru command for - * SMART / Health Information - * @cmd: Passthru command to use - * @nsid: Optional namespace identifier - * @smart_log: User address to store the smart log - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_SMART. - */ -static inline void -nvme_init_get_log_smart(struct nvme_passthru_cmd *cmd, __u32 nsid, - struct nvme_smart_log *smart_log) -{ - nvme_init_get_log(cmd, nsid, NVME_LOG_LID_SMART, NVME_CSI_NVM, - smart_log, sizeof(*smart_log)); -} - -/** - * nvme_init_get_log_fw_slot() - Initialize passthru command for - * Firmware Slot Information - * @cmd: Passthru command to use - * @fw_log: User address to store the log page - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_SMART. - */ -static inline void -nvme_init_get_log_fw_slot(struct nvme_passthru_cmd *cmd, - struct nvme_firmware_slot *fw_log) -{ - nvme_init_get_log(cmd, NVME_NSID_ALL, NVME_LOG_LID_FW_SLOT, - NVME_CSI_NVM, fw_log, sizeof(*fw_log)); -} - -/** - * nvme_init_get_log_changed_ns() - Initialize passthru command for - * Changed Attached Namespace List - * @cmd: Passthru command to use - * @ns_log: User address to store the log page - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_CHANGED_NS. - */ -static inline void -nvme_init_get_log_changed_ns(struct nvme_passthru_cmd *cmd, - struct nvme_ns_list *ns_log) -{ - nvme_init_get_log(cmd, NVME_NSID_ALL, NVME_LOG_LID_CHANGED_NS, - NVME_CSI_NVM, ns_log, sizeof(*ns_log)); -} - - -/** - * nvme_init_get_log_cmd_effects() - Initialize passthru command for - * Commands Supported and Effects - * @cmd: Passthru command to use - * @csi: Command Set Identifier - * @effects_log:User address to store the effects log - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_CMD_EFFECTS. - */ -static inline void -nvme_init_get_log_cmd_effects(struct nvme_passthru_cmd *cmd, - enum nvme_csi csi, struct nvme_cmd_effects_log *effects_log) -{ - nvme_init_get_log(cmd, NVME_NSID_ALL, NVME_LOG_LID_CMD_EFFECTS, csi, - effects_log, sizeof(*effects_log)); -} - -/** - * nvme_init_get_log_device_self_test() - Initialize passthru command for - * Device Self-test - * @cmd: Passthru command to use - * @log: Userspace address of the log payload - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_DEVICE_SELF_TEST. - */ -static inline void -nvme_init_get_log_device_self_test(struct nvme_passthru_cmd *cmd, - struct nvme_self_test_log *log) -{ - nvme_init_get_log(cmd, NVME_NSID_ALL, NVME_LOG_LID_DEVICE_SELF_TEST, - NVME_CSI_NVM, log, sizeof(*log)); -} - -/** - * nvme_init_get_log_telemetry_host() - Initialize passthru command for - * Telemetry Host-Initiated - * @cmd: Passthru command to use - * @lpo: Offset into the telemetry data - * @log: User address for log page data - * @len: Length of provided user buffer to hold the log data in bytes - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_TELEMETRY_HOST. - */ -static inline void -nvme_init_get_log_telemetry_host(struct nvme_passthru_cmd *cmd, __u64 lpo, - void *log, __u32 len) -{ - nvme_init_get_log(cmd, NVME_NSID_NONE, NVME_LOG_LID_TELEMETRY_HOST, - NVME_CSI_NVM, log, len); - cmd->cdw10 |= NVME_FIELD_ENCODE(NVME_LOG_TELEM_HOST_LSP_RETAIN, - NVME_LOG_CDW10_LSP_SHIFT, - NVME_LOG_CDW10_LSP_MASK); - nvme_init_get_log_lpo(cmd, lpo); -} - -/** - * nvme_init_get_log_create_telemetry_host_mcda() - Initialize passthru - * command for Create Telemetry Host-Initiated - * @cmd: Passthru command to use - * @mcda: Maximum Created Data Area - * @log: Userspace address of the log payload - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_TELEMETRY_HOST and - * LSP value %NVME_LOG_TELEM_HOST_LSP_CREATE. - */ -static inline void -nvme_init_get_log_create_telemetry_host_mcda(struct nvme_passthru_cmd *cmd, - enum nvme_telemetry_da mcda, struct nvme_telemetry_log *log) -{ - nvme_init_get_log(cmd, NVME_NSID_NONE, NVME_LOG_LID_TELEMETRY_HOST, - NVME_CSI_NVM, log, sizeof(*log)); - cmd->cdw10 |= NVME_FIELD_ENCODE( - mcda << 1 | NVME_LOG_TELEM_HOST_LSP_CREATE, - NVME_LOG_CDW10_LSP_SHIFT, - NVME_LOG_CDW10_LSP_MASK); -} - -/** - * nvme_init_get_log_create_telemetry_host() - Initialize passthru command for - * Create Telemetry Host-Initiated - * @cmd: Passthru command to use - * @log: Userspace address of the log payload - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_TELEMETRY_HOST and - * LSP value %NVME_LOG_TELEM_HOST_LSP_CREATE. - */ -static inline void -nvme_init_get_log_create_telemetry_host(struct nvme_passthru_cmd *cmd, - struct nvme_telemetry_log *log) -{ - nvme_init_get_log_create_telemetry_host_mcda(cmd, - NVME_TELEMETRY_DA_CTRL_DETERMINE, log); -} - -/** - * nvme_init_get_log_telemetry_ctrl() - Initialize passthru command for - * Telemetry Controller-Initiated - * @cmd: Passthru command to use - * @lpo: Offset into the telemetry data - * @log: User address for log page data - * @len: Length of provided user buffer to hold the log data in bytes - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_TELEMETRY_CTRL. - */ -static inline void -nvme_init_get_log_telemetry_ctrl(struct nvme_passthru_cmd *cmd, - __u64 lpo, void *log, __u32 len) -{ - nvme_init_get_log(cmd, NVME_NSID_NONE, NVME_LOG_LID_TELEMETRY_CTRL, - NVME_CSI_NVM, log, len); - nvme_init_get_log_lpo(cmd, lpo); -} - -/** - * nvme_init_get_log_endurance_group() - Initialize passthru command for - * Endurance Group Information - * @cmd: Passthru command to use - * @endgid: Starting group identifier to return in the list - * @log: User address to store the endurance log - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_ENDURANCE_GROUP. - */ -static inline void -nvme_init_get_log_endurance_group(struct nvme_passthru_cmd *cmd, __u16 endgid, - struct nvme_endurance_group_log *log) -{ - nvme_init_get_log(cmd, NVME_NSID_NONE, NVME_LOG_LID_ENDURANCE_GROUP, - NVME_CSI_NVM, log, sizeof(*log)); - cmd->cdw11 |= NVME_FIELD_ENCODE(endgid, - NVME_LOG_CDW11_LSI_SHIFT, - NVME_LOG_CDW11_LSI_MASK); -} - -/** - * nvme_init_get_log_predictable_lat_nvmset() - Initialize passthru command for - * Predictable Latency Per NVM Set - * @cmd: Passthru command to use - * @nvmsetid: NVM set id - * @log: User address to store the predictable latency log - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_PREDICTABLE_LAT_NVMSET. - */ -static inline void -nvme_init_get_log_predictable_lat_nvmset(struct nvme_passthru_cmd *cmd, - __u16 nvmsetid, struct nvme_nvmset_predictable_lat_log *log) -{ - nvme_init_get_log(cmd, NVME_NSID_NONE, - NVME_LOG_LID_PREDICTABLE_LAT_NVMSET, NVME_CSI_NVM, - log, sizeof(*log)); - cmd->cdw11 |= NVME_FIELD_ENCODE(nvmsetid, - NVME_LOG_CDW11_LSI_SHIFT, - NVME_LOG_CDW11_LSI_MASK); -} - -/** - * nvme_init_get_log_predictable_lat_event() - Initialize passthru command for - * Predictable Latency Event Aggregate - * @cmd: Passthru command to use - * @lpo: Offset into the predictable latency event - * @log: User address for log page data - * @len: Length of provided user buffer to hold the log data in bytes - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_PREDICTABLE_LAT_AGG. - */ -static inline void -nvme_init_get_log_predictable_lat_event(struct nvme_passthru_cmd *cmd, - __u64 lpo, void *log, __u32 len) -{ - nvme_init_get_log(cmd, NVME_NSID_NONE, - NVME_LOG_LID_PREDICTABLE_LAT_AGG, NVME_CSI_NVM, - log, len); - cmd->cdw12 = lpo & 0xffffffff; - cmd->cdw13 = lpo >> 32; -} - -/** - * nvme_init_get_log_ana() - Initialize passthru command for - * Asymmetric Namespace Access - * @cmd: Passthru command to use - * @lsp: Log specific, see &enum nvme_get_log_ana_lsp - * @lpo: Offset to the start of the log page - * @log: User address to store the ana log - * @len: The allocated length of the log page - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_ANA. - */ -static inline void -nvme_init_get_log_ana(struct nvme_passthru_cmd *cmd, - enum nvme_log_ana_lsp lsp, __u64 lpo, void *log, __u32 len) -{ - nvme_init_get_log(cmd, NVME_NSID_NONE, - NVME_LOG_LID_ANA, NVME_CSI_NVM, - log, len); - cmd->cdw10 |= NVME_FIELD_ENCODE(lsp, - NVME_LOG_CDW10_LSP_SHIFT, - NVME_LOG_CDW10_LSP_MASK); - cmd->cdw12 = lpo & 0xffffffff; - cmd->cdw13 = lpo >> 32; -} - -/** - * nvme_init_get_log_ana_groups() - Initialize passthru command for - * Asymmetric Namespace Access groups - * @cmd: Passthru command to use - * @log: User address to store the ana group log - * @len: The allocated length of the log page - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_ANA and LSP value %NVME_LOG_ANA_LSP_RGO_GROUPS_ONLY - */ -static inline void -nvme_init_get_log_ana_groups(struct nvme_passthru_cmd *cmd, - struct nvme_ana_log *log, __u32 len) -{ - nvme_init_get_log_ana(cmd, NVME_LOG_ANA_LSP_RGO_GROUPS_ONLY, - 0, log, len); -} - -/** - * nvme_init_get_log_persistent_event() - Initialize passthru command for - * Persistent Event Log - * @cmd: Passthru command to use - * @action: Action the controller should take during processing this command - * @pevent_log: User address to store the persistent event log - * @len: Size of @pevent_log - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_PERSISTENT_EVENT - */ -static inline void -nvme_init_get_log_persistent_event(struct nvme_passthru_cmd *cmd, - enum nvme_pevent_log_action action, - void *pevent_log, __u32 len) -{ - nvme_init_get_log(cmd, NVME_NSID_ALL, - NVME_LOG_LID_PERSISTENT_EVENT, NVME_CSI_NVM, - pevent_log, len); - cmd->cdw10 |= NVME_FIELD_ENCODE(action, - NVME_LOG_CDW10_LSP_SHIFT, - NVME_LOG_CDW10_LSP_MASK); -} - -/** - * nvme_init_get_log_lba_status() - Initialize passthru command for - * Retrieve LBA Status - * @cmd: Passthru command to use - * @lpo: Offset to the start of the log page - * @log: User address to store the log page - * @len: The allocated length of the log page - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_LBA_STATUS - */ -static inline void -nvme_init_get_log_lba_status(struct nvme_passthru_cmd *cmd, - __u64 lpo, void *log, __u32 len) -{ - nvme_init_get_log(cmd, NVME_NSID_NONE, - NVME_LOG_LID_LBA_STATUS, NVME_CSI_NVM, - log, len); - cmd->cdw12 = lpo & 0xffffffff; - cmd->cdw13 = lpo >> 32; -} - -/** - * nvme_init_get_log_endurance_grp_evt() - Initialize passthru command for - * Endurance Group Event Aggregate - * @cmd: Passthru command to use - * @lpo: Offset to the start of the log page - * @log: User address to store the log page - * @len: The allocated length of the log page - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_ENDURANCE_GRP_EVT - */ -static inline void -nvme_init_get_log_endurance_grp_evt(struct nvme_passthru_cmd *cmd, - __u64 lpo, void *log, __u32 len) -{ - nvme_init_get_log(cmd, NVME_NSID_NONE, - NVME_LOG_LID_ENDURANCE_GRP_EVT, NVME_CSI_NVM, - log, len); - nvme_init_get_log_lpo(cmd, lpo); -} - -/** - * nvme_init_get_log_media_unit_stat() - Initialize passthru command for - * Media Unit Status - * @cmd: Passthru command to use - * @domid: Domain Identifier selection, if supported - * @mus: User address to store the Media Unit statistics log - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_MEDIA_UNIT_STATUS - */ -static inline void -nvme_init_get_log_media_unit_stat(struct nvme_passthru_cmd *cmd, - __u16 domid, struct nvme_media_unit_stat_log *mus) -{ - nvme_init_get_log(cmd, NVME_NSID_NONE, - NVME_LOG_LID_MEDIA_UNIT_STATUS, NVME_CSI_NVM, - mus, sizeof(*mus)); - cmd->cdw11 |= NVME_FIELD_ENCODE(domid, - NVME_LOG_CDW11_LSI_SHIFT, - NVME_LOG_CDW11_LSI_MASK); -} - -/** - * nvme_init_get_log_support_cap_config_list() - Initialize passthru command for - * Supported Capacity Configuration List - * @cmd: Passthru command to use - * @domid: Domain Identifier selection, if supported - * @cap: User address to store supported capabilities config list - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_SUPPORTED_CAP_CONFIG_LIST - */ -static inline void -nvme_init_get_log_support_cap_config_list(struct nvme_passthru_cmd *cmd, - __u16 domid, struct nvme_supported_cap_config_list_log *cap) -{ - nvme_init_get_log(cmd, NVME_NSID_NONE, - NVME_LOG_LID_SUPPORTED_CAP_CONFIG_LIST, NVME_CSI_NVM, - cap, sizeof(*cap)); - cmd->cdw11 |= NVME_FIELD_ENCODE(domid, - NVME_LOG_CDW11_LSI_SHIFT, - NVME_LOG_CDW11_LSI_MASK); -} - -/** - * nvme_init_get_log_fid_supported_effects() - Initialize passthru command for - * Feature Identifiers Supported and Effects - * @cmd: Passthru command to use - * @csi: Command set identifier, see &enum nvme_csi for known values - * @log: FID Supported and Effects data structure - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_FID_SUPPORTED_EFFECTS - */ -static inline void -nvme_init_get_log_fid_supported_effects(struct nvme_passthru_cmd *cmd, - enum nvme_csi csi, struct nvme_fid_supported_effects_log *log) -{ - nvme_init_get_log(cmd, NVME_NSID_NONE, - NVME_LOG_LID_FID_SUPPORTED_EFFECTS, csi, - log, sizeof(*log)); -} - -/** - * nvme_init_get_log_mi_cmd_supported_effects() - Initialize passthru command - * for MI Commands Supported by the controller - * @cmd: Passthru command to use - * @log: MI Command Supported and Effects data structure - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_MI_CMD_SUPPORTED_EFFECTS - */ -static inline void -nvme_init_get_log_mi_cmd_supported_effects(struct nvme_passthru_cmd *cmd, - struct nvme_mi_cmd_supported_effects_log *log) -{ - nvme_init_get_log(cmd, NVME_NSID_NONE, - NVME_LOG_LID_MI_CMD_SUPPORTED_EFFECTS, NVME_CSI_NVM, - log, sizeof(*log)); -} - -/** - * nvme_init_get_log_lockdown() - Initialize passthru command for - * Command and Feature Lockdown - * @cmd: Passthru command to use - * @cnscp: Contents and Scope of Command and Feature Identifier - * Lists - * @lockdown_log: Buffer to store the lockdown log - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_CMD_AND_FEAT_LOCKDOWN - */ -static inline void -nvme_init_get_log_lockdown(struct nvme_passthru_cmd *cmd, - __u8 cnscp, struct nvme_lockdown_log *lockdown_log) -{ - nvme_init_get_log(cmd, NVME_NSID_ALL, - NVME_LOG_LID_CMD_AND_FEAT_LOCKDOWN, NVME_CSI_NVM, - lockdown_log, sizeof(*lockdown_log)); - cmd->cdw10 |= NVME_FIELD_ENCODE(cnscp, - NVME_LOG_CDW10_LSP_SHIFT, - NVME_LOG_CDW10_LSP_MASK); -} - -/** - * nvme_init_get_log_boot_partition() - Initialize passthru command for - * Boot Partition - * @cmd: Passthru command to use - * @lsp: The log specified field of LID - * @part: User address to store the log page - * @len: The allocated size, minimum - * struct nvme_boot_partition - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_BOOT_PARTITION - */ -static inline void -nvme_init_get_log_boot_partition(struct nvme_passthru_cmd *cmd, - __u8 lsp, struct nvme_boot_partition *part, __u32 len) -{ - nvme_init_get_log(cmd, NVME_NSID_NONE, - NVME_LOG_LID_BOOT_PARTITION, NVME_CSI_NVM, - part, len); - cmd->cdw10 |= NVME_FIELD_ENCODE(lsp, - NVME_LOG_CDW10_LSP_SHIFT, - NVME_LOG_CDW10_LSP_MASK); -} - -/** - * nvme_init_get_log_rotational_media_info() - Initialize passthru command for - * Rotational Media Information Log - * @cmd: Passthru command to use - * @endgid: Endurance Group Identifier - * @log: User address to store the log page - * @len: The allocated length of the log page - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_ROTATIONAL_MEDIA_INFO - */ -static inline void -nvme_init_get_log_rotational_media_info(struct nvme_passthru_cmd *cmd, - __u16 endgid, struct nvme_rotational_media_info_log *log, - __u32 len) -{ - nvme_init_get_log(cmd, NVME_NSID_NONE, - NVME_LOG_LID_ROTATIONAL_MEDIA_INFO, NVME_CSI_NVM, - log, len); - cmd->cdw11 |= NVME_FIELD_ENCODE(endgid, - NVME_LOG_CDW11_LSI_SHIFT, - NVME_LOG_CDW11_LSI_MASK); -} - -/** - * nvme_init_get_log_dispersed_ns_participating_nss() - Initialize passthru - * command for Dispersed Namespace Participating NVM Subsystems - * @cmd: Passthru command to use - * @nsid: Namespace Identifier - * @log: User address to store the log page - * @len: The allocated length of the log page - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_DISPERSED_NS_PARTICIPATING_NSS - */ -static inline void -nvme_init_get_log_dispersed_ns_participating_nss(struct nvme_passthru_cmd *cmd, - __u32 nsid, struct nvme_dispersed_ns_participating_nss_log *log, - __u32 len) -{ - nvme_init_get_log(cmd, nsid, - NVME_LOG_LID_DISPERSED_NS_PARTICIPATING_NSS, NVME_CSI_NVM, - log, len); -} - -/** - * nvme_init_get_log_mgmt_addr_list() - Initialize passthru command for - * Management Address List - * @cmd: Passthru command to use - * @log: User address to store the log page - * @len: The allocated length of the log page - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_MGMT_ADDR_LIST - */ -static inline void -nvme_init_get_log_mgmt_addr_list(struct nvme_passthru_cmd *cmd, - struct nvme_mgmt_addr_list_log *log, __u32 len) -{ - nvme_init_get_log(cmd, NVME_NSID_ALL, - NVME_LOG_LID_MGMT_ADDR_LIST, NVME_CSI_NVM, - log, len); -} - -/** - * nvme_init_get_log_phy_rx_eom() - Initialize passthru command for - * Physical Interface Receiver Eye Opening Measurement - * @cmd: Passthru command to use - * @lsp: Log specific, controls action and measurement quality - * @controller: Target controller ID - * @log: User address to store the log page - * @len: The allocated size, minimum - * struct nvme_phy_rx_eom_log - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_PHY_RX_EOM - */ -static inline void -nvme_init_get_log_phy_rx_eom(struct nvme_passthru_cmd *cmd, - __u8 lsp, __u16 controller, struct nvme_phy_rx_eom_log *log, - __u32 len) -{ - nvme_init_get_log(cmd, NVME_NSID_NONE, - NVME_LOG_LID_PHY_RX_EOM, NVME_CSI_NVM, - log, len); - cmd->cdw10 |= NVME_FIELD_ENCODE(lsp, - NVME_LOG_CDW10_LSP_SHIFT, - NVME_LOG_CDW10_LSP_MASK); - cmd->cdw11 |= NVME_FIELD_ENCODE(controller, - NVME_LOG_CDW11_LSI_SHIFT, - NVME_LOG_CDW11_LSI_MASK); -} - -/** - * nvme_init_get_log_reachability_groups() - Initialize passthru command for - * Retrieve Reachability Groups - * @cmd: Passthru command to use - * @rgo: Return groups only - * @log: User address to store the log page - * @len: The allocated length of the log page - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_REACHABILITY_GROUPS - */ -static inline void -nvme_init_get_log_reachability_groups(struct nvme_passthru_cmd *cmd, - bool rgo, struct nvme_reachability_groups_log *log, __u32 len) -{ - nvme_init_get_log(cmd, NVME_NSID_ALL, - NVME_LOG_LID_REACHABILITY_GROUPS, NVME_CSI_NVM, - log, len); - cmd->cdw10 |= NVME_FIELD_ENCODE((__u8)rgo, - NVME_LOG_CDW10_LSP_SHIFT, - NVME_LOG_CDW10_LSP_MASK); -} - -/** - * nvme_init_get_log_reachability_associations() - Initialize passthru command - * for Reachability Associations Log - * @cmd: Passthru command to use - * @rao: Return associations only - * @log: User address to store the log page - * @len: The allocated length of the log page - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_REACHABILITY_ASSOCIATIONS - */ -static inline void -nvme_init_get_log_reachability_associations(struct nvme_passthru_cmd *cmd, - bool rao, struct nvme_reachability_associations_log *log, - __u32 len) -{ - nvme_init_get_log(cmd, NVME_NSID_ALL, - NVME_LOG_LID_REACHABILITY_ASSOCIATIONS, NVME_CSI_NVM, - log, len); - cmd->cdw10 |= NVME_FIELD_ENCODE((__u8)rao, - NVME_LOG_CDW10_LSP_SHIFT, - NVME_LOG_CDW10_LSP_MASK); -} - -/** - * nvme_init_get_log_changed_alloc_ns() - Initialize passthru command for - * Changed Allocated Namespace List - * @cmd: Passthru command to use - * @log: User address to store the log page - * @len: The allocated length of the log page - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_CHANGED_ALLOC_NS - */ -static inline void -nvme_init_get_log_changed_alloc_ns(struct nvme_passthru_cmd *cmd, - struct nvme_ns_list *log, __u32 len) -{ - nvme_init_get_log(cmd, NVME_NSID_ALL, - NVME_LOG_LID_CHANGED_ALLOC_NS, NVME_CSI_NVM, - log, len); -} - -/** - * nvme_init_get_log_fdp_configurations() - Initialize passthru command for - * Flexible Data Placement Configurations - * @cmd: Passthru command to use - * @egid: Endurance group identifier - * @lpo: Offset into log page - * @log: Log page data buffer - * @len: Length (in bytes) of provided user buffer to hold the log data - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_FDP_CONFIGS - */ -static inline void -nvme_init_get_log_fdp_configurations(struct nvme_passthru_cmd *cmd, - __u16 egid, __u64 lpo, void *log, __u32 len) -{ - nvme_init_get_log(cmd, NVME_NSID_NONE, - NVME_LOG_LID_FDP_CONFIGS, NVME_CSI_NVM, - log, len); - cmd->cdw11 |= NVME_FIELD_ENCODE(egid, - NVME_LOG_CDW11_LSI_SHIFT, - NVME_LOG_CDW11_LSI_MASK); - nvme_init_get_log_lpo(cmd, lpo); -} - -/** - * nvme_init_get_log_reclaim_unit_handle_usage() - Initialize passthru - * command for Reclaim Unit Handle Usage - * @cmd: Passthru command to use - * @egid: Endurance group identifier - * @lpo: Offset into log page - * @log: Log page data buffer - * @len: Length (in bytes) of provided user buffer to hold the log data - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_RUH_USAGE - */ -static inline void -nvme_init_get_log_reclaim_unit_handle_usage(struct nvme_passthru_cmd *cmd, - __u16 egid, __u64 lpo, void *log, __u32 len) -{ - nvme_init_get_log(cmd, NVME_NSID_NONE, - NVME_LOG_LID_FDP_RUH_USAGE, NVME_CSI_NVM, - log, len); - cmd->cdw11 |= NVME_FIELD_ENCODE(egid, - NVME_LOG_CDW11_LSI_SHIFT, - NVME_LOG_CDW11_LSI_MASK); - nvme_init_get_log_lpo(cmd, lpo); -} - -/** - * nvme_init_get_log_fdp_stats() - Initialize passthru command for - * Get Flexible Data Placement Statistics - * @cmd: Passthru command to use - * @egid: Endurance group identifier - * @lpo: Offset into log page - * @log: Log page data buffer - * @len: Length (in bytes) of provided user buffer to hold the log data - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_FDP_STATS - */ -static inline -void nvme_init_get_log_fdp_stats(struct nvme_passthru_cmd *cmd, - __u16 egid, __u64 lpo, void *log, __u32 len) -{ - nvme_init_get_log(cmd, NVME_NSID_NONE, - NVME_LOG_LID_FDP_STATS, NVME_CSI_NVM, - log, len); - cmd->cdw11 |= NVME_FIELD_ENCODE(egid, - NVME_LOG_CDW11_LSI_SHIFT, - NVME_LOG_CDW11_LSI_MASK); - nvme_init_get_log_lpo(cmd, lpo); -} - -/** - * nvme_init_get_log_fdp_events() - Initialize passthru command for - * Flexible Data Placement Events - * @cmd: Passthru command to use - * @host_events: Whether to report host or controller events - * @egid: Endurance group identifier - * @lpo: Offset into log page - * @log: Log page data buffer - * @len: Length (in bytes) of provided user buffer to hold - * the log data - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_FDP_EVENTS - */ -static inline void -nvme_init_get_log_fdp_events(struct nvme_passthru_cmd *cmd, - bool host_events, __u16 egid, __u64 lpo, void *log, __u32 len) -{ - nvme_init_get_log(cmd, NVME_NSID_NONE, - NVME_LOG_LID_FDP_EVENTS, NVME_CSI_NVM, - log, len); - cmd->cdw10 |= NVME_FIELD_ENCODE((__u8)(host_events ? 0x1 : 0x0), - NVME_LOG_CDW10_LSP_SHIFT, - NVME_LOG_CDW10_LSP_MASK); - cmd->cdw11 |= NVME_FIELD_ENCODE(egid, - NVME_LOG_CDW11_LSI_SHIFT, - NVME_LOG_CDW11_LSI_MASK); - nvme_init_get_log_lpo(cmd, lpo); -} - - -/** - * nvme_init_get_log_discovery() - Initialize passthru command for Discovery - * @cmd: Passthru command to use - * @lpo: Offset of this log to retrieve - * @log: User address to store the discovery log - * @len: The allocated size for this portion of the log - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_DISCOVERY - */ -static inline void -nvme_init_get_log_discovery(struct nvme_passthru_cmd *cmd, - __u64 lpo, void *log, __u32 len) -{ - nvme_init_get_log(cmd, NVME_NSID_NONE, - NVME_LOG_LID_DISCOVERY, NVME_CSI_NVM, - log, len); - nvme_init_get_log_lpo(cmd, lpo); -} - -/** - * nvme_init_get_log_host_discovery() - Initialize passthru command for - * Host Discover - * @cmd: Passthru command to use - * @allhoste: All host entries - * @log: User address to store the log page - * @len: The allocated length of the log page - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_HOST_DISCOVERY - */ -static inline void -nvme_init_get_log_host_discovery(struct nvme_passthru_cmd *cmd, - bool allhoste, struct nvme_host_discover_log *log, __u32 len) -{ - nvme_init_get_log(cmd, NVME_NSID_ALL, - NVME_LOG_LID_HOST_DISCOVERY, NVME_CSI_NVM, - log, len); - cmd->cdw10 |= NVME_FIELD_ENCODE((__u8)allhoste, - NVME_LOG_CDW10_LSP_SHIFT, - NVME_LOG_CDW10_LSP_MASK); -} - -/** - * nvme_init_get_log_ave_discovery() - Initialize passthru command for - * AVE Discovery - * @cmd: Passthru command to use - * @log: User address to store the log page - * @len: The allocated length of the log page - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_AVE_DISCOVERY - */ -static inline void -nvme_init_get_log_ave_discovery(struct nvme_passthru_cmd *cmd, - struct nvme_ave_discover_log *log, __u32 len) -{ - nvme_init_get_log(cmd, NVME_NSID_ALL, - NVME_LOG_LID_AVE_DISCOVERY, NVME_CSI_NVM, - log, len); -} - -/** - * nvme_init_get_log_pull_model_ddc_req() - Initialize passthru command for - * Pull Model DDC Request - * @cmd: Passthru command to use - * @log: User address to store the log page - * @len: The allocated length of the log page - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_PULL_MODEL_DDC_REQ - */ -static inline void -nvme_init_get_log_pull_model_ddc_req(struct nvme_passthru_cmd *cmd, - struct nvme_pull_model_ddc_req_log *log, __u32 len) -{ - nvme_init_get_log(cmd, NVME_NSID_ALL, - NVME_LOG_LID_PULL_MODEL_DDC_REQ, NVME_CSI_NVM, - log, len); -} - -/** - * nvme_init_get_log_reservation() - Initialize passthru command for - * Reservation Notification - * @cmd: Passthru command to use - * @log: User address to store the reservation log - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_RESERVATION - */ -static inline void -nvme_init_get_log_reservation(struct nvme_passthru_cmd *cmd, - struct nvme_resv_notification_log *log) -{ - nvme_init_get_log(cmd, NVME_NSID_ALL, - NVME_LOG_LID_RESERVATION, NVME_CSI_NVM, - log, sizeof(*log)); -} - -/** - * nvme_init_get_log_sanitize() - Initialize passthru command for - * Sanitize Status - * @cmd: Passthru command to use - * @log: User address to store the sanitize log - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_SANITIZE - */ -static inline void -nvme_init_get_log_sanitize(struct nvme_passthru_cmd *cmd, - struct nvme_sanitize_log_page *log) -{ - nvme_init_get_log(cmd, NVME_NSID_ALL, - NVME_LOG_LID_SANITIZE, NVME_CSI_NVM, - log, sizeof(*log)); -} - -/** - * nvme_init_get_log_zns_changed_zones() - Initialize passthru command for - * list of zones that have changed - * @cmd: Passthru command to use - * @nsid: Namespace ID - * @log: User address to store the changed zone log - * - * Initializes the passthru command buffer for the Get Log command with - * LID value %NVME_LOG_LID_ZNS_CHANGED_ZONES - */ -static inline void -nvme_init_get_log_zns_changed_zones(struct nvme_passthru_cmd *cmd, - __u32 nsid, struct nvme_zns_changed_zone_log *log) -{ - nvme_init_get_log(cmd, nsid, - NVME_LOG_LID_ZNS_CHANGED_ZONES, NVME_CSI_ZNS, - log, sizeof(*log)); -} - -/** - * nvme_get_ana_log_atomic() - Retrieve Asymmetric Namespace Access - * log page atomically - * @hdl: Transport handle - * @rae: Whether to retain asynchronous events - * @rgo: Whether to retrieve ANA groups only (no NSIDs) - * @log: Pointer to a buffer to receive the ANA log page - * @len: Input: the length of the log page buffer. - * Output: the actual length of the ANA log page. - * @retries: The maximum number of times to retry on log page changes - * - * See &struct nvme_ana_log for the definition of the returned structure. - * - * Return: If successful, returns 0 and sets *len to the actual log page length. - * If unsuccessful, returns the nvme command status if a response was received - * (see &enum nvme_status_field) or -1 with errno set otherwise. - * Sets errno = EINVAL if retries == 0. - * Sets errno = EAGAIN if unable to read the log page atomically - * because chgcnt changed during each of the retries attempts. - * Sets errno = ENOSPC if the full log page does not fit in the provided buffer. - */ -int -nvme_get_ana_log_atomic(struct nvme_transport_handle *hdl, bool rae, bool rgo, - struct nvme_ana_log *log, __u32 *len, unsigned int retries); - -/** - * nvme_init_set_features() - Initialize passthru command for - * Set Features - * @cmd: Passthru command to use - * @fid: Feature identifier - * @sv: Save value across power states - */ -static inline void -nvme_init_set_features(struct nvme_passthru_cmd *cmd, __u8 fid, bool sv) -{ - __u32 cdw10 = NVME_FIELD_ENCODE(fid, - NVME_SET_FEATURES_CDW10_FID_SHIFT, - NVME_SET_FEATURES_CDW10_FID_MASK) | - NVME_FIELD_ENCODE(sv, - NVME_SET_FEATURES_CDW10_SV_SHIFT, - NVME_SET_FEATURES_CDW10_SV_MASK); - - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_admin_set_features; - cmd->cdw10 = cdw10; -} - -/** - * nvme_init_set_features_arbitration() -Initialize passthru command for - * Arbitration Features - * @cmd: Passthru command to use - * @sv: Save value across power states - * @ab: Arbitration Burst - * @lpw: Low Priority Weight - * @mpw: Medium Priority Weight - * @hpw: High Priority Weight - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_ARBRITARTION - */ -static inline void -nvme_init_set_features_arbitration(struct nvme_passthru_cmd *cmd, - bool sv, __u8 ab, __u8 lpw, __u8 mpw, __u8 hpw) -{ - nvme_init_set_features(cmd, NVME_FEAT_FID_ARBITRATION, sv); - cmd->cdw11 = NVME_FIELD_ENCODE(ab, - NVME_FEAT_ARBITRATION_BURST_SHIFT, - NVME_FEAT_ARBITRATION_BURST_MASK) | - NVME_FIELD_ENCODE(lpw, - NVME_FEAT_ARBITRATION_LPW_SHIFT, - NVME_FEAT_ARBITRATION_LPW_MASK) | - NVME_FIELD_ENCODE(mpw, - NVME_FEAT_ARBITRATION_MPW_SHIFT, - NVME_FEAT_ARBITRATION_MPW_MASK) | - NVME_FIELD_ENCODE(hpw, - NVME_FEAT_ARBITRATION_HPW_SHIFT, - NVME_FEAT_ARBITRATION_HPW_MASK); -} - -/** - * nvme_init_set_features_power_mgmt() - Initialize passthru command for - * Power Management - * @cmd: Passthru command to use - * @sv: Save value across power states - * @ps: Power State - * @wh: Workload Hint - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_PWRMGMT_PS - */ -static inline void -nvme_init_set_features_power_mgmt(struct nvme_passthru_cmd *cmd, - bool sv, __u8 ps, __u8 wh) -{ - - nvme_init_set_features(cmd, NVME_FEAT_FID_POWER_MGMT, sv); - cmd->cdw11 = NVME_FIELD_ENCODE(ps, - NVME_FEAT_PWRMGMT_PS_SHIFT, - NVME_FEAT_PWRMGMT_PS_MASK) | - NVME_FIELD_ENCODE(wh, - NVME_FEAT_PWRMGMT_WH_SHIFT, - NVME_FEAT_PWRMGMT_WH_MASK); -} - -/** - * nvme_init_set_features_lba_range() - Initialize passthru command for - * LBA Range - * @cmd: Passthru command to use - * @nsid: Namespace ID - * @sv: Save value across power states - * @num: Number of ranges in @data - * @data: User address of feature data - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_LBA_RANGE - */ -static inline void -nvme_init_set_features_lba_range(struct nvme_passthru_cmd *cmd, - __u32 nsid, bool sv, __u8 num, - struct nvme_lba_range_type *data) -{ - nvme_init_set_features(cmd, NVME_FEAT_FID_LBA_RANGE, sv); - cmd->nsid = nsid; - cmd->cdw11 = NVME_FIELD_ENCODE(num - 1, - NVME_SET_FEATURES_CDW11_NUM_SHIFT, - NVME_SET_FEATURES_CDW11_NUM_MASK); - cmd->data_len = sizeof(*data); - cmd->addr = (__u64)(uintptr_t)data; -} - -/** - * nvme_init_set_features_temp_thresh() - Initialize passthru command for - * Temperature Threshold - * @cmd: Passthru command to use - * @sv: Save value across power states - * @tmpth: Temperature Threshold - * @tmpsel: Threshold Temperature Select - * @thsel: Threshold Type Select - * @tmpthh: Temperature Threshold Hysteresis - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_TEMP_THRESH - */ -static inline void -nvme_init_set_features_temp_thresh(struct nvme_passthru_cmd *cmd, - bool sv, __u16 tmpth, __u8 tmpsel, - enum nvme_feat_tmpthresh_thsel thsel, __u8 tmpthh) -{ - - nvme_init_set_features(cmd, NVME_FEAT_FID_TEMP_THRESH, sv); - cmd->cdw11 = NVME_FIELD_ENCODE(tmpth, - NVME_FEAT_TT_TMPTH_SHIFT, - NVME_FEAT_TT_TMPTH_MASK) | - NVME_FIELD_ENCODE(tmpsel, - NVME_FEAT_TT_TMPSEL_SHIFT, - NVME_FEAT_TT_TMPSEL_MASK) | - NVME_FIELD_ENCODE(thsel, - NVME_FEAT_TT_THSEL_SHIFT, - NVME_FEAT_TT_THSEL_MASK) | - NVME_FIELD_ENCODE(tmpthh, - NVME_FEAT_TT_TMPTHH_SHIFT, - NVME_FEAT_TT_TMPTHH_MASK); -} - -/** - * nvme_init_set_features_err_recovery() - Initialize passthru command for - * Error Recovery - * @cmd: Passthru command to use - * @nsid: Namespace ID - * @sv: Save value across power states - * @tler: Time-limited error recovery value - * @dulbe: Deallocated or Unwritten Logical Block Error Enable - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_ERR_RECOVERY - */ -static inline void -nvme_init_set_features_err_recovery(struct nvme_passthru_cmd *cmd, - __u32 nsid, bool sv, __u16 tler, bool dulbe) -{ - nvme_init_set_features(cmd, NVME_FEAT_FID_ERR_RECOVERY, sv); - cmd->nsid = nsid; - cmd->cdw11 = NVME_FIELD_ENCODE(tler, - NVME_FEAT_ERROR_RECOVERY_TLER_SHIFT, - NVME_FEAT_ERROR_RECOVERY_TLER_MASK) | - NVME_FIELD_ENCODE(dulbe, - NVME_FEAT_ERROR_RECOVERY_DULBE_SHIFT, - NVME_FEAT_ERROR_RECOVERY_DULBE_MASK); -} - -/** - * nvme_init_set_features_volatile_wc() - Initialize passthru command for - * Volatile Write Cache - * @cmd: Passthru command to use - * @sv: Save value across power states - * @wce: Write cache enable - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_VOLATILE_WC - */ -static inline void -nvme_init_set_features_volatile_wc(struct nvme_passthru_cmd *cmd, - bool sv, bool wce) -{ - nvme_init_set_features(cmd, NVME_FEAT_FID_VOLATILE_WC, sv); - cmd->cdw11 = NVME_FIELD_ENCODE(wce, - NVME_FEAT_VWC_WCE_SHIFT, - NVME_FEAT_VWC_WCE_MASK); -} - -/** - * nvme_init_set_features_irq_coalesce() - Initialize passthru command for - * IRQ Coalescing - * @cmd: Passthru command to use - * @sv: Save value across power states - * @thr: Aggregation Threshold - * @time: Aggregation Time - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_IRQ_COALESCE - */ -static inline void -nvme_init_set_features_irq_coalesce(struct nvme_passthru_cmd *cmd, - bool sv, __u8 thr, __u8 time) -{ - nvme_init_set_features(cmd, NVME_FEAT_FID_IRQ_COALESCE, sv); - cmd->cdw11 = NVME_FIELD_ENCODE(thr, - NVME_FEAT_IRQC_THR_SHIFT, - NVME_FEAT_IRQC_THR_MASK) | - NVME_FIELD_ENCODE(time, - NVME_FEAT_IRQC_TIME_SHIFT, - NVME_FEAT_IRQC_TIME_MASK); -} - -/** - * nvme_init_set_features_irq_config() - Initialize passthru command for - * IRQ Config - * @cmd: Passthru command to use - * @sv: Save value across power states - * @iv: Interrupt Vector - * @cd: Coalescing Disable - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_IRQ_CONFIG - */ -static inline void -nvme_init_set_features_irq_config(struct nvme_passthru_cmd *cmd, - bool sv, __u16 iv, bool cd) -{ - nvme_init_set_features(cmd, NVME_FEAT_FID_IRQ_CONFIG, sv); - cmd->cdw11 = NVME_FIELD_ENCODE(iv, - NVME_FEAT_ICFG_IV_SHIFT, - NVME_FEAT_ICFG_IV_MASK) | - NVME_FIELD_ENCODE(cd, - NVME_FEAT_ICFG_CD_SHIFT, - NVME_FEAT_ICFG_CD_MASK); -} - -/** - * nvme_init_set_features_write_atomic() - Initialize passthru command for - * Write Atomic - * @cmd: Passthru command to use - * @sv: Save value across power states - * @dn: Disable Normal - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_WRITE_ATOMIC - */ -static inline void -nvme_init_set_features_write_atomic(struct nvme_passthru_cmd *cmd, - bool sv, bool dn) -{ - nvme_init_set_features(cmd, NVME_FEAT_FID_WRITE_ATOMIC, sv); - cmd->cdw11 = NVME_FIELD_ENCODE(dn, - NVME_FEAT_WA_DN_SHIFT, - NVME_FEAT_WA_DN_MASK); -} - -/** - * nvme_init_set_features_async_event() - Initialize passthru command for - * Asynchronous Event Configuration - * @cmd: Passthru command to use - * @sv: Save value across power states - * @events: Events to enable - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_ASYNC_EVENT - */ -static inline void -nvme_init_set_features_async_event(struct nvme_passthru_cmd *cmd, - bool sv, __u32 events) -{ - nvme_init_set_features(cmd, NVME_FEAT_FID_ASYNC_EVENT, sv); - cmd->cdw11 = events; -} - -/** - * nvme_init_set_features_auto_pst() - Initialize passthru command for - * Autonomous Power State Transition - * @cmd: Passthru command to use - * @sv: Save value across power states - * @apste: Autonomous Power State Transition Enable - * @apst: Autonomous Power State Transition data buffer - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_AUTO_PST - */ -static inline void -nvme_init_set_features_auto_pst(struct nvme_passthru_cmd *cmd, - bool sv, bool apste, struct nvme_feat_auto_pst *apst) -{ - nvme_init_set_features(cmd, NVME_FEAT_FID_AUTO_PST, sv); - cmd->cdw11 = NVME_FIELD_ENCODE(apste, - NVME_FEAT_APST_APSTE_SHIFT, - NVME_FEAT_APST_APSTE_MASK); - cmd->data_len = sizeof(*apst); - cmd->addr = (__u64)(uintptr_t)apst; -} - -/** - * nvme_init_set_features_timestamp() - Initialize passthru command for - * Timestamp - * @cmd: Passthru command to use - * @sv: Save value across power states - * @tstmp: The current timestamp value to assign to this feature - * @ts: Timestamp data buffer (populated by this function) - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_TIMESTAMP. The caller must provide a valid - * buffer via @ts, which this function will populate. - */ -static inline void -nvme_init_set_features_timestamp(struct nvme_passthru_cmd *cmd, - bool sv, __u64 tstmp, struct nvme_timestamp *ts) -{ - __le64 t = htole64(tstmp); - - memcpy(ts, &t, sizeof(__le64)); - - nvme_init_set_features(cmd, NVME_FEAT_FID_TIMESTAMP, sv); - cmd->data_len = sizeof(*ts); - cmd->addr = (__u64)(uintptr_t)ts; -} - -/** - * nvme_init_set_features_hctm() - Initialize passthru command for - * Host Controlled Thermal Management - * @cmd: Passthru command to use - * @sv: Save value across power states - * @tmt2: Thermal Management Temperature 2 - * @tmt1: Thermal Management Temperature 1 - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_HCTM - */ -static inline void -nvme_init_set_features_hctm(struct nvme_passthru_cmd *cmd, - bool sv, __u16 tmt2, __u16 tmt1) -{ - nvme_init_set_features(cmd, NVME_FEAT_FID_HCTM, sv); - cmd->cdw11 = NVME_FIELD_ENCODE(tmt2, - NVME_FEAT_HCTM_TMT2_SHIFT, - NVME_FEAT_HCTM_TMT2_MASK) | - NVME_FIELD_ENCODE(tmt1, - NVME_FEAT_HCTM_TMT1_SHIFT, - NVME_FEAT_HCTM_TMT1_MASK); -} - -/** - * nvme_init_set_features_nopsc() - Initialize passthru command for - * Non-Operational Power State Config - * @cmd: Passthru command to use - * @sv: Save value across power states - * @noppme: Non-Operational Power State Permissive Mode Enable - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_NOPSC - */ -static inline void -nvme_init_set_features_nopsc(struct nvme_passthru_cmd *cmd, - bool sv, bool noppme) -{ - nvme_init_set_features(cmd, NVME_FEAT_FID_NOPSC, sv); - cmd->cdw11 = NVME_FIELD_ENCODE(noppme, - NVME_FEAT_NOPS_NOPPME_SHIFT, - NVME_FEAT_NOPS_NOPPME_MASK); -} - -/** - * nvme_init_set_features_rrl() - Initialize passthru command for - * Read Recovery Level - * @cmd: Passthru command to use - * @sv: Save value across power states - * @nvmsetid: NVM set id - * @rrl: Read recovery level setting - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_RRL - */ -static inline void -nvme_init_set_features_rrl(struct nvme_passthru_cmd *cmd, - bool sv, __u16 nvmsetid, __u8 rrl) -{ - nvme_init_set_features(cmd, NVME_FEAT_FID_RRL, sv); - cmd->cdw11 = NVME_FIELD_ENCODE(nvmsetid, - NVME_FEAT_RRL_NVMSETID_SHIFT, - NVME_FEAT_RRL_NVMSETID_MASK); - cmd->cdw12 = NVME_FIELD_ENCODE(rrl, - NVME_FEAT_RRL_RRL_SHIFT, - NVME_FEAT_RRL_RRL_MASK); -} - -/** - * nvme_init_set_features_plm_config() - Initialize passthru command for - * Predictable Latency Mode Config - * @cmd: Passthru command to use - * @sv: Save value across power states - * @nvmsetid: NVM Set Identifier - * @lpe: Predictable Latency Enable - * @data: Pointer to structure nvme_plm_config - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_PLM_CONFIG - */ -static inline void -nvme_init_set_features_plm_config(struct nvme_passthru_cmd *cmd, - bool sv, __u16 nvmsetid, bool lpe, struct nvme_plm_config *data) -{ - nvme_init_set_features(cmd, NVME_FEAT_FID_PLM_CONFIG, sv); - cmd->cdw11 = NVME_FIELD_ENCODE(nvmsetid, - NVME_FEAT_PLM_NVMSETID_SHIFT, - NVME_FEAT_PLM_NVMSETID_MASK); - cmd->cdw12 = NVME_FIELD_ENCODE(lpe, - NVME_FEAT_PLM_LPE_SHIFT, - NVME_FEAT_PLM_LPE_MASK); - cmd->data_len = sizeof(*data); - cmd->addr = (__u64)(uintptr_t)data; -} - -/** - * nvme_init_set_features_plm_window() - Initialize passthru command for - * Predictable Latency Mode Window - * @cmd: Passthru command to use - * @sv: Save value across power states - * @nvmsetid: NVM Set Identifier - * @wsel: Window Select - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_PLM_WINDOW - */ -static inline void -nvme_init_set_features_plm_window(struct nvme_passthru_cmd *cmd, - bool sv, __u16 nvmsetid, - enum nvme_feat_plm_window_select wsel) -{ - nvme_init_set_features(cmd, NVME_FEAT_FID_PLM_WINDOW, sv); - cmd->cdw11 = NVME_FIELD_ENCODE(nvmsetid, - NVME_FEAT_PLM_NVMSETID_SHIFT, - NVME_FEAT_PLM_NVMSETID_MASK); - cmd->cdw12 = NVME_FIELD_ENCODE(wsel, - NVME_FEAT_PLMW_WS_SHIFT, - NVME_FEAT_PLMW_WS_MASK); -} - -/** - * nvme_init_set_features_lba_sts_interval() - Initialize passthru command for - * LBA Status Information Interval - * @cmd: Passthru command to use - * @sv: Save value across power states - * @lsiri: LBA Status Information Report Interval - * @lsipi: LBA Status Information Poll Interval - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_LBA_STS_INTERVAL - */ -static inline void -nvme_init_set_features_lba_sts_interval(struct nvme_passthru_cmd *cmd, - bool sv, __u16 lsiri, __u16 lsipi) -{ - nvme_init_set_features(cmd, NVME_FEAT_FID_LBA_STS_INTERVAL, sv); - cmd->cdw11 = NVME_FIELD_ENCODE(lsiri, - NVME_FEAT_LBAS_LSIRI_SHIFT, - NVME_FEAT_LBAS_LSIRI_MASK) | - NVME_FIELD_ENCODE(lsipi, - NVME_FEAT_LBAS_LSIPI_SHIFT, - NVME_FEAT_LBAS_LSIPI_MASK); -} - -/** - * nvme_init_set_features_host_behavior() - Initialize passthru command for - * Host Behavior - * @cmd: Passthru command to use - * @sv: Save value across power states - * @data: Pointer to structure nvme_feat_host_behavior - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_HOST_BEHAVIOR - */ -static inline void -nvme_init_set_features_host_behavior(struct nvme_passthru_cmd *cmd, - bool sv, struct nvme_feat_host_behavior *data) -{ - nvme_init_set_features(cmd, NVME_FEAT_FID_HOST_BEHAVIOR, sv); - cmd->data_len = sizeof(*data); - cmd->addr = (__u64)(uintptr_t)data; -} - -/** - * nvme_init_set_features_sanitize() - Initialize passthru command for - * Sanitize - * @cmd: Passthru command to use - * @sv: Save value across power states - * @nodrm: No-Deallocate Response Mode - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_SANITIZE - */ -static inline void -nvme_init_set_features_sanitize(struct nvme_passthru_cmd *cmd, - bool sv, bool nodrm) -{ - nvme_init_set_features(cmd, NVME_FEAT_FID_SANITIZE, sv); - cmd->cdw11 = NVME_FIELD_ENCODE(nodrm, - NVME_FEAT_SANITIZE_NODRM_SHIFT, - NVME_FEAT_SANITIZE_NODRM_MASK); -} - -/** - * nvme_init_set_features_endurance_evt_cfg() - Initialize passthru command for - * Endurance Group Event Configuration - * @cmd: Passthru command to use - * @sv: Save value across power states - * @endgid: Endurance Group Identifier - * @egcw: Flags to enable warning, - * see &enum nvme_eg_critical_warning_flags - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_ENDURANCE_EVT_CFG - */ -static inline void -nvme_init_set_features_endurance_evt_cfg(struct nvme_passthru_cmd *cmd, - bool sv, __u16 endgid, __u8 egcw) -{ - nvme_init_set_features(cmd, NVME_FEAT_FID_ENDURANCE_EVT_CFG, sv); - cmd->cdw11 = NVME_FIELD_ENCODE(endgid, - NVME_FEAT_EG_ENDGID_SHIFT, - NVME_FEAT_EG_ENDGID_MASK) | - NVME_FIELD_ENCODE(egcw, - NVME_FEAT_EG_EGCW_SHIFT, - NVME_FEAT_EG_EGCW_MASK); -} - -/** - * nvme_init_set_features_sw_progress() - Initialize passthru command for - * Software Pogress Marker - * @cmd: Passthru command to use - * @sv: Save value across power states - * @pbslc: Pre-boot Software Load Count - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_SW_PROGRESS - */ -static inline void -nvme_init_set_features_sw_progress(struct nvme_passthru_cmd *cmd, - bool sv, __u8 pbslc) -{ - nvme_init_set_features(cmd, NVME_FEAT_FID_SW_PROGRESS, sv); - cmd->cdw11 = NVME_FIELD_ENCODE(pbslc, - NVME_FEAT_SPM_PBSLC_SHIFT, - NVME_FEAT_SPM_PBSLC_MASK); -} - -/** - * nvme_init_set_features_host_id() - Initialize passthru command for - * Host Identifier - * @cmd: Passthru command to use - * @sv: Save value across power states - * @exhid: Enable Extended Host Identifier - * @hostid: Host ID buffer to set - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_HOST_ID. - */ -static inline void -nvme_init_set_features_host_id(struct nvme_passthru_cmd *cmd, - bool sv, bool exhid, __u8 *hostid) -{ - nvme_init_set_features(cmd, NVME_FEAT_FID_HOST_ID, sv); - cmd->cdw11 = NVME_FIELD_ENCODE(exhid, - NVME_FEAT_HOSTID_EXHID_SHIFT, - NVME_FEAT_HOSTID_EXHID_MASK); - cmd->data_len = exhid ? 16 : 8; - cmd->addr = (__u64)(uintptr_t)hostid; -} - -/** - * nvme_init_set_features_resv_mask() - Initialize passthru command for - * Reservation Notification Mask - * @cmd: Passthru command to use - * @nsid: Namespace ID - * @sv: Save value across power states - * @mask: Reservation Notification Mask Field - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_RESV_MASK - */ -static inline void -nvme_init_set_features_resv_mask(struct nvme_passthru_cmd *cmd, __u32 nsid, - bool sv, __u32 mask) -{ - nvme_init_set_features(cmd, NVME_FEAT_FID_RESV_MASK, sv); - cmd->nsid = nsid; - cmd->cdw11 = mask; -} - -/** - * nvme_init_set_features_resv_persist() - Initialize passthru command for - * Reservation Persistence - * @cmd: Passthru command to use - * @nsid: Namespace ID - * @sv: Save value across power states - * @ptpl: Persist Through Power Loss - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_RESV_PERSIST - */ -static inline void -nvme_init_set_features_resv_persist(struct nvme_passthru_cmd *cmd, __u32 nsid, - bool sv, bool ptpl) -{ - nvme_init_set_features(cmd, NVME_FEAT_FID_RESV_PERSIST, sv); - cmd->nsid = nsid; - cmd->cdw11 = NVME_FIELD_ENCODE(ptpl, - NVME_FEAT_RESP_PTPL_SHIFT, - NVME_FEAT_RESP_PTPL_MASK); -} - -/** - * nvme_init_set_features_write_protect() - Initialize passthru command for - * Write Protect - * @cmd: Passthru command to use - * @nsid: Namespace ID - * @sv: Save value across power states - * @wps: Write Protection State - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_WRITE_PROTECT - */ -static inline void -nvme_init_set_features_write_protect(struct nvme_passthru_cmd *cmd, __u32 nsid, - bool sv, enum nvme_feat_nswpcfg_state wps) -{ - nvme_init_set_features(cmd, NVME_FEAT_FID_WRITE_PROTECT, sv); - cmd->nsid = nsid; - cmd->cdw11 = NVME_FIELD_ENCODE(wps, - NVME_FEAT_WP_WPS_SHIFT, - NVME_FEAT_WP_WPS_MASK); -} - -/** - * nvme_init_set_features_iocs_profile() - Initialize passthru command for - * I/O Command Set Profile - * @cmd: Passthru command to use - * @sv: Save value across power states - * @iocsci: I/O Command Set Combination Index - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_IOCS_PROFILE - */ -static inline void -nvme_init_set_features_iocs_profile(struct nvme_passthru_cmd *cmd, - bool sv, __u16 iocsci) -{ - nvme_init_set_features(cmd, NVME_FEAT_FID_IOCS_PROFILE, sv); - cmd->cdw11 = NVME_FIELD_ENCODE(iocsci, - NVME_FEAT_IOCSP_IOCSCI_SHIFT, - NVME_FEAT_IOCSP_IOCSCI_MASK); -} - -/** - * nvme_init_get_features() - Initialize passthru command for - * Get Features - * @cmd: Passthru command to use - * @fid: Feature identifier, see &enum nvme_features_id - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - */ -static inline void -nvme_init_get_features(struct nvme_passthru_cmd *cmd, __u8 fid, - enum nvme_get_features_sel sel) -{ - __u32 cdw10 = NVME_FIELD_ENCODE(fid, - NVME_GET_FEATURES_CDW10_FID_SHIFT, - NVME_GET_FEATURES_CDW10_FID_MASK) | - NVME_FIELD_ENCODE(sel, - NVME_GET_FEATURES_CDW10_SEL_SHIFT, - NVME_GET_FEATURES_CDW10_SEL_MASK); - - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_admin_get_features; - cmd->cdw10 = cdw10; -} - -/** - * nvme_init_get_features_arbitration() - Initialize passthru command for - * Get Features - Arbitration - * @cmd: Passthru command to use - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_ARBITRATION - */ -static inline void -nvme_init_get_features_arbitration(struct nvme_passthru_cmd *cmd, - enum nvme_get_features_sel sel) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_ARBITRATION, sel); -} - -/** - * nvme_init_get_features_power_mgmt() - Initialize passthru command for - * Get Features - Power Management - * @cmd: Passthru command to use - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_POWER_MGMT - */ -static inline void -nvme_init_get_features_power_mgmt(struct nvme_passthru_cmd *cmd, - enum nvme_get_features_sel sel) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_POWER_MGMT, sel); -} - -/** - * nvme_init_get_features_lba_range() - Initialize passthru command for - * Get Features - LBA Range - * @cmd: Passthru command to use - * @nsid: Namespace ID - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * @lrt: Buffer to receive LBA Range Type data structure - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_LBA_RANGE - */ -static inline void -nvme_init_get_features_lba_range(struct nvme_passthru_cmd *cmd, __u32 nsid, - enum nvme_get_features_sel sel, struct nvme_lba_range_type *lrt) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_LBA_RANGE, sel); - cmd->nsid = nsid; - cmd->data_len = sizeof(*lrt); - cmd->addr = (__u64)(uintptr_t)lrt; -} - -/** - * nvme_init_get_features_temp_thresh() - Initialize passthru command for - * Get Features - Temperature Threshold - * @cmd: Passthru command to use - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * @tmpsel: Threshold Temperature Select - * @thsel: Threshold Type Select - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_TEMP_THRESH - */ -static inline void -nvme_init_get_features_temp_thresh(struct nvme_passthru_cmd *cmd, - enum nvme_get_features_sel sel, - __u8 tmpsel, enum nvme_feat_tmpthresh_thsel thsel) -{ - - nvme_init_get_features(cmd, NVME_FEAT_FID_TEMP_THRESH, sel); - cmd->cdw11 = NVME_FIELD_ENCODE(tmpsel, - NVME_FEAT_TT_TMPSEL_SHIFT, - NVME_FEAT_TT_TMPSEL_MASK) | - NVME_FIELD_ENCODE(thsel, - NVME_FEAT_TT_THSEL_SHIFT, - NVME_FEAT_TT_THSEL_MASK); -} - -/** - * nvme_init_get_features_err_recovery() - Initialize passthru command for - * Get Features - Error Recovery - * @cmd: Passthru command to use - * @nsid: Namespace ID - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_ERR_RECOVERY - */ -static inline void -nvme_init_get_features_err_recovery(struct nvme_passthru_cmd *cmd, __u32 nsid, - enum nvme_get_features_sel sel) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_ERR_RECOVERY, sel); - cmd->nsid = nsid; -} - -/** - * nvme_init_get_features_volatile_wc() - Initialize passthru command for - * Get Features - Volatile Write Cache - * @cmd: Passthru command to use - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_VOLATILE_WC - */ -static inline void -nvme_init_get_features_volatile_wc(struct nvme_passthru_cmd *cmd, - enum nvme_get_features_sel sel) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_VOLATILE_WC, sel); -} - -/** - * nvme_init_get_features_num_queues() - Initialize passthru command for - * Get Features - Number of Queues - * @cmd: Passthru command to use - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_NUM_QUEUES - */ -static inline void -nvme_init_get_features_num_queues(struct nvme_passthru_cmd *cmd, - enum nvme_get_features_sel sel) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_NUM_QUEUES, sel); -} - -/** - * nvme_init_get_features_irq_coalesce() - Initialize passthru command for - * Get Features - IRQ Coalesce - * @cmd: Passthru command to use - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_IRQ_COALESCE - */ -static inline void -nvme_init_get_features_irq_coalesce(struct nvme_passthru_cmd *cmd, - enum nvme_get_features_sel sel) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_IRQ_COALESCE, sel); -} - -/** - * nvme_init_get_features_irq_config() - Initialize passthru command for - * Get Features - IRQ Config - * @cmd: Passthru command to use - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * @iv: Interrupt Vector - * @cd: Coalescing Disable - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_IRQ_CONFIG - */ -static inline void -nvme_init_get_features_irq_config(struct nvme_passthru_cmd *cmd, - enum nvme_get_features_sel sel, - __u16 iv, bool cd) -{ - __u32 cdw11 = NVME_FIELD_ENCODE(iv, - NVME_FEAT_ICFG_IV_SHIFT, - NVME_FEAT_ICFG_IV_MASK) | - NVME_FIELD_ENCODE(cd, - NVME_FEAT_ICFG_CD_SHIFT, - NVME_FEAT_ICFG_CD_MASK); - - nvme_init_get_features(cmd, NVME_FEAT_FID_IRQ_CONFIG, sel); - cmd->cdw11 = cdw11; -} - -/** - * nvme_init_get_features_write_atomic() - Initialize passthru command for - * Get Features - Write Atomic - * @cmd: Passthru command to use - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_WRITE_ATOMIC - */ -static inline void -nvme_init_get_features_write_atomic(struct nvme_passthru_cmd *cmd, - enum nvme_get_features_sel sel) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_WRITE_ATOMIC, sel); -} - -/** - * nvme_init_get_features_async_event() - Initialize passthru command for - * Get Features - Asynchronous Event Configuration - * @cmd: Passthru command to use - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_ASYNC_EVENT - */ -static inline void -nvme_init_get_features_async_event(struct nvme_passthru_cmd *cmd, - enum nvme_get_features_sel sel) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_ASYNC_EVENT, sel); -} - -/** - * nvme_init_get_features_auto_pst() - Initialize passthru command for - * Get Features - Autonomous Power State Transition - * @cmd: Passthru command to use - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * @apst: Autonomous Power State Transition data buffer - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_AUTO_PST - */ -static inline void -nvme_init_get_features_auto_pst(struct nvme_passthru_cmd *cmd, - enum nvme_get_features_sel sel, struct nvme_feat_auto_pst *apst) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_AUTO_PST, sel); - cmd->data_len = sizeof(*apst); - cmd->addr = (__u64)(uintptr_t)apst; -} - -/** - * nvme_init_get_features_host_mem_buf() - Initialize passthru command for - * Get Features - Host Memory Buffer - * @cmd: Passthru command to use - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * @attrs: Buffer for returned Host Memory Buffer Attributes - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_HOST_MEM_BUF - */ -static inline void -nvme_init_get_features_host_mem_buf(struct nvme_passthru_cmd *cmd, - enum nvme_get_features_sel sel, - struct nvme_host_mem_buf_attrs *attrs) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_HOST_MEM_BUF, sel); - cmd->data_len = sizeof(*attrs); - cmd->addr = (__u64)(uintptr_t)attrs; -} - -/** - * nvme_init_get_features_timestamp() - Initialize passthru command for - * Get Features - Timestamp - * @cmd: Passthru command to use - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * @ts: Current timestamp buffer - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_TIMESTAMP - */ -static inline void -nvme_init_get_features_timestamp(struct nvme_passthru_cmd *cmd, - enum nvme_get_features_sel sel, struct nvme_timestamp *ts) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_TIMESTAMP, sel); - cmd->data_len = sizeof(*ts); - cmd->addr = (__u64)(uintptr_t)ts; -} - -/** - * nvme_init_get_features_kato() - Initialize passthru command for - * Get Features - Keep Alive Timeout - * @cmd: Passthru command to use - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_KATO - */ -static inline void -nvme_init_get_features_kato(struct nvme_passthru_cmd *cmd, - enum nvme_get_features_sel sel) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_KATO, sel); -} - -/** - * nvme_init_get_features_hctm() - Initialize passthru command for - * Get Features - Host Controlled Thermal Management - * @cmd: Passthru command to use - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_HCTM - */ -static inline void -nvme_init_get_features_hctm(struct nvme_passthru_cmd *cmd, - enum nvme_get_features_sel sel) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_HCTM, sel); -} - -/** - * nvme_init_get_features_nopsc() - Initialize passthru command for - * Get Features - Non-Operational Power State Config - * @cmd: Passthru command to use - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_NOPSC - */ -static inline void -nvme_init_get_features_nopsc(struct nvme_passthru_cmd *cmd, - enum nvme_get_features_sel sel) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_NOPSC, sel); -} - -/** - * nvme_init_get_features_rrl() - Initialize passthru command for - * Get Features - Read Recovery Level - * @cmd: Passthru command to use - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_RRL - */ -static inline void -nvme_init_get_features_rrl(struct nvme_passthru_cmd *cmd, - enum nvme_get_features_sel sel) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_RRL, sel); -} - -/** - * nvme_init_get_features_plm_config() - Initialize passthru command for - * Get Features - Predictable Latency Mode Config - * @cmd: Passthru command to use - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * @nvmsetid: NVM set id - * @plmc: Buffer for returned Predictable Latency Mode Config - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_PLM_CONFIG - */ -static inline void -nvme_init_get_features_plm_config(struct nvme_passthru_cmd *cmd, - enum nvme_get_features_sel sel, __u16 nvmsetid, - struct nvme_plm_config *plmc) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_PLM_CONFIG, sel); - cmd->cdw11 = NVME_FIELD_ENCODE(nvmsetid, - NVME_FEAT_PLM_NVMSETID_SHIFT, - NVME_FEAT_PLM_NVMSETID_MASK); - cmd->data_len = sizeof(*plmc); - cmd->addr = (__u64)(uintptr_t)plmc; -} - -/** - * nvme_init_get_features_plm_window() - Initialize passthru command for - * Get Features - Predictable Latency Mode Window - * @cmd: Passthru command to use - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * @nvmsetid: NVM set id - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_PLM_WINDOW - */ -static inline void -nvme_init_get_features_plm_window(struct nvme_passthru_cmd *cmd, - enum nvme_get_features_sel sel, __u16 nvmsetid) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_PLM_WINDOW, sel); - cmd->cdw11 = NVME_FIELD_ENCODE(nvmsetid, - NVME_FEAT_PLM_NVMSETID_SHIFT, - NVME_FEAT_PLM_NVMSETID_MASK); -} - -/** - * nvme_init_get_features_lba_sts_interval() - Initialize passthru command for - * Get Features - LBA Status Information Interval - * @cmd: Passthru command to use - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_LBA_STS_INTERVAL - */ -static inline void -nvme_init_get_features_lba_sts_interval(struct nvme_passthru_cmd *cmd, - enum nvme_get_features_sel sel) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_LBA_STS_INTERVAL, sel); -} - -/** - * nvme_init_get_features_host_behavior() - Initialize passthru command for - * Get Features - Host Behavior - * @cmd: Passthru command to use - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * @fhb: Pointer to structure nvme_feat_host_behavior - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_HOST_BEHAVIOR - */ -static inline void -nvme_init_get_features_host_behavior(struct nvme_passthru_cmd *cmd, - enum nvme_get_features_sel sel, - struct nvme_feat_host_behavior *fhb) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_HOST_BEHAVIOR, sel); - cmd->data_len = sizeof(*fhb); - cmd->addr = (__u64)(uintptr_t)fhb; -} - -/** - * nvme_init_get_features_sanitize() - Initialize passthru command for - * Get Features - Sanitize - * @cmd: Passthru command to use - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_SANITIZE - */ -static inline void -nvme_init_get_features_sanitize(struct nvme_passthru_cmd *cmd, - enum nvme_get_features_sel sel) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_SANITIZE, sel); -} - -/** - * nvme_init_get_features_endurance_event_cfg() - Initialize passthru command - * for Get Features - Endurance Group Event Configuration - * @cmd: Passthru command to use - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * @endgid: Endurance Group Identifier - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_ENDURANCE_EVT_CFG - */ -static inline void -nvme_init_get_features_endurance_event_cfg(struct nvme_passthru_cmd *cmd, - enum nvme_get_features_sel sel, __u16 endgid) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_ENDURANCE_EVT_CFG, sel); - cmd->cdw11 = NVME_FIELD_ENCODE(endgid, - NVME_FEAT_EG_ENDGID_SHIFT, - NVME_FEAT_EG_ENDGID_MASK); -} - -/** - * nvme_init_get_features_sw_progress() - Initialize passthru command for - * Get Features - Software Progress - * @cmd: Passthru command to use - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_SW_PROGRESS - */ -static inline void -nvme_init_get_features_sw_progress(struct nvme_passthru_cmd *cmd, - enum nvme_get_features_sel sel) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_SW_PROGRESS, sel); -} - -/** - * nvme_init_get_features_host_id() - Initialize passthru command for - * Get Features - Host Identifier - * @cmd: Passthru command to use - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * @exhid: Enable Extended Host Identifier - * @hostid: Buffer for returned host ID - * @len: Length of @hostid - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_HOST_ID - */ -static inline void -nvme_init_get_features_host_id(struct nvme_passthru_cmd *cmd, - enum nvme_get_features_sel sel, bool exhid, - void *hostid, __u32 len) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_HOST_ID, sel); - cmd->cdw11 = NVME_FIELD_ENCODE(exhid, - NVME_FEAT_HOSTID_EXHID_SHIFT, - NVME_FEAT_HOSTID_EXHID_MASK); - cmd->data_len = len; - cmd->addr = (__u64)(uintptr_t)hostid; -} - -/** - * nvme_init_get_features_resv_mask() - Initialize passthru command for - * Get Features - Reservation Notification Mask - * @cmd: Passthru command to use - * @nsid: Namespace ID - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_RESV_MASK - */ -static inline void -nvme_init_get_features_resv_mask(struct nvme_passthru_cmd *cmd, __u32 nsid, - enum nvme_get_features_sel sel) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_RESV_MASK, sel); - cmd->nsid = nsid; -} - -/** - * nvme_init_get_features_resv_persist() - Initialize passthru command for - * Get Features - Reservation Persistence - * @cmd: Passthru command to use - * @nsid: Namespace ID - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_RESV_PERSIST - */ -static inline void -nvme_init_get_features_resv_persist(struct nvme_passthru_cmd *cmd, __u32 nsid, - enum nvme_get_features_sel sel) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_RESV_PERSIST, sel); - cmd->nsid = nsid; -} - -/** - * nvme_init_get_features_write_protect() - Initialize passthru command for - * Get Features - Write Protect - * @cmd: Passthru command to use - * @nsid: Namespace ID - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_WRITE_PROTECT - */ -static inline void -nvme_init_get_features_write_protect(struct nvme_passthru_cmd *cmd, __u32 nsid, - enum nvme_get_features_sel sel) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_WRITE_PROTECT, sel); - cmd->nsid = nsid; -} - -/** - * nvme_init_get_features_iocs_profile() - Initialize passthru command for - * Get Features - I/O Command Set Profile - * @cmd: Passthru command to use - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_IOCS_PROFILE - */ -static inline void -nvme_init_get_features_iocs_profile(struct nvme_passthru_cmd *cmd, - enum nvme_get_features_sel sel) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_IOCS_PROFILE, sel); -} - -/** - * nvme_init_format_nvm() - Initialize passthru command for Format NVM - * @cmd: Passthru command to use - * @nsid: Namespace ID to format - * @lbaf: Logical block address format - * @mset: Metadata settings (extended or separated) - * @pi: Protection information type - * @pil: Protection information location (beginning or end) - * @ses: Secure erase settings - * - * Initializes the passthru command buffer for the Format NVM command. - */ -static inline void -nvme_init_format_nvm(struct nvme_passthru_cmd *cmd, __u32 nsid, __u8 lbaf, - enum nvme_cmd_format_mset mset, enum nvme_cmd_format_pi pi, - enum nvme_cmd_format_pil pil, enum nvme_cmd_format_ses ses) -{ - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_admin_format_nvm; - cmd->nsid = nsid; - cmd->cdw10 = NVME_FIELD_ENCODE(lbaf, - NVME_FORMAT_CDW10_LBAFL_SHIFT, - NVME_FORMAT_CDW10_LBAFL_MASK) | - NVME_FIELD_ENCODE(mset, - NVME_FORMAT_CDW10_MSET_SHIFT, - NVME_FORMAT_CDW10_MSET_MASK) | - NVME_FIELD_ENCODE(pi, - NVME_FORMAT_CDW10_PI_SHIFT, - NVME_FORMAT_CDW10_PI_MASK) | - NVME_FIELD_ENCODE(pil, - NVME_FORMAT_CDW10_PIL_SHIFT, - NVME_FORMAT_CDW10_PIL_MASK) | - NVME_FIELD_ENCODE(ses, - NVME_FORMAT_CDW10_SES_SHIFT, - NVME_FORMAT_CDW10_SES_MASK) | - NVME_FIELD_ENCODE((lbaf >> 4), - NVME_FORMAT_CDW10_LBAFU_SHIFT, - NVME_FORMAT_CDW10_LBAFU_MASK); -} - -/** - * nvme_init_ns_mgmt() - Initialize passthru command for Namespace Management - * @cmd: Passthru command to use - * @nsid: Namespace identifier - * @sel: Type of management operation to perform - * @csi: Command Set Identifier - * @data: Host Software Specified Fields buffer - * - * Initializes the passthru command buffer for the Namespace Management command. - */ -static inline void -nvme_init_ns_mgmt(struct nvme_passthru_cmd *cmd, __u32 nsid, - enum nvme_ns_mgmt_sel sel, __u8 csi, - struct nvme_ns_mgmt_host_sw_specified *data) -{ - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_admin_ns_mgmt; - cmd->nsid = nsid; - cmd->data_len = data ? sizeof(*data) : 0; - cmd->addr = (__u64)(uintptr_t)data; - cmd->cdw10 = NVME_FIELD_ENCODE(sel, - NVME_NAMESPACE_MGMT_CDW10_SEL_SHIFT, - NVME_NAMESPACE_MGMT_CDW10_SEL_MASK); - cmd->cdw11 = NVME_FIELD_ENCODE(csi, - NVME_NAMESPACE_MGMT_CDW11_CSI_SHIFT, - NVME_NAMESPACE_MGMT_CDW11_CSI_MASK); -} - -/** - * nvme_init_ns_mgmt_create() - Initialize passthru command to create a - * non attached namespace - * @cmd: Passthru command to use - * @csi: Command Set Identifier - * @data: Host Software Specified Fields buffer that defines NS - * creation parameters - * - * Initializes the passthru command buffer for the Namespace Management - Create - * command. The command uses NVME_NSID_NONE as the target NSID. - */ -static inline void -nvme_init_ns_mgmt_create(struct nvme_passthru_cmd *cmd, __u8 csi, - struct nvme_ns_mgmt_host_sw_specified *data) -{ - nvme_init_ns_mgmt(cmd, NVME_NSID_NONE, NVME_NS_MGMT_SEL_CREATE, - csi, data); -} - -/** - * nvme_init_ns_mgmt_delete() - Initialize passthru command to delete a - * non attached namespace - * @cmd: Passthru command to use - * @nsid: Namespace identifier to delete - * - * Initializes the passthru command buffer for the Namespace Management - Delete - * command (NVME_NS_MGMT_SEL_DELETE). The command uses the provided @nsid as - * the target NSID. - */ -static inline void -nvme_init_ns_mgmt_delete(struct nvme_passthru_cmd *cmd, __u32 nsid) -{ - nvme_init_ns_mgmt(cmd, nsid, NVME_NS_MGMT_SEL_DELETE, - NVME_CSI_NVM, NULL); -} - -/** - * nvme_init_ns_attach() - Initialize passthru command for - * Namespace Attach/Detach - * @cmd: Passthru command to use - * @nsid: Namespace ID to execute attach selection - * @sel: Attachment selection, see &enum nvme_ns_attach_sel - * @ctrlist: Controller list buffer to modify attachment state of nsid - * - * Initializes the passthru command buffer for the Namespace Attach/Detach command. - */ -static inline void -nvme_init_ns_attach(struct nvme_passthru_cmd *cmd, __u32 nsid, - enum nvme_ns_attach_sel sel, struct nvme_ctrl_list *ctrlist) -{ - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_admin_ns_attach; - cmd->nsid = nsid; - cmd->data_len = sizeof(*ctrlist); - cmd->addr = (__u64)(uintptr_t)ctrlist; - cmd->cdw10 = NVME_FIELD_ENCODE(sel, - NVME_NAMESPACE_ATTACH_CDW10_SEL_SHIFT, - NVME_NAMESPACE_ATTACH_CDW10_SEL_MASK); -} - -/** - * nvme_init_ns_attach_ctrls() - Initialize passthru command to attach - * namespace to controllers - * @cmd: Passthru command to use - * @nsid: Namespace ID to attach - * @ctrlist: Controller list buffer to modify attachment state of nsid - * - * Initializes the passthru command buffer for the Namespace Attach command - * (NVME_NS_ATTACH_SEL_CTRL_ATTACH). - */ -static inline void -nvme_init_ns_attach_ctrls(struct nvme_passthru_cmd *cmd, __u32 nsid, - struct nvme_ctrl_list *ctrlist) -{ - nvme_init_ns_attach(cmd, nsid, NVME_NS_ATTACH_SEL_CTRL_ATTACH, - ctrlist); -} - -/** - * nvme_init_ns_detach_ctrls() - Initialize passthru command to detach - * namespace from controllers - * @cmd: Passthru command to use - * @nsid: Namespace ID to detach - * @ctrlist: Controller list buffer to modify attachment state of nsid - * - * Initializes the passthru command buffer for the Namespace Detach command - * (NVME_NS_ATTACH_SEL_CTRL_DEATTACH). - */ -static inline void -nvme_init_ns_detach_ctrls(struct nvme_passthru_cmd *cmd, __u32 nsid, - struct nvme_ctrl_list *ctrlist) -{ - nvme_init_ns_attach(cmd, nsid, NVME_NS_ATTACH_SEL_CTRL_DEATTACH, - ctrlist); -} - -/** - * nvme_init_fw_download() - Initialize passthru command to download part or - * all of a firmware image to the controller - * @cmd: Passthru command to use - * @data: Userspace address of the firmware data buffer - * @len: Length of data in this command in bytes - * @offset: Offset in the firmware data - * - * Initializes the passthru command buffer for the Firmware Image - * Download command. - * - * Note: Caller must ensure data_len and offset are DWord-aligned (0x4). - * - * Returns: 0 on success, or error code if arguments are invalid. - */ -static inline int -nvme_init_fw_download(struct nvme_passthru_cmd *cmd, void *data, - __u32 len, __u32 offset) -{ - if (len & 0x3 || !len) - return -EINVAL; - - if (offset & 0x3) - return -EINVAL; - - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_admin_fw_download; - cmd->data_len = len; - cmd->addr = (__u64)(uintptr_t)data; - cmd->cdw10 = (len >> 2) - 1;; - cmd->cdw11 = offset >> 2; - - return 0; -} - -/** - * nvme_init_fw_commit() - Initialize passthru command to commit firmware - * using the specified action - * @cmd: Passthru command to use - * @fs: Firmware slot to commit the downloaded image - * @ca: Action to use for the firmware image, - * see &enum nvme_fw_commit_ca - * @bpid: Set to true to select the boot partition id - * - * Initializes the passthru command buffer for the Firmware Commit command. - */ -static inline void -nvme_init_fw_commit(struct nvme_passthru_cmd *cmd, __u8 fs, - enum nvme_fw_commit_ca ca, bool bpid) -{ - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_admin_fw_commit; - cmd->cdw10 = NVME_FIELD_ENCODE(fs, - NVME_FW_COMMIT_CDW10_FS_SHIFT, - NVME_FW_COMMIT_CDW10_FS_MASK) | - NVME_FIELD_ENCODE(ca, - NVME_FW_COMMIT_CDW10_CA_SHIFT, - NVME_FW_COMMIT_CDW10_CA_MASK) | - NVME_FIELD_ENCODE(bpid, - NVME_FW_COMMIT_CDW10_BPID_SHIFT, - NVME_FW_COMMIT_CDW10_BPID_MASK); -} - -/** - * nvme_init_security_send() - Initialize passthru command for Security Send - * @cmd: Passthru command to use - * @nsid: Namespace ID to issue security command on - * @nssf: NVMe Security Specific field - * @spsp: Security Protocol Specific field - * @secp: Security Protocol - * @tl: Protocol specific transfer length - * @data: Security data payload buffer to send - * @len: Data length of the payload in bytes - * - * Initializes the passthru command buffer for the Security Send command. - */ -static inline void -nvme_init_security_send(struct nvme_passthru_cmd *cmd, __u32 nsid, __u8 nssf, - __u16 spsp, __u8 secp, __u32 tl, void *data, __u32 len) -{ - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_admin_security_send; - cmd->nsid = nsid; - cmd->data_len = len; - cmd->addr = (__u64)(uintptr_t)data; - cmd->cdw10 = NVME_FIELD_ENCODE(secp, - NVME_SECURITY_SECP_SHIFT, - NVME_SECURITY_SECP_MASK) | - NVME_FIELD_ENCODE(spsp, - NVME_SECURITY_SPSP0_SHIFT, - NVME_SECURITY_SPSP0_MASK) | - NVME_FIELD_ENCODE(spsp >> 8, - NVME_SECURITY_SPSP1_SHIFT, - NVME_SECURITY_SPSP1_MASK) | - NVME_FIELD_ENCODE(nssf, - NVME_SECURITY_NSSF_SHIFT, - NVME_SECURITY_NSSF_MASK); - cmd->cdw11 = tl; -} - -/** - * nvme_init_security_receive() - Initialize passthru command for - * Security Receive - * @cmd: Passthru command to use - * @nsid: Namespace ID to issue security command on - * @nssf: NVMe Security Specific field - * @spsp: Security Protocol Specific field - * @secp: Security Protocol - * @al: Protocol specific allocation length - * @data: Security data payload buffer to receive data into - * @len: Data length of the payload in bytes (must match @al) - * - * Initializes the passthru command buffer for the Security Receive command. - */ -static inline void -nvme_init_security_receive(struct nvme_passthru_cmd *cmd, __u32 nsid, __u8 nssf, - __u16 spsp, __u8 secp, __u32 al, void *data, __u32 len) -{ - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_admin_security_recv; - cmd->nsid = nsid; - cmd->data_len = len; - cmd->addr = (__u64)(uintptr_t)data; - cmd->cdw10 = NVME_FIELD_ENCODE(secp, - NVME_SECURITY_SECP_SHIFT, - NVME_SECURITY_SECP_MASK) | - NVME_FIELD_ENCODE(spsp, - NVME_SECURITY_SPSP0_SHIFT, - NVME_SECURITY_SPSP0_MASK) | - NVME_FIELD_ENCODE(spsp >> 8, - NVME_SECURITY_SPSP1_SHIFT, - NVME_SECURITY_SPSP1_MASK) | - NVME_FIELD_ENCODE(nssf, - NVME_SECURITY_NSSF_SHIFT, - NVME_SECURITY_NSSF_MASK); - cmd->cdw11 = al; -} - -/** - * nvme_init_get_lba_status() - Initialize passthru command to retrieve - * information on possibly unrecoverable LBAs - * @cmd: Passthru command to use - * @nsid: Namespace ID to retrieve LBA status - * @slba: Starting logical block address to check statuses - * @mndw: Maximum number of dwords to return - * @atype: Action type mechanism to determine LBA status descriptors to - * return, see &enum nvme_lba_status_atype - * @rl: Range length from slba to perform the action - * @lbas: Data payload buffer to return status descriptors - * - * Initializes the passthru command buffer for the Get LBA Status command. - */ -static inline void -nvme_init_get_lba_status(struct nvme_passthru_cmd *cmd, __u32 nsid, __u64 slba, - __u32 mndw, enum nvme_lba_status_atype atype, __u16 rl, - struct nvme_lba_status *lbas) -{ - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_admin_get_lba_status; - cmd->nsid = nsid; - cmd->data_len = (mndw + 1) << 2; - cmd->addr = (__u64)(uintptr_t)lbas; - cmd->cdw10 = slba & 0xffffffff; - cmd->cdw11 = slba >> 32; - cmd->cdw12 = mndw; - cmd->cdw13 = NVME_FIELD_ENCODE(rl, - NVME_GET_LBA_STATUS_CDW13_RL_SHIFT, - NVME_GET_LBA_STATUS_CDW13_RL_MASK) | - NVME_FIELD_ENCODE(atype, - NVME_GET_LBA_STATUS_CDW13_ATYPE_SHIFT, - NVME_GET_LBA_STATUS_CDW13_ATYPE_MASK); -} - -/** - * nvme_init_directive_send() - Initialize passthru command for Directive Send - * @cmd: Passthru command to use - * @nsid: Namespace ID, if applicable - * @doper: Directive send operation, see &enum nvme_directive_send_doper - * @dtype: Directive type, see &enum nvme_directive_dtype - * @dspec: Directive specific field - * @data: Data payload buffer to be send - * @len: Length of data payload in bytes - * - * Initializes the passthru command buffer for the Directive Send command. - */ -static inline void -nvme_init_directive_send(struct nvme_passthru_cmd *cmd, __u32 nsid, - enum nvme_directive_send_doper doper, - enum nvme_directive_dtype dtype, __u16 dspec, - void *data, __u32 len) -{ - - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_admin_directive_send; - cmd->nsid = nsid; - cmd->data_len = len; - cmd->addr = (__u64)(uintptr_t)data; - cmd->cdw10 = len? (len >> 2) - 1 : 0; - cmd->cdw11 = NVME_FIELD_ENCODE(doper, - NVME_DIRECTIVE_CDW11_DOPER_SHIFT, - NVME_DIRECTIVE_CDW11_DOPER_MASK) | - NVME_FIELD_ENCODE(dtype, - NVME_DIRECTIVE_CDW11_DTYPE_SHIFT, - NVME_DIRECTIVE_CDW11_DTYPE_MASK) | - NVME_FIELD_ENCODE(dspec, - NVME_DIRECTIVE_CDW11_DPSEC_SHIFT, - NVME_DIRECTIVE_CDW11_DPSEC_MASK); -} - -/** - * nvme_init_directive_send_id_endir() - Initialize passthru command for - * Directive Send Enable Directive - * @cmd: Passthru command to use - * @nsid: Namespace Identifier - * @endir: Enable Directive - * @dtype: Directive Type - * @id: Pointer to structure nvme_id_directives - * - * Initializes the passthru command buffer for the Directive Send - Identify - * (Enable Directive) command. - */ -static inline void -nvme_init_directive_send_id_endir(struct nvme_passthru_cmd *cmd, __u32 nsid, - bool endir, enum nvme_directive_dtype dtype, - struct nvme_id_directives *id) -{ - nvme_init_directive_send(cmd, nsid, - NVME_DIRECTIVE_SEND_IDENTIFY_DOPER_ENDIR, - NVME_DIRECTIVE_DTYPE_IDENTIFY, 0, id, sizeof(*id)); - cmd->cdw12 = NVME_FIELD_ENCODE(dtype, - NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_DTYPE_SHIFT, - NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_DTYPE_MASK) | - NVME_FIELD_ENCODE(endir, - NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_ENDIR_SHIFT, - NVME_DIRECTIVE_SEND_IDENTIFY_CDW12_ENDIR_MASK); -} - -/** - * nvme_init_directive_send_stream_release_identifier() - Initialize passthru - * command for Directive Send Stream release identifier - * @cmd: Passthru command to use - * @nsid: Namespace ID - * @stream_id: Stream identifier - * - * Initializes the passthru command buffer for the Directive Send - Stream - * Release Identifier command. - */ -static inline void -nvme_init_directive_send_stream_release_identifier(struct nvme_passthru_cmd *cmd, - __u32 nsid, __u16 stream_id) -{ - nvme_init_directive_send(cmd, nsid, - NVME_DIRECTIVE_SEND_STREAMS_DOPER_RELEASE_IDENTIFIER, - NVME_DIRECTIVE_DTYPE_STREAMS, stream_id, NULL, 0); -} - -/** - * nvme_init_directive_send_stream_release_resource() - Initialize passthru - * command for Directive Send Stream release resources - * @cmd: Passthru command to use - * @nsid: Namespace ID - * - * Initializes the passthru command buffer for the Directive Send - Stream - * Release Resource command. - */ -static inline void -nvme_init_directive_send_stream_release_resource(struct nvme_passthru_cmd *cmd, - __u32 nsid) -{ - nvme_init_directive_send(cmd, nsid, - NVME_DIRECTIVE_SEND_STREAMS_DOPER_RELEASE_RESOURCE, - NVME_DIRECTIVE_DTYPE_STREAMS, 0, NULL, 0); -} - -/** - * nvme_init_directive_recv() - Initialize passthru command for - * Directive Receive - * @cmd: Passthru command to use - * @nsid: Namespace ID, if applicable - * @doper: Directive receive operation, - * see &enum nvme_directive_receive_doper - * @dtype: Directive type, see &enum nvme_directive_dtype - * @dspec: Directive specific field - * @data: Userspace address of data payload buffer - * @len: Length of data payload in bytes - * - * Initializes the passthru command buffer for the Directive Receive command. - */ -static inline void -nvme_init_directive_recv(struct nvme_passthru_cmd *cmd, __u32 nsid, - enum nvme_directive_receive_doper doper, - enum nvme_directive_dtype dtype, __u16 dspec, - void *data, __u32 len) -{ - - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_admin_directive_recv; - cmd->nsid = nsid; - cmd->data_len = len; - cmd->addr = (__u64)(uintptr_t)data; - cmd->cdw10 = len ? (len >> 2) - 1 : 0; - cmd->cdw11 = NVME_FIELD_ENCODE(doper, - NVME_DIRECTIVE_CDW11_DOPER_SHIFT, - NVME_DIRECTIVE_CDW11_DOPER_MASK) | - NVME_FIELD_ENCODE(dtype, - NVME_DIRECTIVE_CDW11_DTYPE_SHIFT, - NVME_DIRECTIVE_CDW11_DTYPE_MASK) | - NVME_FIELD_ENCODE(dspec, - NVME_DIRECTIVE_CDW11_DPSEC_SHIFT, - NVME_DIRECTIVE_CDW11_DPSEC_MASK); -} - -/** - * nvme_init_directive_recv_identify_parameters() - Initialize passthru command - * for Directive Receive Identify Parameters - * @cmd: Passthru command to use - * @nsid: Namespace ID - * @id: Identify parameters buffer - * - * Initializes the passthru command buffer for the Directive Receive - Identify - * Parameters command. - */ -static inline void -nvme_init_directive_recv_identify_parameters(struct nvme_passthru_cmd *cmd, - __u32 nsid, struct nvme_id_directives *id) -{ - nvme_init_directive_recv(cmd, nsid, - NVME_DIRECTIVE_RECEIVE_IDENTIFY_DOPER_PARAM, - NVME_DIRECTIVE_DTYPE_IDENTIFY, 0, id, sizeof(*id)); -} - -/** - * nvme_init_directive_recv_stream_parameters() - Initialize passthru command - * for Directive Receive Stream Parameters - * @cmd: Passthru command to use - * @nsid: Namespace ID - * @parms: Streams directive parameters buffer - * - * Initializes the passthru command buffer for the Directive Receive - Stream - * Parameters command. - */ -static inline void -nvme_init_directive_recv_stream_parameters(struct nvme_passthru_cmd *cmd, - __u32 nsid, struct nvme_streams_directive_params *parms) -{ - nvme_init_directive_recv(cmd, nsid, - NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_PARAM, - NVME_DIRECTIVE_DTYPE_STREAMS, 0, parms, sizeof(*parms)); -} - -/** - * nvme_init_directive_recv_stream_status() - Initialize passthru command for - * Directive Receive Stream Status - * @cmd: Passthru command to use - * @nsid: Namespace ID - * @nr_entries: Number of streams to receive - * @id: Stream status buffer - * - * Initializes the passthru command buffer for the Directive Receive - Stream - * Status command. - * - * Return: 0 on success, or error code if arguments are invalid. - */ -static inline int -nvme_init_directive_recv_stream_status(struct nvme_passthru_cmd *cmd, - __u32 nsid, unsigned int nr_entries, - struct nvme_streams_directive_status *id) -{ - if (nr_entries > NVME_STREAM_ID_MAX) - return -EINVAL; - - nvme_init_directive_recv(cmd, nsid, - NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_STATUS, - NVME_DIRECTIVE_DTYPE_STREAMS, 0, id, - (__u32)(sizeof(*id) + nr_entries * sizeof(__le16))); - - return 0; -} - -/** - * nvme_init_directive_recv_stream_allocate() - Initialize passthru command for - * Directive Receive Stream Allocate - * @cmd: Passthru command to use - * @nsid: Namespace ID - * @nsr: Namespace Streams Requested - * - * Initializes the passthru command buffer for the Directive Receive - Stream - * Allocate command. - */ -static inline void -nvme_init_directive_recv_stream_allocate(struct nvme_passthru_cmd *cmd, - __u32 nsid, __u16 nsr) -{ - nvme_init_directive_recv(cmd, nsid, - NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_RESOURCE, - NVME_DIRECTIVE_DTYPE_STREAMS, 0, NULL, 0); - cmd->cdw12 = nsr; -} - -/** - * nvme_init_capacity_mgmt() - Initialize passthru command for - * Capacity Management - * @cmd: Passthru command to use - * @oper: Operation to be performed by the controller - * @elid: Value specific to the value of the Operation field - * @cap: Capacity in bytes of the Endurance Group or NVM Set to - * be created - * - * Initializes the passthru command buffer for the Capacity Management command. - */ -static inline void -nvme_init_capacity_mgmt(struct nvme_passthru_cmd *cmd, - __u8 oper, __u16 elid, __u64 cap) -{ - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_admin_capacity_mgmt; - cmd->cdw10 = NVME_FIELD_ENCODE(oper, - NVME_CAPACITY_MGMT_CDW10_OPER_SHIFT, - NVME_CAPACITY_MGMT_CDW10_OPER_MASK) | - NVME_FIELD_ENCODE(elid, - NVME_CAPACITY_MGMT_CDW10_ELID_SHIFT, - NVME_CAPACITY_MGMT_CDW10_ELID_MASK); - cmd->cdw11 = NVME_FIELD_ENCODE(cap, - NVME_CAPACITY_MGMT_CDW11_CAPL_SHIFT, - NVME_CAPACITY_MGMT_CDW11_CAPL_MASK); - cmd->cdw12 = NVME_FIELD_ENCODE(cap >> 32, - NVME_CAPACITY_MGMT_CDW12_CAPU_SHIFT, - NVME_CAPACITY_MGMT_CDW12_CAPU_MASK); -} - - /** - * nvme_init_lockdown() - Initialize passthru command for Lockdown - * @cmd: Passthru command to use - * @scp: Scope of the command - * @prhbt: Prohibit or allow the command opcode or Set Features command - * @ifc: Affected interface - * @ofi: Opcode or Feature Identifier - * @uidx: UUID Index if controller supports this id selection method - * - * Initializes the passthru command buffer for the Lockdown command. - */ -static inline void -nvme_init_lockdown(struct nvme_passthru_cmd *cmd, __u8 scp, __u8 prhbt, - __u8 ifc, __u8 ofi, __u8 uidx) -{ - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_admin_lockdown; - cmd->cdw10 = NVME_FIELD_ENCODE(ofi, - NVME_LOCKDOWN_CDW10_OFI_SHIFT, - NVME_LOCKDOWN_CDW10_OFI_MASK) | - NVME_FIELD_ENCODE(ifc, - NVME_LOCKDOWN_CDW10_IFC_SHIFT, - NVME_LOCKDOWN_CDW10_IFC_MASK) | - NVME_FIELD_ENCODE(prhbt, - NVME_LOCKDOWN_CDW10_PRHBT_SHIFT, - NVME_LOCKDOWN_CDW10_PRHBT_MASK) | - NVME_FIELD_ENCODE(scp, - NVME_LOCKDOWN_CDW10_SCP_SHIFT, - NVME_LOCKDOWN_CDW10_SCP_MASK); - cmd->cdw14 = NVME_FIELD_ENCODE(uidx, - NVME_LOCKDOWN_CDW14_UIDX_SHIFT, - NVME_LOCKDOWN_CDW14_UIDX_MASK); -} - -/** - * nvme_init_set_property() - Initialize passthru command to set - * controller property - * @cmd: Passthru command to use - * @offset: Property offset from the base to set - * @value: The value to set the property - * - * Initializes the passthru command buffer for the Fabrics Set Property command. - * This is an NVMe-over-Fabrics specific command. - */ -static inline void -nvme_init_set_property(struct nvme_passthru_cmd *cmd, __u32 offset, __u64 value) -{ - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_admin_fabrics; - cmd->nsid = nvme_fabrics_type_property_set; - cmd->cdw10 = nvme_is_64bit_reg(offset); - cmd->cdw11 = (__u32)offset; - cmd->cdw12 = (__u32)(value & 0xffffffff); - cmd->cdw13 = (__u32)(value >> 32); -} - -/** - * nvme_init_get_property() - Initialize passthru command to get - * a controller property - * @cmd: Passthru command to use - * @offset: Property offset from the base to retrieve - * - * Initializes the passthru command buffer for the Fabrics Get Property command. - * This is an NVMe-over-Fabrics specific command. - */ -static inline void -nvme_init_get_property(struct nvme_passthru_cmd *cmd, __u32 offset) -{ - - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_admin_fabrics; - cmd->nsid = nvme_fabrics_type_property_get; - cmd->cdw10 = nvme_is_64bit_reg(offset); - cmd->cdw11 = (__u32)offset; -} - -/** - * nvme_init_sanitize_nvm() - Initialize passthru command to start a - * sanitize operation - * @cmd: Passthru command to use - * @sanact: Sanitize action, see &enum nvme_sanitize_sanact - * @ause: Set to allow unrestricted sanitize exit - * @owpass: Overwrite pass count - * @oipbp: Set to overwrite invert pattern between passes - * @ndas: Set to not deallocate blocks after sanitizing - * @emvs: Set to enter media verification state - * @ovrpat: Overwrite pattern - * - * Initializes the passthru command buffer for the Sanitize NVM command. - */ -static inline void -nvme_init_sanitize_nvm(struct nvme_passthru_cmd *cmd, - enum nvme_sanitize_sanact sanact, bool ause, __u8 owpass, - bool oipbp, bool ndas, bool emvs, __u32 ovrpat) -{ - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_admin_sanitize_nvm; - cmd->cdw10 = NVME_FIELD_ENCODE(sanact, - NVME_SANITIZE_CDW10_SANACT_SHIFT, - NVME_SANITIZE_CDW10_SANACT_MASK) | - NVME_FIELD_ENCODE(ause, - NVME_SANITIZE_CDW10_AUSE_SHIFT, - NVME_SANITIZE_CDW10_AUSE_MASK) | - NVME_FIELD_ENCODE(owpass, - NVME_SANITIZE_CDW10_OWPASS_SHIFT, - NVME_SANITIZE_CDW10_OWPASS_MASK) | - NVME_FIELD_ENCODE(oipbp, - NVME_SANITIZE_CDW10_OIPBP_SHIFT, - NVME_SANITIZE_CDW10_OIPBP_MASK) | - NVME_FIELD_ENCODE(ndas, - NVME_SANITIZE_CDW10_NDAS_SHIFT, - NVME_SANITIZE_CDW10_NDAS_MASK) | - NVME_FIELD_ENCODE(emvs, - NVME_SANITIZE_CDW10_EMVS_SHIFT, - NVME_SANITIZE_CDW10_EMVS_MASK); - cmd->cdw11 = ovrpat; -} - -/** - * nvme_init_sanitize_ns() - Initialize passthru command to start a - * sanitize namespace operation - * @cmd: Passthru command to use - * @sanact: Sanitize action, see &enum nvme_sanitize_sanact - * @ause: Set to allow unrestricted sanitize exit - * @emvs: Set to enter media verification state - * - * Initializes the passthru command buffer for the Sanitize namespace command. - */ -static inline void -nvme_init_sanitize_ns(struct nvme_passthru_cmd *cmd, - enum nvme_sanitize_sanact sanact, bool ause, bool emvs) -{ - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_admin_sanitize_ns; - cmd->cdw10 = NVME_FIELD_ENCODE(sanact, - NVME_SANITIZE_CDW10_SANACT_SHIFT, - NVME_SANITIZE_CDW10_SANACT_MASK) | - NVME_FIELD_ENCODE(ause, - NVME_SANITIZE_CDW10_AUSE_SHIFT, - NVME_SANITIZE_CDW10_AUSE_MASK) | - NVME_FIELD_ENCODE(emvs, - NVME_SANITIZE_CDW10_EMVS_SHIFT, - NVME_SANITIZE_CDW10_EMVS_MASK); -} - -/** - * nvme_init_dev_self_test() - Initialize passthru command to start or - * abort a self test - * @cmd: Passthru command to use - * @nsid: Namespace ID to test - * @stc: Self test code, see &enum nvme_dst_stc - * - * Initializes the passthru command buffer for the Device Self-test command. - */ -static inline void -nvme_init_dev_self_test(struct nvme_passthru_cmd *cmd, __u32 nsid, - enum nvme_dst_stc stc) -{ - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_admin_dev_self_test; - cmd->nsid = nsid; - cmd->cdw10 = NVME_FIELD_ENCODE(stc, - NVME_DEVICE_SELF_TEST_CDW10_STC_SHIFT, - NVME_DEVICE_SELF_TEST_CDW10_STC_MASK); -} - -/** - * nvme_init_virtual_mgmt() - Initialize passthru command for - * Virtualization Resource Management - * @cmd: Passthru command to use - * @act: Virtual resource action, see &enum nvme_virt_mgmt_act - * @rt: Resource type to modify, see &enum nvme_virt_mgmt_rt - * @cntlid: Controller id for which resources are bing modified - * @nr: Number of resources being allocated or assigned - * - * Initializes the passthru command buffer for the Virtualization - * Management command. - */ -static inline void -nvme_init_virtual_mgmt(struct nvme_passthru_cmd *cmd, - enum nvme_virt_mgmt_act act, enum nvme_virt_mgmt_rt rt, - __u16 cntlid, __u16 nr) -{ - memset(cmd, 0, sizeof(*cmd)); - cmd->opcode = nvme_admin_virtual_mgmt; - cmd->cdw10 = NVME_FIELD_ENCODE(act, - NVME_VIRT_MGMT_CDW10_ACT_SHIFT, - NVME_VIRT_MGMT_CDW10_ACT_MASK) | - NVME_FIELD_ENCODE(rt, - NVME_VIRT_MGMT_CDW10_RT_SHIFT, - NVME_VIRT_MGMT_CDW10_RT_MASK) | - NVME_FIELD_ENCODE(cntlid, - NVME_VIRT_MGMT_CDW10_CNTLID_SHIFT, - NVME_VIRT_MGMT_CDW10_CNTLID_MASK); - cmd->cdw11 = NVME_FIELD_ENCODE(nr, - NVME_VIRT_MGMT_CDW11_NR_SHIFT, - NVME_VIRT_MGMT_CDW11_NR_MASK); -} - -/** - * nvme_flush() - Send an nvme flush command - * @hdl: Transport handle - * @nsid: Namespace identifier - * - * The Flush command requests that the contents of volatile write cache be made - * non-volatile. - * - * 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_flush(struct nvme_transport_handle *hdl, __u32 nsid) -{ - struct nvme_passthru_cmd cmd = {}; - - cmd.opcode = nvme_cmd_flush; - cmd.nsid = nsid; - - return nvme_submit_io_passthru(hdl, &cmd); -} - -/** - * nvme_init_dsm() - Initialize passthru command for - * NVMEe I/O Data Set Management - * @cmd: Passthru command to use - * @nsid: Namespace identifier - * @nr: Number of block ranges in the data set management attributes - * @idr: DSM Integral Dataset for Read attribute - * @idw: DSM Integral Dataset for Write attribute - * @ad: DSM Deallocate attribute - * @data: User space destination address to transfer the data - * @len: Length of provided user buffer to hold the log data in bytes - */ -static inline void -nvme_init_dsm(struct nvme_passthru_cmd *cmd, - __u32 nsid, __u16 nr, __u8 idr, __u8 idw, __u8 ad, void *data, - __u32 len) -{ - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_cmd_dsm; - cmd->nsid = nsid; - cmd->data_len = len; - cmd->addr = (__u64)(uintptr_t)data; - cmd->cdw10 = NVME_FIELD_ENCODE(nr - 1, - NVME_DSM_CDW10_NR_SHIFT, - NVME_DSM_CDW10_NR_MASK); - cmd->cdw11 = NVME_FIELD_ENCODE(idr, - NVME_DSM_CDW11_IDR_SHIFT, - NVME_DSM_CDW11_IDR_MASK) | - NVME_FIELD_ENCODE(idw, - NVME_DSM_CDW11_IDW_SHIFT, - NVME_DSM_CDW11_IDW_MASK) | - NVME_FIELD_ENCODE(ad, - NVME_DSM_CDW11_AD_SHIFT, - NVME_DSM_CDW11_AD_MASK); -} - -/** - * nvme_init_var_size_tags() - Initialize Command Dword fields - * for Extended LBA based on Variable Sized Tags - * @cmd: Passthru command to use - * @pif: Protection information format, determines tag placement - * @sts: Storage tag size in bits - * @reftag: Expected Initial Logical Block Reference Tag (EILBRT) - * @storage_tag: Expected Logical Block Storage Tag (ELBST) - * - * Initializes the passthru command buffer fields cdw2, cdw3, and cdw14 - * for commands supporting Extended LBA. This logic is usually called from - * the command-specific init function (like nvme_init_zns_append). - */ -static inline int -nvme_init_var_size_tags(struct nvme_passthru_cmd *cmd, - __u8 pif, __u8 sts, __u64 reftag, __u64 storage_tag) -{ - __u32 cdw2 = 0, cdw3 = 0, cdw14 = 0; - - switch (pif) { - case NVME_NVM_PIF_16B_GUARD: - cdw14 = NVME_FIELD_ENCODE(reftag, - NVME_IOCS_COMMON_CDW14_ELBTL_SHIFT, - NVME_IOCS_COMMON_CDW14_ELBTL_MASK); - cdw14 |= NVME_FIELD_ENCODE(storage_tag << (32 - sts), - NVME_IOCS_COMMON_CDW14_ELBTL_SHIFT, - NVME_IOCS_COMMON_CDW14_ELBTL_MASK); - break; - case NVME_NVM_PIF_32B_GUARD: - cdw14 = NVME_FIELD_ENCODE(reftag, - NVME_IOCS_COMMON_CDW14_ELBTL_SHIFT, - NVME_IOCS_COMMON_CDW14_ELBTL_MASK); - cdw3 = NVME_FIELD_ENCODE(reftag >> 32, - NVME_IOCS_COMMON_CDW3_ELBTU_SHIFT, - NVME_IOCS_COMMON_CDW3_ELBTU_MASK); - cdw14 |= NVME_FIELD_ENCODE((storage_tag << (80 - sts)) & 0xffff0000, - NVME_IOCS_COMMON_CDW14_ELBTL_SHIFT, - NVME_IOCS_COMMON_CDW14_ELBTL_MASK); - if (sts >= 48) - cdw3 |= NVME_FIELD_ENCODE(storage_tag >> (sts - 48), - NVME_IOCS_COMMON_CDW3_ELBTU_SHIFT, - NVME_IOCS_COMMON_CDW3_ELBTU_MASK); - else - cdw3 |= NVME_FIELD_ENCODE(storage_tag << (48 - sts), - NVME_IOCS_COMMON_CDW3_ELBTU_SHIFT, - NVME_IOCS_COMMON_CDW3_ELBTU_MASK); - cdw2 = NVME_FIELD_ENCODE(storage_tag >> (sts - 16), - NVME_IOCS_COMMON_CDW2_ELBTU_SHIFT, - NVME_IOCS_COMMON_CDW2_ELBTU_MASK); - break; - case NVME_NVM_PIF_64B_GUARD: - cdw14 = NVME_FIELD_ENCODE(reftag, - NVME_IOCS_COMMON_CDW14_ELBTL_SHIFT, - NVME_IOCS_COMMON_CDW14_ELBTL_MASK); - cdw3 = NVME_FIELD_ENCODE((reftag >> 32) & 0xffff, - NVME_IOCS_COMMON_CDW3_ELBTU_SHIFT, - NVME_IOCS_COMMON_CDW3_ELBTU_MASK); - cdw14 |= NVME_FIELD_ENCODE(storage_tag << (48 - sts), - NVME_IOCS_COMMON_CDW14_ELBTL_SHIFT, - NVME_IOCS_COMMON_CDW14_ELBTL_MASK); - if (sts >= 16) - cdw3 |= NVME_FIELD_ENCODE((storage_tag >> (sts - 16)) & 0xffff, - NVME_IOCS_COMMON_CDW3_ELBTU_SHIFT, - NVME_IOCS_COMMON_CDW3_ELBTU_MASK); - else - cdw3 |= NVME_FIELD_ENCODE((storage_tag << (16 - sts)) & 0xffff, - NVME_IOCS_COMMON_CDW3_ELBTU_SHIFT, - NVME_IOCS_COMMON_CDW3_ELBTU_MASK); - break; - default: - return -EINVAL; - } - - cmd->cdw2 = cdw2; - cmd->cdw3 = cdw3; - cmd->cdw14 = cdw14; - - return 0; -} - -/** - * nvme_init_app_tag() - Initialize Command Dword fields for - * Logical Block Application Tag/Mask - * @cmd: Passthru command to use - * @lbat: Logical block application tag - * @lbatm: Logical block application tag mask - */ -static inline void -nvme_init_app_tag(struct nvme_passthru_cmd *cmd, - __u16 lbat, __u16 lbatm) -{ - cmd->cdw15 = NVME_FIELD_ENCODE(lbat, - NVME_IOCS_COMMON_CDW15_ELBAT_SHIFT, - NVME_IOCS_COMMON_CDW15_ELBAT_MASK) | - NVME_FIELD_ENCODE(lbatm, - NVME_IOCS_COMMON_CDW15_ELBATM_SHIFT, - NVME_IOCS_COMMON_CDW15_ELBATM_MASK); -} - -/** - * nvme_init_io() - Initialize passthru command for a generic user I/O command - * @cmd: Passthru command to use - * @nsid: Namespace ID - * @opcode: Opcode to execute - * @slba: Starting logical block - * @data: Pointer to user address of the data buffer - * @data_len: Length of user buffer, @data, in bytes - * @metadata: Pointer to user address of the metadata buffer - * @metadata_len:Length of user buffer, @metadata, in bytes - * - * Initializes the passthru command buffer for a generic NVM I/O command. - * Note: If @elbas is true, the caller must ensure the definition/logic for - * nvme_init_set_var_size_tags is available and that the return value from - * that function is checked for error. - */ -static inline void -nvme_init_io(struct nvme_passthru_cmd *cmd, __u8 opcode, __u32 nsid, __u64 slba, - void *data, __u32 data_len, void *metadata, __u32 metadata_len) -{ - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = opcode; - cmd->nsid = nsid; - cmd->metadata = (__u64)(uintptr_t)metadata; - cmd->addr = (__u64)(uintptr_t)data; - cmd->metadata_len = metadata_len; - cmd->data_len = data_len; - cmd->cdw10 = NVME_FIELD_ENCODE(slba, - NVME_IOCS_COMMON_CDW10_SLBAL_SHIFT, - NVME_IOCS_COMMON_CDW10_SLBAL_MASK); - cmd->cdw11 = NVME_FIELD_ENCODE(slba >> 32, - NVME_IOCS_COMMON_CDW11_SLBAU_SHIFT, - NVME_IOCS_COMMON_CDW11_SLBAU_MASK); -} - -/** - * nvme_init_read() - Initialize passthru command for a user read command - * @cmd: Passthru command to use - * @nsid: Namespace ID - * @slba: Starting logical block - * @nlb: Number of logical blocks (0-based) - * @control: Upper 16 bits of cdw12 - * @dsm: Data set management attributes (CETYPE is zero), - * see &enum nvme_io_dsm_flags - * @cev: Command Extension Value (CETYPE is non-zero) - * @data: Pointer to user address of the data buffer - * @data_len: Length of user buffer, @data, in bytes - * @metadata: Pointer to user address of the metadata buffer - * @metadata_len:Length of user buffer, @metadata, in bytes - * - * Initializes the passthru command buffer for the Read command. - * Note: Assumes a macro or separate function exists to translate the combined - * NLB/control/prinfo fields into cdw12/cdw13. This transformation assumes - * the parameters are used for a generic nvme_init_io wrapper. - */ -static inline void -nvme_init_read(struct nvme_passthru_cmd *cmd, __u32 nsid, __u64 slba, - __u16 nlb, __u16 control, __u8 dsm, __u16 cev, - void *data, __u32 data_len, void *metadata, __u32 metadata_len) -{ - nvme_init_io(cmd, nvme_cmd_read, nsid, slba, - data, data_len, metadata, metadata_len); - cmd->cdw12 = NVME_FIELD_ENCODE(nlb, - NVME_IOCS_COMMON_CDW12_NLB_SHIFT, - NVME_IOCS_COMMON_CDW12_NLB_MASK) | - NVME_FIELD_ENCODE(control, - NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT, - NVME_IOCS_COMMON_CDW12_CONTROL_MASK); - cmd->cdw13 = NVME_FIELD_ENCODE(dsm, - NVME_IOCS_COMMON_CDW13_DSM_SHIFT, - NVME_IOCS_COMMON_CDW13_DSM_MASK) | - NVME_FIELD_ENCODE(cev, - NVME_IOCS_COMMON_CDW13_CEV_SHIFT, - NVME_IOCS_COMMON_CDW13_CEV_MASK); -} - -/** - * nvme_init_write() - Initialize passthru command for a user write command - * @cmd: Passthru command to use - * @nsid: Namespace ID - * @slba: Starting logical block - * @nlb: Number of logical blocks (0-based) - * @control: Upper 16 bits of cdw12 - * @dspec: Directive specific value - * @dsm: Data set management attributes (CETYPE is zero), - * see &enum nvme_io_dsm_flags - * @cev: Command Extension Value (CETYPE is non-zero) - * @data: Pointer to user address of the data buffer - * @data_len: Length of user buffer, @data, in bytes - * @metadata: Pointer to user address of the metadata buffer - * @metadata_len:Length of user buffer, @metadata, in bytes - * - * Initializes the passthru command buffer for the Write command. - */ -static inline void -nvme_init_write(struct nvme_passthru_cmd *cmd, __u32 nsid, __u64 slba, - __u16 nlb, __u16 control, __u16 dspec, __u8 dsm, __u8 cev, - void *data, __u32 data_len, void *metadata, __u32 metadata_len) -{ - nvme_init_io(cmd, nvme_cmd_write, nsid, slba, - data, data_len, metadata, metadata_len); - cmd->cdw12 = NVME_FIELD_ENCODE(nlb, - NVME_IOCS_COMMON_CDW12_NLB_SHIFT, - NVME_IOCS_COMMON_CDW12_NLB_MASK) | - NVME_FIELD_ENCODE(control, - NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT, - NVME_IOCS_COMMON_CDW12_CONTROL_MASK); - cmd->cdw13 = NVME_FIELD_ENCODE(dspec, - NVME_IOCS_COMMON_CDW13_DSPEC_SHIFT, - NVME_IOCS_COMMON_CDW13_DSPEC_MASK) | - NVME_FIELD_ENCODE(dsm, - NVME_IOCS_COMMON_CDW13_DSM_SHIFT, - NVME_IOCS_COMMON_CDW13_DSM_MASK) | - NVME_FIELD_ENCODE(cev, - NVME_IOCS_COMMON_CDW13_CEV_SHIFT, - NVME_IOCS_COMMON_CDW13_CEV_MASK); -} -/** - * nvme_init_compare() - Initialize passthru command for a user compare command - * @cmd: Passthru command to use - * @nsid: Namespace ID - * @slba: Starting logical block - * @nlb: Number of logical blocks (0-based) - * @control: Command control flags, see &enum nvme_io_control_flags. - * @cev: Command Extension Value (CETYPE is non-zero) - * @data: Pointer to user address of the data buffer - * @data_len: Length of user buffer, @data, in bytes - * @metadata: Pointer to user address of the metadata buffer - * @metadata_len:Length of user buffer, @metadata, in bytes - * - * Initializes the passthru command buffer for the Compare command. - */ -static inline void -nvme_init_compare(struct nvme_passthru_cmd *cmd, __u32 nsid, __u64 slba, - __u16 nlb, __u16 control, __u8 cev, void *data, __u32 data_len, - void *metadata, __u32 metadata_len) -{ - nvme_init_io(cmd, nvme_cmd_compare, nsid, slba, - data, data_len, metadata, metadata_len); - cmd->cdw12 = NVME_FIELD_ENCODE(nlb, - NVME_IOCS_COMMON_CDW12_NLB_SHIFT, - NVME_IOCS_COMMON_CDW12_NLB_MASK) | - NVME_FIELD_ENCODE(control, - NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT, - NVME_IOCS_COMMON_CDW12_CONTROL_MASK); - cmd->cdw13 = NVME_FIELD_ENCODE(cev, - NVME_IOCS_COMMON_CDW13_CEV_SHIFT, - NVME_IOCS_COMMON_CDW13_CEV_MASK); -} - -/** - * nvme_init_write_zeros() - Initialize passthru command for a - * write zeroes command - * @cmd: Passthru command to use - * @nsid: Namespace ID - * @slba: Starting logical block - * @nlb: Number of logical blocks (0-based) - * @control: Upper 16 bits of cdw12 - * @dspec: Directive specific value - * @dsm: Data set management attributes (CETYPE is zero), - * see &enum nvme_io_dsm_flags - * @cev: Command Extension Value (CETYPE is non-zero) - * - * Initializes the passthru command buffer for the Write Zeroes command. - * Note: Write Zeroes command does not transfer data or metadata. - */ -static inline void -nvme_init_write_zeros(struct nvme_passthru_cmd *cmd, __u32 nsid, __u64 slba, - __u16 nlb, __u16 control, __u16 dspec, __u8 dsm, __u8 cev) -{ - nvme_init_io(cmd, nvme_cmd_write_zeroes, nsid, slba, NULL, 0, NULL, 0); - cmd->cdw12 = NVME_FIELD_ENCODE(nlb, - NVME_IOCS_COMMON_CDW12_NLB_SHIFT, - NVME_IOCS_COMMON_CDW12_NLB_MASK) | - NVME_FIELD_ENCODE(control, - NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT, - NVME_IOCS_COMMON_CDW12_CONTROL_MASK); - cmd->cdw13 = NVME_FIELD_ENCODE(dspec, - NVME_IOCS_COMMON_CDW13_DSPEC_SHIFT, - NVME_IOCS_COMMON_CDW13_DSPEC_MASK) | - NVME_FIELD_ENCODE(dsm, - NVME_IOCS_COMMON_CDW13_DSM_SHIFT, - NVME_IOCS_COMMON_CDW13_DSM_MASK) | - NVME_FIELD_ENCODE(cev, - NVME_IOCS_COMMON_CDW13_CEV_SHIFT, - NVME_IOCS_COMMON_CDW13_CEV_MASK); -} - -/** - * nvme_init_write_uncorrectable() - Initialize passthru command for a - * write uncorrectable command - * @cmd: Passthru command to use - * @nsid: Namespace ID - * @slba: Starting logical block - * @nlb: Number of logical blocks (0-based) - * @control: Upper 16 bits of cdw12 - * @dspec: Directive specific value - * - * Initializes the passthru command buffer for the Write Uncorrectable command. - * Note: This command transfers no data or metadata. - */ -static inline void -nvme_init_write_uncorrectable(struct nvme_passthru_cmd *cmd, __u32 nsid, - __u64 slba, __u16 nlb, __u16 control, __u16 dspec) -{ - nvme_init_io(cmd, nvme_cmd_write_uncor, nsid, slba, NULL, 0, NULL, 0); - cmd->cdw12 = NVME_FIELD_ENCODE(nlb, - NVME_IOCS_COMMON_CDW12_NLB_SHIFT, - NVME_IOCS_COMMON_CDW12_NLB_MASK) | - NVME_FIELD_ENCODE(control, - NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT, - NVME_IOCS_COMMON_CDW12_CONTROL_MASK); - cmd->cdw13 = NVME_FIELD_ENCODE(dspec, - NVME_IOCS_COMMON_CDW13_DSPEC_SHIFT, - NVME_IOCS_COMMON_CDW13_DSPEC_MASK); -} - -/** - * nvme_init_verify() - Initialize passthru command for a verify command - * @cmd: Passthru command to use - * @nsid: Namespace ID - * @slba: Starting logical block - * @nlb: Number of logical blocks (0-based) - * @control: Upper 16 bits of cdw12 - * @cev: Command Extension Value (CETYPE is non-zero) - * @data: Pointer to user address of the data buffer - * @data_len: Length of user buffer, @data, in bytes - * @metadata: Pointer to user address of the metadata buffer - * @metadata_len:Length of user buffer, @metadata, in bytes - * - * Initializes the passthru command buffer for the Verify command. - * Note: Verify command transfers data or metadata to the controller to perform - * the verification but not back to the host. - */ -static inline void -nvme_init_verify(struct nvme_passthru_cmd *cmd, __u32 nsid, __u64 slba, - __u16 nlb, __u16 control, __u8 cev, void *data, __u32 data_len, - void *metadata, __u32 metadata_len) -{ - nvme_init_io(cmd, nvme_cmd_verify, nsid, slba, - data, data_len, metadata, metadata_len); - cmd->cdw12 = NVME_FIELD_ENCODE(nlb, - NVME_IOCS_COMMON_CDW12_NLB_SHIFT, - NVME_IOCS_COMMON_CDW12_NLB_MASK) | - NVME_FIELD_ENCODE(control, - NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT, - NVME_IOCS_COMMON_CDW12_CONTROL_MASK); - cmd->cdw13 = NVME_FIELD_ENCODE(cev, - NVME_IOCS_COMMON_CDW13_CEV_SHIFT, - NVME_IOCS_COMMON_CDW13_CEV_MASK); -} - -/** - * nvme_init_copy() - Initialize passthru command for Copy command - * @cmd: Passthru command to use - * @nsid: Namespace identifier - * @sdlba: Start destination LBA - * @nr: Number of ranges (1-based, 0-based in command) - * @desfmt: Descriptor format - * @prinfor: Protection information field for read - * @prinfow: Protection information field for write - * @cetype: Command Extension Type - * @dtype: Directive Type - * @stcw: Storage Tag Check Write - * @stcr: Storage Tag Check Read - * @fua: Force unit access - * @lr: Limited retry - * @cev: Command Extension Value - * @dspec: Directive specific value - * @cpydsc: Range description buffer - * - * Initializes the passthru command buffer for the Copy command by calculating - * the data length and calling the generic I/O initializer. - */ -static inline void -nvme_init_copy(struct nvme_passthru_cmd *cmd, __u32 nsid, __u64 sdlba, - __u16 nr, __u8 desfmt, __u8 prinfor, __u8 prinfow, - __u8 cetype, __u8 dtype, bool stcw, bool stcr, bool fua, - bool lr, __u16 cev, __u16 dspec, void *cpydsc) -{ - __u32 data_len; - - switch (desfmt) { - case 1: - data_len = nr * sizeof(struct nvme_copy_range_f1); - break; - case 2: - data_len = nr * sizeof(struct nvme_copy_range_f2); - break; - case 3: - data_len = nr * sizeof(struct nvme_copy_range_f3); - break; - default: - data_len = nr * sizeof(struct nvme_copy_range); - break; - } - - nvme_init_io(cmd, nvme_cmd_copy, nsid, sdlba, cpydsc, - data_len, NULL, 0); - cmd->cdw12 = NVME_FIELD_ENCODE(nr - 1, - NVME_COPY_CDW12_NR_SHIFT, - NVME_COPY_CDW12_NR_MASK) | - NVME_FIELD_ENCODE(desfmt, - NVME_COPY_CDW12_DESFMT_SHIFT, - NVME_COPY_CDW12_DESFMT_MASK) | - NVME_FIELD_ENCODE(prinfor, - NVME_COPY_CDW12_PRINFOR_SHIFT, - NVME_COPY_CDW12_PRINFOR_MASK) | - NVME_FIELD_ENCODE(cetype, - NVME_COPY_CDW12_CETYPE_SHIFT, - NVME_COPY_CDW12_CETYPE_MASK) | - NVME_FIELD_ENCODE(dtype, - NVME_COPY_CDW12_DTYPE_SHIFT, - NVME_COPY_CDW12_DTYPE_MASK) | - NVME_FIELD_ENCODE(stcw, - NVME_COPY_CDW12_STCW_SHIFT, - NVME_COPY_CDW12_STCW_MASK) | - NVME_FIELD_ENCODE(stcr, - NVME_COPY_CDW12_STCR_SHIFT, - NVME_COPY_CDW12_STCR_MASK) | - NVME_FIELD_ENCODE(prinfow, - NVME_COPY_CDW12_PRINFOW_SHIFT, - NVME_COPY_CDW12_PRINFOW_MASK) | - NVME_FIELD_ENCODE(fua, - NVME_COPY_CDW12_FUA_SHIFT, - NVME_COPY_CDW12_FUA_MASK) | - NVME_FIELD_ENCODE(lr, - NVME_COPY_CDW12_LR_SHIFT, - NVME_COPY_CDW12_LR_MASK); - cmd->cdw13 = NVME_FIELD_ENCODE(cev, - NVME_IOCS_COMMON_CDW13_CEV_SHIFT, - NVME_IOCS_COMMON_CDW13_CEV_MASK) | - NVME_FIELD_ENCODE(dspec, - NVME_IOCS_COMMON_CDW13_DSPEC_SHIFT, - NVME_IOCS_COMMON_CDW13_DSPEC_MASK); -} - -/** - * nvme_init_resv_acquire() - Initialize passthru command for - * Reservation Acquire - * @cmd: Passthru command to use - * @nsid: Namespace identifier - * @racqa: The action that is performed by the command, - * see &enum nvme_resv_racqa - * @iekey: Set to ignore the existing key - * @disnsrs: Disperse Namespace Reservation Support - * @rtype: The type of reservation to be create, see &enum nvme_resv_rtype - * @crkey: The current reservation key associated with the host - * @prkey: Preempt Reservation Key - * @payload: Data payload buffer to hold crkey and prkey - * - * Initializes the passthru command buffer for the Reservation Acquire command. - */ -static inline void -nvme_init_resv_acquire(struct nvme_passthru_cmd *cmd, __u32 nsid, - enum nvme_resv_racqa racqa, bool iekey, bool disnsrs, - enum nvme_resv_rtype rtype, __u64 crkey, __u64 prkey, - __le64 *payload) -{ - memset(cmd, 0, sizeof(*cmd)); - - payload[0] = htole64(crkey); - payload[1] = htole64(prkey); - - cmd->opcode = nvme_cmd_resv_acquire; - cmd->nsid = nsid; - cmd->data_len = 2 * sizeof(__le64); - cmd->addr = (__u64)(uintptr_t)payload; - cmd->cdw10 = NVME_FIELD_ENCODE(racqa, - NVME_RESV_ACQUIRE_CDW10_RACQA_SHIFT, - NVME_RESV_ACQUIRE_CDW10_RACQA_MASK) | - NVME_FIELD_ENCODE(iekey, - NVME_RESV_ACQUIRE_CDW10_IEKEY_SHIFT, - NVME_RESV_ACQUIRE_CDW10_IEKEY_MASK) | - NVME_FIELD_ENCODE(disnsrs, - NVME_RESV_ACQUIRE_CDW10_DISNSRS_SHIFT, - NVME_RESV_ACQUIRE_CDW10_DISNSRS_MASK) | - NVME_FIELD_ENCODE(rtype, - NVME_RESV_ACQUIRE_CDW10_RTYPE_SHIFT, - NVME_RESV_ACQUIRE_CDW10_RTYPE_MASK); -} - -/** - * nvme_init_resv_register() - Initialize passthru command for - * Reservation Register - * @cmd: Passthru command to use - * @nsid: Namespace identifier - * @rrega: The registration action, see &enum nvme_resv_rrega - * @iekey: Set to ignore the existing key - * @disnsrs: Disperse Namespace Reservation Support - * @cptpl: Change persist through power loss, see &enum nvme_resv_cptpl - * @crkey: The current reservation key associated with the host - * @nrkey: The new reservation key to be register if action is register or - * replace - * @payload: Data payload buffer to hold crkey and nrkey - * - * Initializes the passthru command buffer for the Reservation Register command. - */ -static inline void -nvme_init_resv_register(struct nvme_passthru_cmd *cmd, __u32 nsid, - enum nvme_resv_rrega rrega, bool iekey, bool disnsrs, - enum nvme_resv_cptpl cptpl, __u64 crkey, __u64 nrkey, - __le64 *payload) -{ - memset(cmd, 0, sizeof(*cmd)); - - payload[0] = htole64(crkey); - payload[1] = htole64(nrkey); - - cmd->opcode = nvme_cmd_resv_register; - cmd->nsid = nsid; - cmd->data_len = 2 * sizeof(__le64); - cmd->addr = (__u64)(uintptr_t)payload; - cmd->cdw10 = NVME_FIELD_ENCODE(rrega, - NVME_RESV_REGISTER_CDW10_RREGA_SHIFT, - NVME_RESV_REGISTER_CDW10_RREGA_MASK) | - NVME_FIELD_ENCODE(iekey, - NVME_RESV_REGISTER_CDW10_IEKEY_SHIFT, - NVME_RESV_REGISTER_CDW10_IEKEY_MASK) | - NVME_FIELD_ENCODE(disnsrs, - NVME_RESV_REGISTER_CDW10_DISNSRS_SHIFT, - NVME_RESV_REGISTER_CDW10_DISNSRS_MASK) | - NVME_FIELD_ENCODE(cptpl, - NVME_RESV_REGISTER_CDW10_CPTPL_SHIFT, - NVME_RESV_REGISTER_CDW10_CPTPL_MASK); -} - -/** - * nvme_init_resv_release() - Initialize passthru command for - * Reservation Release - * @cmd: Passthru command to use - * @nsid: Namespace identifier - * @rrela: Reservation release action, see &enum nvme_resv_rrela - * @iekey: Set to ignore the existing key - * @disnsrs: Disperse Namespace Reservation Support - * @rtype: The type of reservation to be create, see &enum nvme_resv_rtype - * @crkey: The current reservation key to release - * @payload: Data payload buffer to hold crkey - * - * Initializes the passthru command buffer for the Reservation Release command. - */ -static inline void -nvme_init_resv_release(struct nvme_passthru_cmd *cmd, __u32 nsid, - enum nvme_resv_rrela rrela, bool iekey, bool disnsrs, - enum nvme_resv_rtype rtype, __u64 crkey, __le64 *payload) -{ - memset(cmd, 0, sizeof(*cmd)); - - payload[0] = htole64(crkey); - - cmd->opcode = nvme_cmd_resv_release; - cmd->nsid = nsid; - cmd->data_len = sizeof(__le64); - cmd->addr = (__u64)(uintptr_t)payload; - cmd->cdw10 = NVME_FIELD_ENCODE(rrela, - NVME_RESV_RELEASE_CDW10_RRELA_SHIFT, - NVME_RESV_RELEASE_CDW10_RRELA_MASK) | - NVME_FIELD_ENCODE(iekey, - NVME_RESV_RELEASE_CDW10_IEKEY_SHIFT, - NVME_RESV_RELEASE_CDW10_IEKEY_MASK) | - NVME_FIELD_ENCODE(disnsrs, - NVME_RESV_RELEASE_CDW10_DISNSRS_SHIFT, - NVME_RESV_RELEASE_CDW10_DISNSRS_MASK) | - NVME_FIELD_ENCODE(rtype, - NVME_RESV_RELEASE_CDW10_RTYPE_SHIFT, - NVME_RESV_RELEASE_CDW10_RTYPE_MASK); -} - -/** - * nvme_init_resv_report() - Initialize passthru command for - * Reservation Report - * @cmd: Passthru command to use - * @nsid: Namespace identifier - * @eds: Request extended Data Structure - * @disnsrs: Disperse Namespace Reservation Support - * @report: The user space destination address to store the reservation - * report buffer - * @len: Number of bytes to request transferred with this command - * - * Initializes the passthru command buffer for the Reservation Report command. - */ -static inline void -nvme_init_resv_report(struct nvme_passthru_cmd *cmd, __u32 nsid, - bool eds, bool disnsrs, struct nvme_resv_status *report, - __u32 len) -{ - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_cmd_resv_report; - cmd->nsid = nsid; - cmd->data_len = len; - cmd->addr = (__u64)(uintptr_t)report; - cmd->cdw10 = (len >> 2) - 1; - cmd->cdw11 = NVME_FIELD_ENCODE(eds, - NVME_RESV_REPORT_CDW11_EDS_SHIFT, - NVME_RESV_REPORT_CDW11_EDS_MASK) | - NVME_FIELD_ENCODE(disnsrs, - NVME_RESV_REPORT_CDW11_DISNSRS_SHIFT, - NVME_RESV_REPORT_CDW11_DISNSRS_MASK); -} - -/** - * nvme_init_io_mgmt_recv() - Initialize passthru command for - * I/O Management Receive command - * @cmd: Passthru command to use - * @nsid: Namespace identifier - * @mo: Management Operation - * @mos: Management Operation Specific - * @data: Userspace address of the data buffer - * @len: Length of @data - * - * Initializes the passthru command buffer for the I/O Management - * Receive command. - */ -static inline void -nvme_init_io_mgmt_recv(struct nvme_passthru_cmd *cmd, __u32 nsid, - __u8 mo, __u16 mos, void *data, __u32 len) -{ - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_cmd_io_mgmt_recv; - cmd->nsid = nsid; - cmd->data_len = len; - cmd->addr = (__u64)(uintptr_t)data; - cmd->cdw10 = NVME_FIELD_ENCODE(mo, - NVME_IO_MGMT_RECV_CDW10_MO_SHIFT, - NVME_IO_MGMT_RECV_CDW10_MO_MASK) | - NVME_FIELD_ENCODE(mos, - NVME_IO_MGMT_RECV_CDW10_MOS_SHIFT, - NVME_IO_MGMT_RECV_CDW10_MOS_MASK); - cmd->cdw11 = (len >> 2) - 1; -} - -/** - * nvme_init_fdp_reclaim_unit_handle_status() - Initialize passthru command - * to get reclaim unit handle status - * @cmd: Passthru command to use - * @nsid: Namespace identifier - * @data: Response buffer - * @len: Length of response buffer - * - * Initializes the passthru command buffer for the I/O Management Receive - - * Reclaim Unit Handle Status command. - */ -static inline void -nvme_init_fdp_reclaim_unit_handle_status(struct nvme_passthru_cmd *cmd, - __u32 nsid, void *data, __u32 len) -{ - nvme_init_io_mgmt_recv(cmd, nsid, NVME_IO_MGMT_RECV_RUH_STATUS, 0, - data, len); -} - -/** - * nvme_init_io_mgmt_send() - Initialize passthru command for - * I/O Management Send command - * @cmd: Passthru command to use - * @nsid: Namespace identifier - * @mo: Management Operation - * @mos: Management Operation Specific - * @data: Userspace address of the data buffer - * @len: Length of @data - * - * Initializes the passthru command buffer for the I/O Management Send command. - */ -static inline void -nvme_init_io_mgmt_send(struct nvme_passthru_cmd *cmd, __u32 nsid, - __u8 mo, __u16 mos, void *data, __u32 len) -{ - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_cmd_io_mgmt_send; - cmd->nsid = nsid; - cmd->data_len = len; - cmd->addr = (__u64)(uintptr_t)data; - cmd->cdw10 = NVME_FIELD_ENCODE(mo, - NVME_IO_MGMT_SEND_CDW10_MO_SHIFT, - NVME_IO_MGMT_SEND_CDW10_MO_MASK) | - NVME_FIELD_ENCODE(mos, - NVME_IO_MGMT_SEND_CDW10_MOS_SHIFT, - NVME_IO_MGMT_SEND_CDW10_MOS_MASK); -} - -/** - * nvme_init_fdp_reclaim_unit_handle_update() - Initialize passthru command to - * update a list of reclaim unit handles - * @cmd: Passthru command to use - * @nsid: Namespace identifier - * @pids: List of placement identifiers buffer - * @npids: Number of placement identifiers - * - * Initializes the passthru command buffer for the I/O Management Send - - * Reclaim Unit Handle Update command. - */ -static inline void -nvme_init_fdp_reclaim_unit_handle_update(struct nvme_passthru_cmd *cmd, - __u32 nsid, void *pids, unsigned int npids) -{ - __u16 mos = npids - 1; /* MOS = NPI - 1 */ - __u32 len = npids * sizeof(__u16); - - nvme_init_io_mgmt_send(cmd, nsid, NVME_IO_MGMT_SEND_RUH_UPDATE, - mos, pids, len); -} - -/** - * nvme_init_zns_mgmt_send() - Initialize passthru command for - * ZNS management send command - * @cmd: Passthru command to use - * @nsid: Namespace ID - * @slba: Starting logical block address - * @zsa: Zone send action - * @selall: Select all flag - * @zsaso: Zone Send Action Specific Option - * @zm: Zone Management - * @data: Userspace address of the data buffer - * @len: Length of @data - * - * Initializes the passthru command buffer for the ZNS Management Send command. - */ -static inline void -nvme_init_zns_mgmt_send(struct nvme_passthru_cmd *cmd, __u32 nsid, - __u64 slba, enum nvme_zns_send_action zsa, bool selall, - __u8 zsaso, __u8 zm, void *data, __u32 len) -{ - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_zns_cmd_mgmt_send; - cmd->nsid = nsid; - cmd->data_len = len; - cmd->addr = (__u64)(uintptr_t)data; - cmd->cdw10 = slba & 0xffffffff; - cmd->cdw11 = slba >> 32; - cmd->cdw13 = NVME_FIELD_ENCODE(zsa, - NVME_ZNS_MGMT_SEND_ZSA_SHIFT, - NVME_ZNS_MGMT_SEND_ZSA_MASK) | - NVME_FIELD_ENCODE(selall, - NVME_ZNS_MGMT_SEND_SEL_SHIFT, - NVME_ZNS_MGMT_SEND_SEL_MASK) | - NVME_FIELD_ENCODE(zsaso, - NVME_ZNS_MGMT_SEND_ZSASO_SHIFT, - NVME_ZNS_MGMT_SEND_ZSASO_MASK) | - NVME_FIELD_ENCODE(zm, - NVME_ZNS_MGMT_SEND_ZM_SHIFT, - NVME_ZNS_MGMT_SEND_ZM_MASK); -} - -/** - * nvme_init_zns_mgmt_recv() - Initialize passthru command for - * ZNS management receive command - * @cmd: Passthru command to use - * @nsid: Namespace ID - * @slba: Starting logical block address - * @zra: zone receive action - * @zras: Zone receive action specific field - * @zraspf: Zone receive action specific features - * @data: Userspace address of the data buffer - * @len: Length of @data - * - * Initializes the passthru command buffer for the ZNS Management - * Receive command. - */ -static inline void -nvme_init_zns_mgmt_recv(struct nvme_passthru_cmd *cmd, __u32 nsid, - __u64 slba, enum nvme_zns_recv_action zra, __u16 zras, - bool zraspf, void *data, __u32 len) -{ - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_zns_cmd_mgmt_recv; - cmd->nsid = nsid; - cmd->data_len = len; - cmd->addr = (__u64)(uintptr_t)data; - cmd->cdw10 = slba & 0xffffffff; - cmd->cdw11 = slba >> 32; - cmd->cdw12 = (len >> 2) - 1; - cmd->cdw13 = NVME_FIELD_ENCODE(zra, - NVME_ZNS_MGMT_RECV_ZRA_SHIFT, - NVME_ZNS_MGMT_RECV_ZRA_MASK) | - NVME_FIELD_ENCODE(zras, - NVME_ZNS_MGMT_RECV_ZRAS_SHIFT, - NVME_ZNS_MGMT_RECV_ZRAS_MASK) | - NVME_FIELD_ENCODE(zraspf, - NVME_ZNS_MGMT_RECV_ZRASPF_SHIFT, - NVME_ZNS_MGMT_RECV_ZRASPF_MASK); -} - -/** - * nvme_init_zns_report_zones() - Initialize passthru command to return - * the list of zones - * @cmd: Passthru command to use - * @nsid: Namespace ID - * @slba: Starting LBA - * @opts: Reporting options - * @extended: Extended report - * @partial: Partial report requested - * @data: Userspace address of the report zones data buffer - * @len: Length of the data buffer - * - * Initializes the passthru command buffer for the ZNS Management Receive - - * Report Zones command. - */ -static inline void -nvme_init_zns_report_zones(struct nvme_passthru_cmd *cmd, __u32 nsid, - __u64 slba, enum nvme_zns_report_options opts, - bool extended, bool partial, - void *data, __u32 len) -{ - enum nvme_zns_recv_action zra = extended ? - NVME_ZNS_ZRA_EXTENDED_REPORT_ZONES : NVME_ZNS_ZRA_REPORT_ZONES; - __u16 zras = (__u16)opts; - bool zraspf = partial; /* ZRASPF is Partial Report Requested */ - - nvme_init_zns_mgmt_recv(cmd, nsid, slba, zra, zras, zraspf, data, len); -} - -/** - * nvme_init_zns_append() - Initialize passthru command to append data to a zone - * @cmd: Passthru command to use - * @nsid: Namespace ID - * @zslba: Zone start logical block address - * @nlb: Number of logical blocks - * @control: Upper 16 bits of cdw12 - * @cev: Command Extension Value - * @dspec: Directive Specific - * @data: Userspace address of the data buffer - * @data_len: Length of @data - * @metadata: Userspace address of the metadata buffer - * @metadata_len: Length of @metadata - * - * Initializes the passthru command buffer for the ZNS Append command. - */ -static inline void -nvme_init_zns_append(struct nvme_passthru_cmd *cmd, __u32 nsid, - __u64 zslba, __u16 nlb, __u16 control, __u16 cev, __u16 dspec, - void *data, __u32 data_len, void *metadata, __u32 metadata_len) -{ - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_zns_cmd_append; - cmd->nsid = nsid; - cmd->metadata = (__u64)(uintptr_t)metadata; - cmd->addr = (__u64)(uintptr_t)data; - cmd->metadata_len = metadata_len; - cmd->data_len = data_len; - cmd->cdw10 = NVME_FIELD_ENCODE(zslba, - NVME_IOCS_COMMON_CDW10_SLBAL_SHIFT, - NVME_IOCS_COMMON_CDW10_SLBAL_MASK); - cmd->cdw11 = NVME_FIELD_ENCODE(zslba >> 32, - NVME_IOCS_COMMON_CDW11_SLBAU_SHIFT, - NVME_IOCS_COMMON_CDW11_SLBAU_MASK); - cmd->cdw12 = NVME_FIELD_ENCODE(nlb, - NVME_IOCS_COMMON_CDW12_NLB_SHIFT, - NVME_IOCS_COMMON_CDW12_NLB_MASK) | - NVME_FIELD_ENCODE(control, - NVME_IOCS_COMMON_CDW12_CONTROL_SHIFT, - NVME_IOCS_COMMON_CDW12_CONTROL_MASK); - cmd->cdw13 = NVME_FIELD_ENCODE(dspec, - NVME_IOCS_COMMON_CDW13_DSPEC_SHIFT, - NVME_IOCS_COMMON_CDW13_DSPEC_MASK); - if (control & NVME_IOCS_COMMON_CDW12_CETYPE_MASK) - cmd->cdw13 |= NVME_FIELD_ENCODE(cev, - NVME_IOCS_COMMON_CDW13_CEV_SHIFT, - NVME_IOCS_COMMON_CDW13_CEV_MASK); -} - -/** - * nvme_init_dim_send() - Initialize passthru command for - * Discovery Information Management (DIM) Send - * @cmd: Passthru command to use - * @tas: Task field of the Command Dword 10 (cdw10) - * @data: Pointer to the DIM data buffer - * @len: Length of @data - * - * Initializes the passthru command buffer for the Discovery Information - * Management Send command. - */ -static inline void -nvme_init_dim_send(struct nvme_passthru_cmd *cmd, - __u8 tas, void *data, __u32 len) -{ - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_admin_discovery_info_mgmt; - cmd->data_len = len; - cmd->addr = (__u64)(uintptr_t)data; - cmd->cdw10 = NVME_FIELD_ENCODE(tas, - NVME_DIM_TAS_SHIFT, - NVME_DIM_TAS_MASK); - -} - -/** - * nvme_init_lm_cdq_create() - Initialize passthru command for - * Controller Data Queue create - Controller Data Queue command - * @cmd: Passthru command to use - * @mos: Management Operation Specific (MOS): This field is - * specific to the SEL type - * @cntlid: Controller ID: For Create CDQ, specifies the target - * migratable controller - * @cdqsize: For Create CDQ, specifies the size of CDQ, in dwords - 4 byte - * @data: Pointer to data buffer - * - * Initializes the passthru command buffer for the Controller Data Queue - * command. Note: The result CDQID is returned in the CQE dword0, which the - * submission function must handle. - */ -static inline void -nvme_init_lm_cdq_create(struct nvme_passthru_cmd *cmd, - __u16 mos, __u16 cntlid, __u32 cdqsize, void *data) -{ - __u16 cqs; - - memset(cmd, 0, sizeof(*cmd)); - - cqs = NVME_FIELD_ENCODE(cntlid, - NVME_LM_CREATE_CDQ_CNTLID_SHIFT, - NVME_LM_CREATE_CDQ_CNTLID_MASK); - - cmd->opcode = nvme_admin_ctrl_data_queue; - cmd->data_len = cdqsize << 2; - cmd->addr = (__u64)(uintptr_t)data; - cmd->cdw10 = NVME_FIELD_ENCODE(NVME_LM_SEL_CREATE_CDQ, - NVME_LM_CDQ_SEL_SHIFT, - NVME_LM_CDQ_SEL_MASK) | - NVME_FIELD_ENCODE(mos, - NVME_LM_CDQ_MOS_SHIFT, - NVME_LM_CDQ_MOS_MASK); - cmd->cdw11 = NVME_FIELD_ENCODE(NVME_LM_CREATE_CDQ_PC, - NVME_LM_CREATE_CDQ_PC_SHIFT, - NVME_LM_CREATE_CDQ_PC_MASK) | - NVME_FIELD_ENCODE(cqs, - NVME_LM_CQS_SHIFT, - NVME_LM_CQS_MASK); - cmd->cdw12 = cdqsize; -} - -/** - * nvme_init_lm_cdq_delete() - Initialize passthru command for - * Controller Data Queue delete - Controller Data Queue command - * @cmd: Passthru command to use - * @mos: Management Operation Specific (MOS): This field is - * specific to the SEL type - * @cdqid: Controller Data Queue ID (CDQID): For Delete CDQ, this - * field is the CDQID to delete. - * - * Initializes the passthru command buffer for the Controller Data Queue delete - * command. - */ -static inline void -nvme_init_lm_cdq_delete(struct nvme_passthru_cmd *cmd, - __u16 mos, __u16 cdqid) -{ - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_admin_ctrl_data_queue; - cmd->cdw10 = NVME_FIELD_ENCODE(NVME_LM_SEL_DELETE_CDQ, - NVME_LM_CDQ_SEL_SHIFT, - NVME_LM_CDQ_SEL_MASK) | - NVME_FIELD_ENCODE(mos, - NVME_LM_CDQ_MOS_SHIFT, - NVME_LM_CDQ_MOS_MASK); - cmd->cdw11 = NVME_FIELD_ENCODE(cdqid, - NVME_LM_DELETE_CDQ_CDQID_SHIFT, - NVME_LM_DELETE_CDQ_CDQID_MASK); -} - -/** - * nvme_init_lm_track_send() - Initialize passthru command for - * Track Send command - * @cmd: Passthru command to use - * @sel: Select (SEL): This field specifies the type of - * management operation to perform - * @mos: Management Operation Specific (MOS): This field - * is specific to the SEL type - * @cdqid: Controller Data Queue ID (CDQID) - * - * Initializes the passthru command buffer for the Track Send command. - */ -static inline void -nvme_init_lm_track_send(struct nvme_passthru_cmd *cmd, - __u8 sel, __u16 mos, __u16 cdqid) -{ - - memset(cmd, 0, sizeof(*cmd)); - cmd->opcode = nvme_admin_track_send; - cmd->cdw10 = NVME_FIELD_ENCODE(sel, - NVME_LM_TRACK_SEND_SEL_SHIFT, - NVME_LM_TRACK_SEND_SEL_MASK) | - NVME_FIELD_ENCODE(mos, - NVME_LM_TRACK_SEND_MOS_SHIFT, - NVME_LM_TRACK_SEND_MOS_MASK); - cmd->cdw11 = cdqid; -} - -/** - * nvme_init_lm_migration_send() - Initialize passthru command for - * Migration Send command - * @cmd: Passthru command to use - * @sel: Select (SEL): This field specifies the type of management - * operation to perform. - * @mos: Management Operation Specific (MOS): This field is specific - * to the SEL type - * @cntlid: Controller ID: This field specifies the identifier of the - * controller to which the operation is performed. - * @stype: Suspend Type (STYPE): This field specifies the type of suspend. - * @dudmq: Delete User Data Migration Queue (DUDMQ): If set, the migration - * queue is deleted is deleted as part of the Suspend operation. - * @csvi: Controller State Version Index (CSVI) - * @csuuidi: Controller State UUID Index (CSUUIDI) - * @cso: Offset: This field specifies the offset, in bytes, within - * the data available to be returned and specifies the starting - * point for that data for what is actually returned to the host. - * @uidx: UUID Index (UIDX) - * @data: Pointer to data buffer - * @len: Length of @data - * - * Initializes the passthru command buffer for the Migration Send command. - */ -static inline void -nvme_init_lm_migration_send(struct nvme_passthru_cmd *cmd, - __u16 sel, __u16 mos, __u16 cntlid, __u8 stype, bool dudmq, - __u8 csvi, __u16 csuuidi, __u64 cso, __u8 uidx, - void *data, __u32 len) -{ - __u32 cdw10 = NVME_FIELD_ENCODE(sel, - NVME_LM_MIGRATION_SEND_SEL_SHIFT, - NVME_LM_MIGRATION_SEND_SEL_MASK) | - NVME_FIELD_ENCODE(mos, - NVME_LM_MIGRATION_SEND_MOS_SHIFT, - NVME_LM_MIGRATION_SEND_MOS_MASK); - __u32 cdw11 = 0; - __u32 cdw14 = NVME_FIELD_ENCODE(uidx, - NVME_LM_MIGRATION_SEND_UIDX_SHIFT, - NVME_LM_MIGRATION_SEND_UIDX_MASK); - - if (sel == NVME_LM_SEL_SUSPEND) { - cdw11 = NVME_FIELD_ENCODE(stype, - NVME_LM_STYPE_SHIFT, - NVME_LM_STYPE_MASK) | - NVME_FIELD_ENCODE(cntlid, - NVME_LM_SUSPEND_CNTLID_SHIFT, - NVME_LM_SUSPEND_CNTLID_MASK); - if (dudmq) - cdw11 |= NVME_LM_DUDMQ; - } else if (sel == NVME_LM_SEL_RESUME) { - cdw11 = NVME_FIELD_ENCODE(cntlid, - NVME_LM_RESUME_CNTLID_SHIFT, - NVME_LM_RESUME_CNTLID_MASK); - } else if (sel == NVME_LM_SEL_SET_CONTROLLER_STATE) { - cdw11 = NVME_FIELD_ENCODE(csuuidi, - NVME_LM_SET_CONTROLLER_STATE_CSUUIDI_SHIFT, - NVME_LM_SET_CONTROLLER_STATE_CSUUIDI_MASK) | - NVME_FIELD_ENCODE(csvi, - NVME_LM_SET_CONTROLLER_STATE_CSVI_SHIFT, - NVME_LM_SET_CONTROLLER_STATE_CSVI_MASK) | - NVME_FIELD_ENCODE(cntlid, - NVME_LM_SET_CONTROLLER_STATE_CNTLID_SHIFT, - NVME_LM_SET_CONTROLLER_STATE_CNTLID_MASK); - } - - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_admin_migration_send; - cmd->data_len = len; - cmd->addr = (__u64)(uintptr_t)data; - cmd->cdw10 = cdw10; - cmd->cdw11 = cdw11; - cmd->cdw12 = (__u32)cso; - cmd->cdw13 = (__u32)(cso >> 32); - cmd->cdw14 = cdw14; - cmd->cdw15 = len / sizeof(__u32); -} - -/** - * nvme_init_lm_migration_recv() - Initialize passthru command for - * Migration Receive command - * @cmd: Passthru command to use - * @offset: Offset: This field specifies the offset, in bytes, within - * the data available to be returned and specifies the starting - * point for that data for what is actually returned to the host. - * @mos: Management Operation Specific (MOS): This field is specific to - * the SEL type - * @cntlid: Controller ID: This field specifies the identifier of the - * controller to which the operation is performed. - * @csuuidi: Controller State UUID Index (CSUUIDI) - * @sel: Select (SEL): This field specifies the type of management - * operation to perform - * @uidx: UUID Index (UIDX) - * @csuidxp: Controller State UUID Index Parameter (CSUIDXP) - * @data: Pointer to data buffer - * @len: Length of @data - * - * Initializes the passthru command buffer for the Migration Receive command. - */ -static inline void -nvme_init_lm_migration_recv(struct nvme_passthru_cmd *cmd, - __u64 offset, __u16 mos, __u16 cntlid, __u16 csuuidi, __u8 sel, - __u8 uidx, __u8 csuidxp, void *data, __u32 len) -{ - __u32 cdw11 = 0; - __u32 data_len = 0; - - if (sel == NVME_LM_SEL_GET_CONTROLLER_STATE) { - cdw11 = NVME_FIELD_ENCODE(csuidxp, - NVME_LM_GET_CONTROLLER_STATE_CSUIDXP_SHIFT, - NVME_LM_GET_CONTROLLER_STATE_CSUIDXP_MASK) | - NVME_FIELD_ENCODE(csuuidi, - NVME_LM_GET_CONTROLLER_STATE_CSUUIDI_SHIFT, - NVME_LM_GET_CONTROLLER_STATE_CSUUIDI_MASK) | - NVME_FIELD_ENCODE(cntlid, - NVME_LM_GET_CONTROLLER_STATE_CNTLID_SHIFT, - NVME_LM_GET_CONTROLLER_STATE_CNTLID_MASK); - data_len = len; - } - - memset(cmd, 0, sizeof(*cmd)); - - cmd->opcode = nvme_admin_migration_receive; - cmd->data_len = data_len; - cmd->addr = (__u64)(uintptr_t)data; - cmd->cdw10 = NVME_FIELD_ENCODE(sel, - NVME_LM_MIGRATION_RECV_SEL_SHIFT, - NVME_LM_MIGRATION_RECV_SEL_MASK) | - NVME_FIELD_ENCODE(mos, - NVME_LM_MIGRATION_RECV_MOS_SHIFT, - NVME_LM_MIGRATION_RECV_MOS_MASK); - cmd->cdw11 = cdw11; - cmd->cdw12 = (__u32)offset; - cmd->cdw13 = (__u32)(offset >> 32); - cmd->cdw14 = NVME_FIELD_ENCODE(uidx, - NVME_LM_MIGRATION_RECV_UIDX_SHIFT, - NVME_LM_MIGRATION_RECV_UIDX_MASK); - cmd->cdw15 = len ? (__u32)((len - 1) / sizeof(__u32)) : 0; -} - -/** - * nvme_init_lm_set_features_ctrl_data_queue() - Initialize passthru command for - * Set Controller Data Queue feature - * @cmd: Passthru command to use - * @cdqid: Controller Data Queue ID (CDQID) - * @hp: Head Pointer (passed in cdw12) - * @tpt: Tail Pointer Trigger (passed in cdw13) - * @etpt: Enable Tail Pointer Trigger - * - * Initializes the passthru command buffer for the Set Features command with - * FID value %NVME_FEAT_FID_CTRL_DATA_QUEUE. - */ -static inline void -nvme_init_lm_set_features_ctrl_data_queue(struct nvme_passthru_cmd *cmd, - __u16 cdqid, __u32 hp, __u32 tpt, bool etpt) -{ - nvme_init_set_features(cmd, NVME_FEAT_FID_CTRL_DATA_QUEUE, false); - cmd->cdw11 = cdqid | - NVME_FIELD_ENCODE(etpt, - NVME_LM_CTRL_DATA_QUEUE_ETPT_SHIFT, - NVME_LM_CTRL_DATA_QUEUE_ETPT_MASK); - cmd->cdw12 = hp; - cmd->cdw13 = tpt; -} - -/** - * nvme_init_lm_get_features_ctrl_data_queue() - Initialize passthru command for - * Get Controller Data Queue feature - * @cmd: Passthru command to use - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * @cdqid: Controller Data Queue ID (CDQID) - * @qfd: Get Controller Data Queue feature data buffer - * - * Initializes the passthru command buffer for the Get Features command with - * FID value %NVME_FEAT_FID_CTRL_DATA_QUEUE. - */ -static inline void -nvme_init_lm_get_features_ctrl_data_queue(struct nvme_passthru_cmd *cmd, - enum nvme_get_features_sel sel, __u16 cdqid, - struct nvme_lm_ctrl_data_queue_fid_data *qfd) -{ - nvme_init_get_features(cmd, NVME_FEAT_FID_CTRL_DATA_QUEUE, sel); - cmd->data_len = sizeof(*qfd); - cmd->addr = (__u64)(uintptr_t)qfd; - cmd->cdw11 = cdqid; -} - -/** - * nvme_identify() - Submit a generic Identify command - * @hdl: Transport handle for the controller. - * @nsid: Namespace ID (if applicable to the requested CNS). - * @csi: Command Set Identifier. - * @cns: Identify Controller or Namespace Structure (CNS) value, - * specifying the type of data to be returned. - * @data: Pointer to the buffer where the identification data will - * be stored. - * @len: Length of the data buffer in bytes. - * - * The generic wrapper for submitting an Identify command, allowing the host - * to specify any combination of Identify parameters. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_identify(struct nvme_transport_handle *hdl, __u32 nsid, enum nvme_csi csi, - enum nvme_identify_cns cns, void *data, __u32 len) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_identify(&cmd, nsid, csi, cns, data, len); - - return nvme_submit_admin_passthru(hdl, &cmd); -} -/** - * nvme_identify_ctrl() - Submit an Identify Controller command - * @hdl: Transport handle for the controller. - * @id: Pointer to the buffer (&struct nvme_id_ctrl) where the - * controller identification data will be stored upon - * successful completion. - * - * Submits the Identify Controller command to retrieve the controller's - * capabilities and configuration data. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_identify_ctrl(struct nvme_transport_handle *hdl, - struct nvme_id_ctrl *id) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_identify_ctrl(&cmd, id); - - return nvme_submit_admin_passthru(hdl, &cmd); -} - -/** - * nvme_identify_active_ns_list() - Submit an Identify Active Namespace - * List command - * @hdl: Transport handle for the controller. - * @nsid: The Namespace ID to query - * @ns_list: Pointer to the buffer (&struct nvme_ns_list) where the - * active namespace list will be stored. - * - * Submits the Identify command to retrieve a list of active Namespace IDs. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_identify_active_ns_list(struct nvme_transport_handle *hdl, - __u32 nsid, struct nvme_ns_list *ns_list) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_identify_active_ns_list(&cmd, nsid, ns_list); - - return nvme_submit_admin_passthru(hdl, &cmd); -} - -/** - * nvme_identify_ns() - Submit an Identify Namespace command - * @hdl: Transport handle for the controller. - * @nsid: The Namespace ID to identify. - * @ns: Pointer to the buffer (&struct nvme_id_ns) where the namespace - * identification data will be stored. - * - * Submits the Identify command to retrieve the Namespace Identification - * data structure for a specified namespace. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ - -static inline int -nvme_identify_ns(struct nvme_transport_handle *hdl, - __u32 nsid, struct nvme_id_ns *ns) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_identify_ns(&cmd, nsid, ns); - - return nvme_submit_admin_passthru(hdl, &cmd); -} - -/** - * nvme_identify_csi_ns() - Submit a CSI-specific Identify Namespace command - * @hdl: Transport handle for the controller. - * @nsid: The Namespace ID to identify. - * @csi: The Command Set Identifier - * @uidx: The UUID Index for the command. - * @id_ns: Pointer to the buffer (@struct nvme_nvm_id_ns) where the - * CSI-specific namespace identification data will be stored. - * - * Submits the Identify command to retrieve Namespace Identification data - * specific to a Command Set Identifier (CSI). - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_identify_csi_ns(struct nvme_transport_handle *hdl, __u32 nsid, - enum nvme_csi csi, __u8 uidx, struct nvme_nvm_id_ns *id_ns) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_identify_csi_ns(&cmd, nsid, csi, uidx, id_ns); - - return nvme_submit_admin_passthru(hdl, &cmd); -} - -/** - * nvme_identify_uuid_list() - Submit an Identify UUID List command - * @hdl: Transport handle for the controller. - * @uuid_list: Pointer to the buffer (&struct nvme_id_uuid_list) where the - * UUID list will be stored. - * - * Submits the Identify command to retrieve a list of UUIDs associated - * with the controller. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_identify_uuid_list(struct nvme_transport_handle *hdl, - struct nvme_id_uuid_list *uuid_list) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_identify_uuid_list(&cmd, uuid_list); - - return nvme_submit_admin_passthru(hdl, &cmd); -} - -/** - * nvme_identify_csi_ns_user_data_format() - Submit an Identify CSI Namespace - * User Data Format command - * @hdl: Transport handle for the controller. - * @csi: Command Set Identifier. - * @fidx: Format Index, specifying which format entry to return. - * @uidx: The UUID Index for the command. - * @data: Pointer to the buffer where the format data will be stored. - * - * Submits the Identify command to retrieve a CSI-specific Namespace User - * Data Format data structure. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_identify_csi_ns_user_data_format(struct nvme_transport_handle *hdl, - enum nvme_csi csi, __u16 fidx, __u8 uidx, void *data) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_identify_csi_ns_user_data_format(&cmd, csi, fidx, uidx, data); - - return nvme_submit_admin_passthru(hdl, &cmd); -} - -/** - * nvme_identify_ns_granularity() - Submit an Identify Namespace Granularity - * List command - * @hdl: Transport handle for the controller. - * @gr_list: Pointer to the buffer (&struct nvme_id_ns_granularity_list) - * where the granularity list will be stored. - * - * Submits the Identify command to retrieve the Namespace Granularity List. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_identify_ns_granularity(struct nvme_transport_handle *hdl, - struct nvme_id_ns_granularity_list *gr_list) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_identify_ns_granularity(&cmd, gr_list); - - return nvme_submit_admin_passthru(hdl, &cmd); -} - -/** - * nvme_identify_ns_descs_list() - Submit an Identify Namespace ID Descriptor - * List command - * @hdl: Transport handle for the controller. - * @nsid: The Namespace ID to query. - * @descs: Pointer to the buffer (&struct nvme_ns_id_desc) where the - * descriptor list will be stored. - * - * Submits the Identify command to retrieve the Namespace ID Descriptor List - * for a specified namespace. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_identify_ns_descs_list(struct nvme_transport_handle *hdl, - __u32 nsid, struct nvme_ns_id_desc *descs) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_identify_ns_descs_list(&cmd, nsid, descs); - - return nvme_submit_admin_passthru(hdl, &cmd); -} - -/** - * nvme_zns_identify_ns() - Submit a ZNS-specific Identify Namespace command - * @hdl: Transport handle for the controller. - * @nsid: The Namespace ID to identify. - * @data: Pointer to the buffer (&struct nvme_zns_id_ns) where the ZNS - * namespace identification data will be stored. - * - * Submits the Identify command to retrieve the Zoned Namespace (ZNS) - * specific identification data structure for a specified namespace. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_zns_identify_ns(struct nvme_transport_handle *hdl, - __u32 nsid, struct nvme_zns_id_ns *data) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_zns_identify_ns(&cmd, nsid, data); - - return nvme_submit_admin_passthru(hdl, &cmd); -} - -/** - * nvme_get_log_simple() - Retrieve a log page using default parameters - * @hdl: Transport handle for the controller. - * @lid: Log Identifier, specifying the log page to retrieve - * (@enum nvme_cmd_get_log_lid). - * @data: Pointer to the buffer where the log page data will be stored. - * @len: Length of the data buffer in bytes. - * - * Submits the Get Log Page command using the common settings: - * NVME\_NSID\_ALL, Retain Asynchronous Event (RAE) set to false, - * and assuming the NVM Command Set. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_simple(struct nvme_transport_handle *hdl, - enum nvme_cmd_get_log_lid lid, void *data, __u32 len) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log(&cmd, NVME_NSID_ALL, lid, NVME_CSI_NVM, data, len); - - return nvme_get_log(hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE); -} - -/** - * nvme_get_log_supported_log_pages() - Retrieve the Supported Log Pages Log Page - * @hdl: Transport handle for the controller. - * @log: Pointer to the buffer (@struct nvme_supported_log_pages) where - * the log page data will be stored. - * - * Submits the Get Log Page command specifically for the Supported Log Pages - * Log. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_supported_log_pages(struct nvme_transport_handle *hdl, - struct nvme_supported_log_pages *log) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_SUPPORTED_LOG_PAGES, - NVME_CSI_NVM, log, sizeof(*log)); - - return nvme_get_log(hdl, &cmd, false, sizeof(*log)); -} - - -/** - * nvme_get_log_error() - Retrieve the Error Information Log Page - * @hdl: Transport handle for the controller. - * @nsid: Namespace ID to request the log for (usually NVME_NSID_ALL). - * @nr_entries: The maximum number of error log entries to retrieve. - * @err_log: Pointer to the buffer (array of @struct nvme_error_log_page) - * where the log page data will be stored. - * - * This log page describes extended error information for a command that - * completed with error, or may report an error that is not specific to a - * particular command. The total size requested is determined by - * @nr_entries * sizeof(@struct nvme_error_log_page). - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_error(struct nvme_transport_handle *hdl, __u32 nsid, - unsigned int nr_entries, struct nvme_error_log_page *err_log) -{ - struct nvme_passthru_cmd cmd; - size_t len = sizeof(*err_log) * nr_entries; - - nvme_init_get_log(&cmd, nsid, NVME_LOG_LID_ERROR, - NVME_CSI_NVM, err_log, len); - - return nvme_get_log(hdl, &cmd, false, len); -} - -/** - * nvme_get_log_fw_slot() - Retrieve the Firmware Slot Information Log Page - * @hdl: Transport handle for the controller. - * @nsid: Namespace ID to request the log for (use NVME_NSID_ALL). - * @fw_log: Pointer to the buffer (@struct nvme_firmware_slot) where the log - * page data will be stored. - * - * This log page describes the firmware revision stored in each firmware slot - * supported. The firmware revision is indicated as an ASCII string. The log - * page also indicates the active slot number. - * - * This command is typically issued for the controller scope, thus using - * NVME_NSID_ALL. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_fw_slot(struct nvme_transport_handle *hdl, __u32 nsid, - struct nvme_firmware_slot *fw_log) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log(&cmd, nsid, NVME_LOG_LID_FW_SLOT, - NVME_CSI_NVM, fw_log, sizeof(*fw_log)); - - return nvme_get_log(hdl, &cmd, false, sizeof(*fw_log)); -} - -/** - * nvme_get_log_changed_ns_list() - Retrieve the Namespace Change Log Page - * @hdl: Transport handle for the controller. - * @nsid: Namespace ID to request the log for (use NVME_NSID_ALL). - * @ns_log: Pointer to the buffer (@struct nvme_ns_list) where the log - * page data will be stored. - * - * This log page describes namespaces attached to this controller that have - * changed since the last time the namespace was identified, been added, or - * deleted. - * - * This command is typically issued for the controller scope, thus using - * NVME_NSID_ALL. The Retain Asynchronous Event (RAE) is true to retain - * asynchronous events associated with the log page - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_changed_ns_list(struct nvme_transport_handle *hdl, __u32 nsid, - struct nvme_ns_list *ns_log) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log(&cmd, nsid, NVME_LOG_LID_CHANGED_NS, - NVME_CSI_NVM, ns_log, sizeof(*ns_log)); - - return nvme_get_log(hdl, &cmd, true, sizeof(*ns_log)); -} - -/** - * nvme_get_log_cmd_effects() - Retrieve the Command Effects Log Page - * @hdl: Transport handle for the controller. - * @csi: Command Set Identifier for the requested log page. - * @effects_log:Pointer to the buffer (@struct nvme_cmd_effects_log) where the - * log page data will be stored. - * - * This log page describes the commands that the controller supports and the - * effects of those commands on the state of the NVM subsystem. - * - * It automatically sets the Log Identifier (LID) and Retain Asynchronous - * Event (RAE) to false. This command is typically issued for the controller - * scope, thus using NVME_NSID_ALL. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_cmd_effects(struct nvme_transport_handle *hdl, - enum nvme_csi csi, struct nvme_cmd_effects_log *effects_log) -{ - struct nvme_passthru_cmd cmd; - size_t len = sizeof(*effects_log); - - nvme_init_get_log_cmd_effects(&cmd, csi, effects_log); - - return nvme_get_log(hdl, &cmd, false, len); -} - -/** - * nvme_get_log_device_self_test() - Retrieve the Device Self-Test Log Page - * @hdl: Transport handle for the controller. - * @log: Pointer to the buffer (@struct nvme_self_test_log) where the log - * page data will be stored. - * - * This log page indicates the status of an in-progress self-test and the - * percent complete of that operation, and the results of the previous 20 - * self-test operations. - * - * It automatically sets the Log Identifier (LID) and Retain Asynchronous - * Event (RAE) to false. This command is typically issued for the controller - * scope, thus using NVME_NSID_ALL. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_device_self_test(struct nvme_transport_handle *hdl, - struct nvme_self_test_log *log) -{ - struct nvme_passthru_cmd cmd; - size_t len = sizeof(*log); - - nvme_init_get_log(&cmd, NVME_NSID_ALL, NVME_LOG_LID_DEVICE_SELF_TEST, - NVME_CSI_NVM, log, len); - - return nvme_get_log(hdl, &cmd, false, len); -} - -/** - * nvme_get_log_create_telemetry_host_mcda() - Create the Host Initiated - * Telemetry Log - * @hdl: Transport handle for the controller. - * @mcda: Maximum Created Data Area. Specifies the maximum amount of data - * that may be returned by the controller. - * @log: Pointer to the buffer (@struct nvme_telemetry_log) where the log - * page data will be stored. - * - * Submits the Get Log Page command to initiate the creation of a Host Initiated - * Telemetry Log. It sets the Log Identifier (LID) to Telemetry Host and - * includes the Maximum Created Data Area (MCDA) in the Log Specific Parameter - * (LSP) field along with the Create bit. - * - * It automatically sets Retain Asynchronous Event (RAE) to false. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_create_telemetry_host_mcda(struct nvme_transport_handle *hdl, - enum nvme_telemetry_da mcda, struct nvme_telemetry_log *log) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_create_telemetry_host_mcda(&cmd, mcda, log); - - return nvme_get_log(hdl, &cmd, false, sizeof(*log)); -} - -/** - * nvme_get_log_create_telemetry_host() - Create the Host Initiated Telemetry - * Log (Controller Determined Size) - * @hdl: Transport handle for the controller. - * @log: Pointer to the buffer (@struct nvme_telemetry_log) where the log - * page data will be stored. - * - * Submits the Get Log Page command to initiate the creation of a Host Initiated - * Telemetry Log. This is a convenience wrapper that automatically uses the - * Controller Determined size for the Maximum Created Data Area (MCDA). - * - * It automatically sets Retain Asynchronous Event (RAE) to false. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_create_telemetry_host(struct nvme_transport_handle *hdl, - struct nvme_telemetry_log *log) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_create_telemetry_host(&cmd, log); - - return nvme_get_log(hdl, &cmd, false, sizeof(*log)); -} - -/** - * nvme_get_log_telemetry_host() - Retrieve the Host-Initiated - * Telemetry Log Page (Retain) - * @hdl: Transport handle for the controller. - * @lpo: Offset (in bytes) into the telemetry data to start the retrieval. - * @log: Pointer to the buffer where the log page data will be stored. - * @len: Length of the buffer provided in @log. - * - * Submits the Get Log Page command to retrieve a previously captured - * Host-Initiated Telemetry Log, starting at a specified offset (@lpo). The Log - * Specific Parameter (LSP) field is set to indicate the capture should be - * retained (not deleted after read). - * - * It automatically sets the Log Identifier (LID) and Retain Asynchronous Event - * (RAE) to false. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_telemetry_host(struct nvme_transport_handle *hdl, - __u64 lpo, void *log, __u32 len) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_telemetry_host(&cmd, lpo, log, len); - - return nvme_get_log(hdl, &cmd, false, len); -} - -/** - * nvme_get_log_telemetry_ctrl() - Retrieve the Controller-Initiated - * Telemetry Log Page - * @hdl: Transport handle for the controller. - * @rae: Retain asynchronous events - * @lpo: Offset (in bytes) into the telemetry data to start the retrieval. - * @log: Pointer to the buffer where the log page data will be stored. - * @len: Length of the buffer provided in @log. - * - * Submits the Get Log Page command specifically for the Controller-Initiated - * Telemetry Log, allowing retrieval of data starting at a specified offset - * (@lpo). - * - * It automatically sets the Log Identifier (LID). - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_telemetry_ctrl(struct nvme_transport_handle *hdl, bool rae, - __u64 lpo, void *log, __u32 len) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_telemetry_ctrl(&cmd, lpo, log, len); - - return nvme_get_log(hdl, &cmd, rae, len); -} - -/** - * nvme_get_log_endurance_group() - Retrieve the Endurance Group Log Page - * @hdl: Transport handle for the controller. - * @endgid: Starting Endurance Group Identifier (ENDGID) to return in - * the list. - * @log: Pointer to the buffer (@struct nvme_endurance_group_log) where - * the log page data will be stored. - * - * This log page indicates if an Endurance Group Event has occurred for a - * particular Endurance Group. The ENDGID is placed in the Log Specific - * Identifier (LSI) field of the Get Log Page command. - * - * It automatically sets the Log Identifier (LID) and Retain Asynchronous - * Event (RAE) to false. This command is typically issued for the controller - * scope, thus using NVME_NSID_NONE. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_endurance_group(struct nvme_transport_handle *hdl, - __u16 endgid, struct nvme_endurance_group_log *log) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_endurance_group(&cmd, endgid, log); - - return nvme_get_log(hdl, &cmd, false, sizeof(*log)); -} - -/** - * nvme_get_log_predictable_lat_nvmset() - Retrieve the Predictable Latency - * Per NVM Set Log Page - * @hdl: Transport handle for the controller. - * @nvmsetid: The NVM Set Identifier (NVMSETID) for which to retrieve the log. - * @log: Pointer to the buffer (@struct nvme_nvmset_predictable_lat_log) - * where the log page data will be stored. - * - * Submits the Get Log Page command specifically for the Predictable Latency Per - * NVM Set Log. The NVMSETID is placed in the Log Specific Identifier (LSI) - * field of the command. - * - * It automatically sets the Log Identifier (LID) and Retain Asynchronous - * Event (RAE) to false. This command is typically issued for the controller - * scope, thus using NVME_NSID_NONE. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_predictable_lat_nvmset(struct nvme_transport_handle *hdl, - __u16 nvmsetid, struct nvme_nvmset_predictable_lat_log *log) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_predictable_lat_nvmset(&cmd, nvmsetid, log); - - return nvme_get_log(hdl, &cmd, false, sizeof(*log)); -} - -/** - * nvme_get_log_predictable_lat_event() - Retrieve the Predictable Latency Event - * Aggregate Log Page - * @hdl: Transport handle for the controller. - * @rae: Retain asynchronous events - * @lpo: Offset (in bytes) into the log page data to start the retrieval. - * @log: Pointer to the buffer where the log page data will be stored. - * @len: Length of the buffer provided in @log. - * - * Submits the Get Log Page command specifically for the Predictable Latency - * Event Aggregate Log, allowing retrieval of data starting at a specified - * offset (@lpo). - * - * It automatically sets the Log Identifier (LID) to - * NVME_LOG_LID_PREDICTABLE_LAT_AGG. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_predictable_lat_event(struct nvme_transport_handle *hdl, - bool rae, __u64 lpo, void *log, __u32 len) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_predictable_lat_event(&cmd, lpo, log, len); - - return nvme_get_log(hdl, &cmd, rae, len); -} - -/** - * nvme_get_log_fdp_configurations() - Retrieve the Flexible Data Placement - * (FDP) Configurations Log Page - * @hdl: Transport handle for the controller. - * @egid: Endurance Group Identifier (EGID) to return in the - * list (used in LSI). - * @lpo: Offset (in bytes) into the log page data to start the retrieval. - * @log: Pointer to the buffer where the log page data will be stored. - * @len: Length of the buffer provided in @log. - * - * Submits the Get Log Page command specifically for the FDP Configurations Log. - * The EGID is placed in the Log Specific Identifier (LSI) field. - * - * It automatically sets the Log Identifier (LID) and Retain Asynchronous - * Event (RAE) to false. This command is typically issued for the controller - * scope, thus using NVME_NSID_NONE. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_fdp_configurations(struct nvme_transport_handle *hdl, - __u16 egid, __u64 lpo, void *log, __u32 len) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_fdp_configurations(&cmd, egid, lpo, log, len); - - return nvme_get_log(hdl, &cmd, false, len); -} - -/** - * nvme_get_log_reclaim_unit_handle_usage() - Retrieve the FDP Reclaim Unit - * Handle (RUH) Usage Log Page - * @hdl: Transport handle for the controller. - * @egid: Endurance Group Identifier (EGID) (used in LSI). - * @lpo: Offset (in bytes) into the log page data to start the retrieval. - * @log: Pointer to the buffer where the log page data will be stored. - * @len: Length of the buffer provided in @log. - * - * Submits the Get Log Page command specifically for the FDP Reclaim Unit Handle - * Usage Log. The EGID is placed in the Log Specific Identifier (LSI) field. - * - * It automatically sets the Log Identifier (LID) and Retain Asynchronous - * Event (RAE) to false. This command is typically issued for the controller - * scope, thus using NVME_NSID_NONE. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_reclaim_unit_handle_usage(struct nvme_transport_handle *hdl, - __u16 egid, __u64 lpo, void *log, __u32 len) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_reclaim_unit_handle_usage(&cmd, egid, lpo, log, len); - - return nvme_get_log(hdl, &cmd, false, len); -} - -/** - * nvme_get_log_fdp_stats() - Retrieve the Flexible Data Placement (FDP) - * Statistics Log Page - * @hdl: Transport handle for the controller. - * @egid: Endurance Group Identifier (EGID) (used in LSI). - * @lpo: Offset (in bytes) into the log page data to start the retrieval. - * @log: Pointer to the buffer where the log page data will be stored. - * @len: Length of the buffer provided in @log. - * - * Submits the Get Log Page command specifically for the FDP Statistics Log. - * The EGID is placed in the Log Specific Identifier (LSI) field. - * - * It automatically sets the Log Identifier (LID) and Retain Asynchronous - * Event (RAE) to false. This command is typically issued for the controller - * scope, thus using NVME_NSID_NONE. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_fdp_stats(struct nvme_transport_handle *hdl, - __u16 egid, __u64 lpo, void *log, __u32 len) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_fdp_stats(&cmd, egid, lpo, log, len); - - return nvme_get_log(hdl, &cmd, false, len); -} - -/** - * nvme_get_log_fdp_events() - Retrieve the Flexible Data Placement (FDP) - * Events Log Page - * @hdl: Transport handle for the controller. - * @egid: Endurance Group Identifier (EGID) (used in LSI). - * @host_events:Whether to report host-initiated events (true) or - * controller-initiated events (false). - * @lpo: Offset (in bytes) into the log page data to start the retrieval. - * @log: Pointer to the buffer where the log page data will be stored. - * @len: Length of the buffer provided in @log. - * - * Submits the Get Log Page command specifically for the FDP Events Log. - * The EGID is placed in the Log Specific Identifier (LSI) field, and the - * @host_events flag is used to set the Log Specific Parameter (LSP) field. - * - * It automatically sets the Log Identifier (LID) and Retain Asynchronous - * Event (RAE) to false. This command is typically issued for the controller - * scope, thus using NVME_NSID_NONE. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_fdp_events(struct nvme_transport_handle *hdl, - __u16 egid, bool host_events, __u64 lpo, void *log, __u32 len) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_fdp_events(&cmd, egid, host_events, lpo, log, len); - - return nvme_get_log(hdl, &cmd, false, len); -} - -/** - * nvme_get_log_ana() - Retrieve the Asymmetric Namespace Access (ANA) Log Page - * @hdl: Transport handle for the controller. - * @rae: Retain asynchronous events - * @lsp: Log specific parameter, see &enum nvme_get_log_ana_lsp. - * @lpo: Offset (in bytes) into the log page data to start the retrieval. - * @log: Pointer to the buffer where the log page data will be stored. - * @len: Length of the buffer provided in @log. - * - * This log consists of a header describing the log and descriptors containing - * the ANA information for groups that contain namespaces attached to the - * controller. The @lsp parameter is placed in the Log Specific Parameter field - * of the command. - * - * See &struct nvme_ana_log for the definition of the returned structure. - * - * It automatically sets the Log Identifier (LID) to NVME_LOG_LID_ANA. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_ana(struct nvme_transport_handle *hdl, bool rae, - enum nvme_log_ana_lsp lsp, __u64 lpo, void *log, __u32 len) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_ana(&cmd, lsp, lpo, log, len); - - return nvme_get_log(hdl, &cmd, rae, len); -} - -/** - * nvme_get_log_ana_groups() - Retrieve the Asymmetric Namespace Access (ANA) - * Groups Only Log Page - * @hdl: Transport handle for the controller. - * @rae: Retain asynchronous events - * @log: Pointer to the buffer (@struct nvme_ana_log) where the log page - * data will be stored. - * @len: Length of the buffer provided in @log. - * - * This function retrieves only the ANA Group Descriptors by setting the Log - * Specific Parameter (LSP) field to NVME_LOG_ANA_LSP_RGO_GROUPS_ONLY. It is a - * convenience wrapper around nvme_get_log_ana, using a Log Page Offset (LPO) of - * 0. - * - * See &struct nvme_ana_log for the definition of the returned structure. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_ana_groups(struct nvme_transport_handle *hdl, bool rae, - struct nvme_ana_log *log, __u32 len) -{ - return nvme_get_log_ana(hdl, rae, NVME_LOG_ANA_LSP_RGO_GROUPS_ONLY, - 0, log, len); -} - -/** - * nvme_get_log_lba_status() - Retrieve the LBA Status Log Page - * @hdl: Transport handle for the controller. - * @rae: Retain asynchronous events - * @lpo: Offset (in bytes) into the log page data to start the retrieval. - * @log: Pointer to the buffer where the log page data will be stored. - * @len: Length of the buffer provided in @log. - * - * Submits the Get Log Page command specifically for the LBA Status Log. - * - * It automatically sets the Log Identifier (LID) to NVME_LOG_LID_LBA_STATUS. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_lba_status(struct nvme_transport_handle *hdl, - bool rae, __u64 lpo, void *log, __u32 len) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_lba_status(&cmd, lpo, log, len); - - return nvme_get_log(hdl, &cmd, rae, len); -} - -/** - * nvme_get_log_endurance_grp_evt() - Retrieve the Endurance Group Event - * Aggregate Log Page - * @hdl: Transport handle for the controller. - * @rae: Retain asynchronous events - * @lpo: Offset (in bytes) into the log page data to start the retrieval. - * @log: Pointer to the buffer where the log page data will be stored. - * @len: Length of the buffer provided in @log. - * - * Submits the Get Log Page command specifically for the Endurance Group Event - * Aggregate Log, allowing retrieval of data starting at a specified offset - * (@lpo). - * - * It automatically sets the Log Identifier (LID) to - * NVME_LOG_LID_ENDURANCE_GRP_EVT. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_endurance_grp_evt(struct nvme_transport_handle *hdl, - bool rae, __u64 lpo, void *log, __u32 len) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_endurance_grp_evt(&cmd, lpo, log, len); - - return nvme_get_log(hdl, &cmd, rae, len); -} - -/** - * nvme_get_log_fid_supported_effects() - Retrieve the Feature Identifiers - * Supported and Effects Log Page - * @hdl: Transport handle for the controller. - * @csi: Command set identifier, see &enum nvme_csi for known values - * @log: Pointer to the buffer (@struct nvme_fid_supported_effects_log) - * where the log page data will be stored. - * - * Submits the Get Log Page command specifically for the Feature Identifiers - * Supported and Effects Log. It automatically sets the Log Identifier (LID). - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_fid_supported_effects(struct nvme_transport_handle *hdl, - enum nvme_csi csi, struct nvme_fid_supported_effects_log *log) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_fid_supported_effects(&cmd, csi, log); - - return nvme_get_log(hdl, &cmd, false, sizeof(*log)); -} - -/** - * nvme_get_log_mi_cmd_supported_effects() - Retrieve the Management Interface - * (MI) Commands Supported and Effects Log Page - * @hdl: Transport handle for the controller. - * @log: Pointer to the buffer (@struct nvme_mi_cmd_supported_effects_log) - * where the log page data will be stored. - * - * Submits the Get Log Page command specifically for the MI Commands Supported - * and Effects Log. It automatically sets the Log Identifier (LID). This command - * is typically issued with a namespace ID of 0xFFFFFFFF (NVME_NSID_NONE). - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_mi_cmd_supported_effects(struct nvme_transport_handle *hdl, - struct nvme_mi_cmd_supported_effects_log *log) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_mi_cmd_supported_effects(&cmd, log); - - return nvme_get_log(hdl, &cmd, false, sizeof(*log)); -} - -/** - * nvme_get_log_boot_partition() - Retrieve the Boot Partition Log Page - * @hdl: Transport handle for the controller. - * @lsp: The Log Specific Parameter (LSP) field for this Log - * Identifier (LID). - * @part: Pointer to the buffer (@struct nvme_boot_partition) where the log - * page data will be stored. - * @len: Length of the buffer provided in @part. - * - * Submits the Get Log Page command specifically for the Boot Partition Log. - * The LSP field is set based on the @lsp parameter. - * - * It automatically sets the Log Identifier (LID) to - * NVME_LOG_LID_BOOT_PARTITION. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_boot_partition(struct nvme_transport_handle *hdl, - __u8 lsp, struct nvme_boot_partition *part, __u32 len) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_boot_partition(&cmd, lsp, part, len); - - return nvme_get_log(hdl, &cmd, false, len); -} - -/** - * nvme_get_log_rotational_media_info() - Retrieve the Rotational Media - * Information Log Page - * @hdl: Transport handle for the controller. - * @endgid: The Endurance Group Identifier (ENDGID) to retrieve the - * log for (used in LSI). - * @log: Pointer to the buffer (@struct nvme_rotational_media_info_log) - * where the log page data will be stored. - * @len: Length of the buffer provided in @log. - * - * Submits the Get Log Page command specifically for the Rotational Media - * Information Log. The ENDGID is placed in the Log Specific Identifier (LSI) - * field of the command. - * - * It automatically sets the Log Identifier (LID) and Retain Asynchronous - * Event (RAE) to false. This command is typically issued for the controller - * scope, thus using NVME_NSID_NONE. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_rotational_media_info(struct nvme_transport_handle *hdl, - __u16 endgid, struct nvme_rotational_media_info_log *log, - __u32 len) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_rotational_media_info(&cmd, endgid, log, len); - - return nvme_get_log(hdl, &cmd, false, len); -} - -/** - * nvme_get_log_dispersed_ns_participating_nss() - Retrieve the Dispersed - * Namespace Participating NVM Subsystems Log Page - * @hdl: Transport handle for the controller. - * @nsid: Namespace ID to request the log for. - * @log: Pointer to the buffer - * (@struct nvme_dispersed_ns_participating_nss_log) - * where the log page data will be stored. - * @len: Length of the buffer provided in @log. - * - * Submits the Get Log Page command specifically for the Dispersed Namespace - * Participating NVM Subsystems Log. It automatically sets the Log Identifier - * (LID) and Retain Asynchronous Event (RAE) to false. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_dispersed_ns_participating_nss(struct nvme_transport_handle *hdl, - __u32 nsid, struct nvme_dispersed_ns_participating_nss_log *log, - __u32 len) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_dispersed_ns_participating_nss(&cmd, nsid, log, len); - - return nvme_get_log(hdl, &cmd, false, len); -} - -/** - * nvme_get_log_mgmt_addr_list() - Retrieve the Management Address List Log Page - * @hdl: Transport handle for the controller. - * @log: Pointer to the buffer (@struct nvme_mgmt_addr_list_log) where - * the log page data will be stored. - * @len: Length of the buffer provided in @log. - * - * Submits the Get Log Page command specifically for the Management Address List Log. - * - * It automatically sets the Log Identifier (LID) to NVME_LOG_LID_MGMT_ADDR_LIST, - * Retain Asynchronous Event (RAE) to false, and uses NVME_NSID_NONE. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_mgmt_addr_list(struct nvme_transport_handle *hdl, - struct nvme_mgmt_addr_list_log *log, __u32 len) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_mgmt_addr_list(&cmd, log, len); - - return nvme_get_log(hdl, &cmd, false, len); -} - -/** - * nvme_get_log_phy_rx_eom() - Retrieve the Physical Interface Receiver Eye - * Opening Measurement Log Page - * @hdl: Transport handle for the controller. - * @lsp: Log Specific Parameter (LSP), which controls the action - * and measurement quality. - * @controller: Target Controller ID (used in LSI). - * @log: Pointer to the buffer (@struct nvme_phy_rx_eom_log) where the log - * page data will be stored. - * @len: Length of the buffer provided in @log. - * - * Submits the Get Log Page command specifically for the Physical Interface - * Receiver Eye Opening Measurement Log. The Controller ID is placed in the - * Log Specific Identifier (LSI) field. - * - * It automatically sets the Log Identifier (LID) to NVME_LOG_LID_PHY_RX_EOM, - * and Retain Asynchronous Event (RAE) to false. This command is typically - * issued for the controller scope, thus using NVME_NSID_NONE. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_phy_rx_eom(struct nvme_transport_handle *hdl, - __u8 lsp, __u16 controller, struct nvme_phy_rx_eom_log *log, - __u32 len) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_phy_rx_eom(&cmd, lsp, controller, log, len); - - return nvme_get_log(hdl, &cmd, false, len); -} - -/** - * nvme_get_log_reachability_groups() - Retrieve the Reachability Groups Log Page - * @hdl: Transport handle for the controller. - * @nsid: Namespace ID to request the log for. - * @rgo: Return Groups Only. Set to true to return only the Reachability - * Group Descriptors. - * @log: Pointer to the buffer (@struct nvme_reachability_groups_log) - * where the log page data will be stored. - * @len: Length of the buffer provided in @log. - * - * Submits the Get Log Page command specifically for the Reachability Groups Log. - * The @rgo parameter is placed in the Log Specific Parameter (LSP) field. - * - * It automatically sets the Log Identifier (LID) to - * NVME_LOG_LID_REACHABILITY_GROUPS. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_reachability_groups(struct nvme_transport_handle *hdl, - __u32 nsid, bool rgo, struct nvme_reachability_groups_log *log, - __u32 len) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_reachability_groups(&cmd, rgo, log, len); - - return nvme_get_log(hdl, &cmd, false, len); -} - -/** - * nvme_get_log_reachability_associations() - Retrieve the Reachability - * Associations Log Page - * @hdl: Transport handle for the controller. - * @rae: Retain asynchronous events - * @rao: Return Associations Only. Set to true to return only the - * Reachability Association Descriptors. - * @log: Pointer to the buffer - * (@struct nvme_reachability_associations_log) where the log - * page data will be stored. - * @len: Length of the buffer provided in @log. - * - * Submits the Get Log Page command specifically for the Reachability - * Associations Log. The @rao parameter is placed in the Log Specific Parameter - * (LSP) field. - * - * It automatically sets the Log Identifier (LID) to - * NVME_LOG_LID_REACHABILITY_ASSOCIATIONS. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_reachability_associations(struct nvme_transport_handle *hdl, - bool rae, bool rao, - struct nvme_reachability_associations_log *log, __u32 len) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_reachability_associations(&cmd, rao, log, len); - - return nvme_get_log(hdl, &cmd, rae, len); -} - -/** - * nvme_get_log_changed_alloc_ns_list() - Retrieve the Changed Allocated - * Namespace List Log Page - * @hdl: Transport handle for the controller. - * @log: Pointer to the buffer (@struct nvme_ns_list) where the log page - * data will be stored. - * @len: Length of the buffer provided in @log. - * - * Submits the Get Log Page command specifically for the Changed Allocated - * Namespace List Log. - * - * It automatically sets the Log Identifier (LID) to - * NVME_LOG_LID_CHANGED_ALLOC_NS_LIST. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_changed_alloc_ns_list(struct nvme_transport_handle *hdl, - struct nvme_ns_list *log, __u32 len) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_changed_ns(&cmd, log); - - return nvme_get_log(hdl, &cmd, true, len); -} - -/** - * nvme_get_log_discovery() - Retrieve the Discovery Log Page - * @hdl: Transport handle for the controller. - * @lpo: Offset (in bytes) into the log page data to start the retrieval. - * @log: Pointer to the buffer where the log page data will be stored. - * @len: Length of the buffer provided in @log. - * - * Submits the Get Log Page command specifically for the Discovery Log. - * Supported only by NVMe-oF Discovery controllers, returning discovery records. - * - * It automatically sets the Log Identifier (LID) to NVME_LOG_LID_DISCOVERY. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_discovery(struct nvme_transport_handle *hdl, - __u64 lpo, __u32 len, void *log) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_discovery(&cmd, lpo, log, len); - - return nvme_get_log(hdl, &cmd, false, len); -} - -/** - * nvme_get_log_host_discovery() - Retrieve the Host Discovery Log Page - * @hdl: Transport handle for the controller. - * @rae: Retain asynchronous events - * @allhoste: All Host Entries. Set to true to report all host entries. - * @log: Pointer to the buffer (@struct nvme_host_discover_log) - * where the log page data will be stored. - * @len: Length of the buffer provided in @log. - * - * Submits the Get Log Page command specifically for the Host Discovery Log. - * The @allhoste parameter is placed in the Log Specific Parameter (LSP) field. - * - * It automatically sets the Log Identifier (LID) to NVME_LOG_LID_HOST_DISCOVERY. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_host_discovery(struct nvme_transport_handle *hdl, - bool rae, bool allhoste, - struct nvme_host_discover_log *log, __u32 len) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_host_discovery(&cmd, allhoste, log, len); - - return nvme_get_log(hdl, &cmd, false, len); -} - -/** - * nvme_get_log_ave_discovery() - Retrieve the Asynchronous Event - * Group (AVE) Discovery Log Page - * @hdl: Transport handle for the controller. - * @rae: Retain asynchronous events - * @log: Pointer to the buffer (@struct nvme_ave_discover_log) where - * the log page data will be stored. - * @len: Length of the buffer provided in @log. - * - * Submits the Get Log Page command specifically for the Asynchronous Event - * Group (AVE) Discovery Log. It automatically sets the Log Identifier (LID). - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_ave_discovery(struct nvme_transport_handle *hdl, - bool rae, struct nvme_ave_discover_log *log, __u32 len) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_ave_discovery(&cmd, log, len); - - return nvme_get_log(hdl, &cmd, rae, len); -} - -/** - * nvme_get_log_pull_model_ddc_req() - Retrieve the Pull Model DDC Request - * Log Page - * @hdl: Transport handle for the controller. - * @rae: Retain asynchronous events - * @log: Pointer to the buffer (@struct nvme_pull_model_ddc_req_log) - * where the log page data will be stored. - * @len: Length of the buffer provided in @log. - * - * Submits the Get Log Page command specifically for the Pull Model DDC Request - * Log. It automatically sets the Log Identifier (LID). - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_pull_model_ddc_req(struct nvme_transport_handle *hdl, - bool rae, struct nvme_pull_model_ddc_req_log *log, __u32 len) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_pull_model_ddc_req(&cmd, log, len); - - return nvme_get_log(hdl, &cmd, rae, len); -} - -/** - * nvme_get_log_media_unit_stat() - Retrieve the Media Unit Status Log Page - * @hdl: Transport handle for the controller. - * @domid: The Domain Identifier (DOMID) selection, if supported - * (used in LSI). - * @mus: Pointer to the buffer (@struct nvme_media_unit_stat_log) - * where the log page data will be stored. - * - * Submits the Get Log Page command specifically for the Media Unit Status Log. - * The DOMID is placed in the Log Specific Identifier (LSI) field of the - * command. - * - * It automatically sets the Log Identifier (LID) to - * NVME_LOG_LID_MEDIA_UNIT_STATUS, and Retain Asynchronous Event (RAE) to false. - * This command is typically issued for the controller scope, thus using - * NVME_NSID_NONE. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_media_unit_stat(struct nvme_transport_handle *hdl, - __u16 domid, struct nvme_media_unit_stat_log *mus) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_media_unit_stat(&cmd, domid, mus); - - return nvme_get_log(hdl, &cmd, false, sizeof(*mus)); -} - -/** - * nvme_get_log_support_cap_config_list() - Retrieve the Supported Capacity - * Configuration List Log Page - * @hdl: Transport handle for the controller. - * @domid: The Domain Identifier (DOMID) selection, if - * supported (used in LSI). - * @cap: Pointer to the buffer - * (@struct nvme_supported_cap_config_list_log) where the log - * page data will be stored. - * - * Submits the Get Log Page command specifically for the Supported Capacity - * Configuration List Log. The DOMID is placed in the Log Specific Identifier - * (LSI) field of the command. - * - * It automatically sets the Log Identifier (LID) to - * NVME_LOG_LID_SUPPORTED_CAP_CONFIG_LIST, and Retain Asynchronous Event (RAE) - * to false. This command is typically issued for the controller scope, thus - * using NVME_NSID_NONE. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_support_cap_config_list(struct nvme_transport_handle *hdl, - __u16 domid, struct nvme_supported_cap_config_list_log *cap) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_support_cap_config_list(&cmd, domid, cap); - - return nvme_get_log(hdl, &cmd, false, sizeof(*cap)); -} - -/** - * nvme_get_log_reservation() - Retrieve the Reservation Notification Log Page - * @hdl: Transport handle for the controller. - * @log: Pointer to the buffer (@struct nvme_resv_notification_log) - * where the log page data will be stored. - * - * Submits the Get Log Page command specifically for the Reservation - * Notification Log. It automatically sets the Log Identifier (LID). - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_reservation(struct nvme_transport_handle *hdl, - struct nvme_resv_notification_log *log) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_reservation(&cmd, log); - - return nvme_get_log(hdl, &cmd, false, sizeof(*log)); -} - -/** - * nvme_get_log_sanitize() - Retrieve the Sanitize Status Log Page - * @hdl: Transport handle for the controller. - * @rae: Retain asynchronous events - * @log: Pointer to the buffer (@struct nvme_sanitize_log_page) - * where the log page data will be stored. - * - * Submits the Get Log Page command specifically for the Sanitize Status Log. - * The log page reports sanitize operation time estimates and information about - * the most recent sanitize operation. - * - * It automatically sets the Log Identifier (LID) to NVME_LOG_LID_SANITIZE. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_sanitize(struct nvme_transport_handle *hdl, - bool rae, struct nvme_sanitize_log_page *log) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_sanitize(&cmd, log); - - return nvme_get_log(hdl, &cmd, rae, sizeof(*log)); -} - -/** - * nvme_get_log_zns_changed_zones() - Retrieve the ZNS Changed Zones Log Page - * @hdl: Transport handle for the controller. - * @nsid: Namespace ID to request the log for. - * @rae: Retain asynchronous events - * @log: Pointer to the buffer (@struct nvme_zns_changed_zone_log) - * where the log page data will be stored. - * - * Submits the Get Log Page command specifically for the ZNS Changed Zones Log. - * This log lists zones that have changed state due to an exceptional event. - * - * It automatically sets the Log Identifier (LID) to - * NVME_LOG_LID_ZNS_CHANGED_ZONES. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_zns_changed_zones(struct nvme_transport_handle *hdl, - __u32 nsid, bool rae, struct nvme_zns_changed_zone_log *log) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_zns_changed_zones(&cmd, nsid, log); - - return nvme_get_log(hdl, &cmd, rae, sizeof(*log)); -} - -/** - * nvme_get_log_persistent_event() - Retrieve the Persistent Event Log Page - * @hdl: Transport handle for the controller. - * @action: Action the controller should take during processing this - * command, see &enum nvme_pevent_log_action (used in LSP). - * @pevent_log: Pointer to the buffer where the log page data will be stored. - * @len: Length of the buffer provided in @pevent_log. - * - * Submits the Get Log Page command specifically for the Persistent Event Log. - * The @action parameter is placed in the Log Specific Parameter (LSP) field. - * - * It automatically sets the Log Identifier (LID) to - * NVME_LOG_LID_PERSISTENT_EVENT and Retain Asynchronous Event (RAE) to false. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_persistent_event(struct nvme_transport_handle *hdl, - enum nvme_pevent_log_action action, void *pevent_log, __u32 len) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_persistent_event(&cmd, action, pevent_log, len); - - /* - * Call the generic log execution function. - * The data length is determined by the 'len' parameter. - */ - return nvme_get_log(hdl, &cmd, false, len); -} - -/** - * nvme_get_log_lockdown() - Retrieve the Command and Feature Lockdown Log Page - * @hdl: Transport handle for the controller. - * @cnscp: Contents and Scope (CNSCP) of Command and Feature - * Identifier Lists (used in LSP). - * @log: Pointer to the buffer (@struct nvme_lockdown_log) where the log - * page data will be stored. - * - * Submits the Get Log Page command specifically for the Command and Feature - * Lockdown Log. The @cnscp parameter is placed in the Log Specific Parameter - * (LSP) field. - * - * It automatically sets the Log Identifier (LID) to - * NVME_LOG_LID_CMD_AND_FEAT_LOCKDOWN and Retain Asynchronous Event (RAE) to - * false. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_lockdown(struct nvme_transport_handle *hdl, - __u8 cnscp, struct nvme_lockdown_log *log) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_lockdown(&cmd, cnscp, log); - - return nvme_get_log(hdl, &cmd, false, sizeof(*log)); -} - -/** - * nvme_get_log_smart() - Retrieve the SMART / Health Information Log Page - * @hdl: Transport handle for the controller. - * @nsid: Namespace ID to request the log for. - * @smart_log: Pointer to the buffer (@struct nvme_smart_log) where the log - * page data will be stored. - * - * Submits the Get Log Page command specifically for the SMART / Health - * Information Log. It automatically sets the Log Identifier (LID) and - * Retain Asynchronous Event (RAE) to false. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_log_smart(struct nvme_transport_handle *hdl, - __u32 nsid, struct nvme_smart_log *smart_log) -{ - struct nvme_passthru_cmd cmd; - - nvme_init_get_log_smart(&cmd, nsid, smart_log); - - return nvme_get_log(hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE); -} - -/** - * nvme_set_features() - Submit a generic Set Features command - * @hdl: Transport handle for the controller. - * @nsid: Namespace ID sto apply the feature to. - * @fid: Feature Identifier (FID) to be set. - * @sv: Save Value (SV): If true, the feature value persists - * across power states. - * @cdw11: Command Dword 11 parameter (feature-specific). - * @cdw12: Command Dword 12 parameter (feature-specific). - * @cdw13: Command Dword 13 parameter (feature-specific). - * @uidx: UUID Index (UIDX) for the command, encoded into cdw14 - * @cdw15: Command Dword 15 parameter (feature-specific). - * @data: Pointer to the data buffer to transfer (if applicable). - * @len: Length of the data buffer in bytes. - * @result: The command completion result (CQE dword0) on success. - * - * Submits the Set Features command, allowing all standard command - * fields (cdw11-cdw15) and data buffer fields to be specified directly. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_set_features(struct nvme_transport_handle *hdl, __u32 nsid, __u8 fid, - bool sv, __u32 cdw11, __u32 cdw12, __u32 cdw13, __u8 uidx, - __u32 cdw15, void *data, __u32 len, __u64 *result) -{ - struct nvme_passthru_cmd cmd; - int err; - - nvme_init_set_features(&cmd, fid, sv); - cmd.nsid = nsid; - cmd.cdw11 = cdw11; - cmd.cdw12 = cdw12; - cmd.cdw13 = cdw13; - cmd.cdw14 = NVME_FIELD_ENCODE(uidx, - NVME_SET_FEATURES_CDW14_UUID_SHIFT, - NVME_SET_FEATURES_CDW14_UUID_MASK); - cmd.cdw15 = cdw15; - cmd.data_len = len; - cmd.addr = (__u64)(uintptr_t)data; - - err = nvme_submit_admin_passthru(hdl, &cmd); - if (result) - *result = cmd.result; - return err; -} - -/** - * nvme_set_features_simple() - Submit a Set Features command using only cdw11 - * @hdl: Transport handle for the controller. - * @nsid: Namespace ID to apply the feature to. - * @fid: Feature Identifier (FID) to be set. - * @sv: Save Value (SV): If true, the feature value persists across - * power states. - * @cdw11: Command Dword 11 parameter (feature-specific value). - * @result: The command completion result (CQE dword0) on success. - * - * Submits the Set Features command for features that only require - * parameters in cdw11. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_set_features_simple(struct nvme_transport_handle *hdl, - __u32 nsid, __u8 fid, bool sv, __u32 cdw11, __u64 *result) -{ - struct nvme_passthru_cmd cmd; - int err; - - nvme_init_set_features(&cmd, fid, sv); - cmd.nsid = nsid; - cmd.cdw11 = cdw11; - - err = nvme_submit_admin_passthru(hdl, &cmd); - if (result) - *result = cmd.result; - return err; -} - -/** - * nvme_get_features() - Submit a Get Features command - * @hdl: Transport handle for the controller. - * @nsid: Namespace ID, if applicable - * @fid: Feature identifier, see &enum nvme_features_id - * @sel: Select which type of attribute to return, - * see &enum nvme_get_features_sel - * @cdw11: Feature specific command dword11 field - * @uidx: UUID Index for differentiating vendor specific encoding - * @data: User address of feature data, if applicable - * @len: Length of feature data, if applicable, in bytes - * @result: The command completion result (CQE dword0) on success. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_features(struct nvme_transport_handle *hdl, __u32 nsid, - __u8 fid, enum nvme_get_features_sel sel, - __u32 cdw11, __u8 uidx, void *data, - __u32 len, __u64 *result) -{ - struct nvme_passthru_cmd cmd; - int err; - - nvme_init_get_features(&cmd, fid, sel); - - cmd.nsid = nsid; - cmd.cdw11 = cdw11; - cmd.cdw14 = NVME_FIELD_ENCODE(uidx, - NVME_GET_FEATURES_CDW14_UUID_SHIFT, - NVME_GET_FEATURES_CDW14_UUID_MASK); - cmd.data_len = len; - cmd.addr = (__u64)(uintptr_t)data; - - err = nvme_submit_admin_passthru(hdl, &cmd); - if (result) - *result = cmd.result; - return err; -} - -/** - * nvme_get_features_simple() - Submit a simple Get Features command - * @hdl: Transport handle for the controller. - * @fid: Feature Identifier (FID) to be retrieved. - * @sel: Select (SEL), specifying which feature value - * to return (&struct nvme_get_features_sel). - * @result: The command completion result (CQE dword0) on success. - * - * Submits the Get Features command for features that only require parameters in - * the CQE dword0 and do not need any parameters in cdw11 through cdw15. - * - * Return: 0 on success, the NVMe command status on error, or a negative - * errno otherwise. - */ -static inline int -nvme_get_features_simple(struct nvme_transport_handle *hdl, __u8 fid, - enum nvme_get_features_sel sel, __u64 *result) -{ - struct nvme_passthru_cmd cmd; - int err; - - nvme_init_get_features(&cmd, fid, sel); - - err = nvme_submit_admin_passthru(hdl, &cmd); - if (result) - *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 7ee594a8c4..61ab8e5b73 100644 --- a/libnvme/src/nvme/linux.c +++ b/libnvme/src/nvme/linux.c @@ -17,6 +17,8 @@ #include #include +#include + #ifdef CONFIG_OPENSSL #include #include diff --git a/libnvme/src/nvme/mi-mctp.c b/libnvme/src/nvme/mi-mctp.c index 3553a3f1d9..4318676813 100644 --- a/libnvme/src/nvme/mi-mctp.c +++ b/libnvme/src/nvme/mi-mctp.c @@ -17,6 +17,7 @@ #include #include #include +#include #if HAVE_LINUX_MCTP_H #include diff --git a/libnvme/test/mi-mctp.c b/libnvme/test/mi-mctp.c index 87fade097a..1bd280bbd5 100644 --- a/libnvme/test/mi-mctp.c +++ b/libnvme/test/mi-mctp.c @@ -13,7 +13,7 @@ #include #include #include - +#include #include #include diff --git a/nvme.c b/nvme.c index dbd62fc14a..02d1af78eb 100644 --- a/nvme.c +++ b/nvme.c @@ -47,6 +47,7 @@ #include #include #include +#include #if HAVE_SYS_RANDOM #include diff --git a/plugins/scaleflux/sfx-nvme.c b/plugins/scaleflux/sfx-nvme.c index 2635e02fea..e4b35150c4 100644 --- a/plugins/scaleflux/sfx-nvme.c +++ b/plugins/scaleflux/sfx-nvme.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include From 94a0cab9f304f5ad5ed16bde4f51b125d92a56ad Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Tue, 3 Mar 2026 12:05:07 +0100 Subject: [PATCH 10/29] build: sort install_headers alphabetically Sort the install_headers list alphabetically to match the convention. Signed-off-by: Daniel Wagner --- libnvme/src/meson.build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libnvme/src/meson.build b/libnvme/src/meson.build index 25a5f1fd31..a3695ff45c 100644 --- a/libnvme/src/meson.build +++ b/libnvme/src/meson.build @@ -96,17 +96,17 @@ install_headers( ) install_headers( [ + 'nvme/cmds.h', 'nvme/fabrics.h', 'nvme/filters.h', 'nvme/ioctl.h', 'nvme/linux.h', - 'nvme/cmds.h', 'nvme/log.h', + 'nvme/mi.h', 'nvme/nbft.h', 'nvme/tree.h', 'nvme/types.h', 'nvme/util.h', - 'nvme/mi.h', ], subdir: 'nvme', install_mode: mode, From fe92102beddba672fd84f765d757092f019af2a8 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Tue, 3 Mar 2026 13:58:38 +0100 Subject: [PATCH 11/29] cmds: move nvme commands to cmds header These function/helpers are nvme commands and are not Linux specific. Signed-off-by: Daniel Wagner --- libnvme/src/meson.build | 1 + libnvme/src/nvme/cmds.c | 414 +++++++++++++++++++++++++++++++++++++++ libnvme/src/nvme/cmds.h | 206 +++++++++++++++++++ libnvme/src/nvme/linux.c | 382 ------------------------------------ libnvme/src/nvme/linux.h | 198 ------------------- libnvme/test/meson.build | 1 + 6 files changed, 622 insertions(+), 580 deletions(-) create mode 100644 libnvme/src/nvme/cmds.c diff --git a/libnvme/src/meson.build b/libnvme/src/meson.build index a3695ff45c..b63b4c67ec 100644 --- a/libnvme/src/meson.build +++ b/libnvme/src/meson.build @@ -7,6 +7,7 @@ # sources = [ 'nvme/base64.c', + 'nvme/cmds.c', 'nvme/crc32.c', 'nvme/fabrics.c', 'nvme/filters.c', diff --git a/libnvme/src/nvme/cmds.c b/libnvme/src/nvme/cmds.c new file mode 100644 index 0000000000..11ed15bd45 --- /dev/null +++ b/libnvme/src/nvme/cmds.c @@ -0,0 +1,414 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/* + * This file is part of libnvme. + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + * + * Authors: Keith Busch + * Chaitanya Kulkarni + */ + +#include +#include + +#include + +#include "cleanup.h" +#include "private.h" + +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) + break; + err = nvme_submit_admin_passthru(hdl, &cmd); + if (err) + break; + + data += xfer; + size -= xfer; + offset += xfer; + } + + return err; +} + +int nvme_set_etdas(struct nvme_transport_handle *hdl, bool *changed) +{ + struct nvme_feat_host_behavior da4; + struct nvme_passthru_cmd cmd; + int err; + + nvme_init_get_features_host_behavior(&cmd, 0, &da4); + err = nvme_submit_admin_passthru(hdl, &cmd); + if (err) + return err; + + if (da4.etdas) { + *changed = false; + return 0; + } + + da4.etdas = 1; + + nvme_init_set_features_host_behavior(&cmd, false, &da4); + err = nvme_submit_admin_passthru(hdl, &cmd); + if (err) + return err; + + *changed = true; + return 0; +} + +int nvme_clear_etdas(struct nvme_transport_handle *hdl, bool *changed) +{ + struct nvme_feat_host_behavior da4; + struct nvme_passthru_cmd cmd; + int err; + + nvme_init_get_features_host_behavior(&cmd, 0, &da4); + err = nvme_submit_admin_passthru(hdl, &cmd); + if (err) + return err; + + if (!da4.etdas) { + *changed = false; + return 0; + } + + da4.etdas = 0; + nvme_init_set_features_host_behavior(&cmd, false, &da4); + err = nvme_submit_admin_passthru(hdl, &cmd); + if (err) + return err; + + *changed = true; + return 0; +} + +int nvme_get_uuid_list(struct nvme_transport_handle *hdl, + struct nvme_id_uuid_list *uuid_list) +{ + struct nvme_passthru_cmd cmd; + struct nvme_id_ctrl ctrl; + int err; + + memset(&ctrl, 0, sizeof(struct nvme_id_ctrl)); + nvme_init_identify_ctrl(&cmd, &ctrl); + err = nvme_submit_admin_passthru(hdl, &cmd); + if (err) { + nvme_msg(hdl->ctx, LOG_ERR, + "ERROR: nvme_identify_ctrl() failed 0x%x\n", err); + return err; + } + + if ((ctrl.ctratt & NVME_CTRL_CTRATT_UUID_LIST) == + NVME_CTRL_CTRATT_UUID_LIST) { + nvme_init_identify_uuid_list(&cmd, uuid_list); + err = nvme_submit_admin_passthru(hdl, &cmd); + } + + return err; +} + +int nvme_get_telemetry_max(struct nvme_transport_handle *hdl, + enum nvme_telemetry_da *da, size_t *data_tx) +{ + struct nvme_id_ctrl *id_ctrl = NULL; + struct nvme_passthru_cmd cmd; + int err; + + id_ctrl = __nvme_alloc(sizeof(*id_ctrl)); + if (!id_ctrl) + return -ENOMEM; + + nvme_init_identify_ctrl(&cmd, id_ctrl); + err = nvme_submit_admin_passthru(hdl, &cmd); + if (err) + return err; + + if (data_tx) { + *data_tx = id_ctrl->mdts; + if (id_ctrl->mdts) { + /* + * assuming CAP.MPSMIN is zero minimum Memory Page Size + * is at least 4096 bytes + */ + *data_tx = (1 << id_ctrl->mdts) * 4096; + } + } + if (da) { + if (id_ctrl->lpa & 0x8) + *da = NVME_TELEMETRY_DA_3; + if (id_ctrl->lpa & 0x40) + *da = NVME_TELEMETRY_DA_4; + + } + return err; +} + +int nvme_get_telemetry_log(struct nvme_transport_handle *hdl, bool create, + bool ctrl, bool rae, size_t max_data_tx, + enum nvme_telemetry_da da, struct nvme_telemetry_log **buf, + size_t *size) +{ + static const __u32 xfer = NVME_LOG_TELEM_BLOCK_SIZE; + struct nvme_telemetry_log *telem; + struct nvme_passthru_cmd cmd; + _cleanup_free_ void *log = NULL; + void *tmp; + int err; + size_t dalb; + + *size = 0; + + log = __nvme_alloc(xfer); + if (!log) + return -ENOMEM; + + if (ctrl) { + nvme_init_get_log_telemetry_ctrl(&cmd, 0, log, xfer); + err = nvme_get_log(hdl, &cmd, true, xfer); + } else { + if (create) { + nvme_init_get_log_create_telemetry_host_mcda(&cmd, + da, log); + err = nvme_get_log(hdl, &cmd, false, xfer); + } else { + nvme_init_get_log_telemetry_host(&cmd, 0, log, xfer); + err = nvme_get_log(hdl, &cmd, false, xfer); + } + } + + if (err) + return err; + + telem = log; + if (ctrl && !telem->ctrlavail) { + *buf = log; + log = NULL; + *size = xfer; + return 0; + } + + switch (da) { + case NVME_TELEMETRY_DA_1: + dalb = le16_to_cpu(telem->dalb1); + break; + case NVME_TELEMETRY_DA_2: + dalb = le16_to_cpu(telem->dalb2); + break; + case NVME_TELEMETRY_DA_3: + /* dalb3 >= dalb2 >= dalb1 */ + dalb = le16_to_cpu(telem->dalb3); + break; + case NVME_TELEMETRY_DA_4: + dalb = le32_to_cpu(telem->dalb4); + break; + default: + return -EINVAL; + } + + if (dalb == 0) + return -ENOENT; + + *size = (dalb + 1) * xfer; + tmp = __nvme_realloc(log, *size); + if (!tmp) + return -ENOMEM; + log = tmp; + + if (ctrl) + nvme_init_get_log_telemetry_ctrl(&cmd, 0, log, *size); + else + nvme_init_get_log_telemetry_host(&cmd, 0, log, *size); + err = nvme_get_log(hdl, &cmd, rae, max_data_tx); + if (err) + return err; + + *buf = log; + log = NULL; + return 0; +} + + +static int nvme_check_get_telemetry_log(struct nvme_transport_handle *hdl, + bool create, bool ctrl, bool rae, + struct nvme_telemetry_log **log, enum nvme_telemetry_da da, + size_t *size) +{ + enum nvme_telemetry_da max_da = 0; + int err; + + err = nvme_get_telemetry_max(hdl, &max_da, NULL); + if (err) + return err; + + if (da > max_da) + return -ENOENT; + + return nvme_get_telemetry_log(hdl, create, ctrl, rae, 4096, da, + log, size); +} + + +int nvme_get_ctrl_telemetry(struct nvme_transport_handle *hdl, bool rae, + struct nvme_telemetry_log **log, + enum nvme_telemetry_da da, size_t *size) +{ + return nvme_check_get_telemetry_log(hdl, false, true, rae, log, + da, size); +} + +int nvme_get_host_telemetry(struct nvme_transport_handle *hdl, + struct nvme_telemetry_log **log, + enum nvme_telemetry_da da, size_t *size) +{ + return nvme_check_get_telemetry_log(hdl, false, false, false, log, + da, size); +} + +int nvme_get_new_host_telemetry(struct nvme_transport_handle *hdl, + struct nvme_telemetry_log **log, + enum nvme_telemetry_da da, size_t *size) +{ + return nvme_check_get_telemetry_log(hdl, true, false, false, log, + da, size); +} + +int nvme_get_lba_status_log(struct nvme_transport_handle *hdl, bool rae, + struct nvme_lba_status_log **log) +{ + _cleanup_free_ struct nvme_lba_status_log *buf = NULL; + struct nvme_passthru_cmd cmd; + __u32 size; + void *tmp; + int err; + + buf = malloc(sizeof(*buf)); + if (!buf) + return -ENOMEM; + + nvme_init_get_log_lba_status(&cmd, 0, log, sizeof(*buf)); + err = nvme_get_log(hdl, &cmd, true, sizeof(*buf)); + if (err) { + *log = NULL; + return err; + } + + size = le32_to_cpu(buf->lslplen); + if (!size) { + *log = buf; + buf = NULL; + return 0; + } + + tmp = realloc(buf, size); + if (!tmp) { + *log = NULL; + return -ENOMEM; + } + buf = tmp; + + nvme_init_get_log_lba_status(&cmd, 0, buf, size); + err = nvme_get_log(hdl, &cmd, rae, NVME_LOG_PAGE_PDU_SIZE); + if (err) { + *log = NULL; + return err; + } + + *log = buf; + buf = NULL; + return 0; +} + +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 + nvme_init_ns_detach_ctrls(&cmd, nsid, &cntlist); + + return nvme_submit_admin_passthru(hdl, &cmd); +} + +int nvme_namespace_attach_ctrls(struct nvme_transport_handle *hdl, bool ish, + __u32 nsid, __u16 num_ctrls, __u16 *ctrlist) +{ + return nvme_ns_attachment(hdl, ish, nsid, num_ctrls, ctrlist, true); +} + +int nvme_namespace_detach_ctrls(struct nvme_transport_handle *hdl, bool ish, + __u32 nsid, __u16 num_ctrls, __u16 *ctrlist) +{ + 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, + bool rgo) +{ + __u32 nanagrpid = le32_to_cpu(id_ctrl->nanagrpid); + size_t size = sizeof(struct nvme_ana_log) + + nanagrpid * sizeof(struct nvme_ana_group_desc); + + return rgo ? size : size + le32_to_cpu(id_ctrl->mnan) * sizeof(__le32); +} + +int nvme_get_ana_log_len(struct nvme_transport_handle *hdl, size_t *analen) +{ + _cleanup_free_ struct nvme_id_ctrl *ctrl = NULL; + struct nvme_passthru_cmd cmd; + int ret; + + ctrl = __nvme_alloc(sizeof(*ctrl)); + if (!ctrl) + return -ENOMEM; + + nvme_init_identify_ctrl(&cmd, ctrl); + ret = nvme_submit_admin_passthru(hdl, &cmd); + if (ret) + return ret; + + *analen = nvme_get_ana_log_len_from_id_ctrl(ctrl, false); + return 0; +} + +int nvme_get_logical_block_size(struct nvme_transport_handle *hdl, + __u32 nsid, int *blksize) +{ + _cleanup_free_ struct nvme_id_ns *ns = NULL; + struct nvme_passthru_cmd cmd; + __u8 flbas; + int ret; + + ns = __nvme_alloc(sizeof(*ns)); + if (!ns) + return -ENOMEM; + + nvme_init_identify_ns(&cmd, nsid, ns); + ret = nvme_submit_admin_passthru(hdl, &cmd); + if (ret) + return ret; + + nvme_id_ns_flbas_to_lbaf_inuse(ns->flbas, &flbas); + *blksize = 1 << ns->lbaf[flbas].ds; + + return 0; +} diff --git a/libnvme/src/nvme/cmds.h b/libnvme/src/nvme/cmds.h index 28a29200a1..bde7b52868 100644 --- a/libnvme/src/nvme/cmds.h +++ b/libnvme/src/nvme/cmds.h @@ -6909,3 +6909,209 @@ nvme_init_mi_cmd_flags(struct nvme_passthru_cmd *cmd, bool ish) NVME_MI_ADMIN_CFLAGS_ISH_MASK); } +/** + * 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 + * @buf: Address of buffer containing all or part of the firmware image. + * + * 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, bool ish, + __u32 size, __u32 xfer, __u32 offset, void *buf); + +/** + * nvme_set_etdas() - Set the Extended Telemetry Data Area 4 Supported bit + * @hdl: Transport handle + * @changed: boolean to indicate whether or not the host + * behavior support feature had been changed + * + * Return: The nvme command status if a response was received (see + * &enum nvme_status_field) or -1 with errno set otherwise. + */ +int nvme_set_etdas(struct nvme_transport_handle *hdl, bool *changed); + +/** + * nvme_clear_etdas() - Clear the Extended Telemetry Data Area 4 Supported bit + * @hdl: Transport handle + * @changed: boolean to indicate whether or not the host + * behavior support feature had been changed + * + * Return: The nvme command status if a response was received (see + * &enum nvme_status_field) or -1 with errno set otherwise. + */ +int nvme_clear_etdas(struct nvme_transport_handle *hdl, bool *changed); + +/** + * nvme_get_uuid_list - Returns the uuid list (if supported) + * @hdl: Transport handle + * @uuid_list: UUID list returned by identify UUID + * + * Return: The nvme command status if a response was received (see + * &enum nvme_status_field) or -1 with errno set otherwise. + */ +int nvme_get_uuid_list(struct nvme_transport_handle *hdl, + struct nvme_id_uuid_list *uuid_list); + +/** + * nvme_get_telemetry_max() - Get telemetry limits + * @hdl: Transport handle + * @da: On success return max supported data area + * @max_data_tx: On success set to max transfer chunk supported by + * the controller + * + * 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_get_telemetry_max(struct nvme_transport_handle *hdl, + enum nvme_telemetry_da *da, size_t *max_data_tx); + +/** + * nvme_get_telemetry_log() - Get specified telemetry log + * @hdl: Transport handle + * @create: Generate new host initated telemetry capture + * @ctrl: Get controller Initiated log + * @rae: Retain asynchronous events + * @max_data_tx: Set the max data transfer size to be used retrieving telemetry. + * @da: Log page data area, valid values: &enum nvme_telemetry_da. + * @log: On success, set to the value of the allocated and retrieved log. + * @size: Ptr to the telemetry log size, so it can be returned + * + * The total size allocated can be calculated as: + * (nvme_telemetry_log da size + 1) * NVME_LOG_TELEM_BLOCK_SIZE. + * + * 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_get_telemetry_log(struct nvme_transport_handle *hdl, bool create, + bool ctrl, bool rae, size_t max_data_tx, + enum nvme_telemetry_da da, struct nvme_telemetry_log **log, + size_t *size); + +/** + * nvme_get_ctrl_telemetry() - Get controller telemetry log + * @hdl: Transport handle + * @rae: Retain asynchronous events + * @log: On success, set to the value of the allocated and retrieved log. + * @da: Log page data area, valid values: &enum nvme_telemetry_da + * @size: Ptr to the telemetry log size, so it can be returned + * + * The total size allocated can be calculated as: + * (nvme_telemetry_log da size + 1) * NVME_LOG_TELEM_BLOCK_SIZE. + * + * 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_get_ctrl_telemetry(struct nvme_transport_handle *hdl, bool rae, + struct nvme_telemetry_log **log, + enum nvme_telemetry_da da, size_t *size); + +/** + * nvme_get_host_telemetry() - Get host telemetry log + * @hdl: Transport handle + * @log: On success, set to the value of the allocated and retrieved log. + * @da: Log page data area, valid values: &enum nvme_telemetry_da + * @size: Ptr to the telemetry log size, so it can be returned + * + * The total size allocated can be calculated as: + * (nvme_telemetry_log da size + 1) * NVME_LOG_TELEM_BLOCK_SIZE. + * + * 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_get_host_telemetry(struct nvme_transport_handle *hdl, + struct nvme_telemetry_log **log, + enum nvme_telemetry_da da, size_t *size); + +/** + * nvme_get_new_host_telemetry() - Get new host telemetry log + * @hdl: Transport handle + * @log: On success, set to the value of the allocated and retrieved log. + * @da: Log page data area, valid values: &enum nvme_telemetry_da + * @size: Ptr to the telemetry log size, so it can be returned + * + * The total size allocated can be calculated as: + * (nvme_telemetry_log da size + 1) * NVME_LOG_TELEM_BLOCK_SIZE. + * + * 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_get_new_host_telemetry(struct nvme_transport_handle *hdl, + struct nvme_telemetry_log **log, + enum nvme_telemetry_da da, size_t *size); + +/** + * nvme_get_ana_log_len_from_id_ctrl() - Retrieve maximum possible ANA log size + * @id_ctrl: Controller identify data + * @rgo: If true, return maximum log page size without NSIDs + * + * Return: A byte limit on the size of the controller's ANA log page + */ +size_t nvme_get_ana_log_len_from_id_ctrl(const struct nvme_id_ctrl *id_ctrl, + bool rgo); + +/** + * nvme_get_ana_log_len() - Retrieve size of the current ANA log + * @hdl: Transport handle + * @analen: Pointer to where the length will be set on success + * + * 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_get_ana_log_len(struct nvme_transport_handle *hdl, size_t *analen); + +/** + * nvme_get_logical_block_size() - Retrieve block size + * @hdl: Transport handle + * @nsid: Namespace id + * @blksize: Pointer to where the block size will be set on success + * + * 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_get_logical_block_size(struct nvme_transport_handle *hdl, __u32 nsid, + int *blksize); + +/** + * nvme_get_lba_status_log() - Retrieve the LBA Status log page + * @hdl: Transport handle + * @rae: Retain asynchronous events + * @log: On success, set to the value of the allocated and retrieved log. + * + * 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_get_lba_status_log(struct nvme_transport_handle *hdl, bool rae, + struct nvme_lba_status_log **log); + +/** + * 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 + * + * 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, 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 + * + * 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, bool ish, + __u32 nsid, __u16 num_ctrls, __u16 *ctrlist); diff --git a/libnvme/src/nvme/linux.c b/libnvme/src/nvme/linux.c index 61ab8e5b73..7059d701c4 100644 --- a/libnvme/src/nvme/linux.c +++ b/libnvme/src/nvme/linux.c @@ -238,388 +238,6 @@ 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, 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) - break; - err = nvme_submit_admin_passthru(hdl, &cmd); - if (err) - break; - - data += xfer; - size -= xfer; - offset += xfer; - } - - return err; -} - -int nvme_set_etdas(struct nvme_transport_handle *hdl, bool *changed) -{ - struct nvme_feat_host_behavior da4; - struct nvme_passthru_cmd cmd; - int err; - - nvme_init_get_features_host_behavior(&cmd, 0, &da4); - err = nvme_submit_admin_passthru(hdl, &cmd); - if (err) - return err; - - if (da4.etdas) { - *changed = false; - return 0; - } - - da4.etdas = 1; - - nvme_init_set_features_host_behavior(&cmd, false, &da4); - err = nvme_submit_admin_passthru(hdl, &cmd); - if (err) - return err; - - *changed = true; - return 0; -} - -int nvme_clear_etdas(struct nvme_transport_handle *hdl, bool *changed) -{ - struct nvme_feat_host_behavior da4; - struct nvme_passthru_cmd cmd; - int err; - - nvme_init_get_features_host_behavior(&cmd, 0, &da4); - err = nvme_submit_admin_passthru(hdl, &cmd); - if (err) - return err; - - if (!da4.etdas) { - *changed = false; - return 0; - } - - da4.etdas = 0; - nvme_init_set_features_host_behavior(&cmd, false, &da4); - err = nvme_submit_admin_passthru(hdl, &cmd); - if (err) - return err; - - *changed = true; - return 0; -} - -int nvme_get_uuid_list(struct nvme_transport_handle *hdl, struct nvme_id_uuid_list *uuid_list) -{ - struct nvme_passthru_cmd cmd; - struct nvme_id_ctrl ctrl; - int err; - - memset(&ctrl, 0, sizeof(struct nvme_id_ctrl)); - nvme_init_identify_ctrl(&cmd, &ctrl); - err = nvme_submit_admin_passthru(hdl, &cmd); - if (err) { - nvme_msg(hdl->ctx, LOG_ERR, - "ERROR: nvme_identify_ctrl() failed 0x%x\n", err); - return err; - } - - if ((ctrl.ctratt & NVME_CTRL_CTRATT_UUID_LIST) == NVME_CTRL_CTRATT_UUID_LIST) { - nvme_init_identify_uuid_list(&cmd, uuid_list); - err = nvme_submit_admin_passthru(hdl, &cmd); - } - - return err; -} - -int nvme_get_telemetry_max(struct nvme_transport_handle *hdl, enum nvme_telemetry_da *da, size_t *data_tx) -{ - struct nvme_id_ctrl *id_ctrl = NULL; - struct nvme_passthru_cmd cmd; - int err; - - id_ctrl = __nvme_alloc(sizeof(*id_ctrl)); - if (!id_ctrl) - return -ENOMEM; - - nvme_init_identify_ctrl(&cmd, id_ctrl); - err = nvme_submit_admin_passthru(hdl, &cmd); - if (err) - return err; - - if (data_tx) { - *data_tx = id_ctrl->mdts; - if (id_ctrl->mdts) { - /* assuming CAP.MPSMIN is zero minimum Memory Page Size is at least - * 4096 bytes - */ - *data_tx = (1 << id_ctrl->mdts) * 4096; - } - } - if (da) { - if (id_ctrl->lpa & 0x8) - *da = NVME_TELEMETRY_DA_3; - if (id_ctrl->lpa & 0x40) - *da = NVME_TELEMETRY_DA_4; - - } - return err; -} - -int nvme_get_telemetry_log(struct nvme_transport_handle *hdl, bool create, bool ctrl, bool rae, size_t max_data_tx, - enum nvme_telemetry_da da, struct nvme_telemetry_log **buf, - size_t *size) -{ - static const __u32 xfer = NVME_LOG_TELEM_BLOCK_SIZE; - struct nvme_telemetry_log *telem; - struct nvme_passthru_cmd cmd; - _cleanup_free_ void *log = NULL; - void *tmp; - int err; - size_t dalb; - - *size = 0; - - log = __nvme_alloc(xfer); - if (!log) - return -ENOMEM; - - if (ctrl) { - nvme_init_get_log_telemetry_ctrl(&cmd, 0, log, xfer); - err = nvme_get_log(hdl, &cmd, true, xfer); - } else { - if (create) { - nvme_init_get_log_create_telemetry_host_mcda(&cmd, da, log); - err = nvme_get_log(hdl, &cmd, false, xfer); - } else { - nvme_init_get_log_telemetry_host(&cmd, 0, log, xfer); - err = nvme_get_log(hdl, &cmd, false, xfer); - } - } - - if (err) - return err; - - telem = log; - if (ctrl && !telem->ctrlavail) { - *buf = log; - log = NULL; - *size = xfer; - return 0; - } - - switch (da) { - case NVME_TELEMETRY_DA_1: - dalb = le16_to_cpu(telem->dalb1); - break; - case NVME_TELEMETRY_DA_2: - dalb = le16_to_cpu(telem->dalb2); - break; - case NVME_TELEMETRY_DA_3: - /* dalb3 >= dalb2 >= dalb1 */ - dalb = le16_to_cpu(telem->dalb3); - break; - case NVME_TELEMETRY_DA_4: - dalb = le32_to_cpu(telem->dalb4); - break; - default: - return -EINVAL; - } - - if (dalb == 0) - return -ENOENT; - - *size = (dalb + 1) * xfer; - tmp = __nvme_realloc(log, *size); - if (!tmp) - return -ENOMEM; - log = tmp; - - if (ctrl) - nvme_init_get_log_telemetry_ctrl(&cmd, 0, log, *size); - else - nvme_init_get_log_telemetry_host(&cmd, 0, log, *size); - err = nvme_get_log(hdl, &cmd, rae, max_data_tx); - if (err) - return err; - - *buf = log; - log = NULL; - return 0; -} - - -static int nvme_check_get_telemetry_log(struct nvme_transport_handle *hdl, bool create, bool ctrl, bool rae, - struct nvme_telemetry_log **log, enum nvme_telemetry_da da, - size_t *size) -{ - enum nvme_telemetry_da max_da = 0; - int err; - - err = nvme_get_telemetry_max(hdl, &max_da, NULL); - if (err) - return err; - - if (da > max_da) - return -ENOENT; - - return nvme_get_telemetry_log(hdl, create, ctrl, rae, 4096, da, log, size); -} - - -int nvme_get_ctrl_telemetry(struct nvme_transport_handle *hdl, bool rae, struct nvme_telemetry_log **log, - enum nvme_telemetry_da da, size_t *size) -{ - return nvme_check_get_telemetry_log(hdl, false, true, rae, log, da, size); -} - -int nvme_get_host_telemetry(struct nvme_transport_handle *hdl, struct nvme_telemetry_log **log, - enum nvme_telemetry_da da, size_t *size) -{ - return nvme_check_get_telemetry_log(hdl, false, false, false, log, da, size); -} - -int nvme_get_new_host_telemetry(struct nvme_transport_handle *hdl, struct nvme_telemetry_log **log, - enum nvme_telemetry_da da, size_t *size) -{ - return nvme_check_get_telemetry_log(hdl, true, false, false, log, da, size); -} - -int nvme_get_lba_status_log(struct nvme_transport_handle *hdl, bool rae, struct nvme_lba_status_log **log) -{ - _cleanup_free_ struct nvme_lba_status_log *buf = NULL; - struct nvme_passthru_cmd cmd; - __u32 size; - void *tmp; - int err; - - buf = malloc(sizeof(*buf)); - if (!buf) - return -ENOMEM; - - nvme_init_get_log_lba_status(&cmd, 0, log, sizeof(*buf)); - err = nvme_get_log(hdl, &cmd, true, sizeof(*buf)); - if (err) { - *log = NULL; - return err; - } - - size = le32_to_cpu(buf->lslplen); - if (!size) { - *log = buf; - buf = NULL; - return 0; - } - - tmp = realloc(buf, size); - if (!tmp) { - *log = NULL; - return -ENOMEM; - } - buf = tmp; - - nvme_init_get_log_lba_status(&cmd, 0, buf, size); - err = nvme_get_log(hdl, &cmd, rae, NVME_LOG_PAGE_PDU_SIZE); - if (err) { - *log = NULL; - return err; - } - - *log = buf; - buf = NULL; - return 0; -} - -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 - nvme_init_ns_detach_ctrls(&cmd, nsid, &cntlist); - - return nvme_submit_admin_passthru(hdl, &cmd); -} - -int nvme_namespace_attach_ctrls(struct nvme_transport_handle *hdl, bool ish, - __u32 nsid, __u16 num_ctrls, __u16 *ctrlist) -{ - return nvme_ns_attachment(hdl, ish, nsid, num_ctrls, ctrlist, true); -} - -int nvme_namespace_detach_ctrls(struct nvme_transport_handle *hdl, bool ish, - __u32 nsid, __u16 num_ctrls, __u16 *ctrlist) -{ - 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, - bool rgo) -{ - __u32 nanagrpid = le32_to_cpu(id_ctrl->nanagrpid); - size_t size = sizeof(struct nvme_ana_log) + - nanagrpid * sizeof(struct nvme_ana_group_desc); - - return rgo ? size : size + le32_to_cpu(id_ctrl->mnan) * sizeof(__le32); -} - -int nvme_get_ana_log_len(struct nvme_transport_handle *hdl, size_t *analen) -{ - _cleanup_free_ struct nvme_id_ctrl *ctrl = NULL; - struct nvme_passthru_cmd cmd; - int ret; - - ctrl = __nvme_alloc(sizeof(*ctrl)); - if (!ctrl) - return -ENOMEM; - - nvme_init_identify_ctrl(&cmd, ctrl); - ret = nvme_submit_admin_passthru(hdl, &cmd); - if (ret) - return ret; - - *analen = nvme_get_ana_log_len_from_id_ctrl(ctrl, false); - return 0; -} - -int nvme_get_logical_block_size(struct nvme_transport_handle *hdl, __u32 nsid, int *blksize) -{ - _cleanup_free_ struct nvme_id_ns *ns = NULL; - struct nvme_passthru_cmd cmd; - __u8 flbas; - int ret; - - ns = __nvme_alloc(sizeof(*ns)); - if (!ns) - return -ENOMEM; - - nvme_init_identify_ns(&cmd, nsid, ns); - ret = nvme_submit_admin_passthru(hdl, &cmd); - if (ret) - return ret; - - nvme_id_ns_flbas_to_lbaf_inuse(ns->flbas, &flbas); - *blksize = 1 << ns->lbaf[flbas].ds; - - return 0; -} - static int __nvme_set_attr(const char *path, const char *value) { _cleanup_fd_ int fd = -1; diff --git a/libnvme/src/nvme/linux.h b/libnvme/src/nvme/linux.h index 36df2d78cf..b5a9341b2a 100644 --- a/libnvme/src/nvme/linux.h +++ b/libnvme/src/nvme/linux.h @@ -21,204 +21,6 @@ * linux-specific utility functions */ -/** - * 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 - * @buf: Address of buffer containing all or part of the firmware image. - * - * 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, bool ish, - __u32 size, __u32 xfer, __u32 offset, void *buf); - -/** - * nvme_set_etdas() - Set the Extended Telemetry Data Area 4 Supported bit - * @hdl: Transport handle - * @changed: boolean to indicate whether or not the host - * behavior support feature had been changed - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_set_etdas(struct nvme_transport_handle *hdl, bool *changed); - -/** - * nvme_clear_etdas() - Clear the Extended Telemetry Data Area 4 Supported bit - * @hdl: Transport handle - * @changed: boolean to indicate whether or not the host - * behavior support feature had been changed - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_clear_etdas(struct nvme_transport_handle *hdl, bool *changed); - -/** - * nvme_get_uuid_list - Returns the uuid list (if supported) - * @hdl: Transport handle - * @uuid_list: UUID list returned by identify UUID - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_get_uuid_list(struct nvme_transport_handle *hdl, - struct nvme_id_uuid_list *uuid_list); - -/** - * nvme_get_telemetry_max() - Get telemetry limits - * @hdl: Transport handle - * @da: On success return max supported data area - * @max_data_tx: On success set to max transfer chunk supported by the controller - * - * 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_get_telemetry_max(struct nvme_transport_handle *hdl, enum nvme_telemetry_da *da, size_t *max_data_tx); - -/** - * nvme_get_telemetry_log() - Get specified telemetry log - * @hdl: Transport handle - * @create: Generate new host initated telemetry capture - * @ctrl: Get controller Initiated log - * @rae: Retain asynchronous events - * @max_data_tx: Set the max data transfer size to be used retrieving telemetry. - * @da: Log page data area, valid values: &enum nvme_telemetry_da. - * @log: On success, set to the value of the allocated and retrieved log. - * @size: Ptr to the telemetry log size, so it can be returned - * - * The total size allocated can be calculated as: - * (nvme_telemetry_log da size + 1) * NVME_LOG_TELEM_BLOCK_SIZE. - * - * 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_get_telemetry_log(struct nvme_transport_handle *hdl, bool create, bool ctrl, bool rae, size_t max_data_tx, - enum nvme_telemetry_da da, struct nvme_telemetry_log **log, - size_t *size); -/** - * nvme_get_ctrl_telemetry() - Get controller telemetry log - * @hdl: Transport handle - * @rae: Retain asynchronous events - * @log: On success, set to the value of the allocated and retrieved log. - * @da: Log page data area, valid values: &enum nvme_telemetry_da - * @size: Ptr to the telemetry log size, so it can be returned - * - * The total size allocated can be calculated as: - * (nvme_telemetry_log da size + 1) * NVME_LOG_TELEM_BLOCK_SIZE. - * - * 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_get_ctrl_telemetry(struct nvme_transport_handle *hdl, bool rae, struct nvme_telemetry_log **log, - enum nvme_telemetry_da da, size_t *size); - -/** - * nvme_get_host_telemetry() - Get host telemetry log - * @hdl: Transport handle - * @log: On success, set to the value of the allocated and retrieved log. - * @da: Log page data area, valid values: &enum nvme_telemetry_da - * @size: Ptr to the telemetry log size, so it can be returned - * - * The total size allocated can be calculated as: - * (nvme_telemetry_log da size + 1) * NVME_LOG_TELEM_BLOCK_SIZE. - * - * 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_get_host_telemetry(struct nvme_transport_handle *hdl, struct nvme_telemetry_log **log, - enum nvme_telemetry_da da, size_t *size); - -/** - * nvme_get_new_host_telemetry() - Get new host telemetry log - * @hdl: Transport handle - * @log: On success, set to the value of the allocated and retrieved log. - * @da: Log page data area, valid values: &enum nvme_telemetry_da - * @size: Ptr to the telemetry log size, so it can be returned - * - * The total size allocated can be calculated as: - * (nvme_telemetry_log da size + 1) * NVME_LOG_TELEM_BLOCK_SIZE. - * - * 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_get_new_host_telemetry(struct nvme_transport_handle *hdl, struct nvme_telemetry_log **log, - enum nvme_telemetry_da da, size_t *size); - -/** - * nvme_get_ana_log_len_from_id_ctrl() - Retrieve maximum possible ANA log size - * @id_ctrl: Controller identify data - * @rgo: If true, return maximum log page size without NSIDs - * - * Return: A byte limit on the size of the controller's ANA log page - */ -size_t nvme_get_ana_log_len_from_id_ctrl(const struct nvme_id_ctrl *id_ctrl, - bool rgo); - -/** - * nvme_get_ana_log_len() - Retrieve size of the current ANA log - * @hdl: Transport handle - * @analen: Pointer to where the length will be set on success - * - * 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_get_ana_log_len(struct nvme_transport_handle *hdl, size_t *analen); - -/** - * nvme_get_logical_block_size() - Retrieve block size - * @hdl: Transport handle - * @nsid: Namespace id - * @blksize: Pointer to where the block size will be set on success - * - * 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_get_logical_block_size(struct nvme_transport_handle *hdl, __u32 nsid, int *blksize); - -/** - * nvme_get_lba_status_log() - Retrieve the LBA Status log page - * @hdl: Transport handle - * @rae: Retain asynchronous events - * @log: On success, set to the value of the allocated and retrieved log. - * - * 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_get_lba_status_log(struct nvme_transport_handle *hdl, bool rae, struct nvme_lba_status_log **log); - -/** - * 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 - * - * 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, 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 - * - * 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, bool ish, - __u32 nsid, __u16 num_ctrls, __u16 *ctrlist); - /** * nvme_open() - Open an nvme controller or namespace device * @ctx: struct nvme_global_ctx object diff --git a/libnvme/test/meson.build b/libnvme/test/meson.build index f33641b4ab..47cacf77ae 100644 --- a/libnvme/test/meson.build +++ b/libnvme/test/meson.build @@ -178,6 +178,7 @@ if openssl_dep.found() endif foreach hdr : [ + 'cmds', 'fabrics', 'filters', 'ioctl', From 7eed503975cedf1ef9149db6a74cf46d0050fac1 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Tue, 3 Mar 2026 14:06:03 +0100 Subject: [PATCH 12/29] linux: reduce the number of includes Forward declare the three data structs and thus avoid to include nvme/ioctl.h and nvme/types.h. This reduces the inter dependencies between the headers and simplifies any porting attempts. Signed-off-by: Daniel Wagner --- libnvme/src/nvme/linux.h | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/libnvme/src/nvme/linux.h b/libnvme/src/nvme/linux.h index b5a9341b2a..73735713be 100644 --- a/libnvme/src/nvme/linux.h +++ b/libnvme/src/nvme/linux.h @@ -6,14 +6,14 @@ * Authors: Keith Busch * Chaitanya Kulkarni */ -#ifndef _LIBNVME_LINUX_H -#define _LIBNVME_LINUX_H +#pragma once #include -#include +#include -#include -#include +struct nvme_transport_handle; +struct nvme_passthru_cmd; +struct nvme_global_ctx; /** * DOC: linux.h @@ -555,5 +555,3 @@ void nvme_set_dry_run(struct nvme_global_ctx *ctx, bool enable); * IOCTL probing is enabled per default. */ void nvme_set_ioctl_probing(struct nvme_global_ctx *ctx, bool enable); - -#endif /* _LIBNVME_LINUX_H */ From f42773a1684eb4568109215f9d66f76d87ff8d56 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Tue, 3 Mar 2026 14:19:18 +0100 Subject: [PATCH 13/29] cmds: move nvme cmds from util to cmds.h or types.h Move the nvme specification parts of utils to either cmds.h or types.h and reduce the number of include dependencies. Signed-off-by: Daniel Wagner --- libnvme/src/nvme/cmds.c | 202 ++++++++++++++++++- libnvme/src/nvme/cmds.h | 120 +++++++++++ libnvme/src/nvme/types.h | 304 +++++++++++++++++++++++++++- libnvme/src/nvme/util.c | 199 ------------------- libnvme/src/nvme/util.h | 419 +-------------------------------------- 5 files changed, 622 insertions(+), 622 deletions(-) diff --git a/libnvme/src/nvme/cmds.c b/libnvme/src/nvme/cmds.c index 11ed15bd45..319c8c4bcf 100644 --- a/libnvme/src/nvme/cmds.c +++ b/libnvme/src/nvme/cmds.c @@ -240,7 +240,6 @@ int nvme_get_telemetry_log(struct nvme_transport_handle *hdl, bool create, return 0; } - static int nvme_check_get_telemetry_log(struct nvme_transport_handle *hdl, bool create, bool ctrl, bool rae, struct nvme_telemetry_log **log, enum nvme_telemetry_da da, @@ -412,3 +411,204 @@ int nvme_get_logical_block_size(struct nvme_transport_handle *hdl, return 0; } + +static inline void nvme_init_copy_range_elbt(__u8 *elbt, __u64 eilbrt) +{ + int i; + + for (i = 0; i < 8; i++) + elbt[9 - i] = (eilbrt >> (8 * i)) & 0xff; + elbt[1] = 0; + elbt[0] = 0; +} + +void nvme_init_copy_range(struct nvme_copy_range *copy, __u16 *nlbs, + __u64 *slbas, __u32 *eilbrts, __u32 *elbatms, + __u32 *elbats, __u16 nr) +{ + int i; + + for (i = 0; i < nr; i++) { + copy[i].nlb = cpu_to_le16(nlbs[i]); + copy[i].slba = cpu_to_le64(slbas[i]); + copy[i].eilbrt = cpu_to_le32(eilbrts[i]); + copy[i].elbatm = cpu_to_le16(elbatms[i]); + copy[i].elbat = cpu_to_le16(elbats[i]); + } +} + +void nvme_init_copy_range_f1(struct nvme_copy_range_f1 *copy, __u16 *nlbs, + __u64 *slbas, __u64 *eilbrts, __u32 *elbatms, + __u32 *elbats, __u16 nr) +{ + int i; + + for (i = 0; i < nr; i++) { + copy[i].nlb = cpu_to_le16(nlbs[i]); + copy[i].slba = cpu_to_le64(slbas[i]); + copy[i].elbatm = cpu_to_le16(elbatms[i]); + copy[i].elbat = cpu_to_le16(elbats[i]); + nvme_init_copy_range_elbt(copy[i].elbt, eilbrts[i]); + } +} + +void nvme_init_copy_range_f2(struct nvme_copy_range_f2 *copy, __u32 *snsids, + __u16 *nlbs, __u64 *slbas, __u16 *sopts, + __u32 *eilbrts, __u32 *elbatms, __u32 *elbats, + __u16 nr) +{ + int i; + + for (i = 0; i < nr; i++) { + copy[i].snsid = cpu_to_le32(snsids[i]); + copy[i].nlb = cpu_to_le16(nlbs[i]); + copy[i].slba = cpu_to_le64(slbas[i]); + copy[i].sopt = cpu_to_le16(sopts[i]); + copy[i].eilbrt = cpu_to_le32(eilbrts[i]); + copy[i].elbatm = cpu_to_le16(elbatms[i]); + copy[i].elbat = cpu_to_le16(elbats[i]); + } +} + +void nvme_init_copy_range_f3(struct nvme_copy_range_f3 *copy, __u32 *snsids, + __u16 *nlbs, __u64 *slbas, __u16 *sopts, + __u64 *eilbrts, __u32 *elbatms, __u32 *elbats, + __u16 nr) +{ + int i; + + for (i = 0; i < nr; i++) { + copy[i].snsid = cpu_to_le32(snsids[i]); + copy[i].nlb = cpu_to_le16(nlbs[i]); + copy[i].slba = cpu_to_le64(slbas[i]); + copy[i].sopt = cpu_to_le16(sopts[i]); + copy[i].elbatm = cpu_to_le16(elbatms[i]); + copy[i].elbat = cpu_to_le16(elbats[i]); + nvme_init_copy_range_elbt(copy[i].elbt, eilbrts[i]); + } +} + +void nvme_init_dsm_range(struct nvme_dsm_range *dsm, __u32 *ctx_attrs, + __u32 *llbas, __u64 *slbas, __u16 nr_ranges) +{ + int i; + + for (i = 0; i < nr_ranges; i++) { + dsm[i].cattr = cpu_to_le32(ctx_attrs[i]); + dsm[i].nlb = cpu_to_le32(llbas[i]); + dsm[i].slba = cpu_to_le64(slbas[i]); + } +} + +void nvme_init_ctrl_list(struct nvme_ctrl_list *cntlist, __u16 num_ctrls, + __u16 *ctrlist) +{ + int i; + + cntlist->num = cpu_to_le16(num_ctrls); + for (i = 0; i < num_ctrls; i++) + cntlist->identifier[i] = cpu_to_le16(ctrlist[i]); +} + +int nvme_get_feature_length(int fid, __u32 cdw11, enum nvme_data_tfr dir, + __u32 *len) +{ + switch (fid) { + case NVME_FEAT_FID_LBA_RANGE: + *len = sizeof(struct nvme_lba_range_type); + break; + case NVME_FEAT_FID_AUTO_PST: + *len = sizeof(struct nvme_feat_auto_pst); + break; + case NVME_FEAT_FID_PLM_CONFIG: + *len = sizeof(struct nvme_plm_config); + break; + case NVME_FEAT_FID_TIMESTAMP: + *len = sizeof(struct nvme_timestamp); + break; + case NVME_FEAT_FID_HOST_BEHAVIOR: + *len = sizeof(struct nvme_feat_host_behavior); + break; + case NVME_FEAT_FID_HOST_ID: + *len = (cdw11 & 0x1) ? 16 : 8; + break; + case NVME_FEAT_FID_HOST_MEM_BUF: + if (dir == NVME_DATA_TFR_HOST_TO_CTRL) { + *len = 0; + break; + } + *len = sizeof(struct nvme_host_mem_buf_attrs); + break; + case NVME_FEAT_FID_ARBITRATION: + case NVME_FEAT_FID_POWER_MGMT: + case NVME_FEAT_FID_TEMP_THRESH: + case NVME_FEAT_FID_ERR_RECOVERY: + case NVME_FEAT_FID_VOLATILE_WC: + case NVME_FEAT_FID_NUM_QUEUES: + case NVME_FEAT_FID_IRQ_COALESCE: + case NVME_FEAT_FID_IRQ_CONFIG: + case NVME_FEAT_FID_WRITE_ATOMIC: + case NVME_FEAT_FID_ASYNC_EVENT: + case NVME_FEAT_FID_KATO: + case NVME_FEAT_FID_HCTM: + case NVME_FEAT_FID_NOPSC: + case NVME_FEAT_FID_RRL: + case NVME_FEAT_FID_PLM_WINDOW: + case NVME_FEAT_FID_LBA_STS_INTERVAL: + case NVME_FEAT_FID_SANITIZE: + case NVME_FEAT_FID_ENDURANCE_EVT_CFG: + case NVME_FEAT_FID_SW_PROGRESS: + case NVME_FEAT_FID_RESV_MASK: + case NVME_FEAT_FID_RESV_PERSIST: + case NVME_FEAT_FID_WRITE_PROTECT: + case NVME_FEAT_FID_POWER_LIMIT: + *len = 0; + break; + case NVME_FEAT_FID_ENH_CTRL_METADATA: + case NVME_FEAT_FID_CTRL_METADATA: + case NVME_FEAT_FID_NS_METADATA: + *len = sizeof(struct nvme_host_metadata); + break; + case NVME_FEAT_FID_PERF_CHARACTERISTICS: + *len = sizeof(struct nvme_perf_characteristics); + break; + case NVME_FEAT_FID_FDP_EVENTS: + *len = NVME_FEAT_FDPE_NOET_MASK * + sizeof(struct nvme_fdp_supported_event_desc); + break; + default: + return -EINVAL; + } + return 0; +} + +int nvme_get_directive_receive_length(enum nvme_directive_dtype dtype, + enum nvme_directive_receive_doper doper, __u32 *len) +{ + switch (dtype) { + case NVME_DIRECTIVE_DTYPE_IDENTIFY: + switch (doper) { + case NVME_DIRECTIVE_RECEIVE_IDENTIFY_DOPER_PARAM: + *len = sizeof(struct nvme_id_directives); + return 0; + default: + return -EINVAL; + } + case NVME_DIRECTIVE_DTYPE_STREAMS: + switch (doper) { + case NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_PARAM: + *len = sizeof(struct nvme_streams_directive_params); + return 0; + case NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_STATUS: + *len = (128 * 1024) * sizeof(__le16); + return 0; + case NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_RESOURCE: + *len = 0; + return 0; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} diff --git a/libnvme/src/nvme/cmds.h b/libnvme/src/nvme/cmds.h index bde7b52868..ef0a4fcde7 100644 --- a/libnvme/src/nvme/cmds.h +++ b/libnvme/src/nvme/cmds.h @@ -7115,3 +7115,123 @@ int nvme_namespace_attach_ctrls(struct nvme_transport_handle *hdl, bool ish, */ int nvme_namespace_detach_ctrls(struct nvme_transport_handle *hdl, bool ish, __u32 nsid, __u16 num_ctrls, __u16 *ctrlist); + +/** + * nvme_init_ctrl_list() - Initialize an nvme_ctrl_list structure from an array. + * @cntlist: The controller list structure to initialize + * @num_ctrls: The number of controllers in the array, &ctrlist. + * @ctrlist: An array of controller identifiers in CPU native endian. + * + * This is intended to be used with any command that takes a controller list + * argument. See nvme_ns_attach_ctrls() and nvme_ns_detach(). + */ +void nvme_init_ctrl_list(struct nvme_ctrl_list *cntlist, __u16 num_ctrls, + __u16 *ctrlist); + +/** + * nvme_init_dsm_range() - Constructs a data set range structure + * @dsm: DSM range array + * @ctx_attrs: Array of context attributes + * @llbas: Array of length in logical blocks + * @slbas: Array of starting logical blocks + * @nr_ranges: The size of the dsm arrays + * + * Each array must be the same size of size 'nr_ranges'. This is intended to be + * used with constructing a payload for nvme_dsm(). + * + * Return: The nvme command status if a response was received or -errno + * otherwise. + */ +void nvme_init_dsm_range(struct nvme_dsm_range *dsm, __u32 *ctx_attrs, + __u32 *llbas, __u64 *slbas, __u16 nr_ranges); + +/** + * nvme_init_copy_range() - Constructs a copy range structure + * @copy: Copy range array + * @nlbs: Number of logical blocks + * @slbas: Starting LBA + * @eilbrts: Expected initial logical block reference tag + * @elbatms: Expected logical block application tag mask + * @elbats: Expected logical block application tag + * @nr: Number of descriptors to construct + */ +void nvme_init_copy_range(struct nvme_copy_range *copy, __u16 *nlbs, + __u64 *slbas, __u32 *eilbrts, __u32 *elbatms, + __u32 *elbats, __u16 nr); + +/** + * nvme_init_copy_range_f1() - Constructs a copy range f1 structure + * @copy: Copy range array + * @nlbs: Number of logical blocks + * @slbas: Starting LBA + * @eilbrts: Expected initial logical block reference tag + * @elbatms: Expected logical block application tag mask + * @elbats: Expected logical block application tag + * @nr: Number of descriptors to construct + */ +void nvme_init_copy_range_f1(struct nvme_copy_range_f1 *copy, __u16 *nlbs, + __u64 *slbas, __u64 *eilbrts, __u32 *elbatms, + __u32 *elbats, __u16 nr); + +/** + * nvme_init_copy_range_f2() - Constructs a copy range f2 structure + * @copy: Copy range array + * @snsids: Source namespace identifier + * @nlbs: Number of logical blocks + * @slbas: Starting LBA + * @sopts: Source options + * @eilbrts: Expected initial logical block reference tag + * @elbatms: Expected logical block application tag mask + * @elbats: Expected logical block application tag + * @nr: Number of descriptors to construct + */ +void nvme_init_copy_range_f2(struct nvme_copy_range_f2 *copy, __u32 *snsids, + __u16 *nlbs, __u64 *slbas, __u16 *sopts, + __u32 *eilbrts, __u32 *elbatms, __u32 *elbats, + __u16 nr); + +/** + * nvme_init_copy_range_f3() - Constructs a copy range f3 structure + * @copy: Copy range array + * @snsids: Source namespace identifier + * @nlbs: Number of logical blocks + * @slbas: Starting LBA + * @sopts: Source options + * @eilbrts: Expected initial logical block reference tag + * @elbatms: Expected logical block application tag mask + * @elbats: Expected logical block application tag + * @nr: Number of descriptors to construct + */ +void nvme_init_copy_range_f3(struct nvme_copy_range_f3 *copy, __u32 *snsids, + __u16 *nlbs, __u64 *slbas, __u16 *sopts, + __u64 *eilbrts, __u32 *elbatms, __u32 *elbats, + __u16 nr); + +/** + * nvme_get_feature_length() - Retrieve the command payload length for a + * specific feature identifier + * @fid: Feature identifier, see &enum nvme_features_id. + * @cdw11: The cdw11 value may affect the transfer (only known fid is + * %NVME_FEAT_FID_HOST_ID) + * @dir: Data transfer direction: false - host to controller, true - + * controller to host may affect the transfer (only known fid is + * %NVME_FEAT_FID_HOST_MEM_BUF). + * @len: On success, set to this features payload length in bytes. + * + * Return: 0 on success, -1 with errno set to EINVAL if the function did not + * recognize &fid. + */ +int nvme_get_feature_length(int fid, __u32 cdw11, enum nvme_data_tfr dir, + __u32 *len); + +/** + * nvme_get_directive_receive_length() - Get directive receive length + * @dtype: Directive type, see &enum nvme_directive_dtype + * @doper: Directive receive operation, see &enum nvme_directive_receive_doper + * @len: On success, set to this directives payload length in bytes. + * + * Return: 0 on success, -1 with errno set to EINVAL if the function did not + * recognize &dtype or &doper. + */ +int nvme_get_directive_receive_length(enum nvme_directive_dtype dtype, + enum nvme_directive_receive_doper doper, __u32 *len); diff --git a/libnvme/src/nvme/types.h b/libnvme/src/nvme/types.h index 3e64258f32..843d6411c7 100644 --- a/libnvme/src/nvme/types.h +++ b/libnvme/src/nvme/types.h @@ -6,9 +6,7 @@ * Authors: Keith Busch * Chaitanya Kulkarni */ - -#ifndef _LIBNVME_TYPES_H -#define _LIBNVME_TYPES_H +#pragma once #include #include @@ -10509,4 +10507,302 @@ struct nvme_lm_ctrl_data_queue_fid_data { __le32 hp; __le32 tpt; }; -#endif /* _LIBNVME_TYPES_H */ + +#define NVME_FEAT_ARB_BURST(v) NVME_GET(v, FEAT_ARBITRATION_BURST) +#define NVME_FEAT_ARB_LPW(v) NVME_GET(v, FEAT_ARBITRATION_LPW) +#define NVME_FEAT_ARB_MPW(v) NVME_GET(v, FEAT_ARBITRATION_MPW) +#define NVME_FEAT_ARB_HPW(v) NVME_GET(v, FEAT_ARBITRATION_HPW) + +static inline void nvme_feature_decode_arbitration(__u32 value, __u8 *ab, + __u8 *lpw, __u8 *mpw, + __u8 *hpw) +{ + *ab = NVME_FEAT_ARB_BURST(value); + *lpw = NVME_FEAT_ARB_LPW(value); + *mpw = NVME_FEAT_ARB_MPW(value); + *hpw = NVME_FEAT_ARB_HPW(value); +}; + +#define NVME_FEAT_PM_PS(v) NVME_GET(v, FEAT_PWRMGMT_PS) +#define NVME_FEAT_PM_WH(v) NVME_GET(v, FEAT_PWRMGMT_WH) + +#define NVME_FEAT_POWER_LIMIT_PLV(v) NVME_GET(v, FEAT_POWER_LIMIT_PLV) +#define NVME_FEAT_POWER_LIMIT_PLS(v) NVME_GET(v, FEAT_POWER_LIMIT_PLS) + +#define NVME_FEAT_POWER_THRESH_PTV(v) NVME_GET(v, FEAT_POWER_THRESH_PTV) +#define NVME_FEAT_POWER_THRESH_PTS(v) NVME_GET(v, FEAT_POWER_THRESH_PTS) +#define NVME_FEAT_POWER_THRESH_PMTS(v) NVME_GET(v, FEAT_POWER_THRESH_PMTS) +#define NVME_FEAT_POWER_THRESH_EPT(v) NVME_GET(v, FEAT_POWER_THRESH_EPT) + +static inline void +nvme_feature_decode_power_mgmt(__u32 value, __u8 *ps, __u8 *wh) +{ + *ps = NVME_FEAT_PM_PS(value); + *wh = NVME_FEAT_PM_WH(value); +} + +#define NVME_FEAT_LBAR_NR(v) NVME_GET(v, FEAT_LBAR_NR) + +static inline void +nvme_feature_decode_lba_range(__u32 value, __u8 *num) +{ + *num = NVME_FEAT_LBAR_NR(value); +} + +#define NVME_FEAT_TT_TMPTH(v) NVME_GET(v, FEAT_TT_TMPTH) +#define NVME_FEAT_TT_TMPSEL(v) NVME_GET(v, FEAT_TT_TMPSEL) +#define NVME_FEAT_TT_THSEL(v) NVME_GET(v, FEAT_TT_THSEL) +#define NVME_FEAT_TT_TMPTHH(v) NVME_GET(v, FEAT_TT_TMPTHH) + +static inline void +nvme_feature_decode_temp_threshold(__u32 value, __u16 *tmpth, + __u8 *tmpsel, __u8 *thsel, __u8 *tmpthh) +{ + *tmpth = NVME_FEAT_TT_TMPTH(value); + *tmpsel = NVME_FEAT_TT_TMPSEL(value); + *thsel = NVME_FEAT_TT_THSEL(value); + *tmpthh = NVME_FEAT_TT_TMPTHH(value); +} + +#define NVME_FEAT_ER_TLER(v) NVME_GET(v, FEAT_ERROR_RECOVERY_TLER) +#define NVME_FEAT_ER_DULBE(v) NVME_GET(v, FEAT_ERROR_RECOVERY_DULBE) + +static inline void +nvme_feature_decode_error_recovery(__u32 value, __u16 *tler, bool *dulbe) +{ + *tler = NVME_FEAT_ER_TLER(value); + *dulbe = NVME_FEAT_ER_DULBE(value); +} + +#define NVME_FEAT_VWC_WCE(v) NVME_GET(v, FEAT_VWC_WCE) + +static inline void +nvme_feature_decode_volatile_write_cache(__u32 value, bool *wce) +{ + *wce = NVME_FEAT_VWC_WCE(value); +} + +#define NVME_FEAT_NRQS_NSQR(v) NVME_GET(v, FEAT_NRQS_NSQR) +#define NVME_FEAT_NRQS_NCQR(v) NVME_GET(v, FEAT_NRQS_NCQR) + +static inline void +nvme_feature_decode_number_of_queues(__u32 value, __u16 *nsqr, __u16 *ncqr) +{ + *nsqr = NVME_FEAT_NRQS_NSQR(value); + *ncqr = NVME_FEAT_NRQS_NCQR(value); +} + +#define NVME_FEAT_IRQC_THR(v) NVME_GET(v, FEAT_IRQC_THR) +#define NVME_FEAT_IRQC_TIME(v) NVME_GET(v, FEAT_IRQC_TIME) + +static inline void +nvme_feature_decode_interrupt_coalescing(__u32 value, __u8 *thr, __u8 *time) +{ + *thr = NVME_FEAT_IRQC_THR(value); + *time = NVME_FEAT_IRQC_TIME(value); +} + +#define NVME_FEAT_ICFG_IV(v) NVME_GET(v, FEAT_ICFG_IV) +#define NVME_FEAT_ICFG_CD(v) NVME_GET(v, FEAT_ICFG_CD) + +static inline void +nvme_feature_decode_interrupt_config(__u32 value, __u16 *iv, bool *cd) +{ + *iv = NVME_FEAT_ICFG_IV(value); + *cd = NVME_FEAT_ICFG_CD(value); +} + +#define NVME_FEAT_WA_DN(v) NVME_GET(v, FEAT_WA_DN) + +static inline void +nvme_feature_decode_write_atomicity(__u32 value, bool *dn) +{ + *dn = NVME_FEAT_WA_DN(value); +} + +#define NVME_FEAT_AE_SMART(v) NVME_GET(v, FEAT_AE_SMART) +#define NVME_FEAT_AE_NAN(v) NVME_GET(v, FEAT_AE_NAN) +#define NVME_FEAT_AE_FW(v) NVME_GET(v, FEAT_AE_FW) +#define NVME_FEAT_AE_TELEM(v) NVME_GET(v, FEAT_AE_TELEM) +#define NVME_FEAT_AE_ANA(v) NVME_GET(v, FEAT_AE_ANA) +#define NVME_FEAT_AE_PLA(v) NVME_GET(v, FEAT_AE_PLA) +#define NVME_FEAT_AE_LBAS(v) NVME_GET(v, FEAT_AE_LBAS) +#define NVME_FEAT_AE_EGA(v) NVME_GET(v, FEAT_AE_EGA) +#define NVME_FEAT_AE_NNSSHDN(v) NVME_GET(v, FEAT_AE_NNSSHDN) +#define NVME_FEAT_AE_TTHRY(v) NVME_GET(v, FEAT_AE_TTHRY) +#define NVME_FEAT_AE_RASSN(v) NVME_GET(v, FEAT_AE_RASSN) +#define NVME_FEAT_AE_RGRP0(v) NVME_GET(v, FEAT_AE_RGRP0) +#define NVME_FEAT_AE_ANSAN(v) NVME_GET(v, FEAT_AE_ANSAN) +#define NVME_FEAT_AE_ZDCN(v) NVME_GET(v, FEAT_AE_ZDCN) +#define NVME_FEAT_AE_PMDRLPCN(v) NVME_GET(v, FEAT_AE_PMDRLPCN) +#define NVME_FEAT_AE_ADLPCN(v) NVME_GET(v, FEAT_AE_ADLPCN) +#define NVME_FEAT_AE_HDLPCN(v) NVME_GET(v, FEAT_AE_HDLPCN) +#define NVME_FEAT_AE_DLPCN(v) NVME_GET(v, FEAT_AE_DLPCN) + +static inline void +nvme_feature_decode_async_event_config(__u32 value, __u8 *smart, bool *nan, + bool *fw, bool *telem, bool *ana, bool *pla, + bool *lbas, bool *ega) +{ + *smart = NVME_FEAT_AE_SMART(value); + *nan = NVME_FEAT_AE_NAN(value); + *fw = NVME_FEAT_AE_FW(value); + *telem = NVME_FEAT_AE_TELEM(value); + *ana = NVME_FEAT_AE_ANA(value); + *pla = NVME_FEAT_AE_PLA(value); + *lbas = NVME_FEAT_AE_LBAS(value); + *ega = NVME_FEAT_AE_EGA(value); +} + +#define NVME_FEAT_APST_APSTE(v) NVME_GET(v, FEAT_APST_APSTE) + +static inline void +nvme_feature_decode_auto_power_state(__u32 value, bool *apste) +{ + *apste = NVME_FEAT_APST_APSTE(value); +} + +#define NVME_FEAT_HMEM_EHM(v) NVME_GET(v, FEAT_HMEM_EHM) + +static inline void +nvme_feature_decode_host_memory_buffer(__u32 value, bool *ehm) +{ + *ehm = NVME_FEAT_HMEM_EHM(value); +} + +#define NVME_FEAT_HCTM_TMT2(v) NVME_GET(v, FEAT_HCTM_TMT2) +#define NVME_FEAT_HCTM_TMT1(v) NVME_GET(v, FEAT_HCTM_TMT1) + +static inline void +nvme_feature_decode_host_thermal_mgmt(__u32 value, __u16 *tmt2, __u16 *tmt1) +{ + *tmt2 = NVME_FEAT_HCTM_TMT2(value); + *tmt1 = NVME_FEAT_HCTM_TMT1(value); +} + +#define NVME_FEAT_NOPS_NOPPME(v) NVME_GET(v, FEAT_NOPS_NOPPME) + +static inline void +nvme_feature_decode_non_op_power_config(__u32 value, bool *noppme) +{ + *noppme = NVME_FEAT_NOPS_NOPPME(value); +} + +#define NVME_FEAT_RRL_RRL(v) NVME_GET(v, FEAT_RRL_RRL) + +static inline void +nvme_feature_decode_read_recovery_level_config(__u32 value, __u8 *rrl) +{ + *rrl = NVME_FEAT_RRL_RRL(value); +} + +#define NVME_FEAT_PLM_LPE(v) NVME_GET(v, FEAT_PLM_LPE) + +static inline void +nvme_feature_decode_predictable_latency_mode_config(__u32 value, bool *lpe) +{ + *lpe = NVME_FEAT_PLM_LPE(value); +} + +#define NVME_FEAT_PLMW_WS(v) NVME_GET(v, FEAT_PLMW_WS) + +static inline void +nvme_feature_decode_predictable_latency_mode_window(__u32 value, __u8 *ws) +{ + *ws = NVME_FEAT_PLMW_WS(value); +} + +#define NVME_FEAT_LBAS_LSIRI(v) NVME_GET(v, FEAT_LBAS_LSIRI) +#define NVME_FEAT_LBAS_LSIPI(v) NVME_GET(v, FEAT_LBAS_LSIPI) + +static inline void +nvme_feature_decode_lba_status_attributes(__u32 value, __u16 *lsiri, + __u16 *lsipi) +{ + *lsiri = NVME_FEAT_LBAS_LSIRI(value); + *lsipi = NVME_FEAT_LBAS_LSIPI(value); +} + +#define NVME_FEAT_SC_NODRM(v) NVME_GET(v, FEAT_SC_NODRM) + +static inline void +nvme_feature_decode_sanitize_config(__u32 value, bool *nodrm) +{ + *nodrm = NVME_FEAT_SC_NODRM(value); +} + +#define NVME_FEAT_EG_ENDGID(v) NVME_GET(v, FEAT_EG_ENDGID) +#define NVME_FEAT_EG_EGCW(v) NVME_GET(v, FEAT_EG_EGCW) + +static inline void +nvme_feature_decode_endurance_group_event_config(__u32 value, + __u16 *endgid, __u8 *endgcw) +{ + *endgid = NVME_FEAT_EG_ENDGID(value); + *endgcw = NVME_FEAT_EG_EGCW(value); +} + +#define NVME_FEAT_PERFC_ATTRI(v) NVME_GET(v, FEAT_PERFC_ATTRI) +#define NVME_FEAT_PERFC_RVSPA(v) NVME_GET(v, FEAT_PERFC_RVSPA) + +static inline void +nvme_feature_decode_perf_characteristics(__u32 value, __u8 *attri, bool *rvspa) +{ + *attri = NVME_FEAT_PERFC_ATTRI(value); + *rvspa = NVME_FEAT_PERFC_RVSPA(value); +} + +#define NVME_FEAT_SPM_PBSLC(v) NVME_GET(v, FEAT_SPM_PBSLC) + +static inline void +nvme_feature_decode_software_progress_marker(__u32 value, __u8 *pbslc) +{ + *pbslc = NVME_FEAT_SPM_PBSLC(value); +} + +#define NVME_FEAT_HOSTID_EXHID(v) NVME_GET(v, FEAT_HOSTID_EXHID) + +static inline void +nvme_feature_decode_host_identifier(__u32 value, bool *exhid) +{ + *exhid = NVME_FEAT_HOSTID_EXHID(value); +} + +#define NVME_FEAT_RM_REGPRE(v) NVME_GET(v, FEAT_RM_REGPRE) +#define NVME_FEAT_RM_RESREL(v) NVME_GET(v, FEAT_RM_RESREL) +#define NVME_FEAT_RM_RESPRE(v) NVME_GET(v, FEAT_RM_RESPRE) + +static inline void +nvme_feature_decode_reservation_notification(__u32 value, bool *regpre, + bool *resrel, bool *respre) +{ + *regpre = NVME_FEAT_RM_REGPRE(value); + *resrel = NVME_FEAT_RM_RESREL(value); + *respre = NVME_FEAT_RM_RESPRE(value); +} + +#define NVME_FEAT_RP_PTPL(v) NVME_GET(v, FEAT_RP_PTPL) + +static inline void +nvme_feature_decode_reservation_persistance(__u32 value, bool *ptpl) +{ + *ptpl = NVME_FEAT_RP_PTPL(value); +} + +#define NVME_FEAT_WP_WPS(v) NVME_GET(v, FEAT_WP_WPS) + +static inline void +nvme_feature_decode_namespace_write_protect(__u32 value, __u8 *wps) +{ + *wps = NVME_FEAT_WP_WPS(value); +} + +#define NVME_FEAT_BPWPC_BP0WPS(v) NVME_GET(v, FEAT_BPWPC_BP0WPS) +#define NVME_FEAT_BPWPC_BP1WPS(v) NVME_GET(v, FEAT_BPWPC_BP1WPS) + +static inline void +nvme_id_ns_flbas_to_lbaf_inuse(__u8 flbas, __u8 *lbaf_inuse) +{ + *lbaf_inuse = ((NVME_FLBAS_HIGHER(flbas) << 4) | + NVME_FLBAS_LOWER(flbas)); +} diff --git a/libnvme/src/nvme/util.c b/libnvme/src/nvme/util.c index 5379101801..74c940ddb8 100644 --- a/libnvme/src/nvme/util.c +++ b/libnvme/src/nvme/util.c @@ -412,205 +412,6 @@ const char *nvme_status_to_string(int status, bool fabrics) return s; } -static inline void nvme_init_copy_range_elbt(__u8 *elbt, __u64 eilbrt) -{ - int i; - - for (i = 0; i < 8; i++) - elbt[9 - i] = (eilbrt >> (8 * i)) & 0xff; - elbt[1] = 0; - elbt[0] = 0; -} - -void nvme_init_copy_range(struct nvme_copy_range *copy, __u16 *nlbs, - __u64 *slbas, __u32 *eilbrts, __u32 *elbatms, - __u32 *elbats, __u16 nr) -{ - int i; - - for (i = 0; i < nr; i++) { - copy[i].nlb = cpu_to_le16(nlbs[i]); - copy[i].slba = cpu_to_le64(slbas[i]); - copy[i].eilbrt = cpu_to_le32(eilbrts[i]); - copy[i].elbatm = cpu_to_le16(elbatms[i]); - copy[i].elbat = cpu_to_le16(elbats[i]); - } -} - -void nvme_init_copy_range_f1(struct nvme_copy_range_f1 *copy, __u16 *nlbs, - __u64 *slbas, __u64 *eilbrts, __u32 *elbatms, - __u32 *elbats, __u16 nr) -{ - int i; - - for (i = 0; i < nr; i++) { - copy[i].nlb = cpu_to_le16(nlbs[i]); - copy[i].slba = cpu_to_le64(slbas[i]); - copy[i].elbatm = cpu_to_le16(elbatms[i]); - copy[i].elbat = cpu_to_le16(elbats[i]); - nvme_init_copy_range_elbt(copy[i].elbt, eilbrts[i]); - } -} - -void nvme_init_copy_range_f2(struct nvme_copy_range_f2 *copy, __u32 *snsids, - __u16 *nlbs, __u64 *slbas, __u16 *sopts, - __u32 *eilbrts, __u32 *elbatms, __u32 *elbats, - __u16 nr) -{ - int i; - - for (i = 0; i < nr; i++) { - copy[i].snsid = cpu_to_le32(snsids[i]); - copy[i].nlb = cpu_to_le16(nlbs[i]); - copy[i].slba = cpu_to_le64(slbas[i]); - copy[i].sopt = cpu_to_le16(sopts[i]); - copy[i].eilbrt = cpu_to_le32(eilbrts[i]); - copy[i].elbatm = cpu_to_le16(elbatms[i]); - copy[i].elbat = cpu_to_le16(elbats[i]); - } -} - -void nvme_init_copy_range_f3(struct nvme_copy_range_f3 *copy, __u32 *snsids, - __u16 *nlbs, __u64 *slbas, __u16 *sopts, - __u64 *eilbrts, __u32 *elbatms, __u32 *elbats, - __u16 nr) -{ - int i; - - for (i = 0; i < nr; i++) { - copy[i].snsid = cpu_to_le32(snsids[i]); - copy[i].nlb = cpu_to_le16(nlbs[i]); - copy[i].slba = cpu_to_le64(slbas[i]); - copy[i].sopt = cpu_to_le16(sopts[i]); - copy[i].elbatm = cpu_to_le16(elbatms[i]); - copy[i].elbat = cpu_to_le16(elbats[i]); - nvme_init_copy_range_elbt(copy[i].elbt, eilbrts[i]); - } -} - -void nvme_init_dsm_range(struct nvme_dsm_range *dsm, __u32 *ctx_attrs, - __u32 *llbas, __u64 *slbas, __u16 nr_ranges) -{ - int i; - - for (i = 0; i < nr_ranges; i++) { - dsm[i].cattr = cpu_to_le32(ctx_attrs[i]); - dsm[i].nlb = cpu_to_le32(llbas[i]); - dsm[i].slba = cpu_to_le64(slbas[i]); - } -} - -void nvme_init_ctrl_list(struct nvme_ctrl_list *cntlist, __u16 num_ctrls, - __u16 *ctrlist) -{ - int i; - - cntlist->num = cpu_to_le16(num_ctrls); - for (i = 0; i < num_ctrls; i++) - cntlist->identifier[i] = cpu_to_le16(ctrlist[i]); -} - -int nvme_get_feature_length(int fid, __u32 cdw11, enum nvme_data_tfr dir, - __u32 *len) -{ - switch (fid) { - case NVME_FEAT_FID_LBA_RANGE: - *len = sizeof(struct nvme_lba_range_type); - break; - case NVME_FEAT_FID_AUTO_PST: - *len = sizeof(struct nvme_feat_auto_pst); - break; - case NVME_FEAT_FID_PLM_CONFIG: - *len = sizeof(struct nvme_plm_config); - break; - case NVME_FEAT_FID_TIMESTAMP: - *len = sizeof(struct nvme_timestamp); - break; - case NVME_FEAT_FID_HOST_BEHAVIOR: - *len = sizeof(struct nvme_feat_host_behavior); - break; - case NVME_FEAT_FID_HOST_ID: - *len = (cdw11 & 0x1) ? 16 : 8; - break; - case NVME_FEAT_FID_HOST_MEM_BUF: - if (dir == NVME_DATA_TFR_HOST_TO_CTRL) { - *len = 0; - break; - } - *len = sizeof(struct nvme_host_mem_buf_attrs); - break; - case NVME_FEAT_FID_ARBITRATION: - case NVME_FEAT_FID_POWER_MGMT: - case NVME_FEAT_FID_TEMP_THRESH: - case NVME_FEAT_FID_ERR_RECOVERY: - case NVME_FEAT_FID_VOLATILE_WC: - case NVME_FEAT_FID_NUM_QUEUES: - case NVME_FEAT_FID_IRQ_COALESCE: - case NVME_FEAT_FID_IRQ_CONFIG: - case NVME_FEAT_FID_WRITE_ATOMIC: - case NVME_FEAT_FID_ASYNC_EVENT: - case NVME_FEAT_FID_KATO: - case NVME_FEAT_FID_HCTM: - case NVME_FEAT_FID_NOPSC: - case NVME_FEAT_FID_RRL: - case NVME_FEAT_FID_PLM_WINDOW: - case NVME_FEAT_FID_LBA_STS_INTERVAL: - case NVME_FEAT_FID_SANITIZE: - case NVME_FEAT_FID_ENDURANCE_EVT_CFG: - case NVME_FEAT_FID_SW_PROGRESS: - case NVME_FEAT_FID_RESV_MASK: - case NVME_FEAT_FID_RESV_PERSIST: - case NVME_FEAT_FID_WRITE_PROTECT: - case NVME_FEAT_FID_POWER_LIMIT: - *len = 0; - break; - case NVME_FEAT_FID_ENH_CTRL_METADATA: - case NVME_FEAT_FID_CTRL_METADATA: - case NVME_FEAT_FID_NS_METADATA: - *len = sizeof(struct nvme_host_metadata); - break; - case NVME_FEAT_FID_PERF_CHARACTERISTICS: - *len = sizeof(struct nvme_perf_characteristics); - break; - case NVME_FEAT_FID_FDP_EVENTS: - *len = NVME_FEAT_FDPE_NOET_MASK * sizeof(struct nvme_fdp_supported_event_desc); - break; - default: - return -EINVAL; - } - return 0; -} - -int nvme_get_directive_receive_length(enum nvme_directive_dtype dtype, - enum nvme_directive_receive_doper doper, __u32 *len) -{ - switch (dtype) { - case NVME_DIRECTIVE_DTYPE_IDENTIFY: - switch (doper) { - case NVME_DIRECTIVE_RECEIVE_IDENTIFY_DOPER_PARAM: - *len = sizeof(struct nvme_id_directives); - return 0; - default: - return -EINVAL; - } - case NVME_DIRECTIVE_DTYPE_STREAMS: - switch (doper) { - case NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_PARAM: - *len = sizeof(struct nvme_streams_directive_params); - return 0; - case NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_STATUS: - *len = (128 * 1024) * sizeof(__le16); - return 0; - case NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_RESOURCE: - *len = 0; - return 0; - default: - return -EINVAL; - } - default: - return -EINVAL; - } -} static const char * const libnvme_status[] = { [ENVME_CONNECT_RESOLVE] = "failed to resolve host", diff --git a/libnvme/src/nvme/util.h b/libnvme/src/nvme/util.h index 0de58ada57..78821a5b3c 100644 --- a/libnvme/src/nvme/util.h +++ b/libnvme/src/nvme/util.h @@ -6,8 +6,7 @@ * Authors: Keith Busch * Chaitanya Kulkarni */ -#ifndef _LIBNVME_UTIL_H -#define _LIBNVME_UTIL_H +#pragma once #include @@ -150,420 +149,6 @@ const char *nvme_errno_to_string(int err); */ const char *nvme_strerror(int err); -/** - * nvme_init_ctrl_list() - Initialize an nvme_ctrl_list structure from an array. - * @cntlist: The controller list structure to initialize - * @num_ctrls: The number of controllers in the array, &ctrlist. - * @ctrlist: An array of controller identifiers in CPU native endian. - * - * This is intended to be used with any command that takes a controller list - * argument. See nvme_ns_attach_ctrls() and nvme_ns_detach(). - */ -void nvme_init_ctrl_list(struct nvme_ctrl_list *cntlist, __u16 num_ctrls, - __u16 *ctrlist); - -/** - * nvme_init_dsm_range() - Constructs a data set range structure - * @dsm: DSM range array - * @ctx_attrs: Array of context attributes - * @llbas: Array of length in logical blocks - * @slbas: Array of starting logical blocks - * @nr_ranges: The size of the dsm arrays - * - * Each array must be the same size of size 'nr_ranges'. This is intended to be - * used with constructing a payload for nvme_dsm(). - * - * Return: The nvme command status if a response was received or -errno - * otherwise. - */ -void nvme_init_dsm_range(struct nvme_dsm_range *dsm, __u32 *ctx_attrs, - __u32 *llbas, __u64 *slbas, __u16 nr_ranges); - -/** - * nvme_init_copy_range() - Constructs a copy range structure - * @copy: Copy range array - * @nlbs: Number of logical blocks - * @slbas: Starting LBA - * @eilbrts: Expected initial logical block reference tag - * @elbatms: Expected logical block application tag mask - * @elbats: Expected logical block application tag - * @nr: Number of descriptors to construct - */ -void nvme_init_copy_range(struct nvme_copy_range *copy, __u16 *nlbs, - __u64 *slbas, __u32 *eilbrts, __u32 *elbatms, - __u32 *elbats, __u16 nr); - -/** - * nvme_init_copy_range_f1() - Constructs a copy range f1 structure - * @copy: Copy range array - * @nlbs: Number of logical blocks - * @slbas: Starting LBA - * @eilbrts: Expected initial logical block reference tag - * @elbatms: Expected logical block application tag mask - * @elbats: Expected logical block application tag - * @nr: Number of descriptors to construct - */ -void nvme_init_copy_range_f1(struct nvme_copy_range_f1 *copy, __u16 *nlbs, - __u64 *slbas, __u64 *eilbrts, __u32 *elbatms, - __u32 *elbats, __u16 nr); - -/** - * nvme_init_copy_range_f2() - Constructs a copy range f2 structure - * @copy: Copy range array - * @snsids: Source namespace identifier - * @nlbs: Number of logical blocks - * @slbas: Starting LBA - * @sopts: Source options - * @eilbrts: Expected initial logical block reference tag - * @elbatms: Expected logical block application tag mask - * @elbats: Expected logical block application tag - * @nr: Number of descriptors to construct - */ -void nvme_init_copy_range_f2(struct nvme_copy_range_f2 *copy, __u32 *snsids, - __u16 *nlbs, __u64 *slbas, __u16 *sopts, - __u32 *eilbrts, __u32 *elbatms, __u32 *elbats, - __u16 nr); - -/** - * nvme_init_copy_range_f3() - Constructs a copy range f3 structure - * @copy: Copy range array - * @snsids: Source namespace identifier - * @nlbs: Number of logical blocks - * @slbas: Starting LBA - * @sopts: Source options - * @eilbrts: Expected initial logical block reference tag - * @elbatms: Expected logical block application tag mask - * @elbats: Expected logical block application tag - * @nr: Number of descriptors to construct - */ -void nvme_init_copy_range_f3(struct nvme_copy_range_f3 *copy, __u32 *snsids, - __u16 *nlbs, __u64 *slbas, __u16 *sopts, - __u64 *eilbrts, __u32 *elbatms, __u32 *elbats, - __u16 nr); - -/** - * nvme_get_feature_length() - Retreive the command payload length for a - * specific feature identifier - * @fid: Feature identifier, see &enum nvme_features_id. - * @cdw11: The cdw11 value may affect the transfer (only known fid is - * %NVME_FEAT_FID_HOST_ID) - * @dir: Data transfer direction: false - host to controller, true - - * controller to host may affect the transfer (only known fid is - * %NVME_FEAT_FID_HOST_MEM_BUF). - * @len: On success, set to this features payload length in bytes. - * - * Return: 0 on success, -1 with errno set to EINVAL if the function did not - * recognize &fid. - */ -int nvme_get_feature_length(int fid, __u32 cdw11, enum nvme_data_tfr dir, - __u32 *len); - -/** - * nvme_get_directive_receive_length() - Get directive receive length - * @dtype: Directive type, see &enum nvme_directive_dtype - * @doper: Directive receive operation, see &enum nvme_directive_receive_doper - * @len: On success, set to this directives payload length in bytes. - * - * Return: 0 on success, -1 with errno set to EINVAL if the function did not - * recognize &dtype or &doper. - */ -int nvme_get_directive_receive_length(enum nvme_directive_dtype dtype, - enum nvme_directive_receive_doper doper, __u32 *len); - -#define NVME_FEAT_ARB_BURST(v) NVME_GET(v, FEAT_ARBITRATION_BURST) -#define NVME_FEAT_ARB_LPW(v) NVME_GET(v, FEAT_ARBITRATION_LPW) -#define NVME_FEAT_ARB_MPW(v) NVME_GET(v, FEAT_ARBITRATION_MPW) -#define NVME_FEAT_ARB_HPW(v) NVME_GET(v, FEAT_ARBITRATION_HPW) - -static inline void nvme_feature_decode_arbitration(__u32 value, __u8 *ab, - __u8 *lpw, __u8 *mpw, - __u8 *hpw) -{ - *ab = NVME_FEAT_ARB_BURST(value); - *lpw = NVME_FEAT_ARB_LPW(value); - *mpw = NVME_FEAT_ARB_MPW(value); - *hpw = NVME_FEAT_ARB_HPW(value); -}; - -#define NVME_FEAT_PM_PS(v) NVME_GET(v, FEAT_PWRMGMT_PS) -#define NVME_FEAT_PM_WH(v) NVME_GET(v, FEAT_PWRMGMT_WH) - -#define NVME_FEAT_POWER_LIMIT_PLV(v) NVME_GET(v, FEAT_POWER_LIMIT_PLV) -#define NVME_FEAT_POWER_LIMIT_PLS(v) NVME_GET(v, FEAT_POWER_LIMIT_PLS) - -#define NVME_FEAT_POWER_THRESH_PTV(v) NVME_GET(v, FEAT_POWER_THRESH_PTV) -#define NVME_FEAT_POWER_THRESH_PTS(v) NVME_GET(v, FEAT_POWER_THRESH_PTS) -#define NVME_FEAT_POWER_THRESH_PMTS(v) NVME_GET(v, FEAT_POWER_THRESH_PMTS) -#define NVME_FEAT_POWER_THRESH_EPT(v) NVME_GET(v, FEAT_POWER_THRESH_EPT) - -static inline void nvme_feature_decode_power_mgmt(__u32 value, __u8 *ps, - __u8 *wh) -{ - *ps = NVME_FEAT_PM_PS(value); - *wh = NVME_FEAT_PM_WH(value); -} - -#define NVME_FEAT_LBAR_NR(v) NVME_GET(v, FEAT_LBAR_NR) - -static inline void nvme_feature_decode_lba_range(__u32 value, __u8 *num) -{ - *num = NVME_FEAT_LBAR_NR(value); -} - -#define NVME_FEAT_TT_TMPTH(v) NVME_GET(v, FEAT_TT_TMPTH) -#define NVME_FEAT_TT_TMPSEL(v) NVME_GET(v, FEAT_TT_TMPSEL) -#define NVME_FEAT_TT_THSEL(v) NVME_GET(v, FEAT_TT_THSEL) -#define NVME_FEAT_TT_TMPTHH(v) NVME_GET(v, FEAT_TT_TMPTHH) - -static inline void nvme_feature_decode_temp_threshold(__u32 value, __u16 *tmpth, - __u8 *tmpsel, __u8 *thsel, - __u8 *tmpthh) -{ - *tmpth = NVME_FEAT_TT_TMPTH(value); - *tmpsel = NVME_FEAT_TT_TMPSEL(value); - *thsel = NVME_FEAT_TT_THSEL(value); - *tmpthh = NVME_FEAT_TT_TMPTHH(value); -} - -#define NVME_FEAT_ER_TLER(v) NVME_GET(v, FEAT_ERROR_RECOVERY_TLER) -#define NVME_FEAT_ER_DULBE(v) NVME_GET(v, FEAT_ERROR_RECOVERY_DULBE) - -static inline void nvme_feature_decode_error_recovery(__u32 value, __u16 *tler, - bool *dulbe) -{ - *tler = NVME_FEAT_ER_TLER(value); - *dulbe = NVME_FEAT_ER_DULBE(value); -} - -#define NVME_FEAT_VWC_WCE(v) NVME_GET(v, FEAT_VWC_WCE) - -static inline void nvme_feature_decode_volatile_write_cache(__u32 value, - bool *wce) -{ - *wce = NVME_FEAT_VWC_WCE(value); -} - -#define NVME_FEAT_NRQS_NSQR(v) NVME_GET(v, FEAT_NRQS_NSQR) -#define NVME_FEAT_NRQS_NCQR(v) NVME_GET(v, FEAT_NRQS_NCQR) - -static inline void nvme_feature_decode_number_of_queues(__u32 value, - __u16 *nsqr, - __u16 *ncqr) -{ - *nsqr = NVME_FEAT_NRQS_NSQR(value); - *ncqr = NVME_FEAT_NRQS_NCQR(value); -} - -#define NVME_FEAT_IRQC_THR(v) NVME_GET(v, FEAT_IRQC_THR) -#define NVME_FEAT_IRQC_TIME(v) NVME_GET(v, FEAT_IRQC_TIME) - -static inline void nvme_feature_decode_interrupt_coalescing(__u32 value, - __u8 *thr, - __u8 *time) -{ - *thr = NVME_FEAT_IRQC_THR(value); - *time = NVME_FEAT_IRQC_TIME(value); -} - -#define NVME_FEAT_ICFG_IV(v) NVME_GET(v, FEAT_ICFG_IV) -#define NVME_FEAT_ICFG_CD(v) NVME_GET(v, FEAT_ICFG_CD) - -static inline void nvme_feature_decode_interrupt_config(__u32 value, __u16 *iv, - bool *cd) -{ - *iv = NVME_FEAT_ICFG_IV(value); - *cd = NVME_FEAT_ICFG_CD(value); -} - -#define NVME_FEAT_WA_DN(v) NVME_GET(v, FEAT_WA_DN) - -static inline void nvme_feature_decode_write_atomicity(__u32 value, bool *dn) -{ - *dn = NVME_FEAT_WA_DN(value); -} - -#define NVME_FEAT_AE_SMART(v) NVME_GET(v, FEAT_AE_SMART) -#define NVME_FEAT_AE_NAN(v) NVME_GET(v, FEAT_AE_NAN) -#define NVME_FEAT_AE_FW(v) NVME_GET(v, FEAT_AE_FW) -#define NVME_FEAT_AE_TELEM(v) NVME_GET(v, FEAT_AE_TELEM) -#define NVME_FEAT_AE_ANA(v) NVME_GET(v, FEAT_AE_ANA) -#define NVME_FEAT_AE_PLA(v) NVME_GET(v, FEAT_AE_PLA) -#define NVME_FEAT_AE_LBAS(v) NVME_GET(v, FEAT_AE_LBAS) -#define NVME_FEAT_AE_EGA(v) NVME_GET(v, FEAT_AE_EGA) -#define NVME_FEAT_AE_NNSSHDN(v) NVME_GET(v, FEAT_AE_NNSSHDN) -#define NVME_FEAT_AE_TTHRY(v) NVME_GET(v, FEAT_AE_TTHRY) -#define NVME_FEAT_AE_RASSN(v) NVME_GET(v, FEAT_AE_RASSN) -#define NVME_FEAT_AE_RGRP0(v) NVME_GET(v, FEAT_AE_RGRP0) -#define NVME_FEAT_AE_ANSAN(v) NVME_GET(v, FEAT_AE_ANSAN) -#define NVME_FEAT_AE_ZDCN(v) NVME_GET(v, FEAT_AE_ZDCN) -#define NVME_FEAT_AE_PMDRLPCN(v) NVME_GET(v, FEAT_AE_PMDRLPCN) -#define NVME_FEAT_AE_ADLPCN(v) NVME_GET(v, FEAT_AE_ADLPCN) -#define NVME_FEAT_AE_HDLPCN(v) NVME_GET(v, FEAT_AE_HDLPCN) -#define NVME_FEAT_AE_DLPCN(v) NVME_GET(v, FEAT_AE_DLPCN) - -static inline void nvme_feature_decode_async_event_config(__u32 value, - __u8 *smart, bool *nan, bool *fw, bool *telem, - bool *ana, bool *pla, bool *lbas, bool *ega) -{ - *smart = NVME_FEAT_AE_SMART(value); - *nan = NVME_FEAT_AE_NAN(value); - *fw = NVME_FEAT_AE_FW(value); - *telem = NVME_FEAT_AE_TELEM(value); - *ana = NVME_FEAT_AE_ANA(value); - *pla = NVME_FEAT_AE_PLA(value); - *lbas = NVME_FEAT_AE_LBAS(value); - *ega = NVME_FEAT_AE_EGA(value); -} - -#define NVME_FEAT_APST_APSTE(v) NVME_GET(v, FEAT_APST_APSTE) - -static inline void nvme_feature_decode_auto_power_state(__u32 value, - bool *apste) -{ - *apste = NVME_FEAT_APST_APSTE(value); -} - -#define NVME_FEAT_HMEM_EHM(v) NVME_GET(v, FEAT_HMEM_EHM) - -static inline void nvme_feature_decode_host_memory_buffer(__u32 value, bool *ehm) -{ - *ehm = NVME_FEAT_HMEM_EHM(value); -} - -#define NVME_FEAT_HCTM_TMT2(v) NVME_GET(v, FEAT_HCTM_TMT2) -#define NVME_FEAT_HCTM_TMT1(v) NVME_GET(v, FEAT_HCTM_TMT1) - -static inline void nvme_feature_decode_host_thermal_mgmt(__u32 value, - __u16 *tmt2, - __u16 *tmt1) -{ - *tmt2 = NVME_FEAT_HCTM_TMT2(value); - *tmt1 = NVME_FEAT_HCTM_TMT1(value); -} - -#define NVME_FEAT_NOPS_NOPPME(v) NVME_GET(v, FEAT_NOPS_NOPPME) - -static inline void nvme_feature_decode_non_op_power_config(__u32 value, - bool *noppme) -{ - *noppme = NVME_FEAT_NOPS_NOPPME(value); -} - -#define NVME_FEAT_RRL_RRL(v) NVME_GET(v, FEAT_RRL_RRL) - -static inline void nvme_feature_decode_read_recovery_level_config(__u32 value, - __u8 *rrl) -{ - *rrl = NVME_FEAT_RRL_RRL(value); -} - -#define NVME_FEAT_PLM_LPE(v) NVME_GET(v, FEAT_PLM_LPE) - -static inline void nvme_feature_decode_predictable_latency_mode_config(__u32 value, - bool *lpe) -{ - *lpe = NVME_FEAT_PLM_LPE(value); -} - -#define NVME_FEAT_PLMW_WS(v) NVME_GET(v, FEAT_PLMW_WS) - -static inline void nvme_feature_decode_predictable_latency_mode_window(__u32 value, - __u8 *ws) -{ - *ws = NVME_FEAT_PLMW_WS(value); -} - -#define NVME_FEAT_LBAS_LSIRI(v) NVME_GET(v, FEAT_LBAS_LSIRI) -#define NVME_FEAT_LBAS_LSIPI(v) NVME_GET(v, FEAT_LBAS_LSIPI) - -static inline void nvme_feature_decode_lba_status_attributes(__u32 value, - __u16 *lsiri, - __u16 *lsipi) -{ - *lsiri = NVME_FEAT_LBAS_LSIRI(value); - *lsipi = NVME_FEAT_LBAS_LSIPI(value); -} - -#define NVME_FEAT_SC_NODRM(v) NVME_GET(v, FEAT_SC_NODRM) - -static inline void nvme_feature_decode_sanitize_config(__u32 value, bool *nodrm) -{ - *nodrm = NVME_FEAT_SC_NODRM(value); -} - -#define NVME_FEAT_EG_ENDGID(v) NVME_GET(v, FEAT_EG_ENDGID) -#define NVME_FEAT_EG_EGCW(v) NVME_GET(v, FEAT_EG_EGCW) - -static inline void nvme_feature_decode_endurance_group_event_config(__u32 value, - __u16 *endgid, __u8 *endgcw) -{ - *endgid = NVME_FEAT_EG_ENDGID(value); - *endgcw = NVME_FEAT_EG_EGCW(value); -} - -#define NVME_FEAT_PERFC_ATTRI(v) NVME_GET(v, FEAT_PERFC_ATTRI) -#define NVME_FEAT_PERFC_RVSPA(v) NVME_GET(v, FEAT_PERFC_RVSPA) - -static inline void nvme_feature_decode_perf_characteristics(__u32 value, __u8 *attri, bool *rvspa) -{ - *attri = NVME_FEAT_PERFC_ATTRI(value); - *rvspa = NVME_FEAT_PERFC_RVSPA(value); -} - -#define NVME_FEAT_SPM_PBSLC(v) NVME_GET(v, FEAT_SPM_PBSLC) - -static inline void nvme_feature_decode_software_progress_marker(__u32 value, - __u8 *pbslc) -{ - *pbslc = NVME_FEAT_SPM_PBSLC(value); -} - -#define NVME_FEAT_HOSTID_EXHID(v) NVME_GET(v, FEAT_HOSTID_EXHID) - -static inline void nvme_feature_decode_host_identifier(__u32 value, bool *exhid) -{ - *exhid = NVME_FEAT_HOSTID_EXHID(value); -} - -#define NVME_FEAT_RM_REGPRE(v) NVME_GET(v, FEAT_RM_REGPRE) -#define NVME_FEAT_RM_RESREL(v) NVME_GET(v, FEAT_RM_RESREL) -#define NVME_FEAT_RM_RESPRE(v) NVME_GET(v, FEAT_RM_RESPRE) - -static inline void nvme_feature_decode_reservation_notification(__u32 value, - bool *regpre, - bool *resrel, - bool *respre) -{ - *regpre = NVME_FEAT_RM_REGPRE(value); - *resrel = NVME_FEAT_RM_RESREL(value); - *respre = NVME_FEAT_RM_RESPRE(value); -} - -#define NVME_FEAT_RP_PTPL(v) NVME_GET(v, FEAT_RP_PTPL) - -static inline void nvme_feature_decode_reservation_persistance(__u32 value, - bool *ptpl) -{ - *ptpl = NVME_FEAT_RP_PTPL(value); -} - -#define NVME_FEAT_WP_WPS(v) NVME_GET(v, FEAT_WP_WPS) - -static inline void nvme_feature_decode_namespace_write_protect(__u32 value, - __u8 *wps) -{ - *wps = NVME_FEAT_WP_WPS(value); -} - -#define NVME_FEAT_BPWPC_BP0WPS(v) NVME_GET(v, FEAT_BPWPC_BP0WPS) -#define NVME_FEAT_BPWPC_BP1WPS(v) NVME_GET(v, FEAT_BPWPC_BP1WPS) - -static inline void nvme_id_ns_flbas_to_lbaf_inuse(__u8 flbas, __u8 *lbaf_inuse) -{ - *lbaf_inuse = ((NVME_FLBAS_HIGHER(flbas) << 4) | - NVME_FLBAS_LOWER(flbas)); -} - struct nvme_root; int hostname2traddr(struct nvme_global_ctx *ctx, const char *traddr, char **hostname); @@ -784,5 +369,3 @@ const char *nvme_iface_matching_addr(const struct ifaddrs *iface_list, const cha * Return: true if a match is found, false otherwise. */ bool nvme_iface_primary_addr_matches(const struct ifaddrs *iface_list, const char *iface, const char *addr); - -#endif /* _LIBNVME_UTIL_H */ From 1be23ca1a2fc7db144bf5ed8b1aea94c5da0103d Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Tue, 3 Mar 2026 14:25:19 +0100 Subject: [PATCH 14/29] tree: reduce the number of includes To reduce complexity and dependencies between the header, include the types.h header and drop the rest. Signed-off-by: Daniel Wagner --- libnvme/src/nvme/tree.h | 12 ++---------- libnvme/src/nvme/types.h | 1 + 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/libnvme/src/nvme/tree.h b/libnvme/src/nvme/tree.h index 01ad5e3008..22fb8620c8 100644 --- a/libnvme/src/nvme/tree.h +++ b/libnvme/src/nvme/tree.h @@ -6,18 +6,12 @@ * Authors: Keith Busch * Chaitanya Kulkarni */ - -#ifndef _LIBNVME_TREE_H -#define _LIBNVME_TREE_H +#pragma once #include #include -#include -#include - -#include -#include +#include /** * DOC: tree.h @@ -1516,5 +1510,3 @@ const char *nvme_host_get_hostsymname(nvme_host_t h); * @hostsymname: Symbolic name */ void nvme_host_set_hostsymname(nvme_host_t h, const char *hostsymname); - -#endif /* _LIBNVME_TREE_H */ diff --git a/libnvme/src/nvme/types.h b/libnvme/src/nvme/types.h index 843d6411c7..5cbab978ef 100644 --- a/libnvme/src/nvme/types.h +++ b/libnvme/src/nvme/types.h @@ -15,6 +15,7 @@ #include struct nvme_global_ctx; +struct nvme_passthru_cmd; struct nvme_transport_handle; /** From 765a0b0d95360caf6878293474ab3ec91f09113d Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Tue, 3 Mar 2026 14:28:26 +0100 Subject: [PATCH 15/29] nbft: include nvme/types.h instead nvme/util.h Include nvme/types.h directly instead via nvme/util.h Signed-off-by: Daniel Wagner --- libnvme/src/nvme/nbft.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/libnvme/src/nvme/nbft.h b/libnvme/src/nvme/nbft.h index 871c05ac59..ae86482e14 100644 --- a/libnvme/src/nvme/nbft.h +++ b/libnvme/src/nvme/nbft.h @@ -6,12 +6,11 @@ * Authors: Stuart Hayes * */ -#ifndef _NBFT_H -#define _NBFT_H +#pragma once #include -#include +#include /** * DOC: nbft.h @@ -1252,5 +1251,3 @@ int nvme_nbft_read(struct nvme_global_ctx *ctx, struct nbft_info **nbft, * @nbft: Parsed NBFT table data. */ void nvme_nbft_free(struct nvme_global_ctx *ctx, struct nbft_info *nbft); - -#endif From 32e92c02ff9e1309f67b13245469adf0ecdf4155 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Tue, 3 Mar 2026 17:18:29 +0100 Subject: [PATCH 16/29] crc32: add spdx license tag The crc.[ch] are missing the spdx tag. Signed-off-by: Daniel Wagner --- libnvme/src/nvme/crc32.c | 1 + libnvme/src/nvme/crc32.h | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/libnvme/src/nvme/crc32.c b/libnvme/src/nvme/crc32.c index e726c9f166..2802e95209 100644 --- a/libnvme/src/nvme/crc32.c +++ b/libnvme/src/nvme/crc32.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: LicenseRef-Gary-S-Brown-CRC32 /* * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or * code or tables extracted from it, as desired without restriction. diff --git a/libnvme/src/nvme/crc32.h b/libnvme/src/nvme/crc32.h index 2bdc8fb71c..c53eff181f 100644 --- a/libnvme/src/nvme/crc32.h +++ b/libnvme/src/nvme/crc32.h @@ -1,9 +1,10 @@ -#ifndef crc32_H -#define crc32_H +/* SPDX-License-Identifier: LicenseRef-Gary-S-Brown-CRC32 */ +/* + * This file is part of libnvme. + */ +#pragma once #include #include uint32_t crc32(uint32_t crc, const void *buf, size_t len); - -#endif From d19ada7fee5e31fefbb3dccddea8131f2221ba63 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Tue, 3 Mar 2026 17:26:01 +0100 Subject: [PATCH 17/29] base64: update spdx tag The code is a copy from the nvme-cli project which was licesenced under the GPL-2.0-or-later license. The library is LGPL-2.1-or-later. Hannes agreed to relicense this code. Signed-off-by: Hannes Reinecke Signed-off-by: Daniel Wagner --- libnvme/src/nvme/base64.c | 2 +- libnvme/src/nvme/base64.h | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libnvme/src/nvme/base64.c b/libnvme/src/nvme/base64.c index c02b5fe0b1..c46209707d 100644 --- a/libnvme/src/nvme/base64.c +++ b/libnvme/src/nvme/base64.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0-or-later +// SPDX-License-Identifier: LGPL-2.1-or-later /* * base64.c - RFC4648-compliant base64 encoding * diff --git a/libnvme/src/nvme/base64.h b/libnvme/src/nvme/base64.h index c0f62e2bf9..957f98cef9 100644 --- a/libnvme/src/nvme/base64.h +++ b/libnvme/src/nvme/base64.h @@ -1,8 +1,8 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -#ifndef _BASE64_H -#define _BASE64_H +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * This file is part of libnvme. + */ +#pragma once int base64_encode(const unsigned char *src, int len, char *dst); int base64_decode(const char *src, int len, unsigned char *dst); - -#endif /* _BASE64_H */ From c871d9c6200e59f1a3b4183c026c217295b3a163 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 4 Mar 2026 10:23:08 +0100 Subject: [PATCH 18/29] log: drop the tree.h header include The dependency on including the root object has been removed, thus drop the include. Signed-off-by: Daniel Wagner --- libnvme/src/nvme/log.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/libnvme/src/nvme/log.h b/libnvme/src/nvme/log.h index bfeb749d59..bdc5f9680a 100644 --- a/libnvme/src/nvme/log.h +++ b/libnvme/src/nvme/log.h @@ -2,14 +2,14 @@ /* * Copyright (c) 2021 Martin Wilck, SUSE LLC */ -#ifndef _LOG_H -#define _LOG_H +#pragma once #include #include +#include -/* for nvme_root_t */ -#include +struct nvme_global_ctx; +struct nvme_transport_handle; #ifndef MAX_LOGLEVEL # define MAX_LOGLEVEL LOG_DEBUG @@ -63,5 +63,3 @@ void nvme_init_default_logging(FILE *fp, int lvl, bool log_pid, */ int nvme_get_logging_level(struct nvme_global_ctx *ctx, bool *log_pid, bool *log_tstamp); - -#endif /* _LOG_H */ From 7109dd3bfa32d427b099c4e6a67dbf54f7131779 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 4 Mar 2026 10:28:17 +0100 Subject: [PATCH 19/29] mi: drop the types.h include The tree.h included already does include types.h. Thus it's possible to drop this include. Signed-off-by: Daniel Wagner --- libnvme/src/nvme/mi.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/libnvme/src/nvme/mi.h b/libnvme/src/nvme/mi.h index 732f471bed..bab5c3077f 100644 --- a/libnvme/src/nvme/mi.h +++ b/libnvme/src/nvme/mi.h @@ -80,14 +80,11 @@ * 1.1, where possible. * */ - -#ifndef _LIBNVME_MI_MI_H -#define _LIBNVME_MI_MI_H +#pragma once #include #include -#include #include /** @@ -1552,5 +1549,3 @@ int nvme_mi_aem_disable(nvme_mi_ep_t ep); * Return: 0 is a success, nonzero is an error and errno may be read for further details */ int nvme_mi_aem_process(nvme_mi_ep_t ep, void *userdata); - -#endif /* _LIBNVME_MI_MI_H */ From 09e54014eaa06e7a93a9d73e7a5d110a5d399fcd Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 4 Mar 2026 11:22:20 +0100 Subject: [PATCH 20/29] lib: move library definition into new headers Refactor all library specific definitions and declarations into two headers. lib-types.h contains the forward declarations for all types used in libnvme. lib.h contains the interfaces and declarations that need to interact with the library. Signed-off-by: Daniel Wagner --- libnvme/src/libnvme.h | 12 +- libnvme/src/meson.build | 3 + libnvme/src/nvme/ioctl.h | 4 +- libnvme/src/nvme/lib-types.h | 13 ++ libnvme/src/nvme/lib.c | 269 +++++++++++++++++++++++++++++++++++ libnvme/src/nvme/lib.h | 192 +++++++++++++++++++++++++ libnvme/src/nvme/linux.c | 196 ------------------------- libnvme/src/nvme/linux.h | 164 +-------------------- libnvme/src/nvme/log.h | 3 +- libnvme/src/nvme/nbft.h | 5 +- libnvme/src/nvme/private.h | 2 + libnvme/src/nvme/tree.c | 50 +------ libnvme/src/nvme/tree.h | 1 + libnvme/src/nvme/types.h | 21 --- libnvme/src/nvme/util.h | 1 + libnvme/test/meson.build | 2 + 16 files changed, 499 insertions(+), 439 deletions(-) create mode 100644 libnvme/src/nvme/lib-types.h create mode 100644 libnvme/src/nvme/lib.c create mode 100644 libnvme/src/nvme/lib.h diff --git a/libnvme/src/libnvme.h b/libnvme/src/libnvme.h index f7f52d0adb..ba936ecb50 100644 --- a/libnvme/src/libnvme.h +++ b/libnvme/src/libnvme.h @@ -14,16 +14,18 @@ extern "C" { #endif -#include #include -#include -#include -#include #include #include +#include +#include +#include +#include +#include +#include #include +#include #include -#include #ifdef __cplusplus } diff --git a/libnvme/src/meson.build b/libnvme/src/meson.build index b63b4c67ec..3572bd0aae 100644 --- a/libnvme/src/meson.build +++ b/libnvme/src/meson.build @@ -12,6 +12,7 @@ sources = [ 'nvme/fabrics.c', 'nvme/filters.c', 'nvme/ioctl.c', + 'nvme/lib.c', 'nvme/linux.c', 'nvme/log.c', 'nvme/mi-mctp.c', @@ -101,6 +102,8 @@ install_headers( 'nvme/fabrics.h', 'nvme/filters.h', 'nvme/ioctl.h', + 'nvme/lib-types.h', + 'nvme/lib.h', 'nvme/linux.h', 'nvme/log.h', 'nvme/mi.h', diff --git a/libnvme/src/nvme/ioctl.h b/libnvme/src/nvme/ioctl.h index a596d3dd14..b84631f7ad 100644 --- a/libnvme/src/nvme/ioctl.h +++ b/libnvme/src/nvme/ioctl.h @@ -11,6 +11,8 @@ #include +#include + /** * DOC: ioctl.h * @@ -117,8 +119,6 @@ struct nvme_uring_cmd { __u32 rsvd2; }; -struct nvme_transport_handle; - /** * nvme_submit_admin_passthru() - Submit an nvme passthrough admin command * @hdl: Transport handle diff --git a/libnvme/src/nvme/lib-types.h b/libnvme/src/nvme/lib-types.h new file mode 100644 index 0000000000..97663847f5 --- /dev/null +++ b/libnvme/src/nvme/lib-types.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * This file is part of libnvme. + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + * + * Authors: Keith Busch + * Chaitanya Kulkarni + */ +#pragma once + +struct nvme_global_ctx; +struct nvme_passthru_cmd; +struct nvme_transport_handle; diff --git a/libnvme/src/nvme/lib.c b/libnvme/src/nvme/lib.c new file mode 100644 index 0000000000..b19ed81bb9 --- /dev/null +++ b/libnvme/src/nvme/lib.c @@ -0,0 +1,269 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/* + * This file is part of libnvme. + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + * + * Authors: Keith Busch + * Chaitanya Kulkarni + */ + +#include + +#include "cleanup.h" +#include "private.h" + +#include +#include +#include + +struct nvme_global_ctx *nvme_create_global_ctx(FILE *fp, int log_level) +{ + struct nvme_global_ctx *ctx; + int fd; + + ctx = calloc(1, sizeof(*ctx)); + if (!ctx) + return NULL; + + if (fp) { + fd = fileno(fp); + if (fd < 0) { + free(ctx); + return NULL; + } + } else + fd = STDERR_FILENO; + + ctx->log.fd = fd; + ctx->log.level = log_level; + + list_head_init(&ctx->hosts); + list_head_init(&ctx->endpoints); + + ctx->ioctl_probing = true; + + return ctx; +} + +void nvme_free_global_ctx(struct nvme_global_ctx *ctx) +{ + struct nvme_host *h, *_h; + + if (!ctx) + return; + + freeifaddrs(ctx->ifaddrs_cache); /* NULL-safe */ + ctx->ifaddrs_cache = NULL; + + free(ctx->options); + nvme_for_each_host_safe(ctx, h, _h) + __nvme_free_host(h); + free(ctx->config_file); + free(ctx->application); + free(ctx); +} + +void nvme_set_dry_run(struct nvme_global_ctx *ctx, bool enable) +{ + ctx->dry_run = enable; +} + +void nvme_set_ioctl_probing(struct nvme_global_ctx *ctx, bool enable) +{ + ctx->ioctl_probing = enable; +} + +void nvme_transport_handle_set_submit_entry(struct nvme_transport_handle *hdl, + void *(*submit_entry)(struct nvme_transport_handle *hdl, + struct nvme_passthru_cmd *cmd)) +{ + hdl->submit_entry = submit_entry; + if (!hdl->submit_exit) + hdl->submit_exit = __nvme_submit_exit; +} + +void nvme_transport_handle_set_submit_exit(struct nvme_transport_handle *hdl, + void (*submit_exit)(struct nvme_transport_handle *hdl, + struct nvme_passthru_cmd *cmd, + int err, void *user_data)) +{ + hdl->submit_exit = submit_exit; + if (!hdl->submit_exit) + hdl->submit_exit = __nvme_submit_exit; +} + +void nvme_transport_handle_set_decide_retry(struct nvme_transport_handle *hdl, + bool (*decide_retry)(struct nvme_transport_handle *hdl, + struct nvme_passthru_cmd *cmd, int err)) +{ + hdl->decide_retry = decide_retry; + if (!hdl->decide_retry) + hdl->decide_retry = __nvme_decide_retry; +} + +static int __nvme_transport_handle_open_direct( + struct nvme_transport_handle *hdl, const char *devname) +{ + struct nvme_passthru_cmd dummy = { 0 }; + _cleanup_free_ char *path = NULL; + _cleanup_free_ char *_devname = NULL; + char *name; + int ret, id, ns; + bool c = true; + + _devname = strdup(devname); + if (!_devname) + return -ENOMEM; + name = basename(_devname); + + hdl->type = NVME_TRANSPORT_HANDLE_TYPE_DIRECT; + + ret = sscanf(name, "nvme%dn%d", &id, &ns); + if (ret == 2) + c = false; + else if (ret != 1 && sscanf(name, "ng%dn%d", &id, &ns) != 2) + return -EINVAL; + + ret = asprintf(&path, "%s/%s", "/dev", name); + if (ret < 0) + return -ENOMEM; + + hdl->fd = open(path, O_RDONLY); + if (hdl->fd < 0) + return -errno; + + ret = fstat(hdl->fd, &hdl->stat); + if (ret < 0) + return -errno; + + if (c) { + if (!S_ISCHR(hdl->stat.st_mode)) + return -EINVAL; + } else if (!S_ISBLK(hdl->stat.st_mode)) { + return -EINVAL; + } + + if (hdl->ctx->ioctl_probing) { + ret = ioctl(hdl->fd, NVME_IOCTL_ADMIN64_CMD, &dummy); + if (ret > 0) + hdl->ioctl64 = true; + } + + return 0; +} + +void __nvme_transport_handle_close_direct(struct nvme_transport_handle *hdl) +{ + close(hdl->fd); + free(hdl); +} + +struct nvme_transport_handle *__nvme_create_transport_handle( + struct nvme_global_ctx *ctx) +{ + struct nvme_transport_handle *hdl; + + hdl = calloc(1, sizeof(*hdl)); + if (!hdl) + return NULL; + + hdl->ctx = ctx; + hdl->submit_entry = __nvme_submit_entry; + hdl->submit_exit = __nvme_submit_exit; + hdl->decide_retry = __nvme_decide_retry; + + return hdl; +} + +int nvme_open(struct nvme_global_ctx *ctx, const char *name, + struct nvme_transport_handle **hdlp) +{ + struct nvme_transport_handle *hdl; + int ret; + + hdl = __nvme_create_transport_handle(ctx); + if (!hdl) + return -ENOMEM; + + hdl->name = strdup(name); + if (!hdl->name) { + free(hdl); + return -ENOMEM; + } + + if (!strncmp(name, "NVME_TEST_FD", 12)) { + hdl->type = NVME_TRANSPORT_HANDLE_TYPE_DIRECT; + hdl->fd = 0xFD; + + if (!strcmp(name, "NVME_TEST_FD64")) + hdl->ioctl64 = true; + + *hdlp = hdl; + return 0; + } + + if (!strncmp(name, "mctp:", strlen("mctp:"))) + ret = __nvme_transport_handle_open_mi(hdl, name); + else + ret = __nvme_transport_handle_open_direct(hdl, name); + + if (ret) { + nvme_close(hdl); + return ret; + } + + *hdlp = hdl; + + return 0; +} + +void nvme_close(struct nvme_transport_handle *hdl) +{ + if (!hdl) + return; + + free(hdl->name); + + switch (hdl->type) { + case NVME_TRANSPORT_HANDLE_TYPE_DIRECT: + __nvme_transport_handle_close_direct(hdl); + break; + case NVME_TRANSPORT_HANDLE_TYPE_MI: + __nvme_transport_handle_close_mi(hdl); + break; + case NVME_TRANSPORT_HANDLE_TYPE_UNKNOWN: + free(hdl); + break; + } +} + +int nvme_transport_handle_get_fd(struct nvme_transport_handle *hdl) +{ + return hdl->fd; +} + +const char *nvme_transport_handle_get_name(struct nvme_transport_handle *hdl) +{ + return basename(hdl->name); +} + +bool nvme_transport_handle_is_blkdev(struct nvme_transport_handle *hdl) +{ + return S_ISBLK(hdl->stat.st_mode); +} + +bool nvme_transport_handle_is_chardev(struct nvme_transport_handle *hdl) +{ + return S_ISCHR(hdl->stat.st_mode); +} + +bool nvme_transport_handle_is_direct(struct nvme_transport_handle *hdl) +{ + return hdl->type == NVME_TRANSPORT_HANDLE_TYPE_DIRECT; +} + +bool nvme_transport_handle_is_mi(struct nvme_transport_handle *hdl) +{ + return hdl->type == NVME_TRANSPORT_HANDLE_TYPE_MI; +} + diff --git a/libnvme/src/nvme/lib.h b/libnvme/src/nvme/lib.h new file mode 100644 index 0000000000..9da0a69fee --- /dev/null +++ b/libnvme/src/nvme/lib.h @@ -0,0 +1,192 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * This file is part of libnvme. + * Copyright (c) 2020 Western Digital Corporation or its affiliates. + * + * Authors: Keith Busch + * Chaitanya Kulkarni + */ +#pragma once + +#include +#include + +#include + +/** + * nvme_create_global_ctx() - Initialize global context object + * @fp: File descriptor for logging messages + * @log_level: Logging level to use + * + * Return: Initialized &struct nvme_global_ctx object + */ +struct nvme_global_ctx *nvme_create_global_ctx(FILE *fp, int log_level); + +/** + * nvme_free_global_ctx() - Free global context object + * @ctx: &struct nvme_global_ctx object + * + * Free an &struct nvme_global_ctx object and all attached objects + */ +void nvme_free_global_ctx(struct nvme_global_ctx *ctx); + +/** + * nvme_open() - Open an nvme controller or namespace device + * @ctx: struct nvme_global_ctx object + * @name: The basename of the device to open + * @hdl: Transport handle to return + * + * This will look for the handle in /dev/ and validate the name and filetype + * match linux conventions. + * + * Return: 0 on success or negative error code otherwise + */ +int nvme_open(struct nvme_global_ctx *ctx, const char *name, + struct nvme_transport_handle **hdl); + +/** + * nvme_close() - Close transport handle + * @hdl: Transport handle + */ +void nvme_close(struct nvme_transport_handle *hdl); + +/** + * nvme_transport_handle_get_fd - Return file descriptor from transport handle + * @hdl: Transport handle + * + * If the device handle is for a ioctl based device, + * nvme_transport_handle_get_fd will return a valid file descriptor. + * + * Return: File descriptor for an IOCTL based transport handle, otherwise -1. + */ +int nvme_transport_handle_get_fd(struct nvme_transport_handle *hdl); + +/** + * nvme_transport_handle_get_name - Return name of the device transport handle + * @hdl: Transport handle + * + * Return: Device file name, otherwise -1. + */ +const char *nvme_transport_handle_get_name(struct nvme_transport_handle *hdl); + +/** + * nvme_transport_handle_is_blkdev - Check if transport handle is a block device + * @hdl: Transport handle + * + * Return: Return true if transport handle is a block device, otherwise false. + */ +bool nvme_transport_handle_is_blkdev(struct nvme_transport_handle *hdl); + +/** + * nvme_transport_handle_is_chardev - Check if transport handle is a char device + * @hdl: Transport handle + * + * Return: Return true if transport handle is a char device, otherwise false. + */ +bool nvme_transport_handle_is_chardev(struct nvme_transport_handle *hdl); + +/** + * nvme_transport_handle_is_direct - Check if transport handle is using IOCTL + * interface + * @hdl: Transport handle + * + * Return: Return true if transport handle is using IOCTL itnerface, + * otherwise false. + */ +bool nvme_transport_handle_is_direct(struct nvme_transport_handle *hdl); + +/** + * nvme_transport_handle_is_mi - Check if transport handle is a using MI + * interface + * @hdl: Transport handle + * + * Return: Return true if transport handle is using MI interface, + * otherwise false. + */ +bool nvme_transport_handle_is_mi(struct nvme_transport_handle *hdl); + +/** + * nvme_transport_handle_set_submit_entry() - Install a submit-entry callback + * @hdl: Transport handle to configure + * @submit_entry: Callback invoked immediately before a passthrough command is + * submitted. The function receives the command about to be issued + * and may return an opaque pointer representing per-command + * context. This pointer is later passed unmodified to the + * submit-exit callback. Implementations typically use this hook + * for logging, tracing, or allocating per-command state. + * + * Installs a user-defined callback that is invoked at the moment a passthrough + * command enters the NVMe submission path. Passing NULL removes any previously + * installed callback. + * + * Return: None. + */ +void nvme_transport_handle_set_submit_entry(struct nvme_transport_handle *hdl, + void *(*submit_entry)(struct nvme_transport_handle *hdl, + struct nvme_passthru_cmd *cmd)); + +/** + * nvme_transport_handle_set_submit_exit() - Install a submit-exit callback + * @hdl: Transport handle to configure + * @submit_exit: Callback invoked after a passthrough command completes. The + * function receives the command, the completion status @err + * (0 for success, a negative errno, or an NVMe status value), and + * the @user_data pointer returned earlier by the submit-entry + * callback. Implementations typically use this hook for logging, + * tracing, or freeing per-command state. + * + * Installs a callback that is invoked when a passthrough command leaves the + * NVMe submission path. Passing NULL removes any previously installed callback. + * + * Return: None. + */ +void nvme_transport_handle_set_submit_exit(struct nvme_transport_handle *hdl, + void (*submit_exit)(struct nvme_transport_handle *hdl, + struct nvme_passthru_cmd *cmd, + int err, void *user_data)); + +/** + * nvme_transport_handle_set_decide_retry() - Install a retry-decision callback + * @hdl: Transport handle to configure + * @decide_retry: Callback used to determine whether a passthrough command + * should be retried after an error. The function is called with + * the command that failed and the error code returned by the + * kernel or device. The callback should return true if the + * submission path should retry the command, or false if the + * error is final. + * + * Installs a user-provided callback to control retry behavior for + * passthrough commands issued through @hdl. This allows transports or + * higher-level logic to implement custom retry policies, such as retrying on + * transient conditions like -EAGAIN or device-specific status codes. + * + * Passing NULL clears any previously installed callback and reverts to the + * default behavior (no retries). + * + * Return: None. + */ +void nvme_transport_handle_set_decide_retry(struct nvme_transport_handle *hdl, + bool (*decide_retry)(struct nvme_transport_handle *hdl, + struct nvme_passthru_cmd *cmd, int err)); + +/** + * nvme_set_dry_run() - Set global dry run state + * @ctx: struct nvme_global_ctx object + * @enable: Enable/disable dry run state + * + * When dry_run is enabled, any IOCTL commands send via the passthru + * interface won't be executed. + */ +void nvme_set_dry_run(struct nvme_global_ctx *ctx, bool enable); + +/** + * nvme_set_ioctl_probing() - Enable/disable 64-bit IOCTL probing + * @ctx: struct nvme_global_ctx object + * @enable: Enable/disable 64-bit IOCTL probing + * + * When IOCTL probing is enabled, a 64-bit IOCTL command is issued to + * figure out if the passthru interface supports it. + * + * IOCTL probing is enabled per default. + */ +void nvme_set_ioctl_probing(struct nvme_global_ctx *ctx, bool enable); diff --git a/libnvme/src/nvme/linux.c b/libnvme/src/nvme/linux.c index 7059d701c4..a9f83a0fd8 100644 --- a/libnvme/src/nvme/linux.c +++ b/libnvme/src/nvme/linux.c @@ -42,202 +42,6 @@ #include "cleanup.h" #include "private.h" -void nvme_set_dry_run(struct nvme_global_ctx *ctx, bool enable) -{ - ctx->dry_run = enable; -} - -void nvme_set_ioctl_probing(struct nvme_global_ctx *ctx, bool enable) -{ - ctx->ioctl_probing = enable; -} - -void nvme_transport_handle_set_submit_entry(struct nvme_transport_handle *hdl, - void *(*submit_entry)(struct nvme_transport_handle *hdl, - struct nvme_passthru_cmd *cmd)) -{ - hdl->submit_entry = submit_entry; - if (!hdl->submit_exit) - hdl->submit_exit = __nvme_submit_exit; -} - -void nvme_transport_handle_set_submit_exit(struct nvme_transport_handle *hdl, - void (*submit_exit)(struct nvme_transport_handle *hdl, - struct nvme_passthru_cmd *cmd, - int err, void *user_data)) -{ - hdl->submit_exit = submit_exit; - if (!hdl->submit_exit) - hdl->submit_exit = __nvme_submit_exit; -} - -void nvme_transport_handle_set_decide_retry(struct nvme_transport_handle *hdl, - bool (*decide_retry)(struct nvme_transport_handle *hdl, - struct nvme_passthru_cmd *cmd, int err)) -{ - hdl->decide_retry = decide_retry; - if (!hdl->decide_retry) - hdl->decide_retry = __nvme_decide_retry; -} - -static int __nvme_transport_handle_open_direct(struct nvme_transport_handle *hdl, const char *devname) -{ - struct nvme_passthru_cmd dummy = { 0 }; - _cleanup_free_ char *path = NULL; - char *name = basename(devname); - int ret, id, ns; - bool c = true; - - hdl->type = NVME_TRANSPORT_HANDLE_TYPE_DIRECT; - - ret = sscanf(name, "nvme%dn%d", &id, &ns); - if (ret == 2) - c = false; - else if (ret != 1 && sscanf(name, "ng%dn%d", &id, &ns) != 2) - return -EINVAL; - - ret = asprintf(&path, "%s/%s", "/dev", name); - if (ret < 0) - return -ENOMEM; - - hdl->fd = open(path, O_RDONLY); - if (hdl->fd < 0) - return -errno; - - ret = fstat(hdl->fd, &hdl->stat); - if (ret < 0) - return -errno; - - if (c) { - if (!S_ISCHR(hdl->stat.st_mode)) - return -EINVAL; - } else if (!S_ISBLK(hdl->stat.st_mode)) { - return -EINVAL; - } - - if (hdl->ctx->ioctl_probing) { - ret = ioctl(hdl->fd, NVME_IOCTL_ADMIN64_CMD, &dummy); - if (ret > 0) - hdl->ioctl64 = true; - } - - return 0; -} - -void __nvme_transport_handle_close_direct(struct nvme_transport_handle *hdl) -{ - close(hdl->fd); - free(hdl); -} - -struct nvme_transport_handle *__nvme_create_transport_handle(struct nvme_global_ctx *ctx) -{ - struct nvme_transport_handle *hdl; - - hdl = calloc(1, sizeof(*hdl)); - if (!hdl) - return NULL; - - hdl->ctx = ctx; - hdl->submit_entry = __nvme_submit_entry; - hdl->submit_exit = __nvme_submit_exit; - hdl->decide_retry = __nvme_decide_retry; - - return hdl; -} - -int nvme_open(struct nvme_global_ctx *ctx, const char *name, - struct nvme_transport_handle **hdlp) -{ - struct nvme_transport_handle *hdl; - int ret; - - hdl = __nvme_create_transport_handle(ctx); - if (!hdl) - return -ENOMEM; - - hdl->name = strdup(name); - if (!hdl->name) { - free(hdl); - return -ENOMEM; - } - - if (!strncmp(name, "NVME_TEST_FD", 12)) { - hdl->type = NVME_TRANSPORT_HANDLE_TYPE_DIRECT; - hdl->fd = 0xFD; - - if (!strcmp(name, "NVME_TEST_FD64")) - hdl->ioctl64 = true; - - *hdlp = hdl; - return 0; - } - - if (!strncmp(name, "mctp:", strlen("mctp:"))) - ret = __nvme_transport_handle_open_mi(hdl, name); - else - ret = __nvme_transport_handle_open_direct(hdl, name); - - if (ret) { - nvme_close(hdl); - return ret; - } - - *hdlp = hdl; - - return 0; -} - -void nvme_close(struct nvme_transport_handle *hdl) -{ - if (!hdl) - return; - - free(hdl->name); - - switch (hdl->type) { - case NVME_TRANSPORT_HANDLE_TYPE_DIRECT: - __nvme_transport_handle_close_direct(hdl); - break; - case NVME_TRANSPORT_HANDLE_TYPE_MI: - __nvme_transport_handle_close_mi(hdl); - break; - case NVME_TRANSPORT_HANDLE_TYPE_UNKNOWN: - free(hdl); - break; - } -} - -int nvme_transport_handle_get_fd(struct nvme_transport_handle *hdl) -{ - return hdl->fd; -} - -const char *nvme_transport_handle_get_name(struct nvme_transport_handle *hdl) -{ - return basename(hdl->name); -} - -bool nvme_transport_handle_is_blkdev(struct nvme_transport_handle *hdl) -{ - return S_ISBLK(hdl->stat.st_mode); -} - -bool nvme_transport_handle_is_chardev(struct nvme_transport_handle *hdl) -{ - return S_ISCHR(hdl->stat.st_mode); -} - -bool nvme_transport_handle_is_direct(struct nvme_transport_handle *hdl) -{ - return hdl->type == NVME_TRANSPORT_HANDLE_TYPE_DIRECT; -} - -bool nvme_transport_handle_is_mi(struct nvme_transport_handle *hdl) -{ - return hdl->type == NVME_TRANSPORT_HANDLE_TYPE_MI; -} - static int __nvme_set_attr(const char *path, const char *value) { _cleanup_fd_ int fd = -1; diff --git a/libnvme/src/nvme/linux.h b/libnvme/src/nvme/linux.h index 73735713be..9070cbcda7 100644 --- a/libnvme/src/nvme/linux.h +++ b/libnvme/src/nvme/linux.h @@ -11,153 +11,13 @@ #include #include -struct nvme_transport_handle; -struct nvme_passthru_cmd; -struct nvme_global_ctx; +#include /** * DOC: linux.h * * linux-specific utility functions */ - -/** - * nvme_open() - Open an nvme controller or namespace device - * @ctx: struct nvme_global_ctx object - * @name: The basename of the device to open - * @hdl: Transport handle to return - * - * This will look for the handle in /dev/ and validate the name and filetype - * match linux conventions. - * - * Return: 0 on success or negative error code otherwise - */ -int nvme_open(struct nvme_global_ctx *ctx, const char *name, - struct nvme_transport_handle **hdl); - -/** - * nvme_close() - Close transport handle - * @hdl: Transport handle - */ -void nvme_close(struct nvme_transport_handle *hdl); - -/** - * nvme_transport_handle_get_fd - Return file descriptor from transport handle - * @hdl: Transport handle - * - * If the device handle is for a ioctl based device, - * nvme_transport_handle_get_fd will return a valid file descriptor. - * - * Return: File descriptor for an IOCTL based transport handle, otherwise -1. - */ -int nvme_transport_handle_get_fd(struct nvme_transport_handle *hdl); - -/** - * nvme_transport_handle_get_name - Return name of the device transport handle - * @hdl: Transport handle - * - * Return: Device file name, otherwise -1. - */ -const char *nvme_transport_handle_get_name(struct nvme_transport_handle *hdl); - -/** - * nvme_transport_handle_is_blkdev - Check if transport handle is a block device - * @hdl: Transport handle - * - * Return: Return true if transport handle is a block device, otherwise false. - */ -bool nvme_transport_handle_is_blkdev(struct nvme_transport_handle *hdl); - -/** - * nvme_transport_handle_is_chardev - Check if transport handle is a char device - * @hdl: Transport handle - * - * Return: Return true if transport handle is a char device, otherwise false. - */ -bool nvme_transport_handle_is_chardev(struct nvme_transport_handle *hdl); - -/** - * nvme_transport_handle_is_direct - Check if transport handle is using IOCTL interface - * @hdl: Transport handle - * - * Return: Return true if transport handle is using IOCTL itnerface, - * otherwise false. - */ -bool nvme_transport_handle_is_direct(struct nvme_transport_handle *hdl); - -/** - * nvme_transport_handle_is_mi - Check if transport handle is a using MI interface - * @hdl: Transport handle - * - * Return: Return true if transport handle is using MI interface, - * otherwise false. - */ -bool nvme_transport_handle_is_mi(struct nvme_transport_handle *hdl); - -/** - * nvme_transport_handle_set_submit_entry() - Install a submit-entry callback - * @hdl: Transport handle to configure - * @submit_entry: Callback invoked immediately before a passthrough command is - * submitted. The function receives the command about to be issued - * and may return an opaque pointer representing per-command - * context. This pointer is later passed unmodified to the - * submit-exit callback. Implementations typically use this hook - * for logging, tracing, or allocating per-command state. - * - * Installs a user-defined callback that is invoked at the moment a passthrough - * command enters the NVMe submission path. Passing NULL removes any previously - * installed callback. - * - * Return: None. - */ -void nvme_transport_handle_set_submit_entry(struct nvme_transport_handle *hdl, - void *(*submit_entry)(struct nvme_transport_handle *hdl, - struct nvme_passthru_cmd *cmd)); - -/** - * nvme_transport_handle_set_submit_exit() - Install a submit-exit callback - * @hdl: Transport handle to configure - * @submit_exit: Callback invoked after a passthrough command completes. The - * function receives the command, the completion status @err - * (0 for success, a negative errno, or an NVMe status value), and - * the @user_data pointer returned earlier by the submit-entry - * callback. Implementations typically use this hook for logging, - * tracing, or freeing per-command state. - * - * Installs a callback that is invoked when a passthrough command leaves the - * NVMe submission path. Passing NULL removes any previously installed callback. - * - * Return: None. - */ -void nvme_transport_handle_set_submit_exit(struct nvme_transport_handle *hdl, - void (*submit_exit)(struct nvme_transport_handle *hdl, - struct nvme_passthru_cmd *cmd, - int err, void *user_data)); - -/** - * nvme_transport_handle_set_decide_retry() - Install a retry-decision callback - * @hdl: Transport handle to configure - * @decide_retry: Callback used to determine whether a passthrough command - * should be retried after an error. The function is called with - * the command that failed and the error code returned by the - * kernel or device. The callback should return true if the - * submission path should retry the command, or false if the - * error is final. - * - * Installs a user-provided callback to control retry behavior for - * passthrough commands issued through @hdl. This allows transports or - * higher-level logic to implement custom retry policies, such as retrying on - * transient conditions like -EAGAIN or device-specific status codes. - * - * Passing NULL clears any previously installed callback and reverts to the - * default behavior (no retries). - * - * Return: None. - */ -void nvme_transport_handle_set_decide_retry(struct nvme_transport_handle *hdl, - bool (*decide_retry)(struct nvme_transport_handle *hdl, - struct nvme_passthru_cmd *cmd, int err)); - /** * enum nvme_hmac_alg - HMAC algorithm * @NVME_HMAC_ALG_NONE: No HMAC algorithm @@ -533,25 +393,3 @@ int nvme_import_tls_key(struct nvme_global_ctx *ctx, const char *encoded_key, int nvme_import_tls_key_versioned(struct nvme_global_ctx *ctx, const char *encoded_key, unsigned char *version, unsigned char *hmac, size_t *key_len, unsigned char **key); - -/** - * nvme_set_dry_run() - Set global dry run state - * @ctx: struct nvme_global_ctx object - * @enable: Enable/disable dry run state - * - * When dry_run is enabled, any IOCTL commands send via the passthru - * interface wont be executed. - */ -void nvme_set_dry_run(struct nvme_global_ctx *ctx, bool enable); - -/** - * nvme_set_ioctl_probing() - Enable/disable 64-bit IOCTL probing - * @ctx: struct nvme_global_ctx object - * @enable: Enable/disable 64-bit IOCTL probing - * - * When IOCTL probing is enabled, a 64-bit IOCTL command is issued to - * figure out if the passthru interface supports it. - * - * IOCTL probing is enabled per default. - */ -void nvme_set_ioctl_probing(struct nvme_global_ctx *ctx, bool enable); diff --git a/libnvme/src/nvme/log.h b/libnvme/src/nvme/log.h index bdc5f9680a..bb8047ec5f 100644 --- a/libnvme/src/nvme/log.h +++ b/libnvme/src/nvme/log.h @@ -8,8 +8,7 @@ #include #include -struct nvme_global_ctx; -struct nvme_transport_handle; +#include #ifndef MAX_LOGLEVEL # define MAX_LOGLEVEL LOG_DEBUG diff --git a/libnvme/src/nvme/nbft.h b/libnvme/src/nvme/nbft.h index ae86482e14..79ae801446 100644 --- a/libnvme/src/nvme/nbft.h +++ b/libnvme/src/nvme/nbft.h @@ -8,9 +8,12 @@ */ #pragma once +#include #include -#include +#include + +#include /** * DOC: nbft.h diff --git a/libnvme/src/nvme/private.h b/libnvme/src/nvme/private.h index b7c5ccf81e..67f816760d 100644 --- a/libnvme/src/nvme/private.h +++ b/libnvme/src/nvme/private.h @@ -443,6 +443,8 @@ nvme_ctrl_t nvme_ctrl_find(nvme_subsystem_t s, const char *transport, const char *subsysnqn, const char *host_traddr, const char *host_iface); +void __nvme_free_host(nvme_host_t h); + #if (LOG_FUNCNAME == 1) #define __nvme_log_func __func__ #else diff --git a/libnvme/src/nvme/tree.c b/libnvme/src/nvme/tree.c index 9ed3375e3b..8cdc1321ef 100644 --- a/libnvme/src/nvme/tree.c +++ b/libnvme/src/nvme/tree.c @@ -56,7 +56,6 @@ struct candidate_args { }; typedef bool (*ctrl_match_t)(struct nvme_ctrl *c, struct candidate_args *candidate); -static void __nvme_free_host(nvme_host_t h); static void __nvme_free_ctrl(nvme_ctrl_t c); static int nvme_subsystem_scan_namespace(struct nvme_global_ctx *ctx, struct nvme_subsystem *s, char *name); @@ -324,35 +323,6 @@ int nvme_scan_topology(struct nvme_global_ctx *ctx, nvme_scan_filter_t f, void * return 0; } -struct nvme_global_ctx *nvme_create_global_ctx(FILE *fp, int log_level) -{ - struct nvme_global_ctx *ctx; - int fd; - - ctx = calloc(1, sizeof(*ctx)); - if (!ctx) - return NULL; - - if (fp) { - fd = fileno(fp); - if (fd < 0) { - free(ctx); - return NULL; - } - } else - fd = STDERR_FILENO; - - ctx->log.fd = fd; - ctx->log.level = log_level; - - list_head_init(&ctx->hosts); - list_head_init(&ctx->endpoints); - - ctx->ioctl_probing = true; - - return ctx; -} - int nvme_read_config(struct nvme_global_ctx *ctx, const char *config_file) { int err; @@ -515,24 +485,6 @@ void nvme_refresh_topology(struct nvme_global_ctx *ctx) nvme_scan_topology(ctx, NULL, NULL); } -void nvme_free_global_ctx(struct nvme_global_ctx *ctx) -{ - struct nvme_host *h, *_h; - - if (!ctx) - return; - - freeifaddrs(ctx->ifaddrs_cache); /* NULL-safe */ - ctx->ifaddrs_cache = NULL; - - free(ctx->options); - nvme_for_each_host_safe(ctx, h, _h) - __nvme_free_host(h); - free(ctx->config_file); - free(ctx->application); - free(ctx); -} - void nvme_root_release_fds(struct nvme_global_ctx *ctx) { struct nvme_host *h, *_h; @@ -758,7 +710,7 @@ int nvme_subsystem_get(struct nvme_global_ctx *ctx, return 0; } -static void __nvme_free_host(struct nvme_host *h) +void __nvme_free_host(struct nvme_host *h) { struct nvme_subsystem *s, *_s; diff --git a/libnvme/src/nvme/tree.h b/libnvme/src/nvme/tree.h index 22fb8620c8..cad6b34387 100644 --- a/libnvme/src/nvme/tree.h +++ b/libnvme/src/nvme/tree.h @@ -11,6 +11,7 @@ #include #include +#include #include /** diff --git a/libnvme/src/nvme/types.h b/libnvme/src/nvme/types.h index 5cbab978ef..c6b7662661 100644 --- a/libnvme/src/nvme/types.h +++ b/libnvme/src/nvme/types.h @@ -14,27 +14,6 @@ #include -struct nvme_global_ctx; -struct nvme_passthru_cmd; -struct nvme_transport_handle; - -/** - * nvme_create_global_ctx() - Initialize global context object - * @fp: File descriptor for logging messages - * @log_level: Logging level to use - * - * Return: Initialized &struct nvme_global_ctx object - */ -struct nvme_global_ctx *nvme_create_global_ctx(FILE *fp, int log_level); - -/** - * nvme_free_global_ctx() - Free global context object - * @ctx: &struct nvme_global_ctx object - * - * Free an &struct nvme_global_ctx object and all attached objects - */ -void nvme_free_global_ctx(struct nvme_global_ctx *ctx); - /** * DOC: types.h * diff --git a/libnvme/src/nvme/util.h b/libnvme/src/nvme/util.h index 78821a5b3c..b7f187c95c 100644 --- a/libnvme/src/nvme/util.h +++ b/libnvme/src/nvme/util.h @@ -150,6 +150,7 @@ const char *nvme_errno_to_string(int err); const char *nvme_strerror(int err); struct nvme_root; +struct nvme_global_ctx; int hostname2traddr(struct nvme_global_ctx *ctx, const char *traddr, char **hostname); diff --git a/libnvme/test/meson.build b/libnvme/test/meson.build index 47cacf77ae..d32a476386 100644 --- a/libnvme/test/meson.build +++ b/libnvme/test/meson.build @@ -182,6 +182,8 @@ foreach hdr : [ 'fabrics', 'filters', 'ioctl', + 'lib', + 'lib-types', 'linux', 'log', 'mi', From 5ccb672f4ef1573558e9b78e1ab473c75643c26c Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 4 Mar 2026 11:35:29 +0100 Subject: [PATCH 21/29] util: move functions into private header These function are only used internally, thus move it to private and thus reduce the API size and dependencies a bit further. Signed-off-by: Daniel Wagner --- libnvme/src/libnvme.ld | 1 - libnvme/src/nvme/private.h | 158 ++++++++++++++++++++++++++++++++++++- libnvme/src/nvme/util.h | 152 ----------------------------------- libnvme/test/meson.build | 2 +- libnvme/test/test-util.c | 1 + 5 files changed, 156 insertions(+), 158 deletions(-) diff --git a/libnvme/src/libnvme.ld b/libnvme/src/libnvme.ld index 7ea480a57f..35c693b795 100644 --- a/libnvme/src/libnvme.ld +++ b/libnvme/src/libnvme.ld @@ -121,7 +121,6 @@ LIBNVME_2_0 { nvme_insert_tls_key; nvme_insert_tls_key_compat; nvme_insert_tls_key_versioned; - nvme_ipaddrs_eq; nvme_lookup_key; nvme_lookup_keyring; nvme_mi_admin_admin_passthru; diff --git a/libnvme/src/nvme/private.h b/libnvme/src/nvme/private.h index 67f816760d..6acd44f479 100644 --- a/libnvme/src/nvme/private.h +++ b/libnvme/src/nvme/private.h @@ -5,9 +5,7 @@ * * Authors: Hannes Reinecke */ - -#ifndef _LIBNVME_PRIVATE_H -#define _LIBNVME_PRIVATE_H +#pragma once #include #include @@ -584,4 +582,156 @@ static inline char *xstrdup(const char *s) */ const struct ifaddrs *nvme_getifaddrs(struct nvme_global_ctx *ctx); -#endif /* _LIBNVME_PRIVATE_H */ +/** + * nvme_ipaddrs_eq - Check if 2 IP addresses are equal. + * @addr1: IP address (can be IPv4 or IPv6) + * @addr2: IP address (can be IPv4 or IPv6) + * + * Return: true if addr1 == addr2. false otherwise. + */ +bool nvme_ipaddrs_eq(const char *addr1, const char *addr2); + +/** + * nvme_iface_matching_addr - Get interface matching @addr + * @iface_list: Interface list returned by getifaddrs() + * @addr: Address to match + * + * Parse the interface list pointed to by @iface_list looking + * for the interface that has @addr as one of its assigned + * addresses. + * + * Return: The name of the interface that owns @addr or NULL. + */ +const char *nvme_iface_matching_addr(const struct ifaddrs *iface_list, + const char *addr); + +/** + * nvme_iface_primary_addr_matches - Check that interface's primary + * address matches + * @iface_list: Interface list returned by getifaddrs() + * @iface: Interface to match + * @addr: Address to match + * + * Parse the interface list pointed to by @iface_list and looking for + * interface @iface. The get its primary address and check if it matches + * @addr. + * + * Return: true if a match is found, false otherwise. + */ +bool nvme_iface_primary_addr_matches(const struct ifaddrs *iface_list, + const char *iface, const char *addr); + +int hostname2traddr(struct nvme_global_ctx *ctx, const char *traddr, + char **hostname); + +/** + * get_entity_name - Get Entity Name (ENAME). + * @buffer: The buffer where the ENAME will be saved as an ASCII string. + * @bufsz: The size of @buffer. + * + * Per TP8010, ENAME is defined as the name associated with the host (i.e. + * hostname). + * + * Return: Number of characters copied to @buffer. + */ +size_t get_entity_name(char *buffer, size_t bufsz); + +/** + * get_entity_version - Get Entity Version (EVER). + * @buffer: The buffer where the EVER will be saved as an ASCII string. + * @bufsz: The size of @buffer. + * + * EVER is defined as the operating system name and version as an ASCII + * string. This function reads different files from the file system and + * builds a string as follows: [os type] [os release] [distro release] + * + * E.g. "Linux 5.17.0-rc1 SLES 15.4" + * + * Return: Number of characters copied to @buffer. + */ +size_t get_entity_version(char *buffer, size_t bufsz); + + +/** + * startswith - Checks that a string starts with a given prefix. + * @s: The string to check + * @prefix: A string that @s could be starting with + * + * Return: If @s starts with @prefix, then return a pointer within @s at + * the first character after the matched @prefix. NULL otherwise. + */ +char *startswith(const char *s, const char *prefix); + +/** + * kv_strip - Strip blanks from key value string + * @kv: The key-value string to strip + * + * Strip leading/trailing blanks as well as trailing comments from the + * Key=Value string pointed to by @kv. + * + * Return: A pointer to the stripped string. Note that the original string, + * @kv, gets modified. + */ +char *kv_strip(char *kv); + +/** + * kv_keymatch - Look for key in key value string + * @kv: The key=value string to search for the presence of @key + * @key: The key to look for + * + * Look for @key in the Key=Value pair pointed to by @k and return a + * pointer to the Value if @key is found. + * + * Check if @kv starts with @key. If it does then make sure that we + * have a whole-word match on the @key, and if we do, return a pointer + * to the first character of value (i.e. skip leading spaces, tabs, + * and equal sign) + * + * Return: A pointer to the first character of "value" if a match is found. + * NULL otherwise. + */ +char *kv_keymatch(const char *kv, const char *key); + +#define __round_mask(val, mult) ((__typeof__(val))((mult)-1)) + +/** + * round_up - Round a value @val to the next multiple specified by @mult. + * @val: Value to round + * @mult: Multiple to round to. + * + * usage: int x = round_up(13, sizeof(__u32)); // 13 -> 16 + */ +#define round_up(val, mult) ((((val)-1) | __round_mask((val), (mult)))+1) + +/** + * nvmf_exat_len() - Return length rounded up by 4 + * @val_len: Value length + * + * Return the size in bytes, rounded to a multiple of 4 (e.g., size of + * __u32), of the buffer needed to hold the exat value of size + * @val_len. + * + * Return: Length rounded up by 4 + */ +static inline __u16 nvmf_exat_len(size_t val_len) +{ + return (__u16)round_up(val_len, sizeof(__u32)); +} + +/** + * nvmf_exat_size - Return min aligned size to hold value + * @val_len: This is the length of the data to be copied to the "exatval" + * field of a "struct nvmf_ext_attr". + * + * Return the size of the "struct nvmf_ext_attr" needed to hold + * a value of size @val_len. + * + * Return: The size in bytes, rounded to a multiple of 4 (i.e. size of + * __u32), of the "struct nvmf_ext_attr" required to hold a string of + * length @val_len. + */ +static inline __u16 nvmf_exat_size(size_t val_len) +{ + return (__u16)(sizeof(struct nvmf_ext_attr) + nvmf_exat_len(val_len)); +} + diff --git a/libnvme/src/nvme/util.h b/libnvme/src/nvme/util.h index b7f187c95c..dad8a0e1fb 100644 --- a/libnvme/src/nvme/util.h +++ b/libnvme/src/nvme/util.h @@ -8,8 +8,6 @@ */ #pragma once -#include - #include /** @@ -149,121 +147,6 @@ const char *nvme_errno_to_string(int err); */ const char *nvme_strerror(int err); -struct nvme_root; -struct nvme_global_ctx; - -int hostname2traddr(struct nvme_global_ctx *ctx, const char *traddr, char **hostname); - -/** - * get_entity_name - Get Entity Name (ENAME). - * @buffer: The buffer where the ENAME will be saved as an ASCII string. - * @bufsz: The size of @buffer. - * - * Per TP8010, ENAME is defined as the name associated with the host (i.e. - * hostname). - * - * Return: Number of characters copied to @buffer. - */ -size_t get_entity_name(char *buffer, size_t bufsz); - -/** - * get_entity_version - Get Entity Version (EVER). - * @buffer: The buffer where the EVER will be saved as an ASCII string. - * @bufsz: The size of @buffer. - * - * EVER is defined as the operating system name and version as an ASCII - * string. This function reads different files from the file system and - * builds a string as follows: [os type] [os release] [distro release] - * - * E.g. "Linux 5.17.0-rc1 SLES 15.4" - * - * Return: Number of characters copied to @buffer. - */ -size_t get_entity_version(char *buffer, size_t bufsz); - -/** - * kv_strip - Strip blanks from key value string - * @kv: The key-value string to strip - * - * Strip leading/trailing blanks as well as trailing comments from the - * Key=Value string pointed to by @kv. - * - * Return: A pointer to the stripped string. Note that the original string, - * @kv, gets modified. - */ -char *kv_strip(char *kv); - -/** - * kv_keymatch - Look for key in key value string - * @kv: The key=value string to search for the presence of @key - * @key: The key to look for - * - * Look for @key in the Key=Value pair pointed to by @k and return a - * pointer to the Value if @key is found. - * - * Check if @kv starts with @key. If it does then make sure that we - * have a whole-word match on the @key, and if we do, return a pointer - * to the first character of value (i.e. skip leading spaces, tabs, - * and equal sign) - * - * Return: A pointer to the first character of "value" if a match is found. - * NULL otherwise. - */ -char *kv_keymatch(const char *kv, const char *key); - -/** - * startswith - Checks that a string starts with a given prefix. - * @s: The string to check - * @prefix: A string that @s could be starting with - * - * Return: If @s starts with @prefix, then return a pointer within @s at - * the first character after the matched @prefix. NULL otherwise. - */ -char *startswith(const char *s, const char *prefix); - -#define __round_mask(val, mult) ((__typeof__(val))((mult)-1)) - -/** - * round_up - Round a value @val to the next multiple specified by @mult. - * @val: Value to round - * @mult: Multiple to round to. - * - * usage: int x = round_up(13, sizeof(__u32)); // 13 -> 16 - */ -#define round_up(val, mult) ((((val)-1) | __round_mask((val), (mult)))+1) - -/** - * nvmf_exat_len() - Return length rounded up by 4 - * @val_len: Value length - * - * Return the size in bytes, rounded to a multiple of 4 (e.g., size of - * __u32), of the buffer needed to hold the exat value of size - * @val_len. - * - * Return: Length rounded up by 4 - */ -static inline __u16 nvmf_exat_len(size_t val_len) -{ - return (__u16)round_up(val_len, sizeof(__u32)); -} - -/** - * nvmf_exat_size - Return min aligned size to hold value - * @val_len: This is the length of the data to be copied to the "exatval" - * field of a "struct nvmf_ext_attr". - * - * Return the size of the "struct nvmf_ext_attr" needed to hold - * a value of size @val_len. - * - * Return: The size in bytes, rounded to a multiple of 4 (i.e. size of - * __u32), of the "struct nvmf_ext_attr" required to hold a string of - * length @val_len. - */ -static inline __u16 nvmf_exat_size(size_t val_len) -{ - return (__u16)(sizeof(struct nvmf_ext_attr) + nvmf_exat_len(val_len)); -} - /** * nvmf_exat_ptr_next - Increment @p to the next element in the array. * @p: Pointer to an element of an array of "struct nvmf_ext_attr". @@ -335,38 +218,3 @@ int nvme_uuid_random(unsigned char uuid[NVME_UUID_LEN]); */ int nvme_uuid_find(struct nvme_id_uuid_list *uuid_list, const unsigned char uuid[NVME_UUID_LEN]); -/** - * nvme_ipaddrs_eq - Check if 2 IP addresses are equal. - * @addr1: IP address (can be IPv4 or IPv6) - * @addr2: IP address (can be IPv4 or IPv6) - * - * Return: true if addr1 == addr2. false otherwise. - */ -bool nvme_ipaddrs_eq(const char *addr1, const char *addr2); - -/** - * nvme_iface_matching_addr - Get interface matching @addr - * @iface_list: Interface list returned by getifaddrs() - * @addr: Address to match - * - * Parse the interface list pointed to by @iface_list looking - * for the interface that has @addr as one of its assigned - * addresses. - * - * Return: The name of the interface that owns @addr or NULL. - */ -const char *nvme_iface_matching_addr(const struct ifaddrs *iface_list, const char *addr); - -/** - * nvme_iface_primary_addr_matches - Check that interface's primary address matches - * @iface_list: Interface list returned by getifaddrs() - * @iface: Interface to match - * @addr: Address to match - * - * Parse the interface list pointed to by @iface_list and looking for - * interface @iface. The get its primary address and check if it matches - * @addr. - * - * Return: true if a match is found, false otherwise. - */ -bool nvme_iface_primary_addr_matches(const struct ifaddrs *iface_list, const char *iface, const char *addr); diff --git a/libnvme/test/meson.build b/libnvme/test/meson.build index d32a476386..210b90b00a 100644 --- a/libnvme/test/meson.build +++ b/libnvme/test/meson.build @@ -143,7 +143,7 @@ if conf.get('HAVE_NETDB') dependencies: [ config_dep, ccan_dep, - libnvme_dep, + libnvme_test_dep, ], ) test('libnvme - util', test_util) diff --git a/libnvme/test/test-util.c b/libnvme/test/test-util.c index 6b22ebfa00..c7b661ee35 100644 --- a/libnvme/test/test-util.c +++ b/libnvme/test/test-util.c @@ -21,6 +21,7 @@ #include #include +#include static size_t safe_strlen(const char *p) { return p ? strlen(p) : strlen("null"); From 0a22a794270e1c5efc95ed4d5681401a255b426a Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 4 Mar 2026 12:03:11 +0100 Subject: [PATCH 22/29] log: move logging definition to lib.h The logging is attached to the global context and thus no low level API is needed outside of the library. Thus move it to lib.h. Signed-off-by: Daniel Wagner --- libnvme/doc/meson.build | 1 - libnvme/libnvme/nvme.i | 2 +- libnvme/src/libnvme-mi.h | 2 +- libnvme/src/libnvme.h | 1 - libnvme/src/libnvme.ld | 3 +- libnvme/src/meson.build | 1 - libnvme/src/nvme/fabrics.c | 6 ++-- libnvme/src/nvme/lib.h | 35 +++++++++++++++++++++ libnvme/src/nvme/log.c | 4 +-- libnvme/src/nvme/log.h | 64 -------------------------------------- libnvme/src/nvme/private.h | 1 - libnvme/test/meson.build | 1 - nvme.c | 1 + 13 files changed, 44 insertions(+), 78 deletions(-) delete mode 100644 libnvme/src/nvme/log.h diff --git a/libnvme/doc/meson.build b/libnvme/doc/meson.build index df0d92f3d9..1e6f3a06cb 100644 --- a/libnvme/doc/meson.build +++ b/libnvme/doc/meson.build @@ -13,7 +13,6 @@ api_files = [ 'filters.h', 'ioctl.h', 'linux.h', - 'log.h', 'mi.h', 'nbft.h', 'tree.h', diff --git a/libnvme/libnvme/nvme.i b/libnvme/libnvme/nvme.i index 8fc2a3989b..6981742d8b 100644 --- a/libnvme/libnvme/nvme.i +++ b/libnvme/libnvme/nvme.i @@ -510,7 +510,7 @@ struct nvme_ns { else if (!strcmp(level, "crit")) log_level = LOG_CRIT; else if (!strcmp(level, "alert")) log_level = LOG_ALERT; else if (!strcmp(level, "emerg")) log_level = LOG_EMERG; - nvme_init_logging($self, log_level, false, false); + nvme_set_logging_level($self, log_level, false, false); } %pythoncode %{ def hosts(self): diff --git a/libnvme/src/libnvme-mi.h b/libnvme/src/libnvme-mi.h index 206b1f7981..bbd7d9243b 100644 --- a/libnvme/src/libnvme-mi.h +++ b/libnvme/src/libnvme-mi.h @@ -13,10 +13,10 @@ extern "C" { #endif +#include #include #include #include -#include #ifdef __cplusplus } diff --git a/libnvme/src/libnvme.h b/libnvme/src/libnvme.h index ba936ecb50..e7ed221685 100644 --- a/libnvme/src/libnvme.h +++ b/libnvme/src/libnvme.h @@ -21,7 +21,6 @@ extern "C" { #include #include #include -#include #include #include #include diff --git a/libnvme/src/libnvme.ld b/libnvme/src/libnvme.ld index 35c693b795..5e44c891f4 100644 --- a/libnvme/src/libnvme.ld +++ b/libnvme/src/libnvme.ld @@ -85,6 +85,7 @@ LIBNVME_2_0 { nvme_get_feature_length; nvme_get_host_telemetry; nvme_get_log; + nvme_get_logging_level; nvme_get_logical_block_size; nvme_get_new_host_telemetry; nvme_get_ns_attr; @@ -117,7 +118,6 @@ LIBNVME_2_0 { nvme_init_ctrl; nvme_init_ctrl_list; nvme_init_dsm_range; - nvme_init_logging; nvme_insert_tls_key; nvme_insert_tls_key_compat; nvme_insert_tls_key_versioned; @@ -230,6 +230,7 @@ LIBNVME_2_0 { nvme_set_etdas; nvme_set_ioctl_probing; nvme_set_keyring; + nvme_set_logging_level; nvme_set_property; nvme_set_root; nvme_skip_namespaces; diff --git a/libnvme/src/meson.build b/libnvme/src/meson.build index 3572bd0aae..44a848e386 100644 --- a/libnvme/src/meson.build +++ b/libnvme/src/meson.build @@ -105,7 +105,6 @@ install_headers( 'nvme/lib-types.h', 'nvme/lib.h', 'nvme/linux.h', - 'nvme/log.h', 'nvme/mi.h', 'nvme/nbft.h', 'nvme/tree.h', diff --git a/libnvme/src/nvme/fabrics.c b/libnvme/src/nvme/fabrics.c index 490383d63a..7c6c9e94be 100644 --- a/libnvme/src/nvme/fabrics.c +++ b/libnvme/src/nvme/fabrics.c @@ -35,9 +35,7 @@ #include #include "cleanup.h" -#include "log.h" #include "private.h" -#include "util.h" #define NVMF_HOSTID_SIZE 37 @@ -2818,7 +2816,7 @@ static int nbft_connect(struct nvme_global_ctx *ctx, /* Pause logging for unavailable SSNSs */ if (ss && ss->unavailable && saved_log_level < 1) - nvme_init_logging(ctx, -1, false, false); + nvme_set_logging_level(ctx, -1, false, false); if (e) { if (e->trtype == NVMF_TRTYPE_TCP && @@ -2830,7 +2828,7 @@ static int nbft_connect(struct nvme_global_ctx *ctx, /* Resume logging */ if (ss && ss->unavailable && saved_log_level < 1) - nvme_init_logging(ctx, + nvme_set_logging_level(ctx, saved_log_level, saved_log_pid, saved_log_tstamp); diff --git a/libnvme/src/nvme/lib.h b/libnvme/src/nvme/lib.h index 9da0a69fee..5ffcfadf85 100644 --- a/libnvme/src/nvme/lib.h +++ b/libnvme/src/nvme/lib.h @@ -10,9 +10,17 @@ #include #include +#include #include +#ifndef MAX_LOGLEVEL +# define MAX_LOGLEVEL LOG_DEBUG +#endif +#ifndef DEFAULT_LOGLEVEL +# define DEFAULT_LOGLEVEL LOG_NOTICE +#endif + /** * nvme_create_global_ctx() - Initialize global context object * @fp: File descriptor for logging messages @@ -30,6 +38,33 @@ struct nvme_global_ctx *nvme_create_global_ctx(FILE *fp, int log_level); */ void nvme_free_global_ctx(struct nvme_global_ctx *ctx); +/** + * nvme_set_logging_level() - Set current logging level + * @ctx: struct nvme_global_ctx object + * @log_level: Logging level to set + * @log_pid: Boolean to enable logging of the PID + * @log_tstamp: Boolean to enable logging of the timestamp + * + * Sets the current logging level for the global context. + */ +void nvme_set_logging_level(struct nvme_global_ctx *ctx, int log_level, + bool log_pid, bool log_tstamp); + +/** + * nvme_get_logging_level() - Get current logging level + * @ctx: struct nvme_global_ctx object + * @log_pid: Pointer to store a current value of logging of + * the PID flag at (optional). + * @log_tstamp: Pointer to store a current value of logging of + * the timestamp flag at (optional). + * + * Retrieves current values of logging variables. + * + * Return: current log level value or DEFAULT_LOGLEVEL if not initialized. + */ +int nvme_get_logging_level(struct nvme_global_ctx *ctx, bool *log_pid, + bool *log_tstamp); + /** * nvme_open() - Open an nvme controller or namespace device * @ctx: struct nvme_global_ctx object diff --git a/libnvme/src/nvme/log.c b/libnvme/src/nvme/log.c index 80cf4fab19..193e1293ee 100644 --- a/libnvme/src/nvme/log.c +++ b/libnvme/src/nvme/log.c @@ -84,10 +84,10 @@ __nvme_msg(struct nvme_global_ctx *ctx, int level, message ? message : ""); } -void nvme_init_logging(struct nvme_global_ctx *ctx, int lvl, +void nvme_set_logging_level(struct nvme_global_ctx *ctx, int log_level, bool log_pid, bool log_tstamp) { - ctx->log.level = lvl; + ctx->log.level = log_level; ctx->log.pid = log_pid; ctx->log.timestamp = log_tstamp; } diff --git a/libnvme/src/nvme/log.h b/libnvme/src/nvme/log.h deleted file mode 100644 index bb8047ec5f..0000000000 --- a/libnvme/src/nvme/log.h +++ /dev/null @@ -1,64 +0,0 @@ -// SPDX-License-Identifier: LGPL-2.1-or-later -/* - * Copyright (c) 2021 Martin Wilck, SUSE LLC - */ -#pragma once - -#include -#include -#include - -#include - -#ifndef MAX_LOGLEVEL -# define MAX_LOGLEVEL LOG_DEBUG -#endif -#ifndef DEFAULT_LOGLEVEL -# define DEFAULT_LOGLEVEL LOG_NOTICE -#endif - -/** - * DOC: log.h - * - * logging functions - */ - -/** - * nvme_init_logging() - Initialize logging - * @ctx: struct nvme_global_ctx object - * @lvl: Logging level to set - * @log_pid: Boolean to enable logging of the PID - * @log_tstamp: Boolean to enable logging of the timestamp - * - * Sets the default logging variables for the library. - */ -void nvme_init_logging(struct nvme_global_ctx *ctx, int lvl, - bool log_pid, bool log_tstamp); - -/** - * nvme_init_default_logging() - Initialize default (fallback) logging - * @fp: File descriptor for logging messages - * @lvl: Logging level to set - * @log_pid: Boolean to enable logging of the PID - * @log_tstamp: Boolean to enable logging of the timestamp - * - * Sets the default logging settings for the library in case the root object - * is absent. - */ -void nvme_init_default_logging(FILE *fp, int lvl, bool log_pid, - bool log_tstamp); - -/** - * nvme_get_logging_level() - Get current logging level - * @ctx: struct nvme_global_ctx object - * @log_pid: Pointer to store a current value of logging of - * the PID flag at (optional). - * @log_tstamp: Pointer to store a current value of logging of - * the timestamp flag at (optional). - * - * Retrieves current values of logging variables. - * - * Return: current log level value or DEFAULT_LOGLEVEL if not initialized. - */ -int nvme_get_logging_level(struct nvme_global_ctx *ctx, bool *log_pid, - bool *log_tstamp); diff --git a/libnvme/src/nvme/private.h b/libnvme/src/nvme/private.h index 6acd44f479..acb2bfce73 100644 --- a/libnvme/src/nvme/private.h +++ b/libnvme/src/nvme/private.h @@ -734,4 +734,3 @@ static inline __u16 nvmf_exat_size(size_t val_len) { return (__u16)(sizeof(struct nvmf_ext_attr) + nvmf_exat_len(val_len)); } - diff --git a/libnvme/test/meson.build b/libnvme/test/meson.build index 210b90b00a..f8a5f47769 100644 --- a/libnvme/test/meson.build +++ b/libnvme/test/meson.build @@ -185,7 +185,6 @@ foreach hdr : [ 'lib', 'lib-types', 'linux', - 'log', 'mi', 'nbft', 'tree', diff --git a/nvme.c b/nvme.c index 02d1af78eb..4dff9163db 100644 --- a/nvme.c +++ b/nvme.c @@ -49,6 +49,7 @@ #include #include + #if HAVE_SYS_RANDOM #include #endif From 42c9c1f521861a76da9aec4a54fb34ea72810157 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 4 Mar 2026 13:06:54 +0100 Subject: [PATCH 23/29] tree: move nvme_ns_*_transport_handle to private header There is no user left for this interface, thus move it to the private header and reduce the API. Signed-off-by: Daniel Wagner --- libnvme/src/libnvme.ld | 2 -- libnvme/src/nvme/private.h | 22 ++++++++++++++++++++++ libnvme/src/nvme/tree.h | 22 ---------------------- libnvme/test/meson.build | 4 ++-- libnvme/test/test.c | 2 ++ libnvme/test/zns.c | 2 ++ 6 files changed, 28 insertions(+), 26 deletions(-) diff --git a/libnvme/src/libnvme.ld b/libnvme/src/libnvme.ld index 5e44c891f4..6116620515 100644 --- a/libnvme/src/libnvme.ld +++ b/libnvme/src/libnvme.ld @@ -189,11 +189,9 @@ LIBNVME_2_0 { nvme_ns_get_serial; nvme_ns_get_subsystem; nvme_ns_get_sysfs_dir; - nvme_ns_get_transport_handle; nvme_ns_get_uuid; nvme_ns_identify; nvme_ns_read; - nvme_ns_release_transport_handle; nvme_ns_rescan; nvme_ns_verify; nvme_ns_write; diff --git a/libnvme/src/nvme/private.h b/libnvme/src/nvme/private.h index acb2bfce73..dbd0fc97d9 100644 --- a/libnvme/src/nvme/private.h +++ b/libnvme/src/nvme/private.h @@ -734,3 +734,25 @@ static inline __u16 nvmf_exat_size(size_t val_len) { return (__u16)(sizeof(struct nvmf_ext_attr) + nvmf_exat_len(val_len)); } + +/** + * nvme_ns_get_transport_handle() - Get associated transport handle + * @n: Namespace instance + * + * libnvme will open() the file (if not already opened) and keep + * an internal copy of the link handle. Following calls to + * this API retrieve the internal cached copy of the link + * handle. The file will remain opened and the device handle will + * remain cached until the ns object is deleted or + * nvme_ns_release_transport_handle() is called. + * + * Return: Link handle with @n or NULL + */ +struct nvme_transport_handle *nvme_ns_get_transport_handle(nvme_ns_t n); + +/** + * nvme_ns_release_transport_handle() - Free transport handle from ns object + * @n: Namespace instance + * + */ +void nvme_ns_release_transport_handle(nvme_ns_t n); diff --git a/libnvme/src/nvme/tree.h b/libnvme/src/nvme/tree.h index cad6b34387..91060943ce 100644 --- a/libnvme/src/nvme/tree.h +++ b/libnvme/src/nvme/tree.h @@ -502,28 +502,6 @@ nvme_ns_t nvme_subsystem_next_ns(nvme_subsystem_t s, nvme_ns_t n); for (p = nvme_namespace_first_path(n); p != NULL; \ p = nvme_namespace_next_path(n, p)) -/** - * nvme_ns_get_transport_handle() - Get associated transport handle - * @n: Namespace instance - * - * libnvme will open() the file (if not already opened) and keep - * an internal copy of the link handle. Following calls to - * this API retrieve the internal cached copy of the link - * handle. The file will remain opened and the device handle will - * remain cached until the ns object is deleted or - * nvme_ns_release_transport_handle() is called. - * - * Return: Link handle with @n or NULL - */ -struct nvme_transport_handle *nvme_ns_get_transport_handle(nvme_ns_t n); - -/** - * nvme_ns_release_transport_handle() - Free transport handle from ns object - * @n: Namespace instance - * - */ -void nvme_ns_release_transport_handle(nvme_ns_t n); - /** * nvme_ns_get_nsid() - NSID of a namespace * @n: Namespace instance diff --git a/libnvme/test/meson.build b/libnvme/test/meson.build index f8a5f47769..4c4d0b0529 100644 --- a/libnvme/test/meson.build +++ b/libnvme/test/meson.build @@ -15,7 +15,7 @@ main = executable( dependencies: [ config_dep, ccan_dep, - libnvme_dep, + libnvme_test_dep, ], ) @@ -61,7 +61,7 @@ zns = executable( dependencies: [ config_dep, ccan_dep, - libnvme_dep, + libnvme_test_dep, ], ) diff --git a/libnvme/test/test.c b/libnvme/test/test.c index 59f0a581df..8b7d54b7cb 100644 --- a/libnvme/test/test.c +++ b/libnvme/test/test.c @@ -17,6 +17,8 @@ */ #include +#include "nvme/private.h" + #include #include #include diff --git a/libnvme/test/zns.c b/libnvme/test/zns.c index 6221140f47..b41ab4c9e7 100644 --- a/libnvme/test/zns.c +++ b/libnvme/test/zns.c @@ -11,6 +11,8 @@ */ #include +#include "nvme/private.h" + #include #include #include From 2bdc5e8b7f9313269671ba32a7a4a1db45f5c795 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 4 Mar 2026 13:32:18 +0100 Subject: [PATCH 24/29] mi: replace nvme_mi_*global_context with nvme_*_global_context Merge these two function together and avoid code duplication. Signed-off-by: Daniel Wagner --- libnvme/examples/mi-mctp-ae.c | 4 +- libnvme/examples/mi-mctp-csi-test.c | 4 +- libnvme/examples/mi-mctp.c | 6 +-- libnvme/src/libnvme.ld | 2 +- libnvme/src/nvme/lib.c | 19 +++++++++ libnvme/src/nvme/lib.h | 11 ++++++ libnvme/src/nvme/mi.c | 61 ----------------------------- libnvme/src/nvme/mi.h | 32 --------------- libnvme/test/mi-mctp.c | 4 +- libnvme/test/mi.c | 4 +- 10 files changed, 42 insertions(+), 105 deletions(-) diff --git a/libnvme/examples/mi-mctp-ae.c b/libnvme/examples/mi-mctp-ae.c index 04dcbd2878..5eeecf6da5 100644 --- a/libnvme/examples/mi-mctp-ae.c +++ b/libnvme/examples/mi-mctp-ae.c @@ -109,7 +109,7 @@ int main(int argc, char **argv) return EXIT_FAILURE; } - ctx = nvme_mi_create_global_ctx(stderr, DEFAULT_LOGLEVEL); + ctx = nvme_create_global_ctx(stderr, DEFAULT_LOGLEVEL); if (!ctx) err(EXIT_FAILURE, "can't create NVMe root"); @@ -173,7 +173,7 @@ int main(int argc, char **argv) //Cleanup nvme_mi_aem_disable(ep); nvme_mi_close(ep); - nvme_mi_free_global_ctx(ctx); + nvme_free_global_ctx(ctx); return rc ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/libnvme/examples/mi-mctp-csi-test.c b/libnvme/examples/mi-mctp-csi-test.c index de6985cee5..a7ca2b7dca 100644 --- a/libnvme/examples/mi-mctp-csi-test.c +++ b/libnvme/examples/mi-mctp-csi-test.c @@ -237,12 +237,12 @@ int main(int argc, char **argv) return EXIT_FAILURE; } - ctx = nvme_mi_create_global_ctx(stderr, DEFAULT_LOGLEVEL); + ctx = nvme_create_global_ctx(stderr, DEFAULT_LOGLEVEL); if (!ctx) err(EXIT_FAILURE, "can't create NVMe root"); rc = do_action_endpoint(action, ctx, net, eid, argc, argv); - nvme_mi_free_global_ctx(ctx); + nvme_free_global_ctx(ctx); return rc ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/libnvme/examples/mi-mctp.c b/libnvme/examples/mi-mctp.c index 0f866dedc9..042e58e663 100644 --- a/libnvme/examples/mi-mctp.c +++ b/libnvme/examples/mi-mctp.c @@ -846,9 +846,9 @@ int main(int argc, char **argv) printf("---\n"); free(desc); } - nvme_mi_free_global_ctx(ctx); + nvme_free_global_ctx(ctx); } else { - ctx = nvme_mi_create_global_ctx(stderr, DEFAULT_LOGLEVEL); + ctx = nvme_create_global_ctx(stderr, DEFAULT_LOGLEVEL); if (!ctx) err(EXIT_FAILURE, "can't create NVMe root"); @@ -857,7 +857,7 @@ int main(int argc, char **argv) errx(EXIT_FAILURE, "can't open MCTP endpoint %d:%d", net, eid); rc = do_action_endpoint(action, ep, argc, argv); nvme_mi_close(ep); - nvme_mi_free_global_ctx(ctx); + nvme_free_global_ctx(ctx); } return rc ? EXIT_FAILURE : EXIT_SUCCESS; diff --git a/libnvme/src/libnvme.ld b/libnvme/src/libnvme.ld index 6116620515..e9e1c6fc55 100644 --- a/libnvme/src/libnvme.ld +++ b/libnvme/src/libnvme.ld @@ -157,7 +157,6 @@ LIBNVME_2_0 { nvme_mi_scan_ep; nvme_mi_scan_mctp; nvme_mi_set_csi; - nvme_mi_set_probe_enabled; nvme_mi_status_to_string; nvme_mi_submit_entry; nvme_mi_submit_exit; @@ -229,6 +228,7 @@ LIBNVME_2_0 { nvme_set_ioctl_probing; nvme_set_keyring; nvme_set_logging_level; + nvme_set_probe_enabled; nvme_set_property; nvme_set_root; nvme_skip_namespaces; diff --git a/libnvme/src/nvme/lib.c b/libnvme/src/nvme/lib.c index b19ed81bb9..b7865da5a3 100644 --- a/libnvme/src/nvme/lib.c +++ b/libnvme/src/nvme/lib.c @@ -13,9 +13,24 @@ #include "private.h" #include +#include #include #include +static bool nvme_mi_probe_enabled_default(void) +{ + char *val; + + val = getenv("LIBNVME_MI_PROBE_ENABLED"); + if (!val) + return true; + + return strcmp(val, "0") && + strcasecmp(val, "false") && + strncasecmp(val, "disable", 7); + +} + struct nvme_global_ctx *nvme_create_global_ctx(FILE *fp, int log_level) { struct nvme_global_ctx *ctx; @@ -41,6 +56,7 @@ struct nvme_global_ctx *nvme_create_global_ctx(FILE *fp, int log_level) list_head_init(&ctx->endpoints); ctx->ioctl_probing = true; + ctx->mi_probe_enabled = nvme_mi_probe_enabled_default(); return ctx; } @@ -48,6 +64,7 @@ struct nvme_global_ctx *nvme_create_global_ctx(FILE *fp, int log_level) void nvme_free_global_ctx(struct nvme_global_ctx *ctx) { struct nvme_host *h, *_h; + nvme_mi_ep_t ep, tmp; if (!ctx) return; @@ -58,6 +75,8 @@ void nvme_free_global_ctx(struct nvme_global_ctx *ctx) free(ctx->options); nvme_for_each_host_safe(ctx, h, _h) __nvme_free_host(h); + nvme_mi_for_each_endpoint_safe(ctx, ep, tmp) + nvme_mi_close(ep); free(ctx->config_file); free(ctx->application); free(ctx); diff --git a/libnvme/src/nvme/lib.h b/libnvme/src/nvme/lib.h index 5ffcfadf85..eeb6444fcf 100644 --- a/libnvme/src/nvme/lib.h +++ b/libnvme/src/nvme/lib.h @@ -204,6 +204,17 @@ void nvme_transport_handle_set_decide_retry(struct nvme_transport_handle *hdl, bool (*decide_retry)(struct nvme_transport_handle *hdl, struct nvme_passthru_cmd *cmd, int err)); +/** + * nvme_set_probe_enabled() - enable/disable the probe for new MI endpoints + * @ctx: &struct nvme_global_ctx object + * @enabled: whether to probe new endpoints + * + * Controls whether newly-created endpoints are probed for quirks on creation. + * Defaults to enabled, which results in some initial messaging with the + * endpoint to determine model-specific details. + */ +void nvme_set_probe_enabled(struct nvme_global_ctx *ctx, bool enabled); + /** * nvme_set_dry_run() - Set global dry run state * @ctx: struct nvme_global_ctx object diff --git a/libnvme/src/nvme/mi.c b/libnvme/src/nvme/mi.c index 00eb2de228..f5153a6e9d 100644 --- a/libnvme/src/nvme/mi.c +++ b/libnvme/src/nvme/mi.c @@ -43,20 +43,6 @@ static int nvme_mi_get_async_message(nvme_mi_ep_t ep, static const int default_timeout = 1000; /* milliseconds; endpoints may override */ -static bool nvme_mi_probe_enabled_default(void) -{ - char *val; - - val = getenv("LIBNVME_MI_PROBE_ENABLED"); - if (!val) - return true; - - return strcmp(val, "0") && - strcasecmp(val, "false") && - strncasecmp(val, "disable", 7); - -} - static int parse_devname(const char *dev, unsigned int *net, uint8_t *eid, unsigned int *ctrl) { @@ -113,53 +99,6 @@ void __nvme_transport_handle_close_mi(struct nvme_transport_handle *hdl) free(hdl); } -/* MI-equivalent of nvme_create_root, but avoids clashing symbol names - * when linking against both libnvme and libnvme-mi. - */ -struct nvme_global_ctx *nvme_mi_create_global_ctx(FILE *fp, int log_level) -{ - struct nvme_global_ctx *ctx; - int fd; - - ctx = calloc(1, sizeof(*ctx)); - if (!ctx) - return NULL; - - if (fp) { - fd = fileno(fp); - if (fd < 0) { - free(ctx); - return NULL; - } - } else - fd = STDERR_FILENO; - - ctx->log.fd = fd; - ctx->log.level = log_level; - - ctx->mi_probe_enabled = nvme_mi_probe_enabled_default(); - - list_head_init(&ctx->hosts); - list_head_init(&ctx->endpoints); - - return ctx; -} - -void nvme_mi_free_global_ctx(struct nvme_global_ctx *ctx) -{ - nvme_mi_ep_t ep, tmp; - - nvme_mi_for_each_endpoint_safe(ctx, ep, tmp) - nvme_mi_close(ep); - - free(ctx); -} - -void nvme_mi_set_probe_enabled(struct nvme_global_ctx *ctx, bool enabled) -{ - ctx->mi_probe_enabled = enabled; -} - static void nvme_mi_record_resp_time(struct nvme_mi_ep *ep) { int rc; diff --git a/libnvme/src/nvme/mi.h b/libnvme/src/nvme/mi.h index bab5c3077f..3127656c31 100644 --- a/libnvme/src/nvme/mi.h +++ b/libnvme/src/nvme/mi.h @@ -651,38 +651,6 @@ struct nvme_mi_control_resp { */ const char *nvme_mi_status_to_string(int status); -/** - * nvme_mi_create_global_ctx() - Create top-level MI (ctx) handle. - * @fp: File descriptor for logging messages - * @log_level: Logging level to use - * - * Create the top-level (library) handle for creating subsequent endpoint - * objects. Similar to nvme_create_global_ctx(), but we provide this to - * allow linking without the core libnvme. - * - * Return: new nvme_global_ctx object, or NULL on failure. - * - * See &nvme_create_global_ctx. - */ -struct nvme_global_ctx *nvme_mi_create_global_ctx(FILE *fp, int log_level); - -/** - * nvme_mi_free_global_ctx() - Free nvme_global_ctx object. - * @ctx: &struct nvme_global_ctx object - */ -void nvme_mi_free_global_ctx(struct nvme_global_ctx *ctx); - -/** - * nvme_mi_set_probe_enabled() - enable/disable the probe for new endpoints - * @ctx: &struct nvme_global_ctx object - * @enabled: whether to probe new endpoints - * - * Controls whether newly-created endpoints are probed for quirks on creation. - * Defaults to enabled, which results in some initial messaging with the - * endpoint to determine model-specific details. - */ -void nvme_mi_set_probe_enabled(struct nvme_global_ctx *ctx, bool enabled); - /* Top level management object: NVMe-MI Management Endpoint */ struct nvme_mi_ep; diff --git a/libnvme/test/mi-mctp.c b/libnvme/test/mi-mctp.c index 1bd280bbd5..87d8bb69e0 100644 --- a/libnvme/test/mi-mctp.c +++ b/libnvme/test/mi-mctp.c @@ -1461,7 +1461,7 @@ int main(void) __nvme_mi_mctp_set_ops(&ops); - ctx = nvme_mi_create_global_ctx(fd, DEFAULT_LOGLEVEL); + ctx = nvme_create_global_ctx(fd, DEFAULT_LOGLEVEL); assert(ctx); ep = nvme_mi_open_mctp(ctx, 0, 0); @@ -1473,7 +1473,7 @@ int main(void) } nvme_mi_close(ep); - nvme_mi_free_global_ctx(ctx); + nvme_free_global_ctx(ctx); test_close_log(fd); diff --git a/libnvme/test/mi.c b/libnvme/test/mi.c index 010f93797a..918200317d 100644 --- a/libnvme/test/mi.c +++ b/libnvme/test/mi.c @@ -2131,7 +2131,7 @@ int main(void) fd = test_setup_log(); - ctx = nvme_mi_create_global_ctx(fd, DEFAULT_LOGLEVEL); + ctx = nvme_create_global_ctx(fd, DEFAULT_LOGLEVEL); assert(ctx); ep = nvme_mi_open_test(ctx); @@ -2142,7 +2142,7 @@ int main(void) } nvme_mi_close(ep); - nvme_mi_free_global_ctx(ctx); + nvme_free_global_ctx(ctx); test_close_log(fd); From 6cff1aff85e5d1760d14b842701319e43012bd0b Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 4 Mar 2026 14:21:15 +0100 Subject: [PATCH 25/29] mi: make nvme_mi_admin_admin_passthru private This function can be retired from the public API after the libnvme-me merge into the libnvme. Signed-off-by: Daniel Wagner --- libnvme/src/libnvme.ld | 1 - libnvme/src/nvme/mi.h | 19 ------------------- libnvme/src/nvme/private.h | 19 +++++++++++++++++++ 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/libnvme/src/libnvme.ld b/libnvme/src/libnvme.ld index e9e1c6fc55..14abcb17e0 100644 --- a/libnvme/src/libnvme.ld +++ b/libnvme/src/libnvme.ld @@ -123,7 +123,6 @@ LIBNVME_2_0 { nvme_insert_tls_key_versioned; nvme_lookup_key; nvme_lookup_keyring; - nvme_mi_admin_admin_passthru; nvme_mi_admin_xfer; nvme_mi_aem_disable; nvme_mi_aem_enable; diff --git a/libnvme/src/nvme/mi.h b/libnvme/src/nvme/mi.h index 3127656c31..d7beda872c 100644 --- a/libnvme/src/nvme/mi.h +++ b/libnvme/src/nvme/mi.h @@ -1326,25 +1326,6 @@ int nvme_mi_admin_xfer(struct nvme_transport_handle *hdl, off_t resp_data_offset, size_t *resp_data_size); -/** - * nvme_mi_admin_admin_passthru() - Submit an nvme admin passthrough command - * @hdl: Transport handle to send command to - * @cmd: The nvme admin command to send - * - * Send a customized NVMe Admin command request message and get the corresponding - * response message. - * - * This interface supports no data, host to controller and controller to - * host but it doesn't support bidirectional data transfer. - * Also this interface only supports data transfer size range [0, 4096] (bytes) - * so the & data_len parameter must be less than 4097. - * - * Return: The nvme command status if a response was received (see - * &enum nvme_status_field) or -1 with errno set otherwise. - */ -int nvme_mi_admin_admin_passthru(struct nvme_transport_handle *hdl, - struct nvme_passthru_cmd *cmd); - /** * nvme_mi_control() - Perform a Control Primitive command * @ep: endpoint for MI communication diff --git a/libnvme/src/nvme/private.h b/libnvme/src/nvme/private.h index dbd0fc97d9..ee807c29d2 100644 --- a/libnvme/src/nvme/private.h +++ b/libnvme/src/nvme/private.h @@ -756,3 +756,22 @@ struct nvme_transport_handle *nvme_ns_get_transport_handle(nvme_ns_t n); * */ void nvme_ns_release_transport_handle(nvme_ns_t n); + +/** + * nvme_mi_admin_admin_passthru() - Submit an nvme admin passthrough command + * @hdl: Transport handle to send command to + * @cmd: The nvme admin command to send + * + * Send a customized NVMe Admin command request message and get the + * corresponding response message. + * + * This interface supports no data, host to controller and controller to + * host but it doesn't support bidirectional data transfer. + * Also this interface only supports data transfer size range [0, 4096] (bytes) + * so the & data_len parameter must be less than 4097. + * + * Return: The nvme command status if a response was received (see + * &enum nvme_status_field) or -1 with errno set otherwise. + */ +int nvme_mi_admin_admin_passthru(struct nvme_transport_handle *hdl, + struct nvme_passthru_cmd *cmd); From 6678fd63af2884582050fd969ae2f7ba952bfcbb Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 4 Mar 2026 14:24:13 +0100 Subject: [PATCH 26/29] lib-types: move struct nvme_passthrue_cmd up This data structure is used through out the library and there is no point in forward declare it and then have it in ioctl.h. Signed-off-by: Daniel Wagner --- libnvme/src/nvme/ioctl.h | 88 ---------------------------------- libnvme/src/nvme/lib-types.h | 92 +++++++++++++++++++++++++++++++++++- 2 files changed, 91 insertions(+), 89 deletions(-) diff --git a/libnvme/src/nvme/ioctl.h b/libnvme/src/nvme/ioctl.h index b84631f7ad..7c002d1852 100644 --- a/libnvme/src/nvme/ioctl.h +++ b/libnvme/src/nvme/ioctl.h @@ -9,8 +9,6 @@ #pragma once -#include - #include /** @@ -33,92 +31,6 @@ */ #define NVME_URING_ENTRIES 16 -/** - * struct nvme_passthru_cmd - nvme passthrough command structure - * @opcode: Operation code, see &enum nvme_io_opcodes and &enum nvme_admin_opcodes - * @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) - * @cdw3: Command Dword 3 (no spec defined use) - * @metadata: User space address to metadata buffer (NULL if not used) - * @addr: User space address to data buffer (NULL if not used) - * @metadata_len: Metadata buffer transfer length - * @data_len: Data buffer transfer length - * @cdw10: Command Dword 10 (command specific) - * @cdw11: Command Dword 11 (command specific) - * @cdw12: Command Dword 12 (command specific) - * @cdw13: Command Dword 13 (command specific) - * @cdw14: Command Dword 14 (command specific) - * @cdw15: Command Dword 15 (command specific) - * @timeout_ms: If non-zero, overrides system default timeout in milliseconds - * @rsvd2: Reserved for future use (and fills an implicit struct pad - * @result: Set on completion to the command's CQE DWORD 0-1 controller response - */ -struct nvme_passthru_cmd { - __u8 opcode; - __u8 flags; - __u16 rsvd1; - __u32 nsid; - __u32 cdw2; - __u32 cdw3; - __u64 metadata; - __u64 addr; - __u32 metadata_len; - __u32 data_len; - __u32 cdw10; - __u32 cdw11; - __u32 cdw12; - __u32 cdw13; - __u32 cdw14; - __u32 cdw15; - __u32 timeout_ms; - __u32 rsvd2; - __u64 result; -}; - -/** - * struct nvme_uring_cmd - nvme uring 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) - * @rsvd1: Reserved for future use - * @nsid: Namespace Identifier, or Fabrics type - * @cdw2: Command Dword 2 (no spec defined use) - * @cdw3: Command Dword 3 (no spec defined use) - * @metadata: User space address to metadata buffer (NULL if not used) - * @addr: User space address to data buffer (NULL if not used) - * @metadata_len: Metadata buffer transfer length - * @data_len: Data buffer transfer length - * @cdw10: Command Dword 10 (command specific) - * @cdw11: Command Dword 11 (command specific) - * @cdw12: Command Dword 12 (command specific) - * @cdw13: Command Dword 13 (command specific) - * @cdw14: Command Dword 14 (command specific) - * @cdw15: Command Dword 15 (command specific) - * @timeout_ms: If non-zero, overrides system default timeout in milliseconds - * @rsvd2: Reserved for future use (and fills an implicit struct pad - */ -struct nvme_uring_cmd { - __u8 opcode; - __u8 flags; - __u16 rsvd1; - __u32 nsid; - __u32 cdw2; - __u32 cdw3; - __u64 metadata; - __u64 addr; - __u32 metadata_len; - __u32 data_len; - __u32 cdw10; - __u32 cdw11; - __u32 cdw12; - __u32 cdw13; - __u32 cdw14; - __u32 cdw15; - __u32 timeout_ms; - __u32 rsvd2; -}; - /** * nvme_submit_admin_passthru() - Submit an nvme passthrough admin command * @hdl: Transport handle diff --git a/libnvme/src/nvme/lib-types.h b/libnvme/src/nvme/lib-types.h index 97663847f5..43eab2ddac 100644 --- a/libnvme/src/nvme/lib-types.h +++ b/libnvme/src/nvme/lib-types.h @@ -8,6 +8,96 @@ */ #pragma once +#include + struct nvme_global_ctx; -struct nvme_passthru_cmd; struct nvme_transport_handle; + +/** + * struct nvme_passthru_cmd - nvme passthrough command structure + * @opcode: Operation code, see &enum nvme_io_opcodes and + * &enum nvme_admin_opcodes + * @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) + * @cdw3: Command Dword 3 (no spec defined use) + * @metadata: User space address to metadata buffer (NULL if not used) + * @addr: User space address to data buffer (NULL if not used) + * @metadata_len: Metadata buffer transfer length + * @data_len: Data buffer transfer length + * @cdw10: Command Dword 10 (command specific) + * @cdw11: Command Dword 11 (command specific) + * @cdw12: Command Dword 12 (command specific) + * @cdw13: Command Dword 13 (command specific) + * @cdw14: Command Dword 14 (command specific) + * @cdw15: Command Dword 15 (command specific) + * @timeout_ms: If non-zero, overrides system default timeout in milliseconds + * @rsvd2: Reserved for future use (and fills an implicit struct pad + * @result: Set on completion to the command's CQE DWORD 0-1 + * controller response + */ +struct nvme_passthru_cmd { + __u8 opcode; + __u8 flags; + __u16 rsvd1; + __u32 nsid; + __u32 cdw2; + __u32 cdw3; + __u64 metadata; + __u64 addr; + __u32 metadata_len; + __u32 data_len; + __u32 cdw10; + __u32 cdw11; + __u32 cdw12; + __u32 cdw13; + __u32 cdw14; + __u32 cdw15; + __u32 timeout_ms; + __u32 rsvd2; + __u64 result; +}; + +/** + * struct nvme_uring_cmd - nvme uring 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) + * @rsvd1: Reserved for future use + * @nsid: Namespace Identifier, or Fabrics type + * @cdw2: Command Dword 2 (no spec defined use) + * @cdw3: Command Dword 3 (no spec defined use) + * @metadata: User space address to metadata buffer (NULL if not used) + * @addr: User space address to data buffer (NULL if not used) + * @metadata_len: Metadata buffer transfer length + * @data_len: Data buffer transfer length + * @cdw10: Command Dword 10 (command specific) + * @cdw11: Command Dword 11 (command specific) + * @cdw12: Command Dword 12 (command specific) + * @cdw13: Command Dword 13 (command specific) + * @cdw14: Command Dword 14 (command specific) + * @cdw15: Command Dword 15 (command specific) + * @timeout_ms: If non-zero, overrides system default timeout in milliseconds + * @rsvd2: Reserved for future use (and fills an implicit struct pad + */ +struct nvme_uring_cmd { + __u8 opcode; + __u8 flags; + __u16 rsvd1; + __u32 nsid; + __u32 cdw2; + __u32 cdw3; + __u64 metadata; + __u64 addr; + __u32 metadata_len; + __u32 data_len; + __u32 cdw10; + __u32 cdw11; + __u32 cdw12; + __u32 cdw13; + __u32 cdw14; + __u32 cdw15; + __u32 timeout_ms; + __u32 rsvd2; +}; From d65a7947369314cd0b63f81b241aa7c679ee5c03 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 4 Mar 2026 14:32:13 +0100 Subject: [PATCH 27/29] fabrics: rename nvme_free_uri to nvmf_free_uri All fabrics function should use the nvmf_ prefix. Signed-off-by: Daniel Wagner --- libnvme/src/libnvme.ld | 2 +- libnvme/src/nvme/cleanup.h | 2 +- libnvme/src/nvme/fabrics.c | 8 ++++---- libnvme/src/nvme/fabrics.h | 4 ++-- libnvme/test/uriparser.c | 2 +- util/cleanup.h | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libnvme/src/libnvme.ld b/libnvme/src/libnvme.ld index 14abcb17e0..9af0b3375f 100644 --- a/libnvme/src/libnvme.ld +++ b/libnvme/src/libnvme.ld @@ -69,7 +69,6 @@ LIBNVME_2_0 { nvme_free_host; nvme_free_ns; nvme_free_subsystem; - nvme_free_uri; nvme_fw_download_seq; nvme_gen_dhchap_key; nvme_generate_tls_key_identity; @@ -320,6 +319,7 @@ LIBNVME_2_0 { nvmf_discovery_nbft; nvmf_eflags_str; nvmf_exat_ptr_next; + nvmf_free_uri; nvmf_get_default_trsvcid; nvmf_get_discovery_log; nvmf_get_discovery_wargs; diff --git a/libnvme/src/nvme/cleanup.h b/libnvme/src/nvme/cleanup.h index 2a1e3db00e..a20cc26ec8 100644 --- a/libnvme/src/nvme/cleanup.h +++ b/libnvme/src/nvme/cleanup.h @@ -49,7 +49,7 @@ static inline DEFINE_CLEANUP_FUNC(cleanup_addrinfo, struct addrinfo *, freeaddri static inline void free_uri(struct nvme_fabrics_uri **uri) { if (*uri) - nvme_free_uri(*uri); + nvmf_free_uri(*uri); } #define _cleanup_uri_ __cleanup__(free_uri) diff --git a/libnvme/src/nvme/fabrics.c b/libnvme/src/nvme/fabrics.c index 7c6c9e94be..5f331cd159 100644 --- a/libnvme/src/nvme/fabrics.c +++ b/libnvme/src/nvme/fabrics.c @@ -1962,13 +1962,13 @@ int nvme_parse_uri(const char *str, struct nvme_fabrics_uri **urip) if (sscanf(str, "%m[^:/]://%m[^/?#]%ms", &scheme, &authority, &path) < 2) { - nvme_free_uri(uri); + nvmf_free_uri(uri); return -EINVAL; } if (sscanf(scheme, "%m[^+]+%ms", &uri->scheme, &uri->protocol) < 1) { - nvme_free_uri(uri); + nvmf_free_uri(uri); return -EINVAL; } @@ -1986,7 +1986,7 @@ int nvme_parse_uri(const char *str, struct nvme_fabrics_uri **urip) /* treat it as IPv4/hostname */ if (sscanf(host, "%m[^:]:%d", &h, &uri->port) < 1) { - nvme_free_uri(uri); + nvmf_free_uri(uri); return -EINVAL; } uri->host = unescape_uri(h, 0); @@ -2030,7 +2030,7 @@ int nvme_parse_uri(const char *str, struct nvme_fabrics_uri **urip) return 0; } -void nvme_free_uri(struct nvme_fabrics_uri *uri) +void nvmf_free_uri(struct nvme_fabrics_uri *uri) { char **s; diff --git a/libnvme/src/nvme/fabrics.h b/libnvme/src/nvme/fabrics.h index b75d6bbff1..9f9549dc51 100644 --- a/libnvme/src/nvme/fabrics.h +++ b/libnvme/src/nvme/fabrics.h @@ -380,12 +380,12 @@ int nvmf_register_ctrl(nvme_ctrl_t c, enum nvmf_dim_tas tas, __u32 *result); int nvme_parse_uri(const char *str, struct nvme_fabrics_uri **uri); /** - * nvme_free_uri() - Free the URI structure + * nvmf_free_uri() - Free the URI structure * @uri: &nvme_fabrics_uri structure * * Free an &nvme_fabrics_uri structure. */ -void nvme_free_uri(struct nvme_fabrics_uri *uri); +void nvmf_free_uri(struct nvme_fabrics_uri *uri); /** * nvmf_get_default_trsvcid() - Get default transport service ID diff --git a/libnvme/test/uriparser.c b/libnvme/test/uriparser.c index 428c5495da..ae3bd87e96 100644 --- a/libnvme/test/uriparser.c +++ b/libnvme/test/uriparser.c @@ -191,7 +191,7 @@ static void test_uriparser(void) assert(strcmp(d->frag, parsed_data->fragment) == 0); } else assert(d->frag == parsed_data->fragment); - nvme_free_uri(parsed_data); + nvmf_free_uri(parsed_data); printf(" OK\n"); } } diff --git a/util/cleanup.h b/util/cleanup.h index bb11d32842..634b3089d2 100644 --- a/util/cleanup.h +++ b/util/cleanup.h @@ -48,7 +48,7 @@ static inline DEFINE_CLEANUP_FUNC(cleanup_nvme_ctrl, nvme_ctrl_t, nvme_free_ctrl static inline void free_uri(struct nvme_fabrics_uri **uri) { if (*uri) - nvme_free_uri(*uri); + nvmf_free_uri(*uri); } #define _cleanup_uri_ __cleanup__(free_uri) From cd87fad8eab0f3c97395bd915f3f8d012b5ee240 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 4 Mar 2026 15:57:55 +0100 Subject: [PATCH 28/29] cmds: avoid possible infinite loop nvme_fw_download_seq() updates data, size, and offset by xfer even though the actual submitted chunk length is min(xfer, size). If xfer > size, size -= xfer underflows (since size is __u32), potentially causing an infinite loop and out-of-bounds reads. Track the chunk size in a variable and advance/decrement by that value instead. Signed-off-by: Daniel Wagner --- libnvme/src/nvme/cmds.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libnvme/src/nvme/cmds.c b/libnvme/src/nvme/cmds.c index 319c8c4bcf..4f88749984 100644 --- a/libnvme/src/nvme/cmds.c +++ b/libnvme/src/nvme/cmds.c @@ -26,17 +26,18 @@ int nvme_fw_download_seq(struct nvme_transport_handle *hdl, bool ish, nvme_init_mi_cmd_flags(&cmd, ish); while (size > 0) { - err = nvme_init_fw_download(&cmd, data, - min(xfer, size), offset); + __u32 chunk = min(xfer, size); + + err = nvme_init_fw_download(&cmd, data, chunk, offset); if (err) break; err = nvme_submit_admin_passthru(hdl, &cmd); if (err) break; - data += xfer; - size -= xfer; - offset += xfer; + data += chunk; + size -= chunk; + offset += chunk; } return err; From c79a59d5ea3cdb3aa6983a3947eda19376a328c1 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 4 Mar 2026 15:59:45 +0100 Subject: [PATCH 29/29] cmds: free id_ctrl after use in nvme_get_telemetry_max id_ctrl is allocated with __nvme_alloc() but never freed. Signed-off-by: Daniel Wagner --- libnvme/src/nvme/cmds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnvme/src/nvme/cmds.c b/libnvme/src/nvme/cmds.c index 4f88749984..71457f5e65 100644 --- a/libnvme/src/nvme/cmds.c +++ b/libnvme/src/nvme/cmds.c @@ -124,7 +124,7 @@ int nvme_get_uuid_list(struct nvme_transport_handle *hdl, int nvme_get_telemetry_max(struct nvme_transport_handle *hdl, enum nvme_telemetry_da *da, size_t *data_tx) { - struct nvme_id_ctrl *id_ctrl = NULL; + _cleanup_free_ struct nvme_id_ctrl *id_ctrl = NULL; struct nvme_passthru_cmd cmd; int err;