All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4]v2 omap-sham off mode and error handling fixes.
@ 2010-11-10 17:36 Dmitry Kasatkin
  2010-11-10 17:36 ` [PATCH 1/4] omap-sham: uses digest buffer in request context Dmitry Kasatkin
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Dmitry Kasatkin @ 2010-11-10 17:36 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, linux-omap

Please ignore previous patch set.
Some old patches appeared there...

Dmitry Kasatkin (4):
  omap-sham: uses digest buffer in request context
  omap-sham: DMA initialization fixes for off mode
  omap-sham: error handling improved
  omap-sham: removed redundunt locking

 drivers/crypto/omap-sham.c |  144 +++++++++++++++++++++++++-------------------
 1 files changed, 83 insertions(+), 61 deletions(-)

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

* [PATCH 1/4] omap-sham: uses digest buffer in request context
  2010-11-10 17:36 [PATCH 0/4]v2 omap-sham off mode and error handling fixes Dmitry Kasatkin
@ 2010-11-10 17:36 ` Dmitry Kasatkin
  2010-11-10 17:36 ` [PATCH 2/4] omap-sham: DMA initialization fixes for off mode Dmitry Kasatkin
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Dmitry Kasatkin @ 2010-11-10 17:36 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, linux-omap

Currently driver storred digest results in req->results
provided by the client. But some clients do not set it
until final() call. It leads to crash.
Changed to use internal buffer to store temporary digest results.

Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@nokia.com>
---
 drivers/crypto/omap-sham.c |   11 ++++++++---
 1 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index a081c7c..2222370 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -97,6 +97,7 @@ struct omap_sham_reqctx {
 	unsigned long		flags;
 	unsigned long		op;
 
+	u8			digest[SHA1_DIGEST_SIZE];
 	size_t			digcnt;
 	u8			*buffer;
 	size_t			bufcnt;
@@ -194,7 +195,7 @@ static inline int omap_sham_wait(struct omap_sham_dev *dd, u32 offset, u32 bit)
 static void omap_sham_copy_hash(struct ahash_request *req, int out)
 {
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
-	u32 *hash = (u32 *)req->result;
+	u32 *hash = (u32 *)ctx->digest;
 	int i;
 
 	if (likely(ctx->flags & FLAGS_SHA1)) {
@@ -453,8 +454,11 @@ static void omap_sham_cleanup(struct ahash_request *req)
 	ctx->flags |= FLAGS_CLEAN;
 	spin_unlock_irqrestore(&dd->lock, flags);
 
-	if (ctx->digcnt)
+	if (ctx->digcnt) {
 		clk_disable(dd->iclk);
+		memcpy(req->result, ctx->digest, (ctx->flags & FLAGS_SHA1) ?
+				SHA1_DIGEST_SIZE : MD5_DIGEST_SIZE);
+	}
 
 	if (ctx->dma_addr)
 		dma_unmap_single(dd->dev, ctx->dma_addr, ctx->buflen,
@@ -576,6 +580,7 @@ static int omap_sham_final_req(struct omap_sham_dev *dd)
 
 static int omap_sham_finish_req_hmac(struct ahash_request *req)
 {
+	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
 	struct omap_sham_ctx *tctx = crypto_tfm_ctx(req->base.tfm);
 	struct omap_sham_hmac_ctx *bctx = tctx->base;
 	int bs = crypto_shash_blocksize(bctx->shash);
@@ -590,7 +595,7 @@ static int omap_sham_finish_req_hmac(struct ahash_request *req)
 
 	return crypto_shash_init(&desc.shash) ?:
 	       crypto_shash_update(&desc.shash, bctx->opad, bs) ?:
-	       crypto_shash_finup(&desc.shash, req->result, ds, req->result);
+	       crypto_shash_finup(&desc.shash, ctx->digest, ds, ctx->digest);
 }
 
 static void omap_sham_finish_req(struct ahash_request *req, int err)
-- 
1.7.0.4

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

* [PATCH 2/4] omap-sham: DMA initialization fixes for off mode
  2010-11-10 17:36 [PATCH 0/4]v2 omap-sham off mode and error handling fixes Dmitry Kasatkin
  2010-11-10 17:36 ` [PATCH 1/4] omap-sham: uses digest buffer in request context Dmitry Kasatkin
@ 2010-11-10 17:36 ` Dmitry Kasatkin
  2010-11-10 17:36 ` [PATCH 3/4] omap-sham: error handling improved Dmitry Kasatkin
  2010-11-10 17:36 ` [PATCH 4/4] omap-sham: removed redundunt locking Dmitry Kasatkin
  3 siblings, 0 replies; 5+ messages in thread
From: Dmitry Kasatkin @ 2010-11-10 17:36 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.

Fixes: NB#202786 - Aegis & SHA1 block off mode changes

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

diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index 2222370..9dfbc4a 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -318,6 +318,16 @@ static int omap_sham_xmit_dma(struct omap_sham_dev *dd, dma_addr_t dma_addr,
 	omap_set_dma_src_params(dd->dma_lch, 0, OMAP_DMA_AMODE_POST_INC,
 				dma_addr, 0, 0);
 
+	omap_set_dma_dest_params(dd->dma_lch, 0,
+			OMAP_DMA_AMODE_CONSTANT,
+			dd->phys_base + SHA_REG_DIN(0), 0, 16);
+
+	omap_set_dma_dest_burst_mode(dd->dma_lch,
+			OMAP_DMA_DATA_BURST_16);
+
+	omap_set_dma_src_burst_mode(dd->dma_lch,
+			OMAP_DMA_DATA_BURST_4);
+
 	err = omap_sham_write_ctrl(dd, length, final, 1);
 	if (err)
 		return err;
@@ -1071,15 +1081,6 @@ static int omap_sham_dma_init(struct omap_sham_dev *dd)
 		dev_err(dd->dev, "Unable to request DMA channel\n");
 		return err;
 	}
-	omap_set_dma_dest_params(dd->dma_lch, 0,
-			OMAP_DMA_AMODE_CONSTANT,
-			dd->phys_base + SHA_REG_DIN(0), 0, 16);
-
-	omap_set_dma_dest_burst_mode(dd->dma_lch,
-			OMAP_DMA_DATA_BURST_16);
-
-	omap_set_dma_src_burst_mode(dd->dma_lch,
-			OMAP_DMA_DATA_BURST_4);
 
 	return 0;
 }
-- 
1.7.0.4

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

* [PATCH 3/4] omap-sham: error handling improved
  2010-11-10 17:36 [PATCH 0/4]v2 omap-sham off mode and error handling fixes Dmitry Kasatkin
  2010-11-10 17:36 ` [PATCH 1/4] omap-sham: uses digest buffer in request context Dmitry Kasatkin
  2010-11-10 17:36 ` [PATCH 2/4] omap-sham: DMA initialization fixes for off mode Dmitry Kasatkin
@ 2010-11-10 17:36 ` Dmitry Kasatkin
  2010-11-10 17:36 ` [PATCH 4/4] omap-sham: removed redundunt locking Dmitry Kasatkin
  3 siblings, 0 replies; 5+ messages in thread
From: Dmitry Kasatkin @ 2010-11-10 17:36 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, linux-omap

Introduces DMA error handling.

DMA error is returned as a result code of the hash request.
Clients needs to handle error codes and may repeat hash calculation attempt.

Also in the case of DMA error, SHAM module is set to be re-initialized again.
It significantly improves stability against possible HW failures.

Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@nokia.com>

Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@nokia.com>
---
 drivers/crypto/omap-sham.c |   67 +++++++++++++++++++++++++++++---------------
 1 files changed, 44 insertions(+), 23 deletions(-)

diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index 9dfbc4a..db20628 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -83,6 +83,7 @@
 #define FLAGS_INIT		0x0100
 #define FLAGS_CPU		0x0200
 #define FLAGS_HMAC		0x0400
+#define FLAGS_ERROR		0x0800
 
 /* 3rd byte */
 #define FLAGS_BUSY		16
@@ -137,6 +138,7 @@ struct omap_sham_dev {
 	int			irq;
 	struct clk		*iclk;
 	spinlock_t		lock;
+	int			err;
 	int			dma;
 	int			dma_lch;
 	struct tasklet_struct	done_task;
@@ -234,10 +236,12 @@ static int omap_sham_write_ctrl(struct omap_sham_dev *dd, size_t length,
 				SHA_REG_MASK_SOFTRESET, SHA_REG_MASK_SOFTRESET);
 
 			if (omap_sham_wait(dd, SHA_REG_SYSSTATUS,
-						SHA_REG_SYSSTATUS_RESETDONE))
+						SHA_REG_SYSSTATUS_RESETDONE)) {
+				clk_disable(dd->iclk);
 				return -ETIMEDOUT;
-
+			}
 			dd->flags |= FLAGS_INIT;
+			dd->err = 0;
 		}
 	} else {
 		omap_sham_write(dd, SHA_REG_DIGCNT, ctx->digcnt);
@@ -279,11 +283,12 @@ static int omap_sham_xmit_cpu(struct omap_sham_dev *dd, const u8 *buf,
 	if (err)
 		return err;
 
+	/* should be non-zero before next lines to disable clocks later */
+	ctx->digcnt += length;
+
 	if (omap_sham_wait(dd, SHA_REG_CTRL, SHA_REG_CTRL_INPUT_READY))
 		return -ETIMEDOUT;
 
-	ctx->digcnt += length;
-
 	if (final)
 		ctx->flags |= FLAGS_FINAL; /* catch last interrupt */
 
@@ -303,7 +308,6 @@ static int omap_sham_xmit_dma(struct omap_sham_dev *dd, dma_addr_t dma_addr,
 
 	dev_dbg(dd->dev, "xmit_dma: digcnt: %d, length: %d, final: %d\n",
 						ctx->digcnt, length, final);
-
 	/* flush cache entries related to our page */
 	if (dma_addr == ctx->dma_addr)
 		dma_sync_single_for_device(dd->dev, dma_addr, length,
@@ -411,6 +415,7 @@ static int omap_sham_update_dma_fast(struct omap_sham_dev *dd)
 {
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
 	unsigned int length;
+	int err;
 
 	ctx->flags |= FLAGS_FAST;
 
@@ -424,7 +429,11 @@ static int omap_sham_update_dma_fast(struct omap_sham_dev *dd)
 
 	ctx->total -= length;
 
-	return omap_sham_xmit_dma(dd, sg_dma_address(ctx->sg), length, 1);
+	err = omap_sham_xmit_dma(dd, sg_dma_address(ctx->sg), length, 1);
+	if (err != -EINPROGRESS)
+		dma_unmap_sg(dd->dev, ctx->sg, 1, DMA_TO_DEVICE);
+
+	return err;
 }
 
 static int omap_sham_update_cpu(struct omap_sham_dev *dd)
@@ -580,9 +589,6 @@ static int omap_sham_final_req(struct omap_sham_dev *dd)
 
 	ctx->bufcnt = 0;
 
-	if (err != -EINPROGRESS)
-		omap_sham_cleanup(req);
-
 	dev_dbg(dd->dev, "final_req: err: %d\n", err);
 
 	return err;
@@ -616,9 +622,11 @@ static void omap_sham_finish_req(struct ahash_request *req, int err)
 		omap_sham_copy_hash(ctx->dd->req, 1);
 		if (ctx->flags & FLAGS_HMAC)
 			err = omap_sham_finish_req_hmac(req);
+	} else {
+		ctx->flags |= FLAGS_ERROR;
 	}
 
-	if (ctx->flags & FLAGS_FINAL)
+	if ((ctx->flags & FLAGS_FINAL) || err)
 		omap_sham_cleanup(req);
 
 	clear_bit(FLAGS_BUSY, &ctx->dd->flags);
@@ -776,12 +784,14 @@ static int omap_sham_final(struct ahash_request *req)
 
 	ctx->flags |= FLAGS_FINUP;
 
-	/* OMAP HW accel works only with buffers >= 9 */
-	/* HMAC is always >= 9 because of ipad */
-	if ((ctx->digcnt + ctx->bufcnt) < 9)
-		err = omap_sham_final_shash(req);
-	else if (ctx->bufcnt)
-		return omap_sham_enqueue(req, OP_FINAL);
+	if (!(ctx->flags & FLAGS_ERROR)) {
+		/* OMAP HW accel works only with buffers >= 9 */
+		/* HMAC is always >= 9 because of ipad */
+		if ((ctx->digcnt + ctx->bufcnt) < 9)
+			err = omap_sham_final_shash(req);
+		else if (ctx->bufcnt)
+			return omap_sham_enqueue(req, OP_FINAL);
+	}
 
 	omap_sham_cleanup(req);
 
@@ -851,6 +861,8 @@ static int omap_sham_cra_init_alg(struct crypto_tfm *tfm, const char *alg_base)
 	struct omap_sham_ctx *tctx = crypto_tfm_ctx(tfm);
 	const char *alg_name = crypto_tfm_alg_name(tfm);
 
+	pr_info("enter\n");
+
 	/* Allocate a fallback and abort if it failed. */
 	tctx->fallback = crypto_alloc_shash(alg_name, 0,
 					    CRYPTO_ALG_NEED_FALLBACK);
@@ -1008,7 +1020,7 @@ static void omap_sham_done_task(unsigned long data)
 	struct omap_sham_dev *dd = (struct omap_sham_dev *)data;
 	struct ahash_request *req = dd->req;
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
-	int ready = 1;
+	int ready = 0, err = 0;
 
 	if (ctx->flags & FLAGS_OUTPUT_READY) {
 		ctx->flags &= ~FLAGS_OUTPUT_READY;
@@ -1018,13 +1030,16 @@ static void omap_sham_done_task(unsigned long data)
 	if (dd->flags & FLAGS_DMA_ACTIVE) {
 		dd->flags &= ~FLAGS_DMA_ACTIVE;
 		omap_sham_update_dma_stop(dd);
-		omap_sham_update_dma_slow(dd);
+		if (!dd->err)
+			err = omap_sham_update_dma_slow(dd);
 	}
 
-	if (ready && !(dd->flags & FLAGS_DMA_ACTIVE)) {
-		dev_dbg(dd->dev, "update done\n");
+	err = dd->err ? : err;
+
+	if (err != -EINPROGRESS && (ready || err)) {
+		dev_dbg(dd->dev, "update done: err: %d\n", err);
 		/* finish curent request */
-		omap_sham_finish_req(req, 0);
+		omap_sham_finish_req(req, err);
 		/* start new request */
 		omap_sham_handle_queue(dd);
 	}
@@ -1056,6 +1071,7 @@ static irqreturn_t omap_sham_irq(int irq, void *dev_id)
 	omap_sham_read(dd, SHA_REG_CTRL);
 
 	ctx->flags |= FLAGS_OUTPUT_READY;
+	dd->err = 0;
 	tasklet_schedule(&dd->done_task);
 
 	return IRQ_HANDLED;
@@ -1065,8 +1081,13 @@ static void omap_sham_dma_callback(int lch, u16 ch_status, void *data)
 {
 	struct omap_sham_dev *dd = data;
 
-	if (likely(lch == dd->dma_lch))
-		tasklet_schedule(&dd->done_task);
+	if (ch_status != OMAP_DMA_BLOCK_IRQ) {
+		pr_err("omap-sham DMA error status: 0x%hx\n", ch_status);
+		dd->err = -EIO;
+		dd->flags &= ~FLAGS_INIT; /* request to re-initialize */
+	}
+
+	tasklet_schedule(&dd->done_task);
 }
 
 static int omap_sham_dma_init(struct omap_sham_dev *dd)
-- 
1.7.0.4


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

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

Locking for queuing and dequeuing is combined.
test_and_set_bit() is also replaced with checking under dd->lock.

Signed-off-by: Dmitry Kasatkin <dmitry.kasatkin@nokia.com>
---
 drivers/crypto/omap-sham.c |   47 +++++++++++++++++++------------------------
 1 files changed, 21 insertions(+), 26 deletions(-)

diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index db20628..6340c5e 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -84,9 +84,7 @@
 #define FLAGS_CPU		0x0200
 #define FLAGS_HMAC		0x0400
 #define FLAGS_ERROR		0x0800
-
-/* 3rd byte */
-#define FLAGS_BUSY		16
+#define FLAGS_BUSY		0x1000
 
 #define OP_UPDATE	1
 #define OP_FINAL	2
@@ -629,32 +627,37 @@ static void omap_sham_finish_req(struct ahash_request *req, int err)
 	if ((ctx->flags & FLAGS_FINAL) || err)
 		omap_sham_cleanup(req);
 
-	clear_bit(FLAGS_BUSY, &ctx->dd->flags);
+	ctx->dd->flags &= ~FLAGS_BUSY;
 
 	if (req->base.complete)
 		req->base.complete(&req->base, err);
 }
 
-static int omap_sham_handle_queue(struct omap_sham_dev *dd)
+static int omap_sham_handle_queue(struct omap_sham_dev *dd,
+				  struct ahash_request *req)
 {
 	struct crypto_async_request *async_req, *backlog;
 	struct omap_sham_reqctx *ctx;
-	struct ahash_request *req, *prev_req;
+	struct ahash_request *prev_req;
 	unsigned long flags;
-	int err = 0;
-
-	if (test_and_set_bit(FLAGS_BUSY, &dd->flags))
-		return 0;
+	int err = 0, ret = 0;
 
 	spin_lock_irqsave(&dd->lock, flags);
-	backlog = crypto_get_backlog(&dd->queue);
+	if (req)
+		ret = ahash_enqueue_request(&dd->queue, req);
+	if (dd->flags & FLAGS_BUSY) {
+		spin_unlock_irqrestore(&dd->lock, flags);
+		return ret;
+	}
 	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)
-		return 0;
+		return ret;
 
 	if (backlog)
 		backlog->complete(backlog, -EINPROGRESS);
@@ -690,7 +693,7 @@ static int omap_sham_handle_queue(struct omap_sham_dev *dd)
 
 	dev_dbg(dd->dev, "exit, err: %d\n", err);
 
-	return err;
+	return ret;
 }
 
 static int omap_sham_enqueue(struct ahash_request *req, unsigned int op)
@@ -698,18 +701,10 @@ static int omap_sham_enqueue(struct ahash_request *req, unsigned int op)
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
 	struct omap_sham_ctx *tctx = crypto_tfm_ctx(req->base.tfm);
 	struct omap_sham_dev *dd = tctx->dd;
-	unsigned long flags;
-	int err;
 
 	ctx->op = op;
 
-	spin_lock_irqsave(&dd->lock, flags);
-	err = ahash_enqueue_request(&dd->queue, req);
-	spin_unlock_irqrestore(&dd->lock, flags);
-
-	omap_sham_handle_queue(dd);
-
-	return err;
+	return omap_sham_handle_queue(dd, req);
 }
 
 static int omap_sham_update(struct ahash_request *req)
@@ -1041,7 +1036,7 @@ static void omap_sham_done_task(unsigned long data)
 		/* finish curent request */
 		omap_sham_finish_req(req, err);
 		/* start new request */
-		omap_sham_handle_queue(dd);
+		omap_sham_handle_queue(dd, NULL);
 	}
 }
 
@@ -1049,7 +1044,7 @@ static void omap_sham_queue_task(unsigned long data)
 {
 	struct omap_sham_dev *dd = (struct omap_sham_dev *)data;
 
-	omap_sham_handle_queue(dd);
+	omap_sham_handle_queue(dd, NULL);
 }
 
 static irqreturn_t omap_sham_irq(int irq, void *dev_id)
-- 
1.7.0.4


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

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

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-11-10 17:36 [PATCH 0/4]v2 omap-sham off mode and error handling fixes Dmitry Kasatkin
2010-11-10 17:36 ` [PATCH 1/4] omap-sham: uses digest buffer in request context Dmitry Kasatkin
2010-11-10 17:36 ` [PATCH 2/4] omap-sham: DMA initialization fixes for off mode Dmitry Kasatkin
2010-11-10 17:36 ` [PATCH 3/4] omap-sham: error handling improved Dmitry Kasatkin
2010-11-10 17:36 ` [PATCH 4/4] omap-sham: removed redundunt locking Dmitry Kasatkin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.