drm/nouveau/fifo: convert user classes to new-style nvkm_object
authorBen Skeggs <bskeggs@redhat.com>
Thu, 20 Aug 2015 04:54:19 +0000 (14:54 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Fri, 28 Aug 2015 02:40:40 +0000 (12:40 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
61 files changed:
drivers/gpu/drm/nouveau/include/nvif/device.h
drivers/gpu/drm/nouveau/include/nvkm/core/engctx.h
drivers/gpu/drm/nouveau/include/nvkm/core/engine.h
drivers/gpu/drm/nouveau/include/nvkm/core/handle.h
drivers/gpu/drm/nouveau/include/nvkm/core/namedb.h [deleted file]
drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h
drivers/gpu/drm/nouveau/nv84_fence.c
drivers/gpu/drm/nouveau/nvkm/core/Kbuild
drivers/gpu/drm/nouveau/nvkm/core/engctx.c
drivers/gpu/drm/nouveau/nvkm/core/gpuobj.c
drivers/gpu/drm/nouveau/nvkm/core/handle.c
drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
drivers/gpu/drm/nouveau/nvkm/core/namedb.c [deleted file]
drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c
drivers/gpu/drm/nouveau/nvkm/engine/cipher/g84.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c
drivers/gpu/drm/nouveau/nvkm/engine/dma/base.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h
drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h
drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h
drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h
drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h
drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm204.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogm204.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h
drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h
drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h
drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c
drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c
drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c
drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c
drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c
drivers/gpu/drm/nouveau/nvkm/engine/sec/g98.c
drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c
drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c
drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c

index 78c6649407e66fb4902dadb919b934271510313e..d52ef8419fd2736ff6fbca1c8d7b1f7b3dbc1eb9 100644 (file)
@@ -64,6 +64,6 @@ u64  nvif_device_time(struct nvif_device *);
 #include <engine/gr.h>
 #include <engine/sw.h>
 
-#define nvxx_fifo(a) nvkm_fifo(nvxx_device(a))
+#define nvxx_fifo(a) nvxx_device(a)->fifo
 #define nvxx_gr(a) nvkm_gr(nvxx_device(a))
 #endif
index dfa24d233321aa8e2ec78b237f549376e13ac4b7..4a77fdaa8b90cc77bf13396f88a27601bd69f532 100644 (file)
@@ -45,7 +45,4 @@ int  _nvkm_engctx_init(struct nvkm_object *);
 int  _nvkm_engctx_fini(struct nvkm_object *, bool suspend);
 #define _nvkm_engctx_rd32 _nvkm_gpuobj_rd32
 #define _nvkm_engctx_wr32 _nvkm_gpuobj_wr32
-
-struct nvkm_object *nvkm_engctx_get(struct nvkm_engine *, u64 addr);
-void nvkm_engctx_put(struct nvkm_object *);
 #endif
index 8c67d755e5c1ec8afe56d8c836d576837fcb1178..9d9c0e779f3fe26e2ee0fe6e640796c63f219498 100644 (file)
@@ -42,6 +42,7 @@ struct nvkm_engine_func {
                int (*sclass)(struct nvkm_oclass *, int index);
        } fifo;
 
+       const struct nvkm_object_func *cclass;
        struct nvkm_sclass sclass[];
 };
 
index 88e8bb17a280ccec46f2cb653fb6e628d2956c43..539278916d23b4823e8ca32fcb799182d8f09bb9 100644 (file)
@@ -4,7 +4,6 @@
 struct nvkm_object;
 
 struct nvkm_handle {
-       struct nvkm_namedb *namedb;
        struct list_head node;
 
        struct list_head head;
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/namedb.h b/drivers/gpu/drm/nouveau/include/nvkm/core/namedb.h
deleted file mode 100644 (file)
index 16337f6..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef __NVKM_NAMEDB_H__
-#define __NVKM_NAMEDB_H__
-#include <core/parent.h>
-struct nvkm_handle;
-
-struct nvkm_namedb {
-       struct nvkm_parent parent;
-       rwlock_t lock;
-       struct list_head list;
-};
-
-static inline struct nvkm_namedb *
-nv_namedb(void *obj)
-{
-#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA
-       BUG_ON(!nv_iclass(obj, NV_NAMEDB_CLASS));
-#endif
-       return obj;
-}
-
-#define nvkm_namedb_create(p,e,c,v,s,m,d)                                   \
-       nvkm_namedb_create_((p), (e), (c), (v), (s), (m),                   \
-                              sizeof(**d), (void **)d)
-#define nvkm_namedb_init(p)                                                 \
-       nvkm_parent_init(&(p)->parent)
-#define nvkm_namedb_fini(p,s)                                               \
-       nvkm_parent_fini(&(p)->parent, (s))
-#define nvkm_namedb_destroy(p)                                              \
-       nvkm_parent_destroy(&(p)->parent)
-
-int  nvkm_namedb_create_(struct nvkm_object *, struct nvkm_object *,
-                           struct nvkm_oclass *, u32 pclass,
-                           struct nvkm_oclass *, u64 engcls,
-                           int size, void **);
-
-int  _nvkm_namedb_ctor(struct nvkm_object *, struct nvkm_object *,
-                         struct nvkm_oclass *, void *, u32,
-                         struct nvkm_object **);
-#define _nvkm_namedb_dtor _nvkm_parent_dtor
-#define _nvkm_namedb_init _nvkm_parent_init
-#define _nvkm_namedb_fini _nvkm_parent_fini
-
-int  nvkm_namedb_insert(struct nvkm_namedb *, u32 name, struct nvkm_object *,
-                       struct nvkm_handle *);
-void nvkm_namedb_remove(struct nvkm_handle *);
-
-struct nvkm_handle *nvkm_namedb_get(struct nvkm_namedb *, u32);
-struct nvkm_handle *nvkm_namedb_get_class(struct nvkm_namedb *, s32);
-struct nvkm_handle *nvkm_namedb_get_vinst(struct nvkm_namedb *, u64);
-struct nvkm_handle *nvkm_namedb_get_cinst(struct nvkm_namedb *, u32);
-void nvkm_namedb_put(struct nvkm_handle *);
-#endif
index ac97072dcfefd883ee8765e3ba390a25d48e365b..d9e494ba50338f89d727a5fa921f2a31c09457ff 100644 (file)
@@ -1,25 +1,39 @@
 #ifndef __NVKM_FIFO_H__
 #define __NVKM_FIFO_H__
-#include <core/namedb.h>
+#define nvkm_fifo_chan(p) container_of((p), struct nvkm_fifo_chan, object)
+#define nvkm_fifo(p) container_of((p), struct nvkm_fifo, engine)
+#include <core/engine.h>
+#include <core/event.h>
+
+#define NVKM_FIFO_CHID_NR 4096
+
+struct nvkm_fifo_engn {
+       struct nvkm_object *object;
+       int refcount;
+       int usecount;
+};
 
 struct nvkm_fifo_chan {
-       struct nvkm_namedb namedb;
-       struct nvkm_gpuobj *pushgpu;
+       const struct nvkm_fifo_chan_func *func;
+       struct nvkm_fifo *fifo;
+       u64 engines;
+       struct nvkm_object object;
+
+       struct list_head head;
+       u16 chid;
+       struct nvkm_gpuobj *inst;
+       struct nvkm_gpuobj *push;
+       struct nvkm_vm *vm;
        void __iomem *user;
        u64 addr;
        u32 size;
-       u16 chid;
-       u64 inst;
+
+       struct nvkm_fifo_engn engn[NVDEV_SUBDEV_NR];
 };
 
-static inline struct nvkm_fifo_chan *
-nvkm_fifo_chan(void *obj)
-{
-       return (void *)nv_namedb(obj);
-}
+extern const struct nvkm_object_func nvkm_fifo_chan_func;
 
 #include <core/gpuobj.h>
-
 struct nvkm_fifo_base {
        struct nvkm_gpuobj gpuobj;
 };
@@ -39,25 +53,27 @@ struct nvkm_fifo_base {
 #define _nvkm_fifo_context_rd32 _nvkm_gpuobj_rd32
 #define _nvkm_fifo_context_wr32 _nvkm_gpuobj_wr32
 
-#include <core/engine.h>
-#include <core/event.h>
-
 struct nvkm_fifo {
        struct nvkm_engine engine;
+       const struct nvkm_fifo_func *func;
 
        struct nvkm_event cevent; /* channel creation event */
        struct nvkm_event uevent; /* async user trigger */
 
-       struct nvkm_object **channel;
+       DECLARE_BITMAP(mask, NVKM_FIFO_CHID_NR);
+       int nr;
+       struct list_head chan;
        spinlock_t lock;
-       u16 min;
-       u16 max;
 
-       int  (*chid)(struct nvkm_fifo *, struct nvkm_object *);
        void (*pause)(struct nvkm_fifo *, unsigned long *);
        void (*start)(struct nvkm_fifo *, unsigned long *);
 };
 
+struct nvkm_fifo_func {
+       void *(*dtor)(struct nvkm_fifo *);
+       const struct nvkm_fifo_chan_oclass *chan[];
+};
+
 void nvkm_fifo_chan_put(struct nvkm_fifo *, unsigned long flags,
                        struct nvkm_fifo_chan **);
 struct nvkm_fifo_chan *
@@ -65,12 +81,6 @@ nvkm_fifo_chan_inst(struct nvkm_fifo *, u64 inst, unsigned long *flags);
 struct nvkm_fifo_chan *
 nvkm_fifo_chan_chid(struct nvkm_fifo *, int chid, unsigned long *flags);
 
-static inline struct nvkm_fifo *
-nvkm_fifo(void *obj)
-{
-       return (void *)nvkm_engine(obj, NVDEV_ENGINE_FIFO);
-}
-
 #define nvkm_fifo_create(o,e,c,fc,lc,d)                                     \
        nvkm_fifo_create_((o), (e), (c), (fc), (lc), sizeof(**d), (void **)d)
 #define nvkm_fifo_init(p)                                                   \
@@ -82,8 +92,6 @@ int nvkm_fifo_create_(struct nvkm_object *, struct nvkm_object *,
                         struct nvkm_oclass *, int min, int max,
                         int size, void **);
 void nvkm_fifo_destroy(struct nvkm_fifo *);
-const char *
-nvkm_client_name_for_fifo_chid(struct nvkm_fifo *fifo, u32 chid);
 
 #define _nvkm_fifo_init _nvkm_engine_init
 #define _nvkm_fifo_fini _nvkm_engine_fini
index 4d7ad6d3fbd4d2213b5f74e0c43da85101949f6a..412c5be5a9ca2858e6ae208dae05bb08ff062558 100644 (file)
@@ -228,7 +228,7 @@ nv84_fence_create(struct nouveau_drm *drm)
        priv->base.context_new = nv84_fence_context_new;
        priv->base.context_del = nv84_fence_context_del;
 
-       priv->base.contexts = fifo->max + 1;
+       priv->base.contexts = fifo->nr;
        priv->base.context_base = fence_context_alloc(priv->base.contexts);
        priv->base.uevent = true;
 
index e56c8eb9b054f911b069167274ab3e633f4bb742..d3932d59ff0929e4c8949d0d0d4f983f756d51ae 100644 (file)
@@ -8,7 +8,6 @@ nvkm-y += nvkm/core/handle.o
 nvkm-y += nvkm/core/ioctl.o
 nvkm-y += nvkm/core/memory.o
 nvkm-y += nvkm/core/mm.o
-nvkm-y += nvkm/core/namedb.o
 nvkm-y += nvkm/core/notify.o
 nvkm-y += nvkm/core/object.o
 nvkm-y += nvkm/core/oproxy.o
index be640fd24f77b5dc64c480103c0cde782f216404..bd13facc53d8183c372ed6e2b529cdef1d8e76fe 100644 (file)
@@ -124,58 +124,12 @@ nvkm_engctx_destroy(struct nvkm_engctx *engctx)
 int
 nvkm_engctx_init(struct nvkm_engctx *engctx)
 {
-       struct nvkm_object *object = nv_object(engctx);
-       struct nvkm_subdev *subdev = nv_subdev(object->engine);
-       struct nvkm_object *parent;
-       struct nvkm_subdev *pardev;
-       int ret;
-
-       ret = nvkm_gpuobj_init(&engctx->gpuobj);
-       if (ret)
-               return ret;
-
-       parent = nv_pclass(object->parent, NV_PARENT_CLASS);
-       pardev = nv_subdev(parent->engine);
-       if (nv_parent(parent)->context_attach) {
-               mutex_lock(&pardev->mutex);
-               ret = nv_parent(parent)->context_attach(parent, object);
-               mutex_unlock(&pardev->mutex);
-       }
-
-       if (ret) {
-               nvkm_error(pardev, "failed to attach %s context, %d\n",
-                          nvkm_subdev_name[subdev->index], ret);
-               return ret;
-       }
-
-       nvkm_trace(pardev, "attached %s context\n", nvkm_subdev_name[subdev->index]);
-       return 0;
+       return nvkm_gpuobj_init(&engctx->gpuobj);
 }
 
 int
 nvkm_engctx_fini(struct nvkm_engctx *engctx, bool suspend)
 {
-       struct nvkm_object *object = nv_object(engctx);
-       struct nvkm_subdev *subdev = nv_subdev(object->engine);
-       struct nvkm_object *parent;
-       struct nvkm_subdev *pardev;
-       int ret = 0;
-
-       parent = nv_pclass(object->parent, NV_PARENT_CLASS);
-       pardev = nv_subdev(parent->engine);
-       if (nv_parent(parent)->context_detach) {
-               mutex_lock(&pardev->mutex);
-               ret = nv_parent(parent)->context_detach(parent, suspend, object);
-               mutex_unlock(&pardev->mutex);
-       }
-
-       if (ret) {
-               nvkm_error(pardev, "failed to detach %s context, %d\n",
-                          nvkm_subdev_name[subdev->index], ret);
-               return ret;
-       }
-
-       nvkm_trace(pardev, "detached %s context\n", nvkm_subdev_name[subdev->index]);
        return nvkm_gpuobj_fini(&engctx->gpuobj, suspend);
 }
 
@@ -210,30 +164,3 @@ _nvkm_engctx_fini(struct nvkm_object *object, bool suspend)
 {
        return nvkm_engctx_fini(nv_engctx(object), suspend);
 }
-
-struct nvkm_object *
-nvkm_engctx_get(struct nvkm_engine *engine, u64 addr)
-{
-       struct nvkm_engctx *engctx;
-       unsigned long flags;
-
-       spin_lock_irqsave(&engine->lock, flags);
-       list_for_each_entry(engctx, &engine->contexts, head) {
-               if (engctx->addr == addr) {
-                       engctx->save = flags;
-                       return nv_object(engctx);
-               }
-       }
-       spin_unlock_irqrestore(&engine->lock, flags);
-       return NULL;
-}
-
-void
-nvkm_engctx_put(struct nvkm_object *object)
-{
-       if (object) {
-               struct nvkm_engine *engine = nv_engine(object->engine);
-               struct nvkm_engctx *engctx = nv_engctx(object);
-               spin_unlock_irqrestore(&engine->lock, engctx->save);
-       }
-}
index 54b46037f4ba3c84ae3957072697651f00656c09..e056f7afc35cf74382f88d05d8ee429d1ebfe677 100644 (file)
@@ -231,6 +231,8 @@ nvkm_gpuobj_destroy(struct nvkm_gpuobj *gpuobj)
        nvkm_object_destroy(&gpuobj->object);
 }
 
+#include <engine/fifo.h>
+
 int
 nvkm_gpuobj_create_(struct nvkm_object *parent, struct nvkm_object *engine,
                    struct nvkm_oclass *oclass, u32 pclass,
@@ -240,11 +242,19 @@ nvkm_gpuobj_create_(struct nvkm_object *parent, struct nvkm_object *engine,
        struct nvkm_device *device = nv_device(parent);
        struct nvkm_gpuobj *pargpu = NULL;
        struct nvkm_gpuobj *gpuobj;
+       struct nvkm_object *object = objgpu;
        const bool zero = (flags & NVOBJ_FLAG_ZERO_ALLOC);
        int ret;
 
        *pobject = NULL;
 
+       while (object && object->func != &nvkm_fifo_chan_func)
+               object = object->parent;
+
+       if (object) {
+               struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
+               pargpu = chan->inst;
+       } else
        if (objgpu) {
                while ((objgpu = nv_pclass(objgpu, NV_GPUOBJ_CLASS))) {
                        if (nv_gpuobj(objgpu)->heap.block_size)
index 2b52a655309b71ddc882d0b73b82b1e611814458..a74ee1c29f8cb5c8cbd5af2c4aaa156db57c5bab 100644 (file)
@@ -23,7 +23,7 @@
  */
 #include <core/handle.h>
 #include <core/client.h>
-#include <core/namedb.h>
+#include <core/parent.h>
 
 #define hprintk(h,l,f,a...) do {                                               \
        struct nvkm_handle *p = (h)->parent; u32 n = p ? p->name : ~0;         \
@@ -98,14 +98,9 @@ int
 nvkm_handle_create(struct nvkm_handle *parent, u32 _handle,
                   struct nvkm_object *object, struct nvkm_handle **phandle)
 {
-       struct nvkm_object *namedb;
        struct nvkm_handle *handle;
        int ret;
 
-       namedb = parent ? parent->object : NULL;
-       while (namedb && !nv_iclass(namedb, NV_NAMEDB_CLASS))
-               namedb = namedb->parent;
-
        handle = kzalloc(sizeof(*handle), GFP_KERNEL);
        if (!handle)
                return -ENOMEM;
@@ -118,15 +113,6 @@ nvkm_handle_create(struct nvkm_handle *parent, u32 _handle,
        handle->parent = parent;
        nvkm_object_ref(object, &handle->object);
 
-       if (namedb) {
-               ret = nvkm_namedb_insert(nv_namedb(namedb), _handle,
-                                        object, handle);
-               if (ret) {
-                       kfree(handle);
-                       return ret;
-               }
-       }
-
        if (parent) {
                if (nv_iclass(parent->object, NV_PARENT_CLASS) &&
                    nv_parent(parent->object)->object_attach) {
@@ -168,40 +154,6 @@ nvkm_handle_destroy(struct nvkm_handle *handle)
        }
 
        hprintk(handle, TRACE, "destroy completed\n");
-       nvkm_namedb_remove(handle);
+       nvkm_object_ref(NULL, &handle->object);
        kfree(handle);
 }
-
-struct nvkm_handle *
-nvkm_handle_get_class(struct nvkm_object *engctx, u16 oclass)
-{
-       struct nvkm_namedb *namedb;
-       if (engctx && (namedb = (void *)nv_pclass(engctx, NV_NAMEDB_CLASS)))
-               return nvkm_namedb_get_class(namedb, oclass);
-       return NULL;
-}
-
-struct nvkm_handle *
-nvkm_handle_get_vinst(struct nvkm_object *engctx, u64 vinst)
-{
-       struct nvkm_namedb *namedb;
-       if (engctx && (namedb = (void *)nv_pclass(engctx, NV_NAMEDB_CLASS)))
-               return nvkm_namedb_get_vinst(namedb, vinst);
-       return NULL;
-}
-
-struct nvkm_handle *
-nvkm_handle_get_cinst(struct nvkm_object *engctx, u32 cinst)
-{
-       struct nvkm_namedb *namedb;
-       if (engctx && (namedb = (void *)nv_pclass(engctx, NV_NAMEDB_CLASS)))
-               return nvkm_namedb_get_cinst(namedb, cinst);
-       return NULL;
-}
-
-void
-nvkm_handle_put(struct nvkm_handle *handle)
-{
-       if (handle)
-               nvkm_namedb_put(handle);
-}
index 04f1bc2d0f8ee8838bc8e98ed3ea6f729535164b..28f9fa289e809a8b057c95dd894bd741ed494185 100644 (file)
@@ -25,7 +25,7 @@
 #include <core/client.h>
 #include <core/engine.h>
 #include <core/handle.h>
-#include <core/namedb.h>
+#include <core/parent.h>
 
 #include <nvif/unpack.h>
 #include <nvif/ioctl.h>
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/namedb.c b/drivers/gpu/drm/nouveau/nvkm/core/namedb.c
deleted file mode 100644 (file)
index 9be1ce9..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright 2012 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * 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 <core/namedb.h>
-#include <core/gpuobj.h>
-#include <core/handle.h>
-
-static struct nvkm_handle *
-nvkm_namedb_lookup(struct nvkm_namedb *namedb, u32 name)
-{
-       struct nvkm_handle *handle;
-
-       list_for_each_entry(handle, &namedb->list, node) {
-               if (handle->name == name)
-                       return handle;
-       }
-
-       return NULL;
-}
-
-static struct nvkm_handle *
-nvkm_namedb_lookup_class(struct nvkm_namedb *namedb, s32 oclass)
-{
-       struct nvkm_handle *handle;
-
-       list_for_each_entry(handle, &namedb->list, node) {
-               if (nv_mclass(handle->object) == oclass)
-                       return handle;
-       }
-
-       return NULL;
-}
-
-static struct nvkm_handle *
-nvkm_namedb_lookup_vinst(struct nvkm_namedb *namedb, u64 vinst)
-{
-       struct nvkm_handle *handle;
-
-       list_for_each_entry(handle, &namedb->list, node) {
-               if (nv_iclass(handle->object, NV_GPUOBJ_CLASS)) {
-                       if (nv_gpuobj(handle->object)->addr == vinst)
-                               return handle;
-               }
-       }
-
-       return NULL;
-}
-
-static struct nvkm_handle *
-nvkm_namedb_lookup_cinst(struct nvkm_namedb *namedb, u32 cinst)
-{
-       struct nvkm_handle *handle;
-
-       list_for_each_entry(handle, &namedb->list, node) {
-               if (nv_iclass(handle->object, NV_GPUOBJ_CLASS)) {
-                       if (nv_gpuobj(handle->object)->node &&
-                           nv_gpuobj(handle->object)->node->offset == cinst)
-                               return handle;
-               }
-       }
-
-       return NULL;
-}
-
-int
-nvkm_namedb_insert(struct nvkm_namedb *namedb, u32 name,
-                  struct nvkm_object *object,
-                  struct nvkm_handle *handle)
-{
-       int ret = -EEXIST;
-       write_lock_irq(&namedb->lock);
-       if (!nvkm_namedb_lookup(namedb, name)) {
-               nvkm_object_ref(object, &handle->object);
-               handle->namedb = namedb;
-               list_add(&handle->node, &namedb->list);
-               ret = 0;
-       }
-       write_unlock_irq(&namedb->lock);
-       return ret;
-}
-
-void
-nvkm_namedb_remove(struct nvkm_handle *handle)
-{
-       struct nvkm_namedb *namedb = handle->namedb;
-       struct nvkm_object *object = handle->object;
-       if (handle->namedb) {
-               write_lock_irq(&namedb->lock);
-               list_del(&handle->node);
-               write_unlock_irq(&namedb->lock);
-       }
-       nvkm_object_ref(NULL, &object);
-}
-
-struct nvkm_handle *
-nvkm_namedb_get(struct nvkm_namedb *namedb, u32 name)
-{
-       struct nvkm_handle *handle;
-       read_lock(&namedb->lock);
-       handle = nvkm_namedb_lookup(namedb, name);
-       if (handle == NULL)
-               read_unlock(&namedb->lock);
-       return handle;
-}
-
-struct nvkm_handle *
-nvkm_namedb_get_class(struct nvkm_namedb *namedb, s32 oclass)
-{
-       struct nvkm_handle *handle;
-       read_lock(&namedb->lock);
-       handle = nvkm_namedb_lookup_class(namedb, oclass);
-       if (handle == NULL)
-               read_unlock(&namedb->lock);
-       return handle;
-}
-
-struct nvkm_handle *
-nvkm_namedb_get_vinst(struct nvkm_namedb *namedb, u64 vinst)
-{
-       struct nvkm_handle *handle;
-       read_lock(&namedb->lock);
-       handle = nvkm_namedb_lookup_vinst(namedb, vinst);
-       if (handle == NULL)
-               read_unlock(&namedb->lock);
-       return handle;
-}
-
-struct nvkm_handle *
-nvkm_namedb_get_cinst(struct nvkm_namedb *namedb, u32 cinst)
-{
-       struct nvkm_handle *handle;
-       read_lock(&namedb->lock);
-       handle = nvkm_namedb_lookup_cinst(namedb, cinst);
-       if (handle == NULL)
-               read_unlock(&namedb->lock);
-       return handle;
-}
-
-void
-nvkm_namedb_put(struct nvkm_handle *handle)
-{
-       if (handle)
-               read_unlock(&handle->namedb->lock);
-}
-
-int
-nvkm_namedb_create_(struct nvkm_object *parent, struct nvkm_object *engine,
-                   struct nvkm_oclass *oclass, u32 pclass,
-                   struct nvkm_oclass *sclass, u64 engcls,
-                   int length, void **pobject)
-{
-       struct nvkm_namedb *namedb;
-       int ret;
-
-       ret = nvkm_parent_create_(parent, engine, oclass, pclass |
-                                 NV_NAMEDB_CLASS, sclass, engcls,
-                                 length, pobject);
-       namedb = *pobject;
-       if (ret)
-               return ret;
-
-       rwlock_init(&namedb->lock);
-       INIT_LIST_HEAD(&namedb->list);
-       return 0;
-}
-
-int
-_nvkm_namedb_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-                 struct nvkm_oclass *oclass, void *data, u32 size,
-                 struct nvkm_object **pobject)
-{
-       struct nvkm_namedb *object;
-       int ret;
-
-       ret = nvkm_namedb_create(parent, engine, oclass, 0, NULL, 0, &object);
-       *pobject = nv_object(object);
-       if (ret)
-               return ret;
-
-       return 0;
-}
index a632570f20e1f19f92d63e5e27c8fdfa33094d2a..1a15b8d6fecead84788813f94d2b7504320caccf 100644 (file)
@@ -85,7 +85,8 @@ gt215_ce_intr(struct nvkm_falcon *ce, struct nvkm_fifo_chan *chan)
        nvkm_error(subdev, "DISPATCH_ERROR %04x [%s] ch %d [%010llx %s] "
                           "subc %d mthd %04x data %08x\n", ssta,
                   en ? en->name : "", chan ? chan->chid : -1,
-                  chan ? chan->inst : 0, nvkm_client_name(chan),
+                  chan ? chan->inst->addr : 0,
+                  chan ? chan->object.client->name : "unknown",
                   subc, mthd, data);
 }
 
index 62cdd1e50a95d259ebdd7d3688ee05867856bb09..74bea4397bf4e207487249e3d90f17d023ba3865 100644 (file)
@@ -121,9 +121,10 @@ g84_cipher_intr(struct nvkm_subdev *subdev)
        if (stat) {
                nvkm_snprintbf(msg, sizeof(msg), g84_cipher_intr_mask, stat);
                nvkm_error(subdev,  "%08x [%s] ch %d [%010llx %s] "
-                                   "mthd %04x data %08x\n",
-                          stat, msg, chan ? chan->chid : -1, (u64)inst << 12,
-                          nvkm_client_name(chan), mthd, data);
+                                   "mthd %04x data %08x\n", stat, msg,
+                          chan ? chan->chid : -1, (u64)inst << 12,
+                          chan ? chan->object.client->name : "unknown",
+                          mthd, data);
        }
        nvkm_fifo_chan_put(fifo, flags, &chan);
 
index 2d9b81fb83a2253b6d54f26d4230aed7af86c23f..62d3fb66d0ec23a8606e6af0267f2fa6d215d012 100644 (file)
@@ -21,7 +21,7 @@
  *
  * Authors: Ben Skeggs
  */
-#define nv04_disp_root(p) container_of((p), struct nv04_disp_root, object);
+#define nv04_disp_root(p) container_of((p), struct nv04_disp_root, object)
 #include "priv.h"
 
 #include <core/client.h>
index 57f6eca078ef696e87c63ef753a0349272554523..1a377201949c9a12e1824ecac15e63aceaaeb81d 100644 (file)
@@ -24,6 +24,7 @@
 #include "priv.h"
 
 #include <core/client.h>
+#include <engine/fifo.h>
 
 #include <nvif/class.h>
 
@@ -88,11 +89,19 @@ nvkm_dma_oclass_base = {
        .ctor = nvkm_dma_oclass_new,
 };
 
+static int
+nvkm_dma_oclass_fifo_new(const struct nvkm_oclass *oclass, void *data, u32 size,
+                        struct nvkm_object **pobject)
+{
+       return nvkm_dma_oclass_new(oclass->engine->subdev.device,
+                                  oclass, data, size, pobject);
+}
+
 static const struct nvkm_sclass
 nvkm_dma_sclass[] = {
-       { 0, 0, NV_DMA_FROM_MEMORY },
-       { 0, 0, NV_DMA_TO_MEMORY },
-       { 0, 0, NV_DMA_IN_MEMORY },
+       { 0, 0, NV_DMA_FROM_MEMORY, NULL, nvkm_dma_oclass_fifo_new },
+       { 0, 0, NV_DMA_TO_MEMORY, NULL, nvkm_dma_oclass_fifo_new },
+       { 0, 0, NV_DMA_IN_MEMORY, NULL, nvkm_dma_oclass_fifo_new },
 };
 
 static int
@@ -110,89 +119,21 @@ nvkm_dma_oclass_base_get(struct nvkm_oclass *sclass, int index,
        return count;
 }
 
-static const struct nvkm_engine_func
-nvkm_dma = {
-       .base.sclass = nvkm_dma_oclass_base_get,
-};
-
-#include <core/gpuobj.h>
-
-static struct nvkm_oclass empty = {
-       .ofuncs = &(struct nvkm_ofuncs) {
-               .dtor = nvkm_object_destroy,
-               .init = _nvkm_object_init,
-               .fini = _nvkm_object_fini,
-       },
-};
-
 static int
-nvkm_dmaobj_compat_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-                       struct nvkm_oclass *oclass, void *data, u32 size,
-                       struct nvkm_object **pobject)
-{
-       struct nvkm_oclass hack = {
-               .base.oclass = oclass->handle,
-               .client = nvkm_client(parent),
-               .parent = parent,
-               .engine = nv_engine(engine),
-       };
-       struct nvkm_dma *dma = (void *)engine;
-       struct nvkm_dma_impl *impl = (void *)dma->engine.subdev.object.oclass;
-       struct nvkm_dmaobj *dmaobj = NULL;
-       struct nvkm_gpuobj *gpuobj;
-       int ret;
-
-       ret = impl->class_new(dma, &hack, data, size, &dmaobj);
-       if (dmaobj)
-               *pobject = &dmaobj->object;
-       if (ret)
-               return ret;
-
-       gpuobj = (void *)nv_pclass(parent, NV_GPUOBJ_CLASS);
-
-       ret = dmaobj->func->bind(dmaobj, gpuobj, 16, &gpuobj);
-       nvkm_object_ref(NULL, pobject);
-       if (ret)
-               return ret;
-
-       ret = nvkm_object_create(parent, engine, &empty, 0, pobject);
-       if (ret)
-               return ret;
-
-       gpuobj->object.parent = *pobject;
-       gpuobj->object.engine = &dma->engine;
-       gpuobj->object.oclass = oclass;
-       gpuobj->object.pclass = NV_GPUOBJ_CLASS;
-#if CONFIG_NOUVEAU_DEBUG >= NV_DBG_PARANOIA
-       gpuobj->object._magic = NVKM_OBJECT_MAGIC;
-#endif
-       *pobject = &gpuobj->object;
-       return 0;
-}
-
-static void
-nvkm_dmaobj_compat_dtor(struct nvkm_object *object)
+nvkm_dma_oclass_fifo_get(struct nvkm_oclass *oclass, int index)
 {
-       struct nvkm_object *parent = object->parent;
-       struct nvkm_gpuobj *gpuobj = (void *)object;
-       nvkm_gpuobj_del(&gpuobj);
-       nvkm_object_ref(NULL, &parent);
+       const int count = ARRAY_SIZE(nvkm_dma_sclass);
+       if (index < count) {
+               oclass->base = nvkm_dma_sclass[index];
+               return index;
+       }
+       return count;
 }
 
-static struct nvkm_ofuncs
-nvkm_dmaobj_compat_ofuncs = {
-       .ctor = nvkm_dmaobj_compat_ctor,
-       .dtor = nvkm_dmaobj_compat_dtor,
-       .init = _nvkm_object_init,
-       .fini = _nvkm_object_fini,
-};
-
-static struct nvkm_oclass
-nvkm_dma_compat_sclass[] = {
-       { NV_DMA_FROM_MEMORY, &nvkm_dmaobj_compat_ofuncs },
-       { NV_DMA_TO_MEMORY, &nvkm_dmaobj_compat_ofuncs },
-       { NV_DMA_IN_MEMORY, &nvkm_dmaobj_compat_ofuncs },
-       {}
+static const struct nvkm_engine_func
+nvkm_dma = {
+       .base.sclass = nvkm_dma_oclass_base_get,
+       .fifo.sclass = nvkm_dma_oclass_fifo_get,
 };
 
 int
@@ -209,7 +150,6 @@ _nvkm_dma_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
        if (ret)
                return ret;
 
-       dmaeng->engine.sclass = nvkm_dma_compat_sclass;
        dmaeng->engine.func = &nvkm_dma;
        return 0;
 }
index 510de3c2d2e43de8942bb1f2346368fda10d17a7..b693127d80e107daf57297f3644550500a692d82 100644 (file)
@@ -44,12 +44,13 @@ nvkm_fifo_chan_put(struct nvkm_fifo *fifo, unsigned long flags,
 struct nvkm_fifo_chan *
 nvkm_fifo_chan_inst(struct nvkm_fifo *fifo, u64 inst, unsigned long *rflags)
 {
+       struct nvkm_fifo_chan *chan;
        unsigned long flags;
-       int i;
        spin_lock_irqsave(&fifo->lock, flags);
-       for (i = fifo->min; i < fifo->max; i++) {
-               struct nvkm_fifo_chan *chan = (void *)fifo->channel[i];
-               if (chan && chan->inst == inst) {
+       list_for_each_entry(chan, &fifo->chan, head) {
+               if (chan->inst->addr == inst) {
+                       list_del(&chan->head);
+                       list_add(&chan->head, &fifo->chan);
                        *rflags = flags;
                        return chan;
                }
@@ -61,45 +62,21 @@ nvkm_fifo_chan_inst(struct nvkm_fifo *fifo, u64 inst, unsigned long *rflags)
 struct nvkm_fifo_chan *
 nvkm_fifo_chan_chid(struct nvkm_fifo *fifo, int chid, unsigned long *rflags)
 {
+       struct nvkm_fifo_chan *chan;
        unsigned long flags;
        spin_lock_irqsave(&fifo->lock, flags);
-       if (fifo->channel[chid]) {
-               *rflags = flags;
-               return (void *)fifo->channel[chid];
+       list_for_each_entry(chan, &fifo->chan, head) {
+               if (chan->chid == chid) {
+                       list_del(&chan->head);
+                       list_add(&chan->head, &fifo->chan);
+                       *rflags = flags;
+                       return chan;
+               }
        }
        spin_unlock_irqrestore(&fifo->lock, flags);
        return NULL;
 }
 
-static int
-nvkm_fifo_chid(struct nvkm_fifo *fifo, struct nvkm_object *object)
-{
-       int engidx = nv_hclass(fifo) & 0xff;
-
-       while (object && object->parent) {
-               if ( nv_iclass(object->parent, NV_ENGCTX_CLASS) &&
-                   (nv_hclass(object->parent) & 0xff) == engidx)
-                       return nvkm_fifo_chan(object)->chid;
-               object = object->parent;
-       }
-
-       return -1;
-}
-
-const char *
-nvkm_client_name_for_fifo_chid(struct nvkm_fifo *fifo, u32 chid)
-{
-       struct nvkm_fifo_chan *chan = NULL;
-       unsigned long flags;
-
-       spin_lock_irqsave(&fifo->lock, flags);
-       if (chid >= fifo->min && chid <= fifo->max)
-               chan = (void *)fifo->channel[chid];
-       spin_unlock_irqrestore(&fifo->lock, flags);
-
-       return nvkm_client_name(chan);
-}
-
 static int
 nvkm_fifo_event_ctor(struct nvkm_object *object, void *data, u32 size,
                     struct nvkm_notify *notify)
@@ -144,21 +121,62 @@ nvkm_fifo_uevent(struct nvkm_fifo *fifo)
        nvkm_event_send(&fifo->uevent, 1, 0, &rep, sizeof(rep));
 }
 
+static int
+nvkm_fifo_class_new(struct nvkm_device *device,
+                   const struct nvkm_oclass *oclass, void *data, u32 size,
+                   struct nvkm_object **pobject)
+{
+       const struct nvkm_fifo_chan_oclass *sclass = oclass->engn;
+       struct nvkm_fifo *fifo = nvkm_fifo(oclass->engine);
+       return sclass->ctor(fifo, oclass, data, size, pobject);
+}
+
+static const struct nvkm_device_oclass
+nvkm_fifo_class = {
+       .ctor = nvkm_fifo_class_new,
+};
+
+static int
+nvkm_fifo_class_get(struct nvkm_oclass *oclass, int index,
+                   const struct nvkm_device_oclass **class)
+{
+       struct nvkm_fifo *fifo = nvkm_fifo(oclass->engine);
+       const struct nvkm_fifo_chan_oclass *sclass;
+       int c = 0;
+
+       while ((sclass = fifo->func->chan[c])) {
+               if (c++ == index) {
+                       oclass->base = sclass->base;
+                       oclass->engn = sclass;
+                       *class = &nvkm_fifo_class;
+                       return 0;
+               }
+       }
+
+       return c;
+}
+
 void
 nvkm_fifo_destroy(struct nvkm_fifo *fifo)
 {
-       kfree(fifo->channel);
        nvkm_event_fini(&fifo->uevent);
        nvkm_event_fini(&fifo->cevent);
        nvkm_engine_destroy(&fifo->engine);
 }
 
+static const struct nvkm_engine_func
+nvkm_fifo_func = {
+       .base.sclass = nvkm_fifo_class_get,
+};
+
 int
 nvkm_fifo_create_(struct nvkm_object *parent, struct nvkm_object *engine,
                  struct nvkm_oclass *oclass,
                  int min, int max, int length, void **pobject)
 {
        struct nvkm_fifo *fifo;
+       int  nr = max + 1;
+       int cnt = nr - min;
        int ret;
 
        ret = nvkm_engine_create_(parent, engine, oclass, true, "PFIFO",
@@ -167,17 +185,21 @@ nvkm_fifo_create_(struct nvkm_object *parent, struct nvkm_object *engine,
        if (ret)
                return ret;
 
-       fifo->min = min;
-       fifo->max = max;
-       fifo->channel = kzalloc(sizeof(*fifo->channel) * (max + 1), GFP_KERNEL);
-       if (!fifo->channel)
-               return -ENOMEM;
+       fifo->engine.func = &nvkm_fifo_func;
+       INIT_LIST_HEAD(&fifo->chan);
+
+       fifo->nr = nr;
+       if (WARN_ON(fifo->nr > NVKM_FIFO_CHID_NR)) {
+               fifo->nr = NVKM_FIFO_CHID_NR;
+               cnt = fifo->nr - min;
+       }
+       bitmap_fill(fifo->mask, NVKM_FIFO_CHID_NR);
+       bitmap_clear(fifo->mask, min, cnt);
 
        ret = nvkm_event_init(&nvkm_fifo_event_func, 1, 1, &fifo->cevent);
        if (ret)
                return ret;
 
-       fifo->chid = nvkm_fifo_chid;
        spin_lock_init(&fifo->lock);
        return 0;
 }
index cc401ae1d6a5da755acfee7b75ce571a9ee78a76..2735c2df221837756d57874e218d776b2c39f2d6 100644 (file)
 #include "chan.h"
 
 #include <core/client.h>
+#include <core/oproxy.h>
+#include <subdev/mmu.h>
 #include <engine/dma.h>
 
-#include <nvif/class.h>
+struct nvkm_fifo_chan_object {
+       struct nvkm_oproxy oproxy;
+       struct nvkm_fifo_chan *chan;
+       int hash;
+};
 
-int
-_nvkm_fifo_channel_ntfy(struct nvkm_object *object, u32 type,
-                       struct nvkm_event **event)
+static int
+nvkm_fifo_chan_child_fini(struct nvkm_oproxy *base, bool suspend)
+{
+       struct nvkm_fifo_chan_object *object =
+               container_of(base, typeof(*object), oproxy);
+       struct nvkm_engine *engine  = object->oproxy.object->engine;
+       struct nvkm_fifo_chan *chan = object->chan;
+       struct nvkm_fifo_engn *engn = &chan->engn[engine->subdev.index];
+       const char *name = nvkm_subdev_name[engine->subdev.index];
+       int ret = 0;
+
+       if (--engn->usecount)
+               return 0;
+
+       if (chan->func->engine_fini) {
+               ret = chan->func->engine_fini(chan, engine, suspend);
+               if (ret) {
+                       nvif_error(&chan->object,
+                                  "detach %s failed, %d\n", name, ret);
+                       return ret;
+               }
+       }
+
+       if (engn->object) {
+               ret = nvkm_object_fini(engn->object, suspend);
+               if (ret && suspend)
+                       return ret;
+       }
+
+       nvif_trace(&chan->object, "detached %s\n", name);
+       return ret;
+}
+
+static int
+nvkm_fifo_chan_child_init(struct nvkm_oproxy *base)
+{
+       struct nvkm_fifo_chan_object *object =
+               container_of(base, typeof(*object), oproxy);
+       struct nvkm_engine *engine  = object->oproxy.object->engine;
+       struct nvkm_fifo_chan *chan = object->chan;
+       struct nvkm_fifo_engn *engn = &chan->engn[engine->subdev.index];
+       const char *name = nvkm_subdev_name[engine->subdev.index];
+       int ret;
+
+       if (engn->usecount++)
+               return 0;
+
+       if (engn->object) {
+               ret = nvkm_object_init(engn->object);
+               if (ret)
+                       return ret;
+       }
+
+       if (chan->func->engine_init) {
+               ret = chan->func->engine_init(chan, engine);
+               if (ret) {
+                       nvif_error(&chan->object,
+                                  "attach %s failed, %d\n", name, ret);
+                       return ret;
+               }
+       }
+
+       nvif_trace(&chan->object, "attached %s\n", name);
+       return 0;
+}
+
+static void
+nvkm_fifo_chan_child_del(struct nvkm_oproxy *base)
+{
+       struct nvkm_fifo_chan_object *object =
+               container_of(base, typeof(*object), oproxy);
+       struct nvkm_engine *engine  = object->oproxy.base.engine;
+       struct nvkm_fifo_chan *chan = object->chan;
+       struct nvkm_fifo_engn *engn = &chan->engn[engine->subdev.index];
+
+       if (chan->func->object_dtor)
+               chan->func->object_dtor(chan, object->hash);
+
+       if (!--engn->refcount) {
+               if (chan->func->engine_dtor)
+                       chan->func->engine_dtor(chan, engine);
+               nvkm_object_ref(NULL, &engn->object);
+               if (chan->vm)
+                       atomic_dec(&chan->vm->engref[engine->subdev.index]);
+       }
+}
+
+static const struct nvkm_oproxy_func
+nvkm_fifo_chan_child_func = {
+       .dtor[0] = nvkm_fifo_chan_child_del,
+       .init[0] = nvkm_fifo_chan_child_init,
+       .fini[0] = nvkm_fifo_chan_child_fini,
+};
+
+static int
+nvkm_fifo_chan_child_old(const struct nvkm_oclass *oclass,
+                        void *data, u32 size, struct nvkm_object **pobject)
 {
-       struct nvkm_fifo *fifo = (void *)object->engine;
-       switch (type) {
-       case G82_CHANNEL_DMA_V0_NTFY_UEVENT:
-               if (nv_mclass(object) >= G82_CHANNEL_DMA) {
-                       *event = &fifo->uevent;
-                       return 0;
+       struct nvkm_fifo_chan *chan = nvkm_fifo_chan(oclass->parent);
+       struct nvkm_object *parent = &chan->object;
+       struct nvkm_engine *engine = oclass->engine;
+       struct nvkm_oclass *eclass = (void *)oclass->priv;
+       struct nvkm_object *engctx = NULL;
+       struct nvkm_fifo_chan_object *object;
+       struct nvkm_fifo_engn *engn = &chan->engn[engine->subdev.index];
+       int ret;
+
+       if (!(object = kzalloc(sizeof(*object), GFP_KERNEL)))
+               return -ENOMEM;
+       nvkm_oproxy_ctor(&nvkm_fifo_chan_child_func, oclass, &object->oproxy);
+       *pobject = &object->oproxy.base;
+       object->chan = chan;
+
+       if (!engn->refcount++) {
+               if (chan->vm)
+                       atomic_inc(&chan->vm->engref[engine->subdev.index]);
+               if (engine->cclass && !engn->object) {
+                       ret = nvkm_object_old(parent, &engine->subdev.object,
+                                             engine->cclass, NULL, 0,
+                                             &engn->object);
+                       if (ret) {
+                               nvkm_engine_unref(&engine);
+                               return ret;
+                       }
+               } else {
+                       nvkm_object_ref(parent, &engn->object);
                }
-               break;
-       default:
-               break;
+
+               if (chan->func->engine_ctor) {
+                       ret = chan->func->engine_ctor(chan, engine,
+                                                     engn->object);
+                       if (ret)
+                               return ret;
+               }
+       }
+       nvkm_object_ref(engn->object, &engctx);
+
+       ret = nvkm_object_old(engctx, &engine->subdev.object, eclass,
+                             data, size, &object->oproxy.object);
+       nvkm_object_ref(NULL, &engctx);
+       if (ret)
+               return ret;
+
+       object->oproxy.object->handle = oclass->handle;
+
+       if (chan->func->object_ctor) {
+               object->hash =
+                       chan->func->object_ctor(chan, object->oproxy.object);
+               if (object->hash < 0)
+                       return object->hash;
        }
+
+       return 0;
+}
+
+static int
+nvkm_fifo_chan_child_new(const struct nvkm_oclass *oclass, void *data, u32 size,
+                        struct nvkm_object **pobject)
+{
+       struct nvkm_engine *engine = oclass->engine;
+       struct nvkm_fifo_chan *chan = nvkm_fifo_chan(oclass->parent);
+       struct nvkm_fifo_engn *engn = &chan->engn[engine->subdev.index];
+       struct nvkm_fifo_chan_object *object;
+       int ret = 0;
+
+       if (!(object = kzalloc(sizeof(*object), GFP_KERNEL)))
+               return -ENOMEM;
+       nvkm_oproxy_ctor(&nvkm_fifo_chan_child_func, oclass, &object->oproxy);
+       object->chan = chan;
+       *pobject = &object->oproxy.base;
+
+       if (!engn->refcount++) {
+               struct nvkm_oclass cclass = {
+                       .client = oclass->client,
+                       .engine = oclass->engine,
+               };
+
+               if (chan->vm)
+                       atomic_inc(&chan->vm->engref[engine->subdev.index]);
+
+               if (engine->func->fifo.cclass) {
+                       ret = engine->func->fifo.cclass(chan, &cclass,
+                                                       &engn->object);
+               } else
+               if (engine->func->cclass) {
+                       ret = nvkm_object_new_(engine->func->cclass, &cclass,
+                                              NULL, 0, &engn->object);
+               }
+               if (ret)
+                       return ret;
+
+               if (chan->func->engine_ctor) {
+                       ret = chan->func->engine_ctor(chan, oclass->engine,
+                                                     engn->object);
+                       if (ret)
+                               return ret;
+               }
+       }
+
+       ret = oclass->base.ctor(&(const struct nvkm_oclass) {
+                                       .base = oclass->base,
+                                       .engn = oclass->engn,
+                                       .handle = oclass->handle,
+                                       .object = oclass->object,
+                                       .client = oclass->client,
+                                       .parent = engn->object ?
+                                                 engn->object :
+                                                 oclass->parent,
+                                       .engine = engine,
+                               }, data, size, &object->oproxy.object);
+       if (ret)
+               return ret;
+
+       if (chan->func->object_ctor) {
+               object->hash =
+                       chan->func->object_ctor(chan, object->oproxy.object);
+               if (object->hash < 0)
+                       return object->hash;
+       }
+
+       return 0;
+}
+
+static int
+nvkm_fifo_chan_child_get(struct nvkm_object *object, int index,
+                        struct nvkm_oclass *oclass)
+{
+       struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
+       struct nvkm_fifo *fifo = chan->fifo;
+       struct nvkm_device *device = fifo->engine.subdev.device;
+       struct nvkm_engine *engine;
+       u64 mask = chan->engines;
+       int ret, i, c;
+
+       for (; c = 0, i = __ffs64(mask), mask; mask &= ~(1ULL << i)) {
+               if ((engine = nvkm_device_engine(device, i)) &&
+                   !engine->func) {
+                       struct nvkm_oclass *sclass = engine->sclass;
+                       int c = 0;
+                       while (sclass && sclass->ofuncs) {
+                               if (c++ == index) {
+                                       oclass->base.oclass = sclass->handle;
+                                       oclass->base.minver = -2;
+                                       oclass->base.maxver = -2;
+                                       oclass->ctor = nvkm_fifo_chan_child_old;
+                                       oclass->priv = sclass;
+                                       oclass->engine = engine;
+                                       return 0;
+                               }
+                               sclass++;
+                       }
+                       index -= c;
+                       continue;
+               }
+
+               if (!(engine = nvkm_device_engine(device, i)))
+                       continue;
+               oclass->engine = engine;
+               oclass->base.oclass = 0;
+
+               if (engine->func->fifo.sclass) {
+                       ret = engine->func->fifo.sclass(oclass, index);
+                       if (oclass->base.oclass) {
+                               if (!oclass->base.ctor)
+                                       oclass->base.ctor = nvkm_object_new;
+                               oclass->ctor = nvkm_fifo_chan_child_new;
+                               return 0;
+                       }
+
+                       index -= ret;
+                       continue;
+               }
+
+               while (engine->func->sclass[c].oclass) {
+                       if (c++ == index) {
+                               oclass->base = engine->func->sclass[index];
+                               if (!oclass->base.ctor)
+                                       oclass->base.ctor = nvkm_object_new;
+                               oclass->ctor = nvkm_fifo_chan_child_new;
+                               return 0;
+                       }
+               }
+               index -= c;
+       }
+
        return -EINVAL;
 }
 
-int
-_nvkm_fifo_channel_map(struct nvkm_object *object, u64 *addr, u32 *size)
+static int
+nvkm_fifo_chan_ntfy(struct nvkm_object *object, u32 type,
+                   struct nvkm_event **pevent)
 {
-       struct nvkm_fifo_chan *chan = (void *)object;
+       struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
+       if (chan->func->ntfy)
+               return chan->func->ntfy(chan, type, pevent);
+       return -ENODEV;
+}
+
+static int
+nvkm_fifo_chan_map(struct nvkm_object *object, u64 *addr, u32 *size)
+{
+       struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
        *addr = chan->addr;
        *size = chan->size;
        return 0;
 }
 
-u32
-_nvkm_fifo_channel_rd32(struct nvkm_object *object, u64 addr)
+static int
+nvkm_fifo_chan_rd32(struct nvkm_object *object, u64 addr, u32 *data)
 {
-       struct nvkm_fifo_chan *chan = (void *)object;
+       struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
        if (unlikely(!chan->user)) {
                chan->user = ioremap(chan->addr, chan->size);
-               if (WARN_ON_ONCE(chan->user == NULL))
-                       return 0;
+               if (!chan->user)
+                       return -ENOMEM;
        }
-       return ioread32_native(chan->user + addr);
+       if (unlikely(addr + 4 > chan->size))
+               return -EINVAL;
+       *data = ioread32_native(chan->user + addr);
+       return 0;
 }
 
-void
-_nvkm_fifo_channel_wr32(struct nvkm_object *object, u64 addr, u32 data)
+static int
+nvkm_fifo_chan_wr32(struct nvkm_object *object, u64 addr, u32 data)
 {
-       struct nvkm_fifo_chan *chan = (void *)object;
+       struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
        if (unlikely(!chan->user)) {
                chan->user = ioremap(chan->addr, chan->size);
-               if (WARN_ON_ONCE(chan->user == NULL))
-                       return;
+               if (!chan->user)
+                       return -ENOMEM;
        }
+       if (unlikely(addr + 4 > chan->size))
+               return -EINVAL;
        iowrite32_native(data, chan->user + addr);
+       return 0;
+}
+
+static int
+nvkm_fifo_chan_fini(struct nvkm_object *object, bool suspend)
+{
+       struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
+       chan->func->fini(chan);
+       return 0;
 }
 
-void
-nvkm_fifo_channel_destroy(struct nvkm_fifo_chan *chan)
+static int
+nvkm_fifo_chan_init(struct nvkm_object *object)
 {
-       struct nvkm_fifo *fifo = (void *)nv_object(chan)->engine;
+       struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
+       chan->func->init(chan);
+       return 0;
+}
+
+static void *
+nvkm_fifo_chan_dtor(struct nvkm_object *object)
+{
+       struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
+       struct nvkm_fifo *fifo = chan->fifo;
+       void *data = chan->func->dtor(chan);
        unsigned long flags;
 
+       spin_lock_irqsave(&fifo->lock, flags);
+       if (!list_empty(&chan->head)) {
+               __clear_bit(chan->chid, fifo->mask);
+               list_del(&chan->head);
+       }
+       spin_unlock_irqrestore(&fifo->lock, flags);
+
        if (chan->user)
                iounmap(chan->user);
 
-       spin_lock_irqsave(&fifo->lock, flags);
-       fifo->channel[chan->chid] = NULL;
-       spin_unlock_irqrestore(&fifo->lock, flags);
+       nvkm_vm_ref(NULL, &chan->vm, NULL);
 
-       nvkm_gpuobj_del(&chan->pushgpu);
-       nvkm_namedb_destroy(&chan->namedb);
+       nvkm_gpuobj_del(&chan->push);
+       nvkm_gpuobj_del(&chan->inst);
+       return data;
 }
 
-void
-_nvkm_fifo_channel_dtor(struct nvkm_object *object)
-{
-       struct nvkm_fifo_chan *chan = (void *)object;
-       nvkm_fifo_channel_destroy(chan);
-}
+const struct nvkm_object_func
+nvkm_fifo_chan_func = {
+       .dtor = nvkm_fifo_chan_dtor,
+       .init = nvkm_fifo_chan_init,
+       .fini = nvkm_fifo_chan_fini,
+       .ntfy = nvkm_fifo_chan_ntfy,
+       .map = nvkm_fifo_chan_map,
+       .rd32 = nvkm_fifo_chan_rd32,
+       .wr32 = nvkm_fifo_chan_wr32,
+       .sclass = nvkm_fifo_chan_child_get,
+};
 
 int
-nvkm_fifo_channel_create_(struct nvkm_object *parent,
-                         struct nvkm_object *engine,
-                         struct nvkm_oclass *oclass,
-                         int bar, u32 addr, u32 size, u64 pushbuf,
-                         u64 engmask, int len, void **ptr)
+nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *func,
+                   struct nvkm_fifo *fifo, u32 size, u32 align, bool zero,
+                   u64 vm, u64 push, u64 engines, int bar, u32 base, u32 user,
+                   const struct nvkm_oclass *oclass,
+                   struct nvkm_fifo_chan *chan)
 {
-       struct nvkm_client *client = nvkm_client(parent);
-       struct nvkm_fifo *fifo = (void *)engine;
-       struct nvkm_fifo_base *base = (void *)parent;
-       struct nvkm_fifo_chan *chan;
-       struct nvkm_subdev *subdev = &fifo->engine.subdev;
-       struct nvkm_device *device = subdev->device;
+       struct nvkm_client *client = oclass->client;
+       struct nvkm_device *device = fifo->engine.subdev.device;
+       struct nvkm_mmu *mmu = device->mmu;
        struct nvkm_dmaobj *dmaobj;
        unsigned long flags;
        int ret;
 
-       /* create base object class */
-       ret = nvkm_namedb_create_(parent, engine, oclass, 0, NULL,
-                                 engmask, len, ptr);
-       chan = *ptr;
+       nvkm_object_ctor(&nvkm_fifo_chan_func, oclass, &chan->object);
+       chan->func = func;
+       chan->fifo = fifo;
+       chan->engines = engines;
+       INIT_LIST_HEAD(&chan->head);
+
+       /* instance memory */
+       ret = nvkm_gpuobj_new(device, size, align, zero, NULL, &chan->inst);
        if (ret)
                return ret;
 
-       /* validate dma object representing push buffer */
-       if (pushbuf) {
-               dmaobj = nvkm_dma_search(device->dma, client, pushbuf);
+       /* allocate push buffer ctxdma instance */
+       if (push) {
+               dmaobj = nvkm_dma_search(device->dma, oclass->client, push);
                if (!dmaobj)
                        return -ENOENT;
 
-               ret = nvkm_object_bind(&dmaobj->object, &base->gpuobj, 16,
-                                      &chan->pushgpu);
+               ret = nvkm_object_bind(&dmaobj->object, chan->inst, -16,
+                                      &chan->push);
                if (ret)
                        return ret;
        }
 
-       /* find a free fifo channel */
-       spin_lock_irqsave(&fifo->lock, flags);
-       for (chan->chid = fifo->min; chan->chid < fifo->max; chan->chid++) {
-               if (!fifo->channel[chan->chid]) {
-                       fifo->channel[chan->chid] = nv_object(chan);
-                       break;
+       /* channel address space */
+       if (!vm && mmu) {
+               if (!client->vm || client->vm->mmu == mmu) {
+                       ret = nvkm_vm_ref(client->vm, &chan->vm, NULL);
+                       if (ret)
+                               return ret;
+               } else {
+                       return -EINVAL;
                }
+       } else {
+               return -ENOENT;
        }
-       spin_unlock_irqrestore(&fifo->lock, flags);
 
-       if (chan->chid == fifo->max) {
-               nvkm_error(subdev, "no free channels\n");
+       /* allocate channel id */
+       spin_lock_irqsave(&fifo->lock, flags);
+       chan->chid = find_first_zero_bit(fifo->mask, NVKM_FIFO_CHID_NR);
+       if (chan->chid >= NVKM_FIFO_CHID_NR) {
+               spin_unlock_irqrestore(&fifo->lock, flags);
                return -ENOSPC;
        }
+       list_add(&chan->head, &fifo->chan);
+       __set_bit(chan->chid, fifo->mask);
+       spin_unlock_irqrestore(&fifo->lock, flags);
 
+       /* determine address of this channel's user registers */
        chan->addr = nv_device_resource_start(device, bar) +
-                    addr + size * chan->chid;
-       chan->size = size;
+                    base + user * chan->chid;
+       chan->size = user;
+
        nvkm_event_send(&fifo->cevent, 1, 0, NULL, 0);
        return 0;
 }
index 63209bc8856be652a4da49e1021f1f9a6f73755d..bfec12dbf49293b8e3837b3687fe856650b72140 100644 (file)
@@ -2,27 +2,31 @@
 #define __NVKM_FIFO_CHAN_H__
 #include "priv.h"
 
-#define nvkm_fifo_channel_create(p,e,c,b,a,s,n,m,d)                         \
-       nvkm_fifo_channel_create_((p), (e), (c), (b), (a), (s), (n),        \
-                                    (m), sizeof(**d), (void **)d)
-#define nvkm_fifo_channel_init(p)                                           \
-       nvkm_namedb_init(&(p)->namedb)
-#define nvkm_fifo_channel_fini(p,s)                                         \
-       nvkm_namedb_fini(&(p)->namedb, (s))
+struct nvkm_fifo_chan_func {
+       void *(*dtor)(struct nvkm_fifo_chan *);
+       void (*init)(struct nvkm_fifo_chan *);
+       void (*fini)(struct nvkm_fifo_chan *);
+       int (*ntfy)(struct nvkm_fifo_chan *, u32 type, struct nvkm_event **);
+       int  (*engine_ctor)(struct nvkm_fifo_chan *, struct nvkm_engine *,
+                           struct nvkm_object *);
+       void (*engine_dtor)(struct nvkm_fifo_chan *, struct nvkm_engine *);
+       int  (*engine_init)(struct nvkm_fifo_chan *, struct nvkm_engine *);
+       int  (*engine_fini)(struct nvkm_fifo_chan *, struct nvkm_engine *,
+                           bool suspend);
+       int  (*object_ctor)(struct nvkm_fifo_chan *, struct nvkm_object *);
+       void (*object_dtor)(struct nvkm_fifo_chan *, int);
+};
 
-int  nvkm_fifo_channel_create_(struct nvkm_object *,
-                                 struct nvkm_object *,
-                                 struct nvkm_oclass *,
-                                 int bar, u32 addr, u32 size, u64 push,
-                                 u64 engmask, int len, void **);
-void nvkm_fifo_channel_destroy(struct nvkm_fifo_chan *);
+int nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *, struct nvkm_fifo *,
+                       u32 size, u32 align, bool zero, u64 vm, u64 push,
+                       u64 engines, int bar, u32 base, u32 user,
+                       const struct nvkm_oclass *, struct nvkm_fifo_chan *);
 
-#define _nvkm_fifo_channel_init _nvkm_namedb_init
-#define _nvkm_fifo_channel_fini _nvkm_namedb_fini
+struct nvkm_fifo_chan_oclass {
+       int (*ctor)(struct nvkm_fifo *, const struct nvkm_oclass *,
+                   void *data, u32 size, struct nvkm_object **);
+       struct nvkm_sclass base;
+};
 
-void _nvkm_fifo_channel_dtor(struct nvkm_object *);
-int  _nvkm_fifo_channel_map(struct nvkm_object *, u64 *, u32 *);
-u32  _nvkm_fifo_channel_rd32(struct nvkm_object *, u64);
-void _nvkm_fifo_channel_wr32(struct nvkm_object *, u64, u32);
-int  _nvkm_fifo_channel_ntfy(struct nvkm_object *, u32, struct nvkm_event **);
+int g84_fifo_chan_ntfy(struct nvkm_fifo_chan *, u32, struct nvkm_event **);
 #endif
index f2b4a96f8794039da252e234436dc7e0910c22fd..a7e5dfae383378a3cc2b03f179fed5b46dc2fa2c 100644 (file)
 
 #include <core/client.h>
 #include <core/ramht.h>
+#include <subdev/mmu.h>
 #include <subdev/timer.h>
 
+#include <nvif/class.h>
+
 int
-g84_fifo_context_detach(struct nvkm_object *parent, bool suspend,
-                       struct nvkm_object *object)
+g84_fifo_chan_ntfy(struct nvkm_fifo_chan *chan, u32 type,
+                  struct nvkm_event **pevent)
 {
-       struct nv50_fifo *fifo = (void *)parent->engine;
-       struct nv50_fifo_base *base = (void *)parent->parent;
-       struct nv50_fifo_chan *chan = (void *)parent;
-       struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
-       struct nvkm_device *device = subdev->device;
-       u32 addr, save, engn;
-       bool done;
+       switch (type) {
+       case G82_CHANNEL_DMA_V0_NTFY_UEVENT:
+               *pevent = &chan->fifo->uevent;
+               return 0;
+       default:
+               break;
+       }
+       return -EINVAL;
+}
 
-       switch (nv_engidx(object->engine)) {
-       case NVDEV_ENGINE_SW    : return 0;
-       case NVDEV_ENGINE_GR    : engn = 0; addr = 0x0020; break;
+static int
+g84_fifo_chan_engine(struct nvkm_engine *engine)
+{
+       switch (engine->subdev.index) {
+       case NVDEV_ENGINE_GR    : return 0;
+       case NVDEV_ENGINE_MPEG  :
+       case NVDEV_ENGINE_MSPPP : return 1;
+       case NVDEV_ENGINE_CE0   : return 2;
        case NVDEV_ENGINE_VP    :
-       case NVDEV_ENGINE_MSPDEC: engn = 3; addr = 0x0040; break;
-       case NVDEV_ENGINE_MSPPP :
-       case NVDEV_ENGINE_MPEG  : engn = 1; addr = 0x0060; break;
+       case NVDEV_ENGINE_MSPDEC: return 3;
+       case NVDEV_ENGINE_CIPHER:
+       case NVDEV_ENGINE_SEC   : return 4;
        case NVDEV_ENGINE_BSP   :
-       case NVDEV_ENGINE_MSVLD : engn = 5; addr = 0x0080; break;
+       case NVDEV_ENGINE_MSVLD : return 5;
+       default:
+               WARN_ON(1);
+               return 0;
+       }
+}
+
+static int
+g84_fifo_chan_engine_addr(struct nvkm_engine *engine)
+{
+       switch (engine->subdev.index) {
+       case NVDEV_ENGINE_DMAOBJ:
+       case NVDEV_ENGINE_SW    : return -1;
+       case NVDEV_ENGINE_GR    : return 0x0020;
+       case NVDEV_ENGINE_VP    :
+       case NVDEV_ENGINE_MSPDEC: return 0x0040;
+       case NVDEV_ENGINE_MPEG  :
+       case NVDEV_ENGINE_MSPPP : return 0x0060;
+       case NVDEV_ENGINE_BSP   :
+       case NVDEV_ENGINE_MSVLD : return 0x0080;
        case NVDEV_ENGINE_CIPHER:
-       case NVDEV_ENGINE_SEC   : engn = 4; addr = 0x00a0; break;
-       case NVDEV_ENGINE_CE0   : engn = 2; addr = 0x00c0; break;
+       case NVDEV_ENGINE_SEC   : return 0x00a0;
+       case NVDEV_ENGINE_CE0   : return 0x00c0;
        default:
-               return -EINVAL;
+               WARN_ON(1);
+               return -1;
        }
+}
 
+static int
+g84_fifo_chan_engine_fini(struct nvkm_fifo_chan *base,
+                         struct nvkm_engine *engine, bool suspend)
+{
+       struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
+       struct nv50_fifo *fifo = chan->fifo;
+       struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
+       struct nvkm_device *device = subdev->device;
+       u32 engn, save;
+       int offset;
+       bool done;
+
+       offset = g84_fifo_chan_engine_addr(engine);
+       if (offset < 0)
+               return 0;
+
+       engn = g84_fifo_chan_engine(engine);
        save = nvkm_mask(device, 0x002520, 0x0000003f, 1 << engn);
-       nvkm_wr32(device, 0x0032fc, nv_gpuobj(base)->addr >> 12);
+       nvkm_wr32(device, 0x0032fc, chan->base.inst->addr >> 12);
        done = nvkm_msec(device, 2000,
                if (nvkm_rd32(device, 0x0032fc) != 0xffffffff)
                        break;
@@ -64,168 +112,179 @@ g84_fifo_context_detach(struct nvkm_object *parent, bool suspend,
        nvkm_wr32(device, 0x002520, save);
        if (!done) {
                nvkm_error(subdev, "channel %d [%s] unload timeout\n",
-                          chan->base.chid, nvkm_client_name(chan));
+                          chan->base.chid, chan->base.object.client->name);
                if (suspend)
                        return -EBUSY;
        }
 
-       nvkm_kmap(base->eng);
-       nvkm_wo32(base->eng, addr + 0x00, 0x00000000);
-       nvkm_wo32(base->eng, addr + 0x04, 0x00000000);
-       nvkm_wo32(base->eng, addr + 0x08, 0x00000000);
-       nvkm_wo32(base->eng, addr + 0x0c, 0x00000000);
-       nvkm_wo32(base->eng, addr + 0x10, 0x00000000);
-       nvkm_wo32(base->eng, addr + 0x14, 0x00000000);
-       nvkm_done(base->eng);
+       nvkm_kmap(chan->eng);
+       nvkm_wo32(chan->eng, offset + 0x00, 0x00000000);
+       nvkm_wo32(chan->eng, offset + 0x04, 0x00000000);
+       nvkm_wo32(chan->eng, offset + 0x08, 0x00000000);
+       nvkm_wo32(chan->eng, offset + 0x0c, 0x00000000);
+       nvkm_wo32(chan->eng, offset + 0x10, 0x00000000);
+       nvkm_wo32(chan->eng, offset + 0x14, 0x00000000);
+       nvkm_done(chan->eng);
        return 0;
 }
 
 
 int
-g84_fifo_context_attach(struct nvkm_object *parent, struct nvkm_object *object)
+g84_fifo_chan_engine_init(struct nvkm_fifo_chan *base,
+                         struct nvkm_engine *engine)
 {
-       struct nv50_fifo_base *base = (void *)parent->parent;
-       struct nvkm_gpuobj *ectx = (void *)object;
-       u64 limit = ectx->addr + ectx->size - 1;
-       u64 start = ectx->addr;
-       u32 addr;
-
-       switch (nv_engidx(object->engine)) {
-       case NVDEV_ENGINE_SW    : return 0;
-       case NVDEV_ENGINE_GR    : addr = 0x0020; break;
-       case NVDEV_ENGINE_VP    :
-       case NVDEV_ENGINE_MSPDEC: addr = 0x0040; break;
-       case NVDEV_ENGINE_MSPPP :
-       case NVDEV_ENGINE_MPEG  : addr = 0x0060; break;
-       case NVDEV_ENGINE_BSP   :
-       case NVDEV_ENGINE_MSVLD : addr = 0x0080; break;
-       case NVDEV_ENGINE_CIPHER:
-       case NVDEV_ENGINE_SEC   : addr = 0x00a0; break;
-       case NVDEV_ENGINE_CE0   : addr = 0x00c0; break;
-       default:
-               return -EINVAL;
-       }
+       struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
+       struct nvkm_gpuobj *engn = chan->engn[engine->subdev.index];
+       u64 limit, start;
+       int offset;
 
-       nv_engctx(ectx)->addr = nv_gpuobj(base)->addr >> 12;
-       nvkm_kmap(base->eng);
-       nvkm_wo32(base->eng, addr + 0x00, 0x00190000);
-       nvkm_wo32(base->eng, addr + 0x04, lower_32_bits(limit));
-       nvkm_wo32(base->eng, addr + 0x08, lower_32_bits(start));
-       nvkm_wo32(base->eng, addr + 0x0c, upper_32_bits(limit) << 24 |
-                                         upper_32_bits(start));
-       nvkm_wo32(base->eng, addr + 0x10, 0x00000000);
-       nvkm_wo32(base->eng, addr + 0x14, 0x00000000);
-       nvkm_done(base->eng);
+       offset = g84_fifo_chan_engine_addr(engine);
+       if (offset < 0)
+               return 0;
+       limit = engn->addr + engn->size - 1;
+       start = engn->addr;
+
+       nvkm_kmap(chan->eng);
+       nvkm_wo32(chan->eng, offset + 0x00, 0x00190000);
+       nvkm_wo32(chan->eng, offset + 0x04, lower_32_bits(limit));
+       nvkm_wo32(chan->eng, offset + 0x08, lower_32_bits(start));
+       nvkm_wo32(chan->eng, offset + 0x0c, upper_32_bits(limit) << 24 |
+                                           upper_32_bits(start));
+       nvkm_wo32(chan->eng, offset + 0x10, 0x00000000);
+       nvkm_wo32(chan->eng, offset + 0x14, 0x00000000);
+       nvkm_done(chan->eng);
        return 0;
 }
 
+static int
+g84_fifo_chan_engine_ctor(struct nvkm_fifo_chan *base,
+                         struct nvkm_engine *engine,
+                         struct nvkm_object *object)
+{
+       struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
+       int engn = engine->subdev.index;
+
+       if (g84_fifo_chan_engine_addr(engine) < 0)
+               return 0;
+
+       if (nv_iclass(object, NV_GPUOBJ_CLASS)) {
+               chan->engn[engn] = nv_gpuobj(object);
+               return 0;
+       }
+
+       return nvkm_object_bind(object, NULL, 0, &chan->engn[engn]);
+}
+
 int
-g84_fifo_object_attach(struct nvkm_object *parent,
-                      struct nvkm_object *object, u32 handle)
+g84_fifo_chan_object_ctor(struct nvkm_fifo_chan *base,
+                         struct nvkm_object *object)
 {
-       struct nv50_fifo_chan *chan = (void *)parent;
+       struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
+       u32 handle = object->handle;
        u32 context;
 
-       if (nv_iclass(object, NV_GPUOBJ_CLASS))
-               context = nv_gpuobj(object)->node->offset >> 4;
-       else
-               context = 0x00000004; /* just non-zero */
-
-       if (object->engine) {
-               switch (nv_engidx(object->engine)) {
-               case NVDEV_ENGINE_DMAOBJ:
-               case NVDEV_ENGINE_SW    : context |= 0x00000000; break;
-               case NVDEV_ENGINE_GR    : context |= 0x00100000; break;
-               case NVDEV_ENGINE_MPEG  :
-               case NVDEV_ENGINE_MSPPP : context |= 0x00200000; break;
-               case NVDEV_ENGINE_ME    :
-               case NVDEV_ENGINE_CE0   : context |= 0x00300000; break;
-               case NVDEV_ENGINE_VP    :
-               case NVDEV_ENGINE_MSPDEC: context |= 0x00400000; break;
-               case NVDEV_ENGINE_CIPHER:
-               case NVDEV_ENGINE_SEC   :
-               case NVDEV_ENGINE_VIC   : context |= 0x00500000; break;
-               case NVDEV_ENGINE_BSP   :
-               case NVDEV_ENGINE_MSVLD : context |= 0x00600000; break;
-               default:
-                       return -EINVAL;
-               }
+       switch (object->engine->subdev.index) {
+       case NVDEV_ENGINE_DMAOBJ:
+       case NVDEV_ENGINE_SW    : context = 0x00000000; break;
+       case NVDEV_ENGINE_GR    : context = 0x00100000; break;
+       case NVDEV_ENGINE_MPEG  :
+       case NVDEV_ENGINE_MSPPP : context = 0x00200000; break;
+       case NVDEV_ENGINE_ME    :
+       case NVDEV_ENGINE_CE0   : context = 0x00300000; break;
+       case NVDEV_ENGINE_VP    :
+       case NVDEV_ENGINE_MSPDEC: context = 0x00400000; break;
+       case NVDEV_ENGINE_CIPHER:
+       case NVDEV_ENGINE_SEC   :
+       case NVDEV_ENGINE_VIC   : context = 0x00500000; break;
+       case NVDEV_ENGINE_BSP   :
+       case NVDEV_ENGINE_MSVLD : context = 0x00600000; break;
+       default:
+               WARN_ON(1);
+               return -EINVAL;
        }
 
-       return nvkm_ramht_insert(chan->ramht, NULL, 0, 0, handle, context);
+       return nvkm_ramht_insert(chan->ramht, object, 0, 4, handle, context);
 }
 
-int
-g84_fifo_chan_init(struct nvkm_object *object)
+static void
+g84_fifo_chan_init(struct nvkm_fifo_chan *base)
 {
-       struct nv50_fifo *fifo = (void *)object->engine;
-       struct nv50_fifo_base *base = (void *)object->parent;
-       struct nv50_fifo_chan *chan = (void *)object;
-       struct nvkm_gpuobj *ramfc = base->ramfc;
+       struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
+       struct nv50_fifo *fifo = chan->fifo;
        struct nvkm_device *device = fifo->base.engine.subdev.device;
+       u64 addr = chan->ramfc->addr >> 8;
        u32 chid = chan->base.chid;
-       int ret;
-
-       ret = nvkm_fifo_channel_init(&chan->base);
-       if (ret)
-               return ret;
 
-       nvkm_wr32(device, 0x002600 + (chid * 4), 0x80000000 | ramfc->addr >> 8);
+       nvkm_wr32(device, 0x002600 + (chid * 4), 0x80000000 | addr);
        nv50_fifo_runlist_update(fifo);
-       return 0;
 }
 
-static int
-g84_fifo_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-                     struct nvkm_oclass *oclass, void *data, u32 size,
-                     struct nvkm_object **pobject)
+static const struct nvkm_fifo_chan_func
+g84_fifo_chan_func = {
+       .dtor = nv50_fifo_chan_dtor,
+       .init = g84_fifo_chan_init,
+       .fini = nv50_fifo_chan_fini,
+       .ntfy = g84_fifo_chan_ntfy,
+       .engine_ctor = g84_fifo_chan_engine_ctor,
+       .engine_dtor = nv50_fifo_chan_engine_dtor,
+       .engine_init = g84_fifo_chan_engine_init,
+       .engine_fini = g84_fifo_chan_engine_fini,
+       .object_ctor = g84_fifo_chan_object_ctor,
+       .object_dtor = nv50_fifo_chan_object_dtor,
+};
+
+int
+g84_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vm, u64 push,
+                  const struct nvkm_oclass *oclass,
+                  struct nv50_fifo_chan *chan)
 {
-       struct nvkm_device *device = nv_engine(engine)->subdev.device;
-       struct nv50_fifo_base *base;
+       struct nvkm_device *device = fifo->base.engine.subdev.device;
        int ret;
 
-       ret = nvkm_fifo_context_create(parent, engine, oclass, NULL, 0x10000,
-                                      0x1000, NVOBJ_FLAG_HEAP, &base);
-       *pobject = nv_object(base);
+       ret = nvkm_fifo_chan_ctor(&g84_fifo_chan_func, &fifo->base,
+                                 0x10000, 0x1000, false, vm, push,
+                                 (1ULL << NVDEV_ENGINE_BSP) |
+                                 (1ULL << NVDEV_ENGINE_CE0) |
+                                 (1ULL << NVDEV_ENGINE_CIPHER) |
+                                 (1ULL << NVDEV_ENGINE_DMAOBJ) |
+                                 (1ULL << NVDEV_ENGINE_GR) |
+                                 (1ULL << NVDEV_ENGINE_ME) |
+                                 (1ULL << NVDEV_ENGINE_MPEG) |
+                                 (1ULL << NVDEV_ENGINE_MSPDEC) |
+                                 (1ULL << NVDEV_ENGINE_MSPPP) |
+                                 (1ULL << NVDEV_ENGINE_MSVLD) |
+                                 (1ULL << NVDEV_ENGINE_SEC) |
+                                 (1ULL << NVDEV_ENGINE_SW) |
+                                 (1ULL << NVDEV_ENGINE_VIC) |
+                                 (1ULL << NVDEV_ENGINE_VP),
+                                 0, 0xc00000, 0x2000, oclass, &chan->base);
+       chan->fifo = fifo;
        if (ret)
                return ret;
 
-       ret = nvkm_gpuobj_new(device, 0x0200, 0, true, &base->base.gpuobj,
-                             &base->eng);
+       ret = nvkm_gpuobj_new(device, 0x0200, 0, true, chan->base.inst,
+                             &chan->eng);
        if (ret)
                return ret;
 
-       ret = nvkm_gpuobj_new(device, 0x4000, 0, false, &base->base.gpuobj,
-                             &base->pgd);
+       ret = nvkm_gpuobj_new(device, 0x4000, 0, false, chan->base.inst,
+                             &chan->pgd);
        if (ret)
                return ret;
 
-       ret = nvkm_vm_ref(nvkm_client(parent)->vm, &base->vm, base->pgd);
+       ret = nvkm_gpuobj_new(device, 0x1000, 0x400, true, chan->base.inst,
+                             &chan->cache);
        if (ret)
                return ret;
 
-       ret = nvkm_gpuobj_new(device, 0x1000, 0x400, true, &base->base.gpuobj,
-                             &base->cache);
+       ret = nvkm_gpuobj_new(device, 0x100, 0x100, true, chan->base.inst,
+                             &chan->ramfc);
        if (ret)
                return ret;
 
-       ret = nvkm_gpuobj_new(device, 0x100, 0x100, true, &base->base.gpuobj,
-                             &base->ramfc);
+       ret = nvkm_ramht_new(device, 0x8000, 16, chan->base.inst, &chan->ramht);
        if (ret)
                return ret;
 
-       return 0;
+       return nvkm_vm_ref(chan->base.vm, &chan->vm, chan->pgd);
 }
-
-struct nvkm_oclass
-g84_fifo_cclass = {
-       .handle = NV_ENGCTX(FIFO, 0x84),
-       .ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = g84_fifo_context_ctor,
-               .dtor = nv50_fifo_context_dtor,
-               .init = _nvkm_fifo_context_init,
-               .fini = _nvkm_fifo_context_fini,
-               .rd32 = _nvkm_fifo_context_rd32,
-               .wr32 = _nvkm_fifo_context_wr32,
-       },
-};
index 99324222dadec4266590ffa6b52b2e8b1ea43455..413288597e04c9a1b95db5a13906ec2b178e1b1e 100644 (file)
@@ -1,23 +1,24 @@
 #ifndef __GF100_FIFO_CHAN_H__
 #define __GF100_FIFO_CHAN_H__
+#define gf100_fifo_chan(p) container_of((p), struct gf100_fifo_chan, base)
 #include "chan.h"
 #include "gf100.h"
 
-struct gf100_fifo_base {
-       struct nvkm_fifo_base base;
+struct gf100_fifo_chan {
+       struct nvkm_fifo_chan base;
+       struct gf100_fifo *fifo;
+
+       struct list_head head;
+       bool killed;
+
        struct nvkm_gpuobj *pgd;
        struct nvkm_vm *vm;
-};
 
-struct gf100_fifo_chan {
-       struct nvkm_fifo_chan base;
-       enum {
-               STOPPED,
-               RUNNING,
-               KILLED
-       } state;
+       struct {
+               struct nvkm_gpuobj *inst;
+               struct nvkm_vma vma;
+       } engn[NVDEV_SUBDEV_NR];
 };
 
-extern struct nvkm_oclass gf100_fifo_cclass;
-extern struct nvkm_oclass gf100_fifo_sclass[];
+extern const struct nvkm_fifo_chan_oclass gf100_fifo_gpfifo_oclass;
 #endif
index 3490cb6d8bd3eaa6fd6bd9b2bf9460558c1e2e43..2b9d8bfc7fd7e86ecf59748e9522f7c320ace13f 100644 (file)
@@ -1,27 +1,29 @@
 #ifndef __GK104_FIFO_CHAN_H__
 #define __GK104_FIFO_CHAN_H__
+#define gk104_fifo_chan(p) container_of((p), struct gk104_fifo_chan, base)
 #include "chan.h"
 #include "gk104.h"
 
-struct gk104_fifo_base {
-       struct nvkm_fifo_base base;
+struct gk104_fifo_chan {
+       struct nvkm_fifo_chan base;
+       struct gk104_fifo *fifo;
+       int engine;
+
+       struct list_head head;
+       bool killed;
+
        struct nvkm_gpuobj *pgd;
        struct nvkm_vm *vm;
-};
 
-struct gk104_fifo_chan {
-       struct nvkm_fifo_chan base;
-       u32 engine;
-       enum {
-               STOPPED,
-               RUNNING,
-               KILLED
-       } state;
+       struct {
+               struct nvkm_gpuobj *inst;
+               struct nvkm_vma vma;
+       } engn[NVDEV_SUBDEV_NR];
 };
 
-extern struct nvkm_oclass gk104_fifo_cclass;
-extern struct nvkm_oclass gk104_fifo_sclass[];
-extern struct nvkm_ofuncs gk104_fifo_chan_ofuncs;
+int gk104_fifo_gpfifo_new(struct nvkm_fifo *, const struct nvkm_oclass *,
+                         void *data, u32 size, struct nvkm_object **);
 
-extern struct nvkm_oclass gm204_fifo_sclass[];
+extern const struct nvkm_fifo_chan_oclass gk104_fifo_gpfifo_oclass;
+extern const struct nvkm_fifo_chan_oclass gm204_fifo_gpfifo_oclass;
 #endif
index 028212df41bcd106372ed559c9cd40afa2bbc04d..ac62a6404f87317f27ac5106d8fbf23d905a3bcb 100644 (file)
@@ -1,24 +1,24 @@
 #ifndef __NV04_FIFO_CHAN_H__
 #define __NV04_FIFO_CHAN_H__
+#define nv04_fifo_chan(p) container_of((p), struct nv04_fifo_chan, base)
 #include "chan.h"
 #include "nv04.h"
 
 struct nv04_fifo_chan {
        struct nvkm_fifo_chan base;
-       u32 subc[8];
+       struct nv04_fifo *fifo;
        u32 ramfc;
+       struct nvkm_gpuobj *engn[NVDEV_SUBDEV_NR];
 };
 
-int  nv04_fifo_object_attach(struct nvkm_object *, struct nvkm_object *, u32);
-void nv04_fifo_object_detach(struct nvkm_object *, int);
+extern const struct nvkm_fifo_chan_func nv04_fifo_dma_func;
+void *nv04_fifo_dma_dtor(struct nvkm_fifo_chan *);
+void nv04_fifo_dma_init(struct nvkm_fifo_chan *);
+void nv04_fifo_dma_fini(struct nvkm_fifo_chan *);
+void nv04_fifo_dma_object_dtor(struct nvkm_fifo_chan *, int);
 
-void nv04_fifo_chan_dtor(struct nvkm_object *);
-int  nv04_fifo_chan_init(struct nvkm_object *);
-int  nv04_fifo_chan_fini(struct nvkm_object *, bool suspend);
-
-extern struct nvkm_oclass nv04_fifo_cclass;
-extern struct nvkm_oclass nv04_fifo_sclass[];
-extern struct nvkm_oclass nv10_fifo_sclass[];
-extern struct nvkm_oclass nv17_fifo_sclass[];
-extern struct nvkm_oclass nv40_fifo_sclass[];
+extern const struct nvkm_fifo_chan_oclass nv04_fifo_dma_oclass;
+extern const struct nvkm_fifo_chan_oclass nv10_fifo_dma_oclass;
+extern const struct nvkm_fifo_chan_oclass nv17_fifo_dma_oclass;
+extern const struct nvkm_fifo_chan_oclass nv40_fifo_dma_oclass;
 #endif
index aeaba7b9bcae6c3af89a8415fbab97bf6e7713f7..2a25019ce0f4740342291adee2bee9ead350ada3 100644 (file)
 
 #include <core/client.h>
 #include <core/ramht.h>
+#include <subdev/mmu.h>
 #include <subdev/timer.h>
 
-int
-nv50_fifo_context_detach(struct nvkm_object *parent, bool suspend,
-                        struct nvkm_object *object)
+static int
+nv50_fifo_chan_engine_addr(struct nvkm_engine *engine)
 {
-       struct nv50_fifo *fifo = (void *)parent->engine;
-       struct nv50_fifo_base *base = (void *)parent->parent;
-       struct nv50_fifo_chan *chan = (void *)parent;
+       switch (engine->subdev.index) {
+       case NVDEV_ENGINE_DMAOBJ:
+       case NVDEV_ENGINE_SW    : return -1;
+       case NVDEV_ENGINE_GR    : return 0x0000;
+       case NVDEV_ENGINE_MPEG  : return 0x0060;
+       default:
+               WARN_ON(1);
+               return -1;
+       }
+}
+
+static int
+nv50_fifo_chan_engine_fini(struct nvkm_fifo_chan *base,
+                          struct nvkm_engine *engine, bool suspend)
+{
+       struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
+       struct nv50_fifo *fifo = chan->fifo;
        struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
        struct nvkm_device *device = subdev->device;
-       u32 addr, me;
-       int ret = 0;
+       int offset, ret = 0;
+       u32 me;
 
-       switch (nv_engidx(object->engine)) {
-       case NVDEV_ENGINE_SW   : return 0;
-       case NVDEV_ENGINE_GR   : addr = 0x0000; break;
-       case NVDEV_ENGINE_MPEG : addr = 0x0060; break;
-       default:
-               return -EINVAL;
-       }
+       offset = nv50_fifo_chan_engine_addr(engine);
+       if (offset < 0)
+               return 0;
 
        /* HW bug workaround:
         *
@@ -62,101 +72,124 @@ nv50_fifo_context_detach(struct nvkm_object *parent, bool suspend,
        me = nvkm_mask(device, 0x00b860, 0x00000001, 0x00000001);
 
        /* do the kickoff... */
-       nvkm_wr32(device, 0x0032fc, nv_gpuobj(base)->addr >> 12);
+       nvkm_wr32(device, 0x0032fc, chan->base.inst->addr >> 12);
        if (nvkm_msec(device, 2000,
                if (nvkm_rd32(device, 0x0032fc) != 0xffffffff)
                        break;
        ) < 0) {
                nvkm_error(subdev, "channel %d [%s] unload timeout\n",
-                          chan->base.chid, nvkm_client_name(chan));
+                          chan->base.chid, chan->base.object.client->name);
                if (suspend)
                        ret = -EBUSY;
        }
        nvkm_wr32(device, 0x00b860, me);
 
        if (ret == 0) {
-               nvkm_kmap(base->eng);
-               nvkm_wo32(base->eng, addr + 0x00, 0x00000000);
-               nvkm_wo32(base->eng, addr + 0x04, 0x00000000);
-               nvkm_wo32(base->eng, addr + 0x08, 0x00000000);
-               nvkm_wo32(base->eng, addr + 0x0c, 0x00000000);
-               nvkm_wo32(base->eng, addr + 0x10, 0x00000000);
-               nvkm_wo32(base->eng, addr + 0x14, 0x00000000);
-               nvkm_done(base->eng);
+               nvkm_kmap(chan->eng);
+               nvkm_wo32(chan->eng, offset + 0x00, 0x00000000);
+               nvkm_wo32(chan->eng, offset + 0x04, 0x00000000);
+               nvkm_wo32(chan->eng, offset + 0x08, 0x00000000);
+               nvkm_wo32(chan->eng, offset + 0x0c, 0x00000000);
+               nvkm_wo32(chan->eng, offset + 0x10, 0x00000000);
+               nvkm_wo32(chan->eng, offset + 0x14, 0x00000000);
+               nvkm_done(chan->eng);
        }
 
        return ret;
 }
 
-int
-nv50_fifo_context_attach(struct nvkm_object *parent, struct nvkm_object *object)
+static int
+nv50_fifo_chan_engine_init(struct nvkm_fifo_chan *base,
+                          struct nvkm_engine *engine)
 {
-       struct nv50_fifo_base *base = (void *)parent->parent;
-       struct nvkm_gpuobj *ectx = (void *)object;
-       u64 limit = ectx->addr + ectx->size - 1;
-       u64 start = ectx->addr;
-       u32 addr;
-
-       switch (nv_engidx(object->engine)) {
-       case NVDEV_ENGINE_SW   : return 0;
-       case NVDEV_ENGINE_GR   : addr = 0x0000; break;
-       case NVDEV_ENGINE_MPEG : addr = 0x0060; break;
-       default:
-               return -EINVAL;
+       struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
+       struct nvkm_gpuobj *engn = chan->engn[engine->subdev.index];
+       u64 limit, start;
+       int offset;
+
+       offset = nv50_fifo_chan_engine_addr(engine);
+       if (offset < 0)
+               return 0;
+       limit = engn->addr + engn->size - 1;
+       start = engn->addr;
+
+       nvkm_kmap(chan->eng);
+       nvkm_wo32(chan->eng, offset + 0x00, 0x00190000);
+       nvkm_wo32(chan->eng, offset + 0x04, lower_32_bits(limit));
+       nvkm_wo32(chan->eng, offset + 0x08, lower_32_bits(start));
+       nvkm_wo32(chan->eng, offset + 0x0c, upper_32_bits(limit) << 24 |
+                                           upper_32_bits(start));
+       nvkm_wo32(chan->eng, offset + 0x10, 0x00000000);
+       nvkm_wo32(chan->eng, offset + 0x14, 0x00000000);
+       nvkm_done(chan->eng);
+       return 0;
+}
+
+void
+nv50_fifo_chan_engine_dtor(struct nvkm_fifo_chan *base,
+                          struct nvkm_engine *engine)
+{
+       struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
+       if (!chan->engn[engine->subdev.index] ||
+            chan->engn[engine->subdev.index]->object.oclass) {
+               chan->engn[engine->subdev.index] = NULL;
+               return;
        }
+       nvkm_gpuobj_del(&chan->engn[engine->subdev.index]);
+}
 
-       nv_engctx(ectx)->addr = nv_gpuobj(base)->addr >> 12;
-
-       nvkm_kmap(base->eng);
-       nvkm_wo32(base->eng, addr + 0x00, 0x00190000);
-       nvkm_wo32(base->eng, addr + 0x04, lower_32_bits(limit));
-       nvkm_wo32(base->eng, addr + 0x08, lower_32_bits(start));
-       nvkm_wo32(base->eng, addr + 0x0c, upper_32_bits(limit) << 24 |
-                                         upper_32_bits(start));
-       nvkm_wo32(base->eng, addr + 0x10, 0x00000000);
-       nvkm_wo32(base->eng, addr + 0x14, 0x00000000);
-       nvkm_done(base->eng);
-       return 0;
+static int
+nv50_fifo_chan_engine_ctor(struct nvkm_fifo_chan *base,
+                          struct nvkm_engine *engine,
+                          struct nvkm_object *object)
+{
+       struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
+       int engn = engine->subdev.index;
+
+       if (nv50_fifo_chan_engine_addr(engine) < 0)
+               return 0;
+
+       if (nv_iclass(object, NV_GPUOBJ_CLASS)) {
+               chan->engn[engn] = nv_gpuobj(object);
+               return 0;
+       }
+
+       return nvkm_object_bind(object, NULL, 0, &chan->engn[engn]);
 }
 
 void
-nv50_fifo_object_detach(struct nvkm_object *parent, int cookie)
+nv50_fifo_chan_object_dtor(struct nvkm_fifo_chan *base, int cookie)
 {
-       struct nv50_fifo_chan *chan = (void *)parent;
+       struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
        nvkm_ramht_remove(chan->ramht, cookie);
 }
 
-int
-nv50_fifo_object_attach(struct nvkm_object *parent,
-                       struct nvkm_object *object, u32 handle)
+static int
+nv50_fifo_chan_object_ctor(struct nvkm_fifo_chan *base,
+                          struct nvkm_object *object)
 {
-       struct nv50_fifo_chan *chan = (void *)parent;
+       struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
+       u32 handle = object->handle;
        u32 context;
 
-       if (nv_iclass(object, NV_GPUOBJ_CLASS))
-               context = nv_gpuobj(object)->node->offset >> 4;
-       else
-               context = 0x00000004; /* just non-zero */
-
-       if (object->engine) {
-               switch (nv_engidx(object->engine)) {
-               case NVDEV_ENGINE_DMAOBJ:
-               case NVDEV_ENGINE_SW    : context |= 0x00000000; break;
-               case NVDEV_ENGINE_GR    : context |= 0x00100000; break;
-               case NVDEV_ENGINE_MPEG  : context |= 0x00200000; break;
-               default:
-                       return -EINVAL;
-               }
+       switch (object->engine->subdev.index) {
+       case NVDEV_ENGINE_DMAOBJ:
+       case NVDEV_ENGINE_SW    : context = 0x00000000; break;
+       case NVDEV_ENGINE_GR    : context = 0x00100000; break;
+       case NVDEV_ENGINE_MPEG  : context = 0x00200000; break;
+       default:
+               WARN_ON(1);
+               return -EINVAL;
        }
 
-       return nvkm_ramht_insert(chan->ramht, NULL, 0, 0, handle, context);
+       return nvkm_ramht_insert(chan->ramht, object, 0, 4, handle, context);
 }
 
-int
-nv50_fifo_chan_fini(struct nvkm_object *object, bool suspend)
+void
+nv50_fifo_chan_fini(struct nvkm_fifo_chan *base)
 {
-       struct nv50_fifo *fifo = (void *)object->engine;
-       struct nv50_fifo_chan *chan = (void *)object;
+       struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
+       struct nv50_fifo *fifo = chan->fifo;
        struct nvkm_device *device = fifo->base.engine.subdev.device;
        u32 chid = chan->base.chid;
 
@@ -164,96 +197,84 @@ nv50_fifo_chan_fini(struct nvkm_object *object, bool suspend)
        nvkm_mask(device, 0x002600 + (chid * 4), 0x80000000, 0x00000000);
        nv50_fifo_runlist_update(fifo);
        nvkm_wr32(device, 0x002600 + (chid * 4), 0x00000000);
-
-       return nvkm_fifo_channel_fini(&chan->base, suspend);
 }
 
-int
-nv50_fifo_chan_init(struct nvkm_object *object)
+static void
+nv50_fifo_chan_init(struct nvkm_fifo_chan *base)
 {
-       struct nv50_fifo *fifo = (void *)object->engine;
-       struct nv50_fifo_base *base = (void *)object->parent;
-       struct nv50_fifo_chan *chan = (void *)object;
-       struct nvkm_gpuobj *ramfc = base->ramfc;
+       struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
+       struct nv50_fifo *fifo = chan->fifo;
        struct nvkm_device *device = fifo->base.engine.subdev.device;
+       u64 addr = chan->ramfc->addr >> 12;
        u32 chid = chan->base.chid;
-       int ret;
-
-       ret = nvkm_fifo_channel_init(&chan->base);
-       if (ret)
-               return ret;
 
-       nvkm_wr32(device, 0x002600 + (chid * 4), 0x80000000 | ramfc->addr >> 12);
+       nvkm_wr32(device, 0x002600 + (chid * 4), 0x80000000 | addr);
        nv50_fifo_runlist_update(fifo);
-       return 0;
 }
 
-void
-nv50_fifo_chan_dtor(struct nvkm_object *object)
+void *
+nv50_fifo_chan_dtor(struct nvkm_fifo_chan *base)
 {
-       struct nv50_fifo_chan *chan = (void *)object;
+       struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
+       nvkm_vm_ref(NULL, &chan->vm, chan->pgd);
        nvkm_ramht_del(&chan->ramht);
-       nvkm_fifo_channel_destroy(&chan->base);
+       nvkm_gpuobj_del(&chan->pgd);
+       nvkm_gpuobj_del(&chan->eng);
+       nvkm_gpuobj_del(&chan->cache);
+       nvkm_gpuobj_del(&chan->ramfc);
+       return chan;
 }
 
-void
-nv50_fifo_context_dtor(struct nvkm_object *object)
-{
-       struct nv50_fifo_base *base = (void *)object;
-       nvkm_vm_ref(NULL, &base->vm, base->pgd);
-       nvkm_gpuobj_del(&base->pgd);
-       nvkm_gpuobj_del(&base->eng);
-       nvkm_gpuobj_del(&base->ramfc);
-       nvkm_gpuobj_del(&base->cache);
-       nvkm_fifo_context_destroy(&base->base);
-}
+static const struct nvkm_fifo_chan_func
+nv50_fifo_chan_func = {
+       .dtor = nv50_fifo_chan_dtor,
+       .init = nv50_fifo_chan_init,
+       .fini = nv50_fifo_chan_fini,
+       .engine_ctor = nv50_fifo_chan_engine_ctor,
+       .engine_dtor = nv50_fifo_chan_engine_dtor,
+       .engine_init = nv50_fifo_chan_engine_init,
+       .engine_fini = nv50_fifo_chan_engine_fini,
+       .object_ctor = nv50_fifo_chan_object_ctor,
+       .object_dtor = nv50_fifo_chan_object_dtor,
+};
 
-static int
-nv50_fifo_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-                      struct nvkm_oclass *oclass, void *data, u32 size,
-                      struct nvkm_object **pobject)
+int
+nv50_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vm, u64 push,
+                   const struct nvkm_oclass *oclass,
+                   struct nv50_fifo_chan *chan)
 {
-       struct nvkm_device *device = nv_engine(engine)->subdev.device;
-       struct nv50_fifo_base *base;
+       struct nvkm_device *device = fifo->base.engine.subdev.device;
        int ret;
 
-       ret = nvkm_fifo_context_create(parent, engine, oclass, NULL, 0x10000,
-                                      0x1000, NVOBJ_FLAG_HEAP, &base);
-       *pobject = nv_object(base);
+       ret = nvkm_fifo_chan_ctor(&nv50_fifo_chan_func, &fifo->base,
+                                 0x10000, 0x1000, false, vm, push,
+                                 (1ULL << NVDEV_ENGINE_DMAOBJ) |
+                                 (1ULL << NVDEV_ENGINE_SW) |
+                                 (1ULL << NVDEV_ENGINE_GR) |
+                                 (1ULL << NVDEV_ENGINE_MPEG),
+                                 0, 0xc00000, 0x2000, oclass, &chan->base);
+       chan->fifo = fifo;
        if (ret)
                return ret;
 
-       ret = nvkm_gpuobj_new(device, 0x0200, 0x1000, true, &base->base.gpuobj,
-                             &base->ramfc);
+       ret = nvkm_gpuobj_new(device, 0x0200, 0x1000, true, chan->base.inst,
+                             &chan->ramfc);
        if (ret)
                return ret;
 
-       ret = nvkm_gpuobj_new(device, 0x1200, 0, true, &base->base.gpuobj,
-                             &base->eng);
+       ret = nvkm_gpuobj_new(device, 0x1200, 0, true, chan->base.inst,
+                             &chan->eng);
        if (ret)
                return ret;
 
-       ret = nvkm_gpuobj_new(device, 0x4000, 0, false, &base->base.gpuobj,
-                             &base->pgd);
+       ret = nvkm_gpuobj_new(device, 0x4000, 0, false, chan->base.inst,
+                             &chan->pgd);
        if (ret)
                return ret;
 
-       ret = nvkm_vm_ref(nvkm_client(parent)->vm, &base->vm, base->pgd);
+       ret = nvkm_ramht_new(device, 0x8000, 16, chan->base.inst, &chan->ramht);
        if (ret)
                return ret;
 
-       return 0;
+       return nvkm_vm_ref(chan->base.vm, &chan->vm, chan->pgd);
 }
-
-struct nvkm_oclass
-nv50_fifo_cclass = {
-       .handle = NV_ENGCTX(FIFO, 0x50),
-       .ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = nv50_fifo_context_ctor,
-               .dtor = nv50_fifo_context_dtor,
-               .init = _nvkm_fifo_context_init,
-               .fini = _nvkm_fifo_context_fini,
-               .rd32 = _nvkm_fifo_context_rd32,
-               .wr32 = _nvkm_fifo_context_wr32,
-       },
-};
index c4f2f1ff4c9e9a3eb5061fedd30705b45bd41eb3..7ef6bc2e27ecf43d2fee7a663693f6e5ebd37e7a 100644 (file)
@@ -1,42 +1,35 @@
 #ifndef __NV50_FIFO_CHAN_H__
 #define __NV50_FIFO_CHAN_H__
+#define nv50_fifo_chan(p) container_of((p), struct nv50_fifo_chan, base)
 #include "chan.h"
 #include "nv50.h"
 
-struct nv50_fifo_base {
-       struct nvkm_fifo_base base;
+struct nv50_fifo_chan {
+       struct nv50_fifo *fifo;
+       struct nvkm_fifo_chan base;
+
        struct nvkm_gpuobj *ramfc;
        struct nvkm_gpuobj *cache;
        struct nvkm_gpuobj *eng;
        struct nvkm_gpuobj *pgd;
+       struct nvkm_ramht *ramht;
        struct nvkm_vm *vm;
-};
 
-struct nv50_fifo_chan {
-       struct nvkm_fifo_chan base;
-       u32 subc[8];
-       struct nvkm_ramht *ramht;
+       struct nvkm_gpuobj *engn[NVDEV_SUBDEV_NR];
 };
 
-extern struct nvkm_oclass nv50_fifo_cclass;
-extern struct nvkm_oclass nv50_fifo_sclass[];
-void nv50_fifo_context_dtor(struct nvkm_object *);
-void nv50_fifo_chan_dtor(struct nvkm_object *);
-int  nv50_fifo_chan_init(struct nvkm_object *);
-int  nv50_fifo_chan_fini(struct nvkm_object *, bool);
-int  nv50_fifo_context_attach(struct nvkm_object *, struct nvkm_object *);
-int  nv50_fifo_context_detach(struct nvkm_object *, bool,
-                             struct nvkm_object *);
-int  nv50_fifo_object_attach(struct nvkm_object *, struct nvkm_object *, u32);
-void nv50_fifo_object_detach(struct nvkm_object *, int);
-extern struct nvkm_ofuncs nv50_fifo_ofuncs_ind;
+int nv50_fifo_chan_ctor(struct nv50_fifo *, u64 vm, u64 push,
+                       const struct nvkm_oclass *, struct nv50_fifo_chan *);
+void *nv50_fifo_chan_dtor(struct nvkm_fifo_chan *);
+void nv50_fifo_chan_fini(struct nvkm_fifo_chan *);
+void nv50_fifo_chan_engine_dtor(struct nvkm_fifo_chan *, struct nvkm_engine *);
+void nv50_fifo_chan_object_dtor(struct nvkm_fifo_chan *, int);
+
+int g84_fifo_chan_ctor(struct nv50_fifo *, u64 vm, u64 push,
+                      const struct nvkm_oclass *, struct nv50_fifo_chan *);
 
-extern struct nvkm_oclass g84_fifo_cclass;
-extern struct nvkm_oclass g84_fifo_sclass[];
-int  g84_fifo_chan_init(struct nvkm_object *);
-int  g84_fifo_context_attach(struct nvkm_object *, struct nvkm_object *);
-int  g84_fifo_context_detach(struct nvkm_object *, bool,
-                            struct nvkm_object *);
-int  g84_fifo_object_attach(struct nvkm_object *, struct nvkm_object *, u32);
-extern struct nvkm_ofuncs g84_fifo_ofuncs_ind;
+extern const struct nvkm_fifo_chan_oclass nv50_fifo_dma_oclass;
+extern const struct nvkm_fifo_chan_oclass nv50_fifo_gpfifo_oclass;
+extern const struct nvkm_fifo_chan_oclass g84_fifo_dma_oclass;
+extern const struct nvkm_fifo_chan_oclass g84_fifo_gpfifo_oclass;
 #endif
index 2016a9884b38cc6e90324866d20207553ee7208e..a5ca52c7b74ffdebb92bd850785ab762bbaa1411 100644 (file)
 #include <nvif/unpack.h>
 
 static int
-g84_fifo_chan_ctor_dma(struct nvkm_object *parent, struct nvkm_object *engine,
-                      struct nvkm_oclass *oclass, void *data, u32 size,
-                      struct nvkm_object **pobject)
+g84_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
+                void *data, u32 size, struct nvkm_object **pobject)
 {
+       struct nvkm_object *parent = oclass->parent;
        union {
                struct nv50_channel_dma_v0 v0;
        } *args = data;
-       struct nvkm_device *device = parent->engine->subdev.device;
-       struct nv50_fifo_base *base = (void *)parent;
+       struct nv50_fifo *fifo = nv50_fifo(base);
        struct nv50_fifo_chan *chan;
        int ret;
 
@@ -48,80 +47,47 @@ g84_fifo_chan_ctor_dma(struct nvkm_object *parent, struct nvkm_object *engine,
                                   "pushbuf %llx offset %016llx\n",
                           args->v0.version, args->v0.vm, args->v0.pushbuf,
                           args->v0.offset);
-               if (args->v0.vm)
-                       return -ENOENT;
+               if (!args->v0.pushbuf)
+                       return -EINVAL;
        } else
                return ret;
 
-       ret = nvkm_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
-                                      0x2000, args->v0.pushbuf,
-                                      (1ULL << NVDEV_ENGINE_DMAOBJ) |
-                                      (1ULL << NVDEV_ENGINE_SW) |
-                                      (1ULL << NVDEV_ENGINE_GR) |
-                                      (1ULL << NVDEV_ENGINE_MPEG) |
-                                      (1ULL << NVDEV_ENGINE_ME) |
-                                      (1ULL << NVDEV_ENGINE_VP) |
-                                      (1ULL << NVDEV_ENGINE_CIPHER) |
-                                      (1ULL << NVDEV_ENGINE_SEC) |
-                                      (1ULL << NVDEV_ENGINE_BSP) |
-                                      (1ULL << NVDEV_ENGINE_MSVLD) |
-                                      (1ULL << NVDEV_ENGINE_MSPDEC) |
-                                      (1ULL << NVDEV_ENGINE_MSPPP) |
-                                      (1ULL << NVDEV_ENGINE_CE0) |
-                                      (1ULL << NVDEV_ENGINE_VIC), &chan);
-       *pobject = nv_object(chan);
-       if (ret)
-               return ret;
-
-       chan->base.inst = base->base.gpuobj.addr;
-       args->v0.chid = chan->base.chid;
+       if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
+               return -ENOMEM;
+       *pobject = &chan->base.object;
 
-       ret = nvkm_ramht_new(device, 0x8000, 16, &base->base.gpuobj,
-                            &chan->ramht);
+       ret = g84_fifo_chan_ctor(fifo, args->v0.vm, args->v0.pushbuf,
+                                oclass, chan);
        if (ret)
                return ret;
 
-       nv_parent(chan)->context_attach = g84_fifo_context_attach;
-       nv_parent(chan)->context_detach = g84_fifo_context_detach;
-       nv_parent(chan)->object_attach = g84_fifo_object_attach;
-       nv_parent(chan)->object_detach = nv50_fifo_object_detach;
+       args->v0.chid = chan->base.chid;
 
-       nvkm_kmap(base->ramfc);
-       nvkm_wo32(base->ramfc, 0x08, lower_32_bits(args->v0.offset));
-       nvkm_wo32(base->ramfc, 0x0c, upper_32_bits(args->v0.offset));
-       nvkm_wo32(base->ramfc, 0x10, lower_32_bits(args->v0.offset));
-       nvkm_wo32(base->ramfc, 0x14, upper_32_bits(args->v0.offset));
-       nvkm_wo32(base->ramfc, 0x3c, 0x003f6078);
-       nvkm_wo32(base->ramfc, 0x44, 0x01003fff);
-       nvkm_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4);
-       nvkm_wo32(base->ramfc, 0x4c, 0xffffffff);
-       nvkm_wo32(base->ramfc, 0x60, 0x7fffffff);
-       nvkm_wo32(base->ramfc, 0x78, 0x00000000);
-       nvkm_wo32(base->ramfc, 0x7c, 0x30000001);
-       nvkm_wo32(base->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) |
+       nvkm_kmap(chan->ramfc);
+       nvkm_wo32(chan->ramfc, 0x08, lower_32_bits(args->v0.offset));
+       nvkm_wo32(chan->ramfc, 0x0c, upper_32_bits(args->v0.offset));
+       nvkm_wo32(chan->ramfc, 0x10, lower_32_bits(args->v0.offset));
+       nvkm_wo32(chan->ramfc, 0x14, upper_32_bits(args->v0.offset));
+       nvkm_wo32(chan->ramfc, 0x3c, 0x003f6078);
+       nvkm_wo32(chan->ramfc, 0x44, 0x01003fff);
+       nvkm_wo32(chan->ramfc, 0x48, chan->base.push->node->offset >> 4);
+       nvkm_wo32(chan->ramfc, 0x4c, 0xffffffff);
+       nvkm_wo32(chan->ramfc, 0x60, 0x7fffffff);
+       nvkm_wo32(chan->ramfc, 0x78, 0x00000000);
+       nvkm_wo32(chan->ramfc, 0x7c, 0x30000001);
+       nvkm_wo32(chan->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) |
                                     (4 << 24) /* SEARCH_FULL */ |
                                     (chan->ramht->gpuobj->node->offset >> 4));
-       nvkm_wo32(base->ramfc, 0x88, base->cache->addr >> 10);
-       nvkm_wo32(base->ramfc, 0x98, nv_gpuobj(base)->addr >> 12);
-       nvkm_done(base->ramfc);
+       nvkm_wo32(chan->ramfc, 0x88, chan->cache->addr >> 10);
+       nvkm_wo32(chan->ramfc, 0x98, chan->base.inst->addr >> 12);
+       nvkm_done(chan->ramfc);
        return 0;
 }
 
-static struct nvkm_ofuncs
-g84_fifo_ofuncs_dma = {
-       .ctor = g84_fifo_chan_ctor_dma,
-       .dtor = nv50_fifo_chan_dtor,
-       .init = g84_fifo_chan_init,
-       .fini = nv50_fifo_chan_fini,
-       .map  = _nvkm_fifo_channel_map,
-       .rd32 = _nvkm_fifo_channel_rd32,
-       .wr32 = _nvkm_fifo_channel_wr32,
-       .ntfy = _nvkm_fifo_channel_ntfy
-};
-
-struct nvkm_oclass
-g84_fifo_sclass[] = {
-       { G82_CHANNEL_DMA, &g84_fifo_ofuncs_dma },
-       { G82_CHANNEL_GPFIFO, &g84_fifo_ofuncs_ind },
-       {}
+const struct nvkm_fifo_chan_oclass
+g84_fifo_dma_oclass = {
+       .base.oclass = G82_CHANNEL_DMA,
+       .base.minver = 0,
+       .base.maxver = 0,
+       .ctor = g84_fifo_dma_new,
 };
index 8cc87103a369aa5da44239ce23aebfa4a51c9ed0..eafa87886643e0b6aab2bc62c1233bd5cd8e126f 100644 (file)
 #include <nvif/class.h>
 #include <nvif/unpack.h>
 
-int
-nv04_fifo_context_attach(struct nvkm_object *parent,
-                        struct nvkm_object *object)
-{
-       nv_engctx(object)->addr = nvkm_fifo_chan(parent)->chid;
-       return 0;
-}
-
 void
-nv04_fifo_object_detach(struct nvkm_object *parent, int cookie)
+nv04_fifo_dma_object_dtor(struct nvkm_fifo_chan *base, int cookie)
 {
-       struct nv04_fifo *fifo = (void *)parent->engine;
-       struct nvkm_instmem *imem = fifo->base.engine.subdev.device->imem;
-       mutex_lock(&nv_subdev(fifo)->mutex);
+       struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
+       struct nvkm_instmem *imem = chan->fifo->base.engine.subdev.device->imem;
        nvkm_ramht_remove(imem->ramht, cookie);
-       mutex_unlock(&nv_subdev(fifo)->mutex);
 }
 
-int
-nv04_fifo_object_attach(struct nvkm_object *parent,
-                       struct nvkm_object *object, u32 handle)
+static int
+nv04_fifo_dma_object_ctor(struct nvkm_fifo_chan *base,
+                         struct nvkm_object *object)
 {
-       struct nv04_fifo *fifo = (void *)parent->engine;
-       struct nv04_fifo_chan *chan = (void *)parent;
-       struct nvkm_instmem *imem = fifo->base.engine.subdev.device->imem;
-       u32 context, chid = chan->base.chid;
-       int ret;
-
-       if (nv_iclass(object, NV_GPUOBJ_CLASS))
-               context = nv_gpuobj(object)->addr >> 4;
-       else
-               context = 0x00000004; /* just non-zero */
-
-       if (object->engine) {
-               switch (nv_engidx(object->engine)) {
-               case NVDEV_ENGINE_DMAOBJ:
-               case NVDEV_ENGINE_SW:
-                       context |= 0x00000000;
-                       break;
-               case NVDEV_ENGINE_GR:
-                       context |= 0x00010000;
-                       break;
-               case NVDEV_ENGINE_MPEG:
-                       context |= 0x00020000;
-                       break;
-               default:
-                       return -EINVAL;
-               }
+       struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
+       struct nvkm_instmem *imem = chan->fifo->base.engine.subdev.device->imem;
+       u32 context = 0x80000000 | chan->base.chid << 24;
+       u32 handle  = object->handle;
+       int hash;
+
+       switch (object->engine->subdev.index) {
+       case NVDEV_ENGINE_DMAOBJ:
+       case NVDEV_ENGINE_SW    : context |= 0x00000000; break;
+       case NVDEV_ENGINE_GR    : context |= 0x00010000; break;
+       case NVDEV_ENGINE_MPEG  : context |= 0x00020000; break;
+       default:
+               WARN_ON(1);
+               return -EINVAL;
        }
 
-       context |= 0x80000000; /* valid */
-       context |= chid << 24;
-
-       mutex_lock(&nv_subdev(fifo)->mutex);
-       ret = nvkm_ramht_insert(imem->ramht, NULL, chid, 0, handle, context);
-       mutex_unlock(&nv_subdev(fifo)->mutex);
-       return ret;
+       mutex_lock(&chan->fifo->base.engine.subdev.mutex);
+       hash = nvkm_ramht_insert(imem->ramht, object, chan->base.chid, 4,
+                                handle, context);
+       mutex_unlock(&chan->fifo->base.engine.subdev.mutex);
+       return hash;
 }
 
-int
-nv04_fifo_chan_fini(struct nvkm_object *object, bool suspend)
+void
+nv04_fifo_dma_fini(struct nvkm_fifo_chan *base)
 {
-       struct nv04_fifo *fifo = (void *)object->engine;
-       struct nv04_fifo_chan *chan = (void *)object;
+       struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
+       struct nv04_fifo *fifo = chan->fifo;
        struct nvkm_device *device = fifo->base.engine.subdev.device;
        struct nvkm_memory *fctx = device->imem->ramfc;
        struct ramfc_desc *c;
        unsigned long flags;
+       u32 mask = fifo->base.nr - 1;
        u32 data = chan->ramfc;
        u32 chid;
 
@@ -107,7 +84,7 @@ nv04_fifo_chan_fini(struct nvkm_object *object, bool suspend)
        nvkm_wr32(device, NV03_PFIFO_CACHES, 0);
 
        /* if this channel is active, replace it with a null context */
-       chid = nvkm_rd32(device, NV03_PFIFO_CACHE1_PUSH1) & fifo->base.max;
+       chid = nvkm_rd32(device, NV03_PFIFO_CACHE1_PUSH1) & mask;
        if (chid == chan->base.chid) {
                nvkm_mask(device, NV04_PFIFO_CACHE1_DMA_PUSH, 0x00000001, 0);
                nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, 0);
@@ -129,7 +106,7 @@ nv04_fifo_chan_fini(struct nvkm_object *object, bool suspend)
 
                nvkm_wr32(device, NV03_PFIFO_CACHE1_GET, 0);
                nvkm_wr32(device, NV03_PFIFO_CACHE1_PUT, 0);
-               nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->base.max);
+               nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, mask);
                nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, 1);
                nvkm_wr32(device, NV04_PFIFO_CACHE1_PULL0, 1);
        }
@@ -138,35 +115,26 @@ nv04_fifo_chan_fini(struct nvkm_object *object, bool suspend)
        nvkm_mask(device, NV04_PFIFO_MODE, 1 << chan->base.chid, 0);
        nvkm_wr32(device, NV03_PFIFO_CACHES, 1);
        spin_unlock_irqrestore(&fifo->base.lock, flags);
-
-       return nvkm_fifo_channel_fini(&chan->base, suspend);
 }
 
-int
-nv04_fifo_chan_init(struct nvkm_object *object)
+void
+nv04_fifo_dma_init(struct nvkm_fifo_chan *base)
 {
-       struct nv04_fifo *fifo = (void *)object->engine;
-       struct nv04_fifo_chan *chan = (void *)object;
+       struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
+       struct nv04_fifo *fifo = chan->fifo;
        struct nvkm_device *device = fifo->base.engine.subdev.device;
        u32 mask = 1 << chan->base.chid;
        unsigned long flags;
-       int ret;
-
-       ret = nvkm_fifo_channel_init(&chan->base);
-       if (ret)
-               return ret;
-
        spin_lock_irqsave(&fifo->base.lock, flags);
        nvkm_mask(device, NV04_PFIFO_MODE, mask, mask);
        spin_unlock_irqrestore(&fifo->base.lock, flags);
-       return 0;
 }
 
-void
-nv04_fifo_chan_dtor(struct nvkm_object *object)
+void *
+nv04_fifo_dma_dtor(struct nvkm_fifo_chan *base)
 {
-       struct nv04_fifo *fifo = (void *)object->engine;
-       struct nv04_fifo_chan *chan = (void *)object;
+       struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
+       struct nv04_fifo *fifo = chan->fifo;
        struct nvkm_instmem *imem = fifo->base.engine.subdev.device->imem;
        struct ramfc_desc *c = fifo->ramfc_desc;
 
@@ -175,22 +143,30 @@ nv04_fifo_chan_dtor(struct nvkm_object *object)
                nvkm_wo32(imem->ramfc, chan->ramfc + c->ctxp, 0x00000000);
        } while ((++c)->bits);
        nvkm_done(imem->ramfc);
-
-       nvkm_fifo_channel_destroy(&chan->base);
+       return chan;
 }
 
+const struct nvkm_fifo_chan_func
+nv04_fifo_dma_func = {
+       .dtor = nv04_fifo_dma_dtor,
+       .init = nv04_fifo_dma_init,
+       .fini = nv04_fifo_dma_fini,
+       .object_ctor = nv04_fifo_dma_object_ctor,
+       .object_dtor = nv04_fifo_dma_object_dtor,
+};
+
 static int
-nv04_fifo_chan_ctor(struct nvkm_object *parent,
-                   struct nvkm_object *engine,
-                   struct nvkm_oclass *oclass, void *data, u32 size,
-                   struct nvkm_object **pobject)
+nv04_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
+                 void *data, u32 size, struct nvkm_object **pobject)
 {
+       struct nvkm_object *parent = oclass->parent;
        union {
                struct nv03_channel_dma_v0 v0;
        } *args = data;
-       struct nv04_fifo *fifo = (void *)engine;
-       struct nvkm_instmem *imem = fifo->base.engine.subdev.device->imem;
-       struct nv04_fifo_chan *chan;
+       struct nv04_fifo *fifo = nv04_fifo(base);
+       struct nv04_fifo_chan *chan = NULL;
+       struct nvkm_device *device = fifo->base.engine.subdev.device;
+       struct nvkm_instmem *imem = device->imem;
        int ret;
 
        nvif_ioctl(parent, "create channel dma size %d\n", size);
@@ -198,29 +174,32 @@ nv04_fifo_chan_ctor(struct nvkm_object *parent,
                nvif_ioctl(parent, "create channel dma vers %d pushbuf %llx "
                                   "offset %08x\n", args->v0.version,
                           args->v0.pushbuf, args->v0.offset);
+               if (!args->v0.pushbuf)
+                       return -EINVAL;
        } else
                return ret;
 
-       ret = nvkm_fifo_channel_create(parent, engine, oclass, 0, 0x800000,
-                                      0x10000, args->v0.pushbuf,
-                                      (1ULL << NVDEV_ENGINE_DMAOBJ) |
-                                      (1ULL << NVDEV_ENGINE_SW) |
-                                      (1ULL << NVDEV_ENGINE_GR), &chan);
-       *pobject = nv_object(chan);
+       if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
+               return -ENOMEM;
+       *pobject = &chan->base.object;
+
+       ret = nvkm_fifo_chan_ctor(&nv04_fifo_dma_func, &fifo->base,
+                                 0x1000, 0x1000, false, 0, args->v0.pushbuf,
+                                 (1ULL << NVDEV_ENGINE_DMAOBJ) |
+                                 (1ULL << NVDEV_ENGINE_GR) |
+                                 (1ULL << NVDEV_ENGINE_SW),
+                                 0, 0x800000, 0x10000, oclass, &chan->base);
+       chan->fifo = fifo;
        if (ret)
                return ret;
 
        args->v0.chid = chan->base.chid;
-
-       nv_parent(chan)->object_attach = nv04_fifo_object_attach;
-       nv_parent(chan)->object_detach = nv04_fifo_object_detach;
-       nv_parent(chan)->context_attach = nv04_fifo_context_attach;
        chan->ramfc = chan->base.chid * 32;
 
        nvkm_kmap(imem->ramfc);
        nvkm_wo32(imem->ramfc, chan->ramfc + 0x00, args->v0.offset);
        nvkm_wo32(imem->ramfc, chan->ramfc + 0x04, args->v0.offset);
-       nvkm_wo32(imem->ramfc, chan->ramfc + 0x08, chan->base.pushgpu->addr >> 4);
+       nvkm_wo32(imem->ramfc, chan->ramfc + 0x08, chan->base.push->addr >> 4);
        nvkm_wo32(imem->ramfc, chan->ramfc + 0x10,
                               NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
                               NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
@@ -232,51 +211,10 @@ nv04_fifo_chan_ctor(struct nvkm_object *parent,
        return 0;
 }
 
-static struct nvkm_ofuncs
-nv04_fifo_ofuncs = {
-       .ctor = nv04_fifo_chan_ctor,
-       .dtor = nv04_fifo_chan_dtor,
-       .init = nv04_fifo_chan_init,
-       .fini = nv04_fifo_chan_fini,
-       .map  = _nvkm_fifo_channel_map,
-       .rd32 = _nvkm_fifo_channel_rd32,
-       .wr32 = _nvkm_fifo_channel_wr32,
-       .ntfy = _nvkm_fifo_channel_ntfy
-};
-
-struct nvkm_oclass
-nv04_fifo_sclass[] = {
-       { NV03_CHANNEL_DMA, &nv04_fifo_ofuncs },
-       {}
-};
-
-int
-nv04_fifo_context_ctor(struct nvkm_object *parent,
-                      struct nvkm_object *engine,
-                      struct nvkm_oclass *oclass, void *data, u32 size,
-                      struct nvkm_object **pobject)
-{
-       struct nv04_fifo_base *base;
-       int ret;
-
-       ret = nvkm_fifo_context_create(parent, engine, oclass, NULL, 0x1000,
-                                      0x1000, NVOBJ_FLAG_HEAP, &base);
-       *pobject = nv_object(base);
-       if (ret)
-               return ret;
-
-       return 0;
-}
-
-struct nvkm_oclass
-nv04_fifo_cclass = {
-       .handle = NV_ENGCTX(FIFO, 0x04),
-       .ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = nv04_fifo_context_ctor,
-               .dtor = _nvkm_fifo_context_dtor,
-               .init = _nvkm_fifo_context_init,
-               .fini = _nvkm_fifo_context_fini,
-               .rd32 = _nvkm_fifo_context_rd32,
-               .wr32 = _nvkm_fifo_context_wr32,
-       },
+const struct nvkm_fifo_chan_oclass
+nv04_fifo_dma_oclass = {
+       .base.oclass = NV03_CHANNEL_DMA,
+       .base.minver = 0,
+       .base.maxver = 0,
+       .ctor = nv04_fifo_dma_new,
 };
index a542515e63f0b426afb2e961a6f313025e1d1171..1ad16205305f8b9e2a3fbc4d934461a534814df7 100644 (file)
 #include <nvif/unpack.h>
 
 static int
-nv10_fifo_chan_ctor(struct nvkm_object *parent,
-                   struct nvkm_object *engine,
-                   struct nvkm_oclass *oclass, void *data, u32 size,
-                   struct nvkm_object **pobject)
+nv10_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
+                 void *data, u32 size, struct nvkm_object **pobject)
 {
+       struct nvkm_object *parent = oclass->parent;
        union {
                struct nv03_channel_dma_v0 v0;
        } *args = data;
-       struct nv04_fifo *fifo = (void *)engine;
-       struct nvkm_instmem *imem = fifo->base.engine.subdev.device->imem;
-       struct nv04_fifo_chan *chan;
+       struct nv04_fifo *fifo = nv04_fifo(base);
+       struct nv04_fifo_chan *chan = NULL;
+       struct nvkm_device *device = fifo->base.engine.subdev.device;
+       struct nvkm_instmem *imem = device->imem;
        int ret;
 
        nvif_ioctl(parent, "create channel dma size %d\n", size);
@@ -49,29 +49,32 @@ nv10_fifo_chan_ctor(struct nvkm_object *parent,
                nvif_ioctl(parent, "create channel dma vers %d pushbuf %llx "
                                   "offset %08x\n", args->v0.version,
                           args->v0.pushbuf, args->v0.offset);
+               if (!args->v0.pushbuf)
+                       return -EINVAL;
        } else
                return ret;
 
-       ret = nvkm_fifo_channel_create(parent, engine, oclass, 0, 0x800000,
-                                      0x10000, args->v0.pushbuf,
-                                      (1ULL << NVDEV_ENGINE_DMAOBJ) |
-                                      (1ULL << NVDEV_ENGINE_SW) |
-                                      (1ULL << NVDEV_ENGINE_GR), &chan);
-       *pobject = nv_object(chan);
+       if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
+               return -ENOMEM;
+       *pobject = &chan->base.object;
+
+       ret = nvkm_fifo_chan_ctor(&nv04_fifo_dma_func, &fifo->base,
+                                 0x1000, 0x1000, false, 0, args->v0.pushbuf,
+                                 (1ULL << NVDEV_ENGINE_DMAOBJ) |
+                                 (1ULL << NVDEV_ENGINE_GR) |
+                                 (1ULL << NVDEV_ENGINE_SW),
+                                 0, 0x800000, 0x10000, oclass, &chan->base);
+       chan->fifo = fifo;
        if (ret)
                return ret;
 
        args->v0.chid = chan->base.chid;
-
-       nv_parent(chan)->object_attach = nv04_fifo_object_attach;
-       nv_parent(chan)->object_detach = nv04_fifo_object_detach;
-       nv_parent(chan)->context_attach = nv04_fifo_context_attach;
        chan->ramfc = chan->base.chid * 32;
 
        nvkm_kmap(imem->ramfc);
        nvkm_wo32(imem->ramfc, chan->ramfc + 0x00, args->v0.offset);
        nvkm_wo32(imem->ramfc, chan->ramfc + 0x04, args->v0.offset);
-       nvkm_wo32(imem->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4);
+       nvkm_wo32(imem->ramfc, chan->ramfc + 0x0c, chan->base.push->addr >> 4);
        nvkm_wo32(imem->ramfc, chan->ramfc + 0x14,
                               NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
                               NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
@@ -83,20 +86,10 @@ nv10_fifo_chan_ctor(struct nvkm_object *parent,
        return 0;
 }
 
-static struct nvkm_ofuncs
-nv10_fifo_ofuncs = {
-       .ctor = nv10_fifo_chan_ctor,
-       .dtor = nv04_fifo_chan_dtor,
-       .init = nv04_fifo_chan_init,
-       .fini = nv04_fifo_chan_fini,
-       .map  = _nvkm_fifo_channel_map,
-       .rd32 = _nvkm_fifo_channel_rd32,
-       .wr32 = _nvkm_fifo_channel_wr32,
-       .ntfy = _nvkm_fifo_channel_ntfy
-};
-
-struct nvkm_oclass
-nv10_fifo_sclass[] = {
-       { NV10_CHANNEL_DMA, &nv10_fifo_ofuncs },
-       {}
+const struct nvkm_fifo_chan_oclass
+nv10_fifo_dma_oclass = {
+       .base.oclass = NV10_CHANNEL_DMA,
+       .base.minver = 0,
+       .base.maxver = 0,
+       .ctor = nv10_fifo_dma_new,
 };
index d0ece53a750b9801637f7a6ed9ab5d90d8ac22a9..2fbb9d4f0900e5765b70284fb2c5ed40aee9db12 100644 (file)
 #include <nvif/unpack.h>
 
 static int
-nv17_fifo_chan_ctor(struct nvkm_object *parent,
-                   struct nvkm_object *engine,
-                   struct nvkm_oclass *oclass, void *data, u32 size,
-                   struct nvkm_object **pobject)
+nv17_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
+                 void *data, u32 size, struct nvkm_object **pobject)
 {
+       struct nvkm_object *parent = oclass->parent;
        union {
                struct nv03_channel_dma_v0 v0;
        } *args = data;
-       struct nv04_fifo *fifo = (void *)engine;
-       struct nvkm_instmem *imem = fifo->base.engine.subdev.device->imem;
-       struct nv04_fifo_chan *chan;
+       struct nv04_fifo *fifo = nv04_fifo(base);
+       struct nv04_fifo_chan *chan = NULL;
+       struct nvkm_device *device = fifo->base.engine.subdev.device;
+       struct nvkm_instmem *imem = device->imem;
        int ret;
 
        nvif_ioctl(parent, "create channel dma size %d\n", size);
@@ -49,31 +49,33 @@ nv17_fifo_chan_ctor(struct nvkm_object *parent,
                nvif_ioctl(parent, "create channel dma vers %d pushbuf %llx "
                                   "offset %08x\n", args->v0.version,
                           args->v0.pushbuf, args->v0.offset);
+               if (!args->v0.pushbuf)
+                       return -EINVAL;
        } else
                return ret;
 
-       ret = nvkm_fifo_channel_create(parent, engine, oclass, 0, 0x800000,
-                                      0x10000, args->v0.pushbuf,
-                                      (1ULL << NVDEV_ENGINE_DMAOBJ) |
-                                      (1ULL << NVDEV_ENGINE_SW) |
-                                      (1ULL << NVDEV_ENGINE_GR) |
-                                      (1ULL << NVDEV_ENGINE_MPEG), /* NV31- */
-                                      &chan);
-       *pobject = nv_object(chan);
+       if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
+               return -ENOMEM;
+       *pobject = &chan->base.object;
+
+       ret = nvkm_fifo_chan_ctor(&nv04_fifo_dma_func, &fifo->base,
+                                 0x1000, 0x1000, false, 0, args->v0.pushbuf,
+                                 (1ULL << NVDEV_ENGINE_DMAOBJ) |
+                                 (1ULL << NVDEV_ENGINE_GR) |
+                                 (1ULL << NVDEV_ENGINE_MPEG) | /* NV31- */
+                                 (1ULL << NVDEV_ENGINE_SW),
+                                 0, 0x800000, 0x10000, oclass, &chan->base);
+       chan->fifo = fifo;
        if (ret)
                return ret;
 
        args->v0.chid = chan->base.chid;
-
-       nv_parent(chan)->object_attach = nv04_fifo_object_attach;
-       nv_parent(chan)->object_detach = nv04_fifo_object_detach;
-       nv_parent(chan)->context_attach = nv04_fifo_context_attach;
        chan->ramfc = chan->base.chid * 64;
 
        nvkm_kmap(imem->ramfc);
        nvkm_wo32(imem->ramfc, chan->ramfc + 0x00, args->v0.offset);
        nvkm_wo32(imem->ramfc, chan->ramfc + 0x04, args->v0.offset);
-       nvkm_wo32(imem->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4);
+       nvkm_wo32(imem->ramfc, chan->ramfc + 0x0c, chan->base.push->addr >> 4);
        nvkm_wo32(imem->ramfc, chan->ramfc + 0x14,
                               NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
                               NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
@@ -85,20 +87,10 @@ nv17_fifo_chan_ctor(struct nvkm_object *parent,
        return 0;
 }
 
-static struct nvkm_ofuncs
-nv17_fifo_ofuncs = {
-       .ctor = nv17_fifo_chan_ctor,
-       .dtor = nv04_fifo_chan_dtor,
-       .init = nv04_fifo_chan_init,
-       .fini = nv04_fifo_chan_fini,
-       .map  = _nvkm_fifo_channel_map,
-       .rd32 = _nvkm_fifo_channel_rd32,
-       .wr32 = _nvkm_fifo_channel_wr32,
-       .ntfy = _nvkm_fifo_channel_ntfy
-};
-
-struct nvkm_oclass
-nv17_fifo_sclass[] = {
-       { NV17_CHANNEL_DMA, &nv17_fifo_ofuncs },
-       {}
+const struct nvkm_fifo_chan_oclass
+nv17_fifo_dma_oclass = {
+       .base.oclass = NV17_CHANNEL_DMA,
+       .base.minver = 0,
+       .base.maxver = 0,
+       .ctor = nv17_fifo_dma_new,
 };
index cd3503cb6837eb157eed6a790608be8ed94f7661..b46a3b3cd0924bec1995e5165a38531f26bea015 100644 (file)
 #include <nvif/class.h>
 #include <nvif/unpack.h>
 
+static bool
+nv40_fifo_dma_engine(struct nvkm_engine *engine, u32 *reg, u32 *ctx)
+{
+       switch (engine->subdev.index) {
+       case NVDEV_ENGINE_DMAOBJ:
+       case NVDEV_ENGINE_SW:
+               return false;
+       case NVDEV_ENGINE_GR:
+               *reg = 0x0032e0;
+               *ctx = 0x38;
+               return true;
+       case NVDEV_ENGINE_MPEG:
+               *reg = 0x00330c;
+               *ctx = 0x54;
+               return true;
+       default:
+               WARN_ON(1);
+               return false;
+       }
+}
+
 static int
-nv40_fifo_context_detach(struct nvkm_object *parent, bool suspend,
-                        struct nvkm_object *engctx)
+nv40_fifo_dma_engine_fini(struct nvkm_fifo_chan *base,
+                         struct nvkm_engine *engine, bool suspend)
 {
-       struct nv04_fifo *fifo = (void *)parent->engine;
-       struct nv04_fifo_chan *chan = (void *)parent;
+       struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
+       struct nv04_fifo *fifo = chan->fifo;
        struct nvkm_device *device = fifo->base.engine.subdev.device;
        struct nvkm_instmem *imem = device->imem;
        unsigned long flags;
        u32 reg, ctx;
+       int chid;
 
-       switch (nv_engidx(engctx->engine)) {
-       case NVDEV_ENGINE_SW:
+       if (!nv40_fifo_dma_engine(engine, &reg, &ctx))
                return 0;
-       case NVDEV_ENGINE_GR:
-               reg = 0x32e0;
-               ctx = 0x38;
-               break;
-       case NVDEV_ENGINE_MPEG:
-               reg = 0x330c;
-               ctx = 0x54;
-               break;
-       default:
-               return -EINVAL;
-       }
 
        spin_lock_irqsave(&fifo->base.lock, flags);
        nvkm_mask(device, 0x002500, 0x00000001, 0x00000000);
 
-       if ((nvkm_rd32(device, 0x003204) & fifo->base.max) == chan->base.chid)
+       chid = nvkm_rd32(device, 0x003204) & (fifo->base.nr - 1);
+       if (chid == chan->base.chid)
                nvkm_wr32(device, reg, 0x00000000);
        nvkm_kmap(imem->ramfc);
        nvkm_wo32(imem->ramfc, chan->ramfc + ctx, 0x00000000);
@@ -72,38 +83,29 @@ nv40_fifo_context_detach(struct nvkm_object *parent, bool suspend,
 }
 
 static int
-nv40_fifo_context_attach(struct nvkm_object *parent, struct nvkm_object *engctx)
+nv40_fifo_dma_engine_init(struct nvkm_fifo_chan *base,
+                         struct nvkm_engine *engine)
 {
-       struct nv04_fifo *fifo = (void *)parent->engine;
-       struct nv04_fifo_chan *chan = (void *)parent;
+       struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
+       struct nv04_fifo *fifo = chan->fifo;
        struct nvkm_device *device = fifo->base.engine.subdev.device;
        struct nvkm_instmem *imem = device->imem;
        unsigned long flags;
-       u32 reg, ctx;
+       u32 inst, reg, ctx;
+       int chid;
 
-       switch (nv_engidx(engctx->engine)) {
-       case NVDEV_ENGINE_SW:
+       if (!nv40_fifo_dma_engine(engine, &reg, &ctx))
                return 0;
-       case NVDEV_ENGINE_GR:
-               reg = 0x32e0;
-               ctx = 0x38;
-               break;
-       case NVDEV_ENGINE_MPEG:
-               reg = 0x330c;
-               ctx = 0x54;
-               break;
-       default:
-               return -EINVAL;
-       }
+       inst = chan->engn[engine->subdev.index]->addr >> 4;
 
        spin_lock_irqsave(&fifo->base.lock, flags);
-       nv_engctx(engctx)->addr = nv_gpuobj(engctx)->addr >> 4;
        nvkm_mask(device, 0x002500, 0x00000001, 0x00000000);
 
-       if ((nvkm_rd32(device, 0x003204) & fifo->base.max) == chan->base.chid)
-               nvkm_wr32(device, reg, nv_engctx(engctx)->addr);
+       chid = nvkm_rd32(device, 0x003204) & (fifo->base.nr - 1);
+       if (chid == chan->base.chid)
+               nvkm_wr32(device, reg, inst);
        nvkm_kmap(imem->ramfc);
-       nvkm_wo32(imem->ramfc, chan->ramfc + ctx, nv_engctx(engctx)->addr);
+       nvkm_wo32(imem->ramfc, chan->ramfc + ctx, inst);
        nvkm_done(imem->ramfc);
 
        nvkm_mask(device, 0x002500, 0x00000001, 0x00000001);
@@ -111,57 +113,91 @@ nv40_fifo_context_attach(struct nvkm_object *parent, struct nvkm_object *engctx)
        return 0;
 }
 
+static void
+nv40_fifo_dma_engine_dtor(struct nvkm_fifo_chan *base,
+                         struct nvkm_engine *engine)
+{
+       struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
+       if (!chan->engn[engine->subdev.index] ||
+            chan->engn[engine->subdev.index]->object.oclass) {
+               chan->engn[engine->subdev.index] = NULL;
+               return;
+       }
+       nvkm_gpuobj_del(&chan->engn[engine->subdev.index]);
+}
+
 static int
-nv40_fifo_object_attach(struct nvkm_object *parent,
-                       struct nvkm_object *object, u32 handle)
+nv40_fifo_dma_engine_ctor(struct nvkm_fifo_chan *base,
+                         struct nvkm_engine *engine,
+                         struct nvkm_object *object)
 {
-       struct nv04_fifo *fifo = (void *)parent->engine;
-       struct nv04_fifo_chan *chan = (void *)parent;
-       struct nvkm_instmem *imem = fifo->base.engine.subdev.device->imem;
-       u32 context, chid = chan->base.chid;
-       int ret;
+       struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
+       const int engn = engine->subdev.index;
+       u32 reg, ctx;
 
-       if (nv_iclass(object, NV_GPUOBJ_CLASS))
-               context = nv_gpuobj(object)->addr >> 4;
-       else
-               context = 0x00000004; /* just non-zero */
-
-       if (object->engine) {
-               switch (nv_engidx(object->engine)) {
-               case NVDEV_ENGINE_DMAOBJ:
-               case NVDEV_ENGINE_SW:
-                       context |= 0x00000000;
-                       break;
-               case NVDEV_ENGINE_GR:
-                       context |= 0x00100000;
-                       break;
-               case NVDEV_ENGINE_MPEG:
-                       context |= 0x00200000;
-                       break;
-               default:
-                       return -EINVAL;
-               }
+       if (!nv40_fifo_dma_engine(engine, &reg, &ctx))
+               return 0;
+
+       if (nv_iclass(object, NV_GPUOBJ_CLASS)) {
+               chan->engn[engn] = nv_gpuobj(object);
+               return 0;
        }
 
-       context |= chid << 23;
+       return nvkm_object_bind(object, NULL, 0, &chan->engn[engn]);
+}
 
-       mutex_lock(&nv_subdev(fifo)->mutex);
-       ret = nvkm_ramht_insert(imem->ramht, NULL, chid, 0, handle, context);
-       mutex_unlock(&nv_subdev(fifo)->mutex);
-       return ret;
+static int
+nv40_fifo_dma_object_ctor(struct nvkm_fifo_chan *base,
+                         struct nvkm_object *object)
+{
+       struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
+       struct nvkm_instmem *imem = chan->fifo->base.engine.subdev.device->imem;
+       u32 context = chan->base.chid << 23;
+       u32 handle  = object->handle;
+       int hash;
+
+       switch (object->engine->subdev.index) {
+       case NVDEV_ENGINE_DMAOBJ:
+       case NVDEV_ENGINE_SW    : context |= 0x00000000; break;
+       case NVDEV_ENGINE_GR    : context |= 0x00100000; break;
+       case NVDEV_ENGINE_MPEG  : context |= 0x00200000; break;
+       default:
+               WARN_ON(1);
+               return -EINVAL;
+       }
+
+       mutex_lock(&chan->fifo->base.engine.subdev.mutex);
+       hash = nvkm_ramht_insert(imem->ramht, object, chan->base.chid, 4,
+                                handle, context);
+       mutex_unlock(&chan->fifo->base.engine.subdev.mutex);
+       return hash;
 }
 
+static const struct nvkm_fifo_chan_func
+nv40_fifo_dma_func = {
+       .dtor = nv04_fifo_dma_dtor,
+       .init = nv04_fifo_dma_init,
+       .fini = nv04_fifo_dma_fini,
+       .engine_ctor = nv40_fifo_dma_engine_ctor,
+       .engine_dtor = nv40_fifo_dma_engine_dtor,
+       .engine_init = nv40_fifo_dma_engine_init,
+       .engine_fini = nv40_fifo_dma_engine_fini,
+       .object_ctor = nv40_fifo_dma_object_ctor,
+       .object_dtor = nv04_fifo_dma_object_dtor,
+};
+
 static int
-nv40_fifo_chan_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-                   struct nvkm_oclass *oclass, void *data, u32 size,
-                   struct nvkm_object **pobject)
+nv40_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
+                 void *data, u32 size, struct nvkm_object **pobject)
 {
+       struct nvkm_object *parent = oclass->parent;
        union {
                struct nv03_channel_dma_v0 v0;
        } *args = data;
-       struct nv04_fifo *fifo = (void *)engine;
-       struct nvkm_instmem *imem = fifo->base.engine.subdev.device->imem;
-       struct nv04_fifo_chan *chan;
+       struct nv04_fifo *fifo = nv04_fifo(base);
+       struct nv04_fifo_chan *chan = NULL;
+       struct nvkm_device *device = fifo->base.engine.subdev.device;
+       struct nvkm_instmem *imem = device->imem;
        int ret;
 
        nvif_ioctl(parent, "create channel dma size %d\n", size);
@@ -169,31 +205,33 @@ nv40_fifo_chan_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
                nvif_ioctl(parent, "create channel dma vers %d pushbuf %llx "
                                   "offset %08x\n", args->v0.version,
                           args->v0.pushbuf, args->v0.offset);
+               if (!args->v0.pushbuf)
+                       return -EINVAL;
        } else
                return ret;
 
-       ret = nvkm_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
-                                      0x1000, args->v0.pushbuf,
-                                      (1ULL << NVDEV_ENGINE_DMAOBJ) |
-                                      (1ULL << NVDEV_ENGINE_SW) |
-                                      (1ULL << NVDEV_ENGINE_GR) |
-                                      (1ULL << NVDEV_ENGINE_MPEG), &chan);
-       *pobject = nv_object(chan);
+       if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
+               return -ENOMEM;
+       *pobject = &chan->base.object;
+
+       ret = nvkm_fifo_chan_ctor(&nv40_fifo_dma_func, &fifo->base,
+                                 0x1000, 0x1000, false, 0, args->v0.pushbuf,
+                                 (1ULL << NVDEV_ENGINE_DMAOBJ) |
+                                 (1ULL << NVDEV_ENGINE_GR) |
+                                 (1ULL << NVDEV_ENGINE_MPEG) |
+                                 (1ULL << NVDEV_ENGINE_SW),
+                                 0, 0xc00000, 0x1000, oclass, &chan->base);
+       chan->fifo = fifo;
        if (ret)
                return ret;
 
        args->v0.chid = chan->base.chid;
-
-       nv_parent(chan)->context_attach = nv40_fifo_context_attach;
-       nv_parent(chan)->context_detach = nv40_fifo_context_detach;
-       nv_parent(chan)->object_attach = nv40_fifo_object_attach;
-       nv_parent(chan)->object_detach = nv04_fifo_object_detach;
        chan->ramfc = chan->base.chid * 128;
 
        nvkm_kmap(imem->ramfc);
        nvkm_wo32(imem->ramfc, chan->ramfc + 0x00, args->v0.offset);
        nvkm_wo32(imem->ramfc, chan->ramfc + 0x04, args->v0.offset);
-       nvkm_wo32(imem->ramfc, chan->ramfc + 0x0c, chan->base.pushgpu->addr >> 4);
+       nvkm_wo32(imem->ramfc, chan->ramfc + 0x0c, chan->base.push->addr >> 4);
        nvkm_wo32(imem->ramfc, chan->ramfc + 0x18, 0x30000000 |
                               NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
                               NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
@@ -206,20 +244,10 @@ nv40_fifo_chan_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
        return 0;
 }
 
-static struct nvkm_ofuncs
-nv40_fifo_ofuncs = {
-       .ctor = nv40_fifo_chan_ctor,
-       .dtor = nv04_fifo_chan_dtor,
-       .init = nv04_fifo_chan_init,
-       .fini = nv04_fifo_chan_fini,
-       .map  = _nvkm_fifo_channel_map,
-       .rd32 = _nvkm_fifo_channel_rd32,
-       .wr32 = _nvkm_fifo_channel_wr32,
-       .ntfy = _nvkm_fifo_channel_ntfy
-};
-
-struct nvkm_oclass
-nv40_fifo_sclass[] = {
-       { NV40_CHANNEL_DMA, &nv40_fifo_ofuncs },
-       {}
+const struct nvkm_fifo_chan_oclass
+nv40_fifo_dma_oclass = {
+       .base.oclass = NV40_CHANNEL_DMA,
+       .base.minver = 0,
+       .base.maxver = 0,
+       .ctor = nv40_fifo_dma_new,
 };
index 11a283099235870cdd62b78474263d9ef91f701f..6b3b15f12c392f5e0c1cdf4072c2c6d3494eed67 100644 (file)
 #include <nvif/unpack.h>
 
 static int
-nv50_fifo_chan_ctor_dma(struct nvkm_object *parent, struct nvkm_object *engine,
-                       struct nvkm_oclass *oclass, void *data, u32 size,
-                       struct nvkm_object **pobject)
+nv50_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
+                 void *data, u32 size, struct nvkm_object **pobject)
 {
+       struct nvkm_object *parent = oclass->parent;
        union {
                struct nv50_channel_dma_v0 v0;
        } *args = data;
-       struct nvkm_device *device = parent->engine->subdev.device;
-       struct nv50_fifo_base *base = (void *)parent;
+       struct nv50_fifo *fifo = nv50_fifo(base);
        struct nv50_fifo_chan *chan;
        int ret;
 
@@ -48,68 +47,45 @@ nv50_fifo_chan_ctor_dma(struct nvkm_object *parent, struct nvkm_object *engine,
                                   "pushbuf %llx offset %016llx\n",
                           args->v0.version, args->v0.vm, args->v0.pushbuf,
                           args->v0.offset);
-               if (args->v0.vm)
-                       return -ENOENT;
+               if (!args->v0.pushbuf)
+                       return -EINVAL;
        } else
                return ret;
 
-       ret = nvkm_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
-                                      0x2000, args->v0.pushbuf,
-                                      (1ULL << NVDEV_ENGINE_DMAOBJ) |
-                                      (1ULL << NVDEV_ENGINE_SW) |
-                                      (1ULL << NVDEV_ENGINE_GR) |
-                                      (1ULL << NVDEV_ENGINE_MPEG), &chan);
-       *pobject = nv_object(chan);
+       if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
+               return -ENOMEM;
+       *pobject = &chan->base.object;
+
+       ret = nv50_fifo_chan_ctor(fifo, args->v0.vm, args->v0.pushbuf,
+                                 oclass, chan);
        if (ret)
                return ret;
 
-       chan->base.inst = base->base.gpuobj.addr;
        args->v0.chid = chan->base.chid;
 
-       nv_parent(chan)->context_attach = nv50_fifo_context_attach;
-       nv_parent(chan)->context_detach = nv50_fifo_context_detach;
-       nv_parent(chan)->object_attach = nv50_fifo_object_attach;
-       nv_parent(chan)->object_detach = nv50_fifo_object_detach;
-
-       ret = nvkm_ramht_new(device, 0x8000, 16, &base->base.gpuobj,
-                            &chan->ramht);
-       if (ret)
-               return ret;
-
-       nvkm_kmap(base->ramfc);
-       nvkm_wo32(base->ramfc, 0x08, lower_32_bits(args->v0.offset));
-       nvkm_wo32(base->ramfc, 0x0c, upper_32_bits(args->v0.offset));
-       nvkm_wo32(base->ramfc, 0x10, lower_32_bits(args->v0.offset));
-       nvkm_wo32(base->ramfc, 0x14, upper_32_bits(args->v0.offset));
-       nvkm_wo32(base->ramfc, 0x3c, 0x003f6078);
-       nvkm_wo32(base->ramfc, 0x44, 0x01003fff);
-       nvkm_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4);
-       nvkm_wo32(base->ramfc, 0x4c, 0xffffffff);
-       nvkm_wo32(base->ramfc, 0x60, 0x7fffffff);
-       nvkm_wo32(base->ramfc, 0x78, 0x00000000);
-       nvkm_wo32(base->ramfc, 0x7c, 0x30000001);
-       nvkm_wo32(base->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) |
+       nvkm_kmap(chan->ramfc);
+       nvkm_wo32(chan->ramfc, 0x08, lower_32_bits(args->v0.offset));
+       nvkm_wo32(chan->ramfc, 0x0c, upper_32_bits(args->v0.offset));
+       nvkm_wo32(chan->ramfc, 0x10, lower_32_bits(args->v0.offset));
+       nvkm_wo32(chan->ramfc, 0x14, upper_32_bits(args->v0.offset));
+       nvkm_wo32(chan->ramfc, 0x3c, 0x003f6078);
+       nvkm_wo32(chan->ramfc, 0x44, 0x01003fff);
+       nvkm_wo32(chan->ramfc, 0x48, chan->base.push->node->offset >> 4);
+       nvkm_wo32(chan->ramfc, 0x4c, 0xffffffff);
+       nvkm_wo32(chan->ramfc, 0x60, 0x7fffffff);
+       nvkm_wo32(chan->ramfc, 0x78, 0x00000000);
+       nvkm_wo32(chan->ramfc, 0x7c, 0x30000001);
+       nvkm_wo32(chan->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) |
                                     (4 << 24) /* SEARCH_FULL */ |
                                     (chan->ramht->gpuobj->node->offset >> 4));
-       nvkm_done(base->ramfc);
+       nvkm_done(chan->ramfc);
        return 0;
 }
 
-static struct nvkm_ofuncs
-nv50_fifo_ofuncs_dma = {
-       .ctor = nv50_fifo_chan_ctor_dma,
-       .dtor = nv50_fifo_chan_dtor,
-       .init = nv50_fifo_chan_init,
-       .fini = nv50_fifo_chan_fini,
-       .map  = _nvkm_fifo_channel_map,
-       .rd32 = _nvkm_fifo_channel_rd32,
-       .wr32 = _nvkm_fifo_channel_wr32,
-       .ntfy = _nvkm_fifo_channel_ntfy
-};
-
-struct nvkm_oclass
-nv50_fifo_sclass[] = {
-       { NV50_CHANNEL_DMA, &nv50_fifo_ofuncs_dma },
-       { NV50_CHANNEL_GPFIFO, &nv50_fifo_ofuncs_ind },
-       {}
+const struct nvkm_fifo_chan_oclass
+nv50_fifo_dma_oclass = {
+       .base.oclass = NV50_CHANNEL_DMA,
+       .base.minver = 0,
+       .base.maxver = 0,
+       .ctor = nv50_fifo_dma_new,
 };
index ab0ecc423e68493361e7a6df3c531b7b508df03f..00fa9d3eff7ad3b9adbda3c223a1ec36088b5b9e 100644 (file)
@@ -47,6 +47,15 @@ g84_fifo_uevent_func = {
        .fini = g84_fifo_uevent_fini,
 };
 
+static const struct nvkm_fifo_func
+g84_fifo_func = {
+       .chan = {
+               &g84_fifo_dma_oclass,
+               &g84_fifo_gpfifo_oclass,
+               NULL
+       },
+};
+
 static int
 g84_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
              struct nvkm_oclass *oclass, void *data, u32 size,
@@ -61,6 +70,8 @@ g84_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
        if (ret)
                return ret;
 
+       fifo->base.func = &g84_fifo_func;
+
        ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 4, 0x1000,
                              false, &fifo->runlist[0]);
        if (ret)
@@ -77,8 +88,6 @@ g84_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
 
        nv_subdev(fifo)->unit = 0x00000100;
        nv_subdev(fifo)->intr = nv04_fifo_intr;
-       nv_engine(fifo)->cclass = &g84_fifo_cclass;
-       nv_engine(fifo)->sclass = g84_fifo_sclass;
        fifo->base.pause = nv04_fifo_pause;
        fifo->base.start = nv04_fifo_start;
        return 0;
index b88e7c569c0a09e5c8fa418cefc4b9af3ccca323..bdad44e84b9209b0805b46ddd4445d8aac1df027 100644 (file)
@@ -58,28 +58,26 @@ gf100_fifo_uevent_func = {
 void
 gf100_fifo_runlist_update(struct gf100_fifo *fifo)
 {
+       struct gf100_fifo_chan *chan;
        struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
        struct nvkm_device *device = subdev->device;
        struct nvkm_memory *cur;
-       int i, p;
+       int nr = 0;
 
        mutex_lock(&nv_subdev(fifo)->mutex);
        cur = fifo->runlist.mem[fifo->runlist.active];
        fifo->runlist.active = !fifo->runlist.active;
 
        nvkm_kmap(cur);
-       for (i = 0, p = 0; i < 128; i++) {
-               struct gf100_fifo_chan *chan = (void *)fifo->base.channel[i];
-               if (chan && chan->state == RUNNING) {
-                       nvkm_wo32(cur, p + 0, i);
-                       nvkm_wo32(cur, p + 4, 0x00000004);
-                       p += 8;
-               }
+       list_for_each_entry(chan, &fifo->chan, head) {
+               nvkm_wo32(cur, (nr * 8) + 0, chan->base.chid);
+               nvkm_wo32(cur, (nr * 8) + 4, 0x00000004);
+               nr++;
        }
        nvkm_done(cur);
 
        nvkm_wr32(device, 0x002270, nvkm_memory_addr(cur) >> 12);
-       nvkm_wr32(device, 0x002274, 0x01f00000 | (p >> 3));
+       nvkm_wr32(device, 0x002274, 0x01f00000 | nr);
 
        if (wait_event_timeout(fifo->runlist.wait,
                               !(nvkm_rd32(device, 0x00227c) & 0x00100000),
@@ -166,7 +164,8 @@ gf100_fifo_recover(struct gf100_fifo *fifo, struct nvkm_engine *engine,
        assert_spin_locked(&fifo->base.lock);
 
        nvkm_mask(device, 0x003004 + (chid * 0x08), 0x00000001, 0x00000000);
-       chan->state = KILLED;
+       list_del_init(&chan->head);
+       chan->killed = true;
 
        fifo->mask |= 1ULL << nv_engidx(engine);
        schedule_work(&fifo->fault);
@@ -198,11 +197,15 @@ gf100_fifo_intr_sched_ctxsw(struct gf100_fifo *fifo)
                (void)save;
 
                if (busy && unk0 && unk1) {
-                       if (!(chan = (void *)fifo->base.channel[chid]))
-                               continue;
-                       if (!(engine = gf100_fifo_engine(fifo, engn)))
-                               continue;
-                       gf100_fifo_recover(fifo, engine, chan);
+                       list_for_each_entry(chan, &fifo->chan, head) {
+                               if (chan->base.chid == chid) {
+                                       engine = gf100_fifo_engine(fifo, engn);
+                                       if (!engine)
+                                               break;
+                                       gf100_fifo_recover(fifo, engine, chan);
+                                       break;
+                               }
+                       }
                }
        }
        spin_unlock_irqrestore(&fifo->base.lock, flags);
@@ -343,7 +346,8 @@ gf100_fifo_intr_fault(struct gf100_fifo *fifo, int unit)
                   write ? "write" : "read", (u64)vahi << 32 | valo,
                   unit, eu ? eu->name : "", client, gpcid, ec ? ec->name : "",
                   reason, er ? er->name : "", chan ? chan->chid : -1,
-                  (u64)inst << 12,  nvkm_client_name(chan));
+                  (u64)inst << 12,
+                  chan ? chan->object.client->name : "unknown");
 
        if (engine && chan)
                gf100_fifo_recover(fifo, engine, (void *)chan);
@@ -369,6 +373,8 @@ gf100_fifo_intr_pbdma(struct gf100_fifo *fifo, int unit)
        u32 chid = nvkm_rd32(device, 0x040120 + (unit * 0x2000)) & 0x7f;
        u32 subc = (addr & 0x00070000) >> 16;
        u32 mthd = (addr & 0x00003ffc);
+       struct nvkm_fifo_chan *chan;
+       unsigned long flags;
        u32 show= stat;
        char msg[128];
 
@@ -381,11 +387,13 @@ gf100_fifo_intr_pbdma(struct gf100_fifo *fifo, int unit)
 
        if (show) {
                nvkm_snprintbf(msg, sizeof(msg), gf100_fifo_pbdma_intr, show);
-               nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d [%s] subc %d "
-                                  "mthd %04x data %08x\n",
-                          unit, show, msg, chid,
-                          nvkm_client_name_for_fifo_chid(&fifo->base, chid),
+               chan = nvkm_fifo_chan_chid(&fifo->base, chid, &flags);
+               nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d [%010llx %s] "
+                                  "subc %d mthd %04x data %08x\n",
+                          unit, show, msg, chid, chan ? chan->inst->addr : 0,
+                          chan ? chan->object.client->name : "unknown",
                           subc, mthd, data);
+               nvkm_fifo_chan_put(&fifo->base, flags, &chan);
        }
 
        nvkm_wr32(device, 0x0400c0 + (unit * 0x2000), 0x80600008);
@@ -579,6 +587,14 @@ gf100_fifo_dtor(struct nvkm_object *object)
        nvkm_fifo_destroy(&fifo->base);
 }
 
+static const struct nvkm_fifo_func
+gf100_fifo_func = {
+       .chan = {
+               &gf100_fifo_gpfifo_oclass,
+               NULL
+       },
+};
+
 static int
 gf100_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
                struct nvkm_oclass *oclass, void *data, u32 size,
@@ -594,6 +610,9 @@ gf100_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
        if (ret)
                return ret;
 
+       fifo->base.func = &gf100_fifo_func;
+
+       INIT_LIST_HEAD(&fifo->chan);
        INIT_WORK(&fifo->fault, gf100_fifo_recover_work);
 
        ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000,
@@ -625,8 +644,6 @@ gf100_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
 
        nv_subdev(fifo)->unit = 0x00000100;
        nv_subdev(fifo)->intr = gf100_fifo_intr;
-       nv_engine(fifo)->cclass = &gf100_fifo_cclass;
-       nv_engine(fifo)->sclass = gf100_fifo_sclass;
        return 0;
 }
 
index 5190bbc6e1a181a6cbc5bf976538578979137cb7..c649ca9b53e3ee2206ad865351a4073a636af00a 100644 (file)
@@ -1,10 +1,15 @@
 #ifndef __GF100_FIFO_H__
 #define __GF100_FIFO_H__
+#define gf100_fifo(p) container_of((p), struct gf100_fifo, base)
 #include "priv.h"
 
+#include <subdev/mmu.h>
+
 struct gf100_fifo {
        struct nvkm_fifo base;
 
+       struct list_head chan;
+
        struct work_struct fault;
        u64 mask;
 
index 9ab3fd40b7dd99881fac664615611d1f513846c7..e7f4679971942f08f3fea87f97e9838a4f6a3fc0 100644 (file)
 
 #include <nvif/class.h>
 
-#define _(a,b) { (a), ((1ULL << (a)) | (b)) }
-static const struct {
-       u64 subdev;
-       u64 mask;
-} fifo_engine[] = {
-       _(NVDEV_ENGINE_GR      , (1ULL << NVDEV_ENGINE_SW) |
-                                (1ULL << NVDEV_ENGINE_CE2)),
-       _(NVDEV_ENGINE_MSPDEC  , 0),
-       _(NVDEV_ENGINE_MSPPP   , 0),
-       _(NVDEV_ENGINE_MSVLD   , 0),
-       _(NVDEV_ENGINE_CE0     , 0),
-       _(NVDEV_ENGINE_CE1     , 0),
-       _(NVDEV_ENGINE_MSENC   , 0),
-};
-#undef _
-#define FIFO_ENGINE_NR ARRAY_SIZE(fifo_engine)
-
 static void
 gk104_fifo_uevent_fini(struct nvkm_event *event, int type, int index)
 {
@@ -76,28 +59,26 @@ void
 gk104_fifo_runlist_update(struct gk104_fifo *fifo, u32 engine)
 {
        struct gk104_fifo_engn *engn = &fifo->engine[engine];
+       struct gk104_fifo_chan *chan;
        struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
        struct nvkm_device *device = subdev->device;
        struct nvkm_memory *cur;
-       int i, p;
+       int nr = 0;
 
        mutex_lock(&nv_subdev(fifo)->mutex);
        cur = engn->runlist[engn->cur_runlist];
        engn->cur_runlist = !engn->cur_runlist;
 
        nvkm_kmap(cur);
-       for (i = 0, p = 0; i < fifo->base.max; i++) {
-               struct gk104_fifo_chan *chan = (void *)fifo->base.channel[i];
-               if (chan && chan->state == RUNNING && chan->engine == engine) {
-                       nvkm_wo32(cur, p + 0, i);
-                       nvkm_wo32(cur, p + 4, 0x00000000);
-                       p += 8;
-               }
+       list_for_each_entry(chan, &engn->chan, head) {
+               nvkm_wo32(cur, (nr * 8) + 0, chan->base.chid);
+               nvkm_wo32(cur, (nr * 8) + 4, 0x00000000);
+               nr++;
        }
        nvkm_done(cur);
 
        nvkm_wr32(device, 0x002270, nvkm_memory_addr(cur) >> 12);
-       nvkm_wr32(device, 0x002274, (engine << 20) | (p >> 3));
+       nvkm_wr32(device, 0x002274, (engine << 20) | nr);
 
        if (wait_event_timeout(engn->wait, !(nvkm_rd32(device, 0x002284 +
                               (engine * 0x08)) & 0x00100000),
@@ -106,31 +87,13 @@ gk104_fifo_runlist_update(struct gk104_fifo *fifo, u32 engine)
        mutex_unlock(&nv_subdev(fifo)->mutex);
 }
 
-static inline int
-gk104_fifo_engidx(struct gk104_fifo *fifo, u32 engn)
-{
-       switch (engn) {
-       case NVDEV_ENGINE_GR    :
-       case NVDEV_ENGINE_CE2   : engn = 0; break;
-       case NVDEV_ENGINE_MSVLD : engn = 1; break;
-       case NVDEV_ENGINE_MSPPP : engn = 2; break;
-       case NVDEV_ENGINE_MSPDEC: engn = 3; break;
-       case NVDEV_ENGINE_CE0   : engn = 4; break;
-       case NVDEV_ENGINE_CE1   : engn = 5; break;
-       case NVDEV_ENGINE_MSENC : engn = 6; break;
-       default:
-               return -1;
-       }
-
-       return engn;
-}
-
 static inline struct nvkm_engine *
 gk104_fifo_engine(struct gk104_fifo *fifo, u32 engn)
 {
-       if (engn >= ARRAY_SIZE(fifo_engine))
-               return NULL;
-       return nvkm_engine(fifo, fifo_engine[engn].subdev);
+       u64 subdevs = gk104_fifo_engine_subdev(engn);
+       if (subdevs)
+               return nvkm_engine(fifo, __ffs(subdevs));
+       return NULL;
 }
 
 static void
@@ -149,7 +112,7 @@ gk104_fifo_recover_work(struct work_struct *work)
        spin_unlock_irqrestore(&fifo->base.lock, flags);
 
        for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn))
-               engm |= 1 << gk104_fifo_engidx(fifo, engn);
+               engm |= 1 << gk104_fifo_subdev_engine(engn);
        nvkm_mask(device, 0x002630, engm, engm);
 
        for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn)) {
@@ -157,7 +120,7 @@ gk104_fifo_recover_work(struct work_struct *work)
                        nvkm_subdev_fini(&engine->subdev, false);
                        WARN_ON(nvkm_subdev_init(&engine->subdev));
                }
-               gk104_fifo_runlist_update(fifo, gk104_fifo_engidx(fifo, engn));
+               gk104_fifo_runlist_update(fifo, gk104_fifo_subdev_engine(engn));
        }
 
        nvkm_wr32(device, 0x00262c, engm);
@@ -177,7 +140,8 @@ gk104_fifo_recover(struct gk104_fifo *fifo, struct nvkm_engine *engine,
        assert_spin_locked(&fifo->base.lock);
 
        nvkm_mask(device, 0x800004 + (chid * 0x08), 0x00000800, 0x00000800);
-       chan->state = KILLED;
+       list_del_init(&chan->head);
+       chan->killed = true;
 
        fifo->mask |= 1ULL << nv_engidx(engine);
        schedule_work(&fifo->fault);
@@ -223,7 +187,7 @@ gk104_fifo_intr_sched_ctxsw(struct gk104_fifo *fifo)
        u32 engn;
 
        spin_lock_irqsave(&fifo->base.lock, flags);
-       for (engn = 0; engn < ARRAY_SIZE(fifo_engine); engn++) {
+       for (engn = 0; engn < ARRAY_SIZE(fifo->engine); engn++) {
                u32 stat = nvkm_rd32(device, 0x002640 + (engn * 0x04));
                u32 busy = (stat & 0x80000000);
                u32 next = (stat & 0x07ff0000) >> 16;
@@ -235,11 +199,15 @@ gk104_fifo_intr_sched_ctxsw(struct gk104_fifo *fifo)
                (void)save;
 
                if (busy && chsw) {
-                       if (!(chan = (void *)fifo->base.channel[chid]))
-                               continue;
-                       if (!(engine = gk104_fifo_engine(fifo, engn)))
-                               continue;
-                       gk104_fifo_recover(fifo, engine, chan);
+                       list_for_each_entry(chan, &fifo->engine[engn].chan, head) {
+                               if (chan->base.chid == chid) {
+                                       engine = gk104_fifo_engine(fifo, engn);
+                                       if (!engine)
+                                               break;
+                                       gk104_fifo_recover(fifo, engine, chan);
+                                       break;
+                               }
+                       }
                }
        }
        spin_unlock_irqrestore(&fifo->base.lock, flags);
@@ -444,7 +412,8 @@ gk104_fifo_intr_fault(struct gk104_fifo *fifo, int unit)
                   write ? "write" : "read", (u64)vahi << 32 | valo,
                   unit, eu ? eu->name : "", client, gpcid, ec ? ec->name : "",
                   reason, er ? er->name : "", chan ? chan->chid : -1,
-                  (u64)inst << 12, nvkm_client_name(chan));
+                  (u64)inst << 12,
+                  chan ? chan->object.client->name : "unknown");
 
        if (engine && chan)
                gk104_fifo_recover(fifo, engine, (void *)chan);
@@ -498,6 +467,8 @@ gk104_fifo_intr_pbdma_0(struct gk104_fifo *fifo, int unit)
        u32 subc = (addr & 0x00070000) >> 16;
        u32 mthd = (addr & 0x00003ffc);
        u32 show = stat;
+       struct nvkm_fifo_chan *chan;
+       unsigned long flags;
        char msg[128];
 
        if (stat & 0x00800000) {
@@ -510,11 +481,13 @@ gk104_fifo_intr_pbdma_0(struct gk104_fifo *fifo, int unit)
 
        if (show) {
                nvkm_snprintbf(msg, sizeof(msg), gk104_fifo_pbdma_intr_0, show);
-               nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d [%s] subc %d "
-                                  "mthd %04x data %08x\n",
-                          unit, show, msg, chid,
-                          nvkm_client_name_for_fifo_chid(&fifo->base, chid),
+               chan = nvkm_fifo_chan_chid(&fifo->base, chid, &flags);
+               nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d [%010llx %s] "
+                                  "subc %d mthd %04x data %08x\n",
+                          unit, show, msg, chid, chan ? chan->inst->addr : 0,
+                          chan ? chan->object.client->name : "unknown",
                           subc, mthd, data);
+               nvkm_fifo_chan_put(&fifo->base, flags, &chan);
        }
 
        nvkm_wr32(device, 0x040108 + (unit * 0x2000), stat);
@@ -722,7 +695,7 @@ gk104_fifo_dtor(struct nvkm_object *object)
        nvkm_vm_put(&fifo->user.bar);
        nvkm_memory_del(&fifo->user.mem);
 
-       for (i = 0; i < FIFO_ENGINE_NR; i++) {
+       for (i = 0; i < ARRAY_SIZE(fifo->engine); i++) {
                nvkm_memory_del(&fifo->engine[i].runlist[1]);
                nvkm_memory_del(&fifo->engine[i].runlist[0]);
        }
@@ -730,6 +703,14 @@ gk104_fifo_dtor(struct nvkm_object *object)
        nvkm_fifo_destroy(&fifo->base);
 }
 
+static const struct nvkm_fifo_func
+gk104_fifo_func = {
+       .chan = {
+               &gk104_fifo_gpfifo_oclass,
+               NULL
+       },
+};
+
 int
 gk104_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
                struct nvkm_oclass *oclass, void *data, u32 size,
@@ -747,9 +728,11 @@ gk104_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
        if (ret)
                return ret;
 
+       fifo->base.func = &gk104_fifo_func;
+
        INIT_WORK(&fifo->fault, gk104_fifo_recover_work);
 
-       for (i = 0; i < FIFO_ENGINE_NR; i++) {
+       for (i = 0; i < ARRAY_SIZE(fifo->engine); i++) {
                ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
                                      0x8000, 0x1000, false,
                                      &fifo->engine[i].runlist[0]);
@@ -763,6 +746,7 @@ gk104_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
                        return ret;
 
                init_waitqueue_head(&fifo->engine[i].wait);
+               INIT_LIST_HEAD(&fifo->engine[i].chan);
        }
 
        ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
@@ -783,8 +767,6 @@ gk104_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
 
        nv_subdev(fifo)->unit = 0x00000100;
        nv_subdev(fifo)->intr = gk104_fifo_intr;
-       nv_engine(fifo)->cclass = &gk104_fifo_cclass;
-       nv_engine(fifo)->sclass = gk104_fifo_sclass;
        return 0;
 }
 
index b71abef84349bdcc345448d29df6ed153147b4b6..1103e6b1ee5a62878ad38d0a212b6403767533d2 100644 (file)
@@ -1,11 +1,15 @@
 #ifndef __GK104_FIFO_H__
 #define __GK104_FIFO_H__
+#define gk104_fifo(p) container_of((p), struct gk104_fifo, base)
 #include "priv.h"
 
+#include <subdev/mmu.h>
+
 struct gk104_fifo_engn {
        struct nvkm_memory *runlist[2];
        int cur_runlist;
        wait_queue_head_t wait;
+       struct list_head chan;
 };
 
 struct gk104_fifo {
@@ -38,4 +42,42 @@ void gk104_fifo_runlist_update(struct gk104_fifo *, u32 engine);
 int  gm204_fifo_ctor(struct nvkm_object *, struct nvkm_object *,
                    struct nvkm_oclass *, void *, u32,
                    struct nvkm_object **);
+
+static inline u64
+gk104_fifo_engine_subdev(int engine)
+{
+       switch (engine) {
+       case 0: return (1ULL << NVDEV_ENGINE_GR) |
+                      (1ULL << NVDEV_ENGINE_SW) |
+                      (1ULL << NVDEV_ENGINE_CE2);
+       case 1: return (1ULL << NVDEV_ENGINE_MSPDEC);
+       case 2: return (1ULL << NVDEV_ENGINE_MSPPP);
+       case 3: return (1ULL << NVDEV_ENGINE_MSVLD);
+       case 4: return (1ULL << NVDEV_ENGINE_CE0);
+       case 5: return (1ULL << NVDEV_ENGINE_CE1);
+       case 6: return (1ULL << NVDEV_ENGINE_MSENC);
+       default:
+               WARN_ON(1);
+               return 0;
+       }
+}
+
+static inline int
+gk104_fifo_subdev_engine(int subdev)
+{
+       switch (subdev) {
+       case NVDEV_ENGINE_GR:
+       case NVDEV_ENGINE_SW:
+       case NVDEV_ENGINE_CE2   : return 0;
+       case NVDEV_ENGINE_MSPDEC: return 1;
+       case NVDEV_ENGINE_MSPPP : return 2;
+       case NVDEV_ENGINE_MSVLD : return 3;
+       case NVDEV_ENGINE_CE0   : return 4;
+       case NVDEV_ENGINE_CE1   : return 5;
+       case NVDEV_ENGINE_MSENC : return 6;
+       default:
+               WARN_ON(1);
+               return 0;
+       }
+}
 #endif
index 2367b4f81a91254791c7307fb63054a0e7ea29ed..18c68ac741a0a40bb2d60ebe99b5b9f907df6556 100644 (file)
 #include "gk104.h"
 #include "changk104.h"
 
+static const struct nvkm_fifo_func
+gm204_fifo_func = {
+       .chan = {
+               &gm204_fifo_gpfifo_oclass,
+               NULL
+       },
+};
+
 int
 gm204_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
                struct nvkm_oclass *oclass, void *data, u32 size,
@@ -32,7 +40,7 @@ gm204_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
        int ret = gk104_fifo_ctor(parent, engine, oclass, data, size, pobject);
        if (ret == 0) {
                struct gk104_fifo *fifo = (void *)*pobject;
-               nv_engine(fifo)->sclass = gm204_fifo_sclass;
+               fifo->base.func = &gm204_fifo_func;
        }
        return ret;
 }
index fd11e0afec2566811518e55e213d6dfca3134281..820132363f68f61c7cca40e2bf7c640796db17ce 100644 (file)
 #include <nvif/unpack.h>
 
 static int
-g84_fifo_chan_ctor_ind(struct nvkm_object *parent, struct nvkm_object *engine,
-                      struct nvkm_oclass *oclass, void *data, u32 size,
-                      struct nvkm_object **pobject)
+g84_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
+                   void *data, u32 size, struct nvkm_object **pobject)
 {
+       struct nvkm_object *parent = oclass->parent;
        union {
                struct nv50_channel_gpfifo_v0 v0;
        } *args = data;
-       struct nvkm_device *device = parent->engine->subdev.device;
-       struct nv50_fifo_base *base = (void *)parent;
+       struct nv50_fifo *fifo = nv50_fifo(base);
        struct nv50_fifo_chan *chan;
        u64 ioffset, ilength;
        int ret;
@@ -50,73 +49,46 @@ g84_fifo_chan_ctor_ind(struct nvkm_object *parent, struct nvkm_object *engine,
                                   "ilength %08x\n",
                           args->v0.version, args->v0.vm, args->v0.pushbuf,
                           args->v0.ioffset, args->v0.ilength);
-               if (args->v0.vm)
-                       return -ENOENT;
+               if (!args->v0.pushbuf)
+                       return -EINVAL;
        } else
                return ret;
 
-       ret = nvkm_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
-                                      0x2000, args->v0.pushbuf,
-                                      (1ULL << NVDEV_ENGINE_DMAOBJ) |
-                                      (1ULL << NVDEV_ENGINE_SW) |
-                                      (1ULL << NVDEV_ENGINE_GR) |
-                                      (1ULL << NVDEV_ENGINE_MPEG) |
-                                      (1ULL << NVDEV_ENGINE_ME) |
-                                      (1ULL << NVDEV_ENGINE_VP) |
-                                      (1ULL << NVDEV_ENGINE_CIPHER) |
-                                      (1ULL << NVDEV_ENGINE_SEC) |
-                                      (1ULL << NVDEV_ENGINE_BSP) |
-                                      (1ULL << NVDEV_ENGINE_MSVLD) |
-                                      (1ULL << NVDEV_ENGINE_MSPDEC) |
-                                      (1ULL << NVDEV_ENGINE_MSPPP) |
-                                      (1ULL << NVDEV_ENGINE_CE0) |
-                                      (1ULL << NVDEV_ENGINE_VIC), &chan);
-       *pobject = nv_object(chan);
-       if (ret)
-               return ret;
-
-       chan->base.inst = base->base.gpuobj.addr;
-       args->v0.chid = chan->base.chid;
+       if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
+               return -ENOMEM;
+       *pobject = &chan->base.object;
 
-       ret = nvkm_ramht_new(device, 0x8000, 16, &base->base.gpuobj,
-                            &chan->ramht);
+       ret = g84_fifo_chan_ctor(fifo, args->v0.vm, args->v0.pushbuf,
+                                oclass, chan);
        if (ret)
                return ret;
 
-       nv_parent(chan)->context_attach = g84_fifo_context_attach;
-       nv_parent(chan)->context_detach = g84_fifo_context_detach;
-       nv_parent(chan)->object_attach = g84_fifo_object_attach;
-       nv_parent(chan)->object_detach = nv50_fifo_object_detach;
-
+       args->v0.chid = chan->base.chid;
        ioffset = args->v0.ioffset;
        ilength = order_base_2(args->v0.ilength / 8);
 
-       nvkm_kmap(base->ramfc);
-       nvkm_wo32(base->ramfc, 0x3c, 0x403f6078);
-       nvkm_wo32(base->ramfc, 0x44, 0x01003fff);
-       nvkm_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4);
-       nvkm_wo32(base->ramfc, 0x50, lower_32_bits(ioffset));
-       nvkm_wo32(base->ramfc, 0x54, upper_32_bits(ioffset) | (ilength << 16));
-       nvkm_wo32(base->ramfc, 0x60, 0x7fffffff);
-       nvkm_wo32(base->ramfc, 0x78, 0x00000000);
-       nvkm_wo32(base->ramfc, 0x7c, 0x30000001);
-       nvkm_wo32(base->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) |
+       nvkm_kmap(chan->ramfc);
+       nvkm_wo32(chan->ramfc, 0x3c, 0x403f6078);
+       nvkm_wo32(chan->ramfc, 0x44, 0x01003fff);
+       nvkm_wo32(chan->ramfc, 0x48, chan->base.push->node->offset >> 4);
+       nvkm_wo32(chan->ramfc, 0x50, lower_32_bits(ioffset));
+       nvkm_wo32(chan->ramfc, 0x54, upper_32_bits(ioffset) | (ilength << 16));
+       nvkm_wo32(chan->ramfc, 0x60, 0x7fffffff);
+       nvkm_wo32(chan->ramfc, 0x78, 0x00000000);
+       nvkm_wo32(chan->ramfc, 0x7c, 0x30000001);
+       nvkm_wo32(chan->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) |
                                     (4 << 24) /* SEARCH_FULL */ |
                                     (chan->ramht->gpuobj->node->offset >> 4));
-       nvkm_wo32(base->ramfc, 0x88, base->cache->addr >> 10);
-       nvkm_wo32(base->ramfc, 0x98, nv_gpuobj(base)->addr >> 12);
-       nvkm_done(base->ramfc);
+       nvkm_wo32(chan->ramfc, 0x88, chan->cache->addr >> 10);
+       nvkm_wo32(chan->ramfc, 0x98, chan->base.inst->addr >> 12);
+       nvkm_done(chan->ramfc);
        return 0;
 }
 
-struct nvkm_ofuncs
-g84_fifo_ofuncs_ind = {
-       .ctor = g84_fifo_chan_ctor_ind,
-       .dtor = nv50_fifo_chan_dtor,
-       .init = g84_fifo_chan_init,
-       .fini = nv50_fifo_chan_fini,
-       .map  = _nvkm_fifo_channel_map,
-       .rd32 = _nvkm_fifo_channel_rd32,
-       .wr32 = _nvkm_fifo_channel_wr32,
-       .ntfy = _nvkm_fifo_channel_ntfy
+const struct nvkm_fifo_chan_oclass
+g84_fifo_gpfifo_oclass = {
+       .base.oclass = G82_CHANNEL_GPFIFO,
+       .base.minver = 0,
+       .base.maxver = 0,
+       .ctor = g84_fifo_gpfifo_new,
 };
index 7fd6401ca905fd8c3d2b653034be02397ccdedee..eb9195a6f375f054472937307f0db137493f04b6 100644 (file)
 #include <nvif/class.h>
 #include <nvif/unpack.h>
 
-static int
-gf100_fifo_context_detach(struct nvkm_object *parent, bool suspend,
-                         struct nvkm_object *object)
+static u32
+gf100_fifo_gpfifo_engine_addr(struct nvkm_engine *engine)
 {
-       struct gf100_fifo *fifo = (void *)parent->engine;
-       struct gf100_fifo_base *base = (void *)parent->parent;
-       struct gf100_fifo_chan *chan = (void *)parent;
-       struct nvkm_gpuobj *engn = &base->base.gpuobj;
-       struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
-       struct nvkm_device *device = subdev->device;
-       u32 addr;
-
-       switch (nv_engidx(object->engine)) {
+       switch (engine->subdev.index) {
        case NVDEV_ENGINE_SW    : return 0;
-       case NVDEV_ENGINE_GR    : addr = 0x0210; break;
-       case NVDEV_ENGINE_CE0   : addr = 0x0230; break;
-       case NVDEV_ENGINE_CE1   : addr = 0x0240; break;
-       case NVDEV_ENGINE_MSVLD : addr = 0x0270; break;
-       case NVDEV_ENGINE_MSPDEC: addr = 0x0250; break;
-       case NVDEV_ENGINE_MSPPP : addr = 0x0260; break;
+       case NVDEV_ENGINE_GR    : return 0x0210;
+       case NVDEV_ENGINE_CE0   : return 0x0230;
+       case NVDEV_ENGINE_CE1   : return 0x0240;
+       case NVDEV_ENGINE_MSPDEC: return 0x0250;
+       case NVDEV_ENGINE_MSPPP : return 0x0260;
+       case NVDEV_ENGINE_MSVLD : return 0x0270;
        default:
-               return -EINVAL;
+               WARN_ON(1);
+               return 0;
        }
+}
+
+static int
+gf100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base,
+                             struct nvkm_engine *engine, bool suspend)
+{
+       const u32 offset = gf100_fifo_gpfifo_engine_addr(engine);
+       struct gf100_fifo_chan *chan = gf100_fifo_chan(base);
+       struct nvkm_subdev *subdev = &chan->fifo->base.engine.subdev;
+       struct nvkm_device *device = subdev->device;
+       struct nvkm_gpuobj *inst = chan->base.inst;
+       int ret = 0;
 
        nvkm_wr32(device, 0x002634, chan->base.chid);
        if (nvkm_msec(device, 2000,
@@ -60,143 +64,197 @@ gf100_fifo_context_detach(struct nvkm_object *parent, bool suspend,
                        break;
        ) < 0) {
                nvkm_error(subdev, "channel %d [%s] kick timeout\n",
-                          chan->base.chid, nvkm_client_name(chan));
+                          chan->base.chid, chan->base.object.client->name);
+               ret = -EBUSY;
                if (suspend)
-                       return -EBUSY;
+                       return ret;
+       }
+
+       if (offset) {
+               nvkm_kmap(inst);
+               nvkm_wo32(inst, offset + 0x00, 0x00000000);
+               nvkm_wo32(inst, offset + 0x04, 0x00000000);
+               nvkm_done(inst);
+       }
+
+       return ret;
+}
+
+static int
+gf100_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base,
+                             struct nvkm_engine *engine)
+{
+       const u32 offset = gf100_fifo_gpfifo_engine_addr(engine);
+       struct gf100_fifo_chan *chan = gf100_fifo_chan(base);
+       struct nvkm_gpuobj *inst = chan->base.inst;
+
+       if (offset) {
+               u64 addr = chan->engn[engine->subdev.index].vma.offset;
+               nvkm_kmap(inst);
+               nvkm_wo32(inst, offset + 0x00, lower_32_bits(addr) | 4);
+               nvkm_wo32(inst, offset + 0x04, upper_32_bits(addr));
+               nvkm_done(inst);
        }
 
-       nvkm_kmap(engn);
-       nvkm_wo32(engn, addr + 0x00, 0x00000000);
-       nvkm_wo32(engn, addr + 0x04, 0x00000000);
-       nvkm_done(engn);
        return 0;
 }
 
+static void
+gf100_fifo_gpfifo_engine_dtor(struct nvkm_fifo_chan *base,
+                             struct nvkm_engine *engine)
+{
+       struct gf100_fifo_chan *chan = gf100_fifo_chan(base);
+       nvkm_gpuobj_unmap(&chan->engn[engine->subdev.index].vma);
+       nvkm_gpuobj_del(&chan->engn[engine->subdev.index].inst);
+}
+
 static int
-gf100_fifo_context_attach(struct nvkm_object *parent,
-                         struct nvkm_object *object)
+gf100_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *base,
+                             struct nvkm_engine *engine,
+                             struct nvkm_object *object)
 {
-       struct gf100_fifo_base *base = (void *)parent->parent;
-       struct nvkm_gpuobj *engn = &base->base.gpuobj;
-       struct nvkm_engctx *ectx = (void *)object;
-       u32 addr;
+       struct gf100_fifo_chan *chan = gf100_fifo_chan(base);
+       int engn = engine->subdev.index;
        int ret;
 
-       switch (nv_engidx(object->engine)) {
-       case NVDEV_ENGINE_SW    : return 0;
-       case NVDEV_ENGINE_GR    : addr = 0x0210; break;
-       case NVDEV_ENGINE_CE0   : addr = 0x0230; break;
-       case NVDEV_ENGINE_CE1   : addr = 0x0240; break;
-       case NVDEV_ENGINE_MSVLD : addr = 0x0270; break;
-       case NVDEV_ENGINE_MSPDEC: addr = 0x0250; break;
-       case NVDEV_ENGINE_MSPPP : addr = 0x0260; break;
-       default:
-               return -EINVAL;
-       }
-
-       if (!ectx->vma.node) {
-               ret = nvkm_gpuobj_map(nv_gpuobj(ectx), base->vm,
-                                     NV_MEM_ACCESS_RW, &ectx->vma);
-               if (ret)
-                       return ret;
+       if (!gf100_fifo_gpfifo_engine_addr(engine))
+               return 0;
 
-               nv_engctx(ectx)->addr = nv_gpuobj(base)->addr >> 12;
+       if (object->oclass) {
+               return nvkm_gpuobj_map(nv_gpuobj(object), chan->vm,
+                                      NV_MEM_ACCESS_RW,
+                                      &chan->engn[engn].vma);
        }
 
-       nvkm_kmap(engn);
-       nvkm_wo32(engn, addr + 0x00, lower_32_bits(ectx->vma.offset) | 4);
-       nvkm_wo32(engn, addr + 0x04, upper_32_bits(ectx->vma.offset));
-       nvkm_done(engn);
-       return 0;
+       ret = nvkm_object_bind(object, NULL, 0, &chan->engn[engn].inst);
+       if (ret)
+               return ret;
+
+       return nvkm_gpuobj_map(chan->engn[engn].inst, chan->vm,
+                              NV_MEM_ACCESS_RW, &chan->engn[engn].vma);
 }
 
-static int
-gf100_fifo_chan_fini(struct nvkm_object *object, bool suspend)
+static void
+gf100_fifo_gpfifo_fini(struct nvkm_fifo_chan *base)
 {
-       struct gf100_fifo *fifo = (void *)object->engine;
-       struct gf100_fifo_chan *chan = (void *)object;
+       struct gf100_fifo_chan *chan = gf100_fifo_chan(base);
+       struct gf100_fifo *fifo = chan->fifo;
        struct nvkm_device *device = fifo->base.engine.subdev.device;
-       u32 chid = chan->base.chid;
+       u32 coff = chan->base.chid * 8;
 
-       if (chan->state == RUNNING && (chan->state = STOPPED) == STOPPED) {
-               nvkm_mask(device, 0x003004 + (chid * 8), 0x00000001, 0x00000000);
+       if (!list_empty(&chan->head) && !chan->killed) {
+               list_del_init(&chan->head);
+               nvkm_mask(device, 0x003004 + coff, 0x00000001, 0x00000000);
                gf100_fifo_runlist_update(fifo);
        }
 
        gf100_fifo_intr_engine(fifo);
 
-       nvkm_wr32(device, 0x003000 + (chid * 8), 0x00000000);
-       return nvkm_fifo_channel_fini(&chan->base, suspend);
+       nvkm_wr32(device, 0x003000 + coff, 0x00000000);
 }
 
-static int
-gf100_fifo_chan_init(struct nvkm_object *object)
+static void
+gf100_fifo_gpfifo_init(struct nvkm_fifo_chan *base)
 {
-       struct nvkm_gpuobj *base = nv_gpuobj(object->parent);
-       struct gf100_fifo *fifo = (void *)object->engine;
-       struct gf100_fifo_chan *chan = (void *)object;
+       struct gf100_fifo_chan *chan = gf100_fifo_chan(base);
+       struct gf100_fifo *fifo = chan->fifo;
        struct nvkm_device *device = fifo->base.engine.subdev.device;
-       u32 chid = chan->base.chid;
-       int ret;
-
-       ret = nvkm_fifo_channel_init(&chan->base);
-       if (ret)
-               return ret;
+       u32 addr = chan->base.inst->addr >> 12;
+       u32 coff = chan->base.chid * 8;
 
-       nvkm_wr32(device, 0x003000 + (chid * 8), 0xc0000000 | base->addr >> 12);
+       nvkm_wr32(device, 0x003000 + coff, 0xc0000000 | addr);
 
-       if (chan->state == STOPPED && (chan->state = RUNNING) == RUNNING) {
-               nvkm_wr32(device, 0x003004 + (chid * 8), 0x001f0001);
+       if (list_empty(&chan->head) && !chan->killed) {
+               list_add_tail(&chan->head, &fifo->chan);
+               nvkm_wr32(device, 0x003004 + coff, 0x001f0001);
                gf100_fifo_runlist_update(fifo);
        }
+}
 
-       return 0;
+static void *
+gf100_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base)
+{
+       struct gf100_fifo_chan *chan = gf100_fifo_chan(base);
+       nvkm_vm_ref(NULL, &chan->vm, chan->pgd);
+       nvkm_gpuobj_del(&chan->pgd);
+       return chan;
 }
 
+static const struct nvkm_fifo_chan_func
+gf100_fifo_gpfifo_func = {
+       .dtor = gf100_fifo_gpfifo_dtor,
+       .init = gf100_fifo_gpfifo_init,
+       .fini = gf100_fifo_gpfifo_fini,
+       .ntfy = g84_fifo_chan_ntfy,
+       .engine_ctor = gf100_fifo_gpfifo_engine_ctor,
+       .engine_dtor = gf100_fifo_gpfifo_engine_dtor,
+       .engine_init = gf100_fifo_gpfifo_engine_init,
+       .engine_fini = gf100_fifo_gpfifo_engine_fini,
+};
+
 static int
-gf100_fifo_chan_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-                    struct nvkm_oclass *oclass, void *data, u32 size,
-                    struct nvkm_object **pobject)
+gf100_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
+                     void *data, u32 size, struct nvkm_object **pobject)
 {
        union {
                struct fermi_channel_gpfifo_v0 v0;
        } *args = data;
-       struct gf100_fifo *fifo = (void *)engine;
-       struct gf100_fifo_base *base = (void *)parent;
+       struct gf100_fifo *fifo = gf100_fifo(base);
+       struct nvkm_device *device = fifo->base.engine.subdev.device;
+       struct nvkm_object *parent = oclass->parent;
        struct gf100_fifo_chan *chan;
-       struct nvkm_gpuobj *ramfc = &base->base.gpuobj;
        u64 usermem, ioffset, ilength;
        int ret, i;
 
        nvif_ioctl(parent, "create channel gpfifo size %d\n", size);
        if (nvif_unpack(args->v0, 0, 0, false)) {
-               nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx"
+               nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx "
                                   "ioffset %016llx ilength %08x\n",
                           args->v0.version, args->v0.vm, args->v0.ioffset,
                           args->v0.ilength);
-               if (args->v0.vm)
-                       return -ENOENT;
        } else
                return ret;
 
-       ret = nvkm_fifo_channel_create(parent, engine, oclass, 1,
-                                      fifo->user.bar.offset, 0x1000, 0,
-                                      (1ULL << NVDEV_ENGINE_SW) |
-                                      (1ULL << NVDEV_ENGINE_GR) |
-                                      (1ULL << NVDEV_ENGINE_CE0) |
-                                      (1ULL << NVDEV_ENGINE_CE1) |
-                                      (1ULL << NVDEV_ENGINE_MSVLD) |
-                                      (1ULL << NVDEV_ENGINE_MSPDEC) |
-                                      (1ULL << NVDEV_ENGINE_MSPPP), &chan);
-       *pobject = nv_object(chan);
+       /* allocate channel */
+       if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
+               return -ENOMEM;
+       *pobject = &chan->base.object;
+       chan->fifo = fifo;
+       INIT_LIST_HEAD(&chan->head);
+
+       ret = nvkm_fifo_chan_ctor(&gf100_fifo_gpfifo_func, &fifo->base,
+                                 0x1000, 0x1000, true, args->v0.vm, 0,
+                                 (1ULL << NVDEV_ENGINE_CE0) |
+                                 (1ULL << NVDEV_ENGINE_CE1) |
+                                 (1ULL << NVDEV_ENGINE_GR) |
+                                 (1ULL << NVDEV_ENGINE_MSPDEC) |
+                                 (1ULL << NVDEV_ENGINE_MSPPP) |
+                                 (1ULL << NVDEV_ENGINE_MSVLD) |
+                                 (1ULL << NVDEV_ENGINE_SW),
+                                 1, fifo->user.bar.offset, 0x1000,
+                                 oclass, &chan->base);
        if (ret)
                return ret;
 
-       chan->base.inst = base->base.gpuobj.addr;
        args->v0.chid = chan->base.chid;
 
-       nv_parent(chan)->context_attach = gf100_fifo_context_attach;
-       nv_parent(chan)->context_detach = gf100_fifo_context_detach;
+       /* page directory */
+       ret = nvkm_gpuobj_new(device, 0x10000, 0x1000, false, NULL, &chan->pgd);
+       if (ret)
+               return ret;
+
+       nvkm_kmap(chan->base.inst);
+       nvkm_wo32(chan->base.inst, 0x0200, lower_32_bits(chan->pgd->addr));
+       nvkm_wo32(chan->base.inst, 0x0204, upper_32_bits(chan->pgd->addr));
+       nvkm_wo32(chan->base.inst, 0x0208, 0xffffffff);
+       nvkm_wo32(chan->base.inst, 0x020c, 0x000000ff);
+       nvkm_done(chan->base.inst);
+
+       ret = nvkm_vm_ref(chan->base.vm, &chan->vm, chan->pgd);
+       if (ret)
+               return ret;
+
+       /* clear channel control registers */
 
        usermem = chan->base.chid * 0x1000;
        ioffset = args->v0.ioffset;
@@ -208,97 +266,33 @@ gf100_fifo_chan_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
        nvkm_done(fifo->user.mem);
        usermem = nvkm_memory_addr(fifo->user.mem) + usermem;
 
-       nvkm_kmap(ramfc);
-       nvkm_wo32(ramfc, 0x08, lower_32_bits(usermem));
-       nvkm_wo32(ramfc, 0x0c, upper_32_bits(usermem));
-       nvkm_wo32(ramfc, 0x10, 0x0000face);
-       nvkm_wo32(ramfc, 0x30, 0xfffff902);
-       nvkm_wo32(ramfc, 0x48, lower_32_bits(ioffset));
-       nvkm_wo32(ramfc, 0x4c, upper_32_bits(ioffset) | (ilength << 16));
-       nvkm_wo32(ramfc, 0x54, 0x00000002);
-       nvkm_wo32(ramfc, 0x84, 0x20400000);
-       nvkm_wo32(ramfc, 0x94, 0x30000001);
-       nvkm_wo32(ramfc, 0x9c, 0x00000100);
-       nvkm_wo32(ramfc, 0xa4, 0x1f1f1f1f);
-       nvkm_wo32(ramfc, 0xa8, 0x1f1f1f1f);
-       nvkm_wo32(ramfc, 0xac, 0x0000001f);
-       nvkm_wo32(ramfc, 0xb8, 0xf8000000);
-       nvkm_wo32(ramfc, 0xf8, 0x10003080); /* 0x002310 */
-       nvkm_wo32(ramfc, 0xfc, 0x10000010); /* 0x002350 */
-       nvkm_done(ramfc);
-       return 0;
-}
-
-static struct nvkm_ofuncs
-gf100_fifo_ofuncs = {
-       .ctor = gf100_fifo_chan_ctor,
-       .dtor = _nvkm_fifo_channel_dtor,
-       .init = gf100_fifo_chan_init,
-       .fini = gf100_fifo_chan_fini,
-       .map  = _nvkm_fifo_channel_map,
-       .rd32 = _nvkm_fifo_channel_rd32,
-       .wr32 = _nvkm_fifo_channel_wr32,
-       .ntfy = _nvkm_fifo_channel_ntfy
-};
-
-struct nvkm_oclass
-gf100_fifo_sclass[] = {
-       { FERMI_CHANNEL_GPFIFO, &gf100_fifo_ofuncs },
-       {}
-};
-
-static int
-gf100_fifo_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-                       struct nvkm_oclass *oclass, void *data, u32 size,
-                       struct nvkm_object **pobject)
-{
-       struct nvkm_device *device = nv_engine(engine)->subdev.device;
-       struct gf100_fifo_base *base;
-       int ret;
-
-       ret = nvkm_fifo_context_create(parent, engine, oclass, NULL, 0x1000,
-                                      0x1000, NVOBJ_FLAG_ZERO_ALLOC |
-                                      NVOBJ_FLAG_HEAP, &base);
-       *pobject = nv_object(base);
-       if (ret)
-               return ret;
-
-       ret = nvkm_gpuobj_new(device, 0x10000, 0x1000, false, NULL, &base->pgd);
-       if (ret)
-               return ret;
-
-       nvkm_kmap(&base->base.gpuobj);
-       nvkm_wo32(&base->base.gpuobj, 0x0200, lower_32_bits(base->pgd->addr));
-       nvkm_wo32(&base->base.gpuobj, 0x0204, upper_32_bits(base->pgd->addr));
-       nvkm_wo32(&base->base.gpuobj, 0x0208, 0xffffffff);
-       nvkm_wo32(&base->base.gpuobj, 0x020c, 0x000000ff);
-       nvkm_done(&base->base.gpuobj);
-
-       ret = nvkm_vm_ref(nvkm_client(parent)->vm, &base->vm, base->pgd);
-       if (ret)
-               return ret;
-
+       /* RAMFC */
+       nvkm_kmap(chan->base.inst);
+       nvkm_wo32(chan->base.inst, 0x08, lower_32_bits(usermem));
+       nvkm_wo32(chan->base.inst, 0x0c, upper_32_bits(usermem));
+       nvkm_wo32(chan->base.inst, 0x10, 0x0000face);
+       nvkm_wo32(chan->base.inst, 0x30, 0xfffff902);
+       nvkm_wo32(chan->base.inst, 0x48, lower_32_bits(ioffset));
+       nvkm_wo32(chan->base.inst, 0x4c, upper_32_bits(ioffset) |
+                                        (ilength << 16));
+       nvkm_wo32(chan->base.inst, 0x54, 0x00000002);
+       nvkm_wo32(chan->base.inst, 0x84, 0x20400000);
+       nvkm_wo32(chan->base.inst, 0x94, 0x30000001);
+       nvkm_wo32(chan->base.inst, 0x9c, 0x00000100);
+       nvkm_wo32(chan->base.inst, 0xa4, 0x1f1f1f1f);
+       nvkm_wo32(chan->base.inst, 0xa8, 0x1f1f1f1f);
+       nvkm_wo32(chan->base.inst, 0xac, 0x0000001f);
+       nvkm_wo32(chan->base.inst, 0xb8, 0xf8000000);
+       nvkm_wo32(chan->base.inst, 0xf8, 0x10003080); /* 0x002310 */
+       nvkm_wo32(chan->base.inst, 0xfc, 0x10000010); /* 0x002350 */
+       nvkm_done(chan->base.inst);
        return 0;
 }
 
-static void
-gf100_fifo_context_dtor(struct nvkm_object *object)
-{
-       struct gf100_fifo_base *base = (void *)object;
-       nvkm_vm_ref(NULL, &base->vm, base->pgd);
-       nvkm_gpuobj_del(&base->pgd);
-       nvkm_fifo_context_destroy(&base->base);
-}
-
-struct nvkm_oclass
-gf100_fifo_cclass = {
-       .handle = NV_ENGCTX(FIFO, 0xc0),
-       .ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = gf100_fifo_context_ctor,
-               .dtor = gf100_fifo_context_dtor,
-               .init = _nvkm_fifo_context_init,
-               .fini = _nvkm_fifo_context_fini,
-               .rd32 = _nvkm_fifo_context_rd32,
-               .wr32 = _nvkm_fifo_context_wr32,
-       },
+const struct nvkm_fifo_chan_oclass
+gf100_fifo_gpfifo_oclass = {
+       .base.oclass = FERMI_CHANNEL_GPFIFO,
+       .base.minver = 0,
+       .base.maxver = 0,
+       .ctor = gf100_fifo_gpfifo_new,
 };
index 264c9705bccc551f083903af19be7af7b11e48aa..2595cf92ff8048cb2e447c6c6f27e1c677e83323 100644 (file)
 #include <nvif/class.h>
 #include <nvif/unpack.h>
 
