diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c')
| -rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c | 144 | 
1 files changed, 144 insertions, 0 deletions
| diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c new file mode 100644 index 000000000000..c9f47d167472 --- /dev/null +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright 2021 Advanced Micro Devices, Inc. + * + * 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + * + * Authors: AMD + * + */ + +#include "dc_trace.h" + +#if defined(CONFIG_X86) +#include <asm/fpu/api.h> +#elif defined(CONFIG_PPC64) +#include <asm/switch_to.h> +#include <asm/cputable.h> +#endif + +/** + * DOC: DC FPU manipulation overview + * + * DC core uses FPU operations in multiple parts of the code, which requires a + * more specialized way to manage these areas' entrance. To fulfill this + * requirement, we created some wrapper functions that encapsulate + * kernel_fpu_begin/end to better fit our need in the display component. In + * summary, in this file, you can find functions related to FPU operation + * management. + */ + +static DEFINE_PER_CPU(int, fpu_recursion_depth); + +/** + * dc_assert_fp_enabled - Check if FPU protection is enabled + * + * This function tells if the code is already under FPU protection or not. A + * function that works as an API for a set of FPU operations can use this + * function for checking if the caller invoked it after DC_FP_START(). For + * example, take a look at dcn2x.c file. + */ +inline void dc_assert_fp_enabled(void) +{ +	int *pcpu, depth = 0; + +	pcpu = get_cpu_ptr(&fpu_recursion_depth); +	depth = *pcpu; +	put_cpu_ptr(&fpu_recursion_depth); + +	ASSERT(depth > 1); +} + +/** + * dc_fpu_begin - Enables FPU protection + * @function_name: A string containing the function name for debug purposes + *   (usually __func__) + * + * @line: A line number where DC_FP_START was invoked for debug purpose + *   (usually __LINE__) + * + * This function is responsible for managing the use of kernel_fpu_begin() with + * the advantage of providing an event trace for debugging. + * + * Note: Do not call this function directly; always use DC_FP_START(). + */ +void dc_fpu_begin(const char *function_name, const int line) +{ +	int *pcpu; + +	pcpu = get_cpu_ptr(&fpu_recursion_depth); +	*pcpu += 1; + +	if (*pcpu == 1) { +#if defined(CONFIG_X86) +		kernel_fpu_begin(); +#elif defined(CONFIG_PPC64) +		if (cpu_has_feature(CPU_FTR_VSX_COMP)) { +			preempt_disable(); +			enable_kernel_vsx(); +		} else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP)) { +			preempt_disable(); +			enable_kernel_altivec(); +		} else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE)) { +			preempt_disable(); +			enable_kernel_fp(); +		} +#endif +	} + +	TRACE_DCN_FPU(true, function_name, line, *pcpu); +	put_cpu_ptr(&fpu_recursion_depth); +} + +/** + * dc_fpu_end - Disable FPU protection + * @function_name: A string containing the function name for debug purposes + * @line: A-line number where DC_FP_END was invoked for debug purpose + * + * This function is responsible for managing the use of kernel_fpu_end() with + * the advantage of providing an event trace for debugging. + * + * Note: Do not call this function directly; always use DC_FP_END(). + */ +void dc_fpu_end(const char *function_name, const int line) +{ +	int *pcpu; + +	pcpu = get_cpu_ptr(&fpu_recursion_depth); +	*pcpu -= 1; +	if (*pcpu <= 0) { +#if defined(CONFIG_X86) +		kernel_fpu_end(); +#elif defined(CONFIG_PPC64) +		if (cpu_has_feature(CPU_FTR_VSX_COMP)) { +			disable_kernel_vsx(); +			preempt_enable(); +		} else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP)) { +			disable_kernel_altivec(); +			preempt_enable(); +		} else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE)) { +			disable_kernel_fp(); +			preempt_enable(); +		} +#endif +	} + +	TRACE_DCN_FPU(false, function_name, line, *pcpu); +	put_cpu_ptr(&fpu_recursion_depth); +} | 
