/** * @param rx_headroom Headroom requested by the user. * @param rx_priv_len Length of transport private data to reserve (0 if unused) * @param rx_hdr_len Length of transport network header. * @param mss Maximal segment size (transport limit). */ UCS_CLASS_INIT_FUNC(uct_ib_iface_t, uct_ib_iface_ops_t *ops, uct_md_h md, uct_worker_h worker, const uct_iface_params_t *params, unsigned rx_priv_len, unsigned rx_hdr_len, unsigned tx_cq_len, size_t mss, const uct_ib_iface_config_t *config) { uct_ib_device_t *dev = &ucs_derived_of(md, uct_ib_md_t)->dev; ucs_status_t status; uint8_t port_num; UCS_CLASS_CALL_SUPER_INIT(uct_base_iface_t, &ops->super, md, worker, &config->super UCS_STATS_ARG(dev->stats)); status = uct_ib_device_find_port(dev, params->dev_name, &port_num); if (status != UCS_OK) { goto err; } self->ops = ops; self->config.rx_payload_offset = sizeof(uct_ib_iface_recv_desc_t) + ucs_max(sizeof(uct_am_recv_desc_t) + params->rx_headroom, rx_priv_len + rx_hdr_len); self->config.rx_hdr_offset = self->config.rx_payload_offset - rx_hdr_len; self->config.rx_headroom_offset= self->config.rx_payload_offset - params->rx_headroom; self->config.seg_size = ucs_min(mss, config->super.max_bcopy); self->config.tx_max_poll = config->tx.max_poll; self->config.rx_max_poll = config->rx.max_poll; self->config.rx_max_batch = ucs_min(config->rx.max_batch, config->rx.queue_len / 4); self->config.port_num = port_num; self->config.sl = config->sl; self->config.gid_index = config->gid_index; status = uct_ib_iface_init_pkey(self, config); if (status != UCS_OK) { goto err; } status = uct_ib_device_query_gid(dev, self->config.port_num, self->config.gid_index, &self->gid); if (status != UCS_OK) { goto err; } status = uct_ib_iface_init_lmc(self, config); if (status != UCS_OK) { goto err; } self->comp_channel = ibv_create_comp_channel(dev->ibv_context); if (self->comp_channel == NULL) { ucs_error("ibv_create_comp_channel() failed: %m"); status = UCS_ERR_IO_ERROR; goto err_free_path_bits; } status = ucs_sys_fcntl_modfl(self->comp_channel->fd, O_NONBLOCK, 0); if (status != UCS_OK) { goto err_destroy_comp_channel; } status = uct_ib_iface_create_cq(self, tx_cq_len, 0, &self->send_cq); if (status != UCS_OK) { goto err_destroy_comp_channel; } status = uct_ib_iface_create_cq(self, config->rx.queue_len, config->rx.inl, &self->recv_cq); if (status != UCS_OK) { goto err_destroy_send_cq; } /* Address scope and size */ if (config->addr_type == UCT_IB_IFACE_ADDRESS_TYPE_AUTO) { if (IBV_PORT_IS_LINK_LAYER_ETHERNET(uct_ib_iface_port_attr(self))) { self->addr_type = UCT_IB_ADDRESS_TYPE_ETH; } else { self->addr_type = uct_ib_address_scope(self->gid.global.subnet_prefix); } } else { ucs_assert(config->addr_type < UCT_IB_ADDRESS_TYPE_LAST); self->addr_type = config->addr_type; } self->addr_size = uct_ib_address_size(self->addr_type); ucs_debug("created uct_ib_iface_t headroom_ofs %d payload_ofs %d hdr_ofs %d data_sz %d", self->config.rx_headroom_offset, self->config.rx_payload_offset, self->config.rx_hdr_offset, self->config.seg_size); return UCS_OK; err_destroy_send_cq: ibv_destroy_cq(self->send_cq); err_destroy_comp_channel: ibv_destroy_comp_channel(self->comp_channel); err_free_path_bits: ucs_free(self->path_bits); err: return status; }
static ucs_status_t uct_ib_md_umr_qp_create(uct_ib_md_t *md) { #if HAVE_EXP_UMR struct ibv_exp_qp_init_attr qp_init_attr; struct ibv_qp_attr qp_attr; uint8_t port_num; int ret; uct_ib_device_t *ibdev; struct ibv_exp_port_attr *port_attr; ibdev = &md->dev; if (!(ibdev->dev_attr.exp_device_cap_flags & IBV_EXP_DEVICE_UMR)) { return UCS_ERR_UNSUPPORTED; } /* TODO: fix port selection. It looks like active port should be used */ port_num = ibdev->first_port; port_attr = uct_ib_device_port_attr(ibdev, port_num); memset(&qp_init_attr, 0, sizeof(qp_init_attr)); md->umr_cq = ibv_create_cq(ibdev->ibv_context, 1, NULL, NULL, 0); if (md->umr_cq == NULL) { ucs_error("failed to create UMR CQ: %m"); goto err; } qp_init_attr.qp_type = IBV_QPT_RC; qp_init_attr.send_cq = md->umr_cq; qp_init_attr.recv_cq = md->umr_cq; qp_init_attr.cap.max_inline_data = 0; qp_init_attr.cap.max_recv_sge = 1; qp_init_attr.cap.max_send_sge = 1; qp_init_attr.srq = NULL; qp_init_attr.cap.max_recv_wr = 16; qp_init_attr.cap.max_send_wr = 16; qp_init_attr.pd = md->pd; qp_init_attr.comp_mask = IBV_EXP_QP_INIT_ATTR_PD|IBV_EXP_QP_INIT_ATTR_MAX_INL_KLMS; qp_init_attr.max_inl_recv = 0; #if (HAVE_IBV_EXP_QP_CREATE_UMR_CAPS || HAVE_EXP_UMR_NEW_API) qp_init_attr.max_inl_send_klms = ibdev->dev_attr.umr_caps.max_send_wqe_inline_klms; #else qp_init_attr.max_inl_send_klms = ibdev->dev_attr.max_send_wqe_inline_klms; #endif #if HAVE_IBV_EXP_QP_CREATE_UMR qp_init_attr.comp_mask |= IBV_EXP_QP_INIT_ATTR_CREATE_FLAGS; qp_init_attr.exp_create_flags = IBV_EXP_QP_CREATE_UMR; #endif md->umr_qp = ibv_exp_create_qp(ibdev->ibv_context, &qp_init_attr); if (md->umr_qp == NULL) { ucs_error("failed to create UMR QP: %m"); goto err_destroy_cq; } memset(&qp_attr, 0, sizeof(qp_attr)); /* Modify QP to INIT state */ qp_attr.qp_state = IBV_QPS_INIT; qp_attr.pkey_index = 0; qp_attr.port_num = port_num; qp_attr.qp_access_flags = UCT_IB_MEM_ACCESS_FLAGS; ret = ibv_modify_qp(md->umr_qp, &qp_attr, IBV_QP_STATE | IBV_QP_PKEY_INDEX | IBV_QP_PORT | IBV_QP_ACCESS_FLAGS); if (ret) { ucs_error("Failed to modify UMR QP to INIT: %m"); goto err_destroy_qp; } /* Modify to RTR */ qp_attr.qp_state = IBV_QPS_RTR; qp_attr.dest_qp_num = md->umr_qp->qp_num; memset(&qp_attr.ah_attr, 0, sizeof(qp_attr.ah_attr)); qp_attr.ah_attr.port_num = port_num; qp_attr.ah_attr.dlid = port_attr->lid; qp_attr.ah_attr.is_global = 1; if (uct_ib_device_query_gid(ibdev, port_num, 0, &qp_attr.ah_attr.grh.dgid) != UCS_OK) { goto err_destroy_qp; } qp_attr.rq_psn = 0; qp_attr.path_mtu = IBV_MTU_512; qp_attr.min_rnr_timer = 7; qp_attr.max_dest_rd_atomic = 1; ret = ibv_modify_qp(md->umr_qp, &qp_attr, IBV_QP_STATE | IBV_QP_AV | IBV_QP_PATH_MTU | IBV_QP_DEST_QPN | IBV_QP_RQ_PSN | IBV_QP_MAX_DEST_RD_ATOMIC | IBV_QP_MIN_RNR_TIMER); if (ret) { ucs_error("Failed to modify UMR QP to RTR: %m"); goto err_destroy_qp; } /* Modify to RTS */ qp_attr.qp_state = IBV_QPS_RTS; qp_attr.sq_psn = 0; qp_attr.timeout = 7; qp_attr.rnr_retry = 7; qp_attr.retry_cnt = 7; qp_attr.max_rd_atomic = 1; ret = ibv_modify_qp(md->umr_qp, &qp_attr, IBV_QP_STATE | IBV_QP_TIMEOUT | IBV_QP_RETRY_CNT | IBV_QP_RETRY_CNT | IBV_QP_RNR_RETRY | IBV_QP_SQ_PSN | IBV_QP_MAX_QP_RD_ATOMIC); if (ret) { ucs_error("Failed to modify UMR QP to RTS: %m"); goto err_destroy_qp; } return UCS_OK; err_destroy_qp: ibv_destroy_qp(md->umr_qp); err_destroy_cq: ibv_destroy_cq(md->umr_cq); err: return UCS_ERR_IO_ERROR; #else return UCS_ERR_UNSUPPORTED; #endif }