LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] ppc64: re-enable kexec to allow module loads with CONFIG_MODVERSIONS and CONFIG_RELOCATABLE turned on
From: Neil Horman @ 2009-11-24 18:11 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: rusty, paulus
In-Reply-To: <20091119195216.GC11414@hmsreliant.think-freely.org>

Neil Horman writes:

> 	Before anyone flames me for what a oddball solution this is, let me just
> say I'm trying to get the ball rolling here.  I think there may be better
> solutions that can be impemented in reloc_64.S, but I've yet to make any of
the
> ones I've tried work successfully.  I'm open to suggestions, but this solution
> is the only one so far that I've been able to get to work. thanks :)

I had thought that the CRCs would be the only things with reloc
addends less than 4G, but it turns out that the toolchain folds
expressions like __pa(&sym) into just a load from a doubleword (in the
TOC) containing the physical address of sym.  That needs to be
relocated and its reloc addend will be less than 4GB.  Hence the
crashes early in boot that you were seeing with my proposed patch to
reloc_64.S.

Given that, your solution seems as reasonable as any.  Should this go
via the modules maintainer, Rusty Russell, perhaps?

In any case,

Acked-by: Paul Mackerras <paulus at samba.org>


I'm not 100% sure, it does kind of split the middle in regards to what tree is
should come through.

Rusy, given the previous entries in this thread, do you have any thoughts on the
patch, or which tree it should go through?  I kind of think that the ppc tree is
just fine here since its currently the only user of this code, but I'll defer to
other opinions on the subject.

Thanks & Regards
Neil

^ permalink raw reply

* Re: [RFC PATCH 09/19] powerpc: gamecube/wii: udbg support for usbgecko
From: Albert Herranz @ 2009-11-24 18:08 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: linuxppc-dev
In-Reply-To: <E6251558-8B55-4A7C-952C-4989D876C69A@kernel.crashing.org>

Segher Boessenkool wrote:
>> +      If you say yes to this option, support will be included for the
>> +      USB Gecko adapter as an udbg console.
>> +      The USB Gecko is a EXI to USB Serial converter that can be plugged
>> +      into a memcard slot in the Nintendo GameCube/Wii.
> 
> Not "a" memcard slot, only the first one, you have it hardcoded.
> 

No. It's not hardcoded in the code. It's specified in the device tree source.
The hardcoded one is just the early udbg, not the "normal" udbg.

>> +#if 0
>> +/*
>> + * Trasmits a null terminated character string.
>> + */
>> +static void ug_puts(char *s)
>> +{
>> +    while (*s)
>> +        ug_putc(*s++);
>> +}
>> +#endif
> 
> Remove?
> 

Ok :)

>> +    stdout = of_find_node_by_path(path);
>> +    if (!stdout) {
>> +        udbg_printf("%s: missing path %s", __func__, path);
>> +        goto done;
>> +    }
>> +
>> +    for (np = NULL;
>> +        (np = of_find_compatible_node(np, NULL, "usbgecko,usbgecko"));)
>> +        if (np == stdout)
>> +            break;
>> +
>> +    of_node_put(stdout);
>> +    if (!np) {
>> +        udbg_printf("%s: stdout is not an usbgecko", __func__);
>> +        goto done;
>> +    }
> 
> Surely there is something called something like of_node_is_compatible()
> you can use here?  You already have the node pointer, there is no need
> to look at all other nodes.
> 

I see the point.
I didn't find of_node_is_compatible() but I'll look what's available here.

Thanks,
Albert

^ permalink raw reply

* Re: [RFC PATCH 06/19] powerpc: gamecube/wii: introduce GAMECUBE_COMMON
From: Albert Herranz @ 2009-11-24 18:03 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: linuxppc-dev
In-Reply-To: <3D2BF5CA-C4BE-4250-8EC9-7A8E767572E2@kernel.crashing.org>

Segher Boessenkool wrote:
>> Add a config option GAMECUBE_COMMON to be used as a dependency for all
>> options common to the Nintendo GameCube and Wii video game consoles.
> 
> Maybe something like GAMECUBE_OR_WII instead?  "COMMON" is so
> common it's meaningless.
> 

I don't like either GAMECUBE_OR_WII.
It looks as if it can be used to match options for the GAMECUBE _or_ WII. But that's not the meaning of it.

This option should be used only for options applicable to both the GAMECUBE and WII, i.e. basically those options in the WII which where "inherited" from the GAMECUBE to make it retro-compatible.

If GAMECUBE_COMMON is unacceptable, maybe GAMECUBE_LEGACY or GAMECUBE_COMPAT?

Thanks,
Albert

^ permalink raw reply

* Re: [RFC PATCH 05/19] powerpc: wii: bootwrapper bits
From: Albert Herranz @ 2009-11-24 17:56 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: linuxppc-dev
In-Reply-To: <90646C9F-F27D-47AD-9985-83DB7381D6BF@kernel.crashing.org>

Segher Boessenkool wrote:
>> + * We enter with an unknown cache, high BATs and MMU status.
> 
> What does this mean?  You know the low four BATs on entry and
> nothing else?
> 

That means that we do not make assumptions regarding:
- the state of the cache (enabled vs disabled)
- if the high BATs are enabled or not
- if the MMU is enabled or not

Is this clearer? I'm not a native english speaker as you may have noticed already :-P

>> +asm ("\n\
> 
> Global asm() is evil.
> 

Yes, you said. Still, I'd like a proper argument :)

>> +    mfmsr    9\n\
>> +    andi.    0, 9, (1<<4)|(1<<5) /* MSR_DR|MSR_IR */\n\
> 
>> +    andc    9, 9, 0\n\
> 
> mfmsr 9 ; rlwinm 9,9,0,~0x30 ?
> 

Yes. Maybe

mfmsr 9 ; rlwinm 9,9,0,~((1<<4)|(1<<5)) /* MSR_DR|MSR_IR */

>> +    mtspr    0x01a, 8    /* SRR0 */\n\
>> +    mtspr    0x01b, 9    /* SRR1 */\n\
> 
> mtsrr0 and mtsrr1
> 

Easier :)

>> +    sync\n\
>> +    rfi\n\
> 
> No need for sync before rfi
> 

Ok.

>> +    mtspr    0x210, 8    /* IBAT0U */\n\
>> +    mtspr    0x211, 8    /* IBAT0L */\n\
> 
> You only need to set the upper BAT to zero, saves some code.
> 

Great. Is this documented somewhere?

>> +    isync\n\
> 
> isync here is cargo cult
> 

I'll offer a dead chicken to compensate for this.

>> +    li    8, 0x01ff    /* first 16MiB */\n\
>> +    li    9, 0x0002    /* rw */\n\
>> +    mtspr    0x210, 8    /* IBAT0U */\n\
>> +    mtspr    0x211, 9    /* IBAT0L */\n\
>> +    mtspr    0x218, 8    /* DBAT0U */\n\
>> +    mtspr    0x219, 9    /* DBAT0L */\n\
> 
> M=0 for RAM?
> 

See analog question for gamecube bootwrapper bits.

>>
> 
> Also, you should normally write the lower BAT first.  Doesn't matter
> here because IR=DR=0 of course.
> 

I can change that too if it's the general way to go.

>> +    lis    8, 0xcc00    /* I/O mem */\n\
>> +    ori    8, 8, 0x3ff    /* 32MiB */\n\
>> +    lis    9, 0x0c00\n\
>> +    ori    9, 9, 0x002a    /* uncached, guarded, rw */\n\
>> +    mtspr    0x21a, 8    /* DBAT1U */\n\
>> +    mtspr    0x21b, 9    /* DBAT1L */\n\
> 
> Is there any real reason you don't identity map this?
> 

