]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/VirtioScsiDxe/VirtioScsi.c
OvmfPkg/Virtio: take RingBaseShift in SetQueueAddress()
[mirror_edk2.git] / OvmfPkg / VirtioScsiDxe / VirtioScsi.c
index 2cb3f43bb01c25c29297f0e7027d11dcd5391b8d..a983b3df7b9caf2d1490af8ec6b0dee7cfc45129 100644 (file)
@@ -27,6 +27,7 @@
 \r
   Copyright (C) 2012, Red Hat, Inc.\r
   Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2017, AMD Inc, All rights reserved.<BR>\r
 \r
   This program and the accompanying materials are licensed and made available\r
   under the terms and conditions of the BSD License which accompanies this\r
@@ -470,7 +471,7 @@ VirtioScsiPassThru (
   // caller retry.\r
   //\r
   if (VirtioFlush (Dev->VirtIo, VIRTIO_SCSI_REQUEST_QUEUE, &Dev->Ring,\r
-        &Indices) != EFI_SUCCESS) {\r
+        &Indices, NULL) != EFI_SUCCESS) {\r
     Packet->InTransferLength  = 0;\r
     Packet->OutTransferLength = 0;\r
     Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;\r
@@ -707,7 +708,7 @@ VirtioScsiInit (
   UINT8      NextDevStat;\r
   EFI_STATUS Status;\r
 \r
-  UINT32     Features;\r
+  UINT64     Features;\r
   UINT16     MaxChannel; // for validation only\r
   UINT32     NumQueues;  // for validation only\r
   UINT16     QueueSize;\r
@@ -800,6 +801,19 @@ VirtioScsiInit (
     goto Failed;\r
   }\r
 \r
+  Features &= VIRTIO_SCSI_F_INOUT | VIRTIO_F_VERSION_1;\r
+\r
+  //\r
+  // In virtio-1.0, feature negotiation is expected to complete before queue\r
+  // discovery, and the device can also reject the selected set of features.\r
+  //\r
+  if (Dev->VirtIo->Revision >= VIRTIO_SPEC_REVISION (1, 0, 0)) {\r
+    Status = Virtio10WriteFeatures (Dev->VirtIo, Features, &NextDevStat);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Failed;\r
+    }\r
+  }\r
+\r
   //\r
   // step 4b -- allocate request virtqueue\r
   //\r
@@ -819,7 +833,7 @@ VirtioScsiInit (
     goto Failed;\r
   }\r
 \r
-  Status = VirtioRingInit (QueueSize, &Dev->Ring);\r
+  Status = VirtioRingInit (Dev->VirtIo, QueueSize, &Dev->Ring);\r
   if (EFI_ERROR (Status)) {\r
     goto Failed;\r
   }\r
@@ -841,21 +855,20 @@ VirtioScsiInit (
   //\r
   // step 4c -- Report GPFN (guest-physical frame number) of queue.\r
   //\r
-  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo,\r
-      (UINT32) ((UINTN) Dev->Ring.Base >> EFI_PAGE_SHIFT));\r
+  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, &Dev->Ring, 0);\r
   if (EFI_ERROR (Status)) {\r
     goto ReleaseQueue;\r
   }\r
 \r
   //\r
-  // step 5 -- Report understood features and guest-tuneables. We want none of\r
-  // the known (or unknown) VIRTIO_SCSI_F_* or VIRTIO_F_* capabilities (see\r
-  // virtio-0.9.5, Appendices B and I), except bidirectional transfers.\r
+  // step 5 -- Report understood features and guest-tuneables.\r
   //\r
-  Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo,\r
-      Features & VIRTIO_SCSI_F_INOUT);\r
-  if (EFI_ERROR (Status)) {\r
-    goto ReleaseQueue;\r
+  if (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) {\r
+    Features &= ~(UINT64)VIRTIO_F_VERSION_1;\r
+    Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);\r
+    if (EFI_ERROR (Status)) {\r
+      goto ReleaseQueue;\r
+    }\r
   }\r
 \r
   //\r
@@ -914,7 +927,7 @@ VirtioScsiInit (
   return EFI_SUCCESS;\r
 \r
 ReleaseQueue:\r
-  VirtioRingUninit (&Dev->Ring);\r
+  VirtioRingUninit (Dev->VirtIo, &Dev->Ring);\r
 \r
 Failed:\r
   //\r
@@ -933,7 +946,6 @@ Failed:
 }\r
 \r
 \r
-\r
 STATIC\r
 VOID\r
 EFIAPI\r
@@ -953,13 +965,39 @@ VirtioScsiUninit (
   Dev->MaxLun         = 0;\r
   Dev->MaxSectors     = 0;\r
 \r
-  VirtioRingUninit (&Dev->Ring);\r
+  VirtioRingUninit (Dev->VirtIo, &Dev->Ring);\r
 \r
   SetMem (&Dev->PassThru,     sizeof Dev->PassThru,     0x00);\r
   SetMem (&Dev->PassThruMode, sizeof Dev->PassThruMode, 0x00);\r
 }\r
 \r
 \r
+//\r
+// Event notification function enqueued by ExitBootServices().\r
+//\r
+\r
+STATIC\r
+VOID\r
+EFIAPI\r
+VirtioScsiExitBoot (\r
+  IN  EFI_EVENT Event,\r
+  IN  VOID      *Context\r
+  )\r
+{\r
+  VSCSI_DEV *Dev;\r
+\r
+  //\r
+  // Reset the device. This causes the hypervisor to forget about the virtio\r
+  // ring.\r
+  //\r
+  // We allocated said ring in EfiBootServicesData type memory, and code\r
+  // executing after ExitBootServices() is permitted to overwrite it.\r
+  //\r
+  Dev = Context;\r
+  Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
+}\r
+\r
+\r
 //\r
 // Probe, start and stop functions of this driver, called by the DXE core for\r
 // specific devices.\r
@@ -1050,6 +1088,12 @@ VirtioScsiDriverBindingStart (
     goto CloseVirtIo;\r
   }\r
 \r
+  Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,\r
+                  &VirtioScsiExitBoot, Dev, &Dev->ExitBoot);\r
+  if (EFI_ERROR (Status)) {\r
+    goto UninitDev;\r
+  }\r
+\r
   //\r
   // Setup complete, attempt to export the driver instance's PassThru\r
   // interface.\r
@@ -1059,11 +1103,14 @@ VirtioScsiDriverBindingStart (
                   &gEfiExtScsiPassThruProtocolGuid, EFI_NATIVE_INTERFACE,\r
                   &Dev->PassThru);\r
   if (EFI_ERROR (Status)) {\r
-    goto UninitDev;\r
+    goto CloseExitBoot;\r
   }\r
 \r
   return EFI_SUCCESS;\r
 \r
+CloseExitBoot:\r
+  gBS->CloseEvent (Dev->ExitBoot);\r
+\r
 UninitDev:\r
   VirtioScsiUninit (Dev);\r
 \r
@@ -1114,6 +1161,8 @@ VirtioScsiDriverBindingStop (
     return Status;\r
   }\r
 \r
+  gBS->CloseEvent (Dev->ExitBoot);\r
+\r
   VirtioScsiUninit (Dev);\r
 \r
   gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r