Skip to content

Commit

Permalink
staging: comedi: COMEDI_CANCEL ioctl should wake up read/write
Browse files Browse the repository at this point in the history
Comedi devices can do blocking read() or write() (or poll()) if an
asynchronous command has been set up, blocking for data (for read()) or
buffer space (for write()).  Various events associated with the
asynchronous command will wake up the blocked reader or writer (or
poller).  It is also possible to force the asynchronous command to
terminate by issuing a `COMEDI_CANCEL` ioctl.  That shuts down the
asynchronous command, but does not currently wake up the blocked reader
or writer (or poller).  If the blocked task could be woken up, it would
see that the command is no longer active and return.  The caller of the
`COMEDI_CANCEL` ioctl could attempt to wake up the blocked task by
sending a signal, but that's a nasty workaround.

Change `do_cancel_ioctl()` to wake up the wait queue after it returns
from `do_cancel()`.  `do_cancel()` can propagate an error return value
from the low-level comedi driver's cancel routine, but it always shuts
the command down regardless, so `do_cancel_ioctl()` can wake up he wait
queue regardless of the return value from `do_cancel()`.

Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Ian Abbott authored and Greg Kroah-Hartman committed Jul 23, 2013
1 parent 3b2f64d commit 69acbaa
Showing 1 changed file with 6 additions and 1 deletion.
7 changes: 6 additions & 1 deletion drivers/staging/comedi/comedi_fops.c
Original file line number Diff line number Diff line change
Expand Up @@ -1705,6 +1705,7 @@ static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg,
void *file)
{
struct comedi_subdevice *s;
int ret;

if (arg >= dev->n_subdevices)
return -EINVAL;
Expand All @@ -1721,7 +1722,11 @@ static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg,
if (s->busy != file)
return -EBUSY;

return do_cancel(dev, s);
ret = do_cancel(dev, s);
if (comedi_get_subdevice_runflags(s) & SRF_USER)
wake_up_interruptible(&s->async->wait_head);

return ret;
}

/*
Expand Down

0 comments on commit 69acbaa

Please sign in to comment.