]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
media: v4l2-async: Get fwnode reference when putting it to the notifier's list
authorSakari Ailus <sakari.ailus@linux.intel.com>
Thu, 4 Apr 2019 23:43:29 +0000 (19:43 -0400)
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>
Thu, 25 Jul 2019 12:01:43 +0000 (08:01 -0400)
The v4l2_async_notifier_add_fwnode_subdev() did not take a reference of
the added fwnode, relying on the caller to handle that instead, in essence
putting the fwnode to be added if there was an error.

As the reference is eventually released during the notifier cleanup, this
is not intuitive nor logical. Improve this by always getting a reference
when the function succeeds, and the caller releasing the reference when it
does not *itself* need it anymore.

Luckily, perhaps, there were just a handful of callers using the function.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Jacopo Mondi <jacopo+renesas@jmondi.org>
Tested-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
drivers/media/platform/am437x/am437x-vpfe.c
drivers/media/platform/davinci/vpif_capture.c
drivers/media/platform/qcom/camss/camss.c
drivers/media/platform/xilinx/xilinx-vipp.c
drivers/media/v4l2-core/v4l2-async.c
drivers/media/v4l2-core/v4l2-fwnode.c
include/media/v4l2-async.h

index 105237edbb586019c8868e9c62d7b84d554560d1..3b1d60ca859b3834eea256f70b829c034ab5ccd9 100644 (file)
@@ -2489,10 +2489,9 @@ vpfe_get_pdata(struct vpfe_device *vpfe)
                pdata->asd[i] = v4l2_async_notifier_add_fwnode_subdev(
                        &vpfe->notifier, of_fwnode_handle(rem),
                        sizeof(struct v4l2_async_subdev));
-               if (IS_ERR(pdata->asd[i])) {
-                       of_node_put(rem);
+               of_node_put(rem);
+               if (IS_ERR(pdata->asd[i]))
                        goto cleanup;
-               }
        }
 
        of_node_put(endpoint);
index 4bbb4fdeae92884407448d9486a16142e51144a2..71f4fe882d138f4f69abd16309a221c8490f7de7 100644 (file)
@@ -1502,6 +1502,7 @@ static struct vpif_capture_config *
 vpif_capture_get_pdata(struct platform_device *pdev)
 {
        struct device_node *endpoint = NULL;
+       struct device_node *rem = NULL;
        struct vpif_capture_config *pdata;
        struct vpif_subdev_info *sdinfo;
        struct vpif_capture_chan_config *chan;
@@ -1532,7 +1533,6 @@ vpif_capture_get_pdata(struct platform_device *pdev)
 
        for (i = 0; i < VPIF_CAPTURE_NUM_CHANNELS; i++) {
                struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 };
-               struct device_node *rem;
                unsigned int flags;
                int err;
 
@@ -1554,10 +1554,8 @@ vpif_capture_get_pdata(struct platform_device *pdev)
                                            VPIF_CAPTURE_NUM_CHANNELS,
                                            sizeof(*chan->inputs),
                                            GFP_KERNEL);
-               if (!chan->inputs) {
-                       of_node_put(rem);
+               if (!chan->inputs)
                        goto err_cleanup;
-               }
 
                chan->input_count++;
                chan->inputs[i].input.type = V4L2_INPUT_TYPE_CAMERA;
@@ -1589,10 +1587,10 @@ vpif_capture_get_pdata(struct platform_device *pdev)
                pdata->asd[i] = v4l2_async_notifier_add_fwnode_subdev(
                        &vpif_obj.notifier, of_fwnode_handle(rem),
                        sizeof(struct v4l2_async_subdev));
-               if (IS_ERR(pdata->asd[i])) {
-                       of_node_put(rem);
+               if (IS_ERR(pdata->asd[i]))
                        goto err_cleanup;
-               }
+
+               of_node_put(rem);
        }
 
 done:
@@ -1604,6 +1602,7 @@ vpif_capture_get_pdata(struct platform_device *pdev)
        return pdata;
 
 err_cleanup:
+       of_node_put(rem);
        of_node_put(endpoint);
        v4l2_async_notifier_cleanup(&vpif_obj.notifier);
 
