[IBAL, HW] Remove pointers from ci_umv_buf_t.
[mirror/winof/.git] / hw / mlx4 / kernel / hca / verbs.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  * Copyright (c) 2004-2005 Mellanox Technologies, Inc. All rights reserved. \r
4  * Portions Copyright (c) 2008 Microsoft Corporation.  All rights reserved.\r
5  *\r
6  * This software is available to you under the OpenIB.org BSD license\r
7  * below:\r
8  *\r
9  *     Redistribution and use in source and binary forms, with or\r
10  *     without modification, are permitted provided that the following\r
11  *     conditions are met:\r
12  *\r
13  *      - Redistributions of source code must retain the above\r
14  *        copyright notice, this list of conditions and the following\r
15  *        disclaimer.\r
16  *\r
17  *      - Redistributions in binary form must reproduce the above\r
18  *        copyright notice, this list of conditions and the following\r
19  *        disclaimer in the documentation and/or other materials\r
20  *        provided with the distribution.\r
21  *\r
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
23  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
24  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
25  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
26  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
27  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
28  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
29  * SOFTWARE.\r
30  *\r
31  * $Id: hca_verbs.c 2073 2007-11-13 11:38:40Z leonid $\r
32  */\r
33 \r
34 \r
35 #include "precomp.h"\r
36 \r
37 #if defined(EVENT_TRACING)\r
38 #ifdef offsetof\r
39 #undef offsetof\r
40 #endif\r
41 #include "verbs.tmh"\r
42 #endif\r
43 \r
44 \r
45 /* Memory regions */\r
46 \r
47 struct ib_mr *ib_get_dma_mr(struct ib_pd *pd, enum ib_access_flags mr_access_flags)\r
48 {\r
49         struct ib_mr *mr;\r
50 \r
51         mr = pd->device->get_dma_mr(pd, mr_access_flags);\r
52  \r
53         if (!IS_ERR(mr)) {\r
54                 mr->device  = pd->device;\r
55                 mr->pd      = pd;\r
56                 mr->p_uctx = pd->p_uctx;\r
57                 atomic_inc(&pd->usecnt);\r
58                 atomic_set(&mr->usecnt, 0);\r
59                 HCA_PRINT(TRACE_LEVEL_INFORMATION ,HCA_DBG_MEMORY ,("pdn %d, usecnt %d \n", \r
60                         ((struct mlx4_ib_pd*)pd)->pdn, pd->usecnt));\r
61         }\r
62 \r
63         return mr;\r
64 }\r
65 \r
66 struct ib_mr *ib_reg_phys_mr(struct ib_pd *pd,\r
67                                   struct ib_phys_buf *phys_buf_array,\r
68                                   int num_phys_buf,\r
69                                   enum ib_access_flags mr_access_flags,\r
70                                   u64 *iova_start)\r
71 {\r
72         struct ib_mr *mr;\r
73 \r
74         if ( pd->device->reg_phys_mr )\r
75                 mr = pd->device->reg_phys_mr(pd, phys_buf_array, num_phys_buf,\r
76                         mr_access_flags, iova_start);\r
77         else\r
78                 mr = ERR_PTR(-ENOSYS);\r
79 \r
80         if (!IS_ERR(mr)) {\r
81                 mr->device  = pd->device;\r
82                 mr->pd   = pd;\r
83                 mr->p_uctx = pd->p_uctx;\r
84                 atomic_inc(&pd->usecnt);\r
85                 atomic_set(&mr->usecnt, 0);\r
86                 HCA_PRINT(TRACE_LEVEL_INFORMATION ,HCA_DBG_MEMORY ,("PD%d use cnt %d \n", \r
87                         ((struct mlx4_ib_pd*)pd)->pdn, pd->usecnt));\r
88         }\r
89 \r
90         return mr;\r
91 }\r
92 \r
93 \r
94  struct ib_mr *ibv_reg_mr(struct ib_pd *pd, \r
95         u64 start, u64 length,\r
96         u64 virt_addr,\r
97         int mr_access_flags,\r
98         ci_umv_buf_t* const p_umv_buf )\r
99 {\r
100         struct ib_mr *ib_mr;\r
101         int err;\r
102         HCA_ENTER(HCA_DBG_MEMORY);\r
103 \r
104         if (p_umv_buf  && p_umv_buf->command) {\r
105                 err = -ENOSYS;\r
106                 goto err_not_supported;\r
107         }\r
108 \r
109         ib_mr = pd->device->reg_user_mr(pd, start, length, virt_addr, mr_access_flags, NULL);\r
110         if (IS_ERR(ib_mr)) {\r
111                 err = PTR_ERR(ib_mr);\r
112                 HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_MEMORY ,("mthca_reg_user_mr failed (%d)\n", err));\r
113                 goto err_reg_user_mr;\r
114         }\r
115 \r
116         ib_mr->device  = pd->device;\r
117         ib_mr->pd      = pd;\r
118         atomic_inc(&pd->usecnt);\r
119         atomic_set(&ib_mr->usecnt, 0);\r
120         HCA_PRINT(TRACE_LEVEL_INFORMATION ,HCA_DBG_MEMORY ,("PD%d use cnt %d, pd_handle %p, ctx %p \n", \r
121                 ((struct mlx4_ib_pd*)pd)->pdn, pd->usecnt, pd, pd->p_uctx));\r
122         HCA_EXIT(HCA_DBG_MEMORY);\r
123         return ib_mr;\r
124 \r
125 err_reg_user_mr:\r
126 err_not_supported:\r
127         HCA_EXIT(HCA_DBG_MEMORY);\r
128         return ERR_PTR(err);\r
129 }\r
130 \r
131 int ib_dereg_mr(struct ib_mr *mr)\r
132 {\r
133         int ret;\r
134         struct ib_pd *pd;\r
135         struct ib_device *p_ibdev;\r
136 \r
137         if (atomic_read(&mr->usecnt))\r
138                 return -EBUSY;\r
139 \r
140         p_ibdev = mr->device;\r
141         pd = mr->pd;\r
142         ret = p_ibdev->dereg_mr(mr);\r
143         if (!ret) {\r
144                 atomic_dec(&pd->usecnt);\r
145                 HCA_PRINT(TRACE_LEVEL_INFORMATION  ,HCA_DBG_MEMORY ,("pdn %d, usecnt %d, pd_handle %p, ctx %p \n", \r
146                         ((struct mlx4_ib_pd*)pd)->pdn, pd->usecnt, pd, pd->p_uctx));\r
147         }\r
148 \r
149         return ret;\r
150 }\r
151 \r
152 static void release_user_cq_qp_resources(\r
153         struct ib_ucontext      *p_uctx)\r
154 {\r
155         if (p_uctx) {\r
156                 atomic_dec(&p_uctx->x.usecnt);\r
157                 if (!atomic_read(&p_uctx->x.usecnt) && p_uctx->closing) {\r
158                         HCA_PRINT(TRACE_LEVEL_ERROR  ,HCA_DBG_SHIM      ,("User resources are released. Removing context\n"));\r
159                         ibv_um_close(p_uctx);\r
160                 }\r
161         }\r
162 }\r
163 \r
164 //\r
165 // Completion queues\r
166 //\r
167 \r
168 struct ib_cq *ibv_create_cq(struct ib_device *p_ibdev,\r
169                            ib_comp_handler comp_handler,\r
170                            void (*event_handler)(struct ib_event *, void *),\r
171                            void *cq_context, int cqe, \r
172                            struct ib_ucontext *p_uctx, ci_umv_buf_t* const p_umv_buf)\r
173 {\r
174         int err;\r
175         struct ib_cq *cq;\r
176         struct ib_udata udata, *p_udata = &udata;\r
177         struct ibv_create_cq *p_req;\r
178         struct ibv_create_cq_resp *p_resp = NULL;\r
179 \r
180         if ( p_uctx && p_umv_buf && p_umv_buf->p_inout_buf ) {\r
181                 // prepare user parameters\r
182                 p_req = (struct ibv_create_cq*)(ULONG_PTR)p_umv_buf->p_inout_buf;\r
183                 p_resp = (struct ibv_create_cq_resp*)(ULONG_PTR)\r
184                         p_umv_buf->p_inout_buf;\r
185                 INIT_UDATA(&udata, &p_req->buf_addr, &p_resp->cqn, \r
186                         sizeof(struct mlx4_ib_create_cq), sizeof(struct mlx4_ib_create_cq_resp));\r
187         }\r
188         else \r
189                 p_udata = NULL;\r
190 \r
191         // create cq\r
192         cq = p_ibdev->create_cq(p_ibdev, cqe, 0, p_uctx, p_udata);\r
193         if (IS_ERR(cq)) {\r
194                 err = PTR_ERR(cq);\r
195                 HCA_PRINT(TRACE_LEVEL_ERROR ,HCA_DBG_CQ ,("create_cq failed (%d)\n", err));\r
196                 goto err_create_cq;\r
197         }\r
198 \r
199         cq->device        = p_ibdev;\r
200         cq->p_uctx        = p_uctx;\r
201         cq->comp_handler  = comp_handler;\r
202         cq->event_handler = event_handler;\r
203         cq->cq_context    = cq_context;\r
204         atomic_set(&cq->usecnt, 0);\r
205         if (p_uctx)\r
206                 atomic_inc(&p_uctx->x.usecnt);\r
207 \r
208         HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_CQ ,\r
209                 ("created CQ: cqn %#x:%#x \n", ((struct mlx4_ib_cq*)cq)->mcq.cqn, cq->cqe ));\r
210 \r
211         // fill results\r
212         if (p_umv_buf) {\r
213                 p_resp->cq_handle = (u64)(ULONG_PTR)cq;\r
214                 p_resp->cqe = cq->cqe;\r
215                 p_umv_buf->output_size = sizeof(struct ibv_create_cq_resp);\r
216         }\r
217         \r
218         return cq;\r
219 \r
220 err_create_cq:\r
221         if( p_umv_buf && p_umv_buf->command ) \r
222                 p_umv_buf->status = IB_ERROR;\r
223         return ERR_PTR(err);\r
224 }\r
225 \r
226 int ib_destroy_cq(struct ib_cq *cq)\r
227 {\r
228         int ret;\r
229         struct ib_ucontext      *p_uctx = cq->p_uctx;\r
230         \r
231         if (atomic_read(&cq->usecnt))\r
232                 return -EBUSY;\r
233 \r
234         HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_CQ ,\r
235                 ("destroying CQ: cqn %#x:%#x \n", ((struct mlx4_ib_cq*)cq)->mcq.cqn, cq->cqe ));\r
236 \r
237         ret = cq->device->destroy_cq(cq);\r
238         release_user_cq_qp_resources(p_uctx);\r
239         return ret;\r
240 }\r
241 \r
242 //\r
243 // Queue pairs \r
244 //\r
245 \r
246 static char *__print_qtype(enum ib_qp_type qtype)\r
247 {\r
248         char *str = NULL;\r
249         switch (qtype) {\r
250                 case IB_QPT_SMI: str = "SMI"; break;\r
251                 case IB_QPT_GSI: str = "GSI"; break;\r
252                 case IB_QPT_RC: str = "RC"; break;\r
253                 case IB_QPT_UC: str = "UC"; break;\r
254                 case IB_QPT_UD: str = "UD"; break;\r
255                 case IB_QPT_RAW_IP_V6: str = "IP_V6"; break;\r
256                 case IB_QPT_RAW_ETY: str = "ETY"; break;\r
257                 default: str = "UKNWN"; break;\r
258         }\r
259         return str;\r
260 }\r
261 \r
262 struct ib_qp *ibv_create_qp(struct ib_pd *pd,\r
263         struct ib_qp_init_attr *qp_init_attr,\r
264         struct ib_ucontext *p_uctx, ci_umv_buf_t* const p_umv_buf)\r
265 {\r
266         int err;\r
267         struct ib_qp *p_ib_qp;\r
268         struct ib_udata udata, *p_udata = &udata;\r
269         struct ibv_create_qp *p_req = NULL;\r
270         struct ibv_create_qp_resp *p_resp= NULL;\r
271 \r
272         HCA_ENTER(HCA_DBG_QP);\r
273 \r
274         if ( p_uctx && p_umv_buf && p_umv_buf->command ) {\r
275                 // prepare user parameters\r
276                 p_req = (struct ibv_create_qp*)(ULONG_PTR)p_umv_buf->p_inout_buf;\r
277                 p_resp = (struct ibv_create_qp_resp*)(ULONG_PTR)p_umv_buf->p_inout_buf;\r
278                 INIT_UDATA(&udata, &p_req->buf_addr, NULL, \r
279                         sizeof(struct mlx4_ib_create_qp), 0);\r
280         }\r
281         else \r
282                 p_udata = NULL;\r
283 \r
284         p_ib_qp = pd->device->create_qp( pd, qp_init_attr, p_udata );\r
285 \r
286         if (IS_ERR(p_ib_qp)) {\r
287                 err = PTR_ERR(p_ib_qp);\r
288                 HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_QP ,("create_qp failed (%d)\n", err));\r
289                 goto err_create_qp;\r
290         }\r
291 \r
292         // fill results\r
293         p_ib_qp->device                         = pd->device;\r
294         p_ib_qp->pd                             = pd;\r
295         p_ib_qp->send_cq                        = qp_init_attr->send_cq;\r
296         p_ib_qp->recv_cq                        = qp_init_attr->recv_cq;\r
297         p_ib_qp->srq                            = qp_init_attr->srq;\r
298         p_ib_qp->p_uctx                                 = p_uctx;\r
299         p_ib_qp->event_handler                  = qp_init_attr->event_handler;\r
300         p_ib_qp->qp_context                     = qp_init_attr->qp_context;\r
301         p_ib_qp->qp_type                                = qp_init_attr->qp_type;\r
302         atomic_inc(&pd->usecnt);\r
303         atomic_inc(&qp_init_attr->send_cq->usecnt);\r
304         atomic_inc(&qp_init_attr->recv_cq->usecnt);\r
305         if (qp_init_attr->srq)\r
306                 atomic_inc(&qp_init_attr->srq->usecnt);\r
307         if (p_uctx)\r
308                 atomic_inc(&p_uctx->x.usecnt);\r
309                 HCA_PRINT(TRACE_LEVEL_INFORMATION ,HCA_DBG_QP ,("pdn %d, usecnt %d, pd_handle %p, ctx %p \n", \r
310                         ((struct mlx4_ib_pd*)pd)->pdn, pd->usecnt, pd, pd->p_uctx));\r
311 \r
312         HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_QP ,\r
313                 ("qtype %s (%d), qnum %#x, q_num  %#x, ssz %d, rsz %d, scq %#x:%#x, rcq %#x:%#x, port_num %d \n",\r
314                 __print_qtype(p_ib_qp->qp_type), p_ib_qp->qp_type,\r
315                 ((struct mlx4_ib_qp*)p_ib_qp)->mqp.qpn, p_ib_qp->qp_num, \r
316                 qp_init_attr->cap.max_send_wr, qp_init_attr->cap.max_recv_wr,\r
317                 ((struct mlx4_ib_cq*)p_ib_qp->send_cq)->mcq.cqn, p_ib_qp->send_cq->cqe,\r
318                 ((struct mlx4_ib_cq*)p_ib_qp->recv_cq)->mcq.cqn, p_ib_qp->recv_cq->cqe,\r
319                 qp_init_attr->port_num\r
320                 ) );\r
321 \r
322         // fill results for user\r
323         if (p_uctx && p_umv_buf && p_umv_buf->p_inout_buf) {\r
324                 struct mlx4_ib_qp *p_mib_qp = (struct mlx4_ib_qp *)p_ib_qp;\r
325                 p_resp->qp_handle = (__u64)(ULONG_PTR)p_ib_qp;\r
326                 p_resp->qpn = p_mib_qp->mqp.qpn;\r
327                 p_resp->max_send_wr = p_mib_qp->sq.max_post;\r
328                 p_resp->max_recv_wr = p_mib_qp->rq.max_post;\r
329                 p_resp->max_send_sge = p_mib_qp->sq.max_gs;\r
330                 p_resp->max_recv_sge = p_mib_qp->rq.max_gs;\r
331                 /*\r
332                  * We don't support inline sends for kernel QPs (yet), and we\r
333                  * don't know what userspace's value should be.\r
334                  */\r
335                 p_resp->max_inline_data = 0;\r
336                 p_umv_buf->output_size = sizeof(struct ibv_create_qp_resp);\r
337         }\r
338 \r
339         return p_ib_qp;\r
340 \r
341 err_create_qp:\r
342         if( p_umv_buf && p_umv_buf->command ) \r
343                 p_umv_buf->status = IB_ERROR;\r
344         HCA_EXIT(HCA_DBG_QP);\r
345         return ERR_PTR(err);\r
346 }\r
347 \r
348 int ib_destroy_qp(struct ib_qp *qp)\r
349 {\r
350         struct ib_pd *p_ib_pd;\r
351         struct ib_cq *scq, *rcq;\r
352         struct ib_srq *srq;\r
353         struct ib_ucontext      *p_uctx;\r
354         int ret;\r
355 \r
356         p_ib_pd  = qp->pd;\r
357         scq = qp->send_cq;\r
358         rcq = qp->recv_cq;\r
359         srq = qp->srq;\r
360         p_uctx = p_ib_pd->p_uctx;\r
361 \r
362         ret = qp->device->destroy_qp(qp);\r
363         if (!ret) {\r
364                 atomic_dec(&p_ib_pd->usecnt);\r
365                 atomic_dec(&scq->usecnt);\r
366                 atomic_dec(&rcq->usecnt);\r
367                 HCA_PRINT(TRACE_LEVEL_INFORMATION  ,HCA_DBG_QP ,("PD%d use cnt %d, pd_handle %p, ctx %p \n", \r
368                         ((struct mlx4_ib_pd*)p_ib_pd)->pdn, p_ib_pd->usecnt, p_ib_pd, p_ib_pd->p_uctx));\r
369                 if (srq)\r
370                         atomic_dec(&srq->usecnt);\r
371                 release_user_cq_qp_resources(p_uctx);\r
372         }\r
373 \r
374         return ret;\r
375 }\r
376 \r
377 //\r
378 // Shared receive queues\r
379 //\r
380 \r
381 \r
382 /* Shared receive queues */\r
383 \r
384 struct ib_srq *ibv_create_srq(struct ib_pd *pd,\r
385         struct ib_srq_init_attr *srq_init_attr,\r
386         struct ib_ucontext *p_uctx, ci_umv_buf_t* const p_umv_buf)\r
387 {\r
388         int err;\r
389         struct ib_srq *p_ib_srq;\r
390         struct ib_udata udata, *p_udata = &udata;\r
391         struct ibv_create_srq *p_req = NULL;\r
392         struct ibv_create_srq_resp *p_resp= NULL;\r
393 \r
394         if ( p_uctx && p_umv_buf && p_umv_buf->p_inout_buf) {\r
395                 // prepare user parameters\r
396                 p_req = (struct ibv_create_srq*)(ULONG_PTR)p_umv_buf->p_inout_buf;\r
397                 p_resp = (struct ibv_create_srq_resp*)(ULONG_PTR)p_umv_buf->p_inout_buf;\r
398                 INIT_UDATA(&udata, &p_req->buf_addr, &p_resp->srqn, \r
399                         sizeof(struct ibv_create_srq), sizeof(struct ibv_create_srq_resp));\r
400         }\r
401         else \r
402                 p_udata = NULL;\r
403 \r
404         p_ib_srq = pd->device->create_srq( pd, srq_init_attr, p_udata );\r
405         if (IS_ERR(p_ib_srq)) {\r
406                 err = PTR_ERR(p_ib_srq);\r
407                 HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_QP ,("create_srq failed (%d)\n", err));\r
408                 goto err_create_srq;\r
409         }\r
410 \r
411         // fill results\r
412         p_ib_srq->device                        = pd->device;\r
413         p_ib_srq->pd                            = pd;\r
414         p_ib_srq->p_uctx                                = p_uctx;\r
415         p_ib_srq->event_handler                 = srq_init_attr->event_handler;\r
416         p_ib_srq->srq_context                   = srq_init_attr->srq_context;\r
417         atomic_inc(&pd->usecnt);\r
418         atomic_set(&p_ib_srq->usecnt, 0);\r
419         if (p_uctx)\r
420                 atomic_inc(&p_uctx->x.usecnt);\r
421                 HCA_PRINT(TRACE_LEVEL_INFORMATION ,HCA_DBG_QP ,("PD%d use cnt %d, pd_handle %p, ctx %p \n", \r
422                         ((struct mlx4_ib_pd*)pd)->pdn, pd->usecnt, pd, pd->p_uctx));\r
423 \r
424         HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_SRQ ,\r
425                 ("uctx %p, qhndl %p, qnum %#x \n", \r
426                 pd->p_uctx, p_ib_srq, ((struct mlx4_ib_srq*)p_ib_srq)->msrq.srqn ) );\r
427 \r
428         // fill results for user\r
429         if (p_uctx && p_umv_buf && p_umv_buf->p_inout_buf) {\r
430                 struct mlx4_ib_srq* p_mib_srq = (struct mlx4_ib_srq*)p_ib_srq;\r
431                 p_resp->srq_handle = (__u64)(ULONG_PTR)p_ib_srq;\r
432                 p_resp->max_wr = p_mib_srq->msrq.max - 1;\r
433                 p_resp->max_sge = p_mib_srq->msrq.max_gs;\r
434                 p_umv_buf->output_size = sizeof(struct ibv_create_srq_resp);\r
435                 HCA_PRINT(TRACE_LEVEL_INFORMATION ,HCA_DBG_QP ,("PD%d use cnt %d \n", \r
436                         ((struct mlx4_ib_pd*)pd)->pdn, pd->usecnt));\r
437         }\r
438 \r
439         return p_ib_srq;\r
440         \r
441 err_create_srq:\r
442         if( p_umv_buf && p_umv_buf->command ) \r
443                 p_umv_buf->status = IB_ERROR;\r
444         HCA_EXIT(HCA_DBG_QP);\r
445         return ERR_PTR(err);\r
446 }\r
447 \r
448 int ib_destroy_srq(struct ib_srq *srq)\r
449 {\r
450         int ret;\r
451         struct ib_pd *p_ib_pd = srq->pd;\r
452         struct ib_ucontext      *p_uctx = p_ib_pd->p_uctx;\r
453 \r
454         ret = srq->device->destroy_srq(srq);\r
455         if (!ret) {\r
456                 atomic_dec(&p_ib_pd->usecnt);\r
457                 HCA_PRINT(TRACE_LEVEL_INFORMATION  ,HCA_DBG_SRQ ,("PD%d use cnt %d, pd_handle %p, ctx %p \n", \r
458                         ((struct mlx4_ib_pd*)p_ib_pd)->pdn, p_ib_pd->usecnt, p_ib_pd, p_ib_pd->p_uctx));\r
459                 release_user_cq_qp_resources(p_uctx);\r
460         }\r
461 \r
462         return ret;\r
463 }\r
464 \r
465 //\r
466 // User context\r
467 //\r
468 static NTSTATUS __map_memory_for_user(\r
469         IN              io_addr_t       addr,\r
470         IN              SIZE_T          size,\r
471         IN              MEMORY_CACHING_TYPE mem_type,\r
472         OUT             umap_t  *       p_map\r
473         )\r
474 {\r
475         NTSTATUS status;\r
476 \r
477         HCA_ENTER(HCA_DBG_SHIM);\r
478 \r
479         p_map->mapped = 0;\r
480         \r
481         // map UAR to kernel \r
482         p_map->kva = ioremap(addr, size);\r
483         if (!p_map->kva) {\r
484                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_LOW ,\r
485                         ("Couldn't map kernel access region, aborting.\n") );\r
486                 status = IB_INSUFFICIENT_MEMORY;\r
487                 goto err_ioremap;\r
488         }\r
489 \r
490         // build MDL \r
491         p_map->mdl = IoAllocateMdl( p_map->kva, (ULONG)size,\r
492                 FALSE, TRUE, NULL );\r
493         if( !p_map->mdl ) {\r
494                 status = IB_INSUFFICIENT_MEMORY;\r
495                 goto err_alloc_mdl;\r
496         }\r
497         MmBuildMdlForNonPagedPool( p_map->mdl );\r
498 \r
499         /* Map the memory into the calling process's address space. */\r
500         __try   {\r
501                 p_map->uva = MmMapLockedPagesSpecifyCache( p_map->mdl,\r
502                         UserMode, mem_type, NULL, FALSE, NormalPagePriority );\r
503         }\r
504         __except(EXCEPTION_EXECUTE_HANDLER) {\r
505                 status = IB_INVALID_PERMISSION;\r
506                 goto err_map;\r
507         }\r
508 \r
509         p_map->mapped = 1;\r
510         status = STATUS_SUCCESS;\r
511         goto done;\r
512 \r
513 err_map:\r
514         IoFreeMdl(p_map->mdl);\r
515 \r
516 err_alloc_mdl:  \r
517         iounmap(p_map->kva, PAGE_SIZE);\r
518 \r
519 err_ioremap:\r
520 done:   \r
521         HCA_EXIT(HCA_DBG_SHIM);\r
522         return status;\r
523 }\r
524 \r
525 static void __unmap_memory_for_user(\r
526         IN              umap_t  *       p_map\r
527         )\r
528 {\r
529         if (p_map->mapped) {\r
530                 p_map->mapped = 0;\r
531                 MmUnmapLockedPages( p_map->uva, p_map->mdl );\r
532                 IoFreeMdl(p_map->mdl);\r
533                 iounmap(p_map->kva, PAGE_SIZE);\r
534         }\r
535 }\r
536 \r
537 ib_api_status_t ibv_um_open(    \r
538         IN                      struct ib_device                *       p_ibdev,\r
539         IN      OUT             ci_umv_buf_t* const                     p_umv_buf,\r
540         OUT                     struct ib_ucontext              **      pp_uctx )\r
541 {\r
542         int err;\r
543         ib_api_status_t         status;\r
544         struct mlx4_ib_ucontext *p_muctx;\r
545         struct ibv_get_context_resp *p_uresp;\r
546         struct mlx4_ib_alloc_ucontext_resp ib_alloc_ucontext_resp;\r
547         struct ib_ucontext              *p_uctx;\r
548         struct ib_udata udata;\r
549 \r
550         HCA_ENTER(HCA_DBG_SHIM);\r
551 \r
552         // create user context in kernel\r
553         INIT_UDATA(&udata, NULL, &ib_alloc_ucontext_resp, \r
554                 0, sizeof(struct mlx4_ib_alloc_ucontext_resp));\r
555 \r
556         p_uctx = p_ibdev->alloc_ucontext(p_ibdev, &udata);\r
557         if (IS_ERR(p_uctx)) {\r
558                 err = PTR_ERR(p_uctx);\r
559                 HCA_PRINT(TRACE_LEVEL_ERROR  ,HCA_DBG_SHIM,\r
560                         ("mthca_alloc_ucontext failed (%d)\n", err));\r
561                 status = errno_to_iberr(err);\r
562                 goto err_alloc_ucontext;\r
563         }\r
564         p_muctx = to_mucontext(p_uctx);\r
565         p_uresp = (struct ibv_get_context_resp *)(ULONG_PTR)p_umv_buf->p_inout_buf;\r
566 \r
567         // fill the rest of ib_ucontext fields \r
568         p_uctx->device = p_ibdev;\r
569         p_uctx->closing = 0;\r
570 \r
571         // livefish\r
572         if (hca_is_livefish(p_ibdev->x.p_fdo))\r
573                 goto done;\r
574         \r
575         // map uar to user space\r
576         status = __map_memory_for_user( \r
577                 (io_addr_t)p_muctx->uar.pfn << PAGE_SHIFT, \r
578                 PAGE_SIZE, MmNonCached, &p_uctx->x.uar );\r
579         if( !NT_SUCCESS(status) ) {\r
580                 goto err_map_uar;\r
581         }\r
582         p_uresp->uar_addr        = (u64)(ULONG_PTR)p_uctx->x.uar.uva;\r
583 \r
584         // map BF to user space\r
585         if (ib_alloc_ucontext_resp.bf_reg_size) {\r
586                 status = __map_memory_for_user( \r
587                         (io_addr_t)(p_muctx->uar.pfn + \r
588                         to_mdev(p_ibdev)->dev->caps.num_uars) << PAGE_SHIFT, \r
589                         PAGE_SIZE, MmWriteCombined, &p_uctx->x.bf );\r
590                 if( !NT_SUCCESS(status) ) {\r
591                         HCA_PRINT(TRACE_LEVEL_WARNING ,HCA_DBG_SHIM,\r
592                                 ("BlueFlame available, but failed to be mapped (%#x)\n", status));\r
593                         p_uresp->bf_page         = 0;\r
594                         p_uresp->bf_buf_size = 0;\r
595                 } \r
596                 else {\r
597                         p_uresp->bf_page         = (u64)(ULONG_PTR)p_uctx->x.bf.uva;\r
598                         p_uresp->bf_buf_size = ib_alloc_ucontext_resp.bf_reg_size / 2;\r
599                         p_uresp->bf_offset       = 0;\r
600                 }\r
601         }\r
602         else {\r
603                         p_uresp->bf_page         = 0;\r
604                         p_uresp->bf_buf_size = 0;\r
605         }\r
606 \r
607 done:\r
608         // fill the response\r
609         p_uresp->bf_reg_size             = ib_alloc_ucontext_resp.bf_reg_size;\r
610         p_uresp->bf_regs_per_page        = ib_alloc_ucontext_resp.bf_regs_per_page;\r
611         p_uresp->qp_tab_size             = ib_alloc_ucontext_resp.qp_tab_size;\r
612 \r
613         *pp_uctx = p_uctx;\r
614         status = IB_SUCCESS;\r
615         goto end;\r
616 \r
617 err_map_uar:\r
618         p_ibdev->dealloc_ucontext(p_uctx);\r
619 err_alloc_ucontext: \r
620 end:\r
621         HCA_EXIT(HCA_DBG_SHIM);\r
622         return status;\r
623 }\r
624 \r
625 \r
626 void ibv_um_close(      struct ib_ucontext * h_um_ca )\r
627 {\r
628         int err;\r
629         ib_api_status_t         status;\r
630         struct ib_ucontext *p_uctx = (struct ib_ucontext *)h_um_ca;\r
631         PFDO_DEVICE_DATA p_fdo = p_uctx->device->x.p_fdo;\r
632 \r
633         HCA_ENTER(HCA_DBG_SHIM);\r
634 \r
635         p_uctx->closing = 1;\r
636 \r
637         if (atomic_read(&p_uctx->x.usecnt)) {\r
638                 HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_SHIM,\r
639                         ("resources are not released (cnt %d)\n", p_uctx->x.usecnt));\r
640                 status = IB_RESOURCE_BUSY;\r
641                 goto err_usage;\r
642         }\r
643         \r
644         if ( !hca_is_livefish(p_fdo)) {\r
645                 __unmap_memory_for_user( &p_uctx->x.bf );\r
646                 __unmap_memory_for_user( &p_uctx->x.uar );\r
647         }\r
648 \r
649         err = p_fdo->bus_ib_ifc.p_ibdev->dealloc_ucontext(p_uctx);\r
650         if (err) {\r
651                 HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_SHIM,\r
652                         ("mthca_dealloc_ucontext failed (%d)\n", err));\r
653                 status = errno_to_iberr(err);\r
654                 goto err_dealloc_ucontext;\r
655         }\r
656 \r
657         HCA_PRINT(TRACE_LEVEL_INFORMATION,HCA_DBG_SHIM,\r
658                 ("pcs %p\n", PsGetCurrentProcess()) );\r
659         status = IB_SUCCESS;\r
660         goto end;\r
661         \r
662 err_dealloc_ucontext: \r
663 err_usage:\r
664 end:\r
665         if (status != IB_SUCCESS)\r
666         {\r
667                 HCA_PRINT(TRACE_LEVEL_ERROR,HCA_DBG_SHIM,\r
668                         ("completes with ERROR status %x\n", status));\r
669         }\r
670         HCA_EXIT(HCA_DBG_SHIM);\r
671         return;\r
672 }\r
673 \r