[IBAL] fix trap that route to local SM .
[mirror/winof/.git] / core / al / user / ual_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  *\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 \r
34 #include "ual_support.h"\r
35 #include "al_debug.h"\r
36 \r
37 #if defined(EVENT_TRACING)\r
38 #ifdef offsetof\r
39 #undef offsetof\r
40 #endif\r
41 #include "ual_mgr.tmh"\r
42 #endif\r
43 \r
44 #include "al_mgr.h"\r
45 #include "al_init.h"\r
46 #include "al_res_mgr.h"\r
47 #include "al_proxy_ioctl.h"\r
48 #include "al.h"\r
49 #include "al_ci_ca.h"\r
50 #include "al_pnp.h"\r
51 #include "al_ioc_pnp.h"\r
52 #include "al_cq.h"\r
53 #include "ual_ca.h"\r
54 #include "ual_qp.h"\r
55 #include "ual_mad.h"\r
56 #include "ib_common.h"\r
57 #include "al_cm_cep.h"\r
58 \r
59 \r
60 /* Global AL manager handle is defined in al_mgr_shared.c */\r
61 extern  ib_al_handle_t          gh_al;\r
62 extern  al_mgr_t*                       gp_al_mgr;\r
63 extern  ib_pool_handle_t        gh_mad_pool;\r
64 \r
65 \r
66 atomic32_t                                      g_open_cnt = 0;\r
67 \r
68 /* Define the thread names to handle various notifications */\r
69 #define CM_THREAD_NAME                  "CM_Thread"\r
70 #define COMP_THREAD_NAME                "Comp_Thread"\r
71 #define MISC_THREAD_NAME                "Misc_Thread"\r
72 \r
73 static DWORD WINAPI\r
74 __cb_thread_routine(\r
75         IN                              void                                            *context );\r
76 \r
77 //static void\r
78 //__process_cm_cb(\r
79 //      IN              cm_cb_ioctl_info_t*                     p_cm_cb_info);\r
80 \r
81 static void\r
82 __process_misc_cb(\r
83         IN              misc_cb_ioctl_info_t*           p_misc_cb_info );\r
84 \r
85 \r
86 static void\r
87 __cleanup_ual_mgr(\r
88         IN                              al_obj_t                                        *p_obj )\r
89 {\r
90         AL_ENTER(AL_DBG_MGR);\r
91 \r
92         UNUSED_PARAM( p_obj );\r
93 \r
94         /* Set the callback thread state to exit. */\r
95         gp_al_mgr->ual_mgr.exit_thread = TRUE;\r
96 \r
97         /* Closing the file handles cancels any pending I/O requests. */\r
98         //CloseHandle( gp_al_mgr->ual_mgr.h_cm_file );\r
99         CloseHandle( gp_al_mgr->ual_mgr.h_cq_file );\r
100         CloseHandle( gp_al_mgr->ual_mgr.h_misc_file );\r
101         CloseHandle( g_al_device );\r
102         g_al_device = INVALID_HANDLE_VALUE;\r
103 }\r
104 \r
105 \r
106 static void\r
107 __free_ual_mgr(\r
108         IN                              al_obj_t                                        *p_obj )\r
109 {\r
110         size_t                  i;\r
111         HANDLE                  h_thread;\r
112 \r
113         UNUSED_PARAM( p_obj );\r
114 \r
115         /*\r
116          * We need to destroy the AL object before the spinlock, since\r
117          * destroying the AL object will try to acquire the spinlock.\r
118          */\r
119         destroy_al_obj( &gp_al_mgr->obj );\r
120 \r
121         /* Verify that the object list is empty. */\r
122         print_al_objs( NULL );\r
123 \r
124         if( gp_al_mgr->ual_mgr.h_cb_port )\r
125         {\r
126                 /* Post a notification to the completion port to make threads exit. */\r
127                 for( i = 0;\r
128                         i < cl_ptr_vector_get_size( &gp_al_mgr->ual_mgr.cb_threads );\r
129                         i++ )\r
130                 {\r
131                         if( !PostQueuedCompletionStatus( gp_al_mgr->ual_mgr.h_cb_port,\r
132                                 0, 0, NULL ) )\r
133                         {\r
134                                 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,\r
135                                         ("PostQueuedCompletionStatus returned %d\n",\r
136                                         GetLastError()) );\r
137                         }\r
138                 }\r
139 \r
140                 while( cl_ptr_vector_get_size( &gp_al_mgr->ual_mgr.cb_threads ) )\r
141                 {\r
142                         h_thread = cl_ptr_vector_get( &gp_al_mgr->ual_mgr.cb_threads, 0 );\r
143                         WaitForSingleObject( h_thread, INFINITE );\r
144                         CloseHandle( h_thread );\r
145                         cl_ptr_vector_remove( &gp_al_mgr->ual_mgr.cb_threads, 0 );\r
146                 }\r
147 \r
148                 CloseHandle( gp_al_mgr->ual_mgr.h_cb_port );\r
149         }\r
150 \r
151         cl_ptr_vector_destroy( &gp_al_mgr->ual_mgr.cb_threads );\r
152         cl_spinlock_destroy( &gp_al_mgr->lock );\r
153 \r
154         cl_free( gp_al_mgr );\r
155         gp_al_mgr = NULL;\r
156 }\r
157 \r
158 \r
159 HANDLE\r
160 ual_create_async_file(\r
161         IN                              uint32_t                                        type )\r
162 {\r
163         cl_status_t                             cl_status;\r
164         ual_bind_file_ioctl_t   ioctl;\r
165         uintn_t                                 bytes_ret;\r
166 \r
167         AL_ENTER( AL_DBG_MGR );\r
168 \r
169         /* Create a file object on which to issue all SA requests. */\r
170         ioctl.h_file = CreateFileW( L"\\\\.\\ibal",\r
171                 GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,\r
172                 NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL );\r
173         if( ioctl.h_file == INVALID_HANDLE_VALUE )\r
174         {\r
175                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
176                         ("CreateFile returned %d.\n", GetLastError()) );\r
177                 return INVALID_HANDLE_VALUE;\r
178         }\r
179 \r
180         /* Bind this file object to the completion port. */\r
181         if( !CreateIoCompletionPort(\r
182                 ioctl.h_file, gp_al_mgr->ual_mgr.h_cb_port, type, 0 ) )\r
183         {\r
184                 CloseHandle( ioctl.h_file );\r
185                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
186                         ("CreateIoCompletionPort for file of type %d returned %d.\n",\r
187                         type, GetLastError()) );\r
188                 return INVALID_HANDLE_VALUE;\r
189         }\r
190 \r
191         /*\r
192          * Send an IOCTL down on the main file handle to bind this file\r
193          * handle with our proxy context.\r
194          */\r
195         cl_status = do_al_dev_ioctl(\r
196                 type, &ioctl, sizeof(ioctl), NULL, 0, &bytes_ret );\r
197         if( cl_status != CL_SUCCESS )\r
198         {\r
199                 CloseHandle( ioctl.h_file );\r
200                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
201                         ("Bind IOCTL for type %d returned %s.\n",\r
202                         type,CL_STATUS_MSG(cl_status)) );\r
203                 return INVALID_HANDLE_VALUE;\r
204         }\r
205 \r
206         AL_EXIT( AL_DBG_MGR );\r
207         return ioctl.h_file;\r
208 }\r
209 \r
210 \r
211 ib_api_status_t\r
212 ual_create_cb_threads( void )\r
213 {\r
214         cl_status_t             cl_status;\r
215         uint32_t                i;\r
216         HANDLE                  h_thread;\r
217 \r
218         AL_ENTER( AL_DBG_MGR );\r
219 \r
220         cl_status = cl_ptr_vector_init(\r
221                 &gp_al_mgr->ual_mgr.cb_threads, cl_proc_count(), 0 );\r
222         if( cl_status != CL_SUCCESS )\r
223         {\r
224                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
225                         ("cl_ptr_vector_init returned %s.\n", CL_STATUS_MSG( cl_status )) );\r
226                 return IB_ERROR;\r
227         }\r
228 \r
229         for( i = 0; i < cl_proc_count(); i++ )\r
230         {\r
231                 h_thread = CreateThread( NULL, 0, __cb_thread_routine, NULL, 0, NULL );\r
232                 if( !h_thread )\r
233                 {\r
234                         AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
235                                 ("CreateThread returned %d.\n", GetLastError()) );\r
236                         return IB_ERROR;\r
237                 }\r
238 \r
239                 /* We already sized the vector, so insertion should work. */\r
240                 cl_status = cl_ptr_vector_insert( &gp_al_mgr->ual_mgr.cb_threads,\r
241                         h_thread, NULL );\r
242                 CL_ASSERT( cl_status == CL_SUCCESS );\r
243         }\r
244 \r
245         AL_EXIT( AL_DBG_MGR );\r
246         return IB_SUCCESS;\r
247 }\r
248 \r
249 \r
250 /*\r
251  * Create the ual manager for the process\r
252  */\r
253 ib_api_status_t\r
254 create_al_mgr()\r
255 {\r
256         ib_api_status_t                 ib_status;\r
257         cl_status_t                             cl_status;\r
258         uintn_t                                 bytes_ret;\r
259         ULONG                                   ver;\r
260 \r
261         AL_ENTER(AL_DBG_MGR);\r
262 \r
263         CL_ASSERT( !gp_al_mgr );\r
264 \r
265         /* First open the kernel device. */\r
266         CL_ASSERT( g_al_device == INVALID_HANDLE_VALUE );\r
267         g_al_device = CreateFileW( L"\\\\.\\ibal",\r
268                 GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,\r
269                 NULL, OPEN_EXISTING, 0, NULL );\r
270         if( g_al_device == INVALID_HANDLE_VALUE )\r
271         {\r
272                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
273                         ("CreateFile returned %d.\n", GetLastError()) );\r
274                 return IB_ERROR;\r
275         }\r
276 \r
277 \r
278         ver = AL_IOCTL_VERSION;\r
279 \r
280         cl_status =\r
281                 do_al_dev_ioctl( UAL_BIND, &ver, sizeof(ver), NULL, 0, &bytes_ret );\r
282         if( cl_status != CL_SUCCESS )\r
283                 return IB_ERROR;\r
284 \r
285         gp_al_mgr = cl_zalloc( sizeof( al_mgr_t ) );\r
286         if( !gp_al_mgr )\r
287         {\r
288                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,\r
289                         ("Failed to cl_zalloc ual_mgr_t.\n") );\r
290                 return IB_INSUFFICIENT_MEMORY;\r
291         }\r
292 \r
293         /* Construct the AL manager. */\r
294         cl_event_construct( &gp_al_mgr->ual_mgr.sync_event );\r
295         cl_ptr_vector_construct( &gp_al_mgr->ual_mgr.cb_threads );\r
296         cl_qlist_init( &gp_al_mgr->al_obj_list );\r
297         cl_qlist_init( &gp_al_mgr->ci_ca_list );\r
298         cl_spinlock_construct( &gp_al_mgr->lock );\r
299         gp_al_mgr->ual_mgr.h_cb_port = NULL;\r
300 \r
301         /* Init the al object in the ual manager */\r
302         construct_al_obj(&gp_al_mgr->obj, AL_OBJ_TYPE_AL_MGR);\r
303         ib_status = init_al_obj( &gp_al_mgr->obj, gp_al_mgr, FALSE,\r
304                 NULL, __cleanup_ual_mgr, __free_ual_mgr );\r
305         if( ib_status != IB_SUCCESS )\r
306         {\r
307                 __free_ual_mgr( &gp_al_mgr->obj );\r
308                 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,\r
309                         ("init_al_obj failed, status = 0x%x.\n", ib_status) );\r
310                 return ib_status;\r
311         }\r
312 \r
313         /* Allocate the I/O completion port for async operations. */\r
314         gp_al_mgr->ual_mgr.h_cb_port = CreateIoCompletionPort(\r
315                 INVALID_HANDLE_VALUE, NULL, 0, 0 );\r
316         if( !gp_al_mgr->ual_mgr.h_cb_port )\r
317         {\r
318                 gp_al_mgr->obj.pfn_destroy( &gp_al_mgr->obj, NULL );\r
319                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
320                         ("Failed to create I/O completion port.\n") );\r
321                 return IB_ERROR;\r
322         }\r
323 \r
324         /* Create the threads to process completion callbacks. */\r
325         ib_status = ual_create_cb_threads();\r
326         if( ib_status != IB_SUCCESS )\r
327         {\r
328                 gp_al_mgr->obj.pfn_destroy( &gp_al_mgr->obj, NULL );\r
329                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR, ("ual_create_cb_threads failed.\n") );\r
330                 return ib_status;\r
331         }\r
332 \r
333         /* Create CM callback file handle. */\r
334         //gp_al_mgr->ual_mgr.h_cm_file = ual_create_async_file( UAL_BIND_CM );\r
335         //if( gp_al_mgr->ual_mgr.h_cq_file == INVALID_HANDLE_VALUE )\r
336         //{\r
337         //      gp_al_mgr->obj.pfn_destroy( &gp_al_mgr->obj, NULL );\r
338         //      AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
339         //              ("ual_create_async_file for UAL_BIND_CM returned %d.\n",\r
340         //              GetLastError()) );\r
341         //      return IB_ERROR;\r
342         //}\r
343 \r
344         /* Create the CQ completion callback file handle. */\r
345         gp_al_mgr->ual_mgr.h_cq_file = ual_create_async_file( UAL_BIND_CQ );\r
346         if( gp_al_mgr->ual_mgr.h_cq_file == INVALID_HANDLE_VALUE )\r
347         {\r
348                 gp_al_mgr->obj.pfn_destroy( &gp_al_mgr->obj, NULL );\r
349                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
350                         ("ual_create_async_file for UAL_BIND_CQ returned %d.\n",\r
351                         GetLastError()) );\r
352                 return IB_ERROR;\r
353         }\r
354 \r
355         /* Create the miscelaneous callback file handle. */\r
356         gp_al_mgr->ual_mgr.h_misc_file = ual_create_async_file( UAL_BIND_MISC );\r
357         if( gp_al_mgr->ual_mgr.h_misc_file == INVALID_HANDLE_VALUE )\r
358         {\r
359                 gp_al_mgr->obj.pfn_destroy( &gp_al_mgr->obj, NULL );\r
360                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
361                         ("ual_create_async_file for UAL_BIND_CQ returned %d.\n",\r
362                         GetLastError()) );\r
363                 return IB_ERROR;\r
364         }\r
365 \r
366         cl_status = cl_spinlock_init( &gp_al_mgr->lock );\r
367         if( cl_status != CL_SUCCESS )\r
368         {\r
369                 gp_al_mgr->obj.pfn_destroy(&gp_al_mgr->obj, NULL);\r
370                 return ib_convert_cl_status( cl_status );\r
371         }\r
372 \r
373         /* With PnP support, open the AL instance before the threads\r
374          * get a chance to process async events\r
375          */\r
376 \r
377         /* Open an implicit al instance for UAL's internal usage.  This call will\r
378          * automatically create the gh_al.\r
379          */\r
380         gh_al = NULL;\r
381         if ((ib_status = do_open_al(&gp_al_mgr->ual_mgr.h_al)) != IB_SUCCESS)\r
382         {\r
383                 gp_al_mgr->obj.pfn_destroy(&gp_al_mgr->obj, NULL);\r
384                 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,\r
385                         ("do_open_al() failed, status = 0x%x.\n", ib_status) );\r
386                 return ( ib_status );\r
387         }\r
388 \r
389         /* Create the global AL MAD pool. */\r
390         ib_status = ib_create_mad_pool( gh_al, 0, 0, 64, &gh_mad_pool );\r
391         if( ib_status != IB_SUCCESS )\r
392         {\r
393                 gp_al_mgr->obj.pfn_destroy(&gp_al_mgr->obj, NULL);\r
394                 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,\r
395                         ("ib_create_mad_pool failed with %s.\n", ib_get_err_str(ib_status)) );\r
396                 return ib_status;\r
397         }\r
398 \r
399         /*\r
400          * Create a global pool key for internal MADs - they are never\r
401          * registered on any CA.\r
402          */\r
403         ib_status = ual_reg_global_mad_pool( gh_mad_pool, &g_pool_key );\r
404         if( ib_status != IB_SUCCESS )\r
405         {\r
406                 gp_al_mgr->obj.pfn_destroy(&gp_al_mgr->obj, NULL);\r
407                 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,\r
408                         ("ual_reg_global_mad_pool failed with %s.\n", ib_get_err_str(ib_status)) );\r
409                 return ib_status;\r
410         }\r
411 \r
412         /* Create the pnp manager before the thread initialize.  This makes\r
413          * sure that the pnp manager is ready to process pnp callbacks as\r
414          * soon as the callback threads start running\r
415          */\r
416         ib_status = create_pnp( &gp_al_mgr->obj );\r
417         if( ib_status != IB_SUCCESS )\r
418         {\r
419                 gp_al_mgr->obj.pfn_destroy(&gp_al_mgr->obj, NULL);\r
420                 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,\r
421                         ("al_pnp_create failed with %s.\n", ib_get_err_str(ib_status)) );\r
422                 return ib_status;\r
423         }\r
424 \r
425         /* Initialize the AL resource manager. */\r
426         ib_status = create_res_mgr( &gp_al_mgr->obj );\r
427         if( ib_status != IB_SUCCESS )\r
428         {\r
429                 gp_al_mgr->obj.pfn_destroy(&gp_al_mgr->obj, NULL);\r
430                 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,\r
431                         ("create_res_mgr failed with %s.\n", ib_get_err_str(ib_status)) );\r
432                 return ib_status;\r
433         }\r
434 \r
435         /* Initialize the AL SA request manager. */\r
436         ib_status = create_sa_req_mgr( &gp_al_mgr->obj );\r
437         if( ib_status != IB_SUCCESS )\r
438         {\r
439                 gp_al_mgr->obj.pfn_destroy(&gp_al_mgr->obj, NULL);\r
440                 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,\r
441                         ("create_sa_req_mgr failed with %s.\n", ib_get_err_str(ib_status)) );\r
442                 return ib_status;\r
443         }\r
444 \r
445         /* Initialize CM */\r
446         ib_status = create_cep_mgr( &gp_al_mgr->obj );\r
447         if( ib_status != IB_SUCCESS )\r
448         {\r
449                 gp_al_mgr->obj.pfn_destroy( &gp_al_mgr->obj, NULL );\r
450                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
451                         ("create_cm_mgr failed, status = 0x%x.\n", ib_status) );\r
452                 return ib_status;\r
453         }\r
454 \r
455         cl_status = cl_event_init( &gp_al_mgr->ual_mgr.sync_event, FALSE );\r
456         if( cl_status != CL_SUCCESS )\r
457         {\r
458                 gp_al_mgr->obj.pfn_destroy(&gp_al_mgr->obj, NULL);\r
459                 return ib_convert_cl_status( cl_status );\r
460         }\r
461 \r
462         /* Everything is ready now.  Issue the first callback requests. */\r
463         if( !DeviceIoControl( gp_al_mgr->ual_mgr.h_misc_file, UAL_GET_MISC_CB_INFO,\r
464                 NULL, 0,\r
465                 &gp_al_mgr->ual_mgr.misc_cb_info, sizeof(misc_cb_ioctl_info_t),\r
466                 NULL, &gp_al_mgr->ual_mgr.misc_ov ) )\r
467         {\r
468                 if( GetLastError() != ERROR_IO_PENDING )\r
469                 {\r
470                         AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
471                                 ("DeviceIoControl for misc callback request returned %d.\n",\r
472                                 GetLastError()) );\r
473                         gp_al_mgr->obj.pfn_destroy(&gp_al_mgr->obj, NULL);\r
474                         return IB_ERROR;\r
475                 }\r
476         }\r
477 \r
478         //if( !DeviceIoControl( gp_al_mgr->ual_mgr.h_cm_file, UAL_GET_CM_CB_INFO,\r
479         //      NULL, 0,\r
480         //      &gp_al_mgr->ual_mgr.cm_cb_info, sizeof(cm_cb_ioctl_info_t),\r
481         //      NULL, &gp_al_mgr->ual_mgr.cm_ov ) )\r
482         //{\r
483         //      if( GetLastError() != ERROR_IO_PENDING )\r
484         //      {\r
485         //              AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
486         //                      ("DeviceIoControl for CM callback request returned %d.\n",\r
487         //                      GetLastError()) );\r
488         //              gp_al_mgr->obj.pfn_destroy(&gp_al_mgr->obj, NULL);\r
489         //              return IB_ERROR;\r
490         //      }\r
491         //}\r
492 \r
493         if( !DeviceIoControl( gp_al_mgr->ual_mgr.h_cq_file, UAL_GET_COMP_CB_INFO,\r
494                 NULL, 0,\r
495                 &gp_al_mgr->ual_mgr.comp_cb_info, sizeof(comp_cb_ioctl_info_t),\r
496                 NULL, &gp_al_mgr->ual_mgr.cq_ov ) )\r
497         {\r
498                 if( GetLastError() != ERROR_IO_PENDING )\r
499                 {\r
500                         AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
501                                 ("DeviceIoControl for CM callback request returned %d.\n",\r
502                                 GetLastError()) );\r
503                         gp_al_mgr->obj.pfn_destroy(&gp_al_mgr->obj, NULL);\r
504                         return IB_ERROR;\r
505                 }\r
506         }\r
507 \r
508         /*\r
509          * Wait until the associated kernel PnP registration completes.  This\r
510          * indicates that all known CAs have been reported to user-space\r
511          * and are being processed by the PnP manager.\r
512          */\r
513 #ifdef _DEBUG_\r
514         cl_status = cl_event_wait_on( &gp_al_mgr->ual_mgr.sync_event,\r
515                 EVENT_NO_TIMEOUT, TRUE );\r
516         CL_ASSERT ( cl_status == CL_SUCCESS);\r
517 #else\r
518         cl_status = cl_event_wait_on( &gp_al_mgr->ual_mgr.sync_event,\r
519                 EVENT_NO_TIMEOUT, TRUE );\r
520 #endif\r
521         \r
522         if( cl_status != CL_SUCCESS )\r
523         {\r
524                 gp_al_mgr->obj.pfn_destroy(&gp_al_mgr->obj, NULL);\r
525                 return ib_convert_cl_status( cl_status );\r
526         }\r
527         /* Release the reference taken in init_al_obj. */\r
528         deref_al_obj( &gp_al_mgr->obj );\r
529         \r
530         AL_EXIT(AL_DBG_MGR);\r
531         return IB_SUCCESS;\r
532 }\r
533 \r
534 \r
535 \r
536 /*\r
537  * UAL thread start routines.\r
538  */\r
539 //\r
540 //\r
541 ///* Thread to process the asynchronous CM notifications */\r
542 //void\r
543 //cm_cb(\r
544 //      IN                              DWORD                                           error_code,\r
545 //      IN                              DWORD                                           ret_bytes,\r
546 //      IN                              LPOVERLAPPED                            p_ov )\r
547 //{\r
548 //      AL_ENTER( AL_DBG_CM );\r
549 //\r
550 //      UNUSED_PARAM( p_ov );\r
551 //\r
552 //      if( !error_code && ret_bytes )\r
553 //      {\r
554 //              /* Check the record type and adjust the pointers */\r
555 //              /*      TBD     */\r
556 //              __process_cm_cb( &gp_al_mgr->ual_mgr.cm_cb_info );\r
557 //      }\r
558 //      \r
559 //      if( error_code != ERROR_OPERATION_ABORTED )\r
560 //      {\r
561 //              if( !DeviceIoControl( gp_al_mgr->ual_mgr.h_cm_file, UAL_GET_CM_CB_INFO,\r
562 //                      NULL, 0,\r
563 //                      &gp_al_mgr->ual_mgr.cm_cb_info, sizeof(cm_cb_ioctl_info_t),\r
564 //                      NULL, &gp_al_mgr->ual_mgr.cm_ov ) )\r
565 //              {\r
566 //                      if( GetLastError() != ERROR_IO_PENDING )\r
567 //                      {\r
568 //                              AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
569 //                                      ("DeviceIoControl for CM callback request returned %d.\n",\r
570 //                                      GetLastError()) );\r
571 //                      }\r
572 //              }\r
573 //      }\r
574 //\r
575 //      AL_EXIT( AL_DBG_CM );\r
576 //}\r
577 \r
578 \r
579 \r
580 //static void\r
581 //__process_cm_cb(\r
582 //      IN              cm_cb_ioctl_info_t*                     p_cm_cb_info)\r
583 //{\r
584 //      switch( p_cm_cb_info->rec_type)\r
585 //      {\r
586 //      case CM_REQ_REC:\r
587 //      {\r
588 //              struct _cm_req_cb_ioctl_rec *p_ioctl_rec =\r
589 //                              &p_cm_cb_info->ioctl_rec.cm_req_cb_ioctl_rec;\r
590 //\r
591 //              if (p_ioctl_rec->req_rec.qp_type == IB_QPT_UNRELIABLE_DGRM)\r
592 //              {\r
593 //                      p_ioctl_rec->req_rec.p_req_pdata =\r
594 //                              (uint8_t *)&p_ioctl_rec->cm_req_pdata_rec.sidr_req_pdata;\r
595 //              }\r
596 //              else\r
597 //              {\r
598 //                      p_ioctl_rec->req_rec.p_req_pdata =\r
599 //                              (uint8_t *)&p_ioctl_rec->cm_req_pdata_rec.req_pdata;\r
600 //              }\r
601 //              ual_cm_req_cb( &p_ioctl_rec->req_rec, &p_ioctl_rec->qp_mod_rtr,\r
602 //                      &p_ioctl_rec->qp_mod_rts, p_ioctl_rec->timeout_ms );\r
603 //              break;\r
604 //      }\r
605 //      case CM_REP_REC:\r
606 //      {\r
607 //              struct _cm_rep_cb_ioctl_rec *p_ioctl_rec =\r
608 //                              &p_cm_cb_info->ioctl_rec.cm_rep_cb_ioctl_rec;\r
609 //\r
610 //              if (p_ioctl_rec->rep_rec.qp_type == IB_QPT_UNRELIABLE_DGRM)\r
611 //              {\r
612 //                      p_ioctl_rec->rep_rec.p_rep_pdata =\r
613 //                              (uint8_t *)&p_ioctl_rec->cm_rep_pdata_rec.sidr_rep_pdata;\r
614 //              }\r
615 //              else\r
616 //              {\r
617 //                      p_ioctl_rec->rep_rec.p_rep_pdata =\r
618 //                              (uint8_t *)&p_ioctl_rec->cm_rep_pdata_rec.rep_pdata;\r
619 //              }\r
620 //              ual_cm_rep_cb( &p_ioctl_rec->rep_rec, &p_ioctl_rec->qp_mod_rtr,\r
621 //                      &p_ioctl_rec->qp_mod_rts );\r
622 //              break;\r
623 //      }\r
624 //      case CM_RTU_REC:\r
625 //      {\r
626 //              struct _cm_rtu_cb_ioctl_rec *p_ioctl_rec =\r
627 //                              &p_cm_cb_info->ioctl_rec.cm_rtu_cb_ioctl_rec;\r
628 //\r
629 //              p_ioctl_rec->rtu_rec.p_rtu_pdata = (uint8_t *)&p_ioctl_rec->rtu_pdata;\r
630 //              ual_cm_rtu_cb( &p_ioctl_rec->rtu_rec );\r
631 //              break;\r
632 //      }\r
633 //      case CM_REJ_REC:\r
634 //      {\r
635 //              struct _cm_rej_cb_ioctl_rec *p_ioctl_rec =\r
636 //                              &p_cm_cb_info->ioctl_rec.cm_rej_cb_ioctl_rec;\r
637 //\r
638 //              p_ioctl_rec->rej_rec.p_rej_pdata = \r
639 //                      (uint8_t*)&p_ioctl_rec->rej_pdata;\r
640 //              p_ioctl_rec->rej_rec.p_ari =\r
641 //                      (uint8_t*)&p_ioctl_rec->ari_pdata;\r
642 //              ual_cm_rej_cb( &p_ioctl_rec->rej_rec );\r
643 //              break;\r
644 //      }\r
645 //      case CM_MRA_REC:\r
646 //      {\r
647 //              struct _cm_mra_cb_ioctl_rec *p_ioctl_rec =\r
648 //                              &p_cm_cb_info->ioctl_rec.cm_mra_cb_ioctl_rec;\r
649 //\r
650 //              p_ioctl_rec->mra_rec.p_mra_pdata =\r
651 //                      (uint8_t*)&p_ioctl_rec->mra_pdata;\r
652 //              ual_cm_mra_cb( &p_cm_cb_info->ioctl_rec.cm_mra_cb_ioctl_rec.mra_rec );\r
653 //              break;\r
654 //      }\r
655 //      case CM_LAP_REC:\r
656 //      {\r
657 //              struct _cm_lap_cb_ioctl_rec *p_ioctl_rec =\r
658 //                              &p_cm_cb_info->ioctl_rec.cm_lap_cb_ioctl_rec;\r
659 //\r
660 //              p_ioctl_rec->lap_rec.p_lap_pdata =\r
661 //                      (uint8_t *)&p_ioctl_rec->lap_pdata;\r
662 //              ual_cm_lap_cb( &p_ioctl_rec->lap_rec );\r
663 //              break;\r
664 //      }\r
665 //      case CM_APR_REC:\r
666 //      {\r
667 //              struct _cm_apr_cb_ioctl_rec *p_ioctl_rec =\r
668 //                              &p_cm_cb_info->ioctl_rec.cm_apr_cb_ioctl_rec;\r
669 //\r
670 //              p_ioctl_rec->apr_rec.p_apr_pdata =\r
671 //                      (uint8_t*)&p_ioctl_rec->apr_pdata;\r
672 //              p_ioctl_rec->apr_rec.p_info =\r
673 //                      (uint8_t*)&p_ioctl_rec->apr_info;\r
674 //              ual_cm_apr_cb( &p_ioctl_rec->apr_rec );\r
675 //              break;\r
676 //      }\r
677 //      case CM_DREQ_REC:\r
678 //      {\r
679 //              struct _cm_dreq_cb_ioctl_rec *p_ioctl_rec =\r
680 //                              &p_cm_cb_info->ioctl_rec.cm_dreq_cb_ioctl_rec;\r
681 //\r
682 //              p_ioctl_rec->dreq_rec.p_dreq_pdata =\r
683 //                      (uint8_t*)&p_ioctl_rec->dreq_pdata;\r
684 //              ual_cm_dreq_cb( &p_ioctl_rec->dreq_rec );\r
685 //              break;\r
686 //      }\r
687 //      case CM_DREP_REC:\r
688 //      {\r
689 //              struct _cm_drep_cb_ioctl_rec *p_ioctl_rec =\r
690 //                              &p_cm_cb_info->ioctl_rec.cm_drep_cb_ioctl_rec;\r
691 //\r
692 //              p_ioctl_rec->drep_rec.p_drep_pdata =\r
693 //                      (uint8_t*)&p_ioctl_rec->drep_pdata;\r
694 //              ual_cm_drep_cb( &p_ioctl_rec->drep_rec );\r
695 //              break;\r
696 //      }\r
697 //      default:\r
698 //              /* Unknown record type - just return */\r
699 //              break;\r
700 //      }\r
701 //}\r
702 //\r
703 //\r
704 //\r
705 static void\r
706 __process_comp_cb(\r
707         IN              comp_cb_ioctl_info_t*                   p_comp_cb_info )\r
708 {\r
709         ib_cq_handle_t  h_cq;\r
710         CL_ASSERT( p_comp_cb_info->cq_context );\r
711         h_cq = (ib_cq_handle_t)(p_comp_cb_info->cq_context);\r
712 \r
713         if( ref_al_obj( &h_cq->obj ) > 1 )\r
714         {\r
715                 CL_ASSERT( h_cq->pfn_user_comp_cb );\r
716                 h_cq->pfn_user_comp_cb( h_cq, (void*)h_cq->obj.context );\r
717         }\r
718         deref_al_obj( &h_cq->obj );\r
719 }\r
720 \r
721 \r
722 \r
723 /* Thread to process the asynchronous completion notifications */\r
724 void\r
725 cq_cb(\r
726         IN                              DWORD                                           error_code,\r
727         IN                              DWORD                                           ret_bytes,\r
728         IN                              LPOVERLAPPED                            p_ov )\r
729 {\r
730         AL_ENTER( AL_DBG_CQ );\r
731 \r
732         UNUSED_PARAM( p_ov );\r
733 \r
734         if( !error_code && ret_bytes )\r
735         {\r
736                 /* Check the record type and adjust the pointers */\r
737                 /*      TBD     */\r
738                 __process_comp_cb( &gp_al_mgr->ual_mgr.comp_cb_info );\r
739         }\r
740         \r
741         if( error_code != ERROR_OPERATION_ABORTED )\r
742         {\r
743                 if( !DeviceIoControl( gp_al_mgr->ual_mgr.h_cq_file, UAL_GET_COMP_CB_INFO,\r
744                         NULL, 0,\r
745                         &gp_al_mgr->ual_mgr.comp_cb_info, sizeof(comp_cb_ioctl_info_t),\r
746                         NULL, &gp_al_mgr->ual_mgr.cq_ov ) )\r
747                 {\r
748                         if( GetLastError() != ERROR_IO_PENDING )\r
749                         {\r
750                                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
751                                         ("DeviceIoControl for CM callback request returned %d.\n",\r
752                                         GetLastError()) );\r
753                         }\r
754                 }\r
755         }\r
756 \r
757         AL_EXIT( AL_DBG_CQ );\r
758 }\r
759 \r
760 \r
761 \r
762 /* Thread to process miscellaneous asynchronous events */\r
763 void\r
764 misc_cb(\r
765         IN                              DWORD                                           error_code,\r
766         IN                              DWORD                                           ret_bytes,\r
767         IN                              LPOVERLAPPED                            p_ov )\r
768 {\r
769         AL_ENTER( AL_DBG_MGR );\r
770 \r
771         UNUSED_PARAM( p_ov );\r
772 \r
773         if( !error_code && ret_bytes )\r
774         {\r
775                 /* Check the record type and adjust the pointers */\r
776                 /*      TBD     */\r
777                 __process_misc_cb( &gp_al_mgr->ual_mgr.misc_cb_info );\r
778         }\r
779         \r
780         if( error_code != ERROR_OPERATION_ABORTED )\r
781         {\r
782                 /* Issue the next request. */\r
783                 if( !DeviceIoControl( gp_al_mgr->ual_mgr.h_misc_file, UAL_GET_MISC_CB_INFO,\r
784                         NULL, 0,\r
785                         &gp_al_mgr->ual_mgr.misc_cb_info, sizeof(misc_cb_ioctl_info_t),\r
786                         NULL, &gp_al_mgr->ual_mgr.misc_ov ) )\r
787                 {\r
788                         if( GetLastError() != ERROR_IO_PENDING )\r
789                         {\r
790                                 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,\r
791                                         ("DeviceIoControl for misc callback request returned %d.\n",\r
792                                         GetLastError()) );\r
793                         }\r
794                 }\r
795         }\r
796 \r
797         AL_EXIT( AL_DBG_MGR );\r
798 }\r
799 \r
800 \r
801 \r
802 void\r
803 __process_misc_cb(\r
804         IN              misc_cb_ioctl_info_t*           p_misc_cb_info )\r
805 {\r
806         switch( p_misc_cb_info->rec_type )\r
807         {\r
808         case CA_ERROR_REC:\r
809         case QP_ERROR_REC:\r
810         case SRQ_ERROR_REC:\r
811         case CQ_ERROR_REC:\r
812         {\r
813                 /* Initiate user-mode asynchronous event processing. */\r
814                 ci_ca_async_event( &p_misc_cb_info->ioctl_rec.event_rec );\r
815                 break;\r
816         }\r
817         case MCAST_REC:\r
818         {\r
819                 ib_mcast_rec_t                  mcast_rec;\r
820                 cl_memcpy((void *)&mcast_rec,\r
821                                         (void*)&p_misc_cb_info->ioctl_rec.mcast_cb_ioctl_rec,\r
822                                         sizeof(ib_mcast_rec_t));\r
823                 mcast_rec.p_member_rec = \r
824                         &p_misc_cb_info->ioctl_rec.mcast_cb_ioctl_rec.member_rec;\r
825                 /******* Call the cb function for app callback *****/\r
826                 break;\r
827         }\r
828         case MAD_SEND_REC:\r
829         {\r
830                 /* We got a send completion. */\r
831                 ib_mad_element_t                        *p_element;\r
832 \r
833                 ib_mad_svc_handle_t                     h_mad_svc = (ib_mad_svc_handle_t)\r
834                         p_misc_cb_info->ioctl_rec.mad_send_cb_ioctl_rec.mad_svc_context;\r
835 \r
836                 /* Copy the data to the user's element. */\r
837                 p_element = p_misc_cb_info->ioctl_rec.mad_send_cb_ioctl_rec.p_um_mad;\r
838                 /* Only update the status if a receive wasn't failed. */\r
839                 if( p_element->status != IB_WCS_TIMEOUT_RETRY_ERR )\r
840                 {\r
841                         p_element->status =\r
842                                 p_misc_cb_info->ioctl_rec.mad_send_cb_ioctl_rec.wc_status;\r
843                 }\r
844                 p_element->p_next = NULL;\r
845 \r
846                 /* Now the user mad_elements should have the right data\r
847                  * Make the client callback\r
848                  */\r
849                 h_mad_svc->pfn_user_send_cb( h_mad_svc,\r
850                         (void*)h_mad_svc->obj.context, p_element );\r
851                 break;\r
852         }\r
853         case MAD_RECV_REC:\r
854         {\r
855                 /*\r
856                  * We've receive a MAD.  We need to get a user-mode MAD of the\r
857                  * correct size, then send it down to retrieve the received MAD.\r
858                  */\r
859                 ual_mad_recv_ioctl_t    ioctl_buf;\r
860                 uintn_t                                 bytes_ret;\r
861                 cl_status_t                             cl_status;\r
862                 ib_api_status_t                 status;\r
863                 ib_mad_svc_handle_t             h_mad_svc;\r
864                 ib_mad_element_t                *p_mad = NULL;\r
865                 ib_mad_element_t                *p_send_mad;\r
866                 ib_mad_t                                *p_mad_buf = NULL;\r
867                 ib_grh_t                                *p_grh = NULL;\r
868 \r
869                 h_mad_svc = (ib_mad_svc_handle_t)\r
870                         p_misc_cb_info->ioctl_rec.mad_recv_cb_ioctl_rec.mad_svc_context;\r
871 \r
872                 p_send_mad =\r
873                         p_misc_cb_info->ioctl_rec.mad_recv_cb_ioctl_rec.p_send_mad;\r
874 \r
875                 cl_memclr( &ioctl_buf, sizeof(ioctl_buf) );\r
876 \r
877                 /*\r
878                  * Get a MAD large enough to receive the MAD.  If we can't get a\r
879                  * MAD, we still perform the IOCTL so that the kernel will return\r
880                  * the MAD to its pool, resulting in a dropped MAD.\r
881                  */\r
882                 status = ib_get_mad( h_mad_svc->obj.p_ci_ca->pool_key,\r
883                         p_misc_cb_info->ioctl_rec.mad_recv_cb_ioctl_rec.elem_size,\r
884                         &p_mad );\r
885 \r
886                 /*\r
887                  * Note that we set any associated send MAD's status here\r
888                  * in case of failure.\r
889                  */\r
890                 if( status == IB_SUCCESS )\r
891                         al_handoff_mad( (ib_al_handle_t)h_mad_svc->obj.h_al, p_mad );\r
892                 else if( p_send_mad )\r
893                         p_send_mad->status = IB_WCS_TIMEOUT_RETRY_ERR;\r
894 \r
895                 ioctl_buf.in.p_user_mad = p_mad;\r
896 \r
897                 if( p_mad )\r
898                 {\r
899                         /* Save off the pointers since the proxy overwrites the element. */\r
900                         p_mad_buf = p_mad->p_mad_buf;\r
901                         p_grh = p_mad->p_grh;\r
902 \r
903                         ioctl_buf.in.p_mad_buf = p_mad_buf;\r
904                         ioctl_buf.in.p_grh = p_grh;\r
905                 }\r
906                 ioctl_buf.in.h_mad = p_misc_cb_info->ioctl_rec.mad_recv_cb_ioctl_rec.h_mad;\r
907 \r
908                 cl_status = do_al_dev_ioctl( UAL_MAD_RECV_COMP,\r
909                         &ioctl_buf.in, sizeof(ioctl_buf.in),\r
910                         &ioctl_buf.out, sizeof(ioctl_buf.out),\r
911                         &bytes_ret );\r
912                 if( cl_status != CL_SUCCESS || bytes_ret != sizeof(ioctl_buf.out) )\r
913                 {\r
914                         AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,\r
915                                 ("UAL_MAD_RECV_COMP IOCTL returned %s.\n",\r
916                                 CL_STATUS_MSG(cl_status)) );\r
917                         status = IB_ERROR;\r
918                 }\r
919                 else\r
920                 {\r
921                         status = ioctl_buf.out.status;\r
922                 }\r
923                 if( p_mad )\r
924                 {\r
925                         if( status == IB_SUCCESS )\r
926                         {\r
927                                 /* We need to reset MAD data pointers. */\r
928                                 p_mad->p_mad_buf = p_mad_buf;\r
929                                 p_mad->p_grh = p_grh;\r
930                                 /* Restore the client's send context1 */\r
931                                 if( p_send_mad )\r
932                                         p_mad->send_context1 = (void* __ptr64)p_send_mad->context1;\r
933                 \r
934                                 h_mad_svc->pfn_user_recv_cb( h_mad_svc,\r
935                                         (void*)h_mad_svc->obj.context, p_mad );\r
936                         }\r
937                         else\r
938                         {\r
939                                 ib_put_mad( p_mad );\r
940                         }\r
941                 }\r
942                 break;\r
943         }\r
944         case SVC_REG_REC:\r
945         {\r
946                 break;\r
947         }\r
948         case QUERY_REC:\r
949         {\r
950                 break;\r
951         }\r
952         case PNP_REC:\r
953         {\r
954                 ib_pnp_event_t                                  pnp_event;\r
955                 ib_net64_t                                              ca_guid;\r
956                 al_ci_ca_t                                              *p_ci_ca;\r
957                 ual_ca_attr_info_ioctl_t                attr_ioctl;\r
958                 uintn_t                                                 bytes_ret;\r
959                 cl_status_t                                             cl_status;\r
960                 ib_ca_attr_t                                    *p_old_ca_attr;\r
961                 ib_api_status_t                                 status;\r
962 \r
963                 pnp_event = p_misc_cb_info->ioctl_rec.pnp_cb_ioctl_rec.pnp_event;\r
964                 ca_guid = p_misc_cb_info->ioctl_rec.pnp_cb_ioctl_rec.pnp_info.ca.ca_guid;\r
965 \r
966                 switch( pnp_event )\r
967                 {\r
968                 case IB_PNP_CA_ADD:\r
969                         /* Create a new CI CA. */\r
970                         create_ci_ca( gh_al, &gp_al_mgr->obj,\r
971                                 p_misc_cb_info->ioctl_rec.pnp_cb_ioctl_rec.pnp_info.ca.ca_guid );\r
972                         break;\r
973 \r
974                 case IB_PNP_CA_REMOVE:\r
975                         /* Destroy the CI CA. */\r
976                         cl_spinlock_acquire( &gp_al_mgr->obj.lock );\r
977                         p_ci_ca = find_ci_ca( ca_guid );\r
978                         if( !p_ci_ca )\r
979                         {\r
980                                 cl_spinlock_release( &gp_al_mgr->obj.lock );\r
981                                 break;\r
982                         }\r
983                         ref_al_obj( &p_ci_ca->obj );\r
984                         cl_spinlock_release( &gp_al_mgr->obj.lock );\r
985 \r
986                         p_ci_ca->obj.pfn_destroy( &p_ci_ca->obj, NULL );\r
987                         break;\r
988 \r
989                 case IB_PNP_PORT_ADD:\r
990                 case IB_PNP_PORT_REMOVE:\r
991                         /* Should never get these. */\r
992                         break;\r
993 \r
994                 case IB_PNP_REG_COMPLETE:\r
995                         /*\r
996                          * Signal that the kernel PnP registration is done, indicating\r
997                          * that the current system state has been reported to the user.\r
998                          */\r
999                         cl_event_signal( &gp_al_mgr->ual_mgr.sync_event );\r
1000                         break;\r
1001 \r
1002                 default:\r
1003                         /* Process the PnP event - most likely a port change event. */\r
1004                         cl_spinlock_acquire( &gp_al_mgr->obj.lock );\r
1005                         p_ci_ca = find_ci_ca( ca_guid );\r
1006                         if( !p_ci_ca )\r
1007                         {\r
1008                                 cl_spinlock_release( &gp_al_mgr->obj.lock );\r
1009                                 break;\r
1010                         }\r
1011                         ref_al_obj( &p_ci_ca->obj );\r
1012                         cl_spinlock_release( &gp_al_mgr->obj.lock );\r
1013 \r
1014                         status = ci_ca_update_attr( p_ci_ca, &p_old_ca_attr );\r
1015                         if( status != IB_SUCCESS) {\r
1016                                 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,\r
1017                                         ("update CA attributes returned %#x.\n", status) );\r
1018         \r
1019                                 /* Dereference the CA now. */\r
1020                                 deref_al_obj( &p_ci_ca->obj );\r
1021                                 break;\r
1022                         }\r
1023                         if ( p_old_ca_attr )\r
1024                                 cl_free( p_old_ca_attr );\r
1025 \r
1026                         /*\r
1027                          * We need to fetch the cached CA attributes from the proxy.  We\r
1028                          * always send down the IOCTL to free the cached attributes.\r
1029                          */\r
1030                         //p_ca_attr = (ib_ca_attr_t*)cl_zalloc(\r
1031                         //      p_misc_cb_info->ioctl_rec.pnp_cb_ioctl_rec.pnp_info.ca.size );\r
1032                         attr_ioctl.in.p_ca_attr = NULL;\r
1033 \r
1034                         /* Get the cached attributes from the kernel. */\r
1035                         attr_ioctl.in.h_ca_attr =\r
1036                                 p_misc_cb_info->ioctl_rec.pnp_cb_ioctl_rec.pnp_info.ca.h_ca_attr;\r
1037                         cl_status = do_al_dev_ioctl( UAL_GET_CA_ATTR_INFO,\r
1038                                 &attr_ioctl, sizeof(attr_ioctl.in),\r
1039                                 &attr_ioctl, sizeof(attr_ioctl.out),\r
1040                                 &bytes_ret );\r
1041 \r
1042                         ///* Notify PnP manager of the changes if we have them. */\r
1043                         //if( p_ca_attr )\r
1044                         //{\r
1045                         //      if( cl_status == CL_SUCCESS &&\r
1046                         //              attr_ioctl.out.status == IB_SUCCESS )\r
1047                         //      {\r
1048                         //              pnp_ca_change( p_ci_ca, p_ca_attr );\r
1049                         //      }\r
1050                         //      else\r
1051                         //      {\r
1052                         //      }\r
1053 \r
1054                         //      cl_free( p_ca_attr );\r
1055                         //}\r
1056                         /* Dereference the CA now. */\r
1057                         deref_al_obj( &p_ci_ca->obj );\r
1058                         break;\r
1059                 }\r
1060 \r
1061                 break;  /* For PNP_EVENT_REC */\r
1062         }\r
1063         case SUB_REC:\r
1064         {\r
1065                 /******* TBD *******/\r
1066                 /* No adjustment needed */\r
1067                 break;\r
1068         }\r
1069         case REPORT_REC:\r
1070         {\r
1071                 ib_report_rec_t                 report_rec;\r
1072                 cl_memcpy((void *)&report_rec,\r
1073                                         (void*)&p_misc_cb_info->ioctl_rec.report_cb_ioctl_rec,\r
1074                                         sizeof(ib_report_rec_t));\r
1075                 report_rec.p_notice = &p_misc_cb_info->ioctl_rec.report_cb_ioctl_rec.notice;\r
1076                 /******* Call the cb function for app callback *****/\r
1077                 break;\r
1078         }\r
1079         default:\r
1080                 CL_ASSERT (0);\r
1081                 break;\r
1082         }\r
1083 }\r
1084 \r
1085 \r
1086 \r
1087 /*\r
1088  * Create a new instance of the access layer.\r
1089  */\r
1090 ib_api_status_t\r
1091 ib_open_al(\r
1092                 OUT                     ib_al_handle_t* const           ph_al )\r
1093 {\r
1094         ib_api_status_t         status;\r
1095 \r
1096         cl_mutex_acquire( &g_open_close_mutex );\r
1097         status = do_open_al( ph_al );\r
1098         if( status == IB_SUCCESS )\r
1099         {\r
1100                 /*\r
1101                  * Bump the open count.  Note that we only do this for external\r
1102                  * calls, not the internal ib_open_al call.\r
1103                  */\r
1104                 cl_atomic_inc( &g_open_cnt );\r
1105         }\r
1106         cl_mutex_release( &g_open_close_mutex );\r
1107         return status;\r
1108 }\r
1109 \r
1110 \r
1111 ib_api_status_t\r
1112 ib_close_al(\r
1113         IN              const   ib_al_handle_t                          h_al )\r
1114 {\r
1115         ib_api_status_t         status;\r
1116 \r
1117         cl_mutex_acquire( &g_open_close_mutex );\r
1118         status = do_close_al( h_al );\r
1119         if( status == IB_SUCCESS && !cl_atomic_dec( &g_open_cnt ) )\r
1120                 al_cleanup();\r
1121         cl_mutex_release( &g_open_close_mutex );\r
1122         return status;\r
1123 }\r
1124 \r
1125 \r
1126 ib_api_status_t\r
1127 do_open_al(\r
1128                 OUT                     ib_al_handle_t* const           ph_al )\r
1129 {\r
1130         ib_al_handle_t                  h_al;\r
1131         ib_api_status_t                 status;\r
1132 \r
1133         AL_ENTER(AL_DBG_MGR);\r
1134 \r
1135         if( !ph_al )\r
1136         {\r
1137                 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("IB_INVALID_PARAMETER\n") );\r
1138                 return IB_INVALID_PARAMETER;\r
1139         }\r
1140 \r
1141         /*\r
1142          * Initialize AL if needed.\r
1143          * This should only occur on the first ib_open_al call.\r
1144          */\r
1145         if( !gp_al_mgr )\r
1146         {\r
1147                 status = al_initialize();\r
1148                 if( status != IB_SUCCESS )\r
1149                 {\r
1150                         al_cleanup();\r
1151                         AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,\r
1152                                 ("ual_init failed, status = %s\n", ib_get_err_str(status) ) );\r
1153                         return status;\r
1154                 }\r
1155                 /*\r
1156                 * Wait for 50ms before returning. This ensures the pnp events are\r
1157                 * delivered before any special qp services are invoked.\r
1158                 */\r
1159                 cl_thread_suspend( 50 );\r
1160         }\r
1161 \r
1162         /* Allocate an access layer instance. */\r
1163         h_al = (ib_al_handle_t)cl_zalloc( sizeof( ib_al_t ) );\r
1164         if( !h_al )\r
1165         {\r
1166                 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("cl_malloc failed\n") );\r
1167                 return IB_INSUFFICIENT_MEMORY;\r
1168         }\r
1169 \r
1170         /* Construct the instance. */\r
1171         construct_al_obj( &h_al->obj, AL_OBJ_TYPE_H_AL );\r
1172         cl_spinlock_construct( &h_al->mad_lock );\r
1173         cl_qlist_init( &h_al->mad_list );\r
1174         cl_qlist_init( &h_al->key_list );\r
1175         cl_qlist_init( &h_al->query_list );\r
1176         cl_qlist_init( &h_al->cep_list );\r
1177 \r
1178         if( cl_spinlock_init( &h_al->mad_lock ) != CL_SUCCESS )\r
1179         {\r
1180                 free_al( &h_al->obj );\r
1181                 AL_EXIT( AL_DBG_ERROR );\r
1182                 return IB_ERROR;\r
1183         }\r
1184 \r
1185         /* Initialize the base object. */\r
1186         status = init_al_obj( &h_al->obj, NULL, FALSE,\r
1187                 destroying_al, NULL, free_al );\r
1188         if( status != IB_SUCCESS )\r
1189         {\r
1190                 free_al( &h_al->obj );\r
1191                 AL_EXIT(AL_DBG_MGR);\r
1192                 return status;\r
1193         }\r
1194         attach_al_obj( &gp_al_mgr->obj, &h_al->obj );\r
1195 \r
1196         /*\r
1197          * Self reference the AL instance so that all attached objects\r
1198          * insert themselve in the instance's handle manager automatically.\r
1199          */\r
1200         h_al->obj.h_al = h_al;\r
1201 \r
1202         /*\r
1203          * We only maintain a single AL instance in the kernel.  It is created\r
1204          * automatically when the device is opened.\r
1205          */\r
1206         if( !gh_al )\r
1207         {\r
1208                 /* Save a copy of the implicit al handle in a global */\r
1209                 gh_al = h_al;\r
1210         }\r
1211 \r
1212         /* Return UAL's handle to caller */\r
1213         *ph_al = (ib_al_handle_t)h_al;\r
1214 \r
1215         /* Release the reference taken in init_al_obj. */\r
1216         deref_al_obj( &h_al->obj );\r
1217 \r
1218         AL_EXIT(AL_DBG_MGR);\r
1219         return IB_SUCCESS;\r
1220 }\r
1221 \r
1222 \r
1223 static DWORD WINAPI\r
1224 __cb_thread_routine(\r
1225         IN                              void                                            *context )\r
1226 {\r
1227         DWORD           ret_bytes, err;\r
1228         OVERLAPPED      *p_ov;\r
1229         ULONG_PTR       key;\r
1230         BOOL            ret;\r
1231 \r
1232         AL_ENTER( AL_DBG_MGR );\r
1233 \r
1234         UNUSED_PARAM( context );\r
1235 \r
1236         do\r
1237         {\r
1238                 ret = GetQueuedCompletionStatus( gp_al_mgr->ual_mgr.h_cb_port,\r
1239                         &ret_bytes, &key, &p_ov, INFINITE );\r
1240 \r
1241                 if( ret && !p_ov )\r
1242                         break;\r
1243 \r
1244                 if( !ret )\r
1245                         err = GetLastError();\r
1246                 else\r
1247                         err = 0;\r
1248 \r
1249                 CL_ASSERT( p_ov );\r
1250                 switch( key )\r
1251                 {\r
1252                 case UAL_BIND_CM:\r
1253                         //DebugBreak();\r
1254                         /* CM callback. */\r
1255                         cm_cb( err, ret_bytes, p_ov );\r
1256                         break;\r
1257 \r
1258                 case UAL_BIND_CQ:\r
1259                         /* CQ completion callback. */\r
1260                         cq_cb( err, ret_bytes, p_ov );\r
1261                         break;\r
1262 \r
1263                 case UAL_BIND_MISC:\r
1264                         /* Misc callback. */\r
1265                         misc_cb( err, ret_bytes, p_ov );\r
1266                         break;\r
1267 \r
1268                 case UAL_BIND_PNP:\r
1269                         /* PnP callback. */\r
1270                         pnp_cb( err, ret_bytes, p_ov );\r
1271                         break;\r
1272 \r
1273                 case UAL_BIND_SA:\r
1274                         /* SA callback. */\r
1275                         sa_req_cb( err, ret_bytes, p_ov );\r
1276                         break;\r
1277 \r
1278                 case UAL_BIND_DESTROY:\r
1279                         if( p_ov )\r
1280                                 deref_al_obj( (al_obj_t*)p_ov->Pointer );\r
1281                         break;\r
1282 \r
1283                 default:\r
1284                         CL_ASSERT( key == UAL_BIND_CM || key == UAL_BIND_CQ ||\r
1285                                 key == UAL_BIND_MISC || key == UAL_BIND_PNP ||\r
1286                                 key == UAL_BIND_SA || key == UAL_BIND_DESTROY );\r
1287                         break;\r
1288                 }\r
1289         } while( !ret || p_ov );\r
1290 \r
1291         AL_EXIT( AL_DBG_MGR );\r
1292         ExitThread( 0 );\r
1293 }\r