Skip to content

Commit

Permalink
drm: exynos: fix for mapping of dma buffers
Browse files Browse the repository at this point in the history
This patch fixes the problem of mapping contigous and non contigous dma buffers.

Currently page struct is calculated from the buf->dma_addr which is not the
physical address. It is replaced by buf->pages which points to the page struct
of the first page of contigous memory chunk. This gives the correct page frame
number for mapping.

Non-contigous dma buffers are described using SG table and SG lists. Each
valid SG List is pointing to a single page or group of pages which are
physically contigous. Current implementation just maps the first page of each
SG List and leave the other pages unmapped, leading to a crash. Given solution
finds the page struct for the faulting page through parsing SG table and map it.

Signed-off-by: Rahul Sharma <rahul.sharma@samsung.com>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
  • Loading branch information
Rahul Sharma authored and Inki Dae committed Dec 4, 2012
1 parent ea6d66c commit 4ddc404
Showing 1 changed file with 25 additions and 3 deletions.
28 changes: 25 additions & 3 deletions drivers/gpu/drm/exynos/exynos_drm_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,37 @@ static int exynos_drm_gem_map_buf(struct drm_gem_object *obj,
{
struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
struct exynos_drm_gem_buf *buf = exynos_gem_obj->buffer;
struct scatterlist *sgl;
unsigned long pfn;
int i;

if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) {
if (!buf->sgt)
return -EINTR;

sgl = buf->sgt->sgl;
for_each_sg(buf->sgt->sgl, sgl, buf->sgt->nents, i) {
if (!sgl) {
DRM_ERROR("invalid SG table\n");
return -EINTR;
}
if (page_offset < (sgl->length >> PAGE_SHIFT))
break;
page_offset -= (sgl->length >> PAGE_SHIFT);
}

if (i >= buf->sgt->nents) {
DRM_ERROR("invalid page offset\n");
return -EINVAL;
}

pfn = __phys_to_pfn(sg_phys(sgl)) + page_offset;
} else {
if (!buf->pages)
return -EINTR;

pfn = page_to_pfn(buf->pages[page_offset++]);
} else
pfn = (buf->dma_addr >> PAGE_SHIFT) + page_offset;
pfn = page_to_pfn(buf->pages[0]) + page_offset;
}

return vm_insert_mixed(vma, f_vaddr, pfn);
}
Expand Down

0 comments on commit 4ddc404

Please sign in to comment.