[IBAL] Cleanup syntax of latest destroy FMR changes.
[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         }\r
317         else\r
318         {\r
319                 deref_al_obj( &h_fmr->obj );\r
320         }\r
321         AL_EXIT( AL_DBG_MR );\r
322         return status;\r
323 }\r
324 \r
325 \r
326 \r
327 ib_api_status_t\r
328 ib_create_shmid(\r
329         IN              const   ib_pd_handle_t                          h_pd,\r
330         IN              const   int                                                     shmid,\r
331         IN              const   ib_mr_create_t* const           p_mr_create,\r
332                 OUT                     net32_t* const                          p_lkey,\r
333                 OUT                     net32_t* const                          p_rkey,\r
334                 OUT                     ib_mr_handle_t* const           ph_mr )\r
335 {\r
336         ib_api_status_t         status;\r
337         cl_status_t                     cl_status;\r
338         net32_t                         lkey;\r
339         net32_t                         rkey;\r
340         ib_mr_handle_t          h_mr;\r
341 \r
342         AL_ENTER( AL_DBG_MR );\r
343 \r
344         if( AL_OBJ_INVALID_HANDLE( h_pd, AL_OBJ_TYPE_H_PD ) )\r
345         {\r
346                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_PD_HANDLE\n") );\r
347                 return IB_INVALID_PD_HANDLE;\r
348         }\r
349         if( !p_mr_create || !p_lkey || !p_rkey || !ph_mr )\r
350         {\r
351                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_PARAMETER\n") );\r
352                 return IB_INVALID_PARAMETER;\r
353         }\r
354 \r
355         /* Register the memory region. */\r
356         status = ib_reg_mem( h_pd, p_mr_create, &lkey, &rkey, &h_mr );\r
357         if( status != IB_SUCCESS )\r
358         {\r
359                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
360                         ("unable to register memory: %s\n", ib_get_err_str(status)) );\r
361                 return status;\r
362         }\r
363 \r
364         /* Create the shmid tracking structure. */\r
365         h_mr->p_shmid = __create_shmid( shmid );\r
366         if( !h_mr->p_shmid )\r
367         {\r
368                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
369                         ("unable to allocate shmid\n") );\r
370                 ib_dereg_mr( h_mr );\r
371                 return IB_INSUFFICIENT_MEMORY;\r
372         }\r
373 \r
374         /*\r
375          * Record that the memory region is associated with this shmid.  The\r
376          * insertion should automatically succeed since the list has a minimum\r
377          * size of 1.\r
378          */\r
379         ref_al_obj( &h_mr->p_shmid->obj );\r
380         cl_status = cl_list_insert_head( &h_mr->p_shmid->mr_list, h_mr );\r
381         CL_ASSERT( cl_status == CL_SUCCESS );\r
382 \r
383         /* Add the shmid to the CI CA for tracking. */\r
384         add_shmid( h_pd->obj.p_ci_ca, h_mr->p_shmid );\r
385 \r
386         /* Return the results. */\r
387         *p_lkey = lkey;\r
388         *p_rkey = rkey;\r
389         *ph_mr = h_mr;\r
390         AL_EXIT( AL_DBG_MR );\r
391         return IB_SUCCESS;\r
392 }\r
393 \r
394 \r
395 \r
396 /*\r
397  * Allocate a new structure to track memory registrations shared across\r
398  * processes.\r
399  */\r
400 static al_shmid_t*\r
401 __create_shmid(\r
402         IN              const   int                                                     shmid )\r
403 {\r
404         al_shmid_t                      *p_shmid;\r
405         ib_api_status_t         status;\r
406         cl_status_t                     cl_status;\r
407 \r
408         /* Allocate the shmid structure. */\r
409         p_shmid = cl_zalloc( sizeof( al_shmid_t ) );\r
410         if( !p_shmid )\r
411         {\r
412                 return NULL;\r
413         }\r
414 \r
415         /* Construct the shmid structure. */\r
416         construct_al_obj( &p_shmid->obj, AL_OBJ_TYPE_H_MR );\r
417         cl_list_construct( &p_shmid->mr_list );\r
418 \r
419         /* Initialize the shmid structure. */\r
420         status = init_al_obj( &p_shmid->obj, p_shmid, TRUE,\r
421                 NULL, NULL, __free_shmid );\r
422         if( status != IB_SUCCESS )\r
423         {\r
424                 __free_shmid( &p_shmid->obj );\r
425                 return NULL;\r
426         }\r
427 \r
428         cl_status = cl_list_init( &p_shmid->mr_list, 1 );\r
429         if( cl_status != CL_SUCCESS )\r
430         {\r
431                 p_shmid->obj.pfn_destroy( &p_shmid->obj, NULL );\r
432                 return NULL;\r
433         }\r
434 \r
435         p_shmid->id = shmid;\r
436 \r
437         /* Release the reference taken in init_al_obj. */\r
438         deref_al_obj( &p_shmid->obj );\r
439 \r
440         return p_shmid;\r
441 }\r
442 \r
443 \r
444 \r
445 static void\r
446 __free_shmid(\r
447         IN                              struct _al_obj                          *p_obj )\r
448 {\r
449         al_shmid_t                      *p_shmid;\r
450 \r
451         p_shmid = PARENT_STRUCT( p_obj, al_shmid_t, obj );\r
452 \r
453         CL_ASSERT( cl_is_list_empty( &p_shmid->mr_list ) );\r
454 \r
455         cl_list_destroy( &p_shmid->mr_list );\r
456         destroy_al_obj( p_obj );\r
457         cl_free( p_shmid );\r
458 }\r
459 \r
460 \r
461 \r
462 ib_api_status_t\r
463 ib_reg_shmid(\r
464         IN              const   ib_pd_handle_t                          h_pd,\r
465         IN              const   ib_shmid_t                                      shmid,\r
466         IN              const   ib_mr_create_t* const           p_mr_create,\r
467         IN      OUT                     uint64_t* const                         p_vaddr,\r
468                 OUT                     net32_t* const                          p_lkey,\r
469                 OUT                     net32_t* const                          p_rkey,\r
470                 OUT                     ib_mr_handle_t* const           ph_mr )\r
471 {\r
472         return reg_shmid( h_pd, shmid, p_mr_create, p_vaddr, p_lkey, p_rkey, ph_mr );\r
473 }\r
474 \r
475 \r
476 ib_api_status_t\r
477 reg_shmid(\r
478         IN              const   ib_pd_handle_t                          h_pd,\r
479         IN              const   ib_shmid_t                                      shmid,\r
480         IN              const   ib_mr_create_t* const           p_mr_create,\r
481         IN      OUT                     uint64_t* const                         p_vaddr,\r
482                 OUT                     net32_t* const                          p_lkey,\r
483                 OUT                     net32_t* const                          p_rkey,\r
484                 OUT                     ib_mr_handle_t* const           ph_mr )\r
485 {\r
486         UNUSED_PARAM( h_pd );\r
487         UNUSED_PARAM( shmid );\r
488         UNUSED_PARAM( p_mr_create );\r
489         UNUSED_PARAM( p_vaddr );\r
490         UNUSED_PARAM( p_lkey );\r
491         UNUSED_PARAM( p_rkey );\r
492         UNUSED_PARAM( ph_mr );\r
493         return IB_ERROR;\r
494 #if 0\r
495         ib_api_status_t         status;\r
496         cl_status_t                     cl_status;\r
497         al_shmid_t                      *p_shmid;\r
498         uint64_t                        vaddr;\r
499         net32_t                         lkey;\r
500         net32_t                         rkey;\r
501         ib_mr_handle_t          h_mr, h_reg_mr;\r
502 \r
503         AL_ENTER( AL_DBG_MR );\r
504 \r
505         if( AL_OBJ_INVALID_HANDLE( h_pd, AL_OBJ_TYPE_H_PD ) )\r
506         {\r
507                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_PD_HANDLE\n") );\r
508                 return IB_INVALID_PD_HANDLE;\r
509         }\r
510         if( !p_vaddr || !p_lkey || !p_rkey || !ph_mr )\r
511         {\r
512                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_PARAMETER\n") );\r
513                 return IB_INVALID_PARAMETER;\r
514         }\r
515 \r
516         /* Let's see if we can acquire the registered memory region. */\r
517         status = acquire_shmid( h_pd->obj.p_ci_ca, shmid, &p_shmid );\r
518         if( status != IB_SUCCESS )\r
519         {\r
520                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
521                         ("shmid not found: %s\n", ib_get_err_str(status)) );\r
522                 return IB_NOT_FOUND;\r
523         }\r
524 \r
525         /* Lock down the shmid to prevent deregistrations while we register. */\r
526         cl_spinlock_acquire( &p_shmid->obj.lock );\r
527 \r
528         /*\r
529          * There's a chance after we acquired the shmid, all current\r
530          * registrations were deregistered.\r
531          */\r
532         if( cl_is_list_empty( &p_shmid->mr_list ) )\r
533         {\r
534                 /* There are no registrations left to share. */\r
535                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("shmid not found\n") );\r
536                 cl_spinlock_release( &p_shmid->obj.lock );\r
537                 release_shmid( p_shmid );\r
538                 return IB_NOT_FOUND;\r
539         }\r
540 \r
541         /* Get a handle to an existing registered memory region. */\r
542         h_reg_mr = cl_list_obj( cl_list_head( &p_shmid->mr_list ) );\r
543 \r
544 // BUGBUG: This release is not safe since the h_reg_mr can be deregistered.\r
545         cl_spinlock_release( &p_shmid->obj.lock );\r
546 \r
547         /* Register the memory region. */\r
548         vaddr = *p_vaddr;\r
549         status = ib_reg_shared( h_reg_mr, h_pd, access_ctrl, &vaddr,\r
550                 &lkey, &rkey, &h_mr );\r
551         if( status != IB_SUCCESS )\r
552         {\r
553                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
554                         ("unable to register shared memory: 0x%0I64x %s\n",\r
555                                 vaddr, ib_get_err_str(status)) );\r
556                 release_shmid( p_shmid );\r
557                 return status;\r
558         }\r
559 \r
560         cl_spinlock_acquire( &p_shmid->obj.lock );\r
561 \r
562         /* Track the registration with the shmid structure. */\r
563         cl_status = cl_list_insert_head( &p_shmid->mr_list, h_mr );\r
564         if( cl_status != CL_SUCCESS )\r
565         {\r
566                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
567                         ("insertion into shmid list failed\n") );\r
568                 cl_spinlock_release( &p_shmid->obj.lock );\r
569                 release_shmid( p_shmid );\r
570                 return ib_convert_cl_status( cl_status );\r
571         }\r
572 \r
573         cl_spinlock_release( &p_shmid->obj.lock );\r
574 \r
575         /* Return the results. */\r
576         h_mr->p_shmid = p_shmid;\r
577         *p_vaddr = vaddr;\r
578         *p_lkey = lkey;\r
579         *p_rkey = rkey;\r
580         *ph_mr = h_mr;\r
581         AL_EXIT( AL_DBG_MR );\r
582         return IB_SUCCESS;\r
583 #endif\r
584 }\r