On 09/11/17 14:16, Brijesh Singh wrote:
> Each network packet is submitted for transmission by pushing the head
> descriptor of a two-part descriptor chain to the Available Ring of the
> TX queue. VirtioNetInitTx() sets up the the descriptor chains for all
> queueable packets in advance, and points all the head descriptors to the
> same shared, never modified, VIRTIO_1_0_NET_REQ header object (or its
> initial VIRTIO_NET_REQ sub-object, dependent on virtio version).
> VirtioNetInitTx() currently uses the header object's system physical
> address for populating the head descriptors.
> 
> When device is behind the IOMMU, VirtioNet driver is required to provide
> the device address of VIRTIO_1_0_NET_REQ header. In this patch we
> dynamically allocate the header using AllocateSharedPages() and map with
> BusMasterCommonBuffer so that header can be accessed by both processor
> and the device.
> 
> We map the header object for CommonBuffer operation because, in order to
> stick with the current code order, we populate the head descriptors with
> the header's device address first, and fill in the header itself second.
> 
> Cc: Ard Biesheuvel <[email protected]>
> Cc: Jordan Justen <[email protected]>
> Cc: Tom Lendacky <[email protected]>
> Cc: Laszlo Ersek <[email protected]>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Brijesh Singh <[email protected]>
> ---
>  OvmfPkg/VirtioNetDxe/VirtioNet.h        |  3 +-
>  OvmfPkg/VirtioNetDxe/SnpInitialize.c    | 64 +++++++++++++++++---
>  OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c |  7 +++
>  3 files changed, 65 insertions(+), 9 deletions(-)
> 
> diff --git a/OvmfPkg/VirtioNetDxe/VirtioNet.h 
> b/OvmfPkg/VirtioNetDxe/VirtioNet.h
> index 7d5f33b01dc8..3f48bcc6b67c 100644
> --- a/OvmfPkg/VirtioNetDxe/VirtioNet.h
> +++ b/OvmfPkg/VirtioNetDxe/VirtioNet.h
> @@ -96,7 +96,8 @@ typedef struct {
>    UINT16                      TxMaxPending;      // VirtioNetInitTx
>    UINT16                      TxCurPending;      // VirtioNetInitTx
>    UINT16                      *TxFreeStack;      // VirtioNetInitTx
> -  VIRTIO_1_0_NET_REQ          TxSharedReq;       // VirtioNetInitTx
> +  VIRTIO_1_0_NET_REQ          *TxSharedReq;      // VirtioNetInitTx
> +  VOID                        *TxSharedReqMap;   // VirtioNetInitTx
>    UINT16                      TxLastUsed;        // VirtioNetInitTx
>    EFI_PHYSICAL_ADDRESS        RxBufDeviceBase;   // VirtioNetInitRx
>  } VNET_DEV;
> diff --git a/OvmfPkg/VirtioNetDxe/SnpInitialize.c 
> b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
> index 54c808c501bf..6cedb406a172 100644
> --- a/OvmfPkg/VirtioNetDxe/SnpInitialize.c
> +++ b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
> @@ -18,6 +18,7 @@
>  **/
>  
>  #include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
>  #include <Library/MemoryAllocationLib.h>
>  #include <Library/UefiBootServicesTableLib.h>
>  
> @@ -147,6 +148,9 @@ ReleaseQueue:
>  
>    @retval EFI_OUT_OF_RESOURCES  Failed to allocate the stack to track the 
> heads
>                                  of free descriptor chains.
> +  @return                       Status codes from VIRTIO_DEVICE_PROTOCOL.
> +                                AllocateSharedPages() or
> +                                VirtioMapAllBytesInSharedBuffer()
>    @retval EFI_SUCCESS           TX setup successful.
>  */
>  
> @@ -157,8 +161,11 @@ VirtioNetInitTx (
>    IN OUT VNET_DEV *Dev
>    )
>  {
> -  UINTN TxSharedReqSize;
> -  UINTN PktIdx;
> +  UINTN                 TxSharedReqSize;
> +  UINTN                 PktIdx;
> +  EFI_STATUS            Status;
> +  EFI_PHYSICAL_ADDRESS  DeviceAddress;
> +  VOID                  *TxSharedReqBuffer;
>  
>    Dev->TxMaxPending = (UINT16) MIN (Dev->TxRing.QueueSize / 2,
>                                   VNET_MAX_PENDING);
> @@ -170,12 +177,42 @@ VirtioNetInitTx (
>    }
>  
>    //
> +  // Allocate TxSharedReq header and map with BusMasterCommonBuffer so that 
> it
> +  // can be accessed equally by both processor and device.
> +  //
> +  Status = Dev->VirtIo->AllocateSharedPages (
> +                          Dev->VirtIo,
> +                          EFI_SIZE_TO_PAGES (sizeof *Dev->TxSharedReq),
> +                          &TxSharedReqBuffer
> +                          );
> +  if (EFI_ERROR (Status)) {
> +    goto FreeTxFreeStack;
> +  }
> +
> +  ZeroMem (TxSharedReqBuffer, sizeof *Dev->TxSharedReq);
> +
> +  Status = VirtioMapAllBytesInSharedBuffer (
> +             Dev->VirtIo,
> +             VirtioOperationBusMasterCommonBuffer,
> +             TxSharedReqBuffer,
> +             sizeof *(Dev->TxSharedReq),
> +             &DeviceAddress,
> +             &Dev->TxSharedReqMap
> +             );
> +  if (EFI_ERROR (Status)) {
> +    goto FreeTxSharedReqBuffer;
> +  }
> +
> +  Dev->TxSharedReq = TxSharedReqBuffer;
> +
> +
> +  //
>    // In VirtIo 1.0, the NumBuffers field is mandatory. In 0.9.5, it depends 
> on
>    // VIRTIO_NET_F_MRG_RXBUF, which we never negotiate.
>    //
>    TxSharedReqSize = (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) 
> ?
> -                    sizeof Dev->TxSharedReq.V0_9_5 :
> -                    sizeof Dev->TxSharedReq;
> +                    sizeof (Dev->TxSharedReq->V0_9_5) :
> +                    sizeof *Dev->TxSharedReq;
>  
>    for (PktIdx = 0; PktIdx < Dev->TxMaxPending; ++PktIdx) {
>      UINT16 DescIdx;
> @@ -187,7 +224,7 @@ VirtioNetInitTx (
>      // For each possibly pending packet, lay out the descriptor for the 
> common
>      // (unmodified by the host) virtio-net request header.
>      //
> -    Dev->TxRing.Desc[DescIdx].Addr  = (UINTN) &Dev->TxSharedReq;
> +    Dev->TxRing.Desc[DescIdx].Addr  = DeviceAddress;
>      Dev->TxRing.Desc[DescIdx].Len   = (UINT32) TxSharedReqSize;
>      Dev->TxRing.Desc[DescIdx].Flags = VRING_DESC_F_NEXT;
>      Dev->TxRing.Desc[DescIdx].Next  = (UINT16) (DescIdx + 1);
> @@ -202,13 +239,13 @@ VirtioNetInitTx (
>    //
>    // virtio-0.9.5, Appendix C, Packet Transmission
>    //
> -  Dev->TxSharedReq.V0_9_5.Flags   = 0;
> -  Dev->TxSharedReq.V0_9_5.GsoType = VIRTIO_NET_HDR_GSO_NONE;
> +  Dev->TxSharedReq->V0_9_5.Flags   = 0;
> +  Dev->TxSharedReq->V0_9_5.GsoType = VIRTIO_NET_HDR_GSO_NONE;
>  
>    //
>    // For VirtIo 1.0 only -- the field exists, but it is unused
>    //
> -  Dev->TxSharedReq.NumBuffers = 0;
> +  Dev->TxSharedReq->NumBuffers = 0;
>  
>    //
>    // virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device
> @@ -223,6 +260,17 @@ VirtioNetInitTx (
>    *Dev->TxRing.Avail.Flags = (UINT16) VRING_AVAIL_F_NO_INTERRUPT;
>  
>    return EFI_SUCCESS;
> +
> +FreeTxSharedReqBuffer:
> +  Dev->VirtIo->FreeSharedPages (
> +                 Dev->VirtIo,
> +                 EFI_SIZE_TO_PAGES (sizeof *(Dev->TxSharedReq)),
> +                 TxSharedReqBuffer
> +                 );
> +FreeTxFreeStack:
> +  FreePool (Dev->TxFreeStack);
> +
> +  return Status;
>  }
>  
>  
> diff --git a/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c 
> b/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
> index ee4f9ed36ecd..2ec3dc385a9f 100644
> --- a/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
> +++ b/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
> @@ -54,6 +54,13 @@ VirtioNetShutdownTx (
>    IN OUT VNET_DEV *Dev
>    )
>  {
> +  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->TxSharedReqMap);
> +  Dev->VirtIo->FreeSharedPages (
> +                 Dev->VirtIo,
> +                 EFI_SIZE_TO_PAGES (sizeof *(Dev->TxSharedReq)),
> +                 (VOID *) Dev->TxSharedReq
> +                 );
> +
>    FreePool (Dev->TxFreeStack);
>  }
>  
> 

(1) Regarding the last argument of FreeSharedPages(), from my previous
review at

[email protected]">http://mid.mail-archive.com/[email protected]

you missed:

On 09/06/17 11:11, Laszlo Ersek wrote:
> (18) The (VOID*) cast is unneeded.

The rest is good.

Thanks!
Laszlo
_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to