The comedi (*insn_read) functions are supposed to do simple one-shot reading of an analog input channel. Currently this driver enables interrupts and uses wait_for_completion_interruptible() to allow the interrupt routine to let the analog input (*insn_read) know that the end-of-conversion has occured. Simplify the function by using the comedi_timeout() helper to check the aux status register to see when the conversion is finished. Signed-off-by: H Hartley Sweeten <hsweeten@xxxxxxxxxxxxxxxxxxx> Cc: Ian Abbott <abbotti@xxxxxxxxx> Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- drivers/staging/comedi/drivers/quatech_daqp_cs.c | 59 +++++++++++------------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c index de28224..dbb8ffc 100644 --- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -48,8 +48,6 @@ Devices: [Quatech] DAQP-208 (daqp), DAQP-308 */ #include <linux/module.h> -#include <linux/semaphore.h> -#include <linux/completion.h> #include "../comedi_pcmcia.h" @@ -59,8 +57,6 @@ struct daqp_private { int stop; enum { semaphore, buffer } interrupt_mode; - - struct completion eos; }; /* The DAQP communicates with the system through a 16 byte I/O window. */ @@ -175,15 +171,6 @@ static int daqp_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) return 0; } -/* Interrupt handler - * - * Operates in one of two modes. If devpriv->interrupt_mode is - * 'semaphore', just signal the devpriv->eos completion and return - * (one-shot mode). Otherwise (continuous mode), read data in from - * the card, transfer it to the buffer provided by the higher-level - * comedi kernel module, and signal various comedi callback routines, - * which run pretty quick. - */ static enum irqreturn daqp_interrupt(int irq, void *dev_id) { struct comedi_device *dev = dev_id; @@ -198,7 +185,6 @@ static enum irqreturn daqp_interrupt(int irq, void *dev_id) switch (devpriv->interrupt_mode) { case semaphore: - complete(&devpriv->eos); break; case buffer: @@ -270,15 +256,27 @@ static void daqp_ai_set_scanlist(struct comedi_device *dev, } } -/* One-shot analog data acquisition routine */ +static int daqp_ai_eos(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned long context) +{ + unsigned int status; + + status = inb(dev->iobase + DAQP_AUX); + if (status & DAQP_AUX_CONVERSION) + return 0; + return -EBUSY; +} static int daqp_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct daqp_private *devpriv = dev->private; + int ret = 0; int i; - int v; int counter = 10000; if (devpriv->stop) @@ -296,12 +294,8 @@ static int daqp_ai_insn_read(struct comedi_device *dev, outb(DAQP_COMMAND_RSTF, dev->iobase + DAQP_COMMAND); - /* Set trigger */ - - v = DAQP_CONTROL_TRIGGER_ONESHOT | DAQP_CONTROL_TRIGGER_INTERNAL - | DAQP_CONTROL_PACER_100kHz | DAQP_CONTROL_EOS_INT_ENABLE; - - outb(v, dev->iobase + DAQP_CONTROL); + /* one-shot internal trigger, no pacer, no interrupts */ + outb(0, dev->iobase + DAQP_CONTROL); /* Reset any pending interrupts (my card has a tendency to require * require multiple reads on the status register to achieve this) @@ -316,25 +310,28 @@ static int daqp_ai_insn_read(struct comedi_device *dev, return -1; } - init_completion(&devpriv->eos); - devpriv->interrupt_mode = semaphore; - for (i = 0; i < insn->n; i++) { /* Start conversion */ outb(DAQP_COMMAND_ARM | DAQP_COMMAND_FIFO_DATA, dev->iobase + DAQP_COMMAND); - /* Wait for interrupt service routine to unblock completion */ - /* Maybe could use a timeout here, but it's interruptible */ - if (wait_for_completion_interruptible(&devpriv->eos)) - return -EINTR; + ret = comedi_timeout(dev, s, insn, daqp_ai_eos, 0); + if (ret) + break; + + /* clear the status event flags */ + inb(dev->iobase + DAQP_STATUS); data[i] = inb(dev->iobase + DAQP_FIFO); data[i] |= inb(dev->iobase + DAQP_FIFO) << 8; data[i] ^= 0x8000; } - return insn->n; + /* stop any conversions and clear the status event flags */ + outb(DAQP_COMMAND_STOP, dev->iobase + DAQP_COMMAND); + inb(dev->iobase + DAQP_STATUS); + + return ret ? ret : insn->n; } /* This function converts ns nanoseconds to a counter value suitable -- 2.5.1 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel