* Re: [PATCH v3 07/13] [POWERPC] TQM5200 DTS
From: David Gibson @ 2007-11-06 22:36 UTC (permalink / raw)
To: Marian Balakowicz; +Cc: linuxppc-dev
In-Reply-To: <20071106200548.10913.42168.stgit@hekate.izotz.org>
On Tue, Nov 06, 2007 at 09:05:48PM +0100, Marian Balakowicz wrote:
> Add device tree source file for TQM5200 board.
>
> Signed-off-by: Marian Balakowicz <m8@semihalf.com>
[snip]
> + usb@1000 {
> + device_type = "usb-ohci-be";
This device_type is bogus. Remember having a valid device_type is the
exception not the rule. Really the only common device_type values are
"cpu", "memory", "network" and "serial".
> + compatible = "mpc5200-ohci","ohci-be";
> + reg = <1000 ff>;
> + interrupts = <2 6 0>;
> + interrupt-parent = <&mpc5200_pic>;
> + };
> +
> + dma-controller@1200 {
> + compatible = "mpc5200-bestcomm";
> + reg = <1200 80>;
> + interrupts = <3 0 0 3 1 0 3 2 0 3 3 0
> + 3 4 0 3 5 0 3 6 0 3 7 0
> + 3 8 0 3 9 0 3 a 0 3 b 0
> + 3 c 0 3 d 0 3 e 0 3 f 0>;
> + interrupt-parent = <&mpc5200_pic>;
> + };
> +
> + xlb@1f00 {
> + compatible = "mpc5200-xlb";
> + reg = <1f00 100>;
> + };
> +
> + serial@2000 { // PSC1
> + device_type = "serial";
> + compatible = "mpc5200-psc-uart";
> + port-number = <0>; // Logical port assignment
I know you said this is still needed, but the driver really needs to
be fixed. This is not a proper way of using the device tree for
logical numbering.
--
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
* [PATCH 0/2] [PPC 4xx] L2-cache synchronization for ppc44x
From: Yuri Tikhonov @ 2007-11-06 22:40 UTC (permalink / raw)
To: linuxppc-dev; +Cc: sr, dzu
Hello all,
Here is a patch-set for support L2-cache synchronization routines for
the ppc44x processors family. I know that the "ppc" branch is for bug-fixing only, thus
the patch-set is just FYI [though enabled but non-coherent L2-cache may appear as a bug for
someone who uses one of the boards listed below :)].
[PATCH 1/2] [PPC 4xx] invalidate_l2cache_range() implementation for ppc44x;
[PATCH 2/2] [PPC 44x] enable L2-cache for the following ppc44x-based boards: ALPR,
Katmai, Ocotea, and Taishan.
Regards, Yuri
--
Yuri Tikhonov, Senior Software Engineer
Emcraft Systems, www.emcraft.com
^ permalink raw reply
* [PATCH 1/2] [PPC 4xx] invalidate_l2cache_range() implementation for ppc44x
From: Yuri Tikhonov @ 2007-11-06 22:40 UTC (permalink / raw)
To: linuxppc-dev; +Cc: sr, dzu
Support for L2-cache coherency synchronization routines in ppc44x
processors.
Signed-off-by: Yuri Tikhonov <yur@emcraft.com>
Signed-off-by: Pavel Kolesnikov <concord@emcraft.com>
--
diff --git a/arch/powerpc/lib/dma-noncoherent.c b/arch/powerpc/lib/dma-noncoherent.c
index 1947380..593a425 100644
--- a/arch/powerpc/lib/dma-noncoherent.c
+++ b/arch/powerpc/lib/dma-noncoherent.c
@@ -351,12 +351,18 @@ void __dma_sync(void *vaddr, size_t size, int direction)
BUG();
case DMA_FROM_DEVICE: /* invalidate only */
invalidate_dcache_range(start, end);
+#ifdef CONFIG_L2_CACHE
+ invalidate_l2cache_range(__pa(start), __pa(end));
+#endif
break;
case DMA_TO_DEVICE: /* writeback only */
clean_dcache_range(start, end);
break;
case DMA_BIDIRECTIONAL: /* writeback and invalidate */
flush_dcache_range(start, end);
+#ifdef CONFIG_L2_CACHE
+ invalidate_l2cache_range(__pa(start), __pa(end));
+#endif
break;
}
}
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index 46cf8fa..de62f85 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -386,6 +386,36 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
sync /* additional sync needed on g4 */
isync
blr
+
+#ifdef CONFIG_L2_CACHE
+/*
+ * Invalidate the Level-2 cache lines corresponded to the address
+ * range.
+ *
+ * invalidate_l2cache_range(unsigned long start, unsigned long stop)
+ */
+#include <asm/ibm4xx.h>
+_GLOBAL(invalidate_l2cache_range)
+ li r5,L2_CACHE_BYTES-1 /* do l2-cache line alignment */
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+ srwi. r4,r4,L2_CACHE_SHIFT
+ mtctr r4
+
+ lis r4, L2C_CMD_INV>>16
+1: mtdcr DCRN_L2C0_ADDR,r3 /* write address to invalidate */
+ mtdcr DCRN_L2C0_CMD,r4 /* issue the Invalidate cmd */
+
+2: mfdcr r5,DCRN_L2C0_SR /* wait for complete */
+ andis. r5,r5,L2C_CMD_CLR>>16
+ beq 2b
+
+ addi r3,r3,L2_CACHE_BYTES /* next address to invalidate */
+ bdnz 1b
+ blr
+#endif
+
/*
* Write any modified data cache blocks out to memory.
* Does not invalidate the corresponding cache lines (especially for
diff --git a/include/asm-powerpc/cache.h b/include/asm-powerpc/cache.h
index 5350704..8a2f9e6 100644
--- a/include/asm-powerpc/cache.h
+++ b/include/asm-powerpc/cache.h
@@ -10,12 +10,14 @@
#define MAX_COPY_PREFETCH 1
#elif defined(CONFIG_PPC32)
#define L1_CACHE_SHIFT 5
+#define L2_CACHE_SHIFT 5
#define MAX_COPY_PREFETCH 4
#else /* CONFIG_PPC64 */
#define L1_CACHE_SHIFT 7
#endif
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
+#define L2_CACHE_BYTES (1 << L2_CACHE_SHIFT)
#define SMP_CACHE_BYTES L1_CACHE_BYTES
diff --git a/include/asm-powerpc/cacheflush.h b/include/asm-powerpc/cacheflush.h
index ba667a3..bdebfaa 100644
--- a/include/asm-powerpc/cacheflush.h
+++ b/include/asm-powerpc/cacheflush.h
@@ -49,6 +49,7 @@ extern void flush_dcache_range(unsigned long start, unsigned long stop);
#ifdef CONFIG_PPC32
extern void clean_dcache_range(unsigned long start, unsigned long stop);
extern void invalidate_dcache_range(unsigned long start, unsigned long stop);
+extern void invalidate_l2cache_range(unsigned long start, unsigned long stop);
#endif /* CONFIG_PPC32 */
#ifdef CONFIG_PPC64
extern void flush_inval_dcache_range(unsigned long start, unsigned long stop);
diff --git a/include/asm-ppc/ibm44x.h b/include/asm-ppc/ibm44x.h
index 8078a58..782909a 100644
--- a/include/asm-ppc/ibm44x.h
+++ b/include/asm-ppc/ibm44x.h
@@ -138,7 +138,6 @@
* The "residual" board information structure the boot loader passes
* into the kernel.
*/
-#ifndef __ASSEMBLY__
/*
* DCRN definitions
@@ -814,6 +813,5 @@
#include <asm/ibm4xx.h>
-#endif /* __ASSEMBLY__ */
#endif /* __ASM_IBM44x_H__ */
#endif /* __KERNEL__ */
^ permalink raw reply related
* [PATCH 2/2] [PPC 44x] enable L2-cache for ALPR, Katmai, Ocotea, and Taishan
From: Yuri Tikhonov @ 2007-11-06 22:40 UTC (permalink / raw)
To: linuxppc-dev; +Cc: sr, dzu
This patch introduces the L2_CACHE configuration option available
for the ppc44x-based boards with L2-cache enabled.
Signed-off-by: Yuri Tikhonov <yur@emcraft.com>
Signed-off-by: Pavel Kolesnikov <concord@emcraft.com>
--
diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig
index 1d2ca42..ad6b581 100644
--- a/arch/ppc/platforms/4xx/Kconfig
+++ b/arch/ppc/platforms/4xx/Kconfig
@@ -396,4 +396,12 @@ config SERIAL_SICC_CONSOLE
bool
depends on SERIAL_SICC && UART0_TTYS1
default y
+
+config L2_CACHE
+ bool "Enable Level-2 Cache"
+ depends on NOT_COHERENT_CACHE && (KATMAI || TAISHAN || OCOTEA || ALPR)
+ default y
+ help
+ This option enables L2-cache on ppc44x controllers.
+ If unsure, say Y.
endmenu
diff --git a/arch/ppc/platforms/4xx/alpr.c b/arch/ppc/platforms/4xx/alpr.c
index 3b6519f..0623801 100644
--- a/arch/ppc/platforms/4xx/alpr.c
+++ b/arch/ppc/platforms/4xx/alpr.c
@@ -537,10 +537,12 @@ static void __init alpr_setup_arch(void)
printk("Prodrive ALPR port (DENX Software Engineering <sr@denx.de>)\n");
}
+#ifdef CONFIG_L2_CACHE
static void __init alpr_init(void)
{
ibm440gx_l2c_setup(&clocks);
}
+#endif
static void alpr_progress(char *buf, unsigned short val)
{
@@ -567,7 +569,9 @@ void __init platform_init(unsigned long r3, unsigned long r4,
#ifdef CONFIG_KGDB
ppc_md.early_serial_map = alpr_early_serial_map;
#endif
+#ifdef CONFIG_L2_CACHE
ppc_md.init = alpr_init;
+#endif
ppc_md.restart = alpr_restart;
}
diff --git a/arch/ppc/platforms/4xx/katmai.c b/arch/ppc/platforms/4xx/katmai.c
index d29ebf6..01f1baf 100644
--- a/arch/ppc/platforms/4xx/katmai.c
+++ b/arch/ppc/platforms/4xx/katmai.c
@@ -219,6 +219,7 @@ katmai_show_cpuinfo(struct seq_file *m)
{
seq_printf(m, "vendor\t\t: AMCC\n");
seq_printf(m, "machine\t\t: PPC440SPe EVB (Katmai)\n");
+ ibm440gx_show_cpuinfo(m);
return 0;
}
@@ -584,6 +585,13 @@ static void katmai_restart(char *cmd)
mtspr(SPRN_DBCR0, DBCR0_RST_CHIP);
}
+#ifdef CONFIG_L2_CACHE
+static void __init katmai_init(void)
+{
+ ibm440gx_l2c_setup(&clocks);
+}
+#endif
+
void __init platform_init(unsigned long r3, unsigned long r4,
unsigned long r5, unsigned long r6, unsigned long r7)
{
@@ -599,4 +607,7 @@ void __init platform_init(unsigned long r3, unsigned long r4,
ppc_md.early_serial_map = katmai_early_serial_map;
#endif
ppc_md.restart = katmai_restart;
+#ifdef CONFIG_L2_CACHE
+ ppc_md.init = katmai_init;
+#endif
}
diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c
index a7435aa..8b13811 100644
--- a/arch/ppc/platforms/4xx/ocotea.c
+++ b/arch/ppc/platforms/4xx/ocotea.c
@@ -321,10 +321,12 @@ ocotea_setup_arch(void)
printk("IBM Ocotea port (MontaVista Software, Inc. <source@mvista.com>)\n");
}
+#ifdef CONFIG_L2_CACHE
static void __init ocotea_init(void)
{
ibm440gx_l2c_setup(&clocks);
}
+#endif
void __init platform_init(unsigned long r3, unsigned long r4,
unsigned long r5, unsigned long r6, unsigned long r7)
@@ -345,5 +347,7 @@ void __init platform_init(unsigned long r3, unsigned long r4,
#ifdef CONFIG_KGDB
ppc_md.early_serial_map = ocotea_early_serial_map;
#endif
+#ifdef CONFIG_L2_CACHE
ppc_md.init = ocotea_init;
+#endif
}
diff --git a/arch/ppc/platforms/4xx/taishan.c b/arch/ppc/platforms/4xx/taishan.c
index f4b9435..8bb6f15 100644
--- a/arch/ppc/platforms/4xx/taishan.c
+++ b/arch/ppc/platforms/4xx/taishan.c
@@ -370,10 +370,12 @@ taishan_setup_arch(void)
printk("AMCC PowerPC 440GX Taishan Platform\n");
}
+#ifdef CONFIG_L2_CACHE
static void __init taishan_init(void)
{
ibm440gx_l2c_setup(&clocks);
}
+#endif
void __init platform_init(unsigned long r3, unsigned long r4,
unsigned long r5, unsigned long r6, unsigned long r7)
@@ -389,6 +391,8 @@ void __init platform_init(unsigned long r3, unsigned long r4,
#ifdef CONFIG_KGDB
ppc_md.early_serial_map = taishan_early_serial_map;
#endif
+#ifdef CONFIG_L2_CACHE
ppc_md.init = taishan_init;
+#endif
}
^ permalink raw reply related
* Re: [PATCH v3 12/13] [POWERPC] Promess Motion-PRO DTS
From: David Gibson @ 2007-11-06 22:42 UTC (permalink / raw)
To: Marian Balakowicz; +Cc: linuxppc-dev
In-Reply-To: <20071106200634.10913.6248.stgit@hekate.izotz.org>
On Tue, Nov 06, 2007 at 09:06:34PM +0100, Marian Balakowicz wrote:
> Add device tree source file for Motion-PRO board.
>
> Signed-off-by: Marian Balakowicz <m8@semihalf.com>
[snip]
> + motionpro-statusled@660 { // Motion-PRO status LED
> + compatible = "promess,motionpro-statusled";
> + reg = <660 10>;
> + interrupts = <1 f 0>;
> + interrupt-parent = <&mpc5200_pic>;
> + blink-delay = <64>; // 100 msec
> + };
> +
> + motionpro-readyled@670 { // Motion-PRO ready LED
> + compatible = "promess,motionpro-readyled";
> + reg = <670 10>;
> + interrupts = <1 10 0>;
> + interrupt-parent = <&mpc5200_pic>;
> + };
Is there actually any difference in behaviour betweeen the two LEDs?
If not, they should probably have the same compatible value, and
perhaps a "label" property or some such to associate them with a
particular LED.
[snip]
> + spi@f00 {
> + device_type = "spi";
No device_type!
> + compatible = "mpc5200b-spi","mpc5200-spi";
> + reg = <f00 20>;
> + interrupts = <2 d 0 2 e 0>;
> + interrupt-parent = <&mpc5200_pic>;
> + };
> +
> + usb@1000 {
> + device_type = "usb-ohci-be";
Nor here.
> + compatible = "mpc5200b-ohci","mpc5200-ohci","ohci-be";
> + reg = <1000 ff>;
> + interrupts = <2 6 0>;
> + interrupt-parent = <&mpc5200_pic>;
> + };
[snip]
> + // PSC2 in spi master mode
> + spi@2200 { // PSC2
> + compatible = "mpc5200b-psc-spi","mpc5200-psc-spi";
> + cell-index = <1>;
>From your description, this is an incorrect usage of cell-index - it
should *only* be used to index into SoC shared registers; never for
logical numbering.
> + reg = <2200 100>;
> + interrupts = <2 2 0>;
> + interrupt-parent = <&mpc5200_pic>;
> + };
--
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: mmap question on ppc440
From: Josh Boyer @ 2007-11-06 22:59 UTC (permalink / raw)
To: benh; +Cc: linuxppc-dev, Stefan Roese
In-Reply-To: <1194386530.6523.37.camel@pasglop>
On Wed, 07 Nov 2007 09:02:10 +1100
Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
>
> On Tue, 2007-11-06 at 07:50 +0100, Stefan Roese wrote:
> > On Monday 05 November 2007, Josh Boyer wrote:
> > > > I am attempting to access the CPLD on the AMCC Sequoia board from
> > > > user-land. I open /dev/mem, and mmap it, then try to access the
> > > > resulting pointer. That works fine when accessing physical addresses
> > > > that correspond to RAM, but as soon as I try to access the CPLD at
> > > > physical address 0xc0000000, I get an infinite machine check.
> > >
> > > That's because the CPLD is actually at physical address 0x1C0000000.
> > > Yay for 36-bit physical addresses.
> >
> > Right. Are you using arch/ppc or arch/powerpc? If it's arch/ppc you could
> > give the following patch a try:
> >
> > @@ -275,6 +275,14 @@
> > {
> > size_t size = vma->vm_end - vma->vm_start;
> >
> > +#if defined(CONFIG_44x) && !defined(CONFIG_PPC_MERGE)
> > + /*
> > + * 2006-08-07: sr
> > + * Needed on 44x-er systems for 36bit addresses (like pci on 440gx)
> > + */
> > + vma->vm_pgoff = (fixup_bigphys_addr(vma->vm_pgoff << PAGE_SHIFT, size) >> PAGE_SHIFT);
> > +#endif
> > +
> > if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size))
> > return -EINVAL;
>
> I think we need to ditch the bigphys fixup stuff and come up with a way
> to make /dev/mem work with the actual 36 bits offsets (after all, it's
> all pgoff, it should work).
We did ditch bigphys in arch/powerpc. mmap64 works apparently.
> The other problem is X of course... 32 bits X server currently cannot
> cope with physical addresses > 32 bits at all. They will just blow up or
> randomly scribble over /dev/mem.
>
> The solution is libpciaccess and the new pci-rework branch of X which
> uses it, but I haven't had a chance to test that properly yet on 4xx.
Um... because arch/powerpc 4xx doesn't have PCI support? :) You and
Valentine and Vitaly keep trading emails about it though, which is a
good sign.
josh
^ permalink raw reply
* Re: [RFC/PATCH] Fix rtas_ibm_suspend_me bugs
From: jschopp @ 2007-11-06 23:08 UTC (permalink / raw)
To: Nathan Lynch; +Cc: linuxppc-dev
In-Reply-To: <20071106044309.GK9695@localdomain>
> - for_each_possible_cpu(i)
> - plpar_hcall_norets(H_PROD,i);
...
> + for_each_online_cpu(i)
> + plpar_hcall_norets(H_PROD, get_hard_smp_processor_id(i));
I assume this bit would be non-contriversial and could be sent up for
immediate upstream inclusion.
Nathan Lynch wrote:
> (very rfc for now, no sign-off, needs more testing)
>
> There are a couple of bugs in the rtas_ibm_suspend_me() and
> rtas_percpu_suspend_me() functions:
>
> 1. rtas_ibm_suspend_me() uses on_each_cpu() to invoke
> rtas_percpu_suspend_me() via IPI:
>
> if (on_each_cpu(rtas_percpu_suspend_me, &data, 1, 0))
> ...
>
> 'data' is on the stack, and rtas_ibm_suspend_me() takes no measures to
> ensure that all instances of rtas_percpu_suspend_me() are finished
> accessing 'data' before returning. This can result in the IPI'd cpus
> accessing random stack data and getting stuck in H_JOIN.
>
> Fix this by moving rtas_suspend_me_data off the stack, and protect it
> with a mutex. Use a completion to ensure that all cpus are done
> accessing the data before unlocking.
>
> 2. rtas_percpu_suspend_me passes the Linux logical cpu id to the
> H_PROD hypervisor method, when it should be using the platform
> interrupt server value for that cpu (hard_smp_processor_id). In
> practice, this probably causes problems only on partitions where
> processors have been removed and added in a particular order.
>
> ---
> arch/powerpc/kernel/rtas.c | 64 ++++++++++++++++++++++++++++++++-----------
> 1 files changed, 47 insertions(+), 17 deletions(-)
>
> diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
> index 2147807..24faaea 100644
> --- a/arch/powerpc/kernel/rtas.c
> +++ b/arch/powerpc/kernel/rtas.c
> @@ -19,6 +19,9 @@
> #include <linux/init.h>
> #include <linux/capability.h>
> #include <linux/delay.h>
> +#include <linux/mutex.h>
> +#include <linux/completion.h>
> +#include <linux/smp.h>
>
> #include <asm/prom.h>
> #include <asm/rtas.h>
> @@ -34,6 +37,7 @@
> #include <asm/lmb.h>
> #include <asm/udbg.h>
> #include <asm/syscalls.h>
> +#include <asm/atomic.h>
>
> struct rtas_t rtas = {
> .lock = SPIN_LOCK_UNLOCKED
> @@ -41,10 +45,21 @@ struct rtas_t rtas = {
> EXPORT_SYMBOL(rtas);
>
> struct rtas_suspend_me_data {
> + atomic_t working; /* number of cpus accessing rtas_suspend_me_data */
> long waiting;
> struct rtas_args *args;
> + struct completion done; /* wait on this until working == 0 */
> };
>
> +static void rtas_suspend_me_data_init(struct rtas_suspend_me_data *rsmd,
> + struct rtas_args *args)
> +{
> + atomic_set(&rsmd->working, 0);
> + rsmd->waiting = 1;
> + rsmd->args = args;
> + init_completion(&rsmd->done);
> +}
> +
> DEFINE_SPINLOCK(rtas_data_buf_lock);
> EXPORT_SYMBOL(rtas_data_buf_lock);
>
> @@ -671,36 +686,49 @@ static void rtas_percpu_suspend_me(void *info)
> * we set it to <0.
> */
> local_irq_save(flags);
> + atomic_inc(&data->working);
> do {
> rc = plpar_hcall_norets(H_JOIN);
> smp_rmb();
> } while (rc == H_SUCCESS && data->waiting > 0);
> if (rc == H_SUCCESS)
> + /* join is complete (or there was an error) and this
> + * cpu was prodded
> + */
> goto out;
>
> if (rc == H_CONTINUE) {
> + /* this cpu does the join */
> data->waiting = 0;
> data->args->args[data->args->nargs] =
> rtas_call(ibm_suspend_me_token, 0, 1, NULL);
> - for_each_possible_cpu(i)
> - plpar_hcall_norets(H_PROD,i);
> } else {
> data->waiting = -EBUSY;
> printk(KERN_ERR "Error on H_JOIN hypervisor call\n");
> }
>
> + /* This cpu did the join or got an error, so we need to prod
> + * everyone else. Extra prods are harmless.
> + */
> + for_each_online_cpu(i)
> + plpar_hcall_norets(H_PROD, get_hard_smp_processor_id(i));
> +
> out:
> + if (atomic_dec_return(&data->working) == 0)
> + complete(&data->done);
> local_irq_restore(flags);
> return;
> }
>
> +static DEFINE_MUTEX(rsm_lock); /* protects rsm_data */
> +static struct rtas_suspend_me_data rsm_data;
> +
> static int rtas_ibm_suspend_me(struct rtas_args *args)
> {
> - int i;
> + int err;
> long state;
> long rc;
> unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
> - struct rtas_suspend_me_data data;
>
> /* Make sure the state is valid */
> rc = plpar_hcall(H_VASI_STATE, retbuf,
> @@ -721,25 +749,27 @@ static int rtas_ibm_suspend_me(struct rtas_args *args)
> return 0;
> }
>
> - data.waiting = 1;
> - data.args = args;
> + mutex_lock(&rsm_lock);
> +
> + rtas_suspend_me_data_init(&rsm_data, args);
>
> - /* Call function on all CPUs. One of us will make the
> - * rtas call
> + /* Call function on all CPUs. One of us (but not necessarily
> + * this one) will make the ibm,suspend-me call.
> */
> - if (on_each_cpu(rtas_percpu_suspend_me, &data, 1, 0))
> - data.waiting = -EINVAL;
> + if (on_each_cpu(rtas_percpu_suspend_me, &rsm_data, 1, 0))
> + rsm_data.waiting = -EINVAL;
> +
> + /* Must wait for all IPIs to complete before unlocking */
> + wait_for_completion(&rsm_data.done);
>
> - if (data.waiting != 0)
> + if (rsm_data.waiting != 0)
> printk(KERN_ERR "Error doing global join\n");
>
> - /* Prod each CPU. This won't hurt, and will wake
> - * anyone we successfully put to sleep with H_JOIN.
> - */
> - for_each_possible_cpu(i)
> - plpar_hcall_norets(H_PROD, i);
> + err = rsm_data.waiting;
> +
> + mutex_unlock(&rsm_lock);
>
> - return data.waiting;
> + return err;
> }
> #else /* CONFIG_PPC_PSERIES */
> static int rtas_ibm_suspend_me(struct rtas_args *args)
^ permalink raw reply
* Re: [PATCH] DTC: Polish up the DTS Version 1 implementation.
From: David Gibson @ 2007-11-06 23:11 UTC (permalink / raw)
To: Jon Loeliger; +Cc: linuxppc-dev
In-Reply-To: <E1IpWlT-0007Qd-IX@jdl.com>
On Tue, Nov 06, 2007 at 04:19:19PM -0600, Jon Loeliger wrote:
> From: Jon Loeliger <jdl@freescale.com>
>
> Fixes BYTESTRING lexing.
> Allows -O dts output to be emitted in a given (1) format version.
Ok... I'd actually be more inclined to remove the option and just have
-Odts *always* use the newer version.
Having dtc be able to convert dts versions forward is easy and
useful. Coverting backwards is far more complicated, because as well
as the actualy incompatible version changes, there's the question of
which dtc version supported which dts features. Not worth it, I
think.
> Skirts around a range check problem in eval_literal() for now.
>
> Signed-off-by: Jon Loeliger <jdl@freescale.com>
> ---
>
> David,
>
> This patch is directly on top of your prior two patches.
> Lemme know what you think.
On top of my two dts-v1 patches that is, I assume?
> diff --git a/dtc-lexer.l b/dtc-lexer.l
> index 1c262d2..b18c0d1 100644
> --- a/dtc-lexer.l
> +++ b/dtc-lexer.l
> @@ -190,6 +190,10 @@ static int dts_version; /* = 0 */
> <*>. {
> yylloc.filenum = srcpos_filenum;
> yylloc.first_line = yylineno;
> + if (yytext[0] == '[') {
> + DPRINT("BYTESTRING\n");
> + BEGIN(BYTESTRING);
> + }
Ow... that's rather embarrassing, that I didn't even notice I'd
totally broken bytestrings. Really must add some bytestrings to
test_tree1.dts so this actually gets checked by the testsuite.
> if ((yytext[0] == '{')
> || (yytext[0] == ';')) {
> DPRINT("<PROPNODENAME>\n");
> diff --git a/dtc-parser.y b/dtc-parser.y
> index ffb2299..652199f 100644
> --- a/dtc-parser.y
> +++ b/dtc-parser.y
> @@ -297,17 +297,23 @@ label:
>
> %%
>
> -void yyerror (char const *s)
> +void yyerror(char const *s)
> {
> const char *fname = srcpos_filename_for_num(yylloc.filenum);
>
> if (strcmp(fname, "-") == 0)
> fname = "stdin";
>
> - fprintf(stderr, "%s:%d %s\n",
> + fprintf(stderr, "%s:%d Error: %s\n",
> fname, yylloc.first_line, s);
Not really related changes, but whatever..
> }
>
> +/*
> + * bits is unused, but it should be 32 or 64 as needed.
> + *
> + * FIXME: However, with bits == 64, ((1ULL << bits) - 1)
> + * overflows before you can actually do the range test.
> + */
> unsigned long long eval_literal(const char *s, int base, int bits)
> {
> unsigned long long val;
> @@ -317,9 +323,10 @@ unsigned long long eval_literal(const char *s, int base, int bits)
> val = strtoull(s, &e, base);
> if (*e)
> yyerror("bad characters in literal");
> - else if ((errno == ERANGE) || (val > ((1ULL << bits)-1)))
> + else if (errno == ERANGE)
> yyerror("literal out of range");
> else if (errno != 0)
> yyerror("bad literal");
> +
Ok.. I don't understand why you've pulled out the range checking
against bits here.
> return val;
> }
> diff --git a/dtc.c b/dtc.c
> index bbef829..38313f5 100644
> --- a/dtc.c
> +++ b/dtc.c
> @@ -225,7 +225,7 @@ int main(int argc, char *argv[])
> }
>
> if (streq(outform, "dts")) {
> - dt_to_source(outf, bi);
> + dt_to_source(outf, bi, 1);
> } else if (streq(outform, "dtb")) {
> dt_to_blob(outf, bi, outversion, boot_cpuid_phys);
> } else if (streq(outform, "asm")) {
> diff --git a/dtc.h b/dtc.h
> index d080153..ba2027b 100644
> --- a/dtc.h
> +++ b/dtc.h
> @@ -238,7 +238,7 @@ struct boot_info *dt_from_blob(FILE *f);
>
> /* Tree source */
>
> -void dt_to_source(FILE *f, struct boot_info *bi);
> +void dt_to_source(FILE *f, struct boot_info *bi, int dts_version);
> struct boot_info *dt_from_source(const char *f);
>
> /* FS trees */
> diff --git a/treesource.c b/treesource.c
> index 376ebc8..ac0c777 100644
> --- a/treesource.c
> +++ b/treesource.c
> @@ -140,14 +140,18 @@ static void write_propval_string(FILE *f, struct data val)
> fprintf(f, "\";\n");
> }
>
> -static void write_propval_cells(FILE *f, struct data val)
> +static void write_propval_cells(FILE *f, struct data val, int dts_version)
> {
> void *propend = val.val + val.len;
> cell_t *cp = (cell_t *)val.val;
>
> fprintf(f, " = <");
> for (;;) {
> - fprintf(f, "%x", be32_to_cpu(*cp++));
> + if (dts_version == 0) {
> + fprintf(f, "%x", be32_to_cpu(*cp++));
> + } else {
> + fprintf(f, "0x%x", be32_to_cpu(*cp++));
> + }
> if ((void *)cp >= propend)
> break;
> fprintf(f, " ");
> @@ -155,14 +159,18 @@ static void write_propval_cells(FILE *f, struct data val)
> fprintf(f, ">;\n");
> }
>
> -static void write_propval_bytes(FILE *f, struct data val)
> +static void write_propval_bytes(FILE *f, struct data val, int dts_version)
> {
> void *propend = val.val + val.len;
> char *bp = val.val;
>
> fprintf(f, " = [");
> for (;;) {
> - fprintf(f, "%02hhx", *bp++);
> + if (dts_version == 0) {
> + fprintf(f, "%02hhx", *bp++);
> + } else {
> + fprintf(f, "0x%02hhx", *bp++);
> + }
Uh.. not quite right. My patch (intentionally) leaves bytestrings as
pure hex, without 0x. We can argue about whether that's a good idea,
if you like, but in any case input and output should match.
To avoid this sort of problem, I suggest before we apply the dts-v1
transition, we apply the patch I'm working on (I'll try to get it out
today), which adds a bunch of extra testcases checking that using dtc
to go dtb->dts->dtb preserves everything.
--
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
* [1/2] dtc: Refactor printing of property values in -Odts mode
From: David Gibson @ 2007-11-06 23:21 UTC (permalink / raw)
To: Jon Loeliger; +Cc: linuxppc-dev
Currently the main recursive tree printing function,
write_tree_source_node(), calls guess_type() to apply heuristics to
see how to print a property value, then calls the appropriate
write_propval_*() function to print it.
However, future heuristics for handling internal labels and the like
don't work well this way. Therefore, this patch refactors things to
have write_tree_source_node() call a new write_propval() function,
which incorporates the heurstic logic from guess_type() and also calls
the right function to do the actual printing.
No behavioural change.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
treesource.c | 97 +++++++++++++++++++++++------------------------------------
1 file changed, 38 insertions(+), 59 deletions(-)
Index: dtc/treesource.c
===================================================================
--- dtc.orig/treesource.c 2007-11-07 09:55:03.000000000 +1100
+++ dtc/treesource.c 2007-11-07 10:19:13.000000000 +1100
@@ -49,13 +49,6 @@
fputc('\t', f);
}
-enum proptype {
- PROP_EMPTY,
- PROP_STRING,
- PROP_CELLS,
- PROP_BYTES,
-};
-
int isstring(char c)
{
return (isprint(c)
@@ -63,31 +56,6 @@
|| strchr("\a\b\t\n\v\f\r", c));
}
-static enum proptype guess_type(struct property *prop)
-{
- int len = prop->val.len;
- char *p = prop->val.val;
- int nnotstring = 0, nnul = 0;
- int i;
-
- if (len == 0)
- return PROP_EMPTY;
-
- for (i = 0; i < len; i++) {
- if (! isstring(p[i]))
- nnotstring++;
- if (p[i] == '\0')
- nnul++;
- }
-
- if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul)))
- return PROP_STRING;
- else if ((len % sizeof(cell_t)) == 0)
- return PROP_CELLS;
- else
- return PROP_BYTES;
-}
-
static void write_propval_string(FILE *f, struct data val)
{
char *str = val.val;
@@ -95,7 +63,7 @@
assert(str[val.len-1] == '\0');
- fprintf(f, " = \"");
+ fprintf(f, "\"");
for (i = 0; i < (val.len-1); i++) {
char c = str[i];
@@ -137,7 +105,7 @@
fprintf(f, "\\x%02hhx", c);
}
}
- fprintf(f, "\";\n");
+ fprintf(f, "\"");
}
static void write_propval_cells(FILE *f, struct data val)
@@ -145,14 +113,14 @@
void *propend = val.val + val.len;
cell_t *cp = (cell_t *)val.val;
- fprintf(f, " = <");
+ fprintf(f, "<");
for (;;) {
fprintf(f, "%x", be32_to_cpu(*cp++));
if ((void *)cp >= propend)
break;
fprintf(f, " ");
}
- fprintf(f, ">;\n");
+ fprintf(f, ">");
}
static void write_propval_bytes(FILE *f, struct data val)
@@ -160,14 +128,45 @@
void *propend = val.val + val.len;
char *bp = val.val;
- fprintf(f, " = [");
+ fprintf(f, "[");
for (;;) {
fprintf(f, "%02hhx", *bp++);
if ((void *)bp >= propend)
break;
fprintf(f, " ");
}
- fprintf(f, "];\n");
+ fprintf(f, "]");
+}
+
+static void write_propval(FILE *f, struct property *prop)
+{
+ int len = prop->val.len;
+ char *p = prop->val.val;
+ int nnotstring = 0, nnul = 0;
+ int i;
+
+ if (len == 0) {
+ fprintf(f, ";\n");
+ return;
+ }
+
+ for (i = 0; i < len; i++) {
+ if (! isstring(p[i]))
+ nnotstring++;
+ if (p[i] == '\0')
+ nnul++;
+ }
+
+ fprintf(f, " = ");
+
+ if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))) {
+ write_propval_string(f, prop->val);
+ } else if (((len % sizeof(cell_t)) == 0)) {
+ write_propval_cells(f, prop->val);
+ } else {
+ write_propval_bytes(f, prop->val);
+ }
+ fprintf(f, ";\n");
}
static void write_tree_source_node(FILE *f, struct node *tree, int level)
@@ -184,31 +183,11 @@
fprintf(f, "/ {\n");
for_each_property(tree, prop) {
- enum proptype type;
-
write_prefix(f, level+1);
if (prop->label)
fprintf(f, "%s: ", prop->label);
fprintf(f, "%s", prop->name);
- type = guess_type(prop);
-
- switch (type) {
- case PROP_EMPTY:
- fprintf(f, ";\n");
- break;
-
- case PROP_STRING:
- write_propval_string(f, prop->val);
- break;
-
- case PROP_CELLS:
- write_propval_cells(f, prop->val);
- break;
-
- case PROP_BYTES:
- write_propval_bytes(f, prop->val);
- break;
- }
+ write_propval(f, prop);
}
for_each_child(tree, child) {
fprintf(f, "\n");
--
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
* [2/2] dtc: Make -Idts -Odts preserve property-internal labels
From: David Gibson @ 2007-11-06 23:22 UTC (permalink / raw)
To: Jon Loeliger; +Cc: linuxppc-dev
In-Reply-To: <20071106232120.GH31367@localhost.localdomain>
This patch changes -Odts mode output so that labels within property
values in the input are preserved in the output. Applied on top of
the earlier patch to preserve node and property labels in -Odts mode,
this means that dtc in -Idts -Odts mode will transfer all labels in
the input to the output.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
tests/label01.dts | 7 +++--
treesource.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 65 insertions(+), 8 deletions(-)
Index: dtc/treesource.c
===================================================================
--- dtc.orig/treesource.c 2007-11-07 10:19:13.000000000 +1100
+++ dtc/treesource.c 2007-11-07 10:19:42.000000000 +1100
@@ -60,13 +60,24 @@
{
char *str = val.val;
int i;
+ int newchunk = 1;
+ struct fixup *l = val.labels;
assert(str[val.len-1] == '\0');
- fprintf(f, "\"");
for (i = 0; i < (val.len-1); i++) {
char c = str[i];
+ if (newchunk) {
+ while (l && (l->offset <= i)) {
+ assert(l->offset == i);
+ fprintf(f, "%s: ", l->ref);
+ l = l->next;
+ }
+ fprintf(f, "\"");
+ newchunk = 0;
+ }
+
switch (c) {
case '\a':
fprintf(f, "\\a");
@@ -96,7 +107,8 @@
fprintf(f, "\\\"");
break;
case '\0':
- fprintf(f, "\", \"");
+ fprintf(f, "\", ");
+ newchunk = 1;
break;
default:
if (isprint(c))
@@ -106,20 +118,41 @@
}
}
fprintf(f, "\"");
+
+ /* Wrap up any labels at the end of the value */
+ while (l) {
+ assert (l->offset == val.len);
+ fprintf(f, " %s:", l->ref);
+ l = l->next;
+ }
}
static void write_propval_cells(FILE *f, struct data val)
{
void *propend = val.val + val.len;
cell_t *cp = (cell_t *)val.val;
+ struct fixup *l = val.labels;
fprintf(f, "<");
for (;;) {
+ while (l && (l->offset <= ((char *)cp - val.val))) {
+ assert(l->offset == ((char *)cp - val.val));
+ fprintf(f, "%s: ", l->ref);
+ l = l->next;
+ }
+
fprintf(f, "%x", be32_to_cpu(*cp++));
if ((void *)cp >= propend)
break;
fprintf(f, " ");
}
+
+ /* Wrap up any labels at the end of the value */
+ while (l) {
+ assert (l->offset == val.len);
+ fprintf(f, " %s:", l->ref);
+ l = l->next;
+ }
fprintf(f, ">");
}
@@ -127,14 +160,27 @@
{
void *propend = val.val + val.len;
char *bp = val.val;
+ struct fixup *l = val.labels;
fprintf(f, "[");
for (;;) {
+ while (l && (l->offset == (bp-val.val))) {
+ fprintf(f, "%s: ", l->ref);
+ l = l->next;
+ }
+
fprintf(f, "%02hhx", *bp++);
if ((void *)bp >= propend)
break;
fprintf(f, " ");
}
+
+ /* Wrap up any labels at the end of the value */
+ while (l) {
+ assert (l->offset == val.len);
+ fprintf(f, " %s:", l->ref);
+ l = l->next;
+ }
fprintf(f, "]");
}
@@ -142,7 +188,9 @@
{
int len = prop->val.len;
char *p = prop->val.val;
+ struct fixup *l;
int nnotstring = 0, nnul = 0;
+ int nnotstringlbl = 0, nnotcelllbl = 0;
int i;
if (len == 0) {
@@ -157,15 +205,23 @@
nnul++;
}
- fprintf(f, " = ");
+ for (l = prop->val.labels; l; l = l->next) {
+ if ((l->offset > 0) && (prop->val.val[l->offset - 1] != '\0'))
+ nnotstringlbl++;
+ if ((l->offset % sizeof(cell_t)) != 0)
+ nnotcelllbl++;
+ }
- if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))) {
+ fprintf(f, " = ");
+ if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))
+ && (nnotstringlbl == 0)) {
write_propval_string(f, prop->val);
- } else if (((len % sizeof(cell_t)) == 0)) {
+ } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
write_propval_cells(f, prop->val);
} else {
write_propval_bytes(f, prop->val);
}
+
fprintf(f, ";\n");
}
Index: dtc/tests/label01.dts
===================================================================
--- dtc.orig/tests/label01.dts 2007-11-07 09:55:03.000000000 +1100
+++ dtc/tests/label01.dts 2007-11-07 10:19:42.000000000 +1100
@@ -36,10 +36,11 @@
};
node: randomnode {
- prop: string = data: "\xff\0stuffstuff\t\t\t\n\n\n" data_end: ;
- blob = [byte: 0a 0b 0c 0d de ea ad be ef byte_end: ];
- ref = < cell: &/memory@0 cell_end: >;
+ prop: string = str: "foo", str_mid: "stuffstuff\t\t\t\n\n\n" str_end: ;
+ blob = [byte: 0a 0b 0c 0d byte_mid: de ea ad be ef byte_end: ];
+ ref = < cell: &/memory@0 0 cell_mid: ffffffff cell_end: >;
mixed = "abc", pre: [1234] post: , gap: < aligned: a b c>;
+ tricky1 = [61 lt1: 62 63 00];
subnode: child {
};
/* subnode_end: is auto-generated by node emit */
--
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: [PATCH v3 04/13] [POWERPC] Add generic support for simple MPC5200 based boards
From: Grant Likely @ 2007-11-06 23:25 UTC (permalink / raw)
To: Wolfgang Denk; +Cc: linuxppc-dev, Marian Balakowicz
In-Reply-To: <20071106222224.D67BA2479C@gemini.denx.de>
On 11/6/07, Wolfgang Denk <wd@denx.de> wrote:
> Dear Grant,
>
> in message <fa686aa40711061304k4779d01cu7fd1b17d1d34e5a2@mail.gmail.com> you wrote:
> >
> > In other words; make the assumption that it is easier to change the
> > kernel than it is to change the device tree.
>
> Are you serious about this?
>
> Reading this from someone with your experience with device trees if
> feeding my worst fears...
I think I better clarify.
Once a device tree is written and shipped on a deployed board, it may
never change again. Or, the kernel version may be updated more
frequently than the device tree.
Say, for example, that in kernel 2.6.25 tqm5200 and cm5200 are both
handled by the same platform code. And lets say that in 2.6.26 we
decide that they really need to have separate platform code (perhaps
due to a firmware bug that needs to be worked around on one board).
In this case, "mpc5200-simple-platform" has suddenly become useless.
Or, does mpc5200-simple-platform now describe the cm5200 or the
tqm5200? (an assumption which cannot be made due to deployed boards
of both types claiming "mpc5200-simple-platform").
Trying to claim "compatible" at the board level is far more difficult
than claiming it at the device level.
Segher suggested on IRC: "for boards it is pretty much useless most of
the time, i think -- use "model" instead"
Cheers,
g.
>
> Best regards,
>
> Wolfgang Denk
>
> --
> DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
> "Text processing has made it possible to right-justify any idea, even
> one which cannot be justified on any other grounds."
> -- J. Finnegan, USC.
>
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195
^ permalink raw reply
* Re: mmap question on ppc440
From: Benjamin Herrenschmidt @ 2007-11-06 23:31 UTC (permalink / raw)
To: Josh Boyer; +Cc: linuxppc-dev, Stefan Roese
In-Reply-To: <20071106165909.0e80fb4e@zod.rchland.ibm.com>
> > The solution is libpciaccess and the new pci-rework branch of X which
> > uses it, but I haven't had a chance to test that properly yet on 4xx.
>
> Um... because arch/powerpc 4xx doesn't have PCI support? :) You and
> Valentine and Vitaly keep trading emails about it though, which is a
> good sign.
Yeah :-) It shouldn't be hard in fact.
Ben.
^ permalink raw reply
* dtc: Add testcases exercising -Odts mode
From: David Gibson @ 2007-11-06 23:34 UTC (permalink / raw)
To: Jon Loeliger; +Cc: linuxppc-dev
This patch adds a batch of testcases exercising dtc's -Odts mode.
Specifically it checks that using dtc to convert dtb->dts->dtb
preserves the original dtb for a number of example dtb files.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Index: dtc/tests/run_tests.sh
===================================================================
--- dtc.orig/tests/run_tests.sh 2007-11-07 10:23:04.000000000 +1100
+++ dtc/tests/run_tests.sh 2007-11-07 10:27:30.000000000 +1100
@@ -83,7 +83,7 @@
done
# v16 and alternate layout tests
- for tree in test_tree1.dtb; do
+ for tree in test_tree1.dtb sw_tree1.test.dtb; do
for version in 17 16; do
for layout in $ALL_LAYOUTS; do
run_test mangle-layout $tree $version $layout
@@ -94,7 +94,7 @@
done
# Read-write tests
- for basetree in test_tree1.dtb; do
+ for basetree in test_tree1.dtb sw_tree1.test.dtb; do
for version in 17 16; do
for layout in $ALL_LAYOUTS; do
tree=v$version.$layout.$basetree
@@ -126,6 +126,13 @@
run_test dtc.sh -I dts -O dtb -o dtc_escapes.test.dtb escapes.dts
run_test string_escapes dtc_escapes.test.dtb
+
+ # Check -Odts mode preserve all dtb information
+ for tree in test_tree1.dtb dtc_tree1.test.dtb dtc_escapes.test.dtb ; do
+ run_test dtc.sh -I dtb -O dts -o odts_$tree.test.dts $tree
+ run_test dtc.sh -I dts -O dtb -o odts_$tree.test.dtb odts_$tree.test.dts
+ run_test dtbs_equal_ordered $tree odts_$tree.test.dtb
+ done
}
while getopts "vdt:" ARG ; do
@@ -144,7 +151,7 @@
fi
# Make sure we don't have stale blobs lying around
-rm -f *.test.dtb
+rm -f *.test.dtb *.test.dts
for set in $TESTSETS; do
case $set in
Index: dtc/tests/Makefile.tests
===================================================================
--- dtc.orig/tests/Makefile.tests 2007-11-07 10:24:34.000000000 +1100
+++ dtc/tests/Makefile.tests 2007-11-07 10:24:38.000000000 +1100
@@ -23,7 +23,7 @@
TESTS_DEPFILES = $(TESTS:%=%.d) $(TESTS_PREFIX)testutils.d
-TESTS_CLEANFILES_L = *.output vgcore.* *.dtb
+TESTS_CLEANFILES_L = *.output vgcore.* *.dtb *.test.dts
TESTS_CLEANFILES = $(TESTS_CLEANFILES_L:%=$(TESTS_PREFIX)%)
BIN += $(TESTS) $(TESTS_PREFIX)dumptrees
--
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
* dtc: Better exercise dtc base and bytestring features
From: David Gibson @ 2007-11-06 23:58 UTC (permalink / raw)
To: Jon Loeliger; +Cc: linuxppc-dev
This patch alters the main testcase, and the dts file corresponding to
it so that we at least trivially exercise dtc's bytestring and base
conversion features.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Index: dtc/tests/test_tree1.dts
===================================================================
--- dtc.orig/tests/test_tree1.dts 2007-11-07 10:37:38.000000000 +1100
+++ dtc/tests/test_tree1.dts 2007-11-07 10:39:32.000000000 +1100
@@ -1,5 +1,5 @@
/memreserve/ deadbeef00000000-deadbeef000fffff;
-/memreserve/ abcd1234 00001234;
+/memreserve/ 75bcd15 1000;
/ {
compatible = "test_tree1";
@@ -8,20 +8,20 @@
subnode@1 {
compatible = "subnode1";
- prop-int = <deadbeef>;
+ prop-int = [deadbeef];
subsubnode {
compatible = "subsubnode1", "subsubnode";
- prop-int = <deadbeef>;
+ prop-int = <h# deadbeef>;
};
};
subnode@2 {
- prop-int = <abcd1234>;
+ prop-int = <d# 123456789>;
subsubnode@0 {
compatible = "subsubnode2", "subsubnode";
- prop-int = <abcd1234>;
+ prop-int = <o# 0726746425>;
};
};
};
Index: dtc/tests/testdata.h
===================================================================
--- dtc.orig/tests/testdata.h 2007-11-07 10:36:40.000000000 +1100
+++ dtc/tests/testdata.h 2007-11-07 10:37:01.000000000 +1100
@@ -17,11 +17,11 @@
#define TEST_ADDR_1 ASM_CONST_LL(0xdeadbeef00000000)
#define TEST_SIZE_1 ASM_CONST_LL(0x100000)
-#define TEST_ADDR_2 ASM_CONST_LL(0xabcd1234)
-#define TEST_SIZE_2 ASM_CONST_LL(0x1234)
+#define TEST_ADDR_2 ASM_CONST_LL(123456789)
+#define TEST_SIZE_2 ASM_CONST_LL(010000)
#define TEST_VALUE_1 cell_to_fdt(0xdeadbeef)
-#define TEST_VALUE_2 cell_to_fdt(0xabcd1234)
+#define TEST_VALUE_2 cell_to_fdt(123456789)
#define TEST_STRING_1 "hello world"
#define TEST_STRING_2 "nastystring: \a\b\t\n\v\f\r\\\""
--
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: [RFC/PATCH] reduce load time for modules with lots of relocs
From: Medve Emilian @ 2007-11-06 23:58 UTC (permalink / raw)
To: Nathan Lynch; +Cc: linuxppc-dev
In-Reply-To: <20071106023355.GJ9695@localdomain>
Hello Nathan,
Would it be possible to do the sort "in place" (without the extra
buffer)? I mean would that upset any other part of the kernel?
Thanks,
Emil.
> -----Original Message-----
> From: Nathan Lynch [mailto:ntl@pobox.com]=20
> Sent: Monday, November 05, 2007 8:34 PM
> To: Medve Emilian
> Cc: linuxppc-dev@ozlabs.org
> Subject: [RFC/PATCH] reduce load time for modules with lots of relocs
>=20
> Nathan Lynch wrote:
> > Medve Emilian-EMMEDVE1 wrote:
> > >=20
> > > I have module with 36K relocation entries (I know, I=20
> know, how could
> > > that be...) and the count_relocs() function takes ~17=20
> seconds to crunch
> > > through the relocation table from the .rela.text section.=20
> I don't think
> > > I can reduce the number of entries in the relocation=20
> table (can I?) so
> > > I'm thinking at improving the performance of=20
> count_relocs() (currently
> > > O(n^2)). Does anybody have a simpler idea? Does anyone have any
> > > constructive suggestion on how to improve the situation?
> >=20
> > This seems to come up every few months. There was a patch submitted
> > here:
> >=20
> > http://ozlabs.org/pipermail/linuxppc-dev/2007-June/037641.html
>=20
> I think this comes up often enough for us to fix it (IIRC unionfs
> people complained about it long ago too), and it's kind of lame to
> spend 17 seconds in the kernel without scheduling. So I dug up some
> old patches that should reduce the complexity to O(n logn), using the
> sort() function, which IMO is preferable to doing our own hash thing
> as that patch from June does. Only the 64-bit code is tested. Does
> this help your situation?
>=20
> arch/powerpc/kernel/module_32.c | 85=20
> +++++++++++++++++++++++++++++++---------
> arch/powerpc/kernel/module_64.c | 80=20
> ++++++++++++++++++++++++++++++-------
> 2 files changed, 132 insertions(+), 33 deletions(-)
>=20
>=20
> diff --git a/arch/powerpc/kernel/module_32.c=20
> b/arch/powerpc/kernel/module_32.c
> index 07a89a3..001b941 100644
> --- a/arch/powerpc/kernel/module_32.c
> +++ b/arch/powerpc/kernel/module_32.c
> @@ -24,6 +24,7 @@
> #include <linux/kernel.h>
> #include <linux/cache.h>
> #include <linux/bug.h>
> +#include <linux/sort.h>
> =20
> #include "setup.h"
> =20
> @@ -50,26 +51,64 @@ void module_free(struct module *mod, void=20
> *module_region)
> table entries. */
> }
> =20
> +static int reloc_cmp(const void *_a, const void *_b)
> +{
> + const Elf32_Rela *a =3D *(Elf32_Rela **)_a, *b =3D=20
> *(Elf32_Rela **)_b;
> +
> + if (a->r_info < b->r_info)
> + return -1;
> + else if (a->r_info > b->r_info)
> + return 1;
> + else if (a->r_addend < b->r_addend)
> + return -1;
> + else if (a->r_addend > b->r_addend)
> + return 1;
> +
> + return 0;
> +}
> +
> +
> /* Count how many different relocations (different symbol, different
> addend) */
> static unsigned int count_relocs(const Elf32_Rela *rela,=20
> unsigned int num)
> {
> - unsigned int i, j, ret =3D 0;
> + unsigned int i, sorted_count =3D 0;
> + Elf32_Word last_info;
> + Elf32_Sword last_addend;
> + Elf32_Rela **sortbuf =3D NULL;
> +
> + if (num =3D=3D 0)
> + return 0;
> +
> + sortbuf =3D vmalloc(num * sizeof(*sortbuf));
> +
> + if (!sortbuf)
> + return -ENOMEM;
> +
> + for (i =3D 0; i < num; i++)
> + sortbuf[i] =3D (Elf32_Rela *)&rela[i];
> +
> + sort(sortbuf, i, sizeof(sortbuf[0]), reloc_cmp, NULL);
> +
> + last_info =3D sortbuf[0]->r_info;
> + last_addend =3D sortbuf[0]->r_addend;
> + sorted_count =3D 1;
> =20
> - /* Sure, this is order(n^2), but it's usually short, and not
> - time critical */
> for (i =3D 0; i < num; i++) {
> - for (j =3D 0; j < i; j++) {
> - /* If this addend appeared before, it's
> - already been counted */
> - if (ELF32_R_SYM(rela[i].r_info)
> - =3D=3D ELF32_R_SYM(rela[j].r_info)
> - && rela[i].r_addend =3D=3D rela[j].r_addend)
> - break;
> - }
> - if (j =3D=3D i) ret++;
> + /* If this r_info,r_addend tuple matches the previous
> + * entry, don't count it again
> + */
> + if (sortbuf[i]->r_info =3D=3D last_info &&
> + sortbuf[i]->r_addend =3D=3D last_addend)
> + continue;
> +
> + last_info =3D sortbuf[i]->r_info;
> + last_addend =3D sortbuf[i]->r_addend;
> + sorted_count++;
> }
> - return ret;
> +
> + vfree(sortbuf);
> + return sorted_count;
> }
> =20
> /* Get the potential trampolines size required of the init and
> @@ -96,15 +135,19 @@ static unsigned long get_plt_size(const=20
> Elf32_Ehdr *hdr,
> continue;
> =20
> if (sechdrs[i].sh_type =3D=3D SHT_RELA) {
> + int count;
> DEBUGP("Found relocations in section %u\n", i);
> DEBUGP("Ptr: %p. Number: %u\n",
> (void *)hdr + sechdrs[i].sh_offset,
> sechdrs[i].sh_size / sizeof(Elf32_Rela));
> - ret +=3D count_relocs((void *)hdr
> + count =3D count_relocs((void *)hdr
> + sechdrs[i].sh_offset,
> sechdrs[i].sh_size
> / sizeof(Elf32_Rela))
> * sizeof(struct ppc_plt_entry);
> + if (count < 0)
> + return count;
> + ret +=3D count;
> }
> }
> =20
> @@ -117,6 +160,7 @@ int module_frob_arch_sections(Elf32_Ehdr *hdr,
> struct module *me)
> {
> unsigned int i;
> + int ret;
> =20
> /* Find .plt and .init.plt sections */
> for (i =3D 0; i < hdr->e_shnum; i++) {
> @@ -131,10 +175,15 @@ int module_frob_arch_sections(Elf32_Ehdr *hdr,
> }
> =20
> /* Override their sizes */
> - sechdrs[me->arch.core_plt_section].sh_size
> - =3D get_plt_size(hdr, sechdrs, secstrings, 0);
> - sechdrs[me->arch.init_plt_section].sh_size
> - =3D get_plt_size(hdr, sechdrs, secstrings, 1);
> + ret =3D get_plt_size(hdr, sechdrs, secstrings, 0);
> + if (ret < 0)
> + return ret;
> + sechdrs[me->arch.core_plt_section].sh_size =3D ret;
> +
> + ret =3D get_plt_size(hdr, sechdrs, secstrings, 1);
> + if (ret < 0)
> + return ret;
> + sechdrs[me->arch.init_plt_section].sh_size =3D ret;
> return 0;
> }
> =20
> diff --git a/arch/powerpc/kernel/module_64.c=20
> b/arch/powerpc/kernel/module_64.c
> index 75c7c4f..bfc5b98 100644
> --- a/arch/powerpc/kernel/module_64.c
> +++ b/arch/powerpc/kernel/module_64.c
> @@ -21,6 +21,7 @@
> #include <linux/err.h>
> #include <linux/vmalloc.h>
> #include <linux/bug.h>
> +#include <linux/sort.h>
> #include <asm/module.h>
> #include <asm/uaccess.h>
> #include <asm/firmware.h>
> @@ -77,28 +78,68 @@ static struct ppc64_stub_entry ppc64_stub =3D
> 0x4e, 0x80, 0x04, 0x20 /* bctr */
> } };
> =20
> +static int reloc_cmp(const void *_a, const void *_b)
> +{
> + const Elf64_Rela *a =3D *(Elf64_Rela **)_a, *b =3D=20
> *(Elf64_Rela **)_b;
> +
> + if (a->r_info < b->r_info)
> + return -1;
> + else if (a->r_info > b->r_info)
> + return 1;
> + else if (a->r_addend < b->r_addend)
> + return -1;
> + else if (a->r_addend > b->r_addend)
> + return 1;
> +
> + return 0;
> +}
> +
> /* Count how many different 24-bit relocations (different symbol,
> different addend) */
> -static unsigned int count_relocs(const Elf64_Rela *rela,=20
> unsigned int num)
> +static int count_relocs(const Elf64_Rela *rela, unsigned int num)
> {
> unsigned int i, j, ret =3D 0;
> + Elf64_Xword last_info;
> + Elf64_Sxword last_addend;
> + Elf64_Rela **sortbuf =3D NULL;
> +
> + if (num =3D=3D 0)
> + return 0;
> +
> + sortbuf =3D vmalloc(num * sizeof(*sortbuf));
> =20
> - /* FIXME: Only count external ones --RR */
> - /* Sure, this is order(n^2), but it's usually short, and not
> - time critical */
> - for (i =3D 0; i < num; i++) {
> + if (!sortbuf)
> + return -ENOMEM;
> +
> + for (j =3D 0, i =3D 0; i < num; i++) {
> /* Only count 24-bit relocs, others don't need stubs */
> if (ELF64_R_TYPE(rela[i].r_info) !=3D R_PPC_REL24)
> continue;
> - for (j =3D 0; j < i; j++) {
> - /* If this addend appeared before, it's
> - already been counted */
> - if (rela[i].r_info =3D=3D rela[j].r_info
> - && rela[i].r_addend =3D=3D rela[j].r_addend)
> - break;
> - }
> - if (j =3D=3D i) ret++;
> + sortbuf[j++] =3D (Elf64_Rela *)&rela[i];
> }
> +
> + if (j =3D=3D 0)
> + goto out;
> +
> + sort(sortbuf, j, sizeof(sortbuf[0]), reloc_cmp, NULL);
> +
> + last_info =3D sortbuf[0]->r_info;
> + last_addend =3D sortbuf[0]->r_addend;
> + ret =3D 1;
> + for (i =3D 0; i < j; i++) {
> + /* If this r_info,r_addend tuple matches the previous
> + * entry, don't count it again
> + */
> + if (sortbuf[i]->r_info =3D=3D last_info &&
> + sortbuf[i]->r_addend =3D=3D last_addend)
> + continue;
> +
> + last_info =3D sortbuf[i]->r_info;
> + last_addend =3D sortbuf[i]->r_addend;
> + ret++;
> + }
> +out:
> + vfree(sortbuf);
> return ret;
> }
> =20
> @@ -129,13 +170,17 @@ static unsigned long=20
> get_stubs_size(const Elf64_Ehdr *hdr,
> /* Every relocated section... */
> for (i =3D 1; i < hdr->e_shnum; i++) {
> if (sechdrs[i].sh_type =3D=3D SHT_RELA) {
> + int count;
> DEBUGP("Found relocations in section %u\n", i);
> DEBUGP("Ptr: %p. Number: %lu\n",
> (void *)sechdrs[i].sh_addr,
> sechdrs[i].sh_size / sizeof(Elf64_Rela));
> - relocs +=3D count_relocs((void=20
> *)sechdrs[i].sh_addr,
> + count =3D count_relocs((void *)sechdrs[i].sh_addr,
> sechdrs[i].sh_size
> / sizeof(Elf64_Rela));
> + if (count < 0)
> + return count;
> + relocs +=3D count;
> }
> }
> =20
> @@ -173,6 +218,7 @@ int module_frob_arch_sections(Elf64_Ehdr *hdr,
> struct module *me)
> {
> unsigned int i;
> + int stubs_size;
> =20
> /* Find .toc and .stubs sections, symtab and strtab */
> for (i =3D 1; i < hdr->e_shnum; i++) {
> @@ -209,7 +255,11 @@ int module_frob_arch_sections(Elf64_Ehdr *hdr,
> me->arch.toc_section =3D me->arch.stubs_section;
> =20
> /* Override the stubs size */
> - sechdrs[me->arch.stubs_section].sh_size =3D=20
> get_stubs_size(hdr, sechdrs);
> + stubs_size =3D get_stubs_size(hdr, sechdrs);
> + if (stubs_size < 0)
> + return stubs_size;
> +
> + sechdrs[me->arch.stubs_section].sh_size =3D stubs_size;
> return 0;
> }
^ permalink raw reply
* [0/3] Transition to C-style literals (cut the next)
From: David Gibson @ 2007-11-07 0:13 UTC (permalink / raw)
To: Jon Loeliger; +Cc: linuxppc-dev
Here's a new version of my patches to switch us over to dts-v1 and
C-style literals. This version addresses some of the problems Jon
pointed out with the last version, and adds some polish in the last
patch which enables dts-v1 output for -Odts mode.
--
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
* [1/3] dtc: Simplify lexing/parsing of literals vs. node/property names
From: David Gibson @ 2007-11-07 0:16 UTC (permalink / raw)
To: Jon Loeliger, linuxppc-dev
In-Reply-To: <20071107001303.GA553@localhost.localdomain>
The current scheme of having CELLDATA and MEMRESERVE states to
recognize hex literals instead of node or property names is
arse-backwards. The patch switches things around so that literals are
lexed in normal states, and property/node names are only recognized in
the special PROPNODENAME state, which is only entered after a { or a
;, and is left as soon as we scan a property/node name or a keyword.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
dtc-lexer.l | 105 +++++++++++---------------------------------------
dtc-parser.y | 123 ++++++++++++++++++++++++++---------------------------------
2 files changed, 80 insertions(+), 148 deletions(-)
Index: dtc/dtc-lexer.l
===================================================================
--- dtc.orig/dtc-lexer.l 2007-11-07 10:02:42.000000000 +1100
+++ dtc/dtc-lexer.l 2007-11-07 11:01:12.000000000 +1100
@@ -21,9 +21,8 @@
%option noyywrap nounput yylineno
%x INCLUDE
-%x CELLDATA
%x BYTESTRING
-%x MEMRESERVE
+%x PROPNODENAME
PROPCHAR [a-zA-Z0-9,._+*#?-]
UNITCHAR [0-9a-f,]
@@ -51,7 +50,7 @@
%%
-"/include/" BEGIN(INCLUDE);
+<*>"/include/" BEGIN(INCLUDE);
<INCLUDE>\"[^"\n]*\" {
yytext[strlen(yytext) - 1] = 0;
@@ -63,13 +62,13 @@
}
-<<EOF>> {
+<*><<EOF>> {
if (!pop_input_file()) {
yyterminate();
}
}
-\"([^\\"]|\\.)*\" {
+<*>\"([^\\"]|\\.)*\" {
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno;
DPRINT("String: %s\n", yytext);
@@ -79,45 +78,24 @@
return DT_STRING;
}
-"/memreserve/" {
+<*>"/memreserve/" {
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno;
DPRINT("Keyword: /memreserve/\n");
- BEGIN(MEMRESERVE);
- return DT_MEMRESERVE;
- }
-
-<MEMRESERVE>[0-9a-fA-F]+ {
- yylloc.filenum = srcpos_filenum;
- yylloc.first_line = yylineno;
- if (yyleng > 2*sizeof(yylval.addr)) {
- fprintf(stderr, "Address value %s too large\n",
- yytext);
- }
- yylval.addr = (u64) strtoull(yytext, NULL, 16);
- DPRINT("Addr: %llx\n",
- (unsigned long long)yylval.addr);
- return DT_ADDR;
- }
-
-<MEMRESERVE>";" {
- yylloc.filenum = srcpos_filenum;
- yylloc.first_line = yylineno;
- DPRINT("/MEMRESERVE\n");
BEGIN(INITIAL);
- return ';';
+ return DT_MEMRESERVE;
}
<*>[a-zA-Z_][a-zA-Z0-9_]*: {
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno;
DPRINT("Label: %s\n", yytext);
- yylval.str = strdup(yytext);
- yylval.str[yyleng-1] = '\0';
+ yylval.labelref = strdup(yytext);
+ yylval.labelref[yyleng-1] = '\0';
return DT_LABEL;
}
-<CELLDATA>[bodh]# {
+[bodh]# {
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno;
if (*yytext == 'b')
@@ -132,27 +110,19 @@
return DT_BASE;
}
-<CELLDATA>[0-9a-fA-F]+ {
- yylloc.filenum = srcpos_filenum;
- yylloc.first_line = yylineno;
- yylval.str = strdup(yytext);
- DPRINT("Cell: '%s'\n", yylval.str);
- return DT_CELL;
- }
-
-<CELLDATA>">" {
+[0-9a-fA-F]+ {
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno;
- DPRINT("/CELLDATA\n");
- BEGIN(INITIAL);
- return '>';
+ yylval.literal = strdup(yytext);
+ DPRINT("Literal: '%s'\n", yylval.literal);
+ return DT_LITERAL;
}
-<CELLDATA>\&{REFCHAR}* {
+\&{REFCHAR}* {
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno;
DPRINT("Ref: %s\n", yytext+1);
- yylval.str = strdup(yytext+1);
+ yylval.labelref = strdup(yytext+1);
return DT_REF;
}
@@ -172,30 +142,13 @@
return ']';
}
-, { /* Technically this is a valid property name,
- but we'd rather use it as punctuation, so detect it
- here in preference */
+<PROPNODENAME>{PROPCHAR}+(@{UNITCHAR}+)? {
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno;
- DPRINT("Char (propname like): %c (\\x%02x)\n", yytext[0],
- (unsigned)yytext[0]);
- return yytext[0];
- }
-
-{PROPCHAR}+ {
- yylloc.filenum = srcpos_filenum;
- yylloc.first_line = yylineno;
- DPRINT("PropName: %s\n", yytext);
- yylval.str = strdup(yytext);
- return DT_PROPNAME;
- }
-
-{PROPCHAR}+(@{UNITCHAR}+)? {
- yylloc.filenum = srcpos_filenum;
- yylloc.first_line = yylineno;
- DPRINT("NodeName: %s\n", yytext);
- yylval.str = strdup(yytext);
- return DT_NODENAME;
+ DPRINT("PropNodeName: %s\n", yytext);
+ yylval.propnodename = strdup(yytext);
+ BEGIN(INITIAL);
+ return DT_PROPNODENAME;
}
@@ -213,21 +166,17 @@
<*>. {
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno;
- switch (yytext[0]) {
- case '<':
- DPRINT("CELLDATA\n");
- BEGIN(CELLDATA);
- break;
- case '[':
- DPRINT("BYTESTRING\n");
- BEGIN(BYTESTRING);
- break;
- default:
-
+ if (yytext[0] == '[') {
+ DPRINT("<BYTESTRING>\n");
+ BEGIN(BYTESTRING);
+ }
+ if ((yytext[0] == '{')
+ || (yytext[0] == ';')) {
+ DPRINT("<PROPNODENAME>\n");
+ BEGIN(PROPNODENAME);
+ }
DPRINT("Char: %c (\\x%02x)\n", yytext[0],
(unsigned)yytext[0]);
- break;
- }
return yytext[0];
}
Index: dtc/dtc-parser.y
===================================================================
--- dtc.orig/dtc-parser.y 2007-11-07 10:02:42.000000000 +1100
+++ dtc/dtc-parser.y 2007-11-07 10:58:51.000000000 +1100
@@ -25,45 +25,46 @@
#include "srcpos.h"
int yylex(void);
-cell_t cell_from_string(char *s, unsigned int base);
+unsigned long long eval_literal(const char *s, int base, int bits);
extern struct boot_info *the_boot_info;
%}
%union {
- cell_t cval;
+ char *propnodename;
+ char *literal;
+ char *labelref;
unsigned int cbase;
u8 byte;
- char *str;
struct data data;
+
+ u64 addr;
+ cell_t cell;
struct property *prop;
struct property *proplist;
struct node *node;
struct node *nodelist;
- int datalen;
- int hexlen;
- u64 addr;
struct reserve_info *re;
}
%token DT_MEMRESERVE
-%token <addr> DT_ADDR
-%token <str> DT_PROPNAME
-%token <str> DT_NODENAME
+%token <propnodename> DT_PROPNODENAME
+%token <literal> DT_LITERAL
%token <cbase> DT_BASE
-%token <str> DT_CELL
%token <byte> DT_BYTE
%token <data> DT_STRING
-%token <str> DT_LABEL
-%token <str> DT_REF
+%token <labelref> DT_LABEL
+%token <labelref> DT_REF
%type <data> propdata
%type <data> propdataprefix
%type <re> memreserve
%type <re> memreserves
-%type <cbase> opt_cell_base
+%type <addr> addr
%type <data> celllist
+%type <cbase> cellbase
+%type <cell> cellval
%type <data> bytestring
%type <prop> propdef
%type <proplist> proplist
@@ -72,8 +73,7 @@
%type <node> nodedef
%type <node> subnode
%type <nodelist> subnodes
-%type <str> label
-%type <str> nodename
+%type <labelref> label
%%
@@ -96,16 +96,23 @@
;
memreserve:
- label DT_MEMRESERVE DT_ADDR DT_ADDR ';'
+ label DT_MEMRESERVE addr addr ';'
{
$$ = build_reserve_entry($3, $4, $1);
}
- | label DT_MEMRESERVE DT_ADDR '-' DT_ADDR ';'
+ | label DT_MEMRESERVE addr '-' addr ';'
{
$$ = build_reserve_entry($3, $5 - $3 + 1, $1);
}
;
+addr:
+ DT_LITERAL
+ {
+ $$ = eval_literal($1, 16, 64);
+ }
+ ;
+
devicetree:
'/' nodedef
{
@@ -132,11 +139,11 @@
;
propdef:
- label DT_PROPNAME '=' propdata ';'
+ label DT_PROPNODENAME '=' propdata ';'
{
$$ = build_property($2, $4, $1);
}
- | label DT_PROPNAME ';'
+ | label DT_PROPNODENAME ';'
{
$$ = build_property($2, empty_data, $1);
}
@@ -176,23 +183,14 @@
}
;
-opt_cell_base:
- /* empty */
- {
- $$ = 16;
- }
- | DT_BASE
- ;
-
celllist:
/* empty */
{
$$ = empty_data;
}
- | celllist opt_cell_base DT_CELL
+ | celllist cellval
{
- $$ = data_append_cell($1,
- cell_from_string($3, $2));
+ $$ = data_append_cell($1, $2);
}
| celllist DT_REF
{
@@ -204,6 +202,21 @@
}
;
+cellbase:
+ /* empty */
+ {
+ $$ = 16;
+ }
+ | DT_BASE
+ ;
+
+cellval:
+ cellbase DT_LITERAL
+ {
+ $$ = eval_literal($2, $1, 32);
+ }
+ ;
+
bytestring:
/* empty */
{
@@ -231,23 +244,12 @@
;
subnode:
- label nodename nodedef
+ label DT_PROPNODENAME nodedef
{
$$ = name_node($3, $2, $1);
}
;
-nodename:
- DT_NODENAME
- {
- $$ = $1;
- }
- | DT_PROPNAME
- {
- $$ = $1;
- }
- ;
-
label:
/* empty */
{
@@ -272,33 +274,18 @@
fname, yylloc.first_line, s);
}
-
-/*
- * Convert a string representation of a numeric cell
- * in the given base into a cell.
- *
- * FIXME: should these specification errors be fatal instead?
- */
-
-cell_t cell_from_string(char *s, unsigned int base)
+unsigned long long eval_literal(const char *s, int base, int bits)
{
- cell_t c;
+ unsigned long long val;
char *e;
- c = strtoul(s, &e, base);
- if (*e) {
- fprintf(stderr,
- "Line %d: Invalid cell value '%s' : "
- "%c is not a base %d digit; %d assumed\n",
- yylloc.first_line, s, *e, base, c);
- }
-
- if (errno == EINVAL || errno == ERANGE) {
- fprintf(stderr,
- "Line %d: Invalid cell value '%s'; %d assumed\n",
- yylloc.first_line, s, c);
- errno = 0;
- }
-
- return c;
+ errno = 0;
+ val = strtoull(s, &e, base);
+ if (*e)
+ yyerror("bad characters in literal");
+ else if ((errno == ERANGE) || (val > ((1ULL << bits)-1)))
+ yyerror("literal out of range");
+ else if (errno != 0)
+ yyerror("bad literal");
+ return val;
}
--
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
* [2/3] dtc: Switch dtc to C-style literals
From: David Gibson @ 2007-11-07 0:17 UTC (permalink / raw)
To: Jon Loeliger, linuxppc-dev
In-Reply-To: <20071107001303.GA553@localhost.localdomain>
dtc: Switch dtc to C-style literals
This patch introduces a new version of dts file, distinguished from
older files by starting with the special token /dts-v1/. dts files in
the new version take C-style literals instead of the old bare hex or
OF-style base notation. In addition, the "range" for of memreserve entries
(/memreserve/ f0000-fffff) is no longer recognized in the new format.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
dtc-lexer.l | 40 ++++++++++++++++++++++++++++++++--------
dtc-parser.y | 38 ++++++++++++++++++++++++++++++++++++--
tests/run_tests.sh | 4 ++++
tests/test_tree1.dts | 14 ++++++++------
tests/test_tree1_dts0.dts | 27 +++++++++++++++++++++++++++
5 files changed, 107 insertions(+), 16 deletions(-)
Index: dtc/dtc-lexer.l
===================================================================
--- dtc.orig/dtc-lexer.l 2007-11-07 11:16:47.000000000 +1100
+++ dtc/dtc-lexer.l 2007-11-07 11:16:51.000000000 +1100
@@ -23,6 +23,7 @@
%x INCLUDE
%x BYTESTRING
%x PROPNODENAME
+%s V1
PROPCHAR [a-zA-Z0-9,._+*#?-]
UNITCHAR [0-9a-f,]
@@ -44,12 +45,18 @@
#define DPRINT(fmt, ...) do { } while (0)
#endif
+static int dts_version; /* = 0 */
-
+#define BEGIN_DEFAULT() if (dts_version == 0) { \
+ DPRINT("<INITIAL>\n"); \
+ BEGIN(INITIAL); \
+ } else { \
+ DPRINT("<V1>\n"); \
+ BEGIN(V1); \
+ }
%}
%%
-
<*>"/include/" BEGIN(INCLUDE);
<INCLUDE>\"[^"\n]*\" {
@@ -58,7 +65,7 @@
/* Some unrecoverable error.*/
exit(1);
}
- BEGIN(INITIAL);
+ BEGIN_DEFAULT();
}
@@ -78,11 +85,20 @@
return DT_STRING;
}
+<*>"/dts-v1/" {
+ yylloc.filenum = srcpos_filenum;
+ yylloc.first_line = yylineno;
+ DPRINT("Keyword: /dts-v1/\n");
+ dts_version = 1;
+ BEGIN_DEFAULT();
+ return DT_V1;
+ }
+
<*>"/memreserve/" {
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno;
DPRINT("Keyword: /memreserve/\n");
- BEGIN(INITIAL);
+ BEGIN_DEFAULT();
return DT_MEMRESERVE;
}
@@ -95,7 +111,7 @@
return DT_LABEL;
}
-[bodh]# {
+<INITIAL>[bodh]# {
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno;
if (*yytext == 'b')
@@ -110,7 +126,15 @@
return DT_BASE;
}
-[0-9a-fA-F]+ {
+<INITIAL>[0-9a-fA-F]+ {
+ yylloc.filenum = srcpos_filenum;
+ yylloc.first_line = yylineno;
+ yylval.literal = strdup(yytext);
+ DPRINT("Literal: '%s'\n", yylval.literal);
+ return DT_LEGACYLITERAL;
+ }
+
+<V1>[0-9]+|0[xX][0-9a-fA-F]+ {
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno;
yylval.literal = strdup(yytext);
@@ -138,7 +162,7 @@
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno;
DPRINT("/BYTESTRING\n");
- BEGIN(INITIAL);
+ BEGIN_DEFAULT();
return ']';
}
@@ -147,7 +171,7 @@
yylloc.first_line = yylineno;
DPRINT("PropNodeName: %s\n", yytext);
yylval.propnodename = strdup(yytext);
- BEGIN(INITIAL);
+ BEGIN_DEFAULT();
return DT_PROPNODENAME;
}
Index: dtc/dtc-parser.y
===================================================================
--- dtc.orig/dtc-parser.y 2007-11-07 11:16:47.000000000 +1100
+++ dtc/dtc-parser.y 2007-11-07 11:16:51.000000000 +1100
@@ -48,9 +48,11 @@
struct reserve_info *re;
}
+%token DT_V1
%token DT_MEMRESERVE
%token <propnodename> DT_PROPNODENAME
%token <literal> DT_LITERAL
+%token <literal> DT_LEGACYLITERAL
%token <cbase> DT_BASE
%token <byte> DT_BYTE
%token <data> DT_STRING
@@ -61,6 +63,8 @@
%type <data> propdataprefix
%type <re> memreserve
%type <re> memreserves
+%type <re> v0_memreserve
+%type <re> v0_memreserves
%type <addr> addr
%type <data> celllist
%type <cbase> cellbase
@@ -78,7 +82,11 @@
%%
sourcefile:
- memreserves devicetree
+ DT_V1 ';' memreserves devicetree
+ {
+ the_boot_info = build_boot_info($3, $4);
+ }
+ | v0_memreserves devicetree
{
the_boot_info = build_boot_info($1, $2);
}
@@ -100,6 +108,24 @@
{
$$ = build_reserve_entry($3, $4, $1);
}
+ ;
+
+v0_memreserves:
+ /* empty */
+ {
+ $$ = NULL;
+ }
+ | v0_memreserve v0_memreserves
+ {
+ $$ = chain_reserve_entry($1, $2);
+ };
+ ;
+
+v0_memreserve:
+ memreserve
+ {
+ $$ = $1;
+ }
| label DT_MEMRESERVE addr '-' addr ';'
{
$$ = build_reserve_entry($3, $5 - $3 + 1, $1);
@@ -108,6 +134,10 @@
addr:
DT_LITERAL
+ {
+ $$ = eval_literal($1, 0, 64);
+ }
+ | DT_LEGACYLITERAL
{
$$ = eval_literal($1, 16, 64);
}
@@ -211,7 +241,11 @@
;
cellval:
- cellbase DT_LITERAL
+ DT_LITERAL
+ {
+ $$ = eval_literal($1, 0, 32);
+ }
+ | cellbase DT_LEGACYLITERAL
{
$$ = eval_literal($2, $1, 32);
}
Index: dtc/tests/run_tests.sh
===================================================================
--- dtc.orig/tests/run_tests.sh 2007-11-07 11:16:47.000000000 +1100
+++ dtc/tests/run_tests.sh 2007-11-07 11:16:51.000000000 +1100
@@ -124,6 +124,10 @@
tree1_tests_rw dtc_tree1.test.dtb
run_test dtbs_equal_ordered dtc_tree1.test.dtb test_tree1.dtb
+ run_test dtc.sh -I dts -O dtb -o dtc_tree1_dts0.test.dtb test_tree1_dts0.dts
+ tree1_tests dtc_tree1_dts0.test.dtb
+ tree1_tests_rw dtc_tree1_dts0.test.dtb
+
run_test dtc.sh -I dts -O dtb -o dtc_escapes.test.dtb escapes.dts
run_test string_escapes dtc_escapes.test.dtb
Index: dtc/tests/test_tree1.dts
===================================================================
--- dtc.orig/tests/test_tree1.dts 2007-11-07 11:16:47.000000000 +1100
+++ dtc/tests/test_tree1.dts 2007-11-07 11:16:51.000000000 +1100
@@ -1,9 +1,11 @@
-/memreserve/ deadbeef00000000-deadbeef000fffff;
-/memreserve/ 75bcd15 1000;
+/dts-v1/;
+
+/memreserve/ 0xdeadbeef00000000 0x100000;
+/memreserve/ 123456789 010000;
/ {
compatible = "test_tree1";
- prop-int = <deadbeef>;
+ prop-int = <0xdeadbeef>;
prop-str = "hello world";
subnode@1 {
@@ -12,16 +14,16 @@
subsubnode {
compatible = "subsubnode1", "subsubnode";
- prop-int = <h# deadbeef>;
+ prop-int = <0xdeadbeef>;
};
};
subnode@2 {
- prop-int = <d# 123456789>;
+ prop-int = <123456789>;
subsubnode@0 {
compatible = "subsubnode2", "subsubnode";
- prop-int = <o# 0726746425>;
+ prop-int = <0726746425>;
};
};
};
Index: dtc/tests/test_tree1_dts0.dts
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ dtc/tests/test_tree1_dts0.dts 2007-11-07 11:16:51.000000000 +1100
@@ -0,0 +1,27 @@
+/memreserve/ deadbeef00000000-deadbeef000fffff;
+/memreserve/ 75bcd15 1000;
+
+/ {
+ compatible = "test_tree1";
+ prop-int = <deadbeef>;
+ prop-str = "hello world";
+
+ subnode@1 {
+ compatible = "subnode1";
+ prop-int = [deadbeef];
+
+ subsubnode {
+ compatible = "subsubnode1", "subsubnode";
+ prop-int = <h# deadbeef>;
+ };
+ };
+
+ subnode@2 {
+ prop-int = <d# 123456789>;
+
+ subsubnode@0 {
+ compatible = "subsubnode2", "subsubnode";
+ prop-int = <o# 0726746425>;
+ };
+ };
+};
--
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
* [3/3] dtc: -Odts produces v1 output
From: David Gibson @ 2007-11-07 0:17 UTC (permalink / raw)
To: Jon Loeliger, linuxppc-dev
In-Reply-To: <20071107001303.GA553@localhost.localdomain>
This patch alters the -Odts mode output so that it uses dts-v1 format.
This means that dtc -Idts -Odts used on a v0 dts file will convert
that file to v1.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
treesource.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
Index: dtc/treesource.c
===================================================================
--- dtc.orig/treesource.c 2007-11-07 11:16:45.000000000 +1100
+++ dtc/treesource.c 2007-11-07 11:16:55.000000000 +1100
@@ -141,7 +141,7 @@
l = l->next;
}
- fprintf(f, "%x", be32_to_cpu(*cp++));
+ fprintf(f, "0x%x", be32_to_cpu(*cp++));
if ((void *)cp >= propend)
break;
fprintf(f, " ");
@@ -258,12 +258,14 @@
{
struct reserve_info *re;
+ fprintf(f, "/dts-v1/;\n\n");
+
for (re = bi->reservelist; re; re = re->next) {
if (re->label)
fprintf(f, "%s: ", re->label);
- fprintf(f, "/memreserve/\t%016llx-%016llx;\n",
+ fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n",
(unsigned long long)re->re.address,
- (unsigned long long)(re->re.address + re->re.size - 1));
+ (unsigned long long)re->re.size);
}
write_tree_source_node(f, bi->dt, 0);
--
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
* libfdt: Add more documentation (path the fifth)
From: David Gibson @ 2007-11-07 0:54 UTC (permalink / raw)
To: Jon Loeliger; +Cc: linuxppc-dev
This patch documents a few more functions in libfdt.h. All the
read-only functions are now documented.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Index: dtc/libfdt/libfdt.h
===================================================================
--- dtc.orig/libfdt/libfdt.h 2007-11-06 10:37:44.000000000 +1100
+++ dtc/libfdt/libfdt.h 2007-11-07 11:52:27.000000000 +1100
@@ -515,12 +515,107 @@
*/
int fdt_parent_offset(const void *fdt, int nodeoffset);
+/**
+ * fdt_node_offset_by_prop_value - find nodes with a given property value
+ * @fdt: pointer to the device tree blob
+ * @startoffset: only find nodes after this offset
+ * @propname: property name to check
+ * @propval: property value to search for
+ * @proplen: length of the value in propval
+ *
+ * fdt_node_offset_by_prop_value() returns the offset of the first
+ * node after startoffset, which has a property named propname whose
+ * value is of length proplen and has value equal to propval; or if
+ * startoffset is -1, the very first such node in the tree.
+ *
+ * To iterate through all nodes matching the criterion, the following
+ * idiom can be used:
+ * offset = fdt_node_offset_by_prop_value(fdt, -1, propname,
+ * propval, proplen);
+ * while (offset != -FDT_ERR_NOTFOUND) {
+ * // other code here
+ * offset = fdt_node_offset_by_prop_value(fdt, offset, propname,
+ * propval, proplen);
+ * }
+ *
+ * Note the -1 in the first call to the function, if 0 is used here
+ * instead, the function will never locate the root node, even if it
+ * matches the criterion.
+ *
+ * returns:
+ * structure block offset of the located node (>= 0, >startoffset),
+ * on success
+ * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the
+ * tree after startoffset
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE, standard meanings
+ */
int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
const char *propname,
const void *propval, int proplen);
+/**
+ * fdt_node_check_compatible: check a node's compatible property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of a tree node
+ * @compatible: string to match against
+ *
+ *
+ * fdt_node_check_compatible() returns 0 if the given node contains a
+ * 'compatible' property with the given string as one of its elements,
+ * it returns non-zero otherwise, or on error.
+ *
+ * returns:
+ * 0, if the node has a 'compatible' property listing the given string
+ * 1, if the node has a 'compatible' property, but it does not list
+ * the given string
+ * -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property
+ * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE, standard meanings
+ */
int fdt_node_check_compatible(const void *fdt, int nodeoffset,
const char *compatible);
+
+/**
+ * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value
+ * @fdt: pointer to the device tree blob
+ * @startoffset: only find nodes after this offset
+ * @compatible: 'compatible' string to match against
+ *
+ * fdt_node_offset_by_compatible() returns the offset of the first
+ * node after startoffset, which has a 'compatible' property which
+ * lists the given compatible string; or if startoffset is -1, the
+ * very first such node in the tree.
+ *
+ * To iterate through all nodes matching the criterion, the following
+ * idiom can be used:
+ * offset = fdt_node_offset_by_compatible(fdt, -1, compatible);
+ * while (offset != -FDT_ERR_NOTFOUND) {
+ * // other code here
+ * offset = fdt_node_offset_by_compatible(fdt, offset, compatible);
+ * }
+ *
+ * Note the -1 in the first call to the function, if 0 is used here
+ * instead, the function will never locate the root node, even if it
+ * matches the criterion.
+ *
+ * returns:
+ * structure block offset of the located node (>= 0, >startoffset),
+ * on success
+ * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the
+ * tree after startoffset
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE, standard meanings
+ */
int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
const char *compatible);
--
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: [RFC/PATCH] reduce load time for modules with lots of relocs
From: Nathan Lynch @ 2007-11-07 1:19 UTC (permalink / raw)
To: Medve Emilian; +Cc: linuxppc-dev
In-Reply-To: <598D5675D34BE349929AF5EDE9B03E270174D37B@az33exm24.fsl.freescale.net>
Medve Emilian wrote:
> Would it be possible to do the sort "in place" (without the extra
> buffer)? I mean would that upset any other part of the kernel?
I suspect so. Sounds like you've got the good testcase, maybe you
should try it and see. :)
^ permalink raw reply
* Re: [PATCH v3 04/13] [POWERPC] Add generic support for simple MPC5200 based boards
From: Stephen Rothwell @ 2007-11-07 2:34 UTC (permalink / raw)
To: Marian Balakowicz; +Cc: linuxppc-dev
In-Reply-To: <20071106200520.10913.47002.stgit@hekate.izotz.org>
[-- Attachment #1: Type: text/plain, Size: 436 bytes --]
Hi Marian,
On Tue, 06 Nov 2007 21:05:20 +0100 Marian Balakowicz <m8@semihalf.com> wrote:
>
> +++ b/arch/powerpc/platforms/52xx/mpc5200_simple.c
> +
> +#include <linux/pci.h>
> +#include <linux/of.h>
> +#include <asm/time.h>
> +#include <asm/io.h>
Its not clear to me that you need any of the above four includes.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH 1/2] [PPC 4xx] invalidate_l2cache_range() implementation for ppc44x
From: Olof Johansson @ 2007-11-07 4:04 UTC (permalink / raw)
To: Yuri Tikhonov; +Cc: linuxppc-dev, sr, dzu
In-Reply-To: <1078030427.20071107014028@emcraft.com>
Hi,
Some comments below. In general this patch adds #ifdefs in common code,
that's normally frowned upon.
It would maybe be better to add a new call to ppc_machdeps and call it
if set.
-Olof
On Wed, Nov 07, 2007 at 01:40:28AM +0300, Yuri Tikhonov wrote:
> Support for L2-cache coherency synchronization routines in ppc44x
> processors.
>
>
> Signed-off-by: Yuri Tikhonov <yur@emcraft.com>
> Signed-off-by: Pavel Kolesnikov <concord@emcraft.com>
>
> --
> diff --git a/arch/powerpc/lib/dma-noncoherent.c b/arch/powerpc/lib/dma-noncoherent.c
> index 1947380..593a425 100644
> --- a/arch/powerpc/lib/dma-noncoherent.c
> +++ b/arch/powerpc/lib/dma-noncoherent.c
> @@ -351,12 +351,18 @@ void __dma_sync(void *vaddr, size_t size, int direction)
> BUG();
> case DMA_FROM_DEVICE: /* invalidate only */
> invalidate_dcache_range(start, end);
> +#ifdef CONFIG_L2_CACHE
> + invalidate_l2cache_range(__pa(start), __pa(end));
> +#endif
> break;
> case DMA_TO_DEVICE: /* writeback only */
> clean_dcache_range(start, end);
> break;
> case DMA_BIDIRECTIONAL: /* writeback and invalidate */
> flush_dcache_range(start, end);
> +#ifdef CONFIG_L2_CACHE
> + invalidate_l2cache_range(__pa(start), __pa(end));
> +#endif
> break;
> }
> }
> diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
> index 46cf8fa..de62f85 100644
> --- a/arch/ppc/kernel/misc.S
> +++ b/arch/ppc/kernel/misc.S
> @@ -386,6 +386,36 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
> sync /* additional sync needed on g4 */
> isync
> blr
> +
> +#ifdef CONFIG_L2_CACHE
> +/*
> + * Invalidate the Level-2 cache lines corresponded to the address
> + * range.
> + *
> + * invalidate_l2cache_range(unsigned long start, unsigned long stop)
> + */
> +#include <asm/ibm4xx.h>
PLease don't add includes to the middle of a file.
> +_GLOBAL(invalidate_l2cache_range)
> + li r5,L2_CACHE_BYTES-1 /* do l2-cache line alignment */
> + andc r3,r3,r5
> + subf r4,r3,r4
> + add r4,r4,r5
> + srwi. r4,r4,L2_CACHE_SHIFT
> + mtctr r4
> +
> + lis r4, L2C_CMD_INV>>16
> +1: mtdcr DCRN_L2C0_ADDR,r3 /* write address to invalidate */
> + mtdcr DCRN_L2C0_CMD,r4 /* issue the Invalidate cmd */
> +
> +2: mfdcr r5,DCRN_L2C0_SR /* wait for complete */
> + andis. r5,r5,L2C_CMD_CLR>>16
> + beq 2b
> +
> + addi r3,r3,L2_CACHE_BYTES /* next address to invalidate */
> + bdnz 1b
> + blr
> +#endif
The whole function above has bad whitespace (spaces instead of tabs)
> +
> /*
> * Write any modified data cache blocks out to memory.
> * Does not invalidate the corresponding cache lines (especially for
> diff --git a/include/asm-powerpc/cache.h b/include/asm-powerpc/cache.h
> index 5350704..8a2f9e6 100644
> --- a/include/asm-powerpc/cache.h
> +++ b/include/asm-powerpc/cache.h
> @@ -10,12 +10,14 @@
> #define MAX_COPY_PREFETCH 1
> #elif defined(CONFIG_PPC32)
> #define L1_CACHE_SHIFT 5
> +#define L2_CACHE_SHIFT 5
> #define MAX_COPY_PREFETCH 4
> #else /* CONFIG_PPC64 */
> #define L1_CACHE_SHIFT 7
> #endif
>
> #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
> +#define L2_CACHE_BYTES (1 << L2_CACHE_SHIFT)
The above looks highly system dependent to me. Should maybe be a part
of the cache info structures instead, and filled in from the device tree?
>
> #define SMP_CACHE_BYTES L1_CACHE_BYTES
>
> diff --git a/include/asm-powerpc/cacheflush.h b/include/asm-powerpc/cacheflush.h
> index ba667a3..bdebfaa 100644
> --- a/include/asm-powerpc/cacheflush.h
> +++ b/include/asm-powerpc/cacheflush.h
> @@ -49,6 +49,7 @@ extern void flush_dcache_range(unsigned long start, unsigned long stop);
> #ifdef CONFIG_PPC32
> extern void clean_dcache_range(unsigned long start, unsigned long stop);
> extern void invalidate_dcache_range(unsigned long start, unsigned long stop);
> +extern void invalidate_l2cache_range(unsigned long start, unsigned long stop);
> #endif /* CONFIG_PPC32 */
> #ifdef CONFIG_PPC64
> extern void flush_inval_dcache_range(unsigned long start, unsigned long stop);
> diff --git a/include/asm-ppc/ibm44x.h b/include/asm-ppc/ibm44x.h
> index 8078a58..782909a 100644
> --- a/include/asm-ppc/ibm44x.h
> +++ b/include/asm-ppc/ibm44x.h
> @@ -138,7 +138,6 @@
> * The "residual" board information structure the boot loader passes
> * into the kernel.
> */
> -#ifndef __ASSEMBLY__
>
> /*
> * DCRN definitions
> @@ -814,6 +813,5 @@
>
> #include <asm/ibm4xx.h>
>
> -#endif /* __ASSEMBLY__ */
> #endif /* __ASM_IBM44x_H__ */
> #endif /* __KERNEL__ */
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [PATCH 2/2] [PPC 44x] enable L2-cache for ALPR, Katmai, Ocotea, and Taishan
From: Olof Johansson @ 2007-11-07 4:06 UTC (permalink / raw)
To: Yuri Tikhonov; +Cc: linuxppc-dev, sr, dzu
In-Reply-To: <1416528026.20071107014041@emcraft.com>
Hi,
See comments below.
-Olof
On Wed, Nov 07, 2007 at 01:40:41AM +0300, Yuri Tikhonov wrote:
> This patch introduces the L2_CACHE configuration option available
> for the ppc44x-based boards with L2-cache enabled.
>
> Signed-off-by: Yuri Tikhonov <yur@emcraft.com>
> Signed-off-by: Pavel Kolesnikov <concord@emcraft.com>
>
> --
> diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig
> index 1d2ca42..ad6b581 100644
> --- a/arch/ppc/platforms/4xx/Kconfig
> +++ b/arch/ppc/platforms/4xx/Kconfig
> @@ -396,4 +396,12 @@ config SERIAL_SICC_CONSOLE
> bool
> depends on SERIAL_SICC && UART0_TTYS1
> default y
> +
> +config L2_CACHE
> + bool "Enable Level-2 Cache"
> + depends on NOT_COHERENT_CACHE && (KATMAI || TAISHAN || OCOTEA || ALPR)
> + default y
> + help
> + This option enables L2-cache on ppc44x controllers.
> + If unsure, say Y.
That's a very generic config name. Maybe something like PPC_4XX_L2_CACHE?
Is there ever a case where a user would NOT want l2 cache enabled (and
disabled permanently enough to rebuild the kernel instead of giving a
kernel command line option?)
> endmenu
> diff --git a/arch/ppc/platforms/4xx/alpr.c b/arch/ppc/platforms/4xx/alpr.c
> index 3b6519f..0623801 100644
> --- a/arch/ppc/platforms/4xx/alpr.c
> +++ b/arch/ppc/platforms/4xx/alpr.c
> @@ -537,10 +537,12 @@ static void __init alpr_setup_arch(void)
> printk("Prodrive ALPR port (DENX Software Engineering <sr@denx.de>)\n");
> }
>
> +#ifdef CONFIG_L2_CACHE
> static void __init alpr_init(void)
> {
> ibm440gx_l2c_setup(&clocks);
> }
> +#endif
>
> static void alpr_progress(char *buf, unsigned short val)
> {
> @@ -567,7 +569,9 @@ void __init platform_init(unsigned long r3, unsigned long r4,
> #ifdef CONFIG_KGDB
> ppc_md.early_serial_map = alpr_early_serial_map;
> #endif
> +#ifdef CONFIG_L2_CACHE
> ppc_md.init = alpr_init;
> +#endif
Why do you take out the above calls if the new option is selected? Seems
odd to remove something that worked(?) before.
> ppc_md.restart = alpr_restart;
> }
>
> diff --git a/arch/ppc/platforms/4xx/katmai.c b/arch/ppc/platforms/4xx/katmai.c
> index d29ebf6..01f1baf 100644
> --- a/arch/ppc/platforms/4xx/katmai.c
> +++ b/arch/ppc/platforms/4xx/katmai.c
> @@ -219,6 +219,7 @@ katmai_show_cpuinfo(struct seq_file *m)
> {
> seq_printf(m, "vendor\t\t: AMCC\n");
> seq_printf(m, "machine\t\t: PPC440SPe EVB (Katmai)\n");
> + ibm440gx_show_cpuinfo(m);
This seems unrelated to this patch.
> return 0;
> }
> @@ -584,6 +585,13 @@ static void katmai_restart(char *cmd)
> mtspr(SPRN_DBCR0, DBCR0_RST_CHIP);
> }
>
> +#ifdef CONFIG_L2_CACHE
> +static void __init katmai_init(void)
> +{
> + ibm440gx_l2c_setup(&clocks);
> +}
> +#endif
> +
> void __init platform_init(unsigned long r3, unsigned long r4,
> unsigned long r5, unsigned long r6, unsigned long r7)
> {
> @@ -599,4 +607,7 @@ void __init platform_init(unsigned long r3, unsigned long r4,
> ppc_md.early_serial_map = katmai_early_serial_map;
> #endif
> ppc_md.restart = katmai_restart;
> +#ifdef CONFIG_L2_CACHE
> + ppc_md.init = katmai_init;
> +#endif
See comment above. Should the above init be called for all configs, not just
when L2_CACHE is enabled?
Also, it looks like the init function is the same on every board. It would
be better to make a common function instead of duplicating it everywhere.
> }
> diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c
> index a7435aa..8b13811 100644
> --- a/arch/ppc/platforms/4xx/ocotea.c
> +++ b/arch/ppc/platforms/4xx/ocotea.c
> @@ -321,10 +321,12 @@ ocotea_setup_arch(void)
> printk("IBM Ocotea port (MontaVista Software, Inc. <source@mvista.com>)\n");
> }
>
> +#ifdef CONFIG_L2_CACHE
> static void __init ocotea_init(void)
> {
> ibm440gx_l2c_setup(&clocks);
> }
> +#endif
>
> void __init platform_init(unsigned long r3, unsigned long r4,
> unsigned long r5, unsigned long r6, unsigned long r7)
> @@ -345,5 +347,7 @@ void __init platform_init(unsigned long r3, unsigned long r4,
> #ifdef CONFIG_KGDB
> ppc_md.early_serial_map = ocotea_early_serial_map;
> #endif
> +#ifdef CONFIG_L2_CACHE
> ppc_md.init = ocotea_init;
> +#endif
> }
> diff --git a/arch/ppc/platforms/4xx/taishan.c b/arch/ppc/platforms/4xx/taishan.c
> index f4b9435..8bb6f15 100644
> --- a/arch/ppc/platforms/4xx/taishan.c
> +++ b/arch/ppc/platforms/4xx/taishan.c
> @@ -370,10 +370,12 @@ taishan_setup_arch(void)
> printk("AMCC PowerPC 440GX Taishan Platform\n");
> }
>
> +#ifdef CONFIG_L2_CACHE
> static void __init taishan_init(void)
> {
> ibm440gx_l2c_setup(&clocks);
> }
> +#endif
>
> void __init platform_init(unsigned long r3, unsigned long r4,
> unsigned long r5, unsigned long r6, unsigned long r7)
> @@ -389,6 +391,8 @@ void __init platform_init(unsigned long r3, unsigned long r4,
> #ifdef CONFIG_KGDB
> ppc_md.early_serial_map = taishan_early_serial_map;
> #endif
> +#ifdef CONFIG_L2_CACHE
> ppc_md.init = taishan_init;
> +#endif
> }
>
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* [PATCH 0/2] pasemi_mac: two bugfixes for 2.6.24
From: Olof Johansson @ 2007-11-07 4:20 UTC (permalink / raw)
To: jgarzik; +Cc: netdev, linuxppc-dev
Hi Jeff,
Two bugfixes for pasemi_mac for 2.6.24:
[PATCH 1/2] pasemi_mac: Don't set replace-source-address descriptor bits
[PATCH 2/2] pasemi_mac: Fix CRC checks
Thanks,
-Olof
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox