Rev 6937 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 6937 | Rev 7144 | ||
---|---|---|---|
Line 785... | Line 785... | ||
785 | if (dev->driver->gem_free_object != NULL) |
785 | if (dev->driver->gem_free_object != NULL) |
786 | dev->driver->gem_free_object(obj); |
786 | dev->driver->gem_free_object(obj); |
787 | } |
787 | } |
788 | EXPORT_SYMBOL(drm_gem_object_free); |
788 | EXPORT_SYMBOL(drm_gem_object_free); |
Line -... | Line 789... | ||
- | 789 | ||
- | 790 | /** |
|
- | 791 | * drm_gem_vm_open - vma->ops->open implementation for GEM |
|
789 | 792 | * @vma: VM area structure |
|
- | 793 | * |
|
- | 794 | * This function implements the #vm_operations_struct open() callback for GEM |
|
- | 795 | * drivers. This must be used together with drm_gem_vm_close(). |
|
790 | 796 | */ |
|
791 | #if 0 |
797 | #if 0 |
792 | void drm_gem_vm_open(struct vm_area_struct *vma) |
798 | void drm_gem_vm_open(struct vm_area_struct *vma) |
793 | { |
799 | { |
Line 794... | Line 800... | ||
794 | struct drm_gem_object *obj = vma->vm_private_data; |
800 | struct drm_gem_object *obj = vma->vm_private_data; |
795 | 801 | ||
796 | drm_gem_object_reference(obj); |
802 | drm_gem_object_reference(obj); |
Line -... | Line 803... | ||
- | 803 | } |
|
- | 804 | EXPORT_SYMBOL(drm_gem_vm_open); |
|
- | 805 | ||
- | 806 | /** |
|
- | 807 | * drm_gem_vm_close - vma->ops->close implementation for GEM |
|
- | 808 | * @vma: VM area structure |
|
- | 809 | * |
|
797 | } |
810 | * This function implements the #vm_operations_struct close() callback for GEM |
798 | EXPORT_SYMBOL(drm_gem_vm_open); |
811 | * drivers. This must be used together with drm_gem_vm_open(). |
799 | 812 | */ |
|
800 | void drm_gem_vm_close(struct vm_area_struct *vma) |
- | |
Line 801... | Line -... | ||
801 | { |
- | |
802 | struct drm_gem_object *obj = vma->vm_private_data; |
- | |
803 | struct drm_device *dev = obj->dev; |
813 | void drm_gem_vm_close(struct vm_area_struct *vma) |
804 | - | ||
805 | mutex_lock(&dev->struct_mutex); |
814 | { |
806 | drm_vm_close_locked(obj->dev, vma); |
815 | struct drm_gem_object *obj = vma->vm_private_data; |
Line -... | Line 816... | ||
- | 816 | ||
- | 817 | drm_gem_object_unreference_unlocked(obj); |
|
- | 818 | } |
|
- | 819 | EXPORT_SYMBOL(drm_gem_vm_close); |
|
- | 820 | ||
- | 821 | /** |
|
- | 822 | * drm_gem_mmap_obj - memory map a GEM object |
|
- | 823 | * @obj: the GEM object to map |
|
- | 824 | * @obj_size: the object size to be mapped, in bytes |
|
- | 825 | * @vma: VMA for the area to be mapped |
|
- | 826 | * |
|
- | 827 | * Set up the VMA to prepare mapping of the GEM object using the gem_vm_ops |
|
- | 828 | * provided by the driver. Depending on their requirements, drivers can either |
|
- | 829 | * provide a fault handler in their gem_vm_ops (in which case any accesses to |
|
- | 830 | * the object will be trapped, to perform migration, GTT binding, surface |
|
- | 831 | * register allocation, or performance monitoring), or mmap the buffer memory |
|
- | 832 | * synchronously after calling drm_gem_mmap_obj. |
|
- | 833 | * |
|
- | 834 | * This function is mainly intended to implement the DMABUF mmap operation, when |
|
- | 835 | * the GEM object is not looked up based on its fake offset. To implement the |
|
- | 836 | * DRM mmap operation, drivers should use the drm_gem_mmap() function. |
|
- | 837 | * |
|
- | 838 | * drm_gem_mmap_obj() assumes the user is granted access to the buffer while |
|
- | 839 | * drm_gem_mmap() prevents unprivileged users from mapping random objects. So |
|
- | 840 | * callers must verify access restrictions before calling this helper. |
|
- | 841 | * |
|
- | 842 | * Return 0 or success or -EINVAL if the object size is smaller than the VMA |
|
- | 843 | * size, or if no gem_vm_ops are provided. |
|
- | 844 | */ |
|
- | 845 | int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size, |
|
- | 846 | struct vm_area_struct *vma) |
|
- | 847 | { |
|
- | 848 | struct drm_device *dev = obj->dev; |
|
- | 849 | ||
- | 850 | /* Check for valid size. */ |
|
- | 851 | if (obj_size < vma->vm_end - vma->vm_start) |
|
- | 852 | return -EINVAL; |
|
- | 853 | ||
- | 854 | if (!dev->driver->gem_vm_ops) |
|
- | 855 | return -EINVAL; |
|
- | 856 | ||
- | 857 | vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP; |
|
- | 858 | vma->vm_ops = dev->driver->gem_vm_ops; |
|
- | 859 | vma->vm_private_data = obj; |
|
- | 860 | vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); |
|
- | 861 | ||
- | 862 | /* Take a ref for this mapping of the object, so that the fault |
|
- | 863 | * handler can dereference the mmap offset's pointer to the object. |
|
- | 864 | * This reference is cleaned up by the corresponding vm_close |
|
- | 865 | * (which should happen whether the vma was created by this call, or |
|
- | 866 | * by a vm_open due to mremap or partial unmap or whatever). |
|
- | 867 | */ |
|
- | 868 | drm_gem_object_reference(obj); |
|
- | 869 | ||
- | 870 | return 0; |
|
- | 871 | } |
|
- | 872 | EXPORT_SYMBOL(drm_gem_mmap_obj); |
|
- | 873 | ||
- | 874 | /** |
|
- | 875 | * drm_gem_mmap - memory map routine for GEM objects |
|
- | 876 | * @filp: DRM file pointer |
|
- | 877 | * @vma: VMA for the area to be mapped |
|
- | 878 | * |
|
- | 879 | * If a driver supports GEM object mapping, mmap calls on the DRM file |
|
- | 880 | * descriptor will end up here. |
|
- | 881 | * |
|
- | 882 | * Look up the GEM object based on the offset passed in (vma->vm_pgoff will |
|
- | 883 | * contain the fake offset we created when the GTT map ioctl was called on |
|
- | 884 | * the object) and map it with a call to drm_gem_mmap_obj(). |
|
- | 885 | * |
|
- | 886 | * If the caller is not granted access to the buffer object, the mmap will fail |
|
- | 887 | * with EACCES. Please see the vma manager for more information. |
|
- | 888 | */ |
|
- | 889 | int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) |
|
- | 890 | { |
|
- | 891 | struct drm_file *priv = filp->private_data; |
|
- | 892 | struct drm_device *dev = priv->minor->dev; |
|
- | 893 | struct drm_gem_object *obj = NULL; |
|
- | 894 | struct drm_vma_offset_node *node; |
|
- | 895 | int ret; |
|
- | 896 | ||
- | 897 | if (drm_device_is_unplugged(dev)) |
|
- | 898 | return -ENODEV; |
|
- | 899 | ||
- | 900 | drm_vma_offset_lock_lookup(dev->vma_offset_manager); |
|
- | 901 | node = drm_vma_offset_exact_lookup_locked(dev->vma_offset_manager, |
|
- | 902 | vma->vm_pgoff, |
|
- | 903 | vma_pages(vma)); |
|
- | 904 | if (likely(node)) { |
|
- | 905 | obj = container_of(node, struct drm_gem_object, vma_node); |
|
- | 906 | /* |
|
- | 907 | * When the object is being freed, after it hits 0-refcnt it |
|
- | 908 | * proceeds to tear down the object. In the process it will |
|
- | 909 | * attempt to remove the VMA offset and so acquire this |
|
807 | drm_gem_object_unreference(obj); |
910 | * mgr->vm_lock. Therefore if we find an object with a 0-refcnt |
- | 911 | * that matches our range, we know it is in the process of being |
|
- | 912 | * destroyed and will be freed as soon as we release the lock - |
|
- | 913 | * so we have to check for the 0-refcnted object and treat it as |
|
- | 914 | * invalid. |
|
- | 915 | */ |
|
- | 916 | if (!kref_get_unless_zero(&obj->refcount)) |
|
- | 917 | obj = NULL; |
|
- | 918 | } |
|
- | 919 | drm_vma_offset_unlock_lookup(dev->vma_offset_manager); |
|
- | 920 | ||
- | 921 | if (!obj) |
|
- | 922 | return -EINVAL; |
|
Line -... | Line 923... | ||
- | 923 | ||
- | 924 | if (!drm_vma_node_is_allowed(node, filp)) { |
|
Line -... | Line 925... | ||
- | 925 | drm_gem_object_unreference_unlocked(obj); |
|
Line -... | Line 926... | ||
- | 926 | return -EACCES; |
|
- | 927 | } |
|
- | 928 | ||
- | 929 | ret = drm_gem_mmap_obj(obj, drm_vma_node_size(node) << PAGE_SHIFT, |
|
808 | mutex_unlock(&dev->struct_mutex); |
930 | vma); |