xref: /openbmc/linux/drivers/gpu/drm/nouveau/nouveau_gem.c (revision d699090510c3223641a23834b4710e2d4309a6ad)
1 /*
2  * Copyright (C) 2008 Ben Skeggs.
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the
14  * next paragraph) shall be included in all copies or substantial
15  * portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  *
25  */
26 
27 #include <drm/drm_gem_ttm_helper.h>
28 
29 #include "nouveau_drv.h"
30 #include "nouveau_dma.h"
31 #include "nouveau_fence.h"
32 #include "nouveau_abi16.h"
33 
34 #include "nouveau_ttm.h"
35 #include "nouveau_gem.h"
36 #include "nouveau_mem.h"
37 #include "nouveau_vmm.h"
38 
39 #include <nvif/class.h>
40 #include <nvif/push206e.h>
41 
nouveau_ttm_fault(struct vm_fault * vmf)42 static vm_fault_t nouveau_ttm_fault(struct vm_fault *vmf)
43 {
44 	struct vm_area_struct *vma = vmf->vma;
45 	struct ttm_buffer_object *bo = vma->vm_private_data;
46 	pgprot_t prot;
47 	vm_fault_t ret;
48 
49 	ret = ttm_bo_vm_reserve(bo, vmf);
50 	if (ret)
51 		return ret;
52 
53 	ret = nouveau_ttm_fault_reserve_notify(bo);
54 	if (ret)
55 		goto error_unlock;
56 
57 	nouveau_bo_del_io_reserve_lru(bo);
58 	prot = vm_get_page_prot(vma->vm_flags);
59 	ret = ttm_bo_vm_fault_reserved(vmf, prot, TTM_BO_VM_NUM_PREFAULT);
60 	nouveau_bo_add_io_reserve_lru(bo);
61 	if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT))
62 		return ret;
63 
64 error_unlock:
65 	dma_resv_unlock(bo->base.resv);
66 	return ret;
67 }
68 
69 static const struct vm_operations_struct nouveau_ttm_vm_ops = {
70 	.fault = nouveau_ttm_fault,
71 	.open = ttm_bo_vm_open,
72 	.close = ttm_bo_vm_close,
73 	.access = ttm_bo_vm_access
74 };
75 
76 void
nouveau_gem_object_del(struct drm_gem_object * gem)77 nouveau_gem_object_del(struct drm_gem_object *gem)
78 {
79 	struct nouveau_bo *nvbo = nouveau_gem_object(gem);
80 	struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
81 	struct device *dev = drm->dev->dev;
82 	int ret;
83 
84 	ret = pm_runtime_get_sync(dev);
85 	if (WARN_ON(ret < 0 && ret != -EACCES)) {
86 		pm_runtime_put_autosuspend(dev);
87 		return;
88 	}
89 
90 	ttm_bo_put(&nvbo->bo);
91 
92 	pm_runtime_mark_last_busy(dev);
93 	pm_runtime_put_autosuspend(dev);
94 }
95 
96 int
nouveau_gem_object_open(struct drm_gem_object * gem,struct drm_file * file_priv)97 nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv)
98 {
99 	struct nouveau_cli *cli = nouveau_cli(file_priv);
100 	struct nouveau_bo *nvbo = nouveau_gem_object(gem);
101 	struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
102 	struct device *dev = drm->dev->dev;
103 	struct nouveau_uvmm *uvmm = nouveau_cli_uvmm(cli);
104 	struct nouveau_vmm *vmm = nouveau_cli_vmm(cli);
105 	struct nouveau_vma *vma;
106 	int ret;
107 
108 	if (vmm->vmm.object.oclass < NVIF_CLASS_VMM_NV50)
109 		return 0;
110 
111 	if (nvbo->no_share && uvmm && &uvmm->resv != nvbo->bo.base.resv)
112 		return -EPERM;
113 
114 	ret = ttm_bo_reserve(&nvbo->bo, false, false, NULL);
115 	if (ret)
116 		return ret;
117 
118 	ret = pm_runtime_get_sync(dev);
119 	if (ret < 0 && ret != -EACCES) {
120 		pm_runtime_put_autosuspend(dev);
121 		goto out;
122 	}
123 
124 	/* only create a VMA on binding */
125 	if (!nouveau_cli_uvmm(cli))
126 		ret = nouveau_vma_new(nvbo, vmm, &vma);
127 	else
128 		ret = 0;
129 	pm_runtime_mark_last_busy(dev);
130 	pm_runtime_put_autosuspend(dev);
131 out:
132 	ttm_bo_unreserve(&nvbo->bo);
133 	return ret;
134 }
135 
136 struct nouveau_gem_object_unmap {
137 	struct nouveau_cli_work work;
138 	struct nouveau_vma *vma;
139 };
140 
141 static void
nouveau_gem_object_delete(struct nouveau_vma * vma)142 nouveau_gem_object_delete(struct nouveau_vma *vma)
143 {
144 	nouveau_fence_unref(&vma->fence);
145 	nouveau_vma_del(&vma);
146 }
147 
148 static void
nouveau_gem_object_delete_work(struct nouveau_cli_work * w)149 nouveau_gem_object_delete_work(struct nouveau_cli_work *w)
150 {
151 	struct nouveau_gem_object_unmap *work =
152 		container_of(w, typeof(*work), work);
153 	nouveau_gem_object_delete(work->vma);
154 	kfree(work);
155 }
156 
157 static void
nouveau_gem_object_unmap(struct nouveau_bo * nvbo,struct nouveau_vma * vma)158 nouveau_gem_object_unmap(struct nouveau_bo *nvbo, struct nouveau_vma *vma)
159 {
160 	struct dma_fence *fence = vma->fence ? &vma->fence->base : NULL;
161 	struct nouveau_gem_object_unmap *work;
162 
163 	list_del_init(&vma->head);
164 
165 	if (!fence) {
166 		nouveau_gem_object_delete(vma);
167 		return;
168 	}
169 
170 	if (!(work = kmalloc(sizeof(*work), GFP_KERNEL))) {
171 		WARN_ON(dma_fence_wait_timeout(fence, false, 2 * HZ) <= 0);
172 		nouveau_gem_object_delete(vma);
173 		return;
174 	}
175 
176 	work->work.func = nouveau_gem_object_delete_work;
177 	work->vma = vma;
178 	nouveau_cli_work_queue(vma->vmm->cli, fence, &work->work);
179 }
180 
181 void
nouveau_gem_object_close(struct drm_gem_object * gem,struct drm_file * file_priv)182 nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv)
183 {
184 	struct nouveau_cli *cli = nouveau_cli(file_priv);
185 	struct nouveau_bo *nvbo = nouveau_gem_object(gem);
186 	struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
187 	struct device *dev = drm->dev->dev;
188 	struct nouveau_vmm *vmm = nouveau_cli_vmm(cli);
189 	struct nouveau_vma *vma;
190 	int ret;
191 
192 	if (vmm->vmm.object.oclass < NVIF_CLASS_VMM_NV50)
193 		return;
194 
195 	if (nouveau_cli_uvmm(cli))
196 		return;
197 
198 	ret = ttm_bo_reserve(&nvbo->bo, false, false, NULL);
199 	if (ret)
200 		return;
201 
202 	vma = nouveau_vma_find(nvbo, vmm);
203 	if (vma) {
204 		if (--vma->refs == 0) {
205 			ret = pm_runtime_get_sync(dev);
206 			if (!WARN_ON(ret < 0 && ret != -EACCES)) {
207 				nouveau_gem_object_unmap(nvbo, vma);
208 				pm_runtime_mark_last_busy(dev);
209 			}
210 			pm_runtime_put_autosuspend(dev);
211 		}
212 	}
213 	ttm_bo_unreserve(&nvbo->bo);
214 }
215 
216 const struct drm_gem_object_funcs nouveau_gem_object_funcs = {
217 	.free = nouveau_gem_object_del,
218 	.open = nouveau_gem_object_open,
219 	.close = nouveau_gem_object_close,
220 	.export = nouveau_gem_prime_export,
221 	.pin = nouveau_gem_prime_pin,
222 	.unpin = nouveau_gem_prime_unpin,
223 	.get_sg_table = nouveau_gem_prime_get_sg_table,
224 	.vmap = drm_gem_ttm_vmap,
225 	.vunmap = drm_gem_ttm_vunmap,
226 	.mmap = drm_gem_ttm_mmap,
227 	.vm_ops = &nouveau_ttm_vm_ops,
228 };
229 
230 int
nouveau_gem_new(struct nouveau_cli * cli,u64 size,int align,uint32_t domain,uint32_t tile_mode,uint32_t tile_flags,struct nouveau_bo ** pnvbo)231 nouveau_gem_new(struct nouveau_cli *cli, u64 size, int align, uint32_t domain,
232 		uint32_t tile_mode, uint32_t tile_flags,
233 		struct nouveau_bo **pnvbo)
234 {
235 	struct nouveau_drm *drm = cli->drm;
236 	struct nouveau_uvmm *uvmm = nouveau_cli_uvmm(cli);
237 	struct dma_resv *resv = NULL;
238 	struct nouveau_bo *nvbo;
239 	int ret;
240 
241 	if (domain & NOUVEAU_GEM_DOMAIN_NO_SHARE) {
242 		if (unlikely(!uvmm))
243 			return -EINVAL;
244 
245 		resv = &uvmm->resv;
246 	}
247 
248 	if (!(domain & (NOUVEAU_GEM_DOMAIN_VRAM | NOUVEAU_GEM_DOMAIN_GART)))
249 		domain |= NOUVEAU_GEM_DOMAIN_CPU;
250 
251 	nvbo = nouveau_bo_alloc(cli, &size, &align, domain, tile_mode,
252 				tile_flags, false);
253 	if (IS_ERR(nvbo))
254 		return PTR_ERR(nvbo);
255 
256 	nvbo->bo.base.funcs = &nouveau_gem_object_funcs;
257 	nvbo->no_share = domain & NOUVEAU_GEM_DOMAIN_NO_SHARE;
258 
259 	/* Initialize the embedded gem-object. We return a single gem-reference
260 	 * to the caller, instead of a normal nouveau_bo ttm reference. */
261 	ret = drm_gem_object_init(drm->dev, &nvbo->bo.base, size);
262 	if (ret) {
263 		drm_gem_object_release(&nvbo->bo.base);
264 		kfree(nvbo);
265 		return ret;
266 	}
267 
268 	if (resv)
269 		dma_resv_lock(resv, NULL);
270 
271 	ret = nouveau_bo_init(nvbo, size, align, domain, NULL, resv);
272 
273 	if (resv)
274 		dma_resv_unlock(resv);
275 
276 	if (ret)
277 		return ret;
278 
279 	/* we restrict allowed domains on nv50+ to only the types
280 	 * that were requested at creation time.  not possibly on
281 	 * earlier chips without busting the ABI.
282 	 */
283 	nvbo->valid_domains = NOUVEAU_GEM_DOMAIN_VRAM |
284 			      NOUVEAU_GEM_DOMAIN_GART;
285 	if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA)
286 		nvbo->valid_domains &= domain;
287 
288 	*pnvbo = nvbo;
289 	return 0;
290 }
291 
292 static int
nouveau_gem_info(struct drm_file * file_priv,struct drm_gem_object * gem,struct drm_nouveau_gem_info * rep)293 nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem,
294 		 struct drm_nouveau_gem_info *rep)
295 {
296 	struct nouveau_cli *cli = nouveau_cli(file_priv);
297 	struct nouveau_bo *nvbo = nouveau_gem_object(gem);
298 	struct nouveau_vmm *vmm = nouveau_cli_vmm(cli);
299 	struct nouveau_vma *vma;
300 
301 	if (is_power_of_2(nvbo->valid_domains))
302 		rep->domain = nvbo->valid_domains;
303 	else if (nvbo->bo.resource->mem_type == TTM_PL_TT)
304 		rep->domain = NOUVEAU_GEM_DOMAIN_GART;
305 	else
306 		rep->domain = NOUVEAU_GEM_DOMAIN_VRAM;
307 	rep->offset = nvbo->offset;
308 	if (vmm->vmm.object.oclass >= NVIF_CLASS_VMM_NV50 &&
309 	    !nouveau_cli_uvmm(cli)) {
310 		vma = nouveau_vma_find(nvbo, vmm);
311 		if (!vma)
312 			return -EINVAL;
313 
314 		rep->offset = vma->addr;
315 	} else
316 		rep->offset = 0;
317 
318 	rep->size = nvbo->bo.base.size;
319 	rep->map_handle = drm_vma_node_offset_addr(&nvbo->bo.base.vma_node);
320 	rep->tile_mode = nvbo->mode;
321 	rep->tile_flags = nvbo->contig ? 0 : NOUVEAU_GEM_TILE_NONCONTIG;
322 	if (cli->device.info.family >= NV_DEVICE_INFO_V0_FERMI)
323 		rep->tile_flags |= nvbo->kind << 8;
324 	else
325 	if (cli->device.info.family >= NV_DEVICE_INFO_V0_TESLA)
326 		rep->tile_flags |= nvbo->kind << 8 | nvbo->comp << 16;
327 	else
328 		rep->tile_flags |= nvbo->zeta;
329 	return 0;
330 }
331 
332 int
nouveau_gem_ioctl_new(struct drm_device * dev,void * data,struct drm_file * file_priv)333 nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
334 		      struct drm_file *file_priv)
335 {
336 	struct nouveau_cli *cli = nouveau_cli(file_priv);
337 	struct drm_nouveau_gem_new *req = data;
338 	struct nouveau_bo *nvbo = NULL;
339 	int ret = 0;
340 
341 	/* If uvmm wasn't initialized until now disable it completely to prevent
342 	 * userspace from mixing up UAPIs.
343 	 */
344 	nouveau_cli_disable_uvmm_noinit(cli);
345 
346 	ret = nouveau_gem_new(cli, req->info.size, req->align,
347 			      req->info.domain, req->info.tile_mode,
348 			      req->info.tile_flags, &nvbo);
349 	if (ret)
350 		return ret;
351 
352 	ret = drm_gem_handle_create(file_priv, &nvbo->bo.base,
353 				    &req->info.handle);
354 	if (ret == 0) {
355 		ret = nouveau_gem_info(file_priv, &nvbo->bo.base, &req->info);
356 		if (ret)
357 			drm_gem_handle_delete(file_priv, req->info.handle);
358 	}
359 
360 	/* drop reference from allocate - handle holds it now */
361 	drm_gem_object_put(&nvbo->bo.base);
362 	return ret;
363 }
364 
365 static int
nouveau_gem_set_domain(struct drm_gem_object * gem,uint32_t read_domains,uint32_t write_domains,uint32_t valid_domains)366 nouveau_gem_set_domain(struct drm_gem_object *gem, uint32_t read_domains,
367 		       uint32_t write_domains, uint32_t valid_domains)
368 {
369 	struct nouveau_bo *nvbo = nouveau_gem_object(gem);
370 	struct ttm_buffer_object *bo = &nvbo->bo;
371 	uint32_t domains = valid_domains & nvbo->valid_domains &
372 		(write_domains ? write_domains : read_domains);
373 	uint32_t pref_domains = 0;
374 
375 	if (!domains)
376 		return -EINVAL;
377 
378 	valid_domains &= ~(NOUVEAU_GEM_DOMAIN_VRAM | NOUVEAU_GEM_DOMAIN_GART);
379 
380 	if ((domains & NOUVEAU_GEM_DOMAIN_VRAM) &&
381 	    bo->resource->mem_type == TTM_PL_VRAM)
382 		pref_domains |= NOUVEAU_GEM_DOMAIN_VRAM;
383 
384 	else if ((domains & NOUVEAU_GEM_DOMAIN_GART) &&
385 		 bo->resource->mem_type == TTM_PL_TT)
386 		pref_domains |= NOUVEAU_GEM_DOMAIN_GART;
387 
388 	else if (domains & NOUVEAU_GEM_DOMAIN_VRAM)
389 		pref_domains |= NOUVEAU_GEM_DOMAIN_VRAM;
390 
391 	else
392 		pref_domains |= NOUVEAU_GEM_DOMAIN_GART;
393 
394 	nouveau_bo_placement_set(nvbo, pref_domains, valid_domains);
395 
396 	return 0;
397 }
398 
399 struct validate_op {
400 	struct list_head list;
401 	struct ww_acquire_ctx ticket;
402 };
403 
404 static void
validate_fini_no_ticket(struct validate_op * op,struct nouveau_channel * chan,struct nouveau_fence * fence,struct drm_nouveau_gem_pushbuf_bo * pbbo)405 validate_fini_no_ticket(struct validate_op *op, struct nouveau_channel *chan,
406 			struct nouveau_fence *fence,
407 			struct drm_nouveau_gem_pushbuf_bo *pbbo)
408 {
409 	struct nouveau_bo *nvbo;
410 	struct drm_nouveau_gem_pushbuf_bo *b;
411 
412 	while (!list_empty(&op->list)) {
413 		nvbo = list_entry(op->list.next, struct nouveau_bo, entry);
414 		b = &pbbo[nvbo->pbbo_index];
415 
416 		if (likely(fence)) {
417 			nouveau_bo_fence(nvbo, fence, !!b->write_domains);
418 
419 			if (chan->vmm->vmm.object.oclass >= NVIF_CLASS_VMM_NV50) {
420 				struct nouveau_vma *vma =
421 					(void *)(unsigned long)b->user_priv;
422 				nouveau_fence_unref(&vma->fence);
423 				dma_fence_get(&fence->base);
424 				vma->fence = fence;
425 			}
426 		}
427 
428 		if (unlikely(nvbo->validate_mapped)) {
429 			ttm_bo_kunmap(&nvbo->kmap);
430 			nvbo->validate_mapped = false;
431 		}
432 
433 		list_del(&nvbo->entry);
434 		nvbo->reserved_by = NULL;
435 		ttm_bo_unreserve(&nvbo->bo);
436 		drm_gem_object_put(&nvbo->bo.base);
437 	}
438 }
439 
440 static void
validate_fini(struct validate_op * op,struct nouveau_channel * chan,struct nouveau_fence * fence,struct drm_nouveau_gem_pushbuf_bo * pbbo)441 validate_fini(struct validate_op *op, struct nouveau_channel *chan,
442 	      struct nouveau_fence *fence,
443 	      struct drm_nouveau_gem_pushbuf_bo *pbbo)
444 {
445 	validate_fini_no_ticket(op, chan, fence, pbbo);
446 	ww_acquire_fini(&op->ticket);
447 }
448 
449 static int
validate_init(struct nouveau_channel * chan,struct drm_file * file_priv,struct drm_nouveau_gem_pushbuf_bo * pbbo,int nr_buffers,struct validate_op * op)450 validate_init(struct nouveau_channel *chan, struct drm_file *file_priv,
451 	      struct drm_nouveau_gem_pushbuf_bo *pbbo,
452 	      int nr_buffers, struct validate_op *op)
453 {
454 	struct nouveau_cli *cli = nouveau_cli(file_priv);
455 	int trycnt = 0;
456 	int ret = -EINVAL, i;
457 	struct nouveau_bo *res_bo = NULL;
458 	LIST_HEAD(gart_list);
459 	LIST_HEAD(vram_list);
460 	LIST_HEAD(both_list);
461 
462 	ww_acquire_init(&op->ticket, &reservation_ww_class);
463 retry:
464 	if (++trycnt > 100000) {
465 		NV_PRINTK(err, cli, "%s failed and gave up.\n", __func__);
466 		return -EINVAL;
467 	}
468 
469 	for (i = 0; i < nr_buffers; i++) {
470 		struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[i];
471 		struct drm_gem_object *gem;
472 		struct nouveau_bo *nvbo;
473 
474 		gem = drm_gem_object_lookup(file_priv, b->handle);
475 		if (!gem) {
476 			NV_PRINTK(err, cli, "Unknown handle 0x%08x\n", b->handle);
477 			ret = -ENOENT;
478 			break;
479 		}
480 		nvbo = nouveau_gem_object(gem);
481 		if (nvbo == res_bo) {
482 			res_bo = NULL;
483 			drm_gem_object_put(gem);
484 			continue;
485 		}
486 
487 		if (nvbo->reserved_by && nvbo->reserved_by == file_priv) {
488 			NV_PRINTK(err, cli, "multiple instances of buffer %d on "
489 				      "validation list\n", b->handle);
490 			drm_gem_object_put(gem);
491 			ret = -EINVAL;
492 			break;
493 		}
494 
495 		ret = ttm_bo_reserve(&nvbo->bo, true, false, &op->ticket);
496 		if (ret) {
497 			list_splice_tail_init(&vram_list, &op->list);
498 			list_splice_tail_init(&gart_list, &op->list);
499 			list_splice_tail_init(&both_list, &op->list);
500 			validate_fini_no_ticket(op, chan, NULL, NULL);
501 			if (unlikely(ret == -EDEADLK)) {
502 				ret = ttm_bo_reserve_slowpath(&nvbo->bo, true,
503 							      &op->ticket);
504 				if (!ret)
505 					res_bo = nvbo;
506 			}
507 			if (unlikely(ret)) {
508 				if (ret != -ERESTARTSYS)
509 					NV_PRINTK(err, cli, "fail reserve\n");
510 				break;
511 			}
512 		}
513 
514 		if (chan->vmm->vmm.object.oclass >= NVIF_CLASS_VMM_NV50) {
515 			struct nouveau_vmm *vmm = chan->vmm;
516 			struct nouveau_vma *vma = nouveau_vma_find(nvbo, vmm);
517 			if (!vma) {
518 				NV_PRINTK(err, cli, "vma not found!\n");
519 				ret = -EINVAL;
520 				break;
521 			}
522 
523 			b->user_priv = (uint64_t)(unsigned long)vma;
524 		} else {
525 			b->user_priv = (uint64_t)(unsigned long)nvbo;
526 		}
527 
528 		nvbo->reserved_by = file_priv;
529 		nvbo->pbbo_index = i;
530 		if ((b->valid_domains & NOUVEAU_GEM_DOMAIN_VRAM) &&
531 		    (b->valid_domains & NOUVEAU_GEM_DOMAIN_GART))
532 			list_add_tail(&nvbo->entry, &both_list);
533 		else
534 		if (b->valid_domains & NOUVEAU_GEM_DOMAIN_VRAM)
535 			list_add_tail(&nvbo->entry, &vram_list);
536 		else
537 		if (b->valid_domains & NOUVEAU_GEM_DOMAIN_GART)
538 			list_add_tail(&nvbo->entry, &gart_list);
539 		else {
540 			NV_PRINTK(err, cli, "invalid valid domains: 0x%08x\n",
541 				 b->valid_domains);
542 			list_add_tail(&nvbo->entry, &both_list);
543 			ret = -EINVAL;
544 			break;
545 		}
546 		if (nvbo == res_bo)
547 			goto retry;
548 	}
549 
550 	ww_acquire_done(&op->ticket);
551 	list_splice_tail(&vram_list, &op->list);
552 	list_splice_tail(&gart_list, &op->list);
553 	list_splice_tail(&both_list, &op->list);
554 	if (ret)
555 		validate_fini(op, chan, NULL, NULL);
556 	return ret;
557 
558 }
559 
560 static int
validate_list(struct nouveau_channel * chan,struct nouveau_cli * cli,struct list_head * list,struct drm_nouveau_gem_pushbuf_bo * pbbo)561 validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli,
562 	      struct list_head *list, struct drm_nouveau_gem_pushbuf_bo *pbbo)
563 {
564 	struct nouveau_drm *drm = chan->drm;
565 	struct nouveau_bo *nvbo;
566 	int ret, relocs = 0;
567 
568 	list_for_each_entry(nvbo, list, entry) {
569 		struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index];
570 
571 		ret = nouveau_gem_set_domain(&nvbo->bo.base, b->read_domains,
572 					     b->write_domains,
573 					     b->valid_domains);
574 		if (unlikely(ret)) {
575 			NV_PRINTK(err, cli, "fail set_domain\n");
576 			return ret;
577 		}
578 
579 		ret = nouveau_bo_validate(nvbo, true, false);
580 		if (unlikely(ret)) {
581 			if (ret != -ERESTARTSYS)
582 				NV_PRINTK(err, cli, "fail ttm_validate\n");
583 			return ret;
584 		}
585 
586 		ret = nouveau_fence_sync(nvbo, chan, !!b->write_domains, true);
587 		if (unlikely(ret)) {
588 			if (ret != -ERESTARTSYS)
589 				NV_PRINTK(err, cli, "fail post-validate sync\n");
590 			return ret;
591 		}
592 
593 		if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA) {
594 			if (nvbo->offset == b->presumed.offset &&
595 			    ((nvbo->bo.resource->mem_type == TTM_PL_VRAM &&
596 			      b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) ||
597 			     (nvbo->bo.resource->mem_type == TTM_PL_TT &&
598 			      b->presumed.domain & NOUVEAU_GEM_DOMAIN_GART)))
599 				continue;
600 
601 			if (nvbo->bo.resource->mem_type == TTM_PL_TT)
602 				b->presumed.domain = NOUVEAU_GEM_DOMAIN_GART;
603 			else
604 				b->presumed.domain = NOUVEAU_GEM_DOMAIN_VRAM;
605 			b->presumed.offset = nvbo->offset;
606 			b->presumed.valid = 0;
607 			relocs++;
608 		}
609 	}
610 
611 	return relocs;
612 }
613 
614 static int
nouveau_gem_pushbuf_validate(struct nouveau_channel * chan,struct drm_file * file_priv,struct drm_nouveau_gem_pushbuf_bo * pbbo,int nr_buffers,struct validate_op * op,bool * apply_relocs)615 nouveau_gem_pushbuf_validate(struct nouveau_channel *chan,
616 			     struct drm_file *file_priv,
617 			     struct drm_nouveau_gem_pushbuf_bo *pbbo,
618 			     int nr_buffers,
619 			     struct validate_op *op, bool *apply_relocs)
620 {
621 	struct nouveau_cli *cli = nouveau_cli(file_priv);
622 	int ret;
623 
624 	INIT_LIST_HEAD(&op->list);
625 
626 	if (nr_buffers == 0)
627 		return 0;
628 
629 	ret = validate_init(chan, file_priv, pbbo, nr_buffers, op);
630 	if (unlikely(ret)) {
631 		if (ret != -ERESTARTSYS)
632 			NV_PRINTK(err, cli, "validate_init\n");
633 		return ret;
634 	}
635 
636 	ret = validate_list(chan, cli, &op->list, pbbo);
637 	if (unlikely(ret < 0)) {
638 		if (ret != -ERESTARTSYS)
639 			NV_PRINTK(err, cli, "validating bo list\n");
640 		validate_fini(op, chan, NULL, NULL);
641 		return ret;
642 	} else if (ret > 0) {
643 		*apply_relocs = true;
644 	}
645 
646 	return 0;
647 }
648 
649 static int
nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli * cli,struct drm_nouveau_gem_pushbuf * req,struct drm_nouveau_gem_pushbuf_reloc * reloc,struct drm_nouveau_gem_pushbuf_bo * bo)650 nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli,
651 				struct drm_nouveau_gem_pushbuf *req,
652 				struct drm_nouveau_gem_pushbuf_reloc *reloc,
653 				struct drm_nouveau_gem_pushbuf_bo *bo)
654 {
655 	int ret = 0;
656 	unsigned i;
657 
658 	for (i = 0; i < req->nr_relocs; i++) {
659 		struct drm_nouveau_gem_pushbuf_reloc *r = &reloc[i];
660 		struct drm_nouveau_gem_pushbuf_bo *b;
661 		struct nouveau_bo *nvbo;
662 		uint32_t data;
663 		long lret;
664 
665 		if (unlikely(r->bo_index >= req->nr_buffers)) {
666 			NV_PRINTK(err, cli, "reloc bo index invalid\n");
667 			ret = -EINVAL;
668 			break;
669 		}
670 
671 		b = &bo[r->bo_index];
672 		if (b->presumed.valid)
673 			continue;
674 
675 		if (unlikely(r->reloc_bo_index >= req->nr_buffers)) {
676 			NV_PRINTK(err, cli, "reloc container bo index invalid\n");
677 			ret = -EINVAL;
678 			break;
679 		}
680 		nvbo = (void *)(unsigned long)bo[r->reloc_bo_index].user_priv;
681 
682 		if (unlikely(r->reloc_bo_offset + 4 >
683 			     nvbo->bo.base.size)) {
684 			NV_PRINTK(err, cli, "reloc outside of bo\n");
685 			ret = -EINVAL;
686 			break;
687 		}
688 
689 		if (!nvbo->kmap.virtual) {
690 			ret = ttm_bo_kmap(&nvbo->bo, 0, PFN_UP(nvbo->bo.base.size),
691 					  &nvbo->kmap);
692 			if (ret) {
693 				NV_PRINTK(err, cli, "failed kmap for reloc\n");
694 				break;
695 			}
696 			nvbo->validate_mapped = true;
697 		}
698 
699 		if (r->flags & NOUVEAU_GEM_RELOC_LOW)
700 			data = b->presumed.offset + r->data;
701 		else
702 		if (r->flags & NOUVEAU_GEM_RELOC_HIGH)
703 			data = (b->presumed.offset + r->data) >> 32;
704 		else
705 			data = r->data;
706 
707 		if (r->flags & NOUVEAU_GEM_RELOC_OR) {
708 			if (b->presumed.domain == NOUVEAU_GEM_DOMAIN_GART)
709 				data |= r->tor;
710 			else
711 				data |= r->vor;
712 		}
713 
714 		lret = dma_resv_wait_timeout(nvbo->bo.base.resv,
715 					     DMA_RESV_USAGE_BOOKKEEP,
716 					     false, 15 * HZ);
717 		if (!lret)
718 			ret = -EBUSY;
719 		else if (lret > 0)
720 			ret = 0;
721 		else
722 			ret = lret;
723 
724 		if (ret) {
725 			NV_PRINTK(err, cli, "reloc wait_idle failed: %d\n",
726 				  ret);
727 			break;
728 		}
729 
730 		nouveau_bo_wr32(nvbo, r->reloc_bo_offset >> 2, data);
731 	}
732 
733 	return ret;
734 }
735 
736 int
nouveau_gem_ioctl_pushbuf(struct drm_device * dev,void * data,struct drm_file * file_priv)737 nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
738 			  struct drm_file *file_priv)
739 {
740 	struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv);
741 	struct nouveau_cli *cli = nouveau_cli(file_priv);
742 	struct nouveau_abi16_chan *temp;
743 	struct nouveau_drm *drm = nouveau_drm(dev);
744 	struct drm_nouveau_gem_pushbuf *req = data;
745 	struct drm_nouveau_gem_pushbuf_push *push;
746 	struct drm_nouveau_gem_pushbuf_reloc *reloc = NULL;
747 	struct drm_nouveau_gem_pushbuf_bo *bo;
748 	struct nouveau_channel *chan = NULL;
749 	struct validate_op op;
750 	struct nouveau_fence *fence = NULL;
751 	int i, j, ret = 0;
752 	bool do_reloc = false, sync = false;
753 
754 	if (unlikely(!abi16))
755 		return -ENOMEM;
756 
757 	if (unlikely(nouveau_cli_uvmm(cli)))
758 		return nouveau_abi16_put(abi16, -ENOSYS);
759 
760 	list_for_each_entry(temp, &abi16->channels, head) {
761 		if (temp->chan->chid == req->channel) {
762 			chan = temp->chan;
763 			break;
764 		}
765 	}
766 
767 	if (!chan)
768 		return nouveau_abi16_put(abi16, -ENOENT);
769 	if (unlikely(atomic_read(&chan->killed)))
770 		return nouveau_abi16_put(abi16, -ENODEV);
771 
772 	sync = req->vram_available & NOUVEAU_GEM_PUSHBUF_SYNC;
773 
774 	req->vram_available = drm->gem.vram_available;
775 	req->gart_available = drm->gem.gart_available;
776 	if (unlikely(req->nr_push == 0))
777 		goto out_next;
778 
779 	if (unlikely(req->nr_push > NOUVEAU_GEM_MAX_PUSH)) {
780 		NV_PRINTK(err, cli, "pushbuf push count exceeds limit: %d max %d\n",
781 			 req->nr_push, NOUVEAU_GEM_MAX_PUSH);
782 		return nouveau_abi16_put(abi16, -EINVAL);
783 	}
784 
785 	if (unlikely(req->nr_buffers > NOUVEAU_GEM_MAX_BUFFERS)) {
786 		NV_PRINTK(err, cli, "pushbuf bo count exceeds limit: %d max %d\n",
787 			 req->nr_buffers, NOUVEAU_GEM_MAX_BUFFERS);
788 		return nouveau_abi16_put(abi16, -EINVAL);
789 	}
790 
791 	if (unlikely(req->nr_relocs > NOUVEAU_GEM_MAX_RELOCS)) {
792 		NV_PRINTK(err, cli, "pushbuf reloc count exceeds limit: %d max %d\n",
793 			 req->nr_relocs, NOUVEAU_GEM_MAX_RELOCS);
794 		return nouveau_abi16_put(abi16, -EINVAL);
795 	}
796 
797 	push = u_memcpya(req->push, req->nr_push, sizeof(*push));
798 	if (IS_ERR(push))
799 		return nouveau_abi16_put(abi16, PTR_ERR(push));
800 
801 	bo = u_memcpya(req->buffers, req->nr_buffers, sizeof(*bo));
802 	if (IS_ERR(bo)) {
803 		u_free(push);
804 		return nouveau_abi16_put(abi16, PTR_ERR(bo));
805 	}
806 
807 	/* Ensure all push buffers are on validate list */
808 	for (i = 0; i < req->nr_push; i++) {
809 		if (push[i].bo_index >= req->nr_buffers) {
810 			NV_PRINTK(err, cli, "push %d buffer not in list\n", i);
811 			ret = -EINVAL;
812 			goto out_prevalid;
813 		}
814 	}
815 
816 	/* Validate buffer list */
817 revalidate:
818 	ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo,
819 					   req->nr_buffers, &op, &do_reloc);
820 	if (ret) {
821 		if (ret != -ERESTARTSYS)
822 			NV_PRINTK(err, cli, "validate: %d\n", ret);
823 		goto out_prevalid;
824 	}
825 
826 	/* Apply any relocations that are required */
827 	if (do_reloc) {
828 		if (!reloc) {
829 			validate_fini(&op, chan, NULL, bo);
830 			reloc = u_memcpya(req->relocs, req->nr_relocs, sizeof(*reloc));
831 			if (IS_ERR(reloc)) {
832 				ret = PTR_ERR(reloc);
833 				goto out_prevalid;
834 			}
835 
836 			goto revalidate;
837 		}
838 
839 		ret = nouveau_gem_pushbuf_reloc_apply(cli, req, reloc, bo);
840 		if (ret) {
841 			NV_PRINTK(err, cli, "reloc apply: %d\n", ret);
842 			goto out;
843 		}
844 	}
845 
846 	if (chan->dma.ib_max) {
847 		ret = nouveau_dma_wait(chan, req->nr_push + 1, 16);
848 		if (ret) {
849 			NV_PRINTK(err, cli, "nv50cal_space: %d\n", ret);
850 			goto out;
851 		}
852 
853 		for (i = 0; i < req->nr_push; i++) {
854 			struct nouveau_vma *vma = (void *)(unsigned long)
855 				bo[push[i].bo_index].user_priv;
856 			u64 addr = vma->addr + push[i].offset;
857 			u32 length = push[i].length & ~NOUVEAU_GEM_PUSHBUF_NO_PREFETCH;
858 			bool no_prefetch = push[i].length & NOUVEAU_GEM_PUSHBUF_NO_PREFETCH;
859 
860 			nv50_dma_push(chan, addr, length, no_prefetch);
861 		}
862 	} else
863 	if (drm->client.device.info.chipset >= 0x25) {
864 		ret = PUSH_WAIT(chan->chan.push, req->nr_push * 2);
865 		if (ret) {
866 			NV_PRINTK(err, cli, "cal_space: %d\n", ret);
867 			goto out;
868 		}
869 
870 		for (i = 0; i < req->nr_push; i++) {
871 			struct nouveau_bo *nvbo = (void *)(unsigned long)
872 				bo[push[i].bo_index].user_priv;
873 
874 			PUSH_CALL(chan->chan.push, nvbo->offset + push[i].offset);
875 			PUSH_DATA(chan->chan.push, 0);
876 		}
877 	} else {
878 		ret = PUSH_WAIT(chan->chan.push, req->nr_push * (2 + NOUVEAU_DMA_SKIPS));
879 		if (ret) {
880 			NV_PRINTK(err, cli, "jmp_space: %d\n", ret);
881 			goto out;
882 		}
883 
884 		for (i = 0; i < req->nr_push; i++) {
885 			struct nouveau_bo *nvbo = (void *)(unsigned long)
886 				bo[push[i].bo_index].user_priv;
887 			uint32_t cmd;
888 
889 			cmd = chan->push.addr + ((chan->dma.cur + 2) << 2);
890 			cmd |= 0x20000000;
891 			if (unlikely(cmd != req->suffix0)) {
892 				if (!nvbo->kmap.virtual) {
893 					ret = ttm_bo_kmap(&nvbo->bo, 0,
894 							  PFN_UP(nvbo->bo.base.size),
895 							  &nvbo->kmap);
896 					if (ret) {
897 						WIND_RING(chan);
898 						goto out;
899 					}
900 					nvbo->validate_mapped = true;
901 				}
902 
903 				nouveau_bo_wr32(nvbo, (push[i].offset +
904 						push[i].length - 8) / 4, cmd);
905 			}
906 
907 			PUSH_JUMP(chan->chan.push, nvbo->offset + push[i].offset);
908 			PUSH_DATA(chan->chan.push, 0);
909 			for (j = 0; j < NOUVEAU_DMA_SKIPS; j++)
910 				PUSH_DATA(chan->chan.push, 0);
911 		}
912 	}
913 
914 	ret = nouveau_fence_new(&fence, chan);
915 	if (ret) {
916 		NV_PRINTK(err, cli, "error fencing pushbuf: %d\n", ret);
917 		WIND_RING(chan);
918 		goto out;
919 	}
920 
921 	if (sync) {
922 		if (!(ret = nouveau_fence_wait(fence, false, false))) {
923 			if ((ret = dma_fence_get_status(&fence->base)) == 1)
924 				ret = 0;
925 		}
926 	}
927 
928 out:
929 	validate_fini(&op, chan, fence, bo);
930 	nouveau_fence_unref(&fence);
931 
932 	if (do_reloc) {
933 		struct drm_nouveau_gem_pushbuf_bo __user *upbbo =
934 			u64_to_user_ptr(req->buffers);
935 
936 		for (i = 0; i < req->nr_buffers; i++) {
937 			if (bo[i].presumed.valid)
938 				continue;
939 
940 			if (copy_to_user(&upbbo[i].presumed, &bo[i].presumed,
941 					 sizeof(bo[i].presumed))) {
942 				ret = -EFAULT;
943 				break;
944 			}
945 		}
946 	}
947 out_prevalid:
948 	if (!IS_ERR(reloc))
949 		u_free(reloc);
950 	u_free(bo);
951 	u_free(push);
952 
953 out_next:
954 	if (chan->dma.ib_max) {
955 		req->suffix0 = 0x00000000;
956 		req->suffix1 = 0x00000000;
957 	} else
958 	if (drm->client.device.info.chipset >= 0x25) {
959 		req->suffix0 = 0x00020000;
960 		req->suffix1 = 0x00000000;
961 	} else {
962 		req->suffix0 = 0x20000000 |
963 			      (chan->push.addr + ((chan->dma.cur + 2) << 2));
964 		req->suffix1 = 0x00000000;
965 	}
966 
967 	return nouveau_abi16_put(abi16, ret);
968 }
969 
970 int
nouveau_gem_ioctl_cpu_prep(struct drm_device * dev,void * data,struct drm_file * file_priv)971 nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data,
972 			   struct drm_file *file_priv)
973 {
974 	struct drm_nouveau_gem_cpu_prep *req = data;
975 	struct drm_gem_object *gem;
976 	struct nouveau_bo *nvbo;
977 	bool no_wait = !!(req->flags & NOUVEAU_GEM_CPU_PREP_NOWAIT);
978 	bool write = !!(req->flags & NOUVEAU_GEM_CPU_PREP_WRITE);
979 	long lret;
980 	int ret;
981 
982 	gem = drm_gem_object_lookup(file_priv, req->handle);
983 	if (!gem)
984 		return -ENOENT;
985 	nvbo = nouveau_gem_object(gem);
986 
987 	lret = dma_resv_wait_timeout(nvbo->bo.base.resv,
988 				     dma_resv_usage_rw(write), true,
989 				     no_wait ? 0 : 30 * HZ);
990 	if (!lret)
991 		ret = -EBUSY;
992 	else if (lret > 0)
993 		ret = 0;
994 	else
995 		ret = lret;
996 
997 	nouveau_bo_sync_for_cpu(nvbo);
998 	drm_gem_object_put(gem);
999 
1000 	return ret;
1001 }
1002 
1003 int
nouveau_gem_ioctl_cpu_fini(struct drm_device * dev,void * data,struct drm_file * file_priv)1004 nouveau_gem_ioctl_cpu_fini(struct drm_device *dev, void *data,
1005 			   struct drm_file *file_priv)
1006 {
1007 	struct drm_nouveau_gem_cpu_fini *req = data;
1008 	struct drm_gem_object *gem;
1009 	struct nouveau_bo *nvbo;
1010 
1011 	gem = drm_gem_object_lookup(file_priv, req->handle);
1012 	if (!gem)
1013 		return -ENOENT;
1014 	nvbo = nouveau_gem_object(gem);
1015 
1016 	nouveau_bo_sync_for_device(nvbo);
1017 	drm_gem_object_put(gem);
1018 	return 0;
1019 }
1020 
1021 int
nouveau_gem_ioctl_info(struct drm_device * dev,void * data,struct drm_file * file_priv)1022 nouveau_gem_ioctl_info(struct drm_device *dev, void *data,
1023 		       struct drm_file *file_priv)
1024 {
1025 	struct drm_nouveau_gem_info *req = data;
1026 	struct drm_gem_object *gem;
1027 	int ret;
1028 
1029 	gem = drm_gem_object_lookup(file_priv, req->handle);
1030 	if (!gem)
1031 		return -ENOENT;
1032 
1033 	ret = nouveau_gem_info(file_priv, gem, req);
1034 	drm_gem_object_put(gem);
1035 	return ret;
1036 }
1037 
1038