[Suspend2][ 06/13] [Suspend2] Compression read routines.

From: Nigel Cunningham
Date: Tue Jun 27 2006 - 00:36:22 EST


Routines used to obtain data from the next module, decompress it and return
a page full to the caller.

Signed-off-by: Nigel Cunningham <nigel@xxxxxxxxxxxx>

kernel/power/compression.c | 100 ++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 100 insertions(+), 0 deletions(-)

diff --git a/kernel/power/compression.c b/kernel/power/compression.c
index db3bca3..5193423 100644
--- a/kernel/power/compression.c
+++ b/kernel/power/compression.c
@@ -275,3 +275,103 @@ failure:
return ret;
}

+/*
+ * suspend_compress_read()
+ * @buffer: u8 *. Address of the buffer.
+ * @len: unsigned int. Length.
+ *
+ * Description: Read data into compression buffer.
+ * Returns: int: Result of reading the image chunk.
+ */
+static int suspend_compress_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->read_chunk(
+ virt_to_page(local_buffer), SUSPEND_SYNC)) < 0) {
+ return ret;
+ }
+ }
+ memcpy (buffer, local_buffer + bufofs, len);
+ bufofs += len;
+ return 0;
+}
+
+/*
+ * suspend_compress_read_chunk()
+ * @buffer_page: struct page *. Pointer to a buffer of size PAGE_SIZE.
+ * @sync: int. Whether the previous module (or core) wants its data synchronously.
+ *
+ * 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 suspend_compress_read_chunk(struct page *buffer_page, int sync)
+{
+ int ret, position_saved;
+ unsigned int len;
+ u16 len_written;
+ char *buffer_start;
+
+ if (!suspend_compressor_transform)
+ return next_driver->read_chunk(buffer_page, SUSPEND_ASYNC);
+
+ /*
+ * All our reads must be synchronous - we can't decompress
+ * data that hasn't been read yet.
+ */
+
+ buffer_start = kmap(buffer_page);
+
+ if ((ret = suspend_compress_read ((u8 *)&len_written, 2)) >= 0) {
+ len = (unsigned int) len_written;
+ ret = suspend_compress_read((u8 *) &position_saved, sizeof(position_saved));
+ if (ret)
+ return ret;
+
+ if (position != position_saved) {
+ printk("Position saved (%d) != position I'm at now (%d).\n",
+ position_saved, position);
+ BUG_ON(1);
+ }
+ if (len >= PAGE_SIZE) { /* uncompressed */
+ ret = suspend_compress_read(buffer_start, PAGE_SIZE);
+ if (ret)
+ return ret;
+
+ position += PAGE_SIZE;
+ } else { /* compressed */
+ if ((ret = suspend_compress_read(page_buffer, len)) >= 0) {
+ int outlen = PAGE_SIZE;
+ /* Important note.
+ *
+ * For Deflate, decompression return values may represent
+ * errors. Deflate complains when everything is alright, so
+ * we ignore the errors unless the number of output bytes is
+ * not PAGE_SIZE.
+ */
+ crypto_comp_decompress(suspend_compressor_transform,
+ page_buffer, len,
+ buffer_start, &outlen);
+ if (outlen != PAGE_SIZE) {
+ printk("Decompression yielded %d bytes instead of %ld.\n", outlen, PAGE_SIZE);
+ ret = -EIO;
+ } else
+ ret = 0;
+ }
+ position += len;
+ }
+ position += 2 + sizeof(int);
+ } else
+ printk("Compress_read returned %d.", ret);
+ kunmap(buffer_page);
+ return ret;
+}
+
+

--
Nigel Cunningham nigel at suspend2 dot net
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/