LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH 4/7] KVM: PPC: Add book3s_32 tlbie flush acceleration
From: Avi Kivity @ 2010-08-01 14:08 UTC (permalink / raw)
  To: Alexander Graf; +Cc: linuxppc-dev, KVM list, kvm-ppc
In-Reply-To: <1280408662-10328-5-git-send-email-agraf@suse.de>

  On 07/29/2010 04:04 PM, Alexander Graf wrote:
> On Book3s_32 the tlbie instruction flushed effective addresses by the mask
> 0x0ffff000. This is pretty hard to reflect with a hash that hashes ~0xfff, so
> to speed up that target we should also keep a special hash around for it.
>
>
>   static inline u64 kvmppc_mmu_hash_vpte(u64 vpage)
>   {
>   	return hash_64(vpage&  0xfffffffffULL, HPTEG_HASH_BITS_VPTE);
> @@ -66,6 +72,11 @@ void kvmppc_mmu_hpte_cache_map(struct kvm_vcpu *vcpu, struct hpte_cache *pte)
>   	index = kvmppc_mmu_hash_pte(pte->pte.eaddr);
>   	hlist_add_head_rcu(&pte->list_pte,&vcpu->arch.hpte_hash_pte[index]);
>
> +	/* Add to ePTE_long list */
> +	index = kvmppc_mmu_hash_pte_long(pte->pte.eaddr);
> +	hlist_add_head_rcu(&pte->list_pte_long,
> +			&vcpu->arch.hpte_hash_pte_long[index]);
> +

Isn't it better to make operations on this list conditional on 
Book3s_32?  Hashes are expensive since they usually cost cache misses.

Can of course be done later as an optimization.

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

^ permalink raw reply

* Re: [PATCH 0/7] Rest of my KVM-PPC patch queue
From: Avi Kivity @ 2010-08-01 14:09 UTC (permalink / raw)
  To: Alexander Graf; +Cc: linuxppc-dev, KVM list, kvm-ppc
In-Reply-To: <1280408662-10328-1-git-send-email-agraf@suse.de>

  On 07/29/2010 04:04 PM, Alexander Graf wrote:
> During the past few weeks a couple of fixes have gathered in my queue. This
> is a dump of everything that is not related to the PV framework.
>
> Please apply on top of the PV stuff.
>

Looks reasonable as well.  I'll apply as soon as I get a review on the 
previous patchset.

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

^ permalink raw reply

* Re: [PATCH 4/7] KVM: PPC: Add book3s_32 tlbie flush acceleration
From: Alexander Graf @ 2010-08-01 20:20 UTC (permalink / raw)
  To: Avi Kivity; +Cc: linuxppc-dev, KVM list, kvm-ppc
In-Reply-To: <4C557FF1.4000400@redhat.com>


On 01.08.2010, at 16:08, Avi Kivity wrote:

> On 07/29/2010 04:04 PM, Alexander Graf wrote:
>> On Book3s_32 the tlbie instruction flushed effective addresses by the =
mask
>> 0x0ffff000. This is pretty hard to reflect with a hash that hashes =
~0xfff, so
>> to speed up that target we should also keep a special hash around for =
it.
>>=20
>>=20
>>  static inline u64 kvmppc_mmu_hash_vpte(u64 vpage)
>>  {
>>  	return hash_64(vpage&  0xfffffffffULL, HPTEG_HASH_BITS_VPTE);
>> @@ -66,6 +72,11 @@ void kvmppc_mmu_hpte_cache_map(struct kvm_vcpu =
*vcpu, struct hpte_cache *pte)
>>  	index =3D kvmppc_mmu_hash_pte(pte->pte.eaddr);
>>  	=
hlist_add_head_rcu(&pte->list_pte,&vcpu->arch.hpte_hash_pte[index]);
>>=20
>> +	/* Add to ePTE_long list */
>> +	index =3D kvmppc_mmu_hash_pte_long(pte->pte.eaddr);
>> +	hlist_add_head_rcu(&pte->list_pte_long,
>> +			&vcpu->arch.hpte_hash_pte_long[index]);
>> +
>=20
> Isn't it better to make operations on this list conditional on =
Book3s_32?  Hashes are expensive since they usually cost cache misses.

Yes, the same for vpte_long and vpte - book3s_32 guests don't need them =
except for the all flush. The tough part is that this is not host but =
guest dependent, so I need to have different structs for book3s_32 and =
book3s_64 guests. This isn't a big issue, but complicates the code.

> Can of course be done later as an optimization.

Yes, that was the plan. Great to see you got the same feeling there =
though :). To be honest, I even started a book3s_32 host optimization =
patch and threw it away because it made the code less readable. So yes, =
this is on my radar.


Alex

^ permalink raw reply

* Re: [PATCH 00/27] KVM PPC PV framework v3
From: Alexander Graf @ 2010-08-01 20:21 UTC (permalink / raw)
  To: Avi Kivity; +Cc: KVM list, linuxppc-dev, kvm-ppc
In-Reply-To: <4C557E7A.3010606@redhat.com>


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

> On 07/29/2010 03:47 PM, Alexander Graf wrote:
>> On PPC we run PR=3D0 (kernel mode) code in PR=3D1 (user mode) and =
don't use the
>> hypervisor extensions.
>>=20
>> While that is all great to show that virtualization is possible, =
there are
>> quite some cases where the emulation overhead of privileged =
instructions is
>> killing performance.
>>=20
>> This patchset tackles exactly that issue. It introduces a paravirtual =
framework
>> using which KVM and Linux share a page to exchange register state =
with. That
>> way we don't have to switch to the hypervisor just to change a value =
of a
>> privileged register.
>>=20
>> To prove my point, I ran the same test I did for the MMU =
optimizations against
>> the PV framework. Here are the results:
>>=20
>> [without]
>>=20
>> debian-powerpc:~# time for i in {1..1000}; do /bin/echo hello>  =
/dev/null; done
>>=20
>> real    0m14.659s
>> user    0m8.967s
>> sys     0m5.688s
>>=20
>> [with]
>>=20
>> debian-powerpc:~# time for i in {1..1000}; do /bin/echo hello>  =
/dev/null; done
>>=20
>> real    0m7.557s
>> user    0m4.121s
>> sys     0m3.426s
>>=20
>>=20
>> So this is a significant performance improvement! I'm quite happy how =
fast this
>> whole thing becomes :)
>>=20
>> I tried to take all comments I've heard from people so far about such =
a PV
>> framework into account. In case you told me something before that is =
a no-go
>> and I still did it, please just tell me again.
>>=20
>> To make use of this whole thing you also need patches to qemu and =
openbios. I
>> have them in my queue, but want to see this set upstream first before =
I start
>> sending patches to the other projects.
>>=20
>> Now go and have fun with fast VMs on PPC! Get yourself a G5 on ebay =
and start
>> experiencing the power yourself. - heh
>>=20
>> v1 ->  v2:
>>=20
>>   - change hypervisor calls to use r0 and r3
>>   - make crit detection only trigger in supervisor mode
>>   - RMO ->  PAM
>>   - introduce kvm_patch_ins
>>   - only flush icache when patching
>>   - introduce kvm_patch_ins_b
>>   - update documentation
>>=20
>> v2 ->  v3:
>>=20
>>   - use pPAPR conventions for hypercall interface
>>   - only use r0 as magic sc number
>>   - remove PVR detection
>>   - remove BookE shared page mapping support
>>   - combine book3s-64 and -32 magic page ra override
>>   - add self-test check if the mapping works to guest code
>>   - add safety check for relocatable kernels
>>=20
>=20
> Looks reasonable.  Since it's fair to say I understand nothing about =
powerpc, I'd like someone who does to review it and ack, please, with an =
emphasis on the interfaces.

Sounds good. Preferably someone with access to the ePAPR spec :).


Alex

^ permalink raw reply

* [git pull] powerpc 5xxx and xilinx virtex changes
From: Grant Likely @ 2010-08-01 23:09 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, linuxppc-dev
  Cc: Albrecht Dreß, Anatolij Gustschin, Adrian Alonso

Hi Ben,

Here are the mpc5xxx and Xilinx virtex changes I've collected for the
2.6.36 merge window.  Please pull.

g.

The following changes since commit b37fa16e78d6f9790462b3181602a26b5af36260=
:
  Linus Torvalds (1):
        Linux 2.6.35-rc6

are available in the git repository at:

  git://git.secretlab.ca/git/linux-2.6 next

Adrian Alonso (1):
      of/xilinxfb: update tft compatible versions

Albrecht Dre=DF (2):
      powerpc/5200: improve uart baud rate calculation (reach high
baud rates, better accuracy)
      powerpc/5200/i2c: improve i2c bus error recovery

Anatolij Gustschin (8):
      powerpc/512x: Group mpc512x board's selection menu
      powerpc/5121: add initial support for PDM360NG board
      powerpc/512x: add clock structure for Video-IN (VIU) unit
      powerpc/5121: fsl-diu-fb: fix issue with re-enabling DIU area descrip=
tor
      powerpc/5121: move fsl-diu-fb.h to include/linux
      powerpc/5121: shared DIU framebuffer support
      powerpc/5121: doc/dts-bindings: update doc of FSL DIU bindings
      powerpc/fsl-diu-fb: Support setting display mode using EDID

 Documentation/powerpc/dts-bindings/fsl/diu.txt |   20 +-
 Documentation/powerpc/dts-bindings/fsl/i2c.txt |    2 +
 arch/powerpc/boot/dts/pdm360ng.dts             |  410 ++++++++++++++++++++=
++++
 arch/powerpc/include/asm/mpc5121.h             |   32 ++
 arch/powerpc/platforms/512x/Kconfig            |   20 +-
 arch/powerpc/platforms/512x/Makefile           |    1 +
 arch/powerpc/platforms/512x/clock.c            |   18 +
 arch/powerpc/platforms/512x/mpc5121_ads.c      |    2 +
 arch/powerpc/platforms/512x/mpc5121_generic.c  |    2 +
 arch/powerpc/platforms/512x/mpc512x.h          |    2 +
 arch/powerpc/platforms/512x/mpc512x_shared.c   |  284 ++++++++++++++++
 arch/powerpc/platforms/512x/pdm360ng.c         |  129 ++++++++
 arch/powerpc/sysdev/fsl_soc.h                  |    1 +
 drivers/i2c/busses/i2c-mpc.c                   |   69 +++--
 drivers/serial/mpc52xx_uart.c                  |  145 +++++++--
 drivers/video/Kconfig                          |    1 +
 drivers/video/fsl-diu-fb.c                     |  137 +++++++--
 drivers/video/xilinxfb.c                       |    2 +
 {drivers/video =3D> include/linux}/fsl-diu-fb.h  |    0
 19 files changed, 1191 insertions(+), 86 deletions(-)
 create mode 100644 arch/powerpc/boot/dts/pdm360ng.dts
 create mode 100644 arch/powerpc/platforms/512x/pdm360ng.c
 rename {drivers/video =3D> include/linux}/fsl-diu-fb.h (100%)


--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply

* [PATCH 02/11] powerpc/nvram: More flexible nvram_create_partition()
From: Benjamin Herrenschmidt @ 2010-08-02  0:55 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1280710522-6362-2-git-send-email-benh@kernel.crashing.org>

Replace nvram_create_os_partition() with a variant that takes
the partition name, signature and size as arguments.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/kernel/nvram_64.c         |   46 +++++++++++++++++++------------
 arch/powerpc/platforms/pseries/nvram.c |    6 ++--
 2 files changed, 31 insertions(+), 21 deletions(-)

diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index a8154f1..974b3ec 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -307,13 +307,15 @@ static int __init nvram_remove_os_partition(void)
 	return 0;
 }
 
-/* nvram_create_os_partition
- *
- * Create a OS linux partition to buffer error logs.
- * Will create a partition starting at the first free
- * space found if space has enough room.
+/**
+ * nvram_create_partition - Create a partition in nvram
+ * @name: name of the partition to create
+ * @sig: signature of the partition to create
+ * @req_size: size to allocate preferrably
+ * @min_size: minimum acceptable size (0 means req_size)
  */
-static int __init nvram_create_os_partition(void)
+static int __init nvram_create_partition(const char *name, int sig,
+					 int req_size, int min_size)
 {
 	struct nvram_partition *part;
 	struct nvram_partition *new_part;
@@ -322,20 +324,27 @@ static int __init nvram_create_os_partition(void)
 	loff_t tmp_index;
 	long size = 0;
 	int rc;
-	
+
+	/* If no minimum size specified, make it the same as the
+	 * requested size
+	 */
+	if (min_size == 0)
+		min_size = req_size;
+
 	/* Find a free partition that will give us the maximum needed size 
 	   If can't find one that will give us the minimum size needed */
 	list_for_each_entry(part, &nvram_part->partition, partition) {
 		if (part->header.signature != NVRAM_SIG_FREE)
 			continue;
 
-		if (part->header.length >= NVRAM_MAX_REQ) {
-			size = NVRAM_MAX_REQ;
+		if (part->header.length >= req_size) {
+			size = req_size;
 			free_part = part;
 			break;
 		}
-		if (!size && part->header.length >= NVRAM_MIN_REQ) {
-			size = NVRAM_MIN_REQ;
+		if (part->header.length > size &&
+		    part->header.length >= min_size) {
+			size = part->header.length;
 			free_part = part;
 		}
 	}
@@ -350,9 +359,9 @@ static int __init nvram_create_os_partition(void)
 	}
 
 	new_part->index = free_part->index;
-	new_part->header.signature = NVRAM_SIG_OS;
+	new_part->header.signature = sig;
 	new_part->header.length = size;
-	strcpy(new_part->header.name, "ppc64,linux");
+	strncpy(new_part->header.name, name, 12);
 	new_part->header.checksum = nvram_checksum(&new_part->header);
 
 	rc = nvram_write_header(new_part);
@@ -451,10 +460,10 @@ static int __init nvram_setup_partition(void)
 	}
 	
 	/* try creating a partition with the free space we have */
-	rc = nvram_create_partition("ppc64,linux", );
-	if (!rc) {
+	rc = 	nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
+				       NVRAM_MIN_REQ, NVRAM_MAX_REQ);
+	if (!rc)
 		return 0;
-	}
 		
 	/* need to free up some space */
 	rc = nvram_remove_os_partition();
