]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - include/linux/scatterlist.h
mmc: sg fallout
[mirror_ubuntu-artful-kernel.git] / include / linux / scatterlist.h
CommitLineData
1da177e4
LT
1#ifndef _LINUX_SCATTERLIST_H
2#define _LINUX_SCATTERLIST_H
3
d32311fe
HX
4#include <asm/scatterlist.h>
5#include <linux/mm.h>
6#include <linux/string.h>
18dabf47
JA
7#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 */
1da177e4 25
d6ec0842
JA
26#define SG_MAGIC 0x87654321
27
82f66fbe
JA
28/**
29 * sg_set_page - Set sg entry to point at given page
30 * @sg: SG entry
31 * @page: The page
32 *
33 * Description:
34 * Use this function to set an sg entry pointing at a page, never assign
35 * the page directly. We encode sg table information in the lower bits
36 * of the page pointer. See sg_page() for looking up the page belonging
37 * to an sg entry.
38 *
39 **/
40static inline void sg_set_page(struct scatterlist *sg, struct page *page)
41{
18dabf47
JA
42 unsigned long page_link = sg->page_link & 0x3;
43
de26103d
JA
44 /*
45 * In order for the low bit stealing approach to work, pages
46 * must be aligned at a 32-bit boundary as a minimum.
47 */
48 BUG_ON((unsigned long) page & 0x03);
d6ec0842
JA
49#ifdef CONFIG_DEBUG_SG
50 BUG_ON(sg->sg_magic != SG_MAGIC);
51#endif
18dabf47 52 sg->page_link = page_link | (unsigned long) page;
82f66fbe
JA
53}
54
18dabf47 55#define sg_page(sg) ((struct page *) ((sg)->page_link & ~0x3))
82f66fbe 56
18dabf47
JA
57/**
58 * sg_set_buf - Set sg entry to point at given data
59 * @sg: SG entry
60 * @buf: Data
61 * @buflen: Data length
62 *
63 **/
03fd9cee 64static inline void sg_set_buf(struct scatterlist *sg, const void *buf,
d32311fe
HX
65 unsigned int buflen)
66{
82f66fbe 67 sg_set_page(sg, virt_to_page(buf));
1da177e4
LT
68 sg->offset = offset_in_page(buf);
69 sg->length = buflen;
70}
71
70eb8040
JA
72/*
73 * We overload the LSB of the page pointer to indicate whether it's
74 * a valid sg entry, or whether it points to the start of a new scatterlist.
75 * Those low bits are there for everyone! (thanks mason :-)
76 */
18dabf47
JA
77#define sg_is_chain(sg) ((sg)->page_link & 0x01)
78#define sg_is_last(sg) ((sg)->page_link & 0x02)
70eb8040 79#define sg_chain_ptr(sg) \
18dabf47 80 ((struct scatterlist *) ((sg)->page_link & ~0x03))
70eb8040
JA
81
82/**
83 * sg_next - return the next scatterlist entry in a list
84 * @sg: The current sg entry
85 *
18dabf47
JA
86 * Description:
87 * Usually the next entry will be @sg@ + 1, but if this sg element is part
88 * of a chained scatterlist, it could jump to the start of a new
89 * scatterlist array.
70eb8040 90 *
18dabf47 91 **/
70eb8040
JA
92static inline struct scatterlist *sg_next(struct scatterlist *sg)
93{
d6ec0842
JA
94#ifdef CONFIG_DEBUG_SG
95 BUG_ON(sg->sg_magic != SG_MAGIC);
96#endif
18dabf47
JA
97 if (sg_is_last(sg))
98 return NULL;
70eb8040 99
18dabf47 100 sg++;
70eb8040
JA
101 if (unlikely(sg_is_chain(sg)))
102 sg = sg_chain_ptr(sg);
103
104 return sg;
105}
96b418c9
JA
106
107/*
108 * Loop over each sg element, following the pointer to a new list if necessary
109 */
110#define for_each_sg(sglist, sg, nr, __i) \
111 for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg))
112
70eb8040
JA
113/**
114 * sg_last - return the last scatterlist entry in a list
115 * @sgl: First entry in the scatterlist
116 * @nents: Number of entries in the scatterlist
117 *
18dabf47
JA
118 * Description:
119 * Should only be used casually, it (currently) scan the entire list
120 * to get the last entry.
70eb8040 121 *
18dabf47
JA
122 * Note that the @sgl@ pointer passed in need not be the first one,
123 * the important bit is that @nents@ denotes the number of entries that
124 * exist from @sgl@.
70eb8040 125 *
18dabf47 126 **/
70eb8040
JA
127static inline struct scatterlist *sg_last(struct scatterlist *sgl,
128 unsigned int nents)
129{
130#ifndef ARCH_HAS_SG_CHAIN
131 struct scatterlist *ret = &sgl[nents - 1];
132#else
133 struct scatterlist *sg, *ret = NULL;
134 int i;
135
136 for_each_sg(sgl, sg, nents, i)
137 ret = sg;
138
d6ec0842
JA
139#endif
140#ifdef CONFIG_DEBUG_SG
141 BUG_ON(sgl[0].sg_magic != SG_MAGIC);
142 BUG_ON(!sg_is_last(ret));
70eb8040
JA
143#endif
144 return ret;
145}
146
147/**
148 * sg_chain - Chain two sglists together
149 * @prv: First scatterlist
150 * @prv_nents: Number of entries in prv
151 * @sgl: Second scatterlist
152 *
18dabf47
JA
153 * Description:
154 * Links @prv@ and @sgl@ together, to form a longer scatterlist.
70eb8040 155 *
18dabf47 156 **/
70eb8040
JA
157static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents,
158 struct scatterlist *sgl)
159{
160#ifndef ARCH_HAS_SG_CHAIN
161 BUG();
162#endif
18dabf47 163 prv[prv_nents - 1].page_link = (unsigned long) sgl | 0x01;
70eb8040
JA
164}
165
82f66fbe
JA
166/**
167 * sg_mark_end - Mark the end of the scatterlist
168 * @sgl: Scatterlist
169 * @nents: Number of entries in sgl
170 *
171 * Description:
172 * Marks the last entry as the termination point for sg_next()
173 *
174 **/
175static inline void sg_mark_end(struct scatterlist *sgl, unsigned int nents)
176{
18dabf47 177 sgl[nents - 1].page_link = 0x02;
82f66fbe
JA
178}
179
180static inline void __sg_mark_end(struct scatterlist *sg)
181{
18dabf47 182 sg->page_link |= 0x02;
82f66fbe
JA
183}
184
82f66fbe
JA
185/**
186 * sg_init_one - Initialize a single entry sg list
187 * @sg: SG entry
188 * @buf: Virtual address for IO
189 * @buflen: IO length
190 *
191 * Notes:
192 * This should not be used on a single entry that is part of a larger
193 * table. Use sg_init_table() for that.
194 *
195 **/
196static inline void sg_init_one(struct scatterlist *sg, const void *buf,
197 unsigned int buflen)
198{
199 memset(sg, 0, sizeof(*sg));
d6ec0842
JA
200#ifdef CONFIG_DEBUG_SG
201 sg->sg_magic = SG_MAGIC;
202#endif
82f66fbe
JA
203 sg_mark_end(sg, 1);
204 sg_set_buf(sg, buf, buflen);
205}
206
207/**
208 * sg_init_table - Initialize SG table
209 * @sgl: The SG table
210 * @nents: Number of entries in table
211 *
212 * Notes:
213 * If this is part of a chained sg table, sg_mark_end() should be
214 * used only on the last table part.
215 *
216 **/
217static inline void sg_init_table(struct scatterlist *sgl, unsigned int nents)
218{
219 memset(sgl, 0, sizeof(*sgl) * nents);
220 sg_mark_end(sgl, nents);
d6ec0842
JA
221#ifdef CONFIG_DEBUG_SG
222 {
223 int i;
224 for (i = 0; i < nents; i++)
225 sgl[i].sg_magic = SG_MAGIC;
226 }
227#endif
82f66fbe
JA
228}
229
230/**
231 * sg_phys - Return physical address of an sg entry
232 * @sg: SG entry
233 *
234 * Description:
235 * This calls page_to_phys() on the page in this sg entry, and adds the
236 * sg offset. The caller must know that it is legal to call page_to_phys()
237 * on the sg page.
238 *
239 **/
240static inline unsigned long sg_phys(struct scatterlist *sg)
241{
242 return page_to_phys(sg_page(sg)) + sg->offset;
243}
244
245/**
246 * sg_virt - Return virtual address of an sg entry
18dabf47 247 * @sg: SG entry
82f66fbe
JA
248 *
249 * Description:
250 * This calls page_address() on the page in this sg entry, and adds the
251 * sg offset. The caller must know that the sg page has a valid virtual
252 * mapping.
253 *
254 **/
255static inline void *sg_virt(struct scatterlist *sg)
256{
257 return page_address(sg_page(sg)) + sg->offset;
258}
259
1da177e4 260#endif /* _LINUX_SCATTERLIST_H */