diff options
author | Yuan Kang <Yuan.Kang@freescale.com> | 2012-06-22 20:48:49 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2012-06-27 02:42:05 -0400 |
commit | 643b39b031f546c7c3c60ef360b8260aa2b32762 (patch) | |
tree | 71658c6a049937d65b48ebe7bc9a159eb655885a | |
parent | b0e09bae37eeacb213d9baf8fcb4d48934a4ada5 (diff) |
crypto: caam - chaining support
support chained scatterlists for aead, ablkcipher and ahash.
Signed-off-by: Yuan Kang <Yuan.Kang@freescale.com>
- fix dma unmap leak
- un-unlikely src == dst, due to experience with AF_ALG
Signed-off-by: Kudupudi Ugendreshwar <B38865@freescale.com>
Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r-- | drivers/crypto/caam/caamalg.c | 114 | ||||
-rw-r--r-- | drivers/crypto/caam/caamhash.c | 53 | ||||
-rw-r--r-- | drivers/crypto/caam/sg_sw_sec4.h | 44 |
3 files changed, 147 insertions, 64 deletions
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c index 5ab480a12b51..0c1ea8492eff 100644 --- a/drivers/crypto/caam/caamalg.c +++ b/drivers/crypto/caam/caamalg.c | |||
@@ -654,8 +654,11 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher, | |||
654 | /* | 654 | /* |
655 | * aead_edesc - s/w-extended aead descriptor | 655 | * aead_edesc - s/w-extended aead descriptor |
656 | * @assoc_nents: number of segments in associated data (SPI+Seq) scatterlist | 656 | * @assoc_nents: number of segments in associated data (SPI+Seq) scatterlist |
657 | * @assoc_chained: if source is chained | ||
657 | * @src_nents: number of segments in input scatterlist | 658 | * @src_nents: number of segments in input scatterlist |
659 | * @src_chained: if source is chained | ||
658 | * @dst_nents: number of segments in output scatterlist | 660 | * @dst_nents: number of segments in output scatterlist |
661 | * @dst_chained: if destination is chained | ||
659 | * @iv_dma: dma address of iv for checking continuity and link table | 662 | * @iv_dma: dma address of iv for checking continuity and link table |
660 | * @desc: h/w descriptor (variable length; must not exceed MAX_CAAM_DESCSIZE) | 663 | * @desc: h/w descriptor (variable length; must not exceed MAX_CAAM_DESCSIZE) |
661 | * @sec4_sg_bytes: length of dma mapped sec4_sg space | 664 | * @sec4_sg_bytes: length of dma mapped sec4_sg space |
@@ -664,8 +667,11 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher, | |||
664 | */ | 667 | */ |
665 | struct aead_edesc { | 668 | struct aead_edesc { |
666 | int assoc_nents; | 669 | int assoc_nents; |
670 | bool assoc_chained; | ||
667 | int src_nents; | 671 | int src_nents; |
672 | bool src_chained; | ||
668 | int dst_nents; | 673 | int dst_nents; |
674 | bool dst_chained; | ||
669 | dma_addr_t iv_dma; | 675 | dma_addr_t iv_dma; |
670 | int sec4_sg_bytes; | 676 | int sec4_sg_bytes; |
671 | dma_addr_t sec4_sg_dma; | 677 | dma_addr_t sec4_sg_dma; |
@@ -676,7 +682,9 @@ struct aead_edesc { | |||
676 | /* | 682 | /* |
677 | * ablkcipher_edesc - s/w-extended ablkcipher descriptor | 683 | * ablkcipher_edesc - s/w-extended ablkcipher descriptor |
678 | * @src_nents: number of segments in input scatterlist | 684 | * @src_nents: number of segments in input scatterlist |
685 | * @src_chained: if source is chained | ||
679 | * @dst_nents: number of segments in output scatterlist | 686 | * @dst_nents: number of segments in output scatterlist |
687 | * @dst_chained: if destination is chained | ||
680 | * @iv_dma: dma address of iv for checking continuity and link table | 688 | * @iv_dma: dma address of iv for checking continuity and link table |
681 | * @desc: h/w descriptor (variable length; must not exceed MAX_CAAM_DESCSIZE) | 689 | * @desc: h/w descriptor (variable length; must not exceed MAX_CAAM_DESCSIZE) |
682 | * @sec4_sg_bytes: length of dma mapped sec4_sg space | 690 | * @sec4_sg_bytes: length of dma mapped sec4_sg space |
@@ -685,7 +693,9 @@ struct aead_edesc { | |||
685 | */ | 693 | */ |
686 | struct ablkcipher_edesc { | 694 | struct ablkcipher_edesc { |
687 | int src_nents; | 695 | int src_nents; |
696 | bool src_chained; | ||
688 | int dst_nents; | 697 | int dst_nents; |
698 | bool dst_chained; | ||
689 | dma_addr_t iv_dma; | 699 | dma_addr_t iv_dma; |
690 | int sec4_sg_bytes; | 700 | int sec4_sg_bytes; |
691 | dma_addr_t sec4_sg_dma; | 701 | dma_addr_t sec4_sg_dma; |
@@ -694,15 +704,19 @@ struct ablkcipher_edesc { | |||
694 | }; | 704 | }; |
695 | 705 | ||
696 | static void caam_unmap(struct device *dev, struct scatterlist *src, | 706 | static void caam_unmap(struct device *dev, struct scatterlist *src, |
697 | struct scatterlist *dst, int src_nents, int dst_nents, | 707 | struct scatterlist *dst, int src_nents, |
708 | bool src_chained, int dst_nents, bool dst_chained, | ||
698 | dma_addr_t iv_dma, int ivsize, dma_addr_t sec4_sg_dma, | 709 | dma_addr_t iv_dma, int ivsize, dma_addr_t sec4_sg_dma, |
699 | int sec4_sg_bytes) | 710 | int sec4_sg_bytes) |
700 | { | 711 | { |
701 | if (unlikely(dst != src)) { | 712 | if (dst != src) { |
702 | dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE); | 713 | dma_unmap_sg_chained(dev, src, src_nents ? : 1, DMA_TO_DEVICE, |
703 | dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE); | 714 | src_chained); |
715 | dma_unmap_sg_chained(dev, dst, dst_nents ? : 1, DMA_FROM_DEVICE, | ||
716 | dst_chained); | ||
704 | } else { | 717 | } else { |
705 | dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL); | 718 | dma_unmap_sg_chained(dev, src, src_nents ? : 1, |
719 | DMA_BIDIRECTIONAL, src_chained); | ||
706 | } | 720 | } |
707 | 721 | ||
708 | if (iv_dma) | 722 | if (iv_dma) |
@@ -719,12 +733,13 @@ static void aead_unmap(struct device *dev, | |||
719 | struct crypto_aead *aead = crypto_aead_reqtfm(req); | 733 | struct crypto_aead *aead = crypto_aead_reqtfm(req); |
720 | int ivsize = crypto_aead_ivsize(aead); | 734 | int ivsize = crypto_aead_ivsize(aead); |
721 | 735 | ||
722 | dma_unmap_sg(dev, req->assoc, edesc->assoc_nents, DMA_TO_DEVICE); | 736 | dma_unmap_sg_chained(dev, req->assoc, edesc->assoc_nents, |
737 | DMA_TO_DEVICE, edesc->assoc_chained); | ||
723 | 738 | ||
724 | caam_unmap(dev, req->src, req->dst, | 739 | caam_unmap(dev, req->src, req->dst, |
725 | edesc->src_nents, edesc->dst_nents, | 740 | edesc->src_nents, edesc->src_chained, edesc->dst_nents, |
726 | edesc->iv_dma, ivsize, edesc->sec4_sg_dma, | 741 | edesc->dst_chained, edesc->iv_dma, ivsize, |
727 | edesc->sec4_sg_bytes); | 742 | edesc->sec4_sg_dma, edesc->sec4_sg_bytes); |
728 | } | 743 | } |
729 | 744 | ||
730 | static void ablkcipher_unmap(struct device *dev, | 745 | static void ablkcipher_unmap(struct device *dev, |
@@ -735,9 +750,9 @@ static void ablkcipher_unmap(struct device *dev, | |||
735 | int ivsize = crypto_ablkcipher_ivsize(ablkcipher); | 750 | int ivsize = crypto_ablkcipher_ivsize(ablkcipher); |
736 | 751 | ||
737 | caam_unmap(dev, req->src, req->dst, | 752 | caam_unmap(dev, req->src, req->dst, |
738 | edesc->src_nents, edesc->dst_nents, | 753 | edesc->src_nents, edesc->src_chained, edesc->dst_nents, |
739 | edesc->iv_dma, ivsize, edesc->sec4_sg_dma, | 754 | edesc->dst_chained, edesc->iv_dma, ivsize, |
740 | edesc->sec4_sg_bytes); | 755 | edesc->sec4_sg_dma, edesc->sec4_sg_bytes); |
741 | } | 756 | } |
742 | 757 | ||
743 | static void aead_encrypt_done(struct device *jrdev, u32 *desc, u32 err, | 758 | static void aead_encrypt_done(struct device *jrdev, u32 *desc, u32 err, |
@@ -1128,25 +1143,26 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req, | |||
1128 | dma_addr_t iv_dma = 0; | 1143 | dma_addr_t iv_dma = 0; |
1129 | int sgc; | 1144 | int sgc; |
1130 | bool all_contig = true; | 1145 | bool all_contig = true; |
1146 | bool assoc_chained = false, src_chained = false, dst_chained = false; | ||
1131 | int ivsize = crypto_aead_ivsize(aead); | 1147 | int ivsize = crypto_aead_ivsize(aead); |
1132 | int sec4_sg_index, sec4_sg_len = 0, sec4_sg_bytes; | 1148 | int sec4_sg_index, sec4_sg_len = 0, sec4_sg_bytes; |
1133 | 1149 | ||
1134 | assoc_nents = sg_count(req->assoc, req->assoclen); | 1150 | assoc_nents = sg_count(req->assoc, req->assoclen, &assoc_chained); |
1135 | src_nents = sg_count(req->src, req->cryptlen); | 1151 | src_nents = sg_count(req->src, req->cryptlen, &src_chained); |
1136 | 1152 | ||
1137 | if (unlikely(req->dst != req->src)) | 1153 | if (unlikely(req->dst != req->src)) |
1138 | dst_nents = sg_count(req->dst, req->cryptlen); | 1154 | dst_nents = sg_count(req->dst, req->cryptlen, &dst_chained); |
1139 | 1155 | ||
1140 | sgc = dma_map_sg(jrdev, req->assoc, assoc_nents ? : 1, | 1156 | sgc = dma_map_sg_chained(jrdev, req->assoc, assoc_nents ? : 1, |
1141 | DMA_BIDIRECTIONAL); | 1157 | DMA_BIDIRECTIONAL, assoc_chained); |
1142 | if (likely(req->src == req->dst)) { | 1158 | if (likely(req->src == req->dst)) { |
1143 | sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1, | 1159 | sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1, |
1144 | DMA_BIDIRECTIONAL); | 1160 | DMA_BIDIRECTIONAL, src_chained); |
1145 | } else { | 1161 | } else { |
1146 | sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1, | 1162 | sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1, |
1147 | DMA_TO_DEVICE); | 1163 | DMA_TO_DEVICE, src_chained); |
1148 | sgc = dma_map_sg(jrdev, req->dst, dst_nents ? : 1, | 1164 | sgc = dma_map_sg_chained(jrdev, req->dst, dst_nents ? : 1, |
1149 | DMA_FROM_DEVICE); | 1165 | DMA_FROM_DEVICE, dst_chained); |
1150 | } | 1166 | } |
1151 | 1167 | ||
1152 | /* Check if data are contiguous */ | 1168 | /* Check if data are contiguous */ |
@@ -1172,8 +1188,11 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req, | |||
1172 | } | 1188 | } |
1173 | 1189 | ||
1174 | edesc->assoc_nents = assoc_nents; | 1190 | edesc->assoc_nents = assoc_nents; |
1191 | edesc->assoc_chained = assoc_chained; | ||
1175 | edesc->src_nents = src_nents; | 1192 | edesc->src_nents = src_nents; |
1193 | edesc->src_chained = src_chained; | ||
1176 | edesc->dst_nents = dst_nents; | 1194 | edesc->dst_nents = dst_nents; |
1195 | edesc->dst_chained = dst_chained; | ||
1177 | edesc->iv_dma = iv_dma; | 1196 | edesc->iv_dma = iv_dma; |
1178 | edesc->sec4_sg_bytes = sec4_sg_bytes; | 1197 | edesc->sec4_sg_bytes = sec4_sg_bytes; |
1179 | edesc->sec4_sg = (void *)edesc + sizeof(struct aead_edesc) + | 1198 | edesc->sec4_sg = (void *)edesc + sizeof(struct aead_edesc) + |
@@ -1307,24 +1326,25 @@ static struct aead_edesc *aead_giv_edesc_alloc(struct aead_givcrypt_request | |||
1307 | int sgc; | 1326 | int sgc; |
1308 | u32 contig = GIV_SRC_CONTIG | GIV_DST_CONTIG; | 1327 | u32 contig = GIV_SRC_CONTIG | GIV_DST_CONTIG; |
1309 | int ivsize = crypto_aead_ivsize(aead); | 1328 | int ivsize = crypto_aead_ivsize(aead); |
1329 | bool assoc_chained = false, src_chained = false, dst_chained = false; | ||
1310 | int sec4_sg_index, sec4_sg_len = 0, sec4_sg_bytes; | 1330 | int sec4_sg_index, sec4_sg_len = 0, sec4_sg_bytes; |
1311 | 1331 | ||
1312 | assoc_nents = sg_count(req->assoc, req->assoclen); | 1332 | assoc_nents = sg_count(req->assoc, req->assoclen, &assoc_chained); |
1313 | src_nents = sg_count(req->src, req->cryptlen); | 1333 | src_nents = sg_count(req->src, req->cryptlen, &src_chained); |
1314 | 1334 | ||
1315 | if (unlikely(req->dst != req->src)) | 1335 | if (unlikely(req->dst != req->src)) |
1316 | dst_nents = sg_count(req->dst, req->cryptlen); | 1336 | dst_nents = sg_count(req->dst, req->cryptlen, &dst_chained); |
1317 | 1337 | ||
1318 | sgc = dma_map_sg(jrdev, req->assoc, assoc_nents ? : 1, | 1338 | sgc = dma_map_sg_chained(jrdev, req->assoc, assoc_nents ? : 1, |
1319 | DMA_BIDIRECTIONAL); | 1339 | DMA_BIDIRECTIONAL, assoc_chained); |
1320 | if (likely(req->src == req->dst)) { | 1340 | if (likely(req->src == req->dst)) { |
1321 | sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1, | 1341 | sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1, |
1322 | DMA_BIDIRECTIONAL); | 1342 | DMA_BIDIRECTIONAL, src_chained); |
1323 | } else { | 1343 | } else { |
1324 | sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1, | 1344 | sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1, |
1325 | DMA_TO_DEVICE); | 1345 | DMA_TO_DEVICE, src_chained); |
1326 | sgc = dma_map_sg(jrdev, req->dst, dst_nents ? : 1, | 1346 | sgc = dma_map_sg_chained(jrdev, req->dst, dst_nents ? : 1, |
1327 | DMA_FROM_DEVICE); | 1347 | DMA_FROM_DEVICE, dst_chained); |
1328 | } | 1348 | } |
1329 | 1349 | ||
1330 | /* Check if data are contiguous */ | 1350 | /* Check if data are contiguous */ |
@@ -1358,8 +1378,11 @@ static struct aead_edesc *aead_giv_edesc_alloc(struct aead_givcrypt_request | |||
1358 | } | 1378 | } |
1359 | 1379 | ||
1360 | edesc->assoc_nents = assoc_nents; | 1380 | edesc->assoc_nents = assoc_nents; |
1381 | edesc->assoc_chained = assoc_chained; | ||
1361 | edesc->src_nents = src_nents; | 1382 | edesc->src_nents = src_nents; |
1383 | edesc->src_chained = src_chained; | ||
1362 | edesc->dst_nents = dst_nents; | 1384 | edesc->dst_nents = dst_nents; |
1385 | edesc->dst_chained = dst_chained; | ||
1363 | edesc->iv_dma = iv_dma; | 1386 | edesc->iv_dma = iv_dma; |
1364 | edesc->sec4_sg_bytes = sec4_sg_bytes; | 1387 | edesc->sec4_sg_bytes = sec4_sg_bytes; |
1365 | edesc->sec4_sg = (void *)edesc + sizeof(struct aead_edesc) + | 1388 | edesc->sec4_sg = (void *)edesc + sizeof(struct aead_edesc) + |
@@ -1459,21 +1482,22 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request | |||
1459 | bool iv_contig = false; | 1482 | bool iv_contig = false; |
1460 | int sgc; | 1483 | int sgc; |
1461 | int ivsize = crypto_ablkcipher_ivsize(ablkcipher); | 1484 | int ivsize = crypto_ablkcipher_ivsize(ablkcipher); |
1485 | bool src_chained = false, dst_chained = false; | ||
1462 | int sec4_sg_index; | 1486 | int sec4_sg_index; |
1463 | 1487 | ||
1464 | src_nents = sg_count(req->src, req->nbytes); | 1488 | src_nents = sg_count(req->src, req->nbytes, &src_chained); |
1465 | 1489 | ||
1466 | if (unlikely(req->dst != req->src)) | 1490 | if (req->dst != req->src) |
1467 | dst_nents = sg_count(req->dst, req->nbytes); | 1491 | dst_nents = sg_count(req->dst, req->nbytes, &dst_chained); |
1468 | 1492 | ||
1469 | if (likely(req->src == req->dst)) { | 1493 | if (likely(req->src == req->dst)) { |
1470 | sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1, | 1494 | sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1, |
1471 | DMA_BIDIRECTIONAL); | 1495 | DMA_BIDIRECTIONAL, src_chained); |
1472 | } else { | 1496 | } else { |
1473 | sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1, | 1497 | sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1, |
1474 | DMA_TO_DEVICE); | 1498 | DMA_TO_DEVICE, src_chained); |
1475 | sgc = dma_map_sg(jrdev, req->dst, dst_nents ? : 1, | 1499 | sgc = dma_map_sg_chained(jrdev, req->dst, dst_nents ? : 1, |
1476 | DMA_FROM_DEVICE); | 1500 | DMA_FROM_DEVICE, dst_chained); |
1477 | } | 1501 | } |
1478 | 1502 | ||
1479 | /* | 1503 | /* |
@@ -1497,7 +1521,9 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request | |||
1497 | } | 1521 | } |
1498 | 1522 | ||
1499 | edesc->src_nents = src_nents; | 1523 | edesc->src_nents = src_nents; |
1524 | edesc->src_chained = src_chained; | ||
1500 | edesc->dst_nents = dst_nents; | 1525 | edesc->dst_nents = dst_nents; |
1526 | edesc->dst_chained = dst_chained; | ||
1501 | edesc->sec4_sg_bytes = sec4_sg_bytes; | 1527 | edesc->sec4_sg_bytes = sec4_sg_bytes; |
1502 | edesc->sec4_sg = (void *)edesc + sizeof(struct ablkcipher_edesc) + | 1528 | edesc->sec4_sg = (void *)edesc + sizeof(struct ablkcipher_edesc) + |
1503 | desc_bytes; | 1529 | desc_bytes; |
@@ -1510,7 +1536,7 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request | |||
1510 | sec4_sg_index += 1 + src_nents; | 1536 | sec4_sg_index += 1 + src_nents; |
1511 | } | 1537 | } |
1512 | 1538 | ||
1513 | if (unlikely(dst_nents)) { | 1539 | if (dst_nents) { |
1514 | sg_to_sec4_sg_last(req->dst, dst_nents, | 1540 | sg_to_sec4_sg_last(req->dst, dst_nents, |
1515 | edesc->sec4_sg + sec4_sg_index, 0); | 1541 | edesc->sec4_sg + sec4_sg_index, 0); |
1516 | } | 1542 | } |
diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c index 7dcf28f48149..895aaf2bca92 100644 --- a/drivers/crypto/caam/caamhash.c +++ b/drivers/crypto/caam/caamhash.c | |||
@@ -175,9 +175,10 @@ static inline dma_addr_t buf_map_to_sec4_sg(struct device *jrdev, | |||
175 | /* Map req->src and put it in link table */ | 175 | /* Map req->src and put it in link table */ |
176 | static inline void src_map_to_sec4_sg(struct device *jrdev, | 176 | static inline void src_map_to_sec4_sg(struct device *jrdev, |
177 | struct scatterlist *src, int src_nents, | 177 | struct scatterlist *src, int src_nents, |
178 | struct sec4_sg_entry *sec4_sg) | 178 | struct sec4_sg_entry *sec4_sg, |
179 | bool chained) | ||
179 | { | 180 | { |
180 | dma_map_sg(jrdev, src, src_nents, DMA_TO_DEVICE); | 181 | dma_map_sg_chained(jrdev, src, src_nents, DMA_TO_DEVICE, chained); |
181 | sg_to_sec4_sg_last(src, src_nents, sec4_sg, 0); | 182 | sg_to_sec4_sg_last(src, src_nents, sec4_sg, 0); |
182 | } | 183 | } |
183 | 184 | ||
@@ -563,6 +564,7 @@ badkey: | |||
563 | * ahash_edesc - s/w-extended ahash descriptor | 564 | * ahash_edesc - s/w-extended ahash descriptor |
564 | * @dst_dma: physical mapped address of req->result | 565 | * @dst_dma: physical mapped address of req->result |
565 | * @sec4_sg_dma: physical mapped address of h/w link table | 566 | * @sec4_sg_dma: physical mapped address of h/w link table |
567 | * @chained: if source is chained | ||
566 | * @src_nents: number of segments in input scatterlist | 568 | * @src_nents: number of segments in input scatterlist |
567 | * @sec4_sg_bytes: length of dma mapped sec4_sg space | 569 | * @sec4_sg_bytes: length of dma mapped sec4_sg space |
568 | * @sec4_sg: pointer to h/w link table | 570 | * @sec4_sg: pointer to h/w link table |
@@ -571,6 +573,7 @@ badkey: | |||
571 | struct ahash_edesc { | 573 | struct ahash_edesc { |
572 | dma_addr_t dst_dma; | 574 | dma_addr_t dst_dma; |
573 | dma_addr_t sec4_sg_dma; | 575 | dma_addr_t sec4_sg_dma; |
576 | bool chained; | ||
574 | int src_nents; | 577 | int src_nents; |
575 | int sec4_sg_bytes; | 578 | int sec4_sg_bytes; |
576 | struct sec4_sg_entry *sec4_sg; | 579 | struct sec4_sg_entry *sec4_sg; |
@@ -582,7 +585,8 @@ static inline void ahash_unmap(struct device *dev, | |||
582 | struct ahash_request *req, int dst_len) | 585 | struct ahash_request *req, int dst_len) |
583 | { | 586 | { |
584 | if (edesc->src_nents) | 587 | if (edesc->src_nents) |
585 | dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE); | 588 | dma_unmap_sg_chained(dev, req->src, edesc->src_nents, |
589 | DMA_TO_DEVICE, edesc->chained); | ||
586 | if (edesc->dst_dma) | 590 | if (edesc->dst_dma) |
587 | dma_unmap_single(dev, edesc->dst_dma, dst_len, DMA_FROM_DEVICE); | 591 | dma_unmap_single(dev, edesc->dst_dma, dst_len, DMA_FROM_DEVICE); |
588 | 592 | ||
@@ -775,6 +779,7 @@ static int ahash_update_ctx(struct ahash_request *req) | |||
775 | dma_addr_t ptr = ctx->sh_desc_update_dma; | 779 | dma_addr_t ptr = ctx->sh_desc_update_dma; |
776 | int src_nents, sec4_sg_bytes, sec4_sg_src_index; | 780 | int src_nents, sec4_sg_bytes, sec4_sg_src_index; |
777 | struct ahash_edesc *edesc; | 781 | struct ahash_edesc *edesc; |
782 | bool chained = false; | ||
778 | int ret = 0; | 783 | int ret = 0; |
779 | int sh_len; | 784 | int sh_len; |
780 | 785 | ||
@@ -783,7 +788,8 @@ static int ahash_update_ctx(struct ahash_request *req) | |||
783 | to_hash = in_len - *next_buflen; | 788 | to_hash = in_len - *next_buflen; |
784 | 789 | ||
785 | if (to_hash) { | 790 | if (to_hash) { |
786 | src_nents = __sg_count(req->src, req->nbytes - (*next_buflen)); | 791 | src_nents = __sg_count(req->src, req->nbytes - (*next_buflen), |
792 | &chained); | ||
787 | sec4_sg_src_index = 1 + (*buflen ? 1 : 0); | 793 | sec4_sg_src_index = 1 + (*buflen ? 1 : 0); |
788 | sec4_sg_bytes = (sec4_sg_src_index + src_nents) * | 794 | sec4_sg_bytes = (sec4_sg_src_index + src_nents) * |
789 | sizeof(struct sec4_sg_entry); | 795 | sizeof(struct sec4_sg_entry); |
@@ -801,6 +807,7 @@ static int ahash_update_ctx(struct ahash_request *req) | |||
801 | } | 807 | } |
802 | 808 | ||
803 | edesc->src_nents = src_nents; | 809 | edesc->src_nents = src_nents; |
810 | edesc->chained = chained; | ||
804 | edesc->sec4_sg_bytes = sec4_sg_bytes; | 811 | edesc->sec4_sg_bytes = sec4_sg_bytes; |
805 | edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) + | 812 | edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) + |
806 | DESC_JOB_IO_LEN; | 813 | DESC_JOB_IO_LEN; |
@@ -818,7 +825,8 @@ static int ahash_update_ctx(struct ahash_request *req) | |||
818 | 825 | ||
819 | if (src_nents) { | 826 | if (src_nents) { |
820 | src_map_to_sec4_sg(jrdev, req->src, src_nents, | 827 | src_map_to_sec4_sg(jrdev, req->src, src_nents, |
821 | edesc->sec4_sg + sec4_sg_src_index); | 828 | edesc->sec4_sg + sec4_sg_src_index, |
829 | chained); | ||
822 | if (*next_buflen) { | 830 | if (*next_buflen) { |
823 | sg_copy_part(next_buf, req->src, to_hash - | 831 | sg_copy_part(next_buf, req->src, to_hash - |
824 | *buflen, req->nbytes); | 832 | *buflen, req->nbytes); |
@@ -958,10 +966,11 @@ static int ahash_finup_ctx(struct ahash_request *req) | |||
958 | int src_nents; | 966 | int src_nents; |
959 | int digestsize = crypto_ahash_digestsize(ahash); | 967 | int digestsize = crypto_ahash_digestsize(ahash); |
960 | struct ahash_edesc *edesc; | 968 | struct ahash_edesc *edesc; |
969 | bool chained = false; | ||
961 | int ret = 0; | 970 | int ret = 0; |
962 | int sh_len; | 971 | int sh_len; |
963 | 972 | ||
964 | src_nents = __sg_count(req->src, req->nbytes); | 973 | src_nents = __sg_count(req->src, req->nbytes, &chained); |
965 | sec4_sg_src_index = 1 + (buflen ? 1 : 0); | 974 | sec4_sg_src_index = 1 + (buflen ? 1 : 0); |
966 | sec4_sg_bytes = (sec4_sg_src_index + src_nents) * | 975 | sec4_sg_bytes = (sec4_sg_src_index + src_nents) * |
967 | sizeof(struct sec4_sg_entry); | 976 | sizeof(struct sec4_sg_entry); |
@@ -979,6 +988,7 @@ static int ahash_finup_ctx(struct ahash_request *req) | |||
979 | init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER | HDR_REVERSE); | 988 | init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER | HDR_REVERSE); |
980 | 989 | ||
981 | edesc->src_nents = src_nents; | 990 | edesc->src_nents = src_nents; |
991 | edesc->chained = chained; | ||
982 | edesc->sec4_sg_bytes = sec4_sg_bytes; | 992 | edesc->sec4_sg_bytes = sec4_sg_bytes; |
983 | edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) + | 993 | edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) + |
984 | DESC_JOB_IO_LEN; | 994 | DESC_JOB_IO_LEN; |
@@ -993,7 +1003,7 @@ static int ahash_finup_ctx(struct ahash_request *req) | |||
993 | last_buflen); | 1003 | last_buflen); |
994 | 1004 | ||
995 | src_map_to_sec4_sg(jrdev, req->src, src_nents, edesc->sec4_sg + | 1005 | src_map_to_sec4_sg(jrdev, req->src, src_nents, edesc->sec4_sg + |
996 | sec4_sg_src_index); | 1006 | sec4_sg_src_index, chained); |
997 | 1007 | ||
998 | append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len + | 1008 | append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len + |
999 | buflen + req->nbytes, LDST_SGF); | 1009 | buflen + req->nbytes, LDST_SGF); |
@@ -1030,12 +1040,14 @@ static int ahash_digest(struct ahash_request *req) | |||
1030 | int src_nents, sec4_sg_bytes; | 1040 | int src_nents, sec4_sg_bytes; |
1031 | dma_addr_t src_dma; | 1041 | dma_addr_t src_dma; |
1032 | struct ahash_edesc *edesc; | 1042 | struct ahash_edesc *edesc; |
1043 | bool chained = false; | ||
1033 | int ret = 0; | 1044 | int ret = 0; |
1034 | u32 options; | 1045 | u32 options; |
1035 | int sh_len; | 1046 | int sh_len; |
1036 | 1047 | ||
1037 | src_nents = sg_count(req->src, req->nbytes); | 1048 | src_nents = sg_count(req->src, req->nbytes, &chained); |
1038 | dma_map_sg(jrdev, req->src, src_nents ? : 1, DMA_TO_DEVICE); | 1049 | dma_map_sg_chained(jrdev, req->src, src_nents ? : 1, DMA_TO_DEVICE, |
1050 | chained); | ||
1039 | sec4_sg_bytes = src_nents * sizeof(struct sec4_sg_entry); | 1051 | sec4_sg_bytes = src_nents * sizeof(struct sec4_sg_entry); |
1040 | 1052 | ||
1041 | /* allocate space for base edesc and hw desc commands, link tables */ | 1053 | /* allocate space for base edesc and hw desc commands, link tables */ |
@@ -1050,6 +1062,7 @@ static int ahash_digest(struct ahash_request *req) | |||
1050 | edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg, | 1062 | edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg, |
1051 | sec4_sg_bytes, DMA_TO_DEVICE); | 1063 | sec4_sg_bytes, DMA_TO_DEVICE); |
1052 | edesc->src_nents = src_nents; | 1064 | edesc->src_nents = src_nents; |
1065 | edesc->chained = chained; | ||
1053 | 1066 | ||
1054 | sh_len = desc_len(sh_desc); | 1067 | sh_len = desc_len(sh_desc); |
1055 | desc = edesc->hw_desc; | 1068 | desc = edesc->hw_desc; |
@@ -1157,6 +1170,7 @@ static int ahash_update_no_ctx(struct ahash_request *req) | |||
1157 | struct ahash_edesc *edesc; | 1170 | struct ahash_edesc *edesc; |
1158 | u32 *desc, *sh_desc = ctx->sh_desc_update_first; | 1171 | u32 *desc, *sh_desc = ctx->sh_desc_update_first; |
1159 | dma_addr_t ptr = ctx->sh_desc_update_first_dma; | 1172 | dma_addr_t ptr = ctx->sh_desc_update_first_dma; |
1173 | bool chained = false; | ||
1160 | int ret = 0; | 1174 | int ret = 0; |
1161 | int sh_len; | 1175 | int sh_len; |
1162 | 1176 | ||
@@ -1164,7 +1178,8 @@ static int ahash_update_no_ctx(struct ahash_request *req) | |||
1164 | to_hash = in_len - *next_buflen; | 1178 | to_hash = in_len - *next_buflen; |
1165 | 1179 | ||
1166 | if (to_hash) { | 1180 | if (to_hash) { |
1167 | src_nents = __sg_count(req->src, req->nbytes - (*next_buflen)); | 1181 | src_nents = __sg_count(req->src, req->nbytes - (*next_buflen), |
1182 | &chained); | ||
1168 | sec4_sg_bytes = (1 + src_nents) * | 1183 | sec4_sg_bytes = (1 + src_nents) * |
1169 | sizeof(struct sec4_sg_entry); | 1184 | sizeof(struct sec4_sg_entry); |
1170 | 1185 | ||
@@ -1181,6 +1196,7 @@ static int ahash_update_no_ctx(struct ahash_request *req) | |||
1181 | } | 1196 | } |
1182 | 1197 | ||
1183 | edesc->src_nents = src_nents; | 1198 | edesc->src_nents = src_nents; |
1199 | edesc->chained = chained; | ||
1184 | edesc->sec4_sg_bytes = sec4_sg_bytes; | 1200 | edesc->sec4_sg_bytes = sec4_sg_bytes; |
1185 | edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) + | 1201 | edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) + |
1186 | DESC_JOB_IO_LEN; | 1202 | DESC_JOB_IO_LEN; |
@@ -1191,7 +1207,7 @@ static int ahash_update_no_ctx(struct ahash_request *req) | |||
1191 | state->buf_dma = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg, | 1207 | state->buf_dma = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg, |
1192 | buf, *buflen); | 1208 | buf, *buflen); |
1193 | src_map_to_sec4_sg(jrdev, req->src, src_nents, | 1209 | src_map_to_sec4_sg(jrdev, req->src, src_nents, |
1194 | edesc->sec4_sg + 1); | 1210 | edesc->sec4_sg + 1, chained); |
1195 | if (*next_buflen) { | 1211 | if (*next_buflen) { |
1196 | sg_copy_part(next_buf, req->src, to_hash - *buflen, | 1212 | sg_copy_part(next_buf, req->src, to_hash - *buflen, |
1197 | req->nbytes); | 1213 | req->nbytes); |
@@ -1258,10 +1274,11 @@ static int ahash_finup_no_ctx(struct ahash_request *req) | |||
1258 | int sec4_sg_bytes, sec4_sg_src_index, src_nents; | 1274 | int sec4_sg_bytes, sec4_sg_src_index, src_nents; |
1259 | int digestsize = crypto_ahash_digestsize(ahash); | 1275 | int digestsize = crypto_ahash_digestsize(ahash); |
1260 | struct ahash_edesc *edesc; | 1276 | struct ahash_edesc *edesc; |
1277 | bool chained = false; | ||
1261 | int sh_len; | 1278 | int sh_len; |
1262 | int ret = 0; | 1279 | int ret = 0; |
1263 | 1280 | ||
1264 | src_nents = __sg_count(req->src, req->nbytes); | 1281 | src_nents = __sg_count(req->src, req->nbytes, &chained); |
1265 | sec4_sg_src_index = 2; | 1282 | sec4_sg_src_index = 2; |
1266 | sec4_sg_bytes = (sec4_sg_src_index + src_nents) * | 1283 | sec4_sg_bytes = (sec4_sg_src_index + src_nents) * |
1267 | sizeof(struct sec4_sg_entry); | 1284 | sizeof(struct sec4_sg_entry); |
@@ -1279,6 +1296,7 @@ static int ahash_finup_no_ctx(struct ahash_request *req) | |||
1279 | init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER | HDR_REVERSE); | 1296 | init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER | HDR_REVERSE); |
1280 | 1297 | ||
1281 | edesc->src_nents = src_nents; | 1298 | edesc->src_nents = src_nents; |
1299 | edesc->chained = chained; | ||
1282 | edesc->sec4_sg_bytes = sec4_sg_bytes; | 1300 | edesc->sec4_sg_bytes = sec4_sg_bytes; |
1283 | edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) + | 1301 | edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) + |
1284 | DESC_JOB_IO_LEN; | 1302 | DESC_JOB_IO_LEN; |
@@ -1289,7 +1307,8 @@ static int ahash_finup_no_ctx(struct ahash_request *req) | |||
1289 | state->buf_dma, buflen, | 1307 | state->buf_dma, buflen, |
1290 | last_buflen); | 1308 | last_buflen); |
1291 | 1309 | ||
1292 | src_map_to_sec4_sg(jrdev, req->src, src_nents, edesc->sec4_sg + 1); | 1310 | src_map_to_sec4_sg(jrdev, req->src, src_nents, edesc->sec4_sg + 1, |
1311 | chained); | ||
1293 | 1312 | ||
1294 | append_seq_in_ptr(desc, edesc->sec4_sg_dma, buflen + | 1313 | append_seq_in_ptr(desc, edesc->sec4_sg_dma, buflen + |
1295 | req->nbytes, LDST_SGF); | 1314 | req->nbytes, LDST_SGF); |
@@ -1332,6 +1351,7 @@ static int ahash_update_first(struct ahash_request *req) | |||
1332 | dma_addr_t src_dma; | 1351 | dma_addr_t src_dma; |
1333 | u32 options; | 1352 | u32 options; |
1334 | struct ahash_edesc *edesc; | 1353 | struct ahash_edesc *edesc; |
1354 | bool chained = false; | ||
1335 | int ret = 0; | 1355 | int ret = 0; |
1336 | int sh_len; | 1356 | int sh_len; |
1337 | 1357 | ||
@@ -1340,8 +1360,10 @@ static int ahash_update_first(struct ahash_request *req) | |||
1340 | to_hash = req->nbytes - *next_buflen; | 1360 | to_hash = req->nbytes - *next_buflen; |
1341 | 1361 | ||
1342 | if (to_hash) { | 1362 | if (to_hash) { |
1343 | src_nents = sg_count(req->src, req->nbytes - (*next_buflen)); | 1363 | src_nents = sg_count(req->src, req->nbytes - (*next_buflen), |
1344 | dma_map_sg(jrdev, req->src, src_nents ? : 1, DMA_TO_DEVICE); | 1364 | &chained); |
1365 | dma_map_sg_chained(jrdev, req->src, src_nents ? : 1, | ||
1366 | DMA_TO_DEVICE, chained); | ||
1345 | sec4_sg_bytes = src_nents * sizeof(struct sec4_sg_entry); | 1367 | sec4_sg_bytes = src_nents * sizeof(struct sec4_sg_entry); |
1346 | 1368 | ||
1347 | /* | 1369 | /* |
@@ -1357,6 +1379,7 @@ static int ahash_update_first(struct ahash_request *req) | |||
1357 | } | 1379 | } |
1358 | 1380 | ||
1359 | edesc->src_nents = src_nents; | 1381 | edesc->src_nents = src_nents; |
1382 | edesc->chained = chained; | ||
1360 | edesc->sec4_sg_bytes = sec4_sg_bytes; | 1383 | edesc->sec4_sg_bytes = sec4_sg_bytes; |
1361 | edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) + | 1384 | edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) + |
1362 | DESC_JOB_IO_LEN; | 1385 | DESC_JOB_IO_LEN; |
diff --git a/drivers/crypto/caam/sg_sw_sec4.h b/drivers/crypto/caam/sg_sw_sec4.h index 2dda9e3a5e67..e0037c8ee243 100644 --- a/drivers/crypto/caam/sg_sw_sec4.h +++ b/drivers/crypto/caam/sg_sw_sec4.h | |||
@@ -37,7 +37,7 @@ sg_to_sec4_sg(struct scatterlist *sg, int sg_count, | |||
37 | dma_to_sec4_sg_one(sec4_sg_ptr, sg_dma_address(sg), | 37 | dma_to_sec4_sg_one(sec4_sg_ptr, sg_dma_address(sg), |
38 | sg_dma_len(sg), offset); | 38 | sg_dma_len(sg), offset); |
39 | sec4_sg_ptr++; | 39 | sec4_sg_ptr++; |
40 | sg = sg_next(sg); | 40 | sg = scatterwalk_sg_next(sg); |
41 | sg_count--; | 41 | sg_count--; |
42 | } | 42 | } |
43 | return sec4_sg_ptr - 1; | 43 | return sec4_sg_ptr - 1; |
@@ -56,7 +56,8 @@ static inline void sg_to_sec4_sg_last(struct scatterlist *sg, int sg_count, | |||
56 | } | 56 | } |
57 | 57 | ||
58 | /* count number of elements in scatterlist */ | 58 | /* count number of elements in scatterlist */ |
59 | static inline int __sg_count(struct scatterlist *sg_list, int nbytes) | 59 | static inline int __sg_count(struct scatterlist *sg_list, int nbytes, |
60 | bool *chained) | ||
60 | { | 61 | { |
61 | struct scatterlist *sg = sg_list; | 62 | struct scatterlist *sg = sg_list; |
62 | int sg_nents = 0; | 63 | int sg_nents = 0; |
@@ -65,7 +66,7 @@ static inline int __sg_count(struct scatterlist *sg_list, int nbytes) | |||
65 | sg_nents++; | 66 | sg_nents++; |
66 | nbytes -= sg->length; | 67 | nbytes -= sg->length; |
67 | if (!sg_is_last(sg) && (sg + 1)->length == 0) | 68 | if (!sg_is_last(sg) && (sg + 1)->length == 0) |
68 | BUG(); /* Not support chaining */ | 69 | *chained = true; |
69 | sg = scatterwalk_sg_next(sg); | 70 | sg = scatterwalk_sg_next(sg); |
70 | } | 71 | } |
71 | 72 | ||
@@ -73,9 +74,10 @@ static inline int __sg_count(struct scatterlist *sg_list, int nbytes) | |||
73 | } | 74 | } |
74 | 75 | ||
75 | /* derive number of elements in scatterlist, but return 0 for 1 */ | 76 | /* derive number of elements in scatterlist, but return 0 for 1 */ |
76 | static inline int sg_count(struct scatterlist *sg_list, int nbytes) | 77 | static inline int sg_count(struct scatterlist *sg_list, int nbytes, |
78 | bool *chained) | ||
77 | { | 79 | { |
78 | int sg_nents = __sg_count(sg_list, nbytes); | 80 | int sg_nents = __sg_count(sg_list, nbytes, chained); |
79 | 81 | ||
80 | if (likely(sg_nents == 1)) | 82 | if (likely(sg_nents == 1)) |
81 | return 0; | 83 | return 0; |
@@ -83,6 +85,38 @@ static inline int sg_count(struct scatterlist *sg_list, int nbytes) | |||
83 | return sg_nents; | 85 | return sg_nents; |
84 | } | 86 | } |
85 | 87 | ||
88 | static int dma_map_sg_chained(struct device *dev, struct scatterlist *sg, | ||
89 | unsigned int nents, enum dma_data_direction dir, | ||
90 | bool chained) | ||
91 | { | ||
92 | if (unlikely(chained)) { | ||
93 | int i; | ||
94 | for (i = 0; i < nents; i++) { | ||
95 | dma_map_sg(dev, sg, 1, dir); | ||
96 | sg = scatterwalk_sg_next(sg); | ||
97 | } | ||
98 | } else { | ||
99 | dma_map_sg(dev, sg, nents, dir); | ||
100 | } | ||
101 | return nents; | ||
102 | } | ||
103 | |||
104 | static int dma_unmap_sg_chained(struct device *dev, struct scatterlist *sg, | ||
105 | unsigned int nents, enum dma_data_direction dir, | ||
106 | bool chained) | ||
107 | { | ||
108 | if (unlikely(chained)) { | ||
109 | int i; | ||
110 | for (i = 0; i < nents; i++) { | ||
111 | dma_unmap_sg(dev, sg, 1, dir); | ||
112 | sg = scatterwalk_sg_next(sg); | ||
113 | } | ||
114 | } else { | ||
115 | dma_unmap_sg(dev, sg, nents, dir); | ||
116 | } | ||
117 | return nents; | ||
118 | } | ||
119 | |||
86 | /* Copy from len bytes of sg to dest, starting from beginning */ | 120 | /* Copy from len bytes of sg to dest, starting from beginning */ |
87 | static inline void sg_copy(u8 *dest, struct scatterlist *sg, unsigned int len) | 121 | static inline void sg_copy(u8 *dest, struct scatterlist *sg, unsigned int len) |
88 | { | 122 | { |