static UCS_F_ALWAYS_INLINE void uct_rc_mlx5_post_send(uct_rc_mlx5_ep_t *ep, struct mlx5_wqe_ctrl_seg *ctrl, uint8_t opcode, uint8_t opmod, unsigned sig_flag, unsigned wqe_size) { unsigned n, num_seg, num_bb; void *src, *dst; uint16_t sw_pi; num_seg = ucs_div_round_up(wqe_size, UCT_IB_MLX5_WQE_SEG_SIZE); num_bb = ucs_div_round_up(wqe_size, MLX5_SEND_WQE_BB); sw_pi = ep->tx.sw_pi; uct_rc_mlx5_set_ctrl_seg(ctrl, sw_pi, opcode, opmod, ep->qp_num, sig_flag, num_seg); uct_ib_mlx5_log_tx(IBV_QPT_RC, ctrl, ep->tx.qstart, ep->tx.qend, (opcode == MLX5_OPCODE_SEND) ? uct_rc_ep_am_packet_dump : NULL); /* TODO Put memory store fence here too, to prevent WC being flushed after DBrec */ ucs_memory_cpu_store_fence(); /* Write doorbell record */ ep->tx.prev_sw_pi = sw_pi; *ep->tx.dbrec = htonl(sw_pi += num_bb); /* Make sure that doorbell record is written before ringing the doorbell */ ucs_memory_bus_store_fence(); /* Set up copy pointers */ dst = ep->tx.bf_reg; src = ctrl; /* BF copy */ /* TODO support DB without BF */ ucs_assert(wqe_size <= ep->tx.bf_size); ucs_assert(num_bb <= UCT_RC_MLX5_MAX_BB); for (n = 0; n < num_bb; ++n) { uct_rc_mlx5_bf_copy_bb(dst, src); dst += MLX5_SEND_WQE_BB; src += MLX5_SEND_WQE_BB; if (ucs_unlikely(src == ep->tx.qend)) { src = ep->tx.qstart; } } /* We don't want the compiler to reorder instructions and hurt latency */ ucs_compiler_fence(); /* Advance queue pointer */ ucs_assert(ctrl == ep->tx.seg); ep->tx.seg = src; ep->tx.sw_pi = sw_pi; /* Flip BF register */ ep->tx.bf_reg = (void*) ((uintptr_t) ep->tx.bf_reg ^ ep->tx.bf_size); uct_rc_ep_tx_posted(&ep->super, sig_flag & MLX5_WQE_CTRL_CQ_UPDATE); }
static ucs_status_t uct_ib_mlx5dv_create_ksm(uct_ib_md_t *ibmd, uct_ib_mem_t *ib_memh, off_t offset) { uct_ib_mlx5_mem_t *memh = ucs_derived_of(ib_memh, uct_ib_mlx5_mem_t); uct_ib_mlx5_md_t *md = ucs_derived_of(ibmd, uct_ib_mlx5_md_t); uint32_t out[UCT_IB_MLX5DV_ST_SZ_DW(create_mkey_out)] = {}; struct ibv_mr *mr = memh->super.mr; ucs_status_t status = UCS_OK; struct mlx5dv_pd dvpd = {}; struct mlx5dv_obj dv = {}; size_t reg_length, length, inlen; int list_size, i; void *mkc, *klm; uint32_t *in; intptr_t addr; if (!(md->flags & UCT_IB_MLX5_MD_FLAG_KSM)) { return UCS_ERR_UNSUPPORTED; } reg_length = UCT_IB_MD_MAX_MR_SIZE; addr = (intptr_t)mr->addr & ~(reg_length - 1); length = mr->length + (intptr_t)mr->addr - addr; list_size = ucs_div_round_up(length, reg_length); inlen = UCT_IB_MLX5DV_ST_SZ_BYTES(create_mkey_in) + UCT_IB_MLX5DV_ST_SZ_BYTES(klm) * list_size; in = ucs_calloc(1, inlen, "mkey mailbox"); if (in == NULL) { return UCS_ERR_NO_MEMORY; } dv.pd.in = md->super.pd; dv.pd.out = &dvpd; mlx5dv_init_obj(&dv, MLX5DV_OBJ_PD); UCT_IB_MLX5DV_SET(create_mkey_in, in, opcode, UCT_IB_MLX5_CMD_OP_CREATE_MKEY); mkc = UCT_IB_MLX5DV_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry); UCT_IB_MLX5DV_SET(mkc, mkc, access_mode_1_0, UCT_IB_MLX5_MKC_ACCESS_MODE_KSM); UCT_IB_MLX5DV_SET(mkc, mkc, a, 1); UCT_IB_MLX5DV_SET(mkc, mkc, rw, 1); UCT_IB_MLX5DV_SET(mkc, mkc, rr, 1); UCT_IB_MLX5DV_SET(mkc, mkc, lw, 1); UCT_IB_MLX5DV_SET(mkc, mkc, lr, 1); UCT_IB_MLX5DV_SET(mkc, mkc, pd, dvpd.pdn); UCT_IB_MLX5DV_SET(mkc, mkc, translations_octword_size, list_size); UCT_IB_MLX5DV_SET(mkc, mkc, log_entity_size, ucs_ilog2(reg_length)); UCT_IB_MLX5DV_SET(mkc, mkc, qpn, 0xffffff); UCT_IB_MLX5DV_SET(mkc, mkc, mkey_7_0, offset & 0xff); UCT_IB_MLX5DV_SET64(mkc, mkc, start_addr, addr + offset); UCT_IB_MLX5DV_SET64(mkc, mkc, len, length); UCT_IB_MLX5DV_SET(create_mkey_in, in, translations_octword_actual_size, list_size); klm = UCT_IB_MLX5DV_ADDR_OF(create_mkey_in, in, klm_pas_mtt); for (i = 0; i < list_size; i++) { if (i == list_size - 1) { UCT_IB_MLX5DV_SET(klm, klm, byte_count, length % reg_length); } else { UCT_IB_MLX5DV_SET(klm, klm, byte_count, reg_length); } UCT_IB_MLX5DV_SET(klm, klm, mkey, mr->lkey); UCT_IB_MLX5DV_SET64(klm, klm, address, addr + (i * reg_length)); klm += UCT_IB_MLX5DV_ST_SZ_BYTES(klm); } memh->atomic_dvmr = mlx5dv_devx_obj_create(md->super.dev.ibv_context, in, inlen, out, sizeof(out)); if (memh->atomic_dvmr == NULL) { ucs_debug("CREATE_MKEY KSM failed: %m"); status = UCS_ERR_UNSUPPORTED; md->flags &= ~UCT_IB_MLX5_MD_FLAG_KSM; goto out; } memh->super.atomic_rkey = (UCT_IB_MLX5DV_GET(create_mkey_out, out, mkey_index) << 8) | (offset & 0xff); ucs_debug("KSM registered memory %p..%p offset 0x%lx on %s rkey 0x%x", mr->addr, mr->addr + mr->length, offset, uct_ib_device_name(&md->super.dev), memh->super.atomic_rkey); out: ucs_free(in); return status; }