diff options
author | Steve Longerbeam <slongerbeam@gmail.com> | 2018-09-29 22:54:18 +0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab+samsung@kernel.org> | 2018-10-04 22:55:38 +0300 |
commit | d079f94c90469f413920b9f2b201537fac2ceb06 (patch) | |
tree | 81c01fba155425c957a7f827963b32efa9e0d872 /drivers/media/platform/renesas-ceu.c | |
parent | d5099f81803fc7a7831aa893097fab3cf8d15d3e (diff) | |
download | linux-d079f94c90469f413920b9f2b201537fac2ceb06.tar.xz |
media: platform: Switch to v4l2_async_notifier_add_subdev
Switch all media platform drivers to call v4l2_async_notifier_add_subdev()
to add asd's to a notifier, in place of referencing the notifier->subdevs[]
array. These drivers also must now call v4l2_async_notifier_init() before
adding asd's to their notifiers.
There may still be cases where a platform driver maintains a list of
asd's that is a duplicate of the notifier asd_list, in which case its
possible the platform driver list can be removed, and can reference the
notifier asd_list instead. One example of where a duplicate list has
been removed in this patch is xilinx-vipp.c. If there are such cases
remaining, those drivers should be optimized to remove the duplicate
platform driver asd lists.
None of the changes to the platform drivers in this patch have been
tested. Verify that the async subdevices needed by the platform are
bound at load time, and that the driver unloads and reloads correctly
with no memory leaking of asd objects.
Suggested-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Steve Longerbeam <slongerbeam@gmail.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Diffstat (limited to 'drivers/media/platform/renesas-ceu.c')
-rw-r--r-- | drivers/media/platform/renesas-ceu.c | 53 |
1 files changed, 29 insertions, 24 deletions
diff --git a/drivers/media/platform/renesas-ceu.c b/drivers/media/platform/renesas-ceu.c index b7ae820a2ef6..eee4ae7234be 100644 --- a/drivers/media/platform/renesas-ceu.c +++ b/drivers/media/platform/renesas-ceu.c @@ -189,8 +189,6 @@ struct ceu_device { /* async subdev notification helpers */ struct v4l2_async_notifier notifier; - /* pointers to "struct ceu_subdevice -> asd" */ - struct v4l2_async_subdev **asds; /* vb2 queue, capture buffer list and active buffer pointer */ struct vb2_queue vb2_vq; @@ -1482,15 +1480,6 @@ static int ceu_init_async_subdevs(struct ceu_device *ceudev, unsigned int n_sd) if (!ceudev->subdevs) return -ENOMEM; - /* - * Reserve memory for 'n_sd' pointers to async_subdevices. - * ceudev->asds members will point to &ceu_subdev.asd - */ - ceudev->asds = devm_kcalloc(ceudev->dev, n_sd, - sizeof(*ceudev->asds), GFP_KERNEL); - if (!ceudev->asds) - return -ENOMEM; - ceudev->sd = NULL; ceudev->sd_index = 0; ceudev->num_sd = 0; @@ -1518,6 +1507,7 @@ static int ceu_parse_platform_data(struct ceu_device *ceudev, return ret; for (i = 0; i < pdata->num_subdevs; i++) { + /* Setup the ceu subdevice and the async subdevice. */ async_sd = &pdata->subdevs[i]; ceu_sd = &ceudev->subdevs[i]; @@ -1529,7 +1519,12 @@ static int ceu_parse_platform_data(struct ceu_device *ceudev, ceu_sd->asd.match.i2c.adapter_id = async_sd->i2c_adapter_id; ceu_sd->asd.match.i2c.address = async_sd->i2c_address; - ceudev->asds[i] = &ceu_sd->asd; + ret = v4l2_async_notifier_add_subdev(&ceudev->notifier, + &ceu_sd->asd); + if (ret) { + v4l2_async_notifier_cleanup(&ceudev->notifier); + return ret; + } } return pdata->num_subdevs; @@ -1542,8 +1537,8 @@ static int ceu_parse_dt(struct ceu_device *ceudev) { struct device_node *of = ceudev->dev->of_node; struct v4l2_fwnode_endpoint fw_ep; + struct device_node *ep, *remote; struct ceu_subdev *ceu_sd; - struct device_node *ep; unsigned int i; int num_ep; int ret; @@ -1562,40 +1557,46 @@ static int ceu_parse_dt(struct ceu_device *ceudev) dev_err(ceudev->dev, "No subdevice connected on endpoint %u.\n", i); ret = -ENODEV; - goto error_put_node; + goto error_cleanup; } ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &fw_ep); if (ret) { dev_err(ceudev->dev, "Unable to parse endpoint #%u.\n", i); - goto error_put_node; + goto error_cleanup; } if (fw_ep.bus_type != V4L2_MBUS_PARALLEL) { dev_err(ceudev->dev, "Only parallel input supported.\n"); ret = -EINVAL; - goto error_put_node; + goto error_cleanup; } /* Setup the ceu subdevice and the async subdevice. */ ceu_sd = &ceudev->subdevs[i]; INIT_LIST_HEAD(&ceu_sd->asd.list); + remote = of_graph_get_remote_port_parent(ep); ceu_sd->mbus_flags = fw_ep.bus.parallel.flags; ceu_sd->asd.match_type = V4L2_ASYNC_MATCH_FWNODE; - ceu_sd->asd.match.fwnode = - fwnode_graph_get_remote_port_parent( - of_fwnode_handle(ep)); + ceu_sd->asd.match.fwnode = of_fwnode_handle(remote); + + ret = v4l2_async_notifier_add_subdev(&ceudev->notifier, + &ceu_sd->asd); + if (ret) { + of_node_put(remote); + goto error_cleanup; + } - ceudev->asds[i] = &ceu_sd->asd; of_node_put(ep); } return num_ep; -error_put_node: +error_cleanup: + v4l2_async_notifier_cleanup(&ceudev->notifier); of_node_put(ep); return ret; } @@ -1674,6 +1675,8 @@ static int ceu_probe(struct platform_device *pdev) if (ret) goto error_pm_disable; + v4l2_async_notifier_init(&ceudev->notifier); + if (IS_ENABLED(CONFIG_OF) && dev->of_node) { ceu_data = of_match_device(ceu_of_match, dev)->data; num_subdevs = ceu_parse_dt(ceudev); @@ -1693,18 +1696,18 @@ static int ceu_probe(struct platform_device *pdev) ceudev->irq_mask = ceu_data->irq_mask; ceudev->notifier.v4l2_dev = &ceudev->v4l2_dev; - ceudev->notifier.subdevs = ceudev->asds; - ceudev->notifier.num_subdevs = num_subdevs; ceudev->notifier.ops = &ceu_notify_ops; ret = v4l2_async_notifier_register(&ceudev->v4l2_dev, &ceudev->notifier); if (ret) - goto error_v4l2_unregister; + goto error_cleanup; dev_info(dev, "Renesas Capture Engine Unit %s\n", dev_name(dev)); return 0; +error_cleanup: + v4l2_async_notifier_cleanup(&ceudev->notifier); error_v4l2_unregister: v4l2_device_unregister(&ceudev->v4l2_dev); error_pm_disable: @@ -1723,6 +1726,8 @@ static int ceu_remove(struct platform_device *pdev) v4l2_async_notifier_unregister(&ceudev->notifier); + v4l2_async_notifier_cleanup(&ceudev->notifier); + v4l2_device_unregister(&ceudev->v4l2_dev); video_unregister_device(&ceudev->vdev); |