[ofw] patch: [ibbus,hw] add power down support for IBBUS

Leonid Keller leonid at mellanox.co.il
Sun Sep 6 18:03:56 PDT 2009


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/20090907/70f33299/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: standby.patch
Type: application/octet-stream
Size: 25231 bytes
Desc: standby.patch
URL: <http://lists.openfabrics.org/pipermail/ofw/attachments/20090907/70f33299/attachment.obj>


More information about the ofw mailing list