1 /*
2  * Copyright (c) 2013-2017 Intel Corporation. All rights reserved.
3  *
4  * This software is available to you under a choice of one of two
5  * licenses.  You may choose to be licensed under the terms of the GNU
6  * General Public License (GPL) Version 2, available from the file
7  * COPYING in the main directory of this source tree, or the
8  * BSD license below:
9  *
10  *     Redistribution and use in source and binary forms, with or
11  *     without modification, are permitted provided that the following
12  *     conditions are met:
13  *
14  *      - Redistributions of source code must retain the above
15  *        copyright notice, this list of conditions and the following
16  *        disclaimer.
17  *
18  *      - Redistributions in binary form must reproduce the above
19  *        copyright notice, this list of conditions and the following
20  *        disclaimer in the documentation and/or other materials
21  *        provided with the distribution.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30  * SOFTWARE.
31  */
32 
33 #include "psmx.h"
34 
_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)35 ssize_t _psmx_tagged_peek(struct fid_ep *ep, void *buf, size_t len,
36 			  void *desc, fi_addr_t src_addr,
37 			  uint64_t tag, uint64_t ignore,
38 			  void *context, uint64_t flags)
39 {
40 	struct psmx_fid_ep *ep_priv;
41 	psm_mq_status_t psm_status;
42 	uint64_t psm_tag, psm_tagsel;
43 	struct psmx_cq_event *event;
44 	int err;
45 
46 	ep_priv = container_of(ep, struct psmx_fid_ep, ep);
47 
48 	if (tag & ep_priv->domain->reserved_tag_bits) {
49 		FI_WARN(&psmx_prov, FI_LOG_EP_DATA,
50 			"using reserved tag bits."
51 			"tag=%lx. reserved_bits=%lx.\n", tag,
52 			ep_priv->domain->reserved_tag_bits);
53 	}
54 
55 	psm_tag = tag & (~ep_priv->domain->reserved_tag_bits);
56 	psm_tagsel = (~ignore) | ep_priv->domain->reserved_tag_bits;
57 
58 	if (flags & (FI_CLAIM | FI_DISCARD))
59 		return -FI_EOPNOTSUPP;
60 
61 	err = psm_mq_iprobe(ep_priv->domain->psm_mq, psm_tag, psm_tagsel,
62 			    &psm_status);
63 
64 	switch (err) {
65 	case PSM_OK:
66 		if (ep_priv->recv_cq) {
67 			tag = psm_status.msg_tag;
68 			len = psm_status.msg_length;
69 			src_addr = 0;
70 			event = psmx_cq_create_event(
71 					ep_priv->recv_cq,
72 					context,		/* op_context */
73 					NULL,			/* buf */
74 					flags|FI_RECV|FI_TAGGED,/* flags */
75 					len,			/* len */
76 					0,			/* data */
77 					tag,			/* tag */
78 					len,			/* olen */
79 					0);			/* err */
80 
81 			if (!event)
82 				return -FI_ENOMEM;
83 
84 			event->source = src_addr;
85 			psmx_cq_enqueue_event(ep_priv->recv_cq, event);
86 		}
87 		return 0;
88 
89 	case PSM_MQ_NO_COMPLETIONS:
90 		if (ep_priv->recv_cq) {
91 			event = psmx_cq_create_event(
92 					ep_priv->recv_cq,
93 					context,		/* op_context */
94 					NULL,			/* buf */
95 					flags|FI_RECV|FI_TAGGED,/* flags */
96 					len,			/* len */
97 					0,			/* data */
98 					tag,			/* tag */
99 					len,			/* olen */
100 					-FI_ENOMSG);		/* err */
101 
102 			if (!event)
103 				return -FI_ENOMEM;
104 
105 			event->source = 0;
106 			psmx_cq_enqueue_event(ep_priv->recv_cq, event);
107 		}
108 		return 0;
109 
110 	default:
111 		return psmx_errno(err);
112 	}
113 }
114 
_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)115 ssize_t _psmx_tagged_recv(struct fid_ep *ep, void *buf, size_t len,
116 			  void *desc, fi_addr_t src_addr,
117 			  uint64_t tag, uint64_t ignore,
118 			  void *context, uint64_t flags)
119 {
120 	struct psmx_fid_ep *ep_priv;
121 	psm_mq_req_t psm_req;
122 	uint64_t psm_tag, psm_tagsel;
123 	struct fi_context *fi_context;
124 	int err;
125 
126 	ep_priv = container_of(ep, struct psmx_fid_ep, ep);
127 
128 	if (flags & FI_PEEK)
129 		return _psmx_tagged_peek(ep, buf, len, desc, src_addr,
130 					 tag, ignore, context, flags);
131 
132 	if (flags & FI_TRIGGER) {
133 		struct psmx_trigger *trigger;
134 		struct fi_triggered_context *ctxt = context;
135 
136 		trigger = calloc(1, sizeof(*trigger));
137 		if (!trigger)
138 			return -FI_ENOMEM;
139 
140 		trigger->op = PSMX_TRIGGERED_TRECV;
141 		trigger->cntr = container_of(ctxt->trigger.threshold.cntr,
142 					     struct psmx_fid_cntr, cntr);
143 		trigger->threshold = ctxt->trigger.threshold.threshold;
144 		trigger->trecv.ep = ep;
145 		trigger->trecv.buf = buf;
146 		trigger->trecv.len = len;
147 		trigger->trecv.desc = desc;
148 		trigger->trecv.src_addr = src_addr;
149 		trigger->trecv.tag = tag;
150 		trigger->trecv.ignore = ignore;
151 		trigger->trecv.context = context;
152 		trigger->trecv.flags = flags & ~FI_TRIGGER;
153 
154 		psmx_cntr_add_trigger(trigger->cntr, trigger);
155 		return 0;
156 	}
157 
158 	if (tag & ep_priv->domain->reserved_tag_bits) {
159 		FI_WARN(&psmx_prov, FI_LOG_EP_DATA,
160 			"using reserved tag bits."
161 			"tag=%lx. reserved_bits=%lx.\n", tag,
162 			ep_priv->domain->reserved_tag_bits);
163 	}
164 
165 	psm_tag = tag & (~ep_priv->domain->reserved_tag_bits);
166 	psm_tagsel = (~ignore) | ep_priv->domain->reserved_tag_bits;
167 
168 	if (ep_priv->recv_selective_completion && !(flags & FI_COMPLETION)) {
169 		fi_context = &ep_priv->nocomp_recv_context;
170 	} else {
171 		if (!context)
172 			return -FI_EINVAL;
173 
174 		fi_context = context;
175 		PSMX_CTXT_TYPE(fi_context) = PSMX_TRECV_CONTEXT;
176 		PSMX_CTXT_USER(fi_context) = buf;
177 		PSMX_CTXT_EP(fi_context) = ep_priv;
178 	}
179 
180 	err = psm_mq_irecv(ep_priv->domain->psm_mq,
181 			   psm_tag, psm_tagsel, 0, /* flags */
182 			   buf, len, (void *)fi_context, &psm_req);
183 
184 	if (err != PSM_OK)
185 		return psmx_errno(err);
186 
187 	if (fi_context == context)
188 		PSMX_CTXT_REQ(fi_context) = psm_req;
189 
190 	return 0;
191 }
192 
psmx_tagged_recv_no_flag_av_map(struct fid_ep * ep,void * buf,size_t len,void * desc,fi_addr_t src_addr,uint64_t tag,uint64_t ignore,void * context)193 ssize_t psmx_tagged_recv_no_flag_av_map(struct fid_ep *ep, void *buf,
194 					size_t len, void *desc,
195 					fi_addr_t src_addr,
196 					uint64_t tag, uint64_t ignore,
197 					void *context)
198 {
199 	struct psmx_fid_ep *ep_priv;
200 	psm_mq_req_t psm_req;
201 	uint64_t psm_tag, psm_tagsel;
202 	struct fi_context *fi_context;
203 	int err;
204 
205 	ep_priv = container_of(ep, struct psmx_fid_ep, ep);
206 
207 	psm_tag = tag & (~ep_priv->domain->reserved_tag_bits);
208 	psm_tagsel = (~ignore) | ep_priv->domain->reserved_tag_bits;
209 
210 	fi_context = context;
211 	PSMX_CTXT_TYPE(fi_context) = PSMX_TRECV_CONTEXT;
212 	PSMX_CTXT_USER(fi_context) = buf;
213 	PSMX_CTXT_EP(fi_context) = ep_priv;
214 
215 	err = psm_mq_irecv(ep_priv->domain->psm_mq,
216 			   psm_tag, psm_tagsel, 0, /* flags */
217 			   buf, len, (void *)fi_context, &psm_req);
218 	if (err != PSM_OK)
219 		return psmx_errno(err);
220 
221 	PSMX_CTXT_REQ(fi_context) = psm_req;
222 	return 0;
223 }
224 
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)225 ssize_t psmx_tagged_recv_no_flag_av_table(struct fid_ep *ep, void *buf,
226 					  size_t len, void *desc,
227 					  fi_addr_t src_addr,
228 					  uint64_t tag, uint64_t ignore,
229 					  void *context)
230 {
231 	struct psmx_fid_ep *ep_priv;
232 	psm_mq_req_t psm_req;
233 	uint64_t psm_tag, psm_tagsel;
234 	struct fi_context *fi_context;
235 	int err;
236 
237 	ep_priv = container_of(ep, struct psmx_fid_ep, ep);
238 
239 	psm_tag = tag & (~ep_priv->domain->reserved_tag_bits);
240 	psm_tagsel = (~ignore) | ep_priv->domain->reserved_tag_bits;
241 
242 	fi_context = context;
243 	PSMX_CTXT_TYPE(fi_context) = PSMX_TRECV_CONTEXT;
244 	PSMX_CTXT_USER(fi_context) = buf;
245 	PSMX_CTXT_EP(fi_context) = ep_priv;
246 
247 	err = psm_mq_irecv(ep_priv->domain->psm_mq,
248 			   psm_tag, psm_tagsel, 0, /* flags */
249 			   buf, len, (void *)fi_context, &psm_req);
250 	if (err != PSM_OK)
251 		return psmx_errno(err);
252 
253 	PSMX_CTXT_REQ(fi_context) = psm_req;
254 	return 0;
255 }
256 
psmx_tagged_recv_no_event_av_map(struct fid_ep * ep,void * buf,size_t len,void * desc,fi_addr_t src_addr,uint64_t tag,uint64_t ignore,void * context)257 ssize_t psmx_tagged_recv_no_event_av_map(struct fid_ep *ep, void *buf,
258 					 size_t len, void *desc,
259 					 fi_addr_t src_addr,
260 					 uint64_t tag, uint64_t ignore,
261 					 void *context)
262 {
263 	struct psmx_fid_ep *ep_priv;
264 	psm_mq_req_t psm_req;
265 	uint64_t psm_tag, psm_tagsel;
266 	struct fi_context *fi_context;
267 	int err;
268 
269 	ep_priv = container_of(ep, struct psmx_fid_ep, ep);
270 
271 	psm_tag = tag & (~ep_priv->domain->reserved_tag_bits);
272 	psm_tagsel = (~ignore) | ep_priv->domain->reserved_tag_bits;
273 
274 	fi_context = &ep_priv->nocomp_recv_context;
275 
276 	err = psm_mq_irecv(ep_priv->domain->psm_mq,
277 			   psm_tag, psm_tagsel, 0, /* flags */
278 			   buf, len, (void *)fi_context, &psm_req);
279 
280 	return psmx_errno(err);
281 }
282 
psmx_tagged_recv_no_event_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)283 ssize_t psmx_tagged_recv_no_event_av_table(struct fid_ep *ep, void *buf,
284 					   size_t len, void *desc,
285 					   fi_addr_t src_addr,
286 					   uint64_t tag, uint64_t ignore,
287 					   void *context)
288 {
289 	struct psmx_fid_ep *ep_priv;
290 	psm_mq_req_t psm_req;
291 	uint64_t psm_tag, psm_tagsel;
292 	struct fi_context *fi_context;
293 	int err;
294 
295 	ep_priv = container_of(ep, struct psmx_fid_ep, ep);
296 
297 	psm_tag = tag & (~ep_priv->domain->reserved_tag_bits);
298 	psm_tagsel = (~ignore) | ep_priv->domain->reserved_tag_bits;
299 
300 	fi_context = &ep_priv->nocomp_recv_context;
301 
302 	err = psm_mq_irecv(ep_priv->domain->psm_mq,
303 			   psm_tag, psm_tagsel, 0, /* flags */
304 			   buf, len, (void *)fi_context, &psm_req);
305 
306 	return psmx_errno(err);
307 }
308 
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)309 static ssize_t psmx_tagged_recv(struct fid_ep *ep, void *buf, size_t len, void *desc,
310 				fi_addr_t src_addr,
311 				uint64_t tag, uint64_t ignore, void *context)
312 {
313 	struct psmx_fid_ep *ep_priv;
314 
315 	ep_priv = container_of(ep, struct psmx_fid_ep, ep);
316 
317 	return _psmx_tagged_recv(ep, buf, len, desc, src_addr, tag, ignore,
318 				 context, ep_priv->rx_flags);
319 }
320 
psmx_tagged_recvmsg(struct fid_ep * ep,const struct fi_msg_tagged * msg,uint64_t flags)321 static ssize_t psmx_tagged_recvmsg(struct fid_ep *ep, const struct fi_msg_tagged *msg,
322 				   uint64_t flags)
323 {
324 	void *buf;
325 	size_t len;
326 
327 	if (!msg || (msg->iov_count && !msg->msg_iov))
328 		return -FI_EINVAL;
329 
330 	if (msg->iov_count > 1) {
331 		return -FI_ENOSYS;
332 	} else if (msg->iov_count) {
333 		buf = msg->msg_iov[0].iov_base;
334 		len = msg->msg_iov[0].iov_len;
335 	} else {
336 		buf = NULL;
337 		len = 0;
338 	}
339 
340 	return _psmx_tagged_recv(ep, buf, len,
341 				 msg->desc ? msg->desc[0] : NULL,
342 				 msg->addr, msg->tag, msg->ignore,
343 				 msg->context, flags);
344 }
345 
psmx_tagged_recv_no_flag(struct fid_ep * ep,void * buf,size_t len,void * desc,fi_addr_t src_addr,uint64_t tag,uint64_t ignore,void * context)346 static ssize_t psmx_tagged_recv_no_flag(struct fid_ep *ep, void *buf,
347 					size_t len, void *desc, fi_addr_t src_addr,
348 					uint64_t tag, uint64_t ignore,
349 					void *context)
350 {
351 	return psmx_tagged_recv_no_flag_av_map(
352 					ep, buf, len, desc, src_addr,
353 					tag, ignore, context);
354 }
355 
psmx_tagged_recv_no_event(struct fid_ep * ep,void * buf,size_t len,void * desc,fi_addr_t src_addr,uint64_t tag,uint64_t ignore,void * context)356 static ssize_t psmx_tagged_recv_no_event(struct fid_ep *ep, void *buf,
357 					size_t len, void *desc, fi_addr_t src_addr,
358 					uint64_t tag, uint64_t ignore,
359 					void *context)
360 {
361 	return psmx_tagged_recv_no_event_av_map(
362 					ep, buf, len, desc, src_addr,
363 					tag, ignore, context);
364 }
365 
psmx_tagged_recvv(struct fid_ep * ep,const struct iovec * iov,void ** desc,size_t count,fi_addr_t src_addr,uint64_t tag,uint64_t ignore,void * context)366 static ssize_t psmx_tagged_recvv(struct fid_ep *ep, const struct iovec *iov, void **desc,
367 				 size_t count, fi_addr_t src_addr,
368 				 uint64_t tag, uint64_t ignore, void *context)
369 {
370 	void *buf;
371 	size_t len;
372 
373 	if (count && !iov)
374 		return -FI_EINVAL;
375 
376 	if (count > 1) {
377 		return -FI_ENOSYS;
378 	} else if (count) {
379 		buf = iov[0].iov_base;
380 		len = iov[0].iov_len;
381 	} else {
382 		buf = NULL;
383 		len = 0;
384 	}
385 
386 	return psmx_tagged_recv(ep, buf, len,
387 				desc ? desc[0] : NULL, src_addr, tag, ignore, context);
388 }
389 
psmx_tagged_recvv_no_flag(struct fid_ep * ep,const struct iovec * iov,void ** desc,size_t count,fi_addr_t src_addr,uint64_t tag,uint64_t ignore,void * context)390 static ssize_t psmx_tagged_recvv_no_flag(struct fid_ep *ep, const struct iovec *iov,
391 					 void **desc, size_t count, fi_addr_t src_addr,
392 					 uint64_t tag, uint64_t ignore, void *context)
393 {
394 	void *buf;
395 	size_t len;
396 
397 	if (count && !iov)
398 		return -FI_EINVAL;
399 
400 	if (count > 1) {
401 		return -FI_ENOSYS;
402 	} else if (count) {
403 		buf = iov[0].iov_base;
404 		len = iov[0].iov_len;
405 	} else {
406 		buf = NULL;
407 		len = 0;
408 	}
409 
410 	return psmx_tagged_recv_no_flag(ep, buf, len,
411 					desc ? desc[0] : NULL, src_addr,
412 					tag, ignore, context);
413 }
414 
psmx_tagged_recvv_no_event(struct fid_ep * ep,const struct iovec * iov,void ** desc,size_t count,fi_addr_t src_addr,uint64_t tag,uint64_t ignore,void * context)415 static ssize_t psmx_tagged_recvv_no_event(struct fid_ep *ep, const struct iovec *iov,
416 					 void **desc, size_t count, fi_addr_t src_addr,
417 					 uint64_t tag, uint64_t ignore, void *context)
418 {
419 	void *buf;
420 	size_t len;
421 
422 	if (count && !iov)
423 		return -FI_EINVAL;
424 
425 	if (count > 1) {
426 		return -FI_ENOSYS;
427 	} else if (count) {
428 		buf = iov[0].iov_base;
429 		len = iov[0].iov_len;
430 	} else {
431 		buf = NULL;
432 		len = 0;
433 	}
434 
435 	return psmx_tagged_recv_no_event(ep, buf, len,
436 					desc ? desc[0] : NULL, src_addr,
437 					tag, ignore, context);
438 }
439 
_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)440 ssize_t _psmx_tagged_send(struct fid_ep *ep, const void *buf, size_t len,
441 			  void *desc, fi_addr_t dest_addr, uint64_t tag,
442 			  void *context, uint64_t flags)
443 {
444 	struct psmx_fid_ep *ep_priv;
445 	struct psmx_fid_av *av;
446 	psm_epaddr_t psm_epaddr;
447 	psm_mq_req_t psm_req;
448 	uint64_t psm_tag;
449 	struct fi_context *fi_context;
450 	int err;
451 	size_t idx;
452 	int no_completion = 0;
453 	struct psmx_cq_event *event;
454 
455 	ep_priv = container_of(ep, struct psmx_fid_ep, ep);
456 
457 	if (flags & FI_TRIGGER) {
458 		struct psmx_trigger *trigger;
459 		struct fi_triggered_context *ctxt = context;
460 
461 		trigger = calloc(1, sizeof(*trigger));
462 		if (!trigger)
463 			return -FI_ENOMEM;
464 
465 		trigger->op = PSMX_TRIGGERED_TSEND;
466 		trigger->cntr = container_of(ctxt->trigger.threshold.cntr,
467 					     struct psmx_fid_cntr, cntr);
468 		trigger->threshold = ctxt->trigger.threshold.threshold;
469 		trigger->tsend.ep = ep;
470 		trigger->tsend.buf = buf;
471 		trigger->tsend.len = len;
472 		trigger->tsend.desc = desc;
473 		trigger->tsend.dest_addr = dest_addr;
474 		trigger->tsend.tag = tag;
475 		trigger->tsend.context = context;
476 		trigger->tsend.flags = flags & ~FI_TRIGGER;
477 
478 		psmx_cntr_add_trigger(trigger->cntr, trigger);
479 		return 0;
480 	}
481 
482 	if (tag & ep_priv->domain->reserved_tag_bits) {
483 		FI_WARN(&psmx_prov, FI_LOG_EP_DATA,
484 			"using reserved tag bits."
485 			"tag=%lx. reserved_bits=%lx.\n", tag,
486 			ep_priv->domain->reserved_tag_bits);
487 	}
488 
489 	av = ep_priv->av;
490 	if (av && av->type == FI_AV_TABLE) {
491 		idx = (size_t)dest_addr;
492 		if (idx >= av->last)
493 			return -FI_EINVAL;
494 
495 		psm_epaddr = av->psm_epaddrs[idx];
496 	} else {
497 		psm_epaddr = (psm_epaddr_t) dest_addr;
498 	}
499 
500 	psm_tag = tag & (~ep_priv->domain->reserved_tag_bits);
501 
502 	if ((flags & PSMX_NO_COMPLETION) ||
503 	    (ep_priv->send_selective_completion && !(flags & FI_COMPLETION)))
504 		no_completion = 1;
505 
506 	if (flags & FI_INJECT) {
507 		if (len > PSMX_INJECT_SIZE)
508 			return -FI_EMSGSIZE;
509 
510 		err = psm_mq_send(ep_priv->domain->psm_mq, psm_epaddr, 0,
511 				  psm_tag, buf, len);
512 
513 		if (err != PSM_OK)
514 			return psmx_errno(err);
515 
516 		if (ep_priv->send_cntr)
517 			psmx_cntr_inc(ep_priv->send_cntr);
518 
519 		if (ep_priv->send_cq && !no_completion) {
520 			event = psmx_cq_create_event(
521 					ep_priv->send_cq,
522 					context, (void *)buf, flags, len,
523 					0 /* data */, psm_tag,
524 					0 /* olen */,
525 					0 /* err */);
526 
527 			if (event)
528 				psmx_cq_enqueue_event(ep_priv->send_cq, event);
529 			else
530 				return -FI_ENOMEM;
531 		}
532 
533 		return 0;
534 	}
535 
536 	if (no_completion && !context) {
537 		fi_context = &ep_priv->nocomp_send_context;
538 	} else {
539 		if (!context)
540 			return -FI_EINVAL;
541 
542 		fi_context = context;
543 		PSMX_CTXT_TYPE(fi_context) = PSMX_TSEND_CONTEXT;
544 		PSMX_CTXT_USER(fi_context) = (void *)buf;
545 		PSMX_CTXT_EP(fi_context) = ep_priv;
546 	}
547 
548 	err = psm_mq_isend(ep_priv->domain->psm_mq, psm_epaddr, 0,
549 				psm_tag, buf, len, (void*)fi_context, &psm_req);
550 
551 	if (err != PSM_OK)
552 		return psmx_errno(err);
553 
554 	if (fi_context == context)
555 		PSMX_CTXT_REQ(fi_context) = psm_req;
556 
557 	return 0;
558 }
559 
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)560 ssize_t psmx_tagged_send_no_flag_av_map(struct fid_ep *ep, const void *buf,
561 					size_t len, void *desc,
562 					fi_addr_t dest_addr, uint64_t tag,
563 					void *context)
564 {
565 	struct psmx_fid_ep *ep_priv;
566 	psm_epaddr_t psm_epaddr;
567 	psm_mq_req_t psm_req;
568 	uint64_t psm_tag;
569 	struct fi_context *fi_context;
570 	int err;
571 
572 	ep_priv = container_of(ep, struct psmx_fid_ep, ep);
573 
574 	psm_epaddr = (psm_epaddr_t) dest_addr;
575 	psm_tag = tag & (~ep_priv->domain->reserved_tag_bits);
576 
577 	fi_context = context;
578 	PSMX_CTXT_TYPE(fi_context) = PSMX_TSEND_CONTEXT;
579 	PSMX_CTXT_USER(fi_context) = (void *)buf;
580 	PSMX_CTXT_EP(fi_context) = ep_priv;
581 
582 	err = psm_mq_isend(ep_priv->domain->psm_mq, psm_epaddr, 0,
583 			   psm_tag, buf, len, (void*)fi_context, &psm_req);
584 
585 	if (err != PSM_OK)
586 		return psmx_errno(err);
587 
588 	PSMX_CTXT_REQ(fi_context) = psm_req;
589 	return 0;
590 }
591 
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)592 ssize_t psmx_tagged_send_no_flag_av_table(struct fid_ep *ep, const void *buf,
593 					  size_t len, void *desc,
594 					  fi_addr_t dest_addr, uint64_t tag,
595 					  void *context)
596 {
597 	struct psmx_fid_ep *ep_priv;
598 	struct psmx_fid_av *av;
599 	psm_epaddr_t psm_epaddr;
600 	psm_mq_req_t psm_req;
601 	uint64_t psm_tag;
602 	struct fi_context *fi_context;
603 	int err;
604 	size_t idx;
605 
606 	ep_priv = container_of(ep, struct psmx_fid_ep, ep);
607 
608 	av = ep_priv->av;
609 	idx = (size_t)dest_addr;
610 	if (idx >= av->last)
611 		return -FI_EINVAL;
612 
613 	psm_epaddr = av->psm_epaddrs[idx];
614 	psm_tag = tag & (~ep_priv->domain->reserved_tag_bits);
615 
616 	fi_context = context;
617 	PSMX_CTXT_TYPE(fi_context) = PSMX_TSEND_CONTEXT;
618 	PSMX_CTXT_USER(fi_context) = (void *)buf;
619 	PSMX_CTXT_EP(fi_context) = ep_priv;
620 
621 	err = psm_mq_isend(ep_priv->domain->psm_mq, psm_epaddr, 0,
622 			   psm_tag, buf, len, (void*)fi_context, &psm_req);
623 
624 	if (err != PSM_OK)
625 		return psmx_errno(err);
626 
627 	PSMX_CTXT_REQ(fi_context) = psm_req;
628 	return 0;
629 }
630 
psmx_tagged_send_no_event_av_map(struct fid_ep * ep,const void * buf,size_t len,void * desc,fi_addr_t dest_addr,uint64_t tag,void * context)631 ssize_t psmx_tagged_send_no_event_av_map(struct fid_ep *ep, const void *buf,
632 					 size_t len, void *desc,
633 					 fi_addr_t dest_addr, uint64_t tag,
634 					 void *context)
635 {
636 	struct psmx_fid_ep *ep_priv;
637 	psm_epaddr_t psm_epaddr;
638 	psm_mq_req_t psm_req;
639 	uint64_t psm_tag;
640 	struct fi_context *fi_context;
641 	int err;
642 
643 	ep_priv = container_of(ep, struct psmx_fid_ep, ep);
644 
645 	psm_epaddr = (psm_epaddr_t) dest_addr;
646 	psm_tag = tag & (~ep_priv->domain->reserved_tag_bits);
647 
648 	fi_context = &ep_priv->nocomp_send_context;
649 
650 	err = psm_mq_isend(ep_priv->domain->psm_mq, psm_epaddr, 0,
651 			   psm_tag, buf, len, (void*)fi_context, &psm_req);
652 
653 	if (err != PSM_OK)
654 		return psmx_errno(err);
655 
656 	return 0;
657 }
658 
psmx_tagged_send_no_event_av_table(struct fid_ep * ep,const void * buf,size_t len,void * desc,fi_addr_t dest_addr,uint64_t tag,void * context)659 ssize_t psmx_tagged_send_no_event_av_table(struct fid_ep *ep, const void *buf,
660 					   size_t len, void *desc,
661 					   fi_addr_t dest_addr, uint64_t tag,
662 					   void *context)
663 {
664 	struct psmx_fid_ep *ep_priv;
665 	struct psmx_fid_av *av;
666 	psm_epaddr_t psm_epaddr;
667 	psm_mq_req_t psm_req;
668 	uint64_t psm_tag;
669 	struct fi_context *fi_context;
670 	int err;
671 	size_t idx;
672 
673 	ep_priv = container_of(ep, struct psmx_fid_ep, ep);
674 
675 	av = ep_priv->av;
676 	idx = (size_t)dest_addr;
677 	if (idx >= av->last)
678 		return -FI_EINVAL;
679 
680 	psm_epaddr = av->psm_epaddrs[idx];
681 	psm_tag = tag & (~ep_priv->domain->reserved_tag_bits);
682 
683 	fi_context = &ep_priv->nocomp_send_context;
684 
685 	err = psm_mq_isend(ep_priv->domain->psm_mq, psm_epaddr, 0,
686 			   psm_tag, buf, len, (void*)fi_context, &psm_req);
687 
688 	if (err != PSM_OK)
689 		return psmx_errno(err);
690 
691 	return 0;
692 }
693 
psmx_tagged_inject_no_flag_av_map(struct fid_ep * ep,const void * buf,size_t len,fi_addr_t dest_addr,uint64_t tag)694 ssize_t psmx_tagged_inject_no_flag_av_map(struct fid_ep *ep, const void *buf, size_t len,
695 					  fi_addr_t dest_addr, uint64_t tag)
696 {
697 	struct psmx_fid_ep *ep_priv;
698 	psm_epaddr_t psm_epaddr;
699 	uint64_t psm_tag;
700 	int err;
701 
702 	if (len > PSMX_INJECT_SIZE)
703 		return -FI_EMSGSIZE;
704 
705 	ep_priv = container_of(ep, struct psmx_fid_ep, ep);
706 
707 	psm_epaddr = (psm_epaddr_t) dest_addr;
708 	psm_tag = tag & (~ep_priv->domain->reserved_tag_bits);
709 
710 	err = psm_mq_send(ep_priv->domain->psm_mq, psm_epaddr, 0, psm_tag, buf, len);
711 
712 	if (err != PSM_OK)
713 		return psmx_errno(err);
714 
715 	if (ep_priv->send_cntr)
716 		psmx_cntr_inc(ep_priv->send_cntr);
717 
718 	return 0;
719 }
720 
psmx_tagged_inject_no_flag_av_table(struct fid_ep * ep,const void * buf,size_t len,fi_addr_t dest_addr,uint64_t tag)721 ssize_t psmx_tagged_inject_no_flag_av_table(struct fid_ep *ep, const void *buf, size_t len,
722 					    fi_addr_t dest_addr, uint64_t tag)
723 {
724 	struct psmx_fid_ep *ep_priv;
725 	struct psmx_fid_av *av;
726 	psm_epaddr_t psm_epaddr;
727 	uint64_t psm_tag;
728 	int err;
729 	size_t idx;
730 
731 	if (len > PSMX_INJECT_SIZE)
732 		return -FI_EMSGSIZE;
733 
734 	ep_priv = container_of(ep, struct psmx_fid_ep, ep);
735 
736 	av = ep_priv->av;
737 	idx = (size_t)dest_addr;
738 	if (idx >= av->last)
739 		return -FI_EINVAL;
740 
741 	psm_epaddr = av->psm_epaddrs[idx];
742 	psm_tag = tag & (~ep_priv->domain->reserved_tag_bits);
743 
744 	err = psm_mq_send(ep_priv->domain->psm_mq, psm_epaddr, 0, psm_tag, buf, len);
745 
746 	if (err != PSM_OK)
747 		return psmx_errno(err);
748 
749 	if (ep_priv->send_cntr)
750 		psmx_cntr_inc(ep_priv->send_cntr);
751 
752 	return 0;
753 }
754 
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)755 static ssize_t psmx_tagged_send(struct fid_ep *ep, const void *buf, size_t len,
756 				void *desc, fi_addr_t dest_addr,
757 				uint64_t tag, void *context)
758 {
759 	struct psmx_fid_ep *ep_priv;
760 
761 	ep_priv = container_of(ep, struct psmx_fid_ep, ep);
762 
763 	return _psmx_tagged_send(ep, buf, len, desc, dest_addr, tag, context,
764 				 ep_priv->tx_flags);
765 }
766 
psmx_tagged_sendmsg(struct fid_ep * ep,const struct fi_msg_tagged * msg,uint64_t flags)767 static ssize_t psmx_tagged_sendmsg(struct fid_ep *ep, const struct fi_msg_tagged *msg,
768 				   uint64_t flags)
769 {
770 	void *buf;
771 	size_t len;
772 
773 	if (!msg || (msg->iov_count && !msg->msg_iov))
774 		return -FI_EINVAL;
775 
776 	if (msg->iov_count > 1) {
777 		return -FI_ENOSYS;
778 	} else if (msg->iov_count) {
779 		buf = msg->msg_iov[0].iov_base;
780 		len = msg->msg_iov[0].iov_len;
781 	} else {
782 		buf = NULL;
783 		len = 0;
784 	}
785 
786 	return _psmx_tagged_send(ep, buf, len,
787 				 msg->desc ? msg->desc[0] : NULL, msg->addr,
788 				 msg->tag, msg->context, flags);
789 }
790 
psmx_tagged_sendv(struct fid_ep * ep,const struct iovec * iov,void ** desc,size_t count,fi_addr_t dest_addr,uint64_t tag,void * context)791 static ssize_t psmx_tagged_sendv(struct fid_ep *ep, const struct iovec *iov, void **desc,
792 				 size_t count, fi_addr_t dest_addr, uint64_t tag, void *context)
793 {
794 	void *buf;
795 	size_t len;
796 
797 	if (count && !iov)
798 		return -FI_EINVAL;
799 
800 	if (count > 1) {
801 		return -FI_ENOSYS;
802 	} else if (count) {
803 		buf = iov[0].iov_base;
804 		len = iov[0].iov_len;
805 	} else {
806 		buf = NULL;
807 		len = 0;
808 	}
809 
810 	return psmx_tagged_send(ep, buf, len,
811 				desc ? desc[0] : NULL, dest_addr, tag, context);
812 }
813 
psmx_tagged_sendv_no_flag_av_map(struct fid_ep * ep,const struct iovec * iov,void ** desc,size_t count,fi_addr_t dest_addr,uint64_t tag,void * context)814 static ssize_t psmx_tagged_sendv_no_flag_av_map(struct fid_ep *ep, const struct iovec *iov,
815 						void **desc, size_t count,
816 						fi_addr_t dest_addr,
817 						uint64_t tag, void *context)
818 {
819 	void *buf;
820 	size_t len;
821 
822 	if (count && !iov)
823 		return -FI_EINVAL;
824 
825 	if (count > 1) {
826 		return -FI_ENOSYS;
827 	} else if (count) {
828 		buf = iov[0].iov_base;
829 		len = iov[0].iov_len;
830 	} else {
831 		buf = NULL;
832 		len = 0;
833 	}
834 
835 	return psmx_tagged_send_no_flag_av_map(ep, buf, len,
836 					       desc ? desc[0] : NULL, dest_addr,
837 					       tag, context);
838 }
839 
psmx_tagged_sendv_no_flag_av_table(struct fid_ep * ep,const struct iovec * iov,void ** desc,size_t count,fi_addr_t dest_addr,uint64_t tag,void * context)840 static ssize_t psmx_tagged_sendv_no_flag_av_table(struct fid_ep *ep, const struct iovec *iov,
841 						  void **desc, size_t count,
842 						  fi_addr_t dest_addr,
843 						  uint64_t tag, void *context)
844 {
845 	void *buf;
846 	size_t len;
847 
848 	if (count && !iov)
849 		return -FI_EINVAL;
850 
851 	if (count > 1) {
852 		return -FI_ENOSYS;
853 	} else if (count) {
854 		buf = iov[0].iov_base;
855 		len = iov[0].iov_len;
856 	} else {
857 		buf = NULL;
858 		len = 0;
859 	}
860 
861 	return psmx_tagged_send_no_flag_av_table(ep, buf, len,
862 						 desc ? desc[0] : NULL, dest_addr,
863 						 tag, context);
864 }
865 
psmx_tagged_sendv_no_event_av_map(struct fid_ep * ep,const struct iovec * iov,void ** desc,size_t count,fi_addr_t dest_addr,uint64_t tag,void * context)866 static ssize_t psmx_tagged_sendv_no_event_av_map(struct fid_ep *ep, const struct iovec *iov,
867 						void **desc, size_t count,
868 						fi_addr_t dest_addr,
869 						uint64_t tag, void *context)
870 {
871 	void *buf;
872 	size_t len;
873 
874 	if (count && !iov)
875 		return -FI_EINVAL;
876 
877 	if (count > 1) {
878 		return -FI_ENOSYS;
879 	} else if (count) {
880 		buf = iov[0].iov_base;
881 		len = iov[0].iov_len;
882 	} else {
883 		buf = NULL;
884 		len = 0;
885 	}
886 
887 	return psmx_tagged_send_no_event_av_map(ep, buf, len,
888 					       desc ? desc[0] : NULL, dest_addr,
889 					       tag, context);
890 }
891 
psmx_tagged_sendv_no_event_av_table(struct fid_ep * ep,const struct iovec * iov,void ** desc,size_t count,fi_addr_t dest_addr,uint64_t tag,void * context)892 static ssize_t psmx_tagged_sendv_no_event_av_table(struct fid_ep *ep, const struct iovec *iov,
893 						  void **desc, size_t count,
894 						  fi_addr_t dest_addr,
895 						  uint64_t tag, void *context)
896 {
897 	void *buf;
898 	size_t len;
899 
900 	if (count && !iov)
901 		return -FI_EINVAL;
902 
903 	if (count > 1) {
904 		return -FI_ENOSYS;
905 	} else if (count) {
906 		buf = iov[0].iov_base;
907 		len = iov[0].iov_len;
908 	} else {
909 		buf = NULL;
910 		len = 0;
911 	}
912 
913 	return psmx_tagged_send_no_event_av_table(ep, buf, len,
914 						 desc ? desc[0] : NULL,
915 						 dest_addr, tag, context);
916 }
917 
psmx_tagged_inject(struct fid_ep * ep,const void * buf,size_t len,fi_addr_t dest_addr,uint64_t tag)918 static ssize_t psmx_tagged_inject(struct fid_ep *ep, const void *buf, size_t len,
919 				  fi_addr_t dest_addr, uint64_t tag)
920 {
921 	struct psmx_fid_ep *ep_priv;
922 
923 	ep_priv = container_of(ep, struct psmx_fid_ep, ep);
924 
925 	return _psmx_tagged_send(ep, buf, len, NULL, dest_addr, tag, NULL,
926 				 ep_priv->tx_flags | FI_INJECT | PSMX_NO_COMPLETION);
927 }
928 
929 /* general case */
930 struct fi_ops_tagged psmx_tagged_ops = {
931 	.size = sizeof(struct fi_ops_tagged),
932 	.recv = psmx_tagged_recv,
933 	.recvv = psmx_tagged_recvv,
934 	.recvmsg = psmx_tagged_recvmsg,
935 	.send = psmx_tagged_send,
936 	.sendv = psmx_tagged_sendv,
937 	.sendmsg = psmx_tagged_sendmsg,
938 	.inject = psmx_tagged_inject,
939 	.senddata = fi_no_tagged_senddata,
940 	.injectdata = fi_no_tagged_injectdata,
941 };
942 
943 /* op_flags=0, no event suppression, FI_AV_MAP */
944 struct fi_ops_tagged psmx_tagged_ops_no_flag_av_map = {
945 	.size = sizeof(struct fi_ops_tagged),
946 	.recv = psmx_tagged_recv_no_flag,
947 	.recvv = psmx_tagged_recvv_no_flag,
948 	.recvmsg = psmx_tagged_recvmsg,
949 	.send = psmx_tagged_send_no_flag_av_map,
950 	.sendv = psmx_tagged_sendv_no_flag_av_map,
951 	.sendmsg = psmx_tagged_sendmsg,
952 	.inject = psmx_tagged_inject_no_flag_av_map,
953 	.senddata = fi_no_tagged_senddata,
954 	.injectdata = fi_no_tagged_injectdata,
955 };
956 
957 /* op_flags=0, no event suppression, FI_AV_TABLE */
958 struct fi_ops_tagged psmx_tagged_ops_no_flag_av_table = {
959 	.size = sizeof(struct fi_ops_tagged),
960 	.recv = psmx_tagged_recv_no_flag,
961 	.recvv = psmx_tagged_recvv_no_flag,
962 	.recvmsg = psmx_tagged_recvmsg,
963 	.send = psmx_tagged_send_no_flag_av_table,
964 	.sendv = psmx_tagged_sendv_no_flag_av_table,
965 	.sendmsg = psmx_tagged_sendmsg,
966 	.inject = psmx_tagged_inject_no_flag_av_table,
967 	.senddata = fi_no_tagged_senddata,
968 	.injectdata = fi_no_tagged_injectdata,
969 };
970 
971 /* op_flags=0, event suppression, FI_AV_MAP */
972 struct fi_ops_tagged psmx_tagged_ops_no_event_av_map = {
973 	.size = sizeof(struct fi_ops_tagged),
974 	.recv = psmx_tagged_recv_no_event,
975 	.recvv = psmx_tagged_recvv_no_event,
976 	.recvmsg = psmx_tagged_recvmsg,
977 	.send = psmx_tagged_send_no_event_av_map,
978 	.sendv = psmx_tagged_sendv_no_event_av_map,
979 	.sendmsg = psmx_tagged_sendmsg,
980 	.inject = psmx_tagged_inject_no_flag_av_map,
981 	.senddata = fi_no_tagged_senddata,
982 	.injectdata = fi_no_tagged_injectdata,
983 };
984 
985 /* op_flags=0, event suppression, FI_AV_TABLE */
986 struct fi_ops_tagged psmx_tagged_ops_no_event_av_table = {
987 	.size = sizeof(struct fi_ops_tagged),
988 	.recv = psmx_tagged_recv_no_event,
989 	.recvv = psmx_tagged_recvv_no_event,
990 	.recvmsg = psmx_tagged_recvmsg,
991 	.send = psmx_tagged_send_no_event_av_table,
992 	.sendv = psmx_tagged_sendv_no_event_av_table,
993 	.sendmsg = psmx_tagged_sendmsg,
994 	.inject = psmx_tagged_inject_no_flag_av_table,
995 	.senddata = fi_no_tagged_senddata,
996 	.injectdata = fi_no_tagged_injectdata,
997 };
998 
999 /* op_flags=0, send event suppression, FI_AV_MAP */
1000 struct fi_ops_tagged psmx_tagged_ops_no_send_event_av_map = {
1001 	.size = sizeof(struct fi_ops_tagged),
1002 	.recv = psmx_tagged_recv_no_flag,
1003 	.recvv = psmx_tagged_recvv_no_flag,
1004 	.recvmsg = psmx_tagged_recvmsg,
1005 	.send = psmx_tagged_send_no_event_av_map,
1006 	.sendv = psmx_tagged_sendv_no_event_av_map,
1007 	.sendmsg = psmx_tagged_sendmsg,
1008 	.inject = psmx_tagged_inject_no_flag_av_map,
1009 	.senddata = fi_no_tagged_senddata,
1010 	.injectdata = fi_no_tagged_injectdata,
1011 };
1012 
1013 /* op_flags=0, send event suppression, FI_AV_TABLE */
1014 struct fi_ops_tagged psmx_tagged_ops_no_send_event_av_table = {
1015 	.size = sizeof(struct fi_ops_tagged),
1016 	.recv = psmx_tagged_recv_no_flag,
1017 	.recvv = psmx_tagged_recvv_no_flag,
1018 	.recvmsg = psmx_tagged_recvmsg,
1019 	.send = psmx_tagged_send_no_event_av_table,
1020 	.sendv = psmx_tagged_sendv_no_event_av_table,
1021 	.sendmsg = psmx_tagged_sendmsg,
1022 	.inject = psmx_tagged_inject_no_flag_av_table,
1023 	.senddata = fi_no_tagged_senddata,
1024 	.injectdata = fi_no_tagged_injectdata,
1025 };
1026 
1027 /* op_flags=0, recv event suppression, FI_AV_MAP */
1028 struct fi_ops_tagged psmx_tagged_ops_no_recv_event_av_map = {
1029 	.size = sizeof(struct fi_ops_tagged),
1030 	.recv = psmx_tagged_recv_no_event,
1031 	.recvv = psmx_tagged_recvv_no_event,
1032 	.recvmsg = psmx_tagged_recvmsg,
1033 	.send = psmx_tagged_send_no_flag_av_map,
1034 	.sendv = psmx_tagged_sendv_no_flag_av_map,
1035 	.sendmsg = psmx_tagged_sendmsg,
1036 	.inject = psmx_tagged_inject_no_flag_av_map,
1037 	.senddata = fi_no_tagged_senddata,
1038 	.injectdata = fi_no_tagged_injectdata,
1039 };
1040 
1041 /* op_flags=0, recv event suppression, FI_AV_TABLE */
1042 struct fi_ops_tagged psmx_tagged_ops_no_recv_event_av_table = {
1043 	.size = sizeof(struct fi_ops_tagged),
1044 	.recv = psmx_tagged_recv_no_event,
1045 	.recvv = psmx_tagged_recvv_no_event,
1046 	.recvmsg = psmx_tagged_recvmsg,
1047 	.send = psmx_tagged_send_no_flag_av_table,
1048 	.sendv = psmx_tagged_sendv_no_flag_av_table,
1049 	.sendmsg = psmx_tagged_sendmsg,
1050 	.inject = psmx_tagged_inject_no_flag_av_table,
1051 	.senddata = fi_no_tagged_senddata,
1052 	.injectdata = fi_no_tagged_injectdata,
1053 };
1054