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>

authored by Rafael J. Wysocki and committed by Jeff Garzik 2a6e58d2 d7b1956f

+19 -3
+17 -3
drivers/ata/libata-scsi.c
··· 46 46 #include <linux/libata.h> 47 47 #include <linux/hdreg.h> 48 48 #include <linux/uaccess.h> 49 + #include <linux/suspend.h> 49 50 50 51 #include "libata.h" 51 52 ··· 1304 1303 1305 1304 tf->command = ATA_CMD_VERIFY; /* READ VERIFY */ 1306 1305 } else { 1306 + /* Some odd clown BIOSen issue spindown on power off (ACPI S4 1307 + * or S5) causing some drives to spin up and down again. 1308 + */ 1309 + if ((qc->ap->flags & ATA_FLAG_NO_POWEROFF_SPINDOWN) && 1310 + system_state == SYSTEM_POWER_OFF) 1311 + goto skip; 1312 + 1313 + if ((qc->ap->flags & ATA_FLAG_NO_HIBERNATE_SPINDOWN) && 1314 + system_entering_hibernation()) 1315 + goto skip; 1316 + 1307 1317 /* XXX: This is for backward compatibility, will be 1308 1318 * removed. Read Documentation/feature-removal-schedule.txt 1309 1319 * for more info. ··· 1338 1326 scmd->scsi_done = qc->scsidone; 1339 1327 qc->scsidone = ata_delayed_done; 1340 1328 } 1341 - scmd->result = SAM_STAT_GOOD; 1342 - return 1; 1329 + goto skip; 1343 1330 } 1344 1331 1345 1332 /* Issue ATA STANDBY IMMEDIATE command */ ··· 1354 1343 1355 1344 return 0; 1356 1345 1357 - invalid_fld: 1346 + invalid_fld: 1358 1347 ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0); 1359 1348 /* "Invalid field in cbd" */ 1349 + return 1; 1350 + skip: 1351 + scmd->result = SAM_STAT_GOOD; 1360 1352 return 1; 1361 1353 } 1362 1354
+2
include/linux/libata.h
··· 187 187 ATA_FLAG_PIO_POLLING = (1 << 9), /* use polling PIO if LLD 188 188 * doesn't handle PIO interrupts */ 189 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 192 ATA_FLAG_DEBUGMSG = (1 << 13), 191 193 ATA_FLAG_IGN_SIMPLEX = (1 << 15), /* ignore SIMPLEX */ 192 194 ATA_FLAG_NO_IORDY = (1 << 16), /* controller lacks iordy */