From 0c47ea2b5023b2096dedfb4ff3cb487d21368c03 Mon Sep 17 00:00:00 2001 From: Debarshi Dutta Date: Thu, 16 Jan 2020 10:25:30 +0530 Subject: [PATCH] nvgpu: unit: rc This patch adds unit tests coverage for rc unit for safety-build. This patch achieves 100% branch coverage. Following tests are added test_rc_init test_rc_fifo_recover test_rc_ctxsw_timeout test_rc_runlist_update test_rc_preempt_timeout test_rc_gr_fault test_rc_sched_error_bad_tsg test_rc_tsg_and_related_engines test_rc_mmu_fault test_rc_pbdma_fault test_rc_deinit Jira NVGPU-4385 Change-Id: I9d3e42272247eec9aa55bd520b32ef0b268e6e5d Change-Id: I9d3e42272247eec9aa55bd520b32ef0b268e6e5d Signed-off-by: Debarshi Dutta Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2279730 Tested-by: mobile promotions Reviewed-by: Vijayakumar Subbu Reviewed-by: mobile promotions GVS: Gerrit_Virtual_Submit --- Makefile.umbrella.tmk | 1 + drivers/gpu/nvgpu/libnvgpu-drv_safe.export | 9 + userspace/Makefile.sources | 1 + userspace/SWUTS.h | 1 + userspace/units/rc/Makefile | 33 ++ userspace/units/rc/Makefile.interface.tmk | 35 ++ userspace/units/rc/Makefile.tmk | 41 ++ userspace/units/rc/nvgpu-rc.c | 476 +++++++++++++++++++++ userspace/units/rc/nvgpu-rc.h | 284 ++++++++++++ 9 files changed, 881 insertions(+) create mode 100644 userspace/units/rc/Makefile create mode 100644 userspace/units/rc/Makefile.interface.tmk create mode 100644 userspace/units/rc/Makefile.tmk create mode 100644 userspace/units/rc/nvgpu-rc.c create mode 100644 userspace/units/rc/nvgpu-rc.h diff --git a/Makefile.umbrella.tmk b/Makefile.umbrella.tmk index c574adcbb..b24292ca5 100644 --- a/Makefile.umbrella.tmk +++ b/Makefile.umbrella.tmk @@ -156,6 +156,7 @@ NV_REPOSITORY_COMPONENTS += userspace/units/gr/intr NV_REPOSITORY_COMPONENTS += userspace/units/acr NV_REPOSITORY_COMPONENTS += userspace/units/ce NV_REPOSITORY_COMPONENTS += userspace/units/cg +NV_REPOSITORY_COMPONENTS += userspace/units/rc NV_REPOSITORY_COMPONENTS += userspace/units/sync NV_REPOSITORY_COMPONENTS += userspace/units/mock-iospace NV_REPOSITORY_COMPONENTS += userspace/units/ecc diff --git a/drivers/gpu/nvgpu/libnvgpu-drv_safe.export b/drivers/gpu/nvgpu/libnvgpu-drv_safe.export index 3276e0fe0..860ad0829 100644 --- a/drivers/gpu/nvgpu/libnvgpu-drv_safe.export +++ b/drivers/gpu/nvgpu/libnvgpu-drv_safe.export @@ -790,3 +790,12 @@ nvgpu_free_nvhost_dev nvgpu_ecc_free nvgpu_ecc_counter_init nvgpu_ecc_finalize_support +nvgpu_rc_fifo_recover +nvgpu_rc_ctxsw_timeout +nvgpu_rc_pbdma_fault +nvgpu_rc_runlist_update +nvgpu_rc_preempt_timeout +nvgpu_rc_gr_fault +nvgpu_rc_sched_error_bad_tsg +nvgpu_rc_tsg_and_related_engines +nvgpu_rc_mmu_fault diff --git a/userspace/Makefile.sources b/userspace/Makefile.sources index 44d6761f2..a88499527 100644 --- a/userspace/Makefile.sources +++ b/userspace/Makefile.sources @@ -154,5 +154,6 @@ UNITS := \ $(UNIT_SRC)/acr \ $(UNIT_SRC)/ce \ $(UNIT_SRC)/cg \ + $(UNIT_SRC)/rc \ $(UNIT_SRC)/sync \ $(UNIT_SRC)/ecc diff --git a/userspace/SWUTS.h b/userspace/SWUTS.h index 49d482fb1..fdf7cf001 100644 --- a/userspace/SWUTS.h +++ b/userspace/SWUTS.h @@ -79,6 +79,7 @@ * - @ref SWUTS-intr * - @ref SWUTS-interface-atomic * - @ref SWUTS-ltc + * - @ref SWUTS-nvgpu-rc * - @ref SWUTS-mc * - @ref SWUTS-mm-allocators-bitmap-allocator * - @ref SWUTS-mm-allocators-buddy-allocator diff --git a/userspace/units/rc/Makefile b/userspace/units/rc/Makefile new file mode 100644 index 000000000..ff3a7e374 --- /dev/null +++ b/userspace/units/rc/Makefile @@ -0,0 +1,33 @@ +# 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-rc.o +MODULE = nvgpu-rc + +LIB_PATHS += -lnvgpu-fifo-common + +include ../Makefile.units + +lib$(MODULE).so: nvgpu-fifo + +nvgpu-fifo: + $(MAKE) -C ../fifo diff --git a/userspace/units/rc/Makefile.interface.tmk b/userspace/units/rc/Makefile.interface.tmk new file mode 100644 index 000000000..397020c4d --- /dev/null +++ b/userspace/units/rc/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-rc + +include $(NV_COMPONENT_DIR)/../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/rc/Makefile.tmk b/userspace/units/rc/Makefile.tmk new file mode 100644 index 000000000..bfc62d790 --- /dev/null +++ b/userspace/units/rc/Makefile.tmk @@ -0,0 +1,41 @@ +################################## 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-rc +NVGPU_UNIT_SRCS=nvgpu-rc.c + +NVGPU_UNIT_INTERFACE_DIRS := \ + $(NV_COMPONENT_DIR)/../fifo \ + $(NV_SOURCE)/kernel/nvgpu/drivers/gpu/nvgpu + +include $(NV_COMPONENT_DIR)/../Makefile.units.common.tmk + +# Local Variables: +# indent-tabs-mode: t +# tab-width: 8 +# End: +# vi: set tabstop=8 noexpandtab: + diff --git a/userspace/units/rc/nvgpu-rc.c b/userspace/units/rc/nvgpu-rc.c new file mode 100644 index 000000000..a8babd3a9 --- /dev/null +++ b/userspace/units/rc/nvgpu-rc.c @@ -0,0 +1,476 @@ +/* + * 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 +#include +#include +#include +#include + +#include "../fifo/nvgpu-fifo-common.h" +#include "../fifo/nvgpu-fifo-gv11b.h" +#include "nvgpu-rc.h" + +#define NV_PMC_BOOT_0_ARCHITECTURE_GV110 (0x00000015 << \ + NVGPU_GPU_ARCHITECTURE_SHIFT) +#define NV_PMC_BOOT_0_IMPLEMENTATION_B 0xB + +#define assert(cond) unit_assert(cond, goto done) + +static u32 stub_gv11b_gr_init_get_no_of_sm(struct gk20a *g) +{ + return 8; +} + +static struct nvgpu_channel *ch = NULL; +static struct nvgpu_tsg *tsg = NULL; + +static int verify_error_notifier(struct nvgpu_channel *ch, u32 error_notifier) +{ + struct nvgpu_posix_channel *cp = ch->os_priv; + if (cp == NULL) { + return UNIT_FAIL; + } else if (cp->err_notifier.error == error_notifier && + cp->err_notifier.status == 0xffff) { + return UNIT_SUCCESS; + } else { + return UNIT_FAIL; + } +} + +static void clear_error_notifier(struct nvgpu_channel *ch) +{ + struct nvgpu_posix_channel *cp = ch->os_priv; + if (cp != NULL) { + cp->err_notifier.error = 0U; + cp->err_notifier.status = 0U; + } +} + +int test_rc_init(struct unit_module *m, struct gk20a *g, void *args) +{ + int ret = 0; + struct nvgpu_posix_channel *posix_channel = NULL; + + ret = test_fifo_setup_gv11b_reg_space(m, g); + if (ret != 0) { + unit_return_fail(m, "fifo reg_space failure"); + } + + /* + * HAL init parameters for gv11b + */ + g->params.gpu_arch = NV_PMC_BOOT_0_ARCHITECTURE_GV110; + g->params.gpu_impl = NV_PMC_BOOT_0_IMPLEMENTATION_B; + + /* + * HAL init required for getting + * the sync ops initialized. + */ + ret = nvgpu_init_hal(g); + if (ret != 0) { + unit_err(m, "failed to init hal"); + goto clean_regspace; + } + + g->ops.gr.init.get_no_of_sm = stub_gv11b_gr_init_get_no_of_sm; + + g->ops.ecc.ecc_init_support(g); + g->ops.mm.init_mm_support(g); + + ret = nvgpu_fifo_init_support(g); + if (ret != 0) { + unit_err(m , "failed to init fifo support"); + goto clean_regspace; + } + + /* Do not allocate from vidmem */ + nvgpu_set_enabled(g, NVGPU_MM_UNIFIED_MEMORY, true); + + ret = nvgpu_runlist_setup_sw(g); + if (ret != 0) { + unit_err(m, "failed runlist setup_sw"); + goto clean_regspace; + } + + tsg = nvgpu_tsg_open(g, getpid()); + if (tsg == NULL) { + ret = UNIT_FAIL; + unit_err(m, "failed tsg open"); + goto clean_regspace; + } + + ch = nvgpu_channel_open_new(g, NVGPU_INVALID_RUNLIST_ID, false, + getpid(), getpid()); + if (ch == NULL) { + ret = UNIT_FAIL; + unit_err(m, "failed channel open"); + goto clear_tsg; + } + + posix_channel = malloc(sizeof(struct nvgpu_posix_channel)); + if (posix_channel == NULL) { + unit_err(m, "failed to allocate memory for posix channel"); + goto clear_channel; + } + + ch->os_priv = posix_channel; + + ret = nvgpu_tsg_bind_channel(tsg, ch); + if (ret) { + unit_err(m, "failed to bind channel"); + goto clear_posix_channel; + } + + return UNIT_SUCCESS; + +clear_posix_channel: + free(posix_channel); +clear_channel: + nvgpu_channel_close(ch); + ch = NULL; +clear_tsg: + nvgpu_ref_put(&tsg->refcount, nvgpu_tsg_release); + tsg = NULL; +clean_regspace: + test_fifo_cleanup_gv11b_reg_space(m, g); + + return ret; +} + +int test_rc_deinit(struct unit_module *m, struct gk20a *g, void *args) +{ + struct nvgpu_posix_channel *posix_channel = ch->os_priv; + int ret = nvgpu_tsg_unbind_channel(tsg, ch); + if (ret != 0) { + ret = UNIT_FAIL; + unit_err(m , "channel already unbound"); + } + + if (ch != NULL && posix_channel != NULL) { + free(posix_channel); + } + + if (ch != NULL) { + nvgpu_channel_close(ch); + } + + if (tsg != NULL) { + nvgpu_ref_put(&tsg->refcount, nvgpu_tsg_release); + } + + if (g->fifo.remove_support) { + g->fifo.remove_support(&g->fifo); + } + + test_fifo_cleanup_gv11b_reg_space(m, g); + + return ret; +} + +int test_rc_fifo_recover(struct unit_module *m, struct gk20a *g, void *args) +{ + g->sw_quiesce_pending = true; + clear_error_notifier(ch); + nvgpu_rc_fifo_recover(g, 0U, 0U, false, false, false, 0U); + + g->sw_quiesce_pending = false; + + return UNIT_SUCCESS; +} + +int test_rc_ctxsw_timeout(struct unit_module *m, struct gk20a *g, void *args) +{ + g->sw_quiesce_pending = true; + clear_error_notifier(ch); + nvgpu_rc_ctxsw_timeout(g, 0U, tsg, false); + + g->sw_quiesce_pending = false; + return verify_error_notifier(ch, NVGPU_ERR_NOTIFIER_FIFO_ERROR_IDLE_TIMEOUT); +} + +int test_rc_runlist_update(struct unit_module *m, struct gk20a *g, void *args) +{ + g->sw_quiesce_pending = true; + nvgpu_rc_runlist_update(g, 0U); + + g->sw_quiesce_pending = false; + return UNIT_SUCCESS; +} + +int test_rc_preempt_timeout(struct unit_module *m, struct gk20a *g, void *args) +{ + g->sw_quiesce_pending = true; + clear_error_notifier(ch); + nvgpu_rc_preempt_timeout(g, tsg); + + g->sw_quiesce_pending = false; + return verify_error_notifier(ch, NVGPU_ERR_NOTIFIER_FIFO_ERROR_IDLE_TIMEOUT); +} + +int test_rc_gr_fault(struct unit_module *m, struct gk20a *g, void *args) +{ + g->sw_quiesce_pending = true; + clear_error_notifier(ch); + nvgpu_rc_gr_fault(g, tsg, ch); + + g->sw_quiesce_pending = false; + return UNIT_SUCCESS; +} + +int test_rc_sched_error_bad_tsg(struct unit_module *m, struct gk20a *g, void *args) +{ + g->sw_quiesce_pending = true; + clear_error_notifier(ch); + nvgpu_rc_sched_error_bad_tsg(g); + + g->sw_quiesce_pending = false; + return UNIT_SUCCESS; +} + +int test_rc_tsg_and_related_engines(struct unit_module *m, struct gk20a *g, void *args) +{ + g->sw_quiesce_pending = true; + nvgpu_rc_tsg_and_related_engines(g, tsg, false, RC_TYPE_SCHED_ERR); + + g->sw_quiesce_pending = false; + return UNIT_SUCCESS; +} + +#define F_RC_MMU_FAULT_ID_INVALID 0 +#define F_RC_MMU_FAULT_ID_TYPE_TSG 1 +#define F_RC_MMU_FAULT_ID_TYPE_NOT_TSG 2 + +static const char *f_rc_mmu_fault[] = { + "id_invalid", + "id_type_tsg", + "id_type_not_tsg", +}; + +int test_rc_mmu_fault(struct unit_module *m, struct gk20a *g, void *args) +{ + u32 branches; + u32 id = NVGPU_INVALID_TSG_ID; + u32 id_type = F_RC_MMU_FAULT_ID_TYPE_NOT_TSG; + g->sw_quiesce_pending = true; + clear_error_notifier(ch); + + for (branches = 0U; branches <= F_RC_MMU_FAULT_ID_TYPE_NOT_TSG; branches++) { + if (branches != F_RC_MMU_FAULT_ID_INVALID) { + id = tsg->tsgid; + id_type = ID_TYPE_UNKNOWN; + } + + if (branches == F_RC_MMU_FAULT_ID_TYPE_TSG) { + id_type = ID_TYPE_TSG; + } + + unit_info(m, "%s branch: %s\n", __func__, f_rc_mmu_fault[branches]); + + nvgpu_rc_mmu_fault(g, 0U, id, id_type, RC_TYPE_MMU_FAULT, NULL); + } + + g->sw_quiesce_pending = false; + return UNIT_SUCCESS; +} + +#define F_RC_IS_CHSW_VALID_OR_SAVE 0U +#define F_RC_IS_CHSW_LOAD_OR_SWITCH 1U +#define F_RC_IS_CHSW_INVALID 2U + +#define F_RC_ID_TYPE_TSG 0U +#define F_RC_ID_TYPE_CH 1U +#define F_RC_ID_TYPE_INVALID 2U + +#define F_RC_ID_TYPE_CH_NULL_CHANNEL 0U +#define F_RC_ID_TYPE_CH_NULL_TSG 1U +#define F_RC_ID_TYPE_CH_FULL 2U + +static const char *f_rc_chsw[] = { + "is_chsw_valid_or_save", + "is_chsw_load_or_switch", + "is_chsw_invalid", +}; + +static const char *f_rc_id_type[] = { + "id_type_tsg", + "id_type_ch", + "id_type_invalid", +}; + +static const char *f_rc_id_ch_subbranch[] = { + "null_channel", + "null_tsg", + "full", +}; + +static void set_pbdma_info_id_type(u32 chsw_branches, + struct nvgpu_pbdma_status_info *info, + struct nvgpu_channel *ch_without_tsg, + u32 id_type_branches, + u32 id_type_ch_branches) +{ + if (id_type_branches == F_RC_ID_TYPE_TSG) { + info->id = (chsw_branches == F_RC_IS_CHSW_VALID_OR_SAVE) ? + tsg->tsgid : PBDMA_STATUS_ID_INVALID; + info->id_type = (chsw_branches == F_RC_IS_CHSW_VALID_OR_SAVE) ? + PBDMA_STATUS_ID_TYPE_TSGID : PBDMA_STATUS_ID_TYPE_INVALID; + info->next_id = (chsw_branches == F_RC_IS_CHSW_LOAD_OR_SWITCH) ? + tsg->tsgid : PBDMA_STATUS_ID_INVALID; + info->next_id_type = (chsw_branches == F_RC_IS_CHSW_LOAD_OR_SWITCH) ? + PBDMA_STATUS_NEXT_ID_TYPE_TSGID : PBDMA_STATUS_NEXT_ID_TYPE_INVALID; + } else if (id_type_branches == F_RC_ID_TYPE_CH) { + if (id_type_ch_branches == F_RC_ID_TYPE_CH_NULL_CHANNEL) { + info->id = NVGPU_INVALID_CHANNEL_ID; + info->id_type = PBDMA_STATUS_ID_TYPE_CHID; + info->next_id = NVGPU_INVALID_CHANNEL_ID; + info->next_id_type = PBDMA_STATUS_NEXT_ID_TYPE_CHID; + } else if (id_type_ch_branches == F_RC_ID_TYPE_CH_NULL_TSG) { + /* Use ch_without_tsg for NULL TSG branch */ + info->id = (chsw_branches == F_RC_IS_CHSW_VALID_OR_SAVE) ? + ch_without_tsg->chid : PBDMA_STATUS_ID_INVALID; + info->id_type = (chsw_branches == F_RC_IS_CHSW_VALID_OR_SAVE) ? + PBDMA_STATUS_ID_TYPE_CHID : PBDMA_STATUS_ID_TYPE_INVALID; + info->next_id = (chsw_branches == F_RC_IS_CHSW_LOAD_OR_SWITCH) ? + ch_without_tsg->chid : PBDMA_STATUS_ID_INVALID; + info->next_id_type = (chsw_branches == F_RC_IS_CHSW_LOAD_OR_SWITCH) ? + PBDMA_STATUS_NEXT_ID_TYPE_CHID : PBDMA_STATUS_NEXT_ID_TYPE_INVALID; + } else { + /* Use ch for full path */ + info->id = (chsw_branches == F_RC_IS_CHSW_VALID_OR_SAVE) ? + ch->chid : PBDMA_STATUS_ID_INVALID; + info->id_type = (chsw_branches == F_RC_IS_CHSW_VALID_OR_SAVE) ? + PBDMA_STATUS_ID_TYPE_CHID : PBDMA_STATUS_ID_TYPE_INVALID; + info->next_id = (chsw_branches == F_RC_IS_CHSW_LOAD_OR_SWITCH) ? + ch->chid : PBDMA_STATUS_ID_INVALID; + info->next_id_type = (chsw_branches == F_RC_IS_CHSW_LOAD_OR_SWITCH) ? + PBDMA_STATUS_NEXT_ID_TYPE_CHID : PBDMA_STATUS_NEXT_ID_TYPE_INVALID; + } + } else { + info->id_type = PBDMA_STATUS_ID_INVALID; + info->next_id_type = PBDMA_STATUS_ID_INVALID; + } +} + +int test_rc_pbdma_fault(struct unit_module *m, struct gk20a *g, void *args) +{ + u32 chsw_branches, id_type_branches; + u32 chsw_subbranch; + + struct nvgpu_channel *ch_without_tsg = NULL; + + ch_without_tsg = nvgpu_channel_open_new(g, NVGPU_INVALID_RUNLIST_ID, false, + getpid(), getpid()); + if (ch_without_tsg == NULL) { + unit_err(m, "failed channel open"); + return UNIT_FAIL; + } + + g->sw_quiesce_pending = true; + + for (chsw_branches = F_RC_IS_CHSW_VALID_OR_SAVE; + chsw_branches <= F_RC_IS_CHSW_INVALID; chsw_branches++) { + struct nvgpu_pbdma_status_info info = {0}; + + if (chsw_branches == F_RC_IS_CHSW_INVALID) { + info.chsw_status = NVGPU_PBDMA_CHSW_STATUS_INVALID; + unit_info(m, "%s branch: %s\n", __func__, f_rc_chsw[chsw_branches]); + nvgpu_rc_pbdma_fault(g, 0U, NVGPU_ERR_NOTIFIER_PBDMA_ERROR, &info); + continue; + } + + for (chsw_subbranch = 0U; chsw_subbranch < 2U; chsw_subbranch++) { + if (chsw_branches == F_RC_IS_CHSW_VALID_OR_SAVE) { + info.chsw_status = + (chsw_subbranch * NVGPU_PBDMA_CHSW_STATUS_VALID) + + ((1 - chsw_subbranch) * NVGPU_PBDMA_CHSW_STATUS_SAVE); + } else { + info.chsw_status = + (chsw_subbranch * NVGPU_PBDMA_CHSW_STATUS_LOAD) + + ((1 - chsw_subbranch) * NVGPU_PBDMA_CHSW_STATUS_SWITCH); + } + } + + for (id_type_branches = F_RC_ID_TYPE_TSG; id_type_branches <= F_RC_ID_TYPE_INVALID; + id_type_branches++) { + u32 id_type_ch_sub_branches; + if (id_type_branches == F_RC_ID_TYPE_CH) { + for (id_type_ch_sub_branches = F_RC_ID_TYPE_CH_NULL_CHANNEL; + id_type_ch_sub_branches <= F_RC_ID_TYPE_CH_FULL; id_type_ch_sub_branches++) { + set_pbdma_info_id_type(chsw_branches, &info, ch_without_tsg, + id_type_branches, id_type_ch_sub_branches); + + unit_info(m, "%s branch: %s - %s - %s\n", __func__, + f_rc_chsw[chsw_branches], + f_rc_id_type[id_type_branches], + f_rc_id_ch_subbranch[id_type_ch_sub_branches]); + + nvgpu_rc_pbdma_fault(g, 0U, NVGPU_ERR_NOTIFIER_PBDMA_ERROR, &info); + } + } else { + set_pbdma_info_id_type(chsw_branches, &info, ch_without_tsg, + id_type_branches, id_type_ch_sub_branches); + + + unit_info(m, "%s branch: %s - %s\n", __func__, + f_rc_chsw[chsw_branches], + f_rc_id_type[id_type_branches]); + + nvgpu_rc_pbdma_fault(g, 0U, NVGPU_ERR_NOTIFIER_PBDMA_ERROR, &info); + } + } + } + + g->sw_quiesce_pending = false; + + nvgpu_channel_close(ch_without_tsg); + + return UNIT_SUCCESS; +} + +struct unit_module_test nvgpu_rc_tests[] = { + UNIT_TEST(rc_init, test_rc_init, NULL, 0), + UNIT_TEST(rc_fifo_recover, test_rc_fifo_recover, NULL, 0), + UNIT_TEST(rc_ctxsw_timeout, test_rc_ctxsw_timeout, NULL, 0), + UNIT_TEST(rc_runlist_update, test_rc_runlist_update, NULL, 0), + UNIT_TEST(rc_preempt_timeout, test_rc_preempt_timeout, NULL, 0), + UNIT_TEST(rc_gr_fault, test_rc_gr_fault, NULL, 0), + UNIT_TEST(rc_sched_error_bad_tsg, test_rc_sched_error_bad_tsg, NULL, 0), + UNIT_TEST(rc_tsg_and_related_engines, test_rc_tsg_and_related_engines, NULL, 0), + UNIT_TEST(rc_mmu_fault, test_rc_mmu_fault, NULL, 0), + UNIT_TEST(rc_pbdma_fault, test_rc_pbdma_fault, NULL, 0), + UNIT_TEST(rc_deinit, test_rc_deinit, NULL, 0), +}; + +UNIT_MODULE(nvgpu-rc, nvgpu_rc_tests, UNIT_PRIO_NVGPU_TEST); \ No newline at end of file diff --git a/userspace/units/rc/nvgpu-rc.h b/userspace/units/rc/nvgpu-rc.h new file mode 100644 index 000000000..f53326c36 --- /dev/null +++ b/userspace/units/rc/nvgpu-rc.h @@ -0,0 +1,284 @@ +/* + * 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_RC_H +#define UNIT_NVGPU_RC_H + +#include + +struct gk20a; +struct unit_module; + +/** @addtogroup SWUTS-nvgpu-rc + * @{ + * + * Software Unit Test Specification for nvgpu-rc + */ + +/** + * Test specification for: test_rc_init + * + * Description: Environment initialization for rc tests + * + * Test Type: Other (setup) + * + * Input: None + * + * Steps: + * - init FIFO register space. + * - init HAL parameters for gv11b. + * - init fifo support for Channel and TSG + * - init Runlist setup + * - open a TSG + * - open a new Channel + * - allocate memory for posix_channel + * - bind Channel to TSG + * + * Output: Returns PASS if all the above steps are successful. FAIL otherwise. + */ +int test_rc_init(struct unit_module *m, struct gk20a *g, void *args); + +/** + * Test specification for: test_rc_deinit + * + * Description: Environment de-initialization for rc tests + * + * Test Type: Other (cleanup) + * + * Input: test_rc_init run for this GPU + * + * Steps: + * - unbind Channel from TSG + * - free posix_channel + * - close Channel + * - close TSG + * - remove FIFO support + * - clear FIFO register space + * + * Output: Returns PASS if all the above steps are successful. FAIL otherwise. + */ +int test_rc_deinit(struct unit_module *m, struct gk20a *g, void *args); + +/** + * Test specification for: test_rc_fifo_recover + * + * Description: Coverage test for nvgpu_rc_fifo_recover + * + * Test Type: Feature + * + * Targets: nvgpu_rc_fifo_recover + * + * Input: test_rc_init run for this GPU + * + * Steps: + * - initialize Channel error_notifier + * - set g->sw_quiesce_pending = true + * - invoke nvgpu_rc_fifo_recover + * + * Output: Cover all branch in safety build. + */ +int test_rc_fifo_recover(struct unit_module *m, struct gk20a *g, void *args); + +/** + * Test specification for: test_rc_ctxsw_timeout + * + * Description: Coverage test for nvgpu_rc_ctxsw_timeout + * + * Test Type: Feature + * + * Targets: nvgpu_rc_ctxsw_timeout + * + * Input: test_rc_init run for this GPU + * + * Steps: + * - initialize Channel error_notifier + * - set g->sw_quiesce_pending = true + * - invoke nvgpu_rc_ctxsw_timeout + * - verfy that error_notifier is set to NVGPU_ERR_NOTIFIER_FIFO_ERROR_IDLE_TIMEOUT + * + * Output: Cover all branch in safety build. + */ +int test_rc_ctxsw_timeout(struct unit_module *m, struct gk20a *g, void *args); + +/** + * Test specification for: test_rc_runlist_update + * + * Description: Coverage test for nvgpu_rc_runlist_update + * + * Test Type: Feature + * + * Targets: nvgpu_rc_runlist_update + * + * Input: test_rc_init run for this GPU + * + * Steps: + * - initialize Channel error_notifier + * - set g->sw_quiesce_pending = true + * - invoke nvgpu_rc_runlist_update + * + * Output: Cover all branch in safety build. + */ +int test_rc_runlist_update(struct unit_module *m, struct gk20a *g, void *args); + +/** + * Test specification for: test_rc_preempt_timeout + * + * Description: Coverage test for nvgpu_rc_preempt_timeout + * + * Test Type: Feature + * + * Targets: nvgpu_rc_preempt_timeout + * + * Input: test_rc_init run for this GPU + * + * Steps: + * - initialize Channel error_notifier + * - set g->sw_quiesce_pending = true + * - invoke nvgpu_rc_preempt_timeout + * - verfy that error_notifier is set to NVGPU_ERR_NOTIFIER_FIFO_ERROR_IDLE_TIMEOUT + * + * Output: Cover all branch in safety build. + */ +int test_rc_preempt_timeout(struct unit_module *m, struct gk20a *g, void *args); + +/** + * Test specification for: test_rc_gr_fault + * + * Description: Coverage test for nvgpu_rc_gr_fault + * + * Test Type: Feature + * + * Targets: nvgpu_rc_gr_fault + * + * Input: test_rc_init run for this GPU + * + * Steps: + * - initialize Channel error_notifier + * - set g->sw_quiesce_pending = true + * - invoke nvgpu_rc_gr_fault + * + * Output: Cover all branch in safety build. + */ +int test_rc_gr_fault(struct unit_module *m, struct gk20a *g, void *args); + +/** + * Test specification for: test_rc_sched_error_bad_tsg + * + * Description: Coverage test for nvgpu_rc_sched_error_bad_tsg + * + * Test Type: Feature + * + * Targets: nvgpu_rc_sched_error_bad_tsg + * + * Input: test_rc_init run for this GPU + * + * Steps: + * - initialize Channel error_notifier + * - set g->sw_quiesce_pending = true + * - invoke nvgpu_rc_sched_error_bad_tsg + * + * Output: Cover all branch in safety build. + */ +int test_rc_sched_error_bad_tsg(struct unit_module *m, struct gk20a *g, void *args); + +/** + * Test specification for: test_rc_tsg_and_related_engines + * + * Description: Coverage test for nvgpu_rc_tsg_and_related_engines + * + * Test Type: Feature + * + * Targets: nvgpu_rc_tsg_and_related_engines + * + * Input: test_rc_init run for this GPU + * + * Steps: + * - initialize Channel error_notifier + * - set g->sw_quiesce_pending = true + * - invoke nvgpu_rc_tsg_and_related_engines + * + * Output: Cover all branch in safety build. + */ +int test_rc_tsg_and_related_engines(struct unit_module *m, struct gk20a *g, void *args); + +/** + * Test specification for: test_rc_mmu_fault + * + * Description: Coverage test for nvgpu_rc_mmu_fault + * + * Test Type: Feature + * + * Targets: nvgpu_rc_mmu_fault + * + * Input: test_rc_init run for this GPU + * + * Steps: + * - initialize Channel error_notifier + * - set g->sw_quiesce_pending = true + * - set invalid_id + * - invoke nvgpu_rc_mmu_fault + * - set id_type_tsg + * - invoke nvgpu_rc_mmu_fault + * - set id_type_non_tsg + * - invoke nvgpu_rc_mmu_fault + * + * Output: Cover all branch in safety build. + */ +int test_rc_mmu_fault(struct unit_module *m, struct gk20a *g, void *args); + +/** + * Test specification for: test_rc_pbdma_fault + * + * Description: Coverage test for nvgpu_rc_pbdma_fault + * + * Test Type: Feature + * + * Targets: nvgpu_rc_pbdma_fault + * + * Input: test_rc_init run for this GPU + * + * Steps: + * - initialize Channel error_notifier + * - set g->sw_quiesce_pending = true + * - For each branch check with the following pbdma_status values + * - set chsw_status to chsw_valid_or_save + * - set id_type to TSG + * - set id_type to Channel + * - set Channel Id to Invalid + * - set Channel Id to a channel without TSG + * - set Channel Id to a channel with a valid TSG + * - set id_type to Invalid + * - set chsw_status to is_chsw_load_or_switch + * - set id_type to TSG + * - set id_type to Channel + * - set Channel Id to Invalid + * - set Channel Id to a channel without TSG + * - set Channel Id to a channel with a valid TSG + * - set id_type to Invalid + * - set chsw_status to chsw_invalid + * + * Output: Cover all branch in safety build. + */ +int test_rc_pbdma_fault(struct unit_module *m, struct gk20a *g, void *args); + +/** @} */ + +#endif /* UNIT_NVGPU_RC_H */