Exemple #1
0
int psmx_domain_check_features(struct psmx_fid_domain *domain, int ep_cap)
{
	if ((domain->caps & ep_cap & ~PSMX_SUB_CAPS) != (ep_cap & ~PSMX_SUB_CAPS)) {
		FI_INFO(&psmx_prov, FI_LOG_CORE,
			"caps mismatch: domain->caps=%llx, ep->caps=%llx, mask=%llx\n",
			domain->caps, ep_cap, ~PSMX_SUB_CAPS);
		return -FI_EOPNOTSUPP;
	}

	if ((ep_cap & FI_TAGGED) && domain->tagged_ep &&
	    ofi_recv_allowed(ep_cap))
		return -FI_EBUSY;

	if ((ep_cap & FI_MSG) && domain->msg_ep &&
	    ofi_recv_allowed(ep_cap))
		return -FI_EBUSY;

	if ((ep_cap & FI_RMA) && domain->rma_ep &&
	    ofi_rma_target_allowed(ep_cap))
		return -FI_EBUSY;

	if ((ep_cap & FI_ATOMICS) && domain->atomics_ep &&
	    ofi_rma_target_allowed(ep_cap))
		return -FI_EBUSY;

	return 0;
}
Exemple #2
0
static uint64_t ofi_get_info_caps(const struct fi_info *prov_info,
				  const struct fi_info *user_info,
				  uint32_t api_version)
{
	int prov_mode, user_mode;
	uint64_t caps;

	assert(user_info);

	caps = ofi_get_caps(prov_info->caps, user_info->caps, prov_info->caps);

	prov_mode = prov_info->domain_attr->mr_mode;

	if (!ofi_rma_target_allowed(caps) ||
	    !(prov_mode & OFI_MR_MODE_RMA_TARGET))
		return caps;

	if (!user_info->domain_attr)
		goto trim_caps;

	user_mode = user_info->domain_attr->mr_mode;

	if ((FI_VERSION_LT(api_version, FI_VERSION(1,5)) &&
	    (user_mode == FI_MR_UNSPEC)) ||
	    (user_mode == FI_MR_BASIC) ||
	    ((user_mode & prov_mode & OFI_MR_MODE_RMA_TARGET) == 
	     (prov_mode & OFI_MR_MODE_RMA_TARGET)))
		return caps;

trim_caps:
	return caps & ~(FI_REMOTE_WRITE | FI_REMOTE_READ);
}
Exemple #3
0
int psmx_domain_enable_ep(struct psmx_fid_domain *domain, struct psmx_fid_ep *ep)
{
	uint64_t ep_cap = 0;

	if (ep)
		ep_cap = ep->caps;

	if ((domain->caps & ep_cap & ~PSMX_SUB_CAPS) != (ep_cap & ~PSMX_SUB_CAPS)) {
		FI_INFO(&psmx_prov, FI_LOG_CORE,
			"caps mismatch: domain->caps=%llx, ep->caps=%llx, mask=%llx\n",
			domain->caps, ep_cap, ~PSMX_SUB_CAPS);
		return -FI_EOPNOTSUPP;
	}

	if (ep_cap & FI_MSG)
		domain->reserved_tag_bits |= PSMX_MSG_BIT;

	if (psmx_env.am_msg)
		domain->reserved_tag_bits &= ~PSMX_MSG_BIT;

	if ((ep_cap & FI_RMA) && psmx_env.tagged_rma)
		domain->reserved_tag_bits |= PSMX_RMA_BIT;

	if (((ep_cap & FI_RMA) || (ep_cap & FI_ATOMICS) || psmx_env.am_msg) &&
	    !domain->am_initialized) {
		int err = psmx_am_init(domain);
		if (err)
			return err;

		domain->am_initialized = 1;
	}

	if ((ep_cap & FI_RMA) && ofi_rma_target_allowed(ep_cap))
		domain->rma_ep = ep;

	if ((ep_cap & FI_ATOMICS) && ofi_rma_target_allowed(ep_cap))
		domain->atomics_ep = ep;

	if ((ep_cap & FI_TAGGED) && ofi_recv_allowed(ep_cap))
		domain->tagged_ep = ep;

	if ((ep_cap & FI_MSG) && ofi_recv_allowed(ep_cap))
		domain->msg_ep = ep;

	return 0;
}
Exemple #4
0
/*
 * Remove unneeded MR mode bits based on the requested capability bits.
 */
