diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/sw.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/sw.h index f5857a6404d3..f2288d468cb6 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/sw.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/sw.h @@ -4,6 +4,7 @@ struct nvkm_sw { struct nvkm_engine engine; + const struct nvkm_sw_func *func; struct list_head chan; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c index 1d68ae68884a..efc18787490c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c @@ -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; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c index 904405a8f5c6..d082f4f73a80 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c @@ -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); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h index edebd9c30c0c..6608bf6c6842 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h @@ -1,35 +1,26 @@ #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 #include 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 diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c index ac106c6c25d0..8920f367c1f8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c @@ -25,33 +25,26 @@ #include #include +#include +#include #include -/******************************************************************************* - * 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, - }, - .vblank = gf100_sw_vblsem_release, - .chan = &gf100_sw_chan_func, -}; +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, + }, + 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; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv04.c index 6958cba393da..d8d9d48b66d2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv04.c @@ -40,9 +40,9 @@ struct nv04_sw_chan { ******************************************************************************/ static int -nv04_sw_mthd_get_ref(struct nvkm_object *object, void *data, u32 size) +nv04_nvsw_mthd_get_ref(struct nvkm_nvsw *nvsw, void *data, u32 size) { - struct nv04_sw_chan *chan = (void *)object->parent; + struct nv04_sw_chan *chan = nv04_sw_chan(nvsw->chan); union { struct nv04_nvsw_get_ref_v0 v0; } *args = data; @@ -56,31 +56,28 @@ nv04_sw_mthd_get_ref(struct nvkm_object *object, void *data, u32 size) } static int -nv04_sw_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) +nv04_nvsw_mthd(struct nvkm_nvsw *nvsw, u32 mthd, void *data, u32 size) { switch (mthd) { case NV04_NVSW_GET_REF: - return nv04_sw_mthd_get_ref(object, data, size); + return nv04_nvsw_mthd_get_ref(nvsw, data, size); default: break; } return -EINVAL; } -static struct nvkm_ofuncs -nv04_sw_ofuncs = { - .ctor = nvkm_nvsw_ctor, - .dtor = nvkm_object_destroy, - .init = _nvkm_object_init, - .fini = _nvkm_object_fini, - .mthd = nv04_sw_mthd, +static const struct nvkm_nvsw_func +nv04_nvsw = { + .mthd = nv04_nvsw_mthd, }; -static struct nvkm_oclass -nv04_sw_sclass[] = { - { NVIF_IOCTL_NEW_V0_SW_NV04, &nv04_sw_ofuncs }, - {} -}; +static int +nv04_nvsw_new(struct nvkm_sw_chan *chan, const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_object **pobject) +{ + return nvkm_nvsw_new_(&nv04_nvsw, chan, oclass, data, size, pobject); +} /******************************************************************************* * software context @@ -103,38 +100,23 @@ nv04_sw_chan_mthd(struct nvkm_sw_chan *base, int subc, u32 mthd, u32 data) } static const struct nvkm_sw_chan_func -nv04_sw_chan_func = { +nv04_sw_chan = { .mthd = nv04_sw_chan_mthd, }; static int -nv04_sw_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv04_sw_chan_new(struct nvkm_sw *sw, struct nvkm_fifo_chan *fifo, + const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { struct nv04_sw_chan *chan; - int ret; - - ret = nvkm_sw_context_create(&nv04_sw_chan_func, - parent, engine, oclass, &chan); - *pobject = nv_object(chan); - if (ret) - return ret; + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; atomic_set(&chan->ref, 0); - return 0; -} + *pobject = &chan->base.object; -static struct nvkm_oclass -nv04_sw_cclass = { - .handle = NV_ENGCTX(SW, 0x04), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv04_sw_context_ctor, - .dtor = _nvkm_sw_context_dtor, - .init = _nvkm_sw_context_init, - .fini = _nvkm_sw_context_fini, - }, -}; + return nvkm_sw_chan_ctor(&nv04_sw_chan, sw, fifo, oclass, &chan->base); +} /******************************************************************************* * software engine/subdev functions @@ -146,6 +128,15 @@ nv04_sw_intr(struct nvkm_subdev *subdev) nvkm_mask(subdev->device, 0x000100, 0x80000000, 0x00000000); } +static const struct nvkm_sw_func +nv04_sw = { + .chan_new = nv04_sw_chan_new, + .sclass = { + { nv04_nvsw_new, { -1, -1, NVIF_IOCTL_NEW_V0_SW_NV04 } }, + {} + } +}; + static int nv04_sw_ctor(struct nvkm_object *parent, struct nvkm_object *engine, struct nvkm_oclass *oclass, void *data, u32 size, @@ -159,8 +150,7 @@ nv04_sw_ctor(struct nvkm_object *parent, struct nvkm_object *engine, if (ret) return ret; - nv_engine(sw)->cclass = &nv04_sw_cclass; - nv_engine(sw)->sclass = nv04_sw_sclass; + sw->func = &nv04_sw; nv_subdev(sw)->intr = nv04_sw_intr; return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv10.c index ecaeeaa8edc7..1b9fc1b1f69e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv10.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv10.c @@ -27,56 +27,40 @@ #include -/******************************************************************************* - * software object classes - ******************************************************************************/ - -static struct nvkm_oclass -nv10_sw_sclass[] = { - { NVIF_IOCTL_NEW_V0_SW_NV10, &nvkm_nvsw_ofuncs }, - {} -}; - /******************************************************************************* * software context ******************************************************************************/ static const struct nvkm_sw_chan_func -nv10_sw_chan_func = { +nv10_sw_chan = { }; static int -nv10_sw_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) +nv10_sw_chan_new(struct nvkm_sw *sw, struct nvkm_fifo_chan *fifo, + const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { struct nvkm_sw_chan *chan; - int ret; - ret = nvkm_sw_context_create(&nv10_sw_chan_func, - parent, engine, oclass, &chan); - *pobject = nv_object(chan); - if (ret) - return ret; + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + *pobject = &chan->object; - return 0; + return nvkm_sw_chan_ctor(&nv10_sw_chan, sw, fifo, oclass, chan); } -static struct nvkm_oclass -nv10_sw_cclass = { - .handle = NV_ENGCTX(SW, 0x04), - .ofuncs = &(struct nvkm_ofuncs) { - .ctor = nv10_sw_context_ctor, - .dtor = _nvkm_sw_context_dtor, - .init = _nvkm_sw_context_init, - .fini = _nvkm_sw_context_fini, - }, -}; - /******************************************************************************* * software engine/subdev functions ******************************************************************************/ +static const struct nvkm_sw_func +nv10_sw = { + .chan_new = nv10_sw_chan_new, + .sclass = { + { nvkm_nvsw_new, { -1, -1, NVIF_IOCTL_NEW_V0_SW_NV10 } }, + {} + } +}; + static int nv10_sw_ctor(struct nvkm_object *parent, struct nvkm_object *engine, struct nvkm_oclass *oclass, void *data, u32 size, @@ -90,8 +74,7 @@ nv10_sw_ctor(struct nvkm_object *parent, struct nvkm_object *engine, if (ret) return ret; - nv_engine(sw)->cclass = &nv10_sw_cclass; - nv_engine(sw)->sclass = nv10_sw_sclass; + sw->func = &nv10_sw; nv_subdev(sw)->intr = nv04_sw_intr; return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c index 35ec1cffb53a..451f758f5ebf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c @@ -31,30 +31,20 @@ #include #include -/******************************************************************************* - * software object classes - ******************************************************************************/ - -static struct nvkm_oclass -nv50_sw_sclass[] = { - { NVIF_IOCTL_NEW_V0_SW_NV50, &nvkm_nvsw_ofuncs }, - {} -}; - /******************************************************************************* * software context ******************************************************************************/ static int -nv50_sw_vblsem_release(struct nvkm_notify *notify) +nv50_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; - nvkm_wr32(device, 0x001704, chan->vblank.channel); + nvkm_wr32(device, 0x001704, chan->base.fifo->inst->addr >> 12); nvkm_wr32(device, 0x001710, 0x80000000 | chan->vblank.ctxdma); bar->flush(bar); @@ -73,7 +63,7 @@ static bool nv50_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 0x018c: chan->vblank.ctxdma = data; return true; @@ -91,41 +81,41 @@ nv50_sw_chan_mthd(struct nvkm_sw_chan *base, int subc, u32 mthd, u32 data) return false; } +void * +nv50_sw_chan_dtor(struct nvkm_sw_chan *base) +{ + struct nv50_sw_chan *chan = nv50_sw_chan(base); + int i; + for (i = 0; i < ARRAY_SIZE(chan->vblank.notify); i++) + nvkm_notify_fini(&chan->vblank.notify[i]); + return chan; +} + static const struct nvkm_sw_chan_func -nv50_sw_chan_func = { +nv50_sw_chan = { + .dtor = nv50_sw_chan_dtor, .mthd = nv50_sw_chan_mthd, }; -void -nv50_sw_context_dtor(struct nvkm_object *object) +static int +nv50_sw_chan_new(struct nvkm_sw *sw, struct nvkm_fifo_chan *fifoch, + const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { - struct nv50_sw_chan *chan = (void *)object; - int i; - - for (i = 0; i < ARRAY_SIZE(chan->vblank.notify); i++) - nvkm_notify_fini(&chan->vblank.notify[i]); - - nvkm_sw_chan_dtor(&chan->base.base.gpuobj.object); -} - -int -nv50_sw_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject) -{ - struct nvkm_disp *disp = parent->engine->subdev.device->disp; - struct nv50_sw_cclass *pclass = (void *)oclass; + struct nvkm_disp *disp = sw->engine.subdev.device->disp; struct nv50_sw_chan *chan; int ret, i; - ret = nvkm_sw_context_create(pclass->chan, parent, engine, oclass, &chan); - *pobject = nv_object(chan); + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + *pobject = &chan->base.object; + + ret = nvkm_sw_chan_ctor(&nv50_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, pclass->vblank, - false, + ret = nvkm_notify_init(NULL, &disp->vblank, + nv50_sw_chan_vblsem_release, false, &(struct nvif_notify_head_req_v0) { .head = i, }, @@ -136,23 +126,9 @@ nv50_sw_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, return ret; } - chan->vblank.channel = nvkm_fifo_chan(parent)->inst->addr >> 12; return 0; } -static struct nv50_sw_cclass -nv50_sw_cclass = { - .base.handle = NV_ENGCTX(SW, 0x50), - .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, - }, - .vblank = nv50_sw_vblsem_release, - .chan = &nv50_sw_chan_func, -}; - /******************************************************************************* * software engine/subdev functions ******************************************************************************/ @@ -171,12 +147,20 @@ nv50_sw_ctor(struct nvkm_object *parent, struct nvkm_object *engine, if (ret) return ret; - nv_engine(sw)->cclass = pclass->cclass; - nv_engine(sw)->sclass = pclass->sclass; + sw->func = pclass->func; nv_subdev(sw)->intr = nv04_sw_intr; return 0; } +static const struct nvkm_sw_func +nv50_sw_func = { + .chan_new = nv50_sw_chan_new, + .sclass = { + { nvkm_nvsw_new, { -1, -1, NVIF_IOCTL_NEW_V0_SW_NV50 } }, + {} + } +}; + struct nvkm_oclass * nv50_sw_oclass = &(struct nv50_sw_oclass) { .base.handle = NV_ENGINE(SW, 0x50), @@ -186,6 +170,5 @@ nv50_sw_oclass = &(struct nv50_sw_oclass) { .init = _nvkm_sw_init, .fini = _nvkm_sw_fini, }, - .cclass = &nv50_sw_cclass.base, - .sclass = nv50_sw_sclass, + .func = &nv50_sw_func, }.base; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h index 534c21079b81..c90a470564e2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h @@ -8,8 +8,7 @@ struct nv50_sw_oclass { struct nvkm_oclass base; - struct nvkm_oclass *cclass; - struct nvkm_oclass *sclass; + const struct nvkm_sw_func *func; }; int nv50_sw_ctor(struct nvkm_object *, struct nvkm_object *, @@ -26,20 +25,11 @@ struct nv50_sw_chan { struct nvkm_sw_chan base; struct { struct nvkm_notify notify[4]; - u32 channel; u32 ctxdma; u64 offset; u32 value; } vblank; }; -int nv50_sw_context_ctor(struct nvkm_object *, - struct nvkm_object *, - struct nvkm_oclass *, void *, u32, - struct nvkm_object **); -void nv50_sw_context_dtor(struct nvkm_object *); - -int nv50_sw_mthd_vblsem_value(struct nvkm_object *, u32, void *, u32); -int nv50_sw_mthd_vblsem_release(struct nvkm_object *, u32, void *, u32); -int nv50_sw_mthd_flip(struct nvkm_object *, u32, void *, u32); +void *nv50_sw_chan_dtor(struct nvkm_sw_chan *); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.c index c3c6829fd001..6652a9196753 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.c @@ -21,19 +21,22 @@ * * Authors: Ben Skeggs */ -#define nvkm_nvsw(p) container_of((p), struct nvkm_nvsw, object) #include "nvsw.h" #include "chan.h" #include -struct nvkm_nvsw { - struct nvkm_object object; - struct nvkm_sw_chan *chan; -}; +static int +nvkm_nvsw_mthd_(struct nvkm_object *base, u32 mthd, void *data, u32 size) +{ + struct nvkm_nvsw *nvsw = nvkm_nvsw(base); + if (nvsw->func->mthd) + return nvsw->func->mthd(nvsw, mthd, data, size); + return -ENODEV; +} static int -nvkm_nvsw_ntfy(struct nvkm_object *base, u32 mthd, struct nvkm_event **pevent) +nvkm_nvsw_ntfy_(struct nvkm_object *base, u32 mthd, struct nvkm_event **pevent) { struct nvkm_nvsw *nvsw = nvkm_nvsw(base); switch (mthd) { @@ -46,29 +49,36 @@ nvkm_nvsw_ntfy(struct nvkm_object *base, u32 mthd, struct nvkm_event **pevent) return -EINVAL; } +static const struct nvkm_object_func +nvkm_nvsw_ = { + .mthd = nvkm_nvsw_mthd_, + .ntfy = nvkm_nvsw_ntfy_, +}; + int -nvkm_nvsw_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, +nvkm_nvsw_new_(const struct nvkm_nvsw_func *func, struct nvkm_sw_chan *chan, + const struct nvkm_oclass *oclass, void *data, u32 size, struct nvkm_object **pobject) { - struct nvkm_sw_chan *chan = (void *)parent; struct nvkm_nvsw *nvsw; - int ret; - ret = nvkm_object_create(parent, engine, oclass, 0, &nvsw); + if (!(nvsw = kzalloc(sizeof(*nvsw), GFP_KERNEL))) + return -ENOMEM; *pobject = &nvsw->object; - if (ret) - return ret; + nvkm_object_ctor(&nvkm_nvsw_, oclass, &nvsw->object); + nvsw->func = func; nvsw->chan = chan; return 0; } -struct nvkm_ofuncs -nvkm_nvsw_ofuncs = { - .ctor = nvkm_nvsw_ctor, - .dtor = nvkm_object_destroy, - .init = _nvkm_object_init, - .fini = _nvkm_object_fini, - .ntfy = nvkm_nvsw_ntfy, +static const struct nvkm_nvsw_func +nvkm_nvsw = { }; + +int +nvkm_nvsw_new(struct nvkm_sw_chan *chan, const struct nvkm_oclass *oclass, + void *data, u32 size, struct nvkm_object **pobject) +{ + return nvkm_nvsw_new_(&nvkm_nvsw, chan, oclass, data, size, pobject); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.h b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.h index c54a12798e84..943ef4c10091 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.h @@ -1,10 +1,21 @@ #ifndef __NVKM_NVSW_H__ #define __NVKM_NVSW_H__ +#define nvkm_nvsw(p) container_of((p), struct nvkm_nvsw, object) #include "priv.h" -extern struct nvkm_ofuncs nvkm_nvsw_ofuncs; -int -nvkm_nvsw_ctor(struct nvkm_object *parent, struct nvkm_object *engine, - struct nvkm_oclass *oclass, void *data, u32 size, - struct nvkm_object **pobject); +struct nvkm_nvsw { + struct nvkm_object object; + const struct nvkm_nvsw_func *func; + struct nvkm_sw_chan *chan; +}; + +struct nvkm_nvsw_func { + int (*mthd)(struct nvkm_nvsw *, u32 mthd, void *data, u32 size); +}; + +int nvkm_nvsw_new_(const struct nvkm_nvsw_func *, struct nvkm_sw_chan *, + const struct nvkm_oclass *, void *data, u32 size, + struct nvkm_object **pobject); +int nvkm_nvsw_new(struct nvkm_sw_chan *, const struct nvkm_oclass *, + void *data, u32 size, struct nvkm_object **pobject); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/sw/priv.h index 42707355eb92..ae610a32ef5a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/priv.h @@ -1,5 +1,18 @@ #ifndef __NVKM_SW_PRIV_H__ #define __NVKM_SW_PRIV_H__ +#define nvkm_sw(p) container_of((p), struct nvkm_sw, engine) #include +struct nvkm_sw_chan; +struct nvkm_sw_chan_sclass { + int (*ctor)(struct nvkm_sw_chan *, const struct nvkm_oclass *, + void *data, u32 size, struct nvkm_object **); + struct nvkm_sclass base; +}; + +struct nvkm_sw_func { + int (*chan_new)(struct nvkm_sw *, struct nvkm_fifo_chan *, + const struct nvkm_oclass *, struct nvkm_object **); + const struct nvkm_sw_chan_sclass sclass[]; +}; #endif