@@ -463,9 +472,10 @@ static int __init nvram_setup_partition(void)
 	}
 	
 	/* create a partition in this new space */
-	rc = nvram_create_os_partition();
+	rc = 	nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
+				       NVRAM_MIN_REQ, NVRAM_MAX_REQ);
 	if (rc) {
-		printk(KERN_ERR "nvram_create_os_partition: Could not find a "
+		printk(KERN_ERR "nvram_create_partition: Could not find a "
 		       "NVRAM partition large enough\n");
 		return rc;
 	}
diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
index f4e4c06..2a1ef5c 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -22,14 +22,14 @@
 #include <asm/prom.h>
 #include <asm/machdep.h>
 
+/* Max bytes to read/write in one go */
+#define NVRW_CNT 0x20
+
 static unsigned int nvram_size;
 static int nvram_fetch, nvram_store;
 static char nvram_buf[NVRW_CNT];	/* assume this is in the first 4GB */
 static DEFINE_SPINLOCK(nvram_lock);
 
-/* Max bytes to read/write in one go */
-#define NVRW_CNT 0x20
-
 static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
 {
 	unsigned int i;
-- 
1.6.3.3

^ permalink raw reply related

* [PATCH 01/11] powerpc/nvram: Move things out of asm/nvram.h
From: Benjamin Herrenschmidt @ 2010-08-02  0:55 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1280710522-6362-1-git-send-email-benh@kernel.crashing.org>

This moves a bunch of definitions out of asm/nvram.h to the files
that use them or just outright remove completely unused stuff.

We leave the partition signatures definitions, they will be useful

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/include/asm/nvram.h       |   42 +------------------------------
 arch/powerpc/kernel/nvram_64.c         |   21 +++++++++++++++-
 arch/powerpc/platforms/chrp/time.c     |    4 +++
 arch/powerpc/platforms/pseries/nvram.c |    2 +
 4 files changed, 28 insertions(+), 41 deletions(-)

diff --git a/arch/powerpc/include/asm/nvram.h b/arch/powerpc/include/asm/nvram.h
index 850b72f..459dc09 100644
--- a/arch/powerpc/include/asm/nvram.h
+++ b/arch/powerpc/include/asm/nvram.h
@@ -10,31 +10,7 @@
 #ifndef _ASM_POWERPC_NVRAM_H
 #define _ASM_POWERPC_NVRAM_H
 
-#include <linux/errno.h>
-
-#define NVRW_CNT 0x20
-#define NVRAM_HEADER_LEN 16 /* sizeof(struct nvram_header) */
-#define NVRAM_BLOCK_LEN 16
-#define NVRAM_MAX_REQ (2080/NVRAM_BLOCK_LEN)
-#define NVRAM_MIN_REQ (1056/NVRAM_BLOCK_LEN)
-
-#define NVRAM_AS0  0x74
-#define NVRAM_AS1  0x75
-#define NVRAM_DATA 0x77
-
-
-/* RTC Offsets */
-
-#define MOTO_RTC_SECONDS	0x1FF9
-#define MOTO_RTC_MINUTES	0x1FFA
-#define MOTO_RTC_HOURS		0x1FFB
-#define MOTO_RTC_DAY_OF_WEEK	0x1FFC
-#define MOTO_RTC_DAY_OF_MONTH	0x1FFD
-#define MOTO_RTC_MONTH		0x1FFE
-#define MOTO_RTC_YEAR		0x1FFF
-#define MOTO_RTC_CONTROLA       0x1FF8
-#define MOTO_RTC_CONTROLB       0x1FF9
-
+/* Signatures for nvram partitions */
 #define NVRAM_SIG_SP	0x02	/* support processor */
 #define NVRAM_SIG_OF	0x50	/* open firmware config */
 #define NVRAM_SIG_FW	0x51	/* general firmware */
@@ -49,25 +25,11 @@
 #define NVRAM_SIG_OS	0xa0	/* OS defined */
 #define NVRAM_SIG_PANIC	0xa1	/* Apple OSX "panic" */
 
-/* If change this size, then change the size of NVNAME_LEN */
-struct nvram_header {
-	unsigned char signature;
-	unsigned char checksum;
-	unsigned short length;
-	char name[12];
-};
-
 #ifdef __KERNEL__
 
+#include <linux/errno.h>
 #include <linux/list.h>
 
-struct nvram_partition {
-	struct list_head partition;
-	struct nvram_header header;
-	unsigned int index;
-};
-
-
 extern int nvram_write_error_log(char * buff, int length,
 					 unsigned int err_type, unsigned int err_seq);
 extern int nvram_read_error_log(char * buff, int length,
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index 9cf197f..a8154f1 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -34,6 +34,25 @@
 
 #undef DEBUG_NVRAM
 
+#define NVRAM_HEADER_LEN 16 /* sizeof(struct nvram_header) */
+#define NVRAM_BLOCK_LEN 16
+#define NVRAM_MAX_REQ (2080/NVRAM_BLOCK_LEN)
+#define NVRAM_MIN_REQ (1056/NVRAM_BLOCK_LEN)
+
+/* If change this size, then change the size of NVNAME_LEN */
+struct nvram_header {
+	unsigned char signature;
+	unsigned char checksum;
+	unsigned short length;
+	char name[12];
+};
+
+struct nvram_partition {
+	struct list_head partition;
+	struct nvram_header header;
+	unsigned int index;
+};
+
 static struct nvram_partition * nvram_part;
 static long nvram_error_log_index = -1;
 static long nvram_error_log_size = 0;
@@ -432,7 +451,7 @@ static int __init nvram_setup_partition(void)
 	}
 	
 	/* try creating a partition with the free space we have */
-	rc = nvram_create_os_partition();
+	rc = nvram_create_partition("ppc64,linux", );
 	if (!rc) {
 		return 0;
 	}
diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c
index 054dfe5..f803f4b 100644
--- a/arch/powerpc/platforms/chrp/time.c
+++ b/arch/powerpc/platforms/chrp/time.c
@@ -29,6 +29,10 @@
 
 extern spinlock_t rtc_lock;
 
+#define NVRAM_AS0  0x74
+#define NVRAM_AS1  0x75
+#define NVRAM_DATA 0x77
+
 static int nvram_as1 = NVRAM_AS1;
 static int nvram_as0 = NVRAM_AS0;
 static int nvram_data = NVRAM_DATA;
diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
index bc3c7f2..f4e4c06 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -27,6 +27,8 @@ static int nvram_fetch, nvram_store;
 static char nvram_buf[NVRW_CNT];	/* assume this is in the first 4GB */
 static DEFINE_SPINLOCK(nvram_lock);
 
+/* Max bytes to read/write in one go */
+#define NVRW_CNT 0x20
 
 static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
 {
-- 
1.6.3.3

^ permalink raw reply related

* [RFC] Clean up ppc64 nvram code
From: Benjamin Herrenschmidt @ 2010-08-02  0:55 UTC (permalink / raw)
  To: linuxppc-dev

This series is a first go at cleaning up some cruft in nvram_64.c for
handling nvram partitions. The current ppc64,linux partition is really
pseries specific, so we change the code for finding/creating it gets
turned into a more generic API for manipulating nvram partitions, and
the specifics to that partition are moved to pseries. We also rename
it to better represent what it's for

^ permalink raw reply

* [PATCH 04/11] powerpc/nvram: Ensure that the partition header/block size is right
From: Benjamin Herrenschmidt @ 2010-08-02  0:55 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1280710522-6362-4-git-send-email-benh@kernel.crashing.org>

Use BUILD_BUG_ON to ensure the structure representing a partition
header have the right size.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/kernel/nvram_64.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index b0f2114..dd18a5a 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -565,6 +565,8 @@ static int __init nvram_init(void)
 	int error;
 	int rc;
 	
+	BUILD_BUG_ON(NVRAM_BLOCK_LEN != 16);
+
 	if (ppc_md.nvram_size == NULL || ppc_md.nvram_size() <= 0)
 		return  -ENODEV;
 
-- 
1.6.3.3

^ permalink raw reply related

* [PATCH 05/11] powerpc/nvram: Completely clear a new partition
From: Benjamin Herrenschmidt @ 2010-08-02  0:55 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1280710522-6362-5-git-send-email-benh@kernel.crashing.org>

When creating a partition, we clear it entirely rather than
just the first two words since the previous code was rather
specific to the pseries log partition format.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/kernel/nvram_64.c |   19 ++++++++++---------
 1 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index dd18a5a..7ddeaa6 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -320,7 +320,7 @@ static int __init nvram_create_partition(const char *name, int sig,
 	struct nvram_partition *part;
 	struct nvram_partition *new_part;
 	struct nvram_partition *free_part = NULL;
-	int seq_init[2] = { 0, 0 };
+	static char nv_init_vals[16];
 	loff_t tmp_index;
 	long size = 0;
 	int rc;
@@ -379,14 +379,15 @@ static int __init nvram_create_partition(const char *name, int sig,
 		return rc;
 	}
 
-	/* make sure and initialize to zero the sequence number and the error
-	   type logged */
-	tmp_index = new_part->index + NVRAM_HEADER_LEN;
-	rc = ppc_md.nvram_write((char *)&seq_init, sizeof(seq_init), &tmp_index);
-	if (rc <= 0) {
-		printk(KERN_ERR "nvram_create_os_partition: nvram_write "
-		       "failed (%d)\n", rc);
-		return rc;
+	/* Clear the partition */
+	for (tmp_index = new_part->index + NVRAM_HEADER_LEN;
+	     tmp_index <  ((size - 1) * NVRAM_BLOCK_LEN);
+	     tmp_index += NVRAM_BLOCK_LEN) {
+		rc = ppc_md.nvram_write(nv_init_vals, NVRAM_BLOCK_LEN, &tmp_index);
+		if (rc <= 0) {
+			pr_err("nvram_create_partition: nvram_write failed (%d)\n", rc);
+			return rc;
+		}
 	}
 	
 	nvram_error_log_index = new_part->index + NVRAM_HEADER_LEN;
-- 
1.6.3.3

^ permalink raw reply related

* [PATCH 03/11] powerpc/nvram: nvram_create_partitions() now uses bytes
From: Benjamin Herrenschmidt @ 2010-08-02  0:55 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1280710522-6362-3-git-send-email-benh@kernel.crashing.org>

This converts nvram_create_partition() to use a size in bytes
rather than blocks. It does the appropriate alignment internally

The size passed is also the data size (ie. doesn't include the
header anymore).

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/kernel/nvram_64.c |   20 ++++++++++++++------
 1 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index 974b3ec..b0f2114 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -34,10 +34,10 @@
 
 #undef DEBUG_NVRAM
 
-#define NVRAM_HEADER_LEN 16 /* sizeof(struct nvram_header) */
-#define NVRAM_BLOCK_LEN 16
-#define NVRAM_MAX_REQ (2080/NVRAM_BLOCK_LEN)
-#define NVRAM_MIN_REQ (1056/NVRAM_BLOCK_LEN)
+#define NVRAM_HEADER_LEN	sizeof(struct nvram_header)
+#define NVRAM_BLOCK_LEN		NVRAM_HEADER_LEN
+#define NVRAM_MAX_REQ		2079
+#define NVRAM_MIN_REQ		1055
 
 /* If change this size, then change the size of NVNAME_LEN */
 struct nvram_header {
@@ -311,7 +311,7 @@ static int __init nvram_remove_os_partition(void)
  * nvram_create_partition - Create a partition in nvram
  * @name: name of the partition to create
  * @sig: signature of the partition to create
- * @req_size: size to allocate preferrably
+ * @req_size: size of data to allocate in bytes
  * @min_size: minimum acceptable size (0 means req_size)
  */
 static int __init nvram_create_partition(const char *name, int sig,
@@ -325,12 +325,20 @@ static int __init nvram_create_partition(const char *name, int sig,
 	long size = 0;
 	int rc;
 
+	/* Convert sizes from bytes to blocks */
+	req_size = _ALIGN_UP(req_size, NVRAM_BLOCK_LEN) / NVRAM_BLOCK_LEN;
+	min_size = _ALIGN_UP(min_size, NVRAM_BLOCK_LEN) / NVRAM_BLOCK_LEN;
+
 	/* If no minimum size specified, make it the same as the
 	 * requested size
 	 */
 	if (min_size == 0)
 		min_size = req_size;
 
+	/* Now add one block to each for the header */
+	req_size += 1;
+	min_size += 1;
+
 	/* Find a free partition that will give us the maximum needed size 
 	   If can't find one that will give us the minimum size needed */
 	list_for_each_entry(part, &nvram_part->partition, partition) {
@@ -450,7 +458,7 @@ static int __init nvram_setup_partition(void)
 		if (strcmp(part->header.name, "ppc64,linux"))
 			continue;
 
-		if (part->header.length >= NVRAM_MIN_REQ) {
+		if ((part->header.length - 1) * NVRAM_BLOCK_LEN >= NVRAM_MIN_REQ) {
 			/* found our partition */
 			nvram_error_log_index = part->index + NVRAM_HEADER_LEN;
 			nvram_error_log_size = ((part->header.length - 1) *
-- 
1.6.3.3

^ permalink raw reply related

* [PATCH 07/11] powerpc/nvram: Improve partition removal
From: Benjamin Herrenschmidt @ 2010-08-02  0:55 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1280710522-6362-7-git-send-email-benh@kernel.crashing.org>

Existing code is nasty, has bugs etc... rewrite the function
more simply, and make it take the signature and optional
name of the partitions to remove as arguments, thus making
it a more generic utility.

We also try to remove a log partition that we find and is too
small rather than creating a duplicate.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/kernel/nvram_64.c |   91 +++++++++++++++++++---------------------
 1 files changed, 43 insertions(+), 48 deletions(-)

diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index 10f4b82..c934b5a 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -247,61 +247,54 @@ static unsigned char __init nvram_checksum(struct nvram_header *p)
 	return c_sum;
 }
 
-static int __init nvram_remove_os_partition(void)
+/**
+ * nvram_remove_partition - Remove one or more partitions in nvram
+ * @name: name of the partition to remove, or NULL for a
+ *        signature only match
+ * @sig: signature of the partition(s) to remove
+ */
+
+static int __init nvram_remove_partition(const char *name, int sig)
 {
-	struct list_head *i;
-	struct list_head *j;
-	struct nvram_partition * part;
-	struct nvram_partition * cur_part;
+	struct nvram_partition *part, *prev, *tmp;
 	int rc;
 
-	list_for_each(i, &nvram_part->partition) {
-		part = list_entry(i, struct nvram_partition, partition);
-		if (part->header.signature != NVRAM_SIG_OS)
+	list_for_each_entry(part, &nvram_part->partition, partition) {
+		if (part->header.signature != sig)
 			continue;
-		
-		/* Make os partition a free partition */
+		if (name && strncmp(name, part->header.name, 12))
+			continue;
+
+		/* Make partition a free partition */
 		part->header.signature = NVRAM_SIG_FREE;
 		sprintf(part->header.name, "wwwwwwwwwwww");
 		part->header.checksum = nvram_checksum(&part->header);
-
-		/* Merge contiguous free partitions backwards */
-		list_for_each_prev(j, &part->partition) {
-			cur_part = list_entry(j, struct nvram_partition, partition);
-			if (cur_part == nvram_part || cur_part->header.signature != NVRAM_SIG_FREE) {
-				break;
-			}
-			
-			part->header.length += cur_part->header.length;
-			part->header.checksum = nvram_checksum(&part->header);
-			part->index = cur_part->index;
-
-			list_del(&cur_part->partition);
-			kfree(cur_part);
-			j = &part->partition; /* fixup our loop */
-		}
-		
-		/* Merge contiguous free partitions forwards */
-		list_for_each(j, &part->partition) {
-			cur_part = list_entry(j, struct nvram_partition, partition);
-			if (cur_part == nvram_part || cur_part->header.signature != NVRAM_SIG_FREE) {
-				break;
-			}
-
-			part->header.length += cur_part->header.length;
-			part->header.checksum = nvram_checksum(&part->header);
-
-			list_del(&cur_part->partition);
-			kfree(cur_part);
-			j = &part->partition; /* fixup our loop */
-		}
-		
 		rc = nvram_write_header(part);
 		if (rc <= 0) {
-			printk(KERN_ERR "nvram_remove_os_partition: nvram_write failed (%d)\n", rc);
+			printk(KERN_ERR "nvram_remove_partition: nvram_write failed (%d)\n", rc);
 			return rc;
 		}
+	}
 
+	/* Merge contiguous ones */
+	prev = NULL;
+	list_for_each_entry_safe(part, tmp, &nvram_part->partition, partition) {
+		if (part->header.signature != NVRAM_SIG_FREE) {
+			prev = NULL;
+			continue;
+		}
+		if (prev) {
+			prev->header.length += part->header.length;
+			prev->header.checksum = nvram_checksum(&part->header);
+			rc = nvram_write_header(part);
+			if (rc <= 0) {
+				printk(KERN_ERR "nvram_remove_partition: nvram_write failed (%d)\n", rc);
+				return rc;
+			}
+			list_del(&part->partition);
+			kfree(part);
+		} else
+			prev = part;
 	}
 	
 	return 0;
@@ -484,17 +477,19 @@ static int __init nvram_setup_partition(void)
 						NVRAM_BLOCK_LEN) - sizeof(struct err_log_info);
 			return 0;
 		}
+
+		/* Found one but it's too small, remove it */
+		nvram_remove_partition("ppc64,linux", NVRAM_SIG_OS);
 	}
 	
 	/* try creating a partition with the free space we have */
 	rc = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
 				       NVRAM_MIN_REQ, NVRAM_MAX_REQ);
 	if (rc < 0) {
-		/* need to free up some space */
-		rc = nvram_remove_os_partition();
-		if (rc)
-			return rc;	
-		/* create a partition in this new space */
+		/* need to free up some space, remove any "OS" partition */
+		nvram_remove_partition(NULL, NVRAM_SIG_OS);
+	
+		/* Try again */
 		rc = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
 					    NVRAM_MIN_REQ, NVRAM_MAX_REQ);
 		if (rc < 0) {
-- 
1.6.3.3

^ permalink raw reply related

* [PATCH 06/11] powerpc/nvram: Shuffle code around in nvram_create_partition()
From: Benjamin Herrenschmidt @ 2010-08-02  0:55 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1280710522-6362-6-git-send-email-benh@kernel.crashing.org>

This error log stuff is really pseries specific. As a first step we move
the initialization of these variables to the caller of
nvram_create_partition(), which is also slightly reorganized so we
setup the free partition before we clear the new partition, so the
chance of an error during clear leaving us with invalid headers
is lessened.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/kernel/nvram_64.c |  107 +++++++++++++++++++++++-----------------
 1 files changed, 62 insertions(+), 45 deletions(-)

diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index 7ddeaa6..10f4b82 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -313,9 +313,15 @@ static int __init nvram_remove_os_partition(void)
  * @sig: signature of the partition to create
  * @req_size: size of data to allocate in bytes
  * @min_size: minimum acceptable size (0 means req_size)
+ *
+ * Returns a negative error code or a positive nvram index
+ * of the beginning of the data area of the newly created
+ * partition. If you provided a min_size smaller than req_size
+ * you need to query for the actual size yourself after the
+ * call using nvram_partition_get_size().
  */
-static int __init nvram_create_partition(const char *name, int sig,
-					 int req_size, int min_size)
+static loff_t __init nvram_create_partition(const char *name, int sig,
+					    int req_size, int min_size)
 {
 	struct nvram_partition *part;
 	struct nvram_partition *new_part;
@@ -334,6 +340,8 @@ static int __init nvram_create_partition(const char *name, int sig,
 	 */
 	if (min_size == 0)
 		min_size = req_size;
+	if (min_size > req_size)
+		return -EINVAL;
 
 	/* Now add one block to each for the header */
 	req_size += 1;
@@ -362,7 +370,7 @@ static int __init nvram_create_partition(const char *name, int sig,
 	/* Create our OS partition */
 	new_part = kmalloc(sizeof(*new_part), GFP_KERNEL);
 	if (!new_part) {
-		printk(KERN_ERR "nvram_create_os_partition: kmalloc failed\n");
+		pr_err("nvram_create_os_partition: kmalloc failed\n");
 		return -ENOMEM;
 	}
 
@@ -374,12 +382,29 @@ static int __init nvram_create_partition(const char *name, int sig,
 
 	rc = nvram_write_header(new_part);
 	if (rc <= 0) {
-		printk(KERN_ERR "nvram_create_os_partition: nvram_write_header "
-				"failed (%d)\n", rc);
+		pr_err("nvram_create_os_partition: nvram_write_header "
+		       "failed (%d)\n", rc);
 		return rc;
 	}
+	list_add_tail(&new_part->partition, &free_part->partition);
 
-	/* Clear the partition */
+	/* Adjust or remove the partition we stole the space from */
+	if (free_part->header.length > size) {
+		free_part->index += size * NVRAM_BLOCK_LEN;
+		free_part->header.length -= size;
+		free_part->header.checksum = nvram_checksum(&free_part->header);
+		rc = nvram_write_header(free_part);
+		if (rc <= 0) {
+			pr_err("nvram_create_os_partition: nvram_write_header "
+			       "failed (%d)\n", rc);
+			return rc;
+		}
+	} else {
+		list_del(&free_part->partition);
+		kfree(free_part);
+	} 
+
+	/* Clear the new partition */
 	for (tmp_index = new_part->index + NVRAM_HEADER_LEN;
 	     tmp_index <  ((size - 1) * NVRAM_BLOCK_LEN);
 	     tmp_index += NVRAM_BLOCK_LEN) {
@@ -390,31 +415,24 @@ static int __init nvram_create_partition(const char *name, int sig,
 		}
 	}
 	
-	nvram_error_log_index = new_part->index + NVRAM_HEADER_LEN;
-	nvram_error_log_size = ((part->header.length - 1) *
-				NVRAM_BLOCK_LEN) - sizeof(struct err_log_info);
-	
-	list_add_tail(&new_part->partition, &free_part->partition);
-
-	if (free_part->header.length <= size) {
-		list_del(&free_part->partition);
-		kfree(free_part);
-		return 0;
-	} 
+	return new_part->index + NVRAM_HEADER_LEN;
+}
 
-	/* Adjust the partition we stole the space from */
-	free_part->index += size * NVRAM_BLOCK_LEN;
-	free_part->header.length -= size;
-	free_part->header.checksum = nvram_checksum(&free_part->header);
+/**
+ * nvram_get_partition_size - Get the data size of an nvram partition
+ * @data_index: This is the offset of the start of the data of
+ *              the partition. The same value that is returned by
+ *              nvram_create_partition().
+ */
+static int nvram_get_partition_size(loff_t data_index)
+{
+	struct nvram_partition *part;
 	
-	rc = nvram_write_header(free_part);
-	if (rc <= 0) {
-		printk(KERN_ERR "nvram_create_os_partition: nvram_write_header "
-		       "failed (%d)\n", rc);
-		return rc;
+	list_for_each_entry(part, &nvram_part->partition, partition) {
+		if (part->index + NVRAM_HEADER_LEN == data_index)
+			return (part->header.length - 1) * NVRAM_BLOCK_LEN;
 	}
-
-	return 0;
+	return -1;
 }
 
 
@@ -469,30 +487,29 @@ static int __init nvram_setup_partition(void)
 	}
 	
 	/* try creating a partition with the free space we have */
-	rc = 	nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
+	rc = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
 				       NVRAM_MIN_REQ, NVRAM_MAX_REQ);
-	if (!rc)
-		return 0;
-		
-	/* need to free up some space */
-	rc = nvram_remove_os_partition();
-	if (rc) {
-		return rc;
+	if (rc < 0) {
+		/* need to free up some space */
+		rc = nvram_remove_os_partition();
+		if (rc)
+			return rc;	
+		/* create a partition in this new space */
+		rc = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
+					    NVRAM_MIN_REQ, NVRAM_MAX_REQ);
+		if (rc < 0) {
+			pr_err("nvram_create_partition: Could not find"
+			       " enough space in NVRAM for partition\n");
+			return rc;
+		}
 	}
 	
-	/* create a partition in this new space */
-	rc = 	nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
-				       NVRAM_MIN_REQ, NVRAM_MAX_REQ);
-	if (rc) {
-		printk(KERN_ERR "nvram_create_partition: Could not find a "
-		       "NVRAM partition large enough\n");
-		return rc;
-	}
+	nvram_error_log_index = rc;	
+	nvram_error_log_size = nvram_get_partition_size(rc) - sizeof(struct err_log_info);
 	
 	return 0;
 }
 
-
 static int __init nvram_scan_partitions(void)
 {
 	loff_t cur_index = 0;
-- 
1.6.3.3

^ permalink raw reply related

* [PATCH 08/11] powerpc/nvram: Add nvram_find_partition()
From: Benjamin Herrenschmidt @ 2010-08-02  0:55 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1280710522-6362-8-git-send-email-benh@kernel.crashing.org>

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/kernel/nvram_64.c |   22 ++++++++++++++++++++++
 1 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index c934b5a..fd0d12d 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -429,6 +429,28 @@ static int nvram_get_partition_size(loff_t data_index)
 }
 
 
+/**
+ * nvram_find_partition - Find an nvram partition by signature and name
+ * @name: Name of the partition or NULL for any name
+ * @sig: Signature to test against
+ * @out_size: if non-NULL, returns the size of the data part of the partition
+ */
+loff_t nvram_find_partition(const char *name, int sig, int *out_size)
+{
+	struct nvram_partition *p;
+
+	list_for_each_entry(p, &nvram_part->partition, partition) {
+		if (p->header.signature == sig &&
+		    (!name || !strncmp(p->header.name, name, 12))) {
+			if (out_size)
+				*out_size = (p->header.length - 1) *
+					NVRAM_BLOCK_LEN;
+			return p->index + NVRAM_HEADER_LEN;
+		}
+	}
+	return 0;
+}
+
 /* nvram_setup_partition
  *
  * This will setup the partition we need for buffering the
-- 
1.6.3.3

^ permalink raw reply related

* [PATCH 09/11] powerpc/nvram: Change nvram_setup_partition() to use new helper
From: Benjamin Herrenschmidt @ 2010-08-02  0:55 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1280710522-6362-9-git-send-email-benh@kernel.crashing.org>

This changes the function to use nvram_find_partition() instead
of doing the lookup "by hand". It also makes some of the logic
clearer and prints out more useful diagnostic information.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/kernel/nvram_64.c |   72 ++++++++++++++++++----------------------
 1 files changed, 32 insertions(+), 40 deletions(-)

diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index fd0d12d..ddc94cf 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -469,9 +469,8 @@ loff_t nvram_find_partition(const char *name, int sig, int *out_size)
  */
 static int __init nvram_setup_partition(void)
 {
-	struct list_head * p;
-	struct nvram_partition * part;
-	int rc;
+	loff_t p;
+	int size;
 
 	/* For now, we don't do any of this on pmac, until I
 	 * have figured out if it's worth killing some unused stuffs
@@ -481,48 +480,41 @@ static int __init nvram_setup_partition(void)
 	if (machine_is(powermac))
 		return -ENOSPC;
 
-	/* see if we have an OS partition that meets our needs.
-	   will try getting the max we need.  If not we'll delete
-	   partitions and try again. */
-	list_for_each(p, &nvram_part->partition) {
-		part = list_entry(p, struct nvram_partition, partition);
-		if (part->header.signature != NVRAM_SIG_OS)
-			continue;
-
-		if (strcmp(part->header.name, "ppc64,linux"))
-			continue;
-
-		if ((part->header.length - 1) * NVRAM_BLOCK_LEN >= NVRAM_MIN_REQ) {
-			/* found our partition */
-			nvram_error_log_index = part->index + NVRAM_HEADER_LEN;
-			nvram_error_log_size = ((part->header.length - 1) *
-						NVRAM_BLOCK_LEN) - sizeof(struct err_log_info);
-			return 0;
-		}
+	p = nvram_find_partition("ppc64,linux", NVRAM_SIG_OS, &size);
 
-		/* Found one but it's too small, remove it */
+	/* Found one but too small, remove it */
+	if (p && size < NVRAM_MIN_REQ) {
+		pr_info("nvram: Found too small ppc64,linux partition"
+			",removing it...");
 		nvram_remove_partition("ppc64,linux", NVRAM_SIG_OS);
+		p = 0;
 	}
-	
-	/* try creating a partition with the free space we have */
-	rc = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
-				       NVRAM_MIN_REQ, NVRAM_MAX_REQ);
-	if (rc < 0) {
-		/* need to free up some space, remove any "OS" partition */
-		nvram_remove_partition(NULL, NVRAM_SIG_OS);
-	
-		/* Try again */
-		rc = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
-					    NVRAM_MIN_REQ, NVRAM_MAX_REQ);
-		if (rc < 0) {
-			pr_err("nvram_create_partition: Could not find"
-			       " enough space in NVRAM for partition\n");
-			return rc;
+
+	/* Create one if we didn't find */
+	if (!p) {
+		p = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
+					   NVRAM_MIN_REQ, NVRAM_MAX_REQ);
+		/* No room for it, try to get rid of any OS partition
+		 * and try again
+		 */
+		if (p == -ENOSPC) {
+			pr_info("nvram: No room to create ppc64,linux"
+				" partition, deleting all OS partitions...");
+			nvram_remove_partition(NULL, NVRAM_SIG_OS);
+			p = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
+						   NVRAM_MIN_REQ, NVRAM_MAX_REQ);
 		}
 	}
-	
-	nvram_error_log_index = rc;	
-	nvram_error_log_size = nvram_get_partition_size(rc) - sizeof(struct err_log_info);
+
+	if (p <= 0) {
+		pr_err("nvram: Failed to find or create ppc64,linux"
+		       " partition, err %d\n", (int)p);
+		return 0;
+	}
+
+	nvram_error_log_index = p;
+	nvram_error_log_size = nvram_get_partition_size(p) -
+		sizeof(struct err_log_info);
 	
 	return 0;
 }
-- 
1.6.3.3

^ permalink raw reply related

* [PATCH 10/11] powerpc/nvram: Move the log partition stuff to pseries
From: Benjamin Herrenschmidt @ 2010-08-02  0:55 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1280710522-6362-10-git-send-email-benh@kernel.crashing.org>

The nvram log partition stuff currently in nvram_64.c is really
pseries specific. It isn't actually used on anything else (despite
the fact that we ran the code to setup the partition on anything
except powermac) and the log format is specific to pseries RTAS
implementation. So move it where it belongs

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/include/asm/nvram.h       |    9 ++-
 arch/powerpc/kernel/nvram_64.c         |  216 +-------------------------------
 arch/powerpc/platforms/pseries/nvram.c |  196 +++++++++++++++++++++++++++++
 3 files changed, 208 insertions(+), 213 deletions(-)

diff --git a/arch/powerpc/include/asm/nvram.h b/arch/powerpc/include/asm/nvram.h
index 459dc09..457a1a5 100644
--- a/arch/powerpc/include/asm/nvram.h
+++ b/arch/powerpc/include/asm/nvram.h
@@ -30,13 +30,14 @@
 #include <linux/errno.h>
 #include <linux/list.h>
 
+#ifdef CONFIG_PPC_PSERIES
 extern int nvram_write_error_log(char * buff, int length,
 					 unsigned int err_type, unsigned int err_seq);
 extern int nvram_read_error_log(char * buff, int length,
 					 unsigned int * err_type, unsigned int *err_seq);
 extern int nvram_clear_error_log(void);
-
 extern int pSeries_nvram_init(void);
+#endif /* CONFIG_PPC_PSERIES */
 
 #ifdef CONFIG_MMIO_NVRAM
 extern int mmio_nvram_init(void);
@@ -47,6 +48,12 @@ static inline int mmio_nvram_init(void)
 }
 #endif
 
+extern loff_t nvram_create_partition(const char *name, int sig,
+				     int req_size, int min_size);
+extern int nvram_remove_partition(const char *name, int sig);
+extern int nvram_get_partition_size(loff_t data_index);
+extern loff_t nvram_find_partition(const char *name, int sig, int *out_size);
+
 #endif /* __KERNEL__ */
 
 /* PowerMac specific nvram stuffs */
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index ddc94cf..d467f8c 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -36,8 +36,6 @@
 
 #define NVRAM_HEADER_LEN	sizeof(struct nvram_header)
 #define NVRAM_BLOCK_LEN		NVRAM_HEADER_LEN
-#define NVRAM_MAX_REQ		2079
-#define NVRAM_MIN_REQ		1055
 
 /* If change this size, then change the size of NVNAME_LEN */
 struct nvram_header {
@@ -54,13 +52,6 @@ struct nvram_partition {
 };
 
 static struct nvram_partition * nvram_part;
-static long nvram_error_log_index = -1;
-static long nvram_error_log_size = 0;
-
-struct err_log_info {
-	int error_type;
-	unsigned int seq_num;
-};
 
 static loff_t dev_nvram_llseek(struct file *file, loff_t offset, int origin)
 {
@@ -254,7 +245,7 @@ static unsigned char __init nvram_checksum(struct nvram_header *p)
  * @sig: signature of the partition(s) to remove
  */
 
-static int __init nvram_remove_partition(const char *name, int sig)
+int __init nvram_remove_partition(const char *name, int sig)
 {
 	struct nvram_partition *part, *prev, *tmp;
 	int rc;
@@ -313,8 +304,8 @@ static int __init nvram_remove_partition(const char *name, int sig)
  * you need to query for the actual size yourself after the
  * call using nvram_partition_get_size().
  */
-static loff_t __init nvram_create_partition(const char *name, int sig,
-					    int req_size, int min_size)
+loff_t __init nvram_create_partition(const char *name, int sig,
+				     int req_size, int min_size)
 {
 	struct nvram_partition *part;
 	struct nvram_partition *new_part;
@@ -417,7 +408,7 @@ static loff_t __init nvram_create_partition(const char *name, int sig,
  *              the partition. The same value that is returned by
  *              nvram_create_partition().
  */
-static int nvram_get_partition_size(loff_t data_index)
+int nvram_get_partition_size(loff_t data_index)
 {
 	struct nvram_partition *part;
 	
@@ -451,74 +442,6 @@ loff_t nvram_find_partition(const char *name, int sig, int *out_size)
 	return 0;
 }
 
-/* nvram_setup_partition
- *
- * This will setup the partition we need for buffering the
- * error logs and cleanup partitions if needed.
- *
- * The general strategy is the following:
- * 1.) If there is ppc64,linux partition large enough then use it.
- * 2.) If there is not a ppc64,linux partition large enough, search
- * for a free partition that is large enough.
- * 3.) If there is not a free partition large enough remove 
- * _all_ OS partitions and consolidate the space.
- * 4.) Will first try getting a chunk that will satisfy the maximum
- * error log size (NVRAM_MAX_REQ).
- * 5.) If the max chunk cannot be allocated then try finding a chunk
- * that will satisfy the minum needed (NVRAM_MIN_REQ).
- */
-static int __init nvram_setup_partition(void)
-{
-	loff_t p;
-	int size;
-
-	/* For now, we don't do any of this on pmac, until I
-	 * have figured out if it's worth killing some unused stuffs
-	 * in our nvram, as Apple defined partitions use pretty much
-	 * all of the space
-	 */
-	if (machine_is(powermac))
-		return -ENOSPC;
-
-	p = nvram_find_partition("ppc64,linux", NVRAM_SIG_OS, &size);
-
-	/* Found one but too small, remove it */
-	if (p && size < NVRAM_MIN_REQ) {
-		pr_info("nvram: Found too small ppc64,linux partition"
-			",removing it...");
-		nvram_remove_partition("ppc64,linux", NVRAM_SIG_OS);
-		p = 0;
-	}
-
-	/* Create one if we didn't find */
-	if (!p) {
-		p = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
-					   NVRAM_MIN_REQ, NVRAM_MAX_REQ);
-		/* No room for it, try to get rid of any OS partition
-		 * and try again
-		 */
-		if (p == -ENOSPC) {
-			pr_info("nvram: No room to create ppc64,linux"
-				" partition, deleting all OS partitions...");
-			nvram_remove_partition(NULL, NVRAM_SIG_OS);
-			p = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
-						   NVRAM_MIN_REQ, NVRAM_MAX_REQ);
-		}
-	}
-
-	if (p <= 0) {
-		pr_err("nvram: Failed to find or create ppc64,linux"
-		       " partition, err %d\n", (int)p);
-		return 0;
-	}
-
-	nvram_error_log_index = p;
-	nvram_error_log_size = nvram_get_partition_size(p) -
-		sizeof(struct err_log_info);
-	
-	return 0;
-}
-
 static int __init nvram_scan_partitions(void)
 {
 	loff_t cur_index = 0;
@@ -617,10 +540,6 @@ static int __init nvram_init(void)
   		printk(KERN_ERR "nvram_init: Failed nvram_scan_partitions\n");
   		return error;
   	}
-  		
-  	if(nvram_setup_partition()) 
-  		printk(KERN_WARNING "nvram_init: Could not find nvram partition"
-  		       " for nvram buffered error logging.\n");
   
 #ifdef DEBUG_NVRAM
 	nvram_print_partitions("NVRAM Partitions");
@@ -635,133 +554,6 @@ void __exit nvram_cleanup(void)
 }
 
 
-#ifdef CONFIG_PPC_PSERIES
-
-/* nvram_write_error_log
- *
- * We need to buffer the error logs into nvram to ensure that we have
- * the failure information to decode.  If we have a severe error there
- * is no way to guarantee that the OS or the machine is in a state to
- * get back to user land and write the error to disk.  For example if
- * the SCSI device driver causes a Machine Check by writing to a bad
- * IO address, there is no way of guaranteeing that the device driver
- * is in any state that is would also be able to write the error data
- * captured to disk, thus we buffer it in NVRAM for analysis on the
- * next boot.
- *
- * In NVRAM the partition containing the error log buffer will looks like:
- * Header (in bytes):
- * +-----------+----------+--------+------------+------------------+
- * | signature | checksum | length | name       | data             |
- * |0          |1         |2      3|4         15|16        length-1|
- * +-----------+----------+--------+------------+------------------+
- *
- * The 'data' section would look like (in bytes):
- * +--------------+------------+-----------------------------------+
- * | event_logged | sequence # | error log                         |
- * |0            3|4          7|8            nvram_error_log_size-1|
- * +--------------+------------+-----------------------------------+
- *
- * event_logged: 0 if event has not been logged to syslog, 1 if it has
- * sequence #: The unique sequence # for each event. (until it wraps)
- * error log: The error log from event_scan
- */
-int nvram_write_error_log(char * buff, int length,
-                          unsigned int err_type, unsigned int error_log_cnt)
-{
-	int rc;
-	loff_t tmp_index;
-	struct err_log_info info;
-	
-	if (nvram_error_log_index == -1) {
-		return -ESPIPE;
-	}
-
-	if (length > nvram_error_log_size) {
-		length = nvram_error_log_size;
-	}
-
-	info.error_type = err_type;
-	info.seq_num = error_log_cnt;
-
-	tmp_index = nvram_error_log_index;
-
-	rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info), &tmp_index);
-	if (rc <= 0) {
-		printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc);
-		return rc;
-	}
-
-	rc = ppc_md.nvram_write(buff, length, &tmp_index);
-	if (rc <= 0) {
-		printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc);
-		return rc;
-	}
-	
-	return 0;
-}
-
-/* nvram_read_error_log
- *
- * Reads nvram for error log for at most 'length'
- */
-int nvram_read_error_log(char * buff, int length,
-                         unsigned int * err_type, unsigned int * error_log_cnt)
-{
-	int rc;
-	loff_t tmp_index;
-	struct err_log_info info;
-	
-	if (nvram_error_log_index == -1)
-		return -1;
-
-	if (length > nvram_error_log_size)
-		length = nvram_error_log_size;
-
-	tmp_index = nvram_error_log_index;
-
-	rc = ppc_md.nvram_read((char *)&info, sizeof(struct err_log_info), &tmp_index);
-	if (rc <= 0) {
-		printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc);
-		return rc;
-	}
-
-	rc = ppc_md.nvram_read(buff, length, &tmp_index);
-	if (rc <= 0) {
-		printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc);
-		return rc;
-	}
-
-	*error_log_cnt = info.seq_num;
-	*err_type = info.error_type;
-
-	return 0;
-}
-
-/* This doesn't actually zero anything, but it sets the event_logged
- * word to tell that this event is safely in syslog.
- */
-int nvram_clear_error_log(void)
-{
-	loff_t tmp_index;
-	int clear_word = ERR_FLAG_ALREADY_LOGGED;
-	int rc;
-
-	if (nvram_error_log_index == -1)
-		return -1;
-
-	tmp_index = nvram_error_log_index;
-	
-	rc = ppc_md.nvram_write((char *)&clear_word, sizeof(int), &tmp_index);
-	if (rc <= 0) {
-		printk(KERN_ERR "nvram_clear_error_log: Failed nvram_write (%d)\n", rc);
-		return rc;
-	}
-
-	return 0;
-}
-
-#endif /* CONFIG_PPC_PSERIES */
 
 module_init(nvram_init);
 module_exit(nvram_cleanup);
diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
index 2a1ef5c..c8b3f0f 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -30,6 +30,16 @@ static int nvram_fetch, nvram_store;
 static char nvram_buf[NVRW_CNT];	/* assume this is in the first 4GB */
 static DEFINE_SPINLOCK(nvram_lock);
 
+static long nvram_error_log_index = -1;
+static long nvram_error_log_size = 0;
+
+struct err_log_info {
+	int error_type;
+	unsigned int seq_num;
+};
+#define NVRAM_MAX_REQ		2079
+#define NVRAM_MIN_REQ		1055
+
 static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
 {
 	unsigned int i;
@@ -121,6 +131,192 @@ static ssize_t pSeries_nvram_get_size(void)
 	return nvram_size ? nvram_size : -ENODEV;
 }
 
+
+/* nvram_write_error_log
+ *
+ * We need to buffer the error logs into nvram to ensure that we have
+ * the failure information to decode.  If we have a severe error there
+ * is no way to guarantee that the OS or the machine is in a state to
+ * get back to user land and write the error to disk.  For example if
+ * the SCSI device driver causes a Machine Check by writing to a bad
+ * IO address, there is no way of guaranteeing that the device driver
+ * is in any state that is would also be able to write the error data
+ * captured to disk, thus we buffer it in NVRAM for analysis on the
+ * next boot.
+ *
+ * In NVRAM the partition containing the error log buffer will looks like:
+ * Header (in bytes):
+ * +-----------+----------+--------+------------+------------------+
+ * | signature | checksum | length | name       | data             |
+ * |0          |1         |2      3|4         15|16        length-1|
+ * +-----------+----------+--------+------------+------------------+
+ *
+ * The 'data' section would look like (in bytes):
+ * +--------------+------------+-----------------------------------+
+ * | event_logged | sequence # | error log                         |
+ * |0            3|4          7|8            nvram_error_log_size-1|
+ * +--------------+------------+-----------------------------------+
+ *
+ * event_logged: 0 if event has not been logged to syslog, 1 if it has
+ * sequence #: The unique sequence # for each event. (until it wraps)
+ * error log: The error log from event_scan
+ */
+int nvram_write_error_log(char * buff, int length,
+                          unsigned int err_type, unsigned int error_log_cnt)
+{
+	int rc;
+	loff_t tmp_index;
+	struct err_log_info info;
+	
+	if (nvram_error_log_index == -1) {
+		return -ESPIPE;
+	}
+
+	if (length > nvram_error_log_size) {
+		length = nvram_error_log_size;
+	}
+
+	info.error_type = err_type;
+	info.seq_num = error_log_cnt;
+
+	tmp_index = nvram_error_log_index;
+
+	rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info), &tmp_index);
+	if (rc <= 0) {
+		printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc);
+		return rc;
+	}
+
+	rc = ppc_md.nvram_write(buff, length, &tmp_index);
+	if (rc <= 0) {
+		printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc);
+		return rc;
+	}
+	
+	return 0;
+}
+
+/* nvram_read_error_log
+ *
+ * Reads nvram for error log for at most 'length'
+ */
+int nvram_read_error_log(char * buff, int length,
+                         unsigned int * err_type, unsigned int * error_log_cnt)
+{
+	int rc;
+	loff_t tmp_index;
+	struct err_log_info info;
+	
+	if (nvram_error_log_index == -1)
+		return -1;
+
+	if (length > nvram_error_log_size)
+		length = nvram_error_log_size;
+
+	tmp_index = nvram_error_log_index;
+
+	rc = ppc_md.nvram_read((char *)&info, sizeof(struct err_log_info), &tmp_index);
+	if (rc <= 0) {
+		printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc);
+		return rc;
+	}
+
+	rc = ppc_md.nvram_read(buff, length, &tmp_index);
+	if (rc <= 0) {
+		printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc);
+		return rc;
+	}
+
+	*error_log_cnt = info.seq_num;
+	*err_type = info.error_type;
+
+	return 0;
+}
+
+/* This doesn't actually zero anything, but it sets the event_logged
+ * word to tell that this event is safely in syslog.
+ */
+int nvram_clear_error_log(void)
+{
+	loff_t tmp_index;
+	int clear_word = ERR_FLAG_ALREADY_LOGGED;
+	int rc;
+
+	if (nvram_error_log_index == -1)
+		return -1;
+
+	tmp_index = nvram_error_log_index;
+	
+	rc = ppc_md.nvram_write((char *)&clear_word, sizeof(int), &tmp_index);
+	if (rc <= 0) {
+		printk(KERN_ERR "nvram_clear_error_log: Failed nvram_write (%d)\n", rc);
+		return rc;
+	}
+
+	return 0;
+}
+
+/* pseries_nvram_init_log_partition
+ *
+ * This will setup the partition we need for buffering the
+ * error logs and cleanup partitions if needed.
+ *
+ * The general strategy is the following:
+ * 1.) If there is ppc64,linux partition large enough then use it.
+ * 2.) If there is not a ppc64,linux partition large enough, search
+ * for a free partition that is large enough.
+ * 3.) If there is not a free partition large enough remove 
+ * _all_ OS partitions and consolidate the space.
+ * 4.) Will first try getting a chunk that will satisfy the maximum
+ * error log size (NVRAM_MAX_REQ).
+ * 5.) If the max chunk cannot be allocated then try finding a chunk
+ * that will satisfy the minum needed (NVRAM_MIN_REQ).
+ */
+static int __init pseries_nvram_init_log_partition(void)
+{
+	loff_t p;
+	int size;
+
+	p = nvram_find_partition("ppc64,linux", NVRAM_SIG_OS, &size);
+
+	/* Found one but too small, remove it */
+	if (p && size < NVRAM_MIN_REQ) {
+		pr_info("nvram: Found too small ppc64,linux partition"
+			",removing it...");
+		nvram_remove_partition("ppc64,linux", NVRAM_SIG_OS);
+		p = 0;
+	}
+
+	/* Create one if we didn't find */
+	if (!p) {
+		p = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
+					   NVRAM_MIN_REQ, NVRAM_MAX_REQ);
+		/* No room for it, try to get rid of any OS partition
+		 * and try again
+		 */
+		if (p == -ENOSPC) {
+			pr_info("nvram: No room to create ppc64,linux"
+				" partition, deleting all OS partitions...");
+			nvram_remove_partition(NULL, NVRAM_SIG_OS);
+			p = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
+						   NVRAM_MIN_REQ, NVRAM_MAX_REQ);
+		}
+	}
+
+	if (p <= 0) {
+		pr_err("nvram: Failed to find or create ppc64,linux"
+		       " partition, err %d\n", (int)p);
+		return 0;
+	}
+
+	nvram_error_log_index = p;
+	nvram_error_log_size = nvram_get_partition_size(p) -
+		sizeof(struct err_log_info);
+	
+	return 0;
+}
+machine_arch_initcall(pseries, pseries_nvram_init_log_partition);
+
 int __init pSeries_nvram_init(void)
 {
 	struct device_node *nvram;
-- 
1.6.3.3

^ permalink raw reply related

* [PATCH 11/11] powerpc/nvram: Rename ppc64, linux partition to ibm, rtas-log
From: Benjamin Herrenschmidt @ 2010-08-02  0:55 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1280710522-6362-11-git-send-email-benh@kernel.crashing.org>

I'm not aware of any userspace tool accessing it by its name anyways,
it's read back by the kernel itself on the next boot to get back
older log entries

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/platforms/pseries/nvram.c |   23 +++++++++++++----------
 1 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
index c8b3f0f..e3acb0b 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -40,6 +40,8 @@ struct err_log_info {
 #define NVRAM_MAX_REQ		2079
 #define NVRAM_MIN_REQ		1055
 
+#define NVRAM_LOG_PART_NAME	"ibm,rtas-log"
+
 static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
 {
 	unsigned int i;
@@ -262,8 +264,8 @@ int nvram_clear_error_log(void)
  * error logs and cleanup partitions if needed.
  *
  * The general strategy is the following:
- * 1.) If there is ppc64,linux partition large enough then use it.
- * 2.) If there is not a ppc64,linux partition large enough, search
+ * 1.) If there is log partition large enough then use it.
+ * 2.) If there is none large enough, search
  * for a free partition that is large enough.
  * 3.) If there is not a free partition large enough remove 
  * _all_ OS partitions and consolidate the space.
