2020-03-08 22:52:36

by Iuliana Prodan

[permalink] [raw]
Subject: [PATCH v4 0/2] crypto: engine - support for parallel and batch requests

Added support for executing multiple, independent or not, requests
for crypto engine. This is based on the return value of
do_one_request(), which is expected to be:
> 0: if hardware still has space in its queue. A driver can implement
do_one_request() to return the number of free entries in
hardware queue;
0: if the request was accepted, by hardware, with success, but the
hardware doesn't support multiple requests or there is no space
left in the hardware queue.
This is to keep the backward compatibility of crypto-engine.
< 0: error.

If hardware supports batch requests, crypto-engine can handle this use-case
through do_batch_requests callback.

Since, these new features, cannot be supported by all hardware,
the crypto-engine framework is backward compatible:
- by using the crypto_engine_alloc_init function, to initialize
crypto-engine, the new callback is NULL and, if do_one_request()
returns 0, crypto-engine will work as before these changes;
- to support multiple requests, in parallel, do_one_request()
needs to be updated to return > 0.
On crypto_pump_requests(), if do_one_request() returns > 0,
a new request is send to hardware, until there is no space
and do_one_request() returns 0.
- to support batch requests, do_batch_requests callback must be
implemented in driver, to execute a batch of requests. The link
between the requests, is expected to be done in driver, in
do_one_request().

---
Changes since V3:
- removed can_enqueue_hardware callback and added a start-stop
mechanism based on the on the return value of do_one_request().

Changes since V2:
- readded cur_req in crypto-engine, to keep, the exact behavior as before
these changes, if can_enqueue_more is not implemented: send requests
to hardware, _one-by-one_, on crypto_pump_requests, and complete it,
on crypto_finalize_request, and so on.
- do_batch_requests is available only with can_enqueue_more.

Changes since V1:
- changed the name of can_enqueue_hardware callback to can_enqueue_more, and
the argument of this callback to crypto_engine structure (for cases when more
than ore crypto-engine is used).
- added a new patch with support for batch requests.

Changes since V0 (RFC):
- removed max_no_req and no_req, as the number of request that can be
processed in parallel;
- added a new callback, can_enqueue_more, to check whether the hardware
can process a new request.

Iuliana Prodan (2):
crypto: engine - support for parallel requests
crypto: engine - support for batch requests

crypto/crypto_engine.c | 150 ++++++++++++++++++++++++++++++++++++------------
include/crypto/engine.h | 15 +++--
2 files changed, 124 insertions(+), 41 deletions(-)

--
2.1.0


2020-03-08 22:52:53

by Iuliana Prodan

[permalink] [raw]
Subject: [PATCH v4 2/2] crypto: engine - support for batch requests

Added support for batch requests, per crypto engine.
A new callback is added, do_batch_requests, which executes a
batch of requests. This has the crypto_engine structure as argument
(for cases when more than one crypto-engine is used).
The crypto_engine_alloc_init_and_set function, initializes
crypto-engine, but also, sets the do_batch_requests callback.
On crypto_pump_requests, if do_batch_requests callback is
implemented in a driver, this will be executed. The link between
the requests will be done in driver, if possible.
do_batch_requests is available only if the hardware has support
for multiple request.

