diff options
Diffstat (limited to 'drivers/crypto/omap-aes.c')
-rw-r--r-- | drivers/crypto/omap-aes.c | 260 |
1 files changed, 136 insertions, 124 deletions
diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c index 799ca517c121..add2a1a72ba4 100644 --- a/drivers/crypto/omap-aes.c +++ b/drivers/crypto/omap-aes.c | |||
@@ -74,11 +74,9 @@ | |||
74 | #define FLAGS_CBC BIT(1) | 74 | #define FLAGS_CBC BIT(1) |
75 | #define FLAGS_GIV BIT(2) | 75 | #define FLAGS_GIV BIT(2) |
76 | 76 | ||
77 | #define FLAGS_NEW_KEY BIT(4) | 77 | #define FLAGS_INIT BIT(4) |
78 | #define FLAGS_NEW_IV BIT(5) | 78 | #define FLAGS_FAST BIT(5) |
79 | #define FLAGS_INIT BIT(6) | 79 | #define FLAGS_BUSY BIT(6) |
80 | #define FLAGS_FAST BIT(7) | ||
81 | #define FLAGS_BUSY 8 | ||
82 | 80 | ||
83 | struct omap_aes_ctx { | 81 | struct omap_aes_ctx { |
84 | struct omap_aes_dev *dd; | 82 | struct omap_aes_dev *dd; |
@@ -98,19 +96,18 @@ struct omap_aes_reqctx { | |||
98 | struct omap_aes_dev { | 96 | struct omap_aes_dev { |
99 | struct list_head list; | 97 | struct list_head list; |
100 | unsigned long phys_base; | 98 | unsigned long phys_base; |
101 | void __iomem *io_base; | 99 | void __iomem *io_base; |
102 | struct clk *iclk; | 100 | struct clk *iclk; |
103 | struct omap_aes_ctx *ctx; | 101 | struct omap_aes_ctx *ctx; |
104 | struct device *dev; | 102 | struct device *dev; |
105 | unsigned long flags; | 103 | unsigned long flags; |
104 | int err; | ||
106 | 105 | ||
107 | u32 *iv; | 106 | spinlock_t lock; |
108 | u32 ctrl; | 107 | struct crypto_queue queue; |
109 | 108 | ||
110 | spinlock_t lock; | 109 | struct tasklet_struct done_task; |
111 | struct crypto_queue queue; | 110 | struct tasklet_struct queue_task; |
112 | |||
113 | struct tasklet_struct task; | ||
114 | 111 | ||
115 | struct ablkcipher_request *req; | 112 | struct ablkcipher_request *req; |
116 | size_t total; | 113 | size_t total; |
@@ -179,9 +176,13 @@ static int omap_aes_wait(struct omap_aes_dev *dd, u32 offset, u32 bit) | |||
179 | 176 | ||
180 | static int omap_aes_hw_init(struct omap_aes_dev *dd) | 177 | static int omap_aes_hw_init(struct omap_aes_dev *dd) |
181 | { | 178 | { |
182 | int err = 0; | 179 | /* |
183 | 180 | * clocks are enabled when request starts and disabled when finished. | |
181 | * It may be long delays between requests. | ||
182 | * Device might go to off mode to save power. | ||
183 | */ | ||
184 | clk_enable(dd->iclk); | 184 | clk_enable(dd->iclk); |
185 | |||
185 | if (!(dd->flags & FLAGS_INIT)) { | 186 | if (!(dd->flags & FLAGS_INIT)) { |
186 | /* is it necessary to reset before every operation? */ | 187 | /* is it necessary to reset before every operation? */ |
187 | omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_SOFTRESET, | 188 | omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_SOFTRESET, |
@@ -193,39 +194,26 @@ static int omap_aes_hw_init(struct omap_aes_dev *dd) | |||
193 | __asm__ __volatile__("nop"); | 194 | __asm__ __volatile__("nop"); |
194 | __asm__ __volatile__("nop"); | 195 | __asm__ __volatile__("nop"); |
195 | 196 | ||
196 | err = omap_aes_wait(dd, AES_REG_SYSSTATUS, | 197 | if (omap_aes_wait(dd, AES_REG_SYSSTATUS, |
197 | AES_REG_SYSSTATUS_RESETDONE); | 198 | AES_REG_SYSSTATUS_RESETDONE)) |
198 | if (!err) | 199 | return -ETIMEDOUT; |
199 | dd->flags |= FLAGS_INIT; | ||
200 | } | ||
201 | 200 | ||
202 | return err; | 201 | dd->flags |= FLAGS_INIT; |
203 | } | 202 | dd->err = 0; |
203 | } | ||
204 | 204 | ||
205 | static void omap_aes_hw_cleanup(struct omap_aes_dev *dd) | 205 | return 0; |
206 | { | ||
207 | clk_disable(dd->iclk); | ||
208 | } | 206 | } |
209 | 207 | ||
210 | static void omap_aes_write_ctrl(struct omap_aes_dev *dd) | 208 | static int omap_aes_write_ctrl(struct omap_aes_dev *dd) |
211 | { | 209 | { |
212 | unsigned int key32; | 210 | unsigned int key32; |
213 | int i; | 211 | int i, err; |
214 | u32 val, mask; | 212 | u32 val, mask; |
215 | 213 | ||
216 | val = FLD_VAL(((dd->ctx->keylen >> 3) - 1), 4, 3); | 214 | err = omap_aes_hw_init(dd); |
217 | if (dd->flags & FLAGS_CBC) | 215 | if (err) |
218 | val |= AES_REG_CTRL_CBC; | 216 | return err; |
219 | if (dd->flags & FLAGS_ENCRYPT) | ||
220 | val |= AES_REG_CTRL_DIRECTION; | ||
221 | |||
222 | if (dd->ctrl == val && !(dd->flags & FLAGS_NEW_IV) && | ||
223 | !(dd->ctx->flags & FLAGS_NEW_KEY)) | ||
224 | goto out; | ||
225 | |||
226 | /* only need to write control registers for new settings */ | ||
227 | |||
228 | dd->ctrl = val; | ||
229 | 217 | ||
230 | val = 0; | 218 | val = 0; |
231 | if (dd->dma_lch_out >= 0) | 219 | if (dd->dma_lch_out >= 0) |
@@ -237,30 +225,43 @@ static void omap_aes_write_ctrl(struct omap_aes_dev *dd) | |||
237 | 225 | ||
238 | omap_aes_write_mask(dd, AES_REG_MASK, val, mask); | 226 | omap_aes_write_mask(dd, AES_REG_MASK, val, mask); |
239 | 227 | ||
240 | pr_debug("Set key\n"); | ||
241 | key32 = dd->ctx->keylen / sizeof(u32); | 228 | key32 = dd->ctx->keylen / sizeof(u32); |
242 | /* set a key */ | 229 | |
230 | /* it seems a key should always be set even if it has not changed */ | ||
243 | for (i = 0; i < key32; i++) { | 231 | for (i = 0; i < key32; i++) { |
244 | omap_aes_write(dd, AES_REG_KEY(i), | 232 | omap_aes_write(dd, AES_REG_KEY(i), |
245 | __le32_to_cpu(dd->ctx->key[i])); | 233 | __le32_to_cpu(dd->ctx->key[i])); |
246 | } | 234 | } |
247 | dd->ctx->flags &= ~FLAGS_NEW_KEY; | ||
248 | 235 | ||
249 | if (dd->flags & FLAGS_NEW_IV) { | 236 | if ((dd->flags & FLAGS_CBC) && dd->req->info) |
250 | pr_debug("Set IV\n"); | 237 | omap_aes_write_n(dd, AES_REG_IV(0), dd->req->info, 4); |
251 | omap_aes_write_n(dd, AES_REG_IV(0), dd->iv, 4); | 238 | |
252 | dd->flags &= ~FLAGS_NEW_IV; | 239 | val = FLD_VAL(((dd->ctx->keylen >> 3) - 1), 4, 3); |
253 | } | 240 | if (dd->flags & FLAGS_CBC) |
241 | val |= AES_REG_CTRL_CBC; | ||
242 | if (dd->flags & FLAGS_ENCRYPT) | ||
243 | val |= AES_REG_CTRL_DIRECTION; | ||
254 | 244 | ||
255 | mask = AES_REG_CTRL_CBC | AES_REG_CTRL_DIRECTION | | 245 | mask = AES_REG_CTRL_CBC | AES_REG_CTRL_DIRECTION | |
256 | AES_REG_CTRL_KEY_SIZE; | 246 | AES_REG_CTRL_KEY_SIZE; |
257 | 247 | ||
258 | omap_aes_write_mask(dd, AES_REG_CTRL, dd->ctrl, mask); | 248 | omap_aes_write_mask(dd, AES_REG_CTRL, val, mask); |
259 | 249 | ||
260 | out: | 250 | /* IN */ |
261 | /* start DMA or disable idle mode */ | 251 | omap_set_dma_dest_params(dd->dma_lch_in, 0, OMAP_DMA_AMODE_CONSTANT, |
262 | omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_START, | 252 | dd->phys_base + AES_REG_DATA, 0, 4); |
263 | AES_REG_MASK_START); | 253 | |
254 | omap_set_dma_dest_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4); | ||
255 | omap_set_dma_src_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4); | ||
256 | |||
257 | /* OUT */ | ||
258 | omap_set_dma_src_params(dd->dma_lch_out, 0, OMAP_DMA_AMODE_CONSTANT, | ||
259 | dd->phys_base + AES_REG_DATA, 0, 4); | ||
260 | |||
261 | omap_set_dma_src_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4); | ||
262 | omap_set_dma_dest_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4); | ||
263 | |||
264 | return 0; | ||
264 | } | 265 | } |
265 | 266 | ||
266 | static struct omap_aes_dev *omap_aes_find_dev(struct omap_aes_ctx *ctx) | 267 | static struct omap_aes_dev *omap_aes_find_dev(struct omap_aes_ctx *ctx) |
@@ -288,8 +289,16 @@ static void omap_aes_dma_callback(int lch, u16 ch_status, void *data) | |||
288 | { | 289 | { |
289 | struct omap_aes_dev *dd = data; | 290 | struct omap_aes_dev *dd = data; |
290 | 291 | ||
291 | if (lch == dd->dma_lch_out) | 292 | if (ch_status != OMAP_DMA_BLOCK_IRQ) { |
292 | tasklet_schedule(&dd->task); | 293 | pr_err("omap-aes DMA error status: 0x%hx\n", ch_status); |
294 | dd->err = -EIO; | ||
295 | dd->flags &= ~FLAGS_INIT; /* request to re-initialize */ | ||
296 | } else if (lch == dd->dma_lch_in) { | ||
297 | return; | ||
298 | } | ||
299 | |||
300 | /* dma_lch_out - completed */ | ||
301 | tasklet_schedule(&dd->done_task); | ||
293 | } | 302 | } |
294 | 303 | ||
295 | static int omap_aes_dma_init(struct omap_aes_dev *dd) | 304 | static int omap_aes_dma_init(struct omap_aes_dev *dd) |
@@ -339,18 +348,6 @@ static int omap_aes_dma_init(struct omap_aes_dev *dd) | |||
339 | goto err_dma_out; | 348 | goto err_dma_out; |
340 | } | 349 | } |
341 | 350 | ||
342 | omap_set_dma_dest_params(dd->dma_lch_in, 0, OMAP_DMA_AMODE_CONSTANT, | ||
343 | dd->phys_base + AES_REG_DATA, 0, 4); | ||
344 | |||
345 | omap_set_dma_dest_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4); | ||
346 | omap_set_dma_src_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4); | ||
347 | |||
348 | omap_set_dma_src_params(dd->dma_lch_out, 0, OMAP_DMA_AMODE_CONSTANT, | ||
349 | dd->phys_base + AES_REG_DATA, 0, 4); | ||
350 | |||
351 | omap_set_dma_src_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4); | ||
352 | omap_set_dma_dest_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4); | ||
353 | |||
354 | return 0; | 351 | return 0; |
355 | 352 | ||
356 | err_dma_out: | 353 | err_dma_out: |
@@ -406,6 +403,11 @@ static int sg_copy(struct scatterlist **sg, size_t *offset, void *buf, | |||
406 | if (!count) | 403 | if (!count) |
407 | return off; | 404 | return off; |
408 | 405 | ||
406 | /* | ||
407 | * buflen and total are AES_BLOCK_SIZE size aligned, | ||
408 | * so count should be also aligned | ||
409 | */ | ||
410 | |||
409 | sg_copy_buf(buf + off, *sg, *offset, count, out); | 411 | sg_copy_buf(buf + off, *sg, *offset, count, out); |
410 | 412 | ||
411 | off += count; | 413 | off += count; |
@@ -461,7 +463,9 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in, | |||
461 | omap_start_dma(dd->dma_lch_in); | 463 | omap_start_dma(dd->dma_lch_in); |
462 | omap_start_dma(dd->dma_lch_out); | 464 | omap_start_dma(dd->dma_lch_out); |
463 | 465 | ||
464 | omap_aes_write_ctrl(dd); | 466 | /* start DMA or disable idle mode */ |
467 | omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_START, | ||
468 | AES_REG_MASK_START); | ||
465 | 469 | ||
466 | return 0; | 470 | return 0; |
467 | } | 471 | } |
@@ -488,8 +492,10 @@ static int omap_aes_crypt_dma_start(struct omap_aes_dev *dd) | |||
488 | count = min(dd->total, sg_dma_len(dd->in_sg)); | 492 | count = min(dd->total, sg_dma_len(dd->in_sg)); |
489 | count = min(count, sg_dma_len(dd->out_sg)); | 493 | count = min(count, sg_dma_len(dd->out_sg)); |
490 | 494 | ||
491 | if (count != dd->total) | 495 | if (count != dd->total) { |
496 | pr_err("request length != buffer length\n"); | ||
492 | return -EINVAL; | 497 | return -EINVAL; |
498 | } | ||
493 | 499 | ||
494 | pr_debug("fast\n"); | 500 | pr_debug("fast\n"); |
495 | 501 | ||
@@ -525,23 +531,25 @@ static int omap_aes_crypt_dma_start(struct omap_aes_dev *dd) | |||
525 | 531 | ||
526 | dd->total -= count; | 532 | dd->total -= count; |
527 | 533 | ||
528 | err = omap_aes_hw_init(dd); | ||
529 | |||
530 | err = omap_aes_crypt_dma(tfm, addr_in, addr_out, count); | 534 | err = omap_aes_crypt_dma(tfm, addr_in, addr_out, count); |
535 | if (err) { | ||
536 | dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE); | ||
537 | dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_TO_DEVICE); | ||
538 | } | ||
531 | 539 | ||
532 | return err; | 540 | return err; |
533 | } | 541 | } |
534 | 542 | ||
535 | static void omap_aes_finish_req(struct omap_aes_dev *dd, int err) | 543 | static void omap_aes_finish_req(struct omap_aes_dev *dd, int err) |
536 | { | 544 | { |
537 | struct omap_aes_ctx *ctx; | 545 | struct ablkcipher_request *req = dd->req; |
538 | 546 | ||
539 | pr_debug("err: %d\n", err); | 547 | pr_debug("err: %d\n", err); |
540 | 548 | ||
541 | ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(dd->req)); | 549 | clk_disable(dd->iclk); |
550 | dd->flags &= ~FLAGS_BUSY; | ||
542 | 551 | ||
543 | if (!dd->total) | 552 | req->base.complete(&req->base, err); |
544 | dd->req->base.complete(&dd->req->base, err); | ||
545 | } | 553 | } |
546 | 554 | ||
547 | static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd) | 555 | static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd) |
@@ -553,8 +561,6 @@ static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd) | |||
553 | 561 | ||
554 | omap_aes_write_mask(dd, AES_REG_MASK, 0, AES_REG_MASK_START); | 562 | omap_aes_write_mask(dd, AES_REG_MASK, 0, AES_REG_MASK_START); |
555 | 563 | ||
556 | omap_aes_hw_cleanup(dd); | ||
557 | |||
558 | omap_stop_dma(dd->dma_lch_in); | 564 | omap_stop_dma(dd->dma_lch_in); |
559 | omap_stop_dma(dd->dma_lch_out); | 565 | omap_stop_dma(dd->dma_lch_out); |
560 | 566 | ||
@@ -574,40 +580,39 @@ static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd) | |||
574 | } | 580 | } |
575 | } | 581 | } |
576 | 582 | ||
577 | if (err || !dd->total) | ||
578 | omap_aes_finish_req(dd, err); | ||
579 | |||
580 | return err; | 583 | return err; |
581 | } | 584 | } |
582 | 585 | ||
583 | static int omap_aes_handle_req(struct omap_aes_dev *dd) | 586 | static int omap_aes_handle_queue(struct omap_aes_dev *dd, |
587 | struct ablkcipher_request *req) | ||
584 | { | 588 | { |
585 | struct crypto_async_request *async_req, *backlog; | 589 | struct crypto_async_request *async_req, *backlog; |
586 | struct omap_aes_ctx *ctx; | 590 | struct omap_aes_ctx *ctx; |
587 | struct omap_aes_reqctx *rctx; | 591 | struct omap_aes_reqctx *rctx; |
588 | struct ablkcipher_request *req; | ||
589 | unsigned long flags; | 592 | unsigned long flags; |
590 | 593 | int err, ret = 0; | |
591 | if (dd->total) | ||
592 | goto start; | ||
593 | 594 | ||
594 | spin_lock_irqsave(&dd->lock, flags); | 595 | spin_lock_irqsave(&dd->lock, flags); |
596 | if (req) | ||
597 | ret = ablkcipher_enqueue_request(&dd->queue, req); | ||
598 | if (dd->flags & FLAGS_BUSY) { | ||
599 | spin_unlock_irqrestore(&dd->lock, flags); | ||
600 | return ret; | ||
601 | } | ||
595 | backlog = crypto_get_backlog(&dd->queue); | 602 | backlog = crypto_get_backlog(&dd->queue); |
596 | async_req = crypto_dequeue_request(&dd->queue); | 603 | async_req = crypto_dequeue_request(&dd->queue); |
597 | if (!async_req) | 604 | if (async_req) |
598 | clear_bit(FLAGS_BUSY, &dd->flags); | 605 | dd->flags |= FLAGS_BUSY; |
599 | spin_unlock_irqrestore(&dd->lock, flags); | 606 | spin_unlock_irqrestore(&dd->lock, flags); |
600 | 607 | ||
601 | if (!async_req) | 608 | if (!async_req) |
602 | return 0; | 609 | return ret; |
603 | 610 | ||
604 | if (backlog) | 611 | if (backlog) |
605 | backlog->complete(backlog, -EINPROGRESS); | 612 | backlog->complete(backlog, -EINPROGRESS); |
606 | 613 | ||
607 | req = ablkcipher_request_cast(async_req); | 614 | req = ablkcipher_request_cast(async_req); |
608 | 615 | ||
609 | pr_debug("get new req\n"); | ||
610 | |||
611 | /* assign new request to device */ | 616 | /* assign new request to device */ |
612 | dd->req = req; | 617 | dd->req = req; |
613 | dd->total = req->nbytes; | 618 | dd->total = req->nbytes; |
@@ -621,27 +626,22 @@ static int omap_aes_handle_req(struct omap_aes_dev *dd) | |||
621 | rctx->mode &= FLAGS_MODE_MASK; | 626 | rctx->mode &= FLAGS_MODE_MASK; |
622 | dd->flags = (dd->flags & ~FLAGS_MODE_MASK) | rctx->mode; | 627 | dd->flags = (dd->flags & ~FLAGS_MODE_MASK) | rctx->mode; |
623 | 628 | ||
624 | dd->iv = req->info; | 629 | dd->ctx = ctx; |
625 | if ((dd->flags & FLAGS_CBC) && dd->iv) | ||
626 | dd->flags |= FLAGS_NEW_IV; | ||
627 | else | ||
628 | dd->flags &= ~FLAGS_NEW_IV; | ||
629 | |||
630 | ctx->dd = dd; | 630 | ctx->dd = dd; |
631 | if (dd->ctx != ctx) { | ||
632 | /* assign new context to device */ | ||
633 | dd->ctx = ctx; | ||
634 | ctx->flags |= FLAGS_NEW_KEY; | ||
635 | } | ||
636 | 631 | ||
637 | if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE)) | 632 | err = omap_aes_write_ctrl(dd); |
638 | pr_err("request size is not exact amount of AES blocks\n"); | 633 | if (!err) |
634 | err = omap_aes_crypt_dma_start(dd); | ||
635 | if (err) { | ||
636 | /* aes_task will not finish it, so do it here */ | ||
637 | omap_aes_finish_req(dd, err); | ||
638 | tasklet_schedule(&dd->queue_task); | ||
639 | } | ||
639 | 640 | ||
640 | start: | 641 | return ret; /* return ret, which is enqueue return value */ |
641 | return omap_aes_crypt_dma_start(dd); | ||
642 | } | 642 | } |
643 | 643 | ||
644 | static void omap_aes_task(unsigned long data) | 644 | static void omap_aes_done_task(unsigned long data) |
645 | { | 645 | { |
646 | struct omap_aes_dev *dd = (struct omap_aes_dev *)data; | 646 | struct omap_aes_dev *dd = (struct omap_aes_dev *)data; |
647 | int err; | 647 | int err; |
@@ -650,40 +650,50 @@ static void omap_aes_task(unsigned long data) | |||
650 | 650 | ||
651 | err = omap_aes_crypt_dma_stop(dd); | 651 | err = omap_aes_crypt_dma_stop(dd); |
652 | 652 | ||
653 | err = omap_aes_handle_req(dd); | 653 | err = dd->err ? : err; |
654 | |||
655 | if (dd->total && !err) { | ||
656 | err = omap_aes_crypt_dma_start(dd); | ||
657 | if (!err) | ||
658 | return; /* DMA started. Not fininishing. */ | ||
659 | } | ||
660 | |||
661 | omap_aes_finish_req(dd, err); | ||
662 | omap_aes_handle_queue(dd, NULL); | ||
654 | 663 | ||
655 | pr_debug("exit\n"); | 664 | pr_debug("exit\n"); |
656 | } | 665 | } |
657 | 666 | ||
667 | static void omap_aes_queue_task(unsigned long data) | ||
668 | { | ||
669 | struct omap_aes_dev *dd = (struct omap_aes_dev *)data; | ||
670 | |||
671 | omap_aes_handle_queue(dd, NULL); | ||
672 | } | ||
673 | |||
658 | static int omap_aes_crypt(struct ablkcipher_request *req, unsigned long mode) | 674 | static int omap_aes_crypt(struct ablkcipher_request *req, unsigned long mode) |
659 | { | 675 | { |
660 | struct omap_aes_ctx *ctx = crypto_ablkcipher_ctx( | 676 | struct omap_aes_ctx *ctx = crypto_ablkcipher_ctx( |
661 | crypto_ablkcipher_reqtfm(req)); | 677 | crypto_ablkcipher_reqtfm(req)); |
662 | struct omap_aes_reqctx *rctx = ablkcipher_request_ctx(req); | 678 | struct omap_aes_reqctx *rctx = ablkcipher_request_ctx(req); |
663 | struct omap_aes_dev *dd; | 679 | struct omap_aes_dev *dd; |
664 | unsigned long flags; | ||
665 | int err; | ||
666 | 680 | ||
667 | pr_debug("nbytes: %d, enc: %d, cbc: %d\n", req->nbytes, | 681 | pr_debug("nbytes: %d, enc: %d, cbc: %d\n", req->nbytes, |
668 | !!(mode & FLAGS_ENCRYPT), | 682 | !!(mode & FLAGS_ENCRYPT), |
669 | !!(mode & FLAGS_CBC)); | 683 | !!(mode & FLAGS_CBC)); |
670 | 684 | ||
685 | if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE)) { | ||
686 | pr_err("request size is not exact amount of AES blocks\n"); | ||
687 | return -EINVAL; | ||
688 | } | ||
689 | |||
671 | dd = omap_aes_find_dev(ctx); | 690 | dd = omap_aes_find_dev(ctx); |
672 | if (!dd) | 691 | if (!dd) |
673 | return -ENODEV; | 692 | return -ENODEV; |
674 | 693 | ||
675 | rctx->mode = mode; | 694 | rctx->mode = mode; |
676 | 695 | ||
677 | spin_lock_irqsave(&dd->lock, flags); | 696 | return omap_aes_handle_queue(dd, req); |
678 | err = ablkcipher_enqueue_request(&dd->queue, req); | ||
679 | spin_unlock_irqrestore(&dd->lock, flags); | ||
680 | |||
681 | if (!test_and_set_bit(FLAGS_BUSY, &dd->flags)) | ||
682 | omap_aes_handle_req(dd); | ||
683 | |||
684 | pr_debug("exit\n"); | ||
685 | |||
686 | return err; | ||
687 | } | 697 | } |
688 | 698 | ||
689 | /* ********************** ALG API ************************************ */ | 699 | /* ********************** ALG API ************************************ */ |
@@ -701,7 +711,6 @@ static int omap_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, | |||
701 | 711 | ||
702 | memcpy(ctx->key, key, keylen); | 712 | memcpy(ctx->key, key, keylen); |
703 | ctx->keylen = keylen; | 713 | ctx->keylen = keylen; |
704 | ctx->flags |= FLAGS_NEW_KEY; | ||
705 | 714 | ||
706 | return 0; | 715 | return 0; |
707 | } | 716 | } |
@@ -750,7 +759,7 @@ static struct crypto_alg algs[] = { | |||
750 | .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, | 759 | .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, |
751 | .cra_blocksize = AES_BLOCK_SIZE, | 760 | .cra_blocksize = AES_BLOCK_SIZE, |
752 | .cra_ctxsize = sizeof(struct omap_aes_ctx), | 761 | .cra_ctxsize = sizeof(struct omap_aes_ctx), |
753 | .cra_alignmask = 0, | 762 | .cra_alignmask = 0, |
754 | .cra_type = &crypto_ablkcipher_type, | 763 | .cra_type = &crypto_ablkcipher_type, |
755 | .cra_module = THIS_MODULE, | 764 | .cra_module = THIS_MODULE, |
756 | .cra_init = omap_aes_cra_init, | 765 | .cra_init = omap_aes_cra_init, |
@@ -770,7 +779,7 @@ static struct crypto_alg algs[] = { | |||
770 | .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, | 779 | .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, |
771 | .cra_blocksize = AES_BLOCK_SIZE, | 780 | .cra_blocksize = AES_BLOCK_SIZE, |
772 | .cra_ctxsize = sizeof(struct omap_aes_ctx), | 781 | .cra_ctxsize = sizeof(struct omap_aes_ctx), |
773 | .cra_alignmask = 0, | 782 | .cra_alignmask = 0, |
774 | .cra_type = &crypto_ablkcipher_type, | 783 | .cra_type = &crypto_ablkcipher_type, |
775 | .cra_module = THIS_MODULE, | 784 | .cra_module = THIS_MODULE, |
776 | .cra_init = omap_aes_cra_init, | 785 | .cra_init = omap_aes_cra_init, |
@@ -849,7 +858,8 @@ static int omap_aes_probe(struct platform_device *pdev) | |||
849 | (reg & AES_REG_REV_MAJOR) >> 4, reg & AES_REG_REV_MINOR); | 858 | (reg & AES_REG_REV_MAJOR) >> 4, reg & AES_REG_REV_MINOR); |
850 | clk_disable(dd->iclk); | 859 | clk_disable(dd->iclk); |
851 | 860 | ||
852 | tasklet_init(&dd->task, omap_aes_task, (unsigned long)dd); | 861 | tasklet_init(&dd->done_task, omap_aes_done_task, (unsigned long)dd); |
862 | tasklet_init(&dd->queue_task, omap_aes_queue_task, (unsigned long)dd); | ||
853 | 863 | ||
854 | err = omap_aes_dma_init(dd); | 864 | err = omap_aes_dma_init(dd); |
855 | if (err) | 865 | if (err) |
@@ -876,7 +886,8 @@ err_algs: | |||
876 | crypto_unregister_alg(&algs[j]); | 886 | crypto_unregister_alg(&algs[j]); |
877 | omap_aes_dma_cleanup(dd); | 887 | omap_aes_dma_cleanup(dd); |
878 | err_dma: | 888 | err_dma: |
879 | tasklet_kill(&dd->task); | 889 | tasklet_kill(&dd->done_task); |
890 | tasklet_kill(&dd->queue_task); | ||
880 | iounmap(dd->io_base); | 891 | iounmap(dd->io_base); |
881 | err_io: | 892 | err_io: |
882 | clk_put(dd->iclk); | 893 | clk_put(dd->iclk); |
@@ -903,7 +914,8 @@ static int omap_aes_remove(struct platform_device *pdev) | |||
903 | for (i = 0; i < ARRAY_SIZE(algs); i++) | 914 | for (i = 0; i < ARRAY_SIZE(algs); i++) |
904 | crypto_unregister_alg(&algs[i]); | 915 | crypto_unregister_alg(&algs[i]); |
905 | 916 | ||
906 | tasklet_kill(&dd->task); | 917 | tasklet_kill(&dd->done_task); |
918 | tasklet_kill(&dd->queue_task); | ||
907 | omap_aes_dma_cleanup(dd); | 919 | omap_aes_dma_cleanup(dd); |
908 | iounmap(dd->io_base); | 920 | iounmap(dd->io_base); |
909 | clk_put(dd->iclk); | 921 | clk_put(dd->iclk); |