|
@@ -361,16 +361,11 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
|
|
|
|
|
|
list_for_each_entry(nvbo, list, entry) {
|
|
|
struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index];
|
|
|
- struct nouveau_fence *prev_fence = nvbo->bo.sync_obj;
|
|
|
|
|
|
- if (prev_fence && nouveau_fence_channel(prev_fence) != chan) {
|
|
|
- spin_lock(&nvbo->bo.lock);
|
|
|
- ret = ttm_bo_wait(&nvbo->bo, false, false, false);
|
|
|
- spin_unlock(&nvbo->bo.lock);
|
|
|
- if (unlikely(ret)) {
|
|
|
- NV_ERROR(dev, "fail wait other chan\n");
|
|
|
- return ret;
|
|
|
- }
|
|
|
+ ret = nouveau_bo_sync_gpu(nvbo, chan);
|
|
|
+ if (unlikely(ret)) {
|
|
|
+ NV_ERROR(dev, "fail pre-validate sync\n");
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
ret = nouveau_gem_set_domain(nvbo->gem, b->read_domains,
|
|
@@ -381,7 +376,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
- nvbo->channel = chan;
|
|
|
+ nvbo->channel = (b->read_domains & (1 << 31)) ? NULL : chan;
|
|
|
ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement,
|
|
|
false, false, false);
|
|
|
nvbo->channel = NULL;
|
|
@@ -390,6 +385,12 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+ ret = nouveau_bo_sync_gpu(nvbo, chan);
|
|
|
+ if (unlikely(ret)) {
|
|
|
+ NV_ERROR(dev, "fail post-validate sync\n");
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
if (nvbo->bo.offset == b->presumed.offset &&
|
|
|
((nvbo->bo.mem.mem_type == TTM_PL_VRAM &&
|
|
|
b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) ||
|
|
@@ -615,6 +616,21 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
|
|
|
|
|
|
mutex_lock(&dev->struct_mutex);
|
|
|
|
|
|
+ /* Mark push buffers as being used on PFIFO, the validation code
|
|
|
+ * will then make sure that if the pushbuf bo moves, that they
|
|
|
+ * happen on the kernel channel, which will in turn cause a sync
|
|
|
+ * to happen before we try and submit the push buffer.
|
|
|
+ */
|
|
|
+ for (i = 0; i < req->nr_push; i++) {
|
|
|
+ if (push[i].bo_index >= req->nr_buffers) {
|
|
|
+ NV_ERROR(dev, "push %d buffer not in list\n", i);
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ bo[push[i].bo_index].read_domains |= (1 << 31);
|
|
|
+ }
|
|
|
+
|
|
|
/* Validate buffer list */
|
|
|
ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo, req->buffers,
|
|
|
req->nr_buffers, &op, &do_reloc);
|