aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs2009-11-03 23:23:53 -0600
committerBen Skeggs2009-11-03 23:24:27 -0600
commitf4c50630269df4201b89a538cbf8e11646f17d82 (patch)
tree750228abbb1af6d0d00a962d857530c9303460b9
parenta8bdf0e00c0653fd343fd7fd64b5f2e8437bb130 (diff)
downloadexternal-libdrm-f4c50630269df4201b89a538cbf8e11646f17d82.tar.gz
external-libdrm-f4c50630269df4201b89a538cbf8e11646f17d82.tar.xz
external-libdrm-f4c50630269df4201b89a538cbf8e11646f17d82.zip
nouveau: modify api slightly to allow caller to handle reloc failures
Signed-off-by: Ben Skeggs <skeggsb@beleth.(none)>
-rw-r--r--libdrm/nouveau/nouveau_private.h3
-rw-r--r--libdrm/nouveau/nouveau_pushbuf.c53
-rw-r--r--libdrm/nouveau/nouveau_pushbuf.h53
3 files changed, 90 insertions, 19 deletions
diff --git a/libdrm/nouveau/nouveau_private.h b/libdrm/nouveau/nouveau_private.h
index 743c8314..784afc91 100644
--- a/libdrm/nouveau/nouveau_private.h
+++ b/libdrm/nouveau/nouveau_private.h
@@ -52,6 +52,9 @@ struct nouveau_pushbuf_priv {
52 unsigned *pushbuf; 52 unsigned *pushbuf;
53 unsigned size; 53 unsigned size;
54 54
55 unsigned marker;
56 unsigned marker_relocs;
57
55 struct drm_nouveau_gem_pushbuf_bo *buffers; 58 struct drm_nouveau_gem_pushbuf_bo *buffers;
56 unsigned nr_buffers; 59 unsigned nr_buffers;
57 struct drm_nouveau_gem_pushbuf_reloc *relocs; 60 struct drm_nouveau_gem_pushbuf_reloc *relocs;
diff --git a/libdrm/nouveau/nouveau_pushbuf.c b/libdrm/nouveau/nouveau_pushbuf.c
index af181b2e..df43effc 100644
--- a/libdrm/nouveau/nouveau_pushbuf.c
+++ b/libdrm/nouveau/nouveau_pushbuf.c
@@ -67,7 +67,6 @@ nouveau_pushbuf_emit_reloc(struct nouveau_channel *chan, void *ptr,
67 67
68 if (nvpb->nr_relocs >= NOUVEAU_GEM_MAX_RELOCS) { 68 if (nvpb->nr_relocs >= NOUVEAU_GEM_MAX_RELOCS) {
69 fprintf(stderr, "too many relocs!!\n"); 69 fprintf(stderr, "too many relocs!!\n");
70 assert(0);
71 return -ENOMEM; 70 return -ENOMEM;
72 } 71 }
73 72
@@ -79,7 +78,6 @@ nouveau_pushbuf_emit_reloc(struct nouveau_channel *chan, void *ptr,
79 pbbo = nouveau_bo_emit_buffer(chan, bo); 78 pbbo = nouveau_bo_emit_buffer(chan, bo);
80 if (!pbbo) { 79 if (!pbbo) {
81 fprintf(stderr, "buffer emit fail :(\n"); 80 fprintf(stderr, "buffer emit fail :(\n");
82 assert(0);
83 return -ENOMEM; 81 return -ENOMEM;
84 } 82 }
85 83
@@ -353,6 +351,57 @@ restart_push:
353 if (chan->flush_notify) 351 if (chan->flush_notify)
354 chan->flush_notify(chan); 352 chan->flush_notify(chan);
355 353
354 nvpb->marker = 0;
356 return ret; 355 return ret;
357} 356}
358 357
358int
359nouveau_pushbuf_marker_emit(struct nouveau_channel *chan,
360 unsigned wait_dwords, unsigned wait_relocs)
361{
362 struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(chan->pushbuf);
363
364 if (AVAIL_RING(chan) < wait_dwords)
365 return nouveau_pushbuf_flush(chan, wait_dwords);
366
367 if (nvpb->nr_relocs + wait_relocs >= NOUVEAU_GEM_MAX_RELOCS)
368 return nouveau_pushbuf_flush(chan, wait_dwords);
369
370 nvpb->marker = nvpb->base.cur - nvpb->pushbuf;
371 nvpb->marker_relocs = nvpb->nr_relocs;
372 return 0;
373}
374
375void
376nouveau_pushbuf_marker_undo(struct nouveau_channel *chan)
377{
378 struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(chan->pushbuf);
379 unsigned i;
380
381 if (!nvpb->marker)
382 return;
383
384 /* undo any relocs/buffers added to the list since last marker */
385 for (i = nvpb->marker_relocs; i < nvpb->nr_relocs; i++) {
386 struct drm_nouveau_gem_pushbuf_reloc *r = &nvpb->relocs[i];
387 struct drm_nouveau_gem_pushbuf_bo *pbbo =
388 &nvpb->buffers[r->bo_index];
389 struct nouveau_bo *bo = (void *)(unsigned long)pbbo->user_priv;
390 struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
391
392 if (--nvbo->pending_refcnt)
393 continue;
394
395 nvbo->pending = NULL;
396 nouveau_bo_ref(NULL, &bo);
397 nvpb->nr_buffers--;
398 }
399 nvpb->nr_relocs = nvpb->marker_relocs;
400
401 /* reset pushbuf back to last marker */
402 nvpb->base.cur = nvpb->pushbuf + nvpb->marker;
403 nvpb->base.remaining = nvpb->size - nvpb->marker;
404 nvpb->marker = 0;
405}
406
407
diff --git a/libdrm/nouveau/nouveau_pushbuf.h b/libdrm/nouveau/nouveau_pushbuf.h
index 3c746ed2..c7ac8c45 100644
--- a/libdrm/nouveau/nouveau_pushbuf.h
+++ b/libdrm/nouveau/nouveau_pushbuf.h
@@ -40,11 +40,30 @@ int
40nouveau_pushbuf_flush(struct nouveau_channel *, unsigned min); 40nouveau_pushbuf_flush(struct nouveau_channel *, unsigned min);
41 41
42int 42int
43nouveau_pushbuf_marker_emit(struct nouveau_channel *chan,
44 unsigned wait_dwords, unsigned wait_relocs);
45
46void
47nouveau_pushbuf_marker_undo(struct nouveau_channel *chan);
48
49int
43nouveau_pushbuf_emit_reloc(struct nouveau_channel *, void *ptr, 50nouveau_pushbuf_emit_reloc(struct nouveau_channel *, void *ptr,
44 struct nouveau_bo *, uint32_t data, uint32_t data2, 51 struct nouveau_bo *, uint32_t data, uint32_t data2,
45 uint32_t flags, uint32_t vor, uint32_t tor); 52 uint32_t flags, uint32_t vor, uint32_t tor);
46 53
47/* Push buffer access macros */ 54/* Push buffer access macros */
55static __inline__ int
56MARK_RING(struct nouveau_channel *chan, unsigned dwords, unsigned relocs)
57{
58 return nouveau_pushbuf_marker_emit(chan, dwords, relocs);
59}
60
61static __inline__ void
62MARK_UNDO(struct nouveau_channel *chan)
63{
64 nouveau_pushbuf_marker_undo(chan);
65}
66
48static __inline__ void 67static __inline__ void
49OUT_RING(struct nouveau_channel *chan, unsigned data) 68OUT_RING(struct nouveau_channel *chan, unsigned data)
50{ 69{
@@ -116,62 +135,62 @@ BIND_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr, unsigned sc)
116 OUT_RING (chan, gr->handle); 135 OUT_RING (chan, gr->handle);
117} 136}
118 137
119static __inline__ void 138static __inline__ int
120OUT_RELOC(struct nouveau_channel *chan, struct nouveau_bo *bo, 139OUT_RELOC(struct nouveau_channel *chan, struct nouveau_bo *bo,
121 unsigned data, unsigned flags, unsigned vor, unsigned tor) 140 unsigned data, unsigned flags, unsigned vor, unsigned tor)
122{ 141{
123 nouveau_pushbuf_emit_reloc(chan, chan->pushbuf->cur++, bo, 142 return nouveau_pushbuf_emit_reloc(chan, chan->pushbuf->cur++, bo,
124 data, 0, flags, vor, tor); 143 data, 0, flags, vor, tor);
125} 144}
126 145
127static __inline__ void 146static __inline__ int
128OUT_RELOC2(struct nouveau_channel *chan, struct nouveau_bo *bo, 147OUT_RELOC2(struct nouveau_channel *chan, struct nouveau_bo *bo,
129 unsigned data, unsigned data2, unsigned flags, 148 unsigned data, unsigned data2, unsigned flags,
130 unsigned vor, unsigned tor) 149 unsigned vor, unsigned tor)
131{ 150{
132 nouveau_pushbuf_emit_reloc(chan, chan->pushbuf->cur++, bo, 151 return nouveau_pushbuf_emit_reloc(chan, chan->pushbuf->cur++, bo,
133 data, data2, flags, vor, tor); 152 data, data2, flags, vor, tor);
134} 153}
135 154
136/* Raw data + flags depending on FB/TT buffer */ 155/* Raw data + flags depending on FB/TT buffer */
137static __inline__ void 156static __inline__ int
138OUT_RELOCd(struct nouveau_channel *chan, struct nouveau_bo *bo, 157OUT_RELOCd(struct nouveau_channel *chan, struct nouveau_bo *bo,
139 unsigned data, unsigned flags, unsigned vor, unsigned tor) 158 unsigned data, unsigned flags, unsigned vor, unsigned tor)
140{ 159{
141 OUT_RELOC(chan, bo, data, flags | NOUVEAU_BO_OR, vor, tor); 160 return OUT_RELOC(chan, bo, data, flags | NOUVEAU_BO_OR, vor, tor);
142} 161}
143 162
144/* FB/TT object handle */ 163/* FB/TT object handle */
145static __inline__ void 164static __inline__ int
146OUT_RELOCo(struct nouveau_channel *chan, struct nouveau_bo *bo, 165OUT_RELOCo(struct nouveau_channel *chan, struct nouveau_bo *bo,
147 unsigned flags) 166 unsigned flags)
148{ 167{
149 OUT_RELOC(chan, bo, 0, flags | NOUVEAU_BO_OR, 168 return OUT_RELOC(chan, bo, 0, flags | NOUVEAU_BO_OR,
150 chan->vram->handle, chan->gart->handle); 169 chan->vram->handle, chan->gart->handle);
151} 170}
152 171
153/* Low 32-bits of offset */ 172/* Low 32-bits of offset */
154static __inline__ void 173static __inline__ int
155OUT_RELOCl(struct nouveau_channel *chan, struct nouveau_bo *bo, 174OUT_RELOCl(struct nouveau_channel *chan, struct nouveau_bo *bo,
156 unsigned delta, unsigned flags) 175 unsigned delta, unsigned flags)
157{ 176{
158 OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_LOW, 0, 0); 177 return OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_LOW, 0, 0);
159} 178}
160 179
161/* Low 32-bits of offset + GPU linear access range info */ 180/* Low 32-bits of offset + GPU linear access range info */
162static __inline__ void 181static __inline__ int
163OUT_RELOCr(struct nouveau_channel *chan, struct nouveau_bo *bo, 182OUT_RELOCr(struct nouveau_channel *chan, struct nouveau_bo *bo,
164 unsigned delta, unsigned size, unsigned flags) 183 unsigned delta, unsigned size, unsigned flags)
165{ 184{
166 OUT_RELOC2(chan, bo, delta, size, flags | NOUVEAU_BO_LOW, 0, 0); 185 return OUT_RELOC2(chan, bo, delta, size, flags | NOUVEAU_BO_LOW, 0, 0);
167} 186}
168 187
169/* High 32-bits of offset */ 188/* High 32-bits of offset */
170static __inline__ void 189static __inline__ int
171OUT_RELOCh(struct nouveau_channel *chan, struct nouveau_bo *bo, 190OUT_RELOCh(struct nouveau_channel *chan, struct nouveau_bo *bo,
172 unsigned delta, unsigned flags) 191 unsigned delta, unsigned flags)
173{ 192{
174 OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_HIGH, 0, 0); 193 return OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_HIGH, 0, 0);
175} 194}
176 195
177#endif 196#endif