CL_ASSERT( p_context );\r
CL_ASSERT( p_event_rec );\r
\r
+ AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_PNP,\r
+ ("p_event_rec->pnp_event = 0x%x (%s)\n",\r
+ p_event_rec->pnp_event, ib_get_pnp_event_str( p_event_rec->pnp_event )) );\r
+\r
/* Setup the PnP record for the callback. */\r
cl_memclr( &u, sizeof(u) );\r
u.user_rec.h_pnp = p_reg;\r
*/\r
boolean_t b_reported_missing;\r
\r
+ /* Flag to control the behaviour of the driver during hibernation */\r
+ uint32_t b_hibernating;\r
+\r
+ /* work item for handling Power Management request */\r
+ PIO_WORKITEM p_po_work_item;\r
+ \r
} bus_pdo_ext_t;\r
\r
\r
{\r
CL_ASSERT( !p_ext->b_present );\r
p_ext->b_reported_missing = TRUE;\r
+ BUS_TRACE( BUS_DBG_PNP, ("%s: ext %p, present %d, missing %d .\n",\r
+ p_ext->cl_ext.vfptr_pnp_po->identity, p_ext, p_ext->b_present, p_ext->b_reported_missing ) );\r
continue;\r
}\r
if( p_ext->h_ca )\r
}\r
\r
\r
+static ib_api_status_t\r
+__iou_was_hibernated(\r
+ IN ib_pnp_iou_rec_t* p_pnp_rec )\r
+{\r
+ NTSTATUS status;\r
+ cl_list_item_t *p_list_item;\r
+ bus_iou_ext_t *p_iou_ext;\r
+ bus_pdo_ext_t *p_pdo_ext = NULL;\r
+ size_t n_devs = 0;\r
+ cl_qlist_t* p_pdo_list = &gp_iou_mgr->iou_list;\r
+\r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
+ cl_mutex_acquire( &gp_iou_mgr->pdo_mutex );\r
+ \r
+ /* Count the number of child devices. */\r
+ for( p_list_item = cl_qlist_head( p_pdo_list );\r
+ p_list_item != cl_qlist_end( p_pdo_list );\r
+ p_list_item = cl_qlist_next( p_list_item ) )\r
+ {\r
+ p_pdo_ext = PARENT_STRUCT( p_list_item, bus_pdo_ext_t, list_item );\r
+ p_iou_ext = (bus_iou_ext_t*)p_pdo_ext;\r
+\r
+ /* TODO: maybe we need more search patterns like vend_id, dev_id ... */\r
+ if( p_pdo_ext->b_present && p_pdo_ext->b_hibernating &&\r
+ (p_iou_ext->guid == p_pnp_rec->pnp_rec.guid) )\r
+ {\r
+ n_devs++;\r
+ break;\r
+ }\r
+\r
+ BUS_TRACE( BUS_DBG_PNP, \r
+ ("Skipped PDO for %s: PDO %p, ext %p, present %d, missing %d, hibernating %d, port_guid %I64x.\n",\r
+ p_pdo_ext->cl_ext.vfptr_pnp_po->identity, p_pdo_ext->cl_ext.p_self_do, \r
+ p_pdo_ext, p_pdo_ext->b_present, p_pdo_ext->b_reported_missing, \r
+ p_pdo_ext->b_hibernating, p_iou_ext->guid ) );\r
+ }\r
+\r
+ if (n_devs)\r
+ {\r
+ /* Take a reference on the parent HCA. */\r
+ p_pdo_ext->h_ca = acquire_ca( p_pnp_rec->ca_guid );\r
+ if( !p_pdo_ext->h_ca )\r
+ {\r
+ BUS_TRACE( BUS_DBG_ERROR, ("acquire_ca failed to find CA by guid %I64x\n",\r
+ p_pnp_rec->ca_guid ) );\r
+ status = IB_INVALID_GUID;\r
+ }\r
+ else \r
+ {\r
+ p_pdo_ext->b_hibernating = FALSE;\r
+ p_pnp_rec->pnp_rec.context = p_pdo_ext;\r
+ status = IB_SUCCESS;\r
+ p_iou_ext = (bus_iou_ext_t*)p_pdo_ext;\r
+ BUS_TRACE( BUS_DBG_PNP, \r
+ ("Found PDO for %s: PDO %p, ext %p, present %d, missing %d, hibernating %d, port_guid %I64x.\n",\r
+ p_pdo_ext->cl_ext.vfptr_pnp_po->identity, p_pdo_ext->cl_ext.p_self_do, \r
+ p_pdo_ext, p_pdo_ext->b_present, p_pdo_ext->b_reported_missing, \r
+ p_pdo_ext->b_hibernating, p_iou_ext->guid ) );\r
+ }\r
+ }\r
+ else \r
+ {\r
+ BUS_TRACE( BUS_DBG_PNP, ("Failed to find PDO for guid %I64x .\n",\r
+ p_pnp_rec->pnp_rec.guid ) );\r
+ status = IB_NOT_FOUND;\r
+ }\r
+\r
+ cl_mutex_release( &gp_iou_mgr->pdo_mutex );\r
+\r
+ BUS_EXIT( BUS_DBG_PNP );\r
+ return status;\r
+}\r
+\r
ib_api_status_t\r
iou_mgr_iou_add(\r
IN ib_pnp_iou_rec_t* p_pnp_rec )\r
\r
BUS_ENTER( BUS_DBG_PNP );\r
\r
+ /* Upon hibernating of the computer IB_BUS driver doesn't remove PDO, but\r
+ marks with a flag. So we first try to find an existing PDO for this port,\r
+ marked with this flag. If it was found, we turn off the flag and use this PDO */\r
+ status = __iou_was_hibernated(p_pnp_rec);\r
+ if( status != IB_NOT_FOUND )\r
+ {\r
+ BUS_EXIT( BUS_DBG_PNP );\r
+ return status;\r
+ }\r
+\r
/* Create the PDO for the new port device. */\r
status = IoCreateDevice( bus_globals.p_driver_obj, sizeof(bus_iou_ext_t),\r
NULL, FILE_DEVICE_CONTROLLER, \r
p_iou_ext->pdo.p_parent_ext = bus_globals.p_bus_ext;\r
p_iou_ext->pdo.b_present = TRUE;\r
p_iou_ext->pdo.b_reported_missing = FALSE;\r
+ BUS_TRACE( BUS_DBG_PNP, ("%s: ext %p, present %d, missing %d .\n",\r
+ p_iou_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_iou_ext, p_iou_ext->pdo.b_present, p_iou_ext->pdo.b_reported_missing ) );\r
\r
p_iou_ext->guid = p_pnp_rec->pnp_rec.guid;\r
p_iou_ext->vend_id = cl_ntoh32( p_pnp_rec->vend_id );\r
* to proceed should it occur before the port's PDO is cleaned up.\r
*/\r
cl_mutex_acquire( &gp_iou_mgr->pdo_mutex );\r
+ CL_ASSERT( p_ext->h_ca );\r
+\r
+ if( p_ext->b_hibernating )\r
+ {\r
+ BUS_TRACE( BUS_DBG_PNP, ("Skip port removing for %s: PDO %p, ext %p, present %d, missing %d, hibernating %d .\n",\r
+ p_ext->cl_ext.vfptr_pnp_po->identity, p_ext->cl_ext.p_self_do, p_ext, p_ext->b_present, \r
+ p_ext->b_reported_missing, p_ext->b_hibernating ) );\r
+ goto hca_deref;\r
+ }\r
+\r
p_ext->b_present = FALSE;\r
+ BUS_TRACE( BUS_DBG_PNP, ("%s: ext %p, present %d, missing %d .\n",\r
+ p_ext->cl_ext.vfptr_pnp_po->identity, p_ext, p_ext->b_present, p_ext->b_reported_missing ) );\r
\r
/* Invalidate removal relations for the bus driver. */\r
IoInvalidateDeviceRelations( bus_globals.p_bus_ext->cl_ext.p_pdo,\r
IoInvalidateDeviceRelations(\r
p_ext->h_ca->obj.p_ci_ca->verbs.p_hca_dev, BusRelations );\r
\r
+hca_deref:\r
deref_al_obj( &p_ext->h_ca->obj );\r
p_ext->h_ca = NULL;\r
cl_mutex_release( &gp_iou_mgr->pdo_mutex );\r
p_ext = p_dev_obj->DeviceExtension;\r
p_ext->pdo.b_present = FALSE;\r
p_ext->pdo.b_reported_missing = TRUE;\r
+ BUS_TRACE( BUS_DBG_PNP, ("%s: ext %p, present %d, missing %d .\n",\r
+ p_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_ext, p_ext->pdo.b_present, p_ext->pdo.b_reported_missing ) );\r
\r
*p_action = IrpComplete;\r
\r
}\r
\r
\r
+\r
+/* Work item callback to handle DevicePowerD3 IRPs at passive level. */\r
+static void\r
+__HibernateUpWorkItem(\r
+ IN DEVICE_OBJECT* p_dev_obj,\r
+ IN void* context )\r
+{\r
+ IO_STACK_LOCATION *p_io_stack;\r
+ bus_pdo_ext_t *p_ext;\r
+ IRP *p_irp;\r
+ POWER_STATE powerState;\r
+\r
+ BUS_ENTER( BUS_DBG_POWER );\r
+\r
+ p_ext = (bus_pdo_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
+ while (!p_ext->h_ca) {\r
+ BUS_TRACE( BUS_DBG_PNP, ("Waiting for the end of HCA registration ... \n"));\r
+ cl_thread_suspend( 200 ); /* suspend for 200 ms */\r
+ }\r
+\r
+ p_ext->dev_po_state = p_io_stack->Parameters.Power.State;\r
+ powerState = PoSetPowerState( p_dev_obj, DevicePowerState, p_ext->dev_po_state );\r
+\r
+ BUS_TRACE( BUS_DBG_POWER, \r
+ ("PoSetPowerState: old state %d, new state to %d\n", \r
+ powerState.DeviceState, p_ext->dev_po_state ));\r
+\r
+ p_irp->IoStatus.Status = STATUS_SUCCESS;\r
+ PoStartNextPowerIrp( p_irp );\r
+ IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
+ IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
+\r
+ BUS_EXIT( BUS_DBG_POWER );\r
+}\r
+\r
/*\r
* The PDOs created by the IB Bus driver are software devices. As such,\r
* all power states are supported. It is left to the HCA power policy \r
IN IRP* const p_irp,\r
OUT cl_irp_action_t* const p_action )\r
{\r
+ NTSTATUS status = STATUS_SUCCESS;\r
IO_STACK_LOCATION *p_io_stack;\r
bus_pdo_ext_t *p_ext;\r
\r
p_ext = p_dev_obj->DeviceExtension;\r
p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
\r
+ BUS_TRACE( BUS_DBG_POWER, \r
+ ("SET_POWER for PDO %p (ext %p): type %s, state %d, action %d \n",\r
+ p_dev_obj, p_ext,\r
+ (p_io_stack->Parameters.Power.Type) ? "DevicePowerState" : "SystemPowerState",\r
+ p_io_stack->Parameters.Power.State.DeviceState, \r
+ p_io_stack->Parameters.Power.ShutdownType ));\r
+\r
+ if ((p_io_stack->Parameters.Power.Type == SystemPowerState) &&\r
+ (p_io_stack->Parameters.Power.State.SystemState ==PowerSystemHibernate ||\r
+ p_io_stack->Parameters.Power.State.SystemState ==PowerSystemSleeping1 ))\r
+ {\r
+ BUS_TRACE( BUS_DBG_POWER, ("Setting b_hibernating flag for PDO %p \n", p_dev_obj));\r
+ p_ext->b_hibernating = TRUE;\r
+ }\r
+\r
if( p_io_stack->Parameters.Power.Type == DevicePowerState )\r
{\r
+ /* after hibernation PDO is not ready for work. we need to wait for finishing of the HCA registration */\r
+ if( p_io_stack->Parameters.Power.State.DeviceState == PowerDeviceD0 && p_ext->b_hibernating)\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
+ status = STATUS_INSUFFICIENT_RESOURCES;\r
+ else {\r
+ /* Process in work item callback. */\r
+ IoMarkIrpPending( p_irp );\r
+ IoQueueWorkItem(\r
+ p_ext->p_po_work_item, __HibernateUpWorkItem, DelayedWorkQueue, p_irp );\r
+ *p_action = IrpDoNothing;\r
+ BUS_EXIT( BUS_DBG_POWER );\r
+ return STATUS_PENDING;\r
+ }\r
+ }\r
+\r
/* Notify the power manager. */\r
p_ext->dev_po_state = p_io_stack->Parameters.Power.State;\r
PoSetPowerState( p_dev_obj, DevicePowerState, p_ext->dev_po_state );\r
/* Fail any requests to hibernate or sleep the system. */\r
switch( p_io_stack->Parameters.Power.State.SystemState )\r
{\r
+ case PowerSystemHibernate:\r
+ case PowerSystemSleeping1: // STANDBY support\r
case PowerSystemWorking:\r
case PowerSystemShutdown:\r
- /* We only support fully working and shutdown system states. */\r
- break;\r
+ break;\r
\r
- default:\r
+ default:\r
status = STATUS_NOT_SUPPORTED;\r
}\r
break;\r
status = PoRequestPowerIrp( p_dev_obj, IRP_MN_SET_POWER, state,\r
__request_power_completion, p_irp, NULL );\r
\r
- if( !NT_SUCCESS( p_irp->IoStatus.Status ) )\r
+ if( status != STATUS_PENDING )\r
{\r
PoStartNextPowerIrp( p_irp );\r
/* Propagate the failure. */\r
p_ext = p_dev_obj->DeviceExtension;\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
+ p_dev_obj, p_ext,\r
+ (p_io_stack->Parameters.Power.Type) ? "DevicePowerState" : "SystemPowerState",\r
+ p_io_stack->Parameters.Power.State.DeviceState, \r
+ p_io_stack->Parameters.Power.ShutdownType ));\r
+\r
switch( p_io_stack->Parameters.Power.Type )\r
{\r
case SystemPowerState:\r
return STATUS_NO_SUCH_DEVICE;\r
}\r
\r
+ BUS_TRACE( BUS_DBG_PNP, ("Found %d PDOs .\n", n_devs ));\r
+\r
/* Add space for our child IOUs. */\r
status = cl_alloc_relations( p_irp, n_devs );\r
if( !NT_SUCCESS( status ) )\r
* the PDO will get cleaned up.\r
*/\r
p_pdo_ext->b_reported_missing = TRUE;\r
+ BUS_TRACE( BUS_DBG_PNP, ("Don't report PDO! %s: PDO %p, ext %p, present %d, missing %d .\n",\r
+ p_pdo_ext->cl_ext.vfptr_pnp_po->identity, p_pdo_ext->cl_ext.p_self_do, \r
+ p_pdo_ext, p_pdo_ext->b_present, p_pdo_ext->b_reported_missing ) );\r
continue;\r
}\r
\r
if( ca_guid && p_pdo_ext->ca_guid != ca_guid )\r
continue;\r
\r
+ BUS_TRACE( BUS_DBG_PNP, ("Reported PDO %p(=%p), ext %p.\n", \r
+ p_pdo_ext->cl_ext.p_self_do, p_pdo_ext->cl_ext.p_pdo, p_pdo_ext ));\r
+ \r
p_rel->Objects[p_rel->Count] = p_pdo_ext->cl_ext.p_pdo;\r
ObReferenceObject( p_rel->Objects[p_rel->Count++] );\r
}\r
{\r
CL_ASSERT( !p_ext->b_present );\r
p_ext->b_reported_missing = TRUE;\r
+ BUS_TRACE( BUS_DBG_PNP, ("%s: PDO %p, ext %p, present %d, missing %d .\n",\r
+ p_ext->cl_ext.vfptr_pnp_po->identity, p_ext->cl_ext.p_self_do, p_ext, p_ext->b_present, p_ext->b_reported_missing ) );\r
continue;\r
}\r
if( p_ext->h_ca )\r
/* Release the reference on the CA object. */\r
deref_al_obj( &p_ext->h_ca->obj );\r
}\r
+ BUS_TRACE( BUS_DBG_PNP, ("Deleted device %s: PDO %p, ext %p\n",\r
+ p_ext->cl_ext.vfptr_pnp_po->identity, p_ext->cl_ext.p_self_do, p_ext ) );\r
IoDeleteDevice( p_ext->cl_ext.p_self_do );\r
}\r
\r
return STATUS_SUCCESS;\r
}\r
\r
+static ib_api_status_t\r
+__port_was_hibernated(\r
+ IN ib_pnp_port_rec_t* p_pnp_rec )\r
+{\r
+ NTSTATUS status;\r
+ cl_list_item_t *p_list_item;\r
+ bus_port_ext_t *p_port_ext;\r
+ bus_pdo_ext_t *p_pdo_ext = NULL;\r
+ size_t n_devs = 0;\r
+ cl_qlist_t* p_pdo_list = &gp_port_mgr->port_list;\r
+\r
+ BUS_ENTER( BUS_DBG_PNP );\r
+ \r
+ cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
+ \r
+ /* Count the number of child devices. */\r
+ for( p_list_item = cl_qlist_head( p_pdo_list );\r
+ p_list_item != cl_qlist_end( p_pdo_list );\r
+ p_list_item = cl_qlist_next( p_list_item ) )\r
+ {\r
+ p_pdo_ext = PARENT_STRUCT( p_list_item, bus_pdo_ext_t, list_item );\r
+ p_port_ext = (bus_port_ext_t*)p_pdo_ext;\r
+ \r
+ if( p_pdo_ext->b_present && p_pdo_ext->b_hibernating &&\r
+ (p_port_ext->port_guid == p_pnp_rec->p_port_attr->port_guid) )\r
+ {\r
+ n_devs++;\r
+ break;\r
+ }\r
+\r
+ BUS_TRACE( BUS_DBG_PNP, \r
+ ("Skipped PDO for %s: PDO %p, ext %p, present %d, missing %d, hibernating %d, port_guid %I64x.\n",\r
+ p_pdo_ext->cl_ext.vfptr_pnp_po->identity, p_pdo_ext->cl_ext.p_self_do, \r
+ p_pdo_ext, p_pdo_ext->b_present, p_pdo_ext->b_reported_missing, \r
+ p_pdo_ext->b_hibernating, p_port_ext->port_guid ) );\r
+ }\r
+\r
+ if (n_devs)\r
+ {\r
+ /* Take a reference on the parent HCA. */\r
+ p_pdo_ext->h_ca = acquire_ca( p_pnp_rec->p_ca_attr->ca_guid );\r
+ if( !p_pdo_ext->h_ca )\r
+ {\r
+ BUS_TRACE( BUS_DBG_ERROR, ("acquire_ca failed to find CA by guid %I64x\n",\r
+ p_pnp_rec->p_ca_attr->ca_guid ) );\r
+ status = IB_INVALID_GUID;\r
+ }\r
+ else \r
+ {\r
+ p_pdo_ext->b_hibernating = FALSE;\r
+ p_pnp_rec->pnp_rec.context = p_pdo_ext;\r
+ status = IB_SUCCESS;\r
+ p_port_ext = (bus_port_ext_t*)p_pdo_ext;\r
+ BUS_TRACE( BUS_DBG_PNP, \r
+ ("Found PDO for %s: PDO %p, ext %p, present %d, missing %d, hibernating %d, port_guid %I64x.\n",\r
+ p_pdo_ext->cl_ext.vfptr_pnp_po->identity, p_pdo_ext->cl_ext.p_self_do, \r
+ p_pdo_ext, p_pdo_ext->b_present, p_pdo_ext->b_reported_missing, \r
+ p_pdo_ext->b_hibernating, p_port_ext->port_guid ) );\r
+ }\r
+ }\r
+ else \r
+ {\r
+ BUS_TRACE( BUS_DBG_PNP, ("Failed to find PDO for guid %I64x .\n",\r
+ p_pnp_rec->p_ca_attr->ca_guid ) );\r
+ status = IB_NOT_FOUND;\r
+ }\r
+\r
+ cl_mutex_release( &gp_port_mgr->pdo_mutex );\r
+\r
+ BUS_EXIT( BUS_DBG_PNP );\r
+ return status;\r
+}\r
\r
ib_api_status_t\r
port_mgr_port_add(\r
return IB_NOT_DONE;\r
}\r
\r
+ /* Upon hibernating of the computer IB_BUS driver doesn't remove PDO, but\r
+ marks with a flag. So we first try to find an existing PDO for this port,\r
+ marked with this flag. If it was found, we turn off the flag and use this PDO */\r
+ status = __port_was_hibernated(p_pnp_rec);\r
+ if( status != IB_NOT_FOUND )\r
+ {\r
+ BUS_EXIT( BUS_DBG_PNP );\r
+ return status;\r
+ }\r
+\r
/* Create the PDO for the new port device. */\r
status = IoCreateDevice( bus_globals.p_driver_obj, sizeof(bus_port_ext_t),\r
NULL, FILE_DEVICE_CONTROLLER,\r
p_port_ext->pdo.p_parent_ext = bus_globals.p_bus_ext;\r
p_port_ext->pdo.b_present = TRUE;\r
p_port_ext->pdo.b_reported_missing = FALSE;\r
+ p_port_ext->pdo.b_hibernating = FALSE;\r
+ p_port_ext->pdo.p_po_work_item = NULL;\r
+ BUS_TRACE( BUS_DBG_PNP, ("Created device for %s: PDO %p,ext %p, present %d, missing %d .\n",\r
+ p_port_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_pdo, p_port_ext, p_port_ext->pdo.b_present, \r
+ p_port_ext->pdo.b_reported_missing ) );\r
\r
/* Cache the CA GUID. */\r
p_port_ext->pdo.ca_guid = p_pnp_rec->p_ca_attr->ca_guid;\r
p_port_ext->pdo.h_ca = acquire_ca( p_pnp_rec->p_ca_attr->ca_guid );\r
if( !p_port_ext->pdo.h_ca )\r
{\r
+ BUS_TRACE( BUS_DBG_PNP, ("Deleted device: PDO %p\n", p_pdo ));\r
IoDeleteDevice( p_pdo );\r
BUS_TRACE_EXIT( BUS_DBG_ERROR, ("acquire_ca failed to find CA.\n") );\r
return IB_INVALID_GUID;\r
*/\r
cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
CL_ASSERT( p_ext->h_ca );\r
+\r
+ if( p_ext->b_hibernating )\r
+ {\r
+ BUS_TRACE( BUS_DBG_PNP, ("Skip port removing for %s: PDO %p, ext %p, present %d, missing %d, hibernating %d .\n",\r
+ p_ext->cl_ext.vfptr_pnp_po->identity, p_ext->cl_ext.p_self_do, p_ext, p_ext->b_present, \r
+ p_ext->b_reported_missing, p_ext->b_hibernating ) );\r
+ goto hca_deref;\r
+ }\r
+\r
p_ext->b_present = FALSE;\r
+ BUS_TRACE( BUS_DBG_PNP, ("Mark removing %s: PDO %p, ext %p, present %d, missing %d .\n",\r
+ p_ext->cl_ext.vfptr_pnp_po->identity, p_ext->cl_ext.p_self_do, p_ext, p_ext->b_present, p_ext->b_reported_missing ) );\r
\r
/* Invalidate removal relations for the bus driver. */\r
IoInvalidateDeviceRelations( bus_globals.p_bus_ext->cl_ext.p_pdo,\r
IoInvalidateDeviceRelations(\r
p_ext->h_ca->obj.p_ci_ca->verbs.p_hca_dev, BusRelations );\r
\r
+hca_deref:\r
deref_al_obj( &p_ext->h_ca->obj );\r
p_ext->h_ca = NULL;\r
cl_mutex_release( &gp_port_mgr->pdo_mutex );\r
\r
/* Notify the Power Manager that the device is started. */\r
PoSetPowerState( p_dev_obj, DevicePowerState, p_ext->dev_po_state );\r
-\r
*p_action = IrpComplete;\r
BUS_EXIT( BUS_DBG_PNP );\r
return STATUS_SUCCESS;\r
\r
/* Remove this PDO from its list. */\r
cl_mutex_acquire( &gp_port_mgr->pdo_mutex );\r
- BUS_TRACE( BUS_DBG_PNP, ("Removing port from vector.\n") );\r
+ BUS_TRACE( BUS_DBG_PNP, ("Removing port from vector: PDO %p, ext %p\n", p_dev_obj, p_ext) );\r
cl_qlist_remove_item( &gp_port_mgr->port_list, &p_ext->pdo.list_item );\r
cl_mutex_release( &gp_port_mgr->pdo_mutex );\r
po_state.DeviceState = PowerDeviceD3;\r
cl_set_pnp_state( &p_ext->pdo.cl_ext, NotStarted );\r
/* Don't delete the device. It may simply be disabled. */\r
*p_action = IrpComplete;\r
- BUS_TRACE_EXIT( BUS_DBG_PNP, ("Device still present.\n") );\r
+ BUS_TRACE_EXIT( BUS_DBG_PNP, ("Device still present: PDO %p, ext %p\n", p_dev_obj, p_ext) );\r
return STATUS_SUCCESS;\r
}\r
\r
/* Reset the state to RemovePending. Complib set it to Deleted. */\r
cl_rollback_pnp_state( &p_ext->pdo.cl_ext );\r
*p_action = IrpComplete;\r
- BUS_TRACE_EXIT( BUS_DBG_PNP, ("Device not reported missing yet.\n") );\r
+ BUS_TRACE_EXIT( BUS_DBG_PNP, ("Device not reported missing yet: PDO %p, ext %p\n", p_dev_obj, p_ext) );\r
return STATUS_SUCCESS;\r
}\r
\r
p_irp->IoStatus.Status = STATUS_SUCCESS;\r
IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
\r
+ BUS_TRACE( BUS_DBG_PNP, ("Deleted device %s: PDO %p(=%p), ext %p\n",\r
+ p_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_ext->pdo.cl_ext.p_self_do, p_dev_obj, p_ext ) );\r
IoDeleteDevice( p_dev_obj );\r
\r
*p_action = IrpDoNothing;\r
p_ext = p_dev_obj->DeviceExtension;\r
p_ext->pdo.b_present = FALSE;\r
p_ext->pdo.b_reported_missing = TRUE;\r
+ BUS_TRACE( BUS_DBG_PNP, ("%s: PDO %p, ext %p, present %d, missing %d .\n",\r
+ p_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_ext->pdo.cl_ext.p_self_do, \r
+ p_ext, p_ext->pdo.b_present, p_ext->pdo.b_reported_missing ) );\r
\r
*p_action = IrpComplete;\r
\r
ipoib_ifc_data_t *p_ipoib_data;\r
bus_port_ext_t *p_ext;\r
const GUID *p_guid;\r
+ \r
\r
BUS_ENTER( BUS_DBG_PNP );\r
\r
\r
p_ext = p_dev_obj->DeviceExtension;\r
\r
+ BUS_TRACE( BUS_DBG_PNP, ("Query i/f for %s: PDO %p (=%p),ext %p, present %d, missing %d .\n",\r
+ p_ext->pdo.cl_ext.vfptr_pnp_po->identity, p_ext->pdo.cl_ext.p_self_do, \r
+ p_dev_obj, p_ext, p_ext->pdo.b_present, p_ext->pdo.b_reported_missing ) );\r
+\r
/* Get the interface. */\r
status = cl_fwd_query_ifc(\r
p_ext->pdo.p_parent_ext->cl_ext.p_self_do, p_io_stack );\r
}\r
\r
\r
+/* Work item callback to handle DevicePowerD3 IRPs at passive level. */\r
+static void\r
+__HibernateUpWorkItem(\r
+ IN DEVICE_OBJECT* p_dev_obj,\r
+ IN void* context )\r
+{\r
+ IO_STACK_LOCATION *p_io_stack;\r
+ bus_pdo_ext_t *p_ext;\r
+ IRP *p_irp;\r
+ POWER_STATE powerState;\r
+\r
+ BUS_ENTER( BUS_DBG_POWER );\r
+\r
+ p_ext = (bus_pdo_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
+ while (!p_ext->h_ca) {\r
+ BUS_TRACE( BUS_DBG_PNP, ("Waiting for the end of HCA registration ... \n"));\r
+ cl_thread_suspend( 200 ); /* suspend for 200 ms */\r
+ }\r
+\r
+ p_ext->dev_po_state = p_io_stack->Parameters.Power.State;\r
+ powerState = PoSetPowerState( p_dev_obj, DevicePowerState, p_ext->dev_po_state );\r
+\r
+ BUS_TRACE( BUS_DBG_POWER, \r
+ ("PoSetPowerState: old state %d, new state to %d\n", \r
+ powerState.DeviceState, p_ext->dev_po_state ));\r
+\r
+ p_irp->IoStatus.Status = STATUS_SUCCESS;\r
+ PoStartNextPowerIrp( p_irp );\r
+ IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
+ IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
+\r
+ BUS_EXIT( BUS_DBG_POWER );\r
+}\r
+\r
+\r
/*\r
* The PDOs created by the IB Bus driver are software devices. As such,\r
* all power states are supported. It is left to the HCA power policy\r
IN IRP* const p_irp,\r
OUT cl_irp_action_t* const p_action )\r
{\r
+ NTSTATUS status = STATUS_SUCCESS;\r
IO_STACK_LOCATION *p_io_stack;\r
bus_pdo_ext_t *p_ext;\r
\r
p_ext = p_dev_obj->DeviceExtension;\r
p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
\r
+ BUS_TRACE( BUS_DBG_POWER, \r
+ ("SET_POWER for PDO %p (ext %p): type %s, state %d, action %d \n",\r
+ p_dev_obj, p_ext,\r
+ (p_io_stack->Parameters.Power.Type) ? "DevicePowerState" : "SystemPowerState",\r
+ p_io_stack->Parameters.Power.State.DeviceState, \r
+ p_io_stack->Parameters.Power.ShutdownType ));\r
+\r
+ if ((p_io_stack->Parameters.Power.Type == SystemPowerState) &&\r
+ (p_io_stack->Parameters.Power.State.SystemState ==PowerSystemHibernate ||\r
+ p_io_stack->Parameters.Power.State.SystemState ==PowerSystemSleeping1 ))\r
+ {\r
+ BUS_TRACE( BUS_DBG_POWER, ("Setting b_hibernating flag for PDO %p \n", p_dev_obj));\r
+ p_ext->b_hibernating = TRUE;\r
+ }\r
+\r
if( p_io_stack->Parameters.Power.Type == DevicePowerState )\r
{\r
+ /* after hibernation PDO is not ready for work. we need to wait for finishing of the HCA registration */\r
+ if( p_io_stack->Parameters.Power.State.DeviceState == PowerDeviceD0 && p_ext->b_hibernating)\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
+ status = STATUS_INSUFFICIENT_RESOURCES;\r
+ else {\r
+ /* Process in work item callback. */\r
+ IoMarkIrpPending( p_irp );\r
+ IoQueueWorkItem(\r
+ p_ext->p_po_work_item, __HibernateUpWorkItem, DelayedWorkQueue, p_irp );\r
+ *p_action = IrpDoNothing;\r
+ BUS_EXIT( BUS_DBG_POWER );\r
+ return STATUS_PENDING;\r
+ }\r
+ }\r
+\r
/* Notify the power manager. */\r
p_ext->dev_po_state = p_io_stack->Parameters.Power.State;\r
PoSetPowerState( p_dev_obj, DevicePowerState, p_ext->dev_po_state );\r
\r
*p_action = IrpComplete;\r
BUS_EXIT( BUS_DBG_POWER );\r
- return STATUS_SUCCESS;\r
+ return status;\r
}\r
\r
CL_ENTER( CL_DBG_PNP, p_ext->dbg_lvl );\r
\r
+ CL_TRACE( CL_DBG_PNP, p_ext->dbg_lvl, \r
+ ("PDO %p, ext %p\n", p_dev_obj, p_ext) );\r
+\r
CL_ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );\r
\r
status = IoAcquireRemoveLock( &p_ext->remove_lock, p_irp );\r
* ------------------------------------------------ */\r
/* Cache of the system to device power states. */\r
DEVICE_POWER_STATE DevicePower[PowerSystemMaximum];\r
- DEVICE_POWER_STATE PowerState; /* state for Power Manager */\r
- PIO_WORKITEM pPoWorkItem;\r
+ DEVICE_POWER_STATE DevicePowerState;\r
+ SYSTEM_POWER_STATE SystemPowerState;\r
+ PIO_WORKITEM pPoWorkItem;\r
\r
/* -------------------------------------------------\r
* IB_AL DATA \r
/* Release AL's CI interface. */\r
p_ext->ci_ifc.wdm.InterfaceDereference( p_ext->ci_ifc.wdm.Context );\r
p_ext->state = HCA_STARTED;\r
+ HCA_PRINT( TRACE_LEVEL_INFORMATION ,HCA_DBG_PNP,\r
+ ("***** HCA deregistered \n"));\r
}\r
}\r
\r
status = __get_ci_interface( p_dev_obj );\r
if( !NT_SUCCESS( status ) )\r
{\r
- HCA_PRINT( TRACE_LEVEL_ERROR,HCA_DBG_SHIM, \r
+ HCA_PRINT( TRACE_LEVEL_ERROR,HCA_DBG_PNP, \r
("__get_ci_interface returned %08x.\n", status));\r
- return status;\r
+ goto exit;\r
}\r
\r
/* Allocate and populate our HCA interface structure. */\r
p_hca_ifc = __alloc_hca_ifc( p_ext );\r
if( !p_hca_ifc )\r
{\r
- HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_SHIM ,("__alloc_hca_ifc failed.\n"));\r
- return STATUS_NO_MEMORY;\r
+ HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_PNP ,("__alloc_hca_ifc failed.\n"));\r
+ status = STATUS_NO_MEMORY;\r
+ goto exit;\r
}\r
\r
/* Notify AL that we're available... */\r
if( ib_status != IB_SUCCESS )\r
{\r
p_ext->ci_ifc.wdm.InterfaceDereference( p_ext->ci_ifc.wdm.Context );\r
- return STATUS_INSUFFICIENT_RESOURCES;\r
+ status = STATUS_INSUFFICIENT_RESOURCES;\r
+ goto exit;\r
}\r
\r
p_ext->state = HCA_REGISTERED;\r
- return STATUS_SUCCESS;\r
+ HCA_PRINT( TRACE_LEVEL_INFORMATION ,HCA_DBG_PNP,\r
+ ("***** HCA registered \n"));\r
+exit:\r
+ HCA_EXIT( HCA_DBG_PNP );\r
+ return status;\r
}\r
\r
\r
if( !NT_SUCCESS( status ) )\r
{\r
HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
- ("Lower drivers failed IRP_MN_START_DEVICE.\n"));\r
+ ("Lower drivers failed IRP_MN_START_DEVICE (%#x).\n", status));\r
return status;\r
}\r
\r
}\r
\r
/* We get started fully powered. */\r
- p_ext->PowerState = PowerDeviceD0;\r
+ p_ext->DevicePowerState = PowerDeviceD0;\r
powerState.DeviceState = PowerDeviceD0;\r
- PoSetPowerState ( p_ext->cl_ext.p_self_do, DevicePowerState, powerState );\r
+ powerState = PoSetPowerState ( p_ext->cl_ext.p_self_do, DevicePowerState, powerState );\r
+ HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, \r
+ ("PoSetPowerState: old state %d, new state to %d\n", \r
+ powerState.DeviceState, p_ext->DevicePowerState ));\r
+\r
\r
{\r
struct mthca_dev *mdev = p_ext->hca.mdev;\r
IN DEVICE_OBJECT* const p_dev_obj )\r
{\r
hca_dev_ext_t *p_ext;\r
- POWER_STATE powerState;\r
+ POWER_STATE powerState;\r
\r
HCA_ENTER( HCA_DBG_PNP );\r
\r
__hca_release_resources(p_dev_obj);\r
\r
/* Notify the power manager that the device is powered down. */\r
+ p_ext->DevicePowerState = PowerDeviceD3;\r
powerState.DeviceState = PowerDeviceD3;\r
- PoSetPowerState ( p_ext->cl_ext.p_self_do, DevicePowerState, powerState );\r
+ powerState = PoSetPowerState ( p_ext->cl_ext.p_self_do, DevicePowerState, powerState );\r
+\r
+ HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PNP, \r
+ ("PoSetPowerState: old state %d, new state to %d\n", \r
+ powerState.DeviceState, p_ext->DevicePowerState ));\r
+\r
\r
/* Clear the PnP state in case we get restarted. */\r
p_ext->pnpState = 0;\r
return STATUS_SUCCESS;;\r
}\r
\r
-\r
static NTSTATUS\r
hca_query_power(\r
IN DEVICE_OBJECT* const p_dev_obj,\r
\r
pIoStack = IoGetCurrentIrpStackLocation( p_irp );\r
\r
+ HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO, \r
+ ("QUERY_POWER for FDO %p: type %s, state %d, action %d, IRQL %d, IRP %p\n",\r
+ p_dev_obj, \r
+ (pIoStack->Parameters.Power.Type) ? "DevicePowerState" : "SystemPowerState",\r
+ pIoStack->Parameters.Power.State.DeviceState, \r
+ pIoStack->Parameters.Power.ShutdownType, KeGetCurrentIrql(), p_irp ));\r
+\r
switch( pIoStack->Parameters.Power.Type )\r
{\r
case SystemPowerState:\r
/* Fail any requests to hibernate or sleep the system. */\r
switch( pIoStack->Parameters.Power.State.SystemState )\r
{\r
+ case PowerSystemSleeping1: // STANDBY support\r
+ case PowerSystemHibernate:\r
+ {\r
+ hca_dev_ext_t*p_ext = (hca_dev_ext_t*)p_dev_obj->DeviceExtension;\r
+ if (atomic_read(&p_ext->usecnt)) \r
+ status = STATUS_UNSUCCESSFUL;\r
+ break;\r
+ }\r
+\r
case PowerSystemWorking:\r
case PowerSystemShutdown:\r
- /* We only support fully working and shutdown system states. */\r
break;\r
\r
default:\r
break;\r
}\r
\r
- if( status == STATUS_NOT_SUPPORTED )\r
- *p_action = IrpComplete;\r
- else\r
+ if( status == STATUS_SUCCESS )\r
*p_action = IrpSkip;\r
+ else\r
+ *p_action = IrpComplete;\r
\r
HCA_EXIT( HCA_DBG_PO );\r
return status;\r
hca_dev_ext_t *p_ext;\r
IO_STACK_LOCATION *pIoStack;\r
\r
- HCA_ENTER( HCA_DBG_PNP );\r
+ HCA_ENTER( HCA_DBG_PO );\r
\r
UNUSED_PARAM( context );\r
\r
\r
if( !NT_SUCCESS( p_irp->IoStatus.Status ) )\r
{\r
- PoStartNextPowerIrp( p_irp );\r
- IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
- HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
+ HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PO, \r
("IRP_MN_SET_POWER for system failed by lower driver with %08x.\n",\r
p_irp->IoStatus.Status));\r
- return STATUS_SUCCESS;\r
+ status = STATUS_SUCCESS;\r
+ PoStartNextPowerIrp( p_irp );\r
+ goto release;\r
}\r
\r
state.DeviceState = \r
status = PoRequestPowerIrp( p_dev_obj, IRP_MN_SET_POWER, state,\r
__RequestPowerCompletion, p_irp, NULL );\r
\r
- if( !NT_SUCCESS( p_irp->IoStatus.Status ) )\r
- {\r
+ HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO, \r
+ ("PoRequestPowerIrp: SET_POWER 'PowerDeviceD%d', status %#x\n", \r
+ state.DeviceState - 1, status ));\r
+\r
+ if( status != STATUS_PENDING ) {\r
+ HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PO,\r
+ ("PoRequestPowerIrp returned %08x.\n", status));\r
+ p_irp->IoStatus.Status = status; /* Propagate the failure. */\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
- HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,\r
- ("PoRequestPowerIrp returned %08x.\n", status));\r
+ goto release;\r
}\r
\r
- HCA_EXIT( HCA_DBG_PNP );\r
- return STATUS_MORE_PROCESSING_REQUIRED;\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
+ HCA_EXIT( HCA_DBG_PO );\r
+ return status;\r
}\r
\r
\r
/* Work item callback to handle DevicePowerD0 IRPs at passive level. */\r
static void\r
-__PowerUpCb(\r
+__DevicePowerUpCompletionWorkItem(\r
IN DEVICE_OBJECT* p_dev_obj,\r
IN void* context )\r
{\r
IO_STACK_LOCATION *pIoStack;\r
hca_dev_ext_t *p_ext;\r
IRP *p_irp;\r
+ POWER_STATE powerState;\r
\r
HCA_ENTER( HCA_DBG_PO );\r
\r
p_ext->pPoWorkItem = NULL;\r
\r
/* restart the HCA */\r
+ HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO, \r
+ ("***** Restart the HCA, IRQL %d\n", KeGetCurrentIrql()));\r
+\r
status = mthca_init_one( p_ext );\r
- if( !NT_SUCCESS( status ) )\r
- goto done;\r
+ if( !NT_SUCCESS( status ) ) {\r
+ HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PO, \r
+ ("!!! mthca_init_one failed (%#x) \n", status));\r
+ goto err_mthca_init;\r
+ }\r
\r
- if( p_ext->p_al_dev )\r
+ if( p_ext->p_al_dev ) {\r
status = __hca_register( p_dev_obj );\r
-\r
-done:\r
- if( !NT_SUCCESS( status ) )\r
- {\r
- /* Flag device as having failed. */\r
- p_ext->pnpState |= PNP_DEVICE_FAILED;\r
- IoInvalidateDeviceState( p_ext->cl_ext.p_pdo );\r
+ if( !NT_SUCCESS( status ) ) {\r
+ HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PO, \r
+ ("!!! __hca_register failed (%#x) \n", status));\r
+ goto err_hca_reg;\r
+ }\r
}\r
\r
+ p_ext->DevicePowerState = pIoStack->Parameters.Power.State.DeviceState;\r
+ powerState = PoSetPowerState( p_dev_obj, DevicePowerState,\r
+ pIoStack->Parameters.Power.State );\r
+\r
+ HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO, \r
+ ("PoSetPowerState: old state %d, new state to %d\n", \r
+ powerState.DeviceState, p_ext->DevicePowerState ));\r
+\r
+ goto exit;\r
+\r
+err_hca_reg:\r
+err_mthca_init:\r
+ /* Flag device as having failed. */\r
+ p_ext->pnpState |= 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->cl_ext.remove_lock, p_irp );\r
-\r
HCA_EXIT( HCA_DBG_PO );\r
}\r
\r
-\r
/*NOTE: Completion routines must NEVER be pageable. */\r
static NTSTATUS\r
-__DevicePowerCompletion(\r
+__DevicePowerUpCompletion(\r
IN DEVICE_OBJECT *p_dev_obj,\r
IN IRP *p_irp,\r
IN void *context )\r
NTSTATUS status = STATUS_SUCCESS;\r
hca_dev_ext_t *p_ext;\r
IO_STACK_LOCATION *pIoStack;\r
- KIRQL irql = KeGetCurrentIrql( );\r
- \r
- \r
\r
HCA_ENTER( HCA_DBG_PO );\r
\r
p_ext = (hca_dev_ext_t*)p_dev_obj->DeviceExtension;\r
pIoStack = IoGetCurrentIrpStackLocation( p_irp );\r
\r
- if( !NT_SUCCESS( p_irp->IoStatus.Status ) )\r
- {\r
- PoStartNextPowerIrp( p_irp );\r
- IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
- HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
+ if( !NT_SUCCESS( p_irp->IoStatus.Status ) ) {\r
+ HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PO, \r
("IRP_MN_SET_POWER for device failed by lower driver with %08x.\n",\r
p_irp->IoStatus.Status));\r
- return STATUS_SUCCESS;\r
- }\r
-\r
- p_ext->PowerState = pIoStack->Parameters.Power.State.DeviceState;\r
- PoSetPowerState( p_dev_obj, DevicePowerState,\r
- pIoStack->Parameters.Power.State );\r
-\r
- if (irql > PASSIVE_LEVEL) {\r
- /* Process in a work item - mthca_start blocks. */\r
- ASSERT( !p_ext->pPoWorkItem );\r
- p_ext->pPoWorkItem = IoAllocateWorkItem( p_dev_obj );\r
- if( !p_ext->pPoWorkItem )\r
- {\r
- IoInvalidateDeviceState( p_ext->cl_ext.p_pdo );\r
-\r
- PoStartNextPowerIrp( p_irp );\r
- IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
-\r
- return STATUS_SUCCESS;\r
- }\r
-\r
- /* Process in work item callback. */\r
- IoMarkIrpPending( p_irp );\r
- IoQueueWorkItem( p_ext->pPoWorkItem, __PowerUpCb, DelayedWorkQueue, p_irp );\r
+ status = STATUS_SUCCESS;\r
+ PoStartNextPowerIrp( p_irp );\r
+ goto release;\r
}\r
- else {\r
-\r
- /* restart the HCA */\r
- status = mthca_init_one( p_ext );\r
- if( !NT_SUCCESS( status ) )\r
- goto done;\r
\r
- if( p_ext->p_al_dev )\r
- status = __hca_register( p_dev_obj );\r
+ /* Process in a work item - mthca_start blocks. */\r
+ ASSERT( !p_ext->pPoWorkItem );\r
+ p_ext->pPoWorkItem = IoAllocateWorkItem( p_dev_obj );\r
+ if( !p_ext->pPoWorkItem ) {\r
+ HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PO, \r
+ ("Failed to allocate work item.\n" ));\r
+ status = STATUS_SUCCESS;\r
+ p_ext->pnpState |= PNP_DEVICE_FAILED;\r
+ IoInvalidateDeviceState( p_ext->cl_ext.p_pdo );\r
+ PoStartNextPowerIrp( p_irp );\r
+ goto release;\r
}\r
\r
-done:\r
- if( !NT_SUCCESS( status ) )\r
- IoInvalidateDeviceState( p_ext->cl_ext.p_pdo );\r
+ /* Process in work item callback. */\r
+ IoMarkIrpPending( p_irp );\r
+ IoQueueWorkItem( p_ext->pPoWorkItem, \r
+ __DevicePowerUpCompletionWorkItem, DelayedWorkQueue, p_irp );\r
+ status = STATUS_MORE_PROCESSING_REQUIRED;\r
+ goto exit;\r
\r
- PoStartNextPowerIrp( p_irp );\r
+release: \r
IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
-\r
+exit: \r
HCA_EXIT( HCA_DBG_PO );\r
- return STATUS_MORE_PROCESSING_REQUIRED;\r
+ return status;\r
}\r
\r
-static NTSTATUS __DeviceDownCbCompletion(\r
+static NTSTATUS __DevicePowerDownWorkItemCompletion(\r
IN DEVICE_OBJECT *p_dev_obj,\r
IN IRP *p_irp,\r
IN void *context )\r
hca_dev_ext_t *p_ext = (hca_dev_ext_t*)p_dev_obj->DeviceExtension;\r
UNUSED_PARAM( context );\r
\r
+ HCA_ENTER( HCA_DBG_PO );\r
+\r
PoStartNextPowerIrp( p_irp );\r
IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
+\r
+ HCA_EXIT( HCA_DBG_PO );\r
return STATUS_SUCCESS;\r
}\r
\r
/* Work item callback to handle DevicePowerD3 IRPs at passive level. */\r
static void\r
-__PowerDownCb(\r
+__DevicePowerDownWorkItem(\r
IN DEVICE_OBJECT* p_dev_obj,\r
IN void* context )\r
{\r
IO_STACK_LOCATION *pIoStack;\r
hca_dev_ext_t *p_ext;\r
IRP *p_irp;\r
+ POWER_STATE powerState;\r
\r
HCA_ENTER( HCA_DBG_PO );\r
\r
IoFreeWorkItem( p_ext->pPoWorkItem );\r
p_ext->pPoWorkItem = NULL;\r
\r
- PoSetPowerState( p_dev_obj, DevicePowerState,\r
+ p_ext->DevicePowerState = pIoStack->Parameters.Power.State.DeviceState;\r
+ powerState = PoSetPowerState( p_dev_obj, DevicePowerState,\r
pIoStack->Parameters.Power.State );\r
\r
- __hca_deregister( p_ext );\r
- mthca_remove_one( p_ext );\r
+ HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO, \r
+ ("PoSetPowerState: old state %d, new state to %d, IRQL %d\n", \r
+ powerState.DeviceState, p_ext->DevicePowerState, KeGetCurrentIrql() ));\r
+\r
+ HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO, \r
+ ("***** Remove the HCA \n"));\r
+\r
+ {\r
+ __hca_deregister( p_ext );\r
+ mthca_remove_one( p_ext );\r
+ }\r
\r
IoCopyCurrentIrpStackLocationToNext( p_irp );\r
#pragma warning( push, 3 )\r
- IoSetCompletionRoutine( p_irp, __DeviceDownCbCompletion,\r
+ IoSetCompletionRoutine( p_irp, __DevicePowerDownWorkItemCompletion,\r
NULL, TRUE, TRUE, TRUE );\r
#pragma warning( pop )\r
PoCallDriver( p_ext->cl_ext.p_next_do, p_irp );\r
p_ext = (hca_dev_ext_t*)p_dev_obj->DeviceExtension;\r
pIoStack = IoGetCurrentIrpStackLocation( p_irp );\r
\r
+ HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_PO, \r
+ ("SET_POWER for FDO %p (ext %p): type %s, state %d, action %d, IRQL %d \n",\r
+ p_dev_obj, p_ext,\r
+ (pIoStack->Parameters.Power.Type) ? "DevicePowerState" : "SystemPowerState",\r
+ pIoStack->Parameters.Power.State.DeviceState, \r
+ pIoStack->Parameters.Power.ShutdownType, KeGetCurrentIrql() ));\r
+\r
switch( pIoStack->Parameters.Power.Type )\r
{\r
case SystemPowerState:\r
+ p_ext->SystemPowerState = pIoStack->Parameters.Power.State.SystemState;\r
+ \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
\r
case DevicePowerState:\r
IoMarkIrpPending( p_irp );\r
- if( pIoStack->Parameters.Power.State.DeviceState == PowerDeviceD0 )\r
- {\r
+ if( pIoStack->Parameters.Power.State.DeviceState == PowerDeviceD0 && \r
+ p_ext->SystemPowerState == PowerSystemWorking)\r
+ { /* power up */\r
/* If we're already powered up, just pass down. */\r
- if( p_ext->PowerState == PowerDeviceD0 )\r
+ if( p_ext->DevicePowerState == PowerDeviceD0 )\r
{\r
status = STATUS_SUCCESS;\r
*p_action = IrpIgnore;\r
/* Process in I/O completion callback. */\r
IoCopyCurrentIrpStackLocationToNext( p_irp );\r
#pragma warning( push, 3 )\r
- IoSetCompletionRoutine( p_irp, __DevicePowerCompletion, NULL, \r
+ IoSetCompletionRoutine( p_irp, __DevicePowerUpCompletion, NULL, \r
TRUE, TRUE, TRUE );\r
#pragma warning( pop )\r
PoCallDriver( p_ext->cl_ext.p_next_do, p_irp );\r
}\r
else\r
- {\r
+ { /* power down */\r
+\r
/* Process in a work item - deregister_ca and HcaDeinit block. */\r
ASSERT( !p_ext->pPoWorkItem );\r
p_ext->pPoWorkItem = IoAllocateWorkItem( p_dev_obj );\r
}\r
\r
/* Process in work item callback. */\r
- IoMarkIrpPending( p_irp );\r
IoQueueWorkItem(\r
- p_ext->pPoWorkItem, __PowerDownCb, DelayedWorkQueue, p_irp );\r
+ p_ext->pPoWorkItem, __DevicePowerDownWorkItem, DelayedWorkQueue, p_irp );\r
}\r
*p_action = IrpDoNothing;\r
status = STATUS_PENDING;\r
out_param ? *out_param : 0,
in_modifier, op_modifier,
op, context->token, 1);
- if (err)
+ if (err) {
+ HCA_PRINT(TRACE_LEVEL_INFORMATION,HCA_DBG_LOW,
+ ("mthca_cmd_wait: Command %02x completed with err %02x\n", op, err));
goto out;
+ }
{
NTSTATUS res;
res = KeWaitForSingleObject( &context->event, Executive, KernelMode, FALSE, &interval );
if (res != STATUS_SUCCESS) {
err = -EBUSY;
+ HCA_PRINT(TRACE_LEVEL_INFORMATION,HCA_DBG_LOW,
+ ("mthca_cmd_wait: Command %02x completed with err %02x\n", op, err));
goto out;
}
}
*status = context->status;
if (*status)
- HCA_PRINT(TRACE_LEVEL_VERBOSE,HCA_DBG_LOW,("mthca_cmd_wait: Command %02x completed with status %02x\n",
+ HCA_PRINT(TRACE_LEVEL_INFORMATION,HCA_DBG_LOW,("mthca_cmd_wait: Command %02x completed with status %02x\n",
op, *status));
if (out_is_imm)