From 9a1457ff1e22db4b6a12671460eb843813edfa32 Mon Sep 17 00:00:00 2001 From: Ankit Kumar Date: Thu, 26 Jan 2023 04:28:17 +0530 Subject: [PATCH] lib/nvme: Add support for IO management commands TP4146 introduced support for two new IO commands, IO management receive and send. Signed-off-by: Ankit Kumar Change-Id: Iaf37310b84e278df043dcf71a0c2ef912c2fca8e Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16520 Reviewed-by: Aleksey Marchuk Reviewed-by: Jim Harris Tested-by: SPDK CI Jenkins --- CHANGELOG.md | 3 ++ include/spdk/nvme.h | 51 ++++++++++++++++++++++++++++++++ include/spdk/nvme_spec.h | 63 ++++++++++++++++++++++++++++++++++++++++ lib/nvme/nvme_ns_cmd.c | 55 +++++++++++++++++++++++++++++++++++ lib/nvme/spdk_nvme.map | 2 ++ 5 files changed, 174 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b127db99f..c98ef7635 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,9 @@ iovecs, unlike the deprecated `spdk_nvmf_request_get_data()`. New API `spdk_nvme_ns_get_format_index` was added to calculate the exact format index, that was used to format the namespace. +Added two new APIs `spdk_nvme_ns_cmd_io_mgmt_recv` and `spdk_nvme_ns_cmd_io_mgmt_send` to +receive and send the I/O management commands. + ## v23.01 ### accel diff --git a/include/spdk/nvme.h b/include/spdk/nvme.h index 83eff5779..fb1aa8e76 100644 --- a/include/spdk/nvme.h +++ b/include/spdk/nvme.h @@ -2,6 +2,7 @@ * Copyright (C) 2015 Intel Corporation. All rights reserved. * Copyright (c) 2019-2021 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 2021, 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * Copyright (c) 2023 Samsung Electronics Co., Ltd. All rights reserved. */ /** \file @@ -3594,6 +3595,56 @@ int spdk_nvme_ns_cmd_reservation_report(struct spdk_nvme_ns *ns, void *payload, uint32_t len, spdk_nvme_cmd_cb cb_fn, void *cb_arg); +/** + * Submit an I/O management receive command to the specified NVMe namespace. + * + * The command is submitted to a qpair allocated by spdk_nvme_ctrlr_alloc_io_qpair(). + * The user must ensure that only one thread submits I/O on a given qpair at any + * given time. + * + * \param ns NVMe namespace to submit the I/O mgmt receive request. + * \param qpair I/O queue pair to submit the request. + * \param payload Virtual address pointer for I/O mgmt receive data. + * \param len Length bytes for I/O mgmt receive data structure. + * \param mo Management operation to perform. + * \param mos Management operation specific field for the mo. + * \param cb_fn Callback function to invoke when the I/O is completed. + * \param cb_arg Argument to pass to the callback function. + * + * \return 0 if successfully submitted, negated errnos on the following error conditions: + * -ENOMEM: The request cannot be allocated. + * -ENXIO: The qpair is failed at the transport level. + */ +int spdk_nvme_ns_cmd_io_mgmt_recv(struct spdk_nvme_ns *ns, + struct spdk_nvme_qpair *qpair, void *payload, + uint32_t len, uint8_t mo, uint16_t mos, + spdk_nvme_cmd_cb cb_fn, void *cb_arg); + +/** + * Submit an I/O management send command to the specified NVMe namespace. + * + * The command is submitted to a qpair allocated by spdk_nvme_ctrlr_alloc_io_qpair(). + * The user must ensure that only one thread submits I/O on a given qpair at any + * given time. + * + * \param ns NVMe namespace to submit the I/O mgmt send request. + * \param qpair I/O queue pair to submit the request. + * \param payload Virtual address pointer for I/O mgmt send data. + * \param len Length bytes for I/O mgmt send data structure. + * \param mo Management operation to perform. + * \param mos Management operation specific field for the mo. + * \param cb_fn Callback function to invoke when the I/O is completed. + * \param cb_arg Argument to pass to the callback function. + * + * \return 0 if successfully submitted, negated errnos on the following error conditions: + * -ENOMEM: The request cannot be allocated. + * -ENXIO: The qpair is failed at the transport level. + */ +int spdk_nvme_ns_cmd_io_mgmt_send(struct spdk_nvme_ns *ns, + struct spdk_nvme_qpair *qpair, void *payload, + uint32_t len, uint8_t mo, uint16_t mos, + spdk_nvme_cmd_cb cb_fn, void *cb_arg); + /** * Submit a compare I/O to the specified NVMe namespace. * diff --git a/include/spdk/nvme_spec.h b/include/spdk/nvme_spec.h index 2d6f0561f..d18edcb10 100644 --- a/include/spdk/nvme_spec.h +++ b/include/spdk/nvme_spec.h @@ -1199,6 +1199,14 @@ union spdk_nvme_cmd_cdw10 { uint32_t rtype : 8; uint32_t reserved2 : 16; } resv_acquire; + + struct { + /* Management Operation */ + uint32_t mo : 8; + uint32_t reserved : 8; + /* Management Operation Specific */ + uint32_t mos : 16; + } mgmt_send_recv; }; SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_cmd_cdw10) == 4, "Incorrect size"); @@ -1669,9 +1677,11 @@ enum spdk_nvme_nvm_opcode { SPDK_NVME_OPC_RESERVATION_REPORT = 0x0e, SPDK_NVME_OPC_RESERVATION_ACQUIRE = 0x11, + SPDK_NVME_OPC_IO_MANAGEMENT_RECEIVE = 0x12, SPDK_NVME_OPC_RESERVATION_RELEASE = 0x15, SPDK_NVME_OPC_COPY = 0x19, + SPDK_NVME_OPC_IO_MANAGEMENT_SEND = 0x1D, }; /** @@ -1745,6 +1755,59 @@ struct spdk_nvme_fdp_event_desc { }; SPDK_STATIC_ASSERT(sizeof(struct spdk_nvme_fdp_event_desc) == 2, "Incorrect size"); +/** + * Reclaim unit handle status descriptor + */ +struct spdk_nvme_fdp_ruhs_desc { + /* Placement Identifier */ + uint16_t pid; + + /* Reclaim Unit Handle Identifier */ + uint16_t ruhid; + + /* Estimated Active Reclaim Unit Time Remaining */ + uint32_t earutr; + + /* Reclaim Unit Available Media Writes */ + uint64_t ruamw; + + uint8_t reserved[16]; +}; +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvme_fdp_ruhs_desc) == 32, "Incorrect size"); + +/** + * Reclaim unit handle status + */ +struct spdk_nvme_fdp_ruhs { + uint8_t reserved[14]; + + /* Number of Reclaim Unit Handle Status Descriptors */ + uint16_t nruhsd; + + struct spdk_nvme_fdp_ruhs_desc ruhs_desc[]; +}; +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvme_fdp_ruhs) == 16, "Incorrect size"); + +/** + * Management operation to perform for IO management receive + */ +enum spdk_nvme_fdp_mgmt_recv_mo { + SPDK_NVME_FDP_IO_MGMT_RECV_NA = 0x00, + SPDK_NVME_FDP_IO_MGMT_RECV_RUHS = 0x01, + /* 0x02-0xFE - reserved */ + SPDK_NVME_FDP_IO_MGMT_RECV_VS = 0xFF, +}; + +/** + * Management operation to perform for IO management send + */ +enum spdk_nvme_fdp_mgmt_send_mo { + SPDK_NVME_FDP_IO_MGMT_SEND_NA = 0x00, + SPDK_NVME_FDP_IO_MGMT_SEND_RUHU = 0x01, + /* 0x02-0xFE - reserved */ + SPDK_NVME_FDP_IO_MGMT_SEND_VS = 0xFF, +}; + enum spdk_nvme_feat { /* 0x00 - reserved */ diff --git a/lib/nvme/nvme_ns_cmd.c b/lib/nvme/nvme_ns_cmd.c index 3416d738b..ec2e70b2a 100644 --- a/lib/nvme/nvme_ns_cmd.c +++ b/lib/nvme/nvme_ns_cmd.c @@ -3,6 +3,7 @@ * All rights reserved. * Copyright (c) 2021 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * Copyright (c) 2023 Samsung Electronics Co., Ltd. All rights reserved. */ #include "nvme_internal.h" @@ -1355,3 +1356,57 @@ spdk_nvme_ns_cmd_reservation_report(struct spdk_nvme_ns *ns, return nvme_qpair_submit_request(qpair, req); } + +int +spdk_nvme_ns_cmd_io_mgmt_recv(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, + void *payload, uint32_t len, uint8_t mo, uint16_t mos, + spdk_nvme_cmd_cb cb_fn, void *cb_arg) +{ + uint32_t num_dwords; + struct nvme_request *req; + struct spdk_nvme_cmd *cmd; + + if (len & 0x3) { + return -EINVAL; + } + + req = nvme_allocate_request_user_copy(qpair, payload, len, cb_fn, cb_arg, false); + if (req == NULL) { + return -ENOMEM; + } + + cmd = &req->cmd; + cmd->opc = SPDK_NVME_OPC_IO_MANAGEMENT_RECEIVE; + cmd->nsid = ns->id; + + cmd->cdw10_bits.mgmt_send_recv.mo = mo; + cmd->cdw10_bits.mgmt_send_recv.mos = mos; + + num_dwords = (len >> 2); + cmd->cdw11 = num_dwords - 1; /* 0-based */ + + return nvme_qpair_submit_request(qpair, req); +} + +int +spdk_nvme_ns_cmd_io_mgmt_send(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, + void *payload, uint32_t len, uint8_t mo, uint16_t mos, + spdk_nvme_cmd_cb cb_fn, void *cb_arg) +{ + struct nvme_request *req; + struct spdk_nvme_cmd *cmd; + + req = nvme_allocate_request_user_copy(qpair, payload, len, cb_fn, cb_arg, false); + if (req == NULL) { + return -ENOMEM; + } + + cmd = &req->cmd; + cmd->opc = SPDK_NVME_OPC_IO_MANAGEMENT_SEND; + cmd->nsid = ns->id; + + cmd->cdw10_bits.mgmt_send_recv.mo = mo; + cmd->cdw10_bits.mgmt_send_recv.mos = mos; + + return nvme_qpair_submit_request(qpair, req); +} diff --git a/lib/nvme/spdk_nvme.map b/lib/nvme/spdk_nvme.map index 5e46d8fa3..ee230096b 100644 --- a/lib/nvme/spdk_nvme.map +++ b/lib/nvme/spdk_nvme.map @@ -165,6 +165,8 @@ spdk_nvme_ns_cmd_reservation_release; spdk_nvme_ns_cmd_reservation_acquire; spdk_nvme_ns_cmd_reservation_report; + spdk_nvme_ns_cmd_io_mgmt_recv; + spdk_nvme_ns_cmd_io_mgmt_send; spdk_nvme_ns_cmd_compare; spdk_nvme_ns_cmd_comparev; spdk_nvme_ns_cmd_comparev_with_md;