[PATCH v2 1/5] drm/gem: Split drm_gem_mmap() into object search and object mapping

Rob Clark robdclark at gmail.com
Tue Jun 4 04:33:07 PDT 2013


On Mon, Jun 3, 2013 at 10:20 PM, Laurent Pinchart
<laurent.pinchart+renesas at ideasonboard.com> wrote:
> 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 at ideasonboard.com>

Cool, thanks.. this was an old TODO of mine that I apparently forgot about :-)

Reviewed-by: Rob Clark <robdclark at gmail.com>

> ---
>  drivers/gpu/drm/drm_gem.c | 83 +++++++++++++++++++++++++++++------------------
>  include/drm/drmP.h        |  2 ++
>  2 files changed, 54 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
> index cf919e3..4321713 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)
>  }
>  EXPORT_SYMBOL(drm_gem_vm_close);
>
> +/**
> + * drm_gem_mmap_obj - memory map a GEM object
> + * @obj: the GEM object to map
> + * @obj_size: the object size to be mapped, in bytes
> + * @vma: VMA for the area to be mapped
> + *
> + * Set up the VMA to prepare mapping of the GEM object using the gem_vm_ops
> + * provided by the driver. Depending on their requirements, drivers can either
> + * provide a fault handler in their gem_vm_ops (in which case any accesses to
> + * the object will be trapped, to perform migration, GTT binding, surface
> + * register allocation, or performance monitoring), or mmap the buffer memory
> + * synchronously after calling drm_gem_mmap_obj.
> + *
> + * This function is mainly intended to implement the DMABUF mmap operation, when
> + * the GEM object is not looked up based on its fake offset. To implement the
> + * DRM mmap operation, drivers should use the drm_gem_mmap() function.
> + *
> + * Return 0 or success or -EINVAL if the object size is smaller than the VMA
> + * size, or if no gem_vm_ops are provided.
> + */
> +int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size,
> +                    struct vm_area_struct *vma)
> +{
> +       struct drm_device *dev = obj->dev;
> +
> +       /* Check for valid size. */
> +       if (obj_size < vma->vm_end - vma->vm_start)
> +               return -EINVAL;
> +
> +       if (!dev->driver->gem_vm_ops)
> +               return -EINVAL;
> +
> +       vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
> +       vma->vm_ops = dev->driver->gem_vm_ops;
> +       vma->vm_private_data = obj;
> +       vma->vm_page_prot =  pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
> +
> +       /* Take a ref for this mapping of the object, so that the fault
> +        * handler can dereference the mmap offset's pointer to the object.
> +        * This reference is cleaned up by the corresponding vm_close
> +        * (which should happen whether the vma was created by this call, or
> +        * by a vm_open due to mremap or partial unmap or whatever).
> +        */
> +       drm_gem_object_reference(obj);
> +
> +       drm_vm_open_locked(dev, vma);
> +       return 0;
> +}
> +EXPORT_SYMBOL(drm_gem_mmap_obj);
>
>  /**
>   * drm_gem_mmap - memory map routine for GEM objects
> @@ -653,11 +702,9 @@ EXPORT_SYMBOL(drm_gem_vm_close);
>   * If a driver supports GEM object mapping, mmap calls on the DRM file
>   * descriptor will end up here.
>   *
> - * If we find the object based on the offset passed in (vma->vm_pgoff will
> + * Look up the GEM object based on the offset passed in (vma->vm_pgoff will
>   * contain the fake offset we created when the GTT map ioctl was called on
> - * the object), we set up the driver fault handler so that any accesses
> - * to the object can be trapped, to perform migration, GTT binding, surface
> - * register allocation, or performance monitoring.
> + * the object) and map it with a call to drm_gem_mmap_obj().
>   */
>  int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
>  {
> @@ -665,7 +712,6 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
>         struct drm_device *dev = priv->minor->dev;
>         struct drm_gem_mm *mm = dev->mm_private;
>         struct drm_local_map *map = NULL;
> -       struct drm_gem_object *obj;
>         struct drm_hash_item *hash;
>         int ret = 0;
>
> @@ -686,32 +732,7 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
>                 goto out_unlock;
>         }
>
> -       /* Check for valid size. */
> -       if (map->size < vma->vm_end - vma->vm_start) {
> -               ret = -EINVAL;
> -               goto out_unlock;
> -       }
> -
> -       obj = map->handle;
> -       if (!obj->dev->driver->gem_vm_ops) {
> -               ret = -EINVAL;
> -               goto out_unlock;
> -       }
> -
> -       vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
> -       vma->vm_ops = obj->dev->driver->gem_vm_ops;
> -       vma->vm_private_data = map->handle;
> -       vma->vm_page_prot =  pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
> -
> -       /* Take a ref for this mapping of the object, so that the fault
> -        * handler can dereference the mmap offset's pointer to the object.
> -        * This reference is cleaned up by the corresponding vm_close
> -        * (which should happen whether the vma was created by this call, or
> -        * by a vm_open due to mremap or partial unmap or whatever).
> -        */
> -       drm_gem_object_reference(obj);
> -
> -       drm_vm_open_locked(dev, vma);
> +       ret = drm_gem_mmap_obj(map->handle, map->size, vma);
>
>  out_unlock:
>         mutex_unlock(&dev->struct_mutex);
> diff --git a/include/drm/drmP.h b/include/drm/drmP.h
> index b06f5af..79fb4c7 100644
> --- a/include/drm/drmP.h
> +++ b/include/drm/drmP.h
> @@ -1616,6 +1616,8 @@ int drm_gem_private_object_init(struct drm_device *dev,
>  void drm_gem_object_handle_free(struct drm_gem_object *obj);
>  void drm_gem_vm_open(struct vm_area_struct *vma);
>  void drm_gem_vm_close(struct vm_area_struct *vma);
> +int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size,
> +                    struct vm_area_struct *vma);
>  int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
>
>  #include <drm/drm_global.h>
> --
> 1.8.1.5
>


More information about the dri-devel mailing list