2010-11-30 08:13:26

by Dmitry Kasatkin

[permalink] [raw]
Subject: [PATCHv2 0/6] omap-aes off mode and error handling fixes

Changes to v1:
- omap type specific handling removed
- fixed backlog handling bug in "redundunt locking is removed"
- aes module initialized once per request instead of dma transaction
more efficient and right way to do it
- checkpatch fixes in separate patch


Dmitry Kasatkin (6):
omap-aes: DMA initialization fixes for OMAP off mode
omap-aes: redundant locking is removed
omap-aes: error handling implementation improved
omap-aes: unnecessary code removed
omap-aes: initialize aes module once per request
omap-aes: checkpatch --file warning fixes

drivers/crypto/omap-aes.c | 260 +++++++++++++++++++++++---------------------
1 files changed, 136 insertions(+), 124 deletions(-)



2010-11-30 08:13:27

by Dmitry Kasatkin

[permalink] [raw]
Subject: [PATCHv2 1/6] omap-aes: DMA initialization fixes for OMAP off mode

DMA parameters for constant data were initialized during driver probe().
It seems that those settings sometimes are lost when devices goes to off mode.
This patch makes DMA initialization just before use.
It solves off mode problems.

Signed-off-by: Dmitry Kasatkin <[email protected]>
---
drivers/crypto/omap-aes.c | 24 ++++++++++++------------
1 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index 799ca51..41c91f3 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -339,18 +339,6 @@ static int omap_aes_dma_init(struct omap_aes_dev *dd)
goto err_dma_out;
}

- omap_set_dma_dest_params(dd->dma_lch_in, 0, OMAP_DMA_AMODE_CONSTANT,
- dd->phys_base + AES_REG_DATA, 0, 4);
-
- omap_set_dma_dest_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4);
- omap_set_dma_src_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4);
-
- omap_set_dma_src_params(dd->dma_lch_out, 0, OMAP_DMA_AMODE_CONSTANT,
- dd->phys_base + AES_REG_DATA, 0, 4);
-
- omap_set_dma_src_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4);
- omap_set_dma_dest_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4);
-
return 0;

err_dma_out:
@@ -443,6 +431,12 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
len32 = DIV_ROUND_UP(length, sizeof(u32));

/* IN */
+ omap_set_dma_dest_params(dd->dma_lch_in, 0, OMAP_DMA_AMODE_CONSTANT,
+ dd->phys_base + AES_REG_DATA, 0, 4);
+
+ omap_set_dma_dest_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4);
+ omap_set_dma_src_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4);
+
omap_set_dma_transfer_params(dd->dma_lch_in, OMAP_DMA_DATA_TYPE_S32,
len32, 1, OMAP_DMA_SYNC_PACKET, dd->dma_in,
OMAP_DMA_DST_SYNC);
@@ -451,6 +445,12 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
dma_addr_in, 0, 0);

/* OUT */
+ omap_set_dma_src_params(dd->dma_lch_out, 0, OMAP_DMA_AMODE_CONSTANT,
+ dd->phys_base + AES_REG_DATA, 0, 4);
+
+ omap_set_dma_src_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4);
+ omap_set_dma_dest_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4);
+
omap_set_dma_transfer_params(dd->dma_lch_out, OMAP_DMA_DATA_TYPE_S32,
len32, 1, OMAP_DMA_SYNC_PACKET,
dd->dma_out, OMAP_DMA_SRC_SYNC);
--
1.7.0.4


2010-11-30 08:13:29

by Dmitry Kasatkin

[permalink] [raw]
Subject: [PATCHv2 3/6] omap-aes: error handling implementation improved

Previous version had not error handling.
Request could remain uncompleted.

Also in the case of DMA error, FLAGS_INIT is unset
and accelerator will be initialized again.

Buffer size allignment is checked.

Signed-off-by: Dmitry Kasatkin <[email protected]>
---
drivers/crypto/omap-aes.c | 134 +++++++++++++++++++++++++++++++--------------
1 files changed, 93 insertions(+), 41 deletions(-)

diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index 2d8f72e..704cc70 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -103,14 +103,16 @@ struct omap_aes_dev {
struct omap_aes_ctx *ctx;
struct device *dev;
unsigned long flags;
+ int err;

u32 *iv;
u32 ctrl;

- spinlock_t lock;
- struct crypto_queue queue;
+ spinlock_t lock;
+ struct crypto_queue queue;

- struct tasklet_struct task;
+ struct tasklet_struct done_task;
+ struct tasklet_struct queue_task;

struct ablkcipher_request *req;
size_t total;
@@ -198,24 +200,30 @@ static int omap_aes_hw_init(struct omap_aes_dev *dd)
return -ETIMEDOUT;
}
dd->flags |= FLAGS_INIT;
+ dd->err = 0;
}

return 0;
}

-static void omap_aes_write_ctrl(struct omap_aes_dev *dd)
+static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
{
unsigned int key32;
- int i;
+ int i, err, init = dd->flags & FLAGS_INIT;
u32 val, mask;

+ err = omap_aes_hw_init(dd);
+ if (err)
+ return err;
+
val = FLD_VAL(((dd->ctx->keylen >> 3) - 1), 4, 3);
if (dd->flags & FLAGS_CBC)
val |= AES_REG_CTRL_CBC;
if (dd->flags & FLAGS_ENCRYPT)
val |= AES_REG_CTRL_DIRECTION;

- if (dd->ctrl == val && !(dd->flags & FLAGS_NEW_IV) &&
+ /* check if hw state & mode have not changed */
+ if (init && dd->ctrl == val && !(dd->flags & FLAGS_NEW_IV) &&
!(dd->ctx->flags & FLAGS_NEW_KEY))
goto out;

@@ -257,6 +265,8 @@ out:
/* start DMA or disable idle mode */
omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_START,
AES_REG_MASK_START);
+
+ return 0;
}

static struct omap_aes_dev *omap_aes_find_dev(struct omap_aes_ctx *ctx)
@@ -284,8 +294,16 @@ static void omap_aes_dma_callback(int lch, u16 ch_status, void *data)
{
struct omap_aes_dev *dd = data;

- if (lch == dd->dma_lch_out)
- tasklet_schedule(&dd->task);
+ if (ch_status != OMAP_DMA_BLOCK_IRQ) {
+ pr_err("omap-aes DMA error status: 0x%hx\n", ch_status);
+ dd->err = -EIO;
+ dd->flags &= ~FLAGS_INIT; /* request to re-initialize */
+ } else if (lch == dd->dma_lch_in) {
+ return;
+ }
+
+ /* dma_lch_out - completed */
+ tasklet_schedule(&dd->done_task);
}

static int omap_aes_dma_init(struct omap_aes_dev *dd)
@@ -390,6 +408,11 @@ static int sg_copy(struct scatterlist **sg, size_t *offset, void *buf,
if (!count)
return off;

+ /*
+ * buflen and total are AES_BLOCK_SIZE size aligned,
+ * so count should be also aligned
+ */
+
sg_copy_buf(buf + off, *sg, *offset, count, out);

off += count;
@@ -415,6 +438,7 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
struct omap_aes_ctx *ctx = crypto_tfm_ctx(tfm);
struct omap_aes_dev *dd = ctx->dd;
int len32;
+ int err;

pr_debug("len: %d\n", length);

@@ -454,11 +478,13 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
omap_set_dma_dest_params(dd->dma_lch_out, 0, OMAP_DMA_AMODE_POST_INC,
dma_addr_out, 0, 0);

+ err = omap_aes_write_ctrl(dd);
+ if (err)
+ return err;
+
omap_start_dma(dd->dma_lch_in);
omap_start_dma(dd->dma_lch_out);

- omap_aes_write_ctrl(dd);
-
return 0;
}

@@ -484,8 +510,10 @@ static int omap_aes_crypt_dma_start(struct omap_aes_dev *dd)
count = min(dd->total, sg_dma_len(dd->in_sg));
count = min(count, sg_dma_len(dd->out_sg));

- if (count != dd->total)
+ if (count != dd->total) {
+ pr_err("request length != buffer length\n");
return -EINVAL;
+ }

pr_debug("fast\n");

@@ -521,25 +549,28 @@ static int omap_aes_crypt_dma_start(struct omap_aes_dev *dd)

dd->total -= count;

- err = omap_aes_hw_init(dd);
-
err = omap_aes_crypt_dma(tfm, addr_in, addr_out, count);
+ if (err) {
+ dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
+ dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_TO_DEVICE);
+ }

return err;
}

static void omap_aes_finish_req(struct omap_aes_dev *dd, int err)
{
+ struct ablkcipher_request *req = dd->req;
struct omap_aes_ctx *ctx;

pr_debug("err: %d\n", err);

dd->flags &= ~FLAGS_BUSY;

- ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(dd->req));
+ ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(req));

- if (!dd->total)
- dd->req->base.complete(&dd->req->base, err);
+ if (req->base.complete)
+ req->base.complete(&req->base, err);
}

static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)
@@ -551,11 +582,11 @@ static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)

omap_aes_write_mask(dd, AES_REG_MASK, 0, AES_REG_MASK_START);

- clk_disable(dd->iclk);
-
omap_stop_dma(dd->dma_lch_in);
omap_stop_dma(dd->dma_lch_out);

+ clk_disable(dd->iclk);
+
if (dd->flags & FLAGS_FAST) {
dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE);
dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
@@ -572,27 +603,24 @@ static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)
}
}

- if (err || !dd->total)
- omap_aes_finish_req(dd, err);
-
return err;
}

-static int omap_aes_handle_req(struct omap_aes_dev *dd,
+static int omap_aes_handle_queue(struct omap_aes_dev *dd,
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 = 0;
+ int err, ret = 0;

spin_lock_irqsave(&dd->lock, flags);
if (req)
- err = ablkcipher_enqueue_request(&dd->queue, req);
+ ret = ablkcipher_enqueue_request(&dd->queue, req);
if (dd->flags & FLAGS_BUSY) {
spin_unlock_irqrestore(&dd->lock, flags);
- return err;
+ return ret;
}
backlog = crypto_get_backlog(&dd->queue);
async_req = crypto_dequeue_request(&dd->queue);
@@ -601,7 +629,7 @@ static int omap_aes_handle_req(struct omap_aes_dev *dd,
spin_unlock_irqrestore(&dd->lock, flags);

if (!async_req)
- return 0;
+ return ret;

if (backlog)
backlog->complete(backlog, -EINPROGRESS);
@@ -636,30 +664,46 @@ static int omap_aes_handle_req(struct omap_aes_dev *dd,
ctx->flags |= FLAGS_NEW_KEY;
}

- if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE))
- pr_err("request size is not exact amount of AES blocks\n");
-
- omap_aes_crypt_dma_start(dd);
+ 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 err;
+ return ret; /* return ret, which is enqueue return value */
}

-static void omap_aes_task(unsigned long data)
+static void omap_aes_done_task(unsigned long data)
{
struct omap_aes_dev *dd = (struct omap_aes_dev *)data;
+ int err;

pr_debug("enter\n");

- omap_aes_crypt_dma_stop(dd);
+ err = omap_aes_crypt_dma_stop(dd);

- if (dd->total)
- omap_aes_crypt_dma_start(dd);
- else
- omap_aes_handle_req(dd, NULL);
+ err = dd->err ? : err;
+
+ if (dd->total && !err) {
+ err = omap_aes_crypt_dma_start(dd);
+ if (!err)
+ return; /* DMA started. Not fininishing. */
+ }
+
+ omap_aes_finish_req(dd, err);
+ 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(
@@ -671,13 +715,18 @@ static int omap_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
!!(mode & FLAGS_ENCRYPT),
!!(mode & FLAGS_CBC));

+ if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE)) {
+ pr_err("request size is not exact amount of AES blocks\n");
+ return -EINVAL;
+ }
+
dd = omap_aes_find_dev(ctx);
if (!dd)
return -ENODEV;

rctx->mode = mode;

- return omap_aes_handle_req(dd, req);
+ return omap_aes_handle_queue(dd, req);
}

