aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKim Phillips <kim.phillips@freescale.com>2008-07-17 08:16:40 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2008-07-17 08:16:40 -0400
commitec6644d6325b5a38525f1d5b20fd4bf7db05cf2a (patch)
treefd5c1d22f84212026b98dc7fd92dcbd900f44c40
parent695ad589698571046d42a4450c2d801486905535 (diff)
crypto: talitos - Preempt overflow interrupts
add requests pending/submit count to prevent request queue full condition by preempting h/w overflow interrupts in software. We do this due to the delay in the delivery and handling of the channel overflow error interrupt. Signed-off-by: Kim Phillips <kim.phillips@freescale.com> Acked-by: Lee Nipper <lee.nipper@freescale.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--drivers/crypto/talitos.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index f644fba35c8c..fdb0680f6ffe 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 */
@@ -1337,6 +1343,7 @@ static int __devexit talitos_remove(struct of_device *ofdev)
1337 if (hw_supports(dev, DESC_HDR_SEL0_RNG)) 1343 if (hw_supports(dev, DESC_HDR_SEL0_RNG))
1338 talitos_unregister_rng(dev); 1344 talitos_unregister_rng(dev);
1339 1345
1346 kfree(priv->submit_count);
1340 kfree(priv->tail); 1347 kfree(priv->tail);
1341 kfree(priv->head); 1348 kfree(priv->head);
1342 1349
@@ -1501,6 +1508,16 @@ static int talitos_probe(struct of_device *ofdev,
1501 } 1508 }
1502 } 1509 }
1503 1510
1511 priv->submit_count = kmalloc(sizeof(int) * priv->num_channels,
1512 GFP_KERNEL);
1513 if (!priv->submit_count) {
1514 dev_err(dev, "failed to allocate fifo submit count space\n");
1515 err = -ENOMEM;
1516 goto err_out;
1517 }
1518 for (i = 0; i < priv->num_channels; i++)
1519 atomic_set(&priv->submit_count[i], -priv->chfifo_len);
1520
1504 priv->head = kzalloc(sizeof(int) * priv->num_channels, GFP_KERNEL); 1521 priv->head = kzalloc(sizeof(int) * priv->num_channels, GFP_KERNEL);
1505 priv->tail = kzalloc(sizeof(int) * priv->num_channels, GFP_KERNEL); 1522 priv->tail = kzalloc(sizeof(int) * priv->num_channels, GFP_KERNEL);
1506 if (!priv->head || !priv->tail) { 1523 if (!priv->head || !priv->tail) {