|
@@ -4123,6 +4123,66 @@ 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)
|
|
|
+{
|
|
|
+ struct ata_port *ap = qc->ap;
|
|
|
+
|
|
|
+ /* XXX: New EH and old EH use different mechanisms to
|
|
|
+ * synchronize EH with regular execution path.
|
|
|
+ *
|
|
|
+ * In new EH, a failed qc is marked with ATA_QCFLAG_FAILED.
|
|
|
+ * Normal execution path is responsible for not accessing a
|
|
|
+ * failed qc. libata core enforces the rule by returning NULL
|
|
|
+ * from ata_qc_from_tag() for failed qcs.
|
|
|
+ *
|
|
|
+ * Old EH depends on ata_qc_complete() nullifying completion
|
|
|
+ * requests if ATA_QCFLAG_EH_SCHEDULED is set. Old EH does
|
|
|
+ * not synchronize with interrupt handler. Only PIO task is
|
|
|
+ * taken care of.
|
|
|
+ */
|
|
|
+ if (ap->ops->error_handler) {
|
|
|
+ WARN_ON(ap->flags & ATA_FLAG_FROZEN);
|
|
|
+
|
|
|
+ if (unlikely(qc->err_mask))
|
|
|
+ qc->flags |= ATA_QCFLAG_FAILED;
|
|
|
+
|
|
|
+ if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) {
|
|
|
+ if (!ata_tag_internal(qc->tag)) {
|
|
|
+ /* always fill result TF for failed qc */
|
|
|
+ ap->ops->tf_read(ap, &qc->result_tf);
|
|
|
+ ata_qc_schedule_eh(qc);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* read result TF if requested */
|
|
|
+ if (qc->flags & ATA_QCFLAG_RESULT_TF)
|
|
|
+ ap->ops->tf_read(ap, &qc->result_tf);
|
|
|
+
|
|
|
+ __ata_qc_complete(qc);
|
|
|
+ } else {
|
|
|
+ if (qc->flags & ATA_QCFLAG_EH_SCHEDULED)
|
|
|
+ return;
|
|
|
+
|
|
|
+ /* read result TF if failed or requested */
|
|
|
+ if (qc->err_mask || qc->flags & ATA_QCFLAG_RESULT_TF)
|
|
|
+ ap->ops->tf_read(ap, &qc->result_tf);
|
|
|
+
|
|
|
+ __ata_qc_complete(qc);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static inline int ata_should_dma_map(struct ata_queued_cmd *qc)
|
|
|
{
|
|
|
struct ata_port *ap = qc->ap;
|
|
@@ -5245,7 +5305,7 @@ EXPORT_SYMBOL_GPL(ata_device_add);
|
|
|
EXPORT_SYMBOL_GPL(ata_host_set_remove);
|
|
|
EXPORT_SYMBOL_GPL(ata_sg_init);
|
|
|
EXPORT_SYMBOL_GPL(ata_sg_init_one);
|
|
|
-EXPORT_SYMBOL_GPL(__ata_qc_complete);
|
|
|
+EXPORT_SYMBOL_GPL(ata_qc_complete);
|
|
|
EXPORT_SYMBOL_GPL(ata_qc_issue_prot);
|
|
|
EXPORT_SYMBOL_GPL(ata_tf_load);
|
|
|
EXPORT_SYMBOL_GPL(ata_tf_read);
|