Эх сурвалжийг харах

drm/nv40/gr: move to exec engine interfaces

Like nv50, this needs a good cleanup.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Ben Skeggs 14 жил өмнө
parent
commit
39c8d36827

+ 1 - 8
drivers/gpu/drm/nouveau/nouveau_drv.h

@@ -1177,14 +1177,7 @@ extern int  nv30_graph_init(struct drm_device *);
 extern void nv20_graph_set_tile_region(struct drm_device *dev, int i);
 
 /* nv40_graph.c */
-extern int  nv40_graph_init(struct drm_device *);
-extern void nv40_graph_takedown(struct drm_device *);
-extern struct nouveau_channel *nv40_graph_channel(struct drm_device *);
-extern int  nv40_graph_create_context(struct nouveau_channel *);
-extern void nv40_graph_destroy_context(struct nouveau_channel *);
-extern int  nv40_graph_load_context(struct nouveau_channel *);
-extern int  nv40_graph_unload_context(struct drm_device *);
-extern int  nv40_graph_object_new(struct nouveau_channel *, u32, u16);
+extern int  nv40_graph_create(struct drm_device *);
 extern void nv40_grctx_init(struct nouveau_grctx *);
 extern void nv40_graph_set_tile_region(struct drm_device *dev, int i);
 

+ 13 - 12
drivers/gpu/drm/nouveau/nouveau_state.c

@@ -299,15 +299,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
 		engine->fb.init_tile_region	= nv30_fb_init_tile_region;
 		engine->fb.set_tile_region	= nv40_fb_set_tile_region;
 		engine->fb.free_tile_region	= nv30_fb_free_tile_region;
-		engine->graph.init		= nv40_graph_init;
-		engine->graph.takedown		= nv40_graph_takedown;
-		engine->graph.fifo_access	= nv04_graph_fifo_access;
-		engine->graph.channel		= nv40_graph_channel;
-		engine->graph.create_context	= nv40_graph_create_context;
-		engine->graph.destroy_context	= nv40_graph_destroy_context;
-		engine->graph.load_context	= nv40_graph_load_context;
-		engine->graph.unload_context	= nv40_graph_unload_context;
-		engine->graph.object_new	= nv40_graph_object_new;
+		engine->graph.init		= nouveau_stub_init;
+		engine->graph.takedown		= nouveau_stub_takedown;
+		engine->graph.fifo_access	= nvc0_graph_fifo_access;
+		engine->graph.channel		= nvc0_graph_channel;
 		engine->graph.set_tile_region	= nv40_graph_set_tile_region;
 		engine->fifo.channels		= 32;
 		engine->fifo.init		= nv40_fifo_init;
@@ -618,11 +613,17 @@ nouveau_card_init(struct drm_device *dev)
 	if (ret)
 		goto out_timer;
 
-	if (dev_priv->card_type == NV_50)
+	switch (dev_priv->card_type) {
+	case NV_40:
+		nv40_graph_create(dev);
+		break;
+	case NV_50:
 		nv50_graph_create(dev);
-	else
-	if (dev_priv->card_type == NV_C0)
+		break;
+	case NV_C0:
 		nvc0_graph_create(dev);
+		break;
+	}
 
 	switch (dev_priv->chipset) {
 	case 0x84:

+ 144 - 151
drivers/gpu/drm/nouveau/nv40_graph.c

@@ -30,13 +30,16 @@
 #include "nouveau_grctx.h"
 #include "nouveau_ramht.h"
 
-static int nv40_graph_register(struct drm_device *);
-static void nv40_graph_isr(struct drm_device *);
+struct nv40_graph_engine {
+	struct nouveau_exec_engine base;
+	u32 grctx_size;
+};
 
-struct nouveau_channel *
+static struct nouveau_channel *
 nv40_graph_channel(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *grctx;
 	uint32_t inst;
 	int i;
 
@@ -46,74 +49,17 @@ nv40_graph_channel(struct drm_device *dev)
 	inst = (inst & NV40_PGRAPH_CTXCTL_CUR_INSTANCE) << 4;
 
 	for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
-		struct nouveau_channel *chan = dev_priv->channels.ptr[i];
+		if (!dev_priv->channels.ptr[i])
+			continue;
 
-		if (chan && chan->ramin_grctx &&
-		    chan->ramin_grctx->pinst == inst)
-			return chan;
+		grctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_GR];
+		if (grctx && grctx->pinst == inst)
+			return dev_priv->channels.ptr[i];
 	}
 
 	return NULL;
 }
 
