Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

drm/nouveau: port all engines to new engine module format



This is a HUGE commit, but it's not nearly as bad as it looks - any problems
can be isolated to a particular chipset and engine combination.  It was
simply too difficult to port each one at a time, the compat layers are
*already* ridiculous.

Most of the changes here are simply to the glue, the process for each of the
engine modules was to start with a standard skeleton and copy+paste the old
code into the appropriate places, fixing up variable names etc as needed.

v2: Marcin Slusarz <marcin.slusarz@gmail.com>
- fix find/replace bug in license header

v3: Ben Skeggs <bskeggs@redhat.com>
- bump indirect pushbuf size to 8KiB, 4KiB barely enough for userspace and
  left no space for kernel's requirements during GEM pushbuf submission.
- fix duplicate assignments noticed by clang

v4: Marcin Slusarz <marcin.slusarz@gmail.com>
- add sparse annotations to nv04_fifo_pause/nv04_fifo_start
- use ioread32_native/iowrite32_native for fifo control registers

v5: Ben Skeggs <bskeggs@redhat.com>
- rebase on v3.6-rc4, modified to keep copy engine fix intact
- nv10/fence: unmap fence bo before destroying
- fixed fermi regression when using nvidia gr fuc
- fixed typo in supported dma_mask checking

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent ac1499d9
Loading
Loading
Loading
Loading
+75 −24
Original line number Diff line number Diff line
@@ -4,9 +4,11 @@

ccflags-y := -Iinclude/drm -DCONFIG_NOUVEAU_DEBUG=7 -DCONFIG_NOUVEAU_DEBUG_DEFAULT=3
ccflags-y += -I$(src)/core/include
ccflags-y += -I$(src)/core
ccflags-y += -I$(src)

nouveau-y := core/core/client.o
nouveau-y += core/core/engctx.o
nouveau-y += core/core/engine.o
nouveau-y += core/core/enum.o
nouveau-y += core/core/gpuobj.o
@@ -90,12 +92,20 @@ nouveau-y += core/subdev/vm/nv44.o
nouveau-y += core/subdev/vm/nv50.o
nouveau-y += core/subdev/vm/nvc0.o

nouveau-y += core/engine/dmaobj/base.o
nouveau-y += core/engine/dmaobj/nv04.o
nouveau-y += core/engine/dmaobj/nv50.o
nouveau-y += core/engine/dmaobj/nvc0.o
nouveau-y += core/engine/bsp/nv84.o
nouveau-y += core/engine/copy/nva3.o
nouveau-y += core/engine/copy/nvc0.o
nouveau-y += core/engine/crypt/nv84.o
nouveau-y += core/engine/crypt/nv98.o
nouveau-y += core/engine/disp/nv04.o
nouveau-y += core/engine/disp/nv50.o
nouveau-y += core/engine/disp/nvd0.o
nouveau-y += core/engine/disp/vga.o
nouveau-y += core/engine/fifo/base.o
nouveau-y += core/engine/fifo/nv04.o
nouveau-y += core/engine/fifo/nv10.o
nouveau-y += core/engine/fifo/nv17.o
@@ -111,41 +121,82 @@ nouveau-y += core/engine/graph/ctxnve0.o
nouveau-y += core/engine/graph/nv04.o
nouveau-y += core/engine/graph/nv10.o
nouveau-y += core/engine/graph/nv20.o
nouveau-y += core/engine/graph/nv25.o
nouveau-y += core/engine/graph/nv2a.o
nouveau-y += core/engine/graph/nv30.o
nouveau-y += core/engine/graph/nv34.o
nouveau-y += core/engine/graph/nv35.o
nouveau-y += core/engine/graph/nv40.o
nouveau-y += core/engine/graph/nv50.o
nouveau-y += core/engine/graph/nvc0.o
nouveau-y += core/engine/graph/nve0.o
nouveau-y += core/engine/mpeg/nv31.o
nouveau-y += core/engine/mpeg/nv40.o
nouveau-y += core/engine/mpeg/nv50.o
nouveau-y += core/engine/mpeg/nv84.o
nouveau-y += core/engine/ppp/nv98.o
nouveau-y += core/engine/software/nv04.o
nouveau-y += core/engine/software/nv10.o
nouveau-y += core/engine/software/nv50.o
nouveau-y += core/engine/software/nvc0.o
nouveau-y += core/engine/vp/nv84.o

