summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhil Noh <Phil.Noh@amd.com>2025-02-10 18:51:35 -0600
committerLiming Gao <gaoliming@byosoft.com.cn>2025-02-19 10:21:00 +0800
commit0192f2d7cb3098d5cf1a2ed25874f47a08001de7 (patch)
tree4a952f17119af1f9c1dfde7a17dd59685b36cd63
parentbc664d1830c9446cb1d33b10a41e6b3d207997f1 (diff)
downloadedk2-0192f2d7cb3098d5cf1a2ed25874f47a08001de7.tar.gz
MdeModulePkg/UsbBusPei: Improve PEI USB enumeration
Unlike DXE USB enumeration that enumerates all changed ports on timer interrupt, PEI USB Enumeration runs once at the driver entry point. USB3.x devices initially appear in USB2.0 ports. When the USB2.0 port is reset, the USB3.x device disappears from the USB2.0 port and appears on the USB3.0 port. The USB3.x device won't be enumerated if the USB2.0 port number is greater than the USB3.0 port number. Re-enumerate USB to make sure USB3.x devices in this case. Signed-off-by: Phil Noh <Phil.Noh@amd.com>
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.c331
1 files changed, 170 insertions, 161 deletions
diff --git a/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.c b/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.c
index 6ea4495162..159cd19340 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.c
+++ b/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.c
@@ -1,6 +1,7 @@
/** @file
The module to produce Usb Bus PPI.
+Copyright (C) 2025 Advanced Micro Devices, Inc. All rights reserved.<BR>
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -428,6 +429,7 @@ PeiUsbEnumeration (
UINT8 CurrentAddress;
UINTN InterfaceIndex;
UINTN EndpointIndex;
+ UINT8 UsbEnumLoop;
CurrentAddress = 0;
if (Usb2HcPpi != NULL) {
@@ -449,179 +451,149 @@ PeiUsbEnumeration (
DEBUG ((DEBUG_INFO, "PeiUsbEnumeration: NumOfRootPort: %x\n", NumOfRootPort));
- for (Index = 0; Index < NumOfRootPort; Index++) {
- //
- // First get root port status to detect changes happen
- //
- if (Usb2HcPpi != NULL) {
- Usb2HcPpi->GetRootHubPortStatus (
- PeiServices,
- Usb2HcPpi,
- (UINT8)Index,
- &PortStatus
- );
- } else {
- UsbHcPpi->GetRootHubPortStatus (
- PeiServices,
- UsbHcPpi,
- (UINT8)Index,
- &PortStatus
- );
- }
-
- DEBUG ((DEBUG_INFO, "USB Status --- Port: %x ConnectChange[%04x] Status[%04x]\n", Index, PortStatus.PortChangeStatus, PortStatus.PortStatus));
- //
- // Only handle connection/enable/overcurrent/reset change.
- //
- if ((PortStatus.PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) {
- continue;
- } else {
- if (IsPortConnect (PortStatus.PortStatus)) {
- MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
- Status = PeiServicesAllocatePages (
- EfiBootServicesCode,
- MemPages,
- &AllocateAddress
+ //
+ // USB3.x devices initially appear in USB2.0 ports. When the USB2.0 port is reset, the USB3.x device disappears
+ // from the USB2.0 port and appears on the USB3.0 port. The USB3.x device won't be enumerated if the USB2.0 port
+ // number is greater than the USB3.0 port number. Re-enumerate USB to make sure USB3.x devices in this case.
+ //
+ for (UsbEnumLoop = 0; UsbEnumLoop < 2; UsbEnumLoop++) {
+ for (Index = 0; Index < NumOfRootPort; Index++) {
+ //
+ // First get root port status to detect changes happen
+ //
+ if (Usb2HcPpi != NULL) {
+ Usb2HcPpi->GetRootHubPortStatus (
+ PeiServices,
+ Usb2HcPpi,
+ (UINT8)Index,
+ &PortStatus
);
- if (EFI_ERROR (Status)) {
- return EFI_OUT_OF_RESOURCES;
- }
+ } else {
+ UsbHcPpi->GetRootHubPortStatus (
+ PeiServices,
+ UsbHcPpi,
+ (UINT8)Index,
+ &PortStatus
+ );
+ }
- PeiUsbDevice = (PEI_USB_DEVICE *)((UINTN)AllocateAddress);
- ZeroMem (PeiUsbDevice, sizeof (PEI_USB_DEVICE));
+ DEBUG ((DEBUG_INFO, "USB Status --- Port: %x ConnectChange[%04x] Status[%04x]\n", Index, PortStatus.PortChangeStatus, PortStatus.PortStatus));
+ //
+ // Only handle connection/enable/overcurrent/reset change.
+ //
+ if ((PortStatus.PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) {
+ continue;
+ } else {
+ if (IsPortConnect (PortStatus.PortStatus)) {
+ MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
+ Status = PeiServicesAllocatePages (
+ EfiBootServicesCode,
+ MemPages,
+ &AllocateAddress
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
- PeiUsbDevice->Signature = PEI_USB_DEVICE_SIGNATURE;
- PeiUsbDevice->DeviceAddress = 0;
- PeiUsbDevice->MaxPacketSize0 = 8;
- PeiUsbDevice->DataToggle = 0;
- CopyMem (
- &(PeiUsbDevice->UsbIoPpi),
- &mUsbIoPpi,
- sizeof (PEI_USB_IO_PPI)
- );
- CopyMem (
- &(PeiUsbDevice->UsbIoPpiList),
- &mUsbIoPpiList,
- sizeof (EFI_PEI_PPI_DESCRIPTOR)
- );
- PeiUsbDevice->UsbIoPpiList.Ppi = &PeiUsbDevice->UsbIoPpi;
- PeiUsbDevice->AllocateAddress = (UINTN)AllocateAddress;
- PeiUsbDevice->UsbHcPpi = UsbHcPpi;
- PeiUsbDevice->Usb2HcPpi = Usb2HcPpi;
- PeiUsbDevice->IsHub = 0x0;
- PeiUsbDevice->DownStreamPortNo = 0x0;
+ PeiUsbDevice = (PEI_USB_DEVICE *)((UINTN)AllocateAddress);
+ ZeroMem (PeiUsbDevice, sizeof (PEI_USB_DEVICE));
- if (((PortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0) ||
- ((PortStatus.PortStatus & (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE)) == 0))
- {
- //
- // If the port already has reset change flag and is connected and enabled, skip the port reset logic.
- //
- ResetRootPort (
- PeiServices,
- PeiUsbDevice->UsbHcPpi,
- PeiUsbDevice->Usb2HcPpi,
- Index,
- 0
+ PeiUsbDevice->Signature = PEI_USB_DEVICE_SIGNATURE;
+ PeiUsbDevice->DeviceAddress = 0;
+ PeiUsbDevice->MaxPacketSize0 = 8;
+ PeiUsbDevice->DataToggle = 0;
+ CopyMem (
+ &(PeiUsbDevice->UsbIoPpi),
+ &mUsbIoPpi,
+ sizeof (PEI_USB_IO_PPI)
);
-
- if (Usb2HcPpi != NULL) {
- Usb2HcPpi->GetRootHubPortStatus (
- PeiServices,
- Usb2HcPpi,
- (UINT8)Index,
- &PortStatus
- );
- } else {
- UsbHcPpi->GetRootHubPortStatus (
- PeiServices,
- UsbHcPpi,
- (UINT8)Index,
- &PortStatus
- );
- }
- } else {
- if (Usb2HcPpi != NULL) {
- Usb2HcPpi->ClearRootHubPortFeature (
- PeiServices,
- Usb2HcPpi,
- (UINT8)Index,
- EfiUsbPortResetChange
- );
+ CopyMem (
+ &(PeiUsbDevice->UsbIoPpiList),
+ &mUsbIoPpiList,
+ sizeof (EFI_PEI_PPI_DESCRIPTOR)
+ );
+ PeiUsbDevice->UsbIoPpiList.Ppi = &PeiUsbDevice->UsbIoPpi;
+ PeiUsbDevice->AllocateAddress = (UINTN)AllocateAddress;
+ PeiUsbDevice->UsbHcPpi = UsbHcPpi;
+ PeiUsbDevice->Usb2HcPpi = Usb2HcPpi;
+ PeiUsbDevice->IsHub = 0x0;
+ PeiUsbDevice->DownStreamPortNo = 0x0;
+
+ if (((PortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0) ||
+ ((PortStatus.PortStatus & (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE)) == 0))
+ {
+ //
+ // If the port already has reset change flag and is connected and enabled, skip the port reset logic.
+ //
+ ResetRootPort (
+ PeiServices,
+ PeiUsbDevice->UsbHcPpi,
+ PeiUsbDevice->Usb2HcPpi,
+ Index,
+ 0
+ );
+
+ if (Usb2HcPpi != NULL) {
+ Usb2HcPpi->GetRootHubPortStatus (
+ PeiServices,
+ Usb2HcPpi,
+ (UINT8)Index,
+ &PortStatus
+ );
+ } else {
+ UsbHcPpi->GetRootHubPortStatus (
+ PeiServices,
+ UsbHcPpi,
+ (UINT8)Index,
+ &PortStatus
+ );
+ }
} else {
- UsbHcPpi->ClearRootHubPortFeature (
- PeiServices,
- UsbHcPpi,
- (UINT8)Index,
- EfiUsbPortResetChange
- );
+ if (Usb2HcPpi != NULL) {
+ Usb2HcPpi->ClearRootHubPortFeature (
+ PeiServices,
+ Usb2HcPpi,
+ (UINT8)Index,
+ EfiUsbPortResetChange
+ );
+ } else {
+ UsbHcPpi->ClearRootHubPortFeature (
+ PeiServices,
+ UsbHcPpi,
+ (UINT8)Index,
+ EfiUsbPortResetChange
+ );
+ }
}
- }
- PeiUsbDevice->DeviceSpeed = (UINT8)PeiUsbGetDeviceSpeed (PortStatus.PortStatus);
- DEBUG ((DEBUG_INFO, "Device Speed =%d\n", PeiUsbDevice->DeviceSpeed));
+ PeiUsbDevice->DeviceSpeed = (UINT8)PeiUsbGetDeviceSpeed (PortStatus.PortStatus);
+ DEBUG ((DEBUG_INFO, "Device Speed =%d\n", PeiUsbDevice->DeviceSpeed));
- if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_SUPER_SPEED)) {
- PeiUsbDevice->MaxPacketSize0 = 512;
- } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_HIGH_SPEED)) {
- PeiUsbDevice->MaxPacketSize0 = 64;
- } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_LOW_SPEED)) {
- PeiUsbDevice->MaxPacketSize0 = 8;
- } else {
- PeiUsbDevice->MaxPacketSize0 = 8;
- }
-
- //
- // Configure that Usb Device
- //
- Status = PeiConfigureUsbDevice (
- PeiServices,
- PeiUsbDevice,
- Index,
- &CurrentAddress
- );
-
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- DEBUG ((DEBUG_INFO, "PeiUsbEnumeration: PeiConfigureUsbDevice Success\n"));
-
- Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList);
-
- if (PeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {
- PeiUsbDevice->IsHub = 0x1;
-
- Status = PeiDoHubConfig (PeiServices, PeiUsbDevice);
- if (EFI_ERROR (Status)) {
- return Status;
+ if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_SUPER_SPEED)) {
+ PeiUsbDevice->MaxPacketSize0 = 512;
+ } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_HIGH_SPEED)) {
+ PeiUsbDevice->MaxPacketSize0 = 64;
+ } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_LOW_SPEED)) {
+ PeiUsbDevice->MaxPacketSize0 = 8;
+ } else {
+ PeiUsbDevice->MaxPacketSize0 = 8;
}
- PeiHubEnumeration (PeiServices, PeiUsbDevice, &CurrentAddress);
- }
-
- for (InterfaceIndex = 1; InterfaceIndex < PeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) {
//
- // Begin to deal with the new device
+ // Configure that Usb Device
//
- MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
- Status = PeiServicesAllocatePages (
- EfiBootServicesCode,
- MemPages,
- &AllocateAddress
- );
+ Status = PeiConfigureUsbDevice (
+ PeiServices,
+ PeiUsbDevice,
+ Index,
+ &CurrentAddress
+ );
+
if (EFI_ERROR (Status)) {
- return EFI_OUT_OF_RESOURCES;
+ continue;
}
- CopyMem ((VOID *)(UINTN)AllocateAddress, PeiUsbDevice, sizeof (PEI_USB_DEVICE));
- PeiUsbDevice = (PEI_USB_DEVICE *)((UINTN)AllocateAddress);
- PeiUsbDevice->AllocateAddress = (UINTN)AllocateAddress;
- PeiUsbDevice->UsbIoPpiList.Ppi = &PeiUsbDevice->UsbIoPpi;
- PeiUsbDevice->InterfaceDesc = PeiUsbDevice->InterfaceDescList[InterfaceIndex];
- for (EndpointIndex = 0; EndpointIndex < PeiUsbDevice->InterfaceDesc->NumEndpoints; EndpointIndex++) {
- PeiUsbDevice->EndpointDesc[EndpointIndex] = PeiUsbDevice->EndpointDescList[InterfaceIndex][EndpointIndex];
- }
+ DEBUG ((DEBUG_INFO, "PeiUsbEnumeration: PeiConfigureUsbDevice Success\n"));
Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList);
@@ -635,11 +607,48 @@ PeiUsbEnumeration (
PeiHubEnumeration (PeiServices, PeiUsbDevice, &CurrentAddress);
}
+
+ for (InterfaceIndex = 1; InterfaceIndex < PeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) {
+ //
+ // Begin to deal with the new device
+ //
+ MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
+ Status = PeiServicesAllocatePages (
+ EfiBootServicesCode,
+ MemPages,
+ &AllocateAddress
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem ((VOID *)(UINTN)AllocateAddress, PeiUsbDevice, sizeof (PEI_USB_DEVICE));
+ PeiUsbDevice = (PEI_USB_DEVICE *)((UINTN)AllocateAddress);
+ PeiUsbDevice->AllocateAddress = (UINTN)AllocateAddress;
+ PeiUsbDevice->UsbIoPpiList.Ppi = &PeiUsbDevice->UsbIoPpi;
+ PeiUsbDevice->InterfaceDesc = PeiUsbDevice->InterfaceDescList[InterfaceIndex];
+ for (EndpointIndex = 0; EndpointIndex < PeiUsbDevice->InterfaceDesc->NumEndpoints; EndpointIndex++) {
+ PeiUsbDevice->EndpointDesc[EndpointIndex] = PeiUsbDevice->EndpointDescList[InterfaceIndex][EndpointIndex];
+ }
+
+ Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList);
+
+ if (PeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {
+ PeiUsbDevice->IsHub = 0x1;
+
+ Status = PeiDoHubConfig (PeiServices, PeiUsbDevice);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PeiHubEnumeration (PeiServices, PeiUsbDevice, &CurrentAddress);
+ }
+ }
+ } else {
+ //
+ // Disconnect change happen, currently we don't support
+ //
}
- } else {
- //
- // Disconnect change happen, currently we don't support
- //
}
}
}