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>
OUT VOID **TxBuf OPTIONAL\r
)\r
{\r
OUT VOID **TxBuf OPTIONAL\r
)\r
{\r
- VNET_DEV *Dev;\r
- EFI_TPL OldTpl;\r
- EFI_STATUS Status;\r
- UINT16 RxCurUsed;\r
- UINT16 TxCurUsed;\r
+ VNET_DEV *Dev;\r
+ EFI_TPL OldTpl;\r
+ EFI_STATUS Status;\r
+ UINT16 RxCurUsed;\r
+ UINT16 TxCurUsed;\r
+ EFI_PHYSICAL_ADDRESS DeviceAddress;\r
\r
if (This == NULL) {\r
return EFI_INVALID_PARAMETER;\r
\r
if (This == NULL) {\r
return EFI_INVALID_PARAMETER;\r
ASSERT (DescIdx < (UINT32) (2 * Dev->TxMaxPending - 1));\r
\r
//\r
ASSERT (DescIdx < (UINT32) (2 * Dev->TxMaxPending - 1));\r
\r
//\r
- // report buffer address to caller that has been enqueued by caller\r
+ // get the device address that has been enqueued for the caller's\r
+ // transmit buffer\r
- *TxBuf = (VOID *)(UINTN) Dev->TxRing.Desc[DescIdx + 1].Addr;\r
+ DeviceAddress = Dev->TxRing.Desc[DescIdx + 1].Addr;\r
\r
//\r
// now this descriptor can be used again to enqueue a transmit buffer\r
//\r
Dev->TxFreeStack[--Dev->TxCurPending] = (UINT16) DescIdx;\r
\r
//\r
// now this descriptor can be used again to enqueue a transmit buffer\r
//\r
Dev->TxFreeStack[--Dev->TxCurPending] = (UINT16) DescIdx;\r
+\r
+ //\r
+ // Unmap the device address and perform the reverse mapping to find the\r
+ // caller buffer address.\r
+ //\r
+ Status = VirtioNetUnmapTxBuf (\r
+ Dev,\r
+ TxBuf,\r
+ DeviceAddress\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // VirtioNetUnmapTxBuf should never fail, if we have reached here\r
+ // that means our internal state has been corrupted\r
+ //\r
+ ASSERT (FALSE);\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
IN UINT16 *Protocol OPTIONAL\r
)\r
{\r
IN UINT16 *Protocol OPTIONAL\r
)\r
{\r
- VNET_DEV *Dev;\r
- EFI_TPL OldTpl;\r
- EFI_STATUS Status;\r
- UINT16 DescIdx;\r
- UINT16 AvailIdx;\r
+ VNET_DEV *Dev;\r
+ EFI_TPL OldTpl;\r
+ EFI_STATUS Status;\r
+ UINT16 DescIdx;\r
+ UINT16 AvailIdx;\r
+ EFI_PHYSICAL_ADDRESS DeviceAddress;\r
\r
if (This == NULL || BufferSize == 0 || Buffer == NULL) {\r
return EFI_INVALID_PARAMETER;\r
\r
if (This == NULL || BufferSize == 0 || Buffer == NULL) {\r
return EFI_INVALID_PARAMETER;\r
ASSERT ((UINTN) (Ptr - (UINT8 *) Buffer) == Dev->Snm.MediaHeaderSize);\r
}\r
\r
ASSERT ((UINTN) (Ptr - (UINT8 *) Buffer) == Dev->Snm.MediaHeaderSize);\r
}\r
\r
+ //\r
+ // Map the transmit buffer system physical address to device address.\r
+ //\r
+ Status = VirtioNetMapTxBuf (\r
+ Dev,\r
+ Buffer,\r
+ BufferSize,\r
+ &DeviceAddress\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
//\r
// virtio-0.9.5, 2.4.1 Supplying Buffers to The Device\r
//\r
DescIdx = Dev->TxFreeStack[Dev->TxCurPending++];\r
//\r
// virtio-0.9.5, 2.4.1 Supplying Buffers to The Device\r
//\r
DescIdx = Dev->TxFreeStack[Dev->TxCurPending++];\r
- Dev->TxRing.Desc[DescIdx + 1].Addr = (UINTN) Buffer;\r
+ Dev->TxRing.Desc[DescIdx + 1].Addr = DeviceAddress;\r
Dev->TxRing.Desc[DescIdx + 1].Len = (UINT32) BufferSize;\r
\r
//\r
Dev->TxRing.Desc[DescIdx + 1].Len = (UINT32) BufferSize;\r
\r
//\r