From 37021a4bd58eeeaf11fe98013cdd8e96f9bd9c54 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 23 Jul 2010 09:06:52 +1000 Subject: [PATCH] --- yaml --- r: 209817 b: refs/heads/master c: 415e6186f17136075f7cc825ba3835d005773637 h: refs/heads/master i: 209815: 395a4ba4ee92db6d0dfab9cce22b0dde24d1cbdb v: v3 --- [refs] | 2 +- trunk/drivers/gpu/drm/nouveau/nouveau_bo.c | 15 +++++++++ trunk/drivers/gpu/drm/nouveau/nouveau_drv.h | 1 + trunk/drivers/gpu/drm/nouveau/nouveau_gem.c | 36 +++++++++++++++------ 4 files changed, 43 insertions(+), 11 deletions(-) diff --git a/[refs] b/[refs] index d9371ed286b1..2d85fe0cf9ee 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 56dfc58ea094e7a8607786f4762c65b09cd85738 +refs/heads/master: 415e6186f17136075f7cc825ba3835d005773637 diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_bo.c b/trunk/drivers/gpu/drm/nouveau/nouveau_bo.c index 84f85183d041..f6f44779d82f 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -36,6 +36,21 @@ #include #include +int +nouveau_bo_sync_gpu(struct nouveau_bo *nvbo, struct nouveau_channel *chan) +{ + struct nouveau_fence *prev_fence = nvbo->bo.sync_obj; + int ret; + + if (!prev_fence || nouveau_fence_channel(prev_fence) == chan) + return 0; + + spin_lock(&nvbo->bo.lock); + ret = ttm_bo_wait(&nvbo->bo, false, false, false); + spin_unlock(&nvbo->bo.lock); + return ret; +} + static void nouveau_bo_del_ttm(struct ttm_buffer_object *bo) { diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_drv.h b/trunk/drivers/gpu/drm/nouveau/nouveau_drv.h index e424bf74d706..1e093a069b7b 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -1165,6 +1165,7 @@ extern u16 nouveau_bo_rd16(struct nouveau_bo *nvbo, unsigned index); extern void nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val); extern u32 nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index); extern void nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val); +extern int nouveau_bo_sync_gpu(struct nouveau_bo *, struct nouveau_channel *); /* nouveau_fence.c */ struct nouveau_fence; diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_gem.c b/trunk/drivers/gpu/drm/nouveau/nouveau_gem.c index 547f2c24c1e7..a915dcdd9a49 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -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);