Skip to content

Commit

Permalink
drm/i915: Use ttm mmap handling for ttm bo's.
Browse files Browse the repository at this point in the history
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@linux.intel.com>
Reviewed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210610070152.572423-5-thomas.hellstrom@linux.intel.com
  • Loading branch information
Maarten Lankhorst committed Jun 11, 2021
1 parent f425821 commit cf3e3e8
Show file tree
Hide file tree
Showing 8 changed files with 251 additions and 92 deletions.
83 changes: 57 additions & 26 deletions drivers/gpu/drm/i915/gem/i915_gem_mman.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -623,6 +624,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;
Expand Down Expand Up @@ -665,40 +668,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;
}
Expand All @@ -718,7 +728,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);
}

/**
Expand Down Expand Up @@ -786,7 +796,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)
Expand Down Expand Up @@ -890,8 +900,18 @@ 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();
Expand All @@ -913,7 +933,9 @@ 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;

if (i915_gem_object_has_iomem(obj))
vma->vm_flags |= VM_IO;

/*
* We keep the ref on mmo->obj, not vm_file, but we require
Expand All @@ -927,6 +949,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 =
Expand Down
6 changes: 3 additions & 3 deletions drivers/gpu/drm/i915/gem/i915_gem_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -342,22 +342,22 @@ 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 *
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 *
Expand Down
3 changes: 3 additions & 0 deletions drivers/gpu/drm/i915/gem/i915_gem_object_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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 */
};

Expand Down Expand Up @@ -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;

Expand Down
3 changes: 1 addition & 2 deletions drivers/gpu/drm/i915/gem/i915_gem_pages.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Loading

0 comments on commit cf3e3e8

Please sign in to comment.