diff options
| author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-16 13:09:16 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-16 13:09:16 -0400 |
| commit | 92d15c2ccbb3e31a3fc71ad28fdb55e1319383c0 (patch) | |
| tree | 8d83c0dc3c6b935d8367e331872f242b742f0a8a /include/linux | |
| parent | f20bf6125605acbbc7eb8c9420d7221c91aa83eb (diff) | |
| parent | 644bd2f048972d75eb1979b1fdca257d528ce687 (diff) | |
Merge branch 'for-linus' of git://git.kernel.dk/data/git/linux-2.6-block
* 'for-linus' of git://git.kernel.dk/data/git/linux-2.6-block: (63 commits)
Fix memory leak in dm-crypt
SPARC64: sg chaining support
SPARC: sg chaining support
PPC: sg chaining support
PS3: sg chaining support
IA64: sg chaining support
x86-64: enable sg chaining
x86-64: update pci-gart iommu to sg helpers
x86-64: update nommu to sg helpers
x86-64: update calgary iommu to sg helpers
swiotlb: sg chaining support
i386: enable sg chaining
i386 dma_map_sg: convert to using sg helpers
mmc: need to zero sglist on init
Panic in blk_rq_map_sg() from CCISS driver
remove sglist_len
remove blk_queue_max_phys_segments in libata
revert sg segment size ifdefs
Fixup u14-34f ENABLE_SG_CHAINING
qla1280: enable use_sg_chaining option
...
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/bio.h | 19 | ||||
| -rw-r--r-- | include/linux/blkdev.h | 8 | ||||
| -rw-r--r-- | include/linux/i2o.h | 3 | ||||
| -rw-r--r-- | include/linux/ide.h | 7 | ||||
| -rw-r--r-- | include/linux/libata.h | 16 | ||||
| -rw-r--r-- | include/linux/scatterlist.h | 84 |
6 files changed, 118 insertions, 19 deletions
diff --git a/include/linux/bio.h b/include/linux/bio.h index 089a8bc55dd4..4da441337d6e 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h | |||
| @@ -176,13 +176,28 @@ struct bio { | |||
| 176 | #define bio_offset(bio) bio_iovec((bio))->bv_offset | 176 | #define bio_offset(bio) bio_iovec((bio))->bv_offset |
| 177 | #define bio_segments(bio) ((bio)->bi_vcnt - (bio)->bi_idx) | 177 | #define bio_segments(bio) ((bio)->bi_vcnt - (bio)->bi_idx) |
| 178 | #define bio_sectors(bio) ((bio)->bi_size >> 9) | 178 | #define bio_sectors(bio) ((bio)->bi_size >> 9) |
| 179 | #define bio_cur_sectors(bio) (bio_iovec(bio)->bv_len >> 9) | ||
| 180 | #define bio_data(bio) (page_address(bio_page((bio))) + bio_offset((bio))) | ||
| 181 | #define bio_barrier(bio) ((bio)->bi_rw & (1 << BIO_RW_BARRIER)) | 179 | #define bio_barrier(bio) ((bio)->bi_rw & (1 << BIO_RW_BARRIER)) |
| 182 | #define bio_sync(bio) ((bio)->bi_rw & (1 << BIO_RW_SYNC)) | 180 | #define bio_sync(bio) ((bio)->bi_rw & (1 << BIO_RW_SYNC)) |
| 183 | #define bio_failfast(bio) ((bio)->bi_rw & (1 << BIO_RW_FAILFAST)) | 181 | #define bio_failfast(bio) ((bio)->bi_rw & (1 << BIO_RW_FAILFAST)) |
| 184 | #define bio_rw_ahead(bio) ((bio)->bi_rw & (1 << BIO_RW_AHEAD)) | 182 | #define bio_rw_ahead(bio) ((bio)->bi_rw & (1 << BIO_RW_AHEAD)) |
| 185 | #define bio_rw_meta(bio) ((bio)->bi_rw & (1 << BIO_RW_META)) | 183 | #define bio_rw_meta(bio) ((bio)->bi_rw & (1 << BIO_RW_META)) |
| 184 | #define bio_empty_barrier(bio) (bio_barrier(bio) && !(bio)->bi_size) | ||
| 185 | |||
| 186 | static inline unsigned int bio_cur_sectors(struct bio *bio) | ||
| 187 | { | ||
| 188 | if (bio->bi_vcnt) | ||
| 189 | return bio_iovec(bio)->bv_len >> 9; | ||
| 190 | |||
| 191 | return 0; | ||
| 192 | } | ||
| 193 | |||
| 194 | static inline void *bio_data(struct bio *bio) | ||
| 195 | { | ||
| 196 | if (bio->bi_vcnt) | ||
| 197 | return page_address(bio_page(bio)) + bio_offset(bio); | ||
| 198 | |||
| 199 | return NULL; | ||
| 200 | } | ||
| 186 | 201 | ||
| 187 | /* | 202 | /* |
| 188 | * will die | 203 | * will die |
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 5ed888b04b29..bbf906a0b419 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
| @@ -330,7 +330,6 @@ typedef void (unplug_fn) (struct request_queue *); | |||
| 330 | 330 | ||
| 331 | struct bio_vec; | 331 | struct bio_vec; |
| 332 | typedef int (merge_bvec_fn) (struct request_queue *, struct bio *, struct bio_vec *); | 332 | typedef int (merge_bvec_fn) (struct request_queue *, struct bio *, struct bio_vec *); |
| 333 | typedef int (issue_flush_fn) (struct request_queue *, struct gendisk *, sector_t *); | ||
| 334 | typedef void (prepare_flush_fn) (struct request_queue *, struct request *); | 333 | typedef void (prepare_flush_fn) (struct request_queue *, struct request *); |
| 335 | typedef void (softirq_done_fn)(struct request *); | 334 | typedef void (softirq_done_fn)(struct request *); |
| 336 | 335 | ||
| @@ -368,7 +367,6 @@ struct request_queue | |||
| 368 | prep_rq_fn *prep_rq_fn; | 367 | prep_rq_fn *prep_rq_fn; |
| 369 | unplug_fn *unplug_fn; | 368 | unplug_fn *unplug_fn; |
| 370 | merge_bvec_fn *merge_bvec_fn; | 369 | merge_bvec_fn *merge_bvec_fn; |
| 371 | issue_flush_fn *issue_flush_fn; | ||
| 372 | prepare_flush_fn *prepare_flush_fn; | 370 | prepare_flush_fn *prepare_flush_fn; |
| 373 | softirq_done_fn *softirq_done_fn; | 371 | softirq_done_fn *softirq_done_fn; |
| 374 | 372 | ||
| @@ -540,6 +538,7 @@ enum { | |||
| 540 | #define blk_barrier_rq(rq) ((rq)->cmd_flags & REQ_HARDBARRIER) | 538 | #define blk_barrier_rq(rq) ((rq)->cmd_flags & REQ_HARDBARRIER) |
| 541 | #define blk_fua_rq(rq) ((rq)->cmd_flags & REQ_FUA) | 539 | #define blk_fua_rq(rq) ((rq)->cmd_flags & REQ_FUA) |
| 542 | #define blk_bidi_rq(rq) ((rq)->next_rq != NULL) | 540 | #define blk_bidi_rq(rq) ((rq)->next_rq != NULL) |
| 541 | #define blk_empty_barrier(rq) (blk_barrier_rq(rq) && blk_fs_request(rq) && !(rq)->hard_nr_sectors) | ||
| 543 | 542 | ||
| 544 | #define list_entry_rq(ptr) list_entry((ptr), struct request, queuelist) | 543 | #define list_entry_rq(ptr) list_entry((ptr), struct request, queuelist) |
| 545 | 544 | ||
| @@ -729,7 +728,9 @@ static inline void blk_run_address_space(struct address_space *mapping) | |||
| 729 | extern int end_that_request_first(struct request *, int, int); | 728 | extern int end_that_request_first(struct request *, int, int); |
| 730 | extern int end_that_request_chunk(struct request *, int, int); | 729 | extern int end_that_request_chunk(struct request *, int, int); |
| 731 | extern void end_that_request_last(struct request *, int); | 730 | extern void end_that_request_last(struct request *, int); |
| 732 | extern void end_request(struct request *req, int uptodate); | 731 | extern void end_request(struct request *, int); |
| 732 | extern void end_queued_request(struct request *, int); | ||
| 733 | extern void end_dequeued_request(struct request *, int); | ||
| 733 | extern void blk_complete_request(struct request *); | 734 | extern void blk_complete_request(struct request *); |
| 734 | 735 | ||
| 735 | /* | 736 | /* |
| @@ -767,7 +768,6 @@ extern void blk_queue_dma_alignment(struct request_queue *, int); | |||
| 767 | extern void blk_queue_softirq_done(struct request_queue *, softirq_done_fn *); | 768 | extern void blk_queue_softirq_done(struct request_queue *, softirq_done_fn *); |
| 768 | extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev); | 769 | extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev); |
| 769 | extern int blk_queue_ordered(struct request_queue *, unsigned, prepare_flush_fn *); | 770 | extern int blk_queue_ordered(struct request_queue *, unsigned, prepare_flush_fn *); |
| 770 | extern void blk_queue_issue_flush_fn(struct request_queue *, issue_flush_fn *); | ||
| 771 | extern int blk_do_ordered(struct request_queue *, struct request **); | 771 | extern int blk_do_ordered(struct request_queue *, struct request **); |
| 772 | extern unsigned blk_ordered_cur_seq(struct request_queue *); | 772 | extern unsigned blk_ordered_cur_seq(struct request_queue *); |
| 773 | extern unsigned blk_ordered_req_seq(struct request *); | 773 | extern unsigned blk_ordered_req_seq(struct request *); |
diff --git a/include/linux/i2o.h b/include/linux/i2o.h index 9752307d16ba..7da5b98d90e6 100644 --- a/include/linux/i2o.h +++ b/include/linux/i2o.h | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/workqueue.h> /* work_struct */ | 32 | #include <linux/workqueue.h> /* work_struct */ |
| 33 | #include <linux/mempool.h> | 33 | #include <linux/mempool.h> |
| 34 | #include <linux/mutex.h> | 34 | #include <linux/mutex.h> |
| 35 | #include <linux/scatterlist.h> | ||
| 35 | 36 | ||
| 36 | #include <asm/io.h> | 37 | #include <asm/io.h> |
| 37 | #include <asm/semaphore.h> /* Needed for MUTEX init macros */ | 38 | #include <asm/semaphore.h> /* Needed for MUTEX init macros */ |
| @@ -837,7 +838,7 @@ static inline int i2o_dma_map_sg(struct i2o_controller *c, | |||
| 837 | if ((sizeof(dma_addr_t) > 4) && c->pae_support) | 838 | if ((sizeof(dma_addr_t) > 4) && c->pae_support) |
| 838 | *mptr++ = cpu_to_le32(i2o_dma_high(sg_dma_address(sg))); | 839 | *mptr++ = cpu_to_le32(i2o_dma_high(sg_dma_address(sg))); |
| 839 | #endif | 840 | #endif |
| 840 | sg++; | 841 | sg = sg_next(sg); |
| 841 | } | 842 | } |
| 842 | *sg_ptr = mptr; | 843 | *sg_ptr = mptr; |
| 843 | 844 | ||
diff --git a/include/linux/ide.h b/include/linux/ide.h index 02a27e8cbad2..30a1931466a6 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h | |||
| @@ -772,7 +772,7 @@ typedef struct hwif_s { | |||
| 772 | 772 | ||
| 773 | unsigned int nsect; | 773 | unsigned int nsect; |
| 774 | unsigned int nleft; | 774 | unsigned int nleft; |
| 775 | unsigned int cursg; | 775 | struct scatterlist *cursg; |
| 776 | unsigned int cursg_ofs; | 776 | unsigned int cursg_ofs; |
| 777 | 777 | ||
| 778 | int rqsize; /* max sectors per request */ | 778 | int rqsize; /* max sectors per request */ |
| @@ -1093,11 +1093,6 @@ extern ide_startstop_t ide_do_reset (ide_drive_t *); | |||
| 1093 | extern void ide_init_drive_cmd (struct request *rq); | 1093 | extern void ide_init_drive_cmd (struct request *rq); |
| 1094 | 1094 | ||
| 1095 | /* | 1095 | /* |
| 1096 | * this function returns error location sector offset in case of a write error | ||
| 1097 | */ | ||
| 1098 | extern u64 ide_get_error_location(ide_drive_t *, char *); | ||
| 1099 | |||
| 1100 | /* | ||
| 1101 | * "action" parameter type for ide_do_drive_cmd() below. | 1096 | * "action" parameter type for ide_do_drive_cmd() below. |
| 1102 | */ | 1097 | */ |
| 1103 | typedef enum { | 1098 | typedef enum { |
diff --git a/include/linux/libata.h b/include/linux/libata.h index 229a9ff9f924..377e6d4d9be3 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
| @@ -29,7 +29,7 @@ | |||
| 29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
| 30 | #include <linux/interrupt.h> | 30 | #include <linux/interrupt.h> |
| 31 | #include <linux/dma-mapping.h> | 31 | #include <linux/dma-mapping.h> |
| 32 | #include <asm/scatterlist.h> | 32 | #include <linux/scatterlist.h> |
| 33 | #include <linux/io.h> | 33 | #include <linux/io.h> |
| 34 | #include <linux/ata.h> | 34 | #include <linux/ata.h> |
| 35 | #include <linux/workqueue.h> | 35 | #include <linux/workqueue.h> |
| @@ -416,6 +416,7 @@ struct ata_queued_cmd { | |||
| 416 | unsigned long flags; /* ATA_QCFLAG_xxx */ | 416 | unsigned long flags; /* ATA_QCFLAG_xxx */ |
| 417 | unsigned int tag; | 417 | unsigned int tag; |
| 418 | unsigned int n_elem; | 418 | unsigned int n_elem; |
| 419 | unsigned int n_iter; | ||
| 419 | unsigned int orig_n_elem; | 420 | unsigned int orig_n_elem; |
| 420 | 421 | ||
| 421 | int dma_dir; | 422 | int dma_dir; |
| @@ -426,7 +427,7 @@ struct ata_queued_cmd { | |||
| 426 | unsigned int nbytes; | 427 | unsigned int nbytes; |
| 427 | unsigned int curbytes; | 428 | unsigned int curbytes; |
| 428 | 429 | ||
| 429 | unsigned int cursg; | 430 | struct scatterlist *cursg; |
| 430 | unsigned int cursg_ofs; | 431 | unsigned int cursg_ofs; |
| 431 | 432 | ||
| 432 | struct scatterlist sgent; | 433 | struct scatterlist sgent; |
| @@ -1043,7 +1044,7 @@ ata_sg_is_last(struct scatterlist *sg, struct ata_queued_cmd *qc) | |||
| 1043 | return 1; | 1044 | return 1; |
| 1044 | if (qc->pad_len) | 1045 | if (qc->pad_len) |
| 1045 | return 0; | 1046 | return 0; |
| 1046 | if (((sg - qc->__sg) + 1) == qc->n_elem) | 1047 | if (qc->n_iter == qc->n_elem) |
| 1047 | return 1; | 1048 | return 1; |
| 1048 | return 0; | 1049 | return 0; |
| 1049 | } | 1050 | } |
| @@ -1051,6 +1052,7 @@ ata_sg_is_last(struct scatterlist *sg, struct ata_queued_cmd *qc) | |||
| 1051 | static inline struct scatterlist * | 1052 | static inline struct scatterlist * |
| 1052 | ata_qc_first_sg(struct ata_queued_cmd *qc) | 1053 | ata_qc_first_sg(struct ata_queued_cmd *qc) |
| 1053 | { | 1054 | { |
| 1055 | qc->n_iter = 0; | ||
| 1054 | if (qc->n_elem) | 1056 | if (qc->n_elem) |
| 1055 | return qc->__sg; | 1057 | return qc->__sg; |
| 1056 | if (qc->pad_len) | 1058 | if (qc->pad_len) |
| @@ -1063,8 +1065,8 @@ ata_qc_next_sg(struct scatterlist *sg, struct ata_queued_cmd *qc) | |||
| 1063 | { | 1065 | { |
| 1064 | if (sg == &qc->pad_sgent) | 1066 | if (sg == &qc->pad_sgent) |
| 1065 | return NULL; | 1067 | return NULL; |
| 1066 | if (++sg - qc->__sg < qc->n_elem) | 1068 | if (++qc->n_iter < qc->n_elem) |
| 1067 | return sg; | 1069 | return sg_next(sg); |
| 1068 | if (qc->pad_len) | 1070 | if (qc->pad_len) |
| 1069 | return &qc->pad_sgent; | 1071 | return &qc->pad_sgent; |
| 1070 | return NULL; | 1072 | return NULL; |
| @@ -1309,9 +1311,11 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc) | |||
| 1309 | qc->dma_dir = DMA_NONE; | 1311 | qc->dma_dir = DMA_NONE; |
| 1310 | qc->__sg = NULL; | 1312 | qc->__sg = NULL; |
| 1311 | qc->flags = 0; | 1313 | qc->flags = 0; |
| 1312 | qc->cursg = qc->cursg_ofs = 0; | 1314 | qc->cursg = NULL; |
| 1315 | qc->cursg_ofs = 0; | ||
| 1313 | qc->nbytes = qc->curbytes = 0; | 1316 | qc->nbytes = qc->curbytes = 0; |
| 1314 | qc->n_elem = 0; | 1317 | qc->n_elem = 0; |
| 1318 | qc->n_iter = 0; | ||
| 1315 | qc->err_mask = 0; | 1319 | qc->err_mask = 0; |
| 1316 | qc->pad_len = 0; | 1320 | qc->pad_len = 0; |
| 1317 | qc->sect_size = ATA_SECT_SIZE; | 1321 | qc->sect_size = ATA_SECT_SIZE; |
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index 4efbd9c445f5..2dc7464cce52 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h | |||
| @@ -20,4 +20,88 @@ static inline void sg_init_one(struct scatterlist *sg, const void *buf, | |||
| 20 | sg_set_buf(sg, buf, buflen); | 20 | sg_set_buf(sg, buf, buflen); |
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | /* | ||
| 24 | * We overload the LSB of the page pointer to indicate whether it's | ||
| 25 | * a valid sg entry, or whether it points to the start of a new scatterlist. | ||
| 26 | * Those low bits are there for everyone! (thanks mason :-) | ||
| 27 | */ | ||
| 28 | #define sg_is_chain(sg) ((unsigned long) (sg)->page & 0x01) | ||
| 29 | #define sg_chain_ptr(sg) \ | ||
| 30 | ((struct scatterlist *) ((unsigned long) (sg)->page & ~0x01)) | ||
| 31 | |||
| 32 | /** | ||
| 33 | * sg_next - return the next scatterlist entry in a list | ||
| 34 | * @sg: The current sg entry | ||
| 35 | * | ||
| 36 | * Usually the next entry will be @sg@ + 1, but if this sg element is part | ||
| 37 | * of a chained scatterlist, it could jump to the start of a new | ||
| 38 | * scatterlist array. | ||
| 39 | * | ||
| 40 | * Note that the caller must ensure that there are further entries after | ||
| 41 | * the current entry, this function will NOT return NULL for an end-of-list. | ||
| 42 | * | ||
| 43 | */ | ||
| 44 | static inline struct scatterlist *sg_next(struct scatterlist *sg) | ||
| 45 | { | ||
| 46 | sg++; | ||
| 47 | |||
| 48 | if (unlikely(sg_is_chain(sg))) | ||
| 49 | sg = sg_chain_ptr(sg); | ||
| 50 | |||
| 51 | return sg; | ||
| 52 | } | ||
| 53 | |||
| 54 | /* | ||
| 55 | * Loop over each sg element, following the pointer to a new list if necessary | ||
| 56 | */ | ||
| 57 | #define for_each_sg(sglist, sg, nr, __i) \ | ||
| 58 | for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg)) | ||
| 59 | |||
| 60 | /** | ||
| 61 | * sg_last - return the last scatterlist entry in a list | ||
| 62 | * @sgl: First entry in the scatterlist | ||
| 63 | * @nents: Number of entries in the scatterlist | ||
| 64 | * | ||
| 65 | * Should only be used casually, it (currently) scan the entire list | ||
| 66 | * to get the last entry. | ||
| 67 | * | ||
| 68 | * Note that the @sgl@ pointer passed in need not be the first one, | ||
| 69 | * the important bit is that @nents@ denotes the number of entries that | ||
| 70 | * exist from @sgl@. | ||
| 71 | * | ||
| 72 | */ | ||
| 73 | static inline struct scatterlist *sg_last(struct scatterlist *sgl, | ||
| 74 | unsigned int nents) | ||
| 75 | { | ||
| 76 | #ifndef ARCH_HAS_SG_CHAIN | ||
| 77 | struct scatterlist *ret = &sgl[nents - 1]; | ||
| 78 | #else | ||
| 79 | struct scatterlist *sg, *ret = NULL; | ||
| 80 | int i; | ||
| 81 | |||
| 82 | for_each_sg(sgl, sg, nents, i) | ||
| 83 | ret = sg; | ||
| 84 | |||
| 85 | #endif | ||
| 86 | return ret; | ||
| 87 | } | ||
| 88 | |||
| 89 | /** | ||
| 90 | * sg_chain - Chain two sglists together | ||
| 91 | * @prv: First scatterlist | ||
| 92 | * @prv_nents: Number of entries in prv | ||
| 93 | * @sgl: Second scatterlist | ||
| 94 | * | ||
| 95 | * Links @prv@ and @sgl@ together, to form a longer scatterlist. | ||
| 96 | * | ||
| 97 | */ | ||
| 98 | static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents, | ||
| 99 | struct scatterlist *sgl) | ||
| 100 | { | ||
| 101 | #ifndef ARCH_HAS_SG_CHAIN | ||
| 102 | BUG(); | ||
| 103 | #endif | ||
| 104 | prv[prv_nents - 1].page = (struct page *) ((unsigned long) sgl | 0x01); | ||
| 105 | } | ||
| 106 | |||
| 23 | #endif /* _LINUX_SCATTERLIST_H */ | 107 | #endif /* _LINUX_SCATTERLIST_H */ |
