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 <ankit.kumar@samsung.com>
Change-Id: Iaf37310b84e278df043dcf71a0c2ef912c2fca8e
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16520
Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Ankit Kumar 2023-01-26 04:28:17 +05:30 committed by Tomasz Zawadzki
parent cc7736c968
commit 9a1457ff1e
5 changed files with 174 additions and 0 deletions

View File

@ -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

View File

@ -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.
*

View File

@ -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 */

View File

@ -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);
}

View File

@ -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;