aboutsummaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2006-05-15 20:57:40 +0900
committerTejun Heo <htejun@gmail.com>2006-05-15 20:57:40 +0900
commite61e067227bc76b4d9411a50d735c9d87f27b0e2 (patch)
tree007d22539b24aa6ae8e258af6e22a4187490a4c1 /include/linux
parent96bd39ec295e49443c8b0c25a6b69fdace18780f (diff)
[PATCH] libata: implement qc->result_tf
Add qc->result_tf and ATA_QCFLAG_RESULT_TF. This moves the responsibility of loading result TF from post-compltion path to qc execution path. qc->result_tf is loaded if explicitly requested or the qc failsa. This allows more efficient completion implementation and correct handling of result TF for controllers which don't have global TF representation such as sil3124/32. Signed-off-by: Tejun Heo <htejun@gmail.com>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/libata.h16
1 files changed, 14 insertions, 2 deletions
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 0e1a3be3947..a4b8a419caa 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -162,7 +162,9 @@ enum {
ATA_QCFLAG_SINGLE = (1 << 2), /* no s/g, just a single buffer */
ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE,
ATA_QCFLAG_IO = (1 << 3), /* standard IO command */
- ATA_QCFLAG_EH_SCHEDULED = (1 << 4), /* EH scheduled */
+ ATA_QCFLAG_RESULT_TF = (1 << 4), /* result TF requested */
+
+ ATA_QCFLAG_EH_SCHEDULED = (1 << 16), /* EH scheduled */
/* host set flags */
ATA_HOST_SIMPLEX = (1 << 0), /* Host is simplex, one DMA channel per host_set only */
@@ -343,7 +345,7 @@ struct ata_queued_cmd {
struct scatterlist *__sg;
unsigned int err_mask;
-
+ struct ata_taskfile result_tf;
ata_qc_cb_t complete_fn;
void *private_data;
@@ -824,6 +826,10 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc)
qc->err_mask = 0;
ata_tf_init(qc->ap, &qc->tf, qc->dev->devno);
+
+ /* init result_tf such that it indicates normal completion */
+ qc->result_tf.command = ATA_DRDY;
+ qc->result_tf.feature = 0;
}
/**
@@ -839,9 +845,15 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc)
*/
static inline void ata_qc_complete(struct ata_queued_cmd *qc)
{
+ struct ata_port *ap = qc->ap;
+
if (unlikely(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);
}