From c34aeebc06e8bdde93e8c8f40d9903b1aaab63c6 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 23 Jan 2011 08:31:14 -0600 Subject: [PATCH] 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 Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index e16850e8d2f..073b88156b3 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); -- 2.20.1