diff options
Diffstat (limited to 'include/linux/scatterlist.h')
-rw-r--r-- | include/linux/scatterlist.h | 191 |
1 files changed, 67 insertions, 124 deletions
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index 457123171389..a3d567a974e8 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h | |||
@@ -7,6 +7,12 @@ | |||
7 | #include <linux/string.h> | 7 | #include <linux/string.h> |
8 | #include <asm/io.h> | 8 | #include <asm/io.h> |
9 | 9 | ||
10 | struct sg_table { | ||
11 | struct scatterlist *sgl; /* the list */ | ||
12 | unsigned int nents; /* number of mapped entries */ | ||
13 | unsigned int orig_nents; /* original size of list */ | ||
14 | }; | ||
15 | |||
10 | /* | 16 | /* |
11 | * Notes on SG table design. | 17 | * Notes on SG table design. |
12 | * | 18 | * |
@@ -26,6 +32,16 @@ | |||
26 | 32 | ||
27 | #define SG_MAGIC 0x87654321 | 33 | #define SG_MAGIC 0x87654321 |
28 | 34 | ||
35 | /* | ||
36 | * We overload the LSB of the page pointer to indicate whether it's | ||
37 | * a valid sg entry, or whether it points to the start of a new scatterlist. | ||
38 | * Those low bits are there for everyone! (thanks mason :-) | ||
39 | */ | ||
40 | #define sg_is_chain(sg) ((sg)->page_link & 0x01) | ||
41 | #define sg_is_last(sg) ((sg)->page_link & 0x02) | ||
42 | #define sg_chain_ptr(sg) \ | ||
43 | ((struct scatterlist *) ((sg)->page_link & ~0x03)) | ||
44 | |||
29 | /** | 45 | /** |
30 | * sg_assign_page - Assign a given page to an SG entry | 46 | * sg_assign_page - Assign a given page to an SG entry |
31 | * @sg: SG entry | 47 | * @sg: SG entry |
@@ -47,6 +63,7 @@ static inline void sg_assign_page(struct scatterlist *sg, struct page *page) | |||
47 | BUG_ON((unsigned long) page & 0x03); | 63 | BUG_ON((unsigned long) page & 0x03); |
48 | #ifdef CONFIG_DEBUG_SG | 64 | #ifdef CONFIG_DEBUG_SG |
49 | BUG_ON(sg->sg_magic != SG_MAGIC); | 65 | BUG_ON(sg->sg_magic != SG_MAGIC); |
66 | BUG_ON(sg_is_chain(sg)); | ||
50 | #endif | 67 | #endif |
51 | sg->page_link = page_link | (unsigned long) page; | 68 | sg->page_link = page_link | (unsigned long) page; |
52 | } | 69 | } |
@@ -73,7 +90,14 @@ static inline void sg_set_page(struct scatterlist *sg, struct page *page, | |||
73 | sg->length = len; | 90 | sg->length = len; |
74 | } | 91 | } |
75 | 92 | ||
76 | #define sg_page(sg) ((struct page *) ((sg)->page_link & ~0x3)) | 93 | static inline struct page *sg_page(struct scatterlist *sg) |
94 | { | ||
95 | #ifdef CONFIG_DEBUG_SG | ||
96 | BUG_ON(sg->sg_magic != SG_MAGIC); | ||
97 | BUG_ON(sg_is_chain(sg)); | ||
98 | #endif | ||
99 | return (struct page *)((sg)->page_link & ~0x3); | ||
100 | } | ||
77 | 101 | ||
78 | /** | 102 | /** |
79 | * sg_set_buf - Set sg entry to point at given data | 103 | * sg_set_buf - Set sg entry to point at given data |
@@ -89,81 +113,12 @@ static inline void sg_set_buf(struct scatterlist *sg, const void *buf, | |||
89 | } | 113 | } |
90 | 114 | ||
91 | /* | 115 | /* |
92 | * We overload the LSB of the page pointer to indicate whether it's | ||
93 | * a valid sg entry, or whether it points to the start of a new scatterlist. | ||
94 | * Those low bits are there for everyone! (thanks mason :-) | ||
95 | */ | ||
96 | #define sg_is_chain(sg) ((sg)->page_link & 0x01) | ||
97 | #define sg_is_last(sg) ((sg)->page_link & 0x02) | ||
98 | #define sg_chain_ptr(sg) \ | ||
99 | ((struct scatterlist *) ((sg)->page_link & ~0x03)) | ||
100 | |||
101 | /** | ||
102 | * sg_next - return the next scatterlist entry in a list | ||
103 | * @sg: The current sg entry | ||
104 | * | ||
105 | * Description: | ||
106 | * Usually the next entry will be @sg@ + 1, but if this sg element is part | ||
107 | * of a chained scatterlist, it could jump to the start of a new | ||
108 | * scatterlist array. | ||
109 | * | ||
110 | **/ | ||
111 | static inline struct scatterlist *sg_next(struct scatterlist *sg) | ||
112 | { | ||
113 | #ifdef CONFIG_DEBUG_SG | ||
114 | BUG_ON(sg->sg_magic != SG_MAGIC); | ||
115 | #endif | ||
116 | if (sg_is_last(sg)) | ||
117 | return NULL; | ||
118 | |||
119 | sg++; | ||
120 | if (unlikely(sg_is_chain(sg))) | ||
121 | sg = sg_chain_ptr(sg); | ||
122 | |||
123 | return sg; | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | * Loop over each sg element, following the pointer to a new list if necessary | 116 | * Loop over each sg element, following the pointer to a new list if necessary |
128 | */ | 117 | */ |
129 | #define for_each_sg(sglist, sg, nr, __i) \ | 118 | #define for_each_sg(sglist, sg, nr, __i) \ |
130 | for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg)) | 119 | for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg)) |
131 | 120 | ||
132 | /** | 121 | /** |
133 | * sg_last - return the last scatterlist entry in a list | ||
134 | * @sgl: First entry in the scatterlist | ||
135 | * @nents: Number of entries in the scatterlist | ||
136 | * | ||
137 | * Description: | ||
138 | * Should only be used casually, it (currently) scan the entire list | ||
139 | * to get the last entry. | ||
140 | * | ||
141 | * Note that the @sgl@ pointer passed in need not be the first one, | ||
142 | * the important bit is that @nents@ denotes the number of entries that | ||
143 | * exist from @sgl@. | ||
144 | * | ||
145 | **/ | ||
146 | static inline struct scatterlist *sg_last(struct scatterlist *sgl, | ||
147 | unsigned int nents) | ||
148 | { | ||
149 | #ifndef ARCH_HAS_SG_CHAIN | ||
150 | struct scatterlist *ret = &sgl[nents - 1]; | ||
151 | #else | ||
152 | struct scatterlist *sg, *ret = NULL; | ||
153 | int i; | ||
154 | |||
155 | for_each_sg(sgl, sg, nents, i) | ||
156 | ret = sg; | ||
157 | |||
158 | #endif | ||
159 | #ifdef CONFIG_DEBUG_SG | ||
160 | BUG_ON(sgl[0].sg_magic != SG_MAGIC); | ||
161 | BUG_ON(!sg_is_last(ret)); | ||
162 | #endif | ||
163 | return ret; | ||
164 | } | ||
165 | |||
166 | /** | ||
167 | * sg_chain - Chain two sglists together | 122 | * sg_chain - Chain two sglists together |
168 | * @prv: First scatterlist | 123 | * @prv: First scatterlist |
169 | * @prv_nents: Number of entries in prv | 124 | * @prv_nents: Number of entries in prv |
@@ -179,71 +134,39 @@ static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents, | |||
179 | #ifndef ARCH_HAS_SG_CHAIN | 134 | #ifndef ARCH_HAS_SG_CHAIN |
180 | BUG(); | 135 | BUG(); |
181 | #endif | 136 | #endif |
182 | prv[prv_nents - 1].page_link = (unsigned long) sgl | 0x01; | ||
183 | } | ||
184 | 137 | ||
185 | /** | 138 | /* |
186 | * sg_mark_end - Mark the end of the scatterlist | 139 | * offset and length are unused for chain entry. Clear them. |
187 | * @sgl: Scatterlist | 140 | */ |
188 | * @nents: Number of entries in sgl | 141 | prv[prv_nents - 1].offset = 0; |
189 | * | 142 | prv[prv_nents - 1].length = 0; |
190 | * Description: | ||
191 | * Marks the last entry as the termination point for sg_next() | ||
192 | * | ||
193 | **/ | ||
194 | static inline void sg_mark_end(struct scatterlist *sgl, unsigned int nents) | ||
195 | { | ||
196 | sgl[nents - 1].page_link = 0x02; | ||
197 | } | ||
198 | |||
199 | static inline void __sg_mark_end(struct scatterlist *sg) | ||
200 | { | ||
201 | sg->page_link |= 0x02; | ||
202 | } | ||
203 | 143 | ||
204 | /** | 144 | /* |
205 | * sg_init_one - Initialize a single entry sg list | 145 | * Set lowest bit to indicate a link pointer, and make sure to clear |
206 | * @sg: SG entry | 146 | * the termination bit if it happens to be set. |
207 | * @buf: Virtual address for IO | 147 | */ |
208 | * @buflen: IO length | 148 | prv[prv_nents - 1].page_link = ((unsigned long) sgl | 0x01) & ~0x02; |
209 | * | ||
210 | * Notes: | ||
211 | * This should not be used on a single entry that is part of a larger | ||
212 | * table. Use sg_init_table() for that. | ||
213 | * | ||
214 | **/ | ||
215 | static inline void sg_init_one(struct scatterlist *sg, const void *buf, | ||
216 | unsigned int buflen) | ||
217 | { | ||
218 | memset(sg, 0, sizeof(*sg)); | ||
219 | #ifdef CONFIG_DEBUG_SG | ||
220 | sg->sg_magic = SG_MAGIC; | ||
221 | #endif | ||
222 | sg_mark_end(sg, 1); | ||
223 | sg_set_buf(sg, buf, buflen); | ||
224 | } | 149 | } |
225 | 150 | ||
226 | /** | 151 | /** |
227 | * sg_init_table - Initialize SG table | 152 | * sg_mark_end - Mark the end of the scatterlist |
228 | * @sgl: The SG table | 153 | * @sg: SG entryScatterlist |
229 | * @nents: Number of entries in table | ||
230 | * | 154 | * |
231 | * Notes: | 155 | * Description: |
232 | * If this is part of a chained sg table, sg_mark_end() should be | 156 | * Marks the passed in sg entry as the termination point for the sg |
233 | * used only on the last table part. | 157 | * table. A call to sg_next() on this entry will return NULL. |
234 | * | 158 | * |
235 | **/ | 159 | **/ |
236 | static inline void sg_init_table(struct scatterlist *sgl, unsigned int nents) | 160 | static inline void sg_mark_end(struct scatterlist *sg) |
237 | { | 161 | { |
238 | memset(sgl, 0, sizeof(*sgl) * nents); | ||
239 | sg_mark_end(sgl, nents); | ||
240 | #ifdef CONFIG_DEBUG_SG | 162 | #ifdef CONFIG_DEBUG_SG |
241 | { | 163 | BUG_ON(sg->sg_magic != SG_MAGIC); |
242 | int i; | ||
243 | for (i = 0; i < nents; i++) | ||
244 | sgl[i].sg_magic = SG_MAGIC; | ||
245 | } | ||
246 | #endif | 164 | #endif |
165 | /* | ||
166 | * Set termination bit, clear potential chain bit | ||
167 | */ | ||
168 | sg->page_link |= 0x02; | ||
169 | sg->page_link &= ~0x01; | ||
247 | } | 170 | } |
248 | 171 | ||
249 | /** | 172 | /** |
@@ -276,4 +199,24 @@ static inline void *sg_virt(struct scatterlist *sg) | |||
276 | return page_address(sg_page(sg)) + sg->offset; | 199 | return page_address(sg_page(sg)) + sg->offset; |
277 | } | 200 | } |
278 | 201 | ||
202 | struct scatterlist *sg_next(struct scatterlist *); | ||
203 | struct scatterlist *sg_last(struct scatterlist *s, unsigned int); | ||
204 | void sg_init_table(struct scatterlist *, unsigned int); | ||
205 | void sg_init_one(struct scatterlist *, const void *, unsigned int); | ||
206 | |||
207 | typedef struct scatterlist *(sg_alloc_fn)(unsigned int, gfp_t); | ||
208 | typedef void (sg_free_fn)(struct scatterlist *, unsigned int); | ||
209 | |||
210 | void __sg_free_table(struct sg_table *, unsigned int, sg_free_fn *); | ||
211 | void sg_free_table(struct sg_table *); | ||
212 | int __sg_alloc_table(struct sg_table *, unsigned int, unsigned int, gfp_t, | ||
213 | sg_alloc_fn *); | ||
214 | int sg_alloc_table(struct sg_table *, unsigned int, gfp_t); | ||
215 | |||
216 | /* | ||
217 | * Maximum number of entries that will be allocated in one piece, if | ||
218 | * a list larger than this is required then chaining will be utilized. | ||
219 | */ | ||
220 | #define SG_MAX_SINGLE_ALLOC (PAGE_SIZE / sizeof(struct scatterlist)) | ||
221 | |||
279 | #endif /* _LINUX_SCATTERLIST_H */ | 222 | #endif /* _LINUX_SCATTERLIST_H */ |