static int ofi_cap_mr_mode(uint64_t info_caps, int mr_mode)
{
	if (!ofi_rma_target_allowed(info_caps)) {
		if (!(mr_mode & FI_MR_LOCAL))
			return 0;

		mr_mode &= ~OFI_MR_MODE_RMA_TARGET;
	}

	return mr_mode & ~(FI_MR_BASIC | FI_MR_SCALABLE);
}
Exemple #5
0
/*
 * - Support FI_MR_LOCAL/FI_LOCAL_MR as ofi_rxm can handle it.
 * - The RxM FI_RMA implementation is pass-through but the provider can handle
 *   FI_MR_PROV_KEY and FI_MR_VIRT_ADDR in its large message transfer rendezvous
 *   protocol.
 * - fi_alter_domain_attr should correctly set the mr_mode in return fi_info
 *   based on hints.
 */
void rxm_info_to_core_mr_modes(uint32_t version, const struct fi_info *hints,
			       struct fi_info *core_info)
{
	/* We handle FI_MR_BASIC and FI_MR_SCALABLE irrespective of version */
	if (hints && hints->domain_attr &&
	    (hints->domain_attr->mr_mode & (FI_MR_SCALABLE | FI_MR_BASIC))) {
		core_info->mode = FI_LOCAL_MR;
		core_info->domain_attr->mr_mode = hints->domain_attr->mr_mode;
	} else if (FI_VERSION_LT(version, FI_VERSION(1, 5))) {
		core_info->mode |= FI_LOCAL_MR;
		/* Specify FI_MR_UNSPEC (instead of FI_MR_BASIC) so that
		 * providers that support only FI_MR_SCALABLE aren't dropped */
		core_info->domain_attr->mr_mode = FI_MR_UNSPEC;
	} else {
		core_info->domain_attr->mr_mode |= FI_MR_LOCAL;
		if (!hints || !ofi_rma_target_allowed(hints->caps))
			core_info->domain_attr->mr_mode |= OFI_MR_BASIC_MAP;
		else if (hints->domain_attr)
			core_info->domain_attr->mr_mode |=
				hints->domain_attr->mr_mode & OFI_MR_BASIC_MAP;
	}
}
Exemple #6
0
int psmx2_ep_open(struct fid_domain *domain, struct fi_info *info,
		  struct fid_ep **ep, void *context)
{
	struct psmx2_fid_domain *domain_priv;
	struct psmx2_fid_ep *ep_priv;
	struct psmx2_ep_name ep_name;
	struct psmx2_ep_name *src_addr;
	struct psmx2_trx_ctxt *trx_ctxt = NULL;
	int err = -FI_EINVAL;
	int alloc_trx_ctxt = 1;

	domain_priv = container_of(domain, struct psmx2_fid_domain,
				   util_domain.domain_fid.fid);
	if (!domain_priv)
		goto errout;

	if (info && info->ep_attr && info->ep_attr->rx_ctx_cnt == FI_SHARED_CONTEXT)
		return  -FI_ENOSYS;

	if (info && info->ep_attr && info->ep_attr->tx_ctx_cnt == FI_SHARED_CONTEXT &&
	    !ofi_recv_allowed(info->caps) && !ofi_rma_target_allowed(info->caps)) {
		alloc_trx_ctxt = 0;
		FI_INFO(&psmx2_prov, FI_LOG_EP_CTRL, "Tx only endpoint with STX context.\n");
	}

	src_addr = NULL;
	if (info && info->src_addr) {
		if (info->addr_format == FI_ADDR_STR)
			src_addr = psmx2_string_to_ep_name(info->src_addr);
		else
			src_addr = info->src_addr;
	}