/* ********************** ALG API ************************************ */
@@ -843,7 +892,8 @@ static int omap_aes_probe(struct platform_device *pdev)
(reg & AES_REG_REV_MAJOR) >> 4, reg & AES_REG_REV_MINOR);
clk_disable(dd->iclk);

- tasklet_init(&dd->task, omap_aes_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);
if (err)
@@ -870,7 +920,8 @@ err_algs:
crypto_unregister_alg(&algs[j]);
omap_aes_dma_cleanup(dd);
err_dma:
- tasklet_kill(&dd->task);
+ tasklet_kill(&dd->done_task);
+ tasklet_kill(&dd->queue_task);
iounmap(dd->io_base);
err_io:
clk_put(dd->iclk);
@@ -897,7 +948,8 @@ static int omap_aes_remove(struct platform_device *pdev)
for (i = 0; i < ARRAY_SIZE(algs); i++)
crypto_unregister_alg(&algs[i]);

- tasklet_kill(&dd->task);
+ tasklet_kill(&dd->done_task);
+ tasklet_kill(&dd->queue_task);
omap_aes_dma_cleanup(dd);
iounmap(dd->io_base);
clk_put(dd->iclk);
--
1.7.0.4


2010-11-30 08:13:04

by Dmitry Kasatkin

[permalink] [raw]
Subject: [PATCHv2 6/6] omap-aes: checkpatch --file warning fixes

Signed-off-by: Dmitry Kasatkin <[email protected]>
---
drivers/crypto/omap-aes.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index b69da4f..add2a1a 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -96,7 +96,7 @@ struct omap_aes_reqctx {
struct omap_aes_dev {
struct list_head list;
unsigned long phys_base;
- void __iomem *io_base;
+ void __iomem *io_base;
struct clk *iclk;
struct omap_aes_ctx *ctx;
struct device *dev;
@@ -759,7 +759,7 @@ static struct crypto_alg algs[] = {
.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
.cra_blocksize = AES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_aes_ctx),
- .cra_alignmask = 0,
+ .cra_alignmask = 0,
.cra_type = &crypto_ablkcipher_type,
.cra_module = THIS_MODULE,
.cra_init = omap_aes_cra_init,
@@ -779,7 +779,7 @@ static struct crypto_alg algs[] = {
.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
.cra_blocksize = AES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_aes_ctx),
- .cra_alignmask = 0,
+ .cra_alignmask = 0,
.cra_type = &crypto_ablkcipher_type,
.cra_module = THIS_MODULE,
.cra_init = omap_aes_cra_init,
--
1.7.0.4

2010-11-30 08:12:58

by Dmitry Kasatkin

[permalink] [raw]
Subject: [PATCHv2 2/6] omap-aes: redundant locking is removed

Submitting request involved double locking for enqueuing and
dequeuing. Now it is done under the same lock.

FLAGS_BUSY is now handled under the same lock.

Signed-off-by: Dmitry Kasatkin <[email protected]>
---
drivers/crypto/omap-aes.c | 70 ++++++++++++++++++++------------------------
1 files changed, 32 insertions(+), 38 deletions(-)

diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index 41c91f3..2d8f72e 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -78,7 +78,7 @@
#define FLAGS_NEW_IV BIT(5)
#define FLAGS_INIT BIT(6)
#define FLAGS_FAST BIT(7)
-#define FLAGS_BUSY 8
+#define FLAGS_BUSY BIT(8)

struct omap_aes_ctx {
struct omap_aes_dev *dd;
@@ -179,9 +179,8 @@ static int omap_aes_wait(struct omap_aes_dev *dd, u32 offset, u32 bit)

static int omap_aes_hw_init(struct omap_aes_dev *dd)
{
- int err = 0;
-
clk_enable(dd->iclk);
+
if (!(dd->flags & FLAGS_INIT)) {
/* is it necessary to reset before every operation? */
omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_SOFTRESET,
@@ -193,18 +192,15 @@ static int omap_aes_hw_init(struct omap_aes_dev *dd)
__asm__ __volatile__("nop");
__asm__ __volatile__("nop");

- err = omap_aes_wait(dd, AES_REG_SYSSTATUS,
- AES_REG_SYSSTATUS_RESETDONE);
- if (!err)
- dd->flags |= FLAGS_INIT;
+ if (omap_aes_wait(dd, AES_REG_SYSSTATUS,
+ AES_REG_SYSSTATUS_RESETDONE)) {
+ clk_disable(dd->iclk);
+ return -ETIMEDOUT;
+ }
+ dd->flags |= FLAGS_INIT;
}

- return err;
-}
-
-static void omap_aes_hw_cleanup(struct omap_aes_dev *dd)
-{
- clk_disable(dd->iclk);
+ return 0;
}

static void omap_aes_write_ctrl(struct omap_aes_dev *dd)
@@ -538,6 +534,8 @@ static void omap_aes_finish_req(struct omap_aes_dev *dd, int err)

pr_debug("err: %d\n", err);

+ dd->flags &= ~FLAGS_BUSY;
+
ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(dd->req));

if (!dd->total)
@@ -553,7 +551,7 @@ static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)

omap_aes_write_mask(dd, AES_REG_MASK, 0, AES_REG_MASK_START);

- omap_aes_hw_cleanup(dd);
+ clk_disable(dd->iclk);

omap_stop_dma(dd->dma_lch_in);
omap_stop_dma(dd->dma_lch_out);
@@ -580,22 +578,26 @@ static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)
return err;
}

