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