linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Nigel Cunningham <nigel@tuxonice.net>
To: linux-pm@lists.linux-foundation.org,
	linux-kernel@vger.kernel.org, tuxonice-devel@lists.tuxonice.net
Cc: Nigel Cunningham <nigel@tuxonice.net>
Subject: [PATCH 12/19] TuxOnIce: Compression support.
Date: Thu,  7 May 2009 00:39:08 +1000	[thread overview]
Message-ID: <1241620755-22133-13-git-send-email-nigel@tuxonice.net> (raw)
In-Reply-To: <1241620755-22133-1-git-send-email-nigel@tuxonice.net>

Multithreaded support for compressing pages using cryptoapi algorithms
and passing them to whatever code is writing the image.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/Kconfig             |   15 ++
 kernel/power/Makefile            |    1 +
 kernel/power/tuxonice_compress.c |  434 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 450 insertions(+), 0 deletions(-)
 create mode 100644 kernel/power/tuxonice_compress.c

diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 498b5c2..1b474a6 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -195,6 +195,21 @@ menuconfig TOI_CORE
 	comment "General Options"
 		depends on TOI_CORE
 
+	config TOI_CRYPTO
+		bool "Compression support"
+		depends on TOI_CORE && CRYPTO
+		default y
+		---help---
+		  This option adds support for using cryptoapi compression
+		  algorithms. Compression is particularly useful as it can
+		  more than double your suspend and resume speed (depending
+		  upon how well your image compresses).
+
+		  You probably want this, so say Y here.
+
+	comment "No compression support available without Cryptoapi support."
+		depends on TOI_CORE && !CRYPTO
+
 	config TOI_KEEP_IMAGE
 		bool "Allow Keep Image Mode"
 		depends on TOI_CORE
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index 9ad139e..3803866 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -15,6 +15,7 @@ tuxonice_core-objs		+= tuxonice_storage.o tuxonice_netlink.o
 endif
 
 obj-$(CONFIG_TOI_CORE)		+= tuxonice_core.o
+obj-$(CONFIG_TOI_CRYPTO)	+= tuxonice_compress.o
 
 obj-$(CONFIG_PM)		+= main.o
 obj-$(CONFIG_PM_SLEEP)		+= console.o
