From a8f461c2b9df3c69f0ea995ce1fb506be50be409 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 4 Mar 2014 11:29:41 -0700 Subject: [PATCH] staging: comedi: pcl818: factor out the common "dropout" detect code The DMA, FIFO, and EOC interrupt handlers all have common code that checks for channel dropout when running an async command. Factor this common code into a helper function. Only return the sample if the channel is valid. The EOC handler was previously returning the value then checking for channel dropout. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl818.c | 71 +++++++++++++------------ 1 file changed, 38 insertions(+), 33 deletions(-) diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 53d1af253494..745beddecdd4 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -555,6 +555,28 @@ static int pcl818_do_insn_bits(struct comedi_device *dev, return insn->n; } +static bool pcl818_ai_dropout(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int chan) +{ + struct pcl818_private *devpriv = dev->private; + unsigned int expected_chan; + + expected_chan = devpriv->act_chanlist[devpriv->act_chanlist_pos]; + if (chan != expected_chan) { + dev_dbg(dev->class_dev, + "A/D mode1/3 %s - channel dropout %d!=%d !\n", + (devpriv->dma) ? "DMA" : + (devpriv->usefifo) ? "FIFO" : "IRQ", + chan, expected_chan); + s->cancel(dev, s); + s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + comedi_event(dev, s); + return true; + } + return false; +} + static bool pcl818_ai_next_chan(struct comedi_device *dev, struct comedi_subdevice *s) { @@ -588,9 +610,9 @@ static bool pcl818_ai_next_chan(struct comedi_device *dev, static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d) { struct comedi_device *dev = d; - struct pcl818_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; unsigned int chan; + unsigned int val; if (pcl818_ai_eoc(dev, s, NULL, 0)) { outb(0, dev->iobase + PCL818_STATUS); /* clear INT request */ @@ -601,19 +623,13 @@ static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d) return IRQ_HANDLED; } - comedi_buf_put(s->async, pcl818_ai_get_sample(dev, s, &chan)); + val = pcl818_ai_get_sample(dev, s, &chan); outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */ - if (chan != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { - dev_dbg(dev->class_dev, - "A/D mode1/3 IRQ - channel dropout %x!=%x !\n", - chan, - devpriv->act_chanlist[devpriv->act_chanlist_pos]); - s->cancel(dev, s); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; - comedi_event(dev, s); + if (pcl818_ai_dropout(dev, s, chan)) return IRQ_HANDLED; - } + + comedi_buf_put(s->async, val); if (!pcl818_ai_next_chan(dev, s)) return IRQ_HANDLED; @@ -627,8 +643,10 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d) struct comedi_device *dev = d; struct pcl818_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; - int i, len, bufptr; unsigned short *ptr; + unsigned int chan; + unsigned int val; + int i, len, bufptr; pcl818_ai_setup_next_dma(dev, s); @@ -639,19 +657,14 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d) bufptr = 0; for (i = 0; i < len; i++) { - if ((ptr[bufptr] & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { /* dropout! */ - dev_dbg(dev->class_dev, - "A/D mode1/3 DMA - channel dropout %d(card)!=%d(chanlist) at %d !\n", - (ptr[bufptr] & 0xf), - devpriv->act_chanlist[devpriv->act_chanlist_pos], - devpriv->act_chanlist_pos); - s->cancel(dev, s); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; - comedi_event(dev, s); + val = ptr[bufptr++]; + chan = val & 0xf; + val = (val >> 4) & s->maxdata; + + if (pcl818_ai_dropout(dev, s, chan)) return IRQ_HANDLED; - } - comedi_buf_put(s->async, ptr[bufptr++] >> 4); /* get one sample */ + comedi_buf_put(s->async, val); if (!pcl818_ai_next_chan(dev, s)) return IRQ_HANDLED; @@ -665,7 +678,6 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d) static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d) { struct comedi_device *dev = d; - struct pcl818_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; unsigned int status; unsigned int chan; @@ -699,16 +711,9 @@ static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d) for (i = 0; i < len; i++) { val = pcl818_ai_get_fifo_sample(dev, s, &chan); - if (chan != devpriv->act_chanlist[devpriv->act_chanlist_pos]) { - dev_dbg(dev->class_dev, - "A/D mode1/3 FIFO - channel dropout %d!=%d !\n", - chan, - devpriv->act_chanlist[devpriv->act_chanlist_pos]); - s->cancel(dev, s); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; - comedi_event(dev, s); + + if (pcl818_ai_dropout(dev, s, chan)) return IRQ_HANDLED; - } comedi_buf_put(s->async, val); -- 2.34.1