[libata] Improve timeout handling
[deliverable/linux.git] / drivers / ata / libata-eh.c
index ce2ef04753390b2c95dacd591662efd3c1800ebb..01831312c3607e3bc8aa98cfb42604e14cc3eba1 100644 (file)
@@ -547,7 +547,7 @@ void ata_scsi_error(struct Scsi_Host *host)
 
        /* For new EH, all qcs are finished in one of three ways -
         * normal completion, error completion, and SCSI timeout.
-        * Both cmpletions can race against SCSI timeout.  When normal
+        * Both completions can race against SCSI timeout.  When normal
         * completion wins, the qc never reaches EH.  When error
         * completion wins, the qc has ATA_QCFLAG_FAILED set.
         *
@@ -562,7 +562,19 @@ void ata_scsi_error(struct Scsi_Host *host)
                int nr_timedout = 0;
 
                spin_lock_irqsave(ap->lock, flags);
-
+               
+               /* This must occur under the ap->lock as we don't want
+                  a polled recovery to race the real interrupt handler
+                  
+                  The lost_interrupt handler checks for any completed but
+                  non-notified command and completes much like an IRQ handler.
+                  
+                  We then fall into the error recovery code which will treat
+                  this as if normal completion won the race */
+
+               if (ap->ops->lost_interrupt)
+                       ap->ops->lost_interrupt(ap);
+                       
                list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) {
                        struct ata_queued_cmd *qc;
 
@@ -606,6 +618,9 @@ void ata_scsi_error(struct Scsi_Host *host)
                ap->eh_tries = ATA_EH_MAX_TRIES;
        } else
                spin_unlock_wait(ap->lock);
+               
+       /* If we timed raced normal completion and there is nothing to
+          recover nr_timedout == 0 why exactly are we doing error recovery ? */
 
  repeat:
        /* invoke error handler */
@@ -2423,11 +2438,14 @@ int ata_eh_reset(struct ata_link *link, int classify,
                }
 
                /* prereset() might have cleared ATA_EH_RESET.  If so,
-                * bang classes and return.
+                * bang classes, thaw and return.
                 */
                if (reset && !(ehc->i.action & ATA_EH_RESET)) {
                        ata_for_each_dev(dev, link, ALL)
                                classes[dev->devno] = ATA_DEV_NONE;
+                       if ((ap->pflags & ATA_PFLAG_FROZEN) &&
+                           ata_is_host_link(link))
+                               ata_eh_thaw_port(ap);
                        rc = 0;
                        goto out;
                }
@@ -2901,7 +2919,7 @@ static int atapi_eh_clear_ua(struct ata_device *dev)
        int i;
 
        for (i = 0; i < ATA_EH_UA_TRIES; i++) {
-               u8 sense_buffer[SCSI_SENSE_BUFFERSIZE];
+               u8 *sense_buffer = dev->link->ap->sector_buf;
                u8 sense_key = 0;
                unsigned int err_mask;
 
This page took 0.027355 seconds and 5 git commands to generate.