mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-16 00:34:20 +08:00
crypto: omap-aes - Support crypto engine framework
Integrate with the newly added crypto engine to make the crypto hardware engine underutilized as each block needs to be processed before the crypto hardware can start working on the next block. The requests from dm-crypt will be listed into engine queue and processed by engine automatically, so remove the 'queue' and 'queue_task' things in omap aes driver. Signed-off-by: Baolin Wang <baolin.wang@linaro.org> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
parent
735d37b542
commit
0529900a01
@ -296,6 +296,7 @@ config CRYPTO_DEV_OMAP_AES
|
|||||||
depends on ARCH_OMAP2 || ARCH_OMAP3 || ARCH_OMAP2PLUS
|
depends on ARCH_OMAP2 || ARCH_OMAP3 || ARCH_OMAP2PLUS
|
||||||
select CRYPTO_AES
|
select CRYPTO_AES
|
||||||
select CRYPTO_BLKCIPHER
|
select CRYPTO_BLKCIPHER
|
||||||
|
select CRYPTO_ENGINE
|
||||||
help
|
help
|
||||||
OMAP processors have AES module accelerator. Select this if you
|
OMAP processors have AES module accelerator. Select this if you
|
||||||
want to use the OMAP module for AES algorithms.
|
want to use the OMAP module for AES algorithms.
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <crypto/scatterwalk.h>
|
#include <crypto/scatterwalk.h>
|
||||||
#include <crypto/aes.h>
|
#include <crypto/aes.h>
|
||||||
|
#include <crypto/algapi.h>
|
||||||
|
|
||||||
#define DST_MAXBURST 4
|
#define DST_MAXBURST 4
|
||||||
#define DMA_MIN (DST_MAXBURST * sizeof(u32))
|
#define DMA_MIN (DST_MAXBURST * sizeof(u32))
|
||||||
@ -152,13 +153,10 @@ struct omap_aes_dev {
|
|||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
spinlock_t lock;
|
|
||||||
struct crypto_queue queue;
|
|
||||||
|
|
||||||
struct tasklet_struct done_task;
|
struct tasklet_struct done_task;
|
||||||
struct tasklet_struct queue_task;
|
|
||||||
|
|
||||||
struct ablkcipher_request *req;
|
struct ablkcipher_request *req;
|
||||||
|
struct crypto_engine *engine;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* total is used by PIO mode for book keeping so introduce
|
* 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);
|
pr_debug("err: %d\n", err);
|
||||||
|
|
||||||
dd->flags &= ~FLAGS_BUSY;
|
crypto_finalize_request(dd->engine, req, err);
|
||||||
|
|
||||||
req->base.complete(&req->base, err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)
|
static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)
|
||||||
@ -606,32 +602,23 @@ static int omap_aes_copy_sgs(struct omap_aes_dev *dd)
|
|||||||
static int omap_aes_handle_queue(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)
|
if (req)
|
||||||
ret = ablkcipher_enqueue_request(&dd->queue, req);
|
return crypto_transfer_request_to_engine(dd->engine, 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);
|
|
||||||
|
|
||||||
if (!async_req)
|
return 0;
|
||||||
return ret;
|
}
|
||||||
|
|
||||||
if (backlog)
|
static int omap_aes_prepare_req(struct crypto_engine *engine,
|
||||||
backlog->complete(backlog, -EINPROGRESS);
|
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 */
|
/* assign new request to device */
|
||||||
dd->req = req;
|
dd->req = req;
|
||||||
@ -662,16 +649,20 @@ static int omap_aes_handle_queue(struct omap_aes_dev *dd,
|
|||||||
dd->ctx = ctx;
|
dd->ctx = ctx;
|
||||||
ctx->dd = dd;
|
ctx->dd = dd;
|
||||||
|
|
||||||
err = omap_aes_write_ctrl(dd);
|
return 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 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)
|
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_finish_req(dd, 0);
|
||||||
omap_aes_handle_queue(dd, NULL);
|
|
||||||
|
|
||||||
pr_debug("exit\n");
|
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)
|
static int omap_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
|
||||||
{
|
{
|
||||||
struct omap_aes_ctx *ctx = crypto_ablkcipher_ctx(
|
struct omap_aes_ctx *ctx = crypto_ablkcipher_ctx(
|
||||||
@ -1175,9 +1158,6 @@ static int omap_aes_probe(struct platform_device *pdev)
|
|||||||
dd->dev = dev;
|
dd->dev = dev;
|
||||||
platform_set_drvdata(pdev, dd);
|
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) :
|
err = (dev->of_node) ? omap_aes_get_res_of(dd, dev, &res) :
|
||||||
omap_aes_get_res_pdev(dd, pdev, &res);
|
omap_aes_get_res_pdev(dd, pdev, &res);
|
||||||
if (err)
|
if (err)
|
||||||
@ -1209,7 +1189,6 @@ static int omap_aes_probe(struct platform_device *pdev)
|
|||||||
(reg & dd->pdata->minor_mask) >> dd->pdata->minor_shift);
|
(reg & dd->pdata->minor_mask) >> dd->pdata->minor_shift);
|
||||||
|
|
||||||
tasklet_init(&dd->done_task, omap_aes_done_task, (unsigned long)dd);
|
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);
|
err = omap_aes_dma_init(dd);
|
||||||
if (err && AES_REG_IRQ_STATUS(dd) && AES_REG_IRQ_ENABLE(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;
|
return 0;
|
||||||
|
err_engine:
|
||||||
|
crypto_engine_exit(dd->engine);
|
||||||
err_algs:
|
err_algs:
|
||||||
for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
|
for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
|
||||||
for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
|
for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
|
||||||
@ -1260,7 +1252,6 @@ err_algs:
|
|||||||
omap_aes_dma_cleanup(dd);
|
omap_aes_dma_cleanup(dd);
|
||||||
err_irq:
|
err_irq:
|
||||||
tasklet_kill(&dd->done_task);
|
tasklet_kill(&dd->done_task);
|
||||||
tasklet_kill(&dd->queue_task);
|
|
||||||
pm_runtime_disable(dev);
|
pm_runtime_disable(dev);
|
||||||
err_res:
|
err_res:
|
||||||
dd = NULL;
|
dd = NULL;
|
||||||
@ -1286,8 +1277,8 @@ static int omap_aes_remove(struct platform_device *pdev)
|
|||||||
crypto_unregister_alg(
|
crypto_unregister_alg(
|
||||||
&dd->pdata->algs_info[i].algs_list[j]);
|
&dd->pdata->algs_info[i].algs_list[j]);
|
||||||
|
|
||||||
|
crypto_engine_exit(dd->engine);
|
||||||
tasklet_kill(&dd->done_task);
|
tasklet_kill(&dd->done_task);
|
||||||
tasklet_kill(&dd->queue_task);
|
|
||||||
omap_aes_dma_cleanup(dd);
|
omap_aes_dma_cleanup(dd);
|
||||||
pm_runtime_disable(dd->dev);
|
pm_runtime_disable(dd->dev);
|
||||||
dd = NULL;
|
dd = NULL;
|
||||||
|
Loading…
Reference in New Issue
Block a user