diff options
author | 2008-10-12 20:29:34 +0800 | |
---|---|---|
committer | 2008-12-25 11:01:10 +1100 | |
commit | 1c2e8811eea5f0c5da3213ea206c2864fa4614fd (patch) | |
tree | 1d1a227e268bef3bd7ce1df189dacee29cbf1937 /drivers/crypto | |
parent | crypto: talitos - Pass correct interrupt status to error handler (diff) | |
download | linux-1c2e8811eea5f0c5da3213ea206c2864fa4614fd.tar.gz linux-1c2e8811eea5f0c5da3213ea206c2864fa4614fd.tar.bz2 linux-1c2e8811eea5f0c5da3213ea206c2864fa4614fd.zip |
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')
-rw-r--r-- | drivers/crypto/talitos.c | 30 | ||||
-rw-r--r-- | drivers/crypto/talitos.h | 3 |
2 files changed, 24 insertions, 9 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) /* descriptors with their done bits set don't get the error */ rmb(); - if ((request->desc->hdr & DESC_HDR_DONE) == DESC_HDR_DONE) + if ((request->desc->hdr & DESC_HDR_DONE) == DESC_HDR_DONE) { status = 0; - else + /* Ack each pkt completed on channel */ + out_be32(priv->reg + TALITOS_ICR, (1 << (ch * 2))); + } else if (!error) break; else @@ -369,6 +371,11 @@ static void talitos_done(unsigned long data) for (ch = 0; ch < priv->num_channels; ch++) flush_channel(dev, ch, 0, 0); + + /* At this point, all completed channels have been processed. + * Unmask done interrupts for channels completed later on. + */ + setbits32(priv->reg + TALITOS_IMR, TALITOS_IMR_DONE); } /* @@ -557,15 +564,22 @@ static irqreturn_t talitos_interrupt(int irq, void *data) isr = in_be32(priv->reg + TALITOS_ISR); isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); - /* ack */ - out_be32(priv->reg + TALITOS_ICR, isr); - out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); + if (unlikely((isr & ~TALITOS_ISR_CHDONE) || isr_lo)) { + /* + * Acknowledge error interrupts here. + * Done interrupts are ack'ed as part of done_task. + */ + out_be32(priv->reg + TALITOS_ICR, isr); + out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); - if (unlikely((isr & ~TALITOS_ISR_CHDONE) || isr_lo)) talitos_error((unsigned long)data, isr, isr_lo); - else - if (likely(isr & TALITOS_ISR_CHDONE)) + } else + if (likely(isr & TALITOS_ISR_CHDONE)) { + /* mask further done interrupts. */ + clrbits32(priv->reg + TALITOS_IMR, TALITOS_IMR_DONE); + /* done_task will unmask done interrupts at exit */ tasklet_schedule(&priv->done_task); + } return (isr || isr_lo) ? IRQ_HANDLED : IRQ_NONE; } diff --git a/drivers/crypto/talitos.h b/drivers/crypto/talitos.h index c48a405abf70..e6b87770df03 100644 --- a/drivers/crypto/talitos.h +++ b/drivers/crypto/talitos.h @@ -37,7 +37,8 @@ #define TALITOS_MCR_LO 0x1038 #define TALITOS_MCR_SWR 0x1 /* s/w reset */ #define TALITOS_IMR 0x1008 /* interrupt mask register */ -#define TALITOS_IMR_INIT 0x10fff /* enable channel IRQs */ +#define TALITOS_IMR_INIT 0x100ff /* enable channel IRQs */ +#define TALITOS_IMR_DONE 0x00055 /* done IRQs */ #define TALITOS_IMR_LO 0x100C #define TALITOS_IMR_LO_INIT 0x20000 /* allow RNGU error IRQs */ #define TALITOS_ISR 0x1010 /* interrupt status register */ |