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