From 6157091177102638c7d94ffc159c0b157a1c9b56 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 20 Aug 2015 14:54:18 +1000 Subject: [PATCH] drm/nouveau/sw: remove dependence on namedb/engctx lookup Signed-off-by: Ben Skeggs --- .../drm/nouveau/include/nvkm/core/object.h | 27 ----- .../gpu/drm/nouveau/include/nvkm/engine/sw.h | 8 +- .../gpu/drm/nouveau/nvkm/engine/disp/nv50.h | 1 - .../gpu/drm/nouveau/nvkm/engine/fifo/gf100.c | 33 +----- .../gpu/drm/nouveau/nvkm/engine/fifo/gk104.c | 33 +----- .../gpu/drm/nouveau/nvkm/engine/fifo/nv04.c | 59 +++------- drivers/gpu/drm/nouveau/nvkm/engine/sw/Kbuild | 1 + drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c | 64 +++++++++++ drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c | 27 ++++- drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h | 16 ++- .../gpu/drm/nouveau/nvkm/engine/sw/gf100.c | 107 ++++++++---------- drivers/gpu/drm/nouveau/nvkm/engine/sw/nv04.c | 50 ++++---- drivers/gpu/drm/nouveau/nvkm/engine/sw/nv10.c | 23 ++-- drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c | 101 +++++------------ drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h | 2 + 15 files changed, 251 insertions(+), 301 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/object.h b/drivers/gpu/drm/nouveau/include/nvkm/core/object.h index 3366ec59a64e..7befea315c98 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/object.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/object.h @@ -109,7 +109,6 @@ struct nvkm_sclass { struct nvkm_oclass { s32 handle; struct nvkm_ofuncs * const ofuncs; - struct nvkm_omthds * const omthds; int (*ctor)(const struct nvkm_oclass *, void *data, u32 size, struct nvkm_object **); @@ -135,12 +134,6 @@ nv_pclass(struct nvkm_object *parent, u32 oclass) return parent; } -struct nvkm_omthds { - u32 start; - u32 limit; - int (*call)(struct nvkm_object *, u32, void *, u32); -}; - struct nvkm_ofuncs { int (*ctor)(struct nvkm_object *, struct nvkm_object *, struct nvkm_oclass *, void *data, u32 size, @@ -171,24 +164,4 @@ int nvkm_object_old(struct nvkm_object *, struct nvkm_object *, void nvkm_object_ref(struct nvkm_object *, struct nvkm_object **); int nvkm_object_inc(struct nvkm_object *); int nvkm_object_dec(struct nvkm_object *, bool suspend); - -static inline int -nv_exec(void *obj, u32 mthd, void *data, u32 size) -{ - struct nvkm_omthds *method = nv_oclass(obj)->omthds; - - while (method && method->call) { - if (mthd >= method->start && mthd <= method->limit) - return method->call(obj, mthd, data, size); - method++; - } - - return -EINVAL; -} - -static inline int -nv_call(void *obj, u32 mthd, u32 data) -{ - return nv_exec(obj, mthd, &data, sizeof(data)); -} #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/sw.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/sw.h index b06140af0a05..f5857a6404d3 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/sw.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/sw.h @@ -4,10 +4,16 @@ struct nvkm_sw { struct nvkm_engine engine; + struct list_head chan; }; +bool nvkm_sw_mthd(struct nvkm_sw *sw, int chid, int subc, u32 mthd, u32 data); + #define nvkm_sw_create(p,e,c,d) \ - nvkm_engine_create((p), (e), (c), true, "SW", "software", (d)) + nvkm_sw_ctor((p), (e), (c), sizeof(**d), (void **)d) +int +nvkm_sw_ctor(struct nvkm_object *parent, struct nvkm_object *engine, + struct nvkm_oclass *oclass, int length, void **pobject); #define nvkm_sw_destroy(d) \ nvkm_engine_destroy(&(d)->engine) #define nvkm_sw_init(d) \ diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h index 21dbd3901113..3c50d28d33a0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h @@ -174,7 +174,6 @@ int nv50_disp_main_ctor(struct nvkm_object *, struct nvkm_object *, struct nvkm_oclass *, void *, u32, struct nvkm_object **); void nv50_disp_main_dtor(struct nvkm_object *); -extern struct nvkm_omthds nv50_disp_main_omthds[]; extern struct nvkm_oclass nv50_disp_cclass; void nv50_disp_mthd_chan(struct nv50_disp *, int debug, int head, const struct nv50_disp_mthd_chan *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index 39031841d057..7f05985ebb37 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -474,32 +475,6 @@ gf100_fifo_recover(struct gf100_fifo *fifo, struct nvkm_engine *engine, schedule_work(&fifo->fault); } -static int -gf100_fifo_swmthd(struct gf100_fifo *fifo, u32 chid, u32 mthd, u32 data) -{ - struct gf100_fifo_chan *chan = NULL; - struct nvkm_handle *bind; - unsigned long flags; - int ret = -EINVAL; - - spin_lock_irqsave(&fifo->base.lock, flags); - if (likely(chid >= fifo->base.min && chid <= fifo->base.max)) - chan = (void *)fifo->base.channel[chid]; - if (unlikely(!chan)) - goto out; - - bind = nvkm_namedb_get_class(nv_namedb(chan), NVIF_IOCTL_NEW_V0_SW_GF100); - if (likely(bind)) { - if (!mthd || !nv_call(bind->object, mthd, data)) - ret = 0; - nvkm_namedb_put(bind); - } - -out: - spin_unlock_irqrestore(&fifo->base.lock, flags); - return ret; -} - static const struct nvkm_enum gf100_fifo_sched_reason[] = { { 0x0a, "CTXSW_TIMEOUT" }, @@ -701,8 +676,10 @@ gf100_fifo_intr_pbdma(struct gf100_fifo *fifo, int unit) char msg[128]; if (stat & 0x00800000) { - if (!gf100_fifo_swmthd(fifo, chid, mthd, data)) - show &= ~0x00800000; + if (device->sw) { + if (nvkm_sw_mthd(device->sw, chid, subc, mthd, data)) + show &= ~0x00800000; + } } if (show) { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index 3d2b16e7a7ee..e0badfc54dc8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -520,32 +521,6 @@ gk104_fifo_recover(struct gk104_fifo *fifo, struct nvkm_engine *engine, schedule_work(&fifo->fault); } -static int -gk104_fifo_swmthd(struct gk104_fifo *fifo, u32 chid, u32 mthd, u32 data) -{ - struct gk104_fifo_chan *chan = NULL; - struct nvkm_handle *bind; - unsigned long flags; - int ret = -EINVAL; - - spin_lock_irqsave(&fifo->base.lock, flags); - if (likely(chid >= fifo->base.min && chid <= fifo->base.max)) - chan = (void *)fifo->base.channel[chid]; - if (unlikely(!chan)) - goto out; - - bind = nvkm_namedb_get_class(nv_namedb(chan), NVIF_IOCTL_NEW_V0_SW_GF100); - if (likely(bind)) { - if (!mthd || !nv_call(bind->object, mthd, data)) - ret = 0; - nvkm_namedb_put(bind); - } - -out: - spin_unlock_irqrestore(&fifo->base.lock, flags); - return ret; -} - static const struct nvkm_enum gk104_fifo_bind_reason[] = { { 0x01, "BIND_NOT_UNBOUND" }, @@ -864,8 +839,10 @@ gk104_fifo_intr_pbdma_0(struct gk104_fifo *fifo, int unit) char msg[128]; if (stat & 0x00800000) { - if (!gk104_fifo_swmthd(fifo, chid, mthd, data)) - show &= ~0x00800000; + if (device->sw) { + if (nvkm_sw_mthd(device->sw, chid, subc, mthd, data)) + show &= ~0x00800000; + } nvkm_wr32(device, 0x0400c0 + (unit * 0x2000), 0x80600008); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c index cd5009302e22..8bdb71f5f1c5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -369,55 +370,29 @@ nv_dma_state_err(u32 state) } static bool -nv04_fifo_swmthd(struct nv04_fifo *fifo, u32 chid, u32 addr, u32 data) +nv04_fifo_swmthd(struct nvkm_device *device, u32 chid, u32 addr, u32 data) { - struct nvkm_device *device = fifo->base.engine.subdev.device; - struct nv04_fifo_chan *chan = NULL; - struct nvkm_handle *bind; - const int subc = (addr >> 13) & 0x7; - const int mthd = addr & 0x1ffc; + struct nvkm_sw *sw = device->sw; + const int subc = (addr & 0x0000e000) >> 13; + const int mthd = (addr & 0x00001ffc); + const u32 mask = 0x0000000f << (subc * 4); + u32 engine = nvkm_rd32(device, 0x003280); bool handled = false; - unsigned long flags; - u32 engine; - - spin_lock_irqsave(&fifo->base.lock, flags); - if (likely(chid >= fifo->base.min && chid <= fifo->base.max)) - chan = (void *)fifo->base.channel[chid]; - if (unlikely(!chan)) - goto out; switch (mthd) { - case 0x0000: - bind = nvkm_namedb_get(nv_namedb(chan), data); - if (unlikely(!bind)) - break; - - if (nv_engidx(bind->object->engine) == NVDEV_ENGINE_SW) { - engine = 0x0000000f << (subc * 4); - chan->subc[subc] = data; - handled = true; - - nvkm_mask(device, NV04_PFIFO_CACHE1_ENGINE, engine, 0); - } - - nvkm_namedb_put(bind); + case 0x0000 ... 0x0000: /* subchannel's engine -> software */ + nvkm_wr32(device, 0x003280, (engine &= ~mask)); + case 0x0180 ... 0x01fc: /* handle -> instance */ + data = nvkm_rd32(device, 0x003258) & 0x0000ffff; + case 0x0100 ... 0x017c: + case 0x0200 ... 0x1ffc: /* pass method down to sw */ + if (!(engine & mask) && sw) + handled = nvkm_sw_mthd(sw, chid, subc, mthd, data); break; default: - engine = nvkm_rd32(device, NV04_PFIFO_CACHE1_ENGINE); - if (unlikely(((engine >> (subc * 4)) & 0xf) != 0)) - break; - - bind = nvkm_namedb_get(nv_namedb(chan), chan->subc[subc]); - if (likely(bind)) { - if (!nv_call(bind->object, mthd, data)) - handled = true; - nvkm_namedb_put(bind); - } break; } -out: - spin_unlock_irqrestore(&fifo->base.lock, flags); return handled; } @@ -426,6 +401,7 @@ nv04_fifo_cache_error(struct nv04_fifo *fifo, u32 chid, u32 get) { struct nvkm_subdev *subdev = &fifo->base.engine.subdev; struct nvkm_device *device = subdev->device; + u32 pull0 = nvkm_rd32(device, 0x003250); u32 mthd, data; int ptr; @@ -444,7 +420,8 @@ nv04_fifo_cache_error(struct nv04_fifo *fifo, u32 chid, u32 get) data = nvkm_rd32(device, NV40_PFIFO_CACHE1_DATA(ptr)); } - if (!nv04_fifo_swmthd(fifo, chid, mthd, data)) { + if (!(pull0 & 0x00000100) || + !nv04_fifo_swmthd(device, chid, mthd, data)) { const char *client_name = nvkm_client_name_for_fifo_chid(&fifo->base, chid); nvkm_error(subdev, "CACHE_ERROR - " diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/sw/Kbuild index 1144d84e46de..1c291e6fcf96 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/Kbuild @@ -1,3 +1,4 @@ +nvkm-y += nvkm/engine/sw/base.o nvkm-y += nvkm/engine/sw/nv04.o nvkm-y += nvkm/engine/sw/nv10.o nvkm-y += nvkm/engine/sw/nv50.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c new file mode 100644 index 000000000000..1d68ae68884a --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c @@ -0,0 +1,64 @@ +/* + * Copyright 2015 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * 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 "priv.h" +#include "chan.h" + +#include + +bool +nvkm_sw_mthd(struct nvkm_sw *sw, int chid, int subc, u32 mthd, u32 data) +{ + struct nvkm_sw_chan *chan; + bool handled = false; + unsigned long flags; + + spin_lock_irqsave(&sw->engine.lock, flags); + list_for_each_entry(chan, &sw->chan, head) { + if (chan->fifo->chid == chid) { + handled = nvkm_sw_chan_mthd(chan, subc, mthd, data); + list_del(&chan->head); + list_add(&chan->head, &sw->chan); + break; + } + } + spin_unlock_irqrestore(&sw->engine.lock, flags); + return handled; +} + +int +nvkm_sw_ctor(struct nvkm_object *parent, struct nvkm_object *engine, + struct nvkm_oclass *oclass, int length, void **pobject) +{ + struct nvkm_sw *sw; + int ret; + + ret = nvkm_engine_create_(parent, engine, oclass, true, "sw", + "sw", length, pobject); + sw = *pobject; + if (ret) + return ret; + + 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 97c0d96463a2..904405a8f5c6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c @@ -24,10 +24,28 @@ #include "chan.h" #include +#include #include #include +bool +nvkm_sw_chan_mthd(struct nvkm_sw_chan *chan, int subc, u32 mthd, u32 data) +{ + switch (mthd) { + case 0x0000: + return true; + case 0x0500: + nvkm_event_send(&chan->event, 1, 0, NULL, 0); + return true; + default: + if (chan->func->mthd) + return chan->func->mthd(chan, subc, mthd, data); + break; + } + return false; +} + static int nvkm_sw_chan_event_ctor(struct nvkm_object *object, void *data, u32 size, struct nvkm_notify *notify) @@ -55,14 +73,17 @@ void nvkm_sw_chan_dtor(struct nvkm_object *base) { struct nvkm_sw_chan *chan = (void *)base; + list_del(&chan->head); nvkm_event_fini(&chan->event); nvkm_engctx_destroy(&chan->base); } int -nvkm_sw_chan_ctor(struct nvkm_object *parent, struct nvkm_object *engine, +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) { + struct nvkm_sw *sw = (void *)engine; struct nvkm_sw_chan *chan; int ret; @@ -72,5 +93,9 @@ nvkm_sw_chan_ctor(struct nvkm_object *parent, struct nvkm_object *engine, if (ret) return ret; + chan->func = func; + chan->fifo = nvkm_fifo_chan(parent); + list_add(&chan->head, &sw->chan); + 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 b5cf4c517a95..edebd9c30c0c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h @@ -6,12 +6,22 @@ struct nvkm_sw_chan { struct nvkm_engctx base; + const struct nvkm_sw_chan_func *func; + struct nvkm_fifo_chan *fifo; + struct list_head head; struct nvkm_event event; }; -#define nvkm_sw_context_create(p,e,c,d) \ - nvkm_sw_chan_ctor((p), (e), (c), sizeof(**d), (void **)d) -int nvkm_sw_chan_ctor(struct nvkm_object *, struct nvkm_object *, +struct nvkm_sw_chan_func { + bool (*mthd)(struct nvkm_sw_chan *, int subc, u32 mthd, u32 data); +}; + +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) \ diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c index d57052cdcad3..ac106c6c25d0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c @@ -24,6 +24,7 @@ #include "nv50.h" #include +#include #include @@ -31,65 +32,9 @@ * software object classes ******************************************************************************/ -static int -gf100_sw_mthd_vblsem_offset(struct nvkm_object *object, u32 mthd, - void *args, u32 size) -{ - struct nv50_sw_chan *chan = (void *)nv_engctx(object->parent); - u64 data = *(u32 *)args; - if (mthd == 0x0400) { - chan->vblank.offset &= 0x00ffffffffULL; - chan->vblank.offset |= data << 32; - } else { - chan->vblank.offset &= 0xff00000000ULL; - chan->vblank.offset |= data; - } - return 0; -} - -static int -gf100_sw_mthd_mp_control(struct nvkm_object *object, u32 mthd, - void *args, u32 size) -{ - struct nv50_sw_chan *chan = (void *)nv_engctx(object->parent); - struct nvkm_sw *sw = (void *)nv_object(chan)->engine; - struct nvkm_device *device = sw->engine.subdev.device; - u32 data = *(u32 *)args; - - switch (mthd) { - case 0x600: - nvkm_wr32(device, 0x419e00, data); /* MP.PM_UNK000 */ - break; - case 0x644: - if (data & ~0x1ffffe) - return -EINVAL; - nvkm_wr32(device, 0x419e44, data); /* MP.TRAP_WARP_ERROR_EN */ - break; - case 0x6ac: - nvkm_wr32(device, 0x419eac, data); /* MP.PM_UNK0AC */ - break; - default: - return -EINVAL; - } - return 0; -} - -static struct nvkm_omthds -gf100_sw_omthds[] = { - { 0x0400, 0x0400, gf100_sw_mthd_vblsem_offset }, - { 0x0404, 0x0404, gf100_sw_mthd_vblsem_offset }, - { 0x0408, 0x0408, nv50_sw_mthd_vblsem_value }, - { 0x040c, 0x040c, nv50_sw_mthd_vblsem_release }, - { 0x0500, 0x0500, nv50_sw_mthd_flip }, - { 0x0600, 0x0600, gf100_sw_mthd_mp_control }, - { 0x0644, 0x0644, gf100_sw_mthd_mp_control }, - { 0x06ac, 0x06ac, gf100_sw_mthd_mp_control }, - {} -}; - static struct nvkm_oclass gf100_sw_sclass[] = { - { NVIF_IOCTL_NEW_V0_SW_GF100, &nvkm_nvsw_ofuncs, gf100_sw_omthds }, + { NVIF_IOCTL_NEW_V0_SW_GF100, &nvkm_nvsw_ofuncs }, {} }; @@ -115,6 +60,53 @@ gf100_sw_vblsem_release(struct nvkm_notify *notify) return NVKM_NOTIFY_DROP; } +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_device *device = engine->subdev.device; + switch (mthd) { + case 0x0400: + chan->vblank.offset &= 0x00ffffffffULL; + chan->vblank.offset |= (u64)data << 32; + return true; + case 0x0404: + chan->vblank.offset &= 0xff00000000ULL; + chan->vblank.offset |= data; + return true; + case 0x0408: + chan->vblank.value = data; + return true; + case 0x040c: + if (data < device->disp->vblank.index_nr) { + nvkm_notify_get(&chan->vblank.notify[data]); + return true; + } + break; + case 0x600: /* MP.PM_UNK000 */ + nvkm_wr32(device, 0x419e00, data); + return true; + case 0x644: /* MP.TRAP_WARP_ERROR_EN */ + if (!(data & ~0x001ffffe)) { + nvkm_wr32(device, 0x419e44, data); + return true; + } + break; + case 0x6ac: /* MP.PM_UNK0AC */ + nvkm_wr32(device, 0x419eac, data); + return true; + default: + break; + } + return false; +} + +static const struct nvkm_sw_chan_func +gf100_sw_chan_func = { + .mthd = gf100_sw_chan_mthd, +}; + static struct nv50_sw_cclass gf100_sw_cclass = { .base.handle = NV_ENGCTX(SW, 0xc0), @@ -125,6 +117,7 @@ gf100_sw_cclass = { .fini = _nvkm_sw_context_fini, }, .vblank = gf100_sw_vblsem_release, + .chan = &gf100_sw_chan_func, }; /******************************************************************************* diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv04.c index 08b59f198c73..6958cba393da 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv04.c @@ -21,6 +21,7 @@ * * Authors: Ben Skeggs */ +#define nv04_sw_chan(p) container_of((p), struct nv04_sw_chan, base) #include "priv.h" #include "chan.h" #include "nvsw.h" @@ -38,29 +39,6 @@ struct nv04_sw_chan { * software object classes ******************************************************************************/ -static int -nv04_sw_set_ref(struct nvkm_object *object, u32 mthd, void *data, u32 size) -{ - struct nv04_sw_chan *chan = (void *)nv_engctx(object->parent); - atomic_set(&chan->ref, *(u32*)data); - return 0; -} - -static int -nv04_sw_flip(struct nvkm_object *object, u32 mthd, void *args, u32 size) -{ - struct nvkm_sw_chan *chan = (void *)nv_engctx(object->parent); - nvkm_event_send(&chan->event, 1, 0, NULL, 0); - return 0; -} - -static struct nvkm_omthds -nv04_sw_omthds[] = { - { 0x0150, 0x0150, nv04_sw_set_ref }, - { 0x0500, 0x0500, nv04_sw_flip }, - {} -}; - static int nv04_sw_mthd_get_ref(struct nvkm_object *object, void *data, u32 size) { @@ -100,7 +78,7 @@ nv04_sw_ofuncs = { static struct nvkm_oclass nv04_sw_sclass[] = { - { NVIF_IOCTL_NEW_V0_SW_NV04, &nv04_sw_ofuncs, nv04_sw_omthds }, + { NVIF_IOCTL_NEW_V0_SW_NV04, &nv04_sw_ofuncs }, {} }; @@ -108,6 +86,27 @@ nv04_sw_sclass[] = { * software context ******************************************************************************/ +static bool +nv04_sw_chan_mthd(struct nvkm_sw_chan *base, int subc, u32 mthd, u32 data) +{ + struct nv04_sw_chan *chan = nv04_sw_chan(base); + + switch (mthd) { + case 0x0150: + atomic_set(&chan->ref, data); + return true; + default: + break; + } + + return false; +} + +static const struct nvkm_sw_chan_func +nv04_sw_chan_func = { + .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, @@ -116,7 +115,8 @@ nv04_sw_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, struct nv04_sw_chan *chan; int ret; - ret = nvkm_sw_context_create(parent, engine, oclass, &chan); + ret = nvkm_sw_context_create(&nv04_sw_chan_func, + parent, engine, oclass, &chan); *pobject = nv_object(chan); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv10.c index d0d4339b857c..ecaeeaa8edc7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv10.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv10.c @@ -31,23 +31,9 @@ * software object classes ******************************************************************************/ -static int -nv10_sw_flip(struct nvkm_object *object, u32 mthd, void *args, u32 size) -{ - struct nvkm_sw_chan *chan = (void *)nv_engctx(object->parent); - nvkm_event_send(&chan->event, 1, 0, NULL, 0); - return 0; -} - -static struct nvkm_omthds -nv10_sw_omthds[] = { - { 0x0500, 0x0500, nv10_sw_flip }, - {} -}; - static struct nvkm_oclass nv10_sw_sclass[] = { - { NVIF_IOCTL_NEW_V0_SW_NV10, &nvkm_nvsw_ofuncs, nv10_sw_omthds }, + { NVIF_IOCTL_NEW_V0_SW_NV10, &nvkm_nvsw_ofuncs }, {} }; @@ -55,6 +41,10 @@ nv10_sw_sclass[] = { * software context ******************************************************************************/ +static const struct nvkm_sw_chan_func +nv10_sw_chan_func = { +}; + static int nv10_sw_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, struct nvkm_oclass *oclass, void *data, u32 size, @@ -63,7 +53,8 @@ nv10_sw_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, struct nvkm_sw_chan *chan; int ret; - ret = nvkm_sw_context_create(parent, engine, oclass, &chan); + ret = nvkm_sw_context_create(&nv10_sw_chan_func, + parent, engine, oclass, &chan); *pobject = nv_object(chan); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c index 9322bde518d2..c3af125c7132 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c @@ -35,80 +35,9 @@ * software object classes ******************************************************************************/ -static int -nv50_sw_mthd_dma_vblsem(struct nvkm_object *object, u32 mthd, - void *args, u32 size) -{ - struct nv50_sw_chan *chan = (void *)nv_engctx(object->parent); - struct nvkm_fifo_chan *fifo = (void *)nv_object(chan)->parent; - struct nvkm_handle *handle; - int ret = -EINVAL; - - handle = nvkm_namedb_get(nv_namedb(fifo), *(u32 *)args); - if (!handle) - return -ENOENT; - - if (nv_iclass(handle->object, NV_GPUOBJ_CLASS)) { - struct nvkm_gpuobj *gpuobj = nv_gpuobj(handle->object); - chan->vblank.ctxdma = gpuobj->node->offset >> 4; - ret = 0; - } - nvkm_namedb_put(handle); - return ret; -} - -static int -nv50_sw_mthd_vblsem_offset(struct nvkm_object *object, u32 mthd, - void *args, u32 size) -{ - struct nv50_sw_chan *chan = (void *)nv_engctx(object->parent); - chan->vblank.offset = *(u32 *)args; - return 0; -} - -int -nv50_sw_mthd_vblsem_value(struct nvkm_object *object, u32 mthd, - void *args, u32 size) -{ - struct nv50_sw_chan *chan = (void *)nv_engctx(object->parent); - chan->vblank.value = *(u32 *)args; - return 0; -} - -int -nv50_sw_mthd_vblsem_release(struct nvkm_object *object, u32 mthd, - void *args, u32 size) -{ - struct nv50_sw_chan *chan = (void *)nv_engctx(object->parent); - u32 head = *(u32 *)args; - if (head >= nvkm_disp(chan)->vblank.index_nr) - return -EINVAL; - - nvkm_notify_get(&chan->vblank.notify[head]); - return 0; -} - -int -nv50_sw_mthd_flip(struct nvkm_object *object, u32 mthd, void *args, u32 size) -{ - struct nv50_sw_chan *chan = (void *)nv_engctx(object->parent); - nvkm_event_send(&chan->base.event, 1, 0, NULL, 0); - return 0; -} - -static struct nvkm_omthds -nv50_sw_omthds[] = { - { 0x018c, 0x018c, nv50_sw_mthd_dma_vblsem }, - { 0x0400, 0x0400, nv50_sw_mthd_vblsem_offset }, - { 0x0404, 0x0404, nv50_sw_mthd_vblsem_value }, - { 0x0408, 0x0408, nv50_sw_mthd_vblsem_release }, - { 0x0500, 0x0500, nv50_sw_mthd_flip }, - {} -}; - static struct nvkm_oclass nv50_sw_sclass[] = { - { NVIF_IOCTL_NEW_V0_SW_NV50, &nvkm_nvsw_ofuncs, nv50_sw_omthds }, + { NVIF_IOCTL_NEW_V0_SW_NV50, &nvkm_nvsw_ofuncs }, {} }; @@ -140,6 +69,31 @@ nv50_sw_vblsem_release(struct nvkm_notify *notify) return NVKM_NOTIFY_DROP; } +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); + switch (mthd) { + case 0x018c: chan->vblank.ctxdma = data; return true; + case 0x0400: chan->vblank.offset = data; return true; + case 0x0404: chan->vblank.value = data; return true; + case 0x0408: + if (data < nvkm_disp(chan)->vblank.index_nr) { + nvkm_notify_get(&chan->vblank.notify[data]); + return true; + } + break; + default: + break; + } + return false; +} + +static const struct nvkm_sw_chan_func +nv50_sw_chan_func = { + .mthd = nv50_sw_chan_mthd, +}; + void nv50_sw_context_dtor(struct nvkm_object *object) { @@ -162,7 +116,7 @@ nv50_sw_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine, struct nv50_sw_chan *chan; int ret, i; - ret = nvkm_sw_context_create(parent, engine, oclass, &chan); + ret = nvkm_sw_context_create(pclass->chan, parent, engine, oclass, &chan); *pobject = nv_object(chan); if (ret) return ret; @@ -194,6 +148,7 @@ nv50_sw_cclass = { .fini = _nvkm_sw_context_fini, }, .vblank = nv50_sw_vblsem_release, + .chan = &nv50_sw_chan_func, }; /******************************************************************************* diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h index f3bf451546b1..534c21079b81 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h @@ -1,5 +1,6 @@ #ifndef __NVKM_SW_NV50_H__ #define __NVKM_SW_NV50_H__ +#define nv50_sw_chan(p) container_of((p), struct nv50_sw_chan, base) #include "priv.h" #include "chan.h" #include "nvsw.h" @@ -18,6 +19,7 @@ int nv50_sw_ctor(struct nvkm_object *, struct nvkm_object *, struct nv50_sw_cclass { struct nvkm_oclass base; int (*vblank)(struct nvkm_notify *); + const struct nvkm_sw_chan_func *chan; }; struct nv50_sw_chan {