@@ -277,34 +279,35 @@ static int __init pseries_nvram_init_log_partition(void)
 	loff_t p;
 	int size;
 
-	p = nvram_find_partition("ppc64,linux", NVRAM_SIG_OS, &size);
+	p = nvram_find_partition(NVRAM_LOG_PART_NAME, NVRAM_SIG_OS, &size);
 
 	/* Found one but too small, remove it */
 	if (p && size < NVRAM_MIN_REQ) {
-		pr_info("nvram: Found too small ppc64,linux partition"
+		pr_info("nvram: Found too small "NVRAM_LOG_PART_NAME" partition"
 			",removing it...");
-		nvram_remove_partition("ppc64,linux", NVRAM_SIG_OS);
+		nvram_remove_partition(NVRAM_LOG_PART_NAME, NVRAM_SIG_OS);
 		p = 0;
 	}
 
 	/* Create one if we didn't find */
 	if (!p) {
-		p = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
+		p = nvram_create_partition(NVRAM_LOG_PART_NAME, NVRAM_SIG_OS,
 					   NVRAM_MIN_REQ, NVRAM_MAX_REQ);
 		/* No room for it, try to get rid of any OS partition
 		 * and try again
 		 */
 		if (p == -ENOSPC) {
-			pr_info("nvram: No room to create ppc64,linux"
+			pr_info("nvram: No room to create "NVRAM_LOG_PART_NAME
 				" partition, deleting all OS partitions...");
 			nvram_remove_partition(NULL, NVRAM_SIG_OS);
-			p = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
-						   NVRAM_MIN_REQ, NVRAM_MAX_REQ);
+			p = nvram_create_partition(NVRAM_LOG_PART_NAME,
+						   NVRAM_SIG_OS, NVRAM_MIN_REQ,
+						   NVRAM_MAX_REQ);
 		}
 	}
 
 	if (p <= 0) {
-		pr_err("nvram: Failed to find or create ppc64,linux"
+		pr_err("nvram: Failed to find or create "NVRAM_LOG_PART_NAME
 		       " partition, err %d\n", (int)p);
 		return 0;
 	}
-- 
1.6.3.3

^ permalink raw reply related

* Re: [PATCH 10/11] powerpc/nvram: Move the log partition stuff to pseries
From: Benjamin Herrenschmidt @ 2010-08-02  1:40 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1280710522-6362-11-git-send-email-benh@kernel.crashing.org>

On Mon, 2010-08-02 at 10:55 +1000, Benjamin Herrenschmidt wrote:
> The nvram log partition stuff currently in nvram_64.c is really
> pseries specific. It isn't actually used on anything else (despite
> the fact that we ran the code to setup the partition on anything
> except powermac) and the log format is specific to pseries RTAS
> implementation. So move it where it belongs

Some glitches in this one, like the wrong init order. I'll move
the nvram scan to be explicitely called by archs who want that stuff.

In fact, I might move the whole partition handling to a separate
file to be selected by archs who want it, and try to merge that with
powermac, but at least we have a first step here.

I'll send an updated patch later, in case there are other comments.

Cheers,
Ben.

> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> ---
>  arch/powerpc/include/asm/nvram.h       |    9 ++-
>  arch/powerpc/kernel/nvram_64.c         |  216 +-------------------------------
>  arch/powerpc/platforms/pseries/nvram.c |  196 +++++++++++++++++++++++++++++
>  3 files changed, 208 insertions(+), 213 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/nvram.h b/arch/powerpc/include/asm/nvram.h
> index 459dc09..457a1a5 100644
> --- a/arch/powerpc/include/asm/nvram.h
> +++ b/arch/powerpc/include/asm/nvram.h
> @@ -30,13 +30,14 @@
>  #include <linux/errno.h>
>  #include <linux/list.h>
>  
> +#ifdef CONFIG_PPC_PSERIES
>  extern int nvram_write_error_log(char * buff, int length,
>  					 unsigned int err_type, unsigned int err_seq);
>  extern int nvram_read_error_log(char * buff, int length,
>  					 unsigned int * err_type, unsigned int *err_seq);
>  extern int nvram_clear_error_log(void);
> -
>  extern int pSeries_nvram_init(void);
> +#endif /* CONFIG_PPC_PSERIES */
>  
>  #ifdef CONFIG_MMIO_NVRAM
>  extern int mmio_nvram_init(void);
> @@ -47,6 +48,12 @@ static inline int mmio_nvram_init(void)
>  }
>  #endif
>  
> +extern loff_t nvram_create_partition(const char *name, int sig,
> +				     int req_size, int min_size);
> +extern int nvram_remove_partition(const char *name, int sig);
> +extern int nvram_get_partition_size(loff_t data_index);
> +extern loff_t nvram_find_partition(const char *name, int sig, int *out_size);
> +
>  #endif /* __KERNEL__ */
>  
>  /* PowerMac specific nvram stuffs */
> diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
> index ddc94cf..d467f8c 100644
> --- a/arch/powerpc/kernel/nvram_64.c
> +++ b/arch/powerpc/kernel/nvram_64.c
> @@ -36,8 +36,6 @@
>  
>  #define NVRAM_HEADER_LEN	sizeof(struct nvram_header)
>  #define NVRAM_BLOCK_LEN		NVRAM_HEADER_LEN
> -#define NVRAM_MAX_REQ		2079
> -#define NVRAM_MIN_REQ		1055
>  
>  /* If change this size, then change the size of NVNAME_LEN */
>  struct nvram_header {
> @@ -54,13 +52,6 @@ struct nvram_partition {
>  };
>  
>  static struct nvram_partition * nvram_part;
> -static long nvram_error_log_index = -1;
> -static long nvram_error_log_size = 0;
> -
> -struct err_log_info {
> -	int error_type;
> -	unsigned int seq_num;
> -};
>  
>  static loff_t dev_nvram_llseek(struct file *file, loff_t offset, int origin)
>  {
> @@ -254,7 +245,7 @@ static unsigned char __init nvram_checksum(struct nvram_header *p)
>   * @sig: signature of the partition(s) to remove
>   */
>  
> -static int __init nvram_remove_partition(const char *name, int sig)
> +int __init nvram_remove_partition(const char *name, int sig)
>  {
>  	struct nvram_partition *part, *prev, *tmp;
>  	int rc;
> @@ -313,8 +304,8 @@ static int __init nvram_remove_partition(const char *name, int sig)
>   * you need to query for the actual size yourself after the
>   * call using nvram_partition_get_size().
>   */
> -static loff_t __init nvram_create_partition(const char *name, int sig,
> -					    int req_size, int min_size)
> +loff_t __init nvram_create_partition(const char *name, int sig,
> +				     int req_size, int min_size)
>  {
>  	struct nvram_partition *part;
>  	struct nvram_partition *new_part;
> @@ -417,7 +408,7 @@ static loff_t __init nvram_create_partition(const char *name, int sig,
>   *              the partition. The same value that is returned by
>   *              nvram_create_partition().
>   */
> -static int nvram_get_partition_size(loff_t data_index)
> +int nvram_get_partition_size(loff_t data_index)
>  {
>  	struct nvram_partition *part;
>  	
> @@ -451,74 +442,6 @@ loff_t nvram_find_partition(const char *name, int sig, int *out_size)
>  	return 0;
>  }
>  
> -/* nvram_setup_partition
> - *
> - * This will setup the partition we need for buffering the
> - * error logs and cleanup partitions if needed.
> - *
> - * The general strategy is the following:
> - * 1.) If there is ppc64,linux partition large enough then use it.
> - * 2.) If there is not a ppc64,linux partition large enough, search
> - * for a free partition that is large enough.
> - * 3.) If there is not a free partition large enough remove 
> - * _all_ OS partitions and consolidate the space.
> - * 4.) Will first try getting a chunk that will satisfy the maximum
> - * error log size (NVRAM_MAX_REQ).
> - * 5.) If the max chunk cannot be allocated then try finding a chunk
> - * that will satisfy the minum needed (NVRAM_MIN_REQ).
> - */
> -static int __init nvram_setup_partition(void)
> -{
> -	loff_t p;
> -	int size;
> -
> -	/* For now, we don't do any of this on pmac, until I
> -	 * have figured out if it's worth killing some unused stuffs
> -	 * in our nvram, as Apple defined partitions use pretty much
> -	 * all of the space
> -	 */
> -	if (machine_is(powermac))
> -		return -ENOSPC;
> -
> -	p = nvram_find_partition("ppc64,linux", NVRAM_SIG_OS, &size);
> -
> -	/* Found one but too small, remove it */
> -	if (p && size < NVRAM_MIN_REQ) {
> -		pr_info("nvram: Found too small ppc64,linux partition"
> -			",removing it...");
> -		nvram_remove_partition("ppc64,linux", NVRAM_SIG_OS);
> -		p = 0;
> -	}
> -
> -	/* Create one if we didn't find */
> -	if (!p) {
> -		p = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
> -					   NVRAM_MIN_REQ, NVRAM_MAX_REQ);
> -		/* No room for it, try to get rid of any OS partition
> -		 * and try again
> -		 */
> -		if (p == -ENOSPC) {
> -			pr_info("nvram: No room to create ppc64,linux"
> -				" partition, deleting all OS partitions...");
> -			nvram_remove_partition(NULL, NVRAM_SIG_OS);
> -			p = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
> -						   NVRAM_MIN_REQ, NVRAM_MAX_REQ);
> -		}
> -	}
> -
> -	if (p <= 0) {
> -		pr_err("nvram: Failed to find or create ppc64,linux"
> -		       " partition, err %d\n", (int)p);
> -		return 0;
> -	}
> -
> -	nvram_error_log_index = p;
> -	nvram_error_log_size = nvram_get_partition_size(p) -
> -		sizeof(struct err_log_info);
> -	
> -	return 0;
> -}
> -
>  static int __init nvram_scan_partitions(void)
>  {
>  	loff_t cur_index = 0;
> @@ -617,10 +540,6 @@ static int __init nvram_init(void)
>    		printk(KERN_ERR "nvram_init: Failed nvram_scan_partitions\n");
>    		return error;
>    	}
> -  		
> -  	if(nvram_setup_partition()) 
> -  		printk(KERN_WARNING "nvram_init: Could not find nvram partition"
> -  		       " for nvram buffered error logging.\n");
>    
>  #ifdef DEBUG_NVRAM
>  	nvram_print_partitions("NVRAM Partitions");
> @@ -635,133 +554,6 @@ void __exit nvram_cleanup(void)
>  }
>  
> 
> -#ifdef CONFIG_PPC_PSERIES
> -
> -/* nvram_write_error_log
> - *
> - * We need to buffer the error logs into nvram to ensure that we have
> - * the failure information to decode.  If we have a severe error there
> - * is no way to guarantee that the OS or the machine is in a state to
> - * get back to user land and write the error to disk.  For example if
> - * the SCSI device driver causes a Machine Check by writing to a bad
> - * IO address, there is no way of guaranteeing that the device driver
> - * is in any state that is would also be able to write the error data
> - * captured to disk, thus we buffer it in NVRAM for analysis on the
> - * next boot.
> - *
> - * In NVRAM the partition containing the error log buffer will looks like:
> - * Header (in bytes):
> - * +-----------+----------+--------+------------+------------------+
> - * | signature | checksum | length | name       | data             |
> - * |0          |1         |2      3|4         15|16        length-1|
> - * +-----------+----------+--------+------------+------------------+
> - *
> - * The 'data' section would look like (in bytes):
> - * +--------------+------------+-----------------------------------+
> - * | event_logged | sequence # | error log                         |
> - * |0            3|4          7|8            nvram_error_log_size-1|
> - * +--------------+------------+-----------------------------------+
> - *
> - * event_logged: 0 if event has not been logged to syslog, 1 if it has
> - * sequence #: The unique sequence # for each event. (until it wraps)
> - * error log: The error log from event_scan
> - */
> -int nvram_write_error_log(char * buff, int length,
> -                          unsigned int err_type, unsigned int error_log_cnt)
> -{
> -	int rc;
> -	loff_t tmp_index;
> -	struct err_log_info info;
> -	
> -	if (nvram_error_log_index == -1) {
> -		return -ESPIPE;
> -	}
> -
> -	if (length > nvram_error_log_size) {
> -		length = nvram_error_log_size;
> -	}
> -
> -	info.error_type = err_type;
> -	info.seq_num = error_log_cnt;
> -
> -	tmp_index = nvram_error_log_index;
> -
> -	rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info), &tmp_index);
> -	if (rc <= 0) {
> -		printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc);
> -		return rc;
> -	}
> -
> -	rc = ppc_md.nvram_write(buff, length, &tmp_index);
> -	if (rc <= 0) {
> -		printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc);
> -		return rc;
> -	}
> -	
> -	return 0;
> -}
> -
> -/* nvram_read_error_log
> - *
> - * Reads nvram for error log for at most 'length'
> - */
> -int nvram_read_error_log(char * buff, int length,
> -                         unsigned int * err_type, unsigned int * error_log_cnt)
> -{
> -	int rc;
> -	loff_t tmp_index;
> -	struct err_log_info info;
> -	
> -	if (nvram_error_log_index == -1)
> -		return -1;
> -
> -	if (length > nvram_error_log_size)
> -		length = nvram_error_log_size;
> -
> -	tmp_index = nvram_error_log_index;
> -
> -	rc = ppc_md.nvram_read((char *)&info, sizeof(struct err_log_info), &tmp_index);
> -	if (rc <= 0) {
> -		printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc);
> -		return rc;
> -	}
> -
> -	rc = ppc_md.nvram_read(buff, length, &tmp_index);
> -	if (rc <= 0) {
> -		printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc);
> -		return rc;
> -	}
> -
> -	*error_log_cnt = info.seq_num;
> -	*err_type = info.error_type;
> -
> -	return 0;
> -}
> -
> -/* This doesn't actually zero anything, but it sets the event_logged
> - * word to tell that this event is safely in syslog.
> - */
> -int nvram_clear_error_log(void)
> -{
> -	loff_t tmp_index;
> -	int clear_word = ERR_FLAG_ALREADY_LOGGED;
> -	int rc;
> -
> -	if (nvram_error_log_index == -1)
> -		return -1;
> -
> -	tmp_index = nvram_error_log_index;
> -	
> -	rc = ppc_md.nvram_write((char *)&clear_word, sizeof(int), &tmp_index);
> -	if (rc <= 0) {
> -		printk(KERN_ERR "nvram_clear_error_log: Failed nvram_write (%d)\n", rc);
> -		return rc;
> -	}
> -
> -	return 0;
> -}
> -
> -#endif /* CONFIG_PPC_PSERIES */
>  
>  module_init(nvram_init);
>  module_exit(nvram_cleanup);
> diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
> index 2a1ef5c..c8b3f0f 100644
> --- a/arch/powerpc/platforms/pseries/nvram.c
> +++ b/arch/powerpc/platforms/pseries/nvram.c
> @@ -30,6 +30,16 @@ static int nvram_fetch, nvram_store;
>  static char nvram_buf[NVRW_CNT];	/* assume this is in the first 4GB */
>  static DEFINE_SPINLOCK(nvram_lock);
>  
> +static long nvram_error_log_index = -1;
> +static long nvram_error_log_size = 0;
> +
> +struct err_log_info {
> +	int error_type;
> +	unsigned int seq_num;
> +};
> +#define NVRAM_MAX_REQ		2079
> +#define NVRAM_MIN_REQ		1055
> +
>  static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
>  {
>  	unsigned int i;
> @@ -121,6 +131,192 @@ static ssize_t pSeries_nvram_get_size(void)
>  	return nvram_size ? nvram_size : -ENODEV;
>  }
>  
> +
> +/* nvram_write_error_log
> + *
> + * We need to buffer the error logs into nvram to ensure that we have
> + * the failure information to decode.  If we have a severe error there
> + * is no way to guarantee that the OS or the machine is in a state to
> + * get back to user land and write the error to disk.  For example if
> + * the SCSI device driver causes a Machine Check by writing to a bad
> + * IO address, there is no way of guaranteeing that the device driver
> + * is in any state that is would also be able to write the error data
> + * captured to disk, thus we buffer it in NVRAM for analysis on the
> + * next boot.
> + *
> + * In NVRAM the partition containing the error log buffer will looks like:
> + * Header (in bytes):
> + * +-----------+----------+--------+------------+------------------+
> + * | signature | checksum | length | name       | data             |
> + * |0          |1         |2      3|4         15|16        length-1|
> + * +-----------+----------+--------+------------+------------------+
> + *
> + * The 'data' section would look like (in bytes):
> + * +--------------+------------+-----------------------------------+
> + * | event_logged | sequence # | error log                         |
> + * |0            3|4          7|8            nvram_error_log_size-1|
> + * +--------------+------------+-----------------------------------+
> + *
> + * event_logged: 0 if event has not been logged to syslog, 1 if it has
> + * sequence #: The unique sequence # for each event. (until it wraps)
> + * error log: The error log from event_scan
> + */
> +int nvram_write_error_log(char * buff, int length,
> +                          unsigned int err_type, unsigned int error_log_cnt)
> +{
> +	int rc;
> +	loff_t tmp_index;
> +	struct err_log_info info;
> +	
> +	if (nvram_error_log_index == -1) {
> +		return -ESPIPE;
> +	}
> +
> +	if (length > nvram_error_log_size) {
> +		length = nvram_error_log_size;
> +	}
> +
> +	info.error_type = err_type;
> +	info.seq_num = error_log_cnt;
> +
> +	tmp_index = nvram_error_log_index;
> +
> +	rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info), &tmp_index);
> +	if (rc <= 0) {
> +		printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc);
> +		return rc;
> +	}
> +
> +	rc = ppc_md.nvram_write(buff, length, &tmp_index);
> +	if (rc <= 0) {
> +		printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc);
> +		return rc;
> +	}
> +	
> +	return 0;
> +}
> +
> +/* nvram_read_error_log
> + *
> + * Reads nvram for error log for at most 'length'
> + */
> +int nvram_read_error_log(char * buff, int length,
> +                         unsigned int * err_type, unsigned int * error_log_cnt)
> +{
> +	int rc;
> +	loff_t tmp_index;
> +	struct err_log_info info;
> +	
> +	if (nvram_error_log_index == -1)
> +		return -1;
> +
> +	if (length > nvram_error_log_size)
> +		length = nvram_error_log_size;
> +
> +	tmp_index = nvram_error_log_index;
> +
> +	rc = ppc_md.nvram_read((char *)&info, sizeof(struct err_log_info), &tmp_index);
> +	if (rc <= 0) {
> +		printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc);
> +		return rc;
> +	}
> +
> +	rc = ppc_md.nvram_read(buff, length, &tmp_index);
> +	if (rc <= 0) {
> +		printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc);
> +		return rc;
> +	}
> +
> +	*error_log_cnt = info.seq_num;
> +	*err_type = info.error_type;
> +
> +	return 0;
> +}
> +
> +/* This doesn't actually zero anything, but it sets the event_logged
> + * word to tell that this event is safely in syslog.
> + */
> +int nvram_clear_error_log(void)
> +{
> +	loff_t tmp_index;
> +	int clear_word = ERR_FLAG_ALREADY_LOGGED;
> +	int rc;
> +
> +	if (nvram_error_log_index == -1)
> +		return -1;
> +
> +	tmp_index = nvram_error_log_index;
> +	
> +	rc = ppc_md.nvram_write((char *)&clear_word, sizeof(int), &tmp_index);
> +	if (rc <= 0) {
> +		printk(KERN_ERR "nvram_clear_error_log: Failed nvram_write (%d)\n", rc);
> +		return rc;
> +	}
> +
> +	return 0;
> +}
> +
> +/* pseries_nvram_init_log_partition
> + *
> + * This will setup the partition we need for buffering the
> + * error logs and cleanup partitions if needed.
> + *
> + * The general strategy is the following:
> + * 1.) If there is ppc64,linux partition large enough then use it.
> + * 2.) If there is not a ppc64,linux partition large enough, search
> + * for a free partition that is large enough.
> + * 3.) If there is not a free partition large enough remove 
> + * _all_ OS partitions and consolidate the space.
> + * 4.) Will first try getting a chunk that will satisfy the maximum
> + * error log size (NVRAM_MAX_REQ).
> + * 5.) If the max chunk cannot be allocated then try finding a chunk
> + * that will satisfy the minum needed (NVRAM_MIN_REQ).
> + */
> +static int __init pseries_nvram_init_log_partition(void)
> +{
> +	loff_t p;
> +	int size;
> +
> +	p = nvram_find_partition("ppc64,linux", NVRAM_SIG_OS, &size);
> +
> +	/* Found one but too small, remove it */
> +	if (p && size < NVRAM_MIN_REQ) {
> +		pr_info("nvram: Found too small ppc64,linux partition"
> +			",removing it...");
> +		nvram_remove_partition("ppc64,linux", NVRAM_SIG_OS);
> +		p = 0;
> +	}
> +
> +	/* Create one if we didn't find */
> +	if (!p) {
> +		p = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
> +					   NVRAM_MIN_REQ, NVRAM_MAX_REQ);
> +		/* No room for it, try to get rid of any OS partition
> +		 * and try again
> +		 */
> +		if (p == -ENOSPC) {
> +			pr_info("nvram: No room to create ppc64,linux"
> +				" partition, deleting all OS partitions...");
> +			nvram_remove_partition(NULL, NVRAM_SIG_OS);
> +			p = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
> +						   NVRAM_MIN_REQ, NVRAM_MAX_REQ);
> +		}
> +	}
> +
> +	if (p <= 0) {
> +		pr_err("nvram: Failed to find or create ppc64,linux"
> +		       " partition, err %d\n", (int)p);
> +		return 0;
> +	}
> +
> +	nvram_error_log_index = p;
> +	nvram_error_log_size = nvram_get_partition_size(p) -
> +		sizeof(struct err_log_info);
> +	
> +	return 0;
> +}
> +machine_arch_initcall(pseries, pseries_nvram_init_log_partition);
> +
>  int __init pSeries_nvram_init(void)
>  {
>  	struct device_node *nvram;

^ permalink raw reply

* Re: [PATCH 02/11] powerpc/nvram: More flexible nvram_create_partition()
From: Michael Ellerman @ 2010-08-02  3:43 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1280710522-6362-3-git-send-email-benh@kernel.crashing.org>

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

On Mon, 2010-08-02 at 10:55 +1000, Benjamin Herrenschmidt wrote:
> Replace nvram_create_os_partition() with a variant that takes
> the partition name, signature and size as arguments.
> 
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> ---
>  arch/powerpc/kernel/nvram_64.c         |   46 +++++++++++++++++++------------
>  arch/powerpc/platforms/pseries/nvram.c |    6 ++--
>  2 files changed, 31 insertions(+), 21 deletions(-)
> 
> diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
> index a8154f1..974b3ec 100644
> --- a/arch/powerpc/kernel/nvram_64.c
> +++ b/arch/powerpc/kernel/nvram_64.c
> @@ -307,13 +307,15 @@ static int __init nvram_remove_os_partition(void)
>  	return 0;
>  }
>  
> -/* nvram_create_os_partition
> - *
> - * Create a OS linux partition to buffer error logs.
> - * Will create a partition starting at the first free
> - * space found if space has enough room.
> +/**
> + * nvram_create_partition - Create a partition in nvram
> + * @name: name of the partition to create
> + * @sig: signature of the partition to create
> + * @req_size: size to allocate preferrably
> + * @min_size: minimum acceptable size (0 means req_size)
>   */
> -static int __init nvram_create_os_partition(void)
> +static int __init nvram_create_partition(const char *name, int sig,
> +					 int req_size, int min_size)
>  {
>  	struct nvram_partition *part;
>  	struct nvram_partition *new_part;
> @@ -322,20 +324,27 @@ static int __init nvram_create_os_partition(void)
>  	loff_t tmp_index;
>  	long size = 0;
>  	int rc;
> -	
> +
> +	/* If no minimum size specified, make it the same as the
> +	 * requested size
> +	 */
> +	if (min_size == 0)
> +		min_size = req_size;
> +
>  	/* Find a free partition that will give us the maximum needed size 
>  	   If can't find one that will give us the minimum size needed */
>  	list_for_each_entry(part, &nvram_part->partition, partition) {
>  		if (part->header.signature != NVRAM_SIG_FREE)
>  			continue;
>  
> -		if (part->header.length >= NVRAM_MAX_REQ) {
> -			size = NVRAM_MAX_REQ;
> +		if (part->header.length >= req_size) {
> +			size = req_size;
>  			free_part = part;
>  			break;
>  		}
> -		if (!size && part->header.length >= NVRAM_MIN_REQ) {
> -			size = NVRAM_MIN_REQ;
> +		if (part->header.length > size &&
> +		    part->header.length >= min_size) {
> +			size = part->header.length;
>  			free_part = part;
>  		}

I can't quite convince myself that this is right, but perhaps I just
need a coffee.

> @@ -350,9 +359,9 @@ static int __init nvram_create_os_partition(void)
>  	}
>  
>  	new_part->index = free_part->index;
> -	new_part->header.signature = NVRAM_SIG_OS;
> +	new_part->header.signature = sig;
>  	new_part->header.length = size;
> -	strcpy(new_part->header.name, "ppc64,linux");
> +	strncpy(new_part->header.name, name, 12);

Should we be checking the name fits?

>  	new_part->header.checksum = nvram_checksum(&new_part->header);
>  
>  	rc = nvram_write_header(new_part);
> @@ -451,10 +460,10 @@ static int __init nvram_setup_partition(void)
>  	}
>  	
>  	/* try creating a partition with the free space we have */
> -	rc = nvram_create_partition("ppc64,linux", );

That looks odd? Trailing comma.

> -	if (!rc) {
> +	rc = 	nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
> +				       NVRAM_MIN_REQ, NVRAM_MAX_REQ);

Odd whitespace.

> +	if (!rc)
>  		return 0;
> -	}
>  		
>  	/* need to free up some space */
>  	rc = nvram_remove_os_partition();
> @@ -463,9 +472,10 @@ static int __init nvram_setup_partition(void)
>  	}
>  	
>  	/* create a partition in this new space */
> -	rc = nvram_create_os_partition();
> +	rc = 	nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
> +				       NVRAM_MIN_REQ, NVRAM_MAX_REQ);

