Merge with rsync://fileserver/linux
[linux-2.6] / drivers / infiniband / core / verbs.c
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.
7  * Copyright (c) 2005 Cisco Systems.  All rights reserved.
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
47 struct ib_pd *ib_alloc_pd(struct ib_device *device)
48 {
49         struct ib_pd *pd;
50
51         pd = device->alloc_pd(device, NULL, NULL);
52
53         if (!IS_ERR(pd)) {
54                 pd->device  = device;
55                 pd->uobject = NULL;
56                 atomic_set(&pd->usecnt, 0);
57         }
58
59         return pd;
60 }
61 EXPORT_SYMBOL(ib_alloc_pd);
62
63 int 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 }
70 EXPORT_SYMBOL(ib_dealloc_pd);
71
72 /* Address handles */
73
74 struct 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)) {
81                 ah->device  = pd->device;
82                 ah->pd      = pd;
83                 ah->uobject = NULL;
84                 atomic_inc(&pd->usecnt);
85         }
86
87         return ah;
88 }
89 EXPORT_SYMBOL(ib_create_ah);
90
91 int 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 }
97 EXPORT_SYMBOL(ib_modify_ah);
98
99 int 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 }
105 EXPORT_SYMBOL(ib_query_ah);
106
107 int 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 }
119 EXPORT_SYMBOL(ib_destroy_ah);
120
121 /* Queue pairs */
122
123 struct 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
128         qp = pd->device->create_qp(pd, qp_init_attr, NULL);
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;
136                 qp->uobject       = NULL;
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 }
149 EXPORT_SYMBOL(ib_create_qp);
150
151 int 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 }
157 EXPORT_SYMBOL(ib_modify_qp);
158
159 int 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 }
168 EXPORT_SYMBOL(ib_query_qp);
169
170 int 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 }
193 EXPORT_SYMBOL(ib_destroy_qp);
194
195 /* Completion queues */
196
197 struct 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
204         cq = device->create_cq(device, cqe, NULL, NULL);
205
206         if (!IS_ERR(cq)) {
207                 cq->device        = device;
208                 cq->uobject       = NULL;
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 }
217 EXPORT_SYMBOL(ib_create_cq);
218
219 int 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 }
226 EXPORT_SYMBOL(ib_destroy_cq);
227
228 int 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 }
242 EXPORT_SYMBOL(ib_resize_cq);
243
244 /* Memory regions */
245
246 struct 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)) {
253                 mr->device  = pd->device;
254                 mr->pd      = pd;
255                 mr->uobject = NULL;
256                 atomic_inc(&pd->usecnt);
257                 atomic_set(&mr->usecnt, 0);
258         }
259
260         return mr;
261 }
262 EXPORT_SYMBOL(ib_get_dma_mr);
263
264 struct 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)) {
276                 mr->device  = pd->device;
277                 mr->pd      = pd;
278                 mr->uobject = NULL;
279                 atomic_inc(&pd->usecnt);
280                 atomic_set(&mr->usecnt, 0);
281         }
282
283         return mr;
284 }
285 EXPORT_SYMBOL(ib_reg_phys_mr);
286
287 int 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 }
317 EXPORT_SYMBOL(ib_rereg_phys_mr);
318
319 int 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 }
324 EXPORT_SYMBOL(ib_query_mr);
325
326 int 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 }
341 EXPORT_SYMBOL(ib_dereg_mr);
342
343 /* Memory windows */
344
345 struct 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)) {
354                 mw->device  = pd->device;
355                 mw->pd      = pd;
356                 mw->uobject = NULL;
357                 atomic_inc(&pd->usecnt);
358         }
359
360         return mw;
361 }
362 EXPORT_SYMBOL(ib_alloc_mw);
363
364 int 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 }
376 EXPORT_SYMBOL(ib_dealloc_mw);
377
378 /* "Fast" memory regions */
379
380 struct 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 }
398 EXPORT_SYMBOL(ib_alloc_fmr);
399
400 int 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 }
410 EXPORT_SYMBOL(ib_unmap_fmr);
411
412 int 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 }
424 EXPORT_SYMBOL(ib_dealloc_fmr);
425
426 /* Multicast groups */
427
428 int 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 }
434 EXPORT_SYMBOL(ib_attach_mcast);
435
436 int 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 }
442 EXPORT_SYMBOL(ib_detach_mcast);