-int
-nv40_graph_create_context(struct nouveau_channel *chan)
-{
-	struct drm_device *dev = chan->dev;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
-	struct nouveau_grctx ctx = {};
-	unsigned long flags;
-	int ret;
-
-	ret = nouveau_gpuobj_new(dev, chan, pgraph->grctx_size, 16,
-				 NVOBJ_FLAG_ZERO_ALLOC, &chan->ramin_grctx);
-	if (ret)
-		return ret;
-
-	/* Initialise default context values */
-	ctx.dev = chan->dev;
-	ctx.mode = NOUVEAU_GRCTX_VALS;
-	ctx.data = chan->ramin_grctx;
-	nv40_grctx_init(&ctx);
-
-	nv_wo32(chan->ramin_grctx, 0, chan->ramin_grctx->pinst);
-
-	/* init grctx pointer in ramfc, and on PFIFO if channel is
-	 * already active there
-	 */
-	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
-	nv_wo32(chan->ramfc, 0x38, chan->ramin_grctx->pinst >> 4);
-	nv_mask(dev, 0x002500, 0x00000001, 0x00000000);
-	if ((nv_rd32(dev, 0x003204) & 0x0000001f) == chan->id)
-		nv_wr32(dev, 0x0032e0, chan->ramin_grctx->pinst >> 4);
-	nv_mask(dev, 0x002500, 0x00000001, 0x00000001);
-	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
-	return 0;
-}
-
-void
-nv40_graph_destroy_context(struct nouveau_channel *chan)
-{
-	struct drm_device *dev = chan->dev;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
-	pgraph->fifo_access(dev, false);
-
-	/* Unload the context if it's the currently active one */
-	if (pgraph->channel(dev) == chan)
-		pgraph->unload_context(dev);
-
-	pgraph->fifo_access(dev, true);
-	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
-
-	/* Free the context resources */
-	nouveau_gpuobj_ref(NULL, &chan->ramin_grctx);
-}
-
 static int
 nv40_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save)
 {
@@ -155,58 +101,88 @@ nv40_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save)
 	return 0;
 }
 
-/* Restore the context for a specific channel into PGRAPH */
-int
-nv40_graph_load_context(struct nouveau_channel *chan)
+static int
+nv40_graph_unload_context(struct drm_device *dev)
 {
-	struct drm_device *dev = chan->dev;
 	uint32_t inst;
 	int ret;
 
-	if (!chan->ramin_grctx)
-		return -EINVAL;
-	inst = chan->ramin_grctx->pinst >> 4;
+	inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR);
+	if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED))
+		return 0;
+	inst &= NV40_PGRAPH_CTXCTL_CUR_INSTANCE;
+
+	ret = nv40_graph_transfer_context(dev, inst, 1);
+
+	nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, inst);
+	return ret;
+}
 
-	ret = nv40_graph_transfer_context(dev, inst, 0);
+static int
+nv40_graph_context_new(struct nouveau_channel *chan, int engine)
+{
+	struct nv40_graph_engine *pgraph = nv_engine(chan->dev, engine);
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *grctx = NULL;
+	struct nouveau_grctx ctx = {};
+	unsigned long flags;
+	int ret;
+
+	ret = nouveau_gpuobj_new(dev, NULL, pgraph->grctx_size, 16,
+				 NVOBJ_FLAG_ZERO_ALLOC, &grctx);
 	if (ret)
 		return ret;
 
-	/* 0x40032C, no idea of it's exact function.  Could simply be a
-	 * record of the currently active PGRAPH context.  It's currently
-	 * unknown as to what bit 24 does.  The nv ddx has it set, so we will
-	 * set it here too.
-	 */
-	nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst);
-	nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR,
-		 (inst & NV40_PGRAPH_CTXCTL_CUR_INSTANCE) |
-		  NV40_PGRAPH_CTXCTL_CUR_LOADED);
-	/* 0x32E0 records the instance address of the active FIFO's PGRAPH
-	 * context.  If at any time this doesn't match 0x40032C, you will
-	 * receive PGRAPH_INTR_CONTEXT_SWITCH
+	/* Initialise default context values */
+	ctx.dev = chan->dev;
+	ctx.mode = NOUVEAU_GRCTX_VALS;
+	ctx.data = grctx;
+	nv40_grctx_init(&ctx);
+
+	nv_wo32(grctx, 0, grctx->vinst);
+
+	/* init grctx pointer in ramfc, and on PFIFO if channel is
+	 * already active there
 	 */
