Re: [PATCH v4 15/15] drm/i915: Use ttm mmap handling for ttm bo's.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Op 2021-05-26 om 19:40 schreef Thomas Hellström:
>
> On 5/26/21 1:32 PM, Thomas Hellström wrote:
>> From: Maarten Lankhorst <maarten.lankhorst@xxxxxxxxxxxxxxx>
>>
>> Use the ttm handlers for servicing page faults, and vm_access.
>>
>> We do our own validation of read-only access, otherwise use the
>> ttm handlers as much as possible.
>>
>> Because the ttm handlers expect the vma_node at vma->base, we slightly
>> need to massage the mmap handlers to look at vma_node->driver_private
>> to fetch the bo, if it's NULL, we assume i915's normal mmap_offset uapi
>> is used.
>>
>> This is the easiest way to achieve compatibility without changing ttm's
>> semantics.
>>
>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@xxxxxxxxxxxxxxx>
>> ---
>>   drivers/gpu/drm/i915/gem/i915_gem_mman.c      |  78 +++++++----
>>   drivers/gpu/drm/i915/gem/i915_gem_object.h    |   6 +-
>>   .../gpu/drm/i915/gem/i915_gem_object_types.h  |   3 +
>>   drivers/gpu/drm/i915/gem/i915_gem_pages.c     |   3 +-
>>   drivers/gpu/drm/i915/gem/i915_gem_ttm.c       | 122 +++++++++++++++++-
>>   .../drm/i915/gem/selftests/i915_gem_mman.c    |  90 +++++++------
>>   drivers/gpu/drm/i915/selftests/igt_mmap.c     |  25 +++-
>>   drivers/gpu/drm/i915/selftests/igt_mmap.h     |  12 +-
>>   8 files changed, 247 insertions(+), 92 deletions(-)
>
> There are a couple of checkpatch.pl --strict warnings/checks with this patch.
>
>
>>
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
>> index fd1c9714f8d8..af04ea593091 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
>> @@ -19,6 +19,7 @@
>>   #include "i915_gem_mman.h"
>>   #include "i915_trace.h"
>>   #include "i915_user_extensions.h"
>> +#include "i915_gem_ttm.h"
>>   #include "i915_vma.h"
>>     static inline bool
>> @@ -622,6 +623,8 @@ mmap_offset_attach(struct drm_i915_gem_object *obj,
>>       struct i915_mmap_offset *mmo;
>>       int err;
>>   +    GEM_BUG_ON(obj->ops->mmap_offset || obj->ops->mmap_ops);
>> +
>>       mmo = lookup_mmo(obj, mmap_type);
>>       if (mmo)
>>           goto out;
>> @@ -664,40 +667,47 @@ mmap_offset_attach(struct drm_i915_gem_object *obj,
>>   }
>>     static int
>> -__assign_mmap_offset(struct drm_file *file,
>> -             u32 handle,
>> +__assign_mmap_offset(struct drm_i915_gem_object *obj,
>>                enum i915_mmap_type mmap_type,
>> -             u64 *offset)
>> +             u64 *offset, struct drm_file *file)
>>   {
>> -    struct drm_i915_gem_object *obj;
>>       struct i915_mmap_offset *mmo;
>> -    int err;
>>   -    obj = i915_gem_object_lookup(file, handle);
>> -    if (!obj)
>> -        return -ENOENT;
>> +    if (i915_gem_object_never_mmap(obj))
>> +        return -ENODEV;
>>   -    if (i915_gem_object_never_mmap(obj)) {
>> -        err = -ENODEV;
>> -        goto out;
>> +    if (obj->ops->mmap_offset)  {
>> +        *offset = obj->ops->mmap_offset(obj);
>> +        return 0;
>>       }
>>         if (mmap_type != I915_MMAP_TYPE_GTT &&
>>           !i915_gem_object_has_struct_page(obj) &&
>> -        !i915_gem_object_type_has(obj, I915_GEM_OBJECT_HAS_IOMEM)) {
>> -        err = -ENODEV;
>> -        goto out;
>> -    }
>> +        !i915_gem_object_type_has(obj, I915_GEM_OBJECT_HAS_IOMEM))
>> +        return -ENODEV;
>>         mmo = mmap_offset_attach(obj, mmap_type, file);
>> -    if (IS_ERR(mmo)) {
>> -        err = PTR_ERR(mmo);
>> -        goto out;
>> -    }
>> +    if (IS_ERR(mmo))
>> +        return PTR_ERR(mmo);
>>         *offset = drm_vma_node_offset_addr(&mmo->vma_node);
>> -    err = 0;
>> -out:
>> +    return 0;
>> +}
>> +
>> +static int
>> +__assign_mmap_offset_handle(struct drm_file *file,
>> +                u32 handle,
>> +                enum i915_mmap_type mmap_type,
>> +                u64 *offset)
>> +{
>> +    struct drm_i915_gem_object *obj;
>> +    int err;
>> +
>> +    obj = i915_gem_object_lookup(file, handle);
>> +    if (!obj)
>> +        return -ENOENT;
>> +
>> +    err = __assign_mmap_offset(obj, mmap_type, offset, file);
>>       i915_gem_object_put(obj);
>>       return err;
>>   }
>> @@ -717,7 +727,7 @@ i915_gem_dumb_mmap_offset(struct drm_file *file,
>>       else
>>           mmap_type = I915_MMAP_TYPE_GTT;
>>   -    return __assign_mmap_offset(file, handle, mmap_type, offset);
>> +    return __assign_mmap_offset_handle(file, handle, mmap_type, offset);
>>   }
>>     /**
>> @@ -785,7 +795,7 @@ i915_gem_mmap_offset_ioctl(struct drm_device *dev, void *data,
>>           return -EINVAL;
>>       }
>>   -    return __assign_mmap_offset(file, args->handle, type, &args->offset);
>> +    return __assign_mmap_offset_handle(file, args->handle, type, &args->offset);
>>   }
>>     static void vm_open(struct vm_area_struct *vma)
>> @@ -889,8 +899,16 @@ int i915_gem_mmap(struct file *filp, struct vm_area_struct *vma)
>>            * destroyed and will be invalid when the vma manager lock
>>            * is released.
>>            */
>> -        mmo = container_of(node, struct i915_mmap_offset, vma_node);
>> -        obj = i915_gem_object_get_rcu(mmo->obj);
>> +        if (!node->driver_private) {
>> +            mmo = container_of(node, struct i915_mmap_offset, vma_node);
>> +            obj = i915_gem_object_get_rcu(mmo->obj);
>> +
>> +            GEM_BUG_ON(obj && obj->ops->mmap_ops);
>> +        } else {
>> +            obj = i915_gem_object_get_rcu(container_of(node, struct drm_i915_gem_object, base.vma_node));
>> +
>> +            GEM_BUG_ON(obj && !obj->ops->mmap_ops);
>> +        }
>>       }
>>       drm_vma_offset_unlock_lookup(dev->vma_offset_manager);
>>       rcu_read_unlock();
>> @@ -912,7 +930,6 @@ int i915_gem_mmap(struct file *filp, struct vm_area_struct *vma)
>>       }
>>         vma->vm_flags |= VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
>> -    vma->vm_private_data = mmo;
>>         /*
>>        * We keep the ref on mmo->obj, not vm_file, but we require
>> @@ -926,6 +943,15 @@ int i915_gem_mmap(struct file *filp, struct vm_area_struct *vma)
>>       /* Drop the initial creation reference, the vma is now holding one. */
>>       fput(anon);
>>   +    if (obj->ops->mmap_ops) {
>> +        vma->vm_page_prot = pgprot_decrypted(vm_get_page_prot(vma->vm_flags));
>> +        vma->vm_ops = obj->ops->mmap_ops;
>> +        vma->vm_private_data = node->driver_private;
>> +        return 0;
>> +    }
>> +
>> +    vma->vm_private_data = mmo;
>> +
>>       switch (mmo->mmap_type) {
>>       case I915_MMAP_TYPE_WC:
>>           vma->vm_page_prot =
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>> index a3ad8cf4eefd..ff59e6c640e6 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
>> @@ -342,14 +342,14 @@ struct scatterlist *
>>   __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
>>                struct i915_gem_object_page_iter *iter,
>>                unsigned int n,
>> -             unsigned int *offset, bool allow_alloc);
>> +             unsigned int *offset, bool allow_alloc, bool dma);
>>     static inline struct scatterlist *
>>   i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
>>                  unsigned int n,
>>                  unsigned int *offset, bool allow_alloc)
>>   {
>> -    return __i915_gem_object_get_sg(obj, &obj->mm.get_page, n, offset, allow_alloc);
>> +    return __i915_gem_object_get_sg(obj, &obj->mm.get_page, n, offset, allow_alloc, false);
>>   }
>>     static inline struct scatterlist *
>> @@ -357,7 +357,7 @@ i915_gem_object_get_sg_dma(struct drm_i915_gem_object *obj,
>>                  unsigned int n,
>>                  unsigned int *offset, bool allow_alloc)
>>   {
>> -    return __i915_gem_object_get_sg(obj, &obj->mm.get_dma_page, n, offset, allow_alloc);
>> +    return __i915_gem_object_get_sg(obj, &obj->mm.get_dma_page, n, offset, allow_alloc, true);
>>   }
>>     struct page *
>> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>> index 68313474e6a6..2a23b77424b3 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
>> @@ -61,6 +61,7 @@ struct drm_i915_gem_object_ops {
>>                const struct drm_i915_gem_pread *arg);
>>       int (*pwrite)(struct drm_i915_gem_object *obj,
>>                 const struct drm_i915_gem_pwrite *arg);
>> +    u64 (*mmap_offset)(struct drm_i915_gem_object *obj);
>>         int (*dmabuf_export)(struct drm_i915_gem_object *obj);
>>   @@ -79,6 +80,7 @@ struct drm_i915_gem_object_ops {
>>       void (*delayed_free)(struct drm_i915_gem_object *obj);
>>       void (*release)(struct drm_i915_gem_object *obj);
>>   +    const struct vm_operations_struct *mmap_ops;
>>       const char *name; /* friendly name for debug, e.g. lockdep classes */
>>   };
>>   @@ -328,6 +330,7 @@ struct drm_i915_gem_object {
>>         struct {
>>           struct sg_table *cached_io_st;
>> +        struct i915_gem_object_page_iter get_io_page;
>>           bool created:1;
>>       } ttm;
>>   diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
>> index 6444e097016d..086005c1c7ea 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
>> @@ -467,9 +467,8 @@ __i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
>>                struct i915_gem_object_page_iter *iter,
>>                unsigned int n,
>>                unsigned int *offset,
>> -             bool allow_alloc)
>> +             bool allow_alloc, bool dma)
>>   {
>> -    const bool dma = iter == &obj->mm.get_dma_page;
>>       struct scatterlist *sg;
>>       unsigned int idx, count;
>>   diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>> index 17598930a99e..d0be957326e0 100644
>> --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>> +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
>> @@ -13,6 +13,7 @@
>>   #include "gem/i915_gem_object.h"
>>   #include "gem/i915_gem_region.h"
>>   #include "gem/i915_gem_ttm.h"
>> +#include "gem/i915_gem_mman.h"
>>     #define I915_PL_LMEM0 TTM_PL_PRIV
>>   #define I915_PL_SYSTEM TTM_PL_SYSTEM
>> @@ -158,11 +159,20 @@ static int i915_ttm_move_notify(struct ttm_buffer_object *bo)
>>     static void i915_ttm_free_cached_io_st(struct drm_i915_gem_object *obj)
>>   {
>> -    if (obj->ttm.cached_io_st) {
>> -        sg_free_table(obj->ttm.cached_io_st);
>> -        kfree(obj->ttm.cached_io_st);
>> -        obj->ttm.cached_io_st = NULL;
>> -    }
>> +    struct radix_tree_iter iter;
>> +    void __rcu **slot;
>> +
>> +    if (!obj->ttm.cached_io_st)
>> +        return;
>> +
>> +    rcu_read_lock();
>> +    radix_tree_for_each_slot(slot, &obj->ttm.get_io_page.radix, &iter, 0)
>> +        radix_tree_delete(&obj->ttm.get_io_page.radix, iter.index);
>> +    rcu_read_unlock();
>> +
>> +    sg_free_table(obj->ttm.cached_io_st);
>> +    kfree(obj->ttm.cached_io_st);
>> +    obj->ttm.cached_io_st = NULL;
>>   }
>>     static void i915_ttm_purge(struct drm_i915_gem_object *obj)
>> @@ -338,12 +348,42 @@ static int i915_ttm_move(struct ttm_buffer_object *bo, bool evict,
>>       ttm_bo_move_sync_cleanup(bo, dst_mem);
>>       i915_ttm_free_cached_io_st(obj);
>>   -    if (!dst_man->use_tt)
>> +    if (!dst_man->use_tt) {
>>           obj->ttm.cached_io_st = dst_st;
>> +        obj->ttm.get_io_page.sg_pos = dst_st->sgl;
>> +        obj->ttm.get_io_page.sg_idx = 0;
>> +    }
>>         return 0;
>>   }
>>   +static int i915_ttm_io_mem_reserve(struct ttm_device *bdev, struct ttm_resource *mem)
>> +{
>> +    if (mem->mem_type < I915_PL_LMEM0)
>> +        return 0;
>> +
>> +    /* We may need to revisit this later, but this allows all caching to be used in mmap */
>> +    mem->bus.caching = ttm_cached;
>
> Since we're now using the TTM bo offsets, we might as well just make this ttm_write_combined now.

Correct. That would be the correct value. TTM will use the correct caching that way.

~Maarten




[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux