]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/VirtioNetDxe/SnpInitialize.c
OvmfPkg/VirtioLib: take VirtIo instance in VirtioRingInit/VirtioRingUninit
[mirror_edk2.git] / OvmfPkg / VirtioNetDxe / SnpInitialize.c
index f06b0a5a5742bef6ea1945bfba5357d7e189f878..6d9b81a9f9399e08c73b13f7d204c2d77d2ab472 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
 \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
 \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
   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
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
@@ -103,7 +104,7 @@ VirtioNetInitRing (
   return EFI_SUCCESS;\r
 \r
 ReleaseQueue:\r
   return EFI_SUCCESS;\r
 \r
 ReleaseQueue:\r
-  VirtioRingUninit (Ring);\r
+  VirtioRingUninit (Dev->VirtIo, Ring);\r
 \r
   return Status;\r
 }\r
 \r
   return Status;\r
 }\r
@@ -138,6 +139,7 @@ VirtioNetInitTx (
   IN OUT VNET_DEV *Dev\r
   )\r
 {\r
   IN OUT VNET_DEV *Dev\r
   )\r
 {\r
+  UINTN TxSharedReqSize;\r
   UINTN PktIdx;\r
 \r
   Dev->TxMaxPending = (UINT16) MIN (Dev->TxRing.QueueSize / 2,\r
   UINTN PktIdx;\r
 \r
   Dev->TxMaxPending = (UINT16) MIN (Dev->TxRing.QueueSize / 2,\r
@@ -149,6 +151,14 @@ VirtioNetInitTx (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
     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
   for (PktIdx = 0; PktIdx < Dev->TxMaxPending; ++PktIdx) {\r
     UINT16 DescIdx;\r
 \r
@@ -160,7 +170,7 @@ VirtioNetInitTx (
     // (unmodified by the host) virtio-net request header.\r
     //\r
     Dev->TxRing.Desc[DescIdx].Addr  = (UINTN) &Dev->TxSharedReq;\r
     // (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
     Dev->TxRing.Desc[DescIdx].Flags = VRING_DESC_F_NEXT;\r
     Dev->TxRing.Desc[DescIdx].Next  = (UINT16) (DescIdx + 1);\r
 \r
@@ -174,8 +184,13 @@ VirtioNetInitTx (
   //\r
   // virtio-0.9.5, Appendix C, Packet Transmission\r
   //\r
   //\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
 \r
   //\r
   // virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device\r
@@ -223,19 +238,28 @@ VirtioNetInitRx (
   )\r
 {\r
   EFI_STATUS Status;\r
   )\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
   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
   //\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
               (Dev->Snm.MediaHeaderSize + Dev->Snm.MaxPacketSize);\r
 \r
   //\r
@@ -280,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
     // 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].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
     Dev->RxRing.Desc[DescIdx].Flags = VRING_DESC_F_WRITE;\r
     RxPtr += Dev->RxRing.Desc[DescIdx++].Len;\r
   }\r
@@ -417,6 +440,19 @@ VirtioNetInitialize (
   ASSERT (Dev->Snm.MediaPresentSupported ==\r
     !!(Features & VIRTIO_NET_F_STATUS));\r
 \r
   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
   //\r
   // step 4b, 4c -- allocate and report virtqueues\r
   //\r
@@ -433,10 +469,12 @@ VirtioNetInitialize (
   //\r
   // step 5 -- keep only the features we want\r
   //\r
   //\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
   }\r
 \r
   //\r
@@ -472,10 +510,10 @@ AbortDevice:
   Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
 \r
 ReleaseTxRing:\r
   Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
 \r
 ReleaseTxRing:\r
-  VirtioRingUninit (&Dev->TxRing);\r
+  VirtioRingUninit (Dev->VirtIo, &Dev->TxRing);\r
 \r
 ReleaseRxRing:\r
 \r
 ReleaseRxRing:\r
-  VirtioRingUninit (&Dev->RxRing);\r
+  VirtioRingUninit (Dev->VirtIo, &Dev->RxRing);\r
 \r
 DeviceFailed:\r
   //\r
 \r
 DeviceFailed:\r
   //\r