mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-22 17:36:20 +03:00
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 <ddutta@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2279730 Tested-by: mobile promotions <svcmobile_promotions@nvidia.com> Reviewed-by: Vijayakumar Subbu <vsubbu@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> GVS: Gerrit_Virtual_Submit
This commit is contained in:
committed by
Alex Waterman
parent
cffefda3e4
commit
0c47ea2b50
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -154,5 +154,6 @@ UNITS := \
|
||||
$(UNIT_SRC)/acr \
|
||||
$(UNIT_SRC)/ce \
|
||||
$(UNIT_SRC)/cg \
|
||||
$(UNIT_SRC)/rc \
|
||||
$(UNIT_SRC)/sync \
|
||||
$(UNIT_SRC)/ecc
|
||||
|
||||
@@ -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
|
||||
|
||||
33
userspace/units/rc/Makefile
Normal file
33
userspace/units/rc/Makefile
Normal file
@@ -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
|
||||
35
userspace/units/rc/Makefile.interface.tmk
Normal file
35
userspace/units/rc/Makefile.interface.tmk
Normal file
@@ -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:
|
||||
41
userspace/units/rc/Makefile.tmk
Normal file
41
userspace/units/rc/Makefile.tmk
Normal file
@@ -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:
|
||||
|
||||
476
userspace/units/rc/nvgpu-rc.c
Normal file
476
userspace/units/rc/nvgpu-rc.c
Normal file
@@ -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 <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <unit/unit.h>
|
||||
#include <unit/io.h>
|
||||
#include <nvgpu/types.h>
|
||||
#include <nvgpu/gk20a.h>
|
||||
#include <nvgpu/hal_init.h>
|
||||
#include <nvgpu/dma.h>
|
||||
#include <nvgpu/posix/io.h>
|
||||
#include <os/posix/os_posix.h>
|
||||
#include <nvgpu/posix/posix-fault-injection.h>
|
||||
#include <nvgpu/posix/posix-nvhost.h>
|
||||
#include <nvgpu/posix/posix-channel.h>
|
||||
#include <nvgpu/runlist.h>
|
||||
#include <nvgpu/channel.h>
|
||||
#include <nvgpu/rc.h>
|
||||
#include <nvgpu/pbdma_status.h>
|
||||
#include <nvgpu/error_notifier.h>
|
||||
|
||||
#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);
|
||||
284
userspace/units/rc/nvgpu-rc.h
Normal file
284
userspace/units/rc/nvgpu-rc.h
Normal file
@@ -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 <nvgpu/types.h>
|
||||
|
||||
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 */
|
||||
Reference in New Issue
Block a user