Signed-off-by: Iuliana Prodan <[email protected]>
---
crypto/crypto_engine.c | 30 +++++++++++++++++++++++++++---
include/crypto/engine.h | 4 ++++
2 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/crypto/crypto_engine.c b/crypto/crypto_engine.c
index dbfd53c2..80723ad 100644
--- a/crypto/crypto_engine.c
+++ b/crypto/crypto_engine.c
@@ -116,8 +116,10 @@ static void crypto_pump_requests(struct crypto_engine *engine,
/* Get the fist request from the engine queue to handle */
backlog = crypto_get_backlog(&engine->queue);
async_req = crypto_dequeue_request(&engine->queue);
- if (!async_req)
- goto out;
+ if (!async_req) {
+ spin_unlock_irqrestore(&engine->queue_lock, flags);
+ goto batch;
+ }

if (backlog)
backlog->complete(backlog, -EINPROGRESS);
@@ -195,6 +197,19 @@ static void crypto_pump_requests(struct crypto_engine *engine,

out:
spin_unlock_irqrestore(&engine->queue_lock, flags);
+
+batch:
+ /*
+ * Batch requests is possible only if
+ * hardware can enqueue multiple requests
+ */
+ if (engine->do_batch_requests) {
+ ret = engine->do_batch_requests(engine);
+ if (ret)
+ dev_err(engine->dev, "failed to do batch requests: %d\n",
+ ret);
+ }
+ return;
}

static void crypto_pump_work(struct kthread_work *work)
@@ -422,6 +437,12 @@ EXPORT_SYMBOL_GPL(crypto_engine_stop);
* and initialize it by setting the maximum number of entries in the software
* crypto-engine queue.
* @dev: the device attached with one hardware engine
+ * @cbk_do_batch: pointer to a callback function to be invoked when executing a
+ * a batch of requests.
+ * This has the form:
+ * callback(struct crypto_engine *engine)
+ * where:
+ * @engine: the crypto engine structure.
* @rt: whether this queue is set to run as a realtime task
* @qlen: maximum size of the crypto-engine queue
*
@@ -429,6 +450,7 @@ EXPORT_SYMBOL_GPL(crypto_engine_stop);
* Return: the crypto engine structure on success, else NULL.
*/
struct crypto_engine *crypto_engine_alloc_init_and_set(struct device *dev,
+ int (*cbk_do_batch)(struct crypto_engine *engine),
bool rt, int qlen)
{
struct sched_param param = { .sched_priority = MAX_RT_PRIO / 2 };
@@ -449,6 +471,8 @@ struct crypto_engine *crypto_engine_alloc_init_and_set(struct device *dev,
engine->cnt_do_req = 0;
engine->cnt_finalize = 0;
engine->priv_data = dev;
+ engine->do_batch_requests = cbk_do_batch;
+
snprintf(engine->name, sizeof(engine->name),
"%s-engine", dev_name(dev));

@@ -482,7 +506,7 @@ EXPORT_SYMBOL_GPL(crypto_engine_alloc_init_and_set);
*/
struct crypto_engine *crypto_engine_alloc_init(struct device *dev, bool rt)
{
- return crypto_engine_alloc_init_and_set(dev, rt,
+ return crypto_engine_alloc_init_and_set(dev, NULL, rt,
CRYPTO_ENGINE_MAX_QLEN);
}
EXPORT_SYMBOL_GPL(crypto_engine_alloc_init);
diff --git a/include/crypto/engine.h b/include/crypto/engine.h
index 33a5be2..c64d942 100644
--- a/include/crypto/engine.h
+++ b/include/crypto/engine.h
@@ -36,6 +36,7 @@
* @unprepare_crypt_hardware: there are currently no more requests on the
* queue so the subsystem notifies the driver that it may relax the
* hardware by issuing this call
+ * @do_batch_requests: execute a batch of requests
* @kworker: kthread worker struct for request pump
* @pump_requests: work struct for scheduling work to the request pump
* @priv_data: the engine private data
@@ -58,6 +59,8 @@ struct crypto_engine {

int (*prepare_crypt_hardware)(struct crypto_engine *engine);
int (*unprepare_crypt_hardware)(struct crypto_engine *engine);
+ int (*do_batch_requests)(struct crypto_engine *engine);
+

struct kthread_worker *kworker;
struct kthread_work pump_requests;
@@ -104,6 +107,7 @@ int crypto_engine_start(struct crypto_engine *engine);
int crypto_engine_stop(struct crypto_engine *engine);
struct crypto_engine *crypto_engine_alloc_init(struct device *dev, bool rt);
struct crypto_engine *crypto_engine_alloc_init_and_set(struct device *dev,
+ int (*cbk_do_batch)(struct crypto_engine *engine),
bool rt, int qlen);
int crypto_engine_exit(struct crypto_engine *engine);

--
2.1.0