aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/crypto/omap-sham.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/crypto/omap-sham.c')
-rw-r--r--drivers/crypto/omap-sham.c67
1 files changed, 44 insertions, 23 deletions
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index 9dfbc4ab7711..db206284835a 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -83,6 +83,7 @@
83#define FLAGS_INIT 0x0100 83#define FLAGS_INIT 0x0100
84#define FLAGS_CPU 0x0200 84#define FLAGS_CPU 0x0200
85#define FLAGS_HMAC 0x0400 85#define FLAGS_HMAC 0x0400
86#define FLAGS_ERROR 0x0800
86 87
87/* 3rd byte */ 88/* 3rd byte */
88#define FLAGS_BUSY 16 89#define FLAGS_BUSY 16
@@ -137,6 +138,7 @@ struct omap_sham_dev {
137 int irq; 138 int irq;
138 struct clk *iclk; 139 struct clk *iclk;
139 spinlock_t lock; 140 spinlock_t lock;
141 int err;
140 int dma; 142 int dma;
141 int dma_lch; 143 int dma_lch;
142 struct tasklet_struct done_task; 144 struct tasklet_struct done_task;
@@ -234,10 +236,12 @@ static int omap_sham_write_ctrl(struct omap_sham_dev *dd, size_t length,
234 SHA_REG_MASK_SOFTRESET, SHA_REG_MASK_SOFTRESET); 236 SHA_REG_MASK_SOFTRESET, SHA_REG_MASK_SOFTRESET);
235 237
236 if (omap_sham_wait(dd, SHA_REG_SYSSTATUS, 238 if (omap_sham_wait(dd, SHA_REG_SYSSTATUS,
237 SHA_REG_SYSSTATUS_RESETDONE)) 239 SHA_REG_SYSSTATUS_RESETDONE)) {
240 clk_disable(dd->iclk);
238 return -ETIMEDOUT; 241 return -ETIMEDOUT;
239 242 }
240 dd->flags |= FLAGS_INIT; 243 dd->flags |= FLAGS_INIT;
244 dd->err = 0;
241 } 245 }
242 } else { 246 } else {
243 omap_sham_write(dd, SHA_REG_DIGCNT, ctx->digcnt); 247 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,
279 if (err) 283 if (err)
280 return err; 284 return err;
281 285
286 /* should be non-zero before next lines to disable clocks later */
287 ctx->digcnt += length;
288
282 if (omap_sham_wait(dd, SHA_REG_CTRL, SHA_REG_CTRL_INPUT_READY)) 289 if (omap_sham_wait(dd, SHA_REG_CTRL, SHA_REG_CTRL_INPUT_READY))
283 return -ETIMEDOUT; 290 return -ETIMEDOUT;
284 291
285 ctx->digcnt += length;
286
287 if (final) 292 if (final)
288 ctx->flags |= FLAGS_FINAL; /* catch last interrupt */ 293 ctx->flags |= FLAGS_FINAL; /* catch last interrupt */
289 294
@@ -303,7 +308,6 @@ static int omap_sham_xmit_dma(struct omap_sham_dev *dd, dma_addr_t dma_addr,
303 308
304 dev_dbg(dd->dev, "xmit_dma: digcnt: %d, length: %d, final: %d\n", 309 dev_dbg(dd->dev, "xmit_dma: digcnt: %d, length: %d, final: %d\n",
305 ctx->digcnt, length, final); 310 ctx->digcnt, length, final);
306
307 /* flush cache entries related to our page */ 311 /* flush cache entries related to our page */
308 if (dma_addr == ctx->dma_addr) 312 if (dma_addr == ctx->dma_addr)
309 dma_sync_single_for_device(dd->dev, dma_addr, length, 313 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)
411{ 415{
412 struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req); 416 struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
413 unsigned int length; 417 unsigned int length;
418 int err;
414 419
415 ctx->flags |= FLAGS_FAST; 420 ctx->flags |= FLAGS_FAST;
416 421
@@ -424,7 +429,11 @@ static int omap_sham_update_dma_fast(struct omap_sham_dev *dd)
424 429
425 ctx->total -= length; 430 ctx->total -= length;
426 431
427 return omap_sham_xmit_dma(dd, sg_dma_address(ctx->sg), length, 1); 432 err = omap_sham_xmit_dma(dd, sg_dma_address(ctx->sg), length, 1);
433 if (err != -EINPROGRESS)
434 dma_unmap_sg(dd->dev, ctx->sg, 1, DMA_TO_DEVICE);
435
436 return err;
428} 437}
429 438
430static int omap_sham_update_cpu(struct omap_sham_dev *dd) 439static 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)
580 589
581 ctx->bufcnt = 0; 590 ctx->bufcnt = 0;
582 591
583 if (err != -EINPROGRESS)
584 omap_sham_cleanup(req);
585
586 dev_dbg(dd->dev, "final_req: err: %d\n", err); 592 dev_dbg(dd->dev, "final_req: err: %d\n", err);
587 593
588 return err; 594 return err;
@@ -616,9 +622,11 @@ static void omap_sham_finish_req(struct ahash_request *req, int err)
616 omap_sham_copy_hash(ctx->dd->req, 1); 622 omap_sham_copy_hash(ctx->dd->req, 1);
617 if (ctx->flags & FLAGS_HMAC) 623 if (ctx->flags & FLAGS_HMAC)
618 err = omap_sham_finish_req_hmac(req); 624 err = omap_sham_finish_req_hmac(req);
625 } else {
626 ctx->flags |= FLAGS_ERROR;
619 } 627 }
620 628
621 if (ctx->flags & FLAGS_FINAL) 629 if ((ctx->flags & FLAGS_FINAL) || err)
622 omap_sham_cleanup(req); 630 omap_sham_cleanup(req);
623 631
624 clear_bit(FLAGS_BUSY, &ctx->dd->flags); 632 clear_bit(FLAGS_BUSY, &ctx->dd->flags);
@@ -776,12 +784,14 @@ static int omap_sham_final(struct ahash_request *req)
776 784
777 ctx->flags |= FLAGS_FINUP; 785 ctx->flags |= FLAGS_FINUP;
778 786
779 /* OMAP HW accel works only with buffers >= 9 */ 787 if (!(ctx->flags & FLAGS_ERROR)) {
780 /* HMAC is always >= 9 because of ipad */ 788 /* OMAP HW accel works only with buffers >= 9 */
781 if ((ctx->digcnt + ctx->bufcnt) < 9) 789 /* HMAC is always >= 9 because of ipad */
782 err = omap_sham_final_shash(req); 790 if ((ctx->digcnt + ctx->bufcnt) < 9)
783 else if (ctx->bufcnt) 791 err = omap_sham_final_shash(req);
784 return omap_sham_enqueue(req, OP_FINAL); 792 else if (ctx->bufcnt)
793 return omap_sham_enqueue(req, OP_FINAL);
794 }
785 795
786 omap_sham_cleanup(req); 796 omap_sham_cleanup(req);
787 797
@@ -851,6 +861,8 @@ static int omap_sham_cra_init_alg(struct crypto_tfm *tfm, const char *alg_base)
851 struct omap_sham_ctx *tctx = crypto_tfm_ctx(tfm); 861 struct omap_sham_ctx *tctx = crypto_tfm_ctx(tfm);
852 const char *alg_name = crypto_tfm_alg_name(tfm); 862 const char *alg_name = crypto_tfm_alg_name(tfm);
853 863
864 pr_info("enter\n");
865
854 /* Allocate a fallback and abort if it failed. */ 866 /* Allocate a fallback and abort if it failed. */
855 tctx->fallback = crypto_alloc_shash(alg_name, 0, 867 tctx->fallback = crypto_alloc_shash(alg_name, 0,
856 CRYPTO_ALG_NEED_FALLBACK); 868 CRYPTO_ALG_NEED_FALLBACK);
@@ -1008,7 +1020,7 @@ static void omap_sham_done_task(unsigned long data)
1008 struct omap_sham_dev *dd = (struct omap_sham_dev *)data; 1020 struct omap_sham_dev *dd = (struct omap_sham_dev *)data;
1009 struct ahash_request *req = dd->req; 1021 struct ahash_request *req = dd->req;
1010 struct omap_sham_reqctx *ctx = ahash_request_ctx(req); 1022 struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
1011 int ready = 1; 1023 int ready = 0, err = 0;
1012 1024
1013 if (ctx->flags & FLAGS_OUTPUT_READY) { 1025 if (ctx->flags & FLAGS_OUTPUT_READY) {
1014 ctx->flags &= ~FLAGS_OUTPUT_READY; 1026 ctx->flags &= ~FLAGS_OUTPUT_READY;
@@ -1018,13 +1030,16 @@ static void omap_sham_done_task(unsigned long data)
1018 if (dd->flags & FLAGS_DMA_ACTIVE) { 1030 if (dd->flags & FLAGS_DMA_ACTIVE) {
1019 dd->flags &= ~FLAGS_DMA_ACTIVE; 1031 dd->flags &= ~FLAGS_DMA_ACTIVE;
1020 omap_sham_update_dma_stop(dd); 1032 omap_sham_update_dma_stop(dd);
1021 omap_sham_update_dma_slow(dd); 1033 if (!dd->err)
1034 err = omap_sham_update_dma_slow(dd);
1022 } 1035 }
1023 1036
1024 if (ready && !(dd->flags & FLAGS_DMA_ACTIVE)) { 1037 err = dd->err ? : err;
1025 dev_dbg(dd->dev, "update done\n"); 1038
1039 if (err != -EINPROGRESS && (ready || err)) {
1040 dev_dbg(dd->dev, "update done: err: %d\n", err);
1026 /* finish curent request */ 1041 /* finish curent request */
1027 omap_sham_finish_req(req, 0); 1042 omap_sham_finish_req(req, err);
1028 /* start new request */ 1043 /* start new request */
1029 omap_sham_handle_queue(dd); 1044 omap_sham_handle_queue(dd);
1030 } 1045 }
@@ -1056,6 +1071,7 @@ static irqreturn_t omap_sham_irq(int irq, void *dev_id)
1056 omap_sham_read(dd, SHA_REG_CTRL); 1071 omap_sham_read(dd, SHA_REG_CTRL);
1057 1072
1058 ctx->flags |= FLAGS_OUTPUT_READY; 1073 ctx->flags |= FLAGS_OUTPUT_READY;
1074 dd->err = 0;
1059 tasklet_schedule(&dd->done_task); 1075 tasklet_schedule(&dd->done_task);
1060 1076
1061 return IRQ_HANDLED; 1077 return IRQ_HANDLED;
@@ -1065,8 +1081,13 @@ static void omap_sham_dma_callback(int lch, u16 ch_status, void *data)
1065{ 1081{
1066 struct omap_sham_dev *dd = data; 1082 struct omap_sham_dev *dd = data;
1067 1083
1068 if (likely(lch == dd->dma_lch)) 1084 if (ch_status != OMAP_DMA_BLOCK_IRQ) {
1069 tasklet_schedule(&dd->done_task); 1085 pr_err("omap-sham DMA error status: 0x%hx\n", ch_status);
1086 dd->err = -EIO;
1087 dd->flags &= ~FLAGS_INIT; /* request to re-initialize */
1088 }
1089
1090 tasklet_schedule(&dd->done_task);
1070} 1091}
1071 1092
1072static int omap_sham_dma_init(struct omap_sham_dev *dd) 1093static int omap_sham_dma_init(struct omap_sham_dev *dd)