RDMA/hns: Fix the gid problem caused by free mr
[platform/kernel/linux-starfive.git] / drivers / infiniband / hw / hns / hns_roce_hw_v2.c
index 1435fe2..621e6e9 100644 (file)
@@ -192,7 +192,6 @@ static int fill_ext_sge_inl_data(struct hns_roce_qp *qp,
                                 unsigned int *sge_idx, u32 msg_len)
 {
        struct ib_device *ibdev = &(to_hr_dev(qp->ibqp.device))->ib_dev;
-       unsigned int ext_sge_sz = qp->sq.max_gs * HNS_ROCE_SGE_SIZE;
        unsigned int left_len_in_pg;
        unsigned int idx = *sge_idx;
        unsigned int i = 0;
@@ -200,7 +199,7 @@ static int fill_ext_sge_inl_data(struct hns_roce_qp *qp,
        void *addr;
        void *dseg;
 
-       if (msg_len > ext_sge_sz) {
+       if (msg_len > qp->sq.ext_sge_cnt * HNS_ROCE_SGE_SIZE) {
                ibdev_err(ibdev,
                          "no enough extended sge space for inline data.\n");
                return -EINVAL;
@@ -2631,31 +2630,124 @@ static void free_dip_list(struct hns_roce_dev *hr_dev)
        spin_unlock_irqrestore(&hr_dev->dip_list_lock, flags);
 }
 
-static void free_mr_exit(struct hns_roce_dev *hr_dev)
+static struct ib_pd *free_mr_init_pd(struct hns_roce_dev *hr_dev)
+{
+       struct hns_roce_v2_priv *priv = hr_dev->priv;
+       struct hns_roce_v2_free_mr *free_mr = &priv->free_mr;
+       struct ib_device *ibdev = &hr_dev->ib_dev;
+       struct hns_roce_pd *hr_pd;
+       struct ib_pd *pd;
+
+       hr_pd = kzalloc(sizeof(*hr_pd), GFP_KERNEL);
+       if (ZERO_OR_NULL_PTR(hr_pd))
+               return NULL;
+       pd = &hr_pd->ibpd;
+       pd->device = ibdev;
+
+       if (hns_roce_alloc_pd(pd, NULL)) {
+               ibdev_err(ibdev, "failed to create pd for free mr.\n");
+               kfree(hr_pd);
+               return NULL;
+       }
+       free_mr->rsv_pd = to_hr_pd(pd);
+       free_mr->rsv_pd->ibpd.device = &hr_dev->ib_dev;
+       free_mr->rsv_pd->ibpd.uobject = NULL;
+       free_mr->rsv_pd->ibpd.__internal_mr = NULL;
+       atomic_set(&free_mr->rsv_pd->ibpd.usecnt, 0);
+
+       return pd;
+}
+
+static struct ib_cq *free_mr_init_cq(struct hns_roce_dev *hr_dev)
+{
+       struct hns_roce_v2_priv *priv = hr_dev->priv;
+       struct hns_roce_v2_free_mr *free_mr = &priv->free_mr;
+       struct ib_device *ibdev = &hr_dev->ib_dev;
+       struct ib_cq_init_attr cq_init_attr = {};
+       struct hns_roce_cq *hr_cq;
+       struct ib_cq *cq;
+
+       cq_init_attr.cqe = HNS_ROCE_FREE_MR_USED_CQE_NUM;
+
+       hr_cq = kzalloc(sizeof(*hr_cq), GFP_KERNEL);
+       if (ZERO_OR_NULL_PTR(hr_cq))
+               return NULL;
+
+       cq = &hr_cq->ib_cq;
+       cq->device = ibdev;
+
+       if (hns_roce_create_cq(cq, &cq_init_attr, NULL)) {
+               ibdev_err(ibdev, "failed to create cq for free mr.\n");
+               kfree(hr_cq);
+               return NULL;
+       }
+       free_mr->rsv_cq = to_hr_cq(cq);
+       free_mr->rsv_cq->ib_cq.device = &hr_dev->ib_dev;
+       free_mr->rsv_cq->ib_cq.uobject = NULL;
+       free_mr->rsv_cq->ib_cq.comp_handler = NULL;
+       free_mr->rsv_cq->ib_cq.event_handler = NULL;
+       free_mr->rsv_cq->ib_cq.cq_context = NULL;
+       atomic_set(&free_mr->rsv_cq->ib_cq.usecnt, 0);
+
+       return cq;
+}
+
+static int free_mr_init_qp(struct hns_roce_dev *hr_dev, struct ib_cq *cq,
+                          struct ib_qp_init_attr *init_attr, int i)
 {
        struct hns_roce_v2_priv *priv = hr_dev->priv;
        struct hns_roce_v2_free_mr *free_mr = &priv->free_mr;
+       struct ib_device *ibdev = &hr_dev->ib_dev;
+       struct hns_roce_qp *hr_qp;
+       struct ib_qp *qp;
        int ret;
+
+       hr_qp = kzalloc(sizeof(*hr_qp), GFP_KERNEL);
+       if (ZERO_OR_NULL_PTR(hr_qp))
+               return -ENOMEM;
+
+       qp = &hr_qp->ibqp;
+       qp->device = ibdev;
+
+       ret = hns_roce_create_qp(qp, init_attr, NULL);
+       if (ret) {
+               ibdev_err(ibdev, "failed to create qp for free mr.\n");
+               kfree(hr_qp);
+               return ret;
+       }
+
+       free_mr->rsv_qp[i] = hr_qp;
+       free_mr->rsv_qp[i]->ibqp.recv_cq = cq;
+       free_mr->rsv_qp[i]->ibqp.send_cq = cq;
+
+       return 0;
+}
+
+static void free_mr_exit(struct hns_roce_dev *hr_dev)
+{
+       struct hns_roce_v2_priv *priv = hr_dev->priv;
+       struct hns_roce_v2_free_mr *free_mr = &priv->free_mr;
+       struct ib_qp *qp;
        int i;
 
        for (i = 0; i < ARRAY_SIZE(free_mr->rsv_qp); i++) {
                if (free_mr->rsv_qp[i]) {
-                       ret = ib_destroy_qp(free_mr->rsv_qp[i]);
-                       if (ret)
-                               ibdev_err(&hr_dev->ib_dev,
-                                         "failed to destroy qp in free mr.\n");
-
+                       qp = &free_mr->rsv_qp[i]->ibqp;
+                       hns_roce_v2_destroy_qp(qp, NULL);
+                       kfree(free_mr->rsv_qp[i]);
                        free_mr->rsv_qp[i] = NULL;
                }
        }
 
        if (free_mr->rsv_cq) {
-               ib_destroy_cq(free_mr->rsv_cq);
+               hns_roce_destroy_cq(&free_mr->rsv_cq->ib_cq, NULL);
+               kfree(free_mr->rsv_cq);
                free_mr->rsv_cq = NULL;
        }
 
        if (free_mr->rsv_pd) {
-               ib_dealloc_pd(free_mr->rsv_pd);
+               hns_roce_dealloc_pd(&free_mr->rsv_pd->ibpd, NULL);
+               kfree(free_mr->rsv_pd);
                free_mr->rsv_pd = NULL;
        }
 }
@@ -2664,55 +2756,46 @@ static int free_mr_alloc_res(struct hns_roce_dev *hr_dev)
 {
        struct hns_roce_v2_priv *priv = hr_dev->priv;
        struct hns_roce_v2_free_mr *free_mr = &priv->free_mr;
-       struct ib_device *ibdev = &hr_dev->ib_dev;
-       struct ib_cq_init_attr cq_init_attr = {};
        struct ib_qp_init_attr qp_init_attr = {};
        struct ib_pd *pd;
        struct ib_cq *cq;
-       struct ib_qp *qp;
        int ret;
        int i;
 
-       pd = ib_alloc_pd(ibdev, 0);
-       if (IS_ERR(pd)) {
-               ibdev_err(ibdev, "failed to create pd for free mr.\n");
-               return PTR_ERR(pd);
-       }
-       free_mr->rsv_pd = pd;
+       pd = free_mr_init_pd(hr_dev);
+       if (!pd)
+               return -ENOMEM;
 
-       cq_init_attr.cqe = HNS_ROCE_FREE_MR_USED_CQE_NUM;
-       cq = ib_create_cq(ibdev, NULL, NULL, NULL, &cq_init_attr);
-       if (IS_ERR(cq)) {
-               ibdev_err(ibdev, "failed to create cq for free mr.\n");
-               ret = PTR_ERR(cq);
-               goto create_failed;
+       cq = free_mr_init_cq(hr_dev);
+       if (!cq) {
+               ret = -ENOMEM;
+               goto create_failed_cq;
        }
-       free_mr->rsv_cq = cq;
 
        qp_init_attr.qp_type = IB_QPT_RC;
        qp_init_attr.sq_sig_type = IB_SIGNAL_ALL_WR;
-       qp_init_attr.send_cq = free_mr->rsv_cq;
-       qp_init_attr.recv_cq = free_mr->rsv_cq;
+       qp_init_attr.send_cq = cq;
+       qp_init_attr.recv_cq = cq;
        for (i = 0; i < ARRAY_SIZE(free_mr->rsv_qp); i++) {
                qp_init_attr.cap.max_send_wr = HNS_ROCE_FREE_MR_USED_SQWQE_NUM;
                qp_init_attr.cap.max_send_sge = HNS_ROCE_FREE_MR_USED_SQSGE_NUM;
                qp_init_attr.cap.max_recv_wr = HNS_ROCE_FREE_MR_USED_RQWQE_NUM;
                qp_init_attr.cap.max_recv_sge = HNS_ROCE_FREE_MR_USED_RQSGE_NUM;
 
-               qp = ib_create_qp(free_mr->rsv_pd, &qp_init_attr);
-               if (IS_ERR(qp)) {
-                       ibdev_err(ibdev, "failed to create qp for free mr.\n");
-                       ret = PTR_ERR(qp);
-                       goto create_failed;
-               }
-
-               free_mr->rsv_qp[i] = qp;
+               ret = free_mr_init_qp(hr_dev, cq, &qp_init_attr, i);
+               if (ret)
+                       goto create_failed_qp;
        }
 
        return 0;
 
-create_failed:
-       free_mr_exit(hr_dev);
+create_failed_qp:
+       hns_roce_destroy_cq(cq, NULL);
+       kfree(cq);
+
+create_failed_cq:
+       hns_roce_dealloc_pd(pd, NULL);
+       kfree(pd);
 
        return ret;
 }
@@ -2728,14 +2811,17 @@ static int free_mr_modify_rsv_qp(struct hns_roce_dev *hr_dev,
        int mask;
        int ret;
 
-       hr_qp = to_hr_qp(free_mr->rsv_qp[sl_num]);
+       hr_qp = to_hr_qp(&free_mr->rsv_qp[sl_num]->ibqp);
        hr_qp->free_mr_en = 1;
+       hr_qp->ibqp.device = ibdev;
+       hr_qp->ibqp.qp_type = IB_QPT_RC;
 
        mask = IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_PORT | IB_QP_ACCESS_FLAGS;
        attr->qp_state = IB_QPS_INIT;
        attr->port_num = 1;
        attr->qp_access_flags = IB_ACCESS_REMOTE_WRITE;
-       ret = ib_modify_qp(&hr_qp->ibqp, attr, mask);
+       ret = hr_dev->hw->modify_qp(&hr_qp->ibqp, attr, mask, IB_QPS_INIT,
+                                   IB_QPS_INIT);
        if (ret) {
                ibdev_err(ibdev, "failed to modify qp to init, ret = %d.\n",
                          ret);
@@ -2756,7 +2842,8 @@ static int free_mr_modify_rsv_qp(struct hns_roce_dev *hr_dev,
 
        rdma_ah_set_sl(&attr->ah_attr, (u8)sl_num);
 
-       ret = ib_modify_qp(&hr_qp->ibqp, attr, mask);
+       ret = hr_dev->hw->modify_qp(&hr_qp->ibqp, attr, mask, IB_QPS_INIT,
+                                   IB_QPS_RTR);
        hr_dev->loop_idc = loopback;
        if (ret) {
                ibdev_err(ibdev, "failed to modify qp to rtr, ret = %d.\n",
@@ -2770,7 +2857,8 @@ static int free_mr_modify_rsv_qp(struct hns_roce_dev *hr_dev,
        attr->sq_psn = HNS_ROCE_FREE_MR_USED_PSN;
        attr->retry_cnt = HNS_ROCE_FREE_MR_USED_QP_RETRY_CNT;
        attr->timeout = HNS_ROCE_FREE_MR_USED_QP_TIMEOUT;
-       ret = ib_modify_qp(&hr_qp->ibqp, attr, mask);
+       ret = hr_dev->hw->modify_qp(&hr_qp->ibqp, attr, mask, IB_QPS_RTR,
+                                   IB_QPS_RTS);
        if (ret)
                ibdev_err(ibdev, "failed to modify qp to rts, ret = %d.\n",
                          ret);
@@ -3414,7 +3502,7 @@ static void free_mr_send_cmd_to_hw(struct hns_roce_dev *hr_dev)
        mutex_lock(&free_mr->mutex);
 
        for (i = 0; i < ARRAY_SIZE(free_mr->rsv_qp); i++) {
-               hr_qp = to_hr_qp(free_mr->rsv_qp[i]);
+               hr_qp = free_mr->rsv_qp[i];
 
                ret = free_mr_post_send_lp_wqe(hr_qp);
                if (ret) {
@@ -3429,7 +3517,7 @@ static void free_mr_send_cmd_to_hw(struct hns_roce_dev *hr_dev)
 
        end = msecs_to_jiffies(HNS_ROCE_V2_FREE_MR_TIMEOUT) + jiffies;
        while (cqe_cnt) {
-               npolled = hns_roce_v2_poll_cq(free_mr->rsv_cq, cqe_cnt, wc);
+               npolled = hns_roce_v2_poll_cq(&free_mr->rsv_cq->ib_cq, cqe_cnt, wc);
                if (npolled < 0) {
                        ibdev_err(ibdev,
                                  "failed to poll cqe for free mr, remain %d cqe.\n",
@@ -5468,7 +5556,7 @@ static int hns_roce_v2_destroy_qp_common(struct hns_roce_dev *hr_dev,
        return ret;
 }
 
-static int hns_roce_v2_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
+int hns_roce_v2_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
 {
        struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
        struct hns_roce_qp *hr_qp = to_hr_qp(ibqp);