From d19db51a0eeb659cd924a9d08b20a2ed4ee46b15 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 8 Nov 2013 15:03:28 +0000 Subject: staging: comedi: cancel commands before detaching device The comedi core module's handling of the `COMEDI_DEVCONFIG` ioctl will not allow a device to be detached if it is busy. However, comedi devices can also be auto-detached due to a removal of a hardware device. One of the things we should do in that case is cancel any asynchronous commands that are running. Add a new function `comedi_device_cancel_all()` to do that and call it from `comedi_device_detach()`. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 15 +++++++++++++++ drivers/staging/comedi/comedi_internal.h | 1 + drivers/staging/comedi/drivers.c | 1 + 3 files changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 9c85f01e847b..eafa18efdeea 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -584,6 +584,21 @@ static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s) return ret; } +void comedi_device_cancel_all(struct comedi_device *dev) +{ + struct comedi_subdevice *s; + int i; + + if (!dev->attached) + return; + + for (i = 0; i < dev->n_subdevices; i++) { + s = &dev->subdevices[i]; + if (s->async) + do_cancel(dev, s); + } +} + static int is_device_busy(struct comedi_device *dev) { struct comedi_subdevice *s; diff --git a/drivers/staging/comedi/comedi_internal.h b/drivers/staging/comedi/comedi_internal.h index fda1a7ba0e16..151693b11383 100644 --- a/drivers/staging/comedi/comedi_internal.h +++ b/drivers/staging/comedi/comedi_internal.h @@ -17,6 +17,7 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, unsigned long new_size); void comedi_buf_reset(struct comedi_async *async); unsigned int comedi_buf_write_n_allocated(struct comedi_async *async); +void comedi_device_cancel_all(struct comedi_device *dev); extern unsigned int comedi_default_buf_size_kb; extern unsigned int comedi_default_buf_maxsize_kb; diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 1f44f2939f6a..4f727731a72d 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -133,6 +133,7 @@ static void comedi_device_detach_cleanup(struct comedi_device *dev) void comedi_device_detach(struct comedi_device *dev) { + comedi_device_cancel_all(dev); down_write(&dev->attach_lock); dev->attached = false; if (dev->driver) -- cgit v1.2.3-55-g7522