From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 6A86221A00AD1 for ; Tue, 4 Jul 2017 18:26:41 -0700 (PDT) Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 04 Jul 2017 18:28:20 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.40,309,1496127600"; d="scan'208";a="988738357" Received: from fmsmsx108.amr.corp.intel.com ([10.18.124.206]) by orsmga003.jf.intel.com with ESMTP; 04 Jul 2017 18:28:19 -0700 Received: from shsmsx101.ccr.corp.intel.com (10.239.4.153) by FMSMSX108.amr.corp.intel.com (10.18.124.206) with Microsoft SMTP Server (TLS) id 14.3.319.2; Tue, 4 Jul 2017 18:28:19 -0700 Received: from shsmsx102.ccr.corp.intel.com ([169.254.2.146]) by SHSMSX101.ccr.corp.intel.com ([169.254.1.197]) with mapi id 14.03.0319.002; Wed, 5 Jul 2017 09:28:17 +0800 From: "Zeng, Star" To: "Wu, Hao A" , "edk2-devel@lists.01.org" CC: Michael Turner , "Zeng, Star" Thread-Topic: [PATCH] MdeModulePkg/NvmExpressDxe: Handle timeout for blocking PassThru req Thread-Index: AQHS3zyV7RmQksRAEkySsXhvnDfKgqJEnWGg Date: Wed, 5 Jul 2017 01:28:16 +0000 Message-ID: <0C09AFA07DD0434D9E2A0C6AEB0483103B8F146B@shsmsx102.ccr.corp.intel.com> References: <20170607031718.12132-1-hao.a.wu@intel.com> In-Reply-To: <20170607031718.12132-1-hao.a.wu@intel.com> Accept-Language: zh-CN, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-product: dlpe-windows dlp-version: 10.0.102.7 dlp-reaction: no-action x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Subject: Re: [PATCH] MdeModulePkg/NvmExpressDxe: Handle timeout for blocking PassThru req X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 05 Jul 2017 01:26:41 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Reviewed-by: Star Zeng -----Original Message----- From: Wu, Hao A=20 Sent: Wednesday, June 7, 2017 11:17 AM To: edk2-devel@lists.01.org Cc: Wu, Hao A ; Zeng, Star ; Micha= el Turner Subject: [PATCH] MdeModulePkg/NvmExpressDxe: Handle timeout for blocking Pa= ssThru req https://bugzilla.tianocore.org/show_bug.cgi?id=3D433 When a blocking NVMe PassThru request experiences timeout, the current code= s in function NvmExpressPassThru() do not abort the timeout request while a= dvancing synchronous Submission Queue tail. Therefore, it is possible to su= bmit a new blocking PassThru request when the synchronous Submission Queue = is full. The commit adds logic to abort the timeout request by resetting the NVMe co= ntroller when a timeout occurs for a blocking PassThru request. Cc: Star Zeng Cc: Michael Turner Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Hao Wu --- .../Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c | 134 +++++++++++++++++= +++- 1 file changed, 133 insertions(+), 1 deletion(-) diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c b/MdeM= odulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c index fb80f39ce8..c33038f0e9 100644 --- a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c +++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c @@ -3,7 +3,7 @@ NVM Express specification. =20 (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
- Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.
+ Copyright (c) 2013 - 2017, Intel Corporation. All rights=20 + reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BS= D License which accompanies this distribution. The full text of the license may b= e found at @@ -317,6 +317,100 @@ EXIT: =20 =20 /** + Aborts the asynchronous PassThru requests. + + @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DAT= A + data structure. + + @retval EFI_SUCCESS The asynchronous PassThru requests have been a= borted. + @return EFI_DEVICE_ERROR Fail to abort all the asynchronous PassThru re= quests. + +**/ +EFI_STATUS +AbortAsyncPassThruTasks ( + IN NVME_CONTROLLER_PRIVATE_DATA *Private + ) +{ + EFI_PCI_IO_PROTOCOL *PciIo; + LIST_ENTRY *Link; + LIST_ENTRY *NextLink; + NVME_BLKIO2_SUBTASK *Subtask; + NVME_BLKIO2_REQUEST *BlkIo2Request; + NVME_PASS_THRU_ASYNC_REQ *AsyncRequest; + EFI_BLOCK_IO2_TOKEN *Token; + EFI_TPL OldTpl; + EFI_STATUS Status; + + PciIo =3D Private->PciIo; + OldTpl =3D gBS->RaiseTPL (TPL_NOTIFY); + + // + // Cancel the unsubmitted subtasks. + // + for (Link =3D GetFirstNode (&Private->UnsubmittedSubtasks); + !IsNull (&Private->UnsubmittedSubtasks, Link); + Link =3D NextLink) { + NextLink =3D GetNextNode (&Private->UnsubmittedSubtasks, Link); + Subtask =3D NVME_BLKIO2_SUBTASK_FROM_LINK (Link); + BlkIo2Request =3D Subtask->BlockIo2Request; + Token =3D BlkIo2Request->Token; + + BlkIo2Request->UnsubmittedSubtaskNum--; + if (Subtask->IsLast) { + BlkIo2Request->LastSubtaskSubmitted =3D TRUE; + } + Token->TransactionStatus =3D EFI_ABORTED; + + RemoveEntryList (Link); + InsertTailList (&BlkIo2Request->SubtasksQueue, Link); + gBS->SignalEvent (Subtask->Event); + } + + // + // Cleanup the resources for the asynchronous PassThru requests. + // + for (Link =3D GetFirstNode (&Private->AsyncPassThruQueue); + !IsNull (&Private->AsyncPassThruQueue, Link); + Link =3D NextLink) { + NextLink =3D GetNextNode (&Private->AsyncPassThruQueue, Link); + AsyncRequest =3D NVME_PASS_THRU_ASYNC_REQ_FROM_THIS (Link); + + if (AsyncRequest->MapData !=3D NULL) { + PciIo->Unmap (PciIo, AsyncRequest->MapData); + } + if (AsyncRequest->MapMeta !=3D NULL) { + PciIo->Unmap (PciIo, AsyncRequest->MapMeta); + } + if (AsyncRequest->MapPrpList !=3D NULL) { + PciIo->Unmap (PciIo, AsyncRequest->MapPrpList); + } + if (AsyncRequest->PrpListHost !=3D NULL) { + PciIo->FreeBuffer ( + PciIo, + AsyncRequest->PrpListNo, + AsyncRequest->PrpListHost + ); + } + + RemoveEntryList (Link); + gBS->SignalEvent (AsyncRequest->CallerEvent); + FreePool (AsyncRequest); + } + + if (IsListEmpty (&Private->AsyncPassThruQueue) && + IsListEmpty (&Private->UnsubmittedSubtasks)) { + Status =3D EFI_SUCCESS; + } else { + Status =3D EFI_DEVICE_ERROR; + } + + gBS->RestoreTPL (OldTpl); + + return Status; +} + + +/** Sends an NVM Express Command Packet to an NVM Express controller or name= space. This function supports both blocking I/O and non-blocking I/O. The blocking I/O functionality i= s required, and the non-blocking I/O functionality is optional. @@ -692,6 +786,44 @@ NvmExpressPassThru ( NvmeDumpStatus(Cq); DEBUG_CODE_END(); } + } else { + // + // Timeout occurs for an NVMe command. Reset the controller to abort t= he + // outstanding commands. + // + DEBUG ((DEBUG_ERROR, "NvmExpressPassThru: Timeout occurs for an=20 + NVMe command.\n")); + + // + // Disable the timer to trigger the process of async transfers tempora= rily. + // + Status =3D gBS->SetTimer (Private->TimerEvent, TimerCancel, 0); + if (EFI_ERROR (Status)) { + goto EXIT; + } + + // + // Reset the NVMe controller. + // + Status =3D NvmeControllerInit (Private); + if (!EFI_ERROR (Status)) { + Status =3D AbortAsyncPassThruTasks (Private); + if (!EFI_ERROR (Status)) { + // + // Re-enable the timer to trigger the process of async transfers. + // + Status =3D gBS->SetTimer (Private->TimerEvent, TimerPeriodic, NVME= _HC_ASYNC_TIMER); + if (!EFI_ERROR (Status)) { + // + // Return EFI_TIMEOUT to indicate a timeout occurs for NVMe Pass= Thru command. + // + Status =3D EFI_TIMEOUT; + } + } + } else { + Status =3D EFI_DEVICE_ERROR; + } + + goto EXIT; } =20 if ((Private->CqHdbl[QueueId].Cqh ^=3D 1) =3D=3D 0) { -- 2.12.0.windows.1