| From foo@baz Mon Sep 17 12:33:31 CEST 2018 |
| From: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> |
| Date: Mon, 2 Jul 2018 12:01:54 -0700 |
| Subject: ata: libahci: Allow reconfigure of DEVSLP register |
| |
| From: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> |
| |
| [ Upstream commit 11c291461b6ea8d1195a96d6bba6673a94aacebc ] |
| |
| There are two modes in which DEVSLP can be entered. The OS initiated or |
| hardware autonomous. |
| |
| In hardware autonomous mode, BIOS configures the AHCI controller and the |
| device to enable DEVSLP. But they may not be ideal for all cases. So in |
| this case, OS should be able to reconfigure DEVSLP register. |
| |
| Currently if the DEVSLP is already enabled, we can't set again as it will |
| simply return. There are some systems where the firmware is setting high |
| DITO by default, in this case we can't modify here to correct settings. |
| With the default in several seconds, we are not able to transition to |
| DEVSLP. |
| |
| This change will allow reconfiguration of devslp register if DITO is |
| different. |
| |
| Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> |
| Reviewed-by: Hans de Goede <hdegoede@redhat.com> |
| Signed-off-by: Tejun Heo <tj@kernel.org> |
| Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/ata/libahci.c | 18 ++++++++++-------- |
| 1 file changed, 10 insertions(+), 8 deletions(-) |
| |
| --- a/drivers/ata/libahci.c |
| +++ b/drivers/ata/libahci.c |
| @@ -2096,7 +2096,7 @@ static void ahci_set_aggressive_devslp(s |
| struct ahci_host_priv *hpriv = ap->host->private_data; |
| void __iomem *port_mmio = ahci_port_base(ap); |
| struct ata_device *dev = ap->link.device; |
| - u32 devslp, dm, dito, mdat, deto; |
| + u32 devslp, dm, dito, mdat, deto, dito_conf; |
| int rc; |
| unsigned int err_mask; |
| |
| @@ -2120,8 +2120,15 @@ static void ahci_set_aggressive_devslp(s |
| return; |
| } |
| |
| - /* device sleep was already enabled */ |
| - if (devslp & PORT_DEVSLP_ADSE) |
| + dm = (devslp & PORT_DEVSLP_DM_MASK) >> PORT_DEVSLP_DM_OFFSET; |
| + dito = devslp_idle_timeout / (dm + 1); |
| + if (dito > 0x3ff) |
| + dito = 0x3ff; |
| + |
| + dito_conf = (devslp >> PORT_DEVSLP_DITO_OFFSET) & 0x3FF; |
| + |
| + /* device sleep was already enabled and same dito */ |
| + if ((devslp & PORT_DEVSLP_ADSE) && (dito_conf == dito)) |
| return; |
| |
| /* set DITO, MDAT, DETO and enable DevSlp, need to stop engine first */ |
| @@ -2129,11 +2136,6 @@ static void ahci_set_aggressive_devslp(s |
| if (rc) |
| return; |
| |
| - dm = (devslp & PORT_DEVSLP_DM_MASK) >> PORT_DEVSLP_DM_OFFSET; |
| - dito = devslp_idle_timeout / (dm + 1); |
| - if (dito > 0x3ff) |
| - dito = 0x3ff; |
| - |
| /* Use the nominal value 10 ms if the read MDAT is zero, |
| * the nominal value of DETO is 20 ms. |
| */ |