- Don't wait for the work item to complete in the SCE completion handler
- Use an event to signal the completion of a reset and wait for that event during IRP_MN_START_DEVICE handling so devices are enumerated synchronously which allows USB boot devices to be enumerated

svn path=/branches/usb-bringup-trunk/; revision=55493
This commit is contained in:
Cameron Gutman 2012-02-08 15:50:52 +00:00
parent 0913187636
commit 4b30c8402f
3 changed files with 57 additions and 17 deletions

View file

@ -1,4 +1,4 @@
/* /*
* PROJECT: ReactOS Universal Serial Bus Hub Driver * PROJECT: ReactOS Universal Serial Bus Hub Driver
* LICENSE: GPL - See COPYING in the top level directory * LICENSE: GPL - See COPYING in the top level directory
* FILE: drivers/usb/usbhub/fdo.c * FILE: drivers/usb/usbhub/fdo.c
@ -260,6 +260,7 @@ DeviceStatusChangeThread(
PWORK_ITEM_DATA WorkItemData; PWORK_ITEM_DATA WorkItemData;
PORT_STATUS_CHANGE PortStatus; PORT_STATUS_CHANGE PortStatus;
LONG PortId; LONG PortId;
BOOLEAN SignalResetComplete = FALSE;
DPRINT1("Entered DeviceStatusChangeThread, Context %x\n", Context); DPRINT1("Entered DeviceStatusChangeThread, Context %x\n", Context);
@ -404,16 +405,32 @@ DeviceStatusChangeThread(
// This is a new device // This is a new device
// //
Status = CreateUsbChildDeviceObject(DeviceObject, PortId, NULL, PortStatus.Status); Status = CreateUsbChildDeviceObject(DeviceObject, PortId, NULL, PortStatus.Status);
//
// Request event signalling later
//
SignalResetComplete = TRUE;
} }
} }
KeSetEvent(&WorkItemData->Event, IO_NO_INCREMENT, FALSE); ExFreePool(WorkItemData);
// //
// Send another SCE Request // Send another SCE Request
// //
DPRINT1("Sending another SCE!\n"); DPRINT1("Sending another SCE!\n");
QueryStatusChangeEndpoint(DeviceObject); QueryStatusChangeEndpoint(DeviceObject);
//
// Check if a reset event was satisfied
//
if (SignalResetComplete)
{
//
// Signal anyone waiting on it
//
KeSetEvent(&HubDeviceExtension->ResetComplete, IO_NO_INCREMENT, FALSE);
}
} }
NTSTATUS NTSTATUS
@ -446,25 +463,15 @@ StatusChangeEndpointCompletion(
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
WorkItemData->Context = RealDeviceObject; WorkItemData->Context = RealDeviceObject;
KeInitializeEvent(&WorkItemData->Event, NotificationEvent, FALSE);
DPRINT1("Initialize work item\n"); DPRINT1("Queuing work item\n");
ExInitializeWorkItem(&WorkItemData->WorkItem, DeviceStatusChangeThread, (PVOID)WorkItemData);
// //
// Queue the work item to handle initializing the device // Queue the work item to handle initializing the device
// //
ExInitializeWorkItem(&WorkItemData->WorkItem, DeviceStatusChangeThread, (PVOID)WorkItemData);
ExQueueWorkItem(&WorkItemData->WorkItem, DelayedWorkQueue); ExQueueWorkItem(&WorkItemData->WorkItem, DelayedWorkQueue);
//
// Wait for the work item
//
KeWaitForSingleObject(&WorkItemData->Event,
Executive,
KernelMode,
FALSE,
NULL);
ExFreePool(WorkItemData);
// //
// Return more processing required so the IO Manger doesnt try to mess with IRP just freed // Return more processing required so the IO Manger doesnt try to mess with IRP just freed
// //
@ -1467,8 +1474,22 @@ RootHubInitCallbackFunction(
// //
Status = SetPortFeature(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, PORT_RESET); Status = SetPortFeature(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, PORT_RESET);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to reset on port %d\n", PortId); DPRINT1("Failed to reset on port %d\n", PortId);
} }
else
{
//
// wait for the reset to be handled since we want to enumerate synchronously
//
KeWaitForSingleObject(&HubDeviceExtension->ResetComplete,
Executive,
KernelMode,
FALSE,
NULL);
KeClearEvent(&HubDeviceExtension->ResetComplete);
}
}
} }
} }
} }
@ -1807,7 +1828,7 @@ USBHUB_FdoHandlePnp(
DPRINT1("RootHubInitNotification %x\n", HubDeviceExtension->HubInterface.RootHubInitNotification); DPRINT1("RootHubInitNotification %x\n", HubDeviceExtension->HubInterface.RootHubInitNotification);
// //
// init roo hub notification // init root hub notification
// //
if (HubDeviceExtension->HubInterface.RootHubInitNotification) if (HubDeviceExtension->HubInterface.RootHubInitNotification)
{ {
@ -1847,8 +1868,22 @@ USBHUB_FdoHandlePnp(
// //
Status = SetPortFeature(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, PORT_RESET); Status = SetPortFeature(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, PORT_RESET);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to reset on port %d\n", PortId); DPRINT1("Failed to reset on port %d\n", PortId);
} }
else
{
//
// wait for the reset to be handled since we want to enumerate synchronously
//
KeWaitForSingleObject(&HubDeviceExtension->ResetComplete,
Executive,
KernelMode,
FALSE,
NULL);
KeClearEvent(&HubDeviceExtension->ResetComplete);
}
}
} }
} }
} }

View file

@ -89,6 +89,11 @@ USBHUB_AddDevice(
HubDeviceExtension->Common.IsFDO = TRUE; HubDeviceExtension->Common.IsFDO = TRUE;
DeviceObject->Flags |= DO_POWER_PAGABLE; DeviceObject->Flags |= DO_POWER_PAGABLE;
//
// initialize reset complete event
//
KeInitializeEvent(&HubDeviceExtension->ResetComplete, NotificationEvent, FALSE);
// //
// Attached to lower device // Attached to lower device
// //

View file

@ -44,7 +44,6 @@ typedef struct _PORT_STATUS_CHANGE
typedef struct _WORK_ITEM_DATA typedef struct _WORK_ITEM_DATA
{ {
WORK_QUEUE_ITEM WorkItem; WORK_QUEUE_ITEM WorkItem;
KEVENT Event;
PVOID Context; PVOID Context;
} WORK_ITEM_DATA, *PWORK_ITEM_DATA; } WORK_ITEM_DATA, *PWORK_ITEM_DATA;
@ -80,6 +79,7 @@ typedef struct _HUB_DEVICE_EXTENSION
PDEVICE_OBJECT RootHubFunctionalDeviceObject; PDEVICE_OBJECT RootHubFunctionalDeviceObject;
ULONG NumberOfHubs; ULONG NumberOfHubs;
KEVENT ResetComplete;
PORT_STATUS_CHANGE *PortStatusChange; PORT_STATUS_CHANGE *PortStatusChange;
URB PendingSCEUrb; URB PendingSCEUrb;