staging:iio:core set the iio_dev.info pointer to null on unregister under lock.
authorJonathan Cameron <jic23@kernel.org>
Wed, 15 Feb 2012 19:48:00 +0000 (19:48 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 24 Feb 2012 20:10:02 +0000 (12:10 -0800)
This prevents use of provider callbacks after it has been unregistered.
Note that all code using this that can be called from a consumer *must*
check the pointer before using and hold the info_exist_lock throughout
the usage of the callbacks in info.

Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/iio/iio.h
drivers/staging/iio/industrialio-core.c

index be6ced3..478dbe5 100644 (file)
@@ -310,6 +310,7 @@ struct iio_buffer_setup_ops {
  * @chan_attr_group:   [INTERN] group for all attrs in base directory
  * @name:              [DRIVER] name of the device.
  * @info:              [DRIVER] callbacks and constant info from driver
+ * @info_exist_lock:   [INTERN] lock to prevent use during removal
  * @chrdev:            [INTERN] associated character device
  * @groups:            [INTERN] attribute groups
  * @groupcounter:      [INTERN] index of next attribute group
@@ -340,6 +341,7 @@ struct iio_dev {
        struct attribute_group          chan_attr_group;
        const char                      *name;
        const struct iio_info           *info;
+       struct mutex                    info_exist_lock;
        const struct iio_buffer_setup_ops       *setup_ops;
        struct cdev                     chrdev;
 #define IIO_MAX_GROUPS 6
index e4824fe..3a2d080 100644 (file)
@@ -594,6 +594,7 @@ struct iio_dev *iio_allocate_device(int sizeof_priv)
                device_initialize(&dev->dev);
                dev_set_drvdata(&dev->dev, (void *)dev);
                mutex_init(&dev->mlock);
+               mutex_init(&dev->info_exist_lock);
 
                dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL);
                if (dev->id < 0) {
@@ -718,6 +719,9 @@ EXPORT_SYMBOL(iio_device_register);
 
 void iio_device_unregister(struct iio_dev *indio_dev)
 {
+       mutex_lock(&indio_dev->info_exist_lock);
+       indio_dev->info = NULL;
+       mutex_unlock(&indio_dev->info_exist_lock);
        device_unregister(&indio_dev->dev);
 }
 EXPORT_SYMBOL(iio_device_unregister);