nouveau-y += nouveau_drm.o nouveau_compat.o \
	     nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
             nouveau_gpuobj.o nouveau_irq.o nouveau_notifier.o \
             nouveau_sgdma.o nouveau_dma.o nouveau_util.o \
             nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \
             nouveau_hw.o nouveau_calc.o \
             nouveau_display.o nouveau_connector.o nouveau_fbcon.o \
             nouveau_hdmi.o nouveau_dp.o \
	     nouveau_pm.o nouveau_volt.o nouveau_perf.o nouveau_temp.o \
	     nouveau_mxm.o nouveau_agp.o \
	     nouveau_abi16.o \
	     nouveau_bios.o \
             nv04_fence.o nv10_fence.o nv50_fence.o nv84_fence.o nvc0_fence.o \
             nv04_software.o nv50_software.o nvc0_software.o \
             nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \
             nv04_crtc.o nv04_display.o nv04_cursor.o \
             nv50_evo.o nv50_crtc.o nv50_dac.o nv50_sor.o \
             nv50_cursor.o nv50_display.o \
             nvd0_display.o \
             nv04_fbcon.o nv50_fbcon.o nvc0_fbcon.o \
	     nv04_pm.o nv40_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o \
	     nouveau_prime.o

nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o
# drm/compat - will go away
nouveau-y += nouveau_compat.o nouveau_revcompat.o

# drm/core
nouveau-y += nouveau_drm.o nouveau_chan.o nouveau_dma.o nouveau_fence.o
nouveau-y += nouveau_agp.o
nouveau-y += nouveau_ttm.o nouveau_sgdma.o nouveau_bo.o nouveau_gem.o

nouveau-y += nouveau_abi16.o
nouveau-y += nv04_fence.o nv10_fence.o nv50_fence.o nv84_fence.o nvc0_fence.o

# drm/kms/common
nouveau-y += nouveau_fbcon.o

# drm/kms/nv04:nv50
nouveau-y += nv04_fbcon.o

# drm/kms/nv50:nvd9
nouveau-y += nv50_fbcon.o nvc0_fbcon.o

# drm/kms/nvd9-

##
## unported bits below
##

# drm/core
nouveau-y += nouveau_drv.o nouveau_state.o nouveau_irq.o
nouveau-y += nouveau_prime.o

# drm/kms/bios
nouveau-y += nouveau_mxm.o nouveau_bios.o

# drm/kms/common
nouveau-y += nouveau_display.o nouveau_connector.o
nouveau-y += nouveau_hdmi.o nouveau_dp.o

# drm/kms/nv04:nv50
nouveau-y += nouveau_hw.o nouveau_calc.o
nouveau-y += nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o
nouveau-y += nv04_crtc.o nv04_display.o nv04_cursor.o

# drm/kms/nv50-
nouveau-y += nv50_display.o nvd0_display.o
nouveau-y += nv50_crtc.o nv50_dac.o nv50_sor.o nv50_cursor.o
nouveau-y += nv50_evo.o

# drm/pm
nouveau-y += nouveau_pm.o nouveau_volt.o nouveau_perf.o nouveau_temp.o
nouveau-y += nv04_pm.o nv40_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o
nouveau-y += nouveau_mem.o

# optional stuff
nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o
nouveau-$(CONFIG_DRM_NOUVEAU_BACKLIGHT) += nouveau_backlight.o
nouveau-$(CONFIG_ACPI) += nouveau_acpi.o


obj-$(CONFIG_DRM_NOUVEAU)+= nouveau.o
+50 −247
Original line number Diff line number Diff line
/*
 * Copyright 2010 Red Hat Inc.
 * Copyright 2012 Red Hat Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -18,289 +18,92 @@
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Authors: Ben Skeggs
 */

#include "drmP.h"

#include "nouveau_drv.h"
#include <core/object.h>
#include <core/ramht.h>
#include <core/math.h>

#include <subdev/bar.h>

