diff --git a/Makefile.umbrella.tmk b/Makefile.umbrella.tmk index af7ce5033..c81457d9d 100644 --- a/Makefile.umbrella.tmk +++ b/Makefile.umbrella.tmk @@ -66,6 +66,7 @@ NV_REPOSITORY_COMPONENTS += userspace/units/fifo NV_REPOSITORY_COMPONENTS += userspace/units/fifo/channel NV_REPOSITORY_COMPONENTS += userspace/units/fifo/runlist NV_REPOSITORY_COMPONENTS += userspace/units/fifo/tsg +NV_REPOSITORY_COMPONENTS += userspace/units/fifo/tsg/gv11b NV_REPOSITORY_COMPONENTS += userspace/units/fuse NV_REPOSITORY_COMPONENTS += userspace/units/list NV_REPOSITORY_COMPONENTS += userspace/units/enabled diff --git a/drivers/gpu/nvgpu/hal/fifo/tsg_gv11b_fusa.c b/drivers/gpu/nvgpu/hal/fifo/tsg_gv11b_fusa.c index b606e2d1c..f4200eea7 100644 --- a/drivers/gpu/nvgpu/hal/fifo/tsg_gv11b_fusa.c +++ b/drivers/gpu/nvgpu/hal/fifo/tsg_gv11b_fusa.c @@ -102,26 +102,13 @@ void gv11b_tsg_bind_channel_eng_method_buffers(struct nvgpu_tsg *tsg, g->ops.ramin.set_eng_method_buffer(g, &ch->inst_block, gpu_va); } -static u32 gv11b_tsg_get_eng_method_buffer_size(struct gk20a *g) -{ - u32 buffer_size; - u32 page_size = U32(PAGE_SIZE); - - buffer_size = nvgpu_safe_add_u32(nvgpu_safe_mult_u32((9U + 1U + 3U), - g->ops.ce.get_num_pce(g)), 2U); - buffer_size = nvgpu_safe_mult_u32((27U * 5U), buffer_size); - buffer_size = roundup(buffer_size, page_size); - nvgpu_log_info(g, "method buffer size in bytes %d", buffer_size); - - return buffer_size; -} - int gv11b_tsg_init_eng_method_buffers(struct gk20a *g, struct nvgpu_tsg *tsg) { struct vm_gk20a *vm = g->mm.bar2.vm; int err = 0; int i; - unsigned int runque, method_buffer_size; + unsigned int runque, buffer_size; + u32 page_size = U32(PAGE_SIZE); unsigned int num_pbdma = g->fifo.num_pbdma; if (tsg->eng_method_buffers != NULL) { @@ -129,11 +116,11 @@ int gv11b_tsg_init_eng_method_buffers(struct gk20a *g, struct nvgpu_tsg *tsg) return 0; } - method_buffer_size = gv11b_tsg_get_eng_method_buffer_size(g); - if (method_buffer_size == 0U) { - nvgpu_info(g, "ce will hit MTHD_BUFFER_FAULT"); - return -EINVAL; - } + buffer_size = nvgpu_safe_add_u32(nvgpu_safe_mult_u32((9U + 1U + 3U), + g->ops.ce.get_num_pce(g)), 2U); + buffer_size = nvgpu_safe_mult_u32((27U * 5U), buffer_size); + buffer_size = roundup(buffer_size, page_size); + nvgpu_log_info(g, "method buffer size in bytes %d", buffer_size); tsg->eng_method_buffers = nvgpu_kzalloc(g, num_pbdma * sizeof(struct nvgpu_mem)); @@ -143,7 +130,7 @@ int gv11b_tsg_init_eng_method_buffers(struct gk20a *g, struct nvgpu_tsg *tsg) } for (runque = 0; runque < num_pbdma; runque++) { - err = nvgpu_dma_alloc_map_sys(vm, method_buffer_size, + err = nvgpu_dma_alloc_map_sys(vm, buffer_size, &tsg->eng_method_buffers[runque]); if (err != 0) { nvgpu_err(g, "alloc eng method buffers, runque=%d", diff --git a/drivers/gpu/nvgpu/libnvgpu-drv_safe.export b/drivers/gpu/nvgpu/libnvgpu-drv_safe.export index 1437ee6e6..c100d5901 100644 --- a/drivers/gpu/nvgpu/libnvgpu-drv_safe.export +++ b/drivers/gpu/nvgpu/libnvgpu-drv_safe.export @@ -207,6 +207,8 @@ nvgpu_dma_alloc_map_sys nvgpu_dma_alloc_sys nvgpu_dma_free nvgpu_dma_unmap_free +nvgpu_engine_get_fast_ce_runlist_id +nvgpu_engine_get_gr_runlist_id nvgpu_get nvgpu_falcon_bl_bootstrap nvgpu_falcon_bootstrap diff --git a/userspace/Makefile.sources b/userspace/Makefile.sources index f50f3cff5..26a2eb5df 100644 --- a/userspace/Makefile.sources +++ b/userspace/Makefile.sources @@ -74,6 +74,7 @@ UNITS := \ $(UNIT_SRC)/fifo/channel \ $(UNIT_SRC)/fifo/runlist \ $(UNIT_SRC)/fifo/tsg \ + $(UNIT_SRC)/fifo/tsg/gv11b \ $(UNIT_SRC)/list \ $(UNIT_SRC)/enabled \ $(UNIT_SRC)/falcon \ diff --git a/userspace/SWUTS.h b/userspace/SWUTS.h index 8132ef3e5..0085f31d8 100644 --- a/userspace/SWUTS.h +++ b/userspace/SWUTS.h @@ -39,6 +39,7 @@ * - @ref SWUTS-fifo-channel * - @ref SWUTS-fifo-runlist * - @ref SWUTS-fifo-tsg + * - @ref SWUTS-fifo-tsg-gv11b * - @ref SWUTS-init * - @ref SWUTS-interface-atomic * - @ref SWUTS-mm-allocators-bitmap-allocator diff --git a/userspace/SWUTS.sources b/userspace/SWUTS.sources index 81bc3df0c..b4f83acb3 100644 --- a/userspace/SWUTS.sources +++ b/userspace/SWUTS.sources @@ -9,6 +9,7 @@ INPUT += ../../../userspace/units/fifo/nvgpu-fifo.h INPUT += ../../../userspace/units/fifo/channel/nvgpu-channel.h INPUT += ../../../userspace/units/fifo/runlist/nvgpu-runlist.h INPUT += ../../../userspace/units/fifo/tsg/nvgpu-tsg.h +INPUT += ../../../userspace/units/fifo/tsg/gv11b/nvgpu-tsg-gv11b.h INPUT += ../../../userspace/units/fuse/nvgpu-fuse.h INPUT += ../../../userspace/units/fuse/nvgpu-fuse-gm20b.h INPUT += ../../../userspace/units/fuse/nvgpu-fuse-gp10b.h diff --git a/userspace/units/fifo/nvgpu-fifo-gv11b.c b/userspace/units/fifo/nvgpu-fifo-gv11b.c index f3361e87b..fe57989c9 100644 --- a/userspace/units/fifo/nvgpu-fifo-gv11b.c +++ b/userspace/units/fifo/nvgpu-fifo-gv11b.c @@ -13476,9 +13476,24 @@ static struct nvgpu_posix_io_callbacks test_reg_callbacks = { .tegra_fuse_readl = tegra_fuse_readl_access_reg_fn, }; +struct test_reg_space { + u32 base; + u32 size; + u32 *data; + void (*init)(u32 *data, u32 size); +}; -#define fifo_array_reg_space(x) sizeof(x)/sizeof(struct nvgpu_posix_io_reg_space) -struct nvgpu_posix_io_reg_space fifo_gv11b_initialized_reg_space[] = { +static void init_reg_space_usermode(u32 *data, u32 size) +{ + u32 i; + + for (i = 0U; i < size/4U; i++) { + data[i] = 0xbadf1100; + } +} + +#define NUM_REG_SPACES 11U +struct test_reg_space reg_spaces[NUM_REG_SPACES] = { [0] = { /* FUSE */ .base = 0x00021000, .size = sizeof(gv11b_fuse_regs), @@ -13508,38 +13523,56 @@ struct nvgpu_posix_io_reg_space fifo_gv11b_initialized_reg_space[] = { .base = 0x2000, .size = sizeof(gv11b_fifo_regs), .data = gv11b_fifo_regs, - } + }, + [6] = { /* USERMODE */ + .base = usermode_cfg0_r(), + .size = 0x10000, + .data = NULL, + .init = init_reg_space_usermode, + }, + [7] = { /* CE */ + .base = 0x104000, + .size = 0x2000, + .data = NULL, + }, + [8] = { /* PBUS */ + .base = 0x1000, + .size = 0x1000, + .data = NULL, + }, + [9] = { /* HSUB_COMMON */ + .base = 0x1fbc00, + .size = 0x400, + .data = NULL, + }, + [10] = { /* PFB */ + .base = 0x100000, + .size = 0x1000, + .data = NULL, + }, }; -struct nvgpu_posix_io_reg_space gv11b_usermode_reg_space = { - .base = 0x00810000, - .size = 0x10000, - .data = NULL, -}; - -static void fifo_io_delete_initialized_reg_space(struct unit_module *m, struct gk20a *g) +static void fifo_io_delete_reg_spaces(struct unit_module *m, struct gk20a *g) { u32 i = 0; - u32 arr_size = fifo_array_reg_space(fifo_gv11b_initialized_reg_space); - for (i = 0; i < arr_size; i++) { - u32 base = fifo_gv11b_initialized_reg_space[i].base; + for (i = 0; i < NUM_REG_SPACES; i++) { + u32 base = reg_spaces[i].base; nvgpu_posix_io_delete_reg_space(g, base); } } -static int fifo_io_add_initialized_reg_space(struct unit_module *m, struct gk20a *g) +static int fifo_io_add_reg_spaces(struct unit_module *m, struct gk20a *g) { int ret = 0; - u32 arr_size = fifo_array_reg_space(fifo_gv11b_initialized_reg_space); u32 i = 0, j = 0; u32 base, size; struct nvgpu_posix_io_reg_space *reg_space; - for (i = 0; i < arr_size; i++) { - base = fifo_gv11b_initialized_reg_space[i].base; - size = fifo_gv11b_initialized_reg_space[i].size; + for (i = 0; i < NUM_REG_SPACES; i++) { + base = reg_spaces[i].base; + size = reg_spaces[i].size; if (nvgpu_posix_io_add_reg_space(g, base, size) != 0) { unit_err(m, "failed to add reg space for %08x\n", base); @@ -13552,16 +13585,26 @@ static int fifo_io_add_initialized_reg_space(struct unit_module *m, struct gk20a unit_err(m, "failed to get reg space for %08x\n", base); ret = -EINVAL; goto clean_init_reg_space; + } else { + unit_info(m, " IO reg space %08x:%08x\n", base + size -1, base); } - memcpy(reg_space->data, fifo_gv11b_initialized_reg_space[i].data, size); + if (reg_spaces[i].data != NULL) { + memcpy(reg_space->data, reg_spaces[i].data, size); + } else { + if (reg_spaces[i].init != NULL) { + reg_spaces[i].init(reg_space->data, size); + } else { + memset(reg_space->data, 0, size); + } + } } return ret; clean_init_reg_space: for (j = 0; j < i; j++) { - base = fifo_gv11b_initialized_reg_space[j].base; + base = reg_spaces[j].base; nvgpu_posix_io_delete_reg_space(g, base); } @@ -13570,46 +13613,20 @@ clean_init_reg_space: int test_fifo_setup_gv11b_reg_space(struct unit_module *m, struct gk20a *g) { - u32 i; - struct nvgpu_posix_io_reg_space *reg_space; - /* Create register space */ nvgpu_posix_io_init_reg_space(g); - if (fifo_io_add_initialized_reg_space(m, g) != 0) { + if (fifo_io_add_reg_spaces(m, g) != 0) { unit_err(m, "failed to get initialized reg space\n"); return UNIT_FAIL; } - /* USERMODE reg space */ - if (nvgpu_posix_io_add_reg_space(g, usermode_cfg0_r(), 0x10000) != 0) { - unit_err(m, "Add USERMODE reg space failed!\n"); - goto clean_up_reg_space; - } - - reg_space = nvgpu_posix_io_get_reg_space(g, usermode_cfg0_r()); - if (reg_space == NULL) { - unit_err(m, "failed to get reg space for %08x\n", - usermode_cfg0_r()); - goto clean_up_reg_space; - } - - for (i = 0U; i < reg_space->size / 4U; i++) { - reg_space->data[i] = 0xbadf1100; - } - (void)nvgpu_posix_register_io(g, &test_reg_callbacks); return 0; - -clean_up_reg_space: - nvgpu_posix_io_delete_reg_space(g, usermode_cfg0_r()); - fifo_io_delete_initialized_reg_space(m, g); - return -ENOMEM; } void test_fifo_cleanup_gv11b_reg_space(struct unit_module *m, struct gk20a *g) { - nvgpu_posix_io_delete_reg_space(g, usermode_cfg0_r()); - fifo_io_delete_initialized_reg_space(m, g); + fifo_io_delete_reg_spaces(m, g); } diff --git a/userspace/units/fifo/nvgpu-fifo.c b/userspace/units/fifo/nvgpu-fifo.c index 744e7a9cc..c06568b10 100644 --- a/userspace/units/fifo/nvgpu-fifo.c +++ b/userspace/units/fifo/nvgpu-fifo.c @@ -110,7 +110,6 @@ int test_fifo_init_support(struct unit_module *m, struct gk20a *g, void *args) gv11b_init_hal(g); g->ops.fifo.init_fifo_setup_hw = NULL; g->ops.gr.init.get_no_of_sm = stub_gv11b_gr_init_get_no_of_sm; - g->ops.tsg.init_eng_method_buffers = NULL; global_m = m; @@ -122,6 +121,7 @@ int test_fifo_init_support(struct unit_module *m, struct gk20a *g, void *args) */ g->ops.userd.setup_sw = stub_userd_setup_sw; #endif + g->ops.mm.init_mm_support(g); err = nvgpu_fifo_init_support(g); if (err != 0) { diff --git a/userspace/units/fifo/tsg/Makefile.interface.tmk b/userspace/units/fifo/tsg/Makefile.interface.tmk index 0da0823ad..b34119718 100644 --- a/userspace/units/fifo/tsg/Makefile.interface.tmk +++ b/userspace/units/fifo/tsg/Makefile.interface.tmk @@ -26,7 +26,7 @@ NVGPU_UNIT_NAME=nvgpu-tsg -include $(NV_COMPONENT_DIR)/../../Makefile.units.common.interface.tmk +include $(NV_SOURCE)/kernel/nvgpu/userspace/units/Makefile.units.common.interface.tmk # Local Variables: # indent-tabs-mode: t diff --git a/userspace/units/fifo/tsg/Makefile.tmk b/userspace/units/fifo/tsg/Makefile.tmk index f8623f91b..d7a10e5f0 100644 --- a/userspace/units/fifo/tsg/Makefile.tmk +++ b/userspace/units/fifo/tsg/Makefile.tmk @@ -28,10 +28,10 @@ NVGPU_UNIT_NAME = nvgpu-tsg NVGPU_UNIT_SRCS = nvgpu-tsg.c NVGPU_UNIT_INTERFACE_DIRS := \ - $(NV_COMPONENT_DIR)/.. \ + $(NV_SOURCE)/kernel/nvgpu/userspace/units/fifo \ $(NV_SOURCE)/kernel/nvgpu/drivers/gpu/nvgpu -include $(NV_COMPONENT_DIR)/../../Makefile.units.common.tmk +include $(NV_SOURCE)/kernel/nvgpu/userspace/units/Makefile.units.common.tmk # Local Variables: # indent-tabs-mode: t diff --git a/userspace/units/fifo/tsg/gv11b/Makefile b/userspace/units/fifo/tsg/gv11b/Makefile new file mode 100644 index 000000000..6878e1c40 --- /dev/null +++ b/userspace/units/fifo/tsg/gv11b/Makefile @@ -0,0 +1,32 @@ +# Copyright (c) 2019, 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. + +.SUFFIXES: + +OBJS = nvgpu-tsg-gv11b.o +MODULE = nvgpu-tsg-gv11b + +LIB_PATHS += -lnvgpu-fifo +include ../../../Makefile.units + +lib$(MODULE).so: fifo + +fifo: + $(MAKE) -C ../.. diff --git a/userspace/units/fifo/tsg/gv11b/Makefile.interface.tmk b/userspace/units/fifo/tsg/gv11b/Makefile.interface.tmk new file mode 100644 index 000000000..4b84cccac --- /dev/null +++ b/userspace/units/fifo/tsg/gv11b/Makefile.interface.tmk @@ -0,0 +1,35 @@ +################################### tell Emacs this is a -*- makefile-gmake -*- +# +# Copyright (c) 2019, 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. +# +# tmake for SW Mobile component makefile +# +############################################################################### + +NVGPU_UNIT_NAME=nvgpu-tsg-gv11b + +include $(NV_SOURCE)/kernel/nvgpu/userspace/units/Makefile.units.common.interface.tmk + +# Local Variables: +# indent-tabs-mode: t +# tab-width: 8 +# End: +# vi: set tabstop=8 noexpandtab: diff --git a/userspace/units/fifo/tsg/gv11b/Makefile.tmk b/userspace/units/fifo/tsg/gv11b/Makefile.tmk new file mode 100644 index 000000000..bf2e203b6 --- /dev/null +++ b/userspace/units/fifo/tsg/gv11b/Makefile.tmk @@ -0,0 +1,40 @@ +################################### tell Emacs this is a -*- makefile-gmake -*- +# +# Copyright (c) 2019, 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. +# +# tmake for SW Mobile component makefile +# +############################################################################### + +NVGPU_UNIT_NAME = nvgpu-tsg-gv11b +NVGPU_UNIT_SRCS = nvgpu-tsg-gv11b.c + +NVGPU_UNIT_INTERFACE_DIRS := \ + $(NV_SOURCE)/kernel/nvgpu/userspace/units/fifo \ + $(NV_SOURCE)/kernel/nvgpu/drivers/gpu/nvgpu + +include $(NV_SOURCE)/kernel/nvgpu/userspace/units/Makefile.units.common.tmk + +# Local Variables: +# indent-tabs-mode: t +# tab-width: 8 +# End: +# vi: set tabstop=8 noexpandtab: diff --git a/userspace/units/fifo/tsg/gv11b/nvgpu-tsg-gv11b.c b/userspace/units/fifo/tsg/gv11b/nvgpu-tsg-gv11b.c new file mode 100644 index 000000000..d6755f6ff --- /dev/null +++ b/userspace/units/fifo/tsg/gv11b/nvgpu-tsg-gv11b.c @@ -0,0 +1,386 @@ +/* + * Copyright (c) 2019, 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 +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common/gr/ctx_priv.h" +#include + +#include "hal/fifo/tsg_gk20a.h" + +#include "hal/init/hal_gv11b.h" +#include "hal/fifo/tsg_gv11b.h" + +#include + +#include "../../nvgpu-fifo.h" +#include "nvgpu-tsg-gv11b.h" + +#ifdef TSG_GV11B_UNIT_DEBUG +#undef unit_verbose +#define unit_verbose unit_info +#else +#define unit_verbose(unit, msg, ...) \ + do { \ + if (0) { \ + unit_info(unit, msg, ##__VA_ARGS__); \ + } \ + } while (0) +#endif + +#define assert(cond) unit_assert(cond, goto done) + +struct tsg_unit_ctx { + u32 branches; +}; + +static struct tsg_unit_ctx unit_ctx; + +#define MAX_STUB 4 + +struct stub_ctx { + const char *name; + u32 count; + u32 chid; + u32 tsgid; +}; + +struct stub_ctx stub[MAX_STUB]; + +static void subtest_setup(u32 branches) +{ + u32 i; + + unit_ctx.branches = branches; + + memset(stub, 0, sizeof(stub)); + for (i = 0; i < MAX_STUB; i++) { + stub[i].name = ""; + stub[i].count = 0; + stub[i].chid = NVGPU_INVALID_CHANNEL_ID; + stub[i].tsgid = NVGPU_INVALID_TSG_ID; + } +} + +#define branches_str test_fifo_flags_str +#define pruned test_fifo_subtest_pruned + +#define GR_RUNQUE 0U /* pbdma 0 */ +#define ASYNC_CE_RUNQUE 2U /* pbdma 2 */ + +#define F_TSG_INIT_ENG_BUF_ALREADY_EXISTS BIT32(0) +#define F_TSG_INIT_ENG_BUF_KZALLOC_FAIL BIT32(1) +#define F_TSG_INIT_ENG_BUF_DMA_ALLOC_FAIL_0 BIT32(2) +#define F_TSG_INIT_ENG_BUF_DMA_ALLOC_FAIL_1 BIT32(3) +#define F_TSG_INIT_ENG_BUF_LAST BIT32(4) + +int test_gv11b_tsg_init_eng_method_buffers(struct unit_module *m, + struct gk20a *g, void *args) +{ + struct nvgpu_tsg _tsg, *tsg = &_tsg; + struct nvgpu_mem dummy; + u32 branches = 0U; + int ret = UNIT_FAIL; + u32 fail = F_TSG_INIT_ENG_BUF_KZALLOC_FAIL | + F_TSG_INIT_ENG_BUF_DMA_ALLOC_FAIL_0 | + F_TSG_INIT_ENG_BUF_DMA_ALLOC_FAIL_1; + u32 prune = F_TSG_INIT_ENG_BUF_ALREADY_EXISTS | fail; + struct nvgpu_posix_fault_inj *kmem_fi; + struct nvgpu_posix_fault_inj *dma_fi; + int err; + static const char *labels[] = { + "buf_exists", + "kzalloc_fail", + "dma_alloc_fail_0", + "dma_alloc_fail_1" + }; + + kmem_fi = nvgpu_kmem_get_fault_injection(); + dma_fi = nvgpu_dma_alloc_get_fault_injection(); + + for (branches = 0U; branches < F_TSG_INIT_ENG_BUF_LAST; branches++) { + + if (pruned(branches, prune)) { + unit_verbose(m, "%s branches=%s (pruned)\n", __func__, + branches_str(branches, labels)); + continue; + } + unit_verbose(m, "%s branches=%s\n", __func__, + branches_str(branches, labels)); + subtest_setup(branches); + + tsg->eng_method_buffers = + branches & F_TSG_INIT_ENG_BUF_ALREADY_EXISTS ? + &dummy : NULL; + + nvgpu_posix_enable_fault_injection(kmem_fi, + branches & F_TSG_INIT_ENG_BUF_KZALLOC_FAIL ? + true : false, 0); + + nvgpu_posix_enable_fault_injection(dma_fi, false, 0); + + if (branches & F_TSG_INIT_ENG_BUF_DMA_ALLOC_FAIL_0) { + nvgpu_posix_enable_fault_injection(dma_fi, true, 0); + } + + if (branches & F_TSG_INIT_ENG_BUF_DMA_ALLOC_FAIL_1) { + nvgpu_posix_enable_fault_injection(dma_fi, true, 1); + } + + err = g->ops.tsg.init_eng_method_buffers(g, tsg); + + if (branches & fail) { + assert(err != 0); + assert(tsg->eng_method_buffers == NULL); + } else { + assert(err == 0); + if ((branches & F_TSG_INIT_ENG_BUF_ALREADY_EXISTS) == 0) { + assert(tsg->eng_method_buffers != NULL); + assert(tsg->eng_method_buffers[ASYNC_CE_RUNQUE].gpu_va != 0UL); + g->ops.tsg.deinit_eng_method_buffers(g, tsg); + assert(tsg->eng_method_buffers == NULL); + } + } + } + + ret = UNIT_SUCCESS; + +done: + if (ret != UNIT_SUCCESS) { + unit_err(m, "%s branches=%s\n", __func__, + branches_str(branches, labels)); + } + + nvgpu_posix_enable_fault_injection(kmem_fi, false, 0); + nvgpu_posix_enable_fault_injection(dma_fi, false, 0); + + return ret; +} + +#define F_TSG_BIND_BUF_NO_METHOD_BUF BIT(0) +#define F_TSG_BIND_BUF_FAST_CE_RUNLIST_ID BIT(1) +#define F_TSG_BIND_BUF_LAST BIT(2) + +int test_gv11b_tsg_bind_channel_eng_method_buffers(struct unit_module *m, + struct gk20a *g, void *args) +{ + struct nvgpu_tsg *tsg = NULL; + struct nvgpu_channel *ch = NULL; + struct nvgpu_mem *eng_method_buffers; + u32 branches = 0U; + int ret = UNIT_FAIL; + u32 prune = F_TSG_BIND_BUF_NO_METHOD_BUF; + int err; + u64 gpu_va; + static const char *labels[] = { + "!eng_method_buf", + "fast_ce_runlist", + }; + + tsg = nvgpu_tsg_open(g, getpid()); + assert(tsg != NULL); + + ch = nvgpu_channel_open_new(g, ~0U, false, getpid(), getpid()); + assert(ch != NULL); + + err = nvgpu_tsg_bind_channel(tsg, ch); + assert(err == 0); + + eng_method_buffers = tsg->eng_method_buffers; + + for (branches = 0U; branches < F_TSG_BIND_BUF_LAST; branches++) { + + if (pruned(branches, prune)) { + unit_verbose(m, "%s branches=%s (pruned)\n", __func__, + branches_str(branches, labels)); + continue; + } + unit_verbose(m, "%s branches=%s\n", __func__, + branches_str(branches, labels)); + subtest_setup(branches); + + tsg->eng_method_buffers = + branches & F_TSG_BIND_BUF_NO_METHOD_BUF ? + NULL : eng_method_buffers; + + if (branches & F_TSG_BIND_BUF_FAST_CE_RUNLIST_ID) { + tsg->runlist_id = nvgpu_engine_get_fast_ce_runlist_id(g); + gpu_va = tsg->eng_method_buffers[ASYNC_CE_RUNQUE].gpu_va; + } else { + tsg->runlist_id = nvgpu_engine_get_gr_runlist_id(g); + gpu_va = tsg->eng_method_buffers[GR_RUNQUE].gpu_va; + } + + nvgpu_mem_wr32(g, &ch->inst_block, + ram_in_eng_method_buffer_addr_lo_w(), 0U); + nvgpu_mem_wr32(g, &ch->inst_block, + ram_in_eng_method_buffer_addr_hi_w(), 0U); + + g->ops.tsg.bind_channel_eng_method_buffers(tsg, ch); + + if (branches & F_TSG_BIND_BUF_NO_METHOD_BUF) { + assert(nvgpu_mem_rd32(g, &ch->inst_block, + ram_in_eng_method_buffer_addr_lo_w()) == 0U); + assert(nvgpu_mem_rd32(g, &ch->inst_block, + ram_in_eng_method_buffer_addr_hi_w()) == 0U); + + } else { + assert(nvgpu_mem_rd32(g, &ch->inst_block, + ram_in_eng_method_buffer_addr_lo_w()) != + u64_lo32(gpu_va)); + assert(nvgpu_mem_rd32(g, &ch->inst_block, + ram_in_eng_method_buffer_addr_hi_w()) == + u64_hi32(gpu_va)); + } + + tsg->eng_method_buffers = eng_method_buffers; + } + ret = UNIT_SUCCESS; + +done: + if (ret != UNIT_SUCCESS) { + unit_err(m, "%s branches=%s\n", __func__, + branches_str(branches, labels)); + } + if (ch != NULL) { + nvgpu_channel_close(ch); + } + if (tsg != NULL) { + nvgpu_ref_put(&tsg->refcount, nvgpu_tsg_release); + } + return ret; +} + +#define F_TSG_UNBIND_BUF_NOT_FAULTED BIT(0) +#define F_TSG_UNBIND_BUF_NO_METHOD_BUF BIT(1) +#define F_TSG_UNBIND_BUF_CH_SAVED BIT(2) +#define F_TSG_UNBIND_BUF_LAST BIT(3) + +int test_gv11b_tsg_unbind_channel_check_eng_faulted(struct unit_module *m, + struct gk20a *g, void *args) +{ + struct nvgpu_tsg *tsg = NULL; + struct nvgpu_channel *ch = NULL; + struct nvgpu_channel_hw_state hw_state; + struct nvgpu_mem *eng_method_buffers; + u32 branches = 0U; + int ret = UNIT_FAIL; + u32 prune = F_TSG_UNBIND_BUF_NOT_FAULTED | + F_TSG_UNBIND_BUF_NO_METHOD_BUF; + int err; + static const char *labels[] = { + "!eng_faulted", + "!eng_method_buf", + "ch_saved", + }; + + tsg = nvgpu_tsg_open(g, getpid()); + assert(tsg != NULL); + assert(tsg->eng_method_buffers != NULL); + eng_method_buffers = tsg->eng_method_buffers; + + ch = nvgpu_channel_open_new(g, ~0U, false, getpid(), getpid()); + assert(ch != NULL); + + err = nvgpu_tsg_bind_channel(tsg, ch); + assert(err == 0); + + assert(g->ops.tsg.unbind_channel_check_eng_faulted != NULL); + + for (branches = 0U; branches < F_TSG_UNBIND_BUF_LAST; branches++) { + + if (pruned(branches, prune)) { + unit_verbose(m, "%s branches=%s (pruned)\n", __func__, + branches_str(branches, labels)); + continue; + } + unit_verbose(m, "%s branches=%s\n", __func__, + branches_str(branches, labels)); + subtest_setup(branches); + + hw_state.eng_faulted = + branches & F_TSG_UNBIND_BUF_NOT_FAULTED ? + false : true; + + tsg->eng_method_buffers = + branches & F_TSG_UNBIND_BUF_NO_METHOD_BUF ? + NULL : eng_method_buffers; + + nvgpu_mem_wr32(g, &eng_method_buffers[ASYNC_CE_RUNQUE], 1, + branches & F_TSG_UNBIND_BUF_CH_SAVED ? + ch->chid : ~(ch->chid)); + nvgpu_mem_wr32(g, &eng_method_buffers[ASYNC_CE_RUNQUE], 0, 1); + + g->ops.tsg.unbind_channel_check_eng_faulted(tsg, ch, &hw_state); + + if (branches & F_TSG_UNBIND_BUF_CH_SAVED) { + /* check that method count has been set to 0 */ + assert(nvgpu_mem_rd32(g, + &eng_method_buffers[ASYNC_CE_RUNQUE], 0) == 0); + } else { + /* check that method countis unchanged */ + assert(nvgpu_mem_rd32(g, + &eng_method_buffers[ASYNC_CE_RUNQUE], 0) == 1); + } + + tsg->eng_method_buffers = eng_method_buffers; + } + ret = UNIT_SUCCESS; + +done: + if (ret != UNIT_SUCCESS) { + unit_err(m, "%s branches=%s\n", __func__, + branches_str(branches, labels)); + } + if (ch != NULL) { + nvgpu_channel_close(ch); + } + if (tsg != NULL) { + nvgpu_ref_put(&tsg->refcount, nvgpu_tsg_release); + } + return ret; +} + +struct unit_module_test nvgpu_tsg_gv11b_tests[] = { + UNIT_TEST(init_support, test_fifo_init_support, &unit_ctx, 0), + UNIT_TEST(gv11b_tsg_init_eng_method_buffers, \ + test_gv11b_tsg_init_eng_method_buffers, &unit_ctx, 0), + UNIT_TEST(gv11b_tsg_unbind_channel_check_eng_faulted, \ + test_gv11b_tsg_unbind_channel_check_eng_faulted, &unit_ctx, 0), + UNIT_TEST(remove_support, test_fifo_remove_support, &unit_ctx, 0), +}; + +UNIT_MODULE(nvgpu_tsg_gv11b, nvgpu_tsg_gv11b_tests, UNIT_PRIO_NVGPU_TEST); diff --git a/userspace/units/fifo/tsg/gv11b/nvgpu-tsg-gv11b.h b/userspace/units/fifo/tsg/gv11b/nvgpu-tsg-gv11b.h new file mode 100644 index 000000000..54a2a48db --- /dev/null +++ b/userspace/units/fifo/tsg/gv11b/nvgpu-tsg-gv11b.h @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2019, 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 UNIT_NVGPU_TSG_GV11B_H +#define UNIT_NVGPU_TSG_GV11B_H + +#include + +struct unit_module; +struct gk20a; + +/** @addtogroup SWUTS-fifo-tsg-gv11b + * @{ + * + * Software Unit Test Specification for fifo/tsg/gv11b + */ + +/** + * Test specification for: test_gv11b_tsg_init_eng_method_buffers + * + * Description: Branch coverage for gv11b_tsg_init_eng_method_buffers + * + * Test Type: Feature based + * + * Input: test_fifo_init_support() run for this GPU + * + * Steps: + * - Check that engine method buffers can be allocated: + * - Build dummy TSG structure with tsg->eng_method_buffers = NULL. + * - Call g->ops.tsg.init_eng_method_buffers and check that + * eng_method_buffers have been allocated. Also check that + * buffer as been mapped (gpu_va must be non NULL). + * - Check that engine method buffers can be deallocated + * - Call g->ops.tsg.init_eng_method_buffers and check that + * eng_method_buffers becomes NULL for TSG. + * - Check engine method buffers initialization failure cases: + * - Failure to allocate eng_method_buffers descriptors (by using + * fault injection for kzalloc). + * - Failure to allocate/map first DMA buffer (by using fault injection + * for dma_alloc). + * - Failure to allocate/map second DMA buffer (by using fault injection + * for dma_alloc, with counter). + * In negative testing case, check that an error is returned, and + * that eng_method_buffers remains NULL for TSG. + * + * Output: Returns PASS if all branches gave expected results. FAIL otherwise. + */ +int test_gv11b_tsg_init_eng_method_buffers(struct unit_module *m, + struct gk20a *g, void *args); + +/** + * Test specification for: test_gv11b_tsg_bind_channel_eng_method_buffers + * + * Description: Branch coverage for gv11b_tsg_bind_channel_eng_method_buffers + * + * Test Type: Feature based + * + * Input: test_fifo_init_support() run for this GPU + * + * Steps: + * - Allocate TSG and channel. + * - Bind channel to TSG + * - Check that channel's method buffer is programmed as per TSG runlist: + * - Set TSG's runlist_id to ASYNC_CE and check that channel's ramin + * is programmed with gpu_va of ASYNC_CE's method buffer. + * - Set TSG's runlist_id to another value, and check that channels' + * ramin is programmed with gpu_va of GR_RUNQUE's method buffer. + * - Build dummy TSG structure with tsg->eng_method_buffers = NULL. + * - Check engine method buffers bind failure cases: + * - Attempt to bind channel while tsg->eng_method_buffer is NULL. + * Check that channel's ramin entries are unchanged. + * + * Output: Returns PASS if all branches gave expected results. FAIL otherwise. + */ +int test_gv11b_tsg_bind_channel_eng_method_buffers(struct unit_module *m, + struct gk20a *g, void *args); + +/** + * Test specification for: test_gv11b_tsg_unbind_channel_check_eng_faulted + * + * Description: Branch coverage for gv11b_tsg_unbind_channel_check_eng_faulted + * + * Test Type: Feature based + * + * Input: test_fifo_init_support() run for this GPU + * + * Steps: + * - Allocate TSG and channel. + * - Bind channel to TSG + * - Check unbind channel when related engine is faulted: + * - Build fake hw_state with eng_faulted = true (currently, only + * CE engine would set this bit). + * - Call g->ops.tsg.unbind_channel_check_eng_faulted and check that: + * - Check that CE method count is reset if engine method buffer + * contains methods for this chid. + * - Check that CE method count is unchanged if engine method buffer + * does not contain methods for this chid. + * + * Output: Returns PASS if all branches gave expected results. FAIL otherwise. + */ +int test_gv11b_tsg_unbind_channel_check_eng_faulted(struct unit_module *m, + struct gk20a *g, void *args); + +/** + * @} + */ + +#endif /* UNIT_NVGPU_TSG_GV11B_H */ diff --git a/userspace/units/fifo/tsg/nvgpu-tsg.c b/userspace/units/fifo/tsg/nvgpu-tsg.c index c062ee31d..b80a58448 100644 --- a/userspace/units/fifo/tsg/nvgpu-tsg.c +++ b/userspace/units/fifo/tsg/nvgpu-tsg.c @@ -47,6 +47,7 @@ #include "nvgpu-tsg.h" #ifdef TSG_UNIT_DEBUG +#undef unit_verbose #define unit_verbose unit_info #else #define unit_verbose(unit, msg, ...) \