From 5b13ed94a7d24fdc8abbac81e7e4d30ab22c6540 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 8 Nov 2013 15:03:32 +0000 Subject: [PATCH] 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 Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 22 +++++++++++++++++++--- drivers/staging/comedi/comedidev.h | 2 ++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index fa8da20..403324c 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); } diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 05cc8db..08652df 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -23,6 +23,7 @@ #include #include #include +#include #include "comedi.h" @@ -187,6 +188,7 @@ struct comedi_device { spinlock_t spinlock; struct mutex mutex; struct rw_semaphore attach_lock; + struct kref refcount; int n_subdevices; struct comedi_subdevice *subdevices; -- 2.7.4