0001
0002 #ifndef SCATTERLIST_H
0003 #define SCATTERLIST_H
0004 #include <linux/kernel.h>
0005
0006 struct scatterlist {
0007 unsigned long page_link;
0008 unsigned int offset;
0009 unsigned int length;
0010 dma_addr_t dma_address;
0011 };
0012
0013
0014 #define sg_is_chain(sg) ((sg)->page_link & 0x01)
0015 #define sg_is_last(sg) ((sg)->page_link & 0x02)
0016 #define sg_chain_ptr(sg) \
0017 ((struct scatterlist *) ((sg)->page_link & ~0x03))
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029 static inline void sg_assign_page(struct scatterlist *sg, struct page *page)
0030 {
0031 unsigned long page_link = sg->page_link & 0x3;
0032
0033
0034
0035
0036
0037 BUG_ON((unsigned long) page & 0x03);
0038 #ifdef CONFIG_DEBUG_SG
0039 BUG_ON(sg_is_chain(sg));
0040 #endif
0041 sg->page_link = page_link | (unsigned long) page;
0042 }
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 static inline void sg_set_page(struct scatterlist *sg, struct page *page,
0059 unsigned int len, unsigned int offset)
0060 {
0061 sg_assign_page(sg, page);
0062 sg->offset = offset;
0063 sg->length = len;
0064 }
0065
0066 static inline struct page *sg_page(struct scatterlist *sg)
0067 {
0068 #ifdef CONFIG_DEBUG_SG
0069 BUG_ON(sg_is_chain(sg));
0070 #endif
0071 return (struct page *)((sg)->page_link & ~0x3);
0072 }
0073
0074
0075
0076
0077 #define for_each_sg(sglist, sg, nr, __i) \
0078 for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg))
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090 static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents,
0091 struct scatterlist *sgl)
0092 {
0093
0094
0095
0096 prv[prv_nents - 1].offset = 0;
0097 prv[prv_nents - 1].length = 0;
0098
0099
0100
0101
0102
0103 prv[prv_nents - 1].page_link = ((unsigned long) sgl | 0x01) & ~0x02;
0104 }
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115 static inline void sg_mark_end(struct scatterlist *sg)
0116 {
0117
0118
0119
0120 sg->page_link |= 0x02;
0121 sg->page_link &= ~0x01;
0122 }
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132 static inline void sg_unmark_end(struct scatterlist *sg)
0133 {
0134 sg->page_link &= ~0x02;
0135 }
0136
0137 static inline struct scatterlist *sg_next(struct scatterlist *sg)
0138 {
0139 if (sg_is_last(sg))
0140 return NULL;
0141
0142 sg++;
0143 if (unlikely(sg_is_chain(sg)))
0144 sg = sg_chain_ptr(sg);
0145
0146 return sg;
0147 }
0148
0149 static inline void sg_init_table(struct scatterlist *sgl, unsigned int nents)
0150 {
0151 memset(sgl, 0, sizeof(*sgl) * nents);
0152 sg_mark_end(&sgl[nents - 1]);
0153 }
0154
0155 static inline dma_addr_t sg_phys(struct scatterlist *sg)
0156 {
0157 return page_to_phys(sg_page(sg)) + sg->offset;
0158 }
0159
0160 static inline void sg_set_buf(struct scatterlist *sg, const void *buf,
0161 unsigned int buflen)
0162 {
0163 sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));
0164 }
0165
0166 static inline void sg_init_one(struct scatterlist *sg,
0167 const void *buf, unsigned int buflen)
0168 {
0169 sg_init_table(sg, 1);
0170 sg_set_buf(sg, buf, buflen);
0171 }
0172 #endif