diff options
author | Tejun Heo <htejun@gmail.com> | 2007-12-05 02:43:11 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2008-01-23 05:24:14 -0500 |
commit | ff2aeb1eb64c8a4770a6304f9addbae9f9828646 (patch) | |
tree | c6febbec290ec6c40bf3abc7bcdb7188f5039443 /include/linux | |
parent | f92a26365a72333f418abe82700c6030d4a1a807 (diff) |
libata: convert to chained sg
libata used private sg iterator to handle padding sg. Now that sg can
be chained, padding can be handled using standard sg ops. Convert to
chained sg.
* s/qc->__sg/qc->sg/
* s/qc->pad_sgent/qc->extra_sg[]/. Because chaining consumes one sg
entry. There need to be two extra sg entries. The renaming is also
for future addition of other extra sg entries.
* Padding setup is moved into ata_sg_setup_extra() which is organized
in a way that future addition of other extra sg entries is easy.
* qc->orig_n_elem is unused and removed.
* qc->n_elem now contains the number of sg entries that LLDs should
map. qc->mapped_n_elem is added to carry the original number of
mapped sgs for unmapping.
* The last sg of the original sg list is used to chain to extra sg
list. The original last sg is pointed to by qc->last_sg and the
content is stored in qc->saved_last_sg. It's restored during
ata_sg_clean().
* All sg walking code has been updated. Unnecessary assertions and
checks for conditions the core layer already guarantees are removed.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Cc: Jens Axboe <jens.axboe@oracle.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'include/linux')
-rw-r--r-- | include/linux/libata.h | 42 |
1 files changed, 8 insertions, 34 deletions
diff --git a/include/linux/libata.h b/include/linux/libata.h index acd90ad78417..162f8b5509ac 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
@@ -458,7 +458,7 @@ struct ata_queued_cmd { | |||
458 | unsigned int tag; | 458 | unsigned int tag; |
459 | unsigned int n_elem; | 459 | unsigned int n_elem; |
460 | unsigned int n_iter; | 460 | unsigned int n_iter; |
461 | unsigned int orig_n_elem; | 461 | unsigned int mapped_n_elem; |
462 | 462 | ||
463 | int dma_dir; | 463 | int dma_dir; |
464 | 464 | ||
@@ -471,11 +471,12 @@ struct ata_queued_cmd { | |||
471 | struct scatterlist *cursg; | 471 | struct scatterlist *cursg; |
472 | unsigned int cursg_ofs; | 472 | unsigned int cursg_ofs; |
473 | 473 | ||
474 | struct scatterlist *last_sg; | ||
475 | struct scatterlist saved_last_sg; | ||
474 | struct scatterlist sgent; | 476 | struct scatterlist sgent; |
475 | struct scatterlist pad_sgent; | 477 | struct scatterlist extra_sg[2]; |
476 | 478 | ||
477 | /* DO NOT iterate over __sg manually, use ata_for_each_sg() */ | 479 | struct scatterlist *sg; |
478 | struct scatterlist *__sg; | ||
479 | 480 | ||
480 | unsigned int err_mask; | 481 | unsigned int err_mask; |
481 | struct ata_taskfile result_tf; | 482 | struct ata_taskfile result_tf; |
@@ -1123,35 +1124,6 @@ extern void ata_port_pbar_desc(struct ata_port *ap, int bar, ssize_t offset, | |||
1123 | const char *name); | 1124 | const char *name); |
1124 | #endif | 1125 | #endif |
1125 | 1126 | ||
1126 | /* | ||
1127 | * qc helpers | ||
1128 | */ | ||
1129 | static inline struct scatterlist * | ||
1130 | ata_qc_first_sg(struct ata_queued_cmd *qc) | ||
1131 | { | ||
1132 | qc->n_iter = 0; | ||
1133 | if (qc->n_elem) | ||
1134 | return qc->__sg; | ||
1135 | if (qc->pad_len) | ||
1136 | return &qc->pad_sgent; | ||
1137 | return NULL; | ||
1138 | } | ||
1139 | |||
1140 | static inline struct scatterlist * | ||
1141 | ata_qc_next_sg(struct scatterlist *sg, struct ata_queued_cmd *qc) | ||
1142 | { | ||
1143 | if (sg == &qc->pad_sgent) | ||
1144 | return NULL; | ||
1145 | if (++qc->n_iter < qc->n_elem) | ||
1146 | return sg_next(sg); | ||
1147 | if (qc->pad_len) | ||
1148 | return &qc->pad_sgent; | ||
1149 | return NULL; | ||
1150 | } | ||
1151 | |||
1152 | #define ata_for_each_sg(sg, qc) \ | ||
1153 | for (sg = ata_qc_first_sg(qc); sg; sg = ata_qc_next_sg(sg, qc)) | ||
1154 | |||
1155 | static inline unsigned int ata_tag_valid(unsigned int tag) | 1127 | static inline unsigned int ata_tag_valid(unsigned int tag) |
1156 | { | 1128 | { |
1157 | return (tag < ATA_MAX_QUEUE) ? 1 : 0; | 1129 | return (tag < ATA_MAX_QUEUE) ? 1 : 0; |
@@ -1386,15 +1358,17 @@ static inline void ata_tf_init(struct ata_device *dev, struct ata_taskfile *tf) | |||
1386 | static inline void ata_qc_reinit(struct ata_queued_cmd *qc) | 1358 | static inline void ata_qc_reinit(struct ata_queued_cmd *qc) |
1387 | { | 1359 | { |
1388 | qc->dma_dir = DMA_NONE; | 1360 | qc->dma_dir = DMA_NONE; |
1389 | qc->__sg = NULL; | 1361 | qc->sg = NULL; |
1390 | qc->flags = 0; | 1362 | qc->flags = 0; |
1391 | qc->cursg = NULL; | 1363 | qc->cursg = NULL; |
1392 | qc->cursg_ofs = 0; | 1364 | qc->cursg_ofs = 0; |
1393 | qc->nbytes = qc->curbytes = 0; | 1365 | qc->nbytes = qc->curbytes = 0; |
1394 | qc->n_elem = 0; | 1366 | qc->n_elem = 0; |
1367 | qc->mapped_n_elem = 0; | ||
1395 | qc->n_iter = 0; | 1368 | qc->n_iter = 0; |
1396 | qc->err_mask = 0; | 1369 | qc->err_mask = 0; |
1397 | qc->pad_len = 0; | 1370 | qc->pad_len = 0; |
1371 | qc->last_sg = NULL; | ||
1398 | qc->sect_size = ATA_SECT_SIZE; | 1372 | qc->sect_size = ATA_SECT_SIZE; |
1399 | 1373 | ||
1400 | ata_tf_init(qc->dev, &qc->tf); | 1374 | ata_tf_init(qc->dev, &qc->tf); |