diff options
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_buf.c')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_buf.c | 88 |
1 files changed, 32 insertions, 56 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_buf.c b/drivers/gpu/drm/exynos/exynos_drm_buf.c index 118c117b3226..48c589661cbe 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_buf.c +++ b/drivers/gpu/drm/exynos/exynos_drm_buf.c @@ -33,71 +33,58 @@ static int lowlevel_buffer_allocate(struct drm_device *dev, unsigned int flags, struct exynos_drm_gem_buf *buf) { - dma_addr_t start_addr; + int ret = 0; unsigned int npages, i = 0; struct scatterlist *sgl; - int ret = 0; + enum dma_attr attr = DMA_ATTR_FORCE_CONTIGUOUS; DRM_DEBUG_KMS("%s\n", __FILE__); - if (IS_NONCONTIG_BUFFER(flags)) { - DRM_DEBUG_KMS("not support allocation type.\n"); - return -EINVAL; - } - if (buf->dma_addr) { DRM_DEBUG_KMS("already allocated.\n"); return 0; } - if (buf->size >= SZ_1M) { - npages = buf->size >> SECTION_SHIFT; - buf->page_size = SECTION_SIZE; - } else if (buf->size >= SZ_64K) { - npages = buf->size >> 16; - buf->page_size = SZ_64K; - } else { - npages = buf->size >> PAGE_SHIFT; - buf->page_size = PAGE_SIZE; + init_dma_attrs(&buf->dma_attrs); + + if (flags & EXYNOS_BO_NONCONTIG) + attr = DMA_ATTR_WRITE_COMBINE; + + dma_set_attr(attr, &buf->dma_attrs); + + 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"); + return -ENOMEM; } buf->sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL); if (!buf->sgt) { DRM_ERROR("failed to allocate sg table.\n"); - return -ENOMEM; + ret = -ENOMEM; + goto err_free_attrs; } - ret = sg_alloc_table(buf->sgt, npages, GFP_KERNEL); + ret = dma_get_sgtable(dev->dev, buf->sgt, buf->kvaddr, buf->dma_addr, + buf->size); if (ret < 0) { - DRM_ERROR("failed to initialize sg table.\n"); - kfree(buf->sgt); - buf->sgt = NULL; - return -ENOMEM; + DRM_ERROR("failed to get sgtable.\n"); + goto err_free_sgt; } - buf->kvaddr = dma_alloc_writecombine(dev->dev, buf->size, - &buf->dma_addr, GFP_KERNEL); - if (!buf->kvaddr) { - DRM_ERROR("failed to allocate buffer.\n"); - ret = -ENOMEM; - goto err1; - } + npages = buf->sgt->nents; buf->pages = kzalloc(sizeof(struct page) * npages, GFP_KERNEL); if (!buf->pages) { DRM_ERROR("failed to allocate pages.\n"); ret = -ENOMEM; - goto err2; + goto err_free_table; } sgl = buf->sgt->sgl; - start_addr = buf->dma_addr; - while (i < npages) { - buf->pages[i] = phys_to_page(start_addr); - sg_set_page(sgl, buf->pages[i], buf->page_size, 0); - sg_dma_address(sgl) = start_addr; - start_addr += buf->page_size; + buf->pages[i] = sg_page(sgl); sgl = sg_next(sgl); i++; } @@ -108,14 +95,16 @@ static int lowlevel_buffer_allocate(struct drm_device *dev, buf->size); return ret; -err2: - dma_free_writecombine(dev->dev, buf->size, buf->kvaddr, - (dma_addr_t)buf->dma_addr); - buf->dma_addr = (dma_addr_t)NULL; -err1: + +err_free_table: sg_free_table(buf->sgt); +err_free_sgt: kfree(buf->sgt); buf->sgt = NULL; +err_free_attrs: + dma_free_attrs(dev->dev, buf->size, buf->kvaddr, + (dma_addr_t)buf->dma_addr, &buf->dma_attrs); + buf->dma_addr = (dma_addr_t)NULL; return ret; } @@ -125,16 +114,6 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev, { DRM_DEBUG_KMS("%s.\n", __FILE__); - /* - * release only physically continuous memory and - * non-continuous memory would be released by exynos - * gem framework. - */ - if (IS_NONCONTIG_BUFFER(flags)) { - DRM_DEBUG_KMS("not support allocation type.\n"); - return; - } - if (!buf->dma_addr) { DRM_DEBUG_KMS("dma_addr is invalid.\n"); return; @@ -150,11 +129,8 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev, kfree(buf->sgt); buf->sgt = NULL; - kfree(buf->pages); - buf->pages = NULL; - - dma_free_writecombine(dev->dev, buf->size, buf->kvaddr, - (dma_addr_t)buf->dma_addr); + dma_free_attrs(dev->dev, buf->size, buf->kvaddr, + (dma_addr_t)buf->dma_addr, &buf->dma_attrs); buf->dma_addr = (dma_addr_t)NULL; } |