7f150595a849be03776c900a5e875aa14a2f897d
[mirror/winof/.git] / hw / mthca / kernel / mt_verbs.c
1 /*\r
2  * Copyright (c) 2004 Mellanox Technologies Ltd.  All rights reserved.\r
3  * Copyright (c) 2004 Infinicon Corporation.  All rights reserved.\r
4  * Copyright (c) 2004 Intel Corporation.  All rights reserved.\r
5  * Copyright (c) 2004 Topspin Corporation.  All rights reserved.\r
6  * Copyright (c) 2004 Voltaire Corporation.  All rights reserved.\r
7  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.\r
8  * Copyright (c) 2005 Cisco Systems.  All rights reserved.\r
9  * Portions Copyright (c) 2008 Microsoft Corporation.  All rights reserved.\r
10  *\r
11  * This software is available to you under the OpenIB.org BSD license\r
12  * below:\r
13  *\r
14  *     Redistribution and use in source and binary forms, with or\r
15  *     without modification, are permitted provided that the following\r
16  *     conditions are met:\r
17  *\r
18  *      - Redistributions of source code must retain the above\r
19  *        copyright notice, this list of conditions and the following\r
20  *        disclaimer.\r
21  *\r
22  *      - Redistributions in binary form must reproduce the above\r
23  *        copyright notice, this list of conditions and the following\r
24  *        disclaimer in the documentation and/or other materials\r
25  *        provided with the distribution.\r
26  *\r
27  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
28  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
29  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
30  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
31  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
32  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
33  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
34  * SOFTWARE.\r
35  *\r
36  * $Id$\r
37  */\r
38 \r
39 #include <ib_verbs.h>\r
40 #include <ib_cache.h>\r
41 #include "mthca_dev.h"\r
42 #include "mx_abi.h"\r
43 \r
44 #if defined(EVENT_TRACING)\r
45 #ifdef offsetof\r
46 #undef offsetof\r
47 #endif\r
48 #include "mt_verbs.tmh"\r
49 #endif\r
50 \r
51 \r
52 void ibv_um_close(      struct ib_ucontext * h_um_ca )\r
53 {\r
54         int err;\r
55         ib_api_status_t         status;\r
56         struct ib_ucontext *context_p = (struct ib_ucontext *)h_um_ca;\r
57 \r
58         HCA_ENTER(HCA_DBG_SHIM);\r
59 \r
60         context_p->is_removing = TRUE;\r
61 \r
62         if (atomic_read(&context_p->usecnt)) {\r
63                 HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_SHIM,\r
64                         ("resources are not released (cnt %d)\n", context_p->usecnt));\r
65                 status = IB_RESOURCE_BUSY;\r
66                 goto err_usage;\r
67         }\r
68         \r
69         err = ibv_dealloc_pd( context_p->pd );\r
70         if (err) {\r
71                 HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_SHIM,\r
72                         ("ibv_dealloc_pd failed (%d)\n", err));\r
73                 status = errno_to_iberr(err);\r
74         }\r
75 \r
76         err = mthca_dealloc_ucontext(context_p);\r
77         if (err) {\r
78                 HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_SHIM,\r
79                         ("mthca_dealloc_ucontext failed (%d)\n", err));\r
80                 status = errno_to_iberr(err);\r
81                 goto err_dealloc_ucontext;\r
82         }\r
83 \r
84         HCA_PRINT(TRACE_LEVEL_INFORMATION,HCA_DBG_SHIM,\r
85                 ("pcs %p\n", PsGetCurrentProcess()) );\r
86         status = IB_SUCCESS;\r
87         goto end;\r
88         \r
89 err_dealloc_ucontext: \r
90 err_usage:\r
91 end:\r
92         if (status != IB_SUCCESS)\r
93         {\r
94                 HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_SHIM,\r
95                         ("completes with ERROR status %x\n", status));\r
96         }\r
97         HCA_EXIT(HCA_DBG_SHIM);\r
98         return;\r
99 }\r
100 \r
101 /* Protection domains */\r
102 \r
103 struct ib_pd *ibv_alloc_pd(struct ib_device *device,\r
104         struct ib_ucontext *context, ci_umv_buf_t* const p_umv_buf)\r
105 {\r
106         struct ib_pd *pd;\r
107 \r
108         // direct call is a must, because "lifefish" devices doesn't fill driver i/f table\r
109         pd = mthca_alloc_pd(device, context, p_umv_buf);\r
110 \r
111         if (!IS_ERR(pd)) {\r
112                 pd->device  = device;\r
113                 pd->ucontext = context;\r
114                 atomic_set(&pd->usecnt, 0);\r
115                 KeInitializeMutex( &pd->mutex, 0 );\r
116                 INIT_LIST_HEAD( &pd->list );\r
117                 HCA_PRINT(TRACE_LEVEL_INFORMATION ,HCA_DBG_CQ ,("PD%d use cnt %d, pd_handle %p, ctx %p \n", \r
118                         ((struct mthca_pd*)pd)->pd_num, pd->usecnt, pd, pd->ucontext));\r
119         }\r
120 \r
121         return pd;\r
122 }\r
123 \r
124 int ibv_dealloc_pd(struct ib_pd *pd)\r
125 {\r
126         if (mthca_is_livefish(to_mdev(pd->device))) \r
127                 goto done;\r
128 \r
129         // we need first to release list of AV MRs to decrease pd->usecnt\r
130         if (pd->ucontext) {\r
131                 struct ib_mr *ib_mr, *tmp;\r
132                 down(&pd->mutex );\r
133                 list_for_each_entry_safe(ib_mr, tmp, &pd->list, list,struct ib_mr,struct ib_mr) {\r
134                         ibv_dereg_mr( ib_mr );\r
135                 }\r
136                 up(&pd->mutex );\r
137         }\r
138 \r
139         if (atomic_read(&pd->usecnt)) {\r
140                 HCA_PRINT(TRACE_LEVEL_ERROR ,HCA_DBG_CQ,("resources are not released (cnt %d)\n", pd->usecnt));\r
141                 return -EBUSY;\r
142         }               \r
143 \r
144 done:\r
145         HCA_PRINT(TRACE_LEVEL_INFORMATION ,HCA_DBG_CQ ,("PD%d use cnt %d, pd_handle %p, ctx %p \n", \r
146                 ((struct mthca_pd*)pd)->pd_num, pd->usecnt, pd, pd->ucontext));\r
147         // direct call is a must, because "lifefish" devices doesn't fill driver i/f table\r
148         return mthca_dealloc_pd(pd);\r
149 }\r
150 \r
151 /* Address handles */\r
152 \r
153 struct ib_ah *ibv_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr,\r
154         struct ib_ucontext *context, ci_umv_buf_t* const p_umv_buf)\r
155 {\r
156         int err;\r
157         struct ib_ah *ah;\r
158         struct ib_mr *ib_mr = NULL;\r
159         u64 start = 0;\r
160         u64 user_handle = 0;\r
161         struct ibv_create_ah_resp *create_ah_resp = 0;\r
162 \r
163         // for user call we need also allocate MR\r
164         if (context && p_umv_buf && p_umv_buf->p_inout_buf) {\r
165                 struct ibv_create_ah *create_ah = (struct ibv_create_ah *)(void*)p_umv_buf->p_inout_buf;\r
166                 \r
167                 // create region; destroy will be done on dealloc_pd\r
168                 ib_mr   = ibv_reg_mr( \r
169                         pd, \r
170                         create_ah->mr.access_flags, \r
171                         (void*)(ULONG_PTR)create_ah->mr.start,\r
172                         create_ah->mr.length, create_ah->mr.hca_va, TRUE, FALSE );\r
173                 if (IS_ERR(ib_mr)) {\r
174                         err = PTR_ERR(ib_mr);\r
175                         HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_AV  ,("ibv_reg_mr failed (%d)\n", err));\r
176                         goto err_alloc_mr;\r
177                 }\r
178 \r
179                 start = create_ah->mr.start;\r
180                 user_handle = create_ah->user_handle;\r
181 \r
182                 // chain this MR to PD list\r
183                 down(&pd->mutex );\r
184                 list_add_tail(&ib_mr->list, &pd->list);\r
185                 up(&pd->mutex );\r
186         }\r
187 \r
188         ah = pd->device->create_ah(pd, ah_attr);\r
189 \r
190         /* fill obligatory fields */\r
191         if (context && p_umv_buf && p_umv_buf->p_inout_buf) {\r
192                 create_ah_resp = (struct ibv_create_ah_resp *)(void*)p_umv_buf->p_inout_buf;\r
193                 create_ah_resp->user_handle = user_handle;\r
194         }\r
195 \r
196         if (IS_ERR(ah)) {\r
197                 err = PTR_ERR(ah);\r
198                 HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_AV ,("create_ah failed (%d)\n", err));\r
199                 goto err_create_ah;\r
200         }\r
201 \r
202         // fill results\r
203         ah->device  = pd->device;\r
204         ah->pd      = pd;\r
205         ah->ucontext = context;\r
206         atomic_inc(&pd->usecnt);\r
207         HCA_PRINT(TRACE_LEVEL_INFORMATION  ,HCA_DBG_AV  ,("PD%d use cnt %d, pd_handle %p, ctx %p \n", \r
208                 ((struct mthca_pd*)pd)->pd_num, pd->usecnt, pd, pd->ucontext));\r
209 \r
210         // fill results for user\r
211         if (context && p_umv_buf && p_umv_buf->p_inout_buf) {\r
212                 struct ibv_create_ah_resp *create_ah_resp = (struct ibv_create_ah_resp *)(void*)p_umv_buf->p_inout_buf;\r
213                 create_ah_resp->start = start;\r
214                 create_ah_resp->mr.lkey = ib_mr->lkey;\r
215                 create_ah_resp->mr.rkey = ib_mr->rkey;\r
216                 create_ah_resp->mr.mr_handle = (u64)(ULONG_PTR)ib_mr;\r
217                 p_umv_buf->output_size = sizeof(struct ibv_create_ah_resp);\r
218         }\r
219 \r
220         return ah;\r
221         \r
222 err_create_ah:\r
223         if (ib_mr)\r
224                 ibv_dereg_mr(ib_mr);\r
225 err_alloc_mr:\r
226         if( p_umv_buf && p_umv_buf->command ) \r
227                 p_umv_buf->status = IB_ERROR;\r
228         return ERR_PTR(ib_mr);\r
229 }\r
230 \r
231 struct ib_ah *ibv_create_ah_from_wc(struct ib_pd *pd, struct _ib_wc *wc,\r
232                                    struct ib_grh *grh, u8 port_num)\r
233 {\r
234         struct ib_ah_attr ah_attr;\r
235         u32 flow_class;\r
236         u16 gid_index;\r
237         int ret;\r
238 \r
239         memset(&ah_attr, 0, sizeof ah_attr);\r
240         ah_attr.dlid = wc->recv.ud.remote_lid;\r
241         ah_attr.sl = wc->recv.ud.remote_sl;\r
242         ah_attr.src_path_bits = wc->recv.ud.path_bits;\r
243         ah_attr.port_num = port_num;\r
244 \r
245         if (wc->recv.ud.recv_opt & IB_RECV_OPT_GRH_VALID) {\r
246                 ah_attr.ah_flags = IB_AH_GRH;\r
247                 ah_attr.grh.dgid = grh->dgid;\r
248 \r
249                 ret = ib_find_cached_gid(pd->device, &grh->sgid, &port_num,\r
250                                          &gid_index);\r
251                 if (ret)\r
252                         return ERR_PTR(ret);\r
253 \r
254                 ah_attr.grh.sgid_index = (u8) gid_index;\r
255                 flow_class = cl_ntoh32(grh->version_tclass_flow);\r
256                 ah_attr.grh.flow_label = flow_class & 0xFFFFF;\r
257                 ah_attr.grh.traffic_class = (u8)((flow_class >> 20) & 0xFF);\r
258                 ah_attr.grh.hop_limit = grh->hop_limit;\r
259         }\r
260 \r
261         return ibv_create_ah(pd, &ah_attr, NULL, NULL);\r
262 }\r
263 \r
264 int ibv_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr)\r
265 {\r
266         return ah->device->modify_ah ?\r
267                 ah->device->modify_ah(ah, ah_attr) :\r
268                 -ENOSYS;\r
269 }\r
270 \r
271 int ibv_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr)\r
272 {\r
273         return ah->device->query_ah ?\r
274                 ah->device->query_ah(ah, ah_attr) :\r
275                 -ENOSYS;\r
276 }\r
277 \r
278 \r
279 static void release_user_cq_qp_resources(\r
280         struct ib_ucontext      *ucontext,\r
281         struct ib_mr * ib_mr)\r
282 {\r
283         if (ucontext) {\r
284                 ibv_dereg_mr( ib_mr );\r
285                 atomic_dec(&ucontext->usecnt);\r
286                 if (!atomic_read(&ucontext->usecnt) && ucontext->is_removing) {\r
287                         HCA_PRINT(TRACE_LEVEL_ERROR  ,HCA_DBG_SHIM      ,("User resources are released. Removing context\n"));\r
288                         ibv_um_close(ucontext);\r
289                 }\r
290         }\r
291 }\r
292 \r
293 int ibv_destroy_ah(struct ib_ah *ah)\r
294 {\r
295         struct ib_pd *pd;\r
296         int ret;\r
297 \r
298         HCA_ENTER(HCA_DBG_AV);\r
299         pd = ah->pd;\r
300 \r
301         ret = ah->device->destroy_ah(ah);\r
302         if (!ret) {\r
303                 atomic_dec(&pd->usecnt);\r
304                 HCA_PRINT(TRACE_LEVEL_INFORMATION  ,HCA_DBG_AV  ,("PD%d use cnt %d, pd_handle %p, ctx %p \n", \r
305                         ((struct mthca_pd*)pd)->pd_num, pd->usecnt, pd, pd->ucontext));\r
306         }\r
307         HCA_EXIT(HCA_DBG_AV);\r
308         return ret;\r
309 }\r
310 \r
311 /* Shared receive queues */\r
312 \r
313 struct ib_srq *ibv_create_srq(struct ib_pd *pd,\r
314         struct ib_srq_init_attr *srq_init_attr,\r
315         struct ib_ucontext *context, ci_umv_buf_t* const p_umv_buf)\r
316 {\r
317         int err;\r
318         struct ib_srq *ib_srq;\r
319         struct ib_mr *ib_mr = NULL;\r
320         u64 user_handle = 0;\r
321         struct ibv_create_srq_resp *create_srq_resp = 0;\r
322 \r
323         // for user call we need also allocate MR\r
324         if (context && p_umv_buf && p_umv_buf->p_inout_buf) {\r
325                 struct ibv_create_srq *create_srp = (struct ibv_create_srq *)(void*)p_umv_buf->p_inout_buf;\r
326                 \r
327                 // create region\r
328                 ib_mr = ibv_reg_mr( \r
329                         (struct ib_pd *)(ULONG_PTR)create_srp->mr.pd_handle, \r
330                         create_srp->mr.access_flags, \r
331                         (void*)(ULONG_PTR)create_srp->mr.start,\r
332                         create_srp->mr.length, create_srp->mr.hca_va, TRUE, FALSE );\r
333                 if (IS_ERR(ib_mr)) {\r
334                         err = PTR_ERR(ib_mr);\r
335                         HCA_PRINT(TRACE_LEVEL_ERROR ,HCA_DBG_QP ,("ibv_reg_mr failed (%d)\n", err));\r
336                         goto err_alloc_mr;\r
337                 }\r
338                 create_srp->lkey = ib_mr->lkey;\r
339                 user_handle = create_srp->user_handle;\r
340         }\r
341 \r
342         ib_srq = pd->device->create_srq(pd, srq_init_attr, p_umv_buf);\r
343 \r
344         /* fill obligatory fields */\r
345         if (context && p_umv_buf && p_umv_buf->p_inout_buf) {\r
346                 create_srq_resp = (struct ibv_create_srq_resp *)(void*)p_umv_buf->p_inout_buf;\r
347                 create_srq_resp->user_handle = user_handle;\r
348         }\r
349 \r
350         if (IS_ERR(ib_srq)) {\r
351                 err = PTR_ERR(ib_srq);\r
352                 HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_QP ,("create_srq failed (%d)\n", err));\r
353                 goto err_create_srq;\r
354         }\r
355 \r
356         // fill results\r
357         ib_srq->device                          = pd->device;\r
358         ib_srq->pd                              = pd;\r
359         ib_srq->ucontext                        = context;\r
360         ib_srq->event_handler           = srq_init_attr->event_handler;\r
361         ib_srq->srq_context             = srq_init_attr->srq_context;\r
362         atomic_inc(&pd->usecnt);\r
363         atomic_set(&ib_srq->usecnt, 0);\r
364         if (context)\r
365                 atomic_inc(&context->usecnt);\r
366                 HCA_PRINT(TRACE_LEVEL_INFORMATION ,HCA_DBG_QP ,("PD%d use cnt %d, pd_handle %p, ctx %p \n", \r
367                         ((struct mthca_pd*)pd)->pd_num, pd->usecnt, pd, pd->ucontext));\r
368 \r
369         HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_SRQ ,\r
370                 ("uctx %p, qhndl %p, qnum %#x \n", \r
371                 pd->ucontext, ib_srq, ((struct mthca_srq*)ib_srq)->srqn ) );\r
372 \r
373         // fill results for user\r
374         if (context && p_umv_buf && p_umv_buf->p_inout_buf) {\r
375                 struct mthca_srq *srq = (struct mthca_srq *)ib_srq;\r
376                 ib_srq->ib_mr = ib_mr;\r
377                 create_srq_resp->mr.lkey = ib_mr->lkey;\r
378                 create_srq_resp->mr.rkey = ib_mr->rkey;\r
379                 create_srq_resp->mr.mr_handle = (u64)(ULONG_PTR)ib_mr;\r
380                 create_srq_resp->srq_handle = (__u64)(ULONG_PTR)srq;\r
381                 create_srq_resp->max_wr = (mthca_is_memfree(to_mdev(pd->device))) ? srq->max - 1 : srq->max;\r
382                 create_srq_resp->max_sge = srq->max_gs;\r
383                 create_srq_resp->srqn= srq->srqn;\r
384                 p_umv_buf->output_size = sizeof(struct ibv_create_srq_resp);\r
385                 HCA_PRINT(TRACE_LEVEL_INFORMATION ,HCA_DBG_QP ,("PD%d use cnt %d \n", \r
386                         ((struct mthca_pd*)pd)->pd_num, pd->usecnt));\r
387         }\r
388 \r
389         return ib_srq;\r
390         \r
391 err_create_srq:\r
392         if (ib_mr)\r
393                 ibv_dereg_mr(ib_mr);\r
394 err_alloc_mr:\r
395         if( p_umv_buf && p_umv_buf->command ) \r
396                 p_umv_buf->status = IB_ERROR;\r
397         HCA_EXIT(HCA_DBG_QP);\r
398         return ERR_PTR(err);\r
399 }\r
400 \r
401 int ibv_modify_srq(struct ib_srq *srq,\r
402         ib_srq_attr_t *srq_attr,\r
403         ib_srq_attr_mask_t srq_attr_mask)\r
404 {\r
405         return srq->device->modify_srq(srq, srq_attr, srq_attr_mask);\r
406 }\r
407 \r
408 int ibv_query_srq(struct ib_srq *srq,\r
409         ib_srq_attr_t *srq_attr)\r
410 {\r
411         return srq->device->query_srq(srq, srq_attr);\r
412 }\r
413 \r
414 int ibv_destroy_srq(struct ib_srq *srq)\r
415 {\r
416         int ret;\r
417         struct ib_pd *pd = srq->pd;\r
418         struct ib_ucontext      *ucontext = pd->ucontext;\r
419         struct ib_mr * ib_mr = srq->ib_mr;\r
420 \r
421         ret = srq->device->destroy_srq(srq);\r
422         if (!ret) {\r
423                 atomic_dec(&pd->usecnt);\r
424                 HCA_PRINT(TRACE_LEVEL_INFORMATION  ,HCA_DBG_SRQ ,("PD%d use cnt %d, pd_handle %p, ctx %p \n", \r
425                         ((struct mthca_pd*)pd)->pd_num, pd->usecnt, pd, pd->ucontext));\r
426                 release_user_cq_qp_resources(ucontext, ib_mr);\r
427         }\r
428 \r
429         return ret;\r
430 }\r
431 \r
432 /* Queue pairs */\r
433 \r
434 struct ib_qp *ibv_create_qp(struct ib_pd *pd,\r
435         struct ib_qp_init_attr *qp_init_attr,\r
436         struct ib_ucontext *context, ci_umv_buf_t* const p_umv_buf)\r
437 {\r
438         int err;\r
439         struct ib_qp *ib_qp;\r
440         struct ib_mr *ib_mr = NULL;\r
441         u64 user_handle = 0;\r
442 \r
443         HCA_ENTER(HCA_DBG_QP);\r
444 \r
445         // for user call we need also allocate MR\r
446         if (context && p_umv_buf && p_umv_buf->p_inout_buf) {\r
447                 struct ibv_create_qp *create_qp = (struct ibv_create_qp *)(void*)p_umv_buf->p_inout_buf;\r
448                 \r
449                 // create region\r
450                 ib_mr   = ibv_reg_mr( \r
451                         (struct ib_pd *)(ULONG_PTR)create_qp->mr.pd_handle, \r
452                         create_qp->mr.access_flags, \r
453                         (void*)(ULONG_PTR)create_qp->mr.start,\r
454                         create_qp->mr.length, create_qp->mr.hca_va, TRUE, FALSE );\r
455                 if (IS_ERR(ib_mr)) {\r
456                         err = PTR_ERR(ib_mr);\r
457                         HCA_PRINT(TRACE_LEVEL_ERROR ,HCA_DBG_QP ,("ibv_reg_mr failed (%d)\n", err));\r
458                         goto err_alloc_mr;\r
459                 }\r
460                 create_qp->lkey = ib_mr->lkey;\r
461                 user_handle = create_qp->user_handle;\r
462         }\r
463 \r
464         ib_qp = pd->device->create_qp(pd, qp_init_attr, p_umv_buf);\r
465 \r
466         if (IS_ERR(ib_qp)) {\r
467                 err = PTR_ERR(ib_qp);\r
468                 HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_QP ,("create_qp failed (%d)\n", err));\r
469                 goto err_create_qp;\r
470         }\r
471 \r
472         // fill results\r
473         ib_qp->device                           = pd->device;\r
474         ib_qp->pd                                       = pd;\r
475         ib_qp->send_cq                          = qp_init_attr->send_cq;\r
476         ib_qp->recv_cq                          = qp_init_attr->recv_cq;\r
477         ib_qp->srq                              = qp_init_attr->srq;\r
478         ib_qp->ucontext                         = context;\r
479         ib_qp->event_handler    = qp_init_attr->event_handler;\r
480         ib_qp->qp_context       = qp_init_attr->qp_context;\r
481         ib_qp->qp_type                          = qp_init_attr->qp_type;\r
482         atomic_inc(&pd->usecnt);\r
483         atomic_inc(&qp_init_attr->send_cq->usecnt);\r
484         atomic_inc(&qp_init_attr->recv_cq->usecnt);\r
485         if (qp_init_attr->srq)\r
486                 atomic_inc(&qp_init_attr->srq->usecnt);\r
487         if (context)\r
488                 atomic_inc(&context->usecnt);\r
489                 HCA_PRINT(TRACE_LEVEL_INFORMATION ,HCA_DBG_QP ,("PD%d use cnt %d, pd_handle %p, ctx %p \n", \r
490                         ((struct mthca_pd*)pd)->pd_num, pd->usecnt, pd, pd->ucontext));\r
491 \r
492         HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_QP ,\r
493                 ("uctx %p, qhndl %p, qnum %#x, q_num  %#x, scq %#x:%#x, rcq %#x:%#x \n",\r
494                 pd->ucontext, ib_qp, ((struct mthca_qp*)ib_qp)->qpn, ib_qp->qp_num,\r
495                 ((struct mthca_cq*)ib_qp->send_cq)->cqn, ib_qp->send_cq->cqe,\r
496                 ((struct mthca_cq*)ib_qp->recv_cq)->cqn, ib_qp->recv_cq->cqe ) );\r
497 \r
498         // fill results for user\r
499         if (context && p_umv_buf && p_umv_buf->p_inout_buf) {\r
500                 struct mthca_qp *qp = (struct mthca_qp *)ib_qp;\r
501                 struct ibv_create_qp_resp *create_qp_resp = (struct ibv_create_qp_resp *)(void*)p_umv_buf->p_inout_buf;\r
502                 ib_qp->ib_mr = ib_mr;\r
503                 create_qp_resp->qpn = ib_qp->qp_num;\r
504                 create_qp_resp->user_handle = user_handle;\r
505                 create_qp_resp->mr.lkey = ib_mr->lkey;\r
506                 create_qp_resp->mr.rkey = ib_mr->rkey;\r
507                 create_qp_resp->mr.mr_handle = (u64)(ULONG_PTR)ib_mr;\r
508                 create_qp_resp->qp_handle = (__u64)(ULONG_PTR)qp;\r
509                 create_qp_resp->max_send_wr = qp->sq.max;\r
510                 create_qp_resp->max_recv_wr = qp->rq.max;\r
511                 create_qp_resp->max_send_sge = qp->sq.max_gs;\r
512                 create_qp_resp->max_recv_sge = qp->rq.max_gs;\r
513                 create_qp_resp->max_inline_data = qp->max_inline_data;\r
514                 p_umv_buf->output_size = sizeof(struct ibv_create_qp_resp);\r
515         }\r
516 \r
517         return ib_qp;\r
518 \r
519 err_create_qp:\r
520         if (ib_mr)\r
521                 ibv_dereg_mr(ib_mr);\r
522 err_alloc_mr:\r
523         if( p_umv_buf && p_umv_buf->command ) \r
524                 p_umv_buf->status = IB_ERROR;\r
525         HCA_EXIT(HCA_DBG_QP);\r
526         return ERR_PTR(err);\r
527 }\r
528 \r
529 int ibv_modify_qp(struct ib_qp *qp,\r
530                  struct ib_qp_attr *qp_attr,\r
531                  int qp_attr_mask)\r
532 {\r
533         return qp->device->modify_qp(qp, qp_attr, qp_attr_mask);\r
534 }\r
535 \r
536 int ibv_query_qp(struct ib_qp *qp,\r
537                 struct ib_qp_attr *qp_attr,\r
538                 int qp_attr_mask,\r
539                 struct ib_qp_init_attr *qp_init_attr)\r
540 {\r
541         return qp->device->query_qp ?\r
542                 qp->device->query_qp(qp, qp_attr, qp_attr_mask, qp_init_attr) :\r
543                 -ENOSYS;\r
544 }\r
545         \r
546 int ibv_destroy_qp(struct ib_qp *qp)\r
547 {\r
548         struct ib_pd *pd;\r
549         struct ib_cq *scq, *rcq;\r
550         struct ib_srq *srq;\r
551         int ret;\r
552         struct ib_ucontext      *ucontext;\r
553         struct ib_mr * ib_mr;\r
554 \r
555         pd  = qp->pd;\r
556         scq = qp->send_cq;\r
557         rcq = qp->recv_cq;\r
558         srq = qp->srq;\r
559         ucontext = pd->ucontext;\r
560         ib_mr = qp->ib_mr;\r
561 \r
562         ret = qp->device->destroy_qp(qp);\r
563         if (!ret) {\r
564                 atomic_dec(&pd->usecnt);\r
565                 atomic_dec(&scq->usecnt);\r
566                 atomic_dec(&rcq->usecnt);\r
567                 HCA_PRINT(TRACE_LEVEL_INFORMATION  ,HCA_DBG_QP ,("PD%d use cnt %d, pd_handle %p, ctx %p \n", \r
568                         ((struct mthca_pd*)pd)->pd_num, pd->usecnt, pd, pd->ucontext));\r
569                 if (srq)\r
570                         atomic_dec(&srq->usecnt);\r
571                 release_user_cq_qp_resources(ucontext, ib_mr);\r
572         }\r
573 \r
574         return ret;\r
575 }\r
576 \r
577 /* Completion queues */\r
578 \r
579 struct ib_cq *ibv_create_cq(struct ib_device *device,\r
580                            ib_comp_handler comp_handler,\r
581                            void (*event_handler)(struct ib_event *, void *),\r
582                            void *cq_context, int cqe, \r
583                            struct ib_ucontext *context, ci_umv_buf_t* const p_umv_buf)\r
584 {\r
585         int err;\r
586         struct ib_cq *cq;\r
587         struct ib_mr *ib_mr = NULL;\r
588         u64 user_handle = 0;\r
589 \r
590         // for user call we need also allocate MR\r
591         if (context && p_umv_buf && p_umv_buf->p_inout_buf) {\r
592                 struct ibv_create_cq *create_cq = (struct ibv_create_cq *)(void*)p_umv_buf->p_inout_buf;\r
593                 \r
594                 // create region\r
595                 ib_mr   = ibv_reg_mr( \r
596                         (struct ib_pd *)(ULONG_PTR)create_cq->mr.pd_handle, \r
597                         create_cq->mr.access_flags, \r
598                         (void*)(ULONG_PTR)create_cq->mr.start,\r
599                         create_cq->mr.length, create_cq->mr.hca_va, TRUE, FALSE );\r
600                 if (IS_ERR(ib_mr)) {\r
601                         err = PTR_ERR(ib_mr);\r
602                         HCA_PRINT(TRACE_LEVEL_ERROR ,HCA_DBG_CQ ,("ibv_reg_mr failed (%d)\n", err));\r
603                         goto err_alloc_mr;\r
604                 }\r
605                 user_handle = create_cq->user_handle;\r
606                 create_cq->lkey = ib_mr->lkey;\r
607                 cqe = create_cq->cqe;\r
608         }\r
609         \r
610         // create cq\r
611         cq = device->create_cq(device, cqe, context, p_umv_buf);\r
612         if (IS_ERR(cq)) {\r
613                 err = PTR_ERR(cq);\r
614                 HCA_PRINT(TRACE_LEVEL_ERROR ,HCA_DBG_CQ ,("create_cq failed (%d)\n", err));\r
615                 goto err_create_cq;\r
616         }\r
617 \r
618         cq->device        = device;\r
619         cq->ucontext = context;\r
620         cq->comp_handler  = comp_handler;\r
621         cq->event_handler = event_handler;\r
622         cq->cq_context    = cq_context;\r
623         atomic_set(&cq->usecnt, 0);\r
624         if (context)\r
625                 atomic_inc(&context->usecnt);\r
626 \r
627         // fill results\r
628         if (context && p_umv_buf && p_umv_buf->p_inout_buf) {\r
629                 struct ibv_create_cq_resp *create_cq_resp = (struct ibv_create_cq_resp *)(void*)p_umv_buf->p_inout_buf;\r
630                 cq->ib_mr = ib_mr;\r
631                 create_cq_resp->user_handle = user_handle;\r
632                 create_cq_resp->mr.lkey = ib_mr->lkey;\r
633                 create_cq_resp->mr.rkey = ib_mr->rkey;\r
634                 create_cq_resp->mr.mr_handle = (u64)(ULONG_PTR)ib_mr;\r
635                 create_cq_resp->cq_handle = (u64)(ULONG_PTR)cq;\r
636                 create_cq_resp->cqe = cq->cqe;\r
637                 p_umv_buf->output_size = sizeof(struct ibv_create_cq_resp);\r
638         }\r
639         \r
640         return cq;\r
641 \r
642 err_create_cq:\r
643         if (ib_mr)\r
644                 ibv_dereg_mr(ib_mr);\r
645 err_alloc_mr:\r
646         if( p_umv_buf && p_umv_buf->command ) \r
647                 p_umv_buf->status = IB_ERROR;\r
648         return ERR_PTR(err);\r
649 }\r
650 \r
651 int ibv_destroy_cq(struct ib_cq *cq)\r
652 {\r
653         int ret;\r
654         struct ib_ucontext      *ucontext = cq->ucontext;\r
655         struct ib_mr * ib_mr = cq->ib_mr;\r
656         \r
657         if (atomic_read(&cq->usecnt))\r
658                 return -EBUSY;\r
659 \r
660         ret = cq->device->destroy_cq(cq);\r
661 \r
662         release_user_cq_qp_resources(ucontext, ib_mr);\r
663         \r
664         return ret;\r
665 }\r
666 \r
667 int ibv_resize_cq(struct ib_cq *cq,\r
668                  int           cqe)\r
669 {\r
670         int ret;\r
671 \r
672         if (!cq->device->resize_cq)\r
673                 return -ENOSYS;\r
674 \r
675         ret = cq->device->resize_cq(cq, &cqe);\r
676         if (!ret)\r
677                 cq->cqe = cqe;\r
678 \r
679         return ret;\r
680 }\r
681 \r
682 /* Memory regions */\r
683 \r
684 struct ib_mr *ibv_reg_mr(struct ib_pd *pd, \r
685         mthca_qp_access_t mr_access_flags,\r
686         void*                   vaddr,\r
687         uint64_t                                length,\r
688         uint64_t                                hca_va,\r
689         boolean_t                               um_call,\r
690         boolean_t                               secure\r
691         )\r
692 {\r
693         struct ib_mr *ib_mr;\r
694         int                          err;\r
695         HCA_ENTER(HCA_DBG_MEMORY);\r
696 \r
697         ib_mr = pd->device->reg_virt_mr(pd, vaddr, length, hca_va, mr_access_flags, um_call, secure);\r
698         if (IS_ERR(ib_mr)) {\r
699                 err = PTR_ERR(ib_mr);\r
700                 HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_MEMORY ,("mthca_reg_user_mr failed (%d)\n", err));\r
701                 goto err_reg_user_mr;\r
702         }\r
703 \r
704         ib_mr->device  = pd->device;\r
705         ib_mr->pd      = pd;\r
706         atomic_inc(&pd->usecnt);\r
707         atomic_set(&ib_mr->usecnt, 0);\r
708         HCA_PRINT(TRACE_LEVEL_INFORMATION ,HCA_DBG_MEMORY ,("PD%d use cnt %d, pd_handle %p, ctx %p \n", \r
709                 ((struct mthca_pd*)pd)->pd_num, pd->usecnt, pd, pd->ucontext));\r
710         HCA_EXIT(HCA_DBG_MEMORY);\r
711         return ib_mr;\r
712 \r
713 err_reg_user_mr:\r
714         HCA_EXIT(HCA_DBG_MEMORY);\r
715         return ERR_PTR(err);\r
716 }\r
717 \r
718 struct ib_mr *ibv_get_dma_mr(struct ib_pd *pd, mthca_qp_access_t mr_access_flags)\r
719 {\r
720         struct ib_mr *mr;\r
721 \r
722         // direct call is a must, because "lifefish" devices doesn't fill driver i/f table\r
723         mr = mthca_get_dma_mr(pd, mr_access_flags);\r
724 \r
725         if (!IS_ERR(mr)) {\r
726                 mr->device  = pd->device;\r
727                 mr->pd      = pd;\r
728                 atomic_inc(&pd->usecnt);\r
729                 atomic_set(&mr->usecnt, 0);\r
730                 HCA_PRINT(TRACE_LEVEL_INFORMATION ,HCA_DBG_MEMORY ,("PD%d use cnt %d \n", \r
731                         ((struct mthca_pd*)pd)->pd_num, pd->usecnt));\r
732         }\r
733 \r
734         return mr;\r
735 }\r
736 \r
737 struct ib_mr *ibv_reg_phys_mr(struct ib_pd *pd,\r
738                              struct ib_phys_buf *phys_buf_array,\r
739                              int num_phys_buf,\r
740                              mthca_qp_access_t mr_access_flags,\r
741                              u64 *iova_start)\r
742 {\r
743         struct ib_mr *mr;\r
744 \r
745         mr = pd->device->reg_phys_mr(pd, phys_buf_array, num_phys_buf,\r
746                                      mr_access_flags, iova_start);\r
747 \r
748         if (!IS_ERR(mr)) {\r
749                 mr->device  = pd->device;\r
750                 mr->pd      = pd;\r
751                 atomic_inc(&pd->usecnt);\r
752                 atomic_set(&mr->usecnt, 0);\r
753                 HCA_PRINT(TRACE_LEVEL_INFORMATION ,HCA_DBG_MEMORY ,("PD%d use cnt %d \n", \r
754                         ((struct mthca_pd*)pd)->pd_num, pd->usecnt));\r
755         }\r
756 \r
757         return mr;\r
758 }\r
759 \r
760 int ibv_rereg_phys_mr(struct ib_mr *mr,\r
761                      int mr_rereg_mask,\r
762                      struct ib_pd *pd,\r
763                      struct ib_phys_buf *phys_buf_array,\r
764                      int num_phys_buf,\r
765                      mthca_qp_access_t mr_access_flags,\r
766                      u64 *iova_start)\r
767 {\r
768         struct ib_pd *old_pd;\r
769         int ret;\r
770 \r
771         if (!mr->device->rereg_phys_mr)\r
772                 return -ENOSYS;\r
773 \r
774         if (atomic_read(&mr->usecnt))\r
775                 return -EBUSY;\r
776 \r
777         old_pd = mr->pd;\r
778 \r
779         ret = mr->device->rereg_phys_mr(mr, mr_rereg_mask, pd,\r
780                                         phys_buf_array, num_phys_buf,\r
781                                         mr_access_flags, iova_start);\r
782 \r
783         if (!ret && (mr_rereg_mask & IB_MR_REREG_PD)) {\r
784                 atomic_dec(&old_pd->usecnt);\r
785                 atomic_inc(&pd->usecnt);\r
786                 HCA_PRINT(TRACE_LEVEL_INFORMATION  ,HCA_DBG_MEMORY ,("PD%d use cnt %d \n", \r
787                         ((struct mthca_pd*)pd)->pd_num, pd->usecnt));\r
788         }\r
789 \r
790         return ret;\r
791 }\r
792 \r
793 int ibv_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr)\r
794 {\r
795         return mr->device->query_mr ?\r
796                 mr->device->query_mr(mr, mr_attr) : -ENOSYS;\r
797 }\r
798 \r
799 int ibv_dereg_mr(struct ib_mr *mr)\r
800 {\r
801         int ret;\r
802         struct ib_pd *pd;\r
803 \r
804         if (atomic_read(&mr->usecnt))\r
805                 return -EBUSY;\r
806 \r
807         pd = mr->pd;\r
808         // direct call is a must, because "lifefish" devices doesn't fill driver i/f table\r
809         ret = mthca_dereg_mr(mr);\r
810         if (!ret) {\r
811                 atomic_dec(&pd->usecnt);\r
812                 HCA_PRINT(TRACE_LEVEL_INFORMATION  ,HCA_DBG_MEMORY ,("PD%d use cnt %d, pd_handle %p, ctx %p \n", \r
813                         ((struct mthca_pd*)pd)->pd_num, pd->usecnt, pd, pd->ucontext));\r
814         }\r
815 \r
816         return ret;\r
817 }\r
818 \r
819 /* Memory windows */\r
820 \r
821 struct ib_mw *ibv_alloc_mw(struct ib_pd *pd)\r
822 {\r
823         struct ib_mw *mw;\r
824 \r
825         if (!pd->device->alloc_mw)\r
826                 return ERR_PTR(-ENOSYS);\r
827 \r
828         mw = pd->device->alloc_mw(pd);\r
829         if (!IS_ERR(mw)) {\r
830                 mw->device  = pd->device;\r
831                 mw->pd      = pd;\r
832                 atomic_inc(&pd->usecnt);\r
833                 HCA_PRINT(TRACE_LEVEL_INFORMATION ,HCA_DBG_MEMORY ,("PD%d use cnt %d \n", \r
834                         ((struct mthca_pd*)pd)->pd_num, pd->usecnt));\r
835         }\r
836 \r
837         return mw;\r
838 }\r
839 \r
840 int ibv_dealloc_mw(struct ib_mw *mw)\r
841 {\r
842         struct ib_pd *pd;\r
843         int ret;\r
844 \r
845         pd = mw->pd;\r
846         ret = mw->device->dealloc_mw(mw);\r
847         if (!ret) {\r
848                 atomic_dec(&pd->usecnt);\r
849                 HCA_PRINT(TRACE_LEVEL_INFORMATION ,HCA_DBG_MEMORY ,("PD%d use cnt %d \n", \r
850                         ((struct mthca_pd*)pd)->pd_num, pd->usecnt));\r
851         }\r
852 \r
853         return ret;\r
854 }\r
855 \r
856 /* "Fast" memory regions */\r
857 \r
858 struct ib_fmr *ibv_alloc_fmr(struct ib_pd *pd,\r
859                             mthca_qp_access_t mr_access_flags,\r
860                             struct ib_fmr_attr *fmr_attr)\r
861 {\r
862         struct ib_fmr *fmr;\r
863 \r
864         if (!pd->device->alloc_fmr)\r
865                 return ERR_PTR(-ENOSYS);\r
866 \r
867         fmr = pd->device->alloc_fmr(pd, mr_access_flags, fmr_attr);\r
868         if (!IS_ERR(fmr)) {\r
869                 fmr->device = pd->device;\r
870                 fmr->pd     = pd;\r
871                 atomic_inc(&pd->usecnt);\r
872                 HCA_PRINT(TRACE_LEVEL_INFORMATION ,HCA_DBG_MEMORY ,("PD%d use cnt %d \n", \r
873                         ((struct mthca_pd*)pd)->pd_num, pd->usecnt));\r
874         }\r
875 \r
876         return fmr;\r
877 }\r
878 \r
879 int ibv_map_phys_fmr(struct ib_fmr *fmr,\r
880                                   u64 *page_list, int list_len,\r
881                                   u64 iova)\r
882 {\r
883         return fmr->device->map_phys_fmr(fmr, page_list, list_len, iova);\r
884 }\r
885 \r
886 int ibv_unmap_fmr(struct list_head *fmr_list)\r
887 {\r
888         struct ib_fmr *fmr;\r
889 \r
890         if (list_empty(fmr_list))\r
891                 return 0;\r
892 \r
893         fmr = list_entry(fmr_list->Flink, struct ib_fmr, list);\r
894         return fmr->device->unmap_fmr(fmr_list);\r
895 }\r
896 \r
897 int ibv_dealloc_fmr(struct ib_fmr *fmr)\r
898 {\r
899         struct ib_pd *pd;\r
900         int ret;\r
901 \r
902         pd = fmr->pd;\r
903         ret = fmr->device->dealloc_fmr(fmr);\r
904         if (!ret) {\r
905                 atomic_dec(&pd->usecnt);\r
906                 HCA_PRINT(TRACE_LEVEL_INFORMATION ,HCA_DBG_MEMORY ,("PD%d use cnt %d \n", \r
907                         ((struct mthca_pd*)pd)->pd_num, pd->usecnt));\r
908         }\r
909 \r
910         return ret;\r
911 }\r
912 \r
913 /* Multicast groups */\r
914 \r
915 int ibv_attach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid)\r
916 {\r
917         if (!qp->device->attach_mcast)\r
918                 return -ENOSYS;\r
919         if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UNRELIABLE_DGRM)\r
920                 return -EINVAL;\r
921 \r
922         return qp->device->attach_mcast(qp, gid, lid);\r
923 }\r
924 \r
925 int ibv_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid)\r
926 {\r
927         if (!qp->device->detach_mcast)\r
928                 return -ENOSYS;\r
929         if (gid->raw[0] != 0xff || qp->qp_type != IB_QPT_UNRELIABLE_DGRM)\r
930                 return -EINVAL;\r
931 \r
932         return qp->device->detach_mcast(qp, gid, lid);\r
933 }\r