From 9a77210b43ef34af52ea7285fadc0ce5779306fe Mon Sep 17 00:00:00 2001 From: Heyi Guo Date: Mon, 4 Dec 2017 10:27:54 +0800 Subject: [PATCH] MdeModulePkg/NvmExpressDxe: fix error status override Commit f6b139b added return status handling to PciIo->Mem.Write. However, the second status handling will override EFI_DEVICE_ERROR returned in this branch: // // Check the NVMe cmd execution result // if (Status != EFI_TIMEOUT) { if ((Cq->Sct == 0) && (Cq->Sc == 0)) { Status = EFI_SUCCESS; } else { Status = EFI_DEVICE_ERROR; ^^^^^^^^^^^^^^^^ Since PciIo->Mem.Write will probably return SUCCESS, it causes NvmExpressPassThru to return SUCCESS even when DEVICE_ERROR occurs. Callers of NvmExpressPassThru will then continue executing which may cause further unexpected results, e.g. DiscoverAllNamespaces couldn't break out the loop. So we save previous status before calling PciIo->Mem.Write and restore the previous one if it already contains error. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Heyi Guo Cc: Eric Dong Cc: Ruiyu Ni Reviewed-by: Hao Wu Reviewed-by: Star Zeng --- MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c index c33038f0e9..7356c1d673 100644 --- a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c +++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c @@ -453,6 +453,7 @@ NvmExpressPassThru ( { NVME_CONTROLLER_PRIVATE_DATA *Private; EFI_STATUS Status; + EFI_STATUS PreviousStatus; EFI_PCI_IO_PROTOCOL *PciIo; NVME_SQ *Sq; NVME_CQ *Cq; @@ -831,6 +832,7 @@ NvmExpressPassThru ( } Data = ReadUnaligned32 ((UINT32*)&Private->CqHdbl[QueueId]); + PreviousStatus = Status; Status = PciIo->Mem.Write ( PciIo, EfiPciIoWidthUint32, @@ -839,6 +841,9 @@ NvmExpressPassThru ( 1, &Data ); + // The return status of PciIo->Mem.Write should not override + // previous status if previous status contains error. + Status = EFI_ERROR (PreviousStatus) ? PreviousStatus : Status; // // For now, the code does not support the non-blocking feature for admin queue.