]> git.karo-electronics.de Git - mv-sheeva.git/blob - include/linux/scatterlist.h
Merge branch 'linus' of master.kernel.org:/pub/scm/linux/kernel/git/perex/alsa
[mv-sheeva.git] / 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
8 static inline void sg_set_buf(struct scatterlist *sg, const void *buf,
9                               unsigned int buflen)
10 {
11         sg->page = virt_to_page(buf);
12         sg->offset = offset_in_page(buf);
13         sg->length = buflen;
14 }
15
16 static inline void sg_init_one(struct scatterlist *sg, const void *buf,
17                                unsigned int buflen)
18 {
19         memset(sg, 0, sizeof(*sg));
20         sg_set_buf(sg, buf, buflen);
21 }
22
23 /*
24  * We overload the LSB of the page pointer to indicate whether it's
25  * a valid sg entry, or whether it points to the start of a new scatterlist.
26  * Those low bits are there for everyone! (thanks mason :-)
27  */
28 #define sg_is_chain(sg)         ((unsigned long) (sg)->page & 0x01)
29 #define sg_chain_ptr(sg)        \
30         ((struct scatterlist *) ((unsigned long) (sg)->page & ~0x01))
31
32 /**
33  * sg_next - return the next scatterlist entry in a list
34  * @sg:         The current sg entry
35  *
36  * Usually the next entry will be @sg@ + 1, but if this sg element is part
37  * of a chained scatterlist, it could jump to the start of a new
38  * scatterlist array.
39  *
40  * Note that the caller must ensure that there are further entries after
41  * the current entry, this function will NOT return NULL for an end-of-list.
42  *
43  */
44 static inline struct scatterlist *sg_next(struct scatterlist *sg)
45 {
46         sg++;
47
48         if (unlikely(sg_is_chain(sg)))
49                 sg = sg_chain_ptr(sg);
50
51         return sg;
52 }
53
54 /*
55  * Loop over each sg element, following the pointer to a new list if necessary
56  */
57 #define for_each_sg(sglist, sg, nr, __i)        \
58         for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg))
59
60 /**
61  * sg_last - return the last scatterlist entry in a list
62  * @sgl:        First entry in the scatterlist
63  * @nents:      Number of entries in the scatterlist
64  *
65  * Should only be used casually, it (currently) scan the entire list
66  * to get the last entry.
67  *
68  * Note that the @sgl@ pointer passed in need not be the first one,
69  * the important bit is that @nents@ denotes the number of entries that
70  * exist from @sgl@.
71  *
72  */
73 static inline struct scatterlist *sg_last(struct scatterlist *sgl,
74                                           unsigned int nents)
75 {
76 #ifndef ARCH_HAS_SG_CHAIN
77         struct scatterlist *ret = &sgl[nents - 1];
78 #else
79         struct scatterlist *sg, *ret = NULL;
80         int i;
81
82         for_each_sg(sgl, sg, nents, i)
83                 ret = sg;
84
85 #endif
86         return ret;
87 }
88
89 /**
90  * sg_chain - Chain two sglists together
91  * @prv:        First scatterlist
92  * @prv_nents:  Number of entries in prv
93  * @sgl:        Second scatterlist
94  *
95  * Links @prv@ and @sgl@ together, to form a longer scatterlist.
96  *
97  */
98 static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents,
99                             struct scatterlist *sgl)
100 {
101 #ifndef ARCH_HAS_SG_CHAIN
102         BUG();
103 #endif
104         prv[prv_nents - 1].page = (struct page *) ((unsigned long) sgl | 0x01);
105 }
106
107 #endif /* _LINUX_SCATTERLIST_H */