	if (alloc_trx_ctxt) {
		trx_ctxt = psmx2_trx_ctxt_alloc(domain_priv, src_addr, 0);
		if (!trx_ctxt)
			goto errout;
	}

	err = psmx2_ep_open_internal(domain_priv, info, &ep_priv, context,
				     trx_ctxt);
	if (err)
		goto errout_free_ctxt;

	ep_priv->type = PSMX2_EP_REGULAR;
	ep_priv->service = PSMX2_ANY_SERVICE;
	if (src_addr) {
		ep_priv->service = src_addr->service;
		if (info->addr_format == FI_ADDR_STR)
			free(src_addr);
	}

	if (ep_priv->service == PSMX2_ANY_SERVICE)
		ep_priv->service = ((getpid() & 0x7FFF) << 16) +
				   ((uintptr_t)ep_priv & 0xFFFF);

	if (alloc_trx_ctxt) {
		trx_ctxt->ep = ep_priv;

		psmx2_lock(&domain_priv->trx_ctxt_lock, 1);
		dlist_insert_before(&trx_ctxt->entry,
				    &domain_priv->trx_ctxt_list);
		psmx2_unlock(&domain_priv->trx_ctxt_lock, 1);

		ep_name.epid = trx_ctxt->psm2_epid;
		ep_name.type = ep_priv->type;

		ofi_ns_add_local_name(&domain_priv->fabric->name_server,
				      &ep_priv->service, &ep_name);
	}

	*ep = &ep_priv->ep;
	return 0;

errout_free_ctxt:
	psmx2_trx_ctxt_free(trx_ctxt);

errout:
	return err;
}
static int fi_bgq_tx_ctx(struct fid_ep *sep, int index,
			struct fi_tx_attr *attr, struct fid_ep **tx_ep,
			void *context)
{
	int ret;
	struct fi_info info = {0};
	struct fi_tx_attr tx_attr = {0};
	struct fi_ep_attr ep_attr = {0};
	struct fi_domain_attr dom_attr = {0};
	struct fi_fabric_attr fab_attr = {0};
	struct fi_bgq_sep *bgq_sep;
	struct fi_bgq_ep  *bgq_tx_ep;

	if (!sep || !attr || !tx_ep) {
		errno = FI_EINVAL;
		return -errno;
	}

	bgq_sep = container_of(sep, struct fi_bgq_sep, ep_fid);

	uint64_t caps = attr->caps;	/* TODO - "By default, a transmit context inherits the properties of its associated endpoint. However, applications may request context specific attributes through the attr parameter." */

	if ((caps & FI_MSG || caps & FI_TAGGED) && (caps & FI_RECV)) {
		FI_LOG(fi_bgq_global.prov, FI_LOG_DEBUG, FI_LOG_DOMAIN,
				"FI_MSG|FI_TAGGED with FI_RECV capability specified for a TX context\n");
		caps &= ~FI_RECV;
	}

	if ((caps & FI_RMA || caps & FI_ATOMIC) && (caps & FI_REMOTE_READ || caps & FI_REMOTE_WRITE)) {
		FI_LOG(fi_bgq_global.prov, FI_LOG_DEBUG, FI_LOG_DOMAIN,
				"FI_RMA|FI_ATOMIC with FI_REMOTE_READ|FI_REMOTE_WRITE capability specified for a TX context\n");
		caps &= ~FI_REMOTE_READ;
		caps &= ~FI_REMOTE_WRITE;
	}

	if (caps & FI_MSG || caps & FI_TAGGED) {
		caps |= FI_SEND;
	}

	if (caps & FI_RMA || caps & FI_ATOMIC) {
		caps |= FI_READ;
		caps |= FI_WRITE;
	}

	if (ofi_recv_allowed(caps) || ofi_rma_target_allowed(caps)) {
		FI_LOG(fi_bgq_global.prov, FI_LOG_DEBUG, FI_LOG_DOMAIN,
				"RX capabilities specified for TX context\n");
		errno = FI_EINVAL;
		return -errno;
	}

	if (!ofi_send_allowed(caps) && !ofi_rma_initiate_allowed(caps)) {
		FI_LOG(fi_bgq_global.prov, FI_LOG_DEBUG, FI_LOG_DOMAIN,
				"TX capabilities not specified for TX context\n");
		errno = FI_EINVAL;
		return -errno;
	}

	if (bgq_sep->domain->tx.count >= fi_bgq_domain_get_tx_max(bgq_sep->domain)) {
		FI_LOG(fi_bgq_global.prov, FI_LOG_DEBUG, FI_LOG_DOMAIN,
				"TX ctx count exceeded (max %lu, created %lu)\n",
				fi_bgq_domain_get_tx_max(bgq_sep->domain), bgq_sep->domain->tx.count);
		errno = FI_EINVAL;
		return -errno;
	}

	info.caps = caps;
	info.mode = attr->mode;

	info.tx_attr = &tx_attr;
	memcpy(info.tx_attr, attr, sizeof(*info.tx_attr));

	info.ep_attr = &ep_attr;
	memcpy(info.ep_attr, bgq_sep->info->ep_attr, sizeof(*info.ep_attr));

	info.domain_attr = &dom_attr;
	memcpy(info.domain_attr, bgq_sep->info->domain_attr, sizeof(*info.domain_attr));

	info.fabric_attr = &fab_attr;
	memcpy(info.fabric_attr, bgq_sep->info->fabric_attr, sizeof(*info.fabric_attr));

	ret = fi_bgq_endpoint_rx_tx((struct fid_domain *)bgq_sep->domain,
		&info, tx_ep, context, -1, index);
	if (ret) {
		goto err;
	}

	bgq_tx_ep = container_of(*tx_ep, struct fi_bgq_ep, ep_fid);
	bgq_tx_ep->ep_fid.fid.fclass = FI_CLASS_TX_CTX;

	bgq_tx_ep->av = bgq_sep->av;
	fi_bgq_ref_inc(&bgq_tx_ep->av->ref_cnt, "address vector");

	bgq_tx_ep->sep = container_of(sep, struct fi_bgq_sep, ep_fid);

	++ bgq_sep->domain->tx.count;

	fi_bgq_ref_inc(&bgq_sep->ref_cnt, "scalable endpoint");

	attr->caps = caps;

	return 0;

err:
	return -errno;
}
static int fi_bgq_rx_ctx(struct fid_ep *sep, int index,
			struct fi_rx_attr *attr, struct fid_ep **rx_ep,
			void *context)
{
	int ret;
	struct fi_info info = {0};
	struct fi_bgq_sep *bgq_sep;
	struct fi_bgq_ep  *bgq_rx_ep;

	if (!sep || !attr || !rx_ep) {
		errno = FI_EINVAL;
		return -errno;
	}

	bgq_sep = container_of(sep, struct fi_bgq_sep, ep_fid);

	uint64_t caps = attr->caps;	/* TODO - "By default, a receive context inherits the properties of its associated endpoint. However, applications may request context specific attributes through the attr parameter." */

	if ((caps & FI_MSG || caps & FI_TAGGED) && (caps & FI_SEND)) {
		FI_LOG(fi_bgq_global.prov, FI_LOG_DEBUG, FI_LOG_DOMAIN,
				"FI_MSG|FI_TAGGED with FI_SEND capability specified for a RX context\n");
		caps &= ~FI_SEND;
	}

	if ((caps & FI_RMA || caps & FI_ATOMIC) && (caps & FI_READ || caps & FI_WRITE)) {
		FI_LOG(fi_bgq_global.prov, FI_LOG_DEBUG, FI_LOG_DOMAIN,
				"FI_RMA|FI_ATOMIC with FI_READ|FI_WRITE capability specified for a RX context\n");
		caps &= ~FI_READ;
		caps &= ~FI_WRITE;
	}

	if (caps & FI_MSG || caps & FI_TAGGED) {
		caps |= FI_RECV;
	}

	if (caps & FI_RMA || caps & FI_ATOMIC) {
		caps |= FI_REMOTE_READ;
		caps |= FI_REMOTE_WRITE;
	}

	if (ofi_send_allowed(caps) || ofi_rma_initiate_allowed(caps)) {
		FI_LOG(fi_bgq_global.prov, FI_LOG_DEBUG, FI_LOG_DOMAIN,
				"TX capabilities specified for RX context\n");
		errno = FI_EINVAL;
		return -errno;
	}

	if (!ofi_recv_allowed(caps) && !ofi_rma_target_allowed(caps)) {
		FI_LOG(fi_bgq_global.prov, FI_LOG_DEBUG, FI_LOG_DOMAIN,
				"RX capabilities not specified for RX context\n");
		errno = FI_EINVAL;
		return -errno;
	}

	if (bgq_sep->domain->rx.count >= fi_bgq_domain_get_rx_max(bgq_sep->domain)) {
		FI_LOG(fi_bgq_global.prov, FI_LOG_DEBUG, FI_LOG_DOMAIN,
				"RX ctx count exceeded (max %lu, created %lu)\n",
				fi_bgq_domain_get_rx_max(bgq_sep->domain), bgq_sep->domain->rx.count);
		errno = FI_EINVAL;
		return -errno;
	}

	info.caps = caps;
	info.mode = attr->mode;

	info.rx_attr = calloc(1, sizeof(*info.rx_attr));
	if (!info.rx_attr) {
		errno = FI_ENOMEM;
		goto err;
	}

	info.rx_attr->caps     = caps;
	info.rx_attr->mode     = attr->mode;
	info.rx_attr->op_flags = attr->op_flags;
	info.rx_attr->msg_order = attr->msg_order;
	info.rx_attr->total_buffered_recv = attr->total_buffered_recv;
	info.rx_attr->iov_limit = attr->iov_limit;

	info.ep_attr = calloc(1, sizeof(*info.ep_attr));
	if (!info.ep_attr) {
		errno = FI_ENOMEM;
		goto err;
	}
	memcpy(info.ep_attr, bgq_sep->info->ep_attr,
			sizeof(*info.ep_attr));

	info.domain_attr = calloc(1, sizeof(*info.domain_attr));
	if (!info.domain_attr) {
		errno = FI_ENOMEM;
		goto err;
	}
	memcpy(info.domain_attr, bgq_sep->info->domain_attr,
			sizeof(*info.domain_attr));

	info.fabric_attr = calloc(1, sizeof(*info.fabric_attr));
	if (!info.fabric_attr) {
		errno = FI_ENOMEM;
		goto err;
	}
	memcpy(info.fabric_attr, bgq_sep->info->fabric_attr,
			sizeof(*info.fabric_attr));

	ret = fi_bgq_endpoint_rx_tx(&bgq_sep->domain->domain_fid, &info,
			rx_ep, context, index, -1);
	if (ret) {
		goto err;
	}

	bgq_rx_ep = container_of(*rx_ep, struct fi_bgq_ep, ep_fid);
	bgq_rx_ep->ep_fid.fid.fclass = FI_CLASS_RX_CTX;

	bgq_rx_ep->sep = container_of(sep, struct fi_bgq_sep, ep_fid);

	bgq_rx_ep->av = bgq_sep->av;
	fi_bgq_ref_inc(&bgq_rx_ep->av->ref_cnt, "address vector");

	++ bgq_sep->domain->rx.count;

	fi_bgq_ref_inc(&bgq_sep->ref_cnt, "scalable endpoint");

	return 0;

err:
	if (info.fabric_attr)
		free(info.fabric_attr);
	if (info.domain_attr)
		free(info.domain_attr);
	if (info.ep_attr)
		free(info.ep_attr);
	if (info.tx_attr)
		free(info.tx_attr);
	return -errno;
}