Skip to content

Commit 95f6918

Browse files
committed
UCT/IB/MLX5: Parse PUT WQEs for outstanding purge
1 parent 7dc59e5 commit 95f6918

2 files changed

Lines changed: 281 additions & 5 deletions

File tree

src/uct/ib/mlx5/rc/rc_mlx5_common.c

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,262 @@
1515
#include <uct/ib/rc/base/rc_iface.h>
1616
#include <ucs/arch/bitops.h>
1717
#include <ucs/profile/profile.h>
18+
#include <endian.h>
19+
#include <string.h>
20+
21+
static void uct_rc_mlx5_get_dptr_buffer(uct_rc_iface_send_op_t *op,
22+
const struct mlx5_wqe_data_seg *dptr,
23+
void **buffer_p, size_t *length_p,
24+
int *is_dm_p)
25+
{
26+
uct_rc_iface_send_desc_t *desc;
27+
void *wqe_buffer;
28+
void *buffer;
29+
30+
ucs_assert(op != NULL);
31+
ucs_assert((void*)op->handler == (void*)ucs_mpool_put);
32+
33+
desc = ucs_derived_of(op, uct_rc_iface_send_desc_t);
34+
wqe_buffer = (void*)(uintptr_t)be64toh(dptr->addr);
35+
*is_dm_p = wqe_buffer != (desc + 1);
36+
buffer = *is_dm_p ? op->buffer : wqe_buffer;
37+
*length_p = ntohl(dptr->byte_count);
38+
39+
ucs_assert((buffer != NULL) || (*length_p == 0));
40+
41+
*buffer_p = buffer;
42+
}
43+
44+
static void uct_rc_mlx5_op_info_fill_comp(uct_ep_op_info_t *info,
45+
uct_rc_iface_send_op_t *op)
46+
{
47+
if ((op != NULL) && (op->user_comp != NULL)) {
48+
info->field_mask |= UCT_EP_OP_INFO_FIELD_COMP;
49+
info->comp = op->user_comp;
50+
}
51+
}
52+
53+
static void
54+
uct_rc_mlx5_op_info_fill_rma_raddr(uct_ep_op_info_t *info,
55+
const struct mlx5_wqe_raddr_seg *raddr)
56+
{
57+
info->field_mask = UCT_EP_OP_INFO_FIELD_OPERATION |
58+
UCT_EP_OP_INFO_FIELD_RMA;
59+
info->rma.field_mask = UCT_EP_OP_INFO_RMA_FIELD_REMOTE_ADDR |
60+
UCT_EP_OP_INFO_RMA_FIELD_RKEY;
61+
info->rma.remote_addr = be64toh(raddr->raddr);
62+
info->rma.rkey = ntohl(raddr->rkey);
63+
}
64+
65+
static ucs_status_t uct_rc_mlx5_op_info_fill_zcopy_iov(
66+
uct_rc_mlx5_op_callback_data_t *callback_data,
67+
const uct_ib_mlx5_txwq_t *txwq, const void *first_dptr, size_t length,
68+
size_t *iovcnt_p)
69+
{
70+
const struct mlx5_wqe_data_seg *dptr;
71+
uint32_t byte_count;
72+
size_t iovcnt, i;
73+
74+
if ((length % sizeof(*dptr)) != 0) {
75+
return UCS_ERR_INVALID_PARAM;
76+
}
77+
78+
iovcnt = length / sizeof(*dptr);
79+
if (iovcnt > ucs_static_array_size(callback_data->iov)) {
80+
return UCS_ERR_INVALID_PARAM;
81+
}
82+
83+
dptr = uct_ib_mlx5_txwq_wrap_any((uct_ib_mlx5_txwq_t*)txwq,
84+
(void*)first_dptr);
85+
for (i = 0; i < iovcnt; ++i) {
86+
byte_count = ntohl(dptr->byte_count);
87+
if (byte_count & MLX5_INLINE_SEG) {
88+
return UCS_ERR_INVALID_PARAM;
89+
}
90+
91+
callback_data->memh[i].lkey = ntohl(dptr->lkey);
92+
callback_data->memh[i].rkey = UCT_IB_INVALID_MKEY;
93+
callback_data->memh[i].flags = 0;
94+
callback_data->iov[i].buffer = (void*)(uintptr_t)be64toh(dptr->addr);
95+
callback_data->iov[i].length = byte_count;
96+
callback_data->iov[i].memh = &callback_data->memh[i];
97+
callback_data->iov[i].stride = 0;
98+
callback_data->iov[i].count = 1;
99+
100+
dptr = uct_ib_mlx5_txwq_wrap_any((uct_ib_mlx5_txwq_t*)txwq,
101+
(void*)(dptr + 1));
102+
}
103+
104+
*iovcnt_p = iovcnt;
105+
return UCS_OK;
106+
}
107+
108+
static void
109+
uct_rc_mlx5_op_info_fill_put_null(uct_ep_op_info_t *info,
110+
const struct mlx5_wqe_raddr_seg *raddr)
111+
{
112+
uct_rc_mlx5_op_info_fill_rma_raddr(info, raddr);
113+
114+
info->operation = UCT_EP_OP_PUT_SHORT;
115+
info->rma.field_mask |= UCT_EP_OP_INFO_RMA_FIELD_PAYLOAD_DATA;
116+
info->rma.payload.data.buffer = NULL;
117+
info->rma.payload.data.length = 0;
118+
}
119+
120+
static ucs_status_t
121+
uct_rc_mlx5_op_info_fill_put_short(uct_ep_op_info_t *info,
122+
const uct_ib_mlx5_txwq_t *txwq,
123+
const struct mlx5_wqe_inl_data_seg *inl,
124+
const struct mlx5_wqe_raddr_seg *raddr,
125+
uint8_t *callback_data,
126+
size_t callback_data_size,
127+
size_t max_inline_length)
128+
{
129+
size_t inline_length = ntohl(inl->byte_count) & ~MLX5_INLINE_SEG;
130+
131+
if ((inline_length > callback_data_size) ||
132+
(inline_length > max_inline_length)) {
133+
return UCS_ERR_INVALID_PARAM;
134+
}
135+
136+
uct_ib_mlx5_txwq_copy_data(txwq, inl + 1, callback_data, inline_length);
137+
uct_rc_mlx5_op_info_fill_rma_raddr(info, raddr);
138+
139+
info->operation = UCT_EP_OP_PUT_SHORT;
140+
info->rma.field_mask |= UCT_EP_OP_INFO_RMA_FIELD_PAYLOAD_DATA;
141+
info->rma.payload.data.buffer = callback_data;
142+
info->rma.payload.data.length = inline_length;
143+
144+
return UCS_OK;
145+
}
146+
147+
static void
148+
uct_rc_mlx5_op_info_fill_put_bcopy(uct_ep_op_info_t *info,
149+
uct_rc_iface_send_op_t *op,
150+
const struct mlx5_wqe_data_seg *dptr,
151+
const struct mlx5_wqe_raddr_seg *raddr)
152+
{
153+
size_t length;
154+
void *buffer;
155+
int is_dm;
156+
157+
uct_rc_mlx5_get_dptr_buffer(op, dptr, &buffer, &length, &is_dm);
158+
uct_rc_mlx5_op_info_fill_rma_raddr(info, raddr);
159+
160+
info->operation = is_dm ? UCT_EP_OP_PUT_SHORT : UCT_EP_OP_PUT_BCOPY;
161+
info->rma.field_mask |= UCT_EP_OP_INFO_RMA_FIELD_PAYLOAD_DATA;
162+
info->rma.payload.data.buffer = buffer;
163+
info->rma.payload.data.length = length;
164+
}
165+
166+
static ucs_status_t uct_rc_mlx5_op_info_fill_put_zcopy(
167+
uct_ep_op_info_t *info, const uct_ib_mlx5_txwq_t *txwq,
168+
uct_rc_iface_send_op_t *op, const struct mlx5_wqe_data_seg *dptr,
169+
const struct mlx5_wqe_raddr_seg *raddr, size_t wqe_size,
170+
uct_rc_mlx5_op_callback_data_t *callback_data)
171+
{
172+
size_t header_size = sizeof(struct mlx5_wqe_ctrl_seg) + sizeof(*raddr);
173+
size_t iovcnt;
174+
ucs_status_t status;
175+
176+
status = uct_rc_mlx5_op_info_fill_zcopy_iov(
177+
callback_data, txwq, dptr, wqe_size - header_size, &iovcnt);
178+
if (status != UCS_OK) {
179+
return status;
180+
}
181+
182+
uct_rc_mlx5_op_info_fill_rma_raddr(info, raddr);
183+
184+
info->operation = UCT_EP_OP_PUT_ZCOPY;
185+
info->rma.field_mask |= UCT_EP_OP_INFO_RMA_FIELD_PAYLOAD_ZCOPY;
186+
info->rma.payload.zcopy.iov = callback_data->iov;
187+
info->rma.payload.zcopy.iovcnt = iovcnt;
188+
189+
uct_rc_mlx5_op_info_fill_comp(info, op);
190+
return UCS_OK;
191+
}
192+
193+
static ucs_status_t uct_rc_mlx5_op_info_fill_put(
194+
uct_ep_op_info_t *info, const uct_ib_mlx5_txwq_t *txwq,
195+
uct_rc_iface_send_op_t *op, const struct mlx5_wqe_ctrl_seg *ctrl,
196+
size_t wqe_size, uct_rc_mlx5_op_callback_data_t *callback_data)
197+
{
198+
size_t header_size = sizeof(*ctrl) + sizeof(struct mlx5_wqe_raddr_seg);
199+
const struct mlx5_wqe_raddr_seg *raddr;
200+
const struct mlx5_wqe_inl_data_seg *inl;
201+
202+
if (wqe_size < header_size) {
203+
return UCS_ERR_INVALID_PARAM;
204+
}
205+
206+
raddr = uct_ib_mlx5_txwq_wrap_any((uct_ib_mlx5_txwq_t*)txwq,
207+
(void*)(ctrl + 1));
208+
/* Empty RDMA_WRITE: zero-length zcopy, or a dummy PUT with no payload. */
209+
if (wqe_size == header_size) {
210+
if ((op != NULL) &&
211+
(op->handler == uct_rc_ep_send_op_completion_handler)) {
212+
return uct_rc_mlx5_op_info_fill_put_zcopy(
213+
info, txwq, op,
214+
(const struct mlx5_wqe_data_seg*)(raddr + 1), raddr,
215+
wqe_size, callback_data);
216+
}
217+
218+
uct_rc_mlx5_op_info_fill_put_null(info, raddr);
219+
return UCS_OK;
220+
}
221+
222+
inl = uct_ib_mlx5_txwq_wrap_any((uct_ib_mlx5_txwq_t*)txwq,
223+
(void*)(raddr + 1));
224+
if (wqe_size < (header_size + sizeof(*inl))) {
225+
return UCS_ERR_INVALID_PARAM;
226+
}
227+
228+
if (inl->byte_count & htonl(MLX5_INLINE_SEG)) {
229+
return uct_rc_mlx5_op_info_fill_put_short(
230+
info, txwq, inl, raddr, callback_data->data,
231+
sizeof(callback_data->data),
232+
wqe_size - header_size - sizeof(*inl));
233+
}
234+
235+
if ((op == NULL) || (op->handler == uct_rc_ep_send_op_completion_handler)) {
236+
return uct_rc_mlx5_op_info_fill_put_zcopy(
237+
info, txwq, op, (const struct mlx5_wqe_data_seg*)inl, raddr,
238+
wqe_size, callback_data);
239+
}
240+
241+
if ((void*)op->handler == (void*)ucs_mpool_put) {
242+
uct_rc_mlx5_op_info_fill_put_bcopy(info, op,
243+
(const struct mlx5_wqe_data_seg*)inl,
244+
raddr);
245+
246+
return UCS_OK;
247+
}
248+
249+
ucs_diag("unsupported put op %p handler %s", op,
250+
ucs_debug_get_symbol_name((void*)op->handler));
251+
252+
return UCS_ERR_UNSUPPORTED;
253+
}
254+
255+
ucs_status_t
256+
uct_rc_mlx5_op_info_fill(uct_ep_op_info_t *info, const uct_ib_mlx5_txwq_t *txwq,
257+
uct_rc_iface_send_op_t *op,
258+
const struct mlx5_wqe_ctrl_seg *ctrl, size_t wqe_size,
259+
int *skip_p,
260+
uct_rc_mlx5_op_callback_data_t *callback_data)
261+
{
262+
*skip_p = 0;
263+
memset(info, 0, sizeof(*info));
264+
265+
switch (uct_ib_mlx5_wqe_opcode(ctrl)) {
266+
case MLX5_OPCODE_RDMA_WRITE:
267+
return uct_rc_mlx5_op_info_fill_put(info, txwq, op, ctrl, wqe_size,
268+
callback_data);
269+
default:
270+
ucs_diag("unsupported op %d", uct_ib_mlx5_wqe_opcode(ctrl));
271+
return UCS_ERR_UNSUPPORTED;
272+
}
273+
}
18274

