of: no longer call prom_ functions directly; use an ops structure
Subsystems (2)
PATCH 2/7 of: no longer call prom_ functions directly; use an ops structure
Rather than assuming an architecture defines prom_getchild and friends, define an ops struct with hooks for the various prom functions that pdt.c needs. This ops struct is filled in by the
arch-(and sometimes firmware-)specific code, and passed to of_pdt_build_devicetree.
Update sparc code to define the ops struct as well.
Signed-off-by Andres Salomon <[email protected]>
--- arch/sparc/kernel/prom_common.c | 36 ++++++++++++++++++++++++++++++++++- drivers/of/pdt.c | 40 +++++++++++++++++--------------------- include/linux/of_pdt.h | 20 ++++++++++++++++++- 3 files changed, 72 insertions(+), 24 deletions(-)
arch/sparc/kernel/prom_common.c +35 -1
@@ -118,11 +118,45 @@ int of_find_in_proplist(const char *list, const char *match, int len) }EXPORT_SYMBOL (of_find_in_proplist); +/* +* SPARC32 and SPARC64's prom_nextprop() do things differently +* here, despite sharing the same interface. SPARC32 doesn't fill in 'buf', +* returning NULL on an error. SPARC64 fills in 'buf', but sets it to an +* empty string upon error. +*/ +static int __init handle_nextprop_quirks (char *buf,const char *name) +{ +if (!name ||strlen (name) ==0 ) +return -1 ; + +#ifdef CONFIG_SPARC32 +strcpy (buf, name); +#endif +return 0 ; +} + +static int __init prom_common_nextprop (phandle node,char *prev,char *buf) +{ +const char *name; + + buf[0 ] ='\0' ; + name =prom_nextprop (node, prev, buf); +return handle_nextprop_quirks (buf, name); +} +unsigned int prom_early_allocated__initdata ; +static struct of_pdt_ops prom_sparc_ops__initdata = { + .nextprop = prom_common_nextprop, + .getproplen = prom_getproplen, + .getproperty = prom_getproperty, + .getchild = prom_getchild, + .getsibling = prom_getsibling, +}; +void __init prom_build_devicetree (void ) { -of_pdt_build_devicetree (prom_root_node); +of_pdt_build_devicetree (prom_root_node, &prom_sparc_ops);of_console_init (); pr_info("PROM: Built device tree with %u bytes of memory.\n",
drivers/of/pdt.c +18 -22
@@ -23,7 +23,8 @@#include <linux/of.h> #include <linux/of_pdt.h> #include <asm/prom.h> -#include <asm/oplib.h> + +static struct of_pdt_ops *of_pdt_prom_ops__initdata ;void __initdata (*prom_build_more)(struct device_node *dp,struct device_node ***nextp);
@@ -59,7 +60,7 @@ static struct property * __init build_one_prop(phandle node, char *prev, {static struct property *tmp =NULL ;struct property *p; -const char *name; +int err;if (tmp) { p = tmp;
@@ -77,28 +78,20 @@ static struct property * __init build_one_prop(phandle node, char *prev, p->value =prom_early_alloc (special_len);memcpy (p->value, special_val, special_len); }else { -if (prev ==NULL ) { - name =prom_firstprop (node, p->name); - }else { - name =prom_nextprop (node, prev, p->name); - } - -if (!name ||strlen (name) ==0 ) { + err = of_pdt_prom_ops->nextprop (node, prev, p->name); +if (err) { tmp = p;return NULL ; } -#ifdef CONFIG_SPARC32 -strcpy (p->name, name); -#endif - p->length =prom_getproplen (node, p->name); + p->length = of_pdt_prom_ops->getproplen (node, p->name);if (p->length <=0 ) { p->length =0 ; }else {int len; p->value =prom_early_alloc (p->length +1 ); - len =prom_getproperty (node, p->name, p->value, - p->length); + len = of_pdt_prom_ops->getproperty (node, p->name, + p->value, p->length);if (len <=0 ) p->length =0 ; ((unsigned char *)p->value)[p->length] ='\0' ;
@@ -130,10 +123,10 @@ static char * __init get_one_property(phandle node, const char *name)char *buf ="<NULL>" ;int len; - len =prom_getproplen (node, name); + len = of_pdt_prom_ops->getproplen (node, name);if (len >0 ) { buf =prom_early_alloc (len); - len =prom_getproperty (node, name, buf, len); + len = of_pdt_prom_ops->getproperty (node, name, buf, len); }return buf;
@@ -211,21 +204,25 @@ static struct device_node * __init prom_build_tree(struct device_node *parent,#endif dp->full_name =build_full_name (dp); - dp->child =prom_build_tree (dp,prom_getchild (node), nextp); + dp->child =prom_build_tree (dp, + of_pdt_prom_ops->getchild (node), nextp);if (prom_build_more)prom_build_more (dp, nextp); - node =prom_getsibling (node); + node = of_pdt_prom_ops->getsibling (node); }return ret; } -void __init of_pdt_build_devicetree (phandle root_node) +void __init of_pdt_build_devicetree (phandle root_node,struct of_pdt_ops *ops) {struct device_node **nextp; +BUG_ON (!ops); + of_pdt_prom_ops = ops; + allnodes =prom_create_node (root_node,NULL );#if defined(CONFIG_SPARC ) allnodes->path_component_name ="" ;
@@ -234,6 +231,5 @@ void __init of_pdt_build_devicetree(phandle root_node) nextp = &allnodes->allnext; allnodes->child =prom_build_tree (allnodes, -prom_getchild (allnodes->phandle), - &nextp); + of_pdt_prom_ops->getchild (allnodes->phandle), &nextp); }
include/linux/of_pdt.h +19 -1
@@ -13,10 +13,28 @@#ifndef _LINUX_OF_PDT_H#define _LINUX_OF_PDT_H +/* overridable operations for calling into the PROM */ +struct of_pdt_ops { +/* +* buf should be 32 bytes; return 0 on success. +* If prev is NULL, the first property will be returned. +*/ +int (*nextprop)(phandle node,char *prev,char *buf); + +/* for both functions, return proplen on success; -1 on error */ +int (*getproplen)(phandle node,const char *prop); +int (*getproperty)(phandle node,const char *prop,char *buf, +int bufsize); + +/* phandles are 0 if no child or sibling exists */ +phandle (*getchild)(phandle parent); +phandle (*getsibling)(phandle node); +}; +extern void *prom_early_alloc (unsigned long size);/* for building the device tree */ -extern void of_pdt_build_devicetree (phandle root_node); +extern void of_pdt_build_devicetree (phandle root_node,struct of_pdt_ops *ops);extern void (*prom_build_more)(struct device_node *dp,struct device_node ***nextp);
Signature · 1 line
1.5.6.5
Grant Likely
AppliedQuoted 10 lines · Andres Salomon
Rather than assuming an architecture defines
prom_getchildand friends, define an ops struct with hooks for the various prom functions thatpdt.cneeds. This ops struct is filled in by the
arch-(and sometimes firmware-)specific code, and passed toof_pdt_build_devicetree.Update sparc code to define the ops struct as well.
Signed-off-by Andres Salomon <[email protected]>
Applied, thanks.
g.
Quoted 201 lines
--- arch/sparc/kernel/prom_common.c | 36 ++++++++++++++++++++++++++++++++++- drivers/of/pdt.c | 40 +++++++++++++++++--------------------- include/linux/of_pdt.h | 20 ++++++++++++++++++- 3 files changed, 72 insertions(+), 24 deletions(-)arch/sparc/kernel/prom_common.c +35
-1@@ -118,11 +118,45 @@ int of_find_in_proplist(const char *list, const char *match, int len) }EXPORT_SYMBOL (of_find_in_proplist); +/* +* SPARC32 and SPARC64's prom_nextprop() do things differently +* here, despite sharing the same interface. SPARC32 doesn't fill in 'buf', +* returning NULL on an error. SPARC64 fills in 'buf', but sets it to an +* empty string upon error. +*/ +static int __init handle_nextprop_quirks (char *buf,const char *name) +{ +if (!name ||strlen (name) ==0 ) +return -1 ; + +#ifdef CONFIG_SPARC32 +strcpy (buf, name); +#endif +return 0 ; +} + +static int __init prom_common_nextprop (phandle node,char *prev,char *buf) +{ +const char *name; + + buf[0 ] ='\0' ; + name =prom_nextprop (node, prev, buf); +return handle_nextprop_quirks (buf, name); +} +unsigned int prom_early_allocated__initdata ; +static struct of_pdt_ops prom_sparc_ops__initdata = { + .nextprop = prom_common_nextprop, + .getproplen = prom_getproplen, + .getproperty = prom_getproperty, + .getchild = prom_getchild, + .getsibling = prom_getsibling, +}; +void __init prom_build_devicetree (void ) { -of_pdt_build_devicetree (prom_root_node); +of_pdt_build_devicetree (prom_root_node, &prom_sparc_ops);of_console_init (); pr_info("PROM: Built device tree with %u bytes of memory.\n",drivers/of/pdt.c +18
-22@@ -23,7 +23,8 @@#include <linux/of.h> #include <linux/of_pdt.h> #include <asm/prom.h> -#include <asm/oplib.h> + +static struct of_pdt_ops *of_pdt_prom_ops__initdata ;void __initdata (*prom_build_more)(struct device_node *dp,struct device_node ***nextp);@@ -59,7 +60,7 @@ static struct property * __init build_one_prop(phandle node, char *prev, {static struct property *tmp =NULL ;struct property *p; -const char *name; +int err;if (tmp) { p = tmp;@@ -77,28 +78,20 @@ static struct property * __init build_one_prop(phandle node, char *prev, p->value =prom_early_alloc (special_len);memcpy (p->value, special_val, special_len); }else { -if (prev ==NULL ) { - name =prom_firstprop (node, p->name); - }else { - name =prom_nextprop (node, prev, p->name); - } - -if (!name ||strlen (name) ==0 ) { + err = of_pdt_prom_ops->nextprop (node, prev, p->name); +if (err) { tmp = p;return NULL ; } -#ifdef CONFIG_SPARC32 -strcpy (p->name, name); -#endif - p->length =prom_getproplen (node, p->name); + p->length = of_pdt_prom_ops->getproplen (node, p->name);if (p->length <=0 ) { p->length =0 ; }else {int len; p->value =prom_early_alloc (p->length +1 ); - len =prom_getproperty (node, p->name, p->value, - p->length); + len = of_pdt_prom_ops->getproperty (node, p->name, + p->value, p->length);if (len <=0 ) p->length =0 ; ((unsigned char *)p->value)[p->length] ='\0' ;@@ -130,10 +123,10 @@ static char * __init get_one_property(phandle node, const char *name)char *buf ="<NULL>" ;int len; - len =prom_getproplen (node, name); + len = of_pdt_prom_ops->getproplen (node, name);if (len >0 ) { buf =prom_early_alloc (len); - len =prom_getproperty (node, name, buf, len); + len = of_pdt_prom_ops->getproperty (node, name, buf, len); }return buf;@@ -211,21 +204,25 @@ static struct device_node * __init prom_build_tree(struct device_node *parent,#endif dp->full_name =build_full_name (dp); - dp->child =prom_build_tree (dp,prom_getchild (node), nextp); + dp->child =prom_build_tree (dp, + of_pdt_prom_ops->getchild (node), nextp);if (prom_build_more)prom_build_more (dp, nextp); - node =prom_getsibling (node); + node = of_pdt_prom_ops->getsibling (node); }return ret; } -void __init of_pdt_build_devicetree (phandle root_node) +void __init of_pdt_build_devicetree (phandle root_node,struct of_pdt_ops *ops) {struct device_node **nextp; +BUG_ON (!ops); + of_pdt_prom_ops = ops; + allnodes =prom_create_node (root_node,NULL );#if defined(CONFIG_SPARC ) allnodes->path_component_name ="" ;@@ -234,6 +231,5 @@ void __init of_pdt_build_devicetree(phandle root_node) nextp = &allnodes->allnext; allnodes->child =prom_build_tree (allnodes, -prom_getchild (allnodes->phandle), - &nextp); + of_pdt_prom_ops->getchild (allnodes->phandle), &nextp); }include/linux/of_pdt.h +19
-1@@ -13,10 +13,28 @@#ifndef _LINUX_OF_PDT_H#define _LINUX_OF_PDT_H +/* overridable operations for calling into the PROM */ +struct of_pdt_ops { +/* +* buf should be 32 bytes; return 0 on success. +* If prev is NULL, the first property will be returned. +*/ +int (*nextprop)(phandle node,char *prev,char *buf); + +/* for both functions, return proplen on success; -1 on error */ +int (*getproplen)(phandle node,const char *prop); +int (*getproperty)(phandle node,const char *prop,char *buf, +int bufsize); + +/* phandles are 0 if no child or sibling exists */ +phandle (*getchild)(phandle parent); +phandle (*getsibling)(phandle node); +}; +extern void *prom_early_alloc (unsigned long size);/* for building the device tree */ -extern void of_pdt_build_devicetree (phandle root_node); +extern void of_pdt_build_devicetree (phandle root_node,struct of_pdt_ops *ops);extern void (*prom_build_more)(struct device_node *dp,struct device_node ***nextp);Signature · 1 line
1.5.6.5