linux-crypto.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5] omap-aes off mode and error handling fixes
@ 2010-11-10 17:26 Dmitry Kasatkin
  2010-11-10 17:26 ` [PATCH 1/5] crypto: omap-aes: change in prevention of OCP bus error Dmitry Kasatkin
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Dmitry Kasatkin @ 2010-11-10 17:26 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, linux-omap

Dmitry Kasatkin (5):
  crypto: omap-aes: change in prevention of OCP bus error
  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

 drivers/crypto/omap-aes.c |  269 ++++++++++++++++++++++++---------------------
 1 files changed, 143 insertions(+), 126 deletions(-)


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/5] crypto: omap-aes: change in prevention of OCP bus error
  2010-11-10 17:26 [PATCH 0/5] omap-aes off mode and error handling fixes Dmitry Kasatkin
@ 2010-11-10 17:26 ` Dmitry Kasatkin
  2010-11-16 17:13   ` Tony Lindgren
  2010-11-10 17:26 ` [PATCH 2/5] omap-aes: DMA initialization fixes for OMAP off mode Dmitry Kasatkin
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Dmitry Kasatkin @ 2010-11-10 17:26 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, linux-omap

Suggested to use udelay() instead of nop as on the higher
core frequencies it might not be enough time.

Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@nokia.com>
---
 drivers/crypto/omap-aes.c |   10 ++++++----
 1 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index 799ca51..9d65611 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -26,6 +26,7 @@
 #include <linux/io.h>
 #include <linux/crypto.h>
 #include <linux/interrupt.h>
+#include <linux/delay.h>
 #include <crypto/scatterwalk.h>
 #include <crypto/aes.h>
 
@@ -187,11 +188,12 @@ static int omap_aes_hw_init(struct omap_aes_dev *dd)
 		omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_SOFTRESET,
 					AES_REG_MASK_SOFTRESET);
 		/*
-		 * prevent OCP bus error (SRESP) in case an access to the module
-		 * is performed while the module is coming out of soft reset
+		 * prevent OCP bus error (SRESP) on OMAP3630 in case an access
+		 * to the module is performed while the module is
+		 * coming out of soft reset
 		 */
-		__asm__ __volatile__("nop");
-		__asm__ __volatile__("nop");
+		if (cpu_is_omap3630())
+			udelay(1);
 
 		err = omap_aes_wait(dd, AES_REG_SYSSTATUS,
 				AES_REG_SYSSTATUS_RESETDONE);
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/5] omap-aes: DMA initialization fixes for OMAP off mode
  2010-11-10 17:26 [PATCH 0/5] omap-aes off mode and error handling fixes Dmitry Kasatkin
  2010-11-10 17:26 ` [PATCH 1/5] crypto: omap-aes: change in prevention of OCP bus error Dmitry Kasatkin
@ 2010-11-10 17:26 ` Dmitry Kasatkin
  2010-11-10 17:48   ` Felipe Balbi
  2010-11-10 17:26 ` [PATCH 3/5] omap-aes: redundant locking is removed Dmitry Kasatkin
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Dmitry Kasatkin @ 2010-11-10 17:26 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, linux-omap

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 <dmitry.kasatkin@nokia.com>
---
 drivers/crypto/omap-aes.c |   30 +++++++++++++++---------------
 1 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index 9d65611..04cab70 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -99,7 +99,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;
@@ -341,18 +341,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:
@@ -445,6 +433,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);
@@ -453,6 +447,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);
@@ -752,7 +752,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,
@@ -772,7 +772,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

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 3/5] omap-aes: redundant locking is removed
  2010-11-10 17:26 [PATCH 0/5] omap-aes off mode and error handling fixes Dmitry Kasatkin
  2010-11-10 17:26 ` [PATCH 1/5] crypto: omap-aes: change in prevention of OCP bus error Dmitry Kasatkin
  2010-11-10 17:26 ` [PATCH 2/5] omap-aes: DMA initialization fixes for OMAP off mode Dmitry Kasatkin
