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
);