[edk2-devel] [PATCH EDK2 v1 1/1] MdeModulePkg/XhciDxe: Decreasing stuck time

wenyi,xie via groups.io xiewenyi2=huawei.com at groups.io
Mon Aug 30 11:20:01 UTC 2021


BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3571

After entering setup browser, if frequently plug and unplug usb
device, the browser may be stuck for a few minutes, and user
can not do any operation during that time.
The root cause is that usually it needs 0.5s to create connection,
and this process will be possibly interrupted when frequently
plug and unplug the usb device. Then USBMassStorageDxe and
XhciDxe will retry and it made the browser stucked.

To decrease the stuck time, add a new flag DisConnect to
struct UsbDevContext, if the device is not connected, no need to
send XhcBulkTransfer, XhcAsyncInterruptTransfer or
XhcSyncInterruptTransfer.

Cc: Jian J Wang <jian.j.wang at intel.com>
Cc: Hao A Wu <hao.a.wu at intel.com>
Cc: Ray Ni <ray.ni at intel.com>
Cc: Liming Gao <gaoliming at byosoft.com.cn>
Signed-off-by: Wenyi Xie <xiewenyi2 at huawei.com>
---
 MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h      |  46 ++++
 MdeModulePkg/Bus/Pci/XhciDxe/XhciBus.h   | 229 ++++++++++++++++++++
 MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c      | 130 ++++++++---
 MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c | 111 ++++++++++
 4 files changed, 488 insertions(+), 28 deletions(-)

diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h
index 3285eb8798c0..43552cb7d470 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h
@@ -191,6 +191,10 @@ struct _USB_DEV_CONTEXT {
   // Every interface has an active AlternateSetting.
   //
   UINT8                     *ActiveAlternateSetting;
+  //
+  // Whether the usb device status is connected or not.
+  //
+  UINT8                     DisConnect;
 };
 
 struct _USB_XHCI_INSTANCE {
@@ -508,6 +512,48 @@ XhcControlTransfer (
   OUT    UINT32                              *TransferResult
   );
 
+/**
+  Submits control transfer to a target USB device.
+
+  @param  This                  This EFI_USB2_HC_PROTOCOL instance.
+  @param  DeviceAddress         The target device address.
+  @param  DeviceSpeed           Target device speed.
+  @param  MaximumPacketLength   Maximum packet size the default control transfer
+                                endpoint is capable of sending or receiving.
+  @param  Request               USB device request to send.
+  @param  TransferDirection     Specifies the data direction for the data stage
+  @param  Data                  Data buffer to be transmitted or received from USB
+                                device.
+  @param  DataLength            The size (in bytes) of the data buffer.
+  @param  Timeout               Indicates the maximum timeout, in millisecond.
+  @param  Translator            Transaction translator to be used by this device.
+  @param  TransferResult        Return the result of this control transfer.
+  @param  IsClear               The flag used to determine whether clear the port or not
+
+  @retval EFI_SUCCESS           Transfer was completed successfully.
+  @retval EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resources.
+  @retval EFI_INVALID_PARAMETER Some parameters are invalid.
+  @retval EFI_TIMEOUT           Transfer failed due to timeout.
+  @retval EFI_DEVICE_ERROR      Transfer failed due to host controller or device error.
+
+**/
+EFI_STATUS
+EFIAPI
+InnerXhcControlTransfer (
+  IN     EFI_USB2_HC_PROTOCOL                *This,
+  IN     UINT8                               DeviceAddress,
+  IN     UINT8                               DeviceSpeed,
+  IN     UINTN                               MaximumPacketLength,
+  IN     EFI_USB_DEVICE_REQUEST              *Request,
+  IN     EFI_USB_DATA_DIRECTION              TransferDirection,
+  IN OUT VOID                                *Data,
+  IN OUT UINTN                               *DataLength,
+  IN     UINTN                               Timeout,
+  IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
+  OUT    UINT32                              *TransferResult,
+  IN     UINT8                               IsClear
+  );
+
 /**
   Submits bulk transfer to a bulk endpoint of a USB device.
 
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciBus.h b/MdeModulePkg/Bus/Pci/XhciDxe/XhciBus.h
new file mode 100644
index 000000000000..8b2591b23bd7
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciBus.h
@@ -0,0 +1,229 @@
+/** @file
+  Only used by Xhc controller to avoid U disk plug-in/out delay
+Copyright (c) 2019 - 2021, Huawei Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#ifndef _EFI_XHCI_BUS_H_
+#define _EFI_XHCI_BUS_H_
+
+#include <Uefi.h>
+#include <Protocol/UsbIo.h>
+#include <Protocol/Usb2HostController.h>
+#include <Protocol/UsbHostController.h>
+
+#define USB_MAX_LANG_ID                16
+#define USB_MAX_INTERFACE              16
+#define USB_MAX_DEVICES                255
+#define USB_MAX_INTERFACE_SETTING      256
+//
+// Hub class control transfer target
+//
+#define USB_HUB_TARGET_PORT                3
+#define USB_HUB_REQ_GET_STATUS             0
+#define USB_GENERAL_DEVICE_REQUEST_TIMEOUT 500
+
+typedef struct _USB_DEVICE     USB_DEVICE;
+typedef struct _USB_INTERFACE  USB_INTERFACE;
+typedef struct _USB_BUS        USB_BUS;
+typedef struct _USB_HUB_API    USB_HUB_API;
+typedef struct {
+  EFI_USB_ENDPOINT_DESCRIPTOR   Desc;
+  UINT8                         Toggle;
+} USB_ENDPOINT_DESC;
+
+typedef struct {
+  EFI_USB_INTERFACE_DESCRIPTOR  Desc;
+  USB_ENDPOINT_DESC             **Endpoints;
+} USB_INTERFACE_SETTING;
+
+typedef struct {
+  USB_INTERFACE_SETTING*        Settings[USB_MAX_INTERFACE_SETTING];
+  UINTN                         NumOfSetting;
+  UINTN                         ActiveIndex;  // Index of active setting
+} USB_INTERFACE_DESC;
+
+typedef struct {
+  EFI_USB_CONFIG_DESCRIPTOR     Desc;
+  USB_INTERFACE_DESC            **Interfaces;
+} USB_CONFIG_DESC;
+
+typedef struct {
+  EFI_USB_DEVICE_DESCRIPTOR     Desc;
+  USB_CONFIG_DESC               **Configs;
+} USB_DEVICE_DESC;
+
+//
+// Stands for the real USB device. Each device may
+// has several seperately working interfaces.
+//
+struct _USB_DEVICE {
+  USB_BUS                   *Bus;
+  //
+  // Configuration information
+  //
+  UINT8                     Speed;
+  UINT8                     Address;
+  UINT32                    MaxPacket0;
+  //
+  // The device's descriptors and its configuration
+  //
+  USB_DEVICE_DESC           *DevDesc;
+  USB_CONFIG_DESC           *ActiveConfig;
+  UINT16                    LangId [USB_MAX_LANG_ID];
+  UINT16                    TotalLangId;
+  UINT8                     NumOfInterface;
+  USB_INTERFACE             *Interfaces [USB_MAX_INTERFACE];
+  //
+  // Parent child relationship
+  //
+  EFI_USB2_HC_TRANSACTION_TRANSLATOR Translator;
+  UINT8                     ParentAddr;
+  USB_INTERFACE             *ParentIf;
+  UINT8                     ParentPort;       // Start at 0
+  UINT8                     Tier;
+  BOOLEAN                   DisconnectFail;
+};
+
+//
+// Stands for different functions of USB device
+//
+struct _USB_INTERFACE {
+  UINTN                     Signature;
+  USB_DEVICE                *Device;
+  USB_INTERFACE_DESC        *IfDesc;
+  USB_INTERFACE_SETTING     *IfSetting;
+  //
+  // Handles and protocols
+  //
+  EFI_HANDLE                Handle;
+  EFI_USB_IO_PROTOCOL       UsbIo;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  BOOLEAN                   IsManaged;
+  //
+  // Hub device special data
+  //
+  BOOLEAN                   IsHub;
+  USB_HUB_API               *HubApi;
+  UINT8                     NumOfPort;
+  EFI_EVENT                 HubNotify;
+  //
+  // Data used only by normal hub devices
+  //
+  USB_ENDPOINT_DESC         *HubEp;
+  UINT8                     *ChangeMap;
+  //
+  // Data used only by root hub to hand over device to
+  // companion UHCI driver if low/full speed devices are
+  // connected to EHCI.
+  //
+  UINT8                     MaxSpeed;
+};
+
+typedef struct _EFI_USB_BUS_PROTOCOL {
+  UINT64                    Reserved;
+} EFI_USB_BUS_PROTOCOL;
+
+//
+// Stands for the current USB Bus
+//
+struct _USB_BUS {
+  UINTN                     Signature;
+  EFI_USB_BUS_PROTOCOL      BusId;
+  //
+  // Managed USB host controller
+  //
+  EFI_HANDLE                HostHandle;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  EFI_USB2_HC_PROTOCOL      *Usb2Hc;
+  EFI_USB_HC_PROTOCOL       *UsbHc;
+  //
+  // Recorded the max supported usb devices.
+  // XHCI can support up to 255 devices.
+  // EHCI/UHCI/OHCI supports up to 127 devices.
+  //
+  UINT32                    MaxDevices;
+  //
+  // An array of device that is on the bus. Devices[0] is
+  // for root hub. Device with address i is at Devices[i].
+  //
+  USB_DEVICE                *Devices[256];
+  //
+  // USB Bus driver need to control the recursive connect policy of the bus, only those wanted
+  // usb child device will be recursively connected.
+  //
+  // WantedUsbIoDPList tracks the Usb child devices which user want to recursivly fully connecte,
+  // every wanted child device is stored in a item of the WantedUsbIoDPList, whose structrure is
+  // DEVICE_PATH_LIST_ITEM
+  //
+  LIST_ENTRY                WantedUsbIoDPList;
+};
+
+typedef
+EFI_STATUS
+(*USB_HUB_INIT) (
+  IN USB_INTERFACE        *UsbIf
+  );
+
+//
+// Get the port status. This function is required to
+// ACK the port change bits although it will return
+// the port changes in PortState. Bus enumeration code
+// doesn't need to ACK the port change bits.
+//
+typedef
+EFI_STATUS
+(*USB_HUB_GET_PORT_STATUS) (
+  IN  USB_INTERFACE       *UsbIf,
+  IN  UINT8               Port,
+  OUT EFI_USB_PORT_STATUS *PortState
+  );
+
+typedef
+VOID
+(*USB_HUB_CLEAR_PORT_CHANGE) (
+  IN USB_INTERFACE        *HubIf,
+  IN UINT8                Port
+  );
+
+typedef
+EFI_STATUS
+(*USB_HUB_SET_PORT_FEATURE) (
+  IN USB_INTERFACE        *UsbIf,
+  IN UINT8                Port,
+  IN EFI_USB_PORT_FEATURE Feature
+  );
+
+typedef
+EFI_STATUS
+(*USB_HUB_CLEAR_PORT_FEATURE) (
+  IN USB_INTERFACE        *UsbIf,
+  IN UINT8                Port,
+  IN EFI_USB_PORT_FEATURE Feature
+  );
+
+typedef
+EFI_STATUS
+(*USB_HUB_RESET_PORT) (
+  IN USB_INTERFACE        *UsbIf,
+  IN UINT8                Port
+  );
+
+typedef
+EFI_STATUS
+(*USB_HUB_RELEASE) (
+  IN USB_INTERFACE        *UsbIf
+  );
+
+//
+// USB Hub Api
+//
+struct _USB_HUB_API{
+  USB_HUB_INIT                Init;
+  USB_HUB_GET_PORT_STATUS     GetPortStatus;
+  USB_HUB_CLEAR_PORT_CHANGE   ClearPortChange;
+  USB_HUB_SET_PORT_FEATURE    SetPortFeature;
+  USB_HUB_CLEAR_PORT_FEATURE  ClearPortFeature;
+  USB_HUB_RESET_PORT          ResetPort;
+  USB_HUB_RELEASE             Release;
+};
+#endif
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
index 43c53bad4e4a..59421d13395c 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
@@ -849,6 +849,66 @@ XhcControlTransfer (
   IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
   OUT    UINT32                              *TransferResult
   )
+{
+  EFI_STATUS            Status;
+  Status = InnerXhcControlTransfer(
+        This,
+        DeviceAddress,
+        DeviceSpeed,
+        MaximumPacketLength,
+        Request,
+        TransferDirection,
+        Data,
+        DataLength,
+        Timeout,
+        Translator,
+        TransferResult,
+        1
+        );
+  return Status;
+}
+
+/**
+  Submits control transfer to a target USB device.
+
+  @param  This                  This EFI_USB2_HC_PROTOCOL instance.
+  @param  DeviceAddress         The target device address.
+  @param  DeviceSpeed           Target device speed.
+  @param  MaximumPacketLength   Maximum packet size the default control transfer
+                                endpoint is capable of sending or receiving.
+  @param  Request               USB device request to send.
+  @param  TransferDirection     Specifies the data direction for the data stage
+  @param  Data                  Data buffer to be transmitted or received from USB
+                                device.
+  @param  DataLength            The size (in bytes) of the data buffer.
+  @param  Timeout               Indicates the maximum timeout, in millisecond.
+  @param  Translator            Transaction translator to be used by this device.
+  @param  TransferResult        Return the result of this control transfer.
+  @param  IsClear               The flag used to determine whether clear the port or not
+
+  @retval EFI_SUCCESS           Transfer was completed successfully.
+  @retval EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resources.
+  @retval EFI_INVALID_PARAMETER Some parameters are invalid.
+  @retval EFI_TIMEOUT           Transfer failed due to timeout.
+  @retval EFI_DEVICE_ERROR      Transfer failed due to host controller or device error.
+
+**/
+EFI_STATUS
+EFIAPI
+InnerXhcControlTransfer (
+  IN     EFI_USB2_HC_PROTOCOL                *This,
+  IN     UINT8                               DeviceAddress,
+  IN     UINT8                               DeviceSpeed,
+  IN     UINTN                               MaximumPacketLength,
+  IN     EFI_USB_DEVICE_REQUEST              *Request,
+  IN     EFI_USB_DATA_DIRECTION              TransferDirection,
+  IN OUT VOID                                *Data,
+  IN OUT UINTN                               *DataLength,
+  IN     UINTN                               Timeout,
+  IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,
+  OUT    UINT32                              *TransferResult,
+  IN     UINT8                               IsClear
+  )
 {
   USB_XHCI_INSTANCE       *Xhc;
   UINT8                   Endpoint;
@@ -959,6 +1019,10 @@ XhcControlTransfer (
     goto ON_EXIT;
   }
 
+  if (Xhc->UsbDevContext[SlotId].DisConnect == 1) {
+    DEBUG ((EFI_D_ERROR, "XhcControlTransfer: ContextIndex %u disconnect\n", SlotId));
+    goto ON_EXIT;
+  }
   //
   // Create a new URB, insert it into the asynchronous
   // schedule list, then poll the execution status.
@@ -1128,35 +1192,34 @@ XhcControlTransfer (
       }
     }
 
-    MapSize = sizeof (mUsbHubClearPortChangeMap) / sizeof (USB_CLEAR_PORT_MAP);
-
-    for (Index = 0; Index < MapSize; Index++) {
-      if (XHC_BIT_IS_SET (State, mUsbHubClearPortChangeMap[Index].HwState)) {
-        ZeroMem (&ClearPortRequest, sizeof (EFI_USB_DEVICE_REQUEST));
-        ClearPortRequest.RequestType  = USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER);
-        ClearPortRequest.Request      = (UINT8) USB_REQ_CLEAR_FEATURE;
-        ClearPortRequest.Value        = mUsbHubClearPortChangeMap[Index].Selector;
-        ClearPortRequest.Index        = Request->Index;
-        ClearPortRequest.Length       = 0;
-
-        XhcControlTransfer (
-          This,
-          DeviceAddress,
-          DeviceSpeed,
-          MaximumPacketLength,
-          &ClearPortRequest,
-          EfiUsbNoData,
-          NULL,
-          &Len,
-          Timeout,
-          Translator,
-          TransferResult
-          );
+    if (IsClear) {
+      MapSize = sizeof (mUsbHubClearPortChangeMap) / sizeof (USB_CLEAR_PORT_MAP);
+      for (Index = 0; Index < MapSize; Index++) {
+        if (XHC_BIT_IS_SET (State, mUsbHubClearPortChangeMap[Index].HwState)) {
+          ZeroMem (&ClearPortRequest, sizeof (EFI_USB_DEVICE_REQUEST));
+          ClearPortRequest.RequestType  = USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_CLASS, USB_TARGET_OTHER);
+          ClearPortRequest.Request      = (UINT8) USB_REQ_CLEAR_FEATURE;
+          ClearPortRequest.Value        = mUsbHubClearPortChangeMap[Index].Selector;
+          ClearPortRequest.Index        = Request->Index;
+          ClearPortRequest.Length       = 0;
+          XhcControlTransfer (
+            This,
+            DeviceAddress,
+            DeviceSpeed,
+            MaximumPacketLength,
+            &ClearPortRequest,
+            EfiUsbNoData,
+            NULL,
+            &Len,
+            Timeout,
+            Translator,
+            TransferResult
+            );
+        }
       }
+
+      XhcPollPortStatusChange (Xhc, Xhc->UsbDevContext[SlotId].RouteString, (UINT8)Request->Index, &PortStatus);
     }
-
-    XhcPollPortStatusChange (Xhc, Xhc->UsbDevContext[SlotId].RouteString, (UINT8)Request->Index, &PortStatus);
-
     *(UINT32 *)Data = *(UINT32*)&PortStatus;
   }
 