-static int omap_aes_handle_req(struct omap_aes_dev *dd)
+static int omap_aes_handle_req(struct omap_aes_dev *dd,
+ struct ablkcipher_request *req)
{
struct crypto_async_request *async_req, *backlog;
struct omap_aes_ctx *ctx;
struct omap_aes_reqctx *rctx;
- struct ablkcipher_request *req;
unsigned long flags;
-
- if (dd->total)
- goto start;
+ int err = 0;

spin_lock_irqsave(&dd->lock, flags);
+ if (req)
+ err = ablkcipher_enqueue_request(&dd->queue, req);
+ if (dd->flags & FLAGS_BUSY) {
+ spin_unlock_irqrestore(&dd->lock, flags);
+ return err;
+ }
backlog = crypto_get_backlog(&dd->queue);
async_req = crypto_dequeue_request(&dd->queue);
- if (!async_req)
- clear_bit(FLAGS_BUSY, &dd->flags);
+ if (async_req)
+ dd->flags |= FLAGS_BUSY;
spin_unlock_irqrestore(&dd->lock, flags);

if (!async_req)
@@ -637,20 +639,23 @@ static int omap_aes_handle_req(struct omap_aes_dev *dd)
if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE))
pr_err("request size is not exact amount of AES blocks\n");

-start:
- return omap_aes_crypt_dma_start(dd);
+ omap_aes_crypt_dma_start(dd);
+
+ return err;
}

static void omap_aes_task(unsigned long data)
{
struct omap_aes_dev *dd = (struct omap_aes_dev *)data;
- int err;

pr_debug("enter\n");

- err = omap_aes_crypt_dma_stop(dd);
+ omap_aes_crypt_dma_stop(dd);

- err = omap_aes_handle_req(dd);
+ if (dd->total)
+ omap_aes_crypt_dma_start(dd);
+ else
+ omap_aes_handle_req(dd, NULL);

pr_debug("exit\n");
}
@@ -661,8 +666,6 @@ static int omap_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
crypto_ablkcipher_reqtfm(req));
struct omap_aes_reqctx *rctx = ablkcipher_request_ctx(req);
struct omap_aes_dev *dd;
- unsigned long flags;
- int err;

pr_debug("nbytes: %d, enc: %d, cbc: %d\n", req->nbytes,
!!(mode & FLAGS_ENCRYPT),
@@ -674,16 +677,7 @@ static int omap_aes_crypt(struct ablkcipher_request *req, unsigned long mode)

rctx->mode = mode;

- spin_lock_irqsave(&dd->lock, flags);
- err = ablkcipher_enqueue_request(&dd->queue, req);
- spin_unlock_irqrestore(&dd->lock, flags);
-
- if (!test_and_set_bit(FLAGS_BUSY, &dd->flags))
- omap_aes_handle_req(dd);
-
- pr_debug("exit\n");
-
- return err;
+ return omap_aes_handle_req(dd, req);
}

