]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
ACPI: Check StorageD3Enable _DSD property in ACPI code
authorMario Limonciello <mario.limonciello@amd.com>
Wed, 9 Jun 2021 18:40:17 +0000 (13:40 -0500)
committerChristoph Hellwig <hch@lst.de>
Wed, 16 Jun 2021 03:14:59 +0000 (05:14 +0200)
Although first implemented for NVME, this check may be usable by
other drivers as well. Microsoft's specification explicitly mentions
that is may be usable by SATA and AHCI devices.  Google also indicates
that they have used this with SDHCI in a downstream kernel tree that
a user can plug a storage device into.

Link: https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/power-management-for-storage-hardware-devices-intro
Suggested-by: Keith Busch <kbusch@kernel.org>
CC: Shyam-sundar S-k <Shyam-sundar.S-k@amd.com>
CC: Alexander Deucher <Alexander.Deucher@amd.com>
CC: Rafael J. Wysocki <rjw@rjwysocki.net>
CC: Prike Liang <prike.liang@amd.com>
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
drivers/acpi/device_pm.c
drivers/nvme/host/pci.c
include/linux/acpi.h

index d260bc1f3e6e72a12310ba92e8b1f399d0cdb04e..d76ab50c71dc2f37eb00a115e24536442df22124 100644 (file)
@@ -1340,4 +1340,33 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on)
        return 1;
 }
 EXPORT_SYMBOL_GPL(acpi_dev_pm_attach);
+
+/**
+ * acpi_storage_d3 - Check if D3 should be used in the suspend path
+ * @dev: Device to check
+ *
+ * Return %true if the platform firmware wants @dev to be programmed
+ * into D3hot or D3cold (if supported) in the suspend path, or %false
+ * when there is no specific preference. On some platforms, if this
+ * hint is ignored, @dev may remain unresponsive after suspending the
+ * platform as a whole.
+ *
+ * Although the property has storage in the name it actually is
+ * applied to the PCIe slot and plugging in a non-storage device the
+ * same platform restrictions will likely apply.
+ */
+bool acpi_storage_d3(struct device *dev)
+{
+       struct acpi_device *adev = ACPI_COMPANION(dev);
+       u8 val;
+
+       if (!adev)
+               return false;
+       if (fwnode_property_read_u8(acpi_fwnode_handle(adev), "StorageD3Enable",
+                       &val))
+               return false;
+       return val == 1;
+}
+EXPORT_SYMBOL_GPL(acpi_storage_d3);
+
 #endif /* CONFIG_PM */
index 3aa7245a505fd76bdbaf29b6eca495203f810f7f..8fbc4c87a0d86193db5e20d69b6220bad6fe9649 100644 (file)
@@ -2828,32 +2828,6 @@ static unsigned long check_vendor_combination_bug(struct pci_dev *pdev)
        return 0;
 }
 
-#ifdef CONFIG_ACPI
-static bool nvme_acpi_storage_d3(struct pci_dev *dev)
-{
-       struct acpi_device *adev = ACPI_COMPANION(&dev->dev);
-       u8 val;
-
-       /*
-        * Look for _DSD property specifying that the storage device on the port
-        * must use D3 to support deep platform power savings during
-        * suspend-to-idle.
-        */
-
-       if (!adev)
-               return false;
-       if (fwnode_property_read_u8(acpi_fwnode_handle(adev), "StorageD3Enable",
-                       &val))
-               return false;
-       return val == 1;
-}
-#else
-static inline bool nvme_acpi_storage_d3(struct pci_dev *dev)
-{
-       return false;
-}
-#endif /* CONFIG_ACPI */
-
 static void nvme_async_probe(void *data, async_cookie_t cookie)
 {
        struct nvme_dev *dev = data;
@@ -2903,7 +2877,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        quirks |= check_vendor_combination_bug(pdev);
 
-       if (!noacpi && nvme_acpi_storage_d3(pdev)) {
+       if (!noacpi && acpi_storage_d3(&pdev->dev)) {
                /*
                 * Some systems use a bios work around to ask for D3 on
                 * platforms that support kernel managed suspend.
index c60745f657e9c9fc10a5276bb90d466652fc9f9f..dd0dafd21e3386102406e581656c787c2f97cb0f 100644 (file)
@@ -1004,6 +1004,7 @@ int acpi_dev_resume(struct device *dev);
 int acpi_subsys_runtime_suspend(struct device *dev);
 int acpi_subsys_runtime_resume(struct device *dev);
 int acpi_dev_pm_attach(struct device *dev, bool power_on);
+bool acpi_storage_d3(struct device *dev);
 #else
 static inline int acpi_subsys_runtime_suspend(struct device *dev) { return 0; }
 static inline int acpi_subsys_runtime_resume(struct device *dev) { return 0; }
@@ -1011,6 +1012,10 @@ static inline int acpi_dev_pm_attach(struct device *dev, bool power_on)
 {
        return 0;
 }
+static inline bool acpi_storage_d3(struct device *dev)
+{
+       return false;
+}
 #endif
 
 #if defined(CONFIG_ACPI) && defined(CONFIG_PM_SLEEP)