drm/exynos: gem: retry without FORCE_CONTIGUOUS when IOMMU is available
authorMarek Szyprowski <m.szyprowski@samsung.com>
Thu, 26 Feb 2015 09:30:45 +0000 (10:30 +0100)
committerSeung-Woo Kim <sw0312.kim@samsung.com>
Wed, 14 Dec 2016 04:44:06 +0000 (13:44 +0900)
When IOMMU is available, drivers can operate even on non-contiguous
buffers (with some performance penalty). If allocation with
FORCE_CONTIGUOUS attribute is set, iommu is available and allocation fails,
then retry allocation without this flag set.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
drivers/gpu/drm/exynos/exynos_drm_buf.c

index 24994ba..8f614d1 100644 (file)
@@ -84,6 +84,26 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
                buf->pages = dma_alloc_attrs(dev->dev, buf->size,
                                        &buf->dma_addr, GFP_KERNEL,
                                        &buf->dma_attrs);
+
+               if (!buf->pages && dma_get_attr(DMA_ATTR_FORCE_CONTIGUOUS,
+                                         &buf->dma_attrs)) {
+                       /* retry without DMA_ATTR_FORCE_CONTIGUOUS */
+                       DRM_DEBUG_KMS("failed to allocate physically contiguous buffer.\n");
+
+                       init_dma_attrs(&buf->dma_attrs);
+
+                       if (flags & EXYNOS_BO_WC || !(flags & EXYNOS_BO_CACHABLE))
+                               attr = DMA_ATTR_WRITE_COMBINE;
+                       else
+                               attr = DMA_ATTR_NON_CONSISTENT;
+                       dma_set_attr(attr, &buf->dma_attrs);
+                       dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &buf->dma_attrs);
+
+                       buf->pages = dma_alloc_attrs(dev->dev, buf->size,
+                                               &buf->dma_addr, GFP_KERNEL,
+                                               &buf->dma_attrs);
+               }
+
                if (!buf->pages) {
                        DRM_ERROR("failed to allocate buffer.\n");
                        return -ENOMEM;