No. There's a bit of nostalgia there.
(On the other hand there's no real reason to identity map it).

>> +    sync\n\
>> +    isync\n\
>> +\n\
> 
> Don't need these
> 

I'll get rid of them, then.

>> +    /* enable high BATs */\n\
>> +    lis    8, 0x8200\n\
>> +    mtspr    0x3f3, 8    /* HID4 */\n\
> 
> You need to use read-modify-write here.  Also, shouldn't you
> enable the extra BATs before setting them?
> 

No. You should first set them up and then enable them.
The content of the HIGH BATs is undefined on boot, AFAIK.

> And you _do_ need isync here as far as I can see.
> 
>> +    /* enable caches */\n\
>> +    mfspr    8, 0x3f0\n\
>> +    ori    8, 8, 0xc000\n\
>> +    mtspr    0x3f0, 8    /* HID0 */\n\
>> +    isync\n\
> 
> You need to invalidate the L1 caches at the same time as you enable
> them.
> 

Ok. I'll check if the caches are enabled. If they aren't I'll invalidate and enable them.

>> +void platform_init(unsigned long r3, unsigned long r4, unsigned long r5)
>> +{
>> +    u32 heapsize = 24*1024*1024 - (u32)_end;
>> +
>> +    simple_alloc_init(_end, heapsize, 32, 64);
>> +    fdt_init(_dtb_start);
>> +
>> +    if (!ug_grab_io_base() && ug_is_adapter_present())
> 
> The "!" reads weird.  Can you not make ug_is_adapter_present()
> call ug_grab_io_base(), anyway?
> 

Calling ug_grab_io_base() from ug_is_adapter_present() can be misleading too (you are supposed to just check if the adapter is present in that function, according to the name).
If the "!" is ugly I can use the following idiom, introducing an error variable.

  error = ug_grab_io_base();
  if (!error && ug_is_adapter_present())
     /* blah */

Thanks,
Albert

^ permalink raw reply

* Re: [RFC PATCH 03/19] powerpc: gamecube: bootwrapper bits
From: Albert Herranz @ 2009-11-24 17:38 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: linuxppc-dev
In-Reply-To: <CE435D2F-8C67-4045-942D-4AA08BF784D0@kernel.crashing.org>

Segher Boessenkool wrote:
> Hi Albert,
> 
>> +asm ("\n\
> 
> 
> A file scope asm?!  Please don't.
> 

So what's your proposal then? Placing it within a fake func?
That asm snippet is the entry point. I took as an example how prpmc2800.c deals with that, providing an own version of the (weak) _zImage_start.

>> + * We enter with the cache enabled, the MMU enabled and some known
>> legacy
>> + * memory mappings active. xBAT3 is unused
> 
> It would be good if you could depend as little as possible on these things;
> that makes writing another bootloader a lot easier.
> 

Ok. I'll do a similar approach as done on the wii bootwrapper.

>> +    /* IBAT3,DBAT3 for first 16Mbytes */\n\
>> +    li    8, 0x01ff    /* 16MB */\n\
>> +    li      9, 0x0002    /* rw */\n\
>> +    mtspr   0x216, 8    /* IBAT3U */\n\
>> +    mtspr   0x217, 9    /* IBAT3L */\n\
>> +    mtspr   0x21e, 8    /* DBAT3U */\n\
>> +    mtspr   0x21f, 9    /* DBAT3L */\n\
> 
> WIMG=0000, are you sure?  Not M=1?
> 

To be honest, I don't recall the details now.
But it was tested in the very early days, the result was not the expected one and, in the end, manual cache coherency management was still needed.

So everything is designed and working assuming M=0.
This can be re-checked again later if needed.

>> +    bcl-    20,4*cr7+so,1f\n\
> 
> Just write  bcl 20,31,1f .

Ok, I used two variants for this and I know which one you like now ;).

> 
> 
> Segher
> 
> 

Thanks,
Albert

^ permalink raw reply

* Re: [PATCH 11/11] of: unify phandle name in struct device_node
From: David Miller @ 2009-11-24 17:37 UTC (permalink / raw)
  To: grant.likely
  Cc: sfr, monstr, microblaze-uclinux, devicetree-discuss, sparclinux,
	linuxppc-dev
In-Reply-To: <20091124081957.6216.74456.stgit@angua>

From: Grant Likely <grant.likely@secretlab.ca>
Date: Tue, 24 Nov 2009 01:20:05 -0700

> In struct device_node, the phandle is named 'linux_phandle' for PowerPC
> and MicroBlaze, and 'node' for SPARC.  There is no good reason for the
> difference, it is just an artifact of the code diverging over a couple
> of years.  This patch renames .node to .linux_phandle for SPARC.

I know it's just a name, but there is no reason to put "linux" in the
member name.  It's the real device phandle value from OpenFirmware not
something invented by Linux's OF layer.

PowerPC uses this for something different, it records the information
here using the special "linux,phandle" and "ibm,phandle" properties.

See unflatten_dt_node() in arch/powerpc/kernel/prom.c before your
changes.

^ permalink raw reply

* Re: [RFC PATCH 14/19] powerpc: allow ioremap within reserved fake ram  regions
From: Albert Herranz @ 2009-11-24 17:09 UTC (permalink / raw)
  To: michael; +Cc: linuxppc-dev
In-Reply-To: <1259019909.31172.63.camel@concordia>

Michael Ellerman wrote:
>> Would it be acceptable to create a global var __allow_ioremap_normal_ram that by default would have a value of 0 and would be set _only_ for those platforms needing it?
>>
>> The other solutions I see is:
>> - add support for discontiguous memory to powerpc 32-bits (which is not something that I can look into now)
>> - don't use the precious second 64MB area (which is a waste)
> 
> - Implement your own ppc_md.ioremap(), see iseries & cell for example.
> 
> Currently that's only called on 64-bit, but you could change that.
> 
> If I'm reading your patch right, you should be able to do that check in
> your platform's ioremap() and then call the generic implementation to do
> the actual work.
> 
> cheers

I could use ppc_md.ioremap to duplicate ioremap except for the ioremap ram check.
But calling the stock ioremap without modifying it is not possible because it checks and bails out when ioremapping a region marked as ram (even if it's not real ram and it's memreserved).

Is the list of memreserved areas preserved once the kernel is running?
If it is preserved another option would be to unban ioremapping ram if memreserved.

Thanks for your input,
Albert

^ permalink raw reply

* Re: [PATCH 2/3] powerpc: Add support for creating FIT uImages
From: Peter Tyser @ 2009-11-24 16:48 UTC (permalink / raw)
  To: Stefano Babic; +Cc: linuxppc-dev, linux-kbuild
In-Reply-To: <4B0BB654.9030604@denx.de>

Hi Stefano,
Thanks for trying the patches out.

On Tue, 2009-11-24 at 11:32 +0100, Stefano Babic wrote:
> Peter Tyser <ptyser wrote:
> > +uboot.fit)
> > +    rm -f "$ofile"
> > +    ${MKITS} -A ppc -C gzip -a $membase -e $membase -v $version \
> > +	-d "$srctree/$dtb" -k "$srctree/$vmz" -o "$object/uImage.its"
> > +    ${MKIMAGE} -f "$object/uImage.its" "$ofile"
> 
> Hi,
> 
> I have tested your patches against last mkimage utility provided with
> u-boot. The utility requires to pass the type of the image (flat_dt),
> even if this is not mentioned in the help output. Without the image type
> parameter, no image is generated, and no error is reported.
> It should be:
> 
>     ${MKIMAGE} -f "$object/uImage.its" - T flat_dt "$ofile"

Argh, I'm seeing the same behavior with the latest mkimage source too.
It looks like there was a regression in the mkimage utility - the "-T"
option shouldn't be necessary to create a FIT image.  I'll send a patch
to U-Boot to fix this behavior.

> I have tried to get an image for the lite5200b board, because I have the
> possibility to test the result on the target. However, dtc fails to
> compile the its generated by your script (Version: DTC 1.2.0-g0ef21055,
> cloned from jdt).

I did my testing using the dtc in the linux kernel source
(scripts/dtc/dtc, version 1.2.0) and version 1.2.0-rc1.  I see the same
error as you when using version 1.2.0-g0ef21055.

> DTC: dts->dtb  on file "arch/powerpc/boot/uImage.its"
> Error: arch/powerpc/boot/uImage.its 1:0 syntax error
> 
> Do you test in different conditions ?

Applying the following change should resolve the dtc syntax error.

diff --git a/scripts/mkits.sh b/scripts/mkits.sh
index 88411dd..75edc27 100755
--- a/scripts/mkits.sh
+++ b/scripts/mkits.sh
@@ -64,7 +64,9 @@ ENTRY_ADDR=`echo $ENTRY_ADDR | sed 's/0x//'`
 RAMFS_ADDR=`echo $RAMFS_ADDR | sed 's/0x//'`
 
 # Create a default, fully populated DTS file
-DATA="/ {
+DATA="/dts-v1/;
+
+/ {
        description = \"Linux kernel ${VERSION}\";
        #address-cells = <1>;
 

I'll wait a few more days for feedback then resubmit with the dts syntax
fix

Thanks for testing,
Peter

^ permalink raw reply related

* Re: [PATCH] PPC: Sync guest visible MMU state
From: Avi Kivity @ 2009-11-24 16:05 UTC (permalink / raw)
  To: Alexander Graf; +Cc: kvm-ppc, kvm, linuxppc-dev
In-Reply-To: <A6B88177-8F90-4C87-B404-63078E3D3D2C@suse.de>

On 11/24/2009 05:04 PM, Alexander Graf wrote:
>>
>>> index 92045a9..1240fcb 100644
>>> --- a/include/linux/kvm.h
>>> +++ b/include/linux/kvm.h
>>> @@ -492,6 +492,7 @@ struct kvm_ioeventfd {
>>>   #ifdef __KVM_HAVE_VCPU_EVENTS
>>>   #define KVM_CAP_VCPU_EVENTS 41
>>>   #endif
>>> +#define KVM_CAP_PPC_SEGSTATE 42
>>>
>>>
>>>        
>> 42 is already taken (s390 psw and D. Adams), please use 43.
>>      
> Aww. Any reason I didn't get the s390 patch in a git pull yet? (damn that Carsten - he got the cool number)
>
>    

It's in the next branch only ('git fetch blah').

-- 
error compiling committee.c: too many arguments to function

^ permalink raw reply

* Re: [PATCH 7/8] spi_mpc8xxx: Turn qe_mode into flags
From: Anton Vorontsov @ 2009-11-24 15:41 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: David Brownell, Greg Kroah-Hartman, linux-kernel, linuxppc-dev,
	spi-devel-general, Andrew Morton
In-Reply-To: <1259039016.16367.118.camel@pasglop>

On Tue, Nov 24, 2009 at 04:03:36PM +1100, Benjamin Herrenschmidt wrote:
[...]
> This patch breaks my 6xx config:
> 
> /home/benh/linux-powerpc-test/arch/powerpc/platforms/83xx/mpc832x_rdb.c: In function ‘of_fsl_spi_probe’:
> /home/benh/linux-powerpc-test/arch/powerpc/platforms/83xx/mpc832x_rdb.c:77: error: ‘struct fsl_spi_platform_data’ has no member named ‘qe_
> 
> The reason is that the mpc832x_rdb.c code still uses the legacy probing
> method. The fix is not totally trivial as the new flags are defined inside
> spi_mpc8xxx.c

Thanks for noticing. I indeed forgot about the legacy stuff. :-/

> If you are going to keep the flags in the .c file you probably also want
> to remove the platform device definition from fsl_devices.h anyways as
> there's no point exposing to the world a structure with a "flags" member
> if the definition of those flags isn't also exposed.

Yep. Though, IIRC Joakim asked to keep the legacy bindings for some
time (until we implement SPI chip-select framework?)... so for now
we'll have to leave we the exposed flags.

Thanks again,

-- 
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2

^ permalink raw reply

* Re: [PATCH] PPC: Sync guest visible MMU state
From: Alexander Graf @ 2009-11-24 15:04 UTC (permalink / raw)
  To: Avi Kivity; +Cc: kvm-ppc, kvm, linuxppc-dev
In-Reply-To: <4B0BF592.9020802@redhat.com>


On 24.11.2009, at 16:02, Avi Kivity wrote:

> On 11/24/2009 09:50 AM, Alexander Graf wrote:
>> Currently userspace has no chance to find out which virtual address =
space we're
>> in and resolve addresses. While that is a big problem for migration, =
it's also
>> unpleasent when debugging, as gdb and the monitor don't work on =
virtual
>> addresses.
>>  =20
>=20
>> index 92045a9..1240fcb 100644
>> --- a/include/linux/kvm.h
>> +++ b/include/linux/kvm.h
>> @@ -492,6 +492,7 @@ struct kvm_ioeventfd {
>>  #ifdef __KVM_HAVE_VCPU_EVENTS
>>  #define KVM_CAP_VCPU_EVENTS 41
>>  #endif
>> +#define KVM_CAP_PPC_SEGSTATE 42
>>=20
>>  =20
>=20
> 42 is already taken (s390 psw and D. Adams), please use 43.

Aww. Any reason I didn't get the s390 patch in a git pull yet? (damn =
that Carsten - he got the cool number)

Alex

^ permalink raw reply

* Re: [PATCH] PPC: Sync guest visible MMU state
From: Avi Kivity @ 2009-11-24 15:02 UTC (permalink / raw)
  To: Alexander Graf; +Cc: kvm-ppc, kvm, linuxppc-dev
In-Reply-To: <1259049003-8028-1-git-send-email-agraf@suse.de>

On 11/24/2009 09:50 AM, Alexander Graf wrote:
> Currently userspace has no chance to find out which virtual address space we're
> in and resolve addresses. While that is a big problem for migration, it's also
> unpleasent when debugging, as gdb and the monitor don't work on virtual
> addresses.
>    

> index 92045a9..1240fcb 100644
> --- a/include/linux/kvm.h
> +++ b/include/linux/kvm.h
> @@ -492,6 +492,7 @@ struct kvm_ioeventfd {
>   #ifdef __KVM_HAVE_VCPU_EVENTS
>   #define KVM_CAP_VCPU_EVENTS 41
>   #endif
> +#define KVM_CAP_PPC_SEGSTATE 42
>
>    

42 is already taken (s390 psw and D. Adams), please use 43.

-- 
error compiling committee.c: too many arguments to function

^ permalink raw reply

* Re: [PATCH] ppc64: re-enable kexec to allow module loads with CONFIG_MODVERSIONS and CONFIG_RELOCATABLE turned on
From: Neil Horman @ 2009-11-24 14:43 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: paulus, nhorman
In-Reply-To: <20091119195216.GC11414@hmsreliant.think-freely.org>

On Thu, Nov 19, 2009 at 02:52:16PM -0500, Neil Horman wrote:
> Hey there-
> 	Before anyone flames me for what a oddball solution this is, let me just
> say I'm trying to get the ball rolling here.  I think there may be better
> solutions that can be impemented in reloc_64.S, but I've yet to make any of the
> ones I've tried work successfully.  I'm open to suggestions, but this solution
> is the only one so far that I've been able to get to work. thanks :)
> 
> 
> Adjust crcs in __kcrctab_* sections if relocs are used with CONFIG_RELOCATABLE
> 
> When CONFIG_MODVERSIONS and CONFIG_RELOCATABLE are enabled on powerpc platforms,
> kdump has been failing in a rather odd way.  specifically modules will not
> install.  This is because when validating the crcs of symbols that the module
> needs, the crc of the module never matches the crc that is stored in the kernel.
> 
> The underlying cause of this is how CONFIG_MODVERSIONS is implemented, and how
> CONFIG_RELOCATABLE are implemented.  with CONFIG_MODVERSIONS enabled, for every
> exported symbol in the kernel we emit 2 symbols, __crc_#sym which is declared
> extern and __kcrctab_##sym, which is placed in the __kcrctab section of the
> binary.  The latter has its value set equal to the address of the former
> (recalling it is declared extern).  After the object file is built, genksyms is
> run on the processed source, and crcs are computed for each exported symbol.
> genksyms then emits a linker script which defines each of the needed __crc_##sym
> symbols, and sets their addresses euqal to their respective crcs.  This script
> is then used in a secondary link to the previously build object file, so that
> the crcs of the missing symbol can be validated on module insert.
> 
> The problem here is that because __kcrctab_sym is set equal to &__crc_##sym, a
> relocation entry is emitted by the compiler for the __kcrctab__##sym.  Normally
> this is not a problem, since relocation on other arches is done without the aid
> of .rel.dyn sections.  PPC however uses these relocations when
> CONFIG_RELOCATABLE is enabled.  nominally, since addressing starts at 0 for ppc,
> its irrelevant, but if we start at a non-zero address (like we do when booting
> via kexec from reserved crashkernel memory), the ppc boot code iterates over the
> relocation entries, and winds up adding that relocation offset to all symbols,
> including the symbols that are actually the aforementioned crc values in the
> __kcrctab_* sections.  This effectively corrupts the crcs and prevents any
> module loads from happening during a kdump.
> 
> My solution is to 'undo' these relocations prior to boot up.  If
> ARCH_USES_RELOC_ENTRIES is defined, we add a symbol at address zero to the
> linker script for that arch (I call it reloc_start, so that &reloc_start = 0).
> This symbol will then indicate the relocation offset for any given boot.  We
> also add an initcall to the module code that, during boot, scans the __kcrctab_*
> sections and subtracts &reloc_start from every entry in those sections,
> restoring the appropriate crc value.
> 
> I've verified that this allows kexec to work properly on ppc64 systems myself.
> 
> Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> 
Ping, any thoughts here?  As I've been mulling this over, I'm beginning to like
this solution better than a completely arch-specific section, as this approach
makes common the bits that any arch is going to need if they implement
CONFIG_RELOCATABLE with a .rel[a].* section set.  The alternative is of course
to simply skip the appropriate relocations, but thats something that every arch
will need to discover on their own.  This makes it a bit more clear whats
happening I think.

Regards
Neil

^ permalink raw reply

* PMP hot plug issue in kernel
From: Bhartiya Anju-B07263 @ 2009-11-24 12:35 UTC (permalink / raw)
  To: linux-ide; +Cc: linuxppc-dev, Chen, Eric, Kalra Ashish-B00888, Ensheng.Huang

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

Hi All,
 
Recently came across an issue which is decribed below.
 
Setup: Port Multiplier with 2 HDD's connected to it; Port multiplier is
connected to a SATA port of the Host Controller.
 
Test: HDD1 is mounted and using dd command a file of size 512MB is being
written on it.
Command: time sh -c "dd if=/dev/zero of=/mnt/hd/ddfile bs=1k
count=512000 && sync"
 
While this command is running, if the second HDD on PMP is plugged out,
the R/W speed of the first HDD gets affected.
Please see the results of experiments on 2.6.31 kernel.
 
Plug Out	 Plug in	 Normal	
real    0m34.433s
user    0m0.932s
sys     0m21.352s	 real    0m23.726s
user    0m0.908s
sys     0m21.388s	 real    0m23.329s
user    0m1.132s
sys     0m20.968s	
 
The results are similiar with multiple Port Multipliers (Si3726, Si4726
and EXAR PMP) and multiple Host controllers (Si3132  and sata_fsl).
 
As the behaviour with multiple Host controllers and Port Multipliers is
the same so this seems to be an issue with libata stack.
Is there already a patch for this issue? Any pointers or help to fix
this will be greatly appreciated.
 
Best Regards,
Anju
Applications Engineer 
Freescale Semiconductor

[-- Attachment #2: Type: text/html, Size: 6347 bytes --]

^ permalink raw reply

* [PATCH] tty/of_serial: add missing ns16550a id
From: Arnd Bergmann @ 2009-11-24 10:22 UTC (permalink / raw)
  To: greg, devicetree-discuss
  Cc: linux-kernel, linux-serial, linuxppc-dev, john.williams

From: Michal Simek <monstr@monstr.eu>

Many boards have a bug-free ns16550 compatible serial port, which we should
register as PORT_16550A. This introduces a new value "ns16550a" for the
compatible property of of_serial to let a firmware choose that model instead
of using the crippled PORT_16550 mode.

Reported-by: Alon Ziv <alonz@nolaviz.org>
Signed-off-by: Michal Simek <monstr@monstr.eu>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>

---
Please apply to the tty tree for 2.6.33

--- a/drivers/serial/of_serial.c
+++ b/drivers/serial/of_serial.c
@@ -161,6 +161,7 @@ static int of_platform_serial_remove(struct of_device *ofdev)
 static struct of_device_id __devinitdata of_platform_serial_table[] = {
 	{ .type = "serial", .compatible = "ns8250",   .data = (void *)PORT_8250, },
 	{ .type = "serial", .compatible = "ns16450",  .data = (void *)PORT_16450, },
+	{ .type = "serial", .compatible = "ns16550a", .data = (void *)PORT_16550A, },
 	{ .type = "serial", .compatible = "ns16550",  .data = (void *)PORT_16550, },
 	{ .type = "serial", .compatible = "ns16750",  .data = (void *)PORT_16750, },
 	{ .type = "serial", .compatible = "ns16850",  .data = (void *)PORT_16850, },

^ permalink raw reply

* [PATCH 11/11] of: unify phandle name in struct device_node
From: Grant Likely @ 2009-11-24  8:20 UTC (permalink / raw)
  To: linuxppc-dev, devicetree-discuss, sparclinux, microblaze-uclinux,
	benh, sfr, davem, monstr
In-Reply-To: <20091124081316.6216.66310.stgit@angua>

In struct device_node, the phandle is named 'linux_phandle' for PowerPC
and MicroBlaze, and 'node' for SPARC.  There is no good reason for the
difference, it is just an artifact of the code diverging over a couple
of years.  This patch renames .node to .linux_phandle for SPARC.

Note: the .node also existed in PowerPC/MicroBlaze, but the only user
seems to be arch/powerpc/platforms/powermac/pfunc_core.c.  It doesn't
look like the assignment between .linux_phandle and .node is
significantly different enough to warrant the separate code paths
unless ibm,phandle properties actually appear in Apple device trees.

I think it is safe to eliminate the old .node property and use
linux_phandle everywhere.

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---

 arch/powerpc/platforms/powermac/pfunc_core.c |    2 +-
 arch/sparc/kernel/devices.c                  |    2 +-
 arch/sparc/kernel/of_device_32.c             |    2 +-
 arch/sparc/kernel/of_device_64.c             |    2 +-
 arch/sparc/kernel/prom_common.c              |    8 ++++----
 arch/sparc/kernel/smp_64.c                   |    2 +-
 drivers/of/fdt.c                             |    3 +--
 drivers/sbus/char/openprom.c                 |   10 +++++-----
 drivers/video/aty/atyfb_base.c               |    2 +-
 include/linux/of.h                           |    3 ---
 10 files changed, 16 insertions(+), 20 deletions(-)

diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c
index 96d5ce5..2004b19 100644
--- a/arch/powerpc/platforms/powermac/pfunc_core.c
+++ b/arch/powerpc/platforms/powermac/pfunc_core.c
@@ -842,7 +842,7 @@ struct pmf_function *__pmf_find_function(struct device_node *target,
 	list_for_each_entry(func, &dev->functions, link) {
 		if (name && strcmp(name, func->name))
 			continue;
-		if (func->phandle && target->node != func->phandle)
+		if (func->phandle && target->linux_phandle != func->phandle)
 			continue;
 		if ((func->flags & flags) == 0)
 			continue;
diff --git a/arch/sparc/kernel/devices.c b/arch/sparc/kernel/devices.c
index b171ae8..2196e71 100644
--- a/arch/sparc/kernel/devices.c
+++ b/arch/sparc/kernel/devices.c
@@ -59,7 +59,7 @@ static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg,
 
 	cur_inst = 0;
 	for_each_node_by_type(dp, "cpu") {
-		int err = check_cpu_node(dp->node, &cur_inst,
+		int err = check_cpu_node(dp->linux_phandle, &cur_inst,
 					 compare, compare_arg,
 					 prom_node, mid);
 		if (!err) {
diff --git a/arch/sparc/kernel/of_device_32.c b/arch/sparc/kernel/of_device_32.c
index 4c26eb5..27f4c2e 100644
--- a/arch/sparc/kernel/of_device_32.c
+++ b/arch/sparc/kernel/of_device_32.c
@@ -433,7 +433,7 @@ build_resources:
 	if (!parent)
 		dev_set_name(&op->dev, "root");
 	else
-		dev_set_name(&op->dev, "%08x", dp->node);
+		dev_set_name(&op->dev, "%08x", dp->linux_phandle);
 
 	if (of_device_register(op)) {
 		printk("%s: Could not register of device.\n",
diff --git a/arch/sparc/kernel/of_device_64.c b/arch/sparc/kernel/of_device_64.c
index 881947e..9a6245d 100644
--- a/arch/sparc/kernel/of_device_64.c
+++ b/arch/sparc/kernel/of_device_64.c
@@ -666,7 +666,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp,
 	if (!parent)
 		dev_set_name(&op->dev, "root");
 	else
-		dev_set_name(&op->dev, "%08x", dp->node);
+		dev_set_name(&op->dev, "%08x", dp->linux_phandle);
 
 	if (of_device_register(op)) {
 		printk("%s: Could not register of device.\n",
diff --git a/arch/sparc/kernel/prom_common.c b/arch/sparc/kernel/prom_common.c
index d80a65d..2a3e302 100644
--- a/arch/sparc/kernel/prom_common.c
+++ b/arch/sparc/kernel/prom_common.c
@@ -42,7 +42,7 @@ struct device_node *of_find_node_by_phandle(phandle handle)
 	struct device_node *np;
 
 	for (np = allnodes; np; np = np->allnext)
-		if (np->node == handle)
+		if (np->linux_phandle == handle)
 			break;
 
 	return np;
@@ -89,7 +89,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len
 			void *old_val = prop->value;
 			int ret;
 
-			ret = prom_setprop(dp->node, name, val, len);
+			ret = prom_setprop(dp->linux_phandle, name, val, len);
 
 			err = -EINVAL;
 			if (ret >= 0) {
@@ -236,7 +236,7 @@ static struct device_node * __init prom_create_node(phandle node,
 
 	dp->name = get_one_property(node, "name");
 	dp->type = get_one_property(node, "device_type");
-	dp->node = node;
+	dp->linux_phandle = node;
 
 	dp->properties = build_prop_list(node);
 
@@ -313,7 +313,7 @@ void __init prom_build_devicetree(void)
 
 	nextp = &allnodes->allnext;
 	allnodes->child = prom_build_tree(allnodes,
-					  prom_getchild(allnodes->node),
+					  prom_getchild(allnodes->linux_phandle),
 					  &nextp);
 	of_console_init();
 
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
index aa36223..9222700 100644
--- a/arch/sparc/kernel/smp_64.c
+++ b/arch/sparc/kernel/smp_64.c
@@ -370,7 +370,7 @@ static int __cpuinit smp_boot_one_cpu(unsigned int cpu)
 	} else {
 		struct device_node *dp = of_find_node_by_cpuid(cpu);
 
-		prom_startcpu(dp->node, entry, cookie);
+		prom_startcpu(dp->linux_phandle, entry, cookie);
 	}
 
 	for (timeout = 0; timeout < 50000; timeout++) {
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 6164781..07ae161 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -315,9 +315,8 @@ unsigned long __init unflatten_dt_node(unsigned long mem,
 					__alignof__(struct property));
 		if (allnextpp) {
 			if (strcmp(pname, "linux,phandle") == 0) {
-				np->node = *((u32 *)*p);
 				if (np->linux_phandle == 0)
-					np->linux_phandle = np->node;
+					np->linux_phandle = *((u32 *)*p);
 			}
 			if (strcmp(pname, "ibm,phandle") == 0)
 				np->linux_phandle = *((u32 *)*p);
diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c
index 75ac19b..a776e65 100644
--- a/drivers/sbus/char/openprom.c
+++ b/drivers/sbus/char/openprom.c
@@ -233,7 +233,7 @@ static int opromnext(void __user *argp, unsigned int cmd, struct device_node *dp
 
 	ph = 0;
 	if (dp)
-		ph = dp->node;
+		ph = dp->linux_phandle;
 
 	data->current_node = dp;
 	*((int *) op->oprom_array) = ph;
@@ -256,7 +256,7 @@ static int oprompci2node(void __user *argp, struct device_node *dp, struct openp
 
 		dp = pci_device_to_OF_node(pdev);
 		data->current_node = dp;
-		*((int *)op->oprom_array) = dp->node;
+		*((int *)op->oprom_array) = dp->linux_phandle;
 		op->oprom_size = sizeof(int);
 		err = copyout(argp, op, bufsize + sizeof(int));
 
@@ -273,7 +273,7 @@ static int oprompath2node(void __user *argp, struct device_node *dp, struct open
 
 	dp = of_find_node_by_path(op->oprom_array);
 	if (dp)
-		ph = dp->node;
+		ph = dp->linux_phandle;
 	data->current_node = dp;
 	*((int *)op->oprom_array) = ph;
 	op->oprom_size = sizeof(int);
@@ -540,7 +540,7 @@ static int opiocgetnext(unsigned int cmd, void __user *argp)
 		}
 	}
 	if (dp)
-		nd = dp->node;
+		nd = dp->linux_phandle;
 	if (copy_to_user(argp, &nd, sizeof(phandle)))
 		return -EFAULT;
 
@@ -570,7 +570,7 @@ static int openprom_bsd_ioctl(struct inode * inode, struct file * file,
 	case OPIOCGETOPTNODE:
 		BUILD_BUG_ON(sizeof(phandle) != sizeof(int));
 
-		if (copy_to_user(argp, &options_node->node, sizeof(phandle)))
+		if (copy_to_user(argp, &options_node->linux_phandle, sizeof(phandle)))
 			return -EFAULT;
 
 		return 0;
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 913b4a4..8357927 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -3104,7 +3104,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
 	}
 
 	dp = pci_device_to_OF_node(pdev);
-	if (node == dp->node) {
+	if (node == dp->linux_phandle) {
 		struct fb_var_screeninfo *var = &default_var;
 		unsigned int N, P, Q, M, T, R;
 		u32 v_total, h_total;
diff --git a/include/linux/of.h b/include/linux/of.h
index 0a51742..0ddd985 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -39,10 +39,7 @@ struct of_irq_controller;
 struct device_node {
 	const char *name;
 	const char *type;
-	phandle	node;
-#if !defined(CONFIG_SPARC)
 	phandle linux_phandle;
-#endif
 	char	*full_name;
 
 	struct	property *properties;

^ permalink raw reply related

* [PATCH 10/11] microblaze: gut implementation of early_init_dt_scan_cpus()
From: Grant Likely @ 2009-11-24  8:19 UTC (permalink / raw)
  To: linuxppc-dev, devicetree-discuss, sparclinux, microblaze-uclinux,
	benh, sfr, davem, monstr
In-Reply-To: <20091124081316.6216.66310.stgit@angua>

Microblaze only has one CPU, it isn't SMP at all.  This function is
effectively just a no-op, so remove it.

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---

 arch/microblaze/kernel/prom.c |   54 -----------------------------------------
 1 files changed, 0 insertions(+), 54 deletions(-)

diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c
index 8c00457..1f79e4d 100644
--- a/arch/microblaze/kernel/prom.c
+++ b/arch/microblaze/kernel/prom.c
@@ -50,60 +50,6 @@ struct device_node *of_chosen;
 int __init early_init_dt_scan_cpus(unsigned long node, const char *uname,
 				   int depth, void *data)
 {
-	static int logical_cpuid;
-	char *type = of_get_flat_dt_prop(node, "device_type", NULL);
-	const u32 *intserv;
-	int i, nthreads;
-	int found = 0;
-
-	/* We are scanning "cpu" nodes only */
-	if (type == NULL || strcmp(type, "cpu") != 0)
-		return 0;
-
-	/* Get physical cpuid */
-	intserv = of_get_flat_dt_prop(node, "reg", NULL);
-	nthreads = 1;
-
-	/*
-	 * Now see if any of these threads match our boot cpu.
-	 * NOTE: This must match the parsing done in smp_setup_cpu_maps.
-	 */
-	for (i = 0; i < nthreads; i++) {
-		/*
-		 * version 2 of the kexec param format adds the phys cpuid of
-		 * booted proc.
-		 */
-		if (initial_boot_params && initial_boot_params->version >= 2) {
-			if (intserv[i] ==
-					initial_boot_params->boot_cpuid_phys) {
-				found = 1;
-				break;
-			}
-		} else {
-			/*
-			 * Check if it's the boot-cpu, set it's hw index now,
-			 * unfortunately this format did not support booting
-			 * off secondary threads.
-			 */
-			if (of_get_flat_dt_prop(node,
-					"linux,boot-cpu", NULL) != NULL) {
-				found = 1;
-				break;
-			}
-		}
-
-#ifdef CONFIG_SMP
-		/* logical cpu id is always 0 on UP kernels */
-		logical_cpuid++;
-#endif
-	}
-
-	if (found) {
-		pr_debug("boot cpu: logical %d physical %d\n", logical_cpuid,
-			intserv[i]);
-		boot_cpuid = logical_cpuid;
-	}
-
 	return 0;
 }
 

^ permalink raw reply related

* [PATCH 09/11] of: merge of_attach_node() & of_detach_node()
From: Grant Likely @ 2009-11-24  8:19 UTC (permalink / raw)
  To: linuxppc-dev, devicetree-discuss, sparclinux, microblaze-uclinux,
	benh, sfr, davem, monstr
In-Reply-To: <20091124081316.6216.66310.stgit@angua>

Merge common code between PowerPC and Microblaze

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---

 arch/microblaze/include/asm/prom.h |    4 --
 arch/microblaze/kernel/prom.c      |   59 -----------------------------------
 arch/powerpc/include/asm/prom.h    |    4 --
 arch/powerpc/kernel/prom.c         |   59 -----------------------------------
 drivers/of/base.c                  |   60 ++++++++++++++++++++++++++++++++++++
 include/linux/of.h                 |    4 ++
 6 files changed, 64 insertions(+), 126 deletions(-)

diff --git a/arch/microblaze/include/asm/prom.h b/arch/microblaze/include/asm/prom.h
index 07d1063..6c6b386 100644
--- a/arch/microblaze/include/asm/prom.h
+++ b/arch/microblaze/include/asm/prom.h
@@ -39,10 +39,6 @@ extern struct device_node *of_chosen;
 
 extern rwlock_t devtree_lock;	/* temporary while merging */
 
-/* For updating the device tree at runtime */
-extern void of_attach_node(struct device_node *);
-extern void of_detach_node(struct device_node *);
-
 /* Other Prototypes */
 extern int early_uartlite_console(void);
 
diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c
index c0d53b7..8c00457 100644
--- a/arch/microblaze/kernel/prom.c
+++ b/arch/microblaze/kernel/prom.c
@@ -313,65 +313,6 @@ struct device_node *of_find_node_by_phandle(phandle handle)
 }
 EXPORT_SYMBOL(of_find_node_by_phandle);
 
-/*
- * Plug a device node into the tree and global list.
- */
-void of_attach_node(struct device_node *np)
-{
-	unsigned long flags;
-
-	write_lock_irqsave(&devtree_lock, flags);
-	np->sibling = np->parent->child;
-	np->allnext = allnodes;
-	np->parent->child = np;
-	allnodes = np;
-	write_unlock_irqrestore(&devtree_lock, flags);
-}
-
-/*
- * "Unplug" a node from the device tree.  The caller must hold
- * a reference to the node.  The memory associated with the node
- * is not freed until its refcount goes to zero.
- */
-void of_detach_node(struct device_node *np)
-{
-	struct device_node *parent;
-	unsigned long flags;
-
-	write_lock_irqsave(&devtree_lock, flags);
-
-	parent = np->parent;
-	if (!parent)
-		goto out_unlock;
-
-	if (allnodes == np)
-		allnodes = np->allnext;
-	else {
-		struct device_node *prev;
-		for (prev = allnodes;
-		     prev->allnext != np;
-		     prev = prev->allnext)
-			;
-		prev->allnext = np->allnext;
-	}
-
-	if (parent->child == np)
-		parent->child = np->sibling;
-	else {
-		struct device_node *prevsib;
-		for (prevsib = np->parent->child;
-		     prevsib->sibling != np;
-		     prevsib = prevsib->sibling)
-			;
-		prevsib->sibling = np->sibling;
-	}
-
-	of_node_set_flag(np, OF_DETACHED);
-
-out_unlock:
-	write_unlock_irqrestore(&devtree_lock, flags);
-}
-
 #if defined(CONFIG_DEBUG_FS) && defined(DEBUG)
 static struct debugfs_blob_wrapper flat_dt_blob;
 
diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h
index 2ab9cbd..f384db8 100644
--- a/arch/powerpc/include/asm/prom.h
+++ b/arch/powerpc/include/asm/prom.h
@@ -34,10 +34,6 @@ extern struct device_node *of_chosen;
 
 #define HAVE_ARCH_DEVTREE_FIXUPS
 
-/* For updating the device tree at runtime */
-extern void of_attach_node(struct device_node *);
-extern void of_detach_node(struct device_node *);
-
 #ifdef CONFIG_PPC32
 /*
  * PCI <-> OF matching functions
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 6873db9..7d0beeb 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -740,65 +740,6 @@ struct device_node *of_find_next_cache_node(struct device_node *np)
 	return NULL;
 }
 
-/*
- * Plug a device node into the tree and global list.
- */
-void of_attach_node(struct device_node *np)
-{
-	unsigned long flags;
-
-	write_lock_irqsave(&devtree_lock, flags);
-	np->sibling = np->parent->child;
-	np->allnext = allnodes;
-	np->parent->child = np;
-	allnodes = np;
-	write_unlock_irqrestore(&devtree_lock, flags);
-}
-
-/*
- * "Unplug" a node from the device tree.  The caller must hold
- * a reference to the node.  The memory associated with the node
- * is not freed until its refcount goes to zero.
- */
-void of_detach_node(struct device_node *np)
-{
-	struct device_node *parent;
-	unsigned long flags;
-
-	write_lock_irqsave(&devtree_lock, flags);
-
-	parent = np->parent;
-	if (!parent)
-		goto out_unlock;
-
-	if (allnodes == np)
-		allnodes = np->allnext;
-	else {
-		struct device_node *prev;
-		for (prev = allnodes;
-		     prev->allnext != np;
-		     prev = prev->allnext)
-			;
-		prev->allnext = np->allnext;
-	}
-
-	if (parent->child == np)
-		parent->child = np->sibling;
-	else {
-		struct device_node *prevsib;
-		for (prevsib = np->parent->child;
-		     prevsib->sibling != np;
-		     prevsib = prevsib->sibling)
-			;
-		prevsib->sibling = np->sibling;
-	}
-
-	of_node_set_flag(np, OF_DETACHED);
-
-out_unlock:
-	write_unlock_irqrestore(&devtree_lock, flags);
-}
-
 #ifdef CONFIG_PPC_PSERIES
 /*
  * Fix up the uninitialized fields in a new device node:
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 4b10c89..9212b87 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -60,6 +60,66 @@ int of_n_size_cells(struct device_node *np)
 }
 EXPORT_SYMBOL(of_n_size_cells);
 
+/**
+ * of_attach_node - Plug a device node into the tree and global list.
+ */
+void of_attach_node(struct device_node *np)
+{
+	unsigned long flags;
+
+	write_lock_irqsave(&devtree_lock, flags);
+	np->sibling = np->parent->child;
+	np->allnext = allnodes;
+	np->parent->child = np;
+	allnodes = np;
+	write_unlock_irqrestore(&devtree_lock, flags);
+}
+
+/**
+ * of_detach_node - "Unplug" a node from the device tree.
+ *
+ * The caller must hold a reference to the node.  The memory associated with
+ * the node is not freed until its refcount goes to zero.
+ */
+void of_detach_node(struct device_node *np)
+{
+	struct device_node *parent;
+	unsigned long flags;
+
+	write_lock_irqsave(&devtree_lock, flags);
+
+	parent = np->parent;
+	if (!parent)
+		goto out_unlock;
+
+	if (allnodes == np)
+		allnodes = np->allnext;
+	else {
+		struct device_node *prev;
+		for (prev = allnodes;
+		     prev->allnext != np;
+		     prev = prev->allnext)
+			;
+		prev->allnext = np->allnext;
+	}
+
+	if (parent->child == np)
+		parent->child = np->sibling;
+	else {
+		struct device_node *prevsib;
+		for (prevsib = np->parent->child;
+		     prevsib->sibling != np;
+		     prevsib = prevsib->sibling)
+			;
+		prevsib->sibling = np->sibling;
+	}
+
+	of_node_set_flag(np, OF_DETACHED);
+
+out_unlock:
+	write_unlock_irqrestore(&devtree_lock, flags);
+}
+
 #if !defined(CONFIG_SPARC)   /* SPARC doesn't do ref counting (yet) */
 /**
  *	of_node_get - Increment refcount of a node
diff --git a/include/linux/of.h b/include/linux/of.h
index d4c014a..0a51742 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -130,6 +130,10 @@ static inline unsigned long of_read_ulong(const u32 *cell, int size)
 
 #define OF_BAD_ADDR	((u64)-1)
 
+/* For updating the device tree at runtime */
+extern void of_attach_node(struct device_node *);
+extern void of_detach_node(struct device_node *);
+
 extern struct device_node *of_find_node_by_name(struct device_node *from,
 	const char *name);
 #define for_each_node_by_name(dn, name) \

^ permalink raw reply related

* [PATCH 08/11] of: Merge of_node_get() and of_node_put()
From: Grant Likely @ 2009-11-24  8:19 UTC (permalink / raw)
  To: linuxppc-dev, devicetree-discuss, sparclinux, microblaze-uclinux,
	benh, sfr, davem, monstr
In-Reply-To: <20091124081316.6216.66310.stgit@angua>

Merge common code between PowerPC and MicroBlaze

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---

 arch/microblaze/kernel/prom.c |   74 ----------------------------------------
 arch/powerpc/kernel/prom.c    |   73 ----------------------------------------
 drivers/of/base.c             |   75 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 75 insertions(+), 147 deletions(-)

diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c
index c97192d..c0d53b7 100644
--- a/arch/microblaze/kernel/prom.c
+++ b/arch/microblaze/kernel/prom.c
@@ -313,80 +313,6 @@ struct device_node *of_find_node_by_phandle(phandle handle)
 }
 EXPORT_SYMBOL(of_find_node_by_phandle);
 
-/**
- *	of_node_get - Increment refcount of a node
- *	@node:	Node to inc refcount, NULL is supported to
- *		simplify writing of callers
- *
- *	Returns node.
- */
-struct device_node *of_node_get(struct device_node *node)
-{
-	if (node)
-		kref_get(&node->kref);
-	return node;
-}
-EXPORT_SYMBOL(of_node_get);
-
-static inline struct device_node *kref_to_device_node(struct kref *kref)
-{
-	return container_of(kref, struct device_node, kref);
-}
-
-/**
- *	of_node_release - release a dynamically allocated node
- *	@kref:  kref element of the node to be released
- *
- *	In of_node_put() this function is passed to kref_put()
- *	as the destructor.
- */
-static void of_node_release(struct kref *kref)
-{
-	struct device_node *node = kref_to_device_node(kref);
-	struct property *prop = node->properties;
-
-	/* We should never be releasing nodes that haven't been detached. */
-	if (!of_node_check_flag(node, OF_DETACHED)) {
-		printk(KERN_INFO "WARNING: Bad of_node_put() on %s\n",
-			node->full_name);
-		dump_stack();
-		kref_init(&node->kref);
-		return;
-	}
-
-	if (!of_node_check_flag(node, OF_DYNAMIC))
-		return;
-
-	while (prop) {
-		struct property *next = prop->next;
-		kfree(prop->name);
-		kfree(prop->value);
-		kfree(prop);
-		prop = next;
-
-		if (!prop) {
-			prop = node->deadprops;
-			node->deadprops = NULL;
-		}
-	}
-	kfree(node->full_name);
-	kfree(node->data);
-	kfree(node);
-}
-
-/**
- *	of_node_put - Decrement refcount of a node
- *	@node:	Node to dec refcount, NULL is supported to
- *		simplify writing of callers
- *
- */
-void of_node_put(struct device_node *node)
-{
-	if (node)
-		kref_put(&node->kref, of_node_release);
-}
-EXPORT_SYMBOL(of_node_put);
-
 /*
  * Plug a device node into the tree and global list.
  */
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 65de093..6873db9 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -740,79 +740,6 @@ struct device_node *of_find_next_cache_node(struct device_node *np)
 	return NULL;
 }
 
-/**
- *	of_node_get - Increment refcount of a node
- *	@node:	Node to inc refcount, NULL is supported to
- *		simplify writing of callers
- *
- *	Returns node.
- */
-struct device_node *of_node_get(struct device_node *node)
-{
-	if (node)
-		kref_get(&node->kref);
-	return node;
-}
-EXPORT_SYMBOL(of_node_get);
-
-static inline struct device_node * kref_to_device_node(struct kref *kref)
-{
-	return container_of(kref, struct device_node, kref);
-}
-
-/**
- *	of_node_release - release a dynamically allocated node
- *	@kref:  kref element of the node to be released
- *
- *	In of_node_put() this function is passed to kref_put()
- *	as the destructor.
- */
-static void of_node_release(struct kref *kref)
-{
-	struct device_node *node = kref_to_device_node(kref);
-	struct property *prop = node->properties;
-
-	/* We should never be releasing nodes that haven't been detached. */
-	if (!of_node_check_flag(node, OF_DETACHED)) {
-		printk("WARNING: Bad of_node_put() on %s\n", node->full_name);
-		dump_stack();
-		kref_init(&node->kref);
-		return;
-	}
-
-	if (!of_node_check_flag(node, OF_DYNAMIC))
-		return;
-
-	while (prop) {
-		struct property *next = prop->next;
-		kfree(prop->name);
-		kfree(prop->value);
-		kfree(prop);
-		prop = next;
-
-		if (!prop) {
-			prop = node->deadprops;
-			node->deadprops = NULL;
-		}
-	}
-	kfree(node->full_name);
-	kfree(node->data);
-	kfree(node);
-}
-
-/**
- *	of_node_put - Decrement refcount of a node
- *	@node:	Node to dec refcount, NULL is supported to
- *		simplify writing of callers
- *
- */
-void of_node_put(struct device_node *node)
-{
-	if (node)
-		kref_put(&node->kref, of_node_release);
-}
-EXPORT_SYMBOL(of_node_put);
-
 /*
  * Plug a device node into the tree and global list.
  */
diff --git a/drivers/of/base.c b/drivers/of/base.c
index e81558f..4b10c89 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -60,6 +60,81 @@ int of_n_size_cells(struct device_node *np)
 }
 EXPORT_SYMBOL(of_n_size_cells);
 
+#if !defined(CONFIG_SPARC)   /* SPARC doesn't do ref counting (yet) */
+/**
+ *	of_node_get - Increment refcount of a node
+ *	@node:	Node to inc refcount, NULL is supported to
+ *		simplify writing of callers
+ *
+ *	Returns node.
+ */
+struct device_node *of_node_get(struct device_node *node)
+{
+	if (node)
+		kref_get(&node->kref);
+	return node;
+}
+EXPORT_SYMBOL(of_node_get);
+
+static inline struct device_node *kref_to_device_node(struct kref *kref)
+{
+	return container_of(kref, struct device_node, kref);
+}
+
+/**
+ *	of_node_release - release a dynamically allocated node
+ *	@kref:  kref element of the node to be released
+ *
+ *	In of_node_put() this function is passed to kref_put()
+ *	as the destructor.
+ */
+static void of_node_release(struct kref *kref)
+{
+	struct device_node *node = kref_to_device_node(kref);
+	struct property *prop = node->properties;
+
+	/* We should never be releasing nodes that haven't been detached. */
+	if (!of_node_check_flag(node, OF_DETACHED)) {
+		pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name);
+		dump_stack();
+		kref_init(&node->kref);
+		return;
+	}
+
+	if (!of_node_check_flag(node, OF_DYNAMIC))
+		return;
+
+	while (prop) {
+		struct property *next = prop->next;
+		kfree(prop->name);
+		kfree(prop->value);
+		kfree(prop);
+		prop = next;
+
+		if (!prop) {
+			prop = node->deadprops;
+			node->deadprops = NULL;
+		}
+	}
+	kfree(node->full_name);
+	kfree(node->data);
+	kfree(node);
+}
+
+/**
+ *	of_node_put - Decrement refcount of a node
+ *	@node:	Node to dec refcount, NULL is supported to
+ *		simplify writing of callers
+ *
+ */
+void of_node_put(struct device_node *node)
+{
+	if (node)
+		kref_put(&node->kref, of_node_release);
+}
+EXPORT_SYMBOL(of_node_put);
+#endif /* !CONFIG_SPARC */
+
 struct property *of_find_property(const struct device_node *np,
 				  const char *name,
 				  int *lenp)

^ permalink raw reply related

* [PATCH 07/11] of: merge machine_is_compatible()
From: Grant Likely @ 2009-11-24  8:19 UTC (permalink / raw)
  To: linuxppc-dev, devicetree-discuss, sparclinux, microblaze-uclinux,
	benh, sfr, davem, monstr
In-Reply-To: <20091124081316.6216.66310.stgit@angua>

Merge common code between PowerPC and Microblaze

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---

 arch/microblaze/kernel/prom.c |   18 ------------------
 arch/powerpc/kernel/prom.c    |   18 ------------------
 drivers/of/base.c             |   18 ++++++++++++++++++
 3 files changed, 18 insertions(+), 36 deletions(-)

diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c
index 543465a..c97192d 100644
--- a/arch/microblaze/kernel/prom.c
+++ b/arch/microblaze/kernel/prom.c
@@ -281,24 +281,6 @@ void __init early_init_devtree_arch(void)
 	/* No Microblaze specific code here */
 }
 
-/**
- * Indicates whether the root node has a given value in its
- * compatible property.
- */
-int machine_is_compatible(const char *compat)
-{
-	struct device_node *root;
-	int rc = 0;
-
-	root = of_find_node_by_path("/");
-	if (root) {
-		rc = of_device_is_compatible(root, compat);
-		of_node_put(root);
-	}
-	return rc;
-}
-EXPORT_SYMBOL(machine_is_compatible);
-
 /*******
  *
  * New implementation of the OF "find" APIs, return a refcounted
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index a5b3b9d..65de093 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -677,24 +677,6 @@ void __init early_init_devtree_arch(void)
 	lmb_enforce_memory_limit(limit);
 }
 
-/**
- * Indicates whether the root node has a given value in its
- * compatible property.
- */
-int machine_is_compatible(const char *compat)
-{
-	struct device_node *root;
-	int rc = 0;
-
-	root = of_find_node_by_path("/");
-	if (root) {
-		rc = of_device_is_compatible(root, compat);
-		of_node_put(root);
-	}
-	return rc;
-}
-EXPORT_SYMBOL(machine_is_compatible);
-
 /*******
  *
  * New implementation of the OF "find" APIs, return a refcounted
diff --git a/drivers/of/base.c b/drivers/of/base.c
index ec56739..e81558f 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -144,6 +144,24 @@ int of_device_is_compatible(const struct device_node *device,
 EXPORT_SYMBOL(of_device_is_compatible);
 
 /**
+ * Indicates whether the root node has a given value in its
+ * compatible property.
+ */
+int machine_is_compatible(const char *compat)
+{
+	struct device_node *root;
+	int rc = 0;
+
+	root = of_find_node_by_path("/");
+	if (root) {
+		rc = of_device_is_compatible(root, compat);
+		of_node_put(root);
+	}
+	return rc;
+}
+EXPORT_SYMBOL(machine_is_compatible);
+
+/**
  *  of_device_is_available - check if a device is available for use
  *
  *  @device: Node to check for availability

^ permalink raw reply related

* [PATCH 06/11] of/flattree: merge early_init_devtree() and early_init_move_devtree()
From: Grant Likely @ 2009-11-24  8:19 UTC (permalink / raw)
  To: linuxppc-dev, devicetree-discuss, sparclinux, microblaze-uclinux,
	benh, sfr, davem, monstr
In-Reply-To: <20091124081316.6216.66310.stgit@angua>

Merge common code between Microblaze and PowerPC

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---

 arch/microblaze/kernel/prom.c |   53 +++--------------------
 arch/powerpc/kernel/prom.c    |   94 +++--------------------------------------
 drivers/of/fdt.c              |   92 ++++++++++++++++++++++++++++++++++++++++
 include/linux/of_fdt.h        |    7 +++
 4 files changed, 115 insertions(+), 131 deletions(-)

diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c
index 7ee021f..543465a 100644
--- a/arch/microblaze/kernel/prom.c
+++ b/arch/microblaze/kernel/prom.c
@@ -47,9 +47,8 @@ struct device_node *of_chosen;
 
 #define early_init_dt_scan_drconf_memory(node) 0
 
-static int __init early_init_dt_scan_cpus(unsigned long node,
-					  const char *uname, int depth,
-					  void *data)
+int __init early_init_dt_scan_cpus(unsigned long node, const char *uname,
+				   int depth, void *data)
 {
 	static int logical_cpuid;
 	char *type = of_get_flat_dt_prop(node, "device_type", NULL);
@@ -113,8 +112,8 @@ void __init early_init_dt_scan_chosen_arch(unsigned long node)
 	/* No Microblaze specific code here */
 }
 
-static int __init early_init_dt_scan_memory(unsigned long node,
-				const char *uname, int depth, void *data)
+int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
+				     int depth, void *data)
 {
 	char *type = of_get_flat_dt_prop(node, "device_type", NULL);
 	u32 *reg, *endp;
@@ -201,7 +200,7 @@ static inline unsigned long phyp_dump_calculate_reserve_size(void)
  * without reserving anything. The memory in case of dump being
  * active is freed when the dump is collected (by userland tools).
  */
-static void __init phyp_dump_reserve_mem(void)
+void __init phyp_dump_reserve_mem(void)
 {
 	unsigned long base, size;
 	unsigned long variable_reserve_size;
@@ -240,7 +239,7 @@ static void __init phyp_dump_reserve_mem(void)
 	}
 }
 #else
-static inline void __init phyp_dump_reserve_mem(void) {}
+inline void __init phyp_dump_reserve_mem(void) {}
 #endif /* CONFIG_PHYP_DUMP  && CONFIG_PPC_RTAS */
 
 #ifdef CONFIG_EARLY_PRINTK
@@ -277,45 +276,9 @@ int __init early_uartlite_console(void)
 }
 #endif
 
-void __init early_init_devtree(void *params)
+void __init early_init_devtree_arch(void)
 {
-	pr_debug(" -> early_init_devtree(%p)\n", params);
-
-	/* Setup flat device-tree pointer */
-	initial_boot_params = params;
-
-#ifdef CONFIG_PHYP_DUMP
-	/* scan tree to see if dump occured during last boot */
-	of_scan_flat_dt(early_init_dt_scan_phyp_dump, NULL);
-#endif
-
-	/* Retrieve various informations from the /chosen node of the
-	 * device-tree, including the platform type, initrd location and
-	 * size, TCE reserve, and more ...
-	 */
-	of_scan_flat_dt(early_init_dt_scan_chosen, NULL);
-
-	/* Scan memory nodes and rebuild LMBs */
-	lmb_init();
-	of_scan_flat_dt(early_init_dt_scan_root, NULL);
-	of_scan_flat_dt(early_init_dt_scan_memory, NULL);
-
-	/* Save command line for /proc/cmdline and then parse parameters */
-	strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);
-	parse_early_param();
-
-	lmb_analyze();
-
-	pr_debug("Phys. mem: %lx\n", (unsigned long) lmb_phys_mem_size());
-
-	pr_debug("Scanning CPUs ...\n");
-
-	/* Retreive CPU related informations from the flat tree
-	 * (altivec support, boot CPU ID, ...)
-	 */
-	of_scan_flat_dt(early_init_dt_scan_cpus, NULL);
-
-	pr_debug(" <- early_init_devtree()\n");
+	/* No Microblaze specific code here */
 }
 
 /**
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 2c7d4a3..a5b3b9d 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -84,33 +84,6 @@ static int __init early_parse_mem(char *p)
 }
 early_param("mem", early_parse_mem);
 
-/**
- * move_device_tree - move tree to an unused area, if needed.
- *
- * The device tree may be allocated beyond our memory limit, or inside the
- * crash kernel region for kdump. If so, move it out of the way.
- */
-static void __init move_device_tree(void)
-{
-	unsigned long start, size;
-	void *p;
-
-	DBG("-> move_device_tree\n");
-
-	start = __pa(initial_boot_params);
-	size = initial_boot_params->totalsize;
-
-	if ((memory_limit && (start + size) > memory_limit) ||
-			overlaps_crashkernel(start, size)) {
-		p = __va(lmb_alloc_base(size, PAGE_SIZE, lmb.rmo_size));
-		memcpy(p, initial_boot_params, size);
-		initial_boot_params = (struct boot_param_header *)p;
-		DBG("Moved device tree to 0x%p\n", p);
-	}
-
-	DBG("<- move_device_tree\n");
-}
-
 /*
  * ibm,pa-features is a per-cpu property that contains a string of
  * attribute descriptors, each of which has a 2 byte header plus up
@@ -267,9 +240,8 @@ static void __init check_cpu_feature_properties(unsigned long node)
 	}
 }
 
-static int __init early_init_dt_scan_cpus(unsigned long node,
-					  const char *uname, int depth,
-					  void *data)
+int __init early_init_dt_scan_cpus(unsigned long node, const char *uname,
+				   int depth, void *data)
 {
 	static int logical_cpuid = 0;
 	char *type = of_get_flat_dt_prop(node, "device_type", NULL);
@@ -483,8 +455,8 @@ static int __init early_init_dt_scan_drconf_memory(unsigned long node)
 #define early_init_dt_scan_drconf_memory(node)	0
 #endif /* CONFIG_PPC_PSERIES */
 
-static int __init early_init_dt_scan_memory(unsigned long node,
-					    const char *uname, int depth, void *data)
+int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
+				     int depth, void *data)
 {
 	char *type = of_get_flat_dt_prop(node, "device_type", NULL);
 	u32 *reg, *endp;
@@ -543,7 +515,7 @@ static int __init early_init_dt_scan_memory(unsigned long node,
 	return 0;
 }
 
-static void __init early_reserve_mem(void)
+void __init early_reserve_mem(void)
 {
 	u64 base, size;
 	u64 *reserve_map;
@@ -635,7 +607,7 @@ static inline unsigned long phyp_dump_calculate_reserve_size(void)
  * without reserving anything. The memory in case of dump being
  * active is freed when the dump is collected (by userland tools).
  */
-static void __init phyp_dump_reserve_mem(void)
+void __init phyp_dump_reserve_mem(void)
 {
 	unsigned long base, size;
 	unsigned long variable_reserve_size;
@@ -674,44 +646,13 @@ static void __init phyp_dump_reserve_mem(void)
 	}
 }
 #else
-static inline void __init phyp_dump_reserve_mem(void) {}
+inline void __init phyp_dump_reserve_mem(void) {}
 #endif /* CONFIG_PHYP_DUMP  && CONFIG_PPC_RTAS */
 
-
-void __init early_init_devtree(void *params)
+void __init early_init_devtree_arch(void)
 {
 	phys_addr_t limit;
 
-	DBG(" -> early_init_devtree(%p)\n", params);
-
-	/* Setup flat device-tree pointer */
-	initial_boot_params = params;
-
-#ifdef CONFIG_PPC_RTAS
-	/* Some machines might need RTAS info for debugging, grab it now. */
-	of_scan_flat_dt(early_init_dt_scan_rtas, NULL);
-#endif
-
-#ifdef CONFIG_PHYP_DUMP
-	/* scan tree to see if dump occured during last boot */
-	of_scan_flat_dt(early_init_dt_scan_phyp_dump, NULL);
-#endif
-
-	/* Retrieve various informations from the /chosen node of the
-	 * device-tree, including the platform type, initrd location and
-	 * size, TCE reserve, and more ...
-	 */
-	of_scan_flat_dt(early_init_dt_scan_chosen, NULL);
-
-	/* Scan memory nodes and rebuild LMBs */
-	lmb_init();
-	of_scan_flat_dt(early_init_dt_scan_root, NULL);
-	of_scan_flat_dt(early_init_dt_scan_memory, NULL);
-
-	/* Save command line for /proc/cmdline and then parse parameters */
-	strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);
-	parse_early_param();
-
 	/* Reserve LMB regions used by kernel, initrd, dt, etc... */
 	lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START);
 	/* If relocatable, reserve first 32k for interrupt vectors etc. */
@@ -734,27 +675,8 @@ void __init early_init_devtree(void *params)
 			limit = memsize & PAGE_MASK;
 	}
 	lmb_enforce_memory_limit(limit);
-
-	lmb_analyze();
-	lmb_dump_all();
-
-	DBG("Phys. mem: %llx\n", lmb_phys_mem_size());
-
-	/* We may need to relocate the flat tree, do it now.
-	 * FIXME .. and the initrd too? */
-	move_device_tree();
-
-	DBG("Scanning CPUs ...\n");
-
-	/* Retreive CPU related informations from the flat tree
-	 * (altivec support, boot CPU ID, ...)
-	 */
-	of_scan_flat_dt(early_init_dt_scan_cpus, NULL);
-
-	DBG(" <- early_init_devtree()\n");
 }
 
-
 /**
  * Indicates whether the root node has a given value in its
  * compatible property.
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 616a476..6164781 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -16,7 +16,12 @@
 #include <linux/of_fdt.h>
 
 #ifdef CONFIG_PPC
+#include <asm/kexec.h>
 #include <asm/machdep.h>
+
+#ifdef CONFIG_PPC_RTAS
+#include <asm/rtas.h>
+#endif
 #endif /* CONFIG_PPC */
 
 int __initdata dt_root_addr_cells;
@@ -479,6 +484,93 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
 }
 
 /**
+ * early_init_move_devtree - move tree to an unused area, if needed.
+ *
+ * The device tree may be allocated beyond our memory limit, or inside the
+ * crash kernel region for kdump. If so, move it out of the way.
+ */
+#if defined(CONFIG_PPC)
+static void __init early_init_move_devtree(void)
+{
+	unsigned long start, size;
+	void *p;
+
+	pr_debug("-> %s()\n", __func__);
+
+	start = __pa(initial_boot_params);
+	size = initial_boot_params->totalsize;
+
+	if ((memory_limit && (start + size) > memory_limit) ||
+			overlaps_crashkernel(start, size)) {
+		p = __va(lmb_alloc_base(size, PAGE_SIZE, lmb.rmo_size));
+		memcpy(p, initial_boot_params, size);
+		initial_boot_params = (struct boot_param_header *)p;
+		pr_debug("Moved device tree to 0x%p\n", p);
+	}
+
+	pr_debug("<- %s()\n", __func__);
+}
+#else
+static void __init early_init_move_devtree(void) {}
+#endif
+
+void __init early_init_devtree(void *params)
+{
+	pr_debug(" -> early_init_devtree(%p)\n", params);
+
+	/* Setup flat device-tree pointer */
+	initial_boot_params = params;
+
+#ifdef CONFIG_PPC_RTAS
+	/* Some machines might need RTAS info for debugging, grab it now. */
+	of_scan_flat_dt(early_init_dt_scan_rtas, NULL);
+#endif
+
+#ifdef CONFIG_PHYP_DUMP
+	/* scan tree to see if dump occured during last boot */
+	of_scan_flat_dt(early_init_dt_scan_phyp_dump, NULL);
+#endif
+
+	/* Retrieve various informations from the /chosen node of the
+	 * device-tree, including the platform type, initrd location and
+	 * size, TCE reserve, and more ...
+	 */
+	of_scan_flat_dt(early_init_dt_scan_chosen, NULL);
+
+	/* Scan memory nodes and rebuild LMBs */
+	lmb_init();
+	of_scan_flat_dt(early_init_dt_scan_root, NULL);
+	of_scan_flat_dt(early_init_dt_scan_memory, NULL);
+
+	/* Save command line for /proc/cmdline and then parse parameters */
+	strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);
+	parse_early_param();
+
+	/* This is in an arbitrary spot, but it is temporary.  After all
+	 * the common code is merged, the structure of the early init
+	 * code will be reevaluated and refactored */
+	early_init_devtree_arch();
+
+	lmb_analyze();
+	lmb_dump_all();
+
+	pr_debug("Phys. mem: %llx\n", lmb_phys_mem_size());
+
+	/* We may need to relocate the flat tree, do it now.
+	 * FIXME .. and the initrd too? */
+	early_init_move_devtree();
+
+	pr_debug("Scanning CPUs ...\n");
+
+	/* Retreive CPU related informations from the flat tree
+	 * (altivec support, boot CPU ID, ...)
+	 */
+	of_scan_flat_dt(early_init_dt_scan_cpus, NULL);
+
+	pr_debug(" <- early_init_devtree()\n");
+}
+
+/**
  * unflatten_device_tree - create tree of device_nodes from flat blob
  *
  * unflattens the device-tree passed by the firmware, creating the
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
index 8118d45..d1b1571 100644
--- a/include/linux/of_fdt.h
+++ b/include/linux/of_fdt.h
@@ -75,6 +75,13 @@ extern void early_init_dt_scan_chosen_arch(unsigned long node);
 extern int early_init_dt_scan_chosen(unsigned long node, const char *uname,
 				     int depth, void *data);
 extern void early_init_dt_check_for_initrd(unsigned long node);
+extern int early_init_dt_scan_cpus(unsigned long node, const char *uname,
+				   int depth, void *data);
+extern int early_init_dt_scan_memory(unsigned long node, const char *uname,
+				     int depth, void *data);
+extern void early_reserve_mem(void);
+extern void early_init_devtree_arch(void);
+extern void phyp_dump_reserve_mem(void);
 extern u64 dt_mem_next_cell(int s, u32 **cellp);
 
 /* Early flat tree scan hooks */

^ permalink raw reply related

* [PATCH 05/11] of/flattree: merge early_init_dt_scan_chosen()
From: Grant Likely @ 2009-11-24  8:18 UTC (permalink / raw)
  To: linuxppc-dev, devicetree-discuss, sparclinux, microblaze-uclinux,
	benh, sfr, davem, monstr
In-Reply-To: <20091124081316.6216.66310.stgit@angua>

Merge common code between PowerPC and Microblaze.  This patch
splits the arch-specific stuff out into a new function,
early_init_dt_scan_chosen_arch().

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---

 arch/microblaze/kernel/prom.c |   44 ++-------------------------------------
 arch/powerpc/kernel/prom.c    |   46 +++++++++--------------------------------
 drivers/of/fdt.c              |   38 ++++++++++++++++++++++++++++++++++
 include/linux/of_fdt.h        |    3 +++
 4 files changed, 53 insertions(+), 78 deletions(-)

diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c
index 7760186..7ee021f 100644
--- a/arch/microblaze/kernel/prom.c
+++ b/arch/microblaze/kernel/prom.c
@@ -108,49 +108,9 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
 	return 0;
 }
 
-static int __init early_init_dt_scan_chosen(unsigned long node,
-				const char *uname, int depth, void *data)
+void __init early_init_dt_scan_chosen_arch(unsigned long node)
 {
-	unsigned long l;
-	char *p;
-
-	pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
-
-	if (depth != 1 ||
-		(strcmp(uname, "chosen") != 0 &&
-				strcmp(uname, "chosen@0") != 0))
-		return 0;
-
-#ifdef CONFIG_KEXEC
-	lprop = (u64 *)of_get_flat_dt_prop(node,
-				"linux,crashkernel-base", NULL);
-	if (lprop)
-		crashk_res.start = *lprop;
-
-	lprop = (u64 *)of_get_flat_dt_prop(node,
-				"linux,crashkernel-size", NULL);
-	if (lprop)
-		crashk_res.end = crashk_res.start + *lprop - 1;
-#endif
-
-	early_init_dt_check_for_initrd(node);
-
-	/* Retreive command line */
-	p = of_get_flat_dt_prop(node, "bootargs", &l);
-	if (p != NULL && l > 0)
-		strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE));
-
-#ifdef CONFIG_CMDLINE
-#ifndef CONFIG_CMDLINE_FORCE
-	if (p == NULL || l == 0 || (l == 1 && (*p) == 0))
-#endif
-		strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
-#endif /* CONFIG_CMDLINE */
-
-	pr_debug("Command line is: %s\n", cmd_line);
-
-	/* break now */
-	return 1;
+	/* No Microblaze specific code here */
 }
 
 static int __init early_init_dt_scan_memory(unsigned long node,
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 43cdba2..2c7d4a3 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -367,18 +367,9 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
 	return 0;
 }
 
-static int __init early_init_dt_scan_chosen(unsigned long node,
-					    const char *uname, int depth, void *data)
+void __init early_init_dt_scan_chosen_arch(unsigned long node)
 {
 	unsigned long *lprop;
-	unsigned long l;
-	char *p;
-
-	DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
-
-	if (depth != 1 ||
-	    (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
-		return 0;
 
 #ifdef CONFIG_PPC64
 	/* check if iommu is forced on or off */
@@ -389,17 +380,17 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
 #endif
 
 	/* mem=x on the command line is the preferred mechanism */
- 	lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL);
- 	if (lprop)
- 		memory_limit = *lprop;
+	lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL);
+	if (lprop)
+		memory_limit = *lprop;
 
 #ifdef CONFIG_PPC64
- 	lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-start", NULL);
- 	if (lprop)
- 		tce_alloc_start = *lprop;
- 	lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-end", NULL);
- 	if (lprop)
- 		tce_alloc_end = *lprop;
+	lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-start", NULL);
+	if (lprop)
+		tce_alloc_start = *lprop;
+	lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-end", NULL);
+	if (lprop)
+		tce_alloc_end = *lprop;
 #endif
 
 #ifdef CONFIG_KEXEC
@@ -411,23 +402,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
 	if (lprop)
 		crashk_res.end = crashk_res.start + *lprop - 1;
 #endif
-
-	early_init_dt_check_for_initrd(node);
-
-	/* Retreive command line */
- 	p = of_get_flat_dt_prop(node, "bootargs", &l);
-	if (p != NULL && l > 0)
-		strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE));
-
-#ifdef CONFIG_CMDLINE
-	if (p == NULL || l == 0 || (l == 1 && (*p) == 0))
-		strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
-#endif /* CONFIG_CMDLINE */
-
-	DBG("Command line is: %s\n", cmd_line);
-
-	/* break now */
-	return 1;
 }
 
 #ifdef CONFIG_PPC_PSERIES
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index ebce509..616a476 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -15,6 +15,10 @@
 #include <linux/of.h>
 #include <linux/of_fdt.h>
 
+#ifdef CONFIG_PPC
+#include <asm/machdep.h>
+#endif /* CONFIG_PPC */
+
 int __initdata dt_root_addr_cells;
 int __initdata dt_root_size_cells;
 
@@ -440,6 +444,40 @@ u64 __init dt_mem_next_cell(int s, u32 **cellp)
 	return of_read_number(p, s);
 }
 
+int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
+				     int depth, void *data)
+{
+	unsigned long l;
+	char *p;
+
+	pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
+
+	if (depth != 1 ||
+	    (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
+		return 0;
+
+	early_init_dt_check_for_initrd(node);
+
+	/* Retreive command line */
+	p = of_get_flat_dt_prop(node, "bootargs", &l);
+	if (p != NULL && l > 0)
+		strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE));
+
+#ifdef CONFIG_CMDLINE
+#ifndef CONFIG_CMDLINE_FORCE
+	if (p == NULL || l == 0 || (l == 1 && (*p) == 0))
+#endif
+		strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
+#endif /* CONFIG_CMDLINE */
+
+	early_init_dt_scan_chosen_arch(node);
+
+	pr_debug("Command line is: %s\n", cmd_line);
+
+	/* break now */
+	return 1;
+}
+
 /**
  * unflatten_device_tree - create tree of device_nodes from flat blob
  *
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
index d1a37e5..8118d45 100644
--- a/include/linux/of_fdt.h
+++ b/include/linux/of_fdt.h
@@ -71,6 +71,9 @@ extern void *of_get_flat_dt_prop(unsigned long node, const char *name,
 				 unsigned long *size);
 extern int of_flat_dt_is_compatible(unsigned long node, const char *name);
 extern unsigned long of_get_flat_dt_root(void);
+extern void early_init_dt_scan_chosen_arch(unsigned long node);
+extern int early_init_dt_scan_chosen(unsigned long node, const char *uname,
+				     int depth, void *data);
 extern void early_init_dt_check_for_initrd(unsigned long node);
 extern u64 dt_mem_next_cell(int s, u32 **cellp);
 

^ permalink raw reply related

* [PATCH 04/11] of/flattree: eliminate cell_t typedef
From: Grant Likely @ 2009-11-24  8:18 UTC (permalink / raw)
  To: linuxppc-dev, devicetree-discuss, sparclinux, microblaze-uclinux,
	benh, sfr, davem, monstr
In-Reply-To: <20091124081316.6216.66310.stgit@angua>

A cell is firmly established as a u32.  No need to do an ugly typedef
to redefine it to cell_t.  Eliminate the unnecessary typedef so that
it doesn't have to be added to the of_fdt header file

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---

 arch/microblaze/kernel/prom.c |   10 ++++------
 arch/powerpc/kernel/prom.c    |   14 ++++++--------
 2 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c
index e0f4c34..7760186 100644
--- a/arch/microblaze/kernel/prom.c
+++ b/arch/microblaze/kernel/prom.c
@@ -42,8 +42,6 @@
 #include <asm/sections.h>
 #include <asm/pci-bridge.h>
 
-typedef u32 cell_t;
-
 /* export that to outside world */
 struct device_node *of_chosen;
 
