From 941b87ff7801899b80f56af49eda2a79b9ed7bd3 Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Tue, 10 May 2016 15:49:03 +0900 Subject: [PATCH 01/16] ARM: mali400: r5p2_rel0: add sc8830 platform codes This comes from r5p0_rel0. Change-Id: I673ca4624c96f7aaedc15a5caa3ec72aeadb6656 Signed-off-by: Joonyoung Shim --- drivers/gpu/arm/mali400/r5p2_rel0/Kbuild | 10 +- .../arm/mali400/r5p2_rel0/platform/sc8830/base.h | 22 + .../r5p2_rel0/platform/sc8830/mali_platform.c | 730 +++++++++++++++++++++ 3 files changed, 761 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/arm/mali400/r5p2_rel0/platform/sc8830/base.h create mode 100644 drivers/gpu/arm/mali400/r5p2_rel0/platform/sc8830/mali_platform.c diff --git a/drivers/gpu/arm/mali400/r5p2_rel0/Kbuild b/drivers/gpu/arm/mali400/r5p2_rel0/Kbuild index ab2a41e..81b4d85 100644 --- a/drivers/gpu/arm/mali400/r5p2_rel0/Kbuild +++ b/drivers/gpu/arm/mali400/r5p2_rel0/Kbuild @@ -21,6 +21,10 @@ MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED ?= 0 MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS ?= 0 MALI_UPPER_HALF_SCHEDULING ?= 1 MALI_ENABLE_CPU_CYCLES ?= 0 +MALI_PLATFORM ?= sc8830 +MALI_FAKE_PLATFORM_DEVICE ?= 1 +DFS_ONE_STEP_SCALE_DOWN ?= 1 +MATCH_DFS_TO_LOWER_FREQ ?= 1 # For customer releases the Linux Device Drivers will be provided as ARM proprietary and GPL releases: # The ARM proprietary product will only include the license/proprietary directory @@ -118,6 +122,7 @@ mali-y += \ linux/mali_pmu_power_up_down.o \ __malidrv_build_info.o +MALI_PLATFORM_FILES = platform/$(MALI_PLATFORM)/mali_platform.c ifneq ($(MALI_PLATFORM_FILES),) mali-y += $(MALI_PLATFORM_FILES:.c=.o) endif @@ -143,6 +148,8 @@ ccflags-y += $(EXTRA_DEFINES) # Set up our defines, which will be passed to gcc ccflags-y += -DSPRD_GPU_BOOST +ccflags-y += -DSPRD_DFS_ONE_STEP_SCALE_DOWN=$(DFS_ONE_STEP_SCALE_DOWN) +ccflags-y += -DSPRD_MATCH_DFS_TO_LOWER_FREQ=$(MATCH_DFS_TO_LOWER_FREQ) ccflags-y += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP) ccflags-y += -DMALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED=$(MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED) @@ -151,6 +158,7 @@ ccflags-y += -DMALI_STATE_TRACKING=1 ccflags-y += -DMALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB) ccflags-y += -DUSING_GPU_UTILIZATION=$(USING_GPU_UTILIZATION) ccflags-y += -DMALI_ENABLE_CPU_CYCLES=$(MALI_ENABLE_CPU_CYCLES) +ccflags-y += -DMALI_FAKE_PLATFORM_DEVICE=$(MALI_FAKE_PLATFORM_DEVICE) ifeq ($(MALI_UPPER_HALF_SCHEDULING),1) ccflags-y += -DMALI_UPPER_HALF_SCHEDULING @@ -207,7 +215,7 @@ VERSION_STRINGS += BUILD=debug else VERSION_STRINGS += BUILD=release endif -VERSION_STRINGS += TARGET_PLATFORM=$(TARGET_PLATFORM) +VERSION_STRINGS += TARGET_PLATFORM=$(MALI_PLATFORM) VERSION_STRINGS += MALI_PLATFORM=$(MALI_PLATFORM) VERSION_STRINGS += KDIR=$(KDIR) VERSION_STRINGS += OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB) diff --git a/drivers/gpu/arm/mali400/r5p2_rel0/platform/sc8830/base.h b/drivers/gpu/arm/mali400/r5p2_rel0/platform/sc8830/base.h new file mode 100644 index 0000000..b7f2f80 --- /dev/null +++ b/drivers/gpu/arm/mali400/r5p2_rel0/platform/sc8830/base.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2010-2011 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. + */ + +#ifndef __ARCH_BASE_H__ +#define __ARCH_BASE_H__ + +#define ARCH_MALI_MEMORY_BASE_DEFAULT (4 * 1024 * 1024UL) +#define ARCH_MALI_MEMORY_SIZE_DEFAULT (1024 * 1024 * 1024UL) + +#define MALI400_L2_MAX_READS_DEFAULT 0x1C + +#endif diff --git a/drivers/gpu/arm/mali400/r5p2_rel0/platform/sc8830/mali_platform.c b/drivers/gpu/arm/mali400/r5p2_rel0/platform/sc8830/mali_platform.c new file mode 100644 index 0000000..8b4cb77 --- /dev/null +++ b/drivers/gpu/arm/mali400/r5p2_rel0/platform/sc8830/mali_platform.c @@ -0,0 +1,730 @@ +/* + * Copyright (C) 2010-2011 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. + */ + +/** + * @file mali_platform.c + * Platform specific Mali driver functions for a default platform + */ + +#include +#include +#include +#include +#ifdef CONFIG_SYSTEM_LOAD_ANALYZER +#include +#endif +#include +#ifdef CONFIG_MALI_DT +#include +#endif +#include +#include +#ifdef CONFIG_PM_RUNTIME +#include +#endif +#include +#include +#include + +#ifdef CONFIG_64BIT +#include +#include +#include +#else +#include +#include +#endif + +#include "base.h" +#include "mali_executor.h" +#include "mali_kernel_common.h" +#include "mali_kernel_linux.h" +#include "mali_pm.h" + +#define GPU_GLITCH_FREE_DFS 0 + +#define UP_THRESHOLD 9/10 +#define DOWN_THRESHOLD 5/10 + +#define __SPRD_GPU_TIMEOUT (3*1000) + +struct gpu_freq_info { + struct clk *clk_src; + int freq; + int div; + int up_threshold; +}; + +struct gpu_dfs_context { + int gpu_clock_on; + int gpu_power_on; + + struct clk *gpu_clock; + struct clk *gpu_clock_i; + struct clk **gpu_clk_src; + int gpu_clk_num; + + int cur_load; + + struct gpu_freq_info *freq_list; + int freq_list_len; + + const struct gpu_freq_info *freq_cur; + const struct gpu_freq_info *freq_next; + + const struct gpu_freq_info *freq_min; + const struct gpu_freq_info *freq_max; + const struct gpu_freq_info *freq_default; + const struct gpu_freq_info *freq_9; + const struct gpu_freq_info *freq_8; + const struct gpu_freq_info *freq_7; + const struct gpu_freq_info *freq_5; + const struct gpu_freq_info *freq_range_max; + const struct gpu_freq_info *freq_range_min; + + struct workqueue_struct *gpu_dfs_workqueue; + struct semaphore* sem; +}; + +extern int gpu_boost_level; +extern int gpu_boost_sf_level; + +extern int gpu_freq_cur; +extern int gpu_freq_min_limit; +extern int gpu_freq_max_limit; +extern char* gpu_freq_list; + +extern _mali_osk_errcode_t mali_executor_initialize(void); +extern void mali_executor_lock(void); +extern void mali_executor_unlock(void); + +static void gpu_dfs_func(struct work_struct *work); +static void mali_platform_utilization(struct mali_gpu_utilization_data *data); + +static DECLARE_WORK(gpu_dfs_work, &gpu_dfs_func); + +DEFINE_SEMAPHORE(gpu_dfs_sem); + +static struct gpu_dfs_context gpu_dfs_ctx = { + .sem = &gpu_dfs_sem, +}; + +struct mali_gpu_device_data mali_gpu_data = { + .shared_mem_size = ARCH_MALI_MEMORY_SIZE_DEFAULT, + .control_interval = 100, + .utilization_callback = mali_platform_utilization, + .get_clock_info = NULL, + .get_freq = NULL, + .set_freq = NULL, +}; + +static void gpu_freq_list_show(char *buf) +{ + struct gpu_dfs_context *ctx = &gpu_dfs_ctx; + int i; + + for (i = 0; i < ctx->freq_list_len; i++) + buf += sprintf(buf, "%2d %6d\n", i, ctx->freq_list[i].freq); +} + +static int sprd_gpu_domain_state(void) +{ + /* FIXME: rtc domain */ + unsigned int power_state1, power_state2, power_state3; + unsigned long timeout = jiffies + msecs_to_jiffies(__SPRD_GPU_TIMEOUT); + + do { + cpu_relax(); + power_state1 = sci_glb_read(REG_PMU_APB_PWR_STATUS0_DBG, + BITS_PD_GPU_TOP_STATE(-1)); + power_state2 = sci_glb_read(REG_PMU_APB_PWR_STATUS0_DBG, + BITS_PD_GPU_TOP_STATE(-1)); + power_state3 = sci_glb_read(REG_PMU_APB_PWR_STATUS0_DBG, + BITS_PD_GPU_TOP_STATE(-1)); + if (time_after(jiffies, timeout)) { + pr_emerg("gpu domain not ready, state %08x %08x\n", + sci_glb_read(REG_PMU_APB_PWR_STATUS0_DBG, -1), + sci_glb_read(REG_AON_APB_APB_EB0, -1)); + } + } while ((power_state1 != power_state2) || + (power_state2 != power_state3)); + + return (int)(power_state1); +} + +static void sprd_gpu_domain_wait_for_ready(void) +{ + int timeout_count = 2000; + + while (sprd_gpu_domain_state() != BITS_PD_GPU_TOP_STATE(0)) { + if (!timeout_count) { + pr_emerg( + "gpu domain not ready too long time, state %08x %08x\n", + sci_glb_read(REG_PMU_APB_PWR_STATUS0_DBG, -1), + sci_glb_read(REG_AON_APB_APB_EB0, -1)); + return; + } + udelay(50); + timeout_count--; + } +} + +static inline void mali_set_div(int clock_div) +{ + sci_glb_write(REG_GPU_APB_APB_CLK_CTRL, BITS_CLK_GPU_DIV(clock_div - 1), + BITS_CLK_GPU_DIV(3)); +} + +static inline void mali_power_on(void) +{ + sci_glb_clr(REG_PMU_APB_PD_GPU_TOP_CFG, BIT_PD_GPU_TOP_FORCE_SHUTDOWN); + udelay(100); + mali_executor_lock(); + gpu_dfs_ctx.gpu_power_on = 1; + mali_executor_unlock(); +} + +static inline void mali_power_off(void) +{ + mali_executor_lock(); + gpu_dfs_ctx.gpu_power_on = 0; + mali_executor_unlock(); + sci_glb_set(REG_PMU_APB_PD_GPU_TOP_CFG, BIT_PD_GPU_TOP_FORCE_SHUTDOWN); +} + +static inline void mali_clock_on(void) +{ + struct gpu_dfs_context *ctx = &gpu_dfs_ctx; + int i; + + for (i = 0; i < ctx->gpu_clk_num; i++) { +#ifdef CONFIG_COMMON_CLK + clk_prepare_enable(ctx->gpu_clk_src[i]); +#else + clk_enable(ctx->gpu_clk_src[i]); +#endif + } + +#ifdef CONFIG_COMMON_CLK + clk_prepare_enable(ctx->gpu_clock_i); +#else + clk_enable(ctx->gpu_clock_i); +#endif + sprd_gpu_domain_wait_for_ready(); + + clk_set_parent(ctx->gpu_clock, ctx->freq_default->clk_src); + + MALI_DEBUG_ASSERT(ctx->freq_cur); + clk_set_parent(ctx->gpu_clock, ctx->freq_cur->clk_src); + mali_set_div(ctx->freq_cur->div); + +#ifdef CONFIG_COMMON_CLK + clk_prepare_enable(ctx->gpu_clock); +#else + clk_enable(ctx->gpu_clock); +#endif + udelay(100); + + mali_executor_lock(); + ctx->gpu_clock_on = 1; + mali_executor_unlock(); + + gpu_freq_cur = ctx->freq_cur->freq; +#ifdef CONFIG_SYSTEM_LOAD_ANALYZER + store_external_load_factor(GPU_FREQ, gpu_freq_cur); +#endif +} + +static inline void mali_clock_off(void) +{ + struct gpu_dfs_context *ctx = &gpu_dfs_ctx; + int i; + + gpu_freq_cur = 0; +#ifdef CONFIG_SYSTEM_LOAD_ANALYZER + store_external_load_factor(GPU_UTILIZATION, 0); + store_external_load_factor(GPU_FREQ, gpu_freq_cur); +#endif + + mali_executor_lock(); + ctx->gpu_clock_on = 0; + mali_executor_unlock(); + +#ifdef CONFIG_COMMON_CLK + clk_disable_unprepare(ctx->gpu_clock); + clk_disable_unprepare(ctx->gpu_clock_i); +#else + clk_disable(ctx->gpu_clock); + clk_disable(ctx->gpu_clock_i); +#endif + + for (i = 0; i < ctx->gpu_clk_num; i++) { +#ifdef CONFIG_COMMON_CLK + clk_disable_unprepare(ctx->gpu_clk_src[i]); +#else + clk_disable(ctx->gpu_clk_src[i]); +#endif + } +} + +int mali_platform_device_init(struct platform_device *pdev) +{ +#ifndef CONFIG_SCX35L64BIT_FPGA /* not use fpga */ + struct gpu_dfs_context *ctx = &gpu_dfs_ctx; + int i, err = -1; +#ifdef CONFIG_ARCH_SCX30G + int clksrc_300m_idx = -1; +#endif +#ifdef CONFIG_MALI_DT + extern struct of_device_id base_dt_ids[]; + struct device_node *np; + int clk_cnt; + + np = of_find_matching_node(NULL, base_dt_ids); + if (!np) + return err; + + ctx->gpu_clock_i = of_clk_get(np, 0); + MALI_DEBUG_ASSERT(ctx->gpu_clock_i); + ctx->gpu_clock = of_clk_get(np, 1); + MALI_DEBUG_ASSERT(ctx->gpu_clock); + + clk_cnt = of_property_count_strings(np, "clock-names"); + ctx->gpu_clk_num = clk_cnt - 2; + ctx->gpu_clk_src = vmalloc(sizeof(struct clk *) * ctx->gpu_clk_num); + MALI_DEBUG_ASSERT(ctx->gpu_clk_src); + + for (i = 0; i < ctx->gpu_clk_num; i++) { + const char *clk_name; + + of_property_read_string_index(np, "clock-names", i + 2, + &clk_name); + ctx->gpu_clk_src[i] = of_clk_get_by_name(np, clk_name); + MALI_DEBUG_ASSERT(ctx->gpu_clk_src[i]); +#ifdef CONFIG_ARCH_SCX30G + if (!strcmp(clk_name, "clk_300m_gpu_gate")) + clksrc_300m_idx = i; +#endif + } + + of_property_read_u32(np, "freq-list-len", &ctx->freq_list_len); + ctx->freq_list = + vmalloc(sizeof(struct gpu_freq_info) * ctx->freq_list_len); + MALI_DEBUG_ASSERT(ctx->freq_list); + + for (i = 0; i < ctx->freq_list_len; i++) { + int clk; + + of_property_read_u32_index(np, "freq-lists", 3 * i + 1, &clk); + ctx->freq_list[i].clk_src = ctx->gpu_clk_src[clk - 2]; + MALI_DEBUG_ASSERT(ctx->freq_list[i].clk_src); + of_property_read_u32_index(np, "freq-lists", 3 * i, + &ctx->freq_list[i].freq); + of_property_read_u32_index(np, "freq-lists", 3 * i + 2, + &ctx->freq_list[i].div); + ctx->freq_list[i].up_threshold = + ctx->freq_list[i].freq * UP_THRESHOLD; + } + + of_property_read_u32(np, "freq-default", &i); + ctx->freq_default = &ctx->freq_list[i]; + MALI_DEBUG_ASSERT(ctx->freq_default); + + of_property_read_u32(np, "freq-9", &i); + ctx->freq_9 = &ctx->freq_list[i]; + MALI_DEBUG_ASSERT(ctx->freq_9); + + of_property_read_u32(np, "freq-8", &i); + ctx->freq_8 = &ctx->freq_list[i]; + MALI_DEBUG_ASSERT(ctx->freq_8); + + of_property_read_u32(np, "freq-7", &i); + ctx->freq_7 = &ctx->freq_list[i]; + MALI_DEBUG_ASSERT(ctx->freq_7); + + of_property_read_u32(np, "freq-5", &i); + ctx->freq_5 = &ctx->freq_list[i]; + MALI_DEBUG_ASSERT(ctx->freq_5); + + of_property_read_u32(np, "freq-range-max", &i); + ctx->freq_range_max = &ctx->freq_list[i]; + MALI_DEBUG_ASSERT(ctx->freq_range_max); + + of_property_read_u32(np, "freq-range-min", &i); + ctx->freq_range_min = &ctx->freq_list[i]; + MALI_DEBUG_ASSERT(ctx->freq_range_min); + + of_node_put(np); + + ctx->freq_max = ctx->freq_range_max; + ctx->freq_min = ctx->freq_range_min; + ctx->freq_cur = ctx->freq_default; +#endif + + sci_glb_write(REG_PMU_APB_PD_GPU_TOP_CFG, + BITS_PD_GPU_TOP_PWR_ON_DLY(1), 0xff0000); + sci_glb_write(REG_PMU_APB_PD_GPU_TOP_CFG, + BITS_PD_GPU_TOP_PWR_ON_SEQ_DLY(1), 0xff00); + sci_glb_write(REG_PMU_APB_PD_GPU_TOP_CFG, + BITS_PD_GPU_TOP_ISO_ON_DLY(1), 0xff); + + mali_power_on(); + + mali_clock_on(); +#ifdef CONFIG_ARCH_SCX30G + /* CPU could disable MPLL, so should increase MPLL refcnt */ + if (clksrc_300m_idx != -1) { +#ifdef CONFIG_COMMON_CLK + clk_prepare_enable(ctx->gpu_clk_src[clksrc_300m_idx]); +#else + clk_enable(ctx->gpu_clk_src[clksrc_300m_idx]); +#endif + } +#endif + + ctx->gpu_dfs_workqueue = create_singlethread_workqueue("gpu_dfs"); + + err = platform_device_add_data(pdev, &mali_gpu_data, + sizeof(mali_gpu_data)); + if (!err) { +#ifdef CONFIG_PM_RUNTIME +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + pm_runtime_set_autosuspend_delay(&(pdev->dev), 50); + pm_runtime_use_autosuspend(&(pdev->dev)); +#endif + pm_runtime_enable(&(pdev->dev)); +#endif + } + + gpu_freq_list = vmalloc(sizeof(char) * 256); + gpu_freq_list_show(gpu_freq_list); + + return err; +#else /* use fpga */ +#ifdef CONFIG_MALI_DT + if (!of_find_matching_node(NULL, gpu_ids)) + return -1; +#endif + sci_glb_clr(REG_PMU_APB_PD_GPU_TOP_CFG, BIT_PD_GPU_TOP_FORCE_SHUTDOWN); + mdelay(2); + + return 0; +#endif /* use fpga */ +} + +int mali_platform_device_deinit(struct platform_device *device) +{ + struct gpu_dfs_context *ctx = &gpu_dfs_ctx; + + destroy_workqueue(ctx->gpu_dfs_workqueue); + + mali_clock_off(); + + mali_power_off(); + + vfree(gpu_freq_list); + vfree(ctx->freq_list); + vfree(ctx->gpu_clk_src); + + return 0; +} + +static int freq_search(struct gpu_freq_info freq_list[], int len, int key) +{ + int low = 0, high = len - 1, mid; + + if (key < 0) + return -1; + + while (low <= high) { + mid = (low + high) / 2; + + if (key == freq_list[mid].freq) + return mid; + + if (key < freq_list[mid].freq) + high = mid - 1; + else + low = mid + 1; + } + + return -1; +} + +void mali_platform_power_mode_change(int power_mode) +{ + struct gpu_dfs_context *ctx = &gpu_dfs_ctx; + + down(ctx->sem); + + MALI_DEBUG_PRINT(3, + ("Mali power mode change %d, gpu_power_on=%d gpu_clock_on=%d\n", + power_mode, ctx->gpu_power_on, ctx->gpu_clock_on)); + + switch (power_mode) { + case 0: /* MALI_POWER_MODE_ON */ + if (!ctx->gpu_power_on) { + /* + * The max limit feature is applied only utilization + * routine, so GPU can work with max freq even though + * max limit is set. + */ + int max_index = freq_search(ctx->freq_list, + ctx->freq_list_len, + gpu_freq_max_limit); + + if (max_index >= 0) + ctx->freq_max = &ctx->freq_list[max_index]; + + ctx->freq_cur = ctx->freq_max; + mali_power_on(); + mali_clock_on(); + } + + if (!ctx->gpu_clock_on) + mali_clock_on(); + break; + case 1: /* MALI_POWER_MODE_LIGHT_SLEEP */ + case 2: /* MALI_POWER_MODE_DEEP_SLEEP */ + default: + if (ctx->gpu_clock_on) + mali_clock_off(); + + if (ctx->gpu_power_on) + mali_power_off(); + break; + }; + + up(ctx->sem); +} + +static void gpu_dfs_func(struct work_struct *work) +{ + struct gpu_dfs_context *ctx = &gpu_dfs_ctx; + + down(ctx->sem); + + if (!ctx->gpu_power_on || !ctx->gpu_clock_on) { + up(ctx->sem); + return; + } + + if (ctx->freq_next == ctx->freq_cur) { + up(ctx->sem); + return; + } + +#if !GPU_GLITCH_FREE_DFS + mali_dev_pause(); + +#ifdef CONFIG_COMMON_CLK + clk_disable_unprepare(ctx->gpu_clock); +#else + clk_disable(ctx->gpu_clock); +#endif +#endif + + if (ctx->freq_next->clk_src != ctx->freq_cur->clk_src) + clk_set_parent(ctx->gpu_clock, ctx->freq_next->clk_src); + + if (ctx->freq_next->div != ctx->freq_cur->div) + mali_set_div(ctx->freq_next->div); + + ctx->freq_cur = ctx->freq_next; + gpu_freq_cur = ctx->freq_cur->freq; +#ifdef CONFIG_SYSTEM_LOAD_ANALYZER + store_external_load_factor(GPU_FREQ, gpu_freq_cur); +#endif + +#if !GPU_GLITCH_FREE_DFS +#ifdef CONFIG_COMMON_CLK + clk_prepare_enable(ctx->gpu_clock); +#else + clk_enable(ctx->gpu_clock); +#endif + udelay(100); + + mali_dev_resume(); +#endif + + up(ctx->sem); +} + +/* + * DVFS of SPRD implementation + */ + +#if !SPRD_DFS_ONE_STEP_SCALE_DOWN +static const struct gpu_freq_info +*get_next_freq(const struct gpu_freq_info *min_freq, + const struct gpu_freq_info *max_freq, int target) +{ + const struct gpu_freq_info *freq; + + for (freq = min_freq; freq <= max_freq; freq++) { + if (freq->up_threshold > target) + return freq; + } + + return max_freq; +} +#endif + +static void mali_platform_utilization(struct mali_gpu_utilization_data *data) +{ +#ifndef CONFIG_SCX35L64BIT_FPGA /* not use fpga */ + struct gpu_dfs_context *ctx = &gpu_dfs_ctx; + int max_index, min_index; + + ctx->cur_load = data->utilization_gpu; + + MALI_DEBUG_PRINT(3, + ("GPU_DFS mali_utilization gpu:%d gp:%d pp:%d\n", + data->utilization_gpu, data->utilization_gp, + data->utilization_pp)); + MALI_DEBUG_PRINT(3, + ("GPU_DFS gpu_boost_level:%d gpu_boost_sf_level:%d\n", + gpu_boost_level, gpu_boost_sf_level)); + + switch (gpu_boost_level) { + case 10: + ctx->freq_max = ctx->freq_min = + &ctx->freq_list[ctx->freq_list_len - 1]; + break; + case 9: + ctx->freq_max = ctx->freq_min = ctx->freq_9; + break; + case 7: + ctx->freq_max = ctx->freq_min = ctx->freq_7; + break; + case 5: + ctx->freq_max = ctx->freq_min = ctx->freq_5; + break; + case 0: + default: + ctx->freq_max = ctx->freq_range_max; + ctx->freq_min = ctx->freq_range_min; + break; + } + + if (!gpu_boost_level && (gpu_boost_sf_level > 0)) { + ctx->freq_max = ctx->freq_min = + &ctx->freq_list[ctx->freq_list_len - 1]; + } + + gpu_boost_level = 0; + gpu_boost_sf_level = 0; + + /* + * SPRD_MATCH_DFS_TO_LOWER_FREQ + * + * If user uses gpufreq_min/max_limit sysfs node, it is possible that + * the minimum DFS frequency is higher than the maximum one. + * So we should correct this inversion phenomenon and there are two + * possible solutions. + * The first one is to change the minimum DFS frequency as the maximum + * one and is suitable for power-saving mode which requires to keep + * minimum frequency always. + * The other one is to change the maximum DFS frequency as the minimum + * one and is suitable for performance mode which requires to keep + * maximum frequency always. + */ + + /* limit min freq */ + min_index = freq_search(ctx->freq_list, ctx->freq_list_len, + gpu_freq_min_limit); + if ((min_index >= 0) && + (ctx->freq_min->freq < ctx->freq_list[min_index].freq)) { + ctx->freq_min = &ctx->freq_list[min_index]; +#if !SPRD_MATCH_DFS_TO_LOWER_FREQ + if (ctx->freq_min->freq > ctx->freq_max->freq) + ctx->freq_max = ctx->freq_min; +#endif + } + + /* limit max freq */ + max_index = freq_search(ctx->freq_list, ctx->freq_list_len, + gpu_freq_max_limit); + if ((max_index >= 0) && + (ctx->freq_max->freq > ctx->freq_list[max_index].freq)) { + ctx->freq_max = &ctx->freq_list[max_index]; +#if SPRD_MATCH_DFS_TO_LOWER_FREQ + if (ctx->freq_max->freq < ctx->freq_min->freq) + ctx->freq_min = ctx->freq_max; +#endif + } + + /* + * Scale up to maximum frequency if current load ratio is equal or + * greater than UP_THRESHOLD. + */ + if (ctx->cur_load >= (256 * UP_THRESHOLD)) { + ctx->freq_next = ctx->freq_max; + + MALI_DEBUG_PRINT(3, ("GPU_DFS util %3d; next_freq %6d\n", + ctx->cur_load, ctx->freq_next->freq)); + } else { + int target_freq = ctx->freq_cur->freq * ctx->cur_load / 256; +#if SPRD_DFS_ONE_STEP_SCALE_DOWN + /* + * Scale down one step if current load ratio is equal or less + * than DOWN_THRESHOLD. + */ + ctx->freq_next = ctx->freq_cur; + if (ctx->cur_load <= (256 * DOWN_THRESHOLD)) { + if (ctx->freq_next != &ctx->freq_list[0]) + ctx->freq_next--; + + /* Avoid meaningless scale down */ + if (ctx->freq_next->up_threshold < target_freq) + ctx->freq_next++; + } + + /* Consider limit max & min freq */ + if (ctx->freq_next->freq > ctx->freq_max->freq) + ctx->freq_next = ctx->freq_max; + else if (ctx->freq_next->freq < ctx->freq_min->freq) + ctx->freq_next = ctx->freq_min; +#else + /* Scale down to target frequency */ + ctx->freq_next = get_next_freq(ctx->freq_min, ctx->freq_max, + target_freq); +#endif + + MALI_DEBUG_PRINT(3, + ("GPU_DFS util %3d; target_freq %6d; cur_freq %6d -> next_freq %6d\n", + ctx->cur_load, target_freq, ctx->freq_cur->freq, + ctx->freq_next->freq)); + } + +#ifdef CONFIG_SYSTEM_LOAD_ANALYZER + store_external_load_factor(GPU_UTILIZATION, ctx->cur_load); +#endif + + if (ctx->freq_next->freq != ctx->freq_cur->freq) + queue_work(ctx->gpu_dfs_workqueue, &gpu_dfs_work); +#endif /* not use fpga */ +} + +bool mali_is_on(void) +{ + struct gpu_dfs_context *ctx = &gpu_dfs_ctx; + + if (ctx->gpu_power_on && ctx->gpu_clock_on) + return true; + else + MALI_DEBUG_PRINT(5, ("gpu_power_on = %d, gpu_clock_on = %d\n", + ctx->gpu_power_on, ctx->gpu_clock_on)); + + return false; +} -- 2.7.4 From c20f05f1b590313f80d4d8d1e3e742acb0878062 Mon Sep 17 00:00:00 2001 From: YoungJun Cho Date: Thu, 2 Jul 2015 19:44:49 +0900 Subject: [PATCH 02/16] ARM: mali400: r5p2_rel0: delete proprietary word in Kbuild This is to guid for non-gpl case, not related with license, but Tango detects it because it simply compares string. Change-Id: Iad42e139fd5d040b3242f1e7358720ef24343570 Signed-off-by: YoungJun Cho [jy0922.shim: applied to r5p2_rel0 from r5p0_rel0] Signed-off-by: Joonyoung Shim --- drivers/gpu/arm/mali400/r5p2_rel0/Kbuild | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/drivers/gpu/arm/mali400/r5p2_rel0/Kbuild b/drivers/gpu/arm/mali400/r5p2_rel0/Kbuild index 81b4d85..9605fd3 100644 --- a/drivers/gpu/arm/mali400/r5p2_rel0/Kbuild +++ b/drivers/gpu/arm/mali400/r5p2_rel0/Kbuild @@ -26,24 +26,8 @@ MALI_FAKE_PLATFORM_DEVICE ?= 1 DFS_ONE_STEP_SCALE_DOWN ?= 1 MATCH_DFS_TO_LOWER_FREQ ?= 1 -# For customer releases the Linux Device Drivers will be provided as ARM proprietary and GPL releases: -# The ARM proprietary product will only include the license/proprietary directory # The GPL product will only include the license/gpl directory -ifeq ($(wildcard $(src)/linux/license/gpl/*),) - ccflags-y += -I$(src)/linux/license/proprietary - ifeq ($(CONFIG_MALI400_PROFILING),y) - $(error Profiling is incompatible with non-GPL license) - endif - ifeq ($(CONFIG_PM_RUNTIME),y) - $(error Runtime PM is incompatible with non-GPL license) - endif - ifeq ($(CONFIG_DMA_SHARED_BUFFER),y) - $(error DMA-BUF is incompatible with non-GPL license) - endif - $(error Linux Device integration is incompatible with non-GPL license) -else - ccflags-y += -I$(src)/linux/license/gpl -endif +ccflags-y += -I$(src)/linux/license/gpl ifeq ($(USING_GPU_UTILIZATION), 1) ifeq ($(USING_DVFS), 1) -- 2.7.4 From 395703b8a280cfe1eaf64f8da4d55f8cdcb806af Mon Sep 17 00:00:00 2001 From: YoungJun Cho Date: Tue, 21 Jul 2015 13:19:27 +0900 Subject: [PATCH 03/16] ARM: mali400: r5p2_rel0: add GLES mem profiler feature This patch adds GLES mem profiler feature. You could use it by "cat /sys/kernel/debug/mali/gles_mem/". Without user-DDK's MALI_IOC_MEM_PROFILE_GLES_MEM, it only show layout. With this ioctl, you could check current GLES relevant memory status in opened session and also check memory leakage in trash subdirectory. The mechanism of detecting memory leakage is checking information when the session is closed. So the user misses to free (GLES)memory during session, it(the PID) could be found in trash. Caution! When app is killed and the session is forcely shut down, then it(the PID) could be found in trash but we can not guarantee there is a real memory leakage. That is because like this case, it is impossible to call MALI_IOC_MEM_PROFILE_GLES_MEM to remove allocated memory. Change-Id: I78a08f7b53594dc20f8cc6f4c892250fdc9e8208 Signed-off-by: YoungJun Cho [jy0922.shim: applied to r5p2_rel0 from r5p0_rel0] Signed-off-by: Joonyoung Shim --- drivers/gpu/arm/mali400/r5p2_rel0/Kbuild | 2 + .../arm/mali400/r5p2_rel0/common/mali_session.c | 191 ++++++++++++++++++++ .../arm/mali400/r5p2_rel0/common/mali_session.h | 76 ++++++++ .../include/linux/mali/mali_utgard_ioctl.h | 3 + .../include/linux/mali/mali_utgard_uk_types.h | 16 ++ .../mali400/r5p2_rel0/linux/mali_kernel_linux.c | 9 + .../mali400/r5p2_rel0/linux/mali_kernel_sysfs.c | 193 +++++++++++++++++++++ .../mali400/r5p2_rel0/linux/mali_kernel_sysfs.h | 6 + .../gpu/arm/mali400/r5p2_rel0/linux/mali_ukk_mem.c | 59 +++++++ .../mali400/r5p2_rel0/linux/mali_ukk_wrappers.h | 4 + 10 files changed, 559 insertions(+) diff --git a/drivers/gpu/arm/mali400/r5p2_rel0/Kbuild b/drivers/gpu/arm/mali400/r5p2_rel0/Kbuild index 9605fd3..8bd7891 100644 --- a/drivers/gpu/arm/mali400/r5p2_rel0/Kbuild +++ b/drivers/gpu/arm/mali400/r5p2_rel0/Kbuild @@ -25,6 +25,7 @@ MALI_PLATFORM ?= sc8830 MALI_FAKE_PLATFORM_DEVICE ?= 1 DFS_ONE_STEP_SCALE_DOWN ?= 1 MATCH_DFS_TO_LOWER_FREQ ?= 1 +GLES_MEM_PROFILE ?= 1 # The GPL product will only include the license/gpl directory ccflags-y += -I$(src)/linux/license/gpl @@ -134,6 +135,7 @@ ccflags-y += $(EXTRA_DEFINES) ccflags-y += -DSPRD_GPU_BOOST ccflags-y += -DSPRD_DFS_ONE_STEP_SCALE_DOWN=$(DFS_ONE_STEP_SCALE_DOWN) ccflags-y += -DSPRD_MATCH_DFS_TO_LOWER_FREQ=$(MATCH_DFS_TO_LOWER_FREQ) +ccflags-y += -DTIZEN_GLES_MEM_PROFILE=$(GLES_MEM_PROFILE) ccflags-y += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP) ccflags-y += -DMALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED=$(MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED) diff --git a/drivers/gpu/arm/mali400/r5p2_rel0/common/mali_session.c b/drivers/gpu/arm/mali400/r5p2_rel0/common/mali_session.c index 8f31e35..fd8827b 100644 --- a/drivers/gpu/arm/mali400/r5p2_rel0/common/mali_session.c +++ b/drivers/gpu/arm/mali400/r5p2_rel0/common/mali_session.c @@ -12,6 +12,9 @@ #include "mali_osk_list.h" #include "mali_session.h" #include "mali_ukk.h" +#if TIZEN_GLES_MEM_PROFILE +#include "mali_kernel_sysfs.h" +#endif _MALI_OSK_LIST_HEAD(mali_sessions); static u32 mali_session_count = 0; @@ -40,16 +43,86 @@ void mali_session_terminate(void) } } +#if TIZEN_GLES_MEM_PROFILE +static void mali_session_gles_mem_init(struct mali_session_data *session) +{ + struct mali_session_gles_mem_profile_info *info; + int i; + + mali_sysfs_gles_mem_profile_add((void *)session); + + for (i = 0; i < MALI_MAX_GLES_MEM_TYPES; i++) { + info = &(session->gles_mem_profile_info[i]); + info->type = i; + info->lock = _mali_osk_mutex_init(_MALI_OSK_LOCKFLAG_ORDERED, + _MALI_OSK_LOCK_ORDER_SESSIONS); + if (!info->lock) + MALI_PRINT_ERROR(("Mutex init failure")); + _MALI_OSK_INIT_LIST_HEAD(&(info->api_head)); + } +} + +static void mali_session_gles_mem_profile_apis_remove( + struct mali_session_gles_mem_profile_info *info) +{ + struct mali_session_gles_mem_profile_api_info *api, *tmp; + + _mali_osk_mutex_wait(info->lock); + + _MALI_OSK_LIST_FOREACHENTRY(api, tmp, &(info->api_head), + struct mali_session_gles_mem_profile_api_info, link) { + _mali_osk_list_delinit(&(api->link)); + _mali_osk_free(api); + } + + _mali_osk_mutex_signal(info->lock); +} + +static void mali_session_gles_mem_deinit(struct mali_session_data *session) +{ + struct mali_session_gles_mem_profile_trash_info *trash_info = NULL; + struct mali_session_gles_mem_profile_info *info; + int i; + + for (i = 0; i < MALI_MAX_GLES_MEM_TYPES; i++) { + info = &(session->gles_mem_profile_info[i]); + if (!info->lock) + continue; + + if (info->size) { + trash_info = + (struct mali_session_gles_mem_profile_trash_info *) + mali_sysfs_gles_mem_profile_move_to_trash( + (void *)trash_info, + (void *)session, i); + } else + mali_session_gles_mem_profile_apis_remove(info); + + _mali_osk_mutex_term(info->lock); + } + + mali_sysfs_gles_mem_profile_remove((void *)session); +} +#endif /* TIZEN_GLES_MEM_PROFILE */ + void mali_session_add(struct mali_session_data *session) { mali_session_lock(); _mali_osk_list_add(&session->link, &mali_sessions); mali_session_count++; mali_session_unlock(); + +#if TIZEN_GLES_MEM_PROFILE + mali_session_gles_mem_init(session); +#endif } void mali_session_remove(struct mali_session_data *session) { +#if TIZEN_GLES_MEM_PROFILE + mali_session_gles_mem_deinit(session); +#endif + mali_session_lock(); _mali_osk_list_delinit(&session->link); mali_session_count--; @@ -111,3 +184,121 @@ void mali_session_memory_tracking(_mali_osk_print_ctx *print_ctx) total_mali_mem_size = _mali_ukk_report_total_memory_size(); _mali_osk_ctxprintf(print_ctx, "Mali mem usage: %u\nMali mem limit: %u\n", mali_mem_usage, total_mali_mem_size); } + +#if TIZEN_GLES_MEM_PROFILE +void mali_session_gles_mem_profile_api_add( + struct mali_session_gles_mem_profile_info *info, + struct mali_session_gles_mem_profile_api_info *api, + _mali_osk_list_t *head) +{ + if (!info->lock) + return; + + _mali_osk_mutex_wait(info->lock); + + _mali_osk_list_add(&(api->link), head); + + _mali_osk_mutex_signal(info->lock); +} + +static const char *mali_session_gles_mem_profile_to_str( + enum mali_session_gles_mem_profile_type type) +{ + switch (type) { + case MALI_GLES_MEM_UNTYPED: + return "mali_gles_mem Untyped"; + case MALI_GLES_MEM_VB_IB: + return "mali_gles_mem Vertex & Index buffer"; + case MALI_GLES_MEM_TEXTURE: + return "mali_gles_mem Texture"; + case MALI_GLES_MEM_RSW: + return "mali_gles_mem RSW"; + case MALI_GLES_MEM_PLBU_HEAP: + return "mali_gles_mem PLBU heap"; + case MALI_GLES_MEM_UNTYPE_GP_CMD_LIST: + return "mali_gles_mem Uuntyped GP cmd list"; + case MALI_GLES_MEM_SHADER: + return "mali_gles_mem Shader"; + case MALI_GLES_MEM_TD: + return "mali_gles_mem TD"; + case MALI_GLES_MEM_UNTYPE_FRAME_POOL: + return "mali_gles_mem Untyped frame pool"; + case MALI_GLES_MEM_UNTYPE_SURFACE: + return "mali_gles_mem Untyped surface"; + case MALI_GLES_MEM_RT: + return "mali_gles_mem Render target"; + case MALI_GLES_MEM_VARYING: + return "mali_gles_mem Varying buffer"; + case MALI_GLES_MEM_STREAMS: + return "mali_gles_mem Streams buffer"; + case MALI_GLES_MEM_POINTER_ARRAY: + return "mali_gles_mem Pointer array buffer"; + case MALI_GLES_MEM_SLAVE_TILE_LIST: + return "mali_gles_mem Slave tile list buffer"; + case MALI_GLES_MEM_POLYGON_CMD_LIST: + return "mali_gles_mem Polygon cmd list"; + case MALI_GLES_MEM_FRAGMENT_STACK: + return "mali_gles_mem Fragment stack"; + case MALI_GLES_MEM_UNIFORM: + return "mali_gles_mem Uniforms"; + case MALI_GLES_MEM_PBUFFER: + return "mali_gles_mem Pbuffer"; + default: + return "mali_gles_mem Untyped"; + } +} + +static void mali_session_gles_mem_profile_api_tracking( + _mali_osk_print_ctx *print_ctx, + struct mali_session_gles_mem_profile_info *info) +{ + struct mali_session_gles_mem_profile_api_info *api, *tmp; + + _MALI_OSK_LIST_FOREACHENTRY(api, tmp, &(info->api_head), + struct mali_session_gles_mem_profile_api_info, link) { + _mali_osk_ctxprintf(print_ctx, "\t| %-36s\t%-30d\n", + api->api, api->size); + } +} + +s64 mali_session_gles_mem_profile_info_tracking(_mali_osk_print_ctx *print_ctx, + void *data, bool trash) +{ + struct mali_session_gles_mem_profile_trash_info *trash_info = NULL; + struct mali_session_gles_mem_profile_info *info; + struct mali_session_data *session = NULL; + s64 total_size = 0; + int i; + + MALI_DEBUG_ASSERT_POINTER(print_ctx); + MALI_DEBUG_ASSERT_POINTER(data); + + if (trash) { + trash_info = + (struct mali_session_gles_mem_profile_trash_info *)data; + } else + session = (struct mali_session_data *)data; + + for (i = 0; i < MALI_MAX_GLES_MEM_TYPES; i++) { + if (trash) + info = &(trash_info->info[i]); + else + info = &(session->gles_mem_profile_info[i]); + if (!info->lock) + continue; + + _mali_osk_mutex_wait(info->lock); + + _mali_osk_ctxprintf(print_ctx, "%-36s\t%-30lld\n", + mali_session_gles_mem_profile_to_str( + i << MALI_GLES_MEM_SHIFT), + info->size); + mali_session_gles_mem_profile_api_tracking(print_ctx, info); + total_size += info->size; + + _mali_osk_mutex_signal(info->lock); + } + + return total_size; +} +#endif /* TIZEN_GLES_MEM_PROFILE */ diff --git a/drivers/gpu/arm/mali400/r5p2_rel0/common/mali_session.h b/drivers/gpu/arm/mali400/r5p2_rel0/common/mali_session.h index 02256cf..9158be4 100644 --- a/drivers/gpu/arm/mali400/r5p2_rel0/common/mali_session.h +++ b/drivers/gpu/arm/mali400/r5p2_rel0/common/mali_session.h @@ -23,6 +23,67 @@ struct mali_soft_system; /* Number of frame builder job lists per session. */ #define MALI_PP_JOB_FB_LOOKUP_LIST_SIZE 16 #define MALI_PP_JOB_FB_LOOKUP_LIST_MASK (MALI_PP_JOB_FB_LOOKUP_LIST_SIZE - 1) +#if TIZEN_GLES_MEM_PROFILE +#define MALI_GLES_MEM_SHIFT 8 + +enum mali_session_gles_mem_profile_type { + MALI_GLES_MEM_PP_READ = (1 << 0), + MALI_GLES_MEM_PP_WRITE = (1 << 1), + MALI_GLES_MEM_GP_READ = (1 << 2), + MALI_GLES_MEM_GP_WRITE = (1 << 3), + MALI_GLES_MEM_CPU_READ = (1 << 4), + MALI_GLES_MEM_CPU_WRITE = (1 << 5), + MALI_GLES_MEM_GP_L2_ALLOC = (1 << 6), + MALI_GLES_MEM_FRAME_POOL_ALLOC = (1 << 7), + /* type of this mem block */ + MALI_GLES_MEM_UNTYPED = (0 << MALI_GLES_MEM_SHIFT), + MALI_GLES_MEM_VB_IB = (1 << MALI_GLES_MEM_SHIFT), + MALI_GLES_MEM_TEXTURE = (2 << MALI_GLES_MEM_SHIFT), + MALI_GLES_MEM_VARYING = (3 << MALI_GLES_MEM_SHIFT), + MALI_GLES_MEM_RT = (4 << MALI_GLES_MEM_SHIFT), + MALI_GLES_MEM_PBUFFER = (5 << MALI_GLES_MEM_SHIFT), + /* memory types for gp command */ + MALI_GLES_MEM_PLBU_HEAP = (6 << MALI_GLES_MEM_SHIFT), + MALI_GLES_MEM_POINTER_ARRAY = (7 << MALI_GLES_MEM_SHIFT), + MALI_GLES_MEM_SLAVE_TILE_LIST = (8 << MALI_GLES_MEM_SHIFT), + MALI_GLES_MEM_UNTYPE_GP_CMD_LIST = (9 << MALI_GLES_MEM_SHIFT), + /* memory type for polygon list command */ + MALI_GLES_MEM_POLYGON_CMD_LIST = (10 << MALI_GLES_MEM_SHIFT), + /* memory types for pp command */ + MALI_GLES_MEM_TD = (11 << MALI_GLES_MEM_SHIFT), + MALI_GLES_MEM_RSW = (12 << MALI_GLES_MEM_SHIFT), + /* other memory types */ + MALI_GLES_MEM_SHADER = (13 << MALI_GLES_MEM_SHIFT), + MALI_GLES_MEM_STREAMS = (14 << MALI_GLES_MEM_SHIFT), + MALI_GLES_MEM_FRAGMENT_STACK = (15 << MALI_GLES_MEM_SHIFT), + MALI_GLES_MEM_UNIFORM = (16 << MALI_GLES_MEM_SHIFT), + MALI_GLES_MEM_UNTYPE_FRAME_POOL = (17 << MALI_GLES_MEM_SHIFT), + MALI_GLES_MEM_UNTYPE_SURFACE = (18 << MALI_GLES_MEM_SHIFT), + MALI_GLES_MEM_MAX = (19 << MALI_GLES_MEM_SHIFT), +}; + +#define MALI_MAX_GLES_MEM_TYPES (MALI_GLES_MEM_MAX >> MALI_GLES_MEM_SHIFT) + +struct mali_session_gles_mem_profile_api_info { + char api[64]; /**< API name */ + u16 id; /**< API ID */ + int size; /**< Total size for this API */ + _MALI_OSK_LIST_HEAD(link); /**< Link for the list of all EGL/GL API */ +}; + +struct mali_session_gles_mem_profile_info { + u32 type; /**< Memory type ID */ + s64 size; /**< Total sizes for this type */ + _mali_osk_mutex_t *lock; /**< Mutex lock */ + _mali_osk_list_t api_head; /**< List of all EGL/GL APIs for this type */ +}; + +struct mali_session_gles_mem_profile_trash_info { + u32 pid; + char *comm; + struct mali_session_gles_mem_profile_info info[MALI_MAX_GLES_MEM_TYPES]; +}; +#endif /* TIZEN_GLES_MEM_PROFILE */ struct mali_session_data { _mali_osk_notification_queue_t *ioctl_queue; @@ -57,6 +118,12 @@ struct mali_session_data { #ifdef SPRD_GPU_BOOST int level; #endif + +#if TIZEN_GLES_MEM_PROFILE + struct dentry *gles_mem_profile_dentry; + struct mali_session_gles_mem_profile_info + gles_mem_profile_info[MALI_MAX_GLES_MEM_TYPES]; +#endif }; _mali_osk_errcode_t mali_session_initialize(void); @@ -124,4 +191,13 @@ u32 mali_session_max_window_num(void); void mali_session_memory_tracking(_mali_osk_print_ctx *print_ctx); +#if TIZEN_GLES_MEM_PROFILE +void mali_session_gles_mem_profile_api_add( + struct mali_session_gles_mem_profile_info *info, + struct mali_session_gles_mem_profile_api_info *api, + _mali_osk_list_t *head); +s64 mali_session_gles_mem_profile_info_tracking(_mali_osk_print_ctx *print_ctx, + void *data, bool trash); +#endif + #endif /* __MALI_SESSION_H__ */ diff --git a/drivers/gpu/arm/mali400/r5p2_rel0/include/linux/mali/mali_utgard_ioctl.h b/drivers/gpu/arm/mali400/r5p2_rel0/include/linux/mali/mali_utgard_ioctl.h index 72585f4..e0e2c4f 100644 --- a/drivers/gpu/arm/mali400/r5p2_rel0/include/linux/mali/mali_utgard_ioctl.h +++ b/drivers/gpu/arm/mali400/r5p2_rel0/include/linux/mali/mali_utgard_ioctl.h @@ -62,6 +62,9 @@ extern "C" { #define MALI_IOC_MEM_QUERY_MMU_PAGE_TABLE_DUMP_SIZE _IOR (MALI_IOC_MEMORY_BASE, _MALI_UK_QUERY_MMU_PAGE_TABLE_DUMP_SIZE, _mali_uk_query_mmu_page_table_dump_size_s) #define MALI_IOC_MEM_DUMP_MMU_PAGE_TABLE _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_DUMP_MMU_PAGE_TABLE, _mali_uk_dump_mmu_page_table_s) #define MALI_IOC_MEM_WRITE_SAFE _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_MEM_WRITE_SAFE, _mali_uk_mem_write_safe_s) +#if TIZEN_GLES_MEM_PROFILE +#define MALI_IOC_MEM_PROFILE_GLES_MEM _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_GLES_MEM_PROFILER, _mali_uk_gles_mem_profiler_s) +#endif #define MALI_IOC_PP_START_JOB _IOWR(MALI_IOC_PP_BASE, _MALI_UK_PP_START_JOB, _mali_uk_pp_start_job_s) #define MALI_IOC_PP_AND_GP_START_JOB _IOWR(MALI_IOC_PP_BASE, _MALI_UK_PP_AND_GP_START_JOB, _mali_uk_pp_and_gp_start_job_s) diff --git a/drivers/gpu/arm/mali400/r5p2_rel0/include/linux/mali/mali_utgard_uk_types.h b/drivers/gpu/arm/mali400/r5p2_rel0/include/linux/mali/mali_utgard_uk_types.h index 4344b2f..fd6e51a 100644 --- a/drivers/gpu/arm/mali400/r5p2_rel0/include/linux/mali/mali_utgard_uk_types.h +++ b/drivers/gpu/arm/mali400/r5p2_rel0/include/linux/mali/mali_utgard_uk_types.h @@ -95,6 +95,9 @@ typedef enum { _MALI_UK_DUMP_MMU_PAGE_TABLE, /**< _mali_ukk_mem_dump_mmu_page_table() */ _MALI_UK_DMA_BUF_GET_SIZE, /**< _mali_ukk_dma_buf_get_size() */ _MALI_UK_MEM_WRITE_SAFE, /**< _mali_uku_mem_write_safe() */ +#if TIZEN_GLES_MEM_PROFILE + _MALI_UK_GLES_MEM_PROFILER, /**< _mali_uku_gles_mem_profiler() */ +#endif /** Common functions for each core */ @@ -840,6 +843,19 @@ typedef struct { u64 page_table_dump; /**< [out] pointer within buffer where MMU page table dump is stored */ } _mali_uk_dump_mmu_page_table_s; +#if TIZEN_GLES_MEM_PROFILE +/** + * @brief Arguments for _mali_uk[uk]_gles_mem_profiler() + */ +typedef struct { + u64 ctx; /**< [in,out] user-kernel context (trashed on output) */ + char api[64]; /**< [in] OpenGLES or EGL API function name */ + u32 entrypoint;/**< [in] OpenGLES or EGL API entrypoint */ + u32 type; /**< [in] Type of memory */ + int size; /**< [in] Number of bytes. +ve means allocated. -ve means freed */ +} _mali_uk_gles_mem_profiler_s; +#endif + /** @} */ /* end group _mali_uk_memory */ diff --git a/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_kernel_linux.c b/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_kernel_linux.c index e1fe5f3..2493266 100644 --- a/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_kernel_linux.c +++ b/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_kernel_linux.c @@ -883,6 +883,15 @@ static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, #endif break; +#if TIZEN_GLES_MEM_PROFILE + case MALI_IOC_MEM_PROFILE_GLES_MEM: + BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_gles_mem_profiler_s), + sizeof(u64))); + err = mem_profile_gles_mem(session_data, + (_mali_uk_gles_mem_profiler_s __user *)arg); + break; +#endif + case MALI_IOC_PP_START_JOB: BUILD_BUG_ON(!IS_ALIGNED(sizeof(_mali_uk_pp_start_job_s), sizeof(u64))); err = pp_start_job_wrapper(session_data, (_mali_uk_pp_start_job_s __user *)arg); diff --git a/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_kernel_sysfs.c b/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_kernel_sysfs.c index ea334c9..34e0084 100644 --- a/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_kernel_sysfs.c +++ b/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_kernel_sysfs.c @@ -61,6 +61,10 @@ #define POWER_BUFFER_SIZE 3 static struct dentry *mali_debugfs_dir = NULL; +#if TIZEN_GLES_MEM_PROFILE +struct dentry *mali_gles_mem_profile_dir; +struct dentry *mali_gles_mem_profile_trash_dir; +#endif typedef enum { _MALI_DEVICE_SUSPEND, @@ -1357,6 +1361,12 @@ int mali_sysfs_register(const char *mali_dev_name) #endif } +#if TIZEN_GLES_MEM_PROFILE + mali_gles_mem_profile_dir = debugfs_create_dir( + "gles_mem", + mali_debugfs_dir); +#endif + #if MALI_STATE_TRACKING debugfs_create_file("state_dump", 0400, mali_debugfs_dir, NULL, &mali_seq_internal_state_fops); #endif @@ -1383,6 +1393,172 @@ int mali_sysfs_unregister(void) return 0; } +#if TIZEN_GLES_MEM_PROFILE +static void gles_mem_profile_show_common(struct seq_file *s, char *comm, + u32 pid) +{ + seq_printf(s, + "%s\n" + "%s (%s)\t\t%s(%d)\n" + "%s\n%s\t\t\t\t%s(%s)\n" + "\t| %s\t\t\t\t%s(%s)\n%s\n", + "===============================================================", + "Process name", comm, "Process ID", pid, + "---------------------------------------------------------------", + "Type Name", "Type Usage", "bytes", "API Name", "API Usage", "bytes", + "***************************************************************"); +} + +static int gles_mem_profile_show(struct seq_file *s, void *private_data) +{ + struct mali_session_data *session = + (struct mali_session_data *)(s->private); + + gles_mem_profile_show_common(s, session->comm, session->pid); + + seq_printf(s, "\n\nTotal Mali GLES mem usage: %lld (bytes)\n", + mali_session_gles_mem_profile_info_tracking(s, + (void *)session, + false)); + + return 0; +} + +static int gles_mem_profile_open(struct inode *inode, struct file *file) +{ + return single_open(file, gles_mem_profile_show, inode->i_private); +} + +static const struct file_operations gles_mem_profile_fops = { + .owner = THIS_MODULE, + .open = gles_mem_profile_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release +}; + +int mali_sysfs_gles_mem_profile_add(void *data) +{ + struct mali_session_data *session = (struct mali_session_data *)data; + char name[11]; + + if (!mali_gles_mem_profile_dir) + return 0; + + _mali_osk_snprintf(name, sizeof(name), "%u", session->pid); + session->gles_mem_profile_dentry = + debugfs_create_file(name, S_IRUSR, + mali_gles_mem_profile_dir, + (void *)session, + &gles_mem_profile_fops); + + return 0; +} + +void mali_sysfs_gles_mem_profile_remove(void *data) +{ + struct mali_session_data *session = (struct mali_session_data *)data; + + debugfs_remove(session->gles_mem_profile_dentry); +} + +static int gles_mem_profile_trash_show(struct seq_file *s, void *private_data) +{ + struct mali_session_gles_mem_profile_trash_info *trash_info = + (struct mali_session_gles_mem_profile_trash_info *)(s->private); + + gles_mem_profile_show_common(s, trash_info->comm, trash_info->pid); + + seq_printf(s, "\n\nTotal Mali GLES mem usage: %lld (bytes)\n", + mali_session_gles_mem_profile_info_tracking(s, + (void *)trash_info, + true)); + + return 0; +} + +static int gles_mem_profile_trash_open(struct inode *inode, struct file *file) +{ + return single_open(file, gles_mem_profile_trash_show, inode->i_private); +} + +static const struct file_operations gles_mem_profile_trash_fops = { + .owner = THIS_MODULE, + .open = gles_mem_profile_trash_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release +}; + +void *mali_sysfs_gles_mem_profile_move_to_trash(void *data1, void *data2, + int idx) +{ + struct mali_session_gles_mem_profile_trash_info *trash_info = + (struct mali_session_gles_mem_profile_trash_info *)data1; + struct mali_session_data *session = (struct mali_session_data *)data2; + struct mali_session_gles_mem_profile_info *tinfo, *info; + + if (!mali_gles_mem_profile_dir) + return NULL; + + if (!trash_info) { + char name[11]; + int i; + + trash_info = + (struct mali_session_gles_mem_profile_trash_info *) + _mali_osk_calloc(1, + sizeof(struct mali_session_gles_mem_profile_trash_info) + ); + if (!trash_info) { + MALI_PRINT_ERROR(("TrashInfo alloc failure")); + return NULL; + } + + trash_info->pid = session->pid; + trash_info->comm = session->comm; + + for (i = 0; i < MALI_MAX_GLES_MEM_TYPES; i++) { + tinfo = &(trash_info->info[i]); + tinfo->type = i; + tinfo->lock = + _mali_osk_mutex_init(_MALI_OSK_LOCKFLAG_ORDERED, + _MALI_OSK_LOCK_ORDER_SESSIONS); + if (!tinfo->lock) + MALI_PRINT_ERROR(("Mutex init failure")); + _MALI_OSK_INIT_LIST_HEAD(&(tinfo->api_head)); + } + + if (!mali_gles_mem_profile_trash_dir) { + mali_gles_mem_profile_trash_dir = + debugfs_create_dir("trash", + mali_gles_mem_profile_dir); + } + + _mali_osk_snprintf(name, sizeof(name), "%u", trash_info->pid); + debugfs_create_file(name, S_IRUSR, + mali_gles_mem_profile_trash_dir, + (void *)trash_info, + &gles_mem_profile_trash_fops); + } + + tinfo = &(trash_info->info[idx]); + info = &(session->gles_mem_profile_info[idx]); + + _mali_osk_mutex_wait(info->lock); + + if (tinfo->lock) { + tinfo->type = info->type; + tinfo->size = info->size; + _mali_osk_list_move_list(&(info->api_head), &(tinfo->api_head)); + } + + _mali_osk_mutex_signal(info->lock); + + return trash_info; +} +#endif /* TIZEN_GLES_MEM_PROFILE */ + #else /* MALI_LICENSE_IS_GPL */ /* Dummy implementations for non-GPL */ @@ -1397,4 +1573,21 @@ int mali_sysfs_unregister(void) return 0; } +#if TIZEN_GLES_MEM_PROFILE +int mali_sysfs_gles_mem_profile_add(void *data) +{ + return 0; +} + +void mali_sysfs_gles_mem_profile_remove(void *data) +{ + return; +} + +void *mali_sysfs_gles_mem_profile_move_to_trash(void *data1, void *data2, + int idx) +{ + return NULL; +} +#endif /* TIZEN_GLES_MEM_PROFILE */ #endif /* MALI_LICENSE_IS_GPL */ diff --git a/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_kernel_sysfs.h b/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_kernel_sysfs.h index a36a0ce..7fcc04f 100644 --- a/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_kernel_sysfs.h +++ b/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_kernel_sysfs.h @@ -21,6 +21,12 @@ extern "C" { int mali_sysfs_register(const char *mali_dev_name); int mali_sysfs_unregister(void); +#if TIZEN_GLES_MEM_PROFILE +int mali_sysfs_gles_mem_profile_add(void *data); +void mali_sysfs_gles_mem_profile_remove(void *data); +void *mali_sysfs_gles_mem_profile_move_to_trash(void *data1, void *data2, + int idx); +#endif #ifdef __cplusplus } diff --git a/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_ukk_mem.c b/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_ukk_mem.c index 96a0d42..c03ac8a 100644 --- a/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_ukk_mem.c +++ b/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_ukk_mem.c @@ -308,3 +308,62 @@ int mem_usage_get_wrapper(struct mali_session_data *session_data, _mali_uk_profi return 0; } +#if TIZEN_GLES_MEM_PROFILE +int mem_profile_gles_mem(struct mali_session_data *session_data, + _mali_uk_gles_mem_profiler_s __user *uargs) +{ + _mali_uk_gles_mem_profiler_s kargs; + struct mali_session_gles_mem_profile_info *info; + struct mali_session_gles_mem_profile_api_info *api, *tmp; + mali_bool flag = MALI_FALSE; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + MALI_CHECK_NON_NULL(session_data, -EINVAL); + + if (copy_from_user(&kargs, uargs, sizeof(_mali_uk_gles_mem_profiler_s))) + return -EFAULT; + + kargs.ctx = (uintptr_t)session_data; + + info = &session_data->gles_mem_profile_info[kargs.type]; + if (!info) { + MALI_PRINT_ERROR(("No info is available. Something wrong")); + return -EINVAL; + } + + _MALI_OSK_LIST_FOREACHENTRY(api, tmp, &(info->api_head), + struct mali_session_gles_mem_profile_api_info, link) { + if (api->id == (u16)kargs.entrypoint) { + /* This API is recorded already. Update it. */ + api->size += kargs.size; + info->size += kargs.size; + flag = MALI_TRUE; + break; + } + } + + if (flag == MALI_FALSE) { + /* + * This is the first time the API is recorded for this info. + * So add it. + */ + api = (struct mali_session_gles_mem_profile_api_info *) + _mali_osk_calloc(1, + sizeof(struct mali_session_gles_mem_profile_api_info)); + if (!api) { + MALI_PRINT_ERROR(("Alloc failure")); + return -ENOMEM; + } + memcpy(&api->api, &kargs.api, sizeof(api->api)); + + api->id = (u16)kargs.entrypoint; + api->size += kargs.size; + info->size += kargs.size; + + mali_session_gles_mem_profile_api_add(info, api, + &(info->api_head)); + } + + return 0; +} +#endif diff --git a/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_ukk_wrappers.h b/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_ukk_wrappers.h index 9eef135..4e80c3d 100644 --- a/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_ukk_wrappers.h +++ b/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_ukk_wrappers.h @@ -40,6 +40,10 @@ int mem_write_safe_wrapper(struct mali_session_data *session_data, _mali_uk_mem_ int mem_query_mmu_page_table_dump_size_wrapper(struct mali_session_data *session_data, _mali_uk_query_mmu_page_table_dump_size_s __user *uargs); int mem_dump_mmu_page_table_wrapper(struct mali_session_data *session_data, _mali_uk_dump_mmu_page_table_s __user *uargs); int mem_usage_get_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_memory_usage_get_s __user *uargs); +#if TIZEN_GLES_MEM_PROFILE +int mem_profile_gles_mem(struct mali_session_data *session_data, + _mali_uk_gles_mem_profiler_s __user *uargs); +#endif int timeline_get_latest_point_wrapper(struct mali_session_data *session, _mali_uk_timeline_get_latest_point_s __user *uargs); int timeline_wait_wrapper(struct mali_session_data *session, _mali_uk_timeline_wait_s __user *uargs); -- 2.7.4 From 0822685323171c28c5cf1c9d6a7dc608c5c8e17a Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Tue, 17 May 2016 13:58:08 +0900 Subject: [PATCH 04/16] ARM: mali400: fix building out of tree s/$(src)/$(srctree)\/$(src)/ $(srctree) has absolute path of kernel root directory, so with this commit, building problem by relative path will be gone from outside of kernel tree. Change-Id: Ib6e4a23a5858b029c75b7e760082846a2247f21a Signed-off-by: Joonyoung Shim --- drivers/gpu/arm/mali400/r4p0_rel0/Kbuild | 24 ++++++++++++------------ drivers/gpu/arm/mali400/r5p0_rel0/Kbuild | 24 ++++++++++++------------ drivers/gpu/arm/mali400/r5p2_rel0/Kbuild | 24 ++++++++++++------------ 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/arm/mali400/r4p0_rel0/Kbuild b/drivers/gpu/arm/mali400/r4p0_rel0/Kbuild index 184e444..98d8874 100755 --- a/drivers/gpu/arm/mali400/r4p0_rel0/Kbuild +++ b/drivers/gpu/arm/mali400/r4p0_rel0/Kbuild @@ -31,7 +31,7 @@ DFS_ONE_STEP_SCALE_DOWN ?= 1 MATCH_DFS_TO_LOWER_FREQ ?= 1 # The GPL product will only include the license/gpl directory -ccflags-y += -I$(src)/linux/license/gpl +ccflags-y += -I$(srctree)/$(src)/linux/license/gpl ifeq ($(CONFIG_MALI400),y) MALI_ENABLE_GPU_CONTROL_IN_PARAM = 0 @@ -115,7 +115,7 @@ mali-$(CONFIG_MALI400_PROFILING) += linux/mali_ukk_profiling.o mali-$(CONFIG_MALI400_PROFILING) += linux/mali_osk_profiling.o mali-$(CONFIG_MALI400_INTERNAL_PROFILING) += linux/mali_profiling_internal.o timestamp-$(TIMESTAMP)/mali_timestamp.o -ccflags-$(CONFIG_MALI400_INTERNAL_PROFILING) += -I$(src)/timestamp-$(TIMESTAMP) +ccflags-$(CONFIG_MALI400_INTERNAL_PROFILING) += -I$(srctree)/$(src)/timestamp-$(TIMESTAMP) mali-$(CONFIG_DMA_SHARED_BUFFER) += linux/mali_memory_dma_buf.o mali-$(CONFIG_SYNC) += linux/mali_sync.o @@ -155,16 +155,16 @@ ifeq ($(MALI_UPPER_HALF_SCHEDULING),1) ccflags-y += -DMALI_UPPER_HALF_SCHEDULING endif -ccflags-$(CONFIG_MALI400_UMP) += -I$(src)/../ump/include/ump +ccflags-$(CONFIG_MALI400_UMP) += -I$(srctree)/$(src)/../ump/include/ump ccflags-$(CONFIG_MALI400_DEBUG) += -DDEBUG # Use our defines when compiling -ccflags-y += -I$(src) -I$(src)/include -I$(src)/common -I$(src)/linux -I$(src)/platform -I$(src)/platform/$(MALI_PLATFORM) +ccflags-y += -I$(srctree)/$(src) -I$(srctree)/$(src)/include -I$(srctree)/$(src)/common -I$(srctree)/$(src)/linux -I$(srctree)/$(src)/platform -I$(srctree)/$(src)/platform/$(MALI_PLATFORM) # Get subversion revision number, fall back to only ${MALI_RELEASE_NAME} if no svn info is available -MALI_RELEASE_NAME=$(shell cat $(src)/.version 2> /dev/null) +MALI_RELEASE_NAME=$(shell cat $(srctree)/$(src)/.version 2> /dev/null) -#SVN_INFO = (cd $(src); svn info 2>/dev/null) +#SVN_INFO = (cd $(srctree)/$(src); svn info 2>/dev/null) ifneq ($(shell $(SVN_INFO) 2>/dev/null),) # SVN detected @@ -175,13 +175,13 @@ CHANGED_REVISION := $(shell $(SVN_INFO) | grep '^Last Changed Rev: ' | cut -d: - REPO_URL := $(shell $(SVN_INFO) | grep '^URL: ' | cut -d: -f2- | cut -b2-) else # SVN -#GIT_REV := $(shell cd $(src); git describe --always 2>/dev/null) +#GIT_REV := $(shell cd $(srctree)/$(src); git describe --always 2>/dev/null) ifneq ($(GIT_REV),) # Git detected DRIVER_REV := $(MALI_RELEASE_NAME)-$(GIT_REV) -CHANGE_DATE := $(shell cd $(src); git log -1 --format="%ci") +CHANGE_DATE := $(shell cd $(srctree)/$(src); git log -1 --format="%ci") CHANGED_REVISION := $(GIT_REV) -REPO_URL := $(shell cd $(src); git describe --all --always 2>/dev/null) +REPO_URL := $(shell cd $(srctree)/$(src); git describe --all --always 2>/dev/null) else # Git # No Git or SVN detected @@ -194,7 +194,7 @@ endif ccflags-y += -DSVN_REV_STRING=\"$(DRIVER_REV)\" VERSION_STRINGS := -VERSION_STRINGS += API_VERSION=$(shell cd $(src); grep "\#define _MALI_API_VERSION" $(FILES_PREFIX)include/linux/mali/mali_utgard_uk_types.h | cut -d' ' -f 3 ) +VERSION_STRINGS += API_VERSION=$(shell cd $(srctree)/$(src); grep "\#define _MALI_API_VERSION" $(FILES_PREFIX)include/linux/mali/mali_utgard_uk_types.h | cut -d' ' -f 3 ) VERSION_STRINGS += REPO_URL=$(REPO_URL) VERSION_STRINGS += REVISION=$(DRIVER_REV) VERSION_STRINGS += CHANGED_REVISION=$(CHANGED_REVISION) @@ -217,5 +217,5 @@ VERSION_STRINGS += USING_POWER_PERFORMANCE_POLICY=$(CONFIG_POWER_PERFORMANCE_POL VERSION_STRINGS += MALI_UPPER_HALF_SCHEDULING=$(MALI_UPPER_HALF_SCHEDULING) # Create file with Mali driver configuration -$(src)/__malidrv_build_info.c: - @echo 'const char *__malidrv_build_info(void) { return "malidrv: $(VERSION_STRINGS)";}' > $(src)/__malidrv_build_info.c +$(srctree)/$(src)/__malidrv_build_info.c: + @echo 'const char *__malidrv_build_info(void) { return "malidrv: $(VERSION_STRINGS)";}' > $(srctree)/$(src)/__malidrv_build_info.c diff --git a/drivers/gpu/arm/mali400/r5p0_rel0/Kbuild b/drivers/gpu/arm/mali400/r5p0_rel0/Kbuild index 34f6974..ae86206 100644 --- a/drivers/gpu/arm/mali400/r5p0_rel0/Kbuild +++ b/drivers/gpu/arm/mali400/r5p0_rel0/Kbuild @@ -28,7 +28,7 @@ MATCH_DFS_TO_LOWER_FREQ ?= 1 GLES_MEM_PROFILE ?= 1 # The GPL product will only include the license/gpl directory -ccflags-y += -I$(src)/linux/license/gpl +ccflags-y += -I$(srctree)/$(src)/linux/license/gpl ifeq ($(USING_GPU_UTILIZATION), 1) ifeq ($(USING_DVFS), 1) @@ -111,7 +111,7 @@ mali-$(CONFIG_MALI400_PROFILING) += linux/mali_ukk_profiling.o mali-$(CONFIG_MALI400_PROFILING) += linux/mali_osk_profiling.o mali-$(CONFIG_MALI400_INTERNAL_PROFILING) += linux/mali_profiling_internal.o timestamp-$(TIMESTAMP)/mali_timestamp.o -ccflags-$(CONFIG_MALI400_INTERNAL_PROFILING) += -I$(src)/timestamp-$(TIMESTAMP) +ccflags-$(CONFIG_MALI400_INTERNAL_PROFILING) += -I$(srctree)/$(src)/timestamp-$(TIMESTAMP) mali-$(CONFIG_DMA_SHARED_BUFFER) += linux/mali_memory_dma_buf.o mali-$(CONFIG_SYNC) += linux/mali_sync.o @@ -146,16 +146,16 @@ ifeq ($(MALI_UPPER_HALF_SCHEDULING),1) ccflags-y += -DMALI_UPPER_HALF_SCHEDULING endif -ccflags-$(CONFIG_MALI400_UMP) += -I$(src)/../ump/include/ump +ccflags-$(CONFIG_MALI400_UMP) += -I$(srctree)/$(src)/../ump/include/ump ccflags-$(CONFIG_MALI400_DEBUG) += -DDEBUG # Use our defines when compiling -ccflags-y += -I$(src) -I$(src)/include -I$(src)/common -I$(src)/linux -I$(src)/platform -I$(src)/platform/$(MALI_PLATFORM) +ccflags-y += -I$(srctree)/$(src) -I$(srctree)/$(src)/include -I$(srctree)/$(src)/common -I$(srctree)/$(src)/linux -I$(srctree)/$(src)/platform -I$(srctree)/$(src)/platform/$(MALI_PLATFORM) # Get subversion revision number, fall back to only ${MALI_RELEASE_NAME} if no svn info is available -MALI_RELEASE_NAME=$(shell cat $(src)/.version 2> /dev/null) +MALI_RELEASE_NAME=$(shell cat $(srctree)/$(src)/.version 2> /dev/null) -#SVN_INFO = (cd $(src); svn info 2>/dev/null) +#SVN_INFO = (cd $(srctree)/$(src); svn info 2>/dev/null) ifneq ($(shell $(SVN_INFO) 2>/dev/null),) # SVN detected @@ -166,13 +166,13 @@ CHANGED_REVISION := $(shell $(SVN_INFO) | grep '^Last Changed Rev: ' | cut -d: - REPO_URL := $(shell $(SVN_INFO) | grep '^URL: ' | cut -d: -f2- | cut -b2-) else # SVN -#GIT_REV := $(shell cd $(src); git describe --always 2>/dev/null) +#GIT_REV := $(shell cd $(srctree)/$(src); git describe --always 2>/dev/null) ifneq ($(GIT_REV),) # Git detected DRIVER_REV := $(MALI_RELEASE_NAME)-$(GIT_REV) -CHANGE_DATE := $(shell cd $(src); git log -1 --format="%ci") +CHANGE_DATE := $(shell cd $(srctree)/$(src); git log -1 --format="%ci") CHANGED_REVISION := $(GIT_REV) -REPO_URL := $(shell cd $(src); git describe --all --always 2>/dev/null) +REPO_URL := $(shell cd $(srctree)/$(src); git describe --all --always 2>/dev/null) else # Git # No Git or SVN detected @@ -186,7 +186,7 @@ ccflags-y += -DSVN_REV_STRING=\"$(DRIVER_REV)\" ccflags-y += -fno-PIC VERSION_STRINGS := -VERSION_STRINGS += API_VERSION=$(shell cd $(src); grep "\#define _MALI_API_VERSION" $(FILES_PREFIX)include/linux/mali/mali_utgard_uk_types.h | cut -d' ' -f 3 ) +VERSION_STRINGS += API_VERSION=$(shell cd $(srctree)/$(src); grep "\#define _MALI_API_VERSION" $(FILES_PREFIX)include/linux/mali/mali_utgard_uk_types.h | cut -d' ' -f 3 ) VERSION_STRINGS += REPO_URL=$(REPO_URL) VERSION_STRINGS += REVISION=$(DRIVER_REV) VERSION_STRINGS += CHANGED_REVISION=$(CHANGED_REVISION) @@ -209,5 +209,5 @@ VERSION_STRINGS += USING_DVFS=$(CONFIG_MALI_DVFS) VERSION_STRINGS += MALI_UPPER_HALF_SCHEDULING=$(MALI_UPPER_HALF_SCHEDULING) # Create file with Mali driver configuration -$(src)/__malidrv_build_info.c: - @echo 'const char *__malidrv_build_info(void) { return "malidrv: $(VERSION_STRINGS)";}' > $(src)/__malidrv_build_info.c +$(srctree)/$(src)/__malidrv_build_info.c: + @echo 'const char *__malidrv_build_info(void) { return "malidrv: $(VERSION_STRINGS)";}' > $(srctree)/$(src)/__malidrv_build_info.c diff --git a/drivers/gpu/arm/mali400/r5p2_rel0/Kbuild b/drivers/gpu/arm/mali400/r5p2_rel0/Kbuild index 8bd7891..42babbd 100644 --- a/drivers/gpu/arm/mali400/r5p2_rel0/Kbuild +++ b/drivers/gpu/arm/mali400/r5p2_rel0/Kbuild @@ -28,7 +28,7 @@ MATCH_DFS_TO_LOWER_FREQ ?= 1 GLES_MEM_PROFILE ?= 1 # The GPL product will only include the license/gpl directory -ccflags-y += -I$(src)/linux/license/gpl +ccflags-y += -I$(srctree)/$(src)/linux/license/gpl ifeq ($(USING_GPU_UTILIZATION), 1) ifeq ($(USING_DVFS), 1) @@ -116,7 +116,7 @@ mali-$(CONFIG_MALI400_PROFILING) += linux/mali_ukk_profiling.o mali-$(CONFIG_MALI400_PROFILING) += linux/mali_osk_profiling.o mali-$(CONFIG_MALI400_INTERNAL_PROFILING) += linux/mali_profiling_internal.o timestamp-$(TIMESTAMP)/mali_timestamp.o -ccflags-$(CONFIG_MALI400_INTERNAL_PROFILING) += -I$(src)/timestamp-$(TIMESTAMP) +ccflags-$(CONFIG_MALI400_INTERNAL_PROFILING) += -I$(srctree)/$(src)/timestamp-$(TIMESTAMP) mali-$(CONFIG_DMA_SHARED_BUFFER) += linux/mali_memory_dma_buf.o mali-$(CONFIG_SYNC) += linux/mali_sync.o @@ -150,16 +150,16 @@ ifeq ($(MALI_UPPER_HALF_SCHEDULING),1) ccflags-y += -DMALI_UPPER_HALF_SCHEDULING endif -ccflags-$(CONFIG_MALI400_UMP) += -I$(src)/../ump/include/ump +ccflags-$(CONFIG_MALI400_UMP) += -I$(srctree)/$(src)/../ump/include/ump ccflags-$(CONFIG_MALI400_DEBUG) += -DDEBUG # Use our defines when compiling -ccflags-y += -I$(src) -I$(src)/include -I$(src)/common -I$(src)/linux -I$(src)/platform -I$(src)/platform/$(MALI_PLATFORM) +ccflags-y += -I$(srctree)/$(src) -I$(srctree)/$(src)/include -I$(srctree)/$(src)/common -I$(srctree)/$(src)/linux -I$(srctree)/$(src)/platform -I$(srctree)/$(src)/platform/$(MALI_PLATFORM) # Get subversion revision number, fall back to only ${MALI_RELEASE_NAME} if no svn info is available -MALI_RELEASE_NAME=$(shell cat $(src)/.version 2> /dev/null) +MALI_RELEASE_NAME=$(shell cat $(srctree)/$(src)/.version 2> /dev/null) -#SVN_INFO = (cd $(src); svn info 2>/dev/null) +#SVN_INFO = (cd $(srctree)/$(src); svn info 2>/dev/null) ifneq ($(shell $(SVN_INFO) 2>/dev/null),) # SVN detected @@ -170,13 +170,13 @@ CHANGED_REVISION := $(shell $(SVN_INFO) | grep '^Last Changed Rev: ' | cut -d: - REPO_URL := $(shell $(SVN_INFO) | grep '^URL: ' | cut -d: -f2- | cut -b2-) else # SVN -#GIT_REV := $(shell cd $(src); git describe --always 2>/dev/null) +#GIT_REV := $(shell cd $(srctree)/$(src); git describe --always 2>/dev/null) ifneq ($(GIT_REV),) # Git detected DRIVER_REV := $(MALI_RELEASE_NAME)-$(GIT_REV) -CHANGE_DATE := $(shell cd $(src); git log -1 --format="%ci") +CHANGE_DATE := $(shell cd $(srctree)/$(src); git log -1 --format="%ci") CHANGED_REVISION := $(GIT_REV) -REPO_URL := $(shell cd $(src); git describe --all --always 2>/dev/null) +REPO_URL := $(shell cd $(srctree)/$(src); git describe --all --always 2>/dev/null) else # Git # No Git or SVN detected @@ -190,7 +190,7 @@ ccflags-y += -DSVN_REV_STRING=\"$(DRIVER_REV)\" ccflags-y += -fno-PIC VERSION_STRINGS := -VERSION_STRINGS += API_VERSION=$(shell cd $(src); grep "\#define _MALI_API_VERSION" $(FILES_PREFIX)include/linux/mali/mali_utgard_uk_types.h | cut -d' ' -f 3 ) +VERSION_STRINGS += API_VERSION=$(shell cd $(srctree)/$(src); grep "\#define _MALI_API_VERSION" $(FILES_PREFIX)include/linux/mali/mali_utgard_uk_types.h | cut -d' ' -f 3 ) VERSION_STRINGS += REPO_URL=$(REPO_URL) VERSION_STRINGS += REVISION=$(DRIVER_REV) VERSION_STRINGS += CHANGED_REVISION=$(CHANGED_REVISION) @@ -213,5 +213,5 @@ VERSION_STRINGS += USING_DVFS=$(CONFIG_MALI_DVFS) VERSION_STRINGS += MALI_UPPER_HALF_SCHEDULING=$(MALI_UPPER_HALF_SCHEDULING) # Create file with Mali driver configuration -$(src)/__malidrv_build_info.c: - @echo 'const char *__malidrv_build_info(void) { return "malidrv: $(VERSION_STRINGS)";}' > $(src)/__malidrv_build_info.c +$(srctree)/$(src)/__malidrv_build_info.c: + @echo 'const char *__malidrv_build_info(void) { return "malidrv: $(VERSION_STRINGS)";}' > $(srctree)/$(src)/__malidrv_build_info.c -- 2.7.4 From c9f5ffa1a62f400e6b426b7d33dc30643f67d1f5 Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Mon, 23 May 2016 15:35:41 +0900 Subject: [PATCH 05/16] ARM: mali400: r5p2_rel0: fix build error MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Include pm_runtime.h to fix below build error when CONFIG_PM_RUNTIME is disabled. drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_kernel_linux.c: In function ‘mali_driver_suspend_scheduler’: drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_kernel_linux.c:595:2: error: implicit declaration of function ‘pm_runtime_active’ [-Werror=implicit-function-declaration] if (pm_runtime_active(dev)) ^ Change-Id: Ic613dd9785a9d563e50361328944bd23d33fd70c Signed-off-by: Joonyoung Shim --- drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_kernel_linux.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_kernel_linux.c b/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_kernel_linux.c index 2493266..3035f08 100644 --- a/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_kernel_linux.c +++ b/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_kernel_linux.c @@ -24,9 +24,7 @@ #include #include #include -#ifdef CONFIG_PM_RUNTIME #include -#endif #include #include "mali_kernel_common.h" #include "mali_session.h" -- 2.7.4 From 3e64e276ca6f653f066aed31dfc13b0c520a592a Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Mon, 23 May 2016 17:23:22 +0900 Subject: [PATCH 06/16] ARM: mali400: r5p2_rel0: replace CONFIG_PM_RUNTIME to CONFIG_PM After commit 464ed18ebdb6 ("PM: Eliminate CONFIG_PM_RUNTIME") which is applied kernel version 3.19, PM_RUNTIME is eliminated. So this patch replaces CONFIG_PM_RUNTIME to CONFIG_PM for kernel version larger than 3.19. Signed-off-by: Seung-Woo Kim [jy0922.shim: apply to mali400 r5p2_rel0 with some modification] Signed-off-by: Joonyoung Shim Change-Id: Iab2e17c07b397fe164623e1ecec58c54296c83a7 --- drivers/gpu/arm/mali400/r5p2_rel0/common/mali_pm.c | 5 ++++- .../gpu/arm/mali400/r5p2_rel0/linux/mali_kernel_linux.c | 9 ++++++--- drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_osk_pm.c | 14 ++++++++------ drivers/gpu/arm/mali400/r5p2_rel0/platform/arm/arm.c | 8 ++++---- 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/arm/mali400/r5p2_rel0/common/mali_pm.c b/drivers/gpu/arm/mali400/r5p2_rel0/common/mali_pm.c index 85cdde0..9c6505c 100644 --- a/drivers/gpu/arm/mali400/r5p2_rel0/common/mali_pm.c +++ b/drivers/gpu/arm/mali400/r5p2_rel0/common/mali_pm.c @@ -8,6 +8,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include + #include "mali_pm.h" #include "mali_kernel_common.h" #include "mali_osk.h" @@ -70,7 +72,8 @@ static int mali_pm_domain_power_cost_result[MALI_MAX_NUMBER_OF_PHYSICAL_PP_GROUP * Keep track of runtime PM state, so that we know * how to resume during OS resume. */ -#ifdef CONFIG_PM_RUNTIME +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) && defined(CONFIG_PM_RUNTIME))\ + || defined(CONFIG_PM) static mali_bool mali_pm_runtime_active = MALI_FALSE; #else /* when kernel don't enable PM_RUNTIME, set the flag always true, diff --git a/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_kernel_linux.c b/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_kernel_linux.c index 3035f08..5ec81ed 100644 --- a/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_kernel_linux.c +++ b/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_kernel_linux.c @@ -179,7 +179,8 @@ static int mali_remove(struct platform_device *pdev); static int mali_driver_suspend_scheduler(struct device *dev); static int mali_driver_resume_scheduler(struct device *dev); -#ifdef CONFIG_PM_RUNTIME +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) && defined(CONFIG_PM_RUNTIME))\ + || defined(CONFIG_PM) static int mali_driver_runtime_suspend(struct device *dev); static int mali_driver_runtime_resume(struct device *dev); static int mali_driver_runtime_idle(struct device *dev); @@ -210,7 +211,8 @@ struct pm_ext_ops mali_dev_ext_pm_ops = { }; #else static const struct dev_pm_ops mali_dev_pm_ops = { -#ifdef CONFIG_PM_RUNTIME +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) && defined(CONFIG_PM_RUNTIME))\ + || defined(CONFIG_PM) .runtime_suspend = mali_driver_runtime_suspend, .runtime_resume = mali_driver_runtime_resume, .runtime_idle = mali_driver_runtime_idle, @@ -627,7 +629,8 @@ static int mali_driver_resume_scheduler(struct device *dev) return 0; } -#ifdef CONFIG_PM_RUNTIME +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) && defined(CONFIG_PM_RUNTIME))\ + || defined(CONFIG_PM) static int mali_driver_runtime_suspend(struct device *dev) { if (MALI_TRUE == mali_pm_runtime_suspend()) { diff --git a/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_osk_pm.c b/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_osk_pm.c index 21180d3..9253e54 100644 --- a/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_osk_pm.c +++ b/drivers/gpu/arm/mali400/r5p2_rel0/linux/mali_osk_pm.c @@ -15,9 +15,7 @@ #include -#ifdef CONFIG_PM_RUNTIME #include -#endif /* CONFIG_PM_RUNTIME */ #include #include #include "mali_osk.h" @@ -27,7 +25,8 @@ /* Can NOT run in atomic context */ _mali_osk_errcode_t _mali_osk_pm_dev_ref_get_sync(void) { -#ifdef CONFIG_PM_RUNTIME +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) && defined(CONFIG_PM_RUNTIME))\ + || defined(CONFIG_PM) int err; MALI_DEBUG_ASSERT_POINTER(mali_platform_device); err = pm_runtime_get_sync(&(mali_platform_device->dev)); @@ -45,7 +44,8 @@ _mali_osk_errcode_t _mali_osk_pm_dev_ref_get_sync(void) /* Can run in atomic context */ _mali_osk_errcode_t _mali_osk_pm_dev_ref_get_async(void) { -#ifdef CONFIG_PM_RUNTIME +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) && defined(CONFIG_PM_RUNTIME))\ + || defined(CONFIG_PM) int err; MALI_DEBUG_ASSERT_POINTER(mali_platform_device); err = pm_runtime_get(&(mali_platform_device->dev)); @@ -64,7 +64,8 @@ _mali_osk_errcode_t _mali_osk_pm_dev_ref_get_async(void) /* Can run in atomic context */ void _mali_osk_pm_dev_ref_put(void) { -#ifdef CONFIG_PM_RUNTIME +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) && defined(CONFIG_PM_RUNTIME))\ + || defined(CONFIG_PM) MALI_DEBUG_ASSERT_POINTER(mali_platform_device); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) pm_runtime_mark_last_busy(&(mali_platform_device->dev)); @@ -77,7 +78,8 @@ void _mali_osk_pm_dev_ref_put(void) void _mali_osk_pm_dev_barrier(void) { -#ifdef CONFIG_PM_RUNTIME +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) && defined(CONFIG_PM_RUNTIME))\ + || defined(CONFIG_PM) pm_runtime_barrier(&(mali_platform_device->dev)); #endif } diff --git a/drivers/gpu/arm/mali400/r5p2_rel0/platform/arm/arm.c b/drivers/gpu/arm/mali400/r5p2_rel0/platform/arm/arm.c index 9eaf07e..4853944 100644 --- a/drivers/gpu/arm/mali400/r5p2_rel0/platform/arm/arm.c +++ b/drivers/gpu/arm/mali400/r5p2_rel0/platform/arm/arm.c @@ -17,9 +17,7 @@ #include #include #include -#ifdef CONFIG_PM_RUNTIME #include -#endif #include #include #include "mali_kernel_common.h" @@ -192,7 +190,8 @@ int mali_platform_device_register(void) /* Register the platform device */ err = platform_device_register(&mali_gpu_device); if (0 == err) { -#ifdef CONFIG_PM_RUNTIME +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) && defined(CONFIG_PM_RUNTIME))\ + || defined(CONFIG_PM) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) pm_runtime_set_autosuspend_delay(&(mali_gpu_device.dev), 1000); pm_runtime_use_autosuspend(&(mali_gpu_device.dev)); @@ -280,7 +279,8 @@ int mali_platform_device_init(struct platform_device *device) err = platform_device_add_data(device, &mali_gpu_data, sizeof(mali_gpu_data)); if (0 == err) { -#ifdef CONFIG_PM_RUNTIME +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) && defined(CONFIG_PM_RUNTIME))\ + || defined(CONFIG_PM) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) pm_runtime_set_autosuspend_delay(&(device->dev), 1000); pm_runtime_use_autosuspend(&(device->dev)); -- 2.7.4 From aea2a5eebeb8e44b8e64c070f67520e5a1c80b7f Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Tue, 10 May 2016 15:27:25 +0900 Subject: [PATCH 07/16] ARM: tizen_tm1_defconfig: Enable mali400 r5p2_rel0 Enable mali400 r5p2_rel0 instead of r5p0_rel0. Change-Id: I4f7f01788d91b6d4e9c102029cbfa5a1b5c3f300 Signed-off-by: Joonyoung Shim --- arch/arm/configs/tizen_tm1_defconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/configs/tizen_tm1_defconfig b/arch/arm/configs/tizen_tm1_defconfig index 5007420..b597df9 100755 --- a/arch/arm/configs/tizen_tm1_defconfig +++ b/arch/arm/configs/tizen_tm1_defconfig @@ -2113,11 +2113,12 @@ CONFIG_MALI400=y CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH=y CONFIG_MALI_SHARED_INTERRUPTS=y # CONFIG_MALI_PMU_PARALLEL_POWER_UP is not set -CONFIG_MALI_VER_R5P0_REL0=y +# CONFIG_MALI_VER_R5P0_REL0 is not set # CONFIG_MALI450 is not set # CONFIG_MALI_DVFS is not set CONFIG_MALI_DT=y # CONFIG_MALI_QUIET is not set +CONFIG_MALI_VER_R5P2_REL0=y # CONFIG_VGASTATE is not set # CONFIG_VIDEO_OUTPUT_CONTROL is not set CONFIG_HDMI=y -- 2.7.4 From 6e9479c7c433aa0e00faa9ab750535ed9d77cc1e Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Mon, 20 Jun 2016 18:42:18 +0900 Subject: [PATCH 08/16] input: touchkey: add resume function Now, there is only suspend function then it will cause a problem that touchkey is not working after sleep, so add resume function. It's enough only that resume function calls tc300k_input_open() because suspend function calls just tc300k_input_close(). Change-Id: I2b96fe797a94fbd20cd3082c9460130dd6b848eb Signed-off-by: Joonyoung Shim --- drivers/input/keyboard/coreriver/tc350-touchkey.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/input/keyboard/coreriver/tc350-touchkey.c b/drivers/input/keyboard/coreriver/tc350-touchkey.c index 4d54fec..0d980a7 100644 --- a/drivers/input/keyboard/coreriver/tc350-touchkey.c +++ b/drivers/input/keyboard/coreriver/tc350-touchkey.c @@ -2373,6 +2373,14 @@ static int tc300k_suspend(struct device *dev) return 0; } + +static int tc300k_resume(struct device *dev) +{ + struct tc300k_data *data = dev_get_drvdata(dev); + struct input_dev *input_dev = data->input_dev; + + return tc300k_input_open(input_dev); +} #endif MODULE_DEVICE_TABLE(i2c, tc300k_id); @@ -2380,6 +2388,7 @@ MODULE_DEVICE_TABLE(i2c, tc300k_id); #ifndef CONFIG_HAS_EARLYSUSPEND const struct dev_pm_ops tc300k_pm_ops = { .suspend = tc300k_suspend, + .resume = tc300k_resume, }; #endif -- 2.7.4 From 773a1cd3ccf9b1fa8e7d492255c6f1ad0f307c95 Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Wed, 6 Jul 2016 19:59:19 +0900 Subject: [PATCH 09/16] sensors/ims1911: use deffered probe for i2c fail case from probe This patch fixes to use deffered probe error for i2c read fail from probe. Change-Id: Ic4bc12fef0c9dee69d98bbdfb1ed1d5f2c2f62de Signed-off-by: Seung-Woo Kim --- drivers/sensors/ims1911.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/sensors/ims1911.c b/drivers/sensors/ims1911.c index 8a32f78..0b078fe 100644 --- a/drivers/sensors/ims1911.c +++ b/drivers/sensors/ims1911.c @@ -761,7 +761,7 @@ static int ims1911_detect(struct ims1911_data *data) if(i2c_read_byte(data, IMS1911_OPERATION_MODE_SEL, &val) == I2C_FAIL) { dev_err(&data->client->dev, "ims1911 i2c fail : not found\n"); - return -1; + return -EPROBE_DEFER; } #if 0 if(val != 0) { -- 2.7.4 From d3717461f4cba8dc7c5b91a9f872e2bab0a4e7f4 Mon Sep 17 00:00:00 2001 From: jooseong lee Date: Wed, 20 Jul 2016 10:07:11 +0900 Subject: [PATCH 10/16] Smack: Assign smack_known_web label for kernel thread's socket in the sk_alloc_security hook Creating struct sock by sk_alloc function in various kernel subsystems like bluetooth dosen't call smack_socket_post_create(). In such case, received sock label is the floor('_') label and makes access deny. Refers to: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=7412301b76bd53ee53b860f611fc3b5b1c2245b5 Change-Id: I614c5f0e6d59be5ca6b49f0581edfef79fc334cf Signed-off-by: jooseong lee --- security/smack/smack_lsm.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index f0cea06..7e800c6 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -2145,8 +2145,16 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) if (ssp == NULL) return -ENOMEM; - ssp->smk_in = skp; - ssp->smk_out = skp; + /* + * Sockets created by kernel threads receive web label. + */ + if (unlikely(current->flags & PF_KTHREAD)) { + ssp->smk_in = &smack_known_web; + ssp->smk_out = &smack_known_web; + } else { + ssp->smk_in = skp; + ssp->smk_out = skp; + } ssp->smk_packet = NULL; sk->sk_security = ssp; -- 2.7.4 From 22ba78a338328de86f001c1c52b74b73331eb515 Mon Sep 17 00:00:00 2001 From: Michal Bloch Date: Thu, 21 Jul 2016 13:41:02 +0200 Subject: [PATCH 11/16] kmsg: allow binary characters * do not touch unprintable characters. This is so that logs can have formatting such as newlines, tabulation, or colours. * the textual part is now delimited by \0. This is because \n which used to be the delimiter is now available for logs. Signed-off-by: Michal Bloch Change-Id: I030a4eab791f4468897d3dcdc5bb04549f30b2f7 Signed-off-by: Kichan Kwon --- kernel/printk_kmsg.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/kernel/printk_kmsg.c b/kernel/printk_kmsg.c index ceb15f6..7a209f4 100644 --- a/kernel/printk_kmsg.c +++ b/kernel/printk_kmsg.c @@ -1061,15 +1061,19 @@ static ssize_t kmsg_read(struct log_buffer *log_b, struct file *file, user->seq, ts_usec, cont); user->prev = msg->flags; - /* escape non-printable characters */ for (i = 0; i < msg->text_len; i++) { unsigned char c = log_text(msg)[i]; - if (c < ' ' || c >= 127 || c == '\\') - p += scnprintf(p, e - p, "\\x%02x", c); - else - append_char(&p, e, c); + append_char(&p, e, c); } + + /* + * The \0 is delimits the text part, while the newline is for formatting + * when catting the device directly. We cannot use \n for delimiting due + * to security: else one could forge dictionary tags through the message + * such as "text\n _PID=123" + */ + append_char(&p, e, '\0'); append_char(&p, e, '\n'); if (msg->dict_len) { @@ -1089,11 +1093,6 @@ static ssize_t kmsg_read(struct log_buffer *log_b, struct file *file, continue; } - if (c < ' ' || c >= 127 || c == '\\') { - p += scnprintf(p, e - p, "\\x%02x", c); - continue; - } - append_char(&p, e, c); } append_char(&p, e, '\n'); -- 2.7.4 From fe8173a61d6c5dd06e63281051a4ab184299fe03 Mon Sep 17 00:00:00 2001 From: Filipe Manana Date: Sun, 9 Nov 2014 08:38:39 +0000 Subject: [PATCH 12/16] Btrfs: make xattr replace operations atomic commit 5f5bc6b1e2d5a6f827bc860ef2dc5b6f365d1339 upstream. Replacing a xattr consists of doing a lookup for its existing value, delete the current value from the respective leaf, release the search path and then finally insert the new value. This leaves a time window where readers (getxattr, listxattrs) won't see any value for the xattr. Xattrs are used to store ACLs, so this has security implications. This change also fixes 2 other existing issues which were: *) Deleting the old xattr value without verifying first if the new xattr will fit in the existing leaf item (in case multiple xattrs are packed in the same item due to name hash collision); *) Returning -EEXIST when the flag XATTR_CREATE is given and the xattr doesn't exist but we have have an existing item that packs muliple xattrs with the same name hash as the input xattr. In this case we should return ENOSPC. A test case for xfstests follows soon. Thanks to Alexandre Oliva for reporting the non-atomicity of the xattr replace implementation. Change-Id: I286d47858be086bb974cb4fa8eee5d32e8bee61d Reported-by: Alexandre Oliva Signed-off-by: Filipe Manana Signed-off-by: Chris Mason [shengyong: backport to 3.10 - FIX: CVE-2014-9710 - adjust context - ASSERT() was added v3.12, so we do check with if statement - set the first parameter of btrfs_item_nr() as NULL, because it is not used, and is removed in v3.13 ] Signed-off-by: Sheng Yong Signed-off-by: Greg Kroah-Hartman Signed-off-by: Junghoon Kim --- fs/btrfs/ctree.c | 2 +- fs/btrfs/ctree.h | 5 ++ fs/btrfs/dir-item.c | 10 +--- fs/btrfs/xattr.c | 159 +++++++++++++++++++++++++++++++++------------------- 4 files changed, 111 insertions(+), 65 deletions(-) diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 7fb054b..82f14a1 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -2769,7 +2769,7 @@ done: */ if (!p->leave_spinning) btrfs_set_path_blocking(p); - if (ret < 0) + if (ret < 0 && !p->skip_release_on_error) btrfs_release_path(p); return ret; } diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index d6dd49b..c19444e 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -586,6 +586,7 @@ struct btrfs_path { unsigned int skip_locking:1; unsigned int leave_spinning:1; unsigned int search_commit_root:1; + unsigned int skip_release_on_error:1; }; /* @@ -3406,6 +3407,10 @@ struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans, int verify_dir_item(struct btrfs_root *root, struct extent_buffer *leaf, struct btrfs_dir_item *dir_item); +struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, + struct btrfs_path *path, + const char *name, + int name_len); /* orphan.c */ int btrfs_insert_orphan_item(struct btrfs_trans_handle *trans, diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index 79e594e..6f61b9b 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c @@ -21,10 +21,6 @@ #include "hash.h" #include "transaction.h" -static struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, - struct btrfs_path *path, - const char *name, int name_len); - /* * insert a name into a directory, doing overflow properly if there is a hash * collision. data_size indicates how big the item inserted should be. On @@ -383,9 +379,9 @@ struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans, * this walks through all the entries in a dir item and finds one * for a specific name. */ -static struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, - struct btrfs_path *path, - const char *name, int name_len) +struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, + struct btrfs_path *path, + const char *name, int name_len) { struct btrfs_dir_item *dir_item; unsigned long name_ptr; diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index 05740b9..9cf20d6 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c @@ -27,6 +27,7 @@ #include "transaction.h" #include "xattr.h" #include "disk-io.h" +#include "locking.h" ssize_t __btrfs_getxattr(struct inode *inode, const char *name, @@ -89,7 +90,7 @@ static int do_setxattr(struct btrfs_trans_handle *trans, struct inode *inode, const char *name, const void *value, size_t size, int flags) { - struct btrfs_dir_item *di; + struct btrfs_dir_item *di = NULL; struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_path *path; size_t name_len = strlen(name); @@ -101,84 +102,128 @@ static int do_setxattr(struct btrfs_trans_handle *trans, path = btrfs_alloc_path(); if (!path) return -ENOMEM; + path->skip_release_on_error = 1; + + if (!value) { + di = btrfs_lookup_xattr(trans, root, path, btrfs_ino(inode), + name, name_len, -1); + if (!di && (flags & XATTR_REPLACE)) + ret = -ENODATA; + else if (di) + ret = btrfs_delete_one_dir_name(trans, root, path, di); + goto out; + } + /* + * For a replace we can't just do the insert blindly. + * Do a lookup first (read-only btrfs_search_slot), and return if xattr + * doesn't exist. If it exists, fall down below to the insert/replace + * path - we can't race with a concurrent xattr delete, because the VFS + * locks the inode's i_mutex before calling setxattr or removexattr. + */ if (flags & XATTR_REPLACE) { - di = btrfs_lookup_xattr(trans, root, path, btrfs_ino(inode), name, - name_len, -1); - if (IS_ERR(di)) { - ret = PTR_ERR(di); - goto out; - } else if (!di) { + if(!mutex_is_locked(&inode->i_mutex)) { + pr_err("BTRFS: assertion failed: %s, file: %s, line: %d", + "mutex_is_locked(&inode->i_mutex)", __FILE__, + __LINE__); + BUG(); + } + di = btrfs_lookup_xattr(NULL, root, path, btrfs_ino(inode), + name, name_len, 0); + if (!di) { ret = -ENODATA; goto out; } - ret = btrfs_delete_one_dir_name(trans, root, path, di); - if (ret) - goto out; btrfs_release_path(path); + di = NULL; + } + ret = btrfs_insert_xattr_item(trans, root, path, btrfs_ino(inode), + name, name_len, value, size); + if (ret == -EOVERFLOW) { /* - * remove the attribute + * We have an existing item in a leaf, split_leaf couldn't + * expand it. That item might have or not a dir_item that + * matches our target xattr, so lets check. */ - if (!value) - goto out; - } else { - di = btrfs_lookup_xattr(NULL, root, path, btrfs_ino(inode), - name, name_len, 0); - if (IS_ERR(di)) { - ret = PTR_ERR(di); + ret = 0; + btrfs_assert_tree_locked(path->nodes[0]); + di = btrfs_match_dir_item_name(root, path, name, name_len); + if (!di && !(flags & XATTR_REPLACE)) { + ret = -ENOSPC; goto out; } - if (!di && !value) - goto out; - btrfs_release_path(path); + } else if (ret == -EEXIST) { + ret = 0; + di = btrfs_match_dir_item_name(root, path, name, name_len); + if(!di) { /* logic error */ + pr_err("BTRFS: assertion failed: %s, file: %s, line: %d", + "di", __FILE__, __LINE__); + BUG(); + } + } else if (ret) { + goto out; } -again: - ret = btrfs_insert_xattr_item(trans, root, path, btrfs_ino(inode), - name, name_len, value, size); - /* - * If we're setting an xattr to a new value but the new value is say - * exactly BTRFS_MAX_XATTR_SIZE, we could end up with EOVERFLOW getting - * back from split_leaf. This is because it thinks we'll be extending - * the existing item size, but we're asking for enough space to add the - * item itself. So if we get EOVERFLOW just set ret to EEXIST and let - * the rest of the function figure it out. - */ - if (ret == -EOVERFLOW) + if (di && (flags & XATTR_CREATE)) { ret = -EEXIST; + goto out; + } - if (ret == -EEXIST) { - if (flags & XATTR_CREATE) - goto out; + if (di) { /* - * We can't use the path we already have since we won't have the - * proper locking for a delete, so release the path and - * re-lookup to delete the thing. + * We're doing a replace, and it must be atomic, that is, at + * any point in time we have either the old or the new xattr + * value in the tree. We don't want readers (getxattr and + * listxattrs) to miss a value, this is specially important + * for ACLs. */ - btrfs_release_path(path); - di = btrfs_lookup_xattr(trans, root, path, btrfs_ino(inode), - name, name_len, -1); - if (IS_ERR(di)) { - ret = PTR_ERR(di); - goto out; - } else if (!di) { - /* Shouldn't happen but just in case... */ - btrfs_release_path(path); - goto again; + const int slot = path->slots[0]; + struct extent_buffer *leaf = path->nodes[0]; + const u16 old_data_len = btrfs_dir_data_len(leaf, di); + const u32 item_size = btrfs_item_size_nr(leaf, slot); + const u32 data_size = sizeof(*di) + name_len + size; + struct btrfs_item *item; + unsigned long data_ptr; + char *ptr; + + if (size > old_data_len) { + if (btrfs_leaf_free_space(root, leaf) < + (size - old_data_len)) { + ret = -ENOSPC; + goto out; + } } - ret = btrfs_delete_one_dir_name(trans, root, path, di); - if (ret) - goto out; + if (old_data_len + name_len + sizeof(*di) == item_size) { + /* No other xattrs packed in the same leaf item. */ + if (size > old_data_len) + btrfs_extend_item(root, path, + size - old_data_len); + else if (size < old_data_len) + btrfs_truncate_item(root, path, data_size, 1); + } else { + /* There are other xattrs packed in the same item. */ + ret = btrfs_delete_one_dir_name(trans, root, path, di); + if (ret) + goto out; + btrfs_extend_item(root, path, data_size); + } + item = btrfs_item_nr(NULL, slot); + ptr = btrfs_item_ptr(leaf, slot, char); + ptr += btrfs_item_size(leaf, item) - data_size; + di = (struct btrfs_dir_item *)ptr; + btrfs_set_dir_data_len(leaf, di, size); + data_ptr = ((unsigned long)(di + 1)) + name_len; + write_extent_buffer(leaf, value, data_ptr, size); + btrfs_mark_buffer_dirty(leaf); + } else { /* - * We have a value to set, so go back and try to insert it now. + * Insert, and we had space for the xattr, so path->slots[0] is + * where our xattr dir_item is and btrfs_insert_xattr_item() + * filled it. */ - if (value) { - btrfs_release_path(path); - goto again; - } } out: btrfs_free_path(path); -- 2.7.4 From 9c9b400993e03d745b704ad68d517be9e4d30544 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 18 Dec 2015 01:34:26 +0000 Subject: [PATCH 13/16] KEYS: Fix race between read and revoke commit b4a1b4f5047e4f54e194681125c74c0aa64d637d upstream. This fixes CVE-2015-7550. There's a race between keyctl_read() and keyctl_revoke(). If the revoke happens between keyctl_read() checking the validity of a key and the key's semaphore being taken, then the key type read method will see a revoked key. This causes a problem for the user-defined key type because it assumes in its read method that there will always be a payload in a non-revoked key and doesn't check for a NULL pointer. Fix this by making keyctl_read() check the validity of a key after taking semaphore instead of before. I think the bug was introduced with the original keyrings code. This was discovered by a multithreaded test program generated by syzkaller (http://github.com/google/syzkaller). Here's a cleaned up version: #include #include #include void *thr0(void *arg) { key_serial_t key = (unsigned long)arg; keyctl_revoke(key); return 0; } void *thr1(void *arg) { key_serial_t key = (unsigned long)arg; char buffer[16]; keyctl_read(key, buffer, 16); return 0; } int main() { key_serial_t key = add_key("user", "%", "foo", 3, KEY_SPEC_USER_KEYRING); pthread_t th[5]; pthread_create(&th[0], 0, thr0, (void *)(unsigned long)key); pthread_create(&th[1], 0, thr1, (void *)(unsigned long)key); pthread_create(&th[2], 0, thr0, (void *)(unsigned long)key); pthread_create(&th[3], 0, thr1, (void *)(unsigned long)key); pthread_join(th[0], 0); pthread_join(th[1], 0); pthread_join(th[2], 0); pthread_join(th[3], 0); return 0; } Build as: cc -o keyctl-race keyctl-race.c -lkeyutils -lpthread Run as: while keyctl-race; do :; done as it may need several iterations to crash the kernel. The crash can be summarised as: BUG: unable to handle kernel NULL pointer dereference at 0000000000000010 IP: [] user_read+0x56/0xa3 ... Call Trace: [] keyctl_read_key+0xb6/0xd7 [] SyS_keyctl+0x83/0xe0 [] entry_SYSCALL_64_fastpath+0x12/0x6f Reported-by: Dmitry Vyukov Signed-off-by: David Howells Tested-by: Dmitry Vyukov Signed-off-by: James Morris Signed-off-by: Greg Kroah-Hartman Change-Id: Ie59035bed50d4e1aa2248a0bd5128a0f997ab29a Signed-off-by: Junghoon Kim --- security/keys/keyctl.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 33cfd27..3242195 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -744,16 +744,16 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) /* the key is probably readable - now try to read it */ can_read_key: - ret = key_validate(key); - if (ret == 0) { - ret = -EOPNOTSUPP; - if (key->type->read) { - /* read the data with the semaphore held (since we - * might sleep) */ - down_read(&key->sem); + ret = -EOPNOTSUPP; + if (key->type->read) { + /* Read the data with the semaphore held (since we might sleep) + * to protect against the key being updated or revoked. + */ + down_read(&key->sem); + ret = key_validate(key); + if (ret == 0) ret = key->type->read(key, buffer, buflen); - up_read(&key->sem); - } + up_read(&key->sem); } error2: -- 2.7.4 From c673f883daef4c7f8d8a7adfeb834e87af6b06ac Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Mon, 29 Dec 2014 09:39:01 -0500 Subject: [PATCH 14/16] KEYS: close race between key lookup and freeing commit a3a8784454692dd72e5d5d34dcdab17b4420e74c upstream. When a key is being garbage collected, it's key->user would get put before the ->destroy() callback is called, where the key is removed from it's respective tracking structures. This leaves a key hanging in a semi-invalid state which leaves a window open for a different task to try an access key->user. An example is find_keyring_by_name() which would dereference key->user for a key that is in the process of being garbage collected (where key->user was freed but ->destroy() wasn't called yet - so it's still present in the linked list). This would cause either a panic, or corrupt memory. Fixes CVE-2014-9529. Signed-off-by: Sasha Levin Signed-off-by: David Howells Signed-off-by: Greg Kroah-Hartman Change-Id: Iab7bb60ba1db5931cd8911ed04452cdb55358eda Signed-off-by: Junghoon Kim --- security/keys/gc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/security/keys/gc.c b/security/keys/gc.c index d67c97b..7978186 100644 --- a/security/keys/gc.c +++ b/security/keys/gc.c @@ -201,12 +201,12 @@ static noinline void key_gc_unused_keys(struct list_head *keys) if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) atomic_dec(&key->user->nikeys); - key_user_put(key->user); - /* now throw away the key memory */ if (key->type->destroy) key->type->destroy(key); + key_user_put(key->user); + kfree(key->description); #ifdef KEY_DEBUGGING -- 2.7.4 From a5559d92337b4832fb01ecead46abc6c4cee8781 Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Mon, 14 Dec 2015 22:03:39 +0100 Subject: [PATCH 15/16] net: add validation for the socket syscall protocol argument MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit [ Upstream commit 79462ad02e861803b3840cc782248c7359451cd9 ] 郭永刚 reported that one could simply crash the kernel as root by using a simple program: int socket_fd; struct sockaddr_in addr; addr.sin_port = 0; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_family = 10; socket_fd = socket(10,3,0x40000000); connect(socket_fd , &addr,16); AF_INET, AF_INET6 sockets actually only support 8-bit protocol identifiers. inet_sock's skc_protocol field thus is sized accordingly, thus larger protocol identifiers simply cut off the higher bits and store a zero in the protocol fields. This could lead to e.g. NULL function pointer because as a result of the cut off inet_num is zero and we call down to inet_autobind, which is NULL for raw sockets. kernel: Call Trace: kernel: [] ? inet_autobind+0x2e/0x70 kernel: [] inet_dgram_connect+0x54/0x80 kernel: [] SYSC_connect+0xd9/0x110 kernel: [] ? ptrace_notify+0x5b/0x80 kernel: [] ? syscall_trace_enter_phase2+0x108/0x200 kernel: [] SyS_connect+0xe/0x10 kernel: [] tracesys_phase2+0x84/0x89 I found no particular commit which introduced this problem. Change-Id: I30cd09ffb9705304bcda7247fe28ac14c8bb20a9 CVE: CVE-2015-8543 Cc: Cong Wang Reported-by: 郭永刚 Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Signed-off-by: Junghoon Kim --- include/net/sock.h | 1 + net/ax25/af_ax25.c | 3 +++ net/decnet/af_decnet.c | 3 +++ net/ipv4/af_inet.c | 3 +++ net/ipv6/af_inet6.c | 3 +++ net/irda/af_irda.c | 3 +++ 6 files changed, 16 insertions(+) diff --git a/include/net/sock.h b/include/net/sock.h index d512f27..6d2ec72 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -353,6 +353,7 @@ struct sock { sk_no_check : 2, sk_userlocks : 4, sk_protocol : 8, +#define SK_PROTOCOL_MAX U8_MAX sk_type : 16; kmemcheck_bitfield_end(flags); int sk_wmem_queued; diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index ba6db78..69940a7 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -806,6 +806,9 @@ static int ax25_create(struct net *net, struct socket *sock, int protocol, struct sock *sk; ax25_cb *ax25; + if (protocol < 0 || protocol > SK_PROTOCOL_MAX) + return -EINVAL; + if (!net_eq(net, &init_net)) return -EAFNOSUPPORT; diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index c21f200..ca61065 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -677,6 +677,9 @@ static int dn_create(struct net *net, struct socket *sock, int protocol, { struct sock *sk; + if (protocol < 0 || protocol > SK_PROTOCOL_MAX) + return -EINVAL; + if (!net_eq(net, &init_net)) return -EAFNOSUPPORT; diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index f022e0e..14ad21e 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -304,6 +304,9 @@ static int inet_create(struct net *net, struct socket *sock, int protocol, if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM) build_ehash_secret(); + if (protocol < 0 || protocol >= IPPROTO_MAX) + return -EINVAL; + sock->state = SS_UNCONNECTED; /* Look for the requested type/protocol pair. */ diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index d29ae19..72aa1a1 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -131,6 +131,9 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol, !inet_ehash_secret) build_ehash_secret(); + if (protocol < 0 || protocol >= IPPROTO_MAX) + return -EINVAL; + /* Look for the requested type/protocol pair. */ lookup_protocol: err = -ESOCKTNOSUPPORT; diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index a5e62ef..f8133ff 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c @@ -1105,6 +1105,9 @@ static int irda_create(struct net *net, struct socket *sock, int protocol, IRDA_DEBUG(2, "%s()\n", __func__); + if (protocol < 0 || protocol > SK_PROTOCOL_MAX) + return -EINVAL; + if (net != &init_net) return -EAFNOSUPPORT; -- 2.7.4 From cea8626c062dd526184b75a9d23b6b92287f8ada Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 26 Sep 2014 11:35:42 +0200 Subject: [PATCH 16/16] netfilter: conntrack: disable generic tracking for known protocols commit db29a9508a9246e77087c5531e45b2c88ec6988b upstream. Given following iptables ruleset: -P FORWARD DROP -A FORWARD -m sctp --dport 9 -j ACCEPT -A FORWARD -p tcp --dport 80 -j ACCEPT -A FORWARD -p tcp -m conntrack -m state ESTABLISHED,RELATED -j ACCEPT One would assume that this allows SCTP on port 9 and TCP on port 80. Unfortunately, if the SCTP conntrack module is not loaded, this allows *all* SCTP communication, to pass though, i.e. -p sctp -j ACCEPT, which we think is a security issue. This is because on the first SCTP packet on port 9, we create a dummy "generic l4" conntrack entry without any port information (since conntrack doesn't know how to extract this information). All subsequent packets that are unknown will then be in established state since they will fallback to proto_generic and will match the 'generic' entry. Our originally proposed version [1] completely disabled generic protocol tracking, but Jozsef suggests to not track protocols for which a more suitable helper is available, hence we now mitigate the issue for in tree known ct protocol helpers only, so that at least NAT and direction information will still be preserved for others. [1] http://www.spinics.net/lists/netfilter-devel/msg33430.html Joint work with Daniel Borkmann. Fixes CVE-2014-8160. Change-Id: I8dbb1b870c0724acba5f20d353c856f16ec00ae0 Signed-off-by: Florian Westphal Signed-off-by: Daniel Borkmann Acked-by: Jozsef Kadlecsik Signed-off-by: Pablo Neira Ayuso Signed-off-by: Zhiqiang Zhang Signed-off-by: Greg Kroah-Hartman Signed-off-by: Junghoon Kim --- net/netfilter/nf_conntrack_proto_generic.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c index d25f293..957c1db 100644 --- a/net/netfilter/nf_conntrack_proto_generic.c +++ b/net/netfilter/nf_conntrack_proto_generic.c @@ -14,6 +14,30 @@ static unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ; +static bool nf_generic_should_process(u8 proto) +{ + switch (proto) { +#ifdef CONFIG_NF_CT_PROTO_SCTP_MODULE + case IPPROTO_SCTP: + return false; +#endif +#ifdef CONFIG_NF_CT_PROTO_DCCP_MODULE + case IPPROTO_DCCP: + return false; +#endif +#ifdef CONFIG_NF_CT_PROTO_GRE_MODULE + case IPPROTO_GRE: + return false; +#endif +#ifdef CONFIG_NF_CT_PROTO_UDPLITE_MODULE + case IPPROTO_UDPLITE: + return false; +#endif + default: + return true; + } +} + static inline struct nf_generic_net *generic_pernet(struct net *net) { return &net->ct.nf_ct_proto.generic; @@ -67,7 +91,7 @@ static int generic_packet(struct nf_conn *ct, static bool generic_new(struct nf_conn *ct, const struct sk_buff *skb, unsigned int dataoff, unsigned int *timeouts) { - return true; + return nf_generic_should_process(nf_ct_protonum(ct)); } #if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT) -- 2.7.4