diff options
author | Jérôme Glisse <jglisse@redhat.com> | 2017-08-03 19:19:56 -0400 |
---|---|---|
committer | Jérôme Glisse <jglisse@redhat.com> | 2017-08-29 10:35:01 -0400 |
commit | a3cb1db3b4fbcab074ab98b3e9e07624abd5d65d (patch) | |
tree | 1fa8a4856ec07af9202772c042e58fcc4b05430f /drivers/gpu/drm | |
parent | 22ec8ae4d72daabc574b0400848dbff1a9abe698 (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>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/nouveau/compote/compote-driver.c | 28 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/compote/compote-memory.c | 90 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/compote/compote.h | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bo.c | 4 |
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); } |