aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/crypto
diff options
context:
space:
mode:
authorLee Nipper <lee.nipper@freescale.com>2008-07-30 04:26:57 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2008-08-13 06:08:33 -0400
commitf3c85bc1bc72b4cc8d58664a490a9d42bdb6565a (patch)
treee3582146af658bd9828b137013615b86199fbbd6 /drivers/crypto
parentb0e0c9e7f6d5764633e93944dafd896dd6097318 (diff)
crypto: talitos - Add handling for SEC 3.x treatment of link table
Later SEC revision requires the link table (used for scatter/gather) to have an extra entry to account for the total length in descriptor [4], which contains cipher Input and ICV. This only applies to decrypt, not encrypt. Without this change, on 837x, a gather return/length error results when a decryption uses a link table to gather the fragments. This is observed by doing a ping with size of 1447 or larger with AES, or a ping with size 1455 or larger with 3des. So, add check for SEC compatible "fsl,3.0" for using extra link table entry. Signed-off-by: Lee Nipper <lee.nipper@freescale.com> Signed-off-by: Kim Phillips <kim.phillips@freescale.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto')
-rw-r--r--drivers/crypto/talitos.c54
1 files changed, 39 insertions, 15 deletions
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index 681c15f42083..ee827a7f7c6a 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -96,6 +96,9 @@ struct talitos_private {
96 unsigned int exec_units; 96 unsigned int exec_units;
97 unsigned int desc_types; 97 unsigned int desc_types;
98 98
99 /* SEC Compatibility info */
100 unsigned long features;
101
99 /* next channel to be assigned next incoming descriptor */ 102 /* next channel to be assigned next incoming descriptor */
100 atomic_t last_chan; 103 atomic_t last_chan;
101 104
@@ -133,6 +136,9 @@ struct talitos_private {
133 struct hwrng rng; 136 struct hwrng rng;
134}; 137};
135 138
139/* .features flag */
140#define TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT 0x00000001
141
136/* 142/*
137 * map virtual single (contiguous) pointer to h/w descriptor pointer 143 * map virtual single (contiguous) pointer to h/w descriptor pointer
138 */ 144 */
@@ -785,7 +791,7 @@ static void ipsec_esp_encrypt_done(struct device *dev,
785 /* copy the generated ICV to dst */ 791 /* copy the generated ICV to dst */
786 if (edesc->dma_len) { 792 if (edesc->dma_len) {
787 icvdata = &edesc->link_tbl[edesc->src_nents + 793 icvdata = &edesc->link_tbl[edesc->src_nents +
788 edesc->dst_nents + 1]; 794 edesc->dst_nents + 2];
789 sg = sg_last(areq->dst, edesc->dst_nents); 795 sg = sg_last(areq->dst, edesc->dst_nents);
790 memcpy((char *)sg_virt(sg) + sg->length - ctx->authsize, 796 memcpy((char *)sg_virt(sg) + sg->length - ctx->authsize,
791 icvdata, ctx->authsize); 797 icvdata, ctx->authsize);
@@ -814,7 +820,7 @@ static void ipsec_esp_decrypt_done(struct device *dev,
814 /* auth check */ 820 /* auth check */
815 if (edesc->dma_len) 821 if (edesc->dma_len)
816 icvdata = &edesc->link_tbl[edesc->src_nents + 822 icvdata = &edesc->link_tbl[edesc->src_nents +
817 edesc->dst_nents + 1]; 823 edesc->dst_nents + 2];
818 else 824 else
819 icvdata = &edesc->link_tbl[0]; 825 icvdata = &edesc->link_tbl[0];
820 826
@@ -921,10 +927,30 @@ static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq,
921 sg_count = sg_to_link_tbl(areq->src, sg_count, cryptlen, 927 sg_count = sg_to_link_tbl(areq->src, sg_count, cryptlen,
922 &edesc->link_tbl[0]); 928 &edesc->link_tbl[0]);
923 if (sg_count > 1) { 929 if (sg_count > 1) {
930 struct talitos_ptr *link_tbl_ptr =
931 &edesc->link_tbl[sg_count-1];
932 struct scatterlist *sg;
933 struct talitos_private *priv = dev_get_drvdata(dev);
934
924 desc->ptr[4].j_extent |= DESC_PTR_LNKTBL_JUMP; 935 desc->ptr[4].j_extent |= DESC_PTR_LNKTBL_JUMP;
925 desc->ptr[4].ptr = cpu_to_be32(edesc->dma_link_tbl); 936 desc->ptr[4].ptr = cpu_to_be32(edesc->dma_link_tbl);
926 dma_sync_single_for_device(ctx->dev, edesc->dma_link_tbl, 937 dma_sync_single_for_device(ctx->dev, edesc->dma_link_tbl,
927 edesc->dma_len, DMA_BIDIRECTIONAL); 938 edesc->dma_len, DMA_BIDIRECTIONAL);
939 /* If necessary for this SEC revision,
940 * add a link table entry for ICV.
941 */
942 if ((priv->features &
943 TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT) &&
944 (edesc->desc.hdr & DESC_HDR_MODE0_ENCRYPT) == 0) {
945 link_tbl_ptr->j_extent = 0;
946 link_tbl_ptr++;
947 link_tbl_ptr->j_extent = DESC_PTR_LNKTBL_RETURN;
948 link_tbl_ptr->len = cpu_to_be16(authsize);
949 sg = sg_last(areq->src, edesc->src_nents ? : 1);
950 link_tbl_ptr->ptr = cpu_to_be32(
951 (char *)sg_dma_address(sg)
952 + sg->length - authsize);
953 }
928 } else { 954 } else {
929 /* Only one segment now, so no link tbl needed */ 955 /* Only one segment now, so no link tbl needed */
930 desc->ptr[4].ptr = cpu_to_be32(sg_dma_address(areq->src)); 956 desc->ptr[4].ptr = cpu_to_be32(sg_dma_address(areq->src));
@@ -944,12 +970,11 @@ static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq,
944 desc->ptr[5].ptr = cpu_to_be32(sg_dma_address(areq->dst)); 970 desc->ptr[5].ptr = cpu_to_be32(sg_dma_address(areq->dst));
945 } else { 971 } else {
946 struct talitos_ptr *link_tbl_ptr = 972 struct talitos_ptr *link_tbl_ptr =
947 &edesc->link_tbl[edesc->src_nents]; 973 &edesc->link_tbl[edesc->src_nents + 1];
948 struct scatterlist *sg;
949 974
950 desc->ptr[5].ptr = cpu_to_be32((struct talitos_ptr *) 975 desc->ptr[5].ptr = cpu_to_be32((struct talitos_ptr *)
951 edesc->dma_link_tbl + 976 edesc->dma_link_tbl +
952 edesc->src_nents); 977 edesc->src_nents + 1);
953 if (areq->src == areq->dst) { 978 if (areq->src == areq->dst) {
954 memcpy(link_tbl_ptr, &edesc->link_tbl[0], 979 memcpy(link_tbl_ptr, &edesc->link_tbl[0],
955 edesc->src_nents * sizeof(struct talitos_ptr)); 980 edesc->src_nents * sizeof(struct talitos_ptr));
@@ -957,14 +982,10 @@ static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq,
957 sg_count = sg_to_link_tbl(areq->dst, sg_count, cryptlen, 982 sg_count = sg_to_link_tbl(areq->dst, sg_count, cryptlen,
958 link_tbl_ptr); 983 link_tbl_ptr);
959 } 984 }
985 /* Add an entry to the link table for ICV data */
960 link_tbl_ptr += sg_count - 1; 986 link_tbl_ptr += sg_count - 1;
961
962 /* handle case where sg_last contains the ICV exclusively */
963 sg = sg_last(areq->dst, edesc->dst_nents);
964 if (sg->length == ctx->authsize)
965 link_tbl_ptr--;
966
967 link_tbl_ptr->j_extent = 0; 987 link_tbl_ptr->j_extent = 0;
988 sg_count++;
968 link_tbl_ptr++; 989 link_tbl_ptr++;
969 link_tbl_ptr->j_extent = DESC_PTR_LNKTBL_RETURN; 990 link_tbl_ptr->j_extent = DESC_PTR_LNKTBL_RETURN;
970 link_tbl_ptr->len = cpu_to_be16(authsize); 991 link_tbl_ptr->len = cpu_to_be16(authsize);
@@ -973,7 +994,7 @@ static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq,
973 link_tbl_ptr->ptr = cpu_to_be32((struct talitos_ptr *) 994 link_tbl_ptr->ptr = cpu_to_be32((struct talitos_ptr *)
974 edesc->dma_link_tbl + 995 edesc->dma_link_tbl +
975 edesc->src_nents + 996 edesc->src_nents +
976 edesc->dst_nents + 1); 997 edesc->dst_nents + 2);
977 998
978 desc->ptr[5].j_extent |= DESC_PTR_LNKTBL_JUMP; 999 desc->ptr[5].j_extent |= DESC_PTR_LNKTBL_JUMP;
979 dma_sync_single_for_device(ctx->dev, edesc->dma_link_tbl, 1000 dma_sync_single_for_device(ctx->dev, edesc->dma_link_tbl,
@@ -1040,12 +1061,12 @@ static struct ipsec_esp_edesc *ipsec_esp_edesc_alloc(struct aead_request *areq,
1040 1061
1041 /* 1062 /*
1042 * allocate space for base edesc plus the link tables, 1063 * allocate space for base edesc plus the link tables,
1043 * allowing for a separate entry for the generated ICV (+ 1), 1064 * allowing for two separate entries for ICV and generated ICV (+ 2),
1044 * and the ICV data itself 1065 * and the ICV data itself
1045 */ 1066 */
1046 alloc_len = sizeof(struct ipsec_esp_edesc); 1067 alloc_len = sizeof(struct ipsec_esp_edesc);
1047 if (src_nents || dst_nents) { 1068 if (src_nents || dst_nents) {
1048 dma_len = (src_nents + dst_nents + 1) * 1069 dma_len = (src_nents + dst_nents + 2) *
1049 sizeof(struct talitos_ptr) + ctx->authsize; 1070 sizeof(struct talitos_ptr) + ctx->authsize;
1050 alloc_len += dma_len; 1071 alloc_len += dma_len;
1051 } else { 1072 } else {
@@ -1104,7 +1125,7 @@ static int aead_authenc_decrypt(struct aead_request *req)
1104 /* stash incoming ICV for later cmp with ICV generated by the h/w */ 1125 /* stash incoming ICV for later cmp with ICV generated by the h/w */
1105 if (edesc->dma_len) 1126 if (edesc->dma_len)
1106 icvdata = &edesc->link_tbl[edesc->src_nents + 1127 icvdata = &edesc->link_tbl[edesc->src_nents +
1107 edesc->dst_nents + 1]; 1128 edesc->dst_nents + 2];
1108 else 1129 else
1109 icvdata = &edesc->link_tbl[0]; 1130 icvdata = &edesc->link_tbl[0];
1110 1131
@@ -1480,6 +1501,9 @@ static int talitos_probe(struct of_device *ofdev,
1480 goto err_out; 1501 goto err_out;
1481 } 1502 }
1482 1503
1504 if (of_device_is_compatible(np, "fsl,sec3.0"))
1505 priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT;
1506
1483 priv->head_lock = kmalloc(sizeof(spinlock_t) * priv->num_channels, 1507 priv->head_lock = kmalloc(sizeof(spinlock_t) * priv->num_channels,
1484 GFP_KERNEL); 1508 GFP_KERNEL);
1485 priv->tail_lock = kmalloc(sizeof(spinlock_t) * priv->num_channels, 1509 priv->tail_lock = kmalloc(sizeof(spinlock_t) * priv->num_channels,