mirror of
https://github.com/reactos/reactos.git
synced 2025-05-25 04:03:56 +00:00
[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
This commit is contained in:
parent
0913187636
commit
4b30c8402f
3 changed files with 57 additions and 17 deletions
|
@ -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 doesn’t try to mess with IRP just freed
|
// 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);
|
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,7 +1868,21 @@ 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
//
|
//
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue