/******************************************************************************* * FI_AV_TABLE specific implementations. ******************************************************************************/ static int table_insert(struct gnix_fid_av *av_priv, const void *addr, size_t count, fi_addr_t *fi_addr, uint64_t flags, void *context) { struct gnix_ep_name ep_name; int ret = count; size_t index, i; int *entry_err = context; if (gnix_check_capacity(av_priv, count)) { return -FI_ENOMEM; } assert(av_priv->table); for (index = av_priv->count, i = 0; i < count; index++, i++) { _gnix_get_ep_name(addr, i, &ep_name, av_priv->domain); /* check if this ep_name fits in the av context bits */ if (ep_name.name_type & GNIX_EPN_TYPE_SEP) { if ((1 << av_priv->rx_ctx_bits) < ep_name.rx_ctx_cnt) { if (flags & FI_SYNC_ERR) { entry_err[i] = -FI_EINVAL; fi_addr[i] = FI_ADDR_NOTAVAIL; ret = -FI_EINVAL; continue; } GNIX_DEBUG(FI_LOG_AV, "ep_name doesn't fit " "into the av context bits\n"); return -FI_EINVAL; } } av_priv->table[index].gnix_addr = ep_name.gnix_addr; av_priv->valid_entry_vec[index] = 1; av_priv->table[index].name_type = ep_name.name_type; av_priv->table[index].cookie = ep_name.cookie; av_priv->table[index].rx_ctx_cnt = ep_name.rx_ctx_cnt; av_priv->table[index].cm_nic_cdm_id = ep_name.cm_nic_cdm_id; av_priv->table[index].key_offset = ep_name.key_offset; if (fi_addr) fi_addr[i] = index; if (flags & FI_SYNC_ERR) { entry_err[i] = FI_SUCCESS; } } av_priv->count += count; return ret; }
static int map_insert(struct gnix_fid_av *av_priv, const void *addr, size_t count, fi_addr_t *fi_addr, uint64_t flags, void *context) { int ret; struct gnix_ep_name ep_name; struct gnix_av_addr_entry *the_entry; gnix_ht_key_t key; size_t i; struct gnix_av_block *blk = NULL; int ret_cnt = count; int *entry_err = context; assert(av_priv->map_ht != NULL); if (count == 0) return 0; blk = calloc(1, sizeof(struct gnix_av_block)); if (blk == NULL) return -FI_ENOMEM; blk->base = calloc(count, sizeof(struct gnix_av_addr_entry)); if (blk->base == NULL) { free(blk); return -FI_ENOMEM; } slist_insert_tail(&blk->slist, &av_priv->block_list); for (i = 0; i < count; i++) { _gnix_get_ep_name(addr, i, &ep_name, av_priv->domain); /* check if this ep_name fits in the av context bits */ if (ep_name.name_type & GNIX_EPN_TYPE_SEP) { if ((1 << av_priv->rx_ctx_bits) < ep_name.rx_ctx_cnt) { if (flags & FI_SYNC_ERR) { entry_err[i] = -FI_EINVAL; fi_addr[i] = FI_ADDR_NOTAVAIL; ret_cnt = -FI_EINVAL; continue; } GNIX_DEBUG(FI_LOG_DEBUG, "ep_name doesn't fit " "into the av context bits\n"); return -FI_EINVAL; } } ((struct gnix_address *)fi_addr)[i] = ep_name.gnix_addr; the_entry = &blk->base[i]; memcpy(&the_entry->gnix_addr, &ep_name.gnix_addr, sizeof(struct gnix_address)); the_entry->name_type = ep_name.name_type; the_entry->cm_nic_cdm_id = ep_name.cm_nic_cdm_id; the_entry->cookie = ep_name.cookie; the_entry->rx_ctx_cnt = ep_name.rx_ctx_cnt; memcpy(&key, &ep_name.gnix_addr, sizeof(gnix_ht_key_t)); ret = _gnix_ht_insert(av_priv->map_ht, key, the_entry); if (flags & FI_SYNC_ERR) { entry_err[i] = FI_SUCCESS; } /* * we are okay with user trying to add more * entries with same key. */ if ((ret != FI_SUCCESS) && (ret != -FI_ENOSPC)) { GNIX_WARN(FI_LOG_AV, "_gnix_ht_insert failed %d\n", ret); if (flags & FI_SYNC_ERR) { entry_err[i] = ret; fi_addr[i] = FI_ADDR_NOTAVAIL; ret_cnt = ret; continue; } return ret; } } return ret_cnt; }
int _gnix_cm_nic_alloc(struct gnix_fid_domain *domain, struct fi_info *info, uint32_t cdm_id, struct gnix_auth_key *auth_key, struct gnix_cm_nic **cm_nic_ptr) { int ret = FI_SUCCESS; struct gnix_cm_nic *cm_nic = NULL; gnix_hashtable_attr_t gnix_ht_attr = {0}; uint32_t name_type = GNIX_EPN_TYPE_UNBOUND; struct gnix_nic_attr nic_attr = {0}; struct gnix_ep_name ep_name; struct gnix_dgram_hndl_attr dgram_hndl_attr = {0}; struct gnix_dgram_hndl_attr *dgram_hndl_attr_ptr = NULL; GNIX_TRACE(FI_LOG_EP_CTRL, "\n"); *cm_nic_ptr = NULL; /* * if app has specified a src_addr in the info * argument and length matches that for gnix_ep_name * we must allocate a cm_nic, otherwise we first * check to see if there is a cm_nic already for this domain * and just use it. */ if (info->src_addr) { /*TODO (optimization): strchr to name_type and strtol */ _gnix_get_ep_name(info->src_addr, 0, &ep_name, domain); name_type = ep_name.name_type; } GNIX_INFO(FI_LOG_EP_CTRL, "creating cm_nic for %u/0x%x/%u\n", auth_key->ptag, auth_key->cookie, cdm_id); cm_nic = (struct gnix_cm_nic *)calloc(1, sizeof(*cm_nic)); if (cm_nic == NULL) { ret = -FI_ENOMEM; goto err; } /* * we have to force allocation of a new nic since we want * an a particulard cdm id */ nic_attr.must_alloc = true; nic_attr.use_cdm_id = true; nic_attr.cdm_id = cdm_id; nic_attr.auth_key = auth_key; ret = gnix_nic_alloc(domain, &nic_attr, &cm_nic->nic); if (ret != FI_SUCCESS) { GNIX_WARN(FI_LOG_EP_CTRL, "gnix_nic_alloc returned %s\n", fi_strerror(-ret)); goto err; } cm_nic->my_name.gnix_addr.cdm_id = cdm_id; cm_nic->ptag = auth_key->ptag; cm_nic->my_name.cookie = auth_key->cookie; cm_nic->my_name.gnix_addr.device_addr = cm_nic->nic->device_addr; cm_nic->domain = domain; cm_nic->ctrl_progress = domain->control_progress; cm_nic->my_name.name_type = name_type; cm_nic->poll_cnt = 0; fastlock_init(&cm_nic->wq_lock); dlist_init(&cm_nic->cm_nic_wq); /* * prep the cm nic's dgram component */ if (domain->control_progress == FI_PROGRESS_AUTO) { dgram_hndl_attr.timeout_needed = __gnix_cm_nic_timeout_needed; dgram_hndl_attr.timeout_progress = __gnix_cm_nic_timeout_progress; dgram_hndl_attr.timeout_data = (void *)cm_nic; dgram_hndl_attr.timeout = domain->params.dgram_progress_timeout; dgram_hndl_attr_ptr = &dgram_hndl_attr; }; ret = _gnix_dgram_hndl_alloc(cm_nic, domain->control_progress, dgram_hndl_attr_ptr, &cm_nic->dgram_hndl); if (ret != FI_SUCCESS) goto err; /* * allocate hash table for translating ep addresses * to ep's. * This table will not be large - how many FI_EP_RDM ep's * will an app create using one domain?, nor in the critical path * so just use defaults. */ cm_nic->addr_to_ep_ht = calloc(1, sizeof(struct gnix_hashtable)); if (cm_nic->addr_to_ep_ht == NULL) goto err; gnix_ht_attr.ht_initial_size = 64; gnix_ht_attr.ht_maximum_size = 1024; gnix_ht_attr.ht_increase_step = 2; gnix_ht_attr.ht_increase_type = GNIX_HT_INCREASE_MULT; gnix_ht_attr.ht_collision_thresh = 500; gnix_ht_attr.ht_hash_seed = 0xdeadbeefbeefdead; gnix_ht_attr.ht_internal_locking = 1; gnix_ht_attr.destructor = NULL; ret = _gnix_ht_init(cm_nic->addr_to_ep_ht, &gnix_ht_attr); if (ret != FI_SUCCESS) { GNIX_WARN(FI_LOG_EP_CTRL, "gnix_ht_init returned %s\n", fi_strerror(-ret)); goto err; } _gnix_ref_init(&cm_nic->ref_cnt, 1, __cm_nic_destruct); *cm_nic_ptr = cm_nic; pthread_mutex_lock(&gnix_cm_nic_list_lock); dlist_insert_tail(&cm_nic->cm_nic_list, &gnix_cm_nic_list); pthread_mutex_unlock(&gnix_cm_nic_list_lock); return ret; err: if (cm_nic->dgram_hndl) _gnix_dgram_hndl_free(cm_nic->dgram_hndl); if (cm_nic->nic) _gnix_nic_free(cm_nic->nic); if (cm_nic->addr_to_ep_ht) { _gnix_ht_destroy(cm_nic->addr_to_ep_ht); free(cm_nic->addr_to_ep_ht); } if (cm_nic != NULL) free(cm_nic); return ret; }