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