summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2012-12-05 23:53:10 +0400
committerDave Airlie <airlied@redhat.com>2012-12-05 23:53:10 +0400
commit00f09afd1740c3b2a1434bf48a124b316aab19f2 (patch)
tree8e7d0c97f1ebecf326f19de32770f868c2994522 /arch
parent7136470d4b37b46565b29b8b9425a8361421483b (diff)
parenta144c2e9f17b738ac47716f1fb033cbfcfcde934 (diff)
downloadlinux-00f09afd1740c3b2a1434bf48a124b316aab19f2.tar.xz
Merge branch 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-next
This patch set adds iommu support, userptr feature to g2d, minor fixups and code cleanups. And the iommu feature has dependency of the below patches related to dma mapping framework. This patch is used to allocate fully physically contiguous memory region. - add sending AVI and AVI info frames. . this adds some codes for composing AVI and AUI info frames and send them every VSYNC for HDMI Certification. - bug fix to previous pull request. - add some code cleanup * 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos: (32 commits) drm/exynos: sending AVI and AUI info frames drm/exynos: Use devm_clk_get in exynos_drm_fimd.c drm/exynos: Use devm_* APIs in exynos_hdmi.c drm/exynos: Use devm_clk_get in exynos_mixer.c drm/exynos: Fix potential NULL pointer dereference drm/exynos: Use devm_clk_get in exynos_drm_g2d.c drm/exynos: use sgt instead of pages for framebuffer address drm: exynos: fix for loosing display mode header during mode adjustment drm/exynos: fix memory leak to EDID block drm/exynos: remove 'pages' and 'page_size' elements in exynos gem buffer drm/exynos: add exynos drm specific fb_mmap function drm/exynos: make sure that overlay data are updated drm/exynos: add vm_ops to specific gem mmaper drm/exynos: add userptr feature for g2d module drm/exynos: remove unnecessary sg_alloc_table call drm: exynos: fix for mapping of dma buffers drm/exynos: remove EXYNOS_BO_NONCONTIG type checking. drm/exynos: add iommu support for g2d drm/exynos: add iommu support for hdmi driver drm/exynos: add iommu support to fimd driver ...
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mm/dma-mapping.c41
1 files changed, 33 insertions, 8 deletions
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 58bc3e4d3bd0..f076f209c7a4 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1036,7 +1036,8 @@ static inline void __free_iova(struct dma_iommu_mapping *mapping,
spin_unlock_irqrestore(&mapping->lock, flags);
}
-static struct page **__iommu_alloc_buffer(struct device *dev, size_t size, gfp_t gfp)
+static struct page **__iommu_alloc_buffer(struct device *dev, size_t size,
+ gfp_t gfp, struct dma_attrs *attrs)
{
struct page **pages;
int count = size >> PAGE_SHIFT;
@@ -1050,6 +1051,23 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size, gfp_t
if (!pages)
return NULL;
+ if (dma_get_attr(DMA_ATTR_FORCE_CONTIGUOUS, attrs))
+ {
+ unsigned long order = get_order(size);
+ struct page *page;
+
+ page = dma_alloc_from_contiguous(dev, count, order);
+ if (!page)
+ goto error;
+
+ __dma_clear_buffer(page, size);
+
+ for (i = 0; i < count; i++)
+ pages[i] = page + i;
+
+ return pages;
+ }
+
while (count) {
int j, order = __fls(count);
@@ -1083,14 +1101,21 @@ error:
return NULL;
}
-static int __iommu_free_buffer(struct device *dev, struct page **pages, size_t size)
+static int __iommu_free_buffer(struct device *dev, struct page **pages,
+ size_t size, struct dma_attrs *attrs)
{
int count = size >> PAGE_SHIFT;
int array_size = count * sizeof(struct page *);
int i;
- for (i = 0; i < count; i++)
- if (pages[i])
- __free_pages(pages[i], 0);
+
+ if (dma_get_attr(DMA_ATTR_FORCE_CONTIGUOUS, attrs)) {
+ dma_release_from_contiguous(dev, pages[0], count);
+ } else {
+ for (i = 0; i < count; i++)
+ if (pages[i])
+ __free_pages(pages[i], 0);
+ }
+
if (array_size <= PAGE_SIZE)
kfree(pages);
else
@@ -1252,7 +1277,7 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
if (gfp & GFP_ATOMIC)
return __iommu_alloc_atomic(dev, size, handle);
- pages = __iommu_alloc_buffer(dev, size, gfp);
+ pages = __iommu_alloc_buffer(dev, size, gfp, attrs);
if (!pages)
return NULL;
@@ -1273,7 +1298,7 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
err_mapping:
__iommu_remove_mapping(dev, *handle, size);
err_buffer:
- __iommu_free_buffer(dev, pages, size);
+ __iommu_free_buffer(dev, pages, size, attrs);
return NULL;
}
@@ -1329,7 +1354,7 @@ void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
}
__iommu_remove_mapping(dev, handle, size);
- __iommu_free_buffer(dev, pages, size);
+ __iommu_free_buffer(dev, pages, size, attrs);
}
static int arm_iommu_get_sgtable(struct device *dev, struct sg_table *sgt,