/* ********************** ALG API ************************************ */
--
1.7.0.4

2010-11-30 08:13:30

by Dmitry Kasatkin

[permalink] [raw]
Subject: [PATCHv2 4/6] omap-aes: unnecessary code removed

Key and IV should always be set before AES operation.
So no need to check if it has changed or not.

Signed-off-by: Dmitry Kasatkin <[email protected]>
---
drivers/crypto/omap-aes.c | 70 +++++++++++----------------------------------
1 files changed, 17 insertions(+), 53 deletions(-)

diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index 704cc70..0b21dce 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -74,11 +74,9 @@
#define FLAGS_CBC BIT(1)
#define FLAGS_GIV BIT(2)

-#define FLAGS_NEW_KEY BIT(4)
-#define FLAGS_NEW_IV BIT(5)
-#define FLAGS_INIT BIT(6)
-#define FLAGS_FAST BIT(7)
-#define FLAGS_BUSY BIT(8)
+#define FLAGS_INIT BIT(4)
+#define FLAGS_FAST BIT(5)
+#define FLAGS_BUSY BIT(6)

struct omap_aes_ctx {
struct omap_aes_dev *dd;
@@ -105,9 +103,6 @@ struct omap_aes_dev {
unsigned long flags;
int err;

- u32 *iv;
- u32 ctrl;
-
spinlock_t lock;
struct crypto_queue queue;

@@ -209,28 +204,13 @@ static int omap_aes_hw_init(struct omap_aes_dev *dd)
static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
{
unsigned int key32;
- int i, err, init = dd->flags & FLAGS_INIT;
+ int i, err;
u32 val, mask;

err = omap_aes_hw_init(dd);
if (err)
return err;

- val = FLD_VAL(((dd->ctx->keylen >> 3) - 1), 4, 3);
- if (dd->flags & FLAGS_CBC)
- val |= AES_REG_CTRL_CBC;
- if (dd->flags & FLAGS_ENCRYPT)
- val |= AES_REG_CTRL_DIRECTION;
-
- /* check if hw state & mode have not changed */
- if (init && dd->ctrl == val && !(dd->flags & FLAGS_NEW_IV) &&
- !(dd->ctx->flags & FLAGS_NEW_KEY))
- goto out;
-
- /* only need to write control registers for new settings */
-
- dd->ctrl = val;
-
val = 0;
if (dd->dma_lch_out >= 0)
val |= AES_REG_MASK_DMA_OUT_EN;
@@ -241,27 +221,28 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)

omap_aes_write_mask(dd, AES_REG_MASK, val, mask);

- pr_debug("Set key\n");
key32 = dd->ctx->keylen / sizeof(u32);
- /* set a key */
+
+ /* it seems a key should always be set even if it has not changed */
for (i = 0; i < key32; i++) {
omap_aes_write(dd, AES_REG_KEY(i),
__le32_to_cpu(dd->ctx->key[i]));
}
- dd->ctx->flags &= ~FLAGS_NEW_KEY;

- if (dd->flags & FLAGS_NEW_IV) {
- pr_debug("Set IV\n");
- omap_aes_write_n(dd, AES_REG_IV(0), dd->iv, 4);
- dd->flags &= ~FLAGS_NEW_IV;
- }
+ if ((dd->flags & FLAGS_CBC) && dd->req->info)
+ omap_aes_write_n(dd, AES_REG_IV(0), dd->req->info, 4);
+
+ val = FLD_VAL(((dd->ctx->keylen >> 3) - 1), 4, 3);
+ if (dd->flags & FLAGS_CBC)
+ val |= AES_REG_CTRL_CBC;
+ if (dd->flags & FLAGS_ENCRYPT)
+ val |= AES_REG_CTRL_DIRECTION;

mask = AES_REG_CTRL_CBC | AES_REG_CTRL_DIRECTION |
AES_REG_CTRL_KEY_SIZE;

- omap_aes_write_mask(dd, AES_REG_CTRL, dd->ctrl, mask);
+ omap_aes_write_mask(dd, AES_REG_CTRL, val, mask);

-out:
/* start DMA or disable idle mode */
omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_START,
AES_REG_MASK_START);
@@ -561,16 +542,12 @@ static int omap_aes_crypt_dma_start(struct omap_aes_dev *dd)
static void omap_aes_finish_req(struct omap_aes_dev *dd, int err)
{
struct ablkcipher_request *req = dd->req;
- struct omap_aes_ctx *ctx;

pr_debug("err: %d\n", err);

dd->flags &= ~FLAGS_BUSY;

- ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(req));
-
- if (req->base.complete)
- req->base.complete(&req->base, err);
+ req->base.complete(&req->base, err);
}

