Skip to content

Commit dc50ffb

Browse files
committed
crypto: qat - add qat_zlib_deflate
jira LE-1907 Rebuild_History Non-Buildable kernel-rt-5.14.0-284.30.1.rt14.315.el9_2 commit-author Lucas Segarra Fernandez <[email protected]> commit 7ce515e The ZLIB format (RFC 1950) is made of deflate compressed data surrounded by a header and a footer. The QAT accelerators support only the deflate algorithm, therefore the header and the footer need to be inserted in software. This adds logic in the QAT driver to support the ZLIB format. In particular: * Generalize the function qat_comp_alg_compress_decompress() to allow skipping an initial region (header) of the source and/or destination scatter lists. * Add logic to register the qat_zlib_deflate algorithm into the acomp framework. * For ZLIB compression, skip the initial portion of the destination buffer before sending the job to the QAT accelerator and insert the ZLIB header and footer in the callback, after the QAT request has been processed. * For ZLIB decompression, parse the header in the input buffer provided by the user and verify its validity before attempting the decompression of the buffer with QAT. Then submit the buffer to QAT for decompression. In the callback verify the correctness of the footer by comparing the value of the ADLER produced by QAT with the one in the destination buffer. Signed-off-by: Lucas Segarra Fernandez <[email protected]> Reviewed-by: Giovanni Cabiddu <[email protected]> Signed-off-by: Herbert Xu <[email protected]> (cherry picked from commit 7ce515e) Signed-off-by: Jonathan Maple <[email protected]>
1 parent 9ad644a commit dc50ffb

File tree

1 file changed

+154
-12
lines changed

1 file changed

+154
-12
lines changed

drivers/crypto/qat/qat_common/qat_comp_algs.c

+154-12
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,15 @@
1313
#include "qat_compression.h"
1414
#include "qat_algs_send.h"
1515

16+
#define QAT_RFC_1950_HDR_SIZE 2
17+
#define QAT_RFC_1950_FOOTER_SIZE 4
18+
#define QAT_RFC_1950_CM_DEFLATE 8
19+
#define QAT_RFC_1950_CM_DEFLATE_CINFO_32K 7
20+
#define QAT_RFC_1950_CM_MASK 0x0f
21+
#define QAT_RFC_1950_CM_OFFSET 4
22+
#define QAT_RFC_1950_DICT_MASK 0x20
23+
#define QAT_RFC_1950_COMP_HDR 0x785e
24+
1625
static DEFINE_MUTEX(algs_lock);
1726
static unsigned int active_devs;
1827

@@ -21,9 +30,12 @@ enum direction {
2130
COMPRESSION = 1,
2231
};
2332

33+
struct qat_compression_req;
34+
2435
struct qat_compression_ctx {
2536
u8 comp_ctx[QAT_COMP_CTX_SIZE];
2637
struct qat_compression_instance *inst;
38+
int (*qat_comp_callback)(struct qat_compression_req *qat_req, void *resp);
2739
};
2840

2941
struct qat_dst {
@@ -97,6 +109,69 @@ static void qat_comp_resubmit(struct work_struct *work)
97109
areq->base.complete(&areq->base, ret);
98110
}
99111

