xref: /freebsd/contrib/ofed/libibverbs/device.c (revision 8e1f58ca)
1d6b92ffaSHans Petter Selasky /*
2d6b92ffaSHans Petter Selasky  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
3d6b92ffaSHans Petter Selasky  * Copyright (c) 2006, 2007 Cisco Systems, Inc.  All rights reserved.
4d6b92ffaSHans Petter Selasky  *
5d6b92ffaSHans Petter Selasky  * This software is available to you under a choice of one of two
6d6b92ffaSHans Petter Selasky  * licenses.  You may choose to be licensed under the terms of the GNU
7d6b92ffaSHans Petter Selasky  * General Public License (GPL) Version 2, available from the file
8d6b92ffaSHans Petter Selasky  * COPYING in the main directory of this source tree, or the
9d6b92ffaSHans Petter Selasky  * OpenIB.org BSD license below:
10d6b92ffaSHans Petter Selasky  *
11d6b92ffaSHans Petter Selasky  *     Redistribution and use in source and binary forms, with or
12d6b92ffaSHans Petter Selasky  *     without modification, are permitted provided that the following
13d6b92ffaSHans Petter Selasky  *     conditions are met:
14d6b92ffaSHans Petter Selasky  *
15d6b92ffaSHans Petter Selasky  *      - Redistributions of source code must retain the above
16d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
17d6b92ffaSHans Petter Selasky  *        disclaimer.
18d6b92ffaSHans Petter Selasky  *
19d6b92ffaSHans Petter Selasky  *      - Redistributions in binary form must reproduce the above
20d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
21d6b92ffaSHans Petter Selasky  *        disclaimer in the documentation and/or other materials
22d6b92ffaSHans Petter Selasky  *        provided with the distribution.
23d6b92ffaSHans Petter Selasky  *
24d6b92ffaSHans Petter Selasky  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25d6b92ffaSHans Petter Selasky  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26d6b92ffaSHans Petter Selasky  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27d6b92ffaSHans Petter Selasky  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28d6b92ffaSHans Petter Selasky  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29d6b92ffaSHans Petter Selasky  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30d6b92ffaSHans Petter Selasky  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31d6b92ffaSHans Petter Selasky  * SOFTWARE.
32d6b92ffaSHans Petter Selasky  */
33d6b92ffaSHans Petter Selasky #define _GNU_SOURCE
34d6b92ffaSHans Petter Selasky #include <config.h>
35d6b92ffaSHans Petter Selasky 
36d6b92ffaSHans Petter Selasky #include <infiniband/endian.h>
37d6b92ffaSHans Petter Selasky #include <stdio.h>
38d6b92ffaSHans Petter Selasky #include <sys/types.h>
39d6b92ffaSHans Petter Selasky #include <sys/stat.h>
40d6b92ffaSHans Petter Selasky #include <fcntl.h>
41d6b92ffaSHans Petter Selasky #include <unistd.h>
42d6b92ffaSHans Petter Selasky #include <stdlib.h>
43d6b92ffaSHans Petter Selasky #include <alloca.h>
44d6b92ffaSHans Petter Selasky #include <errno.h>
45d6b92ffaSHans Petter Selasky 
46d6b92ffaSHans Petter Selasky #include "ibverbs.h"
47d6b92ffaSHans Petter Selasky 
48d6b92ffaSHans Petter Selasky /* Hack to avoid GCC's -Wmissing-prototypes and the similar error from sparse
49d6b92ffaSHans Petter Selasky    with these prototypes. Symbol versionining requires the goofy names, the
50d6b92ffaSHans Petter Selasky    prototype must match the version in verbs.h.
51d6b92ffaSHans Petter Selasky  */
52d6b92ffaSHans Petter Selasky struct ibv_device **__ibv_get_device_list(int *num_devices);
53d6b92ffaSHans Petter Selasky void __ibv_free_device_list(struct ibv_device **list);
54d6b92ffaSHans Petter Selasky const char *__ibv_get_device_name(struct ibv_device *device);
55d6b92ffaSHans Petter Selasky __be64 __ibv_get_device_guid(struct ibv_device *device);
56d6b92ffaSHans Petter Selasky struct ibv_context *__ibv_open_device(struct ibv_device *device);
57d6b92ffaSHans Petter Selasky int __ibv_close_device(struct ibv_context *context);
58d6b92ffaSHans Petter Selasky int __ibv_get_async_event(struct ibv_context *context,
59d6b92ffaSHans Petter Selasky 			  struct ibv_async_event *event);
60d6b92ffaSHans Petter Selasky void __ibv_ack_async_event(struct ibv_async_event *event);
61d6b92ffaSHans Petter Selasky 
62d6b92ffaSHans Petter Selasky static pthread_once_t device_list_once = PTHREAD_ONCE_INIT;
63d6b92ffaSHans Petter Selasky static int num_devices;
64d6b92ffaSHans Petter Selasky static struct ibv_device **device_list;
65d6b92ffaSHans Petter Selasky 
count_devices(void)66d6b92ffaSHans Petter Selasky static void count_devices(void)
67d6b92ffaSHans Petter Selasky {
68d6b92ffaSHans Petter Selasky 	num_devices = ibverbs_init(&device_list);
69d6b92ffaSHans Petter Selasky }
70d6b92ffaSHans Petter Selasky 
__ibv_get_device_list(int * num)71d6b92ffaSHans Petter Selasky struct ibv_device **__ibv_get_device_list(int *num)
72d6b92ffaSHans Petter Selasky {
73d6b92ffaSHans Petter Selasky 	struct ibv_device **l;
74d6b92ffaSHans Petter Selasky 	int i;
75d6b92ffaSHans Petter Selasky 
76d6b92ffaSHans Petter Selasky 	if (num)
77d6b92ffaSHans Petter Selasky 		*num = 0;
78d6b92ffaSHans Petter Selasky 
79d6b92ffaSHans Petter Selasky 	pthread_once(&device_list_once, count_devices);
80d6b92ffaSHans Petter Selasky 
81d6b92ffaSHans Petter Selasky 	if (num_devices < 0) {
82d6b92ffaSHans Petter Selasky 		errno = -num_devices;
83d6b92ffaSHans Petter Selasky 		return NULL;
84d6b92ffaSHans Petter Selasky 	}
85d6b92ffaSHans Petter Selasky 
86d6b92ffaSHans Petter Selasky 	l = calloc(num_devices + 1, sizeof (struct ibv_device *));
87d6b92ffaSHans Petter Selasky 	if (!l) {
88d6b92ffaSHans Petter Selasky 		errno = ENOMEM;
89d6b92ffaSHans Petter Selasky 		return NULL;
90d6b92ffaSHans Petter Selasky 	}
91d6b92ffaSHans Petter Selasky 
92d6b92ffaSHans Petter Selasky 	for (i = 0; i < num_devices; ++i)
93d6b92ffaSHans Petter Selasky 		l[i] = device_list[i];
94d6b92ffaSHans Petter Selasky 	if (num)
95d6b92ffaSHans Petter Selasky 		*num = num_devices;
96d6b92ffaSHans Petter Selasky 
97d6b92ffaSHans Petter Selasky 	return l;
98d6b92ffaSHans Petter Selasky }
99d6b92ffaSHans Petter Selasky default_symver(__ibv_get_device_list, ibv_get_device_list);
100d6b92ffaSHans Petter Selasky 
__ibv_free_device_list(struct ibv_device ** list)101d6b92ffaSHans Petter Selasky void __ibv_free_device_list(struct ibv_device **list)
102d6b92ffaSHans Petter Selasky {
103d6b92ffaSHans Petter Selasky 	free(list);
104d6b92ffaSHans Petter Selasky }
105d6b92ffaSHans Petter Selasky default_symver(__ibv_free_device_list, ibv_free_device_list);
106d6b92ffaSHans Petter Selasky 
__ibv_get_device_name(struct ibv_device * device)107d6b92ffaSHans Petter Selasky const char *__ibv_get_device_name(struct ibv_device *device)
108d6b92ffaSHans Petter Selasky {
109d6b92ffaSHans Petter Selasky 	return device->name;
110d6b92ffaSHans Petter Selasky }
111d6b92ffaSHans Petter Selasky default_symver(__ibv_get_device_name, ibv_get_device_name);
112d6b92ffaSHans Petter Selasky 
__ibv_get_device_guid(struct ibv_device * device)113d6b92ffaSHans Petter Selasky __be64 __ibv_get_device_guid(struct ibv_device *device)
114d6b92ffaSHans Petter Selasky {
115d6b92ffaSHans Petter Selasky 	char attr[24];
116d6b92ffaSHans Petter Selasky 	uint64_t guid = 0;
117d6b92ffaSHans Petter Selasky 	uint16_t parts[4];
118d6b92ffaSHans Petter Selasky 	int i;
119d6b92ffaSHans Petter Selasky 
120d6b92ffaSHans Petter Selasky 	if (ibv_read_sysfs_file(device->ibdev_path, "node_guid",
121d6b92ffaSHans Petter Selasky 				attr, sizeof attr) < 0)
122d6b92ffaSHans Petter Selasky 		return 0;
123d6b92ffaSHans Petter Selasky 
124d6b92ffaSHans Petter Selasky 	if (sscanf(attr, "%hx:%hx:%hx:%hx",
125d6b92ffaSHans Petter Selasky 		   parts, parts + 1, parts + 2, parts + 3) != 4)
126d6b92ffaSHans Petter Selasky 		return 0;
127d6b92ffaSHans Petter Selasky 
128d6b92ffaSHans Petter Selasky 	for (i = 0; i < 4; ++i)
129d6b92ffaSHans Petter Selasky 		guid = (guid << 16) | parts[i];
130d6b92ffaSHans Petter Selasky 
131d6b92ffaSHans Petter Selasky 	return htobe64(guid);
132d6b92ffaSHans Petter Selasky }
133d6b92ffaSHans Petter Selasky default_symver(__ibv_get_device_guid, ibv_get_device_guid);
134d6b92ffaSHans Petter Selasky 
verbs_init_cq(struct ibv_cq * cq,struct ibv_context * context,struct ibv_comp_channel * channel,void * cq_context)135a687910fSSean Lim int verbs_init_cq(struct ibv_cq *cq, struct ibv_context *context,
136d6b92ffaSHans Petter Selasky 		       struct ibv_comp_channel *channel,
137d6b92ffaSHans Petter Selasky 		       void *cq_context)
138d6b92ffaSHans Petter Selasky {
139a687910fSSean Lim 	int err = 0;
140a687910fSSean Lim 
141d6b92ffaSHans Petter Selasky 	cq->context		   = context;
142d6b92ffaSHans Petter Selasky 	cq->channel		   = channel;
143d6b92ffaSHans Petter Selasky 
144a687910fSSean Lim 	err = pthread_mutex_init(&cq->mutex, NULL);
145a687910fSSean Lim 	if (err)
146a687910fSSean Lim 		return err;
147a687910fSSean Lim 	err = pthread_cond_init(&cq->cond, NULL);
148a687910fSSean Lim 	if (err)
149a687910fSSean Lim 		goto err;
150a687910fSSean Lim 
151d6b92ffaSHans Petter Selasky 	if (cq->channel) {
152d6b92ffaSHans Petter Selasky 		pthread_mutex_lock(&context->mutex);
153d6b92ffaSHans Petter Selasky 		++cq->channel->refcnt;
154d6b92ffaSHans Petter Selasky 		pthread_mutex_unlock(&context->mutex);
155d6b92ffaSHans Petter Selasky 	}
156d6b92ffaSHans Petter Selasky 
157d6b92ffaSHans Petter Selasky 	cq->cq_context		   = cq_context;
158d6b92ffaSHans Petter Selasky 	cq->comp_events_completed  = 0;
159d6b92ffaSHans Petter Selasky 	cq->async_events_completed = 0;
160a687910fSSean Lim 
161a687910fSSean Lim 	return err;
162a687910fSSean Lim 
163a687910fSSean Lim err:
164a687910fSSean Lim 	pthread_mutex_destroy(&cq->mutex);
165a687910fSSean Lim 
166a687910fSSean Lim 	return err;
167a687910fSSean Lim }
168a687910fSSean Lim 
verbs_cleanup_cq(struct ibv_cq * cq)169a687910fSSean Lim void verbs_cleanup_cq(struct ibv_cq *cq)
170a687910fSSean Lim {
171a687910fSSean Lim 	pthread_cond_destroy(&cq->cond);
172a687910fSSean Lim 	pthread_mutex_destroy(&cq->mutex);
173d6b92ffaSHans Petter Selasky }
174d6b92ffaSHans Petter Selasky 
175d6b92ffaSHans Petter Selasky static struct ibv_cq_ex *
__lib_ibv_create_cq_ex(struct ibv_context * context,struct ibv_cq_init_attr_ex * cq_attr)176d6b92ffaSHans Petter Selasky __lib_ibv_create_cq_ex(struct ibv_context *context,
177d6b92ffaSHans Petter Selasky 		       struct ibv_cq_init_attr_ex *cq_attr)
178d6b92ffaSHans Petter Selasky {
179d6b92ffaSHans Petter Selasky 	struct verbs_context *vctx = verbs_get_ctx(context);
180d6b92ffaSHans Petter Selasky 	struct ibv_cq_ex *cq;
181a687910fSSean Lim 	int err = 0;
182d6b92ffaSHans Petter Selasky 
183d6b92ffaSHans Petter Selasky 	if (cq_attr->wc_flags & ~IBV_CREATE_CQ_SUP_WC_FLAGS) {
184d6b92ffaSHans Petter Selasky 		errno = EOPNOTSUPP;
185d6b92ffaSHans Petter Selasky 		return NULL;
186d6b92ffaSHans Petter Selasky 	}
187d6b92ffaSHans Petter Selasky 
188d6b92ffaSHans Petter Selasky 	cq = vctx->priv->create_cq_ex(context, cq_attr);
189a687910fSSean Lim 	if (!cq)
190a687910fSSean Lim 		return NULL;
191d6b92ffaSHans Petter Selasky 
192a687910fSSean Lim 	err = verbs_init_cq(ibv_cq_ex_to_cq(cq), context,
193d6b92ffaSHans Petter Selasky 			    cq_attr->channel, cq_attr->cq_context);
194a687910fSSean Lim 	if (err)
195a687910fSSean Lim 		goto err;
196d6b92ffaSHans Petter Selasky 
197d6b92ffaSHans Petter Selasky 	return cq;
198a687910fSSean Lim 
199a687910fSSean Lim err:
200a687910fSSean Lim 	context->ops.destroy_cq(ibv_cq_ex_to_cq(cq));
201a687910fSSean Lim 
202a687910fSSean Lim 	return NULL;
203d6b92ffaSHans Petter Selasky }
204d6b92ffaSHans Petter Selasky 
__ibv_open_device(struct ibv_device * device)205d6b92ffaSHans Petter Selasky struct ibv_context *__ibv_open_device(struct ibv_device *device)
206d6b92ffaSHans Petter Selasky {
207d6b92ffaSHans Petter Selasky 	struct verbs_device *verbs_device = verbs_get_device(device);
208d6b92ffaSHans Petter Selasky 	char *devpath;
209d6b92ffaSHans Petter Selasky 	int cmd_fd, ret;
210d6b92ffaSHans Petter Selasky 	struct ibv_context *context;
211d6b92ffaSHans Petter Selasky 	struct verbs_context *context_ex;
212d6b92ffaSHans Petter Selasky 
213d6b92ffaSHans Petter Selasky 	if (asprintf(&devpath, "/dev/%s", device->dev_name) < 0)
214d6b92ffaSHans Petter Selasky 		return NULL;
215d6b92ffaSHans Petter Selasky 
216d6b92ffaSHans Petter Selasky 	/*
217d6b92ffaSHans Petter Selasky 	 * We'll only be doing writes, but we need O_RDWR in case the
218d6b92ffaSHans Petter Selasky 	 * provider needs to mmap() the file.
219d6b92ffaSHans Petter Selasky 	 */
220d6b92ffaSHans Petter Selasky 	cmd_fd = open(devpath, O_RDWR | O_CLOEXEC);
221d6b92ffaSHans Petter Selasky 	free(devpath);
222d6b92ffaSHans Petter Selasky 
223d6b92ffaSHans Petter Selasky 	if (cmd_fd < 0)
224d6b92ffaSHans Petter Selasky 		return NULL;
225d6b92ffaSHans Petter Selasky 
226d6b92ffaSHans Petter Selasky 	if (!verbs_device->ops->init_context) {
227d6b92ffaSHans Petter Selasky 		context = verbs_device->ops->alloc_context(device, cmd_fd);
228d6b92ffaSHans Petter Selasky 		if (!context)
229d6b92ffaSHans Petter Selasky 			goto err;
230a687910fSSean Lim 
231a687910fSSean Lim 		if (pthread_mutex_init(&context->mutex, NULL)) {
232a687910fSSean Lim 			verbs_device->ops->free_context(context);
233a687910fSSean Lim 			goto err;
234a687910fSSean Lim 		}
235d6b92ffaSHans Petter Selasky 	} else {
236d6b92ffaSHans Petter Selasky 		struct verbs_ex_private *priv;
237d6b92ffaSHans Petter Selasky 
238d6b92ffaSHans Petter Selasky 		/* Library now allocates the context */
239d6b92ffaSHans Petter Selasky 		context_ex = calloc(1, sizeof(*context_ex) +
240d6b92ffaSHans Petter Selasky 				       verbs_device->size_of_context);
241d6b92ffaSHans Petter Selasky 		if (!context_ex) {
242d6b92ffaSHans Petter Selasky 			errno = ENOMEM;
243d6b92ffaSHans Petter Selasky 			goto err;
244d6b92ffaSHans Petter Selasky 		}
245d6b92ffaSHans Petter Selasky 
246d6b92ffaSHans Petter Selasky 		priv = calloc(1, sizeof(*priv));
247d6b92ffaSHans Petter Selasky 		if (!priv) {
248d6b92ffaSHans Petter Selasky 			errno = ENOMEM;
249a687910fSSean Lim 			goto err_context;
250d6b92ffaSHans Petter Selasky 		}
251d6b92ffaSHans Petter Selasky 
252d6b92ffaSHans Petter Selasky 		context_ex->priv = priv;
253d6b92ffaSHans Petter Selasky 		context_ex->context.abi_compat  = __VERBS_ABI_IS_EXTENDED;
254d6b92ffaSHans Petter Selasky 		context_ex->sz = sizeof(*context_ex);
255d6b92ffaSHans Petter Selasky 
256d6b92ffaSHans Petter Selasky 		context = &context_ex->context;
257a687910fSSean Lim 		if (pthread_mutex_init(&context->mutex, NULL))
258a687910fSSean Lim 			goto verbs_err;
259a687910fSSean Lim 
260d6b92ffaSHans Petter Selasky 		ret = verbs_device->ops->init_context(verbs_device, context, cmd_fd);
261d6b92ffaSHans Petter Selasky 		if (ret)
262a687910fSSean Lim 			goto err_mutex;
263d6b92ffaSHans Petter Selasky 		/*
264d6b92ffaSHans Petter Selasky 		 * In order to maintain backward/forward binary compatibility
265d6b92ffaSHans Petter Selasky 		 * with apps compiled against libibverbs-1.1.8 that use the
266d6b92ffaSHans Petter Selasky 		 * flow steering addition, we need to set the two
267d6b92ffaSHans Petter Selasky 		 * ABI_placeholder entries to match the driver set flow
268d6b92ffaSHans Petter Selasky 		 * entries.  This is because apps compiled against
269d6b92ffaSHans Petter Selasky 		 * libibverbs-1.1.8 use an inline ibv_create_flow and
270d6b92ffaSHans Petter Selasky 		 * ibv_destroy_flow function that looks in the placeholder
271d6b92ffaSHans Petter Selasky 		 * spots for the proper entry points.  For apps compiled
272d6b92ffaSHans Petter Selasky 		 * against libibverbs-1.1.9 and later, the inline functions
273d6b92ffaSHans Petter Selasky 		 * will be looking in the right place.
274d6b92ffaSHans Petter Selasky 		 */
275d6b92ffaSHans Petter Selasky 		context_ex->ABI_placeholder1 = (void (*)(void)) context_ex->ibv_create_flow;
276d6b92ffaSHans Petter Selasky 		context_ex->ABI_placeholder2 = (void (*)(void)) context_ex->ibv_destroy_flow;
277d6b92ffaSHans Petter Selasky 
278d6b92ffaSHans Petter Selasky 		if (context_ex->create_cq_ex) {
279d6b92ffaSHans Petter Selasky 			priv->create_cq_ex = context_ex->create_cq_ex;
280d6b92ffaSHans Petter Selasky 			context_ex->create_cq_ex = __lib_ibv_create_cq_ex;
281d6b92ffaSHans Petter Selasky 		}
282d6b92ffaSHans Petter Selasky 	}
283d6b92ffaSHans Petter Selasky 
284d6b92ffaSHans Petter Selasky 	context->device = device;
285d6b92ffaSHans Petter Selasky 	context->cmd_fd = cmd_fd;
286d6b92ffaSHans Petter Selasky 
287d6b92ffaSHans Petter Selasky 	return context;
288d6b92ffaSHans Petter Selasky 
289a687910fSSean Lim err_mutex:
290a687910fSSean Lim 	pthread_mutex_destroy(&context->mutex);
291d6b92ffaSHans Petter Selasky verbs_err:
292d6b92ffaSHans Petter Selasky 	free(context_ex->priv);
293a687910fSSean Lim err_context:
294d6b92ffaSHans Petter Selasky 	free(context_ex);
295d6b92ffaSHans Petter Selasky err:
296d6b92ffaSHans Petter Selasky 	close(cmd_fd);
297d6b92ffaSHans Petter Selasky 	return NULL;
298d6b92ffaSHans Petter Selasky }
299d6b92ffaSHans Petter Selasky default_symver(__ibv_open_device, ibv_open_device);
300d6b92ffaSHans Petter Selasky 
__ibv_close_device(struct ibv_context * context)301d6b92ffaSHans Petter Selasky int __ibv_close_device(struct ibv_context *context)
302d6b92ffaSHans Petter Selasky {
303d6b92ffaSHans Petter Selasky 	int async_fd = context->async_fd;
304d6b92ffaSHans Petter Selasky 	int cmd_fd   = context->cmd_fd;
305d6b92ffaSHans Petter Selasky 	struct verbs_context *context_ex;
306d6b92ffaSHans Petter Selasky 	struct verbs_device *verbs_device = verbs_get_device(context->device);
307d6b92ffaSHans Petter Selasky 
308a687910fSSean Lim 	pthread_mutex_destroy(&context->mutex);
309d6b92ffaSHans Petter Selasky 	context_ex = verbs_get_ctx(context);
310d6b92ffaSHans Petter Selasky 	if (context_ex) {
311d6b92ffaSHans Petter Selasky 		verbs_device->ops->uninit_context(verbs_device, context);
312d6b92ffaSHans Petter Selasky 		free(context_ex->priv);
313d6b92ffaSHans Petter Selasky 		free(context_ex);
314d6b92ffaSHans Petter Selasky 	} else {
315d6b92ffaSHans Petter Selasky 		verbs_device->ops->free_context(context);
316d6b92ffaSHans Petter Selasky 	}
317d6b92ffaSHans Petter Selasky 
318d6b92ffaSHans Petter Selasky 	close(async_fd);
319d6b92ffaSHans Petter Selasky 	close(cmd_fd);
320d6b92ffaSHans Petter Selasky 
321d6b92ffaSHans Petter Selasky 	return 0;
322d6b92ffaSHans Petter Selasky }
323d6b92ffaSHans Petter Selasky default_symver(__ibv_close_device, ibv_close_device);
324d6b92ffaSHans Petter Selasky 
__ibv_get_async_event(struct ibv_context * context,struct ibv_async_event * event)325d6b92ffaSHans Petter Selasky int __ibv_get_async_event(struct ibv_context *context,
326d6b92ffaSHans Petter Selasky 			  struct ibv_async_event *event)
327d6b92ffaSHans Petter Selasky {
328d6b92ffaSHans Petter Selasky 	struct ibv_kern_async_event ev;
329d6b92ffaSHans Petter Selasky 
330d6b92ffaSHans Petter Selasky 	if (read(context->async_fd, &ev, sizeof ev) != sizeof ev)
331d6b92ffaSHans Petter Selasky 		return -1;
332d6b92ffaSHans Petter Selasky 
333d6b92ffaSHans Petter Selasky 	event->event_type = ev.event_type;
334d6b92ffaSHans Petter Selasky 
335d6b92ffaSHans Petter Selasky 	switch (event->event_type) {
336d6b92ffaSHans Petter Selasky 	case IBV_EVENT_CQ_ERR:
337d6b92ffaSHans Petter Selasky 		event->element.cq = (void *) (uintptr_t) ev.element;
338d6b92ffaSHans Petter Selasky 		break;
339d6b92ffaSHans Petter Selasky 
340d6b92ffaSHans Petter Selasky 	case IBV_EVENT_QP_FATAL:
341d6b92ffaSHans Petter Selasky 	case IBV_EVENT_QP_REQ_ERR:
342d6b92ffaSHans Petter Selasky 	case IBV_EVENT_QP_ACCESS_ERR:
343d6b92ffaSHans Petter Selasky 	case IBV_EVENT_COMM_EST:
344d6b92ffaSHans Petter Selasky 	case IBV_EVENT_SQ_DRAINED:
345d6b92ffaSHans Petter Selasky 	case IBV_EVENT_PATH_MIG:
346d6b92ffaSHans Petter Selasky 	case IBV_EVENT_PATH_MIG_ERR:
347d6b92ffaSHans Petter Selasky 	case IBV_EVENT_QP_LAST_WQE_REACHED:
348d6b92ffaSHans Petter Selasky 		event->element.qp = (void *) (uintptr_t) ev.element;
349d6b92ffaSHans Petter Selasky 		break;
350d6b92ffaSHans Petter Selasky 
351d6b92ffaSHans Petter Selasky 	case IBV_EVENT_SRQ_ERR:
352d6b92ffaSHans Petter Selasky 	case IBV_EVENT_SRQ_LIMIT_REACHED:
353d6b92ffaSHans Petter Selasky 		event->element.srq = (void *) (uintptr_t) ev.element;
354d6b92ffaSHans Petter Selasky 		break;
355d6b92ffaSHans Petter Selasky 
356d6b92ffaSHans Petter Selasky 	case IBV_EVENT_WQ_FATAL:
357d6b92ffaSHans Petter Selasky 		event->element.wq = (void *) (uintptr_t) ev.element;
358d6b92ffaSHans Petter Selasky 		break;
359d6b92ffaSHans Petter Selasky 	default:
360d6b92ffaSHans Petter Selasky 		event->element.port_num = ev.element;
361d6b92ffaSHans Petter Selasky 		break;
362d6b92ffaSHans Petter Selasky 	}
363d6b92ffaSHans Petter Selasky 
364d6b92ffaSHans Petter Selasky 	if (context->ops.async_event)
365d6b92ffaSHans Petter Selasky 		context->ops.async_event(event);
366d6b92ffaSHans Petter Selasky 
367d6b92ffaSHans Petter Selasky 	return 0;
368d6b92ffaSHans Petter Selasky }
369d6b92ffaSHans Petter Selasky default_symver(__ibv_get_async_event, ibv_get_async_event);
370d6b92ffaSHans Petter Selasky 
__ibv_ack_async_event(struct ibv_async_event * event)371d6b92ffaSHans Petter Selasky void __ibv_ack_async_event(struct ibv_async_event *event)
372d6b92ffaSHans Petter Selasky {
373d6b92ffaSHans Petter Selasky 	switch (event->event_type) {
374d6b92ffaSHans Petter Selasky 	case IBV_EVENT_CQ_ERR:
375d6b92ffaSHans Petter Selasky 	{
376d6b92ffaSHans Petter Selasky 		struct ibv_cq *cq = event->element.cq;
377d6b92ffaSHans Petter Selasky 
378d6b92ffaSHans Petter Selasky 		pthread_mutex_lock(&cq->mutex);
379d6b92ffaSHans Petter Selasky 		++cq->async_events_completed;
380d6b92ffaSHans Petter Selasky 		pthread_cond_signal(&cq->cond);
381d6b92ffaSHans Petter Selasky 		pthread_mutex_unlock(&cq->mutex);
382d6b92ffaSHans Petter Selasky 
383d6b92ffaSHans Petter Selasky 		return;
384d6b92ffaSHans Petter Selasky 	}
385d6b92ffaSHans Petter Selasky 
386d6b92ffaSHans Petter Selasky 	case IBV_EVENT_QP_FATAL:
387d6b92ffaSHans Petter Selasky 	case IBV_EVENT_QP_REQ_ERR:
388d6b92ffaSHans Petter Selasky 	case IBV_EVENT_QP_ACCESS_ERR:
389d6b92ffaSHans Petter Selasky 	case IBV_EVENT_COMM_EST:
390d6b92ffaSHans Petter Selasky 	case IBV_EVENT_SQ_DRAINED:
391d6b92ffaSHans Petter Selasky 	case IBV_EVENT_PATH_MIG:
392d6b92ffaSHans Petter Selasky 	case IBV_EVENT_PATH_MIG_ERR:
393d6b92ffaSHans Petter Selasky 	case IBV_EVENT_QP_LAST_WQE_REACHED:
394d6b92ffaSHans Petter Selasky 	{
395d6b92ffaSHans Petter Selasky 		struct ibv_qp *qp = event->element.qp;
396d6b92ffaSHans Petter Selasky 
397d6b92ffaSHans Petter Selasky 		pthread_mutex_lock(&qp->mutex);
398d6b92ffaSHans Petter Selasky 		++qp->events_completed;
399d6b92ffaSHans Petter Selasky 		pthread_cond_signal(&qp->cond);
400d6b92ffaSHans Petter Selasky 		pthread_mutex_unlock(&qp->mutex);
401d6b92ffaSHans Petter Selasky 
402d6b92ffaSHans Petter Selasky 		return;
403d6b92ffaSHans Petter Selasky 	}
404d6b92ffaSHans Petter Selasky 
405d6b92ffaSHans Petter Selasky 	case IBV_EVENT_SRQ_ERR:
406d6b92ffaSHans Petter Selasky 	case IBV_EVENT_SRQ_LIMIT_REACHED:
407d6b92ffaSHans Petter Selasky 	{
408d6b92ffaSHans Petter Selasky 		struct ibv_srq *srq = event->element.srq;
409d6b92ffaSHans Petter Selasky 
410d6b92ffaSHans Petter Selasky 		pthread_mutex_lock(&srq->mutex);
411d6b92ffaSHans Petter Selasky 		++srq->events_completed;
412d6b92ffaSHans Petter Selasky 		pthread_cond_signal(&srq->cond);
413d6b92ffaSHans Petter Selasky 		pthread_mutex_unlock(&srq->mutex);
414d6b92ffaSHans Petter Selasky 
415d6b92ffaSHans Petter Selasky 		return;
416d6b92ffaSHans Petter Selasky 	}
417d6b92ffaSHans Petter Selasky 
418d6b92ffaSHans Petter Selasky 	case IBV_EVENT_WQ_FATAL:
419d6b92ffaSHans Petter Selasky 	{
420d6b92ffaSHans Petter Selasky 		struct ibv_wq *wq = event->element.wq;
421d6b92ffaSHans Petter Selasky 
422d6b92ffaSHans Petter Selasky 		pthread_mutex_lock(&wq->mutex);
423d6b92ffaSHans Petter Selasky 		++wq->events_completed;
424d6b92ffaSHans Petter Selasky 		pthread_cond_signal(&wq->cond);
425d6b92ffaSHans Petter Selasky 		pthread_mutex_unlock(&wq->mutex);
426d6b92ffaSHans Petter Selasky 
427d6b92ffaSHans Petter Selasky 		return;
428d6b92ffaSHans Petter Selasky 	}
429d6b92ffaSHans Petter Selasky 
430d6b92ffaSHans Petter Selasky 	default:
431d6b92ffaSHans Petter Selasky 		return;
432d6b92ffaSHans Petter Selasky 	}
433d6b92ffaSHans Petter Selasky }
434d6b92ffaSHans Petter Selasky default_symver(__ibv_ack_async_event, ibv_ack_async_event);
435a687910fSSean Lim 
__ibv_init_wq(struct ibv_wq * wq)436a687910fSSean Lim int __ibv_init_wq(struct ibv_wq *wq)
437a687910fSSean Lim {
438a687910fSSean Lim 	int err = 0;
439a687910fSSean Lim 	wq->events_completed = 0;
440a687910fSSean Lim 	err = pthread_mutex_init(&wq->mutex, NULL);
441a687910fSSean Lim 	if (err)
442a687910fSSean Lim 			return err;
443a687910fSSean Lim 
444a687910fSSean Lim 	err = pthread_cond_init(&wq->cond, NULL);
445a687910fSSean Lim 	if (err)
446a687910fSSean Lim 			goto err;
447a687910fSSean Lim 
448a687910fSSean Lim 	return err;
449a687910fSSean Lim 
450a687910fSSean Lim err:
451a687910fSSean Lim 	pthread_mutex_destroy(&wq->mutex);
452a687910fSSean Lim 
453a687910fSSean Lim 	return err;
454a687910fSSean Lim }
455a687910fSSean Lim default_symver(__ibv_init_wq, ibv_init_wq);
456a687910fSSean Lim 
__ibv_cleanup_wq(struct ibv_wq * wq)457a687910fSSean Lim void __ibv_cleanup_wq(struct ibv_wq *wq)
458a687910fSSean Lim {
4598e1f58caSBartosz Sobczak 	pthread_cond_destroy(&wq->cond);
460a687910fSSean Lim 	pthread_mutex_destroy(&wq->mutex);
461a687910fSSean Lim }
462a687910fSSean Lim default_symver(__ibv_cleanup_wq, ibv_cleanup_wq);
463