Commit 07b9e6cc authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/sw: convert user classes to new-style nvkm_object



Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 5ffeb84b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@

struct nvkm_sw {
	struct nvkm_engine engine;
	const struct nvkm_sw_func *func;
	struct list_head chan;
};

+43 −0
Original line number Diff line number Diff line
@@ -46,6 +46,48 @@ nvkm_sw_mthd(struct nvkm_sw *sw, int chid, int subc, u32 mthd, u32 data)
	return handled;
}

static int
nvkm_sw_oclass_new(const struct nvkm_oclass *oclass, void *data, u32 size,
		   struct nvkm_object **pobject)
{
	struct nvkm_sw_chan *chan = nvkm_sw_chan(oclass->parent);
	const struct nvkm_sw_chan_sclass *sclass = oclass->engn;
	return sclass->ctor(chan, oclass, data, size, pobject);
}

static int
nvkm_sw_oclass_get(struct nvkm_oclass *oclass, int index)
{
	struct nvkm_sw *sw = nvkm_sw(oclass->engine);
	int c = 0;

	while (sw->func->sclass[c].ctor) {
		if (c++ == index) {
			oclass->engn = &sw->func->sclass[index];
			oclass->base =  sw->func->sclass[index].base;
			oclass->base.ctor = nvkm_sw_oclass_new;
			return index;
		}
	}

	return c;
}

static int
nvkm_sw_cclass_get(struct nvkm_fifo_chan *fifoch,
		   const struct nvkm_oclass *oclass,
		   struct nvkm_object **pobject)
{
	struct nvkm_sw *sw = nvkm_sw(oclass->engine);
	return sw->func->chan_new(sw, fifoch, oclass, pobject);
}

static const struct nvkm_engine_func
nvkm_sw = {
	.fifo.cclass = nvkm_sw_cclass_get,
	.fifo.sclass = nvkm_sw_oclass_get,
};

int
nvkm_sw_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
	     struct nvkm_oclass *oclass, int length, void **pobject)
@@ -59,6 +101,7 @@ nvkm_sw_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
	if (ret)
		return ret;

	sw->engine.func = &nvkm_sw;
	INIT_LIST_HEAD(&sw->chan);
	return 0;
}
+28 −18
Original line number Diff line number Diff line
@@ -69,33 +69,43 @@ nvkm_sw_chan_event = {
	.ctor = nvkm_sw_chan_event_ctor,
};

void
nvkm_sw_chan_dtor(struct nvkm_object *base)
static void *
nvkm_sw_chan_dtor(struct nvkm_object *object)
{
	struct nvkm_sw_chan *chan = (void *)base;
	list_del(&chan->head);
	struct nvkm_sw_chan *chan = nvkm_sw_chan(object);
	struct nvkm_sw *sw = chan->sw;
	unsigned long flags;
	void *data = chan;

	if (chan->func->dtor)
		data = chan->func->dtor(chan);
	nvkm_event_fini(&chan->event);
	nvkm_engctx_destroy(&chan->base);

	spin_lock_irqsave(&sw->engine.lock, flags);
	list_del(&chan->head);
	spin_unlock_irqrestore(&sw->engine.lock, flags);
	return data;
}

static const struct nvkm_object_func
nvkm_sw_chan = {
	.dtor = nvkm_sw_chan_dtor,
};

int
nvkm_sw_chan_ctor(const struct nvkm_sw_chan_func *func,
		  struct nvkm_object *parent, struct nvkm_object *engine,
		  struct nvkm_oclass *oclass, int length, void **pobject)
nvkm_sw_chan_ctor(const struct nvkm_sw_chan_func *func, struct nvkm_sw *sw,
		  struct nvkm_fifo_chan *fifo, const struct nvkm_oclass *oclass,
		  struct nvkm_sw_chan *chan)
{
	struct nvkm_sw *sw = (void *)engine;
	struct nvkm_sw_chan *chan;
	int ret;

	ret = nvkm_engctx_create_(parent, engine, oclass, parent,
				  0, 0, 0, length, pobject);
	chan = *pobject;
	if (ret)
		return ret;
	unsigned long flags;

	nvkm_object_ctor(&nvkm_sw_chan, oclass, &chan->object);
	chan->func = func;
	chan->fifo = nvkm_fifo_chan(parent);
	chan->sw = sw;
	chan->fifo = fifo;
	spin_lock_irqsave(&sw->engine.lock, flags);
	list_add(&chan->head, &sw->chan);
	spin_unlock_irqrestore(&sw->engine.lock, flags);

	return nvkm_event_init(&nvkm_sw_chan_event, 1, 1, &chan->event);
}
+8 −17
Original line number Diff line number Diff line
#ifndef __NVKM_SW_CHAN_H__
#define __NVKM_SW_CHAN_H__
#define nvkm_sw_chan(p) container_of((p), struct nvkm_sw_chan, object)
#include "priv.h"
#include <core/engctx.h>
#include <core/event.h>

struct nvkm_sw_chan {
	struct nvkm_engctx base;
	const struct nvkm_sw_chan_func *func;
	struct nvkm_object object;
	struct nvkm_sw *sw;
	struct nvkm_fifo_chan *fifo;
	struct list_head head;

	struct nvkm_event event;
};

struct nvkm_sw_chan_func {
	void *(*dtor)(struct nvkm_sw_chan *);
	bool (*mthd)(struct nvkm_sw_chan *, int subc, u32 mthd, u32 data);
};

int nvkm_sw_chan_ctor(const struct nvkm_sw_chan_func *, struct nvkm_sw *,
		      struct nvkm_fifo_chan *, const struct nvkm_oclass *,
		      struct nvkm_sw_chan *);
bool nvkm_sw_chan_mthd(struct nvkm_sw_chan *, int subc, u32 mthd, u32 data);

#define nvkm_sw_context_create(f,p,e,c,d)                               \
	nvkm_sw_chan_ctor((f), (p), (e), (c), sizeof(**d), (void **)d)
int nvkm_sw_chan_ctor(const struct nvkm_sw_chan_func *,
		      struct nvkm_object *, struct nvkm_object *,
		      struct nvkm_oclass *, int, void **);
void nvkm_sw_chan_dtor(struct nvkm_object *);
#define nvkm_sw_context_init(d)                                       \
	nvkm_engctx_init(&(d)->base)
#define nvkm_sw_context_fini(d,s)                                     \
	nvkm_engctx_fini(&(d)->base, (s))

#define _nvkm_sw_context_dtor nvkm_sw_chan_dtor
#define _nvkm_sw_context_init _nvkm_engctx_init
#define _nvkm_sw_context_fini _nvkm_engctx_fini
#endif
+52 −29
Original line number Diff line number Diff line
@@ -25,33 +25,26 @@

#include <subdev/bar.h>
#include <engine/disp.h>
#include <engine/fifo.h>

#include <nvif/event.h>
#include <nvif/ioctl.h>

/*******************************************************************************
 * software object classes
 ******************************************************************************/

static struct nvkm_oclass
gf100_sw_sclass[] = {
	{ NVIF_IOCTL_NEW_V0_SW_GF100, &nvkm_nvsw_ofuncs },
	{}
};

/*******************************************************************************
 * software context
 ******************************************************************************/

