nvme: Move prp map code from vhost to nvme driver
This will be re-used in the muser transport of nvmf. Change-Id: If00e6ea79ffdc0c3bda0402f39c5f9f4f411788b Signed-off-by: Ben Walker <benjamin.walker@intel.com> Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/425 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com> Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
This commit is contained in:
parent
40529e5d11
commit
49e70693c6
@ -2899,6 +2899,10 @@ int spdk_nvme_cuse_register(struct spdk_nvme_ctrlr *ctrlr);
|
|||||||
*/
|
*/
|
||||||
void spdk_nvme_cuse_unregister(struct spdk_nvme_ctrlr *ctrlr);
|
void spdk_nvme_cuse_unregister(struct spdk_nvme_ctrlr *ctrlr);
|
||||||
|
|
||||||
|
int spdk_nvme_map_prps(void *prv, struct spdk_nvme_cmd *cmd, struct iovec *iovs,
|
||||||
|
uint32_t len, size_t mps,
|
||||||
|
void *(*gpa_to_vva)(void *prv, uint64_t addr, uint64_t len));
|
||||||
|
|
||||||
struct nvme_request;
|
struct nvme_request;
|
||||||
|
|
||||||
struct spdk_nvme_transport;
|
struct spdk_nvme_transport;
|
||||||
|
@ -3312,3 +3312,83 @@ spdk_nvme_ctrlr_get_transport_id(struct spdk_nvme_ctrlr *ctrlr)
|
|||||||
{
|
{
|
||||||
return &ctrlr->trid;
|
return &ctrlr->trid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME need to specify max number of iovs */
|
||||||
|
int
|
||||||
|
spdk_nvme_map_prps(void *prv, struct spdk_nvme_cmd *cmd, struct iovec *iovs,
|
||||||
|
uint32_t len, size_t mps,
|
||||||
|
void *(*gpa_to_vva)(void *prv, uint64_t addr, uint64_t len))
|
||||||
|
{
|
||||||
|
uint64_t prp1, prp2;
|
||||||
|
void *vva;
|
||||||
|
uint32_t i;
|
||||||
|
uint32_t residue_len, nents;
|
||||||
|
uint64_t *prp_list;
|
||||||
|
int iovcnt;
|
||||||
|
|
||||||
|
prp1 = cmd->dptr.prp.prp1;
|
||||||
|
prp2 = cmd->dptr.prp.prp2;
|
||||||
|
|
||||||
|
/* PRP1 may started with unaligned page address */
|
||||||
|
residue_len = mps - (prp1 % mps);
|
||||||
|
residue_len = spdk_min(len, residue_len);
|
||||||
|
|
||||||
|
vva = gpa_to_vva(prv, prp1, residue_len);
|
||||||
|
if (spdk_unlikely(vva == NULL)) {
|
||||||
|
SPDK_ERRLOG("GPA to VVA failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
iovs[0].iov_base = vva;
|
||||||
|
iovs[0].iov_len = residue_len;
|
||||||
|
len -= residue_len;
|
||||||
|
|
||||||
|
if (len) {
|
||||||
|
if (spdk_unlikely(prp2 == 0)) {
|
||||||
|
SPDK_ERRLOG("no PRP2, %d remaining\n", len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len <= mps) {
|
||||||
|
/* 2 PRP used */
|
||||||
|
iovcnt = 2;
|
||||||
|
vva = gpa_to_vva(prv, prp2, len);
|
||||||
|
if (spdk_unlikely(vva == NULL)) {
|
||||||
|
SPDK_ERRLOG("no VVA for %#lx, len%#x\n",
|
||||||
|
prp2, len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
iovs[1].iov_base = vva;
|
||||||
|
iovs[1].iov_len = len;
|
||||||
|
} else {
|
||||||
|
/* PRP list used */
|
||||||
|
nents = (len + mps - 1) / mps;
|
||||||
|
vva = gpa_to_vva(prv, prp2, nents * sizeof(*prp_list));
|
||||||
|
if (spdk_unlikely(vva == NULL)) {
|
||||||
|
SPDK_ERRLOG("no VVA for %#lx, nents=%#x\n",
|
||||||
|
prp2, nents);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
prp_list = vva;
|
||||||
|
i = 0;
|
||||||
|
while (len != 0) {
|
||||||
|
residue_len = spdk_min(len, mps);
|
||||||
|
vva = gpa_to_vva(prv, prp_list[i], residue_len);
|
||||||
|
if (spdk_unlikely(vva == NULL)) {
|
||||||
|
SPDK_ERRLOG("no VVA for %#lx, residue_len=%#x\n",
|
||||||
|
prp_list[i], residue_len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
iovs[i + 1].iov_base = vva;
|
||||||
|
iovs[i + 1].iov_len = residue_len;
|
||||||
|
len -= residue_len;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
iovcnt = i + 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* 1 PRP used */
|
||||||
|
iovcnt = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return iovcnt;
|
||||||
|
}
|
||||||
|
@ -248,74 +248,17 @@ spdk_vhost_nvme_get_queue_head(struct spdk_vhost_nvme_dev *nvme, uint32_t offset
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
spdk_nvme_map_prps(struct spdk_vhost_nvme_dev *nvme, struct spdk_nvme_cmd *cmd,
|
spdk_vhost_nvme_map_prps(struct spdk_vhost_nvme_dev *nvme, struct spdk_nvme_cmd *cmd,
|
||||||
struct spdk_vhost_nvme_task *task, uint32_t len)
|
struct spdk_vhost_nvme_task *task, uint32_t len)
|
||||||
{
|
{
|
||||||
struct spdk_vhost_session *vsession = nvme->vsession;
|
int err;
|
||||||
uint64_t prp1, prp2;
|
|
||||||
void *vva;
|
|
||||||
uint32_t i;
|
|
||||||
uint32_t residue_len, nents, mps = 4096;
|
|
||||||
uint64_t *prp_list;
|
|
||||||
|
|
||||||
prp1 = cmd->dptr.prp.prp1;
|
err = spdk_nvme_map_prps(nvme->session, cmd, task->iovs, len, 4096,
|
||||||
prp2 = cmd->dptr.prp.prp2;
|
vhost_gpa_to_vva);
|
||||||
|
if (spdk_unlikely(err < 0)) {
|
||||||
/* PRP1 may started with unaligned page address */
|
return err;
|
||||||
residue_len = mps - (prp1 % mps);
|
|
||||||
residue_len = spdk_min(len, residue_len);
|
|
||||||
|
|
||||||
vva = vhost_gpa_to_vva(vsession, prp1, residue_len);
|
|
||||||
if (spdk_unlikely(vva == NULL)) {
|
|
||||||
SPDK_ERRLOG("GPA to VVA failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
task->iovs[0].iov_base = vva;
|
task->iovcnt = err;
|
||||||
task->iovs[0].iov_len = residue_len;
|
|
||||||
len -= residue_len;
|
|
||||||
|
|
||||||
if (len) {
|
|
||||||
if (spdk_unlikely(prp2 == 0)) {
|
|
||||||
SPDK_DEBUGLOG(SPDK_LOG_VHOST_NVME, "Invalid PRP2=0 in command\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len <= mps) {
|
|
||||||
/* 2 PRP used */
|
|
||||||
task->iovcnt = 2;
|
|
||||||
vva = vhost_gpa_to_vva(vsession, prp2, len);
|
|
||||||
if (spdk_unlikely(vva == NULL)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
task->iovs[1].iov_base = vva;
|
|
||||||
task->iovs[1].iov_len = len;
|
|
||||||
} else {
|
|
||||||
/* PRP list used */
|
|
||||||
nents = (len + mps - 1) / mps;
|
|
||||||
vva = vhost_gpa_to_vva(vsession, prp2, nents * sizeof(*prp_list));
|
|
||||||
if (spdk_unlikely(vva == NULL)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
prp_list = vva;
|
|
||||||
i = 0;
|
|
||||||
while (len != 0) {
|
|
||||||
residue_len = spdk_min(len, mps);
|
|
||||||
vva = vhost_gpa_to_vva(vsession, prp_list[i], residue_len);
|
|
||||||
if (spdk_unlikely(vva == NULL)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
task->iovs[i + 1].iov_base = vva;
|
|
||||||
task->iovs[i + 1].iov_len = residue_len;
|
|
||||||
len -= residue_len;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
task->iovcnt = i + 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* 1 PRP used */
|
|
||||||
task->iovcnt = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -547,7 +490,7 @@ spdk_nvme_process_sq(struct spdk_vhost_nvme_dev *nvme, struct spdk_vhost_nvme_sq
|
|||||||
len = nlba * block_size;
|
len = nlba * block_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = spdk_nvme_map_prps(nvme, cmd, task, len);
|
ret = spdk_vhost_nvme_map_prps(nvme, cmd, task, len);
|
||||||
if (spdk_unlikely(ret != 0)) {
|
if (spdk_unlikely(ret != 0)) {
|
||||||
SPDK_ERRLOG("nvme command map prps failed\n");
|
SPDK_ERRLOG("nvme command map prps failed\n");
|
||||||
task->dnr = 1;
|
task->dnr = 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user