diff options
| author | Rafael J. Wysocki <rjw@sisk.pl> | 2009-01-19 14:56:43 -0500 |
|---|---|---|
| committer | Jeff Garzik <jgarzik@redhat.com> | 2009-01-27 02:15:49 -0500 |
| commit | 2a6e58d2731dcc05dafa7f976d935e0f0627fcd7 (patch) | |
| tree | 836d0ec85dccde709aeaaedb3b7686ac51805ad1 | |
| parent | d7b1956fed33d30c4815e848fd7a143722916868 (diff) | |
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: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
| -rw-r--r-- | drivers/ata/libata-scsi.c | 20 | ||||
| -rw-r--r-- | include/linux/libata.h | 2 |
2 files changed, 19 insertions, 3 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index a1a6e6298c33..3c4c5ae277ba 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c | |||
| @@ -46,6 +46,7 @@ | |||
| 46 | #include <linux/libata.h> | 46 | #include <linux/libata.h> |
| 47 | #include <linux/hdreg.h> | 47 | #include <linux/hdreg.h> |
| 48 | #include <linux/uaccess.h> | 48 | #include <linux/uaccess.h> |
| 49 | #include <linux/suspend.h> | ||
| 49 | 50 | ||
| 50 | #include "libata.h" | 51 | #include "libata.h" |
| 51 | 52 | ||
| @@ -1303,6 +1304,17 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc) | |||
| 1303 | 1304 | ||
| 1304 | tf->command = ATA_CMD_VERIFY; /* READ VERIFY */ | 1305 | tf->command = ATA_CMD_VERIFY; /* READ VERIFY */ |
| 1305 | } else { | 1306 | } else { |
| 1307 | /* Some odd clown BIOSen issue spindown on power off (ACPI S4 | ||
| 1308 | * or S5) causing some drives to spin up and down again. | ||
| 1309 | */ | ||
| 1310 | if ((qc->ap->flags & ATA_FLAG_NO_POWEROFF_SPINDOWN) && | ||
| 1311 | system_state == SYSTEM_POWER_OFF) | ||
| 1312 | goto skip; | ||
| 1313 | |||
| 1314 | if ((qc->ap->flags & ATA_FLAG_NO_HIBERNATE_SPINDOWN) && | ||
| 1315 | system_entering_hibernation()) | ||
| 1316 | goto skip; | ||
| 1317 | |||
| 1306 | /* XXX: This is for backward compatibility, will be | 1318 | /* XXX: This is for backward compatibility, will be |
| 1307 | * removed. Read Documentation/feature-removal-schedule.txt | 1319 | * removed. Read Documentation/feature-removal-schedule.txt |
| 1308 | * for more info. | 1320 | * for more info. |
| @@ -1326,8 +1338,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc) | |||
| 1326 | scmd->scsi_done = qc->scsidone; | 1338 | scmd->scsi_done = qc->scsidone; |
| 1327 | qc->scsidone = ata_delayed_done; | 1339 | qc->scsidone = ata_delayed_done; |
| 1328 | } | 1340 | } |
| 1329 | scmd->result = SAM_STAT_GOOD; | 1341 | goto skip; |
| 1330 | return 1; | ||
| 1331 | } | 1342 | } |
| 1332 | 1343 | ||
| 1333 | /* Issue ATA STANDBY IMMEDIATE command */ | 1344 | /* Issue ATA STANDBY IMMEDIATE command */ |
| @@ -1343,10 +1354,13 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc) | |||
| 1343 | 1354 | ||
| 1344 | return 0; | 1355 | return 0; |
| 1345 | 1356 | ||
| 1346 | invalid_fld: | 1357 | invalid_fld: |
| 1347 | ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0); | 1358 | ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0); |
| 1348 | /* "Invalid field in cbd" */ | 1359 | /* "Invalid field in cbd" */ |
| 1349 | return 1; | 1360 | return 1; |
| 1361 | skip: | ||
| 1362 | scmd->result = SAM_STAT_GOOD; | ||
| 1363 | return 1; | ||
| 1350 | } | 1364 | } |
| 1351 | 1365 | ||
| 1352 | 1366 | ||
diff --git a/include/linux/libata.h b/include/linux/libata.h index 2c6bd66209ff..bca3ba25f52a 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
| @@ -187,6 +187,8 @@ enum { | |||
| 187 | ATA_FLAG_PIO_POLLING = (1 << 9), /* use polling PIO if LLD | 187 | ATA_FLAG_PIO_POLLING = (1 << 9), /* use polling PIO if LLD |
| 188 | * doesn't handle PIO interrupts */ | 188 | * doesn't handle PIO interrupts */ |
| 189 | ATA_FLAG_NCQ = (1 << 10), /* host supports NCQ */ | 189 | ATA_FLAG_NCQ = (1 << 10), /* host supports NCQ */ |
| 190 | ATA_FLAG_NO_POWEROFF_SPINDOWN = (1 << 11), /* don't spindown before poweroff */ | ||
| 191 | ATA_FLAG_NO_HIBERNATE_SPINDOWN = (1 << 12), /* don't spindown before hibernation */ | ||
| 190 | ATA_FLAG_DEBUGMSG = (1 << 13), | 192 | ATA_FLAG_DEBUGMSG = (1 << 13), |
| 191 | ATA_FLAG_IGN_SIMPLEX = (1 << 15), /* ignore SIMPLEX */ | 193 | ATA_FLAG_IGN_SIMPLEX = (1 << 15), /* ignore SIMPLEX */ |
| 192 | ATA_FLAG_NO_IORDY = (1 << 16), /* controller lacks iordy */ | 194 | ATA_FLAG_NO_IORDY = (1 << 16), /* controller lacks iordy */ |
