|
@@ -36,6 +36,7 @@
|
|
|
#include <linux/interrupt.h>
|
|
|
#include <crypto/scatterwalk.h>
|
|
|
#include <crypto/aes.h>
|
|
|
+#include <crypto/algapi.h>
|
|
|
|
|
|
#define DST_MAXBURST 4
|
|
|
#define DMA_MIN (DST_MAXBURST * sizeof(u32))
|
|
@@ -152,13 +153,10 @@ struct omap_aes_dev {
|
|
|
unsigned long flags;
|
|
|
int err;
|
|
|
|
|
|
- spinlock_t lock;
|
|
|
- struct crypto_queue queue;
|
|
|
-
|
|
|
struct tasklet_struct done_task;
|
|
|
- struct tasklet_struct queue_task;
|
|
|
|
|
|
struct ablkcipher_request *req;
|
|
|
+ struct crypto_engine *engine;
|
|
|
|
|
|
/*
|
|
|
* total is used by PIO mode for book keeping so introduce
|
|
@@ -532,9 +530,7 @@ static void omap_aes_finish_req(struct omap_aes_dev *dd, int err)
|
|
|
|
|
|
pr_debug("err: %d\n", err);
|
|
|
|
|
|
- dd->flags &= ~FLAGS_BUSY;
|
|
|
-
|
|
|
- req->base.complete(&req->base, err);
|
|
|
+ crypto_finalize_request(dd->engine, req, err);
|
|
|
}
|
|
|
|
|
|
static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)
|
|
@@ -604,34 +600,25 @@ static int omap_aes_copy_sgs(struct omap_aes_dev *dd)
|
|
|
}
|
|
|
|
|
|
static int omap_aes_handle_queue(struct omap_aes_dev *dd,
|
|
|
- struct ablkcipher_request *req)
|
|
|
+ struct ablkcipher_request *req)
|
|
|
{
|
|
|
- struct crypto_async_request *async_req, *backlog;
|
|
|
- struct omap_aes_ctx *ctx;
|
|
|
- struct omap_aes_reqctx *rctx;
|
|
|
- unsigned long flags;
|
|
|
- int err, ret = 0, len;
|
|
|
-
|
|
|
- spin_lock_irqsave(&dd->lock, flags);
|
|
|
if (req)
|
|
|
- ret = ablkcipher_enqueue_request(&dd->queue, req);
|
|
|
- if (dd->flags & FLAGS_BUSY) {
|
|
|
- spin_unlock_irqrestore(&dd->lock, flags);
|
|
|
- return ret;
|
|
|
- }
|
|
|
- backlog = crypto_get_backlog(&dd->queue);
|
|
|
- async_req = crypto_dequeue_request(&dd->queue);
|
|
|
- if (async_req)
|
|
|
- dd->flags |= FLAGS_BUSY;
|
|
|
- spin_unlock_irqrestore(&dd->lock, flags);
|
|
|
+ return crypto_transfer_request_to_engine(dd->engine, req);
|
|
|
|
|
|
- if (!async_req)
|
|
|
- return ret;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
|
|
|
- if (backlog)
|
|
|
- backlog->complete(backlog, -EINPROGRESS);
|
|
|
+static int omap_aes_prepare_req(struct crypto_engine *engine,
|
|
|
+ struct ablkcipher_request *req)
|
|
|
+{
|
|
|
+ struct omap_aes_ctx *ctx = crypto_ablkcipher_ctx(
|
|
|
+ crypto_ablkcipher_reqtfm(req));
|
|
|
+ struct omap_aes_dev *dd = omap_aes_find_dev(ctx);
|
|
|
+ struct omap_aes_reqctx *rctx;
|
|
|
+ int len;
|
|
|
|
|
|
- req = ablkcipher_request_cast(async_req);
|
|
|
+ if (!dd)
|
|
|
+ return -ENODEV;
|
|
|
|
|
|
/* assign new request to device */
|
|
|
dd->req = req;
|
|
@@ -662,16 +649,20 @@ static int omap_aes_handle_queue(struct omap_aes_dev *dd,
|
|
|
dd->ctx = ctx;
|
|
|
ctx->dd = dd;
|
|
|
|
|
|
- err = omap_aes_write_ctrl(dd);
|
|
|
- if (!err)
|
|
|
- err = omap_aes_crypt_dma_start(dd);
|
|
|
- if (err) {
|
|
|
- /* aes_task will not finish it, so do it here */
|
|
|
- omap_aes_finish_req(dd, err);
|
|
|
- tasklet_schedule(&dd->queue_task);
|
|
|
- }
|
|
|
+ return omap_aes_write_ctrl(dd);
|
|
|
+}
|
|
|
|
|
|
- return ret; /* return ret, which is enqueue return value */
|
|
|
+static int omap_aes_crypt_req(struct crypto_engine *engine,
|
|
|
+ struct ablkcipher_request *req)
|
|
|
+{
|
|
|
+ struct omap_aes_ctx *ctx = crypto_ablkcipher_ctx(
|
|
|
+ crypto_ablkcipher_reqtfm(req));
|
|
|
+ struct omap_aes_dev *dd = omap_aes_find_dev(ctx);
|
|
|
+
|
|
|
+ if (!dd)
|
|
|
+ return -ENODEV;
|
|
|
+
|
|
|
+ return omap_aes_crypt_dma_start(dd);
|
|
|
}
|
|
|
|
|
|
static void omap_aes_done_task(unsigned long data)
|
|
@@ -704,18 +695,10 @@ static void omap_aes_done_task(unsigned long data)
|
|
|
}
|
|
|
|
|
|
omap_aes_finish_req(dd, 0);
|
|
|
- omap_aes_handle_queue(dd, NULL);
|
|
|
|
|
|
pr_debug("exit\n");
|
|
|
}
|
|
|
|
|
|
-static void omap_aes_queue_task(unsigned long data)
|
|
|
-{
|
|
|
- struct omap_aes_dev *dd = (struct omap_aes_dev *)data;
|
|
|
-
|
|
|
- omap_aes_handle_queue(dd, NULL);
|
|
|
-}
|
|
|
-
|
|
|
static int omap_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
|
|
|
{
|
|
|
struct omap_aes_ctx *ctx = crypto_ablkcipher_ctx(
|
|
@@ -1175,9 +1158,6 @@ static int omap_aes_probe(struct platform_device *pdev)
|
|
|
dd->dev = dev;
|
|
|
platform_set_drvdata(pdev, dd);
|
|
|
|
|
|
- spin_lock_init(&dd->lock);
|
|
|
- crypto_init_queue(&dd->queue, OMAP_AES_QUEUE_LENGTH);
|
|
|
-
|
|
|
err = (dev->of_node) ? omap_aes_get_res_of(dd, dev, &res) :
|
|
|
omap_aes_get_res_pdev(dd, pdev, &res);
|
|
|
if (err)
|
|
@@ -1209,7 +1189,6 @@ static int omap_aes_probe(struct platform_device *pdev)
|
|
|
(reg & dd->pdata->minor_mask) >> dd->pdata->minor_shift);
|
|
|
|
|
|
tasklet_init(&dd->done_task, omap_aes_done_task, (unsigned long)dd);
|
|
|
- tasklet_init(&dd->queue_task, omap_aes_queue_task, (unsigned long)dd);
|
|
|
|
|
|
err = omap_aes_dma_init(dd);
|
|
|
if (err && AES_REG_IRQ_STATUS(dd) && AES_REG_IRQ_ENABLE(dd)) {
|
|
@@ -1250,7 +1229,20 @@ static int omap_aes_probe(struct platform_device *pdev)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /* Initialize crypto engine */
|
|
|
+ dd->engine = crypto_engine_alloc_init(dev, 1);
|
|
|
+ if (!dd->engine)
|
|
|
+ goto err_algs;
|
|
|
+
|
|
|
+ dd->engine->prepare_request = omap_aes_prepare_req;
|
|
|
+ dd->engine->crypt_one_request = omap_aes_crypt_req;
|
|
|
+ err = crypto_engine_start(dd->engine);
|
|
|
+ if (err)
|
|
|
+ goto err_engine;
|
|
|
+
|
|
|
return 0;
|
|
|
+err_engine:
|
|
|
+ crypto_engine_exit(dd->engine);
|
|
|
err_algs:
|
|
|
for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
|
|
|
for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
|
|
@@ -1260,7 +1252,6 @@ err_algs:
|
|
|
omap_aes_dma_cleanup(dd);
|
|
|
err_irq:
|
|
|
tasklet_kill(&dd->done_task);
|
|
|
- tasklet_kill(&dd->queue_task);
|
|
|
pm_runtime_disable(dev);
|
|
|
err_res:
|
|
|
dd = NULL;
|
|
@@ -1286,8 +1277,8 @@ static int omap_aes_remove(struct platform_device *pdev)
|
|
|
crypto_unregister_alg(
|
|
|
&dd->pdata->algs_info[i].algs_list[j]);
|
|
|
|
|
|
+ crypto_engine_exit(dd->engine);
|
|
|
tasklet_kill(&dd->done_task);
|
|
|
- tasklet_kill(&dd->queue_task);
|
|
|
omap_aes_dma_cleanup(dd);
|
|
|
pm_runtime_disable(dd->dev);
|
|
|
dd = NULL;
|