On 8/19/19 2:47 PM, Sakari Ailus wrote: > The V4L2 sub-device's operations are called both from other drivers as > well as through the IOCTL uAPI. Previously the sub-device drivers were > responsible for managing their own serialisation. This patch adds an > optional mutex the drivers may set, and it will be used to serialise > access to driver's data related to a device across the driver's ops. > > Access to the driver's controls through the control framework works as > usual, i.e. using a different mutex. > > Signed-off-by: Sakari Ailus <sakari.ailus@xxxxxxxxxxxxxxx> > --- > include/media/v4l2-subdev.h | 25 +++++++++++++++++-------- > 1 file changed, 17 insertions(+), 8 deletions(-) > > diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h > index 71f1f2f0da53..dc6e11019df6 100644 > --- a/include/media/v4l2-subdev.h > +++ b/include/media/v4l2-subdev.h > @@ -9,6 +9,7 @@ > #define _V4L2_SUBDEV_H > > #include <linux/types.h> > +#include <linux/mutex.h> > #include <linux/v4l2-subdev.h> > #include <media/media-entity.h> > #include <media/v4l2-async.h> > @@ -828,6 +829,7 @@ struct v4l2_subdev_platform_data { > * @host_priv: pointer to private data used by the device where the subdev > * is attached. > * @devnode: subdev device node > + * @lock: A mutex for serialising access to the subdev's operations. Optional. A pointer to a mutex... > * @dev: pointer to the physical device, if any > * @fwnode: The fwnode_handle of the subdev, usually the same as > * either dev->of_node->fwnode or dev->fwnode (whichever is non-NULL). > @@ -862,6 +864,7 @@ struct v4l2_subdev { > void *dev_priv; > void *host_priv; > struct video_device *devnode; > + struct mutex *lock; > struct device *dev; > struct fwnode_handle *fwnode; > struct list_head async_list; > @@ -1101,16 +1104,22 @@ extern const struct v4l2_subdev_ops v4l2_subdev_call_wrappers; > ({ \ > struct v4l2_subdev *__sd = (sd); \ > int __result; \ > - if (!__sd) \ > + if (!__sd) { \ > __result = -ENODEV; \ > - else if (!(__sd->ops->o && __sd->ops->o->f)) \ > + } else if (!(__sd->ops->o && __sd->ops->o->f)) { \ > __result = -ENOIOCTLCMD; \ > - else if (v4l2_subdev_call_wrappers.o && \ > - v4l2_subdev_call_wrappers.o->f) \ > - __result = v4l2_subdev_call_wrappers.o->f( \ > - __sd, ##args); \ > - else \ > - __result = __sd->ops->o->f(__sd, ##args); \ > + } else { \ > + if (__sd->lock) \ > + mutex_lock(__sd->lock); \ > + if (v4l2_subdev_call_wrappers.o && \ > + v4l2_subdev_call_wrappers.o->f) \ > + __result = v4l2_subdev_call_wrappers.o->f( \ > + __sd, ##args); \ > + else \ > + __result = __sd->ops->o->f(__sd, ##args); \ > + if (__sd->lock) \ > + mutex_unlock(__sd->lock); \ > + } \ > __result; \ > }) > > I'm not sure this is the right place to lock. Locking is only needed if the subdev device can be called directly from userspace. So I would put the locking in subdev_do_ioctl() and use mutex_lock_interruptible. If there are subdev ops that in this scenario (i.e. userspace is responsible for configuring the subdev) are still called from another driver, then I would create a v4l2_subdev_call_lock() function that takes the lock. Adding a lock in the v4l2_subdev_call macro feels too invasive. Regards, Hans