]>
Commit | Line | Data |
---|---|---|
62c455ca ZW |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright (c) 2019 HiSilicon Limited. */ | |
3 | #include <crypto/internal/acompress.h> | |
4 | #include <linux/bitfield.h> | |
5 | #include <linux/dma-mapping.h> | |
6 | #include <linux/scatterlist.h> | |
7 | #include "zip.h" | |
8 | ||
9 | #define HZIP_ZLIB_HEAD_SIZE 2 | |
10 | #define HZIP_GZIP_HEAD_SIZE 10 | |
11 | ||
12 | #define GZIP_HEAD_FHCRC_BIT BIT(1) | |
13 | #define GZIP_HEAD_FEXTRA_BIT BIT(2) | |
14 | #define GZIP_HEAD_FNAME_BIT BIT(3) | |
15 | #define GZIP_HEAD_FCOMMENT_BIT BIT(4) | |
16 | ||
17 | #define GZIP_HEAD_FLG_SHIFT 3 | |
18 | #define GZIP_HEAD_FEXTRA_SHIFT 10 | |
19 | #define GZIP_HEAD_FEXTRA_XLEN 2 | |
20 | #define GZIP_HEAD_FHCRC_SIZE 2 | |
21 | ||
22 | #define HZIP_CTX_Q_NUM 2 | |
23 | #define HZIP_GZIP_HEAD_BUF 256 | |
24 | #define HZIP_ALG_PRIORITY 300 | |
25 | ||
26 | static const u8 zlib_head[HZIP_ZLIB_HEAD_SIZE] = {0x78, 0x9c}; | |
27 | static const u8 gzip_head[HZIP_GZIP_HEAD_SIZE] = {0x1f, 0x8b, 0x08, 0x0, 0x0, | |
28 | 0x0, 0x0, 0x0, 0x0, 0x03}; | |
29 | enum hisi_zip_alg_type { | |
30 | HZIP_ALG_TYPE_COMP = 0, | |
31 | HZIP_ALG_TYPE_DECOMP = 1, | |
32 | }; | |
33 | ||
34 | #define COMP_NAME_TO_TYPE(alg_name) \ | |
35 | (!strcmp((alg_name), "zlib-deflate") ? HZIP_ALG_TYPE_ZLIB : \ | |
36 | !strcmp((alg_name), "gzip") ? HZIP_ALG_TYPE_GZIP : 0) \ | |
37 | ||
38 | #define TO_HEAD_SIZE(req_type) \ | |
39 | (((req_type) == HZIP_ALG_TYPE_ZLIB) ? sizeof(zlib_head) : \ | |
40 | ((req_type) == HZIP_ALG_TYPE_GZIP) ? sizeof(gzip_head) : 0) \ | |
41 | ||
42 | #define TO_HEAD(req_type) \ | |
43 | (((req_type) == HZIP_ALG_TYPE_ZLIB) ? zlib_head : \ | |
44 | ((req_type) == HZIP_ALG_TYPE_GZIP) ? gzip_head : 0) \ | |
45 | ||
46 | struct hisi_zip_req { | |
47 | struct acomp_req *req; | |
48 | struct scatterlist *src; | |
49 | struct scatterlist *dst; | |
50 | size_t slen; | |
51 | size_t dlen; | |
52 | struct hisi_acc_hw_sgl *hw_src; | |
53 | struct hisi_acc_hw_sgl *hw_dst; | |
54 | dma_addr_t dma_src; | |
55 | dma_addr_t dma_dst; | |
56 | int req_id; | |
57 | }; | |
58 | ||
59 | struct hisi_zip_req_q { | |
60 | struct hisi_zip_req *q; | |
61 | unsigned long *req_bitmap; | |
62 | rwlock_t req_lock; | |
63 | u16 size; | |
64 | }; | |
65 | ||
66 | struct hisi_zip_qp_ctx { | |
67 | struct hisi_qp *qp; | |
68 | struct hisi_zip_sqe zip_sqe; | |
69 | struct hisi_zip_req_q req_q; | |
70 | struct hisi_acc_sgl_pool sgl_pool; | |
71 | struct hisi_zip *zip_dev; | |
72 | struct hisi_zip_ctx *ctx; | |
73 | }; | |
74 | ||
75 | struct hisi_zip_ctx { | |
76 | #define QPC_COMP 0 | |
77 | #define QPC_DECOMP 1 | |
78 | struct hisi_zip_qp_ctx qp_ctx[HZIP_CTX_Q_NUM]; | |
79 | }; | |
80 | ||
81 | static void hisi_zip_config_buf_type(struct hisi_zip_sqe *sqe, u8 buf_type) | |
82 | { | |
83 | u32 val; | |
84 | ||
85 | val = (sqe->dw9) & ~HZIP_BUF_TYPE_M; | |
86 | val |= FIELD_PREP(HZIP_BUF_TYPE_M, buf_type); | |
87 | sqe->dw9 = val; | |
88 | } | |
89 | ||
90 | static void hisi_zip_config_tag(struct hisi_zip_sqe *sqe, u32 tag) | |
91 | { | |
92 | sqe->tag = tag; | |
93 | } | |
94 | ||
95 | static void hisi_zip_fill_sqe(struct hisi_zip_sqe *sqe, u8 req_type, | |
96 | dma_addr_t s_addr, dma_addr_t d_addr, u32 slen, | |
97 | u32 dlen) | |
98 | { | |
99 | memset(sqe, 0, sizeof(struct hisi_zip_sqe)); | |
100 | ||
101 | sqe->input_data_length = slen; | |
102 | sqe->dw9 = FIELD_PREP(HZIP_REQ_TYPE_M, req_type); | |
103 | sqe->dest_avail_out = dlen; | |
104 | sqe->source_addr_l = lower_32_bits(s_addr); | |
105 | sqe->source_addr_h = upper_32_bits(s_addr); | |
106 | sqe->dest_addr_l = lower_32_bits(d_addr); | |
107 | sqe->dest_addr_h = upper_32_bits(d_addr); | |
108 | } | |
109 | ||
110 | static int hisi_zip_create_qp(struct hisi_qm *qm, struct hisi_zip_qp_ctx *ctx, | |
111 | int alg_type, int req_type) | |
112 | { | |
113 | struct hisi_qp *qp; | |
114 | int ret; | |
115 | ||
116 | qp = hisi_qm_create_qp(qm, alg_type); | |
117 | if (IS_ERR(qp)) | |
118 | return PTR_ERR(qp); | |
119 | ||
120 | qp->req_type = req_type; | |
121 | qp->qp_ctx = ctx; | |
122 | ctx->qp = qp; | |
123 | ||
124 | ret = hisi_qm_start_qp(qp, 0); | |
125 | if (ret < 0) | |
126 | goto err_release_qp; | |
127 | ||
128 | return 0; | |
129 | ||
130 | err_release_qp: | |
131 | hisi_qm_release_qp(qp); | |
132 | return ret; | |
133 | } | |
134 | ||
135 | static void hisi_zip_release_qp(struct hisi_zip_qp_ctx *ctx) | |
136 | { | |
137 | hisi_qm_stop_qp(ctx->qp); | |
138 | hisi_qm_release_qp(ctx->qp); | |
139 | } | |
140 | ||
141 | static int hisi_zip_ctx_init(struct hisi_zip_ctx *hisi_zip_ctx, u8 req_type) | |
142 | { | |
143 | struct hisi_zip *hisi_zip; | |
144 | struct hisi_qm *qm; | |
145 | int ret, i, j; | |
146 | ||
147 | /* find the proper zip device */ | |
148 | hisi_zip = find_zip_device(cpu_to_node(smp_processor_id())); | |
149 | if (!hisi_zip) { | |
150 | pr_err("Failed to find a proper ZIP device!\n"); | |
151 | return -ENODEV; | |
152 | } | |
153 | qm = &hisi_zip->qm; | |
154 | ||
155 | for (i = 0; i < HZIP_CTX_Q_NUM; i++) { | |
156 | /* alg_type = 0 for compress, 1 for decompress in hw sqe */ | |
157 | ret = hisi_zip_create_qp(qm, &hisi_zip_ctx->qp_ctx[i], i, | |
158 | req_type); | |
159 | if (ret) | |
160 | goto err; | |
161 | ||
162 | hisi_zip_ctx->qp_ctx[i].zip_dev = hisi_zip; | |
163 | } | |
164 | ||
165 | return 0; | |
166 | err: | |
167 | for (j = i - 1; j >= 0; j--) | |
168 | hisi_zip_release_qp(&hisi_zip_ctx->qp_ctx[j]); | |
169 | ||
170 | return ret; | |
171 | } | |
172 | ||
173 | static void hisi_zip_ctx_exit(struct hisi_zip_ctx *hisi_zip_ctx) | |
174 | { | |
175 | int i; | |
176 | ||
177 | for (i = 1; i >= 0; i--) | |
178 | hisi_zip_release_qp(&hisi_zip_ctx->qp_ctx[i]); | |
179 | } | |
180 | ||
181 | static u16 get_extra_field_size(const u8 *start) | |
182 | { | |
183 | return *((u16 *)start) + GZIP_HEAD_FEXTRA_XLEN; | |
184 | } | |
185 | ||
186 | static u32 get_name_field_size(const u8 *start) | |
187 | { | |
188 | return strlen(start) + 1; | |
189 | } | |
190 | ||
191 | static u32 get_comment_field_size(const u8 *start) | |
192 | { | |
193 | return strlen(start) + 1; | |
194 | } | |
195 | ||
196 | static u32 __get_gzip_head_size(const u8 *src) | |
197 | { | |
198 | u8 head_flg = *(src + GZIP_HEAD_FLG_SHIFT); | |
199 | u32 size = GZIP_HEAD_FEXTRA_SHIFT; | |
200 | ||
201 | if (head_flg & GZIP_HEAD_FEXTRA_BIT) | |
202 | size += get_extra_field_size(src + size); | |
203 | if (head_flg & GZIP_HEAD_FNAME_BIT) | |
204 | size += get_name_field_size(src + size); | |
205 | if (head_flg & GZIP_HEAD_FCOMMENT_BIT) | |
206 | size += get_comment_field_size(src + size); | |
207 | if (head_flg & GZIP_HEAD_FHCRC_BIT) | |
208 | size += GZIP_HEAD_FHCRC_SIZE; | |
209 | ||
210 | return size; | |
211 | } | |
212 | ||
213 | static int hisi_zip_create_req_q(struct hisi_zip_ctx *ctx) | |
214 | { | |
215 | struct hisi_zip_req_q *req_q; | |
216 | int i, ret; | |
217 | ||
218 | for (i = 0; i < HZIP_CTX_Q_NUM; i++) { | |
219 | req_q = &ctx->qp_ctx[i].req_q; | |
220 | req_q->size = QM_Q_DEPTH; | |
221 | ||
222 | req_q->req_bitmap = kcalloc(BITS_TO_LONGS(req_q->size), | |
223 | sizeof(long), GFP_KERNEL); | |
224 | if (!req_q->req_bitmap) { | |
225 | ret = -ENOMEM; | |
1ed2002f ZW |
226 | if (i == 0) |
227 | return ret; | |
228 | ||
229 | goto err_free_loop0; | |
62c455ca ZW |
230 | } |
231 | rwlock_init(&req_q->req_lock); | |
232 | ||
233 | req_q->q = kcalloc(req_q->size, sizeof(struct hisi_zip_req), | |
234 | GFP_KERNEL); | |
235 | if (!req_q->q) { | |
236 | ret = -ENOMEM; | |
237 | if (i == 0) | |
238 | goto err_free_bitmap; | |
239 | else | |
240 | goto err_free_loop1; | |
241 | } | |
242 | } | |
243 | ||
244 | return 0; | |
245 | ||
246 | err_free_loop1: | |
247 | kfree(ctx->qp_ctx[QPC_DECOMP].req_q.req_bitmap); | |
248 | err_free_loop0: | |
249 | kfree(ctx->qp_ctx[QPC_COMP].req_q.q); | |
250 | err_free_bitmap: | |
251 | kfree(ctx->qp_ctx[QPC_COMP].req_q.req_bitmap); | |
252 | return ret; | |
253 | } | |
254 | ||
255 | static void hisi_zip_release_req_q(struct hisi_zip_ctx *ctx) | |
256 | { | |
257 | int i; | |
258 | ||
259 | for (i = 0; i < HZIP_CTX_Q_NUM; i++) { | |
260 | kfree(ctx->qp_ctx[i].req_q.q); | |
261 | kfree(ctx->qp_ctx[i].req_q.req_bitmap); | |
262 | } | |
263 | } | |
264 | ||
265 | static int hisi_zip_create_sgl_pool(struct hisi_zip_ctx *ctx) | |
266 | { | |
267 | struct hisi_zip_qp_ctx *tmp; | |
268 | int i, ret; | |
269 | ||
270 | for (i = 0; i < HZIP_CTX_Q_NUM; i++) { | |
271 | tmp = &ctx->qp_ctx[i]; | |
272 | ret = hisi_acc_create_sgl_pool(&tmp->qp->qm->pdev->dev, | |
273 | &tmp->sgl_pool, | |
274 | QM_Q_DEPTH << 1); | |
275 | if (ret < 0) { | |
276 | if (i == 1) | |
277 | goto err_free_sgl_pool0; | |
278 | return -ENOMEM; | |
279 | } | |
280 | } | |
281 | ||
282 | return 0; | |
283 | ||
284 | err_free_sgl_pool0: | |
285 | hisi_acc_free_sgl_pool(&ctx->qp_ctx[QPC_COMP].qp->qm->pdev->dev, | |
286 | &ctx->qp_ctx[QPC_COMP].sgl_pool); | |
287 | return -ENOMEM; | |
288 | } | |
289 | ||
290 | static void hisi_zip_release_sgl_pool(struct hisi_zip_ctx *ctx) | |
291 | { | |
292 | int i; | |
293 | ||
294 | for (i = 0; i < HZIP_CTX_Q_NUM; i++) | |
295 | hisi_acc_free_sgl_pool(&ctx->qp_ctx[i].qp->qm->pdev->dev, | |
296 | &ctx->qp_ctx[i].sgl_pool); | |
297 | } | |
298 | ||
299 | static void hisi_zip_remove_req(struct hisi_zip_qp_ctx *qp_ctx, | |
300 | struct hisi_zip_req *req) | |
301 | { | |
302 | struct hisi_zip_req_q *req_q = &qp_ctx->req_q; | |
303 | ||
304 | if (qp_ctx->qp->alg_type == HZIP_ALG_TYPE_COMP) | |
305 | kfree(req->dst); | |
306 | else | |
307 | kfree(req->src); | |
308 | ||
309 | write_lock(&req_q->req_lock); | |
310 | clear_bit(req->req_id, req_q->req_bitmap); | |
311 | memset(req, 0, sizeof(struct hisi_zip_req)); | |
312 | write_unlock(&req_q->req_lock); | |
313 | } | |
314 | ||
315 | static void hisi_zip_acomp_cb(struct hisi_qp *qp, void *data) | |
316 | { | |
317 | struct hisi_zip_sqe *sqe = data; | |
318 | struct hisi_zip_qp_ctx *qp_ctx = qp->qp_ctx; | |
319 | struct hisi_zip_req_q *req_q = &qp_ctx->req_q; | |
320 | struct hisi_zip_req *req = req_q->q + sqe->tag; | |
321 | struct acomp_req *acomp_req = req->req; | |
322 | struct device *dev = &qp->qm->pdev->dev; | |
323 | u32 status, dlen, head_size; | |
324 | int err = 0; | |
325 | ||
326 | status = sqe->dw3 & HZIP_BD_STATUS_M; | |
327 | ||
328 | if (status != 0 && status != HZIP_NC_ERR) { | |
329 | dev_err(dev, "%scompress fail in qp%u: %u, output: %u\n", | |
330 | (qp->alg_type == 0) ? "" : "de", qp->qp_id, status, | |
331 | sqe->produced); | |
332 | err = -EIO; | |
333 | } | |
334 | dlen = sqe->produced; | |
335 | ||
336 | hisi_acc_sg_buf_unmap(dev, req->src, req->hw_src); | |
337 | hisi_acc_sg_buf_unmap(dev, req->dst, req->hw_dst); | |
338 | ||
339 | head_size = (qp->alg_type == 0) ? TO_HEAD_SIZE(qp->req_type) : 0; | |
340 | acomp_req->dlen = dlen + head_size; | |
341 | ||
342 | if (acomp_req->base.complete) | |
343 | acomp_request_complete(acomp_req, err); | |
344 | ||
345 | hisi_zip_remove_req(qp_ctx, req); | |
346 | } | |
347 | ||
348 | static void hisi_zip_set_acomp_cb(struct hisi_zip_ctx *ctx, | |
349 | void (*fn)(struct hisi_qp *, void *)) | |
350 | { | |
351 | int i; | |
352 | ||
353 | for (i = 0; i < HZIP_CTX_Q_NUM; i++) | |
354 | ctx->qp_ctx[i].qp->req_cb = fn; | |
355 | } | |
356 | ||
357 | static int hisi_zip_acomp_init(struct crypto_acomp *tfm) | |
358 | { | |
359 | const char *alg_name = crypto_tfm_alg_name(&tfm->base); | |
360 | struct hisi_zip_ctx *ctx = crypto_tfm_ctx(&tfm->base); | |
361 | int ret; | |
362 | ||
363 | ret = hisi_zip_ctx_init(ctx, COMP_NAME_TO_TYPE(alg_name)); | |
364 | if (ret) | |
365 | return ret; | |
366 | ||
367 | ret = hisi_zip_create_req_q(ctx); | |
368 | if (ret) | |
369 | goto err_ctx_exit; | |
370 | ||
371 | ret = hisi_zip_create_sgl_pool(ctx); | |
372 | if (ret) | |
373 | goto err_release_req_q; | |
374 | ||
375 | hisi_zip_set_acomp_cb(ctx, hisi_zip_acomp_cb); | |
376 | ||
377 | return 0; | |
378 | ||
379 | err_release_req_q: | |
380 | hisi_zip_release_req_q(ctx); | |
381 | err_ctx_exit: | |
382 | hisi_zip_ctx_exit(ctx); | |
383 | return ret; | |
384 | } | |
385 | ||
386 | static void hisi_zip_acomp_exit(struct crypto_acomp *tfm) | |
387 | { | |
388 | struct hisi_zip_ctx *ctx = crypto_tfm_ctx(&tfm->base); | |
389 | ||
390 | hisi_zip_set_acomp_cb(ctx, NULL); | |
391 | hisi_zip_release_sgl_pool(ctx); | |
392 | hisi_zip_release_req_q(ctx); | |
393 | hisi_zip_ctx_exit(ctx); | |
394 | } | |
395 | ||
396 | static int add_comp_head(struct scatterlist *dst, u8 req_type) | |
397 | { | |
398 | int head_size = TO_HEAD_SIZE(req_type); | |
399 | const u8 *head = TO_HEAD(req_type); | |
400 | int ret; | |
401 | ||
402 | ret = sg_copy_from_buffer(dst, sg_nents(dst), head, head_size); | |
403 | if (ret != head_size) | |
404 | return -ENOMEM; | |
405 | ||
406 | return head_size; | |
407 | } | |
408 | ||
409 | static size_t get_gzip_head_size(struct scatterlist *sgl) | |
410 | { | |
411 | char buf[HZIP_GZIP_HEAD_BUF]; | |
412 | ||
413 | sg_copy_to_buffer(sgl, sg_nents(sgl), buf, sizeof(buf)); | |
414 | ||
415 | return __get_gzip_head_size(buf); | |
416 | } | |
417 | ||
418 | static size_t get_comp_head_size(struct scatterlist *src, u8 req_type) | |
419 | { | |
420 | switch (req_type) { | |
421 | case HZIP_ALG_TYPE_ZLIB: | |
422 | return TO_HEAD_SIZE(HZIP_ALG_TYPE_ZLIB); | |
423 | case HZIP_ALG_TYPE_GZIP: | |
424 | return get_gzip_head_size(src); | |
425 | default: | |
426 | pr_err("request type does not support!\n"); | |
427 | return -EINVAL; | |
428 | } | |
429 | } | |
430 | ||
431 | static int get_sg_skip_bytes(struct scatterlist *sgl, size_t bytes, | |
432 | size_t remains, struct scatterlist **out) | |
433 | { | |
434 | #define SPLIT_NUM 2 | |
435 | size_t split_sizes[SPLIT_NUM]; | |
436 | int out_mapped_nents[SPLIT_NUM]; | |
437 | ||
438 | split_sizes[0] = bytes; | |
439 | split_sizes[1] = remains; | |
440 | ||
441 | return sg_split(sgl, 0, 0, SPLIT_NUM, split_sizes, out, | |
442 | out_mapped_nents, GFP_KERNEL); | |
443 | } | |
444 | ||
445 | static struct hisi_zip_req *hisi_zip_create_req(struct acomp_req *req, | |
446 | struct hisi_zip_qp_ctx *qp_ctx, | |
447 | size_t head_size, bool is_comp) | |
448 | { | |
449 | struct hisi_zip_req_q *req_q = &qp_ctx->req_q; | |
450 | struct hisi_zip_req *q = req_q->q; | |
451 | struct hisi_zip_req *req_cache; | |
452 | struct scatterlist *out[2]; | |
453 | struct scatterlist *sgl; | |
454 | size_t len; | |
455 | int ret, req_id; | |
456 | ||
457 | /* | |
458 | * remove/add zlib/gzip head, as hardware operations do not include | |
459 | * comp head. so split req->src to get sgl without heads in acomp, or | |
460 | * add comp head to req->dst ahead of that hardware output compressed | |
461 | * data in sgl splited from req->dst without comp head. | |
462 | */ | |
463 | if (is_comp) { | |
464 | sgl = req->dst; | |
465 | len = req->dlen - head_size; | |
466 | } else { | |
467 | sgl = req->src; | |
468 | len = req->slen - head_size; | |
469 | } | |
470 | ||
471 | ret = get_sg_skip_bytes(sgl, head_size, len, out); | |
472 | if (ret) | |
473 | return ERR_PTR(ret); | |
474 | ||
475 | /* sgl for comp head is useless, so free it now */ | |
476 | kfree(out[0]); | |
477 | ||
478 | write_lock(&req_q->req_lock); | |
479 | ||
480 | req_id = find_first_zero_bit(req_q->req_bitmap, req_q->size); | |
481 | if (req_id >= req_q->size) { | |
482 | write_unlock(&req_q->req_lock); | |
483 | dev_dbg(&qp_ctx->qp->qm->pdev->dev, "req cache is full!\n"); | |
484 | kfree(out[1]); | |
485 | return ERR_PTR(-EBUSY); | |
486 | } | |
487 | set_bit(req_id, req_q->req_bitmap); | |
488 | ||
489 | req_cache = q + req_id; | |
490 | req_cache->req_id = req_id; | |
491 | req_cache->req = req; | |
492 | if (is_comp) { | |
493 | req_cache->src = req->src; | |
494 | req_cache->dst = out[1]; | |
495 | req_cache->slen = req->slen; | |
496 | req_cache->dlen = req->dlen - head_size; | |
497 | } else { | |
498 | req_cache->src = out[1]; | |
499 | req_cache->dst = req->dst; | |
500 | req_cache->slen = req->slen - head_size; | |
501 | req_cache->dlen = req->dlen; | |
502 | } | |
503 | ||
504 | write_unlock(&req_q->req_lock); | |
505 | ||
506 | return req_cache; | |
507 | } | |
508 | ||
509 | static int hisi_zip_do_work(struct hisi_zip_req *req, | |
510 | struct hisi_zip_qp_ctx *qp_ctx) | |
511 | { | |
512 | struct hisi_zip_sqe *zip_sqe = &qp_ctx->zip_sqe; | |
513 | struct hisi_qp *qp = qp_ctx->qp; | |
514 | struct device *dev = &qp->qm->pdev->dev; | |
515 | struct hisi_acc_sgl_pool *pool = &qp_ctx->sgl_pool; | |
516 | dma_addr_t input; | |
517 | dma_addr_t output; | |
518 | int ret; | |
519 | ||
520 | if (!req->src || !req->slen || !req->dst || !req->dlen) | |
521 | return -EINVAL; | |
522 | ||
523 | req->hw_src = hisi_acc_sg_buf_map_to_hw_sgl(dev, req->src, pool, | |
524 | req->req_id << 1, &input); | |
525 | if (IS_ERR(req->hw_src)) | |
526 | return PTR_ERR(req->hw_src); | |
527 | req->dma_src = input; | |
528 | ||
529 | req->hw_dst = hisi_acc_sg_buf_map_to_hw_sgl(dev, req->dst, pool, | |
530 | (req->req_id << 1) + 1, | |
531 | &output); | |
532 | if (IS_ERR(req->hw_dst)) { | |
533 | ret = PTR_ERR(req->hw_dst); | |
534 | goto err_unmap_input; | |
535 | } | |
536 | req->dma_dst = output; | |
537 | ||
538 | hisi_zip_fill_sqe(zip_sqe, qp->req_type, input, output, req->slen, | |
539 | req->dlen); | |
540 | hisi_zip_config_buf_type(zip_sqe, HZIP_SGL); | |
541 | hisi_zip_config_tag(zip_sqe, req->req_id); | |
542 | ||
543 | /* send command to start a task */ | |
544 | ret = hisi_qp_send(qp, zip_sqe); | |
545 | if (ret < 0) | |
546 | goto err_unmap_output; | |
547 | ||
548 | return -EINPROGRESS; | |
549 | ||
550 | err_unmap_output: | |
551 | hisi_acc_sg_buf_unmap(dev, req->dst, req->hw_dst); | |
552 | err_unmap_input: | |
553 | hisi_acc_sg_buf_unmap(dev, req->src, req->hw_src); | |
554 | return ret; | |
555 | } | |
556 | ||
557 | static int hisi_zip_acompress(struct acomp_req *acomp_req) | |
558 | { | |
559 | struct hisi_zip_ctx *ctx = crypto_tfm_ctx(acomp_req->base.tfm); | |
560 | struct hisi_zip_qp_ctx *qp_ctx = &ctx->qp_ctx[QPC_COMP]; | |
561 | struct hisi_zip_req *req; | |
62a9d9fc | 562 | int head_size; |
62c455ca ZW |
563 | int ret; |
564 | ||
565 | /* let's output compression head now */ | |
566 | head_size = add_comp_head(acomp_req->dst, qp_ctx->qp->req_type); | |
567 | if (head_size < 0) | |
568 | return -ENOMEM; | |
569 | ||
62a9d9fc | 570 | req = hisi_zip_create_req(acomp_req, qp_ctx, (size_t)head_size, true); |
62c455ca ZW |
571 | if (IS_ERR(req)) |
572 | return PTR_ERR(req); | |
573 | ||
574 | ret = hisi_zip_do_work(req, qp_ctx); | |
575 | if (ret != -EINPROGRESS) | |
576 | hisi_zip_remove_req(qp_ctx, req); | |
577 | ||
578 | return ret; | |
579 | } | |
580 | ||
581 | static int hisi_zip_adecompress(struct acomp_req *acomp_req) | |
582 | { | |
583 | struct hisi_zip_ctx *ctx = crypto_tfm_ctx(acomp_req->base.tfm); | |
584 | struct hisi_zip_qp_ctx *qp_ctx = &ctx->qp_ctx[QPC_DECOMP]; | |
585 | struct hisi_zip_req *req; | |
586 | size_t head_size; | |
587 | int ret; | |
588 | ||
589 | head_size = get_comp_head_size(acomp_req->src, qp_ctx->qp->req_type); | |
590 | ||
591 | req = hisi_zip_create_req(acomp_req, qp_ctx, head_size, false); | |
592 | if (IS_ERR(req)) | |
593 | return PTR_ERR(req); | |
594 | ||
595 | ret = hisi_zip_do_work(req, qp_ctx); | |
596 | if (ret != -EINPROGRESS) | |
597 | hisi_zip_remove_req(qp_ctx, req); | |
598 | ||
599 | return ret; | |
600 | } | |
601 | ||
602 | static struct acomp_alg hisi_zip_acomp_zlib = { | |
603 | .init = hisi_zip_acomp_init, | |
604 | .exit = hisi_zip_acomp_exit, | |
605 | .compress = hisi_zip_acompress, | |
606 | .decompress = hisi_zip_adecompress, | |
607 | .base = { | |
608 | .cra_name = "zlib-deflate", | |
609 | .cra_driver_name = "hisi-zlib-acomp", | |
610 | .cra_module = THIS_MODULE, | |
611 | .cra_priority = HZIP_ALG_PRIORITY, | |
612 | .cra_ctxsize = sizeof(struct hisi_zip_ctx), | |
613 | } | |
614 | }; | |
615 | ||
616 | static struct acomp_alg hisi_zip_acomp_gzip = { | |
617 | .init = hisi_zip_acomp_init, | |
618 | .exit = hisi_zip_acomp_exit, | |
619 | .compress = hisi_zip_acompress, | |
620 | .decompress = hisi_zip_adecompress, | |
621 | .base = { | |
622 | .cra_name = "gzip", | |
623 | .cra_driver_name = "hisi-gzip-acomp", | |
624 | .cra_module = THIS_MODULE, | |
625 | .cra_priority = HZIP_ALG_PRIORITY, | |
626 | .cra_ctxsize = sizeof(struct hisi_zip_ctx), | |
627 | } | |
628 | }; | |
629 | ||
630 | int hisi_zip_register_to_crypto(void) | |
631 | { | |
632 | int ret = 0; | |
633 | ||
634 | ret = crypto_register_acomp(&hisi_zip_acomp_zlib); | |
635 | if (ret) { | |
636 | pr_err("Zlib acomp algorithm registration failed\n"); | |
637 | return ret; | |
638 | } | |
639 | ||
640 | ret = crypto_register_acomp(&hisi_zip_acomp_gzip); | |
641 | if (ret) { | |
642 | pr_err("Gzip acomp algorithm registration failed\n"); | |
643 | crypto_unregister_acomp(&hisi_zip_acomp_zlib); | |
644 | } | |
645 | ||
646 | return ret; | |
647 | } | |
648 | ||
649 | void hisi_zip_unregister_from_crypto(void) | |
650 | { | |
651 | crypto_unregister_acomp(&hisi_zip_acomp_gzip); | |
652 | crypto_unregister_acomp(&hisi_zip_acomp_zlib); | |
653 | } |