@ 2010-11-10 17:26 ` Dmitry Kasatkin
  2010-11-10 17:26 ` [PATCH 4/5] omap-aes: error handling implementation improved Dmitry Kasatkin
  2010-11-10 17:26 ` [PATCH 5/5] omap-aes: unnecessary code removed Dmitry Kasatkin
  4 siblings, 0 replies; 8+ messages in thread
From: Dmitry Kasatkin @ 2010-11-10 17:26 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, linux-omap

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 <dmitry.kasatkin@nokia.com>
---
 drivers/crypto/omap-aes.c |   68 ++++++++++++++++++++------------------------
 1 files changed, 31 insertions(+), 37 deletions(-)

diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index 04cab70..a4d0ef4 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -79,7 +79,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;
@@ -180,9 +180,10 @@ 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;
+	int err;
 
 	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,
@@ -195,18 +196,14 @@ static int omap_aes_hw_init(struct omap_aes_dev *dd)
 		if (cpu_is_omap3630())
 			udelay(1);
 
-		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)
@@ -540,6 +537,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)
@@ -555,7 +554,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);
@@ -582,22 +581,27 @@ 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;
 
 	spin_lock_irqsave(&dd->lock, flags);
-	backlog = crypto_get_backlog(&dd->queue);
+	if (req)
+		err = ablkcipher_enqueue_request(&dd->queue, req);
+	if (dd->flags & FLAGS_BUSY) {
+		spin_unlock_irqrestore(&dd->lock, flags);
+		return err;
+	}
 	async_req = crypto_dequeue_request(&dd->queue);
-	if (!async_req)
-		clear_bit(FLAGS_BUSY, &dd->flags);
+	if (async_req) {
+		dd->flags |= FLAGS_BUSY;
+		backlog = crypto_get_backlog(&dd->queue);
+	}
 	spin_unlock_irqrestore(&dd->lock, flags);
 
 	if (!async_req)
@@ -639,20 +643,21 @@ 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);
 }
 
 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");
 }
@@ -663,8 +668,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),
@@ -676,16 +679,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


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 4/5] omap-aes: error handling implementation improved
  2010-11-10 17:26 [PATCH 0/5] omap-aes off mode and error handling fixes Dmitry Kasatkin
                   ` (2 preceding siblings ...)
  2010-11-10 17:26 ` [PATCH 3/5] omap-aes: redundant locking is removed Dmitry Kasatkin
@ 2010-11-10 17:26 ` Dmitry Kasatkin
  2010-11-10 17:26 ` [PATCH 5/5] omap-aes: unnecessary code removed Dmitry Kasatkin
  4 siblings, 0 replies; 8+ messages in thread
From: Dmitry Kasatkin @ 2010-11-10 17:26 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, linux-omap

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 <dmitry.kasatkin@nokia.com>
---
 drivers/crypto/omap-aes.c |  135 +++++++++++++++++++++++++++++++--------------
 1 files changed, 94 insertions(+), 41 deletions(-)

diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index a4d0ef4..704c9d1 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -104,14 +104,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;
@@ -180,8 +182,6 @@ 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;
-
 	clk_enable(dd->iclk);
 
 	if (!(dd->flags & FLAGS_INIT)) {
@@ -200,25 +200,32 @@ static int omap_aes_hw_init(struct omap_aes_dev *dd)
 				AES_REG_SYSSTATUS_RESETDONE)) {
 			clk_disable(dd->iclk);
 			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;
 
@@ -260,6 +267,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)
@@ -287,8 +296,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)
@@ -393,6 +410,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;
@@ -418,6 +440,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);
 
@@ -457,11 +480,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;
 }
 
@@ -487,8 +512,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");
 
@@ -524,25 +551,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)
@@ -554,11 +584,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);
@@ -575,27 +605,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;
+	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;
 	}
 	async_req = crypto_dequeue_request(&dd->queue);
 	if (async_req) {
@@ -605,7 +632,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);
@@ -640,28 +667,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");
+	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_crypt_dma_start(dd);
+	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(
@@ -673,13 +718,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 ************************************ */
@@ -845,7 +895,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)
@@ -872,7 +923,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);
@@ -899,7 +951,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

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 5/5] omap-aes: unnecessary code removed
  2010-11-10 17:26 [PATCH 0/5] omap-aes off mode and error handling fixes Dmitry Kasatkin
                   ` (3 preceding siblings ...)
  2010-11-10 17:26 ` [PATCH 4/5] omap-aes: error handling implementation improved Dmitry Kasatkin
@ 2010-11-10 17:26 ` Dmitry Kasatkin
  4 siblings, 0 replies; 8+ messages in thread
From: Dmitry Kasatkin @ 2010-11-10 17:26 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, linux-omap

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 <dmitry.kasatkin@nokia.com>
---
 drivers/crypto/omap-aes.c |   64 +++++++++++---------------------------------
 1 files changed, 16 insertions(+), 48 deletions(-)

diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index 704c9d1..072f221 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -75,11 +75,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;
@@ -106,9 +104,6 @@ struct omap_aes_dev {
 	unsigned long		flags;
 	int			err;
 
-	u32			*iv;
-	u32			ctrl;
-
 	spinlock_t		lock;
 	struct crypto_queue	queue;
 
@@ -211,28 +206,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;
@@ -243,27 +223,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);
@@ -639,8 +620,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;
@@ -654,18 +633,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) {
@@ -747,7 +716,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


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/5] omap-aes: DMA initialization fixes for OMAP off mode
  2010-11-10 17:26 ` [PATCH 2/5] omap-aes: DMA initialization fixes for OMAP off mode Dmitry Kasatkin
@ 2010-11-10 17:48   ` Felipe Balbi
  0 siblings, 0 replies; 8+ messages in thread
From: Felipe Balbi @ 2010-11-10 17:48 UTC (permalink / raw)
  To: Dmitry Kasatkin; +Cc: herbert, linux-crypto, linux-omap

Hi,

On Wed, 2010-11-10 at 19:26 +0200, Dmitry Kasatkin wrote:
> diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
> index 9d65611..04cab70 100644
> --- a/drivers/crypto/omap-aes.c
> +++ b/drivers/crypto/omap-aes.c
> @@ -99,7 +99,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;

this hunk is not part of this patch.

> @@ -752,7 +752,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,

not part of this patch.

> @@ -772,7 +772,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,

not part of this patch

-- 
balbi


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/5] crypto: omap-aes: change in prevention of OCP bus error
  2010-11-10 17:26 ` [PATCH 1/5] crypto: omap-aes: change in prevention of OCP bus error Dmitry Kasatkin
@ 2010-11-16 17:13   ` Tony Lindgren
  0 siblings, 0 replies; 8+ messages in thread
From: Tony Lindgren @ 2010-11-16 17:13 UTC (permalink / raw)
  To: Dmitry Kasatkin; +Cc: herbert, linux-crypto, linux-omap

Hi,

* Dmitry Kasatkin <dmitry.kasatkin@nokia.com> [101110 09:18]:
> Suggested to use udelay() instead of nop as on the higher
> core frequencies it might not be enough time.
> 
> Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@nokia.com>
> ---
>  drivers/crypto/omap-aes.c |   10 ++++++----
>  1 files changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
> index 799ca51..9d65611 100644
> --- a/drivers/crypto/omap-aes.c
> +++ b/drivers/crypto/omap-aes.c
> @@ -26,6 +26,7 @@
>  #include <linux/io.h>
>  #include <linux/crypto.h>
>  #include <linux/interrupt.h>
> +#include <linux/delay.h>
>  #include <crypto/scatterwalk.h>
>  #include <crypto/aes.h>
>  
> @@ -187,11 +188,12 @@ static int omap_aes_hw_init(struct omap_aes_dev *dd)
>  		omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_SOFTRESET,
>  					AES_REG_MASK_SOFTRESET);
>  		/*
> -		 * prevent OCP bus error (SRESP) in case an access to the module
> -		 * is performed while the module is coming out of soft reset
> +		 * prevent OCP bus error (SRESP) on OMAP3630 in case an access
> +		 * to the module is performed while the module is
> +		 * coming out of soft reset
>  		 */
> -		__asm__ __volatile__("nop");
> -		__asm__ __volatile__("nop");
> +		if (cpu_is_omap3630())
> +			udelay(1);
>  
>  		err = omap_aes_wait(dd, AES_REG_SYSSTATUS,
>  				AES_REG_SYSSTATUS_RESETDONE);

Please don't add more cpu_is_omapxxxx tests into drivers, those
will be limited to arch/arm/*omap*/ platform init code soonish.
The drivers should be generic.

Instead, check the crypto hardware version during init. If that
does not work, pass u32 flags in the platform data and define
OMAP_AES_SOFT_RESET_ERROR bit.

Regards,

Tony

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2010-11-16 17:14 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-11-10 17:26 [PATCH 0/5] omap-aes off mode and error handling fixes Dmitry Kasatkin
2010-11-10 17:26 ` [PATCH 1/5] crypto: omap-aes: change in prevention of OCP bus error Dmitry Kasatkin
2010-11-16 17:13   ` Tony Lindgren
2010-11-10 17:26 ` [PATCH 2/5] omap-aes: DMA initialization fixes for OMAP off mode Dmitry Kasatkin
2010-11-10 17:48   ` Felipe Balbi
2010-11-10 17:26 ` [PATCH 3/5] omap-aes: redundant locking is removed Dmitry Kasatkin
2010-11-10 17:26 ` [PATCH 4/5] omap-aes: error handling implementation improved Dmitry Kasatkin
2010-11-10 17:26 ` [PATCH 5/5] omap-aes: unnecessary code removed Dmitry Kasatkin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).