zip_crypto.c 16.7 KB
Newer Older
1 2 3 4 5 6 7 8
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2019 HiSilicon Limited. */
#include <crypto/internal/acompress.h>
#include <linux/bitfield.h>
#include <linux/dma-mapping.h>
#include <linux/scatterlist.h>
#include "zip.h"

9 10 11 12 13 14 15 16 17 18 19 20 21 22
/* hisi_zip_sqe dw3 */
#define HZIP_BD_STATUS_M			GENMASK(7, 0)
/* hisi_zip_sqe dw7 */
#define HZIP_IN_SGE_DATA_OFFSET_M		GENMASK(23, 0)
/* hisi_zip_sqe dw8 */
#define HZIP_OUT_SGE_DATA_OFFSET_M		GENMASK(23, 0)
/* hisi_zip_sqe dw9 */
#define HZIP_REQ_TYPE_M				GENMASK(7, 0)
#define HZIP_ALG_TYPE_ZLIB			0x02
#define HZIP_ALG_TYPE_GZIP			0x03
#define HZIP_BUF_TYPE_M				GENMASK(11, 8)
#define HZIP_PBUFFER				0x0
#define HZIP_SGL				0x1

23 24 25 26 27 28 29 30 31 32
#define HZIP_ZLIB_HEAD_SIZE			2
#define HZIP_GZIP_HEAD_SIZE			10

#define GZIP_HEAD_FHCRC_BIT			BIT(1)
#define GZIP_HEAD_FEXTRA_BIT			BIT(2)
#define GZIP_HEAD_FNAME_BIT			BIT(3)
#define GZIP_HEAD_FCOMMENT_BIT			BIT(4)

#define GZIP_HEAD_FLG_SHIFT			3
#define GZIP_HEAD_FEXTRA_SHIFT			10
33
#define GZIP_HEAD_FEXTRA_XLEN			2UL
34 35 36 37
#define GZIP_HEAD_FHCRC_SIZE			2

#define HZIP_GZIP_HEAD_BUF			256
#define HZIP_ALG_PRIORITY			300
38
#define HZIP_SGL_SGE_NR				10
39 40

static const u8 zlib_head[HZIP_ZLIB_HEAD_SIZE] = {0x78, 0x9c};
41 42 43 44
static const u8 gzip_head[HZIP_GZIP_HEAD_SIZE] = {
	0x1f, 0x8b, 0x08, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x03
};

45 46 47 48 49
enum hisi_zip_alg_type {
	HZIP_ALG_TYPE_COMP = 0,
	HZIP_ALG_TYPE_DECOMP = 1,
};

50 51 52 53 54 55
enum {
	HZIP_QPC_COMP,
	HZIP_QPC_DECOMP,
	HZIP_CTX_Q_NUM
};

56 57 58 59 60 61 62 63 64 65
#define COMP_NAME_TO_TYPE(alg_name)					\
	(!strcmp((alg_name), "zlib-deflate") ? HZIP_ALG_TYPE_ZLIB :	\
	 !strcmp((alg_name), "gzip") ? HZIP_ALG_TYPE_GZIP : 0)		\

#define TO_HEAD_SIZE(req_type)						\
	(((req_type) == HZIP_ALG_TYPE_ZLIB) ? sizeof(zlib_head) :	\
	 ((req_type) == HZIP_ALG_TYPE_GZIP) ? sizeof(gzip_head) : 0)	\

#define TO_HEAD(req_type)						\
	(((req_type) == HZIP_ALG_TYPE_ZLIB) ? zlib_head :		\
66
	 ((req_type) == HZIP_ALG_TYPE_GZIP) ? gzip_head : NULL)		\
67 68 69

struct hisi_zip_req {
	struct acomp_req *req;
70 71
	u32 sskip;
	u32 dskip;
72 73 74 75
	struct hisi_acc_hw_sgl *hw_src;
	struct hisi_acc_hw_sgl *hw_dst;
	dma_addr_t dma_src;
	dma_addr_t dma_dst;
76
	u16 req_id;
77 78 79 80 81 82 83 84 85 86 87 88
};

struct hisi_zip_req_q {
	struct hisi_zip_req *q;
	unsigned long *req_bitmap;
	rwlock_t req_lock;
	u16 size;
};

struct hisi_zip_qp_ctx {
	struct hisi_qp *qp;
	struct hisi_zip_req_q req_q;
89
	struct hisi_acc_sgl_pool *sgl_pool;
90 91 92 93 94 95 96 97
	struct hisi_zip *zip_dev;
	struct hisi_zip_ctx *ctx;
};

struct hisi_zip_ctx {
	struct hisi_zip_qp_ctx qp_ctx[HZIP_CTX_Q_NUM];
};

98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
static int sgl_sge_nr_set(const char *val, const struct kernel_param *kp)
{
	int ret;
	u16 n;

	if (!val)
		return -EINVAL;

	ret = kstrtou16(val, 10, &n);
	if (ret || n == 0 || n > HISI_ACC_SGL_SGE_NR_MAX)
		return -EINVAL;

	return param_set_int(val, kp);
}

static const struct kernel_param_ops sgl_sge_nr_ops = {
	.set = sgl_sge_nr_set,
	.get = param_get_int,
};

static u16 sgl_sge_nr = HZIP_SGL_SGE_NR;
module_param_cb(sgl_sge_nr, &sgl_sge_nr_ops, &sgl_sge_nr, 0444);
MODULE_PARM_DESC(sgl_sge_nr, "Number of sge in sgl(1-255)");

122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
static void hisi_zip_config_buf_type(struct hisi_zip_sqe *sqe, u8 buf_type)
{
	u32 val;

	val = (sqe->dw9) & ~HZIP_BUF_TYPE_M;
	val |= FIELD_PREP(HZIP_BUF_TYPE_M, buf_type);
	sqe->dw9 = val;
}

static void hisi_zip_config_tag(struct hisi_zip_sqe *sqe, u32 tag)
{
	sqe->tag = tag;
}

static void hisi_zip_fill_sqe(struct hisi_zip_sqe *sqe, u8 req_type,
			      dma_addr_t s_addr, dma_addr_t d_addr, u32 slen,
138
			      u32 dlen, u32 sskip, u32 dskip)
139 140 141
{
	memset(sqe, 0, sizeof(struct hisi_zip_sqe));

142 143 144
	sqe->input_data_length = slen - sskip;
	sqe->dw7 = FIELD_PREP(HZIP_IN_SGE_DATA_OFFSET_M, sskip);
	sqe->dw8 = FIELD_PREP(HZIP_OUT_SGE_DATA_OFFSET_M, dskip);
145
	sqe->dw9 = FIELD_PREP(HZIP_REQ_TYPE_M, req_type);
146
	sqe->dest_avail_out = dlen - dskip;
147 148 149 150 151 152
	sqe->source_addr_l = lower_32_bits(s_addr);
	sqe->source_addr_h = upper_32_bits(s_addr);
	sqe->dest_addr_l = lower_32_bits(d_addr);
	sqe->dest_addr_h = upper_32_bits(d_addr);
}

153 154
static int hisi_zip_start_qp(struct hisi_qp *qp, struct hisi_zip_qp_ctx *ctx,
			     int alg_type, int req_type)
155
{
156
	struct device *dev = &qp->qm->pdev->dev;
157 158 159
	int ret;

	qp->req_type = req_type;
160
	qp->alg_type = alg_type;
161 162 163
	qp->qp_ctx = ctx;

	ret = hisi_qm_start_qp(qp, 0);
164
	if (ret < 0) {
165
		dev_err(dev, "failed to start qp (%d)!\n", ret);
166 167
		return ret;
	}
168

169
	ctx->qp = qp;
170

171
	return 0;
172 173 174 175 176 177 178 179
}

static void hisi_zip_release_qp(struct hisi_zip_qp_ctx *ctx)
{
	hisi_qm_stop_qp(ctx->qp);
	hisi_qm_release_qp(ctx->qp);
}

