summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@suse.de>2011-01-23 08:31:14 -0600
committerJames Bottomley <James.Bottomley@suse.de>2011-02-13 13:16:41 -0600
commit4451ef63e1a881eb275eb16dd1980491eea709de (patch)
tree77494fc00d18ce36af9c784f5c865d73cd9528dc
parentb8784f77455124ceb4746e798f7aaf5b3b8a5406 (diff)
downloadop-kernel-dev-4451ef63e1a881eb275eb16dd1980491eea709de.zip
op-kernel-dev-4451ef63e1a881eb275eb16dd1980491eea709de.tar.gz
[SCSI] libata: fix eh locking
The SCSI host eh_cmd_q should be protected by the host lock (not the port lock). This probably doesn't matter that much at the moment, since we try to serialise the add and eh pieces, but it might matter in future for more convenient error handling. Plus this switches libata to the standard eh pattern where you lock, remove from the cmd queue to a local list and unlock and then operate on the local list. Cc: Tejun Heo <tj@kernel.org> Cc: Jeff Garzik <jeff@garzik.org> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
-rw-r--r--drivers/ata/libata-eh.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 17a6378..fc3f339 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -589,9 +589,14 @@ void ata_scsi_error(struct Scsi_Host *host)
struct ata_port *ap = ata_shost_to_port(host);
int i;
unsigned long flags;
+ LIST_HEAD(eh_work_q);
DPRINTK("ENTER\n");
+ spin_lock_irqsave(host->host_lock, flags);
+ list_splice_init(&host->eh_cmd_q, &eh_work_q);
+ spin_unlock_irqrestore(host->host_lock, flags);
+
/* make sure sff pio task is not running */
ata_sff_flush_pio_task(ap);
@@ -627,7 +632,7 @@ void ata_scsi_error(struct Scsi_Host *host)
if (ap->ops->lost_interrupt)
ap->ops->lost_interrupt(ap);
- list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) {
+ list_for_each_entry_safe(scmd, tmp, &eh_work_q, eh_entry) {
struct ata_queued_cmd *qc;
for (i = 0; i < ATA_MAX_QUEUE; i++) {
@@ -762,7 +767,7 @@ void ata_scsi_error(struct Scsi_Host *host)
}
/* finish or retry handled scmd's and clean up */
- WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q));
+ WARN_ON(host->host_failed || !list_empty(&eh_work_q));
scsi_eh_flush_done_q(&ap->eh_done_q);
OpenPOWER on IntegriCloud