summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJérôme Glisse <jglisse@redhat.com>2017-08-03 19:19:56 -0400
committerJérôme Glisse <jglisse@redhat.com>2017-08-29 10:35:01 -0400
commita3cb1db3b4fbcab074ab98b3e9e07624abd5d65d (patch)
tree1fa8a4856ec07af9202772c042e58fcc4b05430f
parent22ec8ae4d72daabc574b0400848dbff1a9abe698 (diff)
drm/nouveau/compote: memory object mmap support
Allow mmap of compote device file to access memory objects. Each memory objects is given a unique range inside the compote device file. Signed-off-by: Jérôme Glisse <jglisse@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/compote/compote-driver.c28
-rw-r--r--drivers/gpu/drm/nouveau/compote/compote-memory.c90
-rw-r--r--drivers/gpu/drm/nouveau/compote/compote.h13
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c4
4 files changed, 133 insertions, 2 deletions
diff --git a/drivers/gpu/drm/nouveau/compote/compote-driver.c b/drivers/gpu/drm/nouveau/compote/compote-driver.c
index 6e05ffc351b3..62b4edd1ca7e 100644
--- a/drivers/gpu/drm/nouveau/compote/compote-driver.c
+++ b/drivers/gpu/drm/nouveau/compote/compote-driver.c
@@ -166,6 +166,31 @@ static int compote_close(struct inode *inode, struct file *file)
return 0;
}
+static ssize_t compote_read(struct file *filp,
+ char __user *buf,
+ size_t count,
+ loff_t *ppos)
+{
+ return -EINVAL;
+}
+
+static int compote_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct compote_file *cfile = file->private_data;
+
+ if (cfile == NULL)
+ return -EINVAL;
+ return compote_mo_mmap(cfile, vma, file);
+}
+
+static ssize_t compote_write(struct file *filp,
+ const char __user *buf,
+ size_t count,
+ loff_t *ppos)
+{
+ return -EINVAL;
+}
+
static long compote_ioctl(struct file *file,
unsigned int cmd,
unsigned long arg)
@@ -200,6 +225,9 @@ static long compote_ioctl(struct file *file,
static const struct file_operations compote_fops = {
.open = compote_open,
+ .read = compote_read,
+ .mmap = compote_mmap,
+ .write = compote_write,
.release = compote_close,
.unlocked_ioctl = compote_ioctl,
.owner = THIS_MODULE,
diff --git a/drivers/gpu/drm/nouveau/compote/compote-memory.c b/drivers/gpu/drm/nouveau/compote/compote-memory.c
index 55fca9092846..8435ec0a8d03 100644
--- a/drivers/gpu/drm/nouveau/compote/compote-memory.c
+++ b/drivers/gpu/drm/nouveau/compote/compote-memory.c
@@ -33,11 +33,12 @@ static struct compote_mo *compote_file_mo_find(struct compote_file *cfile,
uint64_t foffset)
{
struct ttm_bo_device *bdev = &cfile->cdevice->nvdrm->ttm.bdev;
+ unsigned long pgoffset = foffset >> PAGE_SHIFT;
struct drm_vma_offset_node *node;
struct compote_mo *mo = NULL;
drm_vma_offset_lock_lookup(&bdev->vma_manager);
- node = drm_vma_offset_lookup_locked(&bdev->vma_manager, foffset, 1);
+ node = drm_vma_offset_lookup_locked(&bdev->vma_manager, pgoffset, 1);
if (likely(node)) {
struct ttm_buffer_object *bo;
struct nouveau_bo *nvbo;
@@ -66,7 +67,6 @@ static int compote_mo_new(struct compote_mo **mop,
if (mo == NULL)
return -ENOMEM;
-
align = 0;
tile_mode = 0;
tile_flags = 0;
@@ -79,6 +79,7 @@ static int compote_mo_new(struct compote_mo **mop,
mo->cfile = cfile;
mo->nvbo->mo = mo;
kref_init(&mo->kref);
+ INIT_LIST_HEAD(&mo->vas);
mo->npages = PAGE_ALIGN(nbytes);
mo->foffset = drm_vma_node_offset_addr(&mo->nvbo->bo.vma_node);
@@ -150,3 +151,88 @@ long compote_ioctl_mem_free(struct compote_file *cfile, void __user *uarg)
compote_mo_unref(mo);
return 0;
}
+
+static int compote_vm_fault(struct vm_fault *vmf)
+{
+ struct compote_mo_va *mo_va = vmf->vma->vm_private_data;
+ struct ttm_buffer_object *bo;
+ int ret;
+
+ bo = &mo_va->mo->nvbo->bo;
+ vmf->vma->vm_private_data = bo;
+ ret = mo_va->ttm_vm_ops->fault(vmf);
+ vmf->vma->vm_private_data = mo_va;
+
+ return ret;
+}
+
+static void compote_vm_open(struct vm_area_struct *vma)
+{
+ struct compote_mo_va *mo_va = vma->vm_private_data;
+ struct ttm_buffer_object *bo;
+
+ compote_mo_ref(mo_va->mo);
+
+ bo = &mo_va->mo->nvbo->bo;
+ vma->vm_private_data = bo;
+ mo_va->ttm_vm_ops->open(vma);
+ vma->vm_private_data = mo_va;
+}
+
+static void compote_vm_close(struct vm_area_struct *vma)
+{
+ struct compote_mo_va *mo_va = vma->vm_private_data;
+ struct ttm_buffer_object *bo;
+
+ bo = &mo_va->mo->nvbo->bo;
+ vma->vm_private_data = bo;
+ mo_va->ttm_vm_ops->close(vma);
+
+ list_del_init(&mo_va->list);
+ vma->vm_private_data = NULL;
+ compote_mo_unref(mo_va->mo);
+ kfree(mo_va);
+}
+
+static const struct vm_operations_struct compote_vm_ops = {
+ .fault = compote_vm_fault,
+ .open = compote_vm_open,
+ .close = compote_vm_close
+};
+
+int compote_mo_mmap(struct compote_file *cfile,
+ struct vm_area_struct *vma,
+ struct file *file)
+{
+ struct ttm_bo_device *bdev = &cfile->cdevice->nvdrm->ttm.bdev;
+ struct compote_mo_va *mo_va;
+ struct compote_mo *mo;
+ int ret;
+
+ mo = compote_file_mo_find(cfile, vma->vm_pgoff << PAGE_SHIFT);
+ if (mo == NULL)
+ return -EINVAL;
+
+ mo_va = kzalloc(sizeof(*mo_va), GFP_KERNEL);
+ if (mo_va == NULL)
+ return -ENOMEM;
+
+ mo_va->mo = mo;
+ mo_va->start = vma->vm_start;
+ mo_va->end = vma->vm_end;
+ mo_va->pgoffset = vma->vm_pgoff - (mo->foffset >> PAGE_SHIFT);
+
+ ret = ttm_bo_mmap(file, vma, bdev);
+ if (unlikely(ret != 0)) {
+ compote_mo_unref(mo);
+ kfree(mo_va);
+ return ret;
+ }
+
+ list_add_tail(&mo_va->list, &mo->vas);
+ mo_va->ttm_vm_ops = vma->vm_ops;
+ vma->vm_ops = &compote_vm_ops;
+ vma->vm_private_data = mo_va;
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/nouveau/compote/compote.h b/drivers/gpu/drm/nouveau/compote/compote.h
index c0d59960ceef..4d9d2166faf4 100644
--- a/drivers/gpu/drm/nouveau/compote/compote.h
+++ b/drivers/gpu/drm/nouveau/compote/compote.h
@@ -38,15 +38,28 @@ struct compote_file {
struct compote_mo {
struct kref kref;
struct compote_file *cfile;
+ struct list_head vas;
struct nouveau_bo *nvbo;
uint64_t npages;
uint64_t foffset;
};
+struct compote_mo_va {
+ uint64_t start;
+ uint64_t end;
+ uint64_t pgoffset;
+ struct compote_mo *mo;
+ struct list_head list;
+ const struct vm_operations_struct *ttm_vm_ops;
+};
+
long compote_ioctl_mem_alloc(struct compote_file *cfile, void __user *uarg);
long compote_ioctl_mem_free(struct compote_file *cfile, void __user *uarg);
void compote_mo_ref(struct compote_mo *mo);
void compote_mo_unref(struct compote_mo *mo);
+int compote_mo_mmap(struct compote_file *cfile,
+ struct vm_area_struct *vma,
+ struct file *file);
#endif /* COMPOTE_H */
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 3009045cdf46..51762a3764c9 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -1321,6 +1321,10 @@ nouveau_bo_verify_access(struct ttm_buffer_object *bo, struct file *filp)
{
struct nouveau_bo *nvbo = nouveau_bo(bo);
+ /* compote do its own check */
+ if (nvbo->mo)
+ return 0;
+
return drm_vma_node_verify_access(&nvbo->gem.vma_node,
filp->private_data);
}