180
static int hisi_zip_ctx_init(struct hisi_zip_ctx *hisi_zip_ctx, u8 req_type, int node)
181
{
182
	struct hisi_qp *qps[HZIP_CTX_Q_NUM] = { NULL };
183 184 185
	struct hisi_zip *hisi_zip;
	int ret, i, j;

186
	ret = zip_create_qps(qps, HZIP_CTX_Q_NUM, node);
187
	if (ret) {
188
		pr_err("failed to create zip qps (%d)!\n", ret);
189 190
		return -ENODEV;
	}
191 192

	hisi_zip = container_of(qps[0]->qm, struct hisi_zip, qm);
193 194 195

	for (i = 0; i < HZIP_CTX_Q_NUM; i++) {
		/* alg_type = 0 for compress, 1 for decompress in hw sqe */
196 197 198 199 200 201 202 203 204
		ret = hisi_zip_start_qp(qps[i], &hisi_zip_ctx->qp_ctx[i], i,
					req_type);
		if (ret) {
			for (j = i - 1; j >= 0; j--)
				hisi_qm_stop_qp(hisi_zip_ctx->qp_ctx[j].qp);

			hisi_qm_free_qps(qps, HZIP_CTX_Q_NUM);
			return ret;
		}
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264

		hisi_zip_ctx->qp_ctx[i].zip_dev = hisi_zip;
	}

	return 0;
}

static void hisi_zip_ctx_exit(struct hisi_zip_ctx *hisi_zip_ctx)
{
	int i;

	for (i = 1; i >= 0; i--)
		hisi_zip_release_qp(&hisi_zip_ctx->qp_ctx[i]);
}

static u16 get_extra_field_size(const u8 *start)
{
	return *((u16 *)start) + GZIP_HEAD_FEXTRA_XLEN;
}

static u32 get_name_field_size(const u8 *start)
{
	return strlen(start) + 1;
}

static u32 get_comment_field_size(const u8 *start)
{
	return strlen(start) + 1;
}

static u32 __get_gzip_head_size(const u8 *src)
{
	u8 head_flg = *(src + GZIP_HEAD_FLG_SHIFT);
	u32 size = GZIP_HEAD_FEXTRA_SHIFT;

	if (head_flg & GZIP_HEAD_FEXTRA_BIT)
		size += get_extra_field_size(src + size);
	if (head_flg & GZIP_HEAD_FNAME_BIT)
		size += get_name_field_size(src + size);
	if (head_flg & GZIP_HEAD_FCOMMENT_BIT)
		size += get_comment_field_size(src + size);
	if (head_flg & GZIP_HEAD_FHCRC_BIT)
		size += GZIP_HEAD_FHCRC_SIZE;

	return size;
}

static int hisi_zip_create_req_q(struct hisi_zip_ctx *ctx)
{
	struct hisi_zip_req_q *req_q;
	int i, ret;

	for (i = 0; i < HZIP_CTX_Q_NUM; i++) {
		req_q = &ctx->qp_ctx[i].req_q;
		req_q->size = QM_Q_DEPTH;

		req_q->req_bitmap = kcalloc(BITS_TO_LONGS(req_q->size),
					    sizeof(long), GFP_KERNEL);
		if (!req_q->req_bitmap) {
			ret = -ENOMEM;
265 266 267 268
			if (i == 0)
				return ret;

			goto err_free_loop0;
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
		}
		rwlock_init(&req_q->req_lock);

		req_q->q = kcalloc(req_q->size, sizeof(struct hisi_zip_req),
				   GFP_KERNEL);
		if (!req_q->q) {
			ret = -ENOMEM;
			if (i == 0)
				goto err_free_bitmap;
			else
				goto err_free_loop1;
		}
	}

	return 0;

err_free_loop1:
286
	kfree(ctx->qp_ctx[HZIP_QPC_DECOMP].req_q.req_bitmap);
287
err_free_loop0:
288
	kfree(ctx->qp_ctx[HZIP_QPC_COMP].req_q.q);
289
err_free_bitmap:
290
	kfree(ctx->qp_ctx[HZIP_QPC_COMP].req_q.req_bitmap);
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
	return ret;
}

