]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
MdeModulePkg/XhciDxe: enable 64-bit PCI DMA
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / XhciDxe / Xhci.c
index 3224202bfe45c8d2cf6b4bfbc3699e8fd87a48f4..1058f03030cac9a0d2fab40417232317f048e230 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   The XHCI controller driver.\r
 \r
-Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -125,7 +125,7 @@ XhcGetCapability (
   Xhc             = XHC_FROM_THIS (This);\r
   *MaxSpeed       = EFI_USB_SPEED_SUPER;\r
   *PortNumber     = (UINT8) (Xhc->HcSParams1.Data.MaxPorts);\r
-  *Is64BitCapable = (UINT8) (Xhc->HcCParams.Data.Ac64);\r
+  *Is64BitCapable = (UINT8) Xhc->Support64BitDma;\r
   DEBUG ((EFI_D_INFO, "XhcGetCapability: %d ports, 64 bit %d\n", *PortNumber, *Is64BitCapable));\r
 \r
   gBS->RestoreTPL (OldTpl);\r
@@ -905,17 +905,28 @@ XhcControlTransfer (
   *TransferResult = Urb->Result;\r
   *DataLength     = Urb->Completed;\r
 \r
-  if (*TransferResult == EFI_USB_NOERROR) {\r
-    Status = EFI_SUCCESS;\r
-  } else if (*TransferResult == EFI_USB_ERR_STALL) {\r
-    RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);\r
-    if (EFI_ERROR (RecoveryStatus)) {\r
-      DEBUG ((EFI_D_ERROR, "XhcControlTransfer: XhcRecoverHaltedEndpoint failed\n"));\r
+  if (Status == EFI_TIMEOUT) {\r
+    //\r
+    // The transfer timed out. Abort the transfer by dequeueing of the TD.\r
+    //\r
+    RecoveryStatus = XhcDequeueTrbFromEndpoint(Xhc, Urb);\r
+    if (EFI_ERROR(RecoveryStatus)) {\r
+      DEBUG((EFI_D_ERROR, "XhcControlTransfer: XhcDequeueTrbFromEndpoint failed\n"));\r
     }\r
-    Status = EFI_DEVICE_ERROR;\r
     goto FREE_URB;\r
   } else {\r
-    goto FREE_URB;\r
+    if (*TransferResult == EFI_USB_NOERROR) {\r
+      Status = EFI_SUCCESS;\r
+    } else if (*TransferResult == EFI_USB_ERR_STALL) {\r
+      RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);\r
+      if (EFI_ERROR (RecoveryStatus)) {\r
+        DEBUG ((EFI_D_ERROR, "XhcControlTransfer: XhcRecoverHaltedEndpoint failed\n"));\r
+      }\r
+      Status = EFI_DEVICE_ERROR;\r
+      goto FREE_URB;\r
+    } else {\r
+      goto FREE_URB;\r
+    }\r
   }\r
 \r
   Xhc->PciIo->Flush (Xhc->PciIo);\r
@@ -944,7 +955,7 @@ XhcControlTransfer (
         // Store a copy of device scriptor as hub device need this info to configure endpoint.\r
         //\r
         CopyMem (&Xhc->UsbDevContext[SlotId].DevDesc, Data, *DataLength);\r
-        if (Xhc->UsbDevContext[SlotId].DevDesc.BcdUSB == 0x0300) {\r
+        if (Xhc->UsbDevContext[SlotId].DevDesc.BcdUSB >= 0x0300) {\r
           //\r
           // If it's a usb3.0 device, then its max packet size is a 2^n.\r
           //\r
@@ -1241,14 +1252,24 @@ XhcBulkTransfer (
   *TransferResult = Urb->Result;\r
   *DataLength     = Urb->Completed;\r
 \r
-  if (*TransferResult == EFI_USB_NOERROR) {\r
-    Status = EFI_SUCCESS;\r
-  } else if (*TransferResult == EFI_USB_ERR_STALL) {\r
-    RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);\r
-    if (EFI_ERROR (RecoveryStatus)) {\r
-      DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: XhcRecoverHaltedEndpoint failed\n"));\r
+  if (Status == EFI_TIMEOUT) {\r
+    //\r
+    // The transfer timed out. Abort the transfer by dequeueing of the TD.\r
+    //\r
+    RecoveryStatus = XhcDequeueTrbFromEndpoint(Xhc, Urb);\r
+    if (EFI_ERROR(RecoveryStatus)) {\r
+      DEBUG((EFI_D_ERROR, "XhcBulkTransfer: XhcDequeueTrbFromEndpoint failed\n"));\r
+    }\r
+  } else {\r
+    if (*TransferResult == EFI_USB_NOERROR) {\r
+      Status = EFI_SUCCESS;\r
+    } else if (*TransferResult == EFI_USB_ERR_STALL) {\r
+      RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);\r
+      if (EFI_ERROR (RecoveryStatus)) {\r
+        DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: XhcRecoverHaltedEndpoint failed\n"));\r
+      }\r
+      Status = EFI_DEVICE_ERROR;\r
     }\r
-    Status = EFI_DEVICE_ERROR;\r
   }\r
 \r
   Xhc->PciIo->Flush (Xhc->PciIo);\r
@@ -1483,10 +1504,6 @@ XhcSyncInterruptTransfer (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if (!XHCI_IS_DATAIN (EndPointAddress)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
   if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
@@ -1542,14 +1559,24 @@ XhcSyncInterruptTransfer (
   *TransferResult = Urb->Result;\r
   *DataLength     = Urb->Completed;\r
 \r
-  if (*TransferResult == EFI_USB_NOERROR) {\r
-    Status = EFI_SUCCESS;\r
-  } else if (*TransferResult == EFI_USB_ERR_STALL) {\r
-    RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);\r
-    if (EFI_ERROR (RecoveryStatus)) {\r
-      DEBUG ((EFI_D_ERROR, "XhcSyncInterruptTransfer: XhcRecoverHaltedEndpoint failed\n"));\r
+  if (Status == EFI_TIMEOUT) {\r
+    //\r
+    // The transfer timed out. Abort the transfer by dequeueing of the TD.\r
+    //\r
+    RecoveryStatus = XhcDequeueTrbFromEndpoint(Xhc, Urb);\r
+    if (EFI_ERROR(RecoveryStatus)) {\r
+      DEBUG((EFI_D_ERROR, "XhcSyncInterruptTransfer: XhcDequeueTrbFromEndpoint failed\n"));\r
+    }\r
+  } else {\r
+    if (*TransferResult == EFI_USB_NOERROR) {\r
+      Status = EFI_SUCCESS;\r
+    } else if (*TransferResult == EFI_USB_ERR_STALL) {\r
+      RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);\r
+      if (EFI_ERROR (RecoveryStatus)) {\r
+        DEBUG ((EFI_D_ERROR, "XhcSyncInterruptTransfer: XhcRecoverHaltedEndpoint failed\n"));\r
+      }\r
+      Status = EFI_DEVICE_ERROR;\r
     }\r
-    Status = EFI_DEVICE_ERROR;\r
   }\r
 \r
   Xhc->PciIo->Flush (Xhc->PciIo);\r
@@ -1826,7 +1853,7 @@ XhcCreateUsbHc (
   //\r
   Status = gBS->CreateEvent (\r
                   EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
-                  TPL_CALLBACK,\r
+                  TPL_NOTIFY,\r
                   XhcMonitorAsyncRequests,\r
                   Xhc,\r
                   &Xhc->PollTimer\r
@@ -1993,6 +2020,26 @@ XhcDriverBindingStart (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
+  //\r
+  // Enable 64-bit DMA support in the PCI layer if this controller\r
+  // supports it.\r
+  //\r
+  if (Xhc->HcCParams.Data.Ac64 != 0) {\r
+    Status = PciIo->Attributes (\r
+                      PciIo,\r
+                      EfiPciIoAttributeOperationEnable,\r
+                      EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,\r
+                      NULL\r
+                      );\r
+    if (!EFI_ERROR (Status)) {\r
+      Xhc->Support64BitDma = TRUE;\r
+    } else {\r
+      DEBUG ((EFI_D_WARN,\r
+        "%a: failed to enable 64-bit DMA on 64-bit capable controller @ %p (%r)\n",\r
+        __FUNCTION__, Controller, Status));\r
+    }\r
+  }\r
+\r
   XhcSetBiosOwnership (Xhc);\r
 \r
   XhcResetHC (Xhc, XHC_RESET_TIMEOUT);\r