02_libata_add-locking-to-ata_scsi_error.patch
SCSI EH can start before ata_qc_complete is completely
complete. so, latter part of ata_qc_complete can run
side-by-side with ->eng_timeout(), interfering EH.
This patch makes ata_scsi_error() to grab and release host_set
lock before invoking ->eng_timeout().
Note: host_failed decrementing and eh_cmd_q banging are moved
above ->eng_timeout() invocation such that they're done while
holding the lock.
Signed-off-by: Tejun Heo <[EMAIL PROTECTED]>
libata-scsi.c | 12 +++++++++---
1 files changed, 9 insertions(+), 3 deletions(-)
Index: work/drivers/scsi/libata-scsi.c
===================================================================
--- work.orig/drivers/scsi/libata-scsi.c 2005-08-20 22:34:02.000000000
+0900
+++ work/drivers/scsi/libata-scsi.c 2005-08-20 23:13:40.000000000 +0900
@@ -373,12 +373,14 @@ int ata_scsi_slave_config(struct scsi_de
int ata_scsi_error(struct Scsi_Host *host)
{
- struct ata_port *ap;
+ struct ata_port *ap = (struct ata_port *) &host->hostdata[0];
DPRINTK("ENTER\n");
- ap = (struct ata_port *) &host->hostdata[0];
- ap->ops->eng_timeout(ap);
+ /* The following locking ensures that we enter eng_timeout
+ * after ata_qc_complete is complete.
+ */
+ spin_lock_irq(&ap->host_set->lock);
/* TODO: this is per-command; when queueing is supported
* this code will either change or move to a more
@@ -387,6 +389,10 @@ int ata_scsi_error(struct Scsi_Host *hos
host->host_failed--;
INIT_LIST_HEAD(&host->eh_cmd_q);
+ spin_unlock_irq(&ap->host_set->lock);
+
+ ap->ops->eng_timeout(ap);
+
DPRINTK("EXIT\n");
return 0;
}
-
To unsubscribe from this list: send the line "unsubscribe linux-ide" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html