linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RFC] driver core: Ensure DT devices always have fwnode set
@ 2020-11-06 15:07 Mark Brown
  2020-11-06 19:09 ` Saravana Kannan
  0 siblings, 1 reply; 7+ messages in thread
From: Mark Brown @ 2020-11-06 15:07 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki
  Cc: Daniel Mentz, Saravana Kannan, linux-kernel, Mark Brown

Currently the fwnode API and things that rely on it like fw_devlink will
not reliably work for devices created from DT since each subsystem that
creates devices must individually set dev->fwnode in addition to setting
dev->of_node, currently a number of subsystems don't do so. Ensure that
this can't get missed by setting fwnode from of_node if it's not
previously been set by the subsystem.

Reported-by: Saravana Kannan <saravanak@google.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---

*Very* minimally tested.

 drivers/base/core.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/base/core.c b/drivers/base/core.c
index d661ada1518f..658626bafd76 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -2864,6 +2864,10 @@ int device_add(struct device *dev)
 	if (parent && (dev_to_node(dev) == NUMA_NO_NODE))
 		set_dev_node(dev, dev_to_node(parent));
 
+	/* ensure that fwnode is set up */
+	if (IS_ENABLED(CONFIG_OF) && dev->of_node && !dev->fwnode)
+		dev->fwnode = of_fwnode_handle(dev->of_node);
+
 	/* first, register with generic layer. */
 	/* we require the name to be set before, and pass NULL */
 	error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH RFC] driver core: Ensure DT devices always have fwnode set
  2020-11-06 15:07 [PATCH RFC] driver core: Ensure DT devices always have fwnode set Mark Brown
@ 2020-11-06 19:09 ` Saravana Kannan
  2020-11-06 19:23   ` Mark Brown
  2020-11-09 17:25   ` Rob Herring
  0 siblings, 2 replies; 7+ messages in thread
From: Saravana Kannan @ 2020-11-06 19:09 UTC (permalink / raw)
  To: Mark Brown
  Cc: Greg Kroah-Hartman, Rafael J . Wysocki, Daniel Mentz, LKML,
	Rob Herring, Frank Rowand

+Rob and Frank

On Fri, Nov 6, 2020 at 7:09 AM Mark Brown <broonie@kernel.org> wrote:
>
> Currently the fwnode API and things that rely on it like fw_devlink will
> not reliably work for devices created from DT since each subsystem that
> creates devices must individually set dev->fwnode in addition to setting
> dev->of_node, currently a number of subsystems don't do so. Ensure that
> this can't get missed by setting fwnode from of_node if it's not
> previously been set by the subsystem.
>
> Reported-by: Saravana Kannan <saravanak@google.com>
> Signed-off-by: Mark Brown <broonie@kernel.org>
> ---
>
> *Very* minimally tested.
>
>  drivers/base/core.c | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/drivers/base/core.c b/drivers/base/core.c
> index d661ada1518f..658626bafd76 100644
> --- a/drivers/base/core.c
> +++ b/drivers/base/core.c
> @@ -2864,6 +2864,10 @@ int device_add(struct device *dev)
>         if (parent && (dev_to_node(dev) == NUMA_NO_NODE))
>                 set_dev_node(dev, dev_to_node(parent));
>
> +       /* ensure that fwnode is set up */
> +       if (IS_ENABLED(CONFIG_OF) && dev->of_node && !dev->fwnode)
> +               dev->fwnode = of_fwnode_handle(dev->of_node);
> +

I don't think we should add more CONFIG_OF specific code in drivers/base/

If you want to do this in "one common place", then I think the way to
do this is have include/linux/of.h provide something like:
void of_set_device_of_node(dev, of_node)
{
    dev->of_node = of_node;
    dev->fw_node = &of_node->fwnode;
   /* bunch of other housekeeping like setting OF_POPULATED and doing
proper of_node_get() */
   // Passing NULL for of_node could undo all the above for dev->of_node.
}

And all the subsystems that create their own device from an of_node
should use of_set_device_of_node() to set the device's of_node. That
way, all this is done in a consistent manner across subsystems and
avoid all of the of_get/put() and OF_POPULATED set/clear strewn all
over the subsystems.

For example a bunch of subsystems don't do of_get()/of_put() correctly
when they det a device's of_node (I sent patches as I found them).

-Saravana

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH RFC] driver core: Ensure DT devices always have fwnode set
  2020-11-06 19:09 ` Saravana Kannan
@ 2020-11-06 19:23   ` Mark Brown
  2020-11-07  1:55     ` Saravana Kannan
  2020-11-09 17:25   ` Rob Herring
  1 sibling, 1 reply; 7+ messages in thread
From: Mark Brown @ 2020-11-06 19:23 UTC (permalink / raw)
  To: Saravana Kannan
  Cc: Greg Kroah-Hartman, Rafael J . Wysocki, Daniel Mentz, LKML,
	Rob Herring, Frank Rowand

[-- Attachment #1: Type: text/plain, Size: 750 bytes --]

On Fri, Nov 06, 2020 at 11:09:17AM -0800, Saravana Kannan wrote:

> If you want to do this in "one common place", then I think the way to
> do this is have include/linux/of.h provide something like:

> void of_set_device_of_node(dev, of_node)
> {
>     dev->of_node = of_node;
>     dev->fw_node = &of_node->fwnode;
>    /* bunch of other housekeeping like setting OF_POPULATED and doing
> proper of_node_get() */
>    // Passing NULL for of_node could undo all the above for dev->of_node.
> }

That also sounds good, particularly if we have a coccinelle spatch or
some other mechanism that enforced the usage of the function where
appropriate, my main concern is making sure that we do something which
ensures that the boilerplate stuff is handled.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH RFC] driver core: Ensure DT devices always have fwnode set
  2020-11-06 19:23   ` Mark Brown
@ 2020-11-07  1:55     ` Saravana Kannan
  2020-11-09 17:08       ` Mark Brown
  0 siblings, 1 reply; 7+ messages in thread
From: Saravana Kannan @ 2020-11-07  1:55 UTC (permalink / raw)
  To: Mark Brown
  Cc: Greg Kroah-Hartman, Rafael J . Wysocki, Daniel Mentz, LKML,
	Rob Herring, Frank Rowand

On Fri, Nov 6, 2020 at 11:23 AM Mark Brown <broonie@kernel.org> wrote:
>
> On Fri, Nov 06, 2020 at 11:09:17AM -0800, Saravana Kannan wrote:
>
> > If you want to do this in "one common place", then I think the way to
> > do this is have include/linux/of.h provide something like:
>
> > void of_set_device_of_node(dev, of_node)
> > {
> >     dev->of_node = of_node;
> >     dev->fw_node = &of_node->fwnode;
> >    /* bunch of other housekeeping like setting OF_POPULATED and doing
> > proper of_node_get() */
> >    // Passing NULL for of_node could undo all the above for dev->of_node.
> > }
>
> That also sounds good, particularly if we have a coccinelle spatch

I've never used coccinelle. But I can fix 5-10 easily findable ones
like i2c, platform, spi, slimbus, spmi, etc.

> or
> some other mechanism that enforced the usage of the function where
> appropriate, my main concern is making sure that we do something which
> ensures that the boilerplate stuff is handled.

Rob/Frank,

I spent an hour or more looking at this and there are many ways of
doing this. Wanted to know how much you wanted to do inside these
boilerplate functions.

This is the minimum we should do in these helper functions.

+/**
+ * of_unset_dev_of_node - Unset a device's of_node
+ * @dev - device to unset the of_node for
+ *
+ * Use this when you delete a device on which you had called
+ * of_set_dev_of_node() before.
+ */
+static inline void of_unset_dev_of_node(struct device *dev)
+{
+       struct device_node *node = dev->of_node
+
+       if (!node)
+               return;
+
+       dev->fwnode = NULL;
+       dev->of_node = NULL;
+       of_node_put(node);
+}
+
+/**
+ * of_set_dev_of_node - Set a device's of_node
+ * @dev - device to set the of_node for
+ * @node - the device_node that the device was constructed from
+ *
+ * Use this when you create a new device from a device_node. It takes care some
+ * of the housekeeping work that's necessary when you set a device's of_node.
+ *
+ * Use of_unset_dev_of_node() before you delete the device.
+ *
+ * Returns an error if the device already has its of_node set.
+ */
+static inline int of_set_dev_of_node(struct device *dev, struct
device_node *node)
+{
+       if (!node)
+               return 0;
+
+       if (WARN_ON(dev->of_node))
+               return -EBUSY;
+
+       of_node_get(node);
+       dev->of_node = node;
+       dev->fwnode = of_fwnode_handle(node);
+
+       return 0;
+}

But I also had another version that set/cleared OF_POPULATED. But that
meant of_device_alloc() will allocate the device before checking if
the node has already been populated (because I'd delete the check
that's already there and use the one rolled into these helper
functions). I think that inefficiency is okay because I don't think
"trying to populate an already populated node" would be a common
occurrence. But I wasn't sure how you'd feel about it.

Any preferences? Thoughts?

Additional context:
https://lore.kernel.org/lkml/20201104205431.3795207-2-saravanak@google.com/

-Saravana

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH RFC] driver core: Ensure DT devices always have fwnode set
  2020-11-07  1:55     ` Saravana Kannan
@ 2020-11-09 17:08       ` Mark Brown
  0 siblings, 0 replies; 7+ messages in thread
From: Mark Brown @ 2020-11-09 17:08 UTC (permalink / raw)
  To: Saravana Kannan
  Cc: Greg Kroah-Hartman, Rafael J . Wysocki, Daniel Mentz, LKML,
	Rob Herring, Frank Rowand

[-- Attachment #1: Type: text/plain, Size: 543 bytes --]

On Fri, Nov 06, 2020 at 05:55:10PM -0800, Saravana Kannan wrote:
> On Fri, Nov 6, 2020 at 11:23 AM Mark Brown <broonie@kernel.org> wrote:

> > That also sounds good, particularly if we have a coccinelle spatch

> I've never used coccinelle. But I can fix 5-10 easily findable ones
> like i2c, platform, spi, slimbus, spmi, etc.

The thought with coccinelle (or like I say some other mechanism) is that
we would have something around to catch any new users that should be
using the helper but aren't rather than issues with making the changes.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH RFC] driver core: Ensure DT devices always have fwnode set
  2020-11-06 19:09 ` Saravana Kannan
  2020-11-06 19:23   ` Mark Brown
@ 2020-11-09 17:25   ` Rob Herring
  2020-11-09 17:41     ` Mark Brown
  1 sibling, 1 reply; 7+ messages in thread
From: Rob Herring @ 2020-11-09 17:25 UTC (permalink / raw)
  To: Saravana Kannan
  Cc: Mark Brown, Greg Kroah-Hartman, Rafael J . Wysocki, Daniel Mentz,
	LKML, Frank Rowand

On Fri, Nov 6, 2020 at 1:09 PM Saravana Kannan <saravanak@google.com> wrote:
>
> +Rob and Frank
>
> On Fri, Nov 6, 2020 at 7:09 AM Mark Brown <broonie@kernel.org> wrote:
> >
> > Currently the fwnode API and things that rely on it like fw_devlink will
> > not reliably work for devices created from DT since each subsystem that
> > creates devices must individually set dev->fwnode in addition to setting
> > dev->of_node, currently a number of subsystems don't do so. Ensure that
> > this can't get missed by setting fwnode from of_node if it's not
> > previously been set by the subsystem.
> >
> > Reported-by: Saravana Kannan <saravanak@google.com>
> > Signed-off-by: Mark Brown <broonie@kernel.org>
> > ---
> >
> > *Very* minimally tested.
> >
> >  drivers/base/core.c | 4 ++++
> >  1 file changed, 4 insertions(+)
> >
> > diff --git a/drivers/base/core.c b/drivers/base/core.c
> > index d661ada1518f..658626bafd76 100644
> > --- a/drivers/base/core.c
> > +++ b/drivers/base/core.c
> > @@ -2864,6 +2864,10 @@ int device_add(struct device *dev)
> >         if (parent && (dev_to_node(dev) == NUMA_NO_NODE))
> >                 set_dev_node(dev, dev_to_node(parent));
> >
> > +       /* ensure that fwnode is set up */
> > +       if (IS_ENABLED(CONFIG_OF) && dev->of_node && !dev->fwnode)
> > +               dev->fwnode = of_fwnode_handle(dev->of_node);
> > +
>
> I don't think we should add more CONFIG_OF specific code in drivers/base/

It's fwnode specific code because it's fwnode that needs it...

> If you want to do this in "one common place", then I think the way to
> do this is have include/linux/of.h provide something like:
> void of_set_device_of_node(dev, of_node)
> {
>     dev->of_node = of_node;
>     dev->fw_node = &of_node->fwnode;
>    /* bunch of other housekeeping like setting OF_POPULATED and doing
> proper of_node_get() */
>    // Passing NULL for of_node could undo all the above for dev->of_node.
> }
>
> And all the subsystems that create their own device from an of_node
> should use of_set_device_of_node() to set the device's of_node. That
> way, all this is done in a consistent manner across subsystems and
> avoid all of the of_get/put() and OF_POPULATED set/clear strewn all
> over the subsystems.

Perhaps a fwnode call in device_add instead that implements the above
and anything else needed for each type of fwnode. It might even be
possible with that to get rid of most of
of_platform_device_create_pdata() and of_device_add(). IIRC, those
were pretty much copies of the core code.

That would also be less fragile than having a coccinelle script.

Rob

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH RFC] driver core: Ensure DT devices always have fwnode set
  2020-11-09 17:25   ` Rob Herring
