nvme: add the support to remap NVMe command with SGL
Previously we can only remap NVMe command using PRP, now we add the SGL support. Change-Id: Iec352d858a07bdd3d5f261336d6fa1167ba7aa79 Signed-off-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7279 Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Community-CI: Broadcom CI Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
parent
3a58a5f19c
commit
018f6a8f21
@ -4261,6 +4261,118 @@ nvme_cmd_map_prps(void *prv, struct spdk_nvme_cmd *cmd, struct iovec *iovs,
|
|||||||
return iovcnt;
|
return iovcnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
nvme_cmd_map_sgls_data(void *prv, struct spdk_nvme_sgl_descriptor *sgls, uint32_t num_sgls,
|
||||||
|
struct iovec *iovs, uint32_t max_iovcnt,
|
||||||
|
void *(*gpa_to_vva)(void *prv, uint64_t addr, uint64_t len))
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
void *vva;
|
||||||
|
|
||||||
|
if (spdk_unlikely(max_iovcnt < num_sgls)) {
|
||||||
|
return -ERANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < num_sgls; i++) {
|
||||||
|
if (spdk_unlikely(sgls[i].unkeyed.type != SPDK_NVME_SGL_TYPE_DATA_BLOCK)) {
|
||||||
|
SPDK_ERRLOG("Invalid SGL type %u\n", sgls[i].unkeyed.type);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
vva = gpa_to_vva(prv, sgls[i].address, sgls[i].unkeyed.length);
|
||||||
|
if (spdk_unlikely(vva == NULL)) {
|
||||||
|
SPDK_ERRLOG("GPA to VVA failed\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
iovs[i].iov_base = vva;
|
||||||
|
iovs[i].iov_len = sgls[i].unkeyed.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return num_sgls;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
nvme_cmd_map_sgls(void *prv, struct spdk_nvme_cmd *cmd, struct iovec *iovs, uint32_t max_iovcnt,
|
||||||
|
uint32_t len, size_t mps,
|
||||||
|
void *(*gpa_to_vva)(void *prv, uint64_t addr, uint64_t len))
|
||||||
|
{
|
||||||
|
struct spdk_nvme_sgl_descriptor *sgl, *last_sgl;
|
||||||
|
uint32_t num_sgls, seg_len;
|
||||||
|
void *vva;
|
||||||
|
int ret;
|
||||||
|
uint32_t total_iovcnt = 0;
|
||||||
|
|
||||||
|
/* SGL cases */
|
||||||
|
sgl = &cmd->dptr.sgl1;
|
||||||
|
|
||||||
|
/* only one SGL segment */
|
||||||
|
if (sgl->unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK) {
|
||||||
|
assert(max_iovcnt > 0);
|
||||||
|
vva = gpa_to_vva(prv, sgl->address, sgl->unkeyed.length);
|
||||||
|
if (spdk_unlikely(vva == NULL)) {
|
||||||
|
SPDK_ERRLOG("GPA to VVA failed\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
iovs[0].iov_base = vva;
|
||||||
|
iovs[0].iov_len = sgl->unkeyed.length;
|
||||||
|
assert(sgl->unkeyed.length == len);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (spdk_unlikely((sgl->unkeyed.type != SPDK_NVME_SGL_TYPE_SEGMENT) &&
|
||||||
|
(sgl->unkeyed.type != SPDK_NVME_SGL_TYPE_LAST_SEGMENT))) {
|
||||||
|
SPDK_ERRLOG("Invalid SGL type %u\n", sgl->unkeyed.type);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
seg_len = sgl->unkeyed.length;
|
||||||
|
if (spdk_unlikely(seg_len % sizeof(struct spdk_nvme_sgl_descriptor))) {
|
||||||
|
SPDK_ERRLOG("Invalid SGL segment len %u\n", seg_len);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
num_sgls = seg_len / sizeof(struct spdk_nvme_sgl_descriptor);
|
||||||
|
vva = gpa_to_vva(prv, sgl->address, sgl->unkeyed.length);
|
||||||
|
if (spdk_unlikely(vva == NULL)) {
|
||||||
|
SPDK_ERRLOG("GPA to VVA failed\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sgl point to the first segment */
|
||||||
|
sgl = (struct spdk_nvme_sgl_descriptor *)vva;
|
||||||
|
last_sgl = &sgl[num_sgls - 1];
|
||||||
|
|
||||||
|
/* we are done */
|
||||||
|
if (last_sgl->unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK) {
|
||||||
|
/* map whole sgl list */
|
||||||
|
ret = nvme_cmd_map_sgls_data(prv, sgl, num_sgls, &iovs[total_iovcnt],
|
||||||
|
max_iovcnt - total_iovcnt, gpa_to_vva);
|
||||||
|
if (spdk_unlikely(ret < 0)) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
total_iovcnt += ret;
|
||||||
|
|
||||||
|
return total_iovcnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_sgls > 1) {
|
||||||
|
/* map whole sgl exclude last_sgl */
|
||||||
|
ret = nvme_cmd_map_sgls_data(prv, sgl, num_sgls - 1, &iovs[total_iovcnt],
|
||||||
|
max_iovcnt - total_iovcnt, gpa_to_vva);
|
||||||
|
if (spdk_unlikely(ret < 0)) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
total_iovcnt += ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* move to next level's segments */
|
||||||
|
sgl = last_sgl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* FIXME need to specify max number of iovs */
|
/* FIXME need to specify max number of iovs */
|
||||||
int
|
int
|
||||||
spdk_nvme_map_prps(void *prv, struct spdk_nvme_cmd *cmd, struct iovec *iovs,
|
spdk_nvme_map_prps(void *prv, struct spdk_nvme_cmd *cmd, struct iovec *iovs,
|
||||||
@ -4283,5 +4395,5 @@ spdk_nvme_map_cmd(void *prv, struct spdk_nvme_cmd *cmd, struct iovec *iovs, uint
|
|||||||
return nvme_cmd_map_prps(prv, cmd, iovs, max_iovcnt, len, mps, gpa_to_vva);
|
return nvme_cmd_map_prps(prv, cmd, iovs, max_iovcnt, len, mps, gpa_to_vva);
|
||||||
}
|
}
|
||||||
|
|
||||||
return -EINVAL;
|
return nvme_cmd_map_sgls(prv, cmd, iovs, max_iovcnt, len, mps, gpa_to_vva);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user