Hi Marek,

On 10/13/2015 07:22 PM, Marek Szyprowski wrote:
> Exynos GEM objects contains an array of pointers to the pages, which the
> allocated buffer consists of. Till now the code used some hacks (like
> relying on DMA-mapping internal structures or using ARM-specific
> dma_to_pfn helper) to build this array. This patch fixes this by adding
> proper call to dma_get_sgtable_attrs() and using the acquired scatter-list
> to construct needed array. This approach is more portable (work also for
> ARM64) and finally fixes the layering violation that was present in this
> code.

I also sent related patches to update codes of Exynos GEM object and i
think this can be applied easily on my patchset or i will be able to
rebase my patchset on your patch.

> 
> Signed-off-by: Marek Szyprowski <m.szyprowski at samsung.com>
> ---
> Patch is based on exynos-drm-next branch.
> ---
>  drivers/gpu/drm/exynos/exynos_drm_gem.c | 60 
> +++++++++++++++++++--------------
>  1 file changed, 35 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c 
> b/drivers/gpu/drm/exynos/exynos_drm_gem.c
> index 29f48756e72f..e998a64a3dd0 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
> @@ -25,6 +25,10 @@ static int exynos_drm_alloc_buf(struct exynos_drm_gem 
> *exynos_gem)
>       struct drm_device *dev = exynos_gem->base.dev;
>       enum dma_attr attr;
>       unsigned int nr_pages;
> +     struct sg_table sgt;
> +     struct scatterlist *s;
> +     int ret = -ENOMEM;
> +     int i, j;
>  
>       if (exynos_gem->dma_addr) {
>               DRM_DEBUG_KMS("already allocated.\n");
> @@ -56,13 +60,10 @@ static int exynos_drm_alloc_buf(struct exynos_drm_gem 
> *exynos_gem)
>  
>       nr_pages = exynos_gem->size >> PAGE_SHIFT;
>  
> -     if (!is_drm_iommu_supported(dev)) {
> -             exynos_gem->pages = drm_calloc_large(nr_pages,
> -                                                  sizeof(struct page *));
> -             if (!exynos_gem->pages) {
> -                     DRM_ERROR("failed to allocate pages.\n");
> -                     return -ENOMEM;
> -             }
> +     exynos_gem->pages = drm_calloc_large(nr_pages, sizeof(struct page *));
> +     if (!exynos_gem->pages) {
> +             DRM_ERROR("failed to allocate pages.\n");
> +             return -ENOMEM;
>       }
>  
>       exynos_gem->cookie = dma_alloc_attrs(dev->dev, exynos_gem->size,
> @@ -70,30 +71,40 @@ static int exynos_drm_alloc_buf(struct exynos_drm_gem 
> *exynos_gem)
>                                            &exynos_gem->dma_attrs);
>       if (!exynos_gem->cookie) {
>               DRM_ERROR("failed to allocate buffer.\n");
> -             if (exynos_gem->pages)
> -                     drm_free_large(exynos_gem->pages);
> -             return -ENOMEM;
> +             goto err_free;
>       }
>  
> -     if (exynos_gem->pages) {
> -             dma_addr_t start_addr;
> -             unsigned int i = 0;
> -
> -             start_addr = exynos_gem->dma_addr;
> -             while (i < nr_pages) {
> -                     exynos_gem->pages[i] =
> -                             pfn_to_page(dma_to_pfn(dev->dev, start_addr));
> -                     start_addr += PAGE_SIZE;
> -                     i++;
> -             }
> -     } else {
> -             exynos_gem->pages = exynos_gem->cookie;
> +     ret = dma_get_sgtable_attrs(dev->dev, &sgt, exynos_gem->cookie,
> +                                 exynos_gem->dma_addr, exynos_gem->size,
> +                                 &exynos_gem->dma_attrs);
> +     if (ret < 0) {
> +             DRM_ERROR("failed to get sgtable.\n");
> +             goto err_dma_free;
> +     }
> +
> +     j = 0;
> +     for_each_sg(sgt.sgl, s, sgt.orig_nents, i) {
> +             int size = s->length >> PAGE_SHIFT;
> +             struct page *page = sg_page(s);
> +
> +             while (size-- > 0)
> +                     exynos_gem->pages[j++] = page++;
>       }

drm_prime_sg_to_page_addr_arrays() will do same operation.

Thanks.

Reply via email to