OvmfPkg: Make the VirtIo devices use the new VIRTIO_DEVICE_PROTOCOL
This change replaces the accesses to the PCI bus from the Block, Scsi and Net drivers by the use of the new VIRTIO_DEVICE_PROTOCOL protocol that abstracts the transport layer. It means these drivers can be used on PCI and MMIO transport layer. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Olivier Martin <olivier.martin@arm.com> v5: - VirtioFlush(): update comment block in VirtioLib.[hc]; error code is propagated from VirtIo->SetQueueNotify(). - VirtioBlkInit(): jump to Failed label if SetPageSize() fails - VirtioBlkInit(): fixup comment, and add error handling, near SetQueueNum() call - VirtioBlkDriverBindingStart(): remove redundant (always false) check for a subsystem device ID different from VIRTIO_SUBSYSTEM_BLOCK_DEVICE; VirtioBlkDriverBindingSupported() handles it already - VirtioNetGetFeatures(): update stale comment block - VirtioNetGetFeatures(): retrieve MAC address byte for byte (open-coded loop) - VirtioNetDriverBindingStart(): remove redundant (always false) check for a subsystem device ID different from VIRTIO_SUBSYSTEM_NETWORK_CARD; VirtioNetDriverBindingSupported() handles it already - VirtioNetInitRing(): call SetQueueNum() and SetQueueAlign() for proper MMIO operation - VirtioNetInitialize(): fix destination error label for when SetPageSize() fails - VirtioScsi.c: fix comment block of VIRTIO_CFG_WRITE()/VIRTIO_CFG_READ() - VirtioScsiInit(): fix destination error label for when SetPageSize() fails - VirtioScsiInit(): call SetQueueNum() and SetQueueAlign() for proper MMIO operation Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14966 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
@@ -57,14 +57,15 @@ VirtioNetInitRing (
|
||||
//
|
||||
// step 4b -- allocate selected queue
|
||||
//
|
||||
Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueSelect, Selector);
|
||||
Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, Selector);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
Status = VIRTIO_CFG_READ (Dev, Generic.VhdrQueueSize, &QueueSize);
|
||||
Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// For each packet (RX and TX alike), we need two descriptors:
|
||||
// one for the virtio-net request header, and another one for the data
|
||||
@@ -77,14 +78,34 @@ VirtioNetInitRing (
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Additional steps for MMIO: align the queue appropriately, and set the
|
||||
// size. If anything fails from here on, we must release the ring resources.
|
||||
//
|
||||
Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ReleaseQueue;
|
||||
}
|
||||
|
||||
Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ReleaseQueue;
|
||||
}
|
||||
|
||||
//
|
||||
// step 4c -- report GPFN (guest-physical frame number) of queue
|
||||
//
|
||||
Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueAddress,
|
||||
(UINTN) Ring->Base >> EFI_PAGE_SHIFT);
|
||||
Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo,
|
||||
(UINT32)(UINTN) Ring->Base >> EFI_PAGE_SHIFT);
|
||||
if (EFI_ERROR (Status)) {
|
||||
VirtioRingUninit (Ring);
|
||||
goto ReleaseQueue;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
ReleaseQueue:
|
||||
VirtioRingUninit (Ring);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
@@ -287,10 +308,9 @@ VirtioNetInitRx (
|
||||
// virtio-0.9.5, 2.4.1.4 Notifying the Device
|
||||
//
|
||||
MemoryFence ();
|
||||
Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueNotify, VIRTIO_NET_Q_RX);
|
||||
|
||||
Status = Dev->VirtIo->SetQueueNotify (Dev->VirtIo, VIRTIO_NET_Q_RX);
|
||||
if (EFI_ERROR (Status)) {
|
||||
VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0);
|
||||
Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
|
||||
FreePool (Dev->RxBuf);
|
||||
}
|
||||
|
||||
@@ -366,13 +386,21 @@ VirtioNetInitialize (
|
||||
// virtio-0.9.5 spec, 2.2.1 Device Initialization Sequence.
|
||||
//
|
||||
NextDevStat = VSTAT_ACK; // step 2 -- acknowledge device presence
|
||||
Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);
|
||||
Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto InitFailed;
|
||||
}
|
||||
|
||||
NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it
|
||||
Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);
|
||||
Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto DeviceFailed;
|
||||
}
|
||||
|
||||
//
|
||||
// Set Page Size - MMIO VirtIo Specific
|
||||
//
|
||||
Status = Dev->VirtIo->SetPageSize (Dev->VirtIo, EFI_PAGE_SIZE);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto DeviceFailed;
|
||||
}
|
||||
@@ -381,10 +409,11 @@ VirtioNetInitialize (
|
||||
// step 4a -- retrieve features. Note that we're past validating required
|
||||
// features in VirtioNetGetFeatures().
|
||||
//
|
||||
Status = VIRTIO_CFG_READ (Dev, Generic.VhdrDeviceFeatureBits, &Features);
|
||||
Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto DeviceFailed;
|
||||
}
|
||||
|
||||
ASSERT (Features & VIRTIO_NET_F_MAC);
|
||||
ASSERT (Dev->Snm.MediaPresentSupported ==
|
||||
!!(Features & VIRTIO_NET_F_STATUS));
|
||||
@@ -406,7 +435,7 @@ VirtioNetInitialize (
|
||||
// step 5 -- keep only the features we want
|
||||
//
|
||||
Features &= VIRTIO_NET_F_MAC | VIRTIO_NET_F_STATUS;
|
||||
Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrGuestFeatureBits, Features);
|
||||
Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ReleaseTxRing;
|
||||
}
|
||||
@@ -415,7 +444,7 @@ VirtioNetInitialize (
|
||||
// step 6 -- virtio-net initialization complete
|
||||
//
|
||||
NextDevStat |= VSTAT_DRIVER_OK;
|
||||
Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);
|
||||
Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ReleaseTxRing;
|
||||
}
|
||||
@@ -441,7 +470,7 @@ ReleaseTxAux:
|
||||
VirtioNetShutdownTx (Dev);
|
||||
|
||||
AbortDevice:
|
||||
VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0);
|
||||
Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
|
||||
|
||||
ReleaseTxRing:
|
||||
VirtioRingUninit (&Dev->TxRing);
|
||||
@@ -453,7 +482,7 @@ DeviceFailed:
|
||||
//
|
||||
// restore device status invariant for the EfiSimpleNetworkStarted state
|
||||
//
|
||||
VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0);
|
||||
Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
|
||||
|
||||
InitFailed:
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
Reference in New Issue
Block a user