[PATCH 09/18] dmaengine/amba-pl08x: Schedule tasklet in case of error interrupt
Koul, Vinod
vinod.koul at intel.com
Fri Jul 29 08:16:39 EDT 2011
On Fri, 2011-07-29 at 16:19 +0530, Viresh Kumar wrote:
> Currently, if error interrupt occurs, nothing is done in interrupt handler (just
> clearing the interrupts). We must somehow indicate this to the user that DMA is
> over, due to ERR interrupt or TC interrupt.
>
> So, this patch just schedules existing tasklet, with a print showing error
> interrupt has occured on which channels.
>
> Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
> ---
> drivers/dma/amba-pl08x.c | 43 ++++++++++++++++++-------------------------
> 1 files changed, 18 insertions(+), 25 deletions(-)
>
> diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
> index c4ce1a2..b9137bc 100644
> --- a/drivers/dma/amba-pl08x.c
> +++ b/drivers/dma/amba-pl08x.c
> @@ -1630,40 +1630,33 @@ static void pl08x_tasklet(unsigned long data)
> static irqreturn_t pl08x_irq(int irq, void *dev)
> {
> struct pl08x_driver_data *pl08x = dev;
> - u32 mask = 0;
> - u32 val;
> - int i;
> -
> - val = readl(pl08x->base + PL080_ERR_STATUS);
> - if (val) {
> - /* An error interrupt (on one or more channels) */
> - dev_err(&pl08x->adev->dev,
> - "%s error interrupt, register value 0x%08x\n",
> - __func__, val);
> - /*
> - * Simply clear ALL PL08X error interrupts,
> - * regardless of channel and cause
> - * FIXME: should be 0x00000003 on PL081 really.
> - */
> - writel(0x000000FF, pl08x->base + PL080_ERR_CLEAR);
> + u32 err, tc, i;
> +
> + /* check & clear - ERR & TC interrupts */
> + err = readl(pl08x->base + PL080_ERR_STATUS);
> + if (err) {
> + dev_err(&pl08x->adev->dev, "%s error interrupt, register value"
> + "0x%08x\n", __func__, err);
again this looks convoluted, and the stuff is quotes can be in single
line :)
> + writel(err, pl08x->base + PL080_ERR_CLEAR);
> }
> - val = readl(pl08x->base + PL080_INT_STATUS);
> - for (i = 0; i < pl08x->vd->channels; i++) {
> - if ((1 << i) & val) {
> + tc = readl(pl08x->base + PL080_INT_STATUS);
> + if (tc)
> + writel(tc, pl08x->base + PL080_TC_CLEAR);
> +
> + if (!err && !tc)
> + return IRQ_NONE;
> +
> + for (i = 0; i < pl08x->vd->channels; i++)
> + if (((1 << i) & err) || ((1 << i) & tc)) {
> /* Locate physical channel */
> struct pl08x_phy_chan *phychan = &pl08x->phy_chans[i];
> struct pl08x_dma_chan *plchan = phychan->serving;
>
> /* Schedule tasklet on this channel */
> tasklet_schedule(&plchan->tasklet);
but in tasklet you will call the client callback, so how does the client
know if this was success or error? Did I miss anything?
> -
> - mask |= (1 << i);
> }
> - }
> - /* Clear only the terminal interrupts on channels we processed */
> - writel(mask, pl08x->base + PL080_TC_CLEAR);
>
> - return mask ? IRQ_HANDLED : IRQ_NONE;
> + return IRQ_HANDLED;
> }
>
> static void pl08x_dma_slave_init(struct pl08x_dma_chan *chan)
--
~Vinod
More information about the linux-arm-kernel
mailing list