1#ifndef _LINUX_SCATTERLIST_H
2#define _LINUX_SCATTERLIST_H
3
4#include <linux/string.h>
5#include <linux/bug.h>
6#include <linux/mm.h>
7
8#include <asm/types.h>
9#include <asm/scatterlist.h>
10#include <asm/io.h>
11
12struct sg_table {
13 struct scatterlist *sgl;
14 unsigned int nents;
15 unsigned int orig_nents;
16};
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35#define SG_MAGIC 0x87654321
36
37
38
39
40
41
42#define sg_is_chain(sg) ((sg)->page_link & 0x01)
43#define sg_is_last(sg) ((sg)->page_link & 0x02)
44#define sg_chain_ptr(sg) \
45 ((struct scatterlist *) ((sg)->page_link & ~0x03))
46
47
48
49
50
51
52
53
54
55
56
57static inline void sg_assign_page(struct scatterlist *sg, struct page *page)
58{
59 unsigned long page_link = sg->page_link & 0x3;
60
61
62
63
64
65 BUG_ON((unsigned long) page & 0x03);
66#ifdef CONFIG_DEBUG_SG
67 BUG_ON(sg->sg_magic != SG_MAGIC);
68 BUG_ON(sg_is_chain(sg));
69#endif
70 sg->page_link = page_link | (unsigned long) page;
71}
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87static inline void sg_set_page(struct scatterlist *sg, struct page *page,
88 unsigned int len, unsigned int offset)
89{
90 sg_assign_page(sg, page);
91 sg->offset = offset;
92 sg->length = len;
93}
94
95static inline struct page *sg_page(struct scatterlist *sg)
96{
97#ifdef CONFIG_DEBUG_SG
98 BUG_ON(sg->sg_magic != SG_MAGIC);
99 BUG_ON(sg_is_chain(sg));
100#endif
101 return (struct page *)((sg)->page_link & ~0x3);
102}
103
104
105
106
107
108
109
110
111static inline void sg_set_buf(struct scatterlist *sg, const void *buf,
112 unsigned int buflen)
113{
114 sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));
115}
116
117
118
119
120#define for_each_sg(sglist, sg, nr, __i) \
121 for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg))
122
123
124
125
126
127
128
129
130
131
132
133static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents,
134 struct scatterlist *sgl)
135{
136#ifndef ARCH_HAS_SG_CHAIN
137 BUG();
138#endif
139
140
141
142
143 prv[prv_nents - 1].offset = 0;
144 prv[prv_nents - 1].length = 0;
145
146
147
148
149
150 prv[prv_nents - 1].page_link = ((unsigned long) sgl | 0x01) & ~0x02;
151}
152
153
154
155
156
157
158
159
160
161
162static inline void sg_mark_end(struct scatterlist *sg)
163{
164#ifdef CONFIG_DEBUG_SG
165 BUG_ON(sg->sg_magic != SG_MAGIC);
166#endif
167
168
169
170 sg->page_link |= 0x02;
171 sg->page_link &= ~0x01;
172}
173
174
175
176
177
178
179
180
181
182
183
184static inline dma_addr_t sg_phys(struct scatterlist *sg)
185{
186 return page_to_phys(sg_page(sg)) + sg->offset;
187}
188
189
190
191
192
193
194
195
196
197
198
199static inline void *sg_virt(struct scatterlist *sg)
200{
201 return page_address(sg_page(sg)) + sg->offset;
202}
203
204int sg_nents(struct scatterlist *sg);
205struct scatterlist *sg_next(struct scatterlist *);
206struct scatterlist *sg_last(struct scatterlist *s, unsigned int);
207void sg_init_table(struct scatterlist *, unsigned int);
208void sg_init_one(struct scatterlist *, const void *, unsigned int);
209
210typedef struct scatterlist *(sg_alloc_fn)(unsigned int, gfp_t);
211typedef void (sg_free_fn)(struct scatterlist *, unsigned int);
212
213void __sg_free_table(struct sg_table *, unsigned int, sg_free_fn *);
214void sg_free_table(struct sg_table *);
215int __sg_alloc_table(struct sg_table *, unsigned int, unsigned int, gfp_t,
216 sg_alloc_fn *);
217int sg_alloc_table(struct sg_table *, unsigned int, gfp_t);
218int sg_alloc_table_from_pages(struct sg_table *sgt,
219 struct page **pages, unsigned int n_pages,
220 unsigned long offset, unsigned long size,
221 gfp_t gfp_mask);
222
223size_t sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents,
224 void *buf, size_t buflen);
225size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents,
226 void *buf, size_t buflen);
227
228
229
230
231
232#define SG_MAX_SINGLE_ALLOC (PAGE_SIZE / sizeof(struct scatterlist))
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251#define SG_MITER_ATOMIC (1 << 0)
252#define SG_MITER_TO_SG (1 << 1)
253#define SG_MITER_FROM_SG (1 << 2)
254
255struct sg_mapping_iter {
256
257 struct page *page;
258 void *addr;
259 size_t length;
260 size_t consumed;
261
262
263 struct scatterlist *__sg;
264 unsigned int __nents;
265 unsigned int __offset;
266 unsigned int __flags;
267};
268
269void sg_miter_start(struct sg_mapping_iter *miter, struct scatterlist *sgl,
270 unsigned int nents, unsigned int flags);
271bool sg_miter_next(struct sg_mapping_iter *miter);
272void sg_miter_stop(struct sg_mapping_iter *miter);
273
274#endif
275