Skip to content

Commit 30b7078

Browse files
Weihang Lijgunthorpe
authored andcommitted
RDMA/hns: Support inline data in extented sge space for RC
HIP08 supports RC inline up to size of 32 Bytes, and all data should be put into SQWQE. For HIP09, this capability is extended to 1024 Bytes, if length of data is longer than 32 Bytes, they will be filled into extended sge space. Link: https://lore.kernel.org/r/1599744069-9968-1-git-send-email-liweihang@huawei.com Signed-off-by: Weihang Li <liweihang@huawei.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
1 parent 05df492 commit 30b7078

File tree

4 files changed

+162
-52
lines changed

4 files changed

+162
-52
lines changed

drivers/infiniband/hw/hns/hns_roce_device.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,8 @@ struct hns_roce_qp {
665665

666666
struct hns_roce_sge sge;
667667
u32 next_sge;
668+
enum ib_mtu path_mtu;
669+
u32 max_inline_data;
668670

669671
/* 0: flush needed, 1: unneeded */
670672
unsigned long flush_flag;

drivers/infiniband/hw/hns/hns_roce_hw_v2.c

Lines changed: 150 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,67 @@ static void set_atomic_seg(const struct ib_send_wr *wr,
153153
V2_RC_SEND_WQE_BYTE_16_SGE_NUM_S, valid_num_sge);
154154
}
155155

