- 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
* LICENSE: GPL - See COPYING in the top level directory
* FILE: drivers/usb/usbhub/fdo.c
@ -260,6 +260,7 @@ DeviceStatusChangeThread(
PWORK_ITEM_DATA WorkItemData;
PORT_STATUS_CHANGE PortStatus;
LONG PortId;
BOOLEAN SignalResetComplete = FALSE;
DPRINT1("Entered DeviceStatusChangeThread, Context %x\n", Context);
@ -404,16 +405,32 @@ DeviceStatusChangeThread(
// This is a new device
//
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
//
DPRINT1("Sending another SCE!\n");
QueryStatusChangeEndpoint(DeviceObject);
//
// Check if a reset event was satisfied
//
if (SignalResetComplete)
{
//
// Signal anyone waiting on it
//
KeSetEvent(&HubDeviceExtension->ResetComplete, IO_NO_INCREMENT, FALSE);
}
}
NTSTATUS
@ -446,25 +463,15 @@ StatusChangeEndpointCompletion(
return STATUS_INSUFFICIENT_RESOURCES;
}
WorkItemData->Context = RealDeviceObject;
KeInitializeEvent(&WorkItemData->Event, NotificationEvent, FALSE);
DPRINT1("Initialize work item\n");
ExInitializeWorkItem(&WorkItemData->WorkItem, DeviceStatusChangeThread, (PVOID)WorkItemData);
DPRINT1("Queuing work item\n");
//
// Queue the work item to handle initializing the device
//
ExInitializeWorkItem(&WorkItemData->WorkItem, DeviceStatusChangeThread, (PVOID)WorkItemData);
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
//
@ -1467,7 +1474,21 @@ RootHubInitCallbackFunction(
//
Status = SetPortFeature(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, PORT_RESET);
if (!NT_SUCCESS(Status))
{
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);
//
// init roo hub notification
// init root hub notification
//
if (HubDeviceExtension->HubInterface.RootHubInitNotification)
{
@ -1847,7 +1868,21 @@ USBHUB_FdoHandlePnp(
//
Status = SetPortFeature(HubDeviceExtension->RootHubPhysicalDeviceObject, PortId, PORT_RESET);
if (!NT_SUCCESS(Status))
{
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;
DeviceObject->Flags |= DO_POWER_PAGABLE;
//
// initialize reset complete event
//
KeInitializeEvent(&HubDeviceExtension->ResetComplete, NotificationEvent, FALSE);
//
// Attached to lower device
//

View file

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