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/Pci/EhciDxe/Ehci.c | 34 ++++++++++++++++---------- MdeModulePkg/Bus/Pci/EhciDxe/Ehci.h | 41 ++++++++++++++++++++++---------- MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.c | 13 ++++++---- MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c | 6 ++--- MdeModulePkg/Bus/Pci/UhciDxe/Uhci.c | 41 ++++++++++++-------------------- MdeModulePkg/Bus/Pci/UhciDxe/Uhci.h | 36 +++++++++++++++++++++------- MdeModulePkg/Bus/Pci/UhciDxe/UhciSched.c | 6 ++--- 7 files changed, 108 insertions(+), 69 deletions(-) (limited to 'MdeModulePkg/Bus/Pci') diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c b/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c index 13ce7fdfb1..07a690edce 100644 --- a/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c +++ b/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c @@ -126,14 +126,14 @@ EhcReset ( // Host Controller must be Halt when Reset it // if (!EhcIsHalt (Ehc)) { - Status = EhcHaltHC (Ehc, EHC_GENERIC_TIME); + Status = EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT); if (EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; goto ON_EXIT; } } - + // // Clean up the asynchronous transfers, currently only // interrupt supports asynchronous operation. @@ -142,7 +142,7 @@ EhcReset ( EhcAckAllInterrupt (Ehc); EhcFreeSched (Ehc); - Status = EhcResetHC (Ehc, EHC_STALL_1_SECOND); + Status = EhcResetHC (Ehc, EHC_RESET_TIMEOUT); if (EFI_ERROR (Status)) { goto ON_EXIT; @@ -251,7 +251,7 @@ EhcSetState ( switch (State) { case EfiUsbHcStateHalt: - Status = EhcHaltHC (Ehc, EHC_GENERIC_TIME); + Status = EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT); break; case EfiUsbHcStateOperational: @@ -260,7 +260,17 @@ EhcSetState ( break; } - Status = EhcRunHC (Ehc, EHC_GENERIC_TIME); + // + // Software must not write a one to this field unless the host controller + // is in the Halted state. Doing so will yield undefined results. + // refers to Spec[EHCI1.0-2.3.1] + // + if (!EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) { + Status = EFI_DEVICE_ERROR; + break; + } + + Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT); break; case EfiUsbHcStateSuspend: @@ -437,14 +447,14 @@ EhcSetRootHubPortFeature ( // Make sure Host Controller not halt before reset it // if (EhcIsHalt (Ehc)) { - Status = EhcRunHC (Ehc, EHC_GENERIC_TIME); + Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT); if (EFI_ERROR (Status)) { EHC_DEBUG (("EhcSetRootHubPortFeature :failed to start HC - %r\n", Status)); break; } } - + // // Set one to PortReset bit must also set zero to PortEnable bit // @@ -1539,7 +1549,7 @@ EhcDriverBindingStart ( // Robustnesss improvement such as for UoL // EhcClearLegacySupport (Ehc); - EhcResetHC (Ehc, EHC_STALL_1_SECOND); + EhcResetHC (Ehc, EHC_RESET_TIMEOUT); Status = EhcInitHC (Ehc); @@ -1551,12 +1561,12 @@ EhcDriverBindingStart ( // // Start the asynchronous interrupt monitor // - Status = gBS->SetTimer (Ehc->PollTimer, TimerPeriodic, EHC_ASYNC_POLL_TIME); + Status = gBS->SetTimer (Ehc->PollTimer, TimerPeriodic, EHC_ASYNC_POLL_INTERVAL); if (EFI_ERROR (Status)) { EHC_ERROR (("EhcDriverBindingStart: failed to start async interrupt monitor\n")); - EhcHaltHC (Ehc, EHC_GENERIC_TIME); + EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT); goto UNINSTALL_USBHC; } @@ -1659,8 +1669,8 @@ EhcDriverBindingStop ( // Stop AsyncRequest Polling timer then stop the EHCI driver // and uninstall the EHCI protocl. // - gBS->SetTimer (Ehc->PollTimer, TimerCancel, EHC_ASYNC_POLL_TIME); - EhcHaltHC (Ehc, EHC_GENERIC_TIME); + gBS->SetTimer (Ehc->PollTimer, TimerCancel, EHC_ASYNC_POLL_INTERVAL); + EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT); Status = gBS->UninstallProtocolInterface ( Controller, diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.h b/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.h index 7eb61be05a..816587db8d 100644 --- a/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.h +++ b/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.h @@ -49,18 +49,35 @@ typedef struct _USB2_HC_DEV USB2_HC_DEV; #include "EhciDebug.h" enum { - USB2_HC_DEV_SIGNATURE = EFI_SIGNATURE_32 ('e', 'h', 'c', 'i'), - EHC_STALL_1_MICROSECOND = 1, - EHC_STALL_1_MILLISECOND = 1000 * EHC_STALL_1_MICROSECOND, - EHC_STALL_1_SECOND = 1000 * EHC_STALL_1_MILLISECOND, - - EHC_SET_PORT_RESET_TIME = 50 * EHC_STALL_1_MILLISECOND, - EHC_CLEAR_PORT_RESET_TIME = EHC_STALL_1_MILLISECOND, - EHC_GENERIC_TIME = 10 * EHC_STALL_1_MILLISECOND, - EHC_SYNC_POLL_TIME = 20 * EHC_STALL_1_MICROSECOND, - EHC_ASYNC_POLL_TIME = 50 * 10000UL, // The unit of time is 100us - - EHC_TPL = TPL_NOTIFY + EHC_1_MICROSECOND = 1, + EHC_1_MILLISECOND = 1000 * EHC_1_MICROSECOND, + EHC_1_SECOND = 1000 * EHC_1_MILLISECOND, + + // + // EHCI register operation timeout, set by experience + // + EHC_RESET_TIMEOUT = 1 * EHC_1_SECOND, + EHC_GENERIC_TIMEOUT = 10 * EHC_1_MILLISECOND, + + // + // Wait for roothub port power stable, refers to Spec[EHCI1.0-2.3.9] + // + EHC_ROOT_PORT_RECOVERY_STALL = 20 * EHC_1_MILLISECOND, + + // + // Sync and Async transfer polling interval, set by experience, + // and the unit of Async is 100us, means 50ms as interval. + // + EHC_SYNC_POLL_INTERVAL = 20 * EHC_1_MICROSECOND, + EHC_ASYNC_POLL_INTERVAL = 50 * 10000U, + + // + // EHC raises TPL to TPL_NOTIFY to serialize all its operations + // to protect shared data structures. + // + EHC_TPL = TPL_NOTIFY, + + USB2_HC_DEV_SIGNATURE = EFI_SIGNATURE_32 ('e', 'h', 'c', 'i'), }; // diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.c b/MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.c index 290cb3847a..45b6df5c83 100644 --- a/MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.c +++ b/MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.c @@ -214,12 +214,12 @@ EhcWaitOpRegBit ( { UINT32 Index; - for (Index = 0; Index < Timeout / EHC_SYNC_POLL_TIME + 1; Index++) { + for (Index = 0; Index < Timeout / EHC_SYNC_POLL_INTERVAL + 1; Index++) { if (EHC_REG_BIT_IS_SET (Ehc, Offset, Bit) == WaitToSet) { return EFI_SUCCESS; } - gBS->Stall (EHC_SYNC_POLL_TIME); + gBS->Stall (EHC_SYNC_POLL_INTERVAL); } return EFI_TIMEOUT; @@ -614,14 +614,19 @@ EhcInitHC ( // EhcSetOpRegBit (Ehc, EHC_CONFIG_FLAG_OFFSET, CONFIGFLAG_ROUTE_EHC); - Status = EhcEnablePeriodSchd (Ehc, EHC_GENERIC_TIME); + // + // Wait roothub port power stable + // + gBS->Stall (EHC_ROOT_PORT_RECOVERY_STALL); + + Status = EhcEnablePeriodSchd (Ehc, EHC_GENERIC_TIMEOUT); if (EFI_ERROR (Status)) { EHC_ERROR (("EhcInitHC: failed to enable period schedule\n")); return Status; } - Status = EhcEnableAsyncSchd (Ehc, EHC_GENERIC_TIME); + Status = EhcEnableAsyncSchd (Ehc, EHC_GENERIC_TIMEOUT); if (EFI_ERROR (Status)) { EHC_ERROR (("EhcInitHC: failed to enable async schedule\n")); diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c b/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c index 4c2dc86f06..349b5c233a 100644 --- a/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c +++ b/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c @@ -342,7 +342,7 @@ EhcUnlinkQhFromAsync ( // // Set and wait the door bell to synchronize with the hardware // - Status = EhcSetAndWaitDoorBell (Ehc, EHC_GENERIC_TIME); + Status = EhcSetAndWaitDoorBell (Ehc, EHC_GENERIC_TIMEOUT); if (EFI_ERROR (Status)) { EHC_ERROR (("EhcUnlinkQhFromAsync: Failed to synchronize with doorbell\n")); @@ -659,7 +659,7 @@ EhcExecTransfer ( BOOLEAN Finished; Status = EFI_SUCCESS; - Loop = (TimeOut * EHC_STALL_1_MILLISECOND / EHC_SYNC_POLL_TIME) + 1; + Loop = (TimeOut * EHC_1_MILLISECOND / EHC_SYNC_POLL_INTERVAL) + 1; Finished = FALSE; for (Index = 0; Index < Loop; Index++) { @@ -669,7 +669,7 @@ EhcExecTransfer ( break; } - gBS->Stall (EHC_SYNC_POLL_TIME); + gBS->Stall (EHC_SYNC_POLL_INTERVAL); } if (!Finished) { diff --git a/MdeModulePkg/Bus/Pci/UhciDxe/Uhci.c b/MdeModulePkg/Bus/Pci/UhciDxe/Uhci.c index 1dee976504..00108b87e2 100644 --- a/MdeModulePkg/Bus/Pci/UhciDxe/Uhci.c +++ b/MdeModulePkg/Bus/Pci/UhciDxe/Uhci.c @@ -56,44 +56,33 @@ UhciReset ( // // Stop schedule and set the Global Reset bit in the command register // - UhciStopHc (Uhc, STALL_1_SECOND); + UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT); UhciSetRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_GRESET); - // - // Wait 50ms for root port to let reset complete - // See UHCI spec page122 Reset signaling - // - gBS->Stall (ROOT_PORT_REST_TIME); + gBS->Stall (UHC_ROOT_PORT_RESET_STALL); // // Clear the Global Reset bit to zero. // UhciClearRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_GRESET); - // - // UHCI spec page120 reset recovery time - // - gBS->Stall (PORT_RESET_RECOVERY_TIME); + gBS->Stall (UHC_ROOT_PORT_RECOVERY_STALL); break; case EFI_USB_HC_RESET_HOST_CONTROLLER: // // Stop schedule and set Host Controller Reset bit to 1 // - UhciStopHc (Uhc, STALL_1_SECOND); + UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT); UhciSetRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_HCRESET); - // - // this bit will be reset by Host Controller when reset is completed. - // wait 10ms to let reset complete - // - gBS->Stall (PORT_RESET_RECOVERY_TIME); + gBS->Stall (UHC_ROOT_PORT_RECOVERY_STALL); break; default: goto ON_INVAILD_PARAMETER; } - + // // Delete all old transactions on the USB bus, then // reinitialize the frame list @@ -103,13 +92,13 @@ UhciReset ( UhciInitFrameList (Uhc); gBS->RestoreTPL (OldTpl); - + return EFI_SUCCESS; ON_INVAILD_PARAMETER: - + gBS->RestoreTPL (OldTpl); - + return EFI_INVALID_PARAMETER; } @@ -202,7 +191,7 @@ UhciSetState ( switch (State) { case EfiUsbHcStateHalt: - Status = UhciStopHc (Uhc, STALL_1_SECOND); + Status = UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT); break; case EfiUsbHcStateOperational: @@ -224,11 +213,11 @@ UhciSetState ( UsbCmd |= USBCMD_FGR; UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, UsbCmd); } - + // // wait 20ms to let resume complete (20ms is specified by UHCI spec) // - gBS->Stall (FORCE_GLOBAL_RESUME_TIME); + gBS->Stall (UHC_FORCE_GLOBAL_RESUME_STALL); // // Write FGR bit to 0 and EGSM(Enter Global Suspend Mode) bit to 0 @@ -248,7 +237,7 @@ UhciSetState ( Status = EFI_DEVICE_ERROR; goto ON_EXIT; } - + // // Set Enter Global Suspend Mode bit to 1. // @@ -2084,7 +2073,7 @@ UhciCleanDevUp ( // Uninstall the USB_HC and USB_HC2 protocol, then disable the controller // Uhc = UHC_FROM_USB_HC_PROTO (This); - UhciStopHc (Uhc, STALL_1_SECOND); + UhciStopHc (Uhc, UHC_GENERIC_TIMEOUT); gBS->UninstallProtocolInterface ( Controller, @@ -2188,7 +2177,7 @@ UhciDriverBindingStart ( Status = gBS->SetTimer ( Uhc->AsyncIntMonitor, TimerPeriodic, - INTERRUPT_POLLING_TIME + UHC_ASYNC_POLL_INTERVAL ); if (EFI_ERROR (Status)) { diff --git a/MdeModulePkg/Bus/Pci/UhciDxe/Uhci.h b/MdeModulePkg/Bus/Pci/UhciDxe/Uhci.h index 3f2540faf7..e7b4447def 100644 --- a/MdeModulePkg/Bus/Pci/UhciDxe/Uhci.h +++ b/MdeModulePkg/Bus/Pci/UhciDxe/Uhci.h @@ -51,25 +51,43 @@ typedef struct _USB_HC_DEV USB_HC_DEV; #include "UhciDebug.h" enum { + UHC_1_MICROSECOND = 1, + UHC_1_MILLISECOND = 1000 * UHC_1_MICROSECOND, + UHC_1_SECOND = 1000 * UHC_1_MILLISECOND, + + // + // UHCI register operation timeout, set by experience // - // Stall times + UHC_GENERIC_TIMEOUT = UHC_1_SECOND, + // - STALL_1_MS = 1000, - STALL_1_SECOND = 1000 *STALL_1_MS, + // Wait for force global resume(FGR) complete, refers to + // specification[UHCI11-2.1.1] + // + UHC_FORCE_GLOBAL_RESUME_STALL = 20 * UHC_1_MILLISECOND, - UHC_SYN_POLL = 50, - FORCE_GLOBAL_RESUME_TIME = 20 *STALL_1_MS, - ROOT_PORT_REST_TIME = 50 *STALL_1_MS, - PORT_RESET_RECOVERY_TIME = 10 *STALL_1_MS, - INTERRUPT_POLLING_TIME = 50 * 10000UL, + // + // Wait for roothub port reset and recovery, reset stall + // is set by experience, and recovery stall refers to + // specification[UHCI11-2.1.1] + // + UHC_ROOT_PORT_RESET_STALL = 50 * UHC_1_MILLISECOND, + UHC_ROOT_PORT_RECOVERY_STALL = 10 * UHC_1_MILLISECOND, + // + // Sync and Async transfer polling interval, set by experience, + // and the unit of Async is 100us. + // + UHC_SYNC_POLL_INTERVAL = 50 * UHC_1_MICROSECOND, + UHC_ASYNC_POLL_INTERVAL = 50 * 10000UL, + // // UHC raises TPL to TPL_NOTIFY to serialize all its operations // to protect shared data structures. // UHCI_TPL = TPL_NOTIFY, - USB_HC_DEV_SIGNATURE = EFI_SIGNATURE_32 ('u', 'h', 'c', 'i') + USB_HC_DEV_SIGNATURE = EFI_SIGNATURE_32 ('u', 'h', 'c', 'i'), }; #pragma pack(1) diff --git a/MdeModulePkg/Bus/Pci/UhciDxe/UhciSched.c b/MdeModulePkg/Bus/Pci/UhciDxe/UhciSched.c index e1b602e7e2..401d32eb34 100644 --- a/MdeModulePkg/Bus/Pci/UhciDxe/UhciSched.c +++ b/MdeModulePkg/Bus/Pci/UhciDxe/UhciSched.c @@ -575,8 +575,8 @@ UhciExecuteTransfer ( Finished = FALSE; Status = EFI_SUCCESS; - Delay = (TimeOut * STALL_1_MS / UHC_SYN_POLL) + 1; - + Delay = (TimeOut * UHC_1_MILLISECOND / UHC_SYNC_POLL_INTERVAL) + 1; + for (Index = 0; Index < Delay; Index++) { Finished = UhciCheckTdStatus (Uhc, Td, IsLow, QhResult); @@ -587,7 +587,7 @@ UhciExecuteTransfer ( break; } - gBS->Stall (UHC_SYN_POLL); + gBS->Stall (UHC_SYNC_POLL_INTERVAL); } if (!Finished) { -- cgit v1.2.3