diff options
Diffstat (limited to 'drivers/gpu/arm/midgard/mali_kbase_config.c')
-rwxr-xr-x | drivers/gpu/arm/midgard/mali_kbase_config.c | 358 |
1 files changed, 358 insertions, 0 deletions
diff --git a/drivers/gpu/arm/midgard/mali_kbase_config.c b/drivers/gpu/arm/midgard/mali_kbase_config.c new file mode 100755 index 00000000000..fe9f0276455 --- /dev/null +++ b/drivers/gpu/arm/midgard/mali_kbase_config.c @@ -0,0 +1,358 @@ +/* + * + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + + + + +#include <mali_kbase.h> +#include <mali_kbase_defs.h> +#include <mali_kbase_cpuprops.h> +#include <mali_kbase_config_defaults.h> + +/* Specifies how many attributes are permitted in the config (excluding terminating attribute). + * This is used in validation function so we can detect if configuration is properly terminated. This value can be + * changed if we need to introduce more attributes or many memory regions need to be defined */ +#define ATTRIBUTE_COUNT_MAX 32 + +/* Limits for gpu frequency configuration parameters. These will use for config validation. */ +#define MAX_GPU_ALLOWED_FREQ_KHZ 1000000 +#define MIN_GPU_ALLOWED_FREQ_KHZ 1 + +int kbasep_get_config_attribute_count(const kbase_attribute *attributes) +{ + int count = 1; + + if (!attributes) + return -EINVAL; + + while (attributes->id != KBASE_CONFIG_ATTR_END) { + attributes++; + count++; + } + + return count; +} + +const kbase_attribute *kbasep_get_next_attribute(const kbase_attribute *attributes, int attribute_id) +{ + KBASE_DEBUG_ASSERT(attributes != NULL); + + while (attributes->id != KBASE_CONFIG_ATTR_END) { + if (attributes->id == attribute_id) + return attributes; + + attributes++; + } + return NULL; +} + +KBASE_EXPORT_TEST_API(kbasep_get_next_attribute) + +uintptr_t kbasep_get_config_value(struct kbase_device *kbdev, const kbase_attribute *attributes, int attribute_id) +{ + const kbase_attribute *attr; + + KBASE_DEBUG_ASSERT(attributes != NULL); + + attr = kbasep_get_next_attribute(attributes, attribute_id); + if (attr != NULL) + return attr->data; + + /* default values */ + switch (attribute_id) { + case KBASE_CONFIG_ATTR_GPU_IRQ_THROTTLE_TIME_US: + return DEFAULT_IRQ_THROTTLE_TIME_US; + /* Begin scheduling defaults */ + case KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS: + return DEFAULT_JS_SCHEDULING_TICK_NS; + case KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS: + return DEFAULT_JS_SOFT_STOP_TICKS; + case KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL: + return DEFAULT_JS_SOFT_STOP_TICKS_CL; + case KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS: + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8408)) + return DEFAULT_JS_HARD_STOP_TICKS_SS_HW_ISSUE_8408; + else + return DEFAULT_JS_HARD_STOP_TICKS_SS; + case KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL: + return DEFAULT_JS_HARD_STOP_TICKS_CL; + case KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS: + return DEFAULT_JS_HARD_STOP_TICKS_NSS; + case KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS: + return DEFAULT_JS_CTX_TIMESLICE_NS; + case KBASE_CONFIG_ATTR_JS_CFS_CTX_RUNTIME_INIT_SLICES: + return DEFAULT_JS_CFS_CTX_RUNTIME_INIT_SLICES; + case KBASE_CONFIG_ATTR_JS_CFS_CTX_RUNTIME_MIN_SLICES: + return DEFAULT_JS_CFS_CTX_RUNTIME_MIN_SLICES; + case KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS: + if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8408)) + return DEFAULT_JS_RESET_TICKS_SS_HW_ISSUE_8408; + else + return DEFAULT_JS_RESET_TICKS_SS; + case KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL: + return DEFAULT_JS_RESET_TICKS_CL; + case KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS: + return DEFAULT_JS_RESET_TICKS_NSS; + case KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS: + return DEFAULT_JS_RESET_TIMEOUT_MS; + /* End scheduling defaults */ + case KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS: + return 0; + case KBASE_CONFIG_ATTR_PLATFORM_FUNCS: + return 0; + case KBASE_CONFIG_ATTR_SECURE_BUT_LOSS_OF_PERFORMANCE: + return DEFAULT_SECURE_BUT_LOSS_OF_PERFORMANCE; + case KBASE_CONFIG_ATTR_CPU_SPEED_FUNC: + return DEFAULT_CPU_SPEED_FUNC; + case KBASE_CONFIG_ATTR_GPU_SPEED_FUNC: + return 0; + case KBASE_CONFIG_ATTR_ARID_LIMIT: + return DEFAULT_ARID_LIMIT; + case KBASE_CONFIG_ATTR_AWID_LIMIT: + return DEFAULT_AWID_LIMIT; + case KBASE_CONFIG_ATTR_POWER_MANAGEMENT_DVFS_FREQ: + return DEFAULT_PM_DVFS_FREQ; + case KBASE_CONFIG_ATTR_PM_GPU_POWEROFF_TICK_NS: + return DEFAULT_PM_GPU_POWEROFF_TICK_NS; + case KBASE_CONFIG_ATTR_PM_POWEROFF_TICK_SHADER: + return DEFAULT_PM_POWEROFF_TICK_SHADER; + case KBASE_CONFIG_ATTR_PM_POWEROFF_TICK_GPU: + return DEFAULT_PM_POWEROFF_TICK_GPU; + + default: + dev_err(kbdev->dev, "kbasep_get_config_value. Cannot get value of attribute with id=%d and no default value defined", attribute_id); + return 0; + } +} + +KBASE_EXPORT_TEST_API(kbasep_get_config_value) + +mali_bool kbasep_platform_device_init(kbase_device *kbdev) +{ + kbase_platform_funcs_conf *platform_funcs; + + platform_funcs = (kbase_platform_funcs_conf *) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_PLATFORM_FUNCS); + if (platform_funcs) { + if (platform_funcs->platform_init_func) + return platform_funcs->platform_init_func(kbdev); + } + return MALI_TRUE; +} + +void kbasep_platform_device_term(kbase_device *kbdev) +{ + kbase_platform_funcs_conf *platform_funcs; + + platform_funcs = (kbase_platform_funcs_conf *) kbasep_get_config_value(kbdev, kbdev->config_attributes, KBASE_CONFIG_ATTR_PLATFORM_FUNCS); + if (platform_funcs) { + if (platform_funcs->platform_term_func) + platform_funcs->platform_term_func(kbdev); + } +} + +static mali_bool kbasep_validate_gpu_clock_freq(kbase_device *kbdev, const kbase_attribute *attributes) +{ + uintptr_t freq_min = kbasep_get_config_value(kbdev, attributes, KBASE_CONFIG_ATTR_GPU_FREQ_KHZ_MIN); + uintptr_t freq_max = kbasep_get_config_value(kbdev, attributes, KBASE_CONFIG_ATTR_GPU_FREQ_KHZ_MAX); + + if ((freq_min > MAX_GPU_ALLOWED_FREQ_KHZ) || (freq_min < MIN_GPU_ALLOWED_FREQ_KHZ) || (freq_max > MAX_GPU_ALLOWED_FREQ_KHZ) || (freq_max < MIN_GPU_ALLOWED_FREQ_KHZ) || (freq_min > freq_max)) { + dev_warn(kbdev->dev, "Invalid GPU frequencies found in configuration: min=%ldkHz, max=%ldkHz.", freq_min, freq_max); + return MALI_FALSE; + } + + return MALI_TRUE; +} + +static mali_bool kbasep_validate_pm_callback(const kbase_pm_callback_conf *callbacks, const kbase_device * kbdev ) +{ + if (callbacks == NULL) { + /* Having no callbacks is valid */ + return MALI_TRUE; + } + + if ((callbacks->power_off_callback != NULL && callbacks->power_on_callback == NULL) || (callbacks->power_off_callback == NULL && callbacks->power_on_callback != NULL)) { + dev_warn(kbdev->dev, "Invalid power management callbacks: Only one of power_off_callback and power_on_callback was specified"); + return MALI_FALSE; + } + return MALI_TRUE; +} + +static mali_bool kbasep_validate_cpu_speed_func(kbase_cpuprops_clock_speed_function fcn) +{ + return fcn != NULL; +} + +mali_bool kbasep_validate_configuration_attributes(kbase_device *kbdev, const kbase_attribute *attributes) +{ + int i; + mali_bool had_gpu_freq_min = MALI_FALSE, had_gpu_freq_max = MALI_FALSE; + + KBASE_DEBUG_ASSERT(attributes); + + for (i = 0; attributes[i].id != KBASE_CONFIG_ATTR_END; i++) { + if (i >= ATTRIBUTE_COUNT_MAX) { + dev_warn(kbdev->dev, "More than ATTRIBUTE_COUNT_MAX=%d configuration attributes defined. Is attribute list properly terminated?", ATTRIBUTE_COUNT_MAX); + return MALI_FALSE; + } + + switch (attributes[i].id) { + case KBASE_CONFIG_ATTR_GPU_FREQ_KHZ_MIN: + had_gpu_freq_min = MALI_TRUE; + if (MALI_FALSE == kbasep_validate_gpu_clock_freq(kbdev, attributes)) { + /* Warning message handled by kbasep_validate_gpu_clock_freq() */ + return MALI_FALSE; + } + break; + + case KBASE_CONFIG_ATTR_GPU_FREQ_KHZ_MAX: + had_gpu_freq_max = MALI_TRUE; + if (MALI_FALSE == kbasep_validate_gpu_clock_freq(kbdev, attributes)) { + /* Warning message handled by kbasep_validate_gpu_clock_freq() */ + return MALI_FALSE; + } + break; + + /* Only non-zero unsigned 32-bit values accepted */ + case KBASE_CONFIG_ATTR_JS_SCHEDULING_TICK_NS: +#if CSTD_CPU_64BIT + if (attributes[i].data == 0u || (u64) attributes[i].data > (u64) U32_MAX) +#else + if (attributes[i].data == 0u) +#endif + { + dev_warn(kbdev->dev, "Invalid Job Scheduling Configuration attribute for " "KBASE_CONFIG_ATTR_JS_SCHEDULING_TICKS_NS: %d", (int)attributes[i].data); + return MALI_FALSE; + } + break; + + /* All these Job Scheduling attributes are FALLTHROUGH: only unsigned 32-bit values accepted */ + case KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS: + case KBASE_CONFIG_ATTR_JS_SOFT_STOP_TICKS_CL: + case KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_SS: + case KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_CL: + case KBASE_CONFIG_ATTR_JS_HARD_STOP_TICKS_NSS: + case KBASE_CONFIG_ATTR_JS_RESET_TICKS_SS: + case KBASE_CONFIG_ATTR_JS_RESET_TICKS_CL: + case KBASE_CONFIG_ATTR_JS_RESET_TICKS_NSS: + case KBASE_CONFIG_ATTR_JS_RESET_TIMEOUT_MS: + case KBASE_CONFIG_ATTR_JS_CTX_TIMESLICE_NS: + case KBASE_CONFIG_ATTR_JS_CFS_CTX_RUNTIME_INIT_SLICES: + case KBASE_CONFIG_ATTR_JS_CFS_CTX_RUNTIME_MIN_SLICES: +#if CSTD_CPU_64BIT + if ((u64) attributes[i].data > (u64) U32_MAX) { + dev_warn(kbdev->dev, "Job Scheduling Configuration attribute exceeds 32-bits: " "id==%d val==%d", attributes[i].id, (int)attributes[i].data); + return MALI_FALSE; + } +#endif + break; + + case KBASE_CONFIG_ATTR_GPU_IRQ_THROTTLE_TIME_US: +#if CSTD_CPU_64BIT + if ((u64) attributes[i].data > (u64) U32_MAX) { + dev_warn(kbdev->dev, "IRQ throttle time attribute exceeds 32-bits: " "id==%d val==%d", attributes[i].id, (int)attributes[i].data); + return MALI_FALSE; + } +#endif + break; + + case KBASE_CONFIG_ATTR_POWER_MANAGEMENT_CALLBACKS: + if (MALI_FALSE == kbasep_validate_pm_callback((kbase_pm_callback_conf *) attributes[i].data, kbdev)) { + /* Warning message handled by kbasep_validate_pm_callback() */ + return MALI_FALSE; + } + break; + + case KBASE_CONFIG_ATTR_SECURE_BUT_LOSS_OF_PERFORMANCE: + if (attributes[i].data != MALI_TRUE && attributes[i].data != MALI_FALSE) { + dev_warn(kbdev->dev, "Value for KBASE_CONFIG_ATTR_SECURE_BUT_LOSS_OF_PERFORMANCE was not " "MALI_TRUE or MALI_FALSE: %u", (unsigned int)attributes[i].data); + return MALI_FALSE; + } + break; + + case KBASE_CONFIG_ATTR_CPU_SPEED_FUNC: + if (MALI_FALSE == kbasep_validate_cpu_speed_func((kbase_cpuprops_clock_speed_function) attributes[i].data)) { + dev_warn(kbdev->dev, "Invalid function pointer in KBASE_CONFIG_ATTR_CPU_SPEED_FUNC"); + return MALI_FALSE; + } + break; + + case KBASE_CONFIG_ATTR_GPU_SPEED_FUNC: + if (0 == attributes[i].data) { + dev_warn(kbdev->dev, "Invalid function pointer in KBASE_CONFIG_ATTR_GPU_SPEED_FUNC"); + return MALI_FALSE; + } + break; + + case KBASE_CONFIG_ATTR_PLATFORM_FUNCS: + /* any value is allowed */ + break; + + case KBASE_CONFIG_ATTR_AWID_LIMIT: + case KBASE_CONFIG_ATTR_ARID_LIMIT: + if ((u32) attributes[i].data > 0x3) { + dev_warn(kbdev->dev, "Invalid AWID or ARID limit"); + return MALI_FALSE; + } + break; + + case KBASE_CONFIG_ATTR_POWER_MANAGEMENT_DVFS_FREQ: +#if CSTD_CPU_64BIT + if ((u64) attributes[i].data > (u64) U32_MAX) { + dev_warn(kbdev->dev, "PM DVFS interval exceeds 32-bits: " "id==%d val==%d", attributes[i].id, (int)attributes[i].data); + return MALI_FALSE; + } +#endif + break; + + case KBASE_CONFIG_ATTR_PM_GPU_POWEROFF_TICK_NS: +#if CSTD_CPU_64BIT + if (attributes[i].data == 0u || (u64) attributes[i].data > (u64) U32_MAX) { +#else + if (attributes[i].data == 0u) { +#endif + dev_warn(kbdev->dev, "Invalid Power Manager Configuration attribute for " "KBASE_CONFIG_ATTR_PM_GPU_POWEROFF_TICK_NS: %d", (int)attributes[i].data); + return MALI_FALSE; + } + break; + + case KBASE_CONFIG_ATTR_PM_POWEROFF_TICK_SHADER: + case KBASE_CONFIG_ATTR_PM_POWEROFF_TICK_GPU: +#if CSTD_CPU_64BIT + if ((u64) attributes[i].data > (u64) U32_MAX) { + dev_warn(kbdev->dev, "Power Manager Configuration attribute exceeds 32-bits: " "id==%d val==%d", attributes[i].id, (int)attributes[i].data); + return MALI_FALSE; + } +#endif + break; + + default: + dev_warn(kbdev->dev, "Invalid attribute found in configuration: %d", attributes[i].id); + return MALI_FALSE; + } + } + + if (!had_gpu_freq_min) { + dev_warn(kbdev->dev, "Configuration does not include mandatory attribute KBASE_CONFIG_ATTR_GPU_FREQ_KHZ_MIN"); + return MALI_FALSE; + } + + if (!had_gpu_freq_max) { + dev_warn(kbdev->dev, "Configuration does not include mandatory attribute KBASE_CONFIG_ATTR_GPU_FREQ_KHZ_MAX"); + return MALI_FALSE; + } + + return MALI_TRUE; +} |