gpu: nvgpu: unit: init: add quiesce testing

Add testing of quiesce functionality to init unit test.

JIRA NVGPU-3981

Change-Id: Idc64179bc8d532bea385e705d96fb4b376d15cd9
Signed-off-by: Philip Elcan <pelcan@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/2247154
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Philip Elcan
2019-11-11 14:32:12 -05:00
committed by Alex Waterman
parent 234a82fc9a
commit b8c25a5a55
6 changed files with 149 additions and 0 deletions

View File

@@ -171,6 +171,7 @@ void nvgpu_sw_quiesce(struct gk20a *g)
g->sw_quiesce_pending = true; g->sw_quiesce_pending = true;
nvgpu_cond_signal(&g->sw_quiesce_cond); nvgpu_cond_signal(&g->sw_quiesce_cond);
return; return;
fail: fail:

View File

@@ -465,7 +465,9 @@ nvgpu_sw_quiesce
nvgpu_sw_quiesce_remove_support nvgpu_sw_quiesce_remove_support
nvgpu_thread_create nvgpu_thread_create
nvgpu_thread_create_priority nvgpu_thread_create_priority
nvgpu_thread_get_fault_injection
nvgpu_thread_is_running nvgpu_thread_is_running
nvgpu_thread_join
nvgpu_thread_should_stop nvgpu_thread_should_stop
nvgpu_thread_stop nvgpu_thread_stop
nvgpu_thread_stop_graceful nvgpu_thread_stop_graceful

View File

@@ -66,11 +66,13 @@ void nvgpu_start_gpu_idle(struct gk20a *g)
int nvgpu_enable_irqs(struct gk20a *g) int nvgpu_enable_irqs(struct gk20a *g)
{ {
g->mc.irqs_enabled = true;
return 0; return 0;
} }
void nvgpu_disable_irqs(struct gk20a *g) void nvgpu_disable_irqs(struct gk20a *g)
{ {
g->mc.irqs_enabled = false;
} }
void nvgpu_set_power_state(struct gk20a *g, u32 state) void nvgpu_set_power_state(struct gk20a *g, u32 state)

View File

