int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) { struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); unsigned asize = amdgpu_bo_size(bo); int ret; if (!vma->vm_file) return -ENODEV; if (adev == NULL) return -ENODEV; /* Check for valid size. */ if (asize < vma->vm_end - vma->vm_start) return -EINVAL; if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) || (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)) { return -EPERM; } vma->vm_pgoff += amdgpu_bo_mmap_offset(bo) >> PAGE_SHIFT; /* prime mmap does not need to check access, so allow here */ ret = drm_vma_node_allow(&obj->vma_node, vma->vm_file->private_data); if (ret) return ret; ret = ttm_bo_mmap(vma->vm_file, vma, &adev->mman.bdev); drm_vma_node_revoke(&obj->vma_node, vma->vm_file->private_data); return ret; }
/** * drm_gem_handle_create_tail - internal functions to create a handle * @file_priv: drm file-private structure to register the handle for * @obj: object to register * @handlep: pointer to return the created handle to the caller * * This expects the dev->object_name_lock to be held already and will drop it * before returning. Used to avoid races in establishing new handles when * importing an object from either an flink name or a dma-buf. */ int drm_gem_handle_create_tail(struct drm_file *file_priv, struct drm_gem_object *obj, u32 *handlep) { struct drm_device *dev = obj->dev; int ret; WARN_ON(!mutex_is_locked(&dev->object_name_lock)); /* * Get the user-visible handle using idr. Preload and perform * allocation under our spinlock. */ idr_preload(GFP_KERNEL); spin_lock(&file_priv->table_lock); ret = idr_alloc(&file_priv->object_idr, obj, 1, 0, GFP_NOWAIT); drm_gem_object_reference(obj); obj->handle_count++; spin_unlock(&file_priv->table_lock); idr_preload_end(); mutex_unlock(&dev->object_name_lock); if (ret < 0) { drm_gem_object_handle_unreference_unlocked(obj); return ret; } *handlep = ret; ret = drm_vma_node_allow(&obj->vma_node, file_priv->filp); if (ret) { drm_gem_handle_delete(file_priv, *handlep); return ret; } if (dev->driver->gem_open_object) { ret = dev->driver->gem_open_object(obj, file_priv); if (ret) { drm_gem_handle_delete(file_priv, *handlep); return ret; } } return 0; }