aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2010-05-10 21:41:28 +0200
committerJeff Garzik <jgarzik@redhat.com>2010-05-14 22:38:44 -0400
commit2a7adff09ac3dd3d1facaf92b4a8cc1b92d370b6 (patch)
treea2c41f4ee10893795dbd04215798a2469bb994ae
parent1b959c412bbf38ce0fa658183f72027ca8331ee3 (diff)
libata-sff: update bmdma host bus error handling
* Clearing IRQ from ata_sff_error_handler() is necessary only when the port is gonna be thawed before performing EH actions and some controllers don't like being accessed after certain failure modes until they're reset. Clear IRQ iff the port is being thawed. * When the controller succesfully indicated bus error, the point of thawing doesn't matter. Move thawing inside bmdma part of EH. This is a bit ugly but will ease code reorganization later. * Remove the unneeded ata_sff_sync(). Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-rw-r--r--drivers/ata/libata-sff.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 3cc385dbfe2..a4700af43d1 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