-#define _(a,b) { (a), ((1ULL << (a)) | (b)) }
-static const struct {
-       u64 subdev;
-       u64 mask;
-} fifo_engine[] = {
-       _(NVDEV_ENGINE_GR      , (1ULL << NVDEV_ENGINE_SW) |
-                                (1ULL << NVDEV_ENGINE_CE2)),
-       _(NVDEV_ENGINE_MSPDEC  , 0),
-       _(NVDEV_ENGINE_MSPPP   , 0),
-       _(NVDEV_ENGINE_MSVLD   , 0),
-       _(NVDEV_ENGINE_CE0     , 0),
-       _(NVDEV_ENGINE_CE1     , 0),
-       _(NVDEV_ENGINE_MSENC   , 0),
-};
-#undef _
-#define FIFO_ENGINE_NR ARRAY_SIZE(fifo_engine)
-
 static int
-gk104_fifo_chan_kick(struct gk104_fifo_chan *chan)
+gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan)
 {
-       struct nvkm_object *obj = (void *)chan;
-       struct gk104_fifo *fifo = (void *)obj->engine;
+       struct gk104_fifo *fifo = chan->fifo;
        struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
        struct nvkm_device *device = subdev->device;
+       struct nvkm_client *client = chan->base.object.client;
 
        nvkm_wr32(device, 0x002634, chan->base.chid);
        if (nvkm_msec(device, 2000,
@@ -62,198 +45,249 @@ gk104_fifo_chan_kick(struct gk104_fifo_chan *chan)
                        break;
        ) < 0) {
                nvkm_error(subdev, "channel %d [%s] kick timeout\n",
-                          chan->base.chid, nvkm_client_name(chan));
+                          chan->base.chid, client->name);
                return -EBUSY;
        }
 
        return 0;
 }
 
