Exemple #1
0
static ssize_t psmx_ep_cancel(fid_t fid, void *context)
{
	struct psmx_fid_ep *ep;
	psm_mq_status_t status;
	struct fi_context *fi_context = context;
	uint64_t flags;
	struct psmx_cq_event *event;
	int err;

	ep = container_of(fid, struct psmx_fid_ep, ep.fid);
	if (!ep->domain)
		return -FI_EBADF;

	if (!fi_context)
		return -FI_EINVAL;

	switch (PSMX_CTXT_TYPE(fi_context)) {
	case PSMX_TRECV_CONTEXT:
		flags = FI_RECV | FI_TAGGED;
		break;
	case PSMX_RECV_CONTEXT:
	case PSMX_MULTI_RECV_CONTEXT:
		flags = FI_RECV | FI_MSG;
		break;
	default:
		return  -FI_EOPNOTSUPP;
	}

	err = psm_mq_cancel((psm_mq_req_t *)&PSMX_CTXT_REQ(fi_context));
	if (err == PSM_OK) {
		err = psm_mq_test((psm_mq_req_t *)&PSMX_CTXT_REQ(fi_context), &status);
		if (err == PSM_OK && ep->recv_cq) {
			event = psmx_cq_create_event(
					ep->recv_cq,
					status.context,
					NULL,	/* buf */
					flags,
					0,	/* len */
					0,	/* data */
					0,	/* tag */
					0	/* olen */,
					-FI_ECANCELED);
			if (event)
				psmx_cq_enqueue_event(ep->recv_cq, event);
			else
				return -FI_ENOMEM;
		}
	}

	return psmx_errno(err);
}
Exemple #2
0
ssize_t psmx_tagged_send_no_flag_av_map(struct fid_ep *ep, const void *buf,
					size_t len, void *desc,
					fi_addr_t dest_addr, uint64_t tag,
				        void *context)
{
	struct psmx_fid_ep *ep_priv;
	psm_epaddr_t psm_epaddr;
	psm_mq_req_t psm_req;
	uint64_t psm_tag;
	struct fi_context *fi_context;
	int err;

	ep_priv = container_of(ep, struct psmx_fid_ep, ep);

	psm_epaddr = (psm_epaddr_t) dest_addr;
	psm_tag = tag & (~ep_priv->domain->reserved_tag_bits);

	fi_context = context;
	PSMX_CTXT_TYPE(fi_context) = PSMX_TSEND_CONTEXT;
	PSMX_CTXT_USER(fi_context) = (void *)buf;
	PSMX_CTXT_EP(fi_context) = ep_priv;

	err = psm_mq_isend(ep_priv->domain->psm_mq, psm_epaddr, 0,
			   psm_tag, buf, len, (void*)fi_context, &psm_req);

	if (err != PSM_OK)
		return psmx_errno(err);

	PSMX_CTXT_REQ(fi_context) = psm_req;
	return 0;
}
Exemple #3
0
ssize_t psmx_tagged_recv_no_flag_av_table(struct fid_ep *ep, void *buf,
					  size_t len, void *desc,
					  fi_addr_t src_addr,
					  uint64_t tag, uint64_t ignore,
					  void *context)
{
	struct psmx_fid_ep *ep_priv;
	psm_mq_req_t psm_req;
	uint64_t psm_tag, psm_tagsel;
	struct fi_context *fi_context;
	int err;

	ep_priv = container_of(ep, struct psmx_fid_ep, ep);

	psm_tag = tag & (~ep_priv->domain->reserved_tag_bits);
	psm_tagsel = (~ignore) | ep_priv->domain->reserved_tag_bits;

	fi_context = context;
	PSMX_CTXT_TYPE(fi_context) = PSMX_TRECV_CONTEXT;
	PSMX_CTXT_USER(fi_context) = buf;
	PSMX_CTXT_EP(fi_context) = ep_priv;

	err = psm_mq_irecv(ep_priv->domain->psm_mq,
			   psm_tag, psm_tagsel, 0, /* flags */
			   buf, len, (void *)fi_context, &psm_req);
	if (err != PSM_OK)
		return psmx_errno(err);

	PSMX_CTXT_REQ(fi_context) = psm_req;
	return 0;
}
Exemple #4
0
ssize_t psmx_tagged_recv_no_flag_av_table(struct fid_ep *ep, void *buf,
					  size_t len, void *desc,
					  fi_addr_t src_addr,
					  uint64_t tag, uint64_t ignore,
					  void *context)
{
	struct psmx_fid_ep *ep_priv;
	psm_mq_req_t psm_req;
	uint64_t psm_tag, psm_tagsel;
#if (PSM_VERNO_MAJOR >= 2)
	psm_mq_tag_t psm_tag2, psm_tagsel2;
	struct psmx_fid_av *av;
	psm_epaddr_t psm_epaddr;
	size_t idx;
#endif
	struct fi_context *fi_context;
	int err;

	ep_priv = container_of(ep, struct psmx_fid_ep, ep);

	psm_tag = tag & (~ep_priv->domain->reserved_tag_bits);
	psm_tagsel = (~ignore) | ep_priv->domain->reserved_tag_bits;

	fi_context = context;
	PSMX_CTXT_TYPE(fi_context) = PSMX_TRECV_CONTEXT;
	PSMX_CTXT_USER(fi_context) = buf;
	PSMX_CTXT_EP(fi_context) = ep_priv;

#if (PSM_VERNO_MAJOR >= 2)
	if ((ep_priv->caps & FI_DIRECTED_RECV) && src_addr != FI_ADDR_UNSPEC) {
		av = ep_priv->av;
		idx = (size_t)src_addr;
		if (idx >= av->last)
			return -FI_EINVAL;

		psm_epaddr = av->psm_epaddrs[idx];
	}
	else {
		psm_epaddr = NULL;
	}

	PSMX_SET_TAG(psm_tag2, psm_tag, 0);
	PSMX_SET_TAG(psm_tagsel2, psm_tagsel, 0);

	err = psm_mq_irecv2(ep_priv->domain->psm_mq,
			   psm_epaddr,
			   &psm_tag2, &psm_tagsel2, 0, /* flags */
			   buf, len, (void *)fi_context, &psm_req);
#else
	err = psm_mq_irecv(ep_priv->domain->psm_mq,
			   psm_tag, psm_tagsel, 0, /* flags */
			   buf, len, (void *)fi_context, &psm_req);
#endif
	if (err != PSM_OK)
		return psmx_errno(err);

	PSMX_CTXT_REQ(fi_context) = psm_req;
	return 0;
}
Exemple #5
0
static ssize_t psmx_ep_cancel(fid_t fid, void *context)
{
	struct psmx_fid_ep *fid_ep;
	psm_mq_status_t status;
	struct fi_context *fi_context = context;
	int err;

	fid_ep = container_of(fid, struct psmx_fid_ep, ep.fid);
	if (!fid_ep->domain)
		return -EBADF;

	if (!fi_context)
		return -EINVAL;

	err = psm_mq_cancel((psm_mq_req_t *)&PSMX_CTXT_REQ(fi_context));
	if (err == PSM_OK)
		err = psm_mq_test((psm_mq_req_t *)&PSMX_CTXT_REQ(fi_context), &status);

	return psmx_errno(err);
}
Exemple #6
0
ssize_t psmx_tagged_send_no_flag_av_table(struct fid_ep *ep, const void *buf,
					  size_t len, void *desc,
					  fi_addr_t dest_addr, uint64_t tag,
					  void *context)
{
	struct psmx_fid_ep *ep_priv;
	struct psmx_fid_av *av;
	psm_epaddr_t psm_epaddr;
	psm_mq_req_t psm_req;
	uint64_t psm_tag;
#if (PSM_VERNO_MAJOR >= 2)
	psm_mq_tag_t psm_tag2;
#endif
	struct fi_context *fi_context;
	int err;
	size_t idx;

	ep_priv = container_of(ep, struct psmx_fid_ep, ep);

	av = ep_priv->av;
	idx = (size_t)dest_addr;
	if (idx >= av->last)
		return -FI_EINVAL;

	psm_epaddr = av->psm_epaddrs[idx];
	psm_tag = tag & (~ep_priv->domain->reserved_tag_bits);
#if (PSM_VERNO_MAJOR >= 2)
	PSMX_SET_TAG(psm_tag2, psm_tag, 0);
#endif

	fi_context = context;
	PSMX_CTXT_TYPE(fi_context) = PSMX_TSEND_CONTEXT;
	PSMX_CTXT_USER(fi_context) = (void *)buf;
	PSMX_CTXT_EP(fi_context) = ep_priv;

#if (PSM_VERNO_MAJOR >= 2)
	err = psm_mq_isend2(ep_priv->domain->psm_mq, psm_epaddr, 0,
			    &psm_tag2, buf, len, (void*)fi_context, &psm_req);
#else
	err = psm_mq_isend(ep_priv->domain->psm_mq, psm_epaddr, 0,
			   psm_tag, buf, len, (void*)fi_context, &psm_req);
#endif

	if (err != PSM_OK)
		return psmx_errno(err);

	PSMX_CTXT_REQ(fi_context) = psm_req;
	return 0;
}
Exemple #7
0
int psmx_eq_poll_mq(struct psmx_fid_eq *eq, struct psmx_fid_domain *domain_if_null_eq)
{
    psm_mq_req_t psm_req;
    psm_mq_status_t psm_status;
    struct fi_context *fi_context;
    struct psmx_fid_domain *domain;
    struct psmx_fid_ep *tmp_ep;
    struct psmx_fid_eq *tmp_eq;
    struct psmx_fid_cntr *tmp_cntr;
    struct psmx_event *event;
    int multi_recv;
    int err;

    if (eq)
        domain = eq->domain;
    else
        domain = domain_if_null_eq;

    while (1) {
        err = psm_mq_ipeek(domain->psm_mq, &psm_req, NULL);

        if (err == PSM_OK) {
            err = psm_mq_test(&psm_req, &psm_status);

            fi_context = psm_status.context;

            tmp_ep = PSMX_CTXT_EP(fi_context);
            tmp_eq = NULL;
            tmp_cntr = NULL;
            multi_recv = 0;

            switch (PSMX_CTXT_TYPE(fi_context)) {
            case PSMX_NOCOMP_SEND_CONTEXT:
                tmp_ep->pending_sends--;
                if (!tmp_ep->send_cntr_event_flag)
                    tmp_cntr = tmp_ep->send_cntr;
                break;

            case PSMX_NOCOMP_RECV_CONTEXT:
                if (!tmp_ep->recv_cntr_event_flag)
                    tmp_cntr = tmp_ep->recv_cntr;
                break;

            case PSMX_NOCOMP_WRITE_CONTEXT:
                tmp_ep->pending_writes--;
                if (!tmp_ep->write_cntr_event_flag)
                    tmp_cntr = tmp_ep->write_cntr;
                break;

            case PSMX_NOCOMP_READ_CONTEXT:
                tmp_ep->pending_reads--;
                if (!tmp_ep->read_cntr_event_flag)
                    tmp_cntr = tmp_ep->read_cntr;
                break;

            case PSMX_INJECT_CONTEXT:
                tmp_ep->pending_sends--;
                if (!tmp_ep->send_cntr_event_flag)
                    tmp_cntr = tmp_ep->send_cntr;
                free(fi_context);
                break;

            case PSMX_INJECT_WRITE_CONTEXT:
                tmp_ep->pending_writes--;
                if (!tmp_ep->write_cntr_event_flag)
                    tmp_cntr = tmp_ep->write_cntr;
                free(fi_context);
                break;

            case PSMX_SEND_CONTEXT:
                tmp_ep->pending_sends--;
                tmp_eq = tmp_ep->send_eq;
                tmp_cntr = tmp_ep->send_cntr;
                break;

            case PSMX_RECV_CONTEXT:
                tmp_eq = tmp_ep->recv_eq;
                tmp_cntr = tmp_ep->recv_cntr;
                break;

            case PSMX_MULTI_RECV_CONTEXT:
                multi_recv = 1;
                tmp_eq = tmp_ep->recv_eq;
                tmp_cntr = tmp_ep->recv_cntr;
                break;

            case PSMX_READ_CONTEXT:
                tmp_ep->pending_reads--;
                tmp_eq = tmp_ep->send_eq;
                tmp_cntr = tmp_ep->read_cntr;
                break;

            case PSMX_WRITE_CONTEXT:
                tmp_ep->pending_writes--;
                tmp_eq = tmp_ep->send_eq;
                tmp_cntr = tmp_ep->write_cntr;
                break;
            }

            if (tmp_eq) {
                event = psmx_eq_create_event_from_status(tmp_eq, &psm_status);
                if (!event)
                    return -ENOMEM;

                psmx_eq_enqueue_event(tmp_eq, event);
            }

            if (tmp_cntr)
                tmp_cntr->cntr.ops->add(&tmp_cntr->cntr, 1);

            if (multi_recv) {
                struct psmx_multi_recv *req;
                psm_mq_req_t psm_req;

                req = PSMX_CTXT_USER(fi_context);
                req->offset += psm_status.nbytes;
                if (req->offset + req->min_buf_size <= req->len) {
                    err = psm_mq_irecv(tmp_ep->domain->psm_mq,
                                       req->tag, req->tagsel, req->flag,
                                       req->buf + req->offset,
                                       req->len - req->offset,
                                       (void *)fi_context, &psm_req);
                    if (err != PSM_OK)
                        return psmx_errno(err);

                    PSMX_CTXT_REQ(fi_context) = psm_req;
                }
                else {
                    if (tmp_eq) {
                        event = psmx_eq_create_event(
                                    tmp_eq,
                                    req->context,
                                    req->buf,
                                    FI_MULTI_RECV,
                                    req->len,
                                    req->len - req->offset, /* data */
                                    0,	/* tag */
                                    0,	/* olen */
                                    0);	/* err */
                        if (!event)
                            return -ENOMEM;

                        psmx_eq_enqueue_event(tmp_eq, event);
                    }

                    free(req);
                }
            }

            if (!eq || tmp_eq == eq)
                return 1;
        }
        else if (err == PSM_MQ_NO_COMPLETIONS) {
            return 0;
        }
        else {
            return psmx_errno(err);
        }
    }
}
Exemple #8
0
ssize_t _psmx_tagged_send(struct fid_ep *ep, const void *buf, size_t len,
			  void *desc, fi_addr_t dest_addr, uint64_t tag,
			  void *context, uint64_t flags)