@@ -159,7 +157,7 @@ static int __init early_init_dt_scan_memory(unsigned long node,
 				const char *uname, int depth, void *data)
 {
 	char *type = of_get_flat_dt_prop(node, "device_type", NULL);
-	cell_t *reg, *endp;
+	u32 *reg, *endp;
 	unsigned long l;
 
 	/* Look for the ibm,dynamic-reconfiguration-memory node */
@@ -178,13 +176,13 @@ static int __init early_init_dt_scan_memory(unsigned long node,
 	} else if (strcmp(type, "memory") != 0)
 		return 0;
 
-	reg = (cell_t *)of_get_flat_dt_prop(node, "linux,usable-memory", &l);
+	reg = (u32 *)of_get_flat_dt_prop(node, "linux,usable-memory", &l);
 	if (reg == NULL)
-		reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l);
+		reg = (u32 *)of_get_flat_dt_prop(node, "reg", &l);
 	if (reg == NULL)
 		return 0;
 
-	endp = reg + (l / sizeof(cell_t));
+	endp = reg + (l / sizeof(u32));
 
 	pr_debug("memory scan node %s, reg size %ld, data: %x %x %x %x,\n",
 		uname, l, reg[0], reg[1], reg[2], reg[3]);
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 048e3a3..43cdba2 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -67,8 +67,6 @@ int __initdata iommu_force_on;
 unsigned long tce_alloc_start, tce_alloc_end;
 #endif
 
