Skip to content

Commit 0c5e259

Browse files
Luoyoumingjgunthorpe
authored andcommitted
RDMA/hns: Fix incorrect sge nums calculation
The user usually configures the number of sge through the max_send_sge parameter when creating qp, and configures the maximum size of inline data that can be sent through max_inline_data. Inline uses sge to fill data to send. Expect the following: 1) When the sge space cannot hold inline data, the sge space needs to be expanded to accommodate all inline data 2) When the sge space is enough to accommodate inline data, the upper limit of inline data can be increased so that users can send larger inline data Currently case one is not implemented. When the inline data is larger than the sge space, an error of insufficient sge space occurs. This part of the code needs to be reimplemented according to the expected rules. The calculation method of sge num is modified to take the maximum value of max_send_sge and the sge for max_inline_data to solve this problem. Fixes: 05201e0 ("RDMA/hns: Refactor process of setting extended sge") Fixes: 30b7078 ("RDMA/hns: Support inline data in extented sge space for RC") Link: https://lore.kernel.org/r/20221108133847.2304539-3-xuhaoyue1@hisilicon.com Signed-off-by: Luoyouming <luoyouming@huawei.com> Signed-off-by: Haoyue Xu <xuhaoyue1@hisilicon.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
1 parent 8eaa6f7 commit 0c5e259

File tree

5 files changed

+125
-30
lines changed

5 files changed

+125
-30
lines changed

drivers/infiniband/hw/hns/hns_roce_device.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ struct hns_roce_ucontext {
202202
struct list_head page_list;
203203
struct mutex page_mutex;
204204
struct hns_user_mmap_entry *db_mmap_entry;
205+
u32 config;
205206
};
206207

