summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandre Courbot <acourbot@nvidia.com>2014-05-09 18:16:36 +0900
committerAlexandre Courbot <acourbot@nvidia.com>2014-11-04 13:13:05 +0900
commit6d4c1d14f7bb864522721d7c4a76d23ba84ef301 (patch)
treeb7345299dc51cb7f825b7856a155cb467633ea2f
parent524879f4efc9e626fa1862ded6f0a16018ff545d (diff)
downloadnouveau-6d4c1d14f7bb864522721d7c4a76d23ba84ef301.tar.gz
[HACK] add gk20a instmem
This is a gazillion times faster, but requires to invalidate the GPU L2 (probably at a better place than this!)
-rw-r--r--drm/Kbuild1
-rw-r--r--drm/nouveau_bo.c10
-rw-r--r--nvkm/engine/device/nve0.c2
-rw-r--r--nvkm/include/subdev/instmem.h1
-rw-r--r--nvkm/subdev/fb/ramgk20a.c8
-rw-r--r--nvkm/subdev/fb/ramgk20a.h38
-rw-r--r--nvkm/subdev/instmem/Makefile.am3
-rw-r--r--nvkm/subdev/instmem/gk20a.c138
8 files changed, 192 insertions, 9 deletions
diff --git a/drm/Kbuild b/drm/Kbuild
index 12c24c8ab..74ad7f4a9 100644
--- a/drm/Kbuild
+++ b/drm/Kbuild
@@ -161,6 +161,7 @@ nouveau-y += core/subdev/instmem/base.o
nouveau-y += core/subdev/instmem/nv04.o
nouveau-y += core/subdev/instmem/nv40.o
nouveau-y += core/subdev/instmem/nv50.o
+nouveau-y += core/subdev/instmem/gk20a.o
nouveau-y += core/subdev/ltc/base.o
nouveau-y += core/subdev/ltc/gf100.o
nouveau-y += core/subdev/ltc/gk104.o
diff --git a/drm/nouveau_bo.c b/drm/nouveau_bo.c
index d2a4768e3..b9ba600dd 100644
--- a/drm/nouveau_bo.c
+++ b/drm/nouveau_bo.c
@@ -470,6 +470,8 @@ int
nouveau_bo_validate(struct nouveau_bo *nvbo, bool interruptible,
bool no_wait_gpu)
{
+ struct nouveau_device *device;
+ struct ttm_tt *ttm = nvbo->bo.ttm;
int ret;
ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement,
@@ -479,6 +481,14 @@ nouveau_bo_validate(struct nouveau_bo *nvbo, bool interruptible,
nouveau_bo_sync_for_device(nvbo);
+ if (!ttm)
+ return ret;
+
+ device = nvkm_device(&nouveau_bdev(ttm->bdev)->device);
+ nv_wr32(device, 0x70004, 0x00000001);
+ if (!nv_wait(device, 0x070004, 0x00000001, 0x00000000))
+ nv_warn(device, "L2 invalidate timeout\n");
+
return 0;
}
diff --git a/nvkm/engine/device/nve0.c b/nvkm/engine/device/nve0.c
index b1b2e484e..54c934173 100644
--- a/nvkm/engine/device/nve0.c
+++ b/nvkm/engine/device/nve0.c
@@ -170,7 +170,7 @@ nve0_identify(struct nouveau_device *device)
device->oclass[NVDEV_SUBDEV_FB ] = gk20a_fb_oclass;
device->oclass[NVDEV_SUBDEV_LTC ] = gk104_ltc_oclass;
device->oclass[NVDEV_SUBDEV_IBUS ] = &gk20a_ibus_oclass;
- device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = gk20a_instmem_oclass;
device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
device->oclass[NVDEV_SUBDEV_BAR ] = &gk20a_bar_oclass;
device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass;
diff --git a/nvkm/include/subdev/instmem.h b/nvkm/include/subdev/instmem.h
index c1df26f32..6264660be 100644
--- a/nvkm/include/subdev/instmem.h
+++ b/nvkm/include/subdev/instmem.h
@@ -48,5 +48,6 @@ nouveau_instmem(void *obj)
extern struct nouveau_oclass *nv04_instmem_oclass;
extern struct nouveau_oclass *nv40_instmem_oclass;
extern struct nouveau_oclass *nv50_instmem_oclass;
+extern struct nouveau_oclass *gk20a_instmem_oclass;
#endif
diff --git a/nvkm/subdev/fb/ramgk20a.c b/nvkm/subdev/fb/ramgk20a.c
index c8d428ac8..873b1ebfd 100644
--- a/nvkm/subdev/fb/ramgk20a.c
+++ b/nvkm/subdev/fb/ramgk20a.c
@@ -21,16 +21,10 @@
*/
#include "priv.h"
+#include "ramgk20a.h"
#include <subdev/fb.h>
-struct gk20a_mem {
- struct nouveau_mem base;
- void *cpuaddr;
- dma_addr_t handle;
-};
-#define to_gk20a_mem(m) container_of(m, struct gk20a_mem, base)
-
static void
gk20a_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem)
{
diff --git a/nvkm/subdev/fb/ramgk20a.h b/nvkm/subdev/fb/ramgk20a.h
new file mode 100644
index 000000000..105ad2581
--- /dev/null
+++ b/nvkm/subdev/fb/ramgk20a.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ *
+ * 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+
+#ifndef __NVKM_FB_RAMGK20A_H__
+#define __NVKM_FB_RAMGK20A_H__
+
+#include <linux/types.h>
+#include <subdev/fb.h>
+
+struct gk20a_mem {
+ struct nouveau_mem base;
+ void *cpuaddr;
+ dma_addr_t handle;
+};
+
+#define to_gk20a_mem(m) container_of(m, struct gk20a_mem, base)
+
+#endif
diff --git a/nvkm/subdev/instmem/Makefile.am b/nvkm/subdev/instmem/Makefile.am
index c014032c9..129da9b63 100644
--- a/nvkm/subdev/instmem/Makefile.am
+++ b/nvkm/subdev/instmem/Makefile.am
@@ -3,6 +3,7 @@ noinst_LTLIBRARIES = libinstmem.la
libinstmem_la_SOURCES = base.c \
nv04.c \
nv40.c \
- nv50.c
+ nv50.c \
+ gk20a.c
include $(srcdir)/../Makefile.subdev
diff --git a/nvkm/subdev/instmem/gk20a.c b/nvkm/subdev/instmem/gk20a.c
new file mode 100644
index 000000000..85a06bb10
--- /dev/null
+++ b/nvkm/subdev/instmem/gk20a.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ *
+ * 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include <subdev/fb.h>
+
+#include "priv.h"
+#include "../fb/ramgk20a.h"
+
+struct gk20a_instmem_priv {
+ struct nouveau_instmem base;
+};
+
+struct gk20a_instobj_priv {
+ struct nouveau_instobj base;
+ struct nouveau_mem *mem;
+};
+
+static u32
+gk20a_instobj_rd32(struct nouveau_object *object, u64 offset)
+{
+ struct gk20a_instobj_priv *node = (void *)object;
+ struct gk20a_mem *mem = to_gk20a_mem(node->mem);
+
+ return ((u32 *)mem->cpuaddr)[offset / 4];
+}
+
+static void
+gk20a_instobj_wr32(struct nouveau_object *object, u64 offset, u32 data)
+{
+ struct gk20a_instobj_priv *node = (void *)object;
+ struct gk20a_mem *mem = to_gk20a_mem(node->mem);
+
+ ((u32 *)mem->cpuaddr)[offset / 4] = data;
+}
+
+static void
+gk20a_instobj_dtor(struct nouveau_object *object)
+{
+ struct gk20a_instobj_priv *node = (void *)object;
+ struct nouveau_fb *pfb = nouveau_fb(object);
+
+ pfb->ram->put(pfb, &node->mem);
+ nouveau_instobj_destroy(&node->base);
+}
+
+static int
+gk20a_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ struct nouveau_oclass *oclass, void *data, u32 size,
+ struct nouveau_object **pobject)
+{
+ struct nouveau_fb *pfb = nouveau_fb(parent);
+ struct nouveau_instobj_args *args = data;
+ struct gk20a_instobj_priv *node;
+ int ret;
+
+ args->size = max((args->size + 4095) & ~4095, (u32)4096);
+ args->align = max((args->align + 4095) & ~4095, (u32)4096);
+
+ ret = nouveau_instobj_create(parent, engine, oclass, &node);
+ *pobject = nv_object(node);
+ if (ret)
+ return ret;
+
+ ret = pfb->ram->get(pfb, args->size, args->align, 0, 0x800, &node->mem);
+ if (ret)
+ return ret;
+
+ node->base.addr = node->mem->offset;
+ node->base.size = node->mem->size << 12;
+ node->mem->page_shift = 12;
+ return 0;
+}
+
+static struct nouveau_instobj_impl
+gk20a_instobj_oclass = {
+ .base.ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = gk20a_instobj_ctor,
+ .dtor = gk20a_instobj_dtor,
+ .init = _nouveau_instobj_init,
+ .fini = _nouveau_instobj_fini,
+ .rd32 = gk20a_instobj_rd32,
+ .wr32 = gk20a_instobj_wr32,
+ },
+};
+
+static int
+gk20a_instmem_fini(struct nouveau_object *object, bool suspend)
+{
+ struct gk20a_instmem_priv *priv = (void *)object;
+ return nouveau_instmem_fini(&priv->base, suspend);
+}
+
+static int
+gk20a_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ struct nouveau_oclass *oclass, void *data, u32 size,
+ struct nouveau_object **pobject)
+{
+ struct gk20a_instmem_priv *priv;
+ int ret;
+
+ ret = nouveau_instmem_create(parent, engine, oclass, &priv);
+ *pobject = nv_object(priv);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+struct nouveau_oclass *
+gk20a_instmem_oclass = &(struct nouveau_instmem_impl) {
+ .base.handle = NV_SUBDEV(INSTMEM, 0xea),
+ .base.ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = gk20a_instmem_ctor,
+ .dtor = _nouveau_instmem_dtor,
+ .init = _nouveau_instmem_init,
+ .fini = gk20a_instmem_fini,
+ },
+ .instobj = &gk20a_instobj_oclass.base,
+}.base;