diff --git a/kernel/power/tuxonice_compress.c b/kernel/power/tuxonice_compress.c
new file mode 100644
index 0000000..1ce3d02
--- /dev/null
+++ b/kernel/power/tuxonice_compress.c
@@ -0,0 +1,434 @@
+/*
+ * kernel/power/compression.c
+ *
+ * Copyright (C) 2003-2008 Nigel Cunningham (nigel at tuxonice net)
+ *
+ * This file is released under the GPLv2.
+ *
+ * This file contains data compression routines for TuxOnIce,
+ * using cryptoapi.
+ */
+
+#include <linux/suspend.h>
+#include <linux/highmem.h>
+#include <linux/vmalloc.h>
+#include <linux/crypto.h>
+
+#include "tuxonice_builtin.h"
+#include "tuxonice.h"
+#include "tuxonice_modules.h"
+#include "tuxonice_sysfs.h"
+#include "tuxonice_io.h"
+#include "tuxonice_ui.h"
+#include "tuxonice_alloc.h"
+
+static int toi_expected_compression;
+
+static struct toi_module_ops toi_compression_ops;
+static struct toi_module_ops *next_driver;
+
+static char toi_compressor_name[32] = "lzo";
+
+static DEFINE_MUTEX(stats_lock);
+
+struct cpu_context {
+	u8 *page_buffer;
+	struct crypto_comp *transform;
+	unsigned int len;
+	char *buffer_start;
+	char *output_buffer;
+};
+
+static DEFINE_PER_CPU(struct cpu_context, contexts);
+
+static int toi_compress_prepare_result;
+
+/*
+ * toi_compress_cleanup
+ *
+ * Frees memory allocated for our labours.
+ */
+static void toi_compress_cleanup(int toi_or_resume)
+{
+	int cpu;
+
+	if (!toi_or_resume)
+		return;
+
+	for_each_online_cpu(cpu) {
+		struct cpu_context *this = &per_cpu(contexts, cpu);
+		if (this->transform) {
+			crypto_free_comp(this->transform);
+			this->transform = NULL;
+		}
+
+		if (this->page_buffer)
+			toi_free_page(16, (unsigned long) this->page_buffer);
+
+		this->page_buffer = NULL;
+
+		if (this->output_buffer)
+			vfree(this->output_buffer);
+
+		this->output_buffer = NULL;
+	}
+}
+
+/*
+ * toi_crypto_prepare
+ *
+ * Prepare to do some work by allocating buffers and transforms.
+ */
+static int toi_compress_crypto_prepare(void)
+{
+	int cpu;
+
+	if (!*toi_compressor_name) {
+		printk(KERN_INFO "TuxOnIce: Compression enabled but no "
+				"compressor name set.\n");
+		return 1;
+	}
+
+	for_each_online_cpu(cpu) {
+		struct cpu_context *this = &per_cpu(contexts, cpu);
+		this->transform = crypto_alloc_comp(toi_compressor_name, 0, 0);
+		if (IS_ERR(this->transform)) {
+			printk(KERN_INFO "TuxOnIce: Failed to initialise the "
+					"%s compression transform.\n",
+					toi_compressor_name);
+			this->transform = NULL;
+			return 1;
+		}
+
+		this->page_buffer =
+			(char *) toi_get_zeroed_page(16, TOI_ATOMIC_GFP);
+
+		if (!this->page_buffer) {
+			printk(KERN_ERR
+			  "Failed to allocate a page buffer for TuxOnIce "
+			  "compression driver.\n");
+			return -ENOMEM;
+		}
+
+		this->output_buffer =
+			(char *) vmalloc_32(2 * PAGE_SIZE);
+
+		if (!this->output_buffer) {
+			printk(KERN_ERR
+			  "Failed to allocate a output buffer for TuxOnIce "
+			  "compression driver.\n");
+			return -ENOMEM;
+		}
+
+	}
+
+	return 0;
+}
+
+/*
+ * toi_compress_init
+ */
+
+static int toi_compress_init(int toi_or_resume)
+{
+	if (!toi_or_resume)
+		return 0;
+
+	toi_compress_bytes_in = 0;
+	toi_compress_bytes_out = 0;
+
+	next_driver = toi_get_next_filter(&toi_compression_ops);
+
+	if (!next_driver)
+		return -ECHILD;
+
+	toi_compress_prepare_result = toi_compress_crypto_prepare();
+
+	return 0;
+}
+
+/*
+ * toi_compress_rw_init()
+ */
+
+static int toi_compress_rw_init(int rw, int stream_number)
+{
+	if (toi_compress_prepare_result) {
+		printk(KERN_ERR "Failed to initialise compression "
+				"algorithm.\n");
+		if (rw == READ) {
+			printk(KERN_INFO "Unable to read the image.\n");
+			return -ENODEV;
+		} else {
+			printk(KERN_INFO "Continuing without "
+				"compressing the image.\n");
+			toi_compression_ops.enabled = 0;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * toi_compress_write_page()
+ *
+ * Compress a page of data, buffering output and passing on filled
+ * pages to the next module in the pipeline.
+ *
+ * Buffer_page:	Pointer to a buffer of size PAGE_SIZE, containing
+ * data to be compressed.
+ *
+ * Returns:	0 on success. Otherwise the error is that returned by later
+ * 		modules, -ECHILD if we have a broken pipeline or -EIO if
+ * 		zlib errs.
+ */
+static int toi_compress_write_page(unsigned long index,
+		struct page *buffer_page, unsigned int buf_size)
+{
+	int ret, cpu = smp_processor_id();
+	struct cpu_context *ctx = &per_cpu(contexts, cpu);
+
+	if (!ctx->transform)
+		return next_driver->write_page(index, buffer_page, buf_size);
+
+	ctx->buffer_start = kmap(buffer_page);
+
+	ctx->len = buf_size;
+
+	ret = crypto_comp_compress(ctx->transform,
+			ctx->buffer_start, buf_size,
+			ctx->output_buffer, &ctx->len);
+
+	kunmap(buffer_page);
+
+	mutex_lock(&stats_lock);
+	toi_compress_bytes_in += buf_size;
+	toi_compress_bytes_out += ctx->len;
+	mutex_unlock(&stats_lock);
+
+	if (!ret && ctx->len < buf_size) { /* some compression */
+		memcpy(ctx->page_buffer, ctx->output_buffer, ctx->len);
+		return next_driver->write_page(index,
+				virt_to_page(ctx->page_buffer),
+				ctx->len);
+	} else
+		return next_driver->write_page(index, buffer_page, buf_size);
+}
+
+/*
+ * toi_compress_read_page()
+ * @buffer_page: struct page *. Pointer to a buffer of size PAGE_SIZE.
+ *
+ * Retrieve data from later modules and decompress it until the input buffer
+ * is filled.
+ * Zero if successful. Error condition from me or from downstream on failure.
+ */
+static int toi_compress_read_page(unsigned long *index,
+		struct page *buffer_page, unsigned int *buf_size)
+{
+	int ret, cpu = smp_processor_id();
+	unsigned int len;
+	unsigned int outlen = PAGE_SIZE;
+	char *buffer_start;
+	struct cpu_context *ctx = &per_cpu(contexts, cpu);
+
+	if (!ctx->transform)
+		return next_driver->read_page(index, buffer_page, buf_size);
+
+	/*
+	 * All our reads must be synchronous - we can't decompress
+	 * data that hasn't been read yet.
+	 */
+
+	*buf_size = PAGE_SIZE;
+
+	ret = next_driver->read_page(index, buffer_page, &len);
+
+	/* Error or uncompressed data */
+	if (ret || len == PAGE_SIZE)
+		return ret;
+
+	buffer_start = kmap(buffer_page);
+	memcpy(ctx->page_buffer, buffer_start, len);
+	ret = crypto_comp_decompress(
+			ctx->transform,
+			ctx->page_buffer,
+			len, buffer_start, &outlen);
+	if (ret)
+		abort_hibernate(TOI_FAILED_IO,
+			"Compress_read returned %d.\n", ret);
+	else if (outlen != PAGE_SIZE) {
+		abort_hibernate(TOI_FAILED_IO,
+			"Decompression yielded %d bytes instead of %ld.\n",
+			outlen, PAGE_SIZE);
+		printk(KERN_ERR "Decompression yielded %d bytes instead of "
+				"%ld.\n", outlen, PAGE_SIZE);
+		ret = -EIO;
+		*buf_size = outlen;
+	}
+	kunmap(buffer_page);
+	return ret;
+}
+
+/*
+ * toi_compress_print_debug_stats
+ * @buffer: Pointer to a buffer into which the debug info will be printed.
+ * @size: Size of the buffer.
+ *
+ * Print information to be recorded for debugging purposes into a buffer.
+ * Returns: Number of characters written to the buffer.
+ */
+
+static int toi_compress_print_debug_stats(char *buffer, int size)
+{
+	unsigned long pages_in = toi_compress_bytes_in >> PAGE_SHIFT,
+		      pages_out = toi_compress_bytes_out >> PAGE_SHIFT;
+	int len;
+
+	/* Output the compression ratio achieved. */
+	if (*toi_compressor_name)
+		len = scnprintf(buffer, size, "- Compressor is '%s'.\n",
+				toi_compressor_name);
+	else
+		len = scnprintf(buffer, size, "- Compressor is not set.\n");
+
+	if (pages_in)
+		len += scnprintf(buffer+len, size - len, "  Compressed "
+			"%lu bytes into %lu (%ld percent compression).\n",
+		  toi_compress_bytes_in,
+		  toi_compress_bytes_out,
+		  (pages_in - pages_out) * 100 / pages_in);
+	return len;
+}
+
+/*
+ * toi_compress_compression_memory_needed
+ *
+ * Tell the caller how much memory we need to operate during hibernate/resume.
+ * Returns: Unsigned long. Maximum number of bytes of memory required for
+ * operation.
+ */
+static int toi_compress_memory_needed(void)
+{
+	return 2 * PAGE_SIZE;
+}
+
+static int toi_compress_storage_needed(void)
+{
+	return 4 * sizeof(unsigned long) + strlen(toi_compressor_name) + 1;
+}
+
+/*
+ * toi_compress_save_config_info
+ * @buffer: Pointer to a buffer of size PAGE_SIZE.
+ *
+ * Save informaton needed when reloading the image at resume time.
+ * Returns: Number of bytes used for saving our data.
+ */
+static int toi_compress_save_config_info(char *buffer)
+{
+	int namelen = strlen(toi_compressor_name) + 1;
+	int total_len;
+
+	*((unsigned long *) buffer) = toi_compress_bytes_in;
+	*((unsigned long *) (buffer + 1 * sizeof(unsigned long))) =
+		toi_compress_bytes_out;
+	*((unsigned long *) (buffer + 2 * sizeof(unsigned long))) =
+		toi_expected_compression;
+	*((unsigned long *) (buffer + 3 * sizeof(unsigned long))) = namelen;
+	strncpy(buffer + 4 * sizeof(unsigned long), toi_compressor_name,
+								namelen);
+	total_len = 4 * sizeof(unsigned long) + namelen;
+	return total_len;
+}
+
+/* toi_compress_load_config_info
+ * @buffer: Pointer to the start of the data.
+ * @size: Number of bytes that were saved.
+ *
+ * Description:	Reload information needed for decompressing the image at
+ * resume time.
+ */
+static void toi_compress_load_config_info(char *buffer, int size)
+{
+	int namelen;
+
+	toi_compress_bytes_in = *((unsigned long *) buffer);
+	toi_compress_bytes_out = *((unsigned long *) (buffer + 1 *
+				sizeof(unsigned long)));
+	toi_expected_compression = *((unsigned long *) (buffer + 2 *
+				sizeof(unsigned long)));
+	namelen = *((unsigned long *) (buffer + 3 * sizeof(unsigned long)));
+	if (strncmp(toi_compressor_name, buffer + 4 * sizeof(unsigned long),
+				namelen)) {
+		toi_compress_cleanup(1);
+		strncpy(toi_compressor_name, buffer + 4 * sizeof(unsigned long),
+			namelen);
+		toi_compress_crypto_prepare();
+	}
+	return;
+}
+
+/*
+ * toi_expected_compression_ratio
+ *
+ * Description:	Returns the expected ratio between data passed into this module
+ * 		and the amount of data output when writing.
+ * Returns:	100 if the module is disabled. Otherwise the value set by the
+ * 		user via our sysfs entry.
+ */
+
+static int toi_compress_expected_ratio(void)
+{
+	if (!toi_compression_ops.enabled)
+		return 100;
+	else
+		return 100 - toi_expected_compression;
+}
+
+/*
+ * data for our sysfs entries.
+ */
+static struct toi_sysfs_data sysfs_params[] = {
+	SYSFS_INT("expected_compression", SYSFS_RW, &toi_expected_compression,
+			0, 99, 0, NULL),
+	SYSFS_INT("enabled", SYSFS_RW, &toi_compression_ops.enabled, 0, 1, 0,
+			NULL),
+	SYSFS_STRING("algorithm", SYSFS_RW, toi_compressor_name, 31, 0, NULL),
+};
+
+/*
+ * Ops structure.
+ */
+static struct toi_module_ops toi_compression_ops = {
+	.type			= FILTER_MODULE,
+	.name			= "compression",
+	.directory		= "compression",
+	.module			= THIS_MODULE,
+	.initialise		= toi_compress_init,
+	.cleanup		= toi_compress_cleanup,
+	.memory_needed 		= toi_compress_memory_needed,
+	.print_debug_info	= toi_compress_print_debug_stats,
+	.save_config_info	= toi_compress_save_config_info,
+	.load_config_info	= toi_compress_load_config_info,
+	.storage_needed		= toi_compress_storage_needed,
+	.expected_compression	= toi_compress_expected_ratio,
+
+	.rw_init		= toi_compress_rw_init,
+
+	.write_page		= toi_compress_write_page,
+	.read_page		= toi_compress_read_page,
+
+	.sysfs_data		= sysfs_params,
+	.num_sysfs_entries	= sizeof(sysfs_params) /
+		sizeof(struct toi_sysfs_data),
+};
+
+/* ---- Registration ---- */
+
+static __init int toi_compress_load(void)
+{
+	return toi_register_module(&toi_compression_ops);
+}
+
+late_initcall(toi_compress_load);
-- 
1.5.6.3


  parent reply	other threads:[~2009-05-06 14:50 UTC|newest]

Thread overview: 141+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-05-06 14:38 [RFC] TuxOnIce Nigel Cunningham
2009-05-06 14:38 ` [PATCH 1/19] TuxOnIce: Documentation Nigel Cunningham
2009-05-16 20:10   ` Vegard Nossum
2009-05-16 22:18     ` Nigel Cunningham
2009-05-06 14:38 ` [PATCH 2/19] TuxOnIce: GEMS support Nigel Cunningham
2009-05-06 14:38 ` [PATCH 3/19] TuxOnIce: Make drop_pagecache non-static and declared in mm.h Nigel Cunningham
2009-05-06 14:39 ` [PATCH 4/19] TuxOnIce: Add support for just thawing kernel threads Nigel Cunningham
2009-05-06 14:39 ` [PATCH 5/19] TuxOnIce: Create means of determining how many pages can be allocated Nigel Cunningham
2009-05-06 14:39 ` [PATCH 6/19] TuxOnIce: Make functions and variables shared with swsusp non-static Nigel Cunningham
2009-05-06 14:39 ` [PATCH 7/19] TuxOnIce: Modify swsusp bitmaps to allow modification during scanning Nigel Cunningham
2009-05-06 14:39 ` [PATCH 8/19] TuxOnIce: Add core TuxOnIce code Nigel Cunningham
2009-05-06 14:39 ` [PATCH 9/19] TuxOnIce: Netlink support Nigel Cunningham
2009-05-06 21:03   ` Sam Ravnborg
2009-05-06 21:35     ` Nigel Cunningham
2009-05-07  4:34       ` Sam Ravnborg
2009-05-06 14:39 ` [PATCH 10/19] TuxOnIce: Storage manager support Nigel Cunningham
2009-05-06 14:39 ` [PATCH 11/19] TuxOnIce: Block I/O engine Nigel Cunningham
2009-05-06 14:39 ` Nigel Cunningham [this message]
2009-05-06 14:39 ` [PATCH 13/19] TuxOnIce: File allocator Nigel Cunningham
2009-05-06 14:39 ` [PATCH 14/19] TuxOnIce: Swap support Nigel Cunningham
2009-05-06 14:39 ` [PATCH 15/19] TuxOnIce: Userspace user interface support Nigel Cunningham
2009-05-06 14:39 ` [PATCH 16/19] TuxOnIce: Warn user if an initrd doesn't include an attempt at resuming Nigel Cunningham
2009-05-06 14:39 ` [PATCH 17/19] TuxOnIce: Support for replacing swsusp Nigel Cunningham
2009-05-06 14:39 ` [PATCH 18/19] TuxOnIce: Provide a means of determining the freezer state Nigel Cunningham
2009-05-06 14:39 ` [PATCH 19/19] TuxOnIce: Don't try to wake kswapd if the freezer is on Nigel Cunningham
2009-05-07 12:09 ` [RFC] TuxOnIce Pavel Machek
2009-05-07 15:28   ` [TuxOnIce-devel] " Kenneth Crudup
2009-05-07 17:05     ` Kenneth Crudup
2009-05-09  9:10       ` Stefan Richter
2009-05-10  5:37       ` Pavel Machek
2009-05-10  5:37     ` Pavel Machek
2009-05-07 16:55   ` U Kuehn
2009-05-07 17:45     ` Rafael J. Wysocki
2009-05-07 17:49       ` Kenneth Crudup
2009-05-07 18:54         ` Fabio Comolli
2009-05-07 18:57           ` Kenneth Crudup
2009-05-07 17:52       ` Matt Price
2009-05-07 18:22         ` Rafael J. Wysocki
2009-05-07 18:57           ` Fabio Comolli
2009-05-07 19:27             ` Rafael J. Wysocki
2009-05-07 20:41               ` Nigel Cunningham
2009-05-07 23:14                 ` Jesse Barnes
2009-05-07 23:32                   ` Nigel Cunningham
2009-05-07 23:43                     ` Jesse Barnes
2009-05-08  0:13                       ` Nigel Cunningham
2009-05-08  0:39                         ` Jesse Barnes
2009-05-08  0:49                           ` Nigel Cunningham
2009-05-08  0:18                       ` Rafael J. Wysocki
2009-05-07 21:46             ` Pavel Machek
2009-05-08  7:11               ` Fabio Comolli
2009-05-07 21:42     ` Pavel Machek
2009-05-08  0:11     ` Alex Goebel
2009-05-07 17:42   ` Rafael J. Wysocki
2009-05-07 20:37     ` Nigel Cunningham
2009-05-07 21:51     ` Pavel Machek
2009-05-08  1:34       ` [TuxOnIce-devel] " Nigel Cunningham
2009-05-08 14:11         ` Rafael J. Wysocki
2009-05-08 21:52           ` Nigel Cunningham
2009-05-08 22:46             ` Rafael J. Wysocki
2009-05-08 23:30               ` Nigel Cunningham
2009-05-08 23:43                 ` Rafael J. Wysocki
2009-05-25 10:05                   ` Nigel Cunningham
2009-05-25 12:43                     ` Pavel Machek
2009-05-25 13:15                       ` Nigel Cunningham
2009-05-25 21:43                     ` Rafael J. Wysocki
     [not found]                       ` <1243288705.16743.129.camel@nigel-laptop>
2009-05-25 22:39                         ` Rafael J. Wysocki
2009-05-26  0:39                           ` Nigel Cunningham
2009-05-26 22:27                             ` Rafael J. Wysocki
2009-05-27  0:02                               ` Nigel Cunningham
2009-05-27 18:26                                 ` [linux-pm] " Len Brown
2009-05-25 22:45                       ` Oliver Neukum
2009-05-25 22:58                         ` Rafael J. Wysocki
2009-05-25 23:13                           ` Oliver Neukum
2009-05-27 14:38                             ` Martin Steigerwald
2009-05-26  0:42                           ` Nigel Cunningham
2009-05-26  9:19                           ` Pavel Machek
2009-05-26 11:07                             ` Oliver Neukum
2009-05-26 21:33                               ` Nigel Cunningham
2009-05-26 21:56                                 ` [linux-pm] " Alan Stern
2009-05-26 22:24                                   ` Oliver Neukum
2009-05-27  0:00                                     ` Nigel Cunningham
2009-05-26 23:59                                   ` Nigel Cunningham
2009-05-26 21:36                               ` Pavel Machek
2009-05-26 21:29                             ` Nigel Cunningham
2009-05-26 22:51                           ` Oliver Neukum
2009-05-26 23:10                             ` Rafael J. Wysocki
2009-05-26  0:42                         ` Nigel Cunningham
2009-05-08 23:44                 ` Ray Lee
2009-05-27 19:10                   ` Len Brown
2009-05-27 23:43                     ` Nigel Cunningham
2009-05-09 13:54                 ` Pavel Machek
2009-05-25  9:53                   ` Nigel Cunningham
2009-05-25 22:02                     ` Rafael J. Wysocki
2009-05-26  0:19                       ` Nigel Cunningham
2009-05-26 22:37                         ` Rafael J. Wysocki
2009-05-27  0:06                           ` Nigel Cunningham
2009-05-28 11:50                     ` Pavel Machek
2009-05-09 13:27               ` Pavel Machek
2009-05-09 19:32                 ` Rafael J. Wysocki
2009-05-09 22:22                   ` Nigel Cunningham
2009-05-14  9:16                   ` Pavel Machek
2009-05-16 23:11                     ` Nigel Cunningham
2009-05-09 13:03           ` Pavel Machek
2009-05-08 19:44         ` Bartlomiej Zolnierkiewicz
2009-05-08 21:03           ` Rafael J. Wysocki
2009-05-08 22:37             ` Nigel Cunningham
2009-05-08 21:59           ` Nigel Cunningham
2009-05-08 23:05             ` Bartlomiej Zolnierkiewicz
2009-05-08 23:15               ` Nigel Cunningham
2009-05-09 13:58                 ` Pavel Machek
2009-05-25  9:27                   ` Nigel Cunningham
2009-05-25 12:32                     ` Pavel Machek
2009-05-25 13:22                       ` Oliver Neukum
2009-05-25 13:26                         ` Pavel Machek
2009-05-25 21:50                           ` Nigel Cunningham
2009-05-25 21:39                       ` Nigel Cunningham
2009-05-25 22:29                         ` Oliver Neukum
2009-05-26  0:28                           ` Nigel Cunningham
2009-05-26  0:35                           ` david
2009-05-26  0:47                             ` Nigel Cunningham
2009-05-26  8:43                           ` Pavel Machek
2009-05-26 10:56                             ` Oliver Neukum
2009-05-09 11:12             ` Pekka Enberg
2009-05-07 22:37   ` trekker.dk
2009-05-08  1:17     ` Shannon McMackin
2009-05-08 21:47       ` Fabio Comolli
2009-05-10  5:38       ` Pavel Machek
2009-05-11 20:10         ` Vladislav Bolkhovitin
2009-05-10  5:38     ` Pavel Machek
2009-05-11 21:19       ` trekker.dk
2009-05-11 21:23         ` Pavel Machek
2009-05-13 20:19           ` trekker.dk
2009-05-13 20:24             ` Pavel Machek
2009-05-13 22:07               ` trekker.dk
2009-05-11 23:23         ` Alex Goebel
2009-05-16 19:07 ` Martin Steigerwald
2009-05-17  2:53   ` Matt Price
2009-05-17  3:06     ` Nigel Cunningham
2009-05-17  3:24       ` Matt Price
2009-05-17  3:57 ` Benjamin Herrenschmidt
2009-05-17  5:02   ` Nigel Cunningham

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1241620755-22133-13-git-send-email-nigel@tuxonice.net \
    --to=nigel@tuxonice.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@lists.linux-foundation.org \
    --cc=tuxonice-devel@lists.tuxonice.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).