LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH 2/2] powerpc: pcm030/032: add pagesize to dts
From: Anton Vorontsov @ 2010-11-15 17:32 UTC (permalink / raw)
  To: Wolfram Sang; +Cc: linuxppc-dev, devicetree-discuss
In-Reply-To: <1289841916-3825-2-git-send-email-w.sang@pengutronix.de>

On Mon, Nov 15, 2010 at 06:25:16PM +0100, Wolfram Sang wrote:
> Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
> ---
>  arch/powerpc/boot/dts/pcm030.dts |    1 +
>  arch/powerpc/boot/dts/pcm032.dts |    3 ++-
>  2 files changed, 3 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/powerpc/boot/dts/pcm030.dts b/arch/powerpc/boot/dts/pcm030.dts
> index 8a4ec30..e7c36bc 100644
> --- a/arch/powerpc/boot/dts/pcm030.dts
> +++ b/arch/powerpc/boot/dts/pcm030.dts
> @@ -259,6 +259,7 @@
>  			eeprom@52 {
>  				compatible = "catalyst,24c32";
>  				reg = <0x52>;
> +				pagesize = <32>;

I think you'd better drop the pagesize property altogether, and
instead make the compatible string more specific (if needed at
all. are there any 'catalyst,24c32' chips with pagesize != 32?)

Thanks,

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

^ permalink raw reply

* [PATCH 2/2] powerpc: pcm030/032: add pagesize to dts
From: Wolfram Sang @ 2010-11-15 17:25 UTC (permalink / raw)
  To: devicetree-discuss; +Cc: linuxppc-dev
In-Reply-To: <1289841916-3825-1-git-send-email-w.sang@pengutronix.de>

Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
---
 arch/powerpc/boot/dts/pcm030.dts |    1 +
 arch/powerpc/boot/dts/pcm032.dts |    3 ++-
 2 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/boot/dts/pcm030.dts b/arch/powerpc/boot/dts/pcm030.dts
index 8a4ec30..e7c36bc 100644
--- a/arch/powerpc/boot/dts/pcm030.dts
+++ b/arch/powerpc/boot/dts/pcm030.dts
@@ -259,6 +259,7 @@
 			eeprom@52 {
 				compatible = "catalyst,24c32";
 				reg = <0x52>;
+				pagesize = <32>;
 			};
 		};
 
diff --git a/arch/powerpc/boot/dts/pcm032.dts b/arch/powerpc/boot/dts/pcm032.dts
index 85d857a..e175e2c 100644
--- a/arch/powerpc/boot/dts/pcm032.dts
+++ b/arch/powerpc/boot/dts/pcm032.dts
@@ -257,8 +257,9 @@
 				reg = <0x51>;
 			};
 			eeprom@52 {
-				compatible = "at24,24c32";
+				compatible = "catalyst,24c32";
 				reg = <0x52>;
+				pagesize = <32>;
 			};
 		};
 
-- 
1.7.2.3

^ permalink raw reply related

* [PATCH 1/2] misc: at24: parse OF-data, too
From: Wolfram Sang @ 2010-11-15 17:25 UTC (permalink / raw)
  To: devicetree-discuss; +Cc: linuxppc-dev

Information about the pagesize and read-only-status may also come from
the devicetree. Parse this data, too, and act accordingly. While we are
here, change the initialization printout a bit. write_max is useful to
know to detect performance bottlenecks, the rest is superfluous.

Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
---

Grant: As mentioned at ELCE10, I could pretty much respin this old approach I
tried roughly a year ago (just with archdata then). If the approach and docs
are good, I am fine with the patches entering via one of your trees.

 Documentation/powerpc/dts-bindings/eeprom.txt |   28 ++++++++++++++++++++++
 drivers/misc/eeprom/at24.c                    |   33 ++++++++++++++++++++-----
 2 files changed, 53 insertions(+), 6 deletions(-)
 create mode 100644 Documentation/powerpc/dts-bindings/eeprom.txt

diff --git a/Documentation/powerpc/dts-bindings/eeprom.txt b/Documentation/powerpc/dts-bindings/eeprom.txt
new file mode 100644
index 0000000..4342c10
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/eeprom.txt
@@ -0,0 +1,28 @@
+EEPROMs (I2C)
+
+Required properties:
+
+  - compatible : should be "<manufacturer>,<type>"
+		 If there is no specific driver for <manufacturer>, a generic
+		 driver based on <type> is selected. Possible types are:
+		 24c00, 24c01, 24c02, 24c04, 24c08, 24c16, 24c32, 24c64,
+		 24c128, 24c256, 24c512, 24c1024, spd
+
+  - reg : the I2C address of the EEPROM
+
+Optional properties:
+
+  - pagesize : the length of the pagesize for writing. Please consult the
+               manual of your device, that value varies a lot. A wrong value
+	       may result in data loss! If not specified, a safety value of
+	       '1' is used which will be very slow.
+
+  - read-only: this parameterless property disables writes to the eeprom
+
+Example:
+
+eeprom@52 {
+	compatible = "atmel,24c32";
+	reg = <0x52>;
+	pagesize = <32>;
+};
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index 559b0b3..aaf16cb 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -20,6 +20,7 @@
 #include <linux/log2.h>
 #include <linux/bitops.h>
 #include <linux/jiffies.h>
+#include <linux/of.h>
 #include <linux/i2c.h>
 #include <linux/i2c/at24.h>
 
@@ -457,6 +458,27 @@ static ssize_t at24_macc_write(struct memory_accessor *macc, const char *buf,
 
 /*-------------------------------------------------------------------------*/
 
+#ifdef CONFIG_OF
+static void at24_get_ofdata(struct i2c_client *client,
+		struct at24_platform_data *chip)
+{
+	const u32 *val;
+	struct device_node *node = client->dev.of_node;
+
+	if (node) {
+		if (of_get_property(node, "read-only", NULL))
+			chip->flags |= AT24_FLAG_READONLY;
+		val = of_get_property(node, "pagesize", NULL);
+		if (val)
+			chip->page_size = *val;
+	}
+}
+#else
+static void at24_get_ofdata(struct i2c_client *client,
+		struct at24_platform_data *chip)
+{ }
+#endif /* CONFIG_OF */
+
 static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	struct at24_platform_data chip;
@@ -485,6 +507,9 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		 */
 		chip.page_size = 1;
 
+		/* update chipdata if OF is present */
+		at24_get_ofdata(client, &chip);
+
 		chip.setup = NULL;
 		chip.context = NULL;
 	}
@@ -597,19 +622,15 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
 	i2c_set_clientdata(client, at24);
 
-	dev_info(&client->dev, "%zu byte %s EEPROM %s\n",
+	dev_info(&client->dev, "%zu byte %s EEPROM, %s, %u bytes/write\n",
 		at24->bin.size, client->name,
-		writable ? "(writable)" : "(read-only)");
+		writable ? "writable" : "read-only", at24->write_max);
 	if (use_smbus == I2C_SMBUS_WORD_DATA ||
 	    use_smbus == I2C_SMBUS_BYTE_DATA) {
 		dev_notice(&client->dev, "Falling back to %s reads, "
 			   "performance will suffer\n", use_smbus ==
 			   I2C_SMBUS_WORD_DATA ? "word" : "byte");
 	}
-	dev_dbg(&client->dev,
-		"page_size %d, num_addresses %d, write_max %d, use_smbus %d\n",
-		chip.page_size, num_addresses,
-		at24->write_max, use_smbus);
 
 	/* export data to kernel code */
 	if (chip.setup)
-- 
1.7.2.3

^ permalink raw reply related

* Re: [PATCH v2] fsldma: add support to 36-bit physical address
From: Timur Tabi @ 2010-11-15 16:13 UTC (permalink / raw)
  To: Kumar Gala; +Cc: dan.j.williams, linuxppc-dev, linux-kernel
In-Reply-To: <3B38AD35-39A2-4A54-8109-65D6DE436227@kernel.crashing.org>

On Mon, Nov 15, 2010 at 9:16 AM, Kumar Gala <galak@kernel.crashing.org> wro=
te:

> The programming model (if you look at the free-space in the registers and=
 data structures) supports a 64-bit address. =A0I'm trying to avoid changin=
g the driver in the future if we have >36-bit. =A0However this is such a mi=
nor worry that I'll stop and just ack the patch as is.

I must still be missing something.  I'm looking at the description of
the SATR register in the MPC8572 RM, and it shows this:

0 - 3 |   4 - 5   |     6     |   7  |   8 - 11  |   12 - 15  | 16-21 | 22-=
31
 ---  | STFLOWLVL | SPCIORDER | SSME | STRANSINT | SREADTTYPE |  ---  |  ES=
AD

The most that we can extend ESAD to is 16 bits, for a total of a
48-bit physical address.  Where are the other 16 bits supposed to go?

--=20
Timur Tabi
Linux kernel developer at Freescale

^ permalink raw reply

* Re: [PATCH v2] fsldma: add support to 36-bit physical address
From: Kumar Gala @ 2010-11-15 15:16 UTC (permalink / raw)
  To: Timur Tabi; +Cc: dan.j.williams, linuxppc-dev, linux-kernel
In-Reply-To: <AANLkTi=1nutREorMFY2VJyUYQD0SHfiSeskw-u22P+R-@mail.gmail.com>


On Nov 13, 2010, at 4:43 PM, Timur Tabi wrote:

> On Thu, Nov 11, 2010 at 5:56 AM, Kumar Gala =
<galak@kernel.crashing.org> wrote:
>=20
>> Is there any reason we shouldn't set DMA_BIT_MASK(64) since the DMA =
block programming model allows the address to be 64-bits?
>=20
> Can you explain that?  The DMA registers only have room for 36 bits
> for the physical address.

The programming model (if you look at the free-space in the registers =
and data structures) supports a 64-bit address.  I'm trying to avoid =
changing the driver in the future if we have >36-bit.  However this is =
such a minor worry that I'll stop and just ack the patch as is.

- k=

^ permalink raw reply

* Re: [PATCH 2/2] ucc_geth: Fix deadlock
From: Joakim Tjernlund @ 2010-11-14 14:43 UTC (permalink / raw)
  To: Anton Vorontsov; +Cc: netdev, linuxppc-dev
In-Reply-To: <20101112140947.GB28223@oksana.dev.rtsoft.ru>

Anton Vorontsov <cbouatmailru@gmail.com> wrote on 2010/11/12 15:09:47:
>
> On Fri, Nov 12, 2010 at 02:55:09PM +0100, Joakim Tjernlund wrote:
> > This script:
> >  while [ 1==1 ] ; do ifconfig eth0 up; usleep 1950000 ;ifconfig eth0 down; dmesg -c ;done
> > causes in just a second or two:
> > INFO: task ifconfig:572 blocked for more than 120 seconds.
> [...]
> > The reason appears to be ucc_geth_stop meets adjust_link as the
> > PHY reports PHY changes. I belive adjust_link hangs somewhere,
> > holding the PHY lock, because ucc_geth_stop disabled the
> > controller HW.
> > Fix is to stop the PHY before disabling the controller.
> >
> > Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
>
> It's unclear where exactly adjust_link() hangs, but the patch
> looks as the right thing overall.

Yes, I too cannot find where it is hanging, just that it is hanging somewhere.
I am starting to think it is hanging somewhere else. Anyhow, the hang
goes away 100% when this patch is applied.

 Jocke

^ permalink raw reply

* Re: [RFC PATCH 0/6] nvram: Capture oops/panic reports in NVRAM
From: Jim Keniston @ 2010-11-14  4:36 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20101114041510.9457.92921.stgit@localhost.localdomain>

On Sat, 2010-11-13 at 20:15 -0800, Jim Keniston wrote:
> This patch series enables p Series systems to capture oops and panic
> reports from the printk buffer into NVRAM, where they can be examined
> after reboot using the nvram command.
> 

Here's a patch to the nvram command to add --unzip and --ascii options,
for examination of oops/panic reports captured in ibm,oops-log or
ibm,rtas-log.

The nvram command is part of powerpc-utils --
git://powerpc-utils.git.sourceforge.net/gitroot/powerpc-utils/powerpc-utils

You can build it using
cc nvram.c -ldl -lz -o nvram

BTW, as far as I can tell, the zlib_deflate code in the kernel can't
produce the header that the gunzip command wants -- hence the reliance
on libz in the nvram command.

Jim
---

 src/nvram.c |  136 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 136 insertions(+), 0 deletions(-)

diff --git a/src/nvram.c b/src/nvram.c
index d25e073..e00ae12 100644
--- a/src/nvram.c
+++ b/src/nvram.c
@@ -43,6 +43,7 @@
 #include <glob.h>
 #include <getopt.h>
 #include <inttypes.h>
+#include <zlib.h>
 
 #include "nvram.h"
 
@@ -62,6 +63,8 @@ static struct option long_options[] = {
     {"print-event-scan", 	no_argument, 	   NULL, 'E'},
     {"partitions", 		no_argument, 	   NULL, 'P'},
     {"dump", 			required_argument, NULL, 'd'},
+    {"ascii",			required_argument, NULL, 'a'},
+    {"unzip", 			required_argument, NULL, 'z'},
     {"nvram-file", 		required_argument, NULL, 'n'},
     {"nvram-size", 		required_argument, NULL, 's'},
     {"update-config",		required_argument, NULL, 'u'},
@@ -99,6 +102,10 @@ help(void)
     "          print NVRAM paritition header info\n"
     "  --dump <name>\n"
     "          raw dump of partition (use --partitions to see names)\n"
+    "  --ascii <name>\n"
+    "          print partition contents as ASCII text\n"
+    "  --unzip <name>\n"
+    "          decompress and print compressed data from partition\n"
     "  --nvram-file <path>\n"
     "          specify alternate nvram data file (default is /dev/nvram)\n"
     "  --nvram-size\n"
@@ -1189,6 +1196,121 @@ dump_raw_partition(struct nvram *nvram, char *name)
 }
 
 /**
+ * dump_ascii_partition
+ * @brief ASCII data dump of a partition, excluding header
+ *
+ * @param nvram nvram struct containing partition
+ * @param name name of partition to dump
+ * @return 0 on success, !0 otherwise
+ *
+ * Partition subheaders, if any, are dumped along with the rest of the data.
+ * We substitute periods for unprintable characters.
+ */
+int
+dump_ascii_partition(struct nvram *nvram, char *name)
+{
+    struct partition_header *phead;
+    char *start, *end, *c;
+
+    phead = nvram_find_partition(nvram, 0, name, NULL);
+    if (!phead) {
+	err_msg("there is no %s partition!\n", name);
+	return -1;
+    }
+    
+    start = (char*) phead;
+    end = start + phead->length * NVRAM_BLOCK_SIZE;
+    start += sizeof(*phead);	/* Skip partition header. */
+    for (c = start; c < end; c++) {
+	if (isprint(*c) || isspace(*c))
+	    putchar(*c);
+	else
+	    putchar('.');
+    }
+    /* Always end with a newline.*/
+    putchar('\n');
+    return 0;
+}
+
+int
+dump_zipped_text(char *zipped_text, unsigned int zipped_length)
+{
+    z_stream strm;
+    int result;
+    char unzipped_text[4096];
+
+    strm.zalloc = Z_NULL;
+    strm.zfree = Z_NULL;
+    strm.opaque = Z_NULL;
+    strm.avail_in = zipped_length;
+    strm.next_in = zipped_text;
+    result = inflateInit(&strm);
+    if (result != Z_OK) {
+    	err_msg("can't decompress text: inflateInit() returned %d\n", result);
+	return -1;
+    }
+
+    do {
+	strm.avail_out = 4096;
+	strm.next_out = unzipped_text;
+    	result = inflate(&strm, Z_NO_FLUSH);
+	switch (result) {
+	case Z_STREAM_ERROR:
+	case Z_NEED_DICT:
+	case Z_DATA_ERROR:
+	case Z_MEM_ERROR:
+	    err_msg("can't decompress text: inflate() returned %d\n", result);
+	    (void) inflateEnd(&strm);
+	    return -1;
+	}
+	if (fwrite(unzipped_text, 4096 - strm.avail_out, 1, stdout) != 1) {
+	    err_msg("can't decompress text: fwrite() failed\n");
+	    (void) inflateEnd(&strm);
+	    return -1;
+	}
+    } while (strm.avail_out == 0);
+
+    (void) inflateEnd(&strm);
+    return 0;
+}
+
+/**
+ * unzip_partition
+ * @brief Uncompress and print compressed data from a partition.
+ *
+ * @param nvram nvram struct containing partition
+ * @param name name of partition to dump
+ * @return 0 on success, !0 otherwise
+ */
+int
+unzip_partition(struct nvram *nvram, char *name)
+{
+    struct partition_header *phead;
+    char *start, *next;
+    unsigned short zipped_length;
+
+    phead = nvram_find_partition(nvram, 0, name, NULL);
+    if (!phead) {
+	err_msg("there is no %s partition!\n", name);
+	return -1;
+    }
+    
+    start = (char*) phead;
+    next = start + sizeof(*phead);	/* Skip partition header. */
+    next += sizeof(struct err_log_info);	/* Skip sub-header. */
+    zipped_length = *((unsigned short*) next);
+    next += sizeof(unsigned short);		/* Skip compressed length. */
+
+    if ((next-start) + zipped_length > phead->length * NVRAM_BLOCK_SIZE) {
+    	err_msg("bogus size for compressed data in partition %s: %u\n", name,
+	    zipped_length);
+	return -1;
+    }
+
+    return dump_zipped_text(next, zipped_length);
+}
+
+/**
  * print_of_config_part
  * @brief Print the name/value pairs of a partition
  *
@@ -1476,6 +1598,8 @@ main (int argc, char *argv[])
     int print_event_scan = 0;
     int	print_config_var = 0;
     char *dump_name = NULL;
+    char *ascii_name = NULL;
+    char *zip_name = NULL;
     char *update_config_var = NULL;
     char *config_pname = "common";
 
@@ -1504,6 +1628,12 @@ main (int argc, char *argv[])
 	    case 'd':	/* dump */
 		dump_name = optarg;
 		break;
+	    case 'a':	/* ASCII dump */
+	    	ascii_name = optarg;
+		break;
+	    case 'z':	/* dump compressed data */
+		zip_name = optarg;
+		break;
 	    case 'n':	/* nvram-file */
 		nvram.filename = optarg;
 		break;
@@ -1641,6 +1771,12 @@ main (int argc, char *argv[])
     if (dump_name)
 	if (dump_raw_partition(&nvram, dump_name) != 0)
 	    ret = -1;
+    if (ascii_name)
+	if (dump_ascii_partition(&nvram, ascii_name) != 0)
+	    ret = -1;
+    if (zip_name)
+	if (unzip_partition(&nvram, zip_name) != 0)
+	    ret = -1;
    
 err_exit:   
    if (nvram.data)

^ permalink raw reply related

* [PATCH 5/6] nvram: Slim down zlib_deflate workspace when possible
From: Jim Keniston @ 2010-11-14  4:15 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20101114041510.9457.92921.stgit@localhost.localdomain>

Instead of always creating a huge (268K) deflate_workspace with the
maximum compression parameters (windowBits=15, memLevel=8), allow the
caller to obtain a smaller workspace (24K in our case) by specifying
smaller parameter values -- via zlib_deflate_workspacesize2(). In our
case, a small workspace is a win because our choices are to allocate
the workspace when we need it (i.e., during an oops or panic) or
allocate it at boot time.  (We do the latter.)

Signed-off-by: Jim Keniston <jkenisto@us.ibm.com>
---

 include/linux/zlib.h            |   14 ++++++++++++--
 lib/zlib_deflate/deflate.c      |   33 ++++++++++++++++++++++++++++++++-
 lib/zlib_deflate/deflate_syms.c |    1 +
 lib/zlib_deflate/defutil.h      |   17 +++++++++++++----
 4 files changed, 58 insertions(+), 7 deletions(-)

diff --git a/include/linux/zlib.h b/include/linux/zlib.h
index 40c49cb..3f15036 100644
--- a/include/linux/zlib.h
+++ b/include/linux/zlib.h
@@ -179,11 +179,21 @@ typedef z_stream *z_streamp;
 
                         /* basic functions */
 
