Commit b8c157d3 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau: only expose the object classes that are supported by the chipset



We previously added all the available classes for the entire generation,
even though the objects wouldn't work on the hardware.

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent a6a1a380
Loading
Loading
Loading
Loading
+19 −19
Original line number Diff line number Diff line
@@ -316,21 +316,9 @@ struct nouveau_fifo_engine {
	void (*tlb_flush)(struct drm_device *dev);
};

struct nouveau_pgraph_object_method {
	int id;
	int (*exec)(struct nouveau_channel *chan, int grclass, int mthd,
		      uint32_t data);
};

struct nouveau_pgraph_object_class {
	int id;
	u32 engine;
	struct nouveau_pgraph_object_method *methods;
};

struct nouveau_pgraph_engine {
	struct nouveau_pgraph_object_class *grclass;
	bool accel_blocked;
	bool registered;
	int grctx_size;

	/* NV2x/NV3x context table (0x400780) */
@@ -584,6 +572,7 @@ struct drm_nouveau_private {
	bool ramin_available;
	struct drm_mm ramin_heap;
	struct list_head gpuobj_list;
	struct list_head classes;

	struct nouveau_bo *vga_ram;

@@ -816,12 +805,29 @@ extern void nouveau_channel_ref(struct nouveau_channel *chan,
				struct nouveau_channel **pchan);

/* nouveau_object.c */
#define NVOBJ_CLASS(d,c,e) do {                                                \
	int ret = nouveau_gpuobj_class_new((d), (c), NVOBJ_ENGINE_##e);        \
	if (ret)                                                               \
		return ret;                                                    \
} while(0)

#define NVOBJ_MTHD(d,c,m,e) do {                                               \
	int ret = nouveau_gpuobj_mthd_new((d), (c), (m), (e));                 \
	if (ret)                                                               \
		return ret;                                                    \
} while(0)

extern int  nouveau_gpuobj_early_init(struct drm_device *);
extern int  nouveau_gpuobj_init(struct drm_device *);
extern void nouveau_gpuobj_takedown(struct drm_device *);
extern int  nouveau_gpuobj_suspend(struct drm_device *dev);
extern void nouveau_gpuobj_suspend_cleanup(struct drm_device *dev);
extern void nouveau_gpuobj_resume(struct drm_device *dev);
extern int  nouveau_gpuobj_class_new(struct drm_device *, u32 class, u32 eng);
extern int  nouveau_gpuobj_mthd_new(struct drm_device *, u32 class, u32 mthd,
				    int (*exec)(struct nouveau_channel *,
					        u32 class, u32 mthd, u32 data));
extern int  nouveau_gpuobj_mthd_call(struct nouveau_channel *, u32, u32, u32);
extern int nouveau_gpuobj_channel_init(struct nouveau_channel *,
				       uint32_t vram_h, uint32_t tt_h);
extern void nouveau_gpuobj_channel_takedown(struct nouveau_channel *);
@@ -1038,7 +1044,6 @@ extern int nvc0_fifo_load_context(struct nouveau_channel *);
extern int  nvc0_fifo_unload_context(struct drm_device *);

/* nv04_graph.c */
extern struct nouveau_pgraph_object_class nv04_graph_grclass[];
extern int  nv04_graph_init(struct drm_device *);
extern void nv04_graph_takedown(struct drm_device *);
extern void nv04_graph_fifo_access(struct drm_device *, bool);
@@ -1050,7 +1055,6 @@ extern int nv04_graph_unload_context(struct drm_device *);
extern void nv04_graph_context_switch(struct drm_device *);

/* nv10_graph.c */
extern struct nouveau_pgraph_object_class nv10_graph_grclass[];
extern int  nv10_graph_init(struct drm_device *);
extern void nv10_graph_takedown(struct drm_device *);
extern struct nouveau_channel *nv10_graph_channel(struct drm_device *);
@@ -1063,8 +1067,6 @@ extern void nv10_graph_set_region_tiling(struct drm_device *, int, uint32_t,
					 uint32_t, uint32_t);

/* nv20_graph.c */
extern struct nouveau_pgraph_object_class nv20_graph_grclass[];
extern struct nouveau_pgraph_object_class nv30_graph_grclass[];
extern int  nv20_graph_create_context(struct nouveau_channel *);
extern void nv20_graph_destroy_context(struct nouveau_channel *);
extern int  nv20_graph_load_context(struct nouveau_channel *);
@@ -1076,7 +1078,6 @@ extern void nv20_graph_set_region_tiling(struct drm_device *, int, uint32_t,
					 uint32_t, uint32_t);

/* nv40_graph.c */
extern struct nouveau_pgraph_object_class nv40_graph_grclass[];
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 *);
@@ -1089,7 +1090,6 @@ extern void nv40_graph_set_region_tiling(struct drm_device *, int, uint32_t,
					 uint32_t, uint32_t);

