diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_gem.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_gem.c | 47 |
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, | |||
713 | out: | 729 | out: |
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 { |