-static int
-gk104_fifo_context_detach(struct nvkm_object *parent, bool suspend,
-                         struct nvkm_object *object)
+static u32
+gk104_fifo_gpfifo_engine_addr(struct nvkm_engine *engine)
 {
-       struct gk104_fifo_base *base = (void *)parent->parent;
-       struct gk104_fifo_chan *chan = (void *)parent;
-       struct nvkm_gpuobj *engn = &base->base.gpuobj;
-       u32 addr;
-       int ret;
-
-       switch (nv_engidx(object->engine)) {
-       case NVDEV_ENGINE_SW    : return 0;
+       switch (engine->subdev.index) {
+       case NVDEV_ENGINE_SW    :
        case NVDEV_ENGINE_CE0   :
        case NVDEV_ENGINE_CE1   :
-       case NVDEV_ENGINE_CE2   : addr = 0x0000; break;
-       case NVDEV_ENGINE_GR    : addr = 0x0210; break;
-       case NVDEV_ENGINE_MSVLD : addr = 0x0270; break;
-       case NVDEV_ENGINE_MSPDEC: addr = 0x0250; break;
-       case NVDEV_ENGINE_MSPPP : addr = 0x0260; break;
+       case NVDEV_ENGINE_CE2   : return 0x0000;
+       case NVDEV_ENGINE_GR    : return 0x0210;
+       case NVDEV_ENGINE_MSPDEC: return 0x0250;
+       case NVDEV_ENGINE_MSPPP : return 0x0260;
+       case NVDEV_ENGINE_MSVLD : return 0x0270;
        default:
-               return -EINVAL;
+               WARN_ON(1);
+               return 0;
        }
+}
 
-       ret = gk104_fifo_chan_kick(chan);
+static int
+gk104_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base,
+                             struct nvkm_engine *engine, bool suspend)
+{
+       const u32 offset = gk104_fifo_gpfifo_engine_addr(engine);
+       struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
+       struct nvkm_gpuobj *inst = chan->base.inst;
+       int ret;
+
+       ret = gk104_fifo_gpfifo_kick(chan);
        if (ret && suspend)
                return ret;
 
-       if (addr) {
-               nvkm_kmap(engn);
-               nvkm_wo32(engn, addr + 0x00, 0x00000000);
-               nvkm_wo32(engn, addr + 0x04, 0x00000000);
-               nvkm_done(engn);
+       if (offset) {
+               nvkm_kmap(inst);
+               nvkm_wo32(inst, offset + 0x00, 0x00000000);
+               nvkm_wo32(inst, offset + 0x04, 0x00000000);
+               nvkm_done(inst);
+       }
+
+       return ret;
+}
+
+static int
+gk104_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base,
+                             struct nvkm_engine *engine)
+{
+       const u32 offset = gk104_fifo_gpfifo_engine_addr(engine);
+       struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
+       struct nvkm_gpuobj *inst = chan->base.inst;
+
+       if (offset) {
+               u64 addr = chan->engn[engine->subdev.index].vma.offset;
+               nvkm_kmap(inst);
+               nvkm_wo32(inst, offset + 0x00, lower_32_bits(addr) | 4);
+               nvkm_wo32(inst, offset + 0x04, upper_32_bits(addr));
+               nvkm_done(inst);
        }
 
        return 0;
 }
 
