提交 b2a06aec 编写于 作者: S Sakari Ailus 提交者: Mauro Carvalho Chehab

[media] v4l: Only get module if it's different than the driver for v4l2_dev

When the sub-device is registered, increment the use count of the sub-device
owner only if it's different from the owner of the driver for the media
device. This avoids increasing the use count by the module itself and thus
making it possible to unload it when it's not in use.
Signed-off-by: NSakari Ailus <sakari.ailus@linux.intel.com>
Acked-by: NLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: NMauro Carvalho Chehab <m.chehab@samsung.com>
上级 85de721c
...@@ -158,7 +158,17 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, ...@@ -158,7 +158,17 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
/* Warn if we apparently re-register a subdev */ /* Warn if we apparently re-register a subdev */
WARN_ON(sd->v4l2_dev != NULL); WARN_ON(sd->v4l2_dev != NULL);
if (!try_module_get(sd->owner)) /*
* The reason to acquire the module here is to avoid unloading
* a module of sub-device which is registered to a media
* device. To make it possible to unload modules for media
* devices that also register sub-devices, do not
* try_module_get() such sub-device owners.
*/
sd->owner_v4l2_dev = v4l2_dev->dev && v4l2_dev->dev->driver &&
sd->owner == v4l2_dev->dev->driver->owner;
if (!sd->owner_v4l2_dev && !try_module_get(sd->owner))
return -ENODEV; return -ENODEV;
sd->v4l2_dev = v4l2_dev; sd->v4l2_dev = v4l2_dev;
...@@ -192,7 +202,8 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, ...@@ -192,7 +202,8 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
if (sd->internal_ops && sd->internal_ops->unregistered) if (sd->internal_ops && sd->internal_ops->unregistered)
sd->internal_ops->unregistered(sd); sd->internal_ops->unregistered(sd);
error_module: error_module:
module_put(sd->owner); if (!sd->owner_v4l2_dev)
module_put(sd->owner);
sd->v4l2_dev = NULL; sd->v4l2_dev = NULL;
return err; return err;
} }
...@@ -280,6 +291,7 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd) ...@@ -280,6 +291,7 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd)
} }
#endif #endif
video_unregister_device(sd->devnode); video_unregister_device(sd->devnode);
module_put(sd->owner); if (!sd->owner_v4l2_dev)
module_put(sd->owner);
} }
EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev); EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev);
...@@ -584,6 +584,7 @@ struct v4l2_subdev { ...@@ -584,6 +584,7 @@ struct v4l2_subdev {
#endif #endif
struct list_head list; struct list_head list;
struct module *owner; struct module *owner;
bool owner_v4l2_dev;
u32 flags; u32 flags;
struct v4l2_device *v4l2_dev; struct v4l2_device *v4l2_dev;
const struct v4l2_subdev_ops *ops; const struct v4l2_subdev_ops *ops;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册