summaryrefslogtreecommitdiff
path: root/lib/zlib_dfltcc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/zlib_dfltcc')
-rw-r--r--lib/zlib_dfltcc/dfltcc.c25
-rw-r--r--lib/zlib_dfltcc/dfltcc.h57
-rw-r--r--lib/zlib_dfltcc/dfltcc_deflate.c91
-rw-r--r--lib/zlib_dfltcc/dfltcc_deflate.h21
-rw-r--r--lib/zlib_dfltcc/dfltcc_inflate.c24
-rw-r--r--lib/zlib_dfltcc/dfltcc_inflate.h37
6 files changed, 148 insertions, 107 deletions
diff --git a/lib/zlib_dfltcc/dfltcc.c b/lib/zlib_dfltcc/dfltcc.c
index 782f76e9d4da..ac6ac9739f5b 100644
--- a/lib/zlib_dfltcc/dfltcc.c
+++ b/lib/zlib_dfltcc/dfltcc.c
@@ -23,37 +23,18 @@ char *oesc_msg(
}
}
-void dfltcc_reset(
- z_streamp strm,
- uInt size
-)
-{
- struct dfltcc_state *dfltcc_state =
- (struct dfltcc_state *)((char *)strm->state + size);
- struct dfltcc_qaf_param *param =
- (struct dfltcc_qaf_param *)&dfltcc_state->param;
-
+void dfltcc_reset_state(struct dfltcc_state *dfltcc_state) {
/* Initialize available functions */
if (is_dfltcc_enabled()) {
- dfltcc(DFLTCC_QAF, param, NULL, NULL, NULL, NULL, NULL);
- memmove(&dfltcc_state->af, param, sizeof(dfltcc_state->af));
+ dfltcc(DFLTCC_QAF, &dfltcc_state->param, NULL, NULL, NULL, NULL, NULL);
+ memmove(&dfltcc_state->af, &dfltcc_state->param, sizeof(dfltcc_state->af));
} else
memset(&dfltcc_state->af, 0, sizeof(dfltcc_state->af));
/* Initialize parameter block */
memset(&dfltcc_state->param, 0, sizeof(dfltcc_state->param));
dfltcc_state->param.nt = 1;
-
- /* Initialize tuning parameters */
- if (zlib_dfltcc_support == ZLIB_DFLTCC_FULL_DEBUG)
- dfltcc_state->level_mask = DFLTCC_LEVEL_MASK_DEBUG;
- else
- dfltcc_state->level_mask = DFLTCC_LEVEL_MASK;
- dfltcc_state->block_size = DFLTCC_BLOCK_SIZE;
- dfltcc_state->block_threshold = DFLTCC_FIRST_FHT_BLOCK_SIZE;
- dfltcc_state->dht_threshold = DFLTCC_DHT_MIN_SAMPLE_SIZE;
dfltcc_state->param.ribm = DFLTCC_RIBM;
}
-EXPORT_SYMBOL(dfltcc_reset);
MODULE_LICENSE("GPL");
diff --git a/lib/zlib_dfltcc/dfltcc.h b/lib/zlib_dfltcc/dfltcc.h
index 2a2fac1d050a..b96232bdd44d 100644
--- a/lib/zlib_dfltcc/dfltcc.h
+++ b/lib/zlib_dfltcc/dfltcc.h
@@ -93,63 +93,32 @@ static_assert(sizeof(struct dfltcc_param_v0) == 1536);
struct dfltcc_state {
struct dfltcc_param_v0 param; /* Parameter block */
struct dfltcc_qaf_param af; /* Available functions */
+ char msg[64]; /* Buffer for strm->msg */
+};
+
+/*
+ * Extension of inflate_state and deflate_state for DFLTCC.
+ */
+struct dfltcc_deflate_state {
+ struct dfltcc_state common; /* Parameter block */
uLong level_mask; /* Levels on which to use DFLTCC */
uLong block_size; /* New block each X bytes */
uLong block_threshold; /* New block after total_in > X */
uLong dht_threshold; /* New block only if avail_in >= X */
- char msg[64]; /* Buffer for strm->msg */
};
+#define ALIGN_UP(p, size) (__typeof__(p))(((uintptr_t)(p) + ((size) - 1)) & ~((size) - 1))
/* Resides right after inflate_state or deflate_state */
-#define GET_DFLTCC_STATE(state) ((struct dfltcc_state *)((state) + 1))
-
-/* External functions */
-int dfltcc_can_deflate(z_streamp strm);
-int dfltcc_deflate(z_streamp strm,
- int flush,
- block_state *result);
-void dfltcc_reset(z_streamp strm, uInt size);
-int dfltcc_can_inflate(z_streamp strm);
-typedef enum {
- DFLTCC_INFLATE_CONTINUE,
- DFLTCC_INFLATE_BREAK,
- DFLTCC_INFLATE_SOFTWARE,
-} dfltcc_inflate_action;
-dfltcc_inflate_action dfltcc_inflate(z_streamp strm,
- int flush, int *ret);
+#define GET_DFLTCC_STATE(state) ((struct dfltcc_state *)((char *)(state) + ALIGN_UP(sizeof(*state), 8)))
+
+void dfltcc_reset_state(struct dfltcc_state *dfltcc_state);
+
static inline int is_dfltcc_enabled(void)
{
return (zlib_dfltcc_support != ZLIB_DFLTCC_DISABLED &&
test_facility(DFLTCC_FACILITY));
}
-#define DEFLATE_RESET_HOOK(strm) \
- dfltcc_reset((strm), sizeof(deflate_state))
-
-#define DEFLATE_HOOK dfltcc_deflate
-
-#define DEFLATE_NEED_CHECKSUM(strm) (!dfltcc_can_deflate((strm)))
-
#define DEFLATE_DFLTCC_ENABLED() is_dfltcc_enabled()
-#define INFLATE_RESET_HOOK(strm) \
- dfltcc_reset((strm), sizeof(struct inflate_state))
-
-#define INFLATE_TYPEDO_HOOK(strm, flush) \
- if (dfltcc_can_inflate((strm))) { \
- dfltcc_inflate_action action; \
-\
- RESTORE(); \
- action = dfltcc_inflate((strm), (flush), &ret); \
- LOAD(); \
- if (action == DFLTCC_INFLATE_CONTINUE) \
- break; \
- else if (action == DFLTCC_INFLATE_BREAK) \
- goto inf_leave; \
- }
-
-#define INFLATE_NEED_CHECKSUM(strm) (!dfltcc_can_inflate((strm)))
-
-#define INFLATE_NEED_UPDATEWINDOW(strm) (!dfltcc_can_inflate((strm)))
-
#endif /* DFLTCC_H */
diff --git a/lib/zlib_dfltcc/dfltcc_deflate.c b/lib/zlib_dfltcc/dfltcc_deflate.c
index 6c946e8532ee..b732b6d9e35d 100644
--- a/lib/zlib_dfltcc/dfltcc_deflate.c
+++ b/lib/zlib_dfltcc/dfltcc_deflate.c
@@ -2,11 +2,13 @@
#include "../zlib_deflate/defutil.h"
#include "dfltcc_util.h"
-#include "dfltcc.h"
+#include "dfltcc_deflate.h"
#include <asm/setup.h>
#include <linux/export.h>
#include <linux/zutil.h>
+#define GET_DFLTCC_DEFLATE_STATE(state) ((struct dfltcc_deflate_state *)GET_DFLTCC_STATE(state))
+
/*
* Compress.
*/
@@ -15,7 +17,7 @@ int dfltcc_can_deflate(
)
{
deflate_state *state = (deflate_state *)strm->state;
- struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
+ struct dfltcc_deflate_state *dfltcc_state = GET_DFLTCC_DEFLATE_STATE(state);
/* Check for kernel dfltcc command line parameter */
if (zlib_dfltcc_support == ZLIB_DFLTCC_DISABLED ||
@@ -28,22 +30,39 @@ int dfltcc_can_deflate(
return 0;
/* Unsupported hardware */
- if (!is_bit_set(dfltcc_state->af.fns, DFLTCC_GDHT) ||
- !is_bit_set(dfltcc_state->af.fns, DFLTCC_CMPR) ||
- !is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0))
+ if (!is_bit_set(dfltcc_state->common.af.fns, DFLTCC_GDHT) ||
+ !is_bit_set(dfltcc_state->common.af.fns, DFLTCC_CMPR) ||
+ !is_bit_set(dfltcc_state->common.af.fmts, DFLTCC_FMT0))
return 0;
return 1;
}
EXPORT_SYMBOL(dfltcc_can_deflate);
+void dfltcc_reset_deflate_state(z_streamp strm) {
+ deflate_state *state = (deflate_state *)strm->state;
+ struct dfltcc_deflate_state *dfltcc_state = GET_DFLTCC_DEFLATE_STATE(state);
+
+ dfltcc_reset_state(&dfltcc_state->common);
+
+ /* Initialize tuning parameters */
+ if (zlib_dfltcc_support == ZLIB_DFLTCC_FULL_DEBUG)
+ dfltcc_state->level_mask = DFLTCC_LEVEL_MASK_DEBUG;
+ else
+ dfltcc_state->level_mask = DFLTCC_LEVEL_MASK;
+ dfltcc_state->block_size = DFLTCC_BLOCK_SIZE;
+ dfltcc_state->block_threshold = DFLTCC_FIRST_FHT_BLOCK_SIZE;
+ dfltcc_state->dht_threshold = DFLTCC_DHT_MIN_SAMPLE_SIZE;
+}
+EXPORT_SYMBOL(dfltcc_reset_deflate_state);
+
static void dfltcc_gdht(
z_streamp strm
)
{
deflate_state *state = (deflate_state *)strm->state;
struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;
- size_t avail_in = avail_in = strm->avail_in;
+ size_t avail_in = strm->avail_in;
dfltcc(DFLTCC_GDHT,
param, NULL, NULL,
@@ -104,39 +123,46 @@ int dfltcc_deflate(
)
{
deflate_state *state = (deflate_state *)strm->state;
- struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
- struct dfltcc_param_v0 *param = &dfltcc_state->param;
+ struct dfltcc_deflate_state *dfltcc_state = GET_DFLTCC_DEFLATE_STATE(state);
+ struct dfltcc_param_v0 *param = &dfltcc_state->common.param;
uInt masked_avail_in;
dfltcc_cc cc;
int need_empty_block;
int soft_bcc;
int no_flush;
- if (!dfltcc_can_deflate(strm))
+ if (!dfltcc_can_deflate(strm)) {
+ /* Clear history. */
+ if (flush == Z_FULL_FLUSH)
+ param->hl = 0;
return 0;
+ }
again:
masked_avail_in = 0;
soft_bcc = 0;
no_flush = flush == Z_NO_FLUSH;
- /* Trailing empty block. Switch to software, except when Continuation Flag
- * is set, which means that DFLTCC has buffered some output in the
- * parameter block and needs to be called again in order to flush it.
+ /* No input data. Return, except when Continuation Flag is set, which means
+ * that DFLTCC has buffered some output in the parameter block and needs to
+ * be called again in order to flush it.
*/
- if (flush == Z_FINISH && strm->avail_in == 0 && !param->cf) {
- if (param->bcf) {
- /* A block is still open, and the hardware does not support closing
- * blocks without adding data. Thus, close it manually.
- */
+ if (strm->avail_in == 0 && !param->cf) {
+ /* A block is still open, and the hardware does not support closing
+ * blocks without adding data. Thus, close it manually.
+ */
+ if (!no_flush && param->bcf) {
send_eobs(strm, param);
param->bcf = 0;
}
- return 0;
- }
-
- if (strm->avail_in == 0 && !param->cf) {
- *result = need_more;
+ /* Let one of deflate_* functions write a trailing empty block. */
+ if (flush == Z_FINISH)
+ return 0;
+ /* Clear history. */
+ if (flush == Z_FULL_FLUSH)
+ param->hl = 0;
+ /* Trigger block post-processing if necessary. */
+ *result = no_flush ? need_more : block_done;
return 1;
}
@@ -163,13 +189,18 @@ again:
param->bcf = 0;
dfltcc_state->block_threshold =
strm->total_in + dfltcc_state->block_size;
- if (strm->avail_out == 0) {
- *result = need_more;
- return 1;
- }
}
}
+ /* No space for compressed data. If we proceed, dfltcc_cmpr() will return
+ * DFLTCC_CC_OP1_TOO_SHORT without buffering header bits, but we will still
+ * set BCF=1, which is wrong. Avoid complications and return early.
+ */
+ if (strm->avail_out == 0) {
+ *result = need_more;
+ return 1;
+ }
+
/* The caller gave us too much data. Pass only one block worth of
* uncompressed data to DFLTCC and mask the rest, so that on the next
* iteration we start a new block.
@@ -189,7 +220,7 @@ again:
param->cvt = CVT_ADLER32;
if (!no_flush)
/* We need to close a block. Always do this in software - when there is
- * no input data, the hardware will not nohor BCC. */
+ * no input data, the hardware will not hohor BCC. */
soft_bcc = 1;
if (flush == Z_FINISH && !param->bcf)
/* We are about to open a BFINAL block, set Block Header Final bit
@@ -204,8 +235,8 @@ again:
param->sbb = (unsigned int)state->bi_valid;
if (param->sbb > 0)
*strm->next_out = (Byte)state->bi_buf;
- if (param->hl)
- param->nt = 0; /* Honor history */
+ /* Honor history and check value */
+ param->nt = 0;
param->cv = strm->adler;
/* When opening a block, choose a Huffman-Table Type */
@@ -232,7 +263,7 @@ again:
} while (cc == DFLTCC_CC_AGAIN);
/* Translate parameter block to stream */
- strm->msg = oesc_msg(dfltcc_state->msg, param->oesc);
+ strm->msg = oesc_msg(dfltcc_state->common.msg, param->oesc);
state->bi_valid = param->sbb;
if (state->bi_valid == 0)
state->bi_buf = 0; /* Avoid accessing next_out */
diff --git a/lib/zlib_dfltcc/dfltcc_deflate.h b/lib/zlib_dfltcc/dfltcc_deflate.h
new file mode 100644
index 000000000000..be44b43833b1
--- /dev/null
+++ b/lib/zlib_dfltcc/dfltcc_deflate.h
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: Zlib
+#ifndef DFLTCC_DEFLATE_H
+#define DFLTCC_DEFLATE_H
+
+#include "dfltcc.h"
+
+/* External functions */
+int dfltcc_can_deflate(z_streamp strm);
+int dfltcc_deflate(z_streamp strm,
+ int flush,
+ block_state *result);
+void dfltcc_reset_deflate_state(z_streamp strm);
+
+#define DEFLATE_RESET_HOOK(strm) \
+ dfltcc_reset_deflate_state((strm))
+
+#define DEFLATE_HOOK dfltcc_deflate
+
+#define DEFLATE_NEED_CHECKSUM(strm) (!dfltcc_can_deflate((strm)))
+
+#endif /* DFLTCC_DEFLATE_H */
diff --git a/lib/zlib_dfltcc/dfltcc_inflate.c b/lib/zlib_dfltcc/dfltcc_inflate.c
index fb60b5a6a1cb..437cd34c8490 100644
--- a/lib/zlib_dfltcc/dfltcc_inflate.c
+++ b/lib/zlib_dfltcc/dfltcc_inflate.c
@@ -2,7 +2,7 @@
#include "../zlib_inflate/inflate.h"
#include "dfltcc_util.h"
-#include "dfltcc.h"
+#include "dfltcc_inflate.h"
#include <asm/setup.h>
#include <linux/export.h>
#include <linux/zutil.h>
@@ -22,16 +22,20 @@ int dfltcc_can_inflate(
zlib_dfltcc_support == ZLIB_DFLTCC_DEFLATE_ONLY)
return 0;
- /* Unsupported compression settings */
- if (state->wbits != HB_BITS)
- return 0;
-
/* Unsupported hardware */
return is_bit_set(dfltcc_state->af.fns, DFLTCC_XPND) &&
is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0);
}
EXPORT_SYMBOL(dfltcc_can_inflate);
+void dfltcc_reset_inflate_state(z_streamp strm) {
+ struct inflate_state *state = (struct inflate_state *)strm->state;
+ struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
+
+ dfltcc_reset_state(dfltcc_state);
+}
+EXPORT_SYMBOL(dfltcc_reset_inflate_state);
+
static int dfltcc_was_inflate_used(
z_streamp strm
)
@@ -91,8 +95,10 @@ dfltcc_inflate_action dfltcc_inflate(
struct dfltcc_param_v0 *param = &dfltcc_state->param;
dfltcc_cc cc;
- if (flush == Z_BLOCK) {
- /* DFLTCC does not support stopping on block boundaries */
+ if (flush == Z_BLOCK || flush == Z_PACKET_FLUSH) {
+ /* DFLTCC does not support stopping on block boundaries (Z_BLOCK flush option)
+ * as well as the use of Z_PACKET_FLUSH option (used exclusively by PPP driver)
+ */
if (dfltcc_inflate_disable(strm)) {
*ret = Z_STREAM_ERROR;
return DFLTCC_INFLATE_BREAK;
@@ -121,8 +127,6 @@ dfltcc_inflate_action dfltcc_inflate(
/* Translate stream to parameter block */
param->cvt = CVT_ADLER32;
param->sbb = state->bits;
- param->hl = state->whave; /* Software and hardware history formats match */
- param->ho = (state->write - state->whave) & ((1 << HB_BITS) - 1);
if (param->hl)
param->nt = 0; /* Honor history for the first block */
param->cv = state->check;
@@ -136,8 +140,6 @@ dfltcc_inflate_action dfltcc_inflate(
strm->msg = oesc_msg(dfltcc_state->msg, param->oesc);
state->last = cc == DFLTCC_CC_OK;
state->bits = param->sbb;
- state->whave = param->hl;
- state->write = (param->ho + param->hl) & ((1 << HB_BITS) - 1);
state->check = param->cv;
if (cc == DFLTCC_CC_OP2_CORRUPT && param->oesc != 0) {
/* Report an error if stream is corrupted */
diff --git a/lib/zlib_dfltcc/dfltcc_inflate.h b/lib/zlib_dfltcc/dfltcc_inflate.h
new file mode 100644
index 000000000000..98d4bc42e526
--- /dev/null
+++ b/lib/zlib_dfltcc/dfltcc_inflate.h
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: Zlib
+#ifndef DFLTCC_INFLATE_H
+#define DFLTCC_INFLATE_H
+
+#include "dfltcc.h"
+
+/* External functions */
+void dfltcc_reset_inflate_state(z_streamp strm);
+int dfltcc_can_inflate(z_streamp strm);
+typedef enum {
+ DFLTCC_INFLATE_CONTINUE,
+ DFLTCC_INFLATE_BREAK,
+ DFLTCC_INFLATE_SOFTWARE,
+} dfltcc_inflate_action;
+dfltcc_inflate_action dfltcc_inflate(z_streamp strm,
+ int flush, int *ret);
+#define INFLATE_RESET_HOOK(strm) \
+ dfltcc_reset_inflate_state((strm))
+
+#define INFLATE_TYPEDO_HOOK(strm, flush) \
+ if (dfltcc_can_inflate((strm))) { \
+ dfltcc_inflate_action action; \
+\
+ RESTORE(); \
+ action = dfltcc_inflate((strm), (flush), &ret); \
+ LOAD(); \
+ if (action == DFLTCC_INFLATE_CONTINUE) \
+ break; \
+ else if (action == DFLTCC_INFLATE_BREAK) \
+ goto inf_leave; \
+ }
+
+#define INFLATE_NEED_CHECKSUM(strm) (!dfltcc_can_inflate((strm)))
+
+#define INFLATE_NEED_UPDATEWINDOW(strm) (!dfltcc_can_inflate((strm)))
+
+#endif /* DFLTCC_DEFLATE_H */