static u32
nouveau_ramht_hash_handle(struct nouveau_channel *chan, u32 handle)
nouveau_ramht_hash(struct nouveau_ramht *ramht, int chid, u32 handle)
{
	struct drm_device *dev = chan->dev;
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_ramht *ramht = chan->ramht;
	u32 hash = 0;
	int i;

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

	for (i = 32; i > 0; i -= ramht->bits) {
	while (handle) {
		hash ^= (handle & ((1 << ramht->bits) - 1));
		handle >>= ramht->bits;
	}

	if (dev_priv->card_type < NV_50)
		hash ^= chan->id << (ramht->bits - 4);
	hash <<= 3;

	NV_DEBUG(dev, "hash=0x%08x\n", hash);
	hash ^= chid << (ramht->bits - 4);
	hash  = hash << 3;
	return hash;
}

static int
nouveau_ramht_entry_valid(struct drm_device *dev, struct nouveau_gpuobj *ramht,
			  u32 offset)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	u32 ctx = nv_ro32(ramht, offset + 4);

	if (dev_priv->card_type < NV_40)
		return ((ctx & NV_RAMHT_CONTEXT_VALID) != 0);
	return (ctx != 0);
}

static int
nouveau_ramht_entry_same_channel(struct nouveau_channel *chan,
				 struct nouveau_gpuobj *ramht, u32 offset)
{
	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
	u32 ctx = nv_ro32(ramht, offset + 4);

	if (dev_priv->card_type >= NV_50)
		return true;
	else if (dev_priv->card_type >= NV_40)
		return chan->id ==
			((ctx >> NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) & 0x1f);
	else
		return chan->id ==
			((ctx >> NV_RAMHT_CONTEXT_CHANNEL_SHIFT) & 0x1f);
}

int
nouveau_ramht_insert(struct nouveau_channel *chan, u32 handle,
		     struct nouveau_gpuobj *gpuobj)
