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