[PATCH 7/7] ata: libata-eh: Always disable DIPM before calling set_lpm() callback

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The current code performs a SET FEATURES command to disable DIPM if
policy < ATA_LPM_MED_POWER_WITH_DIPM, this means that it will disable
DIPM for policies:
ATA_LPM_UNKNOWN, ATA_LPM_MAX_POWER, ATA_LPM_MED_POWER
(but not for policy ATA_LPM_MED_POWER_WITH_DIPM).

The code called after calling the set_lpm() callback will later perform
a SET FEATURES command to enable DIPM, if
policy >= ATA_LPM_MED_POWER_WITH_DIPM

It seems very logical to disable DIPM before the set_lpm() callback is
called, because the set_lpm() callback is the function (for AHCI) that
sets the proper bits in PxSCTL.IPM, reflecting the support of the HBA.
PxSCTL.IPM controls the LPM states that the device is allowed to enter.

If the device tries to enter a state disabled by PxSCTL.IPM, the
host will NAK the transition.

It is thus imperative that PxSCTL.IPM is written before DIPM is enabled,
to stop the device from entering a state that the host does not support.

While AHCI 1.3.1, section "8.3.1.1 Device Initiated" states:
"""
By default, a device that supports initiating interface power management
states has the capability disabled.
"""

This makes it seem harmless to not disable DIPM before writing PxSCTL.IPM,
however, SATA 3.5a section "13.3.4 Enable/disable Device-initiated
interface power state transitions feature" states:
"""
If Software Settings Preservation is enabled and Device Initiated
Interface Power Management Software Settings Preservation is supported
(see 13.7.11.2.26), then the enable/disable state shall persist across a
COMRESET.
"""

Further SATA 3.5a, section "13.3.7 Enable/disable Software Settings
Preservation feature" states that:
"""
By default, if the device supports software settings preservation, the
feature is enabled on power-up.
"""

Which means that it is possible that DIPM is enabled at probe time,
even after ata_eh_reset() has performed a COMRESET, thus, make sure that
DIPM is always disabled before calling the set_lpm() callback (which will
write PxSCTL.IPM).

For a LPM policy that includes DIPM, ata_eh_set_lpm() will still enable
DIPM using a SET FEATURES command after the set_lpm() callback has been
called (assuming that both the device and host supports DIPM).

Signed-off-by: Niklas Cassel <cassel@xxxxxxxxxx>
---
 drivers/ata/libata-eh.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 91d97d98eed1..1727248f135d 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -3473,7 +3473,7 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
 			hints &= ~ATA_LPM_HIPM;
 
 		/* disable DIPM before changing link config */
-		if (policy < ATA_LPM_MED_POWER_WITH_DIPM && dev_has_dipm) {
+		if (dev_has_dipm) {
 			err_mask = ata_dev_set_feature(dev,
 					SETFEATURES_SATA_DISABLE, SATA_DIPM);
 			if (err_mask && err_mask != AC_ERR_DEV) {
-- 
2.49.0





[Index of Archives]     [Linux Filesystems]     [Linux SCSI]     [Linux RAID]     [Git]     [Kernel Newbies]     [Linux Newbie]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Samba]     [Device Mapper]

  Powered by Linux