diff options
author | Kim Phillips <kim.phillips@freescale.com> | 2008-07-17 08:16:40 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2008-07-17 08:16:40 -0400 |
commit | ec6644d6325b5a38525f1d5b20fd4bf7db05cf2a (patch) | |
tree | fd5c1d22f84212026b98dc7fd92dcbd900f44c40 /drivers/crypto/talitos.c | |
parent | 695ad589698571046d42a4450c2d801486905535 (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>
Diffstat (limited to 'drivers/crypto/talitos.c')
-rw-r--r-- | drivers/crypto/talitos.c | 27 |
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) { |