When device is behind the IOMMU then driver need to pass the device
address when programing the bus master. The patch uses VirtioRingMap() to
map the VRING system physical address[es] to device address[es].
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>
the network device.\r
@param[out] Ring The virtio-ring inside the VNET_DEV structure,\r
corresponding to Selector.\r
the network device.\r
@param[out] Ring The virtio-ring inside the VNET_DEV structure,\r
corresponding to Selector.\r
+ @param[out] Mapping A resulting token to pass to VirtioNetUninitRing()\r
\r
@retval EFI_UNSUPPORTED The queue size reported by the virtio-net device is\r
too small.\r
@return Status codes from VIRTIO_CFG_WRITE(),\r
\r
@retval EFI_UNSUPPORTED The queue size reported by the virtio-net device is\r
too small.\r
@return Status codes from VIRTIO_CFG_WRITE(),\r
- VIRTIO_CFG_READ() and VirtioRingInit().\r
+ VIRTIO_CFG_READ(), VirtioRingInit() and\r
+ VirtioRingMap().\r
@retval EFI_SUCCESS Ring initialized.\r
*/\r
\r
@retval EFI_SUCCESS Ring initialized.\r
*/\r
\r
VirtioNetInitRing (\r
IN OUT VNET_DEV *Dev,\r
IN UINT16 Selector,\r
VirtioNetInitRing (\r
IN OUT VNET_DEV *Dev,\r
IN UINT16 Selector,\r
+ OUT VRING *Ring,\r
+ OUT VOID **Mapping\r
)\r
{\r
EFI_STATUS Status;\r
UINT16 QueueSize;\r
)\r
{\r
EFI_STATUS Status;\r
UINT16 QueueSize;\r
+ UINT64 RingBaseShift;\r
+ VOID *MapInfo;\r
\r
//\r
// step 4b -- allocate selected queue\r
\r
//\r
// step 4b -- allocate selected queue\r
+ //\r
+ // If anything fails from here on, we must release the ring resources.\r
+ //\r
+ Status = VirtioRingMap (Dev->VirtIo, Ring, &RingBaseShift, &MapInfo);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ReleaseQueue;\r
+ }\r
+\r
//\r
// Additional steps for MMIO: align the queue appropriately, and set the\r
//\r
// Additional steps for MMIO: align the queue appropriately, and set the\r
- // size. If anything fails from here on, we must release the ring resources.\r
+ // size. If anything fails from here on, we must unmap the ring resources.\r
//\r
Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);\r
if (EFI_ERROR (Status)) {\r
//\r
Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);\r
if (EFI_ERROR (Status)) {\r
}\r
\r
Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE);\r
if (EFI_ERROR (Status)) {\r
}\r
\r
Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE);\r
if (EFI_ERROR (Status)) {\r
}\r
\r
//\r
// step 4c -- report GPFN (guest-physical frame number) of queue\r
//\r
}\r
\r
//\r
// step 4c -- report GPFN (guest-physical frame number) of queue\r
//\r
- Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, Ring, 0);\r
+ Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, Ring, RingBaseShift);\r
if (EFI_ERROR (Status)) {\r
if (EFI_ERROR (Status)) {\r
+ *Mapping = MapInfo;\r
+\r
+UnmapQueue:\r
+ Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, MapInfo);\r
+\r
ReleaseQueue:\r
VirtioRingUninit (Dev->VirtIo, Ring);\r
\r
ReleaseQueue:\r
VirtioRingUninit (Dev->VirtIo, Ring);\r
\r
//\r
// step 4b, 4c -- allocate and report virtqueues\r
//\r
//\r
// step 4b, 4c -- allocate and report virtqueues\r
//\r
- Status = VirtioNetInitRing (Dev, VIRTIO_NET_Q_RX, &Dev->RxRing);\r
+ Status = VirtioNetInitRing (\r
+ Dev,\r
+ VIRTIO_NET_Q_RX,\r
+ &Dev->RxRing,\r
+ &Dev->RxRingMap\r
+ );\r
if (EFI_ERROR (Status)) {\r
goto DeviceFailed;\r
}\r
\r
if (EFI_ERROR (Status)) {\r
goto DeviceFailed;\r
}\r
\r
- Status = VirtioNetInitRing (Dev, VIRTIO_NET_Q_TX, &Dev->TxRing);\r
+ Status = VirtioNetInitRing (\r
+ Dev,\r
+ VIRTIO_NET_Q_TX,\r
+ &Dev->TxRing,\r
+ &Dev->TxRingMap\r
+ );\r
if (EFI_ERROR (Status)) {\r
goto ReleaseRxRing;\r
}\r
if (EFI_ERROR (Status)) {\r
goto ReleaseRxRing;\r
}\r
Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
\r
ReleaseTxRing:\r
Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
\r
ReleaseTxRing:\r
- VirtioNetUninitRing (Dev, &Dev->TxRing);\r
+ VirtioNetUninitRing (Dev, &Dev->TxRing, Dev->TxRingMap);\r
- VirtioNetUninitRing (Dev, &Dev->RxRing);\r
+ VirtioNetUninitRing (Dev, &Dev->RxRing, Dev->RxRingMap);\r
/**\r
Release TX and RX VRING resources.\r
\r
/**\r
Release TX and RX VRING resources.\r
\r
- @param[in,out] Dev The VNET_DEV driver instance which was using the ring.\r
- @param[in,out] Ring The virtio ring to clean up.\r
+ @param[in,out] Dev The VNET_DEV driver instance which was using\r
+ the ring.\r
+ @param[in,out] Ring The virtio ring to clean up.\r
+ @param[in] RingMap A token return from the VirtioRingMap()\r
*/\r
VOID\r
EFIAPI\r
VirtioNetUninitRing (\r
IN OUT VNET_DEV *Dev,\r
*/\r
VOID\r
EFIAPI\r
VirtioNetUninitRing (\r
IN OUT VNET_DEV *Dev,\r
+ IN OUT VRING *Ring,\r
+ IN VOID *RingMap\r
+ Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, RingMap);\r
VirtioRingUninit (Dev->VirtIo, Ring);\r
}\r
VirtioRingUninit (Dev->VirtIo, Ring);\r
}\r
Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
VirtioNetShutdownRx (Dev);\r
VirtioNetShutdownTx (Dev);\r
Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
VirtioNetShutdownRx (Dev);\r
VirtioNetShutdownTx (Dev);\r
- VirtioNetUninitRing (Dev, &Dev->TxRing);\r
- VirtioNetUninitRing (Dev, &Dev->RxRing);\r
+ VirtioNetUninitRing (Dev, &Dev->TxRing, Dev->TxRingMap);\r
+ VirtioNetUninitRing (Dev, &Dev->RxRing, Dev->RxRingMap);\r
\r
Dev->Snm.State = EfiSimpleNetworkStarted;\r
Status = EFI_SUCCESS;\r
\r
Dev->Snm.State = EfiSimpleNetworkStarted;\r
Status = EFI_SUCCESS;\r
VirtioNetInitialize | | VirtioNetShutdown\r
VirtioNetInitRing {Rx, Tx} | | VirtioNetShutdownRx [SnpSharedHelpers.c]\r
VirtioRingInit | | VirtioNetShutdownTx [SnpSharedHelpers.c]\r
VirtioNetInitialize | | VirtioNetShutdown\r
VirtioNetInitRing {Rx, Tx} | | VirtioNetShutdownRx [SnpSharedHelpers.c]\r
VirtioRingInit | | VirtioNetShutdownTx [SnpSharedHelpers.c]\r
- VirtioNetInitTx | | VirtioNetUninitRing [SnpSharedHelpers.c]\r
- VirtioNetInitRx | | {Tx, Rx}\r
+ VirtioRingMap | | VirtioNetUninitRing [SnpSharedHelpers.c]\r
+ VirtioNetInitTx | | {Tx, Rx}\r
+ VirtioNetInitRx | | VirtIo->UnmapSharedBuffer\r
| | VirtioRingUninit\r
v |\r
+-----------------------------+\r
| | VirtioRingUninit\r
v |\r
+-----------------------------+\r
EFI_HANDLE MacHandle; // VirtioNetDriverBindingStart\r
\r
VRING RxRing; // VirtioNetInitRing\r
EFI_HANDLE MacHandle; // VirtioNetDriverBindingStart\r
\r
VRING RxRing; // VirtioNetInitRing\r
+ VOID *RxRingMap; // VirtioRingMap and\r
+ // VirtioNetInitRing\r
UINT8 *RxBuf; // VirtioNetInitRx\r
UINT16 RxLastUsed; // VirtioNetInitRx\r
\r
VRING TxRing; // VirtioNetInitRing\r
UINT8 *RxBuf; // VirtioNetInitRx\r
UINT16 RxLastUsed; // VirtioNetInitRx\r
\r
VRING TxRing; // VirtioNetInitRing\r
+ VOID *TxRingMap; // VirtioRingMap and\r
+ // VirtioNetInitRing\r
UINT16 TxMaxPending; // VirtioNetInitTx\r
UINT16 TxCurPending; // VirtioNetInitTx\r
UINT16 *TxFreeStack; // VirtioNetInitTx\r
UINT16 TxMaxPending; // VirtioNetInitTx\r
UINT16 TxCurPending; // VirtioNetInitTx\r
UINT16 *TxFreeStack; // VirtioNetInitTx\r
EFIAPI\r
VirtioNetUninitRing (\r
IN OUT VNET_DEV *Dev,\r
EFIAPI\r
VirtioNetUninitRing (\r
IN OUT VNET_DEV *Dev,\r
+ IN OUT VRING *Ring,\r
+ IN VOID *RingMap\r