Commit 1c2e8811 authored by Lee Nipper's avatar Lee Nipper Committed by Herbert Xu
Browse files

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: default avatarLee Nipper <lee.nipper@freescale.com>
Signed-off-by: default avatarKim Phillips <kim.phillips@freescale.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 40405f10
Loading
Loading
Loading
Loading
+22 −8
Original line number Diff line number Diff line
@@ -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 */
	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;
}
+2 −1
Original line number Diff line number Diff line
@@ -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 */