public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Brijesh Singh <brijesh.singh@amd.com>
To: edk2-devel@lists.01.org
Cc: Brijesh Singh <brijesh.singh@amd.com>,
	Ard Biesheuvel <ard.biesheuvel@linaro.org>,
	Jordan Justen <jordan.l.justen@intel.com>,
	Tom Lendacky <thomas.lendacky@amd.com>,
	Laszlo Ersek <lersek@redhat.com>
Subject: [PATCH v2 6/8] OvmfPkg/VirtioNetDxe: add Tx packet map/unmap helper functions
Date: Mon, 11 Sep 2017 07:16:55 -0500	[thread overview]
Message-ID: <20170911121657.34992-7-brijesh.singh@amd.com> (raw)
In-Reply-To: <20170911121657.34992-1-brijesh.singh@amd.com>

When device is behind IOMMU, driver is require to pass the device address
of TxBuf in the Tx VRING. The patch adds helper functions and data
structure to map and unmap the TxBuf system physical address to a device
address.

Since the TxBuf is returned back to caller from VirtioNetGetStatus() hence
we use OrderedCollection interface to save the TxBuf system physical to
device address mapping. After the TxBuf is succesfully transmitted
VirtioNetUnmapTxBuf() does the reverse lookup in OrderedCollection data
structure to get the system physical address of TxBuf for a given device
address.

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 OvmfPkg/VirtioNetDxe/VirtioNet.inf      |   1 +
 OvmfPkg/VirtioNetDxe/VirtioNet.h        |  32 ++++
 OvmfPkg/VirtioNetDxe/SnpInitialize.c    |  15 +-
 OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c | 188 ++++++++++++++++++++
 4 files changed, 235 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/VirtioNetDxe/VirtioNet.inf b/OvmfPkg/VirtioNetDxe/VirtioNet.inf
index a855ad4ac154..9ff6d87e6190 100644
--- a/OvmfPkg/VirtioNetDxe/VirtioNet.inf
+++ b/OvmfPkg/VirtioNetDxe/VirtioNet.inf
@@ -49,6 +49,7 @@
   DebugLib
   DevicePathLib
   MemoryAllocationLib
+  OrderedCollectionLib
   UefiBootServicesTableLib
   UefiDriverEntryPoint
   UefiLib
diff --git a/OvmfPkg/VirtioNetDxe/VirtioNet.h b/OvmfPkg/VirtioNetDxe/VirtioNet.h
index 3f48bcc6b67c..906bec8e88f3 100644
--- a/OvmfPkg/VirtioNetDxe/VirtioNet.h
+++ b/OvmfPkg/VirtioNetDxe/VirtioNet.h
@@ -26,6 +26,7 @@
 #include <Protocol/DevicePath.h>
 #include <Protocol/DriverBinding.h>
 #include <Protocol/SimpleNetwork.h>
+#include <Library/OrderedCollectionLib.h>
 
 #define VNET_SIG SIGNATURE_32 ('V', 'N', 'E', 'T')
 
@@ -100,6 +101,7 @@ typedef struct {
   VOID                        *TxSharedReqMap;   // VirtioNetInitTx
   UINT16                      TxLastUsed;        // VirtioNetInitTx
   EFI_PHYSICAL_ADDRESS        RxBufDeviceBase;   // VirtioNetInitRx
+  ORDERED_COLLECTION          *TxBufMapInfoCollection; // VirtioNetInitTx
 } VNET_DEV;
 
 
@@ -281,6 +283,36 @@ VirtioNetUninitRing (
   );
 
 //
