From: H Hartley Sweeten Date: Tue, 4 Nov 2014 17:55:11 +0000 (-0700) Subject: staging: comedi: addi_apci_3120: don't use timer 2 to count scans X-Git-Url: http://drtracing.org/?a=commitdiff_plain;h=4646364cc8e6346776828155ab817e254194df62;p=deliverable%2Flinux.git staging: comedi: addi_apci_3120: don't use timer 2 to count scans Timer 2 can be used to count the number of scans when the cmd->stop_src is TRIG_COUNT. Unfortunately that timer can also be used by userspace and this breaks the async command. Timer 2 also only works for counting the number of scans when DMA is not used. The number of scans is counted by the core using the private data membmer 'scans_done'. Use that to detect the End-Of-Scan for both DMA and none DMA modes. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c index ec488d163587..10ab6d89a6d5 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c @@ -293,35 +293,11 @@ static int apci3120_ai_cmd(struct comedi_device *dev, apci3120_timer_set_mode(dev, 0, APCI3120_TIMER_MODE2); apci3120_timer_write(dev, 0, divisor); - if (devpriv->use_dma) { + if (devpriv->use_dma) apci3120_setup_dma(dev, s); - } else { + else devpriv->mode |= APCI3120_MODE_EOS_IRQ_ENA; - if (cmd->stop_src == TRIG_COUNT) { - /* - * Timer 2 is used in MODE0 (hardware retriggerable - * one-shot) to count the number of scans. - * - * NOTE: not sure about the -2 value - */ - apci3120_timer_set_mode(dev, 2, APCI3120_TIMER_MODE0); - apci3120_timer_write(dev, 2, cmd->stop_arg - 2); - - apci3120_clr_timer2_interrupt(dev); - - apci3120_timer_enable(dev, 2, true); - - /* configure Timer 2 For counting EOS */ - devpriv->mode |= APCI3120_MODE_TIMER2_AS_COUNTER | - APCI3120_MODE_TIMER2_CLK_EOS | - APCI3120_MODE_TIMER2_IRQ_ENA; - - devpriv->b_Timer2Mode = APCI3120_COUNTER; - devpriv->b_Timer2Interrupt = 1; - } - } - /* set mode to enable acquisition */ outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG); @@ -343,7 +319,8 @@ static void apci3120_interrupt_dma(int irq, void *d) struct comedi_device *dev = d; struct apci3120_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; - struct comedi_cmd *cmd = &s->async->cmd; + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; struct apci3120_dmabuf *dmabuf; unsigned int samplesinbuf; @@ -373,13 +350,12 @@ static void apci3120_interrupt_dma(int irq, void *d) comedi_buf_write_samples(s, dmabuf->virt, samplesinbuf); if (!(cmd->flags & CMDF_WAKE_EOS)) - s->async->events |= COMEDI_CB_EOS; + async->events |= COMEDI_CB_EOS; } - if (cmd->stop_src == TRIG_COUNT && - s->async->scans_done >= cmd->stop_arg) { - s->async->events |= COMEDI_CB_EOA; + + if ((async->events & COMEDI_CB_CANCEL_MASK) || + (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg)) return; - } if (devpriv->use_double_buffer) { /* switch dma buffers for next interrupt */ @@ -395,7 +371,8 @@ static irqreturn_t apci3120_interrupt(int irq, void *d) struct comedi_device *dev = d; struct apci3120_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; - struct comedi_cmd *cmd = &s->async->cmd; + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; unsigned int status; unsigned int int_amcc; @@ -442,10 +419,6 @@ static irqreturn_t apci3120_interrupt(int irq, void *d) if (status & APCI3120_STATUS_TIMER2_INT) { switch (devpriv->b_Timer2Mode) { case APCI3120_COUNTER: - devpriv->mode &= ~APCI3120_MODE_EOS_IRQ_ENA; - outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG); - - s->async->events |= COMEDI_CB_EOA; break; case APCI3120_TIMER: @@ -478,6 +451,10 @@ static irqreturn_t apci3120_interrupt(int irq, void *d) /* do some data transfer */ apci3120_interrupt_dma(irq, d); } + + if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg) + async->events |= COMEDI_CB_EOA; + comedi_handle_events(dev, s); return IRQ_HANDLED;