Patch "ata: libata: disallow dev-initiated LPM transitions to unsupported states" has been added to the 5.4-stable tree

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

 



This is a note to let you know that I've just added the patch titled

    ata: libata: disallow dev-initiated LPM transitions to unsupported states

to the 5.4-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     ata-libata-disallow-dev-initiated-lpm-transitions-to.patch
and it can be found in the queue-5.4 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit fe10e3a0490f7259035dbdebb653f46093c10c9e
Author: Niklas Cassel <niklas.cassel@xxxxxxx>
Date:   Mon Sep 4 22:42:56 2023 +0200

    ata: libata: disallow dev-initiated LPM transitions to unsupported states
    
    [ Upstream commit 24e0e61db3cb86a66824531989f1df80e0939f26 ]
    
    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 <niklas.cassel@xxxxxxx>
    Fixes: 1152b2617a6e ("libata: implement sata_link_scr_lpm() and make ata_dev_set_feature() global")
    Cc: stable@xxxxxxxxxxxxxxx
    Signed-off-by: Damien Le Moal <dlemoal@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 4069c2a79daa2..aa35d1941d1fc 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1838,6 +1838,15 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	else
 		dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n");
 
+	if (!(hpriv->cap & HOST_CAP_PART))
+		host->flags |= ATA_HOST_NO_PART;
+
+	if (!(hpriv->cap & HOST_CAP_SSC))
+		host->flags |= ATA_HOST_NO_SSC;
+
+	if (!(hpriv->cap2 & HOST_CAP2_SDS))
+		host->flags |= ATA_HOST_NO_DEVSLP;
+
 	if (pi.flags & ATA_FLAG_EM)
 		ahci_reset_em(host);
 
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 1e057162e00eb..cec1be2cae47d 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4023,10 +4023,23 @@ int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy,
 	case ATA_LPM_MED_POWER_WITH_DIPM:
 	case ATA_LPM_MIN_POWER_WITH_PARTIAL:
 	case ATA_LPM_MIN_POWER:
-		if (ata_link_nr_enabled(link) > 0)
-			/* no restrictions on LPM transitions */
+		if (ata_link_nr_enabled(link) > 0) {
+			/* assume no restrictions on LPM transitions */
 			scontrol &= ~(0x7 << 8);
-		else {
+
+			/*
+			 * If the controller does not support partial, slumber,
+			 * or devsleep, then disallow these transitions.
+			 */
+			if (link->ap->host->flags & ATA_HOST_NO_PART)
+				scontrol |= (0x1 << 8);
+
+			if (link->ap->host->flags & ATA_HOST_NO_SSC)
+				scontrol |= (0x2 << 8);
+
+			if (link->ap->host->flags & ATA_HOST_NO_DEVSLP)
+				scontrol |= (0x4 << 8);
+		} else {
 			/* empty port, power off */
 			scontrol &= ~0xf;
 			scontrol |= (0x1 << 2);
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 2e448d65a04c7..3804988095f99 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -261,6 +261,10 @@ enum {
 	ATA_HOST_PARALLEL_SCAN	= (1 << 2),	/* Ports on this host can be scanned in parallel */
 	ATA_HOST_IGNORE_ATA	= (1 << 3),	/* Ignore ATA devices on this host. */
 
+	ATA_HOST_NO_PART	= (1 << 4), /* Host does not support partial */
+	ATA_HOST_NO_SSC		= (1 << 5), /* Host does not support slumber */
+	ATA_HOST_NO_DEVSLP	= (1 << 6), /* Host does not support devslp */
+
 	/* bits 24:31 of host->flags are reserved for LLD specific flags */
 
 	/* various lengths of time */



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux