]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | #ifndef _LINUX_SCATTERLIST_H |
2 | #define _LINUX_SCATTERLIST_H | |
3 | ||
d32311fe | 4 | #include <asm/scatterlist.h> |
82f66fbe | 5 | #include <asm/io.h> |
d32311fe HX |
6 | #include <linux/mm.h> |
7 | #include <linux/string.h> | |
1da177e4 | 8 | |
82f66fbe JA |
9 | /** |
10 | * sg_set_page - Set sg entry to point at given page | |
11 | * @sg: SG entry | |
12 | * @page: The page | |
13 | * | |
14 | * Description: | |
15 | * Use this function to set an sg entry pointing at a page, never assign | |
16 | * the page directly. We encode sg table information in the lower bits | |
17 | * of the page pointer. See sg_page() for looking up the page belonging | |
18 | * to an sg entry. | |
19 | * | |
20 | **/ | |
21 | static inline void sg_set_page(struct scatterlist *sg, struct page *page) | |
22 | { | |
23 | sg->page = page; | |
24 | } | |
25 | ||
26 | #define sg_page(sg) ((sg)->page) | |
27 | ||
03fd9cee | 28 | static inline void sg_set_buf(struct scatterlist *sg, const void *buf, |
d32311fe HX |
29 | unsigned int buflen) |
30 | { | |
82f66fbe | 31 | sg_set_page(sg, virt_to_page(buf)); |
1da177e4 LT |
32 | sg->offset = offset_in_page(buf); |
33 | sg->length = buflen; | |
34 | } | |
35 | ||
70eb8040 JA |
36 | /* |
37 | * We overload the LSB of the page pointer to indicate whether it's | |
38 | * a valid sg entry, or whether it points to the start of a new scatterlist. | |
39 | * Those low bits are there for everyone! (thanks mason :-) | |
40 | */ | |
41 | #define sg_is_chain(sg) ((unsigned long) (sg)->page & 0x01) | |
42 | #define sg_chain_ptr(sg) \ | |
43 | ((struct scatterlist *) ((unsigned long) (sg)->page & ~0x01)) | |
44 | ||
45 | /** | |
46 | * sg_next - return the next scatterlist entry in a list | |
47 | * @sg: The current sg entry | |
48 | * | |
49 | * Usually the next entry will be @sg@ + 1, but if this sg element is part | |
50 | * of a chained scatterlist, it could jump to the start of a new | |
51 | * scatterlist array. | |
52 | * | |
53 | * Note that the caller must ensure that there are further entries after | |
54 | * the current entry, this function will NOT return NULL for an end-of-list. | |
55 | * | |
56 | */ | |
57 | static inline struct scatterlist *sg_next(struct scatterlist *sg) | |
58 | { | |
59 | sg++; | |
60 | ||
61 | if (unlikely(sg_is_chain(sg))) | |
62 | sg = sg_chain_ptr(sg); | |
63 | ||
64 | return sg; | |
65 | } | |
96b418c9 JA |
66 | |
67 | /* | |
68 | * Loop over each sg element, following the pointer to a new list if necessary | |
69 | */ | |
70 | #define for_each_sg(sglist, sg, nr, __i) \ | |
71 | for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg)) | |
72 | ||
70eb8040 JA |
73 | /** |
74 | * sg_last - return the last scatterlist entry in a list | |
75 | * @sgl: First entry in the scatterlist | |
76 | * @nents: Number of entries in the scatterlist | |
77 | * | |
78 | * Should only be used casually, it (currently) scan the entire list | |
79 | * to get the last entry. | |
80 | * | |
81 | * Note that the @sgl@ pointer passed in need not be the first one, | |
82 | * the important bit is that @nents@ denotes the number of entries that | |
83 | * exist from @sgl@. | |
84 | * | |
85 | */ | |
86 | static inline struct scatterlist *sg_last(struct scatterlist *sgl, | |
87 | unsigned int nents) | |
88 | { | |
89 | #ifndef ARCH_HAS_SG_CHAIN | |
90 | struct scatterlist *ret = &sgl[nents - 1]; | |
91 | #else | |
92 | struct scatterlist *sg, *ret = NULL; | |
93 | int i; | |
94 | ||
95 | for_each_sg(sgl, sg, nents, i) | |
96 | ret = sg; | |
97 | ||
98 | #endif | |
99 | return ret; | |
100 | } | |
101 | ||
102 | /** | |
103 | * sg_chain - Chain two sglists together | |
104 | * @prv: First scatterlist | |
105 | * @prv_nents: Number of entries in prv | |
106 | * @sgl: Second scatterlist | |
107 | * | |
108 | * Links @prv@ and @sgl@ together, to form a longer scatterlist. | |
109 | * | |
110 | */ | |
111 | static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents, | |
112 | struct scatterlist *sgl) | |
113 | { | |
114 | #ifndef ARCH_HAS_SG_CHAIN | |
115 | BUG(); | |
116 | #endif | |
117 | prv[prv_nents - 1].page = (struct page *) ((unsigned long) sgl | 0x01); | |
118 | } | |
119 | ||
82f66fbe JA |
120 | /** |
121 | * sg_mark_end - Mark the end of the scatterlist | |
122 | * @sgl: Scatterlist | |
123 | * @nents: Number of entries in sgl | |
124 | * | |
125 | * Description: | |
126 | * Marks the last entry as the termination point for sg_next() | |
127 | * | |
128 | **/ | |
129 | static inline void sg_mark_end(struct scatterlist *sgl, unsigned int nents) | |
130 | { | |
131 | } | |
132 | ||
133 | static inline void __sg_mark_end(struct scatterlist *sg) | |
134 | { | |
135 | } | |
136 | ||
137 | ||
138 | /** | |
139 | * sg_init_one - Initialize a single entry sg list | |
140 | * @sg: SG entry | |
141 | * @buf: Virtual address for IO | |
142 | * @buflen: IO length | |
143 | * | |
144 | * Notes: | |
145 | * This should not be used on a single entry that is part of a larger | |
146 | * table. Use sg_init_table() for that. | |
147 | * | |
148 | **/ | |
149 | static inline void sg_init_one(struct scatterlist *sg, const void *buf, | |
150 | unsigned int buflen) | |
151 | { | |
152 | memset(sg, 0, sizeof(*sg)); | |
153 | sg_mark_end(sg, 1); | |
154 | sg_set_buf(sg, buf, buflen); | |
155 | } | |
156 | ||
157 | /** | |
158 | * sg_init_table - Initialize SG table | |
159 | * @sgl: The SG table | |
160 | * @nents: Number of entries in table | |
161 | * | |
162 | * Notes: | |
163 | * If this is part of a chained sg table, sg_mark_end() should be | |
164 | * used only on the last table part. | |
165 | * | |
166 | **/ | |
167 | static inline void sg_init_table(struct scatterlist *sgl, unsigned int nents) | |
168 | { | |
169 | memset(sgl, 0, sizeof(*sgl) * nents); | |
170 | sg_mark_end(sgl, nents); | |
171 | } | |
172 | ||
173 | /** | |
174 | * sg_phys - Return physical address of an sg entry | |
175 | * @sg: SG entry | |
176 | * | |
177 | * Description: | |
178 | * This calls page_to_phys() on the page in this sg entry, and adds the | |
179 | * sg offset. The caller must know that it is legal to call page_to_phys() | |
180 | * on the sg page. | |
181 | * | |
182 | **/ | |
183 | static inline unsigned long sg_phys(struct scatterlist *sg) | |
184 | { | |
185 | return page_to_phys(sg_page(sg)) + sg->offset; | |
186 | } | |
187 | ||
188 | /** | |
189 | * sg_virt - Return virtual address of an sg entry | |
190 | * @sg: SG entry | |
191 | * | |
192 | * Description: | |
193 | * This calls page_address() on the page in this sg entry, and adds the | |
194 | * sg offset. The caller must know that the sg page has a valid virtual | |
195 | * mapping. | |
196 | * | |
197 | **/ | |
198 | static inline void *sg_virt(struct scatterlist *sg) | |
199 | { | |
200 | return page_address(sg_page(sg)) + sg->offset; | |
201 | } | |
202 | ||
1da177e4 | 203 | #endif /* _LINUX_SCATTERLIST_H */ |