diff --git a/drivers/gpu/nvgpu/common/fifo/channel.c b/drivers/gpu/nvgpu/common/fifo/channel.c index 7e3c32e59..9d500cc9d 100644 --- a/drivers/gpu/nvgpu/common/fifo/channel.c +++ b/drivers/gpu/nvgpu/common/fifo/channel.c @@ -1195,7 +1195,7 @@ NVGPU_COV_WHITELIST_BLOCK_END(NVGPU_MISRA(Rule, 15_6)) struct nvgpu_channel *nvgpu_channel_from_id__func(struct gk20a *g, u32 chid, const char *caller) { - if (chid == NVGPU_INVALID_CHANNEL_ID) { + if (chid >= g->fifo.num_channels) { return NULL; } diff --git a/drivers/gpu/nvgpu/common/fifo/tsg.c b/drivers/gpu/nvgpu/common/fifo/tsg.c index 6f9b18e83..e49ccae17 100644 --- a/drivers/gpu/nvgpu/common/fifo/tsg.c +++ b/drivers/gpu/nvgpu/common/fifo/tsg.c @@ -53,7 +53,9 @@ void nvgpu_tsg_disable(struct nvgpu_tsg *tsg) struct nvgpu_tsg *nvgpu_tsg_check_and_get_from_id(struct gk20a *g, u32 tsgid) { - if (tsgid == NVGPU_INVALID_TSG_ID) { + struct nvgpu_fifo *f = &g->fifo; + + if (tsgid >= f->num_channels) { return NULL; } @@ -578,6 +580,11 @@ void nvgpu_tsg_set_error_notifier(struct gk20a *g, struct nvgpu_tsg *tsg, u32 error_notifier) { struct nvgpu_channel *ch = NULL; + u32 max_error_notifier_id = NVGPU_ERR_NOTIFIER_PBDMA_PUSHBUFFER_CRC_MISMATCH; + + if (error_notifier > max_error_notifier_id) { + return; + } nvgpu_rwsem_down_read(&tsg->ch_list_lock); nvgpu_list_for_each_entry(ch, &tsg->ch_list, nvgpu_channel, ch_entry) { diff --git a/userspace/Makefile.sources b/userspace/Makefile.sources index 2e93092a2..747ca5e63 100644 --- a/userspace/Makefile.sources +++ b/userspace/Makefile.sources @@ -37,7 +37,8 @@ CORE_OBJS := \ $(CORE_OUT)/module.o \ $(CORE_OUT)/required_tests.o \ $(CORE_OUT)/results.o \ - $(CORE_OUT)/exec.o + $(CORE_OUT)/exec.o \ + $(CORE_OUT)/utils.o CORE_HEADERS := \ $(CORE_SRC)/../include/unit/*.h diff --git a/userspace/Makefile.tmk b/userspace/Makefile.tmk index 615677cd0..ddf6a4901 100644 --- a/userspace/Makefile.tmk +++ b/userspace/Makefile.tmk @@ -31,7 +31,8 @@ NVGPU_UNIT_COMMON_SRCS := \ src/module.c \ src/required_tests.c \ src/results.c \ - src/exec.c + src/exec.c \ + src/utils.c NVGPU_UNIT_COMMON_INCLUDES := \ include \ ../drivers/gpu/nvgpu \ diff --git a/userspace/include/unit/utils.h b/userspace/include/unit/utils.h new file mode 100644 index 000000000..358491d7a --- /dev/null +++ b/userspace/include/unit/utils.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 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. + */ + +#ifndef __UNIT_UTILS_H__ +#define __UNIT_UTILS_H__ + +#include +#include + +u32 get_random_u32(u32 min, u32 max); + +#endif diff --git a/userspace/libnvgpu-unit.export b/userspace/libnvgpu-unit.export index 206f7fe71..e456a8fa6 100644 --- a/userspace/libnvgpu-unit.export +++ b/userspace/libnvgpu-unit.export @@ -1,5 +1,5 @@ # -# Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2018-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"), @@ -24,3 +24,4 @@ __core_print_stdout __core_print_stderr __unit_info_color verbose_lvl +get_random_u32 diff --git a/userspace/src/utils.c b/userspace/src/utils.c new file mode 100644 index 000000000..0af29187e --- /dev/null +++ b/userspace/src/utils.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 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 + +u32 get_random_u32(u32 min, u32 max) +{ + u32 value = ((u32)rand()) % (max - min + 1); + value += min; + + return value; +} diff --git a/userspace/units/fifo/channel/nvgpu-channel.c b/userspace/units/fifo/channel/nvgpu-channel.c index e8e5eeb2f..34c7afb25 100644 --- a/userspace/units/fifo/channel/nvgpu-channel.c +++ b/userspace/units/fifo/channel/nvgpu-channel.c @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -184,6 +185,78 @@ static int stub_channel_alloc_inst_ENOMEM(struct gk20a *g, return -ENOMEM; } +static int test_channel_open_bvec(struct unit_module *m, + struct gk20a *g, void *vargs, bool priviledged) +{ + struct nvgpu_channel *ch = NULL; + int ret = UNIT_FAIL; + u32 gr_runlist_id = nvgpu_engine_get_gr_runlist_id(g); + u32 valid_runlist_ids[][2] = {{0, 1}}; + u32 invalid_runlist_ids[][2] = {{2, U32_MAX}}; + u32 runlist_id, runlist_id_range; + u32 (*working_list)[2]; + /* + * i is to loop through valid and invalid cases + * j is to loop through different ranges within ith case + * states is for min, max and median + */ + u32 i, j, states; + const char *string_cases[] = {"Valid", "Invalid"}; + const char *string_states[] = {"Min", "Max", "Mid"}; + u32 runlist_range_difference; + + /* loop through valid and invalid cases */ + for (i = 0; i < 2; i++) { + /* select appropriate iteration size */ + runlist_id_range = (i == 0) ? ARRAY_SIZE(valid_runlist_ids) : ARRAY_SIZE(invalid_runlist_ids); + /* select correct working list */ + working_list = (i == 0) ? valid_runlist_ids : invalid_runlist_ids; + for (j = 0; j < runlist_id_range; j++) { + for (states = 0; states < 3; states++) { + /* check for min runlist id */ + if (states == 0) + runlist_id = working_list[j][0]; + else if (states == 1) { + /* check for max valid runlist id */ + runlist_id = working_list[j][1]; + } else { + runlist_range_difference = working_list[j][1] - working_list[j][0]; + /* Check for random runlist id in range */ + if (runlist_range_difference > 1) + runlist_id = get_random_u32(working_list[j][0] + 1, working_list[j][1] - 1); + else + continue; + } + unit_info(m, "BVEC testing for nvgpu_channel_open_new with runlist id = 0x%08x(%s range [0x%08x - 0x%08x] %s)\n", runlist_id, string_cases[i], working_list[j][0], working_list[j][1], string_states[states]); + + ch = nvgpu_channel_open_new(g, runlist_id, priviledged, getpid(), getpid()); + if (i == 0) + unit_assert(ch != NULL && ch->runlist->id == runlist_id, goto done); + else + unit_assert(ch != NULL && ch->runlist->id == gr_runlist_id, goto done); + + /* Clearing for success cases */ + if (ch != NULL) { + nvgpu_channel_close(ch); + ch = NULL; + } + } + } + } + + ret = UNIT_SUCCESS; + +done: + if (ret != UNIT_SUCCESS) { + unit_err(m, "%s failed\n", __func__); + if (ch != NULL) { + nvgpu_channel_close(ch); + } + } + + return ret; +} + int test_channel_open(struct unit_module *m, struct gk20a *g, void *vargs) { struct nvgpu_fifo *f = &g->fifo; @@ -277,6 +350,9 @@ int test_channel_open(struct unit_module *m, struct gk20a *g, void *vargs) if (branches & F_CHANNEL_OPEN_BUG_ON) { next_ch->g = NULL; unit_assert(err != 0, goto done); + /* add to head to increase visibility of timing-related bugs */ + nvgpu_list_add(&next_ch->free_chs, &f->free_chs); + f->used_channels -= 1U; } else { unit_assert(err == 0, goto done); }; @@ -309,6 +385,9 @@ int test_channel_open(struct unit_module *m, struct gk20a *g, void *vargs) nvgpu_channel_close(ch); ch = NULL; + + err = test_channel_open_bvec(m, g, vargs, privileged); + unit_assert(err == 0, goto done); } } ret = UNIT_SUCCESS; @@ -1785,6 +1864,91 @@ done: return ret; } +int test_nvgpu_channel_from_id_bvec(struct unit_module *m, + struct gk20a *g, void *args) +{ + struct nvgpu_channel *ch = NULL; + int ret = UNIT_FAIL; + /* One channel is already opened by default */ + int num_channels_to_open = g->fifo.num_channels; + u32 valid_chids[][2] = {{0, g->fifo.num_channels - 1}}; + u32 invalid_chids[][2] = {{g->fifo.num_channels, U32_MAX}}; + u32 (*working_list)[2]; + u32 chid, chid_ranges; + /* + * i is to loop through valid and invalid cases + * j is to loop through different ranges within ith case + * states is for min, max and median + */ + u32 i, j, states; + int c; + const char *string_cases[] = {"Valid", "Invalid"}; + const char *string_states[] = {"Min", "Max", "Mid"}; + u32 chid_range_difference; + + struct nvgpu_channel **ch_list = (struct nvgpu_channel **)calloc(sizeof(struct nvgpu_channel *), num_channels_to_open); + + for (c = 0; c < num_channels_to_open; c++) { + ch_list[c] = nvgpu_channel_open_new(g, -1, false, getpid(), getpid()); + if (ch_list[c] == NULL) { + unit_err(m, "Unable to create channels\n"); + goto done; + } + } + + /* loop through valid and invalid cases */ + for (i = 0; i < 2; i++) { + /* select appropriate iteration size */ + chid_ranges = (i == 0) ? ARRAY_SIZE(valid_chids) : ARRAY_SIZE(invalid_chids); + /* select correct working list */ + working_list = (i == 0) ? valid_chids : invalid_chids; + for (j = 0; j < chid_ranges; j++) { + for (states = 0; states < 3; states++) { + /* check for min chid */ + if (states == 0) + chid = working_list[j][0]; + else if (states == 1) { + /* check for max valid chid */ + chid = working_list[j][1]; + } else { + chid_range_difference = working_list[j][1] - working_list[j][0]; + /* Check for random chid in range */ + if (chid_range_difference > 1) + chid = get_random_u32(working_list[j][0] + 1, working_list[j][1] - 1); + else + continue; + } + + unit_info(m, "BVEC testing for nvgpu_channel_from_id with chid = 0x%08x(%s range [0x%08x - 0x%08x] %s)\n", chid, string_cases[i], working_list[j][0], working_list[j][1], string_states[states]); + ch = nvgpu_channel_from_id(g, chid); + if (i == 0) + unit_assert(ch != NULL, goto done); + else + unit_assert(ch == NULL, goto done); + + /* Clearing for success cases */ + if (ch != NULL) { + nvgpu_channel_put(ch); + ch = NULL; + } + } + } + } + + ret = UNIT_SUCCESS; + +done: + if (ret != UNIT_SUCCESS) { + unit_err(m, "%s failed\n", __func__); + } + + while (--c >= 0 ) { + nvgpu_channel_close(ch_list[c]); + } + + return ret; +} + int test_channel_put_warn(struct unit_module *m, struct gk20a *g, void *vargs) { struct nvgpu_channel *ch = NULL; @@ -1977,6 +2141,7 @@ struct unit_module_test nvgpu_channel_tests[] = { UNIT_TEST(debug_dump, test_channel_debug_dump, &unit_ctx, 0), UNIT_TEST(semaphore_wakeup, test_channel_semaphore_wakeup, &unit_ctx, 0), UNIT_TEST(channel_from_invalid_id, test_channel_from_invalid_id, &unit_ctx, 0), + UNIT_TEST(nvgpu_channel_from_chid_bvec, test_nvgpu_channel_from_id_bvec, &unit_ctx, 0), UNIT_TEST(channel_put_warn, test_channel_put_warn, &unit_ctx, 0), UNIT_TEST(referenceable_cleanup, test_ch_referenceable_cleanup, &unit_ctx, 0), UNIT_TEST(abort_cleanup, test_channel_abort_cleanup, &unit_ctx, 0), diff --git a/userspace/units/fifo/channel/nvgpu-channel.h b/userspace/units/fifo/channel/nvgpu-channel.h index 8d1d39eee..73eb62703 100644 --- a/userspace/units/fifo/channel/nvgpu-channel.h +++ b/userspace/units/fifo/channel/nvgpu-channel.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. + * 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"), @@ -64,17 +64,21 @@ int test_channel_setup_sw(struct unit_module *m, * * Description: Branch coverage for nvgpu_channel_open_new. * - * Test Type: Feature, Error injection + * Test Type: Feature, Error injection, Boundary Value * * Targets: nvgpu_channel_open_new, nvgpu_channel_from_free_chs * * Input: test_fifo_init_support() run for this GPU + * Equivalence classes: + * runlist_id + * - Valid : {0 - 1, 2 - U32_MAX} * * Steps: * - Check that channel can be allocated with nvgpu_channel_open_new: - * - Allocate channel w/ valid runlist_id. - * - Allocate channel w/ invalid runlist_id (nvgpu_channel_open_new - * should set it to GR runlist_id). + * - For runlist ids [0 - 1], channels must be allocated to + * GR engine and Async Engine respectively and for other ranges + * channels should be allocated to GR engine. Verify the same by + * checking the corresponding runlist id for the channel. * - Allocate w/ or w/o is_privileged_channel set. * - Check that aggresive_sync_destroy is set to true, if used channels * is above threshold (by setting threshold and forcing used_channels @@ -143,7 +147,7 @@ int test_channel_close(struct unit_module *m, struct gk20a *g, void *vargs); * * Description: Branch coverage for nvgpu_channel_setup_bind. * - * Test Type: Feature, Error injection, Boundary values + * Test Type: Feature, Error injection, Boundary value * * Targets: nvgpu_channel_setup_bind, nvgpu_channel_setup_usermode, * nvgpu_channel_as_bound, nvgpu_channel_update_runlist @@ -417,6 +421,29 @@ int test_channel_semaphore_wakeup(struct unit_module *m, int test_channel_from_invalid_id(struct unit_module *m, struct gk20a *g, void *vargs); +/** + * Test specification for: nvgpu_channel_from_id + * + * Description: Validate Boundary Values and Equivalence classes for the function + * nvgpu_channel_from_id + * + * Test Type: Boundary Value + * + * Targets: nvgpu_channel_from_id + * + * Input: test_fifo_init_support() run for this GPU + * Equivalence classes: + * chid + * - Invalid : { g->fifo.num_channels - U32_MAX } + * - Valid : { 0 - g->fifo.num_channels - 1 } + * + * Steps: + * - Test corner cases to retrieve channel with invalid channel id. + * + * Output: Returns PASS if all branches gave expected results. FAIL otherwise. + */ +int test_nvgpu_channel_from_id_bvec(struct unit_module *m, + struct gk20a *g, void *args); /** * Test specification for: test_channel_put_warn * diff --git a/userspace/units/fifo/libnvgpu-fifo-common.export b/userspace/units/fifo/libnvgpu-fifo-common.export index 479d0b891..af8c329c6 100644 --- a/userspace/units/fifo/libnvgpu-fifo-common.export +++ b/userspace/units/fifo/libnvgpu-fifo-common.export @@ -1,5 +1,5 @@ # -# Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. +# 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"), diff --git a/userspace/units/fifo/nvgpu-fifo-common.h b/userspace/units/fifo/nvgpu-fifo-common.h index a48552405..ccdcf783c 100644 --- a/userspace/units/fifo/nvgpu-fifo-common.h +++ b/userspace/units/fifo/nvgpu-fifo-common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. + * 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"), diff --git a/userspace/units/fifo/tsg/nvgpu-tsg.c b/userspace/units/fifo/tsg/nvgpu-tsg.c index 11e0468e2..648f21ba9 100644 --- a/userspace/units/fifo/tsg/nvgpu-tsg.c +++ b/userspace/units/fifo/tsg/nvgpu-tsg.c @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -1085,6 +1086,67 @@ done: return ret; } +int test_tsg_check_and_get_from_id_bvec(struct unit_module *m, + struct gk20a *g, void *args) +{ + struct nvgpu_fifo *f = &g->fifo; + int ret = UNIT_FAIL; + u32 valid_tsg_ids[][2] = {{0, f->num_channels - 1}}; + u32 invalid_tsg_ids[][2] = {{f->num_channels, U32_MAX}}; + u32 tsgid, tsgid_range_len; + u32 (*working_list)[2]; + /* + * i is to loop through valid and invalid cases + * j is to loop through different ranges within ith case + * states is for min, max and median + */ + u32 i, j, states; + const char *string_cases[] = {"Valid", "Invalid"}; + const char *string_states[] = {"Min", "Max", "Mid"}; + u32 tsgid_range_difference; + + /* loop through valid and invalid cases */ + for (i = 0; i < 2; i++) { + /* select appropriate iteration size */ + tsgid_range_len = (i == 0) ? ARRAY_SIZE(valid_tsg_ids) : ARRAY_SIZE(invalid_tsg_ids); + /* select correct working list */ + working_list = (i == 0) ? valid_tsg_ids : invalid_tsg_ids; + for (j = 0; j < tsgid_range_len; j++) { + for (states = 0; states < 3; states++) { + /* check for min tsgid */ + if (states == 0) + tsgid = working_list[j][0]; + else if (states == 1) { + /* check for max tsgid */ + tsgid = working_list[j][1]; + } else { + tsgid_range_difference = working_list[j][1] - working_list[j][0]; + /* Check for random tsgid in range */ + if (tsgid_range_difference > 1) + tsgid = get_random_u32(working_list[j][0] + 1, working_list[j][1] - 1); + else + continue; + } + + unit_info(m, "BVEC testing for nvgpu_tsg_check_and_get_from_id with tsgid = 0x%08x(%s range [0x%08x - 0x%08x] %s)\n", tsgid, string_cases[i], working_list[j][0], working_list[j][1], string_states[states]); + + if (i == 0) + unit_assert(nvgpu_tsg_check_and_get_from_id(g, tsgid) != NULL, goto done); + else + unit_assert(nvgpu_tsg_check_and_get_from_id(g,tsgid) == NULL, goto done); + } + } + } + + ret = UNIT_SUCCESS; +done: + if (ret != UNIT_SUCCESS) { + unit_err(m, "%s failed\n", __func__); + } + + return ret; +} + #define F_TSG_ABORT_CH_ABORT_CLEANUP_NULL BIT(0) #define F_TSG_ABORT_PREEMPT BIT(1) #define F_TSG_ABORT_CH BIT(2) @@ -1364,6 +1426,100 @@ done: return ret; } +int test_nvgpu_tsg_set_error_notifier_bvec(struct unit_module *m, + struct gk20a *g, void *args) +{ + struct nvgpu_tsg *tsg = NULL; + struct nvgpu_channel *ch = NULL; + int ret = 0; + + u32 valid_error_notifier_ids[][2] = {{NVGPU_ERR_NOTIFIER_FIFO_ERROR_IDLE_TIMEOUT, NVGPU_ERR_NOTIFIER_PBDMA_PUSHBUFFER_CRC_MISMATCH}}; + u32 invalid_error_notifier_ids[][2] = {{NVGPU_ERR_NOTIFIER_PBDMA_PUSHBUFFER_CRC_MISMATCH + 1, U32_MAX}}; + u32 (*working_list)[2]; + u32 error_code, error_notifier_range_len; + /* + * i is to loop through valid and invalid cases + * j is to loop through different ranges within ith case + * states is for min, max and median + */ + u32 i, j, states; + const char *string_cases[] = {"Valid", "Invalid"}; + const char *string_states[] = {"Min", "Max", "Mid"}; + u32 tsgid_range_difference; + + struct nvgpu_posix_channel ch_priv; + + tsg = nvgpu_tsg_open(g, getpid()); + unit_assert(tsg != NULL, goto done); + + ch = nvgpu_channel_open_new(g, ~0U, false, getpid(), getpid()); + unit_assert(ch != NULL, goto done); + + ch->os_priv = &ch_priv; + ch_priv.err_notifier.error = 0U; + + ret = nvgpu_tsg_bind_channel(tsg, ch); + unit_assert(ret == 0, goto done); + + ret = UNIT_FAIL; + + /* loop through valid and invalid cases */ + for (i = 0; i < 2; i++) { + /* select appropriate iteration size */ + error_notifier_range_len = (i == 0) ? ARRAY_SIZE(valid_error_notifier_ids) : ARRAY_SIZE(invalid_error_notifier_ids); + /* select correct working list */ + working_list = (i == 0) ? valid_error_notifier_ids : invalid_error_notifier_ids; + for (j = 0; j < error_notifier_range_len; j++) { + for (states = 0; states < 3; states++) { + /* check for min error code */ + if (states == 0) + error_code = working_list[j][0]; + else if (states == 1) { + /* check for max error code */ + error_code = working_list[j][1]; + } else { + tsgid_range_difference = working_list[j][1] - working_list[j][0]; + /* Check for random error code in range */ + if (tsgid_range_difference > 1) + error_code = get_random_u32(working_list[j][0] + 1, working_list[j][1] - 1); + else + continue; + } + + ch_priv.err_notifier.error = 0; + ch_priv.err_notifier.status = 0; + + unit_info(m, "BVEC testing for nvgpu_tsg_set_error_notifier with id = 0x%08x(%s range [0x%08x - 0x%08x] %s)\n", error_code, string_cases[i], working_list[j][0], working_list[j][1], string_states[states]); + + nvgpu_tsg_set_error_notifier(g, tsg, error_code); + if (i == 0) { + unit_assert(ch_priv.err_notifier.error == error_code, goto done); + } else { + unit_assert(ch_priv.err_notifier.error != error_code , goto done); + } + + } + } + } + + ret = UNIT_SUCCESS; +done: + if (ret != UNIT_SUCCESS) { + unit_err(m, "%s failed\n", __func__); + } + + if (ch != NULL) { + nvgpu_channel_close(ch); + ch = NULL; + } + if (tsg != NULL) { + nvgpu_ref_put(&tsg->refcount, nvgpu_tsg_release); + tsg = NULL; + } + + return ret; +} + int test_tsg_set_ctx_mmu_error(struct unit_module *m, struct gk20a *g, void *args) { @@ -1489,6 +1645,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(get_from_id_bvec, test_tsg_check_and_get_from_id_bvec, &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, @@ -1498,6 +1655,7 @@ struct unit_module_test nvgpu_tsg_tests[] = { UNIT_TEST(enable_disable, test_tsg_enable, &unit_ctx, 0), UNIT_TEST(abort, test_tsg_abort, &unit_ctx, 0), UNIT_TEST(mark_error, test_tsg_mark_error, &unit_ctx, 0), + UNIT_TEST(bvec_nvgpu_tsg_set_error_notifier, test_nvgpu_tsg_set_error_notifier_bvec, &unit_ctx, 0), UNIT_TEST(set_ctx_mmu_error, test_tsg_set_ctx_mmu_error, &unit_ctx, 0), UNIT_TEST(reset_faulted_eng_pbdma, test_tsg_reset_faulted_eng_pbdma, &unit_ctx, 0), UNIT_TEST(remove_support, test_fifo_remove_support, &unit_ctx, 0), diff --git a/userspace/units/fifo/tsg/nvgpu-tsg.h b/userspace/units/fifo/tsg/nvgpu-tsg.h index 14ac4ead8..c90b7190f 100644 --- a/userspace/units/fifo/tsg/nvgpu-tsg.h +++ b/userspace/units/fifo/tsg/nvgpu-tsg.h @@ -297,6 +297,33 @@ int test_tsg_enable(struct unit_module *m, int test_tsg_check_and_get_from_id(struct unit_module *m, struct gk20a *g, void *args); +/** + * Test specification for: test_tsg_check_and_get_from_id + * + * Description: This test will validate boundary values for + * the function nvgpu_tsg_check_and_get_from_id + * + * Test Type: Boundary Values + * + * Targets: nvgpu_tsg_check_and_get_from_id + * + * Input: test_fifo_init_support() run for this GPU + * Equivalence classes: + * tsgid + * - Invalid : {(&g->fifo->num_channels - 1) - U32_MAX } + * - Valid : { 0 - (&g->fifo->num_channels - 1) } + * + * Steps: + * - Check that nvgpu_tsg_check_and_get_from_id returns NULL for + * any invalid tsgid. + * - Check that nvgpu_tsg_check_and_get_from_id returns correct + * tsg pointer for any valid tsgid. + * + * Output: Returns PASS if all branches gave expected results. FAIL otherwise. + */ +int test_tsg_check_and_get_from_id_bvec(struct unit_module *m, + struct gk20a *g, void *args); + /** * Test specification for: test_tsg_abort * @@ -374,6 +401,33 @@ int test_tsg_setup_sw(struct unit_module *m, int test_tsg_mark_error(struct unit_module *m, struct gk20a *g, void *args); +/** + * Test specification for: nvgpu_tsg_set_error_notifier + * + * Description: This test will verify the boundary values for the function + * nvgpu_tsg_set_error_notifier + * + * Test Type: Boundary Value + * + * Targets: nvgpu_tsg_set_error_notifier + * + * Input: None + * Equivalence classes: + * error_notifier + * - Invalid : { NVGPU_ERR_NOTIFIER_PBDMA_PUSHBUFFER_CRC_MISMATCH + 1, U32_MAX } + * - Valid : { NVGPU_ERR_NOTIFIER_FIFO_ERROR_IDLE_TIMEOUT, NVGPU_ERR_NOTIFIER_PBDMA_PUSHBUFFER_CRC_MISMATCH } + * + * Steps: + * Check likely cases: + * - Use one TSG with one bound channel for minimum, median and maximum values + * from valid classes. + * - Use one TSG with one bound channel for minimum, maximum and one other random value + * from invalid classes. + * + * Output: Returns PASS if all branches gave expected results. FAIL otherwise. + */ +int test_nvgpu_tsg_set_error_notifier_bvec(struct unit_module *m, + struct gk20a *g, void *args); /** * Test specification for: test_tsg_set_ctx_mmu_error *