diff options
author | Ian Abbott | 2013-11-08 16:03:32 +0100 |
---|---|---|
committer | Greg Kroah-Hartman | 2013-11-12 01:16:44 +0100 |
commit | 5b13ed94a7d24fdc8abbac81e7e4d30ab22c6540 (patch) | |
tree | 0bfade11593603377f28228a2db2ed13cdaa7b7a /drivers/staging/comedi/comedi_fops.c | |
parent | staging: comedi: protect against detach during read operation (diff) | |
download | kernel-qcow2-linux-5b13ed94a7d24fdc8abbac81e7e4d30ab22c6540.tar.gz kernel-qcow2-linux-5b13ed94a7d24fdc8abbac81e7e4d30ab22c6540.tar.xz kernel-qcow2-linux-5b13ed94a7d24fdc8abbac81e7e4d30ab22c6540.zip |
staging: comedi: add a kref to comedi device
Add a `struct kref refcount` member to `struct comedi_device` to allow
safe destruction of the comedi device. Only free the comedi device via
the 'release' callback `kref_put()`. Currently, nothing calls
`kref_put()`, so the safe destruction is ineffective, but this will be
addressed by later patches.
Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/comedi/comedi_fops.c')
-rw-r--r-- | drivers/staging/comedi/comedi_fops.c | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index fa8da20df753..403324c895b1 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -89,12 +89,29 @@ static struct cdev comedi_cdev; static void comedi_device_init(struct comedi_device *dev) { + kref_init(&dev->refcount); spin_lock_init(&dev->spinlock); mutex_init(&dev->mutex); init_rwsem(&dev->attach_lock); dev->minor = -1; } +static void comedi_dev_kref_release(struct kref *kref) +{ + struct comedi_device *dev = + container_of(kref, struct comedi_device, refcount); + + mutex_destroy(&dev->mutex); + kfree(dev); +} + +int comedi_dev_put(struct comedi_device *dev) +{ + if (dev) + return kref_put(&dev->refcount, comedi_dev_kref_release); + return 1; +} + static void comedi_device_cleanup(struct comedi_device *dev) { struct module *driver_module = NULL; @@ -112,7 +129,6 @@ static void comedi_device_cleanup(struct comedi_device *dev) dev->use_count--; } mutex_unlock(&dev->mutex); - mutex_destroy(&dev->mutex); } static bool comedi_clear_board_dev(struct comedi_device *dev) @@ -148,7 +164,7 @@ static void comedi_free_board_dev(struct comedi_device *dev) MKDEV(COMEDI_MAJOR, dev->minor)); } comedi_device_cleanup(dev); - kfree(dev); + comedi_dev_put(dev); } } @@ -2494,7 +2510,7 @@ struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device) if (i == COMEDI_NUM_BOARD_MINORS) { mutex_unlock(&dev->mutex); comedi_device_cleanup(dev); - kfree(dev); + comedi_dev_put(dev); pr_err("comedi: error: ran out of minor numbers for board device files.\n"); return ERR_PTR(-EBUSY); } |