@@ -1993,7 +1993,13 @@ retry:
goto err_out;
}
- if (!tried_spinup && (id[2] == 0x37c8 || id[2] == 0x738c)) {
+ if (flags & ATA_READID_NOSTART && id[2] == 0x37c8)
+ {
+ dev->flags |= ATA_DFLAG_SLEEPING;
+ return -EAGAIN;
+ }
+ if (!(flags & ATA_READID_NOSTART) &&
+ !tried_spinup && (id[2] == 0x37c8 || id[2] == 0x738c)) {
tried_spinup = 1;
/*
* Drive powered-up in standby mode, and requires a specific
@@ -4024,6 +4030,8 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
/* re-read ID */
rc = ata_dev_reread_id(dev, readid_flags);
+ if (rc == -EAGAIN)
+ return rc;
if (rc)
goto fail;
@@ -5414,7 +5422,7 @@ static int __ata_port_resume_common(struct ata_port *ap, pm_message_t mesg,
int rc;
rc = ata_port_request_pm(ap, mesg, ATA_EH_RESET,
- ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, async);
+ ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET | ATA_EHI_NOSTART, async);
return rc;
}
@@ -3086,6 +3086,8 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
if (ehc->i.flags & ATA_EHI_DID_RESET)
readid_flags |= ATA_READID_POSTRESET;
+ if (ehc->i.flags & ATA_EHI_NOSTART)
+ readid_flags |= ATA_READID_NOSTART;
if ((action & ATA_EH_REVALIDATE) && ata_dev_enabled(dev)) {
WARN_ON(dev->class == ATA_DEV_PMP);
@@ -3098,6 +3100,10 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
ata_eh_about_to_do(link, dev, ATA_EH_REVALIDATE);
rc = ata_dev_revalidate(dev, ehc->classes[dev->devno],
readid_flags);
+ if (rc == -EAGAIN) {
+ rc = 0; /* start required but suppressed, handle later */
+ continue;
+ }
if (rc)
goto err;
@@ -3424,7 +3430,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_MIN_POWER && dipm) {
+ if (policy != ATA_LPM_MIN_POWER && dipm && !(dev->flags & ATA_DFLAG_SLEEPING)) {
err_mask = ata_dev_set_feature(dev,
SETFEATURES_SATA_DISABLE, SATA_DIPM);
if (err_mask && err_mask != AC_ERR_DEV) {
@@ -3468,7 +3474,7 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_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 && !no_dipm &&
- ata_id_has_dipm(dev->id)) {
+ ata_id_has_dipm(dev->id) && !(dev->flags & ATA_DFLAG_SLEEPING)) {
err_mask = ata_dev_set_feature(dev,
SETFEATURES_SATA_ENABLE, SATA_DIPM);
if (err_mask && err_mask != AC_ERR_DEV) {
@@ -42,6 +42,7 @@ struct ata_scsi_args {
enum {
/* flags for ata_dev_read_id() */
ATA_READID_POSTRESET = (1 << 0), /* reading ID after reset */
+ ATA_READID_NOSTART = (1 << 1), /* do not start drive */
/* selector for ata_down_xfermask_limit() */
ATA_DNXFER_PIO = 0, /* speed down PIO */
@@ -362,6 +362,7 @@ enum {
/* ata_eh_info->flags */
ATA_EHI_HOTPLUGGED = (1 << 0), /* could have been hotplugged */
+ ATA_EHI_NOSTART = (1 << 1), /* don't start the disk */
ATA_EHI_NO_AUTOPSY = (1 << 2), /* no autopsy */
ATA_EHI_QUIET = (1 << 3), /* be quiet */
ATA_EHI_NO_RECOVERY = (1 << 4), /* no recovery */