Hi Kieran, On Tue, May 23, 2017 at 06:40:08PM +0100, Kieran Bingham wrote: > On 23/05/17 14:02, Sakari Ailus wrote: > > Hi Kieran, > > > > On Mon, May 22, 2017 at 06:36:38PM +0100, Kieran Bingham wrote: > >> From: Kieran Bingham <kieran.bingham+renesas@xxxxxxxxxxxxxxxx> > >> > >> Devices supporting multiple endpoints on a single device node must set > >> their subdevice fwnode to the endpoint to allow distinct comparisons. > >> > >> Adapt the match_fwnode call to compare against the provided fwnodes > >> first, but also to search for a comparison against the parent fwnode. > >> > >> This allows notifiers to pass the endpoint for comparison and still > >> support existing subdevices which store their default parent device > >> node. > >> > >> Signed-off-by: Kieran Bingham <kieran.bingham+renesas@xxxxxxxxxxxxxxxx> > >> > >> --- > >> v2: > >> - Added documentation comments > >> - simplified the OF match by adding match_fwnode_of() > >> > >> v3: > >> - Fix comments > >> - Fix sd_parent, and asd_parent usage > >> > >> drivers/media/v4l2-core/v4l2-async.c | 36 ++++++++++++++++++++++++----- > >> 1 file changed, 31 insertions(+), 5 deletions(-) > >> > >> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c > >> index cbd919d4edd2..12c0707851fd 100644 > >> --- a/drivers/media/v4l2-core/v4l2-async.c > >> +++ b/drivers/media/v4l2-core/v4l2-async.c > >> @@ -41,14 +41,40 @@ static bool match_devname(struct v4l2_subdev *sd, > >> return !strcmp(asd->match.device_name.name, dev_name(sd->dev)); > >> } > >> > >> +/* > >> + * Check whether the two device_node pointers refer to the same OF node. We > >> + * can't compare pointers directly as they can differ if overlays have been > >> + * applied. > >> + */ > >> +static bool match_fwnode_of(struct fwnode_handle *a, struct fwnode_handle *b) > >> +{ > >> + return !of_node_cmp(of_node_full_name(to_of_node(a)), > >> + of_node_full_name(to_of_node(b))); > >> +} > >> + > >> +/* > >> + * As a measure to support drivers which have not been converted to use > >> + * endpoint matching, we also find the parent devices for cross-matching. > >> + * > >> + * When all devices use endpoint matching, this code can be simplified, and the > >> + * parent comparisons can be removed. > >> + */ > >> static bool match_fwnode(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd) > >> { > >> - if (!is_of_node(sd->fwnode) || !is_of_node(asd->match.fwnode.fwnode)) > >> - return sd->fwnode == asd->match.fwnode.fwnode; > >> + struct fwnode_handle *asd_fwnode = asd->match.fwnode.fwnode; > >> + struct fwnode_handle *sd_parent, *asd_parent; > >> + > >> + sd_parent = fwnode_graph_get_port_parent(sd->fwnode); > >> + asd_parent = fwnode_graph_get_port_parent(asd_fwnode); > >> + > >> + if (!is_of_node(sd->fwnode) || !is_of_node(asd_fwnode)) > >> + return sd->fwnode == asd_fwnode || > >> + sd_parent == asd_fwnode || > >> + sd->fwnode == asd_parent; > >> > >> - return !of_node_cmp(of_node_full_name(to_of_node(sd->fwnode)), > >> - of_node_full_name( > >> - to_of_node(asd->match.fwnode.fwnode))); > >> + return match_fwnode_of(sd->fwnode, asd_fwnode) || > >> + match_fwnode_of(sd_parent, asd_fwnode) || > >> + match_fwnode_of(sd->fwnode, asd_parent); > >> } > >> > >> static bool match_custom(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd) > > > > Would this become easier to read if you handled all matching in what is > > called match_fwnode_of() above, also for non-OF fwnodes? Essentially you'd > > have what used to be match_fwnode() there, and new match_fwnode() would call > > that function with all the three combinations. > > > > > > I'd call the other function __match_fwnode() for instance. > > > > > Yes - Took me a moment to understand what you meant here - but yes it's leaner + > cleaner: Looks quite nice! Thanks! :) > > > /* > * As a measure to support drivers which have not been converted to use > * endpoint matching, we also find the parent devices for cross-matching. > * > * When all devices use endpoint matching, this code can be simplified, and the > * parent comparisons can be removed. > */ > > static bool __match_fwnode(struct fwnode_handle *a, struct fwnode_handle *b) > { > if (is_of_node(a) || is_of_node(b)) I think you need && (not ||) although in practice I don't think it'd have made any difference. > return !of_node_cmp(of_node_full_name(to_of_node(a)), > of_node_full_name(to_of_node(b))); > else > return a == b; > } > > static bool match_fwnode(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd) > { > struct fwnode_handle *asd_fwnode = asd->match.fwnode.fwnode; > struct fwnode_handle *sd_parent, *asd_parent; > > sd_parent = fwnode_graph_get_port_parent(sd->fwnode); > asd_parent = fwnode_graph_get_port_parent(asd_fwnode); > > return __match_fwnode(sd->fwnode, asd_fwnode) || > __match_fwnode(sd_parent, asd_fwnode) || > __match_fwnode(sd->fwnode, asd_parent); > } > -- Kind regards, Sakari Ailus e-mail: sakari.ailus@xxxxxx XMPP: sailus@xxxxxxxxxxxxxx