Commit 2a6e58d2 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki Committed by Jeff Garzik

SATA: Blacklisting of systems that spin off disks during ACPI power off

Introduce new libata flags ATA_FLAG_NO_POWEROFF_SPINDOWN and
ATA_FLAG_NO_HIBERNATE_SPINDOWN that, if set, will prevent disks from
being spun off during system power off and hibernation, respectively
(to handle the hibernation case we need the new system state
SYSTEM_HIBERNATE_ENTER that can be checked against by libata, in
analogy with SYSTEM_POWER_OFF).
Signed-off-by: default avatarRafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent d7b1956f
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#include <linux/libata.h> #include <linux/libata.h>
#include <linux/hdreg.h> #include <linux/hdreg.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/suspend.h>
#include "libata.h" #include "libata.h"
...@@ -1303,6 +1304,17 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc) ...@@ -1303,6 +1304,17 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
tf->command = ATA_CMD_VERIFY; /* READ VERIFY */ tf->command = ATA_CMD_VERIFY; /* READ VERIFY */
} else { } else {
/* Some odd clown BIOSen issue spindown on power off (ACPI S4
* or S5) causing some drives to spin up and down again.
*/
if ((qc->ap->flags & ATA_FLAG_NO_POWEROFF_SPINDOWN) &&
system_state == SYSTEM_POWER_OFF)
goto skip;
if ((qc->ap->flags & ATA_FLAG_NO_HIBERNATE_SPINDOWN) &&
system_entering_hibernation())
goto skip;
/* XXX: This is for backward compatibility, will be /* XXX: This is for backward compatibility, will be
* removed. Read Documentation/feature-removal-schedule.txt * removed. Read Documentation/feature-removal-schedule.txt
* for more info. * for more info.
...@@ -1326,8 +1338,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc) ...@@ -1326,8 +1338,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
scmd->scsi_done = qc->scsidone; scmd->scsi_done = qc->scsidone;
qc->scsidone = ata_delayed_done; qc->scsidone = ata_delayed_done;
} }
scmd->result = SAM_STAT_GOOD; goto skip;
return 1;
} }
/* Issue ATA STANDBY IMMEDIATE command */ /* Issue ATA STANDBY IMMEDIATE command */
...@@ -1343,10 +1354,13 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc) ...@@ -1343,10 +1354,13 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
return 0; return 0;
invalid_fld: invalid_fld:
ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0); ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0);
/* "Invalid field in cbd" */ /* "Invalid field in cbd" */
return 1; return 1;
skip:
scmd->result = SAM_STAT_GOOD;
return 1;
} }
......
...@@ -187,6 +187,8 @@ enum { ...@@ -187,6 +187,8 @@ enum {
ATA_FLAG_PIO_POLLING = (1 << 9), /* use polling PIO if LLD ATA_FLAG_PIO_POLLING = (1 << 9), /* use polling PIO if LLD
* doesn't handle PIO interrupts */ * doesn't handle PIO interrupts */
ATA_FLAG_NCQ = (1 << 10), /* host supports NCQ */ ATA_FLAG_NCQ = (1 << 10), /* host supports NCQ */
ATA_FLAG_NO_POWEROFF_SPINDOWN = (1 << 11), /* don't spindown before poweroff */
ATA_FLAG_NO_HIBERNATE_SPINDOWN = (1 << 12), /* don't spindown before hibernation */
ATA_FLAG_DEBUGMSG = (1 << 13), ATA_FLAG_DEBUGMSG = (1 << 13),
ATA_FLAG_IGN_SIMPLEX = (1 << 15), /* ignore SIMPLEX */ ATA_FLAG_IGN_SIMPLEX = (1 << 15), /* ignore SIMPLEX */
ATA_FLAG_NO_IORDY = (1 << 16), /* controller lacks iordy */ ATA_FLAG_NO_IORDY = (1 << 16), /* controller lacks iordy */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment