struct nouveau_grobj *NvM2MF;
struct nouveau_grobj *Nv2D;
uint32_t next_handle;
+ uint32_t next_subchannel;
uint32_t next_sequence;
/* pipe_surface accel */
return 0;
}
-#ifdef NOUVEAU_DMA_SUBCHAN_LRU
-void
-nouveau_dma_subc_bind(struct nouveau_grobj *grobj)
-{
- struct nouveau_channel_priv *nvchan = nouveau_channel(grobj->channel);
- int subc = -1, i;
-
- for (i = 0; i < 8; i++) {
- if (nvchan->subchannel[i].grobj &&
- nvchan->subchannel[i].grobj->bound ==
- NOUVEAU_GROBJ_EXPLICIT_BIND)
- continue;
- if (nvchan->subchannel[i].seq < nvchan->subchannel[subc].seq)
- subc = i;
- }
- assert(subc >= 0);
-
- if (nvchan->subchannel[subc].grobj)
- nvchan->subchannel[subc].grobj->bound = 0;
- nvchan->subchannel[subc].grobj = grobj;
- grobj->subc = subc;
- grobj->bound = NOUVEAU_GROBJ_BOUND;
-
- BEGIN_RING_CH(grobj->channel, grobj, 0, 1);
- nouveau_dma_out (grobj->channel, grobj->handle);
-}
-#endif
-
#ifdef NOUVEAU_DMA_DUMP_POSTRELOC_PUSHBUF
static void
nouveau_dma_parse_pushbuf(struct nouveau_channel *chan, int get, int put)
struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
int push_size = size + 1;
-#ifdef NOUVEAU_DMA_SUBCHAN_LRU
- if (grobj->bound == NOUVEAU_GROBJ_UNBOUND)
- nouveau_dma_subc_bind(grobj);
- nvchan->subchannel[grobj->subc].seq = nvchan->subc_sequence++;
-#endif
-
#ifdef NOUVEAU_DMA_TRACE
NOUVEAU_MSG("BEGIN_RING %d/%08x/%d/0x%04x/%d\n", nvchan->drm.channel,
grobj->handle, grobj->subc, method, size);
nouveau_dma_out(chan, (size << 18) | (grobj->subc << 13) | method);
}
-static inline void
-nouveau_dma_bind(struct nouveau_channel *chan, struct nouveau_grobj *grobj,
- int subc)
-{
- struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
-
- if (nvchan->subchannel[subc].grobj == grobj)
- return;
-
- if (nvchan->subchannel[subc].grobj)
- nvchan->subchannel[subc].grobj->bound = NOUVEAU_GROBJ_UNBOUND;
- nvchan->subchannel[subc].grobj = grobj;
- grobj->subc = subc;
- grobj->bound = NOUVEAU_GROBJ_EXPLICIT_BIND;
-
- nouveau_dma_begin(chan, grobj, 0x0000, 1, __FUNCTION__, __LINE__);
- nouveau_dma_out (chan, grobj->handle);
-}
-
-#define BIND_RING_CH(ch,gr,sc) nouveau_dma_bind((ch), (gr), (sc))
#define BEGIN_RING_CH(ch,gr,m,sz) nouveau_dma_begin((ch), (gr), (m), (sz), __FUNCTION__, __LINE__ )
#define OUT_RING_CH(ch, data) nouveau_dma_out((ch), (data))
#define OUT_RINGp_CH(ch,ptr,dwords) nouveau_dma_outp((ch), (void*)(ptr), \
struct drm_nouveau_channel_alloc drm;
- struct {
- struct nouveau_grobj *grobj;
- uint32_t seq;
- } subchannel[8];
- uint32_t subc_sequence;
-
uint32_t *pushbuf;
void *notifier_block;
if (nvfence->sequence == 0xffffffff)
NOUVEAU_ERR("AII wrap unhandled\n");
- BEGIN_RING_CH(&nvchan->base, nvchan->subchannel[0].grobj, 0x50, 1);
- OUT_RING_CH (&nvchan->base, nvfence->sequence);
+ /*XXX: assumes subc 0 is populated */
+ if (nvchan->dma.free < 2)
+ WAIT_RING_CH(&nvchan->base, 2);
+ nvchan->dma.free -= 2;
+#ifdef NOUVEAU_DMA_DEBUG
+ nvchan->dma.push_free += 2;
+#endif
+ OUT_RING_CH(&nvchan->base, 0x00040050);
+ OUT_RING_CH(&nvchan->base, nvfence->sequence);
if (nvchan->fence_tail) {
nouveau_fence(nvchan->fence_tail)->next = fence;
//#define NOUVEAU_DMA_TRACE
//#define NOUVEAU_DMA_DEBUG
//#define NOUVEAU_DMA_DUMP_POSTRELOC_PUSHBUF
-#define NOUVEAU_DMA_SUBCHAN_LRU
#define NOUVEAU_DMA_BARRIER
#define NOUVEAU_DMA_TIMEOUT 2000
nv->pushbuf = nouveau_pipe_dma_beginp(nv->obj, (mthd), (size)); \
} while(0)
+#define BEGIN_RING_GR(obj,mthd,size) do { \
+ nv->pushbuf = nouveau_pipe_dma_beginp(obj, (mthd), (size)); \
+} while(0)
+
#define OUT_RING(data) do { \
(*nv->pushbuf++) = (data); \
} while(0)
nouveau_pipe_dma_kickoff(nv->channel); \
} while(0)
+#define BIND_RING(o,s) do { \
+ nv->o->subc = (s); \
+ BEGIN_RING(o, 0x0000, 1); \
+ OUT_RING (nv->o->handle); \
+} while(0)
+
#define OUT_RELOC(bo,data,flags,vor,tor) do { \
nouveau_pushbuf_emit_reloc(nv->channel, nv->pushbuf, (void*)(bo), \
(data), (flags), (vor), (tor)); \
struct nouveau_grobj **grobj)
{
struct nouveau_context *nv = nvws->nv;
+ int ret;
- return nouveau_grobj_alloc(nv->channel, nv->next_handle++,
- grclass, grobj);
+ ret = nouveau_grobj_alloc(nv->channel, nv->next_handle++,
+ grclass, grobj);
+ if (ret)
+ return ret;
+
+ (*grobj)->subc = nv->next_subchannel++;
+ assert((*grobj)->subc <= 7);
+ BEGIN_RING_GR(*grobj, 0x0000, 1);
+ OUT_RING ((*grobj)->handle);
+ return 0;
}
uint32_t *
if (!nvchan->pb_tail || nvchan->pb_tail->remaining < (size + 1))
nouveau_pushbuf_flush(grobj->channel);
- if (grobj->bound == NOUVEAU_GROBJ_UNBOUND)
- nouveau_dma_subc_bind(grobj);
- nvchan->subchannel[grobj->subc].seq = nvchan->subc_sequence++;
-
pushbuf = nvchan->pb_tail->cur;
nvchan->pb_tail->cur += (size + 1);
nvchan->pb_tail->remaining -= (size + 1);
NOUVEAU_ERR("Error creating m2mf object: %d\n", ret);
return 1;
}
+ BIND_RING (NvM2MF, nv->next_subchannel++);
BEGIN_RING(NvM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
OUT_RING (nv->sync_notifier->handle);
NOUVEAU_ERR("Error creating 2D surface object: %d\n", ret);
return 1;
}
+ BIND_RING (NvCtxSurf2D, nv->next_subchannel++);
BEGIN_RING(NvCtxSurf2D, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
OUT_RING (nv->channel->vram->handle);
OUT_RING (nv->channel->vram->handle);
NOUVEAU_ERR("Error creating blit object: %d\n", ret);
return 1;
}
+ BIND_RING (NvImageBlit, nv->next_subchannel++);
BEGIN_RING(NvImageBlit, NV_IMAGE_BLIT_DMA_NOTIFY, 1);
OUT_RING (nv->sync_notifier->handle);
BEGIN_RING(NvImageBlit, NV_IMAGE_BLIT_SURFACE, 1);
NOUVEAU_ERR("Error creating rect object: %d\n", ret);
return 1;
}
+ BIND_RING (NvGdiRect, nv->next_subchannel++);
BEGIN_RING(NvGdiRect, NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY, 1);
OUT_RING (nv->sync_notifier->handle);
BEGIN_RING(NvGdiRect, NV04_GDI_RECTANGLE_TEXT_SURFACE, 1);
&nv->Nv2D);
if (ret)
return ret;
-
+ BIND_RING (Nv2D, 0);
BEGIN_RING(Nv2D, NV50_2D_DMA_NOTIFY, 1);
OUT_RING (nv->sync_notifier->handle);
BEGIN_RING(Nv2D, NV50_2D_DMA_IN_MEMORY0, 2);
struct nouveau_channel *channel;
int grclass;
uint32_t handle;
-
- enum {
- NOUVEAU_GROBJ_UNBOUND = 0,
- NOUVEAU_GROBJ_BOUND = 1,
- NOUVEAU_GROBJ_EXPLICIT_BIND = 2,
- } bound;
int subc;
};