Commit 317efce9 authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Mauro Carvalho Chehab

[media] v4l: Reset subdev v4l2_dev field to NULL if registration fails

When subdev registration fails the subdev v4l2_dev field is left to a
non-NULL value. Later calls to v4l2_device_unregister_subdev() will
consider the subdev as registered and will module_put() the subdev
module without any matching module_get().
Fix this by setting the subdev v4l2_dev field to NULL in
v4l2_device_register_subdev() when the function fails.
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: stable@vger.kernel.org
Acked-by: default avatarSylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 90271964
...@@ -159,31 +159,21 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, ...@@ -159,31 +159,21 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
sd->v4l2_dev = v4l2_dev; sd->v4l2_dev = v4l2_dev;
if (sd->internal_ops && sd->internal_ops->registered) { if (sd->internal_ops && sd->internal_ops->registered) {
err = sd->internal_ops->registered(sd); err = sd->internal_ops->registered(sd);
if (err) { if (err)
module_put(sd->owner); goto error_module;
return err;
}
} }
/* This just returns 0 if either of the two args is NULL */ /* This just returns 0 if either of the two args is NULL */
err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler, NULL); err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler, NULL);
if (err) { if (err)
if (sd->internal_ops && sd->internal_ops->unregistered) goto error_unregister;
sd->internal_ops->unregistered(sd);
module_put(sd->owner);
return err;
}
#if defined(CONFIG_MEDIA_CONTROLLER) #if defined(CONFIG_MEDIA_CONTROLLER)
/* Register the entity. */ /* Register the entity. */
if (v4l2_dev->mdev) { if (v4l2_dev->mdev) {
err = media_device_register_entity(v4l2_dev->mdev, entity); err = media_device_register_entity(v4l2_dev->mdev, entity);
if (err < 0) { if (err < 0)
if (sd->internal_ops && sd->internal_ops->unregistered) goto error_unregister;
sd->internal_ops->unregistered(sd);
module_put(sd->owner);
return err;
}
} }
#endif #endif
...@@ -192,6 +182,14 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, ...@@ -192,6 +182,14 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
spin_unlock(&v4l2_dev->lock); spin_unlock(&v4l2_dev->lock);
return 0; return 0;
error_unregister:
if (sd->internal_ops && sd->internal_ops->unregistered)
sd->internal_ops->unregistered(sd);
error_module:
module_put(sd->owner);
sd->v4l2_dev = NULL;
return err;
} }
EXPORT_SYMBOL_GPL(v4l2_device_register_subdev); EXPORT_SYMBOL_GPL(v4l2_device_register_subdev);
......
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