diff options
author | Alexandre Courbot <acourbot@nvidia.com> | 2014-05-09 18:16:36 +0900 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2014-08-07 16:54:54 +0200 |
commit | 6b4454658a0318998405dc06fcd12ccb55c53201 (patch) | |
tree | 388b962049d2223cefcdf8ff1312e70962054a38 | |
parent | 0d87ef24693bf40cb0996c995cadecd23873c96f (diff) |
[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-- | drivers/gpu/drm/nouveau/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/device/nve0.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/include/subdev/instmem.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/fb/ramgk20a.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/fb/ramgk20a.h | 38 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/instmem/gk20a.c | 138 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bo.c | 5 |
7 files changed, 185 insertions, 8 deletions
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 9e8298719a64..cf5e7caee43d 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -149,6 +149,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/ltcg/gf100.o nouveau-y += core/subdev/ltcg/gm107.o nouveau-y += core/subdev/mc/base.o diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nve0.c b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c index 2d1e97d4264f..68aa0db1ec7b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c @@ -163,7 +163,7 @@ nve0_identify(struct nouveau_device *device) device->oclass[NVDEV_SUBDEV_TIMER ] = &gk20a_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = gk20a_fb_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 ] = &nvc0_bar_oclass; device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass; diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h b/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h index c1df26f3230c..6264660bedce 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h +++ b/drivers/gpu/drm/nouveau/core/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/drivers/gpu/drm/nouveau/core/subdev/fb/ramgk20a.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramgk20a.c index 10cdcf8b8a7f..1b8b91dc5ba2 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramgk20a.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramgk20a.c @@ -21,6 +21,7 @@ */ #include "priv.h" +#include "ramgk20a.h" #include <subdev/fb.h> @@ -28,13 +29,6 @@ #include <linux/mm.h> #include <linux/dma-mapping.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/drivers/gpu/drm/nouveau/core/subdev/fb/ramgk20a.h b/drivers/gpu/drm/nouveau/core/subdev/fb/ramgk20a.h new file mode 100644 index 000000000000..105ad2581692 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/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/drivers/gpu/drm/nouveau/core/subdev/instmem/gk20a.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/gk20a.c new file mode 100644 index 000000000000..0bcbba09eb0d --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/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 "core/subdev/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; diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 28e3daef0a5a..825da2332516 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -33,6 +33,7 @@ #include <subdev/fb.h> #include <subdev/vm.h> #include <subdev/bar.h> +#include <subdev/timer.h> #include "nouveau_drm.h" #include "nouveau_dma.h" @@ -518,6 +519,10 @@ nouveau_bo_sync_for_device(struct nouveau_bo *nvbo) ttm_dma_tt_cache_sync_for_device((struct ttm_dma_tt *)ttm, nv_device_base(device)); + + nv_wr32(device, 0x70004, 0x00000001); + if (!nv_wait(device, 0x070004, 0x00000001, 0x00000000)) + nv_warn(device, "L2 invalidate timeout\n"); } } |