mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-22 09:12:24 +03:00
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:
committed by
Alex Waterman
parent
b5617a61d9
commit
5f0d1f39c2
@@ -54,6 +54,7 @@ NV_REPOSITORY_COMPONENTS += userspace/units/interface/rbtree
|
||||
NV_REPOSITORY_COMPONENTS += userspace/units/pramin
|
||||
NV_REPOSITORY_COMPONENTS += userspace/units/priv_ring
|
||||
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_mem
|
||||
NV_REPOSITORY_COMPONENTS += userspace/units/mm/allocators/buddy_allocator
|
||||
|
||||
@@ -436,6 +436,13 @@ nvgpu_kmem_get_fault_injection
|
||||
nvgpu_kzalloc_impl
|
||||
nvgpu_vmalloc_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_mem_create_from_phys
|
||||
nvgpu_mem_iommu_translate
|
||||
@@ -613,6 +620,7 @@ nvgpu_vm_put
|
||||
nvgpu_vm_put_buffers
|
||||
nvgpu_vm_unmap
|
||||
nvgpu_vzalloc_impl
|
||||
nvgpu_wait_for_deferred_interrupts
|
||||
nvgpu_writel
|
||||
nvgpu_writel_check
|
||||
nvgpu_clear_bit
|
||||
|
||||
@@ -62,6 +62,7 @@ UNITS := \
|
||||
$(UNIT_SRC)/interface/lock \
|
||||
$(UNIT_SRC)/interface/atomic \
|
||||
$(UNIT_SRC)/interface/rbtree \
|
||||
$(UNIT_SRC)/mc \
|
||||
$(UNIT_SRC)/mm/nvgpu_sgt \
|
||||
$(UNIT_SRC)/mm/allocators/buddy_allocator \
|
||||
$(UNIT_SRC)/mm/allocators/nvgpu_allocator \
|
||||
|
||||
@@ -1055,6 +1055,78 @@
|
||||
"unit": "list",
|
||||
"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",
|
||||
"case": "as_alloc_share_0k_um",
|
||||
|
||||
26
userspace/units/mc/Makefile
Normal file
26
userspace/units/mc/Makefile
Normal 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
|
||||
23
userspace/units/mc/Makefile.interface.tmk
Normal file
23
userspace/units/mc/Makefile.interface.tmk
Normal 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:
|
||||
24
userspace/units/mc/Makefile.tmk
Normal file
24
userspace/units/mc/Makefile.tmk
Normal 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:
|
||||
805
userspace/units/mc/nvgpu-mc.c
Normal file
805
userspace/units/mc/nvgpu-mc.c
Normal 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);
|
||||
358
userspace/units/mc/nvgpu-mc.h
Normal file
358
userspace/units/mc/nvgpu-mc.h
Normal 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 */
|
||||
Reference in New Issue
Block a user