The Maximum Queue Entries Supported (MQES) field in the CAP (Controller
Capabilities) register for a NVMe controller restrict the maximum
individual queue size that the controller supports.

The origin code does not check this value and always uses a hardcode value
when creating I/O submission/completion queues for asynchronous
transmission. The hardcode value might be larger than the MQES field, this
will lead to an 'Invalid Queue Size' error when creating I/O
submission/completion queues.

The patch will add checks to make sure proper queue size is passed when
creating I/O submission/completion queues.

Cc: Feng Tian <feng.t...@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Hao Wu <hao.a...@intel.com>
---
 MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.c | 26 ++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.c 
b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.c
index 4f83a92..a173504 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.c
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.c
@@ -683,6 +683,7 @@ NvmeCreateIoCompletionQueue (
   EFI_STATUS                               Status;
   NVME_ADMIN_CRIOCQ                        CrIoCq;
   UINT32                                   Index;
+  UINT16                                   QueueSize;
 
   Status = EFI_SUCCESS;
 
@@ -701,8 +702,18 @@ NvmeCreateIoCompletionQueue (
     CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
     CommandPacket.QueueType      = NVME_ADMIN_QUEUE;
 
+    if (Index == 1) {
+      QueueSize = NVME_CCQ_SIZE;
+    } else {
+      if (Private->Cap.Mqes > NVME_ASYNC_CCQ_SIZE) {
+        QueueSize = NVME_ASYNC_CCQ_SIZE;
+      } else {
+        QueueSize = Private->Cap.Mqes;
+      }
+    }
+
     CrIoCq.Qid   = Index;
-    CrIoCq.Qsize = (Index == 1) ? NVME_CCQ_SIZE : NVME_ASYNC_CCQ_SIZE;
+    CrIoCq.Qsize = QueueSize;
     CrIoCq.Pc    = 1;
     CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoCq, sizeof 
(NVME_ADMIN_CRIOCQ));
     CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
@@ -741,6 +752,7 @@ NvmeCreateIoSubmissionQueue (
   EFI_STATUS                               Status;
   NVME_ADMIN_CRIOSQ                        CrIoSq;
   UINT32                                   Index;
+  UINT16                                   QueueSize;
 
   Status = EFI_SUCCESS;
 
@@ -759,8 +771,18 @@ NvmeCreateIoSubmissionQueue (
     CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
     CommandPacket.QueueType      = NVME_ADMIN_QUEUE;
 
+    if (Index == 1) {
+      QueueSize = NVME_CSQ_SIZE;
+    } else {
+      if (Private->Cap.Mqes > NVME_ASYNC_CSQ_SIZE) {
+        QueueSize = NVME_ASYNC_CSQ_SIZE;
+      } else {
+        QueueSize = Private->Cap.Mqes;
+      }
+    }
+
     CrIoSq.Qid   = Index;
-    CrIoSq.Qsize = (Index == 1) ? NVME_CSQ_SIZE : NVME_ASYNC_CSQ_SIZE;
+    CrIoSq.Qsize = QueueSize;
     CrIoSq.Pc    = 1;
     CrIoSq.Cqid  = Index;
     CrIoSq.Qprio = 0;
-- 
1.9.5.msysgit.0

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to