diff --git a/libs/dgpu/libnvgpu-drv-dgpu_safe.export b/libs/dgpu/libnvgpu-drv-dgpu_safe.export index 71b052a84..7dbb7b7ea 100644 --- a/libs/dgpu/libnvgpu-drv-dgpu_safe.export +++ b/libs/dgpu/libnvgpu-drv-dgpu_safe.export @@ -672,7 +672,7 @@ nvgpu_runlist_set_state nvgpu_runlist_setup_sw nvgpu_runlist_unlock_active_runlists nvgpu_runlist_unlock_runlists -nvgpu_runlist_update_for_channel +nvgpu_runlist_update nvgpu_runlist_update_locked nvgpu_rwsem_init nvgpu_rwsem_down_read diff --git a/libs/igpu/libnvgpu-drv-igpu_safe.export b/libs/igpu/libnvgpu-drv-igpu_safe.export index d025e3203..d81fa9d44 100644 --- a/libs/igpu/libnvgpu-drv-igpu_safe.export +++ b/libs/igpu/libnvgpu-drv-igpu_safe.export @@ -687,7 +687,7 @@ nvgpu_runlist_set_state nvgpu_runlist_setup_sw nvgpu_runlist_unlock_active_runlists nvgpu_runlist_unlock_runlists -nvgpu_runlist_update_for_channel +nvgpu_runlist_update nvgpu_runlist_update_locked nvgpu_rwsem_init nvgpu_rwsem_down_read diff --git a/userspace/required_tests.ini b/userspace/required_tests.ini index 2ff7f6db8..97afdd9e5 100644 --- a/userspace/required_tests.ini +++ b/userspace/required_tests.ini @@ -730,7 +730,7 @@ test_preempt_poll_tsg_on_pbdma.preempt_poll=0 [nvgpu_preempt_gv11b] test_fifo_init_support.init_support=0 test_fifo_remove_support.remove_support=0 -test_gv11b_fifo_is_preempt_pending.is_preempt_pending=0 +test_gv11b_fifo_is_preempt_pending.is_preempt_pending=2 test_gv11b_fifo_preempt_channel.preempt_channel=0 test_gv11b_fifo_preempt_runlists_for_rc.preempt_runlists_for_rc=0 test_gv11b_fifo_preempt_trigger.preempt_trigger=0 @@ -743,23 +743,6 @@ test_gp10b_ramfc_commit_userd.commit_userd=0 test_gv11b_ramfc_capture_ram_dump.capture_ram_dump=0 test_gv11b_ramfc_setup.ramfc_setup=0 -[nvgpu_runlist] -test_fifo_init_support.init_support=0 -test_fifo_remove_support.remove_support=0 -test_flat_gen.flat=0 -test_interleave_dual.interleave_dual=0 -test_interleave_single.interleave_single=0 -test_interleaving_levels.interleave_level=0 -test_runlist_get_mask.get_mask=0 -test_runlist_interleave_level_name.interleave_level_name=0 -test_runlist_lock_unlock_active_runlists.lock_unlock_active_runlists=0 -test_runlist_reload_ids.reload_ids=0 -test_runlist_set_state.set_state=0 -test_runlist_setup_sw.setup_sw=0 -test_runlist_update_for_channel.update_for_channel=0 -test_runlist_update_locked.runlist_update=0 -test_tsg_format_gen.tsg_format_flat=0 - [nvgpu_runlist_gk20a] test_fifo_init_support.init_support=0 test_fifo_remove_support.remove_support=0 @@ -786,7 +769,7 @@ test_nvgpu_sgt_get_next.sgt_get_next=0 test_fifo_init_support.init_support=0 test_fifo_remove_support.remove_support=0 test_tsg_abort.abort=0 -test_tsg_bind_channel.bind_channel=0 +test_tsg_bind_channel.bind_channel=2 test_tsg_check_and_get_from_id.get_from_id=0 test_tsg_enable.enable_disable=0 test_tsg_enable_sched.enable_disable_sched=0 diff --git a/userspace/units/fifo/channel/nvgpu-channel.c b/userspace/units/fifo/channel/nvgpu-channel.c index db2377ff7..e8e5eeb2f 100644 --- a/userspace/units/fifo/channel/nvgpu-channel.c +++ b/userspace/units/fifo/channel/nvgpu-channel.c @@ -677,16 +677,17 @@ static int stub_os_channel_alloc_usermode_buffers_ENOMEM( return -ENOMEM; } -static int stub_runlist_update_for_channel(struct gk20a *g, u32 runlist_id, +static int stub_runlist_update(struct gk20a *g, struct nvgpu_runlist *rl, struct nvgpu_channel *ch, bool add, bool wait_for_finish) { stub[1].chid = ch->chid; return 0; } -static int stub_runlist_update_for_channel_ETIMEDOUT(struct gk20a *g, - u32 runlist_id, struct nvgpu_channel *ch, bool add, - bool wait_for_finish) +static int stub_runlist_update_ETIMEDOUT(struct gk20a *g, + struct nvgpu_runlist *rl, + struct nvgpu_channel *ch, bool add, + bool wait_for_finish) { return -ETIMEDOUT; } @@ -835,10 +836,10 @@ int test_channel_setup_bind(struct unit_module *m, struct gk20a *g, void *vargs) F_CHANNEL_SETUP_BIND_USERMODE_TSGID_INVALID ? NVGPU_INVALID_TSG_ID : tsgid_orig; - g->ops.runlist.update_for_channel = branches & + g->ops.runlist.update = branches & F_CHANNEL_SETUP_BIND_USERMODE_UPDATE_RL_FAIL ? - stub_runlist_update_for_channel_ETIMEDOUT : - stub_runlist_update_for_channel; + stub_runlist_update_ETIMEDOUT : + stub_runlist_update; g->ops.ramfc.setup = branches & F_CHANNEL_SETUP_BIND_USERMODE_SETUP_RAMFC_FAIL ? @@ -1338,7 +1339,7 @@ int test_channel_deterministic_idle_unidle(struct unit_module *m, g->ops.mm.cache.l2_flush = stub_mm_l2_flush; /* bug 2621189 */ g->os_channel.alloc_usermode_buffers = stub_os_channel_alloc_usermode_buffers; - g->ops.runlist.update_for_channel = stub_runlist_update_for_channel; + g->ops.runlist.update = stub_runlist_update; (void)memset(&bind_args, 0, sizeof(bind_args)); bind_args.num_gpfifo_entries = 32; @@ -1701,7 +1702,7 @@ int test_channel_semaphore_wakeup(struct unit_module *m, g->ops.mm.cache.l2_flush = stub_mm_l2_flush; /* bug 2621189 */ g->os_channel.alloc_usermode_buffers = stub_os_channel_alloc_usermode_buffers; - g->ops.runlist.update_for_channel = stub_runlist_update_for_channel; + g->ops.runlist.update = stub_runlist_update; g->ops.mm.cache.fb_flush = stub_mm_fb_flush; memset(&bind_args, 0, sizeof(bind_args)); diff --git a/userspace/units/fifo/preempt/gv11b/nvgpu-preempt-gv11b.c b/userspace/units/fifo/preempt/gv11b/nvgpu-preempt-gv11b.c index cbd40cc88..9fd6257c0 100644 --- a/userspace/units/fifo/preempt/gv11b/nvgpu-preempt-gv11b.c +++ b/userspace/units/fifo/preempt/gv11b/nvgpu-preempt-gv11b.c @@ -527,7 +527,7 @@ struct unit_module_test nvgpu_preempt_gv11b_tests[] = { UNIT_TEST(preempt_runlists_for_rc, test_gv11b_fifo_preempt_runlists_for_rc, NULL, 0), UNIT_TEST(preempt_channel, test_gv11b_fifo_preempt_channel, NULL, 0), UNIT_TEST(preempt_tsg, test_gv11b_fifo_preempt_tsg, NULL, 0), - UNIT_TEST(is_preempt_pending, test_gv11b_fifo_is_preempt_pending, NULL, 0), + UNIT_TEST(is_preempt_pending, test_gv11b_fifo_is_preempt_pending, NULL, 2), UNIT_TEST(remove_support, test_fifo_remove_support, &unit_ctx, 0), }; diff --git a/userspace/units/fifo/runlist/nvgpu-runlist.c b/userspace/units/fifo/runlist/nvgpu-runlist.c index bf643aba4..850b075f5 100644 --- a/userspace/units/fifo/runlist/nvgpu-runlist.c +++ b/userspace/units/fifo/runlist/nvgpu-runlist.c @@ -20,1373 +20,13 @@ * DEALINGS IN THE SOFTWARE. */ -#include -#include -#include - -#include #include -#include -#include -#include -#include -#include -#include - -#include "hal/fifo/runlist_ram_gk20a.h" -#include "hal/fifo/tsg_gk20a.h" -#include "nvgpu/hw/gk20a/hw_ram_gk20a.h" -#include "nvgpu-runlist.h" -#include "nvgpu/hw/gk20a/hw_fifo_gk20a.h" - -#define RL_MAX_TIMESLICE_TIMEOUT ram_rl_entry_timeslice_timeout_v(U32_MAX) -#define RL_MAX_TIMESLICE_SCALE ram_rl_entry_timeslice_scale_v(U32_MAX) - -#include "../nvgpu-fifo-common.h" - -#ifdef RUNLIST_UNIT_DEBUG -#define unit_verbose unit_info -#else -#define unit_verbose(unit, msg, ...) \ - do { \ - if (0) { \ - unit_info(unit, msg, ##__VA_ARGS__); \ - } \ - } while (0) -#endif - -struct runlist_unit_ctx { - u32 branches; -}; - -static struct runlist_unit_ctx unit_ctx; - -#define MAX_STUB 4 - -struct stub_ctx { - const char *name; - u32 count; - u32 chid; - u32 tsgid; -}; - -struct stub_ctx stub[MAX_STUB]; - -static void subtest_setup(u32 branches) -{ - u32 i; - - unit_ctx.branches = branches; - - memset(stub, 0, sizeof(stub)); - for (i = 0; i < MAX_STUB; i++) { - stub[i].name = ""; - stub[i].count = 0; - stub[i].chid = NVGPU_INVALID_CHANNEL_ID; - stub[i].tsgid = NVGPU_INVALID_TSG_ID; - } -} - -#define pruned test_fifo_subtest_pruned -#define branches_str test_fifo_flags_str - -static u32 get_log2(u32 num) -{ - u32 res = 0; - - if (num == 0) { - return 0; - } - while (num > 0) { - res++; - num >>= 1; - } - return res - 1U; -} - -#define RL_MAX_TIMESLICE_TIMEOUT ram_rl_entry_timeslice_timeout_v(U32_MAX) -#define RL_MAX_TIMESLICE_SCALE ram_rl_entry_timeslice_scale_v(U32_MAX) - /* - * This helper function mimics the non-FUSA gk20a_runlist_get_tsg_entry - * function that has a simpler logic than other chips but is sufficient for - * runlist test purposes. + * Place holder for runlist unit tests. These will be written once the new + * runlist code is in place. */ -static void generic_runlist_get_tsg_entry(struct nvgpu_tsg *tsg, - u32 *runlist, u32 timeslice) -{ - u32 timeout = timeslice; - u32 scale = 0U; - - while (timeout > RL_MAX_TIMESLICE_TIMEOUT) { - timeout >>= 1U; - scale++; - } - - if (scale > RL_MAX_TIMESLICE_SCALE) { - timeout = RL_MAX_TIMESLICE_TIMEOUT; - scale = RL_MAX_TIMESLICE_SCALE; - } - - runlist[0] = ram_rl_entry_id_f(tsg->tsgid) | - ram_rl_entry_type_tsg_f() | - ram_rl_entry_tsg_length_f(tsg->num_active_channels) | - ram_rl_entry_timeslice_scale_f(scale) | - ram_rl_entry_timeslice_timeout_f(timeout); - runlist[1] = 0; -} - -/* - * This helper function mimics the non-FUSA gk20a_runlist_get_ch_entry - * function that has a simpler logic than other chips but is sufficient for - * runlist test purposes. - */ -static void generic_runlist_get_ch_entry(struct nvgpu_channel *ch, u32 *runlist) -{ - runlist[0] = ram_rl_entry_chid_f(ch->chid); - runlist[1] = 0; -} - -static void setup_fifo(struct gk20a *g, unsigned long *tsg_map, - unsigned long *ch_map, struct nvgpu_tsg *tsgs, - struct nvgpu_channel *chs, unsigned int num_tsgs, - unsigned int num_channels, - struct nvgpu_runlist **runlists, u32 *rl_data, - bool interleave) -{ - struct nvgpu_fifo *f = &g->fifo; - struct nvgpu_runlist *runlist = runlists[0]; - - /* we only use the runlist 0 here */ - runlist->mem[0].aperture = APERTURE_SYSMEM; - runlist->mem[0].cpu_va = rl_data; - - runlist->active_tsgs = tsg_map; - runlist->active_channels = ch_map; - - g->fifo.g = g; - /* to debug, change this to (u64)-1 */ - g->log_mask = 0; - - /* - * set PTIMER src freq to its nominal frequency to avoid rounding - * errors when scaling timeslice. - */ - g->ptimer_src_freq = 31250000; - - f->tsg = tsgs; - f->channel = chs; - f->num_channels = num_channels; - f->runlists = runlists; - - /* - * For testing the runlist entry order format, these simpler dual-u32 - * entries are enough. The logic is same across chips. - */ - f->runlist_entry_size = 2 * sizeof(u32); - g->ops.runlist.get_tsg_entry = generic_runlist_get_tsg_entry; - g->ops.runlist.get_ch_entry = generic_runlist_get_ch_entry; - g->ops.tsg.default_timeslice_us = nvgpu_tsg_default_timeslice_us; - - g->runlist_interleave = interleave; - - /* set bits in active_tsgs correspond to indices in f->tsg[...] */ - nvgpu_bitmap_set(runlist->active_tsgs, 0, num_tsgs); - /* same; these are only used if a high enough tsg appears */ - nvgpu_bitmap_set(runlist->active_channels, 0, num_channels); -} - -static void setup_tsg(struct nvgpu_tsg *tsgs, struct nvgpu_channel *chs, - u32 i, u32 level) -{ - struct nvgpu_tsg *tsg = &tsgs[i]; - struct nvgpu_channel *ch = &chs[i]; - - tsg->tsgid = i; - nvgpu_init_list_node(&tsg->ch_list); - tsg->num_active_channels = 1; - tsg->interleave_level = level; - - /* 1:1 mapping for simplicity */ - ch->chid = i; - nvgpu_list_add_tail(&ch->ch_entry, &tsg->ch_list); -} - -static void setup_tsg_multich(struct nvgpu_tsg *tsgs, struct nvgpu_channel *chs, - u32 i, u32 level, u32 ch_capacity, u32 ch_active) -{ - struct nvgpu_tsg *tsg = &tsgs[i]; - struct nvgpu_channel *ch = &chs[i + 1]; - u32 c; - - setup_tsg(tsgs, chs, i, level); - tsg->num_active_channels = ch_active; - - /* bind the rest of the channels, onwards from the same id */ - for (c = 1; c < ch_capacity; c++) { - ch->chid = i + c; - nvgpu_list_add_tail(&ch->ch_entry, &tsg->ch_list); - ch++; - } -} - -static int run_format_test(struct unit_module *m, struct nvgpu_fifo *f, - struct nvgpu_tsg *tsg, struct nvgpu_channel *chs, - u32 prio, u32 n_ch, u32 *rl_data, - u32 *expect_header, u32 *expect_channel) -{ - u32 n; - - setup_tsg_multich(tsg, chs, 0, prio, 5, n_ch); - - /* entry capacity: tsg header and some channels */ - n = nvgpu_runlist_construct_locked(f, f->runlists[0], 0, 1 + n_ch); - - if (n != 1 + n_ch) { - return -1; - } - if (memcmp(rl_data, expect_header, 2 * sizeof(u32)) != 0) { - unit_err(m, "rl_data[0]=%08x", rl_data[0]); - unit_err(m, "rl_data[1]=%08x", rl_data[1]); - unit_err(m, "expect_header[0]=%08x", expect_header[0]); - unit_err(m, "expect_header[1]=%08x", expect_header[1]); - - unit_err(m, "tsg header mismatch\n"); - return -1; - } - if (memcmp(rl_data + 2, expect_channel, 2 * n_ch * sizeof(u32)) != 0) { - unit_err(m, "channel data mismatch\n"); - return -1; - } - - return 0; -} - -static struct tsg_fmt_test_args { - u32 channels; - u32 chs_bitmap; - u32 level; - u32 timeslice; - u32 expect_header[2]; - u32 expect_channel[10]; -} tsg_fmt_tests[] = { - /* priority 0, one channel */ - { 1, 0x01, 0, 0, { 0x0600e000, 0 }, { 0, 0 } }, - /* priority 1, two channels */ - { 2, 0x03, 1, 0, { 0x0a00e000, 0 }, { 0, 0, 1, 0 } }, - /* priority 2, five channels */ - { 5, 0x1f, 2, 0, { 0x1600e000, 0 }, { 0, 0, 1, 0, 2, 0, 3, 0, 4, 0 } }, - /* priority 0, one channel, nondefault timeslice timeout */ - { 1, 0x01, 0, 0xaa<<3, { 0x06a8e000, 0 }, { 0, 0 } }, - /* priority 0, three channels with two inactives in the middle */ - { 3, 0x01 | 0x04 | 0x10, 0, 0, { 0x0e00e000, 0 }, { 0, 0, 2, 0, 4, 0 } }, -}; - -/* - * Check that inserting a single tsg of any level with a number of channels - * works as expected. - */ -#define F_RUNLIST_FORMAT_FAIL_ENTRIES0 BIT(0) -#define F_RUNLIST_FORMAT_CH2 BIT(1) -#define F_RUNLIST_FORMAT_CH5 BIT(2) -#define F_RUNLIST_FORMAT_CH1_TIMESLICE BIT(3) -#define F_RUNLIST_FORMAT_CH3_INACTIVE2 BIT(4) -#define F_RUNLIST_FORMAT_FAIL_ENTRY1 BIT(5) -#define F_RUNLIST_FORMAT_LAST BIT(6) - -static const char *f_runlist_format[] = { - "priority_0_one_channel", - "fail_zero_entries", - "priority_1_two_channels", - "priority_2_five_channels", - "one_channel_nondefault_timeslice_timeout", - "three_channels_with_two_inactives_in_the_middle", - "fail_one_entry", -}; - -int test_tsg_format_gen(struct unit_module *m, struct gk20a *g, void *args) -{ - struct nvgpu_fifo *f = &g->fifo; - struct nvgpu_runlist runlist; - struct nvgpu_runlist *runlists = &runlist; - unsigned long active_tsgs_map = 0; - unsigned long active_chs_map = 0; - struct nvgpu_tsg tsgs[1] = {{0}}; - struct nvgpu_channel chs[5] = {{0}}; - /* header + at most five channels */ - const u32 entries_in_list_max = 1 + 5; - u32 rl_data[2 * entries_in_list_max]; - struct tsg_fmt_test_args *test_args; - u32 branches = 0U; - int ret = UNIT_FAIL; - int err = 0; - u32 fail = F_RUNLIST_FORMAT_FAIL_ENTRIES0 | - F_RUNLIST_FORMAT_FAIL_ENTRY1; - u32 prune = F_RUNLIST_FORMAT_CH2 | F_RUNLIST_FORMAT_CH5 | - F_RUNLIST_FORMAT_CH1_TIMESLICE | - F_RUNLIST_FORMAT_CH3_INACTIVE2 | - fail; - - setup_fifo(g, &active_tsgs_map, &active_chs_map, tsgs, chs, 1, 5, - &runlists, rl_data, false); - - for (branches = 0U; branches < F_RUNLIST_FORMAT_LAST; - branches++) { - if (pruned(branches, prune)) { - unit_verbose(m, "%s branches=%u (pruned)\n", __func__, - branches); - continue; - } - unit_verbose(m, "%s branches=%u\n", __func__, branches); - subtest_setup(branches); - - if (branches & fail) { - test_args = &tsg_fmt_tests[0]; - } else { - test_args = &tsg_fmt_tests[get_log2(branches)]; - } - - active_chs_map = test_args->chs_bitmap; - - if (test_args->timeslice == 0U) { - tsgs[0].timeslice_us = - g->ops.tsg.default_timeslice_us(g); - } else { - tsgs[0].timeslice_us = test_args->timeslice; - } - - if (branches & fail) { - err = run_format_test(m, f, &tsgs[0], chs, - test_args->level, get_log2(branches)-1, rl_data, - test_args->expect_header, - test_args->expect_channel); - unit_assert(err != 0, goto done); - } else { - err = run_format_test(m, f, &tsgs[0], chs, - test_args->level, test_args->channels, rl_data, - test_args->expect_header, - test_args->expect_channel); - unit_assert(err == 0, goto done); - } - - } - ret = UNIT_SUCCESS; - -done: - if (ret != UNIT_SUCCESS) { - unit_err(m, "%s branches=%s\n", __func__, - branches_str(branches, f_runlist_format)); - } - - return ret; -} - -/* compare 1:1 tsg-channel entries against expectations */ -static int check_same_simple_tsgs(struct unit_module *m, u32 *expected, - u32 *actual, u32 n_entries) -{ - u32 i; - - for (i = 0; i < n_entries; i++) { - u32 want = expected[i]; - /* - * 2 u32s per each entry, 2 entries per tsg, and the second - * entry of each tsg has the channel id at the first u32. - */ - u32 entry_off = 2 * i + 1; - u32 got = actual[2 * entry_off]; - if (want != got) { - unit_return_fail(m, - "wrong entry at %u: expected %u, got %u\n", - i, want, got); - } - } - return UNIT_SUCCESS; -} - -/* Common stuff for all tests below to reduce boilerplate */ -static int test_common_gen(struct unit_module *m, struct gk20a *g, - bool interleave, u32 sizelimit, - u32 *levels, u32 levels_count, - u32 *expected, u32 expect_count) -{ - struct nvgpu_fifo *f = &g->fifo; - struct nvgpu_runlist runlist; - struct nvgpu_runlist *runlists = &runlist; - unsigned long active_tsgs_map = 0; - unsigned long active_chs_map = 0; - struct nvgpu_tsg tsgs[6] = {{0}}; - struct nvgpu_channel chs[6] = {{0}}; - u32 tsgs_in_list = expect_count; - /* a tsg header and a channel entry for each */ - const u32 entries_in_list = 2 * tsgs_in_list; - /* one entry is two u32s in these tests */ - u32 rl_data[2 * entries_in_list]; - u32 n; - u32 i = 0; - - setup_fifo(g, &active_tsgs_map, &active_chs_map, tsgs, chs, - levels_count, 6, &runlists, rl_data, interleave); - - for (i = 0; i < levels_count; i++) { - setup_tsg(tsgs, chs, i, levels[i]); - } - - n = nvgpu_runlist_construct_locked(f, &runlist, 0, - sizelimit != 0U ? sizelimit : entries_in_list); - - if (sizelimit != 0 && sizelimit != entries_in_list) { - /* Less than enough size is always a negative test here */ - if (n != 0xffffffffU) { - unit_info(m, - "limit %d, expected failure, got %u\n", - sizelimit, n); - return UNIT_FAIL; - } - /* - * Compare what we got; should be good up until the limit. For - * odd limit we miss the last u32 but it's better than nothing. - */ - return check_same_simple_tsgs(m, expected, rl_data, - sizelimit / 2); - } - - if (n != entries_in_list) { - unit_info(m, "expected %u entries, got %u\n", - entries_in_list, n); - return UNIT_FAIL; - } - - return check_same_simple_tsgs(m, expected, rl_data, tsgs_in_list); -} - -#define F_RUNLIST_FLAT_GEN_OVERSIZE_TINY BIT(0) -#define F_RUNLIST_FLAT_GEN_OVERSIZE_SINGLE BIT(1) -#define F_RUNLIST_FLAT_GEN_OVERSIZE_ONEHALF BIT(2) -#define F_RUNLIST_FLAT_GEN_OVERSIZE_TWO BIT(3) -#define F_RUNLIST_FLAT_GEN_OVERSIZE_END BIT(4) -#define F_RUNLIST_FLAT_GEN_LAST BIT(5) - -static const char *f_runlist_flat[] = { - "runlist_flat_oversize_tiny", - "runlist_flat_oversize_single", - "runlist_flat_oversize_onehalf", - "runlist_flat_oversize_two", - "runlist_flat_oversize_end", -}; - -int test_flat_gen(struct unit_module *m, struct gk20a *g, void *args) -{ - u32 levels[] = { - /* Some random-ish order of priority levels */ - 0, 1, 2, 1, 0, 2, - }; - u32 expected[] = { - /* High (2) indices first, then medium (1), then low (0). */ - 2, 5, 1, 3, 0, 4, - }; - u32 sizelimits[] = { - 0, 1, 2, 3, 4, 11, - }; - u32 branches = 0U; - int ret = UNIT_FAIL; - u32 prune = F_RUNLIST_FLAT_GEN_OVERSIZE_TINY | - F_RUNLIST_FLAT_GEN_OVERSIZE_SINGLE | - F_RUNLIST_FLAT_GEN_OVERSIZE_ONEHALF | - F_RUNLIST_FLAT_GEN_OVERSIZE_TWO | - F_RUNLIST_FLAT_GEN_OVERSIZE_END; - - for (branches = 0U; branches < F_RUNLIST_FLAT_GEN_LAST; branches++) { - - if (pruned(branches, prune)) { - unit_verbose(m, "%s branches=%u (pruned)\n", __func__, - branches); - continue; - } - unit_verbose(m, "%s branches=%u\n", __func__, branches); - subtest_setup(branches); - - ret = test_common_gen(m, g, false, - sizelimits[get_log2(branches)], - levels, ARRAY_SIZE(levels), - expected, ARRAY_SIZE(expected)); - if (ret != UNIT_SUCCESS) { - unit_err(m, "%s branches=%s\n", __func__, - branches_str(branches, f_runlist_flat)); - break; - } - } - - return ret; -} - -#define F_RUNLIST_INTERLEAVE_SINGLE_L0 BIT(0) -#define F_RUNLIST_INTERLEAVE_SINGLE_L1 BIT(1) -#define F_RUNLIST_INTERLEAVE_SINGLE_L2 BIT(2) -#define F_RUNLIST_INTERLEAVE_SINGLE_LAST BIT(3) - -static const char *f_runlist_interleave_single[] = { - "only_L0_items", - "only_L1_items", - "only_L2_items", -}; - -static struct interleave_single_args { - u32 n_levels; - u32 levels[2]; - u32 n_expected; - u32 expected[2]; -} interleave_single_tests[] = { - /* Only l0 items */ - { 2, { 0, 0 }, 2, { 0, 1 } }, - /* Only l1 items */ - { 2, { 1, 1 }, 2, { 0, 1 } }, - /* Only l2 items */ - { 2, { 2, 2 }, 2, { 0, 1 } }, -}; - -int test_interleave_single(struct unit_module *m, struct gk20a *g, void *args) -{ - struct interleave_single_args *single_args; - u32 branches = 0U; - int ret = UNIT_FAIL; - u32 prune = F_RUNLIST_INTERLEAVE_SINGLE_L0 | - F_RUNLIST_INTERLEAVE_SINGLE_L1 | - F_RUNLIST_INTERLEAVE_SINGLE_L2; - - for (branches = 0U; branches < F_RUNLIST_INTERLEAVE_SINGLE_LAST; - branches++) { - - if (pruned(branches, prune)) { - unit_verbose(m, "%s branches=%u (pruned)\n", __func__, - branches); - continue; - } - unit_verbose(m, "%s branches=%u\n", __func__, branches); - subtest_setup(branches); - - single_args = &interleave_single_tests[get_log2(branches)]; - - ret = test_common_gen(m, g, true, 2 * single_args->n_expected, - single_args->levels, single_args->n_levels, - single_args->expected, single_args->n_expected); - - if (ret != UNIT_SUCCESS) { - unit_err(m, "%s branches=%s\n", __func__, - branches_str(branches, f_runlist_interleave_single)); - break; - } - } - - return ret; -} - -#define F_RUNLIST_INTERLEAVE_DUAL_L0_L1 BIT(0) -#define F_RUNLIST_INTERLEAVE_DUAL_L1_L2 BIT(1) -#define F_RUNLIST_INTERLEAVE_DUAL_L0_L2 BIT(2) -#define F_RUNLIST_INTERLEAVE_DUAL_L0_L2_FAIL BIT(3) -#define F_RUNLIST_INTERLEAVE_DUAL_LAST BIT(4) - -static const char *f_runlist_interleave_dual[] = { - "only_L0_and_L1_items", - "only_L1_and_L2_items", - "only_L0_and_L2_items", - "L0_and_L2_items_2_entries", -}; - -static struct interleave_dual_args { - u32 n_levels; - u32 levels[4]; - u32 n_expected; - u32 expected[6]; -} interleave_dual_tests[] = { - /* Only low and medium priority items. */ - { 4, { 0, 0, 1, 1 }, 6, { 2, 3, 0, 2, 3, 1 } }, - /* Only medium and high priority items. */ - { 4, { 1, 1, 2, 2 }, 6, { 2, 3, 0, 2, 3, 1 } }, - /* Only low and high priority items. */ - { 4, { 0, 0, 2, 2 }, 6, { 2, 3, 0, 2, 3, 1 } }, - /* Only low and high priority items. */ - { 4, { 0, 0, 2, 2 }, 2, { 2, 3, 0, 2, 3, 1 } }, -}; - -int test_interleave_dual(struct unit_module *m, struct gk20a *g, void *args) -{ - struct interleave_dual_args *dual_args; - - u32 branches = 0U; - int ret = UNIT_FAIL; - int err; - u32 fail = F_RUNLIST_INTERLEAVE_DUAL_L0_L2_FAIL; - u32 prune = F_RUNLIST_INTERLEAVE_DUAL_L0_L1 | - F_RUNLIST_INTERLEAVE_DUAL_L1_L2 | - F_RUNLIST_INTERLEAVE_DUAL_L0_L2 | - fail; - - for (branches = 1U; branches < F_RUNLIST_INTERLEAVE_DUAL_LAST; - branches++) { - - if (pruned(branches, prune)) { - unit_verbose(m, "%s branches=%u (pruned)\n", __func__, - branches); - continue; - } - unit_verbose(m, "%s branches=%u\n", __func__, branches); - subtest_setup(branches); - - dual_args = &interleave_dual_tests[get_log2(branches)]; - - err = test_common_gen(m, g, true, 2 * dual_args->n_expected, - dual_args->levels, dual_args->n_levels, - dual_args->expected, dual_args->n_expected); - - if (branches & fail) { - unit_assert(err != UNIT_SUCCESS, goto done); - } else { - unit_assert(err == UNIT_SUCCESS, goto done); - } - } - - ret = UNIT_SUCCESS; - -done: - if (ret != UNIT_SUCCESS) { - unit_err(m, "%s branches=%s\n", __func__, - branches_str(branches, f_runlist_interleave_dual)); - } - - return ret; -} - -static struct interleave_level_test_args { -u32 sizelimit; -} interleave_level_tests[] = { - /* All priority items. */ - { 0 }, - /* Fail at level 2 immediately: space for just a tsg header, - * no ch entries. - */ - { 1 }, - /* Insert both l2 entries, then fail at l1 level. */ - { 2 * 2 }, - /* Insert both l2 entries, one l1, and just one l2: fail at last l2. */ - { (2 + 1 + 1) * 2 }, - /* Stop at exactly the first l2 entry in the first l1-l0 transition. */ - { (2 + 1 + 2 + 1) * 2 }, - /* Stop at exactly the first l0 entry that doesn't fit. */ - { (2 + 1 + 2 + 1 + 2) * 2 }, -}; - -#define F_RUNLIST_INTERLEAVE_LEVELS_ALL_PRIO BIT(0) -#define F_RUNLIST_INTERLEAVE_LEVELS_FAIL_L2 BIT(1) -#define F_RUNLIST_INTERLEAVE_LEVELS_FAIL_L1 BIT(2) -#define F_RUNLIST_INTERLEAVE_LEVELS_FIT BIT(3) -#define F_RUNLIST_INTERLEAVE_LEVELS_FAIL_L0 BIT(4) -#define F_RUNLIST_INTERLEAVE_LEVELS_LAST BIT(5) - -static const char *f_runlist_interleave_levels[] = { - "interleaving", - "interleaving_oversize_tiny", - "interleaving_oversize_l2", - "interleaving_oversize_l2_l1_l2", - "interleaving_oversize_l2_l1_l2_l1", - "interleaving_oversize_l2_l1_l2_l1_l2", -}; - -int test_interleaving_levels(struct unit_module *m, struct gk20a *g, void *args) -{ - u32 sizelimit; - u32 l1 = 0, l2 = 1; - u32 m1 = 2, m2 = 3; - u32 h1 = 4, h2 = 5; - u32 levels[] = { 0, 0, 1, 1, 2, 2 }; - u32 expected[] = { - /* Order of channel ids; partly used also for oversize tests */ - h1, h2, m1, h1, h2, m2, h1, h2, l1, - h1, h2, m1, h1, h2, m2, h1, h2, l2, - }; - - u32 branches = 1U; - int ret = UNIT_FAIL; - u32 prune = F_RUNLIST_INTERLEAVE_LEVELS_ALL_PRIO | - F_RUNLIST_INTERLEAVE_LEVELS_FAIL_L2 | - F_RUNLIST_INTERLEAVE_LEVELS_FAIL_L1 | - F_RUNLIST_INTERLEAVE_LEVELS_FIT | - F_RUNLIST_INTERLEAVE_LEVELS_FAIL_L0; - - for (branches = 0U; branches < F_RUNLIST_INTERLEAVE_LEVELS_LAST; - branches++) { - - if (pruned(branches, prune)) { - unit_verbose(m, "%s branches=%u (pruned)\n", __func__, - branches); - continue; - } - unit_verbose(m, "%s branches=%u\n", __func__, branches); - subtest_setup(branches); - - sizelimit = interleave_level_tests[ - get_log2(branches)].sizelimit; - - ret = test_common_gen(m, g, true, sizelimit, levels, - ARRAY_SIZE(levels), expected, ARRAY_SIZE(expected)); - - if (ret != UNIT_SUCCESS) { - unit_err(m, "%s branches=%s\n", __func__, - branches_str(branches, f_runlist_interleave_levels)); - break; - } - } - return ret; -} - -#define F_RUNLIST_INTERLEAVE_LEVEL_LOW BIT(0) -#define F_RUNLIST_INTERLEAVE_LEVEL_MEDIUM BIT(1) -#define F_RUNLIST_INTERLEAVE_LEVEL_HIGH BIT(2) -#define F_RUNLIST_INTERLEAVE_LEVEL_DEFAULT BIT(3) -#define F_RUNLIST_INTERLEAVE_LEVEL_LAST BIT(4) - -static const char *f_runlist_interleave_level_name[] = { - "LOW", - "MEDIUM", - "HIGH", - "?" -}; - -int test_runlist_interleave_level_name(struct unit_module *m, - struct gk20a *g, void *args) -{ - u32 branches = 0U; - int ret = UNIT_FAIL; - u32 fail = F_RUNLIST_INTERLEAVE_LEVEL_MEDIUM | - F_RUNLIST_INTERLEAVE_LEVEL_HIGH | - F_RUNLIST_INTERLEAVE_LEVEL_DEFAULT; - u32 prune = fail; - const char *interleave_level_name = NULL; - - for (branches = 0U; branches < F_RUNLIST_INTERLEAVE_LEVEL_LAST; - branches++) { - - if (pruned(branches, prune)) { - unit_verbose(m, "%s branches=%u (pruned)\n", __func__, - branches); - continue; - } - unit_verbose(m, "%s branches=%u\n", __func__, branches); - subtest_setup(branches); - - interleave_level_name = - nvgpu_runlist_interleave_level_name(get_log2(branches)); - unit_assert(strcmp(interleave_level_name, - f_runlist_interleave_level_name[ - get_log2(branches)]) == 0, goto done); - } - - ret = UNIT_SUCCESS; - -done: - if (ret != UNIT_SUCCESS) { - unit_err(m, "%s failed\n", __func__); - } - - return ret; -} - -static void stub_runlist_write_state(struct gk20a *g, u32 runlists_mask, - u32 runlist_state) -{ - stub[0].count = runlists_mask; -} - -#define F_RUNLIST_SET_STATE_DISABLED BIT(0) -#define F_RUNLIST_SET_STATE_ENABLED BIT(1) -#define F_RUNLIST_SET_STATE_LAST BIT(2) - -static const char *f_runlist_set_state[] = { - "set_state_disabled", - "set_state_enabled", -}; - -int test_runlist_set_state(struct unit_module *m, struct gk20a *g, void *args) -{ - struct gpu_ops gops = g->ops; - u32 branches = 0U; - int ret = UNIT_FAIL; - u32 fail = F_RUNLIST_SET_STATE_ENABLED | F_RUNLIST_SET_STATE_DISABLED; - u32 prune = fail; - - g->ops.runlist.write_state = stub_runlist_write_state; - - for (branches = 1U; branches < F_RUNLIST_SET_STATE_LAST; branches++) { - - if (pruned(branches, prune)) { - unit_verbose(m, "%s branches=%u (pruned)\n", __func__, - branches); - continue; - } - unit_verbose(m, "%s branches=%u\n", __func__, branches); - subtest_setup(branches); - - if (branches & F_RUNLIST_SET_STATE_DISABLED) { - nvgpu_runlist_set_state(g, 0U, RUNLIST_DISABLED); - unit_assert(stub[0].count == 0U, goto done); - } else { - nvgpu_runlist_set_state(g, 1U, RUNLIST_ENABLED); - unit_assert(stub[0].count == 1U, goto done); - } - } - - ret = UNIT_SUCCESS; - -done: - if (ret != UNIT_SUCCESS) { - unit_err(m, "%s branches=%s\n", __func__, - branches_str(branches, f_runlist_set_state)); - } - - g->ops = gops; - return ret; -} - -#define F_RUNLIST_LOCK_UNLOCK_ACTIVE_RUNLISTS_LAST BIT(0) - -int test_runlist_lock_unlock_active_runlists(struct unit_module *m, - struct gk20a *g, void *args) -{ - int err = 0; - u32 branches = 0U; - int ret = UNIT_FAIL; - u32 fail = 0U; - u32 prune = fail; - - err = nvgpu_runlist_setup_sw(g); - unit_assert(err == 0, goto done); - - for (branches = 0U; - branches < F_RUNLIST_LOCK_UNLOCK_ACTIVE_RUNLISTS_LAST; - branches++) { - - if (pruned(branches, prune)) { - unit_verbose(m, "%s branches=%u (pruned)\n", __func__, - branches); - continue; - } - unit_verbose(m, "%s branches=%u\n", __func__, branches); - subtest_setup(branches); - - nvgpu_runlist_lock_active_runlists(g); - nvgpu_runlist_unlock_active_runlists(g); - - nvgpu_runlist_lock_active_runlists(g); - nvgpu_runlist_unlock_runlists(g, 3U); - - nvgpu_runlist_unlock_runlists(g, 0U); - } - - ret = UNIT_SUCCESS; - -done: - if (ret != UNIT_SUCCESS) { - unit_err(m, "%s failed\n", __func__); - } - - nvgpu_runlist_cleanup_sw(g); - return ret; -} - -#define F_RUNLIST_GET_MASK_ID_TYPE_KNOWN BIT(0) -#define F_RUNLIST_GET_MASK_ID_TYPE_TSG BIT(1) -#define F_RUNLIST_GET_MASK_ACT_ENG_BITMASK_NONZERO BIT(2) -#define F_RUNLIST_GET_MASK_PBDMA_BITMASK_NONZERO BIT(3) -#define F_RUNLIST_GET_MASK_LAST BIT(4) - -static const char *f_runlist_get_mask[] = { - "ID_type_known", - "act_eng_bitmask_nonzero", - "pbdma_bitmask_nonzero", -}; - -int test_runlist_get_mask(struct unit_module *m, struct gk20a *g, void *args) -{ - unsigned int id_type = ID_TYPE_UNKNOWN; - u32 act_eng_bitmask = 0U; - u32 pbdma_bitmask = 0U; - u32 ret_mask = 0U; - int err = 0; - u32 branches = 0U; - int ret = UNIT_FAIL; - u32 fail = 0U; - u32 prune = fail; - - err = nvgpu_runlist_setup_sw(g); - unit_assert(err == 0, goto done); - - for (branches = 0U; branches < F_RUNLIST_GET_MASK_LAST; branches++) { - - if (pruned(branches, prune)) { - unit_verbose(m, "%s branches=%s (pruned)\n", __func__, - branches_str(branches, f_runlist_get_mask)); - continue; - } - unit_verbose(m, "%s branches=%s\n", __func__, - branches_str(branches, f_runlist_get_mask)); - subtest_setup(branches); - - id_type = (branches & F_RUNLIST_GET_MASK_ID_TYPE_KNOWN) ? - ((branches & F_RUNLIST_GET_MASK_ID_TYPE_TSG) ? - ID_TYPE_TSG : ID_TYPE_CHANNEL) : - ID_TYPE_UNKNOWN; - - act_eng_bitmask = (branches & - F_RUNLIST_GET_MASK_ACT_ENG_BITMASK_NONZERO) ? - 1U : 0U; - - pbdma_bitmask = (branches & - F_RUNLIST_GET_MASK_PBDMA_BITMASK_NONZERO) ? - 1U : 0U; - - ret_mask = nvgpu_runlist_get_runlists_mask(g, 0U, id_type, - act_eng_bitmask, pbdma_bitmask); - - } - - if (branches == 0U) { - unit_assert(ret_mask == 3U, goto done); - } else { - unit_assert(ret_mask == 1U, goto done); - } - - ret = UNIT_SUCCESS; - -done: - if (ret != UNIT_SUCCESS) { - unit_err(m, "%s branches=%s\n", __func__, - branches_str(branches, f_runlist_get_mask)); - } - - nvgpu_runlist_cleanup_sw(g); - return ret; -} - -#define F_RUNLIST_SETUP_ALLOC_RUNLIST_INFO_FAIL BIT(0) -#define F_RUNLIST_SETUP_ALLOC_ACTIVE_RUNLIST_INFO_FAIL BIT(1) -#define F_RUNLIST_SETUP_ALLOC_ACTIVE_CHANNELS_FAIL BIT(2) -#define F_RUNLIST_SETUP_ALLOC_ACTIVE_TSGS_FAIL BIT(3) -#define F_RUNLIST_SETUP_ALLOC_DMA_FLAGS_SYS_FAIL BIT(4) -#define F_RUNLIST_SETUP_GPU_IS_VIRTUAL BIT(5) -#define F_RUNLIST_SETUP_LAST BIT(6) - -static const char *f_runlist_setup[] = { - "alloc_runlists_fail", - "alloc_active_runlists_fail", - "alloc_active_channels_fail", - "alloc_active_tsgs_fail", - "alloc_dma_flags_sys_fail", - "GPU_is_virtual" -}; - -int test_runlist_setup_sw(struct unit_module *m, struct gk20a *g, void *args) -{ - struct nvgpu_posix_fault_inj *kmem_fi; - struct nvgpu_posix_fault_inj *dma_fi; - u32 branches = 0U; - int err = 0; - int ret = UNIT_FAIL; - u32 fail = F_RUNLIST_SETUP_ALLOC_RUNLIST_INFO_FAIL | - F_RUNLIST_SETUP_ALLOC_ACTIVE_RUNLIST_INFO_FAIL | - F_RUNLIST_SETUP_ALLOC_ACTIVE_CHANNELS_FAIL | - F_RUNLIST_SETUP_ALLOC_ACTIVE_TSGS_FAIL | - F_RUNLIST_SETUP_ALLOC_DMA_FLAGS_SYS_FAIL; - u32 prune = fail; - - kmem_fi = nvgpu_kmem_get_fault_injection(); - dma_fi = nvgpu_dma_alloc_get_fault_injection(); - - for (branches = 0U; branches < F_RUNLIST_SETUP_LAST; branches++) { - - if (pruned(branches, prune)) { - unit_verbose(m, "%s branches=%s (pruned)\n", __func__, - branches_str(branches, f_runlist_setup)); - continue; - } - unit_verbose(m, "%s branches=%s\n", __func__, - branches_str(branches, f_runlist_setup)); - subtest_setup(branches); - - if ((branches >= F_RUNLIST_SETUP_ALLOC_RUNLIST_INFO_FAIL) && - (branches <= F_RUNLIST_SETUP_ALLOC_ACTIVE_TSGS_FAIL)) { - nvgpu_posix_enable_fault_injection(kmem_fi, - branches & fail ? true : false, - get_log2(branches)); - } - - nvgpu_posix_enable_fault_injection(dma_fi, - branches & F_RUNLIST_SETUP_ALLOC_DMA_FLAGS_SYS_FAIL ? - true : false, 0); - - if (branches & F_RUNLIST_SETUP_GPU_IS_VIRTUAL) { - g->is_virtual = true; - } - - err = nvgpu_runlist_setup_sw(g); - - g->is_virtual = false; - nvgpu_posix_enable_fault_injection(kmem_fi, false, 0); - nvgpu_posix_enable_fault_injection(dma_fi, false, 0); - - if (branches & fail) { - unit_assert(err != 0, goto done); - } else { - unit_assert(err == 0, goto done); - nvgpu_runlist_cleanup_sw(g); - } - } - - ret = UNIT_SUCCESS; - -done: - if (ret != UNIT_SUCCESS) { - unit_err(m, "%s branches=%s\n", __func__, - branches_str(branches, f_runlist_setup)); - } - - return ret; -} - -static int stub_runlist_wait_pending_timedout(struct gk20a *g, u32 runlist_id) -{ - return -ETIMEDOUT; -} - -static int stub_runlist_wait_pending_interrupted(struct gk20a *g, - u32 runlist_id) -{ - return -EINTR; -} - -static int stub_runlist_wait_pending_success(struct gk20a *g, u32 runlist_id) -{ - return 0; -} - -static void stub_runlist_hw_submit(struct gk20a *g, u32 runlist_id, - u32 count, u32 buffer_index) -{ - return; -} - -#define F_RUNLIST_RELOAD_IDS_GPU_NULL BIT(0) -#define F_RUNLIST_RELOAD_IDS_NO_RUNLIST BIT(1) -#define F_RUNLIST_RELOAD_IDS_WAIT_TIMEOUT BIT(2) -#define F_RUNLIST_RELOAD_IDS_WAIT_INTERRUPT BIT(3) -#define F_RUNLIST_RELOAD_IDS_REMOVE_CHANNELS BIT(4) -#define F_RUNLIST_RELOAD_IDS_RESTORE_CHANNELS BIT(5) -#define F_RUNLIST_RELOAD_IDS_LAST BIT(6) - -static const char *f_runlist_reload_ids[] = { - "null_gpu_pointer", - "no_runlist_selected", - "runlist_wait_pending_timeout", - "runlist_wait_pending_interrupted", - "remove_active_channels_from_runlist", - "restore_active_channels_from_runlist", -}; - -int test_runlist_reload_ids(struct unit_module *m, struct gk20a *g, void *args) -{ - struct gpu_ops gops = g->ops; - bool add = false; - u32 runlist_ids = 0U; - u32 branches = 0U; - int ret = UNIT_FAIL; - int err = 0; - u32 fail = F_RUNLIST_RELOAD_IDS_GPU_NULL | - F_RUNLIST_RELOAD_IDS_WAIT_TIMEOUT | - F_RUNLIST_RELOAD_IDS_WAIT_INTERRUPT; - u32 prune = F_RUNLIST_RELOAD_IDS_NO_RUNLIST | - F_RUNLIST_RELOAD_IDS_REMOVE_CHANNELS | - F_RUNLIST_RELOAD_IDS_RESTORE_CHANNELS | - fail; - - g->ops.runlist.hw_submit = stub_runlist_hw_submit; - err = nvgpu_runlist_setup_sw(g); - unit_assert(err == 0, goto done); - - for (branches = 1U; branches < F_RUNLIST_RELOAD_IDS_LAST; - branches++) { - - if (pruned(branches, prune)) { - unit_verbose(m, "%s branches=%u (pruned)\n", __func__, - branches); - continue; - } - unit_verbose(m, "%s branches=%u\n", __func__, branches); - subtest_setup(branches); - - runlist_ids = (branches & F_RUNLIST_RELOAD_IDS_NO_RUNLIST) ? - 0U : 1U; - add = (branches & F_RUNLIST_RELOAD_IDS_RESTORE_CHANNELS) ? - true : false; - - if (branches & F_RUNLIST_RELOAD_IDS_WAIT_TIMEOUT) { - g->ops.runlist.wait_pending = - stub_runlist_wait_pending_timedout; - } else if (branches & F_RUNLIST_RELOAD_IDS_WAIT_INTERRUPT) { - g->ops.runlist.wait_pending = - stub_runlist_wait_pending_interrupted; - } else { - g->ops.runlist.wait_pending = - stub_runlist_wait_pending_success; - } - - if (branches & F_RUNLIST_RELOAD_IDS_GPU_NULL) { - err = nvgpu_runlist_reload_ids(NULL, runlist_ids, add); - } else { - err = nvgpu_runlist_reload_ids(g, runlist_ids, add); - } - - if (branches & fail) { - unit_assert(err != 0, goto done); - } else { - unit_assert(err == 0, goto done); - } - - } - ret = UNIT_SUCCESS; - -done: - if (ret != UNIT_SUCCESS) { - unit_err(m, "%s branches=%s\n", __func__, - branches_str(branches, f_runlist_reload_ids)); - } - - g->ops = gops; - return ret; -} - -static void stub_runlist_get_ch_entry(struct nvgpu_channel *ch, u32 *runlist) -{ -} - -#define F_RUNLIST_UPDATE_ADD BIT(0) -#define F_RUNLIST_UPDATE_CH_NULL BIT(1) -#define F_RUNLIST_UPDATE_CH_TSGID_INVALID BIT(2) -#define F_RUNLIST_UPDATE_ADD_AGAIN BIT(3) -#define F_RUNLIST_UPDATE_RECONSTRUCT_FAIL BIT(4) -#define F_RUNLIST_UPDATE_REMOVE_ALL_CHANNELS BIT(5) -#define F_RUNLIST_UPDATE_LAST BIT(6) - -static const char *f_runlist_update[] = { - "add_ch", - "add_ch_again", - "update_null_ch", - "update_ch_with_invalid_tsgid", - "wait_for_finish", - "update_reconstruct_fail", - "remove_all_channels", -}; - -int test_runlist_update_locked(struct unit_module *m, struct gk20a *g, - void *args) -{ - struct gpu_ops gops = g->ops; - struct nvgpu_channel *ch = NULL; - struct nvgpu_tsg *tsg = NULL; - u32 num_runlist_entries_orig = 0U; - u32 ch_tsgid_orig = 0U; - bool add = false; - u32 branches = 0U; - int ret = UNIT_FAIL; - int err = 0; - u32 fail = F_RUNLIST_UPDATE_RECONSTRUCT_FAIL; - u32 prune = F_RUNLIST_UPDATE_CH_TSGID_INVALID | - F_RUNLIST_UPDATE_ADD_AGAIN | - F_RUNLIST_UPDATE_REMOVE_ALL_CHANNELS | fail; - - g->ops.runlist.hw_submit = stub_runlist_hw_submit; - g->ops.runlist.get_ch_entry = stub_runlist_get_ch_entry; - num_runlist_entries_orig = g->fifo.num_runlist_entries; - g->ptimer_src_freq = 31250000; - - tsg = nvgpu_tsg_open(g, getpid()); - unit_assert(tsg != NULL, goto done); - - ch = nvgpu_channel_open_new(g, NVGPU_INVALID_RUNLIST_ID, false, - getpid(), getpid()); - unit_assert(ch != NULL, goto done); - - err = nvgpu_tsg_bind_channel(tsg, ch); - unit_assert(err == 0, goto done); - - ch_tsgid_orig = ch->tsgid; - - for (branches = 0U; branches < F_RUNLIST_UPDATE_LAST; - branches++) { - - if (pruned(branches, prune)) { - unit_verbose(m, "%s branches=%u (pruned)\n", __func__, - branches); - continue; - } - unit_verbose(m, "%s branches=%u\n", __func__, branches); - subtest_setup(branches); - - ch->tsgid = (branches & F_RUNLIST_UPDATE_CH_TSGID_INVALID) ? - NVGPU_INVALID_TSG_ID : ch_tsgid_orig; - - add = branches & F_RUNLIST_UPDATE_ADD ? true : false; - - if (branches & F_RUNLIST_UPDATE_ADD_AGAIN) { - err = nvgpu_runlist_update_locked(g, - 0U, ch, true, false); - unit_assert(err == 0, goto done); - - add = true; - } - - if (branches & F_RUNLIST_UPDATE_RECONSTRUCT_FAIL) { - g->fifo.num_runlist_entries = 0U; - /* force null ch and add = true to execute fail path */ - branches |= F_RUNLIST_UPDATE_CH_NULL; - add = true; - } else { - g->fifo.num_runlist_entries = num_runlist_entries_orig; - } - - if (branches & F_RUNLIST_UPDATE_REMOVE_ALL_CHANNELS) { - /* Add additional channel to cover more branches */ - struct nvgpu_channel *chA = NULL; - - chA = nvgpu_channel_open_new(g, - NVGPU_INVALID_RUNLIST_ID, false, - getpid(), getpid()); - unit_assert(chA != NULL, goto done); - - err = nvgpu_tsg_bind_channel(tsg, chA); - unit_assert(err == 0, goto done); - - err = nvgpu_runlist_update_locked(g, - 0U, chA, true, false); - unit_assert(err == 0, goto done); - - err = nvgpu_runlist_update_locked(g, - 0U, chA, false, false); - unit_assert(err == 0, goto done); - - err = nvgpu_tsg_force_unbind_channel(tsg, chA); - if (err != 0) { - unit_err(m, "Cannot unbind channel A\n"); - } - if (chA != NULL) { - nvgpu_channel_close(chA); - } - } - - if (branches & F_RUNLIST_UPDATE_CH_NULL) { - err = nvgpu_runlist_update_locked(g, - 0U, NULL, add, false); - } else { - err = nvgpu_runlist_update_locked(g, - 0U, ch, add, false); - } - - if (branches & fail) { - unit_assert(err != 0, goto done); - } else { - unit_assert(err == 0, goto done); - } - ch->tsgid = ch_tsgid_orig; - } - - ret = UNIT_SUCCESS; - -done: - if (ret != UNIT_SUCCESS) { - unit_err(m, "%s branches %u=%s\n", __func__, branches, - branches_str(branches, f_runlist_update)); - } - - err = nvgpu_tsg_force_unbind_channel(tsg, ch); - if (err != 0) { - unit_err(m, "Cannot unbind channel\n"); - } - if (ch != NULL) { - nvgpu_channel_close(ch); - } - if (tsg != NULL) { - nvgpu_ref_put(&tsg->refcount, nvgpu_tsg_release); - } - g->ptimer_src_freq = 0; - g->ops = gops; - return ret; -} - -int test_runlist_update_for_channel(struct unit_module *m, struct gk20a *g, - void *args) -{ - struct gpu_ops gops = g->ops; - struct nvgpu_channel *ch = NULL; - struct nvgpu_tsg *tsg = NULL; - int ret = UNIT_FAIL; - int err = 0; - - g->ops.runlist.hw_submit = stub_runlist_hw_submit; - g->ops.runlist.get_ch_entry = stub_runlist_get_ch_entry; - g->ptimer_src_freq = 31250000; - - tsg = nvgpu_tsg_open(g, getpid()); - unit_assert(tsg != NULL, goto done); - - ch = nvgpu_channel_open_new(g, NVGPU_INVALID_RUNLIST_ID, false, - getpid(), getpid()); - unit_assert(ch != NULL, goto done); - - err = nvgpu_tsg_bind_channel(tsg, ch); - unit_assert(err == 0, goto done); - - err = nvgpu_runlist_update_for_channel(g, 0U, ch, false, false); - unit_assert(err == 0, goto done); - - ret = UNIT_SUCCESS; - -done: - if (ret != UNIT_SUCCESS) { - unit_err(m, "%s failed\n", __func__); - } - - err = nvgpu_tsg_force_unbind_channel(tsg, ch); - if (err != 0) { - unit_err(m, "Cannot unbind channel\n"); - } - if (ch != NULL) { - nvgpu_channel_close(ch); - } - if (tsg != NULL) { - nvgpu_ref_put(&tsg->refcount, nvgpu_tsg_release); - } - g->ptimer_src_freq = 0; - g->ops = gops; - return ret; -} - struct unit_module_test nvgpu_runlist_tests[] = { - - UNIT_TEST(init_support, test_fifo_init_support, &unit_ctx, 0), - UNIT_TEST(setup_sw, test_runlist_setup_sw, NULL, 0), - UNIT_TEST(get_mask, test_runlist_get_mask, NULL, 0), - UNIT_TEST(lock_unlock_active_runlists, test_runlist_lock_unlock_active_runlists, NULL, 0), - UNIT_TEST(set_state, test_runlist_set_state, NULL, 0), - UNIT_TEST(interleave_level_name, test_runlist_interleave_level_name, NULL, 0), - UNIT_TEST(reload_ids, test_runlist_reload_ids, NULL, 0), - UNIT_TEST(runlist_update, test_runlist_update_locked, NULL, 0), - UNIT_TEST(update_for_channel, test_runlist_update_for_channel, NULL, 0), - UNIT_TEST(remove_support, test_fifo_remove_support, &unit_ctx, 0), - UNIT_TEST(tsg_format_flat, test_tsg_format_gen, NULL, 0), - UNIT_TEST(flat, test_flat_gen, NULL, 0), - UNIT_TEST(interleave_single, test_interleave_single, NULL, 0), - UNIT_TEST(interleave_dual, test_interleave_dual, NULL, 0), - UNIT_TEST(interleave_level, test_interleaving_levels, NULL, 0), }; UNIT_MODULE(nvgpu_runlist, nvgpu_runlist_tests, UNIT_PRIO_NVGPU_TEST); diff --git a/userspace/units/fifo/tsg/nvgpu-tsg.c b/userspace/units/fifo/tsg/nvgpu-tsg.c index 8eaec163b..517246350 100644 --- a/userspace/units/fifo/tsg/nvgpu-tsg.c +++ b/userspace/units/fifo/tsg/nvgpu-tsg.c @@ -341,7 +341,7 @@ int test_tsg_bind_channel(struct unit_module *m, /* runlist id mismatch */ tsg->runlist_id = branches & F_TSG_BIND_CHANNEL_RL_MISMATCH ? - ch->runlist_id + 1 : tsg_save.runlist_id; + 0xffffffff : tsg_save.runlist_id; /* ch already already active */ runlist = &f->active_runlists[tsg->runlist_id]; @@ -443,8 +443,8 @@ static int stub_tsg_unbind_channel(struct nvgpu_tsg *tsg, return 0; } -static int stub_runlist_update_for_channel_EINVAL( - struct gk20a *g, u32 runlist_id, +static int stub_runlist_update_EINVAL( + struct gk20a *g, struct nvgpu_runlist *rl, struct nvgpu_channel *ch, bool add, bool wait_for_finish) { stub[0].count++; @@ -542,15 +542,15 @@ int test_tsg_unbind_channel(struct unit_module *m, g->ops.tsg.unbind_channel_check_hw_state = NULL; } - g->ops.runlist.update_for_channel = + g->ops.runlist.update = branches & F_TSG_UNBIND_CHANNEL_RUNLIST_UPDATE_FAIL ? - stub_runlist_update_for_channel_EINVAL : - gops.runlist.update_for_channel; + stub_runlist_update_EINVAL : + gops.runlist.update; if (branches & F_TSG_UNBIND_CHANNEL_RUNLIST_UPDATE_FAIL || branches & F_TSG_UNBIND_CHANNEL_ABORT_RUNLIST_UPDATE_FAIL) { - g->ops.runlist.update_for_channel = - stub_runlist_update_for_channel_EINVAL; + g->ops.runlist.update = + stub_runlist_update_EINVAL; } if ((branches & F_TSG_UNBIND_CHANNEL_UNBIND_HAL) || @@ -1539,7 +1539,7 @@ struct unit_module_test nvgpu_tsg_tests[] = { UNIT_TEST(open, test_tsg_open, &unit_ctx, 0), UNIT_TEST(release, test_tsg_release, &unit_ctx, 0), UNIT_TEST(get_from_id, test_tsg_check_and_get_from_id, &unit_ctx, 0), - UNIT_TEST(bind_channel, test_tsg_bind_channel, &unit_ctx, 0), + UNIT_TEST(bind_channel, test_tsg_bind_channel, &unit_ctx, 2), UNIT_TEST(unbind_channel, test_tsg_unbind_channel, &unit_ctx, 0), UNIT_TEST(unbind_channel_check_hw_state, test_tsg_unbind_channel_check_hw_state, &unit_ctx, 0), diff --git a/userspace/units/gr/intr/nvgpu-gr-intr.c b/userspace/units/gr/intr/nvgpu-gr-intr.c index 34cd823b6..c4c7003b2 100644 --- a/userspace/units/gr/intr/nvgpu-gr-intr.c +++ b/userspace/units/gr/intr/nvgpu-gr-intr.c @@ -148,7 +148,7 @@ static u32 stub_channel_count(struct gk20a *g) return 4; } -static int stub_runlist_update_for_channel(struct gk20a *g, u32 runlist_id, +static int stub_runlist_update(struct gk20a *g, struct nvgpu_runlist *rl, struct nvgpu_channel *ch, bool add, bool wait_for_finish) { return 0; @@ -345,7 +345,7 @@ int test_gr_intr_setup_channel(struct unit_module *m, tsgid); g->ops.channel.count = stub_channel_count; - g->ops.runlist.update_for_channel = stub_runlist_update_for_channel; + g->ops.runlist.update = stub_runlist_update; if (f != NULL) { f->g = g; } diff --git a/userspace/units/gr/setup/nvgpu-gr-setup.c b/userspace/units/gr/setup/nvgpu-gr-setup.c index 256a44257..f08ca0a74 100644 --- a/userspace/units/gr/setup/nvgpu-gr-setup.c +++ b/userspace/units/gr/setup/nvgpu-gr-setup.c @@ -70,9 +70,10 @@ static u32 stub_channel_count(struct gk20a *g) return 4; } -static int stub_runlist_update_for_channel(struct gk20a *g, u32 runlist_id, - struct nvgpu_channel *ch, - bool add, bool wait_for_finish) +static int stub_runlist_update(struct gk20a *g, + struct nvgpu_runlist *rl, + struct nvgpu_channel *ch, + bool add, bool wait_for_finish) { return 0; } @@ -642,7 +643,7 @@ int test_gr_setup_alloc_obj_ctx(struct unit_module *m, tsgid); g->ops.channel.count = stub_channel_count; - g->ops.runlist.update_for_channel = stub_runlist_update_for_channel; + g->ops.runlist.update = stub_runlist_update; /* Save valid gops */ gr_setup_save_valid_ops(g); diff --git a/userspace/units/mm/hal/mmu_fault/gv11b_fusa/mmu-fault-gv11b-fusa.c b/userspace/units/mm/hal/mmu_fault/gv11b_fusa/mmu-fault-gv11b-fusa.c index 2205f4d36..77f6029d1 100644 --- a/userspace/units/mm/hal/mmu_fault/gv11b_fusa/mmu-fault-gv11b-fusa.c +++ b/userspace/units/mm/hal/mmu_fault/gv11b_fusa/mmu-fault-gv11b-fusa.c @@ -522,9 +522,10 @@ static u32 stub_top_get_num_lce(struct gk20a *g) return ret_num_lce; } -static int stub_runlist_update_for_channel(struct gk20a *g, u32 runlist_id, - struct nvgpu_channel *ch, - bool add, bool wait_for_finish) +static int stub_runlist_update(struct gk20a *g, + struct nvgpu_runlist *rl, + struct nvgpu_channel *ch, + bool add, bool wait_for_finish) { return 0; } @@ -644,8 +645,7 @@ int test_handle_mmu_fault_common(struct unit_module *m, } else if (branch & F_TSG_VALID) { /* Init TSG and chB */ g->ops.gr.init.get_no_of_sm = stub_gr_init_get_no_of_sm; - g->ops.runlist.update_for_channel = - stub_runlist_update_for_channel; + g->ops.runlist.update = stub_runlist_update; g->ops.tsg.default_timeslice_us = nvgpu_tsg_default_timeslice_us; g->ops.channel.alloc_inst = nvgpu_channel_alloc_inst;