]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.c
MdeModulePkg NvmExpressDxe: Add BlockIo2 support
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / NvmExpressDxe / NvmExpressHci.c
index e2201b9cef3b08fe4a5aff69704769f6af9c8bf4..dcfe1e865de569395434a4ec82ce17939b7d536e 100644 (file)
@@ -682,33 +682,39 @@ NvmeCreateIoCompletionQueue (
   EFI_NVM_EXPRESS_COMPLETION               Completion;\r
   EFI_STATUS                               Status;\r
   NVME_ADMIN_CRIOCQ                        CrIoCq;\r
-\r
-  ZeroMem (&CommandPacket, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));\r
-  ZeroMem (&Command, sizeof(EFI_NVM_EXPRESS_COMMAND));\r
-  ZeroMem (&Completion, sizeof(EFI_NVM_EXPRESS_COMPLETION));\r
-  ZeroMem (&CrIoCq, sizeof(NVME_ADMIN_CRIOCQ));\r
-\r
-  CommandPacket.NvmeCmd        = &Command;\r
-  CommandPacket.NvmeCompletion = &Completion;\r
-\r
-  Command.Cdw0.Opcode = NVME_ADMIN_CRIOCQ_CMD;\r
-  CommandPacket.TransferBuffer = Private->CqBufferPciAddr[1];\r
-  CommandPacket.TransferLength = EFI_PAGE_SIZE;\r
-  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;\r
-  CommandPacket.QueueType      = NVME_ADMIN_QUEUE;\r
-\r
-  CrIoCq.Qid   = NVME_IO_QUEUE;\r
-  CrIoCq.Qsize = NVME_CCQ_SIZE;\r
-  CrIoCq.Pc    = 1;\r
-  CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoCq, sizeof (NVME_ADMIN_CRIOCQ));\r
-  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;\r
-\r
-  Status = Private->Passthru.PassThru (\r
-                               &Private->Passthru,\r
-                               0,\r
-                               &CommandPacket,\r
-                               NULL\r
-                               );\r
+  UINT32                                   Index;\r
+\r
+  for (Index = 1; Index < NVME_MAX_QUEUES; Index++) {\r
+    ZeroMem (&CommandPacket, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));\r
+    ZeroMem (&Command, sizeof(EFI_NVM_EXPRESS_COMMAND));\r
+    ZeroMem (&Completion, sizeof(EFI_NVM_EXPRESS_COMPLETION));\r
+    ZeroMem (&CrIoCq, sizeof(NVME_ADMIN_CRIOCQ));\r
+\r
+    CommandPacket.NvmeCmd        = &Command;\r
+    CommandPacket.NvmeCompletion = &Completion;\r
+\r
+    Command.Cdw0.Opcode = NVME_ADMIN_CRIOCQ_CMD;\r
+    CommandPacket.TransferBuffer = Private->CqBufferPciAddr[Index];\r
+    CommandPacket.TransferLength = EFI_PAGE_SIZE;\r
+    CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;\r
+    CommandPacket.QueueType      = NVME_ADMIN_QUEUE;\r
+\r
+    CrIoCq.Qid   = Index;\r
+    CrIoCq.Qsize = (Index == 1) ? NVME_CCQ_SIZE : NVME_ASYNC_CCQ_SIZE;\r
+    CrIoCq.Pc    = 1;\r
+    CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoCq, sizeof (NVME_ADMIN_CRIOCQ));\r
+    CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;\r
+\r
+    Status = Private->Passthru.PassThru (\r
+                                 &Private->Passthru,\r
+                                 0,\r
+                                 &CommandPacket,\r
+                                 NULL\r
+                                 );\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+  }\r
 \r
   return Status;\r
 }\r
@@ -732,35 +738,41 @@ NvmeCreateIoSubmissionQueue (
   EFI_NVM_EXPRESS_COMPLETION               Completion;\r
   EFI_STATUS                               Status;\r
   NVME_ADMIN_CRIOSQ                        CrIoSq;\r
-\r
-  ZeroMem (&CommandPacket, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));\r
-  ZeroMem (&Command, sizeof(EFI_NVM_EXPRESS_COMMAND));\r
-  ZeroMem (&Completion, sizeof(EFI_NVM_EXPRESS_COMPLETION));\r
-  ZeroMem (&CrIoSq, sizeof(NVME_ADMIN_CRIOSQ));\r
-\r
-  CommandPacket.NvmeCmd        = &Command;\r
-  CommandPacket.NvmeCompletion = &Completion;\r
-\r
-  Command.Cdw0.Opcode = NVME_ADMIN_CRIOSQ_CMD;\r
-  CommandPacket.TransferBuffer = Private->SqBufferPciAddr[1];\r
-  CommandPacket.TransferLength = EFI_PAGE_SIZE;\r
-  CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;\r
-  CommandPacket.QueueType      = NVME_ADMIN_QUEUE;\r
-\r
-  CrIoSq.Qid   = NVME_IO_QUEUE;\r
-  CrIoSq.Qsize = NVME_CSQ_SIZE;\r
-  CrIoSq.Pc    = 1;\r
-  CrIoSq.Cqid  = NVME_IO_QUEUE;\r
-  CrIoSq.Qprio = 0;\r
-  CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoSq, sizeof (NVME_ADMIN_CRIOSQ));\r
-  CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;\r
-\r
-  Status = Private->Passthru.PassThru (\r
-                               &Private->Passthru,\r
-                               0,\r
-                               &CommandPacket,\r
-                               NULL\r
-                               );\r
+  UINT32                                   Index;\r
+\r
+  for (Index = 1; Index < NVME_MAX_QUEUES; Index++) {\r
+    ZeroMem (&CommandPacket, sizeof(EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));\r
+    ZeroMem (&Command, sizeof(EFI_NVM_EXPRESS_COMMAND));\r
+    ZeroMem (&Completion, sizeof(EFI_NVM_EXPRESS_COMPLETION));\r
+    ZeroMem (&CrIoSq, sizeof(NVME_ADMIN_CRIOSQ));\r
+\r
+    CommandPacket.NvmeCmd        = &Command;\r
+    CommandPacket.NvmeCompletion = &Completion;\r
+\r
+    Command.Cdw0.Opcode = NVME_ADMIN_CRIOSQ_CMD;\r
+    CommandPacket.TransferBuffer = Private->SqBufferPciAddr[Index];\r
+    CommandPacket.TransferLength = EFI_PAGE_SIZE;\r
+    CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;\r
+    CommandPacket.QueueType      = NVME_ADMIN_QUEUE;\r
+\r
+    CrIoSq.Qid   = Index;\r
+    CrIoSq.Qsize = (Index == 1) ? NVME_CSQ_SIZE : NVME_ASYNC_CSQ_SIZE;\r
+    CrIoSq.Pc    = 1;\r
+    CrIoSq.Cqid  = Index;\r
+    CrIoSq.Qprio = 0;\r
+    CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoSq, sizeof (NVME_ADMIN_CRIOSQ));\r
+    CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;\r
+\r
+    Status = Private->Passthru.PassThru (\r
+                                 &Private->Passthru,\r
+                                 0,\r
+                                 &CommandPacket,\r
+                                 NULL\r
+                                 );\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+  }\r
 \r
   return Status;\r
 }\r
