drm/nouveau/sw: remove dependence on namedb/engctx lookup
authorBen Skeggs <bskeggs@redhat.com>
Thu, 20 Aug 2015 04:54:18 +0000 (14:54 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Fri, 28 Aug 2015 02:40:39 +0000 (12:40 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
15 files changed:
drivers/gpu/drm/nouveau/include/nvkm/core/object.h
drivers/gpu/drm/nouveau/include/nvkm/engine/sw.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c
drivers/gpu/drm/nouveau/nvkm/engine/sw/Kbuild
drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c
drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h
drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c
drivers/gpu/drm/nouveau/nvkm/engine/sw/nv04.c
drivers/gpu/drm/nouveau/nvkm/engine/sw/nv10.c
drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c
drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h

index 3366ec59a64ecff80d46c73725357001442fc3c0..7befea315c9851e26bce0a3191d7abc52c304af0 100644 (file)
@@ -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
index b06140af0a05b93151a865aead50b83e86f41149..f5857a6404d356d6d0a56cef270fd14ce10bfbc1 100644 (file)
@@ -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)                                               \
index 21dbd390111328eab3aa0d1cdb9edac3ba7bbae8..3c50d28d33a0097d401bc07d21f4387475f0d41d 100644 (file)
@@ -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 *);
index 39031841d057c6f20253b6b71555a6a8f5a302cd..7f05985ebb377cc881a22cb2eb938c8d367e850b 100644 (file)
@@ -31,6 +31,7 @@
 #include <subdev/fb.h>
 #include <subdev/mmu.h>
 #include <subdev/timer.h>
+#include <engine/sw.h>
 
 #include <nvif/class.h>
 #include <nvif/ioctl.h>
@@ -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) {
index 3d2b16e7a7ee66d0ee655b61b7a61da0270f7ec1..e0badfc54dc8040dba3ab7bffe71c808fafa6bbe 100644 (file)
@@ -31,6 +31,7 @@
 #include <subdev/fb.h>
 #include <subdev/mmu.h>
 #include <subdev/timer.h>
+#include <engine/sw.h>
 
 #include <nvif/class.h>
 #include <nvif/ioctl.h>
@@ -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);
        }
 
index cd5009302e223d11d22ff00202cbd11822cc7cc5..8bdb71f5f1c54689de3ac1adeb9b62574c420dd3 100644 (file)
@@ -29,6 +29,7 @@
 #include <core/ramht.h>
 #include <subdev/instmem.h>
 #include <subdev/timer.h>
+#include <engine/sw.h>
 
 #include <nvif/class.h>
 #include <nvif/unpack.h>
@@ -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 - "
index 1144d84e46de33b4bf8741b1d8c11951699ae3bd..1c291e6fcf964dffe91b2ce25c3adc344e8de85e 100644 (file)
@@ -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 (file)
index 0000000..1d68ae6
--- /dev/null
@@ -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 <bskeggs@redhat.com>
+ */
+#include "priv.h"
+#include "chan.h"
+
+#include <engine/fifo.h>
+
+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;
+}
index 97c0d96463a2ca3c29c63d7e5ce3c6aabed83643..904405a8f5c6b2c5a92cc1e3d88931917757e3ce 100644 (file)
 #include "chan.h"
 
 #include <core/notify.h>
+#include <engine/fifo.h>
 
 #include <nvif/event.h>
 #include <nvif/unpack.h>
 
+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);
 }
index b5cf4c517a955ef7098334bc69ea81fdb0fe2f75..edebd9c30c0c4b29f1a7d019f982ad5b7e43a413 100644 (file)
@@ -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)                                       \
index d57052cdcad3d1cb66366d19b9eb8fdc012e9133..ac106c6c25d07139e53e3980ca99d3ad28cb5e13 100644 (file)
@@ -24,6 +24,7 @@
 #include "nv50.h"
 
 #include <subdev/bar.h>
+#include <engine/disp.h>
 
 #include <nvif/ioctl.h>
 
  * 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,
 };
 
 /*******************************************************************************
index 08b59f198c73a06e5317bf1c3c113ac838117ff0..6958cba393daa4bcaa767a7d3d32c2bb7a8c1655 100644 (file)
@@ -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;
index d0d4339b857c07050f44cd66c42e4a4e37e030a9..ecaeeaa8edc7cca18eb9633f11858078372efab1 100644 (file)
  * 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;
index 9322bde518d2eef8c1ddc2cb421e7372696a0f9e..c3af125c7132e6c8fee298e822bf0fad16de5a9e 100644 (file)
  * 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,
 };
 
 /*******************************************************************************
index f3bf451546b12f6d825aac1357808b650f796d83..534c21079b81a91cf71d7da446a495a374ce6cf8 100644 (file)
@@ -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 {