2019-05-29 07:12:36 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2010-12-15 07:14:24 +10:00
/*
* Copyright ( C ) 2012 Red Hat
*/
2011-12-21 11:23:44 +00:00
# include <linux/dma-buf.h>
2019-07-16 08:42:09 +02:00
# include <linux/vmalloc.h>
2019-11-07 10:43:05 +01:00
# include <drm/drm_drv.h>
2019-11-07 10:43:06 +01:00
# include <drm/drm_gem_shmem_helper.h>
2019-07-16 08:42:09 +02:00
# include <drm/drm_mode.h>
# include <drm/drm_prime.h>
# include "udl_drv.h"
2010-12-15 07:14:24 +10:00
2019-11-07 10:43:06 +01:00
/*
* GEM object funcs
*/
static int udl_gem_object_mmap ( struct drm_gem_object * obj ,
struct vm_area_struct * vma )
{
int ret ;
ret = drm_gem_shmem_mmap ( obj , vma ) ;
if ( ret )
return ret ;
vma - > vm_page_prot = vm_get_page_prot ( vma - > vm_flags ) ;
if ( obj - > import_attach )
vma - > vm_page_prot = pgprot_writecombine ( vma - > vm_page_prot ) ;
vma - > vm_page_prot = pgprot_decrypted ( vma - > vm_page_prot ) ;
return 0 ;
}
static void * udl_gem_object_vmap ( struct drm_gem_object * obj )
{
struct drm_gem_shmem_object * shmem = to_drm_gem_shmem_obj ( obj ) ;
int ret ;
ret = mutex_lock_interruptible ( & shmem - > vmap_lock ) ;
if ( ret )
return ERR_PTR ( ret ) ;
if ( shmem - > vmap_use_count + + > 0 )
goto out ;
ret = drm_gem_shmem_get_pages ( shmem ) ;
if ( ret )
goto err_zero_use ;
if ( obj - > import_attach )
shmem - > vaddr = dma_buf_vmap ( obj - > import_attach - > dmabuf ) ;
else
shmem - > vaddr = vmap ( shmem - > pages , obj - > size > > PAGE_SHIFT ,
VM_MAP , PAGE_KERNEL ) ;
if ( ! shmem - > vaddr ) {
DRM_DEBUG_KMS ( " Failed to vmap pages \n " ) ;
ret = - ENOMEM ;
goto err_put_pages ;
}
out :
mutex_unlock ( & shmem - > vmap_lock ) ;
return shmem - > vaddr ;
err_put_pages :
drm_gem_shmem_put_pages ( shmem ) ;
err_zero_use :
shmem - > vmap_use_count = 0 ;
mutex_unlock ( & shmem - > vmap_lock ) ;
return ERR_PTR ( ret ) ;
}
static const struct drm_gem_object_funcs udl_gem_object_funcs = {
2019-11-14 15:10:22 +01:00
. free = drm_gem_shmem_free_object ,
2019-11-07 10:43:06 +01:00
. print_info = drm_gem_shmem_print_info ,
. pin = drm_gem_shmem_pin ,
. unpin = drm_gem_shmem_unpin ,
. get_sg_table = drm_gem_shmem_get_sg_table ,
. vmap = udl_gem_object_vmap ,
. vunmap = drm_gem_shmem_vunmap ,
. mmap = udl_gem_object_mmap ,
} ;
2019-11-07 10:43:05 +01:00
/*
* Helpers for struct drm_driver
*/
struct drm_gem_object * udl_driver_gem_create_object ( struct drm_device * dev ,
size_t size )
2010-12-15 07:14:24 +10:00
{
2019-11-07 10:43:06 +01:00
struct drm_gem_shmem_object * shmem ;
struct drm_gem_object * obj ;
2010-12-15 07:14:24 +10:00
2019-11-07 10:43:06 +01:00
shmem = kzalloc ( sizeof ( * shmem ) , GFP_KERNEL ) ;
if ( ! shmem )
2019-11-07 10:43:05 +01:00
return NULL ;
2019-11-07 10:43:06 +01:00
obj = & shmem - > base ;
obj - > funcs = & udl_gem_object_funcs ;
return obj ;
2019-11-07 10:43:05 +01:00
}