2 The NvmExpressPei driver is used to manage non-volatile memory subsystem
3 which follows NVM Express specification at PEI phase.
5 Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions
9 of the BSD License which accompanies this distribution. The
10 full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include "NvmExpressPei.h"
21 Transfer MMIO Data to memory.
23 @param[in,out] MemBuffer Destination: Memory address.
24 @param[in] MmioAddr Source: MMIO address.
25 @param[in] Size Size for read.
27 @retval EFI_SUCCESS MMIO read sucessfully.
32 IN OUT VOID
*MemBuffer
,
41 // priority has adjusted
44 *((UINT32
*)MemBuffer
) = MmioRead32 (MmioAddr
);
48 *((UINT64
*)MemBuffer
) = MmioRead64 (MmioAddr
);
52 *((UINT16
*)MemBuffer
) = MmioRead16 (MmioAddr
);
56 *((UINT8
*)MemBuffer
) = MmioRead8 (MmioAddr
);
60 Ptr
= (UINT8
*)MemBuffer
;
61 for (Offset
= 0; Offset
< Size
; Offset
+= 1) {
62 Data
= MmioRead8 (MmioAddr
+ Offset
);
72 Transfer memory data to MMIO.
74 @param[in,out] MmioAddr Destination: MMIO address.
75 @param[in] MemBuffer Source: Memory address.
76 @param[in] Size Size for write.
78 @retval EFI_SUCCESS MMIO write sucessfully.
83 IN OUT UINTN MmioAddr
,
92 // priority has adjusted
95 MmioWrite32 (MmioAddr
, *((UINT32
*)MemBuffer
));
99 MmioWrite64 (MmioAddr
, *((UINT64
*)MemBuffer
));
103 MmioWrite16 (MmioAddr
, *((UINT16
*)MemBuffer
));
107 MmioWrite8 (MmioAddr
, *((UINT8
*)MemBuffer
));
111 Ptr
= (UINT8
*)MemBuffer
;
112 for (Offset
= 0; Offset
< Size
; Offset
+= 1) {
114 MmioWrite8 (MmioAddr
+ Offset
, Data
);
123 Get the page offset for specific NVME based memory.
125 @param[in] BaseMemIndex The Index of BaseMem (0-based).
127 @retval - The page count for specific BaseMem Index
131 NvmeBaseMemPageOffset (
132 IN UINTN BaseMemIndex
137 UINT32 PageSizeList
[5];
139 PageSizeList
[0] = 1; /* ASQ */
140 PageSizeList
[1] = 1; /* ACQ */
141 PageSizeList
[2] = 1; /* SQs */
142 PageSizeList
[3] = 1; /* CQs */
143 PageSizeList
[4] = NVME_PRP_SIZE
; /* PRPs */
145 if (BaseMemIndex
> MAX_BASEMEM_COUNT
) {
146 DEBUG ((DEBUG_ERROR
, "%a: The input BaseMem index is invalid.\n", __FUNCTION__
));
152 for (Index
= 0; Index
< BaseMemIndex
; Index
++) {
153 Pages
+= PageSizeList
[Index
];
160 Wait for NVME controller status to be ready or not.
162 @param[in] Private The pointer to the PEI_NVME_CONTROLLER_PRIVATE_DATA data structure.
163 @param[in] WaitReady Flag for waitting status ready or not.
165 @return EFI_SUCCESS Successfully to wait specific status.
166 @return others Fail to wait for specific controller status.
171 IN PEI_NVME_CONTROLLER_PRIVATE_DATA
*Private
,
181 // Cap.To specifies max delay time in 500ms increments for Csts.Rdy to set after
182 // Cc.Enable. Loop produces a 1 millisecond delay per itteration, up to 500 * Cap.To.
184 if (Private
->Cap
.To
== 0) {
187 Timeout
= Private
->Cap
.To
;
190 Status
= EFI_SUCCESS
;
191 for(Index
= (Timeout
* 500); Index
!= 0; --Index
) {
192 MicroSecondDelay (1000);
195 // Check if the controller is initialized
197 Status
= NVME_GET_CSTS (Private
, &Csts
);
198 if (EFI_ERROR(Status
)) {
199 DEBUG ((DEBUG_ERROR
, "%a: NVME_GET_CSTS fail, Status - %r\n", __FUNCTION__
, Status
));
203 if ((BOOLEAN
) Csts
.Rdy
== WaitReady
) {
209 Status
= EFI_TIMEOUT
;
216 Disable the Nvm Express controller.
218 @param[in] Private The pointer to the PEI_NVME_CONTROLLER_PRIVATE_DATA data structure.
220 @return EFI_SUCCESS Successfully disable the controller.
221 @return others Fail to disable the controller.
225 NvmeDisableController (
226 IN PEI_NVME_CONTROLLER_PRIVATE_DATA
*Private
233 Status
= NVME_GET_CSTS (Private
, &Csts
);
236 // Read Controller Configuration Register.
238 Status
= NVME_GET_CC (Private
, &Cc
);
239 if (EFI_ERROR (Status
)) {
240 DEBUG ((DEBUG_ERROR
, "%a: NVME_GET_CC fail, Status - %r\n", __FUNCTION__
, Status
));
247 // Disable the controller.
249 Status
= NVME_SET_CC (Private
, &Cc
);
250 if (EFI_ERROR (Status
)) {
251 DEBUG ((DEBUG_ERROR
, "%a: NVME_SET_CC fail, Status - %r\n", __FUNCTION__
, Status
));
256 Status
= NvmeWaitController (Private
, FALSE
);
257 if (EFI_ERROR (Status
)) {
258 DEBUG ((DEBUG_ERROR
, "%a: NvmeWaitController fail, Status - %r\n", __FUNCTION__
, Status
));
265 DEBUG ((DEBUG_ERROR
, "%a fail, Status - %r\n", __FUNCTION__
, Status
));
270 Enable the Nvm Express controller.
272 @param[in] Private The pointer to the PEI_NVME_CONTROLLER_PRIVATE_DATA data structure.
274 @return EFI_SUCCESS Successfully enable the controller.
275 @return EFI_DEVICE_ERROR Fail to enable the controller.
276 @return EFI_TIMEOUT Fail to enable the controller in given time slot.
280 NvmeEnableController (
281 IN PEI_NVME_CONTROLLER_PRIVATE_DATA
*Private
288 // Enable the controller
289 // CC.AMS, CC.MPS and CC.CSS are all set to 0
291 ZeroMem (&Cc
, sizeof (NVME_CC
));
295 Status
= NVME_SET_CC (Private
, &Cc
);
296 if (EFI_ERROR (Status
)) {
297 DEBUG ((DEBUG_ERROR
, "%a: NVME_SET_CC fail, Status - %r\n", __FUNCTION__
, Status
));
301 Status
= NvmeWaitController (Private
, TRUE
);
302 if (EFI_ERROR (Status
)) {
303 DEBUG ((DEBUG_ERROR
, "%a: NvmeWaitController fail, Status - %r\n", __FUNCTION__
, Status
));
310 DEBUG ((DEBUG_ERROR
, "%a fail, Status: %r\n", __FUNCTION__
, Status
));
315 Get the Identify Controller data.
317 @param[in] Private The pointer to the PEI_NVME_CONTROLLER_PRIVATE_DATA data structure.
318 @param[in] Buffer The Buffer used to store the Identify Controller data.
320 @return EFI_SUCCESS Successfully get the Identify Controller data.
321 @return others Fail to get the Identify Controller data.
325 NvmeIdentifyController (
326 IN PEI_NVME_CONTROLLER_PRIVATE_DATA
*Private
,
330 EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket
;
331 EDKII_PEI_NVM_EXPRESS_COMMAND Command
;
332 EDKII_PEI_NVM_EXPRESS_COMPLETION Completion
;
335 ZeroMem (&CommandPacket
, sizeof(EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
336 ZeroMem (&Command
, sizeof(EDKII_PEI_NVM_EXPRESS_COMMAND
));
337 ZeroMem (&Completion
, sizeof(EDKII_PEI_NVM_EXPRESS_COMPLETION
));
339 Command
.Cdw0
.Opcode
= NVME_ADMIN_IDENTIFY_CMD
;
341 // According to Nvm Express 1.1 spec Figure 38, When not used, the field shall be cleared to 0h.
342 // For the Identify command, the Namespace Identifier is only used for the Namespace Data structure.
346 CommandPacket
.NvmeCmd
= &Command
;
347 CommandPacket
.NvmeCompletion
= &Completion
;
348 CommandPacket
.TransferBuffer
= Buffer
;
349 CommandPacket
.TransferLength
= sizeof (NVME_ADMIN_CONTROLLER_DATA
);
350 CommandPacket
.CommandTimeout
= NVME_GENERIC_TIMEOUT
;
351 CommandPacket
.QueueType
= NVME_ADMIN_QUEUE
;
353 // Set bit 0 (Cns bit) to 1 to identify the controller
355 CommandPacket
.NvmeCmd
->Cdw10
= 1;
356 CommandPacket
.NvmeCmd
->Flags
= CDW10_VALID
;
358 Status
= NvmePassThru (
360 NVME_CONTROLLER_NSID
,
367 Get specified identify namespace data.
369 @param[in] Private The pointer to the PEI_NVME_CONTROLLER_PRIVATE_DATA data structure.
370 @param[in] NamespaceId The specified namespace identifier.
371 @param[in] Buffer The buffer used to store the identify namespace data.
373 @return EFI_SUCCESS Successfully get the identify namespace data.
374 @return EFI_DEVICE_ERROR Fail to get the identify namespace data.
378 NvmeIdentifyNamespace (
379 IN PEI_NVME_CONTROLLER_PRIVATE_DATA
*Private
,
380 IN UINT32 NamespaceId
,
384 EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket
;
385 EDKII_PEI_NVM_EXPRESS_COMMAND Command
;
386 EDKII_PEI_NVM_EXPRESS_COMPLETION Completion
;
389 ZeroMem (&CommandPacket
, sizeof(EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
390 ZeroMem (&Command
, sizeof(EDKII_PEI_NVM_EXPRESS_COMMAND
));
391 ZeroMem (&Completion
, sizeof(EDKII_PEI_NVM_EXPRESS_COMPLETION
));
393 Command
.Cdw0
.Opcode
= NVME_ADMIN_IDENTIFY_CMD
;
394 Command
.Nsid
= NamespaceId
;
396 CommandPacket
.NvmeCmd
= &Command
;
397 CommandPacket
.NvmeCompletion
= &Completion
;
398 CommandPacket
.TransferBuffer
= Buffer
;
399 CommandPacket
.TransferLength
= sizeof (NVME_ADMIN_NAMESPACE_DATA
);
400 CommandPacket
.CommandTimeout
= NVME_GENERIC_TIMEOUT
;
401 CommandPacket
.QueueType
= NVME_ADMIN_QUEUE
;
403 // Set bit 0 (Cns bit) to 1 to identify a namespace
405 CommandPacket
.NvmeCmd
->Cdw10
= 0;
406 CommandPacket
.NvmeCmd
->Flags
= CDW10_VALID
;
408 Status
= NvmePassThru (
417 Dump the Identify Controller data.
419 @param[in] ControllerData The pointer to the NVME_ADMIN_CONTROLLER_DATA data structure.
423 NvmeDumpControllerData (
424 IN NVME_ADMIN_CONTROLLER_DATA
*ControllerData
430 CopyMem (Sn
, ControllerData
->Sn
, sizeof (ControllerData
->Sn
));
432 CopyMem (Mn
, ControllerData
->Mn
, sizeof (ControllerData
->Mn
));
435 DEBUG ((DEBUG_INFO
, " == NVME IDENTIFY CONTROLLER DATA ==\n"));
436 DEBUG ((DEBUG_INFO
, " PCI VID : 0x%x\n", ControllerData
->Vid
));
437 DEBUG ((DEBUG_INFO
, " PCI SSVID : 0x%x\n", ControllerData
->Ssvid
));
438 DEBUG ((DEBUG_INFO
, " SN : %a\n", Sn
));
439 DEBUG ((DEBUG_INFO
, " MN : %a\n", Mn
));
440 DEBUG ((DEBUG_INFO
, " FR : 0x%lx\n", *((UINT64
*)ControllerData
->Fr
)));
441 DEBUG ((DEBUG_INFO
, " RAB : 0x%x\n", ControllerData
->Rab
));
442 DEBUG ((DEBUG_INFO
, " IEEE : 0x%x\n", *(UINT32
*)ControllerData
->Ieee_oui
));
443 DEBUG ((DEBUG_INFO
, " AERL : 0x%x\n", ControllerData
->Aerl
));
444 DEBUG ((DEBUG_INFO
, " SQES : 0x%x\n", ControllerData
->Sqes
));
445 DEBUG ((DEBUG_INFO
, " CQES : 0x%x\n", ControllerData
->Cqes
));
446 DEBUG ((DEBUG_INFO
, " NN : 0x%x\n", ControllerData
->Nn
));
451 Create IO completion queue.
453 @param[in] Private The pointer to the PEI_NVME_CONTROLLER_PRIVATE_DATA data structure.
455 @return EFI_SUCCESS Successfully create io completion queue.
456 @return others Fail to create io completion queue.
460 NvmeCreateIoCompletionQueue (
461 IN PEI_NVME_CONTROLLER_PRIVATE_DATA
*Private
464 EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket
;
465 EDKII_PEI_NVM_EXPRESS_COMMAND Command
;
466 EDKII_PEI_NVM_EXPRESS_COMPLETION Completion
;
468 NVME_ADMIN_CRIOCQ CrIoCq
;
470 ZeroMem (&CommandPacket
, sizeof(EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
471 ZeroMem (&Command
, sizeof(EDKII_PEI_NVM_EXPRESS_COMMAND
));
472 ZeroMem (&Completion
, sizeof(EDKII_PEI_NVM_EXPRESS_COMPLETION
));
473 ZeroMem (&CrIoCq
, sizeof(NVME_ADMIN_CRIOCQ
));
475 CommandPacket
.NvmeCmd
= &Command
;
476 CommandPacket
.NvmeCompletion
= &Completion
;
478 Command
.Cdw0
.Opcode
= NVME_ADMIN_CRIOCQ_CMD
;
479 Command
.Cdw0
.Cid
= Private
->Cid
[NVME_ADMIN_QUEUE
]++;
480 CommandPacket
.TransferBuffer
= Private
->CqBuffer
[NVME_IO_QUEUE
];
481 CommandPacket
.TransferLength
= EFI_PAGE_SIZE
;
482 CommandPacket
.CommandTimeout
= NVME_GENERIC_TIMEOUT
;
483 CommandPacket
.QueueType
= NVME_ADMIN_QUEUE
;
485 CrIoCq
.Qid
= NVME_IO_QUEUE
;
486 CrIoCq
.Qsize
= NVME_CCQ_SIZE
;
488 CopyMem (&CommandPacket
.NvmeCmd
->Cdw10
, &CrIoCq
, sizeof (NVME_ADMIN_CRIOCQ
));
489 CommandPacket
.NvmeCmd
->Flags
= CDW10_VALID
| CDW11_VALID
;
491 Status
= NvmePassThru (
493 NVME_CONTROLLER_NSID
,
500 Create IO submission queue.
502 @param[in] Private The pointer to the PEI_NVME_CONTROLLER_PRIVATE_DATA data structure.
504 @return EFI_SUCCESS Successfully create io submission queue.
505 @return others Fail to create io submission queue.
509 NvmeCreateIoSubmissionQueue (
510 IN PEI_NVME_CONTROLLER_PRIVATE_DATA
*Private
513 EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket
;
514 EDKII_PEI_NVM_EXPRESS_COMMAND Command
;
515 EDKII_PEI_NVM_EXPRESS_COMPLETION Completion
;
517 NVME_ADMIN_CRIOSQ CrIoSq
;
519 ZeroMem (&CommandPacket
, sizeof(EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET
));
520 ZeroMem (&Command
, sizeof(EDKII_PEI_NVM_EXPRESS_COMMAND
));
521 ZeroMem (&Completion
, sizeof(EDKII_PEI_NVM_EXPRESS_COMPLETION
));
522 ZeroMem (&CrIoSq
, sizeof(NVME_ADMIN_CRIOSQ
));
524 CommandPacket
.NvmeCmd
= &Command
;
525 CommandPacket
.NvmeCompletion
= &Completion
;
527 Command
.Cdw0
.Opcode
= NVME_ADMIN_CRIOSQ_CMD
;
528 Command
.Cdw0
.Cid
= Private
->Cid
[NVME_ADMIN_QUEUE
]++;
529 CommandPacket
.TransferBuffer
= Private
->SqBuffer
[NVME_IO_QUEUE
];
530 CommandPacket
.TransferLength
= EFI_PAGE_SIZE
;
531 CommandPacket
.CommandTimeout
= NVME_GENERIC_TIMEOUT
;
532 CommandPacket
.QueueType
= NVME_ADMIN_QUEUE
;
534 CrIoSq
.Qid
= NVME_IO_QUEUE
;
535 CrIoSq
.Qsize
= NVME_CSQ_SIZE
;
537 CrIoSq
.Cqid
= NVME_IO_QUEUE
;
539 CopyMem (&CommandPacket
.NvmeCmd
->Cdw10
, &CrIoSq
, sizeof (NVME_ADMIN_CRIOSQ
));
540 CommandPacket
.NvmeCmd
->Flags
= CDW10_VALID
| CDW11_VALID
;
542 Status
= NvmePassThru (
544 NVME_CONTROLLER_NSID
,
551 Initialize the Nvm Express controller.
553 @param[in] Private The pointer to the PEI_NVME_CONTROLLER_PRIVATE_DATA data structure.
555 @retval EFI_SUCCESS The NVM Express Controller is initialized successfully.
556 @retval Others A device error occurred while initializing the controller.
561 IN PEI_NVME_CONTROLLER_PRIVATE_DATA
*Private
572 // Dump the NVME controller implementation version
574 NVME_GET_VER (Private
, &Ver
);
575 DEBUG ((DEBUG_INFO
, "NVME controller implementation version: %d.%d\n", Ver
.Mjr
, Ver
.Mnr
));
578 // Read the controller Capabilities register and verify that the NVM command set is supported
580 NVME_GET_CAP (Private
, &Private
->Cap
);
581 if (Private
->Cap
.Css
!= 0x01) {
582 DEBUG ((DEBUG_ERROR
, "%a: The NVME controller doesn't support NVMe command set.\n", __FUNCTION__
));
583 return EFI_UNSUPPORTED
;
587 // Currently, the driver only supports 4k page size
589 if ((Private
->Cap
.Mpsmin
+ 12) > EFI_PAGE_SHIFT
) {
590 DEBUG ((DEBUG_ERROR
, "%a: The driver doesn't support page size other than 4K.\n", __FUNCTION__
));
592 return EFI_UNSUPPORTED
;
595 for (Index
= 0; Index
< NVME_MAX_QUEUES
; Index
++) {
596 Private
->Pt
[Index
] = 0;
597 Private
->Cid
[Index
] = 0;
598 ZeroMem ((VOID
*)(UINTN
)(&Private
->SqTdbl
[Index
]), sizeof (NVME_SQTDBL
));
599 ZeroMem ((VOID
*)(UINTN
)(&Private
->CqHdbl
[Index
]), sizeof (NVME_CQHDBL
));
601 ZeroMem (Private
->Buffer
, EFI_PAGE_SIZE
* NVME_MEM_MAX_PAGES
);
604 // Disable the NVME controller first
606 Status
= NvmeDisableController (Private
);
607 if (EFI_ERROR (Status
)) {
608 DEBUG ((DEBUG_ERROR
, "%a: NvmeDisableController fail, Status - %r\n", __FUNCTION__
, Status
));
613 // Set the number of entries in admin submission & completion queues
615 Aqa
.Asqs
= NVME_ASQ_SIZE
;
617 Aqa
.Acqs
= NVME_ACQ_SIZE
;
621 // Address of admin submission & completion queues
623 Asq
= (UINT64
)(UINTN
)(NVME_ASQ_BASE (Private
) & ~0xFFF);
624 Acq
= (UINT64
)(UINTN
)(NVME_ACQ_BASE (Private
) & ~0xFFF);
627 // Address of I/O submission & completion queues
629 Private
->SqBuffer
[0] = (NVME_SQ
*)(UINTN
)NVME_ASQ_BASE (Private
); // NVME_ADMIN_QUEUE
630 Private
->CqBuffer
[0] = (NVME_CQ
*)(UINTN
)NVME_ACQ_BASE (Private
); // NVME_ADMIN_QUEUE
631 Private
->SqBuffer
[1] = (NVME_SQ
*)(UINTN
)NVME_SQ_BASE (Private
, 0); // NVME_IO_QUEUE
632 Private
->CqBuffer
[1] = (NVME_CQ
*)(UINTN
)NVME_CQ_BASE (Private
, 0); // NVME_IO_QUEUE
633 DEBUG ((DEBUG_INFO
, "Admin Submission Queue Size (Aqa.Asqs) = [%08X]\n", Aqa
.Asqs
));
634 DEBUG ((DEBUG_INFO
, "Admin Completion Queue Size (Aqa.Acqs) = [%08X]\n", Aqa
.Acqs
));
635 DEBUG ((DEBUG_INFO
, "Admin Submission Queue (SqBuffer[0]) = [%08X]\n", Private
->SqBuffer
[0]));
636 DEBUG ((DEBUG_INFO
, "Admin Completion Queue (CqBuffer[0]) = [%08X]\n", Private
->CqBuffer
[0]));
637 DEBUG ((DEBUG_INFO
, "I/O Submission Queue (SqBuffer[1]) = [%08X]\n", Private
->SqBuffer
[1]));
638 DEBUG ((DEBUG_INFO
, "I/O Completion Queue (CqBuffer[1]) = [%08X]\n", Private
->CqBuffer
[1]));
641 // Program admin queue attributes
643 NVME_SET_AQA (Private
, &Aqa
);
646 // Program admin submission & completion queues address
648 NVME_SET_ASQ (Private
, &Asq
);
649 NVME_SET_ACQ (Private
, &Acq
);
652 // Enable the NVME controller
654 Status
= NvmeEnableController (Private
);
655 if (EFI_ERROR (Status
)) {
656 DEBUG ((DEBUG_ERROR
, "%a: NvmeEnableController fail, Status - %r\n", __FUNCTION__
, Status
));
661 // Get the Identify Controller data
663 if (Private
->ControllerData
== NULL
) {
664 Private
->ControllerData
= (NVME_ADMIN_CONTROLLER_DATA
*)AllocateZeroPool (sizeof (NVME_ADMIN_CONTROLLER_DATA
));
665 if (Private
->ControllerData
== NULL
) {
666 return EFI_OUT_OF_RESOURCES
;
669 Status
= NvmeIdentifyController (Private
, Private
->ControllerData
);
670 if (EFI_ERROR (Status
)) {
671 DEBUG ((DEBUG_ERROR
, "%a: NvmeIdentifyController fail, Status - %r\n", __FUNCTION__
, Status
));
674 NvmeDumpControllerData (Private
->ControllerData
);
677 // Check the namespace number for storing the namespaces information
679 if (Private
->ControllerData
->Nn
> MAX_UINT32
/ sizeof (PEI_NVME_NAMESPACE_INFO
)) {
682 "%a: Number of Namespaces field in Identify Controller data not supported by the driver.\n",
685 return EFI_UNSUPPORTED
;
689 // Create one I/O completion queue and one I/O submission queue
691 Status
= NvmeCreateIoCompletionQueue (Private
);
692 if (EFI_ERROR (Status
)) {
693 DEBUG ((DEBUG_ERROR
, "%a: Create IO completion queue fail, Status - %r\n", __FUNCTION__
, Status
));
696 Status
= NvmeCreateIoSubmissionQueue (Private
);
697 if (EFI_ERROR (Status
)) {
698 DEBUG ((DEBUG_ERROR
, "%a: Create IO submission queue fail, Status - %r\n", __FUNCTION__
, Status
));
705 Free the DMA resources allocated by an NVME controller.
707 @param[in] Private The pointer to the PEI_NVME_CONTROLLER_PRIVATE_DATA data structure.
711 NvmeFreeDmaResource (
712 IN PEI_NVME_CONTROLLER_PRIVATE_DATA
*Private
715 ASSERT (Private
!= NULL
);
717 if (Private
->BufferMapping
!= NULL
) {
721 Private
->BufferMapping