media: vimc: handle error in vimc_add_subdevs
authorDafna Hirschfeld <dafna.hirschfeld@collabora.com>
Sat, 28 Mar 2020 07:52:51 +0000 (08:52 +0100)
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Tue, 14 Apr 2020 10:01:43 +0000 (12:01 +0200)
In case the 'add' callback of an entity fails,
then all other entities should unregister and released.
This should be done inside vimc_add_subdevs so that
the function handles its own failure.

In order to call vimc_unregister_subdevs and vimc_release_subdevs from
vimc_add_subdevs, the order of the function should change.

Signed-off-by: Dafna Hirschfeld <dafna.hirschfeld@collabora.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
drivers/media/test_drivers/vimc/vimc-core.c

index 1f84988..dab01cb 100644 (file)
@@ -160,24 +160,6 @@ err_rm_links:
        return ret;
 }
 
-static int vimc_add_subdevs(struct vimc_device *vimc)
-{
-       unsigned int i;
-
-       for (i = 0; i < vimc->pipe_cfg->num_ents; i++) {
-               dev_dbg(vimc->mdev.dev, "new entity for %s\n",
-                       vimc->pipe_cfg->ents[i].name);
-               vimc->ent_devs[i] = vimc->pipe_cfg->ents[i].add(vimc,
-                                       vimc->pipe_cfg->ents[i].name);
-               if (!vimc->ent_devs[i]) {
-                       dev_err(vimc->mdev.dev, "add new entity for %s\n",
-                               vimc->pipe_cfg->ents[i].name);
-                       return -EINVAL;
-               }
-       }
-       return 0;
-}
-
 static void vimc_release_subdevs(struct vimc_device *vimc)
 {
        unsigned int i;
@@ -196,6 +178,26 @@ static void vimc_unregister_subdevs(struct vimc_device *vimc)
                        vimc->pipe_cfg->ents[i].unregister(vimc->ent_devs[i]);
 }
 
+static int vimc_add_subdevs(struct vimc_device *vimc)
+{
+       unsigned int i;
+
+       for (i = 0; i < vimc->pipe_cfg->num_ents; i++) {
+               dev_dbg(vimc->mdev.dev, "new entity for %s\n",
+                       vimc->pipe_cfg->ents[i].name);
+               vimc->ent_devs[i] = vimc->pipe_cfg->ents[i].add(vimc,
+                                       vimc->pipe_cfg->ents[i].name);
+               if (!vimc->ent_devs[i]) {
+                       dev_err(vimc->mdev.dev, "add new entity for %s\n",
+                               vimc->pipe_cfg->ents[i].name);
+                       vimc_unregister_subdevs(vimc);
+                       vimc_release_subdevs(vimc);
+                       return -EINVAL;
+               }
+       }
+       return 0;
+}
+
 static void vimc_v4l2_dev_release(struct v4l2_device *v4l2_dev)
 {
        struct vimc_device *vimc =
@@ -229,8 +231,7 @@ static int vimc_register_devices(struct vimc_device *vimc)
        /* Invoke entity config hooks to initialize and register subdevs */
        ret = vimc_add_subdevs(vimc);
        if (ret)
-               /* remove sundevs that got added */
-               goto err_rm_subdevs;
+               goto err_free_ent_devs;
 
        /* Initialize links */
        ret = vimc_create_links(vimc);
@@ -261,6 +262,7 @@ err_mdev_unregister:
 err_rm_subdevs:
        vimc_unregister_subdevs(vimc);
        vimc_release_subdevs(vimc);
+err_free_ent_devs:
        kfree(vimc->ent_devs);
 err_v4l2_unregister:
        v4l2_device_unregister(&vimc->v4l2_dev);