diff options
Diffstat (limited to 'MdeModulePkg/Bus/Usb')
-rw-r--r-- | MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h | 1 | ||||
-rw-r--r-- | MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c | 76 | ||||
-rw-r--r-- | MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.h | 2 | ||||
-rw-r--r-- | MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c | 4 |
4 files changed, 64 insertions, 19 deletions
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h index d503a27..9ede83a 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h @@ -198,6 +198,7 @@ struct _USB_DEVICE { USB_INTERFACE *ParentIf;
UINT8 ParentPort; // Start at 0
UINT8 Tier;
+ BOOLEAN DisconnectFail;
};
//
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c index 79635cb..430f5aa 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c @@ -450,7 +450,7 @@ UsbSelectConfig ( @param UsbIf The interface to disconnect driver from.
**/
-VOID
+EFI_STATUS
UsbDisconnectDriver (
IN USB_INTERFACE *UsbIf
)
@@ -462,8 +462,9 @@ UsbDisconnectDriver ( // Release the hub if it's a hub controller, otherwise
// disconnect the driver if it is managed by other drivers.
//
+ Status = EFI_SUCCESS;
if (UsbIf->IsHub) {
- UsbIf->HubApi->Release (UsbIf);
+ Status = UsbIf->HubApi->Release (UsbIf);
} else if (UsbIf->IsManaged) {
//
@@ -479,13 +480,17 @@ UsbDisconnectDriver ( gBS->RestoreTPL (TPL_CALLBACK);
Status = gBS->DisconnectController (UsbIf->Handle, NULL, NULL);
- UsbIf->IsManaged = FALSE;
-
+ if (!EFI_ERROR (Status)) {
+ UsbIf->IsManaged = FALSE;
+ }
+
DEBUG (( EFI_D_INFO, "UsbDisconnectDriver: TPL after disconnect is %d, %d\n", (UINT32)UsbGetCurrentTpl(), Status));
ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);
gBS->RaiseTPL (OldTpl);
}
+
+ return Status;
}
@@ -495,17 +500,20 @@ UsbDisconnectDriver ( @param Device The USB device to remove configuration from.
**/
-VOID
+EFI_STATUS
UsbRemoveConfig (
IN USB_DEVICE *Device
)
{
USB_INTERFACE *UsbIf;
UINTN Index;
+ EFI_STATUS Status;
+ EFI_STATUS ReturnStatus;
//
// Remove each interface of the device
//
+ ReturnStatus = EFI_SUCCESS;
for (Index = 0; Index < Device->NumOfInterface; Index++) {
ASSERT (Index < USB_MAX_INTERFACE);
UsbIf = Device->Interfaces[Index];
@@ -514,13 +522,17 @@ UsbRemoveConfig ( continue;
}
- UsbDisconnectDriver (UsbIf);
- UsbFreeInterface (UsbIf);
- Device->Interfaces[Index] = NULL;
+ Status = UsbDisconnectDriver (UsbIf);
+ if (!EFI_ERROR (Status)) {
+ UsbFreeInterface (UsbIf);
+ Device->Interfaces[Index] = NULL;
+ } else {
+ ReturnStatus = Status;
+ }
}
Device->ActiveConfig = NULL;
- Device->NumOfInterface = 0;
+ return ReturnStatus;
}
@@ -540,6 +552,7 @@ UsbRemoveDevice ( USB_BUS *Bus;
USB_DEVICE *Child;
EFI_STATUS Status;
+ EFI_STATUS ReturnStatus;
UINTN Index;
Bus = Device->Bus;
@@ -548,6 +561,7 @@ UsbRemoveDevice ( // Remove all the devices on its downstream ports. Search from devices[1].
// Devices[0] is the root hub.
//
+ ReturnStatus = EFI_SUCCESS;
for (Index = 1; Index < Bus->MaxDevices; Index++) {
Child = Bus->Devices[Index];
@@ -557,21 +571,31 @@ UsbRemoveDevice ( Status = UsbRemoveDevice (Child);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "UsbRemoveDevice: failed to remove child, ignore error\n"));
+ if (!EFI_ERROR (Status)) {
Bus->Devices[Index] = NULL;
+ } else {
+ Bus->Devices[Index]->DisconnectFail = TRUE;
+ ReturnStatus = Status;
+ DEBUG ((EFI_D_INFO, "UsbRemoveDevice: failed to remove child %p at parent %p\n", Child, Device));
}
}
- UsbRemoveConfig (Device);
+ if (EFI_ERROR (ReturnStatus)) {
+ return ReturnStatus;
+ }
- DEBUG (( EFI_D_INFO, "UsbRemoveDevice: device %d removed\n", Device->Address));
+ Status = UsbRemoveConfig (Device);
- ASSERT (Device->Address < Bus->MaxDevices);
- Bus->Devices[Device->Address] = NULL;
- UsbFreeDevice (Device);
+ if (!EFI_ERROR (Status)) {
+ DEBUG (( EFI_D_INFO, "UsbRemoveDevice: device %d removed\n", Device->Address));
- return EFI_SUCCESS;
+ ASSERT (Device->Address < Bus->MaxDevices);
+ Bus->Devices[Device->Address] = NULL;
+ UsbFreeDevice (Device);
+ } else {
+ Bus->Devices[Device->Address]->DisconnectFail = TRUE;
+ }
+ return Status;
}
@@ -968,11 +992,20 @@ UsbHubEnumeration ( UINT8 Byte;
UINT8 Bit;
UINT8 Index;
-
+ USB_DEVICE *Child;
+
ASSERT (Context != NULL);
HubIf = (USB_INTERFACE *) Context;
+ for (Index = 0; Index < HubIf->NumOfPort; Index++) {
+ Child = UsbFindChild (HubIf, Index);
+ if ((Child != NULL) && (Child->DisconnectFail == TRUE)) {
+ DEBUG (( EFI_D_INFO, "UsbEnumeratePort: The device disconnect fails at port %d from hub %p, try again\n", Index, HubIf));
+ UsbRemoveDevice (Child);
+ }
+ }
+
if (HubIf->ChangeMap == NULL) {
return ;
}
@@ -1015,10 +1048,17 @@ UsbRootHubEnumeration ( {
USB_INTERFACE *RootHub;
UINT8 Index;
+ USB_DEVICE *Child;
RootHub = (USB_INTERFACE *) Context;
for (Index = 0; Index < RootHub->NumOfPort; Index++) {
+ Child = UsbFindChild (RootHub, Index);
+ if ((Child != NULL) && (Child->DisconnectFail == TRUE)) {
+ DEBUG (( EFI_D_INFO, "UsbEnumeratePort: The device disconnect fails at port %d from root hub %p, try again\n", Index, RootHub));
+ UsbRemoveDevice (Child);
+ }
+
UsbEnumeratePort (RootHub, Index);
}
}
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.h b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.h index 288d38f..ef7d440 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.h +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.h @@ -151,7 +151,7 @@ UsbSelectConfig ( @return None.
**/
-VOID
+EFI_STATUS
UsbRemoveConfig (
IN USB_DEVICE *Device
);
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c index 9e5299c..2fcacad 100644 --- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c +++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c @@ -988,6 +988,10 @@ UsbHubResetPort ( for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {
Status = UsbHubGetPortStatus (HubIf, Port, &PortState);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
if (!EFI_ERROR (Status) &&
USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_RESET)) {
gBS->Stall (USB_SET_PORT_RECOVERY_STALL);
|