diff options
author | Hans Verkuil <hverkuil-cisco@xs4all.nl> | 2019-03-01 06:11:27 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab+samsung@kernel.org> | 2019-03-19 13:29:37 -0400 |
commit | 218bf10e39ed5fb22a48dee40bfd2bbcb91693ba (patch) | |
tree | fae09b667509e0ed99447119c42b359186350360 /drivers/media/v4l2-core/v4l2-subdev.c | |
parent | 0e43734d4c46e156785bb1d2acc5b3c10b7d5dd5 (diff) | |
download | linux-218bf10e39ed5fb22a48dee40bfd2bbcb91693ba.tar.bz2 |
media: v4l2-subdev: handle module refcounting here
The module ownership refcounting was done in media_entity_get/put,
but that was very confusing and it did not work either in case an
application had a v4l-subdevX device open and the module was
unbound. When the v4l-subdevX device was closed the media_entity_put
was never called and the module refcount was left one too high, making
it impossible to unload it.
Since v4l2-subdev.c was the only place where media_entity_get/put was
called, just move the functionality to v4l2-subdev.c and drop those
confusing entity functions.
Store the module in subdev_fh so module_put no longer depends on
the media_entity struct.
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Diffstat (limited to 'drivers/media/v4l2-core/v4l2-subdev.c')
-rw-r--r-- | drivers/media/v4l2-core/v4l2-subdev.c | 22 |
1 files changed, 9 insertions, 13 deletions
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index f5f0d71ec745..d75815ab0d7b 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -18,6 +18,7 @@ #include <linux/ioctl.h> #include <linux/mm.h> +#include <linux/module.h> #include <linux/slab.h> #include <linux/types.h> #include <linux/videodev2.h> @@ -54,9 +55,6 @@ static int subdev_open(struct file *file) struct video_device *vdev = video_devdata(file); struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); struct v4l2_subdev_fh *subdev_fh; -#if defined(CONFIG_MEDIA_CONTROLLER) - struct media_entity *entity = NULL; -#endif int ret; subdev_fh = kzalloc(sizeof(*subdev_fh), GFP_KERNEL); @@ -73,12 +71,15 @@ static int subdev_open(struct file *file) v4l2_fh_add(&subdev_fh->vfh); file->private_data = &subdev_fh->vfh; #if defined(CONFIG_MEDIA_CONTROLLER) - if (sd->v4l2_dev->mdev) { - entity = media_entity_get(&sd->entity); - if (!entity) { + if (sd->v4l2_dev->mdev && sd->entity.graph_obj.mdev->dev) { + struct module *owner; + + owner = sd->entity.graph_obj.mdev->dev->driver->owner; + if (!try_module_get(owner)) { ret = -EBUSY; goto err; } + subdev_fh->owner = owner; } #endif @@ -91,9 +92,7 @@ static int subdev_open(struct file *file) return 0; err: -#if defined(CONFIG_MEDIA_CONTROLLER) - media_entity_put(entity); -#endif + module_put(subdev_fh->owner); v4l2_fh_del(&subdev_fh->vfh); v4l2_fh_exit(&subdev_fh->vfh); subdev_fh_free(subdev_fh); @@ -111,10 +110,7 @@ static int subdev_close(struct file *file) if (sd->internal_ops && sd->internal_ops->close) sd->internal_ops->close(sd, subdev_fh); -#if defined(CONFIG_MEDIA_CONTROLLER) - if (sd->v4l2_dev->mdev) - media_entity_put(&sd->entity); -#endif + module_put(subdev_fh->owner); v4l2_fh_del(vfh); v4l2_fh_exit(vfh); subdev_fh_free(subdev_fh); |