nvme: add Bit Bucket SGL with READ support

When iterating SGL segment, we can use existing virt_addr parameter
to return UINT64_MAX as a special value to indicate this segment need
to be described as Bit Bucket SGL.

Currently only READ command is supported, we can enable the WRITE
and COMPARE support when necessary.

Change-Id: I50aa2b226ec3449c13ed1d97b3224ee8e7de95a8
Signed-off-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/1467
Community-CI: Mellanox Build Bot
Community-CI: Broadcom CI
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Changpeng Liu 2020-03-26 00:26:23 -04:00 committed by Tomasz Zawadzki
parent 532ae9527b
commit b55279d485
2 changed files with 33 additions and 1 deletions

View File

@ -2276,7 +2276,8 @@ typedef void (*spdk_nvme_req_reset_sgl_cb)(void *cb_arg, uint32_t offset);
* The described segment must be physically contiguous.
*
* \param cb_arg Argument passed to readv/writev.
* \param address Virtual address of this segment.
* \param address Virtual address of this segment, a value of UINT64_MAX
* means the segment should be described via Bit Bucket SGL.
* \param length Length of this physical segment.
*/
typedef int (*spdk_nvme_req_next_sge_cb)(void *cb_arg, void **address, uint32_t *length);

View File

@ -2012,6 +2012,37 @@ nvme_pcie_qpair_build_hw_sgl_request(struct spdk_nvme_qpair *qpair, struct nvme_
return -EFAULT;
}
/* Bit Bucket SGL descriptor */
if ((uint64_t)virt_addr == UINT64_MAX) {
/* TODO: enable WRITE and COMPARE when necessary */
if (req->cmd.opc != SPDK_NVME_OPC_READ) {
SPDK_ERRLOG("Only READ command can be supported\n");
goto exit;
}
if (nseg >= NVME_MAX_SGL_DESCRIPTORS) {
SPDK_ERRLOG("Too many SGL entries\n");
goto exit;
}
sgl->unkeyed.type = SPDK_NVME_SGL_TYPE_BIT_BUCKET;
/* If the SGL describes a destination data buffer, the length of data
* buffer shall be discarded by controller, and the length is included
* in Number of Logical Blocks (NLB) parameter. Otherwise, the length
* is not included in the NLB parameter.
*/
remaining_user_sge_len = spdk_min(remaining_user_sge_len, remaining_transfer_len);
remaining_transfer_len -= remaining_user_sge_len;
sgl->unkeyed.length = remaining_user_sge_len;
sgl->address = 0;
sgl->unkeyed.subtype = 0;
sgl++;
nseg++;
continue;
}
remaining_user_sge_len = spdk_min(remaining_user_sge_len, remaining_transfer_len);
remaining_transfer_len -= remaining_user_sge_len;
while (remaining_user_sge_len > 0) {