scatterlist: add sg_alloc_table_by_pages function
Subsystems (2)
PATCH 1/1 scatterlist: add sg_alloc_table_by_pages function
This patch adds a new constructor for an sg table. The table is constructed from an array of struct pages. All contiguous chunks of the pages are merged into a single sg nodes. A user may provide an offset and a size of a buffer if the buffer is not page-aligned.
The function is dedicated for DMABUF exporters which often performs conversion from an page array to a scatterlist. Moreover the scatterlist should be squashed in order to save memory and to speed-up DMA mapping using dma_map_sg.
The code is based on the patch 'v4l: vb2-dma-contig: add support for scatterlist in userptr mode' and hints from Laurent Pinchart.
--- include/linux/scatterlist.h | 4 +++ lib/scatterlist.c | 63 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 0 deletions(-)
include/linux/scatterlist.h +4 -0
@@ -214,6 +214,10 @@ void sg_free_table(struct sg_table *);int __sg_alloc_table (struct sg_table *,unsigned int ,unsigned int ,gfp_t ,sg_alloc_fn *);int sg_alloc_table (struct sg_table *,unsigned int ,gfp_t ); +int sg_alloc_table_by_pages (struct sg_table *sgt, +struct page **pages,unsigned int n_pages, +unsigned long offset,unsigned long size, +gfp_t gfp_mask);size_t sg_copy_from_buffer (struct scatterlist *sgl,unsigned int nents,void *buf,size_t buflen);
lib/scatterlist.c +63 -0
69 lines not on this page · raw message
Signature · 1 line
1.7.5.4
Hi Tomasz,
Thanks for the patch.
Quoted 5 lines · On Wednesday 18 April 2012 11:44:59 Tomasz Stanislawski wrote:
This patch adds a new constructor for an sg table. The table is constructed from an array of struct pages. All contiguous chunks of the pages are merged into a single sg nodes. A user may provide an offset and a size of a buffer if the buffer is not page-aligned.
Quoted 7 lines
The function is dedicated for DMABUF exporters which often performs conversion from an page array to a scatterlist. Moreover the scatterlist should be squashed in order to save memory and to speed-up DMA mapping using
dma_map_sg.The code is based on the patch 'v4l: vb2-dma-contig: add support for scatterlist in userptr mode' and hints from Laurent Pinchart.
The patch looks good to me. Just a small comment, what do you think about naming the function sg_alloc_table_from_pages instead of sg_table_alloc_by_pages ?
Quoted 40 lines
Signed-off-by Tomasz Stanislawski <[email protected]>Signed-off-by Kyungmin Park <[email protected]>--- include/linux/scatterlist.h | 4 +++ lib/scatterlist.c | 63+++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 0 deletions(-)
include/linux/scatterlist.h +4
-0@@ -214,6 +214,10 @@ void sg_free_table(struct sg_table *);int __sg_alloc_table (struct sg_table *,unsigned int ,unsigned int ,gfp_t ,sg_alloc_fn *);int sg_alloc_table (struct sg_table *,unsigned int ,gfp_t ); +int sg_alloc_table_by_pages (struct sg_table *sgt, +struct page **pages,unsigned int n_pages, +unsigned long offset,unsigned long size, +gfp_t gfp_mask);size_t sg_copy_from_buffer (struct scatterlist *sgl,unsigned int nents,void *buf,size_t buflen);lib/scatterlist.c +1
-0@@ -319,6 +319,69 @@ int sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_mask) EXPORT_SYMBOL(sg_alloc_table);/** +* sg_alloc_table_by_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:
Quoted 8 lines
+ * Allocate and initialize an sg table from a list of pages. Continuous
+ * 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
Maybe you should mention what it returns in case of an error as well.
Quoted 48 lines
+ **/
lib/scatterlist.c +44
-0+int sg_alloc_table_by_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 (pages[i] != 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; + +/* looking for the end of the current chunk */ +for (j = cur_page +1 ; j < n_pages; ++j) +if (pages[j] != 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_by_pages); + +/** * sg_miter_start - start mapping iteration over a sg list * @miter: sg mapping iter to be started * @sgl: sg list to iterate over
Signature · 3 lines
Regards, Laurent Pinchart