[media] au0828: enforce check for graph creation
authorMauro Carvalho Chehab <mchehab@osg.samsung.com>
Fri, 4 Sep 2015 19:08:02 +0000 (16:08 -0300)
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>
Mon, 11 Jan 2016 14:19:00 +0000 (12:19 -0200)
If the graph creation fails, don't register the device.

Acked-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
drivers/media/usb/au0828/au0828-core.c

index 0d77e9cc303b4d702107e86f3e89620b99f66fea..27679e5cdca1adf3d76b192f0c0f44dae5850aa4 100644 (file)
@@ -172,9 +172,9 @@ static void au0828_usb_v4l2_release(struct v4l2_device *v4l2_dev)
        struct au0828_dev *dev =
                container_of(v4l2_dev, struct au0828_dev, v4l2_dev);
 
-       au0828_usb_v4l2_media_release(dev);
        v4l2_ctrl_handler_free(&dev->v4l2_ctrl_hdl);
        v4l2_device_unregister(&dev->v4l2_dev);
+       au0828_usb_v4l2_media_release(dev);
        au0828_usb_release(dev);
 }
 #endif
@@ -253,16 +253,16 @@ static void au0828_media_device_register(struct au0828_dev *dev,
 }
 
 
-static void au0828_create_media_graph(struct au0828_dev *dev)
+static int au0828_create_media_graph(struct au0828_dev *dev)
 {
 #ifdef CONFIG_MEDIA_CONTROLLER
        struct media_device *mdev = dev->media_dev;
        struct media_entity *entity;
        struct media_entity *tuner = NULL, *decoder = NULL;
-       int i;
+       int i, ret;
 
        if (!mdev)
-               return;
+               return 0;
 
        media_device_for_each_entity(entity, mdev) {
                switch (entity->type) {
@@ -279,15 +279,23 @@ static void au0828_create_media_graph(struct au0828_dev *dev)
 
        /* Something bad happened! */
        if (!decoder)
-               return;
-
-       if (tuner)
-               media_create_pad_link(tuner, TUNER_PAD_IF_OUTPUT, decoder, 0,
-                                     MEDIA_LNK_FL_ENABLED);
-       media_create_pad_link(decoder, 1, &dev->vdev.entity, 0,
-                             MEDIA_LNK_FL_ENABLED);
-       media_create_pad_link(decoder, 2, &dev->vbi_dev.entity, 0,
-                             MEDIA_LNK_FL_ENABLED);
+               return -EINVAL;
+
+       if (tuner) {
+               ret = media_create_pad_link(tuner, TUNER_PAD_IF_OUTPUT,
+                                           decoder, 0,
+                                           MEDIA_LNK_FL_ENABLED);
+               if (ret)
+                       return ret;
+       }
+       ret = media_create_pad_link(decoder, 1, &dev->vdev.entity, 0,
+                                   MEDIA_LNK_FL_ENABLED);
+       if (ret)
+               return ret;
+       ret = media_create_pad_link(decoder, 2, &dev->vbi_dev.entity, 0,
+                                   MEDIA_LNK_FL_ENABLED);
+       if (ret)
+               return ret;
 
        for (i = 0; i < AU0828_MAX_INPUT; i++) {
                struct media_entity *ent = &dev->input_ent[i];
@@ -299,20 +307,27 @@ static void au0828_create_media_graph(struct au0828_dev *dev)
                case AU0828_VMUX_CABLE:
                case AU0828_VMUX_TELEVISION:
                case AU0828_VMUX_DVB:
-                       if (tuner)
-                               media_create_pad_link(ent, 0, tuner,
-                                                     TUNER_PAD_RF_INPUT,
-                                                     MEDIA_LNK_FL_ENABLED);
+                       if (!tuner)
+                               break;
+
+                       ret = media_create_pad_link(ent, 0, tuner,
+                                                   TUNER_PAD_RF_INPUT,
+                                                   MEDIA_LNK_FL_ENABLED);
+                       if (ret)
+                               return ret;
                        break;
                case AU0828_VMUX_COMPOSITE:
                case AU0828_VMUX_SVIDEO:
                default: /* AU0828_VMUX_DEBUG */
                        /* FIXME: fix the decoder PAD */
-                       media_create_pad_link(ent, 0, decoder, 0, 0);
+                       ret = media_create_pad_link(ent, 0, decoder, 0, 0);
+                       if (ret)
+                               return ret;
                        break;
                }
        }
 #endif
+       return 0;
 }
 
 static int au0828_usb_probe(struct usb_interface *interface,
@@ -427,7 +442,12 @@ static int au0828_usb_probe(struct usb_interface *interface,
 
        mutex_unlock(&dev->lock);
 
-       au0828_create_media_graph(dev);
+       retval = au0828_create_media_graph(dev);
+       if (retval) {
+               pr_err("%s() au0282_dev_register failed to create graph\n",
+                      __func__);
+               au0828_usb_disconnect(interface);
+       }
 
        return retval;
 }