RDMA/hns: Fix wrong assignment of lp_pktn_ini in QPC
authorWeihang Li <liweihang@huawei.com>
Tue, 14 Jul 2020 11:28:58 +0000 (19:28 +0800)
committerJason Gunthorpe <jgg@nvidia.com>
Thu, 16 Jul 2020 12:52:14 +0000 (09:52 -0300)
The RoCE Engine will schedule to another QP after one has sent
(2 ^ lp_pktn_ini) packets. lp_pktn_ini is set in QPC and should be
calculated from 2 factors:

1. current MTU as a integer
2. the RoCE Engine's maximum slice length 64KB

But the driver use MTU as a enum ib_mtu and the max inline capability, the
lp_pktn_ini will be much bigger than expected which may cause traffic of
some QPs to never get scheduled.

Fixes: b713128de7a1 ("RDMA/hns: Adjust lp_pktn_ini dynamically")
Link: https://lore.kernel.org/r/1594726138-49294-1-git-send-email-liweihang@huawei.com
Signed-off-by: Weihang Li <liweihang@huawei.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
drivers/infiniband/hw/hns/hns_roce_hw_v2.c

index dd01a51816ccaae7dee2a787c6f3fa613c87ec8d..0618ced45bf80a5c36d3b8e30e33e0bbd6c371ea 100644 (file)
@@ -3954,6 +3954,15 @@ static int config_qp_sq_buf(struct hns_roce_dev *hr_dev,
        return 0;
 }
 
+static inline enum ib_mtu get_mtu(struct ib_qp *ibqp,
+                                 const struct ib_qp_attr *attr)
+{
+       if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_UD)
+               return IB_MTU_4096;
+
+       return attr->path_mtu;
+}
+
 static int modify_qp_init_to_rtr(struct ib_qp *ibqp,
                                 const struct ib_qp_attr *attr, int attr_mask,
                                 struct hns_roce_v2_qp_context *context,
@@ -3965,6 +3974,7 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp,
        struct ib_device *ibdev = &hr_dev->ib_dev;
        dma_addr_t trrl_ba;
        dma_addr_t irrl_ba;
+       enum ib_mtu mtu;
        u8 port_num;
        u64 *mtts;
        u8 *dmac;
@@ -4062,23 +4072,23 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp,
        roce_set_field(qpc_mask->byte_52_udpspn_dmac, V2_QPC_BYTE_52_DMAC_M,
                       V2_QPC_BYTE_52_DMAC_S, 0);
 
-       /* mtu*(2^LP_PKTN_INI) should not bigger than 1 message length 64kb */
+       mtu = get_mtu(ibqp, attr);
+
+       if (attr_mask & IB_QP_PATH_MTU) {
+               roce_set_field(context->byte_24_mtu_tc, V2_QPC_BYTE_24_MTU_M,
+                              V2_QPC_BYTE_24_MTU_S, mtu);
+               roce_set_field(qpc_mask->byte_24_mtu_tc, V2_QPC_BYTE_24_MTU_M,
+                              V2_QPC_BYTE_24_MTU_S, 0);
+       }
+
+#define MAX_LP_MSG_LEN 65536
+       /* MTU*(2^LP_PKTN_INI) shouldn't be bigger than 64kb */
        roce_set_field(context->byte_56_dqpn_err, V2_QPC_BYTE_56_LP_PKTN_INI_M,
                       V2_QPC_BYTE_56_LP_PKTN_INI_S,
-                      ilog2(hr_dev->caps.max_sq_inline / IB_MTU_4096));
+                      ilog2(MAX_LP_MSG_LEN / ib_mtu_enum_to_int(mtu)));
        roce_set_field(qpc_mask->byte_56_dqpn_err, V2_QPC_BYTE_56_LP_PKTN_INI_M,
                       V2_QPC_BYTE_56_LP_PKTN_INI_S, 0);
 
-       if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_UD)
-               roce_set_field(context->byte_24_mtu_tc, V2_QPC_BYTE_24_MTU_M,
-                              V2_QPC_BYTE_24_MTU_S, IB_MTU_4096);
-       else if (attr_mask & IB_QP_PATH_MTU)
-               roce_set_field(context->byte_24_mtu_tc, V2_QPC_BYTE_24_MTU_M,
-                              V2_QPC_BYTE_24_MTU_S, attr->path_mtu);
-
-       roce_set_field(qpc_mask->byte_24_mtu_tc, V2_QPC_BYTE_24_MTU_M,
-                      V2_QPC_BYTE_24_MTU_S, 0);
-
        roce_set_bit(qpc_mask->byte_108_rx_reqepsn,
                     V2_QPC_BYTE_108_RX_REQ_PSN_ERR_S, 0);
        roce_set_field(qpc_mask->byte_96_rx_reqmsn, V2_QPC_BYTE_96_RX_REQ_MSN_M,