Commit 484a897f authored by Jonathan Cameron's avatar Jonathan Cameron Committed by Herbert Xu
Browse files

crypto: hisilicon - Use the offset fields in sqe to avoid need to split scatterlists



We can configure sgl offset fields in ZIP sqe to let ZIP engine read/write
sgl data with skipped data. Hence no need to splite the sgl.

Fixes: 62c455ca (crypto: hisilicon - add HiSilicon ZIP accelerator support)
Signed-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: default avatarZhou Wang <wangzhou1@hisilicon.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 8debacd6
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -44,7 +44,6 @@ config CRYPTO_DEV_HISI_ZIP
	depends on ARM64 || (COMPILE_TEST && 64BIT)
	depends on !CPU_BIG_ENDIAN || COMPILE_TEST
	select CRYPTO_DEV_HISI_QM
	select SG_SPLIT
	help
	  Support for HiSilicon ZIP Driver

+4 −0
Original line number Diff line number Diff line
@@ -11,6 +11,10 @@

/* hisi_zip_sqe dw3 */
#define HZIP_BD_STATUS_M			GENMASK(7, 0)
/* hisi_zip_sqe dw7 */
#define HZIP_IN_SGE_DATA_OFFSET_M		GENMASK(23, 0)
/* hisi_zip_sqe dw8 */
#define HZIP_OUT_SGE_DATA_OFFSET_M		GENMASK(23, 0)
/* hisi_zip_sqe dw9 */
#define HZIP_REQ_TYPE_M				GENMASK(7, 0)
#define HZIP_ALG_TYPE_ZLIB			0x02
+23 −69
Original line number Diff line number Diff line
@@ -46,10 +46,8 @@ enum hisi_zip_alg_type {

struct hisi_zip_req {
	struct acomp_req *req;
	struct scatterlist *src;
	struct scatterlist *dst;
	size_t slen;
	size_t dlen;
	int sskip;
	int dskip;
	struct hisi_acc_hw_sgl *hw_src;
	struct hisi_acc_hw_sgl *hw_dst;
	dma_addr_t dma_src;
@@ -119,13 +117,15 @@ static void hisi_zip_config_tag(struct hisi_zip_sqe *sqe, u32 tag)

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

	sqe->input_data_length = slen;
	sqe->input_data_length = slen - sskip;
	sqe->dw7 = FIELD_PREP(HZIP_IN_SGE_DATA_OFFSET_M, sskip);
	sqe->dw8 = FIELD_PREP(HZIP_OUT_SGE_DATA_OFFSET_M, dskip);
	sqe->dw9 = FIELD_PREP(HZIP_REQ_TYPE_M, req_type);
	sqe->dest_avail_out = dlen;
	sqe->dest_avail_out = dlen - dskip;
	sqe->source_addr_l = lower_32_bits(s_addr);
	sqe->source_addr_h = upper_32_bits(s_addr);
	sqe->dest_addr_l = lower_32_bits(d_addr);
@@ -327,11 +327,6 @@ static void hisi_zip_remove_req(struct hisi_zip_qp_ctx *qp_ctx,
{
	struct hisi_zip_req_q *req_q = &qp_ctx->req_q;

	if (qp_ctx->qp->alg_type == HZIP_ALG_TYPE_COMP)
		kfree(req->dst);
	else
		kfree(req->src);

	write_lock(&req_q->req_lock);
	clear_bit(req->req_id, req_q->req_bitmap);
	memset(req, 0, sizeof(struct hisi_zip_req));
@@ -359,8 +354,8 @@ static void hisi_zip_acomp_cb(struct hisi_qp *qp, void *data)
	}
	dlen = sqe->produced;

	hisi_acc_sg_buf_unmap(dev, req->src, req->hw_src);
	hisi_acc_sg_buf_unmap(dev, req->dst, req->hw_dst);
	hisi_acc_sg_buf_unmap(dev, acomp_req->src, req->hw_src);
	hisi_acc_sg_buf_unmap(dev, acomp_req->dst, req->hw_dst);

	head_size = (qp->alg_type == 0) ? TO_HEAD_SIZE(qp->req_type) : 0;
	acomp_req->dlen = dlen + head_size;
@@ -454,20 +449,6 @@ static size_t get_comp_head_size(struct scatterlist *src, u8 req_type)
	}
}

static int get_sg_skip_bytes(struct scatterlist *sgl, size_t bytes,
			     size_t remains, struct scatterlist **out)
{
#define SPLIT_NUM 2
	size_t split_sizes[SPLIT_NUM];
	int out_mapped_nents[SPLIT_NUM];

	split_sizes[0] = bytes;
	split_sizes[1] = remains;

	return sg_split(sgl, 0, 0, SPLIT_NUM, split_sizes, out,
			out_mapped_nents, GFP_KERNEL);
}

static struct hisi_zip_req *hisi_zip_create_req(struct acomp_req *req,
						struct hisi_zip_qp_ctx *qp_ctx,
						size_t head_size, bool is_comp)
@@ -475,31 +456,7 @@ static struct hisi_zip_req *hisi_zip_create_req(struct acomp_req *req,
	struct hisi_zip_req_q *req_q = &qp_ctx->req_q;
	struct hisi_zip_req *q = req_q->q;
	struct hisi_zip_req *req_cache;
	struct scatterlist *out[2];
	struct scatterlist *sgl;
	size_t len;
	int ret, req_id;

	/*
	 * remove/add zlib/gzip head, as hardware operations do not include
	 * comp head. so split req->src to get sgl without heads in acomp, or
	 * add comp head to req->dst ahead of that hardware output compressed
	 * data in sgl splited from req->dst without comp head.
	 */
	if (is_comp) {
		sgl = req->dst;
		len = req->dlen - head_size;
	} else {
		sgl = req->src;
		len = req->slen - head_size;
	}

	ret = get_sg_skip_bytes(sgl, head_size, len, out);
	if (ret)
		return ERR_PTR(ret);

	/* sgl for comp head is useless, so free it now */
	kfree(out[0]);
	int req_id;

	write_lock(&req_q->req_lock);

@@ -507,7 +464,6 @@ static struct hisi_zip_req *hisi_zip_create_req(struct acomp_req *req,
	if (req_id >= req_q->size) {
		write_unlock(&req_q->req_lock);
		dev_dbg(&qp_ctx->qp->qm->pdev->dev, "req cache is full!\n");
		kfree(out[1]);
		return ERR_PTR(-EBUSY);
	}
	set_bit(req_id, req_q->req_bitmap);
@@ -515,16 +471,13 @@ static struct hisi_zip_req *hisi_zip_create_req(struct acomp_req *req,
	req_cache = q + req_id;
	req_cache->req_id = req_id;
	req_cache->req = req;

	if (is_comp) {
		req_cache->src = req->src;
		req_cache->dst = out[1];
		req_cache->slen = req->slen;
		req_cache->dlen = req->dlen - head_size;
		req_cache->sskip = 0;
		req_cache->dskip = head_size;
	} else {
		req_cache->src = out[1];
		req_cache->dst = req->dst;
		req_cache->slen = req->slen - head_size;
		req_cache->dlen = req->dlen;
		req_cache->sskip = head_size;
		req_cache->dskip = 0;
	}

	write_unlock(&req_q->req_lock);
@@ -536,6 +489,7 @@ static int hisi_zip_do_work(struct hisi_zip_req *req,
			    struct hisi_zip_qp_ctx *qp_ctx)
{
	struct hisi_zip_sqe *zip_sqe = &qp_ctx->zip_sqe;
	struct acomp_req *a_req = req->req;
	struct hisi_qp *qp = qp_ctx->qp;
	struct device *dev = &qp->qm->pdev->dev;
	struct hisi_acc_sgl_pool *pool = qp_ctx->sgl_pool;
@@ -543,16 +497,16 @@ static int hisi_zip_do_work(struct hisi_zip_req *req,
	dma_addr_t output;
	int ret;

	if (!req->src || !req->slen || !req->dst || !req->dlen)
	if (!a_req->src || !a_req->slen || !a_req->dst || !a_req->dlen)
		return -EINVAL;

	req->hw_src = hisi_acc_sg_buf_map_to_hw_sgl(dev, req->src, pool,
	req->hw_src = hisi_acc_sg_buf_map_to_hw_sgl(dev, a_req->src, pool,
						    req->req_id << 1, &input);
	if (IS_ERR(req->hw_src))
		return PTR_ERR(req->hw_src);
	req->dma_src = input;

	req->hw_dst = hisi_acc_sg_buf_map_to_hw_sgl(dev, req->dst, pool,
	req->hw_dst = hisi_acc_sg_buf_map_to_hw_sgl(dev, a_req->dst, pool,
						    (req->req_id << 1) + 1,
						    &output);
	if (IS_ERR(req->hw_dst)) {
@@ -561,8 +515,8 @@ static int hisi_zip_do_work(struct hisi_zip_req *req,
	}
	req->dma_dst = output;

	hisi_zip_fill_sqe(zip_sqe, qp->req_type, input, output, req->slen,
			  req->dlen);
	hisi_zip_fill_sqe(zip_sqe, qp->req_type, input, output, a_req->slen,
			  a_req->dlen, req->sskip, req->dskip);
	hisi_zip_config_buf_type(zip_sqe, HZIP_SGL);
	hisi_zip_config_tag(zip_sqe, req->req_id);

@@ -574,9 +528,9 @@ static int hisi_zip_do_work(struct hisi_zip_req *req,
	return -EINPROGRESS;

err_unmap_output:
	hisi_acc_sg_buf_unmap(dev, req->dst, req->hw_dst);
	hisi_acc_sg_buf_unmap(dev, a_req->dst, req->hw_dst);
err_unmap_input:
	hisi_acc_sg_buf_unmap(dev, req->src, req->hw_src);
	hisi_acc_sg_buf_unmap(dev, a_req->src, req->hw_src);
	return ret;
}