Commit 8d2b6e68 authored by Ben Walker's avatar Ben Walker Committed by Tomasz Zawadzki
Browse files

idxd: Add support for vectored crc32 + copy



Change-Id: Ib017280d6d0b2e115f5609b6b1a50793953ffa29
Signed-off-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/10290


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
Community-CI: Mellanox Build Bot
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarPaul Luse <paul.e.luse@intel.com>
parent e2efeef0
Loading
Loading
Loading
Loading
+9 −6
Original line number Diff line number Diff line
@@ -410,19 +410,22 @@ int spdk_idxd_batch_prep_copy_crc32c(struct spdk_idxd_io_channel *chan, struct i
 * submit by writing to the proper device portal.
 *
 * \param chan IDXD channel to submit request.
 * \param dst Destination virtual address.
 * \param src Source virtual address.
 * \param crc_dst Resulting calculation.
 * \param diov Destination iovec
 * \param diovcnt Number of elements in diov
 * \param siov Source iovec
 * \param siovcnt Number of elements in siov
 * \param seed Four byte CRC-32C seed value.
 * \param nbytes Number of bytes to calculate on.
 * \param crc_dst Resulting calculation.
 * \param cb_fn Callback function which will be called when the request is complete.
 * \param cb_arg Opaque value which will be passed back as the cb_arg parameter
 * in the completion callback.
 *
 * \return 0 on success, negative errno on failure.
 */
int spdk_idxd_submit_copy_crc32c(struct spdk_idxd_io_channel *chan, void *dst, void *src,
				 uint32_t *crc_dst, uint32_t seed, uint64_t nbytes,
int spdk_idxd_submit_copy_crc32c(struct spdk_idxd_io_channel *chan,
				 struct iovec *diov, size_t diovcnt,
				 struct iovec *siov, size_t siovcnt,
				 uint32_t seed, uint32_t *crc_dst,
				 spdk_idxd_req_cb cb_fn, void *cb_arg);

/**
+77 −4
Original line number Diff line number Diff line
@@ -914,8 +914,8 @@ err:
	return rc;
}

int
spdk_idxd_submit_copy_crc32c(struct spdk_idxd_io_channel *chan, void *dst, void *src,
static inline int
_idxd_submit_copy_crc32c_single(struct spdk_idxd_io_channel *chan, void *dst, void *src,
				uint32_t *crc_dst, uint32_t seed, uint64_t nbytes,
				spdk_idxd_req_cb cb_fn, void *cb_arg)
{
@@ -963,6 +963,79 @@ error:
	return rc;
}

int
spdk_idxd_submit_copy_crc32c(struct spdk_idxd_io_channel *chan,
			     struct iovec *diov, size_t diovcnt,
			     struct iovec *siov, size_t siovcnt,
			     uint32_t seed, uint32_t *crc_dst,
			     spdk_idxd_req_cb cb_fn, void *cb_arg)
{
	struct idxd_hw_desc *desc;
	struct idxd_ops *op;
	void *src, *dst;
	uint64_t src_addr, dst_addr;
	int rc;
	uint64_t len;
	struct idxd_batch *batch;
	struct spdk_ioviter iter;
	void *prev_crc;

	assert(chan != NULL);
	assert(diov != NULL);
	assert(siov != NULL);

	if (siovcnt == 1 && diovcnt == 1) {
		/* Simple case - crc on one buffer */
		return _idxd_submit_copy_crc32c_single(chan, diov[0].iov_base, siov[0].iov_base,
						       crc_dst, seed, siov[0].iov_len, cb_fn, cb_arg);
	}

	batch = spdk_idxd_batch_create(chan);
	if (!batch) {
		return -EBUSY;
	}

	prev_crc = NULL;
	for (len = spdk_ioviter_first(&iter, siov, siovcnt, diov, diovcnt, &src, &dst);
	     len > 0;
	     len = spdk_ioviter_next(&iter, &src, &dst)) {
		rc = _idxd_prep_batch_cmd(chan, NULL, NULL, batch, &desc, &op);
		if (rc) {
			goto err;
		}

		rc = _vtophys(src, &src_addr, len);
		if (rc) {
			goto err;
		}

		rc = _vtophys(dst, &dst_addr, len);
		if (rc) {
			goto err;
		}

		desc->opcode = IDXD_OPCODE_COPY_CRC;
		desc->dst_addr = dst_addr;
		desc->src_addr = src_addr;
		if (prev_crc == NULL) {
			desc->crc32c.seed = seed;
		} else {
			desc->flags |= IDXD_FLAG_FENCE | IDXD_FLAG_CRC_READ_CRC_SEED;
			desc->crc32c.addr = (uint64_t)prev_crc;
		}

		desc->xfer_size = len;
		prev_crc = &op->hw.crc32c_val;
		op->crc_dst = crc_dst;
	}

	return spdk_idxd_batch_submit(chan, batch, cb_fn, cb_arg);

err:
	spdk_idxd_batch_cancel(chan, batch);
	return rc;
}

uint32_t
spdk_idxd_batch_get_max(void)
{
+14 −4
Original line number Diff line number Diff line
@@ -151,7 +151,6 @@ _process_single_task(struct spdk_io_channel *ch, struct spdk_accel_task *task)
	struct idxd_io_channel *chan = spdk_io_channel_get_ctx(ch);
	int rc = 0;
	uint8_t fill_pattern = (uint8_t)task->fill_pattern;
	void *src;
	struct iovec *iov;
	uint32_t iovcnt;
	struct iovec siov = {};
@@ -202,9 +201,20 @@ _process_single_task(struct spdk_io_channel *ch, struct spdk_accel_task *task)
					     idxd_done, task);
		break;
	case ACCEL_OPCODE_COPY_CRC32C:
		src = (task->v.iovcnt == 0) ? task->src : task->v.iovs[0].iov_base;
		rc = spdk_idxd_submit_copy_crc32c(chan->chan, task->dst, src, task->crc_dst, task->seed,
						  task->nbytes, idxd_done, task);
		if (task->v.iovcnt == 0) {
			siov.iov_base = task->src;
			siov.iov_len = task->nbytes;
			iov = &siov;
			iovcnt = 1;
		} else {
			iov = task->v.iovs;
			iovcnt = task->v.iovcnt;
		}
		diov.iov_base = task->dst;
		diov.iov_len = task->nbytes;
		rc = spdk_idxd_submit_copy_crc32c(chan->chan, &diov, 1, iov, iovcnt,
						  task->seed, task->crc_dst,
						  idxd_done, task);
		break;
	default:
		assert(false);