diff options
author | Jonathan Cameron <jic23@kernel.org> | 2012-02-15 14:48:00 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-02-24 15:10:02 -0500 |
commit | ac917a81117ce0286847666b55dd265f6cda8383 (patch) | |
tree | ea5052ebeb55cc59fc0f3fa28df1560ddfa487f3 /drivers/staging/iio | |
parent | 08cd9ef4eca0b53cdae190b718e4945408c7d3b8 (diff) |
staging:iio:core set the iio_dev.info pointer to null on unregister under lock.
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>
Diffstat (limited to 'drivers/staging/iio')
-rw-r--r-- | drivers/staging/iio/iio.h | 2 | ||||
-rw-r--r-- | drivers/staging/iio/industrialio-core.c | 4 |
2 files changed, 6 insertions, 0 deletions
diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h index be6ced31f65..478dbe5924c 100644 --- a/drivers/staging/iio/iio.h +++ b/drivers/staging/iio/iio.h | |||
@@ -310,6 +310,7 @@ struct iio_buffer_setup_ops { | |||
310 | * @chan_attr_group: [INTERN] group for all attrs in base directory | 310 | * @chan_attr_group: [INTERN] group for all attrs in base directory |
311 | * @name: [DRIVER] name of the device. | 311 | * @name: [DRIVER] name of the device. |
312 | * @info: [DRIVER] callbacks and constant info from driver | 312 | * @info: [DRIVER] callbacks and constant info from driver |
313 | * @info_exist_lock: [INTERN] lock to prevent use during removal | ||
313 | * @chrdev: [INTERN] associated character device | 314 | * @chrdev: [INTERN] associated character device |
314 | * @groups: [INTERN] attribute groups | 315 | * @groups: [INTERN] attribute groups |
315 | * @groupcounter: [INTERN] index of next attribute group | 316 | * @groupcounter: [INTERN] index of next attribute group |
@@ -340,6 +341,7 @@ struct iio_dev { | |||
340 | struct attribute_group chan_attr_group; | 341 | struct attribute_group chan_attr_group; |
341 | const char *name; | 342 | const char *name; |
342 | const struct iio_info *info; | 343 | const struct iio_info *info; |
344 | struct mutex info_exist_lock; | ||
343 | const struct iio_buffer_setup_ops *setup_ops; | 345 | const struct iio_buffer_setup_ops *setup_ops; |
344 | struct cdev chrdev; | 346 | struct cdev chrdev; |
345 | #define IIO_MAX_GROUPS 6 | 347 | #define IIO_MAX_GROUPS 6 |
diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c index e4824fe8b40..3a2d0802662 100644 --- a/drivers/staging/iio/industrialio-core.c +++ b/drivers/staging/iio/industrialio-core.c | |||
@@ -594,6 +594,7 @@ struct iio_dev *iio_allocate_device(int sizeof_priv) | |||
594 | device_initialize(&dev->dev); | 594 | device_initialize(&dev->dev); |
595 | dev_set_drvdata(&dev->dev, (void *)dev); | 595 | dev_set_drvdata(&dev->dev, (void *)dev); |
596 | mutex_init(&dev->mlock); | 596 | mutex_init(&dev->mlock); |
597 | mutex_init(&dev->info_exist_lock); | ||
597 | 598 | ||
598 | dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL); | 599 | dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL); |
599 | if (dev->id < 0) { | 600 | if (dev->id < 0) { |
@@ -718,6 +719,9 @@ EXPORT_SYMBOL(iio_device_register); | |||
718 | 719 | ||
719 | void iio_device_unregister(struct iio_dev *indio_dev) | 720 | void iio_device_unregister(struct iio_dev *indio_dev) |
720 | { | 721 | { |
722 | mutex_lock(&indio_dev->info_exist_lock); | ||
723 | indio_dev->info = NULL; | ||
724 | mutex_unlock(&indio_dev->info_exist_lock); | ||
721 | device_unregister(&indio_dev->dev); | 725 | device_unregister(&indio_dev->dev); |
722 | } | 726 | } |
723 | EXPORT_SYMBOL(iio_device_unregister); | 727 | EXPORT_SYMBOL(iio_device_unregister); |