#endif
{
	struct psmx_fid_ep *ep_priv;
	struct psmx_fid_av *av;
	psm_epaddr_t psm_epaddr;
	psm_mq_req_t psm_req;
	uint64_t psm_tag;
#if (PSM_VERNO_MAJOR >= 2)
	psm_mq_tag_t psm_tag2;
#endif
	struct fi_context *fi_context;
	int err;
	size_t idx;
	int no_completion = 0;
	struct psmx_cq_event *event;

	ep_priv = container_of(ep, struct psmx_fid_ep, ep);

	if (flags & FI_TRIGGER) {
		struct psmx_trigger *trigger;
		struct fi_triggered_context *ctxt = context;

		trigger = calloc(1, sizeof(*trigger));
		if (!trigger)
			return -FI_ENOMEM;

		trigger->op = PSMX_TRIGGERED_TSEND;
		trigger->cntr = container_of(ctxt->trigger.threshold.cntr,
					     struct psmx_fid_cntr, cntr);
		trigger->threshold = ctxt->trigger.threshold.threshold;
		trigger->tsend.ep = ep;
		trigger->tsend.buf = buf;
		trigger->tsend.len = len;
		trigger->tsend.desc = desc;
		trigger->tsend.dest_addr = dest_addr;
		trigger->tsend.tag = tag;
		trigger->tsend.context = context;
		trigger->tsend.flags = flags & ~FI_TRIGGER;
#if (PSM_VERNO_MAJOR >= 2)
		trigger->tsend.data = data;
#endif

		psmx_cntr_add_trigger(trigger->cntr, trigger);
		return 0;
	}

	if (tag & ep_priv->domain->reserved_tag_bits) {
		FI_WARN(&psmx_prov, FI_LOG_EP_DATA,
			"using reserved tag bits."
			"tag=%lx. reserved_bits=%lx.\n", tag,
			ep_priv->domain->reserved_tag_bits);
	}

	av = ep_priv->av;
	if (av && av->type == FI_AV_TABLE) {
		idx = (size_t)dest_addr;
		if (idx >= av->last)
			return -FI_EINVAL;

		psm_epaddr = av->psm_epaddrs[idx];
	}
	else  {
		psm_epaddr = (psm_epaddr_t) dest_addr;
	}

	psm_tag = tag & (~ep_priv->domain->reserved_tag_bits);
#if (PSM_VERNO_MAJOR >= 2)
	PSMX_SET_TAG(psm_tag2, psm_tag, data);
#endif

	if ((flags & PSMX_NO_COMPLETION) ||
	    (ep_priv->send_selective_completion && !(flags & FI_COMPLETION)))
		no_completion = 1;

	if (flags & FI_INJECT) {
		if (len > PSMX_INJECT_SIZE)
			return -FI_EMSGSIZE;

#if (PSM_VERNO_MAJOR >= 2)
		err = psm_mq_send2(ep_priv->domain->psm_mq, psm_epaddr, 0,
				   &psm_tag2, buf, len);
#else
		err = psm_mq_send(ep_priv->domain->psm_mq, psm_epaddr, 0,
				  psm_tag, buf, len);
#endif

		if (err != PSM_OK)
			return psmx_errno(err);

		if (ep_priv->send_cntr)
			psmx_cntr_inc(ep_priv->send_cntr);

		if (ep_priv->send_cq && !no_completion) {
			event = psmx_cq_create_event(
					ep_priv->send_cq,
					context, (void *)buf, flags, len,
#if (PSM_VERNO_MAJOR >= 2)
					(uint64_t) data, psm_tag,
#else
					0 /* data */, psm_tag,
#endif
					0 /* olen */,
					0 /* err */);

			if (event)
				psmx_cq_enqueue_event(ep_priv->send_cq, event);
			else
				return -FI_ENOMEM;
		}

		return 0;
	}

	if (no_completion && !context) {
		fi_context = &ep_priv->nocomp_send_context;
	}
	else {
		if (!context)
			return -FI_EINVAL;

		fi_context = context;
		PSMX_CTXT_TYPE(fi_context) = PSMX_TSEND_CONTEXT;
		PSMX_CTXT_USER(fi_context) = (void *)buf;
		PSMX_CTXT_EP(fi_context) = ep_priv;
	}

#if (PSM_VERNO_MAJOR >= 2)
	err = psm_mq_isend2(ep_priv->domain->psm_mq, psm_epaddr, 0,
				&psm_tag2, buf, len, (void*)fi_context, &psm_req);
#else
	err = psm_mq_isend(ep_priv->domain->psm_mq, psm_epaddr, 0,
				psm_tag, buf, len, (void*)fi_context, &psm_req);
#endif

	if (err != PSM_OK)
		return psmx_errno(err);

	if (fi_context == context)
		PSMX_CTXT_REQ(fi_context) = psm_req;

	return 0;
}
Exemple #9
0
ssize_t _psmx_tagged_peek(struct fid_ep *ep, void *buf, size_t len,
			  void *desc, fi_addr_t src_addr,
			  uint64_t tag, uint64_t ignore,
			  void *context, uint64_t flags)
{
	struct psmx_fid_ep *ep_priv;
#if (PSM_VERNO_MAJOR >= 2)
	psm_mq_status2_t psm_status2;
	psm_mq_tag_t psm_tag2, psm_tagsel2;
	psm_mq_req_t req;
	struct psmx_fid_av *av;
	size_t idx;
	psm_epaddr_t psm_src_addr;
#else
	psm_mq_status_t psm_status;
#endif
	uint64_t psm_tag, psm_tagsel;
	struct psmx_cq_event *event;
	int err;

	ep_priv = container_of(ep, struct psmx_fid_ep, ep);

	if (tag & ep_priv->domain->reserved_tag_bits) {
		FI_WARN(&psmx_prov, FI_LOG_EP_DATA,
			"using reserved tag bits."
			"tag=%lx. reserved_bits=%lx.\n", tag,
			ep_priv->domain->reserved_tag_bits);
	}

	psm_tag = tag & (~ep_priv->domain->reserved_tag_bits);
	psm_tagsel = (~ignore) | ep_priv->domain->reserved_tag_bits;

#if (PSM_VERNO_MAJOR >= 2)
	if (src_addr != FI_ADDR_UNSPEC) {
		av = ep_priv->av;
		if (av && av->type == FI_AV_TABLE) {
			idx = (size_t)src_addr;
			if (idx >= av->last)
				return -FI_EINVAL;

			psm_src_addr = av->psm_epaddrs[idx];
		}
		else {
			psm_src_addr = (psm_epaddr_t)src_addr;
		}
	}
	else {
		psm_src_addr = NULL;
	}

	PSMX_SET_TAG(psm_tag2, psm_tag, 0);
	PSMX_SET_TAG(psm_tagsel2, psm_tagsel, 0);

	if (flags & (FI_CLAIM | FI_DISCARD))
		err = psm_mq_improbe2(ep_priv->domain->psm_mq,
				      psm_src_addr,
				      &psm_tag2, &psm_tagsel2,
				      &req, &psm_status2);
	else
		err = psm_mq_iprobe2(ep_priv->domain->psm_mq,
				     psm_src_addr,
				     &psm_tag2, &psm_tagsel2,
				     &psm_status2);
#else
	if (flags & (FI_CLAIM | FI_DISCARD))
		return -FI_EOPNOTSUPP;

	err = psm_mq_iprobe(ep_priv->domain->psm_mq, psm_tag, psm_tagsel,
			    &psm_status);
#endif
	switch (err) {
	case PSM_OK:
		if (ep_priv->recv_cq) {
#if (PSM_VERNO_MAJOR >= 2)
			if ((flags & FI_CLAIM) && context)
				PSMX_CTXT_REQ((struct fi_context *)context) = req;

			tag = psm_status2.msg_tag.tag0 | (((uint64_t)psm_status2.msg_tag.tag1) << 32);
			len = psm_status2.msg_length;
			src_addr = (fi_addr_t)psm_status2.msg_peer;
#else
			tag = psm_status.msg_tag;
			len = psm_status.msg_length;
			src_addr = 0;
#endif
			event = psmx_cq_create_event(
					ep_priv->recv_cq,
					context,		/* op_context */
					NULL,			/* buf */
					flags|FI_RECV|FI_TAGGED,/* flags */
					len,			/* len */
					0,			/* data */
					tag,			/* tag */
					len,			/* olen */
					0);			/* err */

			if (!event)
				return -FI_ENOMEM;

			event->source = src_addr;
			psmx_cq_enqueue_event(ep_priv->recv_cq, event);
		}
		return 0;

	case PSM_MQ_NO_COMPLETIONS:
		return -FI_ENOMSG;

	default:
		return psmx_errno(err);
	}
}
Exemple #10
0
ssize_t _psmx_tagged_recv(struct fid_ep *ep, void *buf, size_t len,
			  void *desc, fi_addr_t src_addr,
			  uint64_t tag, uint64_t ignore,
			  void *context, uint64_t flags)
{
	struct psmx_fid_ep *ep_priv;
	psm_mq_req_t psm_req;
	uint64_t psm_tag, psm_tagsel;
#if (PSM_VERNO_MAJOR >= 2)
	psm_mq_tag_t psm_tag2, psm_tagsel2;
	struct psmx_fid_av *av;
	size_t idx;
#endif
	struct fi_context *fi_context;
	int err;

	ep_priv = container_of(ep, struct psmx_fid_ep, ep);

	if (flags & FI_PEEK)
		return _psmx_tagged_peek(ep, buf, len, desc, src_addr,
					 tag, ignore, context, flags);

	if (flags & FI_TRIGGER) {
		struct psmx_trigger *trigger;
		struct fi_triggered_context *ctxt = context;

		trigger = calloc(1, sizeof(*trigger));
		if (!trigger)
			return -FI_ENOMEM;

		trigger->op = PSMX_TRIGGERED_TRECV;
		trigger->cntr = container_of(ctxt->trigger.threshold.cntr,
					     struct psmx_fid_cntr, cntr);
		trigger->threshold = ctxt->trigger.threshold.threshold;
		trigger->trecv.ep = ep;
		trigger->trecv.buf = buf;
		trigger->trecv.len = len;
		trigger->trecv.desc = desc;
		trigger->trecv.src_addr = src_addr;
		trigger->trecv.tag = tag;
		trigger->trecv.ignore = ignore;
		trigger->trecv.context = context;
		trigger->trecv.flags = flags & ~FI_TRIGGER;

		psmx_cntr_add_trigger(trigger->cntr, trigger);
		return 0;
	}

#if (PSM_VERNO_MAJOR >= 2)
	if (flags & FI_CLAIM) {
		if (!context)
			return -FI_EINVAL;

		/* TODO: handle FI_DISCARD */

		fi_context = context;
		psm_req = PSMX_CTXT_REQ(fi_context);
		PSMX_CTXT_TYPE(fi_context) = PSMX_TRECV_CONTEXT;
		PSMX_CTXT_USER(fi_context) = buf;
		PSMX_CTXT_EP(fi_context) = ep_priv;

		err = psm_mq_imrecv(ep_priv->domain->psm_mq, 0, /*flags*/
				    buf, len, context, &psm_req);
		if (err != PSM_OK)
			return psmx_errno(err);

		PSMX_CTXT_REQ(fi_context) = psm_req;
		return 0;
	}
#endif

	if (tag & ep_priv->domain->reserved_tag_bits) {
		FI_WARN(&psmx_prov, FI_LOG_EP_DATA,
			"using reserved tag bits."
			"tag=%lx. reserved_bits=%lx.\n", tag,
			ep_priv->domain->reserved_tag_bits);
	}

	psm_tag = tag & (~ep_priv->domain->reserved_tag_bits);
	psm_tagsel = (~ignore) | ep_priv->domain->reserved_tag_bits;

	if (ep_priv->recv_selective_completion && !(flags & FI_COMPLETION) && !context) {
		fi_context = &ep_priv->nocomp_recv_context;
	}
	else {
		if (!context)
			return -FI_EINVAL;

		fi_context = context;
		PSMX_CTXT_TYPE(fi_context) = PSMX_TRECV_CONTEXT;
		PSMX_CTXT_USER(fi_context) = buf;
		PSMX_CTXT_EP(fi_context) = ep_priv;
	}

#if (PSM_VERNO_MAJOR >= 2)
	if ((ep_priv->caps & FI_DIRECTED_RECV) && src_addr != FI_ADDR_UNSPEC) {
		av = ep_priv->av;
		if (av && av->type == FI_AV_TABLE) {
			idx = (size_t)src_addr;
			if (idx >= av->last)
				return -FI_EINVAL;

			src_addr = (fi_addr_t)av->psm_epaddrs[idx];
		}
	}
	else {
		src_addr = 0;
	}

	PSMX_SET_TAG(psm_tag2, psm_tag, 0);
	PSMX_SET_TAG(psm_tagsel2, psm_tagsel, 0);

	err = psm_mq_irecv2(ep_priv->domain->psm_mq,
			   (psm_epaddr_t)src_addr,
			   &psm_tag2, &psm_tagsel2, 0, /* flags */
			   buf, len, (void *)fi_context, &psm_req);
#else
	err = psm_mq_irecv(ep_priv->domain->psm_mq,
			   psm_tag, psm_tagsel, 0, /* flags */
			   buf, len, (void *)fi_context, &psm_req);
#endif

	if (err != PSM_OK)
		return psmx_errno(err);

	if (fi_context == context)
		PSMX_CTXT_REQ(fi_context) = psm_req;

	return 0;
}
Exemple #11
0
ssize_t _psmx_tagged_recv(struct fid_ep *ep, void *buf, size_t len,
			  void *desc, fi_addr_t src_addr,
			  uint64_t tag, uint64_t ignore,
			  void *context, uint64_t flags)
{
	struct psmx_fid_ep *ep_priv;
	psm_mq_req_t psm_req;
	uint64_t psm_tag, psm_tagsel;
	struct fi_context *fi_context;
	int err;

	ep_priv = container_of(ep, struct psmx_fid_ep, ep);

	if (flags & FI_PEEK)
		return _psmx_tagged_peek(ep, buf, len, desc, src_addr,
					 tag, ignore, context, flags);

	if (flags & FI_TRIGGER) {
		struct psmx_trigger *trigger;
		struct fi_triggered_context *ctxt = context;

		trigger = calloc(1, sizeof(*trigger));
		if (!trigger)
			return -FI_ENOMEM;

		trigger->op = PSMX_TRIGGERED_TRECV;
		trigger->cntr = container_of(ctxt->trigger.threshold.cntr,
					     struct psmx_fid_cntr, cntr);
		trigger->threshold = ctxt->trigger.threshold.threshold;
		trigger->trecv.ep = ep;
		trigger->trecv.buf = buf;
		trigger->trecv.len = len;
		trigger->trecv.desc = desc;
		trigger->trecv.src_addr = src_addr;
		trigger->trecv.tag = tag;
		trigger->trecv.ignore = ignore;
		trigger->trecv.context = context;
		trigger->trecv.flags = flags & ~FI_TRIGGER;

		psmx_cntr_add_trigger(trigger->cntr, trigger);
		return 0;
	}

	if (tag & ep_priv->domain->reserved_tag_bits) {
		FI_WARN(&psmx_prov, FI_LOG_EP_DATA,
			"using reserved tag bits."
			"tag=%lx. reserved_bits=%lx.\n", tag,
			ep_priv->domain->reserved_tag_bits);
	}

	psm_tag = tag & (~ep_priv->domain->reserved_tag_bits);
	psm_tagsel = (~ignore) | ep_priv->domain->reserved_tag_bits;

	if (ep_priv->recv_selective_completion && !(flags & FI_COMPLETION) && !context) {
		fi_context = &ep_priv->nocomp_recv_context;
	}
	else {
		if (!context)
			return -FI_EINVAL;

		fi_context = context;
		PSMX_CTXT_TYPE(fi_context) = PSMX_TRECV_CONTEXT;
		PSMX_CTXT_USER(fi_context) = buf;
		PSMX_CTXT_EP(fi_context) = ep_priv;
	}

	err = psm_mq_irecv(ep_priv->domain->psm_mq,
			   psm_tag, psm_tagsel, 0, /* flags */
			   buf, len, (void *)fi_context, &psm_req);

	if (err != PSM_OK)
		return psmx_errno(err);

	if (fi_context == context)
		PSMX_CTXT_REQ(fi_context) = psm_req;

	return 0;
}