summaryrefslogtreecommitdiffstats
path: root/drivers/staging/comedi/kcomedilib
diff options
context:
space:
mode:
authorIan Abbott2013-11-08 16:03:38 +0100
committerGreg Kroah-Hartman2013-11-12 01:16:44 +0100
commit799a66ba36cb51330c53c024dffc6ddb68545c9c (patch)
tree5063dbb4e154d60745dc7a4a37712b62b21b0333 /drivers/staging/comedi/kcomedilib
parentstaging: comedi: use refcount in sysfs attribute handlers (diff)
downloadkernel-qcow2-linux-799a66ba36cb51330c53c024dffc6ddb68545c9c.tar.gz
kernel-qcow2-linux-799a66ba36cb51330c53c024dffc6ddb68545c9c.tar.xz
kernel-qcow2-linux-799a66ba36cb51330c53c024dffc6ddb68545c9c.zip
staging: comedi: kcomedilib: increment reference while device in use
Low-level comedi drivers that use the "kcomedilib" module (currently only the "comedi_bond" driver) call `comedi_open()` to "open" another comedi device (not as a file) and `comedi_close()` to "close" it. (Note: these are the functions exported by the "kcomedilib" module, not the identically named, statically linked functions in the core "comedi" module.) In `comedi_open()`, call `comedi_dev_get_from_minor()` instead of `comedi_dev_from_minor()` to get the pointer to the `struct comedi_device` being "opened". This increments its reference count to prevent it being freed. Call `comedi_dev_put()` if `comedi_open()` returns `NULL`, and also call it from `comedi_close()`. This decrements the reference count. Note that although we now protect against the `struct comedi_device` being freed, we do not yet protect against it being "detached" while it is being used. This will be addressed by a later patch. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/comedi/kcomedilib')
-rw-r--r--drivers/staging/comedi/kcomedilib/kcomedilib_main.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
index cd60677a3ed2..b3a06f2dbad6 100644
--- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
+++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
@@ -35,7 +35,7 @@ MODULE_LICENSE("GPL");
struct comedi_device *comedi_open(const char *filename)
{
- struct comedi_device *dev;
+ struct comedi_device *dev, *retval = NULL;
unsigned int minor;
if (strncmp(filename, "/dev/comedi", 11) != 0)
@@ -46,15 +46,19 @@ struct comedi_device *comedi_open(const char *filename)
if (minor >= COMEDI_NUM_BOARD_MINORS)
return NULL;
- dev = comedi_dev_from_minor(minor);
-
- if (!dev || !dev->attached)
+ dev = comedi_dev_get_from_minor(minor);
+ if (!dev)
return NULL;
- if (!try_module_get(dev->driver->module))
- return NULL;
+ if (dev->attached && try_module_get(dev->driver->module))
+ retval = dev;
+ else
+ retval = NULL;
+
+ if (retval == NULL)
+ comedi_dev_put(dev);
- return dev;
+ return retval;
}
EXPORT_SYMBOL_GPL(comedi_open);
@@ -63,6 +67,7 @@ int comedi_close(struct comedi_device *d)
struct comedi_device *dev = (struct comedi_device *)d;
module_put(dev->driver->module);
+ comedi_dev_put(dev);
return 0;
}