]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | #ifndef _LINUX_SCATTERLIST_H |
2 | #define _LINUX_SCATTERLIST_H | |
3 | ||
85cdffcd | 4 | #include <asm/types.h> |
d32311fe HX |
5 | #include <asm/scatterlist.h> |
6 | #include <linux/mm.h> | |
7 | #include <linux/string.h> | |
18dabf47 JA |
8 | #include <asm/io.h> |
9 | ||
10 | /* | |
11 | * Notes on SG table design. | |
12 | * | |
13 | * Architectures must provide an unsigned long page_link field in the | |
14 | * scatterlist struct. We use that to place the page pointer AND encode | |
15 | * information about the sg table as well. The two lower bits are reserved | |
16 | * for this information. | |
17 | * | |
18 | * If bit 0 is set, then the page_link contains a pointer to the next sg | |
19 | * table list. Otherwise the next entry is at sg + 1. | |
20 | * | |
21 | * If bit 1 is set, then this sg entry is the last element in a list. | |
22 | * | |
23 | * See sg_next(). | |
24 | * | |
25 | */ | |
1da177e4 | 26 | |
d6ec0842 JA |
27 | #define SG_MAGIC 0x87654321 |
28 | ||
645a8d94 TH |
29 | /* |
30 | * We overload the LSB of the page pointer to indicate whether it's | |
31 | * a valid sg entry, or whether it points to the start of a new scatterlist. | |
32 | * Those low bits are there for everyone! (thanks mason :-) | |
33 | */ | |
34 | #define sg_is_chain(sg) ((sg)->page_link & 0x01) | |
35 | #define sg_is_last(sg) ((sg)->page_link & 0x02) | |
36 | #define sg_chain_ptr(sg) \ | |
37 | ((struct scatterlist *) ((sg)->page_link & ~0x03)) | |
38 | ||
82f66fbe | 39 | /** |
642f1490 JA |
40 | * sg_assign_page - Assign a given page to an SG entry |
41 | * @sg: SG entry | |
42 | * @page: The page | |
82f66fbe JA |
43 | * |
44 | * Description: | |
642f1490 JA |
45 | * Assign page to sg entry. Also see sg_set_page(), the most commonly used |
46 | * variant. | |
82f66fbe JA |
47 | * |
48 | **/ | |
642f1490 | 49 | static inline void sg_assign_page(struct scatterlist *sg, struct page *page) |
82f66fbe | 50 | { |
18dabf47 JA |
51 | unsigned long page_link = sg->page_link & 0x3; |
52 | ||
de26103d JA |
53 | /* |
54 | * In order for the low bit stealing approach to work, pages | |
55 | * must be aligned at a 32-bit boundary as a minimum. | |
56 | */ | |
57 | BUG_ON((unsigned long) page & 0x03); | |
d6ec0842 JA |
58 | #ifdef CONFIG_DEBUG_SG |
59 | BUG_ON(sg->sg_magic != SG_MAGIC); | |
645a8d94 | 60 | BUG_ON(sg_is_chain(sg)); |
d6ec0842 | 61 | #endif |
18dabf47 | 62 | sg->page_link = page_link | (unsigned long) page; |
82f66fbe JA |
63 | } |
64 | ||
642f1490 JA |
65 | /** |
66 | * sg_set_page - Set sg entry to point at given page | |
67 | * @sg: SG entry | |
68 | * @page: The page | |
69 | * @len: Length of data | |
70 | * @offset: Offset into page | |
71 | * | |
72 | * Description: | |
73 | * Use this function to set an sg entry pointing at a page, never assign | |
74 | * the page directly. We encode sg table information in the lower bits | |
75 | * of the page pointer. See sg_page() for looking up the page belonging | |
76 | * to an sg entry. | |
77 | * | |
78 | **/ | |
79 | static inline void sg_set_page(struct scatterlist *sg, struct page *page, | |
80 | unsigned int len, unsigned int offset) | |
81 | { | |
82 | sg_assign_page(sg, page); | |
83 | sg->offset = offset; | |
84 | sg->length = len; | |
85 | } | |
86 | ||
645a8d94 TH |
87 | static inline struct page *sg_page(struct scatterlist *sg) |
88 | { | |
89 | #ifdef CONFIG_DEBUG_SG | |
90 | BUG_ON(sg->sg_magic != SG_MAGIC); | |
91 | BUG_ON(sg_is_chain(sg)); | |
92 | #endif | |
93 | return (struct page *)((sg)->page_link & ~0x3); | |
94 | } | |
82f66fbe | 95 | |
18dabf47 JA |
96 | /** |
97 | * sg_set_buf - Set sg entry to point at given data | |
98 | * @sg: SG entry | |
99 | * @buf: Data | |
100 | * @buflen: Data length | |
101 | * | |
102 | **/ | |
03fd9cee | 103 | static inline void sg_set_buf(struct scatterlist *sg, const void *buf, |
d32311fe HX |
104 | unsigned int buflen) |
105 | { | |
642f1490 | 106 | sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf)); |
1da177e4 LT |
107 | } |
108 | ||
70eb8040 JA |
109 | /** |
110 | * sg_next - return the next scatterlist entry in a list | |
111 | * @sg: The current sg entry | |
112 | * | |
18dabf47 JA |
113 | * Description: |
114 | * Usually the next entry will be @sg@ + 1, but if this sg element is part | |
115 | * of a chained scatterlist, it could jump to the start of a new | |
116 | * scatterlist array. | |
70eb8040 | 117 | * |
18dabf47 | 118 | **/ |
70eb8040 JA |
119 | static inline struct scatterlist *sg_next(struct scatterlist *sg) |
120 | { | |
d6ec0842 JA |
121 | #ifdef CONFIG_DEBUG_SG |
122 | BUG_ON(sg->sg_magic != SG_MAGIC); | |
123 | #endif | |
18dabf47 JA |
124 | if (sg_is_last(sg)) |
125 | return NULL; | |
70eb8040 | 126 | |
18dabf47 | 127 | sg++; |
70eb8040 JA |
128 | if (unlikely(sg_is_chain(sg))) |
129 | sg = sg_chain_ptr(sg); | |
130 | ||
131 | return sg; | |
132 | } | |
96b418c9 JA |
133 | |
134 | /* | |
135 | * Loop over each sg element, following the pointer to a new list if necessary | |
136 | */ | |
137 | #define for_each_sg(sglist, sg, nr, __i) \ | |
138 | for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg)) | |
139 | ||
70eb8040 JA |
140 | /** |
141 | * sg_last - return the last scatterlist entry in a list | |
142 | * @sgl: First entry in the scatterlist | |
143 | * @nents: Number of entries in the scatterlist | |
144 | * | |
18dabf47 JA |
145 | * Description: |
146 | * Should only be used casually, it (currently) scan the entire list | |
147 | * to get the last entry. | |
70eb8040 | 148 | * |
18dabf47 JA |
149 | * Note that the @sgl@ pointer passed in need not be the first one, |
150 | * the important bit is that @nents@ denotes the number of entries that | |
151 | * exist from @sgl@. | |
70eb8040 | 152 | * |
18dabf47 | 153 | **/ |
70eb8040 JA |
154 | static inline struct scatterlist *sg_last(struct scatterlist *sgl, |
155 | unsigned int nents) | |
156 | { | |
157 | #ifndef ARCH_HAS_SG_CHAIN | |
158 | struct scatterlist *ret = &sgl[nents - 1]; | |
159 | #else | |
160 | struct scatterlist *sg, *ret = NULL; | |
74eb94f7 | 161 | unsigned int i; |
70eb8040 JA |
162 | |
163 | for_each_sg(sgl, sg, nents, i) | |
164 | ret = sg; | |
165 | ||
d6ec0842 JA |
166 | #endif |
167 | #ifdef CONFIG_DEBUG_SG | |
168 | BUG_ON(sgl[0].sg_magic != SG_MAGIC); | |
169 | BUG_ON(!sg_is_last(ret)); | |
70eb8040 JA |
170 | #endif |
171 | return ret; | |
172 | } | |
173 | ||
174 | /** | |
175 | * sg_chain - Chain two sglists together | |
176 | * @prv: First scatterlist | |
177 | * @prv_nents: Number of entries in prv | |
178 | * @sgl: Second scatterlist | |
179 | * | |
18dabf47 JA |
180 | * Description: |
181 | * Links @prv@ and @sgl@ together, to form a longer scatterlist. | |
70eb8040 | 182 | * |
18dabf47 | 183 | **/ |
70eb8040 JA |
184 | static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents, |
185 | struct scatterlist *sgl) | |
186 | { | |
187 | #ifndef ARCH_HAS_SG_CHAIN | |
188 | BUG(); | |
189 | #endif | |
645a8d94 TH |
190 | |
191 | /* | |
192 | * offset and length are unused for chain entry. Clear them. | |
193 | */ | |
194 | prv->offset = 0; | |
195 | prv->length = 0; | |
196 | ||
73fd546a JA |
197 | /* |
198 | * Set lowest bit to indicate a link pointer, and make sure to clear | |
199 | * the termination bit if it happens to be set. | |
200 | */ | |
201 | prv[prv_nents - 1].page_link = ((unsigned long) sgl | 0x01) & ~0x02; | |
70eb8040 JA |
202 | } |
203 | ||
82f66fbe JA |
204 | /** |
205 | * sg_mark_end - Mark the end of the scatterlist | |
c46f2334 | 206 | * @sg: SG entryScatterlist |
82f66fbe JA |
207 | * |
208 | * Description: | |
c46f2334 JA |
209 | * Marks the passed in sg entry as the termination point for the sg |
210 | * table. A call to sg_next() on this entry will return NULL. | |
82f66fbe JA |
211 | * |
212 | **/ | |
c46f2334 | 213 | static inline void sg_mark_end(struct scatterlist *sg) |
82f66fbe | 214 | { |
c46f2334 JA |
215 | #ifdef CONFIG_DEBUG_SG |
216 | BUG_ON(sg->sg_magic != SG_MAGIC); | |
217 | #endif | |
218 | /* | |
219 | * Set termination bit, clear potential chain bit | |
220 | */ | |
18dabf47 | 221 | sg->page_link |= 0x02; |
c46f2334 | 222 | sg->page_link &= ~0x01; |
82f66fbe JA |
223 | } |
224 | ||
82f66fbe JA |
225 | /** |
226 | * sg_init_table - Initialize SG table | |
227 | * @sgl: The SG table | |
228 | * @nents: Number of entries in table | |
229 | * | |
230 | * Notes: | |
231 | * If this is part of a chained sg table, sg_mark_end() should be | |
232 | * used only on the last table part. | |
233 | * | |
234 | **/ | |
235 | static inline void sg_init_table(struct scatterlist *sgl, unsigned int nents) | |
236 | { | |
237 | memset(sgl, 0, sizeof(*sgl) * nents); | |
d6ec0842 JA |
238 | #ifdef CONFIG_DEBUG_SG |
239 | { | |
513f54b7 | 240 | unsigned int i; |
d6ec0842 JA |
241 | for (i = 0; i < nents; i++) |
242 | sgl[i].sg_magic = SG_MAGIC; | |
243 | } | |
244 | #endif | |
c46f2334 | 245 | sg_mark_end(&sgl[nents - 1]); |
82f66fbe JA |
246 | } |
247 | ||
013fb339 JA |
248 | /** |
249 | * sg_init_one - Initialize a single entry sg list | |
250 | * @sg: SG entry | |
251 | * @buf: Virtual address for IO | |
252 | * @buflen: IO length | |
253 | * | |
254 | * Notes: | |
255 | * This should not be used on a single entry that is part of a larger | |
256 | * table. Use sg_init_table() for that. | |
257 | * | |
258 | **/ | |
259 | static inline void sg_init_one(struct scatterlist *sg, const void *buf, | |
260 | unsigned int buflen) | |
261 | { | |
262 | sg_init_table(sg, 1); | |
263 | sg_set_buf(sg, buf, buflen); | |
264 | } | |
265 | ||
82f66fbe JA |
266 | /** |
267 | * sg_phys - Return physical address of an sg entry | |
268 | * @sg: SG entry | |
269 | * | |
270 | * Description: | |
271 | * This calls page_to_phys() on the page in this sg entry, and adds the | |
272 | * sg offset. The caller must know that it is legal to call page_to_phys() | |
273 | * on the sg page. | |
274 | * | |
275 | **/ | |
85cdffcd | 276 | static inline dma_addr_t sg_phys(struct scatterlist *sg) |
82f66fbe JA |
277 | { |
278 | return page_to_phys(sg_page(sg)) + sg->offset; | |
279 | } | |
280 | ||
281 | /** | |
282 | * sg_virt - Return virtual address of an sg entry | |
18dabf47 | 283 | * @sg: SG entry |
82f66fbe JA |
284 | * |
285 | * Description: | |
286 | * This calls page_address() on the page in this sg entry, and adds the | |
287 | * sg offset. The caller must know that the sg page has a valid virtual | |
288 | * mapping. | |
289 | * | |
290 | **/ | |
291 | static inline void *sg_virt(struct scatterlist *sg) | |
292 | { | |
293 | return page_address(sg_page(sg)) + sg->offset; | |
294 | } | |
295 | ||
1da177e4 | 296 | #endif /* _LINUX_SCATTERLIST_H */ |