OvmfPkg/VirtioNetDxe: map caller-supplied Tx packet to device-address

When device is behind the IOMMU, driver is require to pass the device
address of caller-supplied transmit buffer for the bus master operations.

The patch uses VirtioNetMapTxBuf() to map caller-supplied Tx packet to a
device-address and enqueue the device address in VRING for transfer and
perform the reverse mapping when transfer is completed so that we can
return the caller-supplied buffer.

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>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
This commit is contained in:
Brijesh Singh 2017-09-14 16:22:46 -05:00 committed by Laszlo Ersek
parent bd114d9f77
commit 8fa54a8a94
2 changed files with 49 additions and 13 deletions

View File

@ -66,6 +66,7 @@ VirtioNetGetStatus (
EFI_STATUS Status; EFI_STATUS Status;
UINT16 RxCurUsed; UINT16 RxCurUsed;
UINT16 TxCurUsed; UINT16 TxCurUsed;
EFI_PHYSICAL_ADDRESS DeviceAddress;
if (This == NULL) { if (This == NULL) {
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
@ -141,14 +142,34 @@ VirtioNetGetStatus (
ASSERT (DescIdx < (UINT32) (2 * Dev->TxMaxPending - 1)); ASSERT (DescIdx < (UINT32) (2 * Dev->TxMaxPending - 1));
// //
// report buffer address to caller that has been enqueued by caller // get the device address that has been enqueued for the caller's
// transmit buffer
// //
*TxBuf = (VOID *)(UINTN) Dev->TxRing.Desc[DescIdx + 1].Addr; DeviceAddress = Dev->TxRing.Desc[DescIdx + 1].Addr;
// //
// now this descriptor can be used again to enqueue a transmit buffer // now this descriptor can be used again to enqueue a transmit buffer
// //
Dev->TxFreeStack[--Dev->TxCurPending] = (UINT16) DescIdx; Dev->TxFreeStack[--Dev->TxCurPending] = (UINT16) DescIdx;
//
// Unmap the device address and perform the reverse mapping to find the
// caller buffer address.
//
Status = VirtioNetUnmapTxBuf (
Dev,
TxBuf,
DeviceAddress
);
if (EFI_ERROR (Status)) {
//
// VirtioNetUnmapTxBuf should never fail, if we have reached here
// that means our internal state has been corrupted
//
ASSERT (FALSE);
Status = EFI_DEVICE_ERROR;
goto Exit;
}
} }
} }

View File

@ -78,6 +78,7 @@ VirtioNetTransmit (
EFI_STATUS Status; EFI_STATUS Status;
UINT16 DescIdx; UINT16 DescIdx;
UINT16 AvailIdx; UINT16 AvailIdx;
EFI_PHYSICAL_ADDRESS DeviceAddress;
if (This == NULL || BufferSize == 0 || Buffer == NULL) { if (This == NULL || BufferSize == 0 || Buffer == NULL) {
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
@ -143,11 +144,25 @@ VirtioNetTransmit (
ASSERT ((UINTN) (Ptr - (UINT8 *) Buffer) == Dev->Snm.MediaHeaderSize); ASSERT ((UINTN) (Ptr - (UINT8 *) Buffer) == Dev->Snm.MediaHeaderSize);
} }
//
// Map the transmit buffer system physical address to device address.
//
Status = VirtioNetMapTxBuf (
Dev,
Buffer,
BufferSize,
&DeviceAddress
);
if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
goto Exit;
}
// //
// virtio-0.9.5, 2.4.1 Supplying Buffers to The Device // virtio-0.9.5, 2.4.1 Supplying Buffers to The Device
// //
DescIdx = Dev->TxFreeStack[Dev->TxCurPending++]; DescIdx = Dev->TxFreeStack[Dev->TxCurPending++];
Dev->TxRing.Desc[DescIdx + 1].Addr = (UINTN) Buffer; Dev->TxRing.Desc[DescIdx + 1].Addr = DeviceAddress;
Dev->TxRing.Desc[DescIdx + 1].Len = (UINT32) BufferSize; Dev->TxRing.Desc[DescIdx + 1].Len = (UINT32) BufferSize;
// //