Staging: comedi: pcl818: Tidy up AI command after channel dropout or similar error.
authorIan Abbott <abbotti@mev.co.uk>
Tue, 14 Apr 2009 14:39:53 +0000 (10:39 -0400)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 19 Jun 2009 18:00:30 +0000 (11:00 -0700)
It was causing subsequent commands to fail with -EBUSY.

From: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Frank Mori Hess <fmhess@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/comedi/drivers/pcl818.c

index 29cc5a5..495f802 100644 (file)
@@ -820,6 +820,27 @@ static irqreturn_t interrupt_pcl818(int irq, void *d)
        }
        /* rt_printk("I\n"); */
 
+       if (devpriv->irq_blocked && devpriv->irq_was_now_closed) {
+               if ((devpriv->neverending_ai || (!devpriv->neverending_ai &&
+                                               devpriv->ai_act_scan > 0)) &&
+                               (devpriv->ai_mode == INT_TYPE_AI1_DMA ||
+                                devpriv->ai_mode == INT_TYPE_AI3_DMA)) {
+                       /* The cleanup from ai_cancel() has been delayed
+                          until now because the card doesn't seem to like
+                          being reprogrammed while a DMA transfer is in
+                          progress.
+                        */
+                       struct comedi_subdevice *s = dev->subdevices + 0;
+                       devpriv->ai_act_scan = 0;
+                       devpriv->neverending_ai = 0;
+                       pcl818_ai_cancel(dev, s);
+               }
+
+               outb(0, dev->iobase + PCL818_CLRINT);   /* clear INT request */
+
+               return IRQ_HANDLED;
+       }
+
        switch (devpriv->ai_mode) {
        case INT_TYPE_AI1_DMA:
        case INT_TYPE_AI3_DMA:
@@ -843,25 +864,6 @@ static irqreturn_t interrupt_pcl818(int irq, void *d)
 
        if ((!dev->irq) || (!devpriv->irq_free) || (!devpriv->irq_blocked)
                || (!devpriv->ai_mode)) {
-               if (devpriv->irq_was_now_closed) {
-                       if (devpriv->neverending_ai &&
-                               (devpriv->ai_mode == INT_TYPE_AI1_DMA
-                                       || devpriv->ai_mode ==
-                                       INT_TYPE_AI3_DMA)) {
-                               /* we had neverending ai but ai_cancel() has been called
-                                  the cleanup from ai_cancel() has been delayed until know
-                                  because the card doesn't seem to like being reprogrammed
-                                  while a DMA transfer is in progress
-                                */
-                               struct comedi_subdevice *s = dev->subdevices + 0;
-                               devpriv->ai_mode = devpriv->irq_was_now_closed;
-                               devpriv->irq_was_now_closed = 0;
-                               devpriv->neverending_ai = 0;
-                               pcl818_ai_cancel(dev, s);
-                       }
-                       devpriv->irq_was_now_closed = 0;
-                       return IRQ_HANDLED;
-               }
                comedi_error(dev, "bad IRQ!");
                return IRQ_NONE;
        }
@@ -1453,10 +1455,9 @@ static int pcl818_ai_cancel(struct comedi_device * dev, struct comedi_subdevice
 {
        if (devpriv->irq_blocked > 0) {
                rt_printk("pcl818_ai_cancel()\n");
-               devpriv->irq_was_now_closed = devpriv->ai_mode;
-               devpriv->ai_mode = 0;
+               devpriv->irq_was_now_closed = 1;
 
-               switch (devpriv->irq_was_now_closed) {
+               switch (devpriv->ai_mode) {
 #ifdef unused
                case INT_TYPE_AI1_DMA_RTC:
                case INT_TYPE_AI3_DMA_RTC:
@@ -1465,7 +1466,9 @@ static int pcl818_ai_cancel(struct comedi_device * dev, struct comedi_subdevice
 #endif
                case INT_TYPE_AI1_DMA:
                case INT_TYPE_AI3_DMA:
-                       if (devpriv->neverending_ai) {
+                       if (devpriv->neverending_ai ||
+                                       (!devpriv->neverending_ai &&
+                                        devpriv->ai_act_scan > 0)) {
                                /* wait for running dma transfer to end, do cleanup in interrupt */
                                goto end;
                        }
@@ -1494,6 +1497,8 @@ static int pcl818_ai_cancel(struct comedi_device * dev, struct comedi_subdevice
                        devpriv->irq_blocked = 0;
                        devpriv->last_int_sub = s;
                        devpriv->neverending_ai = 0;
+                       devpriv->ai_mode = 0;
+                       devpriv->irq_was_now_closed = 0;
                        break;
                }
        }