* [PATCH] dt: add of_alias_scan and of_alias_get_id
@ 2011-08-15 1:30 Shawn Guo
[not found] ` <1313371817-5135-1-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2011-08-15 7:28 ` [PATCH v2] " Shawn Guo
0 siblings, 2 replies; 15+ messages in thread
From: Shawn Guo @ 2011-08-15 1:30 UTC (permalink / raw)
To: devicetree-discuss
Cc: linux-kernel, Grant Likely, David Miller, patches, Shawn Guo
The patch adds function of_alias_scan to populate a global lookup
table with the properties of 'aliases' node and function
of_alias_get_id for drivers to find alias id from the lookup table.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
[grant.likey: add locking and rework parse loop]
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
Changes since the last post:
* Pass alloc function pointer as a parameter to of_alias_scan()
* Move of_chosen and of_aliases populating into function
__unflatten_device_tree which is the common path of two
unflattening sites
* Change simple_strtoul() to kstrtoint() which is suggestion by
checkpatch as a warning
drivers/of/base.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++
drivers/of/fdt.c | 12 +++--
include/linux/of.h | 8 +++
include/linux/of_fdt.h | 1 -
4 files changed, 151 insertions(+), 6 deletions(-)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 3ff22e3..5e6ce02 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -17,14 +17,39 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/ctype.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
+/**
+ * struct alias_prop - Alias property in 'aliases' node
+ * @link: List node to link the structure in aliases_lookup list
+ * @alias: Alias property name
+ * @np: Pointer to device_node that the alias stands for
+ * @id: Index value from end of alias name
+ * @stem: Alias string without the index
+ *
+ * The structure represents one alias property of 'aliases' node as
+ * an entry in aliases_lookup list.
+ */
+struct alias_prop {
+ struct list_head link;
+ const char *alias;
+ struct device_node *np;
+ int id;
+ char stem[0];
+};
+
+static LIST_HEAD(aliases_lookup);
+
struct device_node *allnodes;
struct device_node *of_chosen;
+struct device_node *of_aliases;
+
+static DEFINE_MUTEX(of_aliases_mutex);
/* use when traversing tree through the allnext, child, sibling,
* or parent members of struct device_node.
@@ -988,3 +1013,114 @@ out_unlock:
}
#endif /* defined(CONFIG_OF_DYNAMIC) */
+static void of_alias_add(struct alias_prop *ap, struct device_node *np,
+ int id, const char *stem, int stem_len)
+{
+ ap->np = np;
+ ap->id = id;
+ strncpy(ap->stem, stem, stem_len);
+ ap->stem[stem_len] = 0;
+ list_add_tail(&ap->link, &aliases_lookup);
+ pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n",
+ ap->alias, ap->stem, ap->id, np ? np->full_name : NULL);
+}
+
+/**
+ * of_alias_scan - Scan all properties of 'aliases' node
+ *
+ * The function scans all the properties of 'aliases' node and populate
+ * the the global lookup table with the properties. It returns the
+ * number of alias_prop found, or error code in error case.
+ *
+ * @dt_alloc: An allocator that provides a virtual address to memory
+ * for the resulting tree
+ */
+void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
+{
+ struct property *pp;
+
+ if (!of_aliases)
+ return;
+
+ for_each_property(pp, of_aliases->properties) {
+ const char *start = pp->name;
+ const char *end = start + strlen(start);
+ struct device_node *np;
+ struct alias_prop *ap;
+ int id, len;
+
+ /* Skip those we do not want to proceed */
+ if (!strcmp(pp->name, "name") ||
+ !strcmp(pp->name, "phandle") ||
+ !strcmp(pp->name, "linux,phandle"))
+ continue;
+
+ np = of_find_node_by_path(pp->value);
+ if (!np)
+ continue;
+
+ /* walk the alias backwards to extract the id and work out
+ * the 'stem' string */
+ while (isdigit(*(end-1)) && end > start)
+ end--;
+ len = end - start;
+
+ if (kstrtoint(end, 10, &id) < 0)
+ continue;
+
+ /* Allocate an alias_prop with enough space for the stem */
+ ap = dt_alloc(sizeof(*ap) + len + 1, 4);
+ if (!ap)
+ continue;
+ ap->alias = start;
+ of_alias_add(ap, np, id, start, len);
+ }
+}
+
+/**
+ * of_alias_get_id - Get alias id for the given device_node
+ * @np: Pointer to the given device_node
+ * @stem: Alias stem of the given device_node
+ *
+ * The function travels the lookup table to get alias id for the given
+ * device_node and alias stem. It returns the alias id if find it.
+ * If not, dynamically creates one in the lookup table and returns it,
+ * or returns error code if fail to create.
+ */
+int of_alias_get_id(struct device_node *np, const char *stem)
+{
+ struct alias_prop *app;
+ int id = 0;
+ bool found = false;
+
+ mutex_lock(&of_aliases_mutex);
+ list_for_each_entry(app, &aliases_lookup, link) {
+ if (strcmp(app->stem, stem) != 0)
+ continue;
+
+ if (np == app->np) {
+ found = true;
+ id = app->id;
+ break;
+ }
+
+ if (id <= app->id)
+ id = app->id + 1;
+ }
+
+ /* If an id is not found, then allocate a new one */
+ if (!found) {
+ app = kzalloc(sizeof(*app) + strlen(stem) + 1, 4);
+ if (!app) {
+ id = -ENODEV;
+ goto out;
+ }
+ of_alias_add(app, np, id, stem, strlen(stem));
+ }
+
+ out:
+ mutex_unlock(&of_aliases_mutex);
+
+ return id;
+}
+EXPORT_SYMBOL_GPL(of_alias_get_id);
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 65200af..98b6fb1 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -404,6 +404,13 @@ static void __unflatten_device_tree(struct boot_param_header *blob,
be32_to_cpu(((__be32 *)mem)[size / 4]));
*allnextp = NULL;
+ /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
+ of_chosen = of_find_node_by_path("/chosen");
+ if (of_chosen == NULL)
+ of_chosen = of_find_node_by_path("/chosen@0");
+ of_aliases = of_find_node_by_path("/aliases");
+ of_alias_scan(dt_alloc);
+
pr_debug(" <- unflatten_device_tree()\n");
}
@@ -706,11 +713,6 @@ void __init unflatten_device_tree(void)
{
__unflatten_device_tree(initial_boot_params, &allnodes,
early_init_dt_alloc_memory_arch);
-
- /* Get pointer to OF "/chosen" node for use everywhere */
- of_chosen = of_find_node_by_path("/chosen");
- if (of_chosen == NULL)
- of_chosen = of_find_node_by_path("/chosen@0");
}
#endif /* CONFIG_OF_EARLY_FLATTREE */
diff --git a/include/linux/of.h b/include/linux/of.h
index 9180dc5..4ea7d81 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -68,6 +68,7 @@ struct device_node {
/* Pointer for first entry in chain of all nodes. */
extern struct device_node *allnodes;
extern struct device_node *of_chosen;
+extern struct device_node *of_aliases;
extern rwlock_t devtree_lock;
static inline bool of_have_populated_dt(void)
@@ -209,6 +210,9 @@ extern int of_device_is_available(const struct device_node *device);
extern const void *of_get_property(const struct device_node *node,
const char *name,
int *lenp);
+#define for_each_property(pp, properties) \
+ for (pp = properties; pp != NULL; pp = pp->next)
+
extern int of_n_addr_cells(struct device_node *np);
extern int of_n_size_cells(struct device_node *np);
extern const struct of_device_id *of_match_node(
@@ -221,6 +225,10 @@ extern int of_parse_phandles_with_args(struct device_node *np,
const char *list_name, const char *cells_name, int index,
struct device_node **out_node, const void **out_args);
+extern void *early_init_dt_alloc_memory_arch(u64 size, u64 align);
+extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align));
+extern int of_alias_get_id(struct device_node *np, const char *stem);
+
extern int of_machine_is_compatible(const char *compat);
extern int prom_add_property(struct device_node* np, struct property* prop);
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
index c84d900..b74b74f 100644
--- a/include/linux/of_fdt.h
+++ b/include/linux/of_fdt.h
@@ -97,7 +97,6 @@ extern void early_init_dt_check_for_initrd(unsigned long node);
extern int early_init_dt_scan_memory(unsigned long node, const char *uname,
int depth, void *data);
extern void early_init_dt_add_memory_arch(u64 base, u64 size);
-extern void * early_init_dt_alloc_memory_arch(u64 size, u64 align);
extern u64 dt_mem_next_cell(int s, __be32 **cellp);
/*
--
1.7.4.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH] dt: add of_alias_scan and of_alias_get_id
[not found] ` <1313371817-5135-1-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
@ 2011-08-15 5:43 ` David Miller
2011-08-15 6:07 ` Shawn Guo
0 siblings, 1 reply; 15+ messages in thread
From: David Miller @ 2011-08-15 5:43 UTC (permalink / raw)
To: shawn.guo-QSEj5FYQhm4dnm+yROfE0A
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
patches-QSEj5FYQhm4dnm+yROfE0A
From: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Date: Mon, 15 Aug 2011 09:30:17 +0800
> *allnextp = NULL;
>
> + /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
> + of_chosen = of_find_node_by_path("/chosen");
> + if (of_chosen == NULL)
> + of_chosen = of_find_node_by_path("/chosen@0");
> + of_aliases = of_find_node_by_path("/aliases");
> + of_alias_scan(dt_alloc);
> +
> pr_debug(" <- unflatten_device_tree()\n");
> }
You need to add invocations of the scan to other places in the
tree that build the in-kernel device tree.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] dt: add of_alias_scan and of_alias_get_id
[not found] ` <20110815060708.GH7244-+NayF8gZjK2ctlrPMvKcciBecyulp+rMXqFh9Ls21Oc@public.gmane.org>
@ 2011-08-15 6:05 ` David Miller
[not found] ` <20110814.230529.611834234177280886.davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
0 siblings, 1 reply; 15+ messages in thread
From: David Miller @ 2011-08-15 6:05 UTC (permalink / raw)
To: shawn.guo-KZfg59tc24xl57MIdRCFDg
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
patches-QSEj5FYQhm4dnm+yROfE0A
From: Shawn Guo <shawn.guo-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
Date: Mon, 15 Aug 2011 14:07:09 +0800
> Can you please help me a little bit more with the "other places"?
arch/sparc/kernel/prom*.c
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] dt: add of_alias_scan and of_alias_get_id
2011-08-15 5:43 ` David Miller
@ 2011-08-15 6:07 ` Shawn Guo
[not found] ` <20110815060708.GH7244-+NayF8gZjK2ctlrPMvKcciBecyulp+rMXqFh9Ls21Oc@public.gmane.org>
0 siblings, 1 reply; 15+ messages in thread
From: Shawn Guo @ 2011-08-15 6:07 UTC (permalink / raw)
To: David Miller; +Cc: shawn.guo, devicetree-discuss, linux-kernel, patches
Hi David,
On Sun, Aug 14, 2011 at 10:43:41PM -0700, David Miller wrote:
> From: Shawn Guo <shawn.guo@linaro.org>
> Date: Mon, 15 Aug 2011 09:30:17 +0800
>
> > *allnextp = NULL;
> >
> > + /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
> > + of_chosen = of_find_node_by_path("/chosen");
> > + if (of_chosen == NULL)
> > + of_chosen = of_find_node_by_path("/chosen@0");
> > + of_aliases = of_find_node_by_path("/aliases");
> > + of_alias_scan(dt_alloc);
> > +
> > pr_debug(" <- unflatten_device_tree()\n");
> > }
>
> You need to add invocations of the scan to other places in the
> tree that build the in-kernel device tree.
Can you please help me a little bit more with the "other places"?
I'm still pretty new to device tree beyond ARM platform.
--
Regards,
Shawn
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] dt: add of_alias_scan and of_alias_get_id
[not found] ` <20110815063643.GI7244-+NayF8gZjK2ctlrPMvKcciBecyulp+rMXqFh9Ls21Oc@public.gmane.org>
@ 2011-08-15 6:35 ` David Miller
2011-08-15 6:47 ` Shawn Guo
0 siblings, 1 reply; 15+ messages in thread
From: David Miller @ 2011-08-15 6:35 UTC (permalink / raw)
To: shawn.guo-KZfg59tc24xl57MIdRCFDg
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
patches-QSEj5FYQhm4dnm+yROfE0A
From: Shawn Guo <shawn.guo-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
Date: Mon, 15 Aug 2011 14:36:44 +0800
> @@ -245,4 +245,11 @@ void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops)
> nextp = &allnodes->allnext;
> allnodes->child = of_pdt_build_tree(allnodes,
> of_pdt_prom_ops->getchild(allnodes->phandle), &nextp);
> +
> + /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
> + of_chosen = of_find_node_by_path("/chosen");
> + if (of_chosen == NULL)
> + of_chosen = of_find_node_by_path("/chosen@0");
> + of_aliases = of_find_node_by_path("/aliases");
> + of_alias_scan(dt_alloc);
> }
There is no dt_alloc variable visible in this function.
I didn't need to use a compiler to find this problem, and neither
do you.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] dt: add of_alias_scan and of_alias_get_id
[not found] ` <20110814.230529.611834234177280886.davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
@ 2011-08-15 6:36 ` Shawn Guo
[not found] ` <20110815063643.GI7244-+NayF8gZjK2ctlrPMvKcciBecyulp+rMXqFh9Ls21Oc@public.gmane.org>
2011-08-15 6:45 ` Shawn Guo
0 siblings, 2 replies; 15+ messages in thread
From: Shawn Guo @ 2011-08-15 6:36 UTC (permalink / raw)
To: David Miller
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
patches-QSEj5FYQhm4dnm+yROfE0A
On Sun, Aug 14, 2011 at 11:05:29PM -0700, David Miller wrote:
> From: Shawn Guo <shawn.guo-KZfg59tc24xl57MIdRCFDg@public.gmane.org>
> Date: Mon, 15 Aug 2011 14:07:09 +0800
>
> > Can you please help me a little bit more with the "other places"?
>
> arch/sparc/kernel/prom*.c
>
How about the following changes? I do not even have a compiler to do
build test for sparc. Is it possible for me to get one from somewhere?
---8<-----
diff --git a/drivers/of/pdt.c b/drivers/of/pdt.c
index 4d87b5d..124280a 100644
--- a/drivers/of/pdt.c
+++ b/drivers/of/pdt.c
@@ -245,4 +245,11 @@ void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops)
nextp = &allnodes->allnext;
allnodes->child = of_pdt_build_tree(allnodes,
of_pdt_prom_ops->getchild(allnodes->phandle), &nextp);
+
+ /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
+ of_chosen = of_find_node_by_path("/chosen");
+ if (of_chosen == NULL)
+ of_chosen = of_find_node_by_path("/chosen@0");
+ of_aliases = of_find_node_by_path("/aliases");
+ of_alias_scan(dt_alloc);
}
--
Regards,
Shawn
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH] dt: add of_alias_scan and of_alias_get_id
2011-08-15 6:36 ` Shawn Guo
[not found] ` <20110815063643.GI7244-+NayF8gZjK2ctlrPMvKcciBecyulp+rMXqFh9Ls21Oc@public.gmane.org>
@ 2011-08-15 6:45 ` Shawn Guo
1 sibling, 0 replies; 15+ messages in thread
From: Shawn Guo @ 2011-08-15 6:45 UTC (permalink / raw)
To: David Miller; +Cc: devicetree-discuss, linux-kernel, patches
On Mon, Aug 15, 2011 at 02:36:44PM +0800, Shawn Guo wrote:
> On Sun, Aug 14, 2011 at 11:05:29PM -0700, David Miller wrote:
> > From: Shawn Guo <shawn.guo@freescale.com>
> > Date: Mon, 15 Aug 2011 14:07:09 +0800
> >
> > > Can you please help me a little bit more with the "other places"?
> >
> > arch/sparc/kernel/prom*.c
> >
> How about the following changes? I do not even have a compiler to do
> build test for sparc. Is it possible for me to get one from somewhere?
>
> ---8<-----
> diff --git a/drivers/of/pdt.c b/drivers/of/pdt.c
> index 4d87b5d..124280a 100644
> --- a/drivers/of/pdt.c
> +++ b/drivers/of/pdt.c
> @@ -245,4 +245,11 @@ void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops)
> nextp = &allnodes->allnext;
> allnodes->child = of_pdt_build_tree(allnodes,
> of_pdt_prom_ops->getchild(allnodes->phandle), &nextp);
> +
> + /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
> + of_chosen = of_find_node_by_path("/chosen");
> + if (of_chosen == NULL)
> + of_chosen = of_find_node_by_path("/chosen@0");
> + of_aliases = of_find_node_by_path("/aliases");
> + of_alias_scan(dt_alloc);
dt_alloc here needs to be some wrapper function of prom_early_alloc().
> }
--
Regards,
Shawn
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] dt: add of_alias_scan and of_alias_get_id
2011-08-15 6:35 ` David Miller
@ 2011-08-15 6:47 ` Shawn Guo
0 siblings, 0 replies; 15+ messages in thread
From: Shawn Guo @ 2011-08-15 6:47 UTC (permalink / raw)
To: David Miller; +Cc: shawn.guo, devicetree-discuss, linux-kernel, patches
On Sun, Aug 14, 2011 at 11:35:59PM -0700, David Miller wrote:
> From: Shawn Guo <shawn.guo@freescale.com>
> Date: Mon, 15 Aug 2011 14:36:44 +0800
>
> > @@ -245,4 +245,11 @@ void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops)
> > nextp = &allnodes->allnext;
> > allnodes->child = of_pdt_build_tree(allnodes,
> > of_pdt_prom_ops->getchild(allnodes->phandle), &nextp);
> > +
> > + /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
> > + of_chosen = of_find_node_by_path("/chosen");
> > + if (of_chosen == NULL)
> > + of_chosen = of_find_node_by_path("/chosen@0");
> > + of_aliases = of_find_node_by_path("/aliases");
> > + of_alias_scan(dt_alloc);
> > }
>
> There is no dt_alloc variable visible in this function.
>
> I didn't need to use a compiler to find this problem, and neither
> do you.
>
I should have found that before sending it even for comment. Yeah,
you beat me to that!
--
Regards,
Shawn
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2] dt: add of_alias_scan and of_alias_get_id
2011-08-15 1:30 [PATCH] dt: add of_alias_scan and of_alias_get_id Shawn Guo
[not found] ` <1313371817-5135-1-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
@ 2011-08-15 7:28 ` Shawn Guo
[not found] ` <1313393294-8867-1-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
1 sibling, 1 reply; 15+ messages in thread
From: Shawn Guo @ 2011-08-15 7:28 UTC (permalink / raw)
To: devicetree-discuss
Cc: linux-kernel, Grant Likely, David Miller, patches, Shawn Guo
The patch adds function of_alias_scan to populate a global lookup
table with the properties of 'aliases' node and function
of_alias_get_id for drivers to find alias id from the lookup table.
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
[grant.likey: add locking and rework parse loop]
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
Changes since v1:
* Add of_chosen/of_aliases populating and of_alias_scan() invocation
for OF_PROMTREE (non-tested).
drivers/of/base.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++
drivers/of/fdt.c | 12 +++--
drivers/of/pdt.c | 12 ++++
include/linux/of.h | 8 +++
include/linux/of_fdt.h | 1 -
5 files changed, 163 insertions(+), 6 deletions(-)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 3ff22e3..5e6ce02 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -17,14 +17,39 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/ctype.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
+/**
+ * struct alias_prop - Alias property in 'aliases' node
+ * @link: List node to link the structure in aliases_lookup list
+ * @alias: Alias property name
+ * @np: Pointer to device_node that the alias stands for
+ * @id: Index value from end of alias name
+ * @stem: Alias string without the index
+ *
+ * The structure represents one alias property of 'aliases' node as
+ * an entry in aliases_lookup list.
+ */
+struct alias_prop {
+ struct list_head link;
+ const char *alias;
+ struct device_node *np;
+ int id;
+ char stem[0];
+};
+
+static LIST_HEAD(aliases_lookup);
+
struct device_node *allnodes;
struct device_node *of_chosen;
+struct device_node *of_aliases;
+
+static DEFINE_MUTEX(of_aliases_mutex);
/* use when traversing tree through the allnext, child, sibling,
* or parent members of struct device_node.
@@ -988,3 +1013,114 @@ out_unlock:
}
#endif /* defined(CONFIG_OF_DYNAMIC) */
+static void of_alias_add(struct alias_prop *ap, struct device_node *np,
+ int id, const char *stem, int stem_len)
+{
+ ap->np = np;
+ ap->id = id;
+ strncpy(ap->stem, stem, stem_len);
+ ap->stem[stem_len] = 0;
+ list_add_tail(&ap->link, &aliases_lookup);
+ pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n",
+ ap->alias, ap->stem, ap->id, np ? np->full_name : NULL);
+}
+
+/**
+ * of_alias_scan - Scan all properties of 'aliases' node
+ *
+ * The function scans all the properties of 'aliases' node and populate
+ * the the global lookup table with the properties. It returns the
+ * number of alias_prop found, or error code in error case.
+ *
+ * @dt_alloc: An allocator that provides a virtual address to memory
+ * for the resulting tree
+ */
+void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
+{
+ struct property *pp;
+
+ if (!of_aliases)
+ return;
+
+ for_each_property(pp, of_aliases->properties) {
+ const char *start = pp->name;
+ const char *end = start + strlen(start);
+ struct device_node *np;
+ struct alias_prop *ap;
+ int id, len;
+
+ /* Skip those we do not want to proceed */
+ if (!strcmp(pp->name, "name") ||
+ !strcmp(pp->name, "phandle") ||
+ !strcmp(pp->name, "linux,phandle"))
+ continue;
+
+ np = of_find_node_by_path(pp->value);
+ if (!np)
+ continue;
+
+ /* walk the alias backwards to extract the id and work out
+ * the 'stem' string */
+ while (isdigit(*(end-1)) && end > start)
+ end--;
+ len = end - start;
+
+ if (kstrtoint(end, 10, &id) < 0)
+ continue;
+
+ /* Allocate an alias_prop with enough space for the stem */
+ ap = dt_alloc(sizeof(*ap) + len + 1, 4);
+ if (!ap)
+ continue;
+ ap->alias = start;
+ of_alias_add(ap, np, id, start, len);
+ }
+}
+
+/**
+ * of_alias_get_id - Get alias id for the given device_node
+ * @np: Pointer to the given device_node
+ * @stem: Alias stem of the given device_node
+ *
+ * The function travels the lookup table to get alias id for the given
+ * device_node and alias stem. It returns the alias id if find it.
+ * If not, dynamically creates one in the lookup table and returns it,
+ * or returns error code if fail to create.
+ */
+int of_alias_get_id(struct device_node *np, const char *stem)
+{
+ struct alias_prop *app;
+ int id = 0;
+ bool found = false;
+
+ mutex_lock(&of_aliases_mutex);
+ list_for_each_entry(app, &aliases_lookup, link) {
+ if (strcmp(app->stem, stem) != 0)
+ continue;
+
+ if (np == app->np) {
+ found = true;
+ id = app->id;
+ break;
+ }
+
+ if (id <= app->id)
+ id = app->id + 1;
+ }
+
+ /* If an id is not found, then allocate a new one */
+ if (!found) {
+ app = kzalloc(sizeof(*app) + strlen(stem) + 1, 4);
+ if (!app) {
+ id = -ENODEV;
+ goto out;
+ }
+ of_alias_add(app, np, id, stem, strlen(stem));
+ }
+
+ out:
+ mutex_unlock(&of_aliases_mutex);
+
+ return id;
+}
+EXPORT_SYMBOL_GPL(of_alias_get_id);
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 65200af..98b6fb1 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -404,6 +404,13 @@ static void __unflatten_device_tree(struct boot_param_header *blob,
be32_to_cpu(((__be32 *)mem)[size / 4]));
*allnextp = NULL;
+ /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
+ of_chosen = of_find_node_by_path("/chosen");
+ if (of_chosen == NULL)
+ of_chosen = of_find_node_by_path("/chosen@0");
+ of_aliases = of_find_node_by_path("/aliases");
+ of_alias_scan(dt_alloc);
+
pr_debug(" <- unflatten_device_tree()\n");
}
@@ -706,11 +713,6 @@ void __init unflatten_device_tree(void)
{
__unflatten_device_tree(initial_boot_params, &allnodes,
early_init_dt_alloc_memory_arch);
-
- /* Get pointer to OF "/chosen" node for use everywhere */
- of_chosen = of_find_node_by_path("/chosen");
- if (of_chosen == NULL)
- of_chosen = of_find_node_by_path("/chosen@0");
}
#endif /* CONFIG_OF_EARLY_FLATTREE */
diff --git a/drivers/of/pdt.c b/drivers/of/pdt.c
index 4d87b5d..686a4b3 100644
--- a/drivers/of/pdt.c
+++ b/drivers/of/pdt.c
@@ -229,6 +229,11 @@ static struct device_node * __init of_pdt_build_tree(struct device_node *parent,
return ret;
}
+static void *kernel_tree_alloc(u64 size, u64 align)
+{
+ return prom_early_alloc(size);
+}
+
void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops)
{
struct device_node **nextp;
@@ -245,4 +250,11 @@ void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops)
nextp = &allnodes->allnext;
allnodes->child = of_pdt_build_tree(allnodes,
of_pdt_prom_ops->getchild(allnodes->phandle), &nextp);
+
+ /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
+ of_chosen = of_find_node_by_path("/chosen");
+ if (of_chosen == NULL)
+ of_chosen = of_find_node_by_path("/chosen@0");
+ of_aliases = of_find_node_by_path("/aliases");
+ of_alias_scan(kernel_tree_alloc);
}
diff --git a/include/linux/of.h b/include/linux/of.h
index 9180dc5..4ea7d81 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -68,6 +68,7 @@ struct device_node {
/* Pointer for first entry in chain of all nodes. */
extern struct device_node *allnodes;
extern struct device_node *of_chosen;
+extern struct device_node *of_aliases;
extern rwlock_t devtree_lock;
static inline bool of_have_populated_dt(void)
@@ -209,6 +210,9 @@ extern int of_device_is_available(const struct device_node *device);
extern const void *of_get_property(const struct device_node *node,
const char *name,
int *lenp);
+#define for_each_property(pp, properties) \
+ for (pp = properties; pp != NULL; pp = pp->next)
+
extern int of_n_addr_cells(struct device_node *np);
extern int of_n_size_cells(struct device_node *np);
extern const struct of_device_id *of_match_node(
@@ -221,6 +225,10 @@ extern int of_parse_phandles_with_args(struct device_node *np,
const char *list_name, const char *cells_name, int index,
struct device_node **out_node, const void **out_args);
+extern void *early_init_dt_alloc_memory_arch(u64 size, u64 align);
+extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align));
+extern int of_alias_get_id(struct device_node *np, const char *stem);
+
extern int of_machine_is_compatible(const char *compat);
extern int prom_add_property(struct device_node* np, struct property* prop);
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
index c84d900..b74b74f 100644
--- a/include/linux/of_fdt.h
+++ b/include/linux/of_fdt.h
@@ -97,7 +97,6 @@ extern void early_init_dt_check_for_initrd(unsigned long node);
extern int early_init_dt_scan_memory(unsigned long node, const char *uname,
int depth, void *data);
extern void early_init_dt_add_memory_arch(u64 base, u64 size);
-extern void * early_init_dt_alloc_memory_arch(u64 size, u64 align);
extern u64 dt_mem_next_cell(int s, __be32 **cellp);
/*
--
1.7.4.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v2] dt: add of_alias_scan and of_alias_get_id
[not found] ` <1313393294-8867-1-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
@ 2011-09-19 15:18 ` Shawn Guo
2011-09-21 20:35 ` Grant Likely
1 sibling, 0 replies; 15+ messages in thread
From: Shawn Guo @ 2011-09-19 15:18 UTC (permalink / raw)
To: Shawn Guo
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
patches-QSEj5FYQhm4dnm+yROfE0A,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, David Miller
On Mon, Aug 15, 2011 at 03:28:14PM +0800, Shawn Guo wrote:
> The patch adds function of_alias_scan to populate a global lookup
> table with the properties of 'aliases' node and function
> of_alias_get_id for drivers to find alias id from the lookup table.
>
> Signed-off-by: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> [grant.likey: add locking and rework parse loop]
> Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
Hi Grant,
Any comments on this patch?
Regards,
Shawn
> ---
> Changes since v1:
> * Add of_chosen/of_aliases populating and of_alias_scan() invocation
> for OF_PROMTREE (non-tested).
>
> drivers/of/base.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++
> drivers/of/fdt.c | 12 +++--
> drivers/of/pdt.c | 12 ++++
> include/linux/of.h | 8 +++
> include/linux/of_fdt.h | 1 -
> 5 files changed, 163 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index 3ff22e3..5e6ce02 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -17,14 +17,39 @@
> * as published by the Free Software Foundation; either version
> * 2 of the License, or (at your option) any later version.
> */
> +#include <linux/ctype.h>
> #include <linux/module.h>
> #include <linux/of.h>
> #include <linux/spinlock.h>
> #include <linux/slab.h>
> #include <linux/proc_fs.h>
>
> +/**
> + * struct alias_prop - Alias property in 'aliases' node
> + * @link: List node to link the structure in aliases_lookup list
> + * @alias: Alias property name
> + * @np: Pointer to device_node that the alias stands for
> + * @id: Index value from end of alias name
> + * @stem: Alias string without the index
> + *
> + * The structure represents one alias property of 'aliases' node as
> + * an entry in aliases_lookup list.
> + */
> +struct alias_prop {
> + struct list_head link;
> + const char *alias;
> + struct device_node *np;
> + int id;
> + char stem[0];
> +};
> +
> +static LIST_HEAD(aliases_lookup);
> +
> struct device_node *allnodes;
> struct device_node *of_chosen;
> +struct device_node *of_aliases;
> +
> +static DEFINE_MUTEX(of_aliases_mutex);
>
> /* use when traversing tree through the allnext, child, sibling,
> * or parent members of struct device_node.
> @@ -988,3 +1013,114 @@ out_unlock:
> }
> #endif /* defined(CONFIG_OF_DYNAMIC) */
>
> +static void of_alias_add(struct alias_prop *ap, struct device_node *np,
> + int id, const char *stem, int stem_len)
> +{
> + ap->np = np;
> + ap->id = id;
> + strncpy(ap->stem, stem, stem_len);
> + ap->stem[stem_len] = 0;
> + list_add_tail(&ap->link, &aliases_lookup);
> + pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n",
> + ap->alias, ap->stem, ap->id, np ? np->full_name : NULL);
> +}
> +
> +/**
> + * of_alias_scan - Scan all properties of 'aliases' node
> + *
> + * The function scans all the properties of 'aliases' node and populate
> + * the the global lookup table with the properties. It returns the
> + * number of alias_prop found, or error code in error case.
> + *
> + * @dt_alloc: An allocator that provides a virtual address to memory
> + * for the resulting tree
> + */
> +void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
> +{
> + struct property *pp;
> +
> + if (!of_aliases)
> + return;
> +
> + for_each_property(pp, of_aliases->properties) {
> + const char *start = pp->name;
> + const char *end = start + strlen(start);
> + struct device_node *np;
> + struct alias_prop *ap;
> + int id, len;
> +
> + /* Skip those we do not want to proceed */
> + if (!strcmp(pp->name, "name") ||
> + !strcmp(pp->name, "phandle") ||
> + !strcmp(pp->name, "linux,phandle"))
> + continue;
> +
> + np = of_find_node_by_path(pp->value);
> + if (!np)
> + continue;
> +
> + /* walk the alias backwards to extract the id and work out
> + * the 'stem' string */
> + while (isdigit(*(end-1)) && end > start)
> + end--;
> + len = end - start;
> +
> + if (kstrtoint(end, 10, &id) < 0)
> + continue;
> +
> + /* Allocate an alias_prop with enough space for the stem */
> + ap = dt_alloc(sizeof(*ap) + len + 1, 4);
> + if (!ap)
> + continue;
> + ap->alias = start;
> + of_alias_add(ap, np, id, start, len);
> + }
> +}
> +
> +/**
> + * of_alias_get_id - Get alias id for the given device_node
> + * @np: Pointer to the given device_node
> + * @stem: Alias stem of the given device_node
> + *
> + * The function travels the lookup table to get alias id for the given
> + * device_node and alias stem. It returns the alias id if find it.
> + * If not, dynamically creates one in the lookup table and returns it,
> + * or returns error code if fail to create.
> + */
> +int of_alias_get_id(struct device_node *np, const char *stem)
> +{
> + struct alias_prop *app;
> + int id = 0;
> + bool found = false;
> +
> + mutex_lock(&of_aliases_mutex);
> + list_for_each_entry(app, &aliases_lookup, link) {
> + if (strcmp(app->stem, stem) != 0)
> + continue;
> +
> + if (np == app->np) {
> + found = true;
> + id = app->id;
> + break;
> + }
> +
> + if (id <= app->id)
> + id = app->id + 1;
> + }
> +
> + /* If an id is not found, then allocate a new one */
> + if (!found) {
> + app = kzalloc(sizeof(*app) + strlen(stem) + 1, 4);
> + if (!app) {
> + id = -ENODEV;
> + goto out;
> + }
> + of_alias_add(app, np, id, stem, strlen(stem));
> + }
> +
> + out:
> + mutex_unlock(&of_aliases_mutex);
> +
> + return id;
> +}
> +EXPORT_SYMBOL_GPL(of_alias_get_id);
> diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
> index 65200af..98b6fb1 100644
> --- a/drivers/of/fdt.c
> +++ b/drivers/of/fdt.c
> @@ -404,6 +404,13 @@ static void __unflatten_device_tree(struct boot_param_header *blob,
> be32_to_cpu(((__be32 *)mem)[size / 4]));
> *allnextp = NULL;
>
> + /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
> + of_chosen = of_find_node_by_path("/chosen");
> + if (of_chosen == NULL)
> + of_chosen = of_find_node_by_path("/chosen@0");
> + of_aliases = of_find_node_by_path("/aliases");
> + of_alias_scan(dt_alloc);
> +
> pr_debug(" <- unflatten_device_tree()\n");
> }
>
> @@ -706,11 +713,6 @@ void __init unflatten_device_tree(void)
> {
> __unflatten_device_tree(initial_boot_params, &allnodes,
> early_init_dt_alloc_memory_arch);
> -
> - /* Get pointer to OF "/chosen" node for use everywhere */
> - of_chosen = of_find_node_by_path("/chosen");
> - if (of_chosen == NULL)
> - of_chosen = of_find_node_by_path("/chosen@0");
> }
>
> #endif /* CONFIG_OF_EARLY_FLATTREE */
> diff --git a/drivers/of/pdt.c b/drivers/of/pdt.c
> index 4d87b5d..686a4b3 100644
> --- a/drivers/of/pdt.c
> +++ b/drivers/of/pdt.c
> @@ -229,6 +229,11 @@ static struct device_node * __init of_pdt_build_tree(struct device_node *parent,
> return ret;
> }
>
> +static void *kernel_tree_alloc(u64 size, u64 align)
> +{
> + return prom_early_alloc(size);
> +}
> +
> void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops)
> {
> struct device_node **nextp;
> @@ -245,4 +250,11 @@ void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops)
> nextp = &allnodes->allnext;
> allnodes->child = of_pdt_build_tree(allnodes,
> of_pdt_prom_ops->getchild(allnodes->phandle), &nextp);
> +
> + /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
> + of_chosen = of_find_node_by_path("/chosen");
> + if (of_chosen == NULL)
> + of_chosen = of_find_node_by_path("/chosen@0");
> + of_aliases = of_find_node_by_path("/aliases");
> + of_alias_scan(kernel_tree_alloc);
> }
> diff --git a/include/linux/of.h b/include/linux/of.h
> index 9180dc5..4ea7d81 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -68,6 +68,7 @@ struct device_node {
> /* Pointer for first entry in chain of all nodes. */
> extern struct device_node *allnodes;
> extern struct device_node *of_chosen;
> +extern struct device_node *of_aliases;
> extern rwlock_t devtree_lock;
>
> static inline bool of_have_populated_dt(void)
> @@ -209,6 +210,9 @@ extern int of_device_is_available(const struct device_node *device);
> extern const void *of_get_property(const struct device_node *node,
> const char *name,
> int *lenp);
> +#define for_each_property(pp, properties) \
> + for (pp = properties; pp != NULL; pp = pp->next)
> +
> extern int of_n_addr_cells(struct device_node *np);
> extern int of_n_size_cells(struct device_node *np);
> extern const struct of_device_id *of_match_node(
> @@ -221,6 +225,10 @@ extern int of_parse_phandles_with_args(struct device_node *np,
> const char *list_name, const char *cells_name, int index,
> struct device_node **out_node, const void **out_args);
>
> +extern void *early_init_dt_alloc_memory_arch(u64 size, u64 align);
> +extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align));
> +extern int of_alias_get_id(struct device_node *np, const char *stem);
> +
> extern int of_machine_is_compatible(const char *compat);
>
> extern int prom_add_property(struct device_node* np, struct property* prop);
> diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
> index c84d900..b74b74f 100644
> --- a/include/linux/of_fdt.h
> +++ b/include/linux/of_fdt.h
> @@ -97,7 +97,6 @@ extern void early_init_dt_check_for_initrd(unsigned long node);
> extern int early_init_dt_scan_memory(unsigned long node, const char *uname,
> int depth, void *data);
> extern void early_init_dt_add_memory_arch(u64 base, u64 size);
> -extern void * early_init_dt_alloc_memory_arch(u64 size, u64 align);
> extern u64 dt_mem_next_cell(int s, __be32 **cellp);
>
> /*
> --
> 1.7.4.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2] dt: add of_alias_scan and of_alias_get_id
[not found] ` <1313393294-8867-1-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2011-09-19 15:18 ` Shawn Guo
@ 2011-09-21 20:35 ` Grant Likely
1 sibling, 0 replies; 15+ messages in thread
From: Grant Likely @ 2011-09-21 20:35 UTC (permalink / raw)
To: Shawn Guo
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
patches-QSEj5FYQhm4dnm+yROfE0A,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, David Miller
On Mon, Aug 15, 2011 at 03:28:14PM +0800, Shawn Guo wrote:
> The patch adds function of_alias_scan to populate a global lookup
> table with the properties of 'aliases' node and function
> of_alias_get_id for drivers to find alias id from the lookup table.
>
> Signed-off-by: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> [grant.likey: add locking and rework parse loop]
> Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
> ---
> Changes since v1:
> * Add of_chosen/of_aliases populating and of_alias_scan() invocation
> for OF_PROMTREE (non-tested).
Hi Shawn,
It's taken me a very long time to get some bandwidth to look at this
patch. I do have some minor comments, but rather than waiting for a
respin and delaying even further, I'm picking up the bits that are
are ready to go so that the remaining part (auto allocating of unused
ids) can be debated without holding things up.
>
> drivers/of/base.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++
> drivers/of/fdt.c | 12 +++--
> drivers/of/pdt.c | 12 ++++
> include/linux/of.h | 8 +++
> include/linux/of_fdt.h | 1 -
> 5 files changed, 163 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index 3ff22e3..5e6ce02 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -17,14 +17,39 @@
> * as published by the Free Software Foundation; either version
> * 2 of the License, or (at your option) any later version.
> */
> +#include <linux/ctype.h>
> #include <linux/module.h>
> #include <linux/of.h>
> #include <linux/spinlock.h>
> #include <linux/slab.h>
> #include <linux/proc_fs.h>
>
> +/**
> + * struct alias_prop - Alias property in 'aliases' node
> + * @link: List node to link the structure in aliases_lookup list
> + * @alias: Alias property name
> + * @np: Pointer to device_node that the alias stands for
> + * @id: Index value from end of alias name
> + * @stem: Alias string without the index
> + *
> + * The structure represents one alias property of 'aliases' node as
> + * an entry in aliases_lookup list.
> + */
> +struct alias_prop {
> + struct list_head link;
> + const char *alias;
> + struct device_node *np;
> + int id;
> + char stem[0];
> +};
> +
> +static LIST_HEAD(aliases_lookup);
> +
> struct device_node *allnodes;
> struct device_node *of_chosen;
> +struct device_node *of_aliases;
> +
> +static DEFINE_MUTEX(of_aliases_mutex);
>
> /* use when traversing tree through the allnext, child, sibling,
> * or parent members of struct device_node.
> @@ -988,3 +1013,114 @@ out_unlock:
> }
> #endif /* defined(CONFIG_OF_DYNAMIC) */
>
> +static void of_alias_add(struct alias_prop *ap, struct device_node *np,
> + int id, const char *stem, int stem_len)
> +{
> + ap->np = np;
> + ap->id = id;
> + strncpy(ap->stem, stem, stem_len);
> + ap->stem[stem_len] = 0;
> + list_add_tail(&ap->link, &aliases_lookup);
> + pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n",
> + ap->alias, ap->stem, ap->id, np ? np->full_name : NULL);
> +}
> +
> +/**
> + * of_alias_scan - Scan all properties of 'aliases' node
> + *
> + * The function scans all the properties of 'aliases' node and populate
> + * the the global lookup table with the properties. It returns the
> + * number of alias_prop found, or error code in error case.
> + *
> + * @dt_alloc: An allocator that provides a virtual address to memory
> + * for the resulting tree
> + */
> +void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
> +{
> + struct property *pp;
> +
> + if (!of_aliases)
> + return;
> +
> + for_each_property(pp, of_aliases->properties) {
> + const char *start = pp->name;
> + const char *end = start + strlen(start);
> + struct device_node *np;
> + struct alias_prop *ap;
> + int id, len;
> +
> + /* Skip those we do not want to proceed */
> + if (!strcmp(pp->name, "name") ||
> + !strcmp(pp->name, "phandle") ||
> + !strcmp(pp->name, "linux,phandle"))
> + continue;
> +
> + np = of_find_node_by_path(pp->value);
> + if (!np)
> + continue;
> +
> + /* walk the alias backwards to extract the id and work out
> + * the 'stem' string */
> + while (isdigit(*(end-1)) && end > start)
> + end--;
> + len = end - start;
> +
> + if (kstrtoint(end, 10, &id) < 0)
> + continue;
> +
> + /* Allocate an alias_prop with enough space for the stem */
> + ap = dt_alloc(sizeof(*ap) + len + 1, 4);
> + if (!ap)
> + continue;
> + ap->alias = start;
> + of_alias_add(ap, np, id, start, len);
> + }
> +}
> +
> +/**
> + * of_alias_get_id - Get alias id for the given device_node
> + * @np: Pointer to the given device_node
> + * @stem: Alias stem of the given device_node
> + *
> + * The function travels the lookup table to get alias id for the given
> + * device_node and alias stem. It returns the alias id if find it.
> + * If not, dynamically creates one in the lookup table and returns it,
> + * or returns error code if fail to create.
> + */
> +int of_alias_get_id(struct device_node *np, const char *stem)
> +{
> + struct alias_prop *app;
> + int id = 0;
> + bool found = false;
> +
> + mutex_lock(&of_aliases_mutex);
> + list_for_each_entry(app, &aliases_lookup, link) {
> + if (strcmp(app->stem, stem) != 0)
> + continue;
> +
> + if (np == app->np) {
> + found = true;
> + id = app->id;
> + break;
> + }
> +
> + if (id <= app->id)
> + id = app->id + 1;
> + }
> +
> + /* If an id is not found, then allocate a new one */
> + if (!found) {
> + app = kzalloc(sizeof(*app) + strlen(stem) + 1, 4);
> + if (!app) {
> + id = -ENODEV;
> + goto out;
> + }
> + of_alias_add(app, np, id, stem, strlen(stem));
> + }
This was the controversial bit last time around. I'm dropping this
block from the patch because the core aliases scanning is still
important. The allocating of new ids can be debated separately.
> +
> + out:
> + mutex_unlock(&of_aliases_mutex);
> +
> + return id;
> +}
> +EXPORT_SYMBOL_GPL(of_alias_get_id);
> diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
> index 65200af..98b6fb1 100644
> --- a/drivers/of/fdt.c
> +++ b/drivers/of/fdt.c
> @@ -404,6 +404,13 @@ static void __unflatten_device_tree(struct boot_param_header *blob,
> be32_to_cpu(((__be32 *)mem)[size / 4]));
> *allnextp = NULL;
>
> + /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
> + of_chosen = of_find_node_by_path("/chosen");
> + if (of_chosen == NULL)
> + of_chosen = of_find_node_by_path("/chosen@0");
> + of_aliases = of_find_node_by_path("/aliases");
> + of_alias_scan(dt_alloc);
> +
> pr_debug(" <- unflatten_device_tree()\n");
> }
>
> @@ -706,11 +713,6 @@ void __init unflatten_device_tree(void)
> {
> __unflatten_device_tree(initial_boot_params, &allnodes,
> early_init_dt_alloc_memory_arch);
> -
> - /* Get pointer to OF "/chosen" node for use everywhere */
> - of_chosen = of_find_node_by_path("/chosen");
> - if (of_chosen == NULL)
> - of_chosen = of_find_node_by_path("/chosen@0");
Don't move this hunk. There are callers of __unflatten_device_tree,
such as when processing device tree fragments, which do not want to
proceses /chosen or /aliases. I've moved it back to where it started
from.
> }
>
> #endif /* CONFIG_OF_EARLY_FLATTREE */
> diff --git a/drivers/of/pdt.c b/drivers/of/pdt.c
> index 4d87b5d..686a4b3 100644
> --- a/drivers/of/pdt.c
> +++ b/drivers/of/pdt.c
> @@ -229,6 +229,11 @@ static struct device_node * __init of_pdt_build_tree(struct device_node *parent,
> return ret;
> }
>
> +static void *kernel_tree_alloc(u64 size, u64 align)
> +{
> + return prom_early_alloc(size);
> +}
> +
> void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops)
> {
> struct device_node **nextp;
> @@ -245,4 +250,11 @@ void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops)
> nextp = &allnodes->allnext;
> allnodes->child = of_pdt_build_tree(allnodes,
> of_pdt_prom_ops->getchild(allnodes->phandle), &nextp);
> +
> + /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
> + of_chosen = of_find_node_by_path("/chosen");
> + if (of_chosen == NULL)
> + of_chosen = of_find_node_by_path("/chosen@0");
> + of_aliases = of_find_node_by_path("/aliases");
> + of_alias_scan(kernel_tree_alloc);
Thinking about it more, there is no need to have the
of_find_node_by_path() outside of of_alias_scan(). I've moved it. In
fact, I think I'll move the /chosen search into of_alias_scan() too.
> }
> diff --git a/include/linux/of.h b/include/linux/of.h
> index 9180dc5..4ea7d81 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -68,6 +68,7 @@ struct device_node {
> /* Pointer for first entry in chain of all nodes. */
> extern struct device_node *allnodes;
> extern struct device_node *of_chosen;
> +extern struct device_node *of_aliases;
> extern rwlock_t devtree_lock;
>
> static inline bool of_have_populated_dt(void)
> @@ -209,6 +210,9 @@ extern int of_device_is_available(const struct device_node *device);
> extern const void *of_get_property(const struct device_node *node,
> const char *name,
> int *lenp);
> +#define for_each_property(pp, properties) \
> + for (pp = properties; pp != NULL; pp = pp->next)
> +
> extern int of_n_addr_cells(struct device_node *np);
> extern int of_n_size_cells(struct device_node *np);
> extern const struct of_device_id *of_match_node(
> @@ -221,6 +225,10 @@ extern int of_parse_phandles_with_args(struct device_node *np,
> const char *list_name, const char *cells_name, int index,
> struct device_node **out_node, const void **out_args);
>
> +extern void *early_init_dt_alloc_memory_arch(u64 size, u64 align);
> +extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align));
> +extern int of_alias_get_id(struct device_node *np, const char *stem);
> +
> extern int of_machine_is_compatible(const char *compat);
>
> extern int prom_add_property(struct device_node* np, struct property* prop);
> diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
> index c84d900..b74b74f 100644
> --- a/include/linux/of_fdt.h
> +++ b/include/linux/of_fdt.h
> @@ -97,7 +97,6 @@ extern void early_init_dt_check_for_initrd(unsigned long node);
> extern int early_init_dt_scan_memory(unsigned long node, const char *uname,
> int depth, void *data);
> extern void early_init_dt_add_memory_arch(u64 base, u64 size);
> -extern void * early_init_dt_alloc_memory_arch(u64 size, u64 align);
This prototype doesn't need to move. I've moved it back.
Otherwise looks good. I'll post a v3 showing the version that I'm
merging.
g.
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH] dt: add of_alias_scan and of_alias_get_id
@ 2011-09-21 20:46 Grant Likely
2011-09-21 20:55 ` David Miller
2011-09-22 6:53 ` Shawn Guo
0 siblings, 2 replies; 15+ messages in thread
From: Grant Likely @ 2011-09-21 20:46 UTC (permalink / raw)
To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: David S. Miller
From: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
The patch adds function of_alias_scan to populate a global lookup
table with the properties of 'aliases' node and function
of_alias_get_id for drivers to find alias id from the lookup table.
v3: Split out automatic addition of aliases on id lookup so that it can be
debated separately from the core functionality.
v2: - Add of_chosen/of_aliases populating and of_alias_scan() invocation
for OF_PROMTREE.
- Add locking
- rework parse loop
Signed-off-by: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Cc: David S. Miller <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
---
David, let me know if this looks okay to you. I'm still testing this, but
if all looks good then I'll push it out for Linux next before the end of the
week. This version doesn't have the auto-creation of alias entries that
was controversial before.
g.
drivers/of/base.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++
drivers/of/fdt.c | 6 +--
drivers/of/pdt.c | 8 +++
include/linux/of.h | 7 +++
4 files changed, 138 insertions(+), 4 deletions(-)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 3ff22e3..8abde58 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -17,14 +17,39 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/ctype.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
+/**
+ * struct alias_prop - Alias property in 'aliases' node
+ * @link: List node to link the structure in aliases_lookup list
+ * @alias: Alias property name
+ * @np: Pointer to device_node that the alias stands for
+ * @id: Index value from end of alias name
+ * @stem: Alias string without the index
+ *
+ * The structure represents one alias property of 'aliases' node as
+ * an entry in aliases_lookup list.
+ */
+struct alias_prop {
+ struct list_head link;
+ const char *alias;
+ struct device_node *np;
+ int id;
+ char stem[0];
+};
+
+static LIST_HEAD(aliases_lookup);
+
struct device_node *allnodes;
struct device_node *of_chosen;
+struct device_node *of_aliases;
+
+static DEFINE_MUTEX(of_aliases_mutex);
/* use when traversing tree through the allnext, child, sibling,
* or parent members of struct device_node.
@@ -988,3 +1013,99 @@ out_unlock:
}
#endif /* defined(CONFIG_OF_DYNAMIC) */
+static void of_alias_add(struct alias_prop *ap, struct device_node *np,
+ int id, const char *stem, int stem_len)
+{
+ ap->np = np;
+ ap->id = id;
+ strncpy(ap->stem, stem, stem_len);
+ ap->stem[stem_len] = 0;
+ list_add_tail(&ap->link, &aliases_lookup);
+ pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n",
+ ap->alias, ap->stem, ap->id, np ? np->full_name : NULL);
+}
+
+/**
+ * of_alias_scan - Scan all properties of 'aliases' node
+ *
+ * The function scans all the properties of 'aliases' node and populate
+ * the the global lookup table with the properties. It returns the
+ * number of alias_prop found, or error code in error case.
+ *
+ * @dt_alloc: An allocator that provides a virtual address to memory
+ * for the resulting tree
+ */
+void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
+{
+ struct property *pp;
+
+ of_chosen = of_find_node_by_path("/chosen");
+ if (of_chosen == NULL)
+ of_chosen = of_find_node_by_path("/chosen@0");
+ of_aliases = of_find_node_by_path("/aliases");
+ if (!of_aliases)
+ return;
+
+ for_each_property(pp, of_aliases->properties) {
+ const char *start = pp->name;
+ const char *end = start + strlen(start);
+ struct device_node *np;
+ struct alias_prop *ap;
+ int id, len;
+
+ /* Skip those we do not want to proceed */
+ if (!strcmp(pp->name, "name") ||
+ !strcmp(pp->name, "phandle") ||
+ !strcmp(pp->name, "linux,phandle"))
+ continue;
+
+ np = of_find_node_by_path(pp->value);
+ if (!np)
+ continue;
+
+ /* walk the alias backwards to extract the id and work out
+ * the 'stem' string */
+ while (isdigit(*(end-1)) && end > start)
+ end--;
+ len = end - start;
+
+ if (kstrtoint(end, 10, &id) < 0)
+ continue;
+
+ /* Allocate an alias_prop with enough space for the stem */
+ ap = dt_alloc(sizeof(*ap) + len + 1, 4);
+ if (!ap)
+ continue;
+ ap->alias = start;
+ of_alias_add(ap, np, id, start, len);
+ }
+}
+
+/**
+ * of_alias_get_id - Get alias id for the given device_node
+ * @np: Pointer to the given device_node
+ * @stem: Alias stem of the given device_node
+ *
+ * The function travels the lookup table to get alias id for the given
+ * device_node and alias stem. It returns the alias id if find it.
+ */
+int of_alias_get_id(struct device_node *np, const char *stem)
+{
+ struct alias_prop *app;
+ int id = -ENODEV;
+
+ mutex_lock(&of_aliases_mutex);
+ list_for_each_entry(app, &aliases_lookup, link) {
+ if (strcmp(app->stem, stem) != 0)
+ continue;
+
+ if (np == app->np) {
+ id = app->id;
+ break;
+ }
+ }
+ mutex_unlock(&of_aliases_mutex);
+
+ return id;
+}
+EXPORT_SYMBOL_GPL(of_alias_get_id);
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 65200af..aeec35b 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -707,10 +707,8 @@ void __init unflatten_device_tree(void)
__unflatten_device_tree(initial_boot_params, &allnodes,
early_init_dt_alloc_memory_arch);
- /* Get pointer to OF "/chosen" node for use everywhere */
- of_chosen = of_find_node_by_path("/chosen");
- if (of_chosen == NULL)
- of_chosen = of_find_node_by_path("/chosen@0");
+ /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
+ of_alias_scan(early_init_dt_alloc_memory_arch);
}
#endif /* CONFIG_OF_EARLY_FLATTREE */
diff --git a/drivers/of/pdt.c b/drivers/of/pdt.c
index 4d87b5d..bc5b399 100644
--- a/drivers/of/pdt.c
+++ b/drivers/of/pdt.c
@@ -229,6 +229,11 @@ static struct device_node * __init of_pdt_build_tree(struct device_node *parent,
return ret;
}
+static void *kernel_tree_alloc(u64 size, u64 align)
+{
+ return prom_early_alloc(size);
+}
+
void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops)
{
struct device_node **nextp;
@@ -245,4 +250,7 @@ void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops)
nextp = &allnodes->allnext;
allnodes->child = of_pdt_build_tree(allnodes,
of_pdt_prom_ops->getchild(allnodes->phandle), &nextp);
+
+ /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
+ of_alias_scan(kernel_tree_alloc);
}
diff --git a/include/linux/of.h b/include/linux/of.h
index 9180dc5..8b6383d 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -68,6 +68,7 @@ struct device_node {
/* Pointer for first entry in chain of all nodes. */
extern struct device_node *allnodes;
extern struct device_node *of_chosen;
+extern struct device_node *of_aliases;
extern rwlock_t devtree_lock;
static inline bool of_have_populated_dt(void)
@@ -209,6 +210,9 @@ extern int of_device_is_available(const struct device_node *device);
extern const void *of_get_property(const struct device_node *node,
const char *name,
int *lenp);
+#define for_each_property(pp, properties) \
+ for (pp = properties; pp != NULL; pp = pp->next)
+
extern int of_n_addr_cells(struct device_node *np);
extern int of_n_size_cells(struct device_node *np);
extern const struct of_device_id *of_match_node(
@@ -221,6 +225,9 @@ extern int of_parse_phandles_with_args(struct device_node *np,
const char *list_name, const char *cells_name, int index,
struct device_node **out_node, const void **out_args);
+extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align));
+extern int of_alias_get_id(struct device_node *np, const char *stem);
+
extern int of_machine_is_compatible(const char *compat);
extern int prom_add_property(struct device_node* np, struct property* prop);
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH] dt: add of_alias_scan and of_alias_get_id
2011-09-21 20:46 [PATCH] " Grant Likely
@ 2011-09-21 20:55 ` David Miller
2011-09-22 6:53 ` Shawn Guo
1 sibling, 0 replies; 15+ messages in thread
From: David Miller @ 2011-09-21 20:55 UTC (permalink / raw)
To: grant.likely-s3s/WqlpOiPyB63q8FvJNQ
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
From: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
Date: Wed, 21 Sep 2011 14:46:54 -0600
> From: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>
> The patch adds function of_alias_scan to populate a global lookup
> table with the properties of 'aliases' node and function
> of_alias_get_id for drivers to find alias id from the lookup table.
>
> v3: Split out automatic addition of aliases on id lookup so that it can be
> debated separately from the core functionality.
> v2: - Add of_chosen/of_aliases populating and of_alias_scan() invocation
> for OF_PROMTREE.
> - Add locking
> - rework parse loop
>
> Signed-off-by: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> Cc: David S. Miller <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
> Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
Looks good:
Acked-by: David S. Miller <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] dt: add of_alias_scan and of_alias_get_id
2011-09-21 20:46 [PATCH] " Grant Likely
2011-09-21 20:55 ` David Miller
@ 2011-09-22 6:53 ` Shawn Guo
2011-09-22 17:06 ` Grant Likely
1 sibling, 1 reply; 15+ messages in thread
From: Shawn Guo @ 2011-09-22 6:53 UTC (permalink / raw)
To: Grant Likely
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, David S. Miller
On Wed, Sep 21, 2011 at 02:46:54PM -0600, Grant Likely wrote:
> From: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>
> The patch adds function of_alias_scan to populate a global lookup
> table with the properties of 'aliases' node and function
> of_alias_get_id for drivers to find alias id from the lookup table.
>
> v3: Split out automatic addition of aliases on id lookup so that it can be
> debated separately from the core functionality.
> v2: - Add of_chosen/of_aliases populating and of_alias_scan() invocation
> for OF_PROMTREE.
> - Add locking
> - rework parse loop
>
> Signed-off-by: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> Cc: David S. Miller <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
> Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
On imx serial driver:
Tested-by: Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Hi Grant,
I just posted a patch to have of_alias_get_id() back for imx serial
driver with replying to this one. Can you please merge it to through
your tree as well?
--
Regards,
Shawn
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] dt: add of_alias_scan and of_alias_get_id
2011-09-22 6:53 ` Shawn Guo
@ 2011-09-22 17:06 ` Grant Likely
0 siblings, 0 replies; 15+ messages in thread
From: Grant Likely @ 2011-09-22 17:06 UTC (permalink / raw)
To: Shawn Guo; +Cc: devicetree-discuss, linux-kernel, Shawn Guo, David S. Miller
On Thu, Sep 22, 2011 at 02:53:08PM +0800, Shawn Guo wrote:
> On Wed, Sep 21, 2011 at 02:46:54PM -0600, Grant Likely wrote:
> > From: Shawn Guo <shawn.guo@linaro.org>
> >
> > The patch adds function of_alias_scan to populate a global lookup
> > table with the properties of 'aliases' node and function
> > of_alias_get_id for drivers to find alias id from the lookup table.
> >
> > v3: Split out automatic addition of aliases on id lookup so that it can be
> > debated separately from the core functionality.
> > v2: - Add of_chosen/of_aliases populating and of_alias_scan() invocation
> > for OF_PROMTREE.
> > - Add locking
> > - rework parse loop
> >
> > Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> > Cc: David S. Miller <davem@davemloft.net>
> > Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
>
> On imx serial driver:
>
> Tested-by: Shawn Guo <shawn.guo@linaro.org>
>
> Hi Grant,
>
> I just posted a patch to have of_alias_get_id() back for imx serial
> driver with replying to this one. Can you please merge it to through
> your tree as well?
No problem.
g.
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2011-09-22 17:06 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-08-15 1:30 [PATCH] dt: add of_alias_scan and of_alias_get_id Shawn Guo
[not found] ` <1313371817-5135-1-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2011-08-15 5:43 ` David Miller
2011-08-15 6:07 ` Shawn Guo
[not found] ` <20110815060708.GH7244-+NayF8gZjK2ctlrPMvKcciBecyulp+rMXqFh9Ls21Oc@public.gmane.org>
2011-08-15 6:05 ` David Miller
[not found] ` <20110814.230529.611834234177280886.davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
2011-08-15 6:36 ` Shawn Guo
[not found] ` <20110815063643.GI7244-+NayF8gZjK2ctlrPMvKcciBecyulp+rMXqFh9Ls21Oc@public.gmane.org>
2011-08-15 6:35 ` David Miller
2011-08-15 6:47 ` Shawn Guo
2011-08-15 6:45 ` Shawn Guo
2011-08-15 7:28 ` [PATCH v2] " Shawn Guo
[not found] ` <1313393294-8867-1-git-send-email-shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2011-09-19 15:18 ` Shawn Guo
2011-09-21 20:35 ` Grant Likely
-- strict thread matches above, loose matches on Subject: below --
2011-09-21 20:46 [PATCH] " Grant Likely
2011-09-21 20:55 ` David Miller
2011-09-22 6:53 ` Shawn Guo
2011-09-22 17:06 ` 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).