blob: c6136e8a7f58fcb561ffc042b501e7a9f554c1a1 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001#ifndef _LINUX_SCATTERLIST_H
2#define _LINUX_SCATTERLIST_H
3
Herbert Xud32311f2005-09-17 14:41:40 +10004#include <asm/scatterlist.h>
5#include <linux/mm.h>
6#include <linux/string.h>
Jens Axboe18dabf42007-10-22 19:57:20 +02007#include <asm/io.h>
8
9/*
10 * Notes on SG table design.
11 *
12 * Architectures must provide an unsigned long page_link field in the
13 * scatterlist struct. We use that to place the page pointer AND encode
14 * information about the sg table as well. The two lower bits are reserved
15 * for this information.
16 *
17 * If bit 0 is set, then the page_link contains a pointer to the next sg
18 * table list. Otherwise the next entry is at sg + 1.
19 *
20 * If bit 1 is set, then this sg entry is the last element in a list.
21 *
22 * See sg_next().
23 *
24 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070025
Jens Axboe82f66fb2007-10-22 17:07:37 +020026/**
27 * sg_set_page - Set sg entry to point at given page
28 * @sg: SG entry
29 * @page: The page
30 *
31 * Description:
32 * Use this function to set an sg entry pointing at a page, never assign
33 * the page directly. We encode sg table information in the lower bits
34 * of the page pointer. See sg_page() for looking up the page belonging
35 * to an sg entry.
36 *
37 **/
38static inline void sg_set_page(struct scatterlist *sg, struct page *page)
39{
Jens Axboe18dabf42007-10-22 19:57:20 +020040 unsigned long page_link = sg->page_link & 0x3;
41
42 sg->page_link = page_link | (unsigned long) page;
Jens Axboe82f66fb2007-10-22 17:07:37 +020043}
44
Jens Axboe18dabf42007-10-22 19:57:20 +020045#define sg_page(sg) ((struct page *) ((sg)->page_link & ~0x3))
Jens Axboe82f66fb2007-10-22 17:07:37 +020046
Jens Axboe18dabf42007-10-22 19:57:20 +020047/**
48 * sg_set_buf - Set sg entry to point at given data
49 * @sg: SG entry
50 * @buf: Data
51 * @buflen: Data length
52 *
53 **/
Herbert Xu03fd9ce2006-08-14 23:11:53 +100054static inline void sg_set_buf(struct scatterlist *sg, const void *buf,
Herbert Xud32311f2005-09-17 14:41:40 +100055 unsigned int buflen)
56{
Jens Axboe82f66fb2007-10-22 17:07:37 +020057 sg_set_page(sg, virt_to_page(buf));
Linus Torvalds1da177e2005-04-16 15:20:36 -070058 sg->offset = offset_in_page(buf);
59 sg->length = buflen;
60}
61
Jens Axboe70eb8042007-07-16 21:17:16 +020062/*
63 * We overload the LSB of the page pointer to indicate whether it's
64 * a valid sg entry, or whether it points to the start of a new scatterlist.
65 * Those low bits are there for everyone! (thanks mason :-)
66 */
Jens Axboe18dabf42007-10-22 19:57:20 +020067#define sg_is_chain(sg) ((sg)->page_link & 0x01)
68#define sg_is_last(sg) ((sg)->page_link & 0x02)
Jens Axboe70eb8042007-07-16 21:17:16 +020069#define sg_chain_ptr(sg) \
Jens Axboe18dabf42007-10-22 19:57:20 +020070 ((struct scatterlist *) ((sg)->page_link & ~0x03))
Jens Axboe70eb8042007-07-16 21:17:16 +020071
72/**
73 * sg_next - return the next scatterlist entry in a list
74 * @sg: The current sg entry
75 *
Jens Axboe18dabf42007-10-22 19:57:20 +020076 * Description:
77 * Usually the next entry will be @sg@ + 1, but if this sg element is part
78 * of a chained scatterlist, it could jump to the start of a new
79 * scatterlist array.
Jens Axboe70eb8042007-07-16 21:17:16 +020080 *
Jens Axboe18dabf42007-10-22 19:57:20 +020081 **/
Jens Axboe70eb8042007-07-16 21:17:16 +020082static inline struct scatterlist *sg_next(struct scatterlist *sg)
83{
Jens Axboe18dabf42007-10-22 19:57:20 +020084 if (sg_is_last(sg))
85 return NULL;
Jens Axboe70eb8042007-07-16 21:17:16 +020086
Jens Axboe18dabf42007-10-22 19:57:20 +020087 sg++;
Jens Axboe70eb8042007-07-16 21:17:16 +020088 if (unlikely(sg_is_chain(sg)))
89 sg = sg_chain_ptr(sg);
90
91 return sg;
92}
Jens Axboe96b418c2007-05-09 09:02:57 +020093
94/*
95 * Loop over each sg element, following the pointer to a new list if necessary
96 */
97#define for_each_sg(sglist, sg, nr, __i) \
98 for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg))
99
Jens Axboe70eb8042007-07-16 21:17:16 +0200100/**
101 * sg_last - return the last scatterlist entry in a list
102 * @sgl: First entry in the scatterlist
103 * @nents: Number of entries in the scatterlist
104 *
Jens Axboe18dabf42007-10-22 19:57:20 +0200105 * Description:
106 * Should only be used casually, it (currently) scan the entire list
107 * to get the last entry.
Jens Axboe70eb8042007-07-16 21:17:16 +0200108 *
Jens Axboe18dabf42007-10-22 19:57:20 +0200109 * Note that the @sgl@ pointer passed in need not be the first one,
110 * the important bit is that @nents@ denotes the number of entries that
111 * exist from @sgl@.
Jens Axboe70eb8042007-07-16 21:17:16 +0200112 *
Jens Axboe18dabf42007-10-22 19:57:20 +0200113 **/
Jens Axboe70eb8042007-07-16 21:17:16 +0200114static inline struct scatterlist *sg_last(struct scatterlist *sgl,
115 unsigned int nents)
116{
117#ifndef ARCH_HAS_SG_CHAIN
118 struct scatterlist *ret = &sgl[nents - 1];
119#else
120 struct scatterlist *sg, *ret = NULL;
121 int i;
122
123 for_each_sg(sgl, sg, nents, i)
124 ret = sg;
125
126#endif
127 return ret;
128}
129
130/**
131 * sg_chain - Chain two sglists together
132 * @prv: First scatterlist
133 * @prv_nents: Number of entries in prv
134 * @sgl: Second scatterlist
135 *
Jens Axboe18dabf42007-10-22 19:57:20 +0200136 * Description:
137 * Links @prv@ and @sgl@ together, to form a longer scatterlist.
Jens Axboe70eb8042007-07-16 21:17:16 +0200138 *
Jens Axboe18dabf42007-10-22 19:57:20 +0200139 **/
Jens Axboe70eb8042007-07-16 21:17:16 +0200140static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents,
141 struct scatterlist *sgl)
142{
143#ifndef ARCH_HAS_SG_CHAIN
144 BUG();
145#endif
Jens Axboe18dabf42007-10-22 19:57:20 +0200146 prv[prv_nents - 1].page_link = (unsigned long) sgl | 0x01;
Jens Axboe70eb8042007-07-16 21:17:16 +0200147}
148
Jens Axboe82f66fb2007-10-22 17:07:37 +0200149/**
150 * sg_mark_end - Mark the end of the scatterlist
151 * @sgl: Scatterlist
152 * @nents: Number of entries in sgl
153 *
154 * Description:
155 * Marks the last entry as the termination point for sg_next()
156 *
157 **/
158static inline void sg_mark_end(struct scatterlist *sgl, unsigned int nents)
159{
Jens Axboe18dabf42007-10-22 19:57:20 +0200160 sgl[nents - 1].page_link = 0x02;
Jens Axboe82f66fb2007-10-22 17:07:37 +0200161}
162
163static inline void __sg_mark_end(struct scatterlist *sg)
164{
Jens Axboe18dabf42007-10-22 19:57:20 +0200165 sg->page_link |= 0x02;
Jens Axboe82f66fb2007-10-22 17:07:37 +0200166}
167
Jens Axboe82f66fb2007-10-22 17:07:37 +0200168/**
169 * sg_init_one - Initialize a single entry sg list
170 * @sg: SG entry
171 * @buf: Virtual address for IO
172 * @buflen: IO length
173 *
174 * Notes:
175 * This should not be used on a single entry that is part of a larger
176 * table. Use sg_init_table() for that.
177 *
178 **/
179static inline void sg_init_one(struct scatterlist *sg, const void *buf,
180 unsigned int buflen)
181{
182 memset(sg, 0, sizeof(*sg));
183 sg_mark_end(sg, 1);
184 sg_set_buf(sg, buf, buflen);
185}
186
187/**
188 * sg_init_table - Initialize SG table
189 * @sgl: The SG table
190 * @nents: Number of entries in table
191 *
192 * Notes:
193 * If this is part of a chained sg table, sg_mark_end() should be
194 * used only on the last table part.
195 *
196 **/
197static inline void sg_init_table(struct scatterlist *sgl, unsigned int nents)
198{
199 memset(sgl, 0, sizeof(*sgl) * nents);
200 sg_mark_end(sgl, nents);
201}
202
203/**
204 * sg_phys - Return physical address of an sg entry
205 * @sg: SG entry
206 *
207 * Description:
208 * This calls page_to_phys() on the page in this sg entry, and adds the
209 * sg offset. The caller must know that it is legal to call page_to_phys()
210 * on the sg page.
211 *
212 **/
213static inline unsigned long sg_phys(struct scatterlist *sg)
214{
215 return page_to_phys(sg_page(sg)) + sg->offset;
216}
217
218/**
219 * sg_virt - Return virtual address of an sg entry
Jens Axboe18dabf42007-10-22 19:57:20 +0200220 * @sg: SG entry
Jens Axboe82f66fb2007-10-22 17:07:37 +0200221 *
222 * Description:
223 * This calls page_address() on the page in this sg entry, and adds the
224 * sg offset. The caller must know that the sg page has a valid virtual
225 * mapping.
226 *
227 **/
228static inline void *sg_virt(struct scatterlist *sg)
229{
230 return page_address(sg_page(sg)) + sg->offset;
231}
232
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233#endif /* _LINUX_SCATTERLIST_H */