summaryrefslogtreecommitdiff
path: root/drivers/ata
diff options
context:
space:
mode:
authorMario Limonciello <mario.limonciello@amd.com>2021-11-12 23:15:39 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-12-08 11:04:40 +0300
commitb56c75d4d3c3c614fa45a1d4199d0d196c80efba (patch)
tree771a48d1eb66835426706cdbdc4273327a58563f /drivers/ata
parentab8efdbda76ca5ac01d8e37929f31aa186549c63 (diff)
downloadlinux-b56c75d4d3c3c614fa45a1d4199d0d196c80efba.tar.xz
ata: libahci: Adjust behavior when StorageD3Enable _DSD is set
[ Upstream commit 7c5f641a5914ce0303b06bcfcd7674ee64aeebe9 ] The StorageD3Enable _DSD is used for the vendor to indicate that the disk should be opted into or out of a different behavior based upon the platform design. For AMD's Renoir and Green Sardine platforms it's important that any attached SATA storage has transitioned into DevSlp when s2idle is used. If the disk is left in active/partial/slumber, then the system is not able to resume properly. When the StorageD3Enable _DSD is detected, check the system is using s2idle and DevSlp is enabled and if so explicitly wait long enough for the disk to enter DevSlp. Cc: Nehal-bakulchandra Shah <Nehal-bakulchandra.Shah@amd.com> BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=214091 Link: https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/power-management-for-storage-hardware-devices-intro Signed-off-by: Mario Limonciello <mario.limonciello@amd.com> Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/libahci.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 5b3fa2cbe722..395772fa3943 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -2305,6 +2305,18 @@ int ahci_port_resume(struct ata_port *ap)
EXPORT_SYMBOL_GPL(ahci_port_resume);
#ifdef CONFIG_PM
+static void ahci_handle_s2idle(struct ata_port *ap)
+{
+ void __iomem *port_mmio = ahci_port_base(ap);
+ u32 devslp;
+
+ if (pm_suspend_via_firmware())
+ return;
+ devslp = readl(port_mmio + PORT_DEVSLP);
+ if ((devslp & PORT_DEVSLP_ADSE))
+ ata_msleep(ap, devslp_idle_timeout);
+}
+
static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
{
const char *emsg = NULL;
@@ -2318,6 +2330,9 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
ata_port_freeze(ap);
}
+ if (acpi_storage_d3(ap->host->dev))
+ ahci_handle_s2idle(ap);
+
ahci_rpm_put_port(ap);
return rc;
}