Merge tag 'staging-4.5-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh...
[cascardo/linux.git] / drivers / media / v4l2-core / v4l2-device.c
index 7129e43..06fa5f1 100644 (file)
@@ -180,26 +180,26 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
                return -ENODEV;
 
        sd->v4l2_dev = v4l2_dev;
-       if (sd->internal_ops && sd->internal_ops->registered) {
-               err = sd->internal_ops->registered(sd);
-               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)
-               goto error_unregister;
+               goto error_module;
 
 #if defined(CONFIG_MEDIA_CONTROLLER)
        /* Register the entity. */
        if (v4l2_dev->mdev) {
                err = media_device_register_entity(v4l2_dev->mdev, entity);
                if (err < 0)
-                       goto error_unregister;
+                       goto error_module;
        }
 #endif
 
+       if (sd->internal_ops && sd->internal_ops->registered) {
+               err = sd->internal_ops->registered(sd);
+               if (err)
+                       goto error_unregister;
+       }
+
        spin_lock(&v4l2_dev->lock);
        list_add_tail(&sd->list, &v4l2_dev->subdevs);
        spin_unlock(&v4l2_dev->lock);
@@ -207,8 +207,9 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
        return 0;
 
 error_unregister:
-       if (sd->internal_ops && sd->internal_ops->unregistered)
-               sd->internal_ops->unregistered(sd);
+#if defined(CONFIG_MEDIA_CONTROLLER)
+       media_device_unregister_entity(entity);
+#endif
 error_module:
        if (!sd->owner_v4l2_dev)
                module_put(sd->owner);
@@ -258,6 +259,19 @@ int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
 #if defined(CONFIG_MEDIA_CONTROLLER)
                sd->entity.info.dev.major = VIDEO_MAJOR;
                sd->entity.info.dev.minor = vdev->minor;
+
+               /* Interface is created by __video_register_device() */
+               if (vdev->v4l2_dev->mdev) {
+                       struct media_link *link;
+
+                       link = media_create_intf_link(&sd->entity,
+                                                     &vdev->intf_devnode->intf,
+                                                     MEDIA_LNK_FL_ENABLED);
+                       if (!link) {
+                               err = -ENOMEM;
+                               goto clean_up;
+                       }
+               }
 #endif
                sd->devnode = vdev;
        }
@@ -294,7 +308,10 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd)
 
 #if defined(CONFIG_MEDIA_CONTROLLER)
        if (v4l2_dev->mdev) {
-               media_entity_remove_links(&sd->entity);
+               /*
+                * No need to explicitly remove links, as both pads and
+                * links are removed by the function below, in the right order
+                */
                media_device_unregister_entity(&sd->entity);
        }
 #endif