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
36 #include <rdma\verbs.h>
\r
38 #if defined(EVENT_TRACING)
\r
45 #define DRV_VERSION "1.0"
\r
46 #define DRV_RELDATE "02/01/2008"
\r
51 * UVP name does not include file extension. For debug builds, UAL
\r
52 * will append "d.dll". For release builds, UAL will append ".dll"
\r
54 char mlnx_uvp_lib_name[MAX_LIB_NAME] = {"mlx4u"};
\r
59 IN PINTERFACE p_ifc )
\r
61 HCA_ENTER( HCA_DBG_PNP );
\r
62 p_ifc->InterfaceDereference( p_ifc->Context );
\r
63 HCA_EXIT( HCA_DBG_PNP );
\r
66 static int __get_dev_info(PFDO_DEVICE_DATA p_fdo, __be64 *node_guid, u32 *hw_id)
\r
68 struct ib_device_attr device_attr;
\r
69 struct ib_device *p_ibdev = p_fdo->bus_ib_ifc.p_ibdev;
\r
72 HCA_ENTER( HCA_DBG_PNP );
\r
73 if ( hca_is_livefish(p_fdo) ) {
\r
74 *node_guid = cl_hton64((uint64_t)(ULONG_PTR)p_ibdev);
\r
75 p_ibdev->node_guid = *node_guid;
\r
80 err = (p_ibdev->query_device)( p_ibdev, &device_attr );
\r
84 *node_guid = p_ibdev->node_guid;
\r
85 *hw_id = device_attr.hw_ver;
\r
86 HCA_EXIT( HCA_DBG_PNP );
\r
90 #ifndef USE_WDM_FRAMEWORK
\r
93 // TODO: add support for Hibernate/Standby as in WDM version below
\r
99 IN PFDO_DEVICE_DATA p_fdo )
\r
103 IO_STATUS_BLOCK ioStatus;
\r
104 IO_STACK_LOCATION *pIoStack;
\r
107 HCA_ENTER( HCA_DBG_PNP );
\r
109 KeInitializeEvent( &event, NotificationEvent, FALSE );
\r
111 /* Query for the verbs interface. */
\r
112 p_irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, p_fdo->p_al_dev,
\r
113 NULL, 0, NULL, &event, &ioStatus );
\r
116 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
117 ("IoBuildSynchronousFsdRequest failed.\n"));
\r
118 return STATUS_INSUFFICIENT_RESOURCES;
\r
121 /* Format the IRP. */
\r
122 pIoStack = IoGetNextIrpStackLocation( p_irp );
\r
123 pIoStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
\r
124 pIoStack->Parameters.QueryInterface.Version = IB_CI_INTERFACE_VERSION;
\r
125 pIoStack->Parameters.QueryInterface.Size = sizeof(ib_ci_ifc_t);
\r
126 pIoStack->Parameters.QueryInterface.Interface =
\r
127 (INTERFACE*)&p_fdo->ci_ifc;
\r
128 pIoStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
\r
129 pIoStack->Parameters.QueryInterface.InterfaceType =
\r
130 &GUID_IB_CI_INTERFACE;
\r
131 p_irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
\r
133 /* Send the IRP. */
\r
134 status = IoCallDriver( p_fdo->p_al_dev, p_irp );
\r
135 if( status == STATUS_PENDING )
\r
137 KeWaitForSingleObject( &event, Executive, KernelMode,
\r
140 status = ioStatus.Status;
\r
143 if( !NT_SUCCESS( status ) )
\r
145 HCA_PRINT( TRACE_LEVEL_ERROR,HCA_DBG_PNP,
\r
146 ("Query interface for verbs returned %08x.\n", status));
\r
150 HCA_EXIT( HCA_DBG_PNP );
\r
156 __pnp_notify_target(
\r
157 IN void *pNotifyStruct,
\r
160 NTSTATUS status = STATUS_SUCCESS;
\r
161 PFDO_DEVICE_DATA p_fdo = context;
\r
162 PDEVICE_OBJECT p_dev_obj = WdfDeviceWdmGetDeviceObject(p_fdo->FdoDevice);
\r
163 TARGET_DEVICE_REMOVAL_NOTIFICATION *pNotify;
\r
165 HCA_ENTER( HCA_DBG_PNP );
\r
167 pNotify = (TARGET_DEVICE_REMOVAL_NOTIFICATION*)pNotifyStruct;
\r
169 if( IsEqualGUID( &pNotify->Event, &GUID_TARGET_DEVICE_QUERY_REMOVE ) )
\r
171 if ( p_fdo->state == HCA_REGISTERED) {
\r
172 /* Release AL's CI interface. */
\r
173 p_fdo->ci_ifc.wdm.InterfaceDereference( p_fdo->ci_ifc.wdm.Context );
\r
174 p_fdo->state = HCA_IFC_DEREFERENCED;
\r
177 /* Release AL's file object so that it can unload. */
\r
178 CL_ASSERT( p_fdo->p_al_dev );
\r
179 CL_ASSERT( p_fdo->p_al_file_obj );
\r
180 CL_ASSERT( p_fdo->p_al_file_obj == pNotify->FileObject );
\r
181 if( p_fdo->p_al_file_obj ) {
\r
182 ObDereferenceObject( p_fdo->p_al_file_obj );
\r
183 p_fdo->p_al_file_obj = NULL;
\r
184 p_fdo->p_al_dev = NULL;
\r
187 else if( IsEqualGUID( &pNotify->Event,
\r
188 &GUID_TARGET_DEVICE_REMOVE_COMPLETE ) )
\r
190 if (p_fdo->ci_ifc.deregister_ca) {
\r
191 /* Notify AL that the CA is being removed. */
\r
192 p_fdo->ci_ifc.deregister_ca( p_fdo->hca.guid );
\r
193 p_fdo->ci_ifc.deregister_ca = NULL;
\r
196 if ( p_fdo->state == HCA_REGISTERED) {
\r
197 /* Release AL's CI interface. */
\r
198 p_fdo->ci_ifc.wdm.InterfaceDereference( p_fdo->ci_ifc.wdm.Context );
\r
200 p_fdo->state = HCA_STARTED;
\r
202 /* Release AL's file object so that it can unload. */
\r
203 if( p_fdo->p_al_file_obj )
\r
205 ObDereferenceObject( p_fdo->p_al_file_obj );
\r
206 p_fdo->p_al_file_obj = NULL;
\r
207 p_fdo->p_al_dev = NULL;
\r
210 /* Cancel our target device change registration. */
\r
211 if (p_fdo->pnp_target_entry) {
\r
212 IoUnregisterPlugPlayNotification( p_fdo->pnp_target_entry );
\r
213 p_fdo->pnp_target_entry = NULL;
\r
217 else if( IsEqualGUID( &pNotify->Event,
\r
218 &GUID_TARGET_DEVICE_REMOVE_CANCELLED ) )
\r
220 /* Cancel our target device change registration. */
\r
221 if (p_fdo->pnp_target_entry) {
\r
222 IoUnregisterPlugPlayNotification( p_fdo->pnp_target_entry );
\r
223 p_fdo->pnp_target_entry = NULL;
\r
226 /* Get the device object pointer for the AL. */
\r
227 CL_ASSERT( !p_fdo->p_al_file_obj );
\r
228 CL_ASSERT( !p_fdo->p_al_dev );
\r
229 /* Get the AL device object. */
\r
230 HCA_PRINT( TRACE_LEVEL_INFORMATION ,HCA_DBG_SHIM ,("Calling IoGetDeviceObjectPointer.\n"));
\r
231 status = IoGetDeviceObjectPointer( &p_fdo->al_sym_name,
\r
232 FILE_ALL_ACCESS, &p_fdo->p_al_file_obj, &p_fdo->p_al_dev );
\r
233 if( !NT_SUCCESS( status ) )
\r
235 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_SHIM,
\r
236 ("IoGetDeviceObjectPointer returned %08x.\n", status ));
\r
237 return STATUS_SUCCESS;
\r
240 /* Register for removal notification of the IB Fabric root device. */
\r
241 status = IoRegisterPlugPlayNotification(
\r
242 EventCategoryTargetDeviceChange, 0, p_fdo->p_al_file_obj,
\r
243 p_dev_obj->DriverObject, __pnp_notify_target, p_fdo,
\r
244 &p_fdo->pnp_target_entry );
\r
245 if( !NT_SUCCESS( status ) )
\r
247 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
248 ("IoRegisterPlugPlayNotification returned %08x.\n", status));
\r
252 CL_ASSERT( p_fdo->state == HCA_IFC_DEREFERENCED );
\r
253 if ( p_fdo->state == HCA_IFC_DEREFERENCED) {
\r
254 /* Release AL's CI interface. */
\r
255 p_fdo->ci_ifc.wdm.InterfaceReference( p_fdo->ci_ifc.wdm.Context );
\r
256 p_fdo->state = HCA_REGISTERED;
\r
260 HCA_EXIT( HCA_DBG_PNP );
\r
265 static ci_interface_t*
\r
267 IN PFDO_DEVICE_DATA const p_fdo )
\r
269 ci_interface_t *pIfc;
\r
271 HCA_ENTER( HCA_DBG_PNP );
\r
274 (ci_interface_t*)ExAllocatePoolWithTag( PagedPool, sizeof(ci_interface_t), MT_TAG_KERNEL );
\r
277 HCA_PRINT( TRACE_LEVEL_ERROR,HCA_DBG_PNP,
\r
278 ("Failed to allocate ci_interface_t (%d bytes).\n",
\r
279 sizeof(ci_interface_t)));
\r
283 setup_ci_interface( p_fdo->hca.guid, !!hca_is_livefish(p_fdo), pIfc );
\r
285 pIfc->p_hca_dev = WdfDeviceWdmGetPhysicalDevice(p_fdo->FdoDevice);
\r
286 ASSERT(pIfc->p_hca_dev);
\r
287 pIfc->vend_id = (uint32_t)p_fdo->bus_ib_ifc.pdev->ven_id;
\r
288 pIfc->dev_id = (uint16_t)p_fdo->bus_ib_ifc.pdev->dev_id;
\r
289 pIfc->dev_revision = (uint16_t)p_fdo->hca.hw_ver;
\r
291 HCA_EXIT( HCA_DBG_PNP );
\r
297 IN PFDO_DEVICE_DATA p_fdo )
\r
299 HCA_ENTER( HCA_DBG_PNP );
\r
301 if ( p_fdo->state == HCA_REGISTERED) {
\r
302 if (p_fdo->ci_ifc.deregister_ca) {
\r
303 /* Notify AL that the CA is being removed. */
\r
304 p_fdo->ci_ifc.deregister_ca( p_fdo->hca.guid );
\r
305 p_fdo->ci_ifc.deregister_ca = NULL;
\r
306 /* Release AL's CI interface. */
\r
307 p_fdo->ci_ifc.wdm.InterfaceDereference( p_fdo->ci_ifc.wdm.Context );
\r
308 p_fdo->state = HCA_STARTED;
\r
309 HCA_PRINT( TRACE_LEVEL_INFORMATION ,HCA_DBG_PNP,
\r
310 ("***** HCA deregistered \n"));
\r
314 HCA_EXIT( HCA_DBG_PNP );
\r
319 IN PFDO_DEVICE_DATA p_fdo )
\r
322 ib_api_status_t ib_status;
\r
323 ci_interface_t *p_hca_ifc;
\r
325 HCA_ENTER( HCA_DBG_PNP );
\r
327 ASSERT( p_fdo->state == HCA_STARTED );
\r
328 ASSERT( p_fdo->p_al_dev );
\r
330 /* Get the AL's lower interface. */
\r
331 status = __get_ci_interface( p_fdo );
\r
332 if( !NT_SUCCESS( status ) )
\r
334 HCA_PRINT( TRACE_LEVEL_ERROR,HCA_DBG_PNP,
\r
335 ("__get_ci_interface returned %08x.\n", status));
\r
339 /* Allocate and populate our HCA interface structure. */
\r
340 p_hca_ifc = __alloc_hca_ifc( p_fdo );
\r
343 HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_PNP ,("__alloc_hca_ifc failed.\n"));
\r
344 status = STATUS_NO_MEMORY;
\r
348 /* Notify AL that we're available... */
\r
349 ib_status = p_fdo->ci_ifc.register_ca( p_hca_ifc );
\r
350 ExFreePool( p_hca_ifc );
\r
351 if( ib_status != IB_SUCCESS )
\r
353 p_fdo->ci_ifc.wdm.InterfaceDereference( p_fdo->ci_ifc.wdm.Context );
\r
354 status = STATUS_INSUFFICIENT_RESOURCES;
\r
358 p_fdo->state = HCA_REGISTERED;
\r
359 HCA_PRINT( TRACE_LEVEL_INFORMATION ,HCA_DBG_PNP,
\r
360 ("***** HCA registered \n"));
\r
362 HCA_EXIT( HCA_DBG_PNP );
\r
368 IN void *pNotifyStruct,
\r
371 NTSTATUS status = STATUS_SUCCESS;
\r
372 DEVICE_INTERFACE_CHANGE_NOTIFICATION *pNotify;
\r
373 PFDO_DEVICE_DATA p_fdo = context;
\r
374 PDEVICE_OBJECT p_dev_obj = WdfDeviceWdmGetDeviceObject(p_fdo->FdoDevice);
\r
376 HCA_ENTER( HCA_DBG_PNP );
\r
378 pNotify = (DEVICE_INTERFACE_CHANGE_NOTIFICATION*)pNotifyStruct;
\r
380 if( !IsEqualGUID( &pNotify->Event, &GUID_DEVICE_INTERFACE_ARRIVAL ) )
\r
384 * Sanity check. We should only be getting notifications of the
\r
385 * CI interface exported by AL.
\r
388 IsEqualGUID( &pNotify->InterfaceClassGuid, &GUID_IB_CI_INTERFACE ) );
\r
390 if( p_fdo->state != HCA_STARTED )
\r
392 HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_PNP ,("Invalid state: %d\n", p_fdo->state));
\r
396 /* save symbolic name of IBAL for a case of cancelled IBAL removal */
\r
397 if (!p_fdo->al_sym_name.Buffer) {
\r
398 p_fdo->al_sym_name.Length = pNotify->SymbolicLinkName->Length;
\r
399 p_fdo->al_sym_name.MaximumLength = pNotify->SymbolicLinkName->MaximumLength;
\r
400 p_fdo->al_sym_name.Buffer = ExAllocatePoolWithTag( NonPagedPool,
\r
401 p_fdo->al_sym_name.MaximumLength * sizeof(wchar_t), MT_TAG_KERNEL );
\r
402 if (!p_fdo->al_sym_name.Buffer)
\r
404 HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_PNP ,("allocation of sym IBAL name failed.\n"));
\r
407 RtlCopyUnicodeString( &p_fdo->al_sym_name, pNotify->SymbolicLinkName );
\r
410 ASSERT( !p_fdo->p_al_dev );
\r
411 ASSERT( !p_fdo->p_al_file_obj );
\r
413 /* Get the AL device object. */
\r
414 HCA_PRINT( TRACE_LEVEL_INFORMATION ,HCA_DBG_PNP ,("Calling IoGetDeviceObjectPointer.\n"));
\r
415 status = IoGetDeviceObjectPointer( pNotify->SymbolicLinkName,
\r
416 FILE_ALL_ACCESS, &p_fdo->p_al_file_obj, &p_fdo->p_al_dev );
\r
417 if( !NT_SUCCESS( status ) )
\r
419 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
420 ("IoGetDeviceObjectPointer returned %08x.\n", status ));
\r
424 /* Register for removal notification of the IB Fabric root device. */
\r
425 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PNP,
\r
426 ("Registering for target notifications.\n"));
\r
427 status = IoRegisterPlugPlayNotification(
\r
428 EventCategoryTargetDeviceChange, 0, p_fdo->p_al_file_obj,
\r
429 p_dev_obj->DriverObject, __pnp_notify_target, p_fdo,
\r
430 &p_fdo->pnp_target_entry );
\r
431 if( !NT_SUCCESS( status ) )
\r
433 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
434 ("IoRegisterPlugPlayNotification returned %08x.\n", status));
\r
435 goto err_reg_notify;
\r
438 status = __hca_register( p_fdo );
\r
439 if( !NT_SUCCESS( status ) )
\r
441 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
442 ("__get_ci_interface returned %08x.\n", status));
\r
448 IoUnregisterPlugPlayNotification( p_fdo->pnp_target_entry );
\r
449 p_fdo->pnp_target_entry = NULL;
\r
451 ObDereferenceObject( p_fdo->p_al_file_obj );
\r
452 p_fdo->p_al_file_obj = NULL;
\r
453 p_fdo->p_al_dev = NULL;
\r
455 HCA_EXIT( HCA_DBG_PNP );
\r
459 /* Forwards the request to the HCA's PDO. */
\r
462 IN WDFDEVICE const FdoDevice,
\r
463 IN const GUID* const p_guid,
\r
466 IN OUT PVOID InterfaceSpecificData,
\r
467 OUT PINTERFACE p_ifc )
\r
471 HCA_ENTER( HCA_DBG_PNP );
\r
473 status = WdfFdoQueryForInterface( FdoDevice, p_guid, p_ifc,
\r
474 size, Version, InterfaceSpecificData );
\r
476 HCA_EXIT( HCA_DBG_PNP );
\r
481 __unmap_hca_memory(
\r
482 IN PFDO_DEVICE_DATA const p_fdo )
\r
484 struct pci_dev *pdev = p_fdo->bus_ib_ifc.pdev;
\r
487 HCA_ENTER( HCA_DBG_PNP );
\r
489 for( i = 0; i < HCA_BAR_TYPE_MAX; i++ ) {
\r
490 if (pdev->bar[i].virt) {
\r
491 MmUnmapIoSpace( pdev->bar[i].virt, pdev->bar[i].size );
\r
492 cl_memclr( &pdev->bar[i], sizeof(hca_bar_t) );
\r
496 HCA_EXIT( HCA_DBG_PNP );
\r
499 /* release the resources, allocated in hca_start */
\r
501 __hca_release_resources(
\r
502 IN WDFDEVICE Device )
\r
504 PFDO_DEVICE_DATA p_fdo = FdoGetData(Device);
\r
506 HCA_ENTER( HCA_DBG_PNP );
\r
508 switch( p_fdo->state )
\r
510 case HCA_REGISTERED:
\r
511 __hca_deregister( p_fdo );
\r
513 /* Fall through. */
\r
516 mlnx_hca_remove( &p_fdo->hca );
\r
519 if (p_fdo->al_sym_name.Buffer) {
\r
520 ExFreePool( p_fdo->al_sym_name.Buffer );
\r
521 p_fdo->al_sym_name.Buffer = NULL;
\r
524 if( p_fdo->pnp_target_entry )
\r
526 ASSERT( p_fdo->pnp_ifc_entry );
\r
527 IoUnregisterPlugPlayNotification( p_fdo->pnp_target_entry );
\r
528 p_fdo->pnp_target_entry = NULL;
\r
531 if( p_fdo->pnp_ifc_entry ) {
\r
532 IoUnregisterPlugPlayNotification( p_fdo->pnp_ifc_entry );
\r
533 p_fdo->pnp_ifc_entry = NULL;
\r
536 if( p_fdo->p_al_file_obj ) {
\r
537 ObDereferenceObject( p_fdo->p_al_file_obj );
\r
538 p_fdo->p_al_file_obj = NULL;
\r
541 __unmap_hca_memory( p_fdo );
\r
543 p_fdo->state = HCA_ADDED;
\r
545 HCA_EXIT( HCA_DBG_PNP );
\r
550 IN WDFDEVICE Device,
\r
551 IN WDF_POWER_DEVICE_STATE PreviousState
\r
554 PFDO_DEVICE_DATA p_fdo = FdoGetData(Device);
\r
555 NTSTATUS status = STATUS_SUCCESS;
\r
557 UNUSED_PARAM(PreviousState);
\r
558 HCA_ENTER( HCA_DBG_PNP );
\r
560 HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, ("EvtDeviceD0Entry: PreviousState 0x%x\n", PreviousState));
\r
562 /* Connect to IBAL */
\r
563 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO,
\r
564 ("***** Connect to IBAL, IRQL %d\n", KeGetCurrentIrql()));
\r
566 if( p_fdo->p_al_dev && p_fdo->state == HCA_STARTED) {
\r
567 status = __hca_register( p_fdo );
\r
568 if( !NT_SUCCESS( status ) ) {
\r
569 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PO,
\r
570 ("!!! __hca_register failed (%#x) \n", status));
\r
571 status = STATUS_UNSUCCESSFUL;
\r
575 HCA_EXIT( HCA_DBG_PNP );
\r
576 return STATUS_SUCCESS;
\r
581 IN WDFDEVICE Device,
\r
582 IN WDF_POWER_DEVICE_STATE TargetState
\r
586 PFDO_DEVICE_DATA p_fdo = FdoGetData(Device);
\r
588 HCA_ENTER( HCA_DBG_PNP );
\r
590 HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, ("EvtDeviceD0Exit: TargetState 0x%x\n", TargetState));
\r
592 switch (TargetState) {
\r
593 case WdfPowerDeviceD1: /* hopefully, it is STANDBY state */
\r
594 case WdfPowerDevicePrepareForHibernation:
\r
595 if (atomic_read(&p_fdo->usecnt)) {
\r
596 status = STATUS_UNSUCCESSFUL;
\r
599 /* Fall through. */
\r
601 __hca_deregister( p_fdo );
\r
602 status = STATUS_SUCCESS;
\r
606 HCA_EXIT( HCA_DBG_PNP );
\r
611 EvtDevicePrepareHardware(
\r
612 IN WDFDEVICE Device,
\r
613 IN WDFCMRESLIST ResourcesRaw,
\r
614 IN WDFCMRESLIST ResourcesTranslated
\r
619 PFDO_DEVICE_DATA p_fdo = FdoGetData(Device);
\r
620 PDEVICE_OBJECT p_dev_obj = WdfDeviceWdmGetDeviceObject(Device);
\r
621 BUS_INTERFACE_STANDARD bus_pci_ifc;
\r
623 UNUSED_PARAM(ResourcesRaw);
\r
624 UNUSED_PARAM(ResourcesTranslated);
\r
626 HCA_ENTER( HCA_DBG_PNP );
\r
628 HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, ("EvtPrepareHardware: \n"));
\r
632 /* get PCI BUS interface */
\r
633 status = __get_ifc( Device, &GUID_BUS_INTERFACE_STANDARD,
\r
634 sizeof(BUS_INTERFACE_STANDARD), 1, NULL, (PINTERFACE)&bus_pci_ifc);
\r
635 if( !NT_SUCCESS( status ) ) {
\r
636 HCA_PRINT(TRACE_LEVEL_ERROR, HCA_DBG_PNP, ("Getting PCI BUS interface failed: status=0x%x\n", status));
\r
639 RtlCopyMemory( &p_fdo->bus_pci_ifc, &bus_pci_ifc, sizeof(BUS_INTERFACE_STANDARD) );
\r
640 p_fdo->bus_pci_ifc_taken = TRUE;
\r
642 /* get MLX4_BUS IB interface */
\r
643 status = __get_ifc( Device, &MLX4_BUS_IB_INTERFACE_GUID,
\r
644 sizeof(MLX4_BUS_IB_INTERFACE), MLX4_BUS_IB_INTERFACE_VERSION, NULL, (PINTERFACE)&p_fdo->bus_ib_ifc);
\r
645 if( !NT_SUCCESS( status ) ) {
\r
646 HCA_PRINT(TRACE_LEVEL_ERROR, HCA_DBG_PNP, ("Getting MLX4 BUS interface failed: status=0x%x\n", status));
\r
649 p_fdo->bus_ib_ifc_taken = TRUE;
\r
650 p_fdo->bus_ib_ifc.p_ibdev->x.p_fdo = p_fdo;
\r
652 InitializeListHead(&p_fdo->hca.event_list);
\r
653 KeInitializeSpinLock(&p_fdo->hca.event_list_lock);
\r
655 /* get node GUID */
\r
656 err = __get_dev_info( p_fdo, &p_fdo->hca.guid, &p_fdo->hca.hw_ver );
\r
659 HCA_PRINT(TRACE_LEVEL_ERROR ,HCA_DBG_LOW ,
\r
660 ("can't get guid - ib_query_device() failed (%08X)\n", err ));
\r
661 //TODO: no cleanup on error
\r
662 return STATUS_INSUFFICIENT_RESOURCES;
\r
666 mlnx_hca_insert( &p_fdo->hca );
\r
669 * Change the state since the PnP callback can happen
\r
670 * before the callback returns.
\r
672 p_fdo->state = HCA_STARTED;
\r
674 /* Register for interface arrival of the IB_AL device. */
\r
675 status = IoRegisterPlugPlayNotification(
\r
676 EventCategoryDeviceInterfaceChange,
\r
677 PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,
\r
678 (void*)&GUID_IB_CI_INTERFACE, p_dev_obj->DriverObject,
\r
679 __pnp_notify_ifc, p_fdo, &p_fdo->pnp_ifc_entry );
\r
680 if( !NT_SUCCESS( status ) )
\r
682 p_fdo->state = HCA_ADDED;
\r
683 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
684 ("IoRegisterPlugPlayNotification returned %08x.\n", status));
\r
687 HCA_EXIT( HCA_DBG_PNP );
\r
693 EvtDeviceReleaseHardware(
\r
694 IN WDFDEVICE Device,
\r
695 IN WDFCMRESLIST ResourcesTranslated
\r
698 PFDO_DEVICE_DATA p_fdo = FdoGetData(Device);
\r
700 UNUSED_PARAM(ResourcesTranslated);
\r
702 HCA_ENTER( HCA_DBG_PNP );
\r
704 HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, ("EvtDeviceReleaseHardware: FdoData=0x%p\n", p_fdo));
\r
706 // release IBBUS resources
\r
707 __hca_release_resources(Device);
\r
709 // release MLX4_BUS resources
\r
710 if(p_fdo->bus_ib_ifc_taken) {
\r
711 p_fdo->bus_ib_ifc_taken = FALSE;
\r
712 __put_ifc( (PINTERFACE)&p_fdo->bus_ib_ifc );
\r
715 // release PCI BUS resources
\r
716 if(p_fdo->bus_pci_ifc_taken) {
\r
717 p_fdo->bus_pci_ifc_taken = FALSE;
\r
718 __put_ifc( (PINTERFACE)&p_fdo->bus_pci_ifc );
\r
721 HCA_EXIT( HCA_DBG_PNP );
\r
722 return STATUS_SUCCESS;
\r
726 EvtDeviceQueryRemove(
\r
727 IN WDFDEVICE Device
\r
730 PFDO_DEVICE_DATA p_fdo = FdoGetData(Device);
\r
731 HCA_ENTER( HCA_DBG_PNP );
\r
732 if (atomic_read(&p_fdo->usecnt)) {
\r
733 cl_dbg_out( "MLX4: Can't get unloaded. %d applications are still in work\n", p_fdo->usecnt);
\r
734 return STATUS_UNSUCCESSFUL;
\r
736 HCA_EXIT( HCA_DBG_PNP );
\r
737 return STATUS_SUCCESS;
\r
743 IN WDFDRIVER Driver,
\r
744 IN PWDFDEVICE_INIT DeviceInit
\r
747 Routine Description:
\r
749 EvtDeviceAdd is called by the framework in response to AddDevice
\r
750 call from the PnP manager. We create and initialize a device object to
\r
751 represent a new instance of mxe bus.
\r
755 Driver - Handle to a framework driver object created in DriverEntry
\r
757 DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.
\r
765 WDF_OBJECT_ATTRIBUTES attributes;
\r
768 PFDO_DEVICE_DATA p_fdo;
\r
769 WDF_PNPPOWER_EVENT_CALLBACKS Callbacks;
\r
771 UNREFERENCED_PARAMETER(Driver);
\r
775 HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, ("EvtDeviceAdd: 0x%p\n", Driver));
\r
777 // register PnP & Power stuff
\r
779 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&Callbacks);
\r
780 Callbacks.EvtDevicePrepareHardware = EvtDevicePrepareHardware;
\r
781 Callbacks.EvtDeviceReleaseHardware = EvtDeviceReleaseHardware;
\r
782 Callbacks.EvtDeviceQueryRemove = EvtDeviceQueryRemove;
\r
783 Callbacks.EvtDeviceD0Entry = EvtDeviceD0Entry;
\r
784 Callbacks.EvtDeviceD0Exit = EvtDeviceD0Exit;
\r
786 WdfDeviceInitSetPnpPowerEventCallbacks( DeviceInit, &Callbacks );
\r
789 // Initialize all the properties specific to the device.
\r
790 // Framework has default values for the one that are not
\r
791 // set explicitly here. So please read the doc and make sure
\r
792 // you are okay with the defaults.
\r
794 WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_INFINIBAND);
\r
795 WdfDeviceInitSetExclusive(DeviceInit, FALSE);
\r
798 // Initialize attributes structure to specify size and accessor function
\r
799 // for storing device context.
\r
801 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, FDO_DEVICE_DATA);
\r
804 // Create a framework device object. In response to this call, framework
\r
805 // creates a WDM deviceobject.
\r
807 status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
\r
808 if (!NT_SUCCESS(status)) {
\r
809 HCA_PRINT(TRACE_LEVEL_VERBOSE, HCA_DBG_PNP, ("EvtDeviceAdd: WdfDeviceCreate failed with 0x%x\n", status));
\r
814 // Init device context.
\r
816 p_fdo = FdoGetData(device);
\r
817 RtlZeroMemory(p_fdo, sizeof(FDO_DEVICE_DATA));
\r
818 p_fdo->FdoDevice = device;
\r
819 spin_lock_init( &p_fdo->uctx_lock );
\r
820 cl_qlist_init( &p_fdo->uctx_list );
\r
821 atomic_set(&p_fdo->usecnt, 0);
\r
822 p_fdo->state = HCA_ADDED;
\r
827 status = WmiRegistration(device);
\r
828 if (!NT_SUCCESS(status)) {
\r
832 status = STATUS_SUCCESS;
\r
835 HCA_EXIT( HCA_DBG_PNP );
\r
842 IN WDFDRIVER Driver
\r
845 HCA_ENTER( HCA_DBG_PNP );
\r
847 UNUSED_PARAM( Driver );
\r
849 HCA_EXIT( HCA_DBG_PNP );
\r
850 #if defined(EVENT_TRACING)
\r
851 WPP_CLEANUP(WdfDriverWdmGetDriverObject(Driver));
\r
857 IN PDRIVER_OBJECT DriverObject,
\r
858 IN PUNICODE_STRING RegistryPath
\r
861 Routine Description:
\r
863 Initialize the call backs structure of Driver Framework.
\r
867 DriverObject - pointer to the driver object
\r
869 RegistryPath - pointer to a unicode string representing the path,
\r
870 to driver-specific key in the registry.
\r
878 WDF_DRIVER_CONFIG config;
\r
882 #if defined(EVENT_TRACING)
\r
883 WPP_INIT_TRACING(DriverObject, RegistryPath);
\r
886 // global initializations
\r
887 g.DebugPrintLevel = TRACE_LEVEL_VERBOSE;
\r
888 g.DebugPrintFlags = 0xffff;
\r
889 HCA_ENTER( HCA_DBG_PNP );
\r
890 HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_PNP,
\r
891 ("Built %s %s, Version %s, RelDate %s\n",
\r
892 __DATE__, __TIME__, DRV_VERSION, DRV_RELDATE));
\r
893 status = mlnx_hcas_init();
\r
894 if( status != STATUS_SUCCESS ) {
\r
895 HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_PNP ,
\r
896 ("mlnx_hcas_init returned %#x.\n", status));
\r
901 // Initiialize driver config to control the attributes that
\r
902 // are global to the driver. Note that framework by default
\r
903 // provides a driver unload routine. If you create any resources
\r
904 // in the DriverEntry and want to be cleaned in driver unload,
\r
905 // you can override that by specifing one in the Config structure.
\r
908 WDF_DRIVER_CONFIG_INIT(
\r
909 &config, EvtDeviceAdd );
\r
910 config.EvtDriverUnload = EvtDriverUnload;
\r
913 // Create a framework driver object to represent our driver.
\r
915 status = WdfDriverCreate(DriverObject,
\r
916 RegistryPath, WDF_NO_OBJECT_ATTRIBUTES,
\r
917 &config, &hDriver);
\r
919 if (!NT_SUCCESS(status)) {
\r
920 HCA_PRINT(TRACE_LEVEL_VERBOSE, HCA_DBG_PNP, ("WdfDriverCreate failed with status 0x%x\n", status));
\r
925 // read registry parameters
\r
928 DECLARE_CONST_UNICODE_STRING(valueName0, L"DebugLevel");
\r
929 DECLARE_CONST_UNICODE_STRING(valueName1, L"DebugFlags");
\r
931 WDFKEY hKey = NULL;
\r
933 status = WdfDriverOpenParametersRegistryKey( hDriver,
\r
934 STANDARD_RIGHTS_ALL, WDF_NO_OBJECT_ATTRIBUTES, &hKey );
\r
936 if (NT_SUCCESS (status)) {
\r
938 status = WdfRegistryQueryULong(hKey, &valueName0, &value);
\r
939 if (NT_SUCCESS (status)) g.DebugPrintLevel = value;
\r
941 status = WdfRegistryQueryULong(hKey, &valueName1, &value);
\r
942 if (NT_SUCCESS (status)) g.DebugPrintFlags = value;
\r
944 WdfRegistryClose(hKey);
\r
947 // we don't matter the failure in the work with Registry
\r
948 status = STATUS_SUCCESS;
\r
952 HCA_EXIT( HCA_DBG_PNP );
\r
960 UNICODE_STRING g_param_path;
\r
961 static cl_vfptr_pnp_po_t vfptrHcaPnp;
\r
965 IN PDRIVER_OBJECT p_driver_obj,
\r
966 IN PUNICODE_STRING p_registry_path );
\r
970 IN UNICODE_STRING* const p_Param_Path );
\r
974 IN PDRIVER_OBJECT p_driver_obj );
\r
978 IN PDEVICE_OBJECT p_dev_obj,
\r
983 IN PDRIVER_OBJECT pDriverObj,
\r
984 IN PDEVICE_OBJECT pPdo );
\r
988 IN DEVICE_OBJECT* const p_dev_obj,
\r
989 IN IRP* const p_irp,
\r
990 OUT cl_irp_action_t* const p_action );
\r
994 IN DEVICE_OBJECT* const p_dev_obj,
\r
995 IN IRP* const p_irp,
\r
996 OUT cl_irp_action_t* const p_action );
\r
1000 IN DEVICE_OBJECT* const p_dev_obj,
\r
1001 IN IRP* const p_irp,
\r
1002 OUT cl_irp_action_t* const p_action );
\r
1006 IN DEVICE_OBJECT* const p_dev_obj,
\r
1007 IN IRP* const p_irp,
\r
1008 OUT cl_irp_action_t* const p_action );
\r
1012 IN DEVICE_OBJECT* const p_dev_obj,
\r
1013 IN IRP* const p_irp,
\r
1014 OUT cl_irp_action_t* const p_action );
\r
1017 hca_release_resources(
\r
1018 IN DEVICE_OBJECT* const p_dev_obj );
\r
1021 hca_cancel_remove(
\r
1022 IN DEVICE_OBJECT* const p_dev_obj,
\r
1023 IN IRP* const p_irp,
\r
1024 OUT cl_irp_action_t* const p_action );
\r
1027 hca_surprise_remove(
\r
1028 IN DEVICE_OBJECT* const p_dev_obj,
\r
1029 IN IRP* const p_irp,
\r
1030 OUT cl_irp_action_t* const p_action );
\r
1033 hca_query_capabilities(
\r
1034 IN DEVICE_OBJECT* const p_dev_obj,
\r
1035 IN IRP* const p_irp,
\r
1036 OUT cl_irp_action_t* const p_action );
\r
1039 hca_query_interface(
\r
1040 IN DEVICE_OBJECT* const p_dev_obj,
\r
1041 IN IRP* const p_irp,
\r
1042 OUT cl_irp_action_t* const p_action );
\r
1045 hca_query_pnp_state(
\r
1046 IN DEVICE_OBJECT* const p_dev_obj,
\r
1047 IN IRP* const p_irp,
\r
1048 OUT cl_irp_action_t* const p_action );
\r
1051 hca_query_bus_relations(
\r
1052 IN DEVICE_OBJECT* const p_dev_obj,
\r
1053 IN IRP* const p_irp,
\r
1054 OUT cl_irp_action_t* const p_action );
\r
1057 hca_query_removal_relations(
\r
1058 IN DEVICE_OBJECT* const p_dev_obj,
\r
1059 IN IRP* const p_irp,
\r
1060 OUT cl_irp_action_t* const p_action );
\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
1070 IN DEVICE_OBJECT* const p_dev_obj,
\r
1071 IN IRP* const p_irp,
\r
1072 OUT cl_irp_action_t* const p_action );
\r
1074 static ci_interface_t*
\r
1076 IN FDO_DEVICE_DATA* const p_fdo );
\r
1079 __get_ci_interface(
\r
1080 IN DEVICE_OBJECT* const p_dev_obj );
\r
1087 IN PDRIVER_OBJECT pDriverObj,
\r
1088 IN PDEVICE_OBJECT pPdo )
\r
1091 DEVICE_OBJECT *p_dev_obj, *pNextDevObj;
\r
1092 PFDO_DEVICE_DATA p_fdo;
\r
1094 HCA_ENTER(HCA_DBG_PNP);
\r
1097 * Create the device so that we have a device extension to store stuff in.
\r
1099 status = IoCreateDevice( pDriverObj, sizeof(FDO_DEVICE_DATA),
\r
1100 NULL, FILE_DEVICE_INFINIBAND, FILE_DEVICE_SECURE_OPEN,
\r
1101 FALSE, &p_dev_obj );
\r
1102 if( !NT_SUCCESS( status ) )
\r
1104 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
1105 ("IoCreateDevice returned 0x%08X.\n", status));
\r
1109 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1110 cl_memclr( p_fdo, sizeof(FDO_DEVICE_DATA) );
\r
1111 cl_spinlock_init( &p_fdo->uctx_lock );
\r
1112 cl_qlist_init( &p_fdo->uctx_list );
\r
1113 atomic_set(&p_fdo->usecnt, 0);
\r
1115 /* Attach to the device stack. */
\r
1116 pNextDevObj = IoAttachDeviceToDeviceStack( p_dev_obj, pPdo );
\r
1117 if( !pNextDevObj )
\r
1119 //cl_event_destroy( &p_fdo->mutex );
\r
1120 IoDeleteDevice( p_dev_obj );
\r
1121 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
1122 ("IoAttachDeviceToDeviceStack failed.\n"));
\r
1123 return STATUS_NO_SUCH_DEVICE;
\r
1126 /* Inititalize the complib extension. */
\r
1127 cl_init_pnp_po_ext( p_dev_obj, pNextDevObj, pPdo, CL_DBG_PNP | CL_DBG_ERROR,
\r
1128 &vfptrHcaPnp, NULL );
\r
1130 p_fdo->state = HCA_ADDED;
\r
1132 HCA_EXIT(HCA_DBG_PNP);
\r
1136 /* Forwards the request to the HCA's PDO. */
\r
1139 IN DEVICE_OBJECT* const pDevObj,
\r
1140 IN const GUID* const pGuid,
\r
1142 IN USHORT Version,
\r
1143 IN OUT PVOID InterfaceSpecificData,
\r
1144 OUT PINTERFACE pBusIfc )
\r
1148 IO_STATUS_BLOCK ioStatus;
\r
1149 IO_STACK_LOCATION *pIoStack;
\r
1150 DEVICE_OBJECT *pDev;
\r
1153 HCA_ENTER( HCA_DBG_PNP );
\r
1155 CL_ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
\r
1157 pDev = IoGetAttachedDeviceReference( pDevObj );
\r
1159 KeInitializeEvent( &event, NotificationEvent, FALSE );
\r
1161 /* Build the IRP for the HCA. */
\r
1162 pIrp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, pDev,
\r
1163 NULL, 0, NULL, &event, &ioStatus );
\r
1166 ObDereferenceObject( pDev );
\r
1167 HCA_PRINT( TRACE_LEVEL_ERROR,HCA_DBG_PNP,
\r
1168 ("IoBuildSynchronousFsdRequest failed.\n"));
\r
1169 return STATUS_INSUFFICIENT_RESOURCES;
\r
1172 /* Copy the request query parameters. */
\r
1173 pIoStack = IoGetNextIrpStackLocation( pIrp );
\r
1174 pIoStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
\r
1175 pIoStack->Parameters.QueryInterface.Size = size;
\r
1176 pIoStack->Parameters.QueryInterface.Version = Version;
\r
1177 pIoStack->Parameters.QueryInterface.InterfaceType = pGuid;
\r
1178 pIoStack->Parameters.QueryInterface.Interface = (INTERFACE*)pBusIfc;
\r
1179 pIoStack->Parameters.QueryInterface.InterfaceSpecificData = InterfaceSpecificData;
\r
1181 pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
\r
1183 /* Send the IRP. */
\r
1184 status = IoCallDriver( pDev, pIrp );
\r
1185 if( status == STATUS_PENDING )
\r
1187 KeWaitForSingleObject( &event, Executive, KernelMode,
\r
1190 status = ioStatus.Status;
\r
1192 ObDereferenceObject( pDev );
\r
1194 HCA_EXIT( HCA_DBG_PNP );
\r
1198 static ci_interface_t*
\r
1200 IN PFDO_DEVICE_DATA const p_fdo )
\r
1202 ci_interface_t *pIfc;
\r
1204 HCA_ENTER( HCA_DBG_PNP );
\r
1206 pIfc = (ci_interface_t*)ExAllocatePoolWithTag( PagedPool,
\r
1207 sizeof(ci_interface_t), MT_TAG_KERNEL );
\r
1210 HCA_PRINT( TRACE_LEVEL_ERROR,HCA_DBG_PNP,
\r
1211 ("Failed to allocate ci_interface_t (%d bytes).\n",
\r
1212 sizeof(ci_interface_t)));
\r
1216 setup_ci_interface( p_fdo->hca.guid, !!hca_is_livefish(p_fdo), pIfc );
\r
1218 pIfc->p_hca_dev = p_fdo->cl_ext.p_pdo;
\r
1219 ASSERT(pIfc->p_hca_dev);
\r
1220 pIfc->vend_id = (uint32_t)p_fdo->bus_ib_ifc.pdev->ven_id;
\r
1221 pIfc->dev_id = (uint16_t)p_fdo->bus_ib_ifc.pdev->dev_id;
\r
1222 pIfc->dev_revision = (uint16_t)p_fdo->hca.hw_ver;
\r
1224 HCA_EXIT( HCA_DBG_PNP );
\r
1229 __unmap_hca_memory(
\r
1230 IN PFDO_DEVICE_DATA const p_fdo )
\r
1232 struct pci_dev *pdev = p_fdo->bus_ib_ifc.pdev;
\r
1235 HCA_ENTER( HCA_DBG_PNP );
\r
1238 for( i = 0; i < HCA_BAR_TYPE_MAX; i++ ) {
\r
1239 if (pdev->bar[i].virt) {
\r
1240 MmUnmapIoSpace( pdev->bar[i].virt, pdev->bar[i].size );
\r
1241 cl_memclr( &pdev->bar[i], sizeof(hca_bar_t) );
\r
1245 HCA_EXIT( HCA_DBG_PNP );
\r
1249 /* release the resources, allocated in hca_start */
\r
1251 __hca_release_resources(
\r
1252 IN DEVICE_OBJECT* const p_dev_obj )
\r
1254 PFDO_DEVICE_DATA p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1256 HCA_ENTER( HCA_DBG_PNP );
\r
1258 switch( p_fdo->state )
\r
1262 mlnx_hca_remove( &p_fdo->hca );
\r
1265 if (p_fdo->al_sym_name.Buffer) {
\r
1266 ExFreePool( p_fdo->al_sym_name.Buffer );
\r
1267 p_fdo->al_sym_name.Buffer = NULL;
\r
1270 if( p_fdo->pnp_target_entry )
\r
1272 ASSERT( p_fdo->pnp_ifc_entry );
\r
1273 IoUnregisterPlugPlayNotification( p_fdo->pnp_target_entry );
\r
1274 p_fdo->pnp_target_entry = NULL;
\r
1277 if( p_fdo->pnp_ifc_entry ) {
\r
1278 IoUnregisterPlugPlayNotification( p_fdo->pnp_ifc_entry );
\r
1279 p_fdo->pnp_ifc_entry = NULL;
\r
1282 if( p_fdo->p_al_file_obj ) {
\r
1283 ObDereferenceObject( p_fdo->p_al_file_obj );
\r
1284 p_fdo->p_al_file_obj = NULL;
\r
1287 // release MLX4_BUS resources
\r
1288 if(p_fdo->bus_ib_ifc_taken) {
\r
1289 p_fdo->bus_ib_ifc_taken = FALSE;
\r
1290 __put_ifc( (PINTERFACE)&p_fdo->bus_ib_ifc );
\r
1293 // release PCI BUS resources
\r
1294 if(p_fdo->bus_pci_ifc_taken) {
\r
1295 p_fdo->bus_pci_ifc_taken = FALSE;
\r
1296 __put_ifc( (PINTERFACE)&p_fdo->bus_pci_ifc );
\r
1299 __unmap_hca_memory( p_fdo );
\r
1301 p_fdo->state = HCA_ADDED;
\r
1303 HCA_EXIT( HCA_DBG_PNP );
\r
1308 hca_release_resources(
\r
1309 IN DEVICE_OBJECT* const p_dev_obj )
\r
1311 PFDO_DEVICE_DATA p_fdo;
\r
1312 POWER_STATE powerState;
\r
1314 HCA_ENTER( HCA_DBG_PNP );
\r
1316 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1318 /* release all the resources, allocated in hca_start */
\r
1319 __hca_release_resources(p_dev_obj);
\r
1321 /* Notify the power manager that the device is powered down. */
\r
1322 p_fdo->DevicePowerState = PowerDeviceD3;
\r
1323 powerState.DeviceState = PowerDeviceD3;
\r
1324 powerState = PoSetPowerState ( p_fdo->cl_ext.p_self_do, DevicePowerState, powerState );
\r
1326 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PNP,
\r
1327 ("PoSetPowerState: old state %d, new state to %d\n",
\r
1328 powerState.DeviceState, p_fdo->DevicePowerState ));
\r
1330 /* Clear the PnP state in case we get restarted. */
\r
1331 p_fdo->pnpState = 0;
\r
1333 HCA_EXIT( HCA_DBG_PNP );
\r
1338 IN DEVICE_OBJECT* const p_dev_obj,
\r
1339 IN IRP* const p_irp,
\r
1340 OUT cl_irp_action_t* const p_action )
\r
1344 PFDO_DEVICE_DATA p_fdo;
\r
1345 IO_STACK_LOCATION *pIoStack;
\r
1346 POWER_STATE powerState;
\r
1347 BUS_INTERFACE_STANDARD bus_pci_ifc;
\r
1349 HCA_ENTER( HCA_DBG_PNP );
\r
1351 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1353 /* Handled on the way up. */
\r
1354 status = cl_do_sync_pnp( p_dev_obj, p_irp, p_action );
\r
1355 if( !NT_SUCCESS( status ) )
\r
1357 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
1358 ("Lower drivers failed IRP_MN_START_DEVICE (%#x).\n", status));
\r
1362 pIoStack = IoGetCurrentIrpStackLocation( p_irp );
\r
1364 /* get PCI BUS interface */
\r
1365 status = __get_ifc( p_dev_obj, &GUID_BUS_INTERFACE_STANDARD,
\r
1366 sizeof(BUS_INTERFACE_STANDARD), 1, NULL, (PINTERFACE)&bus_pci_ifc);
\r
1367 if( !NT_SUCCESS( status ) ) {
\r
1368 HCA_PRINT(TRACE_LEVEL_ERROR, HCA_DBG_PNP, ("Getting PCI BUS interface failed: status=0x%x\n", status));
\r
1371 RtlCopyMemory( &p_fdo->bus_pci_ifc, &bus_pci_ifc, sizeof(BUS_INTERFACE_STANDARD) );
\r
1372 p_fdo->bus_pci_ifc_taken = TRUE;
\r
1374 /* get MLX4_BUS IB interface */
\r
1375 status = __get_ifc( p_dev_obj, &MLX4_BUS_IB_INTERFACE_GUID,
\r
1376 sizeof(MLX4_BUS_IB_INTERFACE), MLX4_BUS_IB_INTERFACE_VERSION, NULL, (PINTERFACE)&p_fdo->bus_ib_ifc);
\r
1377 if( !NT_SUCCESS( status ) ) {
\r
1378 HCA_PRINT(TRACE_LEVEL_ERROR, HCA_DBG_PNP, ("Getting MLX4 BUS interface failed: status=0x%x\n", status));
\r
1381 p_fdo->bus_ib_ifc_taken = TRUE;
\r
1382 p_fdo->bus_ib_ifc.p_ibdev->x.p_fdo = p_fdo;
\r
1384 InitializeListHead(&p_fdo->hca.event_list);
\r
1385 KeInitializeSpinLock(&p_fdo->hca.event_list_lock);
\r
1387 /* get node GUID */
\r
1388 err = __get_dev_info( p_fdo, &p_fdo->hca.guid, &p_fdo->hca.hw_ver );
\r
1391 HCA_PRINT(TRACE_LEVEL_ERROR ,HCA_DBG_LOW ,
\r
1392 ("can't get guid - ib_query_device() failed (%08X)\n", err ));
\r
1393 //TODO: no cleanup on error
\r
1394 return STATUS_INSUFFICIENT_RESOURCES;
\r
1398 mlnx_hca_insert( &p_fdo->hca );
\r
1401 * Change the state since the PnP callback can happen
\r
1402 * before the callback returns.
\r
1404 p_fdo->state = HCA_STARTED;
\r
1406 /* We get started fully powered. */
\r
1407 p_fdo->DevicePowerState = PowerDeviceD0;
\r
1408 powerState.DeviceState = PowerDeviceD0;
\r
1409 powerState = PoSetPowerState ( p_fdo->cl_ext.p_self_do, DevicePowerState, powerState );
\r
1410 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PNP,
\r
1411 ("PoSetPowerState: old state %d, new state to %d\n",
\r
1412 powerState.DeviceState, p_fdo->DevicePowerState ));
\r
1415 HCA_EXIT( HCA_DBG_PNP );
\r
1421 IN DEVICE_OBJECT* const p_dev_obj,
\r
1422 IN IRP* const p_irp,
\r
1423 OUT cl_irp_action_t* const p_action )
\r
1425 /* All kernel clients will get notified through the device hierarchy. */
\r
1427 /* TODO: set a flag to fail creation of any new IB resources. */
\r
1428 return cl_irp_skip( p_dev_obj, p_irp, p_action );
\r
1434 IN DEVICE_OBJECT* const p_dev_obj,
\r
1435 IN IRP* const p_irp,
\r
1436 OUT cl_irp_action_t* const p_action )
\r
1439 * Must disable everything. Complib framework will
\r
1440 * call ReleaseResources handler.
\r
1442 return cl_irp_skip( p_dev_obj, p_irp, p_action );
\r
1448 IN DEVICE_OBJECT* const p_dev_obj,
\r
1449 IN IRP* const p_irp,
\r
1450 OUT cl_irp_action_t* const p_action )
\r
1452 /* Handled on the way up. */
\r
1453 return cl_do_sync_pnp( p_dev_obj, p_irp, p_action );
\r
1459 IN DEVICE_OBJECT* const p_dev_obj,
\r
1460 IN IRP* const p_irp,
\r
1461 OUT cl_irp_action_t* const p_action )
\r
1463 PFDO_DEVICE_DATA p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1464 if (atomic_read(&p_fdo->usecnt)) {
\r
1465 cl_dbg_out( "MTHCA: Can't get unloaded. %d applications are still in work\n", p_fdo->usecnt);
\r
1466 p_irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
\r
1467 return cl_irp_complete( p_dev_obj, p_irp, p_action );
\r
1469 /* TODO: set a flag to fail creation of any new IB resources. */
\r
1470 return cl_irp_skip( p_dev_obj, p_irp, p_action );
\r
1475 hca_cancel_remove(
\r
1476 IN DEVICE_OBJECT* const p_dev_obj,
\r
1477 IN IRP* const p_irp,
\r
1478 OUT cl_irp_action_t* const p_action )
\r
1480 /* Handled on the way up. */
\r
1481 return cl_do_sync_pnp( p_dev_obj, p_irp, p_action );
\r
1486 hca_surprise_remove(
\r
1487 IN DEVICE_OBJECT* const p_dev_obj,
\r
1488 IN IRP* const p_irp,
\r
1489 OUT cl_irp_action_t* const p_action )
\r
1492 * TODO: Set state so that all further requests
\r
1493 * automatically succeed/fail as needed.
\r
1495 return cl_irp_skip( p_dev_obj, p_irp, p_action );
\r
1500 hca_query_capabilities(
\r
1501 IN DEVICE_OBJECT* const p_dev_obj,
\r
1502 IN IRP* const p_irp,
\r
1503 OUT cl_irp_action_t* const p_action )
\r
1506 PFDO_DEVICE_DATA p_fdo;
\r
1507 IO_STACK_LOCATION *pIoStack;
\r
1508 DEVICE_CAPABILITIES *pCaps;
\r
1510 HCA_ENTER( HCA_DBG_PNP );
\r
1512 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1514 /* Process on the way up. */
\r
1515 status = cl_do_sync_pnp( p_dev_obj, p_irp, p_action );
\r
1516 if( !NT_SUCCESS( status ) )
\r
1518 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
1519 ("cl_do_sync_pnp returned %08X.\n", status));
\r
1523 pIoStack = IoGetCurrentIrpStackLocation( p_irp );
\r
1524 pCaps = pIoStack->Parameters.DeviceCapabilities.Capabilities;
\r
1527 * Store the device power mapping into our extension since we're
\r
1528 * the power policy owner. The mapping is used when handling
\r
1529 * IRP_MN_SET_POWER IRPs.
\r
1532 p_fdo->DevicePower, pCaps->DeviceState, sizeof(p_fdo->DevicePower) );
\r
1534 if( pCaps->DeviceD1 )
\r
1536 HCA_PRINT( TRACE_LEVEL_WARNING ,HCA_DBG_PNP,
\r
1537 ("WARNING: Device reports support for DeviceD1 power state.\n"));
\r
1538 pCaps->DeviceD1 = FALSE;
\r
1541 if( pCaps->DeviceD2 )
\r
1543 HCA_PRINT( TRACE_LEVEL_WARNING,HCA_DBG_PNP,
\r
1544 ("WARNING: Device reports support for DeviceD2 power state.\n"));
\r
1545 pCaps->DeviceD2 = FALSE;
\r
1548 if( pCaps->SystemWake != PowerSystemUnspecified )
\r
1550 HCA_PRINT( TRACE_LEVEL_WARNING ,HCA_DBG_PNP,
\r
1551 ("WARNING: Device reports support for system wake.\n"));
\r
1552 pCaps->SystemWake = PowerSystemUnspecified;
\r
1555 if( pCaps->DeviceWake != PowerDeviceUnspecified )
\r
1557 HCA_PRINT( TRACE_LEVEL_WARNING, HCA_DBG_PNP,
\r
1558 ("WARNING: Device reports support for device wake.\n"));
\r
1559 pCaps->DeviceWake = PowerDeviceUnspecified;
\r
1562 HCA_EXIT( HCA_DBG_PNP );
\r
1568 IN DEVICE_OBJECT* p_dev_obj )
\r
1570 PFDO_DEVICE_DATA p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1572 HCA_ENTER( HCA_DBG_PNP );
\r
1574 cl_atomic_inc( &p_fdo->n_hca_ifc_ref );
\r
1575 ObReferenceObject( p_dev_obj );
\r
1577 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
1578 ("MLX4_HCA: CA_guid %I64x, hca_ifc_ref %d\n",
\r
1579 p_fdo->hca.guid, p_fdo->n_hca_ifc_ref) );
\r
1581 HCA_EXIT( HCA_DBG_PNP );
\r
1586 IN DEVICE_OBJECT* p_dev_obj )
\r
1588 PFDO_DEVICE_DATA p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1590 HCA_ENTER( HCA_DBG_PNP );
\r
1592 cl_atomic_dec( &p_fdo->n_hca_ifc_ref );
\r
1593 ObDereferenceObject( p_dev_obj );
\r
1595 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
1596 ("MLX4_HCA: CA_guid %I64x, hca_ifc_ref %d\n",
\r
1597 p_fdo->hca.guid, p_fdo->n_hca_ifc_ref) );
\r
1599 HCA_EXIT( HCA_DBG_PNP );
\r
1604 IN DEVICE_OBJECT* const p_dev_obj,
\r
1605 IN IO_STACK_LOCATION* const p_io_stack )
\r
1607 RDMA_INTERFACE_VERBS *p_ifc;
\r
1608 PFDO_DEVICE_DATA p_fdo;
\r
1609 ci_interface_t *p_hca_ifc;
\r
1613 HCA_ENTER( HCA_DBG_PNP );
\r
1615 version = VerbsVersionMajor(p_io_stack->Parameters.QueryInterface.Version);
\r
1616 if( version > VERBS_MAJOR_VER )
\r
1618 status = STATUS_NOT_SUPPORTED;
\r
1622 if( p_io_stack->Parameters.QueryInterface.Size < sizeof(RDMA_INTERFACE_VERBS) )
\r
1624 status = STATUS_BUFFER_TOO_SMALL;
\r
1628 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1629 p_hca_ifc = __alloc_hca_ifc( p_fdo );
\r
1632 status = STATUS_NO_MEMORY;
\r
1636 p_ifc = (RDMA_INTERFACE_VERBS *) p_io_stack->Parameters.QueryInterface.Interface;
\r
1638 p_ifc->InterfaceHeader.Size = sizeof(RDMA_INTERFACE_VERBS);
\r
1639 p_ifc->InterfaceHeader.Version = VerbsVersion(VERBS_MAJOR_VER, VERBS_MINOR_VER);
\r
1640 p_ifc->InterfaceHeader.Context = p_dev_obj;
\r
1641 p_ifc->InterfaceHeader.InterfaceReference = __ref_ifc;
\r
1642 p_ifc->InterfaceHeader.InterfaceDereference = __deref_ifc;
\r
1643 p_ifc->Verbs = *p_hca_ifc;
\r
1644 p_ifc->p_hca_obj = &p_fdo->hca;
\r
1646 /* take the reference before returning. */
\r
1647 __ref_ifc( p_dev_obj );
\r
1649 ExFreePool( p_hca_ifc );
\r
1650 status = STATUS_SUCCESS;
\r
1653 HCA_EXIT( HCA_DBG_PNP );
\r
1659 hca_query_interface(
\r
1660 IN DEVICE_OBJECT* const p_dev_obj,
\r
1661 IN IRP* const p_irp,
\r
1662 OUT cl_irp_action_t* const p_action )
\r
1665 IO_STACK_LOCATION *p_io_stack;
\r
1667 HCA_ENTER( HCA_DBG_PNP );
\r
1669 #pragma warning( push, 3 )
\r
1671 #pragma warning( pop )
\r
1673 p_io_stack = IoGetCurrentIrpStackLocation( p_irp );
\r
1675 /* Compare requested GUID with our supported interface GUIDs. */
\r
1676 if( IsEqualGUID( p_io_stack->Parameters.QueryInterface.InterfaceType,
\r
1677 &GUID_RDMA_INTERFACE_VERBS ) )
\r
1679 status = __query_ci_ifc( p_dev_obj, p_io_stack );
\r
1680 *p_action = IrpComplete;
\r
1684 status = p_irp->IoStatus.Status;
\r
1685 *p_action = IrpSkip;
\r
1688 HCA_EXIT( HCA_DBG_PNP );
\r
1694 hca_query_pnp_state(
\r
1695 IN DEVICE_OBJECT* const p_dev_obj,
\r
1696 IN IRP* const p_irp,
\r
1697 OUT cl_irp_action_t* const p_action )
\r
1699 PFDO_DEVICE_DATA p_fdo;
\r
1701 HCA_ENTER( HCA_DBG_PNP );
\r
1703 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1705 p_irp->IoStatus.Information |= p_fdo->pnpState;
\r
1707 *p_action = IrpSkip;
\r
1709 HCA_EXIT( HCA_DBG_PNP );
\r
1710 return STATUS_SUCCESS;;
\r
1715 IN DEVICE_OBJECT* const p_dev_obj,
\r
1716 IN IRP* const p_irp,
\r
1717 OUT cl_irp_action_t* const p_action )
\r
1719 NTSTATUS status = STATUS_SUCCESS;
\r
1720 IO_STACK_LOCATION *pIoStack;
\r
1722 HCA_ENTER(HCA_DBG_PO);
\r
1724 UNUSED_PARAM( p_dev_obj );
\r
1726 pIoStack = IoGetCurrentIrpStackLocation( p_irp );
\r
1728 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO,
\r
1729 ("QUERY_POWER for FDO %p: type %s, state %d, action %d, IRQL %d, IRP %p\n",
\r
1731 (pIoStack->Parameters.Power.Type) ? "DevicePowerState" : "SystemPowerState",
\r
1732 pIoStack->Parameters.Power.State.DeviceState,
\r
1733 pIoStack->Parameters.Power.ShutdownType, KeGetCurrentIrql(), p_irp ));
\r
1735 switch( pIoStack->Parameters.Power.Type )
\r
1737 case SystemPowerState:
\r
1738 /* Fail any requests to hibernate or sleep the system. */
\r
1739 switch( pIoStack->Parameters.Power.State.SystemState )
\r
1741 case PowerSystemSleeping1: // STANDBY support
\r
1742 case PowerSystemHibernate:
\r
1744 PFDO_DEVICE_DATA p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1745 if (atomic_read(&p_fdo->usecnt))
\r
1746 status = STATUS_UNSUCCESSFUL;
\r
1750 case PowerSystemWorking:
\r
1751 case PowerSystemShutdown:
\r
1755 status = STATUS_NOT_SUPPORTED;
\r
1759 case DevicePowerState:
\r
1760 /* Fail any query for low power states. */
\r
1761 switch( pIoStack->Parameters.Power.State.DeviceState )
\r
1763 case PowerDeviceD0:
\r
1764 case PowerDeviceD3:
\r
1765 /* We only support fully powered or off power states. */
\r
1769 status = STATUS_NOT_SUPPORTED;
\r
1774 if( status == STATUS_SUCCESS )
\r
1775 *p_action = IrpSkip;
\r
1777 *p_action = IrpComplete;
\r
1779 HCA_EXIT( HCA_DBG_PO );
\r
1785 __RequestPowerCompletion(
\r
1786 IN DEVICE_OBJECT *p_dev_obj,
\r
1787 IN UCHAR minorFunction,
\r
1788 IN POWER_STATE powerState,
\r
1790 IN IO_STATUS_BLOCK *pIoStatus )
\r
1793 cl_pnp_po_ext_t *p_fdo;
\r
1795 HCA_ENTER( HCA_DBG_PO );
\r
1797 UNUSED_PARAM( minorFunction );
\r
1798 UNUSED_PARAM( powerState );
\r
1800 p_irp = (IRP*)context;
\r
1801 p_fdo = (cl_pnp_po_ext_t*)p_dev_obj->DeviceExtension;
\r
1803 /* Propagate the device IRP status to the system IRP status. */
\r
1804 p_irp->IoStatus.Status = pIoStatus->Status;
\r
1806 /* Continue Power IRP processing. */
\r
1807 PoStartNextPowerIrp( p_irp );
\r
1808 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
1809 IoReleaseRemoveLock( &p_fdo->remove_lock, p_irp );
\r
1810 HCA_EXIT( HCA_DBG_PO );
\r
1814 /*NOTE: Completion routines must NEVER be pageable. */
\r
1816 __SystemPowerCompletion(
\r
1817 IN DEVICE_OBJECT *p_dev_obj,
\r
1819 IN void *context )
\r
1822 POWER_STATE state;
\r
1823 PFDO_DEVICE_DATA p_fdo;
\r
1824 IO_STACK_LOCATION *pIoStack;
\r
1826 HCA_ENTER( HCA_DBG_PO );
\r
1828 UNUSED_PARAM( context );
\r
1830 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1831 pIoStack = IoGetCurrentIrpStackLocation( p_irp );
\r
1833 if( !NT_SUCCESS( p_irp->IoStatus.Status ) )
\r
1835 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PO,
\r
1836 ("IRP_MN_SET_POWER for system failed by lower driver with %08x.\n",
\r
1837 p_irp->IoStatus.Status));
\r
1838 status = STATUS_SUCCESS;
\r
1839 PoStartNextPowerIrp( p_irp );
\r
1843 state.DeviceState =
\r
1844 p_fdo->DevicePower[pIoStack->Parameters.Power.State.SystemState];
\r
1847 * Send a device power IRP to our devnode. Using our device object will
\r
1848 * only work on win2k and other NT based systems.
\r
1850 status = PoRequestPowerIrp( p_dev_obj, IRP_MN_SET_POWER, state,
\r
1851 __RequestPowerCompletion, p_irp, NULL );
\r
1853 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO,
\r
1854 ("PoRequestPowerIrp: SET_POWER 'PowerDeviceD%d', status %#x\n",
\r
1855 state.DeviceState - 1, status ));
\r
1857 if( status != STATUS_PENDING ) {
\r
1858 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PO,
\r
1859 ("PoRequestPowerIrp returned %08x.\n", status));
\r
1860 p_irp->IoStatus.Status = status; /* Propagate the failure. */
\r
1861 PoStartNextPowerIrp( p_irp );
\r
1862 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
1866 status = STATUS_MORE_PROCESSING_REQUIRED;
\r
1870 IoReleaseRemoveLock( &p_fdo->cl_ext.remove_lock, p_irp );
\r
1872 HCA_EXIT( HCA_DBG_PO );
\r
1877 /* Work item callback to handle DevicePowerD0 IRPs at passive level. */
\r
1879 __DevicePowerUpCompletionWorkItem(
\r
1880 IN DEVICE_OBJECT* p_dev_obj,
\r
1881 IN void* context )
\r
1885 IO_STACK_LOCATION *pIoStack;
\r
1886 PFDO_DEVICE_DATA p_fdo;
\r
1888 POWER_STATE powerState;
\r
1890 HCA_ENTER( HCA_DBG_PO );
\r
1892 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1893 p_irp = (IRP*)context;
\r
1894 pIoStack = IoGetCurrentIrpStackLocation( p_irp );
\r
1896 IoFreeWorkItem( p_fdo->pPoWorkItem );
\r
1897 p_fdo->pPoWorkItem = NULL;
\r
1899 /* restart the HCA */
\r
1900 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO,
\r
1901 ("***** Restart the HCA, IRQL %d\n", KeGetCurrentIrql()));
\r
1903 /* get MLX4_BUS IB interface */
\r
1904 status = __get_ifc( p_dev_obj, &MLX4_BUS_IB_INTERFACE_GUID,
\r
1905 sizeof(MLX4_BUS_IB_INTERFACE), MLX4_BUS_IB_INTERFACE_VERSION, NULL, (PINTERFACE)&p_fdo->bus_ib_ifc);
\r
1906 if( !NT_SUCCESS( status ) ) {
\r
1907 HCA_PRINT(TRACE_LEVEL_ERROR, HCA_DBG_PNP, ("Getting MLX4 BUS interface failed: status=0x%x\n", status));
\r
1910 p_fdo->bus_ib_ifc_taken = TRUE;
\r
1911 p_fdo->bus_ib_ifc.p_ibdev->x.p_fdo = p_fdo;
\r
1913 /* get node GUID */
\r
1914 err = __get_dev_info( p_fdo, &p_fdo->hca.guid, &p_fdo->hca.hw_ver );
\r
1917 HCA_PRINT(TRACE_LEVEL_ERROR ,HCA_DBG_LOW ,
\r
1918 ("can't get guid - ib_query_device() failed (%08X)\n", err ));
\r
1919 //TODO: no cleanup on error
\r
1923 p_fdo->DevicePowerState = pIoStack->Parameters.Power.State.DeviceState;
\r
1924 powerState = PoSetPowerState( p_dev_obj, DevicePowerState,
\r
1925 pIoStack->Parameters.Power.State );
\r
1927 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO,
\r
1928 ("PoSetPowerState: old state %d, new state to %d\n",
\r
1929 powerState.DeviceState, p_fdo->DevicePowerState ));
\r
1934 /* Flag device as having failed. */
\r
1935 p_fdo->pnpState |= PNP_DEVICE_FAILED;
\r
1936 IoInvalidateDeviceState( p_fdo->cl_ext.p_pdo );
\r
1938 PoStartNextPowerIrp( p_irp );
\r
1939 IoCompleteRequest( p_irp, IO_NO_INCREMENT );
\r
1940 IoReleaseRemoveLock( &p_fdo->cl_ext.remove_lock, p_irp );
\r
1941 HCA_EXIT( HCA_DBG_PO );
\r
1944 /*NOTE: Completion routines must NEVER be pageable. */
\r
1946 __DevicePowerUpCompletion(
\r
1947 IN DEVICE_OBJECT *p_dev_obj,
\r
1949 IN void *context )
\r
1951 NTSTATUS status = STATUS_SUCCESS;
\r
1952 PFDO_DEVICE_DATA p_fdo;
\r
1953 IO_STACK_LOCATION *pIoStack;
\r
1955 HCA_ENTER( HCA_DBG_PO );
\r
1957 UNUSED_PARAM( context );
\r
1959 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
1960 pIoStack = IoGetCurrentIrpStackLocation( p_irp );
\r
1962 if( !NT_SUCCESS( p_irp->IoStatus.Status ) ) {
\r
1963 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PO,
\r
1964 ("IRP_MN_SET_POWER for device failed by lower driver with %08x.\n",
\r
1965 p_irp->IoStatus.Status));
\r
1966 status = STATUS_SUCCESS;
\r
1967 PoStartNextPowerIrp( p_irp );
\r
1971 /* Process in a work item - mthca_start blocks. */
\r
1972 ASSERT( !p_fdo->pPoWorkItem );
\r
1973 p_fdo->pPoWorkItem = IoAllocateWorkItem( p_dev_obj );
\r
1974 if( !p_fdo->pPoWorkItem ) {
\r
1975 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PO,
\r
1976 ("Failed to allocate work item.\n" ));
\r
1977 status = STATUS_SUCCESS;
\r
1978 p_fdo->pnpState |= PNP_DEVICE_FAILED;
\r
1979 IoInvalidateDeviceState( p_fdo->cl_ext.p_pdo );
\r
1980 PoStartNextPowerIrp( p_irp );
\r
1984 /* Process in work item callback. */
\r
1985 IoMarkIrpPending( p_irp );
\r
1986 IoQueueWorkItem( p_fdo->pPoWorkItem,
\r
1987 __DevicePowerUpCompletionWorkItem, DelayedWorkQueue, p_irp );
\r
1988 status = STATUS_MORE_PROCESSING_REQUIRED;
\r
1992 IoReleaseRemoveLock( &p_fdo->cl_ext.remove_lock, p_irp );
\r
1994 HCA_EXIT( HCA_DBG_PO );
\r
1998 static NTSTATUS __DevicePowerDownWorkItemCompletion(
\r
1999 IN DEVICE_OBJECT *p_dev_obj,
\r
2001 IN void *context )
\r
2003 PFDO_DEVICE_DATA p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
2004 UNUSED_PARAM( context );
\r
2006 HCA_ENTER( HCA_DBG_PO );
\r
2008 PoStartNextPowerIrp( p_irp );
\r
2009 IoReleaseRemoveLock( &p_fdo->cl_ext.remove_lock, p_irp );
\r
2011 HCA_EXIT( HCA_DBG_PO );
\r
2012 return STATUS_SUCCESS;
\r
2015 /* Work item callback to handle DevicePowerD3 IRPs at passive level. */
\r
2017 __DevicePowerDownWorkItem(
\r
2018 IN DEVICE_OBJECT* p_dev_obj,
\r
2019 IN void* context )
\r
2021 IO_STACK_LOCATION *pIoStack;
\r
2022 PFDO_DEVICE_DATA p_fdo;
\r
2024 POWER_STATE powerState;
\r
2026 HCA_ENTER( HCA_DBG_PO );
\r
2028 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
2029 p_irp = (IRP*)context;
\r
2030 pIoStack = IoGetCurrentIrpStackLocation( p_irp );
\r
2032 IoFreeWorkItem( p_fdo->pPoWorkItem );
\r
2033 p_fdo->pPoWorkItem = NULL;
\r
2035 p_fdo->DevicePowerState = pIoStack->Parameters.Power.State.DeviceState;
\r
2036 powerState = PoSetPowerState( p_dev_obj, DevicePowerState,
\r
2037 pIoStack->Parameters.Power.State );
\r
2039 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO,
\r
2040 ("PoSetPowerState: old state %d, new state to %d, IRQL %d\n",
\r
2041 powerState.DeviceState, p_fdo->DevicePowerState, KeGetCurrentIrql() ));
\r
2043 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO,
\r
2044 ("***** Remove the HCA \n"));
\r
2046 // release MLX4_BUS resources
\r
2047 if(p_fdo->bus_ib_ifc_taken) {
\r
2048 p_fdo->bus_ib_ifc_taken = FALSE;
\r
2049 __put_ifc( (PINTERFACE)&p_fdo->bus_ib_ifc );
\r
2052 IoCopyCurrentIrpStackLocationToNext( p_irp );
\r
2053 #pragma warning( push, 3 )
\r
2054 IoSetCompletionRoutine( p_irp, __DevicePowerDownWorkItemCompletion,
\r
2055 NULL, TRUE, TRUE, TRUE );
\r
2056 #pragma warning( pop )
\r
2057 PoCallDriver( p_fdo->cl_ext.p_next_do, p_irp );
\r
2059 HCA_EXIT( HCA_DBG_PO );
\r
2065 IN DEVICE_OBJECT* const p_dev_obj,
\r
2066 IN IRP* const p_irp,
\r
2067 OUT cl_irp_action_t* const p_action )
\r
2070 IO_STACK_LOCATION *pIoStack;
\r
2071 PFDO_DEVICE_DATA p_fdo;
\r
2073 HCA_ENTER( HCA_DBG_PO );
\r
2075 p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
\r
2076 pIoStack = IoGetCurrentIrpStackLocation( p_irp );
\r
2078 HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO,
\r
2079 ("SET_POWER for FDO %p (ext %p): type %s, state %d, action %d, IRQL %d \n",
\r
2081 (pIoStack->Parameters.Power.Type) ? "DevicePowerState" : "SystemPowerState",
\r
2082 pIoStack->Parameters.Power.State.DeviceState,
\r
2083 pIoStack->Parameters.Power.ShutdownType, KeGetCurrentIrql() ));
\r
2085 switch( pIoStack->Parameters.Power.Type )
\r
2087 case SystemPowerState:
\r
2088 p_fdo->SystemPowerState = pIoStack->Parameters.Power.State.SystemState;
\r
2091 * Process on the way up the stack. We cannot block since the
\r
2092 * power dispatch function can be called at elevated IRQL if the
\r
2093 * device is in a paging/hibernation/crash dump path.
\r
2095 IoMarkIrpPending( p_irp );
\r
2096 IoCopyCurrentIrpStackLocationToNext( p_irp );
\r
2097 #pragma warning( push, 3 )
\r
2098 IoSetCompletionRoutine( p_irp, __SystemPowerCompletion, NULL,
\r
2099 TRUE, TRUE, TRUE );
\r
2100 #pragma warning( pop )
\r
2101 PoCallDriver( p_fdo->cl_ext.p_next_do, p_irp );
\r
2103 *p_action = IrpDoNothing;
\r
2104 status = STATUS_PENDING;
\r
2107 case DevicePowerState:
\r
2108 IoMarkIrpPending( p_irp );
\r
2109 if( pIoStack->Parameters.Power.State.DeviceState == PowerDeviceD0 &&
\r
2110 p_fdo->SystemPowerState == PowerSystemWorking)
\r
2112 /* If we're already powered up, just pass down. */
\r
2113 if( p_fdo->DevicePowerState == PowerDeviceD0 )
\r
2115 status = STATUS_SUCCESS;
\r
2116 *p_action = IrpIgnore;
\r
2120 /* Process in I/O completion callback. */
\r
2121 IoCopyCurrentIrpStackLocationToNext( p_irp );
\r
2122 #pragma warning( push, 3 )
\r
2123 IoSetCompletionRoutine( p_irp, __DevicePowerUpCompletion, NULL,
\r
2124 TRUE, TRUE, TRUE );
\r
2125 #pragma warning( pop )
\r
2126 PoCallDriver( p_fdo->cl_ext.p_next_do, p_irp );
\r
2129 { /* power down */
\r
2131 /* Process in a work item - deregister_ca and HcaDeinit block. */
\r
2132 ASSERT( !p_fdo->pPoWorkItem );
\r
2133 p_fdo->pPoWorkItem = IoAllocateWorkItem( p_dev_obj );
\r
2134 if( !p_fdo->pPoWorkItem )
\r
2136 status = STATUS_INSUFFICIENT_RESOURCES;
\r
2140 /* Process in work item callback. */
\r
2142 p_fdo->pPoWorkItem, __DevicePowerDownWorkItem, DelayedWorkQueue, p_irp );
\r
2144 *p_action = IrpDoNothing;
\r
2145 status = STATUS_PENDING;
\r
2149 /* Pass down and let the PDO driver handle it. */
\r
2150 *p_action = IrpIgnore;
\r
2151 status = STATUS_SUCCESS;
\r
2155 if( !NT_SUCCESS( status ) )
\r
2156 *p_action = IrpComplete;
\r
2158 HCA_EXIT( HCA_DBG_PNP );
\r
2163 hca_init_vfptr( void )
\r
2165 vfptrHcaPnp.identity = "MLX4_HCA driver";
\r
2166 vfptrHcaPnp.pfn_start = hca_start;
\r
2167 vfptrHcaPnp.pfn_query_stop = hca_query_stop;
\r
2168 vfptrHcaPnp.pfn_stop = hca_stop;
\r
2169 vfptrHcaPnp.pfn_cancel_stop = hca_cancel_stop;
\r
2170 vfptrHcaPnp.pfn_query_remove = hca_query_remove;
\r
2171 vfptrHcaPnp.pfn_release_resources = hca_release_resources;
\r
2172 vfptrHcaPnp.pfn_remove = cl_do_remove;
\r
2173 vfptrHcaPnp.pfn_cancel_remove = hca_cancel_remove;
\r
2174 vfptrHcaPnp.pfn_surprise_remove = hca_surprise_remove;
\r
2175 vfptrHcaPnp.pfn_query_capabilities = hca_query_capabilities;
\r
2176 vfptrHcaPnp.pfn_query_pnp_state = hca_query_pnp_state;
\r
2177 vfptrHcaPnp.pfn_filter_res_req = cl_irp_skip;
\r
2178 vfptrHcaPnp.pfn_dev_usage_notification = cl_do_sync_pnp;
\r
2179 vfptrHcaPnp.pfn_query_bus_relations = cl_irp_ignore;
\r
2180 vfptrHcaPnp.pfn_query_ejection_relations = cl_irp_ignore;
\r
2181 vfptrHcaPnp.pfn_query_removal_relations = cl_irp_ignore;
\r
2182 vfptrHcaPnp.pfn_query_target_relations = cl_irp_ignore;
\r
2183 vfptrHcaPnp.pfn_unknown = cl_irp_ignore;
\r
2184 vfptrHcaPnp.pfn_query_resources = cl_irp_ignore;
\r
2185 vfptrHcaPnp.pfn_query_res_req = cl_irp_ignore;
\r
2186 vfptrHcaPnp.pfn_query_bus_info = cl_irp_ignore;
\r
2187 vfptrHcaPnp.pfn_query_interface = hca_query_interface;
\r
2188 vfptrHcaPnp.pfn_read_config = cl_irp_ignore;
\r
2189 vfptrHcaPnp.pfn_write_config = cl_irp_ignore;
\r
2190 vfptrHcaPnp.pfn_eject = cl_irp_ignore;
\r
2191 vfptrHcaPnp.pfn_set_lock = cl_irp_ignore;
\r
2192 vfptrHcaPnp.pfn_query_power = hca_query_power;
\r
2193 vfptrHcaPnp.pfn_set_power = hca_set_power;
\r
2194 vfptrHcaPnp.pfn_power_sequence = cl_irp_ignore;
\r
2195 vfptrHcaPnp.pfn_wait_wake = cl_irp_ignore;
\r
2200 IN UNICODE_STRING* const p_registry_path )
\r
2203 /* Remember the terminating entry in the table below. */
\r
2204 RTL_QUERY_REGISTRY_TABLE table[3];
\r
2206 HCA_ENTER( HCA_DBG_PNP );
\r
2208 RtlInitUnicodeString( &g_param_path, NULL );
\r
2209 g_param_path.MaximumLength = p_registry_path->Length +
\r
2210 sizeof(L"\\Parameters");
\r
2211 g_param_path.Buffer = cl_zalloc( g_param_path.MaximumLength );
\r
2212 if( !g_param_path.Buffer )
\r
2214 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
2215 ("Failed to allocate parameters path buffer.\n"));
\r
2216 return STATUS_INSUFFICIENT_RESOURCES;
\r
2219 RtlAppendUnicodeStringToString( &g_param_path, p_registry_path );
\r
2220 RtlAppendUnicodeToString( &g_param_path, L"\\Parameters" );
\r
2223 * Clear the table. This clears all the query callback pointers,
\r
2224 * and sets up the terminating table entry.
\r
2226 cl_memclr( table, sizeof(table) );
\r
2228 /* Setup the table entries. */
\r
2229 table[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
2230 table[0].Name = L"DebugLevel";
\r
2231 table[0].EntryContext = &g.DebugPrintLevel;
\r
2232 table[0].DefaultType = REG_DWORD;
\r
2233 table[0].DefaultData = &g.DebugPrintLevel;
\r
2234 table[0].DefaultLength = sizeof(ULONG);
\r
2237 table[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
2238 table[1].Name = L"DebugFlags";
\r
2239 table[1].EntryContext = &g.DebugPrintFlags;
\r
2240 table[1].DefaultType = REG_DWORD;
\r
2241 table[1].DefaultData = &g.DebugPrintFlags;
\r
2242 table[1].DefaultLength = sizeof(ULONG);
\r
2246 status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE,
\r
2247 g_param_path.Buffer, table, NULL, NULL );
\r
2249 HCA_EXIT( HCA_DBG_PNP );
\r
2255 IN PDRIVER_OBJECT p_driver_obj )
\r
2257 HCA_ENTER( HCA_DBG_PNP );
\r
2259 UNUSED_PARAM( p_driver_obj );
\r
2261 cl_free( g_param_path.Buffer );
\r
2263 HCA_EXIT( HCA_DBG_PNP );
\r
2264 #if defined(EVENT_TRACING)
\r
2265 WPP_CLEANUP(p_driver_obj);
\r
2272 IN PDEVICE_OBJECT p_dev_obj,
\r
2276 PFDO_DEVICE_DATA p_fdo;
\r
2278 HCA_ENTER( HCA_DBG_PNP );
\r
2280 p_fdo = p_dev_obj->DeviceExtension;
\r
2282 IoSkipCurrentIrpStackLocation( p_irp );
\r
2283 status = IoCallDriver( p_fdo->cl_ext.p_next_do, p_irp );
\r
2285 HCA_EXIT( HCA_DBG_PNP );
\r
2292 IN PDRIVER_OBJECT p_driver_obj,
\r
2293 IN PUNICODE_STRING p_registry_path )
\r
2296 #if defined(EVENT_TRACING)
\r
2297 WPP_INIT_TRACING(p_driver_obj ,p_registry_path);
\r
2299 // global initializations
\r
2300 g.DebugPrintLevel = TRACE_LEVEL_VERBOSE;
\r
2301 g.DebugPrintFlags = 0xffff;
\r
2303 HCA_ENTER( HCA_DBG_PNP );
\r
2304 HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_PNP,
\r
2305 ("Built %s %s, Version %s, RelDate %s\n",
\r
2306 __DATE__, __TIME__, DRV_VERSION, DRV_RELDATE));
\r
2308 status = mlnx_hcas_init();
\r
2309 if( status != STATUS_SUCCESS ) {
\r
2310 HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_PNP ,
\r
2311 ("mlnx_hcas_init returned %#x.\n", status));
\r
2315 status = __read_registry( p_registry_path );
\r
2316 if( !NT_SUCCESS( status ) )
\r
2318 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,
\r
2319 ("__read_registry_path returned 0x%X.\n", status));
\r
2323 /*leo: init function table */
\r
2326 p_driver_obj->MajorFunction[IRP_MJ_PNP] = cl_pnp;
\r
2327 p_driver_obj->MajorFunction[IRP_MJ_POWER] = cl_power;
\r
2328 p_driver_obj->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = hca_sysctl;
\r
2329 p_driver_obj->DriverUnload = hca_drv_unload;
\r
2330 p_driver_obj->DriverExtension->AddDevice = hca_add_device;
\r
2333 HCA_EXIT( HCA_DBG_PNP );
\r
2334 return STATUS_SUCCESS;
\r