diff mbox

[v2,1/2] omap3: iovmm: Work around sg_alloc_table size limitation in IOMMU

Message ID 1306931102-10943-1-git-send-email-laurent.pinchart@ideasonboard.com (mailing list archive)
State Superseded, archived
Delegated to: Tony Lindgren
Headers show

Commit Message

Laurent Pinchart June 1, 2011, 12:25 p.m. UTC
sg_alloc_table can only allocate multi-page scatter-gather list tables
if the architecture supports scatter-gather lists chaining. ARM doesn't
fit in that category.

The IOMMU driver abuses the sg table structure only to hold page
addresses without ever passing the table to the device.

Use __sg_alloc_table instead of sg_alloc_table and allocate all entries
in one go. Otherwise trying to use a large userspace to capture video
will hit a BUG_ON in __sg_alloc_table.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
---
 arch/arm/plat-omap/iovmm.c |   14 ++++++++++++--
 1 files changed, 12 insertions(+), 2 deletions(-)

Comments

Tony Lindgren June 1, 2011, 1:11 p.m. UTC | #1
* Laurent Pinchart <laurent.pinchart@ideasonboard.com> [110601 05:21]:
> sg_alloc_table can only allocate multi-page scatter-gather list tables
> if the architecture supports scatter-gather lists chaining. ARM doesn't
> fit in that category.
> 
> The IOMMU driver abuses the sg table structure only to hold page
> addresses without ever passing the table to the device.
> 
> Use __sg_alloc_table instead of sg_alloc_table and allocate all entries
> in one go. Otherwise trying to use a large userspace to capture video
> will hit a BUG_ON in __sg_alloc_table.

Is the "large userspace" above missing a word like buffer?

Tony
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/arch/arm/plat-omap/iovmm.c b/arch/arm/plat-omap/iovmm.c
index 51ef43e..b82cef4 100644
--- a/arch/arm/plat-omap/iovmm.c
+++ b/arch/arm/plat-omap/iovmm.c
@@ -121,6 +121,16 @@  static unsigned sgtable_nents(size_t bytes, u32 da, u32 pa)
 	return nr_entries;
 }
 
+static struct scatterlist *sg_alloc(unsigned int nents, gfp_t gfp_mask)
+{
+	return kmalloc(nents * sizeof(struct scatterlist), gfp_mask);
+}
+
+static void sg_free(struct scatterlist *sg, unsigned int nents)
+{
+	kfree(sg);
+}
+
 /* allocate and initialize sg_table header(a kind of 'superblock') */
 static struct sg_table *sgtable_alloc(const size_t bytes, u32 flags,
 							u32 da, u32 pa)
@@ -146,7 +156,7 @@  static struct sg_table *sgtable_alloc(const size_t bytes, u32 flags,
 	if (!sgt)
 		return ERR_PTR(-ENOMEM);
 
-	err = sg_alloc_table(sgt, nr_entries, GFP_KERNEL);
+	err = __sg_alloc_table(sgt, nr_entries, -1, GFP_KERNEL, sg_alloc);
 	if (err) {
 		kfree(sgt);
 		return ERR_PTR(err);
@@ -163,7 +173,7 @@  static void sgtable_free(struct sg_table *sgt)
 	if (!sgt)
 		return;
 
-	sg_free_table(sgt);
+	__sg_free_table(sgt, -1, sg_free);
 	kfree(sgt);
 
 	pr_debug("%s: sgt:%p\n", __func__, sgt);