1.Fix memory leak. 2.Add output size check.
Yang Shen (2): uadk/hisi_comp - free sgl when send request error uadk/hisi_comp - add output length check for lz77_zstd sgl mode
drv/hisi_comp.c | 92 +++++++++++++++++++++++++++++-------------------- 1 file changed, 54 insertions(+), 38 deletions(-)
-- 2.24.0
Free hardware sgl in error branch to avoid memory leakage.
Signed-off-by: Yang Shen shenyang39@huawei.com --- drv/hisi_comp.c | 60 +++++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 29 deletions(-)
diff --git a/drv/hisi_comp.c b/drv/hisi_comp.c index b6f4d19..e17197d 100644 --- a/drv/hisi_comp.c +++ b/drv/hisi_comp.c @@ -843,6 +843,10 @@ static int fill_zip_comp_sqe(struct hisi_qp *qp, struct wd_comp_msg *msg, return -WD_EINVAL; }
+ ret = ops[alg_type].fill_comp_level(sqe, msg->comp_lv); + if (unlikely(ret)) + return ret; + ret = ops[alg_type].fill_buf[msg->req.data_fmt]((handle_t)qp, sqe, msg); if (unlikely(ret)) return ret; @@ -853,10 +857,6 @@ static int fill_zip_comp_sqe(struct hisi_qp *qp, struct wd_comp_msg *msg,
ops[alg_type].fill_tag(sqe, msg->tag);
- ret = ops[alg_type].fill_comp_level(sqe, msg->comp_lv); - if (unlikely(ret)) - return ret; - state = (msg->stream_mode == WD_COMP_STATEFUL) ? HZ_STATEFUL : HZ_STATELESS; stream_pos = (msg->stream_pos == WD_COMP_STREAM_NEW) ? HZ_STREAM_NEW : @@ -878,6 +878,31 @@ static int fill_zip_comp_sqe(struct hisi_qp *qp, struct wd_comp_msg *msg, return 0; }
+static void free_hw_sgl(handle_t h_qp, struct hisi_zip_sqe *sqe, + enum wd_comp_alg_type alg_type) +{ + void *hw_sgl_in, *hw_sgl_out; + handle_t h_sgl_pool; + + h_sgl_pool = hisi_qm_get_sglpool(h_qp); + if (unlikely(!h_sgl_pool)) { + WD_ERR("failed to get sglpool to free hw sgl!\n"); + return; + } + + hw_sgl_in = VA_ADDR(sqe->source_addr_h, sqe->source_addr_l); + hisi_qm_put_hw_sgl(h_sgl_pool, hw_sgl_in); + + hw_sgl_out = VA_ADDR(sqe->dest_addr_h, sqe->dest_addr_l); + hisi_qm_put_hw_sgl(h_sgl_pool, hw_sgl_out); + + if (alg_type == WD_LZ77_ZSTD) { + hw_sgl_out = VA_ADDR(sqe->literals_addr_h, + sqe->literals_addr_l); + hisi_qm_put_hw_sgl(h_sgl_pool, hw_sgl_out); + } +} + static int hisi_zip_comp_send(handle_t ctx, void *comp_msg) { struct hisi_qp *qp = wd_ctx_get_priv(ctx); @@ -895,6 +920,8 @@ static int hisi_zip_comp_send(handle_t ctx, void *comp_msg) } ret = hisi_qm_send(h_qp, &sqe, 1, &count); if (unlikely(ret < 0)) { + if (msg->req.data_fmt == WD_SGL_BUF) + free_hw_sgl(h_qp, &sqe, msg->alg_type); if (ret != -WD_EBUSY) WD_ERR("failed to send to hardware, ret = %d!\n", ret);
@@ -929,31 +956,6 @@ static int get_alg_type(__u32 type) return alg_type; }
-static void free_hw_sgl(handle_t h_qp, struct hisi_zip_sqe *sqe, - enum wd_comp_alg_type alg_type) -{ - void *hw_sgl_in, *hw_sgl_out; - handle_t h_sgl_pool; - - h_sgl_pool = hisi_qm_get_sglpool(h_qp); - if (unlikely(!h_sgl_pool)) { - WD_ERR("failed to get sglpool to free hw sgl!\n"); - return; - } - - hw_sgl_in = VA_ADDR(sqe->source_addr_h, sqe->source_addr_l); - hisi_qm_put_hw_sgl(h_sgl_pool, hw_sgl_in); - - hw_sgl_out = VA_ADDR(sqe->dest_addr_h, sqe->dest_addr_l); - hisi_qm_put_hw_sgl(h_sgl_pool, hw_sgl_out); - - if (alg_type == WD_LZ77_ZSTD) { - hw_sgl_out = VA_ADDR(sqe->literals_addr_h, - sqe->literals_addr_l); - hisi_qm_put_hw_sgl(h_sgl_pool, hw_sgl_out); - } -} - static void get_ctx_buf(struct hisi_zip_sqe *sqe, struct wd_comp_msg *recv_msg) {
Algorithm lz77_zstd has some output buffer size limit due to hardware. So add the buffer size check. And unify related variables name style.
Signed-off-by: Yang Shen shenyang39@huawei.com --- drv/hisi_comp.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-)
diff --git a/drv/hisi_comp.c b/drv/hisi_comp.c index e17197d..d6c0a2a 100644 --- a/drv/hisi_comp.c +++ b/drv/hisi_comp.c @@ -420,7 +420,7 @@ static int fill_buf_lz77_zstd(handle_t h_qp, struct hisi_zip_sqe *sqe, struct wd_comp_req *req = &msg->req; struct wd_lz77_zstd_data *data = req->priv; __u32 in_size = msg->req.src_len; - __u32 lit_size = in_size + ZSTD_LIT_RESV_SIZE; + __u32 lits_size = in_size + ZSTD_LIT_RESV_SIZE; __u32 out_size = msg->avail_out; void *ctx_buf = NULL;
@@ -442,12 +442,12 @@ static int fill_buf_lz77_zstd(handle_t h_qp, struct hisi_zip_sqe *sqe, }
/* - * For lz77_zstd, the hardware need 784 Bytes buffer to output + * For lz77_zstd, the hardware needs 784 Bytes buffer to output * the frequency information about input data. */ - if (unlikely(out_size < ZSTD_FREQ_DATA_SIZE + lit_size)) { - WD_ERR("invalid: sequences output size(%u) is not enough!\n", - ZSTD_FREQ_DATA_SIZE + in_size); + if (unlikely(out_size < ZSTD_FREQ_DATA_SIZE + lits_size)) { + WD_ERR("invalid: output is not enough, %u bytes are minimum!\n", + ZSTD_FREQ_DATA_SIZE + lits_size); return -WD_EINVAL; }
@@ -458,13 +458,12 @@ static int fill_buf_lz77_zstd(handle_t h_qp, struct hisi_zip_sqe *sqe, msg->ctx_buf + CTX_REPCODE2_OFFSET, REPCODE_SIZE); }
- fill_buf_size_lz77_zstd(sqe, in_size, lit_size, out_size - lit_size); + fill_buf_size_lz77_zstd(sqe, in_size, lits_size, out_size - lits_size);
- fill_buf_addr_lz77_zstd(sqe, req->src, req->dst, - req->dst + lit_size, ctx_buf); + fill_buf_addr_lz77_zstd(sqe, req->src, req->dst, req->dst + lits_size, ctx_buf);
data->literals_start = req->dst; - data->sequences_start = req->dst + lit_size; + data->sequences_start = req->dst + lits_size;
return 0; } @@ -515,7 +514,22 @@ static int fill_buf_lz77_zstd_sgl(handle_t h_qp, struct hisi_zip_sqe *sqe, data->literals_start = req->list_dst; data->sequences_start = seq_start;
+ /* + * For lz77_zstd, the hardware needs 784 Bytes buffer to output + * the frequency information about input data. The sequences + * and frequency data need to be written to an independent sgl + * splited from list_dst. + */ lits_size = hisi_qm_get_list_size(req->list_dst, seq_start); + if (unlikely(lits_size < in_size + ZSTD_LIT_RESV_SIZE)) { + WD_ERR("invalid: output is not enough for literals, %u bytes are minimum!\n", + ZSTD_FREQ_DATA_SIZE + lits_size); + return -WD_EINVAL; + } else if (unlikely(out_size < ZSTD_FREQ_DATA_SIZE + lits_size)) { + WD_ERR("invalid: output is not enough for sequences, at least %u bytes more!\n", + ZSTD_FREQ_DATA_SIZE + lits_size - out_size); + return -WD_EINVAL; + }
fill_buf_size_lz77_zstd(sqe, in_size, lits_size, out_size - lits_size);