[PATCH 1/3] scatterlist: add sg_clone_table function

Prathyush K prathyush.k at samsung.com
Wed Nov 7 02:28:57 PST 2012


This patch adds another constructor for an sg table. An sg table is
created from an existing sg table. The new sg table is allocated and
initialized with same data from the original sg table. The user has to
call 'sg_clone_table' with the required sg table, the existing sg table
and the gfp allocation mask.

This function can be used in the dma-buf framework. If a buffer needs
to be shared across multiple devices using the dma_buf framework, an
sg table needs to be created and mapped to the target device's address
space. This is done in most drivers by creating the sg table from the
pages of the buffer (e.g. calling sg_alloc_table_from_pages function).
In case this needs to be done frequently (e.g. a framebuffer
is repeatedly shared with the GPU, video accelerator, CSC etc), it is
efficient to create an sg table once during buffer allocation and then
create temporary sg tables for dma mapping from the original sg table.

Signed-off-by: Prathyush K <prathyush.k at samsung.com>
---
 include/linux/scatterlist.h |    1 +
 lib/scatterlist.c           |   36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 37 insertions(+), 0 deletions(-)

diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index 4bd6c06..fd12525 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -215,6 +215,7 @@ 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_clone_table(struct sg_table *, struct sg_table *, gfp_t);
 int sg_alloc_table_from_pages(struct sg_table *sgt,
 	struct page **pages, unsigned int n_pages,
 	unsigned long offset, unsigned long size,
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index 3675452..4f106b3 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -329,6 +329,42 @@ int sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_mask)
 }
 EXPORT_SYMBOL(sg_alloc_table);
 
+/*
+ * sg_clone_table - Allocate and initialize an sg table from an existing
+ *			sg table
+ * @sgt_in:	The sg table to clone
+ * @sgt_out:	The output sg table cloned from the original sg table.
+ * @gfp_mask:	GFP allocation mask
+ *
+ * Description:
+ *    Allocate and initialize an sg table from an existing sg table. A user
+ *    would want to create a temporary sg table which is a clone of an
+ *    existing table. This cloned sg table is released by sg_free_table.
+ *
+ * Returns:
+ *    0 on success, negative error on failure
+ */
+int sg_clone_table(struct sg_table *sgt_in, struct sg_table *sgt_out,
+		   gfp_t gfp_mask)
+{
+	struct scatterlist *s, *s_out;
+	unsigned int i;
+	int ret;
+
+	ret = sg_alloc_table(sgt_out, sgt_in->orig_nents, gfp_mask);
+	if (unlikely(ret))
+		return ret;
+
+	s_out = sgt_out->sgl;
+	for_each_sg(sgt_in->sgl, s, sgt_in->orig_nents, i) {
+		sg_set_page(s_out, sg_page(s), s->length, s->offset);
+		s_out = sg_next(s_out);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(sg_clone_table);
+
 /**
  * sg_alloc_table_from_pages - Allocate and initialize an sg table from
  *			       an array of pages
-- 
1.7.0.4



More information about the dri-devel mailing list