aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libata-scsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libata-scsi.c')
-rw-r--r--drivers/scsi/libata-scsi.c44
1 files changed, 43 insertions, 1 deletions
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index b007bb409382..9d67c6768335 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -717,6 +717,47 @@ int ata_scsi_slave_config(struct scsi_device *sdev)
717} 717}
718 718
719/** 719/**
720 * ata_scsi_timed_out - SCSI layer time out callback
721 * @cmd: timed out SCSI command
722 *
723 * Handles SCSI layer timeout. We race with normal completion of
724 * the qc for @cmd. If the qc is already gone, we lose and let
725 * the scsi command finish (EH_HANDLED). Otherwise, the qc has
726 * timed out and EH should be invoked. Prevent ata_qc_complete()
727 * from finishing it by setting EH_SCHEDULED and return
728 * EH_NOT_HANDLED.
729 *
730 * LOCKING:
731 * Called from timer context
732 *
733 * RETURNS:
734 * EH_HANDLED or EH_NOT_HANDLED
735 */
736enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd)
737{
738 struct Scsi_Host *host = cmd->device->host;
739 struct ata_port *ap = (struct ata_port *) &host->hostdata[0];
740 unsigned long flags;
741 struct ata_queued_cmd *qc;
742 enum scsi_eh_timer_return ret = EH_HANDLED;
743
744 DPRINTK("ENTER\n");
745
746 spin_lock_irqsave(&ap->host_set->lock, flags);
747 qc = ata_qc_from_tag(ap, ap->active_tag);
748 if (qc) {
749 assert(qc->scsicmd == cmd);
750 qc->flags |= ATA_QCFLAG_EH_SCHEDULED;
751 qc->err_mask |= AC_ERR_TIMEOUT;
752 ret = EH_NOT_HANDLED;
753 }
754 spin_unlock_irqrestore(&ap->host_set->lock, flags);
755
756 DPRINTK("EXIT, ret=%d\n", ret);
757 return ret;
758}
759
760/**
720 * ata_scsi_error - SCSI layer error handler callback 761 * ata_scsi_error - SCSI layer error handler callback
721 * @host: SCSI host on which error occurred 762 * @host: SCSI host on which error occurred
722 * 763 *
@@ -741,6 +782,7 @@ int ata_scsi_error(struct Scsi_Host *host)
741 spin_lock_irqsave(&ap->host_set->lock, flags); 782 spin_lock_irqsave(&ap->host_set->lock, flags);
742 assert(!(ap->flags & ATA_FLAG_IN_EH)); 783 assert(!(ap->flags & ATA_FLAG_IN_EH));
743 ap->flags |= ATA_FLAG_IN_EH; 784 ap->flags |= ATA_FLAG_IN_EH;
785 assert(ata_qc_from_tag(ap, ap->active_tag) != NULL);
744 spin_unlock_irqrestore(&ap->host_set->lock, flags); 786 spin_unlock_irqrestore(&ap->host_set->lock, flags);
745 787
746 ap->ops->eng_timeout(ap); 788 ap->ops->eng_timeout(ap);
@@ -770,7 +812,7 @@ static void __ata_eh_qc_complete(struct ata_queued_cmd *qc)
770 812
771 spin_lock_irqsave(&ap->host_set->lock, flags); 813 spin_lock_irqsave(&ap->host_set->lock, flags);
772 qc->scsidone = ata_eh_scsidone; 814 qc->scsidone = ata_eh_scsidone;
773 ata_qc_complete(qc); 815 __ata_qc_complete(qc);
774 assert(!ata_tag_valid(qc->tag)); 816 assert(!ata_tag_valid(qc->tag));
775 spin_unlock_irqrestore(&ap->host_set->lock, flags); 817 spin_unlock_irqrestore(&ap->host_set->lock, flags);
776 818