1
2
3
4
5
6
7
8
9#include <linux/module.h>
10#include <linux/slab.h>
11#include <linux/scatterlist.h>
12#include <linux/highmem.h>
13
14
15
16
17
18
19
20
21
22
23
24struct scatterlist *sg_next(struct scatterlist *sg)
25{
26#ifdef CONFIG_DEBUG_SG
27 BUG_ON(sg->sg_magic != SG_MAGIC);
28#endif
29 if (sg_is_last(sg))
30 return NULL;
31
32 sg++;
33 if (unlikely(sg_is_chain(sg)))
34 sg = sg_chain_ptr(sg);
35
36 return sg;
37}
38EXPORT_SYMBOL(sg_next);
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54struct scatterlist *sg_last(struct scatterlist *sgl, unsigned int nents)
55{
56#ifndef ARCH_HAS_SG_CHAIN
57 struct scatterlist *ret = &sgl[nents - 1];
58#else
59 struct scatterlist *sg, *ret = NULL;
60 unsigned int i;
61
62 for_each_sg(sgl, sg, nents, i)
63 ret = sg;
64
65#endif
66#ifdef CONFIG_DEBUG_SG
67 BUG_ON(sgl[0].sg_magic != SG_MAGIC);
68 BUG_ON(!sg_is_last(ret));
69#endif
70 return ret;
71}
72EXPORT_SYMBOL(sg_last);
73
74
75
76
77
78
79
80
81
82
83
84void sg_init_table(struct scatterlist *sgl, unsigned int nents)
85{
86 memset(sgl, 0, sizeof(*sgl) * nents);
87#ifdef CONFIG_DEBUG_SG
88 {
89 unsigned int i;
90 for (i = 0; i < nents; i++)
91 sgl[i].sg_magic = SG_MAGIC;
92 }
93#endif
94 sg_mark_end(&sgl[nents - 1]);
95}
96EXPORT_SYMBOL(sg_init_table);
97
98
99
100
101
102
103
104
105void sg_init_one(struct scatterlist *sg, const void *buf, unsigned int buflen)
106{
107 sg_init_table(sg, 1);
108 sg_set_buf(sg, buf, buflen);
109}
110EXPORT_SYMBOL(sg_init_one);
111
112
113
114
115
116static struct scatterlist *sg_kmalloc(unsigned int nents, gfp_t gfp_mask)
117{
118 if (nents == SG_MAX_SINGLE_ALLOC)
119 return (struct scatterlist *) __get_free_page(gfp_mask);
120 else
121 return kmalloc(nents * sizeof(struct scatterlist), gfp_mask);
122}
123
124static void sg_kfree(struct scatterlist *sg, unsigned int nents)
125{
126 if (nents == SG_MAX_SINGLE_ALLOC)
127 free_page((unsigned long) sg);
128 else
129 kfree(sg);
130}
131
132
133
134
135
136
137
138
139
140
141
142
143
144void __sg_free_table(struct sg_table *table, unsigned int max_ents,
145 sg_free_fn *free_fn)
146{
147 struct scatterlist *sgl, *next;
148
149 if (unlikely(!table->sgl))
150 return;
151
152 sgl = table->sgl;
153 while (table->orig_nents) {
154 unsigned int alloc_size = table->orig_nents;
155 unsigned int sg_size;
156
157
158
159
160
161
162
163 if (alloc_size > max_ents) {
164 next = sg_chain_ptr(&sgl[max_ents - 1]);
165 alloc_size = max_ents;
166 sg_size = alloc_size - 1;
167 } else {
168 sg_size = alloc_size;
169 next = NULL;
170 }
171
172 table->orig_nents -= sg_size;
173 free_fn(sgl, alloc_size);
174 sgl = next;
175 }
176
177 table->sgl = NULL;
178}
179EXPORT_SYMBOL(__sg_free_table);
180
181
182
183
184
185
186void sg_free_table(struct sg_table *table)
187{
188 __sg_free_table(table, SG_MAX_SINGLE_ALLOC, sg_kfree);
189}
190EXPORT_SYMBOL(sg_free_table);
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211int __sg_alloc_table(struct sg_table *table, unsigned int nents,
212 unsigned int max_ents, gfp_t gfp_mask,
213 sg_alloc_fn *alloc_fn)
214{
215 struct scatterlist *sg, *prv;
216 unsigned int left;
217
218#ifndef ARCH_HAS_SG_CHAIN
219 BUG_ON(nents > max_ents);
220#endif
221
222 memset(table, 0, sizeof(*table));
223
224 left = nents;
225 prv = NULL;
226 do {
227 unsigned int sg_size, alloc_size = left;
228
229 if (alloc_size > max_ents) {
230 alloc_size = max_ents;
231 sg_size = alloc_size - 1;
232 } else
233 sg_size = alloc_size;
234
235 left -= sg_size;
236
237 sg = alloc_fn(alloc_size, gfp_mask);
238 if (unlikely(!sg))
239 return -ENOMEM;
240
241 sg_init_table(sg, alloc_size);
242 table->nents = table->orig_nents += sg_size;
243
244
245
246
247
248 if (prv)
249 sg_chain(prv, max_ents, sg);
250 else
251 table->sgl = sg;
252
253
254
255
256 if (!left)
257 sg_mark_end(&sg[sg_size - 1]);
258
259
260
261
262
263
264
265 gfp_mask &= ~__GFP_WAIT;
266 gfp_mask |= __GFP_HIGH;
267 prv = sg;
268 } while (left);
269
270 return 0;
271}
272EXPORT_SYMBOL(__sg_alloc_table);
273
274
275
276
277
278
279
280
281
282
283
284
285int sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_mask)
286{
287 int ret;
288
289 ret = __sg_alloc_table(table, nents, SG_MAX_SINGLE_ALLOC,
290 gfp_mask, sg_kmalloc);
291 if (unlikely(ret))
292 __sg_free_table(table, SG_MAX_SINGLE_ALLOC, sg_kfree);
293
294 return ret;
295}
296EXPORT_SYMBOL(sg_alloc_table);
297
298
299
300
301
302
303
304
305
306
307
308
309
310void sg_miter_start(struct sg_mapping_iter *miter, struct scatterlist *sgl,
311 unsigned int nents, unsigned int flags)
312{
313 memset(miter, 0, sizeof(struct sg_mapping_iter));
314
315 miter->__sg = sgl;
316 miter->__nents = nents;
317 miter->__offset = 0;
318 WARN_ON(!(flags & (SG_MITER_TO_SG | SG_MITER_FROM_SG)));
319 miter->__flags = flags;
320}
321EXPORT_SYMBOL(sg_miter_start);
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341bool sg_miter_next(struct sg_mapping_iter *miter)
342{
343 unsigned int off, len;
344
345
346 if (!miter->__nents)
347 return false;
348
349 sg_miter_stop(miter);
350
351
352 while (miter->__offset == miter->__sg->length) {
353 if (--miter->__nents) {
354 miter->__sg = sg_next(miter->__sg);
355 miter->__offset = 0;
356 } else
357 return false;
358 }
359
360
361 off = miter->__sg->offset + miter->__offset;
362 len = miter->__sg->length - miter->__offset;
363
364 miter->page = nth_page(sg_page(miter->__sg), off >> PAGE_SHIFT);
365 off &= ~PAGE_MASK;
366 miter->length = min_t(unsigned int, len, PAGE_SIZE - off);
367 miter->consumed = miter->length;
368
369 if (miter->__flags & SG_MITER_ATOMIC)
370 miter->addr = kmap_atomic(miter->page, KM_BIO_SRC_IRQ) + off;
371 else
372 miter->addr = kmap(miter->page) + off;
373
374 return true;
375}
376EXPORT_SYMBOL(sg_miter_next);
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391void sg_miter_stop(struct sg_mapping_iter *miter)
392{
393 WARN_ON(miter->consumed > miter->length);
394
395
396 if (miter->addr) {
397 miter->__offset += miter->consumed;
398
399 if (miter->__flags & SG_MITER_TO_SG)
400 flush_kernel_dcache_page(miter->page);
401
402 if (miter->__flags & SG_MITER_ATOMIC) {
403 WARN_ON(!irqs_disabled());
404 kunmap_atomic(miter->addr, KM_BIO_SRC_IRQ);
405 } else
406 kunmap(miter->page);
407
408 miter->page = NULL;
409 miter->addr = NULL;
410 miter->length = 0;
411 miter->consumed = 0;
412 }
413}
414EXPORT_SYMBOL(sg_miter_stop);
415
416
417
418
419
420
421
422
423
424
425
426
427
428static size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents,
429 void *buf, size_t buflen, int to_buffer)
430{
431 unsigned int offset = 0;
432 struct sg_mapping_iter miter;
433 unsigned long flags;
434 unsigned int sg_flags = SG_MITER_ATOMIC;
435
436 if (to_buffer)
437 sg_flags |= SG_MITER_FROM_SG;
438 else
439 sg_flags |= SG_MITER_TO_SG;
440
441 sg_miter_start(&miter, sgl, nents, sg_flags);
442
443 local_irq_save(flags);
444
445 while (sg_miter_next(&miter) && offset < buflen) {
446 unsigned int len;
447
448 len = min(miter.length, buflen - offset);
449
450 if (to_buffer)
451 memcpy(buf + offset, miter.addr, len);
452 else
453 memcpy(miter.addr, buf + offset, len);
454
455 offset += len;
456 }
457
458 sg_miter_stop(&miter);
459
460 local_irq_restore(flags);
461 return offset;
462}
463
464
465
466
467
468
469
470
471
472
473
474size_t sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents,
475 void *buf, size_t buflen)
476{
477 return sg_copy_buffer(sgl, nents, buf, buflen, 0);
478}
479EXPORT_SYMBOL(sg_copy_from_buffer);
480
481
482
483
484
485
486
487
488
489
490
491size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents,
492 void *buf, size_t buflen)
493{
494 return sg_copy_buffer(sgl, nents, buf, buflen, 1);
495}
496EXPORT_SYMBOL(sg_copy_to_buffer);
497