Commit 694be458 authored by Inki Dae's avatar Inki Dae

drm/exynos: consider buffer allocation without iommu

This patch fixes the issue that when buffer allocation is requested
without iommu, the allocation is failed.

Without iommu, dma_alloc_attrs function allocates some memory region
and returns cpu address so this patch makes the cpu address to be set
to buf->kvaddr correctly.

Changelog v2:
- fix buffer free
  . Without iommu, dma_free_attrs function requires kernel space address
    as argument. So it changes the argument, buf->pages to buf->kvaddr.
Signed-off-by: default avatarInki Dae <inki.dae@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
parent d81aecb5
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "exynos_drm_drv.h" #include "exynos_drm_drv.h"
#include "exynos_drm_gem.h" #include "exynos_drm_gem.h"
#include "exynos_drm_buf.h" #include "exynos_drm_buf.h"
#include "exynos_drm_iommu.h"
static int lowlevel_buffer_allocate(struct drm_device *dev, static int lowlevel_buffer_allocate(struct drm_device *dev,
unsigned int flags, struct exynos_drm_gem_buf *buf) unsigned int flags, struct exynos_drm_gem_buf *buf)
...@@ -52,14 +53,45 @@ static int lowlevel_buffer_allocate(struct drm_device *dev, ...@@ -52,14 +53,45 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
dma_set_attr(attr, &buf->dma_attrs); dma_set_attr(attr, &buf->dma_attrs);
dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &buf->dma_attrs); dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &buf->dma_attrs);
buf->pages = dma_alloc_attrs(dev->dev, buf->size, nr_pages = buf->size >> PAGE_SHIFT;
&buf->dma_addr, GFP_KERNEL, &buf->dma_attrs);
if (!buf->pages) { if (!is_drm_iommu_supported(dev)) {
DRM_ERROR("failed to allocate buffer.\n"); dma_addr_t start_addr;
return -ENOMEM; unsigned int i = 0;
buf->pages = kzalloc(sizeof(struct page) * nr_pages,
GFP_KERNEL);
if (!buf->pages) {
DRM_ERROR("failed to allocate pages.\n");
return -ENOMEM;
}
buf->kvaddr = dma_alloc_attrs(dev->dev, buf->size,
&buf->dma_addr, GFP_KERNEL,
&buf->dma_attrs);
if (!buf->kvaddr) {
DRM_ERROR("failed to allocate buffer.\n");
kfree(buf->pages);
return -ENOMEM;
}
start_addr = buf->dma_addr;
while (i < nr_pages) {
buf->pages[i] = phys_to_page(start_addr);
start_addr += PAGE_SIZE;
i++;
}
} else {
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;
}
} }
nr_pages = buf->size >> PAGE_SHIFT;
buf->sgt = drm_prime_pages_to_sg(buf->pages, nr_pages); buf->sgt = drm_prime_pages_to_sg(buf->pages, nr_pages);
if (!buf->sgt) { if (!buf->sgt) {
DRM_ERROR("failed to get sg table.\n"); DRM_ERROR("failed to get sg table.\n");
...@@ -78,6 +110,9 @@ static int lowlevel_buffer_allocate(struct drm_device *dev, ...@@ -78,6 +110,9 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
(dma_addr_t)buf->dma_addr, &buf->dma_attrs); (dma_addr_t)buf->dma_addr, &buf->dma_attrs);
buf->dma_addr = (dma_addr_t)NULL; buf->dma_addr = (dma_addr_t)NULL;
if (!is_drm_iommu_supported(dev))
kfree(buf->pages);
return ret; return ret;
} }
...@@ -100,8 +135,14 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev, ...@@ -100,8 +135,14 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev,
kfree(buf->sgt); kfree(buf->sgt);
buf->sgt = NULL; buf->sgt = NULL;
dma_free_attrs(dev->dev, buf->size, buf->pages, if (!is_drm_iommu_supported(dev)) {
dma_free_attrs(dev->dev, buf->size, buf->kvaddr,
(dma_addr_t)buf->dma_addr, &buf->dma_attrs); (dma_addr_t)buf->dma_addr, &buf->dma_attrs);
kfree(buf->pages);
} else
dma_free_attrs(dev->dev, buf->size, buf->pages,
(dma_addr_t)buf->dma_addr, &buf->dma_attrs);
buf->dma_addr = (dma_addr_t)NULL; buf->dma_addr = (dma_addr_t)NULL;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment