* [PATCH 01/10] of: Keep track of populated platform devices
[not found] <1398707877-22596-1-git-send-email-pawel.moll@arm.com>
@ 2014-04-28 17:57 ` Pawel Moll
2014-04-28 18:02 ` Rob Herring
0 siblings, 1 reply; 14+ messages in thread
From: Pawel Moll @ 2014-04-28 17:57 UTC (permalink / raw)
To: Grant Likely, Rob Herring, Samuel Ortiz, Lee Jones, Arnd Bergmann,
Greg Kroah-Hartman, Russell King
Cc: devicetree, arm, Pawel Moll, linux-kernel, linux-arm-kernel
In "Device Tree powered" systems, platform devices are usually
massively populated with of_platform_populate() call, executed
at some level of initcalls, either by generic architecture
or by platform-specific code.
There are situations though where certain devices must be
created (and bound with drivers) before all the others.
This presents a challenge, as devices created explicitly
would be created again by of_platform_populate().
This patch tries to solve that issue in a generic way,
adding a "populated" flag for a DT node description.
Once set, this device will never be created again via
of_* API, so of_platform_populate() will skip such nodes
(and its children) in a similar way to the non-available
ones.
Cc: devicetree@vger.kernel.org
Signed-off-by: Pawel Moll <pawel.moll@arm.com>
---
drivers/of/platform.c | 10 ++++++++--
include/linux/of.h | 1 +
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 404d1da..0ae757a 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -204,7 +204,8 @@ static struct platform_device *of_platform_device_create_pdata(
{
struct platform_device *dev;
- if (!of_device_is_available(np))
+ if (!of_device_is_available(np) ||
+ of_node_check_flag(np, OF_POPULATED))
return NULL;
dev = of_device_alloc(np, bus_id, parent);
@@ -230,6 +231,8 @@ static struct platform_device *of_platform_device_create_pdata(
return NULL;
}
+ of_node_set_flag(np, OF_POPULATED);
+
return dev;
}
@@ -262,7 +265,8 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
pr_debug("Creating amba device %s\n", node->full_name);
- if (!of_device_is_available(node))
+ if (!of_device_is_available(node) ||
+ of_node_check_flag(node, OF_POPULATED))
return NULL;
dev = amba_device_alloc(NULL, 0, 0);
@@ -305,6 +309,8 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
goto err_free;
}
+ of_node_set_flag(node, OF_POPULATED);
+
return dev;
err_free:
diff --git a/include/linux/of.h b/include/linux/of.h
index 3bad8d1..fd3aaee 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -197,6 +197,7 @@ static inline unsigned long of_read_ulong(const __be32 *cell, int size)
/* flag descriptions */
#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */
#define OF_DETACHED 2 /* node has been detached from the device tree */
+#define OF_POPULATED 3 /* device already created for the node */
#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
--
1.9.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 01/10] of: Keep track of populated platform devices
2014-04-28 17:57 ` [PATCH 01/10] of: Keep track of populated platform devices Pawel Moll
@ 2014-04-28 18:02 ` Rob Herring
[not found] ` <CAL_JsqJxWoxNL=P0SJm+Q1rTRGTpMkzmzTJDbFq2P1vPH4XxZQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
0 siblings, 1 reply; 14+ messages in thread
From: Rob Herring @ 2014-04-28 18:02 UTC (permalink / raw)
To: Pawel Moll
Cc: devicetree@vger.kernel.org, Russell King, Samuel Ortiz,
Arnd Bergmann, Greg Kroah-Hartman, linux-kernel@vger.kernel.org,
arm@kernel.org, Rob Herring, Grant Likely, Lee Jones,
linux-arm-kernel@lists.infradead.org
On Mon, Apr 28, 2014 at 12:57 PM, Pawel Moll <pawel.moll@arm.com> wrote:
> In "Device Tree powered" systems, platform devices are usually
> massively populated with of_platform_populate() call, executed
> at some level of initcalls, either by generic architecture
> or by platform-specific code.
>
> There are situations though where certain devices must be
> created (and bound with drivers) before all the others.
> This presents a challenge, as devices created explicitly
> would be created again by of_platform_populate().
>
> This patch tries to solve that issue in a generic way,
> adding a "populated" flag for a DT node description.
> Once set, this device will never be created again via
> of_* API, so of_platform_populate() will skip such nodes
> (and its children) in a similar way to the non-available
> ones.
>
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Pawel Moll <pawel.moll@arm.com>
> ---
> drivers/of/platform.c | 10 ++++++++--
> include/linux/of.h | 1 +
> 2 files changed, 9 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/of/platform.c b/drivers/of/platform.c
> index 404d1da..0ae757a 100644
> --- a/drivers/of/platform.c
> +++ b/drivers/of/platform.c
> @@ -204,7 +204,8 @@ static struct platform_device *of_platform_device_create_pdata(
> {
> struct platform_device *dev;
>
> - if (!of_device_is_available(np))
> + if (!of_device_is_available(np) ||
> + of_node_check_flag(np, OF_POPULATED))
This and the amba case should be a test_and_set operation to avoid a
race condition.
Rob
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 01/10] of: Keep track of populated platform devices
[not found] ` <CAL_JsqJxWoxNL=P0SJm+Q1rTRGTpMkzmzTJDbFq2P1vPH4XxZQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2014-04-29 12:56 ` Grant Likely
[not found] ` <20140429125657.65910C4089D-WNowdnHR2B42iJbIjFUEsiwD8/FfD2ys@public.gmane.org>
0 siblings, 1 reply; 14+ messages in thread
From: Grant Likely @ 2014-04-29 12:56 UTC (permalink / raw)
To: Rob Herring, Pawel Moll
Cc: Rob Herring, Samuel Ortiz, Lee Jones, Arnd Bergmann,
Greg Kroah-Hartman, Russell King,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
arm-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
On Mon, 28 Apr 2014 13:02:28 -0500, Rob Herring <robherring2-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> On Mon, Apr 28, 2014 at 12:57 PM, Pawel Moll <pawel.moll-5wv7dgnIgG8@public.gmane.org> wrote:
> > In "Device Tree powered" systems, platform devices are usually
> > massively populated with of_platform_populate() call, executed
> > at some level of initcalls, either by generic architecture
> > or by platform-specific code.
> >
> > There are situations though where certain devices must be
> > created (and bound with drivers) before all the others.
> > This presents a challenge, as devices created explicitly
> > would be created again by of_platform_populate().
> >
> > This patch tries to solve that issue in a generic way,
> > adding a "populated" flag for a DT node description.
> > Once set, this device will never be created again via
> > of_* API, so of_platform_populate() will skip such nodes
> > (and its children) in a similar way to the non-available
> > ones.
> >
> > Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> > Signed-off-by: Pawel Moll <pawel.moll-5wv7dgnIgG8@public.gmane.org>
> > ---
> > drivers/of/platform.c | 10 ++++++++--
> > include/linux/of.h | 1 +
> > 2 files changed, 9 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/of/platform.c b/drivers/of/platform.c
> > index 404d1da..0ae757a 100644
> > --- a/drivers/of/platform.c
> > +++ b/drivers/of/platform.c
> > @@ -204,7 +204,8 @@ static struct platform_device *of_platform_device_create_pdata(
> > {
> > struct platform_device *dev;
> >
> > - if (!of_device_is_available(np))
> > + if (!of_device_is_available(np) ||
> > + of_node_check_flag(np, OF_POPULATED))
>
> This and the amba case should be a test_and_set operation to avoid a
> race condition.
Yes. It is an unlikely condition at the time that Pawel is handling, but
it should also work for later calls to of_platform_populate() which may
happen at runtime and in parallel.
g.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 01/10] of: Keep track of populated platform devices
[not found] ` <20140429125657.65910C4089D-WNowdnHR2B42iJbIjFUEsiwD8/FfD2ys@public.gmane.org>
@ 2014-04-30 11:48 ` Pawel Moll
2014-04-30 14:05 ` [PATCH v2] " Pawel Moll
0 siblings, 1 reply; 14+ messages in thread
From: Pawel Moll @ 2014-04-30 11:48 UTC (permalink / raw)
To: Grant Likely
Cc: Rob Herring, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Russell King, Samuel Ortiz, Arnd Bergmann, Greg Kroah-Hartman,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
arm-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org, Rob Herring,
Lee Jones,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
On Tue, 2014-04-29 at 13:56 +0100, Grant Likely wrote:
> > > diff --git a/drivers/of/platform.c b/drivers/of/platform.c
> > > index 404d1da..0ae757a 100644
> > > --- a/drivers/of/platform.c
> > > +++ b/drivers/of/platform.c
> > > @@ -204,7 +204,8 @@ static struct platform_device *of_platform_device_create_pdata(
> > > {
> > > struct platform_device *dev;
> > >
> > > - if (!of_device_is_available(np))
> > > + if (!of_device_is_available(np) ||
> > > + of_node_check_flag(np, OF_POPULATED))
> >
> > This and the amba case should be a test_and_set operation to avoid a
> > race condition.
>
> Yes. It is an unlikely condition at the time that Pawel is handling, but
> it should also work for later calls to of_platform_populate() which may
> happen at runtime and in parallel.
Sure thing, will fix.
Thanks!
Pawel
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2] of: Keep track of populated platform devices
2014-04-30 11:48 ` Pawel Moll
@ 2014-04-30 14:05 ` Pawel Moll
[not found] ` <1398866717-20268-1-git-send-email-pawel.moll-5wv7dgnIgG8@public.gmane.org>
0 siblings, 1 reply; 14+ messages in thread
From: Pawel Moll @ 2014-04-30 14:05 UTC (permalink / raw)
To: Grant Likely, Rob Herring
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Pawel Moll
In "Device Tree powered" systems, platform devices are usually
massively populated with of_platform_populate() call, executed
at some level of initcalls, either by generic architecture
or by platform-specific code.
There are situations though where certain devices must be
created (and bound with drivers) before all the others.
This presents a challenge, as devices created explicitly
would be created again by of_platform_populate().
This patch tries to solve that issue in a generic way,
adding a "populated" flag for a DT node description.
Once set, this device will never be created again via
of_* API, so of_platform_populate() will skip such nodes
(and its children) in a similar way to the non-available
ones.
Signed-off-by: Pawel Moll <pawel.moll-5wv7dgnIgG8@public.gmane.org>
---
Changes since v1:
- added of_node_check_and_set_flag()... (atomic test and set)
- ... used it to atomically mark a node...
- ... clearing the bit on error path.
drivers/of/platform.c | 18 +++++++++++++-----
include/linux/of.h | 7 +++++++
2 files changed, 20 insertions(+), 5 deletions(-)
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 404d1da..b33927a 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -204,12 +204,13 @@ static struct platform_device *of_platform_device_create_pdata(
{
struct platform_device *dev;
- if (!of_device_is_available(np))
+ if (!of_device_is_available(np) ||
+ of_node_check_and_set_flag(np, OF_POPULATED))
return NULL;
dev = of_device_alloc(np, bus_id, parent);
if (!dev)
- return NULL;
+ goto err_clear_flag;
#if defined(CONFIG_MICROBLAZE)
dev->archdata.dma_mask = 0xffffffffUL;
@@ -227,10 +228,14 @@ static struct platform_device *of_platform_device_create_pdata(
if (of_device_add(dev) != 0) {
platform_device_put(dev);
- return NULL;
+ goto err_clear_flag;
}
return dev;
+
+err_clear_flag:
+ of_node_clear_flag(np, OF_POPULATED);
+ return NULL;
}
/**
@@ -262,14 +267,15 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
pr_debug("Creating amba device %s\n", node->full_name);
- if (!of_device_is_available(node))
+ if (!of_device_is_available(node) ||
+ of_node_check_and_set_flag(node, OF_POPULATED))
return NULL;
dev = amba_device_alloc(NULL, 0, 0);
if (!dev) {
pr_err("%s(): amba_device_alloc() failed for %s\n",
__func__, node->full_name);
- return NULL;
+ goto err_clear_flag;
}
/* setup generic device info */
@@ -309,6 +315,8 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
err_free:
amba_device_put(dev);
+err_clear_flag:
+ of_node_clear_flag(node, OF_POPULATED);
return NULL;
}
#else /* CONFIG_ARM_AMBA */
diff --git a/include/linux/of.h b/include/linux/of.h
index 3bad8d1..534cab8 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -130,6 +130,12 @@ static inline int of_node_check_flag(struct device_node *n, unsigned long flag)
return test_bit(flag, &n->_flags);
}
+static inline int of_node_check_and_set_flag(struct device_node *n,
+ unsigned long flag)
+{
+ return test_and_set_bit(flag, &n->_flags);
+}
+
static inline void of_node_set_flag(struct device_node *n, unsigned long flag)
{
set_bit(flag, &n->_flags);
@@ -197,6 +203,7 @@ static inline unsigned long of_read_ulong(const __be32 *cell, int size)
/* flag descriptions */
#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */
#define OF_DETACHED 2 /* node has been detached from the device tree */
+#define OF_POPULATED 3 /* device already created for the node */
#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v2] of: Keep track of populated platform devices
[not found] ` <1398866717-20268-1-git-send-email-pawel.moll-5wv7dgnIgG8@public.gmane.org>
@ 2014-04-30 15:22 ` Rob Herring
[not found] ` <CAL_JsqL=mxqEKpAsXm7Du0vEDpKk4n+dp5-DyvbuGhTA6bP5Lg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
0 siblings, 1 reply; 14+ messages in thread
From: Rob Herring @ 2014-04-30 15:22 UTC (permalink / raw)
To: Pawel Moll
Cc: Grant Likely, Rob Herring,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
On Wed, Apr 30, 2014 at 9:05 AM, Pawel Moll <pawel.moll-5wv7dgnIgG8@public.gmane.org> wrote:
> In "Device Tree powered" systems, platform devices are usually
> massively populated with of_platform_populate() call, executed
> at some level of initcalls, either by generic architecture
> or by platform-specific code.
>
> There are situations though where certain devices must be
> created (and bound with drivers) before all the others.
> This presents a challenge, as devices created explicitly
> would be created again by of_platform_populate().
>
> This patch tries to solve that issue in a generic way,
> adding a "populated" flag for a DT node description.
> Once set, this device will never be created again via
> of_* API, so of_platform_populate() will skip such nodes
> (and its children) in a similar way to the non-available
> ones.
>
> Signed-off-by: Pawel Moll <pawel.moll-5wv7dgnIgG8@public.gmane.org>
One pondering and one minor change below, otherwise:
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> ---
>
> Changes since v1:
>
> - added of_node_check_and_set_flag()... (atomic test and set)
> - ... used it to atomically mark a node...
> - ... clearing the bit on error path.
>
> drivers/of/platform.c | 18 +++++++++++++-----
> include/linux/of.h | 7 +++++++
> 2 files changed, 20 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/of/platform.c b/drivers/of/platform.c
> index 404d1da..b33927a 100644
> --- a/drivers/of/platform.c
> +++ b/drivers/of/platform.c
> @@ -204,12 +204,13 @@ static struct platform_device *of_platform_device_create_pdata(
> {
> struct platform_device *dev;
>
> - if (!of_device_is_available(np))
> + if (!of_device_is_available(np) ||
> + of_node_check_and_set_flag(np, OF_POPULATED))
> return NULL;
>
> dev = of_device_alloc(np, bus_id, parent);
> if (!dev)
> - return NULL;
> + goto err_clear_flag;
I wonder if leaving it set would be the right behavior. I can't see
that we would want to process the node again. But this is the
exceptional case, so its probably not too important and can stay like
this.
>
> #if defined(CONFIG_MICROBLAZE)
> dev->archdata.dma_mask = 0xffffffffUL;
> @@ -227,10 +228,14 @@ static struct platform_device *of_platform_device_create_pdata(
>
> if (of_device_add(dev) != 0) {
> platform_device_put(dev);
> - return NULL;
> + goto err_clear_flag;
> }
>
> return dev;
> +
> +err_clear_flag:
> + of_node_clear_flag(np, OF_POPULATED);
> + return NULL;
> }
>
> /**
> @@ -262,14 +267,15 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
>
> pr_debug("Creating amba device %s\n", node->full_name);
>
> - if (!of_device_is_available(node))
> + if (!of_device_is_available(node) ||
> + of_node_check_and_set_flag(node, OF_POPULATED))
> return NULL;
>
> dev = amba_device_alloc(NULL, 0, 0);
> if (!dev) {
> pr_err("%s(): amba_device_alloc() failed for %s\n",
> __func__, node->full_name);
> - return NULL;
> + goto err_clear_flag;
> }
>
> /* setup generic device info */
> @@ -309,6 +315,8 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
>
> err_free:
> amba_device_put(dev);
> +err_clear_flag:
> + of_node_clear_flag(node, OF_POPULATED);
> return NULL;
> }
> #else /* CONFIG_ARM_AMBA */
> diff --git a/include/linux/of.h b/include/linux/of.h
> index 3bad8d1..534cab8 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -130,6 +130,12 @@ static inline int of_node_check_flag(struct device_node *n, unsigned long flag)
> return test_bit(flag, &n->_flags);
> }
>
> +static inline int of_node_check_and_set_flag(struct device_node *n,
Please keep the well known naming convention of the called function:
of_node_test_and_set_flag
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2] of: Keep track of populated platform devices
[not found] ` <CAL_JsqL=mxqEKpAsXm7Du0vEDpKk4n+dp5-DyvbuGhTA6bP5Lg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2014-05-01 9:26 ` Grant Likely
[not found] ` <20140501092635.05011C409DA-WNowdnHR2B42iJbIjFUEsiwD8/FfD2ys@public.gmane.org>
0 siblings, 1 reply; 14+ messages in thread
From: Grant Likely @ 2014-05-01 9:26 UTC (permalink / raw)
To: Rob Herring, Pawel Moll
Cc: Rob Herring, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
On Wed, 30 Apr 2014 10:22:25 -0500, Rob Herring <robherring2-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> On Wed, Apr 30, 2014 at 9:05 AM, Pawel Moll <pawel.moll-5wv7dgnIgG8@public.gmane.org> wrote:
> > In "Device Tree powered" systems, platform devices are usually
> > massively populated with of_platform_populate() call, executed
> > at some level of initcalls, either by generic architecture
> > or by platform-specific code.
> >
> > There are situations though where certain devices must be
> > created (and bound with drivers) before all the others.
> > This presents a challenge, as devices created explicitly
> > would be created again by of_platform_populate().
> >
> > This patch tries to solve that issue in a generic way,
> > adding a "populated" flag for a DT node description.
> > Once set, this device will never be created again via
> > of_* API, so of_platform_populate() will skip such nodes
> > (and its children) in a similar way to the non-available
> > ones.
> >
> > Signed-off-by: Pawel Moll <pawel.moll-5wv7dgnIgG8@public.gmane.org>
>
> One pondering and one minor change below, otherwise:
>
> Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
>
>
> > ---
> >
> > Changes since v1:
> >
> > - added of_node_check_and_set_flag()... (atomic test and set)
> > - ... used it to atomically mark a node...
> > - ... clearing the bit on error path.
> >
> > drivers/of/platform.c | 18 +++++++++++++-----
> > include/linux/of.h | 7 +++++++
> > 2 files changed, 20 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/of/platform.c b/drivers/of/platform.c
> > index 404d1da..b33927a 100644
> > --- a/drivers/of/platform.c
> > +++ b/drivers/of/platform.c
> > @@ -204,12 +204,13 @@ static struct platform_device *of_platform_device_create_pdata(
> > {
> > struct platform_device *dev;
> >
> > - if (!of_device_is_available(np))
> > + if (!of_device_is_available(np) ||
> > + of_node_check_and_set_flag(np, OF_POPULATED))
> > return NULL;
> >
> > dev = of_device_alloc(np, bus_id, parent);
> > if (!dev)
> > - return NULL;
> > + goto err_clear_flag;
>
> I wonder if leaving it set would be the right behavior. I can't see
> that we would want to process the node again. But this is the
> exceptional case, so its probably not too important and can stay like
> this.
That doesn't work in the case where drivers use of_platform_populate().
MFD devices in particular make use of it. If the driver does not get
cleared on removal of the devices, then all MFD users will be broken on
driver unbind/rebind. *
We really need to have the inverse of of_platform_populate which will
remove all child and child's child devices and clear all flags and such.
Right now moany drivers are open-coding the removal.
* most drivers are somewhat broken on unbind/rebind anyway, but I don't
want to make it impossible for a driver to get it right.
>
> >
> > #if defined(CONFIG_MICROBLAZE)
> > dev->archdata.dma_mask = 0xffffffffUL;
> > @@ -227,10 +228,14 @@ static struct platform_device *of_platform_device_create_pdata(
> >
> > if (of_device_add(dev) != 0) {
> > platform_device_put(dev);
> > - return NULL;
> > + goto err_clear_flag;
> > }
> >
> > return dev;
> > +
> > +err_clear_flag:
> > + of_node_clear_flag(np, OF_POPULATED);
> > + return NULL;
> > }
> >
> > /**
> > @@ -262,14 +267,15 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
> >
> > pr_debug("Creating amba device %s\n", node->full_name);
> >
> > - if (!of_device_is_available(node))
> > + if (!of_device_is_available(node) ||
> > + of_node_check_and_set_flag(node, OF_POPULATED))
> > return NULL;
> >
> > dev = amba_device_alloc(NULL, 0, 0);
> > if (!dev) {
> > pr_err("%s(): amba_device_alloc() failed for %s\n",
> > __func__, node->full_name);
> > - return NULL;
> > + goto err_clear_flag;
> > }
> >
> > /* setup generic device info */
> > @@ -309,6 +315,8 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
> >
> > err_free:
> > amba_device_put(dev);
> > +err_clear_flag:
> > + of_node_clear_flag(node, OF_POPULATED);
> > return NULL;
> > }
> > #else /* CONFIG_ARM_AMBA */
> > diff --git a/include/linux/of.h b/include/linux/of.h
> > index 3bad8d1..534cab8 100644
> > --- a/include/linux/of.h
> > +++ b/include/linux/of.h
> > @@ -130,6 +130,12 @@ static inline int of_node_check_flag(struct device_node *n, unsigned long flag)
> > return test_bit(flag, &n->_flags);
> > }
> >
> > +static inline int of_node_check_and_set_flag(struct device_node *n,
>
> Please keep the well known naming convention of the called function:
> of_node_test_and_set_flag
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2] of: Keep track of populated platform devices
[not found] ` <20140501092635.05011C409DA-WNowdnHR2B42iJbIjFUEsiwD8/FfD2ys@public.gmane.org>
@ 2014-05-01 9:43 ` Grant Likely
[not found] ` <CACxGe6usWdey1qQT2JF=7LuE62H-_xtd1QkRT9z_Tj2pxdQEjQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
0 siblings, 1 reply; 14+ messages in thread
From: Grant Likely @ 2014-05-01 9:43 UTC (permalink / raw)
To: Rob Herring, Pawel Moll
Cc: Rob Herring, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
On Thu, May 1, 2014 at 10:26 AM, Grant Likely <grant.likely-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> On Wed, 30 Apr 2014 10:22:25 -0500, Rob Herring <robherring2-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>> On Wed, Apr 30, 2014 at 9:05 AM, Pawel Moll <pawel.moll-5wv7dgnIgG8@public.gmane.org> wrote:
>> > In "Device Tree powered" systems, platform devices are usually
>> > massively populated with of_platform_populate() call, executed
>> > at some level of initcalls, either by generic architecture
>> > or by platform-specific code.
>> >
>> > There are situations though where certain devices must be
>> > created (and bound with drivers) before all the others.
>> > This presents a challenge, as devices created explicitly
>> > would be created again by of_platform_populate().
>> >
>> > This patch tries to solve that issue in a generic way,
>> > adding a "populated" flag for a DT node description.
>> > Once set, this device will never be created again via
>> > of_* API, so of_platform_populate() will skip such nodes
>> > (and its children) in a similar way to the non-available
>> > ones.
>> >
>> > Signed-off-by: Pawel Moll <pawel.moll-5wv7dgnIgG8@public.gmane.org>
>>
>> One pondering and one minor change below, otherwise:
>>
>> Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
>>
>>
>> > ---
>> >
>> > Changes since v1:
>> >
>> > - added of_node_check_and_set_flag()... (atomic test and set)
>> > - ... used it to atomically mark a node...
>> > - ... clearing the bit on error path.
>> >
>> > drivers/of/platform.c | 18 +++++++++++++-----
>> > include/linux/of.h | 7 +++++++
>> > 2 files changed, 20 insertions(+), 5 deletions(-)
>> >
>> > diff --git a/drivers/of/platform.c b/drivers/of/platform.c
>> > index 404d1da..b33927a 100644
>> > --- a/drivers/of/platform.c
>> > +++ b/drivers/of/platform.c
>> > @@ -204,12 +204,13 @@ static struct platform_device *of_platform_device_create_pdata(
>> > {
>> > struct platform_device *dev;
>> >
>> > - if (!of_device_is_available(np))
>> > + if (!of_device_is_available(np) ||
>> > + of_node_check_and_set_flag(np, OF_POPULATED))
>> > return NULL;
>> >
>> > dev = of_device_alloc(np, bus_id, parent);
>> > if (!dev)
>> > - return NULL;
>> > + goto err_clear_flag;
>>
>> I wonder if leaving it set would be the right behavior. I can't see
>> that we would want to process the node again. But this is the
>> exceptional case, so its probably not too important and can stay like
>> this.
>
> That doesn't work in the case where drivers use of_platform_populate().
> MFD devices in particular make use of it. If the driver does not get
> cleared on removal of the devices, then all MFD users will be broken on
> driver unbind/rebind. *
>
> We really need to have the inverse of of_platform_populate which will
> remove all child and child's child devices and clear all flags and such.
> Right now moany drivers are open-coding the removal.
>
> * most drivers are somewhat broken on unbind/rebind anyway, but I don't
> want to make it impossible for a driver to get it right.
The function shouldn't be too difficult. I would expect it to look
something like this. You'll need to check the details.
static int __of_platform_unpopulate_device(struct device *dev, void *c)
{
if (!dev->of_node || !of_node_get_flag(dev->of_node, OF_POPULATED)
return 0;
// recursively remove the children too --- I'd like to find a way
to do this non-recursively
device_for_each_child(dev, NULL, __of_platform_unpopulate_device);
// Need to check if the device should be explicitly unbound from
it's driver before removing it. However, I think the driver core takes
care of this for us.
// Remove based on the bus type
switch (dev->bus) {
case &platform_bus_type:
platform_device_remove(to_platform_device(dev));
break;
case &amba_bus_type:
amba_device_remove(to_platform_device(dev));
break;
}
// Should check here if there are any other children to the
device. It is probably bad to remove a device that still has children.
Need to check what the driver core will do.
}
void of_platform_unpopulate(struct device *parent)
{
device_for_each_child(parent, NULL, __of_platform_unpopulate_device);
}
>
>>
>> >
>> > #if defined(CONFIG_MICROBLAZE)
>> > dev->archdata.dma_mask = 0xffffffffUL;
>> > @@ -227,10 +228,14 @@ static struct platform_device *of_platform_device_create_pdata(
>> >
>> > if (of_device_add(dev) != 0) {
>> > platform_device_put(dev);
>> > - return NULL;
>> > + goto err_clear_flag;
>> > }
>> >
>> > return dev;
>> > +
>> > +err_clear_flag:
>> > + of_node_clear_flag(np, OF_POPULATED);
>> > + return NULL;
>> > }
>> >
>> > /**
>> > @@ -262,14 +267,15 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
>> >
>> > pr_debug("Creating amba device %s\n", node->full_name);
>> >
>> > - if (!of_device_is_available(node))
>> > + if (!of_device_is_available(node) ||
>> > + of_node_check_and_set_flag(node, OF_POPULATED))
>> > return NULL;
>> >
>> > dev = amba_device_alloc(NULL, 0, 0);
>> > if (!dev) {
>> > pr_err("%s(): amba_device_alloc() failed for %s\n",
>> > __func__, node->full_name);
>> > - return NULL;
>> > + goto err_clear_flag;
>> > }
>> >
>> > /* setup generic device info */
>> > @@ -309,6 +315,8 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
>> >
>> > err_free:
>> > amba_device_put(dev);
>> > +err_clear_flag:
>> > + of_node_clear_flag(node, OF_POPULATED);
>> > return NULL;
>> > }
>> > #else /* CONFIG_ARM_AMBA */
>> > diff --git a/include/linux/of.h b/include/linux/of.h
>> > index 3bad8d1..534cab8 100644
>> > --- a/include/linux/of.h
>> > +++ b/include/linux/of.h
>> > @@ -130,6 +130,12 @@ static inline int of_node_check_flag(struct device_node *n, unsigned long flag)
>> > return test_bit(flag, &n->_flags);
>> > }
>> >
>> > +static inline int of_node_check_and_set_flag(struct device_node *n,
>>
>> Please keep the well known naming convention of the called function:
>> of_node_test_and_set_flag
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2] of: Keep track of populated platform devices
[not found] ` <CACxGe6usWdey1qQT2JF=7LuE62H-_xtd1QkRT9z_Tj2pxdQEjQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2014-05-07 14:37 ` Pawel Moll
2014-05-14 10:56 ` Grant Likely
0 siblings, 1 reply; 14+ messages in thread
From: Pawel Moll @ 2014-05-07 14:37 UTC (permalink / raw)
To: Grant Likely
Cc: Rob Herring, Rob Herring,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
On Thu, 2014-05-01 at 10:43 +0100, Grant Likely wrote:
> > That doesn't work in the case where drivers use of_platform_populate().
> > MFD devices in particular make use of it. If the driver does not get
> > cleared on removal of the devices, then all MFD users will be broken on
> > driver unbind/rebind. *
> >
> > We really need to have the inverse of of_platform_populate which will
> > remove all child and child's child devices and clear all flags and such.
> > Right now moany drivers are open-coding the removal.
Agreed, but, unless I'm missing some fundamental issue, I believe we can
solve the flag clearing problem in a generic way:
--8<-----------
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index 3cf61a1..0f489fb 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -17,6 +17,7 @@
#include <linux/pm_runtime.h>
#include <linux/amba/bus.h>
#include <linux/sizes.h>
+#include <linux/of_device.h>
#include <asm/irq.h>
@@ -268,6 +269,7 @@ static void amba_device_release(struct device *dev)
{
struct amba_device *d = to_amba_device(dev);
+ of_device_node_put(dev);
if (d->res.parent)
release_resource(&d->res);
kfree(d);
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index ef37021..fd14d46 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -41,6 +41,8 @@ extern int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env
static inline void of_device_node_put(struct device *dev)
{
+ if (dev->of_node)
+ of_node_clear_flag(dev->of_node, OF_POPULATED);
of_node_put(dev->of_node);
}
--8<-----------
This will work even if one manually unregisters a DT-originating device,
because of_device_node_put() would be called in both amba and platform
device (kobj) release path.
By the way, the fact that today amba_device_release() doesn't do
of_device_node_put() seems like a bug to me? (node's reference counter
won't be decremented)
> The function shouldn't be too difficult. I would expect it to look
> something like this. You'll need to check the details.
8<-----------
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index dd4328c..b6b5a2b 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -493,4 +493,49 @@ int of_platform_populate(struct device_node *root,
return rc;
}
EXPORT_SYMBOL_GPL(of_platform_populate);
+
+static int of_platform_device_destroy(struct device *dev, void *data)
+{
+ int *parents_children_left = data;
+ int my_children_left = 0;
+
+ /* Do not touch devices not populated from the device tree */
+ if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED)) {
+ *parents_children_left++;
+ return 0;
+ }
+
+ device_for_each_child(dev, &my_children_left,
+ of_platform_device_destroy);
+ if (my_children_left) {
+ *parents_children_left++;
+ return 0;
+ }
+
+ if (dev->bus == &platform_bus_type)
+ platform_device_unregister(to_platform_device(dev));
+ else if (dev->bus == &amba_bustype)
+ amba_device_unregister(to_amba_device(dev));
+
+ return 0;
+}
+
+/**
+ * of_platform_depopulate() - Remove devices populated from device tree
+ * @parent: device which childred will be removed
+ *
+ * Complementary to of_platform_populate(), this function removes children
+ * of the given device (and, recurrently, their children) that have been
+ * created from their respective device tree nodes (and only those,
+ * leaving others - eg. manually created - unharmed). */
+ */
+int of_platform_depopulate(struct device *parent)
+{
+ int children_left = 0;
+
+ device_for_each_child(dev, &children_left, of_platform_device_destroy);
+
+ return children_left ? -EBUSY : 0;
+}
+EXPORT_SYMBOL_GPL(of_platform_depopulate);
#endif /* CONFIG_OF_ADDRESS */
diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h
index 05cb4a9..ef4f4ad 100644
--- a/include/linux/of_platform.h
+++ b/include/linux/of_platform.h
@@ -72,6 +72,7 @@ extern int of_platform_populate(struct device_node *root,
const struct of_device_id *matches,
const struct of_dev_auxdata *lookup,
struct device *parent);
+static inline int of_platform_depopulate(struct device *parent);
#else
static inline int of_platform_populate(struct device_node *root,
const struct of_device_id *matches,
@@ -80,6 +81,10 @@ static inline int of_platform_populate(struct device_node *root,
{
return -ENODEV;
}
+static inline int of_platform_depopulate(struct device *parent)
+{
+ return -ENODEV;
+}
#endif
#endif /* _LINUX_OF_PLATFORM_H */
8<-----------
> static int __of_platform_unpopulate_device(struct device *dev, void *c)
> {
> if (!dev->of_node || !of_node_get_flag(dev->of_node, OF_POPULATED)
> return 0;
>
> // recursively remove the children too --- I'd like to find a way
> to do this non-recursively
> device_for_each_child(dev, NULL, __of_platform_unpopulate_device);
As of_platform_populate() is recursive itself, I don't see much problem
with this.
> // Need to check if the device should be explicitly unbound from
> it's driver before removing it. However, I think the driver core takes
> care of this for us.
Yep, removing either a driver or a device unbinds all existing pairs.
> // Remove based on the bus type
> switch (dev->bus) {
> case &platform_bus_type:
To my surprise gcc said "error: pointers are not permitted as case
values". One learns every day ;-)
> platform_device_remove(to_platform_device(dev));
> break;
> case &amba_bus_type:
> amba_device_remove(to_platform_device(dev));
> break;
> }
>
> // Should check here if there are any other children to the
> device. It is probably bad to remove a device that still has children.
> Need to check what the driver core will do.
> }
The reference count will be still be greater than 0, so the parent won't
be harmed. Nevertheless it's better to consciously handle such case. At
least I tried.
Pawel
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v3] of: Keep track of populated platform devices
[not found] <Message-ID: <1399473437.3706.25.camel@hornet>
@ 2014-05-13 11:48 ` Pawel Moll
[not found] ` <1399981716-24618-1-git-send-email-pawel.moll-5wv7dgnIgG8@public.gmane.org>
0 siblings, 1 reply; 14+ messages in thread
From: Pawel Moll @ 2014-05-13 11:48 UTC (permalink / raw)
To: Grant Likely, Rob Herring, Russell King
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Pawel Moll
In "Device Tree powered" systems, platform devices are usually
massively populated with of_platform_populate() call, executed
at some level of initcalls, either by generic architecture
or by platform-specific code.
There are situations though where certain devices must be
created (and bound with drivers) before all the others.
This presents a challenge, as devices created explicitly
would be created again by of_platform_populate().
This patch tries to solve that issue in a generic way,
adding a "populated" flag for a DT node description.
Once set, this device will never be created again via
of_* API, so of_platform_populate() will skip such nodes
(and its children) in a similar way to the non-available
ones.
The flag is cleared when a device is being removed and
returns the DT node by calling of_device_node_put() (it
was missing from the amba device release function, added).
Signed-off-by: Pawel Moll <pawel.moll-5wv7dgnIgG8@public.gmane.org>
---
Changes since v2:
- the populated flag is now cleared when the device
is being removed by platform or amba bus code
- added missing of_device_node_put() to amba_device_release()
- renamed of_node_check_and_set_flag() to
of_node_check_test_and_set_flag() to follow the
bitops naming convention
- didn't add Rob's ack as the patch changed too much
Changes since v1:
- added of_node_check_and_set_flag()... (atomic test and set)
- ... used it to atomically mark a node...
- ... clearing the bit on error path.
drivers/amba/bus.c | 2 ++
drivers/of/platform.c | 18 +++++++++++++-----
include/linux/of.h | 7 +++++++
include/linux/of_device.h | 2 ++
4 files changed, 24 insertions(+), 5 deletions(-)
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index 3cf61a1..0f489fb 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -17,6 +17,7 @@
#include <linux/pm_runtime.h>
#include <linux/amba/bus.h>
#include <linux/sizes.h>
+#include <linux/of_device.h>
#include <asm/irq.h>
@@ -268,6 +269,7 @@ static void amba_device_release(struct device *dev)
{
struct amba_device *d = to_amba_device(dev);
+ of_device_node_put(dev);
if (d->res.parent)
release_resource(&d->res);
kfree(d);
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index bd47fbc..2d0c8b7 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -206,12 +206,13 @@ static struct platform_device *of_platform_device_create_pdata(
{
struct platform_device *dev;
- if (!of_device_is_available(np))
+ if (!of_device_is_available(np) ||
+ of_node_test_and_set_flag(np, OF_POPULATED))
return NULL;
dev = of_device_alloc(np, bus_id, parent);
if (!dev)
- return NULL;
+ goto err_clear_flag;
#if defined(CONFIG_MICROBLAZE)
dev->archdata.dma_mask = 0xffffffffUL;
@@ -229,10 +230,14 @@ static struct platform_device *of_platform_device_create_pdata(
if (of_device_add(dev) != 0) {
platform_device_put(dev);
- return NULL;
+ goto err_clear_flag;
}
return dev;
+
+err_clear_flag:
+ of_node_clear_flag(np, OF_POPULATED);
+ return NULL;
}
/**
@@ -264,14 +269,15 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
pr_debug("Creating amba device %s\n", node->full_name);
- if (!of_device_is_available(node))
+ if (!of_device_is_available(node) ||
+ of_node_test_and_set_flag(node, OF_POPULATED))
return NULL;
dev = amba_device_alloc(NULL, 0, 0);
if (!dev) {
pr_err("%s(): amba_device_alloc() failed for %s\n",
__func__, node->full_name);
- return NULL;
+ goto err_clear_flag;
}
/* setup generic device info */
@@ -311,6 +317,8 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
err_free:
amba_device_put(dev);
+err_clear_flag:
+ of_node_clear_flag(node, OF_POPULATED);
return NULL;
}
#else /* CONFIG_ARM_AMBA */
diff --git a/include/linux/of.h b/include/linux/of.h
index 3bad8d1..3fd6079 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -130,6 +130,12 @@ static inline int of_node_check_flag(struct device_node *n, unsigned long flag)
return test_bit(flag, &n->_flags);
}
+static inline int of_node_test_and_set_flag(struct device_node *n,
+ unsigned long flag)
+{
+ return test_and_set_bit(flag, &n->_flags);
+}
+
static inline void of_node_set_flag(struct device_node *n, unsigned long flag)
{
set_bit(flag, &n->_flags);
@@ -197,6 +203,7 @@ static inline unsigned long of_read_ulong(const __be32 *cell, int size)
/* flag descriptions */
#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */
#define OF_DETACHED 2 /* node has been detached from the device tree */
+#define OF_POPULATED 3 /* device already created for the node */
#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index ef37021..fd14d46 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -41,6 +41,8 @@ extern int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env
static inline void of_device_node_put(struct device *dev)
{
+ if (dev->of_node)
+ of_node_clear_flag(dev->of_node, OF_POPULATED);
of_node_put(dev->of_node);
}
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v3] of: Keep track of populated platform devices
[not found] ` <1399981716-24618-1-git-send-email-pawel.moll-5wv7dgnIgG8@public.gmane.org>
@ 2014-05-13 12:24 ` Rob Herring
[not found] ` <CAL_Jsq+8xZO0LEhVa4tmOfq6CD2a0O+0CaGCnZLqDguz=yN_zg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
0 siblings, 1 reply; 14+ messages in thread
From: Rob Herring @ 2014-05-13 12:24 UTC (permalink / raw)
To: Pawel Moll
Cc: Grant Likely, Rob Herring, Russell King,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
On Tue, May 13, 2014 at 6:48 AM, Pawel Moll <pawel.moll-5wv7dgnIgG8@public.gmane.org> wrote:
> In "Device Tree powered" systems, platform devices are usually
> massively populated with of_platform_populate() call, executed
> at some level of initcalls, either by generic architecture
> or by platform-specific code.
>
> There are situations though where certain devices must be
> created (and bound with drivers) before all the others.
> This presents a challenge, as devices created explicitly
> would be created again by of_platform_populate().
>
> This patch tries to solve that issue in a generic way,
> adding a "populated" flag for a DT node description.
> Once set, this device will never be created again via
> of_* API, so of_platform_populate() will skip such nodes
> (and its children) in a similar way to the non-available
> ones.
>
> The flag is cleared when a device is being removed and
> returns the DT node by calling of_device_node_put() (it
> was missing from the amba device release function, added).
>
> Signed-off-by: Pawel Moll <pawel.moll-5wv7dgnIgG8@public.gmane.org>
A few formatting nits, but otherwise:
Reviewed-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
[..]
> @@ -206,12 +206,13 @@ static struct platform_device *of_platform_device_create_pdata(
> {
> struct platform_device *dev;
>
> - if (!of_device_is_available(np))
> + if (!of_device_is_available(np) ||
> + of_node_test_and_set_flag(np, OF_POPULATED))
This should be lined up with the ! on the previous line.
> @@ -264,14 +269,15 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
>
> pr_debug("Creating amba device %s\n", node->full_name);
>
> - if (!of_device_is_available(node))
> + if (!of_device_is_available(node) ||
> + of_node_test_and_set_flag(node, OF_POPULATED))
And this one.
> return NULL;
Rob
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2] of: Keep track of populated platform devices
2014-05-07 14:37 ` Pawel Moll
@ 2014-05-14 10:56 ` Grant Likely
[not found] ` <20140514105657.CF966C4153D-WNowdnHR2B42iJbIjFUEsiwD8/FfD2ys@public.gmane.org>
0 siblings, 1 reply; 14+ messages in thread
From: Grant Likely @ 2014-05-14 10:56 UTC (permalink / raw)
To: Pawel Moll
Cc: Rob Herring, Rob Herring,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
On Wed, 07 May 2014 15:37:17 +0100, Pawel Moll <pawel.moll-5wv7dgnIgG8@public.gmane.org> wrote:
> On Thu, 2014-05-01 at 10:43 +0100, Grant Likely wrote:
> > > That doesn't work in the case where drivers use of_platform_populate().
> > > MFD devices in particular make use of it. If the driver does not get
> > > cleared on removal of the devices, then all MFD users will be broken on
> > > driver unbind/rebind. *
> > >
> > > We really need to have the inverse of of_platform_populate which will
> > > remove all child and child's child devices and clear all flags and such.
> > > Right now moany drivers are open-coding the removal.
>
> Agreed, but, unless I'm missing some fundamental issue, I believe we can
> solve the flag clearing problem in a generic way:
>
> --8<-----------
> diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
> index 3cf61a1..0f489fb 100644
> --- a/drivers/amba/bus.c
> +++ b/drivers/amba/bus.c
> @@ -17,6 +17,7 @@
> #include <linux/pm_runtime.h>
> #include <linux/amba/bus.h>
> #include <linux/sizes.h>
> +#include <linux/of_device.h>
>
> #include <asm/irq.h>
>
> @@ -268,6 +269,7 @@ static void amba_device_release(struct device *dev)
> {
> struct amba_device *d = to_amba_device(dev);
>
> + of_device_node_put(dev);
> if (d->res.parent)
> release_resource(&d->res);
> kfree(d);
> diff --git a/include/linux/of_device.h b/include/linux/of_device.h
> index ef37021..fd14d46 100644
> --- a/include/linux/of_device.h
> +++ b/include/linux/of_device.h
> @@ -41,6 +41,8 @@ extern int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env
>
> static inline void of_device_node_put(struct device *dev)
> {
> + if (dev->of_node)
> + of_node_clear_flag(dev->of_node, OF_POPULATED);
> of_node_put(dev->of_node);
> }
> --8<-----------
>
> This will work even if one manually unregisters a DT-originating device,
> because of_device_node_put() would be called in both amba and platform
> device (kobj) release path.
Doing it that way will also catch platform_devices that were created
apart from of_platform_populate() and manually attached to an of_node,
which is done some times. It will also break whenever multiple devices
reference the same node if they call of_device_node_put().
For example, a platform device providing an i2c bus will have a child
device that represents the i2c bus, and that i2c device will point to
the same node.
The flag clear really does need to be kept in the
platform_device_unpopulate path because it is only to be used internally
by of_platform_{populate,depopulate}
>
> By the way, the fact that today amba_device_release() doesn't do
> of_device_node_put() seems like a bug to me? (node's reference counter
> won't be decremented)
Yes, that is a bug. I want to get some unittests added to the DT code to
verify that reference counts are being tracked correctly. Right now it
is an utter mess.
>
> > The function shouldn't be too difficult. I would expect it to look
> > something like this. You'll need to check the details.
>
> 8<-----------
> diff --git a/drivers/of/platform.c b/drivers/of/platform.c
> index dd4328c..b6b5a2b 100644
> --- a/drivers/of/platform.c
> +++ b/drivers/of/platform.c
> @@ -493,4 +493,49 @@ int of_platform_populate(struct device_node *root,
> return rc;
> }
> EXPORT_SYMBOL_GPL(of_platform_populate);
> +
> +static int of_platform_device_destroy(struct device *dev, void *data)
> +{
> + int *parents_children_left = data;
> + int my_children_left = 0;
> +
> + /* Do not touch devices not populated from the device tree */
> + if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED)) {
> + *parents_children_left++;
> + return 0;
> + }
> +
> + device_for_each_child(dev, &my_children_left,
> + of_platform_device_destroy);
> + if (my_children_left) {
> + *parents_children_left++;
> + return 0;
> + }
> +
> + if (dev->bus == &platform_bus_type)
> + platform_device_unregister(to_platform_device(dev));
> + else if (dev->bus == &amba_bustype)
> + amba_device_unregister(to_amba_device(dev));
> +
> + return 0;
> +}
This new code looks good to me. I haven't done any testing though.
Acked-by: Grant Likely <grant.likely-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> +
> +/**
> + * of_platform_depopulate() - Remove devices populated from device tree
> + * @parent: device which childred will be removed
> + *
> + * Complementary to of_platform_populate(), this function removes children
> + * of the given device (and, recurrently, their children) that have been
> + * created from their respective device tree nodes (and only those,
> + * leaving others - eg. manually created - unharmed). */
> + */
> +int of_platform_depopulate(struct device *parent)
> +{
> + int children_left = 0;
> +
> + device_for_each_child(dev, &children_left, of_platform_device_destroy);
> +
> + return children_left ? -EBUSY : 0;
> +}
> +EXPORT_SYMBOL_GPL(of_platform_depopulate);
> #endif /* CONFIG_OF_ADDRESS */
> diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h
> index 05cb4a9..ef4f4ad 100644
> --- a/include/linux/of_platform.h
> +++ b/include/linux/of_platform.h
> @@ -72,6 +72,7 @@ extern int of_platform_populate(struct device_node *root,
> const struct of_device_id *matches,
> const struct of_dev_auxdata *lookup,
> struct device *parent);
> +static inline int of_platform_depopulate(struct device *parent);
> #else
> static inline int of_platform_populate(struct device_node *root,
> const struct of_device_id *matches,
> @@ -80,6 +81,10 @@ static inline int of_platform_populate(struct device_node *root,
> {
> return -ENODEV;
> }
> +static inline int of_platform_depopulate(struct device *parent)
> +{
> + return -ENODEV;
> +}
> #endif
>
> #endif /* _LINUX_OF_PLATFORM_H */
> 8<-----------
>
> > static int __of_platform_unpopulate_device(struct device *dev, void *c)
> > {
> > if (!dev->of_node || !of_node_get_flag(dev->of_node, OF_POPULATED)
> > return 0;
> >
> > // recursively remove the children too --- I'd like to find a way
> > to do this non-recursively
> > device_for_each_child(dev, NULL, __of_platform_unpopulate_device);
>
> As of_platform_populate() is recursive itself, I don't see much problem
> with this
Right, that was just a side comment. I like to avoid recursion as much
as possible in kernel code, but I'm certainly not going to NAK on that
basis.
>
> > // Need to check if the device should be explicitly unbound from
> > it's driver before removing it. However, I think the driver core takes
> > care of this for us.
>
> Yep, removing either a driver or a device unbinds all existing pairs.
>
> > // Remove based on the bus type
> > switch (dev->bus) {
> > case &platform_bus_type:
>
> To my surprise gcc said "error: pointers are not permitted as case
> values". One learns every day ;-)
:-) Good to know.
>
> > platform_device_remove(to_platform_device(dev));
> > break;
> > case &amba_bus_type:
> > amba_device_remove(to_platform_device(dev));
> > break;
> > }
> >
> > // Should check here if there are any other children to the
> > device. It is probably bad to remove a device that still has children.
> > Need to check what the driver core will do.
> > }
>
> The reference count will be still be greater than 0, so the parent won't
> be harmed. Nevertheless it's better to consciously handle such case. At
> least I tried.
>
> Pawel
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3] of: Keep track of populated platform devices
[not found] ` <CAL_Jsq+8xZO0LEhVa4tmOfq6CD2a0O+0CaGCnZLqDguz=yN_zg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2014-05-14 11:05 ` Grant Likely
0 siblings, 0 replies; 14+ messages in thread
From: Grant Likely @ 2014-05-14 11:05 UTC (permalink / raw)
To: Rob Herring, Pawel Moll
Cc: Rob Herring, Russell King,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
On Tue, 13 May 2014 07:24:50 -0500, Rob Herring <robherring2-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> On Tue, May 13, 2014 at 6:48 AM, Pawel Moll <pawel.moll-5wv7dgnIgG8@public.gmane.org> wrote:
> > In "Device Tree powered" systems, platform devices are usually
> > massively populated with of_platform_populate() call, executed
> > at some level of initcalls, either by generic architecture
> > or by platform-specific code.
> >
> > There are situations though where certain devices must be
> > created (and bound with drivers) before all the others.
> > This presents a challenge, as devices created explicitly
> > would be created again by of_platform_populate().
> >
> > This patch tries to solve that issue in a generic way,
> > adding a "populated" flag for a DT node description.
> > Once set, this device will never be created again via
> > of_* API, so of_platform_populate() will skip such nodes
> > (and its children) in a similar way to the non-available
> > ones.
> >
> > The flag is cleared when a device is being removed and
> > returns the DT node by calling of_device_node_put() (it
> > was missing from the amba device release function, added).
> >
> > Signed-off-by: Pawel Moll <pawel.moll-5wv7dgnIgG8@public.gmane.org>
>
> A few formatting nits, but otherwise:
>
> Reviewed-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Acked-by: Grant Likely <grant.likely-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
g.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2] of: Keep track of populated platform devices
[not found] ` <20140514105657.CF966C4153D-WNowdnHR2B42iJbIjFUEsiwD8/FfD2ys@public.gmane.org>
@ 2014-05-15 15:08 ` Pawel Moll
0 siblings, 0 replies; 14+ messages in thread
From: Pawel Moll @ 2014-05-15 15:08 UTC (permalink / raw)
To: Grant Likely
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Rob Herring,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
On Wed, 2014-05-14 at 11:56 +0100, Grant Likely wrote:
> > Agreed, but, unless I'm missing some fundamental issue, I believe we can
> > solve the flag clearing problem in a generic way:
> >
> > --8<-----------
> > diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
> > index 3cf61a1..0f489fb 100644
> > --- a/drivers/amba/bus.c
> > +++ b/drivers/amba/bus.c
> > @@ -17,6 +17,7 @@
> > #include <linux/pm_runtime.h>
> > #include <linux/amba/bus.h>
> > #include <linux/sizes.h>
> > +#include <linux/of_device.h>
> >
> > #include <asm/irq.h>
> >
> > @@ -268,6 +269,7 @@ static void amba_device_release(struct device *dev)
> > {
> > struct amba_device *d = to_amba_device(dev);
> >
> > + of_device_node_put(dev);
> > if (d->res.parent)
> > release_resource(&d->res);
> > kfree(d);
> > diff --git a/include/linux/of_device.h b/include/linux/of_device.h
> > index ef37021..fd14d46 100644
> > --- a/include/linux/of_device.h
> > +++ b/include/linux/of_device.h
> > @@ -41,6 +41,8 @@ extern int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env
> >
> > static inline void of_device_node_put(struct device *dev)
> > {
> > + if (dev->of_node)
> > + of_node_clear_flag(dev->of_node, OF_POPULATED);
> > of_node_put(dev->of_node);
> > }
> > --8<-----------
> >
> > This will work even if one manually unregisters a DT-originating device,
> > because of_device_node_put() would be called in both amba and platform
> > device (kobj) release path.
>
> Doing it that way will also catch platform_devices that were created
> apart from of_platform_populate() and manually attached to an of_node,
> which is done some times. It will also break whenever multiple devices
> reference the same node if they call of_device_node_put().
>
> For example, a platform device providing an i2c bus will have a child
> device that represents the i2c bus, and that i2c device will point to
> the same node.
Yes, can I see it doing this. Without
> The flag clear really does need to be kept in the
> platform_device_unpopulate path because it is only to be used internally
> by of_platform_{populate,depopulate}
Ok, will move it there.
> > By the way, the fact that today amba_device_release() doesn't do
> > of_device_node_put() seems like a bug to me? (node's reference counter
> > won't be decremented)
>
> Yes, that is a bug. I want to get some unittests added to the DT code to
> verify that reference counts are being tracked correctly. Right now it
> is an utter mess.
Ok. If I move the flag, this bit is not longer an integral part of the
patch so will split it into a separate one, but merge the _depopulate()
one instead.
Thanks!
Paweł
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2014-05-15 15:08 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <1398707877-22596-1-git-send-email-pawel.moll@arm.com>
2014-04-28 17:57 ` [PATCH 01/10] of: Keep track of populated platform devices Pawel Moll
2014-04-28 18:02 ` Rob Herring
[not found] ` <CAL_JsqJxWoxNL=P0SJm+Q1rTRGTpMkzmzTJDbFq2P1vPH4XxZQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-04-29 12:56 ` Grant Likely
[not found] ` <20140429125657.65910C4089D-WNowdnHR2B42iJbIjFUEsiwD8/FfD2ys@public.gmane.org>
2014-04-30 11:48 ` Pawel Moll
2014-04-30 14:05 ` [PATCH v2] " Pawel Moll
[not found] ` <1398866717-20268-1-git-send-email-pawel.moll-5wv7dgnIgG8@public.gmane.org>
2014-04-30 15:22 ` Rob Herring
[not found] ` <CAL_JsqL=mxqEKpAsXm7Du0vEDpKk4n+dp5-DyvbuGhTA6bP5Lg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-05-01 9:26 ` Grant Likely
[not found] ` <20140501092635.05011C409DA-WNowdnHR2B42iJbIjFUEsiwD8/FfD2ys@public.gmane.org>
2014-05-01 9:43 ` Grant Likely
[not found] ` <CACxGe6usWdey1qQT2JF=7LuE62H-_xtd1QkRT9z_Tj2pxdQEjQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-05-07 14:37 ` Pawel Moll
2014-05-14 10:56 ` Grant Likely
[not found] ` <20140514105657.CF966C4153D-WNowdnHR2B42iJbIjFUEsiwD8/FfD2ys@public.gmane.org>
2014-05-15 15:08 ` Pawel Moll
[not found] <Message-ID: <1399473437.3706.25.camel@hornet>
2014-05-13 11:48 ` [PATCH v3] " Pawel Moll
[not found] ` <1399981716-24618-1-git-send-email-pawel.moll-5wv7dgnIgG8@public.gmane.org>
2014-05-13 12:24 ` Rob Herring
[not found] ` <CAL_Jsq+8xZO0LEhVa4tmOfq6CD2a0O+0CaGCnZLqDguz=yN_zg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-05-14 11:05 ` Grant Likely
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).