@ 2020-11-09 17:41     ` Mark Brown
  0 siblings, 0 replies; 7+ messages in thread
From: Mark Brown @ 2020-11-09 17:41 UTC (permalink / raw)
  To: Rob Herring
  Cc: Saravana Kannan, Greg Kroah-Hartman, Rafael J . Wysocki,
	Daniel Mentz, LKML, Frank Rowand

[-- Attachment #1: Type: text/plain, Size: 996 bytes --]

On Mon, Nov 09, 2020 at 11:25:39AM -0600, Rob Herring wrote:
> On Fri, Nov 6, 2020 at 1:09 PM Saravana Kannan <saravanak@google.com> wrote:

> > And all the subsystems that create their own device from an of_node
> > should use of_set_device_of_node() to set the device's of_node. That
> > way, all this is done in a consistent manner across subsystems and
> > avoid all of the of_get/put() and OF_POPULATED set/clear strewn all
> > over the subsystems.

> Perhaps a fwnode call in device_add instead that implements the above
> and anything else needed for each type of fwnode. It might even be
> possible with that to get rid of most of

I'd suggested doing it with a callout as well in the original thread
that sparked my proposal - my patch was just the most minimal
implementation to fix the current problem.

> of_platform_device_create_pdata() and of_device_add(). IIRC, those
> were pretty much copies of the core code.

> That would also be less fragile than having a coccinelle script.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2020-11-09 17:41 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-06 15:07 [PATCH RFC] driver core: Ensure DT devices always have fwnode set Mark Brown
2020-11-06 19:09 ` Saravana Kannan
2020-11-06 19:23   ` Mark Brown
2020-11-07  1:55     ` Saravana Kannan
2020-11-09 17:08       ` Mark Brown
2020-11-09 17:25   ` Rob Herring
2020-11-09 17:41     ` Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).