static void hisi_zip_release_req_q(struct hisi_zip_ctx *ctx)
{
	int i;

	for (i = 0; i < HZIP_CTX_Q_NUM; i++) {
		kfree(ctx->qp_ctx[i].req_q.q);
		kfree(ctx->qp_ctx[i].req_q.req_bitmap);
	}
}

static int hisi_zip_create_sgl_pool(struct hisi_zip_ctx *ctx)
{
	struct hisi_zip_qp_ctx *tmp;
307 308
	struct device *dev;
	int i;
309 310 311

	for (i = 0; i < HZIP_CTX_Q_NUM; i++) {
		tmp = &ctx->qp_ctx[i];
312 313
		dev = &tmp->qp->qm->pdev->dev;
		tmp->sgl_pool = hisi_acc_create_sgl_pool(dev, QM_Q_DEPTH << 1,
314
							 sgl_sge_nr);
315
		if (IS_ERR(tmp->sgl_pool)) {
316 317 318 319 320 321 322 323 324
			if (i == 1)
				goto err_free_sgl_pool0;
			return -ENOMEM;
		}
	}

	return 0;

err_free_sgl_pool0:
325 326
	hisi_acc_free_sgl_pool(&ctx->qp_ctx[HZIP_QPC_COMP].qp->qm->pdev->dev,
			       ctx->qp_ctx[HZIP_QPC_COMP].sgl_pool);
327 328 329 330 331 332 333 334 335
	return -ENOMEM;
}

static void hisi_zip_release_sgl_pool(struct hisi_zip_ctx *ctx)
{
	int i;

	for (i = 0; i < HZIP_CTX_Q_NUM; i++)
		hisi_acc_free_sgl_pool(&ctx->qp_ctx[i].qp->qm->pdev->dev,
336
				       ctx->qp_ctx[i].sgl_pool);
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
}

static void hisi_zip_remove_req(struct hisi_zip_qp_ctx *qp_ctx,
				struct hisi_zip_req *req)
{
	struct hisi_zip_req_q *req_q = &qp_ctx->req_q;

	write_lock(&req_q->req_lock);
	clear_bit(req->req_id, req_q->req_bitmap);
	memset(req, 0, sizeof(struct hisi_zip_req));
	write_unlock(&req_q->req_lock);
}

static void hisi_zip_acomp_cb(struct hisi_qp *qp, void *data)
{
	struct hisi_zip_sqe *sqe = data;
	struct hisi_zip_qp_ctx *qp_ctx = qp->qp_ctx;
354
	struct hisi_zip_dfx *dfx = &qp_ctx->zip_dev->dfx;
355 356 357 358 359 360 361
	struct hisi_zip_req_q *req_q = &qp_ctx->req_q;
	struct hisi_zip_req *req = req_q->q + sqe->tag;
	struct acomp_req *acomp_req = req->req;
	struct device *dev = &qp->qm->pdev->dev;
	u32 status, dlen, head_size;
	int err = 0;

362
	atomic64_inc(&dfx->recv_cnt);
363 364 365 366 367
	status = sqe->dw3 & HZIP_BD_STATUS_M;
	if (status != 0 && status != HZIP_NC_ERR) {
		dev_err(dev, "%scompress fail in qp%u: %u, output: %u\n",
			(qp->alg_type == 0) ? "" : "de", qp->qp_id, status,
			sqe->produced);
368
		atomic64_inc(&dfx->err_bd_cnt);
369 370 371 372
		err = -EIO;
	}
	dlen = sqe->produced;

373 374
	hisi_acc_sg_buf_unmap(dev, acomp_req->src, req->hw_src);
	hisi_acc_sg_buf_unmap(dev, acomp_req->dst, req->hw_dst);
375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397

	head_size = (qp->alg_type == 0) ? TO_HEAD_SIZE(qp->req_type) : 0;
	acomp_req->dlen = dlen + head_size;

	if (acomp_req->base.complete)
		acomp_request_complete(acomp_req, err);

	hisi_zip_remove_req(qp_ctx, req);
}

static void hisi_zip_set_acomp_cb(struct hisi_zip_ctx *ctx,
				  void (*fn)(struct hisi_qp *, void *))
{
	int i;

	for (i = 0; i < HZIP_CTX_Q_NUM; i++)
		ctx->qp_ctx[i].qp->req_cb = fn;
}

static int hisi_zip_acomp_init(struct crypto_acomp *tfm)
{
	const char *alg_name = crypto_tfm_alg_name(&tfm->base);
	struct hisi_zip_ctx *ctx = crypto_tfm_ctx(&tfm->base);
398
	struct device *dev;
399 400
	int ret;

401
	ret = hisi_zip_ctx_init(ctx, COMP_NAME_TO_TYPE(alg_name), tfm->base.node);
402 403
	if (ret) {
		pr_err("failed to init ctx (%d)!\n", ret);
404
		return ret;
405 406 407
	}

	dev = &ctx->qp_ctx[0].qp->qm->pdev->dev;
408 409

	ret = hisi_zip_create_req_q(ctx);
410 411
	if (ret) {
		dev_err(dev, "failed to create request queue (%d)!\n", ret);
412
		goto err_ctx_exit;
413
	}
414 415

	ret = hisi_zip_create_sgl_pool(ctx);
416 417
	if (ret) {
		dev_err(dev, "failed to create sgl pool (%d)!\n", ret);
418
		goto err_release_req_q;
419
	}
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448

	hisi_zip_set_acomp_cb(ctx, hisi_zip_acomp_cb);

	return 0;

err_release_req_q:
	hisi_zip_release_req_q(ctx);
err_ctx_exit:
	hisi_zip_ctx_exit(ctx);
	return ret;
}

static void hisi_zip_acomp_exit(struct crypto_acomp *tfm)
{
	struct hisi_zip_ctx *ctx = crypto_tfm_ctx(&tfm->base);

	hisi_zip_set_acomp_cb(ctx, NULL);
	hisi_zip_release_sgl_pool(ctx);
	hisi_zip_release_req_q(ctx);
	hisi_zip_ctx_exit(ctx);
}

static int add_comp_head(struct scatterlist *dst, u8 req_type)
{
	int head_size = TO_HEAD_SIZE(req_type);
	const u8 *head = TO_HEAD(req_type);
	int ret;

	ret = sg_copy_from_buffer(dst, sg_nents(dst), head, head_size);
449 450
	if (ret != head_size) {
		pr_err("the head size of buffer is wrong (%d)!\n", ret);
451
		return -ENOMEM;
452
	}
453 454 455 456

	return head_size;
}

457
static size_t __maybe_unused get_gzip_head_size(struct scatterlist *sgl)
458 459 460 461 462 463 464 465
{
	char buf[HZIP_GZIP_HEAD_BUF];

	sg_copy_to_buffer(sgl, sg_nents(sgl), buf, sizeof(buf));

	return __get_gzip_head_size(buf);
}

466
static int  get_comp_head_size(struct acomp_req *acomp_req, u8 req_type)
467
{
468 469 470 471 472 473 474
	if (!acomp_req->src || !acomp_req->slen)
		return -EINVAL;

	if ((req_type == HZIP_ALG_TYPE_GZIP) &&
	    (acomp_req->slen < GZIP_HEAD_FEXTRA_SHIFT))
		return -EINVAL;

475 476 477 478
	switch (req_type) {
	case HZIP_ALG_TYPE_ZLIB:
		return TO_HEAD_SIZE(HZIP_ALG_TYPE_ZLIB);
	case HZIP_ALG_TYPE_GZIP:
479
		return TO_HEAD_SIZE(HZIP_ALG_TYPE_GZIP);
480 481 482 483 484 485 486 487 488 489 490 491 492
	default:
		pr_err("request type does not support!\n");
		return -EINVAL;
	}
}