-typedef u32 cell_t;
-
 extern rwlock_t devtree_lock;	/* temporary while merging */
 
 /* export that to outside world */
@@ -441,22 +439,22 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
  */
 static int __init early_init_dt_scan_drconf_memory(unsigned long node)
 {
-	cell_t *dm, *ls, *usm;
+	u32 *dm, *ls, *usm;
 	unsigned long l, n, flags;
 	u64 base, size, lmb_size;
 	unsigned int is_kexec_kdump = 0, rngs;
 
 	ls = of_get_flat_dt_prop(node, "ibm,lmb-size", &l);
-	if (ls == NULL || l < dt_root_size_cells * sizeof(cell_t))
+	if (ls == NULL || l < dt_root_size_cells * sizeof(u32))
 		return 0;
 	lmb_size = dt_mem_next_cell(dt_root_size_cells, &ls);
 
 	dm = of_get_flat_dt_prop(node, "ibm,dynamic-memory", &l);
-	if (dm == NULL || l < sizeof(cell_t))
+	if (dm == NULL || l < sizeof(u32))
 		return 0;
 
 	n = *dm++;	/* number of entries */
-	if (l < (n * (dt_root_addr_cells + 4) + 1) * sizeof(cell_t))
+	if (l < (n * (dt_root_addr_cells + 4) + 1) * sizeof(u32))
 		return 0;
 
 	/* check if this is a kexec/kdump kernel. */
@@ -515,7 +513,7 @@ static int __init early_init_dt_scan_memory(unsigned long node,
 					    const char *uname, int depth, void *data)
 {
 	char *type = of_get_flat_dt_prop(node, "device_type", NULL);
-	cell_t *reg, *endp;
+	u32 *reg, *endp;
 	unsigned long l;
 
 	/* Look for the ibm,dynamic-reconfiguration-memory node */
@@ -540,7 +538,7 @@ static int __init early_init_dt_scan_memory(unsigned long node,
 	if (reg == NULL)
 		return 0;
 
-	endp = reg + (l / sizeof(cell_t));
+	endp = reg + (l / sizeof(u32));
 
 	DBG("memory scan node %s, reg size %ld, data: %x %x %x %x,\n",
 	    uname, l, reg[0], reg[1], reg[2], reg[3]);

^ permalink raw reply related

* [PATCH 03/11] of/flattree: merge dt_mem_next_cell
From: Grant Likely @ 2009-11-24  8:18 UTC (permalink / raw)
  To: linuxppc-dev, devicetree-discuss, sparclinux, microblaze-uclinux,
	benh, sfr, davem, monstr
In-Reply-To: <20091124081316.6216.66310.stgit@angua>

Merge common code between PowerPC and Microblaze

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---

 arch/microblaze/kernel/prom.c |    8 --------
 arch/powerpc/kernel/prom.c    |    8 --------
 drivers/of/fdt.c              |    8 ++++++++
 include/linux/of_fdt.h        |    1 +
 4 files changed, 9 insertions(+), 16 deletions(-)

diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c
index 189179a..e0f4c34 100644
--- a/arch/microblaze/kernel/prom.c
+++ b/arch/microblaze/kernel/prom.c
@@ -155,14 +155,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
 	return 1;
 }
 
-static u64 __init dt_mem_next_cell(int s, cell_t **cellp)
-{
-	cell_t *p = *cellp;
-
-	*cellp = p + s;
-	return of_read_number(p, s);
-}
-
 static int __init early_init_dt_scan_memory(unsigned long node,
 				const char *uname, int depth, void *data)
 {
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 78f65a4..048e3a3 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -432,14 +432,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
 	return 1;
 }
 
-static u64 __init dt_mem_next_cell(int s, cell_t **cellp)
-{
-	cell_t *p = *cellp;
-
-	*cellp = p + s;
-	return of_read_number(p, s);
-}
-
 #ifdef CONFIG_PPC_PSERIES
 /*
  * Interpret the ibm,dynamic-memory property in the
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index be200be..ebce509 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -432,6 +432,14 @@ int __init early_init_dt_scan_root(unsigned long node, const char *uname,
 	return 1;
 }
 
+u64 __init dt_mem_next_cell(int s, u32 **cellp)
+{
+	u32 *p = *cellp;
+
+	*cellp = p + s;
+	return of_read_number(p, s);
+}
+
 /**
  * unflatten_device_tree - create tree of device_nodes from flat blob
  *
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
index 828c3cd..d1a37e5 100644
--- a/include/linux/of_fdt.h
+++ b/include/linux/of_fdt.h
@@ -72,6 +72,7 @@ extern void *of_get_flat_dt_prop(unsigned long node, const char *name,
 extern int of_flat_dt_is_compatible(unsigned long node, const char *name);
 extern unsigned long of_get_flat_dt_root(void);
 extern void early_init_dt_check_for_initrd(unsigned long node);
+extern u64 dt_mem_next_cell(int s, u32 **cellp);
 
 /* Early flat tree scan hooks */
 extern int early_init_dt_scan_root(unsigned long node, const char *uname,

^ permalink raw reply related

* [PATCH 02/11] of/flattree: Merge earlyinit_dt_scan_root()
From: Grant Likely @ 2009-11-24  8:18 UTC (permalink / raw)
  To: linuxppc-dev, devicetree-discuss, sparclinux, microblaze-uclinux,
	benh, sfr, davem, monstr
In-Reply-To: <20091124081316.6216.66310.stgit@angua>

Merge common code between PowerPC and Microblaze

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---

 arch/microblaze/kernel/prom.c |   23 -----------------------
 arch/powerpc/kernel/prom.c    |   24 ------------------------
 drivers/of/fdt.c              |   26 ++++++++++++++++++++++++++
 include/linux/of_fdt.h        |    6 ++++++
 4 files changed, 32 insertions(+), 47 deletions(-)

diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c
index 7959495..189179a 100644
--- a/arch/microblaze/kernel/prom.c
+++ b/arch/microblaze/kernel/prom.c
@@ -42,9 +42,6 @@
 #include <asm/sections.h>
 #include <asm/pci-bridge.h>
 
-static int __initdata dt_root_addr_cells;
-static int __initdata dt_root_size_cells;
-
 typedef u32 cell_t;
 
 /* export that to outside world */
@@ -158,26 +155,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
 	return 1;
 }
 
-static int __init early_init_dt_scan_root(unsigned long node,
-				const char *uname, int depth, void *data)
-{
-	u32 *prop;
-
-	if (depth != 0)
-		return 0;
-
-	prop = of_get_flat_dt_prop(node, "#size-cells", NULL);
-	dt_root_size_cells = (prop == NULL) ? 1 : *prop;
-	pr_debug("dt_root_size_cells = %x\n", dt_root_size_cells);
-
-	prop = of_get_flat_dt_prop(node, "#address-cells", NULL);
-	dt_root_addr_cells = (prop == NULL) ? 2 : *prop;
-	pr_debug("dt_root_addr_cells = %x\n", dt_root_addr_cells);
-
-	/* break now */
-	return 1;
-}
-
 static u64 __init dt_mem_next_cell(int s, cell_t **cellp)
 {
 	cell_t *p = *cellp;
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 1ecd6c6..78f65a4 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -61,10 +61,6 @@
 #define DBG(fmt...)
 #endif
 
-
-static int __initdata dt_root_addr_cells;
-static int __initdata dt_root_size_cells;
-
 #ifdef CONFIG_PPC64
 int __initdata iommu_is_off;
 int __initdata iommu_force_on;
@@ -436,26 +432,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
 	return 1;
 }
 
-static int __init early_init_dt_scan_root(unsigned long node,
-					  const char *uname, int depth, void *data)
-{
-	u32 *prop;
-
-	if (depth != 0)
-		return 0;
-
-	prop = of_get_flat_dt_prop(node, "#size-cells", NULL);
-	dt_root_size_cells = (prop == NULL) ? 1 : *prop;
-	DBG("dt_root_size_cells = %x\n", dt_root_size_cells);
-
-	prop = of_get_flat_dt_prop(node, "#address-cells", NULL);
-	dt_root_addr_cells = (prop == NULL) ? 2 : *prop;
-	DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells);
-	
-	/* break now */
-	return 1;
-}
-
 static u64 __init dt_mem_next_cell(int s, cell_t **cellp)
 {
 	cell_t *p = *cellp;
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 6ad98e8..be200be 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -15,6 +15,9 @@
 #include <linux/of.h>
 #include <linux/of_fdt.h>
 
+int __initdata dt_root_addr_cells;
+int __initdata dt_root_size_cells;
+
 struct boot_param_header *initial_boot_params;
 
 char *find_flat_dt_string(u32 offset)
@@ -407,6 +410,29 @@ inline void early_init_dt_check_for_initrd(unsigned long node)
 #endif /* CONFIG_BLK_DEV_INITRD */
 
 /**
+ * early_init_dt_scan_root - fetch the top level address and size cells
+ */
+int __init early_init_dt_scan_root(unsigned long node, const char *uname,
+				   int depth, void *data)
+{
+	u32 *prop;
+
+	if (depth != 0)
+		return 0;
+
+	prop = of_get_flat_dt_prop(node, "#size-cells", NULL);
+	dt_root_size_cells = (prop == NULL) ? 1 : *prop;
+	pr_debug("dt_root_size_cells = %x\n", dt_root_size_cells);
+
+	prop = of_get_flat_dt_prop(node, "#address-cells", NULL);
+	dt_root_addr_cells = (prop == NULL) ? 2 : *prop;
+	pr_debug("dt_root_addr_cells = %x\n", dt_root_addr_cells);
+
+	/* break now */
+	return 1;
+}
+
+/**
  * unflatten_device_tree - create tree of device_nodes from flat blob
  *
  * unflattens the device-tree passed by the firmware, creating the
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
index ec2db82..828c3cd 100644
--- a/include/linux/of_fdt.h
+++ b/include/linux/of_fdt.h
@@ -58,6 +58,8 @@ struct boot_param_header {
 };
 
 /* TBD: Temporary export of fdt globals - remove when code fully merged */
+extern int __initdata dt_root_addr_cells;
+extern int __initdata dt_root_size_cells;
 extern struct boot_param_header *initial_boot_params;
 
 /* For scanning the flat device-tree at boot time */
@@ -71,6 +73,10 @@ extern int of_flat_dt_is_compatible(unsigned long node, const char *name);
 extern unsigned long of_get_flat_dt_root(void);
 extern void early_init_dt_check_for_initrd(unsigned long node);
 
+/* Early flat tree scan hooks */
+extern int early_init_dt_scan_root(unsigned long node, const char *uname,
+				   int depth, void *data);
+
 /* Other Prototypes */
 extern void finish_device_tree(void);
 extern void unflatten_device_tree(void);

^ permalink raw reply related


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