#include <kunit/test.h>
#include "dc.h"
#include "amdgpu_dm_ism.h"
static struct dc_stream_state *alloc_test_stream(struct kunit *test)
{
struct dc_stream_state *stream;
stream = kunit_kzalloc(test, sizeof(*stream), GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, stream);
return stream;
}
static struct amdgpu_dm_ism *alloc_test_ism(struct kunit *test)
{
struct amdgpu_dm_ism *ism;
ism = kunit_kzalloc(test, sizeof(*ism), GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, ism);
return ism;
}
static void dm_test_ism_next_state_running_enter_idle(struct kunit *test)
{
enum amdgpu_dm_ism_state next;
bool ok;
ok = dm_ism_next_state(DM_ISM_STATE_FULL_POWER_RUNNING,
DM_ISM_EVENT_ENTER_IDLE_REQUESTED, &next);
KUNIT_EXPECT_TRUE(test, ok);
KUNIT_EXPECT_EQ(test, (int)next, (int)DM_ISM_STATE_HYSTERESIS_WAITING);
}
static void dm_test_ism_next_state_running_begin_cursor(struct kunit *test)
{
enum amdgpu_dm_ism_state next;
bool ok;
ok = dm_ism_next_state(DM_ISM_STATE_FULL_POWER_RUNNING,
DM_ISM_EVENT_BEGIN_CURSOR_UPDATE, &next);
KUNIT_EXPECT_TRUE(test, ok);
KUNIT_EXPECT_EQ(test, (int)next, (int)DM_ISM_STATE_FULL_POWER_BUSY);
}
static void dm_test_ism_next_state_running_invalid(struct kunit *test)
{
enum amdgpu_dm_ism_state next = DM_ISM_NUM_STATES;
bool ok;
ok = dm_ism_next_state(DM_ISM_STATE_FULL_POWER_RUNNING,
DM_ISM_EVENT_EXIT_IDLE_REQUESTED, &next);
KUNIT_EXPECT_FALSE(test, ok);
KUNIT_EXPECT_EQ(test, (int)next, (int)DM_ISM_NUM_STATES);
}
static void dm_test_ism_next_state_busy_enter_idle(struct kunit *test)
{
enum amdgpu_dm_ism_state next;
bool ok;
ok = dm_ism_next_state(DM_ISM_STATE_FULL_POWER_BUSY,
DM_ISM_EVENT_ENTER_IDLE_REQUESTED, &next);
KUNIT_EXPECT_TRUE(test, ok);
KUNIT_EXPECT_EQ(test, (int)next, (int)DM_ISM_STATE_HYSTERESIS_BUSY);
}
static void dm_test_ism_next_state_busy_end_cursor(struct kunit *test)
{
enum amdgpu_dm_ism_state next;
bool ok;
ok = dm_ism_next_state(DM_ISM_STATE_FULL_POWER_BUSY,
DM_ISM_EVENT_END_CURSOR_UPDATE, &next);
KUNIT_EXPECT_TRUE(test, ok);
KUNIT_EXPECT_EQ(test, (int)next, (int)DM_ISM_STATE_FULL_POWER_RUNNING);
}
static void dm_test_ism_next_state_hyst_wait_exit_idle(struct kunit *test)
{
enum amdgpu_dm_ism_state next;
bool ok;
ok = dm_ism_next_state(DM_ISM_STATE_HYSTERESIS_WAITING,
DM_ISM_EVENT_EXIT_IDLE_REQUESTED, &next);
KUNIT_EXPECT_TRUE(test, ok);
KUNIT_EXPECT_EQ(test, (int)next, (int)DM_ISM_STATE_TIMER_ABORTED);
}
static void dm_test_ism_next_state_hyst_wait_begin_cursor(struct kunit *test)
{
enum amdgpu_dm_ism_state next;
bool ok;
ok = dm_ism_next_state(DM_ISM_STATE_HYSTERESIS_WAITING,
DM_ISM_EVENT_BEGIN_CURSOR_UPDATE, &next);
KUNIT_EXPECT_TRUE(test, ok);
KUNIT_EXPECT_EQ(test, (int)next, (int)DM_ISM_STATE_HYSTERESIS_BUSY);
}
static void dm_test_ism_next_state_hyst_wait_timer(struct kunit *test)
{
enum amdgpu_dm_ism_state next;
bool ok;
ok = dm_ism_next_state(DM_ISM_STATE_HYSTERESIS_WAITING,
DM_ISM_EVENT_TIMER_ELAPSED, &next);
KUNIT_EXPECT_TRUE(test, ok);
KUNIT_EXPECT_EQ(test, (int)next, (int)DM_ISM_STATE_OPTIMIZED_IDLE);
}
static void dm_test_ism_next_state_hyst_wait_immediate(struct kunit *test)
{
enum amdgpu_dm_ism_state next;
bool ok;
ok = dm_ism_next_state(DM_ISM_STATE_HYSTERESIS_WAITING,
DM_ISM_EVENT_IMMEDIATE, &next);
KUNIT_EXPECT_TRUE(test, ok);
KUNIT_EXPECT_EQ(test, (int)next, (int)DM_ISM_STATE_OPTIMIZED_IDLE);
}
static void dm_test_ism_next_state_hyst_busy_exit_idle(struct kunit *test)
{
enum amdgpu_dm_ism_state next;
bool ok;
ok = dm_ism_next_state(DM_ISM_STATE_HYSTERESIS_BUSY,
DM_ISM_EVENT_EXIT_IDLE_REQUESTED, &next);
KUNIT_EXPECT_TRUE(test, ok);
KUNIT_EXPECT_EQ(test, (int)next, (int)DM_ISM_STATE_FULL_POWER_BUSY);
}
static void dm_test_ism_next_state_hyst_busy_end_cursor(struct kunit *test)
{
enum amdgpu_dm_ism_state next;
bool ok;
ok = dm_ism_next_state(DM_ISM_STATE_HYSTERESIS_BUSY,
DM_ISM_EVENT_END_CURSOR_UPDATE, &next);
KUNIT_EXPECT_TRUE(test, ok);
KUNIT_EXPECT_EQ(test, (int)next, (int)DM_ISM_STATE_HYSTERESIS_WAITING);
}
static void dm_test_ism_next_state_opt_idle_exit(struct kunit *test)
{
enum amdgpu_dm_ism_state next;
bool ok;
ok = dm_ism_next_state(DM_ISM_STATE_OPTIMIZED_IDLE,
DM_ISM_EVENT_EXIT_IDLE_REQUESTED, &next);
KUNIT_EXPECT_TRUE(test, ok);
KUNIT_EXPECT_EQ(test, (int)next, (int)DM_ISM_STATE_FULL_POWER_RUNNING);
}
static void dm_test_ism_next_state_opt_idle_begin_cursor(struct kunit *test)
{
enum amdgpu_dm_ism_state next;
bool ok;
ok = dm_ism_next_state(DM_ISM_STATE_OPTIMIZED_IDLE,
DM_ISM_EVENT_BEGIN_CURSOR_UPDATE, &next);
KUNIT_EXPECT_TRUE(test, ok);
KUNIT_EXPECT_EQ(test, (int)next, (int)DM_ISM_STATE_HYSTERESIS_BUSY);
}
static void dm_test_ism_next_state_opt_idle_sso_timer(struct kunit *test)
{
enum amdgpu_dm_ism_state next;
bool ok;
ok = dm_ism_next_state(DM_ISM_STATE_OPTIMIZED_IDLE,
DM_ISM_EVENT_SSO_TIMER_ELAPSED, &next);
KUNIT_EXPECT_TRUE(test, ok);
KUNIT_EXPECT_EQ(test, (int)next, (int)DM_ISM_STATE_OPTIMIZED_IDLE_SSO);
}
static void dm_test_ism_next_state_opt_idle_immediate(struct kunit *test)
{
enum amdgpu_dm_ism_state next;
bool ok;
ok = dm_ism_next_state(DM_ISM_STATE_OPTIMIZED_IDLE,
DM_ISM_EVENT_IMMEDIATE, &next);
KUNIT_EXPECT_TRUE(test, ok);
KUNIT_EXPECT_EQ(test, (int)next, (int)DM_ISM_STATE_OPTIMIZED_IDLE_SSO);
}
static void dm_test_ism_next_state_opt_idle_sso_exit(struct kunit *test)
{
enum amdgpu_dm_ism_state next;
bool ok;
ok = dm_ism_next_state(DM_ISM_STATE_OPTIMIZED_IDLE_SSO,
DM_ISM_EVENT_EXIT_IDLE_REQUESTED, &next);
KUNIT_EXPECT_TRUE(test, ok);
KUNIT_EXPECT_EQ(test, (int)next, (int)DM_ISM_STATE_FULL_POWER_RUNNING);
}
static void dm_test_ism_next_state_opt_idle_sso_cursor(struct kunit *test)
{
enum amdgpu_dm_ism_state next;
bool ok;
ok = dm_ism_next_state(DM_ISM_STATE_OPTIMIZED_IDLE_SSO,
DM_ISM_EVENT_BEGIN_CURSOR_UPDATE, &next);
KUNIT_EXPECT_TRUE(test, ok);
KUNIT_EXPECT_EQ(test, (int)next, (int)DM_ISM_STATE_HYSTERESIS_BUSY);
}
static void dm_test_ism_next_state_aborted_immediate(struct kunit *test)
{
enum amdgpu_dm_ism_state next;
bool ok;
ok = dm_ism_next_state(DM_ISM_STATE_TIMER_ABORTED,
DM_ISM_EVENT_IMMEDIATE, &next);
KUNIT_EXPECT_TRUE(test, ok);
KUNIT_EXPECT_EQ(test, (int)next, (int)DM_ISM_STATE_FULL_POWER_RUNNING);
}
static void dm_test_ism_next_state_aborted_invalid(struct kunit *test)
{
enum amdgpu_dm_ism_state next = DM_ISM_NUM_STATES;
bool ok;
ok = dm_ism_next_state(DM_ISM_STATE_TIMER_ABORTED,
DM_ISM_EVENT_ENTER_IDLE_REQUESTED, &next);
KUNIT_EXPECT_FALSE(test, ok);
KUNIT_EXPECT_EQ(test, (int)next, (int)DM_ISM_NUM_STATES);
}
static void dm_test_ism_sso_delay_null_stream(struct kunit *test)
{
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
ism->config.sso_num_frames = 5;
KUNIT_EXPECT_EQ(test, dm_ism_get_sso_delay(ism, NULL), (uint64_t)0);
}
static void dm_test_ism_sso_delay_zero_frames(struct kunit *test)
{
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
struct dc_stream_state *stream = alloc_test_stream(test);
stream->timing.v_total = 1125;
stream->timing.h_total = 2200;
stream->timing.pix_clk_100hz = 1485000;
ism->config.sso_num_frames = 0;
KUNIT_EXPECT_EQ(test, dm_ism_get_sso_delay(ism, stream), (uint64_t)0);
}
static void dm_test_ism_sso_delay_1080p60_3frames(struct kunit *test)
{
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
struct dc_stream_state *stream = alloc_test_stream(test);
uint64_t expected_one_frame_ns, expected;
stream->timing.v_total = 1125;
stream->timing.h_total = 2200;
stream->timing.pix_clk_100hz = 1485000;
ism->config.sso_num_frames = 3;
expected_one_frame_ns = div64_u64((uint64_t)1125 * 2200 * 10000000ULL,
1485000);
expected = 3 * expected_one_frame_ns;
KUNIT_EXPECT_EQ(test, dm_ism_get_sso_delay(ism, stream), expected);
}
static void dm_test_ism_sso_delay_4k60_1frame(struct kunit *test)
{
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
struct dc_stream_state *stream = alloc_test_stream(test);
uint64_t expected_one_frame_ns;
stream->timing.v_total = 2250;
stream->timing.h_total = 4400;
stream->timing.pix_clk_100hz = 5940000;
ism->config.sso_num_frames = 1;
expected_one_frame_ns = div64_u64((uint64_t)2250 * 4400 * 10000000ULL,
5940000);
KUNIT_EXPECT_EQ(test, dm_ism_get_sso_delay(ism, stream),
expected_one_frame_ns);
}
static void dm_test_ism_idle_delay_null_stream(struct kunit *test)
{
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
ism->config.filter_num_frames = 5;
ism->config.filter_entry_count = 3;
ism->config.activation_num_delay_frames = 10;
KUNIT_EXPECT_EQ(test, dm_ism_get_idle_allow_delay(ism, NULL),
(uint64_t)0);
}
static void dm_test_ism_idle_delay_zero_filter_frames(struct kunit *test)
{
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
struct dc_stream_state *stream = alloc_test_stream(test);
stream->timing.v_total = 1125;
stream->timing.h_total = 2200;
stream->timing.pix_clk_100hz = 1485000;
ism->config.filter_num_frames = 0;
KUNIT_EXPECT_EQ(test, dm_ism_get_idle_allow_delay(ism, stream),
(uint64_t)0);
}
static void dm_test_ism_idle_delay_zero_entry_count(struct kunit *test)
{
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
struct dc_stream_state *stream = alloc_test_stream(test);
stream->timing.v_total = 1125;
stream->timing.h_total = 2200;
stream->timing.pix_clk_100hz = 1485000;
ism->config.filter_num_frames = 5;
ism->config.filter_entry_count = 0;
KUNIT_EXPECT_EQ(test, dm_ism_get_idle_allow_delay(ism, stream),
(uint64_t)0);
}
static void dm_test_ism_idle_delay_zero_delay_frames(struct kunit *test)
{
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
struct dc_stream_state *stream = alloc_test_stream(test);
stream->timing.v_total = 1125;
stream->timing.h_total = 2200;
stream->timing.pix_clk_100hz = 1485000;
ism->config.filter_num_frames = 5;
ism->config.filter_entry_count = 3;
ism->config.activation_num_delay_frames = 0;
KUNIT_EXPECT_EQ(test, dm_ism_get_idle_allow_delay(ism, stream),
(uint64_t)0);
}
static void dm_test_ism_idle_delay_no_short_idles(struct kunit *test)
{
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
struct dc_stream_state *stream = alloc_test_stream(test);
uint64_t one_frame_ns;
stream->timing.v_total = 1125;
stream->timing.h_total = 2200;
stream->timing.pix_clk_100hz = 1485000;
one_frame_ns = div64_u64((uint64_t)1125 * 2200 * 10000000ULL,
1485000);
ism->config.filter_num_frames = 5;
ism->config.filter_entry_count = 3;
ism->config.activation_num_delay_frames = 10;
ism->config.filter_history_size = 8;
ism->config.filter_old_history_threshold = 0;
for (int i = 0; i < 8; i++) {
ism->records[i].duration_ns = one_frame_ns * 100;
ism->records[i].timestamp_ns = 0;
}
ism->next_record_idx = 8;
KUNIT_EXPECT_EQ(test, dm_ism_get_idle_allow_delay(ism, stream),
(uint64_t)0);
}
static void dm_test_ism_idle_delay_enough_short_idles(struct kunit *test)
{
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
struct dc_stream_state *stream = alloc_test_stream(test);
uint64_t one_frame_ns, expected;
stream->timing.v_total = 1125;
stream->timing.h_total = 2200;
stream->timing.pix_clk_100hz = 1485000;
one_frame_ns = div64_u64((uint64_t)1125 * 2200 * 10000000ULL,
1485000);
ism->config.filter_num_frames = 5;
ism->config.filter_entry_count = 3;
ism->config.activation_num_delay_frames = 10;
ism->config.filter_history_size = 8;
ism->config.filter_old_history_threshold = 0;
for (int i = 0; i < 8; i++) {
ism->records[i].duration_ns = one_frame_ns;
ism->records[i].timestamp_ns = 0;
}
ism->next_record_idx = 8;
expected = 10 * one_frame_ns;
KUNIT_EXPECT_EQ(test, dm_ism_get_idle_allow_delay(ism, stream),
expected);
}
static void dm_test_ism_idle_delay_wraps_around_buffer(struct kunit *test)
{
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
struct dc_stream_state *stream = alloc_test_stream(test);
uint64_t one_frame_ns, expected;
stream->timing.v_total = 1125;
stream->timing.h_total = 2200;
stream->timing.pix_clk_100hz = 1485000;
one_frame_ns = div64_u64((uint64_t)1125 * 2200 * 10000000ULL,
1485000);
ism->config.filter_num_frames = 5;
ism->config.filter_entry_count = 3;
ism->config.activation_num_delay_frames = 10;
ism->config.filter_history_size = 8;
ism->config.filter_old_history_threshold = 0;
for (int i = 0; i < AMDGPU_DM_IDLE_HIST_LEN; i++) {
ism->records[i].duration_ns = one_frame_ns;
ism->records[i].timestamp_ns = 0;
}
ism->next_record_idx = 2;
expected = 10 * one_frame_ns;
KUNIT_EXPECT_EQ(test, dm_ism_get_idle_allow_delay(ism, stream),
expected);
}
static void dm_test_ism_idle_delay_old_history_cutoff(struct kunit *test)
{
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
struct dc_stream_state *stream = alloc_test_stream(test);
uint64_t one_frame_ns;
stream->timing.v_total = 1125;
stream->timing.h_total = 2200;
stream->timing.pix_clk_100hz = 1485000;
one_frame_ns = div64_u64((uint64_t)1125 * 2200 * 10000000ULL,
1485000);
ism->config.filter_num_frames = 5;
ism->config.filter_entry_count = 3;
ism->config.activation_num_delay_frames = 10;
ism->config.filter_history_size = 8;
ism->config.filter_old_history_threshold = 20;
ism->last_idle_timestamp_ns = one_frame_ns * 100;
ism->records[6].duration_ns = one_frame_ns;
ism->records[6].timestamp_ns = one_frame_ns * 95;
ism->records[7].duration_ns = one_frame_ns;
ism->records[7].timestamp_ns = one_frame_ns * 98;
for (int i = 0; i < 6; i++) {
ism->records[i].duration_ns = one_frame_ns * 100;
ism->records[i].timestamp_ns = one_frame_ns * 10;
}
ism->next_record_idx = 8;
KUNIT_EXPECT_EQ(test, dm_ism_get_idle_allow_delay(ism, stream),
(uint64_t)0);
}
static void dm_test_ism_idle_delay_mixed_durations(struct kunit *test)
{
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
struct dc_stream_state *stream = alloc_test_stream(test);
uint64_t one_frame_ns;
stream->timing.v_total = 1125;
stream->timing.h_total = 2200;
stream->timing.pix_clk_100hz = 1485000;
one_frame_ns = div64_u64((uint64_t)1125 * 2200 * 10000000ULL,
1485000);
ism->config.filter_num_frames = 5;
ism->config.filter_entry_count = 3;
ism->config.activation_num_delay_frames = 10;
ism->config.filter_history_size = 8;
ism->config.filter_old_history_threshold = 0;
for (int i = 0; i < 8; i++) {
if (i == 6 || i == 7)
ism->records[i].duration_ns = one_frame_ns;
else
ism->records[i].duration_ns = one_frame_ns * 100;
ism->records[i].timestamp_ns = 0;
}
ism->next_record_idx = 8;
KUNIT_EXPECT_EQ(test, dm_ism_get_idle_allow_delay(ism, stream),
(uint64_t)0);
}
static void dm_test_ism_idle_delay_entry_count_exceeds_history_size(struct kunit *test)
{
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
struct dc_stream_state *stream = alloc_test_stream(test);
uint64_t one_frame_ns, expected;
stream->timing.v_total = 1125;
stream->timing.h_total = 2200;
stream->timing.pix_clk_100hz = 1485000;
one_frame_ns = div64_u64((uint64_t)1125 * 2200 * 10000000ULL,
1485000);
ism->config.filter_num_frames = 5;
ism->config.filter_entry_count = 5;
ism->config.filter_history_size = 3;
ism->config.activation_num_delay_frames = 10;
ism->config.filter_old_history_threshold = 0;
for (int i = 0; i < 5; i++) {
ism->records[i].duration_ns = one_frame_ns;
ism->records[i].timestamp_ns = 0;
}
ism->next_record_idx = 5;
expected = 10 * one_frame_ns;
KUNIT_EXPECT_EQ(test, dm_ism_get_idle_allow_delay(ism, stream), expected);
}
static void dm_test_ism_init_sets_initial_state(struct kunit *test)
{
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
struct amdgpu_dm_ism_config config = {
.filter_num_frames = 5,
.filter_entry_count = 3,
.activation_num_delay_frames = 10,
.filter_history_size = 8,
.filter_old_history_threshold = 20,
.sso_num_frames = 2,
};
amdgpu_dm_ism_init(ism, &config);
KUNIT_EXPECT_EQ(test, (int)ism->current_state,
(int)DM_ISM_STATE_FULL_POWER_RUNNING);
KUNIT_EXPECT_EQ(test, (int)ism->previous_state,
(int)DM_ISM_STATE_FULL_POWER_RUNNING);
KUNIT_EXPECT_EQ(test, ism->next_record_idx, 0);
KUNIT_EXPECT_EQ(test, ism->last_idle_timestamp_ns, (uint64_t)0);
KUNIT_EXPECT_EQ(test, ism->config.filter_num_frames,
config.filter_num_frames);
KUNIT_EXPECT_EQ(test, ism->config.filter_entry_count,
config.filter_entry_count);
KUNIT_EXPECT_EQ(test, ism->config.activation_num_delay_frames,
config.activation_num_delay_frames);
KUNIT_EXPECT_EQ(test, ism->config.sso_num_frames, config.sso_num_frames);
}
static void dm_test_ism_fini_after_init(struct kunit *test)
{
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
struct amdgpu_dm_ism_config config = {
.filter_num_frames = 5,
.filter_entry_count = 3,
.activation_num_delay_frames = 10,
.sso_num_frames = 2,
};
amdgpu_dm_ism_init(ism, &config);
amdgpu_dm_ism_fini(ism);
KUNIT_EXPECT_EQ(test, (int)ism->current_state,
(int)DM_ISM_STATE_FULL_POWER_RUNNING);
}
static void dm_test_ism_set_last_idle_ts_updates_timestamp(struct kunit *test)
{
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
uint64_t before;
ism->last_idle_timestamp_ns = 0;
before = ktime_get_ns();
dm_ism_set_last_idle_ts(ism);
KUNIT_EXPECT_GE(test, ism->last_idle_timestamp_ns, before);
}
static void dm_test_ism_insert_record_basic(struct kunit *test)
{
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
ism->last_idle_timestamp_ns = 0;
ism->next_record_idx = 0;
dm_ism_insert_record(ism);
KUNIT_EXPECT_EQ(test, ism->next_record_idx, 1);
KUNIT_EXPECT_GT(test, ism->records[0].timestamp_ns, (uint64_t)0);
KUNIT_EXPECT_EQ(test, ism->records[0].duration_ns,
ism->records[0].timestamp_ns);
}
static void dm_test_ism_insert_record_wraps_around(struct kunit *test)
{
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
ism->last_idle_timestamp_ns = 0;
ism->next_record_idx = AMDGPU_DM_IDLE_HIST_LEN;
dm_ism_insert_record(ism);
KUNIT_EXPECT_EQ(test, ism->next_record_idx, 1);
KUNIT_EXPECT_GT(test, ism->records[0].timestamp_ns, (uint64_t)0);
}
static void dm_test_ism_trigger_event_valid_transition(struct kunit *test)
{
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
bool ok;
ism->current_state = DM_ISM_STATE_FULL_POWER_RUNNING;
ism->previous_state = DM_ISM_STATE_FULL_POWER_RUNNING;
ok = dm_ism_trigger_event(ism, DM_ISM_EVENT_ENTER_IDLE_REQUESTED);
KUNIT_EXPECT_TRUE(test, ok);
KUNIT_EXPECT_EQ(test, (int)ism->current_state,
(int)DM_ISM_STATE_HYSTERESIS_WAITING);
KUNIT_EXPECT_EQ(test, (int)ism->previous_state,
(int)DM_ISM_STATE_FULL_POWER_RUNNING);
}
static void dm_test_ism_trigger_event_invalid_transition(struct kunit *test)
{
struct amdgpu_dm_ism *ism = alloc_test_ism(test);
bool ok;
ism->current_state = DM_ISM_STATE_FULL_POWER_RUNNING;
ism->previous_state = DM_ISM_STATE_FULL_POWER_RUNNING;
ok = dm_ism_trigger_event(ism, DM_ISM_EVENT_EXIT_IDLE_REQUESTED);
KUNIT_EXPECT_FALSE(test, ok);
KUNIT_EXPECT_EQ(test, (int)ism->current_state,
(int)DM_ISM_STATE_FULL_POWER_RUNNING);
KUNIT_EXPECT_EQ(test, (int)ism->previous_state,
(int)DM_ISM_STATE_FULL_POWER_RUNNING);
}
static void dm_test_dispatch_next_event_hyst_wait_no_delay(struct kunit *test)
{
enum amdgpu_dm_ism_event result;
result = dm_ism_dispatch_next_event(DM_ISM_STATE_HYSTERESIS_WAITING,
0, 0);
KUNIT_EXPECT_EQ(test, (int)result, (int)DM_ISM_EVENT_IMMEDIATE);
}
static void dm_test_dispatch_next_event_hyst_wait_with_delay(struct kunit *test)
{
enum amdgpu_dm_ism_event result;
result = dm_ism_dispatch_next_event(DM_ISM_STATE_HYSTERESIS_WAITING,
1000000, 0);
KUNIT_EXPECT_EQ(test, (int)result, (int)DM_ISM_NUM_EVENTS);
}
static void dm_test_dispatch_next_event_opt_idle_no_sso_delay(struct kunit *test)
{
enum amdgpu_dm_ism_event result;
result = dm_ism_dispatch_next_event(DM_ISM_STATE_OPTIMIZED_IDLE,
0, 0);
KUNIT_EXPECT_EQ(test, (int)result, (int)DM_ISM_EVENT_IMMEDIATE);
}
static void dm_test_dispatch_next_event_opt_idle_with_sso_delay(struct kunit *test)
{
enum amdgpu_dm_ism_event result;
result = dm_ism_dispatch_next_event(DM_ISM_STATE_OPTIMIZED_IDLE,
0, 1000000);
KUNIT_EXPECT_EQ(test, (int)result, (int)DM_ISM_NUM_EVENTS);
}
static void dm_test_dispatch_next_event_timer_aborted(struct kunit *test)
{
enum amdgpu_dm_ism_event result;
result = dm_ism_dispatch_next_event(DM_ISM_STATE_TIMER_ABORTED,
0, 0);
KUNIT_EXPECT_EQ(test, (int)result, (int)DM_ISM_EVENT_IMMEDIATE);
}
static void dm_test_dispatch_next_event_no_action_state(struct kunit *test)
{
enum amdgpu_dm_ism_event result;
result = dm_ism_dispatch_next_event(DM_ISM_STATE_FULL_POWER_RUNNING,
0, 0);
KUNIT_EXPECT_EQ(test, (int)result, (int)DM_ISM_NUM_EVENTS);
}
static struct kunit_case dm_ism_test_cases[] = {
KUNIT_CASE(dm_test_ism_next_state_running_enter_idle),
KUNIT_CASE(dm_test_ism_next_state_running_begin_cursor),
KUNIT_CASE(dm_test_ism_next_state_running_invalid),
KUNIT_CASE(dm_test_ism_next_state_busy_enter_idle),
KUNIT_CASE(dm_test_ism_next_state_busy_end_cursor),
KUNIT_CASE(dm_test_ism_next_state_hyst_wait_exit_idle),
KUNIT_CASE(dm_test_ism_next_state_hyst_wait_begin_cursor),
KUNIT_CASE(dm_test_ism_next_state_hyst_wait_timer),
KUNIT_CASE(dm_test_ism_next_state_hyst_wait_immediate),
KUNIT_CASE(dm_test_ism_next_state_hyst_busy_exit_idle),
KUNIT_CASE(dm_test_ism_next_state_hyst_busy_end_cursor),
KUNIT_CASE(dm_test_ism_next_state_opt_idle_exit),
KUNIT_CASE(dm_test_ism_next_state_opt_idle_begin_cursor),
KUNIT_CASE(dm_test_ism_next_state_opt_idle_sso_timer),
KUNIT_CASE(dm_test_ism_next_state_opt_idle_immediate),
KUNIT_CASE(dm_test_ism_next_state_opt_idle_sso_exit),
KUNIT_CASE(dm_test_ism_next_state_opt_idle_sso_cursor),
KUNIT_CASE(dm_test_ism_next_state_aborted_immediate),
KUNIT_CASE(dm_test_ism_next_state_aborted_invalid),
KUNIT_CASE(dm_test_ism_sso_delay_null_stream),
KUNIT_CASE(dm_test_ism_sso_delay_zero_frames),
KUNIT_CASE(dm_test_ism_sso_delay_1080p60_3frames),
KUNIT_CASE(dm_test_ism_sso_delay_4k60_1frame),
KUNIT_CASE(dm_test_ism_idle_delay_null_stream),
KUNIT_CASE(dm_test_ism_idle_delay_zero_filter_frames),
KUNIT_CASE(dm_test_ism_idle_delay_zero_entry_count),
KUNIT_CASE(dm_test_ism_idle_delay_zero_delay_frames),
KUNIT_CASE(dm_test_ism_idle_delay_no_short_idles),
KUNIT_CASE(dm_test_ism_idle_delay_enough_short_idles),
KUNIT_CASE(dm_test_ism_idle_delay_wraps_around_buffer),
KUNIT_CASE(dm_test_ism_idle_delay_old_history_cutoff),
KUNIT_CASE(dm_test_ism_idle_delay_mixed_durations),
KUNIT_CASE(dm_test_ism_idle_delay_entry_count_exceeds_history_size),
KUNIT_CASE(dm_test_ism_init_sets_initial_state),
KUNIT_CASE(dm_test_ism_fini_after_init),
KUNIT_CASE(dm_test_ism_set_last_idle_ts_updates_timestamp),
KUNIT_CASE(dm_test_ism_insert_record_basic),
KUNIT_CASE(dm_test_ism_insert_record_wraps_around),
KUNIT_CASE(dm_test_ism_trigger_event_valid_transition),
KUNIT_CASE(dm_test_ism_trigger_event_invalid_transition),
KUNIT_CASE(dm_test_dispatch_next_event_hyst_wait_no_delay),
KUNIT_CASE(dm_test_dispatch_next_event_hyst_wait_with_delay),
KUNIT_CASE(dm_test_dispatch_next_event_opt_idle_no_sso_delay),
KUNIT_CASE(dm_test_dispatch_next_event_opt_idle_with_sso_delay),
KUNIT_CASE(dm_test_dispatch_next_event_timer_aborted),
KUNIT_CASE(dm_test_dispatch_next_event_no_action_state),
{}
};
static struct kunit_suite dm_ism_test_suite = {
.name = "amdgpu_dm_ism",
.test_cases = dm_ism_test_cases,
};
kunit_test_suite(dm_ism_test_suite);
MODULE_LICENSE("Dual MIT/GPL");
MODULE_DESCRIPTION("KUnit tests for amdgpu_dm_ism");
MODULE_AUTHOR("AMD");