aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/crypto/talitos.c
diff options
context:
space:
mode:
authorLee Nipper <lee.nipper@freescale.com>2008-10-12 08:29:34 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2008-12-24 19:01:10 -0500
commit1c2e8811eea5f0c5da3213ea206c2864fa4614fd (patch)
tree1d1a227e268bef3bd7ce1df189dacee29cbf1937 /drivers/crypto/talitos.c
parent40405f10b853ef404b395c6febca71b0de185490 (diff)
crypto: talitos - Implement done interrupt mitigation
In talitos_interrupt, upon one done interrupt, mask further done interrupts, and ack only any error interrupt. In talitos_done, unmask done interrupts after completing processing. In flush_channel, ack each done channel processed. Keep done overflow interrupts masked because even though each pkt is ack'ed, a few done overflows still occur. 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/talitos.c')
-rw-r--r--drivers/crypto/talitos.c30
1 files changed, 22 insertions, 8 deletions
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index c429f684c79d..b5c2c9340a9c 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -319,9 +319,11 @@ static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
319 319
320 /* descriptors with their done bits set don't get the error */ 320 /* descriptors with their done bits set don't get the error */
321 rmb(); 321 rmb();
322 if ((request->desc->hdr & DESC_HDR_DONE) == DESC_HDR_DONE) 322 if ((request->desc->hdr & DESC_HDR_DONE) == DESC_HDR_DONE) {
323 status = 0; 323 status = 0;
324 else 324 /* Ack each pkt completed on channel */
325 out_be32(priv->reg + TALITOS_ICR, (1 << (ch * 2)));
326 } else
325 if (!error) 327 if (!error)
326 break; 328 break;
327 else 329 else
@@ -369,6 +371,11 @@ static void talitos_done(unsigned long data)
369 371
370 for (ch = 0; ch < priv->num_channels; ch++) 372 for (ch = 0; ch < priv->num_channels; ch++)
371 flush_channel(dev, ch, 0, 0); 373 flush_channel(dev, ch, 0, 0);
374
375 /* At this point, all completed channels have been processed.
376 * Unmask done interrupts for channels completed later on.
377 */
378 setbits32(priv->reg + TALITOS_IMR, TALITOS_IMR_DONE);
372} 379}
373 380
374/* 381/*
@@ -557,15 +564,22 @@ static irqreturn_t talitos_interrupt(int irq, void *data)
557 isr = in_be32(priv->reg + TALITOS_ISR); 564 isr = in_be32(priv->reg + TALITOS_ISR);
558 isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); 565 isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);
559 566
560 /* ack */ 567 if (unlikely((isr & ~TALITOS_ISR_CHDONE) || isr_lo)) {
561 out_be32(priv->reg + TALITOS_ICR, isr); 568 /*
562 out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); 569 * Acknowledge error interrupts here.
570 * Done interrupts are ack'ed as part of done_task.
571 */
572 out_be32(priv->reg + TALITOS_ICR, isr);
573 out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);
563 574
564 if (unlikely((isr & ~TALITOS_ISR_CHDONE) || isr_lo))
565 talitos_error((unsigned long)data, isr, isr_lo); 575 talitos_error((unsigned long)data, isr, isr_lo);
566 else 576 } else
567 if (likely(isr & TALITOS_ISR_CHDONE)) 577 if (likely(isr & TALITOS_ISR_CHDONE)) {
578 /* mask further done interrupts. */
579 clrbits32(priv->reg + TALITOS_IMR, TALITOS_IMR_DONE);
580 /* done_task will unmask done interrupts at exit */
568 tasklet_schedule(&priv->done_task); 581 tasklet_schedule(&priv->done_task);
582 }
569 583
570 return (isr || isr_lo) ? IRQ_HANDLED : IRQ_NONE; 584 return (isr || isr_lo) ? IRQ_HANDLED : IRQ_NONE;
571} 585}