19275

20276
ucs_config_field_t uct_rc_mlx5_common_config_table[] = {

src/uct/ib/mlx5/rc/rc_mlx5_common.h

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#define UCT_RC_MLX5_COMMON_H
99

1010
#include <uct/ib/base/ib_device.h>
11+
#include <uct/ib/base/ib_md.h>
1112
#include <uct/ib/rc/base/rc_iface.h>
1213
#include <uct/ib/rc/base/rc_ep.h>
1314
#include <uct/ib/mlx5/ib_mlx5.h>
@@ -134,11 +135,6 @@ enum {
134135
UCT_RC_MLX5_CQE_APP_OP_TM_CONSUMED_MSG = 0xA
135136
};
136137

137-
#define UCT_RC_MLX5_RMA_MAX_IOV(_av_size) \
138-
((UCT_IB_MLX5_MAX_SEND_WQE_SIZE - ((_av_size) + \
139-
sizeof(struct mlx5_wqe_raddr_seg) + sizeof(struct mlx5_wqe_ctrl_seg))) / \
140-
sizeof(struct mlx5_wqe_data_seg))
141-
142138

143139
#if IBV_HW_TM
144140
# define UCT_RC_MLX5_TM_EAGER_ZCOPY_MAX_IOV(_av_size) \
@@ -247,6 +243,30 @@ typedef struct uct_rc_mlx5_mp_hash_key {
247243
} uct_rc_mlx5_mp_hash_key_t;
248244

249245

246+
#define UCT_RC_MLX5_RMA_MAX_IOV(_av_size) \
247+
((UCT_IB_MLX5_MAX_SEND_WQE_SIZE - \
248+
((_av_size) + sizeof(struct mlx5_wqe_raddr_seg) + \
249+
sizeof(struct mlx5_wqe_ctrl_seg))) / \
250+
sizeof(struct mlx5_wqe_data_seg))
251+
252+
typedef struct {
253+
union {
254+
uint8_t data[UCT_IB_MLX5_MAX_SEND_WQE_SIZE];
255+
struct {
256+
uct_iov_t iov[UCT_RC_MLX5_RMA_MAX_IOV(0)];
257+
uct_ib_mem_t memh[UCT_RC_MLX5_RMA_MAX_IOV(0)];
258+
};
259+
};
260+
} uct_rc_mlx5_op_callback_data_t;
261+
262+
ucs_status_t
263+
uct_rc_mlx5_op_info_fill(uct_ep_op_info_t *info, const uct_ib_mlx5_txwq_t *txwq,
264+
uct_rc_iface_send_op_t *op,
265+
const struct mlx5_wqe_ctrl_seg *ctrl, size_t wqe_size,
266+
int *skip_p,
267+
uct_rc_mlx5_op_callback_data_t *callback_data);
268+
269+
250270
static UCS_F_ALWAYS_INLINE int
251271
uct_rc_mlx5_mp_hash_equal(uct_rc_mlx5_mp_hash_key_t key1,
252272
uct_rc_mlx5_mp_hash_key_t key2)

0 commit comments

Comments
 (0)