static int
gf100_sw_vblsem_release(struct nvkm_notify *notify)
gf100_sw_chan_vblsem_release(struct nvkm_notify *notify)
{
	struct nv50_sw_chan *chan =
		container_of(notify, typeof(*chan), vblank.notify[notify->index]);
	struct nvkm_sw *sw = (void *)nv_object(chan)->engine;
	struct nvkm_sw *sw = chan->base.sw;
	struct nvkm_device *device = sw->engine.subdev.device;
	struct nvkm_bar *bar = device->bar;
	u32 inst = chan->base.fifo->inst->addr >> 12;

	nvkm_wr32(device, 0x001718, 0x80000000 | chan->vblank.channel);
	nvkm_wr32(device, 0x001718, 0x80000000 | inst);
	bar->flush(bar);
	nvkm_wr32(device, 0x06000c, upper_32_bits(chan->vblank.offset));
	nvkm_wr32(device, 0x060010, lower_32_bits(chan->vblank.offset));
@@ -64,7 +57,7 @@ static bool
gf100_sw_chan_mthd(struct nvkm_sw_chan *base, int subc, u32 mthd, u32 data)
{
	struct nv50_sw_chan *chan = nv50_sw_chan(base);
	struct nvkm_engine *engine = chan->base.base.gpuobj.object.engine;
	struct nvkm_engine *engine = chan->base.object.engine;
	struct nvkm_device *device = engine->subdev.device;
	switch (mthd) {
	case 0x0400:
@@ -103,27 +96,58 @@ gf100_sw_chan_mthd(struct nvkm_sw_chan *base, int subc, u32 mthd, u32 data)
}

static const struct nvkm_sw_chan_func
gf100_sw_chan_func = {
gf100_sw_chan = {
	.dtor = nv50_sw_chan_dtor,
	.mthd = gf100_sw_chan_mthd,
};

static struct nv50_sw_cclass
gf100_sw_cclass = {
	.base.handle = NV_ENGCTX(SW, 0xc0),
	.base.ofuncs = &(struct nvkm_ofuncs) {
		.ctor = nv50_sw_context_ctor,
		.dtor = nv50_sw_context_dtor,
		.init = _nvkm_sw_context_init,
		.fini = _nvkm_sw_context_fini,
static int
gf100_sw_chan_new(struct nvkm_sw *sw, struct nvkm_fifo_chan *fifoch,
		  const struct nvkm_oclass *oclass,
		  struct nvkm_object **pobject)
{
	struct nvkm_disp *disp = sw->engine.subdev.device->disp;
	struct nv50_sw_chan *chan;
	int ret, i;

	if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
		return -ENOMEM;
	*pobject = &chan->base.object;

	ret = nvkm_sw_chan_ctor(&gf100_sw_chan, sw, fifoch, oclass,
				&chan->base);
	if (ret)
		return ret;

	for (i = 0; disp && i < disp->vblank.index_nr; i++) {
		ret = nvkm_notify_init(NULL, &disp->vblank,
				       gf100_sw_chan_vblsem_release, false,
				       &(struct nvif_notify_head_req_v0) {
					.head = i,
				       },
	.vblank = gf100_sw_vblsem_release,
	.chan = &gf100_sw_chan_func,
};
				       sizeof(struct nvif_notify_head_req_v0),
				       sizeof(struct nvif_notify_head_rep_v0),
				       &chan->vblank.notify[i]);
		if (ret)
			return ret;
	}

	return 0;
}

/*******************************************************************************
 * software engine/subdev functions
 ******************************************************************************/

static const struct nvkm_sw_func
gf100_sw_func = {
	.chan_new = gf100_sw_chan_new,
	.sclass = {
		{ nvkm_nvsw_new, { -1, -1, NVIF_IOCTL_NEW_V0_SW_GF100 } },
		{}
	}
};

struct nvkm_oclass *
gf100_sw_oclass = &(struct nv50_sw_oclass) {
	.base.handle = NV_ENGINE(SW, 0xc0),
@@ -133,6 +157,5 @@ gf100_sw_oclass = &(struct nv50_sw_oclass) {
		.init = _nvkm_sw_init,
		.fini = _nvkm_sw_fini,
	},
	.cclass = &gf100_sw_cclass.base,
	.sclass =  gf100_sw_sclass,
	.func = &gf100_sw_func,
}.base;
Loading