summaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorScott Wood <scottwood@freescale.com>2007-08-20 19:39:46 +0200
committerPaul Mackerras <paulus@samba.org>2007-08-22 07:21:48 +0200
commit0602801c22ea1767cd0298b11da140bd5cb764d2 (patch)
tree323d76381d007b23b2b60d9865a15193e83c2d7b /arch/powerpc
parent[POWERPC] bootwrapper: Set timebase_period_ns from dt_fixup_cpu_clocks (diff)
downloadlinux-0602801c22ea1767cd0298b11da140bd5cb764d2.tar.xz
linux-0602801c22ea1767cd0298b11da140bd5cb764d2.zip
[POWERPC] bootwrapper: dt_xlate_range() bugfixes
1. The check whether ranges fits in the buffer was using elements rather than bytes. 2. Empty ranges were not properly treated as transparent, and missing ranges were treated as transparent. 3. The loop terminated when translating from the root rather than to. Once bug #2 was fixed, it failed due to a missing ranges in the root node. 4. In decoding the ranges property, the #size-cells used was that of the parent, not the child. Signed-off-by: Scott Wood <scottwood@freescale.com> Acked-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/boot/devtree.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/arch/powerpc/boot/devtree.c b/arch/powerpc/boot/devtree.c
index ae8b886f5a1d..129e6d9b8d43 100644
--- a/arch/powerpc/boot/devtree.c
+++ b/arch/powerpc/boot/devtree.c
@@ -218,7 +218,7 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr,
u32 this_addr[MAX_ADDR_CELLS];
void *parent;
u64 ret_addr, ret_size;
- u32 naddr, nsize, prev_naddr;
+ u32 naddr, nsize, prev_naddr, prev_nsize;
int buflen, offset;
parent = get_parent(node);
@@ -233,7 +233,7 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr,
offset = (naddr + nsize) * res;
if (reglen < offset + naddr + nsize ||
- sizeof(dt_xlate_buf) < offset + naddr + nsize)
+ sizeof(dt_xlate_buf) < (offset + naddr + nsize) * 4)
return 0;
copy_val(last_addr, dt_xlate_buf + offset, naddr);
@@ -244,20 +244,26 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr,
ret_size |= dt_xlate_buf[offset + naddr + 1];
}
- while ((node = get_parent(node))) {
+ for (;;) {
prev_naddr = naddr;
+ prev_nsize = nsize;
+ node = parent;
- get_reg_format(node, &naddr, &nsize);
+ parent = get_parent(node);
+ if (!parent)
+ break;
+
+ get_reg_format(parent, &naddr, &nsize);
buflen = getprop(node, "ranges", dt_xlate_buf,
sizeof(dt_xlate_buf));
- if (buflen < 0)
+ if (buflen == 0)
continue;
- if (buflen > sizeof(dt_xlate_buf))
+ if (buflen < 0 || buflen > sizeof(dt_xlate_buf))
return 0;
offset = find_range(last_addr, dt_xlate_buf, prev_naddr,
- naddr, nsize, buflen / 4);
+ naddr, prev_nsize, buflen / 4);
if (offset < 0)
return 0;