mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2026-01-04 06:20:20 +01:00
nouveau: modify api slightly to allow caller to handle reloc failures
Signed-off-by: Ben Skeggs <skeggsb@beleth.(none)>
This commit is contained in:
parent
a8bdf0e00c
commit
f4c5063026
3 changed files with 90 additions and 19 deletions
|
|
@ -52,6 +52,9 @@ struct nouveau_pushbuf_priv {
|
|||
unsigned *pushbuf;
|
||||
unsigned size;
|
||||
|
||||
unsigned marker;
|
||||
unsigned marker_relocs;
|
||||
|
||||
struct drm_nouveau_gem_pushbuf_bo *buffers;
|
||||
unsigned nr_buffers;
|
||||
struct drm_nouveau_gem_pushbuf_reloc *relocs;
|
||||
|
|
|
|||
|
|
@ -67,7 +67,6 @@ nouveau_pushbuf_emit_reloc(struct nouveau_channel *chan, void *ptr,
|
|||
|
||||
if (nvpb->nr_relocs >= NOUVEAU_GEM_MAX_RELOCS) {
|
||||
fprintf(stderr, "too many relocs!!\n");
|
||||
assert(0);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
|
@ -79,7 +78,6 @@ nouveau_pushbuf_emit_reloc(struct nouveau_channel *chan, void *ptr,
|
|||
pbbo = nouveau_bo_emit_buffer(chan, bo);
|
||||
if (!pbbo) {
|
||||
fprintf(stderr, "buffer emit fail :(\n");
|
||||
assert(0);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
|
@ -353,6 +351,57 @@ restart_push:
|
|||
if (chan->flush_notify)
|
||||
chan->flush_notify(chan);
|
||||
|
||||
nvpb->marker = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_pushbuf_marker_emit(struct nouveau_channel *chan,
|
||||
unsigned wait_dwords, unsigned wait_relocs)
|
||||
{
|
||||
struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(chan->pushbuf);
|
||||
|
||||
if (AVAIL_RING(chan) < wait_dwords)
|
||||
return nouveau_pushbuf_flush(chan, wait_dwords);
|
||||
|
||||
if (nvpb->nr_relocs + wait_relocs >= NOUVEAU_GEM_MAX_RELOCS)
|
||||
return nouveau_pushbuf_flush(chan, wait_dwords);
|
||||
|
||||
nvpb->marker = nvpb->base.cur - nvpb->pushbuf;
|
||||
nvpb->marker_relocs = nvpb->nr_relocs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nouveau_pushbuf_marker_undo(struct nouveau_channel *chan)
|
||||
{
|
||||
struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(chan->pushbuf);
|
||||
unsigned i;
|
||||
|
||||
if (!nvpb->marker)
|
||||
return;
|
||||
|
||||
/* undo any relocs/buffers added to the list since last marker */
|
||||
for (i = nvpb->marker_relocs; 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;
|
||||
|
||||
nvbo->pending = NULL;
|
||||
nouveau_bo_ref(NULL, &bo);
|
||||
nvpb->nr_buffers--;
|
||||
}
|
||||
nvpb->nr_relocs = nvpb->marker_relocs;
|
||||
|
||||
/* reset pushbuf back to last marker */
|
||||
nvpb->base.cur = nvpb->pushbuf + nvpb->marker;
|
||||
nvpb->base.remaining = nvpb->size - nvpb->marker;
|
||||
nvpb->marker = 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -39,12 +39,31 @@ struct nouveau_pushbuf {
|
|||
int
|
||||
nouveau_pushbuf_flush(struct nouveau_channel *, unsigned min);
|
||||
|
||||
int
|
||||
nouveau_pushbuf_marker_emit(struct nouveau_channel *chan,
|
||||
unsigned wait_dwords, unsigned wait_relocs);
|
||||
|
||||
void
|
||||
nouveau_pushbuf_marker_undo(struct nouveau_channel *chan);
|
||||
|
||||
int
|
||||
nouveau_pushbuf_emit_reloc(struct nouveau_channel *, void *ptr,
|
||||
struct nouveau_bo *, uint32_t data, uint32_t data2,
|
||||
uint32_t flags, uint32_t vor, uint32_t tor);
|
||||
|
||||
/* Push buffer access macros */
|
||||
static __inline__ int
|
||||
MARK_RING(struct nouveau_channel *chan, unsigned dwords, unsigned relocs)
|
||||
{
|
||||
return nouveau_pushbuf_marker_emit(chan, dwords, relocs);
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
MARK_UNDO(struct nouveau_channel *chan)
|
||||
{
|
||||
nouveau_pushbuf_marker_undo(chan);
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
OUT_RING(struct nouveau_channel *chan, unsigned data)
|
||||
{
|
||||
|
|
@ -116,62 +135,62 @@ BIND_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr, unsigned sc)
|
|||
OUT_RING (chan, gr->handle);
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
static __inline__ int
|
||||
OUT_RELOC(struct nouveau_channel *chan, struct nouveau_bo *bo,
|
||||
unsigned data, unsigned flags, unsigned vor, unsigned tor)
|
||||
{
|
||||
nouveau_pushbuf_emit_reloc(chan, chan->pushbuf->cur++, bo,
|
||||
data, 0, flags, vor, tor);
|
||||
return nouveau_pushbuf_emit_reloc(chan, chan->pushbuf->cur++, bo,
|
||||
data, 0, flags, vor, tor);
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
static __inline__ int
|
||||
OUT_RELOC2(struct nouveau_channel *chan, struct nouveau_bo *bo,
|
||||
unsigned data, unsigned data2, unsigned flags,
|
||||
unsigned vor, unsigned tor)
|
||||
{
|
||||
nouveau_pushbuf_emit_reloc(chan, chan->pushbuf->cur++, bo,
|
||||
data, data2, flags, vor, tor);
|
||||
return nouveau_pushbuf_emit_reloc(chan, chan->pushbuf->cur++, bo,
|
||||
data, data2, flags, vor, tor);
|
||||
}
|
||||
|
||||
/* Raw data + flags depending on FB/TT buffer */
|
||||
static __inline__ void
|
||||
static __inline__ int
|
||||
OUT_RELOCd(struct nouveau_channel *chan, struct nouveau_bo *bo,
|
||||
unsigned data, unsigned flags, unsigned vor, unsigned tor)
|
||||
{
|
||||
OUT_RELOC(chan, bo, data, flags | NOUVEAU_BO_OR, vor, tor);
|
||||
return OUT_RELOC(chan, bo, data, flags | NOUVEAU_BO_OR, vor, tor);
|
||||
}
|
||||
|
||||
/* FB/TT object handle */
|
||||
static __inline__ void
|
||||
static __inline__ int
|
||||
OUT_RELOCo(struct nouveau_channel *chan, struct nouveau_bo *bo,
|
||||
unsigned flags)
|
||||
{
|
||||
OUT_RELOC(chan, bo, 0, flags | NOUVEAU_BO_OR,
|
||||
chan->vram->handle, chan->gart->handle);
|
||||
return OUT_RELOC(chan, bo, 0, flags | NOUVEAU_BO_OR,
|
||||
chan->vram->handle, chan->gart->handle);
|
||||
}
|
||||
|
||||
/* Low 32-bits of offset */
|
||||
static __inline__ void
|
||||
static __inline__ int
|
||||
OUT_RELOCl(struct nouveau_channel *chan, struct nouveau_bo *bo,
|
||||
unsigned delta, unsigned flags)
|
||||
{
|
||||
OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_LOW, 0, 0);
|
||||
return OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_LOW, 0, 0);
|
||||
}
|
||||
|
||||
/* Low 32-bits of offset + GPU linear access range info */
|
||||
static __inline__ void
|
||||
static __inline__ int
|
||||
OUT_RELOCr(struct nouveau_channel *chan, struct nouveau_bo *bo,
|
||||
unsigned delta, unsigned size, unsigned flags)
|
||||
{
|
||||
OUT_RELOC2(chan, bo, delta, size, flags | NOUVEAU_BO_LOW, 0, 0);
|
||||
return OUT_RELOC2(chan, bo, delta, size, flags | NOUVEAU_BO_LOW, 0, 0);
|
||||
}
|
||||
|
||||
/* High 32-bits of offset */
|
||||
static __inline__ void
|
||||
static __inline__ int
|
||||
OUT_RELOCh(struct nouveau_channel *chan, struct nouveau_bo *bo,
|
||||
unsigned delta, unsigned flags)
|
||||
{
|
||||
OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_HIGH, 0, 0);
|
||||
return OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_HIGH, 0, 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue