gpu: nvgpu: unit: create mc unit test

JIRA NVGPU-2224

Change-Id: Ic433e8bc2ac583c1735203d1b5f0fd61942c33d4
Signed-off-by: Philip Elcan <pelcan@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/2257128
GVS: Gerrit_Virtual_Submit
Reviewed-by: Alex Waterman <alexw@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Philip Elcan
2019-12-04 17:03:28 -05:00
committed by Alex Waterman
parent b5617a61d9
commit 5f0d1f39c2
9 changed files with 1318 additions and 0 deletions

View File

@@ -54,6 +54,7 @@ NV_REPOSITORY_COMPONENTS += userspace/units/interface/rbtree
NV_REPOSITORY_COMPONENTS += userspace/units/pramin NV_REPOSITORY_COMPONENTS += userspace/units/pramin
NV_REPOSITORY_COMPONENTS += userspace/units/priv_ring NV_REPOSITORY_COMPONENTS += userspace/units/priv_ring
NV_REPOSITORY_COMPONENTS += userspace/units/ptimer NV_REPOSITORY_COMPONENTS += userspace/units/ptimer
NV_REPOSITORY_COMPONENTS += userspace/units/mc
NV_REPOSITORY_COMPONENTS += userspace/units/mm/nvgpu_sgt NV_REPOSITORY_COMPONENTS += userspace/units/mm/nvgpu_sgt
NV_REPOSITORY_COMPONENTS += userspace/units/mm/nvgpu_mem NV_REPOSITORY_COMPONENTS += userspace/units/mm/nvgpu_mem
NV_REPOSITORY_COMPONENTS += userspace/units/mm/allocators/buddy_allocator NV_REPOSITORY_COMPONENTS += userspace/units/mm/allocators/buddy_allocator

View File

@@ -436,6 +436,13 @@ nvgpu_kmem_get_fault_injection
nvgpu_kzalloc_impl nvgpu_kzalloc_impl
nvgpu_vmalloc_impl nvgpu_vmalloc_impl
nvgpu_log_msg_impl nvgpu_log_msg_impl
nvgpu_mc_intr_mask
nvgpu_mc_intr_nonstall_pause
nvgpu_mc_intr_nonstall_resume
nvgpu_mc_intr_nonstall_unit_config
nvgpu_mc_intr_stall_pause
nvgpu_mc_intr_stall_resume
nvgpu_mc_intr_stall_unit_config
nvgpu_memset nvgpu_memset
nvgpu_mem_create_from_phys nvgpu_mem_create_from_phys
nvgpu_mem_iommu_translate nvgpu_mem_iommu_translate
@@ -613,6 +620,7 @@ nvgpu_vm_put
nvgpu_vm_put_buffers nvgpu_vm_put_buffers
nvgpu_vm_unmap nvgpu_vm_unmap
nvgpu_vzalloc_impl nvgpu_vzalloc_impl
nvgpu_wait_for_deferred_interrupts
nvgpu_writel nvgpu_writel
nvgpu_writel_check nvgpu_writel_check
nvgpu_clear_bit nvgpu_clear_bit

View File

@@ -62,6 +62,7 @@ UNITS := \
$(UNIT_SRC)/interface/lock \ $(UNIT_SRC)/interface/lock \
$(UNIT_SRC)/interface/atomic \ $(UNIT_SRC)/interface/atomic \
$(UNIT_SRC)/interface/rbtree \ $(UNIT_SRC)/interface/rbtree \
$(UNIT_SRC)/mc \
$(UNIT_SRC)/mm/nvgpu_sgt \ $(UNIT_SRC)/mm/nvgpu_sgt \
$(UNIT_SRC)/mm/allocators/buddy_allocator \ $(UNIT_SRC)/mm/allocators/buddy_allocator \
$(UNIT_SRC)/mm/allocators/nvgpu_allocator \ $(UNIT_SRC)/mm/allocators/nvgpu_allocator \

View File

