1645795cbb13eb685d78336b7939ad6618134b1c
[sfrench/cifs-2.6.git] / include / linux / scatterlist.h
1 #ifndef _LINUX_SCATTERLIST_H
2 #define _LINUX_SCATTERLIST_H
3
4 #include <asm/scatterlist.h>
5 #include <asm/io.h>
6 #include <linux/mm.h>
7 #include <linux/string.h>
8
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
28 static inline void sg_set_buf(struct scatterlist *sg, const void *buf,
29                               unsigned int buflen)
30 {
31         sg_set_page(sg, virt_to_page(buf));
32         sg->offset = offset_in_page(buf);
33         sg->length = buflen;
34 }
35
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 }
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
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
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
203 #endif /* _LINUX_SCATTERLIST_H */