diff options
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bo.c | 15 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_gem.c | 36 |
3 files changed, 42 insertions, 10 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 84f85183d041..f6f44779d82f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c | |||
| @@ -36,6 +36,21 @@ | |||
| 36 | #include <linux/log2.h> | 36 | #include <linux/log2.h> |
| 37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
| 38 | 38 | ||
| 39 | int | ||
| 40 | nouveau_bo_sync_gpu(struct nouveau_bo *nvbo, struct nouveau_channel *chan) | ||
| 41 | { | ||
| 42 | struct nouveau_fence *prev_fence = nvbo->bo.sync_obj; | ||
| 43 | int ret; | ||
| 44 | |||
| 45 | if (!prev_fence || nouveau_fence_channel(prev_fence) == chan) | ||
| 46 | return 0; | ||
| 47 | |||
| 48 | spin_lock(&nvbo->bo.lock); | ||
| 49 | ret = ttm_bo_wait(&nvbo->bo, false, false, false); | ||
| 50 | spin_unlock(&nvbo->bo.lock); | ||
| 51 | return ret; | ||
| 52 | } | ||
| 53 | |||
| 39 | static void | 54 | static void |
| 40 | nouveau_bo_del_ttm(struct ttm_buffer_object *bo) | 55 | nouveau_bo_del_ttm(struct ttm_buffer_object *bo) |
| 41 | { | 56 | { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index e424bf74d706..1e093a069b7b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h | |||
| @@ -1165,6 +1165,7 @@ extern u16 nouveau_bo_rd16(struct nouveau_bo *nvbo, unsigned index); | |||
| 1165 | extern void nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val); | 1165 | extern void nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val); |
| 1166 | extern u32 nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index); | 1166 | extern u32 nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index); |
| 1167 | extern void nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val); | 1167 | extern void nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val); |
| 1168 | extern int nouveau_bo_sync_gpu(struct nouveau_bo *, struct nouveau_channel *); | ||
| 1168 | 1169 | ||
| 1169 | /* nouveau_fence.c */ | 1170 | /* nouveau_fence.c */ |
| 1170 | struct nouveau_fence; | 1171 | struct nouveau_fence; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 547f2c24c1e7..a915dcdd9a49 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c | |||
| @@ -361,16 +361,11 @@ validate_list(struct nouveau_channel *chan, struct list_head *list, | |||
| 361 | 361 | ||
| 362 | list_for_each_entry(nvbo, list, entry) { | 362 | list_for_each_entry(nvbo, list, entry) { |
| 363 | struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index]; | 363 | struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index]; |
| 364 | struct nouveau_fence *prev_fence = nvbo->bo.sync_obj; | ||
| 365 | 364 | ||
| 366 | if (prev_fence && nouveau_fence_channel(prev_fence) != chan) { | 365 | ret = nouveau_bo_sync_gpu(nvbo, chan); |
| 367 | spin_lock(&nvbo->bo.lock); | 366 | if (unlikely(ret)) { |
| 368 | ret = ttm_bo_wait(&nvbo->bo, false, false, false); | 367 | NV_ERROR(dev, "fail pre-validate sync\n"); |
| 369 | spin_unlock(&nvbo->bo.lock); | 368 | return ret; |
| 370 | if (unlikely(ret)) { | ||
| 371 | NV_ERROR(dev, "fail wait other chan\n"); | ||
| 372 | return ret; | ||
| 373 | } | ||
| 374 | } | 369 | } |
| 375 | 370 | ||
| 376 | ret = nouveau_gem_set_domain(nvbo->gem, b->read_domains, | 371 | ret = nouveau_gem_set_domain(nvbo->gem, b->read_domains, |
| @@ -381,7 +376,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list, | |||
| 381 | return ret; | 376 | return ret; |
| 382 | } | 377 | } |
| 383 | 378 | ||
| 384 | nvbo->channel = chan; | 379 | nvbo->channel = (b->read_domains & (1 << 31)) ? NULL : chan; |
| 385 | ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement, | 380 | ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement, |
| 386 | false, false, false); | 381 | false, false, false); |
| 387 | nvbo->channel = NULL; | 382 | nvbo->channel = NULL; |
| @@ -390,6 +385,12 @@ validate_list(struct nouveau_channel *chan, struct list_head *list, | |||
| 390 | return ret; | 385 | return ret; |
| 391 | } | 386 | } |
| 392 | 387 | ||
| 388 | ret = nouveau_bo_sync_gpu(nvbo, chan); | ||
| 389 | if (unlikely(ret)) { | ||
| 390 | NV_ERROR(dev, "fail post-validate sync\n"); | ||
| 391 | return ret; | ||
| 392 | } | ||
| 393 | |||
| 393 | if (nvbo->bo.offset == b->presumed.offset && | 394 | if (nvbo->bo.offset == b->presumed.offset && |
| 394 | ((nvbo->bo.mem.mem_type == TTM_PL_VRAM && | 395 | ((nvbo->bo.mem.mem_type == TTM_PL_VRAM && |
| 395 | b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) || | 396 | b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) || |
| @@ -615,6 +616,21 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, | |||
| 615 | 616 | ||
| 616 | mutex_lock(&dev->struct_mutex); | 617 | mutex_lock(&dev->struct_mutex); |
| 617 | 618 | ||
| 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 | } | ||
| 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, |
| 620 | req->nr_buffers, &op, &do_reloc); | 636 | req->nr_buffers, &op, &do_reloc); |