112+
static int parse_zlib_header(u16 zlib_h)
113+
{
114+
int ret = -EINVAL;
115+
__be16 header;
116+
u8 *header_p;
117+
u8 cmf, flg;
118+
119+
header = cpu_to_be16(zlib_h);
120+
header_p = (u8 *)&header;
121+
122+
flg = header_p[0];
123+
cmf = header_p[1];
124+
125+
if (cmf >> QAT_RFC_1950_CM_OFFSET > QAT_RFC_1950_CM_DEFLATE_CINFO_32K)
126+
return ret;
127+
128+
if ((cmf & QAT_RFC_1950_CM_MASK) != QAT_RFC_1950_CM_DEFLATE)
129+
return ret;
130+
131+
if (flg & QAT_RFC_1950_DICT_MASK)
132+
return ret;
133+
134+
return 0;
135+
}
136+
137+
static int qat_comp_rfc1950_callback(struct qat_compression_req *qat_req,
138+
void *resp)
139+
{
140+
struct acomp_req *areq = qat_req->acompress_req;
141+
enum direction dir = qat_req->dir;
142+
__be32 qat_produced_adler;
143+
144+
qat_produced_adler = cpu_to_be32(qat_comp_get_produced_adler32(resp));
145+
146+
if (dir == COMPRESSION) {
147+
__be16 zlib_header;
148+
149+
zlib_header = cpu_to_be16(QAT_RFC_1950_COMP_HDR);
150+
scatterwalk_map_and_copy(&zlib_header, areq->dst, 0, QAT_RFC_1950_HDR_SIZE, 1);
151+
areq->dlen += QAT_RFC_1950_HDR_SIZE;
152+
153+
scatterwalk_map_and_copy(&qat_produced_adler, areq->dst, areq->dlen,
154+
QAT_RFC_1950_FOOTER_SIZE, 1);
155+
areq->dlen += QAT_RFC_1950_FOOTER_SIZE;
156+
} else {
157+
__be32 decomp_adler;
158+
int footer_offset;
159+
int consumed;
160+
161+
consumed = qat_comp_get_consumed_ctr(resp);
162+
footer_offset = consumed + QAT_RFC_1950_HDR_SIZE;
163+
if (footer_offset + QAT_RFC_1950_FOOTER_SIZE > areq->slen)
164+
return -EBADMSG;
165+
166+
scatterwalk_map_and_copy(&decomp_adler, areq->src, footer_offset,
167+
QAT_RFC_1950_FOOTER_SIZE, 0);
168+
169+
if (qat_produced_adler != decomp_adler)
170+
return -EBADMSG;
171+
}
172+
return 0;
173+
}
174+
100175
static void qat_comp_generic_callback(struct qat_compression_req *qat_req,
101176
void *resp)
102177
{
@@ -167,6 +242,9 @@ static void qat_comp_generic_callback(struct qat_compression_req *qat_req,
167242
res = 0;
168243
areq->dlen = produced;
169244

245+
if (ctx->qat_comp_callback)
246+
res = ctx->qat_comp_callback(qat_req, resp);
247+
170248
end:
171249
qat_bl_free_bufl(accel_dev, &qat_req->buf);
172250
areq->base.complete(&areq->base, res);
@@ -215,26 +293,38 @@ static void qat_comp_alg_exit_tfm(struct crypto_acomp *acomp_tfm)
215293
memset(ctx, 0, sizeof(*ctx));
216294
}
217295

218-
static int qat_comp_alg_compress_decompress(struct acomp_req *areq,
219-
enum direction dir)
296+
static int qat_comp_alg_rfc1950_init_tfm(struct crypto_acomp *acomp_tfm)
297+
{
298+
struct crypto_tfm *tfm = crypto_acomp_tfm(acomp_tfm);
299+
struct qat_compression_ctx *ctx = crypto_tfm_ctx(tfm);
300+
int ret;
301+
302+
ret = qat_comp_alg_init_tfm(acomp_tfm);
303+
ctx->qat_comp_callback = &qat_comp_rfc1950_callback;
304+
305+
return ret;
306+
}
307+
308+
static int qat_comp_alg_compress_decompress(struct acomp_req *areq, enum direction dir,
309+
unsigned int shdr, unsigned int sftr,
310+
unsigned int dhdr, unsigned int dftr)
220311
{
221312
struct qat_compression_req *qat_req = acomp_request_ctx(areq);
222313
struct crypto_acomp *acomp_tfm = crypto_acomp_reqtfm(areq);
223314
struct crypto_tfm *tfm = crypto_acomp_tfm(acomp_tfm);
224315
struct qat_compression_ctx *ctx = crypto_tfm_ctx(tfm);
225316
struct qat_compression_instance *inst = ctx->inst;
226-
struct qat_sgl_to_bufl_params *p_params = NULL;
227317
gfp_t f = qat_algs_alloc_flags(&areq->base);
228-
struct qat_sgl_to_bufl_params params;
229-
unsigned int slen = areq->slen;
230-
unsigned int dlen = areq->dlen;
318+
struct qat_sgl_to_bufl_params params = {0};
319+
int slen = areq->slen - shdr - sftr;
320+
int dlen = areq->dlen - dhdr - dftr;
231321
dma_addr_t sfbuf, dfbuf;
232322
u8 *req = qat_req->req;
233323
size_t ovf_buff_sz;
234324
int ret;
235325

236-
params.sskip = 0;
237-
params.dskip = 0;
326+
params.sskip = shdr;
327+
params.dskip = dhdr;
238328

239329
if (!areq->src || !slen)
240330
return -EINVAL;
@@ -257,6 +347,7 @@ static int qat_comp_alg_compress_decompress(struct acomp_req *areq,
257347
if (!areq->dst)
258348
return -ENOMEM;
259349

350+
dlen -= dhdr + dftr;
260351
areq->dlen = dlen;
261352
qat_req->dst.resubmitted = false;
262353
}
@@ -265,11 +356,10 @@ static int qat_comp_alg_compress_decompress(struct acomp_req *areq,
265356
params.extra_dst_buff = inst->dc_data->ovf_buff_p;
266357
ovf_buff_sz = inst->dc_data->ovf_buff_sz;
267358
params.sz_extra_dst_buff = ovf_buff_sz;
268-
p_params = &params;
269359
}
270360

271361
ret = qat_bl_sgl_to_bufl(ctx->inst->accel_dev, areq->src, areq->dst,
272-
&qat_req->buf, p_params, f);
362+
&qat_req->buf, &params, f);
273363
if (unlikely(ret))
274364
return ret;
275365

@@ -302,12 +392,49 @@ static int qat_comp_alg_compress_decompress(struct acomp_req *areq,
302392

303393
static int qat_comp_alg_compress(struct acomp_req *req)
304394
{
305-
return qat_comp_alg_compress_decompress(req, COMPRESSION);
395+
return qat_comp_alg_compress_decompress(req, COMPRESSION, 0, 0, 0, 0);
306396
}
307397

308398
static int qat_comp_alg_decompress(struct acomp_req *req)
309399
{
310-
return qat_comp_alg_compress_decompress(req, DECOMPRESSION);
400+
return qat_comp_alg_compress_decompress(req, DECOMPRESSION, 0, 0, 0, 0);
401+
}
402+
403+
static int qat_comp_alg_rfc1950_compress(struct acomp_req *req)
404+
{
405+
if (!req->dst && req->dlen != 0)
406+
return -EINVAL;
407+
408+
if (req->dst && req->dlen <= QAT_RFC_1950_HDR_SIZE + QAT_RFC_1950_FOOTER_SIZE)
409+
return -EINVAL;
410+
411+
return qat_comp_alg_compress_decompress(req, COMPRESSION, 0, 0,
412+
QAT_RFC_1950_HDR_SIZE,
413+
QAT_RFC_1950_FOOTER_SIZE);
414+
}
415+
416+
static int qat_comp_alg_rfc1950_decompress(struct acomp_req *req)
417+
{
418+
struct crypto_acomp *acomp_tfm = crypto_acomp_reqtfm(req);
419+
struct crypto_tfm *tfm = crypto_acomp_tfm(acomp_tfm);
420+
struct qat_compression_ctx *ctx = crypto_tfm_ctx(tfm);
421+
struct adf_accel_dev *accel_dev = ctx->inst->accel_dev;
422+
u16 zlib_header;
423+
int ret;
424+
425+
if (req->slen <= QAT_RFC_1950_HDR_SIZE + QAT_RFC_1950_FOOTER_SIZE)
426+
return -EBADMSG;
427+
428+
scatterwalk_map_and_copy(&zlib_header, req->src, 0, QAT_RFC_1950_HDR_SIZE, 0);
429+
430+
ret = parse_zlib_header(zlib_header);
431+
if (ret) {
432+
dev_dbg(&GET_DEV(accel_dev), "Error parsing zlib header\n");
433+
return ret;
434+
}
435+
436+
return qat_comp_alg_compress_decompress(req, DECOMPRESSION, QAT_RFC_1950_HDR_SIZE,
437+
QAT_RFC_1950_FOOTER_SIZE, 0, 0);
311438
}
312439

313440
static struct acomp_alg qat_acomp[] = { {
@@ -325,6 +452,21 @@ static struct acomp_alg qat_acomp[] = { {
325452
.decompress = qat_comp_alg_decompress,
326453
.dst_free = sgl_free,
327454
.reqsize = sizeof(struct qat_compression_req),
455+
}, {
456+
.base = {
457+
.cra_name = "zlib-deflate",
458+
.cra_driver_name = "qat_zlib_deflate",
459+
.cra_priority = 4001,
460+
.cra_flags = CRYPTO_ALG_ASYNC,
461+
.cra_ctxsize = sizeof(struct qat_compression_ctx),
462+
.cra_module = THIS_MODULE,
463+
},
464+
.init = qat_comp_alg_rfc1950_init_tfm,
465+
.exit = qat_comp_alg_exit_tfm,
466+
.compress = qat_comp_alg_rfc1950_compress,
467+
.decompress = qat_comp_alg_rfc1950_decompress,
468+
.dst_free = sgl_free,
469+
.reqsize = sizeof(struct qat_compression_req),
328470
} };
329471

330472
int qat_comp_algs_register(void)

0 commit comments

Comments
 (0)