[go: nahoru, domu]

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