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>
This commit is contained in:
parent
40405f10b8
commit
1c2e8811ee
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user