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 <hswee...@visionengravers.com>
Cc: Ian Abbott <abbo...@mev.co.uk>
Cc: Greg Kroah-Hartman <gre...@linuxfoundation.org>
---
 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 53d1af2..745bedd 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);
 
-- 
1.8.5.2

_______________________________________________
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

Reply via email to