diff options
Diffstat (limited to 'drivers/crypto/talitos.c')
| -rw-r--r-- | drivers/crypto/talitos.c | 49 |
1 files changed, 34 insertions, 15 deletions
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index b11943dadefd..681c15f42083 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c | |||
| @@ -99,6 +99,9 @@ struct talitos_private { | |||
| 99 | /* next channel to be assigned next incoming descriptor */ | 99 | /* next channel to be assigned next incoming descriptor */ |
| 100 | atomic_t last_chan; | 100 | atomic_t last_chan; |
| 101 | 101 | ||
| 102 | /* per-channel number of requests pending in channel h/w fifo */ | ||
| 103 | atomic_t *submit_count; | ||
| 104 | |||
| 102 | /* per-channel request fifo */ | 105 | /* per-channel request fifo */ |
| 103 | struct talitos_request **fifo; | 106 | struct talitos_request **fifo; |
| 104 | 107 | ||
| @@ -263,15 +266,15 @@ static int talitos_submit(struct device *dev, struct talitos_desc *desc, | |||
| 263 | 266 | ||
| 264 | spin_lock_irqsave(&priv->head_lock[ch], flags); | 267 | spin_lock_irqsave(&priv->head_lock[ch], flags); |
| 265 | 268 | ||
| 266 | head = priv->head[ch]; | 269 | if (!atomic_inc_not_zero(&priv->submit_count[ch])) { |
| 267 | request = &priv->fifo[ch][head]; | 270 | /* h/w fifo is full */ |
| 268 | |||
| 269 | if (request->desc) { | ||
| 270 | /* request queue is full */ | ||
| 271 | spin_unlock_irqrestore(&priv->head_lock[ch], flags); | 271 | spin_unlock_irqrestore(&priv->head_lock[ch], flags); |
| 272 | return -EAGAIN; | 272 | return -EAGAIN; |
| 273 | } | 273 | } |
| 274 | 274 | ||
| 275 | head = priv->head[ch]; | ||
| 276 | request = &priv->fifo[ch][head]; | ||
| 277 | |||
| 275 | /* map descriptor and save caller data */ | 278 | /* map descriptor and save caller data */ |
| 276 | request->dma_desc = dma_map_single(dev, desc, sizeof(*desc), | 279 | request->dma_desc = dma_map_single(dev, desc, sizeof(*desc), |
| 277 | DMA_BIDIRECTIONAL); | 280 | DMA_BIDIRECTIONAL); |
| @@ -335,6 +338,9 @@ static void flush_channel(struct device *dev, int ch, int error, int reset_ch) | |||
| 335 | priv->tail[ch] = (tail + 1) & (priv->fifo_len - 1); | 338 | priv->tail[ch] = (tail + 1) & (priv->fifo_len - 1); |
| 336 | 339 | ||
| 337 | spin_unlock_irqrestore(&priv->tail_lock[ch], flags); | 340 | spin_unlock_irqrestore(&priv->tail_lock[ch], flags); |
| 341 | |||
| 342 | atomic_dec(&priv->submit_count[ch]); | ||
| 343 | |||
| 338 | saved_req.callback(dev, saved_req.desc, saved_req.context, | 344 | saved_req.callback(dev, saved_req.desc, saved_req.context, |
| 339 | status); | 345 | status); |
| 340 | /* channel may resume processing in single desc error case */ | 346 | /* channel may resume processing in single desc error case */ |
| @@ -842,7 +848,7 @@ static int sg_to_link_tbl(struct scatterlist *sg, int sg_count, | |||
| 842 | 848 | ||
| 843 | /* adjust (decrease) last one (or two) entry's len to cryptlen */ | 849 | /* adjust (decrease) last one (or two) entry's len to cryptlen */ |
| 844 | link_tbl_ptr--; | 850 | link_tbl_ptr--; |
| 845 | while (link_tbl_ptr->len <= (-cryptlen)) { | 851 | while (be16_to_cpu(link_tbl_ptr->len) <= (-cryptlen)) { |
| 846 | /* Empty this entry, and move to previous one */ | 852 | /* Empty this entry, and move to previous one */ |
| 847 | cryptlen += be16_to_cpu(link_tbl_ptr->len); | 853 | cryptlen += be16_to_cpu(link_tbl_ptr->len); |
| 848 | link_tbl_ptr->len = 0; | 854 | link_tbl_ptr->len = 0; |
| @@ -874,7 +880,7 @@ static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq, | |||
| 874 | unsigned int cryptlen = areq->cryptlen; | 880 | unsigned int cryptlen = areq->cryptlen; |
| 875 | unsigned int authsize = ctx->authsize; | 881 | unsigned int authsize = ctx->authsize; |
| 876 | unsigned int ivsize; | 882 | unsigned int ivsize; |
| 877 | int sg_count; | 883 | int sg_count, ret; |
| 878 | 884 | ||
| 879 | /* hmac key */ | 885 | /* hmac key */ |
| 880 | map_single_talitos_ptr(dev, &desc->ptr[0], ctx->authkeylen, &ctx->key, | 886 | map_single_talitos_ptr(dev, &desc->ptr[0], ctx->authkeylen, &ctx->key, |
| @@ -978,7 +984,12 @@ static int ipsec_esp(struct ipsec_esp_edesc *edesc, struct aead_request *areq, | |||
| 978 | map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv, 0, | 984 | map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv, 0, |
| 979 | DMA_FROM_DEVICE); | 985 | DMA_FROM_DEVICE); |
| 980 | 986 | ||
| 981 | return talitos_submit(dev, desc, callback, areq); | 987 | ret = talitos_submit(dev, desc, callback, areq); |
| 988 | if (ret != -EINPROGRESS) { | ||
| 989 | ipsec_esp_unmap(dev, edesc, areq); | ||
| 990 | kfree(edesc); | ||
| 991 | } | ||
| 992 | return ret; | ||
| 982 | } | 993 | } |
| 983 | 994 | ||
| 984 | 995 | ||
| @@ -1009,6 +1020,8 @@ static struct ipsec_esp_edesc *ipsec_esp_edesc_alloc(struct aead_request *areq, | |||
| 1009 | struct talitos_ctx *ctx = crypto_aead_ctx(authenc); | 1020 | struct talitos_ctx *ctx = crypto_aead_ctx(authenc); |
| 1010 | struct ipsec_esp_edesc *edesc; | 1021 | struct ipsec_esp_edesc *edesc; |
| 1011 | int src_nents, dst_nents, alloc_len, dma_len; | 1022 | int src_nents, dst_nents, alloc_len, dma_len; |
| 1023 | gfp_t flags = areq->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : | ||
| 1024 | GFP_ATOMIC; | ||
| 1012 | 1025 | ||
| 1013 | if (areq->cryptlen + ctx->authsize > TALITOS_MAX_DATA_LEN) { | 1026 | if (areq->cryptlen + ctx->authsize > TALITOS_MAX_DATA_LEN) { |
| 1014 | dev_err(ctx->dev, "cryptlen exceeds h/w max limit\n"); | 1027 | dev_err(ctx->dev, "cryptlen exceeds h/w max limit\n"); |
| @@ -1022,7 +1035,7 @@ static struct ipsec_esp_edesc *ipsec_esp_edesc_alloc(struct aead_request *areq, | |||
| 1022 | dst_nents = src_nents; | 1035 | dst_nents = src_nents; |
| 1023 | } else { | 1036 | } else { |
| 1024 | dst_nents = sg_count(areq->dst, areq->cryptlen + ctx->authsize); | 1037 | dst_nents = sg_count(areq->dst, areq->cryptlen + ctx->authsize); |
| 1025 | dst_nents = (dst_nents == 1) ? 0 : src_nents; | 1038 | dst_nents = (dst_nents == 1) ? 0 : dst_nents; |
| 1026 | } | 1039 | } |
| 1027 | 1040 | ||
| 1028 | /* | 1041 | /* |
| @@ -1040,7 +1053,7 @@ static struct ipsec_esp_edesc *ipsec_esp_edesc_alloc(struct aead_request *areq, | |||
| 1040 | alloc_len += icv_stashing ? ctx->authsize : 0; | 1053 | alloc_len += icv_stashing ? ctx->authsize : 0; |
| 1041 | } | 1054 | } |
| 1042 | 1055 | ||
| 1043 | edesc = kmalloc(alloc_len, GFP_DMA); | 1056 | edesc = kmalloc(alloc_len, GFP_DMA | flags); |
| 1044 | if (!edesc) { | 1057 | if (!edesc) { |
| 1045 | dev_err(ctx->dev, "could not allocate edescriptor\n"); | 1058 | dev_err(ctx->dev, "could not allocate edescriptor\n"); |
| 1046 | return ERR_PTR(-ENOMEM); | 1059 | return ERR_PTR(-ENOMEM); |
| @@ -1337,6 +1350,7 @@ static int __devexit talitos_remove(struct of_device *ofdev) | |||
| 1337 | if (hw_supports(dev, DESC_HDR_SEL0_RNG)) | 1350 | if (hw_supports(dev, DESC_HDR_SEL0_RNG)) |
| 1338 | talitos_unregister_rng(dev); | 1351 | talitos_unregister_rng(dev); |
| 1339 | 1352 | ||
| 1353 | kfree(priv->submit_count); | ||
| 1340 | kfree(priv->tail); | 1354 | kfree(priv->tail); |
| 1341 | kfree(priv->head); | 1355 | kfree(priv->head); |
| 1342 | 1356 | ||
| @@ -1466,9 +1480,6 @@ static int talitos_probe(struct of_device *ofdev, | |||
| 1466 | goto err_out; | 1480 | goto err_out; |
| 1467 | } | 1481 | } |
| 1468 | 1482 | ||
| 1469 | of_node_put(np); | ||
| 1470 | np = NULL; | ||
| 1471 | |||
| 1472 | priv->head_lock = kmalloc(sizeof(spinlock_t) * priv->num_channels, | 1483 | priv->head_lock = kmalloc(sizeof(spinlock_t) * priv->num_channels, |
| 1473 | GFP_KERNEL); | 1484 | GFP_KERNEL); |
| 1474 | priv->tail_lock = kmalloc(sizeof(spinlock_t) * priv->num_channels, | 1485 | priv->tail_lock = kmalloc(sizeof(spinlock_t) * priv->num_channels, |
| @@ -1504,6 +1515,16 @@ static int talitos_probe(struct of_device *ofdev, | |||
| 1504 | } | 1515 | } |
| 1505 | } | 1516 | } |
| 1506 | 1517 | ||
| 1518 | priv->submit_count = kmalloc(sizeof(atomic_t) * priv->num_channels, | ||
| 1519 | GFP_KERNEL); | ||
| 1520 | if (!priv->submit_count) { | ||
| 1521 | dev_err(dev, "failed to allocate fifo submit count space\n"); | ||
| 1522 | err = -ENOMEM; | ||
| 1523 | goto err_out; | ||
| 1524 | } | ||
| 1525 | for (i = 0; i < priv->num_channels; i++) | ||
| 1526 | atomic_set(&priv->submit_count[i], -priv->chfifo_len); | ||
| 1527 | |||
| 1507 | priv->head = kzalloc(sizeof(int) * priv->num_channels, GFP_KERNEL); | 1528 | priv->head = kzalloc(sizeof(int) * priv->num_channels, GFP_KERNEL); |
| 1508 | priv->tail = kzalloc(sizeof(int) * priv->num_channels, GFP_KERNEL); | 1529 | priv->tail = kzalloc(sizeof(int) * priv->num_channels, GFP_KERNEL); |
| 1509 | if (!priv->head || !priv->tail) { | 1530 | if (!priv->head || !priv->tail) { |
| @@ -1559,8 +1580,6 @@ static int talitos_probe(struct of_device *ofdev, | |||
| 1559 | 1580 | ||
| 1560 | err_out: | 1581 | err_out: |
| 1561 | talitos_remove(ofdev); | 1582 | talitos_remove(ofdev); |
| 1562 | if (np) | ||
| 1563 | of_node_put(np); | ||
| 1564 | 1583 | ||
| 1565 | return err; | 1584 | return err; |
| 1566 | } | 1585 | } |
