1cfeb675b50e952051b21ae395e56a67855faffd
[mirror/winof/.git] / core / bus / kernel / bus_port_mgr.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  * Copyright (c) 2006 Mellanox Technologies.  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 <iba/ib_types.h>\r
35 #include <complib/cl_async_proc.h>\r
36 #include <complib/cl_bus_ifc.h>\r
37 #include "ib_common.h"\r
38 #include "bus_pnp.h"\r
39 #include "bus_port_mgr.h"\r
40 #include "al_ca.h"\r
41 #include "al_mgr.h"\r
42 #include <initguid.h>\r
43 #include <wdmguid.h>\r
44 #include "iba/ipoib_ifc.h"\r
45 #include "al_dev.h"\r
46 \r
47 #define IPOIB_PART_DEVICE_ID    L"IBA\\IPoIBP"\r
48 #define IPOIB_DEVICE_ID                 L"IBA\\IPoIB"\r
49 #define IPOIB_COMPAT_ID                 L"IBA\\SID_1000066a00020000\0\0"\r
50 /* Hardware ID is a MULTI_SZ, so is terminated with a double NULL. */\r
51 #define IPOIB_HARDWARE_ID               IPOIB_DEVICE_ID L"\0"\r
52 #define IPOIB_PART_HARDWARE_ID  IPOIB_PART_DEVICE_ID L"\0"\r
53 #define IPOIB_DESCRIPTION               L"OpenIB IPoIB Adapter"\r
54 \r
55 /* {5A9649F4-0101-4a7c-8337-796C48082DA2} */\r
56 DEFINE_GUID(GUID_BUS_TYPE_IBA,\r
57 0x5a9649f4, 0x101, 0x4a7c, 0x83, 0x37, 0x79, 0x6c, 0x48, 0x8, 0x2d, 0xa2);\r
58 \r
59 \r
60 /*\r
61  * Device extension for IPoIB port PDOs.\r
62  */\r
63 typedef struct _bus_port_ext\r
64 {\r
65         bus_pdo_ext_t                   pdo;\r
66 \r
67         port_guid_pkey_t                port_guid;\r
68         uint32_t                                n_port;\r
69 \r
70         /* Number of references on the upper interface. */\r
71         atomic32_t                              n_ifc_ref;\r
72 \r
73 }       bus_port_ext_t;\r
74 \r
75 \r
76 typedef struct _port_pnp_context\r
77 {\r
78         bus_filter_t    *p_bus_filter;\r
79         void                    *p_pdo_ext;\r
80         int                             port_num;\r
81 \r
82 }       port_pnp_ctx_t;\r
83 \r
84 \r
85 extern pkey_array_t  g_pkeys;\r
86 \r
87 /*\r
88  * Function prototypes.\r
89  */\r
90 void\r
91 destroying_port_mgr(\r
92         IN                              cl_obj_t*                                       p_obj );\r
93 \r
94 void\r
95 free_port_mgr(\r
96         IN                              cl_obj_t*                                       p_obj );\r
97 \r
98 ib_api_status_t\r
99 bus_reg_port_pnp(\r
100         IN                              bus_filter_t*                           p_bfi );\r
101 \r
102 ib_api_status_t\r
103 port_mgr_pnp_cb(\r
104         IN                              ib_pnp_rec_t*                           p_pnp_rec );\r
105 \r
106 ib_api_status_t\r
107 port_mgr_port_add(\r
108         IN                              ib_pnp_port_rec_t*                      p_pnp_rec );\r
109 \r
110 void\r
111 port_mgr_port_remove(\r
112         IN                              ib_pnp_port_rec_t*                      p_pnp_rec );\r
113 \r
114 static NTSTATUS\r
115 port_start(\r
116         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
117         IN                              IRP* const                                      p_irp,\r
118                 OUT                     cl_irp_action_t* const          p_action );\r
119 \r
120 static NTSTATUS\r
121 port_query_remove(\r
122         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
123         IN                              IRP* const                                      p_irp,\r
124                 OUT                     cl_irp_action_t* const          p_action );\r
125 \r
126 static void\r
127 port_release_resources(\r
128         IN                              DEVICE_OBJECT* const            p_dev_obj );\r
129 \r
130 static NTSTATUS\r
131 port_remove(\r
132         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
133         IN                              IRP* const                                      p_irp,\r
134                 OUT                     cl_irp_action_t* const          p_action );\r
135 \r
136 static NTSTATUS\r
137 port_surprise_remove(\r
138         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
139         IN                              IRP* const                                      p_irp,\r
140                 OUT                     cl_irp_action_t* const          p_action );\r
141 \r
142 static NTSTATUS\r
143 port_query_capabilities(\r
144         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
145         IN                              IRP* const                                      p_irp,\r
146                 OUT                     cl_irp_action_t* const          p_action );\r
147 \r
148 static NTSTATUS\r
149 port_query_target_relations(\r
150         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
151         IN                              IRP* const                                      p_irp,\r
152                 OUT                     cl_irp_action_t* const          p_action );\r
153 \r
154 static NTSTATUS\r
155 port_query_device_id(\r
156         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
157         IN                              IRP* const                                      p_irp );\r
158 \r
159 static NTSTATUS\r
160 port_query_hardware_ids(\r
161         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
162         IN                              IRP* const                                      p_irp );\r
163 \r
164 static NTSTATUS\r
165 port_query_compatible_ids(\r
166         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
167         IN                              IRP* const                                      p_irp );\r
168 \r
169 static NTSTATUS\r
170 port_query_unique_id(\r
171         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
172         IN                              IRP* const                                      p_irp );\r
173 \r
174 static NTSTATUS\r
175 port_query_description(\r
176         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
177         IN                              IRP* const                                      p_irp );\r
178 \r
179 static NTSTATUS\r
180 port_query_location(\r
181         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
182         IN                              IRP* const                                      p_irp );\r
183 \r
184 static NTSTATUS\r
185 port_query_bus_info(\r
186         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
187         IN                              IRP* const                                      p_irp,\r
188                 OUT                     cl_irp_action_t* const          p_action );\r
189 \r
190 static NTSTATUS\r
191 port_query_ipoib_ifc(\r
192         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
193         IN                              IO_STACK_LOCATION* const        p_io_stack );\r
194 \r
195 static NTSTATUS\r
196 port_query_interface(\r
197         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
198         IN                              IRP* const                                      p_irp,\r
199                 OUT                     cl_irp_action_t* const          p_action );\r
200 \r
201 static NTSTATUS\r
202 port_set_power(\r
203         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
204         IN                              IRP* const                                      p_irp,\r
205                 OUT                     cl_irp_action_t* const          p_action );\r
206 \r
207 \r
208 /* All PnP code is called at passive, so it can all be paged out. */\r
209 #ifdef ALLOC_PRAGMA\r
210 #pragma alloc_text (PAGE, port_start)\r
211 #pragma alloc_text (PAGE, port_query_remove)\r
212 #pragma alloc_text (PAGE, port_release_resources)\r
213 #pragma alloc_text (PAGE, port_remove)\r
214 #pragma alloc_text (PAGE, port_surprise_remove)\r
215 #pragma alloc_text (PAGE, port_query_capabilities)\r
216 #pragma alloc_text (PAGE, port_query_target_relations)\r
217 #pragma alloc_text (PAGE, port_query_device_id)\r
218 #pragma alloc_text (PAGE, port_query_hardware_ids)\r
219 #pragma alloc_text (PAGE, port_query_compatible_ids)\r
220 #pragma alloc_text (PAGE, port_query_unique_id)\r
221 #pragma alloc_text (PAGE, port_query_description)\r
222 #pragma alloc_text (PAGE, port_query_location)\r
223 #pragma alloc_text (PAGE, port_query_bus_info)\r
224 #pragma alloc_text (PAGE, port_query_ipoib_ifc)\r
225 #pragma alloc_text (PAGE, port_query_interface)\r
226 #pragma alloc_text (PAGE_PNP, port_set_power)\r
227 #pragma alloc_text (PAGE, port_mgr_port_add)\r
228 #pragma alloc_text (PAGE, port_mgr_port_remove)\r
229 #endif\r
230 \r
231 \r
232 /*\r
233  * Global virtual function pointer tables shared between all\r
234  * instances of Port PDOs.\r
235  */\r
236 static const cl_vfptr_pnp_po_t          vfptr_port_pnp = {\r
237         "IPoIB",\r
238         port_start,\r
239         cl_irp_succeed,\r
240         cl_irp_succeed,\r
241         cl_irp_succeed,\r
242         port_query_remove,\r
243         port_release_resources,\r
244         port_remove,\r
245         cl_irp_succeed,\r
246         port_surprise_remove,\r
247         port_query_capabilities,\r
248         cl_irp_complete,\r
249         cl_irp_complete,\r
250         cl_irp_succeed,\r
251         cl_irp_complete,\r
252         cl_irp_complete,\r
253         cl_irp_complete,\r
254         port_query_target_relations,\r
255         cl_irp_complete,\r
256         cl_irp_complete,\r
257         cl_irp_complete,\r
258         port_query_bus_info,\r
259         port_query_interface,\r
260         cl_irp_complete,\r
261         cl_irp_complete,\r
262         cl_irp_complete,\r
263         cl_irp_complete,\r
264         cl_irp_succeed,                         // QueryPower\r
265         port_set_power,                         // SetPower\r
266         cl_irp_unsupported,                     // PowerSequence\r
267         cl_irp_unsupported                      // WaitWake\r
268 };\r
269 \r
270 \r
271 static const cl_vfptr_query_txt_t               vfptr_port_query_txt = {\r
272         port_query_device_id,\r
273         port_query_hardware_ids,\r
274         port_query_compatible_ids,\r
275         port_query_unique_id,\r
276         port_query_description,\r
277         port_query_location\r
278 };\r
279 \r
280 \r
281 /*\r
282  * Create the AL load service.\r
283  */\r
284 ib_api_status_t\r
285 create_port_mgr(\r
286                 IN                      bus_filter_t*                           p_bfi,\r
287                 OUT                     port_mgr_t** const                      pp_port_mgr )\r
288 {\r
289         ib_api_status_t         status;\r
290         cl_status_t                     cl_status;\r
291         port_mgr_t                      *gp_port_mgr;\r
292 \r
293         BUS_ENTER( BUS_DBG_PNP );\r
294 \r
295         CL_ASSERT( p_bfi->p_port_mgr == NULL );\r
296 \r
297         gp_port_mgr = cl_zalloc( sizeof( port_mgr_t ) );\r
298         if( !gp_port_mgr )\r
299         {\r
300                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
301                         ("Failed to allocate port manager.\n") );\r
302                 return IB_INSUFFICIENT_MEMORY;\r
303         }\r
304         p_bfi->p_port_mgr = gp_port_mgr;\r
305 \r
306         /* Construct the load service. */\r
307         cl_obj_construct( &gp_port_mgr->obj, AL_OBJ_TYPE_LOADER );\r
308         p_bfi->p_port_mgr_obj = &gp_port_mgr->obj;\r
309         cl_mutex_construct( &gp_port_mgr->pdo_mutex );\r
310         cl_qlist_init( &gp_port_mgr->port_list );\r
311 \r
312         cl_status = cl_mutex_init( &gp_port_mgr->pdo_mutex );\r
313         if( cl_status != CL_SUCCESS )\r
314         {\r
315                 free_port_mgr( &gp_port_mgr->obj );\r
316                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
317                         ("cl_mutex_init returned %#x.\n", cl_status) );\r
318                 return ib_convert_cl_status( cl_status );\r
319         }\r
320 \r
321         /* Initialize the load service object. */\r
322         cl_status = cl_obj_init( &gp_port_mgr->obj, CL_DESTROY_SYNC,\r
323                                                          destroying_port_mgr, NULL, free_port_mgr );\r
324 \r
325         if( cl_status != CL_SUCCESS )\r
326         {\r
327                 free_port_mgr( &gp_port_mgr->obj );\r
328                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
329                         ("cl_obj_init returned %#x.\n", cl_status) );\r
330                 return ib_convert_cl_status( cl_status );\r
331         }\r
332 \r
333         /* Register for port PnP events */\r
334         status = bus_reg_port_pnp(p_bfi);\r
335         if( status != IB_SUCCESS )\r
336         {\r
337                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
338                         ("bus_reg_port_pnp returned %s.\n", ib_get_err_str(status)) );\r
339                 free_port_mgr( &gp_port_mgr->obj );\r
340                 return status;\r
341         }\r
342 \r
343         *pp_port_mgr = gp_port_mgr;\r
344 \r
345         BUS_EXIT( BUS_DBG_PNP );\r
346         return IB_SUCCESS;\r
347 }\r
348 \r
349 \r
350 /*\r
351  * Pre-destroy the load service.\r
352  */\r
353 void\r
354 destroying_port_mgr(\r
355         IN                              cl_obj_t*                                       p_obj )\r
356 {\r
357         ib_api_status_t                 status;\r
358         bus_filter_t                    *p_bfi;\r
359         port_mgr_t                              *gp_port_mgr;\r
360 \r
361         BUS_ENTER( BUS_DBG_PNP );\r
362 \r
363         CL_ASSERT( p_obj );\r
364         p_bfi = get_bfi_by_obj(BFI_PORT_MGR_OBJ, p_obj);\r
365         if (p_bfi == NULL) {\r
366                 BUS_PRINT(BUS_DBG_PNP, ("%s() failed to find p_bfi by obj %p?\n",\r
367                         __FUNCTION__,p_obj));\r
368                 return;\r
369         }\r
370         gp_port_mgr = p_bfi->p_port_mgr;\r
371 \r
372         BUS_PRINT(BUS_DBG_PNP, ("%s(%s) obj %p port_mgr %p port_mgr_obj %p\n",\r
373                         __FUNCTION__,p_bfi->whoami,p_obj,gp_port_mgr,\r
374                         p_bfi->p_port_mgr_obj) );\r
375 \r
376         CL_ASSERT( (void*)p_bfi->p_port_mgr == (void*)p_bfi->p_port_mgr_obj );\r
377         CL_ASSERT( gp_port_mgr == PARENT_STRUCT( p_obj, port_mgr_t, obj ) );\r
378 \r
379         /* Deregister for port PnP events if this is the last Port manager. */\r
380         if ( get_bfi_count() == 1 && bus_globals.h_pnp_port ) {\r
381                 status = ib_dereg_pnp( bus_globals.h_pnp_port, NULL );\r
382                 bus_globals.h_pnp_port = NULL;\r
383                 CL_ASSERT( status == IB_SUCCESS );\r
384         }\r
385         cl_obj_deref( p_bfi->p_port_mgr_obj );\r
386 \r
387         BUS_EXIT( BUS_DBG_PNP );\r
388 }\r
389 \r
390 \r
391 /*\r
392  * Free the load service.\r
393  */\r
394 void\r
395 free_port_mgr(\r
396         IN                              cl_obj_t*                                       p_obj )\r
397 {\r
398         bus_pdo_ext_t   *p_ext;\r
399         cl_list_item_t  *p_list_item;\r
400         bus_filter_t    *p_bfi;\r
401         port_mgr_t              *gp_port_mgr;\r
402 \r
403         BUS_ENTER( BUS_DBG_PNP );\r
404 \r
405         CL_ASSERT( p_obj );\r
406         p_bfi = get_bfi_by_obj(BFI_PORT_MGR_OBJ, p_obj);\r
407         if (p_bfi == NULL) {\r
408                 BUS_PRINT(BUS_DBG_PNP, ("%s: unable to get p_bfi for port obj %p?\n",\r
409                         __FUNCTION__,p_obj));\r
410                 return;\r
411         }\r
412         gp_port_mgr = p_bfi->p_port_mgr;\r
413         if ( !gp_port_mgr ) {\r
414                 // if create fails & then free is called, p_bfi->p_port_mgr == NULL\r
415                 return;\r
416         }\r
417         CL_ASSERT( gp_port_mgr == PARENT_STRUCT( p_obj, port_mgr_t, obj ) );\r
418 \r
419         BUS_PRINT(BUS_DBG_PNP, ("%s(%s) obj %p port_mgr %p port_mgr_obj %p\n",\r
420                         __FUNCTION__, p_bfi->whoami, p_obj,gp_port_mgr,\r
421                         p_bfi->p_port_mgr_obj) );\r
422 \r
423         BUS_PRINT( BUS_DBG_PNP,\r
424                                 ("%s(%s) Mark all IPoIB PDOs as no longer present\n",\r
425                                 __FUNCTION__, p_bfi->whoami));\r
426         /*\r
427          * Mark all IPoIB PDOs as no longer present.  This will cause them\r
428          * to be removed when they process the IRP_MN_REMOVE_DEVICE.\r
429          */\r
430         p_list_item = cl_qlist_remove_head( &gp_port_mgr->port_list );\r
431         while( p_list_item != cl_qlist_end( &gp_port_mgr->port_list ) )\r
432         {\r
433                 p_ext = PARENT_STRUCT( p_list_item, bus_pdo_ext_t, list_item );\r
434                 p_list_item = cl_qlist_remove_head( &gp_port_mgr->port_list );\r
435                 if( p_ext->cl_ext.pnp_state == SurpriseRemoved )\r
436                 {\r
437                         CL_ASSERT( !p_ext->b_present );\r
438                         p_ext->b_reported_missing = TRUE;\r
439                         BUS_TRACE( BUS_DBG_PNP,\r
440                                 ("%s %s: PDO %p, ext %p, present %d, missing %d .\n",\r
441                                 p_bfi->whoami,\r
442                                 p_ext->cl_ext.vfptr_pnp_po->identity, p_ext->cl_ext.p_self_do,\r
443                                 p_ext, p_ext->b_present, p_ext->b_reported_missing ) );\r
444                         continue;\r
445                 }\r
446                 if( p_ext->h_ca && (!p_ext->is_partition_pdo))\r
447                 {\r
448                         /* Invalidate bus relations for the HCA. */\r
449                         IoInvalidateDeviceRelations(\r
450                                 p_ext->h_ca->obj.p_ci_ca->verbs.p_hca_dev, BusRelations );\r
451 \r
452                         /* Release the reference on the CA object. */\r
453                         deref_al_obj( &p_ext->h_ca->obj );\r
454                 }\r
455 \r
456                 BUS_TRACE( BUS_DBG_PNP, ("%s Deleted device %s: PDO %p, ext %p\n",\r
457                                         p_bfi->whoami, p_ext->cl_ext.vfptr_pnp_po->identity,\r
458                                         p_ext->cl_ext.p_self_do, p_ext ) );\r
459 \r
460                 IoDeleteDevice( p_ext->cl_ext.p_self_do );\r
461         }\r
462 \r
463         cl_mutex_destroy( &gp_port_mgr->pdo_mutex );\r
464         cl_obj_deinit( p_obj );\r
465         cl_free( gp_port_mgr );\r
466 \r
467         p_bfi->p_port_mgr = NULL;\r
468         p_bfi->p_port_mgr_obj = NULL;\r
469 \r
470         BUS_EXIT( BUS_DBG_PNP );\r
471 }\r
472 \r
473 \r
474 /*\r
475  * Register the load service for the given PnP class events.\r
476  */\r
477 ib_api_status_t\r
478 bus_reg_port_pnp( IN bus_filter_t *p_bfi )\r
479 {\r
480         ib_pnp_req_t                    pnp_req;\r
481         ib_api_status_t                 status = IB_SUCCESS;\r
482         boolean_t                               need_pnp_reg = FALSE;\r
483 \r
484         /* only need to register for port PNP events once.\r
485          * Do not hold mutex over pnp_reg() call as callback which needs mutex\r
486          * could occur.\r
487          */\r
488         if ( !bus_globals.h_pnp_port )\r
489         {\r
490                 ExAcquireFastMutexUnsafe(&ControlMutex);\r
491                 if ( !bus_globals.h_pnp_port ) {\r
492                         bus_globals.h_pnp_port = (ib_pnp_handle_t)1; /* block others */\r
493                         need_pnp_reg = TRUE;\r
494                 }\r
495                 ExReleaseFastMutexUnsafe(&ControlMutex);\r
496 \r
497                 if ( need_pnp_reg )\r
498                 {\r
499                         cl_memclr( &pnp_req, sizeof( ib_pnp_req_t ) );\r
500                         pnp_req.pnp_class       = IB_PNP_PORT | IB_PNP_FLAG_REG_SYNC;\r
501                         pnp_req.pnp_context = NULL;\r
502                         pnp_req.pfn_pnp_cb      = port_mgr_pnp_cb;\r
503 \r
504                         status = ib_reg_pnp( gh_al, &pnp_req, &bus_globals.h_pnp_port );\r
505                 }\r
506         }\r
507 \r
508         if ( status == IB_SUCCESS )\r
509         {\r
510                 /* Reference this bus filter's port load service */\r
511                 cl_obj_ref( &p_bfi->p_port_mgr->obj );\r
512         }\r
513 \r
514         return status;\r
515 }\r
516 \r
517 \r
518 /*\r
519  * Load service PnP event callback.\r
520  */\r
521 ib_api_status_t\r
522 port_mgr_pnp_cb(\r
523         IN                              ib_pnp_rec_t*                           p_pnp_rec )\r
524 {\r
525         ib_api_status_t         status=IB_SUCCESS;\r
526 \r
527         BUS_ENTER( BUS_DBG_PNP );\r
528 \r
529         CL_ASSERT( p_pnp_rec );\r
530 \r
531         switch( p_pnp_rec->pnp_event )\r
532         {\r
533         case IB_PNP_PORT_ADD:\r
534                 status = port_mgr_port_add( (ib_pnp_port_rec_t*)p_pnp_rec );\r
535                 break;\r
536 \r
537         case IB_PNP_PORT_REMOVE:\r
538                 port_mgr_port_remove( (ib_pnp_port_rec_t*)p_pnp_rec );\r
539                 break;\r
540 \r
541         default:\r
542                 XBUS_PRINT( BUS_DBG_PNP, ("%s() Unhandled PNP Event %s\n",\r
543                                         __FUNCTION__, ib_get_pnp_event_str(p_pnp_rec->pnp_event) ));\r
544                 break;\r
545         }\r
546         BUS_EXIT( BUS_DBG_PNP );\r
547 \r
548         return status;\r
549 }\r
550 \r
551 \r
552 /*\r
553  * Called to get bus relations for an HCA.\r
554  */\r
555 NTSTATUS\r
556 port_mgr_get_bus_relations(\r
557         IN              const   net64_t                                         ca_guid,\r
558         IN                              IRP* const                                      p_irp )\r
559 {\r
560         NTSTATUS                        status;\r
561         bus_filter_t            *p_bfi;\r
562         port_mgr_t                      *gp_port_mgr;\r
563         DEVICE_RELATIONS        *p_rel;\r
564 \r
565         BUS_ENTER( BUS_DBG_PNP );\r
566 \r
567         BUS_PRINT(BUS_DBG_PNP, ("%s() ca_guid %I64x\n",__FUNCTION__,ca_guid));\r
568 \r
569         /* special case guid == 0 - walk all bus filter instances */\r
570         if ( ca_guid == 0ULL ) {\r
571                 for(p_bfi=bus_filters; p_bfi < &bus_filters[MAX_BUS_FILTERS]; p_bfi++) {\r
572                         gp_port_mgr = p_bfi->p_port_mgr;\r
573                         if ( !gp_port_mgr )\r
574                                 continue;\r
575                         cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
576                         status = bus_get_relations( &gp_port_mgr->port_list,\r
577                                                                                 ca_guid,\r
578                                                                                 p_irp );\r
579                         cl_mutex_release( &gp_port_mgr->pdo_mutex );\r
580                 }\r
581 \r
582                 p_rel = (DEVICE_RELATIONS*)p_irp->IoStatus.Information;\r
583                 if ( p_rel ) {\r
584                         BUS_PRINT(BUS_DBG_PNP, ("%s() ca_guid 0 Reports %d\n",\r
585                                                 __FUNCTION__,p_rel->Count));\r
586                 }\r
587                 BUS_EXIT( BUS_DBG_PNP );\r
588                 return STATUS_SUCCESS;\r
589         }\r
590 \r
591         p_bfi = get_bfi_by_ca_guid(ca_guid);\r
592         if (p_bfi == NULL) {\r
593                 BUS_PRINT(BUS_DBG_PNP,\r
594                         ("%s() Null *p_bfi from ca_guid %I64x\n",__FUNCTION__,ca_guid));\r
595                 BUS_EXIT( BUS_DBG_PNP );\r
596                 return STATUS_NO_SUCH_DEVICE;\r
597         }\r
598         gp_port_mgr = p_bfi->p_port_mgr;\r
599 \r
600         BUS_PRINT(BUS_DBG_PNP, ("%s(%s) for ca_guid %I64x port_mgr %p\n",\r
601                                 __FUNCTION__, p_bfi->whoami, ca_guid, gp_port_mgr) );\r
602         if (!gp_port_mgr)\r
603                 return STATUS_NO_SUCH_DEVICE;\r
604 \r
605         cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
606         status = bus_get_relations( &gp_port_mgr->port_list, ca_guid, p_irp );\r
607         cl_mutex_release( &gp_port_mgr->pdo_mutex );\r
608 \r
609         BUS_EXIT( BUS_DBG_PNP );\r
610         return STATUS_SUCCESS;\r
611 }\r
612 \r
613 static ib_api_status_t\r
614 __port_was_hibernated(\r
615         IN                              ib_pnp_port_rec_t*                      p_pnp_rec,\r
616         IN                              bus_filter_t*                           p_bfi )\r
617 {\r
618         NTSTATUS                status;\r
619         cl_list_item_t  *p_list_item;\r
620         bus_port_ext_t  *p_port_ext;\r
621         bus_pdo_ext_t   *p_pdo_ext = NULL;\r
622         size_t                  n_devs = 0;\r
623         port_mgr_t              *gp_port_mgr = p_bfi->p_port_mgr;\r
624         cl_qlist_t              *p_pdo_list = &gp_port_mgr->port_list;\r
625         port_pnp_ctx_t  *p_ctx = p_pnp_rec->pnp_rec.context;\r
626 \r
627         BUS_ENTER( BUS_DBG_PNP );\r
628         \r
629         cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
630         \r
631         /* Count the number of child devices. */\r
632         for( p_list_item = cl_qlist_head( p_pdo_list );\r
633                 p_list_item != cl_qlist_end( p_pdo_list );\r
634                 p_list_item = cl_qlist_next( p_list_item ) )\r
635         {\r
636                 p_pdo_ext = PARENT_STRUCT( p_list_item, bus_pdo_ext_t, list_item );\r
637                 p_port_ext = (bus_port_ext_t*)p_pdo_ext;\r
638         \r
639                 if( p_pdo_ext->b_present && p_pdo_ext->b_hibernating &&\r
640                         (p_port_ext->port_guid.guid == p_pnp_rec->p_port_attr->port_guid) )\r
641                 {\r
642                         n_devs++;\r
643                         break;\r
644                 }\r
645 \r
646                 BUS_TRACE( BUS_DBG_PNP, ("%s Skipped PDO for %s: PDO %p, ext %p, "\r
647                         "present %d, missing %d, hibernating %d, port_guid %I64x.\n",\r
648                         p_bfi->whoami,\r
649                         p_pdo_ext->cl_ext.vfptr_pnp_po->identity,\r
650                         p_pdo_ext->cl_ext.p_self_do, \r
651                         p_pdo_ext, p_pdo_ext->b_present, p_pdo_ext->b_reported_missing, \r
652                         p_pdo_ext->b_hibernating, p_port_ext->port_guid.guid  ) );\r
653         }\r
654 \r
655         if (n_devs)\r
656         {\r
657                 /* Take a reference on the parent HCA. */\r
658                 p_pdo_ext->h_ca = acquire_ca( p_pnp_rec->p_ca_attr->ca_guid );\r
659                 if( !p_pdo_ext->h_ca )\r
660                 {\r
661                         BUS_TRACE( BUS_DBG_ERROR,\r
662                                 ("%s acquire_ca failed to find CA by guid %I64x\n",\r
663                                 p_bfi->whoami, p_pnp_rec->p_ca_attr->ca_guid ) );\r
664                         status = IB_INVALID_GUID;\r
665                 }\r
666                 else \r
667                 {\r
668                         p_pdo_ext->b_hibernating = FALSE;\r
669 \r
670                         CL_ASSERT( p_ctx );\r
671                         p_ctx->p_pdo_ext = p_pdo_ext; // save for port_mgr_port_remove\r
672 \r
673                         status = IB_SUCCESS;\r
674                         p_port_ext = (bus_port_ext_t*)p_pdo_ext;\r
675                         BUS_TRACE( BUS_DBG_PNP, ("%s Found PDO for %s: PDO %p, ext %p, "\r
676                                 "present %d, missing %d, hibernating %d, port_guid %I64x.\n",\r
677                                 p_bfi->whoami,\r
678                                 p_pdo_ext->cl_ext.vfptr_pnp_po->identity,\r
679                                 p_pdo_ext->cl_ext.p_self_do, \r
680                                 p_pdo_ext, p_pdo_ext->b_present, p_pdo_ext->b_reported_missing, \r
681                                 p_pdo_ext->b_hibernating, p_port_ext->port_guid.guid ) );\r
682                 }\r
683         }\r
684         else \r
685         {\r
686                 BUS_TRACE( BUS_DBG_PNP, ("%s Failed to find PDO for guid  %I64x .\n",\r
687                                         p_bfi->whoami, p_pnp_rec->p_ca_attr->ca_guid ) );\r
688                 status = IB_NOT_FOUND;\r
689         }\r
690 \r
691         cl_mutex_release( &gp_port_mgr->pdo_mutex );\r
692 \r
693         BUS_EXIT( BUS_DBG_PNP );\r
694         return status;\r
695 }\r
696 \r
697 #if DBG\r
698 \r
699 void\r
700 dump_pnp_port_rec( ib_pnp_port_rec_t*   pr )\r
701 {\r
702         BUS_PRINT( BUS_DBG_PNP, ("%s() ib_pnp_port_rec_t* @ %p\nib_pnp_rec_t*:\n",\r
703                                 __FUNCTION__,pr));\r
704 \r
705 \r
706         BUS_PRINT( BUS_DBG_PNP, ("  Event %s\n",\r
707                                 ib_get_pnp_event_str(pr->pnp_rec.pnp_event) ));\r
708 \r
709         BUS_PRINT( BUS_DBG_PNP, ("  pnp_context %p\n",pr->pnp_rec.pnp_context));\r
710         BUS_PRINT( BUS_DBG_PNP, ("  context %p\n",pr->pnp_rec.context));\r
711         BUS_PRINT( BUS_DBG_PNP, ("  guid %I64x\n",pr->pnp_rec.guid));\r
712         BUS_PRINT( BUS_DBG_PNP, ("  ca_guid %I64x\n",pr->pnp_rec.ca_guid));\r
713 \r
714         if ( !pr->p_ca_attr ) {\r
715                 BUS_PRINT( BUS_DBG_PNP, ("  NULL *p_ca_attr ?\n"));\r
716         }\r
717         else {\r
718                 BUS_PRINT( BUS_DBG_PNP, ("*p_ca_attr\n"));\r
719                 BUS_PRINT( BUS_DBG_PNP, ("  ca_guid 0x%I64x\n",\r
720                                                                 pr->p_ca_attr->ca_guid ) );\r
721         }\r
722         if ( !pr->p_port_attr ) {\r
723                 BUS_PRINT( BUS_DBG_PNP, ("  NULL *p_port_attr?\n"));\r
724         }\r
725         else {\r
726                 BUS_PRINT( BUS_DBG_PNP, ("*p_port_attr:\n"));\r
727                 BUS_PRINT( BUS_DBG_PNP, ("  port_guid 0x%I64x port_num %d\n",\r
728                                                                 pr->p_port_attr->port_guid,\r
729                                                                 pr->p_port_attr->port_num ));\r
730         }\r
731 }\r
732 \r
733 void\r
734 dump_pnp_iou_rec( ib_pnp_iou_rec_t*     pr )\r
735 {\r
736         BUS_PRINT( BUS_DBG_PNP, ("%s() ib_pnp_iou_rec_t* @ %p\nib_pnp_rec_t*:\n",\r
737                                 __FUNCTION__,pr));\r
738 \r
739 \r
740         BUS_PRINT( BUS_DBG_PNP, ("  Event %s\n",\r
741                                 ib_get_pnp_event_str(pr->pnp_rec.pnp_event) ));\r
742 \r
743         BUS_PRINT( BUS_DBG_PNP, ("  pnp_context %p\n",pr->pnp_rec.pnp_context));\r
744         BUS_PRINT( BUS_DBG_PNP, ("  context %p\n",pr->pnp_rec.context));\r
745         BUS_PRINT( BUS_DBG_PNP, ("  guid %I64x\n",pr->pnp_rec.guid));\r
746         BUS_PRINT( BUS_DBG_PNP, ("  ca_guid %I64x\n",pr->pnp_rec.ca_guid));\r
747 \r
748         BUS_PRINT( BUS_DBG_PNP, ("pnp_iou_rec_t:\n" ));\r
749         BUS_PRINT( BUS_DBG_PNP,\r
750                                 ("  guid 0x%I64x\n  ca_guid %I64x\n  chassis_guid %I64x\n",\r
751                                 pr->guid, pr->ca_guid, pr->chassis_guid ));\r
752         BUS_PRINT( BUS_DBG_PNP,\r
753                                 ("  slot 0x%x\n  vend_id 0x%x\n  dev_id 0x%x  revision 0x%x\n",\r
754                                 pr->slot, pr->vend_id, pr->dev_id, pr->revision ));\r
755         if ( pr->desc[0] ) {\r
756                 BUS_PRINT( BUS_DBG_PNP, ("  Desc %s\n",pr->desc ));\r
757         }\r
758 }\r
759 #endif\r
760 \r
761 \r
762 ib_api_status_t\r
763 port_mgr_port_add(\r
764         IN                              ib_pnp_port_rec_t*                      p_pnp_rec )\r
765 {\r
766         NTSTATUS                status;\r
767     DEVICE_OBJECT   *p_pdo[MAX_NUM_PKEY + 1];\r
768     uint8_t         num_pdo;\r
769         bus_port_ext_t  *p_port_ext;\r
770         ib_net16_t      pdo_cnt;\r
771         pkey_conf_t             *cur_conf; \r
772         pkey_array_t    *cur_pkeys = NULL;\r
773         bus_filter_t    *p_bfi;\r
774         port_mgr_t              *gp_port_mgr;\r
775         port_pnp_ctx_t  *p_ctx = p_pnp_rec->pnp_rec.context;\r
776 \r
777         BUS_ENTER( BUS_DBG_PNP );\r
778 \r
779         CL_ASSERT( p_pnp_rec->p_ca_attr->ca_guid );\r
780 \r
781         p_bfi = get_set_bfi_by_ca_guid( p_pnp_rec->p_ca_attr->ca_guid );\r
782         if ( !p_bfi ) {\r
783                 BUS_TRACE_EXIT( BUS_DBG_PNP,("%s() NULL p_bfi? ca_guid 0x%I64x\n",\r
784                                                                 __FUNCTION__, p_pnp_rec->p_ca_attr->ca_guid ) );\r
785                 return IB_ERROR;\r
786         }\r
787 \r
788         /*\r
789          * Allocate a PNP context for this object. pnp_rec.context is obj unique.\r
790          */\r
791         if ( !p_ctx ) {\r
792                 p_ctx = cl_zalloc( sizeof(*p_ctx) );\r
793                 if( !p_ctx )\r
794                 {\r
795                         BUS_TRACE_EXIT(BUS_DBG_PNP,\r
796                                         ("%s(%s) ca_guid %I64x port(%d) BAD alloc PNP context\n",\r
797                                         __FUNCTION__, p_bfi->whoami, p_bfi->ca_guid, \r
798                                         p_pnp_rec->p_port_attr->port_num));\r
799                         return IB_ERROR;\r
800                 }\r
801                 p_ctx->p_bus_filter = p_bfi;\r
802                 p_ctx->port_num = p_pnp_rec->p_port_attr->port_num;\r
803                 p_pnp_rec->pnp_rec.context = p_ctx;\r
804 \r
805                 BUS_PRINT(BUS_DBG_PNP,\r
806                                         ("%s(%s) ca_guid %I64x port %d ALLOC p_ctx @ %p\n",\r
807                                         __FUNCTION__, p_bfi->whoami, p_bfi->ca_guid, \r
808                                         p_pnp_rec->p_port_attr->port_num,p_ctx));\r
809         }\r
810         gp_port_mgr = p_bfi->p_port_mgr;\r
811 \r
812         if( !bus_globals.b_report_port_nic )\r
813         {\r
814                 BUS_EXIT( BUS_DBG_PNP );\r
815                 return IB_NOT_DONE;\r
816         }\r
817 \r
818         /* Upon hibernating the computer IB_BUS driver doesn't remove PDO, but\r
819            marks with a flag. So we first try to find an existing PDO for this port,\r
820            marked with this flag. If it was found, we turn off the flag and use\r
821            this PDO */\r
822         status = __port_was_hibernated( p_pnp_rec, p_bfi );\r
823         if( status != IB_NOT_FOUND )\r
824         {\r
825                 BUS_EXIT( BUS_DBG_PNP );\r
826                 return status;\r
827         }\r
828 \r
829         cur_conf = bus_globals.p_pkey_conf;\r
830         while(cur_conf)\r
831         {\r
832                 if(p_pnp_rec->p_port_attr->port_guid == cur_conf->pkeys_per_port.port_guid)\r
833                 {\r
834                         cur_pkeys = &cur_conf->pkeys_per_port;\r
835                         break;\r
836                 }\r
837                 cur_conf = cur_conf->next_conf;\r
838         }\r
839     p_port_ext = NULL;\r
840 \r
841         if( !cur_pkeys)\r
842                 pdo_cnt = 1;\r
843         else\r
844                 pdo_cnt = cur_conf->pkeys_per_port.pkey_num + 1;\r
845 \r
846     for (num_pdo = 0; num_pdo < pdo_cnt; num_pdo++)\r
847     {\r
848                 /* Create the PDO for the new port device. */\r
849                 status = IoCreateDevice( bus_globals.p_driver_obj,\r
850                                                                  sizeof(bus_port_ext_t),\r
851                                                                  NULL, FILE_DEVICE_CONTROLLER,\r
852                                                                  FILE_DEVICE_SECURE_OPEN |\r
853                                                                                         FILE_AUTOGENERATED_DEVICE_NAME,\r
854                                                                  FALSE, &p_pdo[num_pdo] );\r
855                 if( !NT_SUCCESS( status ) )\r
856                 {\r
857                         BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
858                                 ("IoCreateDevice returned %08x.\n", status) );\r
859                         return IB_ERROR;\r
860                 }\r
861 \r
862                 /* Initialize the device extension. */\r
863                 cl_init_pnp_po_ext( p_pdo[num_pdo], NULL, p_pdo[num_pdo],\r
864                                                         bus_globals.dbg_lvl, &vfptr_port_pnp,\r
865                                                         &vfptr_port_query_txt );\r
866 \r
867                 /* Set the DO_BUS_ENUMERATED_DEVICE flag to mark it as a PDO. */\r
868                 p_pdo[num_pdo]->Flags |= DO_BUS_ENUMERATED_DEVICE;\r
869 \r
870                 p_port_ext = p_pdo[num_pdo]->DeviceExtension;\r
871                 p_port_ext->pdo.dev_po_state.DeviceState = PowerDeviceD0;\r
872                 p_port_ext->pdo.p_parent_ext = p_bfi->p_bus_ext;\r
873                 p_port_ext->pdo.b_present = TRUE;\r
874                 p_port_ext->pdo.b_reported_missing = FALSE;\r
875                 p_port_ext->pdo.b_hibernating = FALSE;\r
876                 p_port_ext->pdo.p_po_work_item = NULL;\r
877                 BUS_TRACE( BUS_DBG_PNP,\r
878                         ("Created %s %s: PDO %p,ext %p, present %d, missing %d .\n",\r
879                         p_bfi->whoami,\r
880                         p_port_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_pdo[num_pdo],\r
881                         p_port_ext, p_port_ext->pdo.b_present,\r
882                         p_port_ext->pdo.b_reported_missing ) );\r
883 \r
884                 /* Cache the CA GUID. */\r
885                 p_port_ext->pdo.ca_guid = p_pnp_rec->p_ca_attr->ca_guid;\r
886 \r
887                 /* Take a reference on the parent HCA. */\r
888                 if(num_pdo > 0)\r
889                 {\r
890                         p_port_ext->pdo.h_ca = ((bus_port_ext_t*)p_pdo[0]->DeviceExtension)->pdo.h_ca;\r
891                         p_port_ext->pdo.is_partition_pdo = TRUE;\r
892                 }\r
893                 else\r
894                         p_port_ext->pdo.h_ca = acquire_ca( p_pnp_rec->p_ca_attr->ca_guid );\r
895 \r
896                 if( !p_port_ext->pdo.h_ca )\r
897                 {\r
898                         BUS_TRACE( BUS_DBG_PNP, ("Deleted device: PDO %p\n", p_pdo[num_pdo]));\r
899                         IoDeleteDevice( p_pdo[num_pdo]);\r
900                         BUS_TRACE_EXIT( BUS_DBG_ERROR, ("acquire_ca failed to find CA.\n") );\r
901                         return IB_INVALID_GUID;\r
902                 }\r
903                 p_port_ext->port_guid.guid = p_pnp_rec->p_port_attr->port_guid;\r
904                 p_port_ext->n_port = p_pnp_rec->p_port_attr->port_num;\r
905                 p_port_ext->port_guid.pkey = IB_DEFAULT_PKEY;\r
906                 p_port_ext->n_ifc_ref = 0;\r
907 \r
908                 if(num_pdo > 0)\r
909                         p_port_ext->port_guid.pkey = cur_pkeys->pkey_array[num_pdo -1];\r
910 \r
911                 /* Store the device extension in the port vector for future queries. */\r
912                 cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
913                 cl_qlist_insert_tail( &gp_port_mgr->port_list,\r
914                                                           &p_port_ext->pdo.list_item );\r
915                 cl_mutex_release( &gp_port_mgr->pdo_mutex );\r
916 \r
917                 /*\r
918                  * Set the context of the PNP event. The context is passed in for future\r
919                  * events on the same port.\r
920                  */\r
921                 if(num_pdo == 0)\r
922                         p_ctx->p_pdo_ext = p_port_ext;\r
923         }\r
924 \r
925         /* Tell the PnP Manager to rescan for the HCA's bus relations. */\r
926         IoInvalidateDeviceRelations(\r
927                 p_port_ext->pdo.h_ca->obj.p_ci_ca->verbs.p_hca_dev, BusRelations );\r
928 \r
929         BUS_EXIT( BUS_DBG_PNP );\r
930         return IB_SUCCESS;\r
931 }\r
932 \r
933 /************************************************************************************\r
934 * name  :       port_mgr_pkey_rem\r
935 *           removes pdo for each pkey value in pkey_array \r
936 * input :       g_pkeys\r
937 * output:       none\r
938 * return:       cl_status\r
939 *************************************************************************************/\r
940 cl_status_t _port_mgr_pkey_rem( IN      pkey_array_t    *pkeys,\r
941                                                                 IN      port_mgr_t              *gp_port_mgr )\r
942 {\r
943 \r
944         uint16_t                        cnt;\r
945         cl_list_item_t          *p_list_item;\r
946         bus_port_ext_t          *p_port_ext;\r
947         bus_pdo_ext_t           *p_pdo_ext = NULL;\r
948         cl_qlist_t*                     p_pdo_list = &gp_port_mgr->port_list;\r
949 \r
950         BUS_ENTER( BUS_DBG_PNP );\r
951 \r
952         p_port_ext = NULL;\r
953         cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
954         \r
955         /* Count the number of child devices. */\r
956         for( p_list_item = cl_qlist_head( p_pdo_list );\r
957                 p_list_item != cl_qlist_end( p_pdo_list );\r
958                 p_list_item = cl_qlist_next( p_list_item ) )\r
959         {\r
960                 p_pdo_ext = PARENT_STRUCT( p_list_item, bus_pdo_ext_t, list_item );\r
961                 p_port_ext = (bus_port_ext_t*)p_pdo_ext;\r
962 \r
963                 if(p_port_ext->port_guid.guid == pkeys->port_guid)\r
964                 {\r
965                         for(cnt = 0; cnt < pkeys->pkey_num; cnt++)\r
966                         {\r
967                                 if( (p_port_ext->port_guid.pkey == pkeys->pkey_array[cnt]) &&\r
968                                         (p_port_ext->port_guid.pkey != IB_DEFAULT_PKEY))\r
969                                 {\r
970                                         p_port_ext->pdo.b_present = FALSE;\r
971                                         break;\r
972                                 }\r
973                         }\r
974                 }\r
975         }\r
976         cl_mutex_release( &gp_port_mgr->pdo_mutex );\r
977 \r
978         /* Tell the PnP Manager to rescan for the HCA's bus relations. */\r
979         IoInvalidateDeviceRelations(\r
980                 p_port_ext->pdo.h_ca->obj.p_ci_ca->verbs.p_hca_dev, BusRelations );\r
981 \r
982         BUS_EXIT( BUS_DBG_PNP );\r
983         return CL_SUCCESS;\r
984 }\r
985 \r
986 \r
987 cl_status_t port_mgr_pkey_rem( IN pkey_array_t *pkeys )\r
988 {\r
989         bus_filter_t    *p_bfi;\r
990         cl_status_t             status;\r
991         boolean_t               GO;\r
992         int                             success_cnt=0;\r
993 \r
994         for(p_bfi=&bus_filters[0]; p_bfi < &bus_filters[MAX_BUS_FILTERS]; p_bfi++)\r
995         {\r
996                 if ( !p_bfi->p_bus_ext )\r
997                         continue;\r
998                 GO = FALSE;\r
999                 ExAcquireFastMutexUnsafe(&ControlMutex);\r
1000                 if ( p_bfi->ca_guid && p_bfi->p_port_mgr )\r
1001                         GO = TRUE;\r
1002                 ExReleaseFastMutexUnsafe(&ControlMutex);\r
1003                 if ( GO == FALSE )\r
1004                         continue;\r
1005                 status = _port_mgr_pkey_rem( pkeys, p_bfi->p_port_mgr );\r
1006                 if ( status == CL_SUCCESS )\r
1007                         success_cnt++;\r
1008         }\r
1009         return ( success_cnt ? CL_SUCCESS : CL_ERROR );\r
1010 }\r
1011 \r
1012 \r
1013 /************************************************************************************\r
1014 * name  :       port_mgr_pkey_add\r
1015 *           creates pdo for each pkey value in pkey_array \r
1016 * input :       g_pkeys\r
1017 * output:       none\r
1018 * return:       cl_status\r
1019 *************************************************************************************/\r
1020 cl_status_t _port_mgr_pkey_add( IN      pkey_array_t    *req_pkeys,\r
1021                                                                 IN      bus_filter_t    *p_bfi,\r
1022                                                                 IN      port_mgr_t              *gp_port_mgr )\r
1023 {\r
1024         uint16_t                        cnt;\r
1025         NTSTATUS            status;\r
1026         cl_list_item_t          *p_list_item;\r
1027         bus_port_ext_t          *p_port_ext, *pkey_port_ext, *pmatched_guid_ext;\r
1028         DEVICE_OBJECT       *p_pdo[MAX_NUM_PKEY];\r
1029         cl_qlist_t*                     p_pdo_list = &gp_port_mgr->port_list;\r
1030 \r
1031         BUS_ENTER( BUS_DBG_PNP );\r
1032 \r
1033         pmatched_guid_ext = NULL;\r
1034         p_port_ext = NULL;\r
1035         cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
1036         \r
1037         /* Count the number of child devices. */\r
1038         for( p_list_item = cl_qlist_head( p_pdo_list );\r
1039                 p_list_item != cl_qlist_end( p_pdo_list );\r
1040                 p_list_item = cl_qlist_next( p_list_item ) )\r
1041         {\r
1042                 p_port_ext = (bus_port_ext_t*)PARENT_STRUCT( p_list_item, bus_pdo_ext_t, list_item );\r
1043 \r
1044                 if(p_port_ext->port_guid.guid == req_pkeys->port_guid)\r
1045                 {\r
1046                         uint16_t i;\r
1047                         for(i = 0; i < req_pkeys->pkey_num; i++)\r
1048                         {\r
1049                                 if(p_port_ext->port_guid.pkey == req_pkeys->pkey_array[i])\r
1050                                 {\r
1051                                         /* was removed previously */\r
1052                                         p_port_ext->pdo.b_present = TRUE;\r
1053                                         p_port_ext->pdo.b_reported_missing = FALSE;\r
1054                                         req_pkeys->pkey_array[i] = 0;  \r
1055                                 }\r
1056                         }\r
1057                         if(!pmatched_guid_ext)\r
1058                                 pmatched_guid_ext = p_port_ext;\r
1059                 }\r
1060         }\r
1061         cl_mutex_release( &gp_port_mgr->pdo_mutex );\r
1062 \r
1063         if (!pmatched_guid_ext)\r
1064         {\r
1065                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
1066                         ("No existed pdo found.\n") );\r
1067                 return CL_NOT_FOUND;\r
1068         }\r
1069 \r
1070     for (cnt = 0; cnt < req_pkeys->pkey_num; cnt++)\r
1071     {\r
1072                 if(! (cl_hton16(req_pkeys->pkey_array[cnt]) & IB_PKEY_BASE_MASK) )\r
1073                         continue;\r
1074 \r
1075                 /* Create the PDO for the new port device. */\r
1076                 status = IoCreateDevice( bus_globals.p_driver_obj, sizeof(bus_port_ext_t),\r
1077                         NULL, FILE_DEVICE_CONTROLLER,\r
1078                         FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME,\r
1079                         FALSE, &p_pdo[cnt] );\r
1080                 if( !NT_SUCCESS( status ) )\r
1081                 {\r
1082                         BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
1083                                 ("IoCreateDevice returned %08x.\n", status) );\r
1084                         return CL_ERROR;\r
1085                 }\r
1086         \r
1087                 /* Initialize the device extension. */\r
1088                 cl_init_pnp_po_ext( p_pdo[cnt], NULL, p_pdo[cnt], bus_globals.dbg_lvl,\r
1089                         &vfptr_port_pnp, &vfptr_port_query_txt );\r
1090         \r
1091                 /* Set the DO_BUS_ENUMERATED_DEVICE flag to mark it as a PDO. */\r
1092                 p_pdo[cnt]->Flags |= DO_BUS_ENUMERATED_DEVICE;\r
1093         \r
1094                 pkey_port_ext = p_pdo[cnt]->DeviceExtension;\r
1095                 pkey_port_ext->pdo.dev_po_state.DeviceState = PowerDeviceD0;\r
1096                 pkey_port_ext->pdo.p_parent_ext = p_bfi->p_bus_ext;\r
1097                 pkey_port_ext->pdo.b_present = TRUE;\r
1098                 pkey_port_ext->pdo.b_reported_missing = FALSE;\r
1099                 pkey_port_ext->pdo.b_hibernating = FALSE;\r
1100                 pkey_port_ext->pdo.p_po_work_item = NULL;\r
1101                 BUS_TRACE( BUS_DBG_PNP, ("Created device for %s: PDO %p,ext %p, present %d, missing %d .\n",\r
1102                         pkey_port_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_pdo[cnt], pkey_port_ext, pkey_port_ext->pdo.b_present, \r
1103                         pkey_port_ext->pdo.b_reported_missing ) );\r
1104         \r
1105                 /* Cache the CA GUID. */\r
1106                 pkey_port_ext->pdo.ca_guid = pmatched_guid_ext->pdo.ca_guid;\r
1107                 pkey_port_ext->pdo.h_ca = pmatched_guid_ext->pdo.h_ca;\r
1108                 pkey_port_ext->port_guid.guid = pmatched_guid_ext->port_guid.guid;\r
1109                 pkey_port_ext->n_port = pmatched_guid_ext->n_port;\r
1110                 pkey_port_ext->port_guid.pkey = req_pkeys->pkey_array[cnt];\r
1111                 pkey_port_ext->pdo.is_partition_pdo = TRUE;\r
1112                 /* Store the device extension in the port vector for future queries. */\r
1113                 cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
1114                 cl_qlist_insert_tail( &gp_port_mgr->port_list,\r
1115                         &pkey_port_ext->pdo.list_item );\r
1116                 cl_mutex_release( &gp_port_mgr->pdo_mutex );\r
1117         }\r
1118 \r
1119         /* Tell the PnP Manager to rescan for the HCA's bus relations. */\r
1120         IoInvalidateDeviceRelations(\r
1121                 pmatched_guid_ext->pdo.h_ca->obj.p_ci_ca->verbs.p_hca_dev, BusRelations );\r
1122 \r
1123         BUS_EXIT( BUS_DBG_PNP );\r
1124         return CL_SUCCESS;\r
1125 }\r
1126 \r
1127 cl_status_t port_mgr_pkey_add(pkey_array_t *pkeys)\r
1128 {\r
1129         bus_filter_t    *p_bfi;\r
1130         cl_status_t             status;\r
1131         boolean_t               GO;\r
1132         int                             success_cnt=0;\r
1133 \r
1134         for(p_bfi=&bus_filters[0]; p_bfi < &bus_filters[MAX_BUS_FILTERS]; p_bfi++)\r
1135         {\r
1136                 if ( !p_bfi->p_bus_ext )\r
1137                         continue;\r
1138                 GO = FALSE;\r
1139                 ExAcquireFastMutexUnsafe(&ControlMutex);\r
1140                 if ( p_bfi->ca_guid && p_bfi->p_port_mgr )\r
1141                         GO = TRUE;\r
1142                 ExReleaseFastMutexUnsafe(&ControlMutex);\r
1143                 if ( GO == FALSE )\r
1144                         continue;\r
1145                 status = _port_mgr_pkey_add( pkeys, p_bfi, p_bfi->p_port_mgr );\r
1146                 if ( status == CL_SUCCESS )\r
1147                         success_cnt++;\r
1148         }\r
1149         return ( success_cnt ? CL_SUCCESS : CL_ERROR );\r
1150 }\r
1151 \r
1152 \r
1153 void\r
1154 port_mgr_port_remove(\r
1155         IN                              ib_pnp_port_rec_t*              p_pnp_rec )\r
1156 {\r
1157         bus_pdo_ext_t   *p_ext;\r
1158         port_mgr_t              *gp_port_mgr;\r
1159         bus_filter_t    *p_bfi;\r
1160         port_pnp_ctx_t  *p_ctx = p_pnp_rec->pnp_rec.context;\r
1161 \r
1162         BUS_ENTER( BUS_DBG_PNP );\r
1163 \r
1164         if ( !p_ctx ) {\r
1165                 BUS_EXIT( BUS_DBG_PNP );\r
1166                 return;\r
1167         }\r
1168 \r
1169         CL_ASSERT( p_ctx->p_bus_filter->magic == BFI_MAGIC );\r
1170         p_bfi = p_ctx->p_bus_filter;\r
1171         CL_ASSERT( p_bfi );\r
1172 \r
1173         BUS_PRINT(BUS_DBG_PNP,("%s(%s) ca_guid 0x%I64x port_num %d port_mgr %p\n",\r
1174                                                 __FUNCTION__, p_bfi->whoami, p_bfi->ca_guid,\r
1175                                                 p_ctx->port_num, p_bfi->p_port_mgr));\r
1176 \r
1177         /* in the process of device remove, port_mgr has been destroyed.\r
1178          * cleanup allocated PNP port context; one per port.\r
1179          * The issue is the PNP PORT_REMOVE event occurs after\r
1180          * fdo_release_resources() completes.\r
1181          */\r
1182         if ( p_bfi->ca_guid == 0ULL || !p_bfi->p_port_mgr ) {\r
1183                 cl_free( p_ctx );\r
1184                 p_pnp_rec->pnp_rec.context = NULL;\r
1185                 BUS_EXIT( BUS_DBG_PNP );\r
1186                 return;\r
1187         }\r
1188 \r
1189         gp_port_mgr = p_bfi->p_port_mgr;\r
1190 \r
1191         /* Within the PNP record's context is the port extension ptr;\r
1192          * see port_was_hibernated().\r
1193          */\r
1194         p_ext = p_ctx->p_pdo_ext;\r
1195         CL_ASSERT( p_ext );\r
1196         CL_ASSERT(p_bfi == p_ext->p_parent_ext->bus_filter);\r
1197 \r
1198         /*\r
1199          * Flag the port PDO as no longer being present.  We have to wait until\r
1200          * the PnP manager removes it to clean up.  However, we do release the\r
1201          * reference on the CA object in order to allow the removal of the HCA\r
1202          * to proceed should it occur before the port's PDO is cleaned up.\r
1203          */\r
1204         if ( !p_ext->h_ca )\r
1205         {\r
1206                 BUS_TRACE_EXIT( BUS_DBG_PNP, ("%s() %s NULL h_ca? p_ext %p\n",\r
1207                                         __FUNCTION__, p_bfi->whoami, p_ext ) );\r
1208                 return;\r
1209         }\r
1210 \r
1211         cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
1212         CL_ASSERT( p_ext->h_ca );\r
1213 \r
1214         if( p_ext->b_hibernating )\r
1215         {\r
1216                 BUS_TRACE( BUS_DBG_PNP, ("Skip port removing for %s: PDO %p, ext %p, "\r
1217                         "present %d, missing %d, hibernating %d .\n",\r
1218                         p_ext->cl_ext.vfptr_pnp_po->identity, p_ext->cl_ext.p_self_do,\r
1219                         p_ext, p_ext->b_present, p_ext->b_reported_missing,\r
1220                         p_ext->b_hibernating ) );\r
1221                 goto hca_deref;\r
1222         }\r
1223 \r
1224         p_ext->b_present = FALSE;\r
1225         p_ext->b_reported_missing = TRUE;\r
1226 \r
1227         BUS_TRACE( BUS_DBG_PNP,\r
1228                 ("Mark removing %s: PDO %p, ext %p, present %d, missing %d .\n",\r
1229                 p_ext->cl_ext.vfptr_pnp_po->identity, p_ext->cl_ext.p_self_do, p_ext,\r
1230                 p_ext->b_present, p_ext->b_reported_missing ) );\r
1231 \r
1232         /* Invalidate bus relations for the HCA. */\r
1233         IoInvalidateDeviceRelations(\r
1234                 p_ext->h_ca->obj.p_ci_ca->verbs.p_hca_dev, BusRelations );\r
1235 \r
1236         /* Free PNP context memory */\r
1237         cl_free( p_ctx );\r
1238         p_pnp_rec->pnp_rec.context = NULL;\r
1239 \r
1240 hca_deref:\r
1241         deref_al_obj( &p_ext->h_ca->obj );\r
1242         cl_mutex_release( &gp_port_mgr->pdo_mutex );\r
1243 \r
1244         BUS_EXIT( BUS_DBG_PNP );\r
1245 }\r
1246 \r
1247 \r
1248 static NTSTATUS\r
1249 port_start(\r
1250         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1251         IN                                      IRP* const                              p_irp,\r
1252                 OUT                             cl_irp_action_t* const  p_action )\r
1253 {\r
1254         bus_pdo_ext_t   *p_ext;\r
1255 \r
1256         BUS_ENTER( BUS_DBG_PNP );\r
1257 \r
1258         UNUSED_PARAM( p_irp );\r
1259 \r
1260         p_ext = p_dev_obj->DeviceExtension;\r
1261 \r
1262         /* Notify the Power Manager that the device is started. */\r
1263         PoSetPowerState( p_dev_obj, DevicePowerState, p_ext->dev_po_state );\r
1264         *p_action = IrpComplete;\r
1265         BUS_EXIT( BUS_DBG_PNP );\r
1266 \r
1267         return STATUS_SUCCESS;\r
1268 }\r
1269 \r
1270 \r
1271 static NTSTATUS\r
1272 port_query_remove(\r
1273         IN                              DEVICE_OBJECT* const    p_dev_obj,\r
1274         IN                              IRP* const                              p_irp,\r
1275                 OUT                     cl_irp_action_t* const  p_action )\r
1276 {\r
1277         bus_port_ext_t  *p_ext;\r
1278 \r
1279         BUS_ENTER( BUS_DBG_PNP );\r
1280 \r
1281         UNUSED_PARAM( p_irp );\r
1282 \r
1283         p_ext = p_dev_obj->DeviceExtension;\r
1284 \r
1285         *p_action = IrpComplete;\r
1286         if( p_ext->n_ifc_ref )\r
1287         {\r
1288                 /*\r
1289                  * Our interface is still being held by someone.\r
1290                  * Rollback the PnP state that was changed in the complib handler.\r
1291                  */\r
1292                 cl_rollback_pnp_state( &p_ext->pdo.cl_ext );\r
1293 \r
1294                 /* Fail the query. */\r
1295                 BUS_TRACE_EXIT( BUS_DBG_PNP, ("Failing IRP_MN_QUERY_REMOVE_DEVICE:\n"\r
1296                         "\tInterface has %d reference\n", p_ext->n_ifc_ref ) );\r
1297                 return STATUS_UNSUCCESSFUL;\r
1298         }\r
1299 \r
1300         BUS_EXIT( BUS_DBG_PNP );\r
1301         return STATUS_SUCCESS;\r
1302 }\r
1303 \r
1304 \r
1305 static void\r
1306 port_release_resources(\r
1307         IN                                      DEVICE_OBJECT* const    p_dev_obj )\r
1308 {\r
1309         bus_port_ext_t  *p_ext;\r
1310         POWER_STATE             po_state;\r
1311         port_mgr_t              *gp_port_mgr;\r
1312 \r
1313         BUS_ENTER( BUS_DBG_PNP );\r
1314 \r
1315         p_ext = p_dev_obj->DeviceExtension;\r
1316         gp_port_mgr = p_ext->pdo.p_parent_ext->bus_filter->p_port_mgr;\r
1317 \r
1318         /* Remove this PDO from its list. */\r
1319         cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
1320         BUS_TRACE( BUS_DBG_PNP, ("Removing port from vector: PDO %p, ext %p\n",\r
1321                                 p_dev_obj, p_ext) );\r
1322         cl_qlist_remove_item( &gp_port_mgr->port_list, &p_ext->pdo.list_item );\r
1323         cl_mutex_release( &gp_port_mgr->pdo_mutex );\r
1324         po_state.DeviceState = PowerDeviceD3;\r
1325         PoSetPowerState( p_ext->pdo.cl_ext.p_pdo, DevicePowerState, po_state );\r
1326 \r
1327         BUS_EXIT( BUS_DBG_PNP );\r
1328 }\r
1329 \r
1330 \r
1331 static NTSTATUS\r
1332 port_remove(\r
1333         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1334         IN                                      IRP* const                              p_irp,\r
1335                 OUT                             cl_irp_action_t* const  p_action )\r
1336 {\r
1337         bus_port_ext_t  *p_ext;\r
1338 \r
1339         BUS_ENTER( BUS_DBG_PNP );\r
1340 \r
1341         p_ext = p_dev_obj->DeviceExtension;\r
1342 \r
1343         if( p_ext->pdo.b_present )\r
1344         {\r
1345                 CL_ASSERT( p_ext->pdo.cl_ext.pnp_state != NotStarted );\r
1346                 CL_ASSERT( !p_ext->pdo.b_reported_missing );\r
1347                 /* Reset the state to NotStarted.  CompLib set it to Deleted. */\r
1348                 cl_set_pnp_state( &p_ext->pdo.cl_ext, NotStarted );\r
1349                 /* Don't delete the device.  It may simply be disabled. */\r
1350                 *p_action = IrpComplete;\r
1351                 BUS_TRACE_EXIT( BUS_DBG_PNP,\r
1352                                 ("Device %s still present: PDO %p, ext %p\n",\r
1353                                 p_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_dev_obj, p_ext) );\r
1354                 return STATUS_SUCCESS;\r
1355         }\r
1356 \r
1357         if( !p_ext->pdo.b_reported_missing )\r
1358         {\r
1359                 /* Reset the state to RemovePending.  Complib set it to Deleted. */\r
1360                 cl_rollback_pnp_state( &p_ext->pdo.cl_ext );\r
1361                 *p_action = IrpComplete;\r
1362                 BUS_TRACE_EXIT( BUS_DBG_PNP,\r
1363                                                 ("Device %s not reported missing yet: PDO %p, ext %p\n",\r
1364                                                 p_ext->pdo.cl_ext.vfptr_pnp_po->identity,\r
1365                                                 p_dev_obj, p_ext) );\r
1366                 return STATUS_SUCCESS;\r
1367         }\r
1368 \r
1369         /* Wait for all I/O operations to complete. */\r
1370         IoReleaseRemoveLockAndWait( &p_ext->pdo.cl_ext.remove_lock, p_irp );\r
1371 \r
1372         /* Release resources if it was not done yet. */\r
1373         if( p_ext->pdo.cl_ext.last_pnp_state != SurpriseRemoved )\r
1374                 p_ext->pdo.cl_ext.vfptr_pnp_po->pfn_release_resources( p_dev_obj );\r
1375 \r
1376         p_irp->IoStatus.Status = STATUS_SUCCESS;\r
1377         IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
1378 \r
1379         BUS_TRACE( BUS_DBG_PNP, ("Deleted device %s: PDO %p(=%p), ext %p\n",\r
1380                 p_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_ext->pdo.cl_ext.p_self_do,\r
1381                 p_dev_obj, p_ext ) );\r
1382 \r
1383         IoDeleteDevice( p_dev_obj );\r
1384 \r
1385         *p_action = IrpDoNothing;\r
1386         BUS_EXIT( BUS_DBG_PNP );\r
1387         return STATUS_SUCCESS;\r
1388 }\r
1389 \r
1390 \r
1391 static NTSTATUS\r
1392 port_surprise_remove(\r
1393         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1394         IN                              IRP* const                                      p_irp,\r
1395                 OUT                     cl_irp_action_t* const          p_action )\r
1396 {\r
1397         bus_port_ext_t  *p_ext;\r
1398 \r
1399         BUS_ENTER( BUS_DBG_PNP );\r
1400 \r
1401         UNUSED_PARAM( p_irp );\r
1402 \r
1403         p_ext = p_dev_obj->DeviceExtension;\r
1404         p_ext->pdo.b_present = FALSE;\r
1405         p_ext->pdo.b_reported_missing = TRUE;\r
1406         BUS_TRACE( BUS_DBG_PNP, ("%s: PDO %p, ext %p, present %d, missing %d .\n",\r
1407                 p_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_ext->pdo.cl_ext.p_self_do, \r
1408                 p_ext, p_ext->pdo.b_present, p_ext->pdo.b_reported_missing ) );\r
1409 \r
1410         *p_action = IrpComplete;\r
1411 \r
1412         BUS_EXIT( BUS_DBG_PNP );\r
1413         return STATUS_SUCCESS;\r
1414 }\r
1415 \r
1416 \r
1417 static NTSTATUS\r
1418 port_query_capabilities(\r
1419         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1420         IN                                      IRP* const                              p_irp,\r
1421                 OUT                             cl_irp_action_t* const  p_action )\r
1422 {\r
1423         DEVICE_CAPABILITIES             *p_caps;\r
1424         IO_STACK_LOCATION               *p_io_stack;\r
1425 \r
1426         BUS_ENTER( BUS_DBG_PNP );\r
1427 \r
1428         UNUSED_PARAM( p_dev_obj );\r
1429 \r
1430         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
1431         p_caps = p_io_stack->Parameters.DeviceCapabilities.Capabilities;\r
1432 \r
1433         p_caps->DeviceD1 = FALSE;\r
1434         p_caps->DeviceD2 = FALSE;\r
1435         p_caps->LockSupported = FALSE;\r
1436         p_caps->EjectSupported = FALSE;\r
1437         p_caps->Removable = FALSE;\r
1438         p_caps->DockDevice = FALSE;\r
1439         p_caps->UniqueID = TRUE;\r
1440         p_caps->SilentInstall = TRUE;\r
1441         p_caps->RawDeviceOK = FALSE;\r
1442         p_caps->SurpriseRemovalOK = FALSE;\r
1443         p_caps->WakeFromD0 = FALSE;\r
1444         p_caps->WakeFromD1 = FALSE;\r
1445         p_caps->WakeFromD2 = FALSE;\r
1446         p_caps->WakeFromD3 = FALSE;\r
1447         p_caps->HardwareDisabled = FALSE;\r
1448         p_caps->DeviceState[PowerSystemWorking] = PowerDeviceD0;\r
1449         p_caps->DeviceState[PowerSystemSleeping1] = PowerDeviceD3;\r
1450         p_caps->DeviceState[PowerSystemSleeping2] = PowerDeviceD3;\r
1451         p_caps->DeviceState[PowerSystemSleeping3] = PowerDeviceD3;\r
1452         p_caps->DeviceState[PowerSystemHibernate] = PowerDeviceD3;\r
1453         p_caps->DeviceState[PowerSystemShutdown] = PowerDeviceD3;\r
1454         p_caps->SystemWake = PowerSystemUnspecified;\r
1455         p_caps->DeviceWake = PowerDeviceUnspecified;\r
1456         p_caps->D1Latency = 0;\r
1457         p_caps->D2Latency = 0;\r
1458         p_caps->D3Latency = 0;\r
1459 \r
1460         *p_action = IrpComplete;\r
1461         BUS_EXIT( BUS_DBG_PNP );\r
1462         return STATUS_SUCCESS;\r
1463 }\r
1464 \r
1465 \r
1466 static NTSTATUS\r
1467 port_query_target_relations(\r
1468         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1469         IN                                      IRP* const                              p_irp,\r
1470                 OUT                             cl_irp_action_t* const  p_action )\r
1471 {\r
1472         NTSTATUS                        status;\r
1473         DEVICE_RELATIONS        *p_rel;\r
1474 \r
1475         BUS_ENTER( BUS_DBG_PNP );\r
1476 \r
1477         *p_action = IrpComplete;\r
1478 \r
1479         status = cl_alloc_relations( p_irp, 1 );\r
1480         if( !NT_SUCCESS( status ) )\r
1481         {\r
1482                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
1483                         ("cl_alloc_relations returned 0x%08x.\n", status) );\r
1484                 return status;\r
1485         }\r
1486 \r
1487         p_rel = (DEVICE_RELATIONS*)p_irp->IoStatus.Information;\r
1488         p_rel->Count = 1;\r
1489         p_rel->Objects[0] = p_dev_obj;\r
1490 \r
1491         ObReferenceObject( p_dev_obj );\r
1492 \r
1493         BUS_EXIT( BUS_DBG_PNP );\r
1494         return status;\r
1495 }\r
1496 \r
1497 \r
1498 static NTSTATUS\r
1499 port_query_device_id(\r
1500         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1501                 OUT                             IRP* const                              p_irp )\r
1502 {\r
1503         WCHAR                           *p_string;\r
1504         bus_port_ext_t          *p_ext;\r
1505         size_t                          dev_id_size;\r
1506         \r
1507         BUS_ENTER( BUS_DBG_PNP );\r
1508 \r
1509         \r
1510         p_ext = (bus_port_ext_t*)p_dev_obj->DeviceExtension;\r
1511         if( !p_ext->pdo.b_present )\r
1512         {\r
1513                 BUS_TRACE_EXIT( BUS_DBG_ERROR, ("Device not present.\n") );\r
1514                 return STATUS_NO_SUCH_DEVICE;\r
1515         }\r
1516         if(p_ext->port_guid.pkey == IB_DEFAULT_PKEY)\r
1517                 dev_id_size = sizeof(IPOIB_DEVICE_ID);\r
1518         else\r
1519                 dev_id_size = sizeof(IPOIB_PART_DEVICE_ID );\r
1520         /* Device ID is "IBA\SID_<sid> where <sid> is the IPoIB Service ID. */\r
1521         p_string = ExAllocatePoolWithTag( PagedPool, dev_id_size, 'vedq' );\r
1522         if( !p_string )\r
1523         {\r
1524                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
1525                         ("Failed to allocate device ID buffer (%d bytes).\n",\r
1526                         dev_id_size) );\r
1527                 return STATUS_INSUFFICIENT_RESOURCES;\r
1528         }\r
1529 \r
1530         if(p_ext->port_guid.pkey == IB_DEFAULT_PKEY)\r
1531                 cl_memcpy( p_string, IPOIB_DEVICE_ID, sizeof(IPOIB_DEVICE_ID) );\r
1532         else\r
1533                 cl_memcpy( p_string, IPOIB_PART_DEVICE_ID, sizeof(IPOIB_PART_DEVICE_ID) );\r
1534         p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
1535 \r
1536         BUS_EXIT( BUS_DBG_PNP );\r
1537         return STATUS_SUCCESS;\r
1538 }\r
1539 \r
1540 \r
1541 static NTSTATUS\r
1542 port_query_hardware_ids(\r
1543         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1544                 OUT                             IRP* const                              p_irp )\r
1545 {\r
1546         WCHAR                           *p_string;\r
1547         bus_port_ext_t          *p_ext;\r
1548         size_t                          dev_id_size;\r
1549 \r
1550         BUS_ENTER( BUS_DBG_PNP );\r
1551 \r
1552 \r
1553         p_ext = (bus_port_ext_t*)p_dev_obj->DeviceExtension;\r
1554 \r
1555         if(p_ext->port_guid.pkey == IB_DEFAULT_PKEY)\r
1556                 dev_id_size = sizeof(IPOIB_HARDWARE_ID);\r
1557         else\r
1558                 dev_id_size = sizeof(IPOIB_PART_HARDWARE_ID );\r
1559 \r
1560         p_string = ExAllocatePoolWithTag( PagedPool, dev_id_size, 'ihqp' );\r
1561         if( !p_string )\r
1562         {\r
1563                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
1564                         ("Failed to allocate hardware ID buffer (%d bytes).\n",\r
1565                         dev_id_size) );\r
1566                 return STATUS_INSUFFICIENT_RESOURCES;\r
1567         }\r
1568         if(p_ext->port_guid.pkey == IB_DEFAULT_PKEY)\r
1569                 cl_memcpy( p_string, IPOIB_HARDWARE_ID, sizeof(IPOIB_HARDWARE_ID) );\r
1570         else\r
1571                 cl_memcpy( p_string, IPOIB_PART_HARDWARE_ID, sizeof(IPOIB_PART_HARDWARE_ID) );\r
1572         p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
1573 \r
1574         BUS_EXIT( BUS_DBG_PNP );\r
1575         return STATUS_SUCCESS;\r
1576 }\r
1577 \r
1578 \r
1579 static NTSTATUS\r
1580 port_query_compatible_ids(\r
1581         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1582                 OUT                             IRP* const                              p_irp )\r
1583 {\r
1584         WCHAR                           *p_string;\r
1585 \r
1586         BUS_ENTER( BUS_DBG_PNP );\r
1587 \r
1588         UNUSED_PARAM( p_dev_obj );\r
1589 \r
1590         p_string = ExAllocatePoolWithTag( PagedPool, sizeof(IPOIB_COMPAT_ID), 'icqp' );\r
1591         if( !p_string )\r
1592         {\r
1593                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
1594                         ("Failed to allocate compatible ID buffer (%d bytes).\n",\r
1595                         sizeof(IPOIB_COMPAT_ID)) );\r
1596                 return STATUS_INSUFFICIENT_RESOURCES;\r
1597         }\r
1598         cl_memcpy( p_string, IPOIB_COMPAT_ID, sizeof(IPOIB_COMPAT_ID) );\r
1599         p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
1600 \r
1601         BUS_EXIT( BUS_DBG_PNP );\r
1602         return STATUS_SUCCESS;\r
1603 }\r
1604 \r
1605 \r
1606 static NTSTATUS\r
1607 port_query_unique_id(\r
1608         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1609                 OUT                             IRP* const                              p_irp )\r
1610 {\r
1611         NTSTATUS                        status;\r
1612         WCHAR                           *p_string;\r
1613         bus_port_ext_t          *p_ext;\r
1614 \r
1615         BUS_ENTER( BUS_DBG_PNP );\r
1616 \r
1617         p_ext = p_dev_obj->DeviceExtension;\r
1618 \r
1619         if( !p_ext->pdo.b_present )\r
1620         {\r
1621                 BUS_TRACE_EXIT( BUS_DBG_ERROR, ("Device not present.\n") );\r
1622                 return STATUS_NO_SUCH_DEVICE;\r
1623         }\r
1624 \r
1625         /* The instance ID is the port GUID. */\r
1626         p_string = ExAllocatePoolWithTag( PagedPool, sizeof(WCHAR) * 21, 'iuqp' );\r
1627         if( !p_string )\r
1628         {\r
1629                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
1630                         ("Failed to allocate instance ID buffer (%d bytes).\n",\r
1631                         sizeof(WCHAR) * 21) );\r
1632                 return STATUS_NO_MEMORY;\r
1633         }\r
1634 \r
1635         status = RtlStringCchPrintfW( p_string, 21, L"%016I64x%04x",p_ext->port_guid.guid,p_ext->port_guid.pkey );\r
1636         if( !NT_SUCCESS( status ) )\r
1637         {\r
1638                 CL_ASSERT( NT_SUCCESS( status ) );\r
1639                 ExFreePool( p_string );\r
1640                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
1641                         ("RtlStringCchPrintfW returned %08x.\n", status) );\r
1642                 return status;\r
1643         }\r
1644 \r
1645         p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
1646 \r
1647         BUS_EXIT( BUS_DBG_PNP );\r
1648         return STATUS_SUCCESS;\r
1649 }\r
1650 \r
1651 \r
1652 static NTSTATUS\r
1653 port_query_description(\r
1654         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1655                 OUT                             IRP* const                              p_irp )\r
1656 {\r
1657         WCHAR                           *p_string;\r
1658         bus_port_ext_t          *p_ext;\r
1659         \r
1660         BUS_ENTER( BUS_DBG_PNP );\r
1661 \r
1662         p_ext = p_dev_obj->DeviceExtension;\r
1663         if( !p_ext->pdo.b_present )\r
1664         {\r
1665                 BUS_TRACE_EXIT( BUS_DBG_ERROR, ("Device not present.\n") );\r
1666                 return STATUS_NO_SUCH_DEVICE;\r
1667         }\r
1668 \r
1669 \r
1670         /* The instance ID is the port GUID. */\r
1671         p_string = ExAllocatePoolWithTag( PagedPool, sizeof(IPOIB_DESCRIPTION), 'edqp' );\r
1672         if( !p_string )\r
1673         {\r
1674                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
1675                         ("Failed to allocate device description buffer (%d bytes).\n",\r
1676                         sizeof(IPOIB_DESCRIPTION)) );\r
1677                 return STATUS_INSUFFICIENT_RESOURCES;\r
1678         }\r
1679         cl_memcpy( p_string, IPOIB_DESCRIPTION, sizeof(IPOIB_DESCRIPTION) );\r
1680         p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
1681 \r
1682         BUS_EXIT( BUS_DBG_PNP );\r
1683         return STATUS_SUCCESS;\r
1684 }\r
1685 \r
1686 \r
1687 static NTSTATUS\r
1688 port_query_location(\r
1689         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1690                 OUT                             IRP* const                              p_irp )\r
1691 {\r
1692         WCHAR                           *p_string;\r
1693         bus_port_ext_t          *p_ext;\r
1694         size_t                          size;\r
1695         ULONG                           len;\r
1696         NTSTATUS                        status;\r
1697         DEVICE_OBJECT           *p_hca_dev;\r
1698 \r
1699         BUS_ENTER( BUS_DBG_PNP );\r
1700 \r
1701         p_ext = p_dev_obj->DeviceExtension;\r
1702         if( !p_ext->pdo.b_present )\r
1703         {\r
1704                 BUS_TRACE_EXIT( BUS_DBG_ERROR, ("Device not present.\n") );\r
1705                 return STATUS_NO_SUCH_DEVICE;\r
1706         }\r
1707 \r
1708         p_hca_dev = p_ext->pdo.h_ca->obj.p_ci_ca->verbs.p_hca_dev;\r
1709 \r
1710         /* Get the length of the HCA's location. */\r
1711         status = IoGetDeviceProperty( p_hca_dev,\r
1712                 DevicePropertyLocationInformation, 0, NULL, &len );\r
1713         if( status != STATUS_BUFFER_TOO_SMALL )\r
1714         {\r
1715                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
1716                         ("IoGetDeviceProperty for device location size returned %08x.\n",\r
1717                         status) );\r
1718                 return status;\r
1719         }\r
1720 \r
1721         /*\r
1722          * Allocate the string buffer to hold the HCA's location along with the\r
1723          * port number.  The port number is 32-bits, so in decimal it can be at\r
1724          * most 10 characters.\r
1725          */\r
1726         size = len + sizeof(L", port ") + (sizeof(WCHAR) * 10);\r
1727         if( size > (USHORT)-1 )\r
1728         {\r
1729                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
1730                         ("Length beyond limits.\n") );\r
1731                 return STATUS_INSUFFICIENT_RESOURCES;\r
1732         }\r
1733 \r
1734         p_string = ExAllocatePoolWithTag( PagedPool, size, 'olqp' );\r
1735         if( !p_string )\r
1736         {\r
1737                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
1738                         ("Failed to allocate device location buffer (%d bytes).\n", len) );\r
1739                 return STATUS_NO_MEMORY;\r
1740         }\r
1741 \r
1742         /* Get the HCA's location information. */\r
1743         status = IoGetDeviceProperty( p_hca_dev,\r
1744                 DevicePropertyLocationInformation, len, p_string, &len );\r
1745         if( !NT_SUCCESS( status ) )\r
1746         {\r
1747                 ExFreePool( p_string );\r
1748                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
1749                         ("IoGetDeviceProperty for device location returned %08x.\n",\r
1750                         status) );\r
1751                 return status;\r
1752         }\r
1753 \r
1754         /* Append the port number to the HCA's location. */\r
1755         status = RtlStringCbPrintfW( p_string + (len/2) - 1, size - len + 1,\r
1756                 L", port %d", p_ext->n_port );\r
1757         if( !NT_SUCCESS( status ) )\r
1758         {\r
1759                 CL_ASSERT( NT_SUCCESS( status ) );\r
1760                 ExFreePool( p_string );\r
1761                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
1762                         ("RtlStringCbPrintfW returned %08x.\n", status) );\r
1763                 return status;\r
1764         }\r
1765 \r
1766         p_irp->IoStatus.Information = (ULONG_PTR)p_string;\r
1767 \r
1768         BUS_EXIT( BUS_DBG_PNP );\r
1769         return STATUS_SUCCESS;\r
1770 }\r
1771 \r
1772 \r
1773 static NTSTATUS\r
1774 port_query_bus_info(\r
1775         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1776         IN                                      IRP* const                              p_irp,\r
1777                 OUT                             cl_irp_action_t* const  p_action )\r
1778 {\r
1779         PNP_BUS_INFORMATION     *p_bus_info;\r
1780 \r
1781         BUS_ENTER( BUS_DBG_PNP );\r
1782 \r
1783         UNUSED_PARAM( p_dev_obj );\r
1784 \r
1785         *p_action = IrpComplete;\r
1786 \r
1787         p_bus_info = ExAllocatePoolWithTag( PagedPool, sizeof(PNP_BUS_INFORMATION), 'ibqp' );\r
1788         if( !p_bus_info )\r
1789         {\r
1790                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
1791                         ("Failed to allocate PNP_BUS_INFORMATION (%d bytes).\n",\r
1792                         sizeof(PNP_BUS_INFORMATION)) );\r
1793                 return STATUS_INSUFFICIENT_RESOURCES;\r
1794         }\r
1795 \r
1796         p_bus_info->BusTypeGuid = GUID_BUS_TYPE_IBA;\r
1797         //TODO: Memory from Intel - storage miniport would not stay loaded unless\r
1798         //TODO: bus type was PCI.  Look here if SRP is having problems staying\r
1799         //TODO: loaded.\r
1800         p_bus_info->LegacyBusType = PNPBus;\r
1801         p_bus_info->BusNumber = 0;\r
1802 \r
1803         p_irp->IoStatus.Information = (ULONG_PTR)p_bus_info;\r
1804         BUS_EXIT( BUS_DBG_PNP );\r
1805         return STATUS_SUCCESS;\r
1806 }\r
1807 \r
1808 \r
1809 static NTSTATUS\r
1810 port_query_ipoib_ifc(\r
1811         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1812         IN                              IO_STACK_LOCATION* const        p_io_stack )\r
1813 {\r
1814         NTSTATUS                                status;\r
1815         ib_al_ifc_t                             *p_ifc;\r
1816         ib_al_ifc_data_t                *p_ifc_data;\r
1817         ipoib_ifc_data_t                *p_ipoib_data;\r
1818         bus_port_ext_t                  *p_ext;\r
1819         const GUID                              *p_guid;\r
1820 \r
1821         BUS_ENTER( BUS_DBG_PNP );\r
1822 \r
1823         CL_ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );\r
1824 \r
1825         p_ext = p_dev_obj->DeviceExtension;\r
1826 \r
1827         BUS_TRACE( BUS_DBG_PNP, ("Query i/f for %s: PDO %p (=%p),ext %p, present %d, missing %d .\n",\r
1828                 p_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_ext->pdo.cl_ext.p_self_do, \r
1829                 p_dev_obj, p_ext, p_ext->pdo.b_present, p_ext->pdo.b_reported_missing ) );\r
1830 \r
1831         /* Get the interface. */\r
1832         status = cl_fwd_query_ifc(\r
1833                 p_ext->pdo.p_parent_ext->cl_ext.p_self_do, p_io_stack );\r
1834         if( !NT_SUCCESS( status ) )\r
1835         {\r
1836                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
1837                         ("Failed to forward interface query: %08X\n", status) );\r
1838                 return status;\r
1839         }\r
1840 \r
1841         if( !p_io_stack->Parameters.QueryInterface.InterfaceSpecificData )\r
1842         {\r
1843                 BUS_TRACE_EXIT( BUS_DBG_ERROR, ("No interface specific data!\n") );\r
1844                 return status;\r
1845         }\r
1846 \r
1847         p_ifc = (ib_al_ifc_t*)p_io_stack->Parameters.QueryInterface.Interface;\r
1848 \r
1849         p_ifc_data = (ib_al_ifc_data_t*)\r
1850                 p_io_stack->Parameters.QueryInterface.InterfaceSpecificData;\r
1851         p_guid = p_ifc_data->type;\r
1852         if( !IsEqualGUID( p_guid, &GUID_IPOIB_INTERFACE_DATA ) )\r
1853         {\r
1854                 BUS_TRACE_EXIT( BUS_DBG_PNP, ("Unsupported interface data: \n\t"\r
1855                         "0x%08x, 0x%04x, 0x%04x, 0x%02x, 0x%02x, 0x%02x,"\r
1856                         "0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x.\n",\r
1857                         p_guid->Data1, p_guid->Data2, p_guid->Data3,\r
1858                         p_guid->Data4[0], p_guid->Data4[1], p_guid->Data4[2],\r
1859                         p_guid->Data4[3], p_guid->Data4[4], p_guid->Data4[5],\r
1860                         p_guid->Data4[6], p_guid->Data4[7]) );\r
1861                 return status;\r
1862         }\r
1863 \r
1864         if( p_ifc_data->version != IPOIB_INTERFACE_DATA_VERSION )\r
1865         {\r
1866                 p_ifc->wdm.InterfaceDereference( p_ifc->wdm.Context );\r
1867                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
1868                         ("Unsupported version %d, expected %d\n",\r
1869                         p_ifc_data->version, IPOIB_INTERFACE_DATA_VERSION) );\r
1870                 return STATUS_NOT_SUPPORTED;\r
1871         }\r
1872 \r
1873         ASSERT( p_ifc_data->p_data );\r
1874 \r
1875         if( p_ifc_data->size != sizeof(ipoib_ifc_data_t) )\r
1876         {\r
1877                 p_ifc->wdm.InterfaceDereference( p_ifc->wdm.Context );\r
1878                 BUS_TRACE_EXIT( BUS_DBG_PNP,\r
1879                         ("Buffer too small (%d given, %d required).\n",\r
1880                         p_ifc_data->size,\r
1881                         sizeof(ipoib_ifc_data_t)) );\r
1882                 return STATUS_BUFFER_TOO_SMALL;\r
1883         }\r
1884 \r
1885         /* Set the interface data. */\r
1886         p_ipoib_data = (ipoib_ifc_data_t*)p_ifc_data->p_data;\r
1887 \r
1888         p_ipoib_data->ca_guid = p_ext->pdo.h_ca->obj.p_ci_ca->verbs.guid;\r
1889         p_ipoib_data->port_guid = p_ext->port_guid;\r
1890         p_ipoib_data->port_num = (uint8_t)p_ext->n_port;\r
1891 \r
1892         BUS_EXIT( BUS_DBG_PNP );\r
1893         return STATUS_SUCCESS;\r
1894 }\r
1895 \r
1896 \r
1897 static NTSTATUS\r
1898 port_query_interface(\r
1899         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1900         IN                                      IRP* const                              p_irp,\r
1901                 OUT                             cl_irp_action_t* const  p_action )\r
1902 {\r
1903         bus_pdo_ext_t           *p_ext;\r
1904         NTSTATUS                        status;\r
1905         IO_STACK_LOCATION       *p_io_stack;\r
1906 \r
1907         BUS_ENTER( BUS_DBG_PNP );\r
1908 \r
1909         PAGED_CODE();\r
1910 \r
1911         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
1912 \r
1913         /* Bottom of the stack - IRP must be completed. */\r
1914         *p_action = IrpComplete;\r
1915 \r
1916         /* Compare requested GUID with our supported interface GUIDs. */\r
1917         if( IsEqualGUID( p_io_stack->Parameters.QueryInterface.InterfaceType,\r
1918                 &GUID_IB_AL_INTERFACE ) )\r
1919         {\r
1920                 status = port_query_ipoib_ifc( p_dev_obj, p_io_stack );\r
1921         }\r
1922         else if( IsEqualGUID( p_io_stack->Parameters.QueryInterface.InterfaceType,\r
1923                 &GUID_BUS_INTERFACE_STANDARD ) )\r
1924         {\r
1925                 p_ext = p_dev_obj->DeviceExtension;\r
1926                 if( !p_ext->h_ca ||\r
1927                         !p_ext->b_present ||\r
1928                         p_ext->b_reported_missing )\r
1929                 {\r
1930                         return STATUS_NO_SUCH_DEVICE;\r
1931                 }\r
1932 \r
1933                 status = cl_fwd_query_ifc(\r
1934                         p_ext->h_ca->obj.p_ci_ca->verbs.p_hca_dev, p_io_stack );\r
1935         }\r
1936         else\r
1937         {\r
1938                 status = p_irp->IoStatus.Status;\r
1939         }\r
1940         \r
1941         BUS_EXIT( BUS_DBG_PNP );\r
1942         return status;\r
1943 }\r
1944 \r
1945 \r
1946 /* Work item callback to handle DevicePowerD3 IRPs at passive level. */\r
1947 static void\r
1948 __HibernateUpWorkItem(\r
1949         IN                              DEVICE_OBJECT*                          p_dev_obj,\r
1950         IN                              void*                                           context )\r
1951 {\r
1952         IO_STACK_LOCATION       *p_io_stack;\r
1953         bus_pdo_ext_t           *p_ext;\r
1954         IRP                                     *p_irp;\r
1955         POWER_STATE powerState;\r
1956 \r
1957         BUS_ENTER( BUS_DBG_POWER );\r
1958 \r
1959         p_ext = (bus_pdo_ext_t*)p_dev_obj->DeviceExtension;\r
1960         p_irp = (IRP*)context;\r
1961         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
1962 \r
1963         IoFreeWorkItem( p_ext->p_po_work_item );\r
1964         p_ext->p_po_work_item = NULL;\r
1965 \r
1966         while (!p_ext->h_ca) {\r
1967                 BUS_TRACE( BUS_DBG_PNP, ("Waiting for the end of HCA registration ... \n"));\r
1968                 cl_thread_suspend( 200 );       /* suspend for 200 ms */\r
1969         }\r
1970 \r
1971         p_ext->dev_po_state = p_io_stack->Parameters.Power.State;\r
1972         powerState = PoSetPowerState( p_dev_obj, DevicePowerState, p_ext->dev_po_state );\r
1973 \r
1974         BUS_TRACE( BUS_DBG_POWER, \r
1975                 ("PoSetPowerState: old state %d, new state to %d\n", \r
1976                 powerState.DeviceState, p_ext->dev_po_state ));\r
1977 \r
1978         p_irp->IoStatus.Status = STATUS_SUCCESS;\r
1979         PoStartNextPowerIrp( p_irp );\r
1980         IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
1981         IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
1982 \r
1983         BUS_EXIT( BUS_DBG_POWER );\r
1984 }\r
1985 \r
1986 \r
1987 /*\r
1988  * The PDOs created by the IB Bus driver are software devices.  As such,\r
1989  * all power states are supported.  It is left to the HCA power policy\r
1990  * owner to handle which states can be supported by the HCA.\r
1991  */\r
1992 static NTSTATUS\r
1993 port_set_power(\r
1994         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1995         IN                              IRP* const                                      p_irp,\r
1996                 OUT                     cl_irp_action_t* const          p_action )\r
1997 {\r
1998         NTSTATUS                        status = STATUS_SUCCESS;\r
1999         IO_STACK_LOCATION       *p_io_stack;\r
2000         bus_pdo_ext_t           *p_ext;\r
2001 \r
2002         BUS_ENTER( BUS_DBG_POWER );\r
2003 \r
2004         p_ext = p_dev_obj->DeviceExtension;\r
2005         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
2006 \r
2007         BUS_TRACE( BUS_DBG_POWER, \r
2008                 ("SET_POWER for PDO %p (ext %p): type %s, state %d, action %d \n",\r
2009                 p_dev_obj, p_ext,\r
2010                 (p_io_stack->Parameters.Power.Type) ? "DevicePowerState" : "SystemPowerState",\r
2011                 p_io_stack->Parameters.Power.State.DeviceState, \r
2012                 p_io_stack->Parameters.Power.ShutdownType ));\r
2013 \r
2014         if ((p_io_stack->Parameters.Power.Type == SystemPowerState) &&\r
2015                 (p_io_stack->Parameters.Power.State.SystemState ==PowerSystemHibernate ||\r
2016                 p_io_stack->Parameters.Power.State.SystemState ==PowerSystemSleeping1 ))\r
2017         {\r
2018                 BUS_TRACE( BUS_DBG_POWER, ("Setting b_hibernating flag for PDO %p \n", p_dev_obj));\r
2019                 p_ext->b_hibernating = TRUE;\r
2020         }\r
2021 \r
2022         if( p_io_stack->Parameters.Power.Type == DevicePowerState )\r
2023         {\r
2024                 /* after hibernation PDO is not ready for work. we need to wait for finishing of the HCA registration */\r
2025                 if( p_io_stack->Parameters.Power.State.DeviceState == PowerDeviceD0 && p_ext->b_hibernating)\r
2026                 {\r
2027                         /* Process in a work item - deregister_ca and HcaDeinit block. */\r
2028                         ASSERT( !p_ext->p_po_work_item );\r
2029                         p_ext->p_po_work_item = IoAllocateWorkItem( p_dev_obj );\r
2030                         if( !p_ext->p_po_work_item )\r
2031                                 status = STATUS_INSUFFICIENT_RESOURCES;\r
2032                         else {\r
2033                                 /* Process in work item callback. */\r
2034                                 IoMarkIrpPending( p_irp );\r
2035                                 IoQueueWorkItem(\r
2036                                         p_ext->p_po_work_item, __HibernateUpWorkItem, DelayedWorkQueue, p_irp );\r
2037                                 *p_action = IrpDoNothing;\r
2038                                 BUS_EXIT( BUS_DBG_POWER );\r
2039                                 return STATUS_PENDING;\r
2040                         }\r
2041                 }\r
2042 \r
2043                 /* Notify the power manager. */\r
2044                 p_ext->dev_po_state = p_io_stack->Parameters.Power.State;\r
2045                 PoSetPowerState( p_dev_obj, DevicePowerState, p_ext->dev_po_state );\r
2046         }\r
2047 \r
2048         *p_action = IrpComplete;\r
2049         BUS_EXIT( BUS_DBG_POWER );\r
2050         return status;\r
2051 }\r