in prov/gni/src/gnix_ep.c [2467:2726]
int _gnix_ep_alloc(struct fid_domain *domain, struct fi_info *info,
struct gnix_ep_attr *attr,
struct fid_ep **ep, void *context)
{
int ret = FI_SUCCESS;
int err_ret;
struct gnix_fid_domain *domain_priv;
struct gnix_fid_ep *ep_priv;
gnix_ht_key_t *key_ptr;
struct gnix_auth_key *auth_key;
uint32_t cdm_id;
bool free_list_inited = false;
struct gnix_nic_attr nic_attr = {0};
GNIX_TRACE(FI_LOG_EP_CTRL, "\n");
if ((domain == NULL) || (info == NULL) || (ep == NULL) ||
(info->ep_attr == NULL))
return -FI_EINVAL;
domain_priv = container_of(domain, struct gnix_fid_domain, domain_fid);
if (info->ep_attr->auth_key_size) {
auth_key = GNIX_GET_AUTH_KEY(info->ep_attr->auth_key,
info->ep_attr->auth_key_size,
domain_priv->using_vmdh);
if (!auth_key)
return -FI_EINVAL;
} else {
auth_key = domain_priv->auth_key;
assert(auth_key);
}
ep_priv = calloc(1, sizeof(*ep_priv));
if (!ep_priv)
return -FI_ENOMEM;
ep_priv->auth_key = auth_key;
ep_priv->requires_lock = (domain_priv->thread_model !=
FI_THREAD_COMPLETION);
ep_priv->ep_fid.fid.fclass = FI_CLASS_EP;
ep_priv->ep_fid.fid.context = context;
ep_priv->ep_fid.fid.ops = &gnix_ep_fi_ops;
ep_priv->ep_fid.ops = &gnix_ep_ops;
ep_priv->domain = domain_priv;
ep_priv->type = info->ep_attr->type;
ep_priv->info = fi_dupinfo(info);
_gnix_ref_init(&ep_priv->ref_cnt, 1, __ep_destruct);
ep_priv->caps = info->caps & GNIX_EP_CAPS_FULL;
if (info->tx_attr)
ep_priv->op_flags = info->tx_attr->op_flags;
if (info->rx_attr)
ep_priv->op_flags |= info->rx_attr->op_flags;
ep_priv->op_flags &= GNIX_EP_OP_FLAGS;
ep_priv->min_multi_recv = GNIX_OPT_MIN_MULTI_RECV_DEFAULT;
if (attr && attr->msg_ops)
ep_priv->ep_fid.msg = attr->msg_ops;
else
ep_priv->ep_fid.msg = &gnix_ep_msg_ops;
if (attr && attr->rma_ops)
ep_priv->ep_fid.rma = attr->rma_ops;
else
ep_priv->ep_fid.rma = &gnix_ep_rma_ops;
if (attr && attr->tagged_ops)
ep_priv->ep_fid.tagged = attr->tagged_ops;
else
ep_priv->ep_fid.tagged = &gnix_ep_tagged_ops;
if (attr && attr->atomic_ops)
ep_priv->ep_fid.atomic = attr->atomic_ops;
else
ep_priv->ep_fid.atomic = &gnix_ep_atomic_ops;
if (attr && attr->cm_ops)
ep_priv->ep_fid.cm = attr->cm_ops;
else
ep_priv->ep_fid.cm = &gnix_ep_ops_cm;
gnix_ep_caps(ep_priv, ep_priv->caps);
ret = __init_tag_storages(ep_priv, GNIX_TAG_LIST, 1);
if (ret) {
goto err;
}
ret = __fr_freelist_init(ep_priv);
if (ret != FI_SUCCESS) {
GNIX_WARN(FI_LOG_EP_CTRL,
"Error allocating gnix_fab_req freelist (%s)",
fi_strerror(-ret));
goto err;
} else
free_list_inited = true;
/*
* try out XPMEM
*/
ret = _gnix_xpmem_handle_create(domain_priv,
&ep_priv->xpmem_hndl);
if (ret != FI_SUCCESS) {
GNIX_WARN(FI_LOG_EP_CTRL, "xpmem_handl_create returned %s\n",
fi_strerror(-ret));
}
if (attr && attr->cm_nic) {
ep_priv->cm_nic = attr->cm_nic;
_gnix_ref_get(ep_priv->cm_nic);
} else {
/*
* if a cm_nic has not yet been allocated for this
* domain, do it now. Reuse the embedded gnix_nic
* in the cm_nic as the nic for this endpoint
* to reduce demand on Aries hw resources.
*/
fastlock_acquire(&domain_priv->cm_nic_lock);
if (domain_priv->cm_nic == NULL) {
ret = _gnix_cm_nic_alloc(domain_priv, info,
cdm_id,
ep_priv->auth_key,
&domain_priv->cm_nic);
if (ret != FI_SUCCESS) {
GNIX_WARN(FI_LOG_EP_CTRL,
"_gnix_cm_nic_alloc returned %s\n",
fi_strerror(-ret));
fastlock_release(
&domain_priv->cm_nic_lock);
goto err;
}
ep_priv->cm_nic = domain_priv->cm_nic;
ep_priv->nic = ep_priv->cm_nic->nic;
_gnix_ref_get(ep_priv->nic);
} else {
ep_priv->cm_nic = domain_priv->cm_nic;
_gnix_ref_get(ep_priv->cm_nic);
}
fastlock_release(&domain_priv->cm_nic_lock);
}
ep_priv->src_addr.gnix_addr.device_addr =
ep_priv->cm_nic->my_name.gnix_addr.device_addr;
ep_priv->src_addr.cm_nic_cdm_id =
ep_priv->cm_nic->my_name.gnix_addr.cdm_id;
if (attr && attr->use_cdm_id) {
cdm_id = attr->cdm_id;
} else {
ret = _gnix_cm_nic_create_cdm_id(domain_priv, &cdm_id);
if (ret != FI_SUCCESS) {
GNIX_WARN(FI_LOG_EP_CTRL,
"gnix_cm_nic_create_cdm_id returned %s\n",
fi_strerror(-ret));
goto err;
}
}
ep_priv->src_addr.gnix_addr.cdm_id = cdm_id;
key_ptr = (gnix_ht_key_t *)&ep_priv->src_addr.gnix_addr;
ret = _gnix_ht_insert(ep_priv->cm_nic->addr_to_ep_ht,
*key_ptr,
ep_priv);
if ((ret != FI_SUCCESS) && (ret != -FI_ENOSPC)) {
GNIX_WARN(FI_LOG_EP_CTRL,
"__gnix_ht_insert returned %d\n",
ret);
goto err;
}
fastlock_init(&ep_priv->vc_lock);
ep_priv->progress_fn = NULL;
ep_priv->rx_progress_fn = NULL;
ep_priv->tx_enabled = false;
ep_priv->rx_enabled = false;
if (attr && attr->nic) {
ep_priv->nic = attr->nic;
} else {
assert(ep_priv->nic == NULL);
nic_attr.auth_key = ep_priv->auth_key;
ret = gnix_nic_alloc(domain_priv, &nic_attr,
&ep_priv->nic);
if (ret != FI_SUCCESS) {
GNIX_WARN(FI_LOG_EP_CTRL,
"gnix_nic_alloc call returned %d\n", ret);
goto err;
}
if (!(attr && attr->cm_nic)) {
ep_priv->cm_nic = domain_priv->cm_nic;
}
_gnix_ref_get(ep_priv->nic);
}
/*
* if smsg callbacks not present hook them up now
*/
if (ep_priv->nic->smsg_callbacks == NULL)
ep_priv->nic->smsg_callbacks = gnix_ep_smsg_callbacks;
_gnix_ref_get(ep_priv->domain);
*ep = &ep_priv->ep_fid;
return ret;
err:
if (ep_priv->xpmem_hndl) {
err_ret = _gnix_xpmem_handle_destroy(ep_priv->xpmem_hndl);
if (err_ret != FI_SUCCESS) {
GNIX_WARN(FI_LOG_EP_CTRL,
"_gnix_xpmem_handle_destroy returned %s\n",
fi_strerror(-err_ret));
}
}
err_ret = __destruct_tag_storages(ep_priv);
if (err_ret != FI_SUCCESS) {
GNIX_WARN(FI_LOG_EP_CTRL,
"__destruct_tag_stroages returned %s\n",
fi_strerror(-err_ret));
}
if (free_list_inited == true)
__fr_freelist_destroy(ep_priv);
if (ep_priv->cm_nic != NULL) {
err_ret = _gnix_cm_nic_free(ep_priv->cm_nic);
if (err_ret != FI_SUCCESS) {
GNIX_WARN(FI_LOG_EP_CTRL,
"_gnix_cm_nic_free returned %s\n",
fi_strerror(-err_ret));
}
}
if (ep_priv->nic != NULL) {
err_ret = _gnix_nic_free(ep_priv->nic);
if (err_ret != FI_SUCCESS) {
GNIX_WARN(FI_LOG_EP_CTRL,
"_gnix_nic_free returned %s\n",
fi_strerror(-err_ret));
}
}
free(ep_priv);
return ret;
}