+extern int zlib_deflate_workspacesize2 (int windowBits, int memLevel);
+/*
+   Returns the number of bytes that needs to be allocated for a per-
+   stream workspace with the specified parameters.  A pointer to this
+   number of bytes should be returned in stream->workspace before
+   calling zlib_deflateInit2(); and the windowBits and memLevel
+   parameters passed to zlib_deflateInit2() must not exceed those
+   passed here.
+*/
+
 extern int zlib_deflate_workspacesize (void);
 /*
    Returns the number of bytes that needs to be allocated for a per-
-   stream workspace.  A pointer to this number of bytes should be
-   returned in stream->workspace before calling zlib_deflateInit().
+   stream workspace with the default (large) windowBits and memLevel
+   parameters.
 */
 
 /* 
diff --git a/lib/zlib_deflate/deflate.c b/lib/zlib_deflate/deflate.c
index 46a31e5..cdb207a 100644
--- a/lib/zlib_deflate/deflate.c
+++ b/lib/zlib_deflate/deflate.c
@@ -176,6 +176,7 @@ int zlib_deflateInit2(
     deflate_state *s;
     int noheader = 0;
     deflate_workspace *mem;
+    char *next;
 
     ush *overlay;
     /* We overlay pending_buf and d_buf+l_buf. This works since the average
@@ -199,6 +200,21 @@ int zlib_deflateInit2(
 	strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
         return Z_STREAM_ERROR;
     }
+
+    /*
+     * Direct the workspace's pointers to the chunks that were allocated
+     * along with the deflate_workspace struct.
+     */
+    next = (char *) mem;
+    next += sizeof(*mem);
+    mem->window_memory = (Byte *) next;
+    next += zlib_deflate_window_memsize(windowBits);
+    mem->prev_memory = (Pos *) next;
+    next += zlib_deflate_prev_memsize(windowBits);
+    mem->head_memory = (Pos *) next;
+    next += zlib_deflate_head_memsize(memLevel);
+    mem->overlay_memory = next;
+
     s = (deflate_state *) &(mem->deflate_memory);
     strm->state = (struct internal_state *)s;
     s->strm = strm;
@@ -1249,5 +1265,20 @@ static block_state deflate_slow(
 
 int zlib_deflate_workspacesize(void)
 {
-    return sizeof(deflate_workspace);
+    return zlib_deflate_workspacesize2(MAX_WBITS, MAX_MEM_LEVEL);
+}
+
+int zlib_deflate_workspacesize2(int windowBits, int memLevel)
+{
+    if (windowBits < 0) /* undocumented feature: suppress zlib header */
+        windowBits = -windowBits;
+    if (memLevel < 1 || memLevel > MAX_MEM_LEVEL ||
+        windowBits < 9 || windowBits > 15)
+        return -1;
+
+    return sizeof(deflate_workspace)
+        + zlib_deflate_window_memsize(windowBits)
+        + zlib_deflate_prev_memsize(windowBits)
+        + zlib_deflate_head_memsize(memLevel)
+        + zlib_deflate_overlay_memsize(memLevel);
 }
diff --git a/lib/zlib_deflate/deflate_syms.c b/lib/zlib_deflate/deflate_syms.c
index ccfe25f..cdf1cdd 100644
--- a/lib/zlib_deflate/deflate_syms.c
+++ b/lib/zlib_deflate/deflate_syms.c
@@ -11,6 +11,7 @@
 #include <linux/zlib.h>
 
 EXPORT_SYMBOL(zlib_deflate_workspacesize);
+EXPORT_SYMBOL(zlib_deflate_workspacesize2);
 EXPORT_SYMBOL(zlib_deflate);
 EXPORT_SYMBOL(zlib_deflateInit2);
 EXPORT_SYMBOL(zlib_deflateEnd);
diff --git a/lib/zlib_deflate/defutil.h b/lib/zlib_deflate/defutil.h
index 6b15a90..b640b64 100644
--- a/lib/zlib_deflate/defutil.h
+++ b/lib/zlib_deflate/defutil.h
@@ -241,12 +241,21 @@ typedef struct deflate_state {
 typedef struct deflate_workspace {
     /* State memory for the deflator */
     deflate_state deflate_memory;
-    Byte window_memory[2 * (1 << MAX_WBITS)];
-    Pos prev_memory[1 << MAX_WBITS];
-    Pos head_memory[1 << (MAX_MEM_LEVEL + 7)];
-    char overlay_memory[(1 << (MAX_MEM_LEVEL + 6)) * (sizeof(ush)+2)];
+    Byte *window_memory;
+    Pos *prev_memory;
+    Pos *head_memory;
+    char *overlay_memory;
 } deflate_workspace;
 
+#define zlib_deflate_window_memsize(windowBits) \
+	(2 * (1 << (windowBits)) * sizeof(Byte))
+#define zlib_deflate_prev_memsize(windowBits) \
+	((1 << (windowBits)) * sizeof(Pos))
+#define zlib_deflate_head_memsize(memLevel) \
+	((1 << ((memLevel)+7)) * sizeof(Pos))
+#define zlib_deflate_overlay_memsize(memLevel) \
+	((1 << ((memLevel)+6)) * (sizeof(ush)+2))
+
 /* Output a byte on the stream.
  * IN assertion: there is enough room in pending_buf.
  */

^ permalink raw reply related

* [PATCH 6/6] nvram: Shrink our zlib_deflate workspace from 268K to 24K
From: Jim Keniston @ 2010-11-14  4:15 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20101114041510.9457.92921.stgit@localhost.localdomain>

Exploit zlib_deflate_workspacesize2() to create a much smaller
zlib_deflate workspace when capturing oops/panic reports to NVRAM.

Signed-off-by: Jim Keniston <jkenisto@us.ibm.com>
---

 arch/powerpc/platforms/pseries/nvram.c |   11 +++++++----
 1 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
index 8e5ed74..6409cb6 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -17,7 +17,6 @@
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
-#include <linux/vmalloc.h>
 #include <linux/ctype.h>
 #include <linux/kmsg_dump.h>
 #include <linux/zlib.h>
@@ -94,6 +93,8 @@ static struct oops_parition_data {
 } *little_oops_buf;
 
 #define COMPR_LEVEL 6
+#define WINDOW_BITS 12
+#define MEM_LEVEL 4
 static struct z_stream_s stream;
 
 static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
@@ -408,7 +409,8 @@ static void __init nvram_init_oops_partition(int rtas_partition_exists)
 	big_oops_buf_sz = (little_oops_buf_sz * 100) / 45;
 	big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
 	if (big_oops_buf) {
-		stream.workspace = vmalloc(zlib_deflate_workspacesize());
+		stream.workspace = kmalloc(zlib_deflate_workspacesize2(
+				WINDOW_BITS, MEM_LEVEL), GFP_KERNEL);
 		if (!stream.workspace) {
 			pr_err("nvram: No memory for compression workspace; "
 				"skipping compression of %s partition data\n",
@@ -427,7 +429,7 @@ static void __init nvram_init_oops_partition(int rtas_partition_exists)
 		pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc);
 		kfree(little_oops_buf);
 		kfree(big_oops_buf);
-		vfree(stream.workspace);
+		kfree(stream.workspace);
 	}
 }
 
@@ -625,7 +627,8 @@ static int nvram_compress(const void *in, void *out, size_t inlen,
 	int err, ret;
 
 	ret = -EIO;
-	err = zlib_deflateInit(&stream, COMPR_LEVEL);
+	err = zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS,
+						MEM_LEVEL, Z_DEFAULT_STRATEGY);
 	if (err != Z_OK)
 		goto error;
 

^ permalink raw reply related

* [PATCH 4/6] nvram: Add compression to fit more printk output into NVRAM
From: Jim Keniston @ 2010-11-14  4:15 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20101114041510.9457.92921.stgit@localhost.localdomain>

Capture more than twice as much text from the printk buffer, and
compress it to fit it in the ibm,oops-log NVRAM partition.

Signed-off-by: Jim Keniston <jkenisto@us.ibm.com>
---

 arch/powerpc/include/asm/rtas.h        |    6 +
 arch/powerpc/platforms/pseries/nvram.c |  195 ++++++++++++++++++++++++++++----
 2 files changed, 177 insertions(+), 24 deletions(-)

diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h
index 3d35f8a..6e0f4b5 100644
--- a/arch/powerpc/include/asm/rtas.h
+++ b/arch/powerpc/include/asm/rtas.h
@@ -205,10 +205,12 @@ extern void pSeries_log_error(char *buf, unsigned int err_type, int fatal);
 #define ERR_FLAG_ALREADY_LOGGED	0x0
 #define ERR_FLAG_BOOT		0x1 	/* log was pulled from NVRAM on boot */
 #define ERR_TYPE_RTAS_LOG	0x2	/* from rtas event-scan */
-#define ERR_TYPE_KERNEL_PANIC	0x4	/* from panic() */
+#define ERR_TYPE_KERNEL_PANIC	0x4	/* from die()/panic() */
+#define ERR_TYPE_KERNEL_PANIC_GZ 0x8	/* ditto, compressed */
 
 /* All the types and not flags */
-#define ERR_TYPE_MASK	(ERR_TYPE_RTAS_LOG | ERR_TYPE_KERNEL_PANIC)
+#define ERR_TYPE_MASK \
+	(ERR_TYPE_RTAS_LOG | ERR_TYPE_KERNEL_PANIC | ERR_TYPE_KERNEL_PANIC_GZ)
 
 #define RTAS_DEBUG KERN_DEBUG "RTAS: "
  
diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
index e1bc1a4..8e5ed74 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -17,7 +17,10 @@
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/ctype.h>
 #include <linux/kmsg_dump.h>
+#include <linux/zlib.h>
 #include <asm/uaccess.h>
 #include <asm/nvram.h>
 #include <asm/rtas.h>
@@ -74,9 +77,24 @@ static struct kmsg_dumper nvram_kmsg_dumper = {
 	.dump = oops_to_nvram
 };
 
-/* We preallocate oops_buf during init to avoid kmalloc during oops/panic. */
-static size_t oops_buf_sz;
-static char *oops_buf;
+/*
+ * big_oops_buf[] holds the uncompressed text we're capturing.  little_oops_buf
+ * holds the compressed text, plus its length.  little_oops_buf gets written
+ * to NVRAM.
+ *
+ * We preallocate these buffers during init to avoid kmalloc during oops/panic.
+ */
+static size_t big_oops_buf_sz, little_oops_buf_sz;
+static char *big_oops_buf;
+
+static struct oops_parition_data {
+#define OOPS_PTN_PREFIX_SZ sizeof(unsigned short)
+	unsigned short length;
+	char buf[0];
+} *little_oops_buf;
+
+#define COMPR_LEVEL 6
+static struct z_stream_s stream;
 
 static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
 {
@@ -374,13 +392,42 @@ static void __init nvram_init_oops_partition(int rtas_partition_exists)
 		memcpy(&oops_log_partition, &rtas_log_partition,
 						sizeof(rtas_log_partition));
 	}
-	oops_buf_sz = oops_log_partition.size - sizeof(struct err_log_info);
-	oops_buf = kmalloc(oops_buf_sz, GFP_KERNEL);
+
+	little_oops_buf_sz = oops_log_partition.size - OOPS_PTN_PREFIX_SZ;
+	little_oops_buf = kmalloc(oops_log_partition.size, GFP_KERNEL);
+	if (!little_oops_buf) {
+		pr_err("nvram: No memory for %s partition\n",
+						oops_log_partition.name);
+		return;
+	}
+	/*
+	 * Figure compression (preceded by elimination of each line's <n>
+	 * severity prefix) will reduce the oops/panic report to at most
+	 * 45% of its original size.
+	 */
+	big_oops_buf_sz = (little_oops_buf_sz * 100) / 45;
+	big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
+	if (big_oops_buf) {
+		stream.workspace = vmalloc(zlib_deflate_workspacesize());
+		if (!stream.workspace) {
+			pr_err("nvram: No memory for compression workspace; "
+				"skipping compression of %s partition data\n",
+				oops_log_partition.name);
+			kfree(big_oops_buf);
+			big_oops_buf = NULL;
+		}
+	} else {
+		pr_err("No memory for uncompressed %s data; "
+			"skipping compression\n", oops_log_partition.name);
+		stream.workspace = NULL;
+	}
+
 	rc = kmsg_dump_register(&nvram_kmsg_dumper);
 	if (rc != 0) {
 		pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc);
-		kfree(oops_buf);
-		return;
+		kfree(little_oops_buf);
+		kfree(big_oops_buf);
+		vfree(stream.workspace);
 	}
 }
 
