LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] enable RTAS /proc for PowerPC/CHRP platform
From: Christoph Hellwig @ 2006-10-17 13:22 UTC (permalink / raw)
  To: Nicolas DET; +Cc: akpm, linuxppc-dev, Sven Luther, tilmann
In-Reply-To: <4534BE9D.7030908@bplan-gmbh.de>

> --- a/arch/powerpc/kernel/rtas-proc.c	2006-10-14 05:34:03.000000000 +0200
> +++ b/arch/powerpc/kernel/rtas-proc.c	2006-10-16 10:46:16.000000000 +0200
> @@ -253,43 +253,70 @@ static void get_location_code(struct seq
>  static void check_location_string(struct seq_file *m, char *c);
>  static void check_location(struct seq_file *m, char *c);
>  
> +#ifdef CONFIG_PPC64
> +#define PROCRTAS_ROOT "ppc64"
> +#else
> +#define PROCRTAS_ROOT "ppc"

Please don't do any pathname changes.  Even if ppc64 isn't correct it's
what applications expect and what we should provide for a coherent user
interface.

> -	if (!machine_is(pseries))
> +	if ( ! ( machine_is(pseries) || machine_is(chrp) ) )
>  		return -ENODEV;

This should be the only change you need, and it should follow kernel
coding style, aka:

	if (!machine_is(pseries) && !machine_is(chrp))
		return -ENODEV;

>  	rtas_node = of_find_node_by_name(NULL, "rtas");
>  	if (rtas_node == NULL)
>  		return -ENODEV;

And given this check I wonder why we need the platform check at all.  It
should be safe to just remove it.

^ permalink raw reply

* Re: JFFS2 on Lite5200
From: Andrey Volkov @ 2006-10-17 13:20 UTC (permalink / raw)
  To: Andrea Galbusera; +Cc: dedekind, linux-mtd, linuxppc-embedded
In-Reply-To: <1161081183.22948.58.camel@localhost.localdomain>

Hello Andrea,

Andrea Galbusera wrote:
> Hello.
> 
> I'm currently using linux-2.6.16 from denx on a Lite5200 V2.0. I need to
> access a JFFS2 filesystem on the onboard flash ( 16MB Am29L652D ).
> 
> I see the flash using physmap driver and cmdline partitions.
> I experience a problem when creating files on JFFS2 with filename longer
> than a few characters. They appear to be created correctly with the
> content I want, but, after unmounting and remounting the filesystem they
> result unreadable and ls complains with "no such file or
> directory" (short-named files are ok).
--snip--

OMG, again same question,

Andrea, check ml archive, I already sent patch half-year ago
(http://ozlabs.org/pipermail/linuxppc-embedded/2006-April/022566.html)
Problem is in alignment/memcpy: JFFS2 code assumed that memory at
unaligned addresses could be touched, but access to an external MMIO
on MPC5200 _must_ be aligned (i.e. you could not read u32 from odd address).

P.S. Artem, I repeat, I sent this patch _HALF_YEAR_AGO_
how about to fix scan.c?

--
Regards
Andrey

^ permalink raw reply

* [Regression] cpu hotplug failed on kernel 2.6.19-rc2
From: Yao Fei Zhu @ 2006-10-17 13:16 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel

Running cpu hotplug regression tsstcase lhcs_regression on kernel 2.6.19-rc2/IBM System p5 will fall into xmon.

1:mon> e
cpu 0x1: Vector: 300 (Data Access) at [c000000023fa3570]
    pc: c0000000000abfa0: .__drain_pages+0x50/0xbc
    lr: c0000000000abfd8: .__drain_pages+0x88/0xbc
    sp: c000000023fa37f0
   msr: 8000000000001032
   dar: 0
 dsisr: 40010000
  current = 0xc000000002a5d070
  paca    = 0xc000000000494800
    pid   = 3345, comm = hotplug01.sh
1:mon> t
[c000000023fa3890] c0000000000ac040 .page_alloc_cpu_notify+0x34/0x70
[c000000023fa3910] c000000000378190 .notifier_call_chain+0x4c/0x90
[c000000023fa39a0] c000000000076b2c .blocking_notifier_call_chain+0x3c/0x6c
[c000000023fa3a40] c00000000008989c .cpu_down+0x218/0x32c
[c000000023fa3b30] c000000000242a0c .store_online+0x44/0xa0
[c000000023fa3bc0] c00000000023d0e0 .sysdev_store+0x44/0x60
[c000000023fa3c40] c00000000013f160 .sysfs_write_file+0x134/0x1b8
[c000000023fa3cf0] c0000000000dd814 .vfs_write+0x118/0x200
[c000000023fa3d90] c0000000000ddf84 .sys_write+0x4c/0x8c
[c000000023fa3e30] c00000000000871c syscall_exit+0x0/0x40
--- Exception: c01 (System Call) at 000000000fe0de7c
SP (f8ccc0c0) is in userspace
1:mon> r
R00 = 8000000000001032   R16 = 00000000100a0000
R01 = c000000023fa37f0   R17 = 00000000100c2cd8
R02 = c0000000005cc460   R18 = 000000000000003f
R03 = c000000049fff600   R19 = 0000000000000000
R04 = 0000000000000000   R20 = c0000000004c9078
R05 = c000000020dc3250   R21 = 0000000000000005
R06 = 0000000000000000   R22 = c000000000665180
R07 = 0000000000000000   R23 = 0000000000008002
R08 = 0000000000000008   R24 = 0000000000000005
R09 = c000000049fff628   R25 = 0000000000000005
R10 = 0000000000000100   R26 = 0000000000000005
R11 = c000000049fff600   R27 = 0000000000000000
R12 = 0000000000000000   R28 = c000000049fff600
R13 = c000000000494800   R29 = 8000000000001032
R14 = 0000000010080000   R30 = c0000000004d31c8
R15 = 0000000000000000   R31 = 0000000000000000
pc  = c0000000000abfa0 .__drain_pages+0x50/0xbc
lr  = c0000000000abfd8 .__drain_pages+0x88/0xbc
msr = 8000000000001032   cr  = 24242448
ctr = c0000000000ac00c   xer = 0000000000000001   trap =  300
dar = 0000000000000000   dsisr = 40010000
1:mon> di c0000000000abfa0
c0000000000abfa0  e89f0002      lwa     r4,0(r31)
c0000000000abfa4  7f83e378      mr      r3,r28
c0000000000abfa8  38bf0010      addi    r5,r31,16
c0000000000abfac  38c00000      li      r6,0
c0000000000abfb0  4bfff9c1      bl      c0000000000ab970        #
.free_pages_bulk+0x0/0x2b4
c0000000000abfb4  38000000      li      r0,0
c0000000000abfb8  901f0000      stw     r0,0(r31)
c0000000000abfbc  7fa10164      mtmsrd  r29,1
c0000000000abfc0  3b7b0001      addi    r27,r27,1
c0000000000abfc4  3bff0020      addi    r31,r31,32
c0000000000abfc8  2fbb0002      cmpdi   cr7,r27,2
c0000000000abfcc  409effc4      bne     cr7,c0000000000abf90    #
.__drain_pages+0x40/0xbc
c0000000000abfd0  7f83e378      mr      r3,r28
c0000000000abfd4  48008c09      bl      c0000000000b4bdc        #
.next_zone+0x0/0x48
c0000000000abfd8  60000000      nop
c0000000000abfdc  2fa30000      cmpdi   cr7,r3,0
1:mon> mi
1:mon>

^ permalink raw reply

* [POWERPC] simplify stolen time calculation
From: Stephen Rothwell @ 2006-10-17 13:08 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev

In calculating stolen time, we were trying to actually account for time
spent in the hypervisor.  We don't really have enough information to do
that accurately, so don't try.  Instead, we now calculate stolen time as
time that the current cpu thread is not actually dispatching instructions.
On chips without a PURR, we cannot do this, so stolen time will always
be zero.  On chips with a PURR, this is merely the difference between
the elapsed PURR values and the elapsed TB values.

This gives us much more sane vaules from tools such as mpstat, even if
they are still a bit strange e.g. 2 busy threads on one cpu will both
appear to have 50% user time and 50% stolen time while 1 busy thread on
a cpu will look like 100% user on one of them and 100% idle on the other.

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
 arch/powerpc/kernel/time.c |   63 +++++++++++---------------------------------
 1 files changed, 16 insertions(+), 47 deletions(-)


-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index a124499..73e73dd 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -221,11 +221,8 @@ #ifdef CONFIG_PPC_SPLPAR
  */
 struct cpu_purr_data {
 	int	initialized;			/* thread is running */
-	u64	tb0;			/* timebase at origin time */
-	u64	purr0;			/* PURR at origin time */
 	u64	tb;			/* last TB value read */
 	u64	purr;			/* last PURR value read */
-	u64	stolen;			/* stolen time so far */
 	spinlock_t lock;
 };
 
@@ -235,10 +232,8 @@ static void snapshot_tb_and_purr(void *d
 {
 	struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data);
 
-	p->tb0 = mftb();
-	p->purr0 = mfspr(SPRN_PURR);
-	p->tb = p->tb0;
-	p->purr = 0;
+	p->tb = mftb();
+	p->purr = mfspr(SPRN_PURR);
 	wmb();
 	p->initialized = 1;
 }
@@ -259,37 +254,24 @@ void snapshot_timebases(void)
 
 void calculate_steal_time(void)
 {
-	u64 tb, purr, t0;
+	u64 tb, purr;
 	s64 stolen;
-	struct cpu_purr_data *p0, *pme, *phim;
-	int cpu;
+	struct cpu_purr_data *pme;
 
 	if (!cpu_has_feature(CPU_FTR_PURR))
 		return;
-	cpu = smp_processor_id();
-	pme = &per_cpu(cpu_purr_data, cpu);
+	pme = &per_cpu(cpu_purr_data, smp_processor_id());
 	if (!pme->initialized)
 		return;		/* this can happen in early boot */
-	p0 = &per_cpu(cpu_purr_data, cpu & ~1);
-	phim = &per_cpu(cpu_purr_data, cpu ^ 1);
-	spin_lock(&p0->lock);
+	spin_lock(&pme->lock);
 	tb = mftb();
-	purr = mfspr(SPRN_PURR) - pme->purr0;
-	if (!phim->initialized || !cpu_online(cpu ^ 1)) {
-		stolen = (tb - pme->tb) - (purr - pme->purr);
-	} else {
-		t0 = pme->tb0;
-		if (phim->tb0 < t0)
-			t0 = phim->tb0;
-		stolen = phim->tb - t0 - phim->purr - purr - p0->stolen;
-	}
-	if (stolen > 0) {
+	purr = mfspr(SPRN_PURR);
+	stolen = (tb - pme->tb) - (purr - pme->purr);
+	if (stolen > 0)
 		account_steal_time(current, stolen);
-		p0->stolen += stolen;
-	}
 	pme->tb = tb;
 	pme->purr = purr;
-	spin_unlock(&p0->lock);
+	spin_unlock(&pme->lock);
 }
 
 /*
@@ -298,30 +280,17 @@ void calculate_steal_time(void)
  */
 static void snapshot_purr(void)
 {
-	int cpu;
-	u64 purr;
-	struct cpu_purr_data *p0, *pme, *phim;
+	struct cpu_purr_data *pme;
 	unsigned long flags;
 
 	if (!cpu_has_feature(CPU_FTR_PURR))
 		return;
-	cpu = smp_processor_id();
-	pme = &per_cpu(cpu_purr_data, cpu);
-	p0 = &per_cpu(cpu_purr_data, cpu & ~1);
-	phim = &per_cpu(cpu_purr_data, cpu ^ 1);
-	spin_lock_irqsave(&p0->lock, flags);
-	pme->tb = pme->tb0 = mftb();
-	purr = mfspr(SPRN_PURR);
-	if (!phim->initialized) {
-		pme->purr = 0;
-		pme->purr0 = purr;
-	} else {
-		/* set p->purr and p->purr0 for no change in p0->stolen */
-		pme->purr = phim->tb - phim->tb0 - phim->purr - p0->stolen;
-		pme->purr0 = purr - pme->purr;
-	}
+	pme = &per_cpu(cpu_purr_data, smp_processor_id());
+	spin_lock_irqsave(&pme->lock, flags);
+	pme->tb = mftb();
+	pme->purr = mfspr(SPRN_PURR);
 	pme->initialized = 1;
-	spin_unlock_irqrestore(&p0->lock, flags);
+	spin_unlock_irqrestore(&pme->lock, flags);
 }
 
 #endif /* CONFIG_PPC_SPLPAR */
-- 
1.4.2.3

^ permalink raw reply related

* [PATCH] enable RTAS /proc for PowerPC/CHRP platform
From: Nicolas DET @ 2006-10-17 11:29 UTC (permalink / raw)
  To: linuxppc-dev, akpm, Sven Luther, tilmann

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

This patch enables RTAS /proc support for PowerPC 32bits / CHRP platform.

A new entry is created (/proc/ppc/rtas/) which contains the RTAS nodes. 
Theses nodes and the code are the exact same than with the ppc64 
architecture.

This patch has been succefully applied on the kernel 2.6.18.1 and tested 
on bPlan's OpenFirmware.

Signed-off-by: Nicolas DET <nd@bplan-gmbh.de>

[-- Attachment #2: rtas-proc_ppc32.patch --]
[-- Type: text/plain, Size: 2707 bytes --]

--- a/arch/powerpc/kernel/rtas-proc.c	2006-10-14 05:34:03.000000000 +0200
+++ b/arch/powerpc/kernel/rtas-proc.c	2006-10-16 10:46:16.000000000 +0200
@@ -253,43 +253,70 @@ static void get_location_code(struct seq
 static void check_location_string(struct seq_file *m, char *c);
 static void check_location(struct seq_file *m, char *c);
 
+#ifdef CONFIG_PPC64
+#define PROCRTAS_ROOT "ppc64"
+#else
+#define PROCRTAS_ROOT "ppc"
+static int __init proc_ppc32_create(void)
+{
+        struct proc_dir_entry *root;
+
+        root = proc_mkdir(PROCRTAS_ROOT , NULL);
+        if (!root)
+                return -1;
+
+        if (!proc_mkdir("rtas", root))
+                return -1;
+
+        if (!proc_symlink("rtas", NULL, PROCRTAS_ROOT "/rtas"))
+                return -1;
+
+        return 0;
+}
+#endif
+
 static int __init proc_rtas_init(void)
 {
 	struct proc_dir_entry *entry;
 
-	if (!machine_is(pseries))
+	if ( ! ( machine_is(pseries) || machine_is(chrp) ) )
 		return -ENODEV;
 
 	rtas_node = of_find_node_by_name(NULL, "rtas");
 	if (rtas_node == NULL)
 		return -ENODEV;
 
-	entry = create_proc_entry("ppc64/rtas/progress", S_IRUGO|S_IWUSR, NULL);
+#ifndef CONFIG_PPC64
+	if (proc_ppc32_create() != 0)
+		return -ENODEV;
+#endif
+
+	entry = create_proc_entry(PROCRTAS_ROOT "/rtas/progress", S_IRUGO|S_IWUSR, NULL);
 	if (entry)
 		entry->proc_fops = &ppc_rtas_progress_operations;
 
-	entry = create_proc_entry("ppc64/rtas/clock", S_IRUGO|S_IWUSR, NULL);
+	entry = create_proc_entry(PROCRTAS_ROOT "/rtas/clock", S_IRUGO|S_IWUSR, NULL);
 	if (entry)
 		entry->proc_fops = &ppc_rtas_clock_operations;
 
-	entry = create_proc_entry("ppc64/rtas/poweron", S_IWUSR|S_IRUGO, NULL);
+	entry = create_proc_entry(PROCRTAS_ROOT "/rtas/poweron", S_IWUSR|S_IRUGO, NULL);
 	if (entry)
 		entry->proc_fops = &ppc_rtas_poweron_operations;
 
-	entry = create_proc_entry("ppc64/rtas/sensors", S_IRUGO, NULL);
+	entry = create_proc_entry(PROCRTAS_ROOT "/rtas/sensors", S_IRUGO, NULL);
 	if (entry)
 		entry->proc_fops = &ppc_rtas_sensors_operations;
 
-	entry = create_proc_entry("ppc64/rtas/frequency", S_IWUSR|S_IRUGO,
+	entry = create_proc_entry(PROCRTAS_ROOT "/rtas/frequency", S_IWUSR|S_IRUGO,
 				  NULL);
 	if (entry)
 		entry->proc_fops = &ppc_rtas_tone_freq_operations;
 
-	entry = create_proc_entry("ppc64/rtas/volume", S_IWUSR|S_IRUGO, NULL);
+	entry = create_proc_entry(PROCRTAS_ROOT "/rtas/volume", S_IWUSR|S_IRUGO, NULL);
 	if (entry)
 		entry->proc_fops = &ppc_rtas_tone_volume_operations;
 
-	entry = create_proc_entry("ppc64/rtas/rmo_buffer", S_IRUSR, NULL);
+	entry = create_proc_entry(PROCRTAS_ROOT "/rtas/rmo_buffer", S_IRUSR, NULL);
 	if (entry)
 		entry->proc_fops = &ppc_rtas_rmo_buf_ops;
 

[-- Attachment #3: nd.vcf --]
[-- Type: text/x-vcard, Size: 249 bytes --]

begin:vcard
fn:Nicolas DET ( bplan GmbH )
n:DET;Nicolas
org:bplan GmbH
adr:;;;;;;Germany
email;internet:nd@bplan-gmbh.de
title:Software Entwicklung
tel;work:+49 6171 9187 - 31
x-mozilla-html:FALSE
url:http://www.bplan-gmbh.de
version:2.1
end:vcard


^ permalink raw reply

* JFFS2 on Lite5200
From: Andrea Galbusera @ 2006-10-17 10:33 UTC (permalink / raw)
  To: linuxppc-embedded, linux-mtd

Hello.

I'm currently using linux-2.6.16 from denx on a Lite5200 V2.0. I need to
access a JFFS2 filesystem on the onboard flash ( 16MB Am29L652D ).

I see the flash using physmap driver and cmdline partitions.
I experience a problem when creating files on JFFS2 with filename longer
than a few characters. They appear to be created correctly with the
content I want, but, after unmounting and remounting the filesystem they
result unreadable and ls complains with "no such file or
directory" (short-named files are ok).

I can deterministically reproduce the problem this way:

$ eraseall /dev/mtd1	(start with a fresh MTD partition)
$ mount -t jffs2 /dev/mtdblock1 /mnt/flash
$ date > /mnt/flash/short
$ date > /mnt/flash/timestamp
$ ls /mnt/flash/
short  timestamp
$ umount /dev/mtdblock1
$ mount -t jffs2 /dev/mtdblock1 /mnt/flash
$ ls /mnt/flash
ls: /mnt/flash/time: No such file or directory
short

...than I cannot access /mnt/flash/timestamp anymore,
while /mnt/flash/short is ok!

These are the kernel relevant settings:

#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
CONFIG_MTD_DEBUG=y
CONFIG_MTD_DEBUG_VERBOSE=3
CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_CMDLINE_PARTS=y

#
# User Modules And Translation Layers
#
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y

#
# RAM/ROM/Flash chip drivers
#
CONFIG_MTD_CFI=y
CONFIG_MTD_GEN_PROBE=y
CONFIG_MTD_MAP_BANK_WIDTH_1=y
CONFIG_MTD_MAP_BANK_WIDTH_2=y
CONFIG_MTD_MAP_BANK_WIDTH_4=y
CONFIG_MTD_CFI_I1=y
CONFIG_MTD_CFI_I2=y
CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_CFI_AMDSTD_RETRY=0
CONFIG_MTD_CFI_UTIL=y

#
# Mapping drivers for chip access
#
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_PHYSMAP_START=0xff000000
CONFIG_MTD_PHYSMAP_LEN=0x01000000
CONFIG_MTD_PHYSMAP_BANKWIDTH=1

#
# Miscellaneous filesystems
#
CONFIG_JFFS_FS=y
CONFIG_JFFS_FS_VERBOSE=0
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=2
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y


I enabled both MTD and JFFS2 maximum verbosity debug messages. If
relevant, I can post them for any of the commands in the sequence. Btw I
have the same problem with crafted filesystem images built with
mkfs.jffs2 (they fail at first mount).

Trying to exclude MTD issues I tested the same with JFFS and I don't
have any problem, but JFFS is not suitable for my needs :-(

By digging the net, I can't find any reference to this problem. Hope
anybody out there is using this setup (lite5200_defconfig as MTD
disabled) and can help. TIA.

Regards,
Andrea

^ permalink raw reply

* Re: Linux on custom Xilinx board with PPC405 hangs on boot
From: Peter N. Andreasen @ 2006-10-17  9:06 UTC (permalink / raw)
  To: Liu Dave-r63238, Linas Vepstas, linuxppc-dev
In-Reply-To: <36468a5c0609210040o3f2fad38r7f6f9848ffa48ec8@mail.gmail.com>

On 9/21/06, Peter N. Andreasen <peterarbejde@gmail.com> wrote:
> Liu, Linas, list
> Thanks a lot for the answers. It helped me to review the hardware configuration again.
> The problem was the definition of the Flash size.
> It turns out that the Xilinx generated header files define the size of the Flash. But the kernel also has a configuration option: Memory Technology Devices / Mapping Drivers for Chip Access / Physical Length of Chip Mapping
> My arch/ppc/platforms/xilinx_ocp/xparameters_ml300.h defines this as 4Mbyte, but the option in the kernel was set to 64 Mbyte (an extra 0 which I had not seen)

Hello list,
I have successfully booted the kernel, but the uartlite device seems
to give me a lot of headache. I am using Busybox v. 1.0 and made some
changes to the libb.h:
# define CURRENT_VC "/dev/ttl0"
# define VC_1 "/dev/ttl1"
# define VC_2 "/dev/ttl2"
# define VC_3 "/dev/ttl3"
# define VC_4 "/dev/ttl4"
# define VC_5 "/dev/ttl5"

#  define SC_0 "/dev/ttl0"
#  define SC_1 "/dev/ttl1"
#  define SC_FORMAT "/dev/ttl%d"
# define VC_FORMAT "/dev/ttl%d"

To make sure I get the correct device node I also changed this in
xuartllite_serial.h:
#define XULITE_MINOR_START	187
#define UARTLITE_TTY_NAME	"ttl"
#define UARTLITE_TTY_DEVFS_NAME	"ttl/%d"
#define UARTLITE_CU_NAME	"cul"
#define UARTLITE_CU_DEVFS_NAME	"cul/%d"
#define XULITE_MAJOR            204
#define XULITE_AUX_MAJOR        205

The system stops when init launches the busybox init process. This is
the message I get just after "Freeing unused kernel memory: 44k init"

First I got an assert() from the Xilinx Uartlite driver:
...
init started:  Bu
<2>Xilinx OS Independent Code XAssert:  xuartlite.c:194
Code may crash due to unhandled errors.
...
and the system stops.
The check made in the driver is for a 0 length string. If I change it
to ignore that, the console show this instead:
init started:  Bu
init started:  B
trying to run init_process
...
(the "trying to run init process" is a message I put in
run_init_process in init.c in the kernel, and the message it tries to
output is "init started: Busybox version 1.0 .....")

Now my question is:
What exactly are the device nodes I have to make in /dev/ on the
ramdisk on target? I made a ttl, ttl0, and tty  which have major
204/minor 187, and ttl1, ttl2 minor 188 and 189. I also
Hope someone can help me on this

Peter

^ permalink raw reply

* [PATCH] Slight refactor of interrupt mapping for FSL parts
From: Andy Fleming @ 2006-10-17  6:27 UTC (permalink / raw)
  To: linuxppc-dev, Kumar Gala, 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.
* Changed the arch/ppc platform files to specify PHY_POLL, instead of -1
* Changed the fixed phy to use PHY_IGNORE_INTERRUPT
---
This is a respin of the patch to reply to comments from the community

 arch/powerpc/sysdev/fsl_soc.c                |   27 ++++++++++----------------
 arch/ppc/platforms/85xx/mpc8540_ads.c        |    4 ++--
 arch/ppc/platforms/85xx/mpc8560_ads.c        |    4 ++--
 arch/ppc/platforms/85xx/mpc85xx_cds_common.c |    6 +++---
 arch/ppc/platforms/85xx/sbc8560.c            |    2 +-
 arch/ppc/platforms/85xx/stx_gp3.c            |    2 +-
 arch/ppc/platforms/85xx/tqm85xx.c            |    4 ++--
 drivers/net/phy/fixed.c                      |    2 +-
 include/asm-powerpc/prom.h                   |    7 +++++++
 include/linux/phy.h                          |    7 ++++++-
 10 files changed, 35 insertions(+), 30 deletions(-)

diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index dbe92ae..9ed3b27 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,7 @@ static const char *gfar_tx_intr = "tx";
 static const char *gfar_rx_intr = "rx";
 static const char *gfar_err_intr = "error";
 
+
 static int __init gfar_of_init(void)
 {
 	struct device_node *np;
@@ -204,8 +205,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 +214,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 +321,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 +456,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 +503,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 +586,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 +748,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/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c
index 4f839da..00a3ba5 100644
--- a/arch/ppc/platforms/85xx/mpc8540_ads.c
+++ b/arch/ppc/platforms/85xx/mpc8540_ads.c
@@ -92,9 +92,9 @@ #endif
 
 	mdata->irq[0] = MPC85xx_IRQ_EXT5;
 	mdata->irq[1] = MPC85xx_IRQ_EXT5;
-	mdata->irq[2] = -1;
+	mdata->irq[2] = PHY_POLL;
 	mdata->irq[3] = MPC85xx_IRQ_EXT5;
-	mdata->irq[31] = -1;
+	mdata->irq[31] = PHY_POLL;
 
 	/* setup the board related information for the enet controllers */
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c
index 14ecec7..3a06046 100644
--- a/arch/ppc/platforms/85xx/mpc8560_ads.c
+++ b/arch/ppc/platforms/85xx/mpc8560_ads.c
@@ -156,9 +156,9 @@ #endif
 
 	mdata->irq[0] = MPC85xx_IRQ_EXT5;
 	mdata->irq[1] = MPC85xx_IRQ_EXT5;
-	mdata->irq[2] = -1;
+	mdata->irq[2] = PHY_POLL;
 	mdata->irq[3] = MPC85xx_IRQ_EXT5;
-	mdata->irq[31] = -1;
+	mdata->irq[31] = PHY_POLL;
 
 	/* setup the board related information for the enet controllers */
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
index 5ce0f69..2d59eb7 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
@@ -451,9 +451,9 @@ #endif
 
 	mdata->irq[0] = MPC85xx_IRQ_EXT5;
 	mdata->irq[1] = MPC85xx_IRQ_EXT5;
-	mdata->irq[2] = -1;
-	mdata->irq[3] = -1;
-	mdata->irq[31] = -1;
+	mdata->irq[2] = PHY_POLL;
+	mdata->irq[3] = PHY_POLL;
+	mdata->irq[31] = PHY_POLL;
 
 	/* setup the board related information for the enet controllers */
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c
index 764d580..1d10ab9 100644
--- a/arch/ppc/platforms/85xx/sbc8560.c
+++ b/arch/ppc/platforms/85xx/sbc8560.c
@@ -129,7 +129,7 @@ #endif
 
 	mdata->irq[25] = MPC85xx_IRQ_EXT6;
 	mdata->irq[26] = MPC85xx_IRQ_EXT7;
-	mdata->irq[31] = -1;
+	mdata->irq[31] = PHY_POLL;
 
 	/* setup the board related information for the enet controllers */
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c
index 4bb18ab..b1f5b73 100644
--- a/arch/ppc/platforms/85xx/stx_gp3.c
+++ b/arch/ppc/platforms/85xx/stx_gp3.c
@@ -123,7 +123,7 @@ #endif
 
 	mdata->irq[2] = MPC85xx_IRQ_EXT5;
 	mdata->irq[4] = MPC85xx_IRQ_EXT5;
-	mdata->irq[31] = -1;
+	mdata->irq[31] = PHY_POLL;
 
 	/* setup the board related information for the enet controllers */
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
diff --git a/arch/ppc/platforms/85xx/tqm85xx.c b/arch/ppc/platforms/85xx/tqm85xx.c
index dd45f2e..4ee2bd1 100644
--- a/arch/ppc/platforms/85xx/tqm85xx.c
+++ b/arch/ppc/platforms/85xx/tqm85xx.c
@@ -137,9 +137,9 @@ #endif /* CONFIG_MPC8560 */
 
 	mdata->irq[0] = MPC85xx_IRQ_EXT8;
 	mdata->irq[1] = MPC85xx_IRQ_EXT8;
-	mdata->irq[2] = -1;
+	mdata->irq[2] = PHY_POLL;
 	mdata->irq[3] = MPC85xx_IRQ_EXT8;
-	mdata->irq[31] = -1;
+	mdata->irq[31] = PHY_POLL;
 
 	/* setup the board related information for the enet controllers */
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c
index f14e992..096d4a1 100644
--- a/drivers/net/phy/fixed.c
+++ b/drivers/net/phy/fixed.c
@@ -254,7 +254,7 @@ static int fixed_mdio_register_device(in
 		goto device_create_fail;
 	}
 
-	phydev->irq = -1;
+	phydev->irq = PHY_IGNORE_INTERRUPT;
 	phydev->dev.bus = &mdio_bus_type;
 
 	if(number)
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
index 5246297..39f04ef 100644
--- a/include/asm-powerpc/prom.h
+++ b/include/asm-powerpc/prom.h
@@ -17,6 +17,7 @@ #ifdef __KERNEL__
  */
 #include <linux/types.h>
 #include <linux/proc_fs.h>
+#include <linux/platform_device.h>
 #include <asm/atomic.h>
 
 /* Definitions used by the flattened device tree */
@@ -331,6 +332,12 @@ extern int of_irq_map_one(struct device_
 struct pci_dev;
 extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq);
 
+static inline 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;
+}
+
 
 #endif /* __KERNEL__ */
 #endif /* _POWERPC_PROM_H */
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 9447a57..4dbffe4 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -20,6 +20,7 @@ #define __PHY_H
 
 #include <linux/spinlock.h>
 #include <linux/device.h>
+#include <asm/irq.h>
 
 #define PHY_BASIC_FEATURES	(SUPPORTED_10baseT_Half | \
 				 SUPPORTED_10baseT_Full | \
@@ -37,7 +38,11 @@ #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
+#ifndef NO_IRQ
+#define NO_IRQ 0
+#endif
+
+#define PHY_POLL		NO_IRQ
 #define PHY_IGNORE_INTERRUPT	-2
 
 #define PHY_HAS_INTERRUPT	0x00000001
-- 
1.4.2.3

^ permalink raw reply related

* Please pull powerpc.git 'merge' branch
From: Paul Mackerras @ 2006-10-17  4:02 UTC (permalink / raw)
  To: torvalds; +Cc: linuxppc-dev

Linus,

Please do:

git pull \
git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc.git merge

to get some more PowerPC bugfixes, as listed below.

Paul.

 arch/powerpc/configs/mpc834x_itx_defconfig |    2 +-
 arch/powerpc/kernel/cputable.c             |    2 +-
 arch/powerpc/kernel/pci_32.c               |   12 ++++++------
 arch/powerpc/kernel/pci_64.c               |   10 ++++++++--
 arch/powerpc/kernel/process.c              |   10 ++--------
 arch/powerpc/kernel/traps.c                |    3 +--
 arch/powerpc/platforms/83xx/Kconfig        |   13 +++++++++++++
 arch/powerpc/platforms/83xx/Makefile       |    2 ++
 arch/powerpc/platforms/83xx/mpc8360e_pb.c  |   19 +++++++++++++++++++
 arch/powerpc/platforms/cell/spu_base.c     |   15 +++++++++++----
 arch/powerpc/platforms/cell/spufs/file.c   |    1 +
 arch/ppc/kernel/time.c                     |    4 ++++
 arch/ppc/platforms/mpc8272ads_setup.c      |    4 ++--
 arch/ppc/platforms/mpc866ads_setup.c       |    4 ++--
 arch/ppc/platforms/mpc885ads_setup.c       |    4 ++--
 15 files changed, 75 insertions(+), 30 deletions(-)

Anton Blanchard:
      [POWERPC] Never panic when taking altivec exceptions from userspace
      [POWERPC] POWER6 has 6 PMCs
      [POWERPC] Better check in show_instructions
      [POWERPC] Check for offline nodes in pci NUMA code

Benjamin Herrenschmidt:
      [POWERPC] Don't crash on cell with 2 BEs when !CONFIG_NUMA

Eric Sesterhenn:
      [POWERPC] Off-by-one in /arch/ppc/platforms/mpc8*

Kumar Gala:
      [POWERPC] ppc: Add missing calls to set_irq_regs

Li Yang:
      [POWERPC] Fix MPC8360EMDS PB board support
      [POWERPC] Add Makefile entry for MPC832x_mds support

Noguchi, Masato:
      [POWERPC] spufs: fix support for read/write on cntl

Randy Vinson:
      [POWERPC] Fix IO Window Updates on P2P bridges.

Timur Tabi:
      [POWERPC] Add DOS partition table support to mpc834x_itx_defconfig

^ permalink raw reply

* Re: Failed to boot kernel 2.6.19-rc2 due to IBM veth problem.
From: David Gibson @ 2006-10-17  0:15 UTC (permalink / raw)
  To: Yao Fei Zhu; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <4533C4E9.1040504@cn.ibm.com>

On Tue, Oct 17, 2006 at 01:44:09AM +0800, Yao Fei Zhu wrote:
[snip]
> > 
> David, I have verified this fix, it works fine for me, Thanks. What's the status of it? Submitted?

Yes, I've sent it to Santiago Leon, the ibmveth maintainer and also to
Jeff Garzik and Andrew Morton.  It is in Andrew's -mm tree already,
haven't heard from Santiago or Jeff.

-- 
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

* Re: kernel BUG in __cache_alloc_node at linux-2.6.git/mm/slab.c:3177!
From: Christoph Lameter @ 2006-10-16 23:37 UTC (permalink / raw)
  To: Will Schmidt; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <1161031821.31903.28.camel@farscape>

On Mon, 16 Oct 2006, Will Schmidt wrote:

> 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. 

It looks as if node 0 is allready full on bootup. The new code in 2.6.19 
controls locality in a more strict form in the slab. 2.6.18 and earlier 
were able to tolerate if a request for a page from the slab allocator for 
node 0 returns memory on node1 even if node 1 has not been bootstrapped 
yet. But this resulted in a problem in the slab because the node lists 
dedicated for node 0 now had memory from node 1 in it (which led to 
latency problems since slab code subsequently assumes that node local 
memory is very fast, which with corrupted per node lists is no longer 
true.).

You must bootstrap on a node that has memory available. If you would 
bootstrap the slab on node 1 that would work.

> Node 0 MemTotal:       229376 kB
> Node 0 MemUsed:        229376 kB

^^^^^ This node should not be full!!!

Increase memory on node 0 so that the slab can bootstrap.

^ permalink raw reply

* Re: [PATCH] Slight refactor of interrupt mapping for FSL parts
From: Benjamin Herrenschmidt @ 2006-10-16 22:58 UTC (permalink / raw)
  To: Andy Fleming; +Cc: linuxppc-dev, Jeff Garzik
In-Reply-To: <Pine.LNX.4.61.0610161554580.6266@ld0175-tx32.am.freescale.net>


> +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;
> +}
> +

What about having that one in prom_parse.c ?

Ben.

^ permalink raw reply

* Re: [PATCH] Xilinx UART Lite 2.6.18 driver
From: Peter Korsgaard @ 2006-10-16 19:42 UTC (permalink / raw)
  To: David H. Lynch Jr.; +Cc: linuxppc-embedded
In-Reply-To: <45329C42.3030000@dlasys.net>

>>>>> "David" == David H Lynch <dhlii@dlasys.net> writes:

Hi,

 David>     The 8250 is certainly the oldest driver - but it is also
 David> by far the most used. It is also the most heavily maintained,

Yes, because there's so many more-or-less compatible variants of the
hardware. Most drivers don't see a lot of development once they are
past the initial development/testing..

 David> There are complexities to the 8250 that proved to be difficult
 David> and troubling when I based my UartLite driver on it, Those
 David> problems were because the 8250driver suports so many 8250
 David> variants with so many idiosyncracies.

Exactly. Try to compare it to one of the "modern" drivers like
atmel_serial.c - It's almost 3 times as big.

 >> Remove support? I don't remember anything about that.

 David>     I may have misread something there - I thought your
 David> initial driver allowed stting the number of Uarts, and I
 David> beleive your current one does not.  If I am wrong, then I
 David> think support for more Uarts needs to get added to the todo
 David> list.  That is not something important to me. But it probably
 David> will be for others.

There was a discussion about how many device nodes to register with
lanana.org and hence how many devices to support. I went with 4 which
seems to be pretty standard (E.G. virtex.c supports up to 4 8250s). If
more is needed a bigger range can be requested with lanana.org.

Again, let's see a real need before changing anything.

 David> Despite the fact hat you apear to run combined 16550/Uartlite
 David> implimentations, My expectation is that will be rare.  A small
 David> savings in FPGA spare is rarely going to justify more complex
 David> hardware and software.  Multiple port systems are mostly
 David> likely to be all one type or another.

Almost all our designs use both.

P.S.: Would it be possible to fix up your quoting?

-- 
Bye, Peter Korsgaard

^ permalink raw reply

* Re: [PATCH] Slight refactor of interrupt mapping for FSL parts
From: Kumar Gala @ 2006-10-16 21:54 UTC (permalink / raw)
  To: Andy Fleming; +Cc: linuxppc-dev@ozlabs.org list, Jeff Garzik
In-Reply-To: <C6870308-059D-40F8-8567-7A11AFAD2AE2@kernel.crashing.org>


On Oct 16, 2006, at 4:37 PM, Kumar Gala wrote:

>
> On Oct 16, 2006, at 3:57 PM, Andy Fleming wrote:
>
>>
>> * 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.
>
> You forgot to fixup the arch/ppc users of this.
>
>
>> ---
>>  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;
>> +}
>
> Why don't you stick this in prom_parse.c (and add a prototype to  
> prom.h)

Actually, just implement it in the header.

- k

^ permalink raw reply

* RE: [PATCH] Slight refactor of interrupt mapping for FSL parts
From: Joakim Tjernlund @ 2006-10-16 21:51 UTC (permalink / raw)
  To: 'Kumar Gala', 'Andy Fleming'
  Cc: linuxppc-dev, 'Jeff Garzik'
In-Reply-To: <C6870308-059D-40F8-8567-7A11AFAD2AE2@kernel.crashing.org>

> > -#define PHY_POLL		-1
> > +#define PHY_POLL		NO_IRQ
> >  #define PHY_IGNORE_INTERRUPT	-2

What does PHY_IGNORE_INTERRUPT mean? Can I use that in a dummy PHY
driver that just pretends that all is well? Got a ethernet port that
is connect to a switch directly over MII.
How do I express -2 in a dts file?

 Jocke

^ permalink raw reply

* Re: [PATCH] Slight refactor of interrupt mapping for FSL parts
From: Kumar Gala @ 2006-10-16 21:37 UTC (permalink / raw)
  To: Andy Fleming; +Cc: linuxppc-dev, Jeff Garzik
In-Reply-To: <Pine.LNX.4.61.0610161554580.6266@ld0175-tx32.am.freescale.net>


On Oct 16, 2006, at 3:57 PM, Andy Fleming wrote:

>
> * 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.

You forgot to fixup the arch/ppc users of this.


> ---
>  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;
> +}

Why don't you stick this in prom_parse.c (and add a prototype to prom.h)

> +
>  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

* [PATCH] fixup ARCH=ppc timer_interrupt after global pt_regs
From: Peter Korsgaard @ 2006-10-16 19:20 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

* [PATCH] Fixed up the OF functions to only do PCI stuff if PCI is actually configured
From: Andy Fleming @ 2006-10-16 21:03 UTC (permalink / raw)
  To: linuxppc-dev, Kumar Gala

The original problem that inspired this patch was solved quite some time 
ago (Turning off PCI didn't work), but this patch neatens things up a 
little (I think), by putting all the PCI stuff inside a single CONFIG_PCI 
block.  It also removes the OF PCI bus matching entries if CONFIG_PCI is 
off.

---

 arch/powerpc/kernel/prom_parse.c |  288 ++++++++++++++++++++------------------
 1 files changed, 148 insertions(+), 140 deletions(-)

diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c
index 603dff3..346fb7b 100644
--- a/arch/powerpc/kernel/prom_parse.c
+++ b/arch/powerpc/kernel/prom_parse.c
@@ -25,6 +25,12 @@ #define OF_MAX_ADDR_CELLS	4
 #define OF_CHECK_COUNTS(na, ns)	((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \
 			(ns) > 0)
 
+static struct of_bus *of_match_bus(struct device_node *np);
+static int __of_address_to_resource(struct device_node *dev,
+		const u32 *addrp, u64 size, unsigned int flags,
+		struct resource *r);
+
+
 /* Debug utility */
 #ifdef DEBUG
 static void of_dump_addr(const char *s, const u32 *addr, int na)
@@ -101,6 +107,7 @@ static unsigned int of_bus_default_get_f
 }
 
 
+#ifdef CONFIG_PCI
 /*
  * PCI bus specific translator
  */
@@ -162,6 +169,145 @@ static unsigned int of_bus_pci_get_flags
 	return flags;
 }
 
+const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
+			unsigned int *flags)
+{
+	const u32 *prop;
+	unsigned int psize;
+	struct device_node *parent;
+	struct of_bus *bus;
+	int onesize, i, na, ns;
+
+	/* Get parent & match bus type */
+	parent = of_get_parent(dev);
+	if (parent == NULL)
+		return NULL;
+	bus = of_match_bus(parent);
+	if (strcmp(bus->name, "pci")) {
+		of_node_put(parent);
+		return NULL;
+	}
+	bus->count_cells(dev, &na, &ns);
+	of_node_put(parent);
+	if (!OF_CHECK_COUNTS(na, ns))
+		return NULL;
+
+	/* Get "reg" or "assigned-addresses" property */
+	prop = get_property(dev, bus->addresses, &psize);
+	if (prop == NULL)
+		return NULL;
+	psize /= 4;
+
+	onesize = na + ns;
+	for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++)
+		if ((prop[0] & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) {
+			if (size)
+				*size = of_read_number(prop + na, ns);
+			if (flags)
+				*flags = bus->get_flags(prop);
+			return prop;
+		}
+	return NULL;
+}
+EXPORT_SYMBOL(of_get_pci_address);
+
+int of_pci_address_to_resource(struct device_node *dev, int bar,
+			       struct resource *r)
+{
+	const u32	*addrp;
+	u64		size;
+	unsigned int	flags;
+
+	addrp = of_get_pci_address(dev, bar, &size, &flags);
+	if (addrp == NULL)
+		return -EINVAL;
+	return __of_address_to_resource(dev, addrp, size, flags, r);
+}
+EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
+
+static u8 of_irq_pci_swizzle(u8 slot, u8 pin)
+{
+	return (((pin - 1) + slot) % 4) + 1;
+}
+
+int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
+{
+	struct device_node *dn, *ppnode;
+	struct pci_dev *ppdev;
+	u32 lspec;
+	u32 laddr[3];
+	u8 pin;
+	int rc;
+
+	/* Check if we have a device node, if yes, fallback to standard OF
+	 * parsing
+	 */
+	dn = pci_device_to_OF_node(pdev);
+	if (dn)
+		return of_irq_map_one(dn, 0, out_irq);
+
+	/* Ok, we don't, time to have fun. Let's start by building up an
+	 * interrupt spec.  we assume #interrupt-cells is 1, which is standard
+	 * for PCI. If you do different, then don't use that routine.
+	 */
+	rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
+	if (rc != 0)
+		return rc;
+	/* No pin, exit */
+	if (pin == 0)
+		return -ENODEV;
+
+	/* Now we walk up the PCI tree */
+	lspec = pin;
+	for (;;) {
+		/* Get the pci_dev of our parent */
+		ppdev = pdev->bus->self;
+
+		/* Ouch, it's a host bridge... */
+		if (ppdev == NULL) {
+#ifdef CONFIG_PPC64
+			ppnode = pci_bus_to_OF_node(pdev->bus);
+#else
+			struct pci_controller *host;
+			host = pci_bus_to_host(pdev->bus);
+			ppnode = host ? host->arch_data : NULL;
+#endif
+			/* No node for host bridge ? give up */
+			if (ppnode == NULL)
+				return -EINVAL;
+		} else
+			/* We found a P2P bridge, check if it has a node */
+			ppnode = pci_device_to_OF_node(ppdev);
+
+		/* Ok, we have found a parent with a device-node, hand over to
+		 * the OF parsing code.
+		 * We build a unit address from the linux device to be used for
+		 * resolution. Note that we use the linux bus number which may
+		 * not match your firmware bus numbering.
+		 * Fortunately, in most cases, interrupt-map-mask doesn't include
+		 * the bus number as part of the matching.
+		 * You should still be careful about that though if you intend
+		 * to rely on this function (you ship  a firmware that doesn't
+		 * create device nodes for all PCI devices).
+		 */
+		if (ppnode)
+			break;
+
+		/* We can only get here if we hit a P2P bridge with no node,
+		 * let's do standard swizzling and try again
+		 */
+		lspec = of_irq_pci_swizzle(PCI_SLOT(pdev->devfn), lspec);
+		pdev = ppdev;
+	}
+
+	laddr[0] = (pdev->bus->number << 16)
+		| (pdev->devfn << 8);
+	laddr[1]  = laddr[2] = 0;
+	return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
+}
+EXPORT_SYMBOL_GPL(of_irq_map_pci);
+#endif /* CONFIG_PCI */
+
 /*
  * ISA bus specific translator
  */
@@ -223,6 +369,7 @@ static unsigned int of_bus_isa_get_flags
  */
 
 static struct of_bus of_busses[] = {
+#ifdef CONFIG_PCI
 	/* PCI */
 	{
 		.name = "pci",
@@ -233,6 +380,7 @@ static struct of_bus of_busses[] = {
 		.translate = of_bus_pci_translate,
 		.get_flags = of_bus_pci_get_flags,
 	},
+#endif /* CONFIG_PCI */
 	/* ISA */
 	{
 		.name = "isa",
@@ -445,48 +593,6 @@ const u32 *of_get_address(struct device_
 }
 EXPORT_SYMBOL(of_get_address);
 
-const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
-			unsigned int *flags)
-{
-	const u32 *prop;
-	unsigned int psize;
-	struct device_node *parent;
-	struct of_bus *bus;
-	int onesize, i, na, ns;
-
-	/* Get parent & match bus type */
-	parent = of_get_parent(dev);
-	if (parent == NULL)
-		return NULL;
-	bus = of_match_bus(parent);
-	if (strcmp(bus->name, "pci")) {
-		of_node_put(parent);
-		return NULL;
-	}
-	bus->count_cells(dev, &na, &ns);
-	of_node_put(parent);
-	if (!OF_CHECK_COUNTS(na, ns))
-		return NULL;
-
-	/* Get "reg" or "assigned-addresses" property */
-	prop = get_property(dev, bus->addresses, &psize);
-	if (prop == NULL)
-		return NULL;
-	psize /= 4;
-
-	onesize = na + ns;
-	for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++)
-		if ((prop[0] & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) {
-			if (size)
-				*size = of_read_number(prop + na, ns);
-			if (flags)
-				*flags = bus->get_flags(prop);
-			return prop;
-		}
-	return NULL;
-}
-EXPORT_SYMBOL(of_get_pci_address);
-
 static int __of_address_to_resource(struct device_node *dev, const u32 *addrp,
 				    u64 size, unsigned int flags,
 				    struct resource *r)
@@ -529,20 +635,6 @@ int of_address_to_resource(struct device
 }
 EXPORT_SYMBOL_GPL(of_address_to_resource);
 
-int of_pci_address_to_resource(struct device_node *dev, int bar,
-			       struct resource *r)
-{
-	const u32	*addrp;
-	u64		size;
-	unsigned int	flags;
-
-	addrp = of_get_pci_address(dev, bar, &size, &flags);
-	if (addrp == NULL)
-		return -EINVAL;
-	return __of_address_to_resource(dev, addrp, size, flags, r);
-}
-EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
-
 void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
 		unsigned long *busno, unsigned long *phys, unsigned long *size)
 {
@@ -898,87 +990,3 @@ int of_irq_map_one(struct device_node *d
 	return res;
 }
 EXPORT_SYMBOL_GPL(of_irq_map_one);
-
-#ifdef CONFIG_PCI
-static u8 of_irq_pci_swizzle(u8 slot, u8 pin)
-{
-	return (((pin - 1) + slot) % 4) + 1;
-}
-
-int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
-{
-	struct device_node *dn, *ppnode;
-	struct pci_dev *ppdev;
-	u32 lspec;
-	u32 laddr[3];
-	u8 pin;
-	int rc;
-
-	/* Check if we have a device node, if yes, fallback to standard OF
-	 * parsing
-	 */
-	dn = pci_device_to_OF_node(pdev);
-	if (dn)
-		return of_irq_map_one(dn, 0, out_irq);
-
-	/* Ok, we don't, time to have fun. Let's start by building up an
-	 * interrupt spec.  we assume #interrupt-cells is 1, which is standard
-	 * for PCI. If you do different, then don't use that routine.
-	 */
-	rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
-	if (rc != 0)
-		return rc;
-	/* No pin, exit */
-	if (pin == 0)
-		return -ENODEV;
-
-	/* Now we walk up the PCI tree */
-	lspec = pin;
-	for (;;) {
-		/* Get the pci_dev of our parent */
-		ppdev = pdev->bus->self;
-
-		/* Ouch, it's a host bridge... */
-		if (ppdev == NULL) {
-#ifdef CONFIG_PPC64
-			ppnode = pci_bus_to_OF_node(pdev->bus);
-#else
-			struct pci_controller *host;
-			host = pci_bus_to_host(pdev->bus);
-			ppnode = host ? host->arch_data : NULL;
-#endif
-			/* No node for host bridge ? give up */
-			if (ppnode == NULL)
-				return -EINVAL;
-		} else
-			/* We found a P2P bridge, check if it has a node */
-			ppnode = pci_device_to_OF_node(ppdev);
-
-		/* Ok, we have found a parent with a device-node, hand over to
-		 * the OF parsing code.
-		 * We build a unit address from the linux device to be used for
-		 * resolution. Note that we use the linux bus number which may
-		 * not match your firmware bus numbering.
-		 * Fortunately, in most cases, interrupt-map-mask doesn't include
-		 * the bus number as part of the matching.
-		 * You should still be careful about that though if you intend
-		 * to rely on this function (you ship  a firmware that doesn't
-		 * create device nodes for all PCI devices).
-		 */
-		if (ppnode)
-			break;
-
-		/* We can only get here if we hit a P2P bridge with no node,
-		 * let's do standard swizzling and try again
-		 */
-		lspec = of_irq_pci_swizzle(PCI_SLOT(pdev->devfn), lspec);
-		pdev = ppdev;
-	}
-
-	laddr[0] = (pdev->bus->number << 16)
-		| (pdev->devfn << 8);
-	laddr[1]  = laddr[2] = 0;
-	return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
-}
-EXPORT_SYMBOL_GPL(of_irq_map_pci);
-#endif /* CONFIG_PCI */
-- 
1.4.2.3

^ 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

* 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

* 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", &reg_base, sizeof(reg_base));
+	if (n != sizeof(reg_base))
+		return -1;
+
+	n = getprop(devp, "reg-shift", &reg_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: 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 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: [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] 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


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