Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=da071b42f73dabbd0daf7ea4c3ff157d53b00648
Commit:     da071b42f73dabbd0daf7ea4c3ff157d53b00648
Parent:     3cadbcc09891b8544203f211dac13f9cc4e6832a
Author:     Tejun Heo <[EMAIL PROTECTED]>
AuthorDate: Mon May 14 17:26:18 2007 +0200
Committer:  Jeff Garzik <[EMAIL PROTECTED]>
CommitDate: Wed May 16 01:18:31 2007 -0400

    libata: fix shutdown warning message printing
    
    Unlocking ap->lock and ssleeping don't work because SCSI commands can
    be issued from completion path without context.  Reimplement delayed
    completion by allowing translation functions to override
    qc->scsidone(), storing the original completion function to
    scmd->scsi_done() and overriding qc->scsidone() with a function which
    schedules delayed invocation of scmd->scsi_done().
    
    This isn't pretty at all but all the ugly parts are thankfully
    contained in the stop translation path where the compat feature is
    implemented.
    
    Signed-off-by: Tejun Heo <[EMAIL PROTECTED]>
    Signed-off-by: Jeff Garzik <[EMAIL PROTECTED]>
---
 drivers/ata/libata-scsi.c |   35 +++++++++++++++++++++++++++--------
 1 files changed, 27 insertions(+), 8 deletions(-)

diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index dd81fa7..07b5a3d 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -893,6 +893,23 @@ int ata_scsi_change_queue_depth(struct scsi_device *sdev, 
int queue_depth)
        return queue_depth;
 }
 
+/* XXX: for ata_spindown_compat */
+static void ata_delayed_done_timerfn(unsigned long arg)
+{
+       struct scsi_cmnd *scmd = (void *)arg;
+
+       scmd->scsi_done(scmd);
+}
+
+/* XXX: for ata_spindown_compat */
+static void ata_delayed_done(struct scsi_cmnd *scmd)
+{
+       static struct timer_list timer;
+
+       setup_timer(&timer, ata_delayed_done_timerfn, (unsigned long)scmd);
+       mod_timer(&timer, jiffies + 5 * HZ);
+}
+
 /**
  *     ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command
  *     @qc: Storage for translated ATA taskfile
@@ -952,19 +969,21 @@ static unsigned int ata_scsi_start_stop_xlat(struct 
ata_queued_cmd *qc)
                if (ata_spindown_compat &&
                    (system_state == SYSTEM_HALT ||
                     system_state == SYSTEM_POWER_OFF)) {
-                       static int warned = 0;
+                       static unsigned long warned = 0;
 
-                       if (!warned) {
-                               spin_unlock_irq(qc->ap->lock);
+                       if (!test_and_set_bit(0, &warned)) {
                                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 "
                                        "http://linux-ata.org/shutdown.html\n";);
-                               warned = 1;
-                               ssleep(5);
-                               spin_lock_irq(qc->ap->lock);
+
+                               /* ->scsi_done is not used, use it for
+                                * delayed completion.
+                                */
+                               scmd->scsi_done = qc->scsidone;
+                               qc->scsidone = ata_delayed_done;
                        }
                        scmd->result = SAM_STAT_GOOD;
                        return 1;
@@ -1488,14 +1507,14 @@ static int ata_scsi_translate(struct ata_device *dev, 
struct scsi_cmnd *cmd,
 
 early_finish:
         ata_qc_free(qc);
-       done(cmd);
+       qc->scsidone(cmd);
        DPRINTK("EXIT - early finish (good or error)\n");
        return 0;
 
 err_did:
        ata_qc_free(qc);
        cmd->result = (DID_ERROR << 16);
-       done(cmd);
+       qc->scsidone(cmd);
 err_mem:
        DPRINTK("EXIT - internal\n");
        return 0;
-
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  http://vger.kernel.org/majordomo-info.html

Reply via email to