Hello,

Recently, we found that when we plug and remove USB3.0 devices quickly under 
UEFI Shell on LoongArch platform, 

there will be a lag of about 3~15 minutes (the keyboard and mouse do not 
reflect under Setup), which looks like the system has halted.




Here we find two possible areas that can be improved.Please take a look and 
comment.




In xhcidxe driver, XhcBulkTransfer will be called and XhcTransfer  is called 
inside. Its function is to submit a new transaction to a target USB device 

If we unplug the USB device at this time, the xhci driver will call 
RecoveryStatus =  XhcDequeueTrbFromEndpoint(Xhc, Urb); Whose function is Abort 
the transfer 

by dequeueing of the TD. is the function required?  Because the USB device is 
no longer on the USB port at this time, and the process is relatively slow, 

can we change the code of this part into the following form without using this 
function:




diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c 
b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
index 9b26e46a..d877b0f6 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
@@ -716,6 +716,7 @@ ON_EXIT:
   return Status;
 }
 
+#if 0
 /** 
   Submits a new transaction to a target USB device.
 
@@ -784,7 +785,9 @@ XhcTransfer (
     //  
     // The transfer timed out. Abort the transfer by dequeueing of the TD. 
     //  
     RecoveryStatus = XhcDequeueTrbFromEndpoint(Xhc, Urb);
     if (RecoveryStatus == EFI_ALREADY_STARTED) {
       //
       // The URB is finished just before stopping endpoint.
@@ -813,6 +816,7 @@ XhcTransfer (
   XhcFreeUrb (Xhc, Urb);
   return Status;
 }
+#endif
 
 /** 
   Submits control transfer to a target USB device.
@@ -855,6 +859,7 @@ XhcControlTransfer (
   )   
 {
   USB_XHCI_INSTANCE       *Xhc;
+  URB                     *Urb;
   UINT8                   Endpoint;
   UINT8                   Index;
   UINT8                   DescriptorType;
@@ -865,6 +870,7 @@ XhcControlTransfer (
   EFI_USB_HUB_DESCRIPTOR  *HubDesc;
   EFI_TPL                 OldTpl;
   EFI_STATUS              Status;
+  EFI_STATUS              RecoveryStatus;
   UINTN                   MapSize;
   EFI_USB_PORT_STATUS     PortStatus;
   UINT32                  State;
@@ -971,6 +977,8 @@ XhcControlTransfer (




   // combination of Ep addr and its direction.
   //
   Endpoint = (UINT8) (0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0));
+
+#if 0
   Status = XhcTransfer (
              Xhc,
              DeviceAddress,
@@ -988,6 +996,49 @@ XhcControlTransfer (
   if (EFI_ERROR (Status)) {
     goto ON_EXIT;
   }
+#endif
+
+#if 1
+  Urb = XhcCreateUrb (
+          Xhc,
+          DeviceAddress,
+          Endpoint,
+          DeviceSpeed,
+          MaximumPacketLength,
+          XHC_CTRL_TRANSFER,
+          Request,
+          Data,
+          *DataLength,
+          NULL,
+          NULL
+          );
+
+  if (Urb == NULL) {
+    DEBUG ((DEBUG_ERROR, "XhcControlTransfer: failed to create URB!\n"));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);
+
+  *TransferResult = Urb->Result;
+  *DataLength     = Urb->Completed;
+
+  if (*TransferResult == EFI_USB_NOERROR) {
+    Status = EFI_SUCCESS;
+  } else if (*TransferResult == EFI_USB_ERR_STALL) {
+    RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
+
+    if (EFI_ERROR (RecoveryStatus)) {
+      DEBUG ((EFI_D_VERBOSE, "XhcControlTransfer: XhcRecoverHaltedEndpoint 
failed\n"));
+    }
+    Status = EFI_DEVICE_ERROR;
+  }
+
+  Xhc->PciIo->Flush (Xhc->PciIo);
+  XhcFreeUrb (Xhc, Urb);
+
+#endif



   //
   // Hook Get_Descriptor request from UsbBus as we need evaluate context and 
configure endpoint.
@@ -1223,9 +1274,11 @@ XhcBulkTransfer (
   )
 {
   USB_XHCI_INSTANCE       *Xhc;
+  URB                     *Urb;
   UINT8                   SlotId;
   EFI_STATUS              Status;
   EFI_TPL                 OldTpl;
+  EFI_STATUS              RecoveryStatus;
 
   //
   // Validate the parameters
@@ -1270,6 +1323,7 @@ XhcBulkTransfer (
   // Create a new URB, insert it into the asynchronous
   // schedule list, then poll the execution status.
   //
+#if 0
   Status = XhcTransfer (
              Xhc,
              DeviceAddress,
@@ -1283,6 +1337,46 @@ XhcBulkTransfer (
              Timeout,
              TransferResult
              );
+#endif
+
+  Urb = XhcCreateUrb (
+          Xhc,
+          DeviceAddress,
+          EndPointAddress,
+          DeviceSpeed,
+          MaximumPacketLength,
+          XHC_BULK_TRANSFER,
+          NULL,
+          Data[0],
+          *DataLength,
+          NULL,
+          NULL
+          );
+
+  if (Urb == NULL) {
+    DEBUG ((DEBUG_ERROR, "XhcBulkTransfer: failed to create URB!\n"));
+    Status = EFI_OUT_OF_RESOURCES;


+    goto ON_EXIT;
+  }
+
+  Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);
+
+  *TransferResult = Urb->Result;
+  *DataLength     = Urb->Completed;
+
+  if (*TransferResult == EFI_USB_NOERROR) {
+    Status = EFI_SUCCESS;
+  } else if (*TransferResult == EFI_USB_ERR_STALL) {
+    RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
+
+    if (EFI_ERROR (RecoveryStatus)) {
+      DEBUG ((EFI_D_VERBOSE, "XhcControlTransfer: XhcRecoverHaltedEndpoint 
failed\n"));
+    }
+    Status = EFI_DEVICE_ERROR;
+  } 
+
+  Xhc->PciIo->Flush (Xhc->PciIo);
+  XhcFreeUrb (Xhc, Urb);
 
 ON_EXIT:
   if (EFI_ERROR (Status)) {


@@ -1498,9 +1592,11 @@ XhcSyncInterruptTransfer (
   )
 {
   USB_XHCI_INSTANCE       *Xhc;
+  URB                     *Urb;
   UINT8                   SlotId;
   EFI_STATUS              Status;
   EFI_TPL                 OldTpl;
+  EFI_STATUS              RecoveryStatus;
 
   //
   // Validates parameters
@@ -1540,6 +1636,7 @@ XhcSyncInterruptTransfer (
     goto ON_EXIT;
   }
 
+#if 0
   Status = XhcTransfer (
              Xhc,
              DeviceAddress,
@@ -1553,6 +1650,45 @@ XhcSyncInterruptTransfer (
              Timeout,
              TransferResult
              );
+#endif
+  
+  Urb = XhcCreateUrb (
+          Xhc,
+          DeviceAddress,
+          EndPointAddress,
+          DeviceSpeed,
+          MaximumPacketLength,
+          XHC_INT_TRANSFER_SYNC,
+          NULL,
+          Data,
+          *DataLength,
+          NULL,
+          NULL
+          );
+
+  if (Urb == NULL) {
+    DEBUG ((EFI_D_VERBOSE, "XhcSyncInterruptTransfer: failed to create 
URB\n"));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  Status = XhcExecTransfer (Xhc, FALSE, Urb, Timeout);
+
+  *TransferResult = Urb->Result;
+  *DataLength     = Urb->Completed;
+
+  if (*TransferResult == EFI_USB_NOERROR) {
+    Status = EFI_SUCCESS;
+  } else if (*TransferResult == EFI_USB_ERR_STALL) {
+    RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);                     
+    if (EFI_ERROR (RecoveryStatus)) {
+      DEBUG ((EFI_D_VERBOSE, "XhcSyncInterruptTransfer: 
XhcRecoverHaltedEndpoint failed\n"));
+    }
+    Status = EFI_DEVICE_ERROR;
+  }
+
+  Xhc->PciIo->Flush (Xhc->PciIo);
+  XhcFreeUrb (Xhc, Urb);
 
 ON_EXIT:
   if (EFI_ERROR (Status)) {
-- 
2.27.0



Another point worth noteing is that in the UsbMassStorageDxe driver,if the USB 
device is pulled out during UsbBootExecCmdRetry, the UsbBootExecCmd  will 
repeatedly return Timeout.So, is it more reasonable to change the code to the 
following format:




diff --git a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c 
b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c
index eb8f8e81..30586406 100644
--- a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c
+++ b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c
@@ -52,6 +52,7 @@ UsbBootRequestSense (
   SenseCmd.Lun      = (UINT8) (USB_BOOT_LUN (UsbMass->Lun));
   SenseCmd.AllocLen = (UINT8) sizeof (USB_BOOT_REQUEST_SENSE_DATA);
 
+
   Status = Transport->ExecCommand (
                         UsbMass->Context,
                         &SenseCmd,
@@ -198,7 +199,7 @@ UsbBootExecCmd (
 
   if (Status == EFI_TIMEOUT) {
     DEBUG ((EFI_D_ERROR, "UsbBootExecCmd: %r to Exec 0x%x Cmd\n", Status, 
*(UINT8 *)Cmd));
-    return EFI_TIMEOUT;
+    return EFI_DEVICE_ERROR;
   }
 
   //
@@ -213,7 +214,8 @@ UsbBootExecCmd (
   // If command execution failed, then retrieve error info via sense request.
   //
   DEBUG ((EFI_D_ERROR, "UsbBootExecCmd: %r to Exec 0x%x Cmd (Result = %x)\n", 
Status, *(UINT8 *)Cmd, CmdResult));
-  return UsbBootRequestSense (UsbMass);
+  //return UsbBootRequestSense (UsbMass);
+  return EFI_SUCCESS;
 }
 
 
@@ -251,10 +253,12 @@ UsbBootExecCmdWithRetry (
 {
   EFI_STATUS                  Status;
   UINTN                       Retry;
-  EFI_EVENT                   TimeoutEvt;
+  //EFI_EVENT                   TimeoutEvt;
 
-  Retry  = 0;
+  //Retry  = 0;
   Status = EFI_SUCCESS;
+
+#if 0
   Status = gBS->CreateEvent (
                   EVT_TIMER,
                   TPL_CALLBACK,
@@ -271,6 +275,7 @@ UsbBootExecCmdWithRetry (
     goto EXIT;
   }
 
+
   //
   // Execute the cmd and retry if it fails.
   //
@@ -307,6 +312,24 @@ EXIT:
     gBS->CloseEvent (TimeoutEvt);
   }
 
+#endif




+
+  for (Retry = 0; Retry < USB_BOOT_COMMAND_RETRY; Retry++) {
+    Status = UsbBootExecCmd (
+               UsbMass,
+               Cmd,
+               CmdLen,
+               DataDir,
+               Data,
+               DataLen,
+               Timeout
+               );
+
+    if (Status == EFI_SUCCESS || Status == EFI_NO_MEDIA || Status == 
EFI_MEDIA_CHANGED) {
+      break;
+    }
+  }
+
   return Status;
 }
 
@@ -540,6 +563,7 @@ UsbBootReadCapacity (
     //
     //  Get sense data  
     //
+    DbgPrint (EFI_D_INFO,"Sorry,the BlockSize now is 0!!!!\n");
     return UsbBootRequestSense (UsbMass);
   } else {
     Media->BlockSize = BlockSize;
@@ -692,6 +716,7 @@ UsbBootDetectMedia (
   EFI_BLOCK_IO_MEDIA        *Media;
   UINT8                     CmdSet;
   EFI_STATUS                Status;
+  EFI_TPL                   OldTpl;
 
   Media    = &UsbMass->BlockIoMedia;
 
@@ -754,7 +779,10 @@ UsbBootDetectMedia (
     // This function is called from:
     //   Block I/O Protocol APIs, which run at TPL_CALLBACK.
     //   DriverBindingStart(), which raises to TPL_CALLBACK.
-    ASSERT (EfiGetCurrentTpl () == TPL_CALLBACK);
+    //ASSERT (EfiGetCurrentTpl () == TPL_CALLBACK);
+    OldTpl = EfiGetCurrentTpl ();
+    gBS->RestoreTPL (TPL_CALLBACK);
+
 
     //
     // When it is called from DriverBindingStart(), below reinstall fails.
@@ -767,6 +795,9 @@ UsbBootDetectMedia (
            &UsbMass->BlockIo
            );
 
+    ASSERT (EfiGetCurrentTpl () == TPL_CALLBACK);
+    gBS->RaiseTPL (OldTpl);
+
     //
     // Reset MediaId after reinstalling Block I/O Protocol.
     //

diff --git a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.h 
b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.h
index 64b2985e..c502a363 100644
--- a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.h
+++ b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.h
@@ -72,7 +72,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER 
EXPRESS OR IMPLIED.
 //
 // Retry mass command times, set by experience
 //
-#define USB_BOOT_COMMAND_RETRY          5
+#define USB_BOOT_COMMAND_RETRY          1
 



Thank you
Look forward to your reply.




























-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#86677): https://edk2.groups.io/g/devel/message/86677
Mute This Topic: https://groups.io/mt/89156195/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to