1 /*
2  * Copyright (c) 2013-2014 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 #ifndef FI_EQ_H
34 #define FI_EQ_H
35 
36 #include <poll.h>
37 
38 #ifndef _WIN32
39 #include <pthread.h>
40 #endif /* _WIN32 */
41 
42 #include <rdma/fabric.h>
43 #include <rdma/fi_errno.h>
44 
45 
46 #ifdef __cplusplus
47 extern "C" {
48 #endif
49 
50 
51 
52 /*
53  * Wait Set
54  * Allows associating multiple EQs and counters with a single wait object.
55  */
56 
57 /* Use fi_control GETWAIT to get underlying wait object(s) */
58 enum fi_wait_obj {
59 	FI_WAIT_NONE,
60 	FI_WAIT_UNSPEC,
61 	FI_WAIT_SET,
62 	FI_WAIT_FD,
63 	FI_WAIT_MUTEX_COND,	/* pthread mutex & cond */
64 	FI_WAIT_YIELD,
65 	FI_WAIT_POLLFD,
66 };
67 
68 struct fi_wait_attr {
69 	enum fi_wait_obj	wait_obj;
70 	uint64_t		flags;
71 };
72 
73 struct fi_ops_wait {
74 	size_t	size;
75 	int	(*wait)(struct fid_wait *waitset, int timeout);
76 };
77 
78 struct fid_wait {
79 	struct fid		fid;
80 	struct fi_ops_wait	*ops;
81 };
82 
83 #ifndef _WIN32
84 struct fi_mutex_cond {
85 	pthread_mutex_t		*mutex;
86 	pthread_cond_t		*cond;
87 };
88 #endif /* _WIN32 */
89 
90 struct fi_wait_pollfd {
91 	uint64_t		change_index;
92 	size_t			nfds;
93 	struct pollfd		*fd;
94 };
95 
96 /*
97  * Poll Set
98  * Allows polling multiple event queues and counters for progress
99  */
100 
101 struct fi_poll_attr {
102 	uint64_t		flags;
103 };
104 
105 struct fi_ops_poll {
106 	size_t	size;
107 	int	(*poll)(struct fid_poll *pollset, void **context, int count);
108 	int	(*poll_add)(struct fid_poll *pollset, struct fid *event_fid,
109 			uint64_t flags);
110 	int	(*poll_del)(struct fid_poll *pollset, struct fid *event_fid,
111 			uint64_t flags);
112 };
113 
114 struct fid_poll {
115 	struct fid		fid;
116 	struct fi_ops_poll	*ops;
117 };
118 
119 /*
120  * EQ = Event Queue
121  * Used to report various control (not data transfer) events and operations.
122  */
123 
124 struct fi_eq_attr {
125 	size_t			size;
126 	uint64_t		flags;
127 	enum fi_wait_obj	wait_obj;
128 	int			signaling_vector;
129 	struct fid_wait		*wait_set;
130 };
131 
132 /* Standard EQ events */
133 enum {
134 	FI_NOTIFY,
135 	FI_CONNREQ,
136 	FI_CONNECTED,
137 	FI_SHUTDOWN,
138 	FI_MR_COMPLETE,
139 	FI_AV_COMPLETE,
140 	FI_JOIN_COMPLETE,
141 };
142 
143 struct fi_eq_entry {
144 	fid_t			fid;
145 	void			*context;
146 	uint64_t		data;
147 };
148 
149 struct fi_eq_err_entry {
150 	fid_t			fid;
151 	void			*context;
152 	uint64_t		data;
153 	int			err;
154 	int			prov_errno;
155 	/* err_data is available until the next time the EQ is read */
156 	void			*err_data;
157 	size_t			err_data_size;
158 };
159 
160 struct fi_eq_cm_entry {
161 	fid_t			fid;
162 	/* user must call fi_freeinfo to release info */
163 	struct fi_info		*info;
164 	/* connection data placed here, up to space provided */
165 	uint8_t			data[];
166 };
167 
168 struct fi_ops_eq {
169 	size_t	size;
170 	ssize_t	(*read)(struct fid_eq *eq, uint32_t *event,
171 			void *buf, size_t len, uint64_t flags);
172 	ssize_t	(*readerr)(struct fid_eq *eq, struct fi_eq_err_entry *buf,
173 			uint64_t flags);
174 	ssize_t	(*write)(struct fid_eq *eq, uint32_t event,
175 			const void *buf, size_t len, uint64_t flags);
176 	ssize_t	(*sread)(struct fid_eq *eq, uint32_t *event,
177 			void *buf, size_t len, int timeout, uint64_t flags);
178 	const char * (*strerror)(struct fid_eq *eq, int prov_errno,
179 			const void *err_data, char *buf, size_t len);
180 };
181 
182 struct fid_eq {
183 	struct fid		fid;
184 	struct fi_ops_eq	*ops;
185 };
186 
187 
188 /*
189  * CQ = Complete Queue
190  * Used to report the completion of data transfer operations.
191  */
192 
193 enum fi_cq_format {
194 	FI_CQ_FORMAT_UNSPEC,
195 	FI_CQ_FORMAT_CONTEXT,
196 	FI_CQ_FORMAT_MSG,
197 	FI_CQ_FORMAT_DATA,
198 	FI_CQ_FORMAT_TAGGED,
199 };
200 
201 struct fi_cq_entry {
202 	void			*op_context;
203 };
204 
205 struct fi_cq_msg_entry {
206 	void			*op_context;
207 	uint64_t		flags;
208 	size_t			len;
209 };
210 
211 struct fi_cq_data_entry {
212 	void			*op_context;
213 	uint64_t		flags;
214 	size_t			len;
215 	void			*buf;
216 	/* data depends on operation and/or flags - e.g. remote EQ data */
217 	uint64_t		data;
218 };
219 
220 struct fi_cq_tagged_entry {
221 	void			*op_context;
222 	uint64_t		flags;
223 	size_t			len;
224 	void			*buf;
225 	uint64_t		data;
226 	uint64_t		tag;
227 };
228 
229 struct fi_cq_err_entry {
230 	void			*op_context;
231 	uint64_t		flags;
232 	size_t			len;
233 	void			*buf;
234 	uint64_t		data;
235 	uint64_t		tag;
236 	size_t			olen;
237 	int			err;
238 	int			prov_errno;
239 	/* err_data is available until the next time the CQ is read */
240 	void			*err_data;
241 	size_t			err_data_size;
242 };
243 
244 enum fi_cq_wait_cond {
245 	FI_CQ_COND_NONE,
246 	FI_CQ_COND_THRESHOLD	/* size_t threshold */
247 };
248 
249 struct fi_cq_attr {
250 	size_t			size;
251 	uint64_t		flags;
252 	enum fi_cq_format	format;
253 	enum fi_wait_obj	wait_obj;
254 	int			signaling_vector;
255 	enum fi_cq_wait_cond	wait_cond;
256 	struct fid_wait		*wait_set;
257 };
258 
259 struct fi_ops_cq {
260 	size_t	size;
261 	ssize_t	(*read)(struct fid_cq *cq, void *buf, size_t count);
262 	ssize_t	(*readfrom)(struct fid_cq *cq, void *buf, size_t count,
263 			fi_addr_t *src_addr);
264 	ssize_t	(*readerr)(struct fid_cq *cq, struct fi_cq_err_entry *buf,
265 			uint64_t flags);
266 	ssize_t	(*sread)(struct fid_cq *cq, void *buf, size_t count,
267 			const void *cond, int timeout);
268 	ssize_t	(*sreadfrom)(struct fid_cq *cq, void *buf, size_t count,
269 			fi_addr_t *src_addr, const void *cond, int timeout);
270 	int	(*signal)(struct fid_cq *cq);
271 	const char * (*strerror)(struct fid_cq *cq, int prov_errno,
272 			const void *err_data, char *buf, size_t len);
273 };
274 
275 struct fid_cq {
276 	struct fid		fid;
277 	struct fi_ops_cq	*ops;
278 };
279 
280 
281 /*
282  * CNTR = Counter
283  * Used to report the number of completed of asynchronous operations.
284  */
285 
286 enum fi_cntr_events {
287 	FI_CNTR_EVENTS_COMP
288 };
289 
290 struct fi_cntr_attr {
291 	enum fi_cntr_events	events;
292 	enum fi_wait_obj	wait_obj;
293 	struct fid_wait		*wait_set;
294 	uint64_t		flags;
295 };
296 
297 struct fi_ops_cntr {
298 	size_t	size;
299 	uint64_t (*read)(struct fid_cntr *cntr);
300 	uint64_t (*readerr)(struct fid_cntr *cntr);
301 	int	(*add)(struct fid_cntr *cntr, uint64_t value);
302 	int	(*set)(struct fid_cntr *cntr, uint64_t value);
303 	int	(*wait)(struct fid_cntr *cntr, uint64_t threshold, int timeout);
304 	int	(*adderr)(struct fid_cntr *cntr, uint64_t value);
305 	int	(*seterr)(struct fid_cntr *cntr, uint64_t value);
306 };
307 
308 struct fid_cntr {
309 	struct fid		fid;
310 	struct fi_ops_cntr	*ops;
311 };
312 
313 
314 #ifdef FABRIC_DIRECT
315 #include <rdma/fi_direct_eq.h>
316 #endif	/* FABRIC_DIRECT */
317 
318 #ifndef FABRIC_DIRECT_EQ
319 
320 static inline int
fi_trywait(struct fid_fabric * fabric,struct fid ** fids,int count)321 fi_trywait(struct fid_fabric *fabric, struct fid **fids, int count)
322 {
323 	return fabric->ops->trywait(fabric, fids, count);
324 }
325 
326 static inline int
fi_wait(struct fid_wait * waitset,int timeout)327 fi_wait(struct fid_wait *waitset, int timeout)
328 {
329 	return waitset->ops->wait(waitset, timeout);
330 }
331 
332 static inline int
fi_poll(struct fid_poll * pollset,void ** context,int count)333 fi_poll(struct fid_poll *pollset, void **context, int count)
334 {
335 	return pollset->ops->poll(pollset, context, count);
336 }
337 
338 static inline int
fi_poll_add(struct fid_poll * pollset,struct fid * event_fid,uint64_t flags)339 fi_poll_add(struct fid_poll *pollset, struct fid *event_fid, uint64_t flags)
340 {
341 	return pollset->ops->poll_add(pollset, event_fid, flags);
342 }
343 
344 static inline int
fi_poll_del(struct fid_poll * pollset,struct fid * event_fid,uint64_t flags)345 fi_poll_del(struct fid_poll *pollset, struct fid *event_fid, uint64_t flags)
346 {
347 	return pollset->ops->poll_del(pollset, event_fid, flags);
348 }
349 
350 static inline int
fi_eq_open(struct fid_fabric * fabric,struct fi_eq_attr * attr,struct fid_eq ** eq,void * context)351 fi_eq_open(struct fid_fabric *fabric, struct fi_eq_attr *attr,
352 	   struct fid_eq **eq, void *context)
353 {
354 	return fabric->ops->eq_open(fabric, attr, eq, context);
355 }
356 
357 static inline ssize_t
fi_eq_read(struct fid_eq * eq,uint32_t * event,void * buf,size_t len,uint64_t flags)358 fi_eq_read(struct fid_eq *eq, uint32_t *event, void *buf,
359 	   size_t len, uint64_t flags)
360 {
361 	return eq->ops->read(eq, event, buf, len, flags);
362 }
363 
364 static inline ssize_t
fi_eq_readerr(struct fid_eq * eq,struct fi_eq_err_entry * buf,uint64_t flags)365 fi_eq_readerr(struct fid_eq *eq, struct fi_eq_err_entry *buf, uint64_t flags)
366 {
367 	return eq->ops->readerr(eq, buf, flags);
368 }
369 
370 static inline ssize_t
fi_eq_write(struct fid_eq * eq,uint32_t event,const void * buf,size_t len,uint64_t flags)371 fi_eq_write(struct fid_eq *eq, uint32_t event, const void *buf,
372 	    size_t len, uint64_t flags)
373 {
374 	return eq->ops->write(eq, event, buf, len, flags);
375 }
376 
377 static inline ssize_t
fi_eq_sread(struct fid_eq * eq,uint32_t * event,void * buf,size_t len,int timeout,uint64_t flags)378 fi_eq_sread(struct fid_eq *eq, uint32_t *event, void *buf, size_t len,
379 	    int timeout, uint64_t flags)
380 {
381 	return eq->ops->sread(eq, event, buf, len, timeout, flags);
382 }
383 
384 static inline const char *
fi_eq_strerror(struct fid_eq * eq,int prov_errno,const void * err_data,char * buf,size_t len)385 fi_eq_strerror(struct fid_eq *eq, int prov_errno, const void *err_data,
386 	       char *buf, size_t len)
387 {
388 	return eq->ops->strerror(eq, prov_errno, err_data, buf, len);
389 }
390 
391 
fi_cq_read(struct fid_cq * cq,void * buf,size_t count)392 static inline ssize_t fi_cq_read(struct fid_cq *cq, void *buf, size_t count)
393 {
394 	return cq->ops->read(cq, buf, count);
395 }
396 
397 static inline ssize_t
fi_cq_readfrom(struct fid_cq * cq,void * buf,size_t count,fi_addr_t * src_addr)398 fi_cq_readfrom(struct fid_cq *cq, void *buf, size_t count, fi_addr_t *src_addr)
399 {
400 	return cq->ops->readfrom(cq, buf, count, src_addr);
401 }
402 
403 static inline ssize_t
fi_cq_readerr(struct fid_cq * cq,struct fi_cq_err_entry * buf,uint64_t flags)404 fi_cq_readerr(struct fid_cq *cq, struct fi_cq_err_entry *buf, uint64_t flags)
405 {
406 	return cq->ops->readerr(cq, buf, flags);
407 }
408 
409 static inline ssize_t
fi_cq_sread(struct fid_cq * cq,void * buf,size_t count,const void * cond,int timeout)410 fi_cq_sread(struct fid_cq *cq, void *buf, size_t count, const void *cond, int timeout)
411 {
412 	return cq->ops->sread(cq, buf, count, cond, timeout);
413 }
414 
415 static inline ssize_t
fi_cq_sreadfrom(struct fid_cq * cq,void * buf,size_t count,fi_addr_t * src_addr,const void * cond,int timeout)416 fi_cq_sreadfrom(struct fid_cq *cq, void *buf, size_t count,
417 		fi_addr_t *src_addr, const void *cond, int timeout)
418 {
419 	return cq->ops->sreadfrom(cq, buf, count, src_addr, cond, timeout);
420 }
421 
fi_cq_signal(struct fid_cq * cq)422 static inline int fi_cq_signal(struct fid_cq *cq)
423 {
424 	return cq->ops->signal(cq);
425 }
426 
427 static inline const char *
fi_cq_strerror(struct fid_cq * cq,int prov_errno,const void * err_data,char * buf,size_t len)428 fi_cq_strerror(struct fid_cq *cq, int prov_errno, const void *err_data,
429 	       char *buf, size_t len)
430 {
431 	return cq->ops->strerror(cq, prov_errno, err_data, buf, len);
432 }
433 
434 
fi_cntr_read(struct fid_cntr * cntr)435 static inline uint64_t fi_cntr_read(struct fid_cntr *cntr)
436 {
437 	return cntr->ops->read(cntr);
438 }
439 
fi_cntr_readerr(struct fid_cntr * cntr)440 static inline uint64_t fi_cntr_readerr(struct fid_cntr *cntr)
441 {
442 	return cntr->ops->readerr(cntr);
443 }
444 
fi_cntr_add(struct fid_cntr * cntr,uint64_t value)445 static inline int fi_cntr_add(struct fid_cntr *cntr, uint64_t value)
446 {
447 	return cntr->ops->add(cntr, value);
448 }
449 
fi_cntr_adderr(struct fid_cntr * cntr,uint64_t value)450 static inline int fi_cntr_adderr(struct fid_cntr *cntr, uint64_t value)
451 {
452 	return FI_CHECK_OP(cntr->ops, struct fi_ops_cntr, adderr) ?
453 		cntr->ops->adderr(cntr, value) : -FI_ENOSYS;
454 }
455 
fi_cntr_set(struct fid_cntr * cntr,uint64_t value)456 static inline int fi_cntr_set(struct fid_cntr *cntr, uint64_t value)
457 {
458 	return cntr->ops->set(cntr, value);
459 }
460 
fi_cntr_seterr(struct fid_cntr * cntr,uint64_t value)461 static inline int fi_cntr_seterr(struct fid_cntr *cntr, uint64_t value)
462 {
463 	return FI_CHECK_OP(cntr->ops, struct fi_ops_cntr, seterr) ?
464 		cntr->ops->seterr(cntr, value) : -FI_ENOSYS;
465 }
466 
467 static inline int
fi_cntr_wait(struct fid_cntr * cntr,uint64_t threshold,int timeout)468 fi_cntr_wait(struct fid_cntr *cntr, uint64_t threshold, int timeout)
469 {
470 	return cntr->ops->wait(cntr, threshold, timeout);
471 }
472 
473 #endif
474 
475 #ifdef __cplusplus
476 }
477 #endif
478 
479 #endif /* FI_EQ_H */
480