diff --git a/Makefile.umbrella.tmk b/Makefile.umbrella.tmk index 3ee97ffb4..7a2fcb952 100644 --- a/Makefile.umbrella.tmk +++ b/Makefile.umbrella.tmk @@ -43,6 +43,7 @@ NV_REPOSITORY_COMPONENTS += userspace/units/posix/sizes NV_REPOSITORY_COMPONENTS += userspace/units/init NV_REPOSITORY_COMPONENTS += userspace/units/posix/thread NV_REPOSITORY_COMPONENTS += userspace/units/posix/cond +NV_REPOSITORY_COMPONENTS += userspace/units/posix/timers NV_REPOSITORY_COMPONENTS += userspace/units/interface/bsearch NV_REPOSITORY_COMPONENTS += userspace/units/interface/lock NV_REPOSITORY_COMPONENTS += userspace/units/interface/atomic diff --git a/drivers/gpu/nvgpu/libnvgpu-drv_safe.export b/drivers/gpu/nvgpu/libnvgpu-drv_safe.export index 6e5a4daf4..e50efce11 100644 --- a/drivers/gpu/nvgpu/libnvgpu-drv_safe.export +++ b/drivers/gpu/nvgpu/libnvgpu-drv_safe.export @@ -97,6 +97,7 @@ nvgpu_gr_config_set_sm_info_sm_index nvgpu_gr_config_get_sm_info_sm_index nvgpu_gr_config_set_gpc_tpc_mask nvgpu_gr_config_get_gpc_tpc_mask +nvgpu_hr_timestamp nvgpu_can_busy nvgpu_channel_alloc_inst nvgpu_channel_cleanup_sw @@ -123,6 +124,9 @@ nvgpu_cond_signal_interruptible nvgpu_cond_signal_locked nvgpu_cond_timedwait nvgpu_cond_unlock +nvgpu_current_time_ms +nvgpu_current_time_ns +nvgpu_current_time_us nvgpu_detect_chip nvgpu_dma_alloc nvgpu_dma_alloc_get_fault_injection @@ -197,6 +201,7 @@ nvgpu_mm_get_available_big_page_sizes nvgpu_mm_get_default_big_page_size nvgpu_mm_setup_hw nvgpu_mm_suspend +nvgpu_msleep nvgpu_mutex_acquire nvgpu_mutex_destroy nvgpu_mutex_init @@ -248,6 +253,9 @@ nvgpu_readl nvgpu_readl_impl nvgpu_runlist_construct_locked nvgpu_rwsem_init +nvgpu_timeout_expired_msg_impl +nvgpu_timeout_init +nvgpu_timeout_peek_expired nvgpu_tsg_abort nvgpu_tsg_bind_channel nvgpu_tsg_check_and_get_from_id @@ -282,8 +290,10 @@ nvgpu_thread_is_running nvgpu_thread_should_stop nvgpu_thread_stop nvgpu_thread_stop_graceful +nvgpu_udelay nvgpu_userd_init_slabs nvgpu_usermode_writel +nvgpu_usleep_range nvgpu_vfree_impl nvgpu_vm_area_alloc nvgpu_vm_area_free diff --git a/userspace/Makefile.sources b/userspace/Makefile.sources index 67c763644..7da681f5d 100644 --- a/userspace/Makefile.sources +++ b/userspace/Makefile.sources @@ -50,6 +50,7 @@ UNITS := \ $(UNIT_SRC)/posix/sizes \ $(UNIT_SRC)/posix/thread \ $(UNIT_SRC)/posix/cond \ + $(UNIT_SRC)/posix/timers \ $(UNIT_SRC)/pramin \ $(UNIT_SRC)/init \ $(UNIT_SRC)/interface/bsearch \ diff --git a/userspace/units/posix/timers/Makefile b/userspace/units/posix/timers/Makefile new file mode 100644 index 000000000..9f4240307 --- /dev/null +++ b/userspace/units/posix/timers/Makefile @@ -0,0 +1,26 @@ +# Copyright (c) 2019, 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. + +.SUFFIXES: + +OBJS = posix-timers.o +MODULE = posix-timers + +include ../../Makefile.units diff --git a/userspace/units/posix/timers/Makefile.interface.tmk b/userspace/units/posix/timers/Makefile.interface.tmk new file mode 100644 index 000000000..ebf09d4b7 --- /dev/null +++ b/userspace/units/posix/timers/Makefile.interface.tmk @@ -0,0 +1,35 @@ +################################### tell Emacs this is a -*- makefile-gmake -*- +# +# Copyright (c) 2019, 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. +# +# tmake for SW Mobile component makefile +# +############################################################################### + +NVGPU_UNIT_NAME=posix-timers + +include $(NV_COMPONENT_DIR)/../../Makefile.units.common.interface.tmk + +# Local Variables: +# indent-tabs-mode: t +# tab-width: 8 +# End: +# vi: set tabstop=8 noexpandtab: diff --git a/userspace/units/posix/timers/Makefile.tmk b/userspace/units/posix/timers/Makefile.tmk new file mode 100644 index 000000000..e422fe1b7 --- /dev/null +++ b/userspace/units/posix/timers/Makefile.tmk @@ -0,0 +1,35 @@ +################################### tell Emacs this is a -*- makefile-gmake -*- +# +# Copyright (c) 2019, 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. +# +# tmake for SW Mobile component makefile +# +############################################################################### + +NVGPU_UNIT_NAME=posix-timers + +include $(NV_COMPONENT_DIR)/../../Makefile.units.common.tmk + +# Local Variables: +# indent-tabs-mode: t +# tab-width: 8 +# End: +# vi: set tabstop=8 noexpandtab: diff --git a/userspace/units/posix/timers/posix-timers.c b/userspace/units/posix/timers/posix-timers.c new file mode 100644 index 000000000..9194ea621 --- /dev/null +++ b/userspace/units/posix/timers/posix-timers.c @@ -0,0 +1,345 @@ +/* + * Copyright (c) 2019, 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 + +#include +#include + +#include +#include "posix-timers.h" + +struct test_timer_args { + bool counter_timer; +}; + +static struct test_timer_args init_args = { + .counter_timer = true, +}; + +#define TEST_TIMER_COUNT 10 + +/* The value should be kept below 999 since it is used to calculate + * the duration paramater to usleep. This will ensure that the duration + * value passed to usleep is less than 1000000. + */ +#define TEST_TIMER_DURATION 10 + +static struct nvgpu_timeout test_timeout; + +int test_timer_init(struct unit_module *m, + struct gk20a *g, void *args) +{ + int ret; + unsigned int duration; + unsigned long flags; + struct test_timer_args *test_args = (struct test_timer_args *)args; + + if (test_args->counter_timer == true) { + duration = TEST_TIMER_COUNT; + flags = NVGPU_TIMER_RETRY_TIMER; + } else { + duration = TEST_TIMER_DURATION; + flags = NVGPU_TIMER_CPU_TIMER; + } + + ret = nvgpu_timeout_init(g, &test_timeout, + duration, + flags); + + if (ret != 0) { + unit_return_fail(m, "Timer init failed %d\n", ret); + } + + if (test_timeout.g != g) { + unit_return_fail(m, "Timer g struct mismatch %d\n", ret); + } + + if (test_timeout.flags != flags) { + unit_return_fail(m, "Timer flags mismatch %d\n", ret); + } + + return UNIT_SUCCESS; +} + +int test_timer_init_err(struct unit_module *m, + struct gk20a *g, void *args) +{ + int ret, i; + + for (i = 0; i < 12; i++) { + memset(&test_timeout, 0, sizeof(struct nvgpu_timeout)); + /* nvgpu_tiemout_init accepts only BIT(0), BIT(8), and BIT(9) as + * valid flag bits. So ret should be EINVAL */ + ret = nvgpu_timeout_init(g, &test_timeout, 10, (1 << i)); + + if ((i == 0) || (i == 8) || (i == 9)) { + if (ret != 0) { + unit_return_fail(m, + "Timer init failed %d\n", + ret); + } + } else { + if (ret != -EINVAL) { + unit_return_fail(m, + "Timer init with invalid flag %d\n", + ret); + } + } + } + + /* BIT(0), BIT(8) and BIT(9) set. Return value should be 0 */ + ret = nvgpu_timeout_init(g, &test_timeout, 10, 0x301); + if (ret != 0) { + unit_return_fail(m,"Timer init failed with flag 0x301\n"); + } + + /* BIT(8) and BIT(9) set. Return value should be 0 */ + ret = nvgpu_timeout_init(g, &test_timeout, 10, 0x300); + if (ret != 0) { + unit_return_fail(m,"Timer init failed with flag 0x300\n"); + } + + /* BIT(0) and BIT(8) set. Return value should be 0 */ + ret = nvgpu_timeout_init(g, &test_timeout, 10, 0x101); + if (ret != 0) { + unit_return_fail(m,"Timer init failed with flag 0x101\n"); + } + + /* BIT(0) and BIT(9) set. Return value should be 0 */ + ret = nvgpu_timeout_init(g, &test_timeout, 10, 0x201); + if (ret != 0) { + unit_return_fail(m,"Timer init failed with flag 0x201\n"); + } + + /* BIT(0), BIT(7) and BIT(9) set. Return value should be -EINVAL */ + ret = nvgpu_timeout_init(g, &test_timeout, 10, 0x281); + if (ret != -EINVAL) { + unit_return_fail(m,"Timer init failed with flag 0x281\n"); + } + + /* BIT(5), BIT(7) and BIT(9) set. Return value should be -EINVAL */ + ret = nvgpu_timeout_init(g, &test_timeout, 10, 0x2A0); + if (ret != -EINVAL) { + unit_return_fail(m,"Timer init failed with flag 0x2A0\n"); + } + + /* BIT(1), BIT(2) and BIT(3) set. Return value should be -EINVAL */ + ret = nvgpu_timeout_init(g, &test_timeout, 10, 0x00E); + if (ret != -EINVAL) { + unit_return_fail(m,"Timer init failed with flag 0x00E\n"); + } + + /* BIT(1) to BIT(7) set. Return value should be -EINVAL */ + ret = nvgpu_timeout_init(g, &test_timeout, 10, 0x07E); + if (ret != -EINVAL) { + unit_return_fail(m,"Timer init failed with flag 0x07E\n"); + } + + /* All bits set. Return value should be -EINVAL */ + ret = nvgpu_timeout_init(g, &test_timeout, 10, 0xFFFFFFFFFFFFFFFF); + if (ret != -EINVAL) { + unit_return_fail(m,"Timer init failed with flag all 1s\n"); + } + + return UNIT_SUCCESS; +} + +int test_timer_counter(struct unit_module *m, + struct gk20a *g, void *args) +{ + int ret; + + memset(&test_timeout, 0, sizeof(struct nvgpu_timeout)); + + ret = nvgpu_timeout_init(g, &test_timeout, + TEST_TIMER_COUNT, + NVGPU_TIMER_RETRY_TIMER); + + if (ret != 0) { + unit_return_fail(m, "Timer init failed %d\n", ret); + } + + do { + usleep(1); + } while (nvgpu_timeout_expired(&test_timeout) == 0); + + if (!nvgpu_timeout_peek_expired(&test_timeout)) { + unit_return_fail(m, "Counter mismatch %d\n", + test_timeout.retries.attempted); + } + + return UNIT_SUCCESS; +} + +int test_timer_duration(struct unit_module *m, + struct gk20a *g, void *args) +{ + int ret; + + memset(&test_timeout, 0, sizeof(struct nvgpu_timeout)); + + ret = nvgpu_timeout_init(g, &test_timeout, + TEST_TIMER_DURATION, + NVGPU_TIMER_CPU_TIMER); + + if (ret != 0) { + unit_return_fail(m, "Timer init failed %d\n", ret); + } + + /* Sleep for TEST_TIMER_DURATION */ + usleep((TEST_TIMER_DURATION * 1000)); + + do { + usleep(10); + ret = nvgpu_timeout_expired(&test_timeout); + + } while (ret == 0); + + if (ret != -ETIMEDOUT) { + unit_return_fail(m, "Duration timer not expired %d\n", ret); + } + + if (!nvgpu_timeout_peek_expired(&test_timeout)) { + unit_return_fail(m, "Duration failure\n"); + } + + return UNIT_SUCCESS; +} + +int test_timer_delay(struct unit_module *m, + struct gk20a *g, void *args) +{ + signed long ts_before, ts_after, delay; + + ts_before = nvgpu_current_time_us(); + nvgpu_udelay(5000); + ts_after = nvgpu_current_time_us(); + + delay = ts_after - ts_before; + delay /= 1000; + + if (delay < 5) { + unit_return_fail(m, + "Delay Duration incorrect\n"); + } + + ts_before = nvgpu_current_time_us(); + nvgpu_usleep_range(5000, 10000); + ts_after = nvgpu_current_time_us(); + + delay = ts_after - ts_before; + delay /= 1000; + + if (delay < 5) { + unit_return_fail(m, + "Delay Duration incorrect\n"); + } + + return UNIT_SUCCESS; +} + +int test_timer_msleep(struct unit_module *m, + struct gk20a *g, void *args) +{ + signed long ts_before, ts_after, delay; + + delay = 0; + + ts_before = nvgpu_current_time_ms(); + nvgpu_msleep(5); + ts_after = nvgpu_current_time_ms(); + + delay = ts_after - ts_before; + + if (delay < 5) { + unit_return_fail(m, "Sleep Duration incorrect\n"); + } + + return UNIT_SUCCESS; +} + +int test_timer_hrtimestamp(struct unit_module *m, + struct gk20a *g, void *args) +{ + unsigned long cycles_read, cycles_bkp; + int i; + + cycles_read = 0; + cycles_bkp = 0; + + for (i = 0; i < 50; i++) { + cycles_read = nvgpu_hr_timestamp(); + + if (cycles_read < cycles_bkp) { + unit_return_fail(m, + "HR cycle value error %ld < %ld\n", + cycles_read, cycles_bkp); + } + + cycles_bkp = cycles_read; + usleep(1); + } + + return UNIT_SUCCESS; +} + +int test_timer_compare(struct unit_module *m, + struct gk20a *g, void *args) +{ + int i; + signed long time_ms, time_ns; + + i = 0; + time_ms = 0; + time_ns = 0; + + while (i < 10) { + time_ms = nvgpu_current_time_ms(); + time_ns = nvgpu_current_time_ns(); + + time_ns /= 1000000; + + if (time_ns < time_ms) { + unit_return_fail(m, + "Err, ms and ns mismatch\n"); + } + i++; + usleep(1000); + } + + return UNIT_SUCCESS; +} + +struct unit_module_test posix_timers_tests[] = { + UNIT_TEST(init, test_timer_init, &init_args, 0), + UNIT_TEST(init_err, test_timer_init_err, NULL, 0), + UNIT_TEST(counter, test_timer_counter, NULL, 0), + UNIT_TEST(duration, test_timer_duration, NULL, 0), + UNIT_TEST(delay, test_timer_delay, NULL, 0), + UNIT_TEST(msleep, test_timer_msleep, NULL, 0), + UNIT_TEST(hr_cycles, test_timer_hrtimestamp, NULL, 0), + UNIT_TEST(compare, test_timer_compare, NULL, 0), +}; + +UNIT_MODULE(posix_timers, posix_timers_tests, UNIT_PRIO_POSIX_TEST); diff --git a/userspace/units/posix/timers/posix-timers.h b/userspace/units/posix/timers/posix-timers.h new file mode 100644 index 000000000..b704b09b2 --- /dev/null +++ b/userspace/units/posix/timers/posix-timers.h @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2019, 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. + */ + +/** + * @addtogroup SWUTS-posix-timers + * @{ + * + * Software Unit Test Specification for posix-timers + */ +#ifndef __UNIT_POSIX_TIMERS_H__ +#define __UNIT_POSIX_TIMERS_H__ + +/** + * Test specification for test_timer_init + * + * Description: Test the timer initialization routine. + * + * Test Type: Feature based. + * + * Inputs: + * 1) The type of timer to be tested is passed as an argument to the test. + * 2) Global defines for flag and duration values. + * 3) Global nvgpu_timeout structure instance. + * + * Steps: + * 1) Check for the type of timer to be tested. + * 2) Populate the flags and duration values depending on the timer type. + * 3) Invoke the timer init function. + * 4) Check the return value for errors. + * 5) Check the internal parameters in nvgpu_timeout structure to ensure + * proper initialisation. + * + * Output: + * The test returns PASS if the return value from timer init function + * indicates success and the internal parameter values in nvgpu_timeout + * structure is initialised as per the passed arguments. + * Test returns FAIL if timer init function fails or if any of the + * parameters inside the nvgpu_timeout struct is not initialised properly. + * + */ +int test_timer_init(struct unit_module *m, + struct gk20a *g, void *args); + +/** + * Test specification for test_timer_init_err + * + * Description: Test the timer initialisation routine error path. + * + * Test Type: Boundary Value analysis. + * + * Inputs: + * 1) Global nvgpu_timeout structure instance. + * + * Steps: + * 1) Invoke timer initialisation routine in loop with different value for + * flags parameter for each invocation. + * 2) Check for the corresponding return value. The timer initialisation + * function should return error for invalid flag values and return success + * for valid flag values. + * + * Output: + * The test returns PASS if the initialisation routine returns an appropriate + * return value as per the flag value passed for each invocation. + * The test returns FAIL if the initialisation routine does not return the + * expected value for a particular flag for any of the invocation. + * + */ +int test_timer_init_err(struct unit_module *m, + struct gk20a *g, void *args); + +/** + * Test specification for test_timer_counter + * + * Description: Test the counter based timer functionality. + * + * Test Type: Feature based. + * + * Input: + * 1) Global nvgpu_timeout structure instance. + * 2) Global defines for flag and duration parameters. + * + * Steps: + * 1) Reset the global nvgpu_timeout structure with all 0s. + * 2) Initialise the timeout structure. + * 3) Check the return value for error. + * 4) Loop and check for the timer expiry. Sleep is introduced + * between each loop. + * 5) Confirm the status of the timer expiry by verifying the + * counter value. + * + * Output: + * Test returns PASS if the timer expires after the programmed + * counter value. + * Test returns FAIL if the initialisation routine returns error or + * timer expires before the programmed counter value is reached. + * + */ +int test_timer_counter(struct unit_module *m, + struct gk20a *g, void *args); + +/** + * Test specification for test_timer_duration + * + * Description: Test the duration based timer functionality. + * + * Test Type: Feature based. + * + * Input: + * 1) Global nvgpu_timeout structure instance. + * 2) Global defines for flag and duration parameters. + * + * Steps: + * 1) Reset the global nvgpu_timeout structure to all 0s. + * 2) Initialise the timeout structure. + * 3) Check the return value for error. + * 4) Sleep for the required duration + 500ms to ensure the timer expires. + * 5) Check for the timer status. + * 6) Reconfirm the timer status. + * + * Output: + * Test returns PASS if the timer expires after the programmed + * duration. + * Test returns FAIL if the initialisation routine returns error or if + * the timer does not expire even after the programmed duration. + * + */ +int test_timer_duration(struct unit_module *m, + struct gk20a *g, void *args); + +/** + * Test specification for test_timer_delay + * + * Description: Test the delay functionality. + * + * Test Type: Feature based. + * + * Input: None. + * + * Steps: + * 1) Get the current time in us. + * 2) Delay the execution using nvpgu_udelay function. + * 3) Get the time after the delay function is executed. + * 4) Calculate the difference between both timestamps. + * 5) Convert it into msec. + * 6) If the difference is less than the duration for which the + * delay was requested, return fail. + * 7) Continue steps 1-6 for the wrapper api nvgpu_usleep_range + * which internally uses nvgpu_udelay itself. + * + * Output: + * Test returns PASS if the delay function actually delays the execution + * for required amount of time. It also returns PASS if there is a + * reordering of instructions resulting in the test check being invalid + * and the test is skipped by returning PASS. + * Test returns FAIL if the delay function returns before the required + * duration. + * + */ +int test_timer_delay(struct unit_module *m, + struct gk20a *g, void *args); + +/** + * Test specification for test_timer_msleep + * + * Description: Test the sleep functionality. + * + * Test Type: Feature based. + * + * Input: None. + * + * Steps: + * 1) Get the current time in ms. + * 2) Call sleep function for 5ms. + * 3) Get the time after the sleep call. + * 4) Calculate the difference between both the timestamps. + * 5) Compare the difference to deduce the test result. + * + * Output: + * Test returns PASS if the sleep function is completed for required duration. + * Test returns FAIL if the sleep function returns before the requested + * duration. + * + */ +int test_timer_msleep(struct unit_module *m, + struct gk20a *g, void *args); + +/** + * Test specification for test_timer_hrtimestamp + * + * Description: Test the high resolution counter based functionalities. + * + * Test Type: Feature based. + * + * Input: None. + * + * Steps: + * 1) Initialise two counter variables to 0. + * 2) Read the value of HR counter into one of the counter variables. + * 3) Compare the value of read counter value with the bkp counter value. + * 4) If read counter variable is less than the previously read counter value + * return fail. + * 5) Store the read counter value in bkp counter value. + * 6) Suspend execution by calling usleep. + * 7) Loop steps 1 - 6 for multiple times. + * + * Output: + * Test returns PASS if for every read of HR counter, the value returned is + * either greater than or equal to the previous value. + * Test returns FAIL if any of the subsequent read of HR counter returns + * a value less than the previous value. + * + */ +int test_timer_hrtimestamp(struct unit_module *m, + struct gk20a *g, void *args); + +/** + * Test specification for test_timer_compare + * + * Description: Compare the timers in various resoutions. + * + * Test Type: Feature based. + * + * Input: None. + * + * Steps: + * 1) Initialise two timestamp variables. + * 2) Read the time in ms and store in one timestamp variable. + * 3) Read the time in ns and store in the second timestamp variable. + * 4) Do the necessary conversion to make both timers in same resolution. + * 5) Compare the timer values to determine the test results. + * + * Output: + * Test returns PASS if various timer resolutions match each other. + * Test returns FAIL if various timer resolutions does not match with + * each other. + * + */ +int test_timer_compare(struct unit_module *m, + struct gk20a *g, void *args); + +#endif /* __UNIT_POSIX_TIMERS_H__ */