Linux cryptographic layer development
 help / color / mirror / Atom feed
From: huangchenghai <huangchenghai2@huawei.com>
To: ZongYu Wu <wuzongyu1@huawei.com>, <herbert@gondor.apana.org.au>,
	<davem@davemloft.net>
Cc: <linux-kernel@vger.kernel.org>, <linux-crypto@vger.kernel.org>,
	<fanghao11@huawei.com>, <liulongfang@huawei.com>,
	<qianweili@huawei.com>, <wangzhou1@hisilicon.com>
Subject: Re: [PATCH] crypto: hisilicon/zip - add backlog support for zip
Date: Fri, 22 May 2026 18:32:39 +0800	[thread overview]
Message-ID: <4e8734c5-151b-4d45-8b24-8252cd6dcf68@huawei.com> (raw)
In-Reply-To: <20260515114601.2492524-2-wuzongyu1@huawei.com>


在 2026/5/15 19:45, ZongYu Wu 写道:
> From: Chenghai Huang <huangchenghai2@huawei.com>
>
> When the hardware queue is busy, requests are now queued instead of
> being failed immediately. Queued requests are retried when earlier
> requests complete, which prevents transient failures under heavy load.
>
> The backlog path also provides a fallback mechanism while the hardware
> is temporarily unavailable, such as during device reset.
>
> Signed-off-by: Chenghai Huang <huangchenghai2@huawei.com>
> Signed-off-by: Zongyu Wu <wuzongyu1@huawei.com>
> ---
>   drivers/crypto/hisilicon/zip/zip_crypto.c | 284 ++++++++++++++--------
>   1 file changed, 180 insertions(+), 104 deletions(-)
>
> diff --git a/drivers/crypto/hisilicon/zip/zip_crypto.c b/drivers/crypto/hisilicon/zip/zip_crypto.c
> index 70adde049b53..ff287251218e 100644
> --- a/drivers/crypto/hisilicon/zip/zip_crypto.c
> +++ b/drivers/crypto/hisilicon/zip/zip_crypto.c
> @@ -28,6 +28,7 @@
>   
>   #define HZIP_ALG_DEFLATE			GENMASK(5, 4)
>   #define HZIP_ALG_LZ4				BIT(8)
> +#define HZIP_INVAL_REQ_ID			((u16)0xFFFF)
>   
>   static DEFINE_MUTEX(zip_algs_lock);
>   static unsigned int zip_available_devs;
> @@ -55,11 +56,11 @@ struct hisi_zip_req {
>   	dma_addr_t dma_src;
>   	dma_addr_t dma_dst;
>   	struct hisi_zip_qp_ctx *qp_ctx;
> +	struct list_head list;
>   	u16 req_id;
>   };
>   
>   struct hisi_zip_req_q {
> -	struct hisi_zip_req *q;
>   	unsigned long *req_bitmap;
>   	spinlock_t req_lock;
>   	u16 size;
> @@ -135,42 +136,42 @@ static int hisi_zip_fallback_do_work(struct acomp_req *acomp_req, bool is_decomp
>   	return ret;
>   }
>   
> -static struct hisi_zip_req *hisi_zip_create_req(struct hisi_zip_qp_ctx *qp_ctx,
> -						struct acomp_req *req)
> +static int hisi_zip_create_req(struct hisi_zip_req *req)
>   {
> +	struct hisi_zip_qp_ctx *qp_ctx = req->qp_ctx;
>   	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;
>   	int req_id;
>   
> +	/* Check whether any request is being queued */
> +	if (!list_empty(&qp_ctx->qp->backlog.list))
> +		return -EBUSY;
> +
>   	spin_lock(&req_q->req_lock);
>   
>   	req_id = find_first_zero_bit(req_q->req_bitmap, req_q->size);
>   	if (req_id >= req_q->size) {
>   		spin_unlock(&req_q->req_lock);
>   		dev_dbg(&qp_ctx->qp->qm->pdev->dev, "req cache is full!\n");
> -		return ERR_PTR(-EAGAIN);
> +		return -EBUSY;
>   	}
>   	set_bit(req_id, req_q->req_bitmap);
>   
>   	spin_unlock(&req_q->req_lock);
>   
> -	req_cache = q + req_id;
> -	req_cache->req_id = req_id;
> -	req_cache->req = req;
> -	req_cache->qp_ctx = qp_ctx;
> +	req->req_id = req_id;
>   
> -	return req_cache;
> +	return 0;
>   }
>   
> -static void hisi_zip_remove_req(struct hisi_zip_qp_ctx *qp_ctx,
> -				struct hisi_zip_req *req)
> +static void hisi_zip_remove_req(struct hisi_zip_req *req)
>   {
> -	struct hisi_zip_req_q *req_q = &qp_ctx->req_q;
> +	struct hisi_zip_req_q *req_q = &req->qp_ctx->req_q;
>   
>   	spin_lock(&req_q->req_lock);
>   	clear_bit(req->req_id, req_q->req_bitmap);
>   	spin_unlock(&req_q->req_lock);
> +
> +	req->req_id = HZIP_INVAL_REQ_ID;
>   }
>   
>   static void hisi_zip_fill_addr(struct hisi_zip_sqe *sqe, struct hisi_zip_req *req)
> @@ -247,19 +248,21 @@ static void hisi_zip_fill_sqe(struct hisi_zip_ctx *ctx, struct hisi_zip_sqe *sqe
>   	ops->fill_sqe_type(sqe, ops->sqe_type);
>   }
>   
> -static int hisi_zip_do_work(struct hisi_zip_qp_ctx *qp_ctx,
> -			    struct hisi_zip_req *req)
> +static void hisi_zip_enqueue_backlog(struct hisi_zip_req *req)
> +{
> +	struct hisi_qp *qp = req->qp_ctx->qp;
> +
> +	spin_lock_bh(&qp->backlog.lock);
> +	list_add_tail(&req->list, &qp->backlog.list);
> +	spin_unlock_bh(&qp->backlog.lock);
> +}
> +
> +static int hisi_zip_map_req_buffers(struct hisi_zip_req *req)
>   {
> +	struct hisi_zip_qp_ctx *qp_ctx = req->qp_ctx;
>   	struct hisi_acc_sgl_pool *pool = qp_ctx->sgl_pool;
> -	struct hisi_zip_dfx *dfx = &qp_ctx->zip_dev->dfx;
> +	struct device *dev = &qp_ctx->qp->qm->pdev->dev;
>   	struct acomp_req *a_req = req->req;
> -	struct hisi_qp *qp = qp_ctx->qp;
> -	struct device *dev = &qp->qm->pdev->dev;
> -	struct hisi_zip_sqe zip_sqe;
> -	int ret;
> -
> -	if (unlikely(!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, a_req->src, pool,
>   						    req->req_id << 1, &req->dma_src,
> @@ -274,33 +277,110 @@ static int hisi_zip_do_work(struct hisi_zip_qp_ctx *qp_ctx,
>   						    (req->req_id << 1) + 1,
>   						    &req->dma_dst, DMA_FROM_DEVICE);
>   	if (IS_ERR(req->hw_dst)) {
> -		ret = PTR_ERR(req->hw_dst);
> -		dev_err(dev, "failed to map the dst buffer to hw sgl (%d)!\n",
> -			ret);
> -		goto err_unmap_input;
> +		dev_err(dev, "failed to map the dst buffer to hw sgl (%ld)!\n",
> +			PTR_ERR(req->hw_dst));
> +		hisi_acc_sg_buf_unmap(dev, a_req->src, req->hw_src, DMA_TO_DEVICE);
> +		return PTR_ERR(req->hw_dst);
>   	}
>   
> +	return 0;
> +}
> +
> +static void hisi_zip_unmap_req_buffers(struct hisi_zip_req *req)
> +{
> +	struct device *dev = &req->qp_ctx->qp->qm->pdev->dev;
> +	struct acomp_req *a_req = req->req;
> +
> +	hisi_acc_sg_buf_unmap(dev, a_req->dst, req->hw_dst, DMA_FROM_DEVICE);
> +	hisi_acc_sg_buf_unmap(dev, a_req->src, req->hw_src, DMA_TO_DEVICE);
> +}
> +
> +static int hisi_zip_do_work(struct hisi_zip_req *req)
> +{
> +	struct hisi_zip_qp_ctx *qp_ctx = req->qp_ctx;
> +	struct hisi_zip_dfx *dfx = &qp_ctx->zip_dev->dfx;
> +	struct hisi_qp *qp = qp_ctx->qp;
> +	struct hisi_zip_sqe zip_sqe;
> +	int ret;
> +
>   	hisi_zip_fill_sqe(qp_ctx->ctx, &zip_sqe, qp_ctx->req_type, req);
>   
>   	/* send command to start a task */
> -	atomic64_inc(&dfx->send_cnt);
>   	ret = hisi_qp_send(qp, &zip_sqe);
> -	if (unlikely(ret < 0)) {
> -		atomic64_inc(&dfx->send_busy_cnt);
> -		ret = -EAGAIN;
> -		dev_dbg_ratelimited(dev, "failed to send request!\n");
> -		goto err_unmap_output;
> +	if (likely(!ret)) {
> +		atomic64_inc(&dfx->send_cnt);
> +		return -EINPROGRESS;
>   	}
>   
> -	return -EINPROGRESS;
> +	if (ret == -EBUSY)
> +		atomic64_inc(&dfx->send_busy_cnt);
>   
> -err_unmap_output:
> -	hisi_acc_sg_buf_unmap(dev, a_req->dst, req->hw_dst, DMA_FROM_DEVICE);
> -err_unmap_input:
> -	hisi_acc_sg_buf_unmap(dev, a_req->src, req->hw_src, DMA_TO_DEVICE);
>   	return ret;
>   }
>   
> +static void hisi_zip_send_backlog_soft(struct hisi_zip_qp_ctx *qp_ctx)
> +{
> +	bool is_decomp = qp_ctx->qp->alg_type;
> +	struct hisi_zip_req *req, *tmp;
> +	int ret;
> +
> +	list_for_each_entry_safe(req, tmp, &qp_ctx->qp->backlog.list, list) {
> +		list_del(&req->list);
> +
> +		if (req->req_id != HZIP_INVAL_REQ_ID) {
> +			hisi_zip_unmap_req_buffers(req);
> +			hisi_zip_remove_req(req);
> +		}
> +
> +		ret = hisi_zip_fallback_do_work(req->req, is_decomp);
> +
> +		/* Wake up the busy thread first, then return the errno. */
> +		if (req->req->base.complete) {
> +			acomp_request_complete(req->req, -EINPROGRESS);
> +			acomp_request_complete(req->req, ret);
> +		}
> +	}
> +}
> +
> +static void hisi_zip_send_backlog(struct hisi_qp *qp)
> +{
> +	struct  hisi_zip_req *req, *tmp;
> +	int ret;
> +
> +	spin_lock_bh(&qp->backlog.lock);
> +	list_for_each_entry_safe(req, tmp, &qp->backlog.list, list) {
> +		if (req->req_id == HZIP_INVAL_REQ_ID) {
> +			ret = hisi_zip_create_req(req);
> +			if (ret)
> +				continue;
> +
> +			ret = hisi_zip_map_req_buffers(req);
> +			if (unlikely(ret)) {
> +				hisi_zip_remove_req(req);
> +				hisi_zip_send_backlog_soft(req->qp_ctx);
> +				goto unlock;
> +			}
> +		}
> +
> +		ret = hisi_zip_do_work(req);
> +		switch (ret) {
> +		case -EINPROGRESS:
> +			list_del(&req->list);
> +			if (req->req->base.complete)
> +				acomp_request_complete(req->req, -EINPROGRESS);
> +			break;
> +		case -EBUSY:
> +			goto unlock;
> +		default:
> +			hisi_zip_send_backlog_soft(req->qp_ctx);
> +			goto unlock;
> +		}
> +	}
> +
> +unlock:
> +	spin_unlock_bh(&qp->backlog.lock);
> +}
> +
>   static u32 hisi_zip_get_status(struct hisi_zip_sqe *sqe)
>   {
>   	return sqe->dw3 & HZIP_BD_STATUS_M;
> @@ -333,73 +413,89 @@ static void hisi_zip_acomp_cb(struct hisi_qp *qp, void *data)
>   		err = -EIO;
>   	}
>   
> -	hisi_acc_sg_buf_unmap(dev, acomp_req->dst, req->hw_dst, DMA_FROM_DEVICE);
> -	hisi_acc_sg_buf_unmap(dev, acomp_req->src, req->hw_src, DMA_TO_DEVICE);
> +	hisi_zip_unmap_req_buffers(req);
>   
>   	acomp_req->dlen = ops->get_dstlen(sqe);
> +	hisi_zip_remove_req(req);
>   
>   	if (acomp_req->base.complete)
>   		acomp_request_complete(acomp_req, err);
>   
> -	hisi_zip_remove_req(qp_ctx, req);
> +	hisi_zip_send_backlog(qp);
>   }
>   
> -static int hisi_zip_acompress(struct acomp_req *acomp_req)
> +static int hisi_zip_do_comp(struct hisi_zip_req *req)
>   {
> +	struct acomp_req *acomp_req = req->req;
>   	struct hisi_zip_ctx *ctx = crypto_tfm_ctx(acomp_req->base.tfm);
> -	struct hisi_zip_qp_ctx *qp_ctx = &ctx->qp_ctx[HZIP_QPC_COMP];
> -	struct hisi_zip_req *req;
> -	struct device *dev;
> +	struct hisi_qp *qp = req->qp_ctx->qp;
>   	int ret;
>   
> -	if (ctx->fallback)
> -		return hisi_zip_fallback_do_work(acomp_req, 0);
> -
> -	dev = &qp_ctx->qp->qm->pdev->dev;
> +	if (unlikely(!acomp_req->src || !acomp_req->slen ||
> +		     !acomp_req->dst || !acomp_req->dlen))
> +		return -EINVAL;
>   
> -	req = hisi_zip_create_req(qp_ctx, acomp_req);
> -	if (IS_ERR(req))
> -		return PTR_ERR(req);
> +	if (ctx->fallback)
> +		return hisi_zip_fallback_do_work(acomp_req, qp->alg_type);

Sorry. I found a problem after review again: when the QP allocation 
fails, we cannot obtain the service

type through qp->alg_type, because qp is not valid and ctx->fallback 
will true at that point.


I'll fix this and send a v2. Sorry again for the mistake. Please ignore 
this patch.

Best regards,

Chenghai

> +
> +	ret = hisi_zip_create_req(req);
> +	if (ret && (acomp_req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) {
> +		/* all req bitmaps are used add to backlog list */
> +		req->req_id = HZIP_INVAL_REQ_ID;
> +		hisi_zip_enqueue_backlog(req);
> +		return -EBUSY;
> +	} else if (unlikely(ret)) {
> +		return -ENOSPC;
> +	}
>   
> -	ret = hisi_zip_do_work(qp_ctx, req);
> -	if (unlikely(ret != -EINPROGRESS)) {
> -		dev_info_ratelimited(dev, "failed to do compress (%d)!\n", ret);
> -		hisi_zip_remove_req(qp_ctx, req);
> +	ret = hisi_zip_map_req_buffers(req);
> +	if (unlikely(ret))
> +		goto remove_req;
> +
> +	ret = hisi_zip_do_work(req);
> +	if (ret == -EBUSY && (acomp_req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) {
> +		/* hardwre busy add to backlog list */
> +		hisi_zip_enqueue_backlog(req);
> +	} else if (unlikely(ret != -EINPROGRESS)) {
> +		dev_info_ratelimited(&qp->qm->pdev->dev,
> +				     "failed to do %scompress (%d)!\n",
> +				     qp->alg_type ? "de" : "", ret);
> +		ret = -ENOSPC;
> +		goto unmap_req;
>   	}
>   
>   	return ret;
> +
> +unmap_req:
> +	hisi_zip_unmap_req_buffers(req);
> +remove_req:
> +	hisi_zip_remove_req(req);
> +	return ret;
>   }
>   
> -static int hisi_zip_adecompress(struct acomp_req *acomp_req)
> +static int hisi_zip_acompress(struct acomp_req *acomp_req)
>   {
>   	struct hisi_zip_ctx *ctx = crypto_tfm_ctx(acomp_req->base.tfm);
> -	struct hisi_zip_qp_ctx *qp_ctx = &ctx->qp_ctx[HZIP_QPC_DECOMP];
> -	struct hisi_zip_req *req;
> -	struct device *dev;
> -	int ret;
> -
> -	if (ctx->fallback)
> -		return hisi_zip_fallback_do_work(acomp_req, 1);
> +	struct hisi_zip_req *req = acomp_request_ctx(acomp_req);
>   
> -	dev = &qp_ctx->qp->qm->pdev->dev;
> -
> -	req = hisi_zip_create_req(qp_ctx, acomp_req);
> -	if (IS_ERR(req))
> -		return PTR_ERR(req);
> +	req->req = acomp_req;
> +	req->qp_ctx = &ctx->qp_ctx[HZIP_QPC_COMP];
> +	return hisi_zip_do_comp(req);
> +}
>   
> -	ret = hisi_zip_do_work(qp_ctx, req);
> -	if (unlikely(ret != -EINPROGRESS)) {
> -		dev_info_ratelimited(dev, "failed to do decompress (%d)!\n",
> -				     ret);
> -		hisi_zip_remove_req(qp_ctx, req);
> -	}
> +static int hisi_zip_adecompress(struct acomp_req *acomp_req)
> +{
> +	struct hisi_zip_ctx *ctx = crypto_tfm_ctx(acomp_req->base.tfm);
> +	struct hisi_zip_req *req = acomp_request_ctx(acomp_req);
>   
> -	return ret;
> +	req->req = acomp_req;
> +	req->qp_ctx = &ctx->qp_ctx[HZIP_QPC_DECOMP];
> +	return hisi_zip_do_comp(req);
>   }
>   
>   static int hisi_zip_decompress(struct acomp_req *acomp_req)
>   {
> -	return hisi_zip_fallback_do_work(acomp_req, 1);
> +	return hisi_zip_fallback_do_work(acomp_req, HZIP_ALG_TYPE_DECOMP);
>   }
>   
>   static const struct hisi_zip_sqe_ops hisi_zip_ops = {
> @@ -463,7 +559,7 @@ static int hisi_zip_create_req_q(struct hisi_zip_ctx *ctx)
>   {
>   	u16 q_depth = ctx->qp_ctx[0].qp->sq_depth;
>   	struct hisi_zip_req_q *req_q;
> -	int i, ret;
> +	int i;
>   
>   	for (i = 0; i < HZIP_CTX_Q_NUM; i++) {
>   		req_q = &ctx->qp_ctx[i].req_q;
> @@ -471,43 +567,21 @@ static int hisi_zip_create_req_q(struct hisi_zip_ctx *ctx)
>   
>   		req_q->req_bitmap = bitmap_zalloc(req_q->size, GFP_KERNEL);
>   		if (!req_q->req_bitmap) {
> -			ret = -ENOMEM;
> -			if (i == 0)
> -				return ret;
> -
> -			goto err_free_comp_q;
> +			bitmap_free(ctx->qp_ctx[HZIP_QPC_COMP].req_q.req_bitmap);
> +			return -ENOMEM;
>   		}
>   		spin_lock_init(&req_q->req_lock);
> -
> -		req_q->q = kzalloc_objs(struct hisi_zip_req, req_q->size);
> -		if (!req_q->q) {
> -			ret = -ENOMEM;
> -			if (i == 0)
> -				goto err_free_comp_bitmap;
> -			else
> -				goto err_free_decomp_bitmap;
> -		}
>   	}
>   
>   	return 0;
> -
> -err_free_decomp_bitmap:
> -	bitmap_free(ctx->qp_ctx[HZIP_QPC_DECOMP].req_q.req_bitmap);
> -err_free_comp_q:
> -	kfree(ctx->qp_ctx[HZIP_QPC_COMP].req_q.q);
> -err_free_comp_bitmap:
> -	bitmap_free(ctx->qp_ctx[HZIP_QPC_COMP].req_q.req_bitmap);
> -	return ret;
>   }
>   
>   static void hisi_zip_release_req_q(struct hisi_zip_ctx *ctx)
>   {
>   	int i;
>   
> -	for (i = 0; i < HZIP_CTX_Q_NUM; i++) {
> -		kfree(ctx->qp_ctx[i].req_q.q);
> +	for (i = 0; i < HZIP_CTX_Q_NUM; i++)
>   		bitmap_free(ctx->qp_ctx[i].req_q.req_bitmap);
> -	}
>   }
>   
>   static int hisi_zip_create_sgl_pool(struct hisi_zip_ctx *ctx)
> @@ -620,6 +694,7 @@ static struct acomp_alg hisi_zip_acomp_deflate = {
>   		.cra_module		= THIS_MODULE,
>   		.cra_priority		= HZIP_ALG_PRIORITY,
>   		.cra_ctxsize		= sizeof(struct hisi_zip_ctx),
> +		.cra_reqsize		= sizeof(struct hisi_zip_req),
>   	}
>   };
>   
> @@ -658,6 +733,7 @@ static struct acomp_alg hisi_zip_acomp_lz4 = {
>   		.cra_module		= THIS_MODULE,
>   		.cra_priority		= HZIP_ALG_PRIORITY,
>   		.cra_ctxsize		= sizeof(struct hisi_zip_ctx),
> +		.cra_reqsize		= sizeof(struct hisi_zip_req),
>   	}
>   };
>   

  reply	other threads:[~2026-05-22 10:32 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-15 11:45 [PATCH 0/3] crypto: hisilicon - improve backlog handling ZongYu Wu
2026-05-15 11:45 ` [PATCH] crypto: hisilicon/zip - add backlog support for zip ZongYu Wu
2026-05-22 10:32   ` huangchenghai [this message]
2026-05-15 11:46 ` [PATCH 2/3] crypto: hisilicon/sec2 - fix UAF in sec_alg_send_backlog ZongYu Wu
2026-05-15 11:46 ` [PATCH 3/3] crypto: hisilicon/hpre - implement full backlog support for hpre driver ZongYu Wu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4e8734c5-151b-4d45-8b24-8252cd6dcf68@huawei.com \
    --to=huangchenghai2@huawei.com \
    --cc=davem@davemloft.net \
    --cc=fanghao11@huawei.com \
    --cc=herbert@gondor.apana.org.au \
    --cc=linux-crypto@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=liulongfang@huawei.com \
    --cc=qianweili@huawei.com \
    --cc=wangzhou1@hisilicon.com \
    --cc=wuzongyu1@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox