Skip to content

Commit 89a4681

Browse files
Niklas Casselroxanan1996
Niklas Cassel
authored andcommitted
ata: libata: disallow dev-initiated LPM transitions to unsupported states
BugLink: https://bugs.launchpad.net/bugs/2043422 commit 24e0e61 upstream. In AHCI 1.3.1, the register description for CAP.SSC: "When cleared to ‘0’, software must not allow the HBA to initiate transitions to the Slumber state via agressive link power management nor the PxCMD.ICC field in each port, and the PxSCTL.IPM field in each port must be programmed to disallow device initiated Slumber requests." In AHCI 1.3.1, the register description for CAP.PSC: "When cleared to ‘0’, software must not allow the HBA to initiate transitions to the Partial state via agressive link power management nor the PxCMD.ICC field in each port, and the PxSCTL.IPM field in each port must be programmed to disallow device initiated Partial requests." Ensure that we always set the corresponding bits in PxSCTL.IPM, such that a device is not allowed to initiate transitions to power states which are unsupported by the HBA. DevSleep is always initiated by the HBA, however, for completeness, set the corresponding bit in PxSCTL.IPM such that agressive link power management cannot transition to DevSleep if DevSleep is not supported. sata_link_scr_lpm() is used by libahci, ata_piix and libata-pmp. However, only libahci has the ability to read the CAP/CAP2 register to see if these features are supported. Therefore, in order to not introduce any regressions on ata_piix or libata-pmp, create flags that indicate that the respective feature is NOT supported. This way, the behavior for ata_piix and libata-pmp should remain unchanged. This change is based on a patch originally submitted by Runa Guo-oc. Signed-off-by: Niklas Cassel <[email protected]> Fixes: 1152b26 ("libata: implement sata_link_scr_lpm() and make ata_dev_set_feature() global") Cc: [email protected] Signed-off-by: Damien Le Moal <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]> Signed-off-by: Kamal Mostafa <[email protected]> Signed-off-by: Stefan Bader <[email protected]>
1 parent c580ea8 commit 89a4681

File tree

3 files changed

+29
-3
lines changed

3 files changed

+29
-3
lines changed

drivers/ata/ahci.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1886,6 +1886,15 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
18861886
else
18871887
dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n");
18881888

1889+
if (!(hpriv->cap & HOST_CAP_PART))
1890+
host->flags |= ATA_HOST_NO_PART;
1891+
1892+
if (!(hpriv->cap & HOST_CAP_SSC))
1893+
host->flags |= ATA_HOST_NO_SSC;
1894+
1895+
if (!(hpriv->cap2 & HOST_CAP2_SDS))
1896+
host->flags |= ATA_HOST_NO_DEVSLP;
1897+
18891898
if (pi.flags & ATA_FLAG_EM)
18901899
ahci_reset_em(host);
18911900

drivers/ata/libata-sata.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -394,10 +394,23 @@ int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy,
394394
case ATA_LPM_MED_POWER_WITH_DIPM:
395395
case ATA_LPM_MIN_POWER_WITH_PARTIAL:
396396
case ATA_LPM_MIN_POWER:
397-
if (ata_link_nr_enabled(link) > 0)
398-
/* no restrictions on LPM transitions */
397+
if (ata_link_nr_enabled(link) > 0) {
398+
/* assume no restrictions on LPM transitions */
399399
scontrol &= ~(0x7 << 8);
400-
else {
400+
401+
/*
402+
* If the controller does not support partial, slumber,
403+
* or devsleep, then disallow these transitions.
404+
*/
405+
if (link->ap->host->flags & ATA_HOST_NO_PART)
406+
scontrol |= (0x1 << 8);
407+
408+
if (link->ap->host->flags & ATA_HOST_NO_SSC)
409+
scontrol |= (0x2 << 8);
410+
411+
if (link->ap->host->flags & ATA_HOST_NO_DEVSLP)
412+
scontrol |= (0x4 << 8);
413+
} else {
401414
/* empty port, power off */
402415
scontrol &= ~0xf;
403416
scontrol |= (0x1 << 2);

include/linux/libata.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,10 @@ enum {
264264
ATA_HOST_PARALLEL_SCAN = (1 << 2), /* Ports on this host can be scanned in parallel */
265265
ATA_HOST_IGNORE_ATA = (1 << 3), /* Ignore ATA devices on this host. */
266266

267+
ATA_HOST_NO_PART = (1 << 4), /* Host does not support partial */
268+
ATA_HOST_NO_SSC = (1 << 5), /* Host does not support slumber */
269+
ATA_HOST_NO_DEVSLP = (1 << 6), /* Host does not support devslp */
270+
267271
/* bits 24:31 of host->flags are reserved for LLD specific flags */
268272

269273
/* various lengths of time */

0 commit comments

Comments
 (0)