]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
OvmfPkg/VirtioNetDxe: list "VirtioNet.h" in the INF file
[mirror_edk2.git] / OvmfPkg / VirtioNetDxe / SnpSharedHelpers.c
index ee4f9ed36ecdaee26fc7f29ab3e47862b837b893..18dbf1812541b809de94b23c58abb75a2baafe45 100644 (file)
 \r
 #include "VirtioNet.h"\r
 \r
+//\r
+// The user structure for the ordered collection that will track the mapping\r
+// info of the packets queued in TxRing\r
+//\r
+typedef struct {\r
+  VOID                  *Buffer;\r
+  EFI_PHYSICAL_ADDRESS  DeviceAddress;  // lookup key for reverse mapping\r
+  VOID                  *BufMap;\r
+} TX_BUF_MAP_INFO;\r
+\r
 /**\r
   Release RX and TX resources on the boundary of the\r
   EfiSimpleNetworkInitialized state.\r
@@ -54,6 +64,28 @@ VirtioNetShutdownTx (
   IN OUT VNET_DEV *Dev\r
   )\r
 {\r
+  ORDERED_COLLECTION_ENTRY *Entry, *Entry2;\r
+  TX_BUF_MAP_INFO          *TxBufMapInfo;\r
+  VOID                     *UserStruct;\r
+\r
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->TxSharedReqMap);\r
+  Dev->VirtIo->FreeSharedPages (\r
+                 Dev->VirtIo,\r
+                 EFI_SIZE_TO_PAGES (sizeof *(Dev->TxSharedReq)),\r
+                 Dev->TxSharedReq\r
+                 );\r
+\r
+  for (Entry = OrderedCollectionMin (Dev->TxBufCollection);\r
+       Entry != NULL;\r
+       Entry = Entry2) {\r
+    Entry2 = OrderedCollectionNext (Entry);\r
+    OrderedCollectionDelete (Dev->TxBufCollection, Entry, &UserStruct);\r
+    TxBufMapInfo = UserStruct;\r
+    Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, TxBufMapInfo->BufMap);\r
+    FreePool (TxBufMapInfo);\r
+  }\r
+  OrderedCollectionUninit (Dev->TxBufCollection);\r
+\r
   FreePool (Dev->TxFreeStack);\r
 }\r
 \r
@@ -76,3 +108,202 @@ VirtioNetUninitRing (
   Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, RingMap);\r
   VirtioRingUninit (Dev->VirtIo, Ring);\r
 }\r
+\r
+\r
+/**\r
+  Map Caller-supplied TxBuf buffer to the device-mapped address\r
+\r
+  @param[in]    Dev               The VNET_DEV driver instance which wants to\r
+                                  map the Tx packet.\r
+  @param[in]    Buffer            The system physical address of TxBuf\r
+  @param[in]    NumberOfBytes     Number of bytes to map\r
+  @param[out]   DeviceAddress     The resulting device address for the bus\r
+                                  master access.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to\r
+                                  a lack of resources.\r
+  @return                         Status codes from\r
+                                  VirtioMapAllBytesInSharedBuffer()\r
+  @retval EFI_SUCCESS             Caller-supplied buffer is succesfully mapped.\r
+*/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioNetMapTxBuf (\r
+  IN  VNET_DEV              *Dev,\r
+  IN  VOID                  *Buffer,\r
+  IN  UINTN                 NumberOfBytes,\r
+  OUT EFI_PHYSICAL_ADDRESS  *DeviceAddress\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  TX_BUF_MAP_INFO           *TxBufMapInfo;\r
+  EFI_PHYSICAL_ADDRESS      Address;\r
+  VOID                      *Mapping;\r
+\r
+  TxBufMapInfo = AllocatePool (sizeof (*TxBufMapInfo));\r
+  if (TxBufMapInfo == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Status = VirtioMapAllBytesInSharedBuffer (\r
+             Dev->VirtIo,\r
+             VirtioOperationBusMasterRead,\r
+             Buffer,\r
+             NumberOfBytes,\r
+             &Address,\r
+             &Mapping\r
+            );\r
+  if (EFI_ERROR (Status)) {\r
+    goto FreeTxBufMapInfo;\r
+  }\r
+\r
+  TxBufMapInfo->Buffer = Buffer;\r
+  TxBufMapInfo->DeviceAddress = Address;\r
+  TxBufMapInfo->BufMap = Mapping;\r
+\r
+  Status = OrderedCollectionInsert (\r
+             Dev->TxBufCollection,\r
+             NULL,\r
+             TxBufMapInfo\r
+             );\r
+  switch (Status) {\r
+  case EFI_OUT_OF_RESOURCES:\r
+    goto UnmapTxBuf;\r
+  case EFI_ALREADY_STARTED:\r
+    //\r
+    // This should never happen: it implies\r
+    //\r
+    // - an identity-mapping VIRTIO_DEVICE_PROTOCOL.MapSharedBuffer()\r
+    //   implementation -- which is fine,\r
+    //\r
+    // - and an SNP client that queues multiple instances of the exact same\r
+    //   buffer address with SNP.Transmit() -- which is undefined behavior,\r
+    //   based on the TxBuf language in UEFI-2.7,\r
+    //   EFI_SIMPLE_NETWORK.GetStatus().\r
+    //\r
+    ASSERT (FALSE);\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto UnmapTxBuf;\r
+  default:\r
+    ASSERT_EFI_ERROR (Status);\r
+    break;\r
+  }\r
+\r
+  *DeviceAddress = Address;\r
+  return EFI_SUCCESS;\r
+\r
+UnmapTxBuf:\r
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Mapping);\r
+\r
+FreeTxBufMapInfo:\r
+  FreePool (TxBufMapInfo);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Unmap (aka reverse mapping) device mapped TxBuf buffer to the system\r
+  physical address\r
+\r
+  @param[in]    Dev               The VNET_DEV driver instance which wants to\r
+                                  reverse- and unmap the Tx packet.\r
+  @param[out]   Buffer            The system physical address of TxBuf\r
+  @param[in]    DeviceAddress     The device address for the TxBuf\r
+\r
+  @retval EFI_INVALID_PARAMETER   The DeviceAddress is not mapped\r
+  @retval EFI_SUCCESS             The TxBuf at DeviceAddress has been unmapped,\r
+                                  and Buffer has been set to TxBuf's system\r
+                                  physical address.\r
+\r
+*/\r
+EFI_STATUS\r
+EFIAPI\r
+VirtioNetUnmapTxBuf (\r
+  IN  VNET_DEV              *Dev,\r
+  OUT VOID                  **Buffer,\r
+  IN  EFI_PHYSICAL_ADDRESS  DeviceAddress\r
+  )\r
+{\r
+  ORDERED_COLLECTION_ENTRY  *Entry;\r
+  TX_BUF_MAP_INFO           *TxBufMapInfo;\r
+  VOID                      *UserStruct;\r
+\r
+  Entry = OrderedCollectionFind (Dev->TxBufCollection, &DeviceAddress);\r
+  if (Entry == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  OrderedCollectionDelete (Dev->TxBufCollection, Entry, &UserStruct);\r
+\r
+  TxBufMapInfo = UserStruct;\r
+\r
+  *Buffer = TxBufMapInfo->Buffer;\r
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, TxBufMapInfo->BufMap);\r
+  FreePool (TxBufMapInfo);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Comparator function for two TX_BUF_MAP_INFO objects.\r
+\r
+  @param[in] UserStruct1  Pointer to the first TX_BUF_MAP_INFO object.\r
+\r
+  @param[in] UserStruct2  Pointer to the second TX_BUF_MAP_INFO object.\r
+\r
+  @retval <0  If UserStruct1 compares less than UserStruct2.\r
+\r
+  @retval  0  If UserStruct1 compares equal to UserStruct2.\r
+\r
+  @retval >0  If UserStruct1 compares greater than UserStruct2.\r
+*/\r
+INTN\r
+EFIAPI\r
+VirtioNetTxBufMapInfoCompare (\r
+  IN CONST VOID *UserStruct1,\r
+  IN CONST VOID *UserStruct2\r
+  )\r
+{\r
+  CONST TX_BUF_MAP_INFO *MapInfo1;\r
+  CONST TX_BUF_MAP_INFO *MapInfo2;\r
+\r
+  MapInfo1 = UserStruct1;\r
+  MapInfo2 = UserStruct2;\r
+\r
+  return MapInfo1->DeviceAddress < MapInfo2->DeviceAddress ? -1 :\r
+         MapInfo1->DeviceAddress > MapInfo2->DeviceAddress ?  1 :\r
+         0;\r
+}\r
+\r
+/**\r
+  Compare a standalone DeviceAddress against a TX_BUF_MAP_INFO object\r
+  containing an embedded DeviceAddress.\r
+\r
+  @param[in] StandaloneKey  Pointer to DeviceAddress, which has type\r
+                            EFI_PHYSICAL_ADDRESS.\r
+\r
+  @param[in] UserStruct     Pointer to the TX_BUF_MAP_INFO object with the\r
+                            embedded DeviceAddress.\r
+\r
+  @retval <0  If StandaloneKey compares less than UserStruct's key.\r
+\r
+  @retval  0  If StandaloneKey compares equal to UserStruct's key.\r
+\r
+  @retval >0  If StandaloneKey compares greater than UserStruct's key.\r
+**/\r
+INTN\r
+EFIAPI\r
+VirtioNetTxBufDeviceAddressCompare (\r
+  IN CONST VOID *StandaloneKey,\r
+  IN CONST VOID *UserStruct\r
+  )\r
+{\r
+  CONST EFI_PHYSICAL_ADDRESS *DeviceAddress;\r
+  CONST TX_BUF_MAP_INFO      *MapInfo;\r
+\r
+  DeviceAddress = StandaloneKey;\r
+  MapInfo = UserStruct;\r
+\r
+  return *DeviceAddress < MapInfo->DeviceAddress ? -1 :\r
+         *DeviceAddress > MapInfo->DeviceAddress ?  1 :\r
+         0;\r
+}\r