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 <jiangdongxu1@huawei.com>
---
 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