0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #include "vmwgfx_drv.h"
0029
0030 static int vmw_bo_vm_lookup(struct ttm_device *bdev,
0031 struct drm_file *filp,
0032 unsigned long offset,
0033 unsigned long pages,
0034 struct ttm_buffer_object **p_bo)
0035 {
0036 struct vmw_private *dev_priv = container_of(bdev, struct vmw_private, bdev);
0037 struct drm_device *drm = &dev_priv->drm;
0038 struct drm_vma_offset_node *node;
0039 int ret;
0040
0041 *p_bo = NULL;
0042
0043 drm_vma_offset_lock_lookup(bdev->vma_manager);
0044
0045 node = drm_vma_offset_lookup_locked(bdev->vma_manager, offset, pages);
0046 if (likely(node)) {
0047 *p_bo = container_of(node, struct ttm_buffer_object,
0048 base.vma_node);
0049 *p_bo = ttm_bo_get_unless_zero(*p_bo);
0050 }
0051
0052 drm_vma_offset_unlock_lookup(bdev->vma_manager);
0053
0054 if (!*p_bo) {
0055 drm_err(drm, "Could not find buffer object to map\n");
0056 return -EINVAL;
0057 }
0058
0059 if (!drm_vma_node_is_allowed(node, filp)) {
0060 ret = -EACCES;
0061 goto out_no_access;
0062 }
0063
0064 return 0;
0065 out_no_access:
0066 ttm_bo_put(*p_bo);
0067 return ret;
0068 }
0069
0070 int vmw_mmap(struct file *filp, struct vm_area_struct *vma)
0071 {
0072 static const struct vm_operations_struct vmw_vm_ops = {
0073 .pfn_mkwrite = vmw_bo_vm_mkwrite,
0074 .page_mkwrite = vmw_bo_vm_mkwrite,
0075 .fault = vmw_bo_vm_fault,
0076 .open = ttm_bo_vm_open,
0077 .close = ttm_bo_vm_close,
0078 };
0079 struct drm_file *file_priv = filp->private_data;
0080 struct vmw_private *dev_priv = vmw_priv(file_priv->minor->dev);
0081 struct ttm_device *bdev = &dev_priv->bdev;
0082 struct ttm_buffer_object *bo;
0083 int ret;
0084
0085 if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET_START))
0086 return -EINVAL;
0087
0088 ret = vmw_bo_vm_lookup(bdev, file_priv, vma->vm_pgoff, vma_pages(vma), &bo);
0089 if (unlikely(ret != 0))
0090 return ret;
0091
0092 ret = ttm_bo_mmap_obj(vma, bo);
0093 if (unlikely(ret != 0))
0094 goto out_unref;
0095
0096 vma->vm_ops = &vmw_vm_ops;
0097
0098
0099 if (!is_cow_mapping(vma->vm_flags))
0100 vma->vm_flags = (vma->vm_flags & ~VM_MIXEDMAP) | VM_PFNMAP;
0101
0102 ttm_bo_put(bo);
0103
0104 return 0;
0105
0106 out_unref:
0107 ttm_bo_put(bo);
0108 return ret;
0109 }
0110