diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 35ae5b41f662f32d2c1b78180ba86cabb8561d3d..4def48ed6f46c8ff4d7f7472bfc156d20e73f4d9 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -984,6 +984,7 @@ unsigned ata_exec_internal(struct ata_device *dev, DECLARE_COMPLETION(wait); unsigned long flags; unsigned int err_mask; + int rc; spin_lock_irqsave(&ap->host_set->lock, flags); @@ -1036,20 +1037,25 @@ unsigned ata_exec_internal(struct ata_device *dev, spin_unlock_irqrestore(&ap->host_set->lock, flags); - if (!wait_for_completion_timeout(&wait, ATA_TMOUT_INTERNAL)) { - ata_port_flush_task(ap); + rc = wait_for_completion_timeout(&wait, ATA_TMOUT_INTERNAL); + + ata_port_flush_task(ap); + if (!rc) { spin_lock_irqsave(&ap->host_set->lock, flags); /* We're racing with irq here. If we lose, the * following test prevents us from completing the qc - * again. If completion irq occurs after here but - * before the caller cleans up, it will result in a - * spurious interrupt. We can live with that. + * twice. If we win, the port is frozen and will be + * cleaned up by ->post_internal_cmd(). */ if (qc->flags & ATA_QCFLAG_ACTIVE) { - qc->err_mask = AC_ERR_TIMEOUT; - ata_qc_complete(qc); + qc->err_mask |= AC_ERR_TIMEOUT; + + if (ap->ops->error_handler) + ata_port_freeze(ap); + else + ata_qc_complete(qc); ata_dev_printk(dev, KERN_WARNING, "qc timeout (cmd 0x%x)\n", command); @@ -1058,6 +1064,16 @@ unsigned ata_exec_internal(struct ata_device *dev, spin_unlock_irqrestore(&ap->host_set->lock, flags); } + /* do post_internal_cmd */ + if (ap->ops->post_internal_cmd) + ap->ops->post_internal_cmd(qc); + + if (qc->flags & ATA_QCFLAG_FAILED && !qc->err_mask) { + ata_dev_printk(dev, KERN_WARNING, "zero err_mask for failed " + "internal command, assuming AC_ERR_OTHER\n"); + qc->err_mask |= AC_ERR_OTHER; + } + /* finish up */ spin_lock_irqsave(&ap->host_set->lock, flags);