* 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
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox