[libata] Improve timeout handling
On a timeout call a device specific handler early in the recovery so that we can complete and process successful commands which timed out due to IRQ loss or the like rather more elegantly. [Revised to exclude the timeout handling on a few devices that inherit from SFF but are not SFF enough to use the default timeout handler] Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
This commit is contained in:
@@ -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 */
|
||||
|
Fai riferimento in un nuovo problema
Block a user