LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [i2c] i2c-mpc.c driver issues
From: Joakim Tjernlund @ 2007-10-26 11:21 UTC (permalink / raw)
  To: Jean Delvare; +Cc: linuxppc-dev, i2c
In-Reply-To: <20071026115329.0307e207@hyperion.delvare>

On Fri, 2007-10-26 at 11:53 +0200, Jean Delvare wrote:
> Hi Jocke,
> 
> On Wed, 24 Oct 2007 23:06:13 +0200, Tjernlund wrote:
> > While browsing the i2c-mpc.c driver I noticed some things that look odd
> > to me so I figured I report them. Could not find a maintainer in the MAINTANERS file
> > so I sent here, cc:ed linuxppc-dev as well.
> > 
> > 1) There are a lot of return -1 error code that is propagated back to
> >    userspace. Should be changed to proper -Exxx codes.
> 
> This is true of many Linux i2c bus drivers, unfortunately. While nothing
> actually prevents drivers from returning -1 to userspace on error,
> meaningful error codes would of course be preferred.
> 
> > 2) mpc_read(), according to the comment below it sends a STOP condition here but
> >    this function does not known if this is the last read or not. mpc_xfer is
> >    the one that knows when the transaction is over and should send the stop, which it already
> >    does.
> > 
> >  /* Generate stop on last byte */
> >   if (i == length - 1)
> >        writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_TXAK);
> 
> Probably correct, although I am not familiar with this specific
> hardware. I guess that the same is true of mpc_write as well, which is
> even worse because write + read combined transactions are very common
> (while read + write are not.)

Don't think write is a problem, only read. I would have to look at the
HW spec to make sure though.

> 
> I'm not completely sure that mpc_xfer sends the stop. mpc_i2c_stop
> doesn't seem to do much.
> 
> Now that you've identified these bugs, what about sending patches
> to fix them?

Normally I would do that, but I am too busy with other things. Thats
why I only reported this as I know I won't have time to fix it for some
time.

 Jocke

^ permalink raw reply

* Re: [RFC] [PATCH] PowerPC: Workaround for the 440EP(x)/GR(x) processors identical PVR issue.
From: Valentine Barshak @ 2007-10-26 11:05 UTC (permalink / raw)
  To: benh; +Cc: linuxppc-dev, sr
In-Reply-To: <1193345051.7018.15.camel@pasglop>

Benjamin Herrenschmidt wrote:
> On Thu, 2007-10-25 at 22:16 +0400, Valentine Barshak wrote:
>> PowerPC 440EP(x) 440GR(x) processors have the same PVR values, since
>> they have identical cores. However, FPU is not supported on GR(x) and
>> enabling APU instruction broadcast in the CCR0 register (to enable FPU)
>> may cause unpredictable results. There's no safe way to detect FPU
>> support at runtime. This patch provides a workarund for the issue.
>> We use a POWER6 "logical PVR approach". First, we identify all EP(x)
>> and GR(x) processors as GR(x) ones (which is safe). Then we check 
>> the device tree cpu path. If we have a EP(x) processor entry,
>> we call identify_cpu again with PVR | 0x8. This bit is always 0
>> in the real PVR. This way we enable FPU only for 440EP(x).
>>
>> Signed-off-by: Valentine Barshak <vbarshak@ru.mvista.com>
> 
> Why not just or-in the FPU feature bit ?
> 
> Ben.
> 
> 

It's not enough. We need to enable APU instruction broadcast for EP(x) 
(call __init_fpu_44x in arch/powerpc/kernel/cpu_setup_44x.S).
Or do you suggest to or-in FPU feature bit and enable APUIB later, not 
in the cpu_setup callback?
Thanks,
Valentine.

^ permalink raw reply

* Re: [PATCH 01/16] Add of_get_next_parent()
From: David Miller @ 2007-10-26 10:38 UTC (permalink / raw)
  To: michael; +Cc: linuxppc-dev
In-Reply-To: <80449d4682309dbf8cf80816be4f381fe875f3d1.1193381582.git.michael@ellerman.id.au>

From: Michael Ellerman <michael@ellerman.id.au>
Date: Fri, 26 Oct 2007 16:54:31 +1000 (EST)

> Iterating through a device node's parents is simple enough, but dealing
> with the refcounts properly is a little ugly, and replicating that logic
> is asking for someone to get it wrong or forget it all together, eg:
> 
> while (dn != NULL) {
> 	/* loop body */
> 	tmp = of_get_parent(dn);
> 	of_node_put(dn);
> 	dn = tmp;
> }
> 
> So add of_get_next_parent(), inspired by of_get_next_child(). The contract
> is that it returns the parent and drops the reference on the current node,
> this makes the loop look like:
> 
> while (dn != NULL) {
> 	/* loop body */
> 	dn = of_get_next_parent(dn);
> }
> 
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>

Looks good to me:

Acked-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply

* Re: [i2c] i2c-mpc.c driver issues
From: Jean Delvare @ 2007-10-26  9:53 UTC (permalink / raw)
  To: Tjernlund; +Cc: linuxppc-dev, i2c
In-Reply-To: <019001c81681$b5d449c0$5267a8c0@Jocke>

Hi Jocke,

On Wed, 24 Oct 2007 23:06:13 +0200, Tjernlund wrote:
> While browsing the i2c-mpc.c driver I noticed some things that look odd
> to me so I figured I report them. Could not find a maintainer in the MAINTANERS file
> so I sent here, cc:ed linuxppc-dev as well.
> 
> 1) There are a lot of return -1 error code that is propagated back to
>    userspace. Should be changed to proper -Exxx codes.

This is true of many Linux i2c bus drivers, unfortunately. While nothing
actually prevents drivers from returning -1 to userspace on error,
meaningful error codes would of course be preferred.

> 2) mpc_read(), according to the comment below it sends a STOP condition here but
>    this function does not known if this is the last read or not. mpc_xfer is
>    the one that knows when the transaction is over and should send the stop, which it already
>    does.
> 
>  /* Generate stop on last byte */
>   if (i == length - 1)
>        writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_TXAK);

Probably correct, although I am not familiar with this specific
hardware. I guess that the same is true of mpc_write as well, which is
even worse because write + read combined transactions are very common
(while read + write are not.)

