summaryrefslogtreecommitdiff
path: root/drivers/media/v4l2-core
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil-cisco@xs4all.nl>2019-03-01 06:11:27 -0500
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>2019-03-19 13:29:37 -0400
commit218bf10e39ed5fb22a48dee40bfd2bbcb91693ba (patch)
treefae09b667509e0ed99447119c42b359186350360 /drivers/media/v4l2-core
parent0e43734d4c46e156785bb1d2acc5b3c10b7d5dd5 (diff)
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')
-rw-r--r--drivers/media/v4l2-core/v4l2-subdev.c22
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);