Blame view

include/linux/scatterlist.h 7.6 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
  #ifndef _LINUX_SCATTERLIST_H
  #define _LINUX_SCATTERLIST_H
85cdffcde   Hugh Dickins   fix sg_phys to us...
3
  #include <asm/types.h>
d32311fed   Herbert Xu   [PATCH] Introduce...
4
5
6
  #include <asm/scatterlist.h>
  #include <linux/mm.h>
  #include <linux/string.h>
18dabf473   Jens Axboe   Change table chai...
7
  #include <asm/io.h>
0db9299f4   Jens Axboe   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   Jens Axboe   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   Linus Torvalds   Linux-2.6.12-rc2
29

d6ec08420   Jens Axboe   Add CONFIG_DEBUG_...
30
  #define SG_MAGIC	0x87654321
645a8d946   Tejun Heo   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   Jens Axboe   [SG] Add helpers ...
40
  /**
642f14903   Jens Axboe   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   Jens Axboe   [SG] Add helpers ...
44
45
   *
   * Description:
642f14903   Jens Axboe   SG: Change sg_set...
46
47
   *   Assign page to sg entry. Also see sg_set_page(), the most commonly used
   *   variant.
82f66fbef   Jens Axboe   [SG] Add helpers ...
48
49
   *
   **/
642f14903   Jens Axboe   SG: Change sg_set...
50
  static inline void sg_assign_page(struct scatterlist *sg, struct page *page)
82f66fbef   Jens Axboe   [SG] Add helpers ...
51
  {
18dabf473   Jens Axboe   Change table chai...
52
  	unsigned long page_link = sg->page_link & 0x3;
de26103de   Jens Axboe   [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   Jens Axboe   Add CONFIG_DEBUG_...
58
59
  #ifdef CONFIG_DEBUG_SG
  	BUG_ON(sg->sg_magic != SG_MAGIC);
645a8d946   Tejun Heo   scatterlist: add ...
60
  	BUG_ON(sg_is_chain(sg));
d6ec08420   Jens Axboe   Add CONFIG_DEBUG_...
61
  #endif
18dabf473   Jens Axboe   Change table chai...
62
  	sg->page_link = page_link | (unsigned long) page;
82f66fbef   Jens Axboe   [SG] Add helpers ...
63
  }
642f14903   Jens Axboe   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   Tejun Heo   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   Jens Axboe   [SG] Add helpers ...
93

18dabf473   Jens Axboe   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   Herbert Xu   [PATCH] scatterli...
101
  static inline void sg_set_buf(struct scatterlist *sg, const void *buf,
d32311fed   Herbert Xu   [PATCH] Introduce...
102
103
  			      unsigned int buflen)
  {
642f14903   Jens Axboe   SG: Change sg_set...
104
  	sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
  }
96b418c96   Jens Axboe   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   Jens Axboe   Add chained sg su...
111
  /**
70eb8040d   Jens Axboe   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   Jens Axboe   Change table chai...
117
118
   * Description:
   *   Links @prv@ and @sgl@ together, to form a longer scatterlist.
70eb8040d   Jens Axboe   Add chained sg su...
119
   *
18dabf473   Jens Axboe   Change table chai...
120
   **/
70eb8040d   Jens Axboe   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   Tejun Heo   scatterlist: add ...
127
128
129
130
  
  	/*
  	 * offset and length are unused for chain entry.  Clear them.
  	 */
b801a1e7d   Rusty Russell   Don't blatt first...
131
132
  	prv[prv_nents - 1].offset = 0;
  	prv[prv_nents - 1].length = 0;
645a8d946   Tejun Heo   scatterlist: add ...
133

73fd546aa   Jens Axboe   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   Jens Axboe   Add chained sg su...
139
  }
82f66fbef   Jens Axboe   [SG] Add helpers ...
140
141
  /**
   * sg_mark_end - Mark the end of the scatterlist
c46f2334c   Jens Axboe   [SG] Get rid of _...
142
   * @sg:		 SG entryScatterlist
82f66fbef   Jens Axboe   [SG] Add helpers ...
143
144
   *
   * Description:
c46f2334c   Jens Axboe   [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   Jens Axboe   [SG] Add helpers ...
147
148
   *
   **/
c46f2334c   Jens Axboe   [SG] Get rid of _...
149
  static inline void sg_mark_end(struct scatterlist *sg)
82f66fbef   Jens Axboe   [SG] Add helpers ...
150
  {
c46f2334c   Jens Axboe   [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   Jens Axboe   Change table chai...
157
  	sg->page_link |= 0x02;
c46f2334c   Jens Axboe   [SG] Get rid of _...
158
  	sg->page_link &= ~0x01;
82f66fbef   Jens Axboe   [SG] Add helpers ...
159
  }
82f66fbef   Jens Axboe   [SG] Add helpers ...
160
  /**
82f66fbef   Jens Axboe   [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   Hugh Dickins   fix sg_phys to us...
170
  static inline dma_addr_t sg_phys(struct scatterlist *sg)
82f66fbef   Jens Axboe   [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   Jens Axboe   Change table chai...
177
   * @sg:      SG entry
82f66fbef   Jens Axboe   [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   Jens Axboe   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   James Bottomley   SG: work with the...
196
  void __sg_free_table(struct sg_table *, unsigned int, sg_free_fn *);
0db9299f4   Jens Axboe   SG: Move function...
197
  void sg_free_table(struct sg_table *);
7cedb1f17   James Bottomley   SG: work with the...
198
199
  int __sg_alloc_table(struct sg_table *, unsigned int, unsigned int, gfp_t,
  		     sg_alloc_fn *);
0db9299f4   Jens Axboe   SG: Move function...
200
  int sg_alloc_table(struct sg_table *, unsigned int, gfp_t);
b1adaf65b   FUJITA Tomonori   [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   Jens Axboe   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   Tejun Heo   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   Linus Torvalds   Linux-2.6.12-rc2
247
  #endif /* _LINUX_SCATTERLIST_H */