From e21de1a8e592898fb0426c40b11e19acc4b16fdf Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 14 Apr 2009 10:39:53 -0400 Subject: [PATCH] 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 Signed-off-by: Frank Mori Hess Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/pcl818.c | 51 ++++++++++++++++++--------------- 1 file 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; } } -- 2.11.4.GIT