156+
static int fill_ext_sge_inl_data(struct hns_roce_qp *qp,
157+
const struct ib_send_wr *wr,
158+
unsigned int *sge_idx, u32 msg_len)
159+
{
160+
struct ib_device *ibdev = &(to_hr_dev(qp->ibqp.device))->ib_dev;
161+
unsigned int dseg_len = sizeof(struct hns_roce_v2_wqe_data_seg);
162+
unsigned int ext_sge_sz = qp->sq.max_gs * dseg_len;
163+
unsigned int left_len_in_pg;
164+
unsigned int idx = *sge_idx;
165+
unsigned int i = 0;
166+
unsigned int len;
167+
void *addr;
168+
void *dseg;
169+
170+
if (msg_len > ext_sge_sz) {
171+
ibdev_err(ibdev,
172+
"no enough extended sge space for inline data.\n");
173+
return -EINVAL;
174+
}
175+
176+
dseg = hns_roce_get_extend_sge(qp, idx & (qp->sge.sge_cnt - 1));
177+
left_len_in_pg = hr_hw_page_align((uintptr_t)dseg) - (uintptr_t)dseg;
178+
len = wr->sg_list[0].length;
179+
addr = (void *)(unsigned long)(wr->sg_list[0].addr);
180+
181+
/* When copying data to extended sge space, the left length in page may
182+
* not long enough for current user's sge. So the data should be
183+
* splited into several parts, one in the first page, and the others in
184+
* the subsequent pages.
185+
*/
186+
while (1) {
187+
if (len <= left_len_in_pg) {
188+
memcpy(dseg, addr, len);
189+
190+
idx += len / dseg_len;
191+
192+
i++;
193+
if (i >= wr->num_sge)
194+
break;
195+
196+
left_len_in_pg -= len;
197+
len = wr->sg_list[i].length;
198+
addr = (void *)(unsigned long)(wr->sg_list[i].addr);
199+
dseg += len;
200+
} else {
201+
memcpy(dseg, addr, left_len_in_pg);
202+
203+
len -= left_len_in_pg;
204+
addr += left_len_in_pg;
205+
idx += left_len_in_pg / dseg_len;
206+
dseg = hns_roce_get_extend_sge(qp,
207+
idx & (qp->sge.sge_cnt - 1));
208+
left_len_in_pg = 1 << HNS_HW_PAGE_SHIFT;
209+
}
210+
}
211+
212+
*sge_idx = idx;
213+
214+
return 0;
215+
}
216+
156217
static void set_extend_sge(struct hns_roce_qp *qp, const struct ib_send_wr *wr,
157218
unsigned int *sge_ind, unsigned int valid_num_sge)
158219
{
@@ -177,73 +238,115 @@ static void set_extend_sge(struct hns_roce_qp *qp, const struct ib_send_wr *wr,
177238
*sge_ind = idx;
178239
}
179240

241+
static bool check_inl_data_len(struct hns_roce_qp *qp, unsigned int len)
242+
{
243+
struct hns_roce_dev *hr_dev = to_hr_dev(qp->ibqp.device);
244+
int mtu = ib_mtu_enum_to_int(qp->path_mtu);
245+
246+
if (len > qp->max_inline_data || len > mtu) {
247+
ibdev_err(&hr_dev->ib_dev,
248+
"invalid length of data, data len = %u, max inline len = %u, path mtu = %d.\n",
249+
len, qp->max_inline_data, mtu);
250+
return false;
251+
}
252+
253+
return true;
254+
}
255+
256+
static int set_rc_inl(struct hns_roce_qp *qp, const struct ib_send_wr *wr,
257+
struct hns_roce_v2_rc_send_wqe *rc_sq_wqe,
258+
unsigned int *sge_idx)
259+
{
260+
struct hns_roce_dev *hr_dev = to_hr_dev(qp->ibqp.device);
261+
u32 msg_len = le32_to_cpu(rc_sq_wqe->msg_len);
262+
struct ib_device *ibdev = &hr_dev->ib_dev;
263+
unsigned int curr_idx = *sge_idx;
264+
void *dseg = rc_sq_wqe;
265+
unsigned int i;
266+
int ret;
267+
268+
if (unlikely(wr->opcode == IB_WR_RDMA_READ)) {
269+
ibdev_err(ibdev, "invalid inline parameters!\n");
270+
return -EINVAL;
271+
}
272+
273+
if (!check_inl_data_len(qp, msg_len))
274+
return -EINVAL;
275+
276+
dseg += sizeof(struct hns_roce_v2_rc_send_wqe);
277+
278+
roce_set_bit(rc_sq_wqe->byte_4, V2_RC_SEND_WQE_BYTE_4_INLINE_S, 1);
279+
280+
if (msg_len <= HNS_ROCE_V2_MAX_RC_INL_INN_SZ) {
281+
roce_set_bit(rc_sq_wqe->byte_20,
282+
V2_RC_SEND_WQE_BYTE_20_INL_TYPE_S, 0);
283+
284+
for (i = 0; i < wr->num_sge; i++) {
285+
memcpy(dseg, ((void *)wr->sg_list[i].addr),
286+
wr->sg_list[i].length);
287+
dseg += wr->sg_list[i].length;
288+
}
289+
} else {
290+
roce_set_bit(rc_sq_wqe->byte_20,
291+
V2_RC_SEND_WQE_BYTE_20_INL_TYPE_S, 1);
292+
293+
ret = fill_ext_sge_inl_data(qp, wr, &curr_idx, msg_len);
294+
if (ret)
295+
return ret;
296+
297+
roce_set_field(rc_sq_wqe->byte_16,
298+
V2_RC_SEND_WQE_BYTE_16_SGE_NUM_M,
299+
V2_RC_SEND_WQE_BYTE_16_SGE_NUM_S,
300+
curr_idx - *sge_idx);
301+
}
302+
303+
*sge_idx = curr_idx;
304+
305+
return 0;
306+
}
307+
180308
static int set_rwqe_data_seg(struct ib_qp *ibqp, const struct ib_send_wr *wr,
181309
struct hns_roce_v2_rc_send_wqe *rc_sq_wqe,
182310
unsigned int *sge_ind,
183311
unsigned int valid_num_sge)
184312
{
185-
struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
186313
struct hns_roce_v2_wqe_data_seg *dseg =
187314
(void *)rc_sq_wqe + sizeof(struct hns_roce_v2_rc_send_wqe);
188-
struct ib_device *ibdev = &hr_dev->ib_dev;
189315
struct hns_roce_qp *qp = to_hr_qp(ibqp);
190-
void *wqe = dseg;
191316
int j = 0;
192317
int i;
193318

194-
if (wr->send_flags & IB_SEND_INLINE && valid_num_sge) {
195-
if (unlikely(le32_to_cpu(rc_sq_wqe->msg_len) >
196-
hr_dev->caps.max_sq_inline)) {
197-
ibdev_err(ibdev, "inline len(1-%d)=%d, illegal",
198-
rc_sq_wqe->msg_len,
199-
hr_dev->caps.max_sq_inline);
200-
return -EINVAL;
201-
}
319+
roce_set_field(rc_sq_wqe->byte_20,
320+
V2_RC_SEND_WQE_BYTE_20_MSG_START_SGE_IDX_M,
321+
V2_RC_SEND_WQE_BYTE_20_MSG_START_SGE_IDX_S,
322+
(*sge_ind) & (qp->sge.sge_cnt - 1));
202323

203-
if (unlikely(wr->opcode == IB_WR_RDMA_READ)) {
204-
ibdev_err(ibdev, "Not support inline data!\n");
205-
return -EINVAL;
206-
}
324+
if (wr->send_flags & IB_SEND_INLINE)
325+
return set_rc_inl(qp, wr, rc_sq_wqe, sge_ind);
207326

327+
if (valid_num_sge <= HNS_ROCE_SGE_IN_WQE) {
208328
for (i = 0; i < wr->num_sge; i++) {
209-
memcpy(wqe, ((void *)wr->sg_list[i].addr),
210-
wr->sg_list[i].length);
211-
wqe += wr->sg_list[i].length;
329+
if (likely(wr->sg_list[i].length)) {
330+
set_data_seg_v2(dseg, wr->sg_list + i);
331+
dseg++;
332+
}
212333
}
213-
214-
roce_set_bit(rc_sq_wqe->byte_4, V2_RC_SEND_WQE_BYTE_4_INLINE_S,
215-
1);
216334
} else {
217-
if (valid_num_sge <= HNS_ROCE_SGE_IN_WQE) {
218-
for (i = 0; i < wr->num_sge; i++) {
219-
if (likely(wr->sg_list[i].length)) {
220-
set_data_seg_v2(dseg, wr->sg_list + i);
221-
dseg++;
222-
}
335+
for (i = 0; i < wr->num_sge && j < HNS_ROCE_SGE_IN_WQE; i++) {
336+
if (likely(wr->sg_list[i].length)) {
337+
set_data_seg_v2(dseg, wr->sg_list + i);
338+
dseg++;
339+
j++;
223340
}
224-
} else {
225-
roce_set_field(rc_sq_wqe->byte_20,
226-
V2_RC_SEND_WQE_BYTE_20_MSG_START_SGE_IDX_M,
227-
V2_RC_SEND_WQE_BYTE_20_MSG_START_SGE_IDX_S,
228-
(*sge_ind) & (qp->sge.sge_cnt - 1));
229-
230-
for (i = 0; i < wr->num_sge && j < HNS_ROCE_SGE_IN_WQE;
231-
i++) {
232-
if (likely(wr->sg_list[i].length)) {
233-
set_data_seg_v2(dseg, wr->sg_list + i);
234-
dseg++;
235-
j++;
236-
}
237-
}
238-
239-
set_extend_sge(qp, wr, sge_ind, valid_num_sge);
240341
}
241342

242-
roce_set_field(rc_sq_wqe->byte_16,
243-
V2_RC_SEND_WQE_BYTE_16_SGE_NUM_M,
244-
V2_RC_SEND_WQE_BYTE_16_SGE_NUM_S, valid_num_sge);
343+
set_extend_sge(qp, wr, sge_ind, valid_num_sge);
245344
}
246345

346+
roce_set_field(rc_sq_wqe->byte_16,
347+
V2_RC_SEND_WQE_BYTE_16_SGE_NUM_M,
348+
V2_RC_SEND_WQE_BYTE_16_SGE_NUM_S, valid_num_sge);
349+
247350
return 0;
248351
}
249352

@@ -4154,6 +4257,7 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp,
41544257
V2_QPC_BYTE_52_DMAC_S, 0);
41554258

41564259
mtu = get_mtu(ibqp, attr);
4260+
hr_qp->path_mtu = mtu;
41574261

41584262
if (attr_mask & IB_QP_PATH_MTU) {
41594263
roce_set_field(context->byte_24_mtu_tc, V2_QPC_BYTE_24_MTU_M,

drivers/infiniband/hw/hns/hns_roce_hw_v2.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
#define HNS_ROCE_V2_MAX_SQ_SGE_NUM 64
6161
#define HNS_ROCE_V2_MAX_EXTEND_SGE_NUM 0x200000
6262
#define HNS_ROCE_V2_MAX_SQ_INLINE 0x20
63+
#define HNS_ROCE_V2_MAX_RC_INL_INN_SZ 32
6364
#define HNS_ROCE_V2_UAR_NUM 256
6465
#define HNS_ROCE_V2_PHY_UAR_NUM 1
6566
#define HNS_ROCE_V2_MAX_IRQ_NUM 65
@@ -1194,6 +1195,8 @@ struct hns_roce_v2_rc_send_wqe {
11941195
#define V2_RC_SEND_WQE_BYTE_20_MSG_START_SGE_IDX_S 0
11951196
#define V2_RC_SEND_WQE_BYTE_20_MSG_START_SGE_IDX_M GENMASK(23, 0)
11961197

1198+
#define V2_RC_SEND_WQE_BYTE_20_INL_TYPE_S 31
1199+
11971200
struct hns_roce_wqe_frmr_seg {
11981201
__le32 pbl_size;
11991202
__le32 mode_buf_pg_sz;

drivers/infiniband/hw/hns/hns_roce_qp.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -551,10 +551,9 @@ static int set_kernel_sq_size(struct hns_roce_dev *hr_dev,
551551
int ret;
552552

553553
if (!cap->max_send_wr || cap->max_send_wr > hr_dev->caps.max_wqes ||
554-
cap->max_send_sge > hr_dev->caps.max_sq_sg ||
555-
cap->max_inline_data > hr_dev->caps.max_sq_inline) {
554+
cap->max_send_sge > hr_dev->caps.max_sq_sg) {
556555
ibdev_err(ibdev,
557-
"failed to check SQ WR, SGE or inline num, ret = %d.\n",
556+
"failed to check SQ WR or SGE num, ret = %d.\n",
558557
-EINVAL);
559558
return -EINVAL;
560559
}
@@ -577,9 +576,6 @@ static int set_kernel_sq_size(struct hns_roce_dev *hr_dev,
577576
cap->max_send_wr = cnt;
578577
cap->max_send_sge = hr_qp->sq.max_gs;
579578

580-
/* We don't support inline sends for kernel QPs (yet) */
581-
cap->max_inline_data = 0;
582-
583579
return 0;
584580
}
585581

@@ -847,6 +843,11 @@ static int set_qp_param(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
847843

848844
hr_qp->ibqp.qp_type = init_attr->qp_type;
849845

846+
if (init_attr->cap.max_inline_data > hr_dev->caps.max_sq_inline)
847+
init_attr->cap.max_inline_data = hr_dev->caps.max_sq_inline;
848+
849+
hr_qp->max_inline_data = init_attr->cap.max_inline_data;
850+
850851
if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR)
851852
hr_qp->sq_signal_bits = IB_SIGNAL_ALL_WR;
852853
else

0 commit comments

Comments
 (0)