+// utility functions to map caller-supplied Tx buffer system physical address
+// to a device address and vice versa
+//
+EFI_STATUS
+EFIAPI
+VirtioNetMapTxBuf (
+  IN  VNET_DEV              *Dev,
+  IN  UINT16                DescIdx,
+  IN  VOID                  *Buffer,
+  IN  UINTN                 NumberOfBytes,
+  OUT EFI_PHYSICAL_ADDRESS  *DeviceAddress
+  );
+
+INTN
+EFIAPI
+VirtioNetTxMapInfoCompare (
+  IN CONST VOID *UserStruct1,
+  IN CONST VOID *UserStruct2
+  );
+
+EFI_STATUS
+EFIAPI
+VirtioNetUnmapTxBuf (
+  IN  VNET_DEV              *Dev,
+  IN  UINT16                DescIdx,
+  OUT VOID                  **Buffer,
+  IN  EFI_PHYSICAL_ADDRESS  DeviceAddress
+  );
+
+//
 // event callbacks
 //
 VOID
diff --git a/OvmfPkg/VirtioNetDxe/SnpInitialize.c b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
index 6cedb406a172..a8ffb9a8a7b1 100644
--- a/OvmfPkg/VirtioNetDxe/SnpInitialize.c
+++ b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
@@ -176,6 +176,15 @@ VirtioNetInitTx (
     return EFI_OUT_OF_RESOURCES;
   }
 
+  Dev->TxBufMapInfoCollection = OrderedCollectionInit (
+                                  VirtioNetTxMapInfoCompare,
+                                  VirtioNetTxMapInfoCompare
+                                  );
+  if (Dev->TxBufMapInfoCollection == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto FreeTxFreeStack;
+  }
+
   //
   // Allocate TxSharedReq header and map with BusMasterCommonBuffer so that it
   // can be accessed equally by both processor and device.
@@ -186,7 +195,7 @@ VirtioNetInitTx (
                           &TxSharedReqBuffer
                           );
   if (EFI_ERROR (Status)) {
-    goto FreeTxFreeStack;
+    goto UninitMapInfoCollection;
   }
 
   ZeroMem (TxSharedReqBuffer, sizeof *Dev->TxSharedReq);
@@ -267,6 +276,10 @@ FreeTxSharedReqBuffer:
                  EFI_SIZE_TO_PAGES (sizeof *(Dev->TxSharedReq)),
                  TxSharedReqBuffer
                  );
+
+UninitMapInfoCollection:
+  OrderedCollectionUninit (Dev->TxBufMapInfoCollection);
+
 FreeTxFreeStack:
   FreePool (Dev->TxFreeStack);
 
diff --git a/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c b/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
index 2ec3dc385a9f..dafb538b4b5a 100644
--- a/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
+++ b/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
@@ -18,6 +18,17 @@
 
 #include "VirtioNet.h"
 
