/* By default, we allow compressing input buffers of any length, but we must *usethenon-standard"shortdata"templatesothedecompressorcancorrectly *reproducetheuncompresseddatabufferattherightlength.Howeverthe *hardware842compressorwillnotrecognizethe"shortdata"template,and *willfailtodecompressanycompressedbuffercontainingit(Ihavenoidea *whyanyonewouldwanttousesoftwaretocompressandhardwaretodecompress *butthat'sbesidethepoint).Thisparameterforcesthecompression *functiontosimplyrejectanyinputbufferthatisn'tamultipleof8bytes *long,insteadofusingthe"shortdata"template,sothatallcompressed *buffersproducedbythisfunctionwillbedecompressablebythe842hardware *decompressor.Unlessyouhaveaspecificneedforthat,leavethisdisabled *sothatanylengthbuffercanbecompressed.
*/ staticbool sw842_strict;
module_param_named(strict, sw842_strict, bool, 0644);
if (sw842_template_counts)
atomic_inc(&template_count[t[4]]);
return0;
}
staticint add_repeat_template(struct sw842_param *p, u8 r)
{ int ret;
/* repeat param is 0-based */ if (!r || --r > REPEAT_BITS_MAX) return -EINVAL;
ret = add_bits(p, OP_REPEAT, OP_BITS); if (ret) return ret;
ret = add_bits(p, r, REPEAT_BITS); if (ret) return ret;
if (sw842_template_counts)
atomic_inc(&template_repeat_count);
return0;
}
staticint add_short_data_template(struct sw842_param *p, u8 b)
{ int ret, i;
if (!b || b > SHORT_DATA_BITS_MAX) return -EINVAL;
ret = add_bits(p, OP_SHORT_DATA, OP_BITS); if (ret) return ret;
ret = add_bits(p, b, SHORT_DATA_BITS); if (ret) return ret;
for (i = 0; i < b; i++) {
ret = add_bits(p, p->in[i], 8); if (ret) return ret;
}
if (sw842_template_counts)
atomic_inc(&template_short_data_count);
return0;
}
staticint add_zeros_template(struct sw842_param *p)
{ int ret = add_bits(p, OP_ZEROS, OP_BITS);
if (ret) return ret;
if (sw842_template_counts)
atomic_inc(&template_zeros_count);
return0;
}
staticint add_end_template(struct sw842_param *p)
{ int ret = add_bits(p, OP_END, OP_BITS);
if (ret) return ret;
if (sw842_template_counts)
atomic_inc(&template_end_count);
return0;
}
staticbool check_template(struct sw842_param *p, u8 c)
{
u8 *t = comp_ops[c]; int i, match, b = 0;
if (c >= OPS_MAX) returnfalse;
for (i = 0; i < 4; i++) { if (t[i] & OP_ACTION_INDEX) { if (t[i] & OP_AMOUNT_2)
match = check_index(p, 2, b >> 1); elseif (t[i] & OP_AMOUNT_4)
match = check_index(p, 4, b >> 2); elseif (t[i] & OP_AMOUNT_8)
match = check_index(p, 8, 0); else returnfalse; if (!match) returnfalse;
}
/* find the next template to use, and add it *thep->dataNfieldsmustalreadybesetforthecurrent8byteblock
*/ staticint process_next(struct sw842_param *p)
{ int ret, i;
/* if using strict mode, we can only compress a multiple of 8 */ if (sw842_strict && (ilen % 8)) {
pr_err("Using strict mode, can't compress len %d\n", ilen); return -EINVAL;
}
/* let's compress at least 8 bytes, mkay? */ if (unlikely(ilen < 8)) goto skip_comp;
/* make initial 'last' different so we don't match the first time */
last = ~get_unaligned((u64 *)p->in);
while (p->ilen > 7) {
next = get_unaligned((u64 *)p->in);
/* must get the next data, as we need to update the hashtable *entrieswiththenewdataeverytime
*/
get_next_data(p);
/* we don't care about endianness in last or next; *we'rejustcomparing8bytestoanother8bytes, *they'reboththesameendianness
*/ if (next == last) { /* repeat count bits are 0-based, so we stop at +1 */ if (++repeat_count <= REPEAT_BITS_MAX) goto repeat;
} if (repeat_count) {
ret = add_repeat_template(p, repeat_count); if (ret) return ret;
repeat_count = 0; if (next == last) /* reached max repeat bits */ goto repeat;
}
if (next == 0)
ret = add_zeros_template(p); else
ret = process_next(p);
if (repeat_count) {
ret = add_repeat_template(p, repeat_count); if (ret) return ret;
}
skip_comp: if (p->ilen > 0) {
ret = add_short_data_template(p, p->ilen); if (ret) return ret;
p->in += p->ilen;
p->ilen = 0;
}
ret = add_end_template(p); if (ret) return ret;
/* *crc(0:31)isappendedtotargetdatastartingwiththenext *bitafterEndofstreamtemplate. *nx842calculatesCRCfordatainbig-endianformat.Sodoing *sameheresothatsw842decompressioncanbeusedforboth *compresseddata.
*/
crc = crc32_be(0, in, ilen);
ret = add_bits(p, crc, CRC_BITS); if (ret) return ret;
if (p->bit) {
p->out++;
p->olen--;
p->bit = 0;
}
/* pad compressed length to multiple of 8 */
pad = (8 - ((total - p->olen) % 8)) % 8; if (pad) { if (pad > p->olen) /* we were so close! */ return -ENOSPC;
memset(p->out, 0, pad);
p->out += pad;
p->olen -= pad;
}
if (unlikely((total - p->olen) > UINT_MAX)) return -ENOSPC;
*olen = total - p->olen;
return0;
}
EXPORT_SYMBOL_GPL(sw842_compress);
staticint __init sw842_init(void)
{ if (sw842_template_counts)
sw842_debugfs_create();
return0;
}
module_init(sw842_init);
staticvoid __exit sw842_exit(void)
{ if (sw842_template_counts)
sw842_debugfs_remove();
}
module_exit(sw842_exit);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.