diff options
| author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2012-11-24 21:35:48 -0300 | 
|---|---|---|
| committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-01-05 01:25:22 -0200 | 
| commit | 317efce991620adc589b3005b9baed433dcb2a56 (patch) | |
| tree | 606c6efb344bebba61573b965fa537dc44dc428f | |
| parent | 90271964c96f89862b3e06e184e770e16cca7c8f (diff) | |
| download | olio-linux-3.10-317efce991620adc589b3005b9baed433dcb2a56.tar.xz olio-linux-3.10-317efce991620adc589b3005b9baed433dcb2a56.zip  | |
[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: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: stable@vger.kernel.org
Acked-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
| -rw-r--r-- | drivers/media/v4l2-core/v4l2-device.c | 30 | 
1 files changed, 14 insertions, 16 deletions
diff --git a/drivers/media/v4l2-core/v4l2-device.c b/drivers/media/v4l2-core/v4l2-device.c index 513969fa695..98a7f5e9cb1 100644 --- a/drivers/media/v4l2-core/v4l2-device.c +++ b/drivers/media/v4l2-core/v4l2-device.c @@ -159,31 +159,21 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,  	sd->v4l2_dev = v4l2_dev;  	if (sd->internal_ops && sd->internal_ops->registered) {  		err = sd->internal_ops->registered(sd); -		if (err) { -			module_put(sd->owner); -			return err; -		} +		if (err) +			goto error_module;  	}  	/* 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); -	if (err) { -		if (sd->internal_ops && sd->internal_ops->unregistered) -			sd->internal_ops->unregistered(sd); -		module_put(sd->owner); -		return err; -	} +	if (err) +		goto error_unregister;  #if defined(CONFIG_MEDIA_CONTROLLER)  	/* Register the entity. */  	if (v4l2_dev->mdev) {  		err = media_device_register_entity(v4l2_dev->mdev, entity); -		if (err < 0) { -			if (sd->internal_ops && sd->internal_ops->unregistered) -				sd->internal_ops->unregistered(sd); -			module_put(sd->owner); -			return err; -		} +		if (err < 0) +			goto error_unregister;  	}  #endif @@ -192,6 +182,14 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,  	spin_unlock(&v4l2_dev->lock);  	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);  |