From: Hao Wu <hao.a.wu@intel.com>
To: edk2-devel@lists.01.org
Cc: Hao Wu <hao.a.wu@intel.com>, Jian J Wang <jian.j.wang@intel.com>
Subject: [PATCH v6 07/13] MdeModulePkg/NvmExpressPei: Consume S3StorageDeviceInitList LockBox
Date: Thu, 21 Feb 2019 08:24:34 +0800 [thread overview]
Message-ID: <20190221002440.2272-8-hao.a.wu@intel.com> (raw)
In-Reply-To: <20190221002440.2272-1-hao.a.wu@intel.com>
REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1409
For the NvmExpressPei driver, this commit will update the driver to
consume the S3StorageDeviceInitList LockBox in S3 phase. The purpose is to
perform an on-demand (partial) NVM Express device
enumeration/initialization to benefit the S3 resume performance.
Cc: Jian J Wang <jian.j.wang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Hao Wu <hao.a.wu@intel.com>
Reviewed-by: Eric Dong <eric.dong@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
---
MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf | 8 +-
MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h | 36 +++++++
MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c | 53 +++++++++
MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c | 26 +++++
MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiS3.c | 114 ++++++++++++++++++++
5 files changed, 236 insertions(+), 1 deletion(-)
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
index 0666e5892b..22b703e971 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
+++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.inf
@@ -40,6 +40,7 @@
NvmExpressPeiHci.h
NvmExpressPeiPassThru.c
NvmExpressPeiPassThru.h
+ NvmExpressPeiS3.c
NvmExpressPeiStorageSecurity.c
NvmExpressPeiStorageSecurity.h
@@ -54,6 +55,7 @@
BaseMemoryLib
IoLib
TimerLib
+ LockBoxLib
PeimEntryPoint
[Ppis]
@@ -64,9 +66,13 @@
gEfiPeiVirtualBlockIo2PpiGuid ## SOMETIMES_PRODUCES
gEdkiiPeiStorageSecurityCommandPpiGuid ## SOMETIMES_PRODUCES
+[Guids]
+ gS3StorageDeviceInitListGuid ## SOMETIMES_CONSUMES ## UNDEFINED
+
[Depex]
gEfiPeiMemoryDiscoveredPpiGuid AND
- gEdkiiPeiNvmExpressHostControllerPpiGuid
+ gEdkiiPeiNvmExpressHostControllerPpiGuid AND
+ gEfiPeiMasterBootModePpiGuid
[UserExtensions.TianoCore."ExtraFiles"]
NvmExpressPeiExtra.uni
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
index 89666160a1..74e2daf511 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
+++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.h
@@ -267,6 +267,26 @@ NvmePeimEndOfPei (
);
/**
+ Get the size of the current device path instance.
+
+ @param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL
+ structure.
+ @param[out] InstanceSize The size of the current device path instance.
+ @param[out] EntireDevicePathEnd Indicate whether the instance is the last
+ one in the device path strucure.
+
+ @retval EFI_SUCCESS The size of the current device path instance is fetched.
+ @retval Others Fails to get the size of the current device path instance.
+
+**/
+EFI_STATUS
+GetDevicePathInstanceSize (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT UINTN *InstanceSize,
+ OUT BOOLEAN *EntireDevicePathEnd
+ );
+
+/**
Check the validity of the device path of a NVM Express host controller.
@param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL
@@ -309,4 +329,20 @@ NvmeBuildDevicePath (
OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
);
+/**
+ Determine if a specific NVM Express controller can be skipped for S3 phase.
+
+ @param[in] HcDevicePath Device path of the controller.
+ @param[in] HcDevicePathLength Length of the device path specified by
+ HcDevicePath.
+
+ @retval The number of ports that need to be enumerated.
+
+**/
+BOOLEAN
+NvmeS3SkipThisController (
+ IN EFI_DEVICE_PATH_PROTOCOL *HcDevicePath,
+ IN UINTN HcDevicePathLength
+ );
+
#endif
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c b/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
index fd30ad519f..ff95f20329 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
+++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/DevicePath.c
@@ -89,6 +89,59 @@ NextDevicePathNode (
}
/**
+ Get the size of the current device path instance.
+
+ @param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL
+ structure.
+ @param[out] InstanceSize The size of the current device path instance.
+ @param[out] EntireDevicePathEnd Indicate whether the instance is the last
+ one in the device path strucure.
+
+ @retval EFI_SUCCESS The size of the current device path instance is fetched.
+ @retval Others Fails to get the size of the current device path instance.
+
+**/
+EFI_STATUS
+GetDevicePathInstanceSize (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT UINTN *InstanceSize,
+ OUT BOOLEAN *EntireDevicePathEnd
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *Walker;
+
+ if (DevicePath == NULL || InstanceSize == NULL || EntireDevicePathEnd == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Find the end of the device path instance
+ //
+ Walker = DevicePath;
+ while (Walker->Type != END_DEVICE_PATH_TYPE) {
+ Walker = NextDevicePathNode (Walker);
+ }
+
+ //
+ // Check if 'Walker' points to the end of an entire device path
+ //
+ if (Walker->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE) {
+ *EntireDevicePathEnd = TRUE;
+ } else if (Walker->SubType == END_INSTANCE_DEVICE_PATH_SUBTYPE) {
+ *EntireDevicePathEnd = FALSE;
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Compute the size of the device path instance
+ //
+ *InstanceSize = ((UINTN) Walker - (UINTN) (DevicePath)) + sizeof (EFI_DEVICE_PATH_PROTOCOL);
+
+ return EFI_SUCCESS;
+}
+
+/**
Check the validity of the device path of a NVM Express host controller.
@param[in] DevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
index bf33b4b9a0..2dbf54fd3f 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
+++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPei.c
@@ -213,6 +213,7 @@ NvmExpressPeimEntry (
)
{
EFI_STATUS Status;
+ EFI_BOOT_MODE BootMode;
EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI *NvmeHcPpi;
UINT8 Controller;
UINTN MmioBase;
@@ -224,6 +225,15 @@ NvmExpressPeimEntry (
DEBUG ((DEBUG_INFO, "%a: Enters.\n", __FUNCTION__));
//
+ // Get the current boot mode.
+ //
+ Status = PeiServicesGetBootMode (&BootMode);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Fail to get the current boot mode.\n", __FUNCTION__));
+ return Status;
+ }
+
+ //
// Locate the NVME host controller PPI
//
Status = PeiServicesLocatePpi (
@@ -280,6 +290,22 @@ NvmExpressPeimEntry (
}
//
+ // For S3 resume performance consideration, not all NVM Express controllers
+ // will be initialized. The driver consumes the content within
+ // S3StorageDeviceInitList LockBox to see if a controller will be skipped
+ // during S3 resume.
+ //
+ if ((BootMode == BOOT_ON_S3_RESUME) &&
+ (NvmeS3SkipThisController (DevicePath, DevicePathLength))) {
+ DEBUG ((
+ DEBUG_ERROR, "%a: Controller %d is skipped during S3.\n",
+ __FUNCTION__, Controller
+ ));
+ Controller++;
+ continue;
+ }
+
+ //
// Memory allocation for controller private data
//
Private = AllocateZeroPool (sizeof (PEI_NVME_CONTROLLER_PRIVATE_DATA));
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiS3.c b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiS3.c
new file mode 100644
index 0000000000..eb3af75b89
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/NvmExpressPei/NvmExpressPeiS3.c
@@ -0,0 +1,114 @@
+/** @file
+ The NvmExpressPei driver is used to manage non-volatile memory subsystem
+ which follows NVM Express specification at PEI phase.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions
+ of the BSD License which accompanies this distribution. The
+ full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "NvmExpressPei.h"
+
+#include <Guid/S3StorageDeviceInitList.h>
+
+#include <Library/LockBoxLib.h>
+
+/**
+ Determine if a specific NVM Express controller can be skipped for S3 phase.
+
+ @param[in] HcDevicePath Device path of the controller.
+ @param[in] HcDevicePathLength Length of the device path specified by
+ HcDevicePath.
+
+ @retval The number of ports that need to be enumerated.
+
+**/
+BOOLEAN
+NvmeS3SkipThisController (
+ IN EFI_DEVICE_PATH_PROTOCOL *HcDevicePath,
+ IN UINTN HcDevicePathLength
+ )
+{
+ EFI_STATUS Status;
+ UINT8 DummyData;
+ UINTN S3InitDevicesLength;
+ EFI_DEVICE_PATH_PROTOCOL *S3InitDevices;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;
+ UINTN DevicePathInstLength;
+ BOOLEAN EntireEnd;
+ BOOLEAN Skip;
+
+ //
+ // From the LockBox, get the list of device paths for devices need to be
+ // initialized in S3.
+ //
+ S3InitDevices = NULL;
+ S3InitDevicesLength = sizeof (DummyData);
+ EntireEnd = FALSE;
+ Skip = TRUE;
+ Status = RestoreLockBox (&gS3StorageDeviceInitListGuid, &DummyData, &S3InitDevicesLength);
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ return Skip;
+ } else {
+ S3InitDevices = AllocatePool (S3InitDevicesLength);
+ if (S3InitDevices == NULL) {
+ return Skip;
+ }
+
+ Status = RestoreLockBox (&gS3StorageDeviceInitListGuid, S3InitDevices, &S3InitDevicesLength);
+ if (EFI_ERROR (Status)) {
+ return Skip;
+ }
+ }
+
+ if (S3InitDevices == NULL) {
+ return Skip;
+ }
+
+ //
+ // Only need to initialize the controllers that exist in the device list.
+ //
+ do {
+ //
+ // Fetch the size of current device path instance.
+ //
+ Status = GetDevicePathInstanceSize (
+ S3InitDevices,
+ &DevicePathInstLength,
+ &EntireEnd
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ DevicePathInst = S3InitDevices;
+ S3InitDevices = (EFI_DEVICE_PATH_PROTOCOL *)((UINTN) S3InitDevices + DevicePathInstLength);
+
+ if (HcDevicePathLength >= DevicePathInstLength) {
+ continue;
+ }
+
+ //
+ // Compare the device paths to determine if the device is managed by this
+ // controller.
+ //
+ if (CompareMem (
+ DevicePathInst,
+ HcDevicePath,
+ HcDevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL)
+ ) == 0) {
+ Skip = FALSE;
+ break;
+ }
+ } while (!EntireEnd);
+
+ return Skip;
+}
--
2.12.0.windows.1
next prev parent reply other threads:[~2019-02-21 0:24 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-02-21 0:24 [PATCH v6 00/13] Split the S3 PEI phase HW init codes from Opal driver Hao Wu
2019-02-21 0:24 ` [PATCH v6 01/13] MdeModulePkg: Add definitions for ATA AHCI host controller PPI Hao Wu
2019-02-21 0:24 ` [PATCH v6 02/13] MdeModulePkg: Add definitions for EDKII PEI ATA PassThru PPI Hao Wu
2019-02-21 0:24 ` [PATCH v6 03/13] MdeModulePkg: Add definitions for Storage Security Command PPI Hao Wu
2019-02-21 0:24 ` [PATCH v6 04/13] MdeModulePkg: Add GUID for LockBox to save storage dev to init in S3 Hao Wu
2019-02-21 0:24 ` [PATCH v6 05/13] MdeModulePkg/NvmExpressPei: Avoid updating the module-level variable Hao Wu
2019-02-21 0:24 ` [PATCH v6 06/13] MdeModulePkg/NvmExpressPei: Add logic to produce SSC PPI Hao Wu
2019-02-21 0:24 ` Hao Wu [this message]
2019-02-21 0:24 ` [PATCH v6 08/13] MdeModulePkg/AhciPei: Add AHCI mode ATA device support in PEI Hao Wu
2019-02-21 0:24 ` [PATCH v6 09/13] MdeModulePkg/SmmLockBoxLib: Use 'DEBUG_' prefix instead of 'EFI_D_' Hao Wu
2019-02-21 0:24 ` [PATCH v6 10/13] MdeModulePkg/SmmLockBox(PEI): Remove an ASSERT in RestoreLockBox() Hao Wu
2019-02-21 0:24 ` [PATCH v6 11/13] MdeModulePkg/SmmLockBoxLib: Support LockBox enlarge in UpdateLockBox() Hao Wu
2019-02-21 0:24 ` [PATCH v6 12/13] OvmfPkg/LockBoxLib: Update the comments for API UpdateLockBox() Hao Wu
2019-02-21 0:24 ` [PATCH v6 13/13] SecurityPkg/OpalPassword: Remove HW init codes and consume SSC PPI Hao Wu
2019-02-21 4:50 ` Ni, Ray
2019-02-21 5:48 ` Dong, Eric
2019-02-22 1:54 ` [PATCH v6 00/13] Split the S3 PEI phase HW init codes from Opal driver Wu, Hao A
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190221002440.2272-8-hao.a.wu@intel.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox