diff --git a/examples/accel/perf/accel_perf.c b/examples/accel/perf/accel_perf.c index 924a5b129..09d622e88 100644 --- a/examples/accel/perf/accel_perf.c +++ b/examples/accel/perf/accel_perf.c @@ -487,6 +487,11 @@ _batch_prep_cmd(struct worker_thread *worker, struct ap_task *task, struct spdk_ worker->ch, batch, task->dst, *(uint8_t *)task->src, g_xfer_size_bytes, accel_done); break; + case ACCEL_CRC32C: + rc = spdk_accel_batch_prep_crc32c(__accel_task_from_ap_task(task), + worker->ch, batch, (uint32_t *)task->dst, task->src, + g_crc32c_seed, g_xfer_size_bytes, accel_done); + break; default: assert(false); break; @@ -537,13 +542,8 @@ _init_thread(void *arg1) g_num_workers++; pthread_mutex_unlock(&g_workers_lock); - /* TODO: remove the workload selection checks once all are added. */ - if ((g_workload_selection == ACCEL_COPY || - g_workload_selection == ACCEL_DUALCAST || - g_workload_selection == ACCEL_COMPARE || - g_workload_selection == ACCEL_FILL) - && ((g_capabilites & ACCEL_BATCH) == ACCEL_BATCH) && - g_queue_depth > 1) { + /* TODO: remove batch check once implemented for IOAT */ + if ((g_capabilites & ACCEL_BATCH) == ACCEL_BATCH && g_queue_depth > 1) { /* Selected engine supports batching and we have enough, so do it. */ max_per_batch = spdk_accel_batch_get_max(worker->ch); diff --git a/include/spdk/accel_engine.h b/include/spdk/accel_engine.h index 428c771ca..dcf0ab130 100644 --- a/include/spdk/accel_engine.h +++ b/include/spdk/accel_engine.h @@ -299,6 +299,27 @@ int spdk_accel_batch_prep_fill(struct spdk_accel_task *accel_req, struct spdk_io int spdk_accel_submit_fill(struct spdk_accel_task *accel_req, struct spdk_io_channel *ch, void *dst, uint8_t fill, uint64_t nbytes, spdk_accel_completion_cb cb); +/** + * Synchronous call to prepare a crc32c request into a previously initialized batch + * created with spdk_accel_batch_create(). The callback will be called when the crc32c + * completes after the batch has been submitted by an asynchronous call to + * spdk_accel_batch_submit(). + * + * \param accel_req Accel request task. + * \param ch I/O channel to submit request to the accel engine. + * \param batch Handle provided when the batch was started with spdk_accel_batch_create(). + * \param dst Destination to write the CRC-32C to. + * \param src The source address for the data. + * \param seed Four byte seed value. + * \param nbytes Length in bytes. + * \param cb Called when this operation completes. + * + * \return 0 on success, negative errno on failure. + */ +int spdk_accel_batch_prep_crc32c(struct spdk_accel_task *accel_req, struct spdk_io_channel *ch, + struct spdk_accel_batch *batch, uint32_t *dst, void *src, uint32_t seed, + uint64_t nbytes, spdk_accel_completion_cb cb); + /** * Submit a CRC-32C calculation request. * diff --git a/include/spdk_internal/accel_engine.h b/include/spdk_internal/accel_engine.h index e8c2d880a..89f2117b5 100644 --- a/include/spdk_internal/accel_engine.h +++ b/include/spdk_internal/accel_engine.h @@ -60,6 +60,9 @@ struct spdk_accel_engine { void *src1, void *src2, uint64_t nbytes, spdk_accel_completion_cb cb); int (*batch_prep_fill)(void *cb_arg, struct spdk_io_channel *ch, struct spdk_accel_batch *batch, void *dst, uint8_t fill, uint64_t nbytes, spdk_accel_completion_cb cb); + int (*batch_prep_crc32c)(void *cb_arg, struct spdk_io_channel *ch, struct spdk_accel_batch *batch, + uint32_t *dst, void *src, uint32_t seed, uint64_t nbytes, + spdk_accel_completion_cb cb); int (*batch_submit)(void *cb_arg, struct spdk_io_channel *ch, struct spdk_accel_batch *batch, spdk_accel_completion_cb cb); int (*compare)(void *cb_arg, struct spdk_io_channel *ch, void *src1, void *src2, diff --git a/lib/accel/accel_engine.c b/lib/accel/accel_engine.c index 7d36585d7..1f7973224 100644 --- a/lib/accel/accel_engine.c +++ b/lib/accel/accel_engine.c @@ -270,6 +270,21 @@ spdk_accel_batch_prep_fill(struct spdk_accel_task *accel_req, struct spdk_io_cha batch, dst, fill, nbytes, _accel_engine_done); } +/* Accel framework public API for batch prep_crc32c function. All engines are + * required to implement this API. + */ +int +spdk_accel_batch_prep_crc32c(struct spdk_accel_task *accel_req, struct spdk_io_channel *ch, + struct spdk_accel_batch *batch, uint32_t *dst, void *src, uint32_t seed, + uint64_t nbytes, spdk_accel_completion_cb cb) +{ + struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch); + + accel_req->cb = cb; + return accel_ch->engine->batch_prep_crc32c(accel_req->offload_ctx, accel_ch->ch, + batch, dst, src, seed, nbytes, _accel_engine_done); +} + /* Accel framework public API for compare function */ int spdk_accel_submit_compare(struct spdk_accel_task *accel_req, struct spdk_io_channel *ch, @@ -664,6 +679,30 @@ sw_accel_batch_prep_fill(void *cb_arg, struct spdk_io_channel *ch, return 0; } +static int +sw_accel_batch_prep_crc32c(void *cb_arg, struct spdk_io_channel *ch, + struct spdk_accel_batch *batch, uint32_t *dst, void *src, + uint32_t seed, uint64_t nbytes, spdk_accel_completion_cb cb) +{ + struct sw_accel_op *op; + struct sw_accel_io_channel *sw_ch = spdk_io_channel_get_ctx(ch); + + op = _prep_op(cb_arg, sw_ch, batch, cb); + if (op == NULL) { + return -EINVAL; + } + + /* Command specific. */ + op->dst = (void *)dst; + op->src = src; + op->seed = seed; + op->nbytes = nbytes; + op->op_code = SW_ACCEL_OPCODE_CRC32C; + TAILQ_INSERT_TAIL(&sw_ch->batch, op, link); + + return 0; +} + static int sw_accel_batch_submit(void *cb_arg, struct spdk_io_channel *ch, struct spdk_accel_batch *batch, spdk_accel_completion_cb cb) @@ -698,6 +737,9 @@ sw_accel_batch_submit(void *cb_arg, struct spdk_io_channel *ch, struct spdk_acce case SW_ACCEL_OPCODE_MEMFILL: memset(op->dst, op->fill_pattern, op->nbytes); break; + case SW_ACCEL_OPCODE_CRC32C: + *(uint32_t *)op->dst = spdk_crc32c_update(op->src, op->nbytes, ~op->seed); + break; default: assert(false); break; @@ -801,6 +843,7 @@ static struct spdk_accel_engine sw_accel_engine = { .batch_prep_dualcast = sw_accel_batch_prep_dualcast, .batch_prep_compare = sw_accel_batch_prep_compare, .batch_prep_fill = sw_accel_batch_prep_fill, + .batch_prep_crc32c = sw_accel_batch_prep_crc32c, .batch_submit = sw_accel_batch_submit, .compare = sw_accel_submit_compare, .fill = sw_accel_submit_fill, diff --git a/lib/accel/spdk_accel.map b/lib/accel/spdk_accel.map index e7f2f0546..d89d3172f 100644 --- a/lib/accel/spdk_accel.map +++ b/lib/accel/spdk_accel.map @@ -14,6 +14,7 @@ spdk_accel_batch_prep_dualcast; spdk_accel_batch_prep_compare; spdk_accel_batch_prep_fill; + spdk_accel_batch_prep_crc32c; spdk_accel_batch_submit; spdk_accel_submit_copy; spdk_accel_submit_dualcast;