]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c
MdeModulePkg NvmExpressDxe: return error code in error path
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / NvmExpressDxe / NvmExpressPassthru.c
index c33038f0e926555deca50827b021f9a38cd55d68..cfad1587f299acff738723a73ca94d2a94d5fce2 100644 (file)
@@ -3,7 +3,7 @@
   NVM Express specification.\r
 \r
   (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>\r
-  Copyright (c) 2013 - 2017, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   which accompanies this distribution.  The full text of the license may be found at\r
@@ -453,6 +453,7 @@ NvmExpressPassThru (
 {\r
   NVME_CONTROLLER_PRIVATE_DATA   *Private;\r
   EFI_STATUS                     Status;\r
+  EFI_STATUS                     PreviousStatus;\r
   EFI_PCI_IO_PROTOCOL            *PciIo;\r
   NVME_SQ                        *Sq;\r
   NVME_CQ                        *Cq;\r
@@ -592,7 +593,8 @@ NvmExpressPassThru (
   // these two cmds are special which requires their data buffer must support simultaneous access by both the\r
   // processor and a PCI Bus Master. It's caller's responsbility to ensure this.\r
   //\r
-  if (((Sq->Opc & (BIT0 | BIT1)) != 0) && (Sq->Opc != NVME_ADMIN_CRIOCQ_CMD) && (Sq->Opc != NVME_ADMIN_CRIOSQ_CMD)) {\r
+  if (((Sq->Opc & (BIT0 | BIT1)) != 0) &&\r
+      !((Packet->QueueType == NVME_ADMIN_QUEUE) && ((Sq->Opc == NVME_ADMIN_CRIOCQ_CMD) || (Sq->Opc == NVME_ADMIN_CRIOSQ_CMD)))) {\r
     if ((Packet->TransferLength == 0) || (Packet->TransferBuffer == NULL)) {\r
       return EFI_INVALID_PARAMETER;\r
     }\r
@@ -654,6 +656,7 @@ NvmExpressPassThru (
     PhyAddr = (Sq->Prp[0] + EFI_PAGE_SIZE) & ~(EFI_PAGE_SIZE - 1);\r
     Prp = NvmeCreatePrpList (PciIo, PhyAddr, EFI_SIZE_TO_PAGES(Offset + Bytes) - 1, &PrpListHost, &PrpListNo, &MapPrpList);\r
     if (Prp == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
       goto EXIT;\r
     }\r
 \r
@@ -831,6 +834,7 @@ NvmExpressPassThru (
   }\r
 \r
   Data = ReadUnaligned32 ((UINT32*)&Private->CqHdbl[QueueId]);\r
+  PreviousStatus = Status;\r
   Status = PciIo->Mem.Write (\r
                PciIo,\r
                EfiPciIoWidthUint32,\r
@@ -839,6 +843,9 @@ NvmExpressPassThru (
                1,\r
                &Data\r
                );\r
+  // The return status of PciIo->Mem.Write should not override\r
+  // previous status if previous status contains error.\r
+  Status = EFI_ERROR (PreviousStatus) ? PreviousStatus : Status;\r
 \r
   //\r
   // For now, the code does not support the non-blocking feature for admin queue.\r