]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
RDMA/hns: Introduce limit_bank mode with better performance
authorLianfa Weng <wenglianfa@huawei.com>
Tue, 30 Dec 2025 15:49:11 +0000 (23:49 +0800)
committerLeon Romanovsky <leon@kernel.org>
Wed, 31 Dec 2025 10:33:34 +0000 (05:33 -0500)
In limit_bank mode, QPs/CQs are restricted to using half of the banks.
HW concentrates resources on these banks, thereby improving performance
compared to the default mode.

Switch between limit_bank mode and default mode by setting the cap
flag in FW. Since the number of QPs and CQs will be halved, this mode
is suitable for scenarios where fewer QPs and CQs are required.

Signed-off-by: Lianfa Weng <wenglianfa@huawei.com>
Signed-off-by: Junxian Huang <huangjunxian6@hisilicon.com>
Link: https://patch.msgid.link/20251230154911.3397584-1-huangjunxian6@hisilicon.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>
drivers/infiniband/hw/hns/hns_roce_cq.c
drivers/infiniband/hw/hns/hns_roce_device.h
drivers/infiniband/hw/hns/hns_roce_main.c
drivers/infiniband/hw/hns/hns_roce_qp.c

index 6aa82fe9dd3dfbfd0d0d9b845e8e810c3b0d1eb8..857a913326cd88d8a3341a3dded3d38d6062db4e 100644 (file)
@@ -55,7 +55,7 @@ void hns_roce_get_cq_bankid_for_uctx(struct hns_roce_ucontext *uctx)
 {
        struct hns_roce_dev *hr_dev = to_hr_dev(uctx->ibucontext.device);
        struct hns_roce_cq_table *cq_table = &hr_dev->cq_table;
-       u32 least_load = cq_table->ctx_num[0];
+       u32 least_load = U32_MAX;
        u8 bankid = 0;
        u8 i;
 
@@ -63,7 +63,10 @@ void hns_roce_get_cq_bankid_for_uctx(struct hns_roce_ucontext *uctx)
                return;
 
        mutex_lock(&cq_table->bank_mutex);
-       for (i = 1; i < HNS_ROCE_CQ_BANK_NUM; i++) {
+       for (i = 0; i < HNS_ROCE_CQ_BANK_NUM; i++) {
+               if (!(cq_table->valid_cq_bank_mask & BIT(i)))
+                       continue;
+
                if (cq_table->ctx_num[i] < least_load) {
                        least_load = cq_table->ctx_num[i];
                        bankid = i;
@@ -581,6 +584,11 @@ void hns_roce_init_cq_table(struct hns_roce_dev *hr_dev)
                cq_table->bank[i].max = hr_dev->caps.num_cqs /
                                        HNS_ROCE_CQ_BANK_NUM - 1;
        }
+
+       if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_LIMIT_BANK)
+               cq_table->valid_cq_bank_mask = VALID_CQ_BANK_MASK_LIMIT;
+       else
+               cq_table->valid_cq_bank_mask = VALID_CQ_BANK_MASK_DEFAULT;
 }
 
 void hns_roce_cleanup_cq_table(struct hns_roce_dev *hr_dev)
index 318f18cf37aa52df04ae1859e31215b58921125c..3f032b8038af0eb45d590fb9f097c01869f553c1 100644 (file)
 
 #define CQ_BANKID_SHIFT 2
 #define CQ_BANKID_MASK GENMASK(1, 0)
+#define VALID_CQ_BANK_MASK_DEFAULT 0xF
+#define VALID_CQ_BANK_MASK_LIMIT 0x9
+
+#define VALID_EXT_SGE_QP_BANK_MASK_LIMIT 0x42
 
 #define HNS_ROCE_MAX_CQ_COUNT 0xFFFF
 #define HNS_ROCE_MAX_CQ_PERIOD 0xFFFF
@@ -156,6 +160,7 @@ enum {
        HNS_ROCE_CAP_FLAG_CQE_INLINE            = BIT(19),
        HNS_ROCE_CAP_FLAG_BOND                  = BIT(21),
        HNS_ROCE_CAP_FLAG_SRQ_RECORD_DB         = BIT(22),
+       HNS_ROCE_CAP_FLAG_LIMIT_BANK            = BIT(23),
 };
 
 #define HNS_ROCE_DB_TYPE_COUNT                 2
@@ -500,6 +505,7 @@ struct hns_roce_cq_table {
        struct hns_roce_bank bank[HNS_ROCE_CQ_BANK_NUM];
        struct mutex                    bank_mutex;
        u32 ctx_num[HNS_ROCE_CQ_BANK_NUM];
+       u8 valid_cq_bank_mask;
 };
 
 struct hns_roce_srq_table {
index 2f4864ab7d4ef711aa9c776a1e2d451ccd3a7d55..a3490bab297ab222d9c34293724b6bc119d35a82 100644 (file)
@@ -259,6 +259,11 @@ static int hns_roce_query_device(struct ib_device *ib_dev,
                props->max_srq_sge = hr_dev->caps.max_srq_sges;
        }
 
+       if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_LIMIT_BANK) {
+               props->max_cq >>= 1;
+               props->max_qp >>= 1;
+       }
+
        if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_FRMR &&
            hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP09) {
                props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS;
index d1640c5fbaab8f131d2fd0506525383d11cab008..5f7ea6c1664460dac79e98027a8b7088c8bb6d3d 100644 (file)
@@ -197,22 +197,16 @@ static u8 get_affinity_cq_bank(u8 qp_bank)
        return (qp_bank >> 1) & CQ_BANKID_MASK;
 }
 
