Skip to content

Commit 7f3969b

Browse files
Chengchang Tangjgunthorpe
authored andcommitted
RDMA/hns: Fix base address table allocation
For hns, the specification of an entry like resource (E.g. WQE/CQE/EQE) depends on BT page size, buf page size and hopnum. For user mode, the buf page size depends on UMEM. Therefore, the actual specification is controlled by BT page size and hopnum. The current BT page size and hopnum are obtained from firmware. This makes the driver inflexible and introduces unnecessary constraints. Resource allocation failures occur in many scenarios. This patch will calculate whether the BT page size set by firmware is sufficient before allocating BT, and increase the BT page size if it is insufficient. Fixes: 1133401 ("RDMA/hns: Optimize base address table config flow for qp buffer") Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Chengchang Tang <[email protected]> Signed-off-by: Junxian Huang <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 58caa2a commit 7f3969b

File tree

1 file changed

+43
-0
lines changed

1 file changed

+43
-0
lines changed

drivers/infiniband/hw/hns/hns_roce_mr.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
#include <linux/vmalloc.h>
3535
#include <rdma/ib_umem.h>
36+
#include <linux/math.h>
3637
#include "hns_roce_device.h"
3738
#include "hns_roce_cmd.h"
3839
#include "hns_roce_hem.h"
@@ -909,6 +910,44 @@ static int mtr_init_buf_cfg(struct hns_roce_dev *hr_dev,
909910
return page_cnt;
910911
}
911912

913+
static u64 cal_pages_per_l1ba(unsigned int ba_per_bt, unsigned int hopnum)
914+
{
915+
return int_pow(ba_per_bt, hopnum - 1);
916+
}
917+
918+
static unsigned int cal_best_bt_pg_sz(struct hns_roce_dev *hr_dev,
919+
struct hns_roce_mtr *mtr,
920+
unsigned int pg_shift)
921+
{
922+
unsigned long cap = hr_dev->caps.page_size_cap;
923+
struct hns_roce_buf_region *re;
924+
unsigned int pgs_per_l1ba;
925+
unsigned int ba_per_bt;
926+
unsigned int ba_num;
927+
int i;
928+
929+
for_each_set_bit_from(pg_shift, &cap, sizeof(cap) * BITS_PER_BYTE) {
930+
if (!(BIT(pg_shift) & cap))
931+
continue;
932+
933+
ba_per_bt = BIT(pg_shift) / BA_BYTE_LEN;
934+
ba_num = 0;
935+
for (i = 0; i < mtr->hem_cfg.region_count; i++) {
936+
re = &mtr->hem_cfg.region[i];
937+
if (re->hopnum == 0)
938+
continue;
939+
940+
pgs_per_l1ba = cal_pages_per_l1ba(ba_per_bt, re->hopnum);
941+
ba_num += DIV_ROUND_UP(re->count, pgs_per_l1ba);
942+
}
943+
944+
if (ba_num <= ba_per_bt)
945+
return pg_shift;
946+
}
947+
948+
return 0;
949+
}
950+
912951
static int mtr_alloc_mtt(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
913952
unsigned int ba_page_shift)
914953
{
@@ -917,6 +956,10 @@ static int mtr_alloc_mtt(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
917956

918957
hns_roce_hem_list_init(&mtr->hem_list);
919958
if (!cfg->is_direct) {
959+
ba_page_shift = cal_best_bt_pg_sz(hr_dev, mtr, ba_page_shift);
960+
if (!ba_page_shift)
961+
return -ERANGE;
962+
920963
ret = hns_roce_hem_list_request(hr_dev, &mtr->hem_list,
921964
cfg->region, cfg->region_count,
922965
ba_page_shift);

0 commit comments

Comments
 (0)