aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@suse.de>2011-01-23 09:31:14 -0500
committerJeff Garzik <jgarzik@redhat.com>2011-03-02 02:36:45 -0500
commitc34aeebc06e8bdde93e8c8f40d9903b1aaab63c6 (patch)
tree852e437afe7d0e03d2cfc97986dace7228309114 /drivers/ata
parenta29b5dad46ee4168c8fc18e47dabbde49790527b (diff)
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. Signed-off-by: James Bottomley <James.Bottomley@suse.de> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata')
-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 e16850e8d2f8..073b88156b3c 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