Commit:     920a4b1038e442700a1cfac77ea7e20bd615a2c3
Parent:     9666f4009c22f6520ac3fb8a19c9e32ab973e828
Author:     Tejun Heo <[EMAIL PROTECTED]>
AuthorDate: Fri May 4 21:28:48 2007 +0200
Committer:  Jeff Garzik <[EMAIL PROTECTED]>
CommitDate: Fri May 11 18:01:04 2007 -0400

    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
    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 <[EMAIL PROTECTED]>
    Signed-off-by: Jeff Garzik <[EMAIL PROTECTED]>
 Documentation/feature-removal-schedule.txt |   19 +++++++++++++++++++
 drivers/ata/libata-core.c                  |    6 ++++++
 drivers/ata/libata-scsi.c                  |   28 +++++++++++++++++++++++++++-
 drivers/ata/libata.h                       |    1 +
 4 files changed, 53 insertions(+), 1 deletions(-)

diff --git a/Documentation/feature-removal-schedule.txt 
index c6322c7..498ff31 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -328,3 +328,22 @@ Who:   Adrian Bunk <[EMAIL PROTECTED]>
+What: libata.spindown_compat module parameter
+When: Dec 2008
+Why:  halt(8) synchronizes caches for and spins down libata disks
+      because libata didn't use to spin down disk on system halt
+      (only synchronized caches).
+      Spin down on system halt is now implemented and can be tested
+      using sysfs node /sys/class/scsi_disk/h:c:i:l/manage_start_stop.
+      Because issuing spin down command to an already spun down disk
+      makes some disks spin up just to spin down again, the old
+      behavior needs to be maintained till userspace tool is updated
+      to check the sysfs node and not to spin down disks with the
+      node set to one.
+      This module parameter is to give userspace tool the time to
+      get updated and should be removed after userspace is
+      reasonably updated.
+Who:  Tejun Heo <[EMAIL PROTECTED]>
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 2e2a2fa..bf8f65b 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -101,6 +101,12 @@ int libata_noacpi = 1;
 module_param_named(noacpi, libata_noacpi, int, 0444);
 MODULE_PARM_DESC(noacpi, "Disables the use of ACPI in suspend/resume when 
+int ata_spindown_compat = 1;
+module_param_named(spindown_compat, ata_spindown_compat, int, 0644);
+MODULE_PARM_DESC(spindown_compat, "Enable backward compatible spindown "
+                "behavior.  Will be removed.  More info can be found in "
+                "Documentation/feature-removal-schedule.txt\n");
 MODULE_AUTHOR("Jeff Garzik");
 MODULE_DESCRIPTION("Library module for ATA devices");
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 8f80019..dd81fa7 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)
                tf->command = ATA_CMD_VERIFY;   /* READ VERIFY */
-       } else
+       } else {
+               /* XXX: This is for backward compatibility, will be
+                * removed.  Read Documentation/feature-removal-schedule.txt
+                * for more info.
+                */
+               if (ata_spindown_compat &&
+                   (system_state == SYSTEM_HALT ||
+                    system_state == SYSTEM_POWER_OFF)) {
+                       static int warned = 0;
+                       if (!warned) {
+                               spin_unlock_irq(qc->ap->lock);
+                               ata_dev_printk(qc->dev, KERN_WARNING,
+                                       "DISK MIGHT NOT BE SPUN DOWN PROPERLY. "
+                                       "UPDATE SHUTDOWN UTILITY\n");
+                               ata_dev_printk(qc->dev, KERN_WARNING,
+                                       "For more info, visit "
+                                       "\n";);
+                               warned = 1;
+                               ssleep(5);
+                               spin_lock_irq(qc->ap->lock);
+                       }
+                       scmd->result = SAM_STAT_GOOD;
+                       return 1;
+               }
                /* Issue ATA STANDBY IMMEDIATE command */
                tf->command = ATA_CMD_STANDBYNOW1;
+       }
         * Standby and Idle condition timers could be implemented but that
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 5f4d40c..316bf8a 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -58,6 +58,7 @@ extern int atapi_enabled;
 extern int atapi_dmadir;
 extern int libata_fua;
 extern int libata_noacpi;
+extern int ata_spindown_compat;
 extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
 extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
                           u64 block, u32 n_block, unsigned int tf_flags,
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at

Reply via email to