Blame view
include/linux/scatterlist.h
7.6 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 |
#ifndef _LINUX_SCATTERLIST_H #define _LINUX_SCATTERLIST_H |
85cdffcde fix sg_phys to us... |
3 |
#include <asm/types.h> |
d32311fed [PATCH] Introduce... |
4 5 6 |
#include <asm/scatterlist.h> #include <linux/mm.h> #include <linux/string.h> |
18dabf473 Change table chai... |
7 |
#include <asm/io.h> |
0db9299f4 SG: Move function... |
8 9 10 11 12 |
struct sg_table { struct scatterlist *sgl; /* the list */ unsigned int nents; /* number of mapped entries */ unsigned int orig_nents; /* original size of list */ }; |
18dabf473 Change table chai... |
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
/* * 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 Linux-2.6.12-rc2 |
29 |
|
d6ec08420 Add CONFIG_DEBUG_... |
30 |
#define SG_MAGIC 0x87654321 |
645a8d946 scatterlist: add ... |
31 32 33 34 35 36 37 38 39 |
/* * 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 :-) */ #define sg_is_chain(sg) ((sg)->page_link & 0x01) #define sg_is_last(sg) ((sg)->page_link & 0x02) #define sg_chain_ptr(sg) \ ((struct scatterlist *) ((sg)->page_link & ~0x03)) |
82f66fbef [SG] Add helpers ... |
40 |
/** |
642f14903 SG: Change sg_set... |
41 42 43 |
* sg_assign_page - Assign a given page to an SG entry * @sg: SG entry * @page: The page |
82f66fbef [SG] Add helpers ... |
44 45 |
* * Description: |
642f14903 SG: Change sg_set... |
46 47 |
* Assign page to sg entry. Also see sg_set_page(), the most commonly used * variant. |
82f66fbef [SG] Add helpers ... |
48 49 |
* **/ |
642f14903 SG: Change sg_set... |
50 |
static inline void sg_assign_page(struct scatterlist *sg, struct page *page) |
82f66fbef [SG] Add helpers ... |
51 |
{ |
18dabf473 Change table chai... |
52 |
unsigned long page_link = sg->page_link & 0x3; |
de26103de [SG] Add debug ch... |
53 54 55 56 57 |
/* * 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 Add CONFIG_DEBUG_... |
58 59 |
#ifdef CONFIG_DEBUG_SG BUG_ON(sg->sg_magic != SG_MAGIC); |
645a8d946 scatterlist: add ... |
60 |
BUG_ON(sg_is_chain(sg)); |
d6ec08420 Add CONFIG_DEBUG_... |
61 |
#endif |
18dabf473 Change table chai... |
62 |
sg->page_link = page_link | (unsigned long) page; |
82f66fbef [SG] Add helpers ... |
63 |
} |
642f14903 SG: Change sg_set... |
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
/** * 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; } |
645a8d946 scatterlist: add ... |
85 86 87 88 89 90 91 92 |
static inline struct page *sg_page(struct scatterlist *sg) { #ifdef CONFIG_DEBUG_SG BUG_ON(sg->sg_magic != SG_MAGIC); BUG_ON(sg_is_chain(sg)); #endif return (struct page *)((sg)->page_link & ~0x3); } |
82f66fbef [SG] Add helpers ... |
93 |
|
18dabf473 Change table chai... |
94 95 96 97 98 99 100 |
/** * sg_set_buf - Set sg entry to point at given data * @sg: SG entry * @buf: Data * @buflen: Data length * **/ |
03fd9cee7 [PATCH] scatterli... |
101 |
static inline void sg_set_buf(struct scatterlist *sg, const void *buf, |
d32311fed [PATCH] Introduce... |
102 103 |
unsigned int buflen) { |
642f14903 SG: Change sg_set... |
104 |
sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf)); |
1da177e4c Linux-2.6.12-rc2 |
105 |
} |
96b418c96 Add sg helpers fo... |
106 107 108 109 110 |
/* * 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 Add chained sg su... |
111 |
/** |
70eb8040d Add chained sg su... |
112 113 114 115 116 |
* sg_chain - Chain two sglists together * @prv: First scatterlist * @prv_nents: Number of entries in prv * @sgl: Second scatterlist * |
18dabf473 Change table chai... |
117 118 |
* Description: * Links @prv@ and @sgl@ together, to form a longer scatterlist. |
70eb8040d Add chained sg su... |
119 |
* |
18dabf473 Change table chai... |
120 |
**/ |
70eb8040d Add chained sg su... |
121 122 123 124 125 126 |
static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents, struct scatterlist *sgl) { #ifndef ARCH_HAS_SG_CHAIN BUG(); #endif |
645a8d946 scatterlist: add ... |
127 128 129 130 |
/* * offset and length are unused for chain entry. Clear them. */ |
b801a1e7d Don't blatt first... |
131 132 |
prv[prv_nents - 1].offset = 0; prv[prv_nents - 1].length = 0; |
645a8d946 scatterlist: add ... |
133 |
|
73fd546aa SG: clear termina... |
134 135 136 137 138 |
/* * Set lowest bit to indicate a link pointer, and make sure to clear * the termination bit if it happens to be set. */ prv[prv_nents - 1].page_link = ((unsigned long) sgl | 0x01) & ~0x02; |
70eb8040d Add chained sg su... |
139 |
} |
82f66fbef [SG] Add helpers ... |
140 141 |
/** * sg_mark_end - Mark the end of the scatterlist |
c46f2334c [SG] Get rid of _... |
142 |
* @sg: SG entryScatterlist |
82f66fbef [SG] Add helpers ... |
143 144 |
* * Description: |
c46f2334c [SG] Get rid of _... |
145 146 |
* Marks the passed in sg entry as the termination point for the sg * table. A call to sg_next() on this entry will return NULL. |
82f66fbef [SG] Add helpers ... |
147 148 |
* **/ |
c46f2334c [SG] Get rid of _... |
149 |
static inline void sg_mark_end(struct scatterlist *sg) |
82f66fbef [SG] Add helpers ... |
150 |
{ |
c46f2334c [SG] Get rid of _... |
151 152 153 154 155 156 |
#ifdef CONFIG_DEBUG_SG BUG_ON(sg->sg_magic != SG_MAGIC); #endif /* * Set termination bit, clear potential chain bit */ |
18dabf473 Change table chai... |
157 |
sg->page_link |= 0x02; |
c46f2334c [SG] Get rid of _... |
158 |
sg->page_link &= ~0x01; |
82f66fbef [SG] Add helpers ... |
159 |
} |
82f66fbef [SG] Add helpers ... |
160 |
/** |
82f66fbef [SG] Add helpers ... |
161 162 163 164 165 166 167 168 169 |
* 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. * **/ |
85cdffcde fix sg_phys to us... |
170 |
static inline dma_addr_t sg_phys(struct scatterlist *sg) |
82f66fbef [SG] Add helpers ... |
171 172 173 174 175 176 |
{ return page_to_phys(sg_page(sg)) + sg->offset; } /** * sg_virt - Return virtual address of an sg entry |
18dabf473 Change table chai... |
177 |
* @sg: SG entry |
82f66fbef [SG] Add helpers ... |
178 179 180 181 182 183 184 185 186 187 188 |
* * 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; } |
0db9299f4 SG: Move function... |
189 190 191 192 193 194 195 |
struct scatterlist *sg_next(struct scatterlist *); struct scatterlist *sg_last(struct scatterlist *s, unsigned int); void sg_init_table(struct scatterlist *, unsigned int); void sg_init_one(struct scatterlist *, const void *, unsigned int); typedef struct scatterlist *(sg_alloc_fn)(unsigned int, gfp_t); typedef void (sg_free_fn)(struct scatterlist *, unsigned int); |
7cedb1f17 SG: work with the... |
196 |
void __sg_free_table(struct sg_table *, unsigned int, sg_free_fn *); |
0db9299f4 SG: Move function... |
197 |
void sg_free_table(struct sg_table *); |
7cedb1f17 SG: work with the... |
198 199 |
int __sg_alloc_table(struct sg_table *, unsigned int, unsigned int, gfp_t, sg_alloc_fn *); |
0db9299f4 SG: Move function... |
200 |
int sg_alloc_table(struct sg_table *, unsigned int, gfp_t); |
b1adaf65b [SCSI] block: add... |
201 202 203 204 |
size_t sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents, void *buf, size_t buflen); size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents, void *buf, size_t buflen); |
0db9299f4 SG: Move function... |
205 206 207 208 209 |
/* * Maximum number of entries that will be allocated in one piece, if * a list larger than this is required then chaining will be utilized. */ #define SG_MAX_SINGLE_ALLOC (PAGE_SIZE / sizeof(struct scatterlist)) |
137d3edb4 sg: reimplement s... |
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
/* * Mapping sg iterator * * Iterates over sg entries mapping page-by-page. On each successful * iteration, @miter->page points to the mapped page and * @miter->length bytes of data can be accessed at @miter->addr. As * long as an interation is enclosed between start and stop, the user * is free to choose control structure and when to stop. * * @miter->consumed is set to @miter->length on each iteration. It * can be adjusted if the user can't consume all the bytes in one go. * Also, a stopped iteration can be resumed by calling next on it. * This is useful when iteration needs to release all resources and * continue later (e.g. at the next interrupt). */ #define SG_MITER_ATOMIC (1 << 0) /* use kmap_atomic */ struct sg_mapping_iter { /* the following three fields can be accessed directly */ struct page *page; /* currently mapped page */ void *addr; /* pointer to the mapped area */ size_t length; /* length of the mapped area */ size_t consumed; /* number of consumed bytes */ /* these are internal states, keep away */ struct scatterlist *__sg; /* current entry */ unsigned int __nents; /* nr of remaining entries */ unsigned int __offset; /* offset within sg */ unsigned int __flags; }; void sg_miter_start(struct sg_mapping_iter *miter, struct scatterlist *sgl, unsigned int nents, unsigned int flags); bool sg_miter_next(struct sg_mapping_iter *miter); void sg_miter_stop(struct sg_mapping_iter *miter); |
1da177e4c Linux-2.6.12-rc2 |
247 |
#endif /* _LINUX_SCATTERLIST_H */ |