aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nouveau_gem.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_gem.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_gem.c47
1 files changed, 31 insertions, 16 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index 0f417ac1b69..ead7b8fc53f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -245,7 +245,7 @@ validate_fini_list(struct list_head *list, struct nouveau_fence *fence)
245 list_del(&nvbo->entry); 245 list_del(&nvbo->entry);
246 nvbo->reserved_by = NULL; 246 nvbo->reserved_by = NULL;
247 ttm_bo_unreserve(&nvbo->bo); 247 ttm_bo_unreserve(&nvbo->bo);
248 drm_gem_object_unreference(nvbo->gem); 248 drm_gem_object_unreference_unlocked(nvbo->gem);
249 } 249 }
250} 250}
251 251
@@ -300,7 +300,7 @@ retry:
300 validate_fini(op, NULL); 300 validate_fini(op, NULL);
301 if (ret == -EAGAIN) 301 if (ret == -EAGAIN)
302 ret = ttm_bo_wait_unreserved(&nvbo->bo, false); 302 ret = ttm_bo_wait_unreserved(&nvbo->bo, false);
303 drm_gem_object_unreference(gem); 303 drm_gem_object_unreference_unlocked(gem);
304 if (ret) { 304 if (ret) {
305 NV_ERROR(dev, "fail reserve\n"); 305 NV_ERROR(dev, "fail reserve\n");
306 return ret; 306 return ret;
@@ -337,7 +337,9 @@ retry:
337 return -EINVAL; 337 return -EINVAL;
338 } 338 }
339 339
340 mutex_unlock(&drm_global_mutex);
340 ret = ttm_bo_wait_cpu(&nvbo->bo, false); 341 ret = ttm_bo_wait_cpu(&nvbo->bo, false);
342 mutex_lock(&drm_global_mutex);
341 if (ret) { 343 if (ret) {
342 NV_ERROR(dev, "fail wait_cpu\n"); 344 NV_ERROR(dev, "fail wait_cpu\n");
343 return ret; 345 return ret;
@@ -361,16 +363,11 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
361 363
362 list_for_each_entry(nvbo, list, entry) { 364 list_for_each_entry(nvbo, list, entry) {
363 struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index]; 365 struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index];
364 struct nouveau_fence *prev_fence = nvbo->bo.sync_obj;
365 366
366 if (prev_fence && nouveau_fence_channel(prev_fence) != chan) { 367 ret = nouveau_bo_sync_gpu(nvbo, chan);
367 spin_lock(&nvbo->bo.lock); 368 if (unlikely(ret)) {
368 ret = ttm_bo_wait(&nvbo->bo, false, false, false); 369 NV_ERROR(dev, "fail pre-validate sync\n");
369 spin_unlock(&nvbo->bo.lock); 370 return ret;
370 if (unlikely(ret)) {
371 NV_ERROR(dev, "fail wait other chan\n");
372 return ret;
373 }
374 } 371 }
375 372
376 ret = nouveau_gem_set_domain(nvbo->gem, b->read_domains, 373 ret = nouveau_gem_set_domain(nvbo->gem, b->read_domains,
@@ -381,7 +378,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
381 return ret; 378 return ret;
382 } 379 }
383 380
384 nvbo->channel = chan; 381 nvbo->channel = (b->read_domains & (1 << 31)) ? NULL : chan;
385 ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement, 382 ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement,
386 false, false, false); 383 false, false, false);
387 nvbo->channel = NULL; 384 nvbo->channel = NULL;
@@ -390,6 +387,12 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
390 return ret; 387 return ret;
391 } 388 }
392 389
390 ret = nouveau_bo_sync_gpu(nvbo, chan);
391 if (unlikely(ret)) {
392 NV_ERROR(dev, "fail post-validate sync\n");
393 return ret;
394 }
395
393 if (nvbo->bo.offset == b->presumed.offset && 396 if (nvbo->bo.offset == b->presumed.offset &&
394 ((nvbo->bo.mem.mem_type == TTM_PL_VRAM && 397 ((nvbo->bo.mem.mem_type == TTM_PL_VRAM &&
395 b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) || 398 b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) ||
@@ -613,7 +616,20 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
613 return PTR_ERR(bo); 616 return PTR_ERR(bo);
614 } 617 }
615 618
616 mutex_lock(&dev->struct_mutex); 619 /* Mark push buffers as being used on PFIFO, the validation code
620 * will then make sure that if the pushbuf bo moves, that they
621 * happen on the kernel channel, which will in turn cause a sync
622 * to happen before we try and submit the push buffer.
623 */
624 for (i = 0; i < req->nr_push; i++) {
625 if (push[i].bo_index >= req->nr_buffers) {
626 NV_ERROR(dev, "push %d buffer not in list\n", i);
627 ret = -EINVAL;
628 goto out;
629 }
630
631 bo[push[i].bo_index].read_domains |= (1 << 31);
632 }
617 633
618 /* Validate buffer list */ 634 /* Validate buffer list */
619 ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo, req->buffers, 635 ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo, req->buffers,
@@ -647,7 +663,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
647 push[i].length); 663 push[i].length);
648 } 664 }
649 } else 665 } else
650 if (dev_priv->card_type >= NV_20) { 666 if (dev_priv->chipset >= 0x25) {
651 ret = RING_SPACE(chan, req->nr_push * 2); 667 ret = RING_SPACE(chan, req->nr_push * 2);
652 if (ret) { 668 if (ret) {
653 NV_ERROR(dev, "cal_space: %d\n", ret); 669 NV_ERROR(dev, "cal_space: %d\n", ret);
@@ -713,7 +729,6 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
713out: 729out:
714 validate_fini(&op, fence); 730 validate_fini(&op, fence);
715 nouveau_fence_unref((void**)&fence); 731 nouveau_fence_unref((void**)&fence);
716 mutex_unlock(&dev->struct_mutex);
717 kfree(bo); 732 kfree(bo);
718 kfree(push); 733 kfree(push);
719 734
@@ -722,7 +737,7 @@ out_next:
722 req->suffix0 = 0x00000000; 737 req->suffix0 = 0x00000000;
723 req->suffix1 = 0x00000000; 738 req->suffix1 = 0x00000000;
724 } else 739 } else
725 if (dev_priv->card_type >= NV_20) { 740 if (dev_priv->chipset >= 0x25) {
726 req->suffix0 = 0x00020000; 741 req->suffix0 = 0x00020000;
727 req->suffix1 = 0x00000000; 742 req->suffix1 = 0x00000000;
728 } else { 743 } else {