X-Git-Url: http://git.cascardo.info/?a=blobdiff_plain;f=drivers%2Fmedia%2Fvideo%2Fv4l2-device.c;fp=drivers%2Fmedia%2Fvideo%2Fv4l2-device.c;h=0edd618b9ddf17c1a117b157428df48ceccca1ae;hb=32aaeffbd4a7457bf2f7448b33b5946ff2a960eb;hp=c742b1f5e73efa6c226ddfae2d3b80d01df0bd2e;hpb=67b84999b1a8b1af5625b1eabe92146c5eb42932;p=cascardo%2Flinux.git diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c index c742b1f5e73e..0edd618b9ddf 100644 --- a/drivers/media/video/v4l2-device.c +++ b/drivers/media/video/v4l2-device.c @@ -22,6 +22,7 @@ #include #include #include +#include #if defined(CONFIG_SPI) #include #endif @@ -194,6 +195,13 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, } EXPORT_SYMBOL_GPL(v4l2_device_register_subdev); +static void v4l2_device_release_subdev_node(struct video_device *vdev) +{ + struct v4l2_subdev *sd = video_get_drvdata(vdev); + sd->devnode = NULL; + kfree(vdev); +} + int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev) { struct video_device *vdev; @@ -207,22 +215,40 @@ int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev) if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE)) continue; - vdev = &sd->devnode; + vdev = kzalloc(sizeof(*vdev), GFP_KERNEL); + if (!vdev) { + err = -ENOMEM; + goto clean_up; + } + + video_set_drvdata(vdev, sd); strlcpy(vdev->name, sd->name, sizeof(vdev->name)); vdev->v4l2_dev = v4l2_dev; vdev->fops = &v4l2_subdev_fops; - vdev->release = video_device_release_empty; + vdev->release = v4l2_device_release_subdev_node; vdev->ctrl_handler = sd->ctrl_handler; err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1, sd->owner); - if (err < 0) - return err; + if (err < 0) { + kfree(vdev); + goto clean_up; + } #if defined(CONFIG_MEDIA_CONTROLLER) sd->entity.v4l.major = VIDEO_MAJOR; sd->entity.v4l.minor = vdev->minor; #endif + sd->devnode = vdev; } return 0; + +clean_up: + list_for_each_entry(sd, &v4l2_dev->subdevs, list) { + if (!sd->devnode) + break; + video_unregister_device(sd->devnode); + } + + return err; } EXPORT_SYMBOL_GPL(v4l2_device_register_subdev_nodes); @@ -248,7 +274,7 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd) if (v4l2_dev->mdev) media_device_unregister_entity(&sd->entity); #endif - video_unregister_device(&sd->devnode); + video_unregister_device(sd->devnode); module_put(sd->owner); } EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev);