From a7dfca5b456d5f510f61e04ab6680a7be8423bcb Mon Sep 17 00:00:00 2001 From: paul luse Date: Wed, 17 Jun 2020 16:28:15 -0400 Subject: [PATCH] lib/accel: have the accel fw default to use sw at times When an engine has not filled out an entry point for an accel_fw function, call the sw implmentation that's built into the accel_fw transparently. Also update the accel_perf app to no longer block attempts to use capabilities not reported as supported by the selected engine but instead to print an informational message. The exception is batch related commands as their implementation is specific to the engine. Signed-off-by: paul luse Change-Id: I0b3971d075ced20182f97e95147e8887103e68cd Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/2930 Tested-by: SPDK CI Jenkins Reviewed-by: Jim Harris Reviewed-by: Ben Walker Community-CI: Mellanox Build Bot --- examples/accel/perf/accel_perf.c | 6 +- lib/accel/accel_engine.c | 118 +++++++++++++++++++++++-------- 2 files changed, 89 insertions(+), 35 deletions(-) diff --git a/examples/accel/perf/accel_perf.c b/examples/accel/perf/accel_perf.c index 42095c547..17a406af9 100644 --- a/examples/accel/perf/accel_perf.c +++ b/examples/accel/perf/accel_perf.c @@ -639,10 +639,8 @@ accel_perf_start(void *arg1) spdk_put_io_channel(accel_ch); if ((g_capabilites & g_workload_selection) != g_workload_selection) { - SPDK_ERRLOG("Selected workload is not supported by the current engine\n"); - SPDK_NOTICELOG("Software engine is selected by default, enable a HW engine via RPC\n\n"); - spdk_app_stop(-1); - return; + SPDK_WARNLOG("The selected workload is not natively supported by the current engine\n"); + SPDK_WARNLOG("The software engine will be used instead.\n\n"); } g_tsc_rate = spdk_get_ticks_hz(); diff --git a/lib/accel/accel_engine.c b/lib/accel/accel_engine.c index 31e8b2925..1d538965b 100644 --- a/lib/accel/accel_engine.c +++ b/lib/accel/accel_engine.c @@ -68,6 +68,20 @@ struct accel_io_channel { struct spdk_io_channel *ch; }; +/* Forward declarations of software implementations used when an + * engine has not implemented the capability. + */ +static int sw_accel_submit_dualcast(void *cb_arg, struct spdk_io_channel *ch, void *dst1, + void *dst2, void *src, uint64_t nbytes, spdk_accel_completion_cb cb); +static int sw_accel_submit_copy(void *cb_arg, struct spdk_io_channel *ch, void *dst, void *src, + uint64_t nbytes, spdk_accel_completion_cb cb); +static int sw_accel_submit_compare(void *cb_arg, struct spdk_io_channel *ch, void *src1, void *src2, + uint64_t nbytes, spdk_accel_completion_cb cb); +static int sw_accel_submit_fill(void *cb_arg, struct spdk_io_channel *ch, void *dst, uint8_t fill, + uint64_t nbytes, spdk_accel_completion_cb cb); +static int sw_accel_submit_crc32c(void *cb_arg, struct spdk_io_channel *ch, uint32_t *dst, + void *src, uint32_t seed, uint64_t nbytes, spdk_accel_completion_cb cb); + /* Registration of hw modules (currently supports only 1 at a time) */ void spdk_accel_hw_engine_register(struct spdk_accel_engine *accel_engine) @@ -107,6 +121,7 @@ spdk_accel_get_capabilities(struct spdk_io_channel *ch) { struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch); + /* All engines are required to implement this API. */ return accel_ch->engine->get_capabilities(); } @@ -118,8 +133,15 @@ spdk_accel_submit_copy(struct spdk_accel_task *accel_req, struct spdk_io_channel struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch); accel_req->cb = cb; - return accel_ch->engine->copy(accel_req->offload_ctx, accel_ch->ch, dst, src, nbytes, - _accel_engine_done); + + /* If the engine does not support it, fallback to the sw implementation. */ + if (accel_ch->engine->copy) { + return accel_ch->engine->copy(accel_req->offload_ctx, accel_ch->ch, dst, src, nbytes, + _accel_engine_done); + } else { + return sw_accel_submit_copy(accel_req->offload_ctx, accel_ch->ch, dst, src, nbytes, + _accel_engine_done); + } } /* Accel framework public API for dual cast copy function */ @@ -136,11 +158,20 @@ spdk_accel_submit_dualcast(struct spdk_accel_task *accel_req, struct spdk_io_cha } accel_req->cb = cb; - return accel_ch->engine->dualcast(accel_req->offload_ctx, accel_ch->ch, dst1, dst2, src, nbytes, - _accel_engine_done); + + /* If the engine does not support it, fallback to the sw implementation. */ + if (accel_ch->engine->dualcast) { + return accel_ch->engine->dualcast(accel_req->offload_ctx, accel_ch->ch, dst1, dst2, src, nbytes, + _accel_engine_done); + } else { + return sw_accel_submit_dualcast(accel_req->offload_ctx, accel_ch->ch, dst1, dst2, src, nbytes, + _accel_engine_done); + } } -/* Accel framework public API for batch_create function */ +/* Accel framework public API for batch_create function. All engines are + * required to implement this API. + */ struct spdk_accel_batch * spdk_accel_batch_create(struct spdk_io_channel *ch) { @@ -149,7 +180,9 @@ spdk_accel_batch_create(struct spdk_io_channel *ch) return accel_ch->engine->batch_create(accel_ch->ch); } -/* Accel framework public API for batch_submit function */ +/* Accel framework public API for batch_submit function. All engines are + * required to implement this API. + */ int spdk_accel_batch_submit(struct spdk_accel_task *accel_req, struct spdk_io_channel *ch, struct spdk_accel_batch *batch, spdk_accel_completion_cb cb) @@ -161,7 +194,9 @@ spdk_accel_batch_submit(struct spdk_accel_task *accel_req, struct spdk_io_channe _accel_engine_done); } -/* Accel framework public API for getting max batch */ +/* Accel framework public API for getting max batch. All engines are + * required to implement this API. + */ uint32_t spdk_accel_batch_get_max(struct spdk_io_channel *ch) { @@ -170,7 +205,9 @@ spdk_accel_batch_get_max(struct spdk_io_channel *ch) return accel_ch->engine->batch_get_max(); } -/* Accel framework public API for batch prep_copy function */ +/* Accel framework public API for batch prep_copy function. All engines are + * required to implement this API. + */ int spdk_accel_batch_prep_copy(struct spdk_accel_task *accel_req, struct spdk_io_channel *ch, struct spdk_accel_batch *batch, void *dst, void *src, uint64_t nbytes, @@ -180,11 +217,12 @@ spdk_accel_batch_prep_copy(struct spdk_accel_task *accel_req, struct spdk_io_cha accel_req->cb = cb; return accel_ch->engine->batch_prep_copy(accel_req->offload_ctx, accel_ch->ch, batch, dst, src, - nbytes, - _accel_engine_done); + nbytes, _accel_engine_done); } -/* Accel framework public API for batch prep_dualcast function */ +/* Accel framework public API for batch prep_dualcast function. All engines are + * required to implement this API. + */ int spdk_accel_batch_prep_dualcast(struct spdk_accel_task *accel_req, struct spdk_io_channel *ch, struct spdk_accel_batch *batch, void *dst1, void *dst2, void *src, uint64_t nbytes, @@ -202,7 +240,9 @@ spdk_accel_batch_prep_dualcast(struct spdk_accel_task *accel_req, struct spdk_io batch, dst1, dst2, src, nbytes, _accel_engine_done); } -/* Accel framework public API for batch prep_compare function */ +/* Accel framework public API for batch prep_compare function. All engines are + * required to implement this API. + */ int spdk_accel_batch_prep_compare(struct spdk_accel_task *accel_req, struct spdk_io_channel *ch, struct spdk_accel_batch *batch, void *src1, void *src2, uint64_t nbytes, @@ -223,8 +263,15 @@ spdk_accel_submit_compare(struct spdk_accel_task *accel_req, struct spdk_io_chan struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch); accel_req->cb = cb; - return accel_ch->engine->compare(accel_req->offload_ctx, accel_ch->ch, src1, src2, nbytes, - _accel_engine_done); + + /* If the engine does not support it, fallback to the sw implementation. */ + if (accel_ch->engine->compare) { + return accel_ch->engine->compare(accel_req->offload_ctx, accel_ch->ch, src1, src2, nbytes, + _accel_engine_done); + } else { + return sw_accel_submit_compare(accel_req->offload_ctx, accel_ch->ch, src1, src2, nbytes, + _accel_engine_done); + } } /* Accel framework public API for fill function */ @@ -235,8 +282,15 @@ spdk_accel_submit_fill(struct spdk_accel_task *accel_req, struct spdk_io_channel struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch); accel_req->cb = cb; - return accel_ch->engine->fill(accel_req->offload_ctx, accel_ch->ch, dst, fill, nbytes, - _accel_engine_done); + + /* If the engine does not support it, fallback to the sw implementation. */ + if (accel_ch->engine->fill) { + return accel_ch->engine->fill(accel_req->offload_ctx, accel_ch->ch, dst, fill, nbytes, + _accel_engine_done); + } else { + return sw_accel_submit_fill(accel_req->offload_ctx, accel_ch->ch, dst, fill, nbytes, + _accel_engine_done); + } } /* Accel framework public API for CRC-32C function */ @@ -247,10 +301,16 @@ spdk_accel_submit_crc32c(struct spdk_accel_task *accel_req, struct spdk_io_chann struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch); accel_req->cb = cb; - return accel_ch->engine->crc32c(accel_req->offload_ctx, accel_ch->ch, dst, src, - seed, nbytes, _accel_engine_done); -} + /* If the engine does not support it, fallback to the sw implementation. */ + if (accel_ch->engine->crc32c) { + return accel_ch->engine->crc32c(accel_req->offload_ctx, accel_ch->ch, dst, src, + seed, nbytes, _accel_engine_done); + } else { + return sw_accel_submit_crc32c(accel_req->offload_ctx, accel_ch->ch, dst, src, + seed, nbytes, _accel_engine_done); + } +} /* Returns the largest context size of the accel modules. */ size_t @@ -521,8 +581,8 @@ sw_accel_batch_prep_copy(void *cb_arg, struct spdk_io_channel *ch, struct spdk_a static int sw_accel_batch_prep_dualcast(void *cb_arg, struct spdk_io_channel *ch, - struct spdk_accel_batch *batch, - void *dst1, void *dst2, void *src, uint64_t nbytes, spdk_accel_completion_cb cb) + struct spdk_accel_batch *batch, void *dst1, void *dst2, + void *src, 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); @@ -545,8 +605,8 @@ sw_accel_batch_prep_dualcast(void *cb_arg, struct spdk_io_channel *ch, static int sw_accel_batch_prep_compare(void *cb_arg, struct spdk_io_channel *ch, - struct spdk_accel_batch *batch, - void *src1, void *src2, uint64_t nbytes, spdk_accel_completion_cb cb) + struct spdk_accel_batch *batch, void *src1, + void *src2, 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); @@ -617,8 +677,7 @@ sw_accel_batch_submit(void *cb_arg, struct spdk_io_channel *ch, struct spdk_acce static int sw_accel_submit_copy(void *cb_arg, struct spdk_io_channel *ch, void *dst, void *src, - uint64_t nbytes, - spdk_accel_completion_cb cb) + uint64_t nbytes, spdk_accel_completion_cb cb) { struct spdk_accel_task *accel_req; @@ -647,8 +706,7 @@ sw_accel_submit_dualcast(void *cb_arg, struct spdk_io_channel *ch, void *dst1, v static int sw_accel_submit_compare(void *cb_arg, struct spdk_io_channel *ch, void *src1, void *src2, - uint64_t nbytes, - spdk_accel_completion_cb cb) + uint64_t nbytes, spdk_accel_completion_cb cb) { struct spdk_accel_task *accel_req; int result; @@ -664,8 +722,7 @@ sw_accel_submit_compare(void *cb_arg, struct spdk_io_channel *ch, void *src1, vo static int sw_accel_submit_fill(void *cb_arg, struct spdk_io_channel *ch, void *dst, uint8_t fill, - uint64_t nbytes, - spdk_accel_completion_cb cb) + uint64_t nbytes, spdk_accel_completion_cb cb) { struct spdk_accel_task *accel_req; @@ -679,8 +736,7 @@ sw_accel_submit_fill(void *cb_arg, struct spdk_io_channel *ch, void *dst, uint8_ static int sw_accel_submit_crc32c(void *cb_arg, struct spdk_io_channel *ch, uint32_t *dst, void *src, - uint32_t seed, uint64_t nbytes, - spdk_accel_completion_cb cb) + uint32_t seed, uint64_t nbytes, spdk_accel_completion_cb cb) { struct spdk_accel_task *accel_req;