diff options
Diffstat (limited to 'drivers/crypto/omap-sham.c')
-rw-r--r-- | 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 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 | ||
430 | static int omap_sham_update_cpu(struct omap_sham_dev *dd) | 439 | 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) | |||
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 | ||
1072 | static int omap_sham_dma_init(struct omap_sham_dev *dd) | 1093 | static int omap_sham_dma_init(struct omap_sham_dev *dd) |