[ofw] patch: [ibbus,hw] add power down support for IBBUS
Smith, Stan
stan.smith at intel.com
Tue Sep 8 12:07:54 PDT 2009
Hello,
To what degree and what types of testing has this patch under gone?
The '#if 0' blocks should be cleaned up.
I'd like to include this in WinOF 2.1 as on occasion there are BSOD during shutdown which I have been able to attribute to IBAL accessing the HCA driver after HCA has powered down.
Is this patch close to being ready for 2.1 ?
Your thoughts?
thanks,
stan.
________________________________
From: ofw-bounces at lists.openfabrics.org [mailto:ofw-bounces at lists.openfabrics.org] On Behalf Of Leonid Keller
Sent: Sunday, September 06, 2009 6:04 PM
To: ofw at lists.openfabrics.org
Subject: [ofw] patch: [ibbus,hw] add power down support for IBBUS
Mellanox HW doesn't support neither Standby nor hibernation.
To simulate such support, low-level driver resets HCA on power down and starts it up on power up.
IBBUS, continuing to work with HCA, produces BSODs.
This patch deregisters HCA from IBAL on power down and re-registers it on power up, thus preventing crashes on power down.
Index: core/bus/kernel/bus_driver.h
===================================================================
--- core/bus/kernel/bus_driver.h (revision 2421)
+++ core/bus/kernel/bus_driver.h (working copy)
@@ -125,6 +125,17 @@
struct _bus_filter_instance *bus_filter;
+ /* flag, indicating that FDO resources have been released */
+ boolean_t ca_registered;
+ /* current device power state */
+ DEVICE_POWER_STATE device_power_state;
+ /* current system power state */
+ SYSTEM_POWER_STATE system_power_state;
+ /* work item for power operations */
+ PIO_WORKITEM p_po_work_item;
+ /* current PnP state */
+ PNP_DEVICE_STATE pnp_state; /* state for PnP Manager */
+
} bus_fdo_ext_t;
Index: core/bus/kernel/bus_iou_mgr.c
===================================================================
--- core/bus/kernel/bus_iou_mgr.c (revision 2421)
+++ core/bus/kernel/bus_iou_mgr.c (working copy)
@@ -1658,7 +1658,9 @@
if ((p_io_stack->Parameters.Power.Type == SystemPowerState) &&
(p_io_stack->Parameters.Power.State.SystemState ==PowerSystemHibernate ||
- p_io_stack->Parameters.Power.State.SystemState ==PowerSystemSleeping1 ))
+ p_io_stack->Parameters.Power.State.SystemState ==PowerSystemSleeping1 ||
+ p_io_stack->Parameters.Power.State.SystemState ==PowerSystemSleeping2 ||
+ p_io_stack->Parameters.Power.State.SystemState ==PowerSystemSleeping3 ))
{
BUS_TRACE( BUS_DBG_POWER, ("Setting b_hibernating flag for PDO %p \n", p_dev_obj));
p_ext->b_hibernating = TRUE;
Index: core/bus/kernel/bus_pnp.c
===================================================================
--- core/bus/kernel/bus_pnp.c (revision 2421)
+++ core/bus/kernel/bus_pnp.c (working copy)
@@ -49,6 +49,7 @@
#include "iba/ib_cm_ifc.h"
#include "al_cm_cep.h"
#include "al_mgr.h"
+#include "bus_ev_log.h"
/* Interface names are generated by IoRegisterDeviceInterface. */
@@ -113,6 +114,13 @@
IN IO_STACK_LOCATION* const p_io_stack );
static NTSTATUS
+fdo_query_pnp_state(
+ IN DEVICE_OBJECT* const p_dev_obj,
+ IN IRP* const p_irp,
+ OUT cl_irp_action_t* const p_action );
+
+
+static NTSTATUS
fdo_query_interface(
IN DEVICE_OBJECT* const p_dev_obj,
IN IRP* const p_irp,
@@ -150,8 +158,8 @@
cl_do_sync_pnp,
cl_irp_skip,
fdo_query_capabilities,
+ fdo_query_pnp_state,
cl_irp_skip,
- cl_irp_skip,
cl_do_sync_pnp,
fdo_query_bus_relations,
cl_irp_ignore,
@@ -245,8 +253,7 @@
}
p_ext = p_dev_obj->DeviceExtension;
- p_ext->n_al_ifc_ref = 0;
- p_ext->n_ci_ifc_ref = 0;
+ cl_memclr( p_ext, sizeof(bus_fdo_ext_t) );
p_next_do = IoAttachDeviceToDeviceStack( p_dev_obj, p_pdo );
if( !p_next_do )
@@ -383,7 +390,54 @@
return status;
}
+
static NTSTATUS
+__register_ca(
+ IN DEVICE_OBJECT* const p_dev_obj
+ )
+{
+ NTSTATUS status;
+ bus_fdo_ext_t *p_ext;
+ ib_api_status_t ib_status;
+ bus_filter_t *p_bfi;
+
+ BUS_ENTER( BUS_DBG_PNP );
+
+ p_ext = p_dev_obj->DeviceExtension;
+ p_bfi = p_ext->bus_filter;
+
+ /* get HCA verbs interface */
+ status = __get_ifc( p_dev_obj, &GUID_RDMA_INTERFACE_VERBS,
+ sizeof(RDMA_INTERFACE_VERBS),
+ VerbsVersion(VERBS_MAJOR_VER, VERBS_MINOR_VER),
+ p_ext, (PINTERFACE)&p_ext->hca_ifc );
+ if( !NT_SUCCESS( status ) )
+ {
+ BUS_TRACE_EXIT(BUS_DBG_PNP,
+ ("Getting MLX4 BUS interface failed: status=0x%x\n", status));
+ return STATUS_UNSUCCESSFUL;
+ }
+ p_ext->hca_ifc_taken = TRUE;
+
+ /* bind BFI to HCA by CA GUID. Have to be before ib_register_ca */
+ p_bfi->ca_guid = p_ext->hca_ifc.Verbs.guid;
+
+ /* register HCA */
+ ib_status = ib_register_ca( &p_ext->hca_ifc.Verbs, p_ext->cl_ext.p_pdo, p_dev_obj );
+ if( ib_status != IB_SUCCESS )
+ {
+ BUS_TRACE_EXIT( BUS_DBG_ERROR, ("ib_register_ca returned %s.\n",
+ ib_get_err_str(ib_status)) );
+ return STATUS_UNSUCCESSFUL;
+ }
+ BUS_TRACE_EXIT(BUS_DBG_PNP, ("%s bound to CA guid %I64x\n",
+ p_bfi->whoami,p_bfi->ca_guid));
+
+ p_ext->ca_registered = TRUE;
+ return status;
+}
+
+static NTSTATUS
fdo_start(
IN DEVICE_OBJECT* const p_dev_obj,
IN IRP* const p_irp,
@@ -399,6 +453,7 @@
p_ext = p_dev_obj->DeviceExtension;
p_bfi = p_ext->bus_filter;
+ ASSERT( !p_ext->ca_registered );
/* Handled on the way up. */
status = cl_do_sync_pnp( p_dev_obj, p_irp, p_action );
@@ -408,6 +463,7 @@
("Lower drivers failed IRP_MN_START_DEVICE.\n") );
return status;
}
+ p_ext->device_power_state = PowerDeviceD0;
lock_control_event();
if ( !gp_async_proc_mgr ) {
@@ -444,6 +500,11 @@
return STATUS_UNSUCCESSFUL;
}
+ /* start IBAL */
+ status = __register_ca( p_dev_obj );
+ if( !NT_SUCCESS( status ) )
+ return status;
+
if ( AL_init_here ) {
status = IoSetDeviceInterfaceState( &al_ifc_name, TRUE );
ASSERT( NT_SUCCESS( status ) );
@@ -455,33 +516,9 @@
ASSERT( NT_SUCCESS( status ) );
}
- /* get HCA verbs interface */
- status = __get_ifc( p_dev_obj, &GUID_RDMA_INTERFACE_VERBS,
- sizeof(RDMA_INTERFACE_VERBS),
- VerbsVersion(VERBS_MAJOR_VER, VERBS_MINOR_VER),
- p_ext, (PINTERFACE)&p_ext->hca_ifc );
- if( !NT_SUCCESS( status ) )
- {
- BUS_TRACE_EXIT(BUS_DBG_PNP,
- ("Getting MLX4 BUS interface failed: status=0x%x\n", status));
- return STATUS_UNSUCCESSFUL;
- }
- p_ext->hca_ifc_taken = TRUE;
+ CL_PRINT_TO_EVENT_LOG( p_dev_obj, EVENT_IBBUS_ANY_INFO,
+ ("IBBUS started \n" ));
- /* bind BFI to HCA by CA GUID. Have to be before ib_register_ca */
- p_bfi->ca_guid = p_ext->hca_ifc.Verbs.guid;
-
- /* register HCA */
- ib_status = ib_register_ca( &p_ext->hca_ifc.Verbs, p_ext->cl_ext.p_pdo, p_dev_obj );
- if( ib_status != IB_SUCCESS )
- {
- BUS_TRACE_EXIT( BUS_DBG_ERROR, ("ib_register_ca returned %s.\n",
- ib_get_err_str(ib_status)) );
- return STATUS_UNSUCCESSFUL;
- }
-
- BUS_TRACE_EXIT(BUS_DBG_PNP, ("%s bound to CA guid %I64x\n",
- p_bfi->whoami,p_bfi->ca_guid));
return status;
}
@@ -537,6 +574,40 @@
}
+static void
+__deregister_ca(
+ IN DEVICE_OBJECT* const p_dev_obj )
+{
+ bus_fdo_ext_t *p_ext;
+ bus_filter_t *p_bfi;
+ ib_api_status_t ib_status;
+
+ BUS_ENTER( BUS_DBG_PNP );
+
+ p_ext = p_dev_obj->DeviceExtension;
+ p_bfi = p_ext->bus_filter;
+
+ if ( !p_ext->ca_registered )
+ return;
+ p_ext->ca_registered = FALSE;
+
+ //TODO: Fail outstanding I/O operations.
+
+ ib_status = ib_deregister_ca( p_ext->hca_ifc.Verbs.guid );
+ if( ib_status != IB_SUCCESS ) {
+ BUS_PRINT( BUS_DBG_ERROR, ("ib_deregister_ca returned %s.\n",
+ ib_get_err_str(ib_status)) );
+ }
+
+ if ( p_ext->hca_ifc_taken ) {
+ p_ext->hca_ifc.InterfaceHeader.InterfaceDereference(
+ p_ext->hca_ifc.InterfaceHeader.Context);
+ p_ext->hca_ifc_taken = FALSE;
+ }
+
+ BUS_EXIT( BUS_DBG_PNP );
+}
+
/*
* This function gets called after releasing the remove lock and waiting
* for all other threads to release the lock. No more modifications will
@@ -550,7 +621,6 @@
NTSTATUS status;
bus_filter_t *p_bfi;
int ic;
- ib_api_status_t ib_status;
BUS_ENTER( BUS_DBG_PNP );
@@ -560,20 +630,17 @@
p_bfi = p_ext->bus_filter;
CL_ASSERT( p_bfi );
- //TODO: Fail outstanding I/O operations.
+ __deregister_ca( p_dev_obj );
- ib_status = ib_deregister_ca( p_ext->hca_ifc.Verbs.guid );
- if( ib_status != IB_SUCCESS ) {
- BUS_PRINT( BUS_DBG_ERROR, ("ib_deregister_ca returned %s.\n",
- ib_get_err_str(ib_status)) );
- }
-
if ( p_bfi->p_port_mgr )
cl_obj_destroy( p_bfi->p_port_mgr_obj );
if ( p_bfi->p_iou_mgr )
cl_obj_destroy( p_bfi->p_iou_mgr_obj );
+#if 0
+ // IBAL has no right to work with CA after it deregister.
+ // So there is no need to release interface only after IBAL cleanup
/* if not last HCA then release IFC reference, otherwise release IFC after
* IBAL has shutdown; keep the HCA present until IBAL is terminated.
@@ -583,6 +650,7 @@
p_ext->hca_ifc.InterfaceHeader.Context);
p_ext->hca_ifc_taken = FALSE;
}
+#endif
BUS_TRACE( BUS_DBG_PNP, ("Releasing BusFilter %s\n", p_bfi->whoami ));
if (p_bfi) {
@@ -623,6 +691,10 @@
CL_ASSERT( !gp_async_proc_mgr && !gp_async_pnp_mgr && !gp_al_mgr );
+#if 0
+ // IBAL has no right to work with CA after it deregister.
+ // So there is no need to release interface only after IBAL cleanup
+
/* AL needs the HCA to stick around until AL cleanup has completed.
* Now that it's done, let the HCA fade away.
*/
@@ -631,6 +703,7 @@
p_ext->hca_ifc.InterfaceHeader.Context);
p_ext->hca_ifc_taken = FALSE;
}
+#endif
BUS_EXIT( BUS_DBG_PNP );
}
@@ -1082,7 +1155,27 @@
return STATUS_SUCCESS;
}
+static NTSTATUS
+fdo_query_pnp_state(
+ IN DEVICE_OBJECT* const p_dev_obj,
+ IN IRP* const p_irp,
+ OUT cl_irp_action_t* const p_action )
+{
+ bus_fdo_ext_t *p_ext;
+ BUS_ENTER( BUS_DBG_PNP );
+
+ p_ext = (bus_fdo_ext_t*)p_dev_obj->DeviceExtension;
+
+ p_irp->IoStatus.Information |= p_ext->pnp_state;
+
+ *p_action = IrpSkip;
+
+ BUS_EXIT( BUS_DBG_PNP );
+ return STATUS_SUCCESS;;
+}
+
+
static NTSTATUS
fdo_query_interface(
IN DEVICE_OBJECT* const p_dev_obj,
@@ -1153,7 +1246,9 @@
switch( p_io_stack->Parameters.Power.State.SystemState )
{
case PowerSystemHibernate:
- case PowerSystemSleeping1: // STANDBY support
+ case PowerSystemSleeping1: // STANDBY support
+ case PowerSystemSleeping2: // STANDBY support
+ case PowerSystemSleeping3: // STANDBY support
case PowerSystemWorking:
case PowerSystemShutdown:
break;
@@ -1188,91 +1283,187 @@
}
+
+/* Work item callback to handle DevicePowerD0 IRPs at passive level. */
+
static void
-__request_power_completion(
- IN DEVICE_OBJECT *p_dev_obj,
- IN UCHAR minor_function,
- IN POWER_STATE power_state,
- IN void *context,
- IN IO_STATUS_BLOCK *p_io_status )
+__device_power_up_completion_workItem(
+ IN DEVICE_OBJECT* p_dev_obj,
+ IN void* context )
{
+ NTSTATUS status;
+ IO_STACK_LOCATION *p_io_stack;
+ bus_fdo_ext_t *p_ext;
IRP *p_irp;
- cl_pnp_po_ext_t *p_ext;
+ POWER_STATE power_state;
- BUS_ENTER( BUS_DBG_PNP );
+ BUS_ENTER( BUS_DBG_POWER );
- UNUSED_PARAM( minor_function );
- UNUSED_PARAM( power_state );
-
+ p_ext = (bus_fdo_ext_t*)p_dev_obj->DeviceExtension;
p_irp = (IRP*)context;
- p_ext = p_dev_obj->DeviceExtension;
+ p_io_stack = IoGetCurrentIrpStackLocation( p_irp );
- /* Propagate the device IRP status to the system IRP status. */
- p_irp->IoStatus.Status = p_io_status->Status;
+ IoFreeWorkItem( p_ext->p_po_work_item );
+ p_ext->p_po_work_item = NULL;
- /* Continue Power IRP processing. */
+ /* re-register CA */
+ BUS_PRINT( BUS_DBG_POWER,
+ ("***** re-register CA, IRQL %d\n", KeGetCurrentIrql()));
+
+ status = __register_ca( p_dev_obj );
+ if( !NT_SUCCESS( status ) ) {
+ BUS_PRINT( BUS_DBG_POWER,
+ ("!!! __register_ca failed (%#x) \n", status));
+ goto err_fdo_start;
+ }
+
+ p_ext->device_power_state = p_io_stack->Parameters.Power.State.DeviceState;
+ power_state = PoSetPowerState( p_dev_obj, DevicePowerState,
+ p_io_stack->Parameters.Power.State );
+
+ BUS_PRINT( BUS_DBG_POWER,
+ ("PoSetPowerState: old state %d, new state to %d\n",
+ power_state.DeviceState, p_ext->device_power_state ));
+
+ CL_PRINT_TO_EVENT_LOG( p_dev_obj, EVENT_IBBUS_ANY_WARN,
+ ("Power increased to: device %d, system %d.\n",
+ (int)p_ext->device_power_state, (int)p_ext->system_power_state));
+
+ goto exit;
+
+err_fdo_start:
+ /* Flag device as having failed. */
+ p_ext->pnp_state |= PNP_DEVICE_FAILED;
+ IoInvalidateDeviceState( p_ext->cl_ext.p_pdo );
+exit:
PoStartNextPowerIrp( p_irp );
IoCompleteRequest( p_irp, IO_NO_INCREMENT );
- IoReleaseRemoveLock( &p_ext->remove_lock, p_irp );
- BUS_EXIT( BUS_DBG_PNP );
+ IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );
+ BUS_EXIT( BUS_DBG_POWER );
}
/*NOTE: Completion routines must NEVER be pageable. */
static NTSTATUS
-__set_power_completion(
+__device_power_up_completion(
IN DEVICE_OBJECT *p_dev_obj,
IN IRP *p_irp,
IN void *context )
{
- NTSTATUS status;
- POWER_STATE state;
+ NTSTATUS status = STATUS_SUCCESS;
bus_fdo_ext_t *p_ext;
IO_STACK_LOCATION *p_io_stack;
- BUS_ENTER( BUS_DBG_PNP );
+ BUS_ENTER( BUS_DBG_POWER );
UNUSED_PARAM( context );
- p_ext = p_dev_obj->DeviceExtension;
+ p_ext = (bus_fdo_ext_t*)p_dev_obj->DeviceExtension;
p_io_stack = IoGetCurrentIrpStackLocation( p_irp );
- if( !NT_SUCCESS( p_irp->IoStatus.Status ) )
- {
+ if( !NT_SUCCESS( p_irp->IoStatus.Status ) ) {
+ BUS_PRINT( BUS_DBG_POWER,
+ ("IRP_MN_SET_POWER for device failed by lower driver with %08x.\n",
+ p_irp->IoStatus.Status));
+ status = STATUS_SUCCESS;
PoStartNextPowerIrp( p_irp );
- IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );
- BUS_TRACE_EXIT( BUS_DBG_ERROR,
- ("IRP_MN_SET_POWER for system failed by lower driver with %08x.\n",
- p_irp->IoStatus.Status) );
- return STATUS_SUCCESS;
+ goto release;
}
- state.DeviceState =
- p_ext->po_state[p_io_stack->Parameters.Power.State.SystemState];
-
- /*
- * Send a device power IRP to our devnode. Using our device object will
- * only work on win2k and other NT based systems.
- */
- status = PoRequestPowerIrp( p_dev_obj, IRP_MN_SET_POWER, state,
- __request_power_completion, p_irp, NULL );
-
- if( status != STATUS_PENDING )
- {
+ /* Process in a work item to allow blocking. */
+ ASSERT( !p_ext->p_po_work_item );
+ p_ext->p_po_work_item = IoAllocateWorkItem( p_dev_obj );
+ if( !p_ext->p_po_work_item ) {
+ BUS_PRINT( BUS_DBG_POWER,
+ ("Failed to allocate work item.\n" ));
+ status = STATUS_SUCCESS;
+ p_ext->pnp_state |= PNP_DEVICE_FAILED;
+ IoInvalidateDeviceState( p_ext->cl_ext.p_pdo );
PoStartNextPowerIrp( p_irp );
- /* Propagate the failure. */
- p_irp->IoStatus.Status = status;
- IoCompleteRequest( p_irp, IO_NO_INCREMENT );
- IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );
- BUS_TRACE( BUS_DBG_ERROR,
- ("PoRequestPowerIrp returned %08x.\n", status) );
+ goto release;
}
- BUS_EXIT( BUS_DBG_PNP );
- return STATUS_MORE_PROCESSING_REQUIRED;
+ /* Process in work item callback. */
+ IoMarkIrpPending( p_irp );
+ IoQueueWorkItem( p_ext->p_po_work_item,
+ __device_power_up_completion_workItem, DelayedWorkQueue, p_irp );
+ status = STATUS_MORE_PROCESSING_REQUIRED;
+ goto exit;
+
+release:
+ IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );
+exit:
+ BUS_EXIT( BUS_DBG_POWER );
+ return status;
}
+static NTSTATUS __device_power_down_workItem_completion(
+ IN DEVICE_OBJECT *p_dev_obj,
+ IN IRP *p_irp,
+ IN void *context )
+{
+ bus_fdo_ext_t *p_ext = (bus_fdo_ext_t*)p_dev_obj->DeviceExtension;
+ UNUSED_PARAM( context );
+
+ BUS_ENTER( BUS_DBG_POWER );
+
+ PoStartNextPowerIrp( p_irp );
+ IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );
+
+ BUS_EXIT( BUS_DBG_POWER );
+ return STATUS_SUCCESS;
+}
+
+/* Work item callback to handle DevicePowerD3 IRPs at passive level. */
+static void
+__device_power_down_workItem(
+ IN DEVICE_OBJECT* p_dev_obj,
+ IN void* context )
+{
+ IO_STACK_LOCATION *p_io_stack;
+ bus_fdo_ext_t *p_ext;
+ IRP *p_irp;
+ POWER_STATE power_state;
+
+ BUS_ENTER( BUS_DBG_POWER );
+
+ p_ext = (bus_fdo_ext_t*)p_dev_obj->DeviceExtension;
+ p_irp = (IRP*)context;
+ p_io_stack = IoGetCurrentIrpStackLocation( p_irp );
+
+ IoFreeWorkItem( p_ext->p_po_work_item );
+ p_ext->p_po_work_item = NULL;
+
+ p_ext->device_power_state = p_io_stack->Parameters.Power.State.DeviceState;
+ power_state = PoSetPowerState( p_dev_obj, DevicePowerState,
+ p_io_stack->Parameters.Power.State );
+
+ BUS_PRINT( BUS_DBG_POWER,
+ ("PoSetPowerState: old state %d, new state to %d, IRQL %d\n",
+ power_state.DeviceState, p_ext->device_power_state, KeGetCurrentIrql() ));
+
+ CL_PRINT_TO_EVENT_LOG( p_dev_obj, EVENT_IBBUS_ANY_WARN,
+ ("Power decreased to: device %d, system %d.\n",
+ (int)p_ext->device_power_state, (int)p_ext->system_power_state));
+
+ BUS_PRINT( BUS_DBG_POWER,
+ ("***** deregister CA \n"));
+
+ __deregister_ca( p_dev_obj );
+
+ IoCopyCurrentIrpStackLocationToNext( p_irp );
+#pragma warning( push, 3 )
+ IoSetCompletionRoutine( p_irp, __device_power_down_workItem_completion,
+ NULL, TRUE, TRUE, TRUE );
+#pragma warning( pop )
+ PoCallDriver( p_ext->cl_ext.p_next_do, p_irp );
+
+ BUS_EXIT( BUS_DBG_POWER );
+}
+
+
+
static NTSTATUS
__fdo_set_power(
IN DEVICE_OBJECT* const p_dev_obj,
@@ -1289,35 +1480,63 @@
p_io_stack = IoGetCurrentIrpStackLocation( p_irp );
BUS_TRACE( BUS_DBG_POWER,
- ("SET_POWER for FDO %p (ext %p): type %s, state %d, action %d \n",
+ ("SET_POWER for FDO %p (ext %p): type %s, state %d, action %d, IRQL %d \n",
p_dev_obj, p_ext,
(p_io_stack->Parameters.Power.Type)
? "DevicePowerState" : "SystemPowerState",
p_io_stack->Parameters.Power.State.DeviceState,
- p_io_stack->Parameters.Power.ShutdownType ));
+ p_io_stack->Parameters.Power.ShutdownType, KeGetCurrentIrql() ));
switch( p_io_stack->Parameters.Power.Type )
{
case SystemPowerState:
-#if 0
- /*
- * Process on the way up the stack. We cannot block since the
- * power dispatch function can be called at elevated IRQL if the
- * device is in a paging/hibernation/crash dump path.
- */
+ /* Pass down and let the PDO driver handle it. */
+ p_ext->system_power_state = p_io_stack->Parameters.Power.State.SystemState;
+ *p_action = IrpIgnore;
+ status = STATUS_SUCCESS;
+ break;
+
+ case DevicePowerState:
IoMarkIrpPending( p_irp );
- IoCopyCurrentIrpStackLocationToNext( p_irp );
+ if( p_io_stack->Parameters.Power.State.DeviceState == PowerDeviceD0 &&
+ p_ext->system_power_state == PowerSystemWorking)
+ { /* power up */
+ /* If we're already powered up, just pass down. */
+ if( p_ext->device_power_state == PowerDeviceD0 )
+ {
+ status = STATUS_SUCCESS;
+ *p_action = IrpIgnore;
+ break;
+ }
+
+ /* Process in I/O completion callback. */
+ IoCopyCurrentIrpStackLocationToNext( p_irp );
#pragma warning( push, 3 )
- IoSetCompletionRoutine( p_irp, __set_power_completion, NULL,
- TRUE, TRUE, TRUE );
+ IoSetCompletionRoutine( p_irp, __device_power_up_completion, NULL,
+ TRUE, TRUE, TRUE );
#pragma warning( pop )
- PoCallDriver( p_ext->cl_ext.p_next_do, p_irp );
+ PoCallDriver( p_ext->cl_ext.p_next_do, p_irp );
+ }
+ else
+ { /* power down */
+ /* Process in a work item - deregister_ca and HcaDeinit block. */
+ ASSERT( !p_ext->p_po_work_item );
+ p_ext->p_po_work_item = IoAllocateWorkItem( p_dev_obj );
+ if( !p_ext->p_po_work_item )
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+
+ /* Process in work item callback. */
+ IoQueueWorkItem(
+ p_ext->p_po_work_item, __device_power_down_workItem, DelayedWorkQueue, p_irp );
+ }
*p_action = IrpDoNothing;
status = STATUS_PENDING;
break;
-#endif
- case DevicePowerState:
+
default:
/* Pass down and let the PDO driver handle it. */
*p_action = IrpIgnore;
@@ -1325,6 +1544,9 @@
break;
}
+ if( !NT_SUCCESS( status ) )
+ *p_action = IrpComplete;
+
BUS_EXIT( BUS_DBG_POWER );
return status;
}
Index: core/bus/kernel/bus_port_mgr.c
===================================================================
--- core/bus/kernel/bus_port_mgr.c (revision 2421)
+++ core/bus/kernel/bus_port_mgr.c (working copy)
@@ -2106,7 +2106,9 @@
if ((p_io_stack->Parameters.Power.Type == SystemPowerState) &&
(p_io_stack->Parameters.Power.State.SystemState ==PowerSystemHibernate ||
- p_io_stack->Parameters.Power.State.SystemState ==PowerSystemSleeping1 ))
+ p_io_stack->Parameters.Power.State.SystemState ==PowerSystemSleeping1 ||
+ p_io_stack->Parameters.Power.State.SystemState ==PowerSystemSleeping2 ||
+ p_io_stack->Parameters.Power.State.SystemState ==PowerSystemSleeping3 ))
{
BUS_TRACE( BUS_DBG_POWER, ("Setting b_hibernating flag for PDO %p \n", p_dev_obj));
p_ext->b_hibernating = TRUE;
Index: hw/mlx4/kernel/bus/drv/drv.c
===================================================================
--- hw/mlx4/kernel/bus/drv/drv.c (revision 2421)
+++ hw/mlx4/kernel/bus/drv/drv.c (working copy)
@@ -437,7 +437,7 @@
MLX4_PRINT(TRACE_LEVEL_INFORMATION, MLX4_DBG_DRV, ("PreviousState 0x%x\n", PreviousState));
- // start card (needed after Hibernetion)
+ // start card (needed after Hibernation or standby)
if (PreviousState > WdfPowerDeviceD0)
status = __start_card( Device, p_fdo );
if ( !NT_SUCCESS( status ) )
Index: hw/mlx4/kernel/hca/drv.c
===================================================================
--- hw/mlx4/kernel/hca/drv.c (revision 2421)
+++ hw/mlx4/kernel/hca/drv.c (working copy)
@@ -76,12 +76,6 @@
#ifndef USE_WDM_FRAMEWORK
-//
-// TODO: add support for Hibernate/Standby as in WDM version below
-//
-
-
-
static ci_interface_t*
__alloc_hca_ifc(
IN PFDO_DEVICE_DATA const p_fdo )
@@ -197,10 +191,25 @@
IN WDF_POWER_DEVICE_STATE PreviousState
)
{
- UNUSED_PARAM(Device);
- UNUSED_PARAM(PreviousState);
+ NTSTATUS status;
+ PFDO_DEVICE_DATA p_fdo = FdoGetData(Device);
+
HCA_ENTER( HCA_DBG_PNP );
HCA_PRINT(TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, ("EvtDeviceD0Entry: PreviousState 0x%x\n", PreviousState));
+ // start card (needed after Hibernation or standby)
+ if (PreviousState > WdfPowerDeviceD0) {
+ /* get MLX4_BUS IB interface */
+ if ( !p_fdo->bus_ib_ifc_taken ) {
+ status = WdfFdoQueryForInterface( Device, &MLX4_BUS_IB_INTERFACE_GUID,
+ (PINTERFACE)&p_fdo->bus_ib_ifc, sizeof(MLX4_BUS_IB_INTERFACE), MLX4_BUS_IB_INTERFACE_VERSION, NULL );
+ if( !NT_SUCCESS( status ) ) {
+ HCA_PRINT(TRACE_LEVEL_ERROR, HCA_DBG_PNP, ("Getting MLX4 BUS interface failed: status=0x%x\n", status));
+ return status;
+ }
+ p_fdo->bus_ib_ifc_taken = TRUE;
+ p_fdo->bus_ib_ifc.p_ibdev->x.p_fdo = p_fdo;
+ }
+ }
HCA_EXIT( HCA_DBG_PNP );
return STATUS_SUCCESS;
}
@@ -220,6 +229,8 @@
switch (TargetState) {
case WdfPowerDeviceD1: /* hopefully, it is STANDBY state */
+ case WdfPowerDeviceD2: /* hopefully, it is STANDBY state */
+ case WdfPowerDeviceD3: /* hopefully, it is STANDBY state */
case WdfPowerDevicePrepareForHibernation:
if (atomic_read(&p_fdo->usecnt)) {
status = STATUS_UNSUCCESSFUL;
@@ -231,6 +242,14 @@
break;
}
+ if (TargetState > WdfPowerDeviceD0) {
+ if(p_fdo->bus_ib_ifc_taken) {
+ PINTERFACE p_ifc = (PINTERFACE)&p_fdo->bus_ib_ifc;
+ p_ifc->InterfaceDereference( p_ifc->Context );
+ p_fdo->bus_ib_ifc_taken = FALSE;
+ }
+ }
+
HCA_EXIT( HCA_DBG_PNP );
return status;
}
@@ -268,14 +287,16 @@
p_fdo->bus_pci_ifc_taken = TRUE;
/* get MLX4_BUS IB interface */
- status = WdfFdoQueryForInterface( Device, &MLX4_BUS_IB_INTERFACE_GUID,
- (PINTERFACE)&p_fdo->bus_ib_ifc, sizeof(MLX4_BUS_IB_INTERFACE), MLX4_BUS_IB_INTERFACE_VERSION, NULL );
- if( !NT_SUCCESS( status ) ) {
- HCA_PRINT(TRACE_LEVEL_ERROR, HCA_DBG_PNP, ("Getting MLX4 BUS interface failed: status=0x%x\n", status));
- return status;
+ if ( !p_fdo->bus_ib_ifc_taken ) {
+ status = WdfFdoQueryForInterface( Device, &MLX4_BUS_IB_INTERFACE_GUID,
+ (PINTERFACE)&p_fdo->bus_ib_ifc, sizeof(MLX4_BUS_IB_INTERFACE), MLX4_BUS_IB_INTERFACE_VERSION, NULL );
+ if( !NT_SUCCESS( status ) ) {
+ HCA_PRINT(TRACE_LEVEL_ERROR, HCA_DBG_PNP, ("Getting MLX4 BUS interface failed: status=0x%x\n", status));
+ return status;
+ }
+ p_fdo->bus_ib_ifc_taken = TRUE;
+ p_fdo->bus_ib_ifc.p_ibdev->x.p_fdo = p_fdo;
}
- p_fdo->bus_ib_ifc_taken = TRUE;
- p_fdo->bus_ib_ifc.p_ibdev->x.p_fdo = p_fdo;
InitializeListHead(&p_fdo->hca.event_list);
KeInitializeSpinLock(&p_fdo->hca.event_list_lock);
@@ -1397,6 +1418,8 @@
switch( pIoStack->Parameters.Power.State.SystemState )
{
case PowerSystemSleeping1: // STANDBY support
+ case PowerSystemSleeping2: // STANDBY support
+ case PowerSystemSleeping3: // STANDBY support
case PowerSystemHibernate:
{
PFDO_DEVICE_DATA p_fdo = (PFDO_DEVICE_DATA)p_dev_obj->DeviceExtension;
Index: hw/mthca/kernel/hca_pnp.c
===================================================================
--- hw/mthca/kernel/hca_pnp.c (revision 2421)
+++ hw/mthca/kernel/hca_pnp.c (working copy)
@@ -981,6 +981,8 @@
switch( pIoStack->Parameters.Power.State.SystemState )
{
case PowerSystemSleeping1: // STANDBY support
+ case PowerSystemSleeping2: // STANDBY support
+ case PowerSystemSleeping3: // STANDBY support
case PowerSystemHibernate:
{
hca_dev_ext_t*p_ext = (hca_dev_ext_t*)p_dev_obj->DeviceExtension;
IB
B
US
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openfabrics.org/pipermail/ofw/attachments/20090908/8f6e243b/attachment.html>
More information about the ofw
mailing list