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
This commit is contained in:
@@ -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,
|
||||
|
@@ -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_1_MICROSECOND = 1,
|
||||
EHC_1_MILLISECOND = 1000 * EHC_1_MICROSECOND,
|
||||
EHC_1_SECOND = 1000 * EHC_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
|
||||
//
|
||||
// EHCI register operation timeout, set by experience
|
||||
//
|
||||
EHC_RESET_TIMEOUT = 1 * EHC_1_SECOND,
|
||||
EHC_GENERIC_TIMEOUT = 10 * EHC_1_MILLISECOND,
|
||||
|
||||
EHC_TPL = TPL_NOTIFY
|
||||
//
|
||||
// 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'),
|
||||
};
|
||||
|
||||
//
|
||||
|
@@ -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"));
|
||||
|
@@ -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) {
|
||||
|
@@ -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)) {
|
||||
|
@@ -51,25 +51,43 @@ typedef struct _USB_HC_DEV USB_HC_DEV;
|
||||
#include "UhciDebug.h"
|
||||
|
||||
enum {
|
||||
//
|
||||
// Stall times
|
||||
//
|
||||
STALL_1_MS = 1000,
|
||||
STALL_1_SECOND = 1000 *STALL_1_MS,
|
||||
UHC_1_MICROSECOND = 1,
|
||||
UHC_1_MILLISECOND = 1000 * UHC_1_MICROSECOND,
|
||||
UHC_1_SECOND = 1000 * 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,
|
||||
//
|
||||
// UHCI register operation timeout, set by experience
|
||||
//
|
||||
UHC_GENERIC_TIMEOUT = UHC_1_SECOND,
|
||||
|
||||
//
|
||||
// Wait for force global resume(FGR) complete, refers to
|
||||
// specification[UHCI11-2.1.1]
|
||||
//
|
||||
UHC_FORCE_GLOBAL_RESUME_STALL = 20 * UHC_1_MILLISECOND,
|
||||
|
||||
//
|
||||
// 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)
|
||||
|
@@ -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) {
|
||||
|
Reference in New Issue
Block a user