[ofw] patch: [ibbus,hw] add power down support for IBBUS
Leonid Keller
leonid at mellanox.co.il
Mon Sep 14 10:14:30 PDT 2009
Sorry, I was interrupted with some urgent customer issue and temporary
paused the work.
I'd also like to include the patch in 2.1, but the testing (which i've
done) is not enough.
I was running WDK pwrtest.exe for standby and hibernate on win2k8.
It worked without applications on the target node and with opensm on
another node.
But i wanted also to see it working on win2k3.
I was running also some WHQL tests.
"Sleep with stress" has passed.
But "Common Stress" got stuck with Power System IRP handled too long by
IPoIB.
Why does it happen I don't know: neither of our drivers handles Power
System IRPs.
This urgent work i'm dealing with now, can take more 2-3 days, then i'm
going to return to the testing of this patch.
I'd be happy if someone will find time and ability to test it in his
environment.
________________________________
From: Smith, Stan [mailto:stan.smith at intel.com]
Sent: Monday, September 14, 2009 6:45 PM
To: Leonid Keller
Cc: ofw at lists.openfabrics.org
Subject: RE: [ofw] patch: [ibbus,hw] add power down support for
IBBUS
Hello Leonid?
________________________________
From: Smith, Stan
Sent: Tuesday, September 08, 2009 12:08 PM
To: 'Leonid Keller'; ofw at lists.openfabrics.org
Subject: RE: [ofw] patch: [ibbus,hw] add power down support for
IBBUS
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/20090914/0b50acaa/attachment.html>
More information about the ofw
mailing list