static struct hisi_zip_req *hisi_zip_create_req(struct acomp_req *req,
						struct hisi_zip_qp_ctx *qp_ctx,
						size_t head_size, bool is_comp)
{
	struct hisi_zip_req_q *req_q = &qp_ctx->req_q;
	struct hisi_zip_req *q = req_q->q;
	struct hisi_zip_req *req_cache;
493
	int req_id;
494 495 496 497 498 499 500

	write_lock(&req_q->req_lock);

	req_id = find_first_zero_bit(req_q->req_bitmap, req_q->size);
	if (req_id >= req_q->size) {
		write_unlock(&req_q->req_lock);
		dev_dbg(&qp_ctx->qp->qm->pdev->dev, "req cache is full!\n");
501
		return ERR_PTR(-EAGAIN);
502 503 504 505 506 507
	}
	set_bit(req_id, req_q->req_bitmap);

	req_cache = q + req_id;
	req_cache->req_id = req_id;
	req_cache->req = req;
508

509
	if (is_comp) {
510 511
		req_cache->sskip = 0;
		req_cache->dskip = head_size;
512
	} else {
513 514
		req_cache->sskip = head_size;
		req_cache->dskip = 0;
515 516 517 518 519 520 521 522 523 524
	}

	write_unlock(&req_q->req_lock);

	return req_cache;
}

static int hisi_zip_do_work(struct hisi_zip_req *req,
			    struct hisi_zip_qp_ctx *qp_ctx)
{
525
	struct acomp_req *a_req = req->req;
526 527
	struct hisi_qp *qp = qp_ctx->qp;
	struct device *dev = &qp->qm->pdev->dev;
528
	struct hisi_acc_sgl_pool *pool = qp_ctx->sgl_pool;
529
	struct hisi_zip_dfx *dfx = &qp_ctx->zip_dev->dfx;
530
	struct hisi_zip_sqe zip_sqe;
531
	dma_addr_t input, output;
532 533
	int ret;

534
	if (!a_req->src || !a_req->slen || !a_req->dst || !a_req->dlen)
535 536
		return -EINVAL;

537
	req->hw_src = hisi_acc_sg_buf_map_to_hw_sgl(dev, a_req->src, pool,
538
						    req->req_id << 1, &input);
539 540 541
	if (IS_ERR(req->hw_src)) {
		dev_err(dev, "failed to map the src buffer to hw sgl (%ld)!\n",
			PTR_ERR(req->hw_src));
542
		return PTR_ERR(req->hw_src);
543
	}
544 545
	req->dma_src = input;

546
	req->hw_dst = hisi_acc_sg_buf_map_to_hw_sgl(dev, a_req->dst, pool,
547 548 549 550
						    (req->req_id << 1) + 1,
						    &output);
	if (IS_ERR(req->hw_dst)) {
		ret = PTR_ERR(req->hw_dst);
551 552
		dev_err(dev, "failed to map the dst buffer to hw slg (%d)!\n",
			ret);
553 554 555 556
		goto err_unmap_input;
	}
	req->dma_dst = output;

557
	hisi_zip_fill_sqe(&zip_sqe, qp->req_type, input, output, a_req->slen,
558
			  a_req->dlen, req->sskip, req->dskip);
559 560
	hisi_zip_config_buf_type(&zip_sqe, HZIP_SGL);
	hisi_zip_config_tag(&zip_sqe, req->req_id);
561 562

	/* send command to start a task */
563
	atomic64_inc(&dfx->send_cnt);
564
	ret = hisi_qp_send(qp, &zip_sqe);
565 566
	if (ret < 0) {
		atomic64_inc(&dfx->send_busy_cnt);
567
		ret = -EAGAIN;
568
		dev_dbg_ratelimited(dev, "failed to send request!\n");
569
		goto err_unmap_output;
570
	}
571 572 573 574

	return -EINPROGRESS;

err_unmap_output:
575
	hisi_acc_sg_buf_unmap(dev, a_req->dst, req->hw_dst);
576
err_unmap_input:
577
	hisi_acc_sg_buf_unmap(dev, a_req->src, req->hw_src);
578 579 580 581 582 583
	return ret;
}

