diff --git a/userspace/units/init/nvgpu-init.c b/userspace/units/init/nvgpu-init.c index a86709815..5377f3adc 100644 --- a/userspace/units/init/nvgpu-init.c +++ b/userspace/units/init/nvgpu-init.c @@ -740,8 +740,11 @@ int test_quiesce(struct unit_module *m, struct gk20a *g, void *args) nvgpu_thread_join(&g->sw_quiesce_thread); if (!intr_masked) { - unit_err(m, "quiesce failed to mask interrupts\n"); - ret = UNIT_FAIL; + unit_return_fail(m, "quiesce failed to mask interrupts\n"); + } + + if (nvgpu_can_busy(g)) { + unit_return_fail(m, "nvgpu_can_busy() should be false\n"); } /* setup quiesce again */ @@ -767,6 +770,30 @@ int test_quiesce(struct unit_module *m, struct gk20a *g, void *args) unit_return_fail(m, "failed to re-enable quiesce\n"); } + /* setup quiesce again */ + nvgpu_sw_quiesce_remove_support(g); + set_poweron_funcs_success(g); + err = nvgpu_finalize_poweron(g); + if (err != 0) { + unit_return_fail(m, "failed to re-enable quiesce\n"); + } + + /* make sure we simulate interrupts enabled */ + intr_masked = false; + + err = EXPECT_BUG(BUG()); + if (err == 0) { + unit_return_fail(m, "BUG() was expected\n"); + } + + /* wait for quiesce thread to complete */ + nvgpu_thread_join(&g->sw_quiesce_thread); + + if (!intr_masked) { + unit_err(m, "BUG() was expected to quiesce\n"); + ret = UNIT_FAIL; + } + /* branch coverage for error states when requesting quiesce */ g->is_virtual = true; nvgpu_sw_quiesce(g); @@ -783,6 +810,19 @@ int test_quiesce(struct unit_module *m, struct gk20a *g, void *args) nvgpu_set_enabled(g, NVGPU_DISABLE_SW_QUIESCE, false); /* Note: quiesce should still be configured */ + /* coverage for quiesce already requested */ + g->sw_quiesce_pending = true; + nvgpu_sw_quiesce(g); + g->sw_quiesce_pending = false; + + /* coverage for quiesce not initialized */ + g->sw_quiesce_init_done = false; + nvgpu_sw_quiesce(g); + g->sw_quiesce_init_done = true; + if (g->sw_quiesce_pending) { + unit_return_fail(m, "unexpected quiesce pending\n"); + } + /* coverage for device powered off when quiesce requested */ nvgpu_set_power_state(g, NVGPU_STATE_POWERED_OFF); nvgpu_sw_quiesce(g); diff --git a/userspace/units/init/nvgpu-init.h b/userspace/units/init/nvgpu-init.h index 6be4be02d..c9cc2fc96 100644 --- a/userspace/units/init/nvgpu-init.h +++ b/userspace/units/init/nvgpu-init.h @@ -307,15 +307,33 @@ int test_poweroff(struct unit_module *m, struct gk20a *g, void *args); * Test Type: Feature * * Targets: nvgpu_sw_quiesce_init_support, nvgpu_sw_quiesce_remove_support, - * nvgpu_sw_quiesce_thread, nvgpu_sw_quiesce + * nvgpu_sw_quiesce_thread, nvgpu_sw_quiesce, nvgpu_sw_quiesce_bug_cb * * Input: * - test_setup_env() must be called before. * * Steps: + * - Use stub for g->ops.mc.intr_mask, g->ops.runlist.write_state and + * g->ops.fifo.preempt_runlists_for_rc. + * - Call nvgpu_sw_quiesce, wait for SW quiesce threads to complete, + * and check that interrupts have been disabled. + * - Check SW quiesce invoked from BUG(). + * - Check cases where nvgpu_sw_quiesce does not wake up threads: + * - NVGPU_DISABLE_SW_QUIESCE is set. + * - g->sw_quiesce_pending is already true. + * - g->sw_quiesce_init_done is false. + * - Check cases where nvgpu_sw_quiesce_thread skips quiescing: + * - nvgpu_thread_should_stop is true (using fault injection). + * - g->is_virtual is true. + * - g->powered_on is false. + * - Check failure cases in nvgpu_sw_quiesce_init_support: + * - sw_quiesce_cond initialization failure (using cond fault injection). + * - sw_quiesce already initialized. + * - sw_quiesce_thread creation failure (using thread fault injection). + * - sw_quiesce_wdog creation failure (using thread fault injection). * * Output: - * - UNIT_FAIL if nvgpu_finalize_poweron() ever returns the unexpected value. + * - UNIT_FAIL if SW quiesce did not behave as expected. * - UNIT_SUCCESS otherwise */ int test_quiesce(struct unit_module *m, struct gk20a *g, void *args);