207208
struct hns_roce_pd {
@@ -334,6 +335,7 @@ struct hns_roce_wq {
334335
u32 head;
335336
u32 tail;
336337
void __iomem *db_reg;
338+
u32 ext_sge_cnt;
337339
};
338340

339341
struct hns_roce_sge {
@@ -635,6 +637,7 @@ struct hns_roce_qp {
635637
struct list_head rq_node; /* all recv qps are on a list */
636638
struct list_head sq_node; /* all send qps are on a list */
637639
struct hns_user_mmap_entry *dwqe_mmap_entry;
640+
u32 config;
638641
};
639642

640643
struct hns_roce_ib_iboe {

drivers/infiniband/hw/hns/hns_roce_hw_v2.c

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -188,29 +188,19 @@ static void set_atomic_seg(const struct ib_send_wr *wr,
188188
hr_reg_write(rc_sq_wqe, RC_SEND_WQE_SGE_NUM, valid_num_sge);
189189
}
190190

191-
static unsigned int get_std_sge_num(struct hns_roce_qp *qp)
192-
{
193-
if (qp->ibqp.qp_type == IB_QPT_GSI || qp->ibqp.qp_type == IB_QPT_UD)
194-
return 0;
195-
196-
return HNS_ROCE_SGE_IN_WQE;
197-
}
198-
199191
static int fill_ext_sge_inl_data(struct hns_roce_qp *qp,
200192
const struct ib_send_wr *wr,
201193
unsigned int *sge_idx, u32 msg_len)
202194
{
203195
struct ib_device *ibdev = &(to_hr_dev(qp->ibqp.device))->ib_dev;
204196
unsigned int left_len_in_pg;
205197
unsigned int idx = *sge_idx;
206-
unsigned int std_sge_num;
207198
unsigned int i = 0;
208199
unsigned int len;
209200
void *addr;
210201
void *dseg;
211202

212-
std_sge_num = get_std_sge_num(qp);
213-
if (msg_len > (qp->sq.max_gs - std_sge_num) * HNS_ROCE_SGE_SIZE) {
203+
if (msg_len > qp->sq.ext_sge_cnt * HNS_ROCE_SGE_SIZE) {
214204
ibdev_err(ibdev,
215205
"no enough extended sge space for inline data.\n");
216206
return -EINVAL;

drivers/infiniband/hw/hns/hns_roce_main.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,17 +354,31 @@ static int hns_roce_alloc_uar_entry(struct ib_ucontext *uctx)
354354
static int hns_roce_alloc_ucontext(struct ib_ucontext *uctx,
355355
struct ib_udata *udata)
356356
{
357-
int ret;
358357
struct hns_roce_ucontext *context = to_hr_ucontext(uctx);
359-
struct hns_roce_ib_alloc_ucontext_resp resp = {};
360358
struct hns_roce_dev *hr_dev = to_hr_dev(uctx->device);
359+
struct hns_roce_ib_alloc_ucontext_resp resp = {};
360+
struct hns_roce_ib_alloc_ucontext ucmd = {};
361+
int ret;
361362

362363
if (!hr_dev->active)
363364
return -EAGAIN;
364365

365366
resp.qp_tab_size = hr_dev->caps.num_qps;
366367
resp.srq_tab_size = hr_dev->caps.num_srqs;
367368

369+
ret = ib_copy_from_udata(&ucmd, udata,
370+
min(udata->inlen, sizeof(ucmd)));
371+
if (ret)
372+
return ret;
373+
374+
if (hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP09)
375+
context->config = ucmd.config & HNS_ROCE_EXSGE_FLAGS;
376+
377+
if (context->config & HNS_ROCE_EXSGE_FLAGS) {
378+
resp.config |= HNS_ROCE_RSP_EXSGE_FLAGS;
379+
resp.max_inline_data = hr_dev->caps.max_sq_inline;
380+
}
381+
368382
ret = hns_roce_uar_alloc(hr_dev, &context->uar);
369383
if (ret)
370384
goto error_fail_uar_alloc;

drivers/infiniband/hw/hns/hns_roce_qp.c

Lines changed: 90 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -476,38 +476,109 @@ static int set_rq_size(struct hns_roce_dev *hr_dev, struct ib_qp_cap *cap,
476476
return 0;
477477
}
478478

479-
static u32 get_wqe_ext_sge_cnt(struct hns_roce_qp *qp)
479+
static u32 get_max_inline_data(struct hns_roce_dev *hr_dev,
480+
struct ib_qp_cap *cap)
480481
{
481-
/* GSI/UD QP only has extended sge */
482-
if (qp->ibqp.qp_type == IB_QPT_GSI || qp->ibqp.qp_type == IB_QPT_UD)
483-
return qp->sq.max_gs;
484-
485-
if (qp->sq.max_gs > HNS_ROCE_SGE_IN_WQE)
486-
return qp->sq.max_gs - HNS_ROCE_SGE_IN_WQE;
482+
if (cap->max_inline_data) {
483+
cap->max_inline_data = roundup_pow_of_two(cap->max_inline_data);
484+
return min(cap->max_inline_data,
485+
hr_dev->caps.max_sq_inline);
486+
}
487487

488488
return 0;
489489
}
490490

491+
static void update_inline_data(struct hns_roce_qp *hr_qp,
492+
struct ib_qp_cap *cap)
493+
{
494+
u32 sge_num = hr_qp->sq.ext_sge_cnt;
495+
496+
if (hr_qp->config & HNS_ROCE_EXSGE_FLAGS) {
497+
if (!(hr_qp->ibqp.qp_type == IB_QPT_GSI ||
498+
hr_qp->ibqp.qp_type == IB_QPT_UD))
499+
sge_num = max((u32)HNS_ROCE_SGE_IN_WQE, sge_num);
500+
501+
cap->max_inline_data = max(cap->max_inline_data,
502+
sge_num * HNS_ROCE_SGE_SIZE);
503+
}
504+
505+
hr_qp->max_inline_data = cap->max_inline_data;
506+
}
507+
508+
static u32 get_sge_num_from_max_send_sge(bool is_ud_or_gsi,
509+
u32 max_send_sge)
510+
{
511+
unsigned int std_sge_num;
512+
unsigned int min_sge;
513+
514+
std_sge_num = is_ud_or_gsi ? 0 : HNS_ROCE_SGE_IN_WQE;
515+
min_sge = is_ud_or_gsi ? 1 : 0;
516+
return max_send_sge > std_sge_num ? (max_send_sge - std_sge_num) :
517+
min_sge;
518+
}
519+
520+
static unsigned int get_sge_num_from_max_inl_data(bool is_ud_or_gsi,
521+
u32 max_inline_data)
522+
{
523+
unsigned int inline_sge;
524+
525+
inline_sge = roundup_pow_of_two(max_inline_data) / HNS_ROCE_SGE_SIZE;
526+
527+
/*
528+
* if max_inline_data less than
529+
* HNS_ROCE_SGE_IN_WQE * HNS_ROCE_SGE_SIZE,
530+
* In addition to ud's mode, no need to extend sge.
531+
*/
532+
if (!is_ud_or_gsi && inline_sge <= HNS_ROCE_SGE_IN_WQE)
533+
inline_sge = 0;
534+
535+
return inline_sge;
536+
}
537+
491538
static void set_ext_sge_param(struct hns_roce_dev *hr_dev, u32 sq_wqe_cnt,
492539
struct hns_roce_qp *hr_qp, struct ib_qp_cap *cap)
493540
{
541+
bool is_ud_or_gsi = (hr_qp->ibqp.qp_type == IB_QPT_GSI ||
542+
hr_qp->ibqp.qp_type == IB_QPT_UD);
543+
unsigned int std_sge_num;
544+
u32 inline_ext_sge = 0;
545+
u32 ext_wqe_sge_cnt;
494546
u32 total_sge_cnt;
495-
u32 wqe_sge_cnt;
547+
548+
cap->max_inline_data = get_max_inline_data(hr_dev, cap);
496549

497550
hr_qp->sge.sge_shift = HNS_ROCE_SGE_SHIFT;
551+
std_sge_num = is_ud_or_gsi ? 0 : HNS_ROCE_SGE_IN_WQE;
552+
ext_wqe_sge_cnt = get_sge_num_from_max_send_sge(is_ud_or_gsi,
553+
cap->max_send_sge);
498554

499-
hr_qp->sq.max_gs = max(1U, cap->max_send_sge);
555+
if (hr_qp->config & HNS_ROCE_EXSGE_FLAGS) {
556+
inline_ext_sge = max(ext_wqe_sge_cnt,
557+
get_sge_num_from_max_inl_data(is_ud_or_gsi,
558+
cap->max_inline_data));
559+
hr_qp->sq.ext_sge_cnt = inline_ext_sge ?
560+
roundup_pow_of_two(inline_ext_sge) : 0;
500561

501-
wqe_sge_cnt = get_wqe_ext_sge_cnt(hr_qp);
562+
hr_qp->sq.max_gs = max(1U, (hr_qp->sq.ext_sge_cnt + std_sge_num));
563+
hr_qp->sq.max_gs = min(hr_qp->sq.max_gs, hr_dev->caps.max_sq_sg);
564+
565+
ext_wqe_sge_cnt = hr_qp->sq.ext_sge_cnt;
566+
} else {
567+
hr_qp->sq.max_gs = max(1U, cap->max_send_sge);
568+
hr_qp->sq.max_gs = min(hr_qp->sq.max_gs, hr_dev->caps.max_sq_sg);
569+
hr_qp->sq.ext_sge_cnt = hr_qp->sq.max_gs;
570+
}
502571

503572
/* If the number of extended sge is not zero, they MUST use the
504573
* space of HNS_HW_PAGE_SIZE at least.
505574
*/
506-
if (wqe_sge_cnt) {
507-
total_sge_cnt = roundup_pow_of_two(sq_wqe_cnt * wqe_sge_cnt);
575+
if (ext_wqe_sge_cnt) {
576+
total_sge_cnt = roundup_pow_of_two(sq_wqe_cnt * ext_wqe_sge_cnt);
508577
hr_qp->sge.sge_cnt = max(total_sge_cnt,
509578
(u32)HNS_HW_PAGE_SIZE / HNS_ROCE_SGE_SIZE);
510579
}
580+
581+
update_inline_data(hr_qp, cap);
511582
}
512583

513584
static int check_sq_size_with_integrity(struct hns_roce_dev *hr_dev,
@@ -556,6 +627,7 @@ static int set_user_sq_size(struct hns_roce_dev *hr_dev,
556627

557628
hr_qp->sq.wqe_shift = ucmd->log_sq_stride;
558629
hr_qp->sq.wqe_cnt = cnt;
630+
cap->max_send_sge = hr_qp->sq.max_gs;
559631

560632
return 0;
561633
}
@@ -986,13 +1058,9 @@ static int set_qp_param(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
9861058
struct hns_roce_ib_create_qp *ucmd)
9871059
{
9881060
struct ib_device *ibdev = &hr_dev->ib_dev;
1061+
struct hns_roce_ucontext *uctx;
9891062
int ret;
9901063

991-
if (init_attr->cap.max_inline_data > hr_dev->caps.max_sq_inline)
992-
init_attr->cap.max_inline_data = hr_dev->caps.max_sq_inline;
993-
994-
hr_qp->max_inline_data = init_attr->cap.max_inline_data;
995-
9961064
if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR)
9971065
hr_qp->sq_signal_bits = IB_SIGNAL_ALL_WR;
9981066
else
@@ -1015,12 +1083,17 @@ static int set_qp_param(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
10151083
return ret;
10161084
}
10171085

1086+
uctx = rdma_udata_to_drv_context(udata, struct hns_roce_ucontext,
1087+
ibucontext);
1088+
hr_qp->config = uctx->config;
10181089
ret = set_user_sq_size(hr_dev, &init_attr->cap, hr_qp, ucmd);
10191090
if (ret)
10201091
ibdev_err(ibdev,
10211092
"failed to set user SQ size, ret = %d.\n",
10221093
ret);
10231094
} else {
1095+
if (hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP09)
1096+
hr_qp->config = HNS_ROCE_EXSGE_FLAGS;
10241097
ret = set_kernel_sq_size(hr_dev, &init_attr->cap, hr_qp);
10251098
if (ret)
10261099
ibdev_err(ibdev,

include/uapi/rdma/hns-abi.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,26 @@ struct hns_roce_ib_create_qp_resp {
8585
__aligned_u64 dwqe_mmap_key;
8686
};
8787

88+
enum {
89+
HNS_ROCE_EXSGE_FLAGS = 1 << 0,
90+
};
91+
92+
enum {
93+
HNS_ROCE_RSP_EXSGE_FLAGS = 1 << 0,
94+
};
95+
8896
struct hns_roce_ib_alloc_ucontext_resp {
8997
__u32 qp_tab_size;
9098
__u32 cqe_size;
9199
__u32 srq_tab_size;
92100
__u32 reserved;
101+
__u32 config;
102+
__u32 max_inline_data;
103+
};
104+
105+
struct hns_roce_ib_alloc_ucontext {
106+
__u32 config;
107+
__u32 reserved;
93108
};
94109

95110
struct hns_roce_ib_alloc_pd_resp {

0 commit comments

Comments
 (0)