+static void
+gk104_fifo_gpfifo_engine_dtor(struct nvkm_fifo_chan *base,
+                             struct nvkm_engine *engine)
+{
+       struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
+       nvkm_gpuobj_unmap(&chan->engn[engine->subdev.index].vma);
+       nvkm_gpuobj_del(&chan->engn[engine->subdev.index].inst);
+}
+
 static int
-gk104_fifo_context_attach(struct nvkm_object *parent,
-                         struct nvkm_object *object)
+gk104_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *base,
+                             struct nvkm_engine *engine,
+                             struct nvkm_object *object)
 {
-       struct gk104_fifo_base *base = (void *)parent->parent;
-       struct nvkm_gpuobj *engn = &base->base.gpuobj;
-       struct nvkm_engctx *ectx = (void *)object;
-       u32 addr;
+       struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
+       int engn = engine->subdev.index;
        int ret;
 
-       switch (nv_engidx(object->engine)) {
-       case NVDEV_ENGINE_SW   :
-               return 0;
-       case NVDEV_ENGINE_CE0:
-       case NVDEV_ENGINE_CE1:
-       case NVDEV_ENGINE_CE2:
-               nv_engctx(ectx)->addr = nv_gpuobj(base)->addr >> 12;
+       if (!gk104_fifo_gpfifo_engine_addr(engine))
                return 0;
-       case NVDEV_ENGINE_GR    : addr = 0x0210; break;
-       case NVDEV_ENGINE_MSVLD : addr = 0x0270; break;
-       case NVDEV_ENGINE_MSPDEC: addr = 0x0250; break;
-       case NVDEV_ENGINE_MSPPP : addr = 0x0260; break;
-       default:
-               return -EINVAL;
-       }
 
-       if (!ectx->vma.node) {
-               ret = nvkm_gpuobj_map(nv_gpuobj(ectx), base->vm,
-                                     NV_MEM_ACCESS_RW, &ectx->vma);
-               if (ret)
-                       return ret;
-
-               nv_engctx(ectx)->addr = nv_gpuobj(base)->addr >> 12;
+       if (object->oclass) {
+               return nvkm_gpuobj_map(nv_gpuobj(object), chan->vm,
+                                      NV_MEM_ACCESS_RW,
+                                      &chan->engn[engn].vma);
        }
 
-       nvkm_kmap(engn);
-       nvkm_wo32(engn, addr + 0x00, lower_32_bits(ectx->vma.offset) | 4);
-       nvkm_wo32(engn, addr + 0x04, upper_32_bits(ectx->vma.offset));
-       nvkm_done(engn);
-       return 0;
+       ret = nvkm_object_bind(object, NULL, 0, &chan->engn[engn].inst);
+       if (ret)
+               return ret;
+
+       return nvkm_gpuobj_map(chan->engn[engn].inst, chan->vm,
+                              NV_MEM_ACCESS_RW, &chan->engn[engn].vma);
 }
 
-static int
-gk104_fifo_chan_fini(struct nvkm_object *object, bool suspend)
+static void
+gk104_fifo_gpfifo_fini(struct nvkm_fifo_chan *base)
 {
-       struct gk104_fifo *fifo = (void *)object->engine;
-       struct gk104_fifo_chan *chan = (void *)object;
+       struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
+       struct gk104_fifo *fifo = chan->fifo;
        struct nvkm_device *device = fifo->base.engine.subdev.device;
-       u32 chid = chan->base.chid;
+       u32 coff = chan->base.chid * 8;
 
-       if (chan->state == RUNNING && (chan->state = STOPPED) == STOPPED) {
-               nvkm_mask(device, 0x800004 + (chid * 8), 0x00000800, 0x00000800);
+       if (!list_empty(&chan->head)) {
+               list_del_init(&chan->head);
+               nvkm_mask(device, 0x800004 + coff, 0x00000800, 0x00000800);
                gk104_fifo_runlist_update(fifo, chan->engine);
        }
 
-       nvkm_wr32(device, 0x800000 + (chid * 8), 0x00000000);
-       return nvkm_fifo_channel_fini(&chan->base, suspend);
+       nvkm_wr32(device, 0x800000 + coff, 0x00000000);
 }
 
-static int
-gk104_fifo_chan_init(struct nvkm_object *object)
+static void
+gk104_fifo_gpfifo_init(struct nvkm_fifo_chan *base)
 {
-       struct nvkm_gpuobj *base = nv_gpuobj(object->parent);
-       struct gk104_fifo *fifo = (void *)object->engine;
-       struct gk104_fifo_chan *chan = (void *)object;
+       struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
+       struct gk104_fifo *fifo = chan->fifo;
        struct nvkm_device *device = fifo->base.engine.subdev.device;
-       u32 chid = chan->base.chid;
-       int ret;
+       u32 addr = chan->base.inst->addr >> 12;
+       u32 coff = chan->base.chid * 8;
 
-       ret = nvkm_fifo_channel_init(&chan->base);
-       if (ret)
-               return ret;
+       nvkm_mask(device, 0x800004 + coff, 0x000f0000, chan->engine << 16);
+       nvkm_wr32(device, 0x800000 + coff, 0x80000000 | addr);
 
-       nvkm_mask(device, 0x800004 + (chid * 8), 0x000f0000, chan->engine << 16);
-       nvkm_wr32(device, 0x800000 + (chid * 8), 0x80000000 | base->addr >> 12);
-
-       if (chan->state == STOPPED && (chan->state = RUNNING) == RUNNING) {
-               nvkm_mask(device, 0x800004 + (chid * 8), 0x00000400, 0x00000400);
+       if (list_empty(&chan->head) && !chan->killed) {
+               list_add_tail(&chan->head, &fifo->engine[chan->engine].chan);
+               nvkm_mask(device, 0x800004 + coff, 0x00000400, 0x00000400);
                gk104_fifo_runlist_update(fifo, chan->engine);
-               nvkm_mask(device, 0x800004 + (chid * 8), 0x00000400, 0x00000400);
+               nvkm_mask(device, 0x800004 + coff, 0x00000400, 0x00000400);
        }
+}
 
-       return 0;
+static void *
+gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base)
+{
+       struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
+       nvkm_vm_ref(NULL, &chan->vm, chan->pgd);
+       nvkm_gpuobj_del(&chan->pgd);
+       return chan;
 }
 
-static int
-gk104_fifo_chan_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-                    struct nvkm_oclass *oclass, void *data, u32 size,
-                    struct nvkm_object **pobject)
+static const struct nvkm_fifo_chan_func
+gk104_fifo_gpfifo_func = {
+       .dtor = gk104_fifo_gpfifo_dtor,
+       .init = gk104_fifo_gpfifo_init,
+       .fini = gk104_fifo_gpfifo_fini,
+       .ntfy = g84_fifo_chan_ntfy,
+       .engine_ctor = gk104_fifo_gpfifo_engine_ctor,
+       .engine_dtor = gk104_fifo_gpfifo_engine_dtor,
+       .engine_init = gk104_fifo_gpfifo_engine_init,
+       .engine_fini = gk104_fifo_gpfifo_engine_fini,
+};
+
+int
+gk104_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
+                     void *data, u32 size, struct nvkm_object **pobject)
 {
        union {
                struct kepler_channel_gpfifo_a_v0 v0;
        } *args = data;
-       struct gk104_fifo *fifo = (void *)engine;
-       struct gk104_fifo_base *base = (void *)parent;
+       struct gk104_fifo *fifo = gk104_fifo(base);
+       struct nvkm_device *device = fifo->base.engine.subdev.device;
+       struct nvkm_object *parent = oclass->parent;
        struct gk104_fifo_chan *chan;
-       struct nvkm_gpuobj *ramfc = &base->base.gpuobj;
        u64 usermem, ioffset, ilength;
        u32 engines;
        int ret, i;
 
        nvif_ioctl(parent, "create channel gpfifo size %d\n", size);
        if (nvif_unpack(args->v0, 0, 0, false)) {
-               nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx"
+               nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx "
                                   "ioffset %016llx ilength %08x engine %08x\n",
                           args->v0.version, args->v0.vm, args->v0.ioffset,
                           args->v0.ilength, args->v0.engine);
-               if (args->v0.vm)
-                       return -ENOENT;
        } else
                return ret;
 
