aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@suse.de>2011-01-23 09:31:14 -0500
committerJames Bottomley <James.Bottomley@suse.de>2011-02-13 14:16:41 -0500
commit4451ef63e1a881eb275eb16dd1980491eea709de (patch)
tree77494fc00d18ce36af9c784f5c865d73cd9528dc /drivers
parentb8784f77455124ceb4746e798f7aaf5b3b8a5406 (diff)
[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>
Diffstat (limited to 'drivers')
-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 17a637877d03..fc3f339a8d3c 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)
589 struct ata_port *ap = ata_shost_to_port(host); 589 struct ata_port *ap = ata_shost_to_port(host);
590 int i; 590 int i;
591 unsigned long flags; 591 unsigned long flags;
592 LIST_HEAD(eh_work_q);
592 593
593 DPRINTK("ENTER\n"); 594 DPRINTK("ENTER\n");
594 595
596 spin_lock_irqsave(host->host_lock, flags);
597 list_splice_init(&host->eh_cmd_q, &eh_work_q);
598 spin_unlock_irqrestore(host->host_lock, flags);
599
595 /* make sure sff pio task is not running */ 600 /* make sure sff pio task is not running */
596 ata_sff_flush_pio_task(ap); 601 ata_sff_flush_pio_task(ap);
597 602
@@ -627,7 +632,7 @@ void ata_scsi_error(struct Scsi_Host *host)
627 if (ap->ops->lost_interrupt) 632 if (ap->ops->lost_interrupt)
628 ap->ops->lost_interrupt(ap); 633 ap->ops->lost_interrupt(ap);
629 634
630 list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) { 635 list_for_each_entry_safe(scmd, tmp, &eh_work_q, eh_entry) {
631 struct ata_queued_cmd *qc; 636 struct ata_queued_cmd *qc;
632 637
633 for (i = 0; i < ATA_MAX_QUEUE; i++) { 638 for (i = 0; i < ATA_MAX_QUEUE; i++) {
@@ -762,7 +767,7 @@ void ata_scsi_error(struct Scsi_Host *host)
762 } 767 }
763 768
764 /* finish or retry handled scmd's and clean up */ 769 /* finish or retry handled scmd's and clean up */
765 WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q)); 770 WARN_ON(host->host_failed || !list_empty(&eh_work_q));
766 771
767 scsi_eh_flush_done_q(&ap->eh_done_q); 772 scsi_eh_flush_done_q(&ap->eh_done_q);
768 773