[PATCH 20/66] staging: comedi: pcl818: factor out the common "dropout" detect code

H Hartley Sweeten hsweeten at visionengravers.com
Fri Feb 28 23:24:09 UTC 2014


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 <hsweeten at visionengravers.com>
Cc: Ian Abbott <abbotti at mev.co.uk>
Cc: Greg Kroah-Hartman <gregkh at 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 506a9cc..c28671f 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



More information about the devel mailing list