nvme: add spdk_nvme_ctrlr_cmd_io_raw_no_payload_build

Send the given NVM I/O command, I/O buffers, lists and all to
the NVMe controller.

This is a low level interface for submitting I/O commands directly.

This can only be used on PCIe controllers and qpairs.

This function allows a caller to submit an I/O request that is
COMPLETELY pre-defined, right down to the "physical" memory buffers.
It is intended for testing hardware, specifying exact buffer location,
alignment, and offset.  It also allows for specific choice of PRP
and SGLs.

The driver sets the CID.  EVERYTHING else is assumed set by the caller.
Needless to say, this is potentially extremely dangerous for both the host
(accidental/malicionus storage usage/corruption), and the device.
Thus its intent is for very specific hardware testing and environment
reproduction.

Signed-off-by: James Bergsten <jamesx.bergsten@intel.com>
Change-Id: I595fe02fe0dfa9c3ceba1ac116b6900357b02d2c
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/451994
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
This commit is contained in:
James Bergsten 2019-04-22 11:35:27 -07:00 committed by Jim Harris
parent 5f1e468117
commit 2d4f7e20a6
3 changed files with 63 additions and 1 deletions

View File

@ -987,6 +987,43 @@ struct spdk_nvme_qpair *spdk_nvme_ctrlr_alloc_io_qpair(struct spdk_nvme_ctrlr *c
*/
int spdk_nvme_ctrlr_free_io_qpair(struct spdk_nvme_qpair *qpair);
/**
* Send the given NVM I/O command, I/O buffers, lists and all to the NVMe controller.
*
* This is a low level interface for submitting I/O commands directly.
*
* This function allows a caller to submit an I/O request that is
* COMPLETELY pre-defined, right down to the "physical" memory buffers.
* It is intended for testing hardware, specifying exact buffer location,
* alignment, and offset. It also allows for specific choice of PRP
* and SGLs.
*
* The driver sets the CID. EVERYTHING else is assumed set by the caller.
* Needless to say, this is potentially extremely dangerous for both the host
* (accidental/malicionus storage usage/corruption), and the device.
* Thus its intent is for very specific hardware testing and environment
* reproduction.
*
* 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.
*
* This function can only be used on PCIe controllers and qpairs.
*
* \param ctrlr Opaque handle to NVMe controller.
* \param qpair I/O qpair to submit command.
* \param cmd NVM I/O command to submit.
* \param cb_fn Callback function invoked when the I/O command completes.
* \param cb_arg Argument passed to callback function.
*
* \return 0 on success, negated errno on failure.
*/
int spdk_nvme_ctrlr_io_cmd_raw_no_payload_build(struct spdk_nvme_ctrlr *ctrlr,
struct spdk_nvme_qpair *qpair,
struct spdk_nvme_cmd *cmd,
spdk_nvme_cmd_cb cb_fn, void *cb_arg);
/**
* Send the given NVM I/O command to the NVMe controller.
*

View File

@ -33,6 +33,31 @@
#include "nvme_internal.h"
int
spdk_nvme_ctrlr_io_cmd_raw_no_payload_build(struct spdk_nvme_ctrlr *ctrlr,
struct spdk_nvme_qpair *qpair,
struct spdk_nvme_cmd *cmd,
spdk_nvme_cmd_cb cb_fn, void *cb_arg)
{
struct nvme_request *req;
struct nvme_payload payload;
if (ctrlr->trid.trtype != SPDK_NVME_TRANSPORT_PCIE) {
return -EINVAL;
}
memset(&payload, 0, sizeof(payload));
req = nvme_allocate_request(qpair, &payload, 0, cb_fn, cb_arg);
if (req == NULL) {
return -ENOMEM;
}
memcpy(&req->cmd, cmd, sizeof(req->cmd));
return nvme_qpair_submit_request(qpair, req);
}
int
spdk_nvme_ctrlr_cmd_io_raw(struct spdk_nvme_ctrlr *ctrlr,
struct spdk_nvme_qpair *qpair,

View File

@ -2032,7 +2032,7 @@ nvme_pcie_qpair_submit_request(struct spdk_nvme_qpair *qpair, struct nvme_reques
}
if (req->payload_size == 0) {
/* Null payload - leave PRP fields zeroed */
/* Null payload - leave PRP fields untouched */
rc = 0;
} else if (nvme_payload_type(&req->payload) == NVME_PAYLOAD_TYPE_CONTIG) {
rc = nvme_pcie_qpair_build_contig_request(qpair, req, tr);