|
15 | 15 | #include <uct/ib/rc/base/rc_iface.h> |
16 | 16 | #include <ucs/arch/bitops.h> |
17 | 17 | #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 | +} |
18 | 274 |
|
19 | 275 |
|
20 | 276 | ucs_config_field_t uct_rc_mlx5_common_config_table[] = { |
|
0 commit comments