]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
staging: comedi: usbduxsigma: don't clobber ai_timer in command test
authorIan Abbott <abbotti@mev.co.uk>
Wed, 16 Sep 2015 13:17:14 +0000 (14:17 +0100)
committerLuis Henriques <luis.henriques@canonical.com>
Mon, 28 Sep 2015 09:21:33 +0000 (10:21 +0100)
commit 423b24c37dd5794a674c74b0ed56392003a69891 upstream.

`devpriv->ai_timer` is used while an asynchronous command is running on
the AI subdevice.  It also gets modified by the subdevice's `cmdtest`
handler for checking new asynchronous commands
(`usbduxsigma_ai_cmdtest()`), which is not correct as it's allowed to
check new commands while an old command is still running.  Fix it by
moving the code which sets up `devpriv->ai_timer` and
`devpriv->ai_interval` into the subdevice's `cmd` handler,
`usbduxsigma_ai_cmd()`.

** This backported patch also moves the code that sets up
`devpriv->ai_sample_count` from `usbduxsigma_ai_cmdtest()` to
`usbduxsigma_ai_cmd()` for the same reason as above. (This was not
needed in the upstream commit.) **

Note that the removed code in `usbduxsigma_ai_cmdtest()` checked that
`devpriv->ai_timer` did not end up less than than 1, but that could not
happen because `cmd->scan_begin_arg` had already been checked to be at
least the minimum required value (at least when `cmd->scan_begin_src ==
TRIG_TIMER`, which had also been checked to be the case).

Fixes: b986be8527c7 ("staging: comedi: usbduxsigma: tidy up analog input command support)
Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Luis Henriques <luis.henriques@canonical.com>
drivers/staging/comedi/drivers/usbduxsigma.c

index ccc3ef7ba55c479f47d901bf7e3f4520e3552512..e2c0c54e09109311b17ef24e9c927f2cbe5ee2fa 100644 (file)
@@ -572,35 +572,6 @@ static int usbduxsigma_ai_cmdtest(struct comedi_device *dev,
        if (err)
                return 3;
 
-       /* Step 4: fix up any arguments */
-
-       if (high_speed) {
-               /*
-                * every 2 channels get a time window of 125us. Thus, if we
-                * sample all 16 channels we need 1ms. If we sample only one
-                * channel we need only 125us
-                */
-               devpriv->ai_interval = interval;
-               devpriv->ai_timer = cmd->scan_begin_arg / (125000 * interval);
-       } else {
-               /* interval always 1ms */
-               devpriv->ai_interval = 1;
-               devpriv->ai_timer = cmd->scan_begin_arg / 1000000;
-       }
-       if (devpriv->ai_timer < 1)
-               err |= -EINVAL;
-
-       if (cmd->stop_src == TRIG_COUNT) {
-               /* data arrives as one packet */
-               devpriv->ai_sample_count = cmd->stop_arg;
-       } else {
-               /* continuous acquisition */
-               devpriv->ai_sample_count = 0;
-       }
-
-       if (err)
-               return 4;
-
        return 0;
 }
 
@@ -700,6 +671,30 @@ static int usbduxsigma_ai_cmd(struct comedi_device *dev,
 
        /* set current channel of the running acquisition to zero */
        s->async->cur_chan = 0;
+
+       if (devpriv->high_speed) {
+               /*
+                * every 2 channels get a time window of 125us. Thus, if we
+                * sample all 16 channels we need 1ms. If we sample only one
+                * channel we need only 125us
+                */
+               unsigned int interval = usbduxsigma_chans_to_interval(len);
+
+               devpriv->ai_interval = interval;
+               devpriv->ai_timer = cmd->scan_begin_arg / (125000 * interval);
+       } else {
+               /* interval always 1ms */
+               devpriv->ai_interval = 1;
+               devpriv->ai_timer = cmd->scan_begin_arg / 1000000;
+       }
+       if (cmd->stop_src == TRIG_COUNT) {
+               /* data arrives as one packet */
+               devpriv->ai_sample_count = cmd->stop_arg;
+       } else {
+               /* continuous acquisition */
+               devpriv->ai_sample_count = 0;
+       }
+
        for (i = 0; i < len; i++) {
                unsigned int chan  = CR_CHAN(cmd->chanlist[i]);