From 05de598734e741c596394bfbe42b1ab7af8316e1 Mon Sep 17 00:00:00 2001 From: Adttil <2429917001@qq.com> Date: Fri, 29 Nov 2024 08:46:00 +0800 Subject: [PATCH 2/3] Virtio: wait virtio device reset done. The Virtio 1.0 driver performs subsequent negotiation operations only after the device reset operation is complete. Implement this in the VirtioScsiDxe and VirtioBlkDxe. Signed-off-by: jiangdongxu --- OvmfPkg/VirtioBlkDxe/VirtioBlk.c | 21 +++++++++++++++++++++ OvmfPkg/VirtioScsiDxe/VirtioScsi.c | 21 +++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c index 74ed52f9..eed56994 100644 --- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c +++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c @@ -28,6 +28,9 @@ #include "VirtioBlk.h" +#define MAX_RETRY_TIMES 1000 +#define DEVICE_WAIT_INTVL 1000 + /** Convenience macros to read and write region 0 IO space elements of the @@ -721,6 +724,10 @@ VirtioBlkInit ( UINT32 OptIoSize; UINT16 QueueSize; UINT64 RingBaseShift; + UINT8 DevStat; + UINT16 RetryTimes; + + RetryTimes = MAX_RETRY_TIMES; PhysicalBlockExp = 0; AlignmentOffset = 0; @@ -735,12 +742,26 @@ VirtioBlkInit ( goto Failed; } + Status = Dev->VirtIo->GetDeviceStatus (Dev->VirtIo, &DevStat); + while (DevStat != NextDevStat && RetryTimes) { + gBS->Stall(DEVICE_WAIT_INTVL); + Status = Dev->VirtIo->GetDeviceStatus (Dev->VirtIo, &DevStat); + RetryTimes--; + } + NextDevStat |= VSTAT_ACK; // step 2 -- acknowledge device presence Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); if (EFI_ERROR (Status)) { goto Failed; } + Status = Dev->VirtIo->GetDeviceStatus (Dev->VirtIo, &DevStat); + while (DevStat != NextDevStat && RetryTimes) { + gBS->Stall(DEVICE_WAIT_INTVL); + Status = Dev->VirtIo->GetDeviceStatus (Dev->VirtIo, &DevStat); + RetryTimes--; + } + NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); if (EFI_ERROR (Status)) { diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c index 3705f5fc..580fe731 100644 --- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c +++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c @@ -43,6 +43,9 @@ #include "VirtioScsi.h" +#define MAX_RETRY_TIMES 1000 +#define DEVICE_WAIT_INTVL 1000 + /** Convenience macros to read and write configuration elements of the @@ -932,6 +935,10 @@ VirtioScsiInit ( UINT16 MaxChannel; // for validation only UINT32 NumQueues; // for validation only UINT16 QueueSize; + UINT8 DevStat; + UINT16 RetryTimes; + + RetryTimes = MAX_RETRY_TIMES; // // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence. @@ -942,12 +949,26 @@ VirtioScsiInit ( goto Failed; } + Status = Dev->VirtIo->GetDeviceStatus (Dev->VirtIo, &DevStat); + while (DevStat != NextDevStat && RetryTimes) { + gBS->Stall(DEVICE_WAIT_INTVL); + Status = Dev->VirtIo->GetDeviceStatus (Dev->VirtIo, &DevStat); + RetryTimes--; + } + NextDevStat |= VSTAT_ACK; // step 2 -- acknowledge device presence Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); if (EFI_ERROR (Status)) { goto Failed; } + Status = Dev->VirtIo->GetDeviceStatus (Dev->VirtIo, &DevStat); + while (DevStat != NextDevStat && RetryTimes) { + gBS->Stall(DEVICE_WAIT_INTVL); + Status = Dev->VirtIo->GetDeviceStatus (Dev->VirtIo, &DevStat); + RetryTimes--; + } + NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); if (EFI_ERROR (Status)) { -- 2.43.0