static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)
@@ -636,8 +613,6 @@ static int omap_aes_handle_queue(struct omap_aes_dev *dd,

req = ablkcipher_request_cast(async_req);

- pr_debug("get new req\n");
-
/* assign new request to device */
dd->req = req;
dd->total = req->nbytes;
@@ -651,18 +626,8 @@ static int omap_aes_handle_queue(struct omap_aes_dev *dd,
rctx->mode &= FLAGS_MODE_MASK;
dd->flags = (dd->flags & ~FLAGS_MODE_MASK) | rctx->mode;

- dd->iv = req->info;
- if ((dd->flags & FLAGS_CBC) && dd->iv)
- dd->flags |= FLAGS_NEW_IV;
- else
- dd->flags &= ~FLAGS_NEW_IV;
-
+ dd->ctx = ctx;
ctx->dd = dd;
- if (dd->ctx != ctx) {
- /* assign new context to device */
- dd->ctx = ctx;
- ctx->flags |= FLAGS_NEW_KEY;
- }

err = omap_aes_crypt_dma_start(dd);
if (err) {
@@ -744,7 +709,6 @@ static int omap_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,

memcpy(ctx->key, key, keylen);
ctx->keylen = keylen;
- ctx->flags |= FLAGS_NEW_KEY;

return 0;
}
--
1.7.0.4


2010-11-30 08:13:02

by Dmitry Kasatkin

[permalink] [raw]
Subject: [PATCHv2 5/6] omap-aes: initialize aes module once per request

AES module was initialized for every DMA transaction.
That is redundant.
Now it is initialized once per request.

Signed-off-by: Dmitry Kasatkin <[email protected]>
---
drivers/crypto/omap-aes.c | 54 +++++++++++++++++++++++---------------------
1 files changed, 28 insertions(+), 26 deletions(-)

diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index 0b21dce..b69da4f 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -176,6 +176,11 @@ static int omap_aes_wait(struct omap_aes_dev *dd, u32 offset, u32 bit)

static int omap_aes_hw_init(struct omap_aes_dev *dd)
{
+ /*
+ * clocks are enabled when request starts and disabled when finished.
+ * It may be long delays between requests.
+ * Device might go to off mode to save power.
+ */
clk_enable(dd->iclk);

if (!(dd->flags & FLAGS_INIT)) {
@@ -190,10 +195,9 @@ static int omap_aes_hw_init(struct omap_aes_dev *dd)
__asm__ __volatile__("nop");

if (omap_aes_wait(dd, AES_REG_SYSSTATUS,
- AES_REG_SYSSTATUS_RESETDONE)) {
- clk_disable(dd->iclk);
+ AES_REG_SYSSTATUS_RESETDONE))
return -ETIMEDOUT;
- }
+
dd->flags |= FLAGS_INIT;
dd->err = 0;
}
@@ -243,9 +247,19 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)

omap_aes_write_mask(dd, AES_REG_CTRL, val, mask);

- /* start DMA or disable idle mode */
- omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_START,
- AES_REG_MASK_START);
+ /* IN */
+ omap_set_dma_dest_params(dd->dma_lch_in, 0, OMAP_DMA_AMODE_CONSTANT,
+ dd->phys_base + AES_REG_DATA, 0, 4);
+
+ omap_set_dma_dest_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4);
+ omap_set_dma_src_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4);
+
+ /* OUT */
+ omap_set_dma_src_params(dd->dma_lch_out, 0, OMAP_DMA_AMODE_CONSTANT,
+ dd->phys_base + AES_REG_DATA, 0, 4);
+
+ omap_set_dma_src_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4);
+ omap_set_dma_dest_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4);

