From 245cf29bc03fb0a4f1d2b5b9746e738b80ff2218 Mon Sep 17 00:00:00 2001 From: ajesh Date: Wed, 29 Jan 2020 23:14:30 +0530 Subject: [PATCH] gpu: nvgpu: add tests for kref Add unit tests for kref unit. Jira NVGPU-4417 Change-Id: Ie5c6efc72b95aa1f200a59fd9184f20e65548fee Signed-off-by: ajesh Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2287553 Tested-by: mobile promotions Reviewed-by: mobile promotions --- Makefile.umbrella.tmk | 1 + userspace/Makefile.sources | 1 + userspace/SWUTS.h | 1 + userspace/SWUTS.sources | 1 + userspace/required_tests.json | 30 +++ userspace/units/interface/kref/Makefile | 26 +++ .../interface/kref/Makefile.interface.tmk | 23 ++ userspace/units/interface/kref/Makefile.tmk | 24 ++ userspace/units/interface/kref/kref.c | 210 ++++++++++++++++++ userspace/units/interface/kref/kref.h | 180 +++++++++++++++ 10 files changed, 497 insertions(+) create mode 100644 userspace/units/interface/kref/Makefile create mode 100644 userspace/units/interface/kref/Makefile.interface.tmk create mode 100644 userspace/units/interface/kref/Makefile.tmk create mode 100644 userspace/units/interface/kref/kref.c create mode 100644 userspace/units/interface/kref/kref.h diff --git a/Makefile.umbrella.tmk b/Makefile.umbrella.tmk index b24292ca5..22621085b 100644 --- a/Makefile.umbrella.tmk +++ b/Makefile.umbrella.tmk @@ -70,6 +70,7 @@ NV_REPOSITORY_COMPONENTS += userspace/units/interface/rbtree NV_REPOSITORY_COMPONENTS += userspace/units/interface/static_analysis NV_REPOSITORY_COMPONENTS += userspace/units/interface/string NV_REPOSITORY_COMPONENTS += userspace/units/interface/worker +NV_REPOSITORY_COMPONENTS += userspace/units/interface/kref NV_REPOSITORY_COMPONENTS += userspace/units/bus NV_REPOSITORY_COMPONENTS += userspace/units/pramin NV_REPOSITORY_COMPONENTS += userspace/units/priv_ring diff --git a/userspace/Makefile.sources b/userspace/Makefile.sources index a88499527..6911a00a5 100644 --- a/userspace/Makefile.sources +++ b/userspace/Makefile.sources @@ -71,6 +71,7 @@ UNITS := \ $(UNIT_SRC)/interface/static_analysis \ $(UNIT_SRC)/interface/string \ $(UNIT_SRC)/interface/worker \ + $(UNIT_SRC)/interface/kref \ $(UNIT_SRC)/mc \ $(UNIT_SRC)/mm/nvgpu_sgt \ $(UNIT_SRC)/mm/allocators/buddy_allocator \ diff --git a/userspace/SWUTS.h b/userspace/SWUTS.h index 9da69f6c7..11b72d081 100644 --- a/userspace/SWUTS.h +++ b/userspace/SWUTS.h @@ -39,6 +39,7 @@ * - @ref SWUTS-interface-static_analysis * - @ref SWUTS-interface-string * - @ref SWUTS-interface-worker + * - @ref SWUTS-interface-kref * - @ref SWUTS-bus * - @ref SWUTS-falcon * - @ref SWUTS-netlist diff --git a/userspace/SWUTS.sources b/userspace/SWUTS.sources index f6754ea3c..bd146691a 100644 --- a/userspace/SWUTS.sources +++ b/userspace/SWUTS.sources @@ -10,6 +10,7 @@ INPUT += ../../../userspace/units/interface/rbtree/rbtree.h INPUT += ../../../userspace/units/interface/static_analysis/static_analysis.h INPUT += ../../../userspace/units/interface/string/nvgpu-string.h INPUT += ../../../userspace/units/interface/worker/worker.h +INPUT += ../../../userspace/units/interface/kref/kref.h INPUT += ../../../userspace/units/bus/nvgpu-bus.h INPUT += ../../../userspace/units/falcon/falcon_tests/nvgpu-falcon.h INPUT += ../../../userspace/units/netlist/nvgpu-netlist.h diff --git a/userspace/required_tests.json b/userspace/required_tests.json index 4a62489e8..3bc85c9d8 100644 --- a/userspace/required_tests.json +++ b/userspace/required_tests.json @@ -1229,6 +1229,36 @@ "unit": "interface_bsearch", "test_level": 0 }, + { + "test": "test_kref_init", + "case": "kref_init", + "unit": "interface_kref", + "test_level": 0 + }, + { + "test": "test_kref_get", + "case": "kref_get", + "unit": "interface_kref", + "test_level": 0 + }, + { + "test": "test_kref_get_unless", + "case": "kref_get_unless", + "unit": "interface_kref", + "test_level": 0 + }, + { + "test": "test_kref_put", + "case": "kref_put", + "unit": "interface_kref", + "test_level": 0 + }, + { + "test": "test_kref_put_return", + "case": "kref_put_return", + "unit": "interface_kref", + "test_level": 0 + }, { "test": "test_lock_acquire_release", "case": "mutex_acquire_release", diff --git a/userspace/units/interface/kref/Makefile b/userspace/units/interface/kref/Makefile new file mode 100644 index 000000000..0df9b02ac --- /dev/null +++ b/userspace/units/interface/kref/Makefile @@ -0,0 +1,26 @@ +# Copyright (c) 2020, 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 = kref.o +MODULE = kref + +include ../../Makefile.units diff --git a/userspace/units/interface/kref/Makefile.interface.tmk b/userspace/units/interface/kref/Makefile.interface.tmk new file mode 100644 index 000000000..7b3264e78 --- /dev/null +++ b/userspace/units/interface/kref/Makefile.interface.tmk @@ -0,0 +1,23 @@ +################################### tell Emacs this is a -*- makefile-gmake -*- +# +# Copyright (c) 2020, NVIDIA CORPORATION. All Rights Reserved. +# +# NVIDIA CORPORATION and its licensors retain all intellectual property +# and proprietary rights in and to this software, related documentation +# and any modifications thereto. Any use, reproduction, disclosure or +# distribution of this software and related documentation without an express +# license agreement from NVIDIA CORPORATION is strictly prohibited. +# +# tmake for SW Mobile component makefile +# +############################################################################### + +NVGPU_UNIT_NAME=kref + +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/interface/kref/Makefile.tmk b/userspace/units/interface/kref/Makefile.tmk new file mode 100644 index 000000000..4e7f96410 --- /dev/null +++ b/userspace/units/interface/kref/Makefile.tmk @@ -0,0 +1,24 @@ +################################### tell Emacs this is a -*- makefile-gmake -*- +# +# Copyright (c) 2020, NVIDIA CORPORATION. All Rights Reserved. +# +# NVIDIA CORPORATION and its licensors retain all intellectual property +# and proprietary rights in and to this software, related documentation +# and any modifications thereto. Any use, reproduction, disclosure or +# distribution of this software and related documentation without an express +# license agreement from NVIDIA CORPORATION is strictly prohibited. +# +# tmake for SW Mobile component makefile +# +############################################################################### + +NVGPU_UNIT_NAME=kref +NVGPU_UNIT_SRCS=kref.c + +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/interface/kref/kref.c b/userspace/units/interface/kref/kref.c new file mode 100644 index 000000000..c86cbbeaf --- /dev/null +++ b/userspace/units/interface/kref/kref.c @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2020, 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 "kref.h" + +#define LOOP_COUNT 10 + +int release_count = 0; + +static void test_ref_release(struct nvgpu_ref *ref) +{ + release_count += 1; +} + +int test_kref_init(struct unit_module *m, struct gk20a *g, void *args) +{ + int ret = 0; + struct nvgpu_ref test_ref; + + nvgpu_ref_init(&test_ref); + + ret = nvgpu_atomic_read(&test_ref.refcount); + + if (ret != 1) { + unit_return_fail(m, "nvgpu_ref_init failure\n"); + } + + return UNIT_SUCCESS; +} + +int test_kref_get(struct unit_module *m, struct gk20a *g, void *args) +{ + int ret, loop; + struct nvgpu_ref test_ref; + + nvgpu_ref_init(&test_ref); + + for (loop = 1; loop < LOOP_COUNT; loop++) { + nvgpu_ref_get(&test_ref); + } + + ret = nvgpu_atomic_read(&test_ref.refcount); + + if (ret != LOOP_COUNT) { + unit_return_fail(m, "nvgpu_ref_get failure %d\n", ret); + } + + return UNIT_SUCCESS; +} + +int test_kref_get_unless(struct unit_module *m, struct gk20a *g, void *args) +{ + int ret; + struct nvgpu_ref test_ref; + + nvgpu_atomic_set(&test_ref.refcount, 0); + ret = nvgpu_atomic_read(&test_ref.refcount); + if (ret != 0) { + unit_return_fail(m, "nvgpu_ref set to 0 failure %d\n", ret); + } + + ret = nvgpu_ref_get_unless_zero(&test_ref); + if (ret) { + unit_return_fail(m, + "nvgpu_ref_get_unless_zero failure %d\n", ret); + } + + nvgpu_ref_init(&test_ref); + ret = nvgpu_ref_get_unless_zero(&test_ref); + if (!ret) { + unit_return_fail(m, + "nvgpu_ref_get_unless_zero failure\n"); + } + + return UNIT_SUCCESS; +} + +int test_kref_put(struct unit_module *m, struct gk20a *g, void *args) +{ + int ret, loop; + struct nvgpu_ref test_ref; + + release_count = 0; + nvgpu_ref_init(&test_ref); + + for (loop = 1; loop < LOOP_COUNT; loop++) { + nvgpu_ref_get(&test_ref); + } + + ret = nvgpu_atomic_read(&test_ref.refcount); + + if (ret != LOOP_COUNT) { + unit_return_fail(m, "nvgpu_ref_get failure %d\n", ret); + } + + for (loop = 0; loop < LOOP_COUNT; loop++) { + nvgpu_ref_put(&test_ref, test_ref_release); + } + + if (!release_count) { + unit_return_fail(m, + "release function not invoked\n"); + } else if ((release_count > 1)) { + unit_return_fail(m, + "release function invoked more than once\n"); + } + + nvgpu_ref_get(&test_ref); + + nvgpu_ref_put(&test_ref, NULL); + + ret = nvgpu_atomic_read(&test_ref.refcount); + if (ret) { + unit_return_fail(m, + "nvgpu_ref_put with NULL callback failure %d\n", ret); + } + + release_count = 0; + + return UNIT_SUCCESS; +} + +int test_kref_put_return(struct unit_module *m, struct gk20a *g, void *args) +{ + int ret, loop; + struct nvgpu_ref test_ref; + + release_count = 0; + nvgpu_ref_init(&test_ref); + + for (loop = 1; loop < LOOP_COUNT; loop++) { + nvgpu_ref_get(&test_ref); + } + + ret = nvgpu_atomic_read(&test_ref.refcount); + + if (ret != LOOP_COUNT) { + unit_return_fail(m, "refcount not updated%d\n", ret); + } + + for (loop = 0; loop < (LOOP_COUNT - 1); loop++) { + ret = nvgpu_ref_put_return(&test_ref, test_ref_release); + if (ret) { + unit_return_fail(m, + "nvgpu_ref_put_return failure\n"); + } + } + + ret = nvgpu_ref_put_return(&test_ref, test_ref_release); + if (!ret) { + unit_return_fail(m, + "nvgpu_ref_put_return failure\n"); + } + + if (!release_count) { + unit_return_fail(m, + "release function not invoked\n"); + } else if ((release_count > 1)) { + unit_return_fail(m, + "release function invoked more than once\n"); + } + + release_count = 0; + + nvgpu_ref_get(&test_ref); + + ret = nvgpu_ref_put_return(&test_ref, NULL); + if (!ret) { + unit_return_fail(m, + "nvgpu_ref_put_return with NULL callback failure\n"); + } + + return UNIT_SUCCESS; +} + +struct unit_module_test interface_kref_tests[] = { + UNIT_TEST(kref_init, test_kref_init, NULL, 0), + UNIT_TEST(kref_get, test_kref_get, NULL, 0), + UNIT_TEST(kref_get_unless, test_kref_get_unless, NULL, 0), + UNIT_TEST(kref_put, test_kref_put, NULL, 0), + UNIT_TEST(kref_put_return, test_kref_put_return, NULL, 0), +}; + +UNIT_MODULE(interface_kref, interface_kref_tests, UNIT_PRIO_NVGPU_TEST); diff --git a/userspace/units/interface/kref/kref.h b/userspace/units/interface/kref/kref.h new file mode 100644 index 000000000..726aab0f8 --- /dev/null +++ b/userspace/units/interface/kref/kref.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2020, 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_INTERFACE_KREF_H +#define UNIT_INTERFACE_KREF_H + +struct gk20a; +struct unit_module; + +/** @addtogroup SWUTS-interface-kref + * @{ + * + * Software Unit Test Specification for interface-kref + */ + +/** + * Test specification for test_kref_init + * + * Description: Test the reference count initialization implementation. + * + * Test Type: Feature + * + * Targets: nvgpu_ref_init + * + * Input: None + * + * Steps: + * - Invoke the function nvgpu_ref_init to initialize nvgpu_ref structure. + * - Read back the refcount value and confirm the value is initialized to 1. + * Otherwise, return FAIL. + * - Return PASS. + * + * Output: Returns PASS if the refcount is initialized correctly, otherwise + * returns FAIL. + */ +int test_kref_init(struct unit_module *m, struct gk20a *g, void *__args); + +/** + * Test specification for test_kref_get + * + * Description: Test the reference get implementation. + * + * Test Type: Feature + * + * Targets: nvgpu_ref_get + * + * Input: None + * + * Steps: + * - Invoke the function nvgpu_ref_init to initialize nvgpu_ref structure. + * - Invoke the function nvgpu_ref_get in loop to increment the refcount value + * till LOOP_COUNT. + * - Read back the refcount value and confirm that the value returned is in + * sync with the number of times nvgpu_ref_get is called. Otherwise return + * FAIL. + * - Return PASS. + * + * Output: Returns PASS if the refcount is incremented correctly, otherwise + * returns FAIL. + */ +int test_kref_get(struct unit_module *m, struct gk20a *g, void *__args); + +/** + * Test specification for test_kref_get_unless + * + * Description: Test the reference get unless implementation. + * + * Test Type: Feature + * + * Targets: nvgpu_ref_get_unless_zero + * + * Input: None + * + * Steps: + * - Initialize the refcount value as 0 for nvgpu_ref struct. + * - Invoke function nvgpu_ref_get_unless_zero and confirm that the return + * value is 0. Otherwise return FAIL. + * - Invoke the function nvgpu_ref_init to initialize nvgpu_ref structure. + * - Invoke the function nvgpu_ref_get_unless_zero to increment the refcount + * value. + * - Check and confirm that the return value is not zero. Otherwise, return + * FAIL. + * - Return PASS. + * + * Output: Returns SUCCESS if the refcount is increased correctly according to + * the current value in refcount, otherwise return FAIL. + */ +int test_kref_get_unless(struct unit_module *m, struct gk20a *g, void *__args); + +/** + * Test specification for test_kref_put + * + * Description: Test the reference put implementation. + * + * Test Type: Feature + * + * Targets: nvgpu_ref_put + * + * Input: None + * + * Steps: + * - Initialize the release_count as 0. + * - Invoke the function nvgpu_ref_init to initialize nvgpu_ref structure. + * - Invoke the function nvgpu_ref_get in loop to increment the refcount value + * till LOOP_COUNT. + * - Read back the refcount value and confirm that the value returned is in + * sync with the number of times nvgpu_ref_get is called. Otherwise return + * FAIL. + * - Invoke the function nvgpu_ref_put in loop for LOOP_COUNT times to + * decrement the refcount value to 0. + * - Check the value of release_count value which is incremented in the + * release callback function to confirm that the release callback function + * is invoked and invoked only once. Otherwise return FAIL. + * - Invoke the function nvgpu_ref_get to increment the refcount value. + * - Invoke the function nvgpu_ref_put with callback as NULL. + * - Read back the refcount value and confirm that the value is reset to 0. + * Otherwise return FAIL. + * - Return PASS. + * + * Output: Returns SUCCESS if the refcerence is released correctly, otherwise + * return FAIL. + */ +int test_kref_put(struct unit_module *m, struct gk20a *g, void *__args); + +/** + * Test specification for test_kref_put_return + * + * Description: Test the reference put return implementation. + * + * Test Type: Feature + * + * Targets: nvgpu_ref_put_return + * + * Input: None + * + * Steps: + * - Initialize the release_count as 0. + * - Invoke the function nvgpu_ref_init to initialize nvgpu_ref structure. + * - Invoke the function nvgpu_ref_get in loop to increment the refcount value. + * - Read back the refcount value and confirm that the value returned is in + * sync with the number of times nvgpu_ref_get is called. Otherwise return + * FAIL. + * - Invoke the function nvgpu_ref_put in loop for (LOOP_COUNT - 1) to + * decrement the refcount value and confirm that the return value is always + * zero. Otherwise return FAIL. + * - Invoke the function nvgpu_ref_put once more and confirm that the return + * value is equal to one. Otherwise return FAIL. + * - Check the value of release_count value which is incremented in the + * release callback function to confirm that the release callback function + * is invoked and invoked only once. Otherwise return FAIL. + * - Invoke the function nvgpu_ref_get to increment the refcount value. + * - Invoke the function nvgpu_ref_put_return with callback as NULL. + * - Check the return value and return FAIL if it is equal to zero. + * - Return PASS. + * + * Output: Returns SUCCESS if the refcount is initialized correctly, otherwise + * return FAIL. + */ +int test_kref_put_return(struct unit_module *m, struct gk20a *g, void *__args); + +#endif /* UNIT_INTERFACE_KREF_H */