And again.

>  	if (rc) {
> -		printk(KERN_ERR "nvram_create_os_partition: Could not find a "
> +		printk(KERN_ERR "nvram_create_partition: Could not find a "
>  		       "NVRAM partition large enough\n");

pr_err("%s: ..", __func__, ..) if you're touching it anyway?

> diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
> index f4e4c06..2a1ef5c 100644
> --- a/arch/powerpc/platforms/pseries/nvram.c
> +++ b/arch/powerpc/platforms/pseries/nvram.c
> @@ -22,14 +22,14 @@
>  #include <asm/prom.h>
>  #include <asm/machdep.h>
>  
> +/* Max bytes to read/write in one go */
> +#define NVRW_CNT 0x20
> +
>  static unsigned int nvram_size;
>  static int nvram_fetch, nvram_store;
>  static char nvram_buf[NVRW_CNT];	/* assume this is in the first 4GB */
>  static DEFINE_SPINLOCK(nvram_lock);
>  
> -/* Max bytes to read/write in one go */
> -#define NVRW_CNT 0x20
> -

Churn alert, you just moved that hunk there in the previous patch.

cheers



[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply

* Re: [PATCH 03/11] powerpc/nvram: nvram_create_partitions() now uses bytes
From: Michael Ellerman @ 2010-08-02  3:47 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1280710522-6362-4-git-send-email-benh@kernel.crashing.org>

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

On Mon, 2010-08-02 at 10:55 +1000, Benjamin Herrenschmidt wrote:
> This converts nvram_create_partition() to use a size in bytes
> rather than blocks. It does the appropriate alignment internally
> 
> The size passed is also the data size (ie. doesn't include the
> header anymore).
> 
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> ---
>  arch/powerpc/kernel/nvram_64.c |   20 ++++++++++++++------
>  1 files changed, 14 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
> index 974b3ec..b0f2114 100644
> --- a/arch/powerpc/kernel/nvram_64.c
> +++ b/arch/powerpc/kernel/nvram_64.c
> @@ -34,10 +34,10 @@
>  
>  #undef DEBUG_NVRAM
>  
> -#define NVRAM_HEADER_LEN 16 /* sizeof(struct nvram_header) */
> -#define NVRAM_BLOCK_LEN 16
> -#define NVRAM_MAX_REQ (2080/NVRAM_BLOCK_LEN)
> -#define NVRAM_MIN_REQ (1056/NVRAM_BLOCK_LEN)
> +#define NVRAM_HEADER_LEN	sizeof(struct nvram_header)
> +#define NVRAM_BLOCK_LEN		NVRAM_HEADER_LEN
> +#define NVRAM_MAX_REQ		2079
> +#define NVRAM_MIN_REQ		1055

You don't change any callers, but that's because they use these #defines
right.

cheers

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply

* Re: [PATCH 05/11] powerpc/nvram: Completely clear a new partition
From: Michael Ellerman @ 2010-08-02  3:50 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1280710522-6362-6-git-send-email-benh@kernel.crashing.org>

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

On Mon, 2010-08-02 at 10:55 +1000, Benjamin Herrenschmidt wrote:
> When creating a partition, we clear it entirely rather than
> just the first two words since the previous code was rather
> specific to the pseries log partition format.
> 
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> ---
>  arch/powerpc/kernel/nvram_64.c |   19 ++++++++++---------
>  1 files changed, 10 insertions(+), 9 deletions(-)
> 
> diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
> index dd18a5a..7ddeaa6 100644
> --- a/arch/powerpc/kernel/nvram_64.c
> +++ b/arch/powerpc/kernel/nvram_64.c
> @@ -320,7 +320,7 @@ static int __init nvram_create_partition(const char *name, int sig,
>  	struct nvram_partition *part;
>  	struct nvram_partition *new_part;
>  	struct nvram_partition *free_part = NULL;
> -	int seq_init[2] = { 0, 0 };
> +	static char nv_init_vals[16];

Or should we just grab a zeroed page?

>  	loff_t tmp_index;
>  	long size = 0;
>  	int rc;
> @@ -379,14 +379,15 @@ static int __init nvram_create_partition(const char *name, int sig,
>  		return rc;
>  	}
>  
> -	/* make sure and initialize to zero the sequence number and the error
> -	   type logged */
> -	tmp_index = new_part->index + NVRAM_HEADER_LEN;
> -	rc = ppc_md.nvram_write((char *)&seq_init, sizeof(seq_init), &tmp_index);
> -	if (rc <= 0) {
> -		printk(KERN_ERR "nvram_create_os_partition: nvram_write "
> -		       "failed (%d)\n", rc);
> -		return rc;
> +	/* Clear the partition */
> +	for (tmp_index = new_part->index + NVRAM_HEADER_LEN;
> +	     tmp_index <  ((size - 1) * NVRAM_BLOCK_LEN);
                          ^
Extra whitespace          |

cheers


[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply

* Re: [PATCH 02/11] powerpc/nvram: More flexible nvram_create_partition()
From: Benjamin Herrenschmidt @ 2010-08-02  3:54 UTC (permalink / raw)
  To: michael; +Cc: linuxppc-dev
In-Reply-To: <1280720607.2491.175.camel@concordia>

On Mon, 2010-08-02 at 13:43 +1000, Michael Ellerman wrote:

> >  	
> >  	/* try creating a partition with the free space we have */
> > -	rc = nvram_create_partition("ppc64,linux", );
> 
> That looks odd? Trailing comma.

Yeah, that and...

> > diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
> > index f4e4c06..2a1ef5c 100644
> > --- a/arch/powerpc/platforms/pseries/nvram.c
> > +++ b/arch/powerpc/platforms/pseries/nvram.c
> > @@ -22,14 +22,14 @@
> >  #include <asm/prom.h>
> >  #include <asm/machdep.h>
> >  
> > +/* Max bytes to read/write in one go */
> > +#define NVRW_CNT 0x20
> > +
> >  static unsigned int nvram_size;
> >  static int nvram_fetch, nvram_store;
> >  static char nvram_buf[NVRW_CNT];	/* assume this is in the first 4GB */
> >  static DEFINE_SPINLOCK(nvram_lock);
> >  
> > -/* Max bytes to read/write in one go */
> > -#define NVRW_CNT 0x20
> > -
> 
> Churn alert, you just moved that hunk there in the previous patch.

 ... that are local rebasing fu*kage.

I'll sort all that out in the next version.

Thanks,
Ben.

^ permalink raw reply

* [PATCH] perf, powerpc: Convert the FSL driver to use local64_t
From: Paul Mackerras @ 2010-08-02  6:18 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Peter Zijlstra

From: Peter Zijlstra <a.p.zijlstra@chello.nl>

For some reason the FSL driver got left out when we converted perf
to use local64_t instead of atomic64_t.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
---
This is against the perf/core branch in the tip tree at
git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
Posting here for comment.

 arch/powerpc/kernel/perf_event_fsl_emb.c |   28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

Index: linux-2.6/arch/powerpc/kernel/perf_event_fsl_emb.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/perf_event_fsl_emb.c
+++ linux-2.6/arch/powerpc/kernel/perf_event_fsl_emb.c
@@ -162,15 +162,15 @@ static void fsl_emb_pmu_read(struct perf
 	 * Therefore we treat them like NMIs.
 	 */
 	do {
-		prev = atomic64_read(&event->hw.prev_count);
+		prev = local64_read(&event->hw.prev_count);
 		barrier();
 		val = read_pmc(event->hw.idx);
-	} while (atomic64_cmpxchg(&event->hw.prev_count, prev, val) != prev);
+	} while (local64_cmpxchg(&event->hw.prev_count, prev, val) != prev);
 
 	/* The counters are only 32 bits wide */
 	delta = (val - prev) & 0xfffffffful;
-	atomic64_add(delta, &event->count);
-	atomic64_sub(delta, &event->hw.period_left);
+	local64_add(delta, &event->count);
+	local64_sub(delta, &event->hw.period_left);
 }
 
 /*
@@ -296,11 +296,11 @@ static int fsl_emb_pmu_enable(struct per
 
 	val = 0;
 	if (event->hw.sample_period) {
-		s64 left = atomic64_read(&event->hw.period_left);
+		s64 left = local64_read(&event->hw.period_left);
 		if (left < 0x80000000L)
 			val = 0x80000000L - left;
 	}
-	atomic64_set(&event->hw.prev_count, val);
+	local64_set(&event->hw.prev_count, val);
 	write_pmc(i, val);
 	perf_event_update_userpage(event);
 
@@ -371,8 +371,8 @@ static void fsl_emb_pmu_unthrottle(struc
 	if (left < 0x80000000L)
 		val = 0x80000000L - left;
 	write_pmc(event->hw.idx, val);
-	atomic64_set(&event->hw.prev_count, val);
-	atomic64_set(&event->hw.period_left, left);
+	local64_set(&event->hw.prev_count, val);
+	local64_set(&event->hw.period_left, left);
 	perf_event_update_userpage(event);
 	perf_enable();
 	local_irq_restore(flags);
@@ -500,7 +500,7 @@ const struct pmu *hw_perf_event_init(str
 		return ERR_PTR(-ENOTSUPP);
 
 	event->hw.last_period = event->hw.sample_period;
-	atomic64_set(&event->hw.period_left, event->hw.last_period);
+	local64_set(&event->hw.period_left, event->hw.last_period);
 
 	/*
 	 * See if we need to reserve the PMU.
@@ -541,16 +541,16 @@ static void record_and_restart(struct pe
 	int record = 0;
 
 	/* we don't have to worry about interrupts here */
-	prev = atomic64_read(&event->hw.prev_count);
+	prev = local64_read(&event->hw.prev_count);
 	delta = (val - prev) & 0xfffffffful;
-	atomic64_add(delta, &event->count);
+	local64_add(delta, &event->count);
 
 	/*
 	 * See if the total period for this event has expired,
 	 * and update for the next period.
 	 */
 	val = 0;
-	left = atomic64_read(&event->hw.period_left) - delta;
+	left = local64_read(&event->hw.period_left) - delta;
 	if (period) {
 		if (left <= 0) {
 			left += period;
@@ -584,8 +584,8 @@ static void record_and_restart(struct pe
 	}
 
 	write_pmc(event->hw.idx, val);
-	atomic64_set(&event->hw.prev_count, val);
-	atomic64_set(&event->hw.period_left, left);
+	local64_set(&event->hw.prev_count, val);
+	local64_set(&event->hw.period_left, left);
 	perf_event_update_userpage(event);
 }
 

^ permalink raw reply

* RE: [PATCH 3/3 v2] mmc: Add ESDHC weird voltage bits workaround
From: Zang Roy-R61911 @ 2010-08-02  6:19 UTC (permalink / raw)
  To: Anton Vorontsov; +Cc: linuxppc-dev, akpm, linux-mmc
In-Reply-To: <20100730070624.GB20351@oksana.dev.rtsoft.ru>

=20

> -----Original Message-----
> From: Anton Vorontsov [mailto:cbouatmailru@gmail.com]=20
> Sent: Friday, July 30, 2010 15:06 PM
> To: Zang Roy-R61911
> Cc: linux-mmc@vger.kernel.org; linuxppc-dev@ozlabs.org;=20
> akpm@linux-foundation.org
> Subject: Re: [PATCH 3/3 v2] mmc: Add ESDHC weird voltage bits=20
> workaround
>=20
> On Fri, Jul 30, 2010 at 11:52:57AM +0800, Roy Zang wrote:
> > P4080 ESDHC controller does not support 1.8V and 3.0V=20
> voltage. but the
> > host controller capabilities register wrongly set the bits.
> > This patch adds the workaround to correct the weird voltage=20
> setting bits.
> >=20
> > Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
> > ---
> [...]
> > diff --git a/drivers/mmc/host/sdhci-of-core.c=20
> b/drivers/mmc/host/sdhci-of-core.c
> > index 0c30242..1f3913d 100644
> > --- a/drivers/mmc/host/sdhci-of-core.c
> > +++ b/drivers/mmc/host/sdhci-of-core.c
> > @@ -164,6 +164,10 @@ static int __devinit=20
> sdhci_of_probe(struct of_device *ofdev,
> >  	if (sdhci_of_wp_inverted(np))
> >  		host->quirks |=3D SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
> > =20
> > +	if (of_device_is_compatible(np, "fsl,p4080-esdhc"))
> > +		host->quirks |=3D (SDHCI_QUIRK_QORIQ_NO_VDD_180
> > +				|SDHCI_QUIRK_QORIQ_NO_VDD_300);
> > +
>=20
> It should be two properties, something like sdhci,no-vdd-180
> and sdhci,no-vdd-300. But it might be even better: we have
> voltage-ranges for mmc-spi case, see
> Documentation/powerpc/dts-bindings/mmc-spi-slot.txt.
>=20
> If voltage-ranges specified, then we use it, not capabilities
> register.
>=20
> For p4080 it will be 'voltage-ranges =3D <3200 3400>;'. So, with
> voltage-ranges we can do fine grained VDD control without
> introducing anything new.
why not
               voltage-ranges =3D <3300 3300>;
?
Roy

^ permalink raw reply

* Re: ramdisk size is larger than 4MB
From: Shawn Jin @ 2010-08-02  6:34 UTC (permalink / raw)
  To: Scott Wood; +Cc: ppcdev
In-Reply-To: <AANLkTim0pD9LWEgWjX4QvqUkZkYO3YOeELz_XjNJPDft@mail.gmail.com>

>> It should be fine to just change it locally. =A0It would be a problem to
>> change it upstream for all boards, since some supported boards have
>> only 16MB (or even 8MB) of RAM.
>
> I'll definitely try to change it locally first. Would a configurable
> base address for the bootwrapper an acceptable solution?

I found the link_address in the wrapper shell script sets the _start
address. But after changing it to 0x800000, the kernel failed to boot,
shown below. There must be something also needs proper adjustment.
What would that be?

=3D> bootm 4000000
## Booting image at 04000000 ...
   Image Name:   Linux-2.6.33.5
   Image Type:   PowerPC Linux Kernel Image (gzip compressed)
   Data Size:    1757356 Bytes =3D  1.7 MB
   Load Address: 00800000
   Entry Point:  00800554
   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK
Memory <- <0x0 0x8000000> (128MB)
ENET0: local-mac-address <- 00:09:9b:01:58:64
CPU clock-frequency <- 0x7270e00 (120MHz)
CPU timebase-frequency <- 0x7270e0 (8MHz)
CPU bus-frequency <- 0x3938700 (60MHz)

zImage starting: loaded at 0x00800000 (sp: 0x07d1cbd0)
Allocating 0x3a15a4 bytes for kernel ...
gunzipping (0x00000000 <- 0x0080c000:0x00bd702c)...done 0x3886ec bytes

Linux/PowerPC load: root=3D/dev/ram
Finalizing device tree... flat tree at 0xbe4300

Thanks a lot,
-Shawn.

^ 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