[IBAL, MTHCA, MT23108] Fix FMR implementation to properly represent
[mirror/winof/.git] / core / al / kernel / al_mr.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. \r
4  *\r
5  * This software is available to you under the OpenIB.org BSD license\r
6  * below:\r
7  *\r
8  *     Redistribution and use in source and binary forms, with or\r
9  *     without modification, are permitted provided that the following\r
10  *     conditions are met:\r
11  *\r
12  *      - Redistributions of source code must retain the above\r
13  *        copyright notice, this list of conditions and the following\r
14  *        disclaimer.\r
15  *\r
16  *      - Redistributions in binary form must reproduce the above\r
17  *        copyright notice, this list of conditions and the following\r
18  *        disclaimer in the documentation and/or other materials\r
19  *        provided with the distribution.\r
20  *\r
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
22  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
23  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
24  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
25  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
26  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
27  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
28  * SOFTWARE.\r
29  *\r
30  * $Id$\r
31  */\r
32 \r
33 #include <iba/ib_al.h>\r
34 \r
35 #include "al_debug.h"\r
36 #include "al_mr.h"\r
37 #include "al_pd.h"\r
38 #include "al_res_mgr.h"\r
39 #include "al_verbs.h"\r
40 \r
41 #include "ib_common.h"\r
42 \r
43 \r
44 static void\r
45 __cleanup_mlnx_fmr(\r
46         IN                              struct _al_obj                          *p_obj );\r
47 \r
48 static void\r
49 __return_mlnx_fmr(\r
50         IN                              al_obj_t                                        *p_obj );\r
51 \r
52 \r
53 static al_shmid_t*\r
54 __create_shmid(\r
55         IN              const   int                                                     shmid );\r
56 \r
57 static void\r
58 __free_shmid(\r
59         IN                              struct _al_obj                          *p_obj );\r
60 \r
61 \r
62 cl_status_t\r
63 mlnx_fmr_ctor(\r
64         IN                              void* const                                     p_object,\r
65         IN                              void*                                           context,\r
66                 OUT                     cl_pool_item_t** const          pp_pool_item )\r
67 {\r
68         ib_api_status_t                 status;\r
69         mlnx_fmr_handle_t                       h_fmr;\r
70 \r
71         UNUSED_PARAM( context );\r
72 \r
73         h_fmr = (mlnx_fmr_handle_t)p_object;\r
74         cl_memclr( h_fmr, sizeof(mlnx_fmr_t) );\r
75 \r
76         construct_al_obj( &h_fmr->obj, AL_OBJ_TYPE_H_FMR );\r
77         status = init_al_obj( &h_fmr->obj, NULL, FALSE, NULL,\r
78                 __cleanup_mlnx_fmr, __return_mlnx_fmr );\r
79         if( status != IB_SUCCESS )\r
80         {\r
81                 return CL_ERROR;\r
82         }\r
83 \r
84         *pp_pool_item = &((mlnx_fmr_handle_t)p_object)->obj.pool_item;\r
85 \r
86         /* Release the reference taken in init_al_obj. */\r
87         deref_al_obj( &h_fmr->obj );\r
88 \r
89         return CL_SUCCESS;\r
90 }\r
91 \r
92 \r
93 \r
94 void\r
95 mlnx_fmr_dtor(\r
96         IN              const   cl_pool_item_t* const           p_pool_item,\r
97         IN                              void*                                           context )\r
98 {\r
99         al_obj_t                                *p_obj;\r
100 \r
101         UNUSED_PARAM( context );\r
102 \r
103         p_obj = PARENT_STRUCT( p_pool_item, al_obj_t, pool_item );\r
104 \r
105         /*\r
106          * The FMR is being totally destroyed.  Modify the free_cb to destroy the\r
107          * AL object.\r
108          */\r
109         p_obj->pfn_free = (al_pfn_free_t)destroy_al_obj;\r
110         ref_al_obj( p_obj );\r
111         p_obj->pfn_destroy( p_obj, NULL );\r
112 }\r
113 \r
114 \r
115 \r
116 static void\r
117 __cleanup_mlnx_fmr(\r
118         IN                              struct _al_obj                          *p_obj )\r
119 {\r
120         ib_api_status_t                 status;\r
121         mlnx_fmr_handle_t                       h_fmr;\r
122 \r
123         CL_ASSERT( p_obj );\r
124         h_fmr = PARENT_STRUCT( p_obj, mlnx_fmr_t, obj );\r
125 \r
126         /* Deregister the memory. */\r
127         if( verbs_check_mlnx_fmr( h_fmr ) )\r
128         {\r
129                 status = verbs_destroy_mlnx_fmr( h_fmr );\r
130                 CL_ASSERT( status == IB_SUCCESS );\r
131 \r
132                 h_fmr->h_ci_fmr = NULL;\r
133         }\r
134 }\r
135 \r
136 \r
137 \r
138 static void\r
139 __return_mlnx_fmr(\r
140         IN                              al_obj_t                                        *p_obj )\r
141 {\r
142         mlnx_fmr_handle_t                       h_fmr;\r
143 \r
144         h_fmr = PARENT_STRUCT( p_obj, mlnx_fmr_t, obj );\r
145         reset_al_obj( p_obj );\r
146         put_mlnx_fmr( h_fmr );\r
147 }\r
148 \r
149 \r
150 \r
151 ib_api_status_t\r
152 mlnx_create_fmr(\r
153         IN              const   ib_pd_handle_t                          h_pd,\r
154         IN              const   mlnx_fmr_create_t*      const   p_fmr_create,\r
155         OUT                             mlnx_fmr_handle_t*      const   ph_fmr )\r
156 {\r
157         mlnx_fmr_handle_t               h_fmr;\r
158         ib_api_status_t                 status;\r
159 \r
160         AL_ENTER( AL_DBG_MR );\r
161 \r
162         if( AL_OBJ_INVALID_HANDLE( h_pd, AL_OBJ_TYPE_H_PD ) )\r
163         {\r
164                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_PD_HANDLE\n") );\r
165                 return IB_INVALID_PD_HANDLE;\r
166         }\r
167 \r
168         if( !p_fmr_create || !ph_fmr )\r
169         {\r
170                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_PARAMETER\n") );\r
171                 return IB_INVALID_PARAMETER;\r
172         }\r
173 \r
174         /* Get a MR tracking structure. */\r
175         h_fmr = alloc_mlnx_fmr();\r
176         if( !h_fmr )\r
177         {\r
178                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl,\r
179                         ("unable to allocate memory handle\n") );\r
180                 return IB_INSUFFICIENT_MEMORY;\r
181         }\r
182 \r
183         status = attach_al_obj( &h_pd->obj, &h_fmr->obj );\r
184         if( status != IB_SUCCESS )\r
185         {\r
186                 h_fmr->obj.pfn_destroy( &h_fmr->obj, NULL );\r
187                 AL_TRACE_EXIT( AL_DBG_ERROR,\r
188                         ("attach_al_obj returned %s.\n", ib_get_err_str(status)) );\r
189                 return status;\r
190         }\r
191 \r
192         /* Register the memory region. */\r
193         status = verbs_create_mlnx_fmr( h_pd, p_fmr_create, h_fmr );\r
194         if( status != IB_SUCCESS )\r
195         {\r
196                 h_fmr->obj.pfn_destroy( &h_fmr->obj, NULL );\r
197                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl,\r
198                         ("unable to register memory: %s\n", ib_get_err_str(status)) );\r
199                 return status;\r
200         }\r
201 \r
202         *ph_fmr = h_fmr;\r
203         deref_al_obj( &(*ph_fmr )->obj );\r
204 \r
205         AL_EXIT( AL_DBG_MR );\r
206         return IB_SUCCESS;\r
207 }\r
208 \r
209 \r
210 ib_api_status_t\r
211 mlnx_map_phys_fmr(\r
212         IN              const   mlnx_fmr_handle_t                       h_fmr,\r
213         IN              const   uint64_t* const                         paddr_list,\r
214         IN              const   int                                                     list_len,\r
215         IN      OUT                     uint64_t* const                         p_vaddr,\r
216                 OUT                     net32_t* const                          p_lkey,\r
217                 OUT                     net32_t* const                          p_rkey)\r
218 {\r
219         ib_api_status_t                 status;\r
220 \r
221         AL_ENTER( AL_DBG_MR );\r
222 \r
223         if( AL_OBJ_INVALID_HANDLE( h_fmr, AL_OBJ_TYPE_H_FMR ) )\r
224         {\r
225                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_FMR_HANDLE\n") );\r
226                 return IB_INVALID_FMR_HANDLE;\r
227         }\r
228 \r
229         if( !paddr_list || !p_vaddr  || !p_lkey || !p_rkey )\r
230         {\r
231                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_PARAMETER\n") );\r
232                 return IB_INVALID_PARAMETER;\r
233         }\r
234 \r
235         ref_al_obj( &h_fmr->obj );\r
236 \r
237         /* Register the memory region. */\r
238         status = verbs_map_phys_mlnx_fmr( h_fmr, paddr_list, list_len, p_vaddr, p_lkey, p_rkey);\r
239         if( status != IB_SUCCESS )\r
240         {\r
241                 //TODO: do we need to do something more about the error ?\r
242                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl,\r
243                         ("unable to map FMR: %s\n", ib_get_err_str(status)) );\r
244         }\r
245 \r
246         deref_al_obj( &h_fmr->obj );\r
247 \r
248         AL_EXIT( AL_DBG_MR );\r
249         return status;\r
250 }\r
251 \r
252 \r
253 ib_api_status_t\r
254 mlnx_unmap_fmr(\r
255         IN              const   mlnx_fmr_handle_t                               h_fmr )\r
256 {\r
257         ib_api_status_t         status;\r
258 \r
259         AL_ENTER( AL_DBG_MR );\r
260 \r
261         if( AL_OBJ_INVALID_HANDLE( h_fmr, AL_OBJ_TYPE_H_FMR ) )\r
262         {\r
263                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_FMR_HANDLE\n") );\r
264                 return IB_INVALID_FMR_HANDLE;\r
265         }\r
266 \r
267         ref_al_obj( &h_fmr->obj );\r
268         status = verbs_unmap_mlnx_fmr( h_fmr );\r
269         deref_al_obj( &h_fmr->obj );\r
270 \r
271         AL_EXIT( AL_DBG_MR );\r
272         return status;\r
273 }\r
274 \r
275 \r
276 ib_api_status_t\r
277 mlnx_destroy_fmr(\r
278         IN              const   mlnx_fmr_handle_t                               h_fmr )\r
279 {\r
280         ib_api_status_t         status;\r
281 \r
282         AL_ENTER( AL_DBG_MR );\r
283 \r
284         if( AL_OBJ_INVALID_HANDLE( h_fmr, AL_OBJ_TYPE_H_FMR ) )\r
285         {\r
286                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_FMR_HANDLE\n") );\r
287                 return IB_INVALID_FMR_HANDLE;\r
288         }\r
289 \r
290         if( !verbs_check_mlnx_fmr( h_fmr ) )\r
291         {\r
292                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_FMR_HANDLE\n") );\r
293                 return IB_INVALID_FMR_HANDLE;\r
294         }\r
295 \r
296         ref_al_obj( &h_fmr->obj );\r
297 \r
298         /* FMR's are destroyed synchronously */\r
299         status = verbs_destroy_mlnx_fmr( h_fmr );\r
300 \r
301         if( status == IB_SUCCESS )\r
302         {\r
303                 h_fmr->h_ci_fmr = NULL;\r
304                 /* We're good to destroy the object. */\r
305                 h_fmr->obj.pfn_destroy( &h_fmr->obj, NULL );\r
306         }\r
307         deref_al_obj( &h_fmr->obj );\r
308 \r
309         AL_EXIT( AL_DBG_MR );\r
310         return status;\r
311 }\r
312 \r
313 \r
314 \r
315 ib_api_status_t\r
316 ib_create_shmid(\r
317         IN              const   ib_pd_handle_t                          h_pd,\r
318         IN              const   int                                                     shmid,\r
319         IN              const   ib_mr_create_t* const           p_mr_create,\r
320                 OUT                     net32_t* const                          p_lkey,\r
321                 OUT                     net32_t* const                          p_rkey,\r
322                 OUT                     ib_mr_handle_t* const           ph_mr )\r
323 {\r
324         ib_api_status_t         status;\r
325         cl_status_t                     cl_status;\r
326         net32_t                         lkey;\r
327         net32_t                         rkey;\r
328         ib_mr_handle_t          h_mr;\r
329 \r
330         CL_ENTER( AL_DBG_MR, g_al_dbg_lvl );\r
331 \r
332         if( AL_OBJ_INVALID_HANDLE( h_pd, AL_OBJ_TYPE_H_PD ) )\r
333         {\r
334                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_PD_HANDLE\n") );\r
335                 return IB_INVALID_PD_HANDLE;\r
336         }\r
337         if( !p_mr_create || !p_lkey || !p_rkey || !ph_mr )\r
338         {\r
339                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_PARAMETER\n") );\r
340                 return IB_INVALID_PARAMETER;\r
341         }\r
342 \r
343         /* Register the memory region. */\r
344         status = ib_reg_mem( h_pd, p_mr_create, &lkey, &rkey, &h_mr );\r
345         if( status != IB_SUCCESS )\r
346         {\r
347                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl,\r
348                         ("unable to register memory: %s\n", ib_get_err_str(status)) );\r
349                 return status;\r
350         }\r
351 \r
352         /* Create the shmid tracking structure. */\r
353         h_mr->p_shmid = __create_shmid( shmid );\r
354         if( !h_mr->p_shmid )\r
355         {\r
356                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl,\r
357                         ("unable to allocate shmid\n") );\r
358                 ib_dereg_mr( h_mr );\r
359                 return IB_INSUFFICIENT_MEMORY;\r
360         }\r
361 \r
362         /*\r
363          * Record that the memory region is associated with this shmid.  The\r
364          * insertion should automatically succeed since the list has a minimum\r
365          * size of 1.\r
366          */\r
367         ref_al_obj( &h_mr->p_shmid->obj );\r
368         cl_status = cl_list_insert_head( &h_mr->p_shmid->mr_list, h_mr );\r
369         CL_ASSERT( cl_status == CL_SUCCESS );\r
370 \r
371         /* Add the shmid to the CI CA for tracking. */\r
372         add_shmid( h_pd->obj.p_ci_ca, h_mr->p_shmid );\r
373 \r
374         /* Return the results. */\r
375         *p_lkey = lkey;\r
376         *p_rkey = rkey;\r
377         *ph_mr = h_mr;\r
378         CL_EXIT( AL_DBG_MR, g_al_dbg_lvl );\r
379         return IB_SUCCESS;\r
380 }\r
381 \r
382 \r
383 \r
384 /*\r
385  * Allocate a new structure to track memory registrations shared across\r
386  * processes.\r
387  */\r
388 static al_shmid_t*\r
389 __create_shmid(\r
390         IN              const   int                                                     shmid )\r
391 {\r
392         al_shmid_t                      *p_shmid;\r
393         ib_api_status_t         status;\r
394         cl_status_t                     cl_status;\r
395 \r
396         /* Allocate the shmid structure. */\r
397         p_shmid = cl_zalloc( sizeof( al_shmid_t ) );\r
398         if( !p_shmid )\r
399         {\r
400                 return NULL;\r
401         }\r
402 \r
403         /* Construct the shmid structure. */\r
404         construct_al_obj( &p_shmid->obj, AL_OBJ_TYPE_H_MR );\r
405         cl_list_construct( &p_shmid->mr_list );\r
406 \r
407         /* Initialize the shmid structure. */\r
408         status = init_al_obj( &p_shmid->obj, p_shmid, TRUE,\r
409                 NULL, NULL, __free_shmid );\r
410         if( status != IB_SUCCESS )\r
411         {\r
412                 __free_shmid( &p_shmid->obj );\r
413                 return NULL;\r
414         }\r
415 \r
416         cl_status = cl_list_init( &p_shmid->mr_list, 1 );\r
417         if( cl_status != CL_SUCCESS )\r
418         {\r
419                 p_shmid->obj.pfn_destroy( &p_shmid->obj, NULL );\r
420                 return NULL;\r
421         }\r
422 \r
423         p_shmid->id = shmid;\r
424 \r
425         /* Release the reference taken in init_al_obj. */\r
426         deref_al_obj( &p_shmid->obj );\r
427 \r
428         return p_shmid;\r
429 }\r
430 \r
431 \r
432 \r
433 static void\r
434 __free_shmid(\r
435         IN                              struct _al_obj                          *p_obj )\r
436 {\r
437         al_shmid_t                      *p_shmid;\r
438 \r
439         p_shmid = PARENT_STRUCT( p_obj, al_shmid_t, obj );\r
440 \r
441         CL_ASSERT( cl_is_list_empty( &p_shmid->mr_list ) );\r
442 \r
443         cl_list_destroy( &p_shmid->mr_list );\r
444         destroy_al_obj( p_obj );\r
445         cl_free( p_shmid );\r
446 }\r
447 \r
448 \r
449 \r
450 ib_api_status_t\r
451 ib_reg_shmid(\r
452         IN              const   ib_pd_handle_t                          h_pd,\r
453         IN              const   ib_shmid_t                                      shmid,\r
454         IN              const   ib_mr_create_t* const           p_mr_create,\r
455         IN      OUT                     uint64_t* const                         p_vaddr,\r
456                 OUT                     net32_t* const                          p_lkey,\r
457                 OUT                     net32_t* const                          p_rkey,\r
458                 OUT                     ib_mr_handle_t* const           ph_mr )\r
459 {\r
460         return reg_shmid( h_pd, shmid, p_mr_create, p_vaddr, p_lkey, p_rkey, ph_mr );\r
461 }\r
462 \r
463 \r
464 ib_api_status_t\r
465 reg_shmid(\r
466         IN              const   ib_pd_handle_t                          h_pd,\r
467         IN              const   ib_shmid_t                                      shmid,\r
468         IN              const   ib_mr_create_t* const           p_mr_create,\r
469         IN      OUT                     uint64_t* const                         p_vaddr,\r
470                 OUT                     net32_t* const                          p_lkey,\r
471                 OUT                     net32_t* const                          p_rkey,\r
472                 OUT                     ib_mr_handle_t* const           ph_mr )\r
473 {\r
474         UNUSED_PARAM( h_pd );\r
475         UNUSED_PARAM( shmid );\r
476         UNUSED_PARAM( p_mr_create );\r
477         UNUSED_PARAM( p_vaddr );\r
478         UNUSED_PARAM( p_lkey );\r
479         UNUSED_PARAM( p_rkey );\r
480         UNUSED_PARAM( ph_mr );\r
481         return IB_ERROR;\r
482 #if 0\r
483         ib_api_status_t         status;\r
484         cl_status_t                     cl_status;\r
485         al_shmid_t                      *p_shmid;\r
486         uint64_t                        vaddr;\r
487         net32_t                         lkey;\r
488         net32_t                         rkey;\r
489         ib_mr_handle_t          h_mr, h_reg_mr;\r
490 \r
491         CL_ENTER( AL_DBG_MR, g_al_dbg_lvl );\r
492 \r
493         if( AL_OBJ_INVALID_HANDLE( h_pd, AL_OBJ_TYPE_H_PD ) )\r
494         {\r
495                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_PD_HANDLE\n") );\r
496                 return IB_INVALID_PD_HANDLE;\r
497         }\r
498         if( !p_vaddr || !p_lkey || !p_rkey || !ph_mr )\r
499         {\r
500                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_PARAMETER\n") );\r
501                 return IB_INVALID_PARAMETER;\r
502         }\r
503 \r
504         /* Let's see if we can acquire the registered memory region. */\r
505         status = acquire_shmid( h_pd->obj.p_ci_ca, shmid, &p_shmid );\r
506         if( status != IB_SUCCESS )\r
507         {\r
508                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl,\r
509                         ("shmid not found: %s\n", ib_get_err_str(status)) );\r
510                 return IB_NOT_FOUND;\r
511         }\r
512 \r
513         /* Lock down the shmid to prevent deregistrations while we register. */\r
514         cl_spinlock_acquire( &p_shmid->obj.lock );\r
515 \r
516         /*\r
517          * There's a chance after we acquired the shmid, all current\r
518          * registrations were deregistered.\r
519          */\r
520         if( cl_is_list_empty( &p_shmid->mr_list ) )\r
521         {\r
522                 /* There are no registrations left to share. */\r
523                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("shmid not found\n") );\r
524                 cl_spinlock_release( &p_shmid->obj.lock );\r
525                 release_shmid( p_shmid );\r
526                 return IB_NOT_FOUND;\r
527         }\r
528 \r
529         /* Get a handle to an existing registered memory region. */\r
530         h_reg_mr = cl_list_obj( cl_list_head( &p_shmid->mr_list ) );\r
531 \r
532 // BUGBUG: This release is not safe since the h_reg_mr can be deregistered.\r
533         cl_spinlock_release( &p_shmid->obj.lock );\r
534 \r
535         /* Register the memory region. */\r
536         vaddr = *p_vaddr;\r
537         status = ib_reg_shared( h_reg_mr, h_pd, access_ctrl, &vaddr,\r
538                 &lkey, &rkey, &h_mr );\r
539         if( status != IB_SUCCESS )\r
540         {\r
541                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl,\r
542                         ("unable to register shared memory: 0x%0"PRIx64" %s\n",\r
543                                 vaddr, ib_get_err_str(status)) );\r
544                 release_shmid( p_shmid );\r
545                 return status;\r
546         }\r
547 \r
548         cl_spinlock_acquire( &p_shmid->obj.lock );\r
549 \r
550         /* Track the registration with the shmid structure. */\r
551         cl_status = cl_list_insert_head( &p_shmid->mr_list, h_mr );\r
552         if( cl_status != CL_SUCCESS )\r
553         {\r
554                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl,\r
555                         ("insertion into shmid list failed\n") );\r
556                 cl_spinlock_release( &p_shmid->obj.lock );\r
557                 release_shmid( p_shmid );\r
558                 return ib_convert_cl_status( cl_status );\r
559         }\r
560 \r
561         cl_spinlock_release( &p_shmid->obj.lock );\r
562 \r
563         /* Return the results. */\r
564         h_mr->p_shmid = p_shmid;\r
565         *p_vaddr = vaddr;\r
566         *p_lkey = lkey;\r
567         *p_rkey = rkey;\r
568         *ph_mr = h_mr;\r
569         CL_EXIT( AL_DBG_MR, g_al_dbg_lvl );\r
570         return IB_SUCCESS;\r
571 #endif\r
572 }\r