Commit 9a1457ff authored by Ankit Kumar's avatar Ankit Kumar Committed by Tomasz Zawadzki
Browse files

lib/nvme: Add support for IO management commands



TP4146 introduced support for two new IO commands,
IO management receive and send.

Signed-off-by: default avatarAnkit Kumar <ankit.kumar@samsung.com>
Change-Id: Iaf37310b84e278df043dcf71a0c2ef912c2fca8e
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16520


Reviewed-by: default avatarAleksey Marchuk <alexeymar@nvidia.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
parent cc7736c9
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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
+51 −0
Original line number Diff line number Diff line
@@ -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.
 *
+63 −0
Original line number Diff line number Diff line
@@ -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 */

+55 −0
Original line number Diff line number Diff line
@@ -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);
}
+2 −0
Original line number Diff line number Diff line
@@ -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;