]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/VirtioNetDxe/SnpInitialize.c
OvmfPkg/Virtio: take RingBaseShift in SetQueueAddress()
[mirror_edk2.git] / OvmfPkg / VirtioNetDxe / SnpInitialize.c
index 4203fbd6c1a73a058312cc4fcb4318006518d3d3..0ecfe044a97735754eddd1e1a6025e6d24270f5f 100644 (file)
@@ -5,6 +5,7 @@
 \r
   Copyright (C) 2013, Red Hat, Inc.\r
   Copyright (c) 2006 - 2010, 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
@@ -73,7 +74,7 @@ VirtioNetInitRing (
   if (QueueSize < 2) {\r
     return EFI_UNSUPPORTED;\r
   }\r
-  Status = VirtioRingInit (QueueSize, Ring);\r
+  Status = VirtioRingInit (Dev->VirtIo, QueueSize, Ring);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
@@ -95,8 +96,7 @@ VirtioNetInitRing (
   //\r
   // step 4c -- report GPFN (guest-physical frame number) of queue\r
   //\r
-  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo,\r
-      (UINT32)(UINTN) Ring->Base >> EFI_PAGE_SHIFT);\r
+  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, Ring, 0);\r
   if (EFI_ERROR (Status)) {\r
     goto ReleaseQueue;\r
   }\r
@@ -104,7 +104,7 @@ VirtioNetInitRing (
   return EFI_SUCCESS;\r
 \r
 ReleaseQueue:\r
-  VirtioRingUninit (Ring);\r
+  VirtioRingUninit (Dev->VirtIo, Ring);\r
 \r
   return Status;\r
 }\r
@@ -139,6 +139,7 @@ VirtioNetInitTx (
   IN OUT VNET_DEV *Dev\r
   )\r
 {\r
+  UINTN TxSharedReqSize;\r
   UINTN PktIdx;\r
 \r
   Dev->TxMaxPending = (UINT16) MIN (Dev->TxRing.QueueSize / 2,\r
@@ -150,6 +151,14 @@ VirtioNetInitTx (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
+  //\r
+  // In VirtIo 1.0, the NumBuffers field is mandatory. In 0.9.5, it depends on\r
+  // VIRTIO_NET_F_MRG_RXBUF, which we never negotiate.\r
+  //\r
+  TxSharedReqSize = (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) ?\r
+                    sizeof Dev->TxSharedReq.V0_9_5 :\r
+                    sizeof Dev->TxSharedReq;\r
+\r
   for (PktIdx = 0; PktIdx < Dev->TxMaxPending; ++PktIdx) {\r
     UINT16 DescIdx;\r
 \r
@@ -161,7 +170,7 @@ VirtioNetInitTx (
     // (unmodified by the host) virtio-net request header.\r
     //\r
     Dev->TxRing.Desc[DescIdx].Addr  = (UINTN) &Dev->TxSharedReq;\r
-    Dev->TxRing.Desc[DescIdx].Len   = sizeof Dev->TxSharedReq;\r
+    Dev->TxRing.Desc[DescIdx].Len   = (UINT32) TxSharedReqSize;\r
     Dev->TxRing.Desc[DescIdx].Flags = VRING_DESC_F_NEXT;\r
     Dev->TxRing.Desc[DescIdx].Next  = (UINT16) (DescIdx + 1);\r
 \r
@@ -175,8 +184,13 @@ VirtioNetInitTx (
   //\r
   // virtio-0.9.5, Appendix C, Packet Transmission\r
   //\r
-  Dev->TxSharedReq.Flags   = 0;\r
-  Dev->TxSharedReq.GsoType = VIRTIO_NET_HDR_GSO_NONE;\r
+  Dev->TxSharedReq.V0_9_5.Flags   = 0;\r
+  Dev->TxSharedReq.V0_9_5.GsoType = VIRTIO_NET_HDR_GSO_NONE;\r
+\r
+  //\r
+  // For VirtIo 1.0 only -- the field exists, but it is unused\r
+  //\r
+  Dev->TxSharedReq.NumBuffers = 0;\r
 \r
   //\r
   // virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device\r
@@ -224,19 +238,28 @@ VirtioNetInitRx (
   )\r
 {\r
   EFI_STATUS Status;\r
+  UINTN      VirtioNetReqSize;\r
   UINTN      RxBufSize;\r
   UINT16     RxAlwaysPending;\r
   UINTN      PktIdx;\r
   UINT16     DescIdx;\r
   UINT8      *RxPtr;\r
 \r
+  //\r
+  // In VirtIo 1.0, the NumBuffers field is mandatory. In 0.9.5, it depends on\r
+  // VIRTIO_NET_F_MRG_RXBUF, which we never negotiate.\r
+  //\r
+  VirtioNetReqSize = (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) ?\r
+                     sizeof (VIRTIO_NET_REQ) :\r
+                     sizeof (VIRTIO_1_0_NET_REQ);\r
+\r
   //\r
   // For each incoming packet we must supply two descriptors:\r
   // - the recipient for the virtio-net request header, plus\r
   // - the recipient for the network data (which consists of Ethernet header\r
   //   and Ethernet payload).\r
   //\r
-  RxBufSize = sizeof (VIRTIO_NET_REQ) +\r
+  RxBufSize = VirtioNetReqSize +\r
               (Dev->Snm.MediaHeaderSize + Dev->Snm.MaxPacketSize);\r
 \r
   //\r
@@ -281,14 +304,13 @@ VirtioNetInitRx (
     // virtio-0.9.5, 2.4.1.1 Placing Buffers into the Descriptor Table\r
     //\r
     Dev->RxRing.Desc[DescIdx].Addr  = (UINTN) RxPtr;\r
-    Dev->RxRing.Desc[DescIdx].Len   = sizeof (VIRTIO_NET_REQ);\r
+    Dev->RxRing.Desc[DescIdx].Len   = (UINT32) VirtioNetReqSize;\r
     Dev->RxRing.Desc[DescIdx].Flags = VRING_DESC_F_WRITE | VRING_DESC_F_NEXT;\r
     Dev->RxRing.Desc[DescIdx].Next  = (UINT16) (DescIdx + 1);\r
     RxPtr += Dev->RxRing.Desc[DescIdx++].Len;\r
 \r
     Dev->RxRing.Desc[DescIdx].Addr  = (UINTN) RxPtr;\r
-    Dev->RxRing.Desc[DescIdx].Len   = (UINT32) (RxBufSize -\r
-                                                sizeof (VIRTIO_NET_REQ));\r
+    Dev->RxRing.Desc[DescIdx].Len   = (UINT32) (RxBufSize - VirtioNetReqSize);\r
     Dev->RxRing.Desc[DescIdx].Flags = VRING_DESC_F_WRITE;\r
     RxPtr += Dev->RxRing.Desc[DescIdx++].Len;\r
   }\r
@@ -360,7 +382,7 @@ VirtioNetInitialize (
   EFI_TPL    OldTpl;\r
   EFI_STATUS Status;\r
   UINT8      NextDevStat;\r
-  UINT32     Features;\r
+  UINT64     Features;\r
 \r
   if (This == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -418,6 +440,19 @@ VirtioNetInitialize (
   ASSERT (Dev->Snm.MediaPresentSupported ==\r
     !!(Features & VIRTIO_NET_F_STATUS));\r
 \r
+  Features &= VIRTIO_NET_F_MAC | VIRTIO_NET_F_STATUS | 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 DeviceFailed;\r
+    }\r
+  }\r
+\r
   //\r
   // step 4b, 4c -- allocate and report virtqueues\r
   //\r
@@ -434,10 +469,12 @@ VirtioNetInitialize (
   //\r
   // step 5 -- keep only the features we want\r
   //\r
-  Features &= VIRTIO_NET_F_MAC | VIRTIO_NET_F_STATUS;\r
-  Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);\r
-  if (EFI_ERROR (Status)) {\r
-    goto ReleaseTxRing;\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 ReleaseTxRing;\r
+    }\r
   }\r
 \r
   //\r
@@ -473,10 +510,10 @@ AbortDevice:
   Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
 \r
 ReleaseTxRing:\r
-  VirtioRingUninit (&Dev->TxRing);\r
+  VirtioRingUninit (Dev->VirtIo, &Dev->TxRing);\r
 \r
 ReleaseRxRing:\r
-  VirtioRingUninit (&Dev->RxRing);\r
+  VirtioRingUninit (Dev->VirtIo, &Dev->RxRing);\r
 \r
 DeviceFailed:\r
   //\r