summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/compote/compote-memory.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/compote/compote-memory.c')
-rw-r--r--drivers/gpu/drm/nouveau/compote/compote-memory.c90
1 files changed, 88 insertions, 2 deletions
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;
+}