diff options
author | Ian Abbott <abbotti@mev.co.uk> | 2009-04-14 10:39:53 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-06-19 11:00:30 -0700 |
commit | e21de1a8e592898fb0426c40b11e19acc4b16fdf (patch) | |
tree | acae6c7a7f4b940b22be6a9cc8f542d0fa3650ff /drivers/staging/comedi | |
parent | a71f18d2a1ca1b3a0e1e46f3c7259829d4d33f47 (diff) |
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.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 29cc5a5151a..495f802c39a 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; } } |