summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Bus/Pci/EhciDxe
diff options
context:
space:
mode:
authoryshang1 <yshang1@6f19259b-4bc3-4df7-8a09-765794883524>2007-10-08 06:14:13 +0000
committeryshang1 <yshang1@6f19259b-4bc3-4df7-8a09-765794883524>2007-10-08 06:14:13 +0000
commit41e8ff2781f3ca14f73ef5f39e781ccba8cb373d (patch)
tree8fd7edcbb8c98bf324db6e2b043b3603abf67158 /MdeModulePkg/Bus/Pci/EhciDxe
parentba5711102a63d081cb388289983a0e2734e42fb5 (diff)
downloadedk2-platforms-41e8ff2781f3ca14f73ef5f39e781ccba8cb373d.tar.xz
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
Diffstat (limited to 'MdeModulePkg/Bus/Pci/EhciDxe')
-rw-r--r--MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c34
-rw-r--r--MdeModulePkg/Bus/Pci/EhciDxe/Ehci.h41
-rw-r--r--MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.c13
-rw-r--r--MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c6
4 files changed, 63 insertions, 31 deletions
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) {