summaryrefslogtreecommitdiff
path: root/drivers/staging/comedi/drivers/pcl812.c
diff options
context:
space:
mode:
authorH Hartley Sweeten <hsweeten@visionengravers.com>2014-03-04 11:29:36 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-03-06 17:06:12 -0800
commitdb702b7858abd08ecd99bec1544eb519801330aa (patch)
treea54c10ee8c1d2ae8777e7fd3502e3949fae276b3 /drivers/staging/comedi/drivers/pcl812.c
parent8429504a575ded74c6267361592879cedfb7b860 (diff)
staging: comedi: pcl812: factor out the common "next ai chan" code
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@visionengravers.com> Reviewed-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/comedi/drivers/pcl812.c')
-rw-r--r--drivers/staging/comedi/drivers/pcl812.c59
1 files changed, 31 insertions, 28 deletions
diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
index d84348d1d854..8fa4d47a0f9a 100644
--- a/drivers/staging/comedi/drivers/pcl812.c
+++ b/drivers/staging/comedi/drivers/pcl812.c
@@ -885,16 +885,40 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
return 0;
}
+static bool pcl812_ai_next_chan(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ struct pcl812_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_pcl812_ai_int(int irq, void *d)
{
struct comedi_device *dev = d;
- struct pcl812_private *devpriv = dev->private;
struct comedi_subdevice *s = dev->read_subdev;
struct comedi_cmd *cmd = &s->async->cmd;
unsigned int next_chan;
- s->async->events = 0;
-
if (pcl812_ai_eoc(dev, s, NULL, 0)) {
dev_dbg(dev->class_dev, "A/D cmd IRQ without DRDY!\n");
s->cancel(dev, s);
@@ -914,16 +938,8 @@ static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d)
outb(0, dev->iobase + PCL812_CLRINT); /* clear INT request */
- s->async->cur_chan = next_chan;
- if (next_chan == 0) { /* one scan done */
- 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;
- }
- }
+ if (!pcl812_ai_next_chan(dev, s))
+ return IRQ_HANDLED;
comedi_event(dev, s);
return IRQ_HANDLED;
@@ -934,27 +950,14 @@ static void transfer_from_dma_buf(struct comedi_device *dev,
unsigned short *ptr,
unsigned int bufptr, unsigned int len)
{
- struct pcl812_private *devpriv = dev->private;
- struct comedi_cmd *cmd = &s->async->cmd;
unsigned int i;
- s->async->events = 0;
for (i = len; i; i--) {
/* get one sample */
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;
- break;
- }
- }
+ if (!pcl812_ai_next_chan(dev, s))
+ return;
}
comedi_event(dev, s);