2 * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.
\r
3 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
\r
5 * This software is available to you under the OpenIB.org BSD license
\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
12 * - Redistributions of source code must retain the above
\r
13 * copyright notice, this list of conditions and the following
\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
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
30 * $Id: al.c 1611 2006-08-20 14:48:55Z sleybo $
\r
33 #include "precomp.h"
\r
34 #include <initguid.h>
\r
35 #include <wdmguid.h>
\r
37 #if defined(EVENT_TRACING)
\r
44 #define DRV_VERSION "1.0"
\r
45 #define DRV_RELDATE "02/01/2008"
\r
50 * UVP name does not include file extension. For debug builds, UAL
\r
51 * will append "d.dll". For release builds, UAL will append ".dll"
\r
53 char mlnx_uvp_lib_name[MAX_LIB_NAME] = {"mlx4u"};
\r
58 IN PINTERFACE p_ifc )
\r
60 HCA_ENTER( HCA_DBG_PNP );
\r
61 p_ifc->InterfaceDereference( p_ifc->Context );
\r
62 HCA_EXIT( HCA_DBG_PNP );
\r
65 static int __get_dev_info(PFDO_DEVICE_DATA p_fdo, __be64 *node_guid, u32 *hw_id)
\r
67 struct ib_device_attr device_attr;
\r
68 struct ib_device *p_ibdev = p_fdo->bus_ib_ifc.p_ibdev;
\r
71 HCA_ENTER( HCA_DBG_PNP );
\r
72 if ( hca_is_livefish(p_fdo) ) {
\r
73 *node_guid = cl_hton64((uint64_t)(ULONG_PTR)p_ibdev);
\r
74 p_ibdev->node_guid = *node_guid;
\r
79 err = (p_ibdev->query_device)( p_ibdev, &device_attr );
\r
83 *node_guid = p_ibdev->node_guid;
\r
84 *hw_id = device_attr.hw_ver;
\r
85 HCA_EXIT( HCA_DBG_PNP );
\r
89 #ifndef USE_WDM_FRAMEWORK
\r
92 // TODO: add support for Hibernate/Standby as in WDM version below
\r
96 #pragma alloc_text (INIT, DriverEntry)
\r
97 #pragma alloc_text (PAGE, EvtDeviceAdd)
\r
98 #pragma alloc_text (PAGE, EvtDriverUnload)
\r
99 #pragma alloc_text (PAGE, EvtDeviceD0Entry)
\r
100 #pragma alloc_text (PAGE, EvtDeviceD0Exit)
\r
101 #pragma alloc_text (PAGE, EvtPrepareHardware)
\r
102 #pragma alloc_text (PAGE, EvtReleaseHardware)
\r
106 __get_ci_interface(
\r
107 IN PFDO_DEVICE_DATA p_fdo )
\r
111 IO_STATUS_BLOCK ioStatus;
\r
112 IO_STACK_LOCATION *pIoStack;
\r
115 HCA_ENTER( HCA_DBG_PNP );
\r
117 KeInitializeEvent( &event, NotificationEvent, FALSE );
\r
119 /* Query for the verbs interface. */
\r
120 p_irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, p_fdo->p_al_dev,
\r
121 NULL, 0, NULL, &event, &ioStatus );
\r
124 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
125 ("IoBuildSynchronousFsdRequest failed.\n"));
\r
126 return STATUS_INSUFFICIENT_RESOURCES;
\r
129 /* Format the IRP. */
\r
130 pIoStack = IoGetNextIrpStackLocation( p_irp );
\r
131 pIoStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
\r
132 pIoStack->Parameters.QueryInterface.Version = IB_CI_INTERFACE_VERSION;
\r
133 pIoStack->Parameters.QueryInterface.Size = sizeof(ib_ci_ifc_t);
\r
134 pIoStack->Parameters.QueryInterface.Interface =
\r
135 (INTERFACE*)&p_fdo->ci_ifc;
\r
136 pIoStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
\r
137 pIoStack->Parameters.QueryInterface.InterfaceType =
\r
138 &GUID_IB_CI_INTERFACE;
\r
139 p_irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
\r
141 /* Send the IRP. */
\r
142 status = IoCallDriver( p_fdo->p_al_dev, p_irp );
\r
143 if( status == STATUS_PENDING )
\r
145 KeWaitForSingleObject( &event, Executive, KernelMode,
\r
148 status = ioStatus.Status;
\r
151 if( !NT_SUCCESS( status ) )
\r
153 HCA_PRINT( TRACE_LEVEL_ERROR,HCA_DBG_PNP,
\r
154 ("Query interface for verbs returned %08x.\n", status));
\r
158 HCA_EXIT( HCA_DBG_PNP );
\r
164 __pnp_notify_target(
\r
165 IN void *pNotifyStruct,
\r
168 NTSTATUS status = STATUS_SUCCESS;
\r
169 PFDO_DEVICE_DATA p_fdo = context;
\r
170 PDEVICE_OBJECT p_dev_obj = WdfDeviceWdmGetDeviceObject(p_fdo->FdoDevice);
\r
171 TARGET_DEVICE_REMOVAL_NOTIFICATION *pNotify;
\r
173 HCA_ENTER( HCA_DBG_PNP );
\r
175 pNotify = (TARGET_DEVICE_REMOVAL_NOTIFICATION*)pNotifyStruct;
\r
177 if( IsEqualGUID( &pNotify->Event, &GUID_TARGET_DEVICE_QUERY_REMOVE ) )
\r
179 if ( p_fdo->state == HCA_REGISTERED) {
\r
180 /* Release AL's CI interface. */
\r
181 p_fdo->ci_ifc.wdm.InterfaceDereference( p_fdo->ci_ifc.wdm.Context );
\r
182 p_fdo->state = HCA_IFC_DEREFERENCED;
\r
185 /* Release AL's file object so that it can unload. */
\r
186 CL_ASSERT( p_fdo->p_al_dev );
\r
187 CL_ASSERT( p_fdo->p_al_file_obj );
\r
188 CL_ASSERT( p_fdo->p_al_file_obj == pNotify->FileObject );
\r
189 if( p_fdo->p_al_file_obj ) {
\r
190 ObDereferenceObject( p_fdo->p_al_file_obj );
\r
191 p_fdo->p_al_file_obj = NULL;
\r
192 p_fdo->p_al_dev = NULL;
\r
195 else if( IsEqualGUID( &pNotify->Event,
\r
196 &GUID_TARGET_DEVICE_REMOVE_COMPLETE ) )
\r
198 if (p_fdo->ci_ifc.deregister_ca) {
\r
199 /* Notify AL that the CA is being removed. */
\r
200 p_fdo->ci_ifc.deregister_ca( p_fdo->hca.guid );
\r
201 p_fdo->ci_ifc.deregister_ca = NULL;
\r
204 if ( p_fdo->state == HCA_REGISTERED) {
\r
205 /* Release AL's CI interface. */
\r
206 p_fdo->ci_ifc.wdm.InterfaceDereference( p_fdo->ci_ifc.wdm.Context );
\r
208 p_fdo->state = HCA_STARTED;
\r
210 /* Release AL's file object so that it can unload. */
\r
211 if( p_fdo->p_al_file_obj )
\r
213 ObDereferenceObject( p_fdo->p_al_file_obj );
\r
214 p_fdo->p_al_file_obj = NULL;
\r
215 p_fdo->p_al_dev = NULL;
\r
218 /* Cancel our target device change registration. */
\r
219 if (p_fdo->pnp_target_entry) {
\r
220 IoUnregisterPlugPlayNotification( p_fdo->pnp_target_entry );
\r
221 p_fdo->pnp_target_entry = NULL;
\r
225 else if( IsEqualGUID( &pNotify->Event,
\r
226 &GUID_TARGET_DEVICE_REMOVE_CANCELLED ) )
\r
228 /* Cancel our target device change registration. */
\r
229 if (p_fdo->pnp_target_entry) {
\r
230 IoUnregisterPlugPlayNotification( p_fdo->pnp_target_entry );
\r
231 p_fdo->pnp_target_entry = NULL;
\r
234 /* Get the device object pointer for the AL. */
\r
235 CL_ASSERT( !p_fdo->p_al_file_obj );
\r
236 CL_ASSERT( !p_fdo->p_al_dev );
\r
237 /* Get the AL device object. */
\r
238 HCA_PRINT( TRACE_LEVEL_INFORMATION ,HCA_DBG_SHIM ,("Calling IoGetDeviceObjectPointer.\n"));
\r
239 status = IoGetDeviceObjectPointer( &p_fdo->al_sym_name,
\r
240 FILE_ALL_ACCESS, &p_fdo->p_al_file_obj, &p_fdo->p_al_dev );
\r
241 if( !NT_SUCCESS( status ) )
\r
243 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_SHIM,
\r
244 ("IoGetDeviceObjectPointer returned %08x.\n", status ));
\r
245 return STATUS_SUCCESS;
\r
248 /* Register for removal notification of the IB Fabric root device. */
\r
249 status = IoRegisterPlugPlayNotification(
\r
250 EventCategoryTargetDeviceChange, 0, p_fdo->p_al_file_obj,
\r
251 p_dev_obj->DriverObject, __pnp_notify_target, p_fdo,
\r
252 &p_fdo->pnp_target_entry );
\r
253 if( !NT_SUCCESS( status ) )
\r
255 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
256 ("IoRegisterPlugPlayNotification returned %08x.\n", status));
\r
260 CL_ASSERT( p_fdo->state == HCA_IFC_DEREFERENCED );
\r
261 if ( p_fdo->state == HCA_IFC_DEREFERENCED) {
\r
262 /* Release AL's CI interface. */
\r
263 p_fdo->ci_ifc.wdm.InterfaceReference( p_fdo->ci_ifc.wdm.Context );
\r
264 p_fdo->state = HCA_REGISTERED;
\r
268 HCA_EXIT( HCA_DBG_PNP );
\r
273 static ci_interface_t*
\r
275 IN PFDO_DEVICE_DATA const p_fdo )
\r
277 ci_interface_t *pIfc;
\r
279 HCA_ENTER( HCA_DBG_PNP );
\r
282 (ci_interface_t*)ExAllocatePoolWithTag( PagedPool, sizeof(ci_interface_t), MT_TAG_KERNEL );
\r
285 HCA_PRINT( TRACE_LEVEL_ERROR,HCA_DBG_PNP,
\r
286 ("Failed to allocate ci_interface_t (%d bytes).\n",
\r
287 sizeof(ci_interface_t)));
\r
291 setup_ci_interface( p_fdo->hca.guid, !!hca_is_livefish(p_fdo), pIfc );
\r
293 pIfc->p_hca_dev = WdfDeviceWdmGetPhysicalDevice(p_fdo->FdoDevice);
\r
294 pIfc->vend_id = (uint32_t)p_fdo->bus_ib_ifc.pdev->ven_id;
\r
295 pIfc->dev_id = (uint16_t)p_fdo->bus_ib_ifc.pdev->dev_id;
\r
296 pIfc->dev_revision = (uint16_t)p_fdo->hca.hw_ver;
\r
298 HCA_EXIT( HCA_DBG_PNP );
\r
304 IN PFDO_DEVICE_DATA p_fdo )
\r
306 HCA_ENTER( HCA_DBG_PNP );
\r
308 if ( p_fdo->state == HCA_REGISTERED) {
\r
309 if (p_fdo->ci_ifc.deregister_ca) {
\r
310 /* Notify AL that the CA is being removed. */
\r
311 p_fdo->ci_ifc.deregister_ca( p_fdo->hca.guid );
\r
312 p_fdo->ci_ifc.deregister_ca = NULL;
\r
313 /* Release AL's CI interface. */
\r
314 p_fdo->ci_ifc.wdm.InterfaceDereference( p_fdo->ci_ifc.wdm.Context );
\r
315 p_fdo->state = HCA_STARTED;
\r
316 HCA_PRINT( TRACE_LEVEL_INFORMATION ,HCA_DBG_PNP,
\r
317 ("***** HCA deregistered \n"));
\r
321 HCA_EXIT( HCA_DBG_PNP );
\r
326 IN PFDO_DEVICE_DATA p_fdo )
\r
329 ib_api_status_t ib_status;
\r
330 ci_interface_t *p_hca_ifc;
\r
332 HCA_ENTER( HCA_DBG_PNP );
\r
334 ASSERT( p_fdo->state == HCA_STARTED );
\r
335 ASSERT( p_fdo->p_al_dev );
\r
337 /* Get the AL's lower interface. */
\r
338 status = __get_ci_interface( p_fdo );
\r
339 if( !NT_SUCCESS( status ) )
\r
341 HCA_PRINT( TRACE_LEVEL_ERROR,HCA_DBG_PNP,
\r
342 ("__get_ci_interface returned %08x.\n", status));
\r
346 /* Allocate and populate our HCA interface structure. */
\r
347 p_hca_ifc = __alloc_hca_ifc( p_fdo );
\r
350 HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_PNP ,("__alloc_hca_ifc failed.\n"));
\r
351 status = STATUS_NO_MEMORY;
\r
355 /* Notify AL that we're available... */
\r
356 ib_status = p_fdo->ci_ifc.register_ca( p_hca_ifc );
\r
357 ExFreePool( p_hca_ifc );
\r
358 if( ib_status != IB_SUCCESS )
\r
360 p_fdo->ci_ifc.wdm.InterfaceDereference( p_fdo->ci_ifc.wdm.Context );
\r
361 status = STATUS_INSUFFICIENT_RESOURCES;
\r
365 p_fdo->state = HCA_REGISTERED;
\r
366 HCA_PRINT( TRACE_LEVEL_INFORMATION ,HCA_DBG_PNP,
\r
367 ("***** HCA registered \n"));
\r
369 HCA_EXIT( HCA_DBG_PNP );
\r
375 IN void *pNotifyStruct,
\r
378 NTSTATUS status = STATUS_SUCCESS;
\r
379 DEVICE_INTERFACE_CHANGE_NOTIFICATION *pNotify;
\r
380 PFDO_DEVICE_DATA p_fdo = context;
\r
381 PDEVICE_OBJECT p_dev_obj = WdfDeviceWdmGetDeviceObject(p_fdo->FdoDevice);
\r
383 HCA_ENTER( HCA_DBG_PNP );
\r
385 pNotify = (DEVICE_INTERFACE_CHANGE_NOTIFICATION*)pNotifyStruct;
\r
387 if( !IsEqualGUID( &pNotify->Event, &GUID_DEVICE_INTERFACE_ARRIVAL ) )
\r
391 * Sanity check. We should only be getting notifications of the
\r
392 * CI interface exported by AL.
\r
395 IsEqualGUID( &pNotify->InterfaceClassGuid, &GUID_IB_CI_INTERFACE ) );
\r
397 if( p_fdo->state != HCA_STARTED )
\r
399 HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_PNP ,("Invalid state: %d\n", p_fdo->state));
\r
403 /* save symbolic name of IBAL for a case of cancelled IBAL removal */
\r
404 if (!p_fdo->al_sym_name.Buffer) {
\r
405 p_fdo->al_sym_name.Length = pNotify->SymbolicLinkName->Length;
\r
406 p_fdo->al_sym_name.MaximumLength = pNotify->SymbolicLinkName->MaximumLength;
\r
407 p_fdo->al_sym_name.Buffer = ExAllocatePoolWithTag( NonPagedPool,
\r
408 p_fdo->al_sym_name.MaximumLength * sizeof(wchar_t), MT_TAG_KERNEL );
\r
409 if (!p_fdo->al_sym_name.Buffer)
\r
411 HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_PNP ,("allocation of sym IBAL name failed.\n"));
\r
414 RtlCopyUnicodeString( &p_fdo->al_sym_name, pNotify->SymbolicLinkName );
\r
417 ASSERT( !p_fdo->p_al_dev );
\r
418 ASSERT( !p_fdo->p_al_file_obj );
\r
420 /* Get the AL device object. */
\r
421 HCA_PRINT( TRACE_LEVEL_INFORMATION ,HCA_DBG_PNP ,("Calling IoGetDeviceObjectPointer.\n"));
\r
422 status = IoGetDeviceObjectPointer( pNotify->SymbolicLinkName,
\r
423 FILE_ALL_ACCESS, &p_fdo->p_al_file_obj, &p_fdo->p_al_dev );
\r
424 if( !NT_SUCCESS( status ) )
\r
426 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
427 ("IoGetDeviceObjectPointer returned %08x.\n", status ));
\r
431 /* Register for removal notification of the IB Fabric root device. */
\r
432 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PNP,
\r
433 ("Registering for target notifications.\n"));
\r
434 status = IoRegisterPlugPlayNotification(
\r
435 EventCategoryTargetDeviceChange, 0, p_fdo->p_al_file_obj,
\r
436 p_dev_obj->DriverObject, __pnp_notify_target, p_fdo,
\r
437 &p_fdo->pnp_target_entry );
\r
438 if( !NT_SUCCESS( status ) )
\r
440 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
441 ("IoRegisterPlugPlayNotification returned %08x.\n", status));
\r
442 goto err_reg_notify;
\r
445 status = __hca_register( p_fdo );
\r
446 if( !NT_SUCCESS( status ) )
\r
448 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
449 ("__get_ci_interface returned %08x.\n", status));
\r
455 IoUnregisterPlugPlayNotification( p_fdo->pnp_target_entry );
\r
456 p_fdo->pnp_target_entry = NULL;
\r
458 ObDereferenceObject( p_fdo->p_al_file_obj );
\r
459 p_fdo->p_al_file_obj = NULL;
\r
460 p_fdo->p_al_dev = NULL;
\r
462 HCA_EXIT( HCA_DBG_PNP );
\r
466 /* Forwards the request to the HCA's PDO. */
\r
469 IN WDFDEVICE const FdoDevice,
\r
470 IN const GUID* const p_guid,
\r
473 IN OUT PVOID InterfaceSpecificData,
\r
474 OUT PINTERFACE p_ifc )
\r
478 HCA_ENTER( HCA_DBG_PNP );
\r
480 status = WdfFdoQueryForInterface( FdoDevice, p_guid, p_ifc,
\r
481 size, Version, InterfaceSpecificData );
\r
483 HCA_EXIT( HCA_DBG_PNP );
\r
488 __unmap_hca_memory(
\r
489 IN PFDO_DEVICE_DATA const p_fdo )
\r
491 struct pci_dev *pdev = p_fdo->bus_ib_ifc.pdev;
\r
494 HCA_ENTER( HCA_DBG_PNP );
\r
496 for( i = 0; i < HCA_BAR_TYPE_MAX; i++ ) {
\r
497 if (pdev->bar[i].virt) {
\r
498 MmUnmapIoSpace( pdev->bar[i].virt, pdev->bar[i].size );
\r
499 cl_memclr( &pdev->bar[i], sizeof(hca_bar_t) );
\r
503 HCA_EXIT( HCA_DBG_PNP );
\r
506 /* release the resources, allocated in hca_start */
\r
508 __hca_release_resources(
\r
509 IN WDFDEVICE Device )
\r
511 PFDO_DEVICE_DATA p_fdo = FdoGetData(Device);
\r
513 HCA_ENTER( HCA_DBG_PNP );
\r
515 switch( p_fdo->state )
\r
517 case HCA_REGISTERED:
\r
518 __hca_deregister( p_fdo );
\r
520 /* Fall through. */
\r
523 mlnx_hca_remove( &p_fdo->hca );
\r
526 if (p_fdo->al_sym_name.Buffer) {
\r
527 ExFreePool( p_fdo->al_sym_name.Buffer );
\r
528 p_fdo->al_sym_name.Buffer = NULL;
\r
531 if( p_fdo->pnp_target_entry )
\r
533 ASSERT( p_fdo->pnp_ifc_entry );
\r
534 IoUnregisterPlugPlayNotification( p_fdo->pnp_target_entry );
\r
535 p_fdo->pnp_target_entry = NULL;
\r
538 if( p_fdo->pnp_ifc_entry ) {
\r
539 IoUnregisterPlugPlayNotification( p_fdo->pnp_ifc_entry );
\r
540 p_fdo->pnp_ifc_entry = NULL;
\r
543 if( p_fdo->p_al_file_obj ) {
\r
544 ObDereferenceObject( p_fdo->p_al_file_obj );
\r
545 p_fdo->p_al_file_obj = NULL;
\r
548 __unmap_hca_memory( p_fdo );
\r
550 p_fdo->state = HCA_ADDED;
\r
552 HCA_EXIT( HCA_DBG_PNP );
\r
557 IN WDFDEVICE Device,
\r
558 IN WDF_POWER_DEVICE_STATE PreviousState
\r
561 PFDO_DEVICE_DATA p_fdo = FdoGetData(Device);
\r
562 NTSTATUS status = STATUS_SUCCESS;
\r
564 UNUSED_PARAM(PreviousState);
\r
565 HCA_ENTER( HCA_DBG_PNP );
\r
567 HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, ("EvtDeviceD0Entry: PreviousState 0x%x\n", PreviousState));
\r
569 /* Connect to IBAL */
\r
570 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO,
\r
571 ("***** Connect to IBAL, IRQL %d\n", KeGetCurrentIrql()));
\r
573 if( p_fdo->p_al_dev && p_fdo->state == HCA_STARTED) {
\r
574 status = __hca_register( p_fdo );
\r
575 if( !NT_SUCCESS( status ) ) {
\r
576 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PO,
\r
577 ("!!! __hca_register failed (%#x) \n", status));
\r
578 status = STATUS_UNSUCCESSFUL;
\r
582 HCA_EXIT( HCA_DBG_PNP );
\r
583 return STATUS_SUCCESS;
\r
588 IN WDFDEVICE Device,
\r
589 IN WDF_POWER_DEVICE_STATE TargetState
\r
593 PFDO_DEVICE_DATA p_fdo = FdoGetData(Device);
\r
595 HCA_ENTER( HCA_DBG_PNP );
\r
597 HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, ("EvtDeviceD0Exit: TargetState 0x%x\n", TargetState));
\r
599 switch (TargetState) {
\r
600 case WdfPowerDeviceD1: /* hopefully, it is STANDBY state */
\r
601 case WdfPowerDevicePrepareForHibernation:
\r
602 if (atomic_read(&p_fdo->usecnt)) {
\r
603 status = STATUS_UNSUCCESSFUL;
\r
606 /* Fall through. */
\r
608 __hca_deregister( p_fdo );
\r
609 status = STATUS_SUCCESS;
\r
613 HCA_EXIT( HCA_DBG_PNP );
\r
618 EvtDevicePrepareHardware(
\r
619 IN WDFDEVICE Device,
\r
620 IN WDFCMRESLIST ResourcesRaw,
\r
621 IN WDFCMRESLIST ResourcesTranslated
\r
626 PFDO_DEVICE_DATA p_fdo = FdoGetData(Device);
\r
627 PDEVICE_OBJECT p_dev_obj = WdfDeviceWdmGetDeviceObject(Device);
\r
628 BUS_INTERFACE_STANDARD bus_pci_ifc;
\r
630 UNUSED_PARAM(ResourcesRaw);
\r
631 UNUSED_PARAM(ResourcesTranslated);
\r
633 HCA_ENTER( HCA_DBG_PNP );
\r
635 HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, ("EvtPrepareHardware: \n"));
\r
639 /* get PCI BUS interface */
\r
640 status = __get_ifc( Device, &GUID_BUS_INTERFACE_STANDARD,
\r
641 sizeof(BUS_INTERFACE_STANDARD), 1, NULL, (PINTERFACE)&bus_pci_ifc);
\r
642 if( !NT_SUCCESS( status ) ) {
\r
643 HCA_PRINT(TRACE_LEVEL_ERROR, HCA_DBG_PNP, ("Getting PCI BUS interface failed: status=0x%x\n", status));
\r
646 RtlCopyMemory( &p_fdo->bus_pci_ifc, &bus_pci_ifc, sizeof(BUS_INTERFACE_STANDARD) );
\r
647 p_fdo->bus_pci_ifc_taken = TRUE;
\r
649 /* get MLX4_BUS IB interface */
\r
650 status = __get_ifc( Device, &MLX4_BUS_IB_INTERFACE_GUID,
\r
651 sizeof(MLX4_BUS_IB_INTERFACE), MLX4_BUS_IB_INTERFACE_VERSION, NULL, (PINTERFACE)&p_fdo->bus_ib_ifc);
\r
652 if( !NT_SUCCESS( status ) ) {
\r
653 HCA_PRINT(TRACE_LEVEL_ERROR, HCA_DBG_PNP, ("Getting MLX4 BUS interface failed: status=0x%x\n", status));
\r
656 p_fdo->bus_ib_ifc_taken = TRUE;
\r
657 p_fdo->bus_ib_ifc.p_ibdev->x.p_fdo = p_fdo;
\r
659 InitializeListHead(&p_fdo->hca.event_list);
\r
660 KeInitializeSpinLock(&p_fdo->hca.event_list_lock);
\r
662 /* get node GUID */
\r
663 err = __get_dev_info( p_fdo, &p_fdo->hca.guid, &p_fdo->hca.hw_ver );
\r
666 HCA_PRINT(TRACE_LEVEL_ERROR ,HCA_DBG_LOW ,
\r
667 ("can't get guid - ib_query_device() failed (%08X)\n", err ));
\r
668 //TODO: no cleanup on error
\r
669 return STATUS_INSUFFICIENT_RESOURCES;
\r
673 mlnx_hca_insert( &p_fdo->hca );
\r
676 * Change the state since the PnP callback can happen
\r
677 * before the callback returns.
\r
679 p_fdo->state = HCA_STARTED;
\r
681 /* Register for interface arrival of the IB_AL device. */
\r
682 status = IoRegisterPlugPlayNotification(
\r
683 EventCategoryDeviceInterfaceChange,
\r
684 PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,
\r
685 (void*)&GUID_IB_CI_INTERFACE, p_dev_obj->DriverObject,
\r
686 __pnp_notify_ifc, p_fdo, &p_fdo->pnp_ifc_entry );
\r
687 if( !NT_SUCCESS( status ) )
\r
689 p_fdo->state = HCA_ADDED;
\r
690 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
691 ("IoRegisterPlugPlayNotification returned %08x.\n", status));
\r
694 HCA_EXIT( HCA_DBG_PNP );
\r
700 EvtDeviceReleaseHardware(
\r
701 IN WDFDEVICE Device,
\r
702 IN WDFCMRESLIST ResourcesTranslated
\r
705 PFDO_DEVICE_DATA p_fdo = FdoGetData(Device);
\r
707 UNUSED_PARAM(ResourcesTranslated);
\r
709 HCA_ENTER( HCA_DBG_PNP );
\r
711 HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, ("EvtReleaseHardware: FdoData=0x%p\n", p_fdo));
\r
713 // release IBBUS resources
\r
714 __hca_release_resources(Device);
\r
716 // release MLX4_BUS resources
\r
717 if(p_fdo->bus_ib_ifc_taken) {
\r
718 p_fdo->bus_ib_ifc_taken = FALSE;
\r
719 __put_ifc( (PINTERFACE)&p_fdo->bus_ib_ifc );
\r
722 // release PCI BUS resources
\r
723 if(p_fdo->bus_pci_ifc_taken) {
\r
724 p_fdo->bus_pci_ifc_taken = FALSE;
\r
725 __put_ifc( (PINTERFACE)&p_fdo->bus_pci_ifc );
\r
728 HCA_EXIT( HCA_DBG_PNP );
\r
729 return STATUS_SUCCESS;
\r
733 EvtDeviceQueryRemove(
\r
734 IN WDFDEVICE Device
\r
737 PFDO_DEVICE_DATA p_fdo = FdoGetData(Device);
\r
738 HCA_ENTER( HCA_DBG_PNP );
\r
739 if (atomic_read(&p_fdo->usecnt)) {
\r
740 DbgPrint( "MLX4: Can't get unloaded. %d applications are still in work\n", p_fdo->usecnt);
\r
741 return STATUS_UNSUCCESSFUL;
\r
743 HCA_EXIT( HCA_DBG_PNP );
\r
744 return STATUS_SUCCESS;
\r
750 IN WDFDRIVER Driver,
\r
751 IN PWDFDEVICE_INIT DeviceInit
\r
754 Routine Description:
\r
756 EvtDeviceAdd is called by the framework in response to AddDevice
\r
757 call from the PnP manager. We create and initialize a device object to
\r
758 represent a new instance of mxe bus.
\r
762 Driver - Handle to a framework driver object created in DriverEntry
\r
764 DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.
\r
772 WDF_OBJECT_ATTRIBUTES attributes;
\r
775 PFDO_DEVICE_DATA p_fdo;
\r
776 WDF_PNPPOWER_EVENT_CALLBACKS Callbacks;
\r
778 UNREFERENCED_PARAMETER(Driver);
\r
782 HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, ("EvtDeviceAdd: 0x%p\n", Driver));
\r
784 // register PnP & Power stuff
\r
786 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&Callbacks);
\r
787 Callbacks.EvtDevicePrepareHardware = EvtDevicePrepareHardware;
\r
788 Callbacks.EvtDeviceReleaseHardware = EvtDeviceReleaseHardware;
\r
789 Callbacks.EvtDeviceQueryRemove = EvtDeviceQueryRemove;
\r
790 Callbacks.EvtDeviceD0Entry = EvtDeviceD0Entry;
\r
791 Callbacks.EvtDeviceD0Exit = EvtDeviceD0Exit;
\r
793 WdfDeviceInitSetPnpPowerEventCallbacks( DeviceInit, &Callbacks );
\r
796 // Initialize all the properties specific to the device.
\r
797 // Framework has default values for the one that are not
\r
798 // set explicitly here. So please read the doc and make sure
\r
799 // you are okay with the defaults.
\r
801 WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_INFINIBAND);
\r
802 WdfDeviceInitSetExclusive(DeviceInit, FALSE);
\r
805 // Initialize attributes structure to specify size and accessor function
\r
806 // for storing device context.
\r
808 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, FDO_DEVICE_DATA);
\r
811 // Create a framework device object. In response to this call, framework
\r
812 // creates a WDM deviceobject.
\r
814 status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
\r
815 if (!NT_SUCCESS(status)) {
\r
816 HCA_PRINT(TRACE_LEVEL_VERBOSE, HCA_DBG_PNP, ("EvtDeviceAdd: WdfDeviceCreate failed with 0x%x\n", status));
\r
821 // Init device context.
\r
823 p_fdo = FdoGetData(device);
\r
824 RtlZeroMemory(p_fdo, sizeof(FDO_DEVICE_DATA));
\r
825 p_fdo->FdoDevice = device;
\r
826 spin_lock_init( &p_fdo->uctx_lock );
\r
827 cl_qlist_init( &p_fdo->uctx_list );
\r
828 atomic_set(&p_fdo->usecnt, 0);
\r
829 p_fdo->state = HCA_ADDED;
\r
834 status = WmiRegistration(device);
\r
835 if (!NT_SUCCESS(status)) {
\r
839 status = STATUS_SUCCESS;
\r
842 HCA_EXIT( HCA_DBG_PNP );
\r
849 IN WDFDRIVER Driver
\r
852 HCA_ENTER( HCA_DBG_PNP );
\r
854 UNUSED_PARAM( Driver );
\r
856 HCA_EXIT( HCA_DBG_PNP );
\r
857 #if defined(EVENT_TRACING)
\r
858 WPP_CLEANUP(WdfDriverWdmGetDriverObject(Driver));
\r
864 IN PDRIVER_OBJECT DriverObject,
\r
865 IN PUNICODE_STRING RegistryPath
\r
868 Routine Description:
\r
870 Initialize the call backs structure of Driver Framework.
\r
874 DriverObject - pointer to the driver object
\r
876 RegistryPath - pointer to a unicode string representing the path,
\r
877 to driver-specific key in the registry.
\r
885 WDF_DRIVER_CONFIG config;
\r
889 #if defined(EVENT_TRACING)
\r
890 WPP_INIT_TRACING(DriverObject, RegistryPath);
\r
893 // global initializations
\r
894 g.DebugPrintLevel = TRACE_LEVEL_VERBOSE;
\r
895 g.DebugPrintFlags = 0xffff;
\r
896 HCA_ENTER( HCA_DBG_PNP );
\r
897 HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_PNP,
\r
898 ("Built %s %s, Version %s, RelDate %s\n",
\r
899 __DATE__, __TIME__, DRV_VERSION, DRV_RELDATE));
\r
900 status = mlnx_hcas_init();
\r
901 if( status != STATUS_SUCCESS ) {
\r
902 HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_PNP ,
\r
903 ("mlnx_hcas_init returned %#x.\n", status));
\r
908 // Initiialize driver config to control the attributes that
\r
909 // are global to the driver. Note that framework by default
\r
910 // provides a driver unload routine. If you create any resources
\r
911 // in the DriverEntry and want to be cleaned in driver unload,
\r
912 // you can override that by specifing one in the Config structure.
\r
915 WDF_DRIVER_CONFIG_INIT(
\r
916 &config, EvtDeviceAdd );
\r
917 config.EvtDriverUnload = EvtDriverUnload;
\r
920 // Create a framework driver object to represent our driver.
\r
922 status = WdfDriverCreate(DriverObject,
\r
923 RegistryPath, WDF_NO_OBJECT_ATTRIBUTES,
\r
924 &config, &hDriver);
\r
926 if (!NT_SUCCESS(status)) {
\r
927 HCA_PRINT(TRACE_LEVEL_VERBOSE, HCA_DBG_PNP, ("WdfDriverCreate failed with status 0x%x\n", status));
\r
932 // read registry parameters
\r
935 DECLARE_CONST_UNICODE_STRING(valueName0, L"DebugLevel");
\r
936 DECLARE_CONST_UNICODE_STRING(valueName1, L"DebugFlags");
\r
938 WDFKEY hKey = NULL;
\r
940 status = WdfDriverOpenParametersRegistryKey( hDriver,
\r
941 STANDARD_RIGHTS_ALL, WDF_NO_OBJECT_ATTRIBUTES, &hKey );
\r
943 if (NT_SUCCESS (status)) {
\r
945 status = WdfRegistryQueryULong(hKey, &valueName0, &value);
\r
946 if (NT_SUCCESS (status)) g.DebugPrintLevel = value;
\r
948 status = WdfRegistryQueryULong(hKey, &valueName1, &value);
\r
949 if (NT_SUCCESS (status)) g.DebugPrintFlags = value;
\r
951 WdfRegistryClose(hKey);
\r
954 // we don't matter the failure in the work with Registry
\r
955 status = STATUS_SUCCESS;
\r
959 HCA_EXIT( HCA_DBG_PNP );
\r
967 UNICODE_STRING g_param_path;
\r
968 static cl_vfptr_pnp_po_t vfptrHcaPnp;
\r
972 IN PDRIVER_OBJECT p_driver_obj,
\r
973 IN PUNICODE_STRING p_registry_path );
\r
977 IN UNICODE_STRING* const p_Param_Path );
\r
981 IN PDRIVER_OBJECT p_driver_obj );
\r
985 IN PDEVICE_OBJECT p_dev_obj,
\r
990 IN PDRIVER_OBJECT pDriverObj,
\r
991 IN PDEVICE_OBJECT pPdo );
\r
995 IN DEVICE_OBJECT* const p_dev_obj,
\r
996 IN IRP* const p_irp,
\r
997 OUT cl_irp_action_t* const p_action );
\r
1001 IN DEVICE_OBJECT* const p_dev_obj,
\r
1002 IN IRP* const p_irp,
\r
1003 OUT cl_irp_action_t* const p_action );
\r
1007 IN DEVICE_OBJECT* const p_dev_obj,
\r
1008 IN IRP* const p_irp,
\r
1009 OUT cl_irp_action_t* const p_action );
\r
1013 IN DEVICE_OBJECT* const p_dev_obj,
\r
1014 IN IRP* const p_irp,
\r
1015 OUT cl_irp_action_t* const p_action );
\r
1019 IN DEVICE_OBJECT* const p_dev_obj,
\r
1020 IN IRP* const p_irp,
\r
1021 OUT cl_irp_action_t* const p_action );
\r
1024 hca_release_resources(
\r
1025 IN DEVICE_OBJECT* const p_dev_obj );
\r
1028 hca_cancel_remove(
\r
1029 IN DEVICE_OBJECT* const p_dev_obj,
\r
1030 IN IRP* const p_irp,
\r
1031 OUT cl_irp_action_t* const p_action );
\r
1034 hca_surprise_remove(
\r
1035 IN DEVICE_OBJECT* const p_dev_obj,
\r
1036 IN IRP* const p_irp,
\r
1037 OUT cl_irp_action_t* const p_action );
\r
1040 hca_query_capabilities(
\r
1041 IN DEVICE_OBJECT* const p_dev_obj,
\r
1042 IN IRP* const p_irp,
\r
1043 OUT cl_irp_action_t* const p_action );
\r
1046 hca_query_pnp_state(
\r
1047 IN DEVICE_OBJECT* const p_dev_obj,
\r
1048 IN IRP* const p_irp,
\r
1049 OUT cl_irp_action_t* const p_action );
\r
1052 hca_query_bus_relations(
\r
1053 IN DEVICE_OBJECT* const p_dev_obj,
\r
1054 IN IRP* const p_irp,
\r
1055 OUT cl_irp_action_t* const p_action );
\r
1058 hca_query_removal_relations(
\r
1059 IN DEVICE_OBJECT* const p_dev_obj,
\r
1060 IN IRP* const p_irp,
\r
1061 OUT cl_irp_action_t* const p_action );
\r
1065 IN DEVICE_OBJECT* const p_dev_obj,
\r
1066 IN IRP* const p_irp,
\r
1067 OUT cl_irp_action_t* const p_action );
\r
1071 IN DEVICE_OBJECT* const p_dev_obj,
\r
1072 IN IRP* const p_irp,
\r
1073 OUT cl_irp_action_t* const p_action );
\r
1075 static ci_interface_t*
\r
1077 IN FDO_DEVICE_DATA* const p_fdo );
\r
1080 __get_ci_interface(
\r
1081 IN DEVICE_OBJECT* const p_dev_obj );
\r
1085 IN FDO_DEVICE_DATA *p_fdo );
\r
1089 IN DEVICE_OBJECT *p_dev_obj );
\r
1092 __pnp_notify_target(
\r
1093 IN void *pNotifyStruct,
\r
1094 IN void *context );
\r
1098 IN void *pNotifyStruct,
\r
1099 IN void *context );
\r
1102 #ifdef ALLOC_PRAGMA
\r
1103 #pragma alloc_text (INIT, DriverEntry)
\r
1104 #pragma alloc_text (INIT, __read_registry)
\r
1105 #pragma alloc_text (PAGE, hca_drv_unload)
\r
1106 #pragma alloc_text (PAGE, hca_sysctl)
\r
1107 #pragma alloc_text (PAGE, hca_add_device)
\r
1108 #pragma alloc_text (PAGE, hca_start)
\r
1109 #pragma alloc_text (PAGE, hca_query_stop)
\r
1110 #pragma alloc_text (PAGE, hca_stop)
\r
1111 #pragma alloc_text (PAGE, hca_cancel_stop)
\r
1112 #pragma alloc_text (PAGE, hca_query_remove)
\r
1113 #pragma alloc_text (PAGE, hca_release_resources)
\r
1114 #pragma alloc_text (PAGE, hca_cancel_remove)
\r
1115 #pragma alloc_text (PAGE, hca_surprise_remove)
\r
1116 #pragma alloc_text (PAGE, hca_query_capabilities)
\r
1117 #pragma alloc_text (PAGE, hca_query_pnp_state)
\r
1118 #pragma alloc_text (PAGE, hca_query_bus_relations)
\r
1119 #pragma alloc_text (PAGE, hca_query_removal_relations)
\r
1120 #pragma alloc_text (PAGE, hca_set_power)
\r
1121 #pragma alloc_text (PAGE, __alloc_hca_ifc)
\r
1122 #pragma alloc_text (PAGE, __get_ci_interface)
\r
1123 #pragma alloc_text (PAGE, __hca_register)
\r
1124 #pragma alloc_text (PAGE, __pnp_notify_target)
\r
1125 #pragma alloc_text (PAGE, __pnp_notify_ifc)
\r
1131 IN PDRIVER_OBJECT pDriverObj,
\r
1132 IN PDEVICE_OBJECT pPdo )
\r
1135 DEVICE_OBJECT *p_dev_obj, *pNextDevObj;
\r
1136 PFDO_DEVICE_DATA p_fdo;
\r
1138 HCA_ENTER(HCA_DBG_PNP);
\r
1141 * Create the device so that we have a device extension to store stuff in.
\r
1143 status = IoCreateDevice( pDriverObj, sizeof(FDO_DEVICE_DATA),
\r
1144 NULL, FILE_DEVICE_INFINIBAND, FILE_DEVICE_SECURE_OPEN,
\r
1145 FALSE, &p_dev_obj );
\r
1146 if( !NT_SUCCESS( status ) )
\r
1148 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
1149 ("IoCreateDevice returned 0x%08X.\n", status));
\r
1153 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1154 cl_memclr( p_fdo, sizeof(FDO_DEVICE_DATA) );
\r
1155 cl_spinlock_init( &p_fdo->uctx_lock );
\r
1156 cl_qlist_init( &p_fdo->uctx_list );
\r
1157 atomic_set(&p_fdo->usecnt, 0);
\r
1159 /* Attach to the device stack. */
\r
1160 pNextDevObj = IoAttachDeviceToDeviceStack( p_dev_obj, pPdo );
\r
1161 if( !pNextDevObj )
\r
1163 //cl_event_destroy( &p_fdo->mutex );
\r
1164 IoDeleteDevice( p_dev_obj );
\r
1165 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
1166 ("IoAttachDeviceToDeviceStack failed.\n"));
\r
1167 return STATUS_NO_SUCH_DEVICE;
\r
1170 /* Inititalize the complib extension. */
\r
1171 cl_init_pnp_po_ext( p_dev_obj, pNextDevObj, pPdo, 0,
\r
1172 &vfptrHcaPnp, NULL );
\r
1174 p_fdo->state = HCA_ADDED;
\r
1176 HCA_EXIT(HCA_DBG_PNP);
\r
1180 /* Forwards the request to the HCA's PDO. */
\r
1183 IN DEVICE_OBJECT* const pDevObj,
\r
1184 IN const GUID* const pGuid,
\r
1186 IN USHORT Version,
\r
1187 IN OUT PVOID InterfaceSpecificData,
\r
1188 OUT PINTERFACE pBusIfc )
\r
1192 IO_STATUS_BLOCK ioStatus;
\r
1193 IO_STACK_LOCATION *pIoStack;
\r
1194 DEVICE_OBJECT *pDev;
\r
1197 HCA_ENTER( HCA_DBG_PNP );
\r
1199 CL_ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
\r
1201 pDev = IoGetAttachedDeviceReference( pDevObj );
\r
1203 KeInitializeEvent( &event, NotificationEvent, FALSE );
\r
1205 /* Build the IRP for the HCA. */
\r
1206 pIrp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, pDev,
\r
1207 NULL, 0, NULL, &event, &ioStatus );
\r
1210 ObDereferenceObject( pDev );
\r
1211 HCA_PRINT( TRACE_LEVEL_ERROR,HCA_DBG_PNP,
\r
1212 ("IoBuildSynchronousFsdRequest failed.\n"));
\r
1213 return STATUS_INSUFFICIENT_RESOURCES;
\r
1216 /* Copy the request query parameters. */
\r
1217 pIoStack = IoGetNextIrpStackLocation( pIrp );
\r
1218 pIoStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
\r
1219 pIoStack->Parameters.QueryInterface.Size = size;
\r
1220 pIoStack->Parameters.QueryInterface.Version = Version;
\r
1221 pIoStack->Parameters.QueryInterface.InterfaceType = pGuid;
\r
1222 pIoStack->Parameters.QueryInterface.Interface = (INTERFACE*)pBusIfc;
\r
1223 pIoStack->Parameters.QueryInterface.InterfaceSpecificData = InterfaceSpecificData;
\r
1225 pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
\r
1227 /* Send the IRP. */
\r
1228 status = IoCallDriver( pDev, pIrp );
\r
1229 if( status == STATUS_PENDING )
\r
1231 KeWaitForSingleObject( &event, Executive, KernelMode,
\r
1234 status = ioStatus.Status;
\r
1236 ObDereferenceObject( pDev );
\r
1238 HCA_EXIT( HCA_DBG_PNP );
\r
1243 __get_ci_interface(
\r
1244 IN DEVICE_OBJECT* const p_dev_obj )
\r
1248 PFDO_DEVICE_DATA p_fdo;
\r
1249 IO_STATUS_BLOCK ioStatus;
\r
1250 IO_STACK_LOCATION *pIoStack;
\r
1253 HCA_ENTER( HCA_DBG_PNP );
\r
1255 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1257 KeInitializeEvent( &event, NotificationEvent, FALSE );
\r
1259 /* Query for the verbs interface. */
\r
1260 p_irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, p_fdo->p_al_dev,
\r
1261 NULL, 0, NULL, &event, &ioStatus );
\r
1264 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
1265 ("IoBuildSynchronousFsdRequest failed.\n"));
\r
1266 return STATUS_INSUFFICIENT_RESOURCES;
\r
1269 /* Format the IRP. */
\r
1270 pIoStack = IoGetNextIrpStackLocation( p_irp );
\r
1271 pIoStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
\r
1272 pIoStack->Parameters.QueryInterface.Version = IB_CI_INTERFACE_VERSION;
\r
1273 pIoStack->Parameters.QueryInterface.Size = sizeof(ib_ci_ifc_t);
\r
1274 pIoStack->Parameters.QueryInterface.Interface =
\r
1275 (INTERFACE*)&p_fdo->ci_ifc;
\r
1276 pIoStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
\r
1277 pIoStack->Parameters.QueryInterface.InterfaceType =
\r
1278 &GUID_IB_CI_INTERFACE;
\r
1279 p_irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
\r
1281 /* Send the IRP. */
\r
1282 status = IoCallDriver( p_fdo->p_al_dev, p_irp );
\r
1283 if( status == STATUS_PENDING )
\r
1285 KeWaitForSingleObject( &event, Executive, KernelMode,
\r
1288 status = ioStatus.Status;
\r
1291 if( !NT_SUCCESS( status ) )
\r
1293 HCA_PRINT( TRACE_LEVEL_ERROR,HCA_DBG_PNP,
\r
1294 ("Query interface for verbs returned %08x.\n", status));
\r
1298 HCA_EXIT( HCA_DBG_PNP );
\r
1304 __pnp_notify_target(
\r
1305 IN void *pNotifyStruct,
\r
1306 IN void *context )
\r
1308 NTSTATUS status = STATUS_SUCCESS;
\r
1309 DEVICE_OBJECT *p_dev_obj;
\r
1310 PFDO_DEVICE_DATA p_fdo;
\r
1311 TARGET_DEVICE_REMOVAL_NOTIFICATION *pNotify;
\r
1313 HCA_ENTER( HCA_DBG_PNP );
\r
1315 pNotify = (TARGET_DEVICE_REMOVAL_NOTIFICATION*)pNotifyStruct;
\r
1316 p_dev_obj = (DEVICE_OBJECT*)context;
\r
1317 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1319 if( IsEqualGUID( &pNotify->Event, &GUID_TARGET_DEVICE_QUERY_REMOVE ) )
\r
1321 if ( p_fdo->state == HCA_REGISTERED) {
\r
1322 /* Release AL's CI interface. */
\r
1323 p_fdo->ci_ifc.wdm.InterfaceDereference( p_fdo->ci_ifc.wdm.Context );
\r
1324 p_fdo->state = HCA_IFC_DEREFERENCED;
\r
1327 /* Release AL's file object so that it can unload. */
\r
1328 CL_ASSERT( p_fdo->p_al_dev );
\r
1329 CL_ASSERT( p_fdo->p_al_file_obj );
\r
1330 CL_ASSERT( p_fdo->p_al_file_obj == pNotify->FileObject );
\r
1331 if( p_fdo->p_al_file_obj ) {
\r
1332 ObDereferenceObject( p_fdo->p_al_file_obj );
\r
1333 p_fdo->p_al_file_obj = NULL;
\r
1334 p_fdo->p_al_dev = NULL;
\r
1337 else if( IsEqualGUID( &pNotify->Event,
\r
1338 &GUID_TARGET_DEVICE_REMOVE_COMPLETE ) )
\r
1340 if (p_fdo->ci_ifc.deregister_ca) {
\r
1341 /* Notify AL that the CA is being removed. */
\r
1342 p_fdo->ci_ifc.deregister_ca( p_fdo->hca.guid );
\r
1343 p_fdo->ci_ifc.deregister_ca = NULL;
\r
1346 if ( p_fdo->state == HCA_REGISTERED) {
\r
1347 /* Release AL's CI interface. */
\r
1348 p_fdo->ci_ifc.wdm.InterfaceDereference( p_fdo->ci_ifc.wdm.Context );
\r
1350 p_fdo->state = HCA_STARTED;
\r
1352 /* Release AL's file object so that it can unload. */
\r
1353 if( p_fdo->p_al_file_obj )
\r
1355 ObDereferenceObject( p_fdo->p_al_file_obj );
\r
1356 p_fdo->p_al_file_obj = NULL;
\r
1357 p_fdo->p_al_dev = NULL;
\r
1360 /* Cancel our target device change registration. */
\r
1361 if (p_fdo->pnp_target_entry) {
\r
1362 IoUnregisterPlugPlayNotification( p_fdo->pnp_target_entry );
\r
1363 p_fdo->pnp_target_entry = NULL;
\r
1367 else if( IsEqualGUID( &pNotify->Event,
\r
1368 &GUID_TARGET_DEVICE_REMOVE_CANCELLED ) )
\r
1370 /* Cancel our target device change registration. */
\r
1371 if (p_fdo->pnp_target_entry) {
\r
1372 IoUnregisterPlugPlayNotification( p_fdo->pnp_target_entry );
\r
1373 p_fdo->pnp_target_entry = NULL;
\r
1376 /* Get the device object pointer for the AL. */
\r
1377 CL_ASSERT( !p_fdo->p_al_file_obj );
\r
1378 CL_ASSERT( !p_fdo->p_al_dev );
\r
1379 /* Get the AL device object. */
\r
1380 HCA_PRINT( TRACE_LEVEL_INFORMATION ,HCA_DBG_SHIM ,("Calling IoGetDeviceObjectPointer.\n"));
\r
1381 status = IoGetDeviceObjectPointer( &p_fdo->al_sym_name,
\r
1382 FILE_ALL_ACCESS, &p_fdo->p_al_file_obj, &p_fdo->p_al_dev );
\r
1383 if( !NT_SUCCESS( status ) )
\r
1385 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_SHIM,
\r
1386 ("IoGetDeviceObjectPointer returned %08x.\n", status ));
\r
1387 return STATUS_SUCCESS;
\r
1390 /* Register for removal notification of the IB Fabric root device. */
\r
1391 status = IoRegisterPlugPlayNotification(
\r
1392 EventCategoryTargetDeviceChange, 0, p_fdo->p_al_file_obj,
\r
1393 p_dev_obj->DriverObject, __pnp_notify_target, p_dev_obj,
\r
1394 &p_fdo->pnp_target_entry );
\r
1395 if( !NT_SUCCESS( status ) )
\r
1397 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
1398 ("IoRegisterPlugPlayNotification returned %08x.\n", status));
\r
1402 CL_ASSERT( p_fdo->state == HCA_IFC_DEREFERENCED );
\r
1403 if ( p_fdo->state == HCA_IFC_DEREFERENCED) {
\r
1404 /* Release AL's CI interface. */
\r
1405 p_fdo->ci_ifc.wdm.InterfaceReference( p_fdo->ci_ifc.wdm.Context );
\r
1406 p_fdo->state = HCA_REGISTERED;
\r
1410 HCA_EXIT( HCA_DBG_PNP );
\r
1414 static ci_interface_t*
\r
1416 IN PFDO_DEVICE_DATA const p_fdo )
\r
1418 ci_interface_t *pIfc;
\r
1420 HCA_ENTER( HCA_DBG_PNP );
\r
1422 pIfc = (ci_interface_t*)ExAllocatePoolWithTag( PagedPool,
\r
1423 sizeof(ci_interface_t), MT_TAG_KERNEL );
\r
1426 HCA_PRINT( TRACE_LEVEL_ERROR,HCA_DBG_PNP,
\r
1427 ("Failed to allocate ci_interface_t (%d bytes).\n",
\r
1428 sizeof(ci_interface_t)));
\r
1432 setup_ci_interface( p_fdo->hca.guid, !!hca_is_livefish(p_fdo), pIfc );
\r
1434 pIfc->p_hca_dev = p_fdo->cl_ext.p_pdo;
\r
1435 pIfc->vend_id = (uint32_t)p_fdo->bus_ib_ifc.pdev->ven_id;
\r
1436 pIfc->dev_id = (uint16_t)p_fdo->bus_ib_ifc.pdev->dev_id;
\r
1437 pIfc->dev_revision = (uint16_t)p_fdo->hca.hw_ver;
\r
1439 HCA_EXIT( HCA_DBG_PNP );
\r
1445 IN PFDO_DEVICE_DATA p_fdo )
\r
1447 HCA_ENTER( HCA_DBG_PNP );
\r
1449 if ( p_fdo->state == HCA_REGISTERED) {
\r
1450 if (p_fdo->ci_ifc.deregister_ca) {
\r
1451 /* Notify AL that the CA is being removed. */
\r
1452 p_fdo->ci_ifc.deregister_ca( p_fdo->hca.guid );
\r
1453 p_fdo->ci_ifc.deregister_ca = NULL;
\r
1454 /* Release AL's CI interface. */
\r
1455 p_fdo->ci_ifc.wdm.InterfaceDereference( p_fdo->ci_ifc.wdm.Context );
\r
1456 p_fdo->state = HCA_STARTED;
\r
1457 HCA_PRINT( TRACE_LEVEL_INFORMATION ,HCA_DBG_PNP,
\r
1458 ("***** HCA deregistered \n"));
\r
1462 HCA_EXIT( HCA_DBG_PNP );
\r
1467 IN DEVICE_OBJECT *p_dev_obj )
\r
1469 PFDO_DEVICE_DATA p_fdo;
\r
1471 ib_api_status_t ib_status;
\r
1472 ci_interface_t *p_hca_ifc;
\r
1474 HCA_ENTER( HCA_DBG_PNP );
\r
1476 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1478 ASSERT( p_fdo->state == HCA_STARTED );
\r
1479 ASSERT( p_fdo->p_al_dev );
\r
1481 /* Get the AL's lower interface. */
\r
1482 status = __get_ci_interface( p_dev_obj );
\r
1483 if( !NT_SUCCESS( status ) )
\r
1485 HCA_PRINT( TRACE_LEVEL_ERROR,HCA_DBG_PNP,
\r
1486 ("__get_ci_interface returned %08x.\n", status));
\r
1490 /* Allocate and populate our HCA interface structure. */
\r
1491 p_hca_ifc = __alloc_hca_ifc( p_fdo );
\r
1494 HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_PNP ,("__alloc_hca_ifc failed.\n"));
\r
1495 status = STATUS_NO_MEMORY;
\r
1499 /* Notify AL that we're available... */
\r
1500 ib_status = p_fdo->ci_ifc.register_ca( p_hca_ifc );
\r
1501 ExFreePool( p_hca_ifc );
\r
1502 if( ib_status != IB_SUCCESS )
\r
1504 p_fdo->ci_ifc.wdm.InterfaceDereference( p_fdo->ci_ifc.wdm.Context );
\r
1505 status = STATUS_INSUFFICIENT_RESOURCES;
\r
1509 p_fdo->state = HCA_REGISTERED;
\r
1510 HCA_PRINT( TRACE_LEVEL_INFORMATION ,HCA_DBG_PNP,
\r
1511 ("***** HCA registered \n"));
\r
1513 HCA_EXIT( HCA_DBG_PNP );
\r
1520 IN void *pNotifyStruct,
\r
1521 IN void *context )
\r
1523 NTSTATUS status = STATUS_SUCCESS;
\r
1524 DEVICE_OBJECT *p_dev_obj;
\r
1525 PFDO_DEVICE_DATA p_fdo;
\r
1526 DEVICE_INTERFACE_CHANGE_NOTIFICATION *pNotify;
\r
1528 HCA_ENTER( HCA_DBG_PNP );
\r
1530 pNotify = (DEVICE_INTERFACE_CHANGE_NOTIFICATION*)pNotifyStruct;
\r
1531 p_dev_obj = (DEVICE_OBJECT*)context;
\r
1532 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1534 if( !IsEqualGUID( &pNotify->Event, &GUID_DEVICE_INTERFACE_ARRIVAL ) )
\r
1538 * Sanity check. We should only be getting notifications of the
\r
1539 * CI interface exported by AL.
\r
1542 IsEqualGUID( &pNotify->InterfaceClassGuid, &GUID_IB_CI_INTERFACE ) );
\r
1544 if( p_fdo->state != HCA_STARTED )
\r
1546 HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_PNP ,("Invalid state: %d\n", p_fdo->state));
\r
1550 /* save symbolic name of IBAL for a case of cancelled IBAL removal */
\r
1551 if (!p_fdo->al_sym_name.Buffer) {
\r
1552 p_fdo->al_sym_name.Length = pNotify->SymbolicLinkName->Length;
\r
1553 p_fdo->al_sym_name.MaximumLength = pNotify->SymbolicLinkName->MaximumLength;
\r
1554 p_fdo->al_sym_name.Buffer = ExAllocatePoolWithTag( NonPagedPool,
\r
1555 p_fdo->al_sym_name.MaximumLength * sizeof(wchar_t),
\r
1557 if (!p_fdo->al_sym_name.Buffer)
\r
1559 HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_PNP ,("allocation of sym IBAL name failed.\n"));
\r
1562 RtlCopyUnicodeString( &p_fdo->al_sym_name, pNotify->SymbolicLinkName );
\r
1565 ASSERT( !p_fdo->p_al_dev );
\r
1566 ASSERT( !p_fdo->p_al_file_obj );
\r
1568 /* Get the AL device object. */
\r
1569 HCA_PRINT( TRACE_LEVEL_INFORMATION ,HCA_DBG_PNP ,("Calling IoGetDeviceObjectPointer.\n"));
\r
1570 status = IoGetDeviceObjectPointer( pNotify->SymbolicLinkName,
\r
1571 FILE_ALL_ACCESS, &p_fdo->p_al_file_obj, &p_fdo->p_al_dev );
\r
1572 if( !NT_SUCCESS( status ) )
\r
1574 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
1575 ("IoGetDeviceObjectPointer returned %08x.\n", status ));
\r
1579 /* Register for removal notification of the IB Fabric root device. */
\r
1580 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PNP,
\r
1581 ("Registering for target notifications.\n"));
\r
1582 status = IoRegisterPlugPlayNotification(
\r
1583 EventCategoryTargetDeviceChange, 0, p_fdo->p_al_file_obj,
\r
1584 p_dev_obj->DriverObject, __pnp_notify_target, p_dev_obj,
\r
1585 &p_fdo->pnp_target_entry );
\r
1586 if( !NT_SUCCESS( status ) )
\r
1588 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
1589 ("IoRegisterPlugPlayNotification returned %08x.\n", status));
\r
1590 goto err_reg_notify;
\r
1593 status = __hca_register( p_dev_obj );
\r
1594 if( !NT_SUCCESS( status ) )
\r
1596 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
1597 ("__get_ci_interface returned %08x.\n", status));
\r
1603 IoUnregisterPlugPlayNotification( p_fdo->pnp_target_entry );
\r
1604 p_fdo->pnp_target_entry = NULL;
\r
1606 ObDereferenceObject( p_fdo->p_al_file_obj );
\r
1607 p_fdo->p_al_file_obj = NULL;
\r
1608 p_fdo->p_al_dev = NULL;
\r
1610 HCA_EXIT( HCA_DBG_PNP );
\r
1616 __unmap_hca_memory(
\r
1617 IN PFDO_DEVICE_DATA const p_fdo )
\r
1619 struct pci_dev *pdev = p_fdo->bus_ib_ifc.pdev;
\r
1622 HCA_ENTER( HCA_DBG_PNP );
\r
1625 for( i = 0; i < HCA_BAR_TYPE_MAX; i++ ) {
\r
1626 if (pdev->bar[i].virt) {
\r
1627 MmUnmapIoSpace( pdev->bar[i].virt, pdev->bar[i].size );
\r
1628 cl_memclr( &pdev->bar[i], sizeof(hca_bar_t) );
\r
1632 HCA_EXIT( HCA_DBG_PNP );
\r
1636 /* release the resources, allocated in hca_start */
\r
1638 __hca_release_resources(
\r
1639 IN DEVICE_OBJECT* const p_dev_obj )
\r
1641 PFDO_DEVICE_DATA p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1643 HCA_ENTER( HCA_DBG_PNP );
\r
1645 switch( p_fdo->state )
\r
1647 case HCA_REGISTERED:
\r
1648 __hca_deregister( p_fdo );
\r
1650 /* Fall through. */
\r
1653 mlnx_hca_remove( &p_fdo->hca );
\r
1656 if (p_fdo->al_sym_name.Buffer) {
\r
1657 ExFreePool( p_fdo->al_sym_name.Buffer );
\r
1658 p_fdo->al_sym_name.Buffer = NULL;
\r
1661 if( p_fdo->pnp_target_entry )
\r
1663 ASSERT( p_fdo->pnp_ifc_entry );
\r
1664 IoUnregisterPlugPlayNotification( p_fdo->pnp_target_entry );
\r
1665 p_fdo->pnp_target_entry = NULL;
\r
1668 if( p_fdo->pnp_ifc_entry ) {
\r
1669 IoUnregisterPlugPlayNotification( p_fdo->pnp_ifc_entry );
\r
1670 p_fdo->pnp_ifc_entry = NULL;
\r
1673 if( p_fdo->p_al_file_obj ) {
\r
1674 ObDereferenceObject( p_fdo->p_al_file_obj );
\r
1675 p_fdo->p_al_file_obj = NULL;
\r
1678 // release MLX4_BUS resources
\r
1679 if(p_fdo->bus_ib_ifc_taken) {
\r
1680 p_fdo->bus_ib_ifc_taken = FALSE;
\r
1681 __put_ifc( (PINTERFACE)&p_fdo->bus_ib_ifc );
\r
1684 // release PCI BUS resources
\r
1685 if(p_fdo->bus_pci_ifc_taken) {
\r
1686 p_fdo->bus_pci_ifc_taken = FALSE;
\r
1687 __put_ifc( (PINTERFACE)&p_fdo->bus_pci_ifc );
\r
1690 __unmap_hca_memory( p_fdo );
\r
1692 p_fdo->state = HCA_ADDED;
\r
1694 HCA_EXIT( HCA_DBG_PNP );
\r
1699 hca_release_resources(
\r
1700 IN DEVICE_OBJECT* const p_dev_obj )
\r
1702 PFDO_DEVICE_DATA p_fdo;
\r
1703 POWER_STATE powerState;
\r
1705 HCA_ENTER( HCA_DBG_PNP );
\r
1707 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1709 /* release all the resources, allocated in hca_start */
\r
1710 __hca_release_resources(p_dev_obj);
\r
1712 /* Notify the power manager that the device is powered down. */
\r
1713 p_fdo->DevicePowerState = PowerDeviceD3;
\r
1714 powerState.DeviceState = PowerDeviceD3;
\r
1715 powerState = PoSetPowerState ( p_fdo->cl_ext.p_self_do, DevicePowerState, powerState );
\r
1717 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PNP,
\r
1718 ("PoSetPowerState: old state %d, new state to %d\n",
\r
1719 powerState.DeviceState, p_fdo->DevicePowerState ));
\r
1721 /* Clear the PnP state in case we get restarted. */
\r
1722 p_fdo->pnpState = 0;
\r
1724 HCA_EXIT( HCA_DBG_PNP );
\r
1729 IN DEVICE_OBJECT* const p_dev_obj,
\r
1730 IN IRP* const p_irp,
\r
1731 OUT cl_irp_action_t* const p_action )
\r
1735 PFDO_DEVICE_DATA p_fdo;
\r
1736 IO_STACK_LOCATION *pIoStack;
\r
1737 POWER_STATE powerState;
\r
1738 BUS_INTERFACE_STANDARD bus_pci_ifc;
\r
1740 HCA_ENTER( HCA_DBG_PNP );
\r
1742 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1744 /* Handled on the way up. */
\r
1745 status = cl_do_sync_pnp( p_dev_obj, p_irp, p_action );
\r
1746 if( !NT_SUCCESS( status ) )
\r
1748 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
1749 ("Lower drivers failed IRP_MN_START_DEVICE (%#x).\n", status));
\r
1753 pIoStack = IoGetCurrentIrpStackLocation( p_irp );
\r
1755 /* get PCI BUS interface */
\r
1756 status = __get_ifc( p_dev_obj, &GUID_BUS_INTERFACE_STANDARD,
\r
1757 sizeof(BUS_INTERFACE_STANDARD), 1, NULL, (PINTERFACE)&bus_pci_ifc);
\r
1758 if( !NT_SUCCESS( status ) ) {
\r
1759 HCA_PRINT(TRACE_LEVEL_ERROR, HCA_DBG_PNP, ("Getting PCI BUS interface failed: status=0x%x\n", status));
\r
1762 RtlCopyMemory( &p_fdo->bus_pci_ifc, &bus_pci_ifc, sizeof(BUS_INTERFACE_STANDARD) );
\r
1763 p_fdo->bus_pci_ifc_taken = TRUE;
\r
1765 /* get MLX4_BUS IB interface */
\r
1766 status = __get_ifc( p_dev_obj, &MLX4_BUS_IB_INTERFACE_GUID,
\r
1767 sizeof(MLX4_BUS_IB_INTERFACE), MLX4_BUS_IB_INTERFACE_VERSION, NULL, (PINTERFACE)&p_fdo->bus_ib_ifc);
\r
1768 if( !NT_SUCCESS( status ) ) {
\r
1769 HCA_PRINT(TRACE_LEVEL_ERROR, HCA_DBG_PNP, ("Getting MLX4 BUS interface failed: status=0x%x\n", status));
\r
1772 p_fdo->bus_ib_ifc_taken = TRUE;
\r
1773 p_fdo->bus_ib_ifc.p_ibdev->x.p_fdo = p_fdo;
\r
1776 /* get node GUID */
\r
1777 err = __get_dev_info( p_fdo, &p_fdo->hca.guid, &p_fdo->hca.hw_ver );
\r
1780 HCA_PRINT(TRACE_LEVEL_ERROR ,HCA_DBG_LOW ,
\r
1781 ("can't get guid - ib_query_device() failed (%08X)\n", err ));
\r
1782 //TODO: no cleanup on error
\r
1783 return STATUS_INSUFFICIENT_RESOURCES;
\r
1787 mlnx_hca_insert( &p_fdo->hca );
\r
1790 * Change the state since the PnP callback can happen
\r
1791 * before the callback returns.
\r
1793 p_fdo->state = HCA_STARTED;
\r
1795 /* Register for interface arrival of the IB_AL device. */
\r
1796 status = IoRegisterPlugPlayNotification(
\r
1797 EventCategoryDeviceInterfaceChange,
\r
1798 PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,
\r
1799 (void*)&GUID_IB_CI_INTERFACE, p_dev_obj->DriverObject,
\r
1800 __pnp_notify_ifc, p_dev_obj, &p_fdo->pnp_ifc_entry );
\r
1801 if( !NT_SUCCESS( status ) )
\r
1803 p_fdo->state = HCA_ADDED;
\r
1804 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
1805 ("IoRegisterPlugPlayNotification returned %08x.\n", status));
\r
1808 /* We get started fully powered. */
\r
1809 p_fdo->DevicePowerState = PowerDeviceD0;
\r
1810 powerState.DeviceState = PowerDeviceD0;
\r
1811 powerState = PoSetPowerState ( p_fdo->cl_ext.p_self_do, DevicePowerState, powerState );
\r
1812 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PNP,
\r
1813 ("PoSetPowerState: old state %d, new state to %d\n",
\r
1814 powerState.DeviceState, p_fdo->DevicePowerState ));
\r
1817 HCA_EXIT( HCA_DBG_PNP );
\r
1823 hca_query_removal_relations(
\r
1824 IN DEVICE_OBJECT* const p_dev_obj,
\r
1825 IN IRP* const p_irp,
\r
1826 OUT cl_irp_action_t* const p_action )
\r
1829 PFDO_DEVICE_DATA p_fdo;
\r
1831 HCA_ENTER( HCA_DBG_PNP );
\r
1833 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1835 if( p_fdo->state == HCA_REGISTERED )
\r
1837 status = p_fdo->ci_ifc.get_relations( p_fdo->hca.guid, p_irp );
\r
1838 if( !NT_SUCCESS( status ) )
\r
1840 *p_action = IrpComplete;
\r
1841 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
1842 ("AL get_relations returned %08x.\n", status));
\r
1847 *p_action = IrpPassDown;
\r
1848 HCA_EXIT( HCA_DBG_PNP );
\r
1849 return STATUS_SUCCESS;
\r
1854 hca_query_bus_relations(
\r
1855 IN DEVICE_OBJECT* const p_dev_obj,
\r
1856 IN IRP* const p_irp,
\r
1857 OUT cl_irp_action_t* const p_action )
\r
1860 DEVICE_RELATIONS *p_rel;
\r
1861 PFDO_DEVICE_DATA p_fdo;
\r
1863 HCA_ENTER( HCA_DBG_PNP );
\r
1865 p_fdo = p_dev_obj->DeviceExtension;
\r
1867 //cl_event_wait_on( &p_fdo->mutex, EVENT_NO_TIMEOUT, FALSE );
\r
1868 if( p_fdo->state == HCA_REGISTERED )
\r
1870 status = p_fdo->ci_ifc.get_relations( p_fdo->hca.guid, p_irp );
\r
1871 if( !NT_SUCCESS( status ) )
\r
1873 //cl_event_signal( &p_fdo->mutex );
\r
1874 *p_action = IrpComplete;
\r
1875 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
1876 ("AL get_relations returned %08x.\n", status));
\r
1882 status = cl_alloc_relations( p_irp, 1 );
\r
1883 if( !NT_SUCCESS( status ) )
\r
1885 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
1886 ("cl_alloc_relations returned %08x.\n", status));
\r
1890 p_rel = (DEVICE_RELATIONS*)p_irp->IoStatus.Information;
\r
1892 p_rel->Objects[0] = NULL;
\r
1895 //cl_event_signal( &p_fdo->mutex );
\r
1897 *p_action = IrpPassDown;
\r
1898 HCA_EXIT( HCA_DBG_PNP );
\r
1899 return STATUS_SUCCESS;
\r
1905 IN DEVICE_OBJECT* const p_dev_obj,
\r
1906 IN IRP* const p_irp,
\r
1907 OUT cl_irp_action_t* const p_action )
\r
1909 /* All kernel clients will get notified through the device hierarchy. */
\r
1911 /* TODO: set a flag to fail creation of any new IB resources. */
\r
1912 return cl_irp_skip( p_dev_obj, p_irp, p_action );
\r
1918 IN DEVICE_OBJECT* const p_dev_obj,
\r
1919 IN IRP* const p_irp,
\r
1920 OUT cl_irp_action_t* const p_action )
\r
1923 * Must disable everything. Complib framework will
\r
1924 * call ReleaseResources handler.
\r
1926 return cl_irp_skip( p_dev_obj, p_irp, p_action );
\r
1932 IN DEVICE_OBJECT* const p_dev_obj,
\r
1933 IN IRP* const p_irp,
\r
1934 OUT cl_irp_action_t* const p_action )
\r
1936 /* Handled on the way up. */
\r
1937 return cl_do_sync_pnp( p_dev_obj, p_irp, p_action );
\r
1943 IN DEVICE_OBJECT* const p_dev_obj,
\r
1944 IN IRP* const p_irp,
\r
1945 OUT cl_irp_action_t* const p_action )
\r
1947 PFDO_DEVICE_DATA p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1948 if (atomic_read(&p_fdo->usecnt)) {
\r
1949 DbgPrint( "MTHCA: Can't get unloaded. %d applications are still in work\n", p_fdo->usecnt);
\r
1950 p_irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
\r
1951 return cl_irp_complete( p_dev_obj, p_irp, p_action );
\r
1953 /* TODO: set a flag to fail creation of any new IB resources. */
\r
1954 return cl_irp_skip( p_dev_obj, p_irp, p_action );
\r
1959 hca_cancel_remove(
\r
1960 IN DEVICE_OBJECT* const p_dev_obj,
\r
1961 IN IRP* const p_irp,
\r
1962 OUT cl_irp_action_t* const p_action )
\r
1964 /* Handled on the way up. */
\r
1965 return cl_do_sync_pnp( p_dev_obj, p_irp, p_action );
\r
1970 hca_surprise_remove(
\r
1971 IN DEVICE_OBJECT* const p_dev_obj,
\r
1972 IN IRP* const p_irp,
\r
1973 OUT cl_irp_action_t* const p_action )
\r
1976 * TODO: Set state so that all further requests
\r
1977 * automatically succeed/fail as needed.
\r
1979 return cl_irp_skip( p_dev_obj, p_irp, p_action );
\r
1984 hca_query_capabilities(
\r
1985 IN DEVICE_OBJECT* const p_dev_obj,
\r
1986 IN IRP* const p_irp,
\r
1987 OUT cl_irp_action_t* const p_action )
\r
1990 PFDO_DEVICE_DATA p_fdo;
\r
1991 IO_STACK_LOCATION *pIoStack;
\r
1992 DEVICE_CAPABILITIES *pCaps;
\r
1994 HCA_ENTER( HCA_DBG_PNP );
\r
1996 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1998 /* Process on the way up. */
\r
1999 status = cl_do_sync_pnp( p_dev_obj, p_irp, p_action );
\r
2000 if( !NT_SUCCESS( status ) )
\r
2002 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
2003 ("cl_do_sync_pnp returned %08X.\n", status));
\r
2007 pIoStack = IoGetCurrentIrpStackLocation( p_irp );
\r
2008 pCaps = pIoStack->Parameters.DeviceCapabilities.Capabilities;
\r
2011 * Store the device power mapping into our extension since we're
\r
2012 * the power policy owner. The mapping is used when handling
\r
2013 * IRP_MN_SET_POWER IRPs.
\r
2016 p_fdo->DevicePower, pCaps->DeviceState, sizeof(p_fdo->DevicePower) );
\r
2018 if( pCaps->DeviceD1 )
\r
2020 HCA_PRINT( TRACE_LEVEL_WARNING ,HCA_DBG_PNP,
\r
2021 ("WARNING: Device reports support for DeviceD1 power state.\n"));
\r
2022 pCaps->DeviceD1 = FALSE;
\r
2025 if( pCaps->DeviceD2 )
\r
2027 HCA_PRINT( TRACE_LEVEL_WARNING,HCA_DBG_PNP,
\r
2028 ("WARNING: Device reports support for DeviceD2 power state.\n"));
\r
2029 pCaps->DeviceD2 = FALSE;
\r
2032 if( pCaps->SystemWake != PowerSystemUnspecified )
\r
2034 HCA_PRINT( TRACE_LEVEL_WARNING ,HCA_DBG_PNP,
\r
2035 ("WARNING: Device reports support for system wake.\n"));
\r
2036 pCaps->SystemWake = PowerSystemUnspecified;
\r
2039 if( pCaps->DeviceWake != PowerDeviceUnspecified )
\r
2041 HCA_PRINT( TRACE_LEVEL_WARNING, HCA_DBG_PNP,
\r
2042 ("WARNING: Device reports support for device wake.\n"));
\r
2043 pCaps->DeviceWake = PowerDeviceUnspecified;
\r
2046 HCA_EXIT( HCA_DBG_PNP );
\r
2052 hca_query_pnp_state(
\r
2053 IN DEVICE_OBJECT* const p_dev_obj,
\r
2054 IN IRP* const p_irp,
\r
2055 OUT cl_irp_action_t* const p_action )
\r
2057 PFDO_DEVICE_DATA p_fdo;
\r
2059 HCA_ENTER( HCA_DBG_PNP );
\r
2061 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
2063 p_irp->IoStatus.Information |= p_fdo->pnpState;
\r
2065 *p_action = IrpSkip;
\r
2067 HCA_EXIT( HCA_DBG_PNP );
\r
2068 return STATUS_SUCCESS;;
\r
2073 IN DEVICE_OBJECT* const p_dev_obj,
\r
2074 IN IRP* const p_irp,
\r
2075 OUT cl_irp_action_t* const p_action )
\r
2077 NTSTATUS status = STATUS_SUCCESS;
\r
2078 IO_STACK_LOCATION *pIoStack;
\r
2080 HCA_ENTER(HCA_DBG_PO);
\r
2082 UNUSED_PARAM( p_dev_obj );
\r
2084 pIoStack = IoGetCurrentIrpStackLocation( p_irp );
\r
2086 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO,
\r
2087 ("QUERY_POWER for FDO %p: type %s, state %d, action %d, IRQL %d, IRP %p\n",
\r
2089 (pIoStack->Parameters.Power.Type) ? "DevicePowerState" : "SystemPowerState",
\r
2090 pIoStack->Parameters.Power.State.DeviceState,
\r
2091 pIoStack->Parameters.Power.ShutdownType, KeGetCurrentIrql(), p_irp ));
\r
2093 switch( pIoStack->Parameters.Power.Type )
\r
2095 case SystemPowerState:
\r
2096 /* Fail any requests to hibernate or sleep the system. */
\r
2097 switch( pIoStack->Parameters.Power.State.SystemState )
\r
2099 case PowerSystemSleeping1: // STANDBY support
\r
2100 case PowerSystemHibernate:
\r
2102 PFDO_DEVICE_DATA p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
2103 if (atomic_read(&p_fdo->usecnt))
\r
2104 status = STATUS_UNSUCCESSFUL;
\r
2108 case PowerSystemWorking:
\r
2109 case PowerSystemShutdown:
\r
2113 status = STATUS_NOT_SUPPORTED;
\r
2117 case DevicePowerState:
\r
2118 /* Fail any query for low power states. */
\r
2119 switch( pIoStack->Parameters.Power.State.DeviceState )
\r
2121 case PowerDeviceD0:
\r
2122 case PowerDeviceD3:
\r
2123 /* We only support fully powered or off power states. */
\r
2127 status = STATUS_NOT_SUPPORTED;
\r
2132 if( status == STATUS_SUCCESS )
\r
2133 *p_action = IrpSkip;
\r
2135 *p_action = IrpComplete;
\r
2137 HCA_EXIT( HCA_DBG_PO );
\r
2143 __RequestPowerCompletion(
\r
2144 IN DEVICE_OBJECT *p_dev_obj,
\r
2145 IN UCHAR minorFunction,
\r
2146 IN POWER_STATE powerState,
\r
2148 IN IO_STATUS_BLOCK *pIoStatus )
\r
2151 cl_pnp_po_ext_t *p_fdo;
\r
2153 HCA_ENTER( HCA_DBG_PO );
\r
2155 UNUSED_PARAM( minorFunction );
\r
2156 UNUSED_PARAM( powerState );
\r
2158 p_irp = (IRP*)context;
\r
2159 p_fdo = (cl_pnp_po_ext_t*)p_dev_obj->DeviceExtension;
\r
2161 /* Propagate the device IRP status to the system IRP status. */
\r
2162 p_irp->IoStatus.Status = pIoStatus->Status;
\r
2164 /* Continue Power IRP processing. */
\r
2165 PoStartNextPowerIrp( p_irp );
\r
2166 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
2167 IoReleaseRemoveLock( &p_fdo->remove_lock, p_irp );
\r
2168 HCA_EXIT( HCA_DBG_PO );
\r
2172 /*NOTE: Completion routines must NEVER be pageable. */
\r
2174 __SystemPowerCompletion(
\r
2175 IN DEVICE_OBJECT *p_dev_obj,
\r
2177 IN void *context )
\r
2180 POWER_STATE state;
\r
2181 PFDO_DEVICE_DATA p_fdo;
\r
2182 IO_STACK_LOCATION *pIoStack;
\r
2184 HCA_ENTER( HCA_DBG_PO );
\r
2186 UNUSED_PARAM( context );
\r
2188 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
2189 pIoStack = IoGetCurrentIrpStackLocation( p_irp );
\r
2191 if( !NT_SUCCESS( p_irp->IoStatus.Status ) )
\r
2193 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PO,
\r
2194 ("IRP_MN_SET_POWER for system failed by lower driver with %08x.\n",
\r
2195 p_irp->IoStatus.Status));
\r
2196 status = STATUS_SUCCESS;
\r
2197 PoStartNextPowerIrp( p_irp );
\r
2201 state.DeviceState =
\r
2202 p_fdo->DevicePower[pIoStack->Parameters.Power.State.SystemState];
\r
2205 * Send a device power IRP to our devnode. Using our device object will
\r
2206 * only work on win2k and other NT based systems.
\r
2208 status = PoRequestPowerIrp( p_dev_obj, IRP_MN_SET_POWER, state,
\r
2209 __RequestPowerCompletion, p_irp, NULL );
\r
2211 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO,
\r
2212 ("PoRequestPowerIrp: SET_POWER 'PowerDeviceD%d', status %#x\n",
\r
2213 state.DeviceState - 1, status ));
\r
2215 if( status != STATUS_PENDING ) {
\r
2216 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PO,
\r
2217 ("PoRequestPowerIrp returned %08x.\n", status));
\r
2218 p_irp->IoStatus.Status = status; /* Propagate the failure. */
\r
2219 PoStartNextPowerIrp( p_irp );
\r
2220 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
2224 status = STATUS_MORE_PROCESSING_REQUIRED;
\r
2228 IoReleaseRemoveLock( &p_fdo->cl_ext.remove_lock, p_irp );
\r
2230 HCA_EXIT( HCA_DBG_PO );
\r
2235 /* Work item callback to handle DevicePowerD0 IRPs at passive level. */
\r
2237 __DevicePowerUpCompletionWorkItem(
\r
2238 IN DEVICE_OBJECT* p_dev_obj,
\r
2239 IN void* context )
\r
2243 IO_STACK_LOCATION *pIoStack;
\r
2244 PFDO_DEVICE_DATA p_fdo;
\r
2246 POWER_STATE powerState;
\r
2248 HCA_ENTER( HCA_DBG_PO );
\r
2250 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
2251 p_irp = (IRP*)context;
\r
2252 pIoStack = IoGetCurrentIrpStackLocation( p_irp );
\r
2254 IoFreeWorkItem( p_fdo->pPoWorkItem );
\r
2255 p_fdo->pPoWorkItem = NULL;
\r
2257 /* restart the HCA */
\r
2258 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO,
\r
2259 ("***** Restart the HCA, IRQL %d\n", KeGetCurrentIrql()));
\r
2261 /* get MLX4_BUS IB interface */
\r
2262 status = __get_ifc( p_dev_obj, &MLX4_BUS_IB_INTERFACE_GUID,
\r
2263 sizeof(MLX4_BUS_IB_INTERFACE), MLX4_BUS_IB_INTERFACE_VERSION, NULL, (PINTERFACE)&p_fdo->bus_ib_ifc);
\r
2264 if( !NT_SUCCESS( status ) ) {
\r
2265 HCA_PRINT(TRACE_LEVEL_ERROR, HCA_DBG_PNP, ("Getting MLX4 BUS interface failed: status=0x%x\n", status));
\r
2268 p_fdo->bus_ib_ifc_taken = TRUE;
\r
2269 p_fdo->bus_ib_ifc.p_ibdev->x.p_fdo = p_fdo;
\r
2271 /* get node GUID */
\r
2272 err = __get_dev_info( p_fdo, &p_fdo->hca.guid, &p_fdo->hca.hw_ver );
\r
2275 HCA_PRINT(TRACE_LEVEL_ERROR ,HCA_DBG_LOW ,
\r
2276 ("can't get guid - ib_query_device() failed (%08X)\n", err ));
\r
2277 //TODO: no cleanup on error
\r
2281 if( p_fdo->p_al_dev ) {
\r
2282 status = __hca_register( p_dev_obj );
\r
2283 if( !NT_SUCCESS( status ) ) {
\r
2284 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PO,
\r
2285 ("!!! __hca_register failed (%#x) \n", status));
\r
2290 p_fdo->DevicePowerState = pIoStack->Parameters.Power.State.DeviceState;
\r
2291 powerState = PoSetPowerState( p_dev_obj, DevicePowerState,
\r
2292 pIoStack->Parameters.Power.State );
\r
2294 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO,
\r
2295 ("PoSetPowerState: old state %d, new state to %d\n",
\r
2296 powerState.DeviceState, p_fdo->DevicePowerState ));
\r
2301 /* Flag device as having failed. */
\r
2302 p_fdo->pnpState |= PNP_DEVICE_FAILED;
\r
2303 IoInvalidateDeviceState( p_fdo->cl_ext.p_pdo );
\r
2305 PoStartNextPowerIrp( p_irp );
\r
2306 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
2307 IoReleaseRemoveLock( &p_fdo->cl_ext.remove_lock, p_irp );
\r
2308 HCA_EXIT( HCA_DBG_PO );
\r
2311 /*NOTE: Completion routines must NEVER be pageable. */
\r
2313 __DevicePowerUpCompletion(
\r
2314 IN DEVICE_OBJECT *p_dev_obj,
\r
2316 IN void *context )
\r
2318 NTSTATUS status = STATUS_SUCCESS;
\r
2319 PFDO_DEVICE_DATA p_fdo;
\r
2320 IO_STACK_LOCATION *pIoStack;
\r
2322 HCA_ENTER( HCA_DBG_PO );
\r
2324 UNUSED_PARAM( context );
\r
2326 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
2327 pIoStack = IoGetCurrentIrpStackLocation( p_irp );
\r
2329 if( !NT_SUCCESS( p_irp->IoStatus.Status ) ) {
\r
2330 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PO,
\r
2331 ("IRP_MN_SET_POWER for device failed by lower driver with %08x.\n",
\r
2332 p_irp->IoStatus.Status));
\r
2333 status = STATUS_SUCCESS;
\r
2334 PoStartNextPowerIrp( p_irp );
\r
2338 /* Process in a work item - mthca_start blocks. */
\r
2339 ASSERT( !p_fdo->pPoWorkItem );
\r
2340 p_fdo->pPoWorkItem = IoAllocateWorkItem( p_dev_obj );
\r
2341 if( !p_fdo->pPoWorkItem ) {
\r
2342 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PO,
\r
2343 ("Failed to allocate work item.\n" ));
\r
2344 status = STATUS_SUCCESS;
\r
2345 p_fdo->pnpState |= PNP_DEVICE_FAILED;
\r
2346 IoInvalidateDeviceState( p_fdo->cl_ext.p_pdo );
\r
2347 PoStartNextPowerIrp( p_irp );
\r
2351 /* Process in work item callback. */
\r
2352 IoMarkIrpPending( p_irp );
\r
2353 IoQueueWorkItem( p_fdo->pPoWorkItem,
\r
2354 __DevicePowerUpCompletionWorkItem, DelayedWorkQueue, p_irp );
\r
2355 status = STATUS_MORE_PROCESSING_REQUIRED;
\r
2359 IoReleaseRemoveLock( &p_fdo->cl_ext.remove_lock, p_irp );
\r
2361 HCA_EXIT( HCA_DBG_PO );
\r
2365 static NTSTATUS __DevicePowerDownWorkItemCompletion(
\r
2366 IN DEVICE_OBJECT *p_dev_obj,
\r
2368 IN void *context )
\r
2370 PFDO_DEVICE_DATA p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
2371 UNUSED_PARAM( context );
\r
2373 HCA_ENTER( HCA_DBG_PO );
\r
2375 PoStartNextPowerIrp( p_irp );
\r
2376 IoReleaseRemoveLock( &p_fdo->cl_ext.remove_lock, p_irp );
\r
2378 HCA_EXIT( HCA_DBG_PO );
\r
2379 return STATUS_SUCCESS;
\r
2382 /* Work item callback to handle DevicePowerD3 IRPs at passive level. */
\r
2384 __DevicePowerDownWorkItem(
\r
2385 IN DEVICE_OBJECT* p_dev_obj,
\r
2386 IN void* context )
\r
2388 IO_STACK_LOCATION *pIoStack;
\r
2389 PFDO_DEVICE_DATA p_fdo;
\r
2391 POWER_STATE powerState;
\r
2393 HCA_ENTER( HCA_DBG_PO );
\r
2395 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
2396 p_irp = (IRP*)context;
\r
2397 pIoStack = IoGetCurrentIrpStackLocation( p_irp );
\r
2399 IoFreeWorkItem( p_fdo->pPoWorkItem );
\r
2400 p_fdo->pPoWorkItem = NULL;
\r
2402 p_fdo->DevicePowerState = pIoStack->Parameters.Power.State.DeviceState;
\r
2403 powerState = PoSetPowerState( p_dev_obj, DevicePowerState,
\r
2404 pIoStack->Parameters.Power.State );
\r
2406 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO,
\r
2407 ("PoSetPowerState: old state %d, new state to %d, IRQL %d\n",
\r
2408 powerState.DeviceState, p_fdo->DevicePowerState, KeGetCurrentIrql() ));
\r
2410 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO,
\r
2411 ("***** Remove the HCA \n"));
\r
2414 __hca_deregister( p_fdo );
\r
2416 // release MLX4_BUS resources
\r
2417 if(p_fdo->bus_ib_ifc_taken) {
\r
2418 p_fdo->bus_ib_ifc_taken = FALSE;
\r
2419 __put_ifc( (PINTERFACE)&p_fdo->bus_ib_ifc );
\r
2423 IoCopyCurrentIrpStackLocationToNext( p_irp );
\r
2424 #pragma warning( push, 3 )
\r
2425 IoSetCompletionRoutine( p_irp, __DevicePowerDownWorkItemCompletion,
\r
2426 NULL, TRUE, TRUE, TRUE );
\r
2427 #pragma warning( pop )
\r
2428 PoCallDriver( p_fdo->cl_ext.p_next_do, p_irp );
\r
2430 HCA_EXIT( HCA_DBG_PO );
\r
2436 IN DEVICE_OBJECT* const p_dev_obj,
\r
2437 IN IRP* const p_irp,
\r
2438 OUT cl_irp_action_t* const p_action )
\r
2441 IO_STACK_LOCATION *pIoStack;
\r
2442 PFDO_DEVICE_DATA p_fdo;
\r
2444 HCA_ENTER( HCA_DBG_PO );
\r
2446 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
2447 pIoStack = IoGetCurrentIrpStackLocation( p_irp );
\r
2449 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO,
\r
2450 ("SET_POWER for FDO %p (ext %p): type %s, state %d, action %d, IRQL %d \n",
\r
2452 (pIoStack->Parameters.Power.Type) ? "DevicePowerState" : "SystemPowerState",
\r
2453 pIoStack->Parameters.Power.State.DeviceState,
\r
2454 pIoStack->Parameters.Power.ShutdownType, KeGetCurrentIrql() ));
\r
2456 switch( pIoStack->Parameters.Power.Type )
\r
2458 case SystemPowerState:
\r
2459 p_fdo->SystemPowerState = pIoStack->Parameters.Power.State.SystemState;
\r
2462 * Process on the way up the stack. We cannot block since the
\r
2463 * power dispatch function can be called at elevated IRQL if the
\r
2464 * device is in a paging/hibernation/crash dump path.
\r
2466 IoMarkIrpPending( p_irp );
\r
2467 IoCopyCurrentIrpStackLocationToNext( p_irp );
\r
2468 #pragma warning( push, 3 )
\r
2469 IoSetCompletionRoutine( p_irp, __SystemPowerCompletion, NULL,
\r
2470 TRUE, TRUE, TRUE );
\r
2471 #pragma warning( pop )
\r
2472 PoCallDriver( p_fdo->cl_ext.p_next_do, p_irp );
\r
2474 *p_action = IrpDoNothing;
\r
2475 status = STATUS_PENDING;
\r
2478 case DevicePowerState:
\r
2479 IoMarkIrpPending( p_irp );
\r
2480 if( pIoStack->Parameters.Power.State.DeviceState == PowerDeviceD0 &&
\r
2481 p_fdo->SystemPowerState == PowerSystemWorking)
\r
2483 /* If we're already powered up, just pass down. */
\r
2484 if( p_fdo->DevicePowerState == PowerDeviceD0 )
\r
2486 status = STATUS_SUCCESS;
\r
2487 *p_action = IrpIgnore;
\r
2491 /* Process in I/O completion callback. */
\r
2492 IoCopyCurrentIrpStackLocationToNext( p_irp );
\r
2493 #pragma warning( push, 3 )
\r
2494 IoSetCompletionRoutine( p_irp, __DevicePowerUpCompletion, NULL,
\r
2495 TRUE, TRUE, TRUE );
\r
2496 #pragma warning( pop )
\r
2497 PoCallDriver( p_fdo->cl_ext.p_next_do, p_irp );
\r
2500 { /* power down */
\r
2502 /* Process in a work item - deregister_ca and HcaDeinit block. */
\r
2503 ASSERT( !p_fdo->pPoWorkItem );
\r
2504 p_fdo->pPoWorkItem = IoAllocateWorkItem( p_dev_obj );
\r
2505 if( !p_fdo->pPoWorkItem )
\r
2507 status = STATUS_INSUFFICIENT_RESOURCES;
\r
2511 /* Process in work item callback. */
\r
2513 p_fdo->pPoWorkItem, __DevicePowerDownWorkItem, DelayedWorkQueue, p_irp );
\r
2515 *p_action = IrpDoNothing;
\r
2516 status = STATUS_PENDING;
\r
2520 /* Pass down and let the PDO driver handle it. */
\r
2521 *p_action = IrpIgnore;
\r
2522 status = STATUS_SUCCESS;
\r
2526 if( !NT_SUCCESS( status ) )
\r
2527 *p_action = IrpComplete;
\r
2529 HCA_EXIT( HCA_DBG_PNP );
\r
2534 hca_init_vfptr( void )
\r
2536 vfptrHcaPnp.identity = "MLX4_HCA driver";
\r
2537 vfptrHcaPnp.pfn_start = hca_start;
\r
2538 vfptrHcaPnp.pfn_query_stop = hca_query_stop;
\r
2539 vfptrHcaPnp.pfn_stop = hca_stop;
\r
2540 vfptrHcaPnp.pfn_cancel_stop = hca_cancel_stop;
\r
2541 vfptrHcaPnp.pfn_query_remove = hca_query_remove;
\r
2542 vfptrHcaPnp.pfn_release_resources = hca_release_resources;
\r
2543 vfptrHcaPnp.pfn_remove = cl_do_remove;
\r
2544 vfptrHcaPnp.pfn_cancel_remove = hca_cancel_remove;
\r
2545 vfptrHcaPnp.pfn_surprise_remove = hca_surprise_remove;
\r
2546 vfptrHcaPnp.pfn_query_capabilities = hca_query_capabilities;
\r
2547 vfptrHcaPnp.pfn_query_pnp_state = hca_query_pnp_state;
\r
2548 vfptrHcaPnp.pfn_filter_res_req = cl_irp_skip;
\r
2549 vfptrHcaPnp.pfn_dev_usage_notification = cl_do_sync_pnp;
\r
2550 vfptrHcaPnp.pfn_query_bus_relations = hca_query_bus_relations;
\r
2551 vfptrHcaPnp.pfn_query_ejection_relations = cl_irp_ignore;
\r
2552 vfptrHcaPnp.pfn_query_removal_relations = hca_query_removal_relations;
\r
2553 vfptrHcaPnp.pfn_query_target_relations = cl_irp_ignore;
\r
2554 vfptrHcaPnp.pfn_unknown = cl_irp_ignore;
\r
2555 vfptrHcaPnp.pfn_query_resources = cl_irp_ignore;
\r
2556 vfptrHcaPnp.pfn_query_res_req = cl_irp_ignore;
\r
2557 vfptrHcaPnp.pfn_query_bus_info = cl_irp_ignore;
\r
2558 vfptrHcaPnp.pfn_query_interface = cl_irp_ignore;
\r
2559 vfptrHcaPnp.pfn_read_config = cl_irp_ignore;
\r
2560 vfptrHcaPnp.pfn_write_config = cl_irp_ignore;
\r
2561 vfptrHcaPnp.pfn_eject = cl_irp_ignore;
\r
2562 vfptrHcaPnp.pfn_set_lock = cl_irp_ignore;
\r
2563 vfptrHcaPnp.pfn_query_power = hca_query_power;
\r
2564 vfptrHcaPnp.pfn_set_power = hca_set_power;
\r
2565 vfptrHcaPnp.pfn_power_sequence = cl_irp_ignore;
\r
2566 vfptrHcaPnp.pfn_wait_wake = cl_irp_ignore;
\r
2571 IN UNICODE_STRING* const p_registry_path )
\r
2574 /* Remember the terminating entry in the table below. */
\r
2575 RTL_QUERY_REGISTRY_TABLE table[3];
\r
2577 HCA_ENTER( HCA_DBG_PNP );
\r
2579 RtlInitUnicodeString( &g_param_path, NULL );
\r
2580 g_param_path.MaximumLength = p_registry_path->Length +
\r
2581 sizeof(L"\\Parameters");
\r
2582 g_param_path.Buffer = cl_zalloc( g_param_path.MaximumLength );
\r
2583 if( !g_param_path.Buffer )
\r
2585 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
2586 ("Failed to allocate parameters path buffer.\n"));
\r
2587 return STATUS_INSUFFICIENT_RESOURCES;
\r
2590 RtlAppendUnicodeStringToString( &g_param_path, p_registry_path );
\r
2591 RtlAppendUnicodeToString( &g_param_path, L"\\Parameters" );
\r
2594 * Clear the table. This clears all the query callback pointers,
\r
2595 * and sets up the terminating table entry.
\r
2597 cl_memclr( table, sizeof(table) );
\r
2599 /* Setup the table entries. */
\r
2600 table[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
2601 table[0].Name = L"DebugLevel";
\r
2602 table[0].EntryContext = &g.DebugPrintLevel;
\r
2603 table[0].DefaultType = REG_DWORD;
\r
2604 table[0].DefaultData = &g.DebugPrintLevel;
\r
2605 table[0].DefaultLength = sizeof(ULONG);
\r
2608 table[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
2609 table[1].Name = L"DebugFlags";
\r
2610 table[1].EntryContext = &g.DebugPrintFlags;
\r
2611 table[1].DefaultType = REG_DWORD;
\r
2612 table[1].DefaultData = &g.DebugPrintFlags;
\r
2613 table[1].DefaultLength = sizeof(ULONG);
\r
2617 status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE,
\r
2618 g_param_path.Buffer, table, NULL, NULL );
\r
2620 HCA_EXIT( HCA_DBG_PNP );
\r
2626 IN PDRIVER_OBJECT p_driver_obj )
\r
2628 HCA_ENTER( HCA_DBG_PNP );
\r
2630 UNUSED_PARAM( p_driver_obj );
\r
2632 cl_free( g_param_path.Buffer );
\r
2634 HCA_EXIT( HCA_DBG_PNP );
\r
2635 #if defined(EVENT_TRACING)
\r
2636 WPP_CLEANUP(p_driver_obj);
\r
2643 IN PDEVICE_OBJECT p_dev_obj,
\r
2647 PFDO_DEVICE_DATA p_fdo;
\r
2649 HCA_ENTER( HCA_DBG_PNP );
\r
2651 p_fdo = p_dev_obj->DeviceExtension;
\r
2653 IoSkipCurrentIrpStackLocation( p_irp );
\r
2654 status = IoCallDriver( p_fdo->cl_ext.p_next_do, p_irp );
\r
2656 HCA_EXIT( HCA_DBG_PNP );
\r
2663 IN PDRIVER_OBJECT p_driver_obj,
\r
2664 IN PUNICODE_STRING p_registry_path )
\r
2667 #if defined(EVENT_TRACING)
\r
2668 WPP_INIT_TRACING(p_driver_obj ,p_registry_path);
\r
2670 // global initializations
\r
2671 g.DebugPrintLevel = TRACE_LEVEL_VERBOSE;
\r
2672 g.DebugPrintFlags = 0xffff;
\r
2674 HCA_ENTER( HCA_DBG_PNP );
\r
2675 HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_PNP,
\r
2676 ("Built %s %s, Version %s, RelDate %s\n",
\r
2677 __DATE__, __TIME__, DRV_VERSION, DRV_RELDATE));
\r
2679 status = mlnx_hcas_init();
\r
2680 if( status != STATUS_SUCCESS ) {
\r
2681 HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_PNP ,
\r
2682 ("mlnx_hcas_init returned %#x.\n", status));
\r
2686 status = __read_registry( p_registry_path );
\r
2687 if( !NT_SUCCESS( status ) )
\r
2689 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
2690 ("__read_registry_path returned 0x%X.\n", status));
\r
2694 /*leo: init function table */
\r
2697 p_driver_obj->MajorFunction[IRP_MJ_PNP] = cl_pnp;
\r
2698 p_driver_obj->MajorFunction[IRP_MJ_POWER] = cl_power;
\r
2699 p_driver_obj->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = hca_sysctl;
\r
2700 p_driver_obj->DriverUnload = hca_drv_unload;
\r
2701 p_driver_obj->DriverExtension->AddDevice = hca_add_device;
\r
2704 HCA_EXIT( HCA_DBG_PNP );
\r
2705 return STATUS_SUCCESS;
\r