@@ -527,7 +574,105 @@ static size_t capture_oops(const char *old_msgs, size_t old_len,
 	return nc1 + nc2;
 }
 
-/* our kmsg_dump callback */
+/*
+ * For a panic, capture the last capture_len chars of the printk buffer.
+ * For an oops, ensure that we have the start of the oops report, and the
+ * message(s) leading up to it.
+ */
+static size_t capture_msgs(enum kmsg_dump_reason reason,
+				const char *old_msgs, size_t old_len,
+				const char *new_msgs, size_t new_len,
+				char *captured, size_t capture_len)
+{
+	size_t text_len;
+
+	text_len = capture_last_msgs(old_msgs, old_len, new_msgs, new_len,
+						captured, capture_len);
+	if (reason == KMSG_DUMP_OOPS) {
+		const char *poops = strnrstr(captured, OOPS_TAG, capture_len);
+		if (!poops || poops < captured + PREAMBLE_CHARS)
+			text_len = capture_oops(old_msgs, old_len, new_msgs,
+				new_len, captured, capture_len, text_len);
+	}
+	return text_len;
+}
+
+/* Squeeze out each line's <n> severity prefix. */
+static size_t elide_severities(char *buf, size_t len)
+{
+	char *in, *out, *buf_end = buf + len;
+	/* Assume a <n> at the very beginning marks the start of a line. */
+	int newline = 1;
+
+	in = out = buf;
+	while (in < buf_end) {
+		if (newline && in+3 <= buf_end &&
+				*in == '<' && isdigit(in[1]) && in[2] == '>') {
+			in += 3;
+			newline = 0;
+		} else {
+			newline = (*in == '\n');
+			*out++ = *in++;
+		}
+	}
+	return out - buf;
+}
+
+/* Derived from logfs_compress() */
+static int nvram_compress(const void *in, void *out, size_t inlen,
+							size_t outlen)
+{
+	int err, ret;
+
+	ret = -EIO;
+	err = zlib_deflateInit(&stream, COMPR_LEVEL);
+	if (err != Z_OK)
+		goto error;
+
+	stream.next_in = in;
+	stream.avail_in = inlen;
+	stream.total_in = 0;
+	stream.next_out = out;
+	stream.avail_out = outlen;
+	stream.total_out = 0;
+
+	err = zlib_deflate(&stream, Z_FINISH);
+	if (err != Z_STREAM_END)
+		goto error;
+
+	err = zlib_deflateEnd(&stream);
+	if (err != Z_OK)
+		goto error;
+
+	if (stream.total_out >= stream.total_in)
+		goto error;
+
+	ret = stream.total_out;
+error:
+	return ret;
+}
+
+/* Compress the text from big_oops_buf into little_oops_buf. */
+static int zip_oops(size_t text_len)
+{
+	int zipped_len = nvram_compress(big_oops_buf, little_oops_buf->buf,
+					text_len, little_oops_buf_sz);
+	if (zipped_len < 0) {
+		pr_err("nvram: compression failed; returned %d\n", zipped_len);
+		pr_err("nvram: logging uncompressed oops/panic report\n");
+		return -1;
+	}
+	little_oops_buf->length = (unsigned short) zipped_len;
+	return 0;
+}
+
+/*
+ * This is our kmsg_dump callback, called after an oops or panic report
+ * has been written to the printk buffer.  We want to capture as much
+ * of the printk buffer as possible.  First, capture as much as we can
+ * that we think will compress sufficiently to fit in the ibm,oops-log
+ * partition.  If that's too much, go back and capture uncompressed text.
+ */
 static void oops_to_nvram(struct kmsg_dumper *dumper,
 		enum kmsg_dump_reason reason,
 		const char *old_msgs, unsigned long old_len,
@@ -535,19 +680,25 @@ static void oops_to_nvram(struct kmsg_dumper *dumper,
 {
 	static unsigned int oops_count = 0;
 	size_t text_len;
-
-	text_len = capture_last_msgs(old_msgs, old_len, new_msgs, new_len,
-						oops_buf, oops_buf_sz);
-	if (reason == KMSG_DUMP_OOPS) {
-		/*
-		 * Ensure that we have the start of the oops report,
-		 * and the message(s) leading up to it.
-		 */
-		const char *poops = strnrstr(oops_buf, OOPS_TAG, oops_buf_sz);
-		if (!poops || poops < oops_buf + PREAMBLE_CHARS)
-			text_len = capture_oops(old_msgs, old_len, new_msgs,
-				new_len, oops_buf, oops_buf_sz, text_len);
+	unsigned int err_type = ERR_TYPE_KERNEL_PANIC_GZ;
+	int rc = -1;
+
+	if (big_oops_buf) {
+		text_len = capture_msgs(reason, old_msgs, old_len,
+			new_msgs, new_len, big_oops_buf, big_oops_buf_sz);
+		text_len = elide_severities(big_oops_buf, text_len);
+		rc = zip_oops(text_len);
 	}
-	(void) nvram_write_os_partition(&oops_log_partition, oops_buf,
-		(int) text_len, ERR_TYPE_KERNEL_PANIC, ++oops_count);
+	if (rc != 0) {
+		text_len = capture_msgs(reason, old_msgs, old_len,
+				new_msgs, new_len, little_oops_buf->buf,
+				little_oops_buf_sz);
+		err_type = ERR_TYPE_KERNEL_PANIC;
+		little_oops_buf->length = (unsigned short) text_len;
+	}
+
+	(void) nvram_write_os_partition(&oops_log_partition,
+		(char*) little_oops_buf,
+		(int) (OOPS_PTN_PREFIX_SZ + little_oops_buf->length),
+		err_type, ++oops_count);
 }

^ permalink raw reply related

* [PATCH 1/6] nvram: Generalize code for OS partitions in NVRAM
From: Jim Keniston @ 2010-11-14  4:15 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20101114041510.9457.92921.stgit@localhost.localdomain>

Adapt the functions used to create and write to the RTAS-log partition
to work with any OS-type partition.

Signed-off-by: Jim Keniston <jkenisto@us.ibm.com>
---

 arch/powerpc/include/asm/nvram.h       |    3 -
 arch/powerpc/kernel/nvram_64.c         |   31 ++++++-
 arch/powerpc/platforms/pseries/nvram.c |  138 +++++++++++++++++++-------------
 3 files changed, 110 insertions(+), 62 deletions(-)

diff --git a/arch/powerpc/include/asm/nvram.h b/arch/powerpc/include/asm/nvram.h
index 457a1a5..3cd90fd 100644
--- a/arch/powerpc/include/asm/nvram.h
+++ b/arch/powerpc/include/asm/nvram.h
@@ -50,7 +50,8 @@ static inline int mmio_nvram_init(void)
 
 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_remove_partition(const char *name, int sig,
+					const char *exceptions[]);
 extern int nvram_get_partition_size(loff_t data_index);
 extern loff_t nvram_find_partition(const char *name, int sig, int *out_size);
 
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index cda7c3f..3de46cd 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -237,22 +237,45 @@ static unsigned char __init nvram_checksum(struct nvram_header *p)
 	return c_sum;
 }
 
+/*
+ * Per the criteria passed via nvram_remove_partition(), should this
+ * partition be removed?  1=remove, 0=keep
+ */
+static int nvram_condemn_partition(struct nvram_partition *part,
+		const char *name, int sig, const char *exceptions[])
+{
+	if (part->header.signature != sig)
+		return 0;
+	if (name) {
+		if (strncmp(name, part->header.name, 12))
+			return 0;
+	} else if (exceptions) {
+		const char **except;
+		for (except = exceptions; *except; except++) {
+			if (!strncmp(*except, part->header.name, 12))
+				return 0;
+		}
+	}
+	return 1;
+}
+
 /**
  * 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
+ * @exceptions: When removing all partitions with a matching signature,
+ *        leave these alone.
  */
 
-int __init nvram_remove_partition(const char *name, int sig)
+int __init nvram_remove_partition(const char *name, int sig,
+						const char *exceptions[])
 {
 	struct nvram_partition *part, *prev, *tmp;
 	int rc;
 
 	list_for_each_entry(part, &nvram_partitions, partition) {
-		if (part->header.signature != sig)
-			continue;
-		if (name && strncmp(name, part->header.name, 12))
+		if (!nvram_condemn_partition(part, name, sig, exceptions))
 			continue;
 
 		/* Make partition a free partition */
diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
index 4b705dc..43d5c52 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -30,17 +30,30 @@ 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
 
-#define NVRAM_LOG_PART_NAME	"ibm,rtas-log"
+struct os_partition {
+	const char *name;
+	int req_size;	/* desired size, in bytes */
+	int min_size;	/* minimum acceptable size (0 means req_size) */
+	long size;	/* size of data portion of partition */
+	long index;	/* offset of data portion of partition */
+};
+
+static struct os_partition rtas_log_partition = {
+	.name = "ibm,rtas-log",
+	.req_size = 2079,
+	.min_size = 1055,
+	.index = -1
+};
+
+static const char *valid_os_partitions[] = {
+	"ibm,rtas-log",
+	NULL
+};
 
 static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
 {
@@ -134,7 +147,7 @@ static ssize_t pSeries_nvram_get_size(void)
 }
 
 
-/* nvram_write_error_log
+/* nvram_write_os_partition, 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
@@ -156,48 +169,55 @@ static ssize_t pSeries_nvram_get_size(void)
  * The 'data' section would look like (in bytes):
  * +--------------+------------+-----------------------------------+
  * | event_logged | sequence # | error log                         |
- * |0            3|4          7|8            nvram_error_log_size-1|
+ * |0            3|4          7|8                  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,
+int nvram_write_os_partition(struct os_partition *part, 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) {
+	if (part->index == -1) {
 		return -ESPIPE;
 	}
 
-	if (length > nvram_error_log_size) {
-		length = nvram_error_log_size;
+	if (length > part->size) {
+		length = part->size;
 	}
 
 	info.error_type = err_type;
 	info.seq_num = error_log_cnt;
 
-	tmp_index = nvram_error_log_index;
+	tmp_index = part->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);
+		printk(KERN_ERR "nvram_write_os_partition: 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);
+		printk(KERN_ERR "nvram_write_os_partition: Failed nvram_write (%d)\n", rc);
 		return rc;
 	}
 	
 	return 0;
 }
 
+int nvram_write_error_log(char * buff, int length,
+                          unsigned int err_type, unsigned int error_log_cnt)
+{
+	return nvram_write_os_partition(&rtas_log_partition, buff, length,
+						err_type, error_log_cnt);
+}
+
 /* nvram_read_error_log
  *
  * Reads nvram for error log for at most 'length'
@@ -209,13 +229,13 @@ int nvram_read_error_log(char * buff, int length,
 	loff_t tmp_index;
 	struct err_log_info info;
 	
-	if (nvram_error_log_index == -1)
+	if (rtas_log_partition.index == -1)
 		return -1;
 
-	if (length > nvram_error_log_size)
-		length = nvram_error_log_size;
+	if (length > rtas_log_partition.size)
+		length = rtas_log_partition.size;
 
-	tmp_index = nvram_error_log_index;
+	tmp_index = rtas_log_partition.index;
 
 	rc = ppc_md.nvram_read((char *)&info, sizeof(struct err_log_info), &tmp_index);
 	if (rc <= 0) {
@@ -244,10 +264,10 @@ int nvram_clear_error_log(void)
 	int clear_word = ERR_FLAG_ALREADY_LOGGED;
 	int rc;
 
-	if (nvram_error_log_index == -1)
+	if (rtas_log_partition.index == -1)
 		return -1;
 
-	tmp_index = nvram_error_log_index;
+	tmp_index = rtas_log_partition.index;
 	
 	rc = ppc_md.nvram_write((char *)&clear_word, sizeof(int), &tmp_index);
 	if (rc <= 0) {
@@ -258,67 +278,71 @@ int nvram_clear_error_log(void)
 	return 0;
 }
 
-/* pseries_nvram_init_log_partition
+/* pseries_nvram_init_os_partition
  *
- * This will setup the partition we need for buffering the
- * error logs and cleanup partitions if needed.
+ * This set up a partition with an "OS" signature.
  *
  * The general strategy is the following:
- * 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.
- * 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).
+ * 1.) If a partition with the indicated name already exists...
+ *	- If it's large enough, use it.
+ *	- Otherwise, recycle it and keep going.
+ * 2.) Search for a free partition that is large enough.
+ * 3.) If there's not a free partition large enough, recycle any obsolete
+ * OS partitions and try again.
+ * 4.) Will first try getting a chunk that will satisfy the requested size.
+ * 5.) If a chunk of the requested size cannot be allocated, then try finding
+ * a chunk that will satisfy the minum needed.
+ *
+ * Returns 0 on success, else -1.
  */
-static int __init pseries_nvram_init_log_partition(void)
+static int __init pseries_nvram_init_os_partition(struct os_partition *part)
 {
 	loff_t p;
 	int size;
 
-	p = nvram_find_partition(NVRAM_LOG_PART_NAME, NVRAM_SIG_OS, &size);
+	p = nvram_find_partition(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 "NVRAM_LOG_PART_NAME" partition"
-			",removing it...");
-		nvram_remove_partition(NVRAM_LOG_PART_NAME, NVRAM_SIG_OS);
+	if (p && size < part->min_size) {
+		pr_info("nvram: Found too small %s partition,"
+					" removing it...\n", part->name);
+		nvram_remove_partition(part->name, NVRAM_SIG_OS, NULL);
 		p = 0;
 	}
 
 	/* Create one if we didn't find */
 	if (!p) {
-		p = nvram_create_partition(NVRAM_LOG_PART_NAME, NVRAM_SIG_OS,
-					   NVRAM_MAX_REQ, NVRAM_MIN_REQ);
-		/* No room for it, try to get rid of any OS partition
-		 * and try again
-		 */
+		p = nvram_create_partition(part->name, NVRAM_SIG_OS,
+					part->req_size, part->min_size);
 		if (p == -ENOSPC) {
-			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(NVRAM_LOG_PART_NAME,
-						   NVRAM_SIG_OS, NVRAM_MAX_REQ,
-						   NVRAM_MIN_REQ);
+			pr_info("nvram: No room to create %s partition, "
+				"deleting any obsolete OS partitions...\n",
+				part->name);
+			nvram_remove_partition(NULL, NVRAM_SIG_OS,
+						valid_os_partitions);
+			p = nvram_create_partition(part->name, NVRAM_SIG_OS,
+					part->req_size, part->min_size);
 		}
 	}
 
 	if (p <= 0) {
-		pr_err("nvram: Failed to find or create "NVRAM_LOG_PART_NAME
-		       " partition, err %d\n", (int)p);
-		return 0;
+		pr_err("nvram: Failed to find or create %s"
+		       " partition, err %d\n", part->name, (int)p);
+		return -1;
 	}
 
-	nvram_error_log_index = p;
-	nvram_error_log_size = nvram_get_partition_size(p) -
-		sizeof(struct err_log_info);
+	part->index = p;
+	part->size = nvram_get_partition_size(p) - sizeof(struct err_log_info);
 	
 	return 0;
 }
-machine_late_initcall(pseries, pseries_nvram_init_log_partition);
+
+static int __init pseries_nvram_init_log_partitions(void)
+{
+	(void) pseries_nvram_init_os_partition(&rtas_log_partition);
+	return 0;
+}
+machine_late_initcall(pseries, pseries_nvram_init_log_partitions);
 
 int __init pSeries_nvram_init(void)
 {

^ permalink raw reply related

* [RFC PATCH 0/6] nvram: Capture oops/panic reports in NVRAM
From: Jim Keniston @ 2010-11-14  4:15 UTC (permalink / raw)
  To: linuxppc-dev

This patch series enables p Series systems to capture oops and panic
reports from the printk buffer into NVRAM, where they can be examined
after reboot using the nvram command.

Patches 1-2 implement the basic feature, and patch 4 adds compression,
so we can capture more of the printk buffer.  Patches 3 and 5-6 add
refinements.  Patch 5 is not powerpc-specific, and I plan to pursue that
independently on LKML.

This series applies atop the little bug-fix series I posted two days
ago --

"More ppc64 nvram code cleanup"
http://lists.ozlabs.org/pipermail/linuxppc-dev/2010-November/087009.html

-- which in turn applies atop Ben Herrenschmidt's Aug. 2 patch set --

"[RFC] Clean up ppc64 nvram code"
http://lists.ozlabs.org/pipermail/linuxppc-dev/2010-August/084601.html

My patches have been tested against 2.6.37-rc1.
---

Jim Keniston (6):
      Shrink our zlib_deflate workspace from 268K to 24K
      Slim down zlib_deflate workspace when possible
      Add compression to fit more printk output into NVRAM
      Always capture start of oops report to NVRAM
      Capture oops/panic reports in ibm,oops-log partition
      Generalize code for OS partitions in NVRAM


 arch/powerpc/include/asm/nvram.h       |    3 
 arch/powerpc/include/asm/rtas.h        |    6 
 arch/powerpc/kernel/nvram_64.c         |   31 ++
 arch/powerpc/platforms/pseries/nvram.c |  470 ++++++++++++++++++++++++++++----
 include/linux/zlib.h                   |   14 +
 lib/zlib_deflate/deflate.c             |   33 ++
 lib/zlib_deflate/deflate_syms.c        |    1 
 lib/zlib_deflate/defutil.h             |   17 +
 8 files changed, 504 insertions(+), 71 deletions(-)

--
Jim Keniston
IBM Linux Technology Center
Beaverton, OR

^ permalink raw reply

* [PATCH 2/6] nvram: Capture oops/panic reports in ibm, oops-log partition
From: Jim Keniston @ 2010-11-14  4:15 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20101114041510.9457.92921.stgit@localhost.localdomain>

Create the ibm,oops-log NVRAM partition, and capture the end of the printk
buffer in it when there's an oops or panic.  If we can't create the
ibm,oops-log partition, capture the oops/panic report in ibm,rtas-log.

Signed-off-by: Jim Keniston <jkenisto@us.ibm.com>
---

 arch/powerpc/platforms/pseries/nvram.c |   89 ++++++++++++++++++++++++++++++++
 1 files changed, 88 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
index 43d5c52..6c88cda 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -16,6 +16,8 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/kmsg_dump.h>
 #include <asm/uaccess.h>
 #include <asm/nvram.h>
 #include <asm/rtas.h>
@@ -50,11 +52,32 @@ static struct os_partition rtas_log_partition = {
 	.index = -1
 };
 
+static struct os_partition oops_log_partition = {
+	.name = "ibm,oops-log",
+	.req_size = 4000,
+	.min_size = 2000,
+	.index = -1
+};
+
 static const char *valid_os_partitions[] = {
 	"ibm,rtas-log",
+	"ibm,oops-log",
 	NULL
 };
 
+static void oops_to_nvram(struct kmsg_dumper *dumper,
+		enum kmsg_dump_reason reason,
+		const char *old_msgs, unsigned long old_len,
+		const char *new_msgs, unsigned long new_len);
+
+static struct kmsg_dumper nvram_kmsg_dumper = {
+	.dump = oops_to_nvram
+};
+
+/* We preallocate oops_buf during init to avoid kmalloc during oops/panic. */
+static size_t oops_buf_sz;
+static char *oops_buf;
+
 static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
 {
 	unsigned int i;
@@ -337,9 +360,36 @@ static int __init pseries_nvram_init_os_partition(struct os_partition *part)
 	return 0;
 }
 
+static void __init nvram_init_oops_partition(int rtas_partition_exists)
+{
+	int rc;
+
+	rc = pseries_nvram_init_os_partition(&oops_log_partition);
+	if (rc != 0) {
+		if (!rtas_partition_exists)
+			return;
+		pr_notice("nvram: Using %s partition to log both"
+			" RTAS errors and oops/panic reports\n",
+			rtas_log_partition.name);
+		memcpy(&oops_log_partition, &rtas_log_partition,
+						sizeof(rtas_log_partition));
+	}
+	oops_buf_sz = oops_log_partition.size - sizeof(struct err_log_info);
+	oops_buf = kmalloc(oops_buf_sz, GFP_KERNEL);
+	rc = kmsg_dump_register(&nvram_kmsg_dumper);
+	if (rc != 0) {
+		pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc);
+		kfree(oops_buf);
+		return;
+	}
+}
+
 static int __init pseries_nvram_init_log_partitions(void)
 {
-	(void) pseries_nvram_init_os_partition(&rtas_log_partition);
+	int rc;
+
+	rc = pseries_nvram_init_os_partition(&rtas_log_partition);
+	nvram_init_oops_partition(rc == 0);
 	return 0;
 }
 machine_late_initcall(pseries, pseries_nvram_init_log_partitions);
@@ -373,3 +423,40 @@ int __init pSeries_nvram_init(void)
 
 	return 0;
 }
+
+/*
+ * Try to capture the last capture_len bytes of the printk buffer.  Return
+ * the amount actually captured.
+ */
+static size_t capture_last_msgs(const char *old_msgs, size_t old_len,
+				const char *new_msgs, size_t new_len,
+				char *captured, size_t capture_len)
+{
+	if (new_len >= capture_len) {
+		memcpy(captured, new_msgs + (new_len - capture_len),
+								capture_len);
+		return capture_len;
+	} else {
+		/* Grab the end of old_msgs. */
+		size_t old_tail_len = min(old_len, capture_len - new_len);
+		memcpy(captured, old_msgs + (old_len - old_tail_len),
+								old_tail_len);
+		memcpy(captured + old_tail_len, new_msgs, new_len);
+		return old_tail_len + new_len;
+	}
+}
+
+/* our kmsg_dump callback */
+static void oops_to_nvram(struct kmsg_dumper *dumper,
+		enum kmsg_dump_reason reason,
+		const char *old_msgs, unsigned long old_len,
+		const char *new_msgs, unsigned long new_len)
+{
+	static unsigned int oops_count = 0;
+	size_t text_len;
+
+	text_len = capture_last_msgs(old_msgs, old_len, new_msgs, new_len,
+						oops_buf, oops_buf_sz);
+	(void) nvram_write_os_partition(&oops_log_partition, oops_buf,
+		(int) text_len, ERR_TYPE_KERNEL_PANIC, ++oops_count);
+}

^ permalink raw reply related

* [PATCH 3/6] nvram: Always capture start of oops report to NVRAM
From: Jim Keniston @ 2010-11-14  4:15 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <20101114041510.9457.92921.stgit@localhost.localdomain>

If we don't have room to capture the entire oops report, capture as much
as possible, starting 150 chars before the "Oops:" line.

Signed-off-by: Jim Keniston <jkenisto@us.ibm.com>
---

 arch/powerpc/platforms/pseries/nvram.c |   91 ++++++++++++++++++++++++++++++++
 1 files changed, 91 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
index 6c88cda..e1bc1a4 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -446,6 +446,87 @@ static size_t capture_last_msgs(const char *old_msgs, size_t old_len,
 	}
 }
 
+/* Find the last occurrence of needle in haystack, which is haystack_len long.*/
+static const char *strnrstr(const char *haystack, const char *needle,
+							size_t haystack_len)
+{
+	size_t needle_len = strlen(needle);
+	const char *haystack_end = haystack + haystack_len;
+	const char *prev, *next = NULL;
+	do {
+		prev = next;
+		next = strnstr(haystack, needle, haystack_len);
+		if (next) {
+			haystack = next + needle_len;
+			haystack_len = haystack_end - haystack;
+		}
+	} while (next);
+	return prev;
+}
+
+/* The preamble is the last bit of messages logged before the oops. */
+#define PREAMBLE_CHARS 150
+#define OOPS_TAG "Oops: "
+
+/*
+ * Find the beginning of the most recent oops report, back up PREAMBLE_CHARS
+ * characters, and copy up to captured_len characters from there to captured[].
+ * If we can't find the oops, just capture the end of the printk buffer,
+ * if we haven't already.
+ */
+static size_t capture_oops(const char *old_msgs, size_t old_len,
+				const char *new_msgs, size_t new_len,
+				char *captured, size_t capture_len,
+				size_t already_captured)
+{
+	const char *poops;	/* Points to the 'O' in "Oops: ..." */
+	const char *preamble;
+	const char *old_end = old_msgs + old_len;
+	const char *new_end = new_msgs + new_len;
+	size_t nc1, nc2;
+
+	if ((poops = strnrstr(new_msgs, OOPS_TAG, new_len)) != NULL) {
+		/* Oops starts in new_msgs -- the most common case. */
+		preamble = poops - PREAMBLE_CHARS;
+		if (preamble >= new_msgs) {
+			/* preamble is also in new_msgs. */
+			nc1 = min(capture_len, (size_t)(new_end - preamble));
+			memcpy(captured, preamble, nc1);
+			nc2 = 0;
+		} else {
+			/* Have to get some of the preamble from old_msgs */
+			nc1 = min((size_t)(new_msgs - preamble), old_len);
+			memcpy(captured, (old_end - nc1), nc1);
+			nc2 = min(new_len, capture_len - nc1);
+			memcpy(captured + nc1, new_msgs, nc2);
+		}
+	} else if ((poops = strnrstr(old_msgs, OOPS_TAG, old_len)) != NULL) {
+		/* Oops starts in old_msgs. */
+		preamble = poops - PREAMBLE_CHARS;
+		if (preamble < old_msgs)
+			preamble = old_msgs;
+		nc1 = min(capture_len, (size_t)(old_end - preamble));
+		memcpy(captured, preamble, nc1);
+		nc2 = min((size_t)(capture_len - nc1), new_len);
+		memcpy(captured + nc1, new_msgs, nc2);
+	} else {
+		/*
+		 * Either there was a VERY long oops report that scrolled
+		 * out of the printk buffer, or the "Oops" tag is split
+		 * across old_msgs and new_msgs, or oopses don't start with
+		 * "Oops" anymore.  Just capture as much of the last messages
+		 * as we think we can squeeze into NVRAM.
+		 */
+		if (already_captured)
+			return already_captured;
+		nc1 = capture_last_msgs(old_msgs, old_len, new_msgs,
+					new_len, captured, capture_len);
+		nc2 = 0;
+	}
+
+	return nc1 + nc2;
+}
+
 /* our kmsg_dump callback */
 static void oops_to_nvram(struct kmsg_dumper *dumper,
 		enum kmsg_dump_reason reason,
@@ -457,6 +538,16 @@ static void oops_to_nvram(struct kmsg_dumper *dumper,
 
 	text_len = capture_last_msgs(old_msgs, old_len, new_msgs, new_len,
 						oops_buf, oops_buf_sz);
+	if (reason == KMSG_DUMP_OOPS) {
+		/*
+		 * Ensure that we have the start of the oops report,
+		 * and the message(s) leading up to it.
+		 */
+		const char *poops = strnrstr(oops_buf, OOPS_TAG, oops_buf_sz);
+		if (!poops || poops < oops_buf + PREAMBLE_CHARS)
+			text_len = capture_oops(old_msgs, old_len, new_msgs,
+				new_len, oops_buf, oops_buf_sz, text_len);
+	}
 	(void) nvram_write_os_partition(&oops_log_partition, oops_buf,
 		(int) text_len, ERR_TYPE_KERNEL_PANIC, ++oops_count);
 }

^ permalink raw reply related

* Re: [PATCH v2] fsldma: add support to 36-bit physical address
From: Timur Tabi @ 2010-11-13 22:43 UTC (permalink / raw)
  To: Kumar Gala; +Cc: dan.j.williams, linuxppc-dev, linux-kernel
In-Reply-To: <54AAF9B7-9533-45B8-9C49-A964203AF707@kernel.crashing.org>

On Thu, Nov 11, 2010 at 5:56 AM, Kumar Gala <galak@kernel.crashing.org> wrote:

> Is there any reason we shouldn't set DMA_BIT_MASK(64) since the DMA block programming model allows the address to be 64-bits?

Can you explain that?  The DMA registers only have room for 36 bits
for the physical address.

-- 
Timur Tabi
Linux kernel developer at Freescale

^ permalink raw reply

* [PATCH 03/14 V2] arch/powerpc: Use printf extension %pR for struct resource
From: Joe Perches @ 2010-11-13  0:49 UTC (permalink / raw)
  To: Stephen Rothwell; +Cc: Paul Mackerras, Jiri Kosina, linuxppc-dev, linux-kernel
In-Reply-To: <20101113114228.e87c6902.sfr@canb.auug.org.au>

Using %pR standardizes the struct resource output.

Signed-off-by: Joe Perches <joe@perches.com>
---
On Sat, 2010-11-13 at 11:42 +1100, Stephen Rothwell wrote:
> Shouldn't this be just &hose->io_resource?

V2: Fix stupid editing mistake

 arch/powerpc/kernel/pci_64.c     |    3 +--
 arch/powerpc/sysdev/tsi108_dev.c |    8 ++++----
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index d43fc65..2ecb1de 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -193,8 +193,7 @@ int __devinit pcibios_map_io_space(struct pci_bus *bus)
 	hose->io_resource.start += io_virt_offset;
 	hose->io_resource.end += io_virt_offset;
 
-	pr_debug("  hose->io_resource=0x%016llx...0x%016llx\n",
-		 hose->io_resource.start, hose->io_resource.end);
+	pr_debug("  hose->io_resource=%pR\n", &hose->io_resource);
 
 	return 0;
 }
diff --git a/arch/powerpc/sysdev/tsi108_dev.c b/arch/powerpc/sysdev/tsi108_dev.c
index d4d15aa..5e249a8 100644
--- a/arch/powerpc/sysdev/tsi108_dev.c
+++ b/arch/powerpc/sysdev/tsi108_dev.c
@@ -83,8 +83,8 @@ static int __init tsi108_eth_of_init(void)
 		memset(&tsi_eth_data, 0, sizeof(tsi_eth_data));
 
 		ret = of_address_to_resource(np, 0, &r[0]);
-		DBG("%s: name:start->end = %s:0x%lx-> 0x%lx\n",
-			__func__,r[0].name, r[0].start, r[0].end);
+		DBG("%s: name:start->end = %s:%pR\n",
+		    __func__, r[0].name, &r[0]);
 		if (ret)
 			goto err;
 
@@ -92,8 +92,8 @@ static int __init tsi108_eth_of_init(void)
 		r[1].start = irq_of_parse_and_map(np, 0);
 		r[1].end = irq_of_parse_and_map(np, 0);
 		r[1].flags = IORESOURCE_IRQ;
-		DBG("%s: name:start->end = %s:0x%lx-> 0x%lx\n",
-			__func__,r[1].name, r[1].start, r[1].end);
+		DBG("%s: name:start->end = %s:%pR\n",
+			__func__, r[1].name, &r[1]);
 
 		tsi_eth_dev =
 		    platform_device_register_simple("tsi-ethernet", i++, &r[0],
-- 
1.7.3.1.g432b3.dirty

^ permalink raw reply related

* Re: [PATCH 03/14] arch/powerpc: Use printf extension %pR for struct resource
From: Stephen Rothwell @ 2010-11-13  0:42 UTC (permalink / raw)
  To: Joe Perches; +Cc: Paul Mackerras, Jiri Kosina, linuxppc-dev, linux-kernel
In-Reply-To: <7654162f86bedd7d4cd5ccc883916157af6a2369.1289597644.git.joe@perches.com>

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

Hi Joe,

On Fri, 12 Nov 2010 13:37:53 -0800 Joe Perches <joe@perches.com> wrote:
>
> Using %pR standardizes the struct resource output.
> 
> Signed-off-by: Joe Perches <joe@perches.com>
> ---
>  arch/powerpc/kernel/pci_64.c     |    3 +--
>  arch/powerpc/sysdev/tsi108_dev.c |    8 ++++----
>  2 files changed, 5 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
> index d43fc65..2ecb1de 100644
> --- a/arch/powerpc/kernel/pci_64.c
> +++ b/arch/powerpc/kernel/pci_64.c
> @@ -193,8 +193,7 @@ int __devinit pcibios_map_io_space(struct pci_bus *bus)
>  	hose->io_resource.start += io_virt_offset;
>  	hose->io_resource.end += io_virt_offset;
>  
> -	pr_debug("  hose->io_resource=0x%016llx...0x%016llx\n",
> -		 hose->io_resource.start, hose->io_resource.end);
> +	pr_debug("  hose->io_resource=%pR\n", &hose->io_resource.start);
                                              ^^^^^^^^^^^^^^^^^^^^^^^^
Shouldn't this be just &hose->io_resource?

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

[-- Attachment #2: Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply

* [PATCH 08/14] drivers/mtd/nand: Use printf extension %pR for struct resource
From: Joe Perches @ 2010-11-12 21:37 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: Olof Johansson, linuxppc-dev, David Woodhouse, linux-kernel,
	linux-mtd
In-Reply-To: <cover.1289597644.git.joe@perches.com>

Using %pR standardizes the struct resource output.

Signed-off-by: Joe Perches <joe@perches.com>
---
 drivers/mtd/nand/pasemi_nand.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c
index 6ddb246..bb277a5 100644
--- a/drivers/mtd/nand/pasemi_nand.c
+++ b/drivers/mtd/nand/pasemi_nand.c
@@ -107,7 +107,7 @@ static int __devinit pasemi_nand_probe(struct platform_device *ofdev,
 	if (pasemi_nand_mtd)
 		return -ENODEV;
 
-	pr_debug("pasemi_nand at %llx-%llx\n", res.start, res.end);
+	pr_debug("pasemi_nand at %pR\n", &res);
 
 	/* Allocate memory for MTD device structure and private data */
 	pasemi_nand_mtd = kzalloc(sizeof(struct mtd_info) +
-- 
1.7.3.1.g432b3.dirty

^ permalink raw reply related

* [PATCH 03/14] arch/powerpc: Use printf extension %pR for struct resource
From: Joe Perches @ 2010-11-12 21:37 UTC (permalink / raw)
  To: Jiri Kosina; +Cc: Paul Mackerras, linuxppc-dev, linux-kernel
In-Reply-To: <cover.1289597644.git.joe@perches.com>

Using %pR standardizes the struct resource output.

Signed-off-by: Joe Perches <joe@perches.com>
---
 arch/powerpc/kernel/pci_64.c     |    3 +--
 arch/powerpc/sysdev/tsi108_dev.c |    8 ++++----
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index d43fc65..2ecb1de 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -193,8 +193,7 @@ int __devinit pcibios_map_io_space(struct pci_bus *bus)
 	hose->io_resource.start += io_virt_offset;
 	hose->io_resource.end += io_virt_offset;
 
-	pr_debug("  hose->io_resource=0x%016llx...0x%016llx\n",
-		 hose->io_resource.start, hose->io_resource.end);
+	pr_debug("  hose->io_resource=%pR\n", &hose->io_resource.start);
 
 	return 0;
 }
diff --git a/arch/powerpc/sysdev/tsi108_dev.c b/arch/powerpc/sysdev/tsi108_dev.c
index d4d15aa..5e249a8 100644
--- a/arch/powerpc/sysdev/tsi108_dev.c
+++ b/arch/powerpc/sysdev/tsi108_dev.c
@@ -83,8 +83,8 @@ static int __init tsi108_eth_of_init(void)
 		memset(&tsi_eth_data, 0, sizeof(tsi_eth_data));
 
 		ret = of_address_to_resource(np, 0, &r[0]);
-		DBG("%s: name:start->end = %s:0x%lx-> 0x%lx\n",
-			__func__,r[0].name, r[0].start, r[0].end);
+		DBG("%s: name:start->end = %s:%pR\n",
+		    __func__, r[0].name, &r[0]);
 		if (ret)
 			goto err;
 
@@ -92,8 +92,8 @@ static int __init tsi108_eth_of_init(void)
 		r[1].start = irq_of_parse_and_map(np, 0);
 		r[1].end = irq_of_parse_and_map(np, 0);
 		r[1].flags = IORESOURCE_IRQ;
-		DBG("%s: name:start->end = %s:0x%lx-> 0x%lx\n",
-			__func__,r[1].name, r[1].start, r[1].end);
+		DBG("%s: name:start->end = %s:%pR\n",
+			__func__, r[1].name, &r[1]);
 
 		tsi_eth_dev =
 		    platform_device_register_simple("tsi-ethernet", i++, &r[0],
-- 
1.7.3.1.g432b3.dirty

^ permalink raw reply related

* [PATCH 00/14] Use printf extension %pR for struct resource
From: Joe Perches @ 2010-11-12 21:37 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: linux-mips, alsa-devel, linux-parisc, linux-rdma, netdev,
	linux-usb, linux-kernel, socketcan-core, linux-mtd, linuxppc-dev

Yet more trivia...

Joe Perches (14):
  arch/frv: Use printf extension %pR for struct resource
  arch/mips: Use printf extension %pR for struct resource
  arch/powerpc: Use printf extension %pR for struct resource
  drivers/dma/ppc4xx: Use printf extension %pR for struct resource
  drivers/infiniband: Use printf extension %pR for struct resource
  drivers/mfd: Use printf extension %pR for struct resource
  drivers/mtd/maps: Use printf extension %pR for struct resource
  drivers/mtd/nand: Use printf extension %pR for struct resource
  drivers/net/can/sja1000: Use printf extension %pR for struct resource
  drivers/parisc: Use printf extension %pR for struct resource
  drivers/rapidio: Use printf extension %pR for struct resource
  drivers/uwb: Use printf extension %pR for struct resource
  drivers/video: Use printf extension %pR for struct resource
  sound/ppc: Use printf extension %pR for struct resource

 arch/frv/mb93090-mb00/pci-vdk.c               |    8 ++------
 arch/mips/txx9/generic/pci.c                  |    7 ++-----
 arch/powerpc/kernel/pci_64.c                  |    3 +--
 arch/powerpc/sysdev/tsi108_dev.c              |    8 ++++----
 drivers/dma/ppc4xx/adma.c                     |    5 ++---
 drivers/infiniband/hw/ipath/ipath_driver.c    |    5 ++---
 drivers/mfd/sm501.c                           |    7 ++-----
 drivers/mtd/maps/amd76xrom.c                  |    7 ++-----
 drivers/mtd/maps/ck804xrom.c                  |    7 ++-----
 drivers/mtd/maps/esb2rom.c                    |    9 +++------
 drivers/mtd/maps/ichxrom.c                    |    9 +++------
 drivers/mtd/maps/physmap_of.c                 |    4 +---
 drivers/mtd/maps/scx200_docflash.c            |    5 ++---
 drivers/mtd/nand/pasemi_nand.c                |    2 +-
 drivers/net/can/sja1000/sja1000_of_platform.c |    8 ++------
 drivers/parisc/dino.c                         |   13 +++++--------
 drivers/parisc/hppb.c                         |    6 ++----
 drivers/rapidio/rio.c                         |    4 ++--
 drivers/uwb/umc-dev.c                         |    7 ++-----
 drivers/video/platinumfb.c                    |    8 ++------
 sound/ppc/pmac.c                              |   12 ++++--------
 21 files changed, 48 insertions(+), 96 deletions(-)

-- 
1.7.3.1.g432b3.dirty

^ permalink raw reply

* Re: [PATCH 2/2] ucc_geth: Fix deadlock
From: David Miller @ 2010-11-12 20:25 UTC (permalink / raw)
  To: cbouatmailru; +Cc: netdev, linuxppc-dev
In-Reply-To: <20101112140947.GB28223@oksana.dev.rtsoft.ru>

From: Anton Vorontsov <cbouatmailru@gmail.com>
Date: Fri, 12 Nov 2010 17:09:47 +0300

> On Fri, Nov 12, 2010 at 02:55:09PM +0100, Joakim Tjernlund wrote:
>> This script:
>>  while [ 1==1 ] ; do ifconfig eth0 up; usleep 1950000 ;ifconfig eth0 down; dmesg -c ;done
>> causes in just a second or two:
>> INFO: task ifconfig:572 blocked for more than 120 seconds.
> [...]
>> The reason appears to be ucc_geth_stop meets adjust_link as the
>> PHY reports PHY changes. I belive adjust_link hangs somewhere,
>> holding the PHY lock, because ucc_geth_stop disabled the
>> controller HW.
>> Fix is to stop the PHY before disabling the controller.
>> 
>> Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
> 
> It's unclear where exactly adjust_link() hangs, but the patch
> looks as the right thing overall.
> 
> Thanks!
> 
> Reviewed-by: Anton Vorontsov <cbouatmailru@gmail.com>

Applied.

^ permalink raw reply

* Re: [PATCH 1/2] ucc_geth: Do not bring the whole IF down when TX failure.
From: David Miller @ 2010-11-12 20:24 UTC (permalink / raw)
  To: cbouatmailru; +Cc: netdev, linuxppc-dev
In-Reply-To: <20101112140515.GA28223@oksana.dev.rtsoft.ru>

From: Anton Vorontsov <cbouatmailru@gmail.com>
Date: Fri, 12 Nov 2010 17:05:15 +0300

> On Fri, Nov 12, 2010 at 02:55:08PM +0100, Joakim Tjernlund wrote:
>> ucc_geth_close lacks a cancel_work_sync(&ugeth->timeout_work)
>> to stop any outstanding processing of TX fail. However, one
>> can not call cancel_work_sync without fixing the timeout function
>> otherwise it will deadlock. This patch brings ucc_geth in line with
>> gianfar:
>> 
>> Don't bring the interface down and up, just reinit controller HW
>> and PHY.
>> 
>> Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
> 
> Looks sane, thanks!
> 
> Reviewed-by: Anton Vorontsov <cbouatmailru@gmail.com>

Applied.

^ permalink raw reply

* [PATCH] serial: mpc52xx: make printout for type more generic
From: Wolfram Sang @ 2010-11-12 18:47 UTC (permalink / raw)
  To: linux-serial; +Cc: linuxppc-dev, Greg Kroah-Hartman

The printout for the type should be just "5xxx", so 512x users won't
wonder why they have a mpc52xx-type UART.

Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
---

At least I got confused and thought the wrong type was detected.

 drivers/serial/mpc52xx_uart.c |    6 +++++-
 include/linux/serial_core.h   |    2 +-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index c4399e2..126ec7f 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -838,7 +838,11 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new,
 static const char *
 mpc52xx_uart_type(struct uart_port *port)
 {
-	return port->type == PORT_MPC52xx ? "MPC52xx PSC" : NULL;
+	/*
+	 * We keep using PORT_MPC52xx for historic reasons although it applies
+	 * for MPC512x, too, but print "MPC5xxx" to not irritate users
+	 */
+	return port->type == PORT_MPC52xx ? "MPC5xxx PSC" : NULL;
 }
 
 static void
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 212eb4c..3b354bf 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -95,7 +95,7 @@
 /* PPC CPM type number */
 #define PORT_CPM        58
 
-/* MPC52xx type numbers */
+/* MPC52xx (and MPC512x) type numbers */
 #define PORT_MPC52xx	59
 
 /* IBM icom */
-- 
1.7.2.3

^ permalink raw reply related

* RE: [PATCH][v3] fsl_rio: move machine_check handler into machine_check_e500 & machine_check_e500mc
From: Bounine, Alexandre @ 2010-11-12 16:30 UTC (permalink / raw)
  To: Shaohui Xie, linuxppc-dev; +Cc: akpm, Kumar Gala
In-Reply-To: <1289548520-24110-1-git-send-email-b21989@freescale.com>

Shaohui Xie <b21989@freescale.com> wrote:
> diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
> index a45a63c..9ab7b97 100644
> --- a/arch/powerpc/kernel/traps.c
> +++ b/arch/powerpc/kernel/traps.c
> @@ -55,6 +55,7 @@
>  #endif
>  #include <asm/kexec.h>
>  #include <asm/ppc-opcode.h>
> +#include <asm/rio.h>
>=20
>  #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
>  int (*__debugger)(struct pt_regs *regs) __read_mostly;
> @@ -425,6 +426,12 @@ int machine_check_e500mc(struct pt_regs *regs)
>  	unsigned long reason =3D mcsr;
>  	int recoverable =3D 1;
>=20
> +	if (reason & MCSR_BUS_RBERR) {
> +		recoverable =3D fsl_rio_mcheck_exception(regs);
> +		if (recoverable =3D=3D 1)
> +			goto silent_out;
> +	}
> +
>  	printk("Machine check in kernel mode.\n");
>  	printk("Caused by (from MCSR=3D%lx): ", reason);
>=20
> @@ -500,6 +507,7 @@ int machine_check_e500mc(struct pt_regs *regs)
>  		       reason & MCSR_MEA ? "Effective" : "Physical",
addr);
>  	}
>=20
> +silent_out:
>  	mtspr(SPRN_MCSR, mcsr);
>  	return mfspr(SPRN_MCSR) =3D=3D 0 && recoverable;
>  }
> @@ -507,6 +515,13 @@ int machine_check_e500mc(struct pt_regs *regs)
>  int machine_check_e500(struct pt_regs *regs)
>  {
>  	unsigned long reason =3D get_mc_reason(regs);
> +	int ret =3D 0;
> +
> +	if (reason & MCSR_BUS_RBERR) {
> +		ret =3D fsl_rio_mcheck_exception(regs);
> +		if (ret =3D=3D 1)
> +			return ret;
> +	}

Do we really need 'ret' variable here?
There is no further use of it by the rest of the code.
Maybe just return 1 here if fsl_rio_mcheck_exception() returns 1 ?

>=20
>  	printk("Machine check in kernel mode.\n");
>  	printk("Caused by (from MCSR=3D%lx): ", reason);
> @@ -536,7 +551,7 @@ int machine_check_e500(struct pt_regs *regs)
>  	if (reason & MCSR_BUS_RPERR)
>  		printk("Bus - Read Parity Error\n");
>=20
> -	return 0;
> +	return ret;
>  }
>  #elif defined(CONFIG_E200)
>  int machine_check_e200(struct pt_regs *regs)

Works for RapidIO as expected now.

Thank you,

Alex.

^ permalink raw reply

* Re: [PATCH 2/2] ucc_geth: Fix deadlock
From: Anton Vorontsov @ 2010-11-12 14:09 UTC (permalink / raw)
  To: Joakim Tjernlund; +Cc: netdev, linuxppc-dev
In-Reply-To: <1289570109-8160-2-git-send-email-Joakim.Tjernlund@transmode.se>

On Fri, Nov 12, 2010 at 02:55:09PM +0100, Joakim Tjernlund wrote:
> This script:
>  while [ 1==1 ] ; do ifconfig eth0 up; usleep 1950000 ;ifconfig eth0 down; dmesg -c ;done
> causes in just a second or two:
> INFO: task ifconfig:572 blocked for more than 120 seconds.
[...]
> The reason appears to be ucc_geth_stop meets adjust_link as the
> PHY reports PHY changes. I belive adjust_link hangs somewhere,
> holding the PHY lock, because ucc_geth_stop disabled the
> controller HW.
> Fix is to stop the PHY before disabling the controller.
> 
> Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>

It's unclear where exactly adjust_link() hangs, but the patch
looks as the right thing overall.

Thanks!

Reviewed-by: Anton Vorontsov <cbouatmailru@gmail.com>

> ---
>  drivers/net/ucc_geth.c |   10 +++++++---
>  1 files changed, 7 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
> index 6c254ed..06a5db3 100644
> --- a/drivers/net/ucc_geth.c
> +++ b/drivers/net/ucc_geth.c
> @@ -2050,12 +2050,16 @@ static void ucc_geth_stop(struct ucc_geth_private *ugeth)
>  
>  	ugeth_vdbg("%s: IN", __func__);
>  
> +	/*
> +	 * Tell the kernel the link is down.
> +	 * Must be done before disabling the controller
> +	 * or deadlock may happen.
> +	 */
> +	phy_stop(phydev);
> +
>  	/* Disable the controller */
>  	ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
>  
> -	/* Tell the kernel the link is down */
> -	phy_stop(phydev);
> -
>  	/* Mask all interrupts */
>  	out_be32(ugeth->uccf->p_uccm, 0x00000000);

^ 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