nouveau_ramht_insert(struct nouveau_ramht *ramht, int chid,
		     u32 handle, u32 context)
{
	struct drm_device *dev = chan->dev;
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_ramht_entry *entry;
	struct nouveau_gpuobj *ramht = chan->ramht->gpuobj;
	unsigned long flags;
	u32 ctx, co, ho;

	if (nouveau_ramht_find(chan, handle))
		return -EEXIST;

	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
	if (!entry)
		return -ENOMEM;
	entry->channel = chan;
	entry->gpuobj = NULL;
	entry->handle = handle;
	nouveau_gpuobj_ref(gpuobj, &entry->gpuobj);

	if (dev_priv->card_type < NV_40) {
		ctx = NV_RAMHT_CONTEXT_VALID | (gpuobj->addr >> 4) |
		      (chan->id << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) |
		      (gpuobj->engine << NV_RAMHT_CONTEXT_ENGINE_SHIFT);
	} else
	if (dev_priv->card_type < NV_50) {
		ctx = (gpuobj->addr >> 4) |
		      (chan->id << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) |
		      (gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT);
	} else {
		if (gpuobj->engine == NVOBJ_ENGINE_DISPLAY) {
			ctx = (gpuobj->node->offset << 10) |
			      (chan->id << 28) |
			      chan->id; /* HASH_TAG */
		} else {
			ctx = (gpuobj->node->offset >> 4) |
			      ((gpuobj->engine <<
				NV40_RAMHT_CONTEXT_ENGINE_SHIFT));
		}
	}

	spin_lock_irqsave(&chan->ramht->lock, flags);
	list_add(&entry->head, &chan->ramht->entries);
	struct nouveau_bar *bar = nouveau_bar(ramht);
	u32 co, ho;

	co = ho = nouveau_ramht_hash_handle(chan, handle);
	co = ho = nouveau_ramht_hash(ramht, chid, handle);
	do {
		if (!nouveau_ramht_entry_valid(dev, ramht, co)) {
			NV_DEBUG(dev,
				 "insert ch%d 0x%08x: h=0x%08x, c=0x%08x\n",
				 chan->id, co, handle, ctx);
		if (!nv_ro32(ramht, co + 4)) {
			nv_wo32(ramht, co + 0, handle);
			nv_wo32(ramht, co + 4, ctx);

			spin_unlock_irqrestore(&chan->ramht->lock, flags);
			nvimem_flush(dev);
			return 0;
			nv_wo32(ramht, co + 4, context);
			if (bar)
				bar->flush(bar);
			return co;
		}
		NV_DEBUG(dev, "collision ch%d 0x%08x: h=0x%08x\n",
			 chan->id, co, nv_ro32(ramht, co));

		co += 8;
		if (co >= ramht->size)
		if (co >= nv_gpuobj(ramht)->size)
			co = 0;
	} while (co != ho);

	NV_ERROR(dev, "RAMHT space exhausted. ch=%d\n", chan->id);
	list_del(&entry->head);
	spin_unlock_irqrestore(&chan->ramht->lock, flags);
	kfree(entry);
	return -ENOMEM;
}

static struct nouveau_ramht_entry *
nouveau_ramht_remove_entry(struct nouveau_channel *chan, u32 handle)
{
	struct nouveau_ramht *ramht = chan ? chan->ramht : NULL;
	struct nouveau_ramht_entry *entry;
	unsigned long flags;

	if (!ramht)
		return NULL;

	spin_lock_irqsave(&ramht->lock, flags);
	list_for_each_entry(entry, &ramht->entries, head) {
		if (entry->channel == chan &&
		    (!handle || entry->handle == handle)) {
			list_del(&entry->head);
			spin_unlock_irqrestore(&ramht->lock, flags);

			return entry;
		}
	}
	spin_unlock_irqrestore(&ramht->lock, flags);

	return NULL;
}

static void
nouveau_ramht_remove_hash(struct nouveau_channel *chan, u32 handle)
{
	struct drm_device *dev = chan->dev;
	struct nouveau_gpuobj *ramht = chan->ramht->gpuobj;
	unsigned long flags;
	u32 co, ho;

	spin_lock_irqsave(&chan->ramht->lock, flags);
	co = ho = nouveau_ramht_hash_handle(chan, handle);
	do {
		if (nouveau_ramht_entry_valid(dev, ramht, co) &&
		    nouveau_ramht_entry_same_channel(chan, ramht, co) &&
		    (handle == nv_ro32(ramht, co))) {
			NV_DEBUG(dev,
				 "remove ch%d 0x%08x: h=0x%08x, c=0x%08x\n",
				 chan->id, co, handle, nv_ro32(ramht, co + 4));
			nv_wo32(ramht, co + 0, 0x00000000);
			nv_wo32(ramht, co + 4, 0x00000000);
			nvimem_flush(dev);
			goto out;
		}

		co += 8;
		if (co >= ramht->size)
			co = 0;
	} while (co != ho);

	NV_ERROR(dev, "RAMHT entry not found. ch=%d, handle=0x%08x\n",
		 chan->id, handle);
out:
	spin_unlock_irqrestore(&chan->ramht->lock, flags);
}

int
nouveau_ramht_remove(struct nouveau_channel *chan, u32 handle)
{
	struct nouveau_ramht_entry *entry;

	entry = nouveau_ramht_remove_entry(chan, handle);
	if (!entry)
		return -ENOENT;

	nouveau_ramht_remove_hash(chan, entry->handle);
	nouveau_gpuobj_ref(NULL, &entry->gpuobj);
	kfree(entry);
	return 0;
}

struct nouveau_gpuobj *
nouveau_ramht_find(struct nouveau_channel *chan, u32 handle)
void
nouveau_ramht_remove(struct nouveau_ramht *ramht, int cookie)
{
	struct nouveau_ramht *ramht = chan->ramht;
	struct nouveau_ramht_entry *entry;
	struct nouveau_gpuobj *gpuobj = NULL;
	unsigned long flags;

	if (unlikely(!chan->ramht))
		return NULL;

	spin_lock_irqsave(&ramht->lock, flags);
	list_for_each_entry(entry, &chan->ramht->entries, head) {
		if (entry->channel == chan && entry->handle == handle) {
			gpuobj = entry->gpuobj;
			break;
		}
	}
	spin_unlock_irqrestore(&ramht->lock, flags);

	return gpuobj;
}
	struct nouveau_bar *bar = nouveau_bar(ramht);
	nv_wo32(ramht, cookie + 0, 0x00000000);
	nv_wo32(ramht, cookie + 4, 0x00000000);
	if (bar)
		bar->flush(bar);
}