-       for (i = 0, engines = 0; i < FIFO_ENGINE_NR; i++) {
-               if (!nvkm_engine(parent, fifo_engine[i].subdev))
+       /* determine which downstream engines are present */
+       for (i = 0, engines = 0; i < ARRAY_SIZE(fifo->engine); i++) {
+               u64 subdevs = gk104_fifo_engine_subdev(i);
+               if (!nvkm_device_engine(device, __ffs64(subdevs)))
                        continue;
                engines |= (1 << i);
        }
 
+       /* if this is an engine mask query, we're done */
        if (!args->v0.engine) {
-               static struct nvkm_oclass oclass = {
-                       .ofuncs = &nvkm_object_ofuncs,
-               };
                args->v0.engine = engines;
-               return nvkm_object_old(parent, engine, &oclass, NULL, 0, pobject);
+               return nvkm_object_new(oclass, NULL, 0, pobject);
        }
 
-       engines &= args->v0.engine;
-       if (!engines) {
-               nvif_ioctl(parent, "unsupported engines %08x\n",
-                          args->v0.engine);
+       /* check that we support a requested engine - note that the user
+        * argument is a mask in order to allow the user to request (for
+        * example) *any* copy engine, but doesn't matter which.
+        */
+       args->v0.engine &= engines;
+       if (!args->v0.engine) {
+               nvif_ioctl(parent, "no supported engine\n");
                return -ENODEV;
        }
-       i = __ffs(engines);
 
-       ret = nvkm_fifo_channel_create(parent, engine, oclass, 1,
-                                      fifo->user.bar.offset, 0x200, 0,
-                                      fifo_engine[i].mask, &chan);
-       *pobject = nv_object(chan);
+       /* allocate the channel */
+       if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
+               return -ENOMEM;
+       *pobject = &chan->base.object;
+       chan->fifo = fifo;
+       chan->engine = __ffs(args->v0.engine);
+       INIT_LIST_HEAD(&chan->head);
+
+       ret = nvkm_fifo_chan_ctor(&gk104_fifo_gpfifo_func, &fifo->base,
+                                 0x1000, 0x1000, true, args->v0.vm, 0,
+                                 gk104_fifo_engine_subdev(chan->engine),
+                                 1, fifo->user.bar.offset, 0x200,
+                                 oclass, &chan->base);
        if (ret)
                return ret;
 
-       chan->base.inst = base->base.gpuobj.addr;
        args->v0.chid = chan->base.chid;
 
-       nv_parent(chan)->context_attach = gk104_fifo_context_attach;
-       nv_parent(chan)->context_detach = gk104_fifo_context_detach;
-       chan->engine = i;
+       /* page directory */
+       ret = nvkm_gpuobj_new(device, 0x10000, 0x1000, false, NULL, &chan->pgd);
+       if (ret)
+               return ret;
+
+       nvkm_kmap(chan->base.inst);
+       nvkm_wo32(chan->base.inst, 0x0200, lower_32_bits(chan->pgd->addr));
+       nvkm_wo32(chan->base.inst, 0x0204, upper_32_bits(chan->pgd->addr));
+       nvkm_wo32(chan->base.inst, 0x0208, 0xffffffff);
+       nvkm_wo32(chan->base.inst, 0x020c, 0x000000ff);
+       nvkm_done(chan->base.inst);
 
+       ret = nvkm_vm_ref(chan->base.vm, &chan->vm, chan->pgd);
+       if (ret)
+               return ret;
+
+       /* clear channel control registers */
        usermem = chan->base.chid * 0x200;
        ioffset = args->v0.ioffset;
        ilength = order_base_2(args->v0.ilength / 8);
@@ -264,94 +298,31 @@ gk104_fifo_chan_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
        nvkm_done(fifo->user.mem);
        usermem = nvkm_memory_addr(fifo->user.mem) + usermem;
 
-       nvkm_kmap(ramfc);
-       nvkm_wo32(ramfc, 0x08, lower_32_bits(usermem));
-       nvkm_wo32(ramfc, 0x0c, upper_32_bits(usermem));
-       nvkm_wo32(ramfc, 0x10, 0x0000face);
-       nvkm_wo32(ramfc, 0x30, 0xfffff902);
-       nvkm_wo32(ramfc, 0x48, lower_32_bits(ioffset));
-       nvkm_wo32(ramfc, 0x4c, upper_32_bits(ioffset) | (ilength << 16));
-       nvkm_wo32(ramfc, 0x84, 0x20400000);
-       nvkm_wo32(ramfc, 0x94, 0x30000001);
-       nvkm_wo32(ramfc, 0x9c, 0x00000100);
-       nvkm_wo32(ramfc, 0xac, 0x0000001f);
-       nvkm_wo32(ramfc, 0xe8, chan->base.chid);
-       nvkm_wo32(ramfc, 0xb8, 0xf8000000);
-       nvkm_wo32(ramfc, 0xf8, 0x10003080); /* 0x002310 */
-       nvkm_wo32(ramfc, 0xfc, 0x10000010); /* 0x002350 */
-       nvkm_done(ramfc);
-       return 0;
-}
-
-struct nvkm_ofuncs
-gk104_fifo_chan_ofuncs = {
-       .ctor = gk104_fifo_chan_ctor,
-       .dtor = _nvkm_fifo_channel_dtor,
-       .init = gk104_fifo_chan_init,
-       .fini = gk104_fifo_chan_fini,
-       .map  = _nvkm_fifo_channel_map,
-       .rd32 = _nvkm_fifo_channel_rd32,
-       .wr32 = _nvkm_fifo_channel_wr32,
-       .ntfy = _nvkm_fifo_channel_ntfy
-};
-
-struct nvkm_oclass
-gk104_fifo_sclass[] = {
-       { KEPLER_CHANNEL_GPFIFO_A, &gk104_fifo_chan_ofuncs },
-       {}
-};
-
-static int
-gk104_fifo_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-                       struct nvkm_oclass *oclass, void *data, u32 size,
-                       struct nvkm_object **pobject)
-{
-       struct nvkm_device *device = nv_engine(engine)->subdev.device;
-       struct gk104_fifo_base *base;
-       int ret;
-
-       ret = nvkm_fifo_context_create(parent, engine, oclass, NULL, 0x1000,
-                                      0x1000, NVOBJ_FLAG_ZERO_ALLOC, &base);
-       *pobject = nv_object(base);
-       if (ret)
-               return ret;
-
-       ret = nvkm_gpuobj_new(device, 0x10000, 0x1000, false, NULL, &base->pgd);
-       if (ret)
-               return ret;
-
-       nvkm_kmap(&base->base.gpuobj);
-       nvkm_wo32(&base->base.gpuobj, 0x0200, lower_32_bits(base->pgd->addr));
-       nvkm_wo32(&base->base.gpuobj, 0x0204, upper_32_bits(base->pgd->addr));
-       nvkm_wo32(&base->base.gpuobj, 0x0208, 0xffffffff);
-       nvkm_wo32(&base->base.gpuobj, 0x020c, 0x000000ff);
-       nvkm_done(&base->base.gpuobj);
-
-       ret = nvkm_vm_ref(nvkm_client(parent)->vm, &base->vm, base->pgd);
-       if (ret)
-               return ret;
-
+       /* RAMFC */
+       nvkm_kmap(chan->base.inst);
+       nvkm_wo32(chan->base.inst, 0x08, lower_32_bits(usermem));
+       nvkm_wo32(chan->base.inst, 0x0c, upper_32_bits(usermem));
+       nvkm_wo32(chan->base.inst, 0x10, 0x0000face);
+       nvkm_wo32(chan->base.inst, 0x30, 0xfffff902);
+       nvkm_wo32(chan->base.inst, 0x48, lower_32_bits(ioffset));
+       nvkm_wo32(chan->base.inst, 0x4c, upper_32_bits(ioffset) |
+                                        (ilength << 16));
+       nvkm_wo32(chan->base.inst, 0x84, 0x20400000);
+       nvkm_wo32(chan->base.inst, 0x94, 0x30000001);
+       nvkm_wo32(chan->base.inst, 0x9c, 0x00000100);
+       nvkm_wo32(chan->base.inst, 0xac, 0x0000001f);
+       nvkm_wo32(chan->base.inst, 0xe8, chan->base.chid);
+       nvkm_wo32(chan->base.inst, 0xb8, 0xf8000000);
+       nvkm_wo32(chan->base.inst, 0xf8, 0x10003080); /* 0x002310 */
+       nvkm_wo32(chan->base.inst, 0xfc, 0x10000010); /* 0x002350 */
+       nvkm_done(chan->base.inst);
        return 0;
 }
 
