LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] DTS: Adding device tree source for the STx GP3 SSA MPC8555-based board.
From: Bradley Hughes @ 2010-07-21 16:52 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <7AD5FB58-D6EA-4AA6-870B-32E901F72589@kernel.crashing.org>

On Wed, Jul 21, 2010 at 10:24 AM, Kumar Gala <galak@kernel.crashing.org> wr=
ote:
>>
>> + =A0 =A0 soc8555@e0000000 {
>> + =A0 =A0 =A0 =A0 =A0 =A0 #address-cells =3D <1>;
>> + =A0 =A0 =A0 =A0 =A0 =A0 #size-cells =3D <1>;
>> + =A0 =A0 =A0 =A0 =A0 =A0 device_type =3D "soc";
>> + =A0 =A0 =A0 =A0 =A0 =A0 compatible =3D "simple-bus";
>> + =A0 =A0 =A0 =A0 =A0 =A0 ranges =3D <0x0 0xe0000000 0x100000>;
>> + =A0 =A0 =A0 =A0 =A0 =A0 bus-frequency =3D <0>;
>> +
>> + =A0 =A0 =A0 =A0 =A0 =A0 ecm-law@0 {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 compatible =3D "fsl,ecm-law";
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 reg =3D <0x0 0x1000>;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 fsl,num-laws =3D <8>;
>> + =A0 =A0 =A0 =A0 =A0 =A0 };
>> +
>> + =A0 =A0 =A0 =A0 =A0 =A0 ecm@1000 {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 compatible =3D "fsl,mpc8555-ec=
m", "fsl,ecm";
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 reg =3D <0x1000 0x1000>;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 interrupts =3D <17 2>;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 interrupt-parent =3D <&mpic>;
>> + =A0 =A0 =A0 =A0 =A0 =A0 };
>> +
>> + =A0 =A0 =A0 =A0 =A0 =A0 memory-controller@2000 {
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 compatible =3D "fsl,8555-memor=
y-controller";
>
> fsl,mpc8555?

Ah, yes -- it seems the dts I used for an example also has this
problem.  In drivers/edac/mpc85xx_edac.c, bindings still work for
fsl,85.. style notation, but a comment claims that this notation would
be deprecated at some point (2.6.29 or 2.6.30).  I have updated my
local copy and it works fine, should I send a new patch?  I could also
extend this change to the other DTS files affected (A quick search
found 14 instances of fsl,85.. style notation.)  Please let me know
what I should do.

>
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 reg =3D <0x2000 0x1000>;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 interrupt-parent =3D <&mpic>;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 interrupts =3D <18 2>;
>> + =A0 =A0 =A0 =A0 =A0 =A0 };
>> +
>> + =A0 =A0 =A0 =A0 =A0 =A0 L2: l2-cache-controller@20000 {
>
> fsl,mpc8555?
>
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 compatible =3D "fsl,8555-l2-ca=
che-controller";
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 reg =3D <0x20000 0x1000>;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 cache-line-size =3D <32>; // 3=
2 bytes
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 cache-size =3D <0x40000>; // L=
2, 256K
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 interrupt-parent =3D <&mpic>;
>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 interrupts =3D <16 2>;
>> + =A0 =A0 =A0 =A0 =A0 =A0 };
>> +
>
> - k
>
>
>
>

Best Regards,
Bradley

^ permalink raw reply

* Re: [PATCH] DTS: Adding device tree source for the STx GP3 SSA MPC8555-based board.
From: Kumar Gala @ 2010-07-21 14:24 UTC (permalink / raw)
  To: Bradley Hughes; +Cc: linuxppc-dev
In-Reply-To: <AANLkTinQkpBTtmVZYGM71wzREHGDzG6R3k7LbR66yX5c@mail.gmail.com>

> 
> +	soc8555@e0000000 {
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +		device_type = "soc";
> +		compatible = "simple-bus";
> +		ranges = <0x0 0xe0000000 0x100000>;
> +		bus-frequency = <0>;
> +
> +		ecm-law@0 {
> +			compatible = "fsl,ecm-law";
> +			reg = <0x0 0x1000>;
> +			fsl,num-laws = <8>;
> +		};
> +
> +		ecm@1000 {
> +			compatible = "fsl,mpc8555-ecm", "fsl,ecm";
> +			reg = <0x1000 0x1000>;
> +			interrupts = <17 2>;
> +			interrupt-parent = <&mpic>;
> +		};
> +
> +		memory-controller@2000 {
> +			compatible = "fsl,8555-memory-controller";

fsl,mpc8555?

> +			reg = <0x2000 0x1000>;
> +			interrupt-parent = <&mpic>;
> +			interrupts = <18 2>;
> +		};
> +
> +		L2: l2-cache-controller@20000 {

fsl,mpc8555?

> +			compatible = "fsl,8555-l2-cache-controller";
> +			reg = <0x20000 0x1000>;
> +			cache-line-size = <32>;	// 32 bytes
> +			cache-size = <0x40000>;	// L2, 256K
> +			interrupt-parent = <&mpic>;
> +			interrupts = <16 2>;
> +		};
> +

- k

^ permalink raw reply

* Re: [PATCH 92/92]Documentation/powerpc/booting-without-of.txt update web address.
From: Justin P. Mattock @ 2010-07-21  7:00 UTC (permalink / raw)
  To: Michael Neuling
  Cc: Jon Loeliger, trivial, linux-doc, linux-kernel, linuxppc-dev,
	David Gibson
In-Reply-To: <26726.1279692440@neuling.org>

On 07/20/2010 11:07 PM, Michael Neuling wrote:
>>> The patch below fixes a broken web address.
>>>
>>> Signed-off-by: Justin P. Mattock<justinmattock@gmail.com>
>>>
>>> ---
>>>   Documentation/powerpc/booting-without-of.txt |    2 +-
>>>   1 files changed, 1 insertions(+), 1 deletions(-)
>>>
>>> diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/p
> ow
>> erpc/booting-without-of.txt
>>> index 46d2210..7882a10 100644
>>> --- a/Documentation/powerpc/booting-without-of.txt
>>> +++ b/Documentation/powerpc/booting-without-of.txt
>>> @@ -1048,7 +1048,7 @@ IV - "dtc", the device tree compiler
>>>
>>>
>>>   dtc source code can be found at
>>> -<http://ozlabs.org/~dgibson/dtc/dtc.tar.gz>
>>> +<http://ozlabs.org/>
>>
>> I think this link should really be:
>> git clone git://www.jdl.com/software/dtc.git/
>
> Actually, maybe this instead?
>
> http://git.jdl.com/gitweb/?p=dtc.git
>
> Mikey
>


cool thanks.. I resent..

Justin P. Mattock

^ permalink raw reply

* Re: [PATCH 92/92]Documentation/powerpc/booting-without-of.txt update web address.
From: Michael Neuling @ 2010-07-21  6:07 UTC (permalink / raw)
  To: Justin P. Mattock, trivial, linux-doc, David Gibson, linuxppc-dev,
	linux-kernel, Jon Loeliger
In-Reply-To: <26080.1279691826@neuling.org>

> > The patch below fixes a broken web address.
> > 
> > Signed-off-by: Justin P. Mattock <justinmattock@gmail.com>
> > 
> > ---
> >  Documentation/powerpc/booting-without-of.txt |    2 +-
> >  1 files changed, 1 insertions(+), 1 deletions(-)
> > 
> > diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/p
ow
> erpc/booting-without-of.txt
> > index 46d2210..7882a10 100644
> > --- a/Documentation/powerpc/booting-without-of.txt
> > +++ b/Documentation/powerpc/booting-without-of.txt
> > @@ -1048,7 +1048,7 @@ IV - "dtc", the device tree compiler
> >  
> >  
> >  dtc source code can be found at
> > -<http://ozlabs.org/~dgibson/dtc/dtc.tar.gz>
> > +<http://ozlabs.org/>
> 
> I think this link should really be:
> git clone git://www.jdl.com/software/dtc.git/

Actually, maybe this instead?

http://git.jdl.com/gitweb/?p=dtc.git

Mikey

^ permalink raw reply

* Re: one more question about dts
From: Grant Likely @ 2010-07-21  2:59 UTC (permalink / raw)
  To: hacklu; +Cc: linuxppc-dev
In-Reply-To: <201007211037566748594@gmail.com>

T24gVHVlLCBKdWwgMjAsIDIwMTAgYXQgODozNyBQTSwgaGFja2x1IDxlbWJlZHdheS50ZXN0QGdt
YWlsLmNvbT4gd3JvdGU6Cj4gbXmgYm9hcmSgaXMgbXBjODI0NyxhbmSgaaB3cml0ZSBpdCdzIGR0
cyBieSCgoGltaXRhdGluZyBtcGM4MjcyJ3MgZHRzCj4KPiBob3cgY2FuIGkgc2V0IHRoZaBsb2Nh
bGJ1cyBhZGRyZXNzPwo+Cj4gbG9jYWxidXNAZjAwMTAxMDCgewo+IKCgoKCgoKCgoKCgoKCgoKBj
b21wYXRpYmxloD2gImZzbCxtcGM4MjcyLWxvY2FsYnVzIiwKPiCgoKCgoKCgoKCgoKCgoKCgoKCg
oKCgoKCgoKCgoCJmc2wscHEyLWxvY2FsYnVzIjsKPiCgoKCgoKCgoKCgoKCgoKCgI2FkZHJlc3Mt
Y2VsbHOgPaA8Mj47Cj4goKCgoKCgoKCgoKCgoKCgoCNzaXplLWNlbGxzoD2gPDE+Owo+IKCgoKCg
oKCgoKCgoKCgoKByZWegPaA8ZjAwMTAxMDCgNDA+Owo+IKCgoKCgoKCgoKCgoKCgoKByYW5nZXOg
PaA8Cj4goKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgMKAwoDcwMDAwMDAwoDEwMDAw
MDCgICNteSBmbGFzaDEKPiCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKAxoDCgNzEw
MDAwMDCgMTAwMDAwMKAgI215IGZsYXNoMgo+IKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg
oKCgoDIgP6AgPz8/Pz8/P6CgoCA/Pz8/Pz8/oKAgI2hvdyB0byBzZXQgaXQKPiBmb3IgYm9hcmQt
Y29udHJvbD8KPiCgM6AgP6AgPz8/P6CgoKCgoKAgPz8/P6CgoKCgoKCgIyBob3cgdG8gc2V0IGl0
IGZvcgo+IHBjaV9waWOgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoD47CgpUaGVzZSB2YWx1ZXMgcmVm
bGVjdCB0aGUgYmFzZSBhZGRyZXNzIGFuZCB0cmFuc2xhdGlvbiByYW5nZSBvZiBlYWNoCmNoaXAg
c2VsZWN0LiAgSG93IGFyZSB5b3VyIGhhcmR3YXJlIGNoaXBzIHNlbGVjdHMgY29uZmlndXJlZC4K
CklmIEkgYXNzdW1lIHRoYXQgY3MyIGlzIGNvbmZpZ3VyZWQgZm9yIDB4YzEwMDAwMDAgdG8gMHhj
MTAwZmZmZiwgYW5kCmNzMyBpcyBjb25maWd1cmVkIGZvciAweGMyMDAwMDAwIHRvIDB4YzIwM2Zm
ZmYsIHRoZW4geW91ciByYW5nZXMKcHJvcGVydHkgd291bGQgYmU6CgogICAgICAgICAgICAgICAg
cmFuZ2VzID0gPCAwIDAgNzAwMDAwMDAgMTAwMDAwMCAgI215IGZsYXNoMQogICAgICAgICAgICAg
ICAgICAgICAgICAgICAxIDAgNzEwMDAwMDAgMTAwMDAwMCAgI215IGZsYXNoMgogICAgICAgICAg
ICAgICAgICAgICAgICAgICAyIDAgYzEwMDAwMDAgMTAwMDAKICAgICAgICAgICAgICAgICAgICAg
ICAgICAgMyAwIGMyMDAwMDAwIDQwMDAwID47CgoKPgo+IC4uLi4KPiCgYm9hcmQtY29udHJvbEAy
LDCgewo+IKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoHJlZ6A9oDwxoDCgMjA+OwoKSWYgdGhpcyBp
cyBhdHRhY2hlZCB0byBjaGlwc2VsZWN0ICMyLCB0aGVuIHRoaXMgc2hvdWxkIGJlICJyZWcgPSA8
MiAwIDIwPjsiCgo+IKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoGNvbXBhdGlibGWgPaAiZnNsLG1w
YzgyNzJhZHMtYmNzciI7Cj4goKCgoKCgoKCgoKCgoKCgoH07Cj4goKCgoKCgoKCgoKCgoKCgoFBD
SV9QSUM6oGludGVycnVwdC1jb250cm9sbGVyQDMsMKB7Cj4goKCgoKCgoKCgoKCgoKCgoKCgoKCg
oKCgY29tcGF0aWJsZaA9oCJmc2wsbXBjODI3MmFkcy1wY2ktcGljIiwKPiCgoKCgoKCgoKCgoKCg
oKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgImZzbCxwcTJhZHMtcGNpLXBpYyI7Cj4goKCgoKCgoKCg
oKCgoKCgoKCgoKCgoKCgI2ludGVycnVwdC1jZWxsc6A9oDwxPjsKPiCgoKCgoKCgoKCgoKCgoKCg
oKCgoKCgoKBpbnRlcnJ1cHQtY29udHJvbGxlcjsKPiCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKBy
ZWegPaA8M6AwoDg+Owo+IKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoGludGVycnVwdC1wYXJlbnSg
PaA8JlBJQz47Cj4goKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgaW50ZXJydXB0c6A9oDwxNKA4PjsK
PiCgoKCgoKCgoKCgoKCgoKCgfTsKPgo+IHRoYW5rcyBmb3IgYW5zd2VyaW5nfgo+IDIwMTAtMDct
MjEKPiBfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwo+IGhhY2tsdQoKCgotLSAKR3Jh
bnQgTGlrZWx5LCBCLlNjLiwgUC5FbmcuClNlY3JldCBMYWIgVGVjaG5vbG9naWVzIEx0ZC4K

^ permalink raw reply

* one more question about dts
From: hacklu @ 2010-07-21  2:37 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-dev

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

my board is mpc8247,and i write it's dts by   imitating mpc8272's dts 

how can i set the localbus address?

localbus@f0010100 {
                compatible = "fsl,mpc8272-localbus",
                             "fsl,pq2-localbus";
                #address-cells = <2>;
                #size-cells = <1>;
                reg = <f0010100 40>;
                ranges = <
                                 0 0 70000000 1000000  #my flash1
                                 1 0 71000000 1000000  #my flash2
                                 2 ?  ???????    ???????   #how to set it for board-control?
 3  ?  ????        ????        # how to set it for pci_pic                       >;

....
 board-control@2,0 {
                        reg = <1 0 20>;
                        compatible = "fsl,mpc8272ads-bcsr";
                };
                PCI_PIC: interrupt-controller@3,0 {
                        compatible = "fsl,mpc8272ads-pci-pic",
                                     "fsl,pq2ads-pci-pic";
                        #interrupt-cells = <1>;
                        interrupt-controller;
                        reg = <3 0 8>;
                        interrupt-parent = <&PIC>;
                        interrupts = <14 8>;
                };

thanks for answering~
2010-07-21 



hacklu 

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

^ permalink raw reply

* Re: [PATCH] math-emu: correct test for downshifting fraction in _FP_FROM_INT()
From: David Miller @ 2010-07-21  1:45 UTC (permalink / raw)
  To: mikpe
  Cc: linux-s390, linux-sh, linux-kernel, linuxppc-dev, linux-alpha,
	sparclinux
In-Reply-To: <19524.51858.992299.119315@pilspetsen.it.uu.se>

From: Mikael Pettersson <mikpe@it.uu.se>
Date: Mon, 19 Jul 2010 23:58:42 +0200

> The kernel's math-emu code contains a macro _FP_FROM_INT() which is
> used to convert an integer to a raw normalized floating-point value.
> It does this basically in three steps:
 ...
> The fix is simple: the exponent comparison used to determine if the
> fraction should be downshifted must be "<=" not "<".
> 
> I'm sending a kernel module to test this as a reply to this message.
> There are also SPARC user-space test cases in the GCC bug entry.
> 
> Signed-off-by: Mikael Pettersson <mikpe@it.uu.se>

Applied and I'll make sure this gets into -stable too.

Thanks!

^ permalink raw reply

* [PATCH] DTS: Adding device tree source for the STx GP3 SSA MPC8555-based board.
From: Bradley Hughes @ 2010-07-20 22:39 UTC (permalink / raw)
  To: linuxppc-dev

DTS: Adding device tree source for the STx GP3 SSA MPC8555-based board.

---
 arch/powerpc/boot/dts/stxssa.dts |  380 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 380 insertions(+), 0 deletions(-)
 create mode 100644 arch/powerpc/boot/dts/stxssa.dts

diff --git a/arch/powerpc/boot/dts/stxssa.dts b/arch/powerpc/boot/dts/stxssa.dts
new file mode 100644
index 0000000..94d12d7
--- /dev/null
+++ b/arch/powerpc/boot/dts/stxssa.dts
@@ -0,0 +1,380 @@
+/*
+ * MPC8555-based STx GP3 Device Tree Source
+ *
+ * Copyright 2006, 2008 Freescale Semiconductor Inc.
+ *
+ * Copyright 2010 Silicon Turnkey Express LLC.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/dts-v1/;
+
+/ {
+	model = "stx,gp3";
+        compatible = "stx,gp3-8560", "stx,gp3";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	aliases {
+		ethernet0 = &enet0;
+		ethernet1 = &enet1;
+		serial0 = &serial0;
+		serial1 = &serial1;
+		pci0 = &pci0;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8555@0 {
+			device_type = "cpu";
+			reg = <0x0>;
+			d-cache-line-size = <32>;	// 32 bytes
+			i-cache-line-size = <32>;	// 32 bytes
+			d-cache-size = <0x8000>;		// L1, 32K
+			i-cache-size = <0x8000>;		// L1, 32K
+			timebase-frequency = <0>;	//  33 MHz, from uboot
+			bus-frequency = <0>;	// 166 MHz
+			clock-frequency = <0>;	// 825 MHz, from uboot
+			next-level-cache = <&L2>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x10000000>;
+	};
+
+	soc8555@e0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		device_type = "soc";
+		compatible = "simple-bus";
+		ranges = <0x0 0xe0000000 0x100000>;
+		bus-frequency = <0>;
+
+		ecm-law@0 {
+			compatible = "fsl,ecm-law";
+			reg = <0x0 0x1000>;
+			fsl,num-laws = <8>;
+		};
+
+		ecm@1000 {
+			compatible = "fsl,mpc8555-ecm", "fsl,ecm";
+			reg = <0x1000 0x1000>;
+			interrupts = <17 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		memory-controller@2000 {
+			compatible = "fsl,8555-memory-controller";
+			reg = <0x2000 0x1000>;
+			interrupt-parent = <&mpic>;
+			interrupts = <18 2>;
+		};
+
+		L2: l2-cache-controller@20000 {
+			compatible = "fsl,8555-l2-cache-controller";
+			reg = <0x20000 0x1000>;
+			cache-line-size = <32>;	// 32 bytes
+			cache-size = <0x40000>;	// L2, 256K
+			interrupt-parent = <&mpic>;
+			interrupts = <16 2>;
+		};
+
+		i2c@3000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			compatible = "fsl-i2c";
+			reg = <0x3000 0x100>;
+			interrupts = <43 2>;
+			interrupt-parent = <&mpic>;
+			dfsrr;
+		};
+
+		dma@21300 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,mpc8555-dma", "fsl,eloplus-dma";
+			reg = <0x21300 0x4>;
+			ranges = <0x0 0x21100 0x200>;
+			cell-index = <0>;
+			dma-channel@0 {
+				compatible = "fsl,mpc8555-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x0 0x80>;
+				cell-index = <0>;
+				interrupt-parent = <&mpic>;
+				interrupts = <20 2>;
+			};
+			dma-channel@80 {
+				compatible = "fsl,mpc8555-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x80 0x80>;
+				cell-index = <1>;
+				interrupt-parent = <&mpic>;
+				interrupts = <21 2>;
+			};
+			dma-channel@100 {
+				compatible = "fsl,mpc8555-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x100 0x80>;
+				cell-index = <2>;
+				interrupt-parent = <&mpic>;
+				interrupts = <22 2>;
+			};
+			dma-channel@180 {
+				compatible = "fsl,mpc8555-dma-channel",
+						"fsl,eloplus-dma-channel";
+				reg = <0x180 0x80>;
+				cell-index = <3>;
+				interrupt-parent = <&mpic>;
+				interrupts = <23 2>;
+			};
+		};
+
+		enet0: ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <0>;
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <0x24000 0x1000>;
+			ranges = <0x0 0x24000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <29 2 30 2 34 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi0>;
+			phy-handle = <&phy0>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-mdio";
+				reg = <0x520 0x20>;
+
+				phy0: ethernet-phy@2 {
+					interrupt-parent = <&mpic>;
+					interrupts = <5 1>;
+					reg = <0x2>;
+					device_type = "ethernet-phy";
+				};
+				phy1: ethernet-phy@4 {
+					interrupt-parent = <&mpic>;
+					interrupts = <5 1>;
+					reg = <0x4>;
+					device_type = "ethernet-phy";
+				};
+				tbi0: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		enet1: ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cell-index = <1>;
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <0x25000 0x1000>;
+			ranges = <0x0 0x25000 0x1000>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <35 2 36 2 40 2>;
+			interrupt-parent = <&mpic>;
+			tbi-handle = <&tbi1>;
+			phy-handle = <&phy1>;
+
+			mdio@520 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,gianfar-tbi";
+				reg = <0x520 0x20>;
+
+				tbi1: tbi-phy@11 {
+					reg = <0x11>;
+					device_type = "tbi-phy";
+				};
+			};
+		};
+
+		serial0: serial@4500 {
+			cell-index = <0>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4500 0x100>; 	// reg base, size
+			clock-frequency = <0>; 	// should we fill in in uboot?
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		serial1: serial@4600 {
+			cell-index = <1>;
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <0x4600 0x100>;	// reg base, size
+			clock-frequency = <0>; 	// should we fill in in uboot?
+			interrupts = <42 2>;
+			interrupt-parent = <&mpic>;
+		};
+
+		crypto@30000 {
+			compatible = "fsl,sec2.0";
+			reg = <0x30000 0x10000>;
+			interrupts = <45 2>;
+			interrupt-parent = <&mpic>;
+			fsl,num-channels = <4>;
+			fsl,channel-fifo-len = <24>;
+			fsl,exec-units-mask = <0x7e>;
+			fsl,descriptor-types-mask = <0x01010ebf>;
+		};
+
+		mpic: pic@40000 {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <0x40000 0x40000>;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+		};
+
+		cpm@919c0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,mpc8555-cpm", "fsl,cpm2";
+			reg = <0x919c0 0x30>;
+			ranges;
+
+			muram@80000 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges = <0x0 0x80000 0x10000>;
+
+				data@0 {
+					compatible = "fsl,cpm-muram-data";
+					reg = <0x0 0x2000 0x9000 0x1000>;
+				};
+			};
+
+			brg@919f0 {
+				compatible = "fsl,mpc8555-brg",
+				             "fsl,cpm2-brg",
+				             "fsl,cpm-brg";
+				reg = <0x919f0 0x10 0x915f0 0x10>;
+			};
+
+			cpmpic: pic@90c00 {
+				interrupt-controller;
+				#address-cells = <0>;
+				#interrupt-cells = <2>;
+				interrupts = <46 2>;
+				interrupt-parent = <&mpic>;
+				reg = <0x90c00 0x80>;
+				compatible = "fsl,mpc8555-cpm-pic", "fsl,cpm2-pic";
+			};
+		};
+	};
+
+	pci0: pci@e0008000 {
+		interrupt-map-mask = <0x1f800 0x0 0x0 0x7>;
+		interrupt-map = <
+
+			/* IDSEL 0x10 */
+			0x8000 0x0 0x0 0x1 &mpic 0x0 0x1
+			0x8000 0x0 0x0 0x2 &mpic 0x1 0x1
+			0x8000 0x0 0x0 0x3 &mpic 0x2 0x1
+			0x8000 0x0 0x0 0x4 &mpic 0x3 0x1
+
+			/* IDSEL 0x11 */
+			0x8800 0x0 0x0 0x1 &mpic 0x0 0x1
+			0x8800 0x0 0x0 0x2 &mpic 0x1 0x1
+			0x8800 0x0 0x0 0x3 &mpic 0x2 0x1
+			0x8800 0x0 0x0 0x4 &mpic 0x3 0x1
+
+			/* IDSEL 0x12 (Slot 1) */
+			0x9000 0x0 0x0 0x1 &mpic 0x0 0x1
+			0x9000 0x0 0x0 0x2 &mpic 0x1 0x1
+			0x9000 0x0 0x0 0x3 &mpic 0x2 0x1
+			0x9000 0x0 0x0 0x4 &mpic 0x3 0x1
+
+			/* IDSEL 0x13 (Slot 2) */
+			0x9800 0x0 0x0 0x1 &mpic 0x1 0x1
+			0x9800 0x0 0x0 0x2 &mpic 0x2 0x1
+			0x9800 0x0 0x0 0x3 &mpic 0x3 0x1
+			0x9800 0x0 0x0 0x4 &mpic 0x0 0x1
+
+			/* IDSEL 0x14 (Slot 3) */
+			0xa000 0x0 0x0 0x1 &mpic 0x2 0x1
+			0xa000 0x0 0x0 0x2 &mpic 0x3 0x1
+			0xa000 0x0 0x0 0x3 &mpic 0x0 0x1
+			0xa000 0x0 0x0 0x4 &mpic 0x1 0x1
+
+			/* IDSEL 0x15 (Slot 4) */
+			0xa800 0x0 0x0 0x1 &mpic 0x3 0x1
+			0xa800 0x0 0x0 0x2 &mpic 0x0 0x1
+			0xa800 0x0 0x0 0x3 &mpic 0x1 0x1
+			0xa800 0x0 0x0 0x4 &mpic 0x2 0x1
+
+			/* Bus 1 (Tundra Bridge) */
+			/* IDSEL 0x12 (ISA bridge) */
+			0x19000 0x0 0x0 0x1 &mpic 0x0 0x1
+			0x19000 0x0 0x0 0x2 &mpic 0x1 0x1
+			0x19000 0x0 0x0 0x3 &mpic 0x2 0x1
+			0x19000 0x0 0x0 0x4 &mpic 0x3 0x1>;
+		interrupt-parent = <&mpic>;
+		interrupts = <24 2>;
+		bus-range = <0 0>;
+		ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
+			  0x1000000 0x0 0x0 0xe2000000 0x0 0x100000>;
+		clock-frequency = <66666666>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0xe0008000 0x1000>;
+		compatible = "fsl,mpc8540-pci";
+		device_type = "pci";
+
+		i8259@19000 {
+			interrupt-controller;
+			device_type = "interrupt-controller";
+			reg = <0x19000 0x0 0x0 0x0 0x1>;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			compatible = "chrp,iic";
+			interrupts = <1>;
+			interrupt-parent = <&pci0>;
+		};
+	};
+
+	pci1: pci@e0009000 {
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+
+			/* IDSEL 0x15 */
+			0xa800 0x0 0x0 0x1 &mpic 0xb 0x1
+			0xa800 0x0 0x0 0x2 &mpic 0xb 0x1
+			0xa800 0x0 0x0 0x3 &mpic 0xb 0x1
+			0xa800 0x0 0x0 0x4 &mpic 0xb 0x1>;
+		interrupt-parent = <&mpic>;
+		interrupts = <25 2>;
+		bus-range = <0 0>;
+		ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
+			  0x1000000 0x0 0x0 0xe3000000 0x0 0x100000>;
+		clock-frequency = <66666666>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0xe0009000 0x1000>;
+		compatible = "fsl,mpc8540-pci";
+		device_type = "pci";
+	};
+};
-- 
1.7.0.4

^ permalink raw reply related

* [PATCH v2 2/7] Fix case where phys_addr_t != unsigned long when reading proc entries
From: Matthew McClintock @ 2010-07-20 20:14 UTC (permalink / raw)
  To: kexec; +Cc: Matthew McClintock, linuxppc-dev
In-Reply-To: <1279656900-27458-1-git-send-email-msm@freescale.com>

On some actitectures the physical memory can be 64 bits, therefore
the code that reads proc entries needs to take into account it could
read either a 32 bit or 64bit value for the physical addresses.

Signed-off-by: Matthew McClintock <msm@freescale.com>
---
 kexec/arch/ppc/kexec-elf-ppc.c |    1 -
 kexec/arch/ppc/kexec-ppc.c     |  210 ++++++++++++++++++++++++++++------------
 kexec/arch/ppc/kexec-ppc.h     |    1 +
 3 files changed, 148 insertions(+), 64 deletions(-)

diff --git a/kexec/arch/ppc/kexec-elf-ppc.c b/kexec/arch/ppc/kexec-elf-ppc.c
index d155bde..ab2d343 100644
--- a/kexec/arch/ppc/kexec-elf-ppc.c
+++ b/kexec/arch/ppc/kexec-elf-ppc.c
@@ -32,7 +32,6 @@
 
 static const int probe_debug = 0;
 
-unsigned long long initrd_base, initrd_size;
 unsigned char reuse_initrd;
 const char *ramdisk;
 int create_flatten_tree(struct kexec_info *, unsigned char **, unsigned long *,
diff --git a/kexec/arch/ppc/kexec-ppc.c b/kexec/arch/ppc/kexec-ppc.c
index c073f56..d7afad6 100644
--- a/kexec/arch/ppc/kexec-ppc.c
+++ b/kexec/arch/ppc/kexec-ppc.c
@@ -28,6 +28,8 @@
 
 uint64_t rmo_top;
 unsigned long long crash_base, crash_size;
+unsigned long long initrd_base, initrd_size;
+unsigned long long devicetree_base, devicetree_size;
 unsigned int rtas_base, rtas_size;
 int max_memory_ranges;
 
@@ -320,9 +322,7 @@ static int get_devtree_details(unsigned long kexec_flags)
 	DIR *dir, *cdir;
 	FILE *file;
 	struct dirent *dentry;
-	struct stat fstat;
 	int n, i = 0;
-	unsigned long tmp_long;
 
 	if ((dir = opendir(device_tree)) == NULL) {
 		perror(device_tree);
@@ -352,12 +352,18 @@ static int get_devtree_details(unsigned long kexec_flags)
 					perror(fname);
 					goto error_opencdir;
 				}
-				if (fread(&tmp_long, sizeof(unsigned long), 1, file)
-						!= 1) {
+				if ((n = fread(buf, 1, MAXBYTES, file)) < 0) {
 					perror(fname);
 					goto error_openfile;
 				}
-				kernel_end = tmp_long;
+				if (n == 4) {
+					kernel_end = ((uint32_t *)buf)[0];
+				} else if (n == 8) {
+					kernel_end = ((uint64_t *)buf)[0];
+				} else {
+					fprintf(stderr, "%s node has invalid size: %d\n", fname, n);
+					goto error_openfile;
+				}
 				fclose(file);
 
 				/* Add kernel memory to exclude_range */
@@ -375,12 +381,18 @@ static int get_devtree_details(unsigned long kexec_flags)
 					perror(fname);
 					goto error_opencdir;
 				}
-				if (fread(&tmp_long, sizeof(unsigned long), 1,
-						file) != 1) {
+				if ((n = fread(buf, 1, MAXBYTES, file)) < 0) {
 					perror(fname);
 					goto error_openfile;
 				}
-				crash_base = tmp_long;
+				if (n == 4) {
+					crash_base = ((uint32_t *)buf)[0];
+				} else if (n == 8) {
+					crash_base = ((uint64_t *)buf)[0];
+				} else {
+					fprintf(stderr, "%s node has invalid size: %d\n", fname, n);
+					goto error_openfile;
+				}
 				fclose(file);
 
 				memset(fname, 0, sizeof(fname));
@@ -392,12 +404,19 @@ static int get_devtree_details(unsigned long kexec_flags)
 					perror(fname);
 					goto error_opencdir;
 				}
-				if (fread(&tmp_long, sizeof(unsigned long), 1,
-						file) != 1) {
+				if ((n = fread(buf, 1, MAXBYTES, file)) < 0) {
 					perror(fname);
 					goto error_openfile;
 				}
-				crash_size = tmp_long;
+				if (n == 4) {
+					crash_size = ((uint32_t *)buf)[0];
+				} else if (n == 8) {
+					crash_size = ((uint64_t *)buf)[0];
+				} else {
+					fprintf(stderr, "%s node has invalid size: %d\n", fname, n);
+					goto error_openfile;
+				}
+				fclose(file);
 
 				if (crash_base > mem_min)
 					mem_min = crash_base;
@@ -408,6 +427,123 @@ static int get_devtree_details(unsigned long kexec_flags)
 				reserve(KDUMP_BACKUP_LIMIT,
 						crash_base-KDUMP_BACKUP_LIMIT);
 			}
+			/* reserve the initrd_start and end locations. */
+			memset(fname, 0, sizeof(fname));
+			strcpy(fname, device_tree);
+			strcat(fname, dentry->d_name);
+			strcat(fname, "/linux,initrd-start");
+			file = fopen(fname, "r");
+			if (!file) {
+				errno = 0;
+				initrd_start = 0;
+			} else {
+				if ((n = fread(buf, 1, MAXBYTES, file)) < 0) {
+					perror(fname);
+					goto error_openfile;
+				}
+				if (n == 4) {
+					initrd_start = ((uint32_t *)buf)[0];
+				} else if (n == 8) {
+					initrd_start = ((uint64_t *)buf)[0];
+				} else {
+					fprintf(stderr, "%s node has invalid size: %d\n", fname, n);
+					goto error_openfile;
+				}
+				fclose(file);
+			}
+
+			memset(fname, 0, sizeof(fname));
+			strcpy(fname, device_tree);
+			strcat(fname, dentry->d_name);
+			strcat(fname, "/linux,initrd-end");
+			file = fopen(fname, "r");
+			if (!file) {
+				errno = 0;
+				initrd_end = 0;
+			} else {
+				if ((n = fread(buf, 1, MAXBYTES, file)) < 0) {
+					perror(fname);
+					goto error_openfile;
+				}
+				if (n == 4) {
+					initrd_end = ((uint32_t *)buf)[0];
+				} else if (n == 8) {
+					initrd_end = ((uint64_t *)buf)[0];
+				} else {
+					fprintf(stderr, "%s node has invalid size: %d\n", fname, n);
+					goto error_openfile;
+				}
+				fclose(file);
+			}
+
+			if ((initrd_end - initrd_start) != 0 )
+			{
+				initrd_base = initrd_start;
+				initrd_size = initrd_end - initrd_start + 1;
+			}
+
+			if (reuse_initrd) {
+				/* Add initrd address to exclude_range */
+				exclude_range[i].start = initrd_start;
+				exclude_range[i].end = initrd_end;
+				i++;
+				if (i >= max_memory_ranges)
+					realloc_memory_ranges();
+			}
+
+			memset(fname, 0, sizeof(fname));
+			strcpy(fname, device_tree);
+			strcat(fname, dentry->d_name);
+			strcat(fname, "/linux,devicetree-start");
+			file = fopen(fname, "r");
+			if (!file) {
+				errno = 0;
+				devicetree_base = 0;
+			} else {
+				if ((n = fread(buf, 1, MAXBYTES, file)) < 0) {
+					perror(fname);
+					goto error_openfile;
+				}
+				if (n == 4) {
+					devicetree_base = ((uint32_t *)buf)[0];
+				} else if (n == 8) {
+					devicetree_base = ((uint64_t *)buf)[0];
+				} else {
+					fprintf(stderr, "%s node has invalid size: %d\n", fname, n);
+					goto error_openfile;
+				}
+				fclose(file);
+			}
+
+			memset(fname, 0, sizeof(fname));
+			strcpy(fname, device_tree);
+			strcat(fname, dentry->d_name);
+			strcat(fname, "/linux,devicetree-end");
+			file = fopen(fname, "r");
+			if (!file) {
+				errno = 0;
+				devicetree_size = 0;
+			} else {
+				if ((n = fread(buf, 1, MAXBYTES, file)) < 0) {
+					perror(fname);
+					goto error_openfile;
+				}
+				if (n == 4) {
+					devicetree_size = ((uint32_t *)buf)[0];
+				} else if (n == 8) {
+					devicetree_size = ((uint64_t *)buf)[0];
+				} else {
+					fprintf(stderr, "%s node has invalid size: %d\n", fname, n);
+					goto error_openfile;
+				}
+				fclose(file);
+			}
+
+			/* Fixup device tree size */
+			if (devicetree_size != 0)
+				devicetree_size -= devicetree_base;
+
+			/* HTAB */
 			memset(fname, 0, sizeof(fname));
 			strcpy(fname, device_tree);
 			strcat(fname, dentry->d_name);
@@ -449,59 +585,7 @@ static int get_devtree_details(unsigned long kexec_flags)
 			if (i >= max_memory_ranges)
 				realloc_memory_ranges();
 
-			/* reserve the initrd_start and end locations. */
-			if (reuse_initrd) {
-				memset(fname, 0, sizeof(fname));
-				strcpy(fname, device_tree);
-				strcat(fname, dentry->d_name);
-				strcat(fname, "/linux,initrd-start");
-				file = fopen(fname, "r");
-				if (!file) {
-					perror(fname);
-					goto error_opencdir;
-				}
-				/* check for 4 and 8 byte initrd offset sizes */
-				if (stat(fname, &fstat) != 0) {
-					perror(fname);
-					goto error_openfile;
-				}
-				if (fread(&initrd_start, fstat.st_size, 1, file)
-						!= 1) {
-					perror(fname);
-					goto error_openfile;
-				}
-				fclose(file);
-
-				memset(fname, 0, sizeof(fname));
-				strcpy(fname, device_tree);
-				strcat(fname, dentry->d_name);
-				strcat(fname, "/linux,initrd-end");
-				file = fopen(fname, "r");
-				if (!file) {
-					perror(fname);
-					goto error_opencdir;
-				}
-				/* check for 4 and 8 byte initrd offset sizes */
-				if (stat(fname, &fstat) != 0) {
-					perror(fname);
-					goto error_openfile;
-				}
-				if (fread(&initrd_end, fstat.st_size, 1, file)
-						!= 1) {
-					perror(fname);
-					goto error_openfile;
-				}
-				fclose(file);
-
-				/* Add initrd address to exclude_range */
-				exclude_range[i].start = initrd_start;
-				exclude_range[i].end = initrd_end;
-				i++;
-				if (i >= max_memory_ranges)
-					realloc_memory_ranges();
-			}
 		} /* chosen */
-
 		if (strncmp(dentry->d_name, "rtas", 4) == 0) {
 			strcat(fname, "/linux,rtas-base");
 			if ((file = fopen(fname, "r")) == NULL) {
diff --git a/kexec/arch/ppc/kexec-ppc.h b/kexec/arch/ppc/kexec-ppc.h
index fc0471f..aefdc6f 100644
--- a/kexec/arch/ppc/kexec-ppc.h
+++ b/kexec/arch/ppc/kexec-ppc.h
@@ -65,6 +65,7 @@ typedef struct mem_rgns {
 extern mem_rgns_t usablemem_rgns;
 extern int max_memory_ranges;
 extern unsigned long long initrd_base, initrd_size;
+extern unsigned long long devicetree_base, devicetree_size;
 extern unsigned char reuse_initrd;
 #define COMMAND_LINE_SIZE	512 /* from kernel */
 /*fs2dt*/
-- 
1.6.0.6

^ permalink raw reply related

* [PATCH v2 1/7] Restore kexec uImage-ppc to working state
From: Matthew McClintock @ 2010-07-20 20:14 UTC (permalink / raw)
  To: kexec; +Cc: Matthew McClintock, linuxppc-dev

Booting with uImage-ppc was broken by previous work, this
patch should restore it to working order

Signed-off-by: Matthew McClintock <msm@freescale.com>
---
 kexec/arch/ppc/kexec-ppc.c         |   68 ++++++++++++++++++++++-------------
 kexec/arch/ppc/kexec-uImage-ppc.c  |    5 +--
 purgatory/arch/ppc/purgatory-ppc.c |    5 +++
 3 files changed, 49 insertions(+), 29 deletions(-)

diff --git a/kexec/arch/ppc/kexec-ppc.c b/kexec/arch/ppc/kexec-ppc.c
index 55cadd6..c073f56 100644
--- a/kexec/arch/ppc/kexec-ppc.c
+++ b/kexec/arch/ppc/kexec-ppc.c
@@ -261,11 +261,28 @@ static int get_base_ranges(void)
 					break;
 				}
 			}
-			base_memory_range[local_memory_ranges].start =
-				((uint32_t *)buf)[0];
-			base_memory_range[local_memory_ranges].end  =
-				base_memory_range[local_memory_ranges].start +
-				((uint32_t *)buf)[1];
+
+			if (n == 8)
+			{
+				base_memory_range[local_memory_ranges].start =
+					((uint32_t *)buf)[0];
+				base_memory_range[local_memory_ranges].end  =
+					base_memory_range[local_memory_ranges].start +
+					((uint32_t *)buf)[1];
+			}
+			else if (n == 16)
+			{
+				base_memory_range[local_memory_ranges].start =
+                                        ((uint64_t *)buf)[0];
+                                base_memory_range[local_memory_ranges].end  =
+                                        base_memory_range[local_memory_ranges].start +
+                                        ((uint64_t *)buf)[1];
+			}
+			else
+			{
+				fprintf(stderr, "Mem node has invalid size: %d\n", n);
+				return -1;
+			}
 			base_memory_range[local_memory_ranges].type = RANGE_RAM;
 			local_memory_ranges++;
 			dbgprintf("%016llx-%016llx : %x\n",
@@ -327,27 +344,28 @@ static int get_devtree_details(unsigned long kexec_flags)
 		}
 
 		if (strncmp(dentry->d_name, "chosen", 6) == 0) {
-			strcat(fname, "/linux,kernel-end");
-			file = fopen(fname, "r");
-			if (!file) {
-				perror(fname);
-				goto error_opencdir;
-			}
-			if (fread(&tmp_long, sizeof(unsigned long), 1, file)
-					!= 1) {
-				perror(fname);
-				goto error_openfile;
-			}
-			kernel_end = tmp_long;
-			fclose(file);
-
-			/* Add kernel memory to exclude_range */
-			exclude_range[i].start = 0x0UL;
-			exclude_range[i].end = kernel_end;
-			i++;
-			if (i >= max_memory_ranges)
-				realloc_memory_ranges();
+			/* only reserve kernel region if we are doing a crash kernel */
 			if (kexec_flags & KEXEC_ON_CRASH) {
+				strcat(fname, "/linux,kernel-end");
+				file = fopen(fname, "r");
+				if (!file) {
+					perror(fname);
+					goto error_opencdir;
+				}
+				if (fread(&tmp_long, sizeof(unsigned long), 1, file)
+						!= 1) {
+					perror(fname);
+					goto error_openfile;
+				}
+				kernel_end = tmp_long;
+				fclose(file);
+
+				/* Add kernel memory to exclude_range */
+				exclude_range[i].start = 0x0UL;
+				exclude_range[i].end = kernel_end;
+				i++;
+				if (i >= max_memory_ranges)
+					realloc_memory_ranges();
 				memset(fname, 0, sizeof(fname));
 				strcpy(fname, device_tree);
 				strcat(fname, dentry->d_name);
diff --git a/kexec/arch/ppc/kexec-uImage-ppc.c b/kexec/arch/ppc/kexec-uImage-ppc.c
index 45cde2f..4a8d28d 100644
--- a/kexec/arch/ppc/kexec-uImage-ppc.c
+++ b/kexec/arch/ppc/kexec-uImage-ppc.c
@@ -133,13 +133,10 @@ static int ppc_load_bare_bits(int argc, char **argv, const char *buf,
 	addr = dtb_addr;
 	elf_rel_set_symbol(&info->rhdr, "dt_offset", &addr, sizeof(addr));
 
-	addr = rmo_top;
-	elf_rel_set_symbol(&info->rhdr, "mem_size", &addr, sizeof(addr));
-
 #define PUL_STACK_SIZE  (16 * 1024)
 	addr = locate_hole(info, PUL_STACK_SIZE, 0, 0, -1, 1);
 	addr += PUL_STACK_SIZE;
-	elf_rel_set_symbol(&info->rhdr, "pul_stack", &addr, sizeof(addr));
+	elf_rel_set_symbol(&info->rhdr, "stack", &addr, sizeof(addr));
 	/* No allocation past here in order not to overwrite the stack */
 #undef PUL_STACK_SIZE
 
diff --git a/purgatory/arch/ppc/purgatory-ppc.c b/purgatory/arch/ppc/purgatory-ppc.c
index 3d7d484..349e750 100644
--- a/purgatory/arch/ppc/purgatory-ppc.c
+++ b/purgatory/arch/ppc/purgatory-ppc.c
@@ -39,3 +39,8 @@ void post_verification_setup_arch(void)
 	if (panic_kernel)
 		crashdump_backup_memory();
 }
+
+void crashdump_backup_memory(void)
+{
+	return;
+}
-- 
1.6.0.6

^ permalink raw reply related

* [PATCH v2 5/7] Add support for ramdisk on ppc32 for uImage-ppc and Elf-ppc
From: Matthew McClintock @ 2010-07-20 20:14 UTC (permalink / raw)
  To: kexec; +Cc: Matthew McClintock, linuxppc-dev
In-Reply-To: <1279656900-27458-4-git-send-email-msm@freescale.com>

This fixes --reuseinitrd and --ramdisk option for ppc32 on
uImage-ppc and Elf. It works for normal kexec as well as for
kdump.

When using --reuseinitrd you need to specifify retain_initrd
on the command line. Also, if you are doing kdump you need to make
sure your initrd lives in the crashdump region otherwise the
kdump kernel will not be able to access it. The --ramdisk option
should always work.

Signed-off-by: Matthew McClintock <msm@freescale.com>
---
 kexec/arch/ppc/Makefile               |    1 +
 kexec/arch/ppc/include/arch/options.h |    3 +
 kexec/arch/ppc/kexec-elf-ppc.c        |   44 ++++++++++++++++++++-
 kexec/arch/ppc/kexec-ppc.c            |    6 +++
 kexec/arch/ppc/kexec-ppc.h            |    2 +
 kexec/arch/ppc/kexec-uImage-ppc.c     |   68 +++++++++++++++++++++++++++++++-
 6 files changed, 118 insertions(+), 6 deletions(-)

diff --git a/kexec/arch/ppc/Makefile b/kexec/arch/ppc/Makefile
index 5988213..c963175 100644
--- a/kexec/arch/ppc/Makefile
+++ b/kexec/arch/ppc/Makefile
@@ -21,6 +21,7 @@ libfdt_SRCS += $(LIBFDT_SRCS:%=kexec/arch/ppc/libfdt/%)
 CPPFLAGS+=-I$(srcdir)/kexec/arch/$(ARCH)/libfdt
 
 ppc_KEXEC_SRCS += $(libfdt_SRCS)
+ppc_ARCH_REUSE_INITRD =
 
 dist += kexec/arch/ppc/Makefile $(ppc_KEXEC_SRCS)			\
 	kexec/arch/ppc/kexec-ppc.h kexec/arch/ppc/ppc_asm.h		\
diff --git a/kexec/arch/ppc/include/arch/options.h b/kexec/arch/ppc/include/arch/options.h
index f646ccc..0c00ea7 100644
--- a/kexec/arch/ppc/include/arch/options.h
+++ b/kexec/arch/ppc/include/arch/options.h
@@ -8,6 +8,7 @@
 #define OPT_GAMECUBE    (OPT_ARCH_MAX+1)
 #define OPT_DTB         (OPT_ARCH_MAX+2)
 #define OPT_NODES       (OPT_ARCH_MAX+3)
+#define OPT_RAMDISK	(OPT_ARCH_MAX+4)
 
 /* Options relevant to the architecture (excluding loader-specific ones),
  * in this case none:
@@ -35,6 +36,8 @@
 	KEXEC_ARCH_OPTIONS \
 	{"command-line", 1, 0, OPT_APPEND},\
 	{"append",	 1, 0, OPT_APPEND},\
+	{"ramdisk",	 1, 0, OPT_APPEND},\
+	{"initrd",	 1, 0, OPT_APPEND},\
 	{"gamecube",	 1, 0, OPT_GAMECUBE},\
 	{"dtb",	    1, 0, OPT_DTB},\
 	{"reuse-node",	   1, 0, OPT_NODES},\
diff --git a/kexec/arch/ppc/kexec-elf-ppc.c b/kexec/arch/ppc/kexec-elf-ppc.c
index 87e6507..58bba54 100644
--- a/kexec/arch/ppc/kexec-elf-ppc.c
+++ b/kexec/arch/ppc/kexec-elf-ppc.c
@@ -127,6 +127,8 @@ static const struct option options[] = {
 	KEXEC_ARCH_OPTIONS
 	{"command-line", 1, 0, OPT_APPEND},
 	{"append",       1, 0, OPT_APPEND},
+	{"ramdisk",	 1, 0, OPT_RAMDISK},
+	{"initrd",	 1, 0, OPT_RAMDISK},
 	{"gamecube",     1, 0, OPT_GAMECUBE},
 	{"dtb",     1, 0, OPT_DTB},
 	{"reuse-node",     1, 0, OPT_NODES},
@@ -139,10 +141,12 @@ void elf_ppc_usage(void)
 	printf(
 	     "    --command-line=STRING Set the kernel command line to STRING.\n"
 	     "    --append=STRING       Set the kernel command line to STRING.\n"
+	     "    --ramdisk=<filename>  Initial RAM disk.\n"
+	     "    --initrd=<filename>   same as --ramdisk\n"
 	     "    --gamecube=1|0        Enable/disable support for ELFs with changed\n"
 	     "                          addresses suitable for the GameCube.\n"
-	     "     --dtb=<filename>     Specify device tree blob file.\n"
-	     "     --reuse-node=node    Specify nodes which should be taken from /proc/device-tree.\n"
+	     "    --dtb=<filename>	   Specify device tree blob file.\n"
+	     "    --reuse-node=node	   Specify nodes which should be taken from /proc/device-tree.\n"
 	     "                          Can be set multiple times.\n"
 	     );
 }
@@ -177,7 +181,7 @@ int elf_ppc_load(int argc, char **argv,	const char *buf, off_t len,
 	unsigned long my_kernel, my_dt_offset;
 	unsigned long my_stack, my_backup_start;
 	unsigned int slave_code[256 / sizeof(unsigned int)], master_entry;
-	unsigned char *seg_buf = NULL;
+	char *seg_buf = NULL;
 	off_t seg_size = 0;
 	int target_is_gamecube = 0;
 	unsigned int addr;
@@ -193,6 +197,8 @@ int elf_ppc_load(int argc, char **argv,	const char *buf, off_t len,
 	dtb = NULL;
 	max_addr = LONG_MAX;
 	hole_addr = 0;
+	kernel_addr = 0;
+	ramdisk = 0;
 
 	while ((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
 		switch (opt) {
@@ -207,6 +213,9 @@ int elf_ppc_load(int argc, char **argv,	const char *buf, off_t len,
 		case OPT_APPEND:
 			command_line = optarg;
 			break;
+		case OPT_RAMDISK:
+			ramdisk = optarg;
+			break;
 		case OPT_GAMECUBE:
 			target_is_gamecube = atoi(optarg);
 			break;
@@ -234,6 +243,9 @@ int elf_ppc_load(int argc, char **argv,	const char *buf, off_t len,
 		command_line_len = strlen(command_line) + 1;
 	}
 
+	if (ramdisk && reuse_initrd)
+		die("Can't specify --ramdisk or --initrd with --reuseinitrd\n");
+
 	fixup_nodes[cur_fixup] = NULL;
 
 	/* Need to append some command line parameters internally in case of
@@ -339,6 +351,32 @@ int elf_ppc_load(int argc, char **argv,	const char *buf, off_t len,
 	elf_rel_build_load(info, &info->rhdr, (const char *)purgatory,
 			purgatory_size, 0, elf_max_addr(&ehdr), 1, 0);
 
+	if (ramdisk)
+	{
+		seg_buf = slurp_file(ramdisk, &seg_size);
+		hole_addr = add_buffer(info, seg_buf, seg_size, seg_size,
+			0, 0, max_addr, 1);
+		ramdisk_base = hole_addr;
+		ramdisk_size = seg_size;
+	}
+	if (reuse_initrd)
+	{
+		ramdisk_base = initrd_base;
+		ramdisk_size = initrd_size;
+	}
+
+	if (info->kexec_flags & KEXEC_ON_CRASH && ramdisk_base != 0) {
+		if ( (ramdisk_base < crash_base) ||
+			(ramdisk_base > crash_base + crash_size) )
+		{
+			printf("WARNING: ramdisk is above crashkernel region!\n");
+		}
+		else if (ramdisk_base + initrd_size > crash_base + crash_size)
+		{
+			printf("WARNING: ramdisk overflows crashkernel region!\n");
+		}
+	}
+
 	if (dtb) {
 		char *blob_buf;
 		off_t blob_size = 0;
diff --git a/kexec/arch/ppc/kexec-ppc.c b/kexec/arch/ppc/kexec-ppc.c
index d9f1d05..7adea2b 100644
--- a/kexec/arch/ppc/kexec-ppc.c
+++ b/kexec/arch/ppc/kexec-ppc.c
@@ -33,6 +33,12 @@ unsigned long long ramdisk_base = 0, ramdisk_size = 0;
 unsigned long long devicetree_base = 0, devicetree_size = 0;
 unsigned int rtas_base, rtas_size;
 int max_memory_ranges;
+const char *ramdisk;
+
+void arch_reuse_initrd(void)
+{
+	reuse_initrd = 1;
+}
 
 #ifdef WITH_GAMECUBE
 #define MAX_MEMORY_RANGES  64
diff --git a/kexec/arch/ppc/kexec-ppc.h b/kexec/arch/ppc/kexec-ppc.h
index aefdc6f..5ad3575 100644
--- a/kexec/arch/ppc/kexec-ppc.h
+++ b/kexec/arch/ppc/kexec-ppc.h
@@ -65,8 +65,10 @@ typedef struct mem_rgns {
 extern mem_rgns_t usablemem_rgns;
 extern int max_memory_ranges;
 extern unsigned long long initrd_base, initrd_size;
+extern unsigned long long ramdisk_base, ramdisk_size;
 extern unsigned long long devicetree_base, devicetree_size;
 extern unsigned char reuse_initrd;
+extern const char *ramdisk;
 #define COMMAND_LINE_SIZE	512 /* from kernel */
 /*fs2dt*/
 void reserve(unsigned long long where, unsigned long long length);
diff --git a/kexec/arch/ppc/kexec-uImage-ppc.c b/kexec/arch/ppc/kexec-uImage-ppc.c
index 21a7c1b..310d6c3 100644
--- a/kexec/arch/ppc/kexec-uImage-ppc.c
+++ b/kexec/arch/ppc/kexec-uImage-ppc.c
@@ -14,12 +14,16 @@
 #include "kexec-ppc.h"
 #include "fixup_dtb.h"
 #include <kexec-uImage.h>
+#include "crashdump-powerpc.h"
+#include <limits.h>
 
 /* See options.h -- add any more there, too. */
 static const struct option options[] = {
 	KEXEC_ARCH_OPTIONS
 	{"command-line",	1, 0, OPT_APPEND},
 	{"append",	1, 0, OPT_APPEND},
+	{"ramdisk",	1, 0, OPT_RAMDISK},
+	{"initrd",	1, 0, OPT_RAMDISK},
 	{"dtb",		1, 0, OPT_DTB},
 	{"reuse-node",	1, 0, OPT_NODES},
 	{0, 0, 0, 0},
@@ -31,8 +35,10 @@ void uImage_ppc_usage(void)
 	printf(
 			"    --command-line=STRING Set the kernel command line to STRING.\n"
 			"    --append=STRING       Set the kernel command line to STRING.\n"
-			"     --dtb=<filename>     Specify device tree blob file.\n"
-			"     --reuse-node=node    Specify nodes which should be taken from /proc/device-tree.\n"
+			"    --ramdisk=<filename>  Initial RAM disk.\n"
+			"    --initrd=<filename>   same as --ramdisk\n"
+			"    --dtb=<filename>      Specify device tree blob file.\n"
+			"    --reuse-node=node     Specify nodes which should be taken from /proc/device-tree.\n"
 			"                          Can be set multiple times.\n"
 	);
 }
@@ -46,7 +52,7 @@ static int ppc_load_bare_bits(int argc, char **argv, const char *buf,
 		off_t len, struct kexec_info *info, unsigned int load_addr,
 		unsigned int ep)
 {
-	char *command_line, *cmdline_buf;
+	char *command_line, *cmdline_buf, *crash_cmdline;
 	int command_line_len;
 	char *dtb;
 	unsigned int addr;
@@ -56,10 +62,15 @@ static int ppc_load_bare_bits(int argc, char **argv, const char *buf,
 	int cur_fixup = 0;
 	int opt;
 	int ret;
+	char *seg_buf = NULL;
+	off_t seg_size = 0;
+	unsigned long long hole_addr;
+	unsigned long max_addr;
 
 	cmdline_buf = NULL;
 	command_line = NULL;
 	dtb = NULL;
+	max_addr = LONG_MAX;
 
 	while ((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
 		switch (opt) {
@@ -75,6 +86,10 @@ static int ppc_load_bare_bits(int argc, char **argv, const char *buf,
 			command_line = optarg;
 			break;
 
+		case OPT_RAMDISK:
+			ramdisk = optarg;
+			break;
+
 		case OPT_DTB:
 			dtb = optarg;
 			break;
@@ -90,6 +105,9 @@ static int ppc_load_bare_bits(int argc, char **argv, const char *buf,
 		}
 	}
 
+	if (ramdisk && reuse_initrd)
+		die("Can't specify --ramdisk or --initrd with --reuseinitrd\n");
+
 	command_line_len = 0;
 	if (command_line) {
 		command_line_len = strlen(command_line) + 1;
@@ -114,10 +132,54 @@ static int ppc_load_bare_bits(int argc, char **argv, const char *buf,
 	}
 	add_segment(info, buf, len, load_addr, len + (1 * 1024 * 1024));
 
+	if (info->kexec_flags & KEXEC_ON_CRASH) {
+                crash_cmdline = xmalloc(COMMAND_LINE_SIZE);
+                memset((void *)crash_cmdline, 0, COMMAND_LINE_SIZE);
+        } else
+                crash_cmdline = NULL;
+
+	if (info->kexec_flags & KEXEC_ON_CRASH) {
+		ret = load_crashdump_segments(info, crash_cmdline,
+						max_addr, 0);
+		if (ret < 0) {
+			return -1;
+		}
+	}
+
 	cmdline_buf = xmalloc(COMMAND_LINE_SIZE);
 	memset((void *)cmdline_buf, 0, COMMAND_LINE_SIZE);
 	if (command_line)
 		strncat(cmdline_buf, command_line, command_line_len);
+	if (crash_cmdline)
+		strncat(cmdline_buf, crash_cmdline,
+			sizeof(crash_cmdline) -
+			strlen(crash_cmdline) - 1);
+
+	if (ramdisk)
+	{
+		seg_buf = slurp_file(ramdisk, &seg_size);
+		hole_addr = add_buffer(info, seg_buf, seg_size, seg_size,
+			0, 0, max_addr, 1);
+		ramdisk_base = hole_addr;
+		ramdisk_size = seg_size;
+	}
+	if (reuse_initrd)
+	{
+		ramdisk_base = initrd_base;
+		ramdisk_size = initrd_size;
+	}
+
+	if (info->kexec_flags & KEXEC_ON_CRASH && ramdisk_base != 0) {
+		if ( (ramdisk_base < crash_base) ||
+		     (ramdisk_base > crash_base + crash_size) )
+		{
+			printf("WARNING: ramdisk is above crashkernel region!\n");
+		}
+		else if (ramdisk_base + ramdisk_size > crash_base + crash_size)
+		{
+			printf("WARNING: ramdisk overflows crashkernel region!\n");
+		}
+	}
 
 	if (dtb) {
 		char *blob_buf;
-- 
1.6.0.6

^ permalink raw reply related

* [PATCH v2 6/7] Add support for reworking flat device tree support
From: Matthew McClintock @ 2010-07-20 20:14 UTC (permalink / raw)
  To: kexec; +Cc: Matthew McClintock, linuxppc-dev
In-Reply-To: <1279656900-27458-5-git-send-email-msm@freescale.com>

Currently, the device tree is passed as is. You can optionally
update the command line and specifically listed nodes but nothing
is updated automatically.

This patch updates the memreserve regions, memory node, initrd
nodes and attempts to make the device tree look as it should. Some
code is borrowed from the u-boot routines which do similiar things

Also, now if no flat device tree is passed to kexec it will attempt
to rebuild one from the /proc/device-tree file system to use for
the kexec'ed kernel for both uImage and elf formats

Signed-off-by: Matthew McClintock <msm@freescale.com>
---
 kexec/arch/ppc/fixup_dtb.c        |  314 ++++++++++++++++++++++++++++++++++++-
 kexec/arch/ppc/fixup_dtb.h        |    6 +-
 kexec/arch/ppc/kexec-elf-ppc.c    |  148 +++++------------
 kexec/arch/ppc/kexec-ppc.h        |    1 +
 kexec/arch/ppc/kexec-uImage-ppc.c |   54 +++++--
 kexec/arch/ppc/ops.h              |    1 -
 6 files changed, 400 insertions(+), 124 deletions(-)

diff --git a/kexec/arch/ppc/fixup_dtb.c b/kexec/arch/ppc/fixup_dtb.c
index 40e9350..0f9238b 100644
--- a/kexec/arch/ppc/fixup_dtb.c
+++ b/kexec/arch/ppc/fixup_dtb.c
@@ -8,13 +8,36 @@
 #include <sys/stat.h>
 
 #include "../../kexec.h"
+#include "../../kexec-syscall.h"
 #include <libfdt.h>
 #include "ops.h"
 #include "page.h"
 #include "fixup_dtb.h"
+#include "kexec-ppc.h"
 
 const char proc_dts[] = "/proc/device-tree";
 
+#ifdef DEBUG
+static void print_fdt_reserve_regions(char *blob_buf)
+{
+	int i, num;
+
+	/* Print out a summary of the final reserve regions */
+	num =  fdt_num_mem_rsv(blob_buf);
+	printf ("reserve regions: %d\n", num);
+	for (i = 0; i < num; i++)
+	{
+		uint64_t offset, size;
+
+		if (fdt_get_mem_rsv(blob_buf, i, &offset, &size) == 0) {
+			printf("%d: offset: %llx, size: %llx\n", i, offset, size);
+		} else {
+			printf("Error retreiving reserved region\n");
+		}
+	}
+}
+#endif
+
 static void fixup_nodes(char *nodes[])
 {
 	int index = 0;
@@ -92,14 +115,303 @@ static void fixup_cmdline(const char *cmdline)
 	return;
 }
 
-char *fixup_dtb_nodes(char *blob_buf, off_t *blob_size, char *nodes[], char *cmdline)
+#define EXPAND_GRANULARITY     1024
+
+static char *expand_buf(int minexpand, char *blob_buf, off_t *blob_size)
+{
+	int size = fdt_totalsize(blob_buf);
+	int rc;
+
+	size = _ALIGN(size + minexpand, EXPAND_GRANULARITY);
+	blob_buf = realloc(blob_buf, size);
+	if (!blob_buf)
+		fatal("Couldn't find %d bytes to expand device tree\n\r", size);
+	rc = fdt_open_into(blob_buf, blob_buf, size);
+	if (rc != 0)
+		fatal("Couldn't expand fdt into new buffer: %s\n\r",
+			fdt_strerror(rc));
+
+	*blob_size = fdt_totalsize(blob_buf);
+
+	return blob_buf;
+}
+
+static void fixup_reserve_regions(struct kexec_info *info, char *blob_buf, off_t *blob_size)
+{
+	int ret, i;
+	int nodeoffset;
+
+	/* If this is a KEXEC kernel we add all regions since they will
+	 * all need to be saved */
+	if (info->kexec_flags & KEXEC_ON_CRASH) {
+		for (i = 0; i < info->nr_segments; i++)
+		{
+			uint64_t address = (unsigned long)info->segment[i].mem;
+			uint64_t size = info->segment[i].memsz;
+
+			/* We add all except the device tree because it's already added */
+			if (address == devicetree_base) continue;
+
+			while ((i+1) < info->nr_segments &&
+			      (address + size == (unsigned long)info->segment[i+1].mem))
+			{
+				/* We add all except the device tree because it's already added */
+				if ( (unsigned long)info->segment[i+1].mem == devicetree_base)
+					 continue;
+
+				size += info->segment[++i].memsz;
+			}
+
+			ret = fdt_add_mem_rsv(blob_buf, address, size);
+			if (ret) {
+				printf("%s: Error adding memory range to memreserve!\n",
+					fdt_strerror(ret));
+				goto out;
+			}
+		}
+	} else {
+		/* Otherwise we just add back the ramdisk and the device tree
+		 * is already in the list */
+		ret = fdt_add_mem_rsv(blob_buf, ramdisk_base, ramdisk_size);
+		if (ret) {
+			printf("%s: Unable to add new reserved memory for initrd flat device tree\n",
+				fdt_strerror(ret));
+			goto out;
+		}
+	}
+
+	/* Add reserve regions for cpu-release-addr */
+	nodeoffset = fdt_node_offset_by_prop_value(blob_buf, -1, "device_type", "cpu", 4);
+	while (nodeoffset != -FDT_ERR_NOTFOUND)
+	{
+		const void *buf;
+		int sz, ret;
+		u64 val = 0;
+
+		buf = fdt_getprop(blob_buf, nodeoffset, "cpu-release-addr", &sz);
+		if (sz == 4) {
+			val = *(u32 *)buf;
+		} else if (sz == 8) {
+			val = *(u64 *)buf;
+		}
+
+		if (val) {
+			ret = fdt_add_mem_rsv(blob_buf, PAGE_ALIGN(val-PAGE_SIZE), PAGE_SIZE);
+			if (ret)
+				printf("%s: Unable to add reserve for cpu-release-addr!\n",
+					fdt_strerror(ret));
+		}
+
+		nodeoffset = fdt_node_offset_by_prop_value(blob_buf, nodeoffset,
+				"device_type", "cpu", 4);
+	}
+
+out:	;
+
+#ifdef DEBUG
+	print_fdt_reserve_regions(blob_buf);
+#endif
+}
+
+static void fixup_memory(struct kexec_info *info, char *blob_buf)
 {
+	if (info->kexec_flags & KEXEC_ON_CRASH) {
+		int nodeoffset, len = 0;
+		u8 tmp[16];
+		const unsigned long *addrcell, *sizecell;
+
+		nodeoffset = fdt_path_offset(blob_buf, "/memory");
+
+		if (nodeoffset < 0) {
+			printf("Error searching for memory node!\n");
+			return;
+		}
+
+		addrcell = fdt_getprop(blob_buf, 0, "#address-cells", NULL);
+		/* use shifts and mask to ensure endianness */
+		if ((addrcell) && (*addrcell == 2)) {
+			tmp[0] = (crash_base >> 56) & 0xff;
+			tmp[1] = (crash_base >> 48) & 0xff;
+			tmp[2] = (crash_base >> 40) & 0xff;
+			tmp[3] = (crash_base >> 32) & 0xff;
+			tmp[4] = (crash_base >> 24) & 0xff;
+			tmp[5] = (crash_base >> 16) & 0xff;
+			tmp[6] = (crash_base >>  8) & 0xff;
+			tmp[7] = (crash_base      ) & 0xff;
+			len = 8;
+		} else {
+			tmp[0] = (crash_base >> 24) & 0xff;
+			tmp[1] = (crash_base >> 16) & 0xff;
+			tmp[2] = (crash_base >>  8) & 0xff;
+			tmp[3] = (crash_base      ) & 0xff;
+			len = 4;
+		}
+
+		sizecell = fdt_getprop(blob_buf, 0, "#size-cells", NULL);
+		/* use shifts and mask to ensure endianness */
+		if ((sizecell) && (*sizecell == 2)) {
+			tmp[0+len] = (crash_size >> 56) & 0xff;
+			tmp[1+len] = (crash_size >> 48) & 0xff;
+			tmp[2+len] = (crash_size >> 40) & 0xff;
+			tmp[3+len] = (crash_size >> 32) & 0xff;
+			tmp[4+len] = (crash_size >> 24) & 0xff;
+			tmp[5+len] = (crash_size >> 16) & 0xff;
+			tmp[6+len] = (crash_size >>  8) & 0xff;
+			tmp[7+len] = (crash_size      ) & 0xff;
+			len += 8;
+		} else {
+			tmp[0+len] = (crash_size >> 24) & 0xff;
+			tmp[1+len] = (crash_size >> 16) & 0xff;
+			tmp[2+len] = (crash_size >>  8) & 0xff;
+			tmp[3+len] = (crash_size      ) & 0xff;
+			len += 4;
+		}
+
+		if (fdt_setprop(blob_buf, nodeoffset, "reg", tmp, len) != 0) {
+			printf ("Error setting memory node!\n");
+		}
+
+		fdt_delprop(blob_buf, nodeoffset, "linux,usable-memory");
+	}
+}
+
+/* removes crashkernel nodes if they exist and we are *rebooting*
+ * into a crashkernel. These nodes should not exist after we
+ * crash and reboot into a new kernel
+ */
+static void fixup_crashkernel(struct kexec_info *info, char *blob_buf)
+{
+	int nodeoffset;
+
+	nodeoffset = fdt_path_offset(blob_buf, "/chosen");
+
+	if (info->kexec_flags & KEXEC_ON_CRASH)
+	{
+		if (nodeoffset < 0)
+		{
+			printf("fdt_crashkernel: %s\n", fdt_strerror(nodeoffset));
+			return;
+		}
+
+		fdt_delprop(blob_buf, nodeoffset, "linux,crashkernel-base");
+		fdt_delprop(blob_buf, nodeoffset, "linux,crashkernel-size");
+	}
+}
+/* remove the old chosen nodes if they exist and add correct chosen
+ * nodes if we have an initd
+ */
+static void fixup_initrd(char *blob_buf)
+{
+	int err, nodeoffset;
+	unsigned long tmp;
+
+	nodeoffset = fdt_path_offset(blob_buf, "/chosen");
+
+	if ((reuse_initrd || ramdisk) &&
+		((ramdisk_base != 0) && (ramdisk_size != 0)))
+	{
+		if (nodeoffset < 0)
+		{
+			printf("fdt_initrd: %s\n", fdt_strerror(nodeoffset));
+			return;
+		}
+
+		tmp = ramdisk_base;
+		err = fdt_setprop(blob_buf, nodeoffset,
+			"linux,initrd-start", &tmp, sizeof(tmp));
+		if (err < 0) {
+			printf("WARNING: "
+				"could not set linux,initrd-start %s.\n",
+				fdt_strerror(err));
+				return;
+		}
+
+		tmp = ramdisk_base + ramdisk_size + 1;
+		err = fdt_setprop(blob_buf, nodeoffset,
+			"linux,initrd-end", &tmp, sizeof(tmp));
+		if (err < 0) {
+			printf("WARNING: could not set linux,initrd-end %s.\n",
+				fdt_strerror(err));
+				return;
+		}
+	} else {
+		fdt_delprop(blob_buf, nodeoffset, "linux,initrd-start");
+		fdt_delprop(blob_buf, nodeoffset, "linux,initrd-end");
+	}
+}
+
+char *fixup_dtb_init(struct kexec_info *info, char *blob_buf, off_t *blob_size,
+			unsigned long hole_addr, unsigned long *dtb_addr)
+{
+	int ret, i, num = fdt_num_mem_rsv(blob_buf);
+
 	fdt_init(blob_buf);
 
+	/* Remove the existing reserve regions as they will no longer
+	 * be valid after we reboot */
+	for (i = num - 1; i >= 0; i--)
+	{
+		ret = fdt_del_mem_rsv(blob_buf, i);
+		if (ret) {
+			printf("%s: Error deleting memory reserve region %d from device tree!\n",
+					fdt_strerror(ret), i);
+		}
+	}
+
+	/* Pack the FDT first, so we don't grow excessively if there is already free space */
+	ret = fdt_pack(blob_buf);
+	if (ret)
+		printf("%s: Unable to pack flat device tree\n", fdt_strerror(ret));
+
+	/* info->nr_segments just a guide, will grow by at least EXPAND_GRANULARITY */
+	blob_buf = expand_buf(info->nr_segments, blob_buf, blob_size);
+
+	/* add reserve region for *THIS* fdt */
+	*dtb_addr = locate_hole(info, *blob_size, 0,
+				hole_addr, hole_addr+KERNEL_ACCESS_TOP, -1);
+	ret = fdt_add_mem_rsv(blob_buf, *dtb_addr, PAGE_ALIGN(*blob_size));
+	if (ret) {
+		printf("%s: Unable to add new reserved memory for the flat device tree\n",
+			fdt_strerror(ret));
+	}
+
+	return blob_buf;
+}
+
+#ifdef DEBUG
+static void save_fixed_up_dtb(char *blob_buf, off_t blob_size)
+{
+	FILE *fp;
+
+	fp = fopen("debug.dtb", "w");
+	if (fp) {
+		if ( blob_size == fwrite(blob_buf, sizeof(char), blob_size, fp)) {
+			printf("debug.dtb written\n");
+		} else {
+			printf("Unable to write debug.dtb\n");
+		}
+	} else {
+		printf("Unable to dump flat device tree to debug.dtb\n");
+	}
+}
+#endif
+
+char *fixup_dtb_finalize(struct kexec_info *info, char *blob_buf, off_t *blob_size,
+			char *nodes[], char *cmdline)
+{
 	fixup_nodes(nodes);
 	fixup_cmdline(cmdline);
+	fixup_reserve_regions(info, blob_buf, blob_size);
+	fixup_memory(info, blob_buf);
+	fixup_initrd(blob_buf);
+	fixup_crashkernel(info, blob_buf);
 
 	blob_buf = (char *)dt_ops.finalize();
 	*blob_size = fdt_totalsize(blob_buf);
+
+#ifdef DEBUG
+	save_fixed_up_dtb(blob_buf, *blob_size);
+#endif
+
 	return blob_buf;
 }
diff --git a/kexec/arch/ppc/fixup_dtb.h b/kexec/arch/ppc/fixup_dtb.h
index 0ff981e..b706a5a 100644
--- a/kexec/arch/ppc/fixup_dtb.h
+++ b/kexec/arch/ppc/fixup_dtb.h
@@ -1,6 +1,10 @@
 #ifndef __FIXUP_DTB_H
 #define __FIXUP_DTB_H
 
-char *fixup_dtb_nodes(char *blob_buf, off_t *blob_size, char *nodes[], char *cmdline);
+char *fixup_dtb_init(struct kexec_info *info, char *blob_buf, off_t *blob_size,
+			unsigned long hole_addr, unsigned long *dtb_addr);
+
+char *fixup_dtb_finalize(struct kexec_info *info, char *blob_buf, off_t *blob_size,
+			char *nodes[], char *cmdline);
 
 #endif
diff --git a/kexec/arch/ppc/kexec-elf-ppc.c b/kexec/arch/ppc/kexec-elf-ppc.c
index 58bba54..3b55278 100644
--- a/kexec/arch/ppc/kexec-elf-ppc.c
+++ b/kexec/arch/ppc/kexec-elf-ppc.c
@@ -175,23 +175,20 @@ int elf_ppc_load(int argc, char **argv,	const char *buf, off_t len,
 	unsigned char *setup_start;
 	uint32_t setup_size;
 #else
-	unsigned long long *rsvmap_ptr;
-	struct bootblock *bb_ptr;
-	unsigned int nr_segments;
-	unsigned long my_kernel, my_dt_offset;
-	unsigned long my_stack, my_backup_start;
-	unsigned int slave_code[256 / sizeof(unsigned int)], master_entry;
 	char *seg_buf = NULL;
 	off_t seg_size = 0;
 	int target_is_gamecube = 0;
 	unsigned int addr;
 	unsigned long dtb_addr;
+	unsigned long dtb_addr_actual;
 	unsigned long kernel_addr;
 #endif
 #define FIXUP_ENTRYS	(20)
 	char *fixup_nodes[FIXUP_ENTRYS + 1];
 	int cur_fixup = 0;
 	int opt;
+	char *blob_buf = NULL;
+	off_t blob_size = 0;
 
 	command_line = NULL;
 	dtb = NULL;
@@ -351,11 +348,28 @@ int elf_ppc_load(int argc, char **argv,	const char *buf, off_t len,
 	elf_rel_build_load(info, &info->rhdr, (const char *)purgatory,
 			purgatory_size, 0, elf_max_addr(&ehdr), 1, 0);
 
+	/* Here we need to initialize the device tree, and find out where
+	 * it is going to live so we can place it directly after the
+	 * kernel image */
+	if (dtb) {
+		/* Grab device tree from buffer */
+		blob_buf = slurp_file(dtb, &blob_size);
+	} else {
+		create_flatten_tree(info, (unsigned char **)&blob_buf,
+				(unsigned long *)&blob_size, cmdline_buf);
+	}
+	if (!blob_buf || !blob_size)
+		die("Device tree seems to be an empty file.\n");
+
+	/* initial fixup for device tree */
+	blob_buf = fixup_dtb_init(info, blob_buf, &blob_size, kernel_addr, &dtb_addr);
+
 	if (ramdisk)
 	{
 		seg_buf = slurp_file(ramdisk, &seg_size);
+		/* load the ramdisk *above* the device tree */
 		hole_addr = add_buffer(info, seg_buf, seg_size, seg_size,
-			0, 0, max_addr, 1);
+				0, dtb_addr + blob_size + 1,  max_addr, -1);
 		ramdisk_base = hole_addr;
 		ramdisk_size = seg_size;
 	}
@@ -377,111 +391,37 @@ int elf_ppc_load(int argc, char **argv,	const char *buf, off_t len,
 		}
 	}
 
-	if (dtb) {
-		char *blob_buf;
-		off_t blob_size = 0;
-
-		/* Grab device tree from buffer */
-		blob_buf = slurp_file(dtb, &blob_size);
-		if (!blob_buf || !blob_size)
-			die("Device tree seems to be an empty file.\n");
-
-		blob_buf = fixup_dtb_nodes(blob_buf, &blob_size, fixup_nodes,
-				cmdline_buf);
-		dtb_addr = add_buffer(info, blob_buf, blob_size, blob_size, 0, kernel_addr,
-				kernel_addr + KERNEL_ACCESS_TOP, -1);
-	} else {
-		/* create from fs2dt */
-		seg_buf = NULL;
-		seg_size = 0;
-		create_flatten_tree(info, (unsigned char **)&seg_buf,
-				(unsigned long *)&seg_size, cmdline_buf);
-		add_buffer(info, seg_buf, seg_size, seg_size,
-#ifdef CONFIG_PPC64
-				0, 0,  max_addr, -1);
-#else
-		/* load dev tree at 16 Mb offset from kernel load address */
-			0, 0, ehdr.e_phdr[0].p_paddr + SIZE_16M, -1);
-#endif
+	/* Perform final fixup on devie tree, i.e. everything beside what
+	 * was done above */
+	fixup_dtb_finalize(info, blob_buf, &blob_size, fixup_nodes,
+			cmdline_buf);
+	dtb_addr_actual = add_buffer(info, blob_buf, blob_size, blob_size, 0, dtb_addr,
+			kernel_addr + KERNEL_ACCESS_TOP, 1);
+	if (dtb_addr_actual != dtb_addr)
+	{
+		die("Error device tree not loadded to address it was expecting to be loaded too!\n");
 	}
 
+	/* set various variables for the purgatory  ehdr.e_entry is a
+	 * virtual address, we can use kernel_addr which
+	 * should be the physical start address of the kernel */
+	addr = kernel_addr;
+	elf_rel_set_symbol(&info->rhdr, "kernel", &addr, sizeof(addr));
 
-	if (dtb) {
-		/* set various variables for the purgatory  ehdr.e_entry is a
-		 * virtual address, we can use kernel_addr which
-		 * should be the physical start address of the kernel */
-		addr = kernel_addr;
-		elf_rel_set_symbol(&info->rhdr, "kernel", &addr, sizeof(addr));
-
-		addr = dtb_addr;
-		elf_rel_set_symbol(&info->rhdr, "dt_offset",
-						&addr, sizeof(addr));
+	addr = dtb_addr;
+	elf_rel_set_symbol(&info->rhdr, "dt_offset",
+					&addr, sizeof(addr));
 
 #define PUL_STACK_SIZE	(16 * 1024)
-		addr = locate_hole(info, PUL_STACK_SIZE, 0, 0,
+	addr = locate_hole(info, PUL_STACK_SIZE, 0, 0,
 				elf_max_addr(&ehdr), 1);
-		addr += PUL_STACK_SIZE;
-		elf_rel_set_symbol(&info->rhdr, "stack", &addr, sizeof(addr));
+	addr += PUL_STACK_SIZE;
+	elf_rel_set_symbol(&info->rhdr, "stack", &addr, sizeof(addr));
 #undef PUL_STACK_SIZE
 
-		addr = elf_rel_get_addr(&info->rhdr, "purgatory_start");
-		info->entry = (void *)addr;
-
-	} else { /*from fs2dt*/
-
-		/* patch reserve map address for flattened device-tree
-		 * find last entry (both 0) in the reserve mem list.  Assume DT
-		 * entry is before this one
-		 */
-		bb_ptr = (struct bootblock *)(
-			(unsigned char *)info->segment[(info->nr_segments) -
-				1].buf);
-		rsvmap_ptr = (unsigned long long *)(
-			(unsigned char *)info->segment[(info->nr_segments) -
-				1].buf + bb_ptr->off_mem_rsvmap);
-		while (*rsvmap_ptr || *(rsvmap_ptr + 1))
-			rsvmap_ptr += 2;
-		rsvmap_ptr -= 2;
-		*rsvmap_ptr = (unsigned long)(
-				info->segment[(info->nr_segments)-1].mem);
-		rsvmap_ptr++;
-		*rsvmap_ptr = (unsigned long long)bb_ptr->totalsize;
-
-		nr_segments = info->nr_segments;
-
-		/* Set kernel */
-		my_kernel = (unsigned long)info->segment[0].mem;
-		elf_rel_set_symbol(&info->rhdr, "kernel", &my_kernel,
-				sizeof(my_kernel));
-
-		/* Set dt_offset */
-		my_dt_offset = (unsigned long)info->segment[nr_segments -
-			1].mem;
-		elf_rel_set_symbol(&info->rhdr, "dt_offset", &my_dt_offset,
-				sizeof(my_dt_offset));
-
-		/* get slave code from new kernel, put in purgatory */
-		elf_rel_get_symbol(&info->rhdr, "purgatory_start", slave_code,
-				sizeof(slave_code));
-		master_entry = slave_code[0];
-		memcpy(slave_code, info->segment[0].buf, sizeof(slave_code));
-		slave_code[0] = master_entry;
-		elf_rel_set_symbol(&info->rhdr, "purgatory_start", slave_code,
-				sizeof(slave_code));
-
-		/* Set stack address */
-		my_stack = locate_hole(info, 16*1024, 0, 0, max_addr, 1);
-		my_stack += 16*1024;
-		elf_rel_set_symbol(&info->rhdr, "stack", &my_stack,
-				sizeof(my_stack));
-	}
-
-	if (info->kexec_flags & KEXEC_ON_CRASH) {
-		/* Set backup address */
-		my_backup_start = info->backup_start;
-		elf_rel_set_symbol(&info->rhdr, "backup_start",
-				&my_backup_start, sizeof(my_backup_start));
-	}
+	addr = elf_rel_get_addr(&info->rhdr, "purgatory_start");
+	info->entry = (void *)addr;
 #endif
+
 	return 0;
 }
diff --git a/kexec/arch/ppc/kexec-ppc.h b/kexec/arch/ppc/kexec-ppc.h
index 5ad3575..029a656 100644
--- a/kexec/arch/ppc/kexec-ppc.h
+++ b/kexec/arch/ppc/kexec-ppc.h
@@ -64,6 +64,7 @@ typedef struct mem_rgns {
 } mem_rgns_t;
 extern mem_rgns_t usablemem_rgns;
 extern int max_memory_ranges;
+extern unsigned long long crash_base, crash_size;
 extern unsigned long long initrd_base, initrd_size;
 extern unsigned long long ramdisk_base, ramdisk_size;
 extern unsigned long long devicetree_base, devicetree_size;
diff --git a/kexec/arch/ppc/kexec-uImage-ppc.c b/kexec/arch/ppc/kexec-uImage-ppc.c
index 310d6c3..479b86d 100644
--- a/kexec/arch/ppc/kexec-uImage-ppc.c
+++ b/kexec/arch/ppc/kexec-uImage-ppc.c
@@ -17,6 +17,9 @@
 #include "crashdump-powerpc.h"
 #include <limits.h>
 
+int create_flatten_tree(struct kexec_info *, unsigned char **, unsigned long *,
+			char *);
+
 /* See options.h -- add any more there, too. */
 static const struct option options[] = {
 	KEXEC_ARCH_OPTIONS
@@ -57,6 +60,7 @@ static int ppc_load_bare_bits(int argc, char **argv, const char *buf,
 	char *dtb;
 	unsigned int addr;
 	unsigned long dtb_addr;
+	unsigned long dtb_addr_actual;
 #define FIXUP_ENTRYS    (20)
 	char *fixup_nodes[FIXUP_ENTRYS + 1];
 	int cur_fixup = 0;
@@ -66,6 +70,8 @@ static int ppc_load_bare_bits(int argc, char **argv, const char *buf,
 	off_t seg_size = 0;
 	unsigned long long hole_addr;
 	unsigned long max_addr;
+	char *blob_buf = NULL;
+	off_t blob_size = 0;
 
 	cmdline_buf = NULL;
 	command_line = NULL;
@@ -155,11 +161,31 @@ static int ppc_load_bare_bits(int argc, char **argv, const char *buf,
 			sizeof(crash_cmdline) -
 			strlen(crash_cmdline) - 1);
 
+	elf_rel_build_load(info, &info->rhdr, (const char *)purgatory,
+				purgatory_size, 0, -1, -1, 0);
+
+	/* Here we need to initialize the device tree, and find out where
+	 * it is going to live so we can place it directly after the
+	 * kernel image */
+	if (dtb) {
+		/* Grab device tree from buffer */
+		blob_buf = slurp_file(dtb, &blob_size);
+	} else {
+		create_flatten_tree(info, (unsigned char **)&blob_buf,
+				(unsigned long *)&blob_size, cmdline_buf);
+	}
+	if (!blob_buf || !blob_size)
+		die("Device tree seems to be an empty file.\n");
+
+	/* initial fixup for device tree */
+	blob_buf = fixup_dtb_init(info, blob_buf, &blob_size, load_addr, &dtb_addr);
+
 	if (ramdisk)
 	{
 		seg_buf = slurp_file(ramdisk, &seg_size);
+		/* Load ramdisk at top of memory */
 		hole_addr = add_buffer(info, seg_buf, seg_size, seg_size,
-			0, 0, max_addr, 1);
+				0, dtb_addr + blob_size, max_addr, -1);
 		ramdisk_base = hole_addr;
 		ramdisk_size = seg_size;
 	}
@@ -181,24 +207,18 @@ static int ppc_load_bare_bits(int argc, char **argv, const char *buf,
 		}
 	}
 
-	if (dtb) {
-		char *blob_buf;
-		off_t blob_size = 0;
-
-		/* Grab device tree from buffer */
-		blob_buf = slurp_file(dtb, &blob_size);
-		if (!blob_buf || !blob_size)
-			die("Device tree seems to be an empty file.\n");
-		blob_buf = fixup_dtb_nodes(blob_buf, &blob_size, fixup_nodes, cmdline_buf);
-		dtb_addr = add_buffer(info, blob_buf, blob_size, blob_size, 0, load_addr,
-				load_addr + KERNEL_ACCESS_TOP, -1);
-	} else {
-		dtb_addr = 0;
+	/* Perform final fixup on devie tree, i.e. everything beside what
+	 * was done above */
+	fixup_dtb_finalize(info, blob_buf, &blob_size, fixup_nodes,
+			cmdline_buf);
+	dtb_addr_actual = add_buffer(info, blob_buf, blob_size, blob_size, 0, dtb_addr,
+			load_addr + KERNEL_ACCESS_TOP, 1);
+	if (dtb_addr_actual != dtb_addr)
+	{
+		printf("dtb_addr_actual: %lx, dtb_addr: %lx\n", dtb_addr_actual, dtb_addr);
+		die("Error device tree not loadded to address it was expecting to be loaded too!\n");
 	}
 
-	elf_rel_build_load(info, &info->rhdr, (const char *)purgatory,
-			purgatory_size, 0, -1, -1, 0);
-
 	/* set various variables for the purgatory */
 	addr = ep;
 	elf_rel_set_symbol(&info->rhdr, "kernel", &addr, sizeof(addr));
diff --git a/kexec/arch/ppc/ops.h b/kexec/arch/ppc/ops.h
index f33e941..a2eb140 100644
--- a/kexec/arch/ppc/ops.h
+++ b/kexec/arch/ppc/ops.h
@@ -147,5 +147,4 @@ static inline char *get_path(const void *phandle, char *buf, int len)
 
 #define fatal(args...) { printf(args); exit(1); }
 
-char *fixup_dtb_nodes(char *blob_buf, off_t *blob_size, char *nodes[], char *cmdline);
 #endif /* _PPC_BOOT_OPS_H_ */
-- 
1.6.0.6

^ permalink raw reply related

* [PATCH v2 7/7] Add documentation/howto for mpc85xx systems
From: Matthew McClintock @ 2010-07-20 20:15 UTC (permalink / raw)
  To: kexec; +Cc: Matthew McClintock, linuxppc-dev
In-Reply-To: <1279656900-27458-6-git-send-email-msm@freescale.com>

Signed-off-by: Matthew McClintock <msm@freescale.com>
---
 doc/mpc85xx.txt |  190 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 190 insertions(+), 0 deletions(-)
 create mode 100644 doc/mpc85xx.txt

diff --git a/doc/mpc85xx.txt b/doc/mpc85xx.txt
new file mode 100644
index 0000000..af96841
--- /dev/null
+++ b/doc/mpc85xx.txt
@@ -0,0 +1,190 @@
+			  mpc85xx kexec howto
+			  -------------------
+
+		  Matthew McClintock <msm@freescale.com>
+			Last Updated: 2010-07-20
+
+There is some terminology that will be useful which will be described here.
+
+boot kernel - the first one that you start, from u-boot for instance
+kexec kernel - the kernel that you reboot into when running "kexec -e"
+kdump kernel - the kernel that you reboot into after the boot kernel crash
+relocatable kernel - kernel that can boot from a 256MB alignment of physical
+		     memory (for mpc85xx systems at least)
+
+Each of the above types of kernels have specific requirements, they can
+all be different kernels or all the same kernel depending on your
+particular requirements.
+
+1) Build kernel for kexec (i.e. running kexec -e to reboot)
+
+This case is the simplest. You need to enable CONFIG_KEXEC for kexec for the
+"boot kernel", the kexec kernel can be a any kernel that already boots on your
+platform. However, if you want to be able run kexec again after rebooting once
+you will need to have CONFIG_KEXEC enabled for the kexec kernel as well.
+	
+2) Build for kdump (i.e. for rebooting when your main kernel crashes)
+
+In this situation, you need to be aware that the kdump kernel will boot from
+a different physical address than your boot kernel (or even the kexec kernel). 
+There are two approaches to this. First, you can build a relocatable kernel
+which will boot from a different physical address with no changes. This method
+is ideal as it would even allow your boot kernel and kdump kernel to be the
+same one. Optionally, you can build a kernel with custom physical address and
+kernel base address according to where you will load the kdump kernel*, but
+it's much easier to just use a relocatable kernel and let things work
+themselves out at run time.
+
+You will need to enable CONFIG_CRASH_DUMP on the boot kernel. You can chose to
+enable CONFIG_RELOCATABLE for the kdump kernel, and you will still want to
+verify that CONFIG_KERNEL_START and CONFIG_PHYSICAL_START have sane defaults.
+Most likely, you can leave these as 0xC0000000 and 0x0000000 respectively.
+Finally, on the kdump kernel you will want to make sure CONFIG_PROC_VMCORE is
+enabled as well so the core dump is exported via /proc/vmcore. You can just 
+enable all these options on the boot and kdump and use the same kernel for both
+which is the simplest option.
+
+Summary of 1 & 2:
+
+Just enable kexec, crash support, and relocatable kernel and you should be good
+to go for all of the above scenarios using the same kernel.
+
+3) Obtaining a device tree
+
+You best bet for getting a working device tree is to pull the one the current
+kernel is using. The easiest way to do this is use the device tree compiler
+to create one from the proc file system
+
+	$ dtc -I fs -O dtb /proc/device-tree/ > flat-device-tree
+
+Kexec should be able to take this flat device tree, and modifiy it/update it
+as needed for your particular scenario. It will update memreserve regions, add
+initrd/ramdisks, fixup the command line, etc.
+
+NOTE: If no device tree is given, kexec will do the above on it's own to 
+      obtain a useable device tree. You can specify the device tree to use
+      with the --dtb=<flat_device_tree_blob> kexec argument.
+
+4) Kexec'ing a new kernel
+
+If you have followed the procedure above you need to do the following to reboot
+into a new kexec kernel.
+
+	$ kexec -l {uImage,vmlinux}
+	$ kexec -e
+
+These options will boot the new kernel, you should see some message as shown
+below.  NOTE: The old command line is used, so if you are booting from an NFS
+mount it should work fine, however it you are using an initrd/ramdisk there are
+caveats to consider (see #6 below).
+
+	sd 2:0:0:0: [sda] Synchronizing SCSI cache
+	Starting new kernel
+	Bye!
+	Reserving 256MB of memory at 512MB for crashkernel (System RAM: 4096MB)
+	Using MPC8572 DS machine description
+	[snip]
+
+5) Setting for a kdump kernel
+
+For the boot kernel, you need to reserve a region of memory for the kdump kernel
+to use when the system crashes. This region is removed for use from the boot
+kernel and when the system crashes the kdump kernel will operate out of this
+region exclusively. For mpc85xx, we need to pick a region aligned at 256MB if we
+are using a relocatable kernel, other than that the size allocated needs to leave
+enough memory for your kdump environment to function properly as well as store
+the kdump kernel and any other items added (this would most likely be a ramdisk).
+Some valid options are:
+
+	crashkernel={128M,256M,512M}@{256M,512M} and others
+
+For the example below we choose 256MB (0x10000000) of memory located at offset 
+512MB (0x20000000). The command line option would look like this.
+
+	crashkernel=256M@512M
+	
+You can see the values the kernel parsed by running looking
+at your proc entries. In this case, the physical address is a 64bit value.
+
+	$ hexdump -C /proc/device-tree/chosen/linux,crashkernel-base 
+	00000000  00 00 00 00 20 00 00 00                           |.... ...|
+	00000008
+	$ hexdump -C /proc/device-tree/chosen/linux,crashkernel-size 
+	00000000  00 00 00 00 10 00 00 00                           |........|
+	00000008
+
+Kdump kernels are only run when the current kernel crashes, there you can not
+just restart your system. However, you can still trigger a crash for testing 
+purposes by enabling CONFIG_MAGIC_SYSRQ and executing the following.
+
+	$ echo c > /proc/sysrq-trigger
+
+However, before this we need to setup our kdump kernel as shown below.
+
+	$ kexec -p {uImage.reloc, vmlinux}
+
+The kernel we pass in is a relocatable kernel, in the case of vmlinux no changes
+are required since there is no wrapper specifically assigning it to a certain
+address. However, kexec will attempt to honor the addresses given to mkimage
+when you created your uImage, therefore you need to create a uImage with the
+appropriate load and entry address
+
+	$ mkimage -A ppc -O linux -T kernel -C gzip -a 0x20000000 -e 0x20000000
+	-n Linux-2.6.35-rc3
+	Image Name:   Linux-2.6.35-rc3-00246-gd666cd8-
+	Created:      Wed Jul 14 17:34:19 2010
+	Image Type:   PowerPC Linux Kernel Image (gzip compressed)
+	Data Size:    3261979 Bytes = 3185.53 kB = 3.11 MB
+	Load Address: 0x20000000
+	Entry Point:  0x20000000
+
+You do not sctrictly need to use a RELOCATABLE kernel, you can build a kernel
+that can execute from this load address and entry point and it would your 
+kdump kernel would still function properly.
+
+The above load address aligns with the crashkernel argument we passed
+in via the command line. It is important to make sure these addresses match
+each other when using uImage. It's less important for vmlinux since kexec will
+attempt to load it at the first available region which should match correctly.
+	
+6) Misc. options to kexec
+
+There are a few options you can pass into kexec to modify it's behaviour. First,
+if you want to reuse your current initrd/ramdisk you can use the following.
+You will also need to add "retain_initrd" to the boot kernel command line for
+this option to work. So now your command line would look something like this.
+
+	crashkernel=256M@512M retain_initrd
+
+NOTE: If you are setting up a kdump kernel, you will need to make sure your 
+original initrd/ramdisk resides in the memory range reserved for the kdump
+kernel, otherwise the kdump kernel won't be able to access it. For example
+it needs to live within the 512MB-768M range in this case. A warning will
+be displayed if this is not the case.
+
+	$ kexec -p uImage.reloc --reuseinitrd
+
+It's even easier to specify a new ramdisk and you don't need to modify your
+boot kernel command line. You also might need to update your command line to
+boot with your new ramdisk, you can do it via the --command-line option as well
+as add any other changes you want to the command line as well.
+
+	$ kexec -p uImage.reloc --ramdisk=rootfs.ext2.gz
+	  --command-line="root=/dev/ram rw console=ttyS0,115200"
+
+or the following if you wanted kexec and add "retain_initrd" to the command
+line and boot with a ramdisk
+
+	$ kexec -l uImage --ramdisk=rootfs.ext2.gz 
+          --command-line="`cat /proc/cmdline` retain_initrd"
+	$ kexec -e
+
+7) After a crash
+
+If you have a kdump kernel loaded and your system crashes you can now debug
+the crash.
+
+	$ gdb vmlinux /proc/vmcore
+
+You might need to copy these files elsewhere or setup your ramdisk to do these
+things automatically.
-- 
1.6.0.6

^ permalink raw reply related

* [PATCH v2 3/7] Update uImage to support crash kernel and misc fixes
From: Matthew McClintock @ 2010-07-20 20:14 UTC (permalink / raw)
  To: kexec; +Cc: Matthew McClintock, linuxppc-dev
In-Reply-To: <1279656900-27458-2-git-send-email-msm@freescale.com>

Use current command line if none given, specifically useful for
when arguments are added causing the use of the current cmdline
to not occur.

We also try to load the dtb above the kernel, this is useful for
relocatable kernels where they device tree needs to reside just
above the kernel base address.

Only allocate 1 MiB extra for bss space after kernel as it appears
to be more than adequate.

Signed-off-by: Matthew McClintock <msm@freescale.com>
---
 kexec/arch/ppc/kexec-uImage-ppc.c |   32 ++++++++++++++++++++++----------
 1 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/kexec/arch/ppc/kexec-uImage-ppc.c b/kexec/arch/ppc/kexec-uImage-ppc.c
index 4a8d28d..21a7c1b 100644
--- a/kexec/arch/ppc/kexec-uImage-ppc.c
+++ b/kexec/arch/ppc/kexec-uImage-ppc.c
@@ -10,6 +10,7 @@
 #include <getopt.h>
 #include <arch/options.h>
 #include "../../kexec.h"
+#include "../../kexec-syscall.h"
 #include "kexec-ppc.h"
 #include "fixup_dtb.h"
 #include <kexec-uImage.h>
@@ -45,7 +46,7 @@ static int ppc_load_bare_bits(int argc, char **argv, const char *buf,
 		off_t len, struct kexec_info *info, unsigned int load_addr,
 		unsigned int ep)
 {
-	char *command_line;
+	char *command_line, *cmdline_buf;
 	int command_line_len;
 	char *dtb;
 	unsigned int addr;
@@ -56,6 +57,7 @@ static int ppc_load_bare_bits(int argc, char **argv, const char *buf,
 	int opt;
 	int ret;
 
+	cmdline_buf = NULL;
 	command_line = NULL;
 	dtb = NULL;
 
@@ -89,24 +91,34 @@ static int ppc_load_bare_bits(int argc, char **argv, const char *buf,
 	}
 
 	command_line_len = 0;
-	if (command_line)
+	if (command_line) {
+		command_line_len = strlen(command_line) + 1;
+	} else {
+		command_line = get_command_line();
 		command_line_len = strlen(command_line) + 1;
+	}
 
 	fixup_nodes[cur_fixup] = NULL;
 
 	/*
 	 * len contains the length of the whole kernel image except the bss
-	 * section. The 3 MiB should cover it. The purgatory and the dtb are
+	 * section. The 1 MiB should cover it. The purgatory and the dtb are
 	 * allocated from memtop down towards zero so we should never get too
 	 * close to the bss :)
 	 */
-	ret = valid_memory_range(info, load_addr, len + 3 * 1024 * 1024);
+	ret = valid_memory_range(info, load_addr, load_addr + (len + (1 * 1024 * 1024)));
 	if (!ret) {
 		printf("Can't add kernel to addr 0x%08x len %ld\n",
-				load_addr, len + 3 * 1024 * 1024);
+				load_addr, len + (1 * 1024 * 1024));
 		return -1;
 	}
-	add_segment(info, buf, len, load_addr, len + 3 * 1024 * 1024);
+	add_segment(info, buf, len, load_addr, len + (1 * 1024 * 1024));
+
+	cmdline_buf = xmalloc(COMMAND_LINE_SIZE);
+	memset((void *)cmdline_buf, 0, COMMAND_LINE_SIZE);
+	if (command_line)
+		strncat(cmdline_buf, command_line, command_line_len);
+
 	if (dtb) {
 		char *blob_buf;
 		off_t blob_size = 0;
@@ -115,10 +127,9 @@ static int ppc_load_bare_bits(int argc, char **argv, const char *buf,
 		blob_buf = slurp_file(dtb, &blob_size);
 		if (!blob_buf || !blob_size)
 			die("Device tree seems to be an empty file.\n");
-		blob_buf = fixup_dtb_nodes(blob_buf, &blob_size, fixup_nodes, command_line);
-
-		dtb_addr = add_buffer(info, blob_buf, blob_size, blob_size, 0, 0,
-				KERNEL_ACCESS_TOP, -1);
+		blob_buf = fixup_dtb_nodes(blob_buf, &blob_size, fixup_nodes, cmdline_buf);
+		dtb_addr = add_buffer(info, blob_buf, blob_size, blob_size, 0, load_addr,
+				load_addr + KERNEL_ACCESS_TOP, -1);
 	} else {
 		dtb_addr = 0;
 	}
@@ -142,6 +153,7 @@ static int ppc_load_bare_bits(int argc, char **argv, const char *buf,
 
 	addr = elf_rel_get_addr(&info->rhdr, "purgatory_start");
 	info->entry = (void *)addr;
+
 	return 0;
 }
 
-- 
1.6.0.6

^ permalink raw reply related

* [PATCH v2 4/7] Update Elf-ppc to support crash kernel and misc fixes
From: Matthew McClintock @ 2010-07-20 20:14 UTC (permalink / raw)
  To: kexec; +Cc: Matthew McClintock, linuxppc-dev
In-Reply-To: <1279656900-27458-3-git-send-email-msm@freescale.com>

Use current command line if none given, specifically useful for
when arguments are added causing the use of the current cmdline
to not occur

We also try to load the dtb above the kernel, this is useful for
relocatable kernels where they device tree needs to reside just
above the kernel base address

Set the kernel entry address in the relocatable purgatory code
so we jump to the correct start address if not the default. Useful
for relocatable kernels

Signed-off-by: Matthew McClintock <msm@freescale.com>
---
 kexec/arch/ppc/kexec-elf-ppc.c |   26 ++++++++++++++------------
 kexec/arch/ppc/kexec-ppc.c     |    7 ++++---
 2 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/kexec/arch/ppc/kexec-elf-ppc.c b/kexec/arch/ppc/kexec-elf-ppc.c
index ab2d343..87e6507 100644
--- a/kexec/arch/ppc/kexec-elf-ppc.c
+++ b/kexec/arch/ppc/kexec-elf-ppc.c
@@ -182,6 +182,7 @@ int elf_ppc_load(int argc, char **argv,	const char *buf, off_t len,
 	int target_is_gamecube = 0;
 	unsigned int addr;
 	unsigned long dtb_addr;
+	unsigned long kernel_addr;
 #endif
 #define FIXUP_ENTRYS	(20)
 	char *fixup_nodes[FIXUP_ENTRYS + 1];
@@ -228,6 +229,9 @@ int elf_ppc_load(int argc, char **argv,	const char *buf, off_t len,
 	command_line_len = 0;
 	if (command_line) {
 		command_line_len = strlen(command_line) + 1;
+	} else {
+		command_line = get_command_line();
+		command_line_len = strlen(command_line) + 1;
 	}
 
 	fixup_nodes[cur_fixup] = NULL;
@@ -264,11 +268,11 @@ int elf_ppc_load(int argc, char **argv,	const char *buf, off_t len,
 	if (size > phdr->p_memsz)
 		size = phdr->p_memsz;
 
-	hole_addr = locate_hole(info, size, 0, 0, max_addr, 1);
+	kernel_addr = locate_hole(info, size, 0, 0, max_addr, 1);
 #ifdef CONFIG_PPC64
-	ehdr.e_phdr[0].p_paddr = (Elf64_Addr)hole_addr;
+	ehdr.e_phdr[0].p_paddr = (Elf64_Addr)kernel_addr;
 #else
-	ehdr.e_phdr[0].p_paddr = hole_addr;
+	ehdr.e_phdr[0].p_paddr = kernel_addr;
 #endif
 
 	/* Load the Elf data */
@@ -343,10 +347,11 @@ int elf_ppc_load(int argc, char **argv,	const char *buf, off_t len,
 		blob_buf = slurp_file(dtb, &blob_size);
 		if (!blob_buf || !blob_size)
 			die("Device tree seems to be an empty file.\n");
+
 		blob_buf = fixup_dtb_nodes(blob_buf, &blob_size, fixup_nodes,
 				cmdline_buf);
-		dtb_addr = add_buffer(info, blob_buf, blob_size, blob_size, 0, 0,
-				KERNEL_ACCESS_TOP, -1);
+		dtb_addr = add_buffer(info, blob_buf, blob_size, blob_size, 0, kernel_addr,
+				kernel_addr + KERNEL_ACCESS_TOP, -1);
 	} else {
 		/* create from fs2dt */
 		seg_buf = NULL;
@@ -364,19 +369,16 @@ int elf_ppc_load(int argc, char **argv,	const char *buf, off_t len,
 
 
 	if (dtb) {
-		/* set various variables for the purgatory */
-		addr = ehdr.e_entry;
+		/* set various variables for the purgatory  ehdr.e_entry is a
+		 * virtual address, we can use kernel_addr which
+		 * should be the physical start address of the kernel */
+		addr = kernel_addr;
 		elf_rel_set_symbol(&info->rhdr, "kernel", &addr, sizeof(addr));
 
 		addr = dtb_addr;
 		elf_rel_set_symbol(&info->rhdr, "dt_offset",
 						&addr, sizeof(addr));
 
-		addr = rmo_top;
-
-		elf_rel_set_symbol(&info->rhdr, "mem_size",
-						&addr, sizeof(addr));
-
 #define PUL_STACK_SIZE	(16 * 1024)
 		addr = locate_hole(info, PUL_STACK_SIZE, 0, 0,
 				elf_max_addr(&ehdr), 1);
diff --git a/kexec/arch/ppc/kexec-ppc.c b/kexec/arch/ppc/kexec-ppc.c
index d7afad6..d9f1d05 100644
--- a/kexec/arch/ppc/kexec-ppc.c
+++ b/kexec/arch/ppc/kexec-ppc.c
@@ -27,9 +27,10 @@
 #include "config.h"
 
 uint64_t rmo_top;
-unsigned long long crash_base, crash_size;
-unsigned long long initrd_base, initrd_size;
-unsigned long long devicetree_base, devicetree_size;
+unsigned long long crash_base = 0, crash_size = 0;
+unsigned long long initrd_base = 0, initrd_size = 0;
+unsigned long long ramdisk_base = 0, ramdisk_size = 0;
+unsigned long long devicetree_base = 0, devicetree_size = 0;
 unsigned int rtas_base, rtas_size;
 int max_memory_ranges;
 
-- 
1.6.0.6

^ permalink raw reply related

* Re: [PATCH 8/8] v3 Update memory-hotplug documentation
From: Dave Hansen @ 2010-07-20 19:23 UTC (permalink / raw)
  To: Nathan Fontenot
  Cc: linux-mm, greg, linux-kernel, KAMEZAWA Hiroyuki, linuxppc-dev
In-Reply-To: <4C451F3F.8000207@austin.ibm.com>

On Mon, 2010-07-19 at 22:59 -0500, Nathan Fontenot wrote:
> 
> 
> -Now, XXX is defined as start_address_of_section / section_size.
> +Now, XXX is defined as (start_address_of_section / section_size) of
> the first
> +section conatined in the memory block.
> 
>  For example, assume 1GiB section size. A device for a memory starting
> at
>  0x100000000 is /sys/device/system/memory/memory4
>  (0x100000000 / 1Gib = 4)
>  This device covers address range [0x100000000 ... 0x140000000)
> 
> -Under each section, you can see 4 files.
> +Under each section, you can see 5 files.
> 
> -/sys/devices/system/memory/memoryXXX/phys_index
> +/sys/devices/system/memory/memoryXXX/start_phys_index
> +/sys/devices/system/memory/memoryXXX/end_phys_index 

Just wanted to make sure you didn't forget to update this after KAME's
comments on the first couple of patches.


-- Dave

^ permalink raw reply

* Re: [PATCH 4/8] v3 Allow memory_block to span multiple memory sections
From: Dave Hansen @ 2010-07-20 19:21 UTC (permalink / raw)
  To: Nathan Fontenot
  Cc: linux-mm, greg, linux-kernel, KAMEZAWA Hiroyuki, linuxppc-dev
In-Reply-To: <4C451E1C.8070907@austin.ibm.com>

On Mon, 2010-07-19 at 22:55 -0500, Nathan Fontenot wrote:
> +static u32 get_memory_block_size(void)
> +{
> +       u32 block_sz;
> +
> +       block_sz = memory_block_size_bytes();
> +
> +       /* Validate blk_sz is a power of 2 and not less than section size */
> +       if ((block_sz & (block_sz - 1)) || (block_sz < MIN_MEMORY_BLOCK_SIZE))
> +               block_sz = MIN_MEMORY_BLOCK_SIZE;

Is this worth a WARN_ON()?  Seems pretty bogus if someone is returning
funky block sizes.  

-- Dave

^ permalink raw reply

* Re: [PATCH 4/8] v3 Allow memory_block to span multiple memory sections
From: Dave Hansen @ 2010-07-20 19:18 UTC (permalink / raw)
  To: Nathan Fontenot
  Cc: linux-mm, greg, linux-kernel, KAMEZAWA Hiroyuki, linuxppc-dev
In-Reply-To: <4C451E1C.8070907@austin.ibm.com>

On Mon, 2010-07-19 at 22:55 -0500, Nathan Fontenot wrote:
> +static int add_memory_section(int nid, struct mem_section *section,
> +                       unsigned long state, enum mem_add_context context)
> +{
> +       struct memory_block *mem;
> +       int ret = 0;
> +
> +       mem = find_memory_block(section);
> +       if (mem) {
> +               atomic_inc(&mem->section_count);
> +               kobject_put(&mem->sysdev.kobj);
> +       } else
> +               ret = init_memory_block(&mem, section, state);
> +
>         if (!ret) {
> -               if (context == HOTPLUG)
> +               if (context == HOTPLUG &&
> +                   atomic_read(&mem->section_count) == sections_per_block)
>                         ret = register_mem_sect_under_node(mem, nid);
>         } 

I think the atomic_inc() can race with the atomic_dec_and_test() in
remove_memory_block().

Thread 1 does:

	mem = find_memory_block(section);

Thread 2 does 

	atomic_dec_and_test(&mem->section_count);

and destroys the memory block,  Thread 1 runs again:
	
       if (mem) {
               atomic_inc(&mem->section_count);
               kobject_put(&mem->sysdev.kobj);
       } else

but now mem got destroyed by Thread 2.  You probably need to change
find_memory_block() to itself take a reference, and to use
atomic_inc_unless().

-- Dave

^ permalink raw reply

* Re: [PATCH 2/8] v3 Add new phys_index properties
From: Dave Hansen @ 2010-07-20 19:10 UTC (permalink / raw)
  To: Nathan Fontenot
  Cc: linux-mm, greg, linux-kernel, KAMEZAWA Hiroyuki, linuxppc-dev
In-Reply-To: <4C45A3AB.6090407@austin.ibm.com>

On Tue, 2010-07-20 at 08:24 -0500, Nathan Fontenot wrote:
> Update the 'phys_index' properties of a memory block to include a
> 'start_phys_index' which is the same as the current 'phys_index' property.
> This also adds an 'end_phys_index' property to indicate the id of the
> last section in th memory block.
> 
> Patch updated to keep the name of the phys_index property instead of
> renaming it to start_phys_index.

KAME is right on this.  We should keep the old one if at all possible.  

The only other thing we might want to do is move 'phys_index' to
'start_phys_index', and make a new 'phys_index' that does a WARN_ONCE(),
gives a deprecated warning, then calls the new 'start_phys_index' code.

So, basically make the new, more clear name, but keep the old one for a
while and deprecate it.  Maybe we could get away with removing it in ten
years. :)

-- Dave

^ permalink raw reply

* RT Kernel crash in SMP mode on Marvell board
From: Manikandan Ramachandran @ 2010-07-20 18:15 UTC (permalink / raw)
  To: linuxppc-dev

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

Hello All,

   I'm trying to bring up a Marvell board [db644xx] with dual CPU[7447A]
with kernel 2.6.33.5-rt23[Ingo's RT patch]. For conveniance I have
registered IPI interrupt with IRQF_NODELAY flag, all other interrupts are
threaded. I'm able to boot up the system fine, however after few hours I see
random kernel crash in Marvell's PIC module. I understand that the RT kernel
doesn't like the way spinlock is used, I tried to convert to raw_spin_lock,
but the system would get frozen. I can make the system stable by just not
using any locks, but thats not an ideal solution. Can someone please suggest
a better locking mechanism? Crash dump I have given below:

NIP: 00000000 LR: 70030258 CTR: 00000000
REGS: deeebcf0 TRAP: 0400   Tainted: P            (2.6.33.5-rt23)
MSR: 40001032 <ME,IR,DR>  CR: 24004024  XER: 20000004
TASK = df915240[788] 'irq/74-ide0' THREAD: deeea000 CPU: 1
GPR00: 70030390 deeebda0 df915240 72e17ac0 703683f8 00000001 00000000
645d28e8
GPR08: 00000000 00000000 00000000 00000005 46f0b20f 00000000 00fe4600
007fff00
GPR16: 04000000 003d4ba2 007ffeb0 00800000 00ff690c 03000040 00f7eba2
deeebf6c
GPR24: 00000001 00000000 00000000 deeea000 72e17ac0 00000000 703683f8
703683f8
NIP [00000000] (null)
LR [70030258] enqueue_task+0x3c/0x58
Call Trace:
[deeebda0] [0000001e] 0x1e (unreliable)
[deeebdb0] [70030390] activate_task+0x40/0x60
[deeebdc0] [70036850] try_to_wake_up+0x248/0x334
[deeebe00] [70069380] wakeup_next_waiter+0x148/0x14c
[deeebe20] [7029b1d4] rt_spin_lock_slowunlock+0x60/0x84
[deeebe30] [7001a168] marvell_disable_IPI_irq+0xfc/0x110
[deeebe50] [70073934] handle_level_irq+0x40/0x15c
[deeebe70] [70006418] do_IRQ+0xc8/0xf4
[deeebe90] [7001276c] ret_from_except+0x0/0x14
--- Exception: 501 at schedule+0x30/0x50
    LR = schedule+0x24/0x50
[deeebf60] [700717bc] irq_thread+0x98/0x230
[deeebfa0] [7005686c] kthread+0x78/0x7c
[deeebff0] [70011ef4] kernel_thread+0x4c/0x68
Instruction dump:
XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
Kernel panic - not syncing: Fatal exception in interrupt
Call Trace:
[deeebc20
---------------------------------------------------------------------------------------------------------------------

IRQ CONFIGs:

CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
# CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK is not set
CONFIG_IRQ_PER_CPU=y
CONFIG_NR_IRQS=512
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_TRACE_IRQFLAGS_SUPPORT=y

-- 
Thanks,
Manik

Think twice about a tree before you take a printout

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

^ permalink raw reply

* Re: [lm-sensors] [PATCH] hwmon: (tmp421) Add nfactor support (2nd attempt)
From: Andre Prendel @ 2010-07-20 15:09 UTC (permalink / raw)
  To: Jeff Angielski; +Cc: linuxppc-dev, lm-sensors
In-Reply-To: <20100520193556.GB2153@andre-laptop>

On Thu, May 20, 2010 at 09:35:56PM +0200, Andre Prendel wrote:
> On Thu, May 20, 2010 at 03:07:05PM -0400, Jeff Angielski wrote:
> > In any event, here it is again:
> 
> Acked-by: Andre Prendel <andre.prendel@gmx.de>

Hi Jeff,

I'de suggest to resend the patch with my acked-by to the lm-sensors list and
Andrew Morton. It looks like Jean is too busy at the moment.

Regards,
Andre
 
> > 
> > >From 9acd29ff48c64e58a7f5cdb888c86e737c56281c Mon Sep 17 00:00:00 2001
> > From: Jeff Angielski <jeff@theptrgroup.com>
> > Date: Mon, 10 May 2010 10:26:34 -0400
> > Subject: [PATCH] hwmon: (tmp421) Add nfactor support
> > 
> > Add support for reading and writing the n-factor correction
> > registers.  This is needed to compensate for the characteristics
> > of a particular sensor hanging off of the remote channels.
> > 
> > Signed-off-by: Jeff Angielski <jeff@theptrgroup.com>
> > ---
> >  Documentation/hwmon/tmp421 |   19 +++++++++++++++++++
> >  drivers/hwmon/tmp421.c     |   41 +++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 60 insertions(+), 0 deletions(-)
> > 
> > diff --git a/Documentation/hwmon/tmp421 b/Documentation/hwmon/tmp421
> > index 0cf07f8..668228a 100644
> > --- a/Documentation/hwmon/tmp421
> > +++ b/Documentation/hwmon/tmp421
> > @@ -17,6 +17,7 @@ Supported chips:
> >  
> >  Authors:
> >  	Andre Prendel <andre.prendel@gmx.de>
> > +	Jeff Angielski <jeff@theptrgroup.com>
> >  
> >  Description
> >  -----------
> > @@ -34,3 +35,21 @@ the temperature values via the following sysfs files:
> >  
> >  temp[1-4]_input
> >  temp[2-4]_fault
> > +
> > +The chips allow the user to adjust the n-factor value that is used
> > +when converting the remote channel measurements to temperature. The
> > +adjustment has a range of -128 to +127 that yields an effective
> > +n-factor range of 0.706542 to 1.747977.  The power on reset value
> > +for the adjustment is 0 which results in an n-factor of 1.008.
> > +
> > +The effective n-factor is calculated according to the following
> > +equation:
> > +
> > +n_factor = (1.008 * 300) / (300 - nfactor_adjust)
> > +
> > +The driver exports the n-factor adjustment value via the following 
> > +sysfs files:
> > +
> > +temp[2-4]_n_adjust
> > +
> > +
> > diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c
> > index 738c472..dfd62be 100644
> > --- a/drivers/hwmon/tmp421.c
> > +++ b/drivers/hwmon/tmp421.c
> > @@ -49,6 +49,7 @@ enum chips { tmp421, tmp422, tmp423 };
> >  
> >  static const u8 TMP421_TEMP_MSB[4]		= { 0x00, 0x01, 0x02, 0x03 };
> >  static const u8 TMP421_TEMP_LSB[4]		= { 0x10, 0x11, 0x12, 0x13 };
> > +static const u8 TMP421_N_CORRECT[3]		= { 0x21, 0x22, 0x23 };
> >  
> >  /* Flags */
> >  #define TMP421_CONFIG_SHUTDOWN			0x40
> > @@ -76,6 +77,7 @@ struct tmp421_data {
> >  	int channels;
> >  	u8 config;
> >  	s16 temp[4];
> > +	s8 n_adjust[3];
> >  };
> >  
> >  static int temp_from_s16(s16 reg)
> > @@ -115,6 +117,10 @@ static struct tmp421_data *tmp421_update_device(struct device *dev)
> >  			data->temp[i] |= i2c_smbus_read_byte_data(client,
> >  				TMP421_TEMP_LSB[i]);
> >  		}
> > +		for (i = 1; i < data->channels; i++) {
> > +			data->n_adjust[i - 1] = i2c_smbus_read_byte_data(client,
> > +				TMP421_N_CORRECT[i - 1]);
> > +		}
> >  		data->last_updated = jiffies;
> >  		data->valid = 1;
> >  	}
> > @@ -157,6 +163,32 @@ static ssize_t show_fault(struct device *dev,
> >  		return sprintf(buf, "0\n");
> >  }
> >  
> > +static ssize_t show_n_adjust(struct device *dev,
> > +			     struct device_attribute *devattr, char *buf)
> > +{
> > +	int index = to_sensor_dev_attr(devattr)->index;
> > +	struct tmp421_data *data = tmp421_update_device(dev);
> > +
> > +	return sprintf(buf, "%d\n", data->n_adjust[index - 1]);
> > +}
> > +
> > +static ssize_t set_n_adjust(struct device *dev,
> > +			    struct device_attribute *devattr,
> > +			    const char *buf, size_t count)
> > +{
> > +	struct i2c_client *client = to_i2c_client(dev);
> > +	struct tmp421_data *data = i2c_get_clientdata(client);
> > +	int index = to_sensor_dev_attr(devattr)->index;
> > +	int n_adjust = simple_strtol(buf, NULL, 10);
> > +
> > +	mutex_lock(&data->update_lock);
> > +	i2c_smbus_write_byte_data(client, TMP421_N_CORRECT[index - 1],
> > +				  SENSORS_LIMIT(n_adjust, -128, 127));
> > +	mutex_unlock(&data->update_lock);
> > +
> > +	return count;
> > +}
> > +
> >  static mode_t tmp421_is_visible(struct kobject *kobj, struct attribute *a,
> >  				int n)
> >  {
> > @@ -177,19 +209,28 @@ static mode_t tmp421_is_visible(struct kobject *kobj, struct attribute *a,
> >  static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_value, NULL, 0);
> >  static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_value, NULL, 1);
> >  static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_fault, NULL, 1);
> > +static SENSOR_DEVICE_ATTR(temp2_n_adjust, S_IRUSR | S_IWUSR | S_IRGRP,
> > +			  show_n_adjust, set_n_adjust, 1);
> >  static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_value, NULL, 2);
> >  static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_fault, NULL, 2);
> > +static SENSOR_DEVICE_ATTR(temp3_n_adjust, S_IRUSR | S_IWUSR | S_IRGRP,
> > +			  show_n_adjust, set_n_adjust, 2);
> >  static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_value, NULL, 3);
> >  static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_fault, NULL, 3);
> > +static SENSOR_DEVICE_ATTR(temp4_n_adjust, S_IRUSR | S_IWUSR | S_IRGRP,
> > +			  show_n_adjust, set_n_adjust, 3);
> >  
> >  static struct attribute *tmp421_attr[] = {
> >  	&sensor_dev_attr_temp1_input.dev_attr.attr,
> >  	&sensor_dev_attr_temp2_input.dev_attr.attr,
> >  	&sensor_dev_attr_temp2_fault.dev_attr.attr,
> > +	&sensor_dev_attr_temp2_n_adjust.dev_attr.attr,
> >  	&sensor_dev_attr_temp3_input.dev_attr.attr,
> >  	&sensor_dev_attr_temp3_fault.dev_attr.attr,
> > +	&sensor_dev_attr_temp3_n_adjust.dev_attr.attr,
> >  	&sensor_dev_attr_temp4_input.dev_attr.attr,
> >  	&sensor_dev_attr_temp4_fault.dev_attr.attr,
> > +	&sensor_dev_attr_temp4_n_adjust.dev_attr.attr,
> >  	NULL
> >  };
> >  
> > -- 
> > 1.7.0.4
> > 
> > 
> > -- 
> > Jeff Angielski
> > The PTR Group
> > www.theptrgroup.com
> > 
> > _______________________________________________
> > lm-sensors mailing list
> > lm-sensors@lm-sensors.org
> > http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
> 
> _______________________________________________
> lm-sensors mailing list
> lm-sensors@lm-sensors.org
> http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply

* Re: [PATCH] math-emu: correct test for downshifting fraction in _FP_FROM_INT()
From: Mikael Pettersson @ 2010-07-20 13:35 UTC (permalink / raw)
  To: Mikael Pettersson
  Cc: linux-s390, linux-sh, linux-kernel, linuxppc-dev, linux-alpha,
	sparclinux
In-Reply-To: <19524.51858.992299.119315@pilspetsen.it.uu.se>

Mikael Pettersson writes:
 > The kernel's math-emu code contains a macro _FP_FROM_INT() which is
 > used to convert an integer to a raw normalized floating-point value.
 > It does this basically in three steps:
 > 
 > 1. Compute the exponent from the number of leading zero bits.
 > 2. Downshift large fractions to put the MSB in the right position
 >    for normalized fractions.
 > 3. Upshift small fractions to put the MSB in the right position.
 > 
 > There is an boundary error in step 2, causing a fraction with its
 > MSB exactly one bit above the normalized MSB position to not be
 > downshifted.  This results in a non-normalized raw float, which when
 > packed becomes a massively inaccurate representation for that input.
 > 
 > The impact of this depends on a number of arch-specific factors,
 > but it is known to have broken emulation of FXTOD instructions
 > on UltraSPARC III, which was originally reported as GCC bug 44631
 > <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44631>.
 > 
 > Any arch which uses math-emu to emulate conversions from integers to
 > same-size floats may be affected.
 > 
 > The fix is simple: the exponent comparison used to determine if the
 > fraction should be downshifted must be "<=" not "<".
 > 
 > I'm sending a kernel module to test this as a reply to this message.
 > There are also SPARC user-space test cases in the GCC bug entry.
 > 
 > Signed-off-by: Mikael Pettersson <mikpe@it.uu.se>

I forgot to mention that this needs to be backported to older kernels,
so can the maintainer who picks this up please add

	Cc: stable@kernel.org

Thanks,

/Mikael

 > ---
 >  include/math-emu/op-common.h |    2 +-
 >  1 file changed, 1 insertion(+), 1 deletion(-)
 > 
 > diff -rupN linux-2.6.35-rc5/include/math-emu/op-common.h linux-2.6.35-rc5.mathemu-FP_FROM_INT-fraction-downshift-condition/include/math-emu/op-common.h
 > --- linux-2.6.35-rc5/include/math-emu/op-common.h	2010-05-17 19:51:32.000000000 +0200
 > +++ linux-2.6.35-rc5.mathemu-FP_FROM_INT-fraction-downshift-condition/include/math-emu/op-common.h	2010-07-18 22:33:46.000000000 +0200
 > @@ -799,7 +799,7 @@ do {									\
 >  		X##_e -= (_FP_W_TYPE_SIZE - rsize);			\
 >  	X##_e = rsize - X##_e - 1;					\
 >  									\
 > -	if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs < X##_e)	\
 > +	if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs <= X##_e)	\
 >  	  __FP_FRAC_SRS_1(ur_, (X##_e - _FP_WFRACBITS_##fs + 1), rsize);\
 >  	_FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize);			\
 >  	if ((_FP_WFRACBITS_##fs - X##_e - 1) > 0)			\
 > --
 > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
 > the body of a message to majordomo@vger.kernel.org
 > More majordomo info at  http://vger.kernel.org/majordomo-info.html
 > Please read the FAQ at  http://www.tux.org/lkml/
 > 

^ permalink raw reply

* Re: [PATCH 4/8] v3 Allow memory_block to span multiple memory sections
From: Nathan Fontenot @ 2010-07-20 13:28 UTC (permalink / raw)
  To: linux-kernel, linux-mm, linuxppc-dev; +Cc: greg, KAMEZAWA Hiroyuki
In-Reply-To: <4C451E1C.8070907@austin.ibm.com>

Update the memory sysfs code that each sysfs memory directory is now
considered a memory block that can contain multiple memory sections per
memory block.  The default size of each memory block is SECTION_SIZE_BITS
to maintain the current behavior of having a single memory section per
memory block (i.e. one sysfs directory per memory section).

For architectures that want to have memory blocks span multiple
memory sections they need only define their own memory_block_size_bytes()
routine.

Patch refreshed to apply cleanly with previous two patch updates.

Signed-off-by: Nathan Fontenot <nfont@austin.ibm.com>
---
 drivers/base/memory.c |  141 ++++++++++++++++++++++++++++++++++----------------
 1 file changed, 98 insertions(+), 43 deletions(-)

Index: linux-2.6/drivers/base/memory.c
===================================================================
--- linux-2.6.orig/drivers/base/memory.c	2010-07-20 06:43:29.000000000 -0500
+++ linux-2.6/drivers/base/memory.c	2010-07-20 06:44:30.000000000 -0500
@@ -28,6 +28,14 @@
 #include <asm/uaccess.h>
 
 #define MEMORY_CLASS_NAME	"memory"
+#define MIN_MEMORY_BLOCK_SIZE	(1 << SECTION_SIZE_BITS)
+
+static int sections_per_block;
+
+static inline int base_memory_block_id(int section_nr)
+{
+	return (section_nr / sections_per_block) * sections_per_block;
+}
 
 static struct sysdev_class memory_sysdev_class = {
 	.name = MEMORY_CLASS_NAME,
@@ -82,22 +90,21 @@ EXPORT_SYMBOL(unregister_memory_isolate_
  * register_memory - Setup a sysfs device for a memory block
  */
 static
-int register_memory(struct memory_block *memory, struct mem_section *section)
+int register_memory(struct memory_block *memory)
 {
 	int error;
 
 	memory->sysdev.cls = &memory_sysdev_class;
-	memory->sysdev.id = __section_nr(section);
+	memory->sysdev.id = memory->start_phys_index;
 
 	error = sysdev_register(&memory->sysdev);
 	return error;
 }
 
 static void
-unregister_memory(struct memory_block *memory, struct mem_section *section)
+unregister_memory(struct memory_block *memory)
 {
 	BUG_ON(memory->sysdev.cls != &memory_sysdev_class);
-	BUG_ON(memory->sysdev.id != __section_nr(section));
 
 	/* drop the ref. we got in remove_memory_block() */
 	kobject_put(&memory->sysdev.kobj);
@@ -131,13 +138,16 @@ static ssize_t show_mem_end_phys_index(s
 static ssize_t show_mem_removable(struct sys_device *dev,
 			struct sysdev_attribute *attr, char *buf)
 {
-	unsigned long start_pfn;
-	int ret;
+	unsigned long i, pfn;
+	int ret = 1;
 	struct memory_block *mem =
 		container_of(dev, struct memory_block, sysdev);
 
-	start_pfn = section_nr_to_pfn(mem->start_phys_index);
-	ret = is_mem_section_removable(start_pfn, PAGES_PER_SECTION);
+	for (i = mem->start_phys_index; i <= mem->end_phys_index; i++) {
+		pfn = section_nr_to_pfn(i);
+		ret &= is_mem_section_removable(pfn, PAGES_PER_SECTION);
+	}
+
 	return sprintf(buf, "%d\n", ret);
 }
 
@@ -190,17 +200,14 @@ int memory_isolate_notify(unsigned long
  * OK to have direct references to sparsemem variables in here.
  */
 static int
-memory_block_action(struct memory_block *mem, unsigned long action)
+memory_section_action(unsigned long phys_index, unsigned long action)
 {
 	int i;
-	unsigned long psection;
 	unsigned long start_pfn, start_paddr;
 	struct page *first_page;
 	int ret;
-	int old_state = mem->state;
 
-	psection = mem->start_phys_index;
-	first_page = pfn_to_page(psection << PFN_SECTION_SHIFT);
+	first_page = pfn_to_page(phys_index << PFN_SECTION_SHIFT);
 
 	/*
 	 * The probe routines leave the pages reserved, just
@@ -213,8 +220,8 @@ memory_block_action(struct memory_block
 				continue;
 
 			printk(KERN_WARNING "section number %ld page number %d "
-				"not reserved, was it already online? \n",
-				psection, i);
+				"not reserved, was it already online?\n",
+				phys_index, i);
 			return -EBUSY;
 		}
 	}
@@ -225,18 +232,13 @@ memory_block_action(struct memory_block
 			ret = online_pages(start_pfn, PAGES_PER_SECTION);
 			break;
 		case MEM_OFFLINE:
-			mem->state = MEM_GOING_OFFLINE;
 			start_paddr = page_to_pfn(first_page) << PAGE_SHIFT;
 			ret = remove_memory(start_paddr,
 					    PAGES_PER_SECTION << PAGE_SHIFT);
-			if (ret) {
-				mem->state = old_state;
-				break;
-			}
 			break;
 		default:
-			WARN(1, KERN_WARNING "%s(%p, %ld) unknown action: %ld\n",
-					__func__, mem, action, action);
+			WARN(1, KERN_WARNING "%s(%ld, %ld) unknown action: "
+			     "%ld\n", __func__, phys_index, action, action);
 			ret = -EINVAL;
 	}
 
@@ -246,7 +248,7 @@ memory_block_action(struct memory_block
 static int memory_block_change_state(struct memory_block *mem,
 		unsigned long to_state, unsigned long from_state_req)
 {
-	int ret = 0;
+	int i, ret = 0;
 	mutex_lock(&mem->state_mutex);
 
 	if (mem->state != from_state_req) {
@@ -254,8 +256,21 @@ static int memory_block_change_state(str
 		goto out;
 	}
 
-	ret = memory_block_action(mem, to_state);
-	if (!ret)
+	if (to_state == MEM_OFFLINE)
+		mem->state = MEM_GOING_OFFLINE;
+
+	for (i = mem->start_phys_index; i <= mem->end_phys_index; i++) {
+		ret = memory_section_action(i, to_state);
+		if (ret)
+			break;
+	}
+
+	if (ret) {
+		for (i = mem->start_phys_index; i <= mem->end_phys_index; i++)
+			memory_section_action(i, from_state_req);
+
+		mem->state = from_state_req;
+	} else
 		mem->state = to_state;
 
 out:
@@ -268,20 +283,15 @@ store_mem_state(struct sys_device *dev,
 		struct sysdev_attribute *attr, const char *buf, size_t count)
 {
 	struct memory_block *mem;
-	unsigned int phys_section_nr;
 	int ret = -EINVAL;
 
 	mem = container_of(dev, struct memory_block, sysdev);
-	phys_section_nr = mem->start_phys_index;
-
-	if (!present_section_nr(phys_section_nr))
-		goto out;
 
 	if (!strncmp(buf, "online", min((int)count, 6)))
 		ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE);
 	else if(!strncmp(buf, "offline", min((int)count, 7)))
 		ret = memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE);
-out:
+
 	if (ret)
 		return ret;
 	return count;
@@ -458,12 +468,13 @@ struct memory_block *find_memory_block(s
 	struct sys_device *sysdev;
 	struct memory_block *mem;
 	char name[sizeof(MEMORY_CLASS_NAME) + 9 + 1];
+	int block_id = base_memory_block_id(__section_nr(section));
 
 	/*
 	 * This only works because we know that section == sysdev->id
 	 * slightly redundant with sysdev_register()
 	 */
-	sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, __section_nr(section));
+	sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, block_id);
 
 	kobj = kset_find_obj(&memory_sysdev_class.kset, name);
 	if (!kobj)
@@ -475,24 +486,26 @@ struct memory_block *find_memory_block(s
 	return mem;
 }
 
-static int add_memory_block(int nid, struct mem_section *section,
-			unsigned long state, enum mem_add_context context)
+static int init_memory_block(struct memory_block **memory,
+			     struct mem_section *section, unsigned long state)
 {
-	struct memory_block *mem = kzalloc(sizeof(*mem), GFP_KERNEL);
+	struct memory_block *mem;
 	unsigned long start_pfn;
 	int ret = 0;
 
+	mem = kzalloc(sizeof(*mem), GFP_KERNEL);
 	if (!mem)
 		return -ENOMEM;
 
-	mem->start_phys_index = __section_nr(section);
+	mem->start_phys_index = base_memory_block_id(__section_nr(section));
+	mem->end_phys_index = mem->start_phys_index + sections_per_block - 1;
 	mem->state = state;
 	atomic_inc(&mem->section_count);
 	mutex_init(&mem->state_mutex);
 	start_pfn = section_nr_to_pfn(mem->start_phys_index);
 	mem->phys_device = arch_get_memory_phys_device(start_pfn);
 
-	ret = register_memory(mem, section);
+	ret = register_memory(mem);
 	if (!ret)
 		ret = mem_create_simple_file(mem, phys_index);
 	if (!ret)
@@ -503,8 +516,27 @@ static int add_memory_block(int nid, str
 		ret = mem_create_simple_file(mem, phys_device);
 	if (!ret)
 		ret = mem_create_simple_file(mem, removable);
+
+	*memory = mem;
+	return ret;
+}
+
+static int add_memory_section(int nid, struct mem_section *section,
+			unsigned long state, enum mem_add_context context)
+{
+	struct memory_block *mem;
+	int ret = 0;
+
+	mem = find_memory_block(section);
+	if (mem) {
+		atomic_inc(&mem->section_count);
+		kobject_put(&mem->sysdev.kobj);
+	} else
+		ret = init_memory_block(&mem, section, state);
+
 	if (!ret) {
-		if (context == HOTPLUG)
+		if (context == HOTPLUG &&
+		    atomic_read(&mem->section_count) == sections_per_block)
 			ret = register_mem_sect_under_node(mem, nid);
 	}
 
@@ -525,8 +557,9 @@ int remove_memory_block(unsigned long no
 		mem_remove_simple_file(mem, state);
 		mem_remove_simple_file(mem, phys_device);
 		mem_remove_simple_file(mem, removable);
-		unregister_memory(mem, section);
-	}
+		unregister_memory(mem);
+	} else
+		kobject_put(&mem->sysdev.kobj);
 
 	return 0;
 }
@@ -537,7 +570,7 @@ int remove_memory_block(unsigned long no
  */
 int register_new_memory(int nid, struct mem_section *section)
 {
-	return add_memory_block(nid, section, MEM_OFFLINE, HOTPLUG);
+	return add_memory_section(nid, section, MEM_OFFLINE, HOTPLUG);
 }
 
 int unregister_memory_section(struct mem_section *section)
@@ -548,6 +581,24 @@ int unregister_memory_section(struct mem
 	return remove_memory_block(0, section, 0);
 }
 
+u32 __weak memory_block_size_bytes(void)
+{
+	return MIN_MEMORY_BLOCK_SIZE;
+}
+
+static u32 get_memory_block_size(void)
+{
+	u32 block_sz;
+
+	block_sz = memory_block_size_bytes();
+
+	/* Validate blk_sz is a power of 2 and not less than section size */
+	if ((block_sz & (block_sz - 1)) || (block_sz < MIN_MEMORY_BLOCK_SIZE))
+		block_sz = MIN_MEMORY_BLOCK_SIZE;
+
+	return block_sz;
+}
+
 /*
  * Initialize the sysfs support for memory devices...
  */
@@ -556,12 +607,16 @@ int __init memory_dev_init(void)
 	unsigned int i;
 	int ret;
 	int err;
+	int block_sz;
 
 	memory_sysdev_class.kset.uevent_ops = &memory_uevent_ops;
 	ret = sysdev_class_register(&memory_sysdev_class);
 	if (ret)
 		goto out;
 
+	block_sz = get_memory_block_size();
+	sections_per_block = block_sz / MIN_MEMORY_BLOCK_SIZE;
+
 	/*
 	 * Create entries for memory sections that were found
 	 * during boot and have been initialized
@@ -569,8 +624,8 @@ int __init memory_dev_init(void)
 	for (i = 0; i < NR_MEM_SECTIONS; i++) {
 		if (!present_section_nr(i))
 			continue;
-		err = add_memory_block(0, __nr_to_section(i), MEM_ONLINE,
-				       BOOT);
+		err = add_memory_section(0, __nr_to_section(i), MEM_ONLINE,
+					 BOOT);
 		if (!ret)
 			ret = err;
 	}

^ permalink raw reply

* Re: [PATCH 3/8] v3 Add section count to memory_block
From: Nathan Fontenot @ 2010-07-20 13:26 UTC (permalink / raw)
  To: linux-kernel, linux-mm, linuxppc-dev; +Cc: greg, KAMEZAWA Hiroyuki
In-Reply-To: <4C451DD6.3080005@austin.ibm.com>

Add a section count property to the memory_block struct to track the number
of memory sections that have been added/removed from a memory block.  Updated
to use atomic_dec_and_test().

Signed-off-by: Nathan Fontenot <nfont@asutin.ibm.com>
---
 drivers/base/memory.c  |   18 +++++++++++-------
 include/linux/memory.h |    2 ++
 2 files changed, 13 insertions(+), 7 deletions(-)

Index: linux-2.6/drivers/base/memory.c
===================================================================
--- linux-2.6.orig/drivers/base/memory.c	2010-07-20 06:38:21.000000000 -0500
+++ linux-2.6/drivers/base/memory.c	2010-07-20 06:43:29.000000000 -0500
@@ -487,6 +487,7 @@ static int add_memory_block(int nid, str
 
 	mem->start_phys_index = __section_nr(section);
 	mem->state = state;
+	atomic_inc(&mem->section_count);
 	mutex_init(&mem->state_mutex);
 	start_pfn = section_nr_to_pfn(mem->start_phys_index);
 	mem->phys_device = arch_get_memory_phys_device(start_pfn);
@@ -516,13 +517,16 @@ int remove_memory_block(unsigned long no
 	struct memory_block *mem;
 
 	mem = find_memory_block(section);
-	unregister_mem_sect_under_nodes(mem);
-	mem_remove_simple_file(mem, phys_index);
-	mem_remove_simple_file(mem, end_phys_index);
-	mem_remove_simple_file(mem, state);
-	mem_remove_simple_file(mem, phys_device);
-	mem_remove_simple_file(mem, removable);
-	unregister_memory(mem, section);
+
+	if (atomic_dec_and_test(&mem->section_count)) {
+		unregister_mem_sect_under_nodes(mem);
+		mem_remove_simple_file(mem, phys_index);
+		mem_remove_simple_file(mem, end_phys_index);
+		mem_remove_simple_file(mem, state);
+		mem_remove_simple_file(mem, phys_device);
+		mem_remove_simple_file(mem, removable);
+		unregister_memory(mem, section);
+	}
 
 	return 0;
 }
Index: linux-2.6/include/linux/memory.h
===================================================================
--- linux-2.6.orig/include/linux/memory.h	2010-07-20 06:35:38.000000000 -0500
+++ linux-2.6/include/linux/memory.h	2010-07-20 06:38:59.000000000 -0500
@@ -19,11 +19,13 @@
 #include <linux/node.h>
 #include <linux/compiler.h>
 #include <linux/mutex.h>
+#include <asm/atomic.h>
 
 struct memory_block {
 	unsigned long start_phys_index;
 	unsigned long end_phys_index;
 	unsigned long state;
+	atomic_t section_count;
 	/*
 	 * This serializes all state change requests.  It isn't
 	 * held during creation because the control files are

^ permalink raw reply

* Re: [PATCH 2/8] v3 Add new phys_index properties
From: Nathan Fontenot @ 2010-07-20 13:24 UTC (permalink / raw)
  To: linux-kernel, linux-mm, linuxppc-dev; +Cc: greg, KAMEZAWA Hiroyuki
In-Reply-To: <4C451D92.6020406@austin.ibm.com>

Update the 'phys_index' properties of a memory block to include a
'start_phys_index' which is the same as the current 'phys_index' property.
This also adds an 'end_phys_index' property to indicate the id of the
last section in th memory block.

Patch updated to keep the name of the phys_index property instead of
renaming it to start_phys_index.

Signed-off-by: Nathan Fontenot <nfont@austin.ibm.com>
---
 drivers/base/memory.c  |   28 ++++++++++++++++++++--------
 include/linux/memory.h |    3 ++-
 2 files changed, 22 insertions(+), 9 deletions(-)

Index: linux-2.6/drivers/base/memory.c
===================================================================
--- linux-2.6.orig/drivers/base/memory.c	2010-07-19 20:42:11.000000000 -0500
+++ linux-2.6/drivers/base/memory.c	2010-07-20 06:38:21.000000000 -0500
@@ -109,12 +109,20 @@ unregister_memory(struct memory_block *m
  * uses.
  */
 
-static ssize_t show_mem_phys_index(struct sys_device *dev,
+static ssize_t show_mem_start_phys_index(struct sys_device *dev,
 			struct sysdev_attribute *attr, char *buf)
 {
 	struct memory_block *mem =
 		container_of(dev, struct memory_block, sysdev);
-	return sprintf(buf, "%08lx\n", mem->phys_index);
+	return sprintf(buf, "%08lx\n", mem->start_phys_index);
+}
+
+static ssize_t show_mem_end_phys_index(struct sys_device *dev,
+			struct sysdev_attribute *attr, char *buf)
+{
+	struct memory_block *mem =
+		container_of(dev, struct memory_block, sysdev);
+	return sprintf(buf, "%08lx\n", mem->end_phys_index);
 }
 
 /*
@@ -128,7 +136,7 @@ static ssize_t show_mem_removable(struct
 	struct memory_block *mem =
 		container_of(dev, struct memory_block, sysdev);
 
-	start_pfn = section_nr_to_pfn(mem->phys_index);
+	start_pfn = section_nr_to_pfn(mem->start_phys_index);
 	ret = is_mem_section_removable(start_pfn, PAGES_PER_SECTION);
 	return sprintf(buf, "%d\n", ret);
 }
@@ -191,7 +199,7 @@ memory_block_action(struct memory_block
 	int ret;
 	int old_state = mem->state;
 
-	psection = mem->phys_index;
+	psection = mem->start_phys_index;
 	first_page = pfn_to_page(psection << PFN_SECTION_SHIFT);
 
 	/*
@@ -264,7 +272,7 @@ store_mem_state(struct sys_device *dev,
 	int ret = -EINVAL;
 
 	mem = container_of(dev, struct memory_block, sysdev);
-	phys_section_nr = mem->phys_index;
+	phys_section_nr = mem->start_phys_index;
 
 	if (!present_section_nr(phys_section_nr))
 		goto out;
@@ -296,7 +304,8 @@ static ssize_t show_phys_device(struct s
 	return sprintf(buf, "%d\n", mem->phys_device);
 }
 
-static SYSDEV_ATTR(phys_index, 0444, show_mem_phys_index, NULL);
+static SYSDEV_ATTR(phys_index, 0444, show_mem_start_phys_index, NULL);
+static SYSDEV_ATTR(end_phys_index, 0444, show_mem_end_phys_index, NULL);
 static SYSDEV_ATTR(state, 0644, show_mem_state, store_mem_state);
 static SYSDEV_ATTR(phys_device, 0444, show_phys_device, NULL);
 static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL);
@@ -476,16 +485,18 @@ static int add_memory_block(int nid, str
 	if (!mem)
 		return -ENOMEM;
 
-	mem->phys_index = __section_nr(section);
+	mem->start_phys_index = __section_nr(section);
 	mem->state = state;
 	mutex_init(&mem->state_mutex);
-	start_pfn = section_nr_to_pfn(mem->phys_index);
+	start_pfn = section_nr_to_pfn(mem->start_phys_index);
 	mem->phys_device = arch_get_memory_phys_device(start_pfn);
 
 	ret = register_memory(mem, section);
 	if (!ret)
 		ret = mem_create_simple_file(mem, phys_index);
 	if (!ret)
+		ret = mem_create_simple_file(mem, end_phys_index);
+	if (!ret)
 		ret = mem_create_simple_file(mem, state);
 	if (!ret)
 		ret = mem_create_simple_file(mem, phys_device);
@@ -507,6 +518,7 @@ int remove_memory_block(unsigned long no
 	mem = find_memory_block(section);
 	unregister_mem_sect_under_nodes(mem);
 	mem_remove_simple_file(mem, phys_index);
+	mem_remove_simple_file(mem, end_phys_index);
 	mem_remove_simple_file(mem, state);
 	mem_remove_simple_file(mem, phys_device);
 	mem_remove_simple_file(mem, removable);
Index: linux-2.6/include/linux/memory.h
===================================================================
--- linux-2.6.orig/include/linux/memory.h	2010-07-19 20:42:11.000000000 -0500
+++ linux-2.6/include/linux/memory.h	2010-07-20 06:35:38.000000000 -0500
@@ -21,7 +21,8 @@
 #include <linux/mutex.h>
 
 struct memory_block {
-	unsigned long phys_index;
+	unsigned long start_phys_index;
+	unsigned long end_phys_index;
 	unsigned long state;
 	/*
 	 * This serializes all state change requests.  It isn't

^ permalink raw reply


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