]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg/NvmExpressDxe: Fix wrong queue size for async IO queues
authorSean Brogan <sean.brogan@microsoft.com>
Tue, 3 Sep 2019 23:52:26 +0000 (16:52 -0700)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Wed, 20 Nov 2019 02:47:19 +0000 (02:47 +0000)
REF:https://bugzilla.tianocore.org/show_bug.cgi?id=2118

When a packet is queued/completed for the asynchronous IO queue, the logic
to roll over to the front of the queue doesn't account for actual size of
the IO Submission/Completion queue.

This causes a device to hang due to doorbell being outside of visible
queue. An example would be if an NVMe drive only supported a queue size of
128 while the driver supports 256.

Cc: Jian J Wang <jian.j.wang@intel.com>
Signed-off-by: Sean Brogan <sean.brogan@microsoft.com>
Signed-off-by: Hao A Wu <hao.a.wu@intel.com>
Acked-by: Ray Ni <ray.ni@intel.com>
MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.c
MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c

index 3bde96bc957643ea41c51d1d4b1aa5b469c45444..62886d5c91f5cf2425d6ed903d4d00aa28165123 100644 (file)
@@ -672,7 +672,7 @@ ProcessAsyncTaskList (
     }\r
 \r
     Private->CqHdbl[QueueId].Cqh++;\r
-    if (Private->CqHdbl[QueueId].Cqh > NVME_ASYNC_CCQ_SIZE) {\r
+    if (Private->CqHdbl[QueueId].Cqh > MIN (NVME_ASYNC_CCQ_SIZE, Private->Cap.Mqes)) {\r
       Private->CqHdbl[QueueId].Cqh = 0;\r
       Private->Pt[QueueId] ^= 1;\r
     }\r
index 8e721379466a03fe81c2ff736133ec529916be41..e9357b1239c72335a68df5bc8ff062eab962d61d 100644 (file)
@@ -452,6 +452,7 @@ NvmExpressPassThru (
   NVME_SQ                        *Sq;\r
   NVME_CQ                        *Cq;\r
   UINT16                         QueueId;\r
+  UINT16                         QueueSize;\r
   UINT32                         Bytes;\r
   UINT16                         Offset;\r
   EFI_EVENT                      TimerEvent;\r
@@ -540,6 +541,7 @@ NvmExpressPassThru (
   Prp         = NULL;\r
   TimerEvent  = NULL;\r
   Status      = EFI_SUCCESS;\r
+  QueueSize   = MIN (NVME_ASYNC_CSQ_SIZE, Private->Cap.Mqes) + 1;\r
 \r
   if (Packet->QueueType == NVME_ADMIN_QUEUE) {\r
     QueueId = 0;\r
@@ -552,7 +554,7 @@ NvmExpressPassThru (
       //\r
       // Submission queue full check.\r
       //\r
-      if ((Private->SqTdbl[QueueId].Sqt + 1) % (NVME_ASYNC_CSQ_SIZE + 1) ==\r
+      if ((Private->SqTdbl[QueueId].Sqt + 1) % QueueSize ==\r
           Private->AsyncSqHead) {\r
         return EFI_NOT_READY;\r
       }\r
@@ -701,7 +703,7 @@ NvmExpressPassThru (
   //\r
   if ((Event != NULL) && (QueueId != 0)) {\r
     Private->SqTdbl[QueueId].Sqt =\r
-      (Private->SqTdbl[QueueId].Sqt + 1) % (NVME_ASYNC_CSQ_SIZE + 1);\r
+      (Private->SqTdbl[QueueId].Sqt + 1) % QueueSize;\r
   } else {\r
     Private->SqTdbl[QueueId].Sqt ^= 1;\r
   }\r