[PATCH 16/66] staging: comedi: pcl816: factor out the common "next ai chan" code

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


The DMA and EOC interrupt handlers all have common code that bumps the
counters in the private data that keep track of what channel is being
sampled next and when all the data has been sampled.

Factor this common code into a helper function.

Don't clear the events in the driver. The comedi core will clear the events
at the end of the comedi_event().

Make sure the COMEDI_CB_BLOCK event is set when advancing to the next
channel so that when the comedi_event() is finally called the core will
wake the async_queue to return the analog input data.

Also, make sure the COMEDI_CB_EOS event is set at the completion of each
scan.

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/pcl816.c | 63 ++++++++++++++++-----------------
 1 file changed, 31 insertions(+), 32 deletions(-)

diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
index 6000ca91..e7d6717 100644
--- a/drivers/staging/comedi/drivers/pcl816.c
+++ b/drivers/staging/comedi/drivers/pcl816.c
@@ -273,12 +273,37 @@ static int pcl816_ai_insn_read(struct comedi_device *dev,
 	return n;
 }
 
+static bool pcl816_ai_next_chan(struct comedi_device *dev,
+				struct comedi_subdevice *s)
+{
+	struct pcl816_private *devpriv = dev->private;
+	struct comedi_cmd *cmd = &s->async->cmd;
+
+	s->async->events |= COMEDI_CB_BLOCK;
+
+	s->async->cur_chan++;
+	if (s->async->cur_chan >= cmd->chanlist_len) {
+		s->async->cur_chan = 0;
+		devpriv->ai_act_scan++;
+		s->async->events |= COMEDI_CB_EOS;
+	}
+
+	if (cmd->stop_src == TRIG_COUNT &&
+	    devpriv->ai_act_scan >= cmd->stop_arg) {
+		/* all data sampled */
+		s->cancel(dev, s);
+		s->async->events |= COMEDI_CB_EOA;
+		comedi_event(dev, s);
+		return false;
+	}
+
+	return true;
+}
+
 static irqreturn_t interrupt_pcl816_ai_mode13_int(int irq, void *d)
 {
 	struct comedi_device *dev = d;
-	struct pcl816_private *devpriv = dev->private;
 	struct comedi_subdevice *s = dev->read_subdev;
-	struct comedi_cmd *cmd = &s->async->cmd;
 
 	if (pcl816_ai_eoc(dev, s, NULL, 0)) {
 		outb(0, dev->iobase + PCL816_CLRINT);	/* clear INT request */
@@ -293,18 +318,9 @@ static irqreturn_t interrupt_pcl816_ai_mode13_int(int irq, void *d)
 
 	outb(0, dev->iobase + PCL816_CLRINT);	/* clear INT request */
 
-	s->async->cur_chan++;
-	if (s->async->cur_chan >= cmd->chanlist_len) {
-		s->async->cur_chan = 0;
-		devpriv->ai_act_scan++;
-	}
+	if (!pcl816_ai_next_chan(dev, s))
+		return IRQ_HANDLED;
 
-	if (cmd->stop_src == TRIG_COUNT &&
-	    devpriv->ai_act_scan >= cmd->stop_arg) {
-		/* all data sampled */
-		s->cancel(dev, s);
-		s->async->events |= COMEDI_CB_EOA;
-	}
 	comedi_event(dev, s);
 	return IRQ_HANDLED;
 }
@@ -314,30 +330,13 @@ static void transfer_from_dma_buf(struct comedi_device *dev,
 				  unsigned short *ptr,
 				  unsigned int bufptr, unsigned int len)
 {
-	struct pcl816_private *devpriv = dev->private;
-	struct comedi_cmd *cmd = &s->async->cmd;
 	int i;
 
-	s->async->events = 0;
-
 	for (i = 0; i < len; i++) {
-
 		comedi_buf_put(s->async, ptr[bufptr++]);
 
-		s->async->cur_chan++;
-		if (s->async->cur_chan >= cmd->chanlist_len) {
-			s->async->cur_chan = 0;
-			devpriv->ai_act_scan++;
-		}
-
-		if (cmd->stop_src == TRIG_COUNT &&
-		    devpriv->ai_act_scan >= cmd->stop_arg) {
-			/* all data sampled */
-			s->cancel(dev, s);
-			s->async->events |= COMEDI_CB_EOA;
-			s->async->events |= COMEDI_CB_BLOCK;
-			break;
-		}
+		if (!pcl816_ai_next_chan(dev, s))
+			return;
 	}
 
 	comedi_event(dev, s);
-- 
1.8.5.2



More information about the devel mailing list