All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
To: Dan Scally <djrscally@gmail.com>, Sakari Ailus <sakari.ailus@iki.fi>
Cc: gregkh@linuxfoundation.org, rafael@kernel.org,
	linux-kernel@vger.kernel.org, linux-media@vger.kernel.org,
	heikki.krogerus@linux.intel.com,
	andriy.shevchenko@linux.intel.com, jorhand@linux.microsoft.com,
	kitakar@gmail.com
Subject: Re: [PATCH v2] software_node: Add support for fwnode_graph*() family of functions
Date: Wed, 16 Sep 2020 16:06:25 +0100	[thread overview]
Message-ID: <4a355889-6e65-70e0-1646-bb832579fd91@ideasonboard.com> (raw)
In-Reply-To: <7b81d743-736d-62d1-7072-d08759a0d5d7@gmail.com>

Hi Dan,

On 16/09/2020 14:22, Dan Scally wrote:
> Hi Sakari - thanks for the comments
> 
> On 16/09/2020 10:17, Sakari Ailus wrote:
>> Moi Daniel and Heikki,
>>
>> On Wed, Sep 16, 2020 at 12:28:27AM +0100, Daniel Scally wrote:
>>> From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
>>>
>>> This implements the remaining .graph_* callbacks in the
>>> fwnode operations vector for the software nodes. That makes
>>> the fwnode_graph*() functions available in the drivers also
>>> when software nodes are used.
>>>
>>> The implementation tries to mimic the "OF graph" as much as
>>> possible, but there is no support for the "reg" device
>>> property. The ports will need to have the index in their
>>> name which starts with "port" (for example "port0", "port1",
>>> ...) and endpoints will use the index of the software node
>>> that is given to them during creation. The port nodes can
>>> also be grouped under a specially named "ports" subnode,
>>> just like in DT, if necessary.
>>>
>>> The remote-endpoints are reference properties under the
>>> endpoint nodes that are named "remote-endpoint". 
>>>
>>> Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
>>> Co-developed-by: Daniel Scally <djrscally@gmail.com>
>>> Signed-off-by: Daniel Scally <djrscally@gmail.com>
>>> ---
>>> changes in v2:
>>> 	- added software_node_device_is_available
>>> 	- altered software_node_get_next_child to get references
>>> 	- altered software_node_get_next_endpoint to release references
>>> 	to ports and avoid passing invalid combinations of swnodes to
>>> 	software_node_get_next_child
>>> 	- altered swnode_graph_find_next_port to release port rather than
>>> 	old
>>> 	
>>>  drivers/base/swnode.c | 129 +++++++++++++++++++++++++++++++++++++++++-
>>>  1 file changed, 127 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
>>> index 010828fc785b..d69034b807e3 100644
>>> --- a/drivers/base/swnode.c
>>> +++ b/drivers/base/swnode.c
>>> @@ -363,6 +363,11 @@ static void software_node_put(struct fwnode_handle *fwnode)
>>>  	kobject_put(&swnode->kobj);
>>>  }
>>>  
>>> +static bool software_node_device_is_available(const struct fwnode_handle *fwnode)
>>> +{
>>> +	return is_software_node(fwnode);
>> This basically tells whether the device is there. Are there software node
>> based devices, i.e. do you need this?
>>
>> If you do really need this, then I guess this could just return true for
>> now as if you somehow get here, the node is a software node anyway.
> 
> I do think its better to include it; I'm targeting using this with
> ipu3-cio2; the cio2_parse_firmware() call there doesn't pass
> FWNODE_GRAPH_DEVICE_DISABLED to fwnode_graph_get_endpoint_by_id() so
> this function does need to exist to be found by that call (or else
> cio2_parse_firmware() would need to pass that flag...but I don't know
> the effect of doing that on devices that aren't using software nodes so
> it didn't seem like a good idea). I can change it to return true though sure
> 
>>> +}
>>> +
>>>  static bool software_node_property_present(const struct fwnode_handle *fwnode,
>>>  					   const char *propname)
>>>  {
>>> @@ -450,7 +455,7 @@ software_node_get_next_child(const struct fwnode_handle *fwnode,
>>>  		c = list_next_entry(c, entry);
>>>  	else
>>>  		c = list_first_entry(&p->children, struct swnode, entry);
>>> -	return &c->fwnode;
>>> +	return software_node_get(&c->fwnode);
>> This looks like a bugfix that probably should or could be backported. Could
>> you make it a separate patch, with a Fixes: tag?
> Yes, sure. That does change how some of the other code would need to
> work though if this patch were applied but not the separated one. Sorry;
> not sure what's the best way to proceed in that case. Should I just note
> that this patch depends on the prior application of the separated one?

I think the assumption is that this individual change to
software_node_property_present() should be in a patch on it's own
preceeding 'this' one.

Running git-blame on drivers/base/swnode.c identifies this line as
previously being added by: 59abd83672f70, so you would add the tag:

Fixes: 59abd83672f7 ("drivers: base: Introducing software nodes to the
firmware node framework")

to the 'fixing' patch, and that can be backported accordingly.

When patches are sent in a series, the dependency becomes implicit.
You can do this by specifying a range when you do `git format-patch`

If you want to save off the last '2' patches, you can use a range
shorthand of '-2':

for example:

  git format-patch -2 -v3 --cover-letter -o patches/swnode

As it's a 'series' we add a cover letter to group them, and that gives a
location to add some free-form text as you wish too.

--
Kieran


>>
>>>  }
>>>  
>>>  static struct fwnode_handle *
>>> @@ -536,9 +541,125 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode,
>>>  	return 0;
>>>  }
>>>  
>>> +static struct fwnode_handle *
>>> +swnode_graph_find_next_port(const struct fwnode_handle *parent,
>>> +			    struct fwnode_handle *port)
>>> +{
>>> +	struct fwnode_handle *old = port;
>>> +
>>> +	while ((port = software_node_get_next_child(parent, old))) {
>>> +		if (!strncmp(to_swnode(port)->node->name, "port", 4))
>>> +			return port;
>>> +		fwnode_handle_put(port);
>>> +		old = port;
>>> +	}
>>> +
>>> +	return NULL;
>>> +}
>>> +
>>> +static struct fwnode_handle *
>>> +software_node_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
>>> +				      struct fwnode_handle *endpoint)
>>> +{
>>> +	struct swnode *swnode = to_swnode(fwnode);
>>> +	struct fwnode_handle *old = endpoint;
>>> +	struct fwnode_handle *parent_of_old;
>>> +	struct fwnode_handle *parent;
>>> +	struct fwnode_handle *port;
>>> +
>>> +	if (!swnode)
>>> +		return NULL;
>>> +
>>> +	if (endpoint) {
>>> +		port = software_node_get_parent(endpoint);
>>> +		parent = software_node_get_parent(port);
>>> +	} else {
>>> +		parent = software_node_get_named_child_node(fwnode, "ports");
>>> +		if (!parent)
>>> +			parent = software_node_get(&swnode->fwnode);
>>> +
>>> +		port = swnode_graph_find_next_port(parent, NULL);
>>> +	}
>>> +
>>> +	for (; port; port = swnode_graph_find_next_port(parent, port)) {
>>> +
>>> +		if (old) {
>>> +			parent_of_old = software_node_get_parent(old);
>>> +
>>> +			if (parent_of_old != port)
>>> +				old = NULL;
>>> +
>>> +			fwnode_handle_put(parent_of_old);
>>> +		}
>>> +
>>> +		endpoint = software_node_get_next_child(port, old);
>>> +		fwnode_handle_put(old);
>>> +		if (endpoint)
>>> +			break;
>>> +
>>> +		fwnode_handle_put(port);
>>> +	}
>>> +
>>> +	fwnode_handle_put(port);
>>> +	software_node_put(parent);
>> This probably should be fwnode_handle_put() as well as this is basically
>> corresponding the device (i.e. likely not a software node).
> Yep good point, fwnode_handle_put() it is.
>>> +
>>> +	return endpoint;
>>> +}
>>> +
>>> +static struct fwnode_handle *
>>> +software_node_graph_get_remote_endpoint(const struct fwnode_handle *fwnode)
>>> +{
>>> +	struct swnode *swnode = to_swnode(fwnode);
>>> +	const struct software_node_ref_args *ref;
>>> +	const struct property_entry *prop;
>>> +
>>> +	if (!swnode)
>>> +		return NULL;
>>> +
>>> +	prop = property_entry_get(swnode->node->properties, "remote-endpoint");
>>> +	if (!prop || prop->type != DEV_PROP_REF || prop->is_inline)
>>> +		return NULL;
>>> +
>>> +	ref = prop->pointer;
>>> +
>>> +	return software_node_get(software_node_fwnode(ref[0].node));
>>> +}
>>> +
>>> +static struct fwnode_handle *
>>> +software_node_graph_get_port_parent(struct fwnode_handle *fwnode)
>>> +{
>>> +	struct swnode *swnode = to_swnode(fwnode);
>>> +	struct fwnode_handle *parent;
>>> +
>>> +	if (!strcmp(swnode->parent->node->name, "ports"))
>>> +		parent = &swnode->parent->parent->fwnode;
>>> +	else
>>> +		parent = &swnode->parent->fwnode;
>>> +
>>> +	return software_node_get(parent);
>>> +}
>>> +
>>> +static int
>>> +software_node_graph_parse_endpoint(const struct fwnode_handle *fwnode,
>>> +				   struct fwnode_endpoint *endpoint)
>>> +{
>>> +	struct swnode *swnode = to_swnode(fwnode);
>>> +	int ret;
>>> +
>>> +	ret = kstrtou32(swnode->parent->node->name + 4, 10, &endpoint->port);
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	endpoint->id = swnode->id;
>>> +	endpoint->local_fwnode = fwnode;
>>> +
>>> +	return 0;
>>> +}
>>> +
>>>  static const struct fwnode_operations software_node_ops = {
>>>  	.get = software_node_get,
>>>  	.put = software_node_put,
>>> +	.device_is_available = software_node_device_is_available,
>>>  	.property_present = software_node_property_present,
>>>  	.property_read_int_array = software_node_read_int_array,
>>>  	.property_read_string_array = software_node_read_string_array,
>>> @@ -547,7 +668,11 @@ static const struct fwnode_operations software_node_ops = {
>>>  	.get_parent = software_node_get_parent,
>>>  	.get_next_child_node = software_node_get_next_child,
>>>  	.get_named_child_node = software_node_get_named_child_node,
>>> -	.get_reference_args = software_node_get_reference_args
>>> +	.get_reference_args = software_node_get_reference_args,
>>> +	.graph_get_next_endpoint = software_node_graph_get_next_endpoint,
>>> +	.graph_get_remote_endpoint = software_node_graph_get_remote_endpoint,
>>> +	.graph_get_port_parent = software_node_graph_get_port_parent,
>>> +	.graph_parse_endpoint = software_node_graph_parse_endpoint,
>>>  };
>>>  
>>>  /* -------------------------------------------------------------------------- */

  parent reply	other threads:[~2020-09-16 20:39 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-09-15 23:28 [PATCH v2] software_node: Add support for fwnode_graph*() family of functions Daniel Scally
2020-09-16  9:17 ` Sakari Ailus
2020-09-16 13:22   ` Dan Scally
2020-09-16 14:32     ` Andy Shevchenko
2020-09-16 15:06     ` Kieran Bingham [this message]
2020-09-16 16:10       ` Andy Shevchenko
2020-09-18  6:22     ` Sakari Ailus
2020-09-18  6:49       ` Dan Scally
2020-09-18  7:34         ` Sakari Ailus
2020-09-18  7:46           ` Dan Scally
2020-09-18  7:57             ` Sakari Ailus
     [not found]               ` <20200918085709.GA1630537@kuha.fi.intel.com>
2020-09-18  9:10                 ` Dan Scally
2020-09-18  9:15                 ` Sakari Ailus
2020-09-18  9:22                   ` Dan Scally
2020-09-18 12:42               ` Andy Shevchenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4a355889-6e65-70e0-1646-bb832579fd91@ideasonboard.com \
    --to=kieran.bingham+renesas@ideasonboard.com \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=djrscally@gmail.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=heikki.krogerus@linux.intel.com \
    --cc=jorhand@linux.microsoft.com \
    --cc=kitakar@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=rafael@kernel.org \
    --cc=sakari.ailus@iki.fi \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.