diff options
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/libata-sff.c | 20 |
1 files changed, 12 insertions, 8 deletions
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 3cc385d..a4700af 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -2379,7 +2379,7 @@ void ata_sff_error_handler(struct ata_port *ap) ata_reset_fn_t hardreset = ap->ops->hardreset; struct ata_queued_cmd *qc; unsigned long flags; - int thaw = 0; + bool thaw = false; qc = __ata_qc_from_tag(ap, ap->link.active_tag); if (qc && !(qc->flags & ATA_QCFLAG_FAILED)) @@ -2405,15 +2405,22 @@ void ata_sff_error_handler(struct ata_port *ap) if (qc->err_mask == AC_ERR_TIMEOUT && (host_stat & ATA_DMA_ERR)) { qc->err_mask = AC_ERR_HOST_BUS; - thaw = 1; + thaw = true; } ap->ops->bmdma_stop(qc); + + /* if we're gonna thaw, make sure IRQ is clear */ + if (thaw) { + ap->ops->sff_check_status(ap); + ap->ops->sff_irq_clear(ap); + + spin_unlock_irqrestore(ap->lock, flags); + ata_eh_thaw_port(ap); + spin_lock_irqsave(ap->lock, flags); + } } - ata_sff_sync(ap); /* FIXME: We don't need this */ - ap->ops->sff_check_status(ap); - ap->ops->sff_irq_clear(ap); /* We *MUST* do FIFO draining before we issue a reset as several * devices helpfully clear their internal state and will lock solid * if we touch the data port post reset. Pass qc in case anyone wants @@ -2424,9 +2431,6 @@ void ata_sff_error_handler(struct ata_port *ap) spin_unlock_irqrestore(ap->lock, flags); - if (thaw) - ata_eh_thaw_port(ap); - /* PIO and DMA engines have been stopped, perform recovery */ /* Ignore ata_sff_softreset if ctl isn't accessible and |