return 0;
}
@@ -419,7 +433,6 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
struct omap_aes_ctx *ctx = crypto_tfm_ctx(tfm);
struct omap_aes_dev *dd = ctx->dd;
int len32;
- int err;

pr_debug("len: %d\n", length);

@@ -432,12 +445,6 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
len32 = DIV_ROUND_UP(length, sizeof(u32));

/* IN */
- omap_set_dma_dest_params(dd->dma_lch_in, 0, OMAP_DMA_AMODE_CONSTANT,
- dd->phys_base + AES_REG_DATA, 0, 4);
-
- omap_set_dma_dest_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4);
- omap_set_dma_src_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4);
-
omap_set_dma_transfer_params(dd->dma_lch_in, OMAP_DMA_DATA_TYPE_S32,
len32, 1, OMAP_DMA_SYNC_PACKET, dd->dma_in,
OMAP_DMA_DST_SYNC);
@@ -446,12 +453,6 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
dma_addr_in, 0, 0);

/* OUT */
- omap_set_dma_src_params(dd->dma_lch_out, 0, OMAP_DMA_AMODE_CONSTANT,
- dd->phys_base + AES_REG_DATA, 0, 4);
-
- omap_set_dma_src_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4);
- omap_set_dma_dest_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4);
-
omap_set_dma_transfer_params(dd->dma_lch_out, OMAP_DMA_DATA_TYPE_S32,
len32, 1, OMAP_DMA_SYNC_PACKET,
dd->dma_out, OMAP_DMA_SRC_SYNC);
@@ -459,13 +460,13 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
omap_set_dma_dest_params(dd->dma_lch_out, 0, OMAP_DMA_AMODE_POST_INC,
dma_addr_out, 0, 0);

- err = omap_aes_write_ctrl(dd);
- if (err)
- return err;
-
omap_start_dma(dd->dma_lch_in);
omap_start_dma(dd->dma_lch_out);

+ /* start DMA or disable idle mode */
+ omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_START,
+ AES_REG_MASK_START);
+
return 0;
}

@@ -545,6 +546,7 @@ static void omap_aes_finish_req(struct omap_aes_dev *dd, int err)

pr_debug("err: %d\n", err);

+ clk_disable(dd->iclk);
dd->flags &= ~FLAGS_BUSY;

req->base.complete(&req->base, err);
@@ -562,8 +564,6 @@ static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)
omap_stop_dma(dd->dma_lch_in);
omap_stop_dma(dd->dma_lch_out);

- clk_disable(dd->iclk);
-
if (dd->flags & FLAGS_FAST) {
dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE);
dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
@@ -629,7 +629,9 @@ static int omap_aes_handle_queue(struct omap_aes_dev *dd,
dd->ctx = ctx;
ctx->dd = dd;

- err = omap_aes_crypt_dma_start(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);
--
1.7.0.4

2010-12-02 08:37:57

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCHv2 0/6] omap-aes off mode and error handling fixes

On Tue, Nov 30, 2010 at 10:13:26AM +0200, Dmitry Kasatkin wrote:
> Changes to v1:
> - omap type specific handling removed
> - fixed backlog handling bug in "redundunt locking is removed"
> - aes module initialized once per request instead of dma transaction
> more efficient and right way to do it
> - checkpatch fixes in separate patch

All applied. Thanks Dmitry!
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

2010-12-07 09:41:44

by Dmitry Kasatkin

[permalink] [raw]
Subject: Re: [PATCHv2 0/6] omap-aes off mode and error handling fixes

thanks

On 02/12/10 10:37, ext Herbert Xu wrote:
> On Tue, Nov 30, 2010 at 10:13:26AM +0200, Dmitry Kasatkin wrote:
>
>> Changes to v1:
>> - omap type specific handling removed
>> - fixed backlog handling bug in "redundunt locking is removed"
>> - aes module initialized once per request instead of dma transaction
>> more efficient and right way to do it
>> - checkpatch fixes in separate patch
>>
> All applied. Thanks Dmitry!
>