diff options
author | Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> | 2013-04-16 08:14:52 -0400 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> | 2013-06-08 03:14:03 -0400 |
commit | 1c5aafa6eee2d5712f774676d407e5ab6dae9a1b (patch) | |
tree | 5cb8d947cca86c336977ad86a5e0f76eac0e0533 /drivers/gpu/drm/drm_gem.c | |
parent | 328a4719b6a0930721b5f8d5c69993d3b6e3913f (diff) |
drm/gem: Split drm_gem_mmap() into object search and object mapping
The drm_gem_mmap() function first finds the GEM object to be mapped
based on the fake mmap offset and then maps the object. Split the object
mapping code into a standalone drm_gem_mmap_obj() function that can be
used to implement dma-buf mmap() operations.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Rob Clark <robdclark@gmail.com>
Diffstat (limited to 'drivers/gpu/drm/drm_gem.c')
-rw-r--r-- | drivers/gpu/drm/drm_gem.c | 83 |
1 files changed, 52 insertions, 31 deletions
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index cf919e36e8ae..43217138816d 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c | |||
@@ -644,6 +644,55 @@ void drm_gem_vm_close(struct vm_area_struct *vma) | |||
644 | } | 644 | } |
645 | EXPORT_SYMBOL(drm_gem_vm_close); | 645 | EXPORT_SYMBOL(drm_gem_vm_close); |
646 | 646 | ||
647 | /** | ||
648 | * drm_gem_mmap_obj - memory map a GEM object | ||
649 | * @obj: the GEM object to map | ||
650 | * @obj_size: the object size to be mapped, in bytes | ||
651 | * @vma: VMA for the area to be mapped | ||
652 | * | ||
653 | * Set up the VMA to prepare mapping of the GEM object using the gem_vm_ops | ||
654 | * provided by the driver. Depending on their requirements, drivers can either | ||
655 | * provide a fault handler in their gem_vm_ops (in which case any accesses to | ||
656 | * the object will be trapped, to perform migration, GTT binding, surface | ||
657 | * register allocation, or performance monitoring), or mmap the buffer memory | ||
658 | * synchronously after calling drm_gem_mmap_obj. | ||
659 | * | ||
660 | * This function is mainly intended to implement the DMABUF mmap operation, when | ||
661 | * the GEM object is not looked up based on its fake offset. To implement the | ||
662 | * DRM mmap operation, drivers should use the drm_gem_mmap() function. | ||
663 | * | ||
664 | * Return 0 or success or -EINVAL if the object size is smaller than the VMA | ||
665 | * size, or if no gem_vm_ops are provided. | ||
666 | */ | ||
667 | int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size, | ||
668 | struct vm_area_struct *vma) | ||
669 | { | ||
670 | struct drm_device *dev = obj->dev; | ||
671 | |||
672 | /* Check for valid size. */ | ||
673 | if (obj_size < vma->vm_end - vma->vm_start) | ||
674 | return -EINVAL; | ||
675 | |||
676 | if (!dev->driver->gem_vm_ops) | ||
677 | return -EINVAL; | ||
678 | |||
679 | vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP; | ||
680 | vma->vm_ops = dev->driver->gem_vm_ops; | ||
681 | vma->vm_private_data = obj; | ||
682 | vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); | ||
683 | |||
684 | /* Take a ref for this mapping of the object, so that the fault | ||
685 | * handler can dereference the mmap offset's pointer to the object. | ||
686 | * This reference is cleaned up by the corresponding vm_close | ||
687 | * (which should happen whether the vma was created by this call, or | ||
688 | * by a vm_open due to mremap or partial unmap or whatever). | ||
689 | */ | ||
690 | drm_gem_object_reference(obj); | ||
691 | |||
692 | drm_vm_open_locked(dev, vma); | ||
693 | return 0; | ||
694 | } | ||
695 | EXPORT_SYMBOL(drm_gem_mmap_obj); | ||
647 | 696 | ||
648 | /** | 697 | /** |
649 | * drm_gem_mmap - memory map routine for GEM objects | 698 | * drm_gem_mmap - memory map routine for GEM objects |
@@ -653,11 +702,9 @@ EXPORT_SYMBOL(drm_gem_vm_close); | |||
653 | * If a driver supports GEM object mapping, mmap calls on the DRM file | 702 | * If a driver supports GEM object mapping, mmap calls on the DRM file |
654 | * descriptor will end up here. | 703 | * descriptor will end up here. |
655 | * | 704 | * |
656 | * If we find the object based on the offset passed in (vma->vm_pgoff will | 705 | * Look up the GEM object based on the offset passed in (vma->vm_pgoff will |
657 | * contain the fake offset we created when the GTT map ioctl was called on | 706 | * contain the fake offset we created when the GTT map ioctl was called on |
658 | * the object), we set up the driver fault handler so that any accesses | 707 | * the object) and map it with a call to drm_gem_mmap_obj(). |
659 | * to the object can be trapped, to perform migration, GTT binding, surface | ||
660 | * register allocation, or performance monitoring. | ||
661 | */ | 708 | */ |
662 | int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) | 709 | int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) |
663 | { | 710 | { |
@@ -665,7 +712,6 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) | |||
665 | struct drm_device *dev = priv->minor->dev; | 712 | struct drm_device *dev = priv->minor->dev; |
666 | struct drm_gem_mm *mm = dev->mm_private; | 713 | struct drm_gem_mm *mm = dev->mm_private; |
667 | struct drm_local_map *map = NULL; | 714 | struct drm_local_map *map = NULL; |
668 | struct drm_gem_object *obj; | ||
669 | struct drm_hash_item *hash; | 715 | struct drm_hash_item *hash; |
670 | int ret = 0; | 716 | int ret = 0; |
671 | 717 | ||
@@ -686,32 +732,7 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) | |||
686 | goto out_unlock; | 732 | goto out_unlock; |
687 | } | 733 | } |
688 | 734 | ||
689 | /* Check for valid size. */ | 735 | ret = drm_gem_mmap_obj(map->handle, map->size, vma); |
690 | if (map->size < vma->vm_end - vma->vm_start) { | ||
691 | ret = -EINVAL; | ||
692 | goto out_unlock; | ||
693 | } | ||
694 | |||
695 | obj = map->handle; | ||
696 | if (!obj->dev->driver->gem_vm_ops) { | ||
697 | ret = -EINVAL; | ||
698 | goto out_unlock; | ||
699 | } | ||
700 | |||
701 | vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP; | ||
702 | vma->vm_ops = obj->dev->driver->gem_vm_ops; | ||
703 | vma->vm_private_data = map->handle; | ||
704 | vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); | ||
705 | |||
706 | /* Take a ref for this mapping of the object, so that the fault | ||
707 | * handler can dereference the mmap offset's pointer to the object. | ||
708 | * This reference is cleaned up by the corresponding vm_close | ||
709 | * (which should happen whether the vma was created by this call, or | ||
710 | * by a vm_open due to mremap or partial unmap or whatever). | ||
711 | */ | ||
712 | drm_gem_object_reference(obj); | ||
713 | |||
714 | drm_vm_open_locked(dev, vma); | ||
715 | 736 | ||
716 | out_unlock: | 737 | out_unlock: |
717 | mutex_unlock(&dev->struct_mutex); | 738 | mutex_unlock(&dev->struct_mutex); |