162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Copyright (c) 2019 HiSilicon Limited. */
362306a36Sopenharmony_ci#include <crypto/internal/acompress.h>
462306a36Sopenharmony_ci#include <linux/bitfield.h>
562306a36Sopenharmony_ci#include <linux/bitmap.h>
662306a36Sopenharmony_ci#include <linux/dma-mapping.h>
762306a36Sopenharmony_ci#include <linux/scatterlist.h>
862306a36Sopenharmony_ci#include "zip.h"
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci/* hisi_zip_sqe dw3 */
1162306a36Sopenharmony_ci#define HZIP_BD_STATUS_M			GENMASK(7, 0)
1262306a36Sopenharmony_ci/* hisi_zip_sqe dw7 */
1362306a36Sopenharmony_ci#define HZIP_IN_SGE_DATA_OFFSET_M		GENMASK(23, 0)
1462306a36Sopenharmony_ci#define HZIP_SQE_TYPE_M				GENMASK(31, 28)
1562306a36Sopenharmony_ci/* hisi_zip_sqe dw8 */
1662306a36Sopenharmony_ci#define HZIP_OUT_SGE_DATA_OFFSET_M		GENMASK(23, 0)
1762306a36Sopenharmony_ci/* hisi_zip_sqe dw9 */
1862306a36Sopenharmony_ci#define HZIP_REQ_TYPE_M				GENMASK(7, 0)
1962306a36Sopenharmony_ci#define HZIP_ALG_TYPE_ZLIB			0x02
2062306a36Sopenharmony_ci#define HZIP_ALG_TYPE_GZIP			0x03
2162306a36Sopenharmony_ci#define HZIP_BUF_TYPE_M				GENMASK(11, 8)
2262306a36Sopenharmony_ci#define HZIP_PBUFFER				0x0
2362306a36Sopenharmony_ci#define HZIP_SGL				0x1
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#define HZIP_ZLIB_HEAD_SIZE			2
2662306a36Sopenharmony_ci#define HZIP_GZIP_HEAD_SIZE			10
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#define GZIP_HEAD_FHCRC_BIT			BIT(1)
2962306a36Sopenharmony_ci#define GZIP_HEAD_FEXTRA_BIT			BIT(2)
3062306a36Sopenharmony_ci#define GZIP_HEAD_FNAME_BIT			BIT(3)
3162306a36Sopenharmony_ci#define GZIP_HEAD_FCOMMENT_BIT			BIT(4)
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#define GZIP_HEAD_FLG_SHIFT			3
3462306a36Sopenharmony_ci#define GZIP_HEAD_FEXTRA_SHIFT			10
3562306a36Sopenharmony_ci#define GZIP_HEAD_FEXTRA_XLEN			2UL
3662306a36Sopenharmony_ci#define GZIP_HEAD_FHCRC_SIZE			2
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci#define HZIP_GZIP_HEAD_BUF			256
3962306a36Sopenharmony_ci#define HZIP_ALG_PRIORITY			300
4062306a36Sopenharmony_ci#define HZIP_SGL_SGE_NR				10
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci#define HZIP_ALG_ZLIB				GENMASK(1, 0)
4362306a36Sopenharmony_ci#define HZIP_ALG_GZIP				GENMASK(3, 2)
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_cistatic const u8 zlib_head[HZIP_ZLIB_HEAD_SIZE] = {0x78, 0x9c};
4662306a36Sopenharmony_cistatic const u8 gzip_head[HZIP_GZIP_HEAD_SIZE] = {
4762306a36Sopenharmony_ci	0x1f, 0x8b, 0x08, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x03
4862306a36Sopenharmony_ci};
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cienum hisi_zip_alg_type {
5162306a36Sopenharmony_ci	HZIP_ALG_TYPE_COMP = 0,
5262306a36Sopenharmony_ci	HZIP_ALG_TYPE_DECOMP = 1,
5362306a36Sopenharmony_ci};
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_cienum {
5662306a36Sopenharmony_ci	HZIP_QPC_COMP,
5762306a36Sopenharmony_ci	HZIP_QPC_DECOMP,
5862306a36Sopenharmony_ci	HZIP_CTX_Q_NUM
5962306a36Sopenharmony_ci};
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci#define COMP_NAME_TO_TYPE(alg_name)					\
6262306a36Sopenharmony_ci	(!strcmp((alg_name), "zlib-deflate") ? HZIP_ALG_TYPE_ZLIB :	\
6362306a36Sopenharmony_ci	 !strcmp((alg_name), "gzip") ? HZIP_ALG_TYPE_GZIP : 0)		\
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci#define TO_HEAD_SIZE(req_type)						\
6662306a36Sopenharmony_ci	(((req_type) == HZIP_ALG_TYPE_ZLIB) ? sizeof(zlib_head) :	\
6762306a36Sopenharmony_ci	 ((req_type) == HZIP_ALG_TYPE_GZIP) ? sizeof(gzip_head) : 0)	\
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci#define TO_HEAD(req_type)						\
7062306a36Sopenharmony_ci	(((req_type) == HZIP_ALG_TYPE_ZLIB) ? zlib_head :		\
7162306a36Sopenharmony_ci	 ((req_type) == HZIP_ALG_TYPE_GZIP) ? gzip_head : NULL)		\
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_cistruct hisi_zip_req {
7462306a36Sopenharmony_ci	struct acomp_req *req;
7562306a36Sopenharmony_ci	u32 sskip;
7662306a36Sopenharmony_ci	u32 dskip;
7762306a36Sopenharmony_ci	struct hisi_acc_hw_sgl *hw_src;
7862306a36Sopenharmony_ci	struct hisi_acc_hw_sgl *hw_dst;
7962306a36Sopenharmony_ci	dma_addr_t dma_src;
8062306a36Sopenharmony_ci	dma_addr_t dma_dst;
8162306a36Sopenharmony_ci	u16 req_id;
8262306a36Sopenharmony_ci};
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_cistruct hisi_zip_req_q {
8562306a36Sopenharmony_ci	struct hisi_zip_req *q;
8662306a36Sopenharmony_ci	unsigned long *req_bitmap;
8762306a36Sopenharmony_ci	rwlock_t req_lock;
8862306a36Sopenharmony_ci	u16 size;
8962306a36Sopenharmony_ci};
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_cistruct hisi_zip_qp_ctx {
9262306a36Sopenharmony_ci	struct hisi_qp *qp;
9362306a36Sopenharmony_ci	struct hisi_zip_req_q req_q;
9462306a36Sopenharmony_ci	struct hisi_acc_sgl_pool *sgl_pool;
9562306a36Sopenharmony_ci	struct hisi_zip *zip_dev;
9662306a36Sopenharmony_ci	struct hisi_zip_ctx *ctx;
9762306a36Sopenharmony_ci};
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cistruct hisi_zip_sqe_ops {
10062306a36Sopenharmony_ci	u8 sqe_type;
10162306a36Sopenharmony_ci	void (*fill_addr)(struct hisi_zip_sqe *sqe, struct hisi_zip_req *req);
10262306a36Sopenharmony_ci	void (*fill_buf_size)(struct hisi_zip_sqe *sqe, struct hisi_zip_req *req);
10362306a36Sopenharmony_ci	void (*fill_buf_type)(struct hisi_zip_sqe *sqe, u8 buf_type);
10462306a36Sopenharmony_ci	void (*fill_req_type)(struct hisi_zip_sqe *sqe, u8 req_type);
10562306a36Sopenharmony_ci	void (*fill_tag)(struct hisi_zip_sqe *sqe, struct hisi_zip_req *req);
10662306a36Sopenharmony_ci	void (*fill_sqe_type)(struct hisi_zip_sqe *sqe, u8 sqe_type);
10762306a36Sopenharmony_ci	u32 (*get_tag)(struct hisi_zip_sqe *sqe);
10862306a36Sopenharmony_ci	u32 (*get_status)(struct hisi_zip_sqe *sqe);
10962306a36Sopenharmony_ci	u32 (*get_dstlen)(struct hisi_zip_sqe *sqe);
11062306a36Sopenharmony_ci};
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_cistruct hisi_zip_ctx {
11362306a36Sopenharmony_ci	struct hisi_zip_qp_ctx qp_ctx[HZIP_CTX_Q_NUM];
11462306a36Sopenharmony_ci	const struct hisi_zip_sqe_ops *ops;
11562306a36Sopenharmony_ci};
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cistatic int sgl_sge_nr_set(const char *val, const struct kernel_param *kp)
11862306a36Sopenharmony_ci{
11962306a36Sopenharmony_ci	int ret;
12062306a36Sopenharmony_ci	u16 n;
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	if (!val)
12362306a36Sopenharmony_ci		return -EINVAL;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	ret = kstrtou16(val, 10, &n);
12662306a36Sopenharmony_ci	if (ret || n == 0 || n > HISI_ACC_SGL_SGE_NR_MAX)
12762306a36Sopenharmony_ci		return -EINVAL;
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci	return param_set_ushort(val, kp);
13062306a36Sopenharmony_ci}
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_cistatic const struct kernel_param_ops sgl_sge_nr_ops = {
13362306a36Sopenharmony_ci	.set = sgl_sge_nr_set,
13462306a36Sopenharmony_ci	.get = param_get_ushort,
13562306a36Sopenharmony_ci};
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_cistatic u16 sgl_sge_nr = HZIP_SGL_SGE_NR;
13862306a36Sopenharmony_cimodule_param_cb(sgl_sge_nr, &sgl_sge_nr_ops, &sgl_sge_nr, 0444);
13962306a36Sopenharmony_ciMODULE_PARM_DESC(sgl_sge_nr, "Number of sge in sgl(1-255)");
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_cistatic u32 get_extra_field_size(const u8 *start)
14262306a36Sopenharmony_ci{
14362306a36Sopenharmony_ci	return *((u16 *)start) + GZIP_HEAD_FEXTRA_XLEN;
14462306a36Sopenharmony_ci}
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_cistatic u32 get_name_field_size(const u8 *start)
14762306a36Sopenharmony_ci{
14862306a36Sopenharmony_ci	return strlen(start) + 1;
14962306a36Sopenharmony_ci}
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_cistatic u32 get_comment_field_size(const u8 *start)
15262306a36Sopenharmony_ci{
15362306a36Sopenharmony_ci	return strlen(start) + 1;
15462306a36Sopenharmony_ci}
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_cistatic u32 __get_gzip_head_size(const u8 *src)
15762306a36Sopenharmony_ci{
15862306a36Sopenharmony_ci	u8 head_flg = *(src + GZIP_HEAD_FLG_SHIFT);
15962306a36Sopenharmony_ci	u32 size = GZIP_HEAD_FEXTRA_SHIFT;
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	if (head_flg & GZIP_HEAD_FEXTRA_BIT)
16262306a36Sopenharmony_ci		size += get_extra_field_size(src + size);
16362306a36Sopenharmony_ci	if (head_flg & GZIP_HEAD_FNAME_BIT)
16462306a36Sopenharmony_ci		size += get_name_field_size(src + size);
16562306a36Sopenharmony_ci	if (head_flg & GZIP_HEAD_FCOMMENT_BIT)
16662306a36Sopenharmony_ci		size += get_comment_field_size(src + size);
16762306a36Sopenharmony_ci	if (head_flg & GZIP_HEAD_FHCRC_BIT)
16862306a36Sopenharmony_ci		size += GZIP_HEAD_FHCRC_SIZE;
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	return size;
17162306a36Sopenharmony_ci}
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_cistatic u32 __maybe_unused get_gzip_head_size(struct scatterlist *sgl)
17462306a36Sopenharmony_ci{
17562306a36Sopenharmony_ci	char buf[HZIP_GZIP_HEAD_BUF];
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	sg_copy_to_buffer(sgl, sg_nents(sgl), buf, sizeof(buf));
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	return __get_gzip_head_size(buf);
18062306a36Sopenharmony_ci}
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_cistatic int add_comp_head(struct scatterlist *dst, u8 req_type)
18362306a36Sopenharmony_ci{
18462306a36Sopenharmony_ci	int head_size = TO_HEAD_SIZE(req_type);
18562306a36Sopenharmony_ci	const u8 *head = TO_HEAD(req_type);
18662306a36Sopenharmony_ci	int ret;
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci	ret = sg_copy_from_buffer(dst, sg_nents(dst), head, head_size);
18962306a36Sopenharmony_ci	if (unlikely(ret != head_size)) {
19062306a36Sopenharmony_ci		pr_err("the head size of buffer is wrong (%d)!\n", ret);
19162306a36Sopenharmony_ci		return -ENOMEM;
19262306a36Sopenharmony_ci	}
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	return head_size;
19562306a36Sopenharmony_ci}
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_cistatic int get_comp_head_size(struct acomp_req *acomp_req, u8 req_type)
19862306a36Sopenharmony_ci{
19962306a36Sopenharmony_ci	if (unlikely(!acomp_req->src || !acomp_req->slen))
20062306a36Sopenharmony_ci		return -EINVAL;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	if (unlikely(req_type == HZIP_ALG_TYPE_GZIP &&
20362306a36Sopenharmony_ci		     acomp_req->slen < GZIP_HEAD_FEXTRA_SHIFT))
20462306a36Sopenharmony_ci		return -EINVAL;
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	switch (req_type) {
20762306a36Sopenharmony_ci	case HZIP_ALG_TYPE_ZLIB:
20862306a36Sopenharmony_ci		return TO_HEAD_SIZE(HZIP_ALG_TYPE_ZLIB);
20962306a36Sopenharmony_ci	case HZIP_ALG_TYPE_GZIP:
21062306a36Sopenharmony_ci		return TO_HEAD_SIZE(HZIP_ALG_TYPE_GZIP);
21162306a36Sopenharmony_ci	default:
21262306a36Sopenharmony_ci		pr_err("request type does not support!\n");
21362306a36Sopenharmony_ci		return -EINVAL;
21462306a36Sopenharmony_ci	}
21562306a36Sopenharmony_ci}
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_cistatic struct hisi_zip_req *hisi_zip_create_req(struct acomp_req *req,
21862306a36Sopenharmony_ci						struct hisi_zip_qp_ctx *qp_ctx,
21962306a36Sopenharmony_ci						size_t head_size, bool is_comp)
22062306a36Sopenharmony_ci{
22162306a36Sopenharmony_ci	struct hisi_zip_req_q *req_q = &qp_ctx->req_q;
22262306a36Sopenharmony_ci	struct hisi_zip_req *q = req_q->q;
22362306a36Sopenharmony_ci	struct hisi_zip_req *req_cache;
22462306a36Sopenharmony_ci	int req_id;
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	write_lock(&req_q->req_lock);
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	req_id = find_first_zero_bit(req_q->req_bitmap, req_q->size);
22962306a36Sopenharmony_ci	if (req_id >= req_q->size) {
23062306a36Sopenharmony_ci		write_unlock(&req_q->req_lock);
23162306a36Sopenharmony_ci		dev_dbg(&qp_ctx->qp->qm->pdev->dev, "req cache is full!\n");
23262306a36Sopenharmony_ci		return ERR_PTR(-EAGAIN);
23362306a36Sopenharmony_ci	}
23462306a36Sopenharmony_ci	set_bit(req_id, req_q->req_bitmap);
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	write_unlock(&req_q->req_lock);
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci	req_cache = q + req_id;
23962306a36Sopenharmony_ci	req_cache->req_id = req_id;
24062306a36Sopenharmony_ci	req_cache->req = req;
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci	if (is_comp) {
24362306a36Sopenharmony_ci		req_cache->sskip = 0;
24462306a36Sopenharmony_ci		req_cache->dskip = head_size;
24562306a36Sopenharmony_ci	} else {
24662306a36Sopenharmony_ci		req_cache->sskip = head_size;
24762306a36Sopenharmony_ci		req_cache->dskip = 0;
24862306a36Sopenharmony_ci	}
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	return req_cache;
25162306a36Sopenharmony_ci}
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_cistatic void hisi_zip_remove_req(struct hisi_zip_qp_ctx *qp_ctx,
25462306a36Sopenharmony_ci				struct hisi_zip_req *req)
25562306a36Sopenharmony_ci{
25662306a36Sopenharmony_ci	struct hisi_zip_req_q *req_q = &qp_ctx->req_q;
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	write_lock(&req_q->req_lock);
25962306a36Sopenharmony_ci	clear_bit(req->req_id, req_q->req_bitmap);
26062306a36Sopenharmony_ci	write_unlock(&req_q->req_lock);
26162306a36Sopenharmony_ci}
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_cistatic void hisi_zip_fill_addr(struct hisi_zip_sqe *sqe, struct hisi_zip_req *req)
26462306a36Sopenharmony_ci{
26562306a36Sopenharmony_ci	sqe->source_addr_l = lower_32_bits(req->dma_src);
26662306a36Sopenharmony_ci	sqe->source_addr_h = upper_32_bits(req->dma_src);
26762306a36Sopenharmony_ci	sqe->dest_addr_l = lower_32_bits(req->dma_dst);
26862306a36Sopenharmony_ci	sqe->dest_addr_h = upper_32_bits(req->dma_dst);
26962306a36Sopenharmony_ci}
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_cistatic void hisi_zip_fill_buf_size(struct hisi_zip_sqe *sqe, struct hisi_zip_req *req)
27262306a36Sopenharmony_ci{
27362306a36Sopenharmony_ci	struct acomp_req *a_req = req->req;
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci	sqe->input_data_length = a_req->slen - req->sskip;
27662306a36Sopenharmony_ci	sqe->dest_avail_out = a_req->dlen - req->dskip;
27762306a36Sopenharmony_ci	sqe->dw7 = FIELD_PREP(HZIP_IN_SGE_DATA_OFFSET_M, req->sskip);
27862306a36Sopenharmony_ci	sqe->dw8 = FIELD_PREP(HZIP_OUT_SGE_DATA_OFFSET_M, req->dskip);
27962306a36Sopenharmony_ci}
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_cistatic void hisi_zip_fill_buf_type(struct hisi_zip_sqe *sqe, u8 buf_type)
28262306a36Sopenharmony_ci{
28362306a36Sopenharmony_ci	u32 val;
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	val = sqe->dw9 & ~HZIP_BUF_TYPE_M;
28662306a36Sopenharmony_ci	val |= FIELD_PREP(HZIP_BUF_TYPE_M, buf_type);
28762306a36Sopenharmony_ci	sqe->dw9 = val;
28862306a36Sopenharmony_ci}
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_cistatic void hisi_zip_fill_req_type(struct hisi_zip_sqe *sqe, u8 req_type)
29162306a36Sopenharmony_ci{
29262306a36Sopenharmony_ci	u32 val;
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	val = sqe->dw9 & ~HZIP_REQ_TYPE_M;
29562306a36Sopenharmony_ci	val |= FIELD_PREP(HZIP_REQ_TYPE_M, req_type);
29662306a36Sopenharmony_ci	sqe->dw9 = val;
29762306a36Sopenharmony_ci}
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_cistatic void hisi_zip_fill_tag_v1(struct hisi_zip_sqe *sqe, struct hisi_zip_req *req)
30062306a36Sopenharmony_ci{
30162306a36Sopenharmony_ci	sqe->dw13 = req->req_id;
30262306a36Sopenharmony_ci}
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_cistatic void hisi_zip_fill_tag_v2(struct hisi_zip_sqe *sqe, struct hisi_zip_req *req)
30562306a36Sopenharmony_ci{
30662306a36Sopenharmony_ci	sqe->dw26 = req->req_id;
30762306a36Sopenharmony_ci}
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_cistatic void hisi_zip_fill_sqe_type(struct hisi_zip_sqe *sqe, u8 sqe_type)
31062306a36Sopenharmony_ci{
31162306a36Sopenharmony_ci	u32 val;
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	val = sqe->dw7 & ~HZIP_SQE_TYPE_M;
31462306a36Sopenharmony_ci	val |= FIELD_PREP(HZIP_SQE_TYPE_M, sqe_type);
31562306a36Sopenharmony_ci	sqe->dw7 = val;
31662306a36Sopenharmony_ci}
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_cistatic void hisi_zip_fill_sqe(struct hisi_zip_ctx *ctx, struct hisi_zip_sqe *sqe,
31962306a36Sopenharmony_ci			      u8 req_type, struct hisi_zip_req *req)
32062306a36Sopenharmony_ci{
32162306a36Sopenharmony_ci	const struct hisi_zip_sqe_ops *ops = ctx->ops;
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci	memset(sqe, 0, sizeof(struct hisi_zip_sqe));
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	ops->fill_addr(sqe, req);
32662306a36Sopenharmony_ci	ops->fill_buf_size(sqe, req);
32762306a36Sopenharmony_ci	ops->fill_buf_type(sqe, HZIP_SGL);
32862306a36Sopenharmony_ci	ops->fill_req_type(sqe, req_type);
32962306a36Sopenharmony_ci	ops->fill_tag(sqe, req);
33062306a36Sopenharmony_ci	ops->fill_sqe_type(sqe, ops->sqe_type);
33162306a36Sopenharmony_ci}
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_cistatic int hisi_zip_do_work(struct hisi_zip_req *req,
33462306a36Sopenharmony_ci			    struct hisi_zip_qp_ctx *qp_ctx)
33562306a36Sopenharmony_ci{
33662306a36Sopenharmony_ci	struct hisi_acc_sgl_pool *pool = qp_ctx->sgl_pool;
33762306a36Sopenharmony_ci	struct hisi_zip_dfx *dfx = &qp_ctx->zip_dev->dfx;
33862306a36Sopenharmony_ci	struct acomp_req *a_req = req->req;
33962306a36Sopenharmony_ci	struct hisi_qp *qp = qp_ctx->qp;
34062306a36Sopenharmony_ci	struct device *dev = &qp->qm->pdev->dev;
34162306a36Sopenharmony_ci	struct hisi_zip_sqe zip_sqe;
34262306a36Sopenharmony_ci	int ret;
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	if (unlikely(!a_req->src || !a_req->slen || !a_req->dst || !a_req->dlen))
34562306a36Sopenharmony_ci		return -EINVAL;
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	req->hw_src = hisi_acc_sg_buf_map_to_hw_sgl(dev, a_req->src, pool,
34862306a36Sopenharmony_ci						    req->req_id << 1, &req->dma_src);
34962306a36Sopenharmony_ci	if (IS_ERR(req->hw_src)) {
35062306a36Sopenharmony_ci		dev_err(dev, "failed to map the src buffer to hw sgl (%ld)!\n",
35162306a36Sopenharmony_ci			PTR_ERR(req->hw_src));
35262306a36Sopenharmony_ci		return PTR_ERR(req->hw_src);
35362306a36Sopenharmony_ci	}
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	req->hw_dst = hisi_acc_sg_buf_map_to_hw_sgl(dev, a_req->dst, pool,
35662306a36Sopenharmony_ci						    (req->req_id << 1) + 1,
35762306a36Sopenharmony_ci						    &req->dma_dst);
35862306a36Sopenharmony_ci	if (IS_ERR(req->hw_dst)) {
35962306a36Sopenharmony_ci		ret = PTR_ERR(req->hw_dst);
36062306a36Sopenharmony_ci		dev_err(dev, "failed to map the dst buffer to hw slg (%d)!\n",
36162306a36Sopenharmony_ci			ret);
36262306a36Sopenharmony_ci		goto err_unmap_input;
36362306a36Sopenharmony_ci	}
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci	hisi_zip_fill_sqe(qp_ctx->ctx, &zip_sqe, qp->req_type, req);
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci	/* send command to start a task */
36862306a36Sopenharmony_ci	atomic64_inc(&dfx->send_cnt);
36962306a36Sopenharmony_ci	ret = hisi_qp_send(qp, &zip_sqe);
37062306a36Sopenharmony_ci	if (unlikely(ret < 0)) {
37162306a36Sopenharmony_ci		atomic64_inc(&dfx->send_busy_cnt);
37262306a36Sopenharmony_ci		ret = -EAGAIN;
37362306a36Sopenharmony_ci		dev_dbg_ratelimited(dev, "failed to send request!\n");
37462306a36Sopenharmony_ci		goto err_unmap_output;
37562306a36Sopenharmony_ci	}
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	return -EINPROGRESS;
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_cierr_unmap_output:
38062306a36Sopenharmony_ci	hisi_acc_sg_buf_unmap(dev, a_req->dst, req->hw_dst);
38162306a36Sopenharmony_cierr_unmap_input:
38262306a36Sopenharmony_ci	hisi_acc_sg_buf_unmap(dev, a_req->src, req->hw_src);
38362306a36Sopenharmony_ci	return ret;
38462306a36Sopenharmony_ci}
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_cistatic u32 hisi_zip_get_tag_v1(struct hisi_zip_sqe *sqe)
38762306a36Sopenharmony_ci{
38862306a36Sopenharmony_ci	return sqe->dw13;
38962306a36Sopenharmony_ci}
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_cistatic u32 hisi_zip_get_tag_v2(struct hisi_zip_sqe *sqe)
39262306a36Sopenharmony_ci{
39362306a36Sopenharmony_ci	return sqe->dw26;
39462306a36Sopenharmony_ci}
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_cistatic u32 hisi_zip_get_status(struct hisi_zip_sqe *sqe)
39762306a36Sopenharmony_ci{
39862306a36Sopenharmony_ci	return sqe->dw3 & HZIP_BD_STATUS_M;
39962306a36Sopenharmony_ci}
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_cistatic u32 hisi_zip_get_dstlen(struct hisi_zip_sqe *sqe)
40262306a36Sopenharmony_ci{
40362306a36Sopenharmony_ci	return sqe->produced;
40462306a36Sopenharmony_ci}
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_cistatic void hisi_zip_acomp_cb(struct hisi_qp *qp, void *data)
40762306a36Sopenharmony_ci{
40862306a36Sopenharmony_ci	struct hisi_zip_qp_ctx *qp_ctx = qp->qp_ctx;
40962306a36Sopenharmony_ci	const struct hisi_zip_sqe_ops *ops = qp_ctx->ctx->ops;
41062306a36Sopenharmony_ci	struct hisi_zip_dfx *dfx = &qp_ctx->zip_dev->dfx;
41162306a36Sopenharmony_ci	struct hisi_zip_req_q *req_q = &qp_ctx->req_q;
41262306a36Sopenharmony_ci	struct device *dev = &qp->qm->pdev->dev;
41362306a36Sopenharmony_ci	struct hisi_zip_sqe *sqe = data;
41462306a36Sopenharmony_ci	u32 tag = ops->get_tag(sqe);
41562306a36Sopenharmony_ci	struct hisi_zip_req *req = req_q->q + tag;
41662306a36Sopenharmony_ci	struct acomp_req *acomp_req = req->req;
41762306a36Sopenharmony_ci	u32 status, dlen, head_size;
41862306a36Sopenharmony_ci	int err = 0;
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci	atomic64_inc(&dfx->recv_cnt);
42162306a36Sopenharmony_ci	status = ops->get_status(sqe);
42262306a36Sopenharmony_ci	if (unlikely(status != 0 && status != HZIP_NC_ERR)) {
42362306a36Sopenharmony_ci		dev_err(dev, "%scompress fail in qp%u: %u, output: %u\n",
42462306a36Sopenharmony_ci			(qp->alg_type == 0) ? "" : "de", qp->qp_id, status,
42562306a36Sopenharmony_ci			sqe->produced);
42662306a36Sopenharmony_ci		atomic64_inc(&dfx->err_bd_cnt);
42762306a36Sopenharmony_ci		err = -EIO;
42862306a36Sopenharmony_ci	}
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci	dlen = ops->get_dstlen(sqe);
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci	hisi_acc_sg_buf_unmap(dev, acomp_req->src, req->hw_src);
43362306a36Sopenharmony_ci	hisi_acc_sg_buf_unmap(dev, acomp_req->dst, req->hw_dst);
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci	head_size = (qp->alg_type == 0) ? TO_HEAD_SIZE(qp->req_type) : 0;
43662306a36Sopenharmony_ci	acomp_req->dlen = dlen + head_size;
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ci	if (acomp_req->base.complete)
43962306a36Sopenharmony_ci		acomp_request_complete(acomp_req, err);
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci	hisi_zip_remove_req(qp_ctx, req);
44262306a36Sopenharmony_ci}
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_cistatic int hisi_zip_acompress(struct acomp_req *acomp_req)
44562306a36Sopenharmony_ci{
44662306a36Sopenharmony_ci	struct hisi_zip_ctx *ctx = crypto_tfm_ctx(acomp_req->base.tfm);
44762306a36Sopenharmony_ci	struct hisi_zip_qp_ctx *qp_ctx = &ctx->qp_ctx[HZIP_QPC_COMP];
44862306a36Sopenharmony_ci	struct device *dev = &qp_ctx->qp->qm->pdev->dev;
44962306a36Sopenharmony_ci	struct hisi_zip_req *req;
45062306a36Sopenharmony_ci	int head_size;
45162306a36Sopenharmony_ci	int ret;
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci	/* let's output compression head now */
45462306a36Sopenharmony_ci	head_size = add_comp_head(acomp_req->dst, qp_ctx->qp->req_type);
45562306a36Sopenharmony_ci	if (unlikely(head_size < 0)) {
45662306a36Sopenharmony_ci		dev_err_ratelimited(dev, "failed to add comp head (%d)!\n",
45762306a36Sopenharmony_ci				    head_size);
45862306a36Sopenharmony_ci		return head_size;
45962306a36Sopenharmony_ci	}
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci	req = hisi_zip_create_req(acomp_req, qp_ctx, head_size, true);
46262306a36Sopenharmony_ci	if (IS_ERR(req))
46362306a36Sopenharmony_ci		return PTR_ERR(req);
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_ci	ret = hisi_zip_do_work(req, qp_ctx);
46662306a36Sopenharmony_ci	if (unlikely(ret != -EINPROGRESS)) {
46762306a36Sopenharmony_ci		dev_info_ratelimited(dev, "failed to do compress (%d)!\n", ret);
46862306a36Sopenharmony_ci		hisi_zip_remove_req(qp_ctx, req);
46962306a36Sopenharmony_ci	}
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_ci	return ret;
47262306a36Sopenharmony_ci}
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_cistatic int hisi_zip_adecompress(struct acomp_req *acomp_req)
47562306a36Sopenharmony_ci{
47662306a36Sopenharmony_ci	struct hisi_zip_ctx *ctx = crypto_tfm_ctx(acomp_req->base.tfm);
47762306a36Sopenharmony_ci	struct hisi_zip_qp_ctx *qp_ctx = &ctx->qp_ctx[HZIP_QPC_DECOMP];
47862306a36Sopenharmony_ci	struct device *dev = &qp_ctx->qp->qm->pdev->dev;
47962306a36Sopenharmony_ci	struct hisi_zip_req *req;
48062306a36Sopenharmony_ci	int head_size, ret;
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	head_size = get_comp_head_size(acomp_req, qp_ctx->qp->req_type);
48362306a36Sopenharmony_ci	if (unlikely(head_size < 0)) {
48462306a36Sopenharmony_ci		dev_err_ratelimited(dev, "failed to get comp head size (%d)!\n",
48562306a36Sopenharmony_ci				    head_size);
48662306a36Sopenharmony_ci		return head_size;
48762306a36Sopenharmony_ci	}
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci	req = hisi_zip_create_req(acomp_req, qp_ctx, head_size, false);
49062306a36Sopenharmony_ci	if (IS_ERR(req))
49162306a36Sopenharmony_ci		return PTR_ERR(req);
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	ret = hisi_zip_do_work(req, qp_ctx);
49462306a36Sopenharmony_ci	if (unlikely(ret != -EINPROGRESS)) {
49562306a36Sopenharmony_ci		dev_info_ratelimited(dev, "failed to do decompress (%d)!\n",
49662306a36Sopenharmony_ci				     ret);
49762306a36Sopenharmony_ci		hisi_zip_remove_req(qp_ctx, req);
49862306a36Sopenharmony_ci	}
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci	return ret;
50162306a36Sopenharmony_ci}
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_cistatic int hisi_zip_start_qp(struct hisi_qp *qp, struct hisi_zip_qp_ctx *qp_ctx,
50462306a36Sopenharmony_ci			     int alg_type, int req_type)
50562306a36Sopenharmony_ci{
50662306a36Sopenharmony_ci	struct device *dev = &qp->qm->pdev->dev;
50762306a36Sopenharmony_ci	int ret;
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci	qp->req_type = req_type;
51062306a36Sopenharmony_ci	qp->alg_type = alg_type;
51162306a36Sopenharmony_ci	qp->qp_ctx = qp_ctx;
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	ret = hisi_qm_start_qp(qp, 0);
51462306a36Sopenharmony_ci	if (ret < 0) {
51562306a36Sopenharmony_ci		dev_err(dev, "failed to start qp (%d)!\n", ret);
51662306a36Sopenharmony_ci		return ret;
51762306a36Sopenharmony_ci	}
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci	qp_ctx->qp = qp;
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci	return 0;
52262306a36Sopenharmony_ci}
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_cistatic void hisi_zip_release_qp(struct hisi_zip_qp_ctx *qp_ctx)
52562306a36Sopenharmony_ci{
52662306a36Sopenharmony_ci	hisi_qm_stop_qp(qp_ctx->qp);
52762306a36Sopenharmony_ci	hisi_qm_free_qps(&qp_ctx->qp, 1);
52862306a36Sopenharmony_ci}
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_cistatic const struct hisi_zip_sqe_ops hisi_zip_ops_v1 = {
53162306a36Sopenharmony_ci	.sqe_type		= 0,
53262306a36Sopenharmony_ci	.fill_addr		= hisi_zip_fill_addr,
53362306a36Sopenharmony_ci	.fill_buf_size		= hisi_zip_fill_buf_size,
53462306a36Sopenharmony_ci	.fill_buf_type		= hisi_zip_fill_buf_type,
53562306a36Sopenharmony_ci	.fill_req_type		= hisi_zip_fill_req_type,
53662306a36Sopenharmony_ci	.fill_tag		= hisi_zip_fill_tag_v1,
53762306a36Sopenharmony_ci	.fill_sqe_type		= hisi_zip_fill_sqe_type,
53862306a36Sopenharmony_ci	.get_tag		= hisi_zip_get_tag_v1,
53962306a36Sopenharmony_ci	.get_status		= hisi_zip_get_status,
54062306a36Sopenharmony_ci	.get_dstlen		= hisi_zip_get_dstlen,
54162306a36Sopenharmony_ci};
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_cistatic const struct hisi_zip_sqe_ops hisi_zip_ops_v2 = {
54462306a36Sopenharmony_ci	.sqe_type		= 0x3,
54562306a36Sopenharmony_ci	.fill_addr		= hisi_zip_fill_addr,
54662306a36Sopenharmony_ci	.fill_buf_size		= hisi_zip_fill_buf_size,
54762306a36Sopenharmony_ci	.fill_buf_type		= hisi_zip_fill_buf_type,
54862306a36Sopenharmony_ci	.fill_req_type		= hisi_zip_fill_req_type,
54962306a36Sopenharmony_ci	.fill_tag		= hisi_zip_fill_tag_v2,
55062306a36Sopenharmony_ci	.fill_sqe_type		= hisi_zip_fill_sqe_type,
55162306a36Sopenharmony_ci	.get_tag		= hisi_zip_get_tag_v2,
55262306a36Sopenharmony_ci	.get_status		= hisi_zip_get_status,
55362306a36Sopenharmony_ci	.get_dstlen		= hisi_zip_get_dstlen,
55462306a36Sopenharmony_ci};
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_cistatic int hisi_zip_ctx_init(struct hisi_zip_ctx *hisi_zip_ctx, u8 req_type, int node)
55762306a36Sopenharmony_ci{
55862306a36Sopenharmony_ci	struct hisi_qp *qps[HZIP_CTX_Q_NUM] = { NULL };
55962306a36Sopenharmony_ci	struct hisi_zip_qp_ctx *qp_ctx;
56062306a36Sopenharmony_ci	struct hisi_zip *hisi_zip;
56162306a36Sopenharmony_ci	int ret, i, j;
56262306a36Sopenharmony_ci
56362306a36Sopenharmony_ci	ret = zip_create_qps(qps, HZIP_CTX_Q_NUM, node);
56462306a36Sopenharmony_ci	if (ret) {
56562306a36Sopenharmony_ci		pr_err("failed to create zip qps (%d)!\n", ret);
56662306a36Sopenharmony_ci		return -ENODEV;
56762306a36Sopenharmony_ci	}
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	hisi_zip = container_of(qps[0]->qm, struct hisi_zip, qm);
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci	for (i = 0; i < HZIP_CTX_Q_NUM; i++) {
57262306a36Sopenharmony_ci		/* alg_type = 0 for compress, 1 for decompress in hw sqe */
57362306a36Sopenharmony_ci		qp_ctx = &hisi_zip_ctx->qp_ctx[i];
57462306a36Sopenharmony_ci		qp_ctx->ctx = hisi_zip_ctx;
57562306a36Sopenharmony_ci		ret = hisi_zip_start_qp(qps[i], qp_ctx, i, req_type);
57662306a36Sopenharmony_ci		if (ret) {
57762306a36Sopenharmony_ci			for (j = i - 1; j >= 0; j--)
57862306a36Sopenharmony_ci				hisi_qm_stop_qp(hisi_zip_ctx->qp_ctx[j].qp);
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci			hisi_qm_free_qps(qps, HZIP_CTX_Q_NUM);
58162306a36Sopenharmony_ci			return ret;
58262306a36Sopenharmony_ci		}
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci		qp_ctx->zip_dev = hisi_zip;
58562306a36Sopenharmony_ci	}
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci	if (hisi_zip->qm.ver < QM_HW_V3)
58862306a36Sopenharmony_ci		hisi_zip_ctx->ops = &hisi_zip_ops_v1;
58962306a36Sopenharmony_ci	else
59062306a36Sopenharmony_ci		hisi_zip_ctx->ops = &hisi_zip_ops_v2;
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci	return 0;
59362306a36Sopenharmony_ci}
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_cistatic void hisi_zip_ctx_exit(struct hisi_zip_ctx *hisi_zip_ctx)
59662306a36Sopenharmony_ci{
59762306a36Sopenharmony_ci	int i;
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci	for (i = 0; i < HZIP_CTX_Q_NUM; i++)
60062306a36Sopenharmony_ci		hisi_zip_release_qp(&hisi_zip_ctx->qp_ctx[i]);
60162306a36Sopenharmony_ci}
60262306a36Sopenharmony_ci
60362306a36Sopenharmony_cistatic int hisi_zip_create_req_q(struct hisi_zip_ctx *ctx)
60462306a36Sopenharmony_ci{
60562306a36Sopenharmony_ci	u16 q_depth = ctx->qp_ctx[0].qp->sq_depth;
60662306a36Sopenharmony_ci	struct hisi_zip_req_q *req_q;
60762306a36Sopenharmony_ci	int i, ret;
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci	for (i = 0; i < HZIP_CTX_Q_NUM; i++) {
61062306a36Sopenharmony_ci		req_q = &ctx->qp_ctx[i].req_q;
61162306a36Sopenharmony_ci		req_q->size = q_depth;
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci		req_q->req_bitmap = bitmap_zalloc(req_q->size, GFP_KERNEL);
61462306a36Sopenharmony_ci		if (!req_q->req_bitmap) {
61562306a36Sopenharmony_ci			ret = -ENOMEM;
61662306a36Sopenharmony_ci			if (i == 0)
61762306a36Sopenharmony_ci				return ret;
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci			goto err_free_comp_q;
62062306a36Sopenharmony_ci		}
62162306a36Sopenharmony_ci		rwlock_init(&req_q->req_lock);
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci		req_q->q = kcalloc(req_q->size, sizeof(struct hisi_zip_req),
62462306a36Sopenharmony_ci				   GFP_KERNEL);
62562306a36Sopenharmony_ci		if (!req_q->q) {
62662306a36Sopenharmony_ci			ret = -ENOMEM;
62762306a36Sopenharmony_ci			if (i == 0)
62862306a36Sopenharmony_ci				goto err_free_comp_bitmap;
62962306a36Sopenharmony_ci			else
63062306a36Sopenharmony_ci				goto err_free_decomp_bitmap;
63162306a36Sopenharmony_ci		}
63262306a36Sopenharmony_ci	}
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci	return 0;
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_cierr_free_decomp_bitmap:
63762306a36Sopenharmony_ci	bitmap_free(ctx->qp_ctx[HZIP_QPC_DECOMP].req_q.req_bitmap);
63862306a36Sopenharmony_cierr_free_comp_q:
63962306a36Sopenharmony_ci	kfree(ctx->qp_ctx[HZIP_QPC_COMP].req_q.q);
64062306a36Sopenharmony_cierr_free_comp_bitmap:
64162306a36Sopenharmony_ci	bitmap_free(ctx->qp_ctx[HZIP_QPC_COMP].req_q.req_bitmap);
64262306a36Sopenharmony_ci	return ret;
64362306a36Sopenharmony_ci}
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_cistatic void hisi_zip_release_req_q(struct hisi_zip_ctx *ctx)
64662306a36Sopenharmony_ci{
64762306a36Sopenharmony_ci	int i;
64862306a36Sopenharmony_ci
64962306a36Sopenharmony_ci	for (i = 0; i < HZIP_CTX_Q_NUM; i++) {
65062306a36Sopenharmony_ci		kfree(ctx->qp_ctx[i].req_q.q);
65162306a36Sopenharmony_ci		bitmap_free(ctx->qp_ctx[i].req_q.req_bitmap);
65262306a36Sopenharmony_ci	}
65362306a36Sopenharmony_ci}
65462306a36Sopenharmony_ci
65562306a36Sopenharmony_cistatic int hisi_zip_create_sgl_pool(struct hisi_zip_ctx *ctx)
65662306a36Sopenharmony_ci{
65762306a36Sopenharmony_ci	u16 q_depth = ctx->qp_ctx[0].qp->sq_depth;
65862306a36Sopenharmony_ci	struct hisi_zip_qp_ctx *tmp;
65962306a36Sopenharmony_ci	struct device *dev;
66062306a36Sopenharmony_ci	int i;
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_ci	for (i = 0; i < HZIP_CTX_Q_NUM; i++) {
66362306a36Sopenharmony_ci		tmp = &ctx->qp_ctx[i];
66462306a36Sopenharmony_ci		dev = &tmp->qp->qm->pdev->dev;
66562306a36Sopenharmony_ci		tmp->sgl_pool = hisi_acc_create_sgl_pool(dev, q_depth << 1,
66662306a36Sopenharmony_ci							 sgl_sge_nr);
66762306a36Sopenharmony_ci		if (IS_ERR(tmp->sgl_pool)) {
66862306a36Sopenharmony_ci			if (i == 1)
66962306a36Sopenharmony_ci				goto err_free_sgl_pool0;
67062306a36Sopenharmony_ci			return -ENOMEM;
67162306a36Sopenharmony_ci		}
67262306a36Sopenharmony_ci	}
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_ci	return 0;
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_cierr_free_sgl_pool0:
67762306a36Sopenharmony_ci	hisi_acc_free_sgl_pool(&ctx->qp_ctx[HZIP_QPC_COMP].qp->qm->pdev->dev,
67862306a36Sopenharmony_ci			       ctx->qp_ctx[HZIP_QPC_COMP].sgl_pool);
67962306a36Sopenharmony_ci	return -ENOMEM;
68062306a36Sopenharmony_ci}
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_cistatic void hisi_zip_release_sgl_pool(struct hisi_zip_ctx *ctx)
68362306a36Sopenharmony_ci{
68462306a36Sopenharmony_ci	int i;
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ci	for (i = 0; i < HZIP_CTX_Q_NUM; i++)
68762306a36Sopenharmony_ci		hisi_acc_free_sgl_pool(&ctx->qp_ctx[i].qp->qm->pdev->dev,
68862306a36Sopenharmony_ci				       ctx->qp_ctx[i].sgl_pool);
68962306a36Sopenharmony_ci}
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_cistatic void hisi_zip_set_acomp_cb(struct hisi_zip_ctx *ctx,
69262306a36Sopenharmony_ci				  void (*fn)(struct hisi_qp *, void *))
69362306a36Sopenharmony_ci{
69462306a36Sopenharmony_ci	int i;
69562306a36Sopenharmony_ci
69662306a36Sopenharmony_ci	for (i = 0; i < HZIP_CTX_Q_NUM; i++)
69762306a36Sopenharmony_ci		ctx->qp_ctx[i].qp->req_cb = fn;
69862306a36Sopenharmony_ci}
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_cistatic int hisi_zip_acomp_init(struct crypto_acomp *tfm)
70162306a36Sopenharmony_ci{
70262306a36Sopenharmony_ci	const char *alg_name = crypto_tfm_alg_name(&tfm->base);
70362306a36Sopenharmony_ci	struct hisi_zip_ctx *ctx = crypto_tfm_ctx(&tfm->base);
70462306a36Sopenharmony_ci	struct device *dev;
70562306a36Sopenharmony_ci	int ret;
70662306a36Sopenharmony_ci
70762306a36Sopenharmony_ci	ret = hisi_zip_ctx_init(ctx, COMP_NAME_TO_TYPE(alg_name), tfm->base.node);
70862306a36Sopenharmony_ci	if (ret) {
70962306a36Sopenharmony_ci		pr_err("failed to init ctx (%d)!\n", ret);
71062306a36Sopenharmony_ci		return ret;
71162306a36Sopenharmony_ci	}
71262306a36Sopenharmony_ci
71362306a36Sopenharmony_ci	dev = &ctx->qp_ctx[0].qp->qm->pdev->dev;
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_ci	ret = hisi_zip_create_req_q(ctx);
71662306a36Sopenharmony_ci	if (ret) {
71762306a36Sopenharmony_ci		dev_err(dev, "failed to create request queue (%d)!\n", ret);
71862306a36Sopenharmony_ci		goto err_ctx_exit;
71962306a36Sopenharmony_ci	}
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_ci	ret = hisi_zip_create_sgl_pool(ctx);
72262306a36Sopenharmony_ci	if (ret) {
72362306a36Sopenharmony_ci		dev_err(dev, "failed to create sgl pool (%d)!\n", ret);
72462306a36Sopenharmony_ci		goto err_release_req_q;
72562306a36Sopenharmony_ci	}
72662306a36Sopenharmony_ci
72762306a36Sopenharmony_ci	hisi_zip_set_acomp_cb(ctx, hisi_zip_acomp_cb);
72862306a36Sopenharmony_ci
72962306a36Sopenharmony_ci	return 0;
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_cierr_release_req_q:
73262306a36Sopenharmony_ci	hisi_zip_release_req_q(ctx);
73362306a36Sopenharmony_cierr_ctx_exit:
73462306a36Sopenharmony_ci	hisi_zip_ctx_exit(ctx);
73562306a36Sopenharmony_ci	return ret;
73662306a36Sopenharmony_ci}
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_cistatic void hisi_zip_acomp_exit(struct crypto_acomp *tfm)
73962306a36Sopenharmony_ci{
74062306a36Sopenharmony_ci	struct hisi_zip_ctx *ctx = crypto_tfm_ctx(&tfm->base);
74162306a36Sopenharmony_ci
74262306a36Sopenharmony_ci	hisi_zip_set_acomp_cb(ctx, NULL);
74362306a36Sopenharmony_ci	hisi_zip_release_sgl_pool(ctx);
74462306a36Sopenharmony_ci	hisi_zip_release_req_q(ctx);
74562306a36Sopenharmony_ci	hisi_zip_ctx_exit(ctx);
74662306a36Sopenharmony_ci}
74762306a36Sopenharmony_ci
74862306a36Sopenharmony_cistatic struct acomp_alg hisi_zip_acomp_zlib = {
74962306a36Sopenharmony_ci	.init			= hisi_zip_acomp_init,
75062306a36Sopenharmony_ci	.exit			= hisi_zip_acomp_exit,
75162306a36Sopenharmony_ci	.compress		= hisi_zip_acompress,
75262306a36Sopenharmony_ci	.decompress		= hisi_zip_adecompress,
75362306a36Sopenharmony_ci	.base			= {
75462306a36Sopenharmony_ci		.cra_name		= "zlib-deflate",
75562306a36Sopenharmony_ci		.cra_driver_name	= "hisi-zlib-acomp",
75662306a36Sopenharmony_ci		.cra_module		= THIS_MODULE,
75762306a36Sopenharmony_ci		.cra_priority           = HZIP_ALG_PRIORITY,
75862306a36Sopenharmony_ci		.cra_ctxsize		= sizeof(struct hisi_zip_ctx),
75962306a36Sopenharmony_ci	}
76062306a36Sopenharmony_ci};
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_cistatic int hisi_zip_register_zlib(struct hisi_qm *qm)
76362306a36Sopenharmony_ci{
76462306a36Sopenharmony_ci	int ret;
76562306a36Sopenharmony_ci
76662306a36Sopenharmony_ci	if (!hisi_zip_alg_support(qm, HZIP_ALG_ZLIB))
76762306a36Sopenharmony_ci		return 0;
76862306a36Sopenharmony_ci
76962306a36Sopenharmony_ci	ret = crypto_register_acomp(&hisi_zip_acomp_zlib);
77062306a36Sopenharmony_ci	if (ret)
77162306a36Sopenharmony_ci		dev_err(&qm->pdev->dev, "failed to register to zlib (%d)!\n", ret);
77262306a36Sopenharmony_ci
77362306a36Sopenharmony_ci	return ret;
77462306a36Sopenharmony_ci}
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_cistatic void hisi_zip_unregister_zlib(struct hisi_qm *qm)
77762306a36Sopenharmony_ci{
77862306a36Sopenharmony_ci	if (!hisi_zip_alg_support(qm, HZIP_ALG_ZLIB))
77962306a36Sopenharmony_ci		return;
78062306a36Sopenharmony_ci
78162306a36Sopenharmony_ci	crypto_unregister_acomp(&hisi_zip_acomp_zlib);
78262306a36Sopenharmony_ci}
78362306a36Sopenharmony_ci
78462306a36Sopenharmony_cistatic struct acomp_alg hisi_zip_acomp_gzip = {
78562306a36Sopenharmony_ci	.init			= hisi_zip_acomp_init,
78662306a36Sopenharmony_ci	.exit			= hisi_zip_acomp_exit,
78762306a36Sopenharmony_ci	.compress		= hisi_zip_acompress,
78862306a36Sopenharmony_ci	.decompress		= hisi_zip_adecompress,
78962306a36Sopenharmony_ci	.base			= {
79062306a36Sopenharmony_ci		.cra_name		= "gzip",
79162306a36Sopenharmony_ci		.cra_driver_name	= "hisi-gzip-acomp",
79262306a36Sopenharmony_ci		.cra_module		= THIS_MODULE,
79362306a36Sopenharmony_ci		.cra_priority           = HZIP_ALG_PRIORITY,
79462306a36Sopenharmony_ci		.cra_ctxsize		= sizeof(struct hisi_zip_ctx),
79562306a36Sopenharmony_ci	}
79662306a36Sopenharmony_ci};
79762306a36Sopenharmony_ci
79862306a36Sopenharmony_cistatic int hisi_zip_register_gzip(struct hisi_qm *qm)
79962306a36Sopenharmony_ci{
80062306a36Sopenharmony_ci	int ret;
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ci	if (!hisi_zip_alg_support(qm, HZIP_ALG_GZIP))
80362306a36Sopenharmony_ci		return 0;
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_ci	ret = crypto_register_acomp(&hisi_zip_acomp_gzip);
80662306a36Sopenharmony_ci	if (ret)
80762306a36Sopenharmony_ci		dev_err(&qm->pdev->dev, "failed to register to gzip (%d)!\n", ret);
80862306a36Sopenharmony_ci
80962306a36Sopenharmony_ci	return ret;
81062306a36Sopenharmony_ci}
81162306a36Sopenharmony_ci
81262306a36Sopenharmony_cistatic void hisi_zip_unregister_gzip(struct hisi_qm *qm)
81362306a36Sopenharmony_ci{
81462306a36Sopenharmony_ci	if (!hisi_zip_alg_support(qm, HZIP_ALG_GZIP))
81562306a36Sopenharmony_ci		return;
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_ci	crypto_unregister_acomp(&hisi_zip_acomp_gzip);
81862306a36Sopenharmony_ci}
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_ciint hisi_zip_register_to_crypto(struct hisi_qm *qm)
82162306a36Sopenharmony_ci{
82262306a36Sopenharmony_ci	int ret = 0;
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_ci	ret = hisi_zip_register_zlib(qm);
82562306a36Sopenharmony_ci	if (ret)
82662306a36Sopenharmony_ci		return ret;
82762306a36Sopenharmony_ci
82862306a36Sopenharmony_ci	ret = hisi_zip_register_gzip(qm);
82962306a36Sopenharmony_ci	if (ret)
83062306a36Sopenharmony_ci		hisi_zip_unregister_zlib(qm);
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci	return ret;
83362306a36Sopenharmony_ci}
83462306a36Sopenharmony_ci
83562306a36Sopenharmony_civoid hisi_zip_unregister_from_crypto(struct hisi_qm *qm)
83662306a36Sopenharmony_ci{
83762306a36Sopenharmony_ci	hisi_zip_unregister_zlib(qm);
83862306a36Sopenharmony_ci	hisi_zip_unregister_gzip(qm);
83962306a36Sopenharmony_ci}
840