Re: [PATCH for-next 3/7] RDMA/hns: Configure DCA mode for the userspace QP

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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?

> +}
> +
> +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

> +               if (ret) {
> +                       ibdev_err(ibdev, "failed to enable DCA, ret = %d.\n",
> +                                 ret);
> +                       return ret;
> +               }
> +
> +               hr_qp->en_flags |= HNS_ROCE_QP_CAP_DCA;
> +       }
> +
> +       ret = hns_roce_mtr_create(hr_dev, &hr_qp->mtr, buf_attr,
> +                                 HNS_HW_PAGE_SHIFT + hr_dev->caps.mtt_ba_pg_sz,
> +                                 udata, addr);
> +       if (ret) {
> +               ibdev_err(ibdev, "failed to create WQE mtr, ret = %d.\n", ret);
> +               if (dca_en)
> +                       hns_roce_disable_dca(hr_dev, hr_qp);
> +       }
> +
> +       return ret;
> +}
> +
> +static void free_wqe_buf(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
> +                        struct ib_udata *udata)
> +{
> +       hns_roce_mtr_destroy(hr_dev, &hr_qp->mtr);
> +
> +       if (hr_qp->en_flags & HNS_ROCE_QP_CAP_DCA)
> +               hns_roce_disable_dca(hr_dev, hr_qp);
> +}
> +
> +static int alloc_qp_wqe(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
>                         struct ib_qp_init_attr *init_attr,
>                         struct ib_udata *udata, unsigned long addr)
>  {
>         struct ib_device *ibdev = &hr_dev->ib_dev;
>         struct hns_roce_buf_attr buf_attr = {};
> +       bool dca_en;
>         int ret;
>
>         if (!udata && hr_qp->rq_inl_buf.wqe_cnt) {
> @@ -755,16 +823,16 @@ static int alloc_qp_buf(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
>                 hr_qp->rq_inl_buf.wqe_list = NULL;
>         }
>
> -       ret = set_wqe_buf_attr(hr_dev, hr_qp, &buf_attr);
> +       dca_en = check_dca_is_enable(hr_dev, !!udata, addr);
> +       ret = set_wqe_buf_attr(hr_dev, hr_qp, dca_en, &buf_attr);
>         if (ret) {
> -               ibdev_err(ibdev, "failed to split WQE buf, ret = %d.\n", ret);
> +               ibdev_err(ibdev, "failed to set WQE attr, ret = %d.\n", ret);
>                 goto err_inline;
>         }
> -       ret = hns_roce_mtr_create(hr_dev, &hr_qp->mtr, &buf_attr,
> -                                 HNS_HW_PAGE_SHIFT + hr_dev->caps.mtt_ba_pg_sz,
> -                                 udata, addr);
> +
> +       ret = alloc_wqe_buf(hr_dev, hr_qp, dca_en, &buf_attr, udata, addr);
>         if (ret) {
> -               ibdev_err(ibdev, "failed to create WQE mtr, ret = %d.\n", ret);
> +               ibdev_err(ibdev, "failed to alloc WQE buf, ret = %d.\n", ret);
>                 goto err_inline;
>         }
>
> @@ -775,9 +843,10 @@ static int alloc_qp_buf(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
>         return ret;
>  }
>
> -static void free_qp_buf(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp)
> +static void free_qp_wqe(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
> +                       struct ib_udata *udata)
>  {
> -       hns_roce_mtr_destroy(hr_dev, &hr_qp->mtr);
> +       free_wqe_buf(hr_dev, hr_qp, udata);
>         free_rq_inline_buf(hr_qp);
>  }
>
> @@ -835,7 +904,6 @@ static int alloc_qp_db(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
>                                 goto err_out;
>                         }
>                         hr_qp->en_flags |= HNS_ROCE_QP_CAP_SQ_RECORD_DB;
> -                       resp->cap_flags |= HNS_ROCE_QP_CAP_SQ_RECORD_DB;
>                 }
>
>                 if (user_qp_has_rdb(hr_dev, init_attr, udata, resp)) {
> @@ -848,7 +916,6 @@ static int alloc_qp_db(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
>                                 goto err_sdb;
>                         }
>                         hr_qp->en_flags |= HNS_ROCE_QP_CAP_RQ_RECORD_DB;
> -                       resp->cap_flags |= HNS_ROCE_QP_CAP_RQ_RECORD_DB;
>                 }
>         } else {
>                 if (hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP09)
> @@ -1027,18 +1094,18 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
>                 }
>         }
>
> -       ret = alloc_qp_buf(hr_dev, hr_qp, init_attr, udata, ucmd.buf_addr);
> -       if (ret) {
> -               ibdev_err(ibdev, "failed to alloc QP buffer, ret = %d.\n", ret);
> -               goto err_buf;
> -       }
> -
>         ret = alloc_qpn(hr_dev, hr_qp);
>         if (ret) {
>                 ibdev_err(ibdev, "failed to alloc QPN, ret = %d.\n", ret);
>                 goto err_qpn;
>         }
>
> +       ret = alloc_qp_wqe(hr_dev, hr_qp, init_attr, udata, ucmd.buf_addr);
> +       if (ret) {
> +               ibdev_err(ibdev, "failed to alloc QP buffer, ret = %d.\n", ret);
> +               goto err_buf;
> +       }
> +
>         ret = alloc_qp_db(hr_dev, hr_qp, init_attr, udata, &ucmd, &resp);
>         if (ret) {
>                 ibdev_err(ibdev, "failed to alloc QP doorbell, ret = %d.\n",
> @@ -1060,6 +1127,7 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
>         }
>
>         if (udata) {
> +               resp.cap_flags = hr_qp->en_flags;
>                 ret = ib_copy_to_udata(udata, &resp,
>                                        min(udata->outlen, sizeof(resp)));
>                 if (ret) {
> @@ -1088,10 +1156,10 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
>  err_qpc:
>         free_qp_db(hr_dev, hr_qp, udata);
>  err_db:
> +       free_qp_wqe(hr_dev, hr_qp, udata);
> +err_buf:
>         free_qpn(hr_dev, hr_qp);
>  err_qpn:
> -       free_qp_buf(hr_dev, hr_qp);
> -err_buf:
>         free_kernel_wrid(hr_qp);
>         return ret;
>  }
> @@ -1105,7 +1173,7 @@ void hns_roce_qp_destroy(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
>
>         free_qpc(hr_dev, hr_qp);
>         free_qpn(hr_dev, hr_qp);
> -       free_qp_buf(hr_dev, hr_qp);
> +       free_qp_wqe(hr_dev, hr_qp, udata);
>         free_kernel_wrid(hr_qp);
>         free_qp_db(hr_dev, hr_qp, udata);
>
> diff --git a/include/uapi/rdma/hns-abi.h b/include/uapi/rdma/hns-abi.h
> index bcca5be..99da481 100644
> --- a/include/uapi/rdma/hns-abi.h
> +++ b/include/uapi/rdma/hns-abi.h
> @@ -77,6 +77,7 @@ enum hns_roce_qp_cap_flags {
>         HNS_ROCE_QP_CAP_RQ_RECORD_DB = 1 << 0,
>         HNS_ROCE_QP_CAP_SQ_RECORD_DB = 1 << 1,
>         HNS_ROCE_QP_CAP_OWNER_DB = 1 << 2,
> +       HNS_ROCE_QP_CAP_DCA = 1 << 4,
>  };
>
>  struct hns_roce_ib_create_qp_resp {
> --
> 2.7.4
>



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux