[PATCH 065/342] Staging: comedi: pcl818: Tidy up AI command after channel dropout or similar error.

Greg Kroah-Hartman gregkh at suse.de
Fri Jun 19 18:04:49 UTC 2009


From: Ian Abbott <abbotti at mev.co.uk>

It was causing subsequent commands to fail with -EBUSY.

From: Ian Abbott <abbotti at mev.co.uk>
Signed-off-by: Frank Mori Hess <fmhess at users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
---
 drivers/staging/comedi/drivers/pcl818.c |   51 +++++++++++++++++--------------
 1 files changed, 28 insertions(+), 23 deletions(-)

diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
index 29cc5a5..495f802 100644
--- a/drivers/staging/comedi/drivers/pcl818.c
+++ b/drivers/staging/comedi/drivers/pcl818.c
@@ -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;
 		}
 	}
-- 
1.6.3.2




More information about the devel mailing list