From 4b30c8402f8f0ab7e1c15c159dc56d98c5a61cc0 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Wed, 8 Feb 2012 15:50:52 +0000 Subject: [PATCH] [USBHUB] - 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 --- drivers/usb/usbhub_new/fdo.c | 67 +++++++++++++++++++++++++-------- drivers/usb/usbhub_new/usbhub.c | 5 +++ drivers/usb/usbhub_new/usbhub.h | 2 +- 3 files changed, 57 insertions(+), 17 deletions(-) diff --git a/drivers/usb/usbhub_new/fdo.c b/drivers/usb/usbhub_new/fdo.c index d0f11ca2d2d..7b358eb6622 100644 --- a/drivers/usb/usbhub_new/fdo.c +++ b/drivers/usb/usbhub_new/fdo.c @@ -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 doesn’t 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); + } } } } diff --git a/drivers/usb/usbhub_new/usbhub.c b/drivers/usb/usbhub_new/usbhub.c index 347358e7d3a..a88017aa1ce 100644 --- a/drivers/usb/usbhub_new/usbhub.c +++ b/drivers/usb/usbhub_new/usbhub.c @@ -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 // diff --git a/drivers/usb/usbhub_new/usbhub.h b/drivers/usb/usbhub_new/usbhub.h index 7f57dddc82f..14ea5159a74 100644 --- a/drivers/usb/usbhub_new/usbhub.h +++ b/drivers/usb/usbhub_new/usbhub.h @@ -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;