[IBBUS] added support to logging to System Event Log.
[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         IN              const   PDEVICE_OBJECT                          p_fdo\r
262         )\r
263 {\r
264         ib_api_status_t         status;\r
265 \r
266         AL_ENTER( AL_DBG_MGR );\r
267 \r
268         if( !p_ci )\r
269         {\r
270                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_PARAMETER\n") );\r
271                 return IB_INVALID_PARAMETER;\r
272         }\r
273         CL_ASSERT( !find_ci_ca( p_ci->guid ) );\r
274 \r
275         AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_MGR,\r
276                 ("CA guid %I64x.\n", p_ci->guid) );\r
277 \r
278         /* Check the channel interface verbs version. */\r
279         if( p_ci->version != VERBS_VERSION )\r
280         {\r
281                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
282                         ("Unsupported channel interface version, "\r
283                          "expected = 0x%x, actual = 0x%x.\n",\r
284                          VERBS_VERSION, p_ci->version) );\r
285                 return IB_UNSUPPORTED;\r
286         }\r
287 \r
288         /* Construct and initialize the CA structure. */\r
289         status = create_ci_ca( &gp_al_mgr->obj, p_ci, p_hca_dev, p_fdo );\r
290         if( status != IB_SUCCESS )\r
291         {\r
292                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
293                         ("al_mgr_ca_init failed.\n") );\r
294                 return status;\r
295         }\r
296 \r
297         AL_EXIT( AL_DBG_MGR );\r
298         return status;\r
299 }\r
300 \r
301 \r
302 \r
303 /*\r
304  * Process the removal of a CI CA from the system.\r
305  */\r
306 ib_api_status_t\r
307 ib_deregister_ca(\r
308         IN              const   net64_t                                         ca_guid )\r
309 {\r
310         al_ci_ca_t                      *p_ci_ca;\r
311 \r
312         AL_ENTER( AL_DBG_MGR );\r
313 \r
314         AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_MGR,\r
315                 ("Deregistering CA guid %I64x.\n", ca_guid) );\r
316 \r
317         /* Locate the CA. */\r
318         cl_spinlock_acquire( &gp_al_mgr->obj.lock );\r
319         p_ci_ca = find_ci_ca( ca_guid );\r
320         cl_spinlock_release( &gp_al_mgr->obj.lock );\r
321 \r
322         if( !p_ci_ca )\r
323         {\r
324                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("CA not found.\n") );\r
325                 return IB_NOT_FOUND;\r
326         }\r
327 \r
328         /*\r
329          * TODO: Before destroying, do a query PnP call and return IB_BUSY\r
330          * as needed.\r
331          */\r
332         /* Destroy the CI CA. */\r
333         ref_al_obj( &p_ci_ca->obj );\r
334         p_ci_ca->obj.pfn_destroy( &p_ci_ca->obj, NULL );\r
335 \r
336         AL_EXIT( AL_DBG_MGR );\r
337         return IB_SUCCESS;\r
338 }\r
339 \r
340 \r
341 /*\r
342  * Initialize a proxy entry used to map user-mode to kernel-mode resources.\r
343  */\r
344 static cl_status_t\r
345 __init_hdl(\r
346         IN              void* const                                             p_element,\r
347         IN              void*                                                   context )\r
348 {\r
349         al_handle_t             *p_h;\r
350 \r
351         p_h = (al_handle_t*)p_element;\r
352 \r
353         /* Chain free entries one after another. */\r
354         p_h->p_obj = (al_obj_t*)(uintn_t)++(((ib_al_handle_t)context)->free_hdl);\r
355         p_h->type = AL_OBJ_TYPE_UNKNOWN;\r
356 \r
357         return CL_SUCCESS;\r
358 }\r
359 \r
360 \r
361 /*\r
362  * Create a new instance of the access layer.  This function is placed here\r
363  * to prevent sharing the implementation with user-mode.\r
364  */\r
365 ib_api_status_t\r
366 ib_open_al(\r
367                 OUT                     ib_al_handle_t* const           ph_al )\r
368 {\r
369         ib_al_handle_t                  h_al;\r
370         ib_api_status_t                 status;\r
371         cl_status_t                             cl_status;\r
372 \r
373         AL_ENTER( AL_DBG_MGR );\r
374 \r
375         if( !ph_al )\r
376         {\r
377                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_PARAMETER\n") );\r
378                 return IB_INVALID_PARAMETER;\r
379         }\r
380 \r
381         /* Allocate an access layer instance. */\r
382         h_al = cl_zalloc( sizeof( ib_al_t ) );\r
383         if( !h_al )\r
384         {\r
385                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("cl_zalloc failed\n") );\r
386                 return IB_INSUFFICIENT_MEMORY;\r
387         }\r
388 \r
389         /* Construct the instance. */\r
390         construct_al_obj( &h_al->obj, AL_OBJ_TYPE_H_AL );\r
391         cl_spinlock_construct( &h_al->mad_lock );\r
392         cl_qlist_init( &h_al->mad_list );\r
393         cl_qlist_init( &h_al->key_list );\r
394         cl_qlist_init( &h_al->query_list );\r
395         cl_qlist_init( &h_al->cep_list );\r
396 \r
397         cl_vector_construct( &h_al->hdl_vector );\r
398 \r
399         cl_status = cl_spinlock_init( &h_al->mad_lock );\r
400         if( cl_status != CL_SUCCESS )\r
401         {\r
402                 free_al( &h_al->obj );\r
403                 AL_EXIT( AL_DBG_MGR );\r
404                 return ib_convert_cl_status( cl_status );\r
405         }\r
406 \r
407         /* Initialize the handle vector. */\r
408         cl_status = cl_vector_init( &h_al->hdl_vector, AL_HDL_VECTOR_MIN,\r
409                 AL_HDL_VECTOR_GROW, sizeof(al_handle_t), __init_hdl, NULL, h_al );\r
410         if( cl_status != CL_SUCCESS )\r
411         {\r
412                 free_al( &h_al->obj );\r
413                 AL_EXIT( AL_DBG_MGR );\r
414                 return ib_convert_cl_status( cl_status );\r
415         }\r
416         h_al->free_hdl = 1;\r
417 \r
418         /* Initialize the base object. */\r
419         status = init_al_obj( &h_al->obj, NULL, FALSE,\r
420                 destroying_al, NULL, free_al );\r
421         if( status != IB_SUCCESS )\r
422         {\r
423                 free_al( &h_al->obj );\r
424                 AL_EXIT( AL_DBG_MGR );\r
425                 return status;\r
426         }\r
427         status = attach_al_obj( &gp_al_mgr->obj, &h_al->obj );\r
428         if( status != IB_SUCCESS )\r
429         {\r
430                 h_al->obj.pfn_destroy( &h_al->obj, NULL );\r
431                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
432                         ("attach_al_obj returned %s.\n", ib_get_err_str(status)) );\r
433                 return status;\r
434         }\r
435 \r
436         /*\r
437          * Self reference the AL instance so that all attached objects\r
438          * insert themselve in the instance's handle manager automatically.\r
439          */\r
440         h_al->obj.h_al = h_al;\r
441 \r
442         *ph_al = h_al;\r
443 \r
444         /* Release the reference taken in init_al_obj. */\r
445         deref_al_obj( &h_al->obj );\r
446 \r
447         AL_EXIT( AL_DBG_MGR );\r
448         return IB_SUCCESS;\r
449 }\r
450 \r
451 \r
452 uint64_t\r
453 al_hdl_insert(\r
454         IN              const   ib_al_handle_t                          h_al,\r
455         IN                              void* const                                     p_obj,\r
456         IN              const   uint32_t                                        type )\r
457 {\r
458         cl_status_t             status;\r
459         size_t                  size;\r
460         uint64_t                hdl;\r
461         al_handle_t             *p_h;\r
462 \r
463         AL_ENTER( AL_DBG_HDL );\r
464 \r
465         size = cl_vector_get_size( &h_al->hdl_vector );\r
466         hdl = h_al->free_hdl;\r
467         if( h_al->free_hdl == size )\r
468         {\r
469                 /* Grow the vector pool. */\r
470                 status =\r
471                         cl_vector_set_size( &h_al->hdl_vector, size + AL_HDL_VECTOR_GROW );\r
472                 if( status != CL_SUCCESS )\r
473                 {\r
474                         AL_EXIT( AL_DBG_HDL );\r
475                         return AL_INVALID_HANDLE;\r
476                 }\r
477                 /*\r
478                  * Return the the start of the free list since the\r
479                  * entry initializer incremented it.\r
480                  */\r
481                 h_al->free_hdl = size;\r
482         }\r
483 \r
484         /* Get the next free entry. */\r
485         p_h = (al_handle_t*)cl_vector_get_ptr( &h_al->hdl_vector, (size_t)hdl );\r
486 \r
487         /* Update the next entry index. */\r
488         h_al->free_hdl = (size_t)p_h->p_obj;\r
489 \r
490         /* Update the entry. */\r
491         p_h->type = type;\r
492         p_h->p_obj = (al_obj_t*)p_obj;\r
493 \r
494         return hdl;\r
495 }\r
496 \r
497 \r
498 void\r
499 al_hdl_free(\r
500         IN              const   ib_al_handle_t                          h_al,\r
501         IN              const   uint64_t                                        hdl )\r
502 {\r
503         al_handle_t                     *p_h;\r
504 \r
505         CL_ASSERT( hdl < cl_vector_get_size( &h_al->hdl_vector ) );\r
506 \r
507         p_h = (al_handle_t*)cl_vector_get_ptr( &h_al->hdl_vector, (size_t)hdl );\r
508         p_h->type = AL_OBJ_TYPE_UNKNOWN;\r
509         p_h->p_obj = (al_obj_t*)(uintn_t)h_al->free_hdl;\r
510         h_al->free_hdl = hdl;\r
511 }\r
512 \r
513 \r
514 al_obj_t*\r
515 al_hdl_ref(\r
516         IN              const   ib_al_handle_t                          h_al,\r
517         IN              const   uint64_t                                        hdl,\r
518         IN              const   uint32_t                                        type )\r
519 {\r
520         al_handle_t                     *p_h;\r
521         al_obj_t                        *p_obj;\r
522 \r
523         CL_ASSERT( type != AL_OBJ_TYPE_H_MAD && type != AL_OBJ_TYPE_H_CONN );\r
524 \r
525         cl_spinlock_acquire( &h_al->obj.lock );\r
526 \r
527         /* Validate index. */\r
528         if( hdl >= cl_vector_get_size( &h_al->hdl_vector ) )\r
529         {\r
530                 cl_spinlock_release( &h_al->obj.lock );\r
531                 return NULL;\r
532         }\r
533 \r
534         /* Get the specified entry. */\r
535         p_h = (al_handle_t*)cl_vector_get_ptr( &h_al->hdl_vector, (size_t)hdl );\r
536 \r
537         /* Make sure that the handle is valid and the correct type. */\r
538         if( type == AL_OBJ_TYPE_UNKNOWN &&\r
539                 p_h->type != AL_OBJ_TYPE_H_PD && p_h->type != AL_OBJ_TYPE_H_CQ &&\r
540                 p_h->type != AL_OBJ_TYPE_H_AV && p_h->type != AL_OBJ_TYPE_H_QP &&\r
541                 p_h->type != AL_OBJ_TYPE_H_MR && p_h->type != AL_OBJ_TYPE_H_MW &&\r
542                 p_h->type != AL_OBJ_TYPE_H_SRQ )\r
543         {\r
544                 cl_spinlock_release( &h_al->obj.lock );\r
545                 return NULL;\r
546         }\r
547         else if( p_h->type != type )\r
548         {\r
549                 cl_spinlock_release( &h_al->obj.lock );\r
550                 return NULL;\r
551         }\r
552 \r
553         p_obj = p_h->p_obj;\r
554         if( !p_obj->hdl_valid )\r
555         {\r
556                 cl_spinlock_release( &h_al->obj.lock );\r
557                 return NULL;\r
558         }\r
559         ref_al_obj( p_obj );\r
560         cl_spinlock_release( &h_al->obj.lock );\r
561         return p_obj;\r
562 }\r
563 \r
564 \r
565 void*\r
566 al_hdl_chk(\r
567         IN              const   ib_al_handle_t                          h_al,\r
568         IN              const   uint64_t                                        hdl,\r
569         IN              const   uint32_t                                        type )\r
570 {\r
571         al_handle_t                     *p_h;\r
572 \r
573         /* Validate index. */\r
574         if( hdl >= cl_vector_get_size( &h_al->hdl_vector ) )\r
575                 return NULL;\r
576 \r
577         /* Get the specified entry. */\r
578         p_h = (al_handle_t*)cl_vector_get_ptr( &h_al->hdl_vector, (size_t)hdl );\r
579 \r
580         /* Make sure that the handle is valid and the correct type. */\r
581         if( (p_h->type != type) )\r
582                 return NULL;\r
583 \r
584         return p_h->p_obj;\r
585 }\r
586 \r
587 \r
588 void*\r
589 al_hdl_get(\r
590         IN              const   ib_al_handle_t                          h_al,\r
591         IN              const   uint64_t                                        hdl,\r
592         IN              const   uint32_t                                        type )\r
593 {\r
594         al_handle_t                     *p_h;\r
595         void                            *p_obj;\r
596 \r
597         cl_spinlock_acquire( &h_al->obj.lock );\r
598 \r
599         /* Validate index. */\r
600         if( hdl >= cl_vector_get_size( &h_al->hdl_vector ) )\r
601         {\r
602                 cl_spinlock_release( &h_al->obj.lock );\r
603                 return NULL;\r
604         }\r
605 \r
606         /* Get the specified entry. */\r
607         p_h = (al_handle_t*)cl_vector_get_ptr( &h_al->hdl_vector, (size_t)hdl );\r
608 \r
609         /* Make sure that the handle is valid and the correct type. */\r
610         if( (p_h->type != type) )\r
611         {\r
612                 cl_spinlock_release( &h_al->obj.lock );\r
613                 return NULL;\r
614         }\r
615 \r
616         p_obj = (void*)p_h->p_obj;\r
617 \r
618         /* Clear the entry. */\r
619         p_h->type = AL_OBJ_TYPE_UNKNOWN;\r
620         p_h->p_obj = (al_obj_t*)(uintn_t)h_al->free_hdl;\r
621         h_al->free_hdl = hdl;\r
622 \r
623         cl_spinlock_release( &h_al->obj.lock );\r
624         return p_obj;\r
625 }\r
626 \r