static int _gnix_ep_getinfo()

in prov/gni/src/gnix_fabric.c [447:682]


static int _gnix_ep_getinfo(enum fi_ep_type ep_type, uint32_t version,
			    const char *node, const char *service,
			    uint64_t flags, const struct fi_info *hints,
			    struct fi_info **info)
{
	uint64_t mode = GNIX_FAB_MODES;
	struct fi_info *gnix_info = NULL;
	int ret = -FI_ENODATA;
	int mr_mode;

	GNIX_TRACE(FI_LOG_FABRIC, "\n");

	if ((hints && hints->ep_attr) &&
	    (hints->ep_attr->type != FI_EP_UNSPEC &&
	     hints->ep_attr->type != ep_type)) {
		return -FI_ENODATA;
	}

	gnix_info = _gnix_allocinfo();
	if (!gnix_info)
		return -FI_ENOMEM;

	gnix_info->ep_attr->type = ep_type;

	if (hints) {
		/* TODO: Add version check when we decide on how to do it */
		if (hints->addr_format == FI_ADDR_STR) {
			gnix_info->addr_format = FI_ADDR_STR;
		}

		if (hints->ep_attr) {
			/* Only support FI_PROTO_GNI protocol. */
			switch (hints->ep_attr->protocol) {
			case FI_PROTO_UNSPEC:
			case FI_PROTO_GNI:
				break;
			default:
				goto err;
			}

			if ((hints->ep_attr->tx_ctx_cnt > GNIX_SEP_MAX_CNT) &&
				(hints->ep_attr->tx_ctx_cnt !=
						FI_SHARED_CONTEXT)) {
				goto err;
			}

			if (hints->ep_attr->rx_ctx_cnt > GNIX_SEP_MAX_CNT)
				goto err;

			if (hints->ep_attr->tx_ctx_cnt)
				gnix_info->ep_attr->tx_ctx_cnt =
					hints->ep_attr->tx_ctx_cnt;
			if (hints->ep_attr->rx_ctx_cnt)
				gnix_info->ep_attr->rx_ctx_cnt =
					hints->ep_attr->rx_ctx_cnt;

			if (hints->ep_attr->max_msg_size > GNIX_MAX_MSG_SIZE)
				goto err;
		}

		GNIX_DEBUG(FI_LOG_FABRIC, "Passed EP attributes check\n");

		/*
		 * check the mode field
		 */
		if (hints->mode) {
			if ((hints->mode & GNIX_FAB_MODES) != GNIX_FAB_MODES) {
				goto err;
			}
			mode = hints->mode & ~GNIX_FAB_MODES_CLEAR;
			if (FI_VERSION_LT(version, FI_VERSION(1, 5))) {
				mode = hints->mode & ~FI_NOTIFY_FLAGS_ONLY;
			}
		}

		GNIX_DEBUG(FI_LOG_FABRIC, "Passed mode check\n");

		if (hints->caps) {
			/* The provider must support all requested
			 * capabilities. */
			if ((hints->caps & GNIX_EP_CAPS_FULL) != hints->caps)
				goto err;
		}

		GNIX_DEBUG(FI_LOG_FABRIC, "Passed caps check gnix_info->caps = 0x%016lx\n",
			   gnix_info->caps);

		if (hints->tx_attr) {
			if ((hints->tx_attr->op_flags & GNIX_EP_OP_FLAGS) !=
				hints->tx_attr->op_flags) {
				goto err;
			}
			if (hints->tx_attr->inject_size > GNIX_INJECT_SIZE) {
				goto err;
			}

			gnix_info->tx_attr->op_flags =
				hints->tx_attr->op_flags & GNIX_EP_OP_FLAGS;
		}

		GNIX_DEBUG(FI_LOG_FABRIC, "Passed TX attributes check\n");

		if (hints->rx_attr) {
			if ((hints->rx_attr->op_flags & GNIX_EP_OP_FLAGS) !=
					hints->rx_attr->op_flags) {
				goto err;
			}

			gnix_info->rx_attr->op_flags =
				hints->rx_attr->op_flags & GNIX_EP_OP_FLAGS;
		}

		if (hints->fabric_attr && hints->fabric_attr->name &&
		    strncmp(hints->fabric_attr->name, gnix_fab_name,
			    strlen(gnix_fab_name))) {
			goto err;
		}

		GNIX_DEBUG(FI_LOG_FABRIC, "Passed fabric name check\n");

		if (hints->domain_attr) {
			mr_mode = hints->domain_attr->mr_mode;

			if (hints->domain_attr->name &&
			    strncmp(hints->domain_attr->name, gnix_dom_name,
				    strlen(gnix_dom_name))) {
				goto err;
			}

			if (hints->domain_attr->control_progress !=
				FI_PROGRESS_UNSPEC)
				gnix_info->domain_attr->control_progress =
					hints->domain_attr->control_progress;

			if (hints->domain_attr->data_progress !=
				FI_PROGRESS_UNSPEC)
				gnix_info->domain_attr->data_progress =
					hints->domain_attr->data_progress;

			/* If basic registration isn't being requested,
			   require FI_MR_MMU_NOTIFY */
			if (!(hints->domain_attr->mr_mode &
					(FI_MR_BASIC | FI_MR_ALLOCATED)))
				gnix_info->domain_attr->mr_mode |= FI_MR_MMU_NOTIFY;

			if (ofi_check_mr_mode(&gnix_prov, version,
					gnix_info->domain_attr->mr_mode,
					hints) != FI_SUCCESS) {
				GNIX_INFO(FI_LOG_DOMAIN,
					"failed ofi_check_mr_mode, "
					"ret=%d\n", ret);
				goto err;
			}

			if (FI_VERSION_LT(version, FI_VERSION(1, 5))) {
				switch (mr_mode) {
				case FI_MR_UNSPEC:
				case FI_MR_BASIC:
					mr_mode = FI_MR_BASIC;
					break;
				default:
					GNIX_DEBUG(FI_LOG_FABRIC,
						"unsupported mr_mode selected, "
						"ret=%d\n", ret);
					goto err;
				}
			} else {
				/* define the mode we return to the user
				 * prefer basic until scalable
				 * has more testing time */
				if (mr_mode & FI_MR_BASIC)
					mr_mode = OFI_MR_BASIC_MAP;
				else if ((mr_mode & GNIX_MR_BASIC_REQ) ==
							GNIX_MR_BASIC_REQ)
					mr_mode &= GNIX_MR_BASIC_BITS;
				else
					mr_mode &= GNIX_MR_SCALABLE_BITS;
			}

			gnix_info->domain_attr->mr_mode = mr_mode;

			switch (hints->domain_attr->threading) {
			case FI_THREAD_COMPLETION:
				gnix_info->domain_attr->threading =
					hints->domain_attr->threading;
				break;
			default:
				break;
			}

			if (hints->domain_attr->caps) {
				if (hints->domain_attr->caps & ~GNIX_DOM_CAPS) {
					GNIX_WARN(FI_LOG_FABRIC,
						  "Invalid domain caps\n");
					goto err;
				}

				gnix_info->domain_attr->caps =
					hints->domain_attr->caps;
			}

		}
	}

	ret = __gnix_getinfo_resolve_node(node, service, flags, hints,
					  gnix_info);
	if (ret != FI_SUCCESS)
		goto err;

	ofi_alter_info(gnix_info, hints, version);

	GNIX_DEBUG(FI_LOG_FABRIC, "Passed the domain attributes check\n");

	/* The provider may silently enable secondary
	 * capabilities that do not introduce any overhead. */
	if (hints && hints->caps)
		gnix_info->caps = hints->caps | GNIX_EP_SEC_CAPS;
	else
		gnix_info->caps = GNIX_EP_CAPS_FULL | GNIX_EP_SEC_CAPS;

	gnix_info->mode = mode;
	gnix_info->fabric_attr->name = strdup(gnix_fab_name);
	gnix_info->tx_attr->caps = gnix_info->caps;
	gnix_info->tx_attr->mode = gnix_info->mode;
	gnix_info->rx_attr->caps = gnix_info->caps;
	gnix_info->rx_attr->mode = gnix_info->mode;

	*info = gnix_info;

	GNIX_DEBUG(FI_LOG_FABRIC, "Returning EP type: %s\n",
		   fi_tostr(&ep_type, FI_TYPE_EP_TYPE));
	return FI_SUCCESS;
err:
	fi_freeinfo(gnix_info);
	return ret;
}