+//
+// The user structure for the ordered collection that will track the mapping
+// info of the packets queued in TxRing
+//
+typedef struct {
+  UINT16                DescIdx;
+  VOID                  *Buffer;
+  EFI_PHYSICAL_ADDRESS  DeviceAddress;
+  VOID                  *BufMap;
+} TX_BUF_MAP_INFO;
+
 /**
   Release RX and TX resources on the boundary of the
   EfiSimpleNetworkInitialized state.
@@ -54,6 +65,20 @@ VirtioNetShutdownTx (
   IN OUT VNET_DEV *Dev
   )
 {
+  ORDERED_COLLECTION_ENTRY *Entry, *Entry2;
+  TX_BUF_MAP_INFO          *TxBufMapInfo;
+
+  for (Entry = OrderedCollectionMin (Dev->TxBufMapInfoCollection);
+       Entry != NULL;
+       Entry = Entry2) {
+    Entry2 = OrderedCollectionNext (Entry);
+    TxBufMapInfo = (TX_BUF_MAP_INFO *)Entry2;
+    Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, TxBufMapInfo->BufMap);
+    FreePool (TxBufMapInfo);
+    OrderedCollectionDelete (Dev->TxBufMapInfoCollection, Entry, NULL);
+  }
+  OrderedCollectionUninit (Dev->TxBufMapInfoCollection);
+
   Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->TxSharedReqMap);
   Dev->VirtIo->FreeSharedPages (
                  Dev->VirtIo,
@@ -83,3 +108,166 @@ VirtioNetUninitRing (
   Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, RingMap);
   VirtioRingUninit (Dev->VirtIo, Ring);
 }
+
+
+/**
+  Map Caller-supplied TxBuf buffer to the device-mapped address
+
+  @param[in]    Dev               The VNET_DEV driver instance which wants to
+                                  map the Tx packet.
+  @param[in]    DescIdx           VRING descriptor index which will point to
+                                  the device address
+  @param[in]    Buffer            The system physical address of TxBuf
+  @param[in]    NumberOfBytes     Number of bytes to map
+  @param[out]   DeviceAddress     The resulting device address for the bus
+                                  master access.
+
+  @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to
+                                  a lack of resources.
+  @retval EFI_INVALID_PARAMETER   The VRING descriptor index is already mapped.
+*/
+EFI_STATUS
+EFIAPI
+VirtioNetMapTxBuf (
+  IN  VNET_DEV              *Dev,
+  IN  UINT16                DescIdx,
+  IN  VOID                  *Buffer,
+  IN  UINTN                 NumberOfBytes,
+  OUT EFI_PHYSICAL_ADDRESS  *DeviceAddress
+  )
+{
+  EFI_STATUS                Status;
+  TX_BUF_MAP_INFO           *TxBufMapInfo;
+  EFI_PHYSICAL_ADDRESS      Address;
+  VOID                      *Mapping;
+  ORDERED_COLLECTION_ENTRY  *Entry;
+
+  TxBufMapInfo = AllocatePool (sizeof (*TxBufMapInfo));
+  if (TxBufMapInfo == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = VirtioMapAllBytesInSharedBuffer (
+             Dev->VirtIo,
+             VirtioOperationBusMasterRead,
+             Buffer,
+             NumberOfBytes,
+             &Address,
+             &Mapping
+            );
+  if (EFI_ERROR (Status)) {
+    goto FreeTxBufMapInfo;
+  }
+
+  TxBufMapInfo->DescIdx = DescIdx;
+  TxBufMapInfo->Buffer = Buffer;
+  TxBufMapInfo->DeviceAddress = Address;
+  TxBufMapInfo->BufMap = Mapping;
+
+  Status = OrderedCollectionInsert (
+             Dev->TxBufMapInfoCollection,
+             &Entry,
+             TxBufMapInfo
+             );
+  switch (Status) {
+  case RETURN_OUT_OF_RESOURCES:
+    Status = EFI_OUT_OF_RESOURCES;
+    goto UnmapTxBufBuffer;
+  case RETURN_ALREADY_STARTED:
+    Status = EFI_INVALID_PARAMETER;
+    goto UnmapTxBufBuffer;
+  default:
+    ASSERT (Status == RETURN_SUCCESS);
+    break;
+  }
+
+  ASSERT (OrderedCollectionUserStruct (Entry) == TxBufMapInfo);
+
+  *DeviceAddress = Address;
+
+  return EFI_SUCCESS;
+
+UnmapTxBufBuffer:
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Mapping);
+
+FreeTxBufMapInfo:
+  FreePool (TxBufMapInfo);
+  return Status;
+}
+
+/**
+  Unmap (aka reverse mapping) device mapped TxBuf buffer to the system
+  physical address
+
+  @param[in]    Dev               The VNET_DEV driver instance which wants to
+                                  map the Tx packet.
+  @param[in]    DescIdx           VRING descriptor index which point to
+                                  the device address
+  @param[out]   Buffer            The system physical address of TxBuf
+  @param[out]   DeviceAddress     The device address for the TxBuf
+
+  @retval EFI_INVALID_PARAMETER   The VRING descriptor index is not mapped
+*/
+EFI_STATUS
+EFIAPI
+VirtioNetUnmapTxBuf (
+  IN  VNET_DEV              *Dev,
+  IN  UINT16                DescIdx,
+  OUT VOID                  **Buffer,
+  IN  EFI_PHYSICAL_ADDRESS  DeviceAddress
+  )
+{
+  TX_BUF_MAP_INFO           StandaloneKey;
+  ORDERED_COLLECTION_ENTRY  *Entry;
+  TX_BUF_MAP_INFO           *UserStruct;
+  VOID                      *Ptr;
+  EFI_STATUS                Status;
+
+  StandaloneKey.DescIdx = DescIdx;
+  Entry = OrderedCollectionFind (Dev->TxBufMapInfoCollection, &StandaloneKey);
+  if (Entry == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OrderedCollectionDelete (Dev->TxBufMapInfoCollection, Entry, &Ptr);
+
+  UserStruct = Ptr;
+  ASSERT (UserStruct->DescIdx == DescIdx);
+
+  *Buffer =  UserStruct->Buffer;
+  Status = Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, UserStruct->BufMap);
+  FreePool (UserStruct);
+
+  return Status;
+}
+
+/**
+  Comparator function for two user structures.
+
+  @param[in] UserStruct1  Pointer to the first user structure.
+
+  @param[in] UserStruct2  Pointer to the second user structure.
+
+  @retval <0  If UserStruct1 compares less than UserStruct2.
+
+  @retval  0  If UserStruct1 compares equal to UserStruct2.
+
+  @retval >0  If UserStruct1 compares greater than UserStruct2.
+*/
+INTN
+EFIAPI
+VirtioNetTxMapInfoCompare (
+  IN CONST VOID *UserStruct1,
+  IN CONST VOID *UserStruct2
+  )
+{
+  CONST TX_BUF_MAP_INFO *MapInfo1;
+  CONST TX_BUF_MAP_INFO *MapInfo2;
+
+  MapInfo1 = UserStruct1;
+  MapInfo2 = UserStruct2;
+
+  return MapInfo1->DescIdx < MapInfo2->DescIdx ? -1 :
+         MapInfo1->DescIdx > MapInfo2->DescIdx ?  1 :
+         0;
+}
-- 
2.9.4



  parent reply	other threads:[~2017-09-11 12:14 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-09-11 12:16 [PATCH v2 0/8] OvmfPkg/VirtioNetDxe: map host address to device address Brijesh Singh
2017-09-11 12:16 ` [PATCH v2 1/8] OvmfPkg/VirtioNetDxe: add helper VirtioNetUninitRing() Brijesh Singh
2017-09-13  7:26   ` Laszlo Ersek
2017-09-11 12:16 ` [PATCH v2 2/8] OvmfPkg/VirtioNetDxe: map VRINGs using VirtioRingMap() Brijesh Singh
2017-09-13  8:07   ` Laszlo Ersek
2017-09-11 12:16 ` [PATCH v2 3/8] OvmfPkg/VirtioNetDxe: alloc RxBuf using AllocateSharedPages() Brijesh Singh
2017-09-13  9:14   ` Laszlo Ersek
2017-09-11 12:16 ` [PATCH v2 4/8] OvmfPkg/VirtioNetDxe: dynamically alloc transmit header Brijesh Singh
2017-09-13 14:31   ` Laszlo Ersek
2017-09-11 12:16 ` [PATCH v2 5/8] OvmfPkg/VirtioNetDxe: update TechNotes Brijesh Singh
2017-09-13 14:40   ` Laszlo Ersek
2017-09-11 12:16 ` Brijesh Singh [this message]
2017-09-13 18:07   ` [PATCH v2 6/8] OvmfPkg/VirtioNetDxe: add Tx packet map/unmap helper functions Laszlo Ersek
2017-09-13 19:24     ` Laszlo Ersek
2017-09-11 12:16 ` [PATCH v2 7/8] OvmfPkg/VirtioNetDxe: map caller-supplied Tx packet to device-address Brijesh Singh
2017-09-13 20:15   ` Laszlo Ersek
2017-09-11 12:16 ` [PATCH v2 8/8] OvmfPkg/VirtioNetDxe: negotiate VIRTIO_F_IOMMU_PLATFORM Brijesh Singh

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170911121657.34992-7-brijesh.singh@amd.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox