/* * Copyright (c) 2019-2021, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "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_CIC_INTR_STALLING) #define STALL_DIS_REG mc_intr_en_clear_r(NVGPU_CIC_INTR_STALLING) #define NONSTALL_EN_REG mc_intr_en_set_r(NVGPU_CIC_INTR_NONSTALLING) #define NONSTALL_DIS_REG mc_intr_en_clear_r(NVGPU_CIC_INTR_NONSTALLING) #define STALL_PENDING_REG mc_intr_r(NVGPU_CIC_INTR_STALLING) #define NONSTALL_PENDING_REG mc_intr_r(NVGPU_CIC_INTR_NONSTALLING) struct mc_unit { u32 num; u32 bit; }; static struct mc_unit mc_units[] = { { NVGPU_CIC_INTR_UNIT_BUS, mc_intr_pbus_pending_f() }, { NVGPU_CIC_INTR_UNIT_PMU, mc_intr_pmu_pending_f() }, { NVGPU_CIC_INTR_UNIT_PRIV_RING, mc_intr_priv_ring_pending_f() }, { NVGPU_CIC_INTR_UNIT_FIFO, mc_intr_pfifo_pending_f() }, { NVGPU_CIC_INTR_UNIT_LTC, mc_intr_ltc_pending_f() }, { NVGPU_CIC_INTR_UNIT_HUB, mc_intr_replayable_fault_pending_f() }, { NVGPU_CIC_INTR_UNIT_GR, (1 << ACTIVE_GR_ID) /* nvgpu_gr_engine_interrupt_mask() */}, { NVGPU_CIC_INTR_UNIT_PMU, mc_intr_pmu_pending_f() }, { NVGPU_CIC_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 pmu_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.pmu_isr = false; u.priv_ring_isr = false; } 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, u32 intr_unit_bitmask) { 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_pmu_isr(struct gk20a *g) { u.pmu_isr = true; } static void mock_priv_ring_isr(struct gk20a *g) { u.priv_ring_isr = true; } int test_mc_setup_env(struct unit_module *m, struct gk20a *g, void *args) { /* Create mc register space */ 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.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.pmu.pmu_isr = mock_pmu_isr; g->ops.priv_ring.isr = mock_priv_ring_isr; nvgpu_device_init(g); /* 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_mc_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_cic_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_cic_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_cic_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_cic_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_cic_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_cic_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_cic_intr_stall_unit_config(g, NVGPU_CIC_INTR_UNIT_PRIV_RING, true); nvgpu_cic_intr_nonstall_unit_config(g, NVGPU_CIC_INTR_UNIT_BUS, true); /* pause stall */ nvgpu_cic_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_cic_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_cic_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_cic_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_cic_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_cic_intr_mask(g); g->ops.mc.intr_mask = save_func; return UNIT_SUCCESS; } 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 == NVGPU_CIC_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.pmu_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) { unit_return_fail(m, "BUS ISR called from Stall\n"); } if (!u.ce_isr || !u.fb_isr || !u.fifo_isr || !u.gr_isr || !u.pmu_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 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 { u32 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.bus_isr || !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; return UNIT_SUCCESS; } int test_enable_disable_reset(struct unit_module *m, struct gk20a *g, void *args) { u32 units = (mc_enable_pfifo_enabled_f() | mc_enable_pgraph_enabled_f() | mc_enable_blg_enabled_f() | mc_enable_ce2_enabled_f()); u32 val; /* test enable */ nvgpu_posix_io_writel_reg_space(g, mc_enable_r(), 0); g->ops.mc.enable_units(g, (NVGPU_UNIT_FIFO | NVGPU_UNIT_GRAPH | NVGPU_UNIT_BLG | NVGPU_UNIT_CE2), true); 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.enable_units(g, (NVGPU_UNIT_FIFO | NVGPU_UNIT_GRAPH | NVGPU_UNIT_BLG | NVGPU_UNIT_CE2), false); 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); nvgpu_mc_reset_units(g, (NVGPU_UNIT_FIFO | NVGPU_UNIT_GRAPH | NVGPU_UNIT_BLG | NVGPU_UNIT_CE2)); 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_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.sw_irq_stall_pending, 0); nvgpu_atomic_set(&g->mc.sw_irq_nonstall_pending, 0); nvgpu_cic_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.sw_irq_stall_pending, 1); nvgpu_cic_wait_for_deferred_interrupts(g); /* wait on nonstall until timeout for branch coverage */ nvgpu_atomic_set(&g->mc.sw_irq_nonstall_pending, 1); nvgpu_cic_wait_for_deferred_interrupts(g); /* disable the fault injection */ nvgpu_posix_enable_fault_injection(cond_fi, false, 0); return UNIT_SUCCESS; } struct unit_module_test mc_tests[] = { UNIT_TEST(mc_setup_env, test_mc_setup_env, NULL, 0), UNIT_TEST(unit_config, test_unit_config, NULL, 2), 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, 2), UNIT_TEST(isr_stall, test_isr_stall, NULL, 2), UNIT_TEST(isr_nonstall, test_isr_nonstall, NULL, 2), UNIT_TEST(is_intr1_pending, test_is_intr1_pending, NULL, 0), UNIT_TEST(enable_disable_reset, test_enable_disable_reset, NULL, 0), UNIT_TEST(wait_for_deferred_interrupts, test_wait_for_deferred_interrupts, NULL, 0), UNIT_TEST(mc_free_env, test_mc_free_env, NULL, 0), }; UNIT_MODULE(mc, mc_tests, UNIT_PRIO_NVGPU_TEST);