From 77bbbfe851a5223152760404430fae29f5e7ce04 Mon Sep 17 00:00:00 2001 From: Jie Lei Date: Thu, 9 May 2024 17:26:51 +0800 Subject: [PATCH 1/2] hns3 udma: fixed a bug when enabling DCA. driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8V1IQ CVE: NA -------------------------------------------------------- This patch is used to fix the reference counting problem. Fixes: 1f0cdbbca097 ("hns3 udma: support of DCA") Signed-off-by: Ye Zhang Signed-off-by: Jie Lei Signed-off-by: Weibo Zhao --- drivers/ub/hw/hns3/hns3_udma_dca.c | 79 ++++++++++++++++++++---------- drivers/ub/hw/hns3/hns3_udma_qp.c | 19 ++++--- 2 files changed, 65 insertions(+), 33 deletions(-) diff --git a/drivers/ub/hw/hns3/hns3_udma_dca.c b/drivers/ub/hw/hns3/hns3_udma_dca.c index d57fd3148f00..2e17146c592b 100644 --- a/drivers/ub/hw/hns3/hns3_udma_dca.c +++ b/drivers/ub/hw/hns3/hns3_udma_dca.c @@ -604,7 +604,8 @@ int udma_register_udca(struct udma_dev *udma_dev, int ret; ret = copy_from_user(&ucmd, (void *)udrv_data->in_addr, - min_t(uint32_t, udrv_data->in_len, (uint32_t)sizeof(ucmd))); + min_t(uint32_t, udrv_data->in_len, + (uint32_t)sizeof(ucmd))); if (ret) { dev_err(udma_dev->dev, "Failed to copy udata, ret = %d.\n", ret); @@ -781,6 +782,24 @@ static int query_dca_active_pages_proc(struct dca_mem *mem, uint32_t index, return DCA_MEM_STOP_ITERATE; } +static struct udma_qp *udma_dca_get_qp(struct udma_dev *dev, uint32_t qpn) +{ + struct udma_qp *qp; + + xa_lock(&dev->qp_table.xa); + qp = get_qp(dev, qpn); + if (!qp) { + dev_err(dev->dev, "failed to find qp, qpn = 0x%x\n", qpn); + xa_unlock(&dev->qp_table.xa); + return NULL; + } + refcount_inc(&qp->refcount); + + xa_unlock(&dev->qp_table.xa); + + return qp; +} + int udma_query_dca_mem(struct udma_dev *dev, struct udma_dca_query_attr *attr, struct udma_dca_query_resp *resp) { @@ -789,11 +808,10 @@ int udma_query_dca_mem(struct udma_dev *dev, struct udma_dca_query_attr *attr, struct udma_dca_cfg *cfg; struct udma_qp *qp; - qp = get_qp(dev, attr->qpn); - if (qp == NULL) { - dev_err(dev->dev, "failed to find qp, qpn = 0x%llx\n", attr->qpn); + qp = udma_dca_get_qp(dev, attr->qpn); + if (qp == NULL) return -EINVAL; - } + cfg = &qp->dca_cfg; ctx = qp->dca_ctx; @@ -805,6 +823,9 @@ int udma_query_dca_mem(struct udma_dev *dev, struct udma_dca_query_attr *attr, resp->mem_ofs = a_attr.page_index << UDMA_HW_PAGE_SHIFT; resp->page_count = a_attr.page_count; + if (refcount_dec_and_test(&qp->refcount)) + complete(&qp->free); + return a_attr.page_count ? 0 : -ENOMEM; } @@ -1111,14 +1132,12 @@ int udma_dca_attach(struct udma_dev *dev, struct udma_dca_attach_attr *attr, struct udma_dca_cfg *cfg; struct udma_qp *qp; uint32_t buf_id; - int ret; + int ret = 0; - qp = get_qp(dev, attr->qpn); - if (qp == NULL) { - dev_err(dev->dev, "failed to find attach qp, qpn = 0x%llx\n", - attr->qpn); + qp = udma_dca_get_qp(dev, attr->qpn); + if (qp == NULL) return -EINVAL; - } + cfg = &qp->dca_cfg; ctx = qp->dca_ctx; @@ -1131,7 +1150,7 @@ int udma_dca_attach(struct udma_dev *dev, struct udma_dca_attach_attr *attr, if (buf_id != UDMA_DCA_INVALID_BUF_ID) { resp->alloc_pages = cfg->npages; spin_unlock(&cfg->lock); - return 0; + goto refcount_dec; } /* Start to new attach */ @@ -1140,7 +1159,7 @@ int udma_dca_attach(struct udma_dev *dev, struct udma_dca_attach_attr *attr, if (buf_id == UDMA_DCA_INVALID_BUF_ID) { spin_unlock(&cfg->lock); /* No report fail, need try again after the pool increased */ - return 0; + goto refcount_dec; } ret = active_alloced_buf(dev, ctx, qp, buf_id, attr); @@ -1149,7 +1168,7 @@ int udma_dca_attach(struct udma_dev *dev, struct udma_dca_attach_attr *attr, dev_err(dev->dev, "failed to active DCA buf for QP-%llu, ret = %d.\n", qp->qpn, ret); - return ret; + goto refcount_dec; } /* Attach ok */ @@ -1162,7 +1181,15 @@ int udma_dca_attach(struct udma_dev *dev, struct udma_dca_attach_attr *attr, resp->dcan = cfg->dcan; update_dca_buf_status(ctx, cfg->dcan, true); - return 0; + if (refcount_dec_and_test(&qp->refcount)) + complete(&qp->free); + + return ret; + +refcount_dec: + if (refcount_dec_and_test(&qp->refcount)) + complete(&qp->free); + return ret; } void udma_dca_disattach(struct udma_dev *dev, struct udma_dca_attach_attr *attr) @@ -1171,12 +1198,10 @@ void udma_dca_disattach(struct udma_dev *dev, struct udma_dca_attach_attr *attr) struct udma_dca_cfg *cfg; struct udma_qp *qp; - qp = get_qp(dev, attr->qpn); - if (qp == NULL) { - dev_err(dev->dev, "failed to find disattach qp, qpn = 0x%llx\n", - attr->qpn); + qp = udma_dca_get_qp(dev, attr->qpn); + if (qp == NULL) return; - } + cfg = &qp->dca_cfg; ctx = qp->dca_ctx; @@ -1185,6 +1210,9 @@ void udma_dca_disattach(struct udma_dev *dev, struct udma_dca_attach_attr *attr) cfg->buf_id = UDMA_DCA_INVALID_BUF_ID; update_dca_buf_status(ctx, cfg->dcan, false); + + if (refcount_dec_and_test(&qp->refcount)) + complete(&qp->free); } void udma_dca_detach(struct udma_dev *dev, struct udma_dca_detach_attr *attr) @@ -1193,12 +1221,10 @@ void udma_dca_detach(struct udma_dev *dev, struct udma_dca_detach_attr *attr) struct udma_dca_cfg *cfg; struct udma_qp *qp; - qp = get_qp(dev, attr->qpn); - if (qp == NULL) { - dev_err(dev->dev, "failed to find detach qp, qpn = 0x%llx\n", - attr->qpn); + qp = udma_dca_get_qp(dev, attr->qpn); + if (qp == NULL) return; - } + cfg = &qp->dca_cfg; ctx = qp->dca_ctx; @@ -1212,6 +1238,9 @@ void udma_dca_detach(struct udma_dev *dev, struct udma_dca_detach_attr *attr) spin_unlock(&ctx->aging_lock); restart_aging_dca_mem(dev, ctx); + + if (refcount_dec_and_test(&qp->refcount)) + complete(&qp->free); } static int enum_dca_pool_proc(struct dca_mem *mem, uint32_t index, void *param) diff --git a/drivers/ub/hw/hns3/hns3_udma_qp.c b/drivers/ub/hw/hns3/hns3_udma_qp.c index c93cc7857346..213d74f164bd 100644 --- a/drivers/ub/hw/hns3/hns3_udma_qp.c +++ b/drivers/ub/hw/hns3/hns3_udma_qp.c @@ -92,7 +92,7 @@ static int config_qp_rq_buf(struct udma_dev *udma_device, /* search RQ buf's mtts */ count = udma_mtr_find(udma_device, &qp->qp_attr.jfr->buf_mtr, qp->qp_attr.jfr->offset, - mtts_wqe, ARRAY_SIZE(mtts_wqe), NULL); + mtts_wqe, ARRAY_SIZE(mtts_wqe), NULL); if (count < 1) { dev_err(udma_device->dev, "failed to find QP(0x%llx) RQ buf.\n", qp->qpn); @@ -100,21 +100,21 @@ static int config_qp_rq_buf(struct udma_dev *udma_device, } udma_reg_write(context, QPC_RQ_HOP_NUM, - to_udma_hem_hopnum(udma_device->caps.wqe_rq_hop_num, - qp->rq.wqe_cnt)); + to_udma_hem_hopnum(udma_device->caps.wqe_rq_hop_num, + qp->rq.wqe_cnt)); udma_reg_clear(context_mask, QPC_RQ_HOP_NUM); udma_reg_write(context, QPC_RQ_CUR_BLK_ADDR_L, - to_udma_hw_page_addr(mtts_wqe[0])); + to_udma_hw_page_addr(mtts_wqe[0])); udma_reg_write(context, QPC_RQ_CUR_BLK_ADDR_H, - upper_32_bits(to_udma_hw_page_addr(mtts_wqe[0]))); + upper_32_bits(to_udma_hw_page_addr(mtts_wqe[0]))); udma_reg_clear(context_mask, QPC_RQ_CUR_BLK_ADDR_L); udma_reg_clear(context_mask, QPC_RQ_CUR_BLK_ADDR_H); udma_reg_write(context, QPC_RQ_NXT_BLK_ADDR_L, - to_udma_hw_page_addr(mtts_wqe[1])); + to_udma_hw_page_addr(mtts_wqe[1])); udma_reg_write(context, QPC_RQ_NXT_BLK_ADDR_H, - upper_32_bits(to_udma_hw_page_addr(mtts_wqe[1]))); + upper_32_bits(to_udma_hw_page_addr(mtts_wqe[1]))); udma_reg_clear(context_mask, QPC_RQ_NXT_BLK_ADDR_L); udma_reg_clear(context_mask, QPC_RQ_NXT_BLK_ADDR_H); @@ -1629,6 +1629,8 @@ static int alloc_qp_db(struct udma_dev *udma_dev, struct udma_qp *qp, if (udata) { qp->udma_uctx = to_udma_ucontext(udata->uctx); ret = alloc_user_qp_db(udma_dev, qp, ucmd); + } else { + qp->udma_uctx = NULL; } return ret; @@ -1855,7 +1857,8 @@ static void free_qp_db(struct udma_dev *udma_dev, struct udma_qp *qp) return; if (qp->en_flags & HNS3_UDMA_QP_CAP_SQ_RECORD_DB) - udma_db_unmap_user(qp->udma_uctx, &qp->sdb); + if (qp->udma_uctx) + udma_db_unmap_user(qp->udma_uctx, &qp->sdb); } static void free_wqe_buf(struct udma_dev *dev, struct udma_qp *qp) -- Gitee From 7116ad822ea34dc9701bac2db98ab77ae1464d15 Mon Sep 17 00:00:00 2001 From: Jie Lei Date: Fri, 10 May 2024 10:36:14 +0800 Subject: [PATCH 2/2] hns3 udma: resolve the problem when resources are reclaimed. driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8V1IQ CVE: NA -------------------------------------------------------- This patch adapt to fix the bug that occurs when the applied resources are rolled back when the JFC fails to be created. Fixes: 33e5598b116f ("hns3 udma: addressing stage adaptation") Signed-off-by: Ye Zhang Signed-off-by: Jie Lei Signed-off-by: Weibo Zhao --- drivers/ub/hw/hns3/hns3_udma_dca.c | 5 ----- drivers/ub/hw/hns3/hns3_udma_jfc.c | 5 ++--- drivers/ub/hw/hns3/hns3_udma_jfc.h | 1 + drivers/ub/hw/hns3/hns3_udma_jfr.c | 5 ++--- drivers/ub/hw/hns3/hns3_udma_jfr.h | 1 + 5 files changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/ub/hw/hns3/hns3_udma_dca.c b/drivers/ub/hw/hns3/hns3_udma_dca.c index 2e17146c592b..b4afd0790083 100644 --- a/drivers/ub/hw/hns3/hns3_udma_dca.c +++ b/drivers/ub/hw/hns3/hns3_udma_dca.c @@ -1181,11 +1181,6 @@ int udma_dca_attach(struct udma_dev *dev, struct udma_dca_attach_attr *attr, resp->dcan = cfg->dcan; update_dca_buf_status(ctx, cfg->dcan, true); - if (refcount_dec_and_test(&qp->refcount)) - complete(&qp->free); - - return ret; - refcount_dec: if (refcount_dec_and_test(&qp->refcount)) complete(&qp->free); diff --git a/drivers/ub/hw/hns3/hns3_udma_jfc.c b/drivers/ub/hw/hns3/hns3_udma_jfc.c index 580271ccc206..189b1f3630ab 100644 --- a/drivers/ub/hw/hns3/hns3_udma_jfc.c +++ b/drivers/ub/hw/hns3/hns3_udma_jfc.c @@ -238,6 +238,7 @@ static int alloc_jfc_buf(struct udma_dev *udma_dev, struct udma_jfc *udma_jfc, refcount_set(&udma_jfc->refcount, 1); init_completion(&udma_jfc->free); + udma_jfc->udma_uctx = udma_uctx; return ret; err_copy: @@ -501,15 +502,13 @@ static void free_jfc_cqc(struct udma_dev *udma_dev, struct udma_jfc *udma_jfc) static void free_jfc_buf(struct udma_dev *udma_dev, struct udma_jfc *udma_jfc) { - struct udma_ucontext *udma_uctx = to_udma_ucontext(udma_jfc->ubcore_jfc.uctx); - /* wait for all interrupt processed */ if (refcount_dec_and_test(&udma_jfc->refcount)) complete(&udma_jfc->free); wait_for_completion(&udma_jfc->free); if (udma_dev->caps.flags & UDMA_CAP_FLAG_CQ_RECORD_DB) - udma_db_unmap_user(udma_uctx, &udma_jfc->db); + udma_db_unmap_user(udma_jfc->udma_uctx, &udma_jfc->db); udma_mtr_destroy(udma_dev, &udma_jfc->mtr); } diff --git a/drivers/ub/hw/hns3/hns3_udma_jfc.h b/drivers/ub/hw/hns3/hns3_udma_jfc.h index fd41c06b3a49..351ed0acac38 100644 --- a/drivers/ub/hw/hns3/hns3_udma_jfc.h +++ b/drivers/ub/hw/hns3/hns3_udma_jfc.h @@ -32,6 +32,7 @@ struct udma_jfc { struct completion free; struct list_head sq_list; struct list_head rq_list; + struct udma_ucontext *udma_uctx; struct hns3_udma_jfc_attr_ex jfc_attr_ex; }; diff --git a/drivers/ub/hw/hns3/hns3_udma_jfr.c b/drivers/ub/hw/hns3/hns3_udma_jfr.c index fa8423905c88..d2cd484be683 100644 --- a/drivers/ub/hw/hns3/hns3_udma_jfr.c +++ b/drivers/ub/hw/hns3/hns3_udma_jfr.c @@ -226,6 +226,7 @@ static int alloc_jfr_buf(struct udma_dev *dev, struct udma_jfr *jfr, refcount_set(&jfr->refcount, 1); init_completion(&jfr->free); + jfr->udma_uctx = udma_uctx; return 0; err_db: @@ -527,8 +528,6 @@ static void free_jfrc(struct udma_dev *dev, struct udma_jfr *jfr) static void free_jfr_buf(struct udma_dev *dev, struct udma_jfr *jfr) { - struct udma_ucontext *udma_uctx = to_udma_ucontext(jfr->ubcore_jfr.uctx); - if (refcount_dec_and_test(&jfr->refcount)) complete(&jfr->free); @@ -536,7 +535,7 @@ static void free_jfr_buf(struct udma_dev *dev, struct udma_jfr *jfr) if (dev->caps.flags & UDMA_CAP_FLAG_SRQ_RECORD_DB || jfr->jfr_caps & HNS3_UDMA_JFR_CAP_RECORD_DB) - udma_db_unmap_user(udma_uctx, &jfr->db); + udma_db_unmap_user(jfr->udma_uctx, &jfr->db); free_jfr_wqe_buf(dev, jfr); free_jfr_idx(dev, jfr); diff --git a/drivers/ub/hw/hns3/hns3_udma_jfr.h b/drivers/ub/hw/hns3/hns3_udma_jfr.h index 203f33cc14c5..1735840f3340 100644 --- a/drivers/ub/hw/hns3/hns3_udma_jfr.h +++ b/drivers/ub/hw/hns3/hns3_udma_jfr.h @@ -50,6 +50,7 @@ struct udma_jfr { uint32_t qpn; enum ubcore_transport_mode tp_mode; bool share_jfr; + struct udma_ucontext *udma_uctx; }; struct udma_jfr_context { -- Gitee