1 // SPDX-License-Identifier: Zlib
3 #include "../zlib_deflate/defutil.h"
4 #include "dfltcc_util.h"
7 #include <linux/export.h>
8 #include <linux/zutil.h>
13 int dfltcc_can_deflate(
17 deflate_state *state = (deflate_state *)strm->state;
18 struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
20 /* Check for kernel dfltcc command line parameter */
21 if (zlib_dfltcc_support == ZLIB_DFLTCC_DISABLED ||
22 zlib_dfltcc_support == ZLIB_DFLTCC_INFLATE_ONLY)
25 /* Unsupported compression settings */
26 if (!dfltcc_are_params_ok(state->level, state->w_bits, state->strategy,
27 dfltcc_state->level_mask))
30 /* Unsupported hardware */
31 if (!is_bit_set(dfltcc_state->af.fns, DFLTCC_GDHT) ||
32 !is_bit_set(dfltcc_state->af.fns, DFLTCC_CMPR) ||
33 !is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0))
38 EXPORT_SYMBOL(dfltcc_can_deflate);
40 static void dfltcc_gdht(
44 deflate_state *state = (deflate_state *)strm->state;
45 struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;
46 size_t avail_in = avail_in = strm->avail_in;
50 &strm->next_in, &avail_in, NULL);
53 static dfltcc_cc dfltcc_cmpr(
57 deflate_state *state = (deflate_state *)strm->state;
58 struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param;
59 size_t avail_in = strm->avail_in;
60 size_t avail_out = strm->avail_out;
63 cc = dfltcc(DFLTCC_CMPR | HBT_CIRCULAR,
64 param, &strm->next_out, &avail_out,
65 &strm->next_in, &avail_in, state->window);
66 strm->total_in += (strm->avail_in - avail_in);
67 strm->total_out += (strm->avail_out - avail_out);
68 strm->avail_in = avail_in;
69 strm->avail_out = avail_out;
73 static void send_eobs(
75 const struct dfltcc_param_v0 *param
78 deflate_state *state = (deflate_state *)strm->state;
82 bi_reverse(param->eobs >> (15 - param->eobl), param->eobl),
85 if (state->pending != 0) {
86 /* The remaining data is located in pending_out[0:pending]. If someone
87 * calls put_byte() - this might happen in deflate() - the byte will be
88 * placed into pending_buf[pending], which is incorrect. Move the
89 * remaining data to the beginning of pending_buf so that put_byte() is
92 memmove(state->pending_buf, state->pending_out, state->pending);
93 state->pending_out = state->pending_buf;
96 state->compressed_len += param->eobl;
106 deflate_state *state = (deflate_state *)strm->state;
107 struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
108 struct dfltcc_param_v0 *param = &dfltcc_state->param;
109 uInt masked_avail_in;
111 int need_empty_block;
115 if (!dfltcc_can_deflate(strm))
121 no_flush = flush == Z_NO_FLUSH;
123 /* Trailing empty block. Switch to software, except when Continuation Flag
124 * is set, which means that DFLTCC has buffered some output in the
125 * parameter block and needs to be called again in order to flush it.
127 if (flush == Z_FINISH && strm->avail_in == 0 && !param->cf) {
129 /* A block is still open, and the hardware does not support closing
130 * blocks without adding data. Thus, close it manually.
132 send_eobs(strm, param);
138 if (strm->avail_in == 0 && !param->cf) {
143 /* There is an open non-BFINAL block, we are not going to close it just
144 * yet, we have compressed more than DFLTCC_BLOCK_SIZE bytes and we see
145 * more than DFLTCC_DHT_MIN_SAMPLE_SIZE bytes. Open a new block with a new
146 * DHT in order to adapt to a possibly changed input data distribution.
148 if (param->bcf && no_flush &&
149 strm->total_in > dfltcc_state->block_threshold &&
150 strm->avail_in >= dfltcc_state->dht_threshold) {
152 /* We need to flush the DFLTCC buffer before writing the
153 * End-of-block Symbol. Mask the input data and proceed as usual.
155 masked_avail_in += strm->avail_in;
159 /* DFLTCC buffer is empty, so we can manually write the
160 * End-of-block Symbol right away.
162 send_eobs(strm, param);
164 dfltcc_state->block_threshold =
165 strm->total_in + dfltcc_state->block_size;
166 if (strm->avail_out == 0) {
173 /* The caller gave us too much data. Pass only one block worth of
174 * uncompressed data to DFLTCC and mask the rest, so that on the next
175 * iteration we start a new block.
177 if (no_flush && strm->avail_in > dfltcc_state->block_size) {
178 masked_avail_in += (strm->avail_in - dfltcc_state->block_size);
179 strm->avail_in = dfltcc_state->block_size;
182 /* When we have an open non-BFINAL deflate block and caller indicates that
183 * the stream is ending, we need to close an open deflate block and open a
186 need_empty_block = flush == Z_FINISH && param->bcf && !param->bhf;
188 /* Translate stream to parameter block */
189 param->cvt = CVT_ADLER32;
191 /* We need to close a block. Always do this in software - when there is
192 * no input data, the hardware will not nohor BCC. */
194 if (flush == Z_FINISH && !param->bcf)
195 /* We are about to open a BFINAL block, set Block Header Final bit
196 * until the stream ends.
199 /* DFLTCC-CMPR will write to next_out, so make sure that buffers with
200 * higher precedence are empty.
202 Assert(state->pending == 0, "There must be no pending bytes");
203 Assert(state->bi_valid < 8, "There must be less than 8 pending bits");
204 param->sbb = (unsigned int)state->bi_valid;
206 *strm->next_out = (Byte)state->bi_buf;
208 param->nt = 0; /* Honor history */
209 param->cv = strm->adler;
211 /* When opening a block, choose a Huffman-Table Type */
213 if (strm->total_in == 0 && dfltcc_state->block_threshold > 0) {
214 param->htt = HTT_FIXED;
217 param->htt = HTT_DYNAMIC;
224 cc = dfltcc_cmpr(strm);
225 if (strm->avail_in < 4096 && masked_avail_in > 0)
226 /* We are about to call DFLTCC with a small input buffer, which is
227 * inefficient. Since there is masked data, there will be at least
228 * one more DFLTCC call, so skip the current one and make the next
229 * one handle more data.
232 } while (cc == DFLTCC_CC_AGAIN);
234 /* Translate parameter block to stream */
235 strm->msg = oesc_msg(dfltcc_state->msg, param->oesc);
236 state->bi_valid = param->sbb;
237 if (state->bi_valid == 0)
238 state->bi_buf = 0; /* Avoid accessing next_out */
240 state->bi_buf = *strm->next_out & ((1 << state->bi_valid) - 1);
241 strm->adler = param->cv;
243 /* Unmask the input data */
244 strm->avail_in += masked_avail_in;
247 /* If we encounter an error, it means there is a bug in DFLTCC call */
248 Assert(cc != DFLTCC_CC_OP2_CORRUPT || param->oesc == 0, "BUG");
250 /* Update Block-Continuation Flag. It will be used to check whether to call
251 * GDHT the next time.
253 if (cc == DFLTCC_CC_OK) {
255 send_eobs(strm, param);
257 dfltcc_state->block_threshold =
258 strm->total_in + dfltcc_state->block_size;
261 if (flush == Z_FINISH) {
262 if (need_empty_block)
263 /* Make the current deflate() call also close the stream */
267 *result = finish_done;
270 if (flush == Z_FULL_FLUSH)
271 param->hl = 0; /* Clear history */
272 *result = flush == Z_NO_FLUSH ? need_more : block_done;
278 if (strm->avail_in != 0 && strm->avail_out != 0)
279 goto again; /* deflate() must use all input or all output */
282 EXPORT_SYMBOL(dfltcc_deflate);