#include "iba/ib_cm_ifc.h"\r
#include "al_cm_cep.h"\r
#include "al_mgr.h"\r
+#include "bus_ev_log.h"\r
\r
\r
/* Interface names are generated by IoRegisterDeviceInterface. */\r
IN DEVICE_OBJECT* const p_dev_obj,\r
IN IO_STACK_LOCATION* const p_io_stack );\r
\r
+static NTSTATUS\r
+fdo_query_pnp_state(\r
+ IN DEVICE_OBJECT* const p_dev_obj,\r
+ IN IRP* const p_irp, \r
+ OUT cl_irp_action_t* const p_action );\r
+\r
+\r
static NTSTATUS\r
fdo_query_interface(\r
IN DEVICE_OBJECT* const p_dev_obj,\r
cl_do_sync_pnp,\r
cl_irp_skip,\r
fdo_query_capabilities,\r
- cl_irp_skip,\r
+ fdo_query_pnp_state,\r
cl_irp_skip,\r
cl_do_sync_pnp,\r
fdo_query_bus_relations,\r
}\r
\r
p_ext = p_dev_obj->DeviceExtension;\r
- p_ext->n_al_ifc_ref = 0;\r
- p_ext->n_ci_ifc_ref = 0;\r
+ cl_memclr( p_ext, sizeof(bus_fdo_ext_t) );\r
\r
p_next_do = IoAttachDeviceToDeviceStack( p_dev_obj, p_pdo );\r
if( !p_next_do )\r
return status;\r
}\r
\r
+\r
+static NTSTATUS\r
+__register_ca(\r
+ IN DEVICE_OBJECT* const p_dev_obj\r
+ )\r
+{\r
+ NTSTATUS status;\r
+ bus_fdo_ext_t *p_ext;\r
+ ib_api_status_t ib_status;\r
+ bus_filter_t *p_bfi;\r
+\r
+ BUS_ENTER( BUS_DBG_PNP );\r
+\r
+ p_ext = p_dev_obj->DeviceExtension;\r
+ p_bfi = p_ext->bus_filter;\r
+\r
+ /* get HCA verbs interface */\r
+ status = __get_ifc( p_dev_obj, &GUID_RDMA_INTERFACE_VERBS,\r
+ sizeof(RDMA_INTERFACE_VERBS), \r
+ VerbsVersion(VERBS_MAJOR_VER, VERBS_MINOR_VER), \r
+ p_ext, (PINTERFACE)&p_ext->hca_ifc );\r
+ if( !NT_SUCCESS( status ) ) \r
+ {\r
+ BUS_TRACE_EXIT(BUS_DBG_PNP,\r
+ ("Getting MLX4 BUS interface failed: status=0x%x\n", status));\r
+ return STATUS_UNSUCCESSFUL;\r
+ }\r
+ p_ext->hca_ifc_taken = TRUE;\r
+\r
+ /* bind BFI to HCA by CA GUID. Have to be before ib_register_ca */\r
+ p_bfi->ca_guid = p_ext->hca_ifc.Verbs.guid;\r
+\r
+ /* register HCA */\r
+ ib_status = ib_register_ca( &p_ext->hca_ifc.Verbs, p_ext->cl_ext.p_pdo, p_dev_obj );\r
+ if( ib_status != IB_SUCCESS )\r
+ {\r
+ BUS_TRACE_EXIT( BUS_DBG_ERROR, ("ib_register_ca returned %s.\n",\r
+ ib_get_err_str(ib_status)) );\r
+ return STATUS_UNSUCCESSFUL;\r
+ }\r
+ BUS_TRACE_EXIT(BUS_DBG_PNP, ("%s bound to CA guid %I64x\n",\r
+ p_bfi->whoami,p_bfi->ca_guid));\r
+\r
+ p_ext->ca_registered = TRUE;\r
+ return status;\r
+}\r
+\r
static NTSTATUS\r
fdo_start(\r
IN DEVICE_OBJECT* const p_dev_obj,\r
\r
p_ext = p_dev_obj->DeviceExtension;\r
p_bfi = p_ext->bus_filter;\r
+ ASSERT( !p_ext->ca_registered );\r
\r
/* Handled on the way up. */\r
status = cl_do_sync_pnp( p_dev_obj, p_irp, p_action );\r
("Lower drivers failed IRP_MN_START_DEVICE.\n") );\r
return status;\r
}\r
+ p_ext->device_power_state = PowerDeviceD0;\r
\r
lock_control_event();\r
if ( !gp_async_proc_mgr ) {\r
return STATUS_UNSUCCESSFUL;\r
}\r
\r
+ /* start IBAL */\r
+ status = __register_ca( p_dev_obj );\r
+ if( !NT_SUCCESS( status ) )\r
+ return status;\r
+\r
if ( AL_init_here ) {\r
status = IoSetDeviceInterfaceState( &al_ifc_name, TRUE );\r
ASSERT( NT_SUCCESS( status ) );\r
ASSERT( NT_SUCCESS( status ) );\r
}\r
\r
- /* get HCA verbs interface */\r
- status = __get_ifc( p_dev_obj, &GUID_RDMA_INTERFACE_VERBS,\r
- sizeof(RDMA_INTERFACE_VERBS), \r
- VerbsVersion(VERBS_MAJOR_VER, VERBS_MINOR_VER), \r
- p_ext, (PINTERFACE)&p_ext->hca_ifc );\r
- if( !NT_SUCCESS( status ) ) \r
- {\r
- BUS_TRACE_EXIT(BUS_DBG_PNP,\r
- ("Getting MLX4 BUS interface failed: status=0x%x\n", status));\r
- return STATUS_UNSUCCESSFUL;\r
- }\r
- p_ext->hca_ifc_taken = TRUE;\r
-\r
- /* bind BFI to HCA by CA GUID. Have to be before ib_register_ca */\r
- p_bfi->ca_guid = p_ext->hca_ifc.Verbs.guid;\r
+ CL_PRINT_TO_EVENT_LOG( p_dev_obj, EVENT_IBBUS_ANY_INFO,\r
+ ("IBBUS started \n" ));\r
\r
- /* register HCA */\r
- ib_status = ib_register_ca( &p_ext->hca_ifc.Verbs, p_ext->cl_ext.p_pdo, p_dev_obj );\r
- if( ib_status != IB_SUCCESS )\r
- {\r
- BUS_TRACE_EXIT( BUS_DBG_ERROR, ("ib_register_ca returned %s.\n",\r
- ib_get_err_str(ib_status)) );\r
- return STATUS_UNSUCCESSFUL;\r
- }\r
-\r
- BUS_TRACE_EXIT(BUS_DBG_PNP, ("%s bound to CA guid %I64x\n",\r
- p_bfi->whoami,p_bfi->ca_guid));\r
return status;\r
}\r
\r
}\r
\r
\r
+static void\r
+__deregister_ca(\r
+ IN DEVICE_OBJECT* const p_dev_obj )\r
+{\r
+ bus_fdo_ext_t *p_ext;\r
+ bus_filter_t *p_bfi;\r
+ ib_api_status_t ib_status;\r
+\r
+ BUS_ENTER( BUS_DBG_PNP );\r
+\r
+ p_ext = p_dev_obj->DeviceExtension;\r
+ p_bfi = p_ext->bus_filter;\r
+\r
+ if ( !p_ext->ca_registered )\r
+ return;\r
+ p_ext->ca_registered = FALSE;\r
+\r
+ //TODO: Fail outstanding I/O operations.\r
+\r
+ ib_status = ib_deregister_ca( p_ext->hca_ifc.Verbs.guid );\r
+ if( ib_status != IB_SUCCESS ) {\r
+ BUS_PRINT( BUS_DBG_ERROR, ("ib_deregister_ca returned %s.\n",\r
+ ib_get_err_str(ib_status)) );\r
+ }\r
+\r
+ if ( p_ext->hca_ifc_taken ) {\r
+ p_ext->hca_ifc.InterfaceHeader.InterfaceDereference(\r
+ p_ext->hca_ifc.InterfaceHeader.Context);\r
+ p_ext->hca_ifc_taken = FALSE;\r
+ }\r
+\r
+ BUS_EXIT( BUS_DBG_PNP );\r
+}\r
+\r
/*\r
* This function gets called after releasing the remove lock and waiting\r
* for all other threads to release the lock. No more modifications will\r
NTSTATUS status;\r
bus_filter_t *p_bfi;\r
int ic;\r
- ib_api_status_t ib_status;\r
\r
BUS_ENTER( BUS_DBG_PNP );\r
\r
p_bfi = p_ext->bus_filter;\r
CL_ASSERT( p_bfi );\r
\r
- //TODO: Fail outstanding I/O operations.\r
-\r
- ib_status = ib_deregister_ca( p_ext->hca_ifc.Verbs.guid );\r
- if( ib_status != IB_SUCCESS ) {\r
- BUS_PRINT( BUS_DBG_ERROR, ("ib_deregister_ca returned %s.\n",\r
- ib_get_err_str(ib_status)) );\r
- }\r
+ __deregister_ca( p_dev_obj );\r
\r
if ( p_bfi->p_port_mgr )\r
cl_obj_destroy( p_bfi->p_port_mgr_obj );\r
if ( p_bfi->p_iou_mgr )\r
cl_obj_destroy( p_bfi->p_iou_mgr_obj );\r
\r
+#if 0\r
+ // IBAL has no right to work with CA after it deregister.\r
+ // So there is no need to release interface only after IBAL cleanup\r
\r
/* if not last HCA then release IFC reference, otherwise release IFC after\r
* IBAL has shutdown; keep the HCA present until IBAL is terminated.\r
p_ext->hca_ifc.InterfaceHeader.Context);\r
p_ext->hca_ifc_taken = FALSE;\r
}\r
+#endif \r
\r
BUS_TRACE( BUS_DBG_PNP, ("Releasing BusFilter %s\n", p_bfi->whoami ));\r
if (p_bfi) {\r
\r
CL_ASSERT( !gp_async_proc_mgr && !gp_async_pnp_mgr && !gp_al_mgr );\r
\r
+#if 0\r
+ // IBAL has no right to work with CA after it deregister.\r
+ // So there is no need to release interface only after IBAL cleanup\r
+ \r
/* AL needs the HCA to stick around until AL cleanup has completed.\r
* Now that it's done, let the HCA fade away.\r
*/\r
p_ext->hca_ifc.InterfaceHeader.Context);\r
p_ext->hca_ifc_taken = FALSE;\r
}\r
+#endif \r
\r
BUS_EXIT( BUS_DBG_PNP );\r
}\r
return STATUS_SUCCESS;\r
}\r
\r
+static NTSTATUS\r
+fdo_query_pnp_state(\r
+ IN DEVICE_OBJECT* const p_dev_obj,\r
+ IN IRP* const p_irp, \r
+ OUT cl_irp_action_t* const p_action )\r
+{\r
+ bus_fdo_ext_t *p_ext;\r
+\r
+ BUS_ENTER( BUS_DBG_PNP );\r
+\r
+ p_ext = (bus_fdo_ext_t*)p_dev_obj->DeviceExtension;\r
+\r
+ p_irp->IoStatus.Information |= p_ext->pnp_state;\r
+\r
+ *p_action = IrpSkip;\r
+\r
+ BUS_EXIT( BUS_DBG_PNP );\r
+ return STATUS_SUCCESS;;\r
+}\r
+\r
\r
static NTSTATUS\r
fdo_query_interface(\r
switch( p_io_stack->Parameters.Power.State.SystemState )\r
{\r
case PowerSystemHibernate:\r
- case PowerSystemSleeping1: // STANDBY support\r
+ case PowerSystemSleeping1: // STANDBY support\r
+ case PowerSystemSleeping2: // STANDBY support\r
+ case PowerSystemSleeping3: // STANDBY support\r
case PowerSystemWorking:\r
case PowerSystemShutdown:\r
break;\r
}\r
\r
\r
+\r
+/* Work item callback to handle DevicePowerD0 IRPs at passive level. */\r
+\r
static void\r
-__request_power_completion(\r
- IN DEVICE_OBJECT *p_dev_obj,\r
- IN UCHAR minor_function,\r
- IN POWER_STATE power_state,\r
- IN void *context,\r
- IN IO_STATUS_BLOCK *p_io_status )\r
+__device_power_up_completion_workItem(\r
+ IN DEVICE_OBJECT* p_dev_obj,\r
+ IN void* context )\r
{\r
+ NTSTATUS status;\r
+ IO_STACK_LOCATION *p_io_stack;\r
+ bus_fdo_ext_t *p_ext;\r
IRP *p_irp;\r
- cl_pnp_po_ext_t *p_ext;\r
-\r
- BUS_ENTER( BUS_DBG_PNP );\r
+ POWER_STATE power_state;\r
\r
- UNUSED_PARAM( minor_function );\r
- UNUSED_PARAM( power_state );\r
+ BUS_ENTER( BUS_DBG_POWER );\r
\r
+ p_ext = (bus_fdo_ext_t*)p_dev_obj->DeviceExtension;\r
p_irp = (IRP*)context;\r
- p_ext = p_dev_obj->DeviceExtension;\r
+ p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
+\r
+ IoFreeWorkItem( p_ext->p_po_work_item );\r
+ p_ext->p_po_work_item = NULL;\r
\r
- /* Propagate the device IRP status to the system IRP status. */\r
- p_irp->IoStatus.Status = p_io_status->Status;\r
+ /* re-register CA */\r
+ BUS_PRINT( BUS_DBG_POWER, \r
+ ("***** re-register CA, IRQL %d\n", KeGetCurrentIrql()));\r
\r
- /* Continue Power IRP processing. */\r
+ status = __register_ca( p_dev_obj );\r
+ if( !NT_SUCCESS( status ) ) {\r
+ BUS_PRINT( BUS_DBG_POWER, \r
+ ("!!! __register_ca failed (%#x) \n", status));\r
+ goto err_fdo_start;\r
+ }\r
+\r
+ p_ext->device_power_state = p_io_stack->Parameters.Power.State.DeviceState;\r
+ power_state = PoSetPowerState( p_dev_obj, DevicePowerState,\r
+ p_io_stack->Parameters.Power.State );\r
+\r
+ BUS_PRINT( BUS_DBG_POWER, \r
+ ("PoSetPowerState: old state %d, new state to %d\n", \r
+ power_state.DeviceState, p_ext->device_power_state ));\r
+\r
+ CL_PRINT_TO_EVENT_LOG( p_dev_obj, EVENT_IBBUS_ANY_WARN,\r
+ ("Power increased to: device %d, system %d.\n",\r
+ (int)p_ext->device_power_state, (int)p_ext->system_power_state));\r
+\r
+ goto exit;\r
+\r
+err_fdo_start:\r
+ /* Flag device as having failed. */\r
+ p_ext->pnp_state |= PNP_DEVICE_FAILED;\r
+ IoInvalidateDeviceState( p_ext->cl_ext.p_pdo );\r
+exit:\r
PoStartNextPowerIrp( p_irp );\r
IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
- IoReleaseRemoveLock( &p_ext->remove_lock, p_irp );\r
- BUS_EXIT( BUS_DBG_PNP );\r
+ IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
+ BUS_EXIT( BUS_DBG_POWER );\r
}\r
\r
\r
/*NOTE: Completion routines must NEVER be pageable. */\r
static NTSTATUS\r
-__set_power_completion(\r
+__device_power_up_completion(\r
IN DEVICE_OBJECT *p_dev_obj,\r
IN IRP *p_irp,\r
IN void *context )\r
{\r
- NTSTATUS status;\r
- POWER_STATE state;\r
+ NTSTATUS status = STATUS_SUCCESS;\r
bus_fdo_ext_t *p_ext;\r
IO_STACK_LOCATION *p_io_stack;\r
\r
- BUS_ENTER( BUS_DBG_PNP );\r
+ BUS_ENTER( BUS_DBG_POWER );\r
\r
UNUSED_PARAM( context );\r
\r
- p_ext = p_dev_obj->DeviceExtension;\r
+ p_ext = (bus_fdo_ext_t*)p_dev_obj->DeviceExtension;\r
p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
\r
- if( !NT_SUCCESS( p_irp->IoStatus.Status ) )\r
- {\r
+ if( !NT_SUCCESS( p_irp->IoStatus.Status ) ) {\r
+ BUS_PRINT( BUS_DBG_POWER, \r
+ ("IRP_MN_SET_POWER for device failed by lower driver with %08x.\n",\r
+ p_irp->IoStatus.Status));\r
+ status = STATUS_SUCCESS;\r
PoStartNextPowerIrp( p_irp );\r
- IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
- BUS_TRACE_EXIT( BUS_DBG_ERROR, \r
- ("IRP_MN_SET_POWER for system failed by lower driver with %08x.\n",\r
- p_irp->IoStatus.Status) );\r
- return STATUS_SUCCESS;\r
+ goto release;\r
}\r
\r
- state.DeviceState = \r
- p_ext->po_state[p_io_stack->Parameters.Power.State.SystemState];\r
-\r
- /*\r
- * Send a device power IRP to our devnode. Using our device object will\r
- * only work on win2k and other NT based systems.\r
- */\r
- status = PoRequestPowerIrp( p_dev_obj, IRP_MN_SET_POWER, state,\r
- __request_power_completion, p_irp, NULL );\r
-\r
- if( status != STATUS_PENDING )\r
- {\r
+ /* Process in a work item to allow blocking. */\r
+ ASSERT( !p_ext->p_po_work_item );\r
+ p_ext->p_po_work_item = IoAllocateWorkItem( p_dev_obj );\r
+ if( !p_ext->p_po_work_item ) {\r
+ BUS_PRINT( BUS_DBG_POWER, \r
+ ("Failed to allocate work item.\n" ));\r
+ status = STATUS_SUCCESS;\r
+ p_ext->pnp_state |= PNP_DEVICE_FAILED;\r
+ IoInvalidateDeviceState( p_ext->cl_ext.p_pdo );\r
PoStartNextPowerIrp( p_irp );\r
- /* Propagate the failure. */\r
- p_irp->IoStatus.Status = status;\r
- IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
- IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
- BUS_TRACE( BUS_DBG_ERROR,\r
- ("PoRequestPowerIrp returned %08x.\n", status) );\r
+ goto release;\r
}\r
\r
- BUS_EXIT( BUS_DBG_PNP );\r
- return STATUS_MORE_PROCESSING_REQUIRED;\r
+ /* Process in work item callback. */\r
+ IoMarkIrpPending( p_irp );\r
+ IoQueueWorkItem( p_ext->p_po_work_item, \r
+ __device_power_up_completion_workItem, DelayedWorkQueue, p_irp );\r
+ status = STATUS_MORE_PROCESSING_REQUIRED;\r
+ goto exit;\r
+\r
+release: \r
+ IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
+exit: \r
+ BUS_EXIT( BUS_DBG_POWER );\r
+ return status;\r
}\r
\r
\r
+static NTSTATUS __device_power_down_workItem_completion(\r
+ IN DEVICE_OBJECT *p_dev_obj,\r
+ IN IRP *p_irp,\r
+ IN void *context )\r
+{\r
+ bus_fdo_ext_t *p_ext = (bus_fdo_ext_t*)p_dev_obj->DeviceExtension;\r
+ UNUSED_PARAM( context );\r
+\r
+ BUS_ENTER( BUS_DBG_POWER );\r
+\r
+ PoStartNextPowerIrp( p_irp );\r
+ IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
+\r
+ BUS_EXIT( BUS_DBG_POWER );\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+/* Work item callback to handle DevicePowerD3 IRPs at passive level. */\r
+static void\r
+__device_power_down_workItem(\r
+ IN DEVICE_OBJECT* p_dev_obj,\r
+ IN void* context )\r
+{\r
+ IO_STACK_LOCATION *p_io_stack;\r
+ bus_fdo_ext_t *p_ext;\r
+ IRP *p_irp;\r
+ POWER_STATE power_state;\r
+\r
+ BUS_ENTER( BUS_DBG_POWER );\r
+\r
+ p_ext = (bus_fdo_ext_t*)p_dev_obj->DeviceExtension;\r
+ p_irp = (IRP*)context;\r
+ p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
+\r
+ IoFreeWorkItem( p_ext->p_po_work_item );\r
+ p_ext->p_po_work_item = NULL;\r
+\r
+ p_ext->device_power_state = p_io_stack->Parameters.Power.State.DeviceState;\r
+ power_state = PoSetPowerState( p_dev_obj, DevicePowerState,\r
+ p_io_stack->Parameters.Power.State );\r
+\r
+ BUS_PRINT( BUS_DBG_POWER, \r
+ ("PoSetPowerState: old state %d, new state to %d, IRQL %d\n", \r
+ power_state.DeviceState, p_ext->device_power_state, KeGetCurrentIrql() ));\r
+\r
+ CL_PRINT_TO_EVENT_LOG( p_dev_obj, EVENT_IBBUS_ANY_WARN,\r
+ ("Power decreased to: device %d, system %d.\n",\r
+ (int)p_ext->device_power_state, (int)p_ext->system_power_state));\r
+\r
+ BUS_PRINT( BUS_DBG_POWER, \r
+ ("***** deregister CA \n"));\r
+\r
+ __deregister_ca( p_dev_obj );\r
+\r
+ IoCopyCurrentIrpStackLocationToNext( p_irp );\r
+#pragma warning( push, 3 )\r
+ IoSetCompletionRoutine( p_irp, __device_power_down_workItem_completion,\r
+ NULL, TRUE, TRUE, TRUE );\r
+#pragma warning( pop )\r
+ PoCallDriver( p_ext->cl_ext.p_next_do, p_irp );\r
+\r
+ BUS_EXIT( BUS_DBG_POWER );\r
+}\r
+\r
+\r
+\r
static NTSTATUS\r
__fdo_set_power(\r
IN DEVICE_OBJECT* const p_dev_obj,\r
p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
\r
BUS_TRACE( BUS_DBG_POWER, \r
- ("SET_POWER for FDO %p (ext %p): type %s, state %d, action %d \n",\r
+ ("SET_POWER for FDO %p (ext %p): type %s, state %d, action %d, IRQL %d \n",\r
p_dev_obj, p_ext,\r
(p_io_stack->Parameters.Power.Type)\r
? "DevicePowerState" : "SystemPowerState",\r
p_io_stack->Parameters.Power.State.DeviceState, \r
- p_io_stack->Parameters.Power.ShutdownType ));\r
+ p_io_stack->Parameters.Power.ShutdownType, KeGetCurrentIrql() ));\r
\r
switch( p_io_stack->Parameters.Power.Type )\r
{\r
case SystemPowerState:\r
-#if 0\r
- /*\r
- * Process on the way up the stack. We cannot block since the \r
- * power dispatch function can be called at elevated IRQL if the\r
- * device is in a paging/hibernation/crash dump path.\r
- */\r
+ /* Pass down and let the PDO driver handle it. */\r
+ p_ext->system_power_state = p_io_stack->Parameters.Power.State.SystemState;\r
+ *p_action = IrpIgnore;\r
+ status = STATUS_SUCCESS;\r
+ break;\r
+\r
+ case DevicePowerState:\r
IoMarkIrpPending( p_irp );\r
- IoCopyCurrentIrpStackLocationToNext( p_irp );\r
+ if( p_io_stack->Parameters.Power.State.DeviceState == PowerDeviceD0 && \r
+ p_ext->system_power_state == PowerSystemWorking)\r
+ { /* power up */\r
+ /* If we're already powered up, just pass down. */\r
+ if( p_ext->device_power_state == PowerDeviceD0 )\r
+ {\r
+ status = STATUS_SUCCESS;\r
+ *p_action = IrpIgnore;\r
+ break;\r
+ }\r
+\r
+ /* Process in I/O completion callback. */\r
+ IoCopyCurrentIrpStackLocationToNext( p_irp );\r
#pragma warning( push, 3 )\r
- IoSetCompletionRoutine( p_irp, __set_power_completion, NULL, \r
- TRUE, TRUE, TRUE );\r
+ IoSetCompletionRoutine( p_irp, __device_power_up_completion, NULL, \r
+ TRUE, TRUE, TRUE );\r
#pragma warning( pop )\r
- PoCallDriver( p_ext->cl_ext.p_next_do, p_irp );\r
+ PoCallDriver( p_ext->cl_ext.p_next_do, p_irp );\r
+ }\r
+ else\r
+ { /* power down */\r
+\r
+ /* Process in a work item - deregister_ca and HcaDeinit block. */\r
+ ASSERT( !p_ext->p_po_work_item );\r
+ p_ext->p_po_work_item = IoAllocateWorkItem( p_dev_obj );\r
+ if( !p_ext->p_po_work_item )\r
+ {\r
+ status = STATUS_INSUFFICIENT_RESOURCES;\r
+ break;\r
+ }\r
\r
+ /* Process in work item callback. */\r
+ IoQueueWorkItem(\r
+ p_ext->p_po_work_item, __device_power_down_workItem, DelayedWorkQueue, p_irp );\r
+ }\r
*p_action = IrpDoNothing;\r
status = STATUS_PENDING;\r
break;\r
-#endif\r
- case DevicePowerState:\r
+\r
default:\r
/* Pass down and let the PDO driver handle it. */\r
*p_action = IrpIgnore;\r
break;\r
}\r
\r
+ if( !NT_SUCCESS( status ) )\r
+ *p_action = IrpComplete;\r
+\r
BUS_EXIT( BUS_DBG_POWER );\r
return status;\r
}\r