Revision: 14819
          http://sourceforge.net/p/edk2/code/14819
Author:   erictian
Date:     2013-10-30 03:49:24 +0000 (Wed, 30 Oct 2013)
Log Message:
-----------
MdeMdeModulePkg/UsbBusDxe: If DisconnectController() returns an error the USB 
Bus Driver would retry the DisconnectController() from a timer event until it 
succeeds

Signed-off-by: Feng Tian <[email protected]>
Reviewed-by: Ruiyu Ni <[email protected]>

Modified Paths:
--------------
    trunk/edk2/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h
    trunk/edk2/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
    trunk/edk2/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.h
    trunk/edk2/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c

Modified: trunk/edk2/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h  2013-10-30 03:10:30 UTC 
(rev 14818)
+++ trunk/edk2/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h  2013-10-30 03:49:24 UTC 
(rev 14819)
@@ -198,6 +198,7 @@
   USB_INTERFACE             *ParentIf;
   UINT8                     ParentPort;       // Start at 0
   UINT8                     Tier;
+  BOOLEAN                   DisconnectFail;
 };
 
 //

Modified: trunk/edk2/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c       2013-10-30 
03:10:30 UTC (rev 14818)
+++ trunk/edk2/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c       2013-10-30 
03:49:24 UTC (rev 14819)
@@ -450,7 +450,7 @@
   @param  UsbIf                 The interface to disconnect driver from.
 
 **/
-VOID
+EFI_STATUS
 UsbDisconnectDriver (
   IN USB_INTERFACE        *UsbIf
   )
@@ -462,8 +462,9 @@
   // 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 @@
     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 @@
   @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 @@
       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 @@
   USB_BUS                 *Bus;
   USB_DEVICE              *Child;
   EFI_STATUS              Status;
+  EFI_STATUS              ReturnStatus;
   UINTN                   Index;
 
   Bus = Device->Bus;
@@ -548,6 +561,7 @@
   // 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 @@
 
     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 @@
   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 @@
 {
   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);
   }
 }

Modified: trunk/edk2/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.h
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.h       2013-10-30 
03:10:30 UTC (rev 14818)
+++ trunk/edk2/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.h       2013-10-30 
03:49:24 UTC (rev 14819)
@@ -151,7 +151,7 @@
   @return None.
 
 **/
-VOID
+EFI_STATUS
 UsbRemoveConfig (
   IN USB_DEVICE           *Device
   );

Modified: trunk/edk2/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c
===================================================================
--- trunk/edk2/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c  2013-10-30 03:10:30 UTC 
(rev 14818)
+++ trunk/edk2/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c  2013-10-30 03:49:24 UTC 
(rev 14819)
@@ -988,6 +988,10 @@
   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);

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
Android is increasing in popularity, but the open development platform that
developers love is also attractive to malware creators. Download this white
paper to learn more about secure code signing practices that can help keep
Android apps secure.
http://pubads.g.doubleclick.net/gampad/clk?id=65839951&iu=/4140/ostg.clktrk
_______________________________________________
edk2-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-commits

Reply via email to