@@ -767,6 +767,12 @@
"unit": "init", "unit": "init",
"test_level": 0 "test_level": 0
}, },
{
"test": "test_quiesce",
"case": "init_quiesce",
"unit": "init",
"test_level": 0
},
{ {
"test": "test_setup_env", "test": "test_setup_env",
"case": "init_setup_env", "case": "init_setup_env",

View File

@@ -689,6 +689,122 @@ int test_poweroff(struct unit_module *m, struct gk20a *g, void *args)
return UNIT_SUCCESS; return UNIT_SUCCESS;
} }
static bool intr_masked;
static void mock_intr_mask(struct gk20a *g)
{
intr_masked = true;
}
static void mock_runlist_write_state(struct gk20a *g, u32 runlist_mask,
u32 runlist_state)
{
}
static void mock_fifo_preempt_runlists_for_rc(struct gk20a *g, u32 runlist_mask)
{
}
int test_quiesce(struct unit_module *m, struct gk20a *g, void *args)
{
int ret = UNIT_SUCCESS;
struct nvgpu_posix_fault_inj *thread_fi =
nvgpu_thread_get_fault_injection();
int err;
unsigned long *save_enabled_ptr;
/* assume quiesce has been initalized already */
/* make sure we're powered on */
nvgpu_set_power_state(g, NVGPU_STATE_POWERED_ON);
/* make sure we simulate interrupts enabled */
g->mc.irqs_enabled = true;
intr_masked = false;
/* setup HAL for masking interrupts */
g->ops.mc.intr_mask = mock_intr_mask;
/*
* quiesce will request fifo to quiesce, so make sure we don't have
* anything to do.
*/
g->fifo.num_runlists = 0;
g->fifo.num_channels = 0;
/* mock out fifo HALs called during quiesce */
g->ops.runlist.write_state = mock_runlist_write_state;
g->ops.fifo.preempt_runlists_for_rc = mock_fifo_preempt_runlists_for_rc;
nvgpu_sw_quiesce(g);
/* wait for quiesce thread to complete */
nvgpu_thread_join(&g->sw_quiesce_thread);
if (g->mc.irqs_enabled || !intr_masked) {
unit_err(m, "quiesce failed to disable interrupts\n");
ret = UNIT_FAIL;
}
/* 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");
}
/* coverage for thread_should_stop() being set using fault inj */
nvgpu_posix_enable_fault_injection(thread_fi, true, 0);
nvgpu_sw_quiesce(g);
/* wait for quiesce thread to complete */
nvgpu_thread_join(&g->sw_quiesce_thread);
nvgpu_posix_enable_fault_injection(thread_fi, false, 0);
/* 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");
}
/* branch coverage for error states when requesting quiesce */
g->is_virtual = true;
nvgpu_sw_quiesce(g);
/* don't wait for quiesce thread to complete since this is error */
g->is_virtual = false;
save_enabled_ptr = g->enabled_flags;
g->enabled_flags = NULL;
nvgpu_sw_quiesce(g);
/* don't wait for quiesce thread to complete since this is error */
g->enabled_flags = save_enabled_ptr;
nvgpu_set_enabled(g, NVGPU_DISABLE_SW_QUIESCE, true);
nvgpu_sw_quiesce(g);
/* don't wait for quiesce thread to complete since this is error */
nvgpu_set_enabled(g, NVGPU_DISABLE_SW_QUIESCE, false);
/* Note: quiesce should still be configured */
/* coverage for device powered off when quiesce requested */
nvgpu_set_power_state(g, NVGPU_STATE_POWERED_OFF);
nvgpu_sw_quiesce(g);
/* wait for quiesce thread to complete */
nvgpu_thread_join(&g->sw_quiesce_thread);
nvgpu_set_power_state(g, NVGPU_STATE_POWERED_ON);
/* coverage for thread creation failing when creating thread */
nvgpu_sw_quiesce_remove_support(g);
set_poweron_funcs_success(g);
nvgpu_posix_enable_fault_injection(thread_fi, true, 0);
err = nvgpu_finalize_poweron(g);
if (err == 0) {
unit_return_fail(m, "failed to detect thread creation error\n");
}
nvgpu_posix_enable_fault_injection(thread_fi, false, 0);
return ret;
}
struct unit_module_test init_tests[] = { struct unit_module_test init_tests[] = {
UNIT_TEST(init_setup_env, test_setup_env, NULL, 0), UNIT_TEST(init_setup_env, test_setup_env, NULL, 0),
UNIT_TEST(get_litter_value, test_get_litter_value, NULL, 0), UNIT_TEST(get_litter_value, test_get_litter_value, NULL, 0),
@@ -699,6 +815,7 @@ struct unit_module_test init_tests[] = {
UNIT_TEST(init_poweron, test_poweron, NULL, 0), UNIT_TEST(init_poweron, test_poweron, NULL, 0),
UNIT_TEST(init_poweron_branches, test_poweron_branches, NULL, 0), UNIT_TEST(init_poweron_branches, test_poweron_branches, NULL, 0),
UNIT_TEST(init_poweroff, test_poweroff, NULL, 0), UNIT_TEST(init_poweroff, test_poweroff, NULL, 0),
UNIT_TEST(init_quiesce, test_quiesce, NULL, 0),
UNIT_TEST(init_free_env, test_free_env, NULL, 0), UNIT_TEST(init_free_env, test_free_env, NULL, 0),
}; };

View File

@@ -298,4 +298,25 @@ int test_poweron_branches(struct unit_module *m, struct gk20a *g, void *args);
*/ */
int test_poweroff(struct unit_module *m, struct gk20a *g, void *args); int test_poweroff(struct unit_module *m, struct gk20a *g, void *args);
/**
* Test specification for: test_quiesce
*
* Description: Test putting device in quiesce
*
* Test Type: Feature based
*
* Targets: nvgpu_sw_quiesce_init_support, nvgpu_sw_quiesce_remove_support,
* nvgpu_sw_quiesce_thread, nvgpu_sw_quiesce
*
* Input:
* - test_setup_env() must be called before.
*
* Steps:
*
* Output:
* - UNIT_FAIL if nvgpu_finalize_poweron() ever returns the unexpected value.
* - UNIT_SUCCESS otherwise
*/
int test_quiesce(struct unit_module *m, struct gk20a *g, void *args);
#endif /* UNIT_NVGPU_INIT_H */ #endif /* UNIT_NVGPU_INIT_H */