15320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie/* 25320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie * Copyright (C) 2012 Red Hat 35320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie * 45320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie * This file is subject to the terms and conditions of the GNU General Public 55320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie * License v2. See the file COPYING in the main directory of this archive for 65320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie * more details. 75320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie */ 85320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 9760285e7e7ab282c25b5e90816f7c47000557f4fDavid Howells#include <drm/drmP.h> 105320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie#include "udl_drv.h" 115320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie#include <linux/shmem_fs.h> 1296503f592fd729f296f5870a57be0417eeffc92aDave Airlie#include <linux/dma-buf.h> 135320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 145320918b9a87865223fd6b228e530bf30bc64d9dDave Airliestruct udl_gem_object *udl_gem_alloc_object(struct drm_device *dev, 155320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie size_t size) 165320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie{ 175320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie struct udl_gem_object *obj; 185320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 195320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie obj = kzalloc(sizeof(*obj), GFP_KERNEL); 205320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie if (obj == NULL) 215320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie return NULL; 225320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 235320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie if (drm_gem_object_init(dev, &obj->base, size) != 0) { 245320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie kfree(obj); 255320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie return NULL; 265320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie } 275320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 285320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie return obj; 295320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie} 305320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 315320918b9a87865223fd6b228e530bf30bc64d9dDave Airliestatic int 325320918b9a87865223fd6b228e530bf30bc64d9dDave Airlieudl_gem_create(struct drm_file *file, 335320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie struct drm_device *dev, 345320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie uint64_t size, 355320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie uint32_t *handle_p) 365320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie{ 375320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie struct udl_gem_object *obj; 385320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie int ret; 395320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie u32 handle; 405320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 415320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie size = roundup(size, PAGE_SIZE); 425320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 435320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie obj = udl_gem_alloc_object(dev, size); 445320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie if (obj == NULL) 455320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie return -ENOMEM; 465320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 475320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie ret = drm_gem_handle_create(file, &obj->base, &handle); 485320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie if (ret) { 495320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie drm_gem_object_release(&obj->base); 505320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie kfree(obj); 515320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie return ret; 525320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie } 535320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 545320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie drm_gem_object_unreference(&obj->base); 555320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie *handle_p = handle; 565320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie return 0; 575320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie} 585320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 595320918b9a87865223fd6b228e530bf30bc64d9dDave Airlieint udl_dumb_create(struct drm_file *file, 605320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie struct drm_device *dev, 615320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie struct drm_mode_create_dumb *args) 625320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie{ 632b932d8ef009f37d397c211b1dc5d0b056f6ef64David Herrmann args->pitch = args->width * DIV_ROUND_UP(args->bpp, 8); 645320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie args->size = args->pitch * args->height; 655320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie return udl_gem_create(file, dev, 665320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie args->size, &args->handle); 675320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie} 685320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 69fa9e855025b19e96e493ee00de7d933a9794f742Konstantin Khlebnikovint udl_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) 70fa9e855025b19e96e493ee00de7d933a9794f742Konstantin Khlebnikov{ 71fa9e855025b19e96e493ee00de7d933a9794f742Konstantin Khlebnikov int ret; 72fa9e855025b19e96e493ee00de7d933a9794f742Konstantin Khlebnikov 73fa9e855025b19e96e493ee00de7d933a9794f742Konstantin Khlebnikov ret = drm_gem_mmap(filp, vma); 74fa9e855025b19e96e493ee00de7d933a9794f742Konstantin Khlebnikov if (ret) 75fa9e855025b19e96e493ee00de7d933a9794f742Konstantin Khlebnikov return ret; 76fa9e855025b19e96e493ee00de7d933a9794f742Konstantin Khlebnikov 77fa9e855025b19e96e493ee00de7d933a9794f742Konstantin Khlebnikov vma->vm_flags &= ~VM_PFNMAP; 78fa9e855025b19e96e493ee00de7d933a9794f742Konstantin Khlebnikov vma->vm_flags |= VM_MIXEDMAP; 79fa9e855025b19e96e493ee00de7d933a9794f742Konstantin Khlebnikov 80fa9e855025b19e96e493ee00de7d933a9794f742Konstantin Khlebnikov return ret; 81fa9e855025b19e96e493ee00de7d933a9794f742Konstantin Khlebnikov} 82fa9e855025b19e96e493ee00de7d933a9794f742Konstantin Khlebnikov 835320918b9a87865223fd6b228e530bf30bc64d9dDave Airlieint udl_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) 845320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie{ 855320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie struct udl_gem_object *obj = to_udl_bo(vma->vm_private_data); 865320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie struct page *page; 875320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie unsigned int page_offset; 885320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie int ret = 0; 895320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 905320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >> 915320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie PAGE_SHIFT; 925320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 935320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie if (!obj->pages) 945320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie return VM_FAULT_SIGBUS; 955320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 965320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie page = obj->pages[page_offset]; 975320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie ret = vm_insert_page(vma, (unsigned long)vmf->virtual_address, page); 985320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie switch (ret) { 995320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie case -EAGAIN: 1005320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie case 0: 1015320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie case -ERESTARTSYS: 1025320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie return VM_FAULT_NOPAGE; 1035320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie case -ENOMEM: 1045320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie return VM_FAULT_OOM; 1055320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie default: 1065320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie return VM_FAULT_SIGBUS; 1075320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie } 1085320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie} 1095320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 1100cdbe8ac696b5399327f972a1c91263c1a44f1d9David Herrmannstatic int udl_gem_get_pages(struct udl_gem_object *obj) 1115320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie{ 1125dc9e1e87229cb786a5bb58ddd0d60fee6eb4641Rob Clark struct page **pages; 1135320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 1145320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie if (obj->pages) 1155320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie return 0; 1165320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 1170cdbe8ac696b5399327f972a1c91263c1a44f1d9David Herrmann pages = drm_gem_get_pages(&obj->base); 1185dc9e1e87229cb786a5bb58ddd0d60fee6eb4641Rob Clark if (IS_ERR(pages)) 1195dc9e1e87229cb786a5bb58ddd0d60fee6eb4641Rob Clark return PTR_ERR(pages); 1205320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 1215dc9e1e87229cb786a5bb58ddd0d60fee6eb4641Rob Clark obj->pages = pages; 1225320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 1235320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie return 0; 1245320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie} 1255320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 1265320918b9a87865223fd6b228e530bf30bc64d9dDave Airliestatic void udl_gem_put_pages(struct udl_gem_object *obj) 1275320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie{ 1281d507b3af40a60e03a3bbc4c897fc2709c075d24Rob Clark if (obj->base.import_attach) { 1291d507b3af40a60e03a3bbc4c897fc2709c075d24Rob Clark drm_free_large(obj->pages); 1301d507b3af40a60e03a3bbc4c897fc2709c075d24Rob Clark obj->pages = NULL; 1311d507b3af40a60e03a3bbc4c897fc2709c075d24Rob Clark return; 1321d507b3af40a60e03a3bbc4c897fc2709c075d24Rob Clark } 1331d507b3af40a60e03a3bbc4c897fc2709c075d24Rob Clark 1345dc9e1e87229cb786a5bb58ddd0d60fee6eb4641Rob Clark drm_gem_put_pages(&obj->base, obj->pages, false, false); 1355320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie obj->pages = NULL; 1365320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie} 1375320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 1385320918b9a87865223fd6b228e530bf30bc64d9dDave Airlieint udl_gem_vmap(struct udl_gem_object *obj) 1395320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie{ 1405320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie int page_count = obj->base.size / PAGE_SIZE; 1415320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie int ret; 1425320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 143e8aa1d1ebcbcf98fbb20cad83098f25c7d52753fDave Airlie if (obj->base.import_attach) { 144e8aa1d1ebcbcf98fbb20cad83098f25c7d52753fDave Airlie obj->vmapping = dma_buf_vmap(obj->base.import_attach->dmabuf); 145e8aa1d1ebcbcf98fbb20cad83098f25c7d52753fDave Airlie if (!obj->vmapping) 146e8aa1d1ebcbcf98fbb20cad83098f25c7d52753fDave Airlie return -ENOMEM; 147e8aa1d1ebcbcf98fbb20cad83098f25c7d52753fDave Airlie return 0; 148e8aa1d1ebcbcf98fbb20cad83098f25c7d52753fDave Airlie } 149e8aa1d1ebcbcf98fbb20cad83098f25c7d52753fDave Airlie 1500cdbe8ac696b5399327f972a1c91263c1a44f1d9David Herrmann ret = udl_gem_get_pages(obj); 1515320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie if (ret) 1525320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie return ret; 1535320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 1545320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie obj->vmapping = vmap(obj->pages, page_count, 0, PAGE_KERNEL); 1555320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie if (!obj->vmapping) 1565320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie return -ENOMEM; 1575320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie return 0; 1585320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie} 1595320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 1605320918b9a87865223fd6b228e530bf30bc64d9dDave Airlievoid udl_gem_vunmap(struct udl_gem_object *obj) 1615320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie{ 162e8aa1d1ebcbcf98fbb20cad83098f25c7d52753fDave Airlie if (obj->base.import_attach) { 163e8aa1d1ebcbcf98fbb20cad83098f25c7d52753fDave Airlie dma_buf_vunmap(obj->base.import_attach->dmabuf, obj->vmapping); 164e8aa1d1ebcbcf98fbb20cad83098f25c7d52753fDave Airlie return; 165e8aa1d1ebcbcf98fbb20cad83098f25c7d52753fDave Airlie } 166e8aa1d1ebcbcf98fbb20cad83098f25c7d52753fDave Airlie 1675320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie if (obj->vmapping) 1685320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie vunmap(obj->vmapping); 1695320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 1705320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie udl_gem_put_pages(obj); 1715320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie} 1725320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 1735320918b9a87865223fd6b228e530bf30bc64d9dDave Airlievoid udl_gem_free_object(struct drm_gem_object *gem_obj) 1745320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie{ 1755320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie struct udl_gem_object *obj = to_udl_bo(gem_obj); 1765320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 1775320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie if (obj->vmapping) 1785320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie udl_gem_vunmap(obj); 1795320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 180347cf10aed1657a2b385a95f92763a67062c5ad3Dave Airlie if (gem_obj->import_attach) { 181e8aa1d1ebcbcf98fbb20cad83098f25c7d52753fDave Airlie drm_prime_gem_destroy(gem_obj, obj->sg); 182347cf10aed1657a2b385a95f92763a67062c5ad3Dave Airlie put_device(gem_obj->dev->dev); 183347cf10aed1657a2b385a95f92763a67062c5ad3Dave Airlie } 184e8aa1d1ebcbcf98fbb20cad83098f25c7d52753fDave Airlie 1855320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie if (obj->pages) 1865320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie udl_gem_put_pages(obj); 1875320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 1880de23977cfeb5b357ec884ba15417ae118ff9e9bDavid Herrmann drm_gem_free_mmap_offset(gem_obj); 1895320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie} 1905320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 1915320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie/* the dumb interface doesn't work with the GEM straight MMAP 1925320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie interface, it expects to do MMAP on the drm fd, like normal */ 1935320918b9a87865223fd6b228e530bf30bc64d9dDave Airlieint udl_gem_mmap(struct drm_file *file, struct drm_device *dev, 1945320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie uint32_t handle, uint64_t *offset) 1955320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie{ 1965320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie struct udl_gem_object *gobj; 1975320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie struct drm_gem_object *obj; 1985320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie int ret = 0; 1995320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 2005320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie mutex_lock(&dev->struct_mutex); 2015320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie obj = drm_gem_object_lookup(dev, file, handle); 2025320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie if (obj == NULL) { 2035320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie ret = -ENOENT; 2045320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie goto unlock; 2055320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie } 2065320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie gobj = to_udl_bo(obj); 2075320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 2080cdbe8ac696b5399327f972a1c91263c1a44f1d9David Herrmann ret = udl_gem_get_pages(gobj); 2095320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie if (ret) 210ace281e8ab62e026b95c413db5f3c6beed42b829Dan Carpenter goto out; 2110de23977cfeb5b357ec884ba15417ae118ff9e9bDavid Herrmann ret = drm_gem_create_mmap_offset(obj); 2120de23977cfeb5b357ec884ba15417ae118ff9e9bDavid Herrmann if (ret) 2130de23977cfeb5b357ec884ba15417ae118ff9e9bDavid Herrmann goto out; 2145320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 2150de23977cfeb5b357ec884ba15417ae118ff9e9bDavid Herrmann *offset = drm_vma_node_offset_addr(&gobj->base.vma_node); 2165320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie 2175320918b9a87865223fd6b228e530bf30bc64d9dDave Airlieout: 2185320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie drm_gem_object_unreference(&gobj->base); 2195320918b9a87865223fd6b228e530bf30bc64d9dDave Airlieunlock: 2205320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie mutex_unlock(&dev->struct_mutex); 2215320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie return ret; 2225320918b9a87865223fd6b228e530bf30bc64d9dDave Airlie} 22396503f592fd729f296f5870a57be0417eeffc92aDave Airlie 22496503f592fd729f296f5870a57be0417eeffc92aDave Airliestatic int udl_prime_create(struct drm_device *dev, 22596503f592fd729f296f5870a57be0417eeffc92aDave Airlie size_t size, 22696503f592fd729f296f5870a57be0417eeffc92aDave Airlie struct sg_table *sg, 22796503f592fd729f296f5870a57be0417eeffc92aDave Airlie struct udl_gem_object **obj_p) 22896503f592fd729f296f5870a57be0417eeffc92aDave Airlie{ 22996503f592fd729f296f5870a57be0417eeffc92aDave Airlie struct udl_gem_object *obj; 23096503f592fd729f296f5870a57be0417eeffc92aDave Airlie int npages; 23196503f592fd729f296f5870a57be0417eeffc92aDave Airlie 23296503f592fd729f296f5870a57be0417eeffc92aDave Airlie npages = size / PAGE_SIZE; 23396503f592fd729f296f5870a57be0417eeffc92aDave Airlie 23496503f592fd729f296f5870a57be0417eeffc92aDave Airlie *obj_p = NULL; 23596503f592fd729f296f5870a57be0417eeffc92aDave Airlie obj = udl_gem_alloc_object(dev, npages * PAGE_SIZE); 23696503f592fd729f296f5870a57be0417eeffc92aDave Airlie if (!obj) 23796503f592fd729f296f5870a57be0417eeffc92aDave Airlie return -ENOMEM; 23896503f592fd729f296f5870a57be0417eeffc92aDave Airlie 23996503f592fd729f296f5870a57be0417eeffc92aDave Airlie obj->sg = sg; 24096503f592fd729f296f5870a57be0417eeffc92aDave Airlie obj->pages = drm_malloc_ab(npages, sizeof(struct page *)); 24196503f592fd729f296f5870a57be0417eeffc92aDave Airlie if (obj->pages == NULL) { 24296503f592fd729f296f5870a57be0417eeffc92aDave Airlie DRM_ERROR("obj pages is NULL %d\n", npages); 24396503f592fd729f296f5870a57be0417eeffc92aDave Airlie return -ENOMEM; 24496503f592fd729f296f5870a57be0417eeffc92aDave Airlie } 24596503f592fd729f296f5870a57be0417eeffc92aDave Airlie 24696503f592fd729f296f5870a57be0417eeffc92aDave Airlie drm_prime_sg_to_page_addr_arrays(sg, obj->pages, NULL, npages); 24796503f592fd729f296f5870a57be0417eeffc92aDave Airlie 24896503f592fd729f296f5870a57be0417eeffc92aDave Airlie *obj_p = obj; 24996503f592fd729f296f5870a57be0417eeffc92aDave Airlie return 0; 25096503f592fd729f296f5870a57be0417eeffc92aDave Airlie} 25196503f592fd729f296f5870a57be0417eeffc92aDave Airlie 25296503f592fd729f296f5870a57be0417eeffc92aDave Airliestruct drm_gem_object *udl_gem_prime_import(struct drm_device *dev, 25396503f592fd729f296f5870a57be0417eeffc92aDave Airlie struct dma_buf *dma_buf) 25496503f592fd729f296f5870a57be0417eeffc92aDave Airlie{ 25596503f592fd729f296f5870a57be0417eeffc92aDave Airlie struct dma_buf_attachment *attach; 25696503f592fd729f296f5870a57be0417eeffc92aDave Airlie struct sg_table *sg; 25796503f592fd729f296f5870a57be0417eeffc92aDave Airlie struct udl_gem_object *uobj; 25896503f592fd729f296f5870a57be0417eeffc92aDave Airlie int ret; 25996503f592fd729f296f5870a57be0417eeffc92aDave Airlie 26096503f592fd729f296f5870a57be0417eeffc92aDave Airlie /* need to attach */ 261347cf10aed1657a2b385a95f92763a67062c5ad3Dave Airlie get_device(dev->dev); 26296503f592fd729f296f5870a57be0417eeffc92aDave Airlie attach = dma_buf_attach(dma_buf, dev->dev); 263347cf10aed1657a2b385a95f92763a67062c5ad3Dave Airlie if (IS_ERR(attach)) { 264347cf10aed1657a2b385a95f92763a67062c5ad3Dave Airlie put_device(dev->dev); 265959f724728b6a1cb5185230972119dd7bc8b610eThomas Meyer return ERR_CAST(attach); 266347cf10aed1657a2b385a95f92763a67062c5ad3Dave Airlie } 26796503f592fd729f296f5870a57be0417eeffc92aDave Airlie 268011c2282c74db120f01a8414edc66c3f217f5511Imre Deak get_dma_buf(dma_buf); 269011c2282c74db120f01a8414edc66c3f217f5511Imre Deak 27096503f592fd729f296f5870a57be0417eeffc92aDave Airlie sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); 27196503f592fd729f296f5870a57be0417eeffc92aDave Airlie if (IS_ERR(sg)) { 27296503f592fd729f296f5870a57be0417eeffc92aDave Airlie ret = PTR_ERR(sg); 27396503f592fd729f296f5870a57be0417eeffc92aDave Airlie goto fail_detach; 27496503f592fd729f296f5870a57be0417eeffc92aDave Airlie } 27596503f592fd729f296f5870a57be0417eeffc92aDave Airlie 27696503f592fd729f296f5870a57be0417eeffc92aDave Airlie ret = udl_prime_create(dev, dma_buf->size, sg, &uobj); 27796503f592fd729f296f5870a57be0417eeffc92aDave Airlie if (ret) { 27896503f592fd729f296f5870a57be0417eeffc92aDave Airlie goto fail_unmap; 27996503f592fd729f296f5870a57be0417eeffc92aDave Airlie } 28096503f592fd729f296f5870a57be0417eeffc92aDave Airlie 28196503f592fd729f296f5870a57be0417eeffc92aDave Airlie uobj->base.import_attach = attach; 28296503f592fd729f296f5870a57be0417eeffc92aDave Airlie 28396503f592fd729f296f5870a57be0417eeffc92aDave Airlie return &uobj->base; 28496503f592fd729f296f5870a57be0417eeffc92aDave Airlie 28596503f592fd729f296f5870a57be0417eeffc92aDave Airliefail_unmap: 28696503f592fd729f296f5870a57be0417eeffc92aDave Airlie dma_buf_unmap_attachment(attach, sg, DMA_BIDIRECTIONAL); 28796503f592fd729f296f5870a57be0417eeffc92aDave Airliefail_detach: 28896503f592fd729f296f5870a57be0417eeffc92aDave Airlie dma_buf_detach(dma_buf, attach); 289011c2282c74db120f01a8414edc66c3f217f5511Imre Deak dma_buf_put(dma_buf); 290347cf10aed1657a2b385a95f92763a67062c5ad3Dave Airlie put_device(dev->dev); 29196503f592fd729f296f5870a57be0417eeffc92aDave Airlie return ERR_PTR(ret); 29296503f592fd729f296f5870a57be0417eeffc92aDave Airlie} 293