|
@@ -3275,6 +3275,7 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
|
|
|
struct ata_port *ap = ata_is_host_link(link) ? link->ap : NULL;
|
|
|
struct ata_eh_context *ehc = &link->eh_context;
|
|
|
struct ata_device *dev, *link_dev = NULL, *lpm_dev = NULL;
|
|
|
+ enum ata_lpm_policy old_policy = link->lpm_policy;
|
|
|
unsigned int hints = ATA_LPM_EMPTY | ATA_LPM_HIPM;
|
|
|
unsigned int err_mask;
|
|
|
int rc;
|
|
@@ -3338,6 +3339,14 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
|
|
|
goto fail;
|
|
|
}
|
|
|
|
|
|
+ /*
|
|
|
+ * Low level driver acked the transition. Issue DIPM command
|
|
|
+ * with the new policy set.
|
|
|
+ */
|
|
|
+ link->lpm_policy = policy;
|
|
|
+ if (ap && ap->slave_link)
|
|
|
+ ap->slave_link->lpm_policy = policy;
|
|
|
+
|
|
|
/* host config updated, enable DIPM if transitioning to MIN_POWER */
|
|
|
ata_for_each_dev(dev, link, ENABLED) {
|
|
|
if (policy == ATA_LPM_MIN_POWER && ata_id_has_dipm(dev->id)) {
|
|
@@ -3353,12 +3362,14 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- link->lpm_policy = policy;
|
|
|
- if (ap && ap->slave_link)
|
|
|
- ap->slave_link->lpm_policy = policy;
|
|
|
return 0;
|
|
|
|
|
|
fail:
|
|
|
+ /* restore the old policy */
|
|
|
+ link->lpm_policy = old_policy;
|
|
|
+ if (ap && ap->slave_link)
|
|
|
+ ap->slave_link->lpm_policy = old_policy;
|
|
|
+
|
|
|
/* if no device or only one more chance is left, disable LPM */
|
|
|
if (!dev || ehc->tries[dev->devno] <= 2) {
|
|
|
ata_link_printk(link, KERN_WARNING,
|