Commit 2bc9cd66 authored by Vincent Whitchurch's avatar Vincent Whitchurch Committed by Jonathan Cameron

iio: Use per-device lockdep class for mlock

If an IIO driver uses callbacks from another IIO driver and calls
iio_channel_start_all_cb() from one of its buffer setup ops, then
lockdep complains due to the lock nesting, as in the below example with
lmp91000.

Since the locks are being taken on different IIO devices, there is no
actual deadlock.  Fix the warning by telling lockdep to use a different
class for each iio_device.

 ============================================
 WARNING: possible recursive locking detected
 --------------------------------------------
 python3/23 is trying to acquire lock:
 (&indio_dev->mlock){+.+.}-{3:3}, at: iio_update_buffers

 but task is already holding lock:
 (&indio_dev->mlock){+.+.}-{3:3}, at: enable_store

 other info that might help us debug this:
  Possible unsafe locking scenario:

        CPU0
        ----
   lock(&indio_dev->mlock);
   lock(&indio_dev->mlock);

  *** DEADLOCK ***

  May be due to missing lock nesting notation

 5 locks held by python3/23:
  #0: (sb_writers#5){.+.+}-{0:0}, at: ksys_write
  #1: (&of->mutex){+.+.}-{3:3}, at: kernfs_fop_write_iter
  #2: (kn->active#14){.+.+}-{0:0}, at: kernfs_fop_write_iter
  #3: (&indio_dev->mlock){+.+.}-{3:3}, at: enable_store
  #4: (&iio_dev_opaque->info_exist_lock){+.+.}-{3:3}, at: iio_update_buffers

 Call Trace:
  __mutex_lock
  iio_update_buffers
  iio_channel_start_all_cb
  lmp91000_buffer_postenable
  __iio_update_buffers
  enable_store

Fixes: 67e17300 ("iio: potentiostat: add LMP91000 support")
Signed-off-by: default avatarVincent Whitchurch <vincent.whitchurch@axis.com>
Reviewed-by: default avatarAndy Shevchenko <andy.shevchenko@gmail.com>
Link: https://lore.kernel.org/r/20220829091840.2791846-1-vincent.whitchurch@axis.comSigned-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent 0fea1007
...@@ -1626,6 +1626,8 @@ static void iio_dev_release(struct device *device) ...@@ -1626,6 +1626,8 @@ static void iio_dev_release(struct device *device)
iio_device_detach_buffers(indio_dev); iio_device_detach_buffers(indio_dev);
lockdep_unregister_key(&iio_dev_opaque->mlock_key);
ida_free(&iio_ida, iio_dev_opaque->id); ida_free(&iio_ida, iio_dev_opaque->id);
kfree(iio_dev_opaque); kfree(iio_dev_opaque);
} }
...@@ -1685,6 +1687,9 @@ struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv) ...@@ -1685,6 +1687,9 @@ struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv)
INIT_LIST_HEAD(&iio_dev_opaque->buffer_list); INIT_LIST_HEAD(&iio_dev_opaque->buffer_list);
INIT_LIST_HEAD(&iio_dev_opaque->ioctl_handlers); INIT_LIST_HEAD(&iio_dev_opaque->ioctl_handlers);
lockdep_register_key(&iio_dev_opaque->mlock_key);
lockdep_set_class(&indio_dev->mlock, &iio_dev_opaque->mlock_key);
return indio_dev; return indio_dev;
} }
EXPORT_SYMBOL(iio_device_alloc); EXPORT_SYMBOL(iio_device_alloc);
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
* checked by device drivers but should be considered * checked by device drivers but should be considered
* read-only as this is a core internal bit * read-only as this is a core internal bit
* @driver_module: used to make it harder to undercut users * @driver_module: used to make it harder to undercut users
* @mlock_key: lockdep class for iio_dev lock
* @info_exist_lock: lock to prevent use during removal * @info_exist_lock: lock to prevent use during removal
* @trig_readonly: mark the current trigger immutable * @trig_readonly: mark the current trigger immutable
* @event_interface: event chrdevs associated with interrupt lines * @event_interface: event chrdevs associated with interrupt lines
...@@ -42,6 +43,7 @@ struct iio_dev_opaque { ...@@ -42,6 +43,7 @@ struct iio_dev_opaque {
int currentmode; int currentmode;
int id; int id;
struct module *driver_module; struct module *driver_module;
struct lock_class_key mlock_key;
struct mutex info_exist_lock; struct mutex info_exist_lock;
bool trig_readonly; bool trig_readonly;
struct iio_event_interface *event_interface; struct iio_event_interface *event_interface;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment