18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/* Copyright (c) 2019 HiSilicon Limited. */
38c2ecf20Sopenharmony_ci#include <crypto/internal/acompress.h>
48c2ecf20Sopenharmony_ci#include <linux/bitfield.h>
58c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h>
68c2ecf20Sopenharmony_ci#include <linux/scatterlist.h>
78c2ecf20Sopenharmony_ci#include "zip.h"
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci/* hisi_zip_sqe dw3 */
108c2ecf20Sopenharmony_ci#define HZIP_BD_STATUS_M			GENMASK(7, 0)
118c2ecf20Sopenharmony_ci/* hisi_zip_sqe dw7 */
128c2ecf20Sopenharmony_ci#define HZIP_IN_SGE_DATA_OFFSET_M		GENMASK(23, 0)
138c2ecf20Sopenharmony_ci/* hisi_zip_sqe dw8 */
148c2ecf20Sopenharmony_ci#define HZIP_OUT_SGE_DATA_OFFSET_M		GENMASK(23, 0)
158c2ecf20Sopenharmony_ci/* hisi_zip_sqe dw9 */
168c2ecf20Sopenharmony_ci#define HZIP_REQ_TYPE_M				GENMASK(7, 0)
178c2ecf20Sopenharmony_ci#define HZIP_ALG_TYPE_ZLIB			0x02
188c2ecf20Sopenharmony_ci#define HZIP_ALG_TYPE_GZIP			0x03
198c2ecf20Sopenharmony_ci#define HZIP_BUF_TYPE_M				GENMASK(11, 8)
208c2ecf20Sopenharmony_ci#define HZIP_PBUFFER				0x0
218c2ecf20Sopenharmony_ci#define HZIP_SGL				0x1
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#define HZIP_ZLIB_HEAD_SIZE			2
248c2ecf20Sopenharmony_ci#define HZIP_GZIP_HEAD_SIZE			10
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#define GZIP_HEAD_FHCRC_BIT			BIT(1)
278c2ecf20Sopenharmony_ci#define GZIP_HEAD_FEXTRA_BIT			BIT(2)
288c2ecf20Sopenharmony_ci#define GZIP_HEAD_FNAME_BIT			BIT(3)
298c2ecf20Sopenharmony_ci#define GZIP_HEAD_FCOMMENT_BIT			BIT(4)
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci#define GZIP_HEAD_FLG_SHIFT			3
328c2ecf20Sopenharmony_ci#define GZIP_HEAD_FEXTRA_SHIFT			10
338c2ecf20Sopenharmony_ci#define GZIP_HEAD_FEXTRA_XLEN			2UL
348c2ecf20Sopenharmony_ci#define GZIP_HEAD_FHCRC_SIZE			2
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#define HZIP_GZIP_HEAD_BUF			256
378c2ecf20Sopenharmony_ci#define HZIP_ALG_PRIORITY			300
388c2ecf20Sopenharmony_ci#define HZIP_SGL_SGE_NR				10
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_cistatic const u8 zlib_head[HZIP_ZLIB_HEAD_SIZE] = {0x78, 0x9c};
418c2ecf20Sopenharmony_cistatic const u8 gzip_head[HZIP_GZIP_HEAD_SIZE] = {
428c2ecf20Sopenharmony_ci	0x1f, 0x8b, 0x08, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x03
438c2ecf20Sopenharmony_ci};
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_cienum hisi_zip_alg_type {
468c2ecf20Sopenharmony_ci	HZIP_ALG_TYPE_COMP = 0,
478c2ecf20Sopenharmony_ci	HZIP_ALG_TYPE_DECOMP = 1,
488c2ecf20Sopenharmony_ci};
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_cienum {
518c2ecf20Sopenharmony_ci	HZIP_QPC_COMP,
528c2ecf20Sopenharmony_ci	HZIP_QPC_DECOMP,
538c2ecf20Sopenharmony_ci	HZIP_CTX_Q_NUM
548c2ecf20Sopenharmony_ci};
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci#define COMP_NAME_TO_TYPE(alg_name)					\
578c2ecf20Sopenharmony_ci	(!strcmp((alg_name), "zlib-deflate") ? HZIP_ALG_TYPE_ZLIB :	\
588c2ecf20Sopenharmony_ci	 !strcmp((alg_name), "gzip") ? HZIP_ALG_TYPE_GZIP : 0)		\
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci#define TO_HEAD_SIZE(req_type)						\
618c2ecf20Sopenharmony_ci	(((req_type) == HZIP_ALG_TYPE_ZLIB) ? sizeof(zlib_head) :	\
628c2ecf20Sopenharmony_ci	 ((req_type) == HZIP_ALG_TYPE_GZIP) ? sizeof(gzip_head) : 0)	\
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci#define TO_HEAD(req_type)						\
658c2ecf20Sopenharmony_ci	(((req_type) == HZIP_ALG_TYPE_ZLIB) ? zlib_head :		\
668c2ecf20Sopenharmony_ci	 ((req_type) == HZIP_ALG_TYPE_GZIP) ? gzip_head : NULL)		\
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_cistruct hisi_zip_req {
698c2ecf20Sopenharmony_ci	struct acomp_req *req;
708c2ecf20Sopenharmony_ci	u32 sskip;
718c2ecf20Sopenharmony_ci	u32 dskip;
728c2ecf20Sopenharmony_ci	struct hisi_acc_hw_sgl *hw_src;
738c2ecf20Sopenharmony_ci	struct hisi_acc_hw_sgl *hw_dst;
748c2ecf20Sopenharmony_ci	dma_addr_t dma_src;
758c2ecf20Sopenharmony_ci	dma_addr_t dma_dst;
768c2ecf20Sopenharmony_ci	u16 req_id;
778c2ecf20Sopenharmony_ci};
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_cistruct hisi_zip_req_q {
808c2ecf20Sopenharmony_ci	struct hisi_zip_req *q;
818c2ecf20Sopenharmony_ci	unsigned long *req_bitmap;
828c2ecf20Sopenharmony_ci	rwlock_t req_lock;
838c2ecf20Sopenharmony_ci	u16 size;
848c2ecf20Sopenharmony_ci};
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_cistruct hisi_zip_qp_ctx {
878c2ecf20Sopenharmony_ci	struct hisi_qp *qp;
888c2ecf20Sopenharmony_ci	struct hisi_zip_req_q req_q;
898c2ecf20Sopenharmony_ci	struct hisi_acc_sgl_pool *sgl_pool;
908c2ecf20Sopenharmony_ci	struct hisi_zip *zip_dev;
918c2ecf20Sopenharmony_ci	struct hisi_zip_ctx *ctx;
928c2ecf20Sopenharmony_ci};
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_cistruct hisi_zip_ctx {
958c2ecf20Sopenharmony_ci	struct hisi_zip_qp_ctx qp_ctx[HZIP_CTX_Q_NUM];
968c2ecf20Sopenharmony_ci};
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_cistatic int sgl_sge_nr_set(const char *val, const struct kernel_param *kp)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	int ret;
1018c2ecf20Sopenharmony_ci	u16 n;
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	if (!val)
1048c2ecf20Sopenharmony_ci		return -EINVAL;
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci	ret = kstrtou16(val, 10, &n);
1078c2ecf20Sopenharmony_ci	if (ret || n == 0 || n > HISI_ACC_SGL_SGE_NR_MAX)
1088c2ecf20Sopenharmony_ci		return -EINVAL;
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	return param_set_ushort(val, kp);
1118c2ecf20Sopenharmony_ci}
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_cistatic const struct kernel_param_ops sgl_sge_nr_ops = {
1148c2ecf20Sopenharmony_ci	.set = sgl_sge_nr_set,
1158c2ecf20Sopenharmony_ci	.get = param_get_ushort,
1168c2ecf20Sopenharmony_ci};
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_cistatic u16 sgl_sge_nr = HZIP_SGL_SGE_NR;
1198c2ecf20Sopenharmony_cimodule_param_cb(sgl_sge_nr, &sgl_sge_nr_ops, &sgl_sge_nr, 0444);
1208c2ecf20Sopenharmony_ciMODULE_PARM_DESC(sgl_sge_nr, "Number of sge in sgl(1-255)");
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_cistatic void hisi_zip_config_buf_type(struct hisi_zip_sqe *sqe, u8 buf_type)
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	u32 val;
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	val = (sqe->dw9) & ~HZIP_BUF_TYPE_M;
1278c2ecf20Sopenharmony_ci	val |= FIELD_PREP(HZIP_BUF_TYPE_M, buf_type);
1288c2ecf20Sopenharmony_ci	sqe->dw9 = val;
1298c2ecf20Sopenharmony_ci}
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_cistatic void hisi_zip_config_tag(struct hisi_zip_sqe *sqe, u32 tag)
1328c2ecf20Sopenharmony_ci{
1338c2ecf20Sopenharmony_ci	sqe->tag = tag;
1348c2ecf20Sopenharmony_ci}
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_cistatic void hisi_zip_fill_sqe(struct hisi_zip_sqe *sqe, u8 req_type,
1378c2ecf20Sopenharmony_ci			      dma_addr_t s_addr, dma_addr_t d_addr, u32 slen,
1388c2ecf20Sopenharmony_ci			      u32 dlen, u32 sskip, u32 dskip)
1398c2ecf20Sopenharmony_ci{
1408c2ecf20Sopenharmony_ci	memset(sqe, 0, sizeof(struct hisi_zip_sqe));
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	sqe->input_data_length = slen - sskip;
1438c2ecf20Sopenharmony_ci	sqe->dw7 = FIELD_PREP(HZIP_IN_SGE_DATA_OFFSET_M, sskip);
1448c2ecf20Sopenharmony_ci	sqe->dw8 = FIELD_PREP(HZIP_OUT_SGE_DATA_OFFSET_M, dskip);
1458c2ecf20Sopenharmony_ci	sqe->dw9 = FIELD_PREP(HZIP_REQ_TYPE_M, req_type);
1468c2ecf20Sopenharmony_ci	sqe->dest_avail_out = dlen - dskip;
1478c2ecf20Sopenharmony_ci	sqe->source_addr_l = lower_32_bits(s_addr);
1488c2ecf20Sopenharmony_ci	sqe->source_addr_h = upper_32_bits(s_addr);
1498c2ecf20Sopenharmony_ci	sqe->dest_addr_l = lower_32_bits(d_addr);
1508c2ecf20Sopenharmony_ci	sqe->dest_addr_h = upper_32_bits(d_addr);
1518c2ecf20Sopenharmony_ci}
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_cistatic int hisi_zip_start_qp(struct hisi_qp *qp, struct hisi_zip_qp_ctx *ctx,
1548c2ecf20Sopenharmony_ci			     int alg_type, int req_type)
1558c2ecf20Sopenharmony_ci{
1568c2ecf20Sopenharmony_ci	struct device *dev = &qp->qm->pdev->dev;
1578c2ecf20Sopenharmony_ci	int ret;
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci	qp->req_type = req_type;
1608c2ecf20Sopenharmony_ci	qp->alg_type = alg_type;
1618c2ecf20Sopenharmony_ci	qp->qp_ctx = ctx;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	ret = hisi_qm_start_qp(qp, 0);
1648c2ecf20Sopenharmony_ci	if (ret < 0) {
1658c2ecf20Sopenharmony_ci		dev_err(dev, "failed to start qp (%d)!\n", ret);
1668c2ecf20Sopenharmony_ci		return ret;
1678c2ecf20Sopenharmony_ci	}
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci	ctx->qp = qp;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	return 0;
1728c2ecf20Sopenharmony_ci}
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_cistatic void hisi_zip_release_qp(struct hisi_zip_qp_ctx *ctx)
1758c2ecf20Sopenharmony_ci{
1768c2ecf20Sopenharmony_ci	hisi_qm_stop_qp(ctx->qp);
1778c2ecf20Sopenharmony_ci	hisi_qm_release_qp(ctx->qp);
1788c2ecf20Sopenharmony_ci}
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_cistatic int hisi_zip_ctx_init(struct hisi_zip_ctx *hisi_zip_ctx, u8 req_type, int node)
1818c2ecf20Sopenharmony_ci{
1828c2ecf20Sopenharmony_ci	struct hisi_qp *qps[HZIP_CTX_Q_NUM] = { NULL };
1838c2ecf20Sopenharmony_ci	struct hisi_zip *hisi_zip;
1848c2ecf20Sopenharmony_ci	int ret, i, j;
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	ret = zip_create_qps(qps, HZIP_CTX_Q_NUM, node);
1878c2ecf20Sopenharmony_ci	if (ret) {
1888c2ecf20Sopenharmony_ci		pr_err("failed to create zip qps (%d)!\n", ret);
1898c2ecf20Sopenharmony_ci		return -ENODEV;
1908c2ecf20Sopenharmony_ci	}
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	hisi_zip = container_of(qps[0]->qm, struct hisi_zip, qm);
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci	for (i = 0; i < HZIP_CTX_Q_NUM; i++) {
1958c2ecf20Sopenharmony_ci		/* alg_type = 0 for compress, 1 for decompress in hw sqe */
1968c2ecf20Sopenharmony_ci		ret = hisi_zip_start_qp(qps[i], &hisi_zip_ctx->qp_ctx[i], i,
1978c2ecf20Sopenharmony_ci					req_type);
1988c2ecf20Sopenharmony_ci		if (ret) {
1998c2ecf20Sopenharmony_ci			for (j = i - 1; j >= 0; j--)
2008c2ecf20Sopenharmony_ci				hisi_qm_stop_qp(hisi_zip_ctx->qp_ctx[j].qp);
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci			hisi_qm_free_qps(qps, HZIP_CTX_Q_NUM);
2038c2ecf20Sopenharmony_ci			return ret;
2048c2ecf20Sopenharmony_ci		}
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci		hisi_zip_ctx->qp_ctx[i].zip_dev = hisi_zip;
2078c2ecf20Sopenharmony_ci	}
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	return 0;
2108c2ecf20Sopenharmony_ci}
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_cistatic void hisi_zip_ctx_exit(struct hisi_zip_ctx *hisi_zip_ctx)
2138c2ecf20Sopenharmony_ci{
2148c2ecf20Sopenharmony_ci	int i;
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	for (i = 1; i >= 0; i--)
2178c2ecf20Sopenharmony_ci		hisi_zip_release_qp(&hisi_zip_ctx->qp_ctx[i]);
2188c2ecf20Sopenharmony_ci}
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_cistatic u16 get_extra_field_size(const u8 *start)
2218c2ecf20Sopenharmony_ci{
2228c2ecf20Sopenharmony_ci	return *((u16 *)start) + GZIP_HEAD_FEXTRA_XLEN;
2238c2ecf20Sopenharmony_ci}
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_cistatic u32 get_name_field_size(const u8 *start)
2268c2ecf20Sopenharmony_ci{
2278c2ecf20Sopenharmony_ci	return strlen(start) + 1;
2288c2ecf20Sopenharmony_ci}
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_cistatic u32 get_comment_field_size(const u8 *start)
2318c2ecf20Sopenharmony_ci{
2328c2ecf20Sopenharmony_ci	return strlen(start) + 1;
2338c2ecf20Sopenharmony_ci}
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_cistatic u32 __get_gzip_head_size(const u8 *src)
2368c2ecf20Sopenharmony_ci{
2378c2ecf20Sopenharmony_ci	u8 head_flg = *(src + GZIP_HEAD_FLG_SHIFT);
2388c2ecf20Sopenharmony_ci	u32 size = GZIP_HEAD_FEXTRA_SHIFT;
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	if (head_flg & GZIP_HEAD_FEXTRA_BIT)
2418c2ecf20Sopenharmony_ci		size += get_extra_field_size(src + size);
2428c2ecf20Sopenharmony_ci	if (head_flg & GZIP_HEAD_FNAME_BIT)
2438c2ecf20Sopenharmony_ci		size += get_name_field_size(src + size);
2448c2ecf20Sopenharmony_ci	if (head_flg & GZIP_HEAD_FCOMMENT_BIT)
2458c2ecf20Sopenharmony_ci		size += get_comment_field_size(src + size);
2468c2ecf20Sopenharmony_ci	if (head_flg & GZIP_HEAD_FHCRC_BIT)
2478c2ecf20Sopenharmony_ci		size += GZIP_HEAD_FHCRC_SIZE;
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	return size;
2508c2ecf20Sopenharmony_ci}
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_cistatic int hisi_zip_create_req_q(struct hisi_zip_ctx *ctx)
2538c2ecf20Sopenharmony_ci{
2548c2ecf20Sopenharmony_ci	struct hisi_zip_req_q *req_q;
2558c2ecf20Sopenharmony_ci	int i, ret;
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	for (i = 0; i < HZIP_CTX_Q_NUM; i++) {
2588c2ecf20Sopenharmony_ci		req_q = &ctx->qp_ctx[i].req_q;
2598c2ecf20Sopenharmony_ci		req_q->size = QM_Q_DEPTH;
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci		req_q->req_bitmap = kcalloc(BITS_TO_LONGS(req_q->size),
2628c2ecf20Sopenharmony_ci					    sizeof(long), GFP_KERNEL);
2638c2ecf20Sopenharmony_ci		if (!req_q->req_bitmap) {
2648c2ecf20Sopenharmony_ci			ret = -ENOMEM;
2658c2ecf20Sopenharmony_ci			if (i == 0)
2668c2ecf20Sopenharmony_ci				return ret;
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci			goto err_free_loop0;
2698c2ecf20Sopenharmony_ci		}
2708c2ecf20Sopenharmony_ci		rwlock_init(&req_q->req_lock);
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci		req_q->q = kcalloc(req_q->size, sizeof(struct hisi_zip_req),
2738c2ecf20Sopenharmony_ci				   GFP_KERNEL);
2748c2ecf20Sopenharmony_ci		if (!req_q->q) {
2758c2ecf20Sopenharmony_ci			ret = -ENOMEM;
2768c2ecf20Sopenharmony_ci			if (i == 0)
2778c2ecf20Sopenharmony_ci				goto err_free_bitmap;
2788c2ecf20Sopenharmony_ci			else
2798c2ecf20Sopenharmony_ci				goto err_free_loop1;
2808c2ecf20Sopenharmony_ci		}
2818c2ecf20Sopenharmony_ci	}
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci	return 0;
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_cierr_free_loop1:
2868c2ecf20Sopenharmony_ci	kfree(ctx->qp_ctx[HZIP_QPC_DECOMP].req_q.req_bitmap);
2878c2ecf20Sopenharmony_cierr_free_loop0:
2888c2ecf20Sopenharmony_ci	kfree(ctx->qp_ctx[HZIP_QPC_COMP].req_q.q);
2898c2ecf20Sopenharmony_cierr_free_bitmap:
2908c2ecf20Sopenharmony_ci	kfree(ctx->qp_ctx[HZIP_QPC_COMP].req_q.req_bitmap);
2918c2ecf20Sopenharmony_ci	return ret;
2928c2ecf20Sopenharmony_ci}
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_cistatic void hisi_zip_release_req_q(struct hisi_zip_ctx *ctx)
2958c2ecf20Sopenharmony_ci{
2968c2ecf20Sopenharmony_ci	int i;
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	for (i = 0; i < HZIP_CTX_Q_NUM; i++) {
2998c2ecf20Sopenharmony_ci		kfree(ctx->qp_ctx[i].req_q.q);
3008c2ecf20Sopenharmony_ci		kfree(ctx->qp_ctx[i].req_q.req_bitmap);
3018c2ecf20Sopenharmony_ci	}
3028c2ecf20Sopenharmony_ci}
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_cistatic int hisi_zip_create_sgl_pool(struct hisi_zip_ctx *ctx)
3058c2ecf20Sopenharmony_ci{
3068c2ecf20Sopenharmony_ci	struct hisi_zip_qp_ctx *tmp;
3078c2ecf20Sopenharmony_ci	struct device *dev;
3088c2ecf20Sopenharmony_ci	int i;
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	for (i = 0; i < HZIP_CTX_Q_NUM; i++) {
3118c2ecf20Sopenharmony_ci		tmp = &ctx->qp_ctx[i];
3128c2ecf20Sopenharmony_ci		dev = &tmp->qp->qm->pdev->dev;
3138c2ecf20Sopenharmony_ci		tmp->sgl_pool = hisi_acc_create_sgl_pool(dev, QM_Q_DEPTH << 1,
3148c2ecf20Sopenharmony_ci							 sgl_sge_nr);
3158c2ecf20Sopenharmony_ci		if (IS_ERR(tmp->sgl_pool)) {
3168c2ecf20Sopenharmony_ci			if (i == 1)
3178c2ecf20Sopenharmony_ci				goto err_free_sgl_pool0;
3188c2ecf20Sopenharmony_ci			return -ENOMEM;
3198c2ecf20Sopenharmony_ci		}
3208c2ecf20Sopenharmony_ci	}
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	return 0;
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_cierr_free_sgl_pool0:
3258c2ecf20Sopenharmony_ci	hisi_acc_free_sgl_pool(&ctx->qp_ctx[HZIP_QPC_COMP].qp->qm->pdev->dev,
3268c2ecf20Sopenharmony_ci			       ctx->qp_ctx[HZIP_QPC_COMP].sgl_pool);
3278c2ecf20Sopenharmony_ci	return -ENOMEM;
3288c2ecf20Sopenharmony_ci}
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_cistatic void hisi_zip_release_sgl_pool(struct hisi_zip_ctx *ctx)
3318c2ecf20Sopenharmony_ci{
3328c2ecf20Sopenharmony_ci	int i;
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci	for (i = 0; i < HZIP_CTX_Q_NUM; i++)
3358c2ecf20Sopenharmony_ci		hisi_acc_free_sgl_pool(&ctx->qp_ctx[i].qp->qm->pdev->dev,
3368c2ecf20Sopenharmony_ci				       ctx->qp_ctx[i].sgl_pool);
3378c2ecf20Sopenharmony_ci}
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_cistatic void hisi_zip_remove_req(struct hisi_zip_qp_ctx *qp_ctx,
3408c2ecf20Sopenharmony_ci				struct hisi_zip_req *req)
3418c2ecf20Sopenharmony_ci{
3428c2ecf20Sopenharmony_ci	struct hisi_zip_req_q *req_q = &qp_ctx->req_q;
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci	write_lock(&req_q->req_lock);
3458c2ecf20Sopenharmony_ci	clear_bit(req->req_id, req_q->req_bitmap);
3468c2ecf20Sopenharmony_ci	memset(req, 0, sizeof(struct hisi_zip_req));
3478c2ecf20Sopenharmony_ci	write_unlock(&req_q->req_lock);
3488c2ecf20Sopenharmony_ci}
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_cistatic void hisi_zip_acomp_cb(struct hisi_qp *qp, void *data)
3518c2ecf20Sopenharmony_ci{
3528c2ecf20Sopenharmony_ci	struct hisi_zip_sqe *sqe = data;
3538c2ecf20Sopenharmony_ci	struct hisi_zip_qp_ctx *qp_ctx = qp->qp_ctx;
3548c2ecf20Sopenharmony_ci	struct hisi_zip_dfx *dfx = &qp_ctx->zip_dev->dfx;
3558c2ecf20Sopenharmony_ci	struct hisi_zip_req_q *req_q = &qp_ctx->req_q;
3568c2ecf20Sopenharmony_ci	struct hisi_zip_req *req = req_q->q + sqe->tag;
3578c2ecf20Sopenharmony_ci	struct acomp_req *acomp_req = req->req;
3588c2ecf20Sopenharmony_ci	struct device *dev = &qp->qm->pdev->dev;
3598c2ecf20Sopenharmony_ci	u32 status, dlen, head_size;
3608c2ecf20Sopenharmony_ci	int err = 0;
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	atomic64_inc(&dfx->recv_cnt);
3638c2ecf20Sopenharmony_ci	status = sqe->dw3 & HZIP_BD_STATUS_M;
3648c2ecf20Sopenharmony_ci	if (status != 0 && status != HZIP_NC_ERR) {
3658c2ecf20Sopenharmony_ci		dev_err(dev, "%scompress fail in qp%u: %u, output: %u\n",
3668c2ecf20Sopenharmony_ci			(qp->alg_type == 0) ? "" : "de", qp->qp_id, status,
3678c2ecf20Sopenharmony_ci			sqe->produced);
3688c2ecf20Sopenharmony_ci		atomic64_inc(&dfx->err_bd_cnt);
3698c2ecf20Sopenharmony_ci		err = -EIO;
3708c2ecf20Sopenharmony_ci	}
3718c2ecf20Sopenharmony_ci	dlen = sqe->produced;
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci	hisi_acc_sg_buf_unmap(dev, acomp_req->src, req->hw_src);
3748c2ecf20Sopenharmony_ci	hisi_acc_sg_buf_unmap(dev, acomp_req->dst, req->hw_dst);
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	head_size = (qp->alg_type == 0) ? TO_HEAD_SIZE(qp->req_type) : 0;
3778c2ecf20Sopenharmony_ci	acomp_req->dlen = dlen + head_size;
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci	if (acomp_req->base.complete)
3808c2ecf20Sopenharmony_ci		acomp_request_complete(acomp_req, err);
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	hisi_zip_remove_req(qp_ctx, req);
3838c2ecf20Sopenharmony_ci}
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_cistatic void hisi_zip_set_acomp_cb(struct hisi_zip_ctx *ctx,
3868c2ecf20Sopenharmony_ci				  void (*fn)(struct hisi_qp *, void *))
3878c2ecf20Sopenharmony_ci{
3888c2ecf20Sopenharmony_ci	int i;
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	for (i = 0; i < HZIP_CTX_Q_NUM; i++)
3918c2ecf20Sopenharmony_ci		ctx->qp_ctx[i].qp->req_cb = fn;
3928c2ecf20Sopenharmony_ci}
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_cistatic int hisi_zip_acomp_init(struct crypto_acomp *tfm)
3958c2ecf20Sopenharmony_ci{
3968c2ecf20Sopenharmony_ci	const char *alg_name = crypto_tfm_alg_name(&tfm->base);
3978c2ecf20Sopenharmony_ci	struct hisi_zip_ctx *ctx = crypto_tfm_ctx(&tfm->base);
3988c2ecf20Sopenharmony_ci	struct device *dev;
3998c2ecf20Sopenharmony_ci	int ret;
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci	ret = hisi_zip_ctx_init(ctx, COMP_NAME_TO_TYPE(alg_name), tfm->base.node);
4028c2ecf20Sopenharmony_ci	if (ret) {
4038c2ecf20Sopenharmony_ci		pr_err("failed to init ctx (%d)!\n", ret);
4048c2ecf20Sopenharmony_ci		return ret;
4058c2ecf20Sopenharmony_ci	}
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	dev = &ctx->qp_ctx[0].qp->qm->pdev->dev;
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	ret = hisi_zip_create_req_q(ctx);
4108c2ecf20Sopenharmony_ci	if (ret) {
4118c2ecf20Sopenharmony_ci		dev_err(dev, "failed to create request queue (%d)!\n", ret);
4128c2ecf20Sopenharmony_ci		goto err_ctx_exit;
4138c2ecf20Sopenharmony_ci	}
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	ret = hisi_zip_create_sgl_pool(ctx);
4168c2ecf20Sopenharmony_ci	if (ret) {
4178c2ecf20Sopenharmony_ci		dev_err(dev, "failed to create sgl pool (%d)!\n", ret);
4188c2ecf20Sopenharmony_ci		goto err_release_req_q;
4198c2ecf20Sopenharmony_ci	}
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	hisi_zip_set_acomp_cb(ctx, hisi_zip_acomp_cb);
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci	return 0;
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_cierr_release_req_q:
4268c2ecf20Sopenharmony_ci	hisi_zip_release_req_q(ctx);
4278c2ecf20Sopenharmony_cierr_ctx_exit:
4288c2ecf20Sopenharmony_ci	hisi_zip_ctx_exit(ctx);
4298c2ecf20Sopenharmony_ci	return ret;
4308c2ecf20Sopenharmony_ci}
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_cistatic void hisi_zip_acomp_exit(struct crypto_acomp *tfm)
4338c2ecf20Sopenharmony_ci{
4348c2ecf20Sopenharmony_ci	struct hisi_zip_ctx *ctx = crypto_tfm_ctx(&tfm->base);
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	hisi_zip_set_acomp_cb(ctx, NULL);
4378c2ecf20Sopenharmony_ci	hisi_zip_release_sgl_pool(ctx);
4388c2ecf20Sopenharmony_ci	hisi_zip_release_req_q(ctx);
4398c2ecf20Sopenharmony_ci	hisi_zip_ctx_exit(ctx);
4408c2ecf20Sopenharmony_ci}
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_cistatic int add_comp_head(struct scatterlist *dst, u8 req_type)
4438c2ecf20Sopenharmony_ci{
4448c2ecf20Sopenharmony_ci	int head_size = TO_HEAD_SIZE(req_type);
4458c2ecf20Sopenharmony_ci	const u8 *head = TO_HEAD(req_type);
4468c2ecf20Sopenharmony_ci	int ret;
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci	ret = sg_copy_from_buffer(dst, sg_nents(dst), head, head_size);
4498c2ecf20Sopenharmony_ci	if (ret != head_size) {
4508c2ecf20Sopenharmony_ci		pr_err("the head size of buffer is wrong (%d)!\n", ret);
4518c2ecf20Sopenharmony_ci		return -ENOMEM;
4528c2ecf20Sopenharmony_ci	}
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	return head_size;
4558c2ecf20Sopenharmony_ci}
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_cistatic size_t __maybe_unused get_gzip_head_size(struct scatterlist *sgl)
4588c2ecf20Sopenharmony_ci{
4598c2ecf20Sopenharmony_ci	char buf[HZIP_GZIP_HEAD_BUF];
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci	sg_copy_to_buffer(sgl, sg_nents(sgl), buf, sizeof(buf));
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci	return __get_gzip_head_size(buf);
4648c2ecf20Sopenharmony_ci}
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_cistatic int  get_comp_head_size(struct acomp_req *acomp_req, u8 req_type)
4678c2ecf20Sopenharmony_ci{
4688c2ecf20Sopenharmony_ci	if (!acomp_req->src || !acomp_req->slen)
4698c2ecf20Sopenharmony_ci		return -EINVAL;
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	if ((req_type == HZIP_ALG_TYPE_GZIP) &&
4728c2ecf20Sopenharmony_ci	    (acomp_req->slen < GZIP_HEAD_FEXTRA_SHIFT))
4738c2ecf20Sopenharmony_ci		return -EINVAL;
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	switch (req_type) {
4768c2ecf20Sopenharmony_ci	case HZIP_ALG_TYPE_ZLIB:
4778c2ecf20Sopenharmony_ci		return TO_HEAD_SIZE(HZIP_ALG_TYPE_ZLIB);
4788c2ecf20Sopenharmony_ci	case HZIP_ALG_TYPE_GZIP:
4798c2ecf20Sopenharmony_ci		return TO_HEAD_SIZE(HZIP_ALG_TYPE_GZIP);
4808c2ecf20Sopenharmony_ci	default:
4818c2ecf20Sopenharmony_ci		pr_err("request type does not support!\n");
4828c2ecf20Sopenharmony_ci		return -EINVAL;
4838c2ecf20Sopenharmony_ci	}
4848c2ecf20Sopenharmony_ci}
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_cistatic struct hisi_zip_req *hisi_zip_create_req(struct acomp_req *req,
4878c2ecf20Sopenharmony_ci						struct hisi_zip_qp_ctx *qp_ctx,
4888c2ecf20Sopenharmony_ci						size_t head_size, bool is_comp)
4898c2ecf20Sopenharmony_ci{
4908c2ecf20Sopenharmony_ci	struct hisi_zip_req_q *req_q = &qp_ctx->req_q;
4918c2ecf20Sopenharmony_ci	struct hisi_zip_req *q = req_q->q;
4928c2ecf20Sopenharmony_ci	struct hisi_zip_req *req_cache;
4938c2ecf20Sopenharmony_ci	int req_id;
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci	write_lock(&req_q->req_lock);
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci	req_id = find_first_zero_bit(req_q->req_bitmap, req_q->size);
4988c2ecf20Sopenharmony_ci	if (req_id >= req_q->size) {
4998c2ecf20Sopenharmony_ci		write_unlock(&req_q->req_lock);
5008c2ecf20Sopenharmony_ci		dev_dbg(&qp_ctx->qp->qm->pdev->dev, "req cache is full!\n");
5018c2ecf20Sopenharmony_ci		return ERR_PTR(-EAGAIN);
5028c2ecf20Sopenharmony_ci	}
5038c2ecf20Sopenharmony_ci	set_bit(req_id, req_q->req_bitmap);
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci	req_cache = q + req_id;
5068c2ecf20Sopenharmony_ci	req_cache->req_id = req_id;
5078c2ecf20Sopenharmony_ci	req_cache->req = req;
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci	if (is_comp) {
5108c2ecf20Sopenharmony_ci		req_cache->sskip = 0;
5118c2ecf20Sopenharmony_ci		req_cache->dskip = head_size;
5128c2ecf20Sopenharmony_ci	} else {
5138c2ecf20Sopenharmony_ci		req_cache->sskip = head_size;
5148c2ecf20Sopenharmony_ci		req_cache->dskip = 0;
5158c2ecf20Sopenharmony_ci	}
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci	write_unlock(&req_q->req_lock);
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	return req_cache;
5208c2ecf20Sopenharmony_ci}
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_cistatic int hisi_zip_do_work(struct hisi_zip_req *req,
5238c2ecf20Sopenharmony_ci			    struct hisi_zip_qp_ctx *qp_ctx)
5248c2ecf20Sopenharmony_ci{
5258c2ecf20Sopenharmony_ci	struct acomp_req *a_req = req->req;
5268c2ecf20Sopenharmony_ci	struct hisi_qp *qp = qp_ctx->qp;
5278c2ecf20Sopenharmony_ci	struct device *dev = &qp->qm->pdev->dev;
5288c2ecf20Sopenharmony_ci	struct hisi_acc_sgl_pool *pool = qp_ctx->sgl_pool;
5298c2ecf20Sopenharmony_ci	struct hisi_zip_dfx *dfx = &qp_ctx->zip_dev->dfx;
5308c2ecf20Sopenharmony_ci	struct hisi_zip_sqe zip_sqe;
5318c2ecf20Sopenharmony_ci	dma_addr_t input, output;
5328c2ecf20Sopenharmony_ci	int ret;
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci	if (!a_req->src || !a_req->slen || !a_req->dst || !a_req->dlen)
5358c2ecf20Sopenharmony_ci		return -EINVAL;
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci	req->hw_src = hisi_acc_sg_buf_map_to_hw_sgl(dev, a_req->src, pool,
5388c2ecf20Sopenharmony_ci						    req->req_id << 1, &input);
5398c2ecf20Sopenharmony_ci	if (IS_ERR(req->hw_src)) {
5408c2ecf20Sopenharmony_ci		dev_err(dev, "failed to map the src buffer to hw sgl (%ld)!\n",
5418c2ecf20Sopenharmony_ci			PTR_ERR(req->hw_src));
5428c2ecf20Sopenharmony_ci		return PTR_ERR(req->hw_src);
5438c2ecf20Sopenharmony_ci	}
5448c2ecf20Sopenharmony_ci	req->dma_src = input;
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ci	req->hw_dst = hisi_acc_sg_buf_map_to_hw_sgl(dev, a_req->dst, pool,
5478c2ecf20Sopenharmony_ci						    (req->req_id << 1) + 1,
5488c2ecf20Sopenharmony_ci						    &output);
5498c2ecf20Sopenharmony_ci	if (IS_ERR(req->hw_dst)) {
5508c2ecf20Sopenharmony_ci		ret = PTR_ERR(req->hw_dst);
5518c2ecf20Sopenharmony_ci		dev_err(dev, "failed to map the dst buffer to hw slg (%d)!\n",
5528c2ecf20Sopenharmony_ci			ret);
5538c2ecf20Sopenharmony_ci		goto err_unmap_input;
5548c2ecf20Sopenharmony_ci	}
5558c2ecf20Sopenharmony_ci	req->dma_dst = output;
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	hisi_zip_fill_sqe(&zip_sqe, qp->req_type, input, output, a_req->slen,
5588c2ecf20Sopenharmony_ci			  a_req->dlen, req->sskip, req->dskip);
5598c2ecf20Sopenharmony_ci	hisi_zip_config_buf_type(&zip_sqe, HZIP_SGL);
5608c2ecf20Sopenharmony_ci	hisi_zip_config_tag(&zip_sqe, req->req_id);
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci	/* send command to start a task */
5638c2ecf20Sopenharmony_ci	atomic64_inc(&dfx->send_cnt);
5648c2ecf20Sopenharmony_ci	ret = hisi_qp_send(qp, &zip_sqe);
5658c2ecf20Sopenharmony_ci	if (ret < 0) {
5668c2ecf20Sopenharmony_ci		atomic64_inc(&dfx->send_busy_cnt);
5678c2ecf20Sopenharmony_ci		ret = -EAGAIN;
5688c2ecf20Sopenharmony_ci		dev_dbg_ratelimited(dev, "failed to send request!\n");
5698c2ecf20Sopenharmony_ci		goto err_unmap_output;
5708c2ecf20Sopenharmony_ci	}
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci	return -EINPROGRESS;
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_cierr_unmap_output:
5758c2ecf20Sopenharmony_ci	hisi_acc_sg_buf_unmap(dev, a_req->dst, req->hw_dst);
5768c2ecf20Sopenharmony_cierr_unmap_input:
5778c2ecf20Sopenharmony_ci	hisi_acc_sg_buf_unmap(dev, a_req->src, req->hw_src);
5788c2ecf20Sopenharmony_ci	return ret;
5798c2ecf20Sopenharmony_ci}
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_cistatic int hisi_zip_acompress(struct acomp_req *acomp_req)
5828c2ecf20Sopenharmony_ci{
5838c2ecf20Sopenharmony_ci	struct hisi_zip_ctx *ctx = crypto_tfm_ctx(acomp_req->base.tfm);
5848c2ecf20Sopenharmony_ci	struct hisi_zip_qp_ctx *qp_ctx = &ctx->qp_ctx[HZIP_QPC_COMP];
5858c2ecf20Sopenharmony_ci	struct device *dev = &qp_ctx->qp->qm->pdev->dev;
5868c2ecf20Sopenharmony_ci	struct hisi_zip_req *req;
5878c2ecf20Sopenharmony_ci	int head_size;
5888c2ecf20Sopenharmony_ci	int ret;
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	/* let's output compression head now */
5918c2ecf20Sopenharmony_ci	head_size = add_comp_head(acomp_req->dst, qp_ctx->qp->req_type);
5928c2ecf20Sopenharmony_ci	if (head_size < 0) {
5938c2ecf20Sopenharmony_ci		dev_err_ratelimited(dev, "failed to add comp head (%d)!\n",
5948c2ecf20Sopenharmony_ci				    head_size);
5958c2ecf20Sopenharmony_ci		return head_size;
5968c2ecf20Sopenharmony_ci	}
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci	req = hisi_zip_create_req(acomp_req, qp_ctx, head_size, true);
5998c2ecf20Sopenharmony_ci	if (IS_ERR(req))
6008c2ecf20Sopenharmony_ci		return PTR_ERR(req);
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	ret = hisi_zip_do_work(req, qp_ctx);
6038c2ecf20Sopenharmony_ci	if (ret != -EINPROGRESS) {
6048c2ecf20Sopenharmony_ci		dev_info_ratelimited(dev, "failed to do compress (%d)!\n", ret);
6058c2ecf20Sopenharmony_ci		hisi_zip_remove_req(qp_ctx, req);
6068c2ecf20Sopenharmony_ci	}
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_ci	return ret;
6098c2ecf20Sopenharmony_ci}
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_cistatic int hisi_zip_adecompress(struct acomp_req *acomp_req)
6128c2ecf20Sopenharmony_ci{
6138c2ecf20Sopenharmony_ci	struct hisi_zip_ctx *ctx = crypto_tfm_ctx(acomp_req->base.tfm);
6148c2ecf20Sopenharmony_ci	struct hisi_zip_qp_ctx *qp_ctx = &ctx->qp_ctx[HZIP_QPC_DECOMP];
6158c2ecf20Sopenharmony_ci	struct device *dev = &qp_ctx->qp->qm->pdev->dev;
6168c2ecf20Sopenharmony_ci	struct hisi_zip_req *req;
6178c2ecf20Sopenharmony_ci	int head_size, ret;
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	head_size = get_comp_head_size(acomp_req, qp_ctx->qp->req_type);
6208c2ecf20Sopenharmony_ci	if (head_size < 0) {
6218c2ecf20Sopenharmony_ci		dev_err_ratelimited(dev, "failed to get comp head size (%d)!\n",
6228c2ecf20Sopenharmony_ci				    head_size);
6238c2ecf20Sopenharmony_ci		return head_size;
6248c2ecf20Sopenharmony_ci	}
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ci	req = hisi_zip_create_req(acomp_req, qp_ctx, head_size, false);
6278c2ecf20Sopenharmony_ci	if (IS_ERR(req))
6288c2ecf20Sopenharmony_ci		return PTR_ERR(req);
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci	ret = hisi_zip_do_work(req, qp_ctx);
6318c2ecf20Sopenharmony_ci	if (ret != -EINPROGRESS) {
6328c2ecf20Sopenharmony_ci		dev_info_ratelimited(dev, "failed to do decompress (%d)!\n",
6338c2ecf20Sopenharmony_ci				     ret);
6348c2ecf20Sopenharmony_ci		hisi_zip_remove_req(qp_ctx, req);
6358c2ecf20Sopenharmony_ci	}
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci	return ret;
6388c2ecf20Sopenharmony_ci}
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_cistatic struct acomp_alg hisi_zip_acomp_zlib = {
6418c2ecf20Sopenharmony_ci	.init			= hisi_zip_acomp_init,
6428c2ecf20Sopenharmony_ci	.exit			= hisi_zip_acomp_exit,
6438c2ecf20Sopenharmony_ci	.compress		= hisi_zip_acompress,
6448c2ecf20Sopenharmony_ci	.decompress		= hisi_zip_adecompress,
6458c2ecf20Sopenharmony_ci	.base			= {
6468c2ecf20Sopenharmony_ci		.cra_name		= "zlib-deflate",
6478c2ecf20Sopenharmony_ci		.cra_driver_name	= "hisi-zlib-acomp",
6488c2ecf20Sopenharmony_ci		.cra_module		= THIS_MODULE,
6498c2ecf20Sopenharmony_ci		.cra_priority           = HZIP_ALG_PRIORITY,
6508c2ecf20Sopenharmony_ci		.cra_ctxsize		= sizeof(struct hisi_zip_ctx),
6518c2ecf20Sopenharmony_ci	}
6528c2ecf20Sopenharmony_ci};
6538c2ecf20Sopenharmony_ci
6548c2ecf20Sopenharmony_cistatic struct acomp_alg hisi_zip_acomp_gzip = {
6558c2ecf20Sopenharmony_ci	.init			= hisi_zip_acomp_init,
6568c2ecf20Sopenharmony_ci	.exit			= hisi_zip_acomp_exit,
6578c2ecf20Sopenharmony_ci	.compress		= hisi_zip_acompress,
6588c2ecf20Sopenharmony_ci	.decompress		= hisi_zip_adecompress,
6598c2ecf20Sopenharmony_ci	.base			= {
6608c2ecf20Sopenharmony_ci		.cra_name		= "gzip",
6618c2ecf20Sopenharmony_ci		.cra_driver_name	= "hisi-gzip-acomp",
6628c2ecf20Sopenharmony_ci		.cra_module		= THIS_MODULE,
6638c2ecf20Sopenharmony_ci		.cra_priority           = HZIP_ALG_PRIORITY,
6648c2ecf20Sopenharmony_ci		.cra_ctxsize		= sizeof(struct hisi_zip_ctx),
6658c2ecf20Sopenharmony_ci	}
6668c2ecf20Sopenharmony_ci};
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ciint hisi_zip_register_to_crypto(void)
6698c2ecf20Sopenharmony_ci{
6708c2ecf20Sopenharmony_ci	int ret;
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_ci	ret = crypto_register_acomp(&hisi_zip_acomp_zlib);
6738c2ecf20Sopenharmony_ci	if (ret) {
6748c2ecf20Sopenharmony_ci		pr_err("failed to register to zlib (%d)!\n", ret);
6758c2ecf20Sopenharmony_ci		return ret;
6768c2ecf20Sopenharmony_ci	}
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ci	ret = crypto_register_acomp(&hisi_zip_acomp_gzip);
6798c2ecf20Sopenharmony_ci	if (ret) {
6808c2ecf20Sopenharmony_ci		pr_err("failed to register to gzip (%d)!\n", ret);
6818c2ecf20Sopenharmony_ci		crypto_unregister_acomp(&hisi_zip_acomp_zlib);
6828c2ecf20Sopenharmony_ci	}
6838c2ecf20Sopenharmony_ci
6848c2ecf20Sopenharmony_ci	return ret;
6858c2ecf20Sopenharmony_ci}
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_civoid hisi_zip_unregister_from_crypto(void)
6888c2ecf20Sopenharmony_ci{
6898c2ecf20Sopenharmony_ci	crypto_unregister_acomp(&hisi_zip_acomp_gzip);
6908c2ecf20Sopenharmony_ci	crypto_unregister_acomp(&hisi_zip_acomp_zlib);
6918c2ecf20Sopenharmony_ci}
692