@@ -1055,6 +1055,78 @@
"unit": "list", "unit": "list",
"test_level": 0 "test_level": 0
}, },
{
"test": "test_enable_disable_reset",
"case": "enable_disable_reset",
"unit": "mc",
"test_level": 0
},
{
"test": "test_is_stall_and_eng_intr_pending",
"case": "intr_is_stall_and_eng_intr_pending",
"unit": "mc",
"test_level": 0
},
{
"test": "test_intr_stall",
"case": "intr_stall",
"unit": "mc",
"test_level": 0
},
{
"test": "test_is_intr1_pending",
"case": "is_intr1_pending",
"unit": "mc",
"test_level": 0
},
{
"test": "test_isr_nonstall",
"case": "isr_nonstall",
"unit": "mc",
"test_level": 0
},
{
"test": "test_isr_stall",
"case": "isr_stall",
"unit": "mc",
"test_level": 0
},
{
"test": "test_free_env",
"case": "mc_free_env",
"unit": "mc",
"test_level": 0
},
{
"test": "test_setup_env",
"case": "mc_setup_env",
"unit": "mc",
"test_level": 0
},
{
"test": "test_pause_resume_mask",
"case": "pause_resume_mask",
"unit": "mc",
"test_level": 0
},
{
"test": "test_reset_mask",
"case": "reset_mask",
"unit": "mc",
"test_level": 0
},
{
"test": "test_unit_config",
"case": "unit_config",
"unit": "mc",
"test_level": 0
},
{
"test": "test_wait_for_deferred_interrupts",
"case": "wait_for_deferred_interrupts",
"unit": "mc",
"test_level": 0
},
{ {
"test": "test_as_alloc_share", "test": "test_as_alloc_share",
"case": "as_alloc_share_0k_um", "case": "as_alloc_share_0k_um",

View File

@@ -0,0 +1,26 @@
# 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-mc.o
MODULE = mc
include ../Makefile.units

View File

@@ -0,0 +1,23 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2019, NVIDIA CORPORATION. All Rights Reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=mc
include $(NV_COMPONENT_DIR)/../Makefile.units.common.interface.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,24 @@
################################### tell Emacs this is a -*- makefile-gmake -*-
#
# Copyright (c) 2019, NVIDIA CORPORATION. All Rights Reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto. Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
#
# tmake for SW Mobile component makefile
#
###############################################################################
NVGPU_UNIT_NAME=mc
NVGPU_UNIT_SRCS=nvgpu-mc.c
include $(NV_COMPONENT_DIR)/../Makefile.units.common.tmk
# Local Variables:
# indent-tabs-mode: t
# tab-width: 8
# End:
# vi: set tabstop=8 noexpandtab:

View File

@@ -0,0 +1,805 @@
/*
* 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 <unit/unit.h>
#include <unit/io.h>
#include <nvgpu/posix/io.h>
#include <nvgpu/gk20a.h>
#include <nvgpu/mc.h>
#include <nvgpu/hal_init.h>
#include <nvgpu/top.h>
#include <nvgpu/engines.h>
#include <nvgpu/ltc.h>
#include <nvgpu/hw/gp10b/hw_mc_gp10b.h>
#include <nvgpu/posix/cond.h>
#include <nvgpu/posix/posix-fault-injection.h>
#include "nvgpu-mc.h"
#define MC_ADDR_SPACE_START 0x00000000
#define MC_ADDR_SPACE_SIZE 0xfff
/* value for GV11B */
#define MC_BOOT_0_GV11B (NVGPU_GPUID_GV11B << 20)
/* to set the security fuses */
#define GP10B_FUSE_REG_BASE 0x00021000U
#define GP10B_FUSE_OPT_PRIV_SEC_EN (GP10B_FUSE_REG_BASE+0x434U)
#define ACTIVE_GR_ID 1
#define ACTIVE_CE_ID 2
#define STALL_EN_REG mc_intr_en_set_r(NVGPU_MC_INTR_STALLING)
#define STALL_DIS_REG mc_intr_en_clear_r(NVGPU_MC_INTR_STALLING)
#define NONSTALL_EN_REG mc_intr_en_set_r(NVGPU_MC_INTR_NONSTALLING)
#define NONSTALL_DIS_REG mc_intr_en_clear_r(NVGPU_MC_INTR_NONSTALLING)
#define STALL_PENDING_REG mc_intr_r(NVGPU_MC_INTR_STALLING)
#define NONSTALL_PENDING_REG mc_intr_r(NVGPU_MC_INTR_NONSTALLING)
struct mc_unit {
u32 num;
u32 bit;
};
static struct mc_unit mc_units[] = {
{ MC_INTR_UNIT_BUS, mc_intr_pbus_pending_f() },
{ MC_INTR_UNIT_PRIV_RING, mc_intr_priv_ring_pending_f() },
{ MC_INTR_UNIT_FIFO, mc_intr_pfifo_pending_f() },
{ MC_INTR_UNIT_LTC, mc_intr_ltc_pending_f() },
{ MC_INTR_UNIT_HUB, mc_intr_replayable_fault_pending_f() },
{ MC_INTR_UNIT_GR, (1 << ACTIVE_GR_ID) /* nvgpu_gr_engine_interrupt_mask() */},
{ MC_INTR_UNIT_PMU, mc_intr_pmu_pending_f() },
{ MC_INTR_UNIT_CE, (1 << ACTIVE_CE_ID) /* nvgpu_ce_engine_interrupt_mask() */ },
};
#define NUM_MC_UNITS ARRAY_SIZE(mc_units)
#define INVALID_UNIT 100
/*
* Mock I/O
*/
/*
* Write callback. Forward the write access to the mock IO framework.
*/
static void writel_access_reg_fn(struct gk20a *g,
struct nvgpu_reg_access *access)
{
nvgpu_posix_io_writel_reg_space(g, access->addr, access->value);
}
/*
* Read callback. Get the register value from the mock IO framework.
*/
static void readl_access_reg_fn(struct gk20a *g,
struct nvgpu_reg_access *access)
{
access->value = nvgpu_posix_io_readl_reg_space(g, access->addr);
}
static struct nvgpu_posix_io_callbacks test_reg_callbacks = {
/* Write APIs all can use the same accessor. */
.writel = writel_access_reg_fn,
.writel_check = writel_access_reg_fn,
.bar1_writel = writel_access_reg_fn,
.usermode_writel = writel_access_reg_fn,
/* Likewise for the read APIs. */
.__readl = readl_access_reg_fn,
.readl = readl_access_reg_fn,
.bar1_readl = readl_access_reg_fn,
};
struct unit_ctx {
bool bus_isr;
bool ce_isr;
bool fb_isr;
bool fifo_isr;
bool gr_isr;
bool ltc_isr;
bool priv_ring_isr;
u32 ce_isr_return;
u32 fifo_isr_return;
int gr_isr_return;
};
static struct unit_ctx u;
static void reset_ctx(void)
{
u.bus_isr = false;
u.ce_isr = false;
u.fb_isr = false;
u.fifo_isr = false;
u.gr_isr = false;
u.gr_isr_return = 0;
u.ltc_isr = false;
u.priv_ring_isr = false;
}
/*
* Replacement functions that can be assigned to function pointers
*/
static int mock_get_device_info(struct gk20a *g,
struct nvgpu_device_info *dev_info,
u32 engine_type, u32 inst_id)
{
if (engine_type == NVGPU_ENGINE_GRAPHICS) {
dev_info->intr_id = ACTIVE_GR_ID;
dev_info->engine_id = 0;
dev_info->engine_type = 0;
} else if (engine_type == NVGPU_ENGINE_LCE) {
dev_info->intr_id = ACTIVE_CE_ID;
dev_info->engine_id = 1;
dev_info->engine_type = 0x13;
dev_info->reset_id = ffs(mc_enable_ce2_enabled_f()) - 1;
}
return 0;
}
static bool mock_pbdma_find_for_runlist(struct gk20a *g, u32 runlist_id,
u32 *pbdma_id)
{
return true;
}
static u32 mock_get_num_engine_type_entries(struct gk20a *g, u32 engine_type)
{
if (engine_type == NVGPU_ENGINE_LCE) {
return 1;
}
return 0;
}
static void mock_bus_isr(struct gk20a *g)
{
u.bus_isr = true;
}
static void mock_ce_stall_isr(struct gk20a *g, u32 inst_id, u32 pri_base)
{
u.ce_isr = true;
}
static u32 mock_ce_nonstall_isr(struct gk20a *g, u32 inst_id, u32 pri_base)
{
u.ce_isr = true;
return u.ce_isr_return;
}
static void mock_fb_isr(struct gk20a *g)
{
u.fb_isr = true;
}
static void mock_fifo_stall_isr(struct gk20a *g)
{
u.fifo_isr = true;
}
static u32 mock_fifo_nonstall_isr(struct gk20a *g)
{
u.fifo_isr = true;
return u.fifo_isr_return;
}
static u32 mock_gr_nonstall_isr(struct gk20a *g)
{
u.gr_isr = true;
return (u32)u.gr_isr_return;
}
static int mock_gr_stall_isr(struct gk20a *g)
{
u.gr_isr = true;
return u.gr_isr_return;
}
static void mock_ltc_isr(struct gk20a *g, u32 ltc)
{
u.ltc_isr = true;
}
static void mock_priv_ring_isr(struct gk20a *g)
{
u.priv_ring_isr = true;
}
int test_setup_env(struct unit_module *m,
struct gk20a *g, void *args)
{
/* Create mc register space */
nvgpu_posix_io_init_reg_space(g);
if (nvgpu_posix_io_add_reg_space(g, MC_ADDR_SPACE_START,
MC_ADDR_SPACE_SIZE) != 0) {
unit_err(m, "%s: failed to create register space\n",
__func__);
return UNIT_FAIL;
}
/* Create fuse register space */
if (nvgpu_posix_io_add_reg_space(g, GP10B_FUSE_REG_BASE, 0xfff) != 0) {
unit_err(m, "%s: failed to create register space\n",
__func__);
return UNIT_FAIL;
}
(void)nvgpu_posix_register_io(g, &test_reg_callbacks);
nvgpu_posix_io_writel_reg_space(g, mc_boot_0_r(), MC_BOOT_0_GV11B);
nvgpu_posix_io_writel_reg_space(g, GP10B_FUSE_OPT_PRIV_SEC_EN, 0x0);
if (nvgpu_detect_chip(g) != 0) {
unit_err(m, "%s: failed to init HAL\n", __func__);
return UNIT_FAIL;
}
/* override HALs */
g->ops.top.get_device_info = mock_get_device_info;
g->ops.pbdma.find_for_runlist = mock_pbdma_find_for_runlist;
g->ops.top.get_num_engine_type_entries =
mock_get_num_engine_type_entries;
g->ops.bus.isr = mock_bus_isr;
g->ops.ce.isr_stall = mock_ce_stall_isr;
g->ops.ce.isr_nonstall = mock_ce_nonstall_isr;
g->ops.fb.intr.isr = mock_fb_isr;
g->ops.fifo.intr_0_isr = mock_fifo_stall_isr;
g->ops.fifo.intr_1_isr = mock_fifo_nonstall_isr;
g->ops.gr.intr.stall_isr = mock_gr_stall_isr;
g->ops.gr.intr.nonstall_isr = mock_gr_nonstall_isr;
g->ops.ltc.intr.isr = mock_ltc_isr;
g->ops.priv_ring.isr = mock_priv_ring_isr;
/* setup engines for getting interrupt info */
g->fifo.g = g;
if (nvgpu_engine_setup_sw(g) != 0) {
unit_return_fail(m, "failed to setup engines\n");
}
/* setup LTC just enough */
g->ltc = nvgpu_kzalloc(g, sizeof(struct nvgpu_ltc));
if (g->ltc == NULL) {
unit_return_fail(m, "failed to alloc\n");
}
g->ltc->ltc_count = 1;
return UNIT_SUCCESS;
}
int test_free_env(struct unit_module *m, struct gk20a *g, void *args)
{
/* Free mc register space */
nvgpu_posix_io_delete_reg_space(g, MC_ADDR_SPACE_START);
nvgpu_posix_io_delete_reg_space(g, GP10B_FUSE_REG_BASE);
nvgpu_engine_cleanup_sw(g);
nvgpu_kfree(g, g->ltc);
return UNIT_SUCCESS;
}
int test_unit_config(struct unit_module *m, struct gk20a *g, void *args)
{
u32 i;
u32 unit;
u32 val;
/* clear regs */
nvgpu_posix_io_writel_reg_space(g, STALL_EN_REG, 0x0);
nvgpu_posix_io_writel_reg_space(g, STALL_DIS_REG, 0x0);
nvgpu_posix_io_writel_reg_space(g, NONSTALL_EN_REG, 0x0);
nvgpu_posix_io_writel_reg_space(g, NONSTALL_DIS_REG, 0x0);
for (i = 0; i < NUM_MC_UNITS; i++) {
unit = mc_units[i].num;
/* enable stall intr */
nvgpu_mc_intr_stall_unit_config(g, unit, true);
val = nvgpu_posix_io_readl_reg_space(g, STALL_EN_REG);
if (val != mc_units[i].bit) {
unit_return_fail(m, "failed to enable stall intr for unit %u val=0x%08x\n",
unit, val);
}
/* disable stall intr */
nvgpu_mc_intr_stall_unit_config(g, unit, false);
val = nvgpu_posix_io_readl_reg_space(g, STALL_DIS_REG);
if (val != mc_units[i].bit) {
unit_return_fail(m, "failed to disable stall intr for unit %u val=0x%08x\n",
unit, val);
}
/* enable nonstall intr */
nvgpu_mc_intr_nonstall_unit_config(g, unit, true);
val = nvgpu_posix_io_readl_reg_space(g, NONSTALL_EN_REG);
if (val != mc_units[i].bit) {
unit_return_fail(m, "failed to enable nonstall intr for unit %u val=0x%08x\n",
unit, val);
}
/* disable stall intr */
nvgpu_mc_intr_nonstall_unit_config(g, unit, false);
val = nvgpu_posix_io_readl_reg_space(g, NONSTALL_DIS_REG);
if (val != mc_units[i].bit) {
unit_return_fail(m, "failed to disable nonstall intr for unit %u val=0x%08x\n",
unit, val);
}
}
/* negative testing - invalid unit - stall */
nvgpu_posix_io_writel_reg_space(g, STALL_EN_REG, 0x0); /* clear reg */
nvgpu_mc_intr_stall_unit_config(g, U32_MAX, true);
val = nvgpu_posix_io_readl_reg_space(g, STALL_EN_REG);
if (val != 0U) {
unit_return_fail(m, "Incorrectly enabled interrupt for invalid unit, val=0x%08x\n",
val);
}
/* negative testing - invalid unit - nonstall */
nvgpu_posix_io_writel_reg_space(g, NONSTALL_EN_REG, 0x0); /* clear reg */
nvgpu_mc_intr_nonstall_unit_config(g, U32_MAX, true);
val = nvgpu_posix_io_readl_reg_space(g, NONSTALL_EN_REG);
if (val != 0U) {
unit_return_fail(m, "Incorrectly enabled interrupt for invalid unit, val=0x%08x\n",
val);
}
return UNIT_SUCCESS;
}
int test_pause_resume_mask(struct unit_module *m, struct gk20a *g, void *args)
{
u32 val;
u32 expected_stall_val = mc_intr_priv_ring_pending_f();
u32 expected_nonstall_val = mc_intr_pbus_pending_f();
void (*save_func)(struct gk20a *g);
/* clear regs */
nvgpu_posix_io_writel_reg_space(g, STALL_EN_REG, 0x0);
nvgpu_posix_io_writel_reg_space(g, STALL_DIS_REG, 0x0);
nvgpu_posix_io_writel_reg_space(g, NONSTALL_EN_REG, 0x0);
nvgpu_posix_io_writel_reg_space(g, NONSTALL_DIS_REG, 0x0);
/* cleanup anything from previous tests */
g->mc.intr_mask_restore[0] = 0U;
g->mc.intr_mask_restore[1] = 0U;
/* enable something to pause and resume */
nvgpu_mc_intr_stall_unit_config(g, MC_INTR_UNIT_PRIV_RING, true);
nvgpu_mc_intr_nonstall_unit_config(g, MC_INTR_UNIT_BUS, true);
/* pause stall */
nvgpu_mc_intr_stall_pause(g);
val = nvgpu_posix_io_readl_reg_space(g, STALL_DIS_REG);
if (val != U32_MAX) {
unit_return_fail(m, "failed to pause stall intr\n");
}
/* pause nonstall */
nvgpu_mc_intr_nonstall_pause(g);
val = nvgpu_posix_io_readl_reg_space(g, NONSTALL_DIS_REG);
if (val != U32_MAX) {
unit_return_fail(m, "failed to pause nonstall intr\n");
}
/* resume stall */
nvgpu_posix_io_writel_reg_space(g, STALL_EN_REG, 0x0);
nvgpu_mc_intr_stall_resume(g);
val = nvgpu_posix_io_readl_reg_space(g, STALL_EN_REG);
if (val != expected_stall_val) {
unit_return_fail(m, "failed to resume stall intr\n");
}
/* resume nonstall */
nvgpu_posix_io_writel_reg_space(g, NONSTALL_EN_REG, 0x0);
nvgpu_mc_intr_nonstall_resume(g);
val = nvgpu_posix_io_readl_reg_space(g, NONSTALL_EN_REG);
if (val != expected_nonstall_val) {
unit_return_fail(m, "failed to resume nonstall intr\n");
}
/* clear regs */
nvgpu_posix_io_writel_reg_space(g, STALL_DIS_REG, 0x0);
nvgpu_posix_io_writel_reg_space(g, NONSTALL_DIS_REG, 0x0);
/* mask all */
nvgpu_mc_intr_mask(g);
val = nvgpu_posix_io_readl_reg_space(g, STALL_DIS_REG);
if (val != U32_MAX) {
unit_return_fail(m, "failed to mask stall intr\n");
}
val = nvgpu_posix_io_readl_reg_space(g, NONSTALL_DIS_REG);
if (val != U32_MAX) {
unit_return_fail(m, "failed to mask nonstall intr\n");
}
/* make this HAL NULL for branch coverage */
save_func = g->ops.mc.intr_mask;
g->ops.mc.intr_mask = NULL;
nvgpu_mc_intr_mask(g);
g->ops.mc.intr_mask = save_func;
return UNIT_SUCCESS;
}
static void switch_ce_engine_type(struct nvgpu_engine_info *info)
{
if (info->engine_enum == NVGPU_ENGINE_ASYNC_CE) {
info->engine_enum = NVGPU_ENGINE_GRCE;
} else if (info->engine_enum == NVGPU_ENGINE_GRCE) {
info->engine_enum = NVGPU_ENGINE_ASYNC_CE;
} else {
BUG();
}
}
int test_intr_stall(struct unit_module *m, struct gk20a *g, void *args)
{
u32 i, pend, val;
for (i = 0; i < 32; i++) {
pend = (1 << i);
nvgpu_posix_io_writel_reg_space(g, STALL_PENDING_REG, pend);
val = g->ops.mc.intr_stall(g);
if (val != pend) {
unit_return_fail(m, "incorrect stall value returned\n");
}
}
return UNIT_SUCCESS;
}
int test_is_stall_and_eng_intr_pending(struct unit_module *m, struct gk20a *g,
void *args)
{
u32 act_eng_id = 0; /* GR engine */
u32 eng_intr_pending = 0;
u32 intrs_pending = 0;
u32 expected_eng_intr_pending = 0;
bool result;
unsigned int i;
/* test with nothing pending */
nvgpu_posix_io_writel_reg_space(g, STALL_PENDING_REG, 0);
result = g->ops.mc.is_stall_and_eng_intr_pending(g, act_eng_id,
&eng_intr_pending);
if (result) {
unit_return_fail(m, "incorrect value returned\n");
}
/* test with everything pending */
for (i = 0U; i < NUM_MC_UNITS; i++) {
intrs_pending |= mc_units[i].bit;
if (mc_units[i].num == MC_INTR_UNIT_GR) {
expected_eng_intr_pending = mc_units[i].bit;
}
}
nvgpu_posix_io_writel_reg_space(g, STALL_PENDING_REG, intrs_pending);
result = g->ops.mc.is_stall_and_eng_intr_pending(g, act_eng_id,
&eng_intr_pending);
if (!result || (eng_intr_pending != expected_eng_intr_pending)) {
unit_return_fail(m, "incorrect value returned\n");
}
return UNIT_SUCCESS;
}
int test_isr_stall(struct unit_module *m, struct gk20a *g, void *args)
{
u32 intrs_pending = 0;
u32 i;
bool (*save_intr_hub_pending)(struct gk20a *g, u32 intr);
/* for branch coverage, test with nothing pending */
nvgpu_posix_io_writel_reg_space(g, STALL_PENDING_REG, 0);
reset_ctx();
g->ops.mc.isr_stall(g);
if (u.bus_isr || u.ce_isr || u.fb_isr || u.fifo_isr || u.gr_isr ||
u.priv_ring_isr) {
unit_return_fail(m, "unexpected ISR called\n");
}
/* setup regs for basic test with all units intr pending */
for (i = 0; i < NUM_MC_UNITS; i++) {
intrs_pending |= mc_units[i].bit;
}
nvgpu_posix_io_writel_reg_space(g, STALL_PENDING_REG, intrs_pending);
nvgpu_posix_io_writel_reg_space(g, mc_intr_ltc_r(), 1U);
reset_ctx();
g->ops.mc.isr_stall(g);
if (!u.bus_isr || !u.ce_isr || !u.fb_isr || !u.fifo_isr || !u.gr_isr ||
!u.priv_ring_isr) {
unit_return_fail(m, "not all ISRs called\n");
}
/* for branch coverage set this HAL to NULL */
save_intr_hub_pending = g->ops.mc.is_intr_hub_pending;
g->ops.mc.is_intr_hub_pending = NULL;
for (i = 0; i < NUM_MC_UNITS; i++) {
intrs_pending |= mc_units[i].bit;
}
nvgpu_posix_io_writel_reg_space(g, STALL_PENDING_REG, intrs_pending);
reset_ctx();
g->ops.mc.isr_stall(g);
if (u.fb_isr) {
unit_return_fail(m, "unexpected ISR called\n");
}
g->ops.mc.is_intr_hub_pending = save_intr_hub_pending;
/* for branch coverage return error from GR ISR */
for (i = 0; i < NUM_MC_UNITS; i++) {
intrs_pending |= mc_units[i].bit;
}
nvgpu_posix_io_writel_reg_space(g, STALL_PENDING_REG, intrs_pending);
reset_ctx();
u.gr_isr_return = -1;
g->ops.mc.isr_stall(g);
/* for branch coverage set this HAL to NULL */
g->ops.ce.isr_stall = NULL;
for (i = 0; i < NUM_MC_UNITS; i++) {
intrs_pending |= mc_units[i].bit;
}
nvgpu_posix_io_writel_reg_space(g, STALL_PENDING_REG, intrs_pending);
reset_ctx();
g->ops.mc.isr_stall(g);
g->ops.ce.isr_stall = mock_ce_stall_isr;
/* for branch coverage set CE engine to other type */
switch_ce_engine_type(&g->fifo.engine_info[1]);
for (i = 0; i < NUM_MC_UNITS; i++) {
intrs_pending |= mc_units[i].bit;
}
nvgpu_posix_io_writel_reg_space(g, STALL_PENDING_REG, intrs_pending);
reset_ctx();
g->ops.mc.isr_stall(g);
if (!u.ce_isr) {
unit_return_fail(m, "ISR not called\n");
}
/*
* for branch coverage set LTC intr in main intr reg, but not ltc
* intr reg
*/
for (i = 0; i < NUM_MC_UNITS; i++) {
intrs_pending |= mc_units[i].bit;
}
nvgpu_posix_io_writel_reg_space(g, STALL_PENDING_REG, intrs_pending);
nvgpu_posix_io_writel_reg_space(g, mc_intr_ltc_r(), 0U);
reset_ctx();
g->ops.mc.isr_stall(g);
if (u.ltc_isr) {
unit_return_fail(m, "unexpected ISR called\n");
}
return UNIT_SUCCESS;
}
int test_is_intr1_pending(struct unit_module *m, struct gk20a *g, void *args)
{
struct match_struct {
enum nvgpu_unit unit;
u32 mask;
bool expect;
};
const struct match_struct match_table[] = {
{ NVGPU_UNIT_FIFO, ~mc_enable_pfifo_enabled_f(), false },
{ NVGPU_UNIT_FIFO, mc_enable_pfifo_enabled_f(), true },
{ INVALID_UNIT, 0x0, false },
};
unsigned int i;
bool val;
for (i = 0; i < ARRAY_SIZE(match_table); i++) {
val = g->ops.mc.is_intr1_pending(g, match_table[i].unit,
match_table[i].mask);
if (val != match_table[i].expect) {
unit_return_fail(m, "incorrect stall value returned\n");
}
}
return UNIT_SUCCESS;
}
int test_isr_nonstall(struct unit_module *m, struct gk20a *g, void *args)
{
u32 intrs_pending = 0;
u32 i;
u32 val;
/* for branch coverage, test with nothing pending */
nvgpu_posix_io_writel_reg_space(g, NONSTALL_PENDING_REG, 0);
reset_ctx();
val = g->ops.mc.isr_nonstall(g);
if (u.bus_isr || u.ce_isr || u.fb_isr || u.fifo_isr || u.gr_isr ||
u.priv_ring_isr) {
unit_return_fail(m, "unexpected ISR called\n");
}
/* setup regs for basic test with all units intr pending */
for (i = 0; i < NUM_MC_UNITS; i++) {
intrs_pending |= mc_units[i].bit;
}
nvgpu_posix_io_writel_reg_space(g, NONSTALL_PENDING_REG, intrs_pending);
reset_ctx();
u.ce_isr_return = 0x1;
u.fifo_isr_return = 0x2;
u.gr_isr_return = 0x4;
val = g->ops.mc.isr_nonstall(g);
if (!u.ce_isr || !u.fifo_isr || !u.gr_isr) {
unit_return_fail(m, "not all ISRs called\n");
}
if (val != 0x7) {
unit_return_fail(m, "incorrect ops returned 0x%08x\n", val);
}
/* for branch coverage set this HAL to NULL */
g->ops.ce.isr_nonstall = NULL;
for (i = 0; i < NUM_MC_UNITS; i++) {
intrs_pending |= mc_units[i].bit;
}
nvgpu_posix_io_writel_reg_space(g, NONSTALL_PENDING_REG, intrs_pending);
reset_ctx();
g->ops.mc.isr_nonstall(g);
g->ops.ce.isr_nonstall = mock_ce_nonstall_isr;
/* for branch coverage set CE engine to the opposite type */
switch_ce_engine_type(&g->fifo.engine_info[1]);
for (i = 0; i < NUM_MC_UNITS; i++) {
intrs_pending |= mc_units[i].bit;
}
nvgpu_posix_io_writel_reg_space(g, NONSTALL_PENDING_REG, intrs_pending);
reset_ctx();
g->ops.mc.isr_nonstall(g);
if (!u.ce_isr) {
unit_return_fail(m, "ISR not called\n");
}
return UNIT_SUCCESS;
}
int test_enable_disable_reset(struct unit_module *m, struct gk20a *g, void *args)
{
u32 units = (g->ops.mc.reset_mask(g, NVGPU_UNIT_FIFO) |
g->ops.mc.reset_mask(g, NVGPU_UNIT_GRAPH) |
g->ops.mc.reset_mask(g, NVGPU_UNIT_BLG) |
mc_enable_ce2_enabled_f());
u32 val;
/* test enable */
nvgpu_posix_io_writel_reg_space(g, mc_enable_r(), 0);
g->ops.mc.enable(g, units);
val = nvgpu_posix_io_readl_reg_space(g, mc_enable_r());
if (val != units) {
unit_return_fail(m, "failed to reset units val=0x%08x\n", val);
}
/* test disable */
g->ops.mc.disable(g, units);
val = nvgpu_posix_io_readl_reg_space(g, mc_enable_r());
if (val != 0U) {
unit_return_fail(m, "failed to reset units val=0x%08x\n", val);
}
/* test reset */
nvgpu_posix_io_writel_reg_space(g, mc_enable_r(), units);
g->ops.mc.reset(g, units);
val = nvgpu_posix_io_readl_reg_space(g, mc_enable_r());
if (val != units) {
unit_return_fail(m, "failed to reset units val=0x%08x\n", val);
}
/* for branch coverage, do not include CE's */
units = NVGPU_UNIT_FIFO | NVGPU_UNIT_GRAPH;
nvgpu_posix_io_writel_reg_space(g, mc_enable_r(), units);
g->ops.mc.reset(g, units);
val = nvgpu_posix_io_readl_reg_space(g, mc_enable_r());
if (val != units) {
unit_return_fail(m, "failed to reset units val=0x%08x\n", val);
}
return UNIT_SUCCESS;
}
int test_reset_mask(struct unit_module *m, struct gk20a *g, void *args)
{
struct match_struct {
enum nvgpu_unit unit;
u32 mask;
};
const struct match_struct match_table[] = {
{ NVGPU_UNIT_FIFO, mc_enable_pfifo_enabled_f() },
{ NVGPU_UNIT_PERFMON, mc_enable_perfmon_enabled_f() },
{ NVGPU_UNIT_GRAPH, mc_enable_pgraph_enabled_f() },
{ NVGPU_UNIT_BLG, mc_enable_blg_enabled_f() },
};
unsigned int i;
u32 val;
for (i = 0U; i < ARRAY_SIZE(match_table); i++) {
val = g->ops.mc.reset_mask(g, match_table[i].unit);
if (val != match_table[i].mask) {
unit_return_fail(m, "incorrect mask returned\n");
}
}
/* pass invalid unit for branch coverage */
val = g->ops.mc.reset_mask(g, INVALID_UNIT);
if (val != 0U) {
unit_return_fail(m, "incorrect mask returned\n");
}
return UNIT_SUCCESS;
}
int test_wait_for_deferred_interrupts(struct unit_module *m, struct gk20a *g,
void *args)
{
struct nvgpu_posix_fault_inj *cond_fi =
nvgpu_cond_get_fault_injection();
nvgpu_cond_init(&g->mc.sw_irq_stall_last_handled_cond);
nvgpu_cond_init(&g->mc.sw_irq_nonstall_last_handled_cond);
/* immediate completion */
nvgpu_atomic_set(&g->mc.hw_irq_stall_count, 0);
nvgpu_atomic_set(&g->mc.sw_irq_stall_last_handled, 0);
nvgpu_atomic_set(&g->mc.hw_irq_nonstall_count, 0);
nvgpu_atomic_set(&g->mc.sw_irq_nonstall_last_handled, 0);
nvgpu_wait_for_deferred_interrupts(g);
/* cause timeout */
nvgpu_posix_enable_fault_injection(cond_fi, true, 0);
/* wait on stall until timeout for branch coverage */
nvgpu_atomic_set(&g->mc.hw_irq_stall_count, 1);
nvgpu_atomic_set(&g->mc.sw_irq_stall_last_handled, 0);
nvgpu_atomic_set(&g->mc.hw_irq_nonstall_count, 0);
nvgpu_atomic_set(&g->mc.sw_irq_nonstall_last_handled, 0);
nvgpu_wait_for_deferred_interrupts(g);
/* wait on nonstall until timeout for branch coverage */
nvgpu_atomic_set(&g->mc.hw_irq_stall_count, 0);
nvgpu_atomic_set(&g->mc.sw_irq_stall_last_handled, 0);
nvgpu_atomic_set(&g->mc.hw_irq_nonstall_count, 1);
nvgpu_atomic_set(&g->mc.sw_irq_nonstall_last_handled, 0);
nvgpu_wait_for_deferred_interrupts(g);
return UNIT_SUCCESS;
}
struct unit_module_test mc_tests[] = {
UNIT_TEST(mc_setup_env, test_setup_env, NULL, 0),
UNIT_TEST(unit_config, test_unit_config, NULL, 0),
UNIT_TEST(pause_resume_mask, test_pause_resume_mask, NULL, 0),
UNIT_TEST(intr_stall, test_intr_stall, NULL, 0),
UNIT_TEST(intr_is_stall_and_eng_intr_pending,
test_is_stall_and_eng_intr_pending, NULL, 0),
UNIT_TEST(isr_stall, test_isr_stall, NULL, 0),
UNIT_TEST(isr_nonstall, test_isr_nonstall, NULL, 0),
UNIT_TEST(is_intr1_pending, test_is_intr1_pending, NULL, 0),
UNIT_TEST(enable_disable_reset, test_enable_disable_reset, NULL, 0),
UNIT_TEST(reset_mask, test_reset_mask, NULL, 0),
UNIT_TEST(wait_for_deferred_interrupts, test_wait_for_deferred_interrupts, NULL, 0),
UNIT_TEST(mc_free_env, test_free_env, NULL, 0),
};
UNIT_MODULE(mc, mc_tests, UNIT_PRIO_NVGPU_TEST);

View File

@@ -0,0 +1,358 @@
/*
* 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_MC_H
#define UNIT_NVGPU_MC_H
struct gk20a;
struct unit_module;
/** @addtogroup SWUTS-mc
* @{
*
* Software Unit Test Specification for MC
*/
/**
* Test specification for: test_setup_env
*
* Description: Do basic setup before starting other tests.
*
* Test Type: Other (setup)
*
* Input: None
*
* Steps:
* - Initialize reg spaces used by tests.
* - Override HALs for other dependent units.
* - Do minimal initialization for engines and ltc units.
*
* Output:
* - UNIT_FAIL if encounters an error creating reg space
* - UNIT_SUCCESS otherwise
*/
int test_setup_env(struct unit_module *m,
struct gk20a *g, void *args);
/**
* Test specification for: test_free_env
*
* Description: Do basic setup before starting other tests.
*
* Test Type: Other (setup)
*
* Input: test_setup_env has run.
*
* Steps:
* - Free reg spaces.
* - Cleanup engine setup.
* - Free ltc memory.
*
* Output: UNIT_SUCCESS always.
*/
int test_free_env(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_unit_config
*
* Description: Validate function of nvgpu_mc_intr_stall_unit_config and
* nvgpu_mc_intr_nonstall_unit_config.
*
* Test Type: Feature based
*
* Targets: nvgpu_mc_intr_stall_unit_config, nvgpu_mc_intr_nonstall_unit_config
*
* Input: test_setup_env must have been run.
*
* Steps:
* - Set each of the mock registers for enabling & disabling the stall &
* non-stall interrupts to 0.
* - Loop through table of units:
* - Call nvgpu_mc_intr_stall_unit_config for the unit to enable the stall
* interrupt.
* - Verify the stall interrupt enable register has the bit set for the unit.
* - Call nvgpu_mc_intr_stall_unit_config for the unit to disable the interrupt.
* - Verify the stall interrupt disable register has the bit set for the unit.
* - Call nvgpu_mc_intr_nonstall_unit_config for the unit to enable the
* non-stall interrupt.
* - Verify the non-stall interrupt enable register has the bit set for the unit.
* - Call nvgpu_mc_intr_nonstall_unit_config for the unit to disable the interrupt.
* - Verify the non-stall interrupt disable register has the bit set for the unit.
* - Clear the stall enable register.
* - For negative testing, call nvgpu_mc_intr_stall_unit_config() with an
* invalid unit number, and verify no bits are set in the stall interrupt
* enable register.
* - Clear the stall enable register.
* - For negative testing, call nvgpu_mc_intr_nonstall_unit_config() with an
* invalid unit number, and verify no bits are set in the non-stall interrupt
* enable register.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_unit_config(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_pause_resume_mask
*
* Description: Validate function for pausing, resuming, and masking interrupts.
*
* Test Type: Feature based
*
* Targets: nvgpu_mc_intr_stall_pause, nvgpu_mc_intr_stall_resume,
* nvgpu_mc_intr_nonstall_pause, nvgpu_mc_intr_nonstall_resume,
* nvgpu_mc_intr_mask
*
* Input: test_setup_env must have been run.
*
* Steps:
* - Clear each of the mock registers for enabling & disabling the stall &
* non-stall interrupts.
* - Clear mc state regs for active interrupts.
* - Enable interupts so they can be paused and resumed.
* - Pause the interrupts.
* - Verify all the bits were written in the stall and non-stall interrupt
* disable registers.
* - Resume the interrupts.
* - Verify the correct values are in the stall and non-stall interrupt enable
* registers.
* - Clear the stall and non-stall disable registers.
* - Mask the interrupts.
* - Verify all the bits were written in the stall and non-stall interrupt
* disable registers.
* - For branch coverage, temporarily set the g->ops.mc.intr_mask HAL to NULL.
* - Mask the interrupts.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_pause_resume_mask(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_intr_stall
*
* Description: Validate function mc_gp10b_intr_stall which returns the pending
* interrupts.
*
* Test Type: Feature based
*
* Targets: mc_gp10b_intr_stall
*
* Input: test_setup_env must have been run.
*
* Steps:
* - Loop through setting each bit individually in the stall interrupt pending
* register:
* - For iteration, call the HAL and verify the correct value is returned.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_intr_stall(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_is_stall_and_eng_intr_pending
*
* Description: Validate function of HAL gv11b_mc_is_stall_and_eng_intr_pending.
*
* Test Type: Feature based
*
* Targets: gv11b_mc_is_stall_and_eng_intr_pending
*
* Input: test_setup_env must have been run.
*
* Steps:
* - Clear the stall interrupt pending register.
* - Call the HAL API and verify it returns false since nothing is pending.
* - Set all interrupts pending in the stall interrupt pending register.
* - Call the HAL API and verify it returns true and the correct pending mask.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_is_stall_and_eng_intr_pending(struct unit_module *m, struct gk20a *g,
void *args);
/**
* Test specification for: test_isr_stall
*
* Description: Validate handling of the stall interrupts by the stall interrupt
* service routine.
*
* Test Type: Feature based
*
* Targets: mc_gp10b_isr_stall
*
* Input: test_setup_env must have been run.
*
* Steps:
* - Clear the stall interrupt pending register.
* - Call the stall ISR.
* - Verify none of the mock unit ISRs (for bus, ce, fb, etc) are called.
* - Set all interrupts pending in the stall interrupt pending register.
* - Call the stall ISR.
* - Verify all of the mock unit ISRs are called.
* - For branch coverage, set the HAL pointer g->ops.mc.is_intr_hub_pending to
* NULL.
* - Call the stall ISR. No exception should occur.
* - For branch coverage, configure the mock GR ISR to return an error.
* - Call the stall ISR. No exception should occur.
* - For branch coverage, configure the mock CE ISR pointer to NULL.
* - Call the stall ISR. No exception should occur.
* - For branch coverage, configure the active CE engine to the other type.
* - Call the stall ISR. No exception should occur.
* - For branch coverage, enable the LTC interupt pending in main MC pending
* register, MC_INTR, but disable the LTC interrupt pending in the LTC-specific
* register, MC_INTR_LTC.
* - Call the stall ISR.
* - Verify the mock LTC ISR was not called.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_isr_stall(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_isr_nonstall
*
* Description: Validate handling of the stall interrupts by the non-stall
* interrupt service routine.
*
* Test Type: Feature based
*
* Targets: gm20b_mc_isr_nonstall
*
* Input: test_setup_env must have been run.
*
* Steps:
* - Clear the non-stall interrupt pending register.
* - Call the non-stall ISR.
* - Verify none of the mock unit ISRs (for bus, ce, fb, etc) are called.
* - Set all interrupts pending in the non-stall interrupt pending register.
* - Call the non-stall ISR.
* - Verify all of the mock unit ISRs are called and the correct ops are returned.
* - For branch coverage, configure the mock CE ISR pointer to NULL.
* - Call the non-stall ISR. No exception should occur.
* - For branch coverage, configure the active CE engine to the other type.
* - Call the non-stall ISR. No exception should occur.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_isr_nonstall(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_is_intr1_pending
*
* Description: Validate functionality of mc_gp10b_is_intr1_pending.
*
* Test Type: Feature based
*
* Targets: mc_gp10b_is_intr1_pending
*
* Input: test_setup_env must have been run.
*
* Steps:
* - Call the HAL API, requesting if the FIFO Unit is pending, passing in a
* register mask that does not have that Unit pending. Verify false is
* returned.
* - Call the HAL API, requesting if the FIFO Unit is pending, passing in a
* register mask that does have that Unit pending. Verify true is returned.
* - Call the HAL API passing in an invalid unit number. Verify false is
* returned.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_is_intr1_pending(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_enable_disable_reset
*
* Description: Validate functionality of functions for enabling, disabling,
* and reseting units.
*
* Test Type: Feature based
*
* Targets: gm20b_mc_enable, gm20b_mc_disable, gm20b_mc_reset
*
* Input: test_setup_env must have been run.
*
* Steps:
* - Call the enable HAL API to enable units.
* - Read the MC_ENABLE reg to verify the units were enabled.
* - Call the disable HAL API to disable units.
* - Read the MC_ENABLE reg to verify the units were disabled.
* - Call the reset HAL API to reset units.
* - Read the MC_ENABLE reg to verify the units were re-enabled.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_enable_disable_reset(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_reset_mask
*
* Description: Validate functionality of HAL to get reset mask for a unit.
*
* Test Type: Feature based
*
* Targets: gm20b_mc_reset_mask
*
* Input: test_setup_env must have been run.
*
* Steps:
* - Call the enable HAL API for a number of units and verify the correct
* mask is returned.
* - For branch coverage pass in an invalid Unit number, and verify the mask
* returned is 0.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_reset_mask(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_wait_for_deferred_interrupts
*
* Description: Validate functionality of HAL to get reset mask for a unit.
*
* Test Type: Feature based
*
* Targets: nvgpu_wait_for_deferred_interrupts
*
* Input: test_setup_env must have been run.
*
* Steps:
* - Initialize cond structures required by the API.
* - Set the irq count states in the gk20a struct to 0 to cause immediate
* completion.
* - Call the API.
* - Enable cond fault injection to simulate a timeouts.
* - Set the irq count states in the gk20a struct to simulate pending stall
* interrupts.
* - Call the API.
* - Set the irq count states in the gk20a struct to simulate pending non-stall
* interrupts.
*
* Output: Returns PASS if expected result is met, FAIL otherwise.
*/
int test_wait_for_deferred_interrupts(struct unit_module *m, struct gk20a *g,
void *args);
/**
* @}
*/
#endif /* UNIT_NVGPU_CE_H */