static struct nouveau_oclass
nouveau_ramht_oclass = {
	.handle = 0x0000abcd,
	.ofuncs = &(struct nouveau_ofuncs) {
		.ctor = NULL,
		.dtor = _nouveau_gpuobj_dtor,
		.init = _nouveau_gpuobj_init,
		.fini = _nouveau_gpuobj_fini,
		.rd32 = _nouveau_gpuobj_rd32,
		.wr32 = _nouveau_gpuobj_wr32,
	},
};

int
nouveau_ramht_new(struct drm_device *dev, struct nouveau_gpuobj *gpuobj,
		  struct nouveau_ramht **pramht)
nouveau_ramht_new(struct nouveau_object *parent, struct nouveau_object *pargpu,
		  u32 size, u32 align, struct nouveau_ramht **pramht)
{
	struct nouveau_ramht *ramht;
	int ret;

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

	ramht->dev = dev;
	kref_init(&ramht->refcount);
	ramht->bits = drm_order(gpuobj->size / 8);
	INIT_LIST_HEAD(&ramht->entries);
	spin_lock_init(&ramht->lock);
	nouveau_gpuobj_ref(gpuobj, &ramht->gpuobj);

	ret = nouveau_gpuobj_create(parent, parent->engine ?
				    parent->engine : parent, /* <nv50 ramht */
				    &nouveau_ramht_oclass, 0, pargpu, size,
				    align, NVOBJ_FLAG_ZERO_ALLOC, &ramht);
	*pramht = ramht;
	return 0;
}

static void
nouveau_ramht_del(struct kref *ref)
{
	struct nouveau_ramht *ramht =
		container_of(ref, struct nouveau_ramht, refcount);

	nouveau_gpuobj_ref(NULL, &ramht->gpuobj);
	kfree(ramht);
}
	if (ret)
		return ret;

void
nouveau_ramht_ref(struct nouveau_ramht *ref, struct nouveau_ramht **ptr,
		  struct nouveau_channel *chan)
{
	struct nouveau_ramht_entry *entry;
	struct nouveau_ramht *ramht;

	if (ref)
		kref_get(&ref->refcount);

	ramht = *ptr;
	if (ramht) {
		while ((entry = nouveau_ramht_remove_entry(chan, 0))) {
			nouveau_ramht_remove_hash(chan, entry->handle);
			nouveau_gpuobj_ref(NULL, &entry->gpuobj);
			kfree(entry);
		}

		kref_put(&ramht->refcount, nouveau_ramht_del);
	}
	*ptr = ref;
	ramht->bits = log2i(nv_gpuobj(ramht)->size >> 3);
	return 0;
}
+125 −32
Original line number Diff line number Diff line
/*
 * Copyright 2011 Red Hat Inc.
 * Copyright 2012 Red Hat Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
@@ -22,61 +22,154 @@
 * Authors: Ben Skeggs
 */

#include "drmP.h"
#include "nouveau_drv.h"
#include "nouveau_util.h"
#include <core/ramht.h>
#include <core/os.h>
#include <core/class.h>
#include <core/engctx.h>

/*XXX: This stub is currently used on NV98+ also, as soon as this becomes
 *     more than just an enable/disable stub this needs to be split out to
 *     nv98_bsp.c...
 */
#include <engine/bsp.h>

struct nv84_bsp_priv {
	struct nouveau_bsp base;
};

struct nv84_bsp_chan {
	struct nouveau_bsp_chan base;
};

struct nv84_bsp_engine {
	struct nouveau_exec_engine base;
/*******************************************************************************
 * BSP object classes
 ******************************************************************************/

static struct nouveau_oclass
nv84_bsp_sclass[] = {
	{},
};

/*******************************************************************************
 * BSP context
 ******************************************************************************/

static int
nv84_bsp_fini(struct drm_device *dev, int engine, bool suspend)
nv84_bsp_context_ctor(struct nouveau_object *parent,
		      struct nouveau_object *engine,
		      struct nouveau_oclass *oclass, void *data, u32 size,
		      struct nouveau_object **pobject)
{
	if (!(nv_rd32(dev, 0x000200) & 0x00008000))
		return 0;
	struct nv84_bsp_chan *priv;
	int ret;

	ret = nouveau_bsp_context_create(parent, engine, oclass, NULL,
					 0, 0, 0, &priv);
	*pobject = nv_object(priv);
	if (ret)
		return ret;

