summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/libata-core.c33
-rw-r--r--drivers/scsi/libata-scsi.c2
-rw-r--r--drivers/scsi/libata.h1
-rw-r--r--include/linux/libata.h1
4 files changed, 23 insertions, 14 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 22db7393225..977a53dd167 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -3620,19 +3620,7 @@ void ata_qc_free(struct ata_queued_cmd *qc)
}
}
-/**
- * ata_qc_complete - Complete an active ATA command
- * @qc: Command to complete
- * @err_mask: ATA Status register contents
- *
- * Indicate to the mid and upper layers that an ATA
- * command has completed, with either an ok or not-ok status.
- *
- * LOCKING:
- * spin_lock_irqsave(host_set lock)
- */
-
-void ata_qc_complete(struct ata_queued_cmd *qc)
+inline void __ata_qc_complete(struct ata_queued_cmd *qc)
{
assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */
assert(qc->flags & ATA_QCFLAG_ACTIVE);
@@ -3650,6 +3638,25 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
qc->complete_fn(qc);
}
+/**
+ * ata_qc_complete - Complete an active ATA command
+ * @qc: Command to complete
+ * @err_mask: ATA Status register contents
+ *
+ * Indicate to the mid and upper layers that an ATA
+ * command has completed, with either an ok or not-ok status.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host_set lock)
+ */
+void ata_qc_complete(struct ata_queued_cmd *qc)
+{
+ if (unlikely(qc->flags & ATA_QCFLAG_EH_SCHEDULED))
+ return;
+
+ __ata_qc_complete(qc);
+}
+
static inline int ata_should_dma_map(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index b007bb40938..1df468eb2bf 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -770,7 +770,7 @@ static void __ata_eh_qc_complete(struct ata_queued_cmd *qc)
spin_lock_irqsave(&ap->host_set->lock, flags);
qc->scsidone = ata_eh_scsidone;
- ata_qc_complete(qc);
+ __ata_qc_complete(qc);
assert(!ata_tag_valid(qc->tag));
spin_unlock_irqrestore(&ap->host_set->lock, flags);
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index 9d76923a225..1cd071a32e9 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -46,6 +46,7 @@ extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc);
extern void ata_qc_free(struct ata_queued_cmd *qc);
extern unsigned int ata_qc_issue(struct ata_queued_cmd *qc);
+extern void __ata_qc_complete(struct ata_queued_cmd *qc);
extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
extern void ata_dev_select(struct ata_port *ap, unsigned int device,
unsigned int wait, unsigned int can_sleep);
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 68b3fe6f9a4..5c70a57f93e 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -169,6 +169,7 @@ enum {
ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */
ATA_QCFLAG_SINGLE = (1 << 4), /* no s/g, just a single buffer */
ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE,
+ ATA_QCFLAG_EH_SCHEDULED = (1 << 5), /* EH scheduled */
/* various lengths of time */
ATA_TMOUT_EDD = 5 * HZ, /* heuristic */