@@ -844,12 +856,17 @@ NvmeControllerInit (
 \r
   Private->Cid[0] = 0;\r
   Private->Cid[1] = 0;\r
+  Private->Cid[2] = 0;\r
   Private->Pt[0]  = 0;\r
   Private->Pt[1]  = 0;\r
+  Private->Pt[2]  = 0;\r
   Private->SqTdbl[0].Sqt = 0;\r
   Private->SqTdbl[1].Sqt = 0;\r
+  Private->SqTdbl[2].Sqt = 0;\r
   Private->CqHdbl[0].Cqh = 0;\r
   Private->CqHdbl[1].Cqh = 0;\r
+  Private->CqHdbl[2].Cqh = 0;\r
+  Private->AsyncSqHead   = 0;\r
 \r
   Status = NvmeDisableController (Private);\r
 \r
@@ -878,7 +895,7 @@ NvmeControllerInit (
   //\r
   // Address of I/O submission & completion queue.\r
   //\r
-  ZeroMem (Private->Buffer, EFI_PAGES_TO_SIZE (4));\r
+  ZeroMem (Private->Buffer, EFI_PAGES_TO_SIZE (6));\r
   Private->SqBuffer[0]        = (NVME_SQ *)(UINTN)(Private->Buffer);\r
   Private->SqBufferPciAddr[0] = (NVME_SQ *)(UINTN)(Private->BufferPciAddr);\r
   Private->CqBuffer[0]        = (NVME_CQ *)(UINTN)(Private->Buffer + 1 * EFI_PAGE_SIZE);\r
@@ -887,14 +904,20 @@ NvmeControllerInit (
   Private->SqBufferPciAddr[1] = (NVME_SQ *)(UINTN)(Private->BufferPciAddr + 2 * EFI_PAGE_SIZE);\r
   Private->CqBuffer[1]        = (NVME_CQ *)(UINTN)(Private->Buffer + 3 * EFI_PAGE_SIZE);\r
   Private->CqBufferPciAddr[1] = (NVME_CQ *)(UINTN)(Private->BufferPciAddr + 3 * EFI_PAGE_SIZE);\r
+  Private->SqBuffer[2]        = (NVME_SQ *)(UINTN)(Private->Buffer + 4 * EFI_PAGE_SIZE);\r
+  Private->SqBufferPciAddr[2] = (NVME_SQ *)(UINTN)(Private->BufferPciAddr + 4 * EFI_PAGE_SIZE);\r
+  Private->CqBuffer[2]        = (NVME_CQ *)(UINTN)(Private->Buffer + 5 * EFI_PAGE_SIZE);\r
+  Private->CqBufferPciAddr[2] = (NVME_CQ *)(UINTN)(Private->BufferPciAddr + 5 * EFI_PAGE_SIZE);\r
 \r
   DEBUG ((EFI_D_INFO, "Private->Buffer = [%016X]\n", (UINT64)(UINTN)Private->Buffer));\r
-  DEBUG ((EFI_D_INFO, "Admin Submission Queue size (Aqa.Asqs) = [%08X]\n", Aqa.Asqs));\r
-  DEBUG ((EFI_D_INFO, "Admin Completion Queue size (Aqa.Acqs) = [%08X]\n", Aqa.Acqs));\r
-  DEBUG ((EFI_D_INFO, "Admin Submission Queue (SqBuffer[0]) = [%016X]\n", Private->SqBuffer[0]));\r
-  DEBUG ((EFI_D_INFO, "Admin Completion Queue (CqBuffer[0]) = [%016X]\n", Private->CqBuffer[0]));\r
-  DEBUG ((EFI_D_INFO, "I/O   Submission Queue (SqBuffer[1]) = [%016X]\n", Private->SqBuffer[1]));\r
-  DEBUG ((EFI_D_INFO, "I/O   Completion Queue (CqBuffer[1]) = [%016X]\n", Private->CqBuffer[1]));\r
+  DEBUG ((EFI_D_INFO, "Admin     Submission Queue size (Aqa.Asqs) = [%08X]\n", Aqa.Asqs));\r
+  DEBUG ((EFI_D_INFO, "Admin     Completion Queue size (Aqa.Acqs) = [%08X]\n", Aqa.Acqs));\r
+  DEBUG ((EFI_D_INFO, "Admin     Submission Queue (SqBuffer[0]) = [%016X]\n", Private->SqBuffer[0]));\r
+  DEBUG ((EFI_D_INFO, "Admin     Completion Queue (CqBuffer[0]) = [%016X]\n", Private->CqBuffer[0]));\r
+  DEBUG ((EFI_D_INFO, "Sync  I/O Submission Queue (SqBuffer[1]) = [%016X]\n", Private->SqBuffer[1]));\r
+  DEBUG ((EFI_D_INFO, "Sync  I/O Completion Queue (CqBuffer[1]) = [%016X]\n", Private->CqBuffer[1]));\r
+  DEBUG ((EFI_D_INFO, "Async I/O Submission Queue (SqBuffer[2]) = [%016X]\n", Private->SqBuffer[2]));\r
+  DEBUG ((EFI_D_INFO, "Async I/O Completion Queue (CqBuffer[2]) = [%016X]\n", Private->CqBuffer[2]));\r
 \r
   //\r
   // Program admin queue attributes.\r
@@ -971,7 +994,8 @@ NvmeControllerInit (
   DEBUG ((EFI_D_INFO, "    NN        : 0x%x\n", Private->ControllerData->Nn));\r
 \r
   //\r
-  // Create one I/O completion queue.\r
+  // Create two I/O completion queues.\r
+  // One for blocking I/O, one for non-blocking I/O.\r
   //\r
   Status = NvmeCreateIoCompletionQueue (Private);\r
   if (EFI_ERROR(Status)) {\r
@@ -979,7 +1003,8 @@ NvmeControllerInit (
   }\r
 \r
   //\r
-  // Create one I/O Submission queue.\r
+  // Create two I/O Submission queues.\r
+  // One for blocking I/O, one for non-blocking I/O.\r
   //\r
   Status = NvmeCreateIoSubmissionQueue (Private);\r
   if (EFI_ERROR(Status)) {\r