On 2021/5/10 22:36, Zhu Yanjun wrote: > On Mon, May 10, 2021 at 9:28 PM Weihang Li <liweihang@xxxxxxxxxx> wrote: >> From: Xi Wang <wangxi11@xxxxxxxxxx> >> >> If the userspace driver assign a NULL to the field of 'buf_addr' in >> 'struct hns_roce_ib_create_qp' when creating QP, this means the kernel >> driver need setup the QP as DCA mode. So add a QP capability bit in >> response to indicate the userspace driver that the DCA mode has been >> enabled. >> >> Signed-off-by: Xi Wang <wangxi11@xxxxxxxxxx> >> Signed-off-by: Weihang Li <liweihang@xxxxxxxxxx> >> --- >> drivers/infiniband/hw/hns/hns_roce_dca.c | 17 +++++ >> drivers/infiniband/hw/hns/hns_roce_dca.h | 3 + >> drivers/infiniband/hw/hns/hns_roce_device.h | 5 ++ >> drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 23 +++++- >> drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 2 + >> drivers/infiniband/hw/hns/hns_roce_qp.c | 110 ++++++++++++++++++++++------ >> include/uapi/rdma/hns-abi.h | 1 + >> 7 files changed, 137 insertions(+), 24 deletions(-) >> >> diff --git a/drivers/infiniband/hw/hns/hns_roce_dca.c b/drivers/infiniband/hw/hns/hns_roce_dca.c >> index 604d6cf..5eec1fb 100644 >> --- a/drivers/infiniband/hw/hns/hns_roce_dca.c >> +++ b/drivers/infiniband/hw/hns/hns_roce_dca.c >> @@ -386,6 +386,23 @@ static void free_dca_mem(struct dca_mem *mem) >> spin_unlock(&mem->lock); >> } >> >> +int hns_roce_enable_dca(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp) >> +{ >> + struct hns_roce_dca_cfg *cfg = &hr_qp->dca_cfg; >> + >> + cfg->buf_id = HNS_DCA_INVALID_BUF_ID; >> + >> + return 0; > The returned value is always 0? You're right, I will change it to void, thank you. > >> +} >> + >> +void hns_roce_disable_dca(struct hns_roce_dev *hr_dev, >> + struct hns_roce_qp *hr_qp) >> +{ >> + struct hns_roce_dca_cfg *cfg = &hr_qp->dca_cfg; >> + >> + cfg->buf_id = HNS_DCA_INVALID_BUF_ID; >> +} >> + >> static inline struct hns_roce_ucontext * >> uverbs_attr_to_hr_uctx(struct uverbs_attr_bundle *attrs) >> { >> diff --git a/drivers/infiniband/hw/hns/hns_roce_dca.h b/drivers/infiniband/hw/hns/hns_roce_dca.h >> index 97caf03..419606ef 100644 >> --- a/drivers/infiniband/hw/hns/hns_roce_dca.h >> +++ b/drivers/infiniband/hw/hns/hns_roce_dca.h >> @@ -26,4 +26,7 @@ void hns_roce_register_udca(struct hns_roce_dev *hr_dev, >> void hns_roce_unregister_udca(struct hns_roce_dev *hr_dev, >> struct hns_roce_ucontext *uctx); >> >> +int hns_roce_enable_dca(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp); >> +void hns_roce_disable_dca(struct hns_roce_dev *hr_dev, >> + struct hns_roce_qp *hr_qp); >> #endif >> diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h >> index 28fe33f..d1ca142 100644 >> --- a/drivers/infiniband/hw/hns/hns_roce_device.h >> +++ b/drivers/infiniband/hw/hns/hns_roce_device.h >> @@ -332,6 +332,10 @@ struct hns_roce_mtr { >> struct hns_roce_hem_cfg hem_cfg; /* config for hardware addressing */ >> }; >> >> +struct hns_roce_dca_cfg { >> + u32 buf_id; >> +}; >> + >> struct hns_roce_mw { >> struct ib_mw ibmw; >> u32 pdn; >> @@ -633,6 +637,7 @@ struct hns_roce_qp { >> struct hns_roce_wq sq; >> >> struct hns_roce_mtr mtr; >> + struct hns_roce_dca_cfg dca_cfg; >> >> u32 buff_size; >> struct mutex mutex; >> diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c >> index edcfd39..9adac50 100644 >> --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c >> +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c >> @@ -350,6 +350,11 @@ static int set_rwqe_data_seg(struct ib_qp *ibqp, const struct ib_send_wr *wr, >> return 0; >> } >> >> +static inline bool check_qp_dca_enable(struct hns_roce_qp *hr_qp) >> +{ >> + return !!(hr_qp->en_flags & HNS_ROCE_QP_CAP_DCA); >> +} >> + >> static int check_send_valid(struct hns_roce_dev *hr_dev, >> struct hns_roce_qp *hr_qp) >> { >> @@ -4531,6 +4536,21 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp, >> roce_set_field(qpc_mask->byte_140_raq, V2_QPC_BYTE_140_TRRL_BA_M, >> V2_QPC_BYTE_140_TRRL_BA_S, 0); >> >> + /* hip09 reused the IRRL_HEAD fileds in hip08 */ >> + if (hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP09) { >> + if (check_qp_dca_enable(hr_qp)) { >> + roce_set_bit(context->byte_196_sq_psn, >> + V2_QPC_BYTE_196_DCA_MODE_S, 1); >> + roce_set_bit(qpc_mask->byte_196_sq_psn, >> + V2_QPC_BYTE_196_DCA_MODE_S, 0); >> + } >> + } else { >> + /* reset IRRL_HEAD */ >> + roce_set_field(qpc_mask->byte_196_sq_psn, >> + V2_QPC_BYTE_196_IRRL_HEAD_M, >> + V2_QPC_BYTE_196_IRRL_HEAD_S, 0); >> + } >> + >> context->irrl_ba = cpu_to_le32(irrl_ba >> 6); >> qpc_mask->irrl_ba = 0; >> roce_set_field(context->byte_208_irrl, V2_QPC_BYTE_208_IRRL_BA_M, >> @@ -4688,9 +4708,6 @@ static int modify_qp_rtr_to_rts(struct ib_qp *ibqp, >> roce_set_field(qpc_mask->byte_212_lsn, V2_QPC_BYTE_212_LSN_M, >> V2_QPC_BYTE_212_LSN_S, 0); >> >> - roce_set_field(qpc_mask->byte_196_sq_psn, V2_QPC_BYTE_196_IRRL_HEAD_M, >> - V2_QPC_BYTE_196_IRRL_HEAD_S, 0); >> - >> return 0; >> } >> >> diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h >> index a2100a6..eecf27c 100644 >> --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h >> +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h >> @@ -853,6 +853,8 @@ struct hns_roce_v2_qp_context { >> #define V2_QPC_BYTE_196_IRRL_HEAD_S 0 >> #define V2_QPC_BYTE_196_IRRL_HEAD_M GENMASK(7, 0) >> >> +#define V2_QPC_BYTE_196_DCA_MODE_S 6 >> + >> #define V2_QPC_BYTE_196_SQ_MAX_PSN_S 8 >> #define V2_QPC_BYTE_196_SQ_MAX_PSN_M GENMASK(31, 8) >> >> diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c b/drivers/infiniband/hw/hns/hns_roce_qp.c >> index 230a909..a8740ef 100644 >> --- a/drivers/infiniband/hw/hns/hns_roce_qp.c >> +++ b/drivers/infiniband/hw/hns/hns_roce_qp.c >> @@ -39,6 +39,7 @@ >> #include "hns_roce_common.h" >> #include "hns_roce_device.h" >> #include "hns_roce_hem.h" >> +#include "hns_roce_dca.h" >> >> static void flush_work_handle(struct work_struct *work) >> { >> @@ -589,8 +590,21 @@ static int set_user_sq_size(struct hns_roce_dev *hr_dev, >> return 0; >> } >> >> +static bool check_dca_is_enable(struct hns_roce_dev *hr_dev, bool is_user, >> + unsigned long addr) >> +{ >> + if (!(hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_DCA_MODE)) >> + return false; >> + >> + /* If the user QP's buffer addr is 0, the DCA mode should be enabled */ >> + if (is_user) >> + return !addr; >> + >> + return false; >> +} >> + >> static int set_wqe_buf_attr(struct hns_roce_dev *hr_dev, >> - struct hns_roce_qp *hr_qp, >> + struct hns_roce_qp *hr_qp, bool dca_en, >> struct hns_roce_buf_attr *buf_attr) >> { >> int buf_size; >> @@ -637,6 +651,19 @@ static int set_wqe_buf_attr(struct hns_roce_dev *hr_dev, >> buf_attr->page_shift = HNS_HW_PAGE_SHIFT + hr_dev->caps.mtt_buf_pg_sz; >> buf_attr->region_count = idx; >> >> + if (dca_en) { >> + /* >> + * When enable DCA, there's no need to alloc buffer now, and >> + * the page shift should be fixed to 4K. >> + */ >> + buf_attr->mtt_only = true; >> + buf_attr->page_shift = HNS_HW_PAGE_SHIFT; >> + } else { >> + buf_attr->mtt_only = false; >> + buf_attr->page_shift = HNS_HW_PAGE_SHIFT + >> + hr_dev->caps.mtt_buf_pg_sz; >> + } >> + >> return 0; >> } >> >> @@ -735,12 +762,53 @@ static void free_rq_inline_buf(struct hns_roce_qp *hr_qp) >> kfree(hr_qp->rq_inl_buf.wqe_list); >> } >> >> -static int alloc_qp_buf(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp, >> +static int alloc_wqe_buf(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp, >> + bool dca_en, struct hns_roce_buf_attr *buf_attr, >> + struct ib_udata *udata, unsigned long addr) >> +{ >> + struct ib_device *ibdev = &hr_dev->ib_dev; >> + int ret; >> + >> + if (dca_en) { >> + /* DCA must be enabled after the buffer size is configured. */ >> + ret = hns_roce_enable_dca(hr_dev, hr_qp); > ret is always 0. The following will not be reached. > > Zhu Yanjun > Thanks for the reminder, I will fix this. Weihang >> + if (ret) { >> + ibdev_err(ibdev, "failed to enable DCA, ret = %d.\n", >> + ret); >> + return ret; >> + } >> + >> + hr_qp->en_flags |= HNS_ROCE_QP_CAP_DCA; >> + }