-	nv_wr32(dev, NV40_PFIFO_GRCTX_INSTANCE, inst);
+	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+	nv_wo32(chan->ramfc, 0x38, grctx->vinst >> 4);
+	nv_mask(dev, 0x002500, 0x00000001, 0x00000000);
+	if ((nv_rd32(dev, 0x003204) & 0x0000001f) == chan->id)
+		nv_wr32(dev, 0x0032e0, grctx->vinst >> 4);
+	nv_mask(dev, 0x002500, 0x00000001, 0x00000001);
+	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
+
+	chan->engctx[engine] = grctx;
 	return 0;
 }
 
-int
-nv40_graph_unload_context(struct drm_device *dev)
+static void
+nv40_graph_context_del(struct nouveau_channel *chan, int engine)
 {
-	uint32_t inst;
-	int ret;
+	struct nouveau_gpuobj *grctx = chan->engctx[engine];
+	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	unsigned long flags;
 
-	inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR);
-	if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED))
-		return 0;
-	inst &= NV40_PGRAPH_CTXCTL_CUR_INSTANCE;
+	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
+	nv04_graph_fifo_access(dev, false);
 
-	ret = nv40_graph_transfer_context(dev, inst, 1);
+	/* Unload the context if it's the currently active one */
+	if (nv40_graph_channel(dev) == chan)
+		nv40_graph_unload_context(dev);
 
-	nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, inst);
-	return ret;
+	nv04_graph_fifo_access(dev, true);
+	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
+
+	/* Free the context resources */
+	nouveau_gpuobj_ref(NULL, &grctx);
+	chan->engctx[engine] = NULL;
 }
 
 int
-nv40_graph_object_new(struct nouveau_channel *chan, u32 handle, u16 class)
+nv40_graph_object_new(struct nouveau_channel *chan, int engine,
+		      u32 handle, u16 class)
 {
 	struct drm_device *dev = chan->dev;
 	struct nouveau_gpuobj *obj = NULL;
@@ -284,14 +260,14 @@ nv40_graph_set_tile_region(struct drm_device *dev, int i)
  * C51		0x4e
  */
 int
-nv40_graph_init(struct drm_device *dev)
+nv40_graph_init(struct drm_device *dev, int engine)
 {
-	struct drm_nouveau_private *dev_priv =
-		(struct drm_nouveau_private *)dev->dev_private;
+	struct nv40_graph_engine *pgraph = nv_engine(dev, engine);
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
 	struct nouveau_grctx ctx = {};
 	uint32_t vramsz, *cp;
-	int ret, i, j;
+	int i, j;
 
 	nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) &
 			~NV_PMC_ENABLE_PGRAPH);
@@ -307,7 +283,7 @@ nv40_graph_init(struct drm_device *dev)
 	ctx.data = cp;
 	ctx.ctxprog_max = 256;
 	nv40_grctx_init(&ctx);
-	dev_priv->engine.graph.grctx_size = ctx.ctxvals_pos * 4;
+	pgraph->grctx_size = ctx.ctxvals_pos * 4;
 
 	nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
 	for (i = 0; i < ctx.ctxprog_len; i++)
@@ -315,14 +291,9 @@ nv40_graph_init(struct drm_device *dev)
 
 	kfree(cp);
 
-	ret = nv40_graph_register(dev);
-	if (ret)
-		return ret;
-
 	/* No context present currently */
 	nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0x00000000);
 
-	nouveau_irq_register(dev, 12, nv40_graph_isr);
 	nv_wr32(dev, NV03_PGRAPH_INTR   , 0xFFFFFFFF);
 	nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xFFFFFFFF);
 
@@ -455,47 +426,10 @@ nv40_graph_init(struct drm_device *dev)
 	return 0;
 }
 
-void nv40_graph_takedown(struct drm_device *dev)
-{
-	nouveau_irq_unregister(dev, 12);
-}
-
 static int
