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