From nobody Mon Apr 29 10:07:12 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+79950+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+79950+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1630322715; cv=none; d=zohomail.com; s=zohoarc; b=d5uQrVnjZ1Q2MZ/lShX7bjsHo/K5V2CWtW4j74TKmMqUvbOxMKHvEDcznm7y4PwSMZqN0uJTCEvb04iobKmXAJfD4T+HdibrH44rdYjUh3RTqdI+OrmMxzmukCIqmTalv7gKVeHn3cN9FR0EEXZ7CQdwjfNoyjAFvSJsNxrIwgU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1630322715; h=Content-Type:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=XmpxGvo1tTFHG0H/UkqucxX78qvu0baazgCe3zSeRts=; b=JIhV2V9rRw+uTpTqYpc8wRV4SNDj8iZ0SSKrqBpekCIYmAJ9v34iZ44xR4jzD85iw2jTGTIUZujE/JqF2KY0iV3U1P26PF7BuqmGpFPfcTiq80sfydybg4XLBwQIOaAAzwHrK4YFIdvafiCx0TtwM+XvXlgEM16KG6UegLyKrpk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+79950+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1630322715301475.1862633493555; Mon, 30 Aug 2021 04:25:15 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id h9pkYY1788612xgqgn5rMIMj; Mon, 30 Aug 2021 04:25:14 -0700 X-Received: from szxga03-in.huawei.com (szxga03-in.huawei.com [45.249.212.189]) by mx.groups.io with SMTP id smtpd.web08.15686.1630322713595643910 for ; Mon, 30 Aug 2021 04:25:14 -0700 X-Received: from dggemv704-chm.china.huawei.com (unknown [172.30.72.53]) by szxga03-in.huawei.com (SkyGuard) with ESMTP id 4GynzN3vpXz8CXL; Mon, 30 Aug 2021 19:24:48 +0800 (CST) X-Received: from dggpemm000003.china.huawei.com (7.185.36.128) by dggemv704-chm.china.huawei.com (10.3.19.47) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2176.2; Mon, 30 Aug 2021 19:25:08 +0800 X-Received: from HGH1000039998.huawei.com (10.184.68.188) by dggpemm000003.china.huawei.com (7.185.36.128) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.8; Mon, 30 Aug 2021 19:25:08 +0800 From: "wenyi,xie via groups.io" To: , , , , CC: , , Subject: [edk2-devel] [PATCH EDK2 v1 1/1] MdeModulePkg/XhciDxe: Decreasing stuck time Date: Mon, 30 Aug 2021 19:20:01 +0800 Message-ID: <1630322401-26962-2-git-send-email-xiewenyi2@huawei.com> In-Reply-To: <1630322401-26962-1-git-send-email-xiewenyi2@huawei.com> References: <1630322401-26962-1-git-send-email-xiewenyi2@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.184.68.188] X-ClientProxiedBy: dggems706-chm.china.huawei.com (10.3.19.183) To dggpemm000003.china.huawei.com (7.185.36.128) X-CFilter-Loop: Reflected Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,xiewenyi2@huawei.com X-Gm-Message-State: W0rSOhFs2YRZt4FAq6TNVk9kx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1630322714; bh=K6PO3ZOzuEfmC/Qc594J5B8Atftm8zP75abHIL1bCFA=; h=CC:Content-Type:Date:From:Reply-To:Subject:To; b=GBaiRnLVLIuwHNOAEvxzxiV1Is/nFbF6RHJKD5KsN/qKMkr888gHJOjeRI7N+MMoBPz TIqa//dOYo802u89R3KUw6al03sxsSFraFFGxTRx1/x5LGHWnrvAOjKlYyGjlhRhnCoea mEc03YuPPENUTPzn2j4zOG1MnxzPipYdcK0= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1630322716975100009 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3571 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 Cc: Hao A Wu Cc: Ray Ni Cc: Liming Gao Signed-off-by: Wenyi Xie --- 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/Xhc= iDxe/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; }; =20 struct _USB_XHCI_INSTANCE { @@ -508,6 +512,48 @@ XhcControlTransfer ( OUT UINT32 *TransferResult ); =20 +/** + 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 tr= ansfer + endpoint is capable of sending or receivin= g. + @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 millisec= ond. + @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 t= he port or not + + @retval EFI_SUCCESS Transfer was completed successfully. + @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resourc= es. + @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. =20 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.
+SPDX-License-Identifier: BSD-2-Clause-Patent +**/ +#ifndef _EFI_XHCI_BUS_H_ +#define _EFI_XHCI_BUS_H_ + +#include +#include +#include +#include + +#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 bu= s, only those wanted + // usb child device will be recursively connected. + // + // WantedUsbIoDPList tracks the Usb child devices which user want to rec= ursivly fully connecte, + // every wanted child device is stored in a item of the WantedUsbIoDPLis= t, 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/Xhc= iDxe/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 =3D 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 tr= ansfer + endpoint is capable of sending or receivin= g. + @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 millisec= ond. + @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 t= he port or not + + @retval EFI_SUCCESS Transfer was completed successfully. + @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resourc= es. + @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; } =20 + if (Xhc->UsbDevContext[SlotId].DisConnect =3D=3D 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 ( } } =20 - MapSize =3D sizeof (mUsbHubClearPortChangeMap) / sizeof (USB_CLEAR_POR= T_MAP); - - for (Index =3D 0; Index < MapSize; Index++) { - if (XHC_BIT_IS_SET (State, mUsbHubClearPortChangeMap[Index].HwState)= ) { - ZeroMem (&ClearPortRequest, sizeof (EFI_USB_DEVICE_REQUEST)); - ClearPortRequest.RequestType =3D USB_REQUEST_TYPE (EfiUsbNoData, = USB_REQ_TYPE_CLASS, USB_TARGET_OTHER); - ClearPortRequest.Request =3D (UINT8) USB_REQ_CLEAR_FEATURE; - ClearPortRequest.Value =3D mUsbHubClearPortChangeMap[Index]= .Selector; - ClearPortRequest.Index =3D Request->Index; - ClearPortRequest.Length =3D 0; - - XhcControlTransfer ( - This, - DeviceAddress, - DeviceSpeed, - MaximumPacketLength, - &ClearPortRequest, - EfiUsbNoData, - NULL, - &Len, - Timeout, - Translator, - TransferResult - ); + if (IsClear) { + MapSize =3D sizeof (mUsbHubClearPortChangeMap) / sizeof (USB_CLEAR_P= ORT_MAP); + for (Index =3D 0; Index < MapSize; Index++) { + if (XHC_BIT_IS_SET (State, mUsbHubClearPortChangeMap[Index].HwStat= e)) { + ZeroMem (&ClearPortRequest, sizeof (EFI_USB_DEVICE_REQUEST)); + ClearPortRequest.RequestType =3D USB_REQUEST_TYPE (EfiUsbNoData= , USB_REQ_TYPE_CLASS, USB_TARGET_OTHER); + ClearPortRequest.Request =3D (UINT8) USB_REQ_CLEAR_FEATURE; + ClearPortRequest.Value =3D mUsbHubClearPortChangeMap[Inde= x].Selector; + ClearPortRequest.Index =3D Request->Index; + ClearPortRequest.Length =3D 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 =3D *(UINT32*)&PortStatus; } =20 @@ -1261,7 +1324,10 @@ XhcBulkTransfer ( if (SlotId =3D=3D 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 =3D=3D 0) { goto ON_EXIT; } + if (Xhc->UsbDevContext[SlotId].DisConnect) { + DEBUG ((EFI_D_ERROR, "XhcAsyncInterruptTransfer: UsbDevContext %u disc= onnect\n", SlotId)); + goto ON_EXIT; + } =20 Urb =3D XhciInsertAsyncIntTransfer ( Xhc, @@ -1519,6 +1589,10 @@ XhcSyncInterruptTransfer ( if (SlotId =3D=3D 0) { goto ON_EXIT; } + if (Xhc->UsbDevContext[SlotId].DisConnect) { + DEBUG ((EFI_D_ERROR, "XhcSyncInterruptTransfer: UsbDevContext %u disco= nnect\n", SlotId)); + goto ON_EXIT; + } =20 Status =3D XhcTransfer ( Xhc, diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c b/MdeModulePkg/Bus/Pc= i/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 **/ =20 #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 =3D HubIf->Device; + PortNum =3D HubIf->NumOfPort; + Len =3D 4; + // DevReq + DevReq.RequestType =3D USB_REQUEST_TYPE (EfiUsbDataIn, + USB_REQ_TYPE_CLASS, USB_HUB_TARGET_PORT); + DevReq.Request =3D (UINT8) USB_HUB_REQ_GET_STATUS; + DevReq.Value =3D 0; + DevReq.Index =3D Port; + DevReq.Length =3D 4; + // + //controlTransfer to get hub port status + // + Status =3D 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 =3D %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 =3D 0; + UINT8 Port[MAX_DEVICE_NUM]; + UINT32 PortDevice[MAX_DEVICE_NUM]; + EFI_STATUS Status; + Ep =3D Urb->Ep; + // + //Find hub device Context Index + // + for (Index =3D 0; Index < MAX_DEVICE_NUM; Index++) { + if (Xhc->UsbDevContext[Index + 1].BusDevAddr =3D=3D Ep.BusAddr) { + HubIndex =3D Index + 1; + break; + } + } + if (Index =3D=3D USB_MAX_DEVICES) { + return; + } + //Find port device Index and Port + for (Index =3D 0; Index < MAX_DEVICE_NUM; Index++) { + if (CompareMem(&Xhc->UsbDevContext[Index + 1].ParentRouteString, + &Xhc->UsbDevContext[HubIndex].RouteString, + sizeof(Xhc->UsbDevContext[HubIndex].RouteString)) =3D= =3D 0) { + // Device index in Xhc Devcontext + PortDevice[PortIndex] =3D Index + 1; + // Device port in hub + Port[PortIndex] =3D Xhc->UsbDevContext[Index + 1].RouteString.Route.= RouteString >> + (4 * (Xhc->UsbDevContext[Index + 1].ParentRouteStri= ng.Route.TierNum - 1)); + PortIndex ++; + } + } + if (PortIndex =3D=3D 0) { + return; + } + // + // If Device has child device, the device is hud + // + HubIf =3D (USB_INTERFACE *) Urb->Context; + for (Index =3D 0; Index < PortIndex; Index ++) { + Status =3D XhcGetHubPortStatus(HubIf, &PortState, Port[Index]); + if (EFI_ERROR(Status)) { + continue; + } + if ((PortState.PortStatus & USB_PORT_STAT_CONNECTION) =3D=3D 0 && + (PortState.PortChangeStatus & USB_PORT_STAT_C_CONNECTION) =3D=3D = 1) { + Xhc->UsbDevContext[PortDevice[Index]].DisConnect =3D 1; + } + } +} =20 /** 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 =3D gBS->RaiseTPL (XHC_TPL); } =20 @@ -2152,6 +2261,7 @@ XhcInitializeDeviceSlot ( Xhc->UsbDevContext[SlotId].SlotId =3D SlotId; Xhc->UsbDevContext[SlotId].RouteString.Dword =3D RouteChart.Dword; Xhc->UsbDevContext[SlotId].ParentRouteString.Dword =3D ParentRouteChart.= Dword; + Xhc->UsbDevContext[SlotId].DisConnect =3D 0; =20 // // 4.3.3 Device Slot Initialization @@ -2365,6 +2475,7 @@ XhcInitializeDeviceSlot64 ( Xhc->UsbDevContext[SlotId].SlotId =3D SlotId; Xhc->UsbDevContext[SlotId].RouteString.Dword =3D RouteChart.Dword; Xhc->UsbDevContext[SlotId].ParentRouteString.Dword =3D ParentRouteChart.= Dword; + Xhc->UsbDevContext[SlotId].DisConnect =3D 0; =20 // // 4.3.3 Device Slot Initialization --=20 2.20.1.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- 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/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-