@@ -3622,6 +3622,10 @@ int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy,
/* no restrictions on LPM transitions */
scontrol &= ~(0x3 << 8);
break;
+ case ATA_LPM_POWER_OFF:
+ scontrol &= ~0xf;
+ scontrol |= (0x1 << 2);
+ break;
default:
WARN_ON(1);
}
@@ -3754,6 +3754,11 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
config_lpm:
/* configure link power saving */
if (link->lpm_policy != ap->target_lpm_policy) {
+ /* refuse to power off occupied port */
+ if (ap->target_lpm_policy == ATA_LPM_POWER_OFF &&
+ (ata_link_nr_enabled(link) > 0))
+ goto out;
+
rc = ata_eh_set_lpm(link, ap->target_lpm_policy, &dev);
if (rc)
goto rest_fail;
@@ -108,6 +108,7 @@ static const char *ata_lpm_policy_names[] = {
[ATA_LPM_MAX_POWER] = "max_performance",
[ATA_LPM_MED_POWER] = "medium_power",
[ATA_LPM_MIN_POWER] = "min_power",
+ [ATA_LPM_POWER_OFF] = "power_off",
};
static ssize_t ata_scsi_lpm_store(struct device *dev,
@@ -473,6 +473,7 @@ enum ata_lpm_policy {
ATA_LPM_MAX_POWER,
ATA_LPM_MED_POWER,
ATA_LPM_MIN_POWER,
+ ATA_LPM_POWER_OFF,
};
enum ata_lpm_hints {
Signed-off-by: Kristen Carlson Accardi <kristen@linux.intel.com> --- drivers/ata/libata-core.c | 4 ++++ drivers/ata/libata-eh.c | 5 +++++ drivers/ata/libata-scsi.c | 1 + include/linux/libata.h | 1 + 4 files changed, 11 insertions(+), 0 deletions(-)