diff options
Diffstat (limited to 'drivers/of/pdt.c')
| -rw-r--r-- | drivers/of/pdt.c | 136 | 
1 files changed, 57 insertions, 79 deletions
diff --git a/drivers/of/pdt.c b/drivers/of/pdt.c index 28295d0a50f..36b4035881b 100644 --- a/drivers/of/pdt.c +++ b/drivers/of/pdt.c @@ -22,7 +22,6 @@  #include <linux/slab.h>  #include <linux/of.h>  #include <linux/of_pdt.h> -#include <asm/prom.h>  static struct of_pdt_ops *of_pdt_prom_ops __initdata; @@ -36,19 +35,55 @@ unsigned int of_pdt_unique_id __initdata;  	(p)->unique_id = of_pdt_unique_id++; \  } while (0) -static inline const char *of_pdt_node_name(struct device_node *dp) +static char * __init of_pdt_build_full_name(struct device_node *dp)  { -	return dp->path_component_name; +	int len, ourlen, plen; +	char *n; + +	dp->path_component_name = build_path_component(dp); + +	plen = strlen(dp->parent->full_name); +	ourlen = strlen(dp->path_component_name); +	len = ourlen + plen + 2; + +	n = prom_early_alloc(len); +	strcpy(n, dp->parent->full_name); +	if (!of_node_is_root(dp->parent)) { +		strcpy(n + plen, "/"); +		plen++; +	} +	strcpy(n + plen, dp->path_component_name); + +	return n;  } -#else +#else /* CONFIG_SPARC */  static inline void of_pdt_incr_unique_id(void *p) { }  static inline void irq_trans_init(struct device_node *dp) { } -static inline const char *of_pdt_node_name(struct device_node *dp) +static char * __init of_pdt_build_full_name(struct device_node *dp)  { -	return dp->name; +	static int failsafe_id = 0; /* for generating unique names on failure */ +	char *buf; +	int len; + +	if (of_pdt_prom_ops->pkg2path(dp->phandle, NULL, 0, &len)) +		goto failsafe; + +	buf = prom_early_alloc(len + 1); +	if (of_pdt_prom_ops->pkg2path(dp->phandle, buf, len, &len)) +		goto failsafe; +	return buf; + + failsafe: +	buf = prom_early_alloc(strlen(dp->parent->full_name) + +			       strlen(dp->name) + 16); +	sprintf(buf, "%s/%s@unknown%i", +		of_node_is_root(dp->parent) ? "" : dp->parent->full_name, +		dp->name, failsafe_id++); +	pr_err("%s: pkg2path failed; assigning %s\n", __func__, buf); +	return buf;  }  #endif /* !CONFIG_SPARC */ @@ -132,47 +167,6 @@ static char * __init of_pdt_get_one_property(phandle node, const char *name)  	return buf;  } -static char * __init of_pdt_try_pkg2path(phandle node) -{ -	char *res, *buf = NULL; -	int len; - -	if (!of_pdt_prom_ops->pkg2path) -		return NULL; - -	if (of_pdt_prom_ops->pkg2path(node, buf, 0, &len)) -		return NULL; -	buf = prom_early_alloc(len + 1); -	if (of_pdt_prom_ops->pkg2path(node, buf, len, &len)) { -		pr_err("%s: package-to-path failed\n", __func__); -		return NULL; -	} - -	res = strrchr(buf, '/'); -	if (!res) { -		pr_err("%s: couldn't find / in %s\n", __func__, buf); -		return NULL; -	} -	return res+1; -} - -/* - * When fetching the node's name, first try using package-to-path; if - * that fails (either because the arch hasn't supplied a PROM callback, - * or some other random failure), fall back to just looking at the node's - * 'name' property. - */ -static char * __init of_pdt_build_name(phandle node) -{ -	char *buf; - -	buf = of_pdt_try_pkg2path(node); -	if (!buf) -		buf = of_pdt_get_one_property(node, "name"); - -	return buf; -} -  static struct device_node * __init of_pdt_create_node(phandle node,  						    struct device_node *parent)  { @@ -182,12 +176,11 @@ static struct device_node * __init of_pdt_create_node(phandle node,  		return NULL;  	dp = prom_early_alloc(sizeof(*dp)); +	of_node_init(dp);  	of_pdt_incr_unique_id(dp);  	dp->parent = parent; -	kref_init(&dp->kref); - -	dp->name = of_pdt_build_name(node); +	dp->name = of_pdt_get_one_property(node, "name");  	dp->type = of_pdt_get_one_property(node, "device_type");  	dp->phandle = node; @@ -198,26 +191,6 @@ static struct device_node * __init of_pdt_create_node(phandle node,  	return dp;  } -static char * __init of_pdt_build_full_name(struct device_node *dp) -{ -	int len, ourlen, plen; -	char *n; - -	plen = strlen(dp->parent->full_name); -	ourlen = strlen(of_pdt_node_name(dp)); -	len = ourlen + plen + 2; - -	n = prom_early_alloc(len); -	strcpy(n, dp->parent->full_name); -	if (!of_node_is_root(dp->parent)) { -		strcpy(n + plen, "/"); -		plen++; -	} -	strcpy(n + plen, of_pdt_node_name(dp)); - -	return n; -} -  static struct device_node * __init of_pdt_build_tree(struct device_node *parent,  						   phandle node,  						   struct device_node ***nextp) @@ -240,9 +213,6 @@ static struct device_node * __init of_pdt_build_tree(struct device_node *parent,  		*(*nextp) = dp;  		*nextp = &dp->allnext; -#if defined(CONFIG_SPARC) -		dp->path_component_name = build_path_component(dp); -#endif  		dp->full_name = of_pdt_build_full_name(dp);  		dp->child = of_pdt_build_tree(dp, @@ -257,6 +227,11 @@ static struct device_node * __init of_pdt_build_tree(struct device_node *parent,  	return ret;  } +static void * __init 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; @@ -264,13 +239,16 @@ void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops)  	BUG_ON(!ops);  	of_pdt_prom_ops = ops; -	allnodes = of_pdt_create_node(root_node, NULL); +	of_allnodes = of_pdt_create_node(root_node, NULL);  #if defined(CONFIG_SPARC) -	allnodes->path_component_name = ""; +	of_allnodes->path_component_name = "";  #endif -	allnodes->full_name = "/"; +	of_allnodes->full_name = "/"; + +	nextp = &of_allnodes->allnext; +	of_allnodes->child = of_pdt_build_tree(of_allnodes, +			of_pdt_prom_ops->getchild(of_allnodes->phandle), &nextp); -	nextp = &allnodes->allnext; -	allnodes->child = of_pdt_build_tree(allnodes, -			of_pdt_prom_ops->getchild(allnodes->phandle), &nextp); +	/* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */ +	of_alias_scan(kernel_tree_alloc);  }  | 
