From: Nigel Cunningham <ncunningham@linuxmail.org>
To: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: Suspend 2 merge: 46/51: LZF support.
Date: Thu, 25 Nov 2004 00:02:09 +1100 [thread overview]
Message-ID: <1101300108.5805.380.camel@desktop.cunninghams> (raw)
In-Reply-To: <1101292194.5805.180.camel@desktop.cunninghams>
This is LZF support, contributed under a dual license (see below) by
Marc Lehmann. It flies! (Those stats in the debug info in an earlier
patch were real!).
diff -ruN 852-lzf-old/kernel/power/lzf/lzf_c.c 852-lzf-new/kernel/power/lzf/lzf_c.c
--- 852-lzf-old/kernel/power/lzf/lzf_c.c 1970-01-01 10:00:00.000000000 +1000
+++ 852-lzf-new/kernel/power/lzf/lzf_c.c 2004-11-04 16:27:41.000000000 +1100
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2000-2003 Marc Alexander Lehmann <pcg@goof.com>
+ *
+ * Redistribution and use in source and binary forms, with or without modifica-
+ * tion, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
+ * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
+ * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
+ * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * the GNU General Public License version 2 (the "GPL"), in which case the
+ * provisions of the GPL are applicable instead of the above. If you wish to
+ * allow the use of your version of this file only under the terms of the
+ * GPL and not to allow others to use your version of this file under the
+ * BSD license, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the GPL. If
+ * you do not delete the provisions above, a recipient may use your version
+ * of this file under either the BSD or the GPL.
+ */
+
+#define HSIZE (1 << (HLOG))
+
+/*
+ * don't play with this unless you benchmark!
+ * decompression is not dependent on the hash function
+ * the hashing function might seem strange, just believe me
+ * it works ;)
+ */
+#define FRST(p) (((p[0]) << 8) + p[1])
+#define NEXT(v,p) (((v) << 8) + p[2])
+#define IDX(h) ((((h ^ (h << 5)) >> (3*8 - HLOG)) + h*3) & (HSIZE - 1))
+/*
+ * IDX works because it is very similar to a multiplicative hash, e.g.
+ * (h * 57321 >> (3*8 - HLOG))
+ * the next one is also quite good, albeit slow ;)
+ * (int)(cos(h & 0xffffff) * 1e6)
+ */
+
+#if 0
+/* original lzv-like hash function */
+# define FRST(p) (p[0] << 5) ^ p[1]
+# define NEXT(v,p) ((v) << 5) ^ p[2]
+# define IDX(h) ((h) & (HSIZE - 1))
+#endif
+
+#define MAX_LIT (1 << 5)
+#define MAX_OFF (1 << 13)
+#define MAX_REF ((1 << 8) + (1 << 3))
+
+/*
+ * compressed format
+ *
+ * 000LLLLL <L+1> ; literal
+ * LLLOOOOO oooooooo ; backref L
+ * 111OOOOO LLLLLLLL oooooooo ; backref L+7
+ *
+ */
+
+unsigned int
+lzf_compress (const void *const in_data, unsigned int in_len,
+ void *out_data, unsigned int out_len, void *hbuf)
+{
+ const u8 **htab = hbuf;
+ const u8 **hslot;
+ const u8 *ip = (const u8 *)in_data;
+ u8 *op = (u8 *)out_data;
+ const u8 *in_end = ip + in_len;
+ u8 *out_end = op + out_len;
+ const u8 *ref;
+
+ unsigned int hval = FRST (ip);
+ unsigned long off;
+ int lit = 0;
+
+#if INIT_HTAB
+# if USE_MEMCPY
+ memset (htab, 0, sizeof (htab));
+# else
+ for (hslot = htab; hslot < htab + HSIZE; hslot++)
+ *hslot++ = ip;
+# endif
+#endif
+
+ for (;;)
+ {
+ if (ip < in_end - 2)
+ {
+ hval = NEXT (hval, ip);
+ hslot = htab + IDX (hval);
+ ref = *hslot; *hslot = ip;
+
+ if (1
+#if INIT_HTAB && !USE_MEMCPY
+ && ref < ip /* the next test will actually take care of this, but this is faster */
+#endif
+ && (off = ip - ref - 1) < MAX_OFF
+ && ip + 4 < in_end
+ && ref > (u8 *)in_data
+#if STRICT_ALIGN
+ && ref[0] == ip[0]
+ && ref[1] == ip[1]
+ && ref[2] == ip[2]
+#else
+ && *(u16 *)ref == *(u16 *)ip
+ && ref[2] == ip[2]
+#endif
+ )
+ {
+ /* match found at *ref++ */
+ unsigned int len = 2;
+ unsigned int maxlen = in_end - ip - len;
+ maxlen = maxlen > MAX_REF ? MAX_REF : maxlen;
+
+ do
+ len++;
+ while (len < maxlen && ref[len] == ip[len]);
+
+ if (op + lit + 1 + 3 >= out_end)
+ return 0;
+
+ if (lit)
+ {
+ *op++ = lit - 1;
+ lit = -lit;
+ do
+ *op++ = ip[lit];
+ while (++lit);
+ }
+
+ len -= 2;
+ ip++;
+
+ if (len < 7)
+ {
+ *op++ = (off >> 8) + (len << 5);
+ }
+ else
+ {
+ *op++ = (off >> 8) + ( 7 << 5);
+ *op++ = len - 7;
+ }
+
+ *op++ = off;
+
+#if ULTRA_FAST
+ ip += len;
+ hval = FRST (ip);
+ hval = NEXT (hval, ip);
+ htab[IDX (hval)] = ip;
+ ip++;
+#else
+ do
+ {
+ hval = NEXT (hval, ip);
+ htab[IDX (hval)] = ip;
+ ip++;
+ }
+ while (len--);
+#endif
+ continue;
+ }
+ }
+ else if (ip == in_end)
+ break;
+
+ /* one more literal byte we must copy */
+ lit++;
+ ip++;
+
+ if (lit == MAX_LIT)
+ {
+ if (op + 1 + MAX_LIT >= out_end)
+ return 0;
+
+ *op++ = MAX_LIT - 1;
+#if USE_MEMCPY
+ memcpy (op, ip - MAX_LIT, MAX_LIT);
+ op += MAX_LIT;
+ lit = 0;
+#else
+ lit = -lit;
+ do
+ *op++ = ip[lit];
+ while (++lit);
+#endif
+ }
+ }
+
+ if (lit)
+ {
+ if (op + lit + 1 >= out_end)
+ return 0;
+
+ *op++ = lit - 1;
+ lit = -lit;
+ do
+ *op++ = ip[lit];
+ while (++lit);
+ }
+
+ return op - (u8 *) out_data;
+}
diff -ruN 852-lzf-old/kernel/power/lzf/lzf_d.c 852-lzf-new/kernel/power/lzf/lzf_d.c
--- 852-lzf-old/kernel/power/lzf/lzf_d.c 1970-01-01 10:00:00.000000000 +1000
+++ 852-lzf-new/kernel/power/lzf/lzf_d.c 2004-11-04 16:27:41.000000000 +1100
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2000-2002 Marc Alexander Lehmann <pcg@goof.com>
+ *
+ * Redistribution and use in source and binary forms, with or without modifica-
+ * tion, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
+ * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
+ * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
+ * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * the GNU General Public License version 2 (the "GPL"), in which case the
+ * provisions of the GPL are applicable instead of the above. If you wish to
+ * allow the use of your version of this file only under the terms of the
+ * GPL and not to allow others to use your version of this file under the
+ * BSD license, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the GPL. If
+ * you do not delete the provisions above, a recipient may use your version
+ * of this file under either the BSD or the GPL.
+ */
+
+unsigned int
+lzf_decompress (const void *const in_data, unsigned int in_len,
+ void *out_data, unsigned int out_len)
+{
+ u8 const *ip = in_data;
+ u8 *op = out_data;
+ u8 const *const in_end = ip + in_len;
+ u8 *const out_end = op + out_len;
+
+ do
+ {
+ unsigned int ctrl = *ip++;
+
+ if (ctrl < (1 << 5)) /* literal run */
+ {
+ ctrl++;
+
+ if (op + ctrl > out_end)
+ return 0;
+
+#if USE_MEMCPY
+ memcpy (op, ip, ctrl);
+ op += ctrl;
+ ip += ctrl;
+#else
+ do
+ *op++ = *ip++;
+ while (--ctrl);
+#endif
+ }
+ else /* back reference */
+ {
+ unsigned int len = ctrl >> 5;
+
+ u8 *ref = op - ((ctrl & 0x1f) << 8) - 1;
+
+ if (len == 7)
+ len += *ip++;
+
+ ref -= *ip++;
+
+ if (op + len + 2 > out_end)
+ return 0;
+
+ if (ref < (u8 *)out_data)
+ return 0;
+
+ *op++ = *ref++;
+ *op++ = *ref++;
+
+ do
+ *op++ = *ref++;
+ while (--len);
+ }
+ }
+ while (op < out_end && ip < in_end);
+
+ return op - (u8 *)out_data;
+}
+
diff -ruN 852-lzf-old/kernel/power/suspend_lzf.c 852-lzf-new/kernel/power/suspend_lzf.c
--- 852-lzf-old/kernel/power/suspend_lzf.c 1970-01-01 10:00:00.000000000 +1000
+++ 852-lzf-new/kernel/power/suspend_lzf.c 2004-11-11 08:46:15.000000000 +1100
@@ -0,0 +1,554 @@
+/*
+ * kernel/power/lzf_compress.c
+ *
+ * Copyright (C) 2003 Marc Lehmann <pcg@goof.com>
+ * Copyright (C) 2003,2004 Nigel Cunningham <ncunningham@linuxmail.org>
+ *
+ * This file is released under the GPLv2.
+ *
+ * This file contains data compression routines for suspend,
+ * using LZH compression.
+ *
+ */
+
+#include <linux/suspend.h>
+#include <linux/module.h>
+#include <linux/highmem.h>
+#include <linux/vmalloc.h>
+
+#include "plugins.h"
+#include "proc.h"
+#include "suspend.h"
+
+static int expected_lzf_compression = 0;
+
+/*
+ * size of hashtable is (1 << HLOG) * sizeof (char *)
+ * decompression is independent of the hash table size
+ * the difference between 15 and 14 is very small
+ * for small blocks (and 14 is also faster).
+ * For a low-memory configuration, use HLOG == 13;
+ * For best compression, use 15 or 16.
+ */
+#ifndef HLOG
+# define HLOG 14
+#endif
+
+/*
+ * sacrifice some compression quality in favour of compression speed.
+ * (roughly 1-2% worse compression for large blocks and
+ * 9-10% for small, redundant, blocks and >>20% better speed in both cases)
+ * In short: enable this for binary data, disable this for text data.
+ */
+#ifndef ULTRA_FAST
+# define ULTRA_FAST 1
+#endif
+
+#define STRICT_ALIGN 0
+#define USE_MEMCPY 1
+#define INIT_HTAB 0
+
+#include "lzf/lzf_c.c"
+#include "lzf/lzf_d.c"
+
+static struct suspend_plugin_ops lzf_compression_ops;
+static struct suspend_plugin_ops * next_driver;
+
+static void *compression_workspace = NULL;
+static u8 *local_buffer = NULL;
+static struct page * local_buffer_page = NULL;
+static u8 *page_buffer = NULL;
+static struct page * page_buffer_page = NULL;
+static unsigned int bufofs;
+
+static __nosavedata unsigned long bytes_in = 0, bytes_out = 0;
+
+/* allocate_compression_space
+ *
+ * Description: Allocate space for use in [de]compressing our data.
+ * Each call must have a matching call to free_memory.
+ * Returns: Int: Zero if successful, -ENONEM otherwise.
+ */
+
+static inline int allocate_compression_space(void)
+{
+ BUG_ON(compression_workspace);
+
+ compression_workspace = vmalloc_32((1<<HLOG)*sizeof(char *));
+ if (!compression_workspace) {
+ printk(KERN_WARNING
+ "Failed to allocate %d bytes for lzf workspace\n",
+ (1<<HLOG)*sizeof(char *));
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+/* free_zlib_memory
+ *
+ * Description: Frees memory allocated by the allocation routine (above).
+ */
+
+static inline void free_memory(void)
+{
+ if (!compression_workspace)
+ return;
+
+ vfree(compression_workspace);
+ compression_workspace = NULL;
+}
+
+/* ---- Local buffer management ---- */
+
+/* allocate_local_buffer
+ *
+ * Description: Allocates a page of memory for buffering output.
+ * Returns: Int: Zero if successful, -ENONEM otherwise.
+ */
+
+static int allocate_local_buffer(void)
+{
+ if (!local_buffer) {
+ local_buffer = (char *) get_zeroed_page(GFP_ATOMIC);
+
+ if (!local_buffer) {
+ printk(KERN_ERR
+ "Failed to allocate the local buffer for "
+ "lzf compression driver.\n");
+ return -ENOMEM;
+ }
+ local_buffer_page = virt_to_page(local_buffer);
+ }
+
+ if (!page_buffer) {
+ page_buffer = (char *) get_zeroed_page(GFP_ATOMIC);
+
+ if (!page_buffer) {
+ printk(KERN_ERR
+ "Failed to allocate the page buffer for "
+ "lzf compression driver.\n");
+ return -ENOMEM;
+ }
+ page_buffer_page = virt_to_page(page_buffer);
+ }
+
+ return 0;
+}
+
+/* free_local_buffer
+ *
+ * Description: Frees memory allocated for buffering output.
+ */
+
+static inline void free_local_buffer(void)
+{
+ if (local_buffer)
+ free_pages((unsigned long) local_buffer, 0);
+
+ local_buffer = NULL;
+ local_buffer_page = NULL;
+
+ if (page_buffer)
+ free_pages((unsigned long) page_buffer, 0);
+
+ page_buffer = NULL;
+ page_buffer_page = NULL;
+}
+
+/* ---- Exported functions ---- */
+
+/* write_init()
+ *
+ * Description: Allocate buffers and prepare to compress data.
+ * Arguments: Stream_number: Ignored.
+ * Returns: Zero on success, -ENOMEM if unable to vmalloc.
+ */
+
+static int lzf_write_init(int stream_number)
+{
+ int result;
+
+ next_driver = get_next_filter(&lzf_compression_ops);
+
+ if (!next_driver) {
+ printk("LZF Compression Driver: Argh! No one wants my output!");
+ return -ECHILD;
+ }
+
+ if ((result = allocate_compression_space()))
+ return result;
+
+ if ((result = allocate_local_buffer()))
+ return result;
+
+ /* Only reset the stats if starting to write an image */
+ if (stream_number == 2)
+ bytes_in = bytes_out = 0;
+
+ bufofs = 0;
+
+ return 0;
+}
+
+/* lzf_write()
+ *
+ * Description: Helper function for write_chunk. Write the compressed data.
+ * Arguments: u8*: Output buffer to be written.
+ * unsigned int: Length of buffer.
+ * Return: int: Result to be passed back to caller.
+ */
+
+static int lzf_write (u8 *buffer, unsigned int len)
+{
+ int ret;
+
+ bytes_out += len;
+
+ while (len + bufofs > PAGE_SIZE) {
+ unsigned int chunk = PAGE_SIZE - bufofs;
+ memcpy (local_buffer + bufofs, buffer, chunk);
+ buffer += chunk;
+ len -= chunk;
+ bufofs = 0;
+ if ((ret = next_driver->ops.filter.write_chunk(local_buffer_page)) < 0)
+ return ret;
+ }
+ memcpy (local_buffer + bufofs, buffer, len);
+ bufofs += len;
+ return 0;
+}
+
+/* lzf_write_chunk()
+ *
+ * Description: Compress a page of data, buffering output and passing on
+ * filled pages to the next plugin in the pipeline.
+ * Arguments: 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
+ * plugins, -ECHILD if we have a broken pipeline or -EPERM if
+ * zlib errs.
+ */
+
+static int lzf_write_chunk(struct page * buffer_page)
+{
+ int ret;
+ u16 len;
+ char * buffer_start = kmap(buffer_page);
+
+ bytes_in += PAGE_SIZE;
+
+ len = lzf_compress(buffer_start, PAGE_SIZE, page_buffer,
+ PAGE_SIZE - 3, compression_workspace);
+
+ if ((ret = lzf_write((u8 *)&len, 2)) >= 0) {
+ if (len) // some compression
+ ret = lzf_write(page_buffer, len);
+ else
+ ret = lzf_write(buffer_start, PAGE_SIZE);
+ }
+ kunmap(buffer_page);
+ return ret;
+}
+
+/* write_cleanup()
+ *
+ * Description: Write unflushed data and free workspace.
+ * Returns: Result of writing last page.
+ */
+
+static int lzf_write_cleanup(void)
+{
+ int ret;
+
+ ret = next_driver->ops.filter.write_chunk(local_buffer_page);
+
+ free_memory();
+ free_local_buffer();
+
+ return ret;
+}
+
+/* read_init()
+ *
+ * Description: Prepare to read a new stream of data.
+ * Arguments: int: Section of image about to be read.
+ * Returns: int: Zero on success, error number otherwise.
+ */
+
+static int lzf_read_init(int stream_number)
+{
+ int result;
+
+ next_driver = get_next_filter(&lzf_compression_ops);
+
+ if (!next_driver) {
+ printk("LZF Compression Driver: Argh! No one wants "
+ "to feed me data!");
+ return -ECHILD;
+ }
+
+ if ((result = allocate_local_buffer()))
+ return result;
+
+ bufofs = PAGE_SIZE;
+
+ return 0;
+}
+
+/* lzf_read()
+ *
+ * Description: Read data into compression buffer.
+ * Arguments: u8 *: Address of the buffer.
+ * unsigned int: Length
+ * Returns: int: Result of reading the image chunk.
+ */
+
+static int lzf_read (u8 * buffer, unsigned int len)
+{
+ int ret;
+
+ while (len + bufofs > PAGE_SIZE) {
+ unsigned int chunk = PAGE_SIZE - bufofs;
+ memcpy(buffer, local_buffer + bufofs, chunk);
+ buffer += chunk;
+ len -= chunk;
+ bufofs = 0;
+ if ((ret = next_driver->ops.filter.read_chunk(
+ local_buffer_page, SUSPEND_SYNC)) < 0) {
+ return ret;
+ }
+ }
+ memcpy (buffer, local_buffer + bufofs, len);
+ bufofs += len;
+ return 0;
+}
+
+/* lzf_read_chunk()
+ *
+ * Description: Retrieve data from later plugins and decompress it until the
+ * input buffer is filled.
+ * Arguments: Buffer_start: Pointer to a buffer of size PAGE_SIZE.
+ * Sync: Whether the previous plugin (or core) wants its
+ * data synchronously.
+ * Returns: Zero if successful. Error condition from me or from downstream
+ * on failure.
+ */
+
+static int lzf_read_chunk(struct page * buffer_page, int sync)
+{
+ int ret;
+ u16 len;
+ char * buffer_start = kmap(buffer_page);
+
+ /*
+ * All our reads must be synchronous - we can't decompress
+ * data that hasn't been read yet.
+ */
+
+ if ((ret = lzf_read ((u8 *)&len, 2)) >= 0) {
+ if (len == 0) { // uncompressed
+ ret = lzf_read(buffer_start, PAGE_SIZE);
+ } else { // compressed
+ if ((ret = lzf_read(page_buffer, len)) >= 0) {
+ ret = lzf_decompress(page_buffer, len, buffer_start, PAGE_SIZE);
+ if (ret != PAGE_SIZE)
+ ret = -EPERM; // why EPERM??
+ else
+ ret = 0;
+ }
+ }
+ }
+ kunmap(buffer_page);
+ return ret;
+}
+
+/* read_cleanup()
+ *
+ * Description: Clean up after reading part or all of a stream of data.
+ * Returns: int: Always zero. Never fails.
+ */
+
+static int lzf_read_cleanup(void)
+{
+ free_local_buffer();
+ return 0;
+}
+
+/* lzf_print_debug_stats
+ *
+ * Description: Print information to be recorded for debugging purposes into a
+ * buffer.
+ * Arguments: buffer: Pointer to a buffer into which the debug info will be
+ * printed.
+ * size: Size of the buffer.
+ * Returns: Number of characters written to the buffer.
+ */
+
+static int lzf_print_debug_stats(char * buffer, int size)
+{
+ int pages_in = bytes_in >> PAGE_SHIFT,
+ pages_out = bytes_out >> PAGE_SHIFT;
+ int len;
+
+ /* Output the compression ratio achieved. */
+ len = suspend_snprintf(buffer, size, "- LZF Compressor enabled.\n");
+ if (pages_in)
+ len+= suspend_snprintf(buffer+len, size - len,
+ " Compressed %ld bytes into %ld (%d percent compression).\n",
+ bytes_in, bytes_out, (pages_in - pages_out) * 100 / pages_in);
+ return len;
+}
+
+/* compression_memory_needed
+ *
+ * Description: Tell the caller how much memory we need to operate during
+ * suspend/resume.
+ * Returns: Unsigned long. Maximum number of bytes of memory required for
+ * operation.
+ */
+
+static unsigned long lzf_memory_needed(void)
+{
+ return PAGE_SIZE * 2 + (1<<HLOG)*sizeof(char *);
+}
+
+static unsigned long lzf_storage_needed(void)
+{
+ return 2 * sizeof(unsigned long);
+}
+
+/* lzf_save_config_info
+ *
+ * Description: Save informaton needed when reloading the image at resume time.
+ * Arguments: Buffer: Pointer to a buffer of size PAGE_SIZE.
+ * Returns: Number of bytes used for saving our data.
+ */
+
+static int lzf_save_config_info(char * buffer)
+{
+ *((unsigned long *) buffer) = bytes_in;
+ *((unsigned long *) (buffer + sizeof(unsigned long))) = bytes_out;
+ *((int *) (buffer + 2 * sizeof(unsigned long))) = expected_lzf_compression;
+ return 2 * sizeof(unsigned long) + sizeof(int);
+}
+
+/* lzf_load_config_info
+ *
+ * Description: Reload information needed for decompressing the image at
+ * resume time.
+ * Arguments: Buffer: Pointer to the start of the data.
+ * Size: Number of bytes that were saved.
+ */
+
+static void lzf_load_config_info(char * buffer, int size)
+{
+ if(size == 2 * sizeof(unsigned long) + sizeof(int)) {
+ bytes_in = *((unsigned long *) buffer);
+ bytes_out = *((unsigned long *) (buffer + sizeof(unsigned long)));
+ expected_lzf_compression = *((int *) (buffer + 2 * sizeof(unsigned long)));
+ } else
+ printk("Suspend LZF config info size mismatch: settings ignored.\n");
+ return;
+}
+
+/* lzf_get_expected_compression
+ *
+ * Description: Returns the expected ratio between data passed into this plugin
+ * and the amount of data output when writing.
+ * Returns: 100 if the plugin is disabled. Otherwise the value set by the
+ * user via our proc entry.
+ */
+
+static int lzf_get_expected_compression(void)
+{
+ return 100 - expected_lzf_compression;
+}
+
+/*
+ * data for our proc entries.
+ */
+
+static struct suspend_proc_data expected_compression_proc_data = {
+ .filename = "expected_lzf_compression",
+ .permissions = PROC_RW,
+ .type = SUSPEND_PROC_DATA_INTEGER,
+ .data = {
+ .integer = {
+ .variable = &expected_lzf_compression,
+ .minimum = 0,
+ .maximum = 99,
+ }
+ }
+};
+
+static struct suspend_proc_data disable_compression_proc_data = {
+ .filename = "disable_lzf_compression",
+ .permissions = PROC_RW,
+ .type = SUSPEND_PROC_DATA_INTEGER,
+ .data = {
+ .integer = {
+ .variable = &lzf_compression_ops.disabled,
+ .minimum = 0,
+ .maximum = 1,
+ }
+ }
+};
+
+/*
+ * Ops structure.
+ */
+
+static struct suspend_plugin_ops lzf_compression_ops = {
+ .type = FILTER_PLUGIN,
+ .name = "LZF Page Compressor",
+ .memory_needed = lzf_memory_needed,
+ .print_debug_info = lzf_print_debug_stats,
+ .save_config_info = lzf_save_config_info,
+ .load_config_info = lzf_load_config_info,
+ .storage_needed = lzf_storage_needed,
+ .ops = {
+ .filter = {
+ .write_init = lzf_write_init,
+ .write_chunk = lzf_write_chunk,
+ .write_cleanup = lzf_write_cleanup,
+ .read_init = lzf_read_init,
+ .read_chunk = lzf_read_chunk,
+ .read_cleanup = lzf_read_cleanup,
+ .expected_compression = lzf_get_expected_compression,
+ }
+ }
+};
+
+/* ---- Registration ---- */
+
+static __init int lzf_load(void)
+{
+ int result;
+
+ if (!(result = suspend_register_plugin(&lzf_compression_ops))) {
+ printk("Software Suspend LZF Compression Driver registered.\n");
+ suspend_register_procfile(&expected_compression_proc_data);
+ suspend_register_procfile(&disable_compression_proc_data);
+ }
+ return result;
+}
+
+#ifdef MODULE
+static __exit void lzf_unload(void)
+{
+ printk("Software Suspend LZF Compression Driver unloading.\n");
+ suspend_unregister_procfile(&expected_compression_proc_data);
+ suspend_unregister_procfile(&disable_compression_proc_data);
+ suspend_unregister_plugin(&lzf_compression_ops);
+}
+
+
+module_init(lzf_load);
+module_exit(lzf_unload);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Marc Lehmann");
+MODULE_DESCRIPTION("LZF Compression support for Suspend2");
+#else
+late_initcall(lzf_load);
+#endif
next prev parent reply other threads:[~2004-11-24 18:36 UTC|newest]
Thread overview: 244+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-11-24 12:56 Suspend 2 merge Nigel Cunningham
2004-11-24 12:56 ` Suspend2 merge: 1/51: Device trees Nigel Cunningham
2004-11-24 12:56 ` Suspend2 merge: 2/51: Find class by name Nigel Cunningham
2004-11-24 12:57 ` Suspend 2 merge: 3/51: e820 table support Nigel Cunningham
2004-11-25 16:53 ` Pavel Machek
2004-11-24 12:57 ` Suspend 2 merge: 4/51: Get module list Nigel Cunningham
2004-11-25 16:56 ` Pavel Machek
2004-11-25 21:25 ` Nigel Cunningham
2004-11-25 21:32 ` Pavel Machek
2004-11-24 12:57 ` Suspend 2 merge: 5/51: Workthread freezer support Nigel Cunningham
2004-11-25 16:57 ` Pavel Machek
2004-11-24 12:57 ` Suspend 2 merge: 7/51: Reboot handler hook Nigel Cunningham
2004-11-24 13:07 ` Christoph Hellwig
2004-11-24 20:19 ` Nigel Cunningham
2004-11-25 2:37 ` Nigel Cunningham
2004-11-24 12:57 ` Suspend 2 merge: 8/51: /proc/acpi/sleep hook Nigel Cunningham
2004-11-24 13:13 ` Christoph Hellwig
2004-11-24 12:57 ` Suspend 2 merge: 9/51: init/* changes Nigel Cunningham
2004-11-25 17:07 ` Pavel Machek
2004-11-25 21:36 ` Nigel Cunningham
2004-11-25 21:45 ` Pavel Machek
2004-11-25 21:51 ` Nigel Cunningham
2004-11-25 21:58 ` Pavel Machek
2004-11-25 22:03 ` Nigel Cunningham
2004-11-25 22:30 ` Pavel Machek
2004-11-27 2:14 ` Matthew Garrett
2004-11-27 7:22 ` Pavel Machek
2004-11-27 9:31 ` Herbert Xu
2004-11-27 13:21 ` Matthew Garrett
2004-11-27 16:20 ` Pavel Machek
2004-11-28 22:43 ` Nigel Cunningham
2004-11-24 12:57 ` Suspend 2 merge: 10/51: Exports for suspend built as modules Nigel Cunningham
2004-11-24 13:12 ` Christoph Hellwig
2004-11-24 21:52 ` Nigel Cunningham
2004-11-24 14:44 ` Ingo Molnar
2004-11-24 20:46 ` Nigel Cunningham
2004-11-25 18:07 ` Pavel Machek
2004-11-25 21:40 ` Nigel Cunningham
2004-11-25 21:50 ` Pavel Machek
2004-11-24 12:57 ` Suspend 2 merge: 11/51: Export vt functions Nigel Cunningham
2004-11-24 12:57 ` Suspend 2 merge:L 12/51: Disable OOM killer when suspending Nigel Cunningham
2004-11-25 18:12 ` Pavel Machek
2004-11-25 21:47 ` Nigel Cunningham
2004-11-25 21:54 ` Pavel Machek
2004-11-24 12:57 ` Suspend 2 merge: 13/51: Disable highmem tlb flush for copyback Nigel Cunningham
2004-11-25 18:13 ` Pavel Machek
2004-11-24 12:57 ` Suspend 2 merge: 14/51: Disable page alloc failure message when suspending Nigel Cunningham
2004-11-24 14:15 ` Christoph Hellwig
2004-11-24 20:46 ` Nigel Cunningham
2004-11-24 16:00 ` Dave Hansen
2004-11-24 21:06 ` Nigel Cunningham
2004-11-24 22:25 ` Dave Hansen
2004-11-25 18:15 ` Pavel Machek
2004-11-25 21:49 ` Nigel Cunningham
2004-11-25 21:56 ` Pavel Machek
2004-11-25 22:46 ` Nigel Cunningham
2004-11-25 23:22 ` Pavel Machek
2004-11-24 12:58 ` Suspend 2 merge: 15/51: Disable pdflush during suspend Nigel Cunningham
2004-11-24 12:58 ` Suspend 2 merge: 16/51: Disable cache reaping " Nigel Cunningham
2004-11-25 18:18 ` Pavel Machek
2004-11-25 22:00 ` Nigel Cunningham
2004-11-24 12:58 ` Suspend 2 merge: 17/51: Disable MCE checking " Nigel Cunningham
2004-11-25 18:19 ` Pavel Machek
2004-11-25 22:05 ` Nigel Cunningham
2004-11-25 22:31 ` Pavel Machek
2004-11-25 22:38 ` Nigel Cunningham
2004-11-25 22:45 ` Pavel Machek
2004-11-24 12:58 ` Suspend 2 merge: 18/51: Debug page_alloc support Nigel Cunningham
2004-11-24 16:02 ` Dave Hansen
2004-11-24 20:17 ` Nigel Cunningham
2004-11-24 22:26 ` Dave Hansen
2004-11-25 18:21 ` Pavel Machek
2004-11-25 22:06 ` Nigel Cunningham
2004-11-24 12:58 ` Suspend 2 merge: 19/51: Remove MTRR sysdev support Nigel Cunningham
2004-11-24 16:27 ` Zwane Mwaikambo
2004-11-24 20:17 ` Nigel Cunningham
2004-11-25 18:22 ` Pavel Machek
2004-11-28 22:34 ` Nigel Cunningham
2004-11-24 12:58 ` Suspend 2 merge: 20/51: Timer freezer (experimental) Nigel Cunningham
2004-11-24 12:58 ` Suspend 2 merge: 21/51: Refrigerator upgrade Nigel Cunningham
2004-11-25 18:33 ` Pavel Machek
2004-11-25 22:10 ` Nigel Cunningham
2004-11-25 22:36 ` Pavel Machek
2004-11-25 22:49 ` Nigel Cunningham
2004-11-25 23:25 ` Pavel Machek
2004-11-25 23:49 ` Nigel Cunningham
2004-11-26 0:05 ` Pavel Machek
2004-11-26 0:12 ` Nigel Cunningham
2004-11-26 0:18 ` Pavel Machek
2004-11-27 17:18 ` Pavel Machek
2004-11-26 21:00 ` Christoph Hellwig
2004-11-24 12:58 ` Suspend 2 merge: 22/51: Suspend2 lowlevel code Nigel Cunningham
2004-11-24 16:42 ` Zwane Mwaikambo
2004-11-24 21:20 ` Nigel Cunningham
2004-11-24 21:55 ` Zwane Mwaikambo
2004-11-24 21:56 ` Nigel Cunningham
2004-11-25 18:39 ` Pavel Machek
2004-11-25 22:15 ` Nigel Cunningham
2004-11-25 22:38 ` Pavel Machek
2004-11-24 12:58 ` Suspend 2 merge: 23/51: PPC support Nigel Cunningham
2004-11-25 18:40 ` Pavel Machek
2004-11-25 22:15 ` Nigel Cunningham
2004-11-24 12:59 ` Suspend 2 merge: 24/51: Keyboard and serial console hooks Nigel Cunningham
2004-11-24 13:29 ` Christoph Hellwig
2004-11-24 18:47 ` Yaroslav Rastrigin
2004-11-24 21:38 ` Nigel Cunningham
2004-11-24 21:57 ` Jan Rychter
2004-11-24 23:02 ` Christoph Hellwig
2004-11-25 1:22 ` Jan Rychter
2004-11-25 10:08 ` Christoph Hellwig
2004-11-26 20:21 ` pb
2004-11-25 19:28 ` Pavel Machek
2004-11-28 22:34 ` Nigel Cunningham
2004-11-28 23:39 ` Pavel Machek
2004-11-29 22:15 ` Nigel Cunningham
2004-11-24 12:59 ` Suspend 2 merge: 25/51: Documentation Nigel Cunningham
2004-11-24 12:59 ` Suspend 2 merge: 26/51: Kconfig and makefile Nigel Cunningham
2004-11-24 16:34 ` Roman Zippel
2004-11-24 21:11 ` Nigel Cunningham
2004-11-24 21:46 ` Roman Zippel
2004-11-24 21:53 ` Nigel Cunningham
2004-11-25 2:37 ` Nigel Cunningham
2004-11-24 12:59 ` Suspend 2 merge: 27/51: Block I/O module Nigel Cunningham
2004-11-24 12:59 ` Suspend 2 merge: 28/51: Suspend memory pool hooks Nigel Cunningham
2004-11-25 19:34 ` Pavel Machek
2004-11-24 12:59 ` Suspend 2 merge: 29/51: Clear swapfile bdev in swapoff Nigel Cunningham
2004-11-24 12:59 ` Suspend 2 merge: 30/51: Enable slab alloc fallback to suspend memory pool Nigel Cunningham
2004-11-25 19:36 ` Pavel Machek
2004-11-24 12:59 ` Suspend 2 merge: 31/51: Export tlb flushing Nigel Cunningham
2004-11-24 15:32 ` Martin J. Bligh
2004-11-24 21:04 ` Nigel Cunningham
2004-11-24 12:59 ` Suspend 2 merge: 32/51: Make show task non-static Nigel Cunningham
2004-11-24 12:59 ` Suspend 2 merge: 33/51: More documentation Nigel Cunningham
2004-11-24 13:00 ` Suspend 2 merge: 34/51: Includes Nigel Cunningham
2004-11-24 13:25 ` Christoph Hellwig
2004-11-24 20:17 ` Nigel Cunningham
2004-11-24 23:19 ` Matthew Garrett
2004-11-25 2:43 ` Nigel Cunningham
2004-11-24 13:00 ` Suspend 2 merge: 35/51: Code always built in to the kernel Nigel Cunningham
2004-11-25 23:32 ` Pavel Machek
2004-11-25 23:57 ` Nigel Cunningham
2004-11-26 0:08 ` Pavel Machek
2004-11-26 0:17 ` Nigel Cunningham
2004-11-26 0:23 ` Pavel Machek
2004-11-27 2:19 ` Matthew Garrett
2004-11-28 22:39 ` Nigel Cunningham
2004-11-27 9:00 ` Jan Rychter
2004-11-27 17:22 ` Pavel Machek
2004-11-24 13:00 ` Suspend 2 merge: 36/51: Highlevel I/O routines Nigel Cunningham
2004-11-25 23:36 ` Pavel Machek
2004-11-27 1:39 ` Tomas Carnecky
2004-11-24 13:00 ` Suspend 2 merge: 37/51: Memory pool support Nigel Cunningham
2004-11-25 23:37 ` Pavel Machek
2004-11-24 13:00 ` Suspend 2 merge: 38/51: Page directory support Nigel Cunningham
2004-11-24 13:01 ` Suspend 2 merge: 39/51: Plugins support Nigel Cunningham
2004-11-24 13:01 ` Suspend 2 merge: 40/51: Prepare image Nigel Cunningham
2004-11-24 13:01 ` Suspend 2 merge: 41/51: Ranges (extents) Nigel Cunningham
2004-11-24 13:01 ` Suspend 2 merge: 42/51: Suspend.c Nigel Cunningham
2004-11-24 16:52 ` Zwane Mwaikambo
2004-11-24 21:23 ` Nigel Cunningham
2004-11-25 23:43 ` Pavel Machek
2004-11-24 13:01 ` Suspend 2 merge: 43/51: Utility functions Nigel Cunningham
2004-11-25 23:46 ` Pavel Machek
2004-11-26 0:04 ` Nigel Cunningham
2004-11-26 0:04 ` Nigel Cunningham
2004-11-27 16:11 ` Dave Hansen
2004-11-27 16:11 ` Dave Hansen
2004-11-28 21:36 ` Nigel Cunningham
2004-11-28 21:36 ` Nigel Cunningham
2004-11-24 13:01 ` Suspend 2 merge: 44/51: Text UI plugin Nigel Cunningham
2004-11-24 13:02 ` Suspend 2 merge: 45/51: Bootsplash support Nigel Cunningham
2004-11-24 13:02 ` Nigel Cunningham [this message]
2004-11-24 23:01 ` Suspend 2 merge: 46/51: LZF support Bartlomiej Zolnierkiewicz
2004-11-25 2:38 ` Nigel Cunningham
2004-11-25 6:32 ` hugang
2004-11-25 6:52 ` Dmitry Torokhov
2004-11-25 7:07 ` hugang
2004-11-25 10:10 ` Christoph Hellwig
2004-11-24 13:02 ` Suspend 2 merge: 47/51: GZIP support Nigel Cunningham
2004-11-25 23:50 ` Pavel Machek
2004-11-24 13:02 ` Suspend 2 merge: 48/51: Swapwriter Nigel Cunningham
2004-11-25 23:55 ` Pavel Machek
2004-11-26 0:05 ` Nigel Cunningham
2004-11-24 13:02 ` Suspend 2 merge: 49/51: Checksumming Nigel Cunningham
2004-11-25 23:56 ` Pavel Machek
2004-11-26 0:00 ` Nigel Cunningham
2004-11-26 0:14 ` Pavel Machek
2004-11-29 9:55 ` Rob Landley
2004-11-30 0:24 ` Nigel Cunningham
2004-11-29 23:30 ` Rob Landley
2004-11-30 0:49 ` Nigel Cunningham
2004-11-30 13:07 ` Pavel Machek
2004-11-30 21:45 ` Nigel Cunningham
2004-11-30 13:02 ` Pavel Machek
2004-11-30 13:38 ` Matthew Garrett
2004-11-30 22:38 ` Pavel Machek
2004-12-02 21:31 ` Rob Landley
2004-11-24 13:02 ` Suspend 2 merge: 50/51: Device mapper support Nigel Cunningham
2004-11-25 23:58 ` Pavel Machek
2004-11-26 0:07 ` Nigel Cunningham
2004-12-02 20:40 ` Alasdair G Kergon
2004-12-02 21:04 ` Nigel Cunningham
2004-12-02 21:49 ` Alasdair G Kergon
2004-12-02 22:08 ` Nigel Cunningham
2004-12-03 17:47 ` Alasdair G Kergon
2004-12-03 19:57 ` Nigel Cunningham
2004-12-03 20:12 ` Alasdair G Kergon
2004-12-14 0:47 ` Nigel Cunningham
2004-11-24 13:03 ` Suspend 2 merge: 51/51: Notes Nigel Cunningham
2004-11-26 0:01 ` Pavel Machek
2004-11-26 0:09 ` Nigel Cunningham
2004-11-26 0:24 ` Pavel Machek
2004-11-24 13:03 ` Suspend 2 merge: 6/51 Nigel Cunningham
2004-11-24 13:28 ` Suspend 2 merge Christoph Hellwig
2004-11-24 20:46 ` Nigel Cunningham
2004-11-25 19:20 ` Pavel Machek
2004-11-25 22:34 ` Nigel Cunningham
2004-11-25 23:22 ` Pavel Machek
2004-11-25 23:46 ` Nigel Cunningham
2004-11-26 0:39 ` Pavel Machek
2004-11-26 9:08 ` Nigel Cunningham
2004-11-26 12:38 ` Pavel Machek
2004-11-26 15:54 ` Christoph Hellwig
2004-11-26 22:36 ` Pavel Machek
2004-11-28 22:35 ` Nigel Cunningham
2004-11-28 23:55 ` Pavel Machek
2004-11-29 3:20 ` Nigel Cunningham
2004-11-29 13:03 ` Pavel Machek
2004-11-30 0:24 ` Nigel Cunningham
2004-11-30 10:19 ` Pavel Machek
[not found] ` <20041126043203.GA2713@hugang.soulinfo.com>
2004-11-26 9:08 ` Nigel Cunningham
2004-11-26 13:37 ` Pavel Machek
2004-11-26 13:31 ` Pavel Machek
[not found] ` <20041126082109.GA842@hugang.soulinfo.com>
2004-11-26 13:25 ` Pavel Machek
2004-11-28 21:40 ` Nigel Cunningham
2004-11-29 9:34 ` Stefan Seyfried
2004-11-29 22:20 ` Nigel Cunningham
2004-11-29 22:34 ` Pavel Machek
2004-11-30 12:16 ` Stefan Seyfried
2004-11-30 21:16 ` Nigel Cunningham
2004-11-30 22:20 ` Pavel Machek
2004-12-01 9:27 ` Nigel Cunningham
2004-12-01 10:08 ` Pavel Machek
2004-12-01 20:39 ` 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=1101300108.5805.380.camel@desktop.cunninghams \
--to=ncunningham@linuxmail.org \
--cc=linux-kernel@vger.kernel.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.