Skip to contentSkip to conversation

dt: add of_alias_scan and of_alias_get_id

PATCH In review Grant Likely 4 participants 6 messages Sep 21, 2011 – Sep 22, 2011

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 dt: add of_alias_scan and of_alias_get_id

From: Shawn Guo <[email protected]>

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

Cc David S. Miller <davem-fT/PcQaiUtIeIZ0/[email protected]>

---

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(-)
drivers/of/base.c +121 -0
index 3ff22e3..8abde58 100644
@@ -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);
drivers/of/fdt.c +2 -4
index 65200af..aeec35b 100644
@@ -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 */
drivers/of/pdt.c +8 -0
index 4d87b5d..bc5b399 100644
@@ -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);
 }
include/linux/of.h +7 -0
index 9180dc5..8b6383d 100644
@@ -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);
Acked-by on v1 1/1
#1 lore raw

From: Grant Likely <grant.likely-s3s/[email protected]>
Date: Wed, 21 Sep 2011 14:46:54 -0600

Quoted 13 lines

From: Shawn Guo <[email protected]>

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

Quoted 3 lines
Cc David S. Miller <davem-fT/PcQaiUtIeIZ0/[email protected]>

Looks good:

#2 lore raw

PATCH 1/1 serial/imx: add of_alias_get_id() reference back

In reply to Grant Likely

As of_alias_get_id() gets fixed and ready for use, the patch adds the of_alias_get_id() reference back to imx serial driver.

---
 drivers/tty/serial/imx.c |   13 +++++++++----
 1 files changed, 9 insertions(+), 4 deletions(-)
drivers/tty/serial/imx.c +9 -4
index 4a36470..b550cff 100644
@@ -1318,17 +1318,22 @@ static int serial_imx_resume(struct platform_device *dev)
 static int serial_imx_probe_dt(struct imx_port *sport,
 		struct platform_device *pdev)
 {
-	static int portnum = 0;
 	struct device_node *np = pdev->dev.of_node;
 	const struct of_device_id *of_id =
 			of_match_device(imx_uart_dt_ids, &pdev->dev);
+	int ret;
 
 	if (!np)
 		return -ENODEV;
 
-	sport->port.line = portnum++;
-	if (sport->port.line >= UART_NR)
-		return -EINVAL;
+	ret = of_alias_get_id(np, "serial");
+	if (ret < 0) {
+		pr_err("%s: failed to get alias id, errno %d\n",
+			__func__, ret);
+		return -ENODEV;
+	} else {
+		sport->port.line = ret;
+	}
 
 	if (of_get_property(np, "fsl,uart-has-rtscts", NULL))
 		sport->have_rtscts = 1;
Signature · 1 line
1.7.4.1
author Applied
#3 lore raw

Re: [PATCH] serial/imx: add of_alias_get_id() reference back

Quoted 22 lines · Shawn Guo

As of_alias_get_id() gets fixed and ready for use, the patch adds the of_alias_get_id() reference back to imx serial driver.

---
 drivers/tty/serial/imx.c |   13 +++++++++----
 1 files changed, 9 insertions(+), 4 deletions(-)
drivers/tty/serial/imx.c +1 -1
index 4a36470..b550cff 100644
@@ -1318,17 +1318,22 @@ static int serial_imx_resume(struct platform_device *dev)
 static int serial_imx_probe_dt(struct imx_port *sport,
 		struct platform_device *pdev)
 {
-	static int portnum = 0;
 	struct device_node *np = pdev->dev.of_node;
 	const struct of_device_id *of_id =
 			of_match_device(imx_uart_dt_ids, &pdev->dev);
+	int ret;
 

drivers/tty/serial/imx.c static int serial_imx_resume(struct platform_device *dev) · line 1332

Quoted 10 lines
drivers/tty/serial/imx.c +4 -3
 	if (!np)
 		return -ENODEV;
 
-	sport->port.line = portnum++;
-	if (sport->port.line >= UART_NR)
-		return -EINVAL;
+	ret = of_alias_get_id(np, "serial");
+	if (ret < 0) {
+		pr_err("%s: failed to get alias id, errno %d\n",
+			__func__, ret);

Should really be using dev_err();

drivers/tty/serial/imx.c static int serial_imx_resume(struct platform_device *dev) · line 1336

Quoted 4 lines
drivers/tty/serial/imx.c +4 -0
+		return -ENODEV;
+	} else {
+		sport->port.line = ret;
+	}

The 'else' is unnecessary. I've removed it.

Merged, thanks.

g.

Quoted 7 lines
drivers/tty/serial/imx.c +0 -0
 	if (of_get_property(np, "fsl,uart-has-rtscts", NULL))
 		sport->have_rtscts = 1;
Signature · 1 line
1.7.4.1
Tested-by on v1 1/1
#4 lore raw
In reply to Grant Likely
Quoted 13 lines · Grant Likely

From: Shawn Guo <[email protected]>

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

Quoted 3 lines

On imx serial driver:

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?

Signature · 2 lines
Regards,
Shawn
#5 lore raw
Quoted 20 lines · Shawn Guo
Quoted 13 lines · Grant Likely

From: Shawn Guo <[email protected]>

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

Quoted 3 lines

On imx serial driver:

Quoted 7 lines

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.