/* nv50_graph.c */
extern struct nouveau_pgraph_object_class nv50_graph_grclass[];
extern int  nv50_graph_init(struct drm_device *);
extern void nv50_graph_takedown(struct drm_device *);
extern void nv50_graph_fifo_access(struct drm_device *, bool);
+5 −31
Original line number Diff line number Diff line
@@ -80,33 +80,6 @@ nouveau_irq_uninstall(struct drm_device *dev)
	nv_wr32(dev, NV03_PMC_INTR_EN_0, 0);
}

static int
nouveau_call_method(struct nouveau_channel *chan, int class, int mthd, int data)
{
	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
	struct nouveau_pgraph_object_method *grm;
	struct nouveau_pgraph_object_class *grc;

	grc = dev_priv->engine.graph.grclass;
	while (grc->id) {
		if (grc->id == class)
			break;
		grc++;
	}

	if (grc->id != class || !grc->methods)
		return -ENOENT;

	grm = grc->methods;
	while (grm->id) {
		if (grm->id == mthd)
			return grm->exec(chan, class, mthd, data);
		grm++;
	}

	return -ENOENT;
}

static bool
nouveau_fifo_swmthd(struct drm_device *dev, u32 chid, u32 addr, u32 data)
{
@@ -142,7 +115,7 @@ nouveau_fifo_swmthd(struct drm_device *dev, u32 chid, u32 addr, u32 data)
		if (unlikely(((engine >> (subc * 4)) & 0xf) != 0))
			break;

		if (!nouveau_call_method(chan, chan->sw_subchannel[subc],
		if (!nouveau_gpuobj_mthd_call(chan, chan->sw_subchannel[subc],
					      mthd, data))
			handled = true;
		break;
@@ -541,6 +514,7 @@ nouveau_pgraph_intr_swmthd(struct drm_device *dev,
			   struct nouveau_pgraph_trap *trap)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_channel *chan;
	unsigned long flags;
	int ret = -EINVAL;

@@ -548,8 +522,8 @@ nouveau_pgraph_intr_swmthd(struct drm_device *dev,
	if (trap->channel > 0 &&
	    trap->channel < dev_priv->engine.fifo.channels &&
	    dev_priv->channels.ptr[trap->channel]) {
		ret = nouveau_call_method(dev_priv->channels.ptr[trap->channel],
					  trap->class, trap->mthd, trap->data);
		chan = dev_priv->channels.ptr[trap->channel];
		ret = nouveau_gpuobj_mthd_call(chan, trap->class, trap->mthd, trap->data);
	}
	spin_unlock_irqrestore(&dev_priv->channels.lock, flags);

+98 −14
Original line number Diff line number Diff line
@@ -36,6 +36,83 @@
#include "nouveau_drm.h"
#include "nouveau_ramht.h"

struct nouveau_gpuobj_method {
	struct list_head head;
	u32 mthd;
	int (*exec)(struct nouveau_channel *, u32 class, u32 mthd, u32 data);
};

struct nouveau_gpuobj_class {
	struct list_head head;
	struct list_head methods;
	u32 id;
	u32 engine;
};

int
nouveau_gpuobj_class_new(struct drm_device *dev, u32 class, u32 engine)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_gpuobj_class *oc;

	oc = kzalloc(sizeof(*oc), GFP_KERNEL);
	if (!oc)
		return -ENOMEM;

	INIT_LIST_HEAD(&oc->methods);
	oc->id = class;
	oc->engine = engine;
	list_add(&oc->head, &dev_priv->classes);
	return 0;
}

int
nouveau_gpuobj_mthd_new(struct drm_device *dev, u32 class, u32 mthd,
			int (*exec)(struct nouveau_channel *, u32, u32, u32))
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_gpuobj_method *om;
	struct nouveau_gpuobj_class *oc;

	list_for_each_entry(oc, &dev_priv->classes, head) {
		if (oc->id == class)
			goto found;
	}

	return -EINVAL;

found:
	om = kzalloc(sizeof(*om), GFP_KERNEL);
	if (!om)
		return -ENOMEM;

	om->mthd = mthd;
	om->exec = exec;
	list_add(&om->head, &oc->methods);
	return 0;
}

int
nouveau_gpuobj_mthd_call(struct nouveau_channel *chan,
			 u32 class, u32 mthd, u32 data)
{
	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
	struct nouveau_gpuobj_method *om;
	struct nouveau_gpuobj_class *oc;

	list_for_each_entry(oc, &dev_priv->classes, head) {
		if (oc->id != class)
			continue;

		list_for_each_entry(om, &oc->methods, head) {
			if (om->mthd == mthd)
				return om->exec(chan, class, mthd, data);
		}
	}

	return -ENOENT;
}

/* NVidia uses context objects to drive drawing operations.

   Context objects can be selected into 8 subchannels in the FIFO,
@@ -205,9 +282,20 @@ void
nouveau_gpuobj_takedown(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_gpuobj_method *om, *tm;
	struct nouveau_gpuobj_class *oc, *tc;

	NV_DEBUG(dev, "\n");

	list_for_each_entry_safe(oc, tc, &dev_priv->classes, head) {
		list_for_each_entry_safe(om, tm, &oc->methods, head) {
			list_del(&om->head);
			kfree(om);
		}
		list_del(&oc->head);
		kfree(oc);
	}

	BUG_ON(!list_empty(&dev_priv->gpuobj_list));
}

@@ -527,26 +615,22 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class,
		      struct nouveau_gpuobj **gpuobj)
{
	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
	struct nouveau_pgraph_object_class *grc;
	struct drm_device *dev = chan->dev;
	struct nouveau_gpuobj_class *oc;
	int ret;

	NV_DEBUG(dev, "ch%d class=0x%04x\n", chan->id, class);

	grc = pgraph->grclass;
	while (grc->id) {
		if (grc->id == class)
			break;
		grc++;
	list_for_each_entry(oc, &dev_priv->classes, head) {
		if (oc->id == class)
			goto found;
	}

	if (!grc->id) {
	NV_ERROR(dev, "illegal object class: 0x%x\n", class);
	return -EINVAL;
	}

	if (grc->engine == NVOBJ_ENGINE_SW)
found:
	if (oc->engine == NVOBJ_ENGINE_SW)
		return nouveau_gpuobj_sw_new(chan, class, gpuobj);

	ret = nouveau_gpuobj_new(dev, chan,
@@ -585,8 +669,8 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class,
	}
	dev_priv->engine.instmem.flush(dev);

	(*gpuobj)->engine = grc->engine;
	(*gpuobj)->class  = class;
	(*gpuobj)->engine = oc->engine;
	(*gpuobj)->class  = oc->id;
	return 0;
}

+0 −7
Original line number Diff line number Diff line
@@ -65,7 +65,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
		engine->timer.takedown		= nv04_timer_takedown;
		engine->fb.init			= nv04_fb_init;
		engine->fb.takedown		= nv04_fb_takedown;
		engine->graph.grclass		= nv04_graph_grclass;
		engine->graph.init		= nv04_graph_init;
		engine->graph.takedown		= nv04_graph_takedown;
		engine->graph.fifo_access	= nv04_graph_fifo_access;
@@ -118,7 +117,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
		engine->fb.init			= nv10_fb_init;
		engine->fb.takedown		= nv10_fb_takedown;
		engine->fb.set_region_tiling	= nv10_fb_set_region_tiling;
		engine->graph.grclass		= nv10_graph_grclass;
		engine->graph.init		= nv10_graph_init;
		engine->graph.takedown		= nv10_graph_takedown;
		engine->graph.channel		= nv10_graph_channel;
@@ -172,7 +170,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
		engine->fb.init			= nv10_fb_init;
		engine->fb.takedown		= nv10_fb_takedown;
		engine->fb.set_region_tiling	= nv10_fb_set_region_tiling;
		engine->graph.grclass		= nv20_graph_grclass;
		engine->graph.init		= nv20_graph_init;
		engine->graph.takedown		= nv20_graph_takedown;
		engine->graph.channel		= nv10_graph_channel;
@@ -226,7 +223,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
		engine->fb.init			= nv30_fb_init;
		engine->fb.takedown		= nv30_fb_takedown;
		engine->fb.set_region_tiling	= nv10_fb_set_region_tiling;
		engine->graph.grclass		= nv30_graph_grclass;
		engine->graph.init		= nv30_graph_init;
		engine->graph.takedown		= nv20_graph_takedown;
		engine->graph.fifo_access	= nv04_graph_fifo_access;
@@ -283,7 +279,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
		engine->fb.init			= nv40_fb_init;
		engine->fb.takedown		= nv40_fb_takedown;
		engine->fb.set_region_tiling	= nv40_fb_set_region_tiling;
		engine->graph.grclass		= nv40_graph_grclass;
		engine->graph.init		= nv40_graph_init;
		engine->graph.takedown		= nv40_graph_takedown;
		engine->graph.fifo_access	= nv04_graph_fifo_access;
@@ -345,7 +340,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
		engine->timer.takedown		= nv04_timer_takedown;
		engine->fb.init			= nv50_fb_init;
		engine->fb.takedown		= nv50_fb_takedown;
		engine->graph.grclass		= nv50_graph_grclass;
		engine->graph.init		= nv50_graph_init;
		engine->graph.takedown		= nv50_graph_takedown;
		engine->graph.fifo_access	= nv50_graph_fifo_access;
@@ -424,7 +418,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
		engine->timer.takedown		= nv04_timer_takedown;
		engine->fb.init			= nvc0_fb_init;
		engine->fb.takedown		= nvc0_fb_takedown;
		engine->graph.grclass		= NULL;  //nvc0_graph_grclass;
		engine->graph.init		= nvc0_graph_init;
		engine->graph.takedown		= nvc0_graph_takedown;
		engine->graph.fifo_access	= nvc0_graph_fifo_access;
+301 −229

File changed.

Preview size limit exceeded, changes collapsed.

Loading