Merge tag 'drm-misc-next-2020-02-10' of git://anongit.freedesktop.org/drm/drm-misc...
[platform/kernel/linux-rpi.git] / drivers / gpu / drm / panfrost / panfrost_mmu.c
index d369457..23314f4 100644 (file)
@@ -269,14 +269,15 @@ static int mmu_map_sg(struct panfrost_device *pfdev, struct panfrost_mmu *mmu,
        return 0;
 }
 
-int panfrost_mmu_map(struct panfrost_gem_object *bo)
+int panfrost_mmu_map(struct panfrost_gem_mapping *mapping)
 {
+       struct panfrost_gem_object *bo = mapping->obj;
        struct drm_gem_object *obj = &bo->base.base;
        struct panfrost_device *pfdev = to_panfrost_device(obj->dev);
        struct sg_table *sgt;
        int prot = IOMMU_READ | IOMMU_WRITE;
 
-       if (WARN_ON(bo->is_mapped))
+       if (WARN_ON(mapping->active))
                return 0;
 
        if (bo->noexec)
@@ -286,25 +287,28 @@ int panfrost_mmu_map(struct panfrost_gem_object *bo)
        if (WARN_ON(IS_ERR(sgt)))
                return PTR_ERR(sgt);
 
-       mmu_map_sg(pfdev, bo->mmu, bo->node.start << PAGE_SHIFT, prot, sgt);
-       bo->is_mapped = true;
+       mmu_map_sg(pfdev, mapping->mmu, mapping->mmnode.start << PAGE_SHIFT,
+                  prot, sgt);
+       mapping->active = true;
 
        return 0;
 }
 
-void panfrost_mmu_unmap(struct panfrost_gem_object *bo)
+void panfrost_mmu_unmap(struct panfrost_gem_mapping *mapping)
 {
+       struct panfrost_gem_object *bo = mapping->obj;
        struct drm_gem_object *obj = &bo->base.base;
        struct panfrost_device *pfdev = to_panfrost_device(obj->dev);
-       struct io_pgtable_ops *ops = bo->mmu->pgtbl_ops;
-       u64 iova = bo->node.start << PAGE_SHIFT;
-       size_t len = bo->node.size << PAGE_SHIFT;
+       struct io_pgtable_ops *ops = mapping->mmu->pgtbl_ops;
+       u64 iova = mapping->mmnode.start << PAGE_SHIFT;
+       size_t len = mapping->mmnode.size << PAGE_SHIFT;
        size_t unmapped_len = 0;
 
-       if (WARN_ON(!bo->is_mapped))
+       if (WARN_ON(!mapping->active))
                return;
 
-       dev_dbg(pfdev->dev, "unmap: as=%d, iova=%llx, len=%zx", bo->mmu->as, iova, len);
+       dev_dbg(pfdev->dev, "unmap: as=%d, iova=%llx, len=%zx",
+               mapping->mmu->as, iova, len);
 
        while (unmapped_len < len) {
                size_t unmapped_page;
@@ -318,8 +322,9 @@ void panfrost_mmu_unmap(struct panfrost_gem_object *bo)
                unmapped_len += pgsize;
        }
 
-       panfrost_mmu_flush_range(pfdev, bo->mmu, bo->node.start << PAGE_SHIFT, len);
-       bo->is_mapped = false;
+       panfrost_mmu_flush_range(pfdev, mapping->mmu,
+                                mapping->mmnode.start << PAGE_SHIFT, len);
+       mapping->active = false;
 }
 
 static void mmu_tlb_inv_context_s1(void *cookie)
@@ -394,10 +399,10 @@ void panfrost_mmu_pgtable_free(struct panfrost_file_priv *priv)
        free_io_pgtable_ops(mmu->pgtbl_ops);
 }
 
-static struct panfrost_gem_object *
-addr_to_drm_mm_node(struct panfrost_device *pfdev, int as, u64 addr)
+static struct panfrost_gem_mapping *
+addr_to_mapping(struct panfrost_device *pfdev, int as, u64 addr)
 {
-       struct panfrost_gem_object *bo = NULL;
+       struct panfrost_gem_mapping *mapping = NULL;
        struct panfrost_file_priv *priv;
        struct drm_mm_node *node;
        u64 offset = addr >> PAGE_SHIFT;
@@ -418,8 +423,9 @@ found_mmu:
        drm_mm_for_each_node(node, &priv->mm) {
                if (offset >= node->start &&
                    offset < (node->start + node->size)) {
-                       bo = drm_mm_node_to_panfrost_bo(node);
-                       drm_gem_object_get(&bo->base.base);
+                       mapping = drm_mm_node_to_panfrost_mapping(node);
+
+                       kref_get(&mapping->refcount);
                        break;
                }
        }
@@ -427,7 +433,7 @@ found_mmu:
        spin_unlock(&priv->mm_lock);
 out:
        spin_unlock(&pfdev->as_lock);
-       return bo;
+       return mapping;
 }
 
 #define NUM_FAULT_PAGES (SZ_2M / PAGE_SIZE)
@@ -436,28 +442,30 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
                                       u64 addr)
 {
        int ret, i;
+       struct panfrost_gem_mapping *bomapping;
        struct panfrost_gem_object *bo;
        struct address_space *mapping;
        pgoff_t page_offset;
        struct sg_table *sgt;
        struct page **pages;
 
-       bo = addr_to_drm_mm_node(pfdev, as, addr);
-       if (!bo)
+       bomapping = addr_to_mapping(pfdev, as, addr);
+       if (!bomapping)
                return -ENOENT;
 
+       bo = bomapping->obj;
        if (!bo->is_heap) {
                dev_WARN(pfdev->dev, "matching BO is not heap type (GPU VA = %llx)",
-                        bo->node.start << PAGE_SHIFT);
+                        bomapping->mmnode.start << PAGE_SHIFT);
                ret = -EINVAL;
                goto err_bo;
        }
-       WARN_ON(bo->mmu->as != as);
+       WARN_ON(bomapping->mmu->as != as);
 
        /* Assume 2MB alignment and size multiple */
        addr &= ~((u64)SZ_2M - 1);
        page_offset = addr >> PAGE_SHIFT;
-       page_offset -= bo->node.start;
+       page_offset -= bomapping->mmnode.start;
 
        mutex_lock(&bo->base.pages_lock);
 
@@ -509,13 +517,14 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
                goto err_map;
        }
 
-       mmu_map_sg(pfdev, bo->mmu, addr, IOMMU_WRITE | IOMMU_READ | IOMMU_NOEXEC, sgt);
+       mmu_map_sg(pfdev, bomapping->mmu, addr,
+                  IOMMU_WRITE | IOMMU_READ | IOMMU_NOEXEC, sgt);
 
-       bo->is_mapped = true;
+       bomapping->active = true;
 
        dev_dbg(pfdev->dev, "mapped page fault @ AS%d %llx", as, addr);
 
-       drm_gem_object_put_unlocked(&bo->base.base);
+       panfrost_gem_mapping_put(bomapping);
 
        return 0;