[Intel-gfx] [PATCH 13/28] drm/i915: Remove pages_mutex and intel_gtt->vma_ops.set/clear_pages members

Matthew Auld matthew.william.auld at gmail.com
Fri Oct 22 10:59:27 UTC 2021


On Thu, 21 Oct 2021 at 18:30, Matthew Auld
<matthew.william.auld at gmail.com> wrote:
>
> On Thu, 21 Oct 2021 at 11:36, Maarten Lankhorst
> <maarten.lankhorst at linux.intel.com> wrote:
> >
> > Big delta, but boils down to moving set_pages to i915_vma.c, and removing
> > the special handling, all callers use the defaults anyway. We only remap
> > in ggtt, so default case will fall through.
> >
> > Because we still don't require locking in i915_vma_unpin(), handle this by
> > using xchg in get_pages(), as it's locked with obj->mutex, and cmpxchg in
> > unpin, which only fails if we race a against a new pin.
> >
> > Signed-off-by: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/display/intel_dpt.c      |   2 -
> >  drivers/gpu/drm/i915/gt/gen6_ppgtt.c          |  15 -
> >  drivers/gpu/drm/i915/gt/intel_ggtt.c          | 345 ----------------
> >  drivers/gpu/drm/i915/gt/intel_gtt.c           |  13 -
> >  drivers/gpu/drm/i915/gt/intel_gtt.h           |   7 -
> >  drivers/gpu/drm/i915/gt/intel_ppgtt.c         |  12 -
> >  drivers/gpu/drm/i915/i915_vma.c               | 388 ++++++++++++++++--
> >  drivers/gpu/drm/i915/i915_vma.h               |   3 +
> >  drivers/gpu/drm/i915/i915_vma_types.h         |   1 -
> >  drivers/gpu/drm/i915/selftests/i915_gem_gtt.c |  12 +-
> >  drivers/gpu/drm/i915/selftests/mock_gtt.c     |   4 -
> >  11 files changed, 368 insertions(+), 434 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/display/intel_dpt.c b/drivers/gpu/drm/i915/display/intel_dpt.c
> > index 8f7b1f7534a4..ef428f3fc538 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dpt.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dpt.c
> > @@ -221,8 +221,6 @@ intel_dpt_create(struct intel_framebuffer *fb)
> >
> >         vm->vma_ops.bind_vma    = dpt_bind_vma;
> >         vm->vma_ops.unbind_vma  = dpt_unbind_vma;
> > -       vm->vma_ops.set_pages   = ggtt_set_pages;
> > -       vm->vma_ops.clear_pages = clear_pages;
> >
> >         vm->pte_encode = gen8_ggtt_pte_encode;
> >
> > diff --git a/drivers/gpu/drm/i915/gt/gen6_ppgtt.c b/drivers/gpu/drm/i915/gt/gen6_ppgtt.c
> > index 5caa1703716e..5c048b4ccd4d 100644
> > --- a/drivers/gpu/drm/i915/gt/gen6_ppgtt.c
> > +++ b/drivers/gpu/drm/i915/gt/gen6_ppgtt.c
> > @@ -270,19 +270,6 @@ static void gen6_ppgtt_cleanup(struct i915_address_space *vm)
> >         free_pd(&ppgtt->base.vm, ppgtt->base.pd);
> >  }
> >
> > -static int pd_vma_set_pages(struct i915_vma *vma)
> > -{
> > -       vma->pages = ERR_PTR(-ENODEV);
> > -       return 0;
> > -}
> > -
> > -static void pd_vma_clear_pages(struct i915_vma *vma)
> > -{
> > -       GEM_BUG_ON(!vma->pages);
> > -
> > -       vma->pages = NULL;
> > -}
> > -
> >  static void pd_vma_bind(struct i915_address_space *vm,
> >                         struct i915_vm_pt_stash *stash,
> >                         struct i915_vma *vma,
> > @@ -322,8 +309,6 @@ static void pd_vma_unbind(struct i915_address_space *vm, struct i915_vma *vma)
> >  }
> >
> >  static const struct i915_vma_ops pd_vma_ops = {
> > -       .set_pages = pd_vma_set_pages,
> > -       .clear_pages = pd_vma_clear_pages,
> >         .bind_vma = pd_vma_bind,
> >         .unbind_vma = pd_vma_unbind,
> >  };
> > diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c
> > index f17383e76eb7..6da57199bb33 100644
> > --- a/drivers/gpu/drm/i915/gt/intel_ggtt.c
> > +++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c
> > @@ -20,9 +20,6 @@
> >  #include "intel_gtt.h"
> >  #include "gen8_ppgtt.h"
> >
> > -static int
> > -i915_get_ggtt_vma_pages(struct i915_vma *vma);
> > -
> >  static void i915_ggtt_color_adjust(const struct drm_mm_node *node,
> >                                    unsigned long color,
> >                                    u64 *start,
> > @@ -875,21 +872,6 @@ static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size)
> >         return 0;
> >  }
> >
> > -int ggtt_set_pages(struct i915_vma *vma)
> > -{
> > -       int ret;
> > -
> > -       GEM_BUG_ON(vma->pages);
> > -
> > -       ret = i915_get_ggtt_vma_pages(vma);
> > -       if (ret)
> > -               return ret;
> > -
> > -       vma->page_sizes = vma->obj->mm.page_sizes;
> > -
> > -       return 0;
> > -}
> > -
> >  static void gen6_gmch_remove(struct i915_address_space *vm)
> >  {
> >         struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
> > @@ -950,8 +932,6 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)
> >
> >         ggtt->vm.vma_ops.bind_vma    = ggtt_bind_vma;
> >         ggtt->vm.vma_ops.unbind_vma  = ggtt_unbind_vma;
> > -       ggtt->vm.vma_ops.set_pages   = ggtt_set_pages;
> > -       ggtt->vm.vma_ops.clear_pages = clear_pages;
> >
> >         ggtt->vm.pte_encode = gen8_ggtt_pte_encode;
> >
> > @@ -1100,8 +1080,6 @@ static int gen6_gmch_probe(struct i915_ggtt *ggtt)
> >
> >         ggtt->vm.vma_ops.bind_vma    = ggtt_bind_vma;
> >         ggtt->vm.vma_ops.unbind_vma  = ggtt_unbind_vma;
> > -       ggtt->vm.vma_ops.set_pages   = ggtt_set_pages;
> > -       ggtt->vm.vma_ops.clear_pages = clear_pages;
> >
> >         return ggtt_probe_common(ggtt, size);
> >  }
> > @@ -1145,8 +1123,6 @@ static int i915_gmch_probe(struct i915_ggtt *ggtt)
> >
> >         ggtt->vm.vma_ops.bind_vma    = ggtt_bind_vma;
> >         ggtt->vm.vma_ops.unbind_vma  = ggtt_unbind_vma;
> > -       ggtt->vm.vma_ops.set_pages   = ggtt_set_pages;
> > -       ggtt->vm.vma_ops.clear_pages = clear_pages;
> >
> >         if (unlikely(ggtt->do_idle_maps))
> >                 drm_notice(&i915->drm,
> > @@ -1294,324 +1270,3 @@ void i915_ggtt_resume(struct i915_ggtt *ggtt)
> >
> >         intel_ggtt_restore_fences(ggtt);
> >  }
> > -
> > -static struct scatterlist *
> > -rotate_pages(struct drm_i915_gem_object *obj, unsigned int offset,
> > -            unsigned int width, unsigned int height,
> > -            unsigned int src_stride, unsigned int dst_stride,
> > -            struct sg_table *st, struct scatterlist *sg)
> > -{
> > -       unsigned int column, row;
> > -       unsigned int src_idx;
> > -
> > -       for (column = 0; column < width; column++) {
> > -               unsigned int left;
> > -
> > -               src_idx = src_stride * (height - 1) + column + offset;
> > -               for (row = 0; row < height; row++) {
> > -                       st->nents++;
> > -                       /*
> > -                        * We don't need the pages, but need to initialize
> > -                        * the entries so the sg list can be happily traversed.
> > -                        * The only thing we need are DMA addresses.
> > -                        */
> > -                       sg_set_page(sg, NULL, I915_GTT_PAGE_SIZE, 0);
> > -                       sg_dma_address(sg) =
> > -                               i915_gem_object_get_dma_address(obj, src_idx);
> > -                       sg_dma_len(sg) = I915_GTT_PAGE_SIZE;
> > -                       sg = sg_next(sg);
> > -                       src_idx -= src_stride;
> > -               }
> > -
> > -               left = (dst_stride - height) * I915_GTT_PAGE_SIZE;
> > -
> > -               if (!left)
> > -                       continue;
> > -
> > -               st->nents++;
> > -
> > -               /*
> > -                * The DE ignores the PTEs for the padding tiles, the sg entry
> > -                * here is just a conenience to indicate how many padding PTEs
> > -                * to insert at this spot.
> > -                */
> > -               sg_set_page(sg, NULL, left, 0);
> > -               sg_dma_address(sg) = 0;
> > -               sg_dma_len(sg) = left;
> > -               sg = sg_next(sg);
> > -       }
> > -
> > -       return sg;
> > -}
> > -
> > -static noinline struct sg_table *
> > -intel_rotate_pages(struct intel_rotation_info *rot_info,
> > -                  struct drm_i915_gem_object *obj)
> > -{
> > -       unsigned int size = intel_rotation_info_size(rot_info);
> > -       struct drm_i915_private *i915 = to_i915(obj->base.dev);
> > -       struct sg_table *st;
> > -       struct scatterlist *sg;
> > -       int ret = -ENOMEM;
> > -       int i;
> > -
> > -       /* Allocate target SG list. */
> > -       st = kmalloc(sizeof(*st), GFP_KERNEL);
> > -       if (!st)
> > -               goto err_st_alloc;
> > -
> > -       ret = sg_alloc_table(st, size, GFP_KERNEL);
> > -       if (ret)
> > -               goto err_sg_alloc;
> > -
> > -       st->nents = 0;
> > -       sg = st->sgl;
> > -
> > -       for (i = 0 ; i < ARRAY_SIZE(rot_info->plane); i++)
> > -               sg = rotate_pages(obj, rot_info->plane[i].offset,
> > -                                 rot_info->plane[i].width, rot_info->plane[i].height,
> > -                                 rot_info->plane[i].src_stride,
> > -                                 rot_info->plane[i].dst_stride,
> > -                                 st, sg);
> > -
> > -       return st;
> > -
> > -err_sg_alloc:
> > -       kfree(st);
> > -err_st_alloc:
> > -
> > -       drm_dbg(&i915->drm, "Failed to create rotated mapping for object size %zu! (%ux%u tiles, %u pages)\n",
> > -               obj->base.size, rot_info->plane[0].width,
> > -               rot_info->plane[0].height, size);
> > -
> > -       return ERR_PTR(ret);
> > -}
> > -
> > -static struct scatterlist *
> > -remap_pages(struct drm_i915_gem_object *obj,
> > -           unsigned int offset, unsigned int alignment_pad,
> > -           unsigned int width, unsigned int height,
> > -           unsigned int src_stride, unsigned int dst_stride,
> > -           struct sg_table *st, struct scatterlist *sg)
> > -{
> > -       unsigned int row;
> > -
> > -       if (alignment_pad) {
> > -               st->nents++;
> > -
> > -               /*
> > -                * The DE ignores the PTEs for the padding tiles, the sg entry
> > -                * here is just a convenience to indicate how many padding PTEs
> > -                * to insert at this spot.
> > -                */
> > -               sg_set_page(sg, NULL, alignment_pad * 4096, 0);
> > -               sg_dma_address(sg) = 0;
> > -               sg_dma_len(sg) = alignment_pad * 4096;
> > -               sg = sg_next(sg);
> > -       }
> > -
> > -       for (row = 0; row < height; row++) {
> > -               unsigned int left = width * I915_GTT_PAGE_SIZE;
> > -
> > -               while (left) {
> > -                       dma_addr_t addr;
> > -                       unsigned int length;
> > -
> > -                       /*
> > -                        * We don't need the pages, but need to initialize
> > -                        * the entries so the sg list can be happily traversed.
> > -                        * The only thing we need are DMA addresses.
> > -                        */
> > -
> > -                       addr = i915_gem_object_get_dma_address_len(obj, offset, &length);
> > -
> > -                       length = min(left, length);
> > -
> > -                       st->nents++;
> > -
> > -                       sg_set_page(sg, NULL, length, 0);
> > -                       sg_dma_address(sg) = addr;
> > -                       sg_dma_len(sg) = length;
> > -                       sg = sg_next(sg);
> > -
> > -                       offset += length / I915_GTT_PAGE_SIZE;
> > -                       left -= length;
> > -               }
> > -
> > -               offset += src_stride - width;
> > -
> > -               left = (dst_stride - width) * I915_GTT_PAGE_SIZE;
> > -
> > -               if (!left)
> > -                       continue;
> > -
> > -               st->nents++;
> > -
> > -               /*
> > -                * The DE ignores the PTEs for the padding tiles, the sg entry
> > -                * here is just a conenience to indicate how many padding PTEs
> > -                * to insert at this spot.
> > -                */
> > -               sg_set_page(sg, NULL, left, 0);
> > -               sg_dma_address(sg) = 0;
> > -               sg_dma_len(sg) = left;
> > -               sg = sg_next(sg);
> > -       }
> > -
> > -       return sg;
> > -}
> > -
> > -static noinline struct sg_table *
> > -intel_remap_pages(struct intel_remapped_info *rem_info,
> > -                 struct drm_i915_gem_object *obj)
> > -{
> > -       unsigned int size = intel_remapped_info_size(rem_info);
> > -       struct drm_i915_private *i915 = to_i915(obj->base.dev);
> > -       struct sg_table *st;
> > -       struct scatterlist *sg;
> > -       unsigned int gtt_offset = 0;
> > -       int ret = -ENOMEM;
> > -       int i;
> > -
> > -       /* Allocate target SG list. */
> > -       st = kmalloc(sizeof(*st), GFP_KERNEL);
> > -       if (!st)
> > -               goto err_st_alloc;
> > -
> > -       ret = sg_alloc_table(st, size, GFP_KERNEL);
> > -       if (ret)
> > -               goto err_sg_alloc;
> > -
> > -       st->nents = 0;
> > -       sg = st->sgl;
> > -
> > -       for (i = 0 ; i < ARRAY_SIZE(rem_info->plane); i++) {
> > -               unsigned int alignment_pad = 0;
> > -
> > -               if (rem_info->plane_alignment)
> > -                       alignment_pad = ALIGN(gtt_offset, rem_info->plane_alignment) - gtt_offset;
> > -
> > -               sg = remap_pages(obj,
> > -                                rem_info->plane[i].offset, alignment_pad,
> > -                                rem_info->plane[i].width, rem_info->plane[i].height,
> > -                                rem_info->plane[i].src_stride, rem_info->plane[i].dst_stride,
> > -                                st, sg);
> > -
> > -               gtt_offset += alignment_pad +
> > -                             rem_info->plane[i].dst_stride * rem_info->plane[i].height;
> > -       }
> > -
> > -       i915_sg_trim(st);
> > -
> > -       return st;
> > -
> > -err_sg_alloc:
> > -       kfree(st);
> > -err_st_alloc:
> > -
> > -       drm_dbg(&i915->drm, "Failed to create remapped mapping for object size %zu! (%ux%u tiles, %u pages)\n",
> > -               obj->base.size, rem_info->plane[0].width,
> > -               rem_info->plane[0].height, size);
> > -
> > -       return ERR_PTR(ret);
> > -}
> > -
> > -static noinline struct sg_table *
> > -intel_partial_pages(const struct i915_ggtt_view *view,
> > -                   struct drm_i915_gem_object *obj)
> > -{
> > -       struct sg_table *st;
> > -       struct scatterlist *sg, *iter;
> > -       unsigned int count = view->partial.size;
> > -       unsigned int offset;
> > -       int ret = -ENOMEM;
> > -
> > -       st = kmalloc(sizeof(*st), GFP_KERNEL);
> > -       if (!st)
> > -               goto err_st_alloc;
> > -
> > -       ret = sg_alloc_table(st, count, GFP_KERNEL);
> > -       if (ret)
> > -               goto err_sg_alloc;
> > -
> > -       iter = i915_gem_object_get_sg_dma(obj, view->partial.offset, &offset);
> > -       GEM_BUG_ON(!iter);
> > -
> > -       sg = st->sgl;
> > -       st->nents = 0;
> > -       do {
> > -               unsigned int len;
> > -
> > -               len = min(sg_dma_len(iter) - (offset << PAGE_SHIFT),
> > -                         count << PAGE_SHIFT);
> > -               sg_set_page(sg, NULL, len, 0);
> > -               sg_dma_address(sg) =
> > -                       sg_dma_address(iter) + (offset << PAGE_SHIFT);
> > -               sg_dma_len(sg) = len;
> > -
> > -               st->nents++;
> > -               count -= len >> PAGE_SHIFT;
> > -               if (count == 0) {
> > -                       sg_mark_end(sg);
> > -                       i915_sg_trim(st); /* Drop any unused tail entries. */
> > -
> > -                       return st;
> > -               }
> > -
> > -               sg = __sg_next(sg);
> > -               iter = __sg_next(iter);
> > -               offset = 0;
> > -       } while (1);
> > -
> > -err_sg_alloc:
> > -       kfree(st);
> > -err_st_alloc:
> > -       return ERR_PTR(ret);
> > -}
> > -
> > -static int
> > -i915_get_ggtt_vma_pages(struct i915_vma *vma)
> > -{
> > -       int ret;
> > -
> > -       /*
> > -        * The vma->pages are only valid within the lifespan of the borrowed
> > -        * obj->mm.pages. When the obj->mm.pages sg_table is regenerated, so
> > -        * must be the vma->pages. A simple rule is that vma->pages must only
> > -        * be accessed when the obj->mm.pages are pinned.
> > -        */
> > -       GEM_BUG_ON(!i915_gem_object_has_pinned_pages(vma->obj));
> > -
> > -       switch (vma->ggtt_view.type) {
> > -       default:
> > -               GEM_BUG_ON(vma->ggtt_view.type);
> > -               fallthrough;
> > -       case I915_GGTT_VIEW_NORMAL:
> > -               vma->pages = vma->obj->mm.pages;
> > -               return 0;
> > -
> > -       case I915_GGTT_VIEW_ROTATED:
> > -               vma->pages =
> > -                       intel_rotate_pages(&vma->ggtt_view.rotated, vma->obj);
> > -               break;
> > -
> > -       case I915_GGTT_VIEW_REMAPPED:
> > -               vma->pages =
> > -                       intel_remap_pages(&vma->ggtt_view.remapped, vma->obj);
> > -               break;
> > -
> > -       case I915_GGTT_VIEW_PARTIAL:
> > -               vma->pages = intel_partial_pages(&vma->ggtt_view, vma->obj);
> > -               break;
> > -       }
> > -
> > -       ret = 0;
> > -       if (IS_ERR(vma->pages)) {
> > -               ret = PTR_ERR(vma->pages);
> > -               vma->pages = NULL;
> > -               drm_err(&vma->vm->i915->drm,
> > -                       "Failed to get pages for VMA view type %u (%d)!\n",
> > -                       vma->ggtt_view.type, ret);
> > -       }
> > -       return ret;
> > -}
> > diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.c b/drivers/gpu/drm/i915/gt/intel_gtt.c
> > index 67d14afa6623..12eed5fcb17a 100644
> > --- a/drivers/gpu/drm/i915/gt/intel_gtt.c
> > +++ b/drivers/gpu/drm/i915/gt/intel_gtt.c
> > @@ -221,19 +221,6 @@ void i915_address_space_init(struct i915_address_space *vm, int subclass)
> >         INIT_LIST_HEAD(&vm->bound_list);
> >  }
> >
> > -void clear_pages(struct i915_vma *vma)
> > -{
> > -       GEM_BUG_ON(!vma->pages);
> > -
> > -       if (vma->pages != vma->obj->mm.pages) {
> > -               sg_free_table(vma->pages);
> > -               kfree(vma->pages);
> > -       }
> > -       vma->pages = NULL;
> > -
> > -       memset(&vma->page_sizes, 0, sizeof(vma->page_sizes));
> > -}
> > -
> >  void *__px_vaddr(struct drm_i915_gem_object *p)
> >  {
> >         enum i915_map_type type;
> > diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.h b/drivers/gpu/drm/i915/gt/intel_gtt.h
> > index bc6750263359..306e7645fdc5 100644
> > --- a/drivers/gpu/drm/i915/gt/intel_gtt.h
> > +++ b/drivers/gpu/drm/i915/gt/intel_gtt.h
> > @@ -206,9 +206,6 @@ struct i915_vma_ops {
> >          */
> >         void (*unbind_vma)(struct i915_address_space *vm,
> >                            struct i915_vma *vma);
> > -
> > -       int (*set_pages)(struct i915_vma *vma);
> > -       void (*clear_pages)(struct i915_vma *vma);
> >  };
> >
> >  struct i915_address_space {
> > @@ -594,10 +591,6 @@ release_pd_entry(struct i915_page_directory * const pd,
> >                  const struct drm_i915_gem_object * const scratch);
> >  void gen6_ggtt_invalidate(struct i915_ggtt *ggtt);
> >
> > -int ggtt_set_pages(struct i915_vma *vma);
> > -int ppgtt_set_pages(struct i915_vma *vma);
> > -void clear_pages(struct i915_vma *vma);
> > -
> >  void ppgtt_bind_vma(struct i915_address_space *vm,
> >                     struct i915_vm_pt_stash *stash,
> >                     struct i915_vma *vma,
> > diff --git a/drivers/gpu/drm/i915/gt/intel_ppgtt.c b/drivers/gpu/drm/i915/gt/intel_ppgtt.c
> > index 4396bfd630d8..083b3090c69c 100644
> > --- a/drivers/gpu/drm/i915/gt/intel_ppgtt.c
> > +++ b/drivers/gpu/drm/i915/gt/intel_ppgtt.c
> > @@ -289,16 +289,6 @@ void i915_vm_free_pt_stash(struct i915_address_space *vm,
> >         }
> >  }
> >
> > -int ppgtt_set_pages(struct i915_vma *vma)
> > -{
> > -       GEM_BUG_ON(vma->pages);
> > -
> > -       vma->pages = vma->obj->mm.pages;
> > -       vma->page_sizes = vma->obj->mm.page_sizes;
> > -
> > -       return 0;
> > -}
> > -
> >  void ppgtt_init(struct i915_ppgtt *ppgtt, struct intel_gt *gt,
> >                 unsigned long lmem_pt_obj_flags)
> >  {
> > @@ -315,6 +305,4 @@ void ppgtt_init(struct i915_ppgtt *ppgtt, struct intel_gt *gt,
> >
> >         ppgtt->vm.vma_ops.bind_vma    = ppgtt_bind_vma;
> >         ppgtt->vm.vma_ops.unbind_vma  = ppgtt_unbind_vma;
> > -       ppgtt->vm.vma_ops.set_pages   = ppgtt_set_pages;
> > -       ppgtt->vm.vma_ops.clear_pages = clear_pages;
> >  }
> > diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
> > index ac09b685678a..bacc8d68e495 100644
> > --- a/drivers/gpu/drm/i915/i915_vma.c
> > +++ b/drivers/gpu/drm/i915/i915_vma.c
> > @@ -112,7 +112,6 @@ vma_create(struct drm_i915_gem_object *obj,
> >                 return ERR_PTR(-ENOMEM);
> >
> >         kref_init(&vma->ref);
> > -       mutex_init(&vma->pages_mutex);
> >         vma->vm = i915_vm_get(vm);
> >         vma->ops = &vm->vma_ops;
> >         vma->obj = obj;
> > @@ -789,10 +788,343 @@ static bool try_qad_pin(struct i915_vma *vma, unsigned int flags)
> >         return pinned;
> >  }
> >
> > -static int vma_get_pages(struct i915_vma *vma)
> > +
> > +
> > +static struct scatterlist *
> > +rotate_pages(struct drm_i915_gem_object *obj, unsigned int offset,
> > +            unsigned int width, unsigned int height,
> > +            unsigned int src_stride, unsigned int dst_stride,
> > +            struct sg_table *st, struct scatterlist *sg)
> >  {
> > -       int err = 0;
> > -       bool pinned_pages = true;
> > +       unsigned int column, row;
> > +       unsigned int src_idx;
> > +
> > +       for (column = 0; column < width; column++) {
> > +               unsigned int left;
> > +
> > +               src_idx = src_stride * (height - 1) + column + offset;
> > +               for (row = 0; row < height; row++) {
> > +                       st->nents++;
> > +                       /*
> > +                        * We don't need the pages, but need to initialize
> > +                        * the entries so the sg list can be happily traversed.
> > +                        * The only thing we need are DMA addresses.
> > +                        */
> > +                       sg_set_page(sg, NULL, I915_GTT_PAGE_SIZE, 0);
> > +                       sg_dma_address(sg) =
> > +                               i915_gem_object_get_dma_address(obj, src_idx);
> > +                       sg_dma_len(sg) = I915_GTT_PAGE_SIZE;
> > +                       sg = sg_next(sg);
> > +                       src_idx -= src_stride;
> > +               }
> > +
> > +               left = (dst_stride - height) * I915_GTT_PAGE_SIZE;
> > +
> > +               if (!left)
> > +                       continue;
> > +
> > +               st->nents++;
> > +
> > +               /*
> > +                * The DE ignores the PTEs for the padding tiles, the sg entry
> > +                * here is just a conenience to indicate how many padding PTEs
> > +                * to insert at this spot.
> > +                */
> > +               sg_set_page(sg, NULL, left, 0);
> > +               sg_dma_address(sg) = 0;
> > +               sg_dma_len(sg) = left;
> > +               sg = sg_next(sg);
> > +       }
> > +
> > +       return sg;
> > +}
> > +
> > +static noinline struct sg_table *
> > +intel_rotate_pages(struct intel_rotation_info *rot_info,
> > +                  struct drm_i915_gem_object *obj)
> > +{
> > +       unsigned int size = intel_rotation_info_size(rot_info);
> > +       struct drm_i915_private *i915 = to_i915(obj->base.dev);
> > +       struct sg_table *st;
> > +       struct scatterlist *sg;
> > +       int ret = -ENOMEM;
> > +       int i;
> > +
> > +       /* Allocate target SG list. */
> > +       st = kmalloc(sizeof(*st), GFP_KERNEL);
> > +       if (!st)
> > +               goto err_st_alloc;
> > +
> > +       ret = sg_alloc_table(st, size, GFP_KERNEL);
> > +       if (ret)
> > +               goto err_sg_alloc;
> > +
> > +       st->nents = 0;
> > +       sg = st->sgl;
> > +
> > +       for (i = 0 ; i < ARRAY_SIZE(rot_info->plane); i++)
> > +               sg = rotate_pages(obj, rot_info->plane[i].offset,
> > +                                 rot_info->plane[i].width, rot_info->plane[i].height,
> > +                                 rot_info->plane[i].src_stride,
> > +                                 rot_info->plane[i].dst_stride,
> > +                                 st, sg);
> > +
> > +       return st;
> > +
> > +err_sg_alloc:
> > +       kfree(st);
> > +err_st_alloc:
> > +
> > +       drm_dbg(&i915->drm, "Failed to create rotated mapping for object size %zu! (%ux%u tiles, %u pages)\n",
> > +               obj->base.size, rot_info->plane[0].width,
> > +               rot_info->plane[0].height, size);
> > +
> > +       return ERR_PTR(ret);
> > +}
> > +
> > +static struct scatterlist *
> > +remap_pages(struct drm_i915_gem_object *obj,
> > +           unsigned int offset, unsigned int alignment_pad,
> > +           unsigned int width, unsigned int height,
> > +           unsigned int src_stride, unsigned int dst_stride,
> > +           struct sg_table *st, struct scatterlist *sg)
> > +{
> > +       unsigned int row;
> > +
> > +       if (alignment_pad) {
> > +               st->nents++;
> > +
> > +               /*
> > +                * The DE ignores the PTEs for the padding tiles, the sg entry
> > +                * here is just a convenience to indicate how many padding PTEs
> > +                * to insert at this spot.
> > +                */
> > +               sg_set_page(sg, NULL, alignment_pad * 4096, 0);
> > +               sg_dma_address(sg) = 0;
> > +               sg_dma_len(sg) = alignment_pad * 4096;
> > +               sg = sg_next(sg);
> > +       }
> > +
> > +       for (row = 0; row < height; row++) {
> > +               unsigned int left = width * I915_GTT_PAGE_SIZE;
> > +
> > +               while (left) {
> > +                       dma_addr_t addr;
> > +                       unsigned int length;
> > +
> > +                       /*
> > +                        * We don't need the pages, but need to initialize
> > +                        * the entries so the sg list can be happily traversed.
> > +                        * The only thing we need are DMA addresses.
> > +                        */
> > +
> > +                       addr = i915_gem_object_get_dma_address_len(obj, offset, &length);
> > +
> > +                       length = min(left, length);
> > +
> > +                       st->nents++;
> > +
> > +                       sg_set_page(sg, NULL, length, 0);
> > +                       sg_dma_address(sg) = addr;
> > +                       sg_dma_len(sg) = length;
> > +                       sg = sg_next(sg);
> > +
> > +                       offset += length / I915_GTT_PAGE_SIZE;
> > +                       left -= length;
> > +               }
> > +
> > +               offset += src_stride - width;
> > +
> > +               left = (dst_stride - width) * I915_GTT_PAGE_SIZE;
> > +
> > +               if (!left)
> > +                       continue;
> > +
> > +               st->nents++;
> > +
> > +               /*
> > +                * The DE ignores the PTEs for the padding tiles, the sg entry
> > +                * here is just a conenience to indicate how many padding PTEs
> > +                * to insert at this spot.
> > +                */
> > +               sg_set_page(sg, NULL, left, 0);
> > +               sg_dma_address(sg) = 0;
> > +               sg_dma_len(sg) = left;
> > +               sg = sg_next(sg);
> > +       }
> > +
> > +       return sg;
> > +}
> > +
> > +static noinline struct sg_table *
> > +intel_remap_pages(struct intel_remapped_info *rem_info,
> > +                 struct drm_i915_gem_object *obj)
> > +{
> > +       unsigned int size = intel_remapped_info_size(rem_info);
> > +       struct drm_i915_private *i915 = to_i915(obj->base.dev);
> > +       struct sg_table *st;
> > +       struct scatterlist *sg;
> > +       unsigned int gtt_offset = 0;
> > +       int ret = -ENOMEM;
> > +       int i;
> > +
> > +       /* Allocate target SG list. */
> > +       st = kmalloc(sizeof(*st), GFP_KERNEL);
> > +       if (!st)
> > +               goto err_st_alloc;
> > +
> > +       ret = sg_alloc_table(st, size, GFP_KERNEL);
> > +       if (ret)
> > +               goto err_sg_alloc;
> > +
> > +       st->nents = 0;
> > +       sg = st->sgl;
> > +
> > +       for (i = 0 ; i < ARRAY_SIZE(rem_info->plane); i++) {
> > +               unsigned int alignment_pad = 0;
> > +
> > +               if (rem_info->plane_alignment)
> > +                       alignment_pad = ALIGN(gtt_offset, rem_info->plane_alignment) - gtt_offset;
> > +
> > +               sg = remap_pages(obj,
> > +                                rem_info->plane[i].offset, alignment_pad,
> > +                                rem_info->plane[i].width, rem_info->plane[i].height,
> > +                                rem_info->plane[i].src_stride, rem_info->plane[i].dst_stride,
> > +                                st, sg);
> > +
> > +               gtt_offset += alignment_pad +
> > +                             rem_info->plane[i].dst_stride * rem_info->plane[i].height;
> > +       }
> > +
> > +       i915_sg_trim(st);
> > +
> > +       return st;
> > +
> > +err_sg_alloc:
> > +       kfree(st);
> > +err_st_alloc:
> > +
> > +       drm_dbg(&i915->drm, "Failed to create remapped mapping for object size %zu! (%ux%u tiles, %u pages)\n",
> > +               obj->base.size, rem_info->plane[0].width,
> > +               rem_info->plane[0].height, size);
> > +
> > +       return ERR_PTR(ret);
> > +}
> > +
> > +static noinline struct sg_table *
> > +intel_partial_pages(const struct i915_ggtt_view *view,
> > +                   struct drm_i915_gem_object *obj)
> > +{
> > +       struct sg_table *st;
> > +       struct scatterlist *sg, *iter;
> > +       unsigned int count = view->partial.size;
> > +       unsigned int offset;
> > +       int ret = -ENOMEM;
> > +
> > +       st = kmalloc(sizeof(*st), GFP_KERNEL);
> > +       if (!st)
> > +               goto err_st_alloc;
> > +
> > +       ret = sg_alloc_table(st, count, GFP_KERNEL);
> > +       if (ret)
> > +               goto err_sg_alloc;
> > +
> > +       iter = i915_gem_object_get_sg_dma(obj, view->partial.offset, &offset);
> > +       GEM_BUG_ON(!iter);
> > +
> > +       sg = st->sgl;
> > +       st->nents = 0;
> > +       do {
> > +               unsigned int len;
> > +
> > +               len = min(sg_dma_len(iter) - (offset << PAGE_SHIFT),
> > +                         count << PAGE_SHIFT);
> > +               sg_set_page(sg, NULL, len, 0);
> > +               sg_dma_address(sg) =
> > +                       sg_dma_address(iter) + (offset << PAGE_SHIFT);
> > +               sg_dma_len(sg) = len;
> > +
> > +               st->nents++;
> > +               count -= len >> PAGE_SHIFT;
> > +               if (count == 0) {
> > +                       sg_mark_end(sg);
> > +                       i915_sg_trim(st); /* Drop any unused tail entries. */
> > +
> > +                       return st;
> > +               }
> > +
> > +               sg = __sg_next(sg);
> > +               iter = __sg_next(iter);
> > +               offset = 0;
> > +       } while (1);
> > +
> > +err_sg_alloc:
> > +       kfree(st);
> > +err_st_alloc:
> > +       return ERR_PTR(ret);
> > +}
> > +
> > +static int
> > +__i915_vma_get_pages(struct i915_vma *vma)
> > +{
> > +       struct sg_table *pages;
> > +       int ret;
> > +
> > +       /*
> > +        * The vma->pages are only valid within the lifespan of the borrowed
> > +        * obj->mm.pages. When the obj->mm.pages sg_table is regenerated, so
> > +        * must be the vma->pages. A simple rule is that vma->pages must only
> > +        * be accessed when the obj->mm.pages are pinned.
> > +        */
> > +       GEM_BUG_ON(!i915_gem_object_has_pinned_pages(vma->obj));
> > +
> > +       switch (vma->ggtt_view.type) {
> > +       default:
> > +               GEM_BUG_ON(vma->ggtt_view.type);
> > +               fallthrough;
> > +       case I915_GGTT_VIEW_NORMAL:
> > +               pages = vma->obj->mm.pages;
> > +               break;
> > +
> > +       case I915_GGTT_VIEW_ROTATED:
> > +               pages =
> > +                       intel_rotate_pages(&vma->ggtt_view.rotated, vma->obj);
> > +               break;
> > +
> > +       case I915_GGTT_VIEW_REMAPPED:
> > +               pages =
> > +                       intel_remap_pages(&vma->ggtt_view.remapped, vma->obj);
> > +               break;
> > +
> > +       case I915_GGTT_VIEW_PARTIAL:
> > +               pages = intel_partial_pages(&vma->ggtt_view, vma->obj);
> > +               break;
> > +       }
> > +
> > +       ret = 0;
> > +       /* gen6 ppgtt doesn't have backing pages, special-case it */
> > +       if (IS_ERR(pages) && pages != ERR_PTR(-ENODEV)) {
>
> Where does this -ENODEV come from? AFAIK for the gen6 thing mm.pages =
> ZERO_SIZE_PTR. Also, just checking, I assume we always hit the
> VIEW_NORMAL for that?
>
> > +               ret = PTR_ERR(pages);
> > +               pages = NULL;
> > +               drm_err(&vma->vm->i915->drm,
> > +                       "Failed to get pages for VMA view type %u (%d)!\n",
> > +                       vma->ggtt_view.type, ret);
>
> Can we just return here?
>
> > +       }
> > +
> > +       pages = xchg(&vma->pages, pages);
> > +
> > +       /* did we race against a put_pages? */
> > +       if (pages && pages != vma->obj->mm.pages) {
> > +               sg_free_table(vma->pages);
> > +               kfree(vma->pages);
> > +       }
>
> What is this race exactly, can we add some more details here please?
> So we can more easily evaluate the lockless trickery here.

Ok, the lockless stuff just gets removed by the end of the series.


More information about the dri-devel mailing list