diff options
-rw-r--r-- | drivers/crypto/sahara.c | 152 |
1 files changed, 66 insertions, 86 deletions
diff --git a/drivers/crypto/sahara.c b/drivers/crypto/sahara.c index 55c0d2bea426..04d3b4309e4c 100644 --- a/drivers/crypto/sahara.c +++ b/drivers/crypto/sahara.c | |||
@@ -22,7 +22,9 @@ | |||
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/irq.h> | 23 | #include <linux/irq.h> |
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | #include <linux/kthread.h> | ||
25 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/mutex.h> | ||
26 | #include <linux/of.h> | 28 | #include <linux/of.h> |
27 | #include <linux/of_device.h> | 29 | #include <linux/of_device.h> |
28 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
@@ -38,7 +40,6 @@ | |||
38 | #define FLAGS_ENCRYPT BIT(0) | 40 | #define FLAGS_ENCRYPT BIT(0) |
39 | #define FLAGS_CBC BIT(1) | 41 | #define FLAGS_CBC BIT(1) |
40 | #define FLAGS_NEW_KEY BIT(3) | 42 | #define FLAGS_NEW_KEY BIT(3) |
41 | #define FLAGS_BUSY 4 | ||
42 | 43 | ||
43 | #define SAHARA_HDR_BASE 0x00800000 | 44 | #define SAHARA_HDR_BASE 0x00800000 |
44 | #define SAHARA_HDR_SKHA_ALG_AES 0 | 45 | #define SAHARA_HDR_SKHA_ALG_AES 0 |
@@ -119,7 +120,6 @@ struct sahara_hw_link { | |||
119 | }; | 120 | }; |
120 | 121 | ||
121 | struct sahara_ctx { | 122 | struct sahara_ctx { |
122 | struct sahara_dev *dev; | ||
123 | unsigned long flags; | 123 | unsigned long flags; |
124 | int keylen; | 124 | int keylen; |
125 | u8 key[AES_KEYSIZE_128]; | 125 | u8 key[AES_KEYSIZE_128]; |
@@ -136,15 +136,15 @@ struct sahara_dev { | |||
136 | void __iomem *regs_base; | 136 | void __iomem *regs_base; |
137 | struct clk *clk_ipg; | 137 | struct clk *clk_ipg; |
138 | struct clk *clk_ahb; | 138 | struct clk *clk_ahb; |
139 | struct mutex queue_mutex; | ||
140 | struct task_struct *kthread; | ||
141 | struct completion dma_completion; | ||
139 | 142 | ||
140 | struct sahara_ctx *ctx; | 143 | struct sahara_ctx *ctx; |
141 | spinlock_t lock; | 144 | spinlock_t lock; |
142 | struct crypto_queue queue; | 145 | struct crypto_queue queue; |
143 | unsigned long flags; | 146 | unsigned long flags; |
144 | 147 | ||
145 | struct tasklet_struct done_task; | ||
146 | struct tasklet_struct queue_task; | ||
147 | |||
148 | struct sahara_hw_desc *hw_desc[SAHARA_MAX_HW_DESC]; | 148 | struct sahara_hw_desc *hw_desc[SAHARA_MAX_HW_DESC]; |
149 | dma_addr_t hw_phys_desc[SAHARA_MAX_HW_DESC]; | 149 | dma_addr_t hw_phys_desc[SAHARA_MAX_HW_DESC]; |
150 | 150 | ||
@@ -157,7 +157,6 @@ struct sahara_dev { | |||
157 | struct sahara_hw_link *hw_link[SAHARA_MAX_HW_LINK]; | 157 | struct sahara_hw_link *hw_link[SAHARA_MAX_HW_LINK]; |
158 | dma_addr_t hw_phys_link[SAHARA_MAX_HW_LINK]; | 158 | dma_addr_t hw_phys_link[SAHARA_MAX_HW_LINK]; |
159 | 159 | ||
160 | struct ablkcipher_request *req; | ||
161 | size_t total; | 160 | size_t total; |
162 | struct scatterlist *in_sg; | 161 | struct scatterlist *in_sg; |
163 | unsigned int nb_in_sg; | 162 | unsigned int nb_in_sg; |
@@ -165,7 +164,6 @@ struct sahara_dev { | |||
165 | unsigned int nb_out_sg; | 164 | unsigned int nb_out_sg; |
166 | 165 | ||
167 | u32 error; | 166 | u32 error; |
168 | struct timer_list watchdog; | ||
169 | }; | 167 | }; |
170 | 168 | ||
171 | static struct sahara_dev *dev_ptr; | 169 | static struct sahara_dev *dev_ptr; |
@@ -404,34 +402,6 @@ static void sahara_dump_links(struct sahara_dev *dev) | |||
404 | dev_dbg(dev->device, "\n"); | 402 | dev_dbg(dev->device, "\n"); |
405 | } | 403 | } |
406 | 404 | ||
407 | static void sahara_aes_done_task(unsigned long data) | ||
408 | { | ||
409 | struct sahara_dev *dev = (struct sahara_dev *)data; | ||
410 | |||
411 | dma_unmap_sg(dev->device, dev->out_sg, dev->nb_out_sg, | ||
412 | DMA_TO_DEVICE); | ||
413 | dma_unmap_sg(dev->device, dev->in_sg, dev->nb_in_sg, | ||
414 | DMA_FROM_DEVICE); | ||
415 | |||
416 | spin_lock(&dev->lock); | ||
417 | clear_bit(FLAGS_BUSY, &dev->flags); | ||
418 | spin_unlock(&dev->lock); | ||
419 | |||
420 | dev->req->base.complete(&dev->req->base, dev->error); | ||
421 | } | ||
422 | |||
423 | static void sahara_watchdog(unsigned long data) | ||
424 | { | ||
425 | struct sahara_dev *dev = (struct sahara_dev *)data; | ||
426 | unsigned int err = sahara_read(dev, SAHARA_REG_ERRSTATUS); | ||
427 | unsigned int stat = sahara_read(dev, SAHARA_REG_STATUS); | ||
428 | |||
429 | sahara_decode_status(dev, stat); | ||
430 | sahara_decode_error(dev, err); | ||
431 | dev->error = -ETIMEDOUT; | ||
432 | sahara_aes_done_task(data); | ||
433 | } | ||
434 | |||
435 | static int sahara_hw_descriptor_create(struct sahara_dev *dev) | 405 | static int sahara_hw_descriptor_create(struct sahara_dev *dev) |
436 | { | 406 | { |
437 | struct sahara_ctx *ctx = dev->ctx; | 407 | struct sahara_ctx *ctx = dev->ctx; |
@@ -515,9 +485,6 @@ static int sahara_hw_descriptor_create(struct sahara_dev *dev) | |||
515 | sahara_dump_descriptors(dev); | 485 | sahara_dump_descriptors(dev); |
516 | sahara_dump_links(dev); | 486 | sahara_dump_links(dev); |
517 | 487 | ||
518 | /* Start processing descriptor chain. */ | ||
519 | mod_timer(&dev->watchdog, | ||
520 | jiffies + msecs_to_jiffies(SAHARA_TIMEOUT_MS)); | ||
521 | sahara_write(dev, dev->hw_phys_desc[0], SAHARA_REG_DAR); | 488 | sahara_write(dev, dev->hw_phys_desc[0], SAHARA_REG_DAR); |
522 | 489 | ||
523 | return 0; | 490 | return 0; |
@@ -532,37 +499,19 @@ unmap_in: | |||
532 | return -EINVAL; | 499 | return -EINVAL; |
533 | } | 500 | } |
534 | 501 | ||
535 | static void sahara_aes_queue_task(unsigned long data) | 502 | static int sahara_aes_process(struct ablkcipher_request *req) |
536 | { | 503 | { |
537 | struct sahara_dev *dev = (struct sahara_dev *)data; | 504 | struct sahara_dev *dev = dev_ptr; |
538 | struct crypto_async_request *async_req, *backlog; | ||
539 | struct sahara_ctx *ctx; | 505 | struct sahara_ctx *ctx; |
540 | struct sahara_aes_reqctx *rctx; | 506 | struct sahara_aes_reqctx *rctx; |
541 | struct ablkcipher_request *req; | ||
542 | int ret; | 507 | int ret; |
543 | 508 | ||
544 | spin_lock(&dev->lock); | ||
545 | backlog = crypto_get_backlog(&dev->queue); | ||
546 | async_req = crypto_dequeue_request(&dev->queue); | ||
547 | if (!async_req) | ||
548 | clear_bit(FLAGS_BUSY, &dev->flags); | ||
549 | spin_unlock(&dev->lock); | ||
550 | |||
551 | if (!async_req) | ||
552 | return; | ||
553 | |||
554 | if (backlog) | ||
555 | backlog->complete(backlog, -EINPROGRESS); | ||
556 | |||
557 | req = ablkcipher_request_cast(async_req); | ||
558 | |||
559 | /* Request is ready to be dispatched by the device */ | 509 | /* Request is ready to be dispatched by the device */ |
560 | dev_dbg(dev->device, | 510 | dev_dbg(dev->device, |
561 | "dispatch request (nbytes=%d, src=%p, dst=%p)\n", | 511 | "dispatch request (nbytes=%d, src=%p, dst=%p)\n", |
562 | req->nbytes, req->src, req->dst); | 512 | req->nbytes, req->src, req->dst); |
563 | 513 | ||
564 | /* assign new request to device */ | 514 | /* assign new request to device */ |
565 | dev->req = req; | ||
566 | dev->total = req->nbytes; | 515 | dev->total = req->nbytes; |
567 | dev->in_sg = req->src; | 516 | dev->in_sg = req->src; |
568 | dev->out_sg = req->dst; | 517 | dev->out_sg = req->dst; |
@@ -576,16 +525,25 @@ static void sahara_aes_queue_task(unsigned long data) | |||
576 | memcpy(dev->iv_base, req->info, AES_KEYSIZE_128); | 525 | memcpy(dev->iv_base, req->info, AES_KEYSIZE_128); |
577 | 526 | ||
578 | /* assign new context to device */ | 527 | /* assign new context to device */ |
579 | ctx->dev = dev; | ||
580 | dev->ctx = ctx; | 528 | dev->ctx = ctx; |
581 | 529 | ||
530 | reinit_completion(&dev->dma_completion); | ||
531 | |||
582 | ret = sahara_hw_descriptor_create(dev); | 532 | ret = sahara_hw_descriptor_create(dev); |
583 | if (ret < 0) { | 533 | |
584 | spin_lock(&dev->lock); | 534 | ret = wait_for_completion_timeout(&dev->dma_completion, |
585 | clear_bit(FLAGS_BUSY, &dev->flags); | 535 | msecs_to_jiffies(SAHARA_TIMEOUT_MS)); |
586 | spin_unlock(&dev->lock); | 536 | if (!ret) { |
587 | dev->req->base.complete(&dev->req->base, ret); | 537 | dev_err(dev->device, "AES timeout\n"); |
538 | return -ETIMEDOUT; | ||
588 | } | 539 | } |
540 | |||
541 | dma_unmap_sg(dev->device, dev->out_sg, dev->nb_out_sg, | ||
542 | DMA_TO_DEVICE); | ||
543 | dma_unmap_sg(dev->device, dev->in_sg, dev->nb_in_sg, | ||
544 | DMA_FROM_DEVICE); | ||
545 | |||
546 | return 0; | ||
589 | } | 547 | } |
590 | 548 | ||
591 | static int sahara_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, | 549 | static int sahara_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, |
@@ -627,12 +585,9 @@ static int sahara_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, | |||
627 | 585 | ||
628 | static int sahara_aes_crypt(struct ablkcipher_request *req, unsigned long mode) | 586 | static int sahara_aes_crypt(struct ablkcipher_request *req, unsigned long mode) |
629 | { | 587 | { |
630 | struct sahara_ctx *ctx = crypto_ablkcipher_ctx( | ||
631 | crypto_ablkcipher_reqtfm(req)); | ||
632 | struct sahara_aes_reqctx *rctx = ablkcipher_request_ctx(req); | 588 | struct sahara_aes_reqctx *rctx = ablkcipher_request_ctx(req); |
633 | struct sahara_dev *dev = dev_ptr; | 589 | struct sahara_dev *dev = dev_ptr; |
634 | int err = 0; | 590 | int err = 0; |
635 | int busy; | ||
636 | 591 | ||
637 | dev_dbg(dev->device, "nbytes: %d, enc: %d, cbc: %d\n", | 592 | dev_dbg(dev->device, "nbytes: %d, enc: %d, cbc: %d\n", |
638 | req->nbytes, !!(mode & FLAGS_ENCRYPT), !!(mode & FLAGS_CBC)); | 593 | req->nbytes, !!(mode & FLAGS_ENCRYPT), !!(mode & FLAGS_CBC)); |
@@ -643,16 +598,13 @@ static int sahara_aes_crypt(struct ablkcipher_request *req, unsigned long mode) | |||
643 | return -EINVAL; | 598 | return -EINVAL; |
644 | } | 599 | } |
645 | 600 | ||
646 | ctx->dev = dev; | ||
647 | |||
648 | rctx->mode = mode; | 601 | rctx->mode = mode; |
649 | spin_lock_bh(&dev->lock); | 602 | |
603 | mutex_lock(&dev->queue_mutex); | ||
650 | err = ablkcipher_enqueue_request(&dev->queue, req); | 604 | err = ablkcipher_enqueue_request(&dev->queue, req); |
651 | busy = test_and_set_bit(FLAGS_BUSY, &dev->flags); | 605 | mutex_unlock(&dev->queue_mutex); |
652 | spin_unlock_bh(&dev->lock); | ||
653 | 606 | ||
654 | if (!busy) | 607 | wake_up_process(dev->kthread); |
655 | tasklet_schedule(&dev->queue_task); | ||
656 | 608 | ||
657 | return err; | 609 | return err; |
658 | } | 610 | } |
@@ -755,6 +707,36 @@ static void sahara_aes_cra_exit(struct crypto_tfm *tfm) | |||
755 | ctx->fallback = NULL; | 707 | ctx->fallback = NULL; |
756 | } | 708 | } |
757 | 709 | ||
710 | static int sahara_queue_manage(void *data) | ||
711 | { | ||
712 | struct sahara_dev *dev = (struct sahara_dev *)data; | ||
713 | struct crypto_async_request *async_req; | ||
714 | int ret = 0; | ||
715 | |||
716 | do { | ||
717 | __set_current_state(TASK_INTERRUPTIBLE); | ||
718 | |||
719 | mutex_lock(&dev->queue_mutex); | ||
720 | async_req = crypto_dequeue_request(&dev->queue); | ||
721 | mutex_unlock(&dev->queue_mutex); | ||
722 | |||
723 | if (async_req) { | ||
724 | struct ablkcipher_request *req = | ||
725 | ablkcipher_request_cast(async_req); | ||
726 | |||
727 | ret = sahara_aes_process(req); | ||
728 | |||
729 | async_req->complete(async_req, ret); | ||
730 | |||
731 | continue; | ||
732 | } | ||
733 | |||
734 | schedule(); | ||
735 | } while (!kthread_should_stop()); | ||
736 | |||
737 | return 0; | ||
738 | } | ||
739 | |||
758 | static struct crypto_alg aes_algs[] = { | 740 | static struct crypto_alg aes_algs[] = { |
759 | { | 741 | { |
760 | .cra_name = "ecb(aes)", | 742 | .cra_name = "ecb(aes)", |
@@ -806,8 +788,6 @@ static irqreturn_t sahara_irq_handler(int irq, void *data) | |||
806 | unsigned int stat = sahara_read(dev, SAHARA_REG_STATUS); | 788 | unsigned int stat = sahara_read(dev, SAHARA_REG_STATUS); |
807 | unsigned int err = sahara_read(dev, SAHARA_REG_ERRSTATUS); | 789 | unsigned int err = sahara_read(dev, SAHARA_REG_ERRSTATUS); |
808 | 790 | ||
809 | del_timer(&dev->watchdog); | ||
810 | |||
811 | sahara_write(dev, SAHARA_CMD_CLEAR_INT | SAHARA_CMD_CLEAR_ERR, | 791 | sahara_write(dev, SAHARA_CMD_CLEAR_INT | SAHARA_CMD_CLEAR_ERR, |
812 | SAHARA_REG_CMD); | 792 | SAHARA_REG_CMD); |
813 | 793 | ||
@@ -822,7 +802,7 @@ static irqreturn_t sahara_irq_handler(int irq, void *data) | |||
822 | dev->error = -EINVAL; | 802 | dev->error = -EINVAL; |
823 | } | 803 | } |
824 | 804 | ||
825 | tasklet_schedule(&dev->done_task); | 805 | complete(&dev->dma_completion); |
826 | 806 | ||
827 | return IRQ_HANDLED; | 807 | return IRQ_HANDLED; |
828 | } | 808 | } |
@@ -961,17 +941,17 @@ static int sahara_probe(struct platform_device *pdev) | |||
961 | crypto_init_queue(&dev->queue, SAHARA_QUEUE_LENGTH); | 941 | crypto_init_queue(&dev->queue, SAHARA_QUEUE_LENGTH); |
962 | 942 | ||
963 | spin_lock_init(&dev->lock); | 943 | spin_lock_init(&dev->lock); |
944 | mutex_init(&dev->queue_mutex); | ||
964 | 945 | ||
965 | dev_ptr = dev; | 946 | dev_ptr = dev; |
966 | 947 | ||
967 | tasklet_init(&dev->queue_task, sahara_aes_queue_task, | 948 | dev->kthread = kthread_run(sahara_queue_manage, dev, "sahara_crypto"); |
968 | (unsigned long)dev); | 949 | if (IS_ERR(dev->kthread)) { |
969 | tasklet_init(&dev->done_task, sahara_aes_done_task, | 950 | err = PTR_ERR(dev->kthread); |
970 | (unsigned long)dev); | 951 | goto err_link; |
952 | } | ||
971 | 953 | ||
972 | init_timer(&dev->watchdog); | 954 | init_completion(&dev->dma_completion); |
973 | dev->watchdog.function = &sahara_watchdog; | ||
974 | dev->watchdog.data = (unsigned long)dev; | ||
975 | 955 | ||
976 | clk_prepare_enable(dev->clk_ipg); | 956 | clk_prepare_enable(dev->clk_ipg); |
977 | clk_prepare_enable(dev->clk_ahb); | 957 | clk_prepare_enable(dev->clk_ahb); |
@@ -1016,6 +996,7 @@ err_algs: | |||
1016 | dev->hw_link[0], dev->hw_phys_link[0]); | 996 | dev->hw_link[0], dev->hw_phys_link[0]); |
1017 | clk_disable_unprepare(dev->clk_ipg); | 997 | clk_disable_unprepare(dev->clk_ipg); |
1018 | clk_disable_unprepare(dev->clk_ahb); | 998 | clk_disable_unprepare(dev->clk_ahb); |
999 | kthread_stop(dev->kthread); | ||
1019 | dev_ptr = NULL; | 1000 | dev_ptr = NULL; |
1020 | err_link: | 1001 | err_link: |
1021 | dma_free_coherent(&pdev->dev, | 1002 | dma_free_coherent(&pdev->dev, |
@@ -1043,8 +1024,7 @@ static int sahara_remove(struct platform_device *pdev) | |||
1043 | SAHARA_MAX_HW_DESC * sizeof(struct sahara_hw_desc), | 1024 | SAHARA_MAX_HW_DESC * sizeof(struct sahara_hw_desc), |
1044 | dev->hw_desc[0], dev->hw_phys_desc[0]); | 1025 | dev->hw_desc[0], dev->hw_phys_desc[0]); |
1045 | 1026 | ||
1046 | tasklet_kill(&dev->done_task); | 1027 | kthread_stop(dev->kthread); |
1047 | tasklet_kill(&dev->queue_task); | ||
1048 | 1028 | ||
1049 | sahara_unregister_algs(dev); | 1029 | sahara_unregister_algs(dev); |
1050 | 1030 | ||