summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Bus/Usb/UsbBusDxe
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg/Bus/Usb/UsbBusDxe')
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c8
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h11
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c6
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c24
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c8
5 files changed, 39 insertions, 18 deletions
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c
index 742cdc193..ff6b99c87 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 094aea21c..d503a278a 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h
@@ -99,10 +99,19 @@ 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
//
#define USB_CLR_ROOT_PORT_RESET_STALL (20 * USB_BUS_1_MILLISECOND)
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c
index 529b13618..35cdaf552 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c
@@ -2,7 +2,7 @@
Manage Usb Descriptor List
-Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@@ -360,8 +360,8 @@ UsbParseConfigDesc (
Setting = UsbParseInterfaceDesc (DescBuf, Len, &Consumed);
if (Setting == NULL) {
- DEBUG (( EFI_D_ERROR, "UsbParseConfigDesc: failed to parse interface setting\n"));
- goto ON_ERROR;
+ DEBUG (( EFI_D_ERROR, "UsbParseConfigDesc: warning: failed to get interface setting, stop parsing now.\n"));
+ break;
} else if (Setting->Desc.InterfaceNumber >= NumIf) {
DEBUG (( EFI_D_ERROR, "UsbParseConfigDesc: mal-formated interface descriptor\n"));
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
index 74de7d5d5..0aa896173 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
@@ -2,7 +2,7 @@
Usb bus enumeration support.
-Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@@ -814,14 +814,20 @@ UsbEnumerateNewDev (
return EFI_SUCCESS;
ON_ERROR:
- if (Address != Bus->MaxDevices) {
- Bus->Devices[Address] = NULL;
- }
-
- if (Child != NULL) {
- UsbFreeDevice (Child);
- }
-
+ //
+ // If reach here, it means the enumeration process on a given port is interrupted due to error.
+ // The s/w resources, including the assigned address(Address) and the allocated usb device data
+ // structure(Bus->Devices[Address]), will NOT be freed here. These resources will be freed when
+ // the device is unplugged from the port or DriverBindingStop() is invoked.
+ //
+ // This way is used to co-work with the lower layer EDKII UHCI/EHCI/XHCI host controller driver.
+ // It's mainly because to keep UEFI spec unchanged EDKII XHCI driver have to maintain a state machine
+ // to keep track of the mapping between actual address and request address. If the request address
+ // (Address) is freed here, the Address value will be used by next enumerated device. Then EDKII XHCI
+ // host controller driver will have wrong information, which will cause further transaction error.
+ //
+ // EDKII UHCI/EHCI doesn't get impacted as it's make sense to reserve s/w resource till it gets unplugged.
+ //
return Status;
}
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c
index 2d24bb4b8..9e5299c0e 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;
}