aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-05-04 15:28:48 -0400
committerJeff Garzik <jeff@garzik.org>2007-05-11 18:01:04 -0400
commit920a4b1038e442700a1cfac77ea7e20bd615a2c3 (patch)
tree4209c04b64b021a3e4253a484b108b2475a2860a /drivers
parent9666f4009c22f6520ac3fb8a19c9e32ab973e828 (diff)
libata: implement libata.spindown_compat
Now that libata uses sd->manage_start_stop, libata spins down disk on shutdown. In an attempt to compensate libata's previous shortcoming, some distros sync and spin down disks attached via libata in their shutdown(8). Some disks spin back up just to spin down again on STANDBYNOW1 if the command is issued when the disk is spun down, so this double spinning down causes problem. This patch implements module parameter libata.spindown_compat which, when set to one (default value), prevents libata from spinning down disks on shutdown thus avoiding double spinning down. Note that libata spins down disks for suspend to mem and disk, so with libata.spindown_compat set to one, disks should be properly spun down in all cases without modifying shutdown(8). shutdown(8) should be fixed eventually. Some drive do spin up on SYNCHRONZE_CACHE even when their cache is clean. Those disks currently spin up briefly when sd tries to shutdown the device and then the machine powers off immediately, which can't be good for the head. We can't skip SYNCHRONIZE_CACHE during shudown as it can be dangerous data integrity-wise. So, this spindown_compat parameter is already scheduled for removal by the end of the next year and here's what shutdown(8) should do. * Check whether /sys/modules/libata/parameters/spindown_compat exists. If it does, write 0 to it. * For each libata harddisk { * Check whether /sys/class/scsi_disk/h:c:i:l/manage_start_stop exists. Iff it doesn't, synchronize cache and spin the disk down as before. } The above procedure will make shutdown(8) work properly with kernels before this change, ones with this workaround and later ones without it. To accelerate shutdown(8) updates, if the compat mode is in use, this patch prints BIG FAT warning for five seconds during shutdown (the optimal interval to annoy the user just the right amount discovered by hours of tireless usability testing). Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/libata-core.c6
-rw-r--r--drivers/ata/libata-scsi.c28
-rw-r--r--drivers/ata/libata.h1
3 files changed, 34 insertions, 1 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 2e2a2fa8e9e9..bf8f65b09591 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -101,6 +101,12 @@ int libata_noacpi = 1;
101module_param_named(noacpi, libata_noacpi, int, 0444); 101module_param_named(noacpi, libata_noacpi, int, 0444);
102MODULE_PARM_DESC(noacpi, "Disables the use of ACPI in suspend/resume when set"); 102MODULE_PARM_DESC(noacpi, "Disables the use of ACPI in suspend/resume when set");
103 103
104int ata_spindown_compat = 1;
105module_param_named(spindown_compat, ata_spindown_compat, int, 0644);
106MODULE_PARM_DESC(spindown_compat, "Enable backward compatible spindown "
107 "behavior. Will be removed. More info can be found in "
108 "Documentation/feature-removal-schedule.txt\n");
109
104MODULE_AUTHOR("Jeff Garzik"); 110MODULE_AUTHOR("Jeff Garzik");
105MODULE_DESCRIPTION("Library module for ATA devices"); 111MODULE_DESCRIPTION("Library module for ATA devices");
106MODULE_LICENSE("GPL"); 112MODULE_LICENSE("GPL");
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 8f800196d596..dd81fa78cdcf 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -944,9 +944,35 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
944 } 944 }
945 945
946 tf->command = ATA_CMD_VERIFY; /* READ VERIFY */ 946 tf->command = ATA_CMD_VERIFY; /* READ VERIFY */
947 } else 947 } else {
948 /* XXX: This is for backward compatibility, will be
949 * removed. Read Documentation/feature-removal-schedule.txt
950 * for more info.
951 */
952 if (ata_spindown_compat &&
953 (system_state == SYSTEM_HALT ||
954 system_state == SYSTEM_POWER_OFF)) {
955 static int warned = 0;
956
957 if (!warned) {
958 spin_unlock_irq(qc->ap->lock);
959 ata_dev_printk(qc->dev, KERN_WARNING,
960 "DISK MIGHT NOT BE SPUN DOWN PROPERLY. "
961 "UPDATE SHUTDOWN UTILITY\n");
962 ata_dev_printk(qc->dev, KERN_WARNING,
963 "For more info, visit "
964 "http://linux-ata.org/shutdown.html\n");
965 warned = 1;
966 ssleep(5);
967 spin_lock_irq(qc->ap->lock);
968 }
969 scmd->result = SAM_STAT_GOOD;
970 return 1;
971 }
972
948 /* Issue ATA STANDBY IMMEDIATE command */ 973 /* Issue ATA STANDBY IMMEDIATE command */
949 tf->command = ATA_CMD_STANDBYNOW1; 974 tf->command = ATA_CMD_STANDBYNOW1;
975 }
950 976
951 /* 977 /*
952 * Standby and Idle condition timers could be implemented but that 978 * Standby and Idle condition timers could be implemented but that
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 5f4d40cd3288..316bf8ae4536 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -58,6 +58,7 @@ extern int atapi_enabled;
58extern int atapi_dmadir; 58extern int atapi_dmadir;
59extern int libata_fua; 59extern int libata_fua;
60extern int libata_noacpi; 60extern int libata_noacpi;
61extern int ata_spindown_compat;
61extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev); 62extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
62extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, 63extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
63 u64 block, u32 n_block, unsigned int tf_flags, 64 u64 block, u32 n_block, unsigned int tf_flags,