162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * 842 Software Decompression 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2015 Dan Streetman, IBM Corp 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * See 842.h for details of the 842 compressed format. 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 1162306a36Sopenharmony_ci#define MODULE_NAME "842_decompress" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include "842.h" 1462306a36Sopenharmony_ci#include "842_debugfs.h" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci/* rolling fifo sizes */ 1762306a36Sopenharmony_ci#define I2_FIFO_SIZE (2 * (1 << I2_BITS)) 1862306a36Sopenharmony_ci#define I4_FIFO_SIZE (4 * (1 << I4_BITS)) 1962306a36Sopenharmony_ci#define I8_FIFO_SIZE (8 * (1 << I8_BITS)) 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cistatic u8 decomp_ops[OPS_MAX][4] = { 2262306a36Sopenharmony_ci { D8, N0, N0, N0 }, 2362306a36Sopenharmony_ci { D4, D2, I2, N0 }, 2462306a36Sopenharmony_ci { D4, I2, D2, N0 }, 2562306a36Sopenharmony_ci { D4, I2, I2, N0 }, 2662306a36Sopenharmony_ci { D4, I4, N0, N0 }, 2762306a36Sopenharmony_ci { D2, I2, D4, N0 }, 2862306a36Sopenharmony_ci { D2, I2, D2, I2 }, 2962306a36Sopenharmony_ci { D2, I2, I2, D2 }, 3062306a36Sopenharmony_ci { D2, I2, I2, I2 }, 3162306a36Sopenharmony_ci { D2, I2, I4, N0 }, 3262306a36Sopenharmony_ci { I2, D2, D4, N0 }, 3362306a36Sopenharmony_ci { I2, D4, I2, N0 }, 3462306a36Sopenharmony_ci { I2, D2, I2, D2 }, 3562306a36Sopenharmony_ci { I2, D2, I2, I2 }, 3662306a36Sopenharmony_ci { I2, D2, I4, N0 }, 3762306a36Sopenharmony_ci { I2, I2, D4, N0 }, 3862306a36Sopenharmony_ci { I2, I2, D2, I2 }, 3962306a36Sopenharmony_ci { I2, I2, I2, D2 }, 4062306a36Sopenharmony_ci { I2, I2, I2, I2 }, 4162306a36Sopenharmony_ci { I2, I2, I4, N0 }, 4262306a36Sopenharmony_ci { I4, D4, N0, N0 }, 4362306a36Sopenharmony_ci { I4, D2, I2, N0 }, 4462306a36Sopenharmony_ci { I4, I2, D2, N0 }, 4562306a36Sopenharmony_ci { I4, I2, I2, N0 }, 4662306a36Sopenharmony_ci { I4, I4, N0, N0 }, 4762306a36Sopenharmony_ci { I8, N0, N0, N0 } 4862306a36Sopenharmony_ci}; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistruct sw842_param { 5162306a36Sopenharmony_ci u8 *in; 5262306a36Sopenharmony_ci u8 bit; 5362306a36Sopenharmony_ci u64 ilen; 5462306a36Sopenharmony_ci u8 *out; 5562306a36Sopenharmony_ci u8 *ostart; 5662306a36Sopenharmony_ci u64 olen; 5762306a36Sopenharmony_ci}; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci#define beN_to_cpu(d, s) \ 6062306a36Sopenharmony_ci ((s) == 2 ? be16_to_cpu(get_unaligned((__be16 *)d)) : \ 6162306a36Sopenharmony_ci (s) == 4 ? be32_to_cpu(get_unaligned((__be32 *)d)) : \ 6262306a36Sopenharmony_ci (s) == 8 ? be64_to_cpu(get_unaligned((__be64 *)d)) : \ 6362306a36Sopenharmony_ci 0) 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistatic int next_bits(struct sw842_param *p, u64 *d, u8 n); 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cistatic int __split_next_bits(struct sw842_param *p, u64 *d, u8 n, u8 s) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci u64 tmp = 0; 7062306a36Sopenharmony_ci int ret; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci if (n <= s) { 7362306a36Sopenharmony_ci pr_debug("split_next_bits invalid n %u s %u\n", n, s); 7462306a36Sopenharmony_ci return -EINVAL; 7562306a36Sopenharmony_ci } 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci ret = next_bits(p, &tmp, n - s); 7862306a36Sopenharmony_ci if (ret) 7962306a36Sopenharmony_ci return ret; 8062306a36Sopenharmony_ci ret = next_bits(p, d, s); 8162306a36Sopenharmony_ci if (ret) 8262306a36Sopenharmony_ci return ret; 8362306a36Sopenharmony_ci *d |= tmp << s; 8462306a36Sopenharmony_ci return 0; 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistatic int next_bits(struct sw842_param *p, u64 *d, u8 n) 8862306a36Sopenharmony_ci{ 8962306a36Sopenharmony_ci u8 *in = p->in, b = p->bit, bits = b + n; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci if (n > 64) { 9262306a36Sopenharmony_ci pr_debug("next_bits invalid n %u\n", n); 9362306a36Sopenharmony_ci return -EINVAL; 9462306a36Sopenharmony_ci } 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci /* split this up if reading > 8 bytes, or if we're at the end of 9762306a36Sopenharmony_ci * the input buffer and would read past the end 9862306a36Sopenharmony_ci */ 9962306a36Sopenharmony_ci if (bits > 64) 10062306a36Sopenharmony_ci return __split_next_bits(p, d, n, 32); 10162306a36Sopenharmony_ci else if (p->ilen < 8 && bits > 32 && bits <= 56) 10262306a36Sopenharmony_ci return __split_next_bits(p, d, n, 16); 10362306a36Sopenharmony_ci else if (p->ilen < 4 && bits > 16 && bits <= 24) 10462306a36Sopenharmony_ci return __split_next_bits(p, d, n, 8); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci if (DIV_ROUND_UP(bits, 8) > p->ilen) 10762306a36Sopenharmony_ci return -EOVERFLOW; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci if (bits <= 8) 11062306a36Sopenharmony_ci *d = *in >> (8 - bits); 11162306a36Sopenharmony_ci else if (bits <= 16) 11262306a36Sopenharmony_ci *d = be16_to_cpu(get_unaligned((__be16 *)in)) >> (16 - bits); 11362306a36Sopenharmony_ci else if (bits <= 32) 11462306a36Sopenharmony_ci *d = be32_to_cpu(get_unaligned((__be32 *)in)) >> (32 - bits); 11562306a36Sopenharmony_ci else 11662306a36Sopenharmony_ci *d = be64_to_cpu(get_unaligned((__be64 *)in)) >> (64 - bits); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci *d &= GENMASK_ULL(n - 1, 0); 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci p->bit += n; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci if (p->bit > 7) { 12362306a36Sopenharmony_ci p->in += p->bit / 8; 12462306a36Sopenharmony_ci p->ilen -= p->bit / 8; 12562306a36Sopenharmony_ci p->bit %= 8; 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci return 0; 12962306a36Sopenharmony_ci} 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_cistatic int do_data(struct sw842_param *p, u8 n) 13262306a36Sopenharmony_ci{ 13362306a36Sopenharmony_ci u64 v; 13462306a36Sopenharmony_ci int ret; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci if (n > p->olen) 13762306a36Sopenharmony_ci return -ENOSPC; 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci ret = next_bits(p, &v, n * 8); 14062306a36Sopenharmony_ci if (ret) 14162306a36Sopenharmony_ci return ret; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci switch (n) { 14462306a36Sopenharmony_ci case 2: 14562306a36Sopenharmony_ci put_unaligned(cpu_to_be16((u16)v), (__be16 *)p->out); 14662306a36Sopenharmony_ci break; 14762306a36Sopenharmony_ci case 4: 14862306a36Sopenharmony_ci put_unaligned(cpu_to_be32((u32)v), (__be32 *)p->out); 14962306a36Sopenharmony_ci break; 15062306a36Sopenharmony_ci case 8: 15162306a36Sopenharmony_ci put_unaligned(cpu_to_be64((u64)v), (__be64 *)p->out); 15262306a36Sopenharmony_ci break; 15362306a36Sopenharmony_ci default: 15462306a36Sopenharmony_ci return -EINVAL; 15562306a36Sopenharmony_ci } 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci p->out += n; 15862306a36Sopenharmony_ci p->olen -= n; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci return 0; 16162306a36Sopenharmony_ci} 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_cistatic int __do_index(struct sw842_param *p, u8 size, u8 bits, u64 fsize) 16462306a36Sopenharmony_ci{ 16562306a36Sopenharmony_ci u64 index, offset, total = round_down(p->out - p->ostart, 8); 16662306a36Sopenharmony_ci int ret; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci ret = next_bits(p, &index, bits); 16962306a36Sopenharmony_ci if (ret) 17062306a36Sopenharmony_ci return ret; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci offset = index * size; 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci /* a ring buffer of fsize is used; correct the offset */ 17562306a36Sopenharmony_ci if (total > fsize) { 17662306a36Sopenharmony_ci /* this is where the current fifo is */ 17762306a36Sopenharmony_ci u64 section = round_down(total, fsize); 17862306a36Sopenharmony_ci /* the current pos in the fifo */ 17962306a36Sopenharmony_ci u64 pos = total - section; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci /* if the offset is past/at the pos, we need to 18262306a36Sopenharmony_ci * go back to the last fifo section 18362306a36Sopenharmony_ci */ 18462306a36Sopenharmony_ci if (offset >= pos) 18562306a36Sopenharmony_ci section -= fsize; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci offset += section; 18862306a36Sopenharmony_ci } 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci if (offset + size > total) { 19162306a36Sopenharmony_ci pr_debug("index%x %lx points past end %lx\n", size, 19262306a36Sopenharmony_ci (unsigned long)offset, (unsigned long)total); 19362306a36Sopenharmony_ci return -EINVAL; 19462306a36Sopenharmony_ci } 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci if (size != 2 && size != 4 && size != 8) 19762306a36Sopenharmony_ci WARN(1, "__do_index invalid size %x\n", size); 19862306a36Sopenharmony_ci else 19962306a36Sopenharmony_ci pr_debug("index%x to %lx off %lx adjoff %lx tot %lx data %lx\n", 20062306a36Sopenharmony_ci size, (unsigned long)index, 20162306a36Sopenharmony_ci (unsigned long)(index * size), (unsigned long)offset, 20262306a36Sopenharmony_ci (unsigned long)total, 20362306a36Sopenharmony_ci (unsigned long)beN_to_cpu(&p->ostart[offset], size)); 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci memcpy(p->out, &p->ostart[offset], size); 20662306a36Sopenharmony_ci p->out += size; 20762306a36Sopenharmony_ci p->olen -= size; 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci return 0; 21062306a36Sopenharmony_ci} 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_cistatic int do_index(struct sw842_param *p, u8 n) 21362306a36Sopenharmony_ci{ 21462306a36Sopenharmony_ci switch (n) { 21562306a36Sopenharmony_ci case 2: 21662306a36Sopenharmony_ci return __do_index(p, 2, I2_BITS, I2_FIFO_SIZE); 21762306a36Sopenharmony_ci case 4: 21862306a36Sopenharmony_ci return __do_index(p, 4, I4_BITS, I4_FIFO_SIZE); 21962306a36Sopenharmony_ci case 8: 22062306a36Sopenharmony_ci return __do_index(p, 8, I8_BITS, I8_FIFO_SIZE); 22162306a36Sopenharmony_ci default: 22262306a36Sopenharmony_ci return -EINVAL; 22362306a36Sopenharmony_ci } 22462306a36Sopenharmony_ci} 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_cistatic int do_op(struct sw842_param *p, u8 o) 22762306a36Sopenharmony_ci{ 22862306a36Sopenharmony_ci int i, ret = 0; 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci if (o >= OPS_MAX) 23162306a36Sopenharmony_ci return -EINVAL; 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 23462306a36Sopenharmony_ci u8 op = decomp_ops[o][i]; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci pr_debug("op is %x\n", op); 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci switch (op & OP_ACTION) { 23962306a36Sopenharmony_ci case OP_ACTION_DATA: 24062306a36Sopenharmony_ci ret = do_data(p, op & OP_AMOUNT); 24162306a36Sopenharmony_ci break; 24262306a36Sopenharmony_ci case OP_ACTION_INDEX: 24362306a36Sopenharmony_ci ret = do_index(p, op & OP_AMOUNT); 24462306a36Sopenharmony_ci break; 24562306a36Sopenharmony_ci case OP_ACTION_NOOP: 24662306a36Sopenharmony_ci break; 24762306a36Sopenharmony_ci default: 24862306a36Sopenharmony_ci pr_err("Internal error, invalid op %x\n", op); 24962306a36Sopenharmony_ci return -EINVAL; 25062306a36Sopenharmony_ci } 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci if (ret) 25362306a36Sopenharmony_ci return ret; 25462306a36Sopenharmony_ci } 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci if (sw842_template_counts) 25762306a36Sopenharmony_ci atomic_inc(&template_count[o]); 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci return 0; 26062306a36Sopenharmony_ci} 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci/** 26362306a36Sopenharmony_ci * sw842_decompress 26462306a36Sopenharmony_ci * 26562306a36Sopenharmony_ci * Decompress the 842-compressed buffer of length @ilen at @in 26662306a36Sopenharmony_ci * to the output buffer @out, using no more than @olen bytes. 26762306a36Sopenharmony_ci * 26862306a36Sopenharmony_ci * The compressed buffer must be only a single 842-compressed buffer, 26962306a36Sopenharmony_ci * with the standard format described in the comments in 842.h 27062306a36Sopenharmony_ci * Processing will stop when the 842 "END" template is detected, 27162306a36Sopenharmony_ci * not the end of the buffer. 27262306a36Sopenharmony_ci * 27362306a36Sopenharmony_ci * Returns: 0 on success, error on failure. The @olen parameter 27462306a36Sopenharmony_ci * will contain the number of output bytes written on success, or 27562306a36Sopenharmony_ci * 0 on error. 27662306a36Sopenharmony_ci */ 27762306a36Sopenharmony_ciint sw842_decompress(const u8 *in, unsigned int ilen, 27862306a36Sopenharmony_ci u8 *out, unsigned int *olen) 27962306a36Sopenharmony_ci{ 28062306a36Sopenharmony_ci struct sw842_param p; 28162306a36Sopenharmony_ci int ret; 28262306a36Sopenharmony_ci u64 op, rep, tmp, bytes, total; 28362306a36Sopenharmony_ci u64 crc; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci p.in = (u8 *)in; 28662306a36Sopenharmony_ci p.bit = 0; 28762306a36Sopenharmony_ci p.ilen = ilen; 28862306a36Sopenharmony_ci p.out = out; 28962306a36Sopenharmony_ci p.ostart = out; 29062306a36Sopenharmony_ci p.olen = *olen; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci total = p.olen; 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci *olen = 0; 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci do { 29762306a36Sopenharmony_ci ret = next_bits(&p, &op, OP_BITS); 29862306a36Sopenharmony_ci if (ret) 29962306a36Sopenharmony_ci return ret; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci pr_debug("template is %lx\n", (unsigned long)op); 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci switch (op) { 30462306a36Sopenharmony_ci case OP_REPEAT: 30562306a36Sopenharmony_ci ret = next_bits(&p, &rep, REPEAT_BITS); 30662306a36Sopenharmony_ci if (ret) 30762306a36Sopenharmony_ci return ret; 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci if (p.out == out) /* no previous bytes */ 31062306a36Sopenharmony_ci return -EINVAL; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci /* copy rep + 1 */ 31362306a36Sopenharmony_ci rep++; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci if (rep * 8 > p.olen) 31662306a36Sopenharmony_ci return -ENOSPC; 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci while (rep-- > 0) { 31962306a36Sopenharmony_ci memcpy(p.out, p.out - 8, 8); 32062306a36Sopenharmony_ci p.out += 8; 32162306a36Sopenharmony_ci p.olen -= 8; 32262306a36Sopenharmony_ci } 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci if (sw842_template_counts) 32562306a36Sopenharmony_ci atomic_inc(&template_repeat_count); 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci break; 32862306a36Sopenharmony_ci case OP_ZEROS: 32962306a36Sopenharmony_ci if (8 > p.olen) 33062306a36Sopenharmony_ci return -ENOSPC; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci memset(p.out, 0, 8); 33362306a36Sopenharmony_ci p.out += 8; 33462306a36Sopenharmony_ci p.olen -= 8; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci if (sw842_template_counts) 33762306a36Sopenharmony_ci atomic_inc(&template_zeros_count); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci break; 34062306a36Sopenharmony_ci case OP_SHORT_DATA: 34162306a36Sopenharmony_ci ret = next_bits(&p, &bytes, SHORT_DATA_BITS); 34262306a36Sopenharmony_ci if (ret) 34362306a36Sopenharmony_ci return ret; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci if (!bytes || bytes > SHORT_DATA_BITS_MAX) 34662306a36Sopenharmony_ci return -EINVAL; 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci while (bytes-- > 0) { 34962306a36Sopenharmony_ci ret = next_bits(&p, &tmp, 8); 35062306a36Sopenharmony_ci if (ret) 35162306a36Sopenharmony_ci return ret; 35262306a36Sopenharmony_ci *p.out = (u8)tmp; 35362306a36Sopenharmony_ci p.out++; 35462306a36Sopenharmony_ci p.olen--; 35562306a36Sopenharmony_ci } 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci if (sw842_template_counts) 35862306a36Sopenharmony_ci atomic_inc(&template_short_data_count); 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci break; 36162306a36Sopenharmony_ci case OP_END: 36262306a36Sopenharmony_ci if (sw842_template_counts) 36362306a36Sopenharmony_ci atomic_inc(&template_end_count); 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci break; 36662306a36Sopenharmony_ci default: /* use template */ 36762306a36Sopenharmony_ci ret = do_op(&p, op); 36862306a36Sopenharmony_ci if (ret) 36962306a36Sopenharmony_ci return ret; 37062306a36Sopenharmony_ci break; 37162306a36Sopenharmony_ci } 37262306a36Sopenharmony_ci } while (op != OP_END); 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci /* 37562306a36Sopenharmony_ci * crc(0:31) is saved in compressed data starting with the 37662306a36Sopenharmony_ci * next bit after End of stream template. 37762306a36Sopenharmony_ci */ 37862306a36Sopenharmony_ci ret = next_bits(&p, &crc, CRC_BITS); 37962306a36Sopenharmony_ci if (ret) 38062306a36Sopenharmony_ci return ret; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci /* 38362306a36Sopenharmony_ci * Validate CRC saved in compressed data. 38462306a36Sopenharmony_ci */ 38562306a36Sopenharmony_ci if (crc != (u64)crc32_be(0, out, total - p.olen)) { 38662306a36Sopenharmony_ci pr_debug("CRC mismatch for decompression\n"); 38762306a36Sopenharmony_ci return -EINVAL; 38862306a36Sopenharmony_ci } 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci if (unlikely((total - p.olen) > UINT_MAX)) 39162306a36Sopenharmony_ci return -ENOSPC; 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci *olen = total - p.olen; 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci return 0; 39662306a36Sopenharmony_ci} 39762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(sw842_decompress); 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_cistatic int __init sw842_init(void) 40062306a36Sopenharmony_ci{ 40162306a36Sopenharmony_ci if (sw842_template_counts) 40262306a36Sopenharmony_ci sw842_debugfs_create(); 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci return 0; 40562306a36Sopenharmony_ci} 40662306a36Sopenharmony_cimodule_init(sw842_init); 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_cistatic void __exit sw842_exit(void) 40962306a36Sopenharmony_ci{ 41062306a36Sopenharmony_ci if (sw842_template_counts) 41162306a36Sopenharmony_ci sw842_debugfs_remove(); 41262306a36Sopenharmony_ci} 41362306a36Sopenharmony_cimodule_exit(sw842_exit); 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 41662306a36Sopenharmony_ciMODULE_DESCRIPTION("Software 842 Decompressor"); 41762306a36Sopenharmony_ciMODULE_AUTHOR("Dan Streetman <ddstreet@ieee.org>"); 418