Rev 6082 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 6082 | Rev 6293 | ||
---|---|---|---|
Line 347... | Line 347... | ||
347 | 347 | ||
348 | return ret; |
348 | return ret; |
349 | } |
349 | } |
Line -... | Line 350... | ||
- | 350 | EXPORT_SYMBOL(sg_alloc_table); |
|
- | 351 | ||
- | 352 | /** |
|
- | 353 | * sg_alloc_table_from_pages - Allocate and initialize an sg table from |
|
- | 354 | * an array of pages |
|
- | 355 | * @sgt: The sg table header to use |
|
- | 356 | * @pages: Pointer to an array of page pointers |
|
- | 357 | * @n_pages: Number of pages in the pages array |
|
- | 358 | * @offset: Offset from start of the first page to the start of a buffer |
|
- | 359 | * @size: Number of valid bytes in the buffer (after offset) |
|
- | 360 | * @gfp_mask: GFP allocation mask |
|
- | 361 | * |
|
- | 362 | * Description: |
|
- | 363 | * Allocate and initialize an sg table from a list of pages. Contiguous |
|
- | 364 | * ranges of the pages are squashed into a single scatterlist node. A user |
|
- | 365 | * may provide an offset at a start and a size of valid data in a buffer |
|
- | 366 | * specified by the page array. The returned sg table is released by |
|
- | 367 | * sg_free_table. |
|
- | 368 | * |
|
- | 369 | * Returns: |
|
- | 370 | * 0 on success, negative error on failure |
|
- | 371 | */ |
|
- | 372 | int sg_alloc_table_from_pages(struct sg_table *sgt, |
|
- | 373 | struct page **pages, unsigned int n_pages, |
|
- | 374 | unsigned long offset, unsigned long size, |
|
- | 375 | gfp_t gfp_mask) |
|
- | 376 | { |
|
- | 377 | unsigned int chunks; |
|
- | 378 | unsigned int i; |
|
- | 379 | unsigned int cur_page; |
|
- | 380 | int ret; |
|
- | 381 | struct scatterlist *s; |
|
- | 382 | ||
- | 383 | /* compute number of contiguous chunks */ |
|
- | 384 | chunks = 1; |
|
- | 385 | for (i = 1; i < n_pages; ++i) |
|
- | 386 | if (page_to_pfn(pages[i]) != page_to_pfn(pages[i - 1]) + 1) |
|
- | 387 | ++chunks; |
|
- | 388 | ||
- | 389 | ret = sg_alloc_table(sgt, chunks, gfp_mask); |
|
Line -... | Line 390... | ||
- | 390 | if (unlikely(ret)) |
|
- | 391 | return ret; |
|
- | 392 | ||
- | 393 | /* merging chunks and putting them into the scatterlist */ |
|
- | 394 | cur_page = 0; |
|
Line -... | Line 395... | ||
- | 395 | for_each_sg(sgt->sgl, s, sgt->orig_nents, i) { |
|
- | 396 | unsigned long chunk_size; |
|
- | 397 | unsigned int j; |
|
- | 398 | ||
- | 399 | /* look for the end of the current chunk */ |
|
- | 400 | for (j = cur_page + 1; j < n_pages; ++j) |
|
- | 401 | if (page_to_pfn(pages[j]) != |
|
- | 402 | page_to_pfn(pages[j - 1]) + 1) |
|
- | 403 | break; |
|
- | 404 | ||
- | 405 | chunk_size = ((j - cur_page) << PAGE_SHIFT) - offset; |
|
- | 406 | sg_set_page(s, pages[cur_page], min(size, chunk_size), offset); |
|
- | 407 | size -= chunk_size; |
|
- | 408 | offset = 0; |
|
- | 409 | cur_page = j; |
|
- | 410 | } |
|
Line 350... | Line 411... | ||
350 | EXPORT_SYMBOL(sg_alloc_table); |
411 | |
351 | 412 | return 0; |
|
352 | 413 | } |
|
353 | 414 | EXPORT_SYMBOL(sg_alloc_table_from_pages); |