static int hisi_zip_acompress(struct acomp_req *acomp_req)
{
	struct hisi_zip_ctx *ctx = crypto_tfm_ctx(acomp_req->base.tfm);
584
	struct hisi_zip_qp_ctx *qp_ctx = &ctx->qp_ctx[HZIP_QPC_COMP];
585
	struct device *dev = &qp_ctx->qp->qm->pdev->dev;
586
	struct hisi_zip_req *req;
587
	int head_size;
588 589 590 591
	int ret;

	/* let's output compression head now */
	head_size = add_comp_head(acomp_req->dst, qp_ctx->qp->req_type);
592 593 594 595 596
	if (head_size < 0) {
		dev_err_ratelimited(dev, "failed to add comp head (%d)!\n",
				    head_size);
		return head_size;
	}
597

598
	req = hisi_zip_create_req(acomp_req, qp_ctx, head_size, true);
599 600 601 602
	if (IS_ERR(req))
		return PTR_ERR(req);

	ret = hisi_zip_do_work(req, qp_ctx);
603 604
	if (ret != -EINPROGRESS) {
		dev_info_ratelimited(dev, "failed to do compress (%d)!\n", ret);
605
		hisi_zip_remove_req(qp_ctx, req);
606
	}
607 608 609 610 611 612 613

	return ret;
}

static int hisi_zip_adecompress(struct acomp_req *acomp_req)
{
	struct hisi_zip_ctx *ctx = crypto_tfm_ctx(acomp_req->base.tfm);
614
	struct hisi_zip_qp_ctx *qp_ctx = &ctx->qp_ctx[HZIP_QPC_DECOMP];
615
	struct device *dev = &qp_ctx->qp->qm->pdev->dev;
616
	struct hisi_zip_req *req;
617
	int head_size, ret;
618

619 620 621 622 623 624
	head_size = get_comp_head_size(acomp_req, qp_ctx->qp->req_type);
	if (head_size < 0) {
		dev_err_ratelimited(dev, "failed to get comp head size (%d)!\n",
				    head_size);
		return head_size;
	}
625 626 627 628 629 630

	req = hisi_zip_create_req(acomp_req, qp_ctx, head_size, false);
	if (IS_ERR(req))
		return PTR_ERR(req);

	ret = hisi_zip_do_work(req, qp_ctx);
631 632 633
	if (ret != -EINPROGRESS) {
		dev_info_ratelimited(dev, "failed to do decompress (%d)!\n",
				     ret);
634
		hisi_zip_remove_req(qp_ctx, req);
635
	}
636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669

	return ret;
}

static struct acomp_alg hisi_zip_acomp_zlib = {
	.init			= hisi_zip_acomp_init,
	.exit			= hisi_zip_acomp_exit,
	.compress		= hisi_zip_acompress,
	.decompress		= hisi_zip_adecompress,
	.base			= {
		.cra_name		= "zlib-deflate",
		.cra_driver_name	= "hisi-zlib-acomp",
		.cra_module		= THIS_MODULE,
		.cra_priority           = HZIP_ALG_PRIORITY,
		.cra_ctxsize		= sizeof(struct hisi_zip_ctx),
	}
};

static struct acomp_alg hisi_zip_acomp_gzip = {
	.init			= hisi_zip_acomp_init,
	.exit			= hisi_zip_acomp_exit,
	.compress		= hisi_zip_acompress,
	.decompress		= hisi_zip_adecompress,
	.base			= {
		.cra_name		= "gzip",
		.cra_driver_name	= "hisi-gzip-acomp",
		.cra_module		= THIS_MODULE,
		.cra_priority           = HZIP_ALG_PRIORITY,
		.cra_ctxsize		= sizeof(struct hisi_zip_ctx),
	}
};

int hisi_zip_register_to_crypto(void)
{
670
	int ret;
671 672 673

	ret = crypto_register_acomp(&hisi_zip_acomp_zlib);
	if (ret) {
674
		pr_err("failed to register to zlib (%d)!\n", ret);
675 676 677 678 679
		return ret;
	}

	ret = crypto_register_acomp(&hisi_zip_acomp_gzip);
	if (ret) {
680
		pr_err("failed to register to gzip (%d)!\n", ret);
681 682 683 684 685 686 687 688 689 690 691
		crypto_unregister_acomp(&hisi_zip_acomp_zlib);
	}

	return ret;
}

void hisi_zip_unregister_from_crypto(void)
{
	crypto_unregister_acomp(&hisi_zip_acomp_gzip);
	crypto_unregister_acomp(&hisi_zip_acomp_zlib);
}