Commit 9b4d2f37 authored by Sakari Ailus's avatar Sakari Ailus Committed by Mauro Carvalho Chehab

media: v4l: async: Only pass match information for async subdev validation

Pass only information required for sub-device matching to functions
checking whether the async sub-device already exists. Do the same for
debug message printing. This makes further changes to other aspects of
async sub-devices easier.

Accordingly, also perform further renames:

	asd_equal as v4l2_async_match_equal,
	v4l2_async_nf_has_async_subdev as v4l2_async_nf_has_async_match,
	__v4l2_async_nf_has_async_subdev as
		v4l2_async_nf_has_async_subdev_entry and
	v4l2_async_nf_asd_valid as v4l2_async_nf_match_valid.
Signed-off-by: default avatarSakari Ailus <sakari.ailus@linux.intel.com>
Tested-by: Philipp Zabel <p.zabel@pengutronix.de> # imx6qp
Tested-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> # rcar + adv746x
Reviewed-by: default avatarLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Tested-by: Aishwarya Kothari <aishwarya.kothari@toradex.com> # Apalis i.MX6Q with TC358743
Tested-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> # Renesas RZ/G2L SMARC
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@kernel.org>
parent 7a2259fc
...@@ -64,14 +64,15 @@ static void v4l2_async_nf_call_destroy(struct v4l2_async_notifier *n, ...@@ -64,14 +64,15 @@ static void v4l2_async_nf_call_destroy(struct v4l2_async_notifier *n,
} }
static bool match_i2c(struct v4l2_async_notifier *notifier, static bool match_i2c(struct v4l2_async_notifier *notifier,
struct v4l2_subdev *sd, struct v4l2_async_subdev *asd) struct v4l2_subdev *sd,
struct v4l2_async_match_desc *match)
{ {
#if IS_ENABLED(CONFIG_I2C) #if IS_ENABLED(CONFIG_I2C)
struct i2c_client *client = i2c_verify_client(sd->dev); struct i2c_client *client = i2c_verify_client(sd->dev);
return client && return client &&
asd->match.i2c.adapter_id == client->adapter->nr && match->i2c.adapter_id == client->adapter->nr &&
asd->match.i2c.address == client->addr; match->i2c.address == client->addr;
#else #else
return false; return false;
#endif #endif
...@@ -91,7 +92,7 @@ static struct device *notifier_dev(struct v4l2_async_notifier *notifier) ...@@ -91,7 +92,7 @@ static struct device *notifier_dev(struct v4l2_async_notifier *notifier)
static bool static bool
match_fwnode_one(struct v4l2_async_notifier *notifier, match_fwnode_one(struct v4l2_async_notifier *notifier,
struct v4l2_subdev *sd, struct fwnode_handle *sd_fwnode, struct v4l2_subdev *sd, struct fwnode_handle *sd_fwnode,
struct v4l2_async_subdev *asd) struct v4l2_async_match_desc *match)
{ {
struct fwnode_handle *other_fwnode; struct fwnode_handle *other_fwnode;
struct fwnode_handle *dev_fwnode; struct fwnode_handle *dev_fwnode;
...@@ -101,14 +102,14 @@ match_fwnode_one(struct v4l2_async_notifier *notifier, ...@@ -101,14 +102,14 @@ match_fwnode_one(struct v4l2_async_notifier *notifier,
dev_dbg(notifier_dev(notifier), dev_dbg(notifier_dev(notifier),
"v4l2-async: fwnode match: need %pfw, trying %pfw\n", "v4l2-async: fwnode match: need %pfw, trying %pfw\n",
sd_fwnode, asd->match.fwnode); sd_fwnode, match->fwnode);
/* /*
* Both the subdev and the async subdev can provide either an endpoint * Both the subdev and the async subdev can provide either an endpoint
* fwnode or a device fwnode. Start with the simple case of direct * fwnode or a device fwnode. Start with the simple case of direct
* fwnode matching. * fwnode matching.
*/ */
if (sd_fwnode == asd->match.fwnode) { if (sd_fwnode == match->fwnode) {
dev_dbg(notifier_dev(notifier), dev_dbg(notifier_dev(notifier),
"v4l2-async: direct match found\n"); "v4l2-async: direct match found\n");
return true; return true;
...@@ -123,7 +124,7 @@ match_fwnode_one(struct v4l2_async_notifier *notifier, ...@@ -123,7 +124,7 @@ match_fwnode_one(struct v4l2_async_notifier *notifier,
* match unconnected endpoints. * 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); asd_fwnode_is_ep = fwnode_graph_is_endpoint(match->fwnode);
if (sd_fwnode_is_ep == asd_fwnode_is_ep) { if (sd_fwnode_is_ep == asd_fwnode_is_ep) {
dev_dbg(notifier_dev(notifier), dev_dbg(notifier_dev(notifier),
...@@ -137,9 +138,9 @@ match_fwnode_one(struct v4l2_async_notifier *notifier, ...@@ -137,9 +138,9 @@ match_fwnode_one(struct v4l2_async_notifier *notifier,
*/ */
if (sd_fwnode_is_ep) { 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; other_fwnode = match->fwnode;
} else { } else {
dev_fwnode = fwnode_graph_get_port_parent(asd->match.fwnode); dev_fwnode = fwnode_graph_get_port_parent(match->fwnode);
other_fwnode = sd_fwnode; other_fwnode = sd_fwnode;
} }
...@@ -179,13 +180,14 @@ match_fwnode_one(struct v4l2_async_notifier *notifier, ...@@ -179,13 +180,14 @@ match_fwnode_one(struct v4l2_async_notifier *notifier,
} }
static bool match_fwnode(struct v4l2_async_notifier *notifier, static bool match_fwnode(struct v4l2_async_notifier *notifier,
struct v4l2_subdev *sd, struct v4l2_async_subdev *asd) struct v4l2_subdev *sd,
struct v4l2_async_match_desc *match)
{ {
dev_dbg(notifier_dev(notifier), dev_dbg(notifier_dev(notifier),
"v4l2-async: matching for notifier %pfw, sd fwnode %pfw\n", "v4l2-async: matching for notifier %pfw, sd fwnode %pfw\n",
dev_fwnode(notifier_dev(notifier)), sd->fwnode); dev_fwnode(notifier_dev(notifier)), sd->fwnode);
if (match_fwnode_one(notifier, sd, sd->fwnode, asd)) if (match_fwnode_one(notifier, sd, sd->fwnode, match))
return true; return true;
/* Also check the secondary fwnode. */ /* Also check the secondary fwnode. */
...@@ -195,7 +197,7 @@ static bool match_fwnode(struct v4l2_async_notifier *notifier, ...@@ -195,7 +197,7 @@ static bool match_fwnode(struct v4l2_async_notifier *notifier,
dev_dbg(notifier_dev(notifier), dev_dbg(notifier_dev(notifier),
"v4l2-async: trying secondary fwnode match\n"); "v4l2-async: trying secondary fwnode match\n");
return match_fwnode_one(notifier, sd, sd->fwnode->secondary, asd); return match_fwnode_one(notifier, sd, sd->fwnode->secondary, match);
} }
static LIST_HEAD(subdev_list); static LIST_HEAD(subdev_list);
...@@ -207,7 +209,8 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier, ...@@ -207,7 +209,8 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier,
struct v4l2_subdev *sd) struct v4l2_subdev *sd)
{ {
bool (*match)(struct v4l2_async_notifier *notifier, bool (*match)(struct v4l2_async_notifier *notifier,
struct v4l2_subdev *sd, struct v4l2_async_subdev *asd); struct v4l2_subdev *sd,
struct v4l2_async_match_desc *match);
struct v4l2_async_subdev *asd; struct v4l2_async_subdev *asd;
list_for_each_entry(asd, &notifier->waiting, list) { list_for_each_entry(asd, &notifier->waiting, list) {
...@@ -226,28 +229,26 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier, ...@@ -226,28 +229,26 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier,
} }
/* match cannot be NULL here */ /* match cannot be NULL here */
if (match(notifier, sd, asd)) if (match(notifier, sd, &asd->match))
return asd; return asd;
} }
return NULL; return NULL;
} }
/* Compare two async sub-device descriptors for equivalence */ /* Compare two async match descriptors for equivalence */
static bool asd_equal(struct v4l2_async_subdev *asd_x, static bool v4l2_async_match_equal(struct v4l2_async_match_desc *match1,
struct v4l2_async_subdev *asd_y) struct v4l2_async_match_desc *match2)
{ {
if (asd_x->match.type != asd_y->match.type) if (match1->type != match2->type)
return false; return false;
switch (asd_x->match.type) { switch (match1->type) {
case V4L2_ASYNC_MATCH_TYPE_I2C: case V4L2_ASYNC_MATCH_TYPE_I2C:
return asd_x->match.i2c.adapter_id == return match1->i2c.adapter_id == match2->i2c.adapter_id &&
asd_y->match.i2c.adapter_id && match1->i2c.address == match2->i2c.address;
asd_x->match.i2c.address ==
asd_y->match.i2c.address;
case V4L2_ASYNC_MATCH_TYPE_FWNODE: case V4L2_ASYNC_MATCH_TYPE_FWNODE:
return asd_x->match.fwnode == asd_y->match.fwnode; return match1->fwnode == match2->fwnode;
default: default:
break; break;
} }
...@@ -497,21 +498,21 @@ v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier, ...@@ -497,21 +498,21 @@ v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier,
/* See if an async sub-device can be found in a notifier's lists. */ /* See if an async sub-device can be found in a notifier's lists. */
static bool static bool
__v4l2_async_nf_has_async_subdev(struct v4l2_async_notifier *notifier, v4l2_async_nf_has_async_match_entry(struct v4l2_async_notifier *notifier,
struct v4l2_async_subdev *asd) struct v4l2_async_match_desc *match)
{ {
struct v4l2_async_subdev *asd_y; struct v4l2_async_subdev *asd;
struct v4l2_subdev *sd; struct v4l2_subdev *sd;
list_for_each_entry(asd_y, &notifier->waiting, list) list_for_each_entry(asd, &notifier->waiting, list)
if (asd_equal(asd, asd_y)) if (v4l2_async_match_equal(&asd->match, match))
return true; return true;
list_for_each_entry(sd, &notifier->done, async_list) { list_for_each_entry(sd, &notifier->done, async_list) {
if (WARN_ON(!sd->asd)) if (WARN_ON(!sd->asd))
continue; continue;
if (asd_equal(asd, sd->asd)) if (v4l2_async_match_equal(&sd->asd->match, match))
return true; return true;
} }
...@@ -525,46 +526,48 @@ __v4l2_async_nf_has_async_subdev(struct v4l2_async_notifier *notifier, ...@@ -525,46 +526,48 @@ __v4l2_async_nf_has_async_subdev(struct v4l2_async_notifier *notifier,
* the notifier. * the notifier.
*/ */
static bool static bool
v4l2_async_nf_has_async_subdev(struct v4l2_async_notifier *notifier, v4l2_async_nf_has_async_match(struct v4l2_async_notifier *notifier,
struct v4l2_async_subdev *asd, bool skip_self) struct v4l2_async_match_desc *match,
bool skip_self)
{ {
struct v4l2_async_subdev *asd_y; struct v4l2_async_subdev *asd;
lockdep_assert_held(&list_lock); lockdep_assert_held(&list_lock);
/* Check that an asd is not being added more than once. */ /* Check that an asd is not being added more than once. */
list_for_each_entry(asd_y, &notifier->asd_list, asd_list) { list_for_each_entry(asd, &notifier->asd_list, asd_list) {
if (skip_self && asd == asd_y) if (skip_self && &asd->match == match)
continue; continue;
if (asd_equal(asd, asd_y)) if (v4l2_async_match_equal(&asd->match, match))
return true; return true;
} }
/* Check that an asd does not exist in other notifiers. */ /* Check that an asd does not exist in other notifiers. */
list_for_each_entry(notifier, &notifier_list, list) list_for_each_entry(notifier, &notifier_list, list)
if (__v4l2_async_nf_has_async_subdev(notifier, asd)) if (v4l2_async_nf_has_async_match_entry(notifier, match))
return true; return true;
return false; return false;
} }
static int v4l2_async_nf_asd_valid(struct v4l2_async_notifier *notifier, static int v4l2_async_nf_match_valid(struct v4l2_async_notifier *notifier,
struct v4l2_async_subdev *asd, struct v4l2_async_match_desc *match,
bool skip_self) bool skip_self)
{ {
struct device *dev = notifier_dev(notifier); struct device *dev = notifier_dev(notifier);
switch (asd->match.type) { switch (match->type) {
case V4L2_ASYNC_MATCH_TYPE_I2C: case V4L2_ASYNC_MATCH_TYPE_I2C:
case V4L2_ASYNC_MATCH_TYPE_FWNODE: case V4L2_ASYNC_MATCH_TYPE_FWNODE:
if (v4l2_async_nf_has_async_subdev(notifier, asd, skip_self)) { if (v4l2_async_nf_has_async_match(notifier, match,
dev_dbg(dev, "v4l2-async: subdev descriptor already listed in a notifier\n"); skip_self)) {
dev_dbg(dev, "v4l2-async: match descriptor already listed in a notifier\n");
return -EEXIST; return -EEXIST;
} }
break; break;
default: default:
dev_err(dev, "v4l2-async: Invalid match type %u on %p\n", dev_err(dev, "v4l2-async: Invalid match type %u on %p\n",
asd->match.type, asd); match->type, match);
return -EINVAL; return -EINVAL;
} }
...@@ -588,7 +591,7 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier) ...@@ -588,7 +591,7 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
mutex_lock(&list_lock); mutex_lock(&list_lock);
list_for_each_entry(asd, &notifier->asd_list, asd_list) { list_for_each_entry(asd, &notifier->asd_list, asd_list) {
ret = v4l2_async_nf_asd_valid(notifier, asd, true); ret = v4l2_async_nf_match_valid(notifier, &asd->match, true);
if (ret) if (ret)
goto err_unlock; goto err_unlock;
...@@ -722,7 +725,7 @@ static int __v4l2_async_nf_add_subdev(struct v4l2_async_notifier *notifier, ...@@ -722,7 +725,7 @@ static int __v4l2_async_nf_add_subdev(struct v4l2_async_notifier *notifier,
mutex_lock(&list_lock); mutex_lock(&list_lock);
ret = v4l2_async_nf_asd_valid(notifier, asd, false); ret = v4l2_async_nf_match_valid(notifier, &asd->match, false);
if (ret) if (ret)
goto unlock; goto unlock;
...@@ -902,16 +905,16 @@ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd) ...@@ -902,16 +905,16 @@ void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
} }
EXPORT_SYMBOL(v4l2_async_unregister_subdev); EXPORT_SYMBOL(v4l2_async_unregister_subdev);
static void print_waiting_subdev(struct seq_file *s, static void print_waiting_match(struct seq_file *s,
struct v4l2_async_subdev *asd) struct v4l2_async_match_desc *match)
{ {
switch (asd->match.type) { switch (match->type) {
case V4L2_ASYNC_MATCH_TYPE_I2C: case V4L2_ASYNC_MATCH_TYPE_I2C:
seq_printf(s, " [i2c] dev=%d-%04x\n", asd->match.i2c.adapter_id, seq_printf(s, " [i2c] dev=%d-%04x\n", match->i2c.adapter_id,
asd->match.i2c.address); match->i2c.address);
break; break;
case V4L2_ASYNC_MATCH_TYPE_FWNODE: { case V4L2_ASYNC_MATCH_TYPE_FWNODE: {
struct fwnode_handle *devnode, *fwnode = asd->match.fwnode; struct fwnode_handle *devnode, *fwnode = match->fwnode;
devnode = fwnode_graph_is_endpoint(fwnode) ? devnode = fwnode_graph_is_endpoint(fwnode) ?
fwnode_graph_get_port_parent(fwnode) : fwnode_graph_get_port_parent(fwnode) :
...@@ -948,7 +951,7 @@ static int pending_subdevs_show(struct seq_file *s, void *data) ...@@ -948,7 +951,7 @@ static int pending_subdevs_show(struct seq_file *s, void *data)
list_for_each_entry(notif, &notifier_list, list) { list_for_each_entry(notif, &notifier_list, list) {
seq_printf(s, "%s:\n", v4l2_async_nf_name(notif)); seq_printf(s, "%s:\n", v4l2_async_nf_name(notif));
list_for_each_entry(asd, &notif->waiting, list) list_for_each_entry(asd, &notif->waiting, list)
print_waiting_subdev(s, asd); print_waiting_match(s, &asd->match);
} }
mutex_unlock(&list_lock); mutex_unlock(&list_lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment