aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/crypto
diff options
context:
space:
mode:
authorJoel Fernandes <joelf@ti.com>2013-08-17 22:42:32 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2013-08-21 07:28:05 -0400
commit6242332ff2f3431c4fb6f4b21581f38f16569c13 (patch)
tree21213c27d44ec7a100abeb984d92acffad3798df /drivers/crypto
parent1801ad9483b796271a985ab71cfe26f7bbeae6dd (diff)
crypto: omap-aes - Add support for cases of unaligned lengths
For cases where offset/length of on any page of the input SG is not aligned by AES_BLOCK_SIZE, we copy all the pages from the input SG list into a contiguous buffer and prepare a single element SG list for this buffer with length as the total bytes to crypt. This is requried for cases such as when an SG list of 16 bytes total size contains 16 pages each containing 1 byte. DMA using the direct buffers of such instances is not possible. For this purpose, we first detect if the unaligned case and accordingly allocate enough number of pages to satisfy the request and prepare SG lists. We then copy data into the buffer, and copy data out of it on completion. Signed-off-by: Joel Fernandes <joelf@ti.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto')
-rw-r--r--drivers/crypto/omap-aes.c86
1 files changed, 83 insertions, 3 deletions
diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index 7a08a152838a..2fd22ca6a58f 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -158,9 +158,23 @@ struct omap_aes_dev {
158 struct tasklet_struct queue_task; 158 struct tasklet_struct queue_task;
159 159
160 struct ablkcipher_request *req; 160 struct ablkcipher_request *req;
161
162 /*
163 * total is used by PIO mode for book keeping so introduce
164 * variable total_save as need it to calc page_order
165 */
161 size_t total; 166 size_t total;
167 size_t total_save;
168
162 struct scatterlist *in_sg; 169 struct scatterlist *in_sg;
163 struct scatterlist *out_sg; 170 struct scatterlist *out_sg;
171
172 /* Buffers for copying for unaligned cases */
173 struct scatterlist in_sgl;
174 struct scatterlist out_sgl;
175 struct scatterlist *orig_out;
176 int sgs_copied;
177
164 struct scatter_walk in_walk; 178 struct scatter_walk in_walk;
165 struct scatter_walk out_walk; 179 struct scatter_walk out_walk;
166 int dma_in; 180 int dma_in;
@@ -537,12 +551,51 @@ static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)
537 dmaengine_terminate_all(dd->dma_lch_in); 551 dmaengine_terminate_all(dd->dma_lch_in);
538 dmaengine_terminate_all(dd->dma_lch_out); 552 dmaengine_terminate_all(dd->dma_lch_out);
539 553
540 dma_unmap_sg(dd->dev, dd->in_sg, dd->in_sg_len, DMA_TO_DEVICE);
541 dma_unmap_sg(dd->dev, dd->out_sg, dd->out_sg_len, DMA_FROM_DEVICE);
542
543 return err; 554 return err;
544} 555}
545 556
557int omap_aes_check_aligned(struct scatterlist *sg)
558{
559 while (sg) {
560 if (!IS_ALIGNED(sg->offset, 4))
561 return -1;
562 if (!IS_ALIGNED(sg->length, AES_BLOCK_SIZE))
563 return -1;
564 sg = sg_next(sg);
565 }
566 return 0;
567}
568
569int omap_aes_copy_sgs(struct omap_aes_dev *dd)
570{
571 void *buf_in, *buf_out;
572 int pages;
573
574 pages = get_order(dd->total);
575
576 buf_in = (void *)__get_free_pages(GFP_ATOMIC, pages);
577 buf_out = (void *)__get_free_pages(GFP_ATOMIC, pages);
578
579 if (!buf_in || !buf_out) {
580 pr_err("Couldn't allocated pages for unaligned cases.\n");
581 return -1;
582 }
583
584 dd->orig_out = dd->out_sg;
585
586 sg_copy_buf(buf_in, dd->in_sg, 0, dd->total, 0);
587
588 sg_init_table(&dd->in_sgl, 1);
589 sg_set_buf(&dd->in_sgl, buf_in, dd->total);
590 dd->in_sg = &dd->in_sgl;
591
592 sg_init_table(&dd->out_sgl, 1);
593 sg_set_buf(&dd->out_sgl, buf_out, dd->total);
594 dd->out_sg = &dd->out_sgl;
595
596 return 0;
597}
598
546static int omap_aes_handle_queue(struct omap_aes_dev *dd, 599static int omap_aes_handle_queue(struct omap_aes_dev *dd,
547 struct ablkcipher_request *req) 600 struct ablkcipher_request *req)
548{ 601{
@@ -576,9 +629,19 @@ static int omap_aes_handle_queue(struct omap_aes_dev *dd,
576 /* assign new request to device */ 629 /* assign new request to device */
577 dd->req = req; 630 dd->req = req;
578 dd->total = req->nbytes; 631 dd->total = req->nbytes;
632 dd->total_save = req->nbytes;
579 dd->in_sg = req->src; 633 dd->in_sg = req->src;
580 dd->out_sg = req->dst; 634 dd->out_sg = req->dst;
581 635
636 if (omap_aes_check_aligned(dd->in_sg) ||
637 omap_aes_check_aligned(dd->out_sg)) {
638 if (omap_aes_copy_sgs(dd))
639 pr_err("Failed to copy SGs for unaligned cases\n");
640 dd->sgs_copied = 1;
641 } else {
642 dd->sgs_copied = 0;
643 }
644
582 dd->in_sg_len = scatterwalk_bytes_sglen(dd->in_sg, dd->total); 645 dd->in_sg_len = scatterwalk_bytes_sglen(dd->in_sg, dd->total);
583 dd->out_sg_len = scatterwalk_bytes_sglen(dd->out_sg, dd->total); 646 dd->out_sg_len = scatterwalk_bytes_sglen(dd->out_sg, dd->total);
584 BUG_ON(dd->in_sg_len < 0 || dd->out_sg_len < 0); 647 BUG_ON(dd->in_sg_len < 0 || dd->out_sg_len < 0);
@@ -606,14 +669,31 @@ static int omap_aes_handle_queue(struct omap_aes_dev *dd,
606static void omap_aes_done_task(unsigned long data) 669static void omap_aes_done_task(unsigned long data)
607{ 670{
608 struct omap_aes_dev *dd = (struct omap_aes_dev *)data; 671 struct omap_aes_dev *dd = (struct omap_aes_dev *)data;
672 void *buf_in, *buf_out;
673 int pages;
609 674
610 pr_debug("enter done_task\n"); 675 pr_debug("enter done_task\n");
611 676
612 if (!dd->pio_only) { 677 if (!dd->pio_only) {
613 dma_sync_sg_for_device(dd->dev, dd->out_sg, dd->out_sg_len, 678 dma_sync_sg_for_device(dd->dev, dd->out_sg, dd->out_sg_len,
614 DMA_FROM_DEVICE); 679 DMA_FROM_DEVICE);
680 dma_unmap_sg(dd->dev, dd->in_sg, dd->in_sg_len, DMA_TO_DEVICE);
681 dma_unmap_sg(dd->dev, dd->out_sg, dd->out_sg_len,
682 DMA_FROM_DEVICE);
615 omap_aes_crypt_dma_stop(dd); 683 omap_aes_crypt_dma_stop(dd);
616 } 684 }
685
686 if (dd->sgs_copied) {
687 buf_in = sg_virt(&dd->in_sgl);
688 buf_out = sg_virt(&dd->out_sgl);
689
690 sg_copy_buf(buf_out, dd->orig_out, 0, dd->total_save, 1);
691
692 pages = get_order(dd->total_save);
693 free_pages((unsigned long)buf_in, pages);
694 free_pages((unsigned long)buf_out, pages);
695 }
696
617 omap_aes_finish_req(dd, 0); 697 omap_aes_finish_req(dd, 0);
618 omap_aes_handle_queue(dd, NULL); 698 omap_aes_handle_queue(dd, NULL);
619 699