[IBBUS] a little fix to 2019 patch (remove HCA registration with IBAL.). [mlnx: 4105]
[mirror/winof/.git] / core / bus / kernel / bus_pnp.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 \r
35 /*\r
36  * Implemenation of all PnP functionality for FDO (power policy owners).\r
37  */\r
38 \r
39 #include "bus_pnp.h"\r
40 #include "al_ca.h"\r
41 #include "al_init.h"\r
42 #include "al_dev.h"\r
43 #include "bus_port_mgr.h"\r
44 #include "bus_iou_mgr.h"\r
45 #include "complib/cl_memory.h"\r
46 #include <initguid.h>\r
47 #include "iba/ib_ci_ifc.h"\r
48 #include "iba/ib_cm_ifc.h"\r
49 #include "al_cm_cep.h"\r
50 #include "al_mgr.h"\r
51 \r
52 \r
53 /* Interface names are generated by IoRegisterDeviceInterface. */\r
54 static UNICODE_STRING   al_ifc_name;\r
55 static UNICODE_STRING   ci_ifc_name;\r
56 static UNICODE_STRING   cm_ifc_name;\r
57 \r
58 KEVENT                                  g_ControlEvent;\r
59 ULONG                                   g_bfi_InstanceCount;\r
60 bus_filter_t                    g_bus_filters[MAX_BUS_FILTERS];\r
61 \r
62 extern ib_al_handle_t   gh_al; // NULL if AL needs init.\r
63 \r
64 \r
65 static NTSTATUS\r
66 fdo_start(\r
67         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
68         IN                                      IRP* const                              p_irp, \r
69                 OUT                             cl_irp_action_t* const  p_action );\r
70 \r
71 static void\r
72 fdo_release_resources(\r
73         IN                                      DEVICE_OBJECT* const    p_dev_obj );\r
74 \r
75 static NTSTATUS\r
76 fdo_query_remove(\r
77         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
78         IN                                      IRP* const                              p_irp, \r
79                 OUT                             cl_irp_action_t* const  p_action );\r
80 \r
81 static NTSTATUS\r
82 fdo_query_capabilities(\r
83         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
84         IN                                      IRP* const                              p_irp, \r
85                 OUT                             cl_irp_action_t* const  p_action );\r
86 \r
87 static NTSTATUS\r
88 fdo_query_bus_relations(\r
89         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
90         IN                                      IRP* const                              p_irp, \r
91                 OUT                             cl_irp_action_t* const  p_action );\r
92 \r
93 static NTSTATUS\r
94 __query_al_ifc(\r
95         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
96         IN                              IO_STACK_LOCATION* const        p_io_stack );\r
97 \r
98 static NTSTATUS\r
99 __get_relations(\r
100         IN              const   net64_t                                         ca_guid,\r
101         IN                              IRP* const                                      p_irp );\r
102 \r
103 static NTSTATUS\r
104 __query_ci_ifc(\r
105         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
106         IN                              IO_STACK_LOCATION* const        p_io_stack );\r
107 \r
108 static NTSTATUS\r
109 __query_cm_ifc(\r
110         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
111         IN                              IO_STACK_LOCATION* const        p_io_stack );\r
112 \r
113 static NTSTATUS\r
114 fdo_query_interface(\r
115         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
116         IN                              IRP* const                                      p_irp, \r
117                 OUT                     cl_irp_action_t* const          p_action );\r
118 \r
119 static NTSTATUS\r
120 __fdo_query_power(\r
121         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
122         IN                              IRP* const                                      p_irp,\r
123                 OUT                     cl_irp_action_t* const          p_action );\r
124 \r
125 static NTSTATUS\r
126 __fdo_set_power(\r
127         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
128         IN                              IRP* const                                      p_irp,\r
129                 OUT                     cl_irp_action_t* const          p_action );\r
130 \r
131 static void\r
132 __set_ifc(\r
133                 OUT                     ib_al_ifc_t* const                      p_ifc );\r
134 \r
135 \r
136 \r
137 \r
138 /* Global virtual function pointer tables shared between all instances of FDO. */\r
139 static const cl_vfptr_pnp_po_t          vfptr_fdo_pnp = {\r
140         "IB Bus",\r
141         fdo_start,\r
142         cl_irp_skip,\r
143         cl_irp_skip,\r
144         cl_do_sync_pnp,\r
145         fdo_query_remove,\r
146         fdo_release_resources,\r
147         cl_do_remove,\r
148         cl_do_sync_pnp,\r
149         cl_irp_skip,\r
150         fdo_query_capabilities,\r
151         cl_irp_skip,\r
152         cl_irp_skip,\r
153         cl_do_sync_pnp,\r
154         fdo_query_bus_relations,\r
155         cl_irp_ignore,\r
156         cl_irp_skip,\r
157         cl_irp_ignore,\r
158         cl_irp_ignore,\r
159         cl_irp_ignore,\r
160         cl_irp_ignore,\r
161         cl_irp_ignore,\r
162         fdo_query_interface,    /* QueryInterface */\r
163         cl_irp_ignore,\r
164         cl_irp_ignore,\r
165         cl_irp_ignore,\r
166         cl_irp_ignore,\r
167         __fdo_query_power,              /* QueryPower */\r
168         __fdo_set_power,                /* SetPower */\r
169         cl_irp_ignore,                  /* PowerSequence */\r
170         cl_irp_ignore                   /* WaitWake */\r
171 };\r
172 \r
173 \r
174 NTSTATUS\r
175 bus_add_device(\r
176         IN                              DRIVER_OBJECT                           *p_driver_obj,\r
177         IN                              DEVICE_OBJECT                           *p_pdo )\r
178 {\r
179         NTSTATUS                status;\r
180         DEVICE_OBJECT   *p_dev_obj, *p_next_do;\r
181         bus_fdo_ext_t   *p_ext=NULL;\r
182         UNICODE_STRING  dev_name, dos_name;\r
183         bus_filter_t    *p_bfi;\r
184         int                             ic;\r
185 \r
186         BUS_ENTER( BUS_DBG_PNP );\r
187 \r
188         /* allocate a Bus Filter Instance */\r
189         p_bfi = alloc_bfi( p_driver_obj, &ic );\r
190         if ( !p_bfi )\r
191         {\r
192                 BUS_TRACE_EXIT( BUS_DBG_PNP,\r
193                         ("%s() Err - Exceeded MAX_BUS_FILTERS(%d)\n",MAX_BUS_FILTERS));\r
194                 return STATUS_UNSUCCESSFUL;\r
195         }\r
196 \r
197         /* Create the FDO device object to attach to the stack. */\r
198 \r
199         /* if 1st Bus Filter Instance, then create device names for user ioctl */\r
200         if ( ic == 1 )\r
201         {\r
202                 RtlInitUnicodeString( &dev_name, AL_DEVICE_NAME );\r
203                 RtlInitUnicodeString( &dos_name, L"\\DosDevices\\Global\\ibal" );\r
204 \r
205                 status = IoCreateDevice( p_driver_obj, sizeof(bus_fdo_ext_t),\r
206                                                                  &dev_name, FILE_DEVICE_BUS_EXTENDER,\r
207                                                                  FILE_DEVICE_SECURE_OPEN, FALSE, &p_dev_obj );\r
208                 if( !NT_SUCCESS(status) )\r
209                 {\r
210                         BUS_PRINT( BUS_DBG_ERROR, \r
211                                 ("Failed to create ControlDeviceObject, status %x.\n",status) );\r
212                         goto err1;\r
213                 }\r
214                 IoDeleteSymbolicLink( &dos_name );\r
215                 status = IoCreateSymbolicLink( &dos_name, &dev_name );\r
216                 if( !NT_SUCCESS(status) )\r
217                 {\r
218                         BUS_PRINT( BUS_DBG_ERROR,\r
219                                 ("Failed to create symlink for dos name.\n") );\r
220                         goto err2;\r
221                 }\r
222         }\r
223         else {\r
224                 status = IoCreateDevice( p_driver_obj, sizeof(bus_fdo_ext_t),\r
225                                                                  NULL, FILE_DEVICE_BUS_EXTENDER,\r
226                                                                  FILE_DEVICE_SECURE_OPEN, FALSE, &p_dev_obj );\r
227                 if( !NT_SUCCESS(status) )\r
228                 {\r
229                         BUS_PRINT( BUS_DBG_ERROR, \r
230                                 ("Failed to create bus root FDO device.\n") );\r
231                         goto err1;\r
232                 }\r
233         }\r
234 \r
235         p_ext = p_dev_obj->DeviceExtension;\r
236         p_ext->n_al_ifc_ref = 0;\r
237         p_ext->n_ci_ifc_ref = 0;\r
238 \r
239         p_next_do = IoAttachDeviceToDeviceStack( p_dev_obj, p_pdo );\r
240         if( !p_next_do )\r
241         {\r
242                 BUS_PRINT( BUS_DBG_ERROR, ("IoAttachToDeviceStack failed.\n") );\r
243                 status = STATUS_NO_SUCH_DEVICE;\r
244                 goto err2;\r
245         }\r
246 \r
247         cl_init_pnp_po_ext( p_dev_obj, p_next_do, p_pdo, bus_globals.dbg_lvl,\r
248                                                 &vfptr_fdo_pnp, NULL );\r
249 \r
250         p_bfi->p_bus_ext = p_ext;\r
251         p_ext->bus_filter = p_bfi;\r
252 \r
253         /*\r
254          * if not 1st Bus Filter Instance, then finished...\r
255          */\r
256         if ( ic > 1 )\r
257                 goto adxit;\r
258 \r
259         /* Register the upper interface (the one used by clients). */\r
260         status = IoRegisterDeviceInterface( p_pdo, &GUID_IB_AL_INTERFACE, NULL,\r
261                                                                                 &al_ifc_name );\r
262         if( !NT_SUCCESS( status ) )\r
263         {\r
264                 BUS_PRINT( BUS_DBG_ERROR, \r
265                         ("IoRegisterDeviceInterface for upper interface returned %08x\n",\r
266                         status) );\r
267                 status = STATUS_NO_SUCH_DEVICE;\r
268                 goto err3;\r
269         }\r
270 \r
271         /* Register the lower (CI) interface (the one used by HCA VPDs). */\r
272         status = IoRegisterDeviceInterface( p_pdo, &GUID_IB_CI_INTERFACE, NULL,\r
273                                                                                 &ci_ifc_name );\r
274         if( !NT_SUCCESS( status ) )\r
275         {\r
276                 BUS_PRINT( BUS_DBG_ERROR, \r
277                         ("IoRegisterDeviceInterface for lower interface returned %08x\n",\r
278                         status) );\r
279                 status = STATUS_NO_SUCH_DEVICE;\r
280                 goto err3;\r
281         }\r
282 \r
283         status = IoRegisterDeviceInterface( p_pdo, &GUID_INFINIBAND_INTERFACE_CM, NULL,\r
284                                                                                 &cm_ifc_name );\r
285         if( !NT_SUCCESS( status ) )\r
286         {\r
287                 BUS_PRINT( BUS_DBG_ERROR, \r
288                         ("IoRegisterDeviceInterface for cm interface returned %08x\n",\r
289                         status) );\r
290                 status = STATUS_NO_SUCH_DEVICE;\r
291                 goto err3;\r
292         }\r
293 \r
294 adxit:\r
295         BUS_PRINT( BUS_DBG_PNP, ("%s exit status 0\n", p_bfi->whoami) );\r
296 \r
297         BUS_EXIT( BUS_DBG_PNP );\r
298         return STATUS_SUCCESS;\r
299 \r
300 err3:\r
301         IoDetachDevice( p_ext->cl_ext.p_next_do );\r
302 err2:\r
303         IoDeleteDevice( p_dev_obj );\r
304 err1:\r
305         BUS_PRINT( BUS_DBG_PNP, ("%s exit status 0x%x\n", p_bfi->whoami,status) );\r
306         ic = free_bfi(p_bfi);\r
307         /* if last Bus filter, then cleanup */\r
308         if ( ic == 0 )\r
309         {\r
310                 IoDeleteSymbolicLink( &dos_name );\r
311                 RtlFreeUnicodeString( &al_ifc_name );\r
312         }\r
313         BUS_EXIT( BUS_DBG_PNP );\r
314         return status;\r
315 }\r
316 \r
317 \r
318 /* Forwards the request to the HCA's FDO. */\r
319 static NTSTATUS\r
320 __get_ifc(\r
321         IN                              DEVICE_OBJECT* const            pDevObj,\r
322         IN              const   GUID* const                                     pGuid,\r
323         IN                              USHORT                                          size,\r
324         IN                              USHORT                                          Version,\r
325         IN OUT                  PVOID                                           InterfaceSpecificData,\r
326                 OUT                     PINTERFACE                                      pHcaIfc )\r
327 {\r
328         NTSTATUS                        status;\r
329         IRP                                     *pIrp;\r
330         IO_STATUS_BLOCK         ioStatus;\r
331         IO_STACK_LOCATION       *pIoStack;\r
332         DEVICE_OBJECT           *pDev;\r
333         KEVENT                          event;\r
334 \r
335         BUS_ENTER( BUS_DBG_PNP );\r
336 \r
337         CL_ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );\r
338 \r
339         pDev = IoGetAttachedDeviceReference( pDevObj );\r
340 \r
341         KeInitializeEvent( &event, NotificationEvent, FALSE );\r
342 \r
343         /* Build the IRP for the HCA. */\r
344         pIrp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, pDev,\r
345                 NULL, 0, NULL, &event, &ioStatus );\r
346         if( !pIrp )\r
347         {\r
348                 ObDereferenceObject( pDev );\r
349                 BUS_PRINT( BUS_DBG_PNP, \r
350                         ("IoBuildSynchronousFsdRequest failed.\n"));\r
351                 return STATUS_INSUFFICIENT_RESOURCES;\r
352         }\r
353 \r
354         /* Copy the request query parameters. */\r
355         pIoStack = IoGetNextIrpStackLocation( pIrp );\r
356         pIoStack->MinorFunction = IRP_MN_QUERY_INTERFACE;\r
357         pIoStack->Parameters.QueryInterface.Size = size;\r
358         pIoStack->Parameters.QueryInterface.Version = Version;\r
359         pIoStack->Parameters.QueryInterface.InterfaceType = pGuid;\r
360         pIoStack->Parameters.QueryInterface.Interface = (INTERFACE*)pHcaIfc;\r
361         pIoStack->Parameters.QueryInterface.InterfaceSpecificData = InterfaceSpecificData;\r
362 \r
363         pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;\r
364 \r
365         /* Send the IRP. */\r
366         status = IoCallDriver( pDev, pIrp );\r
367         if( status == STATUS_PENDING )\r
368         {\r
369                 KeWaitForSingleObject( &event, Executive, KernelMode,\r
370                         FALSE, NULL );\r
371 \r
372                 status = ioStatus.Status;\r
373         }\r
374         ObDereferenceObject( pDev );\r
375 \r
376         BUS_EXIT( BUS_DBG_PNP );\r
377         return status;\r
378 }\r
379 \r
380 static NTSTATUS\r
381 fdo_start(\r
382         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
383         IN                                      IRP* const                              p_irp, \r
384                 OUT                             cl_irp_action_t* const  p_action )\r
385 {\r
386         NTSTATUS                status;\r
387         bus_fdo_ext_t   *p_ext;\r
388         ib_api_status_t ib_status;\r
389         bus_filter_t    *p_bfi;\r
390         boolean_t               AL_init_here = FALSE;\r
391 \r
392         BUS_ENTER( BUS_DBG_PNP );\r
393 \r
394         p_ext = p_dev_obj->DeviceExtension;\r
395         p_bfi = p_ext->bus_filter;\r
396 \r
397         /* Handled on the way up. */\r
398         status = cl_do_sync_pnp( p_dev_obj, p_irp, p_action );\r
399         if( !NT_SUCCESS( status ) )\r
400         {\r
401                 BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
402                         ("Lower drivers failed IRP_MN_START_DEVICE.\n") );\r
403                 return status;\r
404         }\r
405 \r
406         lock_control_event();\r
407         if ( !gh_al ) {\r
408                 /* Initialize AL */\r
409                 ib_status = al_initialize();\r
410                 if( ib_status != IB_SUCCESS )\r
411                 {\r
412                         al_cleanup();\r
413                         BUS_TRACE_EXIT( BUS_DBG_ERROR, ("al_initialize returned %s.\n",\r
414                                                         ib_get_err_str(ib_status)) );\r
415                         unlock_control_event();\r
416                         return STATUS_UNSUCCESSFUL;\r
417                 }\r
418                 AL_init_here = TRUE;\r
419         }\r
420         unlock_control_event();\r
421 \r
422         /* Initialize the port manager. */\r
423         ib_status = create_port_mgr( p_ext->bus_filter, &p_ext->p_port_mgr );\r
424         if( ib_status != IB_SUCCESS )\r
425         {\r
426                 BUS_TRACE_EXIT( BUS_DBG_ERROR, ("create_port_mgr returned %s.\n",\r
427                         ib_get_err_str(ib_status)) );\r
428                 return STATUS_UNSUCCESSFUL;\r
429         }\r
430 \r
431         /* Initialize the IOU manager. */\r
432         ib_status = create_iou_mgr( p_ext->bus_filter, &p_ext->p_iou_mgr );\r
433         if( ib_status != IB_SUCCESS )\r
434         {\r
435                 BUS_TRACE_EXIT( BUS_DBG_ERROR, ("create_iou_mgr returned %s.\n",\r
436                         ib_get_err_str(ib_status)) );\r
437                 return STATUS_UNSUCCESSFUL;\r
438         }\r
439 \r
440         if ( AL_init_here ) {\r
441                 status = IoSetDeviceInterfaceState( &al_ifc_name, TRUE );\r
442                 ASSERT( NT_SUCCESS( status ) );\r
443 \r
444                 status = IoSetDeviceInterfaceState( &ci_ifc_name, TRUE );\r
445                 ASSERT( NT_SUCCESS( status ) );\r
446 \r
447                 status = IoSetDeviceInterfaceState( &cm_ifc_name, TRUE );\r
448                 ASSERT( NT_SUCCESS( status ) );\r
449         }\r
450 \r
451         /* get HCA verbs interface */\r
452         status = __get_ifc( p_dev_obj, &GUID_RDMA_INTERFACE_VERBS,\r
453                                                 sizeof(RDMA_INTERFACE_VERBS), \r
454                                                 VerbsVersion(VERBS_MAJOR_VER, VERBS_MINOR_VER), \r
455                                                 p_ext, (PINTERFACE)&p_ext->hca_ifc );\r
456         if( !NT_SUCCESS( status ) ) \r
457         {\r
458                 BUS_TRACE_EXIT(BUS_DBG_PNP,\r
459                         ("Getting MLX4 BUS interface failed: status=0x%x\n", status));\r
460                 return STATUS_UNSUCCESSFUL;\r
461         }\r
462         p_ext->hca_ifc_taken = TRUE;\r
463 \r
464         /* bind BFI to HCA by CA GUID. Have to be before ib_register_ca */\r
465         p_bfi->ca_guid = p_ext->hca_ifc.Verbs.guid;\r
466 \r
467         /* register HCA */\r
468         ib_status = ib_register_ca( &p_ext->hca_ifc.Verbs, p_ext->cl_ext.p_pdo );\r
469         if( ib_status != IB_SUCCESS )\r
470         {\r
471                 BUS_TRACE_EXIT( BUS_DBG_ERROR, ("ib_register_ca returned %s.\n",\r
472                         ib_get_err_str(ib_status)) );\r
473                 return STATUS_UNSUCCESSFUL;\r
474         }\r
475 \r
476         BUS_TRACE_EXIT(BUS_DBG_PNP, ("%s bound to CA guid %I64x\n",\r
477                                                                         p_bfi->whoami,p_bfi->ca_guid));\r
478         return status;\r
479 }\r
480 \r
481 \r
482 static NTSTATUS\r
483 fdo_query_remove(\r
484         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
485         IN                                      IRP* const                              p_irp, \r
486                 OUT                             cl_irp_action_t* const  p_action )\r
487 {\r
488         bus_fdo_ext_t   *p_ext;\r
489 \r
490         BUS_ENTER( BUS_DBG_PNP );\r
491 \r
492         p_ext = p_dev_obj->DeviceExtension;\r
493 \r
494         CL_ASSERT(p_ext->bus_filter);\r
495         BUS_PRINT( BUS_DBG_PNP,\r
496                 ("IRP_MN_QUERY_REMOVE_DEVICE %s @ FDO %p refs(CI %d AL %d)\n"\r
497                 "   %s CA %I64x\n", \r
498                 p_ext->cl_ext.vfptr_pnp_po->identity, p_ext, p_ext->n_ci_ifc_ref,\r
499                 p_ext->n_al_ifc_ref,\r
500                 p_ext->bus_filter->whoami, p_ext->bus_filter->ca_guid) );\r
501 \r
502         if( p_ext->n_ci_ifc_ref )\r
503         {\r
504                 /*\r
505                  * Our interface is still being held by someone.\r
506                  * Rollback the PnP state that was changed in the cl_ext handler.\r
507                  */\r
508                 cl_rollback_pnp_state( &p_ext->cl_ext );\r
509 \r
510                 /* Fail the query. */\r
511                 *p_action = IrpComplete;\r
512                 BUS_TRACE_EXIT( BUS_DBG_PNP, \r
513                         ("Failing IRP_MN_QUERY_REMOVE_DEVICE:\n"\r
514                         "\tLowerInterface has %d references\n", \r
515                         p_ext->n_ci_ifc_ref ) );\r
516                 return STATUS_UNSUCCESSFUL;\r
517         }\r
518 \r
519         /* remove port & iou managers */        \r
520         CL_ASSERT( p_ext->bus_filter );\r
521 \r
522         //TODO: Fail outstanding I/O operations.\r
523 \r
524         *p_action = IrpSkip;\r
525         /* The FDO driver must set the status even when passing down. */\r
526         p_irp->IoStatus.Status = STATUS_SUCCESS;\r
527 \r
528         BUS_EXIT( BUS_DBG_PNP );\r
529         return STATUS_SUCCESS;\r
530 }\r
531 \r
532 \r
533 /*\r
534  * This function gets called after releasing the remove lock and waiting\r
535  * for all other threads to release the lock.  No more modifications will\r
536  * occur to the PDO pointer vectors.\r
537  */\r
538 static void\r
539 fdo_release_resources(\r
540         IN                                      DEVICE_OBJECT* const    p_dev_obj )\r
541 {\r
542         bus_fdo_ext_t   *p_ext;\r
543         NTSTATUS                status;\r
544         bus_filter_t    *p_bfi;\r
545         int                             ic;\r
546         ib_api_status_t ib_status;\r
547 \r
548         BUS_ENTER( BUS_DBG_PNP );\r
549 \r
550         p_ext = p_dev_obj->DeviceExtension;\r
551         ic = get_bfi_count();\r
552 \r
553         p_bfi = p_ext->bus_filter;\r
554         CL_ASSERT( p_bfi );\r
555 \r
556         //TODO: Fail outstanding I/O operations.\r
557 \r
558         ib_status = ib_deregister_ca( p_ext->hca_ifc.Verbs.guid );\r
559         if( ib_status != IB_SUCCESS ) {\r
560                 BUS_PRINT( BUS_DBG_ERROR, ("ib_deregister_ca returned %s.\n",\r
561                         ib_get_err_str(ib_status)) );\r
562         }\r
563 \r
564         if ( p_ext->p_port_mgr && p_bfi->p_port_mgr ) {\r
565                 cl_obj_destroy( &p_ext->p_port_mgr->obj );\r
566                 p_ext->p_port_mgr = NULL;\r
567         }\r
568 \r
569         if ( p_ext->p_iou_mgr && p_bfi->p_iou_mgr ) {\r
570                 cl_obj_destroy( &p_ext->p_iou_mgr->obj );\r
571                 p_ext->p_iou_mgr = NULL;\r
572         }\r
573 \r
574         if (p_ext->hca_ifc_taken) {\r
575                 p_ext->hca_ifc.InterfaceHeader.InterfaceDereference(\r
576                         p_ext->hca_ifc.InterfaceHeader.Context);\r
577         }\r
578 \r
579         BUS_PRINT( BUS_DBG_PNP, ("Releasing BusFilter %s\n", p_bfi->whoami ));\r
580         if (p_bfi) {\r
581                 p_ext->bus_filter = NULL;\r
582                 p_bfi->p_bus_ext = NULL;\r
583         }\r
584 \r
585         ic = free_bfi( p_bfi );\r
586 \r
587         /* if not last Buf Filter Instance, then exit, otherwise cleanup/shutdown */\r
588         if ( ic > 0 ) {\r
589                 BUS_PRINT( BUS_DBG_PNP, (" %d remaining BusFilters\n", ic ));\r
590                 return;\r
591         }\r
592 \r
593         /* Disable any exported interfaces. */\r
594         status = IoSetDeviceInterfaceState( &al_ifc_name, FALSE );\r
595         ASSERT( NT_SUCCESS( status ) );\r
596         status = IoSetDeviceInterfaceState( &ci_ifc_name, FALSE );\r
597         ASSERT( NT_SUCCESS( status ) );\r
598         status = IoSetDeviceInterfaceState( &cm_ifc_name, FALSE );\r
599         ASSERT( NT_SUCCESS( status ) );\r
600 \r
601         /* Release the memory allocated for the interface symbolic names. */\r
602         RtlFreeUnicodeString( &cm_ifc_name );\r
603         RtlFreeUnicodeString( &ci_ifc_name );\r
604         RtlFreeUnicodeString( &al_ifc_name );\r
605 \r
606         al_cleanup();\r
607 \r
608         BUS_EXIT( BUS_DBG_PNP );\r
609 }\r
610 \r
611 \r
612 static NTSTATUS\r
613 fdo_query_capabilities(\r
614         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
615         IN                                      IRP* const                              p_irp, \r
616                 OUT                             cl_irp_action_t* const  p_action )\r
617 {\r
618         NTSTATUS                        status;\r
619         bus_fdo_ext_t           *p_ext;\r
620         IO_STACK_LOCATION       *p_io_stack;\r
621 \r
622         BUS_ENTER( BUS_DBG_PNP );\r
623 \r
624         p_ext = p_dev_obj->DeviceExtension;\r
625 \r
626         /* Process on the way up. */\r
627         status = cl_do_sync_pnp( p_dev_obj, p_irp, p_action );\r
628 \r
629         if( !NT_SUCCESS( status ) )\r
630         {\r
631                 BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
632                         ("cl_do_sync_pnp returned %08x.\n", status) );\r
633                 return status;\r
634         }\r
635 \r
636         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
637 \r
638         /*\r
639          * Store the device power maping into our extension since we're\r
640          * the power policy owner.  The mapping is used when handling\r
641          * IRP_MN_SET_POWER IRPs.\r
642          */\r
643         cl_memcpy( p_ext->po_state, \r
644                 p_io_stack->Parameters.DeviceCapabilities.Capabilities->DeviceState,\r
645                 sizeof( p_ext->po_state ) );\r
646 \r
647         BUS_EXIT( BUS_DBG_PNP );\r
648         return status;\r
649 }\r
650 \r
651 \r
652 static NTSTATUS\r
653 fdo_query_bus_relations(\r
654         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
655         IN                                      IRP* const                              p_irp, \r
656                 OUT                             cl_irp_action_t* const  p_action )\r
657 {\r
658         NTSTATUS                        status = STATUS_SUCCESS; /*default to success*/\r
659         bus_fdo_ext_t           *p_ext;\r
660         bus_filter_t            *p_bfi;\r
661         int                                     waitLoop = 0;\r
662 \r
663         BUS_ENTER( BUS_DBG_PNP );\r
664 \r
665         p_ext = p_dev_obj->DeviceExtension;\r
666 \r
667         if ( !p_ext->bus_filter )\r
668         {\r
669                 /* BFI has already been released */\r
670                 *p_action = IrpComplete;\r
671                 BUS_TRACE_EXIT( BUS_DBG_PNP, ("NULL BFI\n") );\r
672                 return STATUS_SUCCESS;\r
673         }\r
674 \r
675         p_bfi = p_ext->bus_filter;\r
676         CL_ASSERT( p_bfi->magic == BFI_MAGIC );\r
677 \r
678         while ( p_bfi->ca_guid == 0ULL )\r
679         {\r
680                 /* HCA not yet bound to a BFI slot (no PNP ADD event seen), no bus\r
681                  * relations yet.\r
682                  */\r
683                 BUS_PRINT(BUS_DBG_ERROR, ("%s ca_guid %I64x\n",p_bfi->whoami,\r
684                                                                 p_bfi->ca_guid));\r
685                 cl_thread_suspend( 100 );       /* suspend for 100 ms */\r
686                 waitLoop++;\r
687                 if(waitLoop>50) break;\r
688         }\r
689         if ( p_bfi->ca_guid != 0ULL )\r
690         {\r
691                 status = port_mgr_get_bus_relations( p_bfi->ca_guid, p_irp );\r
692                 if( status == STATUS_SUCCESS || \r
693                         status == STATUS_NO_SUCH_DEVICE )\r
694                 {\r
695                         status = iou_mgr_get_bus_relations( p_bfi->ca_guid, p_irp );\r
696                 }\r
697                 if( status == STATUS_NO_SUCH_DEVICE )\r
698                         status = STATUS_SUCCESS;\r
699         }\r
700 \r
701         switch( status )\r
702         {\r
703         case STATUS_NO_SUCH_DEVICE:\r
704                 *p_action = IrpSkip;\r
705                 status = STATUS_SUCCESS;\r
706                 break;\r
707 \r
708         case STATUS_SUCCESS:\r
709                 *p_action = IrpPassDown;\r
710                 break;\r
711 \r
712         default:\r
713                 *p_action = IrpComplete;\r
714                 break;\r
715         }\r
716 \r
717         BUS_EXIT( BUS_DBG_PNP );\r
718         return status;\r
719 }\r
720 \r
721 \r
722 void\r
723 al_ref_ifc(\r
724         IN                              DEVICE_OBJECT*                          p_dev_obj )\r
725 {\r
726         bus_fdo_ext_t   *p_ext;\r
727 \r
728         BUS_ENTER( BUS_DBG_PNP );\r
729 \r
730         p_ext = p_dev_obj->DeviceExtension;\r
731 \r
732         cl_atomic_inc( &p_ext->n_al_ifc_ref );\r
733         ObReferenceObject( p_dev_obj );\r
734 \r
735         BUS_EXIT( BUS_DBG_PNP );\r
736 }\r
737 \r
738 \r
739 void\r
740 al_deref_ifc(\r
741         IN                              DEVICE_OBJECT*                          p_dev_obj )\r
742 {\r
743         bus_fdo_ext_t   *p_ext;\r
744 \r
745         BUS_ENTER( BUS_DBG_PNP );\r
746 \r
747         p_ext = p_dev_obj->DeviceExtension;\r
748 \r
749         cl_atomic_dec( &p_ext->n_al_ifc_ref );\r
750         ObDereferenceObject( p_dev_obj );\r
751 \r
752         CL_ASSERT(p_ext->bus_filter);\r
753         BUS_PRINT( BUS_DBG_PNP, ("%s CA_guid %I64x al_ifc_ref %d\n",\r
754                                         p_ext->bus_filter->whoami, p_ext->bus_filter->ca_guid,\r
755                                         p_ext->n_al_ifc_ref) );\r
756 \r
757         BUS_EXIT( BUS_DBG_PNP );\r
758 }\r
759 \r
760 \r
761 void\r
762 al_ref_ci_ifc(\r
763         IN                              DEVICE_OBJECT*                          p_dev_obj )\r
764 {\r
765         bus_fdo_ext_t   *p_ext;\r
766 \r
767         BUS_ENTER( BUS_DBG_PNP );\r
768 \r
769         p_ext = p_dev_obj->DeviceExtension;\r
770 \r
771         cl_atomic_inc( &p_ext->n_ci_ifc_ref );\r
772         ObReferenceObject( p_dev_obj );\r
773 \r
774         BUS_EXIT( BUS_DBG_PNP );\r
775 }\r
776 \r
777 \r
778 void\r
779 al_deref_ci_ifc(\r
780         IN                              DEVICE_OBJECT*                          p_dev_obj )\r
781 {\r
782         bus_fdo_ext_t   *p_ext;\r
783 \r
784         BUS_ENTER( BUS_DBG_PNP );\r
785 \r
786         p_ext = p_dev_obj->DeviceExtension;\r
787 \r
788         cl_atomic_dec( &p_ext->n_ci_ifc_ref );\r
789         ObDereferenceObject( p_dev_obj );\r
790 \r
791         CL_ASSERT(p_ext->bus_filter);\r
792         BUS_PRINT( BUS_DBG_PNP, ("%s CA_guid %I64x ci_ifc_ref %d\n",\r
793                                                 p_ext->bus_filter->whoami, p_ext->bus_filter->ca_guid,\r
794                                                 p_ext->n_ci_ifc_ref) );\r
795 \r
796         BUS_EXIT( BUS_DBG_PNP );\r
797 }\r
798 \r
799 \r
800 static NTSTATUS\r
801 __query_al_ifc(\r
802         IN                                      DEVICE_OBJECT* const            p_dev_obj,\r
803         IN                                      IO_STACK_LOCATION* const        p_io_stack )\r
804 {\r
805         ib_al_ifc_t             *p_ifc;\r
806 \r
807         BUS_ENTER( BUS_DBG_PNP );\r
808 \r
809         if( p_io_stack->Parameters.QueryInterface.Version != \r
810                 AL_INTERFACE_VERSION )\r
811         {\r
812                 BUS_TRACE_EXIT( BUS_DBG_PNP, ("Incorrect interface version (%d)\n",\r
813                         p_io_stack->Parameters.QueryInterface.Version ) );\r
814                 return STATUS_NOT_SUPPORTED;\r
815         }\r
816 \r
817         if( p_io_stack->Parameters.QueryInterface.Size < sizeof(ib_al_ifc_t) )\r
818         {\r
819                 BUS_TRACE_EXIT( BUS_DBG_PNP, \r
820                         ("Buffer too small (%d given, %d required).\n",\r
821                         p_io_stack->Parameters.QueryInterface.Size, sizeof(ib_al_ifc_t)) );\r
822                 return STATUS_BUFFER_TOO_SMALL;\r
823         }\r
824 \r
825         // Copy the interface.\r
826         p_ifc = (ib_al_ifc_t*)p_io_stack->Parameters.QueryInterface.Interface;\r
827 \r
828         p_ifc->wdm.Size = sizeof(ib_al_ifc_t);\r
829         p_ifc->wdm.Version = AL_INTERFACE_VERSION;\r
830         p_ifc->wdm.Context = p_dev_obj;\r
831         p_ifc->wdm.InterfaceReference = al_ref_ifc;\r
832         p_ifc->wdm.InterfaceDereference = al_deref_ifc;\r
833 \r
834         __set_ifc( p_ifc );\r
835 \r
836         // take the reference before returning.\r
837         al_ref_ifc( p_dev_obj );\r
838         BUS_EXIT( BUS_DBG_PNP );\r
839         return STATUS_SUCCESS;\r
840 }\r
841 \r
842 static void\r
843 __set_ifc(\r
844                 OUT                     ib_al_ifc_t* const                      p_ifc )\r
845 {\r
846         BUS_ENTER( BUS_DBG_PNP );\r
847 \r
848         p_ifc->wdm.Size = sizeof(ib_al_ifc_t);\r
849         p_ifc->wdm.InterfaceReference = al_ref_ifc;\r
850         p_ifc->wdm.InterfaceDereference = al_deref_ifc;\r
851 \r
852         p_ifc->sync_destroy = ib_sync_destroy;\r
853         p_ifc->open_ca = ib_open_ca;\r
854         p_ifc->query_ca = ib_query_ca;\r
855         p_ifc->get_dev = get_ca_dev;\r
856         p_ifc->close_ca = ib_close_ca;\r
857         p_ifc->alloc_pd = ib_alloc_pd;\r
858         p_ifc->dealloc_pd = ib_dealloc_pd;\r
859         p_ifc->create_av = ib_create_av;\r
860         p_ifc->query_av = ib_query_av;\r
861         p_ifc->modify_av = ib_modify_av;\r
862         p_ifc->destroy_av = ib_destroy_av;\r
863         p_ifc->create_qp = ib_create_qp;\r
864         p_ifc->get_spl_qp = ib_get_spl_qp;\r
865         p_ifc->query_qp = ib_query_qp;\r
866         p_ifc->modify_qp = ib_modify_qp;\r
867         p_ifc->destroy_qp = ib_destroy_qp;\r
868         p_ifc->create_cq = ib_create_cq;\r
869         p_ifc->modify_cq = ib_modify_cq;\r
870         p_ifc->query_cq = ib_query_cq;\r
871         p_ifc->destroy_cq = ib_destroy_cq;\r
872         p_ifc->reg_mem = ib_reg_mem;\r
873         p_ifc->reg_phys = ib_reg_phys;\r
874         p_ifc->query_mr = ib_query_mr;\r
875         p_ifc->rereg_mem = ib_rereg_mem;\r
876         p_ifc->reg_shmid = ib_reg_shmid;\r
877         p_ifc->dereg_mr = ib_dereg_mr;\r
878         p_ifc->create_mw = ib_create_mw;\r
879         p_ifc->query_mw = ib_query_mw;\r
880         p_ifc->bind_mw = ib_bind_mw;\r
881         p_ifc->destroy_mw = ib_destroy_mw;\r
882         p_ifc->post_send = ib_post_send;\r
883         p_ifc->post_recv = ib_post_recv;\r
884         p_ifc->send_mad = ib_send_mad;\r
885         p_ifc->cancel_mad = ib_cancel_mad;\r
886         p_ifc->poll_cq = ib_poll_cq;\r
887         p_ifc->rearm_cq = ib_rearm_cq;\r
888         p_ifc->join_mcast = ib_join_mcast;\r
889         p_ifc->leave_mcast = ib_leave_mcast;\r
890         p_ifc->local_mad = ib_local_mad;\r
891         p_ifc->cm_listen = ib_cm_listen;\r
892         p_ifc->cm_cancel = ib_cm_cancel;\r
893         p_ifc->cm_req = ib_cm_req;\r
894         p_ifc->cm_rep = ib_cm_rep;\r
895         p_ifc->cm_rtu = ib_cm_rtu;\r
896         p_ifc->cm_rej = ib_cm_rej;\r
897         p_ifc->cm_mra = ib_cm_mra;\r
898         p_ifc->cm_lap = ib_cm_lap;\r
899         p_ifc->cm_apr = ib_cm_apr;\r
900         p_ifc->force_apm = ib_force_apm;\r
901         p_ifc->cm_dreq = ib_cm_dreq;\r
902         p_ifc->cm_drep = ib_cm_drep;\r
903         p_ifc->cm_handoff = ib_cm_handoff;\r
904         p_ifc->create_ioc = ib_create_ioc;\r
905         p_ifc->destroy_ioc = ib_destroy_ioc;\r
906         p_ifc->reg_ioc = ib_reg_ioc;\r
907         p_ifc->add_svc_entry = ib_add_svc_entry;\r
908         p_ifc->remove_svc_entry = ib_remove_svc_entry;\r
909         p_ifc->get_ca_guids = ib_get_ca_guids;\r
910         p_ifc->get_ca_by_gid = ib_get_ca_by_gid;\r
911         p_ifc->get_port_by_gid = ib_get_port_by_gid;\r
912         p_ifc->create_mad_pool = ib_create_mad_pool;\r
913         p_ifc->destroy_mad_pool = ib_destroy_mad_pool;\r
914         p_ifc->reg_mad_pool = ib_reg_mad_pool;\r
915         p_ifc->dereg_mad_pool = ib_dereg_mad_pool;\r
916         p_ifc->get_mad = ib_get_mad;\r
917         p_ifc->put_mad = ib_put_mad;\r
918         p_ifc->init_dgrm_svc = ib_init_dgrm_svc;\r
919         p_ifc->reg_mad_svc = ib_reg_mad_svc;\r
920         p_ifc->reg_svc = ib_reg_svc;\r
921         p_ifc->dereg_svc = ib_dereg_svc;\r
922         p_ifc->query = ib_query;\r
923         p_ifc->cancel_query = ib_cancel_query;\r
924         p_ifc->reg_pnp = ib_reg_pnp;\r
925         p_ifc->dereg_pnp = ib_dereg_pnp;\r
926         p_ifc->subscribe = ib_subscribe;\r
927         p_ifc->unsubscribe = ib_unsubscribe;\r
928         p_ifc->reject_ioc = ib_reject_ioc;\r
929         p_ifc->ci_call = ib_ci_call;\r
930         p_ifc->open_al = ib_open_al;\r
931         p_ifc->close_al = ib_close_al;\r
932         p_ifc->get_err_str = ib_get_err_str;\r
933         p_ifc->get_wc_status_str = ib_get_wc_status_str;\r
934         p_ifc->create_mlnx_fmr = mlnx_create_fmr;\r
935         p_ifc->map_phys_mlnx_fmr = mlnx_map_phys_fmr;\r
936         p_ifc->unmap_mlnx_fmr = mlnx_unmap_fmr;\r
937         p_ifc->destroy_mlnx_fmr = mlnx_destroy_fmr;\r
938         p_ifc->create_mlnx_fmr_pool = mlnx_create_fmr_pool;\r
939         p_ifc->destroy_mlnx_fmr_pool = mlnx_destroy_fmr_pool;\r
940         p_ifc->map_phys_mlnx_fmr_pool = mlnx_map_phys_fmr_pool;\r
941         p_ifc->unmap_mlnx_fmr_pool = mlnx_unmap_fmr_pool;\r
942         p_ifc->flush_mlnx_fmr_pool = mlnx_flush_fmr_pool;\r
943         p_ifc->create_srq = ib_create_srq;\r
944         p_ifc->modify_srq = ib_modify_srq;\r
945         p_ifc->query_srq = ib_query_srq;\r
946         p_ifc->destroy_srq = ib_destroy_srq;\r
947         p_ifc->post_srq_recv = ib_post_srq_recv;\r
948 \r
949         BUS_EXIT( BUS_DBG_PNP );\r
950 }\r
951 \r
952 \r
953 static NTSTATUS\r
954 __get_relations(\r
955         IN              const   net64_t                                         ca_guid,\r
956         IN                              IRP* const                                      p_irp )\r
957 {\r
958         UNUSED_PARAM( ca_guid );\r
959         UNUSED_PARAM( p_irp );\r
960 \r
961         BUS_ENTER( BUS_DBG_PNP );\r
962 \r
963         /*\r
964          * Now that ibbus is in the same device stack as the HCA driver, skip\r
965          * returning relations here as ibbus has already done the deed.\r
966          * This interface remains to minimize changes to HCA drivers for now.\r
967          */\r
968 \r
969         BUS_EXIT( BUS_DBG_PNP );\r
970         return STATUS_SUCCESS;\r
971 }\r
972 \r
973 \r
974 static NTSTATUS\r
975 __query_ci_ifc(\r
976         IN                                      DEVICE_OBJECT* const            p_dev_obj,\r
977         IN                                      IO_STACK_LOCATION* const        p_io_stack )\r
978 {\r
979         ib_ci_ifc_t             *p_ifc;\r
980 \r
981         BUS_ENTER( BUS_DBG_PNP );\r
982 \r
983         if( p_io_stack->Parameters.QueryInterface.Version != \r
984                 IB_CI_INTERFACE_VERSION )\r
985         {\r
986                 BUS_TRACE_EXIT( BUS_DBG_PNP, ("Incorrect interface version (%d)\n",\r
987                         p_io_stack->Parameters.QueryInterface.Version ) );\r
988                 return STATUS_NOT_SUPPORTED;\r
989         }\r
990 \r
991         if( p_io_stack->Parameters.QueryInterface.Size < sizeof(ib_ci_ifc_t) )\r
992         {\r
993                 BUS_TRACE_EXIT( BUS_DBG_PNP, \r
994                         ("Buffer too small (%d given, %d required).\n",\r
995                         p_io_stack->Parameters.QueryInterface.Size, sizeof(ib_ci_ifc_t)) );\r
996                 return STATUS_BUFFER_TOO_SMALL;\r
997         }\r
998 \r
999         /* Copy the interface. */\r
1000         p_ifc = (ib_ci_ifc_t*)p_io_stack->Parameters.QueryInterface.Interface;\r
1001 \r
1002         p_ifc->wdm.Size = sizeof(ib_ci_ifc_t);\r
1003         p_ifc->wdm.Version = IB_CI_INTERFACE_VERSION;\r
1004         p_ifc->wdm.Context = p_dev_obj;\r
1005         p_ifc->wdm.InterfaceReference = al_ref_ci_ifc;\r
1006         p_ifc->wdm.InterfaceDereference = al_deref_ci_ifc;\r
1007 \r
1008         /* Set the entry points. */\r
1009         p_ifc->register_ca = ib_register_ca;\r
1010         p_ifc->deregister_ca = ib_deregister_ca;\r
1011         p_ifc->get_relations = __get_relations;\r
1012         p_ifc->get_err_str = ib_get_err_str;\r
1013 \r
1014         /* take the reference before returning. */\r
1015         al_ref_ci_ifc( p_dev_obj );\r
1016         BUS_EXIT( BUS_DBG_PNP );\r
1017         return STATUS_SUCCESS;\r
1018 }\r
1019 \r
1020 \r
1021 static NTSTATUS\r
1022 __query_cm_ifc(\r
1023         IN                                      DEVICE_OBJECT* const            p_dev_obj,\r
1024         IN                                      IO_STACK_LOCATION* const        p_io_stack )\r
1025 {\r
1026         INFINIBAND_INTERFACE_CM *p_ifc;\r
1027 \r
1028         BUS_ENTER( BUS_DBG_PNP );\r
1029 \r
1030         if( p_io_stack->Parameters.QueryInterface.Version != IbaCmVersion(1, 0) )\r
1031         {\r
1032                 BUS_TRACE_EXIT( BUS_DBG_PNP, ("Incorrect interface version (%d)\n",\r
1033                         p_io_stack->Parameters.QueryInterface.Version ) );\r
1034                 return STATUS_NOT_SUPPORTED;\r
1035         }\r
1036 \r
1037         if( p_io_stack->Parameters.QueryInterface.Size < sizeof(INFINIBAND_INTERFACE_CM) )\r
1038         {\r
1039                 BUS_TRACE_EXIT( BUS_DBG_PNP, \r
1040                         ("Buffer too small (%d given, %d required).\n",\r
1041                         p_io_stack->Parameters.QueryInterface.Size, sizeof(INFINIBAND_INTERFACE_CM)) );\r
1042                 return STATUS_BUFFER_TOO_SMALL;\r
1043         }\r
1044 \r
1045         /* Copy the interface. */\r
1046         p_ifc = (INFINIBAND_INTERFACE_CM*)p_io_stack->Parameters.QueryInterface.Interface;\r
1047 \r
1048         p_ifc->InterfaceHeader.Size = sizeof(INFINIBAND_INTERFACE_CM);\r
1049         p_ifc->InterfaceHeader.Version = IbaCmVersion(1, 0);\r
1050         p_ifc->InterfaceHeader.Context = p_dev_obj;\r
1051         p_ifc->InterfaceHeader.InterfaceReference = al_ref_ifc;\r
1052         p_ifc->InterfaceHeader.InterfaceDereference = al_deref_ifc;\r
1053         cm_get_interface(&p_ifc->CM);\r
1054 \r
1055         /* take the reference before returning. */\r
1056         al_ref_ifc( p_dev_obj );\r
1057         BUS_EXIT( BUS_DBG_PNP );\r
1058         return STATUS_SUCCESS;\r
1059 }\r
1060 \r
1061 \r
1062 static NTSTATUS\r
1063 fdo_query_interface(\r
1064         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1065         IN                                      IRP* const                              p_irp, \r
1066                 OUT                             cl_irp_action_t* const  p_action )\r
1067 {\r
1068         NTSTATUS                        status;\r
1069         IO_STACK_LOCATION       *p_io_stack;\r
1070 \r
1071         BUS_ENTER( BUS_DBG_PNP );\r
1072 \r
1073         PAGED_CODE();\r
1074 \r
1075         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
1076         \r
1077         /* Compare requested GUID with our supported interface GUIDs. */\r
1078         if( IsEqualGUID( p_io_stack->Parameters.QueryInterface.InterfaceType,\r
1079                 &GUID_IB_AL_INTERFACE ) )\r
1080         {\r
1081                 status = __query_al_ifc( p_dev_obj, p_io_stack );\r
1082         }\r
1083         else if( IsEqualGUID( p_io_stack->Parameters.QueryInterface.InterfaceType,\r
1084                 &GUID_IB_CI_INTERFACE ) )\r
1085         {\r
1086                 status = __query_ci_ifc( p_dev_obj, p_io_stack );\r
1087         }\r
1088         else if( IsEqualGUID( p_io_stack->Parameters.QueryInterface.InterfaceType,\r
1089                 &GUID_INFINIBAND_INTERFACE_CM ) )\r
1090         {\r
1091                 status = __query_cm_ifc( p_dev_obj, p_io_stack );\r
1092         }\r
1093         else\r
1094         {\r
1095                 status = p_irp->IoStatus.Status;\r
1096         }\r
1097 \r
1098         if( NT_SUCCESS( status ) )\r
1099                 *p_action = IrpSkip;\r
1100         else if( status == STATUS_BUFFER_TOO_SMALL )\r
1101                 *p_action = IrpComplete;\r
1102         else\r
1103                 *p_action = IrpIgnore;\r
1104 \r
1105         BUS_EXIT( BUS_DBG_PNP );\r
1106         return status;\r
1107 }\r
1108 \r
1109 \r
1110 static NTSTATUS\r
1111 __fdo_query_power(\r
1112         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1113         IN                              IRP* const                                      p_irp,\r
1114                 OUT                     cl_irp_action_t* const          p_action )\r
1115 {\r
1116         NTSTATUS                        status = STATUS_SUCCESS;\r
1117         IO_STACK_LOCATION       *p_io_stack;\r
1118 \r
1119         BUS_ENTER( BUS_DBG_POWER );\r
1120 \r
1121         UNUSED_PARAM( p_dev_obj );\r
1122 \r
1123         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
1124 \r
1125         switch( p_io_stack->Parameters.Power.Type )\r
1126         {\r
1127         case SystemPowerState:\r
1128                 /* Fail any requests to hibernate or sleep the system. */\r
1129                 switch( p_io_stack->Parameters.Power.State.SystemState )\r
1130                 {\r
1131                         case PowerSystemHibernate:\r
1132                         case PowerSystemSleeping1:      // STANDBY support\r
1133                         case PowerSystemWorking:\r
1134                         case PowerSystemShutdown:\r
1135                                 break;\r
1136 \r
1137                         default:\r
1138                                 status = STATUS_NOT_SUPPORTED;\r
1139                 }\r
1140                 break;\r
1141 \r
1142         case DevicePowerState:\r
1143                 /* Fail any query for low power states. */\r
1144                 switch( p_io_stack->Parameters.Power.State.DeviceState )\r
1145                 {\r
1146                 case PowerDeviceD0:\r
1147                 case PowerDeviceD3:\r
1148                         /* We only support fully powered or off power states. */\r
1149                         break;\r
1150 \r
1151                 default:\r
1152                         status = STATUS_NOT_SUPPORTED;\r
1153                 }\r
1154                 break;\r
1155         }\r
1156 \r
1157         if( status == STATUS_NOT_SUPPORTED )\r
1158                 *p_action = IrpComplete;\r
1159         else\r
1160                 *p_action = IrpSkip;\r
1161 \r
1162         BUS_EXIT( BUS_DBG_POWER );\r
1163         return status;\r
1164 }\r
1165 \r
1166 \r
1167 static void\r
1168 __request_power_completion(\r
1169         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
1170         IN                              UCHAR                                           minor_function,\r
1171         IN                              POWER_STATE                                     power_state,\r
1172         IN                              void                                            *context,\r
1173         IN                              IO_STATUS_BLOCK                         *p_io_status )\r
1174 {\r
1175         IRP                                     *p_irp;\r
1176         cl_pnp_po_ext_t         *p_ext;\r
1177 \r
1178         BUS_ENTER( BUS_DBG_PNP );\r
1179 \r
1180         UNUSED_PARAM( minor_function );\r
1181         UNUSED_PARAM( power_state );\r
1182 \r
1183         p_irp = (IRP*)context;\r
1184         p_ext = p_dev_obj->DeviceExtension;\r
1185 \r
1186         /* Propagate the device IRP status to the system IRP status. */\r
1187         p_irp->IoStatus.Status = p_io_status->Status;\r
1188 \r
1189         /* Continue Power IRP processing. */\r
1190         PoStartNextPowerIrp( p_irp );\r
1191         IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
1192         IoReleaseRemoveLock( &p_ext->remove_lock, p_irp );\r
1193         BUS_EXIT( BUS_DBG_PNP );\r
1194 }\r
1195 \r
1196 \r
1197 /*NOTE: Completion routines must NEVER be pageable. */\r
1198 static NTSTATUS\r
1199 __set_power_completion(\r
1200         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
1201         IN                              IRP                                                     *p_irp,\r
1202         IN                              void                                            *context )\r
1203 {\r
1204         NTSTATUS                        status;\r
1205         POWER_STATE                     state;\r
1206         bus_fdo_ext_t           *p_ext;\r
1207         IO_STACK_LOCATION       *p_io_stack;\r
1208 \r
1209         BUS_ENTER( BUS_DBG_PNP );\r
1210 \r
1211         UNUSED_PARAM( context );\r
1212 \r
1213         p_ext = p_dev_obj->DeviceExtension;\r
1214         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
1215 \r
1216         if( !NT_SUCCESS( p_irp->IoStatus.Status ) )\r
1217         {\r
1218                 PoStartNextPowerIrp( p_irp );\r
1219                 IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
1220                 BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
1221                         ("IRP_MN_SET_POWER for system failed by lower driver with %08x.\n",\r
1222                         p_irp->IoStatus.Status) );\r
1223                 return STATUS_SUCCESS;\r
1224         }\r
1225 \r
1226         state.DeviceState = \r
1227                 p_ext->po_state[p_io_stack->Parameters.Power.State.SystemState];\r
1228 \r
1229         /*\r
1230          * Send a device power IRP to our devnode.  Using our device object will\r
1231          * only work on win2k and other NT based systems.\r
1232          */\r
1233         status = PoRequestPowerIrp( p_dev_obj, IRP_MN_SET_POWER, state,\r
1234                 __request_power_completion, p_irp, NULL );\r
1235 \r
1236         if( status != STATUS_PENDING )\r
1237         {\r
1238                 PoStartNextPowerIrp( p_irp );\r
1239                 /* Propagate the failure. */\r
1240                 p_irp->IoStatus.Status = status;\r
1241                 IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
1242                 IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
1243                 BUS_TRACE( BUS_DBG_ERROR,\r
1244                         ("PoRequestPowerIrp returned %08x.\n", status) );\r
1245         }\r
1246 \r
1247         BUS_EXIT( BUS_DBG_PNP );\r
1248         return STATUS_MORE_PROCESSING_REQUIRED;\r
1249 }\r
1250 \r
1251 \r
1252 static NTSTATUS\r
1253 __fdo_set_power(\r
1254         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1255         IN                              IRP* const                                      p_irp,\r
1256                 OUT                     cl_irp_action_t* const          p_action )\r
1257 {\r
1258         NTSTATUS                        status;\r
1259         IO_STACK_LOCATION       *p_io_stack;\r
1260         bus_fdo_ext_t           *p_ext;\r
1261 \r
1262         BUS_ENTER( BUS_DBG_POWER );\r
1263 \r
1264         p_ext = p_dev_obj->DeviceExtension;\r
1265         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
1266 \r
1267         BUS_TRACE( BUS_DBG_POWER, \r
1268                 ("SET_POWER for FDO %p (ext %p): type %s, state %d, action %d \n",\r
1269                 p_dev_obj, p_ext,\r
1270                 (p_io_stack->Parameters.Power.Type)\r
1271                         ? "DevicePowerState" : "SystemPowerState",\r
1272                 p_io_stack->Parameters.Power.State.DeviceState, \r
1273                 p_io_stack->Parameters.Power.ShutdownType ));\r
1274 \r
1275         switch( p_io_stack->Parameters.Power.Type )\r
1276         {\r
1277         case SystemPowerState:\r
1278 #if 0\r
1279                 /*\r
1280                  * Process on the way up the stack.  We cannot block since the \r
1281                  * power dispatch function can be called at elevated IRQL if the\r
1282                  * device is in a paging/hibernation/crash dump path.\r
1283                  */\r
1284                 IoMarkIrpPending( p_irp );\r
1285                 IoCopyCurrentIrpStackLocationToNext( p_irp );\r
1286 #pragma warning( push, 3 )\r
1287                 IoSetCompletionRoutine( p_irp, __set_power_completion, NULL, \r
1288                         TRUE, TRUE, TRUE );\r
1289 #pragma warning( pop )\r
1290                 PoCallDriver( p_ext->cl_ext.p_next_do, p_irp );\r
1291 \r
1292                 *p_action = IrpDoNothing;\r
1293                 status = STATUS_PENDING;\r
1294                 break;\r
1295 #endif\r
1296         case DevicePowerState:\r
1297         default:\r
1298                 /* Pass down and let the PDO driver handle it. */\r
1299                 *p_action = IrpIgnore;\r
1300                 status = STATUS_SUCCESS;\r
1301                 break;\r
1302         }\r
1303 \r
1304         BUS_EXIT( BUS_DBG_POWER );\r
1305         return status;\r
1306 }\r
1307 \r
1308 \r
1309 /*\r
1310  * A CA GUID of zero means that all devices should be reported.\r
1311  */\r
1312 NTSTATUS\r
1313 bus_get_relations(\r
1314         IN                              cl_qlist_t*     const                   p_pdo_list,\r
1315         IN              const   net64_t                                         ca_guid,\r
1316         IN                              IRP* const                                      p_irp )\r
1317 {\r
1318         NTSTATUS                        status;\r
1319         DEVICE_RELATIONS        *p_rel;\r
1320         cl_list_item_t          *p_list_item;\r
1321         bus_pdo_ext_t           *p_pdo_ext;\r
1322         size_t                          n_devs = 0;\r
1323 \r
1324         BUS_ENTER( BUS_DBG_PNP );\r
1325 \r
1326         /* Count the number of child devices. */\r
1327         for( p_list_item = cl_qlist_head( p_pdo_list );\r
1328                 p_list_item != cl_qlist_end( p_pdo_list );\r
1329                 p_list_item = cl_qlist_next( p_list_item ) )\r
1330         {\r
1331                 p_pdo_ext = PARENT_STRUCT( p_list_item, bus_pdo_ext_t, list_item );\r
1332 \r
1333                 if( !p_pdo_ext->b_present )\r
1334                 {\r
1335                         // mark it missing to be removed in port_remove\r
1336                         p_pdo_ext->b_reported_missing = TRUE;\r
1337                         /*\r
1338                          * We don't report a PDO that is no longer present.  This is how\r
1339                          * the PDO will get cleaned up.\r
1340                          */\r
1341                         BUS_TRACE( BUS_DBG_PNP, ("Don't report PDO! %s: PDO %p, ext %p, "\r
1342                                 "present %d, missing %d .\n",\r
1343                                 p_pdo_ext->cl_ext.vfptr_pnp_po->identity,\r
1344                                 p_pdo_ext->cl_ext.p_self_do, p_pdo_ext, p_pdo_ext->b_present,\r
1345                                 p_pdo_ext->b_reported_missing ) );\r
1346                         continue;\r
1347                 }\r
1348                 \r
1349                 if( ca_guid && p_pdo_ext->ca_guid != ca_guid )\r
1350                         continue;\r
1351 \r
1352                 n_devs++;\r
1353         }\r
1354 \r
1355         if( !n_devs )\r
1356         {\r
1357                 BUS_TRACE_EXIT( BUS_DBG_PNP, ("Found 0 PDOs ca_guid %I64x\n", ca_guid));\r
1358                 return STATUS_NO_SUCH_DEVICE;\r
1359         }\r
1360 \r
1361         BUS_TRACE( BUS_DBG_PNP, ("Found %d PDOs ca_guid %I64x\n", n_devs, ca_guid));\r
1362 \r
1363         /* Add space for our child IOUs. */\r
1364         status = cl_alloc_relations( p_irp, n_devs );\r
1365         if( !NT_SUCCESS( status ) )\r
1366         {\r
1367                 BUS_TRACE_EXIT( BUS_DBG_ERROR,\r
1368                         ("cl_alloc_relations returned %08x.\n", status) );\r
1369                 return status;\r
1370         }\r
1371 \r
1372         p_rel = (DEVICE_RELATIONS*)p_irp->IoStatus.Information;\r
1373 \r
1374         for( p_list_item = cl_qlist_head( p_pdo_list );\r
1375                 p_list_item != cl_qlist_end( p_pdo_list );\r
1376                 p_list_item = cl_qlist_next( p_list_item ) )\r
1377         {\r
1378                 p_pdo_ext = PARENT_STRUCT( p_list_item, bus_pdo_ext_t, list_item );\r
1379 \r
1380                 if( !p_pdo_ext->b_present )\r
1381                         continue;\r
1382 \r
1383                 if( ca_guid && p_pdo_ext->ca_guid != ca_guid )\r
1384                         continue;\r
1385 \r
1386                 BUS_TRACE( BUS_DBG_PNP, ("Reported PDO %p(=%p), ext %p\n", \r
1387                         p_pdo_ext->cl_ext.p_self_do, p_pdo_ext->cl_ext.p_pdo, p_pdo_ext ));\r
1388                 \r
1389                 p_rel->Objects[p_rel->Count] = p_pdo_ext->cl_ext.p_pdo;\r
1390                 ObReferenceObject( p_rel->Objects[p_rel->Count++] );\r
1391         }\r
1392 \r
1393         BUS_EXIT( BUS_DBG_PNP );\r
1394         return STATUS_SUCCESS;\r
1395 }\r
1396 \r
1397 \r
1398 /*\r
1399  * find a bus filter instance (p_bfi) given an *cl_obj: port_mgr or iou_mgr. \r
1400  */\r
1401 \r
1402 bus_filter_t *\r
1403 get_bfi_by_obj(IN int obj_type, IN cl_obj_t *p_obj )\r
1404 {\r
1405         bus_filter_t    *p_bfi;\r
1406         bus_filter_t    *matched=NULL;\r
1407 \r
1408         CL_ASSERT((obj_type == BFI_PORT_MGR_OBJ) || (obj_type == BFI_IOU_MGR_OBJ));\r
1409 \r
1410         lock_control_event();\r
1411 \r
1412         for(p_bfi=g_bus_filters; p_bfi < &g_bus_filters[MAX_BUS_FILTERS]; p_bfi++) {\r
1413 \r
1414                 if ( !p_bfi->p_bus_ext )\r
1415                         continue;\r
1416 \r
1417                 if ( obj_type == BFI_PORT_MGR_OBJ ) {\r
1418                         if ( p_obj == p_bfi->p_port_mgr_obj ) {\r
1419                                 matched = p_bfi;\r
1420                                 break;\r
1421                         }\r
1422                 }\r
1423                 else {\r
1424                         if ( p_obj == p_bfi->p_iou_mgr_obj ) {\r
1425                                 matched = p_bfi;\r
1426                                 break;\r
1427                         }\r
1428                 }\r
1429         }\r
1430         unlock_control_event();\r
1431 \r
1432         BUS_PRINT( BUS_DBG_PNP,\r
1433                                 ("%s() cl_obj %p type %s_MGR_OBJ --> bfi[%d] %p\n",\r
1434                                 __FUNCTION__,p_obj,\r
1435                                 (obj_type == BFI_PORT_MGR_OBJ ? "PORT": "IOU"),\r
1436                                 (matched ? (matched - g_bus_filters) : (-1)), matched ) );\r
1437 \r
1438         return matched;\r
1439 }\r
1440 \r
1441 /*\r
1442  * find a bus filter instance given an HCA guid.\r
1443  * BFIs are bound to GUIDs in fdo_start().\r
1444  */\r
1445 \r
1446 bus_filter_t *\r
1447 get_bfi_by_ca_guid( IN net64_t ca_guid )\r
1448 {\r
1449         bus_filter_t    *p_bfi;\r
1450         bus_filter_t    *matched=NULL;\r
1451 \r
1452         if ( ca_guid == 0ULL )\r
1453         {\r
1454                 matched = g_bus_filters;\r
1455                 BUS_PRINT( BUS_DBG_PNP, ("%s() ERR guid %I64x -> bfi[0] %p\n",\r
1456                                                                 __FUNCTION__, ca_guid, matched) );\r
1457                 CL_ASSERT( ca_guid );\r
1458                 return matched;\r
1459         }\r
1460 \r
1461         lock_control_event();\r
1462 \r
1463         for(p_bfi=g_bus_filters; p_bfi < &g_bus_filters[MAX_BUS_FILTERS]; p_bfi++)\r
1464         {\r
1465                 if ( !p_bfi->p_bus_ext )\r
1466                         continue;\r
1467 \r
1468                 if ( ca_guid == p_bfi->ca_guid )\r
1469                 {\r
1470                         matched = p_bfi;\r
1471                         break;\r
1472                 }\r
1473         }\r
1474         unlock_control_event();\r
1475 \r
1476 #if DBG\r
1477         if ( !matched )\r
1478         {\r
1479                 BUS_PRINT( BUS_DBG_PNP, ("No Match ca_guid 0x%I64x -> bfi[%d] %p\n",\r
1480                                                                         ca_guid, -1, matched ) );\r
1481         }\r
1482 #endif\r
1483         return matched;\r
1484 }\r
1485 \r
1486 \r
1487 bus_filter_t *\r
1488 alloc_bfi( IN DRIVER_OBJECT  *p_driver_obj, OUT int *p_instance_count )\r
1489 {\r
1490         bus_filter_t    *p_bfi;\r
1491         bus_filter_t    *matched=NULL;\r
1492 \r
1493     /* Using unsafe function so that the IRQL remains at PASSIVE_LEVEL.\r
1494      * IoCreateDeviceSecure & IoCreateSymbolicLink must be called at\r
1495      * PASSIVE_LEVEL.\r
1496          */\r
1497         lock_control_event();\r
1498 \r
1499         // find 1st unused bfi slot.\r
1500         for(p_bfi=g_bus_filters; p_bfi < &g_bus_filters[MAX_BUS_FILTERS]; p_bfi++)\r
1501         {\r
1502                 if ( !p_bfi->p_bus_ext )\r
1503                 {\r
1504                         /* temp setting until 'real' p_bus_ext is alloc; see bus_add_device.\r
1505                          * If p_bus_ext is ! 0, then bfi slot is allocated, although it\r
1506                          * may not yet have a bound CA guid; set set_get_\r
1507                          */\r
1508                         p_bfi->p_bus_ext = (bus_fdo_ext_t*)p_driver_obj;\r
1509                         matched = p_bfi;\r
1510                         *p_instance_count = ++g_bfi_InstanceCount; // record in-use\r
1511                         break;\r
1512                 }\r
1513         }\r
1514         unlock_control_event();\r
1515 \r
1516 #if DBG\r
1517         RtlStringCbPrintfA ( p_bfi->whoami,\r
1518                                                  sizeof(p_bfi->whoami),\r
1519                                                  "bfi-%d",\r
1520                                                  (g_bfi_InstanceCount - 1) );\r
1521 \r
1522         p_bfi->magic = BFI_MAGIC;\r
1523 #endif\r
1524 \r
1525         BUS_PRINT( BUS_DBG_PNP, ("%s() %s %p\n",\r
1526                                 __FUNCTION__, (matched ? matched->whoami:"Nobody"), matched) );\r
1527 \r
1528         return matched;\r
1529 }\r
1530 \r
1531 \r
1532 int\r
1533 free_bfi( IN  bus_filter_t  *p_bfi )\r
1534 {\r
1535         int     remaining;\r
1536 \r
1537         lock_control_event();\r
1538         p_bfi->p_bus_ext = NULL;\r
1539         p_bfi->ca_guid = 0ULL;\r
1540         remaining = --g_bfi_InstanceCount; // one less bfi in-use\r
1541         unlock_control_event();\r
1542         \r
1543         return remaining;\r
1544 }\r
1545 \r
1546 int\r
1547 get_bfi_count( void )\r
1548 {\r
1549         int     ic;\r
1550 \r
1551         lock_control_event();\r
1552         ic = g_bfi_InstanceCount;\r
1553         unlock_control_event();\r
1554         \r
1555         return ic;\r
1556 }\r
1557 \r
1558 #if DBG\r
1559 char *get_obj_state_str(cl_state_t state)\r
1560 {\r
1561         switch( state ) {\r
1562           case CL_UNINITIALIZED:\r
1563                 return "UNINITIALIZED";\r
1564           case CL_INITIALIZED:\r
1565                 return "INITIALIZED";\r
1566           case CL_DESTROYING:\r
1567                 return "DESTROYING";\r
1568           case CL_DESTROYED:\r
1569                 return "DESTROYED";\r
1570           default:\r
1571                 break;\r
1572         }\r
1573         return "Err - Bad obj state";\r
1574 }\r
1575 #endif\r
1576 \r