staging: comedi: add a kref to comedi device
authorIan Abbott <abbotti@mev.co.uk>
Fri, 8 Nov 2013 15:03:32 +0000 (15:03 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 12 Nov 2013 00:16:44 +0000 (16:16 -0800)
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>
drivers/staging/comedi/comedi_fops.c
drivers/staging/comedi/comedidev.h

index fa8da20df7531e53b3798ca2425bb64e142e5480..403324c895b13af2e5baa07cd43194396f0497df 100644 (file)
@@ -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);
        }
index 05cc8dbcd515f513f06e6ad74fdb45b2f962fb65..08652dfa8c031db7a6ebc3b6243c8ed7919a83d9 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/mutex.h>
 #include <linux/spinlock_types.h>
 #include <linux/rwsem.h>
+#include <linux/kref.h>
 
 #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;