-static void
-gk104_fifo_context_dtor(struct nvkm_object *object)
-{
-       struct gk104_fifo_base *base = (void *)object;
-       nvkm_vm_ref(NULL, &base->vm, base->pgd);
-       nvkm_gpuobj_del(&base->pgd);
-       nvkm_fifo_context_destroy(&base->base);
-}
-
-struct nvkm_oclass
-gk104_fifo_cclass = {
-       .handle = NV_ENGCTX(FIFO, 0xe0),
-       .ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = gk104_fifo_context_ctor,
-               .dtor = gk104_fifo_context_dtor,
-               .init = _nvkm_fifo_context_init,
-               .fini = _nvkm_fifo_context_fini,
-               .rd32 = _nvkm_fifo_context_rd32,
-               .wr32 = _nvkm_fifo_context_wr32,
-       },
+const struct nvkm_fifo_chan_oclass
+gk104_fifo_gpfifo_oclass = {
+       .base.oclass = KEPLER_CHANNEL_GPFIFO_A,
+       .base.minver = 0,
+       .base.maxver = 0,
+       .ctor = gk104_fifo_gpfifo_new,
 };
index 7beee1f8729af23e42f405b13c44d9cd4aaef2b0..6511d6e21ecc11084ea3cee5d44e0e9963ab594a 100644 (file)
 
 #include <nvif/class.h>
 
-struct nvkm_oclass
-gm204_fifo_sclass[] = {
-       { MAXWELL_CHANNEL_GPFIFO_A, &gk104_fifo_chan_ofuncs },
-       {}
+const struct nvkm_fifo_chan_oclass
+gm204_fifo_gpfifo_oclass = {
+       .base.oclass = MAXWELL_CHANNEL_GPFIFO_A,
+       .base.minver = 0,
+       .base.maxver = 0,
+       .ctor = gk104_fifo_gpfifo_new,
 };
index ca7de9a6d67fb6fd805caa25c336807775a6d36b..a8c69f878221127beb788f72d406de0418308b4b 100644 (file)
 #include <nvif/unpack.h>
 
 static int
-nv50_fifo_chan_ctor_ind(struct nvkm_object *parent, struct nvkm_object *engine,
-                       struct nvkm_oclass *oclass, void *data, u32 size,
-                       struct nvkm_object **pobject)
+nv50_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
+                    void *data, u32 size, struct nvkm_object **pobject)
 {
+       struct nvkm_object *parent = oclass->parent;
        union {
                struct nv50_channel_gpfifo_v0 v0;
        } *args = data;
-       struct nvkm_device *device = parent->engine->subdev.device;
-       struct nv50_fifo_base *base = (void *)parent;
+       struct nv50_fifo *fifo = nv50_fifo(base);
        struct nv50_fifo_chan *chan;
        u64 ioffset, ilength;
        int ret;
@@ -50,61 +49,44 @@ nv50_fifo_chan_ctor_ind(struct nvkm_object *parent, struct nvkm_object *engine,
                                   "ilength %08x\n",
                           args->v0.version, args->v0.vm, args->v0.pushbuf,
                           args->v0.ioffset, args->v0.ilength);
-               if (args->v0.vm)
-                       return -ENOENT;
+               if (!args->v0.pushbuf)
+                       return -EINVAL;
        } else
                return ret;
 
-       ret = nvkm_fifo_channel_create(parent, engine, oclass, 0, 0xc00000,
-                                      0x2000, args->v0.pushbuf,
-                                      (1ULL << NVDEV_ENGINE_DMAOBJ) |
-                                      (1ULL << NVDEV_ENGINE_SW) |
-                                      (1ULL << NVDEV_ENGINE_GR) |
-                                      (1ULL << NVDEV_ENGINE_MPEG), &chan);
-       *pobject = nv_object(chan);
-       if (ret)
-               return ret;
-
-       chan->base.inst = base->base.gpuobj.addr;
-       args->v0.chid = chan->base.chid;
-
-       nv_parent(chan)->context_attach = nv50_fifo_context_attach;
-       nv_parent(chan)->context_detach = nv50_fifo_context_detach;
-       nv_parent(chan)->object_attach = nv50_fifo_object_attach;
-       nv_parent(chan)->object_detach = nv50_fifo_object_detach;
+       if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
+               return -ENOMEM;
+       *pobject = &chan->base.object;
 
-       ret = nvkm_ramht_new(device, 0x8000, 16, &base->base.gpuobj,
-                            &chan->ramht);
+       ret = nv50_fifo_chan_ctor(fifo, args->v0.vm, args->v0.pushbuf,
+                                 oclass, chan);
        if (ret)
                return ret;
 
+       args->v0.chid = chan->base.chid;
        ioffset = args->v0.ioffset;
        ilength = order_base_2(args->v0.ilength / 8);
 
-       nvkm_kmap(base->ramfc);
-       nvkm_wo32(base->ramfc, 0x3c, 0x403f6078);
-       nvkm_wo32(base->ramfc, 0x44, 0x01003fff);
-       nvkm_wo32(base->ramfc, 0x48, chan->base.pushgpu->node->offset >> 4);
-       nvkm_wo32(base->ramfc, 0x50, lower_32_bits(ioffset));
-       nvkm_wo32(base->ramfc, 0x54, upper_32_bits(ioffset) | (ilength << 16));
-       nvkm_wo32(base->ramfc, 0x60, 0x7fffffff);
-       nvkm_wo32(base->ramfc, 0x78, 0x00000000);
-       nvkm_wo32(base->ramfc, 0x7c, 0x30000001);
-       nvkm_wo32(base->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) |
+       nvkm_kmap(chan->ramfc);
+       nvkm_wo32(chan->ramfc, 0x3c, 0x403f6078);
+       nvkm_wo32(chan->ramfc, 0x44, 0x01003fff);
+       nvkm_wo32(chan->ramfc, 0x48, chan->base.push->node->offset >> 4);
+       nvkm_wo32(chan->ramfc, 0x50, lower_32_bits(ioffset));
+       nvkm_wo32(chan->ramfc, 0x54, upper_32_bits(ioffset) | (ilength << 16));
+       nvkm_wo32(chan->ramfc, 0x60, 0x7fffffff);
+       nvkm_wo32(chan->ramfc, 0x78, 0x00000000);
+       nvkm_wo32(chan->ramfc, 0x7c, 0x30000001);
+       nvkm_wo32(chan->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) |
                                     (4 << 24) /* SEARCH_FULL */ |
                                     (chan->ramht->gpuobj->node->offset >> 4));
-       nvkm_done(base->ramfc);
+       nvkm_done(chan->ramfc);
        return 0;
 }
 
-struct nvkm_ofuncs
-nv50_fifo_ofuncs_ind = {
-       .ctor = nv50_fifo_chan_ctor_ind,
-       .dtor = nv50_fifo_chan_dtor,
-       .init = nv50_fifo_chan_init,
-       .fini = nv50_fifo_chan_fini,
-       .map  = _nvkm_fifo_channel_map,
-       .rd32 = _nvkm_fifo_channel_rd32,
-       .wr32 = _nvkm_fifo_channel_wr32,
-       .ntfy = _nvkm_fifo_channel_ntfy
+const struct nvkm_fifo_chan_oclass
+nv50_fifo_gpfifo_oclass = {
+       .base.oclass = NV50_CHANNEL_GPFIFO,
+       .base.minver = 0,
+       .base.maxver = 0,
+       .ctor = nv50_fifo_gpfifo_new,
 };
index d880cfa6de9efbff1f8b88fc1c5669367ab3b65c..d1ad3fa72c343933f105fc3ce16593293854d66c 100644 (file)
@@ -25,6 +25,7 @@
 #include "channv04.h"
 #include "regsnv04.h"
 
+#include <core/client.h>
 #include <core/handle.h>
 #include <core/ramht.h>
 #include <subdev/instmem.h>
@@ -136,6 +137,8 @@ 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;
+       struct nvkm_fifo_chan *chan;
+       unsigned long flags;
        u32 pull0 = nvkm_rd32(device, 0x003250);
        u32 mthd, data;
        int ptr;
@@ -157,12 +160,12 @@ nv04_fifo_cache_error(struct nv04_fifo *fifo, u32 chid, u32 get)
 
        if (!(pull0 & 0x00000100) ||
            !nv04_fifo_swmthd(device, chid, mthd, data)) {
-               const char *client_name =
-                       nvkm_client_name_for_fifo_chid(&fifo->base, chid);
+               chan = nvkm_fifo_chan_chid(&fifo->base, chid, &flags);
                nvkm_error(subdev, "CACHE_ERROR - "
                           "ch %d [%s] subc %d mthd %04x data %08x\n",
-                          chid, client_name, (mthd >> 13) & 7, mthd & 0x1ffc,
-                          data);
+                          chid, chan ? chan->object.client->name : "unknown",
+                          (mthd >> 13) & 7, mthd & 0x1ffc, data);
+               nvkm_fifo_chan_put(&fifo->base, flags, &chan);
        }
 
        nvkm_wr32(device, NV04_PFIFO_CACHE1_DMA_PUSH, 0);
@@ -189,10 +192,12 @@ nv04_fifo_dma_pusher(struct nv04_fifo *fifo, u32 chid)
        u32 dma_put = nvkm_rd32(device, 0x003240);
        u32 push = nvkm_rd32(device, 0x003220);
        u32 state = nvkm_rd32(device, 0x003228);
-       const char *client_name;
-
-       client_name = nvkm_client_name_for_fifo_chid(&fifo->base, chid);
+       struct nvkm_fifo_chan *chan;
+       unsigned long flags;
+       const char *name;
 
+       chan = nvkm_fifo_chan_chid(&fifo->base, chid, &flags);
+       name = chan ? chan->object.client->name : "unknown";
        if (device->card_type == NV_50) {
                u32 ho_get = nvkm_rd32(device, 0x003328);
                u32 ho_put = nvkm_rd32(device, 0x003320);
@@ -202,7 +207,7 @@ nv04_fifo_dma_pusher(struct nv04_fifo *fifo, u32 chid)
                nvkm_error(subdev, "DMA_PUSHER - "
                           "ch %d [%s] get %02x%08x put %02x%08x ib_get %08x "
                           "ib_put %08x state %08x (err: %s) push %08x\n",
-                          chid, client_name, ho_get, dma_get, ho_put, dma_put,
+                          chid, name, ho_get, dma_get, ho_put, dma_put,
                           ib_get, ib_put, state, nv_dma_state_err(state),
                           push);
 
@@ -217,12 +222,13 @@ nv04_fifo_dma_pusher(struct nv04_fifo *fifo, u32 chid)
        } else {
                nvkm_error(subdev, "DMA_PUSHER - ch %d [%s] get %08x put %08x "
                                   "state %08x (err: %s) push %08x\n",
-                          chid, client_name, dma_get, dma_put, state,
+                          chid, name, dma_get, dma_put, state,
                           nv_dma_state_err(state), push);
 
                if (dma_get != dma_put)
                        nvkm_wr32(device, 0x003244, dma_put);
        }
+       nvkm_fifo_chan_put(&fifo->base, flags, &chan);
 
        nvkm_wr32(device, 0x003228, 0x00000000);
        nvkm_wr32(device, 0x003220, 0x00000001);
@@ -241,7 +247,7 @@ nv04_fifo_intr(struct nvkm_subdev *subdev)
        reassign = nvkm_rd32(device, NV03_PFIFO_CACHES) & 1;
        nvkm_wr32(device, NV03_PFIFO_CACHES, 0);
 
-       chid = nvkm_rd32(device, NV03_PFIFO_CACHE1_PUSH1) & fifo->base.max;
+       chid = nvkm_rd32(device, NV03_PFIFO_CACHE1_PUSH1) & (fifo->base.nr - 1);
        get  = nvkm_rd32(device, NV03_PFIFO_CACHE1_GET);
 
        if (stat & NV_PFIFO_INTR_CACHE_ERROR) {
@@ -311,7 +317,7 @@ nv04_fifo_init(struct nvkm_object *object)
        nvkm_wr32(device, NV03_PFIFO_RAMRO, nvkm_memory_addr(ramro) >> 8);
        nvkm_wr32(device, NV03_PFIFO_RAMFC, nvkm_memory_addr(ramfc) >> 8);
 
-       nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->base.max);
+       nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->base.nr - 1);
 
        nvkm_wr32(device, NV03_PFIFO_INTR_0, 0xffffffff);
        nvkm_wr32(device, NV03_PFIFO_INTR_EN_0, 0xffffffff);
@@ -329,6 +335,14 @@ nv04_fifo_dtor(struct nvkm_object *object)
        nvkm_fifo_destroy(&fifo->base);
 }
 
+static const struct nvkm_fifo_func
+nv04_fifo_func = {
+       .chan = {
+               &nv04_fifo_dma_oclass,
+               NULL
+       },
+};
+
 static int
 nv04_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
               struct nvkm_oclass *oclass, void *data, u32 size,
@@ -342,10 +356,10 @@ nv04_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
        if (ret)
                return ret;
 
+       fifo->base.func = &nv04_fifo_func;
+
        nv_subdev(fifo)->unit = 0x00000100;
        nv_subdev(fifo)->intr = nv04_fifo_intr;
-       nv_engine(fifo)->cclass = &nv04_fifo_cclass;
-       nv_engine(fifo)->sclass = nv04_fifo_sclass;
        fifo->base.pause = nv04_fifo_pause;
        fifo->base.start = nv04_fifo_start;
        fifo->ramfc_desc = nv04_ramfc;
index 5cde3310ee4ddd7e1276ca35d1650f6c2266a76d..c33dc56f8e022a27035b8c88a9dabd82623d3913 100644 (file)
@@ -1,5 +1,6 @@
 #ifndef __NV04_FIFO_H__
 #define __NV04_FIFO_H__
+#define nv04_fifo(p) container_of((p), struct nv04_fifo, base)
 #include "priv.h"
 
 struct ramfc_desc {
@@ -15,14 +16,6 @@ struct nv04_fifo {
        struct ramfc_desc *ramfc_desc;
 };
 
-struct nv04_fifo_base {
-       struct nvkm_fifo_base base;
-};
-
-int  nv04_fifo_context_ctor(struct nvkm_object *, struct nvkm_object *,
-                           struct nvkm_oclass *, void *, u32,
-                           struct nvkm_object **);
-
 void nv04_fifo_dtor(struct nvkm_object *);
 int  nv04_fifo_init(struct nvkm_object *);
 #endif
index ae0a1b17eb922c44c8e5c8b748d04b242e9b9475..d7fab9598fb0e9a841ef34ef56e291efc289027c 100644 (file)
@@ -39,16 +39,11 @@ nv10_ramfc[] = {
        {}
 };
 
-static struct nvkm_oclass
-nv10_fifo_cclass = {
-       .handle = NV_ENGCTX(FIFO, 0x10),
-       .ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = nv04_fifo_context_ctor,
-               .dtor = _nvkm_fifo_context_dtor,
-               .init = _nvkm_fifo_context_init,
-               .fini = _nvkm_fifo_context_fini,
-               .rd32 = _nvkm_fifo_context_rd32,
-               .wr32 = _nvkm_fifo_context_wr32,
+static const struct nvkm_fifo_func
+nv10_fifo_func = {
+       .chan = {
+               &nv10_fifo_dma_oclass,
+               NULL
        },
 };
 
@@ -65,10 +60,10 @@ nv10_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
        if (ret)
                return ret;
 
+       fifo->base.func = &nv10_fifo_func;
+
        nv_subdev(fifo)->unit = 0x00000100;
        nv_subdev(fifo)->intr = nv04_fifo_intr;
-       nv_engine(fifo)->cclass = &nv10_fifo_cclass;
-       nv_engine(fifo)->sclass = nv10_fifo_sclass;
        fifo->base.pause = nv04_fifo_pause;
        fifo->base.start = nv04_fifo_start;
        fifo->ramfc_desc = nv10_ramfc;
index ff2b6d95d80473f640f045a27bba477ad6e3824a..a8e28fc24e756c390fe1adb493919cc80da5cde7 100644 (file)
@@ -47,19 +47,6 @@ nv17_ramfc[] = {
        {}
 };
 
-static struct nvkm_oclass
-nv17_fifo_cclass = {
-       .handle = NV_ENGCTX(FIFO, 0x17),
-       .ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = nv04_fifo_context_ctor,
-               .dtor = _nvkm_fifo_context_dtor,
-               .init = _nvkm_fifo_context_init,
-               .fini = _nvkm_fifo_context_fini,
-               .rd32 = _nvkm_fifo_context_rd32,
-               .wr32 = _nvkm_fifo_context_wr32,
-       },
-};
-
 static int
 nv17_fifo_init(struct nvkm_object *object)
 {
@@ -85,7 +72,7 @@ nv17_fifo_init(struct nvkm_object *object)
        nvkm_wr32(device, NV03_PFIFO_RAMFC, nvkm_memory_addr(ramfc) >> 8 |
                                            0x00010000);
 
-       nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->base.max);
+       nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->base.nr - 1);
 
        nvkm_wr32(device, NV03_PFIFO_INTR_0, 0xffffffff);
        nvkm_wr32(device, NV03_PFIFO_INTR_EN_0, 0xffffffff);
@@ -96,6 +83,14 @@ nv17_fifo_init(struct nvkm_object *object)
        return 0;
 }
 
+static const struct nvkm_fifo_func
+nv17_fifo_func = {
+       .chan = {
+               &nv17_fifo_dma_oclass,
+               NULL
+       },
+};
+
 static int
 nv17_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
               struct nvkm_oclass *oclass, void *data, u32 size,
@@ -109,10 +104,10 @@ nv17_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
        if (ret)
                return ret;
 
+       fifo->base.func = &nv17_fifo_func;
+
        nv_subdev(fifo)->unit = 0x00000100;
        nv_subdev(fifo)->intr = nv04_fifo_intr;
-       nv_engine(fifo)->cclass = &nv17_fifo_cclass;
-       nv_engine(fifo)->sclass = nv17_fifo_sclass;
        fifo->base.pause = nv04_fifo_pause;
        fifo->base.start = nv04_fifo_start;
        fifo->ramfc_desc = nv17_ramfc;
index 64be69fc9572337ad6a04b61b605d8658025cb4c..aca146377d36de4898adf3efabfefd268bd0299d 100644 (file)
@@ -56,19 +56,6 @@ nv40_ramfc[] = {
        {}
 };
 
-static struct nvkm_oclass
-nv40_fifo_cclass = {
-       .handle = NV_ENGCTX(FIFO, 0x40),
-       .ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = nv04_fifo_context_ctor,
-               .dtor = _nvkm_fifo_context_dtor,
-               .init = _nvkm_fifo_context_init,
-               .fini = _nvkm_fifo_context_fini,
-               .rd32 = _nvkm_fifo_context_rd32,
-               .wr32 = _nvkm_fifo_context_wr32,
-       },
-};
-
 static int
 nv40_fifo_init(struct nvkm_object *object)
 {
@@ -115,7 +102,7 @@ nv40_fifo_init(struct nvkm_object *object)
                break;
        }
 
-       nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->base.max);
+       nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->base.nr - 1);
 
        nvkm_wr32(device, NV03_PFIFO_INTR_0, 0xffffffff);
        nvkm_wr32(device, NV03_PFIFO_INTR_EN_0, 0xffffffff);
@@ -126,6 +113,14 @@ nv40_fifo_init(struct nvkm_object *object)
        return 0;
 }
 
+static const struct nvkm_fifo_func
+nv40_fifo_func = {
+       .chan = {
+               &nv40_fifo_dma_oclass,
+               NULL
+       },
+};
+
 static int
 nv40_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
               struct nvkm_oclass *oclass, void *data, u32 size,
@@ -139,10 +134,10 @@ nv40_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
        if (ret)
                return ret;
 
+       fifo->base.func = &nv40_fifo_func;
+
        nv_subdev(fifo)->unit = 0x00000100;
        nv_subdev(fifo)->intr = nv04_fifo_intr;
-       nv_engine(fifo)->cclass = &nv40_fifo_cclass;
-       nv_engine(fifo)->sclass = nv40_fifo_sclass;
        fifo->base.pause = nv04_fifo_pause;
        fifo->base.start = nv04_fifo_start;
        fifo->ramfc_desc = nv40_ramfc;
index bf17cb0e8385be5321fb28f13963f887ce85d122..ad653e9c461a39a0b1c71f05af3ca020d21dc764 100644 (file)
@@ -35,7 +35,7 @@ nv50_fifo_runlist_update_locked(struct nv50_fifo *fifo)
        fifo->cur_runlist = !fifo->cur_runlist;
 
        nvkm_kmap(cur);
-       for (i = fifo->base.min, p = 0; i < fifo->base.max; i++) {
+       for (i = 0, p = 0; i < fifo->base.nr; i++) {
                if (nvkm_rd32(device, 0x002600 + (i * 4)) & 0x80000000)
                        nvkm_wo32(cur, p++ * 4, i);
        }
@@ -94,6 +94,15 @@ nv50_fifo_dtor(struct nvkm_object *object)
        nvkm_fifo_destroy(&fifo->base);
 }
 
+static const struct nvkm_fifo_func
+nv50_fifo_func = {
+       .chan = {
+               &nv50_fifo_dma_oclass,
+               &nv50_fifo_gpfifo_oclass,
+               NULL
+       },
+};
+
 static int
 nv50_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
               struct nvkm_oclass *oclass, void *data, u32 size,
@@ -108,6 +117,8 @@ nv50_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
        if (ret)
                return ret;
 
+       fifo->base.func = &nv50_fifo_func;
+
        ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 4, 0x1000,
                              false, &fifo->runlist[0]);
        if (ret)
@@ -120,8 +131,6 @@ nv50_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
 
        nv_subdev(fifo)->unit = 0x00000100;
        nv_subdev(fifo)->intr = nv04_fifo_intr;
-       nv_engine(fifo)->cclass = &nv50_fifo_cclass;
-       nv_engine(fifo)->sclass = nv50_fifo_sclass;
        fifo->base.pause = nv04_fifo_pause;
        fifo->base.start = nv04_fifo_start;
        return 0;
index 306593fc56bb1b50c6b10c8f2e3e461d10398b6c..a7d5dba12fb8e302ddd24bc1948711b0be843434 100644 (file)
@@ -1,5 +1,6 @@
 #ifndef __NV50_FIFO_H__
 #define __NV50_FIFO_H__
+#define nv50_fifo(p) container_of((p), struct nv50_fifo, base)
 #include "priv.h"
 
 struct nv50_fifo {
index b202f7f9413d16ba4816590013cb39707422559f..a30d160f30db637b02575d42721775b363cff8ae 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __NVKM_FIFO_PRIV_H__
 #define __NVKM_FIFO_PRIV_H__
 #include <engine/fifo.h>
-#include <core/engctx.h>
 
 void nv04_fifo_pause(struct nvkm_fifo *, unsigned long *);
 void nv04_fifo_start(struct nvkm_fifo *, unsigned long *);
index c6ff24b5a11dfe11322ff9bc4f96a7d5dc72f57c..ebc9dee03beb87ebf8cdf0260c8c388e5d291ef0 100644 (file)
@@ -1168,10 +1168,14 @@ gf100_gr_intr(struct nvkm_subdev *subdev)
        u32 data = nvkm_rd32(device, 0x400708);
        u32 code = nvkm_rd32(device, 0x400110);
        u32 class;
-       int chid;
+       const char *name = "unknown";
+       int chid = -1;
 
        chan = nvkm_fifo_chan_inst(device->fifo, (u64)inst << 12, &flags);
-       chid = chan ? chan->chid : -1;
+       if (chan) {
+               name = chan->object.client->name;
+               chid = chan->chid;
+       }
 
        if (nv_device(gr)->card_type < NV_E0 || subc < 4)
                class = nvkm_rd32(device, 0x404200 + (subc * 4));
@@ -1191,8 +1195,8 @@ gf100_gr_intr(struct nvkm_subdev *subdev)
                if (!gf100_gr_mthd_sw(device, class, mthd, data)) {
                        nvkm_error(subdev, "ILLEGAL_MTHD ch %d [%010llx %s] "
                                   "subc %d class %04x mthd %04x data %08x\n",
-                                  chid, inst << 12, nvkm_client_name(chan),
-                                  subc, class, mthd, data);
+                                  chid, inst << 12, name, subc,
+                                  class, mthd, data);
                }
                nvkm_wr32(device, 0x400100, 0x00000010);
                stat &= ~0x00000010;
@@ -1201,8 +1205,7 @@ gf100_gr_intr(struct nvkm_subdev *subdev)
        if (stat & 0x00000020) {
                nvkm_error(subdev, "ILLEGAL_CLASS ch %d [%010llx %s] "
                           "subc %d class %04x mthd %04x data %08x\n",
-                          chid, inst << 12, nvkm_client_name(chan), subc,
-                          class, mthd, data);
+                          chid, inst << 12, name, subc, class, mthd, data);
                nvkm_wr32(device, 0x400100, 0x00000020);
                stat &= ~0x00000020;
        }
@@ -1213,14 +1216,14 @@ gf100_gr_intr(struct nvkm_subdev *subdev)
                nvkm_error(subdev, "DATA_ERROR %08x [%s] ch %d [%010llx %s] "
                                   "subc %d class %04x mthd %04x data %08x\n",
                           code, en ? en->name : "", chid, inst << 12,
-                          nvkm_client_name(chan), subc, class, mthd, data);
+                          name, subc, class, mthd, data);
                nvkm_wr32(device, 0x400100, 0x00100000);
                stat &= ~0x00100000;
        }
 
        if (stat & 0x00200000) {
                nvkm_error(subdev, "TRAP ch %d [%010llx %s]\n",
-                          chid, inst << 12, nvkm_client_name(chan));
+                          chid, inst << 12, name);
                gf100_gr_trap_intr(gr);
                nvkm_wr32(device, 0x400100, 0x00200000);
                stat &= ~0x00200000;
index 262638b4e0c5923a381b7cb8d73420941e3f438d..29feab391fe401c90dc90509fbe0b483259d30e4 100644 (file)
@@ -230,7 +230,8 @@ nv20_gr_intr(struct nvkm_subdev *subdev)
                                   "nstatus %08x [%s] ch %d [%s] subc %d "
                                   "class %04x mthd %04x data %08x\n",
                           show, msg, nsource, src, nstatus, sta, chid,
-                          nvkm_client_name(chan), subc, class, mthd, data);
+                          chan ? chan->object.client->name : "unknown",
+                          subc, class, mthd, data);
        }
 
        nvkm_fifo_chan_put(device->fifo, flags, &chan);
index 4db2a17f5308bc9328cd24873dd4ffd7e2915144..e716ae12b55ce9365a11719c740eaf48b5897005 100644 (file)
@@ -353,7 +353,8 @@ nv40_gr_intr(struct nvkm_subdev *subdev)
                                   "class %04x mthd %04x data %08x\n",
                           show, msg, nsource, src, nstatus, sta,
                           chan ? chan->fifo->chid : -1, inst << 4,
-                          nvkm_client_name(chan), subc, class, mthd, data);
+                          chan ? chan->fifo->object.client->name : "unknown",
+                          subc, class, mthd, data);
        }
 
        spin_unlock_irqrestore(&gr->base.engine.lock, flags);
index daac54075705f3802af3a2e16ce6cc336fd971c5..5f22dd3c788cc99729c47bc5f72226a795e31a26 100644 (file)
@@ -608,7 +608,7 @@ nv50_gr_tp_trap(struct nv50_gr *gr, int type, u32 ustatus_old,
 
 static int
 nv50_gr_trap_handler(struct nv50_gr *gr, u32 display,
-                    int chid, u64 inst, struct nvkm_fifo_chan *chan)
+                    int chid, u64 inst, const char *name)
 {
        struct nvkm_subdev *subdev = &gr->base.engine.subdev;
        struct nvkm_device *device = subdev->device;
@@ -648,8 +648,7 @@ nv50_gr_trap_handler(struct nv50_gr *gr, u32 display,
                                           "ch %d [%010llx %s] subc %d "
                                           "class %04x mthd %04x data %08x%08x "
                                           "400808 %08x 400848 %08x\n",
-                                          chid, inst, nvkm_client_name(chan),
-                                          subc, class, mthd,
+                                          chid, inst, name, subc, class, mthd,
                                           datah, datal, addr, r848);
                        } else
                        if (display) {
@@ -674,9 +673,8 @@ nv50_gr_trap_handler(struct nv50_gr *gr, u32 display,
                                nvkm_error(subdev,
                                           "ch %d [%010llx %s] subc %d "
                                           "class %04x mthd %04x data %08x "
-                                          "40084c %08x\n", chid, inst,
-                                          nvkm_client_name(chan), subc,
-                                          class, mthd, data, addr);
+                                          "40084c %08x\n", chid, inst, name,
+                                          subc, class, mthd, data, addr);
                        } else
                        if (display) {
                                nvkm_error(subdev, "no stuck command?\n");
@@ -849,11 +847,15 @@ nv50_gr_intr(struct nvkm_subdev *subdev)
        u32 show = stat, show_bitfield = stat;
        const struct nvkm_enum *en;
        unsigned long flags;
+       const char *name = "unknown";
        char msg[128];
-       int chid;
+       int chid = -1;
 
        chan = nvkm_fifo_chan_inst(device->fifo, (u64)inst << 12, &flags);
-       chid = chan ? chan->chid : -1;
+       if (chan)  {
+               name = chan->object.client->name;
+               chid = chan->chid;
+       }
 
        if (show & 0x00100000) {
                u32 ecode = nvkm_rd32(device, 0x400110);
@@ -864,7 +866,7 @@ nv50_gr_intr(struct nvkm_subdev *subdev)
        }
 
        if (stat & 0x00200000) {
-               if (!nv50_gr_trap_handler(gr, show, chid, (u64)inst << 12, chan))
+               if (!nv50_gr_trap_handler(gr, show, chid, (u64)inst << 12, name))
                        show &= ~0x00200000;
                show_bitfield &= ~0x00200000;
        }
@@ -877,8 +879,8 @@ nv50_gr_intr(struct nvkm_subdev *subdev)
                nvkm_snprintbf(msg, sizeof(msg), nv50_gr_intr_name, show);
                nvkm_error(subdev, "%08x [%s] ch %d [%010llx %s] subc %d "
                                   "class %04x mthd %04x data %08x\n",
-                          stat, msg, chid, (u64)inst << 12,
-                          nvkm_client_name(chan), subc, class, mthd, data);
+                          stat, msg, chid, (u64)inst << 12, name,
+                          subc, class, mthd, data);
        }
 
        if (nvkm_rd32(device, 0x400824) & (1 << 31))
index 05597f2070ed7a75c1cdc71acd2055ee2662aa69..211b44c00c850a778dcf26b9720167ea8fe4fa75 100644 (file)
@@ -231,8 +231,8 @@ nv31_mpeg_intr(struct nvkm_subdev *subdev)
        if (show) {
                nvkm_error(subdev, "ch %d [%s] %08x %08x %08x %08x\n",
                           mpeg->chan ? mpeg->chan->fifo->chid : -1,
-                          nvkm_client_name(mpeg->chan),
-                          stat, type, mthd, data);
+                          mpeg->chan ? mpeg->chan->fifo->object.client->name :
+                          "unknown", stat, type, mthd, data);
        }
 
        spin_unlock_irqrestore(&mpeg->base.engine.lock, flags);
index 1223baddfb9abb46cce9a97b24e14bef3463708a..ff9ddc67a292139151b7d5c4bf50e98a3820c9b7 100644 (file)
@@ -145,13 +145,11 @@ nv44_mpeg_intr(struct nvkm_subdev *subdev)
        u32 mthd = nvkm_rd32(device, 0x00b234);
        u32 data = nvkm_rd32(device, 0x00b238);
        u32 show = stat;
-       int chid = -1;
 
        spin_lock_irqsave(&mpeg->base.engine.lock, flags);
        list_for_each_entry(temp, &mpeg->chan, head) {
                if (temp->inst >> 4 == inst) {
                        chan = temp;
-                       chid = chan->fifo->chid;
                        list_del(&chan->head);
                        list_add(&chan->head, &mpeg->chan);
                        break;
@@ -176,7 +174,8 @@ nv44_mpeg_intr(struct nvkm_subdev *subdev)
 
        if (show) {
                nvkm_error(subdev, "ch %d [%08x %s] %08x %08x %08x %08x\n",
-                          chid, inst << 4, nvkm_client_name(chan),
+                          chan ? chan->fifo->chid : -1, inst << 4,
+                          chan ? chan->fifo->object.client->name : "unknown",
                           stat, type, mthd, data);
        }
 
index e6544097726c480d1d32e2fac941d79d86086868..c15934d7ff63a5ef4408399c2eeeedd070a1f04b 100644 (file)
@@ -84,7 +84,8 @@ g98_sec_intr(struct nvkm_falcon *sec, struct nvkm_fifo_chan *chan)
        nvkm_error(subdev, "DISPATCH_ERROR %04x [%s] ch %d [%010llx %s] "
                           "subc %d mthd %04x data %08x\n", ssta,
                   en ? en->name : "UNKNOWN", chan ? chan->chid : -1,
-                  chan ? chan->inst : 0, nvkm_client_name(chan),
+                  chan ? chan->inst->addr : 0,
+                  chan ? chan->object.client->name : "unknown",
                   subc, mthd, data);
 }
 
index 4e8b632ef5b167c3d55c80b78894f57be0af4a7f..35ec1cffb53a255bcbf0d8aaec4698c1100e4f43 100644 (file)
@@ -24,8 +24,8 @@
 #include "nv50.h"
 
 #include <core/handle.h>
-#include <core/namedb.h>
 #include <engine/disp.h>
+#include <engine/fifo/chan.h>
 #include <subdev/bar.h>
 
 #include <nvif/event.h>
@@ -136,7 +136,7 @@ nv50_sw_context_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
                        return ret;
        }
 
-       chan->vblank.channel = nv_gpuobj(parent->parent)->addr >> 12;
+       chan->vblank.channel = nvkm_fifo_chan(parent)->inst->addr >> 12;
        return 0;
 }
 
index 4a88bbd814b76b3c040a836e809ae183ac3f3324..383030434079b61ef8b99b55dde75bd50b0353f1 100644 (file)
@@ -338,7 +338,7 @@ void
 gt215_clk_post(struct nvkm_clk *clk, unsigned long *flags)
 {
        struct nvkm_device *device = clk->subdev.device;
-       struct nvkm_fifo *fifo = nvkm_fifo(clk);
+       struct nvkm_fifo *fifo = device->fifo;
 
        if (fifo && flags)
                fifo->start(fifo, flags);
index ea83f7d9ddc81dfc6b65faca099889d70623e01d..711ea96bcd36ab8af74f8270f1a384cabbe100f7 100644 (file)
@@ -189,12 +189,14 @@ nv50_fb_intr(struct nvkm_subdev *subdev)
        else                     sc = NULL;
 
        chan = nvkm_fifo_chan_inst(fifo, inst, &flags);
-       nvkm_error(subdev, "trapped %s at %02x%04x%04x on channel "
-                          "%08x [%s] engine %02x [%s] client %02x [%s] "
+       nvkm_error(subdev, "trapped %s at %02x%04x%04x on channel %d [%08x %s] "
+                          "engine %02x [%s] client %02x [%s] "
                           "subclient %02x [%s] reason %08x [%s]\n",
                   (trap[5] & 0x00000100) ? "read" : "write",
-                  trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, inst,
-                  nvkm_client_name(chan), st0, en ? en->name : "",
+                  trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff,
+                  chan ? chan->chid : -1, inst,
+                  chan ? chan->object.client->name : "unknown",
+                  st0, en ? en->name : "",
                   st2, cl ? cl->name : "", st3, sc ? sc->name : "",
                   st1, re ? re->name : "");
        nvkm_fifo_chan_put(fifo, flags, &chan);