Change table chaining layout
[safe/jmp/linux-2.6] / include / linux / scatterlist.h
1 #ifndef _LINUX_SCATTERLIST_H
2 #define _LINUX_SCATTERLIST_H
3
4 #include <asm/scatterlist.h>
5 #include <linux/mm.h>
6 #include <linux/string.h>
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  */
25
26 /**
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  **/
38 static inline void sg_set_page(struct scatterlist *sg, struct page *page)
39 {
40         unsigned long page_link = sg->page_link & 0x3;
41
42         sg->page_link = page_link | (unsigned long) page;
43 }
44
45 #define sg_page(sg)     ((struct page *) ((sg)->page_link & ~0x3))
46
47 /**
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  **/
54 static inline void sg_set_buf(struct scatterlist *sg, const void *buf,
55                               unsigned int buflen)
56 {
57         sg_set_page(sg, virt_to_page(buf));
58         sg->offset = offset_in_page(buf);
59         sg->length = buflen;
60 }
61
62 /*
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  */
67 #define sg_is_chain(sg)         ((sg)->page_link & 0x01)
68 #define sg_is_last(sg)          ((sg)->page_link & 0x02)
69 #define sg_chain_ptr(sg)        \
70         ((struct scatterlist *) ((sg)->page_link & ~0x03))
71
72 /**
73  * sg_next - return the next scatterlist entry in a list
74  * @sg:         The current sg entry
75  *
76  * 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.
80  *
81  **/
82 static inline struct scatterlist *sg_next(struct scatterlist *sg)
83 {
84         if (sg_is_last(sg))
85                 return NULL;
86
87         sg++;
88         if (unlikely(sg_is_chain(sg)))
89                 sg = sg_chain_ptr(sg);
90
91         return sg;
92 }
93
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
100 /**
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  *
105  * Description:
106  *   Should only be used casually, it (currently) scan the entire list
107  *   to get the last entry.
108  *
109  *   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@.
112  *
113  **/
114 static 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  *
136  * Description:
137  *   Links @prv@ and @sgl@ together, to form a longer scatterlist.
138  *
139  **/
140 static 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
146         prv[prv_nents - 1].page_link = (unsigned long) sgl | 0x01;
147 }
148
149 /**
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  **/
158 static inline void sg_mark_end(struct scatterlist *sgl, unsigned int nents)
159 {
160         sgl[nents - 1].page_link = 0x02;
161 }
162
163 static inline void __sg_mark_end(struct scatterlist *sg)
164 {
165         sg->page_link |= 0x02;
166 }
167
168 /**
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  **/
179 static 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  **/
197 static 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  **/
213 static 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
220  * @sg:      SG entry
221  *
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  **/
228 static inline void *sg_virt(struct scatterlist *sg)
229 {
230         return page_address(sg_page(sg)) + sg->offset;
231 }
232
233 #endif /* _LINUX_SCATTERLIST_H */