From 41e8ff2781f3ca14f73ef5f39e781ccba8cb373d Mon Sep 17 00:00:00 2001 From: yshang1 Date: Mon, 8 Oct 2007 06:14:13 +0000 Subject: Fixed unexpected timeout in Usb MassStorage Driver. Fixed unexpected timeout in Uhci/Ehci driver. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@4038 6f19259b-4bc3-4df7-8a09-765794883524 --- MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c | 6 +-- MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c | 60 +++++++++++-------------- MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c | 22 ++++----- MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.h | 9 ++-- MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.c | 62 ++++++++++++------------- MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.h | 72 ++++++++++++++++++++++++++---- 6 files changed, 140 insertions(+), 91 deletions(-) (limited to 'MdeModulePkg/Bus/Usb/UsbBusDxe') diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c index 6d68d818d2..c9e1755fde 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c @@ -464,7 +464,7 @@ UsbCtrlRequest ( Direction, Buf, &Len, - 50 * USB_STALL_1_MS, + USB_GENERAL_DEVICE_REQUEST_TIMEOUT, &UsbDev->Translator, &Result ); @@ -554,7 +554,7 @@ UsbGetMaxPacketSize0 ( return EFI_SUCCESS; } - gBS->Stall (100 * USB_STALL_1_MS); + gBS->Stall (USB_RETRY_MAX_PACK_SIZE_STALL); } return EFI_DEVICE_ERROR; @@ -981,7 +981,7 @@ UsbIoClearFeature ( UsbIo, &DevReq, EfiUsbNoData, - 10 * USB_STALL_1_MS, + USB_CLEAR_FEATURE_REQUEST_TIMEOUT, NULL, 0, &UsbResult diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c index b92e9e072e..65eb2dd77f 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c @@ -656,13 +656,9 @@ UsbEnumerateNewDev ( Parent = HubIf->Device; Bus = Parent->Bus; HubApi = HubIf->HubApi; - - - // - // Wait at least 100 ms for the power on port to stable - // - gBS->Stall (100 * USB_STALL_1_MS); - + + gBS->Stall (USB_WAIT_PORT_STABLE_STALL); + // // Hub resets the device for at least 10 milliseconds. // Host learns device speed. If device is of low/full speed @@ -774,11 +770,8 @@ UsbEnumerateNewDev ( DEBUG ((EFI_D_ERROR, "UsbEnumerateNewDev: failed to set device address - %r\n", Status)); goto ON_ERROR; } - - // - // Wait 20ms for set address to complete - // - gBS->Stall (20 * USB_STALL_1_MS); + + gBS->Stall (USB_SET_DEVICE_ADDRESS_STALL); DEBUG ((EFI_D_INFO, "UsbEnumerateNewDev: device is now ADDRESSED at %d\n", Address)); @@ -886,47 +879,44 @@ UsbEnumeratePort ( if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_OVERCURRENT)) { // - // Both OverCurrent and OverCurrentChange set, means over current occurs, - // which probably is caused by short circuit. It has to wait system hardware - // to perform recovery. + // Case1: + // Both OverCurrent and OverCurrentChange set, means over current occurs, + // which probably is caused by short circuit. It has to wait system hardware + // to perform recovery. // DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: Critical Over Current\n", Port)); return EFI_DEVICE_ERROR; - } else { - // - // Only OverCurrentChange set, means system has been recoveried from - // over current. As a result, all ports are nearly power-off, so - // it's necessary to detach and enumerate all ports again. - // - DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: 2.0 device Recovery Over Current\n", Port)); - goto ON_ENUMERATE; - - } + } + // + // Case2: + // Only OverCurrentChange set, means system has been recoveried from + // over current. As a result, all ports are nearly power-off, so + // it's necessary to detach and enumerate all ports again. + // + DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: 2.0 device Recovery Over Current\n", Port)); } if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_ENABLE)) { // - // 1.1 roothub port reg doesn't reflect over-current state, while its counterpart - // on 2.0 roothub does. When over-current has influence on 1.1 device, the port - // would be disabled, so it's also necessary to detach and enumerate again. + // Case3: + // 1.1 roothub port reg doesn't reflect over-current state, while its counterpart + // on 2.0 roothub does. When over-current has influence on 1.1 device, the port + // would be disabled, so it's also necessary to detach and enumerate again. // DEBUG (( EFI_D_ERROR, "UsbEnumeratePort: 1.1 device Recovery Over Current\n", Port)); - goto ON_ENUMERATE; } if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_CONNECTION)) { // - // Device connected or disconnected normally. + // Case4: + // Device connected or disconnected normally. // - goto ON_ENUMERATE; + DEBUG ((EFI_D_ERROR, "UsbEnumeratePort: Device Connect/Discount Normally\n", Port)); } -ON_ENUMERATE: - // - // In case there is already a device on this port logically, it's safety to remove - // and enumerate again. + // Following as the above cases, it's safety to remove and create again. // Child = UsbFindChild (HubIf, Port); diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c index 795f545b77..8a69ca6ece 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c @@ -745,7 +745,7 @@ UsbHubInit ( UsbHubCtrlSetPortFeature (HubIf->Device, Index, (EFI_USB_PORT_FEATURE) USB_HUB_PORT_POWER); } - gBS->Stall (HubDesc.PwrOn2PwrGood * 2 * USB_STALL_1_MS); + gBS->Stall (HubDesc.PwrOn2PwrGood * USB_SET_PORT_POWER_STALL); UsbHubAckHubStatus (HubIf->Device); DEBUG (( EFI_D_INFO, "UsbHubInit: hub %d initialized\n", HubDev->Address)); @@ -915,14 +915,14 @@ UsbHubResetPort ( // Drive the reset signal for at least 10ms. Check USB 2.0 Spec // section 7.1.7.5 for timing requirements. // - gBS->Stall (20 * USB_STALL_1_MS); + gBS->Stall (USB_SET_PORT_RESET_STALL); // // USB hub will clear RESET bit if reset is actually finished. // ZeroMem (&PortState, sizeof (EFI_USB_PORT_STATUS)); - for (Index = 0; Index < 20; Index++) { + for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) { Status = UsbHubGetPortStatus (HubIf, Port, &PortState); if (!EFI_ERROR (Status) && @@ -931,7 +931,7 @@ UsbHubResetPort ( return EFI_SUCCESS; } - gBS->Stall (5 * USB_STALL_1_MS); + gBS->Stall (USB_WAIT_PORT_STS_CHANGE_STALL); } return EFI_TIMEOUT; @@ -1228,7 +1228,7 @@ UsbRootHubResetPort ( // Drive the reset signal for at least 50ms. Check USB 2.0 Spec // section 7.1.7.5 for timing requirements. // - gBS->Stall (50 * USB_STALL_1_MS); + gBS->Stall (USB_SET_ROOT_PORT_RESET_STALL); Status = UsbHcClearRootHubPortFeature (Bus, Port, EfiUsbPortReset); @@ -1237,7 +1237,7 @@ UsbRootHubResetPort ( return Status; } - gBS->Stall (USB_STALL_1_MS); + gBS->Stall (USB_CLR_ROOT_PORT_RESET_STALL); // // USB host controller won't clear the RESET bit until @@ -1245,7 +1245,7 @@ UsbRootHubResetPort ( // ZeroMem (&PortState, sizeof (EFI_USB_PORT_STATUS)); - for (Index = 0; Index < USB_HUB_LOOP; Index++) { + for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) { Status = UsbHcGetRootHubPortStatus (Bus, Port, &PortState); if (EFI_ERROR (Status)) { @@ -1256,11 +1256,11 @@ UsbRootHubResetPort ( break; } - gBS->Stall (10 * USB_STALL_1_MS); + gBS->Stall (USB_WAIT_PORT_STS_CHANGE_STALL); } - if (Index == USB_HUB_LOOP) { - DEBUG (( EFI_D_ERROR, "UsbRootHubResetPort: reset not finished in time on port %d\n", Port)); + if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) { + DEBUG ((EFI_D_ERROR, "UsbRootHubResetPort: reset not finished in time on port %d\n", Port)); return EFI_TIMEOUT; } @@ -1286,7 +1286,7 @@ UsbRootHubResetPort ( return Status; } - gBS->Stall (20 * USB_STALL_1_MS); + gBS->Stall (USB_SET_ROOT_PORT_ENABLE_STALL); } } diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.h b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.h index a5bcbb2623..36b6a43482 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.h +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.h @@ -90,8 +90,11 @@ enum { USB_HUB_CLASS_CODE = 0x09, USB_HUB_SUBCLASS_CODE = 0x00, - - USB_HUB_LOOP = 50 + // + // Host software return timeout if port status doesn't change + // after 500ms(LOOP * STALL = 100 * 5ms), set by experience + // + USB_WAIT_PORT_STS_CHANGE_LOOP = 100, }; #pragma pack(1) @@ -112,7 +115,7 @@ typedef struct { typedef struct { UINT16 ChangedBit; - UINT8 Feature; + EFI_USB_PORT_FEATURE Feature; } USB_CHANGE_FEATURE_MAP; diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.c index 2e2333aa7c..910ebc5d23 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.c +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.c @@ -1142,6 +1142,24 @@ UsbBusControllerDriverStart ( goto CLOSE_HC; } + UsbHcReset (UsbBus, EFI_USB_HC_RESET_GLOBAL); + UsbHcSetState (UsbBus, EfiUsbHcStateOperational); + + // + // Install an EFI_USB_BUS_PROTOCOL to host controler to identify it. + // + Status = gBS->InstallProtocolInterface ( + &Controller, + &mUsbBusProtocolGuid, + EFI_NATIVE_INTERFACE, + &UsbBus->BusId + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to install bus protocol %r\n", Status)); + goto CLOSE_HC; + } + // // Create a fake usb device for root hub // @@ -1149,7 +1167,7 @@ UsbBusControllerDriverStart ( if (RootHub == NULL) { Status = EFI_OUT_OF_RESOURCES; - goto CLOSE_HC; + goto UNINSTALL_USBBUS; } RootIf = AllocateZeroPool (sizeof (USB_INTERFACE)); @@ -1157,7 +1175,7 @@ UsbBusControllerDriverStart ( if (RootIf == NULL) { gBS->FreePool (RootHub); Status = EFI_OUT_OF_RESOURCES; - goto CLOSE_HC; + goto FREE_ROOTHUB; } RootHub->Bus = UsbBus; @@ -1166,11 +1184,7 @@ UsbBusControllerDriverStart ( RootIf->Signature = USB_INTERFACE_SIGNATURE; RootIf->Device = RootHub; RootIf->DevicePath = UsbBus->DevicePath; - - UsbHcReset (UsbBus, EFI_USB_HC_RESET_GLOBAL); - UsbHcSetState (UsbBus, EfiUsbHcStateOperational); - Status = mUsbRootHubApi.Init (RootIf); if (EFI_ERROR (Status)) { @@ -1180,31 +1194,20 @@ UsbBusControllerDriverStart ( UsbBus->Devices[0] = RootHub; - // - // Install an EFI_USB_BUS_PROTOCOL to host controler to identify it. - // - Status = gBS->InstallProtocolInterface ( - &Controller, - &mUsbBusProtocolGuid, - EFI_NATIVE_INTERFACE, - &UsbBus->BusId - ); - - if (EFI_ERROR (Status)) { - DEBUG (( EFI_D_ERROR, "UsbBusStart: Failed to install bus protocol %r\n", Status)); - - mUsbRootHubApi.Release (RootIf); - goto FREE_ROOTHUB; - } - - DEBUG (( EFI_D_INFO, "UsbBusStart: usb bus started on %x, root hub %x\n", Controller, RootIf)); return EFI_SUCCESS; - + FREE_ROOTHUB: - gBS->FreePool (RootIf); - gBS->FreePool (RootHub); - + if (RootIf != NULL) { + gBS->FreePool (RootIf); + } + if (RootHub != NULL) { + gBS->FreePool (RootHub); + } + +UNINSTALL_USBBUS: + gBS->UninstallProtocolInterface (Controller, &mUsbBusProtocolGuid, &UsbBus->BusId); + CLOSE_HC: if (UsbBus->Usb2Hc != NULL) { gBS->CloseProtocol ( @@ -1214,7 +1217,6 @@ CLOSE_HC: Controller ); } - if (UsbBus->UsbHc != NULL) { gBS->CloseProtocol ( Controller, @@ -1223,14 +1225,12 @@ CLOSE_HC: Controller ); } - gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); - gBS->FreePool (UsbBus); DEBUG (( EFI_D_ERROR, "UsbBusStart: Failed to start bus driver %r\n", Status)); diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.h b/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.h index 4bf9d53015..971e01b47a 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.h +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.h @@ -55,21 +55,77 @@ typedef struct _USB_HUB_API USB_HUB_API; #include "UsbEnumer.h" enum { + USB_MAX_LANG_ID = 16, + USB_MAX_INTERFACE = 16, + USB_MAX_DEVICES = 128, + + USB_BUS_1_MILLISECOND = 1000, + // - // Time definition + // Roothub and hub's polling interval, set by experience, + // The unit of roothub is 100us, means 1s as interval, and + // the unit of hub is 1ms, means 64ms as interval. // - USB_STALL_1_MS = 1000, - TICKS_PER_MS = 10000U, - USB_ROOTHUB_POLL_INTERVAL = 1000 * TICKS_PER_MS, + USB_ROOTHUB_POLL_INTERVAL = 1000 * 10000U, USB_HUB_POLL_INTERVAL = 64, // - // Maximum definition + // Wait for port stable to work, refers to specification + // [USB20-9.1.2] // - USB_MAX_LANG_ID = 16, - USB_MAX_INTERFACE = 16, - USB_MAX_DEVICES = 128, + USB_WAIT_PORT_STABLE_STALL = 100 * USB_BUS_1_MILLISECOND, + + // + // Wait for port statue reg change, set by experience + // + USB_WAIT_PORT_STS_CHANGE_STALL = 5 * USB_BUS_1_MILLISECOND, + + // + // Wait for set device address, refers to specification + // [USB20-9.2.6.3, it says 2ms] + // + USB_SET_DEVICE_ADDRESS_STALL = 20 * USB_BUS_1_MILLISECOND, + + // + // Wait for retry max packet size, set by experience + // + USB_RETRY_MAX_PACK_SIZE_STALL = 100 * USB_BUS_1_MILLISECOND, + // + // Wait for hub port power-on, refers to specification + // [USB20-11.23.2] + // + USB_SET_PORT_POWER_STALL = 2 * USB_BUS_1_MILLISECOND, + + // + // Wait for port reset, refers to specification + // [USB20-7.1.7.5, it says 10ms for hub and 50ms for + // root hub] + // + USB_SET_PORT_RESET_STALL = 20 * USB_BUS_1_MILLISECOND, + USB_SET_ROOT_PORT_RESET_STALL = 50 * USB_BUS_1_MILLISECOND, + + // + // Wait for clear roothub port reset, set by experience + // + USB_CLR_ROOT_PORT_RESET_STALL = 1 * USB_BUS_1_MILLISECOND, + + // + // Wait for set roothub port enable, set by experience + // + USB_SET_ROOT_PORT_ENABLE_STALL = 20 * USB_BUS_1_MILLISECOND, + + // + // Send general device request timeout, refers to + // specification[USB20-11.24.1] + // + USB_GENERAL_DEVICE_REQUEST_TIMEOUT = 50 * USB_BUS_1_MILLISECOND, + + // + // Send clear feature request timeout, set by experience + // + USB_CLEAR_FEATURE_REQUEST_TIMEOUT = 10 * USB_BUS_1_MILLISECOND, + // // Bus raises TPL to TPL_NOTIFY to serialize all its operations // to protect shared data structures. -- cgit v1.2.3