index 63da18773d2459e4597ce6c49564d3456c5618f5..3fdc9f964a3c6bd84b29a7b257bab23d9c8b2ede 100644 (file)
@@ -486,9 +486,9 @@ static int camss_of_parse_ports(struct camss *camss)
                asd = v4l2_async_notifier_add_fwnode_subdev(
                        &camss->notifier, of_fwnode_handle(remote),
                        sizeof(*csd));
+               of_node_put(remote);
                if (IS_ERR(asd)) {
                        ret = PTR_ERR(asd);
-                       of_node_put(remote);
                        goto err_cleanup;
                }
 
index edce0402155dfb007b1b456f7456ecc6ccf218f5..cc2856efea5947cfd91f02f6cb18b9e9e01e15a7 100644 (file)
@@ -385,9 +385,9 @@ static int xvip_graph_parse_one(struct xvip_composite_device *xdev,
                asd = v4l2_async_notifier_add_fwnode_subdev(
                        &xdev->notifier, remote,
                        sizeof(struct xvip_graph_entity));
+               fwnode_handle_put(remote);
                if (IS_ERR(asd)) {
                        ret = PTR_ERR(asd);
-                       fwnode_handle_put(remote);
                        goto err_notifier_cleanup;
                }
        }
index 8d307b538f52539833607d1218ef0cab5f3ac033..7d364c545a40986e7388e76d01b3200654e3f59d 100644 (file)
@@ -593,10 +593,11 @@ v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,
                return ERR_PTR(-ENOMEM);
 
        asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
-       asd->match.fwnode = fwnode;
+       asd->match.fwnode = fwnode_handle_get(fwnode);
 
        ret = v4l2_async_notifier_add_subdev(notifier, asd);
        if (ret) {
+               fwnode_handle_put(fwnode);
                kfree(asd);
                return ERR_PTR(ret);
        }
index 6972c5af25c69757e7a11ea2e2ca764e1f27131c..3bd1888787eb3c3728c7f60ea5c85dc11fada8a1 100644 (file)
@@ -775,23 +775,17 @@ static int v4l2_fwnode_reference_parse(struct device *dev,
                asd = v4l2_async_notifier_add_fwnode_subdev(notifier,
                                                            args.fwnode,
                                                            sizeof(*asd));
+               fwnode_handle_put(args.fwnode);
                if (IS_ERR(asd)) {
-                       ret = PTR_ERR(asd);
                        /* not an error if asd already exists */
-                       if (ret == -EEXIST) {
-                               fwnode_handle_put(args.fwnode);
+                       if (PTR_ERR(asd) == -EEXIST)
                                continue;
-                       }
 
-                       goto error;
+                       return PTR_ERR(asd);
                }
        }
 
        return 0;
-
-error:
-       fwnode_handle_put(args.fwnode);
-       return ret;
 }
 
 /*
@@ -1081,23 +1075,18 @@ v4l2_fwnode_reference_parse_int_props(struct device *dev,
 
                asd = v4l2_async_notifier_add_fwnode_subdev(notifier, fwnode,
                                                            sizeof(*asd));
+               fwnode_handle_put(fwnode);
                if (IS_ERR(asd)) {
                        ret = PTR_ERR(asd);
                        /* not an error if asd already exists */
-                       if (ret == -EEXIST) {
-                               fwnode_handle_put(fwnode);
+                       if (ret == -EEXIST)
                                continue;
-                       }
 
-                       goto error;
+                       return PTR_ERR(asd);
                }
        }
 
        return !fwnode || PTR_ERR(fwnode) == -ENOENT ? 0 : PTR_ERR(fwnode);
-
-error:
-       fwnode_handle_put(fwnode);
-       return ret;
 }
 
 int v4l2_async_notifier_parse_fwnode_sensor_common(struct device *dev,
index 2e3d93f742a3b64e35767f5a2fc08caa794b5489..a95f7fd8969e71aef80609d959d64c2cdf6d041b 100644 (file)
@@ -172,8 +172,9 @@ int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier *notifier,
  *                  the driver's async sub-device struct, i.e. both
  *                  begin at the same memory address.
  *
- * Allocate a fwnode-matched asd of size asd_struct_size, and add it
- * to the notifiers @asd_list.
+ * Allocate a fwnode-matched asd of size asd_struct_size, and add it to the
+ * notifiers @asd_list. The function also gets a reference of the fwnode which
+ * is released later at notifier cleanup time.
  */
 struct v4l2_async_subdev *
 v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier,