aboutsummaryrefslogtreecommitdiff
path: root/drivers/scsi/libata-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libata-core.c')
-rw-r--r--drivers/scsi/libata-core.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 63857a90ac2..35ae5b41f66 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -3430,16 +3430,31 @@ skip_map:
* LOCKING:
* None. (grabs host lock)
*/
-
void ata_poll_qc_complete(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
unsigned long flags;
spin_lock_irqsave(&ap->host_set->lock, flags);
- ap->flags &= ~ATA_FLAG_NOINTR;
- ata_irq_on(ap);
- ata_qc_complete(qc);
+
+ if (ap->ops->error_handler) {
+ /* EH might have kicked in while host_set lock is released */
+ qc = ata_qc_from_tag(ap, qc->tag);
+ if (qc) {
+ if (!(qc->err_mask & AC_ERR_HSM)) {
+ ap->flags &= ~ATA_FLAG_NOINTR;
+ ata_irq_on(ap);
+ ata_qc_complete(qc);
+ } else
+ ata_port_freeze(ap);
+ }
+ } else {
+ /* old EH */
+ ap->flags &= ~ATA_FLAG_NOINTR;
+ ata_irq_on(ap);
+ ata_qc_complete(qc);
+ }
+
spin_unlock_irqrestore(&ap->host_set->lock, flags);
}