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

@ -61,11 +61,12 @@ VirtioNetGetStatus (
OUT VOID **TxBuf OPTIONAL
)
{
VNET_DEV *Dev;
EFI_TPL OldTpl;
EFI_STATUS Status;
UINT16 RxCurUsed;
UINT16 TxCurUsed;
VNET_DEV *Dev;
EFI_TPL OldTpl;
EFI_STATUS Status;
UINT16 RxCurUsed;
UINT16 TxCurUsed;
EFI_PHYSICAL_ADDRESS DeviceAddress;
if (This == NULL) {
return EFI_INVALID_PARAMETER;
@ -141,14 +142,34 @@ VirtioNetGetStatus (
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
//
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

@ -73,11 +73,12 @@ VirtioNetTransmit (
IN UINT16 *Protocol OPTIONAL
)
{
VNET_DEV *Dev;
EFI_TPL OldTpl;
EFI_STATUS Status;
UINT16 DescIdx;
UINT16 AvailIdx;
VNET_DEV *Dev;
EFI_TPL OldTpl;
EFI_STATUS Status;
UINT16 DescIdx;
UINT16 AvailIdx;
EFI_PHYSICAL_ADDRESS DeviceAddress;
if (This == NULL || BufferSize == 0 || Buffer == NULL) {
return EFI_INVALID_PARAMETER;
@ -143,11 +144,25 @@ VirtioNetTransmit (
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
//
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;
//