-nv40_graph_register(struct drm_device *dev)
+nv40_graph_fini(struct drm_device *dev, int engine)
 {
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-
-	if (dev_priv->engine.graph.registered)
-		return 0;
-
-	NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */
-	NVOBJ_CLASS(dev, 0x0030, GR); /* null */
-	NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */
-	NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */
-	NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */
-	NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */
-	NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */
-	NVOBJ_CLASS(dev, 0x3089, GR); /* sifm (nv40) */
-	NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */
-	NVOBJ_CLASS(dev, 0x3062, GR); /* surf2d (nv40) */
-	NVOBJ_CLASS(dev, 0x0043, GR); /* rop */
-	NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */
-	NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */
-	NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */
-	NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */
-	NVOBJ_CLASS(dev, 0x309e, GR); /* swzsurf */
-
-	/* curie */
-	if (nv44_graph_class(dev))
-		NVOBJ_CLASS(dev, 0x4497, GR);
-	else
-		NVOBJ_CLASS(dev, 0x4097, GR);
-
-	/* nvsw */
-	NVOBJ_CLASS(dev, 0x506e, SW);
-	NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip);
-
-	dev_priv->engine.graph.registered = true;
+	nv40_graph_unload_context(dev);
 	return 0;
 }
 
@@ -503,17 +437,17 @@ static int
 nv40_graph_isr_chid(struct drm_device *dev, u32 inst)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_channel *chan;
+	struct nouveau_gpuobj *grctx;
 	unsigned long flags;
 	int i;
 
 	spin_lock_irqsave(&dev_priv->channels.lock, flags);
 	for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
-		chan = dev_priv->channels.ptr[i];
-		if (!chan || !chan->ramin_grctx)
+		if (!dev_priv->channels.ptr[i])
 			continue;
+		grctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_GR];
 
-		if (inst == chan->ramin_grctx->pinst)
+		if (grctx && grctx->pinst == inst)
 			break;
 	}
 	spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
@@ -564,3 +498,62 @@ nv40_graph_isr(struct drm_device *dev)
 		}
 	}
 }
+
+static void
+nv40_graph_destroy(struct drm_device *dev, int engine)
+{
+	struct nv40_graph_engine *pgraph = nv_engine(dev, engine);
+
+	nouveau_irq_unregister(dev, 12);
+
+	NVOBJ_ENGINE_DEL(dev, GR);
+	kfree(pgraph);
+}
+
+int
+nv40_graph_create(struct drm_device *dev)
+{
+	struct nv40_graph_engine *pgraph;
+
+	pgraph = kzalloc(sizeof(*pgraph), GFP_KERNEL);
+	if (!pgraph)
+		return -ENOMEM;
+
+	pgraph->base.destroy = nv40_graph_destroy;
+	pgraph->base.init = nv40_graph_init;
+	pgraph->base.fini = nv40_graph_fini;
+	pgraph->base.context_new = nv40_graph_context_new;
+	pgraph->base.context_del = nv40_graph_context_del;
+	pgraph->base.object_new = nv40_graph_object_new;
+
+	NVOBJ_ENGINE_ADD(dev, GR, &pgraph->base);
+	nouveau_irq_register(dev, 12, nv40_graph_isr);
+
+	NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */
+	NVOBJ_CLASS(dev, 0x0030, GR); /* null */
+	NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */
+	NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */
+	NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */
+	NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */
+	NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */
+	NVOBJ_CLASS(dev, 0x3089, GR); /* sifm (nv40) */
+	NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */
+	NVOBJ_CLASS(dev, 0x3062, GR); /* surf2d (nv40) */
+	NVOBJ_CLASS(dev, 0x0043, GR); /* rop */
+	NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */
+	NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */
+	NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */
+	NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */
+	NVOBJ_CLASS(dev, 0x309e, GR); /* swzsurf */
+
+	/* curie */
+	if (nv44_graph_class(dev))
+		NVOBJ_CLASS(dev, 0x4497, GR);
+	else
+		NVOBJ_CLASS(dev, 0x4097, GR);
+
+	/* nvsw */
+	NVOBJ_CLASS(dev, 0x506e, SW);
+	NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip);
+	return 0;
+}