* Re: [PATCH 1/4] powerpc: More bootwrapper reorg
From: Paul Mackerras @ 2006-10-16 10:45 UTC (permalink / raw)
To: Mark A. Greer; +Cc: linuxppc-dev
In-Reply-To: <20061012013346.GB9143@mag.az.mvista.com>
Mark A. Greer writes:
> More reorganization of the bootwrapper:
> - Add dtb section to zImage
Unfortunately it doesn't build for powermac because zImage.coff.lds is
missing the _dtb_start/end symbols. Could you add the necessary bits
to zImage.coff.lds and resend?
Paul.
^ permalink raw reply
* Re: [PATCH 2/4] powerpc: Add flatdevtree source
From: Paul Mackerras @ 2006-10-16 10:46 UTC (permalink / raw)
To: Mark A. Greer; +Cc: linuxppc-dev
In-Reply-To: <20061012013427.GC9143@mag.az.mvista.com>
Mark A. Greer writes:
> Add the latest version of the flatdevtree code and corresponding glue.
Please resend with the fixes you posted subsequently applied. Same
for your patch 4/4.
Paul.
^ permalink raw reply
* RE: preempt crash in 2.6.18
From: Rune Torgersen @ 2006-10-16 13:50 UTC (permalink / raw)
To: Vitaly Bordug, Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <20061015132058.01c68605@localhost.localdomain>
[-- Attachment #1: Type: text/plain, Size: 1141 bytes --]
-----Original Message-----
From: Vitaly Bordug [mailto:vbordug@ru.mvista.com]
On Sat, 14 Oct 2006 09:14:38 +1000
Benjamin Herrenschmidt wrote:
> On Sat, 2006-10-14 at 01:21 +0400, Vitaly Bordug wrote:
> > On Fri, 13 Oct 2006 09:16:52 -0500
> > Rune Torgersen wrote:
> >
> > >
> > > This is from a Freescale 8265 running 2.6.18
> > > Anyone have any idea what this is and how to fix it?
> > >
> > Yes. Actually, I recall alike thing and used to fix with proper
> > spin-locking if the cascade PCI irq, which apparently does do_irq
> > that seems to confuse preempt counters.
> >
> > Just a pure guess.
>
> How so ? Cascades shouldn't do do_IRQ with the new irq code anyway
> unless this is still arch/ppc, they should do either __do_IRQ or
> better, generic_handle_irq().
>
To clarify - I was about __do_IRQ and arch/ppc.
Anyway, cascade for PCI is the first place I'd give a look.
In our case it turned out to be in the TIPC network code. post_timeout was called and didn't unlock a lock.
The patch had been in the TIPC tree for abpout 2 days when we saw the problem.
--
Sincerely,
-Vitaly
[-- Attachment #2: Type: text/html, Size: 1792 bytes --]
^ permalink raw reply
* Not know how to build image and user application from ELDK 4.0
From: tran vanle @ 2006-10-16 14:21 UTC (permalink / raw)
To: linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 437 bytes --]
Hi every one
I have just installed ELDK 4.0 for TQM 8xxL and read it README but I don't know how to build my custom image or adding user application.Such as I want to build ssh and openssh but I don't know where to start and how to do it step by step.
Every one who HAD did it please guide me step by step to do it
Thanks for all
---------------------------------
On Yahoo!7
PS Trixi: Check back weekly for Trixi's latest update
[-- Attachment #2: Type: text/html, Size: 547 bytes --]
^ permalink raw reply
* Re: kernel BUG in __cache_alloc_node at linux-2.6.git/mm/slab.c:3177!
From: Will Schmidt @ 2006-10-16 16:00 UTC (permalink / raw)
To: Christoph Lameter; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <Pine.LNX.4.64.0610131515200.28279@schroedinger.engr.sgi.com>
On Fri, 2006-13-10 at 15:22 -0700, Christoph Lameter wrote:
> Here is another fall back fix checking if the slab has already been setup
> for this node. MPOL_INTERLEAVE could redirect the allocation.
>
with this patch applied, a different error in the same area..
freeing bootmem node 0
freeing bootmem node 1
Memory: 530256k/557056k available (5508k kernel code, 30468k reserved,
2224k data, 543k bss, 244k init)
Kernel panic - not syncing: kmem_cache_create(): failed to create slab
`size-32'
> Index: linux-2.6.19-rc1-mm1/mm/slab.c
> ===================================================================
> --- linux-2.6.19-rc1-mm1.orig/mm/slab.c 2006-10-10 21:47:12.949563383 -0500
> +++ linux-2.6.19-rc1-mm1/mm/slab.c 2006-10-13 17:21:31.937863714 -0500
> @@ -3158,12 +3158,15 @@ void *fallback_alloc(struct kmem_cache *
> struct zone **z;
> void *obj = NULL;
>
> - for (z = zonelist->zones; *z && !obj; z++)
> + for (z = zonelist->zones; *z && !obj; z++) {
> + int nid = zone_to_nid(*z);
> +
> if (zone_idx(*z) <= ZONE_NORMAL &&
> - cpuset_zone_allowed(*z, flags))
> + cpuset_zone_allowed(*z, flags) &&
> + cache->nodelists[nid])
> obj = __cache_alloc_node(cache,
> - flags | __GFP_THISNODE,
> - zone_to_nid(*z));
> + flags | __GFP_THISNODE, nid);
> + }
> return obj;
> }
>
>
^ permalink raw reply
* Re: Recently removed io accessors
From: Linas Vepstas @ 2006-10-16 16:51 UTC (permalink / raw)
To: Peter Korsgaard; +Cc: linuxppc-dev, Paul Mackerras, sfr
In-Reply-To: <8764ent8j4.fsf@sleipner.barco.com>
On Sat, Oct 14, 2006 at 01:57:03PM +0200, Peter Korsgaard wrote:
> PM> code up a loop of readw (or equivalent) in the driver with a big
> PM> comment explaining why you need to do it that way.
>
> It doesn't have to be readw (16bit accesses). Enabling the BE mode and
> using _outsl/_insl (32bit access with byteswap) works fine.
I think Paul was trrying to say that it might be easier just to
16-bit words. Are you trying to use 32-bit access due to performance
concerns?
--linas
^ permalink raw reply
* Re: Failed to boot kernel 2.6.19-rc2 due to IBM veth problem.
From: Yao Fei Zhu @ 2006-10-16 17:44 UTC (permalink / raw)
To: David Gibson; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <20061016014334.GA30921@localhost.localdomain>
David Gibson 写道:
> On Mon, Oct 16, 2006 at 12:26:37AM +0800, Yao Fei Zhu wrote:
>
>>Hi, all,
>>
>>Boot kernel 2.6.19-rc2 on IBM System P5 partitions will fall into xmon.
>>Here is the boot log,
>
>
> This is probably the same bug I recently posted about. The patch
> below should fix it.
>
> ibmveth: Fix index increment calculation
>
> The recent commit 751ae21c6cd1493e3d0a4935b08fb298b9d89773 introduced
> a bug in the producer/consumer index calculation in the ibmveth driver
> - incautious use of the post-increment ++ operator resulted in an
> increment being immediately reverted. This patch corrects the logic.
>
> Without this patch, the driver oopses almost immediately after
> activation on at least some machines.
>
> Signed-off-by: David Gibson <dwg@au1.ibm.com>
>
> Index: working-2.6/drivers/net/ibmveth.c
> ===================================================================
> --- working-2.6.orig/drivers/net/ibmveth.c 2006-10-13 14:19:54.000000000 +1000
> +++ working-2.6/drivers/net/ibmveth.c 2006-10-13 14:19:59.000000000 +1000
> @@ -212,8 +212,8 @@ static void ibmveth_replenish_buffer_poo
> break;
> }
>
> - free_index = pool->consumer_index++ % pool->size;
> - pool->consumer_index = free_index;
> + free_index = pool->consumer_index;
> + pool->consumer_index = (pool->consumer_index + 1) % pool->size;
> index = pool->free_map[free_index];
>
> ibmveth_assert(index != IBM_VETH_INVALID_MAP);
> @@ -329,8 +329,10 @@ static void ibmveth_remove_buffer_from_p
> adapter->rx_buff_pool[pool].buff_size,
> DMA_FROM_DEVICE);
>
> - free_index = adapter->rx_buff_pool[pool].producer_index++ % adapter->rx_buff_pool[pool].size;
> - adapter->rx_buff_pool[pool].producer_index = free_index;
> + free_index = adapter->rx_buff_pool[pool].producer_index;
> + adapter->rx_buff_pool[pool].producer_index
> + = (adapter->rx_buff_pool[pool].producer_index + 1)
> + % adapter->rx_buff_pool[pool].size;
> adapter->rx_buff_pool[pool].free_map[free_index] = index;
>
> mb();
>
>
David, I have verified this fix, it works fine for me, Thanks. What's the status of it? Submitted?
^ permalink raw reply
* Re: RFC: qe lib code location?
From: Andy Fleming @ 2006-10-16 18:46 UTC (permalink / raw)
To: Dan Malek; +Cc: Li Yang, linuxppc-dev list, Kim Phillips
In-Reply-To: <713AF674-0689-4F20-9896-70696969ED24@embeddededge.com>
On Oct 3, 2006, at 12:30, Dan Malek wrote:
>
> On Oct 3, 2006, at 12:34 PM, Kumar Gala wrote:
>
>> I was wondering what peoples thought were on having the qe lib code
>> live in drivers/qe instead of sysdev/qe_lib (with the exception of
>> the interrupt controller code)
>
> My personal reason for choosing one place or the other
> is based upon usefulness to architectures other than PowerPC,
> or general kernel APIs that may change. If something is
> useful to architectures other than PowerPC, clearly it
> should go there. If the software has dependencies on
> general kernel APIs (networking is a good example), I like
> to put is there in hopes that someone changing the APIs
> will at least make an attempt to keep this code up to
> date as well.
>
> I think it neither of these apply (and I don't think the VM
> interfaces are a good argument because they generally
> affect the architecture ports anyway), then I think it
> should stay in a more architecture specific place.
My feeling here is that, all things being equal, drivers/ is better.
My reasoning is that, should Freescale decide to release a non-
powerpc chip with a QUICC Engine, having the code in drivers/ makes
this easier. It would also allow for some screwier implementations
(put an 8360 on a PCI card, and just use the QE directly from the
host processor). Of course, all of this is pure speculation, so if
there's a good reason *not* to put it in drivers/, we should probably
just maintain the status quo.
>
>
>> Yes, one can argue the cpm code should live in drivers/cpm by this
>> logic, but lets considered them grandfathered for now.
>
> I would say that based on my opinion above the cpm
> stuff should stay in sysdev, too. These are not only
> powerpc specific, but even Freescale embedded powerpc
> specific. I don't think that code belongs in drivers.
>
> Thanks.
>
> -- Dan
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* Re: Recently removed io accessors
From: Peter Korsgaard @ 2006-10-16 18:54 UTC (permalink / raw)
To: Linas Vepstas; +Cc: linuxppc-dev, Paul Mackerras, sfr
In-Reply-To: <20061016165140.GB6537@austin.ibm.com>
>>>>> "LV" == Linas Vepstas <linas@austin.ibm.com> writes:
Hi,
>> It doesn't have to be readw (16bit accesses). Enabling the BE mode
>> and using _outsl/_insl (32bit access with byteswap) works fine.
LV> I think Paul was trrying to say that it might be easier just to
LV> 16-bit words. Are you trying to use 32-bit access due to
LV> performance concerns?
Yes, this is the hot path of the driver as I don't have DMA hardware
(copy to/from packet buffer).
Another reason is that the same driver is used for the entire 911x
series, some which have an 16bit interface and others with full 32bit.
--
Bye, Peter Korsgaard
^ permalink raw reply
* Re: kernel BUG in __cache_alloc_node at linux-2.6.git/mm/slab.c:3177!
From: Will Schmidt @ 2006-10-16 19:20 UTC (permalink / raw)
To: Christoph Lameter; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <Pine.LNX.4.64.0610131515200.28279@schroedinger.engr.sgi.com>
Here is the content of /sys/devices/system/node/* and /proc/meminfo.
This is from the same partition, booted with a 2.6.16-ish distro
kernel.
notice that the node1/meminfo MemUsed value seems just a little bit
elevated. MemFree being larger than MemTotal seems a bit wrong too.
14:07:43 0 willschm@airbag2:~> find /sys/devices/system/node -type f
-print -exec cat {} \;
/sys/devices/system/node/node1/distance
20 10
/sys/devices/system/node/node1/numastat
numa_hit 6279
numa_miss 141588
numa_foreign 0
interleave_hit 5218
local_node 0
other_node 147867
/sys/devices/system/node/node1/meminfo
Node 1 MemTotal: 327680 kB
Node 1 MemFree: 435704 kB
Node 1 MemUsed: 18446744073709443592 kB
Node 1 Active: 41412 kB
Node 1 Inactive: 19976 kB
Node 1 HighTotal: 0 kB
Node 1 HighFree: 0 kB
Node 1 LowTotal: 327680 kB
Node 1 LowFree: 435704 kB
Node 1 Dirty: 0 kB
Node 1 Writeback: 0 kB
Node 1 Mapped: 0 kB
Node 1 Slab: 0 kB
Node 1 HugePages_Total: 0
Node 1 HugePages_Free: 0
/sys/devices/system/node/node1/cpumap
00000000,00000000,00000000,00000000
/sys/devices/system/node/node0/distance
10 20
/sys/devices/system/node/node0/numastat
numa_hit 0
numa_miss 0
numa_foreign 141749
interleave_hit 0
local_node 0
other_node 0
/sys/devices/system/node/node0/meminfo
Node 0 MemTotal: 229376 kB
Node 0 MemFree: 0 kB
Node 0 MemUsed: 229376 kB
Node 0 Active: 0 kB
Node 0 Inactive: 0 kB
Node 0 HighTotal: 0 kB
Node 0 HighFree: 0 kB
Node 0 LowTotal: 229376 kB
Node 0 LowFree: 0 kB
Node 0 Dirty: 8 kB
Node 0 Writeback: 0 kB
Node 0 Mapped: 33940 kB
Node 0 Slab: 25500 kB
Node 0 HugePages_Total: 0
Node 0 HugePages_Free: 0
/sys/devices/system/node/node0/cpumap
00000000,00000000,00000000,000000ff
---
14:07:45 0 willschm@airbag2:~> cat /proc/meminfo
MemTotal: 531628 kB
MemFree: 436000 kB
Buffers: 2880 kB
Cached: 35156 kB
SwapCached: 0 kB
Active: 41364 kB
Inactive: 19976 kB
HighTotal: 0 kB
HighFree: 0 kB
LowTotal: 531628 kB
LowFree: 436000 kB
SwapTotal: 803240 kB
SwapFree: 803240 kB
Dirty: 0 kB
Writeback: 0 kB
Mapped: 33776 kB
Slab: 25332 kB
CommitLimit: 1069052 kB
Committed_AS: 81980 kB
PageTables: 1088 kB
VmallocTotal: 8589934592 kB
VmallocUsed: 2560 kB
VmallocChunk: 8589931608 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
Hugepagesize: 16384 kB
^ permalink raw reply
* Re: Not know how to build image and user application from ELDK 4.0
From: Wolfgang Denk @ 2006-10-16 19:20 UTC (permalink / raw)
To: tran vanle; +Cc: linuxppc-embedded
In-Reply-To: <20061016142137.34580.qmail@web33007.mail.mud.yahoo.com>
In message <20061016142137.34580.qmail@web33007.mail.mud.yahoo.com> you wrote:
>
> I have just installed ELDK 4.0 for TQM 8xxL and read it README but I don't know how to build my custom image or adding user application.Such as I want to build ssh and openssh but I don't know where to start and how to do it step by step.
> Every one who HAD did it please guide me step by step to do it
I strongly recommend to read the extensive documentation that is
available at http://www.denx.de/wiki/view/DULG/Manual?stickboard=tqm8xxl
Also, I would like to point out that you should use ELDK 3.1.1 for
MPC8xx based systems like the TQM8xxL (that's the reason why the
TQM8xxL ships with ELDK 3.1.1 included on CDROM).
Best regards,
Wolfgang Denk
--
Software Engineering: Embedded and Realtime Systems, Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
A Perl script is correct if it's halfway readable and gets the job
done before your boss fires you.
- L. Wall & R. L. Schwartz, _Programming Perl_
^ permalink raw reply
* Re: kernel BUG in __cache_alloc_node at linux-2.6.git/mm/slab.c:3177!
From: Christoph Lameter @ 2006-10-16 19:25 UTC (permalink / raw)
To: Will Schmidt; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <1161026409.31903.15.camel@farscape>
On Mon, 16 Oct 2006, Will Schmidt wrote:
> Node 1 MemTotal: 327680 kB
> Node 1 MemFree: 435704 kB
Too big.
> Node 1 MemUsed: 18446744073709443592 kB
Memused is going negative?
> Node 1 Active: 41412 kB
> Node 1 Inactive: 19976 kB
> Node 1 HighTotal: 0 kB
> Node 1 HighFree: 0 kB
> Node 1 LowTotal: 327680 kB
> Node 1 LowFree: 435704 kB
> Node 1 Dirty: 0 kB
> Node 1 Writeback: 0 kB
> Node 1 Mapped: 0 kB
> Node 1 Slab: 0 kB
zero slab??? That cannot be. The slab allocator always allocs on each
node. Or is this <2.6.18 with the strange counters that we had before?
> Node 0 MemTotal: 229376 kB
> Node 0 MemFree: 0 kB
> Node 0 MemUsed: 229376 kB
Node 0 is filled up during bootup?
^ permalink raw reply
* [PATCH] fix ARCH=ppc timer_interrupt after global pt_regs
From: Peter Korsgaard @ 2006-10-16 19:30 UTC (permalink / raw)
To: paulus; +Cc: linuxppc-dev
Hi,
2.6.19-rc2 doesn't boot on arch/ppc (atleast of 4xx), because the
'global-pt_regs' megapatch forgot to fix up the arch/ppc
timer_interrupt handler. This patch fixes it.
Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
diff -urpN linux-2.6.19-rc2.orig/arch/ppc/kernel/time.c linux-2.6.19-rc2/arch/ppc/kernel/time.c
--- linux-2.6.19-rc2.orig/arch/ppc/kernel/time.c 2006-10-16 21:05:52.000000000 +0200
+++ linux-2.6.19-rc2/arch/ppc/kernel/time.c 2006-10-16 21:12:42.000000000 +0200
@@ -56,6 +56,7 @@
#include <linux/time.h>
#include <linux/init.h>
#include <linux/profile.h>
+#include <linux/irq.h>
#include <asm/io.h>
#include <asm/nvram.h>
@@ -129,6 +130,7 @@ void wakeup_decrementer(void)
*/
void timer_interrupt(struct pt_regs * regs)
{
+ struct pt_regs *old_regs;
int next_dec;
unsigned long cpu = smp_processor_id();
unsigned jiffy_stamp = last_jiffy_stamp(cpu);
@@ -137,6 +139,7 @@ void timer_interrupt(struct pt_regs * re
if (atomic_read(&ppc_n_lost_interrupts) != 0)
do_IRQ(regs);
+ old_regs = set_irq_regs(regs);
irq_enter();
while ((next_dec = tb_ticks_per_jiffy - tb_delta(&jiffy_stamp)) <= 0) {
@@ -188,6 +191,7 @@ void timer_interrupt(struct pt_regs * re
ppc_md.heartbeat();
irq_exit();
+ set_irq_regs(old_regs);
}
/*
--
Bye, Peter Korsgaard
^ permalink raw reply
* Re: [PATCH] Xilinx UART Lite 2.6.18 driver
From: Peter Korsgaard @ 2006-10-16 19:49 UTC (permalink / raw)
To: David H. Lynch Jr.; +Cc: linuxppc-embedded
In-Reply-To: <4532A1D1.4040006@dlasys.net>
>>>>> "David" == David H Lynch <dhlii@dlasys.net> writes:
Hi,
>> I'm still not convinced that DCR access and variable register
>> offsets are needed - But it can always be added (through a
>> seperate struct in platform_data) - Patches are welcome.
David> It does not matter whether you or I are convinced. It
David> matters whether there are people that need it. Xilinx has a
David> reference design that uses DCR. While I have never tripped
David> over an actual implimentation that uses DCR there are others
David> on this list that have.
Those people are welcome to add it then. Benh recently posted some
patches with a dcr abstraction that could probably make it pretty
clean to add.
David> Right now I can not get your driver to work. I spent alot
David> of time trying to fix it and got nowhere. I can not get it to
David> receive at all, and I can not get it to send after switching
David> from the console driver without dropping characters. I am very
David> busy with other things right now and it is going to be a long
David> time before I have time to look at your driver again.
Sorry to hear. We are using it in several designs without problems and
it also worked for Oluf. I'm afraid I won't be able to help you
anymore unless you provide more details.
David> But what matters is not whether the changes are intrusive,
David> but whether they produce a better result.
Sorry, I don't agree. Maintainability is very important.
David> I am glad somebody is using your driver and finding it
David> works. But we are all better served by fixing the failure
David> cases.
Yes, please do or provide enough details for me to reproduce it.
David> It is not particularly odd at all. The UartLite despite
David> its simplicity is worse than a normal driver - different FPGA
David> implimentations can vary. Normal drivers for fixed inflexible
David> hardware often do not work accross differing implimentations,
David> why would you expect something like UartLite to be invariant ?
It's no worse than Xilinx 8250 core. There's only 1 implementation of
the uarlite IP core - Xilinx's.
David> I would also ask what data rates you and others with
David> Working UartLites are using ? The cases I am dealing with run
David> at 57600 and 115200 respectively - it is not that odd for
David> driver problems to manifest themselves only or more frequently
David> at high baud rates.
We're using 115200 for most designs, but one design is using it at
1mbit.
David> Without being difficult - don't hold your breath. It is
David> something I would like to do, but I do not have infinite time.
Ok.
--
Bye, Peter Korsgaard
^ permalink raw reply
* Re: [PATCH] Xilinx UART Lite 2.6.18 driver
From: Peter Korsgaard @ 2006-10-16 19:52 UTC (permalink / raw)
To: linuxppc-embedded
In-Reply-To: <4532A1D1.4040006@dlasys.net>
>>>>> "David" == David H Lynch <dhlii@dlasys.net> writes:
Hi,
>> I'm still not convinced that DCR access and variable register
>> offsets are needed - But it can always be added (through a
>> seperate struct in platform_data) - Patches are welcome.
David> It does not matter whether you or I are convinced. It
David> matters whether there are people that need it. Xilinx has a
David> reference design that uses DCR. While I have never tripped
David> over an actual implimentation that uses DCR there are others
David> on this list that have.
Those people are welcome to add it then. Benh recently posted some
patches with a dcr abstraction that could probably make it pretty
clean to add. I don't have a DCR based design to do the implementation
and test, so it's pretty low on my priority list.
David> Right now I can not get your driver to work. I spent alot
David> of time trying to fix it and got nowhere. I can not get it to
David> receive at all, and I can not get it to send after switching
David> from the console driver without dropping characters. I am very
David> busy with other things right now and it is going to be a long
David> time before I have time to look at your driver again.
Sorry to hear. We are using it in several designs without problems and
it also worked for Oluf. I'm afraid I won't be able to help you
anymore unless you provide more details.
David> But what matters is not whether the changes are intrusive,
David> but whether they produce a better result.
Sorry, I don't agree. Maintainability is very important.
David> I am glad somebody is using your driver and finding it
David> works. But we are all better served by fixing the failure
David> cases.
Yes, please do or provide enough details for me to reproduce it.
David> It is not particularly odd at all. The UartLite despite
David> its simplicity is worse than a normal driver - different FPGA
David> implimentations can vary. Normal drivers for fixed inflexible
David> hardware often do not work accross differing implimentations,
David> why would you expect something like UartLite to be invariant ?
It's no worse than Xilinx 8250 core. There's only 1 implementation of
the uarlite IP core - Xilinx's.
David> I would also ask what data rates you and others with
David> Working UartLites are using ? The cases I am dealing with run
David> at 57600 and 115200 respectively - it is not that odd for
David> driver problems to manifest themselves only or more frequently
David> at high baud rates.
We're using 115200 for most designs, but one design is using it at
1mbit.
David> Without being difficult - don't hold your breath. It is
David> something I would like to do, but I do not have infinite time.
Ok.
--
Bye, Peter Korsgaard
^ permalink raw reply
* Re: [PATCH] fix ARCH=ppc timer_interrupt after global pt_regs
From: Josh Boyer @ 2006-10-16 20:05 UTC (permalink / raw)
To: Peter Korsgaard; +Cc: linuxppc-dev, paulus
In-Reply-To: <871wp8ukh0.fsf@sleipner.barco.com>
On Mon, 2006-10-16 at 21:30 +0200, Peter Korsgaard wrote:
> Hi,
>
> 2.6.19-rc2 doesn't boot on arch/ppc (atleast of 4xx), because the
> 'global-pt_regs' megapatch forgot to fix up the arch/ppc
> timer_interrupt handler. This patch fixes it.
Kumar Galak already fixed this on Oct 11 in the powerpc git tree.
Paul, could you send this fix to Linus soon please?
josh
^ permalink raw reply
* Re: [PATCH] fix ARCH=ppc timer_interrupt after global pt_regs
From: Peter Korsgaard @ 2006-10-16 20:18 UTC (permalink / raw)
To: Josh Boyer; +Cc: linuxppc-dev, paulus
In-Reply-To: <1161029148.3172.19.camel@zod.rchland.ibm.com>
>>>>> "JB" == Josh Boyer <jwboyer@linux.vnet.ibm.com> writes:
Hi,
JB> Kumar Galak already fixed this on Oct 11 in the powerpc git tree.
Ahh, I didn't notice.
JB> Paul, could you send this fix to Linus soon please?
Yes, please - I spend most of the morning tracking this down.
--
Bye, Peter Korsgaard
^ permalink raw reply
* Re: [PATCH] fix ARCH=ppc timer_interrupt after global pt_regs
From: Kumar Gala @ 2006-10-16 20:22 UTC (permalink / raw)
To: Peter Korsgaard; +Cc: linuxppc-dev, paulus
In-Reply-To: <87slhot3pe.fsf@sleipner.barco.com>
On Oct 16, 2006, at 3:18 PM, Peter Korsgaard wrote:
>>>>>> "JB" == Josh Boyer <jwboyer@linux.vnet.ibm.com> writes:
>
> Hi,
>
> JB> Kumar Galak already fixed this on Oct 11 in the powerpc git tree.
>
> Ahh, I didn't notice.
>
> JB> Paul, could you send this fix to Linus soon please?
>
> Yes, please - I spend most of the morning tracking this down.
Yeah, akpm picked up the patch for -mm.
- k
^ permalink raw reply
* Re: [PATCH] fix ARCH=ppc timer_interrupt after global pt_regs
From: Kumar Gala @ 2006-10-16 20:40 UTC (permalink / raw)
To: Kumar Gala; +Cc: Peter Korsgaard, paulus, linuxppc-dev
In-Reply-To: <0371C551-B535-4B95-81F3-8CC95C4FFC82@kernel.crashing.org>
On Oct 16, 2006, at 3:22 PM, Kumar Gala wrote:
>
> On Oct 16, 2006, at 3:18 PM, Peter Korsgaard wrote:
>
>>>>>>> "JB" == Josh Boyer <jwboyer@linux.vnet.ibm.com> writes:
>>
>> Hi,
>>
>> JB> Kumar Galak already fixed this on Oct 11 in the powerpc git tree.
>>
>> Ahh, I didn't notice.
>>
>> JB> Paul, could you send this fix to Linus soon please?
>>
>> Yes, please - I spend most of the morning tracking this down.
>
> Yeah, akpm picked up the patch for -mm.
Paul's got this in is powerpc.git tree now so it should go to Linus
on his next pull request.
- k
^ permalink raw reply
* Re: [PATCH 1/4] powerpc: More bootwrapper reorg
From: Mark A. Greer @ 2006-10-16 20:49 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <17715.25272.777558.66052@cargo.ozlabs.ibm.com>
On Mon, Oct 16, 2006 at 08:45:12PM +1000, Paul Mackerras wrote:
> Mark A. Greer writes:
>
> > More reorganization of the bootwrapper:
> > - Add dtb section to zImage
>
> Unfortunately it doesn't build for powermac because zImage.coff.lds is
> missing the _dtb_start/end symbols. Could you add the necessary bits
> to zImage.coff.lds and resend?
Sure. See below.
I did my best swag on zImage.coff.lds but I'm not a coff or lds expert so
please make sure that they're correct. I could compile pmac32_defconfig
with this patch.
The other patches will be on their way momentarily too.
Mark
---
More reorganization of the bootwrapper:
- Add dtb section to zImage
- ft_init now called by platform_init
- Pack a flat dt before calling kernel
- Remove size parameter from free
- printf only calls console_ops.write it its not NULL
- Some cleanup
Signed-off-by: Mark A. Greer <mgreer@mvista.com>
---
main.c | 27 ++++++---------------------
of.c | 8 +-------
ops.h | 25 ++++++++++++++-----------
stdio.c | 3 ++-
wrapper | 4 ++--
zImage.coff.lds.S | 4 ++++
zImage.lds.S | 5 +++++
7 files changed, 34 insertions(+), 42 deletions(-)
---
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c
index d719bb9..4184974 100644
--- a/arch/powerpc/boot/main.c
+++ b/arch/powerpc/boot/main.c
@@ -27,6 +27,8 @@ extern char _vmlinux_start[];
extern char _vmlinux_end[];
extern char _initrd_start[];
extern char _initrd_end[];
+extern char _dtb_start[];
+extern char _dtb_end[];
struct addr_range {
unsigned long addr;
@@ -250,10 +252,6 @@ #endif
flush_cache((void *)vmlinux.addr, vmlinux.size);
}
-void __attribute__ ((weak)) ft_init(void *dt_blob)
-{
-}
-
/* A buffer that may be edited by tools operating on a zImage binary so as to
* edit the command line passed to vmlinux (by setting /chosen/bootargs).
* The buffer is put in it's own section so that tools may locate it easier.
@@ -285,19 +283,12 @@ static void set_cmdline(char *buf)
setprop(devp, "bootargs", buf, strlen(buf) + 1);
}
-/* Section where ft can be tacked on after zImage is built */
-union blobspace {
- struct boot_param_header hdr;
- char space[8*1024];
-} dt_blob __attribute__((__section__("__builtin_ft")));
-
struct platform_ops platform_ops;
struct dt_ops dt_ops;
struct console_ops console_ops;
void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
{
- int have_dt = 0;
kernel_entry_t kentry;
char cmdline[COMMAND_LINE_SIZE];
@@ -306,15 +297,7 @@ void start(unsigned long a1, unsigned lo
memset(&dt_ops, 0, sizeof(dt_ops));
memset(&console_ops, 0, sizeof(console_ops));
- /* Override the dt_ops and device tree if there was an flat dev
- * tree attached to the zImage.
- */
- if (dt_blob.hdr.magic == OF_DT_HEADER) {
- have_dt = 1;
- ft_init(&dt_blob);
- }
-
- if (platform_init(promptr))
+ if (platform_init(promptr, _dtb_start, _dtb_end))
exit();
if (console_ops.open && (console_ops.open() < 0))
exit();
@@ -342,8 +325,10 @@ void start(unsigned long a1, unsigned lo
console_ops.close();
kentry = (kernel_entry_t) vmlinux.addr;
- if (have_dt)
+ if (_dtb_end > _dtb_start) {
+ dt_ops.ft_pack();
kentry(dt_ops.ft_addr(), 0, NULL);
+ }
else
/* XXX initrd addr/size should be passed in properties */
kentry(a1, a2, promptr);
diff --git a/arch/powerpc/boot/of.c b/arch/powerpc/boot/of.c
index 3a71845..0182f38 100644
--- a/arch/powerpc/boot/of.c
+++ b/arch/powerpc/boot/of.c
@@ -256,24 +256,18 @@ static void of_console_write(char *buf,
call_prom("write", 3, 1, of_stdout_handle, buf, len);
}
-int platform_init(void *promptr)
+int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end)
{
- platform_ops.fixups = NULL;
platform_ops.image_hdr = of_image_hdr;
platform_ops.malloc = of_try_claim;
- platform_ops.free = NULL;
platform_ops.exit = of_exit;
dt_ops.finddevice = of_finddevice;
dt_ops.getprop = of_getprop;
dt_ops.setprop = of_setprop;
- dt_ops.translate_addr = NULL;
console_ops.open = of_console_open;
console_ops.write = of_console_write;
- console_ops.edit_cmdline = NULL;
- console_ops.close = NULL;
- console_ops.data = NULL;
prom = (int (*)(void *))promptr;
return 0;
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h
index 135eb4b..59832fb 100644
--- a/arch/powerpc/boot/ops.h
+++ b/arch/powerpc/boot/ops.h
@@ -22,7 +22,8 @@ struct platform_ops {
void (*fixups)(void);
void (*image_hdr)(const void *);
void * (*malloc)(u32 size);
- void (*free)(void *ptr, u32 size);
+ void (*free)(void *ptr);
+ void * (*realloc)(void *ptr, unsigned long size);
void (*exit)(void);
};
extern struct platform_ops platform_ops;
@@ -30,12 +31,11 @@ extern struct platform_ops platform_ops;
/* Device Tree operations */
struct dt_ops {
void * (*finddevice)(const char *name);
- int (*getprop)(const void *node, const char *name, void *buf,
+ int (*getprop)(const void *phandle, const char *name, void *buf,
const int buflen);
- int (*setprop)(const void *node, const char *name,
+ int (*setprop)(const void *phandle, const char *name,
const void *buf, const int buflen);
- u64 (*translate_addr)(const char *path, const u32 *in_addr,
- const u32 addr_len);
+ void (*ft_pack)(void);
unsigned long (*ft_addr)(void);
};
extern struct dt_ops dt_ops;
@@ -59,10 +59,13 @@ struct serial_console_data {
void (*close)(void);
};
-extern int platform_init(void *promptr);
-extern void simple_alloc_init(void);
-extern void ft_init(void *dt_blob);
-extern int serial_console_init(void);
+int platform_init(void *promptr, char *dt_blob_start, char *dt_blob_end);
+int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device);
+int serial_console_init(void);
+int ns16550_console_init(void *devp, struct serial_console_data *scdp);
+void *simple_alloc_init(char *base, u32 heap_size, u32 granularity,
+ u32 max_allocs);
+
static inline void *finddevice(const char *name)
{
@@ -84,10 +87,10 @@ static inline void *malloc(u32 size)
return (platform_ops.malloc) ? platform_ops.malloc(size) : NULL;
}
-static inline void free(void *ptr, u32 size)
+static inline void free(void *ptr)
{
if (platform_ops.free)
- platform_ops.free(ptr, size);
+ platform_ops.free(ptr);
}
static inline void exit(void)
diff --git a/arch/powerpc/boot/stdio.c b/arch/powerpc/boot/stdio.c
index 6d5f638..0a9feeb 100644
--- a/arch/powerpc/boot/stdio.c
+++ b/arch/powerpc/boot/stdio.c
@@ -320,6 +320,7 @@ printf(const char *fmt, ...)
va_start(args, fmt);
n = vsprintf(sprint_buf, fmt, args);
va_end(args);
- console_ops.write(sprint_buf, n);
+ if (console_ops.write)
+ console_ops.write(sprint_buf, n);
return n;
}
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index eab7318..b5fb1fe 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -179,11 +179,11 @@ if [ -z "$cacheit" ]; then
fi
if [ -n "$initrd" ]; then
- addsec $tmp "$initrd" initrd
+ addsec $tmp "$initrd" $isection
fi
if [ -n "$dtb" ]; then
- addsec $tmp "$dtb" dtb
+ addsec $tmp "$dtb" .kernel:dtb
fi
if [ "$platform" != "miboot" ]; then
diff --git a/arch/powerpc/boot/zImage.coff.lds.S b/arch/powerpc/boot/zImage.coff.lds.S
index 05f3238..a360905 100644
--- a/arch/powerpc/boot/zImage.coff.lds.S
+++ b/arch/powerpc/boot/zImage.coff.lds.S
@@ -21,6 +21,10 @@ SECTIONS
*(.got2)
__got2_end = .;
+ _dtb_start = .;
+ *(.kernel:dtb)
+ _dtb_end = .;
+
_vmlinux_start = .;
*(.kernel:vmlinux.strip)
_vmlinux_end = .;
diff --git a/arch/powerpc/boot/zImage.lds.S b/arch/powerpc/boot/zImage.lds.S
index 4b6bb3f..4be3c64 100644
--- a/arch/powerpc/boot/zImage.lds.S
+++ b/arch/powerpc/boot/zImage.lds.S
@@ -21,6 +21,11 @@ SECTIONS
__got2_end = .;
}
+ . = ALIGN(8);
+ _dtb_start = .;
+ .kernel:dtb : { *(.kernel:dtb) }
+ _dtb_end = .;
+
. = ALIGN(4096);
_vmlinux_start = .;
.kernel:vmlinux.strip : { *(.kernel:vmlinux.strip) }
^ permalink raw reply related
* Re: [PATCH 2/4] powerpc: Add flatdevtree source
From: Mark A. Greer @ 2006-10-16 20:50 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <17715.25338.313368.506272@cargo.ozlabs.ibm.com>
On Mon, Oct 16, 2006 at 08:46:18PM +1000, Paul Mackerras wrote:
> Mark A. Greer writes:
>
> > Add the latest version of the flatdevtree code and corresponding glue.
>
> Please resend with the fixes you posted subsequently applied. Same
> for your patch 4/4.
Add the latest version of the flatdevtree code and corresponding glue.
A phandle table now tracks values returned by ft_find_device().
The value returned by ft_find_device() is a phandle which is really
an index into the phandle table. The phandle table contains the address
of the corresponding node. When the flat dt is edited/moved, the node
pointers in the phandle table are updated accordingly so no phandles kept
by the caller become stale.
Signed-off-by: Mark A. Greer <mgreer@mvista.com>
---
Makefile | 3
flatdevtree.c | 880 +++++++++++++++++++++++++++++++++++++++++++++++++++++
flatdevtree.h | 62 +++
flatdevtree_env.h | 47 ++
flatdevtree_misc.c | 56 +++
5 files changed, 1046 insertions(+), 2 deletions(-)
---
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 37ddfca..8660cc5 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -40,7 +40,8 @@ zliblinuxheader := zlib.h zconf.h zutil.
$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) \
$(addprefix $(obj)/,$(zlibheader))
-src-wlib := string.S stdio.c main.c div64.S $(zlib)
+src-wlib := string.S stdio.c main.c flatdevtree.c flatdevtree_misc.c div64.S \
+ $(zlib)
src-plat := of.c
src-boot := crt0.S $(src-wlib) $(src-plat) empty.c
diff --git a/arch/powerpc/boot/flatdevtree.c b/arch/powerpc/boot/flatdevtree.c
new file mode 100644
index 0000000..c76c194
--- /dev/null
+++ b/arch/powerpc/boot/flatdevtree.c
@@ -0,0 +1,880 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright Pantelis Antoniou 2006
+ * Copyright (C) IBM Corporation 2006
+ *
+ * Authors: Pantelis Antoniou <pantelis@embeddedalley.com>
+ * Hollis Blanchard <hollisb@us.ibm.com>
+ * Mark A. Greer <mgreer@mvista.com>
+ * Paul Mackerras <paulus@samba.org>
+ */
+
+#include <string.h>
+#include <stddef.h>
+#include "flatdevtree.h"
+#include "flatdevtree_env.h"
+
+#define _ALIGN(x, al) (((x) + (al) - 1) & ~((al) - 1))
+
+/* Routines for keeping node ptrs returned by ft_find_device current */
+/* First entry not used b/c it would return 0 and be taken as NULL/error */
+static void *ft_node_add(struct ft_cxt *cxt, char *node)
+{
+ unsigned int i;
+
+ for (i = 1; i < cxt->nodes_used; i++) /* already there? */
+ if (cxt->node_tbl[i] == node)
+ return (void *)i;
+
+ if (cxt->nodes_used < cxt->node_max) {
+ cxt->node_tbl[cxt->nodes_used] = node;
+ return (void *)cxt->nodes_used++;
+ }
+
+ return NULL;
+}
+
+static char *ft_node_ph2node(struct ft_cxt *cxt, const void *phandle)
+{
+ unsigned int i = (unsigned int)phandle;
+
+ if (i < cxt->nodes_used)
+ return cxt->node_tbl[i];
+ return NULL;
+}
+
+static void ft_node_update_before(struct ft_cxt *cxt, char *addr, int shift)
+{
+ unsigned int i;
+
+ if (shift == 0)
+ return;
+
+ for (i = 1; i < cxt->nodes_used; i++)
+ if (cxt->node_tbl[i] < addr)
+ cxt->node_tbl[i] += shift;
+}
+
+static void ft_node_update_after(struct ft_cxt *cxt, char *addr, int shift)
+{
+ unsigned int i;
+
+ if (shift == 0)
+ return;
+
+ for (i = 1; i < cxt->nodes_used; i++)
+ if (cxt->node_tbl[i] >= addr)
+ cxt->node_tbl[i] += shift;
+}
+
+/* Struct used to return info from ft_next() */
+struct ft_atom {
+ u32 tag;
+ const char *name;
+ void *data;
+ u32 size;
+};
+
+/* Set ptrs to current one's info; return addr of next one */
+static char *ft_next(struct ft_cxt *cxt, char *p, struct ft_atom *ret)
+{
+ u32 sz;
+
+ if (p >= cxt->rgn[FT_STRUCT].start + cxt->rgn[FT_STRUCT].size)
+ return NULL;
+
+ ret->tag = be32_to_cpu(*(u32 *) p);
+ p += 4;
+
+ switch (ret->tag) { /* Tag */
+ case OF_DT_BEGIN_NODE:
+ ret->name = p;
+ ret->data = (void *)(p - 4); /* start of node */
+ p += _ALIGN(strlen(p) + 1, 4);
+ break;
+ case OF_DT_PROP:
+ ret->size = sz = be32_to_cpu(*(u32 *) p);
+ ret->name = cxt->str_anchor + be32_to_cpu(*(u32 *) (p + 4));
+ ret->data = (void *)(p + 8);
+ p += 8 + _ALIGN(sz, 4);
+ break;
+ case OF_DT_END_NODE:
+ case OF_DT_NOP:
+ break;
+ case OF_DT_END:
+ default:
+ p = NULL;
+ break;
+ }
+
+ return p;
+}
+
+#define HDR_SIZE _ALIGN(sizeof(struct boot_param_header), 8)
+#define EXPAND_INCR 1024 /* alloc this much extra when expanding */
+
+/* See if the regions are in the standard order and non-overlapping */
+static int ft_ordered(struct ft_cxt *cxt)
+{
+ char *p = (char *)cxt->bph + HDR_SIZE;
+ enum ft_rgn_id r;
+
+ for (r = FT_RSVMAP; r <= FT_STRINGS; ++r) {
+ if (p > cxt->rgn[r].start)
+ return 0;
+ p = cxt->rgn[r].start + cxt->rgn[r].size;
+ }
+ return p <= (char *)cxt->bph + cxt->max_size;
+}
+
+/* Copy the tree to a newly-allocated region and put things in order */
+static int ft_reorder(struct ft_cxt *cxt, int nextra)
+{
+ unsigned long tot;
+ enum ft_rgn_id r;
+ char *p, *pend;
+ int stroff;
+
+ tot = HDR_SIZE + EXPAND_INCR;
+ for (r = FT_RSVMAP; r <= FT_STRINGS; ++r)
+ tot += cxt->rgn[r].size;
+ if (nextra > 0)
+ tot += nextra;
+ tot = _ALIGN(tot, 8);
+
+ if (!cxt->realloc)
+ return 0;
+ p = cxt->realloc(NULL, tot);
+ if (!p)
+ return 0;
+
+ memcpy(p, cxt->bph, sizeof(struct boot_param_header));
+ /* offsets get fixed up later */
+
+ cxt->bph = (struct boot_param_header *)p;
+ cxt->max_size = tot;
+ pend = p + tot;
+ p += HDR_SIZE;
+
+ memcpy(p, cxt->rgn[FT_RSVMAP].start, cxt->rgn[FT_RSVMAP].size);
+ cxt->rgn[FT_RSVMAP].start = p;
+ p += cxt->rgn[FT_RSVMAP].size;
+
+ memcpy(p, cxt->rgn[FT_STRUCT].start, cxt->rgn[FT_STRUCT].size);
+ ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start,
+ p - cxt->rgn[FT_STRUCT].start);
+ cxt->p += p - cxt->rgn[FT_STRUCT].start;
+ cxt->rgn[FT_STRUCT].start = p;
+
+ p = pend - cxt->rgn[FT_STRINGS].size;
+ memcpy(p, cxt->rgn[FT_STRINGS].start, cxt->rgn[FT_STRINGS].size);
+ stroff = cxt->str_anchor - cxt->rgn[FT_STRINGS].start;
+ cxt->rgn[FT_STRINGS].start = p;
+ cxt->str_anchor = p + stroff;
+
+ cxt->isordered = 1;
+ return 1;
+}
+
+static inline char *prev_end(struct ft_cxt *cxt, enum ft_rgn_id r)
+{
+ if (r > FT_RSVMAP)
+ return cxt->rgn[r - 1].start + cxt->rgn[r - 1].size;
+ return (char *)cxt->bph + HDR_SIZE;
+}
+
+static inline char *next_start(struct ft_cxt *cxt, enum ft_rgn_id r)
+{
+ if (r < FT_STRINGS)
+ return cxt->rgn[r + 1].start;
+ return (char *)cxt->bph + cxt->max_size;
+}
+
+/*
+ * See if we can expand region rgn by nextra bytes by using up
+ * free space after or before the region.
+ */
+static int ft_shuffle(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn,
+ int nextra)
+{
+ char *p = *pp;
+ char *rgn_start, *rgn_end;
+
+ rgn_start = cxt->rgn[rgn].start;
+ rgn_end = rgn_start + cxt->rgn[rgn].size;
+ if (nextra <= 0 || rgn_end + nextra <= next_start(cxt, rgn)) {
+ /* move following stuff */
+ if (p < rgn_end) {
+ if (nextra < 0)
+ memmove(p, p - nextra, rgn_end - p + nextra);
+ else
+ memmove(p + nextra, p, rgn_end - p);
+ if (rgn == FT_STRUCT)
+ ft_node_update_after(cxt, p, nextra);
+ }
+ cxt->rgn[rgn].size += nextra;
+ if (rgn == FT_STRINGS)
+ /* assumes strings only added at beginning */
+ cxt->str_anchor += nextra;
+ return 1;
+ }
+ if (prev_end(cxt, rgn) <= rgn_start - nextra) {
+ /* move preceding stuff */
+ if (p > rgn_start) {
+ memmove(rgn_start - nextra, rgn_start, p - rgn_start);
+ if (rgn == FT_STRUCT)
+ ft_node_update_before(cxt, p, -nextra);
+ }
+ *p -= nextra;
+ cxt->rgn[rgn].start -= nextra;
+ cxt->rgn[rgn].size += nextra;
+ return 1;
+ }
+ return 0;
+}
+
+static int ft_make_space(struct ft_cxt *cxt, char **pp, enum ft_rgn_id rgn,
+ int nextra)
+{
+ unsigned long size, ssize, tot;
+ char *str, *next;
+ enum ft_rgn_id r;
+
+ if (!cxt->isordered && !ft_reorder(cxt, nextra))
+ return 0;
+ if (ft_shuffle(cxt, pp, rgn, nextra))
+ return 1;
+
+ /* See if there is space after the strings section */
+ ssize = cxt->rgn[FT_STRINGS].size;
+ if (cxt->rgn[FT_STRINGS].start + ssize
+ < (char *)cxt->bph + cxt->max_size) {
+ /* move strings up as far as possible */
+ str = (char *)cxt->bph + cxt->max_size - ssize;
+ cxt->str_anchor += str - cxt->rgn[FT_STRINGS].start;
+ memmove(str, cxt->rgn[FT_STRINGS].start, ssize);
+ cxt->rgn[FT_STRINGS].start = str;
+ /* enough space now? */
+ if (rgn >= FT_STRUCT && ft_shuffle(cxt, pp, rgn, nextra))
+ return 1;
+ }
+
+ /* how much total free space is there following this region? */
+ tot = 0;
+ for (r = rgn; r < FT_STRINGS; ++r) {
+ char *r_end = cxt->rgn[r].start + cxt->rgn[r].size;
+ tot += next_start(cxt, rgn) - r_end;
+ }
+
+ /* cast is to shut gcc up; we know nextra >= 0 */
+ if (tot < (unsigned int)nextra) {
+ /* have to reallocate */
+ char *newp, *new_start;
+ int shift;
+
+ if (!cxt->realloc)
+ return 0;
+ size = _ALIGN(cxt->max_size + (nextra - tot) + EXPAND_INCR, 8);
+ newp = cxt->realloc(cxt->bph, size);
+ if (!newp)
+ return 0;
+ cxt->max_size = size;
+ shift = newp - (char *)cxt->bph;
+
+ if (shift) { /* realloc can return same addr */
+ cxt->bph = (struct boot_param_header *)newp;
+ ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start,
+ shift);
+ for (r = FT_RSVMAP; r <= FT_STRINGS; ++r) {
+ new_start = cxt->rgn[r].start + shift;
+ cxt->rgn[r].start = new_start;
+ }
+ *pp += shift;
+ cxt->str_anchor += shift;
+ }
+
+ /* move strings up to the end */
+ str = newp + size - ssize;
+ cxt->str_anchor += str - cxt->rgn[FT_STRINGS].start;
+ memmove(str, cxt->rgn[FT_STRINGS].start, ssize);
+ cxt->rgn[FT_STRINGS].start = str;
+
+ if (ft_shuffle(cxt, pp, rgn, nextra))
+ return 1;
+ }
+
+ /* must be FT_RSVMAP and we need to move FT_STRUCT up */
+ if (rgn == FT_RSVMAP) {
+ next = cxt->rgn[FT_RSVMAP].start + cxt->rgn[FT_RSVMAP].size
+ + nextra;
+ ssize = cxt->rgn[FT_STRUCT].size;
+ if (next + ssize >= cxt->rgn[FT_STRINGS].start)
+ return 0; /* "can't happen" */
+ memmove(next, cxt->rgn[FT_STRUCT].start, ssize);
+ ft_node_update_after(cxt, cxt->rgn[FT_STRUCT].start, nextra);
+ cxt->rgn[FT_STRUCT].start = next;
+
+ if (ft_shuffle(cxt, pp, rgn, nextra))
+ return 1;
+ }
+
+ return 0; /* "can't happen" */
+}
+
+static void ft_put_word(struct ft_cxt *cxt, u32 v)
+{
+ *(u32 *) cxt->p = cpu_to_be32(v);
+ cxt->p += 4;
+}
+
+static void ft_put_bin(struct ft_cxt *cxt, const void *data, unsigned int sz)
+{
+ unsigned long sza = _ALIGN(sz, 4);
+
+ /* zero out the alignment gap if necessary */
+ if (sz < sza)
+ *(u32 *) (cxt->p + sza - 4) = 0;
+
+ /* copy in the data */
+ memcpy(cxt->p, data, sz);
+
+ cxt->p += sza;
+}
+
+int ft_begin_node(struct ft_cxt *cxt, const char *name)
+{
+ unsigned long nlen = strlen(name) + 1;
+ unsigned long len = 8 + _ALIGN(nlen, 4);
+
+ if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, len))
+ return -1;
+ ft_put_word(cxt, OF_DT_BEGIN_NODE);
+ ft_put_bin(cxt, name, strlen(name) + 1);
+ return 0;
+}
+
+void ft_end_node(struct ft_cxt *cxt)
+{
+ ft_put_word(cxt, OF_DT_END_NODE);
+}
+
+void ft_nop(struct ft_cxt *cxt)
+{
+ if (ft_make_space(cxt, &cxt->p, FT_STRUCT, 4))
+ ft_put_word(cxt, OF_DT_NOP);
+}
+
+#define NO_STRING 0x7fffffff
+
+static int lookup_string(struct ft_cxt *cxt, const char *name)
+{
+ char *p, *end;
+
+ p = cxt->rgn[FT_STRINGS].start;
+ end = p + cxt->rgn[FT_STRINGS].size;
+ while (p < end) {
+ if (strcmp(p, (char *)name) == 0)
+ return p - cxt->str_anchor;
+ p += strlen(p) + 1;
+ }
+
+ return NO_STRING;
+}
+
+/* lookup string and insert if not found */
+static int map_string(struct ft_cxt *cxt, const char *name)
+{
+ int off;
+ char *p;
+
+ off = lookup_string(cxt, name);
+ if (off != NO_STRING)
+ return off;
+ p = cxt->rgn[FT_STRINGS].start;
+ if (!ft_make_space(cxt, &p, FT_STRINGS, strlen(name) + 1))
+ return NO_STRING;
+ strcpy(p, name);
+ return p - cxt->str_anchor;
+}
+
+int ft_prop(struct ft_cxt *cxt, const char *name, const void *data,
+ unsigned int sz)
+{
+ int off, len;
+
+ off = lookup_string(cxt, name);
+ if (off == NO_STRING)
+ return -1;
+
+ len = 12 + _ALIGN(sz, 4);
+ if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, len))
+ return -1;
+
+ ft_put_word(cxt, OF_DT_PROP);
+ ft_put_word(cxt, sz);
+ ft_put_word(cxt, off);
+ ft_put_bin(cxt, data, sz);
+ return 0;
+}
+
+int ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str)
+{
+ return ft_prop(cxt, name, str, strlen(str) + 1);
+}
+
+int ft_prop_int(struct ft_cxt *cxt, const char *name, unsigned int val)
+{
+ u32 v = cpu_to_be32((u32) val);
+
+ return ft_prop(cxt, name, &v, 4);
+}
+
+/* Calculate the size of the reserved map */
+static unsigned long rsvmap_size(struct ft_cxt *cxt)
+{
+ struct ft_reserve *res;
+
+ res = (struct ft_reserve *)cxt->rgn[FT_RSVMAP].start;
+ while (res->start || res->len)
+ ++res;
+ return (char *)(res + 1) - cxt->rgn[FT_RSVMAP].start;
+}
+
+/* Calculate the size of the struct region by stepping through it */
+static unsigned long struct_size(struct ft_cxt *cxt)
+{
+ char *p = cxt->rgn[FT_STRUCT].start;
+ char *next;
+ struct ft_atom atom;
+
+ /* make check in ft_next happy */
+ if (cxt->rgn[FT_STRUCT].size == 0)
+ cxt->rgn[FT_STRUCT].size = 0xfffffffful - (unsigned long)p;
+
+ while ((next = ft_next(cxt, p, &atom)) != NULL)
+ p = next;
+ return p + 4 - cxt->rgn[FT_STRUCT].start;
+}
+
+/* add `adj' on to all string offset values in the struct area */
+static void adjust_string_offsets(struct ft_cxt *cxt, int adj)
+{
+ char *p = cxt->rgn[FT_STRUCT].start;
+ char *next;
+ struct ft_atom atom;
+ int off;
+
+ while ((next = ft_next(cxt, p, &atom)) != NULL) {
+ if (atom.tag == OF_DT_PROP) {
+ off = be32_to_cpu(*(u32 *) (p + 8));
+ *(u32 *) (p + 8) = cpu_to_be32(off + adj);
+ }
+ p = next;
+ }
+}
+
+/* start construction of the flat OF tree from scratch */
+void ft_begin(struct ft_cxt *cxt, void *blob, unsigned int max_size,
+ void *(*realloc_fn) (void *, unsigned long))
+{
+ struct boot_param_header *bph = blob;
+ char *p;
+ struct ft_reserve *pres;
+
+ /* clear the cxt */
+ memset(cxt, 0, sizeof(*cxt));
+
+ cxt->bph = bph;
+ cxt->max_size = max_size;
+ cxt->realloc = realloc_fn;
+ cxt->isordered = 1;
+
+ /* zero everything in the header area */
+ memset(bph, 0, sizeof(*bph));
+
+ bph->magic = cpu_to_be32(OF_DT_HEADER);
+ bph->version = cpu_to_be32(0x10);
+ bph->last_comp_version = cpu_to_be32(0x10);
+
+ /* start pointers */
+ cxt->rgn[FT_RSVMAP].start = p = blob + HDR_SIZE;
+ cxt->rgn[FT_RSVMAP].size = sizeof(struct ft_reserve);
+ pres = (struct ft_reserve *)p;
+ cxt->rgn[FT_STRUCT].start = p += sizeof(struct ft_reserve);
+ cxt->rgn[FT_STRUCT].size = 4;
+ cxt->rgn[FT_STRINGS].start = blob + max_size;
+ cxt->rgn[FT_STRINGS].size = 0;
+
+ /* init rsvmap and struct */
+ pres->start = 0;
+ pres->len = 0;
+ *(u32 *) p = cpu_to_be32(OF_DT_END);
+
+ cxt->str_anchor = blob;
+}
+
+/* open up an existing blob to be examined or modified */
+int ft_open(struct ft_cxt *cxt, void *blob, unsigned int max_size,
+ unsigned int max_find_device,
+ void *(*realloc_fn) (void *, unsigned long))
+{
+ struct boot_param_header *bph = blob;
+
+ /* can't cope with version < 16 */
+ if (be32_to_cpu(bph->version) < 16)
+ return -1;
+
+ /* clear the cxt */
+ memset(cxt, 0, sizeof(*cxt));
+
+ /* alloc node_tbl to track node ptrs returned by ft_find_device */
+ ++max_find_device;
+ cxt->node_tbl = realloc_fn(NULL, max_find_device * sizeof(char *));
+ if (!cxt->node_tbl)
+ return -1;
+ memset(cxt->node_tbl, 0, max_find_device * sizeof(char *));
+ cxt->node_max = max_find_device;
+ cxt->nodes_used = 1; /* don't use idx 0 b/c looks like NULL */
+
+ cxt->bph = bph;
+ cxt->max_size = max_size;
+ cxt->realloc = realloc_fn;
+
+ cxt->rgn[FT_RSVMAP].start = blob + be32_to_cpu(bph->off_mem_rsvmap);
+ cxt->rgn[FT_RSVMAP].size = rsvmap_size(cxt);
+ cxt->rgn[FT_STRUCT].start = blob + be32_to_cpu(bph->off_dt_struct);
+ cxt->rgn[FT_STRUCT].size = struct_size(cxt);
+ cxt->rgn[FT_STRINGS].start = blob + be32_to_cpu(bph->off_dt_strings);
+ cxt->rgn[FT_STRINGS].size = be32_to_cpu(bph->dt_strings_size);
+ /* Leave as '0' to force first ft_make_space call to do a ft_reorder
+ * and move dt to an area allocated by realloc.
+ cxt->isordered = ft_ordered(cxt);
+ */
+
+ cxt->p = cxt->rgn[FT_STRUCT].start;
+ cxt->str_anchor = cxt->rgn[FT_STRINGS].start;
+
+ return 0;
+}
+
+/* add a reserver physical area to the rsvmap */
+int ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size)
+{
+ char *p;
+ struct ft_reserve *pres;
+
+ p = cxt->rgn[FT_RSVMAP].start + cxt->rgn[FT_RSVMAP].size
+ - sizeof(struct ft_reserve);
+ if (!ft_make_space(cxt, &p, FT_RSVMAP, sizeof(struct ft_reserve)))
+ return -1;
+
+ pres = (struct ft_reserve *)p;
+ pres->start = cpu_to_be64(physaddr);
+ pres->len = cpu_to_be64(size);
+
+ return 0;
+}
+
+void ft_begin_tree(struct ft_cxt *cxt)
+{
+ cxt->p = cxt->rgn[FT_STRUCT].start;
+}
+
+void ft_end_tree(struct ft_cxt *cxt)
+{
+ struct boot_param_header *bph = cxt->bph;
+ char *p, *oldstr, *str, *endp;
+ unsigned long ssize;
+ int adj;
+
+ if (!cxt->isordered)
+ return; /* we haven't touched anything */
+
+ /* adjust string offsets */
+ oldstr = cxt->rgn[FT_STRINGS].start;
+ adj = cxt->str_anchor - oldstr;
+ if (adj)
+ adjust_string_offsets(cxt, adj);
+
+ /* make strings end on 8-byte boundary */
+ ssize = cxt->rgn[FT_STRINGS].size;
+ endp = (char *)_ALIGN((unsigned long)cxt->rgn[FT_STRUCT].start
+ + cxt->rgn[FT_STRUCT].size + ssize, 8);
+ str = endp - ssize;
+
+ /* move strings down to end of structs */
+ memmove(str, oldstr, ssize);
+ cxt->str_anchor = str;
+ cxt->rgn[FT_STRINGS].start = str;
+
+ /* fill in header fields */
+ p = (char *)bph;
+ bph->totalsize = cpu_to_be32(endp - p);
+ bph->off_mem_rsvmap = cpu_to_be32(cxt->rgn[FT_RSVMAP].start - p);
+ bph->off_dt_struct = cpu_to_be32(cxt->rgn[FT_STRUCT].start - p);
+ bph->off_dt_strings = cpu_to_be32(cxt->rgn[FT_STRINGS].start - p);
+ bph->dt_strings_size = cpu_to_be32(ssize);
+}
+
+void *ft_find_device(struct ft_cxt *cxt, const char *srch_path)
+{
+ char *node;
+
+ /* require absolute path */
+ if (srch_path[0] != '/')
+ return NULL;
+ node = ft_find_descendent(cxt, cxt->rgn[FT_STRUCT].start, srch_path);
+ return ft_node_add(cxt, node);
+}
+
+void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path)
+{
+ struct ft_atom atom;
+ char *p;
+ const char *cp, *q;
+ int cl;
+ int depth = -1;
+ int dmatch = 0;
+ const char *path_comp[FT_MAX_DEPTH];
+
+ cp = srch_path;
+ cl = 0;
+ p = top;
+
+ while ((p = ft_next(cxt, p, &atom)) != NULL) {
+ switch (atom.tag) {
+ case OF_DT_BEGIN_NODE:
+ ++depth;
+ if (depth != dmatch)
+ break;
+ cxt->genealogy[depth] = atom.data;
+ cxt->genealogy[depth + 1] = NULL;
+ if (depth && !(strncmp(atom.name, cp, cl) == 0
+ && (atom.name[cl] == '/'
+ || atom.name[cl] == '\0'
+ || atom.name[cl] == '@')))
+ break;
+ path_comp[dmatch] = cp;
+ /* it matches so far, advance to next path component */
+ cp += cl;
+ /* skip slashes */
+ while (*cp == '/')
+ ++cp;
+ /* we're done if this is the end of the string */
+ if (*cp == 0)
+ return atom.data;
+ /* look for end of this component */
+ q = strchr(cp, '/');
+ if (q)
+ cl = q - cp;
+ else
+ cl = strlen(cp);
+ ++dmatch;
+ break;
+ case OF_DT_END_NODE:
+ if (depth == 0)
+ return NULL;
+ if (dmatch > depth) {
+ --dmatch;
+ cl = cp - path_comp[dmatch] - 1;
+ cp = path_comp[dmatch];
+ while (cl > 0 && cp[cl - 1] == '/')
+ --cl;
+ }
+ --depth;
+ break;
+ }
+ }
+ return NULL;
+}
+
+void *ft_get_parent(struct ft_cxt *cxt, const void *phandle)
+{
+ void *node;
+ int d;
+ struct ft_atom atom;
+ char *p;
+
+ node = ft_node_ph2node(cxt, phandle);
+ if (node == NULL)
+ return NULL;
+
+ for (d = 0; cxt->genealogy[d] != NULL; ++d)
+ if (cxt->genealogy[d] == node)
+ return cxt->genealogy[d > 0 ? d - 1 : 0];
+
+ /* have to do it the hard way... */
+ p = cxt->rgn[FT_STRUCT].start;
+ d = 0;
+ while ((p = ft_next(cxt, p, &atom)) != NULL) {
+ switch (atom.tag) {
+ case OF_DT_BEGIN_NODE:
+ cxt->genealogy[d] = atom.data;
+ if (node == atom.data) {
+ /* found it */
+ cxt->genealogy[d + 1] = NULL;
+ return d > 0 ? cxt->genealogy[d - 1] : node;
+ }
+ ++d;
+ break;
+ case OF_DT_END_NODE:
+ --d;
+ break;
+ }
+ }
+ return NULL;
+}
+
+int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
+ void *buf, const unsigned int buflen)
+{
+ struct ft_atom atom;
+ void *node;
+ char *p;
+ int depth;
+ unsigned int size;
+
+ node = ft_node_ph2node(cxt, phandle);
+ if (node == NULL)
+ return -1;
+
+ depth = 0;
+ p = (char *)node;
+
+ while ((p = ft_next(cxt, p, &atom)) != NULL) {
+ switch (atom.tag) {
+ case OF_DT_BEGIN_NODE:
+ ++depth;
+ break;
+ case OF_DT_PROP:
+ if ((depth != 1) || strcmp(atom.name, propname))
+ break;
+ size = min(atom.size, buflen);
+ memcpy(buf, atom.data, size);
+ return atom.size;
+ case OF_DT_END_NODE:
+ if (--depth <= 0)
+ return -1;
+ }
+ }
+ return -1;
+}
+
+int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
+ const void *buf, const unsigned int buflen)
+{
+ struct ft_atom atom;
+ void *node;
+ char *p, *next;
+ int nextra, depth;
+
+ node = ft_node_ph2node(cxt, phandle);
+ if (node == NULL)
+ return -1;
+
+ depth = 0;
+ p = node;
+
+ while ((next = ft_next(cxt, p, &atom)) != NULL) {
+ switch (atom.tag) {
+ case OF_DT_BEGIN_NODE:
+ ++depth;
+ break;
+ case OF_DT_END_NODE:
+ if (--depth > 0)
+ break;
+ /* haven't found the property, insert here */
+ cxt->p = p;
+ return ft_prop(cxt, propname, buf, buflen);
+ case OF_DT_PROP:
+ if ((depth != 1) || strcmp(atom.name, propname))
+ break;
+ /* found an existing property, overwrite it */
+ nextra = _ALIGN(buflen, 4) - _ALIGN(atom.size, 4);
+ cxt->p = atom.data;
+ if (nextra && !ft_make_space(cxt, &cxt->p, FT_STRUCT,
+ nextra))
+ return -1;
+ *(u32 *) (cxt->p - 8) = cpu_to_be32(buflen);
+ ft_put_bin(cxt, buf, buflen);
+ return 0;
+ }
+ p = next;
+ }
+ return -1;
+}
+
+int ft_del_prop(struct ft_cxt *cxt, const void *phandle, const char *propname)
+{
+ struct ft_atom atom;
+ void *node;
+ char *p, *next;
+ int size;
+
+ node = ft_node_ph2node(cxt, phandle);
+ if (node == NULL)
+ return -1;
+
+ p = node;
+ while ((next = ft_next(cxt, p, &atom)) != NULL) {
+ switch (atom.tag) {
+ case OF_DT_BEGIN_NODE:
+ case OF_DT_END_NODE:
+ return -1;
+ case OF_DT_PROP:
+ if (strcmp(atom.name, propname))
+ break;
+ /* found the property, remove it */
+ size = 12 + -_ALIGN(atom.size, 4);
+ cxt->p = p;
+ if (!ft_make_space(cxt, &cxt->p, FT_STRUCT, -size))
+ return -1;
+ return 0;
+ }
+ p = next;
+ }
+ return -1;
+}
+
+void *ft_create_node(struct ft_cxt *cxt, const void *parent, const char *path)
+{
+ struct ft_atom atom;
+ char *p, *next;
+ int depth = 0;
+
+ p = cxt->rgn[FT_STRUCT].start;
+ while ((next = ft_next(cxt, p, &atom)) != NULL) {
+ switch (atom.tag) {
+ case OF_DT_BEGIN_NODE:
+ ++depth;
+ if (depth == 1 && strcmp(atom.name, path) == 0)
+ /* duplicate node path, return error */
+ return NULL;
+ break;
+ case OF_DT_END_NODE:
+ --depth;
+ if (depth > 0)
+ break;
+ /* end of node, insert here */
+ cxt->p = p;
+ ft_begin_node(cxt, path);
+ ft_end_node(cxt);
+ return p;
+ }
+ p = next;
+ }
+ return NULL;
+}
diff --git a/arch/powerpc/boot/flatdevtree.h b/arch/powerpc/boot/flatdevtree.h
index 761c8dc..b9cd9f6 100644
--- a/arch/powerpc/boot/flatdevtree.h
+++ b/arch/powerpc/boot/flatdevtree.h
@@ -17,7 +17,7 @@
#ifndef FLATDEVTREE_H
#define FLATDEVTREE_H
-#include "types.h"
+#include "flatdevtree_env.h"
/* Definitions used by the flattened device tree */
#define OF_DT_HEADER 0xd00dfeed /* marker */
@@ -43,4 +43,64 @@ struct boot_param_header {
u32 dt_strings_size; /* size of the DT strings block */
};
+struct ft_reserve {
+ u64 start;
+ u64 len;
+};
+
+struct ft_region {
+ char *start;
+ unsigned long size;
+};
+
+enum ft_rgn_id {
+ FT_RSVMAP,
+ FT_STRUCT,
+ FT_STRINGS,
+ FT_N_REGION
+};
+
+#define FT_MAX_DEPTH 50
+
+struct ft_cxt {
+ struct boot_param_header *bph;
+ int max_size; /* maximum size of tree */
+ int isordered; /* everything in standard order */
+ void *(*realloc)(void *, unsigned long);
+ char *str_anchor;
+ char *p; /* current insertion point in structs */
+ struct ft_region rgn[FT_N_REGION];
+ void *genealogy[FT_MAX_DEPTH+1];
+ char **node_tbl;
+ unsigned int node_max;
+ unsigned int nodes_used;
+};
+
+int ft_begin_node(struct ft_cxt *cxt, const char *name);
+void ft_end_node(struct ft_cxt *cxt);
+
+void ft_begin_tree(struct ft_cxt *cxt);
+void ft_end_tree(struct ft_cxt *cxt);
+
+void ft_nop(struct ft_cxt *cxt);
+int ft_prop(struct ft_cxt *cxt, const char *name,
+ const void *data, unsigned int sz);
+int ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str);
+int ft_prop_int(struct ft_cxt *cxt, const char *name, unsigned int val);
+void ft_begin(struct ft_cxt *cxt, void *blob, unsigned int max_size,
+ void *(*realloc_fn)(void *, unsigned long));
+int ft_open(struct ft_cxt *cxt, void *blob, unsigned int max_size,
+ unsigned int max_find_device,
+ void *(*realloc_fn)(void *, unsigned long));
+int ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size);
+
+void ft_dump_blob(const void *bphp);
+void ft_merge_blob(struct ft_cxt *cxt, void *blob);
+void *ft_find_device(struct ft_cxt *cxt, const char *srch_path);
+void *ft_find_descendent(struct ft_cxt *cxt, void *top, const char *srch_path);
+int ft_get_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
+ void *buf, const unsigned int buflen);
+int ft_set_prop(struct ft_cxt *cxt, const void *phandle, const char *propname,
+ const void *buf, const unsigned int buflen);
+
#endif /* FLATDEVTREE_H */
diff --git a/arch/powerpc/boot/flatdevtree_env.h b/arch/powerpc/boot/flatdevtree_env.h
new file mode 100644
index 0000000..83bc1c7
--- /dev/null
+++ b/arch/powerpc/boot/flatdevtree_env.h
@@ -0,0 +1,47 @@
+/*
+ * This file adds the header file glue so that the shared files
+ * flatdevicetree.[ch] can compile and work in the powerpc bootwrapper.
+ *
+ * strncmp & strchr copied from <file:lib/strings.c>
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * Maintained by: Mark A. Greer <mgreer@mvista.com>
+ */
+#ifndef _PPC_BOOT_FLATDEVTREE_ENV_H_
+#define _PPC_BOOT_FLATDEVTREE_ENV_H_
+
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "string.h"
+#include "stdio.h"
+#include "ops.h"
+
+#define be16_to_cpu(x) (x)
+#define cpu_to_be16(x) (x)
+#define be32_to_cpu(x) (x)
+#define cpu_to_be32(x) (x)
+#define be64_to_cpu(x) (x)
+#define cpu_to_be64(x) (x)
+
+static inline int strncmp(const char *cs, const char *ct, size_t count)
+{
+ signed char __res = 0;
+
+ while (count) {
+ if ((__res = *cs - *ct++) != 0 || !*cs++)
+ break;
+ count--;
+ }
+ return __res;
+}
+
+static inline char *strchr(const char *s, int c)
+{
+ for (; *s != (char)c; ++s)
+ if (*s == '\0')
+ return NULL;
+ return (char *)s;
+}
+
+#endif /* _PPC_BOOT_FLATDEVTREE_ENV_H_ */
diff --git a/arch/powerpc/boot/flatdevtree_misc.c b/arch/powerpc/boot/flatdevtree_misc.c
new file mode 100644
index 0000000..c7f9adb
--- /dev/null
+++ b/arch/powerpc/boot/flatdevtree_misc.c
@@ -0,0 +1,56 @@
+/*
+ * This file does the necessary interface mapping between the bootwrapper
+ * device tree operations and the interface provided by shared source
+ * files flatdevicetree.[ch].
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2006 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <stddef.h>
+#include "flatdevtree.h"
+#include "ops.h"
+
+static struct ft_cxt cxt;
+
+static void *ft_finddevice(const char *name)
+{
+ return ft_find_device(&cxt, name);
+}
+
+static int ft_getprop(const void *phandle, const char *propname, void *buf,
+ const int buflen)
+{
+ return ft_get_prop(&cxt, phandle, propname, buf, buflen);
+}
+
+static int ft_setprop(const void *phandle, const char *propname,
+ const void *buf, const int buflen)
+{
+ return ft_set_prop(&cxt, phandle, propname, buf, buflen);
+}
+
+static void ft_pack(void)
+{
+ ft_end_tree(&cxt);
+}
+
+static unsigned long ft_addr(void)
+{
+ return (unsigned long)cxt.bph;
+}
+
+int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device)
+{
+ dt_ops.finddevice = ft_finddevice;
+ dt_ops.getprop = ft_getprop;
+ dt_ops.setprop = ft_setprop;
+ dt_ops.ft_pack = ft_pack;
+ dt_ops.ft_addr = ft_addr;
+
+ return ft_open(&cxt, dt_blob, max_size, max_find_device,
+ platform_ops.realloc);
+}
^ permalink raw reply related
* Re: kernel BUG in __cache_alloc_node at linux-2.6.git/mm/slab.c:3177!
From: Will Schmidt @ 2006-10-16 20:50 UTC (permalink / raw)
To: Christoph Lameter; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <Pine.LNX.4.64.0610161221300.6908@schroedinger.engr.sgi.com>
On Mon, 2006-16-10 at 12:25 -0700, Christoph Lameter wrote:
> zero slab??? That cannot be. The slab allocator always allocs on each
> node. Or is this <2.6.18 with the strange counters that we had before?
This is output from 2.6.18-rc2. MemFree, MemTotal, MemUsed still
wrong. Node0 slab is still zero. I've also attached the numa=debug
boot log from this boot, in case it has any clues that were missing from
the other boot log.
15:40:53 0 willschm@airbag2:~> find /sys/devices/system/node/ -type f -exec cat {} \;
20 10
numa_hit 4952
numa_miss 152776
numa_foreign 0
interleave_hit 3176
local_node 0
other_node 157761
Node 1 MemTotal: 327680 kB
Node 1 MemFree: 441136 kB
Node 1 MemUsed: 18446744073709438160 kB
Node 1 Active: 39008 kB
Node 1 Inactive: 18040 kB
Node 1 HighTotal: 0 kB
Node 1 HighFree: 0 kB
Node 1 LowTotal: 327680 kB
Node 1 LowFree: 441136 kB
Node 1 Dirty: 0 kB
Node 1 Writeback: 0 kB
Node 1 FilePages: 39868 kB
Node 1 Mapped: 15080 kB
Node 1 AnonPages: 17172 kB
Node 1 PageTables: 956 kB
Node 1 NFS Unstable: 0 kB
Node 1 Bounce: 0 kB
Node 1 Slab: 26036 kB
Node 1 HugePages_Total: 0
Node 1 HugePages_Free: 0
00000000,00000000,00000000,00000000
10 20
numa_hit 0
numa_miss 0
numa_foreign 152941
interleave_hit 0
local_node 0
other_node 0
Node 0 MemTotal: 229376 kB
Node 0 MemFree: 0 kB
Node 0 MemUsed: 229376 kB
Node 0 Active: 0 kB
Node 0 Inactive: 0 kB
Node 0 HighTotal: 0 kB
Node 0 HighFree: 0 kB
Node 0 LowTotal: 229376 kB
Node 0 LowFree: 0 kB
Node 0 Dirty: 0 kB
Node 0 Writeback: 0 kB
Node 0 FilePages: 0 kB
Node 0 Mapped: 0 kB
Node 0 AnonPages: 0 kB
Node 0 PageTables: 0 kB
Node 0 NFS Unstable: 0 kB
Node 0 Bounce: 0 kB
Node 0 Slab: 0 kB
Node 0 HugePages_Total: 0
Node 0 HugePages_Free: 0
00000000,00000000,00000000,000000ff
15:40:57 0 willschm@airbag2:~>
-
-----------------------------------------------------
ppc64_pft_size = 0x18
physicalMemorySize = 0x22000000
ppc64_caches.dcache_line_size = 0x80
ppc64_caches.icache_line_size = 0x80
htab_address = 0x0000000000000000
htab_hash_mask = 0x1ffff
-----------------------------------------------------
Linux version 2.6.18-rc2 (willschm@airbag2) (gcc version 4.1.0 (SUSE
Linux)) #1 SMP Mon Oct 16 15:27:37 CDT 2006
[boot]0012 Setup Arch
NUMA associativity depth for CPU/Memory: 3
add_region nid 1 start_pfn 0x0 pages 0x8000
add_region nid 0 start_pfn 0x8000 pages 0x2000
add_region nid 0 start_pfn 0xa000 pages 0x2000
add_region nid 0 start_pfn 0xc000 pages 0x2000
add_region nid 0 start_pfn 0xe000 pages 0x2000
add_region nid 0 start_pfn 0x10000 pages 0x2000
add_region nid 0 start_pfn 0x12000 pages 0x2000
add_region nid 0 start_pfn 0x14000 pages 0x2000
add_region nid 1 start_pfn 0x16000 pages 0x2000
add_region nid 1 start_pfn 0x18000 pages 0x2000
add_region nid 1 start_pfn 0x1a000 pages 0x2000
add_region nid 1 start_pfn 0x1c000 pages 0x2000
add_region nid 1 start_pfn 0x1e000 pages 0x2000
add_region nid 1 start_pfn 0x20000 pages 0x2000
Node 0 Memory: 0x8000000-0x16000000
Node 1 Memory: 0x0-0x8000000 0x16000000-0x22000000
adding cpu 0 to node 0
node 0
NODE_DATA() = c000000015ffd780
start_paddr = 8000000
end_paddr = 16000000
bootmap_paddr = 15ffb000
free_bootmem 8000000 e000000
reserve_bootmem ffc0000 40000
reserve_bootmem 15ffb000 2000
reserve_bootmem 15ffd780 2880
node 1
NODE_DATA() = c000000021ff6580
start_paddr = 0
end_paddr = 22000000
bootmap_paddr = 21ff1000
free_bootmem 0 8000000
free_bootmem 16000000 c000000
reserve_bootmem 0 802000
reserve_bootmem 2606000 9000
reserve_bootmem 77b2000 84e000
reserve_bootmem 21ff1000 5000
reserve_bootmem 21ff6580 2880
reserve_bootmem 21ff8e58 71a4
No ramdisk, default root is /dev/sda2
EEH: No capable adapters found
PPC64 nvram contains 7168 bytes
Using shared processor idle loop
free_area_init node 0 e000 8000 (hole: 0)
On node 0 totalpages: 57344
DMA zone: 57344 pages, LIFO batch:15
free_area_init node 1 22000 0 (hole: e000)
On node 1 totalpages: 81920
DMA zone: 81920 pages, LIFO batch:15
[boot]0015 Setup Done
Built 2 zonelists. Total pages: 139264
^ permalink raw reply
* Re: [PATCH 3/4] powerpc: Add non-OF serial console support
From: Mark A. Greer @ 2006-10-16 20:52 UTC (permalink / raw)
To: Mark A. Greer; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <20061012013508.GD9143@mag.az.mvista.com>
Changed how ns16550.c sets up reg_base with data from 'virtual-reg'
property.
Mark
---
Add serial console support for non-OF systems. There is a generic serial
console layer which calls a serial console driver. Included is the serial
console driver for the ns16550 class of uarts. Necessary support routines
are added as well.
Signed-off-by: Mark A. Greer <mgreer@mvista.com>
---
Makefile | 4 -
io.h | 53 +++++++++++++++++++++++
ns16550.c | 74 ++++++++++++++++++++++++++++++++
serial.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
util.S | 101 ++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 372 insertions(+), 2 deletions(-)
---
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 8660cc5..ef1bec4 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -40,8 +40,8 @@ zliblinuxheader := zlib.h zconf.h zutil.
$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) \
$(addprefix $(obj)/,$(zlibheader))
-src-wlib := string.S stdio.c main.c flatdevtree.c flatdevtree_misc.c div64.S \
- $(zlib)
+src-wlib := string.S stdio.c main.c flatdevtree.c flatdevtree_misc.c ns16550.c \
+ serial.c div64.S util.S $(zlib)
src-plat := of.c
src-boot := crt0.S $(src-wlib) $(src-plat) empty.c
diff --git a/arch/powerpc/boot/io.h b/arch/powerpc/boot/io.h
new file mode 100644
index 0000000..32974ed
--- /dev/null
+++ b/arch/powerpc/boot/io.h
@@ -0,0 +1,53 @@
+#ifndef _IO_H
+#define __IO_H
+/*
+ * Low-level I/O routines.
+ *
+ * Copied from <file:include/asm-powerpc/io.h> (which has no copyright)
+ */
+static inline int in_8(const volatile unsigned char *addr)
+{
+ int ret;
+
+ __asm__ __volatile__("lbz%U1%X1 %0,%1; twi 0,%0,0; isync"
+ : "=r" (ret) : "m" (*addr));
+ return ret;
+}
+
+static inline void out_8(volatile unsigned char *addr, int val)
+{
+ __asm__ __volatile__("stb%U0%X0 %1,%0; sync"
+ : "=m" (*addr) : "r" (val));
+}
+
+static inline unsigned in_le32(const volatile unsigned *addr)
+{
+ unsigned ret;
+
+ __asm__ __volatile__("lwbrx %0,0,%1; twi 0,%0,0; isync"
+ : "=r" (ret) : "r" (addr), "m" (*addr));
+ return ret;
+}
+
+static inline unsigned in_be32(const volatile unsigned *addr)
+{
+ unsigned ret;
+
+ __asm__ __volatile__("lwz%U1%X1 %0,%1; twi 0,%0,0; isync"
+ : "=r" (ret) : "m" (*addr));
+ return ret;
+}
+
+static inline void out_le32(volatile unsigned *addr, int val)
+{
+ __asm__ __volatile__("stwbrx %1,0,%2; sync" : "=m" (*addr)
+ : "r" (val), "r" (addr));
+}
+
+static inline void out_be32(volatile unsigned *addr, int val)
+{
+ __asm__ __volatile__("stw%U0%X0 %1,%0; sync"
+ : "=m" (*addr) : "r" (val));
+}
+
+#endif /* _IO_H */
diff --git a/arch/powerpc/boot/ns16550.c b/arch/powerpc/boot/ns16550.c
new file mode 100644
index 0000000..1ffe72e
--- /dev/null
+++ b/arch/powerpc/boot/ns16550.c
@@ -0,0 +1,74 @@
+/*
+ * 16550 serial console support.
+ *
+ * Original copied from <file:arch/ppc/boot/common/ns16550.c>
+ * (which had no copyright)
+ * Modifications: 2006 (c) MontaVista Software, Inc.
+ *
+ * Modified by: Mark A. Greer <mgreer@mvista.com>
+ */
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "string.h"
+#include "stdio.h"
+#include "io.h"
+#include "ops.h"
+
+#define UART_DLL 0 /* Out: Divisor Latch Low */
+#define UART_DLM 1 /* Out: Divisor Latch High */
+#define UART_FCR 2 /* Out: FIFO Control Register */
+#define UART_LCR 3 /* Out: Line Control Register */
+#define UART_MCR 4 /* Out: Modem Control Register */
+#define UART_LSR 5 /* In: Line Status Register */
+#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
+#define UART_LSR_DR 0x01 /* Receiver data ready */
+#define UART_MSR 6 /* In: Modem Status Register */
+#define UART_SCR 7 /* I/O: Scratch Register */
+
+static unsigned char *reg_base;
+static u32 reg_shift;
+
+static int ns16550_open(void)
+{
+ out_8(reg_base + (UART_FCR << reg_shift), 0x06);
+ return 0;
+}
+
+static void ns16550_putc(unsigned char c)
+{
+ while ((in_8(reg_base + (UART_LSR << reg_shift)) & UART_LSR_THRE) == 0);
+ out_8(reg_base, c);
+}
+
+static unsigned char ns16550_getc(void)
+{
+ while ((in_8(reg_base + (UART_LSR << reg_shift)) & UART_LSR_DR) == 0);
+ return in_8(reg_base);
+}
+
+static u8 ns16550_tstc(void)
+{
+ return ((in_8(reg_base + (UART_LSR << reg_shift)) & UART_LSR_DR) != 0);
+}
+
+int ns16550_console_init(void *devp, struct serial_console_data *scdp)
+{
+ int n;
+
+ n = getprop(devp, "virtual-reg", ®_base, sizeof(reg_base));
+ if (n != sizeof(reg_base))
+ return -1;
+
+ n = getprop(devp, "reg-shift", ®_shift, sizeof(reg_shift));
+ if (n != sizeof(reg_shift))
+ reg_shift = 0;
+
+ scdp->open = ns16550_open;
+ scdp->putc = ns16550_putc;
+ scdp->getc = ns16550_getc;
+ scdp->tstc = ns16550_tstc;
+ scdp->close = NULL;
+
+ return 0;
+}
diff --git a/arch/powerpc/boot/serial.c b/arch/powerpc/boot/serial.c
new file mode 100644
index 0000000..e8de4cf
--- /dev/null
+++ b/arch/powerpc/boot/serial.c
@@ -0,0 +1,142 @@
+/*
+ * Generic serial console support
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * Code in serial_edit_cmdline() copied from <file:arch/ppc/boot/simple/misc.c>
+ * and was written by Matt Porter <mporter@kernel.crashing.org>.
+ *
+ * 2001,2006 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "string.h"
+#include "stdio.h"
+#include "io.h"
+#include "ops.h"
+
+extern void udelay(long delay);
+
+static int serial_open(void)
+{
+ struct serial_console_data *scdp = console_ops.data;
+ return scdp->open();
+}
+
+static void serial_write(char *buf, int len)
+{
+ struct serial_console_data *scdp = console_ops.data;
+
+ while (*buf != '\0')
+ scdp->putc(*buf++);
+}
+
+static void serial_edit_cmdline(char *buf, int len)
+{
+ int timer = 0, count;
+ char ch, *cp;
+ struct serial_console_data *scdp = console_ops.data;
+
+ cp = buf;
+ count = strlen(buf);
+ cp = &buf[count];
+ count++;
+
+ while (timer++ < 5*1000) {
+ if (scdp->tstc()) {
+ while (((ch = scdp->getc()) != '\n') && (ch != '\r')) {
+ /* Test for backspace/delete */
+ if ((ch == '\b') || (ch == '\177')) {
+ if (cp != buf) {
+ cp--;
+ count--;
+ printf("\b \b");
+ }
+ /* Test for ^x/^u (and wipe the line) */
+ } else if ((ch == '\030') || (ch == '\025')) {
+ while (cp != buf) {
+ cp--;
+ count--;
+ printf("\b \b");
+ }
+ } else if (count < len) {
+ *cp++ = ch;
+ count++;
+ scdp->putc(ch);
+ }
+ }
+ break; /* Exit 'timer' loop */
+ }
+ udelay(1000); /* 1 msec */
+ }
+ *cp = 0;
+}
+
+static void serial_close(void)
+{
+ struct serial_console_data *scdp = console_ops.data;
+
+ if (scdp->close)
+ scdp->close();
+}
+
+static void *serial_get_stdout_devp(void)
+{
+ void *devp;
+ char devtype[MAX_PROP_LEN];
+ char path[MAX_PATH_LEN];
+
+ devp = finddevice("/chosen");
+ if (devp == NULL)
+ goto err_out;
+
+ if (getprop(devp, "linux,stdout-path", path, MAX_PATH_LEN) > 0) {
+ devp = finddevice(path);
+ if (devp == NULL)
+ goto err_out;
+
+ if ((getprop(devp, "device_type", devtype, sizeof(devtype)) > 0)
+ && !strcmp(devtype, "serial"))
+ return devp;
+ }
+err_out:
+ return NULL;
+}
+
+static struct serial_console_data serial_cd;
+
+/* Node's "compatible" property determines which serial driver to use */
+int serial_console_init(void)
+{
+ void *devp;
+ int rc = -1;
+ char compat[MAX_PROP_LEN];
+
+ devp = serial_get_stdout_devp();
+ if (devp == NULL)
+ goto err_out;
+
+ if (getprop(devp, "compatible", compat, sizeof(compat)) < 0)
+ goto err_out;
+
+ if (!strcmp(compat, "ns16550"))
+ rc = ns16550_console_init(devp, &serial_cd);
+
+ /* Add other serial console driver calls here */
+
+ if (!rc) {
+ console_ops.open = serial_open;
+ console_ops.write = serial_write;
+ console_ops.edit_cmdline = serial_edit_cmdline;
+ console_ops.close = serial_close;
+ console_ops.data = &serial_cd;
+
+ return 0;
+ }
+err_out:
+ return -1;
+}
diff --git a/arch/powerpc/boot/util.S b/arch/powerpc/boot/util.S
new file mode 100644
index 0000000..b8e1c23
--- /dev/null
+++ b/arch/powerpc/boot/util.S
@@ -0,0 +1,101 @@
+/*
+ * Copied from <file:arch/powerpc/kernel/misc_32.S>
+ *
+ * This file contains miscellaneous low-level functions.
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras.
+ *
+ * kexec bits:
+ * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
+ * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+#include "ppc_asm.h"
+
+#define SPRN_PVR 0x11F /* Processor Version Register */
+
+ .text
+/*
+ * complement mask on the msr then "or" some values on.
+ * _nmask_and_or_msr(nmask, value_to_or)
+ */
+ .globl _nmask_and_or_msr
+_nmask_and_or_msr:
+ mfmsr r0 /* Get current msr */
+ andc r0,r0,r3 /* And off the bits set in r3 (first parm) */
+ or r0,r0,r4 /* Or on the bits in r4 (second parm) */
+ SYNC /* Some chip revs have problems here... */
+ mtmsr r0 /* Update machine state */
+ isync
+ blr /* Done */
+
+/* udelay (on non-601 processors) needs to know the period of the
+ * timebase in nanoseconds. This used to be hardcoded to be 60ns
+ * (period of 66MHz/4). Now a variable is used that is initialized to
+ * 60 for backward compatibility, but it can be overridden as necessary
+ * with code something like this:
+ * extern unsigned long timebase_period_ns;
+ * timebase_period_ns = 1000000000 / bd->bi_tbfreq;
+ */
+ .data
+ .globl timebase_period_ns
+timebase_period_ns:
+ .long 60
+
+ .text
+/*
+ * Delay for a number of microseconds
+ */
+ .globl udelay
+udelay:
+ mfspr r4,SPRN_PVR
+ srwi r4,r4,16
+ cmpwi 0,r4,1 /* 601 ? */
+ bne .udelay_not_601
+00: li r0,86 /* Instructions / microsecond? */
+ mtctr r0
+10: addi r0,r0,0 /* NOP */
+ bdnz 10b
+ subic. r3,r3,1
+ bne 00b
+ blr
+
+.udelay_not_601:
+ mulli r4,r3,1000 /* nanoseconds */
+ /* Change r4 to be the number of ticks using:
+ * (nanoseconds + (timebase_period_ns - 1 )) / timebase_period_ns
+ * timebase_period_ns defaults to 60 (16.6MHz) */
+ mflr r5
+ bl 0f
+0: mflr r6
+ mtlr r5
+ lis r5,0b@ha
+ addi r5,r5,0b@l
+ subf r5,r5,r6 /* In case we're relocated */
+ addis r5,r5,timebase_period_ns@ha
+ lwz r5,timebase_period_ns@l(r5)
+ add r4,r4,r5
+ addi r4,r4,-1
+ divw r4,r4,r5 /* BUS ticks */
+1: mftbu r5
+ mftb r6
+ mftbu r7
+ cmpw 0,r5,r7
+ bne 1b /* Get [synced] base time */
+ addc r9,r6,r4 /* Compute end time */
+ addze r8,r5
+2: mftbu r5
+ cmpw 0,r5,r8
+ blt 2b
+ bgt 3f
+ mftb r6
+ cmpw 0,r6,r9
+ blt 2b
+3: blr
^ permalink raw reply related
* Re: [PATCH 4/4] powerpc: Add simple memory allocator to bootwrapper
From: Mark A. Greer @ 2006-10-16 20:54 UTC (permalink / raw)
To: Paul Mackerras; +Cc: Mark A. Greer, linuxppc-dev
In-Reply-To: <20061013035946.GB32327@mag.az.mvista.com>
Resending patch that combines previous two patches with this subject.
Mark
---
Provide primitive malloc, free, and realloc functions for bootwrapper.
Signed-off-by: Mark A. Greer <mgreer@mvista.com>
---
Makefile | 2
simple_alloc.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 150 insertions(+), 1 deletion(-)
---
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index ef1bec4..895e537 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -41,7 +41,7 @@ zliblinuxheader := zlib.h zconf.h zutil.
$(addprefix $(obj)/,$(zlibheader))
src-wlib := string.S stdio.c main.c flatdevtree.c flatdevtree_misc.c ns16550.c \
- serial.c div64.S util.S $(zlib)
+ serial.c simple_alloc.c div64.S util.S $(zlib)
src-plat := of.c
src-boot := crt0.S $(src-wlib) $(src-plat) empty.c
diff --git a/arch/powerpc/boot/simple_alloc.c b/arch/powerpc/boot/simple_alloc.c
new file mode 100644
index 0000000..cfe3a75
--- /dev/null
+++ b/arch/powerpc/boot/simple_alloc.c
@@ -0,0 +1,149 @@
+/*
+ * Implement primitive realloc(3) functionality.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2006 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <stddef.h>
+#include "types.h"
+#include "page.h"
+#include "string.h"
+#include "ops.h"
+
+#define ENTRY_BEEN_USED 0x01
+#define ENTRY_IN_USE 0x02
+
+static struct alloc_info {
+ u32 flags;
+ u32 base;
+ u32 size;
+} *alloc_tbl;
+
+static u32 tbl_entries;
+static u32 alloc_min;
+static u32 next_base;
+static u32 space_left;
+
+/*
+ * First time an entry is used, its base and size are set.
+ * An entry can be freed and re-malloc'd but its base & size don't change.
+ * Should be smart enough for needs of bootwrapper.
+ */
+static void *simple_malloc(u32 size)
+{
+ u32 i;
+ struct alloc_info *p = alloc_tbl;
+
+ if (size == 0)
+ goto err_out;
+
+ size = _ALIGN_UP(size, alloc_min);
+
+ for (i=0; i<tbl_entries; i++, p++)
+ if (!(p->flags & ENTRY_BEEN_USED)) { /* never been used */
+ if (size <= space_left) {
+ p->base = next_base;
+ p->size = size;
+ p->flags = ENTRY_BEEN_USED | ENTRY_IN_USE;
+ next_base += size;
+ space_left -= size;
+ return (void *)p->base;
+ }
+ goto err_out; /* not enough space left */
+ }
+ /* reuse an entry keeping same base & size */
+ else if (!(p->flags & ENTRY_IN_USE) && (size <= p->size)) {
+ p->flags |= ENTRY_IN_USE;
+ return (void *)p->base;
+ }
+err_out:
+ return NULL;
+}
+
+static struct alloc_info *simple_find_entry(void *ptr)
+{
+ u32 i;
+ struct alloc_info *p = alloc_tbl;
+
+ for (i=0; i<tbl_entries; i++,p++) {
+ if (!(p->flags & ENTRY_BEEN_USED))
+ break;
+ if ((p->flags & ENTRY_IN_USE) && (p->base == (u32)ptr))
+ return p;
+ }
+ return NULL;
+}
+
+static void simple_free(void *ptr)
+{
+ struct alloc_info *p = simple_find_entry(ptr);
+
+ if (p != NULL)
+ p->flags &= ~ENTRY_IN_USE;
+}
+
+/*
+ * Change size of area pointed to by 'ptr' to 'size'.
+ * If 'ptr' is NULL, then its a malloc(). If 'size' is 0, then its a free().
+ * 'ptr' must be NULL or a pointer to a non-freed area previously returned by
+ * simple_realloc() or simple_malloc().
+ */
+static void *simple_realloc(void *ptr, unsigned long size)
+{
+ struct alloc_info *p;
+ void *new;
+
+ if (size == 0) {
+ simple_free(ptr);
+ return NULL;
+ }
+
+ if (ptr == NULL)
+ return simple_malloc(size);
+
+ p = simple_find_entry(ptr);
+ if (p == NULL) /* ptr not from simple_malloc/simple_realloc */
+ return NULL;
+ if (size <= p->size) /* fits in current block */
+ return ptr;
+
+ new = simple_malloc(size);
+ memcpy(new, ptr, p->size);
+ simple_free(ptr);
+ return new;
+}
+
+/*
+ * Returns addr of first byte after heap so caller can see if it took
+ * too much space. If so, change args & try again.
+ */
+void *simple_alloc_init(char *base, u32 heap_size, u32 granularity,
+ u32 max_allocs)
+{
+ u32 heap_base, tbl_size;
+
+ heap_size = _ALIGN_UP(heap_size, granularity);
+ alloc_min = granularity;
+ tbl_entries = max_allocs;
+
+ tbl_size = tbl_entries * sizeof(struct alloc_info);
+
+ alloc_tbl = (struct alloc_info *)_ALIGN_UP((unsigned long)base, 8);
+ memset(alloc_tbl, 0, tbl_size);
+
+ heap_base = _ALIGN_UP((u32)alloc_tbl + tbl_size, alloc_min);
+
+ next_base = heap_base;
+ space_left = heap_size;
+
+ platform_ops.malloc = simple_malloc;
+ platform_ops.free = simple_free;
+ platform_ops.realloc = simple_realloc;
+
+ return (void *)(heap_base + heap_size);
+}
^ permalink raw reply related
* [PATCH] Slight refactor of interrupt mapping for FSL parts
From: Andy Fleming @ 2006-10-16 20:57 UTC (permalink / raw)
To: linuxppc-dev, galak; +Cc: Jeff Garzik
* Cleaned up interrupt mapping a little by adding a helper
function which parses the irq out of the device-tree, and puts
it into a resource.
* Changed the PHY Layer to use NO_IRQ instead of -1 for PHY_POLL.
This means that polling will always be used if mapping the
interrupt fails for any reason.
---
arch/powerpc/sysdev/fsl_soc.c | 33 ++++++++++++++++-----------------
include/linux/phy.h | 2 +-
2 files changed, 17 insertions(+), 18 deletions(-)
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index dbe92ae..aa24b51 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -146,7 +146,7 @@ static int __init gfar_mdio_of_init(void
}
for (k = 0; k < 32; k++)
- mdio_data.irq[k] = -1;
+ mdio_data.irq[k] = NO_IRQ;
while ((child = of_get_next_child(np, child)) != NULL) {
int irq = irq_of_parse_and_map(child, 0);
@@ -177,6 +177,13 @@ static const char *gfar_tx_intr = "tx";
static const char *gfar_rx_intr = "rx";
static const char *gfar_err_intr = "error";
+
+void of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
+{
+ r->start = r->end = irq_of_parse_and_map(dev, index);
+ r->flags = IORESOURCE_IRQ;
+}
+
static int __init gfar_of_init(void)
{
struct device_node *np;
@@ -204,8 +211,7 @@ static int __init gfar_of_init(void)
if (ret)
goto err;
- r[1].start = r[1].end = irq_of_parse_and_map(np, 0);
- r[1].flags = IORESOURCE_IRQ;
+ of_irq_to_resource(np, 0, &r[1]);
model = get_property(np, "model", NULL);
@@ -214,12 +220,10 @@ static int __init gfar_of_init(void)
r[1].name = gfar_tx_intr;
r[2].name = gfar_rx_intr;
- r[2].start = r[2].end = irq_of_parse_and_map(np, 1);
- r[2].flags = IORESOURCE_IRQ;
+ of_irq_to_resource(np, 1, &r[2]);
r[3].name = gfar_err_intr;
- r[3].start = r[3].end = irq_of_parse_and_map(np, 2);
- r[3].flags = IORESOURCE_IRQ;
+ of_irq_to_resource(np, 2, &r[3]);
n_res += 2;
}
@@ -323,8 +327,7 @@ static int __init fsl_i2c_of_init(void)
if (ret)
goto err;
- r[1].start = r[1].end = irq_of_parse_and_map(np, 0);
- r[1].flags = IORESOURCE_IRQ;
+ of_irq_to_resource(np, 0, &r[1]);
i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2);
if (IS_ERR(i2c_dev)) {
@@ -459,8 +462,7 @@ static int __init fsl_usb_of_init(void)
if (ret)
goto err;
- r[1].start = r[1].end = irq_of_parse_and_map(np, 0);
- r[1].flags = IORESOURCE_IRQ;
+ of_irq_to_resource(np, 0, &r[1]);
usb_dev_mph =
platform_device_register_simple("fsl-ehci", i, r, 2);
@@ -507,8 +509,7 @@ static int __init fsl_usb_of_init(void)
if (ret)
goto unreg_mph;
- r[1].start = r[1].end = irq_of_parse_and_map(np, 0);
- r[1].flags = IORESOURCE_IRQ;
+ of_irq_to_resource(np, 0, &r[1]);
usb_dev_dr =
platform_device_register_simple("fsl-ehci", i, r, 2);
@@ -591,8 +592,7 @@ static int __init fs_enet_of_init(void)
r[2].name = fcc_regs_c;
fs_enet_data.fcc_regs_c = r[2].start;
- r[3].start = r[3].end = irq_of_parse_and_map(np, 0);
- r[3].flags = IORESOURCE_IRQ;
+ of_irq_to_resource(np, 0, &r[3]);
fs_enet_dev =
platform_device_register_simple("fsl-cpm-fcc", i, &r[0], 4);
@@ -754,8 +754,7 @@ static int __init cpm_uart_of_init(void)
goto err;
r[1].name = scc_pram;
- r[2].start = r[2].end = irq_of_parse_and_map(np, 0);
- r[2].flags = IORESOURCE_IRQ;
+ of_irq_to_resource(np, 0, &r[2]);
cpm_uart_dev =
platform_device_register_simple("fsl-cpm-scc:uart", i, &r[0], 3);
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 9447a57..d7b3751 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -37,7 +37,7 @@ #define PHY_GBIT_FEATURES (PHY_BASIC_FEA
* or not desired for this PHY. Set to PHY_IGNORE_INTERRUPT if
* the attached driver handles the interrupt
*/
-#define PHY_POLL -1
+#define PHY_POLL NO_IRQ
#define PHY_IGNORE_INTERRUPT -2
#define PHY_HAS_INTERRUPT 0x00000001
--
1.4.2.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox