aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/crypto
diff options
context:
space:
mode:
authorMark A. Greer <mgreer@animalcreek.com>2013-01-08 13:57:42 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2013-01-19 18:16:42 -0500
commitebedbf79026bebe6667322c2407bf05023600929 (patch)
treebd59cb3cc7eebf04ad814a2d0d73731a94560065 /drivers/crypto
parent0635fb3a3c6a6d1a70996428016dca6d3d8f0961 (diff)
crypto: omap-aes - Add code to use dmaengine API
Add code to use the new dmaengine API alongside the existing DMA code that uses the private OMAP DMA API. The API to use is chosen by defining or undefining 'OMAP_AES_DMA_PRIVATE'. CC: Russell King <rmk+kernel@arm.linux.org.uk> CC: Dmitry Kasatkin <dmitry.kasatkin@intel.com> Signed-off-by: Mark A. Greer <mgreer@animalcreek.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto')
-rw-r--r--drivers/crypto/omap-aes.c184
1 files changed, 183 insertions, 1 deletions
diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index 3262139eb9bd..14ec9e209ef8 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -12,6 +12,8 @@
12 * 12 *
13 */ 13 */
14 14
15#define OMAP_AES_DMA_PRIVATE
16
15#define pr_fmt(fmt) "%s: " fmt, __func__ 17#define pr_fmt(fmt) "%s: " fmt, __func__
16 18
17#include <linux/err.h> 19#include <linux/err.h>
@@ -22,6 +24,8 @@
22#include <linux/platform_device.h> 24#include <linux/platform_device.h>
23#include <linux/scatterlist.h> 25#include <linux/scatterlist.h>
24#include <linux/dma-mapping.h> 26#include <linux/dma-mapping.h>
27#include <linux/dmaengine.h>
28#include <linux/omap-dma.h>
25#include <linux/pm_runtime.h> 29#include <linux/pm_runtime.h>
26#include <linux/io.h> 30#include <linux/io.h>
27#include <linux/crypto.h> 31#include <linux/crypto.h>
@@ -29,7 +33,8 @@
29#include <crypto/scatterwalk.h> 33#include <crypto/scatterwalk.h>
30#include <crypto/aes.h> 34#include <crypto/aes.h>
31 35
32#include <linux/omap-dma.h> 36#define DST_MAXBURST 4
37#define DMA_MIN (DST_MAXBURST * sizeof(u32))
33 38
34/* OMAP TRM gives bitfields as start:end, where start is the higher bit 39/* OMAP TRM gives bitfields as start:end, where start is the higher bit
35 number. For example 7:0 */ 40 number. For example 7:0 */
@@ -110,19 +115,33 @@ struct omap_aes_dev {
110 struct ablkcipher_request *req; 115 struct ablkcipher_request *req;
111 size_t total; 116 size_t total;
112 struct scatterlist *in_sg; 117 struct scatterlist *in_sg;
118#ifndef OMAP_AES_DMA_PRIVATE
119 struct scatterlist in_sgl;
120#endif
113 size_t in_offset; 121 size_t in_offset;
114 struct scatterlist *out_sg; 122 struct scatterlist *out_sg;
123#ifndef OMAP_AES_DMA_PRIVATE
124 struct scatterlist out_sgl;
125#endif
115 size_t out_offset; 126 size_t out_offset;
116 127
117 size_t buflen; 128 size_t buflen;
118 void *buf_in; 129 void *buf_in;
119 size_t dma_size; 130 size_t dma_size;
120 int dma_in; 131 int dma_in;
132#ifdef OMAP_AES_DMA_PRIVATE
121 int dma_lch_in; 133 int dma_lch_in;
134#else
135 struct dma_chan *dma_lch_in;
136#endif
122 dma_addr_t dma_addr_in; 137 dma_addr_t dma_addr_in;
123 void *buf_out; 138 void *buf_out;
124 int dma_out; 139 int dma_out;
140#ifdef OMAP_AES_DMA_PRIVATE
125 int dma_lch_out; 141 int dma_lch_out;
142#else
143 struct dma_chan *dma_lch_out;
144#endif
126 dma_addr_t dma_addr_out; 145 dma_addr_t dma_addr_out;
127}; 146};
128 147
@@ -187,10 +206,17 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
187 return err; 206 return err;
188 207
189 val = 0; 208 val = 0;
209#ifdef OMAP_AES_DMA_PRIVATE
190 if (dd->dma_lch_out >= 0) 210 if (dd->dma_lch_out >= 0)
191 val |= AES_REG_MASK_DMA_OUT_EN; 211 val |= AES_REG_MASK_DMA_OUT_EN;
192 if (dd->dma_lch_in >= 0) 212 if (dd->dma_lch_in >= 0)
193 val |= AES_REG_MASK_DMA_IN_EN; 213 val |= AES_REG_MASK_DMA_IN_EN;
214#else
215 if (dd->dma_lch_out != NULL)
216 val |= AES_REG_MASK_DMA_OUT_EN;
217 if (dd->dma_lch_in != NULL)
218 val |= AES_REG_MASK_DMA_IN_EN;
219#endif
194 220
195 mask = AES_REG_MASK_DMA_IN_EN | AES_REG_MASK_DMA_OUT_EN; 221 mask = AES_REG_MASK_DMA_IN_EN | AES_REG_MASK_DMA_OUT_EN;
196 222
@@ -218,6 +244,7 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
218 244
219 omap_aes_write_mask(dd, AES_REG_CTRL, val, mask); 245 omap_aes_write_mask(dd, AES_REG_CTRL, val, mask);
220 246
247#ifdef OMAP_AES_DMA_PRIVATE
221 /* IN */ 248 /* IN */
222 omap_set_dma_dest_params(dd->dma_lch_in, 0, OMAP_DMA_AMODE_CONSTANT, 249 omap_set_dma_dest_params(dd->dma_lch_in, 0, OMAP_DMA_AMODE_CONSTANT,
223 dd->phys_base + AES_REG_DATA, 0, 4); 250 dd->phys_base + AES_REG_DATA, 0, 4);
@@ -231,6 +258,7 @@ static int omap_aes_write_ctrl(struct omap_aes_dev *dd)
231 258
232 omap_set_dma_src_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4); 259 omap_set_dma_src_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4);
233 omap_set_dma_dest_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4); 260 omap_set_dma_dest_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4);
261#endif
234 262
235 return 0; 263 return 0;
236} 264}
@@ -256,6 +284,7 @@ static struct omap_aes_dev *omap_aes_find_dev(struct omap_aes_ctx *ctx)
256 return dd; 284 return dd;
257} 285}
258 286
287#ifdef OMAP_AES_DMA_PRIVATE
259static void omap_aes_dma_callback(int lch, u16 ch_status, void *data) 288static void omap_aes_dma_callback(int lch, u16 ch_status, void *data)
260{ 289{
261 struct omap_aes_dev *dd = data; 290 struct omap_aes_dev *dd = data;
@@ -271,13 +300,30 @@ static void omap_aes_dma_callback(int lch, u16 ch_status, void *data)
271 /* dma_lch_out - completed */ 300 /* dma_lch_out - completed */
272 tasklet_schedule(&dd->done_task); 301 tasklet_schedule(&dd->done_task);
273} 302}
303#else
304static void omap_aes_dma_out_callback(void *data)
305{
306 struct omap_aes_dev *dd = data;
307
308 /* dma_lch_out - completed */
309 tasklet_schedule(&dd->done_task);
310}
311#endif
274 312
275static int omap_aes_dma_init(struct omap_aes_dev *dd) 313static int omap_aes_dma_init(struct omap_aes_dev *dd)
276{ 314{
277 int err = -ENOMEM; 315 int err = -ENOMEM;
316#ifndef OMAP_AES_DMA_PRIVATE
317 dma_cap_mask_t mask;
318#endif
278 319
320#ifdef OMAP_AES_DMA_PRIVATE
279 dd->dma_lch_out = -1; 321 dd->dma_lch_out = -1;
280 dd->dma_lch_in = -1; 322 dd->dma_lch_in = -1;
323#else
324 dd->dma_lch_out = NULL;
325 dd->dma_lch_in = NULL;
326#endif
281 327
282 dd->buf_in = (void *)__get_free_pages(GFP_KERNEL, OMAP_AES_CACHE_SIZE); 328 dd->buf_in = (void *)__get_free_pages(GFP_KERNEL, OMAP_AES_CACHE_SIZE);
283 dd->buf_out = (void *)__get_free_pages(GFP_KERNEL, OMAP_AES_CACHE_SIZE); 329 dd->buf_out = (void *)__get_free_pages(GFP_KERNEL, OMAP_AES_CACHE_SIZE);
@@ -306,6 +352,7 @@ static int omap_aes_dma_init(struct omap_aes_dev *dd)
306 goto err_map_out; 352 goto err_map_out;
307 } 353 }
308 354
355#ifdef OMAP_AES_DMA_PRIVATE
309 err = omap_request_dma(dd->dma_in, "omap-aes-rx", 356 err = omap_request_dma(dd->dma_in, "omap-aes-rx",
310 omap_aes_dma_callback, dd, &dd->dma_lch_in); 357 omap_aes_dma_callback, dd, &dd->dma_lch_in);
311 if (err) { 358 if (err) {
@@ -318,11 +365,33 @@ static int omap_aes_dma_init(struct omap_aes_dev *dd)
318 dev_err(dd->dev, "Unable to request DMA channel\n"); 365 dev_err(dd->dev, "Unable to request DMA channel\n");
319 goto err_dma_out; 366 goto err_dma_out;
320 } 367 }
368#else
369 dma_cap_zero(mask);
370 dma_cap_set(DMA_SLAVE, mask);
371
372 dd->dma_lch_in = dma_request_channel(mask, omap_dma_filter_fn,
373 &dd->dma_in);
374 if (!dd->dma_lch_in) {
375 dev_err(dd->dev, "Unable to request in DMA channel\n");
376 goto err_dma_in;
377 }
378
379 dd->dma_lch_out = dma_request_channel(mask, omap_dma_filter_fn,
380 &dd->dma_out);
381 if (!dd->dma_lch_out) {
382 dev_err(dd->dev, "Unable to request out DMA channel\n");
383 goto err_dma_out;
384 }
385#endif
321 386
322 return 0; 387 return 0;
323 388
324err_dma_out: 389err_dma_out:
390#ifdef OMAP_AES_DMA_PRIVATE
325 omap_free_dma(dd->dma_lch_in); 391 omap_free_dma(dd->dma_lch_in);
392#else
393 dma_release_channel(dd->dma_lch_in);
394#endif
326err_dma_in: 395err_dma_in:
327 dma_unmap_single(dd->dev, dd->dma_addr_out, dd->buflen, 396 dma_unmap_single(dd->dev, dd->dma_addr_out, dd->buflen,
328 DMA_FROM_DEVICE); 397 DMA_FROM_DEVICE);
@@ -339,8 +408,13 @@ err_alloc:
339 408
340static void omap_aes_dma_cleanup(struct omap_aes_dev *dd) 409static void omap_aes_dma_cleanup(struct omap_aes_dev *dd)
341{ 410{
411#ifdef OMAP_AES_DMA_PRIVATE
342 omap_free_dma(dd->dma_lch_out); 412 omap_free_dma(dd->dma_lch_out);
343 omap_free_dma(dd->dma_lch_in); 413 omap_free_dma(dd->dma_lch_in);
414#else
415 dma_release_channel(dd->dma_lch_out);
416 dma_release_channel(dd->dma_lch_in);
417#endif
344 dma_unmap_single(dd->dev, dd->dma_addr_out, dd->buflen, 418 dma_unmap_single(dd->dev, dd->dma_addr_out, dd->buflen,
345 DMA_FROM_DEVICE); 419 DMA_FROM_DEVICE);
346 dma_unmap_single(dd->dev, dd->dma_addr_in, dd->buflen, DMA_TO_DEVICE); 420 dma_unmap_single(dd->dev, dd->dma_addr_in, dd->buflen, DMA_TO_DEVICE);
@@ -398,12 +472,24 @@ static int sg_copy(struct scatterlist **sg, size_t *offset, void *buf,
398 return off; 472 return off;
399} 473}
400 474
475#ifdef OMAP_AES_DMA_PRIVATE
401static int omap_aes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in, 476static int omap_aes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
402 dma_addr_t dma_addr_out, int length) 477 dma_addr_t dma_addr_out, int length)
478#else
479static int omap_aes_crypt_dma(struct crypto_tfm *tfm,
480 struct scatterlist *in_sg, struct scatterlist *out_sg)
481#endif
403{ 482{
404 struct omap_aes_ctx *ctx = crypto_tfm_ctx(tfm); 483 struct omap_aes_ctx *ctx = crypto_tfm_ctx(tfm);
405 struct omap_aes_dev *dd = ctx->dd; 484 struct omap_aes_dev *dd = ctx->dd;
485#ifdef OMAP_AES_DMA_PRIVATE
406 int len32; 486 int len32;
487#else
488 struct dma_async_tx_descriptor *tx_in, *tx_out;
489 struct dma_slave_config cfg;
490 dma_addr_t dma_addr_in = sg_dma_address(in_sg);
491 int ret, length = sg_dma_len(in_sg);
492#endif
407 493
408 pr_debug("len: %d\n", length); 494 pr_debug("len: %d\n", length);
409 495
@@ -413,6 +499,7 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
413 dma_sync_single_for_device(dd->dev, dma_addr_in, length, 499 dma_sync_single_for_device(dd->dev, dma_addr_in, length,
414 DMA_TO_DEVICE); 500 DMA_TO_DEVICE);
415 501
502#ifdef OMAP_AES_DMA_PRIVATE
416 len32 = DIV_ROUND_UP(length, sizeof(u32)); 503 len32 = DIV_ROUND_UP(length, sizeof(u32));
417 504
418 /* IN */ 505 /* IN */
@@ -433,6 +520,60 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in,
433 520
434 omap_start_dma(dd->dma_lch_in); 521 omap_start_dma(dd->dma_lch_in);
435 omap_start_dma(dd->dma_lch_out); 522 omap_start_dma(dd->dma_lch_out);
523#else
524 memset(&cfg, 0, sizeof(cfg));
525
526 cfg.src_addr = dd->phys_base + AES_REG_DATA;
527 cfg.dst_addr = dd->phys_base + AES_REG_DATA;
528 cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
529 cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
530 cfg.src_maxburst = DST_MAXBURST;
531 cfg.dst_maxburst = DST_MAXBURST;
532
533 /* IN */
534 ret = dmaengine_slave_config(dd->dma_lch_in, &cfg);
535 if (ret) {
536 dev_err(dd->dev, "can't configure IN dmaengine slave: %d\n",
537 ret);
538 return ret;
539 }
540
541 tx_in = dmaengine_prep_slave_sg(dd->dma_lch_in, in_sg, 1,
542 DMA_MEM_TO_DEV,
543 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
544 if (!tx_in) {
545 dev_err(dd->dev, "IN prep_slave_sg() failed\n");
546 return -EINVAL;
547 }
548
549 /* No callback necessary */
550 tx_in->callback_param = dd;
551
552 /* OUT */
553 ret = dmaengine_slave_config(dd->dma_lch_out, &cfg);
554 if (ret) {
555 dev_err(dd->dev, "can't configure OUT dmaengine slave: %d\n",
556 ret);
557 return ret;
558 }
559
560 tx_out = dmaengine_prep_slave_sg(dd->dma_lch_out, out_sg, 1,
561 DMA_DEV_TO_MEM,
562 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
563 if (!tx_out) {
564 dev_err(dd->dev, "OUT prep_slave_sg() failed\n");
565 return -EINVAL;
566 }
567
568 tx_out->callback = omap_aes_dma_out_callback;
569 tx_out->callback_param = dd;
570
571 dmaengine_submit(tx_in);
572 dmaengine_submit(tx_out);
573
574 dma_async_issue_pending(dd->dma_lch_in);
575 dma_async_issue_pending(dd->dma_lch_out);
576#endif
436 577
437 /* start DMA or disable idle mode */ 578 /* start DMA or disable idle mode */
438 omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_START, 579 omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_START,
@@ -448,6 +589,10 @@ static int omap_aes_crypt_dma_start(struct omap_aes_dev *dd)
448 int err, fast = 0, in, out; 589 int err, fast = 0, in, out;
449 size_t count; 590 size_t count;
450 dma_addr_t addr_in, addr_out; 591 dma_addr_t addr_in, addr_out;
592#ifndef OMAP_AES_DMA_PRIVATE
593 struct scatterlist *in_sg, *out_sg;
594 int len32;
595#endif
451 596
452 pr_debug("total: %d\n", dd->total); 597 pr_debug("total: %d\n", dd->total);
453 598
@@ -486,6 +631,11 @@ static int omap_aes_crypt_dma_start(struct omap_aes_dev *dd)
486 addr_in = sg_dma_address(dd->in_sg); 631 addr_in = sg_dma_address(dd->in_sg);
487 addr_out = sg_dma_address(dd->out_sg); 632 addr_out = sg_dma_address(dd->out_sg);
488 633
634#ifndef OMAP_AES_DMA_PRIVATE
635 in_sg = dd->in_sg;
636 out_sg = dd->out_sg;
637#endif
638
489 dd->flags |= FLAGS_FAST; 639 dd->flags |= FLAGS_FAST;
490 640
491 } else { 641 } else {
@@ -493,6 +643,29 @@ static int omap_aes_crypt_dma_start(struct omap_aes_dev *dd)
493 count = sg_copy(&dd->in_sg, &dd->in_offset, dd->buf_in, 643 count = sg_copy(&dd->in_sg, &dd->in_offset, dd->buf_in,
494 dd->buflen, dd->total, 0); 644 dd->buflen, dd->total, 0);
495 645
646#ifndef OMAP_AES_DMA_PRIVATE
647 len32 = DIV_ROUND_UP(count, DMA_MIN) * DMA_MIN;
648
649 /*
650 * The data going into the AES module has been copied
651 * to a local buffer and the data coming out will go
652 * into a local buffer so set up local SG entries for
653 * both.
654 */
655 sg_init_table(&dd->in_sgl, 1);
656 dd->in_sgl.offset = dd->in_offset;
657 sg_dma_len(&dd->in_sgl) = len32;
658 sg_dma_address(&dd->in_sgl) = dd->dma_addr_in;
659
660 sg_init_table(&dd->out_sgl, 1);
661 dd->out_sgl.offset = dd->out_offset;
662 sg_dma_len(&dd->out_sgl) = len32;
663 sg_dma_address(&dd->out_sgl) = dd->dma_addr_out;
664
665 in_sg = &dd->in_sgl;
666 out_sg = &dd->out_sgl;
667#endif
668
496 addr_in = dd->dma_addr_in; 669 addr_in = dd->dma_addr_in;
497 addr_out = dd->dma_addr_out; 670 addr_out = dd->dma_addr_out;
498 671
@@ -502,7 +675,11 @@ static int omap_aes_crypt_dma_start(struct omap_aes_dev *dd)
502 675
503 dd->total -= count; 676 dd->total -= count;
504 677
678#ifdef OMAP_AES_DMA_PRIVATE
505 err = omap_aes_crypt_dma(tfm, addr_in, addr_out, count); 679 err = omap_aes_crypt_dma(tfm, addr_in, addr_out, count);
680#else
681 err = omap_aes_crypt_dma(tfm, in_sg, out_sg);
682#endif
506 if (err) { 683 if (err) {
507 dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE); 684 dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
508 dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_TO_DEVICE); 685 dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_TO_DEVICE);
@@ -532,8 +709,13 @@ static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)
532 709
533 omap_aes_write_mask(dd, AES_REG_MASK, 0, AES_REG_MASK_START); 710 omap_aes_write_mask(dd, AES_REG_MASK, 0, AES_REG_MASK_START);
534 711
712#ifdef OMAP_AES_DMA_PRIVATE
535 omap_stop_dma(dd->dma_lch_in); 713 omap_stop_dma(dd->dma_lch_in);
536 omap_stop_dma(dd->dma_lch_out); 714 omap_stop_dma(dd->dma_lch_out);
715#else
716 dmaengine_terminate_all(dd->dma_lch_in);
717 dmaengine_terminate_all(dd->dma_lch_out);
718#endif
537 719
538 if (dd->flags & FLAGS_FAST) { 720 if (dd->flags & FLAGS_FAST) {
539 dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE); 721 dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE);