Skip to content

Commit

Permalink
drm/exynos: consider buffer allocation without iommu
Browse files Browse the repository at this point in the history
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: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
  • Loading branch information
Inki Dae committed Jan 4, 2013
1 parent d81aecb commit 694be45
Showing 1 changed file with 48 additions and 7 deletions.
55 changes: 48 additions & 7 deletions drivers/gpu/drm/exynos/exynos_drm_buf.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "exynos_drm_drv.h"
#include "exynos_drm_gem.h"
#include "exynos_drm_buf.h"
#include "exynos_drm_iommu.h"

static int lowlevel_buffer_allocate(struct drm_device *dev,
unsigned int flags, struct exynos_drm_gem_buf *buf)
Expand Down Expand Up @@ -52,14 +53,45 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
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;
nr_pages = buf->size >> PAGE_SHIFT;

if (!is_drm_iommu_supported(dev)) {
dma_addr_t start_addr;
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);
if (!buf->sgt) {
DRM_ERROR("failed to get sg table.\n");
Expand All @@ -78,6 +110,9 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
(dma_addr_t)buf->dma_addr, &buf->dma_attrs);
buf->dma_addr = (dma_addr_t)NULL;

if (!is_drm_iommu_supported(dev))
kfree(buf->pages);

return ret;
}

Expand All @@ -100,8 +135,14 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev,
kfree(buf->sgt);
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);
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;
}

Expand Down

0 comments on commit 694be45

Please sign in to comment.