Remove a possible deadlock while waiting to write the analog output data.

The data transfer rate for every D/A data write in this driver is 2.2us.
Wait up to 10us for the board to be ready then and return -ETIME.

Signed-off-by: H Hartley Sweeten <hswee...@visionengravers.com>
Cc: Ian Abbott <abbo...@mev.co.uk>
Cc: Greg Kroah-Hartman <gre...@linuxfoundation.org>
---
 drivers/staging/comedi/drivers/adl_pci6208.c | 25 +++++++++++++++++++++----
 1 file changed, 21 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c 
b/drivers/staging/comedi/drivers/adl_pci6208.c
index 9150582..059d7ea 100644
--- a/drivers/staging/comedi/drivers/adl_pci6208.c
+++ b/drivers/staging/comedi/drivers/adl_pci6208.c
@@ -39,6 +39,7 @@ References:
 */
 
 #include <linux/module.h>
+#include <linux/delay.h>
 #include <linux/pci.h>
 
 #include "../comedidev.h"
@@ -82,6 +83,21 @@ struct pci6208_private {
        unsigned int ao_readback[PCI6208_MAX_AO_CHANNELS];
 };
 
+static int pci6208_ao_wait_for_data_send(struct comedi_device *dev,
+                                        unsigned int timeout)
+{
+       unsigned int status;
+
+       while (timeout--) {
+               status = inw(dev->iobase + PCI6208_AO_STATUS);
+               if ((status & PCI6208_AO_STATUS_DATA_SEND) == 0)
+                       return 0;
+               udelay(1);
+       }
+
+       return -ETIME;
+}
+
 static int pci6208_ao_winsn(struct comedi_device *dev,
                            struct comedi_subdevice *s,
                            struct comedi_insn *insn, unsigned int *data)
@@ -90,15 +106,16 @@ static int pci6208_ao_winsn(struct comedi_device *dev,
        int chan = CR_CHAN(insn->chanspec);
        unsigned int invert = 1 << (16 - 1);
        unsigned int val = devpriv->ao_readback[chan];
-       unsigned short status;
+       int ret;
        int i;
 
        for (i = 0; i < insn->n; i++) {
                val = data[i];
 
-               do {
-                       status = inw(dev->iobase + PCI6208_AO_STATUS);
-               } while (status & PCI6208_AO_STATUS_DATA_SEND);
+               /* D/A transfer rate is 2.2us, wait up to 10us */
+               ret = pci6208_ao_wait_for_data_send(dev, 10);
+               if (ret)
+                       return ret;
 
                outw(val ^ invert, dev->iobase + PCI6208_AO_CONTROL(chan));
        }
-- 
1.8.3.2

_______________________________________________
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

Reply via email to