diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c index 742cdc1931..ff6b99c87f 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c @@ -813,6 +813,7 @@ UsbIoPortReset ( USB_DEVICE *Dev; EFI_TPL OldTpl; EFI_STATUS Status; + UINT8 DevAddress; OldTpl = gBS->RaiseTPL (USB_BUS_TPL); @@ -834,12 +835,17 @@ UsbIoPortReset ( goto ON_EXIT; } + HubIf->HubApi->ClearPortChange (HubIf, Dev->ParentPort); + // // Reset the device to its current address. The device now has an address // of ZERO after port reset, so need to set Dev->Address to the device again for // host to communicate with it. // - Status = UsbSetAddress (Dev, Dev->Address); + DevAddress = Dev->Address; + Dev->Address = 0; + Status = UsbSetAddress (Dev, DevAddress); + Dev->Address = DevAddress; gBS->Stall (USB_SET_DEVICE_ADDRESS_STALL); diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h index 094aea21cd..d503a278a4 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h @@ -99,9 +99,18 @@ typedef struct _USB_HUB_API USB_HUB_API; // [USB20-7.1.7.5, it says 10ms for hub and 50ms for // root hub] // -#define USB_SET_PORT_RESET_STALL (10 * USB_BUS_1_MILLISECOND) +// According to USB2.0, Chapter 11.5.1.5 Resetting, +// the worst case for TDRST is 20ms +// +#define USB_SET_PORT_RESET_STALL (20 * USB_BUS_1_MILLISECOND) #define USB_SET_ROOT_PORT_RESET_STALL (50 * USB_BUS_1_MILLISECOND) +// +// Wait for port recovery to accept SetAddress, refers to specification +// [USB20-7.1.7.5, it says 10 ms for TRSTRCY] +// +#define USB_SET_PORT_RECOVERY_STALL (10 * USB_BUS_1_MILLISECOND) + // // Wait for clear roothub port reset, set by experience // diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c index 2d24bb4b8a..9e5299c0ef 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c @@ -975,13 +975,13 @@ UsbHubResetPort ( } // - // Drive the reset signal for at least 10ms. Check USB 2.0 Spec + // Drive the reset signal for worst 20ms. Check USB 2.0 Spec // section 7.1.7.5 for timing requirements. // gBS->Stall (USB_SET_PORT_RESET_STALL); // - // USB hub will clear RESET bit if reset is actually finished. + // Check USB_PORT_STAT_C_RESET bit to see if the resetting state is done. // ZeroMem (&PortState, sizeof (EFI_USB_PORT_STATUS)); @@ -989,8 +989,8 @@ UsbHubResetPort ( Status = UsbHubGetPortStatus (HubIf, Port, &PortState); if (!EFI_ERROR (Status) && - !USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_RESET)) { - + USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_RESET)) { + gBS->Stall (USB_SET_PORT_RECOVERY_STALL); return EFI_SUCCESS; }