diff options
author | Tejun Heo <htejun@gmail.com> | 2006-05-15 07:57:40 -0400 |
---|---|---|
committer | Tejun Heo <htejun@gmail.com> | 2006-05-15 07:57:40 -0400 |
commit | e61e067227bc76b4d9411a50d735c9d87f27b0e2 (patch) | |
tree | 007d22539b24aa6ae8e258af6e22a4187490a4c1 | |
parent | 96bd39ec295e49443c8b0c25a6b69fdace18780f (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>
-rw-r--r-- | drivers/scsi/libata-core.c | 4 | ||||
-rw-r--r-- | drivers/scsi/libata-scsi.c | 18 | ||||
-rw-r--r-- | include/linux/libata.h | 16 |
3 files changed, 23 insertions, 15 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 19ae3fa1cfcb..51cb9ca5519c 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
@@ -955,7 +955,6 @@ void ata_qc_complete_internal(struct ata_queued_cmd *qc) | |||
955 | { | 955 | { |
956 | struct completion *waiting = qc->private_data; | 956 | struct completion *waiting = qc->private_data; |
957 | 957 | ||
958 | qc->ap->ops->tf_read(qc->ap, &qc->tf); | ||
959 | complete(waiting); | 958 | complete(waiting); |
960 | } | 959 | } |
961 | 960 | ||
@@ -997,6 +996,7 @@ unsigned ata_exec_internal(struct ata_port *ap, struct ata_device *dev, | |||
997 | qc->tf = *tf; | 996 | qc->tf = *tf; |
998 | if (cdb) | 997 | if (cdb) |
999 | memcpy(qc->cdb, cdb, ATAPI_CDB_LEN); | 998 | memcpy(qc->cdb, cdb, ATAPI_CDB_LEN); |
999 | qc->flags |= ATA_QCFLAG_RESULT_TF; | ||
1000 | qc->dma_dir = dma_dir; | 1000 | qc->dma_dir = dma_dir; |
1001 | if (dma_dir != DMA_NONE) { | 1001 | if (dma_dir != DMA_NONE) { |
1002 | ata_sg_init_one(qc, buf, buflen); | 1002 | ata_sg_init_one(qc, buf, buflen); |
@@ -1034,7 +1034,7 @@ unsigned ata_exec_internal(struct ata_port *ap, struct ata_device *dev, | |||
1034 | /* finish up */ | 1034 | /* finish up */ |
1035 | spin_lock_irqsave(&ap->host_set->lock, flags); | 1035 | spin_lock_irqsave(&ap->host_set->lock, flags); |
1036 | 1036 | ||
1037 | *tf = qc->tf; | 1037 | *tf = qc->result_tf; |
1038 | err_mask = qc->err_mask; | 1038 | err_mask = qc->err_mask; |
1039 | 1039 | ||
1040 | ata_qc_free(qc); | 1040 | ata_qc_free(qc); |
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index b0c83c28d578..ce90b6352a81 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c | |||
@@ -537,7 +537,7 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, | |||
537 | void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc) | 537 | void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc) |
538 | { | 538 | { |
539 | struct scsi_cmnd *cmd = qc->scsicmd; | 539 | struct scsi_cmnd *cmd = qc->scsicmd; |
540 | struct ata_taskfile *tf = &qc->tf; | 540 | struct ata_taskfile *tf = &qc->result_tf; |
541 | unsigned char *sb = cmd->sense_buffer; | 541 | unsigned char *sb = cmd->sense_buffer; |
542 | unsigned char *desc = sb + 8; | 542 | unsigned char *desc = sb + 8; |
543 | 543 | ||
@@ -608,7 +608,7 @@ void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc) | |||
608 | void ata_gen_fixed_sense(struct ata_queued_cmd *qc) | 608 | void ata_gen_fixed_sense(struct ata_queued_cmd *qc) |
609 | { | 609 | { |
610 | struct scsi_cmnd *cmd = qc->scsicmd; | 610 | struct scsi_cmnd *cmd = qc->scsicmd; |
611 | struct ata_taskfile *tf = &qc->tf; | 611 | struct ata_taskfile *tf = &qc->result_tf; |
612 | unsigned char *sb = cmd->sense_buffer; | 612 | unsigned char *sb = cmd->sense_buffer; |
613 | 613 | ||
614 | memset(sb, 0, SCSI_SENSE_BUFFERSIZE); | 614 | memset(sb, 0, SCSI_SENSE_BUFFERSIZE); |
@@ -1199,14 +1199,11 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) | |||
1199 | */ | 1199 | */ |
1200 | if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) && | 1200 | if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) && |
1201 | ((cdb[2] & 0x20) || need_sense)) { | 1201 | ((cdb[2] & 0x20) || need_sense)) { |
1202 | qc->ap->ops->tf_read(qc->ap, &qc->tf); | ||
1203 | ata_gen_ata_desc_sense(qc); | 1202 | ata_gen_ata_desc_sense(qc); |
1204 | } else { | 1203 | } else { |
1205 | if (!need_sense) { | 1204 | if (!need_sense) { |
1206 | cmd->result = SAM_STAT_GOOD; | 1205 | cmd->result = SAM_STAT_GOOD; |
1207 | } else { | 1206 | } else { |
1208 | qc->ap->ops->tf_read(qc->ap, &qc->tf); | ||
1209 | |||
1210 | /* TODO: decide which descriptor format to use | 1207 | /* TODO: decide which descriptor format to use |
1211 | * for 48b LBA devices and call that here | 1208 | * for 48b LBA devices and call that here |
1212 | * instead of the fixed desc, which is only | 1209 | * instead of the fixed desc, which is only |
@@ -1217,10 +1214,8 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) | |||
1217 | } | 1214 | } |
1218 | } | 1215 | } |
1219 | 1216 | ||
1220 | if (need_sense) { | 1217 | if (need_sense) |
1221 | /* The ata_gen_..._sense routines fill in tf */ | 1218 | ata_dump_status(qc->ap->id, &qc->result_tf); |
1222 | ata_dump_status(qc->ap->id, &qc->tf); | ||
1223 | } | ||
1224 | 1219 | ||
1225 | qc->scsidone(cmd); | 1220 | qc->scsidone(cmd); |
1226 | 1221 | ||
@@ -2004,7 +1999,6 @@ static void atapi_sense_complete(struct ata_queued_cmd *qc) | |||
2004 | * a sense descriptors, since that's only | 1999 | * a sense descriptors, since that's only |
2005 | * correct for ATA, not ATAPI | 2000 | * correct for ATA, not ATAPI |
2006 | */ | 2001 | */ |
2007 | qc->ap->ops->tf_read(qc->ap, &qc->tf); | ||
2008 | ata_gen_ata_desc_sense(qc); | 2002 | ata_gen_ata_desc_sense(qc); |
2009 | } | 2003 | } |
2010 | 2004 | ||
@@ -2080,7 +2074,6 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc) | |||
2080 | * a sense descriptors, since that's only | 2074 | * a sense descriptors, since that's only |
2081 | * correct for ATA, not ATAPI | 2075 | * correct for ATA, not ATAPI |
2082 | */ | 2076 | */ |
2083 | qc->ap->ops->tf_read(qc->ap, &qc->tf); | ||
2084 | ata_gen_ata_desc_sense(qc); | 2077 | ata_gen_ata_desc_sense(qc); |
2085 | } else { | 2078 | } else { |
2086 | u8 *scsicmd = cmd->cmnd; | 2079 | u8 *scsicmd = cmd->cmnd; |
@@ -2361,6 +2354,9 @@ ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd) | |||
2361 | */ | 2354 | */ |
2362 | qc->nsect = cmd->bufflen / ATA_SECT_SIZE; | 2355 | qc->nsect = cmd->bufflen / ATA_SECT_SIZE; |
2363 | 2356 | ||
2357 | /* request result TF */ | ||
2358 | qc->flags |= ATA_QCFLAG_RESULT_TF; | ||
2359 | |||
2364 | return 0; | 2360 | return 0; |
2365 | 2361 | ||
2366 | invalid_fld: | 2362 | invalid_fld: |
diff --git a/include/linux/libata.h b/include/linux/libata.h index 0e1a3be39475..a4b8a419caad 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
@@ -162,7 +162,9 @@ enum { | |||
162 | ATA_QCFLAG_SINGLE = (1 << 2), /* no s/g, just a single buffer */ | 162 | ATA_QCFLAG_SINGLE = (1 << 2), /* no s/g, just a single buffer */ |
163 | ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE, | 163 | ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE, |
164 | ATA_QCFLAG_IO = (1 << 3), /* standard IO command */ | 164 | ATA_QCFLAG_IO = (1 << 3), /* standard IO command */ |
165 | ATA_QCFLAG_EH_SCHEDULED = (1 << 4), /* EH scheduled */ | 165 | ATA_QCFLAG_RESULT_TF = (1 << 4), /* result TF requested */ |
166 | |||
167 | ATA_QCFLAG_EH_SCHEDULED = (1 << 16), /* EH scheduled */ | ||
166 | 168 | ||
167 | /* host set flags */ | 169 | /* host set flags */ |
168 | ATA_HOST_SIMPLEX = (1 << 0), /* Host is simplex, one DMA channel per host_set only */ | 170 | ATA_HOST_SIMPLEX = (1 << 0), /* Host is simplex, one DMA channel per host_set only */ |
@@ -343,7 +345,7 @@ struct ata_queued_cmd { | |||
343 | struct scatterlist *__sg; | 345 | struct scatterlist *__sg; |
344 | 346 | ||
345 | unsigned int err_mask; | 347 | unsigned int err_mask; |
346 | 348 | struct ata_taskfile result_tf; | |
347 | ata_qc_cb_t complete_fn; | 349 | ata_qc_cb_t complete_fn; |
348 | 350 | ||
349 | void *private_data; | 351 | void *private_data; |
@@ -824,6 +826,10 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc) | |||
824 | qc->err_mask = 0; | 826 | qc->err_mask = 0; |
825 | 827 | ||
826 | ata_tf_init(qc->ap, &qc->tf, qc->dev->devno); | 828 | ata_tf_init(qc->ap, &qc->tf, qc->dev->devno); |
829 | |||
830 | /* init result_tf such that it indicates normal completion */ | ||
831 | qc->result_tf.command = ATA_DRDY; | ||
832 | qc->result_tf.feature = 0; | ||
827 | } | 833 | } |
828 | 834 | ||
829 | /** | 835 | /** |
@@ -839,9 +845,15 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc) | |||
839 | */ | 845 | */ |
840 | static inline void ata_qc_complete(struct ata_queued_cmd *qc) | 846 | static inline void ata_qc_complete(struct ata_queued_cmd *qc) |
841 | { | 847 | { |
848 | struct ata_port *ap = qc->ap; | ||
849 | |||
842 | if (unlikely(qc->flags & ATA_QCFLAG_EH_SCHEDULED)) | 850 | if (unlikely(qc->flags & ATA_QCFLAG_EH_SCHEDULED)) |
843 | return; | 851 | return; |
844 | 852 | ||
853 | /* read result TF if failed or requested */ | ||
854 | if (qc->err_mask || qc->flags & ATA_QCFLAG_RESULT_TF) | ||
855 | ap->ops->tf_read(ap, &qc->result_tf); | ||
856 | |||
845 | __ata_qc_complete(qc); | 857 | __ata_qc_complete(qc); |
846 | } | 858 | } |
847 | 859 | ||