summaryrefslogtreecommitdiffstats
path: root/drivers/staging/comedi
diff options
context:
space:
mode:
authorIan Abbott2009-04-14 16:39:53 +0200
committerGreg Kroah-Hartman2009-06-19 20:00:30 +0200
commite21de1a8e592898fb0426c40b11e19acc4b16fdf (patch)
treeacae6c7a7f4b940b22be6a9cc8f542d0fa3650ff /drivers/staging/comedi
parentStaging: comedi: pcl818: Fix option handling for FIFO mode (hopefully!). (diff)
downloadkernel-qcow2-linux-e21de1a8e592898fb0426c40b11e19acc4b16fdf.tar.gz
kernel-qcow2-linux-e21de1a8e592898fb0426c40b11e19acc4b16fdf.tar.xz
kernel-qcow2-linux-e21de1a8e592898fb0426c40b11e19acc4b16fdf.zip
Staging: comedi: pcl818: Tidy up AI command after channel dropout or similar error.
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>
Diffstat (limited to 'drivers/staging/comedi')
-rw-r--r--drivers/staging/comedi/drivers/pcl818.c51
1 files changed, 28 insertions, 23 deletions
diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
index 29cc5a5151a6..495f802c39ac 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;
}
}