@@ -1261,7 +1324,10 @@ XhcBulkTransfer (
   if (SlotId == 0) {
     goto ON_EXIT;
   }
-
+  if (Xhc->UsbDevContext[SlotId].DisConnect) {
+    DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: UsbDevContext %u disconnect\n", SlotId));
+    goto ON_EXIT;
+  }
   //
   // Create a new URB, insert it into the asynchronous
   // schedule list, then poll the execution status.
@@ -1405,6 +1471,10 @@ XhcAsyncInterruptTransfer (
   if (SlotId == 0) {
     goto ON_EXIT;
   }
+  if (Xhc->UsbDevContext[SlotId].DisConnect) {
+    DEBUG ((EFI_D_ERROR, "XhcAsyncInterruptTransfer: UsbDevContext %u disconnect\n", SlotId));
+    goto ON_EXIT;
+  }
 
   Urb = XhciInsertAsyncIntTransfer (
           Xhc,
@@ -1519,6 +1589,10 @@ XhcSyncInterruptTransfer (
   if (SlotId == 0) {
     goto ON_EXIT;
   }
+  if (Xhc->UsbDevContext[SlotId].DisConnect) {
+    DEBUG ((EFI_D_ERROR, "XhcSyncInterruptTransfer: UsbDevContext %u disconnect\n", SlotId));
+    goto ON_EXIT;
+  }
 
   Status = XhcTransfer (
              Xhc,
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
index 7cbc9a8502ea..6d7d67d00c18 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
@@ -9,6 +9,114 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 **/
 
 #include "Xhci.h"
+#include "XhciBus.h"
+#define MAX_DEVICE_NUM 255
+EFI_STATUS
+EFIAPI
+XhcGetHubPortStatus (
+  IN USB_INTERFACE              *HubIf,
+  IN EFI_USB_PORT_STATUS        *PortState,
+  IN UINT8                      Port
+  )
+{
+  USB_DEVICE                    *Device;
+  UINT8                         PortNum;
+  EFI_STATUS                    Status;
+  UINT32                        Result;
+  EFI_USB_DEVICE_REQUEST        DevReq;
+  UINTN                         Len;
+  Device = HubIf->Device;
+  PortNum = HubIf->NumOfPort;
+  Len = 4;
+  // DevReq
+  DevReq.RequestType = USB_REQUEST_TYPE (EfiUsbDataIn,
+                             USB_REQ_TYPE_CLASS, USB_HUB_TARGET_PORT);
+  DevReq.Request = (UINT8) USB_HUB_REQ_GET_STATUS;
+  DevReq.Value = 0;
+  DevReq.Index = Port;
+  DevReq.Length = 4;
+  //
+  //controlTransfer to get hub port status
+  //
+  Status = InnerXhcControlTransfer (
+                Device->Bus->Usb2Hc,
+                Device->Address,
+                Device->Speed,
+                Device->MaxPacket0,
+                &DevReq,
+                EfiUsbDataIn,
+                (void *) PortState,
+                &Len,
+                USB_GENERAL_DEVICE_REQUEST_TIMEOUT,
+                &Device->Translator,
+                &Result,
+                0
+                );
+  if (EFI_ERROR(Status)) {
+    DEBUG ((EFI_D_ERROR, "StoreHubPortStatus:ControlTransfer status = %r\n", Status));
+    return Status;
+  }
+  return EFI_SUCCESS;
+}
+VOID
+XhcGetHubDevice (
+  IN USB_XHCI_INSTANCE          *Xhc,
+  IN URB                        *Urb
+  )
+{
+  USB_INTERFACE                 *HubIf;
+  EFI_USB_PORT_STATUS           PortState;
+  USB_ENDPOINT                  Ep;
+  UINT8                         Index;
+  UINT32                        HubIndex;
+  UINT32                        PortIndex = 0;
+  UINT8                         Port[MAX_DEVICE_NUM];
+  UINT32                        PortDevice[MAX_DEVICE_NUM];
+  EFI_STATUS                    Status;
+  Ep = Urb->Ep;
+  //
+  //Find hub device Context Index
+  //
+  for (Index = 0; Index < MAX_DEVICE_NUM; Index++) {
+    if (Xhc->UsbDevContext[Index + 1].BusDevAddr == Ep.BusAddr) {
+      HubIndex = Index + 1;
+      break;
+    }
+  }
+  if (Index == USB_MAX_DEVICES) {
+    return;
+  }
+  //Find port device Index and Port
+  for (Index = 0; Index < MAX_DEVICE_NUM; Index++) {
+    if (CompareMem(&Xhc->UsbDevContext[Index + 1].ParentRouteString,
+                    &Xhc->UsbDevContext[HubIndex].RouteString,
+                    sizeof(Xhc->UsbDevContext[HubIndex].RouteString)) == 0) {
+      // Device index in Xhc Devcontext
+      PortDevice[PortIndex] = Index + 1;
+      // Device port in hub
+      Port[PortIndex] = Xhc->UsbDevContext[Index + 1].RouteString.Route.RouteString >>
+                       (4 * (Xhc->UsbDevContext[Index + 1].ParentRouteString.Route.TierNum - 1));
+      PortIndex ++;
+    }
+  }
+  if (PortIndex == 0) {
+    return;
+  }
+  //
+  // If Device has child device, the device is hud
+  //
+  HubIf = (USB_INTERFACE *) Urb->Context;
+  for (Index = 0; Index < PortIndex; Index ++) {
+    Status = XhcGetHubPortStatus(HubIf, &PortState, Port[Index]);
+    if (EFI_ERROR(Status)) {
+      continue;
+    }
+    if ((PortState.PortStatus & USB_PORT_STAT_CONNECTION) == 0 &&
+         (PortState.PortChangeStatus & USB_PORT_STAT_C_CONNECTION) == 1) {
+      Xhc->UsbDevContext[PortDevice[Index]].DisConnect = 1;
+    }
+  }
+}
 
 /**
   Create a command transfer TRB to support XHCI command interfaces.
@@ -1686,6 +1794,7 @@ XhcMonitorAsyncRequests (
       //
       gBS->RestoreTPL (OldTpl);
       (Urb->Callback) (ProcBuf, Urb->Completed, Urb->Context, Urb->Result);
+      XhcGetHubDevice (Xhc, Urb);
       OldTpl = gBS->RaiseTPL (XHC_TPL);
     }
 
@@ -2152,6 +2261,7 @@ XhcInitializeDeviceSlot (
   Xhc->UsbDevContext[SlotId].SlotId                  = SlotId;
   Xhc->UsbDevContext[SlotId].RouteString.Dword       = RouteChart.Dword;
   Xhc->UsbDevContext[SlotId].ParentRouteString.Dword = ParentRouteChart.Dword;
+  Xhc->UsbDevContext[SlotId].DisConnect              = 0;
 
   //
   // 4.3.3 Device Slot Initialization
@@ -2365,6 +2475,7 @@ XhcInitializeDeviceSlot64 (
   Xhc->UsbDevContext[SlotId].SlotId                  = SlotId;
   Xhc->UsbDevContext[SlotId].RouteString.Dword       = RouteChart.Dword;
   Xhc->UsbDevContext[SlotId].ParentRouteString.Dword = ParentRouteChart.Dword;
+  Xhc->UsbDevContext[SlotId].DisConnect              = 0;
 
   //
   // 4.3.3 Device Slot Initialization
-- 
2.20.1.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#79950): https://edk2.groups.io/g/devel/message/79950
Mute This Topic: https://groups.io/mt/85248417/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-





More information about the edk2-devel-archive mailing list