]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/infiniband/core/verbs.c
[PATCH] IB: Fix a couple of MAD code paths
[mirror_ubuntu-bionic-kernel.git] / drivers / infiniband / core / verbs.c
CommitLineData
1da177e4
LT
1/*
2 * Copyright (c) 2004 Mellanox Technologies Ltd. All rights reserved.
3 * Copyright (c) 2004 Infinicon Corporation. All rights reserved.
4 * Copyright (c) 2004 Intel Corporation. All rights reserved.
5 * Copyright (c) 2004 Topspin Corporation. All rights reserved.
6 * Copyright (c) 2004 Voltaire Corporation. All rights reserved.
b5e81bf5 7 * Copyright (c) 2005 Cisco Systems. All rights reserved.
1da177e4
LT
8 *
9 * This software is available to you under a choice of one of two
10 * licenses. You may choose to be licensed under the terms of the GNU
11 * General Public License (GPL) Version 2, available from the file
12 * COPYING in the main directory of this source tree, or the
13 * OpenIB.org BSD license below:
14 *
15 * Redistribution and use in source and binary forms, with or
16 * without modification, are permitted provided that the following
17 * conditions are met:
18 *
19 * - Redistributions of source code must retain the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer.
22 *
23 * - Redistributions in binary form must reproduce the above
24 * copyright notice, this list of conditions and the following
25 * disclaimer in the documentation and/or other materials
26 * provided with the distribution.
27 *
28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
32 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
33 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
34 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35 * SOFTWARE.
36 *
37 * $Id: verbs.c 1349 2004-12-16 21:09:43Z roland $
38 */
39
40#include <linux/errno.h>
41#include <linux/err.h>
42
43#include <ib_verbs.h>
44
45/* Protection domains */
46
47struct ib_pd *ib_alloc_pd(struct ib_device *device)
48{
49 struct ib_pd *pd;
50
b5e81bf5 51 pd = device->alloc_pd(device, NULL, NULL);
1da177e4
LT
52
53 if (!IS_ERR(pd)) {
b5e81bf5
RD
54 pd->device = device;
55 pd->uobject = NULL;
1da177e4
LT
56 atomic_set(&pd->usecnt, 0);
57 }
58
59 return pd;
60}
61EXPORT_SYMBOL(ib_alloc_pd);
62
63int ib_dealloc_pd(struct ib_pd *pd)
64{
65 if (atomic_read(&pd->usecnt))
66 return -EBUSY;
67
68 return pd->device->dealloc_pd(pd);
69}
70EXPORT_SYMBOL(ib_dealloc_pd);
71
72/* Address handles */
73
74struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
75{
76 struct ib_ah *ah;
77
78 ah = pd->device->create_ah(pd, ah_attr);
79
80 if (!IS_ERR(ah)) {
b5e81bf5
RD
81 ah->device = pd->device;
82 ah->pd = pd;
83 ah->uobject = NULL;
1da177e4
LT
84 atomic_inc(&pd->usecnt);
85 }
86
87 return ah;
88}
89EXPORT_SYMBOL(ib_create_ah);
90
91int ib_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr)
92{
93 return ah->device->modify_ah ?
94 ah->device->modify_ah(ah, ah_attr) :
95 -ENOSYS;
96}
97EXPORT_SYMBOL(ib_modify_ah);
98
99int ib_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr)
100{
101 return ah->device->query_ah ?
102 ah->device->query_ah(ah, ah_attr) :
103 -ENOSYS;
104}
105EXPORT_SYMBOL(ib_query_ah);
106
107int ib_destroy_ah(struct ib_ah *ah)
108{
109 struct ib_pd *pd;
110 int ret;
111
112 pd = ah->pd;
113 ret = ah->device->destroy_ah(ah);
114 if (!ret)
115 atomic_dec(&pd->usecnt);
116
117 return ret;
118}
119EXPORT_SYMBOL(ib_destroy_ah);
120
121/* Queue pairs */
122
123struct ib_qp *ib_create_qp(struct ib_pd *pd,
124 struct ib_qp_init_attr *qp_init_attr)
125{
126 struct ib_qp *qp;
127
b5e81bf5 128 qp = pd->device->create_qp(pd, qp_init_attr, NULL);
1da177e4
LT
129
130 if (!IS_ERR(qp)) {
131 qp->device = pd->device;
132 qp->pd = pd;
133 qp->send_cq = qp_init_attr->send_cq;
134 qp->recv_cq = qp_init_attr->recv_cq;
135 qp->srq = qp_init_attr->srq;
b5e81bf5 136 qp->uobject = NULL;
1da177e4
LT
137 qp->event_handler = qp_init_attr->event_handler;
138 qp->qp_context = qp_init_attr->qp_context;
139 qp->qp_type = qp_init_attr->qp_type;
140 atomic_inc(&pd->usecnt);
141 atomic_inc(&qp_init_attr->send_cq->usecnt);
142 atomic_inc(&qp_init_attr->recv_cq->usecnt);
143 if (qp_init_attr->srq)
144 atomic_inc(&qp_init_attr->srq->usecnt);
145 }
146
147 return qp;
148}
149EXPORT_SYMBOL(ib_create_qp);
150
151int ib_modify_qp(struct ib_qp *qp,
152 struct ib_qp_attr *qp_attr,
153 int qp_attr_mask)
154{
155 return qp->device->modify_qp(qp, qp_attr, qp_attr_mask);
156}
157EXPORT_SYMBOL(ib_modify_qp);
158
159int ib_query_qp(struct ib_qp *qp,
160 struct ib_qp_attr *qp_attr,
161 int qp_attr_mask,
162 struct ib_qp_init_attr *qp_init_attr)
163{
164 return qp->device->query_qp ?
165 qp->device->query_qp(qp, qp_attr, qp_attr_mask, qp_init_attr) :
166 -ENOSYS;
167}
168EXPORT_SYMBOL(ib_query_qp);
169
170int ib_destroy_qp(struct ib_qp *qp)
171{
172 struct ib_pd *pd;
173 struct ib_cq *scq, *rcq;
174 struct ib_srq *srq;
175 int ret;
176
177 pd = qp->pd;
178 scq = qp->send_cq;
179 rcq = qp->recv_cq;
180 srq = qp->srq;
181
182 ret = qp->device->destroy_qp(qp);
183 if (!ret) {
184 atomic_dec(&pd->usecnt);
185 atomic_dec(&scq->usecnt);
186 atomic_dec(&rcq->usecnt);
187 if (srq)
188 atomic_dec(&srq->usecnt);
189 }
190
191 return ret;
192}
193EXPORT_SYMBOL(ib_destroy_qp);
194
195/* Completion queues */
196
197struct ib_cq *ib_create_cq(struct ib_device *device,
198 ib_comp_handler comp_handler,
199 void (*event_handler)(struct ib_event *, void *),
200 void *cq_context, int cqe)
201{
202 struct ib_cq *cq;
203
b5e81bf5 204 cq = device->create_cq(device, cqe, NULL, NULL);
1da177e4
LT
205
206 if (!IS_ERR(cq)) {
207 cq->device = device;
b5e81bf5 208 cq->uobject = NULL;
1da177e4
LT
209 cq->comp_handler = comp_handler;
210 cq->event_handler = event_handler;
211 cq->cq_context = cq_context;
212 atomic_set(&cq->usecnt, 0);
213 }
214
215 return cq;
216}
217EXPORT_SYMBOL(ib_create_cq);
218
219int ib_destroy_cq(struct ib_cq *cq)
220{
221 if (atomic_read(&cq->usecnt))
222 return -EBUSY;
223
224 return cq->device->destroy_cq(cq);
225}
226EXPORT_SYMBOL(ib_destroy_cq);
227
228int ib_resize_cq(struct ib_cq *cq,
229 int cqe)
230{
231 int ret;
232
233 if (!cq->device->resize_cq)
234 return -ENOSYS;
235
236 ret = cq->device->resize_cq(cq, &cqe);
237 if (!ret)
238 cq->cqe = cqe;
239
240 return ret;
241}
242EXPORT_SYMBOL(ib_resize_cq);
243
244/* Memory regions */
245
246struct ib_mr *ib_get_dma_mr(struct ib_pd *pd, int mr_access_flags)
247{
248 struct ib_mr *mr;
249
250 mr = pd->device->get_dma_mr(pd, mr_access_flags);
251
252 if (!IS_ERR(mr)) {
b5e81bf5
RD
253 mr->device = pd->device;
254 mr->pd = pd;
255 mr->uobject = NULL;
1da177e4
LT
256 atomic_inc(&pd->usecnt);
257 atomic_set(&mr->usecnt, 0);
258 }
259
260 return mr;
261}
262EXPORT_SYMBOL(ib_get_dma_mr);
263
264struct ib_mr *ib_reg_phys_mr(struct ib_pd *pd,
265 struct ib_phys_buf *phys_buf_array,
266 int num_phys_buf,
267 int mr_access_flags,
268 u64 *iova_start)
269{
270 struct ib_mr *mr;
271
272 mr = pd->device->reg_phys_mr(pd, phys_buf_array, num_phys_buf,
273 mr_access_flags, iova_start);
274
275 if (!IS_ERR(mr)) {
b5e81bf5
RD
276 mr->device = pd->device;
277 mr->pd = pd;
278 mr->uobject = NULL;
1da177e4
LT
279 atomic_inc(&pd->usecnt);
280 atomic_set(&mr->usecnt, 0);
281 }
282
283 return mr;
284}
285EXPORT_SYMBOL(ib_reg_phys_mr);
286
287int ib_rereg_phys_mr(struct ib_mr *mr,
288 int mr_rereg_mask,
289 struct ib_pd *pd,
290 struct ib_phys_buf *phys_buf_array,
291 int num_phys_buf,
292 int mr_access_flags,
293 u64 *iova_start)
294{
295 struct ib_pd *old_pd;
296 int ret;
297
298 if (!mr->device->rereg_phys_mr)
299 return -ENOSYS;
300
301 if (atomic_read(&mr->usecnt))
302 return -EBUSY;
303
304 old_pd = mr->pd;
305
306 ret = mr->device->rereg_phys_mr(mr, mr_rereg_mask, pd,
307 phys_buf_array, num_phys_buf,
308 mr_access_flags, iova_start);
309
310 if (!ret && (mr_rereg_mask & IB_MR_REREG_PD)) {
311 atomic_dec(&old_pd->usecnt);
312 atomic_inc(&pd->usecnt);
313 }
314
315 return ret;
316}
317EXPORT_SYMBOL(ib_rereg_phys_mr);
318
319int ib_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr)
320{
321 return mr->device->query_mr ?
322 mr->device->query_mr(mr, mr_attr) : -ENOSYS;
323}
324EXPORT_SYMBOL(ib_query_mr);
325
326int ib_dereg_mr(struct ib_mr *mr)
327{
328 struct ib_pd *pd;
329 int ret;
330
331 if (atomic_read(&mr->usecnt))
332 return -EBUSY;
333
334 pd = mr->pd;
335 ret = mr->device->dereg_mr(mr);
336 if (!ret)
337 atomic_dec(&pd->usecnt);
338
339 return ret;
340}
341EXPORT_SYMBOL(ib_dereg_mr);
342
343/* Memory windows */
344
345struct ib_mw *ib_alloc_mw(struct ib_pd *pd)
346{
347 struct ib_mw *mw;
348
349 if (!pd->device->alloc_mw)
350 return ERR_PTR(-ENOSYS);
351
352 mw = pd->device->alloc_mw(pd);
353 if (!IS_ERR(mw)) {
b5e81bf5
RD
354 mw->device = pd->device;
355 mw->pd = pd;
356 mw->uobject = NULL;
1da177e4
LT
357 atomic_inc(&pd->usecnt);
358 }
359
360 return mw;
361}
362EXPORT_SYMBOL(ib_alloc_mw);
363
364int ib_dealloc_mw(struct ib_mw *mw)
365{
366 struct ib_pd *pd;
367 int ret;
368
369 pd = mw->pd;
370 ret = mw->device->dealloc_mw(mw);
371 if (!ret)
372 atomic_dec(&pd->usecnt);
373
374 return ret;
375}
376EXPORT_SYMBOL(ib_dealloc_mw);
377
378/* "Fast" memory regions */
379
380struct ib_fmr *ib_alloc_fmr(struct ib_pd *pd,
381 int mr_access_flags,
382 struct ib_fmr_attr *fmr_attr)
383{
384 struct ib_fmr *fmr;
385
386 if (!pd->device->alloc_fmr)
387 return ERR_PTR(-ENOSYS);
388
389 fmr = pd->device->alloc_fmr(pd, mr_access_flags, fmr_attr);
390 if (!IS_ERR(fmr)) {
391 fmr->device = pd->device;
392 fmr->pd = pd;
393 atomic_inc(&pd->usecnt);
394 }
395
396 return fmr;
397}
398EXPORT_SYMBOL(ib_alloc_fmr);
399
400int ib_unmap_fmr(struct list_head *fmr_list)
401{
402 struct ib_fmr *fmr;
403
404 if (list_empty(fmr_list))
405 return 0;
406
407 fmr = list_entry(fmr_list->next, struct ib_fmr, list);
408 return fmr->device->unmap_fmr(fmr_list);
409}
410EXPORT_SYMBOL(ib_unmap_fmr);
411
412int ib_dealloc_fmr(struct ib_fmr *fmr)
413{
414 struct ib_pd *pd;
415 int ret;
416
417 pd = fmr->pd;
418 ret = fmr->device->dealloc_fmr(fmr);
419 if (!ret)
420 atomic_dec(&pd->usecnt);
421
422 return ret;
423}
424EXPORT_SYMBOL(ib_dealloc_fmr);
425
426/* Multicast groups */
427
428int ib_attach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid)
429{
430 return qp->device->attach_mcast ?
431 qp->device->attach_mcast(qp, gid, lid) :
432 -ENOSYS;
433}
434EXPORT_SYMBOL(ib_attach_mcast);
435
436int ib_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid)
437{
438 return qp->device->detach_mcast ?
439 qp->device->detach_mcast(qp, gid, lid) :
440 -ENOSYS;
441}
442EXPORT_SYMBOL(ib_detach_mcast);