Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f90c34bd authored by Andres Salomon's avatar Andres Salomon Committed by Grant Likely
Browse files

of/promtree: 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: default avatarAndres Salomon <dilinger@queued.net>
Acked-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarGrant Likely <grant.likely@secretlab.ca>
parent 3cfc535c
Loading
Loading
Loading
Loading
+35 −1
Original line number Original line Diff line number Diff line
@@ -118,11 +118,45 @@ int of_find_in_proplist(const char *list, const char *match, int len)
}
}
EXPORT_SYMBOL(of_find_in_proplist);
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;
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)
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();
	of_console_init();


	pr_info("PROM: Built device tree with %u bytes of memory.\n",
	pr_info("PROM: Built device tree with %u bytes of memory.\n",
+18 −22
Original line number Original line Diff line number Diff line
@@ -23,7 +23,8 @@
#include <linux/of.h>
#include <linux/of.h>
#include <linux/of_pdt.h>
#include <linux/of_pdt.h>
#include <asm/prom.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,
void __initdata (*prom_build_more)(struct device_node *dp,
		struct device_node ***nextp);
		struct device_node ***nextp);
@@ -59,7 +60,7 @@ static struct property * __init build_one_prop(phandle node, char *prev,
{
{
	static struct property *tmp = NULL;
	static struct property *tmp = NULL;
	struct property *p;
	struct property *p;
	const char *name;
	int err;


	if (tmp) {
	if (tmp) {
		p = 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);
		p->value = prom_early_alloc(special_len);
		memcpy(p->value, special_val, special_len);
		memcpy(p->value, special_val, special_len);
	} else {
	} else {
		if (prev == NULL) {
		err = of_pdt_prom_ops->nextprop(node, prev, p->name);
			name = prom_firstprop(node, p->name);
		if (err) {
		} else {
			name = prom_nextprop(node, prev, p->name);
		}

		if (!name || strlen(name) == 0) {
			tmp = p;
			tmp = p;
			return NULL;
			return NULL;
		}
		}
#ifdef CONFIG_SPARC32
		p->length = of_pdt_prom_ops->getproplen(node, p->name);
		strcpy(p->name, name);
#endif
		p->length = prom_getproplen(node, p->name);
		if (p->length <= 0) {
		if (p->length <= 0) {
			p->length = 0;
			p->length = 0;
		} else {
		} else {
			int len;
			int len;


			p->value = prom_early_alloc(p->length + 1);
			p->value = prom_early_alloc(p->length + 1);
			len = prom_getproperty(node, p->name, p->value,
			len = of_pdt_prom_ops->getproperty(node, p->name,
					       p->length);
					p->value, p->length);
			if (len <= 0)
			if (len <= 0)
				p->length = 0;
				p->length = 0;
			((unsigned char *)p->value)[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>";
	char *buf = "<NULL>";
	int len;
	int len;


	len = prom_getproplen(node, name);
	len = of_pdt_prom_ops->getproplen(node, name);
	if (len > 0) {
	if (len > 0) {
		buf = prom_early_alloc(len);
		buf = prom_early_alloc(len);
		len = prom_getproperty(node, name, buf, len);
		len = of_pdt_prom_ops->getproperty(node, name, buf, len);
	}
	}


	return buf;
	return buf;
@@ -211,21 +204,25 @@ static struct device_node * __init prom_build_tree(struct device_node *parent,
#endif
#endif
		dp->full_name = build_full_name(dp);
		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)
		if (prom_build_more)
			prom_build_more(dp, nextp);
			prom_build_more(dp, nextp);


		node = prom_getsibling(node);
		node = of_pdt_prom_ops->getsibling(node);
	}
	}


	return ret;
	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;
	struct device_node **nextp;


	BUG_ON(!ops);
	of_pdt_prom_ops = ops;

	allnodes = prom_create_node(root_node, NULL);
	allnodes = prom_create_node(root_node, NULL);
#if defined(CONFIG_SPARC)
#if defined(CONFIG_SPARC)
	allnodes->path_component_name = "";
	allnodes->path_component_name = "";
@@ -234,6 +231,5 @@ void __init of_pdt_build_devicetree(phandle root_node)


	nextp = &allnodes->allnext;
	nextp = &allnodes->allnext;
	allnodes->child = prom_build_tree(allnodes,
	allnodes->child = prom_build_tree(allnodes,
					  prom_getchild(allnodes->phandle),
			of_pdt_prom_ops->getchild(allnodes->phandle), &nextp);
					  &nextp);
}
}
+19 −1
Original line number Original line Diff line number Diff line
@@ -13,10 +13,28 @@
#ifndef _LINUX_OF_PDT_H
#ifndef _LINUX_OF_PDT_H
#define _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);
extern void *prom_early_alloc(unsigned long size);


/* for building the device tree */
/* 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,
extern void (*prom_build_more)(struct device_node *dp,
		struct device_node ***nextp);
		struct device_node ***nextp);