From: Russell King <rmk+ker...@arm.linux.org.uk>

Provide a get_pages() method for gem objects, which allows our objects
to provide their own method to obtain the struct page array and
scatterlist.

Signed-off-by: Russell King <rmk+kernel at arm.linux.org.uk>
---
 drivers/staging/etnaviv/etnaviv_gem.c       | 67 ++++++++++++++++-------------
 drivers/staging/etnaviv/etnaviv_gem.h       |  1 +
 drivers/staging/etnaviv/etnaviv_gem_prime.c |  1 +
 3 files changed, 38 insertions(+), 31 deletions(-)

diff --git a/drivers/staging/etnaviv/etnaviv_gem.c 
b/drivers/staging/etnaviv/etnaviv_gem.c
index 2120cd378d86..e508d64aa2d3 100644
--- a/drivers/staging/etnaviv/etnaviv_gem.c
+++ b/drivers/staging/etnaviv/etnaviv_gem.c
@@ -24,39 +24,35 @@
 #include "etnaviv_mmu.h"

 /* called with dev->struct_mutex held */
-static struct page **get_pages(struct etnaviv_gem_object *etnaviv_obj)
+static int etnaviv_gem_shmem_get_pages(struct etnaviv_gem_object *etnaviv_obj)
 {
-       if (!etnaviv_obj->pages) {
-               struct drm_device *dev = etnaviv_obj->base.dev;
-               struct page **p;
-               int npages = etnaviv_obj->base.size >> PAGE_SHIFT;
-
-               p = drm_gem_get_pages(&etnaviv_obj->base);
+       struct drm_device *dev = etnaviv_obj->base.dev;
+       struct page **p;
+       int npages = etnaviv_obj->base.size >> PAGE_SHIFT;

-               if (IS_ERR(p)) {
-                       dev_err(dev->dev, "could not get pages: %ld\n",
-                                       PTR_ERR(p));
-                       return p;
-               }
+       p = drm_gem_get_pages(&etnaviv_obj->base);
+       if (IS_ERR(p)) {
+               dev_err(dev->dev, "could not get pages: %ld\n", PTR_ERR(p));
+               return PTR_ERR(p);
+       }

-               etnaviv_obj->sgt = drm_prime_pages_to_sg(p, npages);
-               if (IS_ERR(etnaviv_obj->sgt)) {
-                       dev_err(dev->dev, "failed to allocate sgt\n");
-                       drm_gem_put_pages(&etnaviv_obj->base, p, false, false);
-                       return ERR_CAST(etnaviv_obj->sgt);
-               }
+       etnaviv_obj->sgt = drm_prime_pages_to_sg(p, npages);
+       if (IS_ERR(etnaviv_obj->sgt)) {
+               dev_err(dev->dev, "failed to allocate sgt\n");
+               drm_gem_put_pages(&etnaviv_obj->base, p, false, false);
+               return PTR_ERR(p);
+       }

-               etnaviv_obj->pages = p;
+       etnaviv_obj->pages = p;

-               /* For non-cached buffers, ensure the new pages are clean
-                * because display controller, GPU, etc. are not coherent:
-                */
-               if (etnaviv_obj->flags & (ETNA_BO_WC|ETNA_BO_UNCACHED))
-                       dma_map_sg(dev->dev, etnaviv_obj->sgt->sgl,
-                                  etnaviv_obj->sgt->nents, DMA_BIDIRECTIONAL);
-       }
+       /* For non-cached buffers, ensure the new pages are clean
+        * because display controller, GPU, etc. are not coherent:
+        */
+       if (etnaviv_obj->flags & (ETNA_BO_WC|ETNA_BO_UNCACHED))
+               dma_map_sg(dev->dev, etnaviv_obj->sgt->sgl,
+                          etnaviv_obj->sgt->nents, DMA_BIDIRECTIONAL);

-       return etnaviv_obj->pages;
+       return 0;
 }

 static void put_pages(struct etnaviv_gem_object *etnaviv_obj)
@@ -83,7 +79,15 @@ static void put_pages(struct etnaviv_gem_object *etnaviv_obj)

 struct page **etnaviv_gem_get_pages(struct etnaviv_gem_object *etnaviv_obj)
 {
-       return get_pages(etnaviv_obj);
+       int ret;
+
+       if (!etnaviv_obj->pages) {
+               ret = etnaviv_obj->ops->get_pages(etnaviv_obj);
+               if (ret < 0)
+                       return ERR_PTR(ret);
+       }
+
+       return etnaviv_obj->pages;
 }

 void etnaviv_gem_put_pages(struct etnaviv_gem_object *etnaviv_obj)
@@ -181,7 +185,7 @@ int etnaviv_gem_fault(struct vm_area_struct *vma, struct 
vm_fault *vmf)
                goto out;

        /* make sure we have pages attached now */
-       pages = get_pages(to_etnaviv_bo(obj));
+       pages = etnaviv_gem_get_pages(to_etnaviv_bo(obj));
        if (IS_ERR(pages)) {
                ret = PTR_ERR(pages);
                goto out_unlock;
@@ -265,7 +269,7 @@ int etnaviv_gem_get_iova_locked(struct etnaviv_gpu *gpu,
        if (!etnaviv_obj->iova  && !(etnaviv_obj->flags & ETNA_BO_CMDSTREAM)) {
                struct etnaviv_drm_private *priv = obj->dev->dev_private;
                struct etnaviv_iommu *mmu = priv->mmu;
-               struct page **pages = get_pages(etnaviv_obj);
+               struct page **pages = etnaviv_gem_get_pages(etnaviv_obj);
                uint32_t offset;
                struct drm_mm_node *node = NULL;

@@ -367,7 +371,7 @@ void *etnaviv_gem_vaddr_locked(struct drm_gem_object *obj)
        WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex));

        if (!etnaviv_obj->vaddr) {
-               struct page **pages = get_pages(etnaviv_obj);
+               struct page **pages = etnaviv_gem_get_pages(etnaviv_obj);

                if (IS_ERR(pages))
                        return ERR_CAST(pages);
@@ -532,6 +536,7 @@ static void etnaviv_gem_shmem_release(struct 
etnaviv_gem_object *etnaviv_obj)
 }

 static const struct etnaviv_gem_ops etnaviv_gem_shmem_ops = {
+       .get_pages = etnaviv_gem_shmem_get_pages,
        .release = etnaviv_gem_shmem_release,
 };

diff --git a/drivers/staging/etnaviv/etnaviv_gem.h 
b/drivers/staging/etnaviv/etnaviv_gem.h
index 569a407cbd35..bbfcbd7557fe 100644
--- a/drivers/staging/etnaviv/etnaviv_gem.h
+++ b/drivers/staging/etnaviv/etnaviv_gem.h
@@ -68,6 +68,7 @@ struct etnaviv_gem_object {
 #define to_etnaviv_bo(x) container_of(x, struct etnaviv_gem_object, base)

 struct etnaviv_gem_ops {
+       int (*get_pages)(struct etnaviv_gem_object *);
        void (*release)(struct etnaviv_gem_object *);
 };

diff --git a/drivers/staging/etnaviv/etnaviv_gem_prime.c 
b/drivers/staging/etnaviv/etnaviv_gem_prime.c
index 3a986ae9b00b..d15f4b60fa47 100644
--- a/drivers/staging/etnaviv/etnaviv_gem_prime.c
+++ b/drivers/staging/etnaviv/etnaviv_gem_prime.c
@@ -78,6 +78,7 @@ static void etnaviv_gem_prime_release(struct 
etnaviv_gem_object *etnaviv_obj)
 }

 static const struct etnaviv_gem_ops etnaviv_gem_prime_ops = {
+       /* .get_pages should never be called */
        .release = etnaviv_gem_prime_release,
 };

-- 
2.1.4

Reply via email to