707e334bfc947ccd1170001c88ce6102b0fc19c5
[mirror/winof/.git] / core / al / kernel / al_mgr.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  * 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$\r
32  */\r
33 \r
34 #include <complib/cl_atomic.h>\r
35 #include <complib/cl_async_proc.h>\r
36 #include <complib/cl_memory.h>\r
37 #include <complib/cl_qlist.h>\r
38 #include <complib/cl_spinlock.h>\r
39 #include <complib/cl_vector.h>\r
40 \r
41 #include <iba/ib_ci.h>\r
42 \r
43 #include "al.h"\r
44 #include "al_cm_cep.h"\r
45 #include "al_debug.h"\r
46 \r
47 #if defined(EVENT_TRACING)\r
48 #ifdef offsetof\r
49 #undef offsetof\r
50 #endif\r
51 #include "al_mgr.tmh"\r
52 #endif\r
53 \r
54 #include "al_dm.h"\r
55 #include "al_mad_pool.h"\r
56 #include "al_mcast.h"\r
57 #include "al_mgr.h"\r
58 #include "al_pnp.h"\r
59 #include "al_ioc_pnp.h"\r
60 #include "al_query.h"\r
61 #include "al_res_mgr.h"\r
62 #include "al_smi.h"\r
63 #include "ib_common.h"\r
64 \r
65 #ifndef CL_KERNEL\r
66 #include "ual_mgr.h"\r
67 #endif\r
68 \r
69 \r
70 #define AL_HDL_VECTOR_MIN       64\r
71 #define AL_HDL_VECTOR_GROW      64\r
72 \r
73 \r
74 static void\r
75 __free_al_mgr(\r
76         IN                              al_obj_t                                        *p_obj );\r
77 \r
78 void\r
79 free_al(\r
80         IN                              al_obj_t                                        *p_obj );\r
81 \r
82 \r
83 \r
84 ib_api_status_t\r
85 create_al_mgr()\r
86 {\r
87         cl_status_t                             cl_status;\r
88         ib_api_status_t                 status;\r
89 \r
90         AL_ENTER( AL_DBG_MGR );\r
91 \r
92         CL_ASSERT( !gp_al_mgr );\r
93 \r
94         gp_al_mgr = cl_zalloc( sizeof( al_mgr_t ) );\r
95         if( !gp_al_mgr )\r
96         {\r
97                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("cl_zalloc failed.\n") );\r
98                 return IB_INSUFFICIENT_MEMORY;\r
99         }\r
100 \r
101         /* Construct the AL manager components. */\r
102         cl_qlist_init( &gp_al_mgr->ci_ca_list );\r
103         cl_qlist_init( &gp_al_mgr->al_obj_list );\r
104         cl_spinlock_construct( &gp_al_mgr->lock );\r
105 \r
106         /* Initialize the AL management components. */\r
107         construct_al_obj( &gp_al_mgr->obj, AL_OBJ_TYPE_AL_MGR );\r
108         status = init_al_obj( &gp_al_mgr->obj, gp_al_mgr, FALSE,\r
109                 NULL, NULL, __free_al_mgr );\r
110         if( status != IB_SUCCESS )\r
111         {\r
112                 __free_al_mgr( &gp_al_mgr->obj );\r
113                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
114                         ("init_al_obj failed, status = 0x%x.\n", status) );\r
115                 return status;\r
116         }\r
117 \r
118         cl_status = cl_spinlock_init( &gp_al_mgr->lock );\r
119         if( cl_status != CL_SUCCESS )\r
120         {\r
121                 gp_al_mgr->obj.pfn_destroy( &gp_al_mgr->obj, NULL );\r
122                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
123                         ("cl_spinlock_init failed\n") );\r
124                 return ib_convert_cl_status( cl_status );\r
125         }\r
126 \r
127         /* We should be able to open AL now. */\r
128         status = ib_open_al( &gh_al );\r
129         if( status != IB_SUCCESS )\r
130         {\r
131                 gp_al_mgr->obj.pfn_destroy( &gp_al_mgr->obj, NULL );\r
132                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
133                         ("ib_open_al failed, status = 0x%x.\n", status) );\r
134                 return status;\r
135         }\r
136 \r
137         /*\r
138          * Initialize the AL management services.\r
139          * Create the PnP manager first - the other services depend on PnP.\r
140          */\r
141         status = create_pnp( &gp_al_mgr->obj );\r
142         if( status != IB_SUCCESS )\r
143         {\r
144                 gp_al_mgr->obj.pfn_destroy( &gp_al_mgr->obj, NULL );\r
145                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
146                         ("al_pnp_create failed with %s.\n", ib_get_err_str(status)) );\r
147                 return status;\r
148         }\r
149 \r
150         /* Create the global AL MAD pool. */\r
151         status = ib_create_mad_pool( gh_al, 0, 0, 64, &gh_mad_pool );\r
152         if( status != IB_SUCCESS )\r
153         {\r
154                 gp_al_mgr->obj.pfn_destroy( &gp_al_mgr->obj, NULL );\r
155                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
156                         ("ib_create_mad_pool failed with %s.\n", ib_get_err_str(status)) );\r
157                 return status;\r
158         }\r
159 \r
160         /* Initialize the AL resource manager. */\r
161         status = create_res_mgr( &gp_al_mgr->obj );\r
162         if( status != IB_SUCCESS )\r
163         {\r
164                 gp_al_mgr->obj.pfn_destroy( &gp_al_mgr->obj, NULL );\r
165                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
166                         ("create_res_mgr failed with %s.\n", ib_get_err_str(status)) );\r
167                 return status;\r
168         }\r
169 \r
170         /* Initialize the AL special QP manager. */\r
171         status = create_spl_qp_mgr( &gp_al_mgr->obj );\r
172         if( status != IB_SUCCESS )\r
173         {\r
174                 gp_al_mgr->obj.pfn_destroy( &gp_al_mgr->obj, NULL );\r
175                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
176                         ("create_spl_qp_mgr failed with %s.\n", ib_get_err_str(status)) );\r
177                 return status;\r
178         }\r
179 \r
180         /* Initialize the AL SA request manager. */\r
181         status = create_sa_req_mgr( &gp_al_mgr->obj );\r
182         if( status != IB_SUCCESS )\r
183         {\r
184                 gp_al_mgr->obj.pfn_destroy( &gp_al_mgr->obj, NULL );\r
185                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
186                         ("create_sa_req_mgr failed, status = 0x%x.\n", status) );\r
187                 return status;\r
188         }\r
189 \r
190         /* Initialize CM */\r
191         status = create_cep_mgr( &gp_al_mgr->obj );\r
192         if( status != IB_SUCCESS )\r
193         {\r
194                 gp_al_mgr->obj.pfn_destroy( &gp_al_mgr->obj, NULL );\r
195                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
196                         ("create_cm_mgr failed, status = 0x%x.\n", status) );\r
197                 return status;\r
198         }\r
199 \r
200         /* Initialize the AL device management agent. */\r
201 \r
202 /*\r
203         Disable support of DM agent.\r
204 \r
205         status = create_dm_agent( &gp_al_mgr->obj );\r
206         if( status != IB_SUCCESS )\r
207         {\r
208                 gp_al_mgr->obj.pfn_destroy( &gp_al_mgr->obj, NULL );\r
209                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
210                         ("create_dm_agent failed, status = 0x%x.\n", status) );\r
211                 return status;\r
212         }\r
213 */\r
214         status = create_ioc_pnp( &gp_al_mgr->obj );\r
215         if( status != IB_SUCCESS )\r
216         {\r
217                 gp_al_mgr->obj.pfn_destroy( &gp_al_mgr->obj, NULL );\r
218                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
219                         ("create_ioc_pnp failed, status = 0x%x.\n", status) );\r
220                 return status;\r
221         }\r
222 \r
223         /* Release the reference taken in init_al_obj. */\r
224         deref_al_obj( &gp_al_mgr->obj );\r
225 \r
226         AL_EXIT( AL_DBG_MGR );\r
227         return IB_SUCCESS;\r
228 }\r
229 \r
230 \r
231 \r
232 static void\r
233 __free_al_mgr(\r
234         IN                              al_obj_t                                        *p_obj )\r
235 {\r
236         CL_ASSERT( p_obj == &gp_al_mgr->obj );\r
237 \r
238         /*\r
239          * We need to destroy the AL object before the spinlock, since\r
240          * destroying the AL object will try to acquire the spinlock.\r
241          */\r
242         destroy_al_obj( p_obj );\r
243 \r
244         /* Verify that the object list is empty. */\r
245         print_al_objs( NULL );\r
246 \r
247         cl_spinlock_destroy( &gp_al_mgr->lock );\r
248         cl_free( gp_al_mgr );\r
249         gp_al_mgr = NULL;\r
250 }\r
251 \r
252 \r
253 \r
254 /*\r
255  * Register a new CI CA with the access layer.\r
256  */\r
257 ib_api_status_t\r
258 ib_register_ca(\r
259         IN              const   ci_interface_t*                         p_ci,\r
260         IN              const   PDEVICE_OBJECT                          p_hca_dev\r
261         )\r
262 {\r
263         ib_api_status_t         status;\r
264 \r
265         AL_ENTER( AL_DBG_MGR );\r
266 \r
267         if( !p_ci )\r
268         {\r
269                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_PARAMETER\n") );\r
270                 return IB_INVALID_PARAMETER;\r
271         }\r
272         CL_ASSERT( !find_ci_ca( p_ci->guid ) );\r
273 \r
274         AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_MGR,\r
275                 ("CA guid %I64x.\n", p_ci->guid) );\r
276 \r
277         /* Check the channel interface verbs version. */\r
278         if( p_ci->version != VERBS_VERSION )\r
279         {\r
280                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
281                         ("Unsupported channel interface version, "\r
282                          "expected = 0x%x, actual = 0x%x.\n",\r
283                          VERBS_VERSION, p_ci->version) );\r
284                 return IB_UNSUPPORTED;\r
285         }\r
286 \r
287         /* Construct and initialize the CA structure. */\r
288         status = create_ci_ca( &gp_al_mgr->obj, p_ci, p_hca_dev );\r
289         if( status != IB_SUCCESS )\r
290         {\r
291                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
292                         ("al_mgr_ca_init failed.\n") );\r
293                 return status;\r
294         }\r
295 \r
296         AL_EXIT( AL_DBG_MGR );\r
297         return status;\r
298 }\r
299 \r
300 \r
301 \r
302 /*\r
303  * Process the removal of a CI CA from the system.\r
304  */\r
305 ib_api_status_t\r
306 ib_deregister_ca(\r
307         IN              const   net64_t                                         ca_guid )\r
308 {\r
309         al_ci_ca_t                      *p_ci_ca;\r
310 \r
311         AL_ENTER( AL_DBG_MGR );\r
312 \r
313         AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_MGR,\r
314                 ("Deregistering CA guid %I64x.\n", ca_guid) );\r
315 \r
316         /* Locate the CA. */\r
317         cl_spinlock_acquire( &gp_al_mgr->obj.lock );\r
318         p_ci_ca = find_ci_ca( ca_guid );\r
319         cl_spinlock_release( &gp_al_mgr->obj.lock );\r
320 \r
321         if( !p_ci_ca )\r
322         {\r
323                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("CA not found.\n") );\r
324                 return IB_NOT_FOUND;\r
325         }\r
326 \r
327         /*\r
328          * TODO: Before destroying, do a query PnP call and return IB_BUSY\r
329          * as needed.\r
330          */\r
331         /* Destroy the CI CA. */\r
332         ref_al_obj( &p_ci_ca->obj );\r
333         p_ci_ca->obj.pfn_destroy( &p_ci_ca->obj, NULL );\r
334 \r
335         AL_EXIT( AL_DBG_MGR );\r
336         return IB_SUCCESS;\r
337 }\r
338 \r
339 \r
340 /*\r
341  * Initialize a proxy entry used to map user-mode to kernel-mode resources.\r
342  */\r
343 static cl_status_t\r
344 __init_hdl(\r
345         IN              void* const                                             p_element,\r
346         IN              void*                                                   context )\r
347 {\r
348         al_handle_t             *p_h;\r
349 \r
350         p_h = (al_handle_t*)p_element;\r
351 \r
352         /* Chain free entries one after another. */\r
353         p_h->p_obj = (al_obj_t*)(uintn_t)++(((ib_al_handle_t)context)->free_hdl);\r
354         p_h->type = AL_OBJ_TYPE_UNKNOWN;\r
355 \r
356         return CL_SUCCESS;\r
357 }\r
358 \r
359 \r
360 /*\r
361  * Create a new instance of the access layer.  This function is placed here\r
362  * to prevent sharing the implementation with user-mode.\r
363  */\r
364 ib_api_status_t\r
365 ib_open_al(\r
366                 OUT                     ib_al_handle_t* const           ph_al )\r
367 {\r
368         ib_al_handle_t                  h_al;\r
369         ib_api_status_t                 status;\r
370         cl_status_t                             cl_status;\r
371 \r
372         AL_ENTER( AL_DBG_MGR );\r
373 \r
374         if( !ph_al )\r
375         {\r
376                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_PARAMETER\n") );\r
377                 return IB_INVALID_PARAMETER;\r
378         }\r
379 \r
380         /* Allocate an access layer instance. */\r
381         h_al = cl_zalloc( sizeof( ib_al_t ) );\r
382         if( !h_al )\r
383         {\r
384                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("cl_zalloc failed\n") );\r
385                 return IB_INSUFFICIENT_MEMORY;\r
386         }\r
387 \r
388         /* Construct the instance. */\r
389         construct_al_obj( &h_al->obj, AL_OBJ_TYPE_H_AL );\r
390         cl_spinlock_construct( &h_al->mad_lock );\r
391         cl_qlist_init( &h_al->mad_list );\r
392         cl_qlist_init( &h_al->key_list );\r
393         cl_qlist_init( &h_al->query_list );\r
394         cl_qlist_init( &h_al->cep_list );\r
395 \r
396         cl_vector_construct( &h_al->hdl_vector );\r
397 \r
398         cl_status = cl_spinlock_init( &h_al->mad_lock );\r
399         if( cl_status != CL_SUCCESS )\r
400         {\r
401                 free_al( &h_al->obj );\r
402                 AL_EXIT( AL_DBG_MGR );\r
403                 return ib_convert_cl_status( cl_status );\r
404         }\r
405 \r
406         /* Initialize the handle vector. */\r
407         cl_status = cl_vector_init( &h_al->hdl_vector, AL_HDL_VECTOR_MIN,\r
408                 AL_HDL_VECTOR_GROW, sizeof(al_handle_t), __init_hdl, NULL, h_al );\r
409         if( cl_status != CL_SUCCESS )\r
410         {\r
411                 free_al( &h_al->obj );\r
412                 AL_EXIT( AL_DBG_MGR );\r
413                 return ib_convert_cl_status( cl_status );\r
414         }\r
415         h_al->free_hdl = 1;\r
416 \r
417         /* Initialize the base object. */\r
418         status = init_al_obj( &h_al->obj, NULL, FALSE,\r
419                 destroying_al, NULL, free_al );\r
420         if( status != IB_SUCCESS )\r
421         {\r
422                 free_al( &h_al->obj );\r
423                 AL_EXIT( AL_DBG_MGR );\r
424                 return status;\r
425         }\r
426         status = attach_al_obj( &gp_al_mgr->obj, &h_al->obj );\r
427         if( status != IB_SUCCESS )\r
428         {\r
429                 h_al->obj.pfn_destroy( &h_al->obj, NULL );\r
430                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
431                         ("attach_al_obj returned %s.\n", ib_get_err_str(status)) );\r
432                 return status;\r
433         }\r
434 \r
435         /*\r
436          * Self reference the AL instance so that all attached objects\r
437          * insert themselve in the instance's handle manager automatically.\r
438          */\r
439         h_al->obj.h_al = h_al;\r
440 \r
441         *ph_al = h_al;\r
442 \r
443         /* Release the reference taken in init_al_obj. */\r
444         deref_al_obj( &h_al->obj );\r
445 \r
446         AL_EXIT( AL_DBG_MGR );\r
447         return IB_SUCCESS;\r
448 }\r
449 \r
450 \r
451 uint64_t\r
452 al_hdl_insert(\r
453         IN              const   ib_al_handle_t                          h_al,\r
454         IN                              void* const                                     p_obj,\r
455         IN              const   uint32_t                                        type )\r
456 {\r
457         cl_status_t             status;\r
458         size_t                  size;\r
459         uint64_t                hdl;\r
460         al_handle_t             *p_h;\r
461 \r
462         AL_ENTER( AL_DBG_HDL );\r
463 \r
464         size = cl_vector_get_size( &h_al->hdl_vector );\r
465         hdl = h_al->free_hdl;\r
466         if( h_al->free_hdl == size )\r
467         {\r
468                 /* Grow the vector pool. */\r
469                 status =\r
470                         cl_vector_set_size( &h_al->hdl_vector, size + AL_HDL_VECTOR_GROW );\r
471                 if( status != CL_SUCCESS )\r
472                 {\r
473                         AL_EXIT( AL_DBG_HDL );\r
474                         return AL_INVALID_HANDLE;\r
475                 }\r
476                 /*\r
477                  * Return the the start of the free list since the\r
478                  * entry initializer incremented it.\r
479                  */\r
480                 h_al->free_hdl = size;\r
481         }\r
482 \r
483         /* Get the next free entry. */\r
484         p_h = (al_handle_t*)cl_vector_get_ptr( &h_al->hdl_vector, (size_t)hdl );\r
485 \r
486         /* Update the next entry index. */\r
487         h_al->free_hdl = (size_t)p_h->p_obj;\r
488 \r
489         /* Update the entry. */\r
490         p_h->type = type;\r
491         p_h->p_obj = (al_obj_t*)p_obj;\r
492 \r
493         return hdl;\r
494 }\r
495 \r
496 \r
497 void\r
498 al_hdl_free(\r
499         IN              const   ib_al_handle_t                          h_al,\r
500         IN              const   uint64_t                                        hdl )\r
501 {\r
502         al_handle_t                     *p_h;\r
503 \r
504         CL_ASSERT( hdl < cl_vector_get_size( &h_al->hdl_vector ) );\r
505 \r
506         p_h = (al_handle_t*)cl_vector_get_ptr( &h_al->hdl_vector, (size_t)hdl );\r
507         p_h->type = AL_OBJ_TYPE_UNKNOWN;\r
508         p_h->p_obj = (al_obj_t*)(uintn_t)h_al->free_hdl;\r
509         h_al->free_hdl = hdl;\r
510 }\r
511 \r
512 \r
513 al_obj_t*\r
514 al_hdl_ref(\r
515         IN              const   ib_al_handle_t                          h_al,\r
516         IN              const   uint64_t                                        hdl,\r
517         IN              const   uint32_t                                        type )\r
518 {\r
519         al_handle_t                     *p_h;\r
520         al_obj_t                        *p_obj;\r
521 \r
522         CL_ASSERT( type != AL_OBJ_TYPE_H_MAD && type != AL_OBJ_TYPE_H_CONN );\r
523 \r
524         cl_spinlock_acquire( &h_al->obj.lock );\r
525 \r
526         /* Validate index. */\r
527         if( hdl >= cl_vector_get_size( &h_al->hdl_vector ) )\r
528         {\r
529                 cl_spinlock_release( &h_al->obj.lock );\r
530                 return NULL;\r
531         }\r
532 \r
533         /* Get the specified entry. */\r
534         p_h = (al_handle_t*)cl_vector_get_ptr( &h_al->hdl_vector, (size_t)hdl );\r
535 \r
536         /* Make sure that the handle is valid and the correct type. */\r
537         if( type == AL_OBJ_TYPE_UNKNOWN &&\r
538                 p_h->type != AL_OBJ_TYPE_H_PD && p_h->type != AL_OBJ_TYPE_H_CQ &&\r
539                 p_h->type != AL_OBJ_TYPE_H_AV && p_h->type != AL_OBJ_TYPE_H_QP &&\r
540                 p_h->type != AL_OBJ_TYPE_H_MR && p_h->type != AL_OBJ_TYPE_H_MW &&\r
541                 p_h->type != AL_OBJ_TYPE_H_SRQ )\r
542         {\r
543                 cl_spinlock_release( &h_al->obj.lock );\r
544                 return NULL;\r
545         }\r
546         else if( p_h->type != type )\r
547         {\r
548                 cl_spinlock_release( &h_al->obj.lock );\r
549                 return NULL;\r
550         }\r
551 \r
552         p_obj = p_h->p_obj;\r
553         if( !p_obj->hdl_valid )\r
554         {\r
555                 cl_spinlock_release( &h_al->obj.lock );\r
556                 return NULL;\r
557         }\r
558         ref_al_obj( p_obj );\r
559         cl_spinlock_release( &h_al->obj.lock );\r
560         return p_obj;\r
561 }\r
562 \r
563 \r
564 void*\r
565 al_hdl_chk(\r
566         IN              const   ib_al_handle_t                          h_al,\r
567         IN              const   uint64_t                                        hdl,\r
568         IN              const   uint32_t                                        type )\r
569 {\r
570         al_handle_t                     *p_h;\r
571 \r
572         /* Validate index. */\r
573         if( hdl >= cl_vector_get_size( &h_al->hdl_vector ) )\r
574                 return NULL;\r
575 \r
576         /* Get the specified entry. */\r
577         p_h = (al_handle_t*)cl_vector_get_ptr( &h_al->hdl_vector, (size_t)hdl );\r
578 \r
579         /* Make sure that the handle is valid and the correct type. */\r
580         if( (p_h->type != type) )\r
581                 return NULL;\r
582 \r
583         return p_h->p_obj;\r
584 }\r
585 \r
586 \r
587 void*\r
588 al_hdl_get(\r
589         IN              const   ib_al_handle_t                          h_al,\r
590         IN              const   uint64_t                                        hdl,\r
591         IN              const   uint32_t                                        type )\r
592 {\r
593         al_handle_t                     *p_h;\r
594         void                            *p_obj;\r
595 \r
596         cl_spinlock_acquire( &h_al->obj.lock );\r
597 \r
598         /* Validate index. */\r
599         if( hdl >= cl_vector_get_size( &h_al->hdl_vector ) )\r
600         {\r
601                 cl_spinlock_release( &h_al->obj.lock );\r
602                 return NULL;\r
603         }\r
604 \r
605         /* Get the specified entry. */\r
606         p_h = (al_handle_t*)cl_vector_get_ptr( &h_al->hdl_vector, (size_t)hdl );\r
607 \r
608         /* Make sure that the handle is valid and the correct type. */\r
609         if( (p_h->type != type) )\r
610         {\r
611                 cl_spinlock_release( &h_al->obj.lock );\r
612                 return NULL;\r
613         }\r
614 \r
615         p_obj = (void*)p_h->p_obj;\r
616 \r
617         /* Clear the entry. */\r
618         p_h->type = AL_OBJ_TYPE_UNKNOWN;\r
619         p_h->p_obj = (al_obj_t*)(uintn_t)h_al->free_hdl;\r
620         h_al->free_hdl = hdl;\r
621 \r
622         cl_spinlock_release( &h_al->obj.lock );\r
623         return p_obj;\r
624 }\r
625 \r