349,9 → 349,70 |
} |
EXPORT_SYMBOL(sg_alloc_table); |
|
/** |
* sg_alloc_table_from_pages - Allocate and initialize an sg table from |
* an array of pages |
* @sgt: The sg table header to use |
* @pages: Pointer to an array of page pointers |
* @n_pages: Number of pages in the pages array |
* @offset: Offset from start of the first page to the start of a buffer |
* @size: Number of valid bytes in the buffer (after offset) |
* @gfp_mask: GFP allocation mask |
* |
* Description: |
* Allocate and initialize an sg table from a list of pages. Contiguous |
* ranges of the pages are squashed into a single scatterlist node. A user |
* may provide an offset at a start and a size of valid data in a buffer |
* specified by the page array. The returned sg table is released by |
* sg_free_table. |
* |
* Returns: |
* 0 on success, negative error on failure |
*/ |
int sg_alloc_table_from_pages(struct sg_table *sgt, |
struct page **pages, unsigned int n_pages, |
unsigned long offset, unsigned long size, |
gfp_t gfp_mask) |
{ |
unsigned int chunks; |
unsigned int i; |
unsigned int cur_page; |
int ret; |
struct scatterlist *s; |
|
/* compute number of contiguous chunks */ |
chunks = 1; |
for (i = 1; i < n_pages; ++i) |
if (page_to_pfn(pages[i]) != page_to_pfn(pages[i - 1]) + 1) |
++chunks; |
|
ret = sg_alloc_table(sgt, chunks, gfp_mask); |
if (unlikely(ret)) |
return ret; |
|
/* merging chunks and putting them into the scatterlist */ |
cur_page = 0; |
for_each_sg(sgt->sgl, s, sgt->orig_nents, i) { |
unsigned long chunk_size; |
unsigned int j; |
|
/* look for the end of the current chunk */ |
for (j = cur_page + 1; j < n_pages; ++j) |
if (page_to_pfn(pages[j]) != |
page_to_pfn(pages[j - 1]) + 1) |
break; |
|
chunk_size = ((j - cur_page) << PAGE_SHIFT) - offset; |
sg_set_page(s, pages[cur_page], min(size, chunk_size), offset); |
size -= chunk_size; |
offset = 0; |
cur_page = j; |
} |
|
return 0; |
} |
EXPORT_SYMBOL(sg_alloc_table_from_pages); |
|
void __sg_page_iter_start(struct sg_page_iter *piter, |
struct scatterlist *sglist, unsigned int nents, |
unsigned long pgoffset) |