summaryrefslogtreecommitdiff
path: root/drivers/media/platform/soc_camera
diff options
context:
space:
mode:
authorSteve Longerbeam <slongerbeam@gmail.com>2018-09-29 22:54:18 +0300
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>2018-10-04 22:55:38 +0300
commitd079f94c90469f413920b9f2b201537fac2ceb06 (patch)
tree81c01fba155425c957a7f827963b32efa9e0d872 /drivers/media/platform/soc_camera
parentd5099f81803fc7a7831aa893097fab3cf8d15d3e (diff)
downloadlinux-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/soc_camera')
-rw-r--r--drivers/media/platform/soc_camera/soc_camera.c35
1 files changed, 25 insertions, 10 deletions
diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c
index 44b6859d7238..0a70fb67c401 100644
--- a/drivers/media/platform/soc_camera/soc_camera.c
+++ b/drivers/media/platform/soc_camera/soc_camera.c
@@ -1442,8 +1442,14 @@ static int scan_async_group(struct soc_camera_host *ici,
goto eaddpdev;
}
- sasc->notifier.subdevs = asd;
- sasc->notifier.num_subdevs = size;
+ v4l2_async_notifier_init(&sasc->notifier);
+
+ for (i = 0; i < size; i++) {
+ ret = v4l2_async_notifier_add_subdev(&sasc->notifier, asd[i]);
+ if (ret)
+ goto eaddasd;
+ }
+
sasc->notifier.ops = &soc_camera_async_ops;
icd->sasc = sasc;
@@ -1466,6 +1472,8 @@ static int scan_async_group(struct soc_camera_host *ici,
v4l2_clk_unregister(icd->clk);
eclkreg:
icd->clk = NULL;
+eaddasd:
+ v4l2_async_notifier_cleanup(&sasc->notifier);
platform_device_del(sasc->pdev);
eaddpdev:
platform_device_put(sasc->pdev);
@@ -1540,8 +1548,14 @@ static int soc_of_bind(struct soc_camera_host *ici,
goto eaddpdev;
}
- sasc->notifier.subdevs = &info->subdev;
- sasc->notifier.num_subdevs = 1;
+ v4l2_async_notifier_init(&sasc->notifier);
+
+ ret = v4l2_async_notifier_add_subdev(&sasc->notifier, info->subdev);
+ if (ret) {
+ of_node_put(remote);
+ goto eaddasd;
+ }
+
sasc->notifier.ops = &soc_camera_async_ops;
icd->sasc = sasc;
@@ -1568,6 +1582,8 @@ static int soc_of_bind(struct soc_camera_host *ici,
v4l2_clk_unregister(icd->clk);
eclkreg:
icd->clk = NULL;
+eaddasd:
+ v4l2_async_notifier_cleanup(&sasc->notifier);
platform_device_del(sasc->pdev);
eaddpdev:
platform_device_put(sasc->pdev);
@@ -1582,7 +1598,7 @@ static void scan_of_host(struct soc_camera_host *ici)
{
struct device *dev = ici->v4l2_dev.dev;
struct device_node *np = dev->of_node;
- struct device_node *epn = NULL, *ren;
+ struct device_node *epn = NULL, *rem;
unsigned int i;
for (i = 0; ; i++) {
@@ -1590,17 +1606,15 @@ static void scan_of_host(struct soc_camera_host *ici)
if (!epn)
break;
- ren = of_graph_get_remote_port(epn);
- if (!ren) {
+ rem = of_graph_get_remote_port_parent(epn);
+ if (!rem) {
dev_notice(dev, "no remote for %pOF\n", epn);
continue;
}
/* so we now have a remote node to connect */
if (!i)
- soc_of_bind(ici, epn, ren->parent);
-
- of_node_put(ren);
+ soc_of_bind(ici, epn, rem);
if (i) {
dev_err(dev, "multiple subdevices aren't supported yet!\n");
@@ -1926,6 +1940,7 @@ void soc_camera_host_unregister(struct soc_camera_host *ici)
list_for_each_entry(sasc, &notifiers, list) {
/* Must call unlocked to avoid AB-BA dead-lock */
v4l2_async_notifier_unregister(&sasc->notifier);
+ v4l2_async_notifier_cleanup(&sasc->notifier);
put_device(&sasc->pdev->dev);
}