summaryrefslogtreecommitdiff
path: root/drivers/media/v4l2-core/v4l2-fwnode.c
diff options
context:
space:
mode:
authorSteve Longerbeam <slongerbeam@gmail.com>2018-09-29 15:54:08 -0400
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>2018-10-04 15:33:09 -0400
commiteae2aed1eab9bf08146403ac702517d2e4fe932e (patch)
tree9b07bc63eff0aaecf9f724685ce6bb34c1c9fcff /drivers/media/v4l2-core/v4l2-fwnode.c
parent23989b43f1079fdb90a621cc554a516b3a012981 (diff)
media: v4l2-fwnode: Switch to v4l2_async_notifier_add_subdev
The fwnode endpoint and reference parsing functions in v4l2-fwnode.c are modified to make use of v4l2_async_notifier_add_subdev(). As a result the notifier->subdevs array is no longer allocated or re-allocated, and by extension the max_subdevs value is also no longer needed. Callers of the fwnode endpoint and reference parsing functions must now first initialize the notifier with a call to v4l2_async_notifier_init(). This includes the function v4l2_async_register_subdev_sensor_common(), and the intel-ipu3, omap3isp, and rcar-vin drivers. Since the notifier->subdevs array is no longer allocated in the fwnode endpoint and reference parsing functions, the callers of those functions must never reference that array, since it is now NULL. Of the drivers that make use of the fwnode/ref parsing, only the intel-ipu3 driver references the ->subdevs[] array, (in the notifier completion callback), so that driver has been modified to iterate through the notifier->asd_list instead. 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/v4l2-core/v4l2-fwnode.c')
-rw-r--r--drivers/media/v4l2-core/v4l2-fwnode.c132
1 files changed, 28 insertions, 104 deletions
diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c
index 0b8c736b1606..88383d3d5974 100644
--- a/drivers/media/v4l2-core/v4l2-fwnode.c
+++ b/drivers/media/v4l2-core/v4l2-fwnode.c
@@ -320,33 +320,6 @@ void v4l2_fwnode_put_link(struct v4l2_fwnode_link *link)
}
EXPORT_SYMBOL_GPL(v4l2_fwnode_put_link);
-static int v4l2_async_notifier_realloc(struct v4l2_async_notifier *notifier,
- unsigned int max_subdevs)
-{
- struct v4l2_async_subdev **subdevs;
-
- if (max_subdevs <= notifier->max_subdevs)
- return 0;
-
- subdevs = kvmalloc_array(
- max_subdevs, sizeof(*notifier->subdevs),
- GFP_KERNEL | __GFP_ZERO);
- if (!subdevs)
- return -ENOMEM;
-
- if (notifier->subdevs) {
- memcpy(subdevs, notifier->subdevs,
- sizeof(*subdevs) * notifier->num_subdevs);
-
- kvfree(notifier->subdevs);
- }
-
- notifier->subdevs = subdevs;
- notifier->max_subdevs = max_subdevs;
-
- return 0;
-}
-
static int v4l2_async_notifier_fwnode_parse_endpoint(
struct device *dev, struct v4l2_async_notifier *notifier,
struct fwnode_handle *endpoint, unsigned int asd_struct_size,
@@ -391,8 +364,13 @@ static int v4l2_async_notifier_fwnode_parse_endpoint(
if (ret < 0)
goto out_err;
- notifier->subdevs[notifier->num_subdevs] = asd;
- notifier->num_subdevs++;
+ ret = v4l2_async_notifier_add_subdev(notifier, asd);
+ if (ret < 0) {
+ /* not an error if asd already exists */
+ if (ret == -EEXIST)
+ ret = 0;
+ goto out_err;
+ }
return 0;
@@ -411,8 +389,7 @@ static int __v4l2_async_notifier_parse_fwnode_endpoints(
struct v4l2_async_subdev *asd))
{
struct fwnode_handle *fwnode;
- unsigned int max_subdevs = notifier->max_subdevs;
- int ret;
+ int ret = 0;
if (WARN_ON(asd_struct_size < sizeof(struct v4l2_async_subdev)))
return -EINVAL;
@@ -432,40 +409,6 @@ static int __v4l2_async_notifier_parse_fwnode_endpoints(
struct fwnode_endpoint ep;
ret = fwnode_graph_parse_endpoint(fwnode, &ep);
- if (ret) {
- fwnode_handle_put(fwnode);
- return ret;
- }
-
- if (ep.port != port)
- continue;
- }
- max_subdevs++;
- }
-
- /* No subdevs to add? Return here. */
- if (max_subdevs == notifier->max_subdevs)
- return 0;
-
- ret = v4l2_async_notifier_realloc(notifier, max_subdevs);
- if (ret)
- return ret;
-
- for (fwnode = NULL; (fwnode = fwnode_graph_get_next_endpoint(
- dev_fwnode(dev), fwnode)); ) {
- struct fwnode_handle *dev_fwnode;
- bool is_available;
-
- dev_fwnode = fwnode_graph_get_port_parent(fwnode);
- is_available = fwnode_device_is_available(dev_fwnode);
- fwnode_handle_put(dev_fwnode);
- if (!is_available)
- continue;
-
- if (has_port) {
- struct fwnode_endpoint ep;
-
- ret = fwnode_graph_parse_endpoint(fwnode, &ep);
if (ret)
break;
@@ -473,11 +416,6 @@ static int __v4l2_async_notifier_parse_fwnode_endpoints(
continue;
}
- if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) {
- ret = -EINVAL;
- break;
- }
-
ret = v4l2_async_notifier_fwnode_parse_endpoint(
dev, notifier, fwnode, asd_struct_size, parse_endpoint);
if (ret < 0)
@@ -548,31 +486,23 @@ static int v4l2_fwnode_reference_parse(
if (ret != -ENOENT && ret != -ENODATA)
return ret;
- ret = v4l2_async_notifier_realloc(notifier,
- notifier->num_subdevs + index);
- if (ret)
- return ret;
-
for (index = 0; !fwnode_property_get_reference_args(
dev_fwnode(dev), prop, NULL, 0, index, &args);
index++) {
struct v4l2_async_subdev *asd;
- if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) {
- ret = -EINVAL;
- goto error;
- }
+ asd = v4l2_async_notifier_add_fwnode_subdev(
+ notifier, args.fwnode, sizeof(*asd));
+ if (IS_ERR(asd)) {
+ ret = PTR_ERR(asd);
+ /* not an error if asd already exists */
+ if (ret == -EEXIST) {
+ fwnode_handle_put(args.fwnode);
+ continue;
+ }
- asd = kzalloc(sizeof(*asd), GFP_KERNEL);
- if (!asd) {
- ret = -ENOMEM;
goto error;
}
-
- notifier->subdevs[notifier->num_subdevs] = asd;
- asd->match.fwnode = args.fwnode;
- asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
- notifier->num_subdevs++;
}
return 0;
@@ -843,31 +773,23 @@ static int v4l2_fwnode_reference_parse_int_props(
index++;
} while (1);
- ret = v4l2_async_notifier_realloc(notifier,
- notifier->num_subdevs + index);
- if (ret)
- return -ENOMEM;
-
for (index = 0; !IS_ERR((fwnode = v4l2_fwnode_reference_get_int_prop(
dev_fwnode(dev), prop, index, props,
nprops))); index++) {
struct v4l2_async_subdev *asd;
- if (WARN_ON(notifier->num_subdevs >= notifier->max_subdevs)) {
- ret = -EINVAL;
- goto error;
- }
+ asd = v4l2_async_notifier_add_fwnode_subdev(notifier, fwnode,
+ sizeof(*asd));
+ if (IS_ERR(asd)) {
+ ret = PTR_ERR(asd);
+ /* not an error if asd already exists */
+ if (ret == -EEXIST) {
+ fwnode_handle_put(fwnode);
+ continue;
+ }
- asd = kzalloc(sizeof(struct v4l2_async_subdev), GFP_KERNEL);
- if (!asd) {
- ret = -ENOMEM;
goto error;
}
-
- notifier->subdevs[notifier->num_subdevs] = asd;
- asd->match.fwnode = fwnode;
- asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
- notifier->num_subdevs++;
}
return PTR_ERR(fwnode) == -ENOENT ? 0 : PTR_ERR(fwnode);
@@ -924,6 +846,8 @@ int v4l2_async_register_subdev_sensor_common(struct v4l2_subdev *sd)
if (!notifier)
return -ENOMEM;
+ v4l2_async_notifier_init(notifier);
+
ret = v4l2_async_notifier_parse_fwnode_sensor_common(sd->dev,
notifier);
if (ret < 0)