From 88234890ea8fd8f60101c0b9690f1ea756cc3c5b Mon Sep 17 00:00:00 2001 From: Justin Date: Mon, 25 Mar 2013 18:06:02 -0500 Subject: smdk4412: mali: merge with r3p1 driver from note8 Change-Id: I75db69081b986ec326fe347f73aa3655648e6b81 --- drivers/media/video/samsung/mali/Kbuild_module | 9 +- drivers/media/video/samsung/mali/Makefile | 24 +- .../video/samsung/mali/arch-orion-m400/config.h | 154 ++++++++++ drivers/media/video/samsung/mali/common/mali_gp.c | 45 +-- .../media/video/samsung/mali/common/mali_gp_job.c | 18 +- .../media/video/samsung/mali/common/mali_gp_job.h | 38 ++- .../video/samsung/mali/common/mali_gp_scheduler.c | 18 +- .../media/video/samsung/mali/common/mali_group.h | 2 +- .../media/video/samsung/mali/common/mali_hw_core.h | 33 --- .../video/samsung/mali/common/mali_kernel_common.h | 10 + .../video/samsung/mali/common/mali_kernel_core.c | 6 +- .../video/samsung/mali/common/mali_kernel_core.h | 1 + .../video/samsung/mali/common/mali_kernel_mem_os.c | 6 +- drivers/media/video/samsung/mali/common/mali_osk.h | 11 + .../video/samsung/mali/common/mali_osk_profiling.h | 22 +- drivers/media/video/samsung/mali/common/mali_pp.c | 121 ++------ .../media/video/samsung/mali/common/mali_pp_job.c | 59 +++- .../media/video/samsung/mali/common/mali_pp_job.h | 103 +++---- .../video/samsung/mali/common/mali_pp_scheduler.c | 248 ++++++++-------- .../video/samsung/mali/common/mali_pp_scheduler.h | 1 - drivers/media/video/samsung/mali/common/mali_ukk.h | 10 +- .../linux/mali/mali_utgard_profiling_events.h | 24 -- .../video/samsung/mali/linux/mali_kernel_linux.c | 112 +++++-- .../video/samsung/mali/linux/mali_kernel_sysfs.c | 22 +- .../video/samsung/mali/linux/mali_osk_locks.c | 27 +- .../media/video/samsung/mali/linux/mali_osk_mali.c | 2 +- .../samsung/mali/linux/mali_osk_notification.c | 43 ++- .../video/samsung/mali/linux/mali_osk_profiling.c | 261 ----------------- .../samsung/mali/linux/mali_osk_profiling_gator.c | 261 +++++++++++++++++ .../mali/linux/mali_osk_profiling_internal.c | 324 +++++++++++++++++++++ .../video/samsung/mali/linux/mali_osk_specific.h | 14 +- .../samsung/mali/linux/mali_profiling_internal.c | 294 ------------------- .../samsung/mali/linux/mali_profiling_internal.h | 36 --- .../media/video/samsung/mali/linux/mali_uk_types.h | 3 +- .../media/video/samsung/mali/linux/mali_ukk_gp.c | 37 ++- .../media/video/samsung/mali/linux/mali_ukk_pp.c | 13 +- .../mali/platform/orion-m400/mali_platform.c | 46 ++- .../mali/platform/pegasus-m400/mali_platform.c | 54 ++-- .../platform/pegasus-m400/mali_platform_dvfs.c | 38 ++- .../media/video/samsung/mali/regs/mali_gp_regs.h | 2 + drivers/media/video/samsung/ump/Kconfig | 13 +- drivers/media/video/samsung/ump/Makefile | 9 + drivers/media/video/samsung/ump/Makefile.common | 4 +- .../video/samsung/ump/common/ump_kernel_api.c | 23 +- .../video/samsung/ump/common/ump_kernel_common.c | 20 +- .../ump/common/ump_kernel_descriptor_mapping.c | 33 +-- .../samsung/ump/common/ump_kernel_memory_backend.h | 7 +- .../video/samsung/ump/common/ump_kernel_ref_drv.c | 63 ++++ drivers/media/video/samsung/ump/common/ump_osk.h | 6 +- .../media/video/samsung/ump/common/ump_uk_types.h | 4 + .../ump/include/ump_kernel_interface_ref_drv.h | 8 +- .../video/samsung/ump/linux/ump_kernel_linux.c | 9 +- .../linux/ump_kernel_memory_backend_dedicated.c | 6 +- .../ump/linux/ump_kernel_memory_backend_os.c | 11 +- .../ump/linux/ump_kernel_memory_backend_vcm.c | 290 ++++++++++++++++++ .../ump/linux/ump_kernel_memory_backend_vcm.h | 22 ++ .../video/samsung/ump/linux/ump_memory_backend.c | 7 + .../samsung/ump/linux/ump_osk_low_level_mem.c | 141 ++++++++- .../video/samsung/ump/linux/ump_ukk_ref_wrappers.c | 7 +- 59 files changed, 2023 insertions(+), 1212 deletions(-) create mode 100644 drivers/media/video/samsung/mali/arch-orion-m400/config.h delete mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_profiling.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_profiling_gator.c create mode 100644 drivers/media/video/samsung/mali/linux/mali_osk_profiling_internal.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_profiling_internal.c delete mode 100644 drivers/media/video/samsung/mali/linux/mali_profiling_internal.h create mode 100644 drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.c create mode 100644 drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.h (limited to 'drivers/media') diff --git a/drivers/media/video/samsung/mali/Kbuild_module b/drivers/media/video/samsung/mali/Kbuild_module index d861b72..e865954 100644 --- a/drivers/media/video/samsung/mali/Kbuild_module +++ b/drivers/media/video/samsung/mali/Kbuild_module @@ -16,13 +16,16 @@ OSKOS=linux USING_UMP ?= 0 USING_OS_MEMORY ?= 0 USING_MALI_PMM_TESTSUITE ?= 0 -OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB ?= 6 +OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB ?= 16 USING_PROFILING ?= 1 USING_INTERNAL_PROFILING ?= 0 DISABLE_PP0 ?= 0 DISABLE_PP1 ?= 0 DISABLE_PP2 ?= 0 DISABLE_PP3 ?= 0 +PROFILING_SKIP_PP_JOBS ?= 0 +PROFILING_SKIP_PP_AND_GP_JOBS ?= 0 +PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH ?= 0 TIMESTAMP ?= default BUILD ?= debug TARGET_PLATFORM ?= default @@ -129,6 +132,10 @@ DEFINES += -DDISABLE_PP0=$(DISABLE_PP0) DEFINES += -DDISABLE_PP1=$(DISABLE_PP1) DEFINES += -DDISABLE_PP2=$(DISABLE_PP2) DEFINES += -DDISABLE_PP3=$(DISABLE_PP3) +DEFINES += -DPROFILING_SKIP_PP_JOBS=$(PROFILING_SKIP_PP_JOBS) +DEFINES += -DPROFILING_SKIP_PP_AND_GP_JOBS=$(PROFILING_SKIP_PP_AND_GP_JOBS) +DEFINES += -DPROFILING_PRINT_L2_HITRATE_ON_GP_FINISH=$(PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH) + DEFINES += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP) DEFINES += -DMALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED=$(MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED) DEFINES += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS) diff --git a/drivers/media/video/samsung/mali/Makefile b/drivers/media/video/samsung/mali/Makefile index 524f910..3e25b61 100644 --- a/drivers/media/video/samsung/mali/Makefile +++ b/drivers/media/video/samsung/mali/Makefile @@ -49,10 +49,15 @@ USING_GPU_UTILIZATION=1 USING_MALI_DVFS_ENABLED=1 endif -ifeq ($(CONFIG_VIDEO_MALI400MP_DEBUG),y) +ifeq ($(CONFIG_VIDEO_UMP_DEBUG),y) BUILD=debug endif +ifeq ($(CONFIG_VIDEO_MALI400MP_STREAMLINE_PROFILING),y) +USING_PROFILING=1 +USING_TRACEPOINTS=1 +endif + # set up defaults if not defined by the user USE_UMPV2 ?= 0 PANIC_ON_WATCHDOG_TIMEOUT ?= 1 @@ -68,7 +73,7 @@ USING_MALI_RUN_TIME_PM ?= 0 USING_MALI_PMM_TESTSUITE ?= 0 USING_MALI_PMU ?= 0 USING_GPU_UTILIZATION ?= 0 -OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB ?= 6 +OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB ?= 16 USING_PROFILING ?= 0 USING_INTERNAL_PROFILING ?= 0 USING_TRACEPOINTS ?= 0 @@ -81,6 +86,9 @@ DISABLE_PP0 ?= 0 DISABLE_PP1 ?= 0 DISABLE_PP2 ?= 0 DISABLE_PP3 ?= 0 +PROFILING_SKIP_PP_JOBS ?= 0 +PROFILING_SKIP_PP_AND_GP_JOBS ?= 0 +PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH ?= 0 TIMESTAMP ?= default BUILD ?= release TARGET_PLATFORM ?= default @@ -145,6 +153,9 @@ DEFINES += -DDISABLE_PP0=$(DISABLE_PP0) DEFINES += -DDISABLE_PP1=$(DISABLE_PP1) DEFINES += -DDISABLE_PP2=$(DISABLE_PP2) DEFINES += -DDISABLE_PP3=$(DISABLE_PP3) +DEFINES += -DPROFILING_SKIP_PP_JOBS=$(PROFILING_SKIP_PP_JOBS) +DEFINES += -DPROFILING_SKIP_PP_AND_GP_JOBS=$(PROFILING_SKIP_PP_AND_GP_JOBS) +DEFINES += -DPROFILING_PRINT_L2_HITRATE_ON_GP_FINISH=$(PROFILING_PRINT_L2_HITRATE_ON_GP_FINISH) DEFINES += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP) DEFINES += -DMALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED=$(MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED) DEFINES += -DMALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS=$(MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS) @@ -168,7 +179,7 @@ else endif # Target build file -obj-$(CONFIG_VIDEO_MALI400MP) += mali.o +obj-$(CONFIG_VIDEO_UMP) += mali.o # Use our defines when compiling # MALI @@ -179,10 +190,9 @@ INCLUDES = \ -I$(MALI_INCLUDE_PREFIX)linux \ -I$(MALI_INCLUDE_PREFIX)platform\ -I$(MALI_INCLUDE_PREFIX)regs - EXTRA_CFLAGS += $(INCLUDES)\ - $(DEFINES) + $(DEFINES) EXTRA_CFLAGS += -I$(MALI_INCLUDE_PREFIX)linux/license/gpl EXTRA_CFLAGS += -I$(MALI_INCLUDE_PREFIX)common/pmm @@ -266,7 +276,7 @@ mali-y := \ linux/mali_pmu_power_up_down.o \ $(MALI_PLATFORM_FILE) \ $(OSKFILES) \ - $(UKKFILES) + $(UKKFILES) # __malidrv_build_info.c # Selecting files to compile by parsing the config file @@ -279,7 +289,7 @@ EXTRA_CFLAGS += -I$(MALI_INCLUDE_PREFIX)timestamp-$(TIMESTAMP) else ifeq ($(USING_PROFILING),1) PROFILING_BACKEND_SOURCES = \ - linux/mali_osk_profiling.o + linux/mali_osk_profiling_gator.o endif endif diff --git a/drivers/media/video/samsung/mali/arch-orion-m400/config.h b/drivers/media/video/samsung/mali/arch-orion-m400/config.h new file mode 100644 index 0000000..5c4d79d --- /dev/null +++ b/drivers/media/video/samsung/mali/arch-orion-m400/config.h @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2010 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_CONFIG_H__ +#define __ARCH_CONFIG_H__ + +/* Configuration for the EB platform with ZBT memory enabled */ +/*zepplin added 2010.08.17 for orion configuration*/ +#define MALI_BASE_ADDR 0x13000000 +#define GP_ADDR MALI_BASE_ADDR +#define L2_ADDR MALI_BASE_ADDR+0x1000 +#define PMU_ADDR MALI_BASE_ADDR+0x2000 +#define GP_MMU_ADDR MALI_BASE_ADDR+0x3000 +#define PP0_MMU_ADDR MALI_BASE_ADDR+0x4000 +#define PP1_MMU_ADDR MALI_BASE_ADDR+0x5000 +#define PP2_MMU_ADDR MALI_BASE_ADDR+0x6000 +#define PP3_MMU_ADDR MALI_BASE_ADDR+0x7000 +#define PP0_ADDR MALI_BASE_ADDR+0x8000 +#define PP1_ADDR MALI_BASE_ADDR+0xA000 +#define PP2_ADDR MALI_BASE_ADDR+0xC000 +#define PP3_ADDR MALI_BASE_ADDR+0xE000 + +/*for mmu and os memory*/ +#define MEM_BASE_ADDR 0x40000000 +#define MEM_TOTAL_SIZE 0x40000000 +#define MEM_MALI_OS_SIZE 0x40000000 + +/*for dedicated memory*/ +//#define MEM_MALI_BASE 0x58000000 +//#define MEM_MALI_SIZE 0x08000000 +#define MEM_MALI_SIZE CONFIG_MALI_MEM_SIZE*1024*1024 +#define MEM_MALI_BASE 0x80000000 - MEM_MALI_SIZE + +static _mali_osk_resource_t arch_configuration [] = +{ + { + .type = MALI400GP, + .description = "Mali-400 GP", + .base = GP_ADDR, + .irq = IRQ_GP_3D, + .mmu_id = 1 + }, + { + .type = MALI400PP, + .base = PP0_ADDR, + .irq = IRQ_PP0_3D, + .description = "Mali-400 PP 0", + .mmu_id = 2 + }, + { + .type = MALI400PP, + .base = PP1_ADDR, + .irq = IRQ_PP1_3D, + .description = "Mali-400 PP 1", + .mmu_id = 3 + }, + { + .type = MALI400PP, + .base = PP2_ADDR, + .irq = IRQ_PP2_3D, + .description = "Mali-400 PP 2", + .mmu_id = 4 + }, + { + .type = MALI400PP, + .base = PP3_ADDR, + .irq = IRQ_PP3_3D, + .description = "Mali-400 PP 3", + .mmu_id = 5 + }, +#if USING_MMU + { + .type = MMU, + .base = GP_MMU_ADDR, + .irq = IRQ_GPMMU_3D, + .description = "Mali-400 MMU for GP", + .mmu_id = 1 + }, + { + .type = MMU, + .base = PP0_MMU_ADDR, + .irq = IRQ_PPMMU0_3D, + .description = "Mali-400 MMU for PP 0", + .mmu_id = 2 + }, + { + .type = MMU, + .base = PP1_MMU_ADDR, + .irq = IRQ_PPMMU1_3D, + .description = "Mali-400 MMU for PP 1", + .mmu_id = 3 + }, + { + .type = MMU, + .base = PP2_MMU_ADDR, + .irq = IRQ_PPMMU2_3D, + .description = "Mali-400 MMU for PP 2", + .mmu_id = 4 + }, + { + .type = MMU, + .base = PP3_MMU_ADDR, + .irq = IRQ_PPMMU3_3D, + .description = "Mali-400 MMU for PP 3", + .mmu_id = 5 + }, +#if USING_OS_MEMORY + { + .type = OS_MEMORY, + .description = "System Memory", + .size = MEM_MALI_OS_SIZE, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE + }, +#endif +#if USING_DED /* Dedicated Memory */ + { + .type = MEMORY, + .description = "Dedicated Memory", + .base = MEM_MALI_BASE, + .size = MEM_MALI_SIZE, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE + }, +#endif/* if USING_OS_MEMORY*/ + { + .type = MEM_VALIDATION, + .description = "memory validation", + .base = MEM_BASE_ADDR, + .size = MEM_TOTAL_SIZE, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE + }, +#else /* Not using MMU */ + { + .type = MEMORY, + .description = "Dedicated Memory", + .base = MEM_MALI_BASE, + .size = MEM_MALI_SIZE, + .flags = _MALI_CPU_WRITEABLE | _MALI_CPU_READABLE | _MALI_PP_READABLE | _MALI_PP_WRITEABLE | _MALI_GP_READABLE | _MALI_GP_WRITEABLE | _MALI_MMU_READABLE | _MALI_MMU_WRITEABLE + }, +#endif + { + .type = MALI400L2, + .base = L2_ADDR, + .description = "Mali-400 L2 cache" + }, +}; + +#endif /* __ARCH_CONFIG_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_gp.c b/drivers/media/video/samsung/mali/common/mali_gp.c index 2110471..1624e46 100644 --- a/drivers/media/video/samsung/mali/common/mali_gp.c +++ b/drivers/media/video/samsung/mali/common/mali_gp.c @@ -361,8 +361,8 @@ void mali_gp_job_start(struct mali_gp_core *core, struct mali_gp_job *job) #if MALI_TIMELINE_PROFILING_ENABLED _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0) | MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH, - mali_gp_job_get_frame_builder_id(job), mali_gp_job_get_flush_id(job), 0, 0, 0); - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0), mali_gp_job_get_pid(job), mali_gp_job_get_tid(job), 0, 0, 0); + job->frame_builder_id, job->flush_id, 0, 0, 0); + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0), job->pid, job->tid, 0, 0, 0); #endif core->running_job = job; @@ -480,7 +480,9 @@ static void mali_gp_bottom_half(void *data) u32 irq_errors; #if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), MALI_PROFILING_MAKE_EVENT_DATA_CORE_GP(0), 0, 0); +#if 0 /* Bottom half TLP logging is currently not supported */ + _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_START| MALI_PROFILING_EVENT_CHANNEL_SOFTWARE , _mali_osk_get_pid(), _mali_osk_get_tid()+11000, 0, 0, 0); +#endif #endif mali_group_lock(core->group); /* Group lock grabbed in core handlers, but released in common group handler */ @@ -489,9 +491,6 @@ static void mali_gp_bottom_half(void *data) { MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.", core->hw_core.description)); mali_group_unlock(core->group); -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0); -#endif return; } @@ -506,9 +505,6 @@ static void mali_gp_bottom_half(void *data) mali_gp_post_process_job(core, MALI_FALSE); MALI_DEBUG_PRINT(4, ("Mali GP: Job completed, calling group handler\n")); mali_group_bottom_half(core->group, GROUP_EVENT_GP_JOB_COMPLETED); /* Will release group lock */ -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0); -#endif return; } } @@ -523,9 +519,6 @@ static void mali_gp_bottom_half(void *data) mali_gp_post_process_job(core, MALI_FALSE); MALI_PRINT_ERROR(("Mali GP: Unknown interrupt 0x%08X from core %s, aborting job\n", irq_readout, core->hw_core.description)); mali_group_bottom_half(core->group, GROUP_EVENT_GP_JOB_FAILED); /* Will release group lock */ -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0); -#endif return; } else if (MALI_TRUE == core->core_timed_out) /* SW timeout */ @@ -537,9 +530,6 @@ static void mali_gp_bottom_half(void *data) mali_group_bottom_half(core->group, GROUP_EVENT_GP_JOB_TIMED_OUT); } core->core_timed_out = MALI_FALSE; -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0); -#endif return; } else if (irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM) @@ -556,30 +546,25 @@ static void mali_gp_bottom_half(void *data) mali_gp_post_process_job(core, MALI_TRUE); MALI_DEBUG_PRINT(3, ("Mali GP: PLBU needs more heap memory\n")); mali_group_bottom_half(core->group, GROUP_EVENT_GP_OOM); /* Will release group lock */ -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0); -#endif return; } else if (irq_readout & MALIGP2_REG_VAL_IRQ_HANG) { - /* we mask hang interrupts, so this should never happen... */ - MALI_DEBUG_ASSERT( 0 ); + /* Just ignore hang interrupts, the job timer will detect hanging jobs anyways */ + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_HANG); } - /* The only way to get here is if we only got one of two needed END_CMD_LST - * interrupts. Disable the interrupt that has been received and continue to - * run. */ - mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, - MALIGP2_REG_VAL_IRQ_MASK_USED & - ((irq_readout & MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST) - ? ~MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST - : ~MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST - )); + /* + * The only way to get here is if we got a HANG interrupt, which we ignore, or only one of two needed END_CMD_LST interrupts. + * Re-enable interrupts and let core continue to run. + */ + mali_hw_core_register_write(&core->hw_core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_USED); mali_group_unlock(core->group); #if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0); +#if 0 /* Bottom half TLP logging is currently not supported */ + _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_STOP| MALI_PROFILING_EVENT_CHANNEL_SOFTWARE , _mali_osk_get_pid(), _mali_osk_get_tid()+11000, 0, 0, 0); +#endif #endif } diff --git a/drivers/media/video/samsung/mali/common/mali_gp_job.c b/drivers/media/video/samsung/mali/common/mali_gp_job.c index 2e445d6..abe1d93 100644 --- a/drivers/media/video/samsung/mali/common/mali_gp_job.c +++ b/drivers/media/video/samsung/mali/common/mali_gp_job.c @@ -13,27 +13,29 @@ #include "mali_osk_list.h" #include "mali_uk_types.h" -struct mali_gp_job *mali_gp_job_create(struct mali_session_data *session, _mali_uk_gp_start_job_s *uargs, u32 id) +struct mali_gp_job *mali_gp_job_create(struct mali_session_data *session, _mali_uk_gp_start_job_s *args, u32 id) { struct mali_gp_job *job; job = _mali_osk_malloc(sizeof(struct mali_gp_job)); if (NULL != job) { - if (0 != copy_from_user(&job->uargs, uargs, sizeof(_mali_uk_gp_start_job_s))) - { - _mali_osk_free(job); - return NULL; - } - _mali_osk_list_init(&job->list); job->session = session; job->id = id; - job->heap_current_addr = job->uargs.frame_registers[4]; + job->user_id = args->user_job_ptr; + _mali_osk_memcpy(job->frame_registers, args->frame_registers, sizeof(job->frame_registers)); + job->heap_current_addr = args->frame_registers[4]; + job->perf_counter_flag = args->perf_counter_flag; + job->perf_counter_src0 = args->perf_counter_src0; + job->perf_counter_src1 = args->perf_counter_src1; job->perf_counter_value0 = 0; job->perf_counter_value1 = 0; + job->pid = _mali_osk_get_pid(); job->tid = _mali_osk_get_tid(); + job->frame_builder_id = args->frame_builder_id; + job->flush_id = args->flush_id; return job; } diff --git a/drivers/media/video/samsung/mali/common/mali_gp_job.h b/drivers/media/video/samsung/mali/common/mali_gp_job.h index 7b45552..9c29f1c 100644 --- a/drivers/media/video/samsung/mali/common/mali_gp_job.h +++ b/drivers/media/video/samsung/mali/common/mali_gp_job.h @@ -25,16 +25,22 @@ struct mali_gp_job { _mali_osk_list_t list; /**< Used to link jobs together in the scheduler queue */ struct mali_session_data *session; /**< Session which submitted this job */ - _mali_uk_gp_start_job_s uargs; /**< Arguments from user space */ u32 id; /**< identifier for this job in kernel space (sequential numbering) */ + u32 user_id; /**< identifier for the job in user space */ + u32 frame_registers[MALIGP2_NUM_REGS_FRAME]; /**< core specific registers associated with this job, see ARM DDI0415A */ u32 heap_current_addr; /**< Holds the current HEAP address when the job has completed */ + u32 perf_counter_flag; /**< bitmask indicating which performance counters to enable, see \ref _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE and related macro definitions */ + u32 perf_counter_src0; /**< source id for performance counter 0 (see ARM DDI0415A, Table 3-60) */ + u32 perf_counter_src1; /**< source id for performance counter 1 (see ARM DDI0415A, Table 3-60) */ u32 perf_counter_value0; /**< Value of performance counter 0 (to be returned to user space) */ u32 perf_counter_value1; /**< Value of performance counter 1 (to be returned to user space) */ u32 pid; /**< Process ID of submitting process */ u32 tid; /**< Thread ID of submitting thread */ + u32 frame_builder_id; /**< id of the originating frame builder */ + u32 flush_id; /**< flush id within the originating frame builder */ }; -struct mali_gp_job *mali_gp_job_create(struct mali_session_data *session, _mali_uk_gp_start_job_s *uargs, u32 id); +struct mali_gp_job *mali_gp_job_create(struct mali_session_data *session, _mali_uk_gp_start_job_s *args, u32 id); void mali_gp_job_delete(struct mali_gp_job *job); MALI_STATIC_INLINE u32 mali_gp_job_get_id(struct mali_gp_job *job) @@ -44,32 +50,22 @@ MALI_STATIC_INLINE u32 mali_gp_job_get_id(struct mali_gp_job *job) MALI_STATIC_INLINE u32 mali_gp_job_get_user_id(struct mali_gp_job *job) { - return job->uargs.user_job_ptr; + return job->user_id; } MALI_STATIC_INLINE u32 mali_gp_job_get_frame_builder_id(struct mali_gp_job *job) { - return job->uargs.frame_builder_id; + return job->frame_builder_id; } MALI_STATIC_INLINE u32 mali_gp_job_get_flush_id(struct mali_gp_job *job) { - return job->uargs.flush_id; -} - -MALI_STATIC_INLINE u32 mali_gp_job_get_pid(struct mali_gp_job *job) -{ - return job->pid; -} - -MALI_STATIC_INLINE u32 mali_gp_job_get_tid(struct mali_gp_job *job) -{ - return job->tid; + return job->flush_id; } MALI_STATIC_INLINE u32* mali_gp_job_get_frame_registers(struct mali_gp_job *job) { - return job->uargs.frame_registers; + return job->frame_registers; } MALI_STATIC_INLINE struct mali_session_data *mali_gp_job_get_session(struct mali_gp_job *job) @@ -79,12 +75,12 @@ MALI_STATIC_INLINE struct mali_session_data *mali_gp_job_get_session(struct mali MALI_STATIC_INLINE mali_bool mali_gp_job_has_vs_job(struct mali_gp_job *job) { - return (job->uargs.frame_registers[0] != job->uargs.frame_registers[1]) ? MALI_TRUE : MALI_FALSE; + return (job->frame_registers[0] != job->frame_registers[1]) ? MALI_TRUE : MALI_FALSE; } MALI_STATIC_INLINE mali_bool mali_gp_job_has_plbu_job(struct mali_gp_job *job) { - return (job->uargs.frame_registers[2] != job->uargs.frame_registers[3]) ? MALI_TRUE : MALI_FALSE; + return (job->frame_registers[2] != job->frame_registers[3]) ? MALI_TRUE : MALI_FALSE; } MALI_STATIC_INLINE u32 mali_gp_job_get_current_heap_addr(struct mali_gp_job *job) @@ -99,17 +95,17 @@ MALI_STATIC_INLINE void mali_gp_job_set_current_heap_addr(struct mali_gp_job *jo MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_flag(struct mali_gp_job *job) { - return job->uargs.perf_counter_flag; + return job->perf_counter_flag; } MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_src0(struct mali_gp_job *job) { - return job->uargs.perf_counter_src0; + return job->perf_counter_src0; } MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_src1(struct mali_gp_job *job) { - return job->uargs.perf_counter_src1; + return job->perf_counter_src1; } MALI_STATIC_INLINE u32 mali_gp_job_get_perf_counter_value0(struct mali_gp_job *job) diff --git a/drivers/media/video/samsung/mali/common/mali_gp_scheduler.c b/drivers/media/video/samsung/mali/common/mali_gp_scheduler.c index 52fa15b..f06d899 100644 --- a/drivers/media/video/samsung/mali/common/mali_gp_scheduler.c +++ b/drivers/media/video/samsung/mali/common/mali_gp_scheduler.c @@ -274,17 +274,25 @@ void mali_gp_scheduler_resume(void) mali_gp_scheduler_unlock(); } -_mali_osk_errcode_t _mali_ukk_gp_start_job(void *ctx, _mali_uk_gp_start_job_s *uargs) +_mali_osk_errcode_t _mali_ukk_gp_start_job(_mali_uk_gp_start_job_s *args) { struct mali_session_data *session; struct mali_gp_job *job; - MALI_DEBUG_ASSERT_POINTER(uargs); - MALI_DEBUG_ASSERT_POINTER(ctx); + MALI_DEBUG_ASSERT_POINTER(args); + + if (NULL == args->ctx) + { + return _MALI_OSK_ERR_INVALID_ARGS; + } - session = (struct mali_session_data*)ctx; + session = (struct mali_session_data*)args->ctx; + if (NULL == session) + { + return _MALI_OSK_ERR_FAULT; + } - job = mali_gp_job_create(session, uargs, mali_scheduler_get_new_id()); + job = mali_gp_job_create(session, args, mali_scheduler_get_new_id()); if (NULL == job) { return _MALI_OSK_ERR_NOMEM; diff --git a/drivers/media/video/samsung/mali/common/mali_group.h b/drivers/media/video/samsung/mali/common/mali_group.h index 1561d6b..3533d13 100644 --- a/drivers/media/video/samsung/mali/common/mali_group.h +++ b/drivers/media/video/samsung/mali/common/mali_group.h @@ -102,7 +102,7 @@ _mali_osk_errcode_t mali_group_start_gp_job(struct mali_group *group, struct mal */ _mali_osk_errcode_t mali_group_start_pp_job(struct mali_group *group, struct mali_pp_job *job, u32 sub_job); -/** @brief Resume GP job that suspended waiting for more heap memory +/** @brief Resume GP job that suspended waiting for more heap memory */ void mali_group_resume_gp_with_new_heap(struct mali_group *group, u32 job_id, u32 start_addr, u32 end_addr); /** @brief Abort GP job diff --git a/drivers/media/video/samsung/mali/common/mali_hw_core.h b/drivers/media/video/samsung/mali/common/mali_hw_core.h index b62e843..c797804 100644 --- a/drivers/media/video/samsung/mali/common/mali_hw_core.h +++ b/drivers/media/video/samsung/mali/common/mali_hw_core.h @@ -48,20 +48,6 @@ MALI_STATIC_INLINE void mali_hw_core_register_write_relaxed(struct mali_hw_core _mali_osk_mem_iowrite32_relaxed(core->mapped_registers, relative_address, new_val); } -/* Conditionally write a register. - * The register will only be written if the new value is different from the old_value. - * If the new value is different, the old value will also be updated */ -MALI_STATIC_INLINE void mali_hw_core_register_write_relaxed_conditional(struct mali_hw_core *core, u32 relative_address, u32 new_val, const u32 old_val) -{ - MALI_DEBUG_PRINT(6, ("register_write_relaxed for core %s, relative addr=0x%04X, val=0x%08X\n", - core->description, relative_address, new_val)); - if(old_val != new_val) - { - _mali_osk_mem_iowrite32_relaxed(core->mapped_registers, relative_address, new_val); - } -} - - MALI_STATIC_INLINE void mali_hw_core_register_write(struct mali_hw_core *core, u32 relative_address, u32 new_val) { MALI_DEBUG_PRINT(6, ("register_write for core %s, relative addr=0x%04X, val=0x%08X\n", @@ -82,23 +68,4 @@ MALI_STATIC_INLINE void mali_hw_core_register_write_array_relaxed(struct mali_hw } } -/* Conditionally write a set of registers. - * The register will only be written if the new value is different from the old_value. - * If the new value is different, the old value will also be updated */ -MALI_STATIC_INLINE void mali_hw_core_register_write_array_relaxed_conditional(struct mali_hw_core *core, u32 relative_address, u32 *write_array, u32 nr_of_regs, const u32* old_array) -{ - u32 i; - MALI_DEBUG_PRINT(6, ("register_write_array: for core %s, relative addr=0x%04X, nr of regs=%u\n", - core->description,relative_address, nr_of_regs)); - - /* Do not use burst writes against the registers */ - for (i = 0; i< nr_of_regs; i++) - { - if(old_array[i] != write_array[i]) - { - mali_hw_core_register_write_relaxed(core, relative_address + i*4, write_array[i]); - } - } -} - #endif /* __MALI_HW_CORE_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_common.h b/drivers/media/video/samsung/mali/common/mali_kernel_common.h index a33660b..b354f92 100644 --- a/drivers/media/video/samsung/mali/common/mali_kernel_common.h +++ b/drivers/media/video/samsung/mali/common/mali_kernel_common.h @@ -18,6 +18,16 @@ #endif #endif +/* Macro for generating a kernel panic. + * Turned on off by compile-time Makefile settings + */ +#if defined(USING_KERNEL_PANIC) +#include + #define MALI_PANIC(fmt, args...) panic( fmt, ## args ); +#else + #define MALI_PANIC(fmt, args...) +#endif + /* The file include several useful macros for error checking, debugging and printing. * - MALI_PRINTF(...) Do not use this function: Will be included in Release builds. * - MALI_DEBUG_PRINT(nr, (X) ) Prints the second argument if nr<=MALI_DEBUG_LEVEL. diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_core.c b/drivers/media/video/samsung/mali/common/mali_kernel_core.c index f31c505..45e86d2 100644 --- a/drivers/media/video/samsung/mali/common/mali_kernel_core.c +++ b/drivers/media/video/samsung/mali/common/mali_kernel_core.c @@ -35,10 +35,6 @@ #if MALI_TIMELINE_PROFILING_ENABLED #include "mali_osk_profiling.h" #endif -#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED -#include "mali_profiling_internal.h" -#endif - /** Pointer to table of resource definitions available to the Mali driver. * _mali_osk_resources_init() sets up the pointer to this table. @@ -58,10 +54,12 @@ static u32 global_gpu_minor_version = 0; static u32 first_pp_offset = 0; +#define HANG_CHECK_MSECS_DEFAULT 500 /* 500 ms */ #define WATCHDOG_MSECS_DEFAULT 4000 /* 4 s */ /* timer related */ int mali_max_job_runtime = WATCHDOG_MSECS_DEFAULT; +int mali_hang_check_interval = HANG_CHECK_MSECS_DEFAULT; static _mali_osk_resource_t *mali_find_resource(_mali_osk_resource_type_t type, u32 offset) { diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_core.h b/drivers/media/video/samsung/mali/common/mali_kernel_core.h index 0ac967e..d424c48 100644 --- a/drivers/media/video/samsung/mali/common/mali_kernel_core.h +++ b/drivers/media/video/samsung/mali/common/mali_kernel_core.h @@ -13,6 +13,7 @@ #include "mali_osk.h" +extern int mali_hang_check_interval; extern int mali_max_job_runtime; typedef enum diff --git a/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.c b/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.c index 2830ff8..243595d 100644 --- a/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.c +++ b/drivers/media/video/samsung/mali/common/mali_kernel_mem_os.c @@ -132,7 +132,7 @@ static mali_physical_memory_allocation_result os_allocator_allocate(void* ctx, m allocation->num_pages = ((left + _MALI_OSK_CPU_PAGE_SIZE - 1) & ~(_MALI_OSK_CPU_PAGE_SIZE - 1)) >> _MALI_OSK_CPU_PAGE_ORDER; MALI_DEBUG_PRINT(6, ("Allocating page array of size %d bytes\n", allocation->num_pages * sizeof(struct page*))); - while (left > 0 && ((info->num_pages_allocated + pages_allocated) < info->num_pages_max) && _mali_osk_mem_check_allocated(os_mem_max_usage)) + while (left > 0) { err = mali_allocation_engine_map_physical(engine, descriptor, *offset, MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC, info->cpu_usage_adjust, _MALI_OSK_CPU_PAGE_SIZE); if ( _MALI_OSK_ERR_OK != err) @@ -243,7 +243,11 @@ static void os_allocator_release(void * ctx, void * handle) static mali_physical_memory_allocation_result os_allocator_allocate_page_table_block(void * ctx, mali_page_table_block * block) { +#ifdef CONFIG_CPU_EXYNOS4210 int allocation_order = 6; /* _MALI_OSK_CPU_PAGE_SIZE << 6 */ +#else + int allocation_order = 11; /* _MALI_OSK_CPU_PAGE_SIZE << 11 */ +#endif void *virt = NULL; u32 size = _MALI_OSK_CPU_PAGE_SIZE << allocation_order; os_allocator * info; diff --git a/drivers/media/video/samsung/mali/common/mali_osk.h b/drivers/media/video/samsung/mali/common/mali_osk.h index c478057..e32d15d 100644 --- a/drivers/media/video/samsung/mali/common/mali_osk.h +++ b/drivers/media/video/samsung/mali/common/mali_osk.h @@ -1422,6 +1422,17 @@ void _mali_osk_notification_queue_term( _mali_osk_notification_queue_t *queue ); */ void _mali_osk_notification_queue_send( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t *object ); +#if MALI_STATE_TRACKING +/** @brief Receive a notification from a queue + * + * Check if a notification queue is empty. + * + * @param queue The queue to check. + * @return MALI_TRUE if queue is empty, otherwise MALI_FALSE. + */ +mali_bool _mali_osk_notification_queue_is_empty( _mali_osk_notification_queue_t *queue ); +#endif + /** @brief Receive a notification from a queue * * Receives a single notification from the given queue. diff --git a/drivers/media/video/samsung/mali/common/mali_osk_profiling.h b/drivers/media/video/samsung/mali/common/mali_osk_profiling.h index bf1cf8c..fd9a8fb 100644 --- a/drivers/media/video/samsung/mali/common/mali_osk_profiling.h +++ b/drivers/media/video/samsung/mali/common/mali_osk_profiling.h @@ -11,9 +11,12 @@ #ifndef __MALI_OSK_PROFILING_H__ #define __MALI_OSK_PROFILING_H__ -#if MALI_TIMELINE_PROFILING_ENABLED && defined (CONFIG_TRACEPOINTS) +#if MALI_TIMELINE_PROFILING_ENABLED +#if defined (CONFIG_TRACEPOINTS) && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED #include "mali_linux_trace.h" +#endif /* CONFIG_TRACEPOINTS && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED */ + #include "mali_profiling_events.h" #define MALI_PROFILING_MAX_BUFFER_ENTRIES 1048576 @@ -56,8 +59,13 @@ _mali_osk_errcode_t _mali_osk_profiling_start(u32 * limit); * @param data4 Fifth data parameter, depending on event_id specified. * @return _MALI_OSK_ERR_OK on success, otherwise failure. */ +#if defined (CONFIG_TRACEPOINTS) && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED /* Call Linux tracepoint directly */ #define _mali_osk_profiling_add_event(event_id, data0, data1, data2, data3, data4) trace_mali_timeline_event((event_id), (data0), (data1), (data2), (data3), (data4)) +#else +/* Internal profiling is handled like a plain function call */ +void _mali_osk_profiling_add_event(u32 event_id, u32 data0, u32 data1, u32 data2, u32 data3, u32 data4); +#endif /** * Report a hardware counter event. @@ -66,8 +74,13 @@ _mali_osk_errcode_t _mali_osk_profiling_start(u32 * limit); * @param value The value of the counter. */ +#if defined (CONFIG_TRACEPOINTS) && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED /* Call Linux tracepoint directly */ #define _mali_osk_profiling_report_hw_counter(counter_id, value) trace_mali_hw_counter(counter_id, value) +#else +/* Internal profiling is handled like a plain function call */ +void _mali_osk_profiling_report_hw_counter(u32 counter_id, u32 value); +#endif /** * Report SW counters @@ -127,12 +140,7 @@ mali_bool _mali_osk_profiling_have_recording(void); /** @} */ /* end group _mali_osk_profiling */ -#else - /* Dummy add_event, for when profiling is disabled. */ - -#define _mali_osk_profiling_add_event(event_id, data0, data1, data2, data3, data4) - -#endif /* MALI_TIMELINE_PROFILING_ENABLED && defined(CONFIG_TRACEPOINTS*/ +#endif /* MALI_TIMELINE_PROFILING_ENABLED */ #endif /* __MALI_OSK_PROFILING_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_pp.c b/drivers/media/video/samsung/mali/common/mali_pp.c index b525063..5549f82 100644 --- a/drivers/media/video/samsung/mali/common/mali_pp.c +++ b/drivers/media/video/samsung/mali/common/mali_pp.c @@ -12,7 +12,6 @@ #include "mali_hw_core.h" #include "mali_group.h" #include "mali_osk.h" -#include "mali_pp_scheduler.h" #include "regs/mali_200_regs.h" #include "mali_kernel_common.h" #include "mali_kernel_core.h" @@ -195,55 +194,6 @@ _mali_osk_errcode_t mali_pp_stop_bus_wait(struct mali_pp_core *core) return _MALI_OSK_ERR_OK; } -/* Frame register reset values. - * Taken from the Mali400 TRM, 3.6. Pixel processor control register summary */ -static const u32 mali_frame_registers_reset_values[_MALI_PP_MAX_FRAME_REGISTERS] = -{ - 0x0, /* Renderer List Address Register */ - 0x0, /* Renderer State Word Base Address Register */ - 0x0, /* Renderer Vertex Base Register */ - 0x2, /* Feature Enable Register */ - 0x0, /* Z Clear Value Register */ - 0x0, /* Stencil Clear Value Register */ - 0x0, /* ABGR Clear Value 0 Register */ - 0x0, /* ABGR Clear Value 1 Register */ - 0x0, /* ABGR Clear Value 2 Register */ - 0x0, /* ABGR Clear Value 3 Register */ - 0x0, /* Bounding Box Left Right Register */ - 0x0, /* Bounding Box Bottom Register */ - 0x0, /* FS Stack Address Register */ - 0x0, /* FS Stack Size and Initial Value Register */ - 0x0, /* Reserved */ - 0x0, /* Reserved */ - 0x0, /* Origin Offset X Register */ - 0x0, /* Origin Offset Y Register */ - 0x75, /* Subpixel Specifier Register */ - 0x0, /* Tiebreak mode Register */ - 0x0, /* Polygon List Format Register */ - 0x0, /* Scaling Register */ - 0x0 /* Tilebuffer configuration Register */ -}; - -/* WBx register reset values */ -static const u32 mali_wb_registers_reset_values[_MALI_PP_MAX_WB_REGISTERS] = -{ - 0x0, /* WBx Source Select Register */ - 0x0, /* WBx Target Address Register */ - 0x0, /* WBx Target Pixel Format Register */ - 0x0, /* WBx Target AA Format Register */ - 0x0, /* WBx Target Layout */ - 0x0, /* WBx Target Scanline Length */ - 0x0, /* WBx Target Flags Register */ - 0x0, /* WBx MRT Enable Register */ - 0x0, /* WBx MRT Offset Register */ - 0x0, /* WBx Global Test Enable Register */ - 0x0, /* WBx Global Test Reference Value Register */ - 0x0 /* WBx Global Test Compare Function Register */ -}; - -/* Performance Counter 0 Enable Register reset value */ -static const u32 mali_perf_cnt_enable_reset_value = 0; - _mali_osk_errcode_t mali_pp_hard_reset(struct mali_pp_core *core) { /* Bus must be stopped before calling this function */ @@ -256,7 +206,7 @@ _mali_osk_errcode_t mali_pp_hard_reset(struct mali_pp_core *core) MALI_DEBUG_PRINT(2, ("Mali PP: Hard reset of core %s\n", core->hw_core.description)); MALI_ASSERT_GROUP_LOCKED(core->group); - mali_pp_post_process_job(core); /* @@@@ is there some cases where it is unsafe to post process the job here? */ + mali_pp_post_process_job(core); /* @@@@ is there some cases where it is unsafe to post process the job here? */ /* Set register to a bogus value. The register will be used to detect when reset is complete */ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_WRITE_BOUNDARY_LOW, reset_invalid_value); @@ -297,11 +247,10 @@ _mali_osk_errcode_t mali_pp_reset(struct mali_pp_core *core) MALI_DEBUG_PRINT(4, ("Mali PP: Reset of core %s\n", core->hw_core.description)); MALI_ASSERT_GROUP_LOCKED(core->group); - mali_pp_post_process_job(core); /* @@@@ is there some cases where it is unsafe to post process the job here? */ + mali_pp_post_process_job(core); /* @@@@ is there some cases where it is unsafe to post process the job here? */ mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, 0); /* disable the IRQs */ - #if defined(USING_MALI200) /* On Mali-200, stop the bus, then do a hard reset of the core */ @@ -370,10 +319,7 @@ void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 s MALI_DEBUG_ASSERT_POINTER(core); MALI_ASSERT_GROUP_LOCKED(core->group); - mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_FRAME, frame_registers, MALI200_NUM_REGS_FRAME, mali_frame_registers_reset_values); - - _mali_osk_mem_barrier(); - + mali_hw_core_register_write_array_relaxed(&core->hw_core, MALI200_REG_ADDR_FRAME, frame_registers, MALI200_NUM_REGS_FRAME); if (0 != sub_job) { /* @@ -382,34 +328,22 @@ void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 s * but we need to patch these for all other sub jobs */ mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_FRAME, mali_pp_job_get_addr_frame(job, sub_job)); - mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_STACK, mali_pp_job_get_addr_stack(job, sub_job), mali_frame_registers_reset_values[MALI200_REG_ADDR_STACK/4]); + mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_STACK, mali_pp_job_get_addr_stack(job, sub_job)); } if (wb0_registers[0]) /* M200_WB0_REG_SOURCE_SELECT register */ { - mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB0, wb0_registers, MALI200_NUM_REGS_WBx, mali_wb_registers_reset_values); - } - else - { - mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB0, 0, mali_wb_registers_reset_values[0] ); + mali_hw_core_register_write_array_relaxed(&core->hw_core, MALI200_REG_ADDR_WB0, wb0_registers, MALI200_NUM_REGS_WBx); } if (wb1_registers[0]) /* M200_WB1_REG_SOURCE_SELECT register */ { - mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB1, wb1_registers, MALI200_NUM_REGS_WBx, mali_wb_registers_reset_values); - } - else - { - mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB1, 0, mali_wb_registers_reset_values[0] ); + mali_hw_core_register_write_array_relaxed(&core->hw_core, MALI200_REG_ADDR_WB1, wb1_registers, MALI200_NUM_REGS_WBx); } if (wb2_registers[0]) /* M200_WB2_REG_SOURCE_SELECT register */ { - mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB2, wb2_registers, MALI200_NUM_REGS_WBx, mali_wb_registers_reset_values); - } - else - { - mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB2, 0, mali_wb_registers_reset_values[0] ); + mali_hw_core_register_write_array_relaxed(&core->hw_core, MALI200_REG_ADDR_WB2, wb2_registers, MALI200_NUM_REGS_WBx); } /* This selects which performance counters we are reading */ @@ -418,14 +352,13 @@ void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 s /* global_config has enabled HW counters, this will override anything specified by user space */ if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) { - mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); - mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value); - + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE); } if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) { - mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); - mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value); + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE); } } else @@ -437,15 +370,15 @@ void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 s if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE) { core->counter_src0_used = mali_pp_job_get_perf_counter_src0(job); - mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); - mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value); + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE); } if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE) { core->counter_src1_used = mali_pp_job_get_perf_counter_src1(job); - mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); - mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value); + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); + mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE); } } } @@ -466,8 +399,8 @@ void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 s core->timeout_job_id = mali_pp_job_get_id(job); #if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id) | MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH, mali_pp_job_get_frame_builder_id(job), mali_pp_job_get_flush_id(job), 0, 0, 0); - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id), mali_pp_job_get_pid(job), mali_pp_job_get_tid(job), 0, 0, 0); + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id) | MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH, job->frame_builder_id, job->flush_id, 0, 0, 0); + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id), job->pid, job->tid, 0, 0, 0); #endif core->running_job = job; @@ -565,7 +498,9 @@ static void mali_pp_bottom_half(void *data) u32 irq_errors; #if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0); +#if 0 /* Bottom half TLP logging is currently not supported */ + _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_START| MALI_PROFILING_EVENT_CHANNEL_SOFTWARE , _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0); +#endif #endif mali_group_lock(core->group); /* Group lock grabbed in core handlers, but released in common group handler */ @@ -574,9 +509,6 @@ static void mali_pp_bottom_half(void *data) { MALI_PRINT_ERROR(("Interrupt bottom half of %s when core is OFF.", core->hw_core.description)); mali_group_unlock(core->group); -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0); -#endif return; } @@ -589,9 +521,6 @@ static void mali_pp_bottom_half(void *data) mali_pp_post_process_job(core); MALI_DEBUG_PRINT(3, ("Mali PP: Job completed, calling group handler\n")); mali_group_bottom_half(core->group, GROUP_EVENT_PP_JOB_COMPLETED); /* Will release group lock */ -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0); -#endif return; } @@ -606,9 +535,6 @@ static void mali_pp_bottom_half(void *data) MALI_PRINT_ERROR(("Mali PP: Unknown interrupt 0x%08X from core %s, aborting job\n", irq_readout, core->hw_core.description)); mali_group_bottom_half(core->group, GROUP_EVENT_PP_JOB_FAILED); /* Will release group lock */ -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0); -#endif return; } else if (MALI_TRUE == core->core_timed_out) /* SW timeout */ @@ -625,9 +551,6 @@ static void mali_pp_bottom_half(void *data) mali_group_unlock(core->group); } core->core_timed_out = MALI_FALSE; -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0); -#endif return; } else if (irq_readout & MALI200_REG_VAL_IRQ_HANG) @@ -644,7 +567,9 @@ static void mali_pp_bottom_half(void *data) mali_group_unlock(core->group); #if MALI_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF, 0, _mali_osk_get_tid(), 0, 0, 0); +#if 0 /* Bottom half TLP logging is currently not supported */ + _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_STOP| MALI_PROFILING_EVENT_CHANNEL_SOFTWARE , _mali_osk_get_pid(), _mali_osk_get_tid(), 0, 0, 0); +#endif #endif } diff --git a/drivers/media/video/samsung/mali/common/mali_pp_job.c b/drivers/media/video/samsung/mali/common/mali_pp_job.c index 3c23637..47b8a0a 100644 --- a/drivers/media/video/samsung/mali/common/mali_pp_job.c +++ b/drivers/media/video/samsung/mali/common/mali_pp_job.c @@ -14,41 +14,65 @@ #include "mali_kernel_common.h" #include "mali_uk_types.h" -struct mali_pp_job *mali_pp_job_create(struct mali_session_data *session, _mali_uk_pp_start_job_s *uargs, u32 id) +struct mali_pp_job *mali_pp_job_create(struct mali_session_data *session, _mali_uk_pp_start_job_s *args, u32 id) { struct mali_pp_job *job; + if (args->num_cores > _MALI_PP_MAX_SUB_JOBS) + { + MALI_PRINT_ERROR(("Mali PP job: Too many sub jobs specified in job object\n")); + return NULL; + } + job = _mali_osk_malloc(sizeof(struct mali_pp_job)); if (NULL != job) { u32 i; + _mali_osk_list_init(&job->list); + job->session = session; + job->id = id; + job->user_id = args->user_job_ptr; + job->barrier = args->flags & _MALI_PP_JOB_FLAG_BARRIER ? MALI_TRUE : MALI_FALSE; + job->active_barrier = job->barrier; + job->no_notification = args->flags & _MALI_PP_JOB_FLAG_NO_NOTIFICATION ? MALI_TRUE : MALI_FALSE; + _mali_osk_memcpy(job->frame_registers, args->frame_registers, sizeof(job->frame_registers)); + _mali_osk_memcpy(job->frame_registers_addr_frame, args->frame_registers_addr_frame, sizeof(job->frame_registers_addr_frame)); + _mali_osk_memcpy(job->frame_registers_addr_stack, args->frame_registers_addr_stack, sizeof(job->frame_registers_addr_stack)); - if (0 != _mali_osk_copy_from_user(&job->uargs, uargs, sizeof(_mali_uk_pp_start_job_s))) + /* Only copy write back registers for the units that are enabled */ + job->wb0_registers[0] = 0; + job->wb1_registers[0] = 0; + job->wb2_registers[0] = 0; + if (args->wb0_registers[0]) /* M200_WB0_REG_SOURCE_SELECT register */ { - _mali_osk_free(job); - return NULL; + _mali_osk_memcpy(job->wb0_registers, args->wb0_registers, sizeof(job->wb0_registers)); } - - if (job->uargs.num_cores > _MALI_PP_MAX_SUB_JOBS) + if (args->wb1_registers[0]) /* M200_WB1_REG_SOURCE_SELECT register */ + { + _mali_osk_memcpy(job->wb1_registers, args->wb1_registers, sizeof(job->wb1_registers)); + } + if (args->wb2_registers[0]) /* M200_WB2_REG_SOURCE_SELECT register */ { - MALI_PRINT_ERROR(("Mali PP job: Too many sub jobs specified in job object\n")); - _mali_osk_free(job); - return NULL; + _mali_osk_memcpy(job->wb2_registers, args->wb2_registers, sizeof(job->wb2_registers)); } - _mali_osk_list_init(&job->list); - job->session = session; - job->id = id; - for (i = 0; i < job->uargs.num_cores; i++) + job->perf_counter_flag = args->perf_counter_flag; + job->perf_counter_src0 = args->perf_counter_src0; + job->perf_counter_src1 = args->perf_counter_src1; + for (i = 0; i < args->num_cores; i++) { job->perf_counter_value0[i] = 0; job->perf_counter_value1[i] = 0; } + job->sub_job_count = args->num_cores; job->sub_jobs_started = 0; job->sub_jobs_completed = 0; job->sub_job_errors = 0; + job->pid = _mali_osk_get_pid(); job->tid = _mali_osk_get_tid(); + job->frame_builder_id = args->frame_builder_id; + job->flush_id = args->flush_id; return job; } @@ -60,3 +84,12 @@ void mali_pp_job_delete(struct mali_pp_job *job) { _mali_osk_free(job); } + +_mali_osk_errcode_t mali_pp_job_check(struct mali_pp_job *job) +{ + if ((0 == job->frame_registers[0]) || (0 == job->frame_registers[1])) + { + return _MALI_OSK_ERR_FAULT; + } + return _MALI_OSK_ERR_OK; +} diff --git a/drivers/media/video/samsung/mali/common/mali_pp_job.h b/drivers/media/video/samsung/mali/common/mali_pp_job.h index 7e25504..4399c1d 100644 --- a/drivers/media/video/samsung/mali/common/mali_pp_job.h +++ b/drivers/media/video/samsung/mali/common/mali_pp_job.h @@ -27,28 +27,40 @@ struct mali_pp_job { _mali_osk_list_t list; /**< Used to link jobs together in the scheduler queue */ struct mali_session_data *session; /**< Session which submitted this job */ - _mali_uk_pp_start_job_s uargs; /**< Arguments from user space */ u32 id; /**< identifier for this job in kernel space (sequencial numbering) */ + u32 user_id; /**< identifier for the job in user space */ + u32 frame_registers[_MALI_PP_MAX_FRAME_REGISTERS]; /**< core specific registers associated with this job, see ARM DDI0415A */ + u32 frame_registers_addr_frame[_MALI_PP_MAX_SUB_JOBS - 1]; /**< ADDR_FRAME registers for sub job 1-7 */ + u32 frame_registers_addr_stack[_MALI_PP_MAX_SUB_JOBS - 1]; /**< ADDR_STACK registers for sub job 1-7 */ + u32 wb0_registers[_MALI_PP_MAX_WB_REGISTERS]; /**< Write back unit 0 registers */ + u32 wb1_registers[_MALI_PP_MAX_WB_REGISTERS]; /**< Write back unit 1 registers */ + u32 wb2_registers[_MALI_PP_MAX_WB_REGISTERS]; /**< Write back unit 2 registers */ + u32 perf_counter_flag; /**< bitmask indicating which performance counters to enable, see \ref _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE and related macro definitions */ + u32 perf_counter_src0; /**< Source id for performance counter 0 (see ARM DDI0415A, Table 3-60) */ + u32 perf_counter_src1; /**< Source id for performance counter 1 (see ARM DDI0415A, Table 3-60) */ u32 perf_counter_value0[_MALI_PP_MAX_SUB_JOBS]; /**< Value of performance counter 0 (to be returned to user space), one for each sub job */ - u32 perf_counter_value1[_MALI_PP_MAX_SUB_JOBS]; /**< Value of performance counter 1 (to be returned to user space), one for each sub job */ + u32 perf_counter_value1[_MALI_PP_MAX_SUB_JOBS]; /**< Value of performance counter 1 (to be returned to user space), one for each sub job */ + u32 sub_job_count; /**< Total number of sub-jobs in this superjob */ u32 sub_jobs_started; /**< Total number of sub-jobs started (always started in ascending order) */ u32 sub_jobs_completed; /**< Number of completed sub-jobs in this superjob */ u32 sub_job_errors; /**< Bitfield with errors (errors for each single sub-job is or'ed together) */ u32 pid; /**< Process ID of submitting process */ u32 tid; /**< Thread ID of submitting thread */ + u32 frame_builder_id; /**< id of the originating frame builder */ + u32 flush_id; /**< flush id within the originating frame builder */ + mali_bool barrier; /**< [in] MALI_TRUE means wait for all my previous jobs to complete before scheduling this one */ + mali_bool active_barrier; /**< [in] Changes from MALI_TRUE to MALI_FALSE when barrier has been resolved */ + mali_bool no_notification; /**< [in] MALI_TRUE means do not notify user space when this job has completed */ }; -struct mali_pp_job *mali_pp_job_create(struct mali_session_data *session, _mali_uk_pp_start_job_s *uargs, u32 id); +struct mali_pp_job *mali_pp_job_create(struct mali_session_data *session, _mali_uk_pp_start_job_s *args, u32 id); void mali_pp_job_delete(struct mali_pp_job *job); -MALI_STATIC_INLINE _mali_osk_errcode_t mali_pp_job_check(struct mali_pp_job *job) -{ - if ((0 == job->uargs.frame_registers[0]) || (0 == job->uargs.frame_registers[1])) - { - return _MALI_OSK_ERR_FAULT; - } - return _MALI_OSK_ERR_OK; -} +_mali_osk_errcode_t mali_pp_job_check(struct mali_pp_job *job); + +/****************************************************** + * simple utility functions for dealing with pp jobs: + *****************************************************/ MALI_STATIC_INLINE u32 mali_pp_job_get_id(struct mali_pp_job *job) { @@ -57,43 +69,33 @@ MALI_STATIC_INLINE u32 mali_pp_job_get_id(struct mali_pp_job *job) MALI_STATIC_INLINE u32 mali_pp_job_get_user_id(struct mali_pp_job *job) { - return job->uargs.user_job_ptr; + return job->user_id; } MALI_STATIC_INLINE u32 mali_pp_job_get_frame_builder_id(struct mali_pp_job *job) { - return job->uargs.frame_builder_id; + return job->frame_builder_id; } MALI_STATIC_INLINE u32 mali_pp_job_get_flush_id(struct mali_pp_job *job) { - return job->uargs.flush_id; -} - -MALI_STATIC_INLINE u32 mali_pp_job_get_pid(struct mali_pp_job *job) -{ - return job->pid; -} - -MALI_STATIC_INLINE u32 mali_pp_job_get_tid(struct mali_pp_job *job) -{ - return job->tid; + return job->flush_id; } MALI_STATIC_INLINE u32* mali_pp_job_get_frame_registers(struct mali_pp_job *job) { - return job->uargs.frame_registers; + return job->frame_registers; } MALI_STATIC_INLINE u32 mali_pp_job_get_addr_frame(struct mali_pp_job *job, u32 sub_job) { if (sub_job == 0) { - return job->uargs.frame_registers[MALI200_REG_ADDR_FRAME / sizeof(u32)]; + return job->frame_registers[MALI200_REG_ADDR_FRAME / sizeof(u32)]; } else if (sub_job < _MALI_PP_MAX_SUB_JOBS) { - return job->uargs.frame_registers_addr_frame[sub_job - 1]; + return job->frame_registers_addr_frame[sub_job - 1]; } return 0; @@ -103,11 +105,11 @@ MALI_STATIC_INLINE u32 mali_pp_job_get_addr_stack(struct mali_pp_job *job, u32 s { if (sub_job == 0) { - return job->uargs.frame_registers[MALI200_REG_ADDR_STACK / sizeof(u32)]; + return job->frame_registers[MALI200_REG_ADDR_STACK / sizeof(u32)]; } else if (sub_job < _MALI_PP_MAX_SUB_JOBS) { - return job->uargs.frame_registers_addr_stack[sub_job - 1]; + return job->frame_registers_addr_stack[sub_job - 1]; } return 0; @@ -115,32 +117,32 @@ MALI_STATIC_INLINE u32 mali_pp_job_get_addr_stack(struct mali_pp_job *job, u32 s MALI_STATIC_INLINE u32* mali_pp_job_get_wb0_registers(struct mali_pp_job *job) { - return job->uargs.wb0_registers; + return job->wb0_registers; } MALI_STATIC_INLINE u32* mali_pp_job_get_wb1_registers(struct mali_pp_job *job) { - return job->uargs.wb1_registers; + return job->wb1_registers; } MALI_STATIC_INLINE u32* mali_pp_job_get_wb2_registers(struct mali_pp_job *job) { - return job->uargs.wb2_registers; + return job->wb2_registers; } MALI_STATIC_INLINE void mali_pp_job_disable_wb0(struct mali_pp_job *job) { - job->uargs.wb0_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0; + job->wb0_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0; } MALI_STATIC_INLINE void mali_pp_job_disable_wb1(struct mali_pp_job *job) { - job->uargs.wb1_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0; + job->wb1_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0; } MALI_STATIC_INLINE void mali_pp_job_disable_wb2(struct mali_pp_job *job) { - job->uargs.wb2_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0; + job->wb2_registers[MALI200_REG_ADDR_WB_SOURCE_SELECT] = 0; } MALI_STATIC_INLINE struct mali_session_data *mali_pp_job_get_session(struct mali_pp_job *job) @@ -150,7 +152,7 @@ MALI_STATIC_INLINE struct mali_session_data *mali_pp_job_get_session(struct mali MALI_STATIC_INLINE mali_bool mali_pp_job_has_unstarted_sub_jobs(struct mali_pp_job *job) { - return (job->sub_jobs_started < job->uargs.num_cores) ? MALI_TRUE : MALI_FALSE; + return (job->sub_jobs_started < job->sub_job_count) ? MALI_TRUE : MALI_FALSE; } /* Function used when we are terminating a session with jobs. Return TRUE if it has a rendering job. @@ -158,7 +160,7 @@ MALI_STATIC_INLINE mali_bool mali_pp_job_has_unstarted_sub_jobs(struct mali_pp_j MALI_STATIC_INLINE mali_bool mali_pp_job_is_currently_rendering_and_if_so_abort_new_starts(struct mali_pp_job *job) { /* All can not be started, since then it would not be in the job queue */ - MALI_DEBUG_ASSERT( job->sub_jobs_started != job->uargs.num_cores ); + MALI_DEBUG_ASSERT( job->sub_jobs_started != job->sub_job_count ); /* If at least one job is started */ if ( (job->sub_jobs_started > 0) ) @@ -166,7 +168,7 @@ MALI_STATIC_INLINE mali_bool mali_pp_job_is_currently_rendering_and_if_so_abort_ /* If at least one job is currently being rendered, and thus assigned to a group and core */ if (job->sub_jobs_started > job->sub_jobs_completed ) { - u32 jobs_remaining = job->uargs.num_cores - job->sub_jobs_started; + u32 jobs_remaining = job->sub_job_count - job->sub_jobs_started; job->sub_jobs_started += jobs_remaining; job->sub_jobs_completed += jobs_remaining; job->sub_job_errors += jobs_remaining; @@ -180,7 +182,7 @@ MALI_STATIC_INLINE mali_bool mali_pp_job_is_currently_rendering_and_if_so_abort_ MALI_STATIC_INLINE mali_bool mali_pp_job_is_complete(struct mali_pp_job *job) { - return (job->uargs.num_cores == job->sub_jobs_completed) ? MALI_TRUE : MALI_FALSE; + return (job->sub_job_count == job->sub_jobs_completed) ? MALI_TRUE : MALI_FALSE; } MALI_STATIC_INLINE u32 mali_pp_job_get_first_unstarted_sub_job(struct mali_pp_job *job) @@ -190,7 +192,7 @@ MALI_STATIC_INLINE u32 mali_pp_job_get_first_unstarted_sub_job(struct mali_pp_jo MALI_STATIC_INLINE u32 mali_pp_job_get_sub_job_count(struct mali_pp_job *job) { - return job->uargs.num_cores; + return job->sub_job_count; } MALI_STATIC_INLINE void mali_pp_job_mark_sub_job_started(struct mali_pp_job *job, u32 sub_job) @@ -200,15 +202,6 @@ MALI_STATIC_INLINE void mali_pp_job_mark_sub_job_started(struct mali_pp_job *job job->sub_jobs_started++; } -MALI_STATIC_INLINE void mali_pp_job_mark_sub_job_not_stated(struct mali_pp_job *job, u32 sub_job) -{ - /* This is only safe on Mali-200. */ -#if !defined(USING_MALI200) - MALI_DEBUG_ASSERT(0); -#endif - job->sub_jobs_started--; -} - MALI_STATIC_INLINE void mali_pp_job_mark_sub_job_completed(struct mali_pp_job *job, mali_bool success) { job->sub_jobs_completed++; @@ -229,32 +222,32 @@ MALI_STATIC_INLINE mali_bool mali_pp_job_was_success(struct mali_pp_job *job) MALI_STATIC_INLINE mali_bool mali_pp_job_has_active_barrier(struct mali_pp_job *job) { - return job->uargs.flags & _MALI_PP_JOB_FLAG_BARRIER ? MALI_TRUE : MALI_FALSE; + return job->active_barrier; } MALI_STATIC_INLINE void mali_pp_job_barrier_enforced(struct mali_pp_job *job) { - job->uargs.flags &= ~_MALI_PP_JOB_FLAG_BARRIER; + job->active_barrier = MALI_FALSE; } MALI_STATIC_INLINE mali_bool mali_pp_job_use_no_notification(struct mali_pp_job *job) { - return job->uargs.flags & _MALI_PP_JOB_FLAG_NO_NOTIFICATION ? MALI_TRUE : MALI_FALSE; + return job->no_notification; } MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_flag(struct mali_pp_job *job) { - return job->uargs.perf_counter_flag; + return job->perf_counter_flag; } MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_src0(struct mali_pp_job *job) { - return job->uargs.perf_counter_src0; + return job->perf_counter_src0; } MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_src1(struct mali_pp_job *job) { - return job->uargs.perf_counter_src1; + return job->perf_counter_src1; } MALI_STATIC_INLINE u32 mali_pp_job_get_perf_counter_value0(struct mali_pp_job *job, u32 sub_job) diff --git a/drivers/media/video/samsung/mali/common/mali_pp_scheduler.c b/drivers/media/video/samsung/mali/common/mali_pp_scheduler.c index eedf661..a944055 100644 --- a/drivers/media/video/samsung/mali/common/mali_pp_scheduler.c +++ b/drivers/media/video/samsung/mali/common/mali_pp_scheduler.c @@ -17,8 +17,6 @@ #include "mali_pp_job.h" #include "mali_group.h" #include "mali_cluster.h" -#include "mali_osk_profiling.h" - /* Maximum of 8 PP cores (a group can only have maximum of 1 PP core) */ #define MALI_MAX_NUMBER_OF_PP_GROUPS 8 @@ -41,14 +39,10 @@ struct mali_pp_slot */ enum mali_pp_slot_state state; struct mali_session_data *session; - struct mali_pp_job *job; - u32 subjob; }; static u32 pp_version = 0; static _MALI_OSK_LIST_HEAD(job_queue); /* List of jobs with some unscheduled work */ -static u32 job_queue_depth; - static struct mali_pp_slot slots[MALI_MAX_NUMBER_OF_PP_GROUPS]; static u32 num_slots = 0; static u32 num_slots_idle = 0; @@ -67,7 +61,7 @@ _mali_osk_errcode_t mali_pp_scheduler_initialize(void) _MALI_OSK_INIT_LIST_HEAD(&job_queue); - pp_scheduler_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ |_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_SCHEDULER); + pp_scheduler_lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED |_MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_SCHEDULER); if (NULL == pp_scheduler_lock) { return _MALI_OSK_ERR_NOMEM; @@ -160,7 +154,7 @@ static mali_bool mali_pp_scheduler_session_has_running_jobs(struct mali_session_ for (i = 0; i < num_slots; i++) { if (MALI_PP_SLOT_STATE_WORKING == slots[i].state) - { + { if (slots[i].session == session) { return MALI_TRUE; @@ -171,123 +165,131 @@ static mali_bool mali_pp_scheduler_session_has_running_jobs(struct mali_session_ return MALI_FALSE; } -static mali_bool slots_available(void) -{ - return num_slots_idle > 0; -} - static void mali_pp_scheduler_schedule(void) { + u32 i; struct mali_pp_job *job; +#if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS + struct mali_session_data * session; +#endif + + MALI_ASSERT_PP_SCHEDULER_LOCKED(); - if (0 < pause_count || 0 == num_slots_idle || 0 == job_queue_depth) + if (0 < pause_count || 0 == num_slots_idle || _mali_osk_list_empty(&job_queue)) { MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Nothing to schedule (paused=%u, idle slots=%u)\n", pause_count, num_slots_idle)); return; /* Nothing to do, so early out */ } - while(slots_available() && 0 < job_queue_depth) + +#if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP + if ( num_slots_idle < num_slots ) + { + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Job not started, since only %d/%d cores are available\n", num_slots_idle,num_slots)); + return; + } +#endif + +#if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS + /* Finding initial session for the PP cores */ + job = _MALI_OSK_LIST_ENTRY(job_queue.next, struct mali_pp_job, list); + session = job->session; + if ( num_slots != num_slots_idle ) + { + for (i = 0; (i < num_slots) ; i++) + { + if ( slots[i].state == MALI_PP_SLOT_STATE_IDLE ) + { + continue; + } + session = mali_group_get_session(slots[i].group); + break; + } + } +#endif + + for (i = 0; (i < num_slots) && (0 < num_slots_idle); i++) { - u32 i, slot_count; - struct mali_pp_slot *reserved_slots[num_slots]; - struct mali_session_data *session; + u32 sub_job; - mali_pp_scheduler_lock(); - /* Get job */ - if (_mali_osk_list_empty(&job_queue) || !slots_available()) + if (_mali_osk_list_empty(&job_queue)) /* move this check down to where we know we have started all sub jobs for this job??? */ { - mali_pp_scheduler_unlock(); break; /* No more jobs to schedule, so early out */ } + + if (MALI_PP_SLOT_STATE_IDLE != slots[i].state) + { + continue; + } + job = _MALI_OSK_LIST_ENTRY(job_queue.next, struct mali_pp_job, list); MALI_DEBUG_ASSERT(mali_pp_job_has_unstarted_sub_jobs(job)); /* All jobs on the job_queue should have unstarted sub jobs */ - session = mali_pp_job_get_session(job); if (MALI_TRUE == mali_pp_job_has_active_barrier(job)) { if (MALI_TRUE == mali_pp_scheduler_session_has_running_jobs(mali_pp_job_get_session(job))) { - /* There is already a running job from this - * session, so we need to enforce the barrier */ - mali_pp_scheduler_unlock(); + /* There is already a running job from this session, so we need to enforce the barrier */ return; } else { - /* Barrier is now enforced, update job object - * so we don't delay execution of sub-jobs */ + /* Barrier is now enforced, update job object so we don't delay execution of sub-jobs */ mali_pp_job_barrier_enforced(job); } } - /* Reserve slots */ - for (i = 0, slot_count = 0; i < num_slots; i++) + #if MALI_PP_SCHEDULER_KEEP_SUB_JOB_STARTS_ALIGNED + if ( (0==job->sub_jobs_started) && (num_slots_idle < num_slots) && (job->sub_job_count > num_slots_idle)) { - struct mali_pp_slot *slot = &slots[i]; - - if (MALI_PP_SLOT_STATE_IDLE != slot->state) continue; - - slot->state = MALI_PP_SLOT_STATE_WORKING; - slot->session = session; - slot->job = job; - slot->subjob = mali_pp_job_get_first_unstarted_sub_job(job); - mali_pp_job_mark_sub_job_started(job, slot->subjob); - --job_queue_depth; - - --num_slots_idle; - reserved_slots[slot_count++] = slot; - - if (!mali_pp_job_has_unstarted_sub_jobs(job)) - { - _mali_osk_list_del(&job->list); - break; - } + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Job with %d subjobs not started, since only %d/%d cores are available\n", job->sub_job_count, num_slots_idle,num_slots)); + return; } + #endif - MALI_DEBUG_ASSERT(0 < slot_count); + #if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP_BETWEEN_APPS + if ( job->session != session ) + { + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Job not started since existing job is from another application\n")); + return; + } + #endif - mali_pp_scheduler_unlock(); + sub_job = mali_pp_job_get_first_unstarted_sub_job(job); - /* Start (sub)job(s) on core(s) */ - for(i = 0; i < slot_count; i++) + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Starting job %u (0x%08X) part %u/%u\n", mali_pp_job_get_id(job), job, sub_job + 1, mali_pp_job_get_sub_job_count(job))); + if (_MALI_OSK_ERR_OK == mali_group_start_pp_job(slots[i].group, job, sub_job)) { - struct mali_pp_slot *slot = reserved_slots[i]; - struct mali_pp_job *job; - u32 subjob; + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Job %u (0x%08X) part %u/%u started\n", mali_pp_job_get_id(job), job, sub_job + 1, mali_pp_job_get_sub_job_count(job))); - MALI_DEBUG_ASSERT_POINTER(slot); - MALI_DEBUG_ASSERT(MALI_PP_SLOT_STATE_WORKING == slot->state); - MALI_DEBUG_ASSERT_POINTER(slot->job); + /* Mark this sub job as started */ + mali_pp_job_mark_sub_job_started(job, sub_job); - job = slot->job; - subjob = slot->subjob; + /* Mark slot as busy */ + slots[i].state = MALI_PP_SLOT_STATE_WORKING; + slots[i].session = mali_pp_job_get_session(job); + num_slots_idle--; - if (_MALI_OSK_ERR_OK == mali_group_start_pp_job(slot->group, slot->job, slot->subjob)) - { - MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Job %u (0x%08X) part %u/%u started\n", - mali_pp_job_get_id(job), job, subjob + 1, - mali_pp_job_get_sub_job_count(job))); - } - else + if (!mali_pp_job_has_unstarted_sub_jobs(job)) { - MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Failed to start PP job\n")); - /* This can only happen on Mali-200 */ -#if !defined(USING_MALI200) - MALI_DEBUG_ASSERT(0); + /* + * All sub jobs have now started for this job, remove this job from the job queue. + * The job will now only be referred to by the slots which are running it. + * The last slot to complete will make sure it is returned to user space. + */ + _mali_osk_list_del(&job->list); +#if MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP + MALI_DEBUG_PRINT(6, ("Mali PP scheduler: Skip scheduling more jobs when MALI_PP_SCHEDULER_FORCE_NO_JOB_OVERLAP is set.\n")); + return; #endif - mali_pp_scheduler_lock(); - /* Put job back on queue */ - mali_pp_job_mark_sub_job_not_stated(job, subjob); - _mali_osk_list_add(&job->list, &job_queue); - /* Set slot idle */ - slot->state = MALI_PP_SLOT_STATE_IDLE; - slot->session = NULL; - slot->job = NULL; - slot->subjob = 0; - mali_pp_scheduler_unlock(); } } + else + { + MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Failed to start PP job\n")); + return; + } } } @@ -333,42 +335,35 @@ static void mali_pp_scheduler_return_job_to_user(struct mali_pp_job *job) void mali_pp_scheduler_do_schedule(void) { + mali_pp_scheduler_lock(); + mali_pp_scheduler_schedule(); + + mali_pp_scheduler_unlock(); } void mali_pp_scheduler_job_done(struct mali_group *group, struct mali_pp_job *job, u32 sub_job, mali_bool success) { u32 i; - struct mali_pp_slot *slot = NULL; mali_bool job_is_done; - MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Job %u (0x%08X) part %u/%u completed (%s)\n", - mali_pp_job_get_id(job), - job, sub_job + 1, - mali_pp_job_get_sub_job_count(job), - success ? "success" : "failure")); + MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Job %u (0x%08X) part %u/%u completed (%s)\n", mali_pp_job_get_id(job), job, sub_job + 1, mali_pp_job_get_sub_job_count(job), success ? "success" : "failure")); mali_pp_scheduler_lock(); - mali_pp_job_mark_sub_job_completed(job, success); - /* Find slot which was running this job */ for (i = 0; i < num_slots; i++) { - slot = &slots[i]; - if (slot->group == group) - break; + if (slots[i].group == group) + { + MALI_DEBUG_ASSERT(MALI_PP_SLOT_STATE_WORKING == slots[i].state); + slots[i].state = MALI_PP_SLOT_STATE_IDLE; + slots[i].session = NULL; + num_slots_idle++; + mali_pp_job_mark_sub_job_completed(job, success); + } } - MALI_DEBUG_ASSERT_POINTER(slot); - - slot->state = MALI_PP_SLOT_STATE_IDLE; - slot->session = NULL; - slot->job = NULL; - slot->subjob = 0; - - num_slots_idle++; - /* If paused, then this was the last job, so wake up sleeping workers */ if (pause_count > 0) { @@ -378,6 +373,10 @@ void mali_pp_scheduler_job_done(struct mali_group *group, struct mali_pp_job *jo */ _mali_osk_wait_queue_wake_up(pp_scheduler_working_wait_queue); } + else + { + mali_pp_scheduler_schedule(); + } job_is_done = mali_pp_job_is_complete(job); @@ -389,8 +388,6 @@ void mali_pp_scheduler_job_done(struct mali_group *group, struct mali_pp_job *jo MALI_DEBUG_PRINT(4, ("Mali PP scheduler: All parts completed for job %u (0x%08X)\n", mali_pp_job_get_id(job), job)); mali_pp_scheduler_return_job_to_user(job); } - - mali_pp_scheduler_schedule(); } void mali_pp_scheduler_suspend(void) @@ -399,7 +396,11 @@ void mali_pp_scheduler_suspend(void) pause_count++; /* Increment the pause_count so that no more jobs will be scheduled */ mali_pp_scheduler_unlock(); - /* Go to sleep. When woken up again (in mali_pp_scheduler_job_done), the + /*mali_pp_scheduler_working_lock();*/ + /* We have now aquired the working lock, which means that we have successfully paused the scheduler */ + /*mali_pp_scheduler_working_unlock();*/ + + /* go to sleep. When woken up again (in mali_pp_scheduler_job_done), the * mali_pp_scheduler_suspended() function will be called. This will return true * iff state is idle and pause_count > 0, so if the core is active this * will not do anything. @@ -418,17 +419,17 @@ void mali_pp_scheduler_resume(void) mali_pp_scheduler_unlock(); } -_mali_osk_errcode_t _mali_ukk_pp_start_job(void *ctx, _mali_uk_pp_start_job_s *uargs) +_mali_osk_errcode_t _mali_ukk_pp_start_job(_mali_uk_pp_start_job_s *args) { struct mali_session_data *session; struct mali_pp_job *job; - MALI_DEBUG_ASSERT_POINTER(uargs); - MALI_DEBUG_ASSERT_POINTER(ctx); + MALI_DEBUG_ASSERT_POINTER(args); + MALI_DEBUG_ASSERT_POINTER(args->ctx); - session = (struct mali_session_data*)ctx; + session = (struct mali_session_data*)args->ctx; - job = mali_pp_job_create(session, uargs, mali_scheduler_get_new_id()); + job = mali_pp_job_create(session, args, mali_scheduler_get_new_id()); if (NULL == job) { return _MALI_OSK_ERR_NOMEM; @@ -450,15 +451,13 @@ _mali_osk_errcode_t _mali_ukk_pp_start_job(void *ctx, _mali_uk_pp_start_job_s *u mali_pp_scheduler_lock(); - job_queue_depth += mali_pp_job_get_sub_job_count(job); _mali_osk_list_addtail(&job->list, &job_queue); - MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Job %u (0x%08X) with %u parts queued\n", - mali_pp_job_get_id(job), job, mali_pp_job_get_sub_job_count(job))); + MALI_DEBUG_PRINT(3, ("Mali PP scheduler: Job %u (0x%08X) with %u parts queued\n", mali_pp_job_get_id(job), job, mali_pp_job_get_sub_job_count(job))); - mali_pp_scheduler_unlock(); + mali_pp_scheduler_schedule(); - if (slots_available()) mali_pp_scheduler_schedule(); + mali_pp_scheduler_unlock(); return _MALI_OSK_ERR_OK; } @@ -490,8 +489,9 @@ void _mali_ukk_pp_job_disable_wb(_mali_uk_pp_disable_wb_s *args) session = (struct mali_session_data*)args->ctx; - /* Check queue for jobs that match */ mali_pp_scheduler_lock(); + + /* Check queue for jobs that match */ _MALI_OSK_LIST_FOREACHENTRY(job, tmp, &job_queue, struct mali_pp_job, list) { if (mali_pp_job_get_session(job) == session && @@ -513,6 +513,7 @@ void _mali_ukk_pp_job_disable_wb(_mali_uk_pp_disable_wb_s *args) break; } } + mali_pp_scheduler_unlock(); } @@ -530,7 +531,6 @@ void mali_pp_scheduler_abort_session(struct mali_session_data *session) if (mali_pp_job_get_session(job) == session) { _mali_osk_list_del(&(job->list)); - job_queue_depth -= mali_pp_job_get_sub_job_count(job) - mali_pp_job_get_first_unstarted_sub_job(job); if ( mali_pp_job_is_currently_rendering_and_if_so_abort_new_starts(job) ) { @@ -551,9 +551,14 @@ void mali_pp_scheduler_abort_session(struct mali_session_data *session) { struct mali_group *group = slots[i].group; - MALI_DEBUG_PRINT(5, ("PP sched abort: Attempting abort for session 0x%08x on group 0x%08x\n", session, group)); + MALI_DEBUG_PRINT(5, ("PP sched abort: Looking at group 0x%08x\n", group)); + + if (MALI_PP_SLOT_STATE_WORKING == slots[i].state) + { + MALI_DEBUG_PRINT(4, ("Mali PP scheduler: Aborting session 0x%08x from group 0x%08x\n", session, group)); - mali_group_abort_session(group, session); + mali_group_abort_session(group, session); + } } } @@ -568,11 +573,6 @@ static mali_bool mali_pp_scheduler_is_suspended(void) return ret; } -int mali_pp_scheduler_get_queue_depth(void) -{ - return job_queue_depth; -} - #if MALI_STATE_TRACKING u32 mali_pp_scheduler_dump_state(char *buf, u32 size) { diff --git a/drivers/media/video/samsung/mali/common/mali_pp_scheduler.h b/drivers/media/video/samsung/mali/common/mali_pp_scheduler.h index 59bf403..48eb3bd 100644 --- a/drivers/media/video/samsung/mali/common/mali_pp_scheduler.h +++ b/drivers/media/video/samsung/mali/common/mali_pp_scheduler.h @@ -33,7 +33,6 @@ void mali_pp_scheduler_resume(void); */ void mali_pp_scheduler_abort_session(struct mali_session_data *session); -int mali_pp_scheduler_get_queue_depth(void); u32 mali_pp_scheduler_dump_state(char *buf, u32 size); #endif /* __MALI_PP_SCHEDULER_H__ */ diff --git a/drivers/media/video/samsung/mali/common/mali_ukk.h b/drivers/media/video/samsung/mali/common/mali_ukk.h index 6d41b6e..6b018d0 100644 --- a/drivers/media/video/samsung/mali/common/mali_ukk.h +++ b/drivers/media/video/samsung/mali/common/mali_ukk.h @@ -449,11 +449,10 @@ _mali_osk_errcode_t _mali_ukk_va_to_mali_pa( _mali_uk_va_to_mali_pa_s * args ); * * Job completion can be awaited with _mali_ukk_wait_for_notification(). * - * @oaram ctx user-kernel context (mali_session) - * @param uargs see _mali_uk_pp_start_job_s in "mali_utgard_uk_types.h". Use _mali_osk_copy_from_user to retrieve data! + * @param args see _mali_uk_pp_start_job_s in "mali_utgard_uk_types.h" * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. */ -_mali_osk_errcode_t _mali_ukk_pp_start_job( void *ctx, _mali_uk_pp_start_job_s *uargs ); +_mali_osk_errcode_t _mali_ukk_pp_start_job( _mali_uk_pp_start_job_s *args ); /** @brief Returns the number of Fragment Processors in the system * @@ -503,11 +502,10 @@ void _mali_ukk_pp_job_disable_wb(_mali_uk_pp_disable_wb_s *args); * * Job completion can be awaited with _mali_ukk_wait_for_notification(). * - * @oaram ctx user-kernel context (mali_session) - * @param uargs see _mali_uk_gp_start_job_s in "mali_utgard_uk_types.h". Use _mali_osk_copy_from_user to retrieve data! + * @param args see _mali_uk_gp_start_job_s in "mali_utgard_uk_types.h" * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. */ -_mali_osk_errcode_t _mali_ukk_gp_start_job( void *ctx, _mali_uk_gp_start_job_s *uargs ); +_mali_osk_errcode_t _mali_ukk_gp_start_job( _mali_uk_gp_start_job_s *args ); /** @brief Returns the number of Vertex Processors in the system. * diff --git a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_profiling_events.h b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_profiling_events.h index 92ca058..b96596e 100644 --- a/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_profiling_events.h +++ b/drivers/media/video/samsung/mali/include/linux/mali/mali_utgard_profiling_events.h @@ -71,7 +71,6 @@ typedef enum MALI_PROFILING_EVENT_REASON_SINGLE_SW_UMP_TRY_LOCK = 53, MALI_PROFILING_EVENT_REASON_SINGLE_SW_UMP_LOCK = 54, MALI_PROFILING_EVENT_REASON_SINGLE_SW_UMP_UNLOCK = 55, - MALI_PROFILING_EVENT_REASON_SINGLE_LOCK_CONTENDED = 56, } cinstr_profiling_event_reason_single_sw_t; /** @@ -81,7 +80,6 @@ typedef enum { MALI_PROFILING_EVENT_REASON_START_STOP_SW_NONE = 0, MALI_PROFILING_EVENT_REASON_START_STOP_MALI = 1, - MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF = 2, } cinstr_profiling_event_reason_start_stop_sw_t; /** @@ -126,26 +124,4 @@ typedef enum MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE = 1, } cinstr_profiling_event_reason_single_gpu_t; -/** - * These values are applicable for the 3rd data parameter when - * the type MALI_PROFILING_EVENT_TYPE_START is used from the software channel - * with the MALI_PROFILING_EVENT_REASON_START_STOP_BOTTOM_HALF reason. - */ -typedef enum -{ - MALI_PROFILING_EVENT_DATA_CORE_GP0 = 1, - MALI_PROFILING_EVENT_DATA_CORE_PP0 = 5, - MALI_PROFILING_EVENT_DATA_CORE_PP1 = 6, - MALI_PROFILING_EVENT_DATA_CORE_PP2 = 7, - MALI_PROFILING_EVENT_DATA_CORE_PP3 = 8, - MALI_PROFILING_EVENT_DATA_CORE_PP4 = 9, - MALI_PROFILING_EVENT_DATA_CORE_PP5 = 10, - MALI_PROFILING_EVENT_DATA_CORE_PP6 = 11, - MALI_PROFILING_EVENT_DATA_CORE_PP7 = 12, -} cinstr_profiling_event_data_core_t; - -#define MALI_PROFILING_MAKE_EVENT_DATA_CORE_GP(num) (MALI_PROFILING_EVENT_DATA_CORE_GP0 + (num)) -#define MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(num) (MALI_PROFILING_EVENT_DATA_CORE_PP0 + (num)) - - #endif /*_MALI_UTGARD_PROFILING_EVENTS_H_*/ diff --git a/drivers/media/video/samsung/mali/linux/mali_kernel_linux.c b/drivers/media/video/samsung/mali/linux/mali_kernel_linux.c index 8367515..233c0ca 100644 --- a/drivers/media/video/samsung/mali/linux/mali_kernel_linux.c +++ b/drivers/media/video/samsung/mali/linux/mali_kernel_linux.c @@ -29,9 +29,6 @@ #include "mali_platform.h" #include "mali_kernel_license.h" #include "mali_dma_buf.h" -#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED -#include "mali_profiling_internal.h" -#endif /* Streamline support for the Mali driver */ #if defined(CONFIG_TRACEPOINTS) && MALI_TIMELINE_PROFILING_ENABLED @@ -54,10 +51,17 @@ module_param(mali_debug_level, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IR MODULE_PARM_DESC(mali_debug_level, "Higher number, more dmesg output"); /* By default the module uses any available major, but it's possible to set it at load time to a specific number */ +#if MALI_MAJOR_PREDEFINE +int mali_major = 244; +#else int mali_major = 0; +#endif module_param(mali_major, int, S_IRUGO); /* r--r--r-- */ MODULE_PARM_DESC(mali_major, "Device major number"); +module_param(mali_hang_check_interval, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(mali_hang_check_interval, "Interval at which to check for progress after the hw watchdog has been triggered"); + module_param(mali_max_job_runtime, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH); MODULE_PARM_DESC(mali_max_job_runtime, "Maximum allowed job runtime in msecs.\nJobs will be killed after this no matter what"); @@ -75,6 +79,92 @@ MODULE_PARM_DESC(mali_boot_profiling, "Start profiling as a part of Mali driver #include "mali_user_settings_db.h" EXPORT_SYMBOL(mali_set_user_setting); EXPORT_SYMBOL(mali_get_user_setting); +#if MALI_DVFS_ENABLED +extern int mali_dvfs_control; +module_param(mali_dvfs_control, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(mali_dvfs_control, "Mali Current DVFS"); +#if defined(CONFIG_CPU_EXYNOS4210) +#else +extern int step0_clk; +module_param(step0_clk, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step0_clk, "Mali Current step0_clk"); +#ifdef DEBUG +extern int step0_vol; +module_param(step0_vol, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step0_vol, "Mali Current step0_vol"); +#endif + +#if (MALI_DVFS_STEPS > 1) +extern int step1_clk; +module_param(step1_clk, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step1_clk, "Mali Current step1_clk"); + +extern int step0_up; +module_param(step0_up, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step0_up, "Mali Current step0_up"); + +extern int step1_down; +module_param(step1_down, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step1_down, "Mali Current step1_down"); +#ifdef DEBUG +extern int step1_vol; +module_param(step1_vol, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step1_vol, "Mali Current step1_vol"); +#endif + +#if (MALI_DVFS_STEPS > 2) +extern int step2_clk; +module_param(step2_clk, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step2_clk, "Mali Current step2_clk"); + +extern int step1_up; +module_param(step1_up, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step1_up, "Mali Current step1_up"); + +extern int step2_down; +module_param(step2_down, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step2_down, "Mali Current step2_down"); +#ifdef DEBUG +extern int step2_vol; +module_param(step2_vol, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step2_vol, "Mali Current step2_vol"); +#endif + +#if (MALI_DVFS_STEPS > 3) +extern int step3_clk; +module_param(step3_clk, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step3_clk, "Mali Current step3_clk"); + +extern int step2_up; +module_param(step2_up, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step2_up, "Mali Current step2_up"); + +extern int step3_down; +module_param(step3_down, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step3_down, "Mali Current step3_down"); +#ifdef DEBUG +extern int step3_vol; +module_param(step3_vol, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH); /* rw-rw-r-- */ +MODULE_PARM_DESC(step3_vol, "Mali Current step3_vol"); +#endif +#endif +#endif +#endif +#endif + +extern int mali_gpu_clk; +module_param(mali_gpu_clk, int, S_IRUSR | S_IRGRP | S_IROTH); /* r--r--r-- */ +MODULE_PARM_DESC(mali_gpu_clk, "Mali Current Clock"); + +extern int mali_gpu_vol; +module_param(mali_gpu_vol, int, S_IRUSR | S_IRGRP | S_IROTH); /* r--r--r-- */ +MODULE_PARM_DESC(mali_gpu_vol, "Mali Current Voltage"); + +extern int gpu_power_state; +module_param(gpu_power_state, int, S_IRUSR | S_IRGRP | S_IROTH); /* r--r--r-- */ +MODULE_PARM_DESC(gpu_power_state, "Mali Power State"); +#endif + static char mali_dev_name[] = "mali"; /* should be const, but the functions we call requires non-cost */ @@ -129,15 +219,6 @@ int mali_driver_init(void) ret = map_errcode(mali_initialize_subsystems()); if (0 != ret) goto initialize_subsystems_failed; -#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED - ret = _mali_internal_profiling_init(mali_boot_profiling ? MALI_TRUE : MALI_FALSE); - if (0 != ret) - { - /* No biggie if we wheren't able to initialize the profiling */ - MALI_PRINT_ERROR(("Failed to initialize profiling, feature will be unavailable\n")); - } -#endif - ret = initialize_sysfs(); if (0 != ret) goto initialize_sysfs_failed; @@ -147,9 +228,6 @@ int mali_driver_init(void) /* Error handling */ initialize_sysfs_failed: -#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED - _mali_internal_profiling_term(); -#endif mali_terminate_subsystems(); initialize_subsystems_failed: mali_osk_low_level_mem_term(); @@ -169,10 +247,6 @@ void mali_driver_exit(void) /* No need to terminate sysfs, this will be done automatically along with device termination */ -#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED - _mali_internal_profiling_term(); -#endif - mali_terminate_subsystems(); mali_osk_low_level_mem_term(); diff --git a/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.c b/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.c index 77ebc9d..e2dc17b 100644 --- a/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.c +++ b/drivers/media/video/samsung/mali/linux/mali_kernel_sysfs.c @@ -44,7 +44,6 @@ #include "mali_kernel_core.h" #include "mali_user_settings_db.h" #include "mali_device_pause_resume.h" -#include "mali_profiling_internal.h" #define POWER_BUFFER_SIZE 3 @@ -70,7 +69,6 @@ static const char* const mali_power_events[_MALI_MAX_EVENTS] = { static u32 virtual_power_status_register=0; static char pwr_buf[POWER_BUFFER_SIZE]; - static int open_copy_private_data(struct inode *inode, struct file *filp) { filp->private_data = inode->i_private; @@ -792,7 +790,7 @@ static ssize_t profiling_record_read(struct file *filp, char __user *ubuf, size_ char buf[64]; int r; - r = sprintf(buf, "%u\n", _mali_internal_profiling_is_recording() ? 1 : 0); + r = sprintf(buf, "%u\n", _mali_osk_profiling_is_recording() ? 1 : 0); return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); } @@ -825,16 +823,16 @@ static ssize_t profiling_record_write(struct file *filp, const char __user *ubuf u32 limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; /* This can be made configurable at a later stage if we need to */ /* check if we are already recording */ - if (MALI_TRUE == _mali_internal_profiling_is_recording()) + if (MALI_TRUE == _mali_osk_profiling_is_recording()) { MALI_DEBUG_PRINT(3, ("Recording of profiling events already in progress\n")); return -EFAULT; } /* check if we need to clear out an old recording first */ - if (MALI_TRUE == _mali_internal_profiling_have_recording()) + if (MALI_TRUE == _mali_osk_profiling_have_recording()) { - if (_MALI_OSK_ERR_OK != _mali_internal_profiling_clear()) + if (_MALI_OSK_ERR_OK != _mali_osk_profiling_clear()) { MALI_DEBUG_PRINT(3, ("Failed to clear existing recording of profiling events\n")); return -EFAULT; @@ -842,7 +840,7 @@ static ssize_t profiling_record_write(struct file *filp, const char __user *ubuf } /* start recording profiling data */ - if (_MALI_OSK_ERR_OK != _mali_internal_profiling_start(&limit)) + if (_MALI_OSK_ERR_OK != _mali_osk_profiling_start(&limit)) { MALI_DEBUG_PRINT(3, ("Failed to start recording of profiling events\n")); return -EFAULT; @@ -854,7 +852,7 @@ static ssize_t profiling_record_write(struct file *filp, const char __user *ubuf { /* stop recording profiling data */ u32 count = 0; - if (_MALI_OSK_ERR_OK != _mali_internal_profiling_stop(&count)) + if (_MALI_OSK_ERR_OK != _mali_osk_profiling_stop(&count)) { MALI_DEBUG_PRINT(2, ("Failed to stop recording of profiling events\n")); return -EFAULT; @@ -878,7 +876,7 @@ static void *profiling_events_start(struct seq_file *s, loff_t *pos) loff_t *spos; /* check if we have data avaiable */ - if (MALI_TRUE != _mali_internal_profiling_have_recording()) + if (MALI_TRUE != _mali_osk_profiling_have_recording()) { return NULL; } @@ -898,13 +896,13 @@ static void *profiling_events_next(struct seq_file *s, void *v, loff_t *pos) loff_t *spos = v; /* check if we have data avaiable */ - if (MALI_TRUE != _mali_internal_profiling_have_recording()) + if (MALI_TRUE != _mali_osk_profiling_have_recording()) { return NULL; } /* check if the next entry actually is avaiable */ - if (_mali_internal_profiling_get_count() <= (u32)(*spos + 1)) + if (_mali_osk_profiling_get_count() <= (u32)(*spos + 1)) { return NULL; } @@ -929,7 +927,7 @@ static int profiling_events_show(struct seq_file *seq_file, void *v) index = (u32)*spos; /* Retrieve all events */ - if (_MALI_OSK_ERR_OK == _mali_internal_profiling_get_event(index, ×tamp, &event_id, data)) + if (_MALI_OSK_ERR_OK == _mali_osk_profiling_get_event(index, ×tamp, &event_id, data)) { seq_printf(seq_file, "%llu %u %u %u %u %u %u\n", timestamp, event_id, data[0], data[1], data[2], data[3], data[4]); return 0; diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_locks.c b/drivers/media/video/samsung/mali/linux/mali_osk_locks.c index d007d93..ee857d5 100644 --- a/drivers/media/video/samsung/mali/linux/mali_osk_locks.c +++ b/drivers/media/video/samsung/mali/linux/mali_osk_locks.c @@ -13,12 +13,19 @@ * Implemenation of the OS abstraction layer for the kernel device driver */ +/* needed to detect kernel version specific code */ +#include + #include #include -#include -#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +#include +#else /* pre 2.6.26 the file was in the arch specific location */ +#include +#endif +#include #include "mali_osk.h" #include "mali_kernel_common.h" @@ -27,9 +34,9 @@ typedef enum { _MALI_OSK_INTERNAL_LOCKTYPE_SPIN, /* Mutex, implicitly non-interruptable, use spin_lock/spin_unlock */ _MALI_OSK_INTERNAL_LOCKTYPE_SPIN_IRQ, /* Mutex, IRQ version of spinlock, use spin_lock_irqsave/spin_unlock_irqrestore */ - _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX, /* Interruptable, use mutex_unlock()/down_interruptable() */ - _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT, /* Non-Interruptable, use mutex_unlock()/down() */ - _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT_RW, /* Non-interruptable, Reader/Writer, use {mutex_unlock,down}{read,write}() */ + _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX, /* Interruptable, use up()/down_interruptable() */ + _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT, /* Non-Interruptable, use up()/down() */ + _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT_RW, /* Non-interruptable, Reader/Writer, use {up,down}{read,write}() */ /* Linux supports, but we do not support: * Non-Interruptable Reader/Writer spinlock mutexes - RW optimization will be switched off @@ -48,7 +55,7 @@ struct _mali_osk_lock_t_struct union { spinlock_t spinlock; - struct mutex mutex; + struct semaphore sema; struct rw_semaphore rw_sema; } obj; MALI_DEBUG_CODE( @@ -125,7 +132,7 @@ _mali_osk_lock_t *_mali_osk_lock_init( _mali_osk_lock_flags_t flags, u32 initial } /* Initially unlocked */ - mutex_init(&lock->obj.mutex); + sema_init( &lock->obj.sema, 1 ); } #ifdef DEBUG @@ -187,7 +194,7 @@ _mali_osk_errcode_t _mali_osk_lock_wait( _mali_osk_lock_t *lock, _mali_osk_lock_ break; case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX: - if (mutex_lock_interruptible(&lock->obj.mutex)) + if ( down_interruptible(&lock->obj.sema) ) { MALI_PRINT_ERROR(("Can not lock mutex\n")); err = _MALI_OSK_ERR_RESTARTSYSCALL; @@ -195,7 +202,7 @@ _mali_osk_errcode_t _mali_osk_lock_wait( _mali_osk_lock_t *lock, _mali_osk_lock_ break; case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT: - mutex_lock(&lock->obj.mutex); + down(&lock->obj.sema); break; case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT_RW: @@ -301,7 +308,7 @@ void _mali_osk_lock_signal( _mali_osk_lock_t *lock, _mali_osk_lock_mode_t mode ) case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX: /* FALLTHROUGH */ case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT: - mutex_unlock(&lock->obj.mutex); + up(&lock->obj.sema); break; case _MALI_OSK_INTERNAL_LOCKTYPE_MUTEX_NONINT_RW: diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_mali.c b/drivers/media/video/samsung/mali/linux/mali_osk_mali.c index 8dc90fd..06cb215 100644 --- a/drivers/media/video/samsung/mali/linux/mali_osk_mali.c +++ b/drivers/media/video/samsung/mali/linux/mali_osk_mali.c @@ -14,11 +14,11 @@ */ #include #include +#include #include "mali_kernel_common.h" /* MALI_xxx macros */ #include "mali_osk.h" /* kernel side OS functions */ #include "mali_uk_types.h" -#include #include "arch/config.h" /* contains the configuration of the arch we are compiling for */ _mali_osk_errcode_t _mali_osk_resources_init( _mali_osk_resource_t **arch_config, u32 *num_resources ) diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_notification.c b/drivers/media/video/samsung/mali/linux/mali_osk_notification.c index 2cfb5ef..c14c0d5 100644 --- a/drivers/media/video/samsung/mali/linux/mali_osk_notification.c +++ b/drivers/media/video/samsung/mali/linux/mali_osk_notification.c @@ -21,7 +21,11 @@ #include #include -#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +#include +#else /* pre 2.6.26 the file was in the arch specific location */ +#include +#endif /** * Declaration of the notification queue object type @@ -31,7 +35,7 @@ */ struct _mali_osk_notification_queue_t_struct { - spinlock_t mutex; /**< Mutex protecting the list */ + struct semaphore mutex; /**< Mutex protecting the list */ wait_queue_head_t receive_queue; /**< Threads waiting for new entries to the queue */ struct list_head head; /**< List of notifications waiting to be picked up */ }; @@ -49,7 +53,7 @@ _mali_osk_notification_queue_t *_mali_osk_notification_queue_init( void ) result = (_mali_osk_notification_queue_t *)kmalloc(sizeof(_mali_osk_notification_queue_t), GFP_KERNEL); if (NULL == result) return NULL; - spin_lock_init(&result->mutex); + sema_init(&result->mutex, 1); init_waitqueue_head(&result->receive_queue); INIT_LIST_HEAD(&result->head); @@ -117,22 +121,39 @@ void _mali_osk_notification_queue_send( _mali_osk_notification_queue_t *queue, _ notification = container_of( object, _mali_osk_notification_wrapper_t, data ); /* lock queue access */ - spin_lock(&queue->mutex); + down(&queue->mutex); /* add to list */ list_add_tail(¬ification->list, &queue->head); /* unlock the queue */ - spin_unlock(&queue->mutex); + up(&queue->mutex); /* and wake up one possible exclusive waiter */ wake_up(&queue->receive_queue); } +static int _mali_notification_queue_is_empty( _mali_osk_notification_queue_t *queue ) +{ + int ret; + + down(&queue->mutex); + ret = list_empty(&queue->head); + up(&queue->mutex); + return ret; +} + +#if MALI_STATE_TRACKING +mali_bool _mali_osk_notification_queue_is_empty( _mali_osk_notification_queue_t *queue ) +{ + return _mali_notification_queue_is_empty(queue) ? MALI_TRUE : MALI_FALSE; +} +#endif + _mali_osk_errcode_t _mali_osk_notification_queue_dequeue( _mali_osk_notification_queue_t *queue, _mali_osk_notification_t **result ) { _mali_osk_errcode_t ret = _MALI_OSK_ERR_ITEM_NOT_FOUND; _mali_osk_notification_wrapper_t *wrapper_object; - spin_lock(&queue->mutex); + down(&queue->mutex); if (!list_empty(&queue->head)) { @@ -142,7 +163,7 @@ _mali_osk_errcode_t _mali_osk_notification_queue_dequeue( _mali_osk_notification ret = _MALI_OSK_ERR_OK; } - spin_unlock(&queue->mutex); + up(&queue->mutex); return ret; } @@ -156,10 +177,12 @@ _mali_osk_errcode_t _mali_osk_notification_queue_receive( _mali_osk_notification /* default result */ *result = NULL; - if (wait_event_interruptible(queue->receive_queue, - _MALI_OSK_ERR_OK == _mali_osk_notification_queue_dequeue(queue, result))) + while (_MALI_OSK_ERR_OK != _mali_osk_notification_queue_dequeue(queue, result)) { - return _MALI_OSK_ERR_RESTARTSYSCALL; + if (wait_event_interruptible(queue->receive_queue, !_mali_notification_queue_is_empty(queue))) + { + return _MALI_OSK_ERR_RESTARTSYSCALL; + } } return _MALI_OSK_ERR_OK; /* all ok */ diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_profiling.c b/drivers/media/video/samsung/mali/linux/mali_osk_profiling.c deleted file mode 100644 index 95bee53..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_osk_profiling.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright (C) 2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include - -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_ukk.h" -#include "mali_uk_types.h" -#include "mali_osk_profiling.h" -#include "mali_linux_trace.h" -#include "mali_gp.h" -#include "mali_pp.h" -#include "mali_l2_cache.h" -#include "mali_user_settings_db.h" - -_mali_osk_errcode_t _mali_osk_profiling_init(mali_bool auto_start) -{ - if (MALI_TRUE == auto_start) - { - mali_set_user_setting(_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, MALI_TRUE); - } - - return _MALI_OSK_ERR_OK; -} - -void _mali_osk_profiling_term(void) -{ - /* Nothing to do */ -} - -_mali_osk_errcode_t _mali_osk_profiling_start(u32 * limit) -{ - /* Nothing to do */ - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t _mali_osk_profiling_stop(u32 *count) -{ - /* Nothing to do */ - return _MALI_OSK_ERR_OK; -} - -u32 _mali_osk_profiling_get_count(void) -{ - return 0; -} - -_mali_osk_errcode_t _mali_osk_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5]) -{ - /* Nothing to do */ - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t _mali_osk_profiling_clear(void) -{ - /* Nothing to do */ - return _MALI_OSK_ERR_OK; -} - -mali_bool _mali_osk_profiling_is_recording(void) -{ - return MALI_FALSE; -} - -mali_bool _mali_osk_profiling_have_recording(void) -{ - return MALI_FALSE; -} - -void _mali_osk_profiling_report_sw_counters(u32 *counters) -{ - trace_mali_sw_counters(_mali_osk_get_pid(), _mali_osk_get_tid(), NULL, counters); -} - - -_mali_osk_errcode_t _mali_ukk_profiling_start(_mali_uk_profiling_start_s *args) -{ - return _mali_osk_profiling_start(&args->limit); -} - -_mali_osk_errcode_t _mali_ukk_profiling_add_event(_mali_uk_profiling_add_event_s *args) -{ - /* Always add process and thread identificator in the first two data elements for events from user space */ - _mali_osk_profiling_add_event(args->event_id, _mali_osk_get_pid(), _mali_osk_get_tid(), args->data[2], args->data[3], args->data[4]); - - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t _mali_ukk_profiling_stop(_mali_uk_profiling_stop_s *args) -{ - return _mali_osk_profiling_stop(&args->count); -} - -_mali_osk_errcode_t _mali_ukk_profiling_get_event(_mali_uk_profiling_get_event_s *args) -{ - return _mali_osk_profiling_get_event(args->index, &args->timestamp, &args->event_id, args->data); -} - -_mali_osk_errcode_t _mali_ukk_profiling_clear(_mali_uk_profiling_clear_s *args) -{ - return _mali_osk_profiling_clear(); -} - -_mali_osk_errcode_t _mali_ukk_sw_counters_report(_mali_uk_sw_counters_report_s *args) -{ - _mali_osk_profiling_report_sw_counters(args->counters); - return _MALI_OSK_ERR_OK; -} - -/** - * Called by gator.ko to set HW counters - * - * @param counter_id The counter ID. - * @param event_id Event ID that the counter should count (HW counter value from TRM). - * - * @return 1 on success, 0 on failure. - */ -int _mali_profiling_set_event(u32 counter_id, s32 event_id) -{ - - if (COUNTER_VP_C0 == counter_id) - { - struct mali_gp_core* gp_core = mali_gp_get_global_gp_core(); - if (NULL != gp_core) - { - if (MALI_TRUE == mali_gp_core_set_counter_src0(gp_core, event_id)) - { - return 1; - } - } - } - if (COUNTER_VP_C1 == counter_id) - { - struct mali_gp_core* gp_core = mali_gp_get_global_gp_core(); - if (NULL != gp_core) - { - if (MALI_TRUE == mali_gp_core_set_counter_src1(gp_core, event_id)) - { - return 1; - } - } - } - if (COUNTER_FP0_C0 <= counter_id && COUNTER_FP3_C1 >= counter_id) - { - u32 core_id = (counter_id - COUNTER_FP0_C0) >> 1; - struct mali_pp_core* pp_core = mali_pp_get_global_pp_core(core_id); - if (NULL != pp_core) - { - u32 counter_src = (counter_id - COUNTER_FP0_C0) & 1; - if (0 == counter_src) - { - if (MALI_TRUE == mali_pp_core_set_counter_src0(pp_core, event_id)) - { - return 1; - } - } - else - { - if (MALI_TRUE == mali_pp_core_set_counter_src1(pp_core, event_id)) - { - return 1; - } - } - } - } - if (COUNTER_L2_C0 <= counter_id && COUNTER_L2_C1 >= counter_id) - { - u32 core_id = (counter_id - COUNTER_L2_C0) >> 1; - struct mali_l2_cache_core* l2_cache_core = mali_l2_cache_core_get_glob_l2_core(core_id); - if (NULL != l2_cache_core) - { - u32 counter_src = (counter_id - COUNTER_L2_C0) & 1; - if (0 == counter_src) - { - if (MALI_TRUE == mali_l2_cache_core_set_counter_src0(l2_cache_core, event_id)) - { - return 1; - } - } - else - { - if (MALI_TRUE == mali_l2_cache_core_set_counter_src1(l2_cache_core, event_id)) - { - return 1; - } - } - } - } - - return 0; -} - -/** - * Called by gator.ko to retrieve the L2 cache counter values for the first L2 cache. - * The L2 cache counters are unique in that they are polled by gator, rather than being - * transmitted via the tracepoint mechanism. - * - * @param src0 First L2 cache counter ID. - * @param val0 First L2 cache counter value. - * @param src1 Second L2 cache counter ID. - * @param val1 Second L2 cache counter value. - */ -void _mali_profiling_get_counters(u32 *src0, u32 *val0, u32 *src1, u32 *val1) -{ - struct mali_l2_cache_core *l2_cache = mali_l2_cache_core_get_glob_l2_core(0); - if (NULL != l2_cache) - { - if (MALI_TRUE == mali_l2_cache_lock_power_state(l2_cache)) - { - /* It is now safe to access the L2 cache core in order to retrieve the counters */ - mali_l2_cache_core_get_counter_values(l2_cache, src0, val0, src1, val1); - } - mali_l2_cache_unlock_power_state(l2_cache); - } -} - -/* - * List of possible actions to be controlled by Streamline. - * The following numbers are used by gator to control the frame buffer dumping and s/w counter reporting. - * We cannot use the enums in mali_uk_types.h because they are unknown inside gator. - */ -#define FBDUMP_CONTROL_ENABLE (1) -#define FBDUMP_CONTROL_RATE (2) -#define SW_COUNTER_ENABLE (3) -#define FBDUMP_CONTROL_RESIZE_FACTOR (4) - -/** - * Called by gator to control the production of profiling information at runtime. - */ -void _mali_profiling_control(u32 action, u32 value) -{ - switch(action) - { - case FBDUMP_CONTROL_ENABLE: - mali_set_user_setting(_MALI_UK_USER_SETTING_COLORBUFFER_CAPTURE_ENABLED, (value == 0 ? MALI_FALSE : MALI_TRUE)); - break; - case FBDUMP_CONTROL_RATE: - mali_set_user_setting(_MALI_UK_USER_SETTING_BUFFER_CAPTURE_N_FRAMES, value); - break; - case SW_COUNTER_ENABLE: - mali_set_user_setting(_MALI_UK_USER_SETTING_SW_COUNTER_ENABLED, value); - break; - case FBDUMP_CONTROL_RESIZE_FACTOR: - mali_set_user_setting(_MALI_UK_USER_SETTING_BUFFER_CAPTURE_RESIZE_FACTOR, value); - break; - default: - break; /* Ignore unimplemented actions */ - } -} - -EXPORT_SYMBOL(_mali_profiling_set_event); -EXPORT_SYMBOL(_mali_profiling_get_counters); -EXPORT_SYMBOL(_mali_profiling_control); diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_profiling_gator.c b/drivers/media/video/samsung/mali/linux/mali_osk_profiling_gator.c new file mode 100644 index 0000000..95bee53 --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_osk_profiling_gator.c @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_ukk.h" +#include "mali_uk_types.h" +#include "mali_osk_profiling.h" +#include "mali_linux_trace.h" +#include "mali_gp.h" +#include "mali_pp.h" +#include "mali_l2_cache.h" +#include "mali_user_settings_db.h" + +_mali_osk_errcode_t _mali_osk_profiling_init(mali_bool auto_start) +{ + if (MALI_TRUE == auto_start) + { + mali_set_user_setting(_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, MALI_TRUE); + } + + return _MALI_OSK_ERR_OK; +} + +void _mali_osk_profiling_term(void) +{ + /* Nothing to do */ +} + +_mali_osk_errcode_t _mali_osk_profiling_start(u32 * limit) +{ + /* Nothing to do */ + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _mali_osk_profiling_stop(u32 *count) +{ + /* Nothing to do */ + return _MALI_OSK_ERR_OK; +} + +u32 _mali_osk_profiling_get_count(void) +{ + return 0; +} + +_mali_osk_errcode_t _mali_osk_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5]) +{ + /* Nothing to do */ + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _mali_osk_profiling_clear(void) +{ + /* Nothing to do */ + return _MALI_OSK_ERR_OK; +} + +mali_bool _mali_osk_profiling_is_recording(void) +{ + return MALI_FALSE; +} + +mali_bool _mali_osk_profiling_have_recording(void) +{ + return MALI_FALSE; +} + +void _mali_osk_profiling_report_sw_counters(u32 *counters) +{ + trace_mali_sw_counters(_mali_osk_get_pid(), _mali_osk_get_tid(), NULL, counters); +} + + +_mali_osk_errcode_t _mali_ukk_profiling_start(_mali_uk_profiling_start_s *args) +{ + return _mali_osk_profiling_start(&args->limit); +} + +_mali_osk_errcode_t _mali_ukk_profiling_add_event(_mali_uk_profiling_add_event_s *args) +{ + /* Always add process and thread identificator in the first two data elements for events from user space */ + _mali_osk_profiling_add_event(args->event_id, _mali_osk_get_pid(), _mali_osk_get_tid(), args->data[2], args->data[3], args->data[4]); + + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _mali_ukk_profiling_stop(_mali_uk_profiling_stop_s *args) +{ + return _mali_osk_profiling_stop(&args->count); +} + +_mali_osk_errcode_t _mali_ukk_profiling_get_event(_mali_uk_profiling_get_event_s *args) +{ + return _mali_osk_profiling_get_event(args->index, &args->timestamp, &args->event_id, args->data); +} + +_mali_osk_errcode_t _mali_ukk_profiling_clear(_mali_uk_profiling_clear_s *args) +{ + return _mali_osk_profiling_clear(); +} + +_mali_osk_errcode_t _mali_ukk_sw_counters_report(_mali_uk_sw_counters_report_s *args) +{ + _mali_osk_profiling_report_sw_counters(args->counters); + return _MALI_OSK_ERR_OK; +} + +/** + * Called by gator.ko to set HW counters + * + * @param counter_id The counter ID. + * @param event_id Event ID that the counter should count (HW counter value from TRM). + * + * @return 1 on success, 0 on failure. + */ +int _mali_profiling_set_event(u32 counter_id, s32 event_id) +{ + + if (COUNTER_VP_C0 == counter_id) + { + struct mali_gp_core* gp_core = mali_gp_get_global_gp_core(); + if (NULL != gp_core) + { + if (MALI_TRUE == mali_gp_core_set_counter_src0(gp_core, event_id)) + { + return 1; + } + } + } + if (COUNTER_VP_C1 == counter_id) + { + struct mali_gp_core* gp_core = mali_gp_get_global_gp_core(); + if (NULL != gp_core) + { + if (MALI_TRUE == mali_gp_core_set_counter_src1(gp_core, event_id)) + { + return 1; + } + } + } + if (COUNTER_FP0_C0 <= counter_id && COUNTER_FP3_C1 >= counter_id) + { + u32 core_id = (counter_id - COUNTER_FP0_C0) >> 1; + struct mali_pp_core* pp_core = mali_pp_get_global_pp_core(core_id); + if (NULL != pp_core) + { + u32 counter_src = (counter_id - COUNTER_FP0_C0) & 1; + if (0 == counter_src) + { + if (MALI_TRUE == mali_pp_core_set_counter_src0(pp_core, event_id)) + { + return 1; + } + } + else + { + if (MALI_TRUE == mali_pp_core_set_counter_src1(pp_core, event_id)) + { + return 1; + } + } + } + } + if (COUNTER_L2_C0 <= counter_id && COUNTER_L2_C1 >= counter_id) + { + u32 core_id = (counter_id - COUNTER_L2_C0) >> 1; + struct mali_l2_cache_core* l2_cache_core = mali_l2_cache_core_get_glob_l2_core(core_id); + if (NULL != l2_cache_core) + { + u32 counter_src = (counter_id - COUNTER_L2_C0) & 1; + if (0 == counter_src) + { + if (MALI_TRUE == mali_l2_cache_core_set_counter_src0(l2_cache_core, event_id)) + { + return 1; + } + } + else + { + if (MALI_TRUE == mali_l2_cache_core_set_counter_src1(l2_cache_core, event_id)) + { + return 1; + } + } + } + } + + return 0; +} + +/** + * Called by gator.ko to retrieve the L2 cache counter values for the first L2 cache. + * The L2 cache counters are unique in that they are polled by gator, rather than being + * transmitted via the tracepoint mechanism. + * + * @param src0 First L2 cache counter ID. + * @param val0 First L2 cache counter value. + * @param src1 Second L2 cache counter ID. + * @param val1 Second L2 cache counter value. + */ +void _mali_profiling_get_counters(u32 *src0, u32 *val0, u32 *src1, u32 *val1) +{ + struct mali_l2_cache_core *l2_cache = mali_l2_cache_core_get_glob_l2_core(0); + if (NULL != l2_cache) + { + if (MALI_TRUE == mali_l2_cache_lock_power_state(l2_cache)) + { + /* It is now safe to access the L2 cache core in order to retrieve the counters */ + mali_l2_cache_core_get_counter_values(l2_cache, src0, val0, src1, val1); + } + mali_l2_cache_unlock_power_state(l2_cache); + } +} + +/* + * List of possible actions to be controlled by Streamline. + * The following numbers are used by gator to control the frame buffer dumping and s/w counter reporting. + * We cannot use the enums in mali_uk_types.h because they are unknown inside gator. + */ +#define FBDUMP_CONTROL_ENABLE (1) +#define FBDUMP_CONTROL_RATE (2) +#define SW_COUNTER_ENABLE (3) +#define FBDUMP_CONTROL_RESIZE_FACTOR (4) + +/** + * Called by gator to control the production of profiling information at runtime. + */ +void _mali_profiling_control(u32 action, u32 value) +{ + switch(action) + { + case FBDUMP_CONTROL_ENABLE: + mali_set_user_setting(_MALI_UK_USER_SETTING_COLORBUFFER_CAPTURE_ENABLED, (value == 0 ? MALI_FALSE : MALI_TRUE)); + break; + case FBDUMP_CONTROL_RATE: + mali_set_user_setting(_MALI_UK_USER_SETTING_BUFFER_CAPTURE_N_FRAMES, value); + break; + case SW_COUNTER_ENABLE: + mali_set_user_setting(_MALI_UK_USER_SETTING_SW_COUNTER_ENABLED, value); + break; + case FBDUMP_CONTROL_RESIZE_FACTOR: + mali_set_user_setting(_MALI_UK_USER_SETTING_BUFFER_CAPTURE_RESIZE_FACTOR, value); + break; + default: + break; /* Ignore unimplemented actions */ + } +} + +EXPORT_SYMBOL(_mali_profiling_set_event); +EXPORT_SYMBOL(_mali_profiling_get_counters); +EXPORT_SYMBOL(_mali_profiling_control); diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_profiling_internal.c b/drivers/media/video/samsung/mali/linux/mali_osk_profiling_internal.c new file mode 100644 index 0000000..2df935d --- /dev/null +++ b/drivers/media/video/samsung/mali/linux/mali_osk_profiling_internal.c @@ -0,0 +1,324 @@ +/* + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_osk_mali.h" +#include "mali_ukk.h" +#include "mali_timestamp.h" +#include "mali_osk_profiling.h" +#include "mali_user_settings_db.h" + +typedef struct mali_profiling_entry +{ + u64 timestamp; + u32 event_id; + u32 data[5]; +} mali_profiling_entry; + + +typedef enum mali_profiling_state +{ + MALI_PROFILING_STATE_UNINITIALIZED, + MALI_PROFILING_STATE_IDLE, + MALI_PROFILING_STATE_RUNNING, + MALI_PROFILING_STATE_RETURN, +} mali_profiling_state; + +static _mali_osk_lock_t *lock = NULL; +static mali_profiling_state prof_state = MALI_PROFILING_STATE_UNINITIALIZED; +static mali_profiling_entry* profile_entries = NULL; +static u32 profile_entry_count = 0; +static _mali_osk_atomic_t profile_insert_index; +static _mali_osk_atomic_t profile_entries_written; + +_mali_osk_errcode_t _mali_osk_profiling_init(mali_bool auto_start) +{ + profile_entries = NULL; + profile_entry_count = 0; + _mali_osk_atomic_init(&profile_insert_index, 0); + _mali_osk_atomic_init(&profile_entries_written, 0); + + lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_PROFILING); + if (NULL == lock) + { + return _MALI_OSK_ERR_FAULT; + } + + prof_state = MALI_PROFILING_STATE_IDLE; + + if (MALI_TRUE == auto_start) + { + u32 limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; /* Use maximum buffer size */ + + mali_set_user_setting(_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, MALI_TRUE); + if (_MALI_OSK_ERR_OK != _mali_osk_profiling_start(&limit)) + { + return _MALI_OSK_ERR_FAULT; + } + } + + return _MALI_OSK_ERR_OK; +} + +void _mali_osk_profiling_term(void) +{ + prof_state = MALI_PROFILING_STATE_UNINITIALIZED; + + /* wait for all elements to be completely inserted into array */ + while (_mali_osk_atomic_read(&profile_insert_index) != _mali_osk_atomic_read(&profile_entries_written)) + { + /* do nothing */; + } + + if (NULL != profile_entries) + { + _mali_osk_vfree(profile_entries); + profile_entries = NULL; + } + + if (NULL != lock) + { + _mali_osk_lock_term(lock); + lock = NULL; + } +} + +inline _mali_osk_errcode_t _mali_osk_profiling_start(u32 * limit) +{ + _mali_osk_errcode_t ret; + + mali_profiling_entry *new_profile_entries = _mali_osk_valloc(*limit * sizeof(mali_profiling_entry)); + + if(NULL == new_profile_entries) + { + return _MALI_OSK_ERR_NOMEM; + } + + _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); + + if (prof_state != MALI_PROFILING_STATE_IDLE) + { + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_vfree(new_profile_entries); + return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ + } + + if (*limit > MALI_PROFILING_MAX_BUFFER_ENTRIES) + { + *limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; + } + + profile_entries = new_profile_entries; + profile_entry_count = *limit; + + ret = _mali_timestamp_reset(); + + if (ret == _MALI_OSK_ERR_OK) + { + prof_state = MALI_PROFILING_STATE_RUNNING; + } + else + { + _mali_osk_vfree(profile_entries); + profile_entries = NULL; + } + + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return ret; +} + +inline void _mali_osk_profiling_add_event(u32 event_id, u32 data0, u32 data1, u32 data2, u32 data3, u32 data4) +{ + if (prof_state == MALI_PROFILING_STATE_RUNNING) + { + u32 cur_index = (_mali_osk_atomic_inc_return(&profile_insert_index) - 1) % profile_entry_count; + + profile_entries[cur_index].timestamp = _mali_timestamp_get(); + profile_entries[cur_index].event_id = event_id; + profile_entries[cur_index].data[0] = data0; + profile_entries[cur_index].data[1] = data1; + profile_entries[cur_index].data[2] = data2; + profile_entries[cur_index].data[3] = data3; + profile_entries[cur_index].data[4] = data4; + + /* If event is "leave API function", add current memory usage to the event + * as data point 4. This is used in timeline profiling to indicate how + * much memory was used when leaving a function. */ + if (event_id == (MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_SINGLE_SW_LEAVE_API_FUNC)) + { + profile_entries[cur_index].data[4] = _mali_ukk_report_memory_usage(); + } + + _mali_osk_atomic_inc(&profile_entries_written); + } +} + +inline void _mali_osk_profiling_report_hw_counter(u32 counter_id, u32 value) +{ + /* Not implemented */ +} + +void _mali_osk_profiling_report_sw_counters(u32 *counters) +{ + /* Not implemented */ +} + +inline _mali_osk_errcode_t _mali_osk_profiling_stop(u32 * count) +{ + _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); + + if (prof_state != MALI_PROFILING_STATE_RUNNING) + { + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ + } + + /* go into return state (user to retreive events), no more events will be added after this */ + prof_state = MALI_PROFILING_STATE_RETURN; + + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + + /* wait for all elements to be completely inserted into array */ + while (_mali_osk_atomic_read(&profile_insert_index) != _mali_osk_atomic_read(&profile_entries_written)) + { + /* do nothing */; + } + + *count = _mali_osk_atomic_read(&profile_insert_index); + if(*count>profile_entry_count) *count=profile_entry_count; + + return _MALI_OSK_ERR_OK; +} + +inline u32 _mali_osk_profiling_get_count(void) +{ + u32 retval = 0; + + _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); + if (prof_state == MALI_PROFILING_STATE_RETURN) + { + retval = _mali_osk_atomic_read(&profile_entries_written); + if(retval>profile_entry_count) retval = profile_entry_count; + } + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + + return retval; +} + +inline _mali_osk_errcode_t _mali_osk_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5]) +{ + _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); + + if(index=profile_entry_count) + { + idx = (index + _mali_osk_atomic_read(&profile_insert_index)) % profile_entry_count; + } + + if (prof_state != MALI_PROFILING_STATE_RETURN) + { + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ + } + + if (idx >= _mali_osk_atomic_read(&profile_entries_written)) + { + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_FAULT; + } + + *timestamp = profile_entries[idx].timestamp; + *event_id = profile_entries[idx].event_id; + data[0] = profile_entries[idx].data[0]; + data[1] = profile_entries[idx].data[1]; + data[2] = profile_entries[idx].data[2]; + data[3] = profile_entries[idx].data[3]; + data[4] = profile_entries[idx].data[4]; + } + else + { + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_FAULT; + } + + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_OK; +} + +inline _mali_osk_errcode_t _mali_osk_profiling_clear(void) +{ + _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); + + if (prof_state != MALI_PROFILING_STATE_RETURN) + { + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ + } + + prof_state = MALI_PROFILING_STATE_IDLE; + profile_entry_count = 0; + _mali_osk_atomic_init(&profile_insert_index, 0); + _mali_osk_atomic_init(&profile_entries_written, 0); + if (NULL != profile_entries) + { + _mali_osk_vfree(profile_entries); + profile_entries = NULL; + } + + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_OK; +} + +mali_bool _mali_osk_profiling_is_recording(void) +{ + return prof_state == MALI_PROFILING_STATE_RUNNING ? MALI_TRUE : MALI_FALSE; +} + +mali_bool _mali_osk_profiling_have_recording(void) +{ + return prof_state == MALI_PROFILING_STATE_RETURN ? MALI_TRUE : MALI_FALSE; +} + +_mali_osk_errcode_t _mali_ukk_profiling_start(_mali_uk_profiling_start_s *args) +{ + return _mali_osk_profiling_start(&args->limit); +} + +_mali_osk_errcode_t _mali_ukk_profiling_add_event(_mali_uk_profiling_add_event_s *args) +{ + /* Always add process and thread identificator in the first two data elements for events from user space */ + _mali_osk_profiling_add_event(args->event_id, _mali_osk_get_pid(), _mali_osk_get_tid(), args->data[2], args->data[3], args->data[4]); + return _MALI_OSK_ERR_OK; +} + +_mali_osk_errcode_t _mali_ukk_profiling_stop(_mali_uk_profiling_stop_s *args) +{ + return _mali_osk_profiling_stop(&args->count); +} + +_mali_osk_errcode_t _mali_ukk_profiling_get_event(_mali_uk_profiling_get_event_s *args) +{ + return _mali_osk_profiling_get_event(args->index, &args->timestamp, &args->event_id, args->data); +} + +_mali_osk_errcode_t _mali_ukk_profiling_clear(_mali_uk_profiling_clear_s *args) +{ + return _mali_osk_profiling_clear(); +} + +_mali_osk_errcode_t _mali_ukk_sw_counters_report(_mali_uk_sw_counters_report_s *args) +{ + _mali_osk_profiling_report_sw_counters(args->counters); + return _MALI_OSK_ERR_OK; +} + diff --git a/drivers/media/video/samsung/mali/linux/mali_osk_specific.h b/drivers/media/video/samsung/mali/linux/mali_osk_specific.h index 157368b..83ee906 100644 --- a/drivers/media/video/samsung/mali/linux/mali_osk_specific.h +++ b/drivers/media/video/samsung/mali/linux/mali_osk_specific.h @@ -17,15 +17,17 @@ #ifndef __MALI_OSK_SPECIFIC_H__ #define __MALI_OSK_SPECIFIC_H__ -#include +#ifdef __cplusplus +extern "C" +{ +#endif #define MALI_STATIC_INLINE static inline #define MALI_NON_STATIC_INLINE inline -MALI_STATIC_INLINE u32 _mali_osk_copy_from_user(void *to, void *from, u32 n) -{ - return (u32)copy_from_user(to, from, (unsigned long)n); +#ifdef __cplusplus } +#endif /** The list of events supported by the Mali DDK. */ typedef enum @@ -37,7 +39,7 @@ typedef enum ACTIVITY_FP0, ACTIVITY_FP1, ACTIVITY_FP2, - ACTIVITY_FP3, + ACTIVITY_FP3, /* L2 cache counters */ COUNTER_L2_C0, @@ -57,7 +59,7 @@ typedef enum COUNTER_FP3_C0, COUNTER_FP3_C1, - /* + /* * If more hardware counters are added, the _mali_osk_hw_counter_table * below should also be updated. */ diff --git a/drivers/media/video/samsung/mali/linux/mali_profiling_internal.c b/drivers/media/video/samsung/mali/linux/mali_profiling_internal.c deleted file mode 100644 index 8202497..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_profiling_internal.c +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright (C) 2010-2012 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_osk_mali.h" -#include "mali_ukk.h" -#include "mali_timestamp.h" -#include "mali_osk_profiling.h" -#include "mali_user_settings_db.h" -#include "mali_profiling_internal.h" - -typedef struct mali_profiling_entry -{ - u64 timestamp; - u32 event_id; - u32 data[5]; -} mali_profiling_entry; - - -typedef enum mali_profiling_state -{ - MALI_PROFILING_STATE_UNINITIALIZED, - MALI_PROFILING_STATE_IDLE, - MALI_PROFILING_STATE_RUNNING, - MALI_PROFILING_STATE_RETURN, -} mali_profiling_state; - -static _mali_osk_lock_t *lock = NULL; -static mali_profiling_state prof_state = MALI_PROFILING_STATE_UNINITIALIZED; -static mali_profiling_entry* profile_entries = NULL; -static _mali_osk_atomic_t profile_insert_index; -static u32 profile_mask = 0; -static inline void add_event(u32 event_id, u32 data0, u32 data1, u32 data2, u32 data3, u32 data4); - -void probe_mali_timeline_event(void *data, TP_PROTO(unsigned int event_id, unsigned int d0, unsigned int d1, unsigned - int d2, unsigned int d3, unsigned int d4)) -{ - add_event(event_id, d0, d1, d2, d3, d4); -} - -_mali_osk_errcode_t _mali_internal_profiling_init(mali_bool auto_start) -{ - profile_entries = NULL; - profile_mask = 0; - _mali_osk_atomic_init(&profile_insert_index, 0); - - lock = _mali_osk_lock_init(_MALI_OSK_LOCKFLAG_ORDERED | _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, _MALI_OSK_LOCK_ORDER_PROFILING); - if (NULL == lock) - { - return _MALI_OSK_ERR_FAULT; - } - - prof_state = MALI_PROFILING_STATE_IDLE; - - if (MALI_TRUE == auto_start) - { - u32 limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; /* Use maximum buffer size */ - - mali_set_user_setting(_MALI_UK_USER_SETTING_SW_EVENTS_ENABLE, MALI_TRUE); - if (_MALI_OSK_ERR_OK != _mali_internal_profiling_start(&limit)) - { - return _MALI_OSK_ERR_FAULT; - } - } - - return _MALI_OSK_ERR_OK; -} - -void _mali_internal_profiling_term(void) -{ - u32 count; - - /* Ensure profiling is stopped */ - _mali_internal_profiling_stop(&count); - - prof_state = MALI_PROFILING_STATE_UNINITIALIZED; - - if (NULL != profile_entries) - { - _mali_osk_vfree(profile_entries); - profile_entries = NULL; - } - - if (NULL != lock) - { - _mali_osk_lock_term(lock); - lock = NULL; - } -} - -_mali_osk_errcode_t _mali_internal_profiling_start(u32 * limit) -{ - _mali_osk_errcode_t ret; - - mali_profiling_entry *new_profile_entries; - - _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); - - if (MALI_PROFILING_MAX_BUFFER_ENTRIES < *limit) - { - *limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; - } - - profile_mask = 1; - while (profile_mask <= *limit) - { - profile_mask <<= 1; - } - profile_mask >>= 1; - - *limit = profile_mask; - - profile_mask--; /* turns the power of two into a mask of one less */ - - new_profile_entries = _mali_osk_valloc(*limit * sizeof(mali_profiling_entry)); - - if (NULL == new_profile_entries) - { - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_NOMEM; - } - - if (MALI_PROFILING_STATE_IDLE != prof_state) - { - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - _mali_osk_vfree(new_profile_entries); - return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ - } - - profile_entries = new_profile_entries; - - ret = _mali_timestamp_reset(); - - if (_MALI_OSK_ERR_OK == ret) - { - prof_state = MALI_PROFILING_STATE_RUNNING; - } - else - { - _mali_osk_vfree(profile_entries); - profile_entries = NULL; - } - - register_trace_mali_timeline_event(probe_mali_timeline_event, NULL); - - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return ret; -} - -static inline void add_event(u32 event_id, u32 data0, u32 data1, u32 data2, u32 data3, u32 data4) -{ - u32 cur_index = (_mali_osk_atomic_inc_return(&profile_insert_index) - 1) & profile_mask; - - profile_entries[cur_index].timestamp = _mali_timestamp_get(); - profile_entries[cur_index].event_id = event_id; - profile_entries[cur_index].data[0] = data0; - profile_entries[cur_index].data[1] = data1; - profile_entries[cur_index].data[2] = data2; - profile_entries[cur_index].data[3] = data3; - profile_entries[cur_index].data[4] = data4; - - /* If event is "leave API function", add current memory usage to the event - * as data point 4. This is used in timeline profiling to indicate how - * much memory was used when leaving a function. */ - if (event_id == (MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_EVENT_CHANNEL_SOFTWARE|MALI_PROFILING_EVENT_REASON_SINGLE_SW_LEAVE_API_FUNC)) - { - profile_entries[cur_index].data[4] = _mali_ukk_report_memory_usage(); - } -} - -_mali_osk_errcode_t _mali_internal_profiling_stop(u32 * count) -{ - _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); - - if (MALI_PROFILING_STATE_RUNNING != prof_state) - { - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ - } - - /* go into return state (user to retreive events), no more events will be added after this */ - prof_state = MALI_PROFILING_STATE_RETURN; - - unregister_trace_mali_timeline_event(probe_mali_timeline_event, NULL); - tracepoint_synchronize_unregister(); - - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - - *count = _mali_osk_atomic_read(&profile_insert_index); - if (*count > profile_mask) *count = profile_mask; - - return _MALI_OSK_ERR_OK; -} - -u32 _mali_internal_profiling_get_count(void) -{ - u32 retval = 0; - - _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); - if (MALI_PROFILING_STATE_RETURN == prof_state) - { - retval = _mali_osk_atomic_read(&profile_insert_index); - if (retval > profile_mask) retval = profile_mask; - } - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - - return retval; -} - -_mali_osk_errcode_t _mali_internal_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5]) -{ - u32 raw_index = _mali_osk_atomic_read(&profile_insert_index); - - _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); - - if (index < profile_mask) - { - if ((raw_index & ~profile_mask) != 0) - { - index += raw_index; - index &= profile_mask; - } - - if (prof_state != MALI_PROFILING_STATE_RETURN) - { - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ - } - - if(index >= raw_index) - { - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_FAULT; - } - - *timestamp = profile_entries[index].timestamp; - *event_id = profile_entries[index].event_id; - data[0] = profile_entries[index].data[0]; - data[1] = profile_entries[index].data[1]; - data[2] = profile_entries[index].data[2]; - data[3] = profile_entries[index].data[3]; - data[4] = profile_entries[index].data[4]; - } - else - { - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_FAULT; - } - - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t _mali_internal_profiling_clear(void) -{ - _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); - - if (MALI_PROFILING_STATE_RETURN != prof_state) - { - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ - } - - prof_state = MALI_PROFILING_STATE_IDLE; - profile_mask = 0; - _mali_osk_atomic_init(&profile_insert_index, 0); - - if (NULL != profile_entries) - { - _mali_osk_vfree(profile_entries); - profile_entries = NULL; - } - - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_OK; -} - -mali_bool _mali_internal_profiling_is_recording(void) -{ - return prof_state == MALI_PROFILING_STATE_RUNNING ? MALI_TRUE : MALI_FALSE; -} - -mali_bool _mali_internal_profiling_have_recording(void) -{ - return prof_state == MALI_PROFILING_STATE_RETURN ? MALI_TRUE : MALI_FALSE; -} diff --git a/drivers/media/video/samsung/mali/linux/mali_profiling_internal.h b/drivers/media/video/samsung/mali/linux/mali_profiling_internal.h deleted file mode 100644 index 092b9b0..0000000 --- a/drivers/media/video/samsung/mali/linux/mali_profiling_internal.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2012 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 __MALI_PROFILING_INTERNAL_H__ -#define __MALI_PROFILING_INTERNAL_H__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include "mali_osk.h" - -int _mali_internal_profiling_init(mali_bool auto_start); -void _mali_internal_profiling_term(void); - -mali_bool _mali_internal_profiling_is_recording(void); -mali_bool _mali_internal_profiling_have_recording(void); -_mali_osk_errcode_t _mali_internal_profiling_clear(void); -_mali_osk_errcode_t _mali_internal_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5]); -u32 _mali_internal_profiling_get_count(void); -int _mali_internal_profiling_stop(u32 * count); -int _mali_internal_profiling_start(u32 * limit); - -#ifdef __cplusplus -} -#endif - -#endif /* __MALI_PROFILING_INTERNAL_H__ */ diff --git a/drivers/media/video/samsung/mali/linux/mali_uk_types.h b/drivers/media/video/samsung/mali/linux/mali_uk_types.h index fbe902a..1a81246 100644 --- a/drivers/media/video/samsung/mali/linux/mali_uk_types.h +++ b/drivers/media/video/samsung/mali/linux/mali_uk_types.h @@ -12,6 +12,7 @@ #define __MALI_UK_TYPES_H__ /* Simple wrapper in order to find the OS specific location of this file */ -#include +//#include +#include "../include/linux/mali/mali_utgard_uk_types.h" #endif /* __MALI_UK_TYPES_H__ */ diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_gp.c b/drivers/media/video/samsung/mali/linux/mali_ukk_gp.c index 4ee4a81..7070016 100644 --- a/drivers/media/video/samsung/mali/linux/mali_ukk_gp.c +++ b/drivers/media/video/samsung/mali/linux/mali_ukk_gp.c @@ -18,15 +18,40 @@ int gp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_gp_start_job_s __user *uargs) { - _mali_osk_errcode_t err; + _mali_uk_gp_start_job_s kargs; + _mali_osk_errcode_t err; - MALI_CHECK_NON_NULL(uargs, -EINVAL); - MALI_CHECK_NON_NULL(session_data, -EINVAL); + MALI_CHECK_NON_NULL(uargs, -EINVAL); + MALI_CHECK_NON_NULL(session_data, -EINVAL); - err = _mali_ukk_gp_start_job(session_data, uargs); - if (_MALI_OSK_ERR_OK != err) return map_errcode(err); + if (!access_ok(VERIFY_WRITE, uargs, sizeof(_mali_uk_gp_start_job_s))) + { + return -EFAULT; + } - return 0; + if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_gp_start_job_s))) return -EFAULT; + + kargs.ctx = session_data; + err = _mali_ukk_gp_start_job(&kargs); + if (_MALI_OSK_ERR_OK != err) return map_errcode(err); + + kargs.ctx = NULL; /* prevent kernel address to be returned to user space */ + + if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_gp_start_job_s))) + { + /* + * If this happens, then user space will not know that the job was actually started, + * and if we return a queued job, then user space will still think that one is still queued. + * This will typically lead to a deadlock in user space. + * This could however only happen if user space deliberately passes a user buffer which + * passes the access_ok(VERIFY_WRITE) check, but isn't fully writable at the time of copy_to_user(). + * The official Mali driver will never attempt to do that, and kernel space should not be affected. + * That is why we do not bother to do a complex rollback in this very very very rare case. + */ + return -EFAULT; + } + + return 0; } int gp_get_core_version_wrapper(struct mali_session_data *session_data, _mali_uk_get_gp_core_version_s __user *uargs) diff --git a/drivers/media/video/samsung/mali/linux/mali_ukk_pp.c b/drivers/media/video/samsung/mali/linux/mali_ukk_pp.c index 00a84f7..c11c61b 100644 --- a/drivers/media/video/samsung/mali/linux/mali_ukk_pp.c +++ b/drivers/media/video/samsung/mali/linux/mali_ukk_pp.c @@ -18,15 +18,24 @@ int pp_start_job_wrapper(struct mali_session_data *session_data, _mali_uk_pp_start_job_s __user *uargs) { + _mali_uk_pp_start_job_s kargs; _mali_osk_errcode_t err; MALI_CHECK_NON_NULL(uargs, -EINVAL); MALI_CHECK_NON_NULL(session_data, -EINVAL); - err = _mali_ukk_pp_start_job(session_data, uargs); + if (!access_ok(VERIFY_WRITE, uargs, sizeof(_mali_uk_pp_start_job_s))) + { + return -EFAULT; + } + + if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_pp_start_job_s))) return -EFAULT; + + kargs.ctx = session_data; + err = _mali_ukk_pp_start_job(&kargs); if (_MALI_OSK_ERR_OK != err) return map_errcode(err); - return 0; + return 0; } int pp_get_number_of_cores_wrapper(struct mali_session_data *session_data, _mali_uk_get_pp_number_of_cores_s __user *uargs) diff --git a/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform.c b/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform.c index 792b9a9..119831d 100644 --- a/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform.c +++ b/drivers/media/video/samsung/mali/platform/orion-m400/mali_platform.c @@ -1,9 +1,9 @@ /* * Copyright (C) 2010-2012 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. */ @@ -19,7 +19,7 @@ #include "mali_linux_pm.h" #if USING_MALI_PMM -#include "mali_pmm.h" +#include "mali_pm.h" #endif #include @@ -156,7 +156,7 @@ void mali_regulator_set_voltage(int min_uV, int max_uV) return; } MALI_DEBUG_PRINT(2, ("= regulator_set_voltage: %d, %d \n",min_uV, max_uV)); - + #if MALI_TIMELINE_PROFILING_ENABLED _mali_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | @@ -166,7 +166,7 @@ void mali_regulator_set_voltage(int min_uV, int max_uV) regulator_set_voltage(g3d_regulator,min_uV,max_uV); voltage = regulator_get_voltage(g3d_regulator); - + #if MALI_TIMELINE_PROFILING_ENABLED _mali_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | @@ -178,7 +178,7 @@ void mali_regulator_set_voltage(int min_uV, int max_uV) _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); } -#endif +#endif unsigned long mali_clk_get_rate(void) { @@ -228,7 +228,7 @@ mali_bool mali_clk_get(mali_bool bis_vpll) if (mali_parent_clock == NULL) { mali_parent_clock = clk_get(NULL, GPUMOUT1CLK_NAME); - + if (IS_ERR(mali_parent_clock)) { MALI_PRINT( ( "MALI Error : failed to get source mali parent clock\n")); return MALI_FALSE; @@ -279,7 +279,7 @@ void mali_clk_put(mali_bool binc_mali_clock) clk_put(mali_parent_clock); mali_parent_clock = 0; } - + if (mpll_clock) { clk_put(mpll_clock); @@ -303,7 +303,7 @@ void mali_clk_put(mali_bool binc_mali_clock) clk_put(vpll_src_clock); vpll_src_clock = 0; } - + if (ext_xtal_clock) { clk_put(ext_xtal_clock); @@ -382,14 +382,14 @@ mali_bool mali_clk_set_rate(unsigned int clk, unsigned int mhz) mali_clk_put(MALI_FALSE); _mali_osk_lock_signal(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); - + return MALI_TRUE; } static mali_bool init_mali_clock(void) { mali_bool ret = MALI_TRUE; - + gpu_power_state = 0; if (mali_clock != 0) @@ -416,7 +416,7 @@ static mali_bool init_mali_clock(void) g3d_regulator = regulator_get(NULL, "vdd_g3d"); #endif - if (IS_ERR(g3d_regulator)) + if (IS_ERR(g3d_regulator)) { MALI_PRINT( ("MALI Error : failed to get vdd_g3d\n")); ret = MALI_FALSE; @@ -429,8 +429,6 @@ static mali_bool init_mali_clock(void) #endif MALI_DEBUG_PRINT(2, ("MALI Clock is set at mali driver\n")); - - MALI_DEBUG_PRINT(3,("::clk_put:: %s mali_parent_clock - normal\n", __FUNCTION__)); MALI_DEBUG_PRINT(3,("::clk_put:: %s mpll_clock - normal\n", __FUNCTION__)); @@ -443,7 +441,7 @@ static mali_bool init_mali_clock(void) err_regulator: regulator_put(g3d_regulator); #endif - + err_clock_get: mali_clk_put(MALI_TRUE); @@ -456,7 +454,7 @@ static mali_bool deinit_mali_clock(void) return MALI_TRUE; #ifdef CONFIG_REGULATOR - if (g3d_regulator) + if (g3d_regulator) { regulator_put(g3d_regulator); g3d_regulator=NULL; @@ -506,8 +504,8 @@ _mali_osk_errcode_t g3d_power_domain_control(int bpower_on) if (bpower_on) { #if MALI_PMM_RUNTIME_JOB_CONTROL_ON - MALI_DEBUG_PRINT(3,("_mali_osk_pmm_dev_activate \n")); - _mali_osk_pmm_dev_activate(); + MALI_DEBUG_PRINT(3,("_mali_osk_pm_dev_activate \n")); + _mali_osk_pm_dev_activate(); #else //MALI_PMM_RUNTIME_JOB_CONTROL_ON void __iomem *status; u32 timeout; @@ -529,14 +527,14 @@ _mali_osk_errcode_t g3d_power_domain_control(int bpower_on) else { #if MALI_PMM_RUNTIME_JOB_CONTROL_ON - MALI_DEBUG_PRINT( 4,("_mali_osk_pmm_dev_idle\n")); - _mali_osk_pmm_dev_idle(); + MALI_DEBUG_PRINT( 4,("_mali_osk_pm_dev_idle\n")); + _mali_osk_pm_dev_idle(); #else //MALI_PMM_RUNTIME_JOB_CONTROL_ON void __iomem *status; u32 timeout; __raw_writel(0, S5P_PMU_G3D_CONF); - + status = S5P_PMU_G3D_CONF + 0x4; /* Wait max 1ms */ timeout = 10; @@ -561,7 +559,7 @@ _mali_osk_errcode_t mali_platform_init() #if MALI_DVFS_ENABLED if (!clk_register_map) clk_register_map = _mali_osk_mem_mapioregion( CLK_DIV_STAT_G3D, 0x20, CLK_DESC ); if(!init_mali_dvfs_status(MALI_DVFS_DEFAULT_STEP)) - MALI_DEBUG_PRINT(1, ("mali_platform_init failed\n")); + MALI_DEBUG_PRINT(1, ("mali_platform_init failed\n")); #endif MALI_SUCCESS; @@ -593,7 +591,7 @@ _mali_osk_errcode_t mali_platform_powerdown(u32 cores) if (gpu_power_state == 0) { MALI_DEBUG_PRINT( 3,("disable clock\n")); - disable_mali_clocks(); + disable_mali_clocks(); } } else @@ -635,7 +633,7 @@ _mali_osk_errcode_t mali_platform_powerup(u32 cores) void mali_gpu_utilization_handler(u32 utilization) { - if (bPoweroff==0) + if (bPoweroff==0) { #if MALI_DVFS_ENABLED if(!mali_dvfs_handler(utilization)) diff --git a/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform.c b/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform.c index 8fc26cd..a08bc97 100644 --- a/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform.c +++ b/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform.c @@ -33,7 +33,8 @@ #if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED #include "mali_osk_profiling.h" -#include "cinstr/mali_cinstr_profiling_events_m200.h" +unsigned long gFreq = 366; +int gVolt = 5000; #endif #include @@ -58,7 +59,7 @@ typedef struct mali_runtime_resumeTag{ int vol; }mali_runtime_resume_table; -mali_runtime_resume_table mali_runtime_resume = {350, 950000}; +mali_runtime_resume_table mali_runtime_resume = {266, 900000}; /* lock/unlock CPU freq by Mali */ extern int cpufreq_lock_by_mali(unsigned int freq); @@ -84,11 +85,11 @@ static struct clk *mali_clock = 0; static unsigned int GPU_MHZ = 1000000; -int mali_gpu_clk = 350; -int mali_gpu_vol = 950000; +int mali_gpu_clk = 266; +int mali_gpu_vol = 900000; #if MALI_DVFS_ENABLED -#define MALI_DVFS_DEFAULT_STEP 2 +#define MALI_DVFS_DEFAULT_STEP 1 #endif #if MALI_VOLTAGE_LOCK int mali_lock_vol = 0; @@ -204,21 +205,15 @@ void mali_regulator_set_voltage(int min_uV, int max_uV) MALI_DEBUG_PRINT(2, ("= regulator_set_voltage: %d, %d \n",min_uV, max_uV)); -#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE | - MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | - MALI_PROFILING_EVENT_REASON_SINGLE_SW_GPU_VOLTS, - min_uV, max_uV, 1, 0, 0); -#endif - regulator_set_voltage(g3d_regulator,min_uV,max_uV); voltage = regulator_get_voltage(g3d_regulator); #if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE | - MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | - MALI_PROFILING_EVENT_REASON_SINGLE_SW_GPU_VOLTS, - voltage, 0, 2, 0, 0); + gVolt = voltage/1000; + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | + MALI_PROFILING_EVENT_CHANNEL_GPU | + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, gFreq, gVolt, + 0, 0, 0); #endif mali_gpu_vol = voltage; @@ -379,7 +374,7 @@ mali_bool mali_clk_set_rate(unsigned int clk, unsigned int mhz) #if !MALI_DVFS_ENABLED clk = mali_gpu_clk; #endif - + trace_printk("SPI_GPUFREQ_%uMHz\n", mali_gpu_clk); _mali_osk_lock_wait(mali_dvfs_lock, _MALI_OSK_LOCKMODE_RW); if (mali_clk_get(bis_vpll) == MALI_FALSE) @@ -406,23 +401,16 @@ mali_bool mali_clk_set_rate(unsigned int clk, unsigned int mhz) if (clk_enable(mali_clock) < 0) return MALI_FALSE; -#if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED - unsigned long previous_rate = 0; - previous_rate = clk_get_rate(mali_clock); - _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE | - MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | - MALI_PROFILING_EVENT_REASON_SINGLE_SW_GPU_FREQ, - previous_rate, 0, 0, 0, 0); -#endif clk_set_rate(mali_clock, rate); rate = clk_get_rate(mali_clock); #if MALI_INTERNAL_TIMELINE_PROFILING_ENABLED - _mali_osk_profiling_add_event( MALI_PROFILING_EVENT_TYPE_SINGLE | - MALI_PROFILING_EVENT_CHANNEL_SOFTWARE | - MALI_PROFILING_EVENT_REASON_SINGLE_SW_GPU_FREQ, - rate, 1, 0, 0, 0); + gFreq = rate/1000000; + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | + MALI_PROFILING_EVENT_CHANNEL_GPU | + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE, + gFreq, gVolt, 0, 0, 0); #endif if (bis_vpll) @@ -539,7 +527,7 @@ static _mali_osk_errcode_t enable_mali_clocks(void) } #if CPUFREQ_LOCK_DURING_440 /* lock/unlock CPU freq by Mali */ - if (mali_gpu_clk == 440) + if (mali_gpu_clk >= 440) err = cpufreq_lock_by_mali(1200); #endif #else @@ -557,7 +545,7 @@ static _mali_osk_errcode_t disable_mali_clocks(void) clk_disable(mali_clock); MALI_DEBUG_PRINT(3,("disable_mali_clocks mali_clock %p \n", mali_clock)); -#if MALI_DVFS_ENABLED +#if MALI_DVFS_ENABLED && CPUFREQ_LOCK_DURING_440 /* lock/unlock CPU freq by Mali */ cpufreq_unlock_by_mali(); #endif @@ -598,7 +586,6 @@ _mali_osk_errcode_t g3d_power_domain_control(int bpower_on) timeout--; _mali_osk_time_ubusydelay(100); } - MALI_PRINTF(("MALI Power domain enabled")); #endif //MALI_PMM_RUNTIME_JOB_CONTROL_ON } else @@ -623,7 +610,6 @@ _mali_osk_errcode_t g3d_power_domain_control(int bpower_on) timeout--; _mali_osk_time_ubusydelay( 100); } - MALI_PRINTF(("MALI Power domain disabled")); #endif //MALI_PMM_RUNTIME_JOB_CONTROL_ON } @@ -665,6 +651,7 @@ _mali_osk_errcode_t mali_platform_deinit() _mali_osk_errcode_t mali_platform_powerdown(u32 cores) { + trace_printk("SPI_GPU_PWR Idle\n"); MALI_DEBUG_PRINT(3,("power down is called in mali_platform_powerdown state %x core %x \n", gpu_power_state, cores)); if (gpu_power_state != 0) // power down after state is 0 @@ -686,6 +673,7 @@ _mali_osk_errcode_t mali_platform_powerdown(u32 cores) _mali_osk_errcode_t mali_platform_powerup(u32 cores) { + trace_printk("SPI_GPU_PWR Start\n"); MALI_DEBUG_PRINT(3,("power up is called in mali_platform_powerup state %x core %x \n", gpu_power_state, cores)); if (gpu_power_state == 0) // power up only before state is 0 diff --git a/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform_dvfs.c b/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform_dvfs.c index e83addd..cc1164e 100644 --- a/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform_dvfs.c +++ b/drivers/media/video/samsung/mali/platform/pegasus-m400/mali_platform_dvfs.c @@ -175,6 +175,7 @@ mali_dvfs_threshold_table mali_dvfs_threshold[MALI_DVFS_STEPS]={ #ifdef EXYNOS4_ASV_ENABLED #define ASV_LEVEL 12 /* ASV0, 1, 11 is reserved */ +#define ASV_LEVEL_PRIME 13 /* ASV0, 1, 12 is reserved */ static unsigned int asv_3d_volt_9_table_1ghz_type[MALI_DVFS_STEPS-1][ASV_LEVEL] = { { 975000, 950000, 950000, 950000, 925000, 925000, 925000, 900000, 900000, 900000, 900000, 875000}, /* L3(160Mhz) */ @@ -202,7 +203,7 @@ static unsigned int asv_3d_volt_9_table[MALI_DVFS_STEPS-1][ASV_LEVEL] = { #endif }; -static unsigned int asv_3d_volt_9_table_for_prime[MALI_DVFS_STEPS][ASV_LEVEL] = { +static unsigned int asv_3d_volt_9_table_for_prime[MALI_DVFS_STEPS][ASV_LEVEL_PRIME] = { { 950000, 937500, 925000, 912500, 900000, 887500, 875000, 862500, 875000, 862500, 850000, 850000}, /* L4(160Mhz) */ #if (MALI_DVFS_STEPS > 1) { 975000, 962500, 950000, 937500, 925000, 912500, 900000, 887500, 900000, 887500, 875000, 862500}, /* L3(266Mhz) */ @@ -211,7 +212,7 @@ static unsigned int asv_3d_volt_9_table_for_prime[MALI_DVFS_STEPS][ASV_LEVEL] = #if (MALI_DVFS_STEPS > 3) { 1087500, 1075000, 1062500, 1050000, 1037500, 1025000, 1012500, 1000000, 1012500, 1000000, 987500, 975000}, /* L1(440Mhz) */ #if (MALI_DVFS_STEPS > 4) - { 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1087500, 1075000, 1062500, 1050000}, /* L0(533Mhz) */ + { 1150000, 1137500, 1125000, 1112500, 1100000, 1087500, 1075000, 1062500, 1087500, 1075000, 1062500, 1050000}, /* L0(600Mhz) */ #endif #endif #endif @@ -330,10 +331,12 @@ static mali_bool set_mali_dvfs_status(u32 step,mali_bool boostup) } #ifdef EXYNOS4_ASV_ENABLED - if (mali_dvfs[step].clock == 160) - exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_100V); - else - exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_130V); + if (samsung_rev() < EXYNOS4412_REV_2_0) { + if (mali_dvfs[step].clock == 160) + exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_100V); + else + exynos4x12_set_abb_member(ABB_G3D, ABB_MODE_130V); + } #endif @@ -390,26 +393,33 @@ static mali_bool mali_dvfs_table_update(void) unsigned int i; unsigned int step_num = MALI_DVFS_STEPS; + if(samsung_rev() < EXYNOS4412_REV_2_0) + step_num = MALI_DVFS_STEPS - 1; + if(soc_is_exynos4412()) { if (exynos_armclk_max == 1000000) { - step_num = MALI_DVFS_STEPS - 1; + MALI_PRINT(("::C::exynos_result_of_asv : %d\n", exynos_result_of_asv)); for (i = 0; i < step_num; i++) { - MALI_PRINT((":::exynos_result_of_asv : %d\n", exynos_result_of_asv)); mali_dvfs[i].vol = asv_3d_volt_9_table_1ghz_type[i][exynos_result_of_asv]; - MALI_PRINT(("mali_dvfs[%d].vol = %d 1ghz_type\n", i, mali_dvfs[i].vol)); + MALI_PRINT(("mali_dvfs[%d].vol = %d \n", i, mali_dvfs[i].vol)); + } + } else if(((is_special_flag() >> G3D_LOCK_FLAG) & 0x1) && (samsung_rev() >= EXYNOS4412_REV_2_0)) { + MALI_PRINT(("::L::exynos_result_of_asv : %d\n", exynos_result_of_asv)); + for (i = 0; i < step_num; i++) { + mali_dvfs[i].vol = asv_3d_volt_9_table_for_prime[i][exynos_result_of_asv] + 25000; + MALI_PRINT(("mali_dvfs[%d].vol = %d \n ", i, mali_dvfs[i].vol)); } } else if (samsung_rev() >= EXYNOS4412_REV_2_0) { + MALI_PRINT(("::P::exynos_result_of_asv : %d\n", exynos_result_of_asv)); for (i = 0; i < step_num; i++) { - MALI_PRINT((":::exynos_result_of_asv : %d\n", exynos_result_of_asv)); mali_dvfs[i].vol = asv_3d_volt_9_table_for_prime[i][exynos_result_of_asv]; - MALI_PRINT(("mali_dvfs[%d].vol = %d 1.6ghz_type\n", i, mali_dvfs[i].vol)); + MALI_PRINT(("mali_dvfs[%d].vol = %d \n", i, mali_dvfs[i].vol)); } } else { - step_num = MALI_DVFS_STEPS - 1; + MALI_PRINT(("::Q::exynos_result_of_asv : %d\n", exynos_result_of_asv)); for (i = 0; i < step_num; i++) { - MALI_PRINT((":::exynos_result_of_asv : %d\n", exynos_result_of_asv)); mali_dvfs[i].vol = asv_3d_volt_9_table[i][exynos_result_of_asv]; - MALI_PRINT(("mali_dvfs[%d].vol = %d 1.4ghz_type\n", i, mali_dvfs[i].vol)); + MALI_PRINT(("mali_dvfs[%d].vol = %d \n", i, mali_dvfs[i].vol)); } } } diff --git a/drivers/media/video/samsung/mali/regs/mali_gp_regs.h b/drivers/media/video/samsung/mali/regs/mali_gp_regs.h index dd259cf..21c83c0 100644 --- a/drivers/media/video/samsung/mali/regs/mali_gp_regs.h +++ b/drivers/media/video/samsung/mali/regs/mali_gp_regs.h @@ -145,6 +145,7 @@ typedef enum MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST | \ MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST | \ MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | \ + MALIGP2_REG_VAL_IRQ_HANG | \ MALIGP2_REG_VAL_IRQ_FORCE_HANG | \ MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR | \ MALIGP2_REG_VAL_IRQ_SYNC_ERROR | \ @@ -155,6 +156,7 @@ typedef enum MALIGP2_REG_VAL_IRQ_VS_END_CMD_LST | \ MALIGP2_REG_VAL_IRQ_PLBU_END_CMD_LST | \ MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | \ + MALIGP2_REG_VAL_IRQ_HANG | \ MALIGP2_REG_VAL_IRQ_FORCE_HANG | \ MALIGP2_REG_VAL_IRQ_WRITE_BOUND_ERR | \ MALIGP2_REG_VAL_IRQ_SYNC_ERROR | \ diff --git a/drivers/media/video/samsung/ump/Kconfig b/drivers/media/video/samsung/ump/Kconfig index aaae26e..9d8e5e6 100644 --- a/drivers/media/video/samsung/ump/Kconfig +++ b/drivers/media/video/samsung/ump/Kconfig @@ -17,10 +17,18 @@ config UMP_VCM_ALLOC help Use VCM(virtual-contiguous-memory) to allocate physical memory. + +config UMP_R3P1_LSI + bool "Uses the R3P1 as a ump module" + depends on VIDEO_UMP + default n + ---help--- + This uses the r3p1 as a UMP kernel module + choice depends on VIDEO_UMP prompt "UMP MEMEMORY OPTION" -default UMP_OSMEM_ONLY +default UMP_OSMEM_ONLY config UMP_DED_ONLY bool "ump dedicated memory only" ---help--- @@ -37,7 +45,7 @@ config UMP_VCM_ONLY endchoice config UMP_MEM_SIZE int "UMP Memory Size" - depends on VIDEO_UMP + depends on VIDEO_UMP default "512" ---help--- This value is dedicated memory size of UMP (unit is MByte). @@ -48,4 +56,3 @@ config VIDEO_UMP_DEBUG default n help This enables UMP driver debug messages. - diff --git a/drivers/media/video/samsung/ump/Makefile b/drivers/media/video/samsung/ump/Makefile index 0ba1253..3a1aac0 100644 --- a/drivers/media/video/samsung/ump/Makefile +++ b/drivers/media/video/samsung/ump/Makefile @@ -18,6 +18,12 @@ UMP_MEM_SIZE= $(CONFIG_UMP_MEM_SIZE) USING_MEMORY=1 endif +ifeq ($(CONFIG_UMP_VCM_ONLY),y) +UMP_MEM_SIZE= $(CONFIG_UMP_MEM_SIZE) +USING_MEMORY=2 +endif + + # For UMP Debug ifeq ($(CONFIG_VIDEO_UMP_DEBUG),y) DEFINES += -DDEBUG @@ -72,6 +78,9 @@ ump-y := \ $(KBUILDROOT)common/ump_kernel_ref_drv.o\ $(OSKFILES) +ump-$(CONFIG_UMP_VCM_ALLOC) += \ + $(KBUILDROOT)linux/ump_kernel_memory_backend_vcm.o \ + EXTRA_CFLAGS += $(INCLUDES) \ $(DEFINES) diff --git a/drivers/media/video/samsung/ump/Makefile.common b/drivers/media/video/samsung/ump/Makefile.common index 503a38d..26a3d6c 100644 --- a/drivers/media/video/samsung/ump/Makefile.common +++ b/drivers/media/video/samsung/ump/Makefile.common @@ -1,9 +1,9 @@ # # Copyright (C) 2010-2012 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. # diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_api.c b/drivers/media/video/samsung/ump/common/ump_kernel_api.c index 6569b02..83f0d30 100644 --- a/drivers/media/video/samsung/ump/common/ump_kernel_api.c +++ b/drivers/media/video/samsung/ump/common/ump_kernel_api.c @@ -1,9 +1,9 @@ /* * Copyright (C) 2010-2012 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. */ @@ -55,7 +55,24 @@ UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_secure_id(ump_secu return (ump_dd_handle)mem; } +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_get(ump_secure_id secure_id) +{ + ump_dd_mem * mem; + + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + DBG_MSG(5, ("Getting handle from secure ID. ID: %u\n", secure_id)); + if (0 != ump_descriptor_mapping_get(device.secure_id_map, (int)secure_id, (void**)&mem)) + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(1, ("Secure ID not found. ID: %u\n", secure_id)); + return UMP_DD_HANDLE_INVALID; + } + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + return (ump_dd_handle)mem; +} UMP_KERNEL_API_EXPORT unsigned long ump_dd_phys_block_count_get(ump_dd_handle memh) { @@ -260,7 +277,7 @@ _mali_osk_errcode_t _ump_ukk_release( _ump_uk_release_s *release_info ) } _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); - DBG_MSG_IF(1, _MALI_OSK_ERR_OK != ret, ("UMP memory with ID %u does not belong to this session.\n", secure_id)); + DBG_MSG_IF(1, _MALI_OSK_ERR_OK != ret, ("UMP memory with ID %u does not belong to this session.\n", secure_id)); DBG_MSG(4, ("_ump_ukk_release() returning 0x%x\n", ret)); return ret; diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_common.c b/drivers/media/video/samsung/ump/common/ump_kernel_common.c index b1545e8..a27bc77 100644 --- a/drivers/media/video/samsung/ump/common/ump_kernel_common.c +++ b/drivers/media/video/samsung/ump/common/ump_kernel_common.c @@ -233,7 +233,12 @@ _mali_osk_errcode_t _ump_ukk_map_mem( _ump_uk_map_mem_s *args ) MSG_ERR(("Session data is NULL in _ump_ukk_map_mem()\n")); return _MALI_OSK_ERR_INVALID_ARGS; } - + /* SEC kernel stability 2012-02-17 */ + if (NULL == session_data->cookies_map) + { + MSG_ERR(("session_data->cookies_map is NULL in _ump_ukk_map_mem()\n")); + return _MALI_OSK_ERR_INVALID_ARGS; + } descriptor = (ump_memory_allocation*) _mali_osk_calloc( 1, sizeof(ump_memory_allocation)); if (NULL == descriptor) { @@ -283,6 +288,12 @@ _mali_osk_errcode_t _ump_ukk_map_mem( _ump_uk_map_mem_s *args ) args->is_cached = 1; DBG_MSG(3, ("Mapping UMP secure_id: %d as cached.\n", args->secure_id)); } + else if ( args->is_cached) + { + mem->is_cached = 1; + descriptor->is_cached = 1; + DBG_MSG(3, ("Warning mapping UMP secure_id: %d. As cached, while it was allocated uncached.\n", args->secure_id)); + } else { descriptor->is_cached = 0; @@ -360,7 +371,12 @@ void _ump_ukk_unmap_mem( _ump_uk_unmap_mem_s *args ) MSG_ERR(("Session data is NULL in _ump_ukk_map_mem()\n")); return; } - + /* SEC kernel stability 2012-02-17 */ + if (NULL == session_data->cookies_map) + { + MSG_ERR(("session_data->cookies_map is NULL in _ump_ukk_map_mem()\n")); + return; + } if (0 != ump_descriptor_mapping_get( session_data->cookies_map, (int)args->cookie, (void**)&descriptor) ) { MSG_ERR(("_ump_ukk_map_mem: cookie 0x%X not found for this session\n", args->cookie )); diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.c b/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.c index d6b59b7..cc7b8be 100644 --- a/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.c +++ b/drivers/media/video/samsung/ump/common/ump_kernel_descriptor_mapping.c @@ -1,9 +1,9 @@ /* * Copyright (C) 2010-2012 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. */ @@ -65,9 +65,9 @@ void ump_descriptor_mapping_destroy(ump_descriptor_mapping * map) int ump_descriptor_mapping_allocate_mapping(ump_descriptor_mapping * map, void * target) { - int descriptor = -1;/*-EFAULT;*/ - _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RW); - descriptor = _mali_osk_find_first_zero_bit(map->table->usage, map->current_nr_mappings); + int descriptor = -1;/*-EFAULT;*/ + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RW); + descriptor = _mali_osk_find_first_zero_bit(map->table->usage, map->current_nr_mappings); if (descriptor == map->current_nr_mappings) { int nr_mappings_new; @@ -89,8 +89,8 @@ int ump_descriptor_mapping_allocate_mapping(ump_descriptor_mapping * map, void * goto unlock_and_exit; } - _mali_osk_memcpy(new_table->usage, old_table->usage, (sizeof(unsigned long)*map->current_nr_mappings) / BITS_PER_LONG); - _mali_osk_memcpy(new_table->mappings, old_table->mappings, map->current_nr_mappings * sizeof(void*)); + _mali_osk_memcpy(new_table->usage, old_table->usage, (sizeof(unsigned long)*map->current_nr_mappings) / BITS_PER_LONG); + _mali_osk_memcpy(new_table->mappings, old_table->mappings, map->current_nr_mappings * sizeof(void*)); map->table = new_table; map->current_nr_mappings = nr_mappings_new; descriptor_table_free(old_table); @@ -107,10 +107,10 @@ unlock_and_exit: int ump_descriptor_mapping_get(ump_descriptor_mapping * map, int descriptor, void** target) { - int result = -1;/*-EFAULT;*/ - DEBUG_ASSERT(map); - _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO); - if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) + int result = -1;/*-EFAULT;*/ + DEBUG_ASSERT(map); + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO); + if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) { *target = map->table->mappings[descriptor]; result = 0; @@ -122,9 +122,9 @@ int ump_descriptor_mapping_get(ump_descriptor_mapping * map, int descriptor, voi int ump_descriptor_mapping_set(ump_descriptor_mapping * map, int descriptor, void * target) { - int result = -1;/*-EFAULT;*/ - _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO); - if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) + int result = -1;/*-EFAULT;*/ + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RO); + if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) { map->table->mappings[descriptor] = target; result = 0; @@ -135,8 +135,8 @@ int ump_descriptor_mapping_set(ump_descriptor_mapping * map, int descriptor, voi void ump_descriptor_mapping_free(ump_descriptor_mapping * map, int descriptor) { - _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RW); - if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) + _mali_osk_lock_wait(map->lock, _MALI_OSK_LOCKMODE_RW); + if ( (descriptor >= 0) && (descriptor < map->current_nr_mappings) && _mali_osk_test_bit(descriptor, map->table->usage) ) { map->table->mappings[descriptor] = NULL; _mali_osk_clear_nonatomic_bit(descriptor, map->table->usage); @@ -163,4 +163,3 @@ static void descriptor_table_free(ump_descriptor_table * table) { _mali_osk_free(table); } - diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_memory_backend.h b/drivers/media/video/samsung/ump/common/ump_kernel_memory_backend.h index a91ae28..73915ee 100644 --- a/drivers/media/video/samsung/ump/common/ump_kernel_memory_backend.h +++ b/drivers/media/video/samsung/ump/common/ump_kernel_memory_backend.h @@ -1,9 +1,9 @@ /* * Copyright (C) 2010-2012 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. */ @@ -40,6 +40,8 @@ typedef struct ump_memory_backend u32 (*stat)(struct ump_memory_backend *backend); int (*pre_allocate_physical_check)(void *ctx, u32 size); u32 (*adjust_to_mali_phys)(void *ctx, u32 cpu_phys); + void *(*get)(ump_dd_mem *mem, void *args); + void (*set)(ump_dd_mem *mem, void *args); void * ctx; } ump_memory_backend; @@ -47,4 +49,3 @@ ump_memory_backend * ump_memory_backend_create ( void ); void ump_memory_backend_destroy( void ); #endif /*__UMP_KERNEL_MEMORY_BACKEND_H__ */ - diff --git a/drivers/media/video/samsung/ump/common/ump_kernel_ref_drv.c b/drivers/media/video/samsung/ump/common/ump_kernel_ref_drv.c index cd5825e..cb13232 100644 --- a/drivers/media/video/samsung/ump/common/ump_kernel_ref_drv.c +++ b/drivers/media/video/samsung/ump/common/ump_kernel_ref_drv.c @@ -195,3 +195,66 @@ _mali_osk_errcode_t _ump_ukk_allocate( _ump_uk_allocate_s *user_interaction ) return _MALI_OSK_ERR_OK; } + + +UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_meminfo_set(ump_dd_handle memh, void* args) +{ + ump_dd_mem * mem; + ump_secure_id secure_id; + + DEBUG_ASSERT_POINTER(memh); + + secure_id = ump_dd_secure_id_get(memh); + + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + if (0 == ump_descriptor_mapping_get(device.secure_id_map, (int)secure_id, (void**)&mem)) + { + device.backend->set(mem, args); + } + else + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(1, ("Failed to look up mapping in ump_meminfo_set(). ID: %u\n", (ump_secure_id)secure_id)); + return UMP_DD_INVALID; + } + + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + return UMP_DD_SUCCESS; +} + +UMP_KERNEL_API_EXPORT void *ump_dd_meminfo_get(ump_secure_id secure_id, void* args) +{ + ump_dd_mem * mem; + void *result; + + _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + if (0 == ump_descriptor_mapping_get(device.secure_id_map, (int)secure_id, (void**)&mem)) + { + result = device.backend->get(mem, args); + } + else + { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + DBG_MSG(1, ("Failed to look up mapping in ump_meminfo_get(). ID: %u\n", (ump_secure_id)secure_id)); + return UMP_DD_HANDLE_INVALID; + } + + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); + + return result; +} + +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_get_from_vaddr(unsigned long vaddr) +{ + ump_dd_mem * mem; + + DBG_MSG(5, ("Getting handle from Virtual address. vaddr: %u\n", vaddr)); + + _ump_osk_mem_mapregion_get(&mem, vaddr); + + DBG_MSG(1, ("Getting handle's Handle : 0x%8lx\n", mem)); + + return (ump_dd_handle)mem; +} + diff --git a/drivers/media/video/samsung/ump/common/ump_osk.h b/drivers/media/video/samsung/ump/common/ump_osk.h index cae0433..dabdc7f 100644 --- a/drivers/media/video/samsung/ump/common/ump_osk.h +++ b/drivers/media/video/samsung/ump/common/ump_osk.h @@ -1,9 +1,9 @@ /* * Copyright (C) 2010-2012 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. */ @@ -42,6 +42,8 @@ void _ump_osk_mem_mapregion_term( ump_memory_allocation * descriptor ); void _ump_osk_msync( ump_dd_mem * mem, void * virt, u32 offset, u32 size, ump_uk_msync_op op, ump_session_data * session_data ); +void _ump_osk_mem_mapregion_get( ump_dd_mem ** mem, unsigned long vaddr); + #ifdef __cplusplus } #endif diff --git a/drivers/media/video/samsung/ump/common/ump_uk_types.h b/drivers/media/video/samsung/ump/common/ump_uk_types.h index 4fd1ef7..143588d 100644 --- a/drivers/media/video/samsung/ump/common/ump_uk_types.h +++ b/drivers/media/video/samsung/ump/common/ump_uk_types.h @@ -49,7 +49,9 @@ typedef enum _UMP_IOC_SWITCH_HW_USAGE, _UMP_IOC_LOCK, _UMP_IOC_UNLOCK, +#ifdef CONFIG_ION_EXYNOS _UMP_IOC_ION_IMPORT, +#endif }_ump_uk_functions; typedef enum @@ -108,6 +110,7 @@ typedef struct _ump_uk_allocate_s ump_uk_alloc_constraints constraints; /**< Only input to Devicedriver */ } _ump_uk_allocate_s; +#ifdef CONFIG_ION_EXYNOS typedef struct _ump_uk_ion_import_s { void *ctx; /**< [in,out] user-kernel context (trashed on output) */ @@ -116,6 +119,7 @@ typedef struct _ump_uk_ion_import_s u32 size; /**< Input and output. Requested size; input. Returned size; output */ ump_uk_alloc_constraints constraints; /**< Only input to Devicedriver */ } _ump_uk_ion_import_s; +#endif /** * SIZE_GET ([in] u32 secure_id, [out]size ) diff --git a/drivers/media/video/samsung/ump/include/ump_kernel_interface_ref_drv.h b/drivers/media/video/samsung/ump/include/ump_kernel_interface_ref_drv.h index c993746..36c5c9d 100644 --- a/drivers/media/video/samsung/ump/include/ump_kernel_interface_ref_drv.h +++ b/drivers/media/video/samsung/ump/include/ump_kernel_interface_ref_drv.h @@ -1,9 +1,9 @@ /* * Copyright (C) 2010, 2012 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. */ @@ -23,6 +23,10 @@ extern "C" { /** Turn specified physical memory into UMP memory. */ UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_phys_blocks(ump_dd_physical_block * blocks, unsigned long num_blocks); +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_get(ump_secure_id secure_id); +UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_meminfo_set(ump_dd_handle memh, void* args); +UMP_KERNEL_API_EXPORT void *ump_dd_meminfo_get(ump_secure_id secure_id, void* args); +UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_get_from_vaddr(unsigned long vaddr); #ifdef __cplusplus } diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_linux.c b/drivers/media/video/samsung/ump/linux/ump_kernel_linux.c index 158cc88..a358a3c 100644 --- a/drivers/media/video/samsung/ump/linux/ump_kernel_linux.c +++ b/drivers/media/video/samsung/ump/linux/ump_kernel_linux.c @@ -92,7 +92,7 @@ static int ump_file_ioctl(struct inode *inode, struct file *filp, unsigned int c #endif static int ump_file_mmap(struct file * filp, struct vm_area_struct * vma); -#if defined(CONFIG_VIDEO_MALI400MP) +#if defined(CONFIG_VIDEO_UMP) extern int map_errcode( _mali_osk_errcode_t err ); #endif @@ -400,7 +400,7 @@ static int ump_file_ioctl(struct inode *inode, struct file *filp, unsigned int c return err; } -#ifndef CONFIG_VIDEO_MALI400MP +#ifndef CONFIG_VIDEO_UMP int map_errcode( _mali_osk_errcode_t err ) { switch(err) @@ -429,7 +429,7 @@ static int ump_file_mmap(struct file * filp, struct vm_area_struct * vma) /* Validate the session data */ session_data = (struct ump_session_data *)filp->private_data; - if (NULL == session_data) + if (NULL == session_data || NULL == session_data->cookies_map->table->mappings) { MSG_ERR(("mmap() called without any session data available\n")); return -EFAULT; @@ -474,6 +474,9 @@ EXPORT_SYMBOL(ump_dd_phys_blocks_get); EXPORT_SYMBOL(ump_dd_size_get); EXPORT_SYMBOL(ump_dd_reference_add); EXPORT_SYMBOL(ump_dd_reference_release); +EXPORT_SYMBOL(ump_dd_meminfo_get); +EXPORT_SYMBOL(ump_dd_meminfo_set); +EXPORT_SYMBOL(ump_dd_handle_get_from_vaddr); /* Export our own extended kernel space allocator */ EXPORT_SYMBOL(ump_dd_handle_create_from_phys_blocks); diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.c b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.c index 463e609..82c16cc 100644 --- a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.c +++ b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_dedicated.c @@ -1,9 +1,9 @@ /* * Copyright (C) 2010-2012 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. */ @@ -108,6 +108,8 @@ ump_memory_backend * ump_block_allocator_create(u32 base_address, u32 size) backend->stat = block_allocator_stat; backend->pre_allocate_physical_check = NULL; backend->adjust_to_mali_phys = NULL; + backend->get = NULL; + backend->set = NULL; return backend; } diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c index fc3afa8..8f6a9b3 100644 --- a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c +++ b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_os.c @@ -77,6 +77,8 @@ ump_memory_backend * ump_os_memory_backend_create(const int max_allocation) backend->stat = os_stat; backend->pre_allocate_physical_check = NULL; backend->adjust_to_mali_phys = NULL; + backend->get = NULL; + backend->set = NULL; return backend; } @@ -134,19 +136,20 @@ static int os_allocate(void* ctx, ump_dd_mem * descriptor) return 0; /* failure */ } - while (left > 0 && ((info->num_pages_allocated + pages_allocated) < info->num_pages_max)) + while (left > 0) { struct page * new_page; if (is_cached) { - new_page = alloc_page(GFP_HIGHUSER | __GFP_ZERO | __GFP_REPEAT | __GFP_NOWARN); + new_page = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NORETRY | __GFP_NOWARN ); } else { - new_page = alloc_page(GFP_HIGHUSER | __GFP_ZERO | __GFP_REPEAT | __GFP_NOWARN | __GFP_COLD); + new_page = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NORETRY | __GFP_NOWARN | __GFP_COLD); } if (NULL == new_page) { + MSG_ERR(("UMP memory allocated: Out of Memory !!\n")); break; } @@ -180,6 +183,8 @@ static int os_allocate(void* ctx, ump_dd_mem * descriptor) if (left) { DBG_MSG(1, ("Failed to allocate needed pages\n")); + DBG_MSG(1, ("UMP memory allocated: %d kB Configured maximum OS memory usage: %d kB\n", + (pages_allocated * _MALI_OSK_CPU_PAGE_SIZE)/1024, (info->num_pages_max* _MALI_OSK_CPU_PAGE_SIZE)/1024)); while(pages_allocated) { diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.c b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.c new file mode 100644 index 0000000..46797ea --- /dev/null +++ b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.c @@ -0,0 +1,290 @@ +/* + * Copyright (C) 2010-2012 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. + */ + +/* create by boojin.kim@samsung.com */ +/* needed to detect kernel version specific code */ +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +#include +#else /* pre 2.6.26 the file was in the arch specific location */ +#include +#endif + +#include +#include +#include +#include +#include +#include "ump_kernel_common.h" +#include "ump_kernel_memory_backend.h" +#include "ump_kernel_interface_ref_drv.h" +#include "ump_kernel_memory_backend_vcm.h" +#include "../common/ump_uk_types.h" +#include +#include +#include + +#define UMP_REF_DRV_UK_VCM_DEV_G2D 12 + +typedef struct ump_vcm { + struct vcm *vcm; + struct vcm_res *vcm_res; + unsigned int dev_id; +} ump_vcm; + +typedef struct vcm_allocator { + struct semaphore mutex; + u32 num_vcm_blocks; +} vcm_allocator; + +static void ump_vcm_free(void* ctx, ump_dd_mem * descriptor); +static int ump_vcm_allocate(void* ctx, ump_dd_mem * descriptor); +static void *vcm_res_get(ump_dd_mem *mem, void* args); +static void vcm_attr_set(ump_dd_mem *mem, void* args); +static int vcm_mem_allocator(vcm_allocator *info, ump_dd_mem *descriptor); +static void vcm_memory_backend_destroy(ump_memory_backend * backend); + + +/* + * Create VCM memory backend + */ +ump_memory_backend * ump_vcm_memory_backend_create(const int max_allocation) +{ + ump_memory_backend * backend; + vcm_allocator * info; + + info = kmalloc(sizeof(vcm_allocator), GFP_KERNEL); + if (NULL == info) + { + return NULL; + } + + info->num_vcm_blocks = 0; + + + sema_init(&info->mutex, 1); + + backend = kmalloc(sizeof(ump_memory_backend), GFP_KERNEL); + if (NULL == backend) + { + kfree(info); + return NULL; + } + + backend->ctx = info; + backend->allocate = ump_vcm_allocate; + backend->release = ump_vcm_free; + backend->shutdown = vcm_memory_backend_destroy; + backend->pre_allocate_physical_check = NULL; + backend->adjust_to_mali_phys = NULL; + + backend->get = vcm_res_get; + backend->set = vcm_attr_set; + + + return backend; +} + +/* + * Destroy specified VCM memory backend + */ +static void vcm_memory_backend_destroy(ump_memory_backend * backend) +{ + vcm_allocator * info = (vcm_allocator*)backend->ctx; +#if 0 + DBG_MSG_IF(1, 0 != info->num_pages_allocated, ("%d pages still in use during shutdown\n", info->num_pages_allocated)); +#endif + kfree(info); + kfree(backend); +} + +/* + * Allocate UMP memory + */ +static int ump_vcm_allocate(void *ctx, ump_dd_mem * descriptor) +{ + int ret; /* success */ + vcm_allocator *info; + struct ump_vcm *ump_vcm; + + BUG_ON(!descriptor); + BUG_ON(!ctx); + + info = (vcm_allocator*)ctx; + + ump_vcm = kmalloc(sizeof(struct ump_vcm), GFP_KERNEL); + if (NULL == ump_vcm) + { + return 0; + } + + ump_vcm->dev_id = (int)descriptor->backend_info & ~UMP_REF_DRV_UK_CONSTRAINT_USE_CACHE; + + if(ump_vcm->dev_id == UMP_REF_DRV_UK_CONSTRAINT_NONE) { /* None */ + ump_vcm->dev_id = UMP_REF_DRV_UK_VCM_DEV_G2D; /* this ID is G2D */ + } + else if(ump_vcm->dev_id == UMP_REF_DRV_UK_CONSTRAINT_PHYSICALLY_LINEAR) { /* Physical Linear */ + return 0; + } + else { /* Other VCM */ + ump_vcm->dev_id -= 2; + } + + DBG_MSG(5, ("Device ID for VCM : %d\n", ump_vcm->dev_id)); + ump_vcm->vcm = vcm_find_vcm(ump_vcm->dev_id); + + if (!ump_vcm->vcm) + { + return 0; + } + descriptor->backend_info = (void*)ump_vcm; + + if (down_interruptible(&info->mutex)) { + DBG_MSG(1, ("Failed to get mutex in ump_vcm_allocate\n")); + return 0; /* failure */ + } + + ret = vcm_mem_allocator(info, descriptor); + up(&info->mutex); + + return ret; /* success */ +} + +static int vcm_mem_allocator(vcm_allocator *info, ump_dd_mem *descriptor) +{ + unsigned long num_blocks; + int i; + struct vcm_phys *phys; + struct vcm_phys_part *part; + int size_total = 0; + struct ump_vcm *ump_vcm; + + ump_vcm = (struct ump_vcm*)descriptor->backend_info; + + ump_vcm->vcm_res = + vcm_make_binding(ump_vcm->vcm, descriptor->size_bytes, + ump_vcm->dev_id, 0); + + phys = ump_vcm->vcm_res->phys; + part = phys->parts; + num_blocks = phys->count; + + DBG_MSG(5, + ("Allocating page array. Size: %lu, VCM Reservation : 0x%x\n", + phys->count * sizeof(ump_dd_physical_block), + ump_vcm->vcm_res->start)); + + /* Now, make a copy of the block information supplied by the user */ + descriptor->block_array = + (ump_dd_physical_block *) vmalloc(sizeof(ump_dd_physical_block) * + num_blocks); + + if (NULL == descriptor->block_array) { + vfree(descriptor->block_array); + DBG_MSG(1, ("Could not allocate a mem handle for function.\n")); + return 0; /* failure */ + } + + for (i = 0; i < num_blocks; i++) { + descriptor->block_array[i].addr = part->start; + descriptor->block_array[i].size = part->size; + + dmac_unmap_area(phys_to_virt(part->start), part->size, DMA_FROM_DEVICE); + outer_inv_range(part->start, part->start + part->size); + + ++part; + size_total += descriptor->block_array[i].size; + DBG_MSG(6, + ("UMP memory created with VCM. addr 0x%x, size: 0x%x\n", + descriptor->block_array[i].addr, + descriptor->block_array[i].size)); + } + + descriptor->size_bytes = size_total; + descriptor->nr_blocks = num_blocks; + descriptor->ctx = NULL; + + info->num_vcm_blocks += num_blocks; + return 1; +} + +/* + * Free specified UMP memory + */ +static void ump_vcm_free(void *ctx, ump_dd_mem * descriptor) +{ + struct ump_vcm *ump_vcm; + vcm_allocator *info; + + BUG_ON(!descriptor); + BUG_ON(!ctx); + + ump_vcm = (struct ump_vcm*)descriptor->backend_info; + info = (vcm_allocator*)ctx; + + BUG_ON(descriptor->nr_blocks > info->num_vcm_blocks); + + if (down_interruptible(&info->mutex)) { + DBG_MSG(1, ("Failed to get mutex in ump_vcm_free\n")); + return; + } + + DBG_MSG(5, ("Releasing %lu VCM pages\n", descriptor->nr_blocks)); + + info->num_vcm_blocks -= descriptor->nr_blocks; + + up(&info->mutex); + + DBG_MSG(6, ("Freeing physical page by VCM\n")); + vcm_destroy_binding(ump_vcm->vcm_res); + ump_vcm->vcm = NULL; + ump_vcm->vcm_res = NULL; + + kfree(ump_vcm); + vfree(descriptor->block_array); +} + +static void *vcm_res_get(ump_dd_mem *mem, void *args) +{ + struct ump_vcm *ump_vcm; + enum vcm_dev_id vcm_id; + + ump_vcm = (struct ump_vcm*)mem->backend_info; + vcm_id = (enum vcm_dev_id)args; + + if (vcm_reservation_in_vcm + (vcm_find_vcm(vcm_id), ump_vcm->vcm_res) + == S5PVCM_RES_NOT_IN_VCM) + return NULL; + else + return ump_vcm->vcm_res; +} + +static void vcm_attr_set(ump_dd_mem *mem, void *args) +{ + struct ump_vcm *ump_vcm, *ump_vcmh; + + ump_vcm = (struct ump_vcm*)args; + + ump_vcmh = kmalloc(sizeof(struct ump_vcm), GFP_KERNEL); + if (NULL == ump_vcmh) + { + return; + } + + ump_vcmh->dev_id = ump_vcm->dev_id; + ump_vcmh->vcm = ump_vcm->vcm; + ump_vcmh->vcm_res = ump_vcm->vcm_res; + + mem->backend_info= (void*)ump_vcmh; + + return; +} diff --git a/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.h b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.h new file mode 100644 index 0000000..c1ead0d --- /dev/null +++ b/drivers/media/video/samsung/ump/linux/ump_kernel_memory_backend_vcm.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2010-2012 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 ump_kernel_memory_backend_vcm.h + */ + +#ifndef __UMP_KERNEL_MEMORY_BACKEND_VCM_H__ +#define __UMP_KERNEL_MEMORY_BACKEND_VCM_H__ + +#include "ump_kernel_memory_backend.h" + +ump_memory_backend * ump_vcm_memory_backend_create(const int max_allocation); + +#endif /* __UMP_KERNEL_MEMORY_BACKEND_VCM_H__ */ diff --git a/drivers/media/video/samsung/ump/linux/ump_memory_backend.c b/drivers/media/video/samsung/ump/linux/ump_memory_backend.c index 23357f4..d067cfe 100644 --- a/drivers/media/video/samsung/ump/linux/ump_memory_backend.c +++ b/drivers/media/video/samsung/ump/linux/ump_memory_backend.c @@ -56,6 +56,13 @@ ump_memory_backend* ump_memory_backend_create ( void ) DBG_MSG(2, ("Using OS memory backend, allocation limit: %d\n", ump_memory_size)); backend = ump_os_memory_backend_create(ump_memory_size); } +#ifdef CONFIG_UMP_VCM_ALLOC + else if (2 == ump_backend) + { + DBG_MSG(2, ("Using VCM memory backend, allocation limit: %d\n", ump_memory_size)); + backend = ump_vcm_memory_backend_create(ump_memory_size); + } +#endif return backend; } diff --git a/drivers/media/video/samsung/ump/linux/ump_osk_low_level_mem.c b/drivers/media/video/samsung/ump/linux/ump_osk_low_level_mem.c index 0073c4d..8ae169a 100644 --- a/drivers/media/video/samsung/ump/linux/ump_osk_low_level_mem.c +++ b/drivers/media/video/samsung/ump/linux/ump_osk_low_level_mem.c @@ -23,6 +23,7 @@ #include /* kernel module definitions */ #include #include +#include #include #include @@ -210,6 +211,95 @@ _mali_osk_errcode_t _ump_osk_mem_mapregion_map( ump_memory_allocation * descript return retval; } +static u32 _ump_osk_virt_to_phys_start(ump_dd_mem * mem, u32 start, u32 address, int *index) +{ + int i; + u32 offset = address - start; + ump_dd_physical_block *block; + u32 sum = 0; + + for (i=0; inr_blocks; i++) { + block = &mem->block_array[i]; + sum += block->size; + if (sum > offset) { + *index = i; + DBG_MSG(3, ("_ump_osk_virt_to_phys : index : %d, virtual 0x%x, phys 0x%x\n", i, address, (u32)block->addr + offset - (sum -block->size))); + return (u32)block->addr + offset - (sum -block->size); + } + } + + return _MALI_OSK_ERR_FAULT; +} + +static u32 _ump_osk_virt_to_phys_end(ump_dd_mem * mem, u32 start, u32 address, int *index) +{ + int i; + u32 offset = address - start; + ump_dd_physical_block *block; + u32 sum = 0; + + for (i=0; inr_blocks; i++) { + block = &mem->block_array[i]; + sum += block->size; + if (sum >= offset) { + *index = i; + DBG_MSG(3, ("_ump_osk_virt_to_phys : index : %d, virtual 0x%x, phys 0x%x\n", i, address, (u32)block->addr + offset - (sum -block->size))); + return (u32)block->addr + offset - (sum -block->size); + } + } + + return _MALI_OSK_ERR_FAULT; +} + +static void _ump_osk_msync_with_virt(ump_dd_mem * mem, ump_uk_msync_op op, u32 start, u32 address, u32 size) +{ + int start_index, end_index; + u32 start_p, end_p; + + DBG_MSG(3, ("Cache flush with user virtual address. start : 0x%x, end : 0x%x, address 0x%x, size 0x%x\n", start, start+mem->size_bytes, address, size)); + + start_p = _ump_osk_virt_to_phys_start(mem, start, address, &start_index); + end_p = _ump_osk_virt_to_phys_end(mem, start, address+size, &end_index); + + if (start_index==end_index) { + if (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE) + outer_flush_range(start_p, end_p); + else + outer_clean_range(start_p, end_p); + } else { + ump_dd_physical_block *block; + int i; + + for (i=start_index; i<=end_index; i++) { + block = &mem->block_array[i]; + + if (i == start_index) { + if (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE) { + outer_flush_range(start_p, block->addr+block->size); + } else { + outer_clean_range(start_p, block->addr+block->size); + } + } + else if (i == end_index) { + if (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE) { + outer_flush_range(block->addr, end_p); + } else { + outer_clean_range(block->addr, end_p); + } + break; + } + else { + if (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE) { + outer_flush_range(block->addr, block->addr+block->size); + } else { + outer_clean_range(block->addr, block->addr+block->size); + } + } + } + } + return; +} + static void level1_cache_flush_all(void) { DBG_MSG(4, ("UMP[xx] Flushing complete L1 cache\n")); @@ -229,7 +319,11 @@ void _ump_osk_msync( ump_dd_mem * mem, void * virt, u32 offset, u32 size, ump_uk end_v = (void *)(start_v + size - 1); /* There is no dmac_clean_range, so the L1 is always flushed, * also for UMP_MSYNC_CLEAN. */ - dmac_flush_range(start_v, end_v); + if (size >= SZ_64K) + flush_all_cpu_caches(); + else + dmac_flush_range(start_v, end_v); + DBG_MSG(3, ("UMP[%02u] Flushing CPU L1 Cache. Cpu address: %x-%x\n", mem->secure_id, start_v,end_v)); } else @@ -278,6 +372,14 @@ void _ump_osk_msync( ump_dd_mem * mem, void * virt, u32 offset, u32 size, ump_uk /* Flush L2 using physical addresses, block for block. */ + if ((virt!=NULL) && (mem->size_bytes >= SZ_1M)) { + if (op == _UMP_UK_MSYNC_CLEAN) + outer_clean_all(); + else if ((op == _UMP_UK_MSYNC_INVALIDATE) || (op == _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE)) + outer_flush_all(); + return; + } + for (i=0 ; i < mem->nr_blocks; i++) { u32 start_p, end_p; @@ -344,3 +446,40 @@ void _ump_osk_msync( ump_dd_mem * mem, void * virt, u32 offset, u32 size, ump_uk return; } + +void _ump_osk_mem_mapregion_get( ump_dd_mem ** mem, unsigned long vaddr) +{ + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + ump_vma_usage_tracker * vma_usage_tracker; + ump_memory_allocation *descriptor; + ump_dd_handle handle; + + DBG_MSG(3, ("_ump_osk_mem_mapregion_get: vaddr 0x%08lx\n", vaddr)); + + down_read(&mm->mmap_sem); + vma = find_vma(mm, vaddr); + up_read(&mm->mmap_sem); + if(!vma) + { + DBG_MSG(3, ("Not found VMA\n")); + *mem = NULL; + return; + } + DBG_MSG(4, ("Get vma: 0x%08lx vma->vm_start: 0x%08lx\n", (unsigned long)vma, vma->vm_start)); + + vma_usage_tracker = (struct ump_vma_usage_tracker*)vma->vm_private_data; + if(vma_usage_tracker == NULL) + { + DBG_MSG(3, ("Not found vma_usage_tracker\n")); + *mem = NULL; + return; + } + + descriptor = (struct ump_memory_allocation*)vma_usage_tracker->descriptor; + handle = (ump_dd_handle)descriptor->handle; + + DBG_MSG(3, ("Get handle: 0x%08lx\n", handle)); + *mem = (ump_dd_mem*)handle; +} + diff --git a/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.c b/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.c index 9692e5b..a6691ed 100644 --- a/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.c +++ b/drivers/media/video/samsung/ump/linux/ump_ukk_ref_wrappers.c @@ -89,7 +89,6 @@ int ump_allocate_wrapper(u32 __user * argument, struct ump_session_data * sessi return 0; /* success */ } - #ifdef CONFIG_ION_EXYNOS /* * IOCTL operation; Import fd to UMP memory @@ -130,6 +129,12 @@ int ump_ion_import_wrapper(u32 __user * argument, struct ump_session_data * ses sg_ion = ion_map_dma(ion_client_ump,ion_hnd); blocks = (ump_dd_physical_block*)_mali_osk_malloc(sizeof(ump_dd_physical_block)*1024); + + if (NULL == blocks) { + MSG_ERR(("Failed to allocate blocks in ump_ioctl_allocate()\n")); + return -ENOMEM; + } + sg = sg_ion; do { blocks[i].addr = sg_phys(sg); -- cgit v1.1