diff options
-rw-r--r-- | drivers/crypto/talitos.c | 127 | ||||
-rw-r--r-- | drivers/crypto/talitos.h | 8 |
2 files changed, 91 insertions, 44 deletions
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index b5c2c9340a9c..16c97caa17ac 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c | |||
@@ -137,6 +137,7 @@ struct talitos_private { | |||
137 | 137 | ||
138 | /* .features flag */ | 138 | /* .features flag */ |
139 | #define TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT 0x00000001 | 139 | #define TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT 0x00000001 |
140 | #define TALITOS_FTR_HW_AUTH_CHECK 0x00000002 | ||
140 | 141 | ||
141 | /* | 142 | /* |
142 | * map virtual single (contiguous) pointer to h/w descriptor pointer | 143 | * map virtual single (contiguous) pointer to h/w descriptor pointer |
@@ -183,6 +184,11 @@ static int reset_channel(struct device *dev, int ch) | |||
183 | setbits32(priv->reg + TALITOS_CCCR_LO(ch), TALITOS_CCCR_LO_CDWE | | 184 | setbits32(priv->reg + TALITOS_CCCR_LO(ch), TALITOS_CCCR_LO_CDWE | |
184 | TALITOS_CCCR_LO_CDIE); | 185 | TALITOS_CCCR_LO_CDIE); |
185 | 186 | ||
187 | /* and ICCR writeback, if available */ | ||
188 | if (priv->features & TALITOS_FTR_HW_AUTH_CHECK) | ||
189 | setbits32(priv->reg + TALITOS_CCCR_LO(ch), | ||
190 | TALITOS_CCCR_LO_IWSE); | ||
191 | |||
186 | return 0; | 192 | return 0; |
187 | } | 193 | } |
188 | 194 | ||
@@ -238,6 +244,11 @@ static int init_device(struct device *dev) | |||
238 | setbits32(priv->reg + TALITOS_IMR, TALITOS_IMR_INIT); | 244 | setbits32(priv->reg + TALITOS_IMR, TALITOS_IMR_INIT); |
239 | setbits32(priv->reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT); | 245 | setbits32(priv->reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT); |
240 | 246 | ||
247 | /* disable integrity check error interrupts (use writeback instead) */ | ||
248 | if (priv->features & TALITOS_FTR_HW_AUTH_CHECK) | ||
249 | setbits32(priv->reg + TALITOS_MDEUICR_LO, | ||
250 | TALITOS_MDEUICR_LO_ICE); | ||
251 | |||
241 | return 0; | 252 | return 0; |
242 | } | 253 | } |
243 | 254 | ||
@@ -375,7 +386,8 @@ static void talitos_done(unsigned long data) | |||
375 | /* At this point, all completed channels have been processed. | 386 | /* At this point, all completed channels have been processed. |
376 | * Unmask done interrupts for channels completed later on. | 387 | * Unmask done interrupts for channels completed later on. |
377 | */ | 388 | */ |
378 | setbits32(priv->reg + TALITOS_IMR, TALITOS_IMR_DONE); | 389 | setbits32(priv->reg + TALITOS_IMR, TALITOS_IMR_INIT); |
390 | setbits32(priv->reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT); | ||
379 | } | 391 | } |
380 | 392 | ||
381 | /* | 393 | /* |
@@ -812,7 +824,7 @@ static void ipsec_esp_encrypt_done(struct device *dev, | |||
812 | aead_request_complete(areq, err); | 824 | aead_request_complete(areq, err); |
813 | } | 825 | } |
814 | 826 | ||
815 | static void ipsec_esp_decrypt_done(struct device *dev, | 827 | static void ipsec_esp_decrypt_swauth_done(struct device *dev, |
816 | struct talitos_desc *desc, void *context, | 828 | struct talitos_desc *desc, void *context, |
817 | int err) | 829 | int err) |
818 | { | 830 | { |
@@ -844,6 +856,27 @@ static void ipsec_esp_decrypt_done(struct device *dev, | |||
844 | aead_request_complete(req, err); | 856 | aead_request_complete(req, err); |
845 | } | 857 | } |
846 | 858 | ||
859 | static void ipsec_esp_decrypt_hwauth_done(struct device *dev, | ||
860 | struct talitos_desc *desc, void *context, | ||
861 | int err) | ||
862 | { | ||
863 | struct aead_request *req = context; | ||
864 | struct ipsec_esp_edesc *edesc = | ||
865 | container_of(desc, struct ipsec_esp_edesc, desc); | ||
866 | |||
867 | ipsec_esp_unmap(dev, edesc, req); | ||
868 | |||
869 | /* check ICV auth status */ | ||
870 | if (!err) | ||
871 | if ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) != | ||
872 | DESC_HDR_LO_ICCR1_PASS) | ||
873 | err = -EBADMSG; | ||
874 | |||
875 | kfree(edesc); | ||
876 | |||
877 | aead_request_complete(req, err); | ||
878 | } | ||
879 | |||
847 | /* | 880 | /* |
848 | * convert scatterlist to SEC h/w link table format | 881 | * convert scatterlist to SEC h/w link table format |
849 | * stop at cryptlen bytes | 882 | * stop at cryptlen bytes |
@@ -897,6 +930,7 @@ static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq, | |||
897 | unsigned int authsize = ctx->authsize; | 930 | unsigned int authsize = ctx->authsize; |
898 | unsigned int ivsize; | 931 | unsigned int ivsize; |
899 | int sg_count, ret; | 932 | int sg_count, ret; |
933 | int sg_link_tbl_len; | ||
900 | 934 | ||
901 | /* hmac key */ | 935 | /* hmac key */ |
902 | map_single_talitos_ptr(dev, &desc->ptr[0], ctx->authkeylen, &ctx->key, | 936 | map_single_talitos_ptr(dev, &desc->ptr[0], ctx->authkeylen, &ctx->key, |
@@ -934,33 +968,19 @@ static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq, | |||
934 | if (sg_count == 1) { | 968 | if (sg_count == 1) { |
935 | desc->ptr[4].ptr = cpu_to_be32(sg_dma_address(areq->src)); | 969 | desc->ptr[4].ptr = cpu_to_be32(sg_dma_address(areq->src)); |
936 | } else { | 970 | } else { |
937 | sg_count = sg_to_link_tbl(areq->src, sg_count, cryptlen, | 971 | sg_link_tbl_len = cryptlen; |
972 | |||
973 | if ((edesc->desc.hdr & DESC_HDR_MODE1_MDEU_CICV) && | ||
974 | (edesc->desc.hdr & DESC_HDR_MODE0_ENCRYPT) == 0) { | ||
975 | sg_link_tbl_len = cryptlen + authsize; | ||
976 | } | ||
977 | sg_count = sg_to_link_tbl(areq->src, sg_count, sg_link_tbl_len, | ||
938 | &edesc->link_tbl[0]); | 978 | &edesc->link_tbl[0]); |
939 | if (sg_count > 1) { | 979 | if (sg_count > 1) { |
940 | struct talitos_ptr *link_tbl_ptr = | ||
941 | &edesc->link_tbl[sg_count-1]; | ||
942 | struct scatterlist *sg; | ||
943 | struct talitos_private *priv = dev_get_drvdata(dev); | ||
944 | |||
945 | desc->ptr[4].j_extent |= DESC_PTR_LNKTBL_JUMP; | 980 | desc->ptr[4].j_extent |= DESC_PTR_LNKTBL_JUMP; |
946 | desc->ptr[4].ptr = cpu_to_be32(edesc->dma_link_tbl); | 981 | desc->ptr[4].ptr = cpu_to_be32(edesc->dma_link_tbl); |
947 | dma_sync_single_for_device(ctx->dev, edesc->dma_link_tbl, | 982 | dma_sync_single_for_device(ctx->dev, edesc->dma_link_tbl, |
948 | edesc->dma_len, DMA_BIDIRECTIONAL); | 983 | edesc->dma_len, DMA_BIDIRECTIONAL); |
949 | /* If necessary for this SEC revision, | ||
950 | * add a link table entry for ICV. | ||
951 | */ | ||
952 | if ((priv->features & | ||
953 | TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT) && | ||
954 | (edesc->desc.hdr & DESC_HDR_MODE0_ENCRYPT) == 0) { | ||
955 | link_tbl_ptr->j_extent = 0; | ||
956 | link_tbl_ptr++; | ||
957 | link_tbl_ptr->j_extent = DESC_PTR_LNKTBL_RETURN; | ||
958 | link_tbl_ptr->len = cpu_to_be16(authsize); | ||
959 | sg = sg_last(areq->src, edesc->src_nents ? : 1); | ||
960 | link_tbl_ptr->ptr = cpu_to_be32( | ||
961 | (char *)sg_dma_address(sg) | ||
962 | + sg->length - authsize); | ||
963 | } | ||
964 | } else { | 984 | } else { |
965 | /* Only one segment now, so no link tbl needed */ | 985 | /* Only one segment now, so no link tbl needed */ |
966 | desc->ptr[4].ptr = cpu_to_be32(sg_dma_address(areq->src)); | 986 | desc->ptr[4].ptr = cpu_to_be32(sg_dma_address(areq->src)); |
@@ -985,13 +1005,9 @@ static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq, | |||
985 | desc->ptr[5].ptr = cpu_to_be32((struct talitos_ptr *) | 1005 | desc->ptr[5].ptr = cpu_to_be32((struct talitos_ptr *) |
986 | edesc->dma_link_tbl + | 1006 | edesc->dma_link_tbl + |
987 | edesc->src_nents + 1); | 1007 | edesc->src_nents + 1); |
988 | if (areq->src == areq->dst) { | 1008 | sg_count = sg_to_link_tbl(areq->dst, sg_count, cryptlen, |
989 | memcpy(link_tbl_ptr, &edesc->link_tbl[0], | 1009 | link_tbl_ptr); |
990 | edesc->src_nents * sizeof(struct talitos_ptr)); | 1010 | |
991 | } else { | ||
992 | sg_count = sg_to_link_tbl(areq->dst, sg_count, cryptlen, | ||
993 | link_tbl_ptr); | ||
994 | } | ||
995 | /* Add an entry to the link table for ICV data */ | 1011 | /* Add an entry to the link table for ICV data */ |
996 | link_tbl_ptr += sg_count - 1; | 1012 | link_tbl_ptr += sg_count - 1; |
997 | link_tbl_ptr->j_extent = 0; | 1013 | link_tbl_ptr->j_extent = 0; |
@@ -1116,11 +1132,14 @@ static int aead_authenc_encrypt(struct aead_request *req) | |||
1116 | return ipsec_esp(edesc, req, NULL, 0, ipsec_esp_encrypt_done); | 1132 | return ipsec_esp(edesc, req, NULL, 0, ipsec_esp_encrypt_done); |
1117 | } | 1133 | } |
1118 | 1134 | ||
1135 | |||
1136 | |||
1119 | static int aead_authenc_decrypt(struct aead_request *req) | 1137 | static int aead_authenc_decrypt(struct aead_request *req) |
1120 | { | 1138 | { |
1121 | struct crypto_aead *authenc = crypto_aead_reqtfm(req); | 1139 | struct crypto_aead *authenc = crypto_aead_reqtfm(req); |
1122 | struct talitos_ctx *ctx = crypto_aead_ctx(authenc); | 1140 | struct talitos_ctx *ctx = crypto_aead_ctx(authenc); |
1123 | unsigned int authsize = ctx->authsize; | 1141 | unsigned int authsize = ctx->authsize; |
1142 | struct talitos_private *priv = dev_get_drvdata(ctx->dev); | ||
1124 | struct ipsec_esp_edesc *edesc; | 1143 | struct ipsec_esp_edesc *edesc; |
1125 | struct scatterlist *sg; | 1144 | struct scatterlist *sg; |
1126 | void *icvdata; | 1145 | void *icvdata; |
@@ -1132,22 +1151,39 @@ static int aead_authenc_decrypt(struct aead_request *req) | |||
1132 | if (IS_ERR(edesc)) | 1151 | if (IS_ERR(edesc)) |
1133 | return PTR_ERR(edesc); | 1152 | return PTR_ERR(edesc); |
1134 | 1153 | ||
1135 | /* stash incoming ICV for later cmp with ICV generated by the h/w */ | 1154 | if ((priv->features & TALITOS_FTR_HW_AUTH_CHECK) && |
1136 | if (edesc->dma_len) | 1155 | (((!edesc->src_nents && !edesc->dst_nents) || |
1137 | icvdata = &edesc->link_tbl[edesc->src_nents + | 1156 | priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT))) { |
1138 | edesc->dst_nents + 2]; | ||
1139 | else | ||
1140 | icvdata = &edesc->link_tbl[0]; | ||
1141 | 1157 | ||
1142 | sg = sg_last(req->src, edesc->src_nents ? : 1); | 1158 | /* decrypt and check the ICV */ |
1159 | edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND | | ||
1160 | DESC_HDR_MODE1_MDEU_CICV; | ||
1143 | 1161 | ||
1144 | memcpy(icvdata, (char *)sg_virt(sg) + sg->length - ctx->authsize, | 1162 | /* reset integrity check result bits */ |
1145 | ctx->authsize); | 1163 | edesc->desc.hdr_lo = 0; |
1146 | 1164 | ||
1147 | /* decrypt */ | 1165 | return ipsec_esp(edesc, req, NULL, 0, ipsec_esp_decrypt_hwauth_done); |
1148 | edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND; | ||
1149 | 1166 | ||
1150 | return ipsec_esp(edesc, req, NULL, 0, ipsec_esp_decrypt_done); | 1167 | } else { |
1168 | |||
1169 | /* Have to check the ICV with software */ | ||
1170 | |||
1171 | edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND; | ||
1172 | |||
1173 | /* stash incoming ICV for later cmp with ICV generated by the h/w */ | ||
1174 | if (edesc->dma_len) | ||
1175 | icvdata = &edesc->link_tbl[edesc->src_nents + | ||
1176 | edesc->dst_nents + 2]; | ||
1177 | else | ||
1178 | icvdata = &edesc->link_tbl[0]; | ||
1179 | |||
1180 | sg = sg_last(req->src, edesc->src_nents ? : 1); | ||
1181 | |||
1182 | memcpy(icvdata, (char *)sg_virt(sg) + sg->length - ctx->authsize, | ||
1183 | ctx->authsize); | ||
1184 | |||
1185 | return ipsec_esp(edesc, req, NULL, 0, ipsec_esp_decrypt_swauth_done); | ||
1186 | } | ||
1151 | } | 1187 | } |
1152 | 1188 | ||
1153 | static int aead_authenc_givencrypt( | 1189 | static int aead_authenc_givencrypt( |
@@ -1460,10 +1496,10 @@ static int talitos_probe(struct of_device *ofdev, | |||
1460 | 1496 | ||
1461 | priv->ofdev = ofdev; | 1497 | priv->ofdev = ofdev; |
1462 | 1498 | ||
1463 | INIT_LIST_HEAD(&priv->alg_list); | ||
1464 | |||
1465 | tasklet_init(&priv->done_task, talitos_done, (unsigned long)dev); | 1499 | tasklet_init(&priv->done_task, talitos_done, (unsigned long)dev); |
1466 | 1500 | ||
1501 | INIT_LIST_HEAD(&priv->alg_list); | ||
1502 | |||
1467 | priv->irq = irq_of_parse_and_map(np, 0); | 1503 | priv->irq = irq_of_parse_and_map(np, 0); |
1468 | 1504 | ||
1469 | if (priv->irq == NO_IRQ) { | 1505 | if (priv->irq == NO_IRQ) { |
@@ -1516,6 +1552,9 @@ static int talitos_probe(struct of_device *ofdev, | |||
1516 | if (of_device_is_compatible(np, "fsl,sec3.0")) | 1552 | if (of_device_is_compatible(np, "fsl,sec3.0")) |
1517 | priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT; | 1553 | priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT; |
1518 | 1554 | ||
1555 | if (of_device_is_compatible(np, "fsl,sec2.1")) | ||
1556 | priv->features |= TALITOS_FTR_HW_AUTH_CHECK; | ||
1557 | |||
1519 | priv->head_lock = kmalloc(sizeof(spinlock_t) * priv->num_channels, | 1558 | priv->head_lock = kmalloc(sizeof(spinlock_t) * priv->num_channels, |
1520 | GFP_KERNEL); | 1559 | GFP_KERNEL); |
1521 | priv->tail_lock = kmalloc(sizeof(spinlock_t) * priv->num_channels, | 1560 | priv->tail_lock = kmalloc(sizeof(spinlock_t) * priv->num_channels, |
diff --git a/drivers/crypto/talitos.h b/drivers/crypto/talitos.h index e6b87770df03..125560a1d5f7 100644 --- a/drivers/crypto/talitos.h +++ b/drivers/crypto/talitos.h | |||
@@ -56,6 +56,7 @@ | |||
56 | #define TALITOS_CCCR_CONT 0x2 /* channel continue */ | 56 | #define TALITOS_CCCR_CONT 0x2 /* channel continue */ |
57 | #define TALITOS_CCCR_RESET 0x1 /* channel reset */ | 57 | #define TALITOS_CCCR_RESET 0x1 /* channel reset */ |
58 | #define TALITOS_CCCR_LO(ch) (ch * TALITOS_CH_STRIDE + 0x110c) | 58 | #define TALITOS_CCCR_LO(ch) (ch * TALITOS_CH_STRIDE + 0x110c) |
59 | #define TALITOS_CCCR_LO_IWSE 0x80 /* chan. ICCR writeback enab. */ | ||
59 | #define TALITOS_CCCR_LO_CDWE 0x10 /* chan. done writeback enab. */ | 60 | #define TALITOS_CCCR_LO_CDWE 0x10 /* chan. done writeback enab. */ |
60 | #define TALITOS_CCCR_LO_NT 0x4 /* notification type */ | 61 | #define TALITOS_CCCR_LO_NT 0x4 /* notification type */ |
61 | #define TALITOS_CCCR_LO_CDIE 0x2 /* channel done IRQ enable */ | 62 | #define TALITOS_CCCR_LO_CDIE 0x2 /* channel done IRQ enable */ |
@@ -103,6 +104,9 @@ | |||
103 | #define TALITOS_AESUISR_LO 0x4034 | 104 | #define TALITOS_AESUISR_LO 0x4034 |
104 | #define TALITOS_MDEUISR 0x6030 /* message digest unit */ | 105 | #define TALITOS_MDEUISR 0x6030 /* message digest unit */ |
105 | #define TALITOS_MDEUISR_LO 0x6034 | 106 | #define TALITOS_MDEUISR_LO 0x6034 |
107 | #define TALITOS_MDEUICR 0x6038 /* interrupt control */ | ||
108 | #define TALITOS_MDEUICR_LO 0x603c | ||
109 | #define TALITOS_MDEUICR_LO_ICE 0x4000 /* integrity check IRQ enable */ | ||
106 | #define TALITOS_AFEUISR 0x8030 /* arc4 unit */ | 110 | #define TALITOS_AFEUISR 0x8030 /* arc4 unit */ |
107 | #define TALITOS_AFEUISR_LO 0x8034 | 111 | #define TALITOS_AFEUISR_LO 0x8034 |
108 | #define TALITOS_RNGUISR 0xa030 /* random number unit */ | 112 | #define TALITOS_RNGUISR 0xa030 /* random number unit */ |
@@ -131,6 +135,9 @@ | |||
131 | 135 | ||
132 | /* written back when done */ | 136 | /* written back when done */ |
133 | #define DESC_HDR_DONE __constant_cpu_to_be32(0xff000000) | 137 | #define DESC_HDR_DONE __constant_cpu_to_be32(0xff000000) |
138 | #define DESC_HDR_LO_ICCR1_MASK __constant_cpu_to_be32(0x00180000) | ||
139 | #define DESC_HDR_LO_ICCR1_PASS __constant_cpu_to_be32(0x00080000) | ||
140 | #define DESC_HDR_LO_ICCR1_FAIL __constant_cpu_to_be32(0x00100000) | ||
134 | 141 | ||
135 | /* primary execution unit select */ | 142 | /* primary execution unit select */ |
136 | #define DESC_HDR_SEL0_MASK __constant_cpu_to_be32(0xf0000000) | 143 | #define DESC_HDR_SEL0_MASK __constant_cpu_to_be32(0xf0000000) |
@@ -169,6 +176,7 @@ | |||
169 | #define DESC_HDR_SEL1_CRCU __constant_cpu_to_be32(0x00080000) | 176 | #define DESC_HDR_SEL1_CRCU __constant_cpu_to_be32(0x00080000) |
170 | 177 | ||
171 | /* secondary execution unit mode (MODE1) and derivatives */ | 178 | /* secondary execution unit mode (MODE1) and derivatives */ |
179 | #define DESC_HDR_MODE1_MDEU_CICV __constant_cpu_to_be32(0x00004000) | ||
172 | #define DESC_HDR_MODE1_MDEU_INIT __constant_cpu_to_be32(0x00001000) | 180 | #define DESC_HDR_MODE1_MDEU_INIT __constant_cpu_to_be32(0x00001000) |
173 | #define DESC_HDR_MODE1_MDEU_HMAC __constant_cpu_to_be32(0x00000800) | 181 | #define DESC_HDR_MODE1_MDEU_HMAC __constant_cpu_to_be32(0x00000800) |
174 | #define DESC_HDR_MODE1_MDEU_PAD __constant_cpu_to_be32(0x00000400) | 182 | #define DESC_HDR_MODE1_MDEU_PAD __constant_cpu_to_be32(0x00000400) |