diff --git a/Makefile.umbrella.tmk b/Makefile.umbrella.tmk index 58c99ec1d..d911bf496 100644 --- a/Makefile.umbrella.tmk +++ b/Makefile.umbrella.tmk @@ -130,6 +130,7 @@ NV_REPOSITORY_COMPONENTS += userspace/units/ce NV_REPOSITORY_COMPONENTS += userspace/units/cg NV_REPOSITORY_COMPONENTS += userspace/units/sync NV_REPOSITORY_COMPONENTS += userspace/units/mock-iospace +NV_REPOSITORY_COMPONENTS += userspace/units/ecc endif # Local Variables: diff --git a/drivers/gpu/nvgpu/libnvgpu-drv_safe.export b/drivers/gpu/nvgpu/libnvgpu-drv_safe.export index b31d0104d..4aebf45b7 100644 --- a/drivers/gpu/nvgpu/libnvgpu-drv_safe.export +++ b/drivers/gpu/nvgpu/libnvgpu-drv_safe.export @@ -697,3 +697,6 @@ nvgpu_test_and_set_bit vm_aspace_id nvgpu_get_nvhost_dev nvgpu_free_nvhost_dev +nvgpu_ecc_free +nvgpu_ecc_counter_init +nvgpu_ecc_finalize_support diff --git a/userspace/Makefile.sources b/userspace/Makefile.sources index c91a7f508..62222c199 100644 --- a/userspace/Makefile.sources +++ b/userspace/Makefile.sources @@ -138,3 +138,4 @@ UNITS := \ $(UNIT_SRC)/ce \ $(UNIT_SRC)/cg \ $(UNIT_SRC)/sync + $(UNIT_SRC)/ecc diff --git a/userspace/required_tests.json b/userspace/required_tests.json index 8ff1b7112..4da09c870 100644 --- a/userspace/required_tests.json +++ b/userspace/required_tests.json @@ -4261,5 +4261,29 @@ "case": "vm_bind", "unit": "vm", "test_level": 0 + }, + { + "test": "test_ecc_init_support", + "case": "ecc_init_support", + "unit": "ecc", + "test_level": 0 + }, + { + "test": "test_ecc_finalize_support", + "case": "ecc_finalize_support", + "unit": "ecc", + "test_level": 0 + }, + { + "test": "test_ecc_counter_init", + "case": "ecc_counter_init", + "unit": "ecc", + "test_level": 0 + }, + { + "test": "test_ecc_free", + "case": "ecc_free", + "unit": "ecc", + "test_level": 0 } ] diff --git a/userspace/units/ecc/Makefile b/userspace/units/ecc/Makefile new file mode 100644 index 000000000..1c7e982e3 --- /dev/null +++ b/userspace/units/ecc/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 = nvgpu-ecc.o +MODULE = ecc + +include ../Makefile.units diff --git a/userspace/units/ecc/Makefile.interface.tmk b/userspace/units/ecc/Makefile.interface.tmk new file mode 100644 index 000000000..3e160a337 --- /dev/null +++ b/userspace/units/ecc/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=nvgpu-ecc + +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/ecc/Makefile.tmk b/userspace/units/ecc/Makefile.tmk new file mode 100644 index 000000000..1d30b83ce --- /dev/null +++ b/userspace/units/ecc/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=nvgpu-ecc + +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/ecc/nvgpu-ecc.c b/userspace/units/ecc/nvgpu-ecc.c new file mode 100644 index 000000000..9ca1ddfb2 --- /dev/null +++ b/userspace/units/ecc/nvgpu-ecc.c @@ -0,0 +1,248 @@ +/* + * 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 +#include + +#include "nvgpu-ecc.h" + +static void mock_ecc_free(struct gk20a *g) { + +} + +int test_ecc_init_support(struct unit_module *m, struct gk20a *g, + void *args) +{ + /* + * Case #1: + * - First time ecc intialization. + * - "nvgpu_ecc_init_support" should perform init and return 0. + */ + g->ecc.initialized = false; + if (nvgpu_ecc_init_support(g) != 0) { + return UNIT_FAIL; + } + + /* + * Case #2: + * - Second time ecc intialization. + * - "nvgpu_ecc_init_support" should skip init but return 0. + */ + g->ecc.initialized = true; + if (nvgpu_ecc_init_support(g) != 0) { + return UNIT_FAIL; + } + + return UNIT_SUCCESS; +} + +int test_ecc_finalize_support(struct unit_module *m, struct gk20a *g, + void *args) +{ + /* + * Case #1: + * - First time ecc intialization. + * - "nvgpu_ecc_finalize_support" should perform init and return 0. + */ + g->ecc.initialized = false; + if (nvgpu_ecc_finalize_support(g) != 0) { + return UNIT_FAIL; + } + + /* + * Case #2: + * - Second time ecc intialization. + * - "nvgpu_ecc_finalize_support" should skip init but return 0. + */ + g->ecc.initialized = true; + if (nvgpu_ecc_finalize_support(g) != 0) { + return UNIT_FAIL; + } + + return UNIT_SUCCESS; +} + +int test_ecc_counter_init(struct unit_module *m, struct gk20a *g, + void *args) +{ + int ret = UNIT_SUCCESS; + struct nvgpu_ecc_stat *stat = NULL; + char *name; + struct nvgpu_posix_fault_inj *kmem_fi = + nvgpu_kmem_get_fault_injection(); + + /* + * Test setup: + * - Allocate memory for ecc counter name. + * - Initialize ecc support. + */ + name = nvgpu_kzalloc(g, NVGPU_ECC_STAT_NAME_MAX_SIZE + 1); + if (name == NULL) { + return UNIT_FAIL; + } + + if (nvgpu_ecc_init_support(g) != 0) { + ret = UNIT_FAIL; + goto cleanup; + } + + /* + * Case #1: + * - Initialize "name" with valid length string. + * - "nvgpu_ecc_counter_init" should return 0. + */ + strcpy(name, "test_counter"); + if (nvgpu_ecc_counter_init(g, &stat, name) != 0) { + ret = UNIT_FAIL; + goto cleanup; + } + nvgpu_kfree(g, stat); + + /* + * Case #2: + * - Inject SW fault to cause "nvgpu_kzalloc" failure. + * - "nvgpu_ecc_counter_init" should return -ENOMEM. + */ + nvgpu_posix_enable_fault_injection(kmem_fi, true, 0); + if (nvgpu_ecc_counter_init(g, &stat, name) != -ENOMEM) { + ret = UNIT_FAIL; + goto cleanup; + } + nvgpu_posix_enable_fault_injection(kmem_fi, false, 0); + + /* + * Case #3: + * - Intialize "name" with string of length greater than + * NVGPU_ECC_STAT_NAME_MAX_SIZE. + * - "nvgpu_ecc_counter_init" should return 0, with a truncated + * counter name. + */ + memset(name, NVGPU_ECC_STAT_NAME_MAX_SIZE, 'a'); + if (nvgpu_ecc_counter_init(g, &stat, name) != 0) { + ret = UNIT_FAIL; + goto cleanup; + } + nvgpu_kfree(g, stat); + stat = NULL; + +cleanup: + if (stat != NULL) { + nvgpu_kfree(g, stat); + } + nvgpu_kfree(g, name); + + return ret; +} + +int test_ecc_free(struct unit_module *m, struct gk20a *g, + void *args) +{ + int ret = UNIT_SUCCESS; + + if (nvgpu_ecc_init_support(g) != 0) { + return UNIT_FAIL; + } + + /* + * Setup: + * - allocate memory for gr and clear it to zero. + * - set gr->config to NULL to return immediately from + * nvgpu_gr_ecc_free. + * - Allocate memory for ltc and clear it to zero, this should set + * the ltc_Count and slice_per_ltc to 0. + */ + g->gr = nvgpu_kzalloc(g, sizeof(*g->gr)); + if (g->gr == NULL) { + return UNIT_FAIL; + } + g->ltc = nvgpu_kzalloc(g, sizeof(*g->ltc)); + if (g->ltc == NULL) { + nvgpu_kfree(g, g->gr); + return UNIT_FAIL; + } + + /* + * Case #1: + * - fb, fpba and pmu ecc HALs have ecc free handles set to NULL. + * - "nvgpu_ecc_free" should skip freeing ecc counters for fb, fpba, + * pmu and return without faulting. + */ + g->ops.fb.fb_ecc_free = NULL; + g->ops.pmu.ecc_free = NULL; + g->ecc.ltc.ecc_sec_count = nvgpu_kzalloc(g, + sizeof(*g->ecc.ltc.ecc_sec_count)); + g->ecc.ltc.ecc_ded_count = nvgpu_kzalloc(g, + sizeof(*g->ecc.ltc.ecc_ded_count)); + if (g->ecc.ltc.ecc_sec_count == NULL + || g->ecc.ltc.ecc_ded_count == NULL) { + ret = UNIT_FAIL; + goto cleanup; + } + nvgpu_ecc_free(g); + + /* + * Case #2: + * - fb and pmu ecc HALs have ecc free handles are set. + * - "nvgpu_ecc_free" should return without faulting. + */ + g->ops.fb.fb_ecc_free = mock_ecc_free; + g->ops.pmu.ecc_free = mock_ecc_free; + g->ecc.ltc.ecc_sec_count = nvgpu_kzalloc(g, + sizeof(*g->ecc.ltc.ecc_sec_count)); + g->ecc.ltc.ecc_ded_count = nvgpu_kzalloc(g, + sizeof(*g->ecc.ltc.ecc_ded_count)); + if (g->ecc.ltc.ecc_sec_count == NULL + || g->ecc.ltc.ecc_ded_count == NULL) { + ret = UNIT_FAIL; + goto cleanup; + } + nvgpu_ecc_free(g); + g->ecc.ltc.ecc_sec_count = NULL; + g->ecc.ltc.ecc_ded_count = NULL; + +cleanup: + if (g->ecc.ltc.ecc_sec_count != NULL) { + nvgpu_kfree(g, g->ecc.ltc.ecc_sec_count); + } + if (g->ecc.ltc.ecc_ded_count != NULL) { + nvgpu_kfree(g, g->ecc.ltc.ecc_ded_count); + } + nvgpu_kfree(g, g->gr); + nvgpu_kfree(g, g->ltc); + + return ret; +} + +struct unit_module_test ecc_tests[] = { + UNIT_TEST(ecc_init_support, test_ecc_init_support, NULL, 0), + UNIT_TEST(ecc_finalize_support, test_ecc_finalize_support, NULL, 0), + UNIT_TEST(ecc_counter_init, test_ecc_counter_init, NULL, 0), + UNIT_TEST(ecc_free, test_ecc_free, NULL, 0), +}; + +UNIT_MODULE(ecc, ecc_tests, UNIT_PRIO_NVGPU_TEST); diff --git a/userspace/units/ecc/nvgpu-ecc.h b/userspace/units/ecc/nvgpu-ecc.h new file mode 100644 index 000000000..0689e6a4c --- /dev/null +++ b/userspace/units/ecc/nvgpu-ecc.h @@ -0,0 +1,159 @@ +/* + * 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. + */ + +#ifndef UNIT_NVGPU_ECC_H +#define UNIT_NVGPU_ECC_H + +struct gk20a; +struct unit_module; + +/** @addtogroup SWUTS-ecc + * @{ + * + * Software Unit Test Specification for nvgpu.common.ecc + */ + + +/** + * Test specification for: test_ecc_init_support + * + * Description: Verify the "nvgpu_ecc_init_support" API. + * + * Test Type: Feature Based + * + * Targets: nvgpu_ecc_init_support + * + * Input: None + * + * Steps: + * - Test case #1 + * - Fresh initalization, ecc.initialized = false. + * - "nvgpu_ecc_init_support" should succeed and return 0. + * - Test case #2 + * - Re-initialization, ecc.initailiziation = true. + * - "nvgpu_ecc_init_support" will succeed but skip init and return 0. + * + * Output: + * - UNIT_FAIL if "nvgpu_ecc_init_support" fails with non-zero return value. + * - UNIT_SUCCESS otherwise + */ +int test_ecc_init_support(struct unit_module *m, + struct gk20a *g, void *args); + +/** + * Test specification for: test_ecc_finalize_support + * + * Description: Verify the "nvgpu_ecc_finalize_support" API. + * + * Test Type: Feature Based + * + * Targets: "nvgpu_ecc_finalize_support" + * + * Input: None + * + * Steps: + * - Test case #1 + * - Fresh initalization, ecc.initialized = false. + * - "nvgpu_ecc_finalize_support" should succeed and return 0. + * - Test case #2 + * - Re-initialization, ecc.initailiziation = true. + * - "nvgpu_ecc_finalize_support" will succeed but skip init and return 0. + * + * Output: + * - UNIT_FAIL if "nvgpu_ecc_finalize_support" fails with non-zero return value. + + * - UNIT_SUCCESS otherwise + */ +int test_ecc_finalize_support(struct unit_module *m, + struct gk20a *g, void *args); + +/** + * Test specification for: test_ecc_counter_init + * + * Description: Verify "nvgpu_ecc_counter_init" API. + * + * Test Type: Feature Based + * + * Targets: nvgpu_ecc_counter_init + * + * Input: nvgpu_ecc_init_support + * + * Steps: + * - Invokes "nvgpu_ecc_init_support". + * - Allocate memory for counter name string. + * - Test case #1 + * - Invokes "nvgpu_ecc_counter_init" with valid counter name("test_counter") + * - "nvgpu_ecc_counter_init" should succeed and return 0. + * - Test case #2 + * - Inject memory allocation fault + * - "nvgpu_ecc_counter_init" should return -ENOMEM + * - Test Case #3 + * - Set counter name to string with invalid length equal to + * NVGPU_ECC_STAT_NAME_MAX_SIZE. + * - "nvgpu_ecc_counter_init" will truncate the counter name and return 0. + * + * Output: + * - UNIT_FAIL under the following conditions: + * - Counter name memory allocation failed. + * - "nvgpu_ecc_init_support" failed. + * - "nvgpu_ecc_counter_init" failed. + * - UNIT_SUCCESS otherwise + */ +int test_ecc_counter_init(struct unit_module *m, + struct gk20a *g, void *args); + +/** + * Test specification for: test_ecc_free + * + * Description: Verify "nvgpu_ecc_free" API. + * + * Test Type: Feature Based + * + * Targets: nvgpu_ecc_free + * + * Input: nvgpu_ecc_init_support + * + * Steps: + * - Do the following setup + * - "nvgpu_ecc_init_support". + * - assign respective HALs and allocate memory for g->ltc and g->gr. + * - Test case #1 + * - Invokes "nvgpu_ecc_free" with unassigned fb_ecc_free, fbpa_ecc_free + * and pmu.ecc_free HALs. + * - "nvgpu_ecc_free" should succeed without faulting. + * - Test case #2 + * - Invokes "nvgpu_ecc_free" with uassigned fb_ecc_free, fbpa_ecc_free + * and pmu.ecc_free HALs. + * - "nvgpu_ecc_free" should succeed without faulting. + * + * Output: + * - UNIT_FAIL under the following conditions: + * - "nvgpu_ecc_init_support" failed. + * - Memory allocation failed for either g->gr or g->ltc. + * - Memory allocation failed for either ltc.ecc_sec/ded_count. + * + * - UNIT_SUCCESS otherwise + */ +int test_ecc_free(struct unit_module *m, + struct gk20a *g, void *args); + +#endif /* UNIT_NVGPU_ECC_H */