@param[in,out] Dev The VNET_DEV driver instance about to enter the\r
EfiSimpleNetworkInitialized state.\r
\r
- @retval EFI_OUT_OF_RESOURCES Failed to allocate RX destination area.\r
- @return Status codes from VIRTIO_CFG_WRITE().\r
+ @return Status codes from VIRTIO_CFG_WRITE() or\r
+ VIRTIO_DEVICE_PROTOCOL.AllocateSharedPages or\r
+ VirtioMapAllBytesInSharedBuffer().\r
@retval EFI_SUCCESS RX setup successful. The device is live and may\r
already be writing to the receive area.\r
*/\r
IN OUT VNET_DEV *Dev\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
+ EFI_STATUS Status;\r
+ UINTN VirtioNetReqSize;\r
+ UINTN RxBufSize;\r
+ UINT16 RxAlwaysPending;\r
+ UINTN PktIdx;\r
+ UINT16 DescIdx;\r
+ UINTN NumBytes;\r
+ EFI_PHYSICAL_ADDRESS RxBufDeviceAddress;\r
+ VOID *RxBuffer;\r
\r
//\r
// In VirtIo 1.0, the NumBuffers field is mandatory. In 0.9.5, it depends on\r
//\r
RxAlwaysPending = (UINT16) MIN (Dev->RxRing.QueueSize / 2, VNET_MAX_PENDING);\r
\r
- Dev->RxBuf = AllocatePool (RxAlwaysPending * RxBufSize);\r
- if (Dev->RxBuf == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ //\r
+ // The RxBuf is shared between guest and hypervisor, use\r
+ // AllocateSharedPages() to allocate this memory region and map it with\r
+ // BusMasterCommonBuffer so that it can be accessed by both guest and\r
+ // hypervisor.\r
+ //\r
+ NumBytes = RxAlwaysPending * RxBufSize;\r
+ Dev->RxBufNrPages = EFI_SIZE_TO_PAGES (NumBytes);\r
+ Status = Dev->VirtIo->AllocateSharedPages (\r
+ Dev->VirtIo,\r
+ Dev->RxBufNrPages,\r
+ &RxBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
}\r
\r
+ ZeroMem (RxBuffer, NumBytes);\r
+\r
+ Status = VirtioMapAllBytesInSharedBuffer (\r
+ Dev->VirtIo,\r
+ VirtioOperationBusMasterCommonBuffer,\r
+ RxBuffer,\r
+ NumBytes,\r
+ &Dev->RxBufDeviceBase,\r
+ &Dev->RxBufMap\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto FreeSharedBuffer;\r
+ }\r
+\r
+ Dev->RxBuf = RxBuffer;\r
+\r
//\r
// virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device\r
//\r
// link each chain into (from) the available ring as well\r
//\r
DescIdx = 0;\r
- RxPtr = Dev->RxBuf;\r
+ RxBufDeviceAddress = Dev->RxBufDeviceBase;\r
for (PktIdx = 0; PktIdx < RxAlwaysPending; ++PktIdx) {\r
//\r
// virtio-0.9.5, 2.4.1.2 Updating the Available Ring\r
//\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].Addr = RxBufDeviceAddress;\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
+ RxBufDeviceAddress += Dev->RxRing.Desc[DescIdx++].Len;\r
\r
- Dev->RxRing.Desc[DescIdx].Addr = (UINTN) RxPtr;\r
+ Dev->RxRing.Desc[DescIdx].Addr = RxBufDeviceAddress;\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
+ RxBufDeviceAddress += Dev->RxRing.Desc[DescIdx++].Len;\r
}\r
\r
//\r
Status = Dev->VirtIo->SetQueueNotify (Dev->VirtIo, VIRTIO_NET_Q_RX);\r
if (EFI_ERROR (Status)) {\r
Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
- FreePool (Dev->RxBuf);\r
+ goto UnmapSharedBuffer;\r
}\r
\r
return Status;\r
+\r
+UnmapSharedBuffer:\r
+ Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RxBufMap);\r
+\r
+FreeSharedBuffer:\r
+ Dev->VirtIo->FreeSharedPages (\r
+ Dev->VirtIo,\r
+ Dev->RxBufNrPages,\r
+ RxBuffer\r
+ );\r
+ return Status;\r
}\r
\r
\r
Protocol instances for virtio-net devices.\r
\r
Copyright (C) 2013, Red Hat, Inc.\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
// VirtioNetInitRing\r
UINT8 *RxBuf; // VirtioNetInitRx\r
UINT16 RxLastUsed; // VirtioNetInitRx\r
+ UINTN RxBufNrPages; // VirtioNetInitRx\r
+ EFI_PHYSICAL_ADDRESS RxBufDeviceBase; // VirtioNetInitRx\r
+ VOID *RxBufMap; // VirtioNetInitRx\r
\r
VRING TxRing; // VirtioNetInitRing\r
VOID *TxRingMap; // VirtioRingMap and\r