summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2009-10-27 14:32:40 +1000
committerBen Skeggs <skeggsb@beleth.(none)>2009-11-04 14:58:19 +1000
commita8bdf0e00c0653fd343fd7fd64b5f2e8437bb130 (patch)
tree43c6b49c4519126f0191df1d9596969d70ac2f3a
parent63910f8aa624be5f2eaa78e08a318d388a22f829 (diff)
nouveau: add reloc refcnt to pending bo list
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--libdrm/nouveau/nouveau_bo.c1
-rw-r--r--libdrm/nouveau/nouveau_private.h1
-rw-r--r--libdrm/nouveau/nouveau_pushbuf.c24
3 files changed, 19 insertions, 7 deletions
diff --git a/libdrm/nouveau/nouveau_bo.c b/libdrm/nouveau/nouveau_bo.c
index b7e6d867..85fc14f6 100644
--- a/libdrm/nouveau/nouveau_bo.c
+++ b/libdrm/nouveau/nouveau_bo.c
@@ -607,6 +607,7 @@ nouveau_bo_emit_buffer(struct nouveau_channel *chan, struct nouveau_bo *bo)
pbbo = nvpb->buffers + nvpb->nr_buffers++;
nvbo->pending = pbbo;
nvbo->pending_channel = chan;
+ nvbo->pending_refcnt = 0;
nouveau_bo_ref(bo, &ref);
pbbo->user_priv = (uint64_t)(unsigned long)ref;
diff --git a/libdrm/nouveau/nouveau_private.h b/libdrm/nouveau/nouveau_private.h
index 9ce87fb2..743c8314 100644
--- a/libdrm/nouveau/nouveau_private.h
+++ b/libdrm/nouveau/nouveau_private.h
@@ -99,6 +99,7 @@ struct nouveau_bo_priv {
/* Tracking */
struct drm_nouveau_gem_pushbuf_bo *pending;
struct nouveau_channel *pending_channel;
+ int pending_refcnt;
int write_marker;
/* Userspace object */
diff --git a/libdrm/nouveau/nouveau_pushbuf.c b/libdrm/nouveau/nouveau_pushbuf.c
index d434a5fc..af181b2e 100644
--- a/libdrm/nouveau/nouveau_pushbuf.c
+++ b/libdrm/nouveau/nouveau_pushbuf.c
@@ -60,6 +60,7 @@ nouveau_pushbuf_emit_reloc(struct nouveau_channel *chan, void *ptr,
uint32_t flags, uint32_t vor, uint32_t tor)
{
struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(chan->pushbuf);
+ struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
struct drm_nouveau_gem_pushbuf_reloc *r;
struct drm_nouveau_gem_pushbuf_bo *pbbo;
uint32_t domains = 0;
@@ -70,7 +71,7 @@ nouveau_pushbuf_emit_reloc(struct nouveau_channel *chan, void *ptr,
return -ENOMEM;
}
- if (nouveau_bo(bo)->user && (flags & NOUVEAU_BO_WR)) {
+ if (nvbo->user && (flags & NOUVEAU_BO_WR)) {
fprintf(stderr, "write to user buffer!!\n");
return -EINVAL;
}
@@ -82,6 +83,8 @@ nouveau_pushbuf_emit_reloc(struct nouveau_channel *chan, void *ptr,
return -ENOMEM;
}
+ nvbo->pending_refcnt++;
+
if (flags & NOUVEAU_BO_VRAM)
domains |= NOUVEAU_GEM_DOMAIN_VRAM;
if (flags & NOUVEAU_BO_GART)
@@ -95,7 +98,7 @@ nouveau_pushbuf_emit_reloc(struct nouveau_channel *chan, void *ptr,
}
if (flags & NOUVEAU_BO_WR) {
pbbo->write_domains |= domains;
- nouveau_bo(bo)->write_marker = 1;
+ nvbo->write_marker = 1;
}
r = nvpb->relocs + nvpb->nr_relocs++;
@@ -322,18 +325,25 @@ restart_push:
/* Update presumed offset/domain for any buffers that moved.
* Dereference all buffers on validate list
*/
- for (i = 0; i < nvpb->nr_buffers; i++) {
- struct drm_nouveau_gem_pushbuf_bo *pbbo = &nvpb->buffers[i];
+ for (i = 0; i < nvpb->nr_relocs; i++) {
+ struct drm_nouveau_gem_pushbuf_reloc *r = &nvpb->relocs[i];
+ struct drm_nouveau_gem_pushbuf_bo *pbbo =
+ &nvpb->buffers[r->bo_index];
struct nouveau_bo *bo = (void *)(unsigned long)pbbo->user_priv;
+ struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
+
+ if (--nvbo->pending_refcnt)
+ continue;
if (pbbo->presumed_ok == 0) {
- nouveau_bo(bo)->domain = pbbo->presumed_domain;
- nouveau_bo(bo)->offset = pbbo->presumed_offset;
+ nvbo->domain = pbbo->presumed_domain;
+ nvbo->offset = pbbo->presumed_offset;
}
- nouveau_bo(bo)->pending = NULL;
+ nvbo->pending = NULL;
nouveau_bo_ref(NULL, &bo);
}
+
nvpb->nr_buffers = 0;
nvpb->nr_relocs = 0;