Commit 49e70693 authored by Ben Walker's avatar Ben Walker Committed by Tomasz Zawadzki
Browse files

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: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/425


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-by: default avatarAleksey Marchuk <alexeymar@mellanox.com>
Reviewed-by: default avatarDarek Stojaczyk <dariusz.stojaczyk@intel.com>
parent 40529e5d
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -2899,6 +2899,10 @@ int spdk_nvme_cuse_register(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 spdk_nvme_transport;
+80 −0
Original line number Diff line number Diff line
@@ -3312,3 +3312,83 @@ spdk_nvme_ctrlr_get_transport_id(struct spdk_nvme_ctrlr *ctrlr)
{
	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;
}
+9 −66
Original line number Diff line number Diff line
@@ -248,74 +248,17 @@ spdk_vhost_nvme_get_queue_head(struct spdk_vhost_nvme_dev *nvme, uint32_t offset
}

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_session *vsession = nvme->vsession;
	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;
	prp2 = cmd->dptr.prp.prp2;
	int err;

	/* PRP1 may started with unaligned page address */
	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->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;
	err = spdk_nvme_map_prps(nvme->session, cmd, task->iovs, len, 4096,
				 vhost_gpa_to_vva);
	if (spdk_unlikely(err < 0)) {
		return err;
	}
			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;
	}

	task->iovcnt = err;
	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;
		}

		ret = spdk_nvme_map_prps(nvme, cmd, task, len);
		ret = spdk_vhost_nvme_map_prps(nvme, cmd, task, len);
		if (spdk_unlikely(ret != 0)) {
			SPDK_ERRLOG("nvme command map prps failed\n");
			task->dnr = 1;