-static u8 get_least_load_bankid_for_qp(struct ib_qp_init_attr *init_attr,
-                                       struct hns_roce_bank *bank)
+static u8 get_least_load_bankid_for_qp(struct hns_roce_bank *bank, u8 valid_qp_bank_mask)
 {
 #define INVALID_LOAD_QPNUM 0xFFFFFFFF
-       struct ib_cq *scq = init_attr->send_cq;
        u32 least_load = INVALID_LOAD_QPNUM;
-       unsigned long cqn = 0;
        u8 bankid = 0;
        u32 bankcnt;
        u8 i;
 
-       if (scq)
-               cqn = to_hr_cq(scq)->cqn;
-
        for (i = 0; i < HNS_ROCE_QP_BANK_NUM; i++) {
-               if (scq && (get_affinity_cq_bank(i) != (cqn & CQ_BANKID_MASK)))
+               if (!(valid_qp_bank_mask & BIT(i)))
                        continue;
 
                bankcnt = bank[i].inuse;
@@ -246,6 +240,42 @@ static int alloc_qpn_with_bankid(struct hns_roce_bank *bank, u8 bankid,
 
        return 0;
 }
+
+static bool use_ext_sge(struct ib_qp_init_attr *init_attr)
+{
+       return init_attr->cap.max_send_sge > HNS_ROCE_SGE_IN_WQE ||
+               init_attr->qp_type == IB_QPT_UD ||
+               init_attr->qp_type == IB_QPT_GSI;
+}
+
+static u8 select_qp_bankid(struct hns_roce_dev *hr_dev,
+                          struct ib_qp_init_attr *init_attr)
+{
+       struct hns_roce_qp_table *qp_table = &hr_dev->qp_table;
+       struct hns_roce_bank *bank = qp_table->bank;
+       struct ib_cq *scq = init_attr->send_cq;
+       u8 valid_qp_bank_mask = 0;
+       unsigned long cqn = 0;
+       u8 i;
+
+       if (scq)
+               cqn = to_hr_cq(scq)->cqn;
+
+       for (i = 0; i < HNS_ROCE_QP_BANK_NUM; i++) {
+               if (scq && (get_affinity_cq_bank(i) != (cqn & CQ_BANKID_MASK)))
+                       continue;
+
+               if ((hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_LIMIT_BANK) &&
+                   use_ext_sge(init_attr) &&
+                   !(VALID_EXT_SGE_QP_BANK_MASK_LIMIT & BIT(i)))
+                       continue;
+
+               valid_qp_bank_mask |= BIT(i);
+       }
+
+       return get_least_load_bankid_for_qp(bank, valid_qp_bank_mask);
+}
+
 static int alloc_qpn(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
                     struct ib_qp_init_attr *init_attr)
 {
@@ -258,8 +288,7 @@ static int alloc_qpn(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
                num = 1;
        } else {
                mutex_lock(&qp_table->bank_mutex);
-               bankid = get_least_load_bankid_for_qp(init_attr, qp_table->bank);
-
+               bankid = select_qp_bankid(hr_dev, init_attr);
                ret = alloc_qpn_with_bankid(&qp_table->bank[bankid], bankid,
                                            &num);
                if (ret) {