Home | History | Annotate | Line # | Download | only in nouveau
nouveau_gem.c revision 1.2.2.2
      1 /*	$NetBSD: nouveau_gem.c,v 1.2.2.2 2014/08/10 06:55:30 tls Exp $	*/
      2 
      3 /*
      4  * Copyright (C) 2008 Ben Skeggs.
      5  * All Rights Reserved.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining
      8  * a copy of this software and associated documentation files (the
      9  * "Software"), to deal in the Software without restriction, including
     10  * without limitation the rights to use, copy, modify, merge, publish,
     11  * distribute, sublicense, and/or sell copies of the Software, and to
     12  * permit persons to whom the Software is furnished to do so, subject to
     13  * the following conditions:
     14  *
     15  * The above copyright notice and this permission notice (including the
     16  * next paragraph) shall be included in all copies or substantial
     17  * portions of the Software.
     18  *
     19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     20  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     22  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
     23  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     24  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     25  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     26  *
     27  */
     28 
     29 #include <sys/cdefs.h>
     30 __KERNEL_RCSID(0, "$NetBSD: nouveau_gem.c,v 1.2.2.2 2014/08/10 06:55:30 tls Exp $");
     31 
     32 #include <subdev/fb.h>
     33 
     34 #include "nouveau_drm.h"
     35 #include "nouveau_dma.h"
     36 #include "nouveau_fence.h"
     37 #include "nouveau_abi16.h"
     38 
     39 #include "nouveau_ttm.h"
     40 #include "nouveau_gem.h"
     41 
     42 void
     43 nouveau_gem_object_del(struct drm_gem_object *gem)
     44 {
     45 	struct nouveau_bo *nvbo = nouveau_gem_object(gem);
     46 	struct ttm_buffer_object *bo = &nvbo->bo;
     47 
     48 	if (gem->import_attach)
     49 		drm_prime_gem_destroy(gem, nvbo->bo.sg);
     50 
     51 	drm_gem_object_release(gem);
     52 
     53 	/* reset filp so nouveau_bo_del_ttm() can test for it */
     54 #ifdef __NetBSD__
     55 	/* XXX Whattakludge!  */
     56 	gem->gemo_shm_uao = NULL;
     57 #else
     58 	gem->filp = NULL;
     59 #endif
     60 	ttm_bo_unref(&bo);
     61 }
     62 
     63 int
     64 nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv)
     65 {
     66 	struct nouveau_cli *cli = nouveau_cli(file_priv);
     67 	struct nouveau_bo *nvbo = nouveau_gem_object(gem);
     68 	struct nouveau_vma *vma;
     69 	int ret;
     70 
     71 	if (!cli->base.vm)
     72 		return 0;
     73 
     74 	ret = ttm_bo_reserve(&nvbo->bo, false, false, false, 0);
     75 	if (ret)
     76 		return ret;
     77 
     78 	vma = nouveau_bo_vma_find(nvbo, cli->base.vm);
     79 	if (!vma) {
     80 		vma = kzalloc(sizeof(*vma), GFP_KERNEL);
     81 		if (!vma) {
     82 			ret = -ENOMEM;
     83 			goto out;
     84 		}
     85 
     86 		ret = nouveau_bo_vma_add(nvbo, cli->base.vm, vma);
     87 		if (ret) {
     88 			kfree(vma);
     89 			goto out;
     90 		}
     91 	} else {
     92 		vma->refcount++;
     93 	}
     94 
     95 out:
     96 	ttm_bo_unreserve(&nvbo->bo);
     97 	return ret;
     98 }
     99 
    100 static void
    101 nouveau_gem_object_delete(void *data)
    102 {
    103 	struct nouveau_vma *vma = data;
    104 	nouveau_vm_unmap(vma);
    105 	nouveau_vm_put(vma);
    106 	kfree(vma);
    107 }
    108 
    109 static void
    110 nouveau_gem_object_unmap(struct nouveau_bo *nvbo, struct nouveau_vma *vma)
    111 {
    112 	const bool mapped = nvbo->bo.mem.mem_type != TTM_PL_SYSTEM;
    113 	struct nouveau_fence *fence = NULL;
    114 
    115 	list_del(&vma->head);
    116 
    117 	if (mapped) {
    118 		spin_lock(&nvbo->bo.bdev->fence_lock);
    119 		fence = nouveau_fence_ref(nvbo->bo.sync_obj);
    120 		spin_unlock(&nvbo->bo.bdev->fence_lock);
    121 	}
    122 
    123 	if (fence) {
    124 		nouveau_fence_work(fence, nouveau_gem_object_delete, vma);
    125 	} else {
    126 		if (mapped)
    127 			nouveau_vm_unmap(vma);
    128 		nouveau_vm_put(vma);
    129 		kfree(vma);
    130 	}
    131 	nouveau_fence_unref(&fence);
    132 }
    133 
    134 void
    135 nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv)
    136 {
    137 	struct nouveau_cli *cli = nouveau_cli(file_priv);
    138 	struct nouveau_bo *nvbo = nouveau_gem_object(gem);
    139 	struct nouveau_vma *vma;
    140 	int ret;
    141 
    142 	if (!cli->base.vm)
    143 		return;
    144 
    145 	ret = ttm_bo_reserve(&nvbo->bo, false, false, false, 0);
    146 	if (ret)
    147 		return;
    148 
    149 	vma = nouveau_bo_vma_find(nvbo, cli->base.vm);
    150 	if (vma) {
    151 		if (--vma->refcount == 0)
    152 			nouveau_gem_object_unmap(nvbo, vma);
    153 	}
    154 	ttm_bo_unreserve(&nvbo->bo);
    155 }
    156 
    157 int
    158 nouveau_gem_new(struct drm_device *dev, int size, int align, uint32_t domain,
    159 		uint32_t tile_mode, uint32_t tile_flags,
    160 		struct nouveau_bo **pnvbo)
    161 {
    162 	struct nouveau_drm *drm = nouveau_drm(dev);
    163 	struct nouveau_bo *nvbo;
    164 	u32 flags = 0;
    165 	int ret;
    166 
    167 	if (domain & NOUVEAU_GEM_DOMAIN_VRAM)
    168 		flags |= TTM_PL_FLAG_VRAM;
    169 	if (domain & NOUVEAU_GEM_DOMAIN_GART)
    170 		flags |= TTM_PL_FLAG_TT;
    171 	if (!flags || domain & NOUVEAU_GEM_DOMAIN_CPU)
    172 		flags |= TTM_PL_FLAG_SYSTEM;
    173 
    174 	ret = nouveau_bo_new(dev, size, align, flags, tile_mode,
    175 			     tile_flags, NULL, pnvbo);
    176 	if (ret)
    177 		return ret;
    178 	nvbo = *pnvbo;
    179 
    180 	/* we restrict allowed domains on nv50+ to only the types
    181 	 * that were requested at creation time.  not possibly on
    182 	 * earlier chips without busting the ABI.
    183 	 */
    184 	nvbo->valid_domains = NOUVEAU_GEM_DOMAIN_VRAM |
    185 			      NOUVEAU_GEM_DOMAIN_GART;
    186 	if (nv_device(drm->device)->card_type >= NV_50)
    187 		nvbo->valid_domains &= domain;
    188 
    189 	/* Initialize the embedded gem-object. We return a single gem-reference
    190 	 * to the caller, instead of a normal nouveau_bo ttm reference. */
    191 	ret = drm_gem_object_init(dev, &nvbo->gem, nvbo->bo.mem.size);
    192 	if (ret) {
    193 		nouveau_bo_ref(NULL, pnvbo);
    194 		return -ENOMEM;
    195 	}
    196 
    197 #ifndef __NetBSD__		/* XXX Let TTM swap; skip GEM like radeon.  */
    198 	nvbo->bo.persistent_swap_storage = nvbo->gem.filp;
    199 #endif
    200 	return 0;
    201 }
    202 
    203 static int
    204 nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem,
    205 		 struct drm_nouveau_gem_info *rep)
    206 {
    207 	struct nouveau_cli *cli = nouveau_cli(file_priv);
    208 	struct nouveau_bo *nvbo = nouveau_gem_object(gem);
    209 	struct nouveau_vma *vma;
    210 
    211 	if (nvbo->bo.mem.mem_type == TTM_PL_TT)
    212 		rep->domain = NOUVEAU_GEM_DOMAIN_GART;
    213 	else
    214 		rep->domain = NOUVEAU_GEM_DOMAIN_VRAM;
    215 
    216 	rep->offset = nvbo->bo.offset;
    217 	if (cli->base.vm) {
    218 		vma = nouveau_bo_vma_find(nvbo, cli->base.vm);
    219 		if (!vma)
    220 			return -EINVAL;
    221 
    222 		rep->offset = vma->offset;
    223 	}
    224 
    225 	rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT;
    226 	rep->map_handle = drm_vma_node_offset_addr(&nvbo->bo.vma_node);
    227 	rep->tile_mode = nvbo->tile_mode;
    228 	rep->tile_flags = nvbo->tile_flags;
    229 	return 0;
    230 }
    231 
    232 int
    233 nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
    234 		      struct drm_file *file_priv)
    235 {
    236 	struct nouveau_drm *drm = nouveau_drm(dev);
    237 	struct nouveau_cli *cli = nouveau_cli(file_priv);
    238 	struct nouveau_fb *pfb = nouveau_fb(drm->device);
    239 	struct drm_nouveau_gem_new *req = data;
    240 	struct nouveau_bo *nvbo = NULL;
    241 	int ret = 0;
    242 
    243 	if (!pfb->memtype_valid(pfb, req->info.tile_flags)) {
    244 		NV_ERROR(cli, "bad page flags: 0x%08x\n", req->info.tile_flags);
    245 		return -EINVAL;
    246 	}
    247 
    248 	ret = nouveau_gem_new(dev, req->info.size, req->align,
    249 			      req->info.domain, req->info.tile_mode,
    250 			      req->info.tile_flags, &nvbo);
    251 	if (ret)
    252 		return ret;
    253 
    254 	ret = drm_gem_handle_create(file_priv, &nvbo->gem, &req->info.handle);
    255 	if (ret == 0) {
    256 		ret = nouveau_gem_info(file_priv, &nvbo->gem, &req->info);
    257 		if (ret)
    258 			drm_gem_handle_delete(file_priv, req->info.handle);
    259 	}
    260 
    261 	/* drop reference from allocate - handle holds it now */
    262 	drm_gem_object_unreference_unlocked(&nvbo->gem);
    263 	return ret;
    264 }
    265 
    266 static int
    267 nouveau_gem_set_domain(struct drm_gem_object *gem, uint32_t read_domains,
    268 		       uint32_t write_domains, uint32_t valid_domains)
    269 {
    270 	struct nouveau_bo *nvbo = nouveau_gem_object(gem);
    271 	struct ttm_buffer_object *bo = &nvbo->bo;
    272 	uint32_t domains = valid_domains & nvbo->valid_domains &
    273 		(write_domains ? write_domains : read_domains);
    274 	uint32_t pref_flags = 0, valid_flags = 0;
    275 
    276 	if (!domains)
    277 		return -EINVAL;
    278 
    279 	if (valid_domains & NOUVEAU_GEM_DOMAIN_VRAM)
    280 		valid_flags |= TTM_PL_FLAG_VRAM;
    281 
    282 	if (valid_domains & NOUVEAU_GEM_DOMAIN_GART)
    283 		valid_flags |= TTM_PL_FLAG_TT;
    284 
    285 	if ((domains & NOUVEAU_GEM_DOMAIN_VRAM) &&
    286 	    bo->mem.mem_type == TTM_PL_VRAM)
    287 		pref_flags |= TTM_PL_FLAG_VRAM;
    288 
    289 	else if ((domains & NOUVEAU_GEM_DOMAIN_GART) &&
    290 		 bo->mem.mem_type == TTM_PL_TT)
    291 		pref_flags |= TTM_PL_FLAG_TT;
    292 
    293 	else if (domains & NOUVEAU_GEM_DOMAIN_VRAM)
    294 		pref_flags |= TTM_PL_FLAG_VRAM;
    295 
    296 	else
    297 		pref_flags |= TTM_PL_FLAG_TT;
    298 
    299 	nouveau_bo_placement_set(nvbo, pref_flags, valid_flags);
    300 
    301 	return 0;
    302 }
    303 
    304 struct validate_op {
    305 	struct list_head vram_list;
    306 	struct list_head gart_list;
    307 	struct list_head both_list;
    308 	struct ww_acquire_ctx ticket;
    309 };
    310 
    311 static void
    312 validate_fini_list(struct list_head *list, struct nouveau_fence *fence,
    313 		   struct ww_acquire_ctx *ticket)
    314 {
    315 	struct list_head *entry, *tmp;
    316 	struct nouveau_bo *nvbo;
    317 
    318 	list_for_each_safe(entry, tmp, list) {
    319 		nvbo = list_entry(entry, struct nouveau_bo, entry);
    320 
    321 		if (likely(fence))
    322 			nouveau_bo_fence(nvbo, fence);
    323 
    324 		if (unlikely(nvbo->validate_mapped)) {
    325 			ttm_bo_kunmap(&nvbo->kmap);
    326 			nvbo->validate_mapped = false;
    327 		}
    328 
    329 		list_del(&nvbo->entry);
    330 		nvbo->reserved_by = NULL;
    331 		ttm_bo_unreserve_ticket(&nvbo->bo, ticket);
    332 		drm_gem_object_unreference_unlocked(&nvbo->gem);
    333 	}
    334 }
    335 
    336 static void
    337 validate_fini_no_ticket(struct validate_op *op, struct nouveau_fence *fence)
    338 {
    339 	validate_fini_list(&op->vram_list, fence, &op->ticket);
    340 	validate_fini_list(&op->gart_list, fence, &op->ticket);
    341 	validate_fini_list(&op->both_list, fence, &op->ticket);
    342 }
    343 
    344 static void
    345 validate_fini(struct validate_op *op, struct nouveau_fence *fence)
    346 {
    347 	validate_fini_no_ticket(op, fence);
    348 	ww_acquire_fini(&op->ticket);
    349 }
    350 
    351 static int
    352 validate_init(struct nouveau_channel *chan, struct drm_file *file_priv,
    353 	      struct drm_nouveau_gem_pushbuf_bo *pbbo,
    354 	      int nr_buffers, struct validate_op *op)
    355 {
    356 	struct nouveau_cli *cli = nouveau_cli(file_priv);
    357 	struct drm_device *dev = chan->drm->dev;
    358 	int trycnt = 0;
    359 	int ret, i;
    360 	struct nouveau_bo *res_bo = NULL;
    361 
    362 	ww_acquire_init(&op->ticket, &reservation_ww_class);
    363 retry:
    364 	if (++trycnt > 100000) {
    365 		NV_ERROR(cli, "%s failed and gave up.\n", __func__);
    366 		return -EINVAL;
    367 	}
    368 
    369 	for (i = 0; i < nr_buffers; i++) {
    370 		struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[i];
    371 		struct drm_gem_object *gem;
    372 		struct nouveau_bo *nvbo;
    373 
    374 		gem = drm_gem_object_lookup(dev, file_priv, b->handle);
    375 		if (!gem) {
    376 			NV_ERROR(cli, "Unknown handle 0x%08x\n", b->handle);
    377 			ww_acquire_done(&op->ticket);
    378 			validate_fini(op, NULL);
    379 			return -ENOENT;
    380 		}
    381 		nvbo = nouveau_gem_object(gem);
    382 		if (nvbo == res_bo) {
    383 			res_bo = NULL;
    384 			drm_gem_object_unreference_unlocked(gem);
    385 			continue;
    386 		}
    387 
    388 		if (nvbo->reserved_by && nvbo->reserved_by == file_priv) {
    389 			NV_ERROR(cli, "multiple instances of buffer %d on "
    390 				      "validation list\n", b->handle);
    391 			drm_gem_object_unreference_unlocked(gem);
    392 			ww_acquire_done(&op->ticket);
    393 			validate_fini(op, NULL);
    394 			return -EINVAL;
    395 		}
    396 
    397 		ret = ttm_bo_reserve(&nvbo->bo, true, false, true, &op->ticket);
    398 		if (ret) {
    399 			validate_fini_no_ticket(op, NULL);
    400 			if (unlikely(ret == -EDEADLK)) {
    401 				ret = ttm_bo_reserve_slowpath(&nvbo->bo, true,
    402 							      &op->ticket);
    403 				if (!ret)
    404 					res_bo = nvbo;
    405 			}
    406 			if (unlikely(ret)) {
    407 				ww_acquire_done(&op->ticket);
    408 				ww_acquire_fini(&op->ticket);
    409 				drm_gem_object_unreference_unlocked(gem);
    410 				if (ret != -ERESTARTSYS)
    411 					NV_ERROR(cli, "fail reserve\n");
    412 				return ret;
    413 			}
    414 		}
    415 
    416 		b->user_priv = (uint64_t)(unsigned long)nvbo;
    417 		nvbo->reserved_by = file_priv;
    418 		nvbo->pbbo_index = i;
    419 		if ((b->valid_domains & NOUVEAU_GEM_DOMAIN_VRAM) &&
    420 		    (b->valid_domains & NOUVEAU_GEM_DOMAIN_GART))
    421 			list_add_tail(&nvbo->entry, &op->both_list);
    422 		else
    423 		if (b->valid_domains & NOUVEAU_GEM_DOMAIN_VRAM)
    424 			list_add_tail(&nvbo->entry, &op->vram_list);
    425 		else
    426 		if (b->valid_domains & NOUVEAU_GEM_DOMAIN_GART)
    427 			list_add_tail(&nvbo->entry, &op->gart_list);
    428 		else {
    429 			NV_ERROR(cli, "invalid valid domains: 0x%08x\n",
    430 				 b->valid_domains);
    431 			list_add_tail(&nvbo->entry, &op->both_list);
    432 			ww_acquire_done(&op->ticket);
    433 			validate_fini(op, NULL);
    434 			return -EINVAL;
    435 		}
    436 		if (nvbo == res_bo)
    437 			goto retry;
    438 	}
    439 
    440 	ww_acquire_done(&op->ticket);
    441 	return 0;
    442 }
    443 
    444 static int
    445 validate_sync(struct nouveau_channel *chan, struct nouveau_bo *nvbo)
    446 {
    447 	struct nouveau_fence *fence = NULL;
    448 	int ret = 0;
    449 
    450 	spin_lock(&nvbo->bo.bdev->fence_lock);
    451 	fence = nouveau_fence_ref(nvbo->bo.sync_obj);
    452 	spin_unlock(&nvbo->bo.bdev->fence_lock);
    453 
    454 	if (fence) {
    455 		ret = nouveau_fence_sync(fence, chan);
    456 		nouveau_fence_unref(&fence);
    457 	}
    458 
    459 	return ret;
    460 }
    461 
    462 static int
    463 validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli,
    464 	      struct list_head *list, struct drm_nouveau_gem_pushbuf_bo *pbbo,
    465 	      uint64_t user_pbbo_ptr)
    466 {
    467 	struct nouveau_drm *drm = chan->drm;
    468 	struct drm_nouveau_gem_pushbuf_bo __user *upbbo =
    469 				(void __force __user *)(uintptr_t)user_pbbo_ptr;
    470 	struct nouveau_bo *nvbo;
    471 	int ret, relocs = 0;
    472 
    473 	list_for_each_entry(nvbo, list, entry) {
    474 		struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index];
    475 
    476 		ret = nouveau_gem_set_domain(&nvbo->gem, b->read_domains,
    477 					     b->write_domains,
    478 					     b->valid_domains);
    479 		if (unlikely(ret)) {
    480 			NV_ERROR(cli, "fail set_domain\n");
    481 			return ret;
    482 		}
    483 
    484 		ret = nouveau_bo_validate(nvbo, true, false);
    485 		if (unlikely(ret)) {
    486 			if (ret != -ERESTARTSYS)
    487 				NV_ERROR(cli, "fail ttm_validate\n");
    488 			return ret;
    489 		}
    490 
    491 		ret = validate_sync(chan, nvbo);
    492 		if (unlikely(ret)) {
    493 			NV_ERROR(cli, "fail post-validate sync\n");
    494 			return ret;
    495 		}
    496 
    497 		if (nv_device(drm->device)->card_type < NV_50) {
    498 			if (nvbo->bo.offset == b->presumed.offset &&
    499 			    ((nvbo->bo.mem.mem_type == TTM_PL_VRAM &&
    500 			      b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) ||
    501 			     (nvbo->bo.mem.mem_type == TTM_PL_TT &&
    502 			      b->presumed.domain & NOUVEAU_GEM_DOMAIN_GART)))
    503 				continue;
    504 
    505 			if (nvbo->bo.mem.mem_type == TTM_PL_TT)
    506 				b->presumed.domain = NOUVEAU_GEM_DOMAIN_GART;
    507 			else
    508 				b->presumed.domain = NOUVEAU_GEM_DOMAIN_VRAM;
    509 			b->presumed.offset = nvbo->bo.offset;
    510 			b->presumed.valid = 0;
    511 			relocs++;
    512 
    513 			if (copy_to_user(&upbbo[nvbo->pbbo_index].presumed,
    514 					     &b->presumed, sizeof(b->presumed)))
    515 				return -EFAULT;
    516 		}
    517 	}
    518 
    519 	return relocs;
    520 }
    521 
    522 static int
    523 nouveau_gem_pushbuf_validate(struct nouveau_channel *chan,
    524 			     struct drm_file *file_priv,
    525 			     struct drm_nouveau_gem_pushbuf_bo *pbbo,
    526 			     uint64_t user_buffers, int nr_buffers,
    527 			     struct validate_op *op, int *apply_relocs)
    528 {
    529 	struct nouveau_cli *cli = nouveau_cli(file_priv);
    530 	int ret, relocs = 0;
    531 
    532 	INIT_LIST_HEAD(&op->vram_list);
    533 	INIT_LIST_HEAD(&op->gart_list);
    534 	INIT_LIST_HEAD(&op->both_list);
    535 
    536 	if (nr_buffers == 0)
    537 		return 0;
    538 
    539 	ret = validate_init(chan, file_priv, pbbo, nr_buffers, op);
    540 	if (unlikely(ret)) {
    541 		if (ret != -ERESTARTSYS)
    542 			NV_ERROR(cli, "validate_init\n");
    543 		return ret;
    544 	}
    545 
    546 	ret = validate_list(chan, cli, &op->vram_list, pbbo, user_buffers);
    547 	if (unlikely(ret < 0)) {
    548 		if (ret != -ERESTARTSYS)
    549 			NV_ERROR(cli, "validate vram_list\n");
    550 		validate_fini(op, NULL);
    551 		return ret;
    552 	}
    553 	relocs += ret;
    554 
    555 	ret = validate_list(chan, cli, &op->gart_list, pbbo, user_buffers);
    556 	if (unlikely(ret < 0)) {
    557 		if (ret != -ERESTARTSYS)
    558 			NV_ERROR(cli, "validate gart_list\n");
    559 		validate_fini(op, NULL);
    560 		return ret;
    561 	}
    562 	relocs += ret;
    563 
    564 	ret = validate_list(chan, cli, &op->both_list, pbbo, user_buffers);
    565 	if (unlikely(ret < 0)) {
    566 		if (ret != -ERESTARTSYS)
    567 			NV_ERROR(cli, "validate both_list\n");
    568 		validate_fini(op, NULL);
    569 		return ret;
    570 	}
    571 	relocs += ret;
    572 
    573 	*apply_relocs = relocs;
    574 	return 0;
    575 }
    576 
    577 static inline void
    578 u_free(void *addr)
    579 {
    580 	if (!is_vmalloc_addr(addr))
    581 		kfree(addr);
    582 	else
    583 		vfree(addr);
    584 }
    585 
    586 static inline void *
    587 u_memcpya(uint64_t user, unsigned nmemb, unsigned size)
    588 {
    589 	void *mem;
    590 	void __user *userptr = (void __force __user *)(uintptr_t)user;
    591 
    592 	size *= nmemb;
    593 
    594 	mem = kmalloc(size, GFP_KERNEL | __GFP_NOWARN);
    595 	if (!mem)
    596 		mem = vmalloc(size);
    597 	if (!mem)
    598 		return ERR_PTR(-ENOMEM);
    599 
    600 	if (copy_from_user(mem, userptr, size)) {
    601 		u_free(mem);
    602 		return ERR_PTR(-EFAULT);
    603 	}
    604 
    605 	return mem;
    606 }
    607 
    608 static int
    609 nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli,
    610 				struct drm_nouveau_gem_pushbuf *req,
    611 				struct drm_nouveau_gem_pushbuf_bo *bo)
    612 {
    613 	struct drm_nouveau_gem_pushbuf_reloc *reloc = NULL;
    614 	int ret = 0;
    615 	unsigned i;
    616 
    617 	reloc = u_memcpya(req->relocs, req->nr_relocs, sizeof(*reloc));
    618 	if (IS_ERR(reloc))
    619 		return PTR_ERR(reloc);
    620 
    621 	for (i = 0; i < req->nr_relocs; i++) {
    622 		struct drm_nouveau_gem_pushbuf_reloc *r = &reloc[i];
    623 		struct drm_nouveau_gem_pushbuf_bo *b;
    624 		struct nouveau_bo *nvbo;
    625 		uint32_t data;
    626 
    627 		if (unlikely(r->bo_index > req->nr_buffers)) {
    628 			NV_ERROR(cli, "reloc bo index invalid\n");
    629 			ret = -EINVAL;
    630 			break;
    631 		}
    632 
    633 		b = &bo[r->bo_index];
    634 		if (b->presumed.valid)
    635 			continue;
    636 
    637 		if (unlikely(r->reloc_bo_index > req->nr_buffers)) {
    638 			NV_ERROR(cli, "reloc container bo index invalid\n");
    639 			ret = -EINVAL;
    640 			break;
    641 		}
    642 		nvbo = (void *)(unsigned long)bo[r->reloc_bo_index].user_priv;
    643 
    644 		if (unlikely(r->reloc_bo_offset + 4 >
    645 			     nvbo->bo.mem.num_pages << PAGE_SHIFT)) {
    646 			NV_ERROR(cli, "reloc outside of bo\n");
    647 			ret = -EINVAL;
    648 			break;
    649 		}
    650 
    651 		if (!nvbo->kmap.virtual) {
    652 			ret = ttm_bo_kmap(&nvbo->bo, 0, nvbo->bo.mem.num_pages,
    653 					  &nvbo->kmap);
    654 			if (ret) {
    655 				NV_ERROR(cli, "failed kmap for reloc\n");
    656 				break;
    657 			}
    658 			nvbo->validate_mapped = true;
    659 		}
    660 
    661 		if (r->flags & NOUVEAU_GEM_RELOC_LOW)
    662 			data = b->presumed.offset + r->data;
    663 		else
    664 		if (r->flags & NOUVEAU_GEM_RELOC_HIGH)
    665 			data = (b->presumed.offset + r->data) >> 32;
    666 		else
    667 			data = r->data;
    668 
    669 		if (r->flags & NOUVEAU_GEM_RELOC_OR) {
    670 			if (b->presumed.domain == NOUVEAU_GEM_DOMAIN_GART)
    671 				data |= r->tor;
    672 			else
    673 				data |= r->vor;
    674 		}
    675 
    676 		spin_lock(&nvbo->bo.bdev->fence_lock);
    677 		ret = ttm_bo_wait(&nvbo->bo, false, false, false);
    678 		spin_unlock(&nvbo->bo.bdev->fence_lock);
    679 		if (ret) {
    680 			NV_ERROR(cli, "reloc wait_idle failed: %d\n", ret);
    681 			break;
    682 		}
    683 
    684 		nouveau_bo_wr32(nvbo, r->reloc_bo_offset >> 2, data);
    685 	}
    686 
    687 	u_free(reloc);
    688 	return ret;
    689 }
    690 
    691 int
    692 nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
    693 			  struct drm_file *file_priv)
    694 {
    695 	struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
    696 	struct nouveau_cli *cli = nouveau_cli(file_priv);
    697 	struct nouveau_abi16_chan *temp;
    698 	struct nouveau_drm *drm = nouveau_drm(dev);
    699 	struct drm_nouveau_gem_pushbuf *req = data;
    700 	struct drm_nouveau_gem_pushbuf_push *push;
    701 	struct drm_nouveau_gem_pushbuf_bo *bo;
    702 	struct nouveau_channel *chan = NULL;
    703 	struct validate_op op;
    704 	struct nouveau_fence *fence = NULL;
    705 	int i, j, ret = 0, do_reloc = 0;
    706 
    707 	if (unlikely(!abi16))
    708 		return -ENOMEM;
    709 
    710 	list_for_each_entry(temp, &abi16->channels, head) {
    711 		if (temp->chan->handle == (NVDRM_CHAN | req->channel)) {
    712 			chan = temp->chan;
    713 			break;
    714 		}
    715 	}
    716 
    717 	if (!chan)
    718 		return nouveau_abi16_put(abi16, -ENOENT);
    719 
    720 	req->vram_available = drm->gem.vram_available;
    721 	req->gart_available = drm->gem.gart_available;
    722 	if (unlikely(req->nr_push == 0))
    723 		goto out_next;
    724 
    725 	if (unlikely(req->nr_push > NOUVEAU_GEM_MAX_PUSH)) {
    726 		NV_ERROR(cli, "pushbuf push count exceeds limit: %d max %d\n",
    727 			 req->nr_push, NOUVEAU_GEM_MAX_PUSH);
    728 		return nouveau_abi16_put(abi16, -EINVAL);
    729 	}
    730 
    731 	if (unlikely(req->nr_buffers > NOUVEAU_GEM_MAX_BUFFERS)) {
    732 		NV_ERROR(cli, "pushbuf bo count exceeds limit: %d max %d\n",
    733 			 req->nr_buffers, NOUVEAU_GEM_MAX_BUFFERS);
    734 		return nouveau_abi16_put(abi16, -EINVAL);
    735 	}
    736 
    737 	if (unlikely(req->nr_relocs > NOUVEAU_GEM_MAX_RELOCS)) {
    738 		NV_ERROR(cli, "pushbuf reloc count exceeds limit: %d max %d\n",
    739 			 req->nr_relocs, NOUVEAU_GEM_MAX_RELOCS);
    740 		return nouveau_abi16_put(abi16, -EINVAL);
    741 	}
    742 
    743 	push = u_memcpya(req->push, req->nr_push, sizeof(*push));
    744 	if (IS_ERR(push))
    745 		return nouveau_abi16_put(abi16, PTR_ERR(push));
    746 
    747 	bo = u_memcpya(req->buffers, req->nr_buffers, sizeof(*bo));
    748 	if (IS_ERR(bo)) {
    749 		u_free(push);
    750 		return nouveau_abi16_put(abi16, PTR_ERR(bo));
    751 	}
    752 
    753 	/* Ensure all push buffers are on validate list */
    754 	for (i = 0; i < req->nr_push; i++) {
    755 		if (push[i].bo_index >= req->nr_buffers) {
    756 			NV_ERROR(cli, "push %d buffer not in list\n", i);
    757 			ret = -EINVAL;
    758 			goto out_prevalid;
    759 		}
    760 	}
    761 
    762 	/* Validate buffer list */
    763 	ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo, req->buffers,
    764 					   req->nr_buffers, &op, &do_reloc);
    765 	if (ret) {
    766 		if (ret != -ERESTARTSYS)
    767 			NV_ERROR(cli, "validate: %d\n", ret);
    768 		goto out_prevalid;
    769 	}
    770 
    771 	/* Apply any relocations that are required */
    772 	if (do_reloc) {
    773 		ret = nouveau_gem_pushbuf_reloc_apply(cli, req, bo);
    774 		if (ret) {
    775 			NV_ERROR(cli, "reloc apply: %d\n", ret);
    776 			goto out;
    777 		}
    778 	}
    779 
    780 	if (chan->dma.ib_max) {
    781 		ret = nouveau_dma_wait(chan, req->nr_push + 1, 16);
    782 		if (ret) {
    783 			NV_ERROR(cli, "nv50cal_space: %d\n", ret);
    784 			goto out;
    785 		}
    786 
    787 		for (i = 0; i < req->nr_push; i++) {
    788 			struct nouveau_bo *nvbo = (void *)(unsigned long)
    789 				bo[push[i].bo_index].user_priv;
    790 
    791 			nv50_dma_push(chan, nvbo, push[i].offset,
    792 				      push[i].length);
    793 		}
    794 	} else
    795 	if (nv_device(drm->device)->chipset >= 0x25) {
    796 		ret = RING_SPACE(chan, req->nr_push * 2);
    797 		if (ret) {
    798 			NV_ERROR(cli, "cal_space: %d\n", ret);
    799 			goto out;
    800 		}
    801 
    802 		for (i = 0; i < req->nr_push; i++) {
    803 			struct nouveau_bo *nvbo = (void *)(unsigned long)
    804 				bo[push[i].bo_index].user_priv;
    805 
    806 			OUT_RING(chan, (nvbo->bo.offset + push[i].offset) | 2);
    807 			OUT_RING(chan, 0);
    808 		}
    809 	} else {
    810 		ret = RING_SPACE(chan, req->nr_push * (2 + NOUVEAU_DMA_SKIPS));
    811 		if (ret) {
    812 			NV_ERROR(cli, "jmp_space: %d\n", ret);
    813 			goto out;
    814 		}
    815 
    816 		for (i = 0; i < req->nr_push; i++) {
    817 			struct nouveau_bo *nvbo = (void *)(unsigned long)
    818 				bo[push[i].bo_index].user_priv;
    819 			uint32_t cmd;
    820 
    821 			cmd = chan->push.vma.offset + ((chan->dma.cur + 2) << 2);
    822 			cmd |= 0x20000000;
    823 			if (unlikely(cmd != req->suffix0)) {
    824 				if (!nvbo->kmap.virtual) {
    825 					ret = ttm_bo_kmap(&nvbo->bo, 0,
    826 							  nvbo->bo.mem.
    827 							  num_pages,
    828 							  &nvbo->kmap);
    829 					if (ret) {
    830 						WIND_RING(chan);
    831 						goto out;
    832 					}
    833 					nvbo->validate_mapped = true;
    834 				}
    835 
    836 				nouveau_bo_wr32(nvbo, (push[i].offset +
    837 						push[i].length - 8) / 4, cmd);
    838 			}
    839 
    840 			OUT_RING(chan, 0x20000000 |
    841 				      (nvbo->bo.offset + push[i].offset));
    842 			OUT_RING(chan, 0);
    843 			for (j = 0; j < NOUVEAU_DMA_SKIPS; j++)
    844 				OUT_RING(chan, 0);
    845 		}
    846 	}
    847 
    848 	ret = nouveau_fence_new(chan, false, &fence);
    849 	if (ret) {
    850 		NV_ERROR(cli, "error fencing pushbuf: %d\n", ret);
    851 		WIND_RING(chan);
    852 		goto out;
    853 	}
    854 
    855 out:
    856 	validate_fini(&op, fence);
    857 	nouveau_fence_unref(&fence);
    858 
    859 out_prevalid:
    860 	u_free(bo);
    861 	u_free(push);
    862 
    863 out_next:
    864 	if (chan->dma.ib_max) {
    865 		req->suffix0 = 0x00000000;
    866 		req->suffix1 = 0x00000000;
    867 	} else
    868 	if (nv_device(drm->device)->chipset >= 0x25) {
    869 		req->suffix0 = 0x00020000;
    870 		req->suffix1 = 0x00000000;
    871 	} else {
    872 		req->suffix0 = 0x20000000 |
    873 			      (chan->push.vma.offset + ((chan->dma.cur + 2) << 2));
    874 		req->suffix1 = 0x00000000;
    875 	}
    876 
    877 	return nouveau_abi16_put(abi16, ret);
    878 }
    879 
    880 static inline uint32_t
    881 domain_to_ttm(struct nouveau_bo *nvbo, uint32_t domain)
    882 {
    883 	uint32_t flags = 0;
    884 
    885 	if (domain & NOUVEAU_GEM_DOMAIN_VRAM)
    886 		flags |= TTM_PL_FLAG_VRAM;
    887 	if (domain & NOUVEAU_GEM_DOMAIN_GART)
    888 		flags |= TTM_PL_FLAG_TT;
    889 
    890 	return flags;
    891 }
    892 
    893 int
    894 nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data,
    895 			   struct drm_file *file_priv)
    896 {
    897 	struct drm_nouveau_gem_cpu_prep *req = data;
    898 	struct drm_gem_object *gem;
    899 	struct nouveau_bo *nvbo;
    900 	bool no_wait = !!(req->flags & NOUVEAU_GEM_CPU_PREP_NOWAIT);
    901 	int ret = -EINVAL;
    902 
    903 	gem = drm_gem_object_lookup(dev, file_priv, req->handle);
    904 	if (!gem)
    905 		return -ENOENT;
    906 	nvbo = nouveau_gem_object(gem);
    907 
    908 	spin_lock(&nvbo->bo.bdev->fence_lock);
    909 	ret = ttm_bo_wait(&nvbo->bo, true, true, no_wait);
    910 	spin_unlock(&nvbo->bo.bdev->fence_lock);
    911 	drm_gem_object_unreference_unlocked(gem);
    912 	return ret;
    913 }
    914 
    915 int
    916 nouveau_gem_ioctl_cpu_fini(struct drm_device *dev, void *data,
    917 			   struct drm_file *file_priv)
    918 {
    919 	return 0;
    920 }
    921 
    922 int
    923 nouveau_gem_ioctl_info(struct drm_device *dev, void *data,
    924 		       struct drm_file *file_priv)
    925 {
    926 	struct drm_nouveau_gem_info *req = data;
    927 	struct drm_gem_object *gem;
    928 	int ret;
    929 
    930 	gem = drm_gem_object_lookup(dev, file_priv, req->handle);
    931 	if (!gem)
    932 		return -ENOENT;
    933 
    934 	ret = nouveau_gem_info(file_priv, gem, req);
    935 	drm_gem_object_unreference_unlocked(gem);
    936 	return ret;
    937 }
    938 
    939