I'm not completely sure that mpc_xfer sends the stop. mpc_i2c_stop
doesn't seem to do much.

Now that you've identified these bugs, what about sending patches
to fix them?

-- 
Jean Delvare

^ permalink raw reply

* Re: ppc manual paging question
From: Wang, Baojun @ 2007-10-26  9:50 UTC (permalink / raw)
  To: benh, linuxppc-dev
In-Reply-To: <393040796.08064@lzu.edu.cn>

[-- Attachment #1: Type: text/plain, Size: 3456 bytes --]

On Monday 22 October 2007 16:04:14, Benjamin Herrenschmidt wrote:
> > Yup, I've found how does the kernel handle tlbs, I think the most
> > important thing is I forgot read/write the SPRN_SPRG3 register as _switch
> > does.
>
> SPRG3 is for use by the operating system for whatever you want... if you
> are copying linux code, then you probably indeed want to get that right
> but you don't have to use SPRG3.
>
> > I've add the _PAGE_PRESENT flag to the related PTE
>
> Hrm.. that has nothing ot do with the PTE. Bolting is more a property of
> your replacement algorithm in the TLB miss handler.
>
> Ben.

Hi,

  First thanks a lot for your help I've finish the tlb code, now I can 
manually translate the virtual address correctly, I verified this by printing 
out the data within the virtual address and it's fine. now the only thing 
left is jump to that address (the address is point to _start function), But I 
got an error about unable to access the stack (0xd100fc60 ...), but it is 
valid before the instruction:

/**
 * XXX: should not defined here
 */
#define EVENTS_USER_ADDR_OFFSET 36

_GLOBAL(jump_xm_dom)
        stwu    r1,-INT_FRAME_SIZE(r1)
        mflr    r0
        stw     r0,INT_FRAME_SIZE+4(r1)

        stw     r31,INT_FRAME_SIZE+128(r1)

        lwz     r5,EVENTS_USER_ADDR_OFFSET(r4)
        mr      r31,r5  /* new_domain->events_user_addr */

        cmpwi   r3,0
        beq     1f

        mtctr   r3      /* jump to entry_point */
        bctrl

        li      r3,0
1:
        lwz     r31,INT_FRAME_SIZE+128(r1)

        lwz     r0,INT_FRAME_SIZE+4(r1)
        addi    r1,r1,INT_FRAME_SIZE
        mtlr    r0
        blr

the SP is valid before `bctrl', while exec bctrl, I got the error said unable 
to access address SP ($r1) from bdigdb, without bdigbd (running directly), an 
error is print out while the system is dead: 

insn: 94 21 ff 40 7c 08 02 a6 90 01 00 c4 7f e3 fb 78 3d 20 10 01 90 69 07 a0 
48 00 02 55 80 01 00 c4
$T0440:10000094;01:d1072e60;#ee

address d1072e60 is the address of SP ($r1) before bctrl.

NOTE entry_point($r3) is address like 0x100000a0 which is loaded from the 
userspace by a loader program (it loads all section marked as PT_LOAD, such 
as .text, the above insn is the entry of .text section, which is _start), but 
the above code is from the kernel space. and here is the _start function:

#define INT_FRAME_SIZE  192

.globl _start
_start:
        stwu    1, -INT_FRAME_SIZE(1)
        mflr    0
        stw     0, INT_FRAME_SIZE+4(1)

        mr      3,31    /* new_domain->events_user_addr */

        lis     9, event_handling@ha
        stw     3, event_handling@l(9)
        bl      kmain

        lwz     0, INT_FRAME_SIZE+4(1);
        mtlr    0
        addi    1, 1, INT_FRAME_SIZE
        blr

.size   _start, .-_start

I'm sorry I'm not very familiar with the ppc assembly, is there something 
fundamentally wrong? Thank you very much!

  Regards,
Wang

-- 
Wang, Baojun                                        Lanzhou University
Distributed & Embedded System Lab              http://dslab.lzu.edu.cn
School of Information Science and Engeneering        wangbj@lzu.edu.cn
Tianshui South Road 222. Lanzhou 730000                     .P.R.China
Tel:+86-931-8912025                                Fax:+86-931-8912022

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* mpc8xx, i2c read DB busy issue
From: Ankur Maheshwari @ 2007-10-26  9:30 UTC (permalink / raw)
  To: linuxppc-embedded

Hi all,

I am trying to use mpc860 as i2c-SLAVE. Kernel, I am using is 
Linux-2.4.4, which I can't change due to some reasons.

I am able to do I2C read/write operations on mpc8xx-i2c slave only after 
re-insmoding my driver module (i2c-algo-8xx.c, and adapter layer drive, 
code I took form i2c-rpx/r360.c ).

The issue I am facing is when I insmod i2c-driver on fresh Linux boot, 
any i2c-mpc860 as slave read/write operation gives me busy status (which 
is for Rx BD not available) in Controller's i2c Event Registers. When I 
get busy status I have to do force_close() and re-init of bd, then only 
busy status goes off.

I tried calling cpm_iic_init(); twice while __init but with no change in 
busy status.

After some initial try, i2c slave write works but i2c read gives no data 
to the master. After re-insmoding driver, read/write works with some 
times (1 out of 15 times) i2c-read failing.

But still I can't understand why busy is coming....

Any help or suggestions are highly appreciated.

thanks,
Ankur Maheshwari

 

^ permalink raw reply

* Re: [PATCH 11/16] Use of_get_next_child() in eeh_restore_bars()
From: Stephen Rothwell @ 2007-10-26  7:29 UTC (permalink / raw)
  To: Michael Ellerman; +Cc: linuxppc-dev
In-Reply-To: <ef7facd658919117aa7c693b4eeb12241ca859d8.1193381582.git.michael@ellerman.id.au>

[-- Attachment #1: Type: text/plain, Size: 699 bytes --]

On Fri, 26 Oct 2007 16:54:43 +1000 (EST) Michael Ellerman <michael@ellerman.id.au> wrote:
>
> +++ b/arch/powerpc/platforms/pseries/eeh.c
> @@ -841,11 +841,8 @@ void eeh_restore_bars(struct pci_dn *pdn)
>  	if ((pdn->eeh_mode & EEH_MODE_SUPPORTED) && !IS_BRIDGE(pdn->class_code))
>  		__restore_bars (pdn);
>  
> -	dn = pdn->node->child;
> -	while (dn) {
> +	for (dn = NULL; (dn = of_get_next_child(pdn->node, dn));)

Just wondering if we need

#define for_each_child_node(dn, parent) \
	for (dn = of_get_next_child(parent, NULL); dn; \
		dn = of_get_next_child(parent, dn))

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Re: [PATCH 09/16] Use of_get_next_parent() in axon_msi.c
From: Stephen Rothwell @ 2007-10-26  7:24 UTC (permalink / raw)
  To: Michael Ellerman; +Cc: linuxppc-dev
In-Reply-To: <4e749fe7078e2c006cf40921cea904833c75263c.1193381582.git.michael@ellerman.id.au>

[-- Attachment #1: Type: text/plain, Size: 763 bytes --]

On Fri, 26 Oct 2007 16:54:41 +1000 (EST) Michael Ellerman <michael@ellerman.id.au> wrote:
>
> +++ b/arch/powerpc/platforms/cell/axon_msi.c
> @@ -125,7 +125,7 @@ static struct axon_msic *find_msi_translator(struct pci_dev *dev)
>  		return NULL;
>  	}
>  
> -	for (; dn; tmp = of_get_parent(dn), of_node_put(dn), dn = tmp) {
> +	for (; dn; dn = of_get_next_parent(dn)) {
>  		ph = of_get_property(dn, "msi-translator", NULL);
>  		if (ph)
>  			break;

You no longer assign anything to tmp, but just below here, you may jump
to out_error: which will do an of_node_put(tmp).  So you need to
initialise tmp or have another error goto label.

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH 16/16] Use of_get_next_child() in EEH print_device_node_tree()
From: Michael Ellerman @ 2007-10-26  6:54 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <80449d4682309dbf8cf80816be4f381fe875f3d1.1193381582.git.michael@ellerman.id.au>

We should use of_get_next_child() in print_device_node_tree() to safely
traverse the node's children.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/platforms/pseries/eeh_driver.c |    6 ++----
 1 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index abf1850..0a23bc4 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -44,6 +44,7 @@ static inline const char * pcid_name (struct pci_dev *pdev)
 #ifdef DEBUG
 static void print_device_node_tree (struct pci_dn *pdn, int dent)
 {
+	struct device_node *pc;
 	int i;
 	if (!pdn) return;
 	for (i=0;i<dent; i++)
@@ -52,11 +53,8 @@ static void print_device_node_tree (struct pci_dn *pdn, int dent)
 		pdn->node->name, pdn->eeh_mode, pdn->eeh_config_addr,
 		pdn->eeh_pe_config_addr, pdn->node->full_name);
 	dent += 3;
-	struct device_node *pc = pdn->node->child;
-	while (pc) {
+	for (pc = NULL; (pc = of_get_next_child(pdn->node, pc));)
 		print_device_node_tree(PCI_DN(pc), dent);
-		pc = pc->sibling;
-	}
 }
 #endif
 
-- 
1.5.2.rc1.1884.g59b20

^ permalink raw reply related

* [PATCH 15/16] Use of_get_next_child() in eeh_reset_device()
From: Michael Ellerman @ 2007-10-26  6:54 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <80449d4682309dbf8cf80816be4f381fe875f3d1.1193381582.git.michael@ellerman.id.au>

We should use of_get_next_child() in eeh_reset_device() to safely
traverse the node's children.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>

---

Linas, I don't grok the logic in here, can you check it's OK. The old code
would potentially not walk through all siblings if pe_dn->node was not
equal to pe_dn->node->parent->child, but now it will regardless.


 arch/powerpc/platforms/pseries/eeh_driver.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index 15e015e..abf1850 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -249,7 +249,7 @@ static void eeh_report_failure(struct pci_dev *dev, void *userdata)
 
 static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus)
 {
-	struct device_node *dn;
+	struct device_node *dn, *parent;
 	int cnt, rc;
 
 	/* pcibios will clear the counter; save the value */
@@ -270,15 +270,16 @@ static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus)
 	if (!pcibios_find_pci_bus(dn) && PCI_DN(dn->parent))
 		dn = dn->parent->child;
 
-	while (dn) {
+	parent = of_node_get(dn->parent);
+	for (dn = NULL; (dn = of_get_next_child(parent, dn));) {
 		struct pci_dn *ppe = PCI_DN(dn);
 		/* On Power4, always true because eeh_pe_config_addr=0 */
 		if (pe_dn->eeh_pe_config_addr == ppe->eeh_pe_config_addr) {
 			rtas_configure_bridge(ppe);
 			eeh_restore_bars(ppe);
  		}
-		dn = dn->sibling;
 	}
+	of_node_put(parent);
 
 	/* Give the system 5 seconds to finish running the user-space
 	 * hotplug shutdown scripts, e.g. ifdown for ethernet.  Yes, 
-- 
1.5.2.rc1.1884.g59b20

^ permalink raw reply related

* [PATCH 14/16] Use of_get_next_child() in __eeh_clear_slot()
From: Michael Ellerman @ 2007-10-26  6:54 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <80449d4682309dbf8cf80816be4f381fe875f3d1.1193381582.git.michael@ellerman.id.au>

We should use of_get_next_child() in __eeh_clear_slot() to safely
traverse the node's children.

To achieve this we need to change __eeh_clear_slot() to take the parent
node, not the child. This is also safer, as passing anything other than
node->child to the existing routine will not traverse all peers, only
those deeper in the sibling list.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/platforms/pseries/eeh.c |   11 ++++++-----
 1 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index d06ab36..1537597 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -412,16 +412,17 @@ void eeh_mark_slot (struct device_node *dn, int mode_flag)
 	__eeh_mark_slot(dn, mode_flag);
 }
 
-static void __eeh_clear_slot (struct device_node *dn, int mode_flag)
+static void __eeh_clear_slot(struct device_node *parent, int mode_flag)
 {
-	while (dn) {
+	struct device_node *dn;
+
+	for (dn = NULL; (dn = of_get_next_child(parent, dn));) {
 		if (PCI_DN(dn)) {
 			PCI_DN(dn)->eeh_mode &= ~mode_flag;
 			PCI_DN(dn)->eeh_check_count = 0;
 			if (dn->child)
-				__eeh_clear_slot (dn->child, mode_flag);
+				__eeh_clear_slot(dn, mode_flag);
 		}
-		dn = dn->sibling;
 	}
 }
 
@@ -438,7 +439,7 @@ void eeh_clear_slot (struct device_node *dn, int mode_flag)
 
 	PCI_DN(dn)->eeh_mode &= ~mode_flag;
 	PCI_DN(dn)->eeh_check_count = 0;
-	__eeh_clear_slot (dn->child, mode_flag);
+	__eeh_clear_slot(dn, mode_flag);
 	spin_unlock_irqrestore(&confirm_error_lock, flags);
 }
 
-- 
1.5.2.rc1.1884.g59b20

^ permalink raw reply related

* [PATCH 13/16] Use of_get_next_child() in __eeh_mark_slot()
From: Michael Ellerman @ 2007-10-26  6:54 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <80449d4682309dbf8cf80816be4f381fe875f3d1.1193381582.git.michael@ellerman.id.au>

We should use of_get_next_child() in __eeh_mark_slot() to safely
traverse the node's children.

To achieve this we need to change __eeh_mark_slot() to take the parent
node, not the child. This is also safer, as passing anything other than
node->child to the existing routine will not traverse all peers, only
those deeper in the sibling list.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/platforms/pseries/eeh.c |   11 ++++++-----
 1 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index d1d6d55..d06ab36 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -373,9 +373,11 @@ struct device_node * find_device_pe(struct device_node *dn)
  *  an interrupt context, which is bad.
  */
 
-static void __eeh_mark_slot (struct device_node *dn, int mode_flag)
+static void __eeh_mark_slot(struct device_node *parent, int mode_flag)
 {
-	while (dn) {
+	struct device_node *dn;
+
+	for (dn = NULL; (dn = of_get_next_child(parent, dn));) {
 		if (PCI_DN(dn)) {
 			/* Mark the pci device driver too */
 			struct pci_dev *dev = PCI_DN(dn)->pcidev;
@@ -386,9 +388,8 @@ static void __eeh_mark_slot (struct device_node *dn, int mode_flag)
 				dev->error_state = pci_channel_io_frozen;
 
 			if (dn->child)
-				__eeh_mark_slot (dn->child, mode_flag);
+				__eeh_mark_slot(dn, mode_flag);
 		}
-		dn = dn->sibling;
 	}
 }
 
@@ -408,7 +409,7 @@ void eeh_mark_slot (struct device_node *dn, int mode_flag)
 	if (dev)
 		dev->error_state = pci_channel_io_frozen;
 
-	__eeh_mark_slot (dn->child, mode_flag);
+	__eeh_mark_slot(dn, mode_flag);
 }
 
 static void __eeh_clear_slot (struct device_node *dn, int mode_flag)
-- 
1.5.2.rc1.1884.g59b20

^ permalink raw reply related

* [PATCH 12/16] Use of_get_next_child() in eeh_add_device_tree_early()
From: Michael Ellerman @ 2007-10-26  6:54 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <80449d4682309dbf8cf80816be4f381fe875f3d1.1193381582.git.michael@ellerman.id.au>

We should use of_get_next_child() in the eeh_add_device_tree_early()
routine to safely traverse the node's children.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/platforms/pseries/eeh.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index abe3de1..d1d6d55 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -1120,7 +1120,7 @@ static void eeh_add_device_early(struct device_node *dn)
 void eeh_add_device_tree_early(struct device_node *dn)
 {
 	struct device_node *sib;
-	for (sib = dn->child; sib; sib = sib->sibling)
+	for (sib = NULL; (sib = of_get_next_child(dn, sib));)
 		eeh_add_device_tree_early(sib);
 	eeh_add_device_early(dn);
 }
-- 
1.5.2.rc1.1884.g59b20

^ permalink raw reply related

* [PATCH 11/16] Use of_get_next_child() in eeh_restore_bars()
From: Michael Ellerman @ 2007-10-26  6:54 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <80449d4682309dbf8cf80816be4f381fe875f3d1.1193381582.git.michael@ellerman.id.au>

We should use of_get_next_child() in the eeh_restore_bars()
routine to safely traverse the node's children.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/platforms/pseries/eeh.c |    5 +----
 1 files changed, 1 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 7309caa..abe3de1 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -841,11 +841,8 @@ void eeh_restore_bars(struct pci_dn *pdn)
 	if ((pdn->eeh_mode & EEH_MODE_SUPPORTED) && !IS_BRIDGE(pdn->class_code))
 		__restore_bars (pdn);
 
-	dn = pdn->node->child;
-	while (dn) {
+	for (dn = NULL; (dn = of_get_next_child(pdn->node, dn));)
 		eeh_restore_bars (PCI_DN(dn));
-		dn = dn->sibling;
-	}
 }
 
 /**
-- 
1.5.2.rc1.1884.g59b20

^ permalink raw reply related

* [PATCH 10/16] Use of_get_next_child() in EEH gather_pci_data()
From: Michael Ellerman @ 2007-10-26  6:54 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <80449d4682309dbf8cf80816be4f381fe875f3d1.1193381582.git.michael@ellerman.id.au>

We should use of_get_next_child() in the EEH gather_pci_data()
routine to safely traverse the node's children.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/platforms/pseries/eeh.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 22322b3..7309caa 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -238,12 +238,10 @@ static size_t gather_pci_data(struct pci_dn *pdn, char * buf, size_t len)
 
 	/* Gather status on devices under the bridge */
 	if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) {
-		dn = pdn->node->child;
-		while (dn) {
+		for (dn = NULL; (dn = of_get_next_child(pdn->node, dn));) {
 			pdn = PCI_DN(dn);
 			if (pdn)
 				n += gather_pci_data(pdn, buf+n, len-n);
-			dn = dn->sibling;
 		}
 	}
 
-- 
1.5.2.rc1.1884.g59b20

^ permalink raw reply related

* [PATCH 09/16] Use of_get_next_parent() in axon_msi.c
From: Michael Ellerman @ 2007-10-26  6:54 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <80449d4682309dbf8cf80816be4f381fe875f3d1.1193381582.git.michael@ellerman.id.au>

We can use of_get_next_parent() in two places in axon_msi.c to
simplify the looping logic.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/platforms/cell/axon_msi.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index 095988f..76870fe 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -125,7 +125,7 @@ static struct axon_msic *find_msi_translator(struct pci_dev *dev)
 		return NULL;
 	}
 
-	for (; dn; tmp = of_get_parent(dn), of_node_put(dn), dn = tmp) {
+	for (; dn; dn = of_get_next_parent(dn)) {
 		ph = of_get_property(dn, "msi-translator", NULL);
 		if (ph)
 			break;
@@ -171,7 +171,7 @@ static int axon_msi_check_device(struct pci_dev *dev, int nvec, int type)
 
 static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg)
 {
-	struct device_node *dn, *tmp;
+	struct device_node *dn;
 	struct msi_desc *entry;
 	int len;
 	const u32 *prop;
@@ -184,7 +184,7 @@ static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg)
 
 	entry = list_first_entry(&dev->msi_list, struct msi_desc, list);
 
-	for (; dn; tmp = of_get_parent(dn), of_node_put(dn), dn = tmp) {
+	for (; dn; dn = of_get_next_parent(dn)) {
 		if (entry->msi_attrib.is_64) {
 			prop = of_get_property(dn, "msi-address-64", &len);
 			if (prop)
-- 
1.5.2.rc1.1884.g59b20

^ permalink raw reply related

* [PATCH 08/16] Use of_get_next_parent() in pseries_mpic_init_IRQ()
From: Michael Ellerman @ 2007-10-26  6:54 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <80449d4682309dbf8cf80816be4f381fe875f3d1.1193381582.git.michael@ellerman.id.au>

Use of_get_next_parent() in pseries_mpic_init_IRQ() to simplify
the loop logic.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/platforms/pseries/setup.c |    9 +++------
 1 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index fdb9b1c..f08dfaf 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -129,7 +129,7 @@ void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc)
 
 static void __init pseries_mpic_init_IRQ(void)
 {
-	struct device_node *np, *old, *cascade = NULL;
+	struct device_node *np, *cascade = NULL;
         const unsigned int *addrp;
 	unsigned long intack = 0;
 	const unsigned int *opprop;
@@ -182,11 +182,8 @@ static void __init pseries_mpic_init_IRQ(void)
 	}
 
 	/* Check ACK type */
-	for (old = of_node_get(cascade); old != NULL ; old = np) {
-		np = of_get_parent(old);
-		of_node_put(old);
-		if (np == NULL)
-			break;
+	np = of_node_get(cascade);
+	while ((np = of_get_next_parent(np))) {
 		if (strcmp(np->name, "pci") != 0)
 			continue;
 		addrp = of_get_property(np, "8259-interrupt-acknowledge",
-- 
1.5.2.rc1.1884.g59b20

^ permalink raw reply related

* [PATCH 07/16] Use of_get_next_parent() in xics_setup_8259_cascade()
From: Michael Ellerman @ 2007-10-26  6:54 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <80449d4682309dbf8cf80816be4f381fe875f3d1.1193381582.git.michael@ellerman.id.au>

Use of_get_next_parent() in xics_setup_8259_cascade() to simplify
the loop logic.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/platforms/pseries/xics.c |    9 +++------
 1 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 66e7d68..58a3cc7 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -617,7 +617,7 @@ static void __init xics_init_one_node(struct device_node *np,
 
 static void __init xics_setup_8259_cascade(void)
 {
-	struct device_node *np, *old, *found = NULL;
+	struct device_node *np, *found = NULL;
 	int cascade, naddr;
 	const u32 *addrp;
 	unsigned long intack = 0;
@@ -638,11 +638,8 @@ static void __init xics_setup_8259_cascade(void)
 	}
 	pr_debug("xics: cascade mapped to irq %d\n", cascade);
 
-	for (old = of_node_get(found); old != NULL ; old = np) {
-		np = of_get_parent(old);
-		of_node_put(old);
-		if (np == NULL)
-			break;
+	np = of_node_get(found);
+	while ((np = of_get_next_parent(np))) {
 		if (strcmp(np->name, "pci") != 0)
 			continue;
 		addrp = of_get_property(np, "8259-interrupt-acknowledge", NULL);
-- 
1.5.2.rc1.1884.g59b20

^ permalink raw reply related

* [PATCH 06/16] Use of_get_next_child() in pci_dma_bus_setup_pSeries()
From: Michael Ellerman @ 2007-10-26  6:54 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <80449d4682309dbf8cf80816be4f381fe875f3d1.1193381582.git.michael@ellerman.id.au>

pci_dma_bus_setup_pSeries() should use of_get_next_child() to safely
iterate through the nodes children.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/platforms/pseries/iommu.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index ef1aa8d..1a9e14f 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -343,7 +343,7 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus)
 	of_node_put(isa_dn);
 
 	/* Count number of direct PCI children of the PHB. */
-	for (children = 0, tmp = dn->child; tmp; tmp = tmp->sibling)
+	for (children = 0, tmp = NULL; (tmp = of_get_next_child(dn, tmp));)
 		children++;
 
 	DBG("Children: %d\n", children);
-- 
1.5.2.rc1.1884.g59b20

^ permalink raw reply related

* [PATCH 05/16] Use of_get_next_parent() in pci_dma_dev_setup_pSeriesLP()
From: Michael Ellerman @ 2007-10-26  6:54 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <80449d4682309dbf8cf80816be4f381fe875f3d1.1193381582.git.michael@ellerman.id.au>

pci_dma_dev_setup_pSeriesLP() should use of_get_next_parent() to safely
iterate through the parent nodes.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/platforms/pseries/iommu.c |   12 ++++++++----
 1 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 5e9430e..ef1aa8d 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -503,8 +503,9 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
 	dn = pci_device_to_OF_node(dev);
 	DBG("  node is %s\n", dn->full_name);
 
-	for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table;
-	     pdn = pdn->parent) {
+	for (pdn = of_node_get(dn);
+	     pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table;
+	     pdn = of_get_next_parent(pdn)) {
 		dma_window = of_get_property(pdn, "ibm,dma-window", NULL);
 		if (dma_window)
 			break;
@@ -514,7 +515,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
 		printk(KERN_WARNING "pci_dma_dev_setup_pSeriesLP: "
 		       "no DMA window found for pci dev=%s dn=%s\n",
 				 pci_name(dev), dn? dn->full_name : "<null>");
-		return;
+		goto out_put;
 	}
 	DBG("  parent is %s\n", pdn->full_name);
 
@@ -524,7 +525,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
 	if (dma_window == NULL || pdn->parent == NULL) {
 		DBG("  no dma window for device, linking to parent\n");
 		dev->dev.archdata.dma_data = PCI_DN(pdn)->iommu_table;
-		return;
+		goto out_put;
 	}
 
 	pci = PCI_DN(pdn);
@@ -544,6 +545,9 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
 	}
 
 	dev->dev.archdata.dma_data = pci->iommu_table;
+
+out_put:
+	of_node_put(pdn);
 }
 #else  /* CONFIG_PCI */
 #define pci_dma_bus_setup_pSeries	NULL
-- 
1.5.2.rc1.1884.g59b20

^ permalink raw reply related

* [PATCH 04/16] Use of_get_next_parent() in pci_dma_dev_setup_pSeries()
From: Michael Ellerman @ 2007-10-26  6:54 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <80449d4682309dbf8cf80816be4f381fe875f3d1.1193381582.git.michael@ellerman.id.au>

pci_dma_dev_setup_pSeries() should use of_get_next_parent() to safely
iterate through the parent nodes.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/platforms/pseries/iommu.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index e2b325d..5e9430e 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -472,14 +472,17 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev)
 	 * an already allocated iommu table is found and use that.
 	 */
 
+	dn = of_node_get(dn);
 	while (dn && PCI_DN(dn) && PCI_DN(dn)->iommu_table == NULL)
-		dn = dn->parent;
+		dn = of_get_next_parent(dn);
 
 	if (dn && PCI_DN(dn))
 		dev->dev.archdata.dma_data = PCI_DN(dn)->iommu_table;
 	else
 		printk(KERN_WARNING "iommu: Device %s has no iommu table\n",
 		       pci_name(dev));
+
+	of_node_put(dn);
 }
 
 static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
-- 
1.5.2.rc1.1884.g59b20

^ permalink raw reply related

* [PATCH 03/16] Use of_get_next_parent() in pci_dma_bus_setup_pSeriesLP()
From: Michael Ellerman @ 2007-10-26  6:54 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <80449d4682309dbf8cf80816be4f381fe875f3d1.1193381582.git.michael@ellerman.id.au>

pci_dma_bus_setup_pSeriesLP() should use of_get_next_parent() to safely
iterate through the parent nodes.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/platforms/pseries/iommu.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 83c0e0f..e2b325d 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -403,7 +403,7 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
 	DBG("pci_dma_bus_setup_pSeriesLP: setting up bus %s\n", dn->full_name);
 
 	/* Find nearest ibm,dma-window, walking up the device tree */
-	for (pdn = dn; pdn != NULL; pdn = pdn->parent) {
+	for (pdn = of_node_get(dn); pdn; pdn = of_get_next_parent(pdn)) {
 		dma_window = of_get_property(pdn, "ibm,dma-window", NULL);
 		if (dma_window != NULL)
 			break;
@@ -411,6 +411,7 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
 
 	if (dma_window == NULL) {
 		DBG("  no ibm,dma-window property !\n");
+		of_node_put(pdn);
 		return;
 	}
 
@@ -437,6 +438,8 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
 
 	if (pdn != dn)
 		PCI_DN(dn)->iommu_table = ppci->iommu_table;
+
+	of_node_put(pdn);
 }
 
 
-- 
1.5.2.rc1.1884.g59b20

^ permalink raw reply related

* [PATCH 02/16] Use of_get_next_parent() in pci_dma_bus_setup_pSeries()
From: Michael Ellerman @ 2007-10-26  6:54 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <80449d4682309dbf8cf80816be4f381fe875f3d1.1193381582.git.michael@ellerman.id.au>

pci_dma_bus_setup_pSeries() should use of_get_next_parent() to safely
iterate through the parent nodes.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/platforms/pseries/iommu.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index be17d23..83c0e0f 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -314,7 +314,7 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus)
 {
 	struct device_node *dn;
 	struct iommu_table *tbl;
-	struct device_node *isa_dn, *isa_dn_orig;
+	struct device_node *isa_dn;
 	struct device_node *tmp;
 	struct pci_dn *pci;
 	int children;
@@ -334,13 +334,13 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus)
 	/* Check if the ISA bus on the system is under
 	 * this PHB.
 	 */
-	isa_dn = isa_dn_orig = of_find_node_by_type(NULL, "isa");
+	isa_dn = of_find_node_by_type(NULL, "isa");
 
 	while (isa_dn && isa_dn != dn)
-		isa_dn = isa_dn->parent;
+		isa_dn = of_get_next_parent(isa_dn);
 
-	if (isa_dn_orig)
-		of_node_put(isa_dn_orig);
+	/* Drop our reference, it's still safe to check the pointer below */
+	of_node_put(isa_dn);
 
 	/* Count number of direct PCI children of the PHB. */
 	for (children = 0, tmp = dn->child; tmp; tmp = tmp->sibling)
-- 
1.5.2.rc1.1884.g59b20

^ permalink raw reply related

* [PATCH 01/16] Add of_get_next_parent()
From: Michael Ellerman @ 2007-10-26  6:54 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: davem

Iterating through a device node's parents is simple enough, but dealing
with the refcounts properly is a little ugly, and replicating that logic
is asking for someone to get it wrong or forget it all together, eg:

while (dn != NULL) {
	/* loop body */
	tmp = of_get_parent(dn);
	of_node_put(dn);
	dn = tmp;
}

So add of_get_next_parent(), inspired by of_get_next_child(). The contract
is that it returns the parent and drops the reference on the current node,
this makes the loop look like:

while (dn != NULL) {
	/* loop body */
	dn = of_get_next_parent(dn);
}

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 drivers/of/base.c  |   25 +++++++++++++++++++++++++
 include/linux/of.h |    1 +
 2 files changed, 26 insertions(+), 0 deletions(-)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 9377f3b..e0db2b5 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -138,6 +138,31 @@ struct device_node *of_get_parent(const struct device_node *node)
 EXPORT_SYMBOL(of_get_parent);
 
 /**
+ *	of_get_next_parent - Iterate to a node's parent
+ *	@node:	Node to get parent of
+ *
+ * 	This is like of_get_parent() except that it drops the
+ * 	refcount on the passed node, making it suitable for iterating
+ * 	through a node's parents.
+ *
+ *	Returns a node pointer with refcount incremented, use
+ *	of_node_put() on it when done.
+ */
+struct device_node *of_get_next_parent(struct device_node *node)
+{
+	struct device_node *parent;
+
+	if (!node)
+		return NULL;
+
+	read_lock(&devtree_lock);
+	parent = of_node_get(node->parent);
+	of_node_put(node);
+	read_unlock(&devtree_lock);
+	return parent;
+}
+
+/**
  *	of_get_next_child - Iterate a node childs
  *	@node:	parent node
  *	@prev:	previous child of the parent node, or NULL to get first
diff --git a/include/linux/of.h b/include/linux/of.h
index 5c39b92..3557d1e 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -44,6 +44,7 @@ extern struct device_node *of_find_compatible_node(struct device_node *from,
 extern struct device_node *of_find_node_by_path(const char *path);
 extern struct device_node *of_find_node_by_phandle(phandle handle);
 extern struct device_node *of_get_parent(const struct device_node *node);
+extern struct device_node *of_get_next_parent(struct device_node *node);
 extern struct device_node *of_get_next_child(const struct device_node *node,
 					     struct device_node *prev);
 extern struct property *of_find_property(const struct device_node *np,
-- 
1.5.2.rc1.1884.g59b20

^ permalink raw reply related

* [2/2] dtc: Switch dtc to C-style literals
From: David Gibson @ 2007-10-26  6:20 UTC (permalink / raw)
  To: Jon Loeliger; +Cc: linuxppc-dev
In-Reply-To: <20071026061718.GA6136@localhost.localdomain>

This patch introduces a new version of dts file, distinguished from
older files by starting with the special token /dts-v1/.  dts files in
the new version take C-style literals instead of the old bare hex or
OF-style base notation.  In addition, the "range" for of memreserve entries
(/memreserve/ f0000-fffff) is no longer recognized in the new format.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

---
 dtc-lexer.l               |   40 ++++++++++++++++++++++++++++++++--------
 dtc-parser.y              |   38 ++++++++++++++++++++++++++++++++++++--
 tests/run_tests.sh        |    4 ++++
 tests/test_tree1.dts      |   16 +++++++++-------
 tests/test_tree1_dts0.dts |   27 +++++++++++++++++++++++++++
 5 files changed, 108 insertions(+), 17 deletions(-)

Index: dtc/dtc-lexer.l
===================================================================
--- dtc.orig/dtc-lexer.l	2007-10-26 15:11:02.000000000 +1000
+++ dtc/dtc-lexer.l	2007-10-26 15:36:46.000000000 +1000
@@ -23,6 +23,7 @@
 %x INCLUDE
 %x BYTESTRING
 %x PROPNODENAME
+%s V1
 
 PROPCHAR	[a-zA-Z0-9,._+*#?-]
 UNITCHAR	[0-9a-f,]
@@ -44,12 +45,18 @@
 #define DPRINT(fmt, ...)	do { } while (0)
 #endif
 
+static int dts_version; /* = 0 */
 
-
+#define BEGIN_DEFAULT()	if (dts_version == 0) { \
+				DPRINT("<INITIAL>\n"); \
+				BEGIN(INITIAL); \
+			} else { \
+				DPRINT("<V1>\n"); \
+				BEGIN(V1); \
+			}
 %}
 
 %%
-
 <*>"/include/"		BEGIN(INCLUDE);
 
 <INCLUDE>\"[^"\n]*\"	{
@@ -58,7 +65,7 @@
 				/* Some unrecoverable error.*/
 				exit(1);
 			}
-			BEGIN(INITIAL);
+			BEGIN_DEFAULT();
 		}
 
 
@@ -78,11 +85,20 @@
 			return DT_STRING;
 		}
 
+<*>"/dts-v1/"	{
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			DPRINT("Keyword: /dts-v1/\n");
+			dts_version = 1;
+			BEGIN_DEFAULT();
+			return DT_V1;
+		}
+
 <*>"/memreserve/"	{
 			yylloc.filenum = srcpos_filenum;
 			yylloc.first_line = yylineno;
 			DPRINT("Keyword: /memreserve/\n");
-			BEGIN(INITIAL);
+			BEGIN_DEFAULT();
 			return DT_MEMRESERVE;
 		}
 
@@ -95,7 +111,7 @@
 			return DT_LABEL;
 		}
 
-[bodh]# {
+<INITIAL>[bodh]# {
 			yylloc.filenum = srcpos_filenum;
 			yylloc.first_line = yylineno;
 			if (*yytext == 'b')
@@ -110,7 +126,15 @@
 			return DT_BASE;
 		}
 
-[0-9a-fA-F]+	{
+<INITIAL>[0-9a-fA-F]+	{
+			yylloc.filenum = srcpos_filenum;
+			yylloc.first_line = yylineno;
+			yylval.literal = strdup(yytext);
+			DPRINT("Literal: '%s'\n", yylval.literal);
+			return DT_LEGACYLITERAL;
+		}
+
+<V1>[0-9]+|0[xX][0-9a-fA-F]+      {
 			yylloc.filenum = srcpos_filenum;
 			yylloc.first_line = yylineno;
 			yylval.literal = strdup(yytext);
@@ -138,7 +162,7 @@
 			yylloc.filenum = srcpos_filenum;
 			yylloc.first_line = yylineno;
 			DPRINT("/BYTESTRING\n");
-			BEGIN(INITIAL);
+			BEGIN_DEFAULT();
 			return ']';
 		}
 
@@ -147,7 +171,7 @@
 			yylloc.first_line = yylineno;
 			DPRINT("PropNodeName: %s\n", yytext);
 			yylval.propnodename = strdup(yytext);
-			BEGIN(INITIAL);
+			BEGIN_DEFAULT();
 			return DT_PROPNODENAME;
 		}
 
Index: dtc/dtc-parser.y
===================================================================
--- dtc.orig/dtc-parser.y	2007-10-26 15:11:02.000000000 +1000
+++ dtc/dtc-parser.y	2007-10-26 15:49:05.000000000 +1000
@@ -48,9 +48,11 @@
 	struct reserve_info *re;
 }
 
+%token DT_V1
 %token DT_MEMRESERVE
 %token <propnodename> DT_PROPNODENAME
 %token <literal> DT_LITERAL
+%token <literal> DT_LEGACYLITERAL
 %token <cbase> DT_BASE
 %token <byte> DT_BYTE
 %token <data> DT_STRING
@@ -61,6 +63,8 @@
 %type <data> propdataprefix
 %type <re> memreserve
 %type <re> memreserves
+%type <re> v0_memreserve
+%type <re> v0_memreserves
 %type <addr> addr
 %type <data> celllist
 %type <cbase> cellbase
@@ -78,7 +82,11 @@
 %%
 
 sourcefile:
-	  memreserves devicetree
+	  DT_V1 ';' memreserves devicetree
+		{
+			the_boot_info = build_boot_info($3, $4);
+		}
+	| v0_memreserves devicetree
 		{
 			the_boot_info = build_boot_info($1, $2);
 		}
@@ -100,6 +108,24 @@
 		{
 			$$ = build_reserve_entry($3, $4, $1);
 		}
+	;
+
+v0_memreserves:
+	  /* empty */
+		{
+			$$ = NULL;
+		}
+	| v0_memreserve v0_memreserves
+		{
+			$$ = chain_reserve_entry($1, $2);
+		};
+	;
+
+v0_memreserve:
+	  memreserve
+		{
+			$$ = $1;
+		}
 	| label DT_MEMRESERVE addr '-' addr ';'
 		{
 			$$ = build_reserve_entry($3, $5 - $3 + 1, $1);
@@ -108,6 +134,10 @@
 
 addr:
 	  DT_LITERAL
+	  	{
+			$$ = eval_literal($1, 0, 64);
+		}
+	| DT_LEGACYLITERAL
 		{
 			$$ = eval_literal($1, 16, 64);
 		}
@@ -212,7 +242,11 @@
 	;
 
 cellval:
-	  cellbase DT_LITERAL
+	  DT_LITERAL
+		{
+			$$ = eval_literal($1, 0, 32);
+		}
+	| cellbase DT_LEGACYLITERAL
 		{
 			$$ = eval_literal($2, $1, 32);
 		}
Index: dtc/tests/run_tests.sh
===================================================================
--- dtc.orig/tests/run_tests.sh	2007-10-26 15:11:02.000000000 +1000
+++ dtc/tests/run_tests.sh	2007-10-26 15:18:43.000000000 +1000
@@ -118,6 +118,10 @@
     tree1_tests_rw dtc_tree1.test.dtb
     run_test dtbs_equal_ordered dtc_tree1.test.dtb test_tree1.dtb
 
+    run_test dtc.sh -I dts -O dtb -o dtc_tree1_dts0.test.dtb test_tree1_dts0.dts
+    tree1_tests dtc_tree1_dts0.test.dtb
+    tree1_tests_rw dtc_tree1_dts0.test.dtb
+
     run_test dtc.sh -I dts -O dtb -o dtc_escapes.test.dtb escapes.dts
     run_test string_escapes dtc_escapes.test.dtb
 }
Index: dtc/tests/test_tree1.dts
===================================================================
--- dtc.orig/tests/test_tree1.dts	2007-10-26 15:11:02.000000000 +1000
+++ dtc/tests/test_tree1.dts	2007-10-26 15:18:43.000000000 +1000
@@ -1,27 +1,29 @@
-/memreserve/ deadbeef00000000-deadbeef000fffff;
-/memreserve/ abcd1234 00001234;
+/dts-v1/;
+
+/memreserve/ 0xdeadbeef00000000 0x100000;
+/memreserve/ 0xabcd1234 0x00001234;
 
 / {
 	compatible = "test_tree1";
-	prop-int = <deadbeef>;
+	prop-int = <0xdeadbeef>;
 	prop-str = "hello world";
 
 	subnode@1 {
 		compatible = "subnode1";
-		prop-int = <deadbeef>;
+		prop-int = <0xdeadbeef>;
 
 		subsubnode {
 			compatible = "subsubnode1", "subsubnode";
-			prop-int = <deadbeef>;
+			prop-int = <0xdeadbeef>;
 		};
 	};
 
 	subnode@2 {
-		prop-int = <abcd1234>;
+		prop-int = <0xabcd1234>;
 
 		subsubnode@0 {
 			compatible = "subsubnode2", "subsubnode";
-			prop-int = <abcd1234>;
+			prop-int = <0xabcd1234>;
 		};
 	};
 };
Index: dtc/tests/test_tree1_dts0.dts
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ dtc/tests/test_tree1_dts0.dts	2007-10-26 15:18:43.000000000 +1000
@@ -0,0 +1,27 @@
+/memreserve/ deadbeef00000000-deadbeef000fffff;
+/memreserve/ abcd1234 00001234;
+
+/ {
+	compatible = "test_tree1";
+	prop-int = <deadbeef>;
+	prop-str = "hello world";
+
+	subnode@1 {
+		compatible = "subnode1";
+		prop-int = <deadbeef>;
+
+		subsubnode {
+			compatible = "subsubnode1", "subsubnode";
+			prop-int = <deadbeef>;
+		};
+	};
+
+	subnode@2 {
+		prop-int = <abcd1234>;
+
+		subsubnode@0 {
+			compatible = "subsubnode2", "subsubnode";
+			prop-int = <abcd1234>;
+		};
+	};
+};


-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox