2 * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.
\r
3 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
\r
5 * This software is available to you under the OpenIB.org BSD license
\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
12 * - Redistributions of source code must retain the above
\r
13 * copyright notice, this list of conditions and the following
\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
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
33 #include <iba/ib_al.h>
\r
35 #include "al_debug.h"
\r
36 #if defined(EVENT_TRACING)
\r
40 #include "al_mr.tmh"
\r
44 #include "al_res_mgr.h"
\r
45 #include "al_verbs.h"
\r
47 #include "ib_common.h"
\r
52 IN struct _al_obj *p_obj );
\r
56 IN al_obj_t *p_obj );
\r
61 IN const int shmid );
\r
65 IN struct _al_obj *p_obj );
\r
70 IN void* const p_object,
\r
72 OUT cl_pool_item_t** const pp_pool_item )
\r
74 ib_api_status_t status;
\r
75 mlnx_fmr_handle_t h_fmr;
\r
77 UNUSED_PARAM( context );
\r
79 h_fmr = (mlnx_fmr_handle_t)p_object;
\r
80 cl_memclr( h_fmr, sizeof(mlnx_fmr_t) );
\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
90 *pp_pool_item = &((mlnx_fmr_handle_t)p_object)->obj.pool_item;
\r
92 /* Release the reference taken in init_al_obj. */
\r
93 deref_al_obj( &h_fmr->obj );
\r
102 IN const cl_pool_item_t* const p_pool_item,
\r
107 UNUSED_PARAM( context );
\r
109 p_obj = PARENT_STRUCT( p_pool_item, al_obj_t, pool_item );
\r
112 * The FMR is being totally destroyed. Modify the free_cb to destroy the
\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
123 __cleanup_mlnx_fmr(
\r
124 IN struct _al_obj *p_obj )
\r
126 ib_api_status_t status;
\r
127 mlnx_fmr_handle_t h_fmr;
\r
129 CL_ASSERT( p_obj );
\r
130 h_fmr = PARENT_STRUCT( p_obj, mlnx_fmr_t, obj );
\r
132 /* Deregister the memory. */
\r
133 if( verbs_check_mlnx_fmr( h_fmr ) )
\r
135 status = verbs_destroy_mlnx_fmr( h_fmr );
\r
136 CL_ASSERT( status == IB_SUCCESS );
\r
138 h_fmr->h_ci_fmr = NULL;
\r
146 IN al_obj_t *p_obj )
\r
148 mlnx_fmr_handle_t h_fmr;
\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
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
163 mlnx_fmr_handle_t h_fmr;
\r
164 ib_api_status_t status;
\r
166 AL_ENTER( AL_DBG_MR );
\r
168 if( AL_OBJ_INVALID_HANDLE( h_pd, AL_OBJ_TYPE_H_PD ) )
\r
170 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_PD_HANDLE\n") );
\r
171 return IB_INVALID_PD_HANDLE;
\r
174 if( !p_fmr_create || !ph_fmr )
\r
176 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_PARAMETER\n") );
\r
177 return IB_INVALID_PARAMETER;
\r
180 /* Get a MR tracking structure. */
\r
181 h_fmr = alloc_mlnx_fmr();
\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
189 status = attach_al_obj( &h_pd->obj, &h_fmr->obj );
\r
190 if( status != IB_SUCCESS )
\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
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
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
209 /* Release the reference taken in alloc_mlnx_fmr for initialization. */
\r
210 deref_al_obj( &(*ph_fmr )->obj );
\r
212 AL_EXIT( AL_DBG_MR );
\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
226 ib_api_status_t status;
\r
228 AL_ENTER( AL_DBG_MR );
\r
230 if( AL_OBJ_INVALID_HANDLE( h_fmr, AL_OBJ_TYPE_H_FMR ) )
\r
232 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_FMR_HANDLE\n") );
\r
233 return IB_INVALID_FMR_HANDLE;
\r
236 if( !paddr_list || !p_vaddr || !p_lkey || !p_rkey )
\r
238 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_PARAMETER\n") );
\r
239 return IB_INVALID_PARAMETER;
\r
242 ref_al_obj( &h_fmr->obj );
\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
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
253 deref_al_obj( &h_fmr->obj );
\r
255 AL_EXIT( AL_DBG_MR );
\r
262 IN const mlnx_fmr_handle_t h_fmr )
\r
264 ib_api_status_t status;
\r
266 AL_ENTER( AL_DBG_MR );
\r
268 if( AL_OBJ_INVALID_HANDLE( h_fmr, AL_OBJ_TYPE_H_FMR ) )
\r
270 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_FMR_HANDLE\n") );
\r
271 return IB_INVALID_FMR_HANDLE;
\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
278 AL_EXIT( AL_DBG_MR );
\r
285 IN const mlnx_fmr_handle_t h_fmr )
\r
287 ib_api_status_t status;
\r
289 AL_ENTER( AL_DBG_MR );
\r
291 if( AL_OBJ_INVALID_HANDLE( h_fmr, AL_OBJ_TYPE_H_FMR ) )
\r
293 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_FMR_HANDLE\n") );
\r
294 return IB_INVALID_FMR_HANDLE;
\r
297 if( !verbs_check_mlnx_fmr( h_fmr ) )
\r
299 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_FMR_HANDLE\n") );
\r
300 return IB_INVALID_FMR_HANDLE;
\r
303 ref_al_obj( &h_fmr->obj );
\r
305 /* FMR's are destroyed synchronously */
\r
306 status = verbs_destroy_mlnx_fmr( h_fmr );
\r
308 if( status == IB_SUCCESS )
\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
315 h_fmr->obj.pfn_destroy( &h_fmr->obj, NULL );
\r
317 deref_al_obj( &h_fmr->obj );
\r
319 AL_EXIT( AL_DBG_MR );
\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
334 ib_api_status_t status;
\r
335 cl_status_t cl_status;
\r
338 ib_mr_handle_t h_mr;
\r
340 AL_ENTER( AL_DBG_MR );
\r
342 if( AL_OBJ_INVALID_HANDLE( h_pd, AL_OBJ_TYPE_H_PD ) )
\r
344 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_PD_HANDLE\n") );
\r
345 return IB_INVALID_PD_HANDLE;
\r
347 if( !p_mr_create || !p_lkey || !p_rkey || !ph_mr )
\r
349 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_PARAMETER\n") );
\r
350 return IB_INVALID_PARAMETER;
\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
357 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
\r
358 ("unable to register memory: %s\n", ib_get_err_str(status)) );
\r
362 /* Create the shmid tracking structure. */
\r
363 h_mr->p_shmid = __create_shmid( shmid );
\r
364 if( !h_mr->p_shmid )
\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
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
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
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
384 /* Return the results. */
\r
388 AL_EXIT( AL_DBG_MR );
\r
395 * Allocate a new structure to track memory registrations shared across
\r
400 IN const int shmid )
\r
402 al_shmid_t *p_shmid;
\r
403 ib_api_status_t status;
\r
404 cl_status_t cl_status;
\r
406 /* Allocate the shmid structure. */
\r
407 p_shmid = cl_zalloc( sizeof( al_shmid_t ) );
\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
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
422 __free_shmid( &p_shmid->obj );
\r
426 cl_status = cl_list_init( &p_shmid->mr_list, 1 );
\r
427 if( cl_status != CL_SUCCESS )
\r
429 p_shmid->obj.pfn_destroy( &p_shmid->obj, NULL );
\r
433 p_shmid->id = shmid;
\r
435 /* Release the reference taken in init_al_obj. */
\r
436 deref_al_obj( &p_shmid->obj );
\r
445 IN struct _al_obj *p_obj )
\r
447 al_shmid_t *p_shmid;
\r
449 p_shmid = PARENT_STRUCT( p_obj, al_shmid_t, obj );
\r
451 CL_ASSERT( cl_is_list_empty( &p_shmid->mr_list ) );
\r
453 cl_list_destroy( &p_shmid->mr_list );
\r
454 destroy_al_obj( p_obj );
\r
455 cl_free( p_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
470 return reg_shmid( h_pd, shmid, p_mr_create, p_vaddr, p_lkey, p_rkey, ph_mr );
\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
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
493 ib_api_status_t status;
\r
494 cl_status_t cl_status;
\r
495 al_shmid_t *p_shmid;
\r
499 ib_mr_handle_t h_mr, h_reg_mr;
\r
501 AL_ENTER( AL_DBG_MR );
\r
503 if( AL_OBJ_INVALID_HANDLE( h_pd, AL_OBJ_TYPE_H_PD ) )
\r
505 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_PD_HANDLE\n") );
\r
506 return IB_INVALID_PD_HANDLE;
\r
508 if( !p_vaddr || !p_lkey || !p_rkey || !ph_mr )
\r
510 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_PARAMETER\n") );
\r
511 return IB_INVALID_PARAMETER;
\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
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
523 /* Lock down the shmid to prevent deregistrations while we register. */
\r
524 cl_spinlock_acquire( &p_shmid->obj.lock );
\r
527 * There's a chance after we acquired the shmid, all current
\r
528 * registrations were deregistered.
\r
530 if( cl_is_list_empty( &p_shmid->mr_list ) )
\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
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
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
545 /* Register the memory region. */
\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
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
558 cl_spinlock_acquire( &p_shmid->obj.lock );
\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
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
571 cl_spinlock_release( &p_shmid->obj.lock );
\r
573 /* Return the results. */
\r
574 h_mr->p_shmid = p_shmid;
\r
579 AL_EXIT( AL_DBG_MR );
\r