def post_send(self): """ Posts one send WQE to the SQ by doing all the required work such as building the control/data segments, updating and ringing the dbr, updating the producer indexes, etc. """ idx = self.qattr.sq.post_idx if self.qattr.sq.post_idx < self.qattr.sq.wqe_num else 0 buf_offset = self.qattr.sq.offset + (idx << dve.MLX5_SEND_WQE_SHIFT) # Prepare WQE imm_be32 = struct.unpack( "<I", struct.pack(">I", self.imm + self.qattr.sq.post_idx))[0] ctrl_seg = WqeCtrlSeg(imm=imm_be32, fm_ce_se=dve.MLX5_WQE_CTRL_CQ_UPDATE) data_seg = WqeDataSeg(self.mr.length, self.mr.lkey, self.mr.buf) ctrl_seg.opmod_idx_opcode = (self.qattr.sq.post_idx & 0xffff) << 8 | dve.MLX5_OPCODE_SEND_IMM size_in_octowords = int((ctrl_seg.sizeof() + data_seg.sizeof()) / 16) ctrl_seg.qpn_ds = self.qpn << 8 | size_in_octowords Wqe([ctrl_seg, data_seg], self.umems['qp'].umem_addr + buf_offset) self.qattr.sq.post_idx += int( (size_in_octowords * 16 + dve.MLX5_SEND_WQE_BB - 1) / dve.MLX5_SEND_WQE_BB) # Make sure descriptors are written dma.udma_to_dev_barrier() # Update the doorbell record mem.writebe32(self.umems['qp_dbr'].umem_addr, self.qattr.sq.post_idx & 0xffff, dve.MLX5_SND_DBR) dma.udma_to_dev_barrier() # Ring the doorbell and post the WQE dma.mmio_write64_as_be(self.uar['qp'].reg_addr, mem.read64(ctrl_seg.addr))
def create_queue_attrs(self): # RQ calculations wqe_size = WqeDataSeg.sizeof() * self.max_recv_sge self.qattr.rq.wqe_size = self.roundup_pow_of_two(wqe_size) max_recv_wr = self.roundup_pow_of_two(self.num_msgs) self.qattr.rq.wq_size = max(self.qattr.rq.wqe_size * max_recv_wr, dve.MLX5_SEND_WQE_BB) self.qattr.rq.wqe_num = math.ceil(self.qattr.rq.wq_size / self.qattr.rq.wqe_size) self.qattr.rq.wqe_shift = int(math.log2(self.qattr.rq.wqe_size - 1)) + 1 # SQ calculations self.qattr.sq.offset = self.qattr.rq.wq_size # 192 = max overhead size of all structs needed for all operations in RC wqe_size = 192 + WqeDataSeg.sizeof() # Align wqe size to MLX5_SEND_WQE_BB self.qattr.sq.wqe_size = (wqe_size + dve.MLX5_SEND_WQE_BB - 1) & ~(dve.MLX5_SEND_WQE_BB - 1) self.qattr.sq.wq_size = self.roundup_pow_of_two(self.qattr.sq.wqe_size * self.num_msgs) self.qattr.sq.wqe_num = math.ceil(self.qattr.sq.wq_size / dve.MLX5_SEND_WQE_BB) self.qattr.sq.wqe_shift = int(math.log2(dve.MLX5_SEND_WQE_BB))
def prepare_send_elements(self): mr = self.client.mr sge_count = 2 unit_size = mr.length / 2 data_segs = [ WqeDataSeg(unit_size, mr.lkey, mr.buf + i * unit_size) for i in range(sge_count) ] ctrl_seg = WqeCtrlSeg() ctrl_seg.fm_ce_se = dve.MLX5_WQE_CTRL_CQ_UPDATE segment_num = 1 + len(data_segs) ctrl_seg.opmod_idx_opcode = dve.MLX5_OPCODE_SEND ctrl_seg.qpn_ds = segment_num | int(self.client.qp.qp_num) << 8 self.raw_send_wqe = Wqe([ctrl_seg] + data_segs) self.regular_send_sge = SGE(mr.buf, mr.length, mr.lkey)
def post_recv(self): """ Posts one receive WQE to the RQ by doing all the required work such as building the control/data segments, updating the dbr and the producer indexes. """ buf_offset = self.qattr.rq.offset + self.qattr.rq.wqe_size * self.qattr.rq.head # Prepare WQE data_seg = WqeDataSeg(self.mr.length, self.mr.lkey, self.mr.buf) Wqe([data_seg], self.umems['qp'].umem_addr + buf_offset) # Update indexes self.qattr.rq.post_idx += 1 self.qattr.rq.head = self.qattr.rq.head + 1 if self.qattr.rq.head + 1 < self.qattr.rq.wqe_num else 0 # Update the doorbell record dma.udma_to_dev_barrier() mem.writebe32(self.umems['qp_dbr'].umem_addr, self.qattr.rq.post_idx & 0xffff, dve.MLX5_RCV_DBR)