	nv_mask(dev, 0x000200, 0x00008000, 0x00000000);
	return 0;
}

static void
nv84_bsp_context_dtor(struct nouveau_object *object)
{
	struct nv84_bsp_chan *priv = (void *)object;
	nouveau_bsp_context_destroy(&priv->base);
}

static int
nv84_bsp_init(struct drm_device *dev, int engine)
nv84_bsp_context_init(struct nouveau_object *object)
{
	nv_mask(dev, 0x000200, 0x00008000, 0x00000000);
	nv_mask(dev, 0x000200, 0x00008000, 0x00008000);
	struct nv84_bsp_chan *priv = (void *)object;
	int ret;

	ret = nouveau_bsp_context_init(&priv->base);
	if (ret)
		return ret;

	return 0;
}

static int
nv84_bsp_context_fini(struct nouveau_object *object, bool suspend)
{
	struct nv84_bsp_chan *priv = (void *)object;
	return nouveau_bsp_context_fini(&priv->base, suspend);
}

static struct nouveau_oclass
nv84_bsp_cclass = {
	.handle = NV_ENGCTX(BSP, 0x84),
	.ofuncs = &(struct nouveau_ofuncs) {
		.ctor = nv84_bsp_context_ctor,
		.dtor = nv84_bsp_context_dtor,
		.init = nv84_bsp_context_init,
		.fini = nv84_bsp_context_fini,
		.rd32 = _nouveau_bsp_context_rd32,
		.wr32 = _nouveau_bsp_context_wr32,
	},
};

/*******************************************************************************
 * BSP engine/subdev functions
 ******************************************************************************/

static void
nv84_bsp_destroy(struct drm_device *dev, int engine)
nv84_bsp_intr(struct nouveau_subdev *subdev)
{
	struct nv84_bsp_engine *pbsp = nv_engine(dev, engine);
}

	NVOBJ_ENGINE_DEL(dev, BSP);
static int
nv84_bsp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
	      struct nouveau_oclass *oclass, void *data, u32 size,
	      struct nouveau_object **pobject)
{
	struct nv84_bsp_priv *priv;
	int ret;

	ret = nouveau_bsp_create(parent, engine, oclass, &priv);
	*pobject = nv_object(priv);
	if (ret)
		return ret;

	kfree(pbsp);
	nv_subdev(priv)->unit = 0x04008000;
	nv_subdev(priv)->intr = nv84_bsp_intr;
	nv_engine(priv)->cclass = &nv84_bsp_cclass;
	nv_engine(priv)->sclass = nv84_bsp_sclass;
	return 0;
}

int
nv84_bsp_create(struct drm_device *dev)
static void
nv84_bsp_dtor(struct nouveau_object *object)
{
	struct nv84_bsp_engine *pbsp;
	struct nv84_bsp_priv *priv = (void *)object;
	nouveau_bsp_destroy(&priv->base);
}

	pbsp = kzalloc(sizeof(*pbsp), GFP_KERNEL);
	if (!pbsp)
		return -ENOMEM;
static int
nv84_bsp_init(struct nouveau_object *object)
{
	struct nv84_bsp_priv *priv = (void *)object;
	int ret;

	pbsp->base.destroy = nv84_bsp_destroy;
	pbsp->base.init = nv84_bsp_init;
	pbsp->base.fini = nv84_bsp_fini;
	ret = nouveau_bsp_init(&priv->base);
	if (ret)
		return ret;

	NVOBJ_ENGINE_ADD(dev, BSP, &pbsp->base);
	return 0;
}

static int
nv84_bsp_fini(struct nouveau_object *object, bool suspend)
{
	struct nv84_bsp_priv *priv = (void *)object;
	return nouveau_bsp_fini(&priv->base, suspend);
}

struct nouveau_oclass
nv84_bsp_oclass = {
	.handle = NV_ENGINE(BSP, 0x84),
	.ofuncs = &(struct nouveau_ofuncs) {
		.ctor = nv84_bsp_ctor,
		.dtor = nv84_bsp_dtor,
		.init = nv84_bsp_init,
		.fini = nv84_bsp_fini,
	},
};
+140 −128

File changed.

Preview size limit exceeded, changes collapsed.

+175 −175

File changed.

Preview size limit exceeded, changes collapsed.

Loading