From: Yu'an Wang wangyuan46@huawei.com
driver inclusion category: bugfix bugzilla: NA CVE: NA
1.In this patch, we try to fix problem of decompress an empty file. When we try to decompress an empty file by gzip, the way of changed head_size is unreasonable. So we use fixed length head_size. 2.In crypto frame, "-EBUSY" means this request is successful, but stop sending. So we should change the return. 3.We add some dfx to collect software send/recv/send_busy/err_bd cnt.
Signed-off-by: Yu'an Wang wangyuan46@huawei.com Reviewed-by: Mingqiang Ling lingmingqiang@huawei.com Reviewed-by: Guangwei Zhou zhouguangwei5@huawei.com Reviewed-by: Yang shen shenyang39@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/crypto/hisilicon/zip/zip.h | 8 ++++ drivers/crypto/hisilicon/zip/zip_crypto.c | 24 +++++++--- drivers/crypto/hisilicon/zip/zip_main.c | 73 +++++++++++++++++++++++++++++-- 3 files changed, 96 insertions(+), 9 deletions(-)
diff --git a/drivers/crypto/hisilicon/zip/zip.h b/drivers/crypto/hisilicon/zip/zip.h index ddd5924..81bfcfe 100644 --- a/drivers/crypto/hisilicon/zip/zip.h +++ b/drivers/crypto/hisilicon/zip/zip.h @@ -17,10 +17,18 @@ enum hisi_zip_error_type { HZIP_NC_ERR = 0x0d, };
+struct zip_dfx { + atomic64_t send_cnt; + atomic64_t recv_cnt; + atomic64_t send_busy_cnt; + atomic64_t err_bd_cnt; +}; + struct hisi_zip_ctrl; struct hisi_zip { struct hisi_qm qm; struct hisi_zip_ctrl *ctrl; + struct zip_dfx dfx; };
int zip_create_qps(struct hisi_qp **qps, int ctx_num); diff --git a/drivers/crypto/hisilicon/zip/zip_crypto.c b/drivers/crypto/hisilicon/zip/zip_crypto.c index b247021..1cf8844 100644 --- a/drivers/crypto/hisilicon/zip/zip_crypto.c +++ b/drivers/crypto/hisilicon/zip/zip_crypto.c @@ -353,6 +353,7 @@ static void hisi_zip_acomp_cb(struct hisi_qp *qp, void *data) { struct hisi_zip_sqe *sqe = data; struct hisi_zip_qp_ctx *qp_ctx = qp->qp_ctx; + struct zip_dfx *dfx = &qp_ctx->zip_dev->dfx; struct hisi_zip_req_q *req_q = &qp_ctx->req_q; struct hisi_zip_req *req = req_q->q + sqe->tag; struct acomp_req *acomp_req = req->req; @@ -360,11 +361,13 @@ static void hisi_zip_acomp_cb(struct hisi_qp *qp, void *data) u32 status, dlen, head_size; int err = 0;
+ atomic64_inc(&dfx->recv_cnt); status = sqe->dw3 & HZIP_BD_STATUS_M; if (status != 0 && status != HZIP_NC_ERR) { dev_err(dev, "%scompress fail in qp%u: %u, output: %u\n", (qp->alg_type == 0) ? "" : "de", qp->qp_id, status, sqe->produced); + atomic64_inc(&dfx->err_bd_cnt); err = -EIO; } dlen = sqe->produced; @@ -452,7 +455,7 @@ static int add_comp_head(struct scatterlist *dst, u8 req_type) return head_size; }
-static size_t get_gzip_head_size(struct scatterlist *sgl) +static size_t __maybe_unused get_gzip_head_size(struct scatterlist *sgl) { char buf[HZIP_GZIP_HEAD_BUF];
@@ -461,13 +464,20 @@ static size_t get_gzip_head_size(struct scatterlist *sgl) return __get_gzip_head_size(buf); }
-static int get_comp_head_size(struct scatterlist *src, u8 req_type) +static int get_comp_head_size(struct acomp_req *acomp_req, u8 req_type) { + if (!acomp_req->src || !acomp_req->slen) + return -EINVAL; + + if ((req_type == HZIP_ALG_TYPE_GZIP) && + (acomp_req->slen < GZIP_HEAD_FEXTRA_SHIFT)) + return -EINVAL; + switch (req_type) { case HZIP_ALG_TYPE_ZLIB: return TO_HEAD_SIZE(HZIP_ALG_TYPE_ZLIB); case HZIP_ALG_TYPE_GZIP: - return get_gzip_head_size(src); + return TO_HEAD_SIZE(HZIP_ALG_TYPE_GZIP); default: pr_err("request type does not support!\n"); return -EINVAL; @@ -489,7 +499,7 @@ 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"); - return ERR_PTR(-EBUSY); + return ERR_PTR(-EPERM); } set_bit(req_id, req_q->req_bitmap);
@@ -518,6 +528,7 @@ static int hisi_zip_do_work(struct hisi_zip_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; + struct zip_dfx *dfx = &qp_ctx->zip_dev->dfx; dma_addr_t input; dma_addr_t output; int ret; @@ -549,8 +560,11 @@ static int hisi_zip_do_work(struct hisi_zip_req *req, hisi_zip_config_tag(zip_sqe, req->req_id);
/* send command to start a task */ + atomic64_inc(&dfx->send_cnt); ret = hisi_qp_send(qp, zip_sqe); if (ret < 0) { + atomic64_inc(&dfx->send_busy_cnt); + ret = -EPERM; dev_dbg_ratelimited(dev, "send task message failed!\n"); goto err_unmap_output; } @@ -602,7 +616,7 @@ static int hisi_zip_adecompress(struct acomp_req *acomp_req) int head_size; int ret;
- head_size = get_comp_head_size(acomp_req->src, qp_ctx->qp->req_type); + head_size = get_comp_head_size(acomp_req, qp_ctx->qp->req_type); if (head_size < 0) return -ENOMEM;
diff --git a/drivers/crypto/hisilicon/zip/zip_main.c b/drivers/crypto/hisilicon/zip/zip_main.c index 83e2869..15ba6d3 100644 --- a/drivers/crypto/hisilicon/zip/zip_main.c +++ b/drivers/crypto/hisilicon/zip/zip_main.c @@ -98,6 +98,11 @@ #define HZIP_BUF_SIZE 22 #define FORMAT_DECIMAL 10
+#define HZIP_CNT_CLR_CE_EN BIT(0) +#define HZIP_RO_CNT_CLR_CE_EN BIT(2) +#define HZIP_RD_CNT_CLR_CE_EN (HZIP_CNT_CLR_CE_EN | \ + HZIP_RO_CNT_CLR_CE_EN) + static const char hisi_zip_name[] = "hisi_zip"; static struct dentry *hzip_debugfs_root; static struct hisi_qm_list zip_devices; @@ -107,6 +112,18 @@ struct hisi_zip_hw_error { const char *msg; };
+struct zip_dfx_item { + const char *name; + u32 offset; +}; + +static struct zip_dfx_item zip_dfx_files[] = { + {"send_cnt", offsetof(struct zip_dfx, send_cnt)}, + {"recv_cnt", offsetof(struct zip_dfx, recv_cnt)}, + {"send_busy_cnt", offsetof(struct zip_dfx, send_busy_cnt)}, + {"err_bd_cnt", offsetof(struct zip_dfx, err_bd_cnt)}, +}; + static const struct hisi_zip_hw_error zip_hw_error[] = { { .int_msk = BIT(0), .msg = "zip_ecc_1bitt_err" }, { .int_msk = BIT(1), .msg = "zip_ecc_2bit_err" }, @@ -309,10 +326,19 @@ static int hisi_zip_set_user_domain_and_cache(struct hisi_qm *qm) /* hisi_zip_debug_regs_clear() - clear the zip debug regs */ static void hisi_zip_debug_regs_clear(struct hisi_qm *qm) { + int i, j; + /* clear current_qm */ writel(0x0, qm->io_base + QM_DFX_MB_CNT_VF); writel(0x0, qm->io_base + QM_DFX_DB_CNT_VF);
+ /* enable rdclr_en */ + writel(HZIP_RD_CNT_CLR_CE_EN, qm->io_base + HZIP_SOFT_CTRL_CNT_CLR_CE); + for (i = 0; i < ARRAY_SIZE(core_offsets); i++) + for (j = 0; j < ARRAY_SIZE(hzip_dfx_regs); j++) + readl(qm->io_base + core_offsets[i] + + hzip_dfx_regs[j].offset); + /* clear rdclr_en */ writel(0x0, qm->io_base + HZIP_SOFT_CTRL_CNT_CLR_CE);
@@ -532,11 +558,31 @@ static ssize_t hisi_zip_ctrl_debug_write(struct file *filp, .write = hisi_zip_ctrl_debug_write, };
+static int zip_debugfs_atomic64_set(void *data, u64 val) +{ + if (!val) + atomic64_set((atomic64_t *)data, 0); + else + return -EINVAL; + + return 0; +} + +static int zip_debugfs_atomic64_get(void *data, u64 *val) +{ + *val = atomic64_read((atomic64_t *)data); + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(zip_atomic64_ops, zip_debugfs_atomic64_get, + zip_debugfs_atomic64_set, "%llu\n"); + static int hisi_zip_core_debug_init(struct hisi_qm *qm) { struct device *dev = &qm->pdev->dev; struct debugfs_regset32 *regset; - struct dentry *tmp_d, *tmp; + struct dentry *tmp_d; char buf[HZIP_BUF_SIZE]; int i, ret;
@@ -561,14 +607,31 @@ static int hisi_zip_core_debug_init(struct hisi_qm *qm) regset->nregs = ARRAY_SIZE(hzip_dfx_regs); regset->base = qm->io_base + core_offsets[i];
- tmp = debugfs_create_regset32("regs", 0444, tmp_d, regset); - if (!tmp) - return -ENOENT; + debugfs_create_regset32("regs", 0444, tmp_d, regset); }
return 0; }
+static void hisi_zip_dfx_debug_init(struct hisi_qm *qm) +{ + struct hisi_zip *zip = container_of(qm, struct hisi_zip, qm); + struct zip_dfx *dfx = &zip->dfx; + struct dentry *tmp_dir; + void *data; + int i; + + tmp_dir = debugfs_create_dir("zip_dfx", qm->debug.debug_root); + for (i = 0; i < ARRAY_SIZE(zip_dfx_files); i++) { + data = (atomic64_t *)((uintptr_t)dfx + zip_dfx_files[i].offset); + debugfs_create_file(zip_dfx_files[i].name, + 0644, + tmp_dir, + data, + &zip_atomic64_ops); + } +} + static int hisi_zip_ctrl_debug_init(struct hisi_qm *qm) { struct hisi_zip *zip = container_of(qm, struct hisi_zip, qm); @@ -611,6 +674,8 @@ static int hisi_zip_debugfs_init(struct hisi_qm *qm) goto failed_to_create; }
+ hisi_zip_dfx_debug_init(qm); + return 0;
failed_to_create: