diff options
Diffstat (limited to 'drivers/media/v4l2-core/v4l2-async.c')
| -rw-r--r-- | drivers/media/v4l2-core/v4l2-async.c | 45 | 
1 files changed, 31 insertions, 14 deletions
diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index c6995718237a..2f1b718a9189 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -52,6 +52,15 @@ static int v4l2_async_nf_call_complete(struct v4l2_async_notifier *n)  	return n->ops->complete(n);  } +static void v4l2_async_nf_call_destroy(struct v4l2_async_notifier *n, +				       struct v4l2_async_subdev *asd) +{ +	if (!n->ops || !n->ops->destroy) +		return; + +	n->ops->destroy(asd); +} +  static bool match_i2c(struct v4l2_async_notifier *notifier,  		      struct v4l2_subdev *sd, struct v4l2_async_subdev *asd)  { @@ -66,8 +75,10 @@ static bool match_i2c(struct v4l2_async_notifier *notifier,  #endif  } -static bool match_fwnode(struct v4l2_async_notifier *notifier, -			 struct v4l2_subdev *sd, struct v4l2_async_subdev *asd) +static bool +match_fwnode_one(struct v4l2_async_notifier *notifier, +		 struct v4l2_subdev *sd, struct fwnode_handle *sd_fwnode, +		 struct v4l2_async_subdev *asd)  {  	struct fwnode_handle *other_fwnode;  	struct fwnode_handle *dev_fwnode; @@ -80,15 +91,7 @@ static bool match_fwnode(struct v4l2_async_notifier *notifier,  	 * fwnode or a device fwnode. Start with the simple case of direct  	 * fwnode matching.  	 */ -	if (sd->fwnode == asd->match.fwnode) -		return true; - -	/* -	 * Check the same situation for any possible secondary assigned to the -	 * subdev's fwnode -	 */ -	if (!IS_ERR_OR_NULL(sd->fwnode->secondary) && -	    sd->fwnode->secondary == asd->match.fwnode) +	if (sd_fwnode == asd->match.fwnode)  		return true;  	/* @@ -99,7 +102,7 @@ static bool match_fwnode(struct v4l2_async_notifier *notifier,  	 * ACPI. This won't make a difference, as drivers should not try to  	 * match unconnected endpoints.  	 */ -	sd_fwnode_is_ep = fwnode_graph_is_endpoint(sd->fwnode); +	sd_fwnode_is_ep = fwnode_graph_is_endpoint(sd_fwnode);  	asd_fwnode_is_ep = fwnode_graph_is_endpoint(asd->match.fwnode);  	if (sd_fwnode_is_ep == asd_fwnode_is_ep) @@ -110,11 +113,11 @@ static bool match_fwnode(struct v4l2_async_notifier *notifier,  	 * parent of the endpoint fwnode, and compare it with the other fwnode.  	 */  	if (sd_fwnode_is_ep) { -		dev_fwnode = fwnode_graph_get_port_parent(sd->fwnode); +		dev_fwnode = fwnode_graph_get_port_parent(sd_fwnode);  		other_fwnode = asd->match.fwnode;  	} else {  		dev_fwnode = fwnode_graph_get_port_parent(asd->match.fwnode); -		other_fwnode = sd->fwnode; +		other_fwnode = sd_fwnode;  	}  	fwnode_handle_put(dev_fwnode); @@ -143,6 +146,19 @@ static bool match_fwnode(struct v4l2_async_notifier *notifier,  	return true;  } +static bool match_fwnode(struct v4l2_async_notifier *notifier, +			 struct v4l2_subdev *sd, struct v4l2_async_subdev *asd) +{ +	if (match_fwnode_one(notifier, sd, sd->fwnode, asd)) +		return true; + +	/* Also check the secondary fwnode. */ +	if (IS_ERR_OR_NULL(sd->fwnode->secondary)) +		return false; + +	return match_fwnode_one(notifier, sd, sd->fwnode->secondary, asd); +} +  static LIST_HEAD(subdev_list);  static LIST_HEAD(notifier_list);  static DEFINE_MUTEX(list_lock); @@ -626,6 +642,7 @@ static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)  		}  		list_del(&asd->asd_list); +		v4l2_async_nf_call_destroy(notifier, asd);  		kfree(asd);  	}  }  | 
