From f8e96dfd0e19c86074d4ce5cf1d2069b42619e80 Mon Sep 17 00:00:00 2001 From: Chunsang Jeong Date: Sat, 13 Aug 2011 23:11:20 +0900 Subject: Update with r2p2-03release at 17th, Jul from malideveloper.com Signed-off-by: Chunsang Jeong --- drivers/gpu/arm/mali/Kconfig | 16 +- drivers/gpu/arm/mali/Makefile | 16 +- drivers/gpu/arm/mali/common/mali_kernel_GP2.c | 45 +++- drivers/gpu/arm/mali/common/mali_kernel_MALI200.c | 45 +++- drivers/gpu/arm/mali/common/mali_kernel_core.c | 79 ++++-- drivers/gpu/arm/mali/common/mali_kernel_core.h | 12 +- drivers/gpu/arm/mali/common/mali_kernel_l2_cache.c | 13 +- .../gpu/arm/mali/common/mali_kernel_mem_buddy.c | 3 + drivers/gpu/arm/mali/common/mali_kernel_mem_mmu.c | 284 ++++++++++++++++----- .../gpu/arm/mali/common/mali_kernel_rendercore.c | 170 +++++++++++- .../gpu/arm/mali/common/mali_kernel_rendercore.h | 15 ++ .../gpu/arm/mali/common/mali_kernel_subsystem.h | 13 + .../gpu/arm/mali/common/mali_kernel_utilization.c | 24 +- drivers/gpu/arm/mali/common/mali_kernel_vsync.c | 29 +++ drivers/gpu/arm/mali/common/mali_osk.h | 43 +++- drivers/gpu/arm/mali/common/mali_osk_list.h | 2 +- drivers/gpu/arm/mali/common/mali_uk_types.h | 42 ++- drivers/gpu/arm/mali/common/mali_ukk.h | 17 +- drivers/gpu/arm/mali/common/pmm/mali_pmm.c | 187 +++++++++----- drivers/gpu/arm/mali/common/pmm/mali_pmm.h | 33 ++- drivers/gpu/arm/mali/common/pmm/mali_pmm_policy.h | 16 +- .../mali/common/pmm/mali_pmm_policy_jobcontrol.c | 18 +- .../mali/common/pmm/mali_pmm_policy_jobcontrol.h | 4 +- drivers/gpu/arm/mali/common/pmm/mali_pmm_state.c | 33 +++ drivers/gpu/arm/mali/common/pmm/mali_pmm_state.h | 29 ++- .../mali/linux/license/gpl/mali_kernel_license.h | 2 +- .../gpu/arm/mali/linux/mali_device_pause_resume.c | 18 +- drivers/gpu/arm/mali/linux/mali_kernel_ioctl.h | 2 + drivers/gpu/arm/mali/linux/mali_kernel_linux.c | 137 +++++----- drivers/gpu/arm/mali/linux/mali_kernel_linux.h | 14 + drivers/gpu/arm/mali/linux/mali_kernel_pm.c | 149 ++--------- drivers/gpu/arm/mali/linux/mali_kernel_sysfs.c | 137 ++++++++++ drivers/gpu/arm/mali/linux/mali_kernel_sysfs.h | 30 +++ .../arm/mali/linux/mali_linux_dvfs_pause_resume.c | 72 ++++++ drivers/gpu/arm/mali/linux/mali_linux_pm.h | 8 +- .../gpu/arm/mali/linux/mali_linux_pm_testsuite.h | 4 - drivers/gpu/arm/mali/linux/mali_osk_irq.c | 15 +- drivers/gpu/arm/mali/linux/mali_osk_locks.c | 34 +-- .../gpu/arm/mali/linux/mali_osk_low_level_mem.c | 276 +++++++++++++------- drivers/gpu/arm/mali/linux/mali_osk_mali.c | 7 +- drivers/gpu/arm/mali/linux/mali_osk_misc.c | 12 + drivers/gpu/arm/mali/linux/mali_osk_notification.c | 32 +-- drivers/gpu/arm/mali/linux/mali_osk_pm.c | 18 +- drivers/gpu/arm/mali/linux/mali_osk_timers.c | 1 - drivers/gpu/arm/mali/linux/mali_ukk_core.c | 2 +- drivers/gpu/arm/mali/linux/mali_ukk_gp.c | 2 +- drivers/gpu/arm/mali/linux/mali_ukk_vsync.c | 41 +++ drivers/gpu/arm/mali/linux/mali_ukk_wrappers.h | 2 + drivers/gpu/arm/mali/platform/mali_platform.h | 18 +- .../arm/mali/timestamp-arm11-cc/mali_timestamp.h | 2 +- .../arm/mali/timestamp-default/mali_timestamp.h | 2 +- drivers/gpu/arm/ump/Kconfig | 2 +- drivers/gpu/arm/ump/Makefile | 2 +- drivers/gpu/arm/ump/common/ump_kernel_api.c | 45 +++- drivers/gpu/arm/ump/common/ump_kernel_common.c | 6 - drivers/gpu/arm/ump/common/ump_osk.h | 2 +- .../arm/ump/linux/license/gpl/ump_kernel_license.h | 2 +- .../linux/ump_kernel_memory_backend_dedicated.c | 1 + .../arm/ump/linux/ump_kernel_memory_backend_os.c | 5 +- drivers/gpu/arm/ump/linux/ump_osk_low_level_mem.c | 111 ++++++-- drivers/gpu/arm/ump/linux/ump_ukk_wrappers.c | 4 +- 61 files changed, 1718 insertions(+), 687 deletions(-) create mode 100644 drivers/gpu/arm/mali/common/mali_kernel_vsync.c create mode 100644 drivers/gpu/arm/mali/linux/mali_kernel_sysfs.c create mode 100644 drivers/gpu/arm/mali/linux/mali_kernel_sysfs.h create mode 100644 drivers/gpu/arm/mali/linux/mali_linux_dvfs_pause_resume.c mode change 100755 => 100644 drivers/gpu/arm/mali/linux/mali_osk_notification.c mode change 100755 => 100644 drivers/gpu/arm/mali/linux/mali_osk_pm.c mode change 100755 => 100644 drivers/gpu/arm/mali/linux/mali_osk_timers.c mode change 100755 => 100644 drivers/gpu/arm/mali/linux/mali_ukk_core.c create mode 100644 drivers/gpu/arm/mali/linux/mali_ukk_vsync.c mode change 100755 => 100644 drivers/gpu/arm/mali/platform/mali_platform.h diff --git a/drivers/gpu/arm/mali/Kconfig b/drivers/gpu/arm/mali/Kconfig index dd9cb7ce977..e17f277ff68 100644 --- a/drivers/gpu/arm/mali/Kconfig +++ b/drivers/gpu/arm/mali/Kconfig @@ -18,24 +18,10 @@ config USING_UMP ---help--- Using UMP for Mali memory. -config ONLY_ZBT - bool "Only ZBT" - depends on MALI400MP - default "0" - ---help--- - Only ZBT, add here more - -config USING_ZBT - bool "Using ZBT" - depends on MALI400MP - default "1" - ---help--- - This support ZBT add here more - config USING_OS_MEMORY bool "Using OS memory" depends on MALI400MP - default "0" + default "1" ---help--- This enables for Mali to use OS memory. diff --git a/drivers/gpu/arm/mali/Makefile b/drivers/gpu/arm/mali/Makefile index 84817064db0..1f955dd7219 100755 --- a/drivers/gpu/arm/mali/Makefile +++ b/drivers/gpu/arm/mali/Makefile @@ -31,10 +31,6 @@ ifeq ($(CONFIG_USING_MMU),y) USING_MMU=1 endif -ifeq ($(CONFIG_ONLY_ZBT),y) -ONLY_ZBT =1 -endif - ifeq ($(CONFIG_USING_OS_MEMORY),y) USING_OS_MEMORY=1 endif @@ -63,13 +59,12 @@ endif ARCH ?= arm USING_MMU ?= 1 USING_UMP ?= 0 -ONLY_ZBT ?= 0 -USING_ZBT ?= 1 USING_OS_MEMORY ?= 0 USING_PMM ?= 0 USING_GPU_UTILIZATION ?= 0 USING_MALI_RUN_TIME_PM ?= 0 USING_MALI_PMM_TESTSUITE ?= 0 +OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB ?= 6 USING_PROFILING ?= 0 TIMESTAMP ?= default TARGET_PLATFORM ?= default @@ -83,16 +78,18 @@ endif submodule_enabled = $(shell gcc $(DEFINES) -E $(MALICONFIGDIR)/config.h | grep type | grep -c $(2)) # Set up our defines, which will be passed to gcc -DEFINES += -DUSING_ZBT=$(USING_ZBT) DEFINES += -DUSING_OS_MEMORY=$(USING_OS_MEMORY) DEFINES += -DUSING_MMU=$(USING_MMU) DEFINES += -DUSING_UMP=$(USING_UMP) -DEFINES += -DONLY_ZBT=$(ONLY_ZBT) DEFINES += -D_MALI_OSK_SPECIFIC_INDIRECT_MMAP DEFINES += -DMALI_TIMELINE_PROFILING_ENABLED=$(USING_PROFILING) DEFINES += -DMALI_POWER_MGMT_TEST_SUITE=$(USING_MALI_PMM_TESTSUITE) DEFINES += -DMALI_PMM_RUNTIME_JOB_CONTROL_ON=$(USING_MALI_RUN_TIME_PM) +# MALI_STATE_TRACKING is only supported on Linux kernels from version 2.6.32. +DEFINES += -DMALI_STATE_TRACKING=1 +DEFINES += -DMALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB=$(OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB) + ifneq ($(call submodule_enabled, $M, PMU),0) MALI_PLATFORM_FILE = platform/mali400-pmu/mali_platform.o else @@ -168,6 +165,9 @@ mali-y := \ $(OSKOS)/mali_osk_indir_mmap.o \ common/mali_kernel_rendercore.o \ common/mali_kernel_descriptor_mapping.o \ + common/mali_kernel_vsync.o \ + linux/mali_ukk_vsync.o \ + linux/mali_kernel_sysfs.o \ $(MALI_PLATFORM_FILE) \ $(OSKFILES) \ $(UKKFILES) diff --git a/drivers/gpu/arm/mali/common/mali_kernel_GP2.c b/drivers/gpu/arm/mali/common/mali_kernel_GP2.c index d6ce174abb5..552b57efcb4 100755 --- a/drivers/gpu/arm/mali/common/mali_kernel_GP2.c +++ b/drivers/gpu/arm/mali/common/mali_kernel_GP2.c @@ -101,6 +101,9 @@ static _mali_osk_errcode_t maligp_renderunit_create(_mali_osk_resource_t * resou #if USING_MMU static void maligp_subsystem_broadcast_notification(mali_core_notification_message message, u32 data); #endif +#if MALI_STATE_TRACKING +u32 maligp_subsystem_dump_state(char *buf, u32 size); +#endif /* Internal support functions */ static _mali_osk_errcode_t maligp_core_version_legal( mali_core_renderunit *core ); @@ -156,6 +159,9 @@ struct mali_kernel_subsystem mali_subsystem_gp2= #else NULL, #endif +#if MALI_STATE_TRACKING + maligp_subsystem_dump_state, /* dump_state */ +#endif } ; static mali_core_subsystem subsystem_maligp ; @@ -698,6 +704,9 @@ static _mali_osk_errcode_t subsystem_maligp_start_job(mali_core_job * job, mali_ subsystem_flush_mapped_mem_cache(); MALI_DEBUG_PRINT(4, ("Mali GP: STARTING GP WITH CMD: 0x%x\n", startcmd)); +#if MALI_STATE_TRACKING + _mali_osk_atomic_inc(&job->session->jobs_started); +#endif /* This is the command that starts the Core */ mali_core_renderunit_register_write(core, @@ -827,6 +836,9 @@ static int subsystem_maligp_irq_handler_bottom_half(mali_core_renderunit* core) #endif MALI_DEBUG_PRINT(2, ("Mali GP: Job aborted - userspace would not provide more heap memory.\n")); +#if MALI_STATE_TRACKING + _mali_osk_atomic_inc(&job->session->jobs_ended); +#endif return JOB_STATUS_END_OOM; /* Core is ready for more jobs.*/ } /* finished ? */ @@ -887,6 +899,9 @@ static int subsystem_maligp_irq_handler_bottom_half(mali_core_renderunit* core) mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, MALIGP2_REG_VAL_IRQ_MASK_ALL); +#if MALI_STATE_TRACKING + _mali_osk_atomic_inc(&job->session->jobs_ended); +#endif return JOB_STATUS_END_SUCCESS; /* core idle */ } /* sw watchdog timeout handling or time to do hang checking ? */ @@ -916,6 +931,11 @@ static int subsystem_maligp_irq_handler_bottom_half(mali_core_renderunit* core) #ifdef DEBUG maligp_print_regs(2, core); #endif + +#if MALI_STATE_TRACKING + _mali_osk_atomic_inc(&job->session->jobs_ended); +#endif + return JOB_STATUS_END_HANG; } /* if hang timeout checking was enabled and we detected progress, will be fall down to this check */ @@ -1016,6 +1036,9 @@ static int subsystem_maligp_irq_handler_bottom_half(mali_core_renderunit* core) MALI_DEBUG_PRINT(1, ("Mali GP: Registers Before reset:\n")); maligp_print_regs(1, core); #endif +#if MALI_STATE_TRACKING + _mali_osk_atomic_inc(&job->session->jobs_ended); +#endif return JOB_STATUS_END_UNKNOWN_ERR; } } @@ -1026,7 +1049,7 @@ to a created mali_core_job object with the data given from userspace */ static _mali_osk_errcode_t subsystem_maligp_get_new_job_from_user(struct mali_core_session * session, void * argument) { maligp_job *jobgp; - mali_core_job *job; + mali_core_job *job = NULL; mali_core_job *previous_replaced_job; _mali_osk_errcode_t err = _MALI_OSK_ERR_OK; _mali_uk_gp_start_job_s * user_ptr_job_input; @@ -1148,6 +1171,16 @@ function_exit: { _mali_osk_free(jobgp); } +#if MALI_STATE_TRACKING + if (_MALI_UK_START_JOB_STARTED==user_ptr_job_input->status) + { + if(job) + { + job->job_nr=_mali_osk_atomic_inc_return(&session->jobs_received); + } + } +#endif + MALI_ERROR(err); } @@ -1275,6 +1308,9 @@ static void subsystem_maligp_return_job_to_user( mali_core_job * job, mali_subsy job_out->perf_counter_l2_val1 = jobgp->perf_counter_l2_val1; #endif +#if MALI_STATE_TRACKING + _mali_osk_atomic_inc(&session->jobs_returned); +#endif _mali_osk_notification_queue_send( session->notification_queue, jobgp->notification_obj); jobgp->notification_obj = NULL; @@ -1403,3 +1439,10 @@ _mali_osk_errcode_t maligp_signal_power_down( mali_bool immediate_only ) } #endif + +#if MALI_STATE_TRACKING +u32 maligp_subsystem_dump_state(char *buf, u32 size) +{ + return mali_core_renderunit_dump_state(&subsystem_maligp, buf, size); +} +#endif diff --git a/drivers/gpu/arm/mali/common/mali_kernel_MALI200.c b/drivers/gpu/arm/mali/common/mali_kernel_MALI200.c index c1eb8fed32d..75e6af78978 100755 --- a/drivers/gpu/arm/mali/common/mali_kernel_MALI200.c +++ b/drivers/gpu/arm/mali/common/mali_kernel_MALI200.c @@ -93,6 +93,9 @@ static _mali_osk_errcode_t mali200_renderunit_create(_mali_osk_resource_t * reso #if USING_MMU static void mali200_subsystem_broadcast_notification(mali_core_notification_message message, u32 data); #endif +#if MALI_STATE_TRACKING +u32 mali200_subsystem_dump_state(char *buf, u32 size); +#endif /* Internal support functions */ static _mali_osk_errcode_t mali200_core_version_legal( mali_core_renderunit *core ); @@ -135,7 +138,10 @@ struct mali_kernel_subsystem mali_subsystem_mali200= #if USING_MMU mali200_subsystem_broadcast_notification, /* broadcast_notification */ #else - NULL + NULL, +#endif +#if MALI_STATE_TRACKING + mali200_subsystem_dump_state, /* dump_state */ #endif } ; @@ -626,6 +632,10 @@ static _mali_osk_errcode_t subsystem_mali200_start_job(mali_core_job * job, mali subsystem_flush_mapped_mem_cache(); _mali_osk_mem_barrier(); +#if MALI_STATE_TRACKING + _mali_osk_atomic_inc(&job->session->jobs_started); +#endif + /* This is the command that starts the Core */ mali_core_renderunit_register_write( core, @@ -751,6 +761,9 @@ static int subsystem_mali200_irq_handler_bottom_half(struct mali_core_renderunit } +#if MALI_STATE_TRACKING + _mali_osk_atomic_inc(&job->session->jobs_ended); +#endif return JOB_STATUS_END_SUCCESS; /* reschedule */ } /* Overall SW watchdog timeout or (time to do hang checking and progress detected)? */ @@ -765,6 +778,11 @@ static int subsystem_mali200_irq_handler_bottom_half(struct mali_core_renderunit /* no progress detected, killed by the watchdog */ MALI_DEBUG_PRINT(2, ("M200: SW-Timeout Rawstat: 0x%x Tile_addr: 0x%x Status: 0x%x.\n", irq_readout ,current_tile_addr ,core_status) ); /* In this case will the system outside cleanup and reset the core */ + +#if MALI_STATE_TRACKING + _mali_osk_atomic_inc(&job->session->jobs_ended); +#endif + return JOB_STATUS_END_HANG; } /* HW watchdog triggered or an existing hang check passed? */ @@ -808,6 +826,9 @@ static int subsystem_mali200_irq_handler_bottom_half(struct mali_core_renderunit (void)bus_error; } +#if MALI_STATE_TRACKING + _mali_osk_atomic_inc(&job->session->jobs_ended); +#endif return JOB_STATUS_END_UNKNOWN_ERR; /* reschedule */ } } @@ -818,7 +839,7 @@ to a created mali_core_job object with the data given from userspace */ static _mali_osk_errcode_t subsystem_mali200_get_new_job_from_user(struct mali_core_session * session, void * argument) { mali200_job *job200; - mali_core_job *job; + mali_core_job *job = NULL; mali_core_job *previous_replaced_job; _mali_osk_errcode_t err = _MALI_OSK_ERR_OK; _mali_uk_pp_start_job_s * user_ptr_job_input; @@ -948,6 +969,16 @@ function_exit: { _mali_osk_free(job200); } +#if MALI_STATE_TRACKING + if (_MALI_UK_START_JOB_STARTED==user_ptr_job_input->status) + { + if(job) + { + job->job_nr=_mali_osk_atomic_inc_return(&session->jobs_received); + } + } +#endif + MALI_ERROR(err); } @@ -1020,6 +1051,9 @@ static void subsystem_mali200_return_job_to_user( mali_core_job * job, mali_subs job_out->perf_counter_l2_val1_raw = job200->perf_counter_l2_val1_raw; #endif +#if MALI_STATE_TRACKING + _mali_osk_atomic_inc(&session->jobs_returned); +#endif _mali_osk_notification_queue_send( session->notification_queue, job200->notification_obj); job200->notification_obj = NULL; @@ -1172,3 +1206,10 @@ _mali_osk_errcode_t malipp_signal_power_down( u32 core_num, mali_bool immediate_ } #endif + +#if MALI_STATE_TRACKING +u32 mali200_subsystem_dump_state(char *buf, u32 size) +{ + return mali_core_renderunit_dump_state(&subsystem_mali200, buf, size); +} +#endif diff --git a/drivers/gpu/arm/mali/common/mali_kernel_core.c b/drivers/gpu/arm/mali/common/mali_kernel_core.c index f3603cc7d0c..d4d0f5013fb 100755 --- a/drivers/gpu/arm/mali/common/mali_kernel_core.c +++ b/drivers/gpu/arm/mali/common/mali_kernel_core.c @@ -21,6 +21,9 @@ #if defined USING_MALI400_L2_CACHE #include "mali_kernel_l2_cache.h" #endif +#if USING_MALI_PMM +#include "mali_pmm.h" +#endif /* USING_MALI_PMM */ /* platform specific set up */ #include "mali_platform.h" @@ -49,6 +52,7 @@ static _mali_osk_errcode_t mali_kernel_subsystem_core_system_info_fill(_mali_sys static _mali_osk_errcode_t mali_kernel_subsystem_core_session_begin(struct mali_session_data * mali_session_data, mali_kernel_subsystem_session_slot * slot, _mali_osk_notification_queue_t * queue); static _mali_osk_errcode_t build_system_info(void); +static void cleanup_system_info(_mali_system_info *cleanup); /** * @brief handler for MEM_VALIDATION resources @@ -95,6 +99,9 @@ static struct mali_kernel_subsystem mali_subsystem_core = mali_kernel_subsystem_core_session_begin, /* session_begin */ NULL, /* session_end */ NULL, /* broadcast_notification */ +#if MALI_STATE_TRACKING + NULL, /* dump_state */ +#endif }; static struct mali_kernel_subsystem * subsystems[] = @@ -298,6 +305,9 @@ static void terminate_subsystems(void) if (NULL != subsystems[i]->shutdown) subsystems[i]->shutdown(i); } if (system_info_lock) _mali_osk_lock_term( system_info_lock ); + + /* Free _mali_system_info struct */ + cleanup_system_info(system_info); } void _mali_kernel_core_broadcast_subsystem_message(mali_core_notification_message message, u32 data) @@ -335,6 +345,30 @@ static void mali_kernel_subsystem_core_cleanup(mali_kernel_subsystem_identifier _mali_osk_resources_term(&arch_configuration, num_resources); } +static void cleanup_system_info(_mali_system_info *cleanup) +{ + _mali_core_info * current_core; + _mali_mem_info * current_mem; + + /* delete all the core info structs */ + while (NULL != cleanup->core_info) + { + current_core = cleanup->core_info; + cleanup->core_info = cleanup->core_info->next; + _mali_osk_free(current_core); + } + + /* delete all the mem info struct */ + while (NULL != cleanup->mem_info) + { + current_mem = cleanup->mem_info; + cleanup->mem_info = cleanup->mem_info->next; + _mali_osk_free(current_mem); + } + + /* delete the system info struct itself */ + _mali_osk_free(cleanup); +} static _mali_osk_errcode_t build_system_info(void) { @@ -400,25 +434,7 @@ error_exit: if (NULL == cleanup) MALI_ERROR((_mali_osk_errcode_t)err); /* no cleanup needed, return what err contains */ /* cleanup */ - - /* delete all the core info structs */ - while (NULL != cleanup->core_info) - { - current_core = cleanup->core_info; - cleanup->core_info = cleanup->core_info->next; - _mali_osk_free(current_core); - } - - /* delete all the mem info struct */ - while (NULL != cleanup->mem_info) - { - current_mem = cleanup->mem_info; - cleanup->mem_info = cleanup->mem_info->next; - _mali_osk_free(current_mem); - } - - /* delete the system info struct itself */ - _mali_osk_free(cleanup); + cleanup_system_info(cleanup); /* return whatever err is, we could end up here in both the error and success cases */ MALI_ERROR((_mali_osk_errcode_t)err); @@ -865,3 +881,28 @@ _mali_osk_errcode_t mali_core_signal_power_down( mali_pmm_core_id core, mali_boo } #endif + + +#if MALI_STATE_TRACKING +u32 _mali_kernel_core_dump_state(char* buf, u32 size) +{ + int i, n; + char *original_buf = buf; + for (i = 0; i < SUBSYSTEMS_COUNT; ++i) + { + if (NULL != subsystems[i]->dump_state) + { + n = subsystems[i]->dump_state(buf, size); + size -= n; + buf += n; + } + } +#if USING_MALI_PMM + n = mali_pmm_dump_os_thread_state(buf, size); + size -= n; + buf += n; +#endif + /* Return number of bytes written to buf */ + return (u32)(buf - original_buf); +} +#endif diff --git a/drivers/gpu/arm/mali/common/mali_kernel_core.h b/drivers/gpu/arm/mali/common/mali_kernel_core.h index 3819ecc5e1c..ced6b8fb118 100755 --- a/drivers/gpu/arm/mali/common/mali_kernel_core.h +++ b/drivers/gpu/arm/mali/common/mali_kernel_core.h @@ -88,9 +88,9 @@ _mali_osk_errcode_t mali_kernel_core_validate_mali_phys_range( u32 phys_base, u3 * @brief Signal a power up on a Mali core. * * This function flags a core as powered up. - * For PP and GP cores it calls functions that move the core from a power off + * For PP and GP cores it calls functions that move the core from a power off * queue into the idle queue ready to run jobs. It also tries to schedule any - * pending jobs to run on it. + * pending jobs to run on it. * * This function will fail if the core is not powered off - either running or * already idle. @@ -100,7 +100,7 @@ _mali_osk_errcode_t mali_kernel_core_validate_mali_phys_range( u32 phys_base, u3 * * @return _MALI_OSK_ERR_OK if the core has been powered up. Otherwise a * suitable _mali_osk_errcode_t error. - */ + */ _mali_osk_errcode_t mali_core_signal_power_up( mali_pmm_core_id core, mali_bool queue_only ); /** @@ -108,9 +108,9 @@ _mali_osk_errcode_t mali_core_signal_power_up( mali_pmm_core_id core, mali_bool * * This function flags a core as powered down. * For PP and GP cores it calls functions that move the core from an idle - * queue into the power off queue. + * queue into the power off queue. * - * This function will fail if the core is not idle - either running or + * This function will fail if the core is not idle - either running or * already powered down. * * @param core The PMM core id to power up. @@ -119,7 +119,7 @@ _mali_osk_errcode_t mali_core_signal_power_up( mali_pmm_core_id core, mali_bool * * @return _MALI_OSK_ERR_OK if the core has been powered up. Otherwise a * suitable _mali_osk_errcode_t error. - */ + */ _mali_osk_errcode_t mali_core_signal_power_down( mali_pmm_core_id core, mali_bool immediate_only ); #endif diff --git a/drivers/gpu/arm/mali/common/mali_kernel_l2_cache.c b/drivers/gpu/arm/mali/common/mali_kernel_l2_cache.c index af307c6ec0b..3c4c68d74bd 100755 --- a/drivers/gpu/arm/mali/common/mali_kernel_l2_cache.c +++ b/drivers/gpu/arm/mali/common/mali_kernel_l2_cache.c @@ -33,6 +33,7 @@ typedef enum mali_l2_cache_register { /*unused = 0x0003 */ MALI400_L2_CACHE_REGISTER_COMMAND = 0x0004, /**< Misc cache commands, e.g. clear */ MALI400_L2_CACHE_REGISTER_CLEAR_PAGE = 0x0005, + MALI400_L2_CACHE_REGISTER_MAX_READS = 0x0006, /**< Limit of outstanding read requests */ MALI400_L2_CACHE_REGISTER_ENABLE = 0x0007, /**< Enable misc cache features */ MALI400_L2_CACHE_REGISTER_PERFCNT_SRC0 = 0x0008, MALI400_L2_CACHE_REGISTER_PERFCNT_VAL0 = 0x0009, @@ -87,6 +88,10 @@ typedef struct mali_kernel_l2_cache_core } mali_kernel_l2_cache_core; +#define MALI400_L2_MAX_READS_DEFAULT 0x1C + +int mali_l2_max_reads = MALI400_L2_MAX_READS_DEFAULT; + /** * Mali L2 cache subsystem startup function @@ -154,6 +159,9 @@ struct mali_kernel_subsystem mali_subsystem_l2_cache = NULL, /**< session_begin */ NULL, /**< session_end */ NULL, /**< broadcast_notification */ +#if MALI_STATE_TRACKING + NULL, /**< dump_state */ +#endif }; @@ -193,6 +201,7 @@ static void mali_l2_cache_terminate(mali_kernel_subsystem_identifier id) _MALI_OSK_LIST_FOREACHENTRY( cache, temp_cache, &caches_head, mali_kernel_l2_cache_core, list ) { /* reset to defaults */ + mali_l2_cache_register_write(cache, MALI400_L2_CACHE_REGISTER_MAX_READS, (u32)MALI400_L2_MAX_READS_DEFAULT); mali_l2_cache_register_write(cache, MALI400_L2_CACHE_REGISTER_ENABLE, (u32)MALI400_L2_CACHE_ENABLE_DEFAULT); /* remove from the list of cacges on the system */ @@ -327,11 +336,11 @@ void mali_kernel_l2_cache_do_enable(void) { mali_kernel_l2_cache_core * cache, *temp_cache; - /* loop over all L2 cache units and enable them*/ _MALI_OSK_LIST_FOREACHENTRY( cache, temp_cache, &caches_head, mali_kernel_l2_cache_core, list) { mali_l2_cache_register_write(cache, MALI400_L2_CACHE_REGISTER_ENABLE, (u32)MALI400_L2_CACHE_ENABLE_ACCESS | (u32)MALI400_L2_CACHE_ENABLE_READ_ALLOCATE); + mali_l2_cache_register_write(cache, MALI400_L2_CACHE_REGISTER_MAX_READS, (u32)mali_l2_max_reads); } } @@ -486,6 +495,7 @@ void mali_kernel_l2_cache_get_perf_counters(u32 *src0, u32 *val0, u32 *src1, u32 MALI_DEBUG_PRINT(5, ("L2 cache counters get: SRC0=%u, VAL0=%u, SRC1=%u, VAL1=%u\n", cur_src0, cur_val0, cur_src1, cur_val1)); + /* Only update the counter source once, with the value from the first L2 cache unit. */ if (first_time) { *src0 = cur_src0; @@ -493,6 +503,7 @@ void mali_kernel_l2_cache_get_perf_counters(u32 *src0, u32 *val0, u32 *src1, u32 first_time = 0; } + /* Bail out if the L2 cache units have different counters set. */ if (*src0 == cur_src0 && *src1 == cur_src1) { *val0 += cur_val0; diff --git a/drivers/gpu/arm/mali/common/mali_kernel_mem_buddy.c b/drivers/gpu/arm/mali/common/mali_kernel_mem_buddy.c index 2f0e0ffafea..8277fd1e1c6 100755 --- a/drivers/gpu/arm/mali/common/mali_kernel_mem_buddy.c +++ b/drivers/gpu/arm/mali/common/mali_kernel_mem_buddy.c @@ -389,6 +389,9 @@ struct mali_kernel_subsystem mali_subsystem_memory = mali_memory_core_session_begin, /* session_begin */ mali_memory_core_session_end, /* session_end */ NULL, /* broadcast_notification */ +#if MALI_STATE_TRACKING + NULL, /* dump_state */ +#endif }; /* Initialized when this subsystem is initialized. This is determined by the diff --git a/drivers/gpu/arm/mali/common/mali_kernel_mem_mmu.c b/drivers/gpu/arm/mali/common/mali_kernel_mem_mmu.c index f43ca21cdf1..0476986ffd2 100755 --- a/drivers/gpu/arm/mali/common/mali_kernel_mem_mmu.c +++ b/drivers/gpu/arm/mali/common/mali_kernel_mem_mmu.c @@ -329,10 +329,13 @@ static _mali_osk_errcode_t mali_memory_core_resource_os_memory(_mali_osk_resourc * also call this directly (depending on compilation options), having locked * the descriptor. * + * This function will fail if it is unable to put the MMU in stall mode (which + * might be the case if a page fault is also being processed). + * * @param args see _mali_uk_mem_munmap_s in "mali_uk_types.h" * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure. */ -static void _mali_ukk_mem_munmap_internal( _mali_uk_mem_munmap_s *args ); +static _mali_osk_errcode_t _mali_ukk_mem_munmap_internal( _mali_uk_mem_munmap_s *args ); /** * The MMU interrupt handler @@ -373,6 +376,30 @@ static u32 mali_mmu_register_read(mali_kernel_memory_mmu * unit, mali_mmu_regist */ static void mali_mmu_register_write(mali_kernel_memory_mmu * unit, mali_mmu_register reg, u32 val); +/** + * Issues the reset command to the MMU and waits for HW to be ready again + * @param mmu The MMU to reset + */ +static void mali_mmu_raw_reset(mali_kernel_memory_mmu * mmu); + +/** + * Issues the enable paging command to the MMU and waits for HW to complete the request + * @param mmu The MMU to enable paging for + */ +static void mali_mmu_enable_paging(mali_kernel_memory_mmu * mmu); + +/** + * Issues the enable stall command to the MMU and waits for HW to complete the request + * @param mmu The MMU to enable paging for + * @return MALI_TRUE if HW stall was successfully engaged, otherwise MALI_FALSE (req timed out) + */ +static mali_bool mali_mmu_enable_stall(mali_kernel_memory_mmu * mmu); + +/** + * Issues the disable stall command to the MMU and waits for HW to complete the request + * @param mmu The MMU to enable paging for + */ +static void mali_mmu_disable_stall(mali_kernel_memory_mmu * mmu); #if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 static void ump_memory_release(void * ctx, void * handle); @@ -463,7 +490,10 @@ struct mali_kernel_subsystem mali_subsystem_memory = mali_memory_core_system_info_fill, /* system_info_fill */ mali_memory_core_session_begin, /* session_begin */ mali_memory_core_session_end, /* session_end */ - NULL /* broadcast_notification */ + NULL, /* broadcast_notification */ +#if MALI_STATE_TRACKING + NULL, /* dump_state */ +#endif }; static mali_kernel_mem_address_manager mali_address_manager = @@ -530,7 +560,7 @@ static void mali_memory_core_terminate(mali_kernel_subsystem_identifier id) _MALI_OSK_LIST_FOREACHENTRY(mmu, temp_mmu, &mmu_head, mali_kernel_memory_mmu, list) { /* reset to defaults */ - mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_SOFT_RESET); + mali_mmu_raw_reset(mmu); /* unregister the irq */ _mali_osk_irq_term(mmu->irq); @@ -541,6 +571,7 @@ static void mali_memory_core_terminate(mali_kernel_subsystem_identifier id) /* release resources */ _mali_osk_mem_unmapioregion(mmu->base, mmu->mapping_size, mmu->mapped_registers); _mali_osk_mem_unreqregion(mmu->base, mmu->mapping_size); + _mali_osk_lock_term(mmu->lock); _mali_osk_free(mmu); } @@ -884,7 +915,7 @@ static _mali_osk_errcode_t mali_memory_core_load_complete(mali_kernel_subsystem_ _MALI_OSK_LIST_FOREACHENTRY(mmu, temp_mmu, &mmu_head, mali_kernel_memory_mmu, list) { mali_mmu_register_write(mmu, MALI_MMU_REGISTER_DTE_ADDR, mali_empty_page_directory); - mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_PAGING); + mali_mmu_enable_paging(mmu); } MALI_DEBUG_PRINT(4, ("MMUs activated\n")); @@ -989,7 +1020,7 @@ static _mali_osk_errcode_t mali_memory_core_resource_mmu(_mali_osk_resource_t * /* setup MMU interrupt mask */ /* set all values to known defaults */ - mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_SOFT_RESET); + mali_mmu_raw_reset(mmu); mali_mmu_register_write(mmu, MALI_MMU_REGISTER_INT_MASK, MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR); /* setup MMU page directory pointer */ /* The mali_page_directory pointer is guaranteed to be 4kb aligned because we've used get_zeroed_page to accquire it */ @@ -1018,7 +1049,7 @@ static _mali_osk_errcode_t mali_memory_core_resource_mmu(_mali_osk_resource_t * } /* set to a known state */ - mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_SOFT_RESET); + mali_mmu_raw_reset(mmu); mali_mmu_register_write(mmu, MALI_MMU_REGISTER_INT_MASK, MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR); MALI_DEBUG_PRINT(2, ("MMU registered\n")); @@ -1216,6 +1247,9 @@ static void mali_kernel_mmu_bus_reset(mali_kernel_memory_mmu * mmu) /* no new request will come from any of the connected cores from now * we must now flush the playback buffer for any requests queued already */ + + _mali_osk_lock_wait(mmu->lock, _MALI_OSK_LOCKMODE_RW); + MALI_DEBUG_PRINT(4, ("Switching to the special page fault flush page directory\n")); /* don't use the mali_mmu_activate_address_space function here as we can't stall the MMU */ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_DTE_ADDR, mali_page_fault_flush_page_directory); @@ -1236,16 +1270,23 @@ static void mali_kernel_mmu_bus_reset(mali_kernel_memory_mmu * mmu) MALI_DEBUG_PRINT_IF(1, i == replay_buffer_max_number_of_checks, ("MMU: %s: Failed to flush replay buffer on page fault\n", mmu->description)); MALI_DEBUG_PRINT(1, ("Replay playback took %ld usec\n", i * replay_buffer_check_interval)); } + + _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW); + #endif /* notify all subsystems that the core should be reset once the bus is actually stopped */ MALI_DEBUG_PRINT(4,("Sending job abort command to subsystems\n")); _mali_kernel_core_broadcast_subsystem_message(MMU_KILL_STEP2_RESET_ALL_CORES_AND_ABORT_THEIR_JOBS, (u32)mmu); + _mali_osk_lock_wait(mmu->lock, _MALI_OSK_LOCKMODE_RW); + /* reprogram the MMU */ - mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_SOFT_RESET); + mali_mmu_raw_reset(mmu); mali_mmu_register_write(mmu, MALI_MMU_REGISTER_INT_MASK, MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR); mali_mmu_register_write(mmu, MALI_MMU_REGISTER_DTE_ADDR, mali_empty_page_directory); /* no session is active, so just activate the empty page directory */ - mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_PAGING); + mali_mmu_enable_paging(mmu); + + _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW); /* release the extra address space reference, will schedule */ mali_memory_core_mmu_release_address_space_reference(mmu); @@ -1255,6 +1296,101 @@ static void mali_kernel_mmu_bus_reset(mali_kernel_memory_mmu * mmu) MALI_DEBUG_PRINT(4, ("Page fault handling complete\n")); } +static void mali_mmu_raw_reset(mali_kernel_memory_mmu * mmu) +{ + const int max_loop_count = 100; + const int delay_in_usecs = 1; + + mali_mmu_register_write(mmu, MALI_MMU_REGISTER_DTE_ADDR, 0xCAFEBABE); + mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_SOFT_RESET); + + if (!mali_benchmark) + { + int i; + for (i = 0; i < max_loop_count; ++i) + { + if (mali_mmu_register_read(mmu, MALI_MMU_REGISTER_DTE_ADDR) == 0) + { + break; + } + _mali_osk_time_ubusydelay(delay_in_usecs); + } + MALI_DEBUG_PRINT_IF(1, (max_loop_count == i), ("Reset request failed, MMU status is 0x%08X\n", mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS))); + } +} + +static void mali_mmu_enable_paging(mali_kernel_memory_mmu * mmu) +{ + const int max_loop_count = 100; + const int delay_in_usecs = 1; + + mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_PAGING); + + if (!mali_benchmark) + { + int i; + for (i = 0; i < max_loop_count; ++i) + { + if (mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS) & MALI_MMU_STATUS_BIT_PAGING_ENABLED) + { + break; + } + _mali_osk_time_ubusydelay(delay_in_usecs); + } + MALI_DEBUG_PRINT_IF(1, (max_loop_count == i), ("Enable paging request failed, MMU status is 0x%08X\n", mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS))); + } +} + +static mali_bool mali_mmu_enable_stall(mali_kernel_memory_mmu * mmu) +{ + const int max_loop_count = 100; + const int delay_in_usecs = 999; + int i; + + mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_STALL); + + if (!mali_benchmark) + { + for (i = 0; i < max_loop_count; ++i) + { + if (mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS) & MALI_MMU_STATUS_BIT_STALL_ACTIVE) + { + break; + } + _mali_osk_time_ubusydelay(delay_in_usecs); + } + MALI_DEBUG_PRINT_IF(1, (max_loop_count == i), ("Enable stall request failed, MMU status is 0x%08X\n", mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS))); + if (max_loop_count == i) + { + return MALI_FALSE; + } + } + + return MALI_TRUE; +} + +static void mali_mmu_disable_stall(mali_kernel_memory_mmu * mmu) +{ + const int max_loop_count = 100; + const int delay_in_usecs = 1; + int i; + + mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_DISABLE_STALL); + + if (!mali_benchmark) + { + for (i = 0; i < max_loop_count; ++i) + { + if ((mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS) & MALI_MMU_STATUS_BIT_STALL_ACTIVE) == 0) + { + break; + } + _mali_osk_time_ubusydelay(delay_in_usecs); + } + MALI_DEBUG_PRINT_IF(1, (max_loop_count == i), ("Disable stall request failed, MMU status is 0x%08X\n", mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS))); + } +} + void mali_kernel_mmu_reset(void * input_mmu) { mali_kernel_memory_mmu * mmu; @@ -1270,10 +1406,10 @@ void mali_kernel_mmu_reset(void * input_mmu) return; } _mali_osk_lock_wait(mmu->lock, _MALI_OSK_LOCKMODE_RW); - mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_SOFT_RESET); + mali_mmu_raw_reset(mmu); mali_mmu_register_write(mmu, MALI_MMU_REGISTER_INT_MASK, MALI_MMU_INTERRUPT_PAGE_FAULT | MALI_MMU_INTERRUPT_READ_BUS_ERROR); mali_mmu_register_write(mmu, MALI_MMU_REGISTER_DTE_ADDR, mali_empty_page_directory); /* no session is active, so just activate the empty page directory */ - mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_PAGING); + mali_mmu_enable_paging(mmu); _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW); } @@ -1401,7 +1537,6 @@ static void mali_mmu_register_write(mali_kernel_memory_mmu * unit, mali_mmu_regi _mali_osk_mem_iowrite32(unit->mapped_registers, (u32)reg * sizeof(u32), val); } - #if MALI_USE_UNIFIED_MEMORY_PROVIDER != 0 static mali_physical_memory_allocation_result ump_memory_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info) { @@ -1572,6 +1707,7 @@ _mali_osk_errcode_t _mali_ukk_attach_ump_mem( _mali_uk_attach_ump_mem_s *args ) descriptor->mali_address = args->mali_address; descriptor->mali_addr_mapping_info = (void*)session_data; descriptor->process_addr_mapping_info = NULL; /* do not map to process address space */ + descriptor->lock = session_data->lock; if (args->flags & _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE) { descriptor->flags = MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE; @@ -1591,14 +1727,19 @@ _mali_osk_errcode_t _mali_ukk_attach_ump_mem( _mali_uk_attach_ump_mem_s *args ) external_memory_allocator.name = "UMP Memory"; external_memory_allocator.next = NULL; + _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); + if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_memory(memory_engine, descriptor, &external_memory_allocator, NULL)) { + _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); mali_descriptor_mapping_free(session_data->descriptor_mapping, md); ump_dd_reference_release(ump_mem); _mali_osk_free(descriptor); MALI_ERROR(_MALI_OSK_ERR_NOMEM); } + _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); + args->cookie = md; MALI_DEBUG_PRINT(5,("Returning from UMP attach\n")); @@ -1626,7 +1767,13 @@ _mali_osk_errcode_t _mali_ukk_release_ump_mem( _mali_uk_release_ump_mem_s *args } mali_descriptor_mapping_free(session_data->descriptor_mapping, args->cookie); + + _mali_osk_lock_wait( session_data->lock, _MALI_OSK_LOCKMODE_RW ); + mali_allocation_engine_release_memory(memory_engine, descriptor); + + _mali_osk_lock_signal( session_data->lock, _MALI_OSK_LOCKMODE_RW ); + _mali_osk_free(descriptor); MALI_SUCCESS; @@ -1765,7 +1912,7 @@ _mali_osk_errcode_t _mali_ukk_map_external_mem( _mali_uk_map_external_mem_s *arg descriptor->mali_address = args->mali_address; descriptor->mali_addr_mapping_info = (void*)session_data; descriptor->process_addr_mapping_info = NULL; /* do not map to process address space */ - descriptor->lock = NULL; + descriptor->lock = session_data->lock; if (args->flags & _MALI_MAP_EXTERNAL_MAP_GUARD_PAGE) { descriptor->flags = MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE; @@ -1778,13 +1925,18 @@ _mali_osk_errcode_t _mali_ukk_map_external_mem( _mali_uk_map_external_mem_s *arg MALI_ERROR(_MALI_OSK_ERR_FAULT); } + _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); + if (_MALI_OSK_ERR_OK != mali_allocation_engine_allocate_memory(memory_engine, descriptor, &external_memory_allocator, NULL)) { + _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); mali_descriptor_mapping_free(session_data->descriptor_mapping, md); _mali_osk_free(descriptor); MALI_ERROR(_MALI_OSK_ERR_NOMEM); } + _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW); + args->cookie = md; MALI_DEBUG_PRINT(5,("Returning from range_map_external_memory\n")); @@ -1812,7 +1964,13 @@ _mali_osk_errcode_t _mali_ukk_unmap_external_mem( _mali_uk_unmap_external_mem_s } mali_descriptor_mapping_free(session_data->descriptor_mapping, args->cookie); + + _mali_osk_lock_wait( session_data->lock, _MALI_OSK_LOCKMODE_RW ); + mali_allocation_engine_release_memory(memory_engine, descriptor); + + _mali_osk_lock_signal( session_data->lock, _MALI_OSK_LOCKMODE_RW ); + _mali_osk_free(descriptor); MALI_SUCCESS; @@ -1867,6 +2025,8 @@ void mali_mmu_page_table_cache_destroy(void) _mali_osk_free(alloc->usage_map); _mali_osk_free(alloc); } + + _mali_osk_lock_term(page_table_cache.lock); } _mali_osk_errcode_t mali_mmu_get_table_page(u32 *table_page, mali_io_address *mapping) @@ -2027,24 +2187,10 @@ void* mali_memory_core_mmu_lookup(u32 id) void mali_mmu_activate_address_space(mali_kernel_memory_mmu * mmu, u32 page_directory) { - const int delay_in_usecs = 10; - const int max_loop_count = 10; - int i; - - mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_STALL); - - if (!mali_benchmark) { - for (i = 0; i < max_loop_count; ++i) - { - if (mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS) & MALI_MMU_STATUS_BIT_STALL_ACTIVE) break; - _mali_osk_time_ubusydelay(delay_in_usecs); - } - MALI_DEBUG_PRINT_IF(1, (max_loop_count == i), ("Stall request failed, swapping anyway\n")); - } - + mali_mmu_enable_stall(mmu); /* this might fail, but changing the DTE address and ZAP should work anyway... */ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_DTE_ADDR, page_directory); mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE); - mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_DISABLE_STALL); + mali_mmu_disable_stall(mmu); } _mali_osk_errcode_t mali_memory_core_mmu_activate_page_table(void* mmu_ptr, struct mali_session_data * mali_session_data, void(*callback)(void*), void * callback_argument) @@ -2571,7 +2717,7 @@ _mali_osk_errcode_t _mali_ukk_mem_mmap( _mali_uk_mem_mmap_s *args ) descriptor->lock = session_data->lock; _mali_osk_list_init( &descriptor->list ); - _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); + _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW); if (0 == mali_allocation_engine_allocate_memory(memory_engine, descriptor, physical_memory_allocators, &session_data->memory_head)) { @@ -2584,12 +2730,9 @@ _mali_osk_errcode_t _mali_ukk_mem_mmap( _mali_uk_mem_mmap_s *args ) _mali_osk_lock_wait(mmu->lock, _MALI_OSK_LOCKMODE_RW); - mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_STALL); - if (!mali_benchmark) { - while ( (mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS) & MALI_MMU_STATUS_BIT_STALL_ACTIVE) == 0) _mali_osk_time_ubusydelay(1); - } + mali_mmu_enable_stall(mmu); /* this might fail, but ZAP should work anyway... */ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE); - mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_DISABLE_STALL); + mali_mmu_disable_stall(mmu); _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW); } @@ -2615,7 +2758,7 @@ _mali_osk_errcode_t _mali_ukk_mem_mmap( _mali_uk_mem_mmap_s *args ) } } -static void _mali_ukk_mem_munmap_internal( _mali_uk_mem_munmap_s *args ) +static _mali_osk_errcode_t _mali_ukk_mem_munmap_internal( _mali_uk_mem_munmap_s *args ) { memory_session * session_data; mali_kernel_memory_mmu * mmu, * temp_mmu; @@ -2638,24 +2781,28 @@ static void _mali_ukk_mem_munmap_internal( _mali_uk_mem_munmap_s *args ) */ _MALI_OSK_LIST_FOREACHENTRY(mmu, temp_mmu, &session_data->active_mmus, mali_kernel_memory_mmu, session_link) { - const int max_loop_count = 100; - const int sleep_duration = 1; /* must be below 1000 */ - int i; - _mali_osk_lock_wait(mmu->lock, _MALI_OSK_LOCKMODE_RW); - mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ENABLE_STALL); - - if (!mali_benchmark) + /* + * If we're unable to stall, then make sure we tell our caller that, + * the caller should then release the session lock for a while, + * then this function again. + * This function will fail if we're in page fault mode, and to get + * out of page fault mode, the page fault handler must be able to + * take the session lock. + */ + if (!mali_mmu_enable_stall(mmu)) { - for ( i = 0; i < max_loop_count; i++) - { - if (mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS) & MALI_MMU_STATUS_BIT_STALL_ACTIVE) break; - _mali_osk_time_ubusydelay(sleep_duration); - } - - MALI_DEBUG_PRINT_IF(3, max_loop_count == i, ("Stall failed, trying zap anyway\n")); + _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW); + return _MALI_OSK_ERR_BUSY; } + + _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW); + } + + _MALI_OSK_LIST_FOREACHENTRY(mmu, temp_mmu, &session_data->active_mmus, mali_kernel_memory_mmu, session_link) + { + _mali_osk_lock_wait(mmu->lock, _MALI_OSK_LOCKMODE_RW); } /* This function also removes the memory from the session's memory list */ @@ -2668,10 +2815,12 @@ static void _mali_ukk_mem_munmap_internal( _mali_uk_mem_munmap_s *args ) _MALI_OSK_LIST_FOREACHENTRY(mmu, temp_mmu, &session_data->active_mmus, mali_kernel_memory_mmu, session_link) { mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_ZAP_CACHE); - mali_mmu_register_write(mmu, MALI_MMU_REGISTER_COMMAND, MALI_MMU_COMMAND_DISABLE_STALL); + mali_mmu_disable_stall(mmu); _mali_osk_lock_signal(mmu->lock, _MALI_OSK_LOCKMODE_RW); } + + return _MALI_OSK_ERR_OK; } /* Handler for unmapping memory for MMU builds */ @@ -2679,6 +2828,7 @@ _mali_osk_errcode_t _mali_ukk_mem_munmap( _mali_uk_mem_munmap_s *args ) { mali_memory_allocation * descriptor; _mali_osk_lock_t *descriptor_lock; + _mali_osk_errcode_t err; descriptor = (mali_memory_allocation *)args->cookie; MALI_DEBUG_ASSERT_POINTER(descriptor); @@ -2692,20 +2842,34 @@ _mali_osk_errcode_t _mali_ukk_mem_munmap( _mali_uk_mem_munmap_s *args ) descriptor_lock = descriptor->lock; /* should point to the session data lock... */ - if (descriptor_lock) + err = _MALI_OSK_ERR_BUSY; + while (err == _MALI_OSK_ERR_BUSY) { - _mali_osk_lock_wait( descriptor_lock, _MALI_OSK_LOCKMODE_RW ); - } - /* Noninterruptable spinlock type, so must always have locked. Checking should've been done in OSK function. */ + if (descriptor_lock) + { + _mali_osk_lock_wait( descriptor_lock, _MALI_OSK_LOCKMODE_RW ); + } - _mali_ukk_mem_munmap_internal( args ); - /* descriptor is no longer valid - it may've been freed */ + err = _mali_ukk_mem_munmap_internal( args ); - if (descriptor_lock) - { - _mali_osk_lock_signal( descriptor_lock, _MALI_OSK_LOCKMODE_RW ); + if (descriptor_lock) + { + _mali_osk_lock_signal( descriptor_lock, _MALI_OSK_LOCKMODE_RW ); + } + + if (err == _MALI_OSK_ERR_BUSY) + { + /* + * Reason for this; + * We where unable to stall the MMU, probably because we are in page fault handling. + * Sleep for a while with the session lock released, then try again. + * Abnormal termination of programs with running Mali jobs is a normal reason for this. + */ + _mali_osk_time_ubusydelay(10); + } } - return _MALI_OSK_ERR_OK; + + return err; } /* Is called when the rendercore wants the mmu to give an interrupt */ diff --git a/drivers/gpu/arm/mali/common/mali_kernel_rendercore.c b/drivers/gpu/arm/mali/common/mali_kernel_rendercore.c index e3027cc4f26..5ff681b32d3 100755 --- a/drivers/gpu/arm/mali/common/mali_kernel_rendercore.c +++ b/drivers/gpu/arm/mali/common/mali_kernel_rendercore.c @@ -94,14 +94,18 @@ struct mali_kernel_subsystem mali_subsystem_rendercore= NULL, /* session_begin */ NULL, /* session_end */ #if USING_MMU - rendercore_subsystem_broadcast_notification /* broadcast_notification */ + rendercore_subsystem_broadcast_notification, /* broadcast_notification */ #else - NULL + NULL, +#endif +#if MALI_STATE_TRACKING + NULL, /* dump_state */ #endif } ; static _mali_osk_lock_t *rendercores_global_mutex = NULL; static u32 rendercores_global_mutex_is_held = 0; +static u32 rendercores_global_mutex_owner = 0; /** The 'dummy' rendercore subsystem to allow global subsystem mutex to be * locked for all subsystems that extend the ''rendercore'' */ @@ -544,6 +548,7 @@ static void mali_core_renderunit_irq_handler_remove(mali_core_renderunit *core) mali_core_renderunit * mali_core_renderunit_get_mali_core_nr(mali_core_subsystem *subsys, u32 mali_core_nr) { mali_core_renderunit * core; + MALI_ASSERT_MUTEX_IS_GRABBED(subsys); if (subsys->number_of_cores <= mali_core_nr) { MALI_PRINT_ERROR(("Trying to get illegal mali_core_nr: 0x%x for %s", mali_core_nr, subsys->name)); @@ -603,6 +608,8 @@ void mali_core_subsystem_attach_mmu(mali_core_subsystem* subsys) u32 i; mali_core_renderunit * core; + MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsys); + for(i=0 ; i < subsys->number_of_cores ; ++i) { core = mali_core_renderunit_get_mali_core_nr(subsys,i); @@ -610,6 +617,8 @@ void mali_core_subsystem_attach_mmu(mali_core_subsystem* subsys) core->mmu = mali_memory_core_mmu_lookup(core->mmu_id); MALI_DEBUG_PRINT(2, ("Attach mmu: 0x%x to core: %s in subsystem: %s\n", core->mmu, core->description, subsys->name)); } + + MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys); } #endif @@ -862,11 +871,11 @@ _mali_osk_errcode_t mali_core_subsystem_ioctl_number_of_cores_get(mali_core_sess if ( NULL != number_of_cores ) { *number_of_cores = subsystem->number_of_cores; - } - MALI_DEBUG_PRINT(4, ("Core: ioctl_number_of_cores_get: %s: %u\n", subsystem->name, *number_of_cores) ) ; + MALI_DEBUG_PRINT(4, ("Core: ioctl_number_of_cores_get: %s: %u\n", subsystem->name, *number_of_cores) ) ; + } - MALI_SUCCESS; + MALI_SUCCESS; } _mali_osk_errcode_t mali_core_subsystem_ioctl_start_job(mali_core_session * session, void *job_data) @@ -1058,15 +1067,7 @@ static void mali_core_subsystem_move_core_set_idle(mali_core_renderunit *core) oldstatus = core->state; - if( core->pend_power_down ) - { - core->state = CORE_OFF ; - _mali_osk_list_move( &core->list, &subsystem->renderunit_off_head ); - /* Done the move from the active queues, so the pending power down can be done */ - core->pend_power_down = MALI_FALSE; - malipmm_core_power_down_okay( core->pmm_id ); - } - else + if ( !core->pend_power_down ) { core->state = CORE_IDLE ; _mali_osk_list_move( &core->list, &subsystem->renderunit_idle_head ); @@ -1089,6 +1090,15 @@ static void mali_core_subsystem_move_core_set_idle(mali_core_renderunit *core) #endif /* USING_MMU */ } + if( core->pend_power_down ) + { + core->state = CORE_OFF ; + _mali_osk_list_move( &core->list, &subsystem->renderunit_off_head ); + + /* Done the move from the active queues, so the pending power down can be done */ + core->pend_power_down = MALI_FALSE; + malipmm_core_power_down_okay( core->pmm_id ); + } #else /* !USING_MALI_PMM */ @@ -1389,6 +1399,13 @@ void mali_core_session_begin(mali_core_session * session) MALI_CORE_SUBSYSTEM_MUTEX_GRAB(subsystem); _mali_osk_list_add(&session->all_sessions_list, &session->subsystem->all_sessions_head); + +#if MALI_STATE_TRACKING + _mali_osk_atomic_init(&session->jobs_received, 0); + _mali_osk_atomic_init(&session->jobs_returned, 0); + session->pid = _mali_osk_get_pid(); +#endif + MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsystem); MALI_DEBUG_PRINT(5, ("Core: session_begin: for %s DONE\n", session->subsystem->name) ) ; @@ -1934,3 +1951,128 @@ _mali_osk_errcode_t mali_core_subsystem_signal_power_up(mali_core_subsystem *sub } #endif /* USING_MALI_PMM */ + +#if MALI_STATE_TRACKING +u32 mali_core_renderunit_dump_state(mali_core_subsystem* subsystem, char *buf, u32 size) +{ + u32 i, len = 0; + mali_core_renderunit *core; + mali_core_renderunit *tmp_core; + + mali_core_session* session; + mali_core_session* tmp_session; + + if (0 >= size) + { + return 0; + } + + MALI_CORE_SUBSYSTEM_MUTEX_GRAB( subsystem ); + + len += _mali_osk_snprintf(buf + len, size - len, "Subsystem:\n"); + len += _mali_osk_snprintf(buf + len, size - len, " Name: %s\n", subsystem->name); + + for (i = 0; i < subsystem->number_of_cores; i++) + { + len += _mali_osk_snprintf(buf + len, size - len, " Core: #%u\n", + subsystem->mali_core_array[i]->core_number); + len += _mali_osk_snprintf(buf + len, size - len, " Description: %s\n", + subsystem->mali_core_array[i]->description); + switch(subsystem->mali_core_array[i]->state) + { + case CORE_IDLE: + len += _mali_osk_snprintf(buf + len, size - len, " State: CORE_IDLE\n"); + break; + case CORE_WORKING: + len += _mali_osk_snprintf(buf + len, size - len, " State: CORE_WORKING\n"); + break; + case CORE_WATCHDOG_TIMEOUT: + len += _mali_osk_snprintf(buf + len, size - len, " State: CORE_WATCHDOG_TIMEOUT\n"); + break; + case CORE_POLL: + len += _mali_osk_snprintf(buf + len, size - len, " State: CORE_POLL\n"); + break; + case CORE_HANG_CHECK_TIMEOUT: + len += _mali_osk_snprintf(buf + len, size - len, " State: CORE_HANG_CHECK_TIMEOUT\n"); + break; + case CORE_OFF: + len += _mali_osk_snprintf(buf + len, size - len, " State: CORE_OFF\n"); + break; + default: + len += _mali_osk_snprintf(buf + len, size - len, " State: Unknown (0x%X)\n", + subsystem->mali_core_array[i]->state); + break; + } + len += _mali_osk_snprintf(buf + len, size - len, " Current job: 0x%X\n", + (u32)(subsystem->mali_core_array[i]->current_job)); + if (subsystem->mali_core_array[i]->current_job) + { + len += _mali_osk_snprintf(buf + len, size - len, " Current job session: 0x%X\n", + subsystem->mali_core_array[i]->current_job->session); + len += _mali_osk_snprintf(buf + len, size - len, " Current job number: %d\n", + subsystem->mali_core_array[i]->current_job->job_nr); + len += _mali_osk_snprintf(buf + len, size - len, " Current job render_time jiffies: %d\n", + _mali_osk_time_tickcount()-subsystem->mali_core_array[i]->current_job->start_time_jiffies); + } + len += _mali_osk_snprintf(buf + len, size - len, " Core version: 0x%X\n", + subsystem->mali_core_array[i]->core_version); +#if USING_MALI_PMM + len += _mali_osk_snprintf(buf + len, size - len, " PMM id: 0x%X\n", + subsystem->mali_core_array[i]->pmm_id); + len += _mali_osk_snprintf(buf + len, size - len, " Power down requested: %s\n", + subsystem->mali_core_array[i]->pend_power_down ? "TRUE" : "FALSE"); +#endif + } + + len += _mali_osk_snprintf(buf + len, size - len, " Cores on idle list:\n"); + _MALI_OSK_LIST_FOREACHENTRY(core, tmp_core, &subsystem->renderunit_idle_head, mali_core_renderunit, list) + { + len += _mali_osk_snprintf(buf + len, size - len, " Core #%u\n", core->core_number); + } + + len += _mali_osk_snprintf(buf + len, size - len, " Cores on off list:\n"); + _MALI_OSK_LIST_FOREACHENTRY(core, tmp_core, &subsystem->renderunit_off_head, mali_core_renderunit, list) + { + len += _mali_osk_snprintf(buf + len, size - len, " Core #%u\n", core->core_number); + } + + len += _mali_osk_snprintf(buf + len, size - len, " Connected sessions:\n"); + _MALI_OSK_LIST_FOREACHENTRY(session, tmp_session, &subsystem->all_sessions_head, mali_core_session, all_sessions_list) + { + len += _mali_osk_snprintf(buf + len, size - len, + " Session 0x%X:\n", (u32)session); + len += _mali_osk_snprintf(buf + len, size - len, + " Waiting job: 0x%X\n", (u32)session->job_waiting_to_run); + len += _mali_osk_snprintf(buf + len, size - len, " Notification queue: %s\n", + _mali_osk_notification_queue_is_empty(session->notification_queue) ? "EMPTY" : "NON-EMPTY"); + len += _mali_osk_snprintf(buf + len, size - len, + " Jobs received:%4d\n", _mali_osk_atomic_read(&session->jobs_received)); + len += _mali_osk_snprintf(buf + len, size - len, + " Jobs started :%4d\n", _mali_osk_atomic_read(&session->jobs_started)); + len += _mali_osk_snprintf(buf + len, size - len, + " Jobs ended :%4d\n", _mali_osk_atomic_read(&session->jobs_ended)); + len += _mali_osk_snprintf(buf + len, size - len, + " Jobs returned:%4d\n", _mali_osk_atomic_read(&session->jobs_returned)); + len += _mali_osk_snprintf(buf + len, size - len, " PID: %d\n", session->pid); + } + + len += _mali_osk_snprintf(buf + len, size - len, " Waiting sessions sum all priorities: %u\n", + subsystem->awaiting_sessions_sum_all_priorities); + for (i = 0; i < PRIORITY_LEVELS; i++) + { + len += _mali_osk_snprintf(buf + len, size - len, " Waiting sessions with priority %u:\n", i); + _MALI_OSK_LIST_FOREACHENTRY(session, tmp_session, &subsystem->awaiting_sessions_head[i], + mali_core_session, awaiting_sessions_list) + { + len += _mali_osk_snprintf(buf + len, size - len, " Session 0x%X:\n", (u32)session); + len += _mali_osk_snprintf(buf + len, size - len, " Waiting job: 0x%X\n", + (u32)session->job_waiting_to_run); + len += _mali_osk_snprintf(buf + len, size - len, " Notification queue: %s\n", + _mali_osk_notification_queue_is_empty(session->notification_queue) ? "EMPTY" : "NON-EMPTY"); + } + } + + MALI_CORE_SUBSYSTEM_MUTEX_RELEASE( subsystem ); + return len; +} +#endif diff --git a/drivers/gpu/arm/mali/common/mali_kernel_rendercore.h b/drivers/gpu/arm/mali/common/mali_kernel_rendercore.h index 80d7dd82cea..b72d467a0c3 100755 --- a/drivers/gpu/arm/mali/common/mali_kernel_rendercore.h +++ b/drivers/gpu/arm/mali/common/mali_kernel_rendercore.h @@ -188,6 +188,13 @@ typedef struct mali_core_session struct mali_session_data * mmu_session; /* The session associated with the MMU page tables for this core */ #endif u32 magic_nr; +#if MALI_STATE_TRACKING + _mali_osk_atomic_t jobs_received; + _mali_osk_atomic_t jobs_started; + _mali_osk_atomic_t jobs_ended; + _mali_osk_atomic_t jobs_returned; + u32 pid; +#endif } mali_core_session; @@ -204,6 +211,7 @@ typedef struct mali_core_job u32 start_time_jiffies; unsigned long watchdog_jiffies; u32 abort_id; + u32 job_nr; } mali_core_job; /* @@ -287,12 +295,14 @@ typedef struct register_array_user MALI_DEBUG_PRINT(5, ("MUTEX: GRABBED %s() %d on %s\n",__FUNCTION__, __LINE__, subsys->name)); \ if ( SUBSYSTEM_MAGIC_NR != subsys->magic_nr ) MALI_PRINT_ERROR(("Wrong magic number"));\ rendercores_global_mutex_is_held = 1; \ + rendercores_global_mutex_owner = _mali_osk_get_tid(); \ } while (0) ; #define MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys) \ do { \ MALI_DEBUG_PRINT(5, ("MUTEX: RELEASE %s() %d on %s\n",__FUNCTION__, __LINE__, subsys->name)); \ rendercores_global_mutex_is_held = 0; \ + rendercores_global_mutex_owner = 0; \ if ( SUBSYSTEM_MAGIC_NR != subsys->magic_nr ) MALI_PRINT_ERROR(("Wrong magic number"));\ _mali_osk_lock_signal( rendercores_global_mutex, _MALI_OSK_LOCKMODE_RW); \ MALI_DEBUG_PRINT(5, ("MUTEX: RELEASED %s() %d on %s\n",__FUNCTION__, __LINE__, subsys->name)); \ @@ -304,6 +314,7 @@ typedef struct register_array_user do { \ if ( 0 == rendercores_global_mutex_is_held ) MALI_PRINT_ERROR(("ASSERT MUTEX SHOULD BE GRABBED"));\ if ( SUBSYSTEM_MAGIC_NR != input_pointer->magic_nr ) MALI_PRINT_ERROR(("Wrong magic number"));\ + if ( rendercores_global_mutex_owner != _mali_osk_get_tid() ) MALI_PRINT_ERROR(("Owner mismatch"));\ } while (0) @@ -345,4 +356,8 @@ _mali_osk_errcode_t mali_core_subsystem_signal_power_down(mali_core_subsystem *s _mali_osk_errcode_t mali_core_subsystem_signal_power_up(mali_core_subsystem *subsys, u32 mali_core_nr, mali_bool queue_only); #endif +#if MALI_STATE_TRACKING +u32 mali_core_renderunit_dump_state(mali_core_subsystem* subsystem, char *buf, u32 size); +#endif + #endif /* __MALI_RENDERCORE_H__ */ diff --git a/drivers/gpu/arm/mali/common/mali_kernel_subsystem.h b/drivers/gpu/arm/mali/common/mali_kernel_subsystem.h index ba757abef0a..9efba566bd9 100755 --- a/drivers/gpu/arm/mali/common/mali_kernel_subsystem.h +++ b/drivers/gpu/arm/mali/common/mali_kernel_subsystem.h @@ -71,6 +71,11 @@ typedef struct mali_kernel_subsystem /* Used by subsystems to send messages to each other. This is the receiving end */ void (*broadcast_notification)(mali_core_notification_message message, u32 data); + +#if MALI_STATE_TRACKING + /** Dump the current state of the subsystem */ + u32 (*dump_state)(char *buf, u32 size); +#endif } mali_kernel_subsystem; /* functions used by the subsystems to interact with the core */ @@ -91,4 +96,12 @@ _mali_osk_errcode_t _mali_kernel_core_register_resource_handler(_mali_osk_resour */ void _mali_kernel_core_broadcast_subsystem_message(mali_core_notification_message message, u32 data); +#if MALI_STATE_TRACKING +/** + * Tell all subsystems to dump their current state + */ +u32 _mali_kernel_core_dump_state(char *buf, u32 size); +#endif + + #endif /* __MALI_KERNEL_SUBSYSTEM_H__ */ diff --git a/drivers/gpu/arm/mali/common/mali_kernel_utilization.c b/drivers/gpu/arm/mali/common/mali_kernel_utilization.c index 1ba122a9856..a8acd8c2cce 100755 --- a/drivers/gpu/arm/mali/common/mali_kernel_utilization.c +++ b/drivers/gpu/arm/mali/common/mali_kernel_utilization.c @@ -29,7 +29,7 @@ static mali_bool timer_running = MALI_FALSE; static void calculate_gpu_utilization(void* arg) { - u64 time_now = _mali_osk_time_get_ns(); + u64 time_now; u64 time_period; u32 leading_zeroes; u32 shift_val; @@ -39,7 +39,7 @@ static void calculate_gpu_utilization(void* arg) _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW); - if (accumulated_work_time == 0) + if (accumulated_work_time == 0 && work_start_time == 0) { /* Don't reschedule timer, this will be started if new work arrives */ timer_running = MALI_FALSE; @@ -52,6 +52,7 @@ static void calculate_gpu_utilization(void* arg) return; } + time_now = _mali_osk_time_get_ns(); time_period = time_now - period_start_time; /* If we are currently busy, update working period up to now */ @@ -129,20 +130,15 @@ _mali_osk_errcode_t mali_utilization_init(void) return _MALI_OSK_ERR_OK; } - - - void mali_utilization_suspend(void) { - if (NULL != utilization_timer) - { - _mali_osk_timer_del(utilization_timer); - timer_running = MALI_FALSE; - } + if (NULL != utilization_timer) + { + _mali_osk_timer_del(utilization_timer); + timer_running = MALI_FALSE; + } } - - void mali_utilization_term(void) { if (NULL != utilization_timer) @@ -198,9 +194,11 @@ void mali_utilization_core_end(void) /* * No more cores are working, so accumulate the time we was busy. */ - u64 time_now = _mali_osk_time_get_ns(); + u64 time_now; + _mali_osk_lock_wait(time_data_lock, _MALI_OSK_LOCKMODE_RW); + time_now = _mali_osk_time_get_ns(); accumulated_work_time += (time_now - work_start_time); work_start_time = 0; diff --git a/drivers/gpu/arm/mali/common/mali_kernel_vsync.c b/drivers/gpu/arm/mali/common/mali_kernel_vsync.c new file mode 100644 index 00000000000..8dfa3a393ba --- /dev/null +++ b/drivers/gpu/arm/mali/common/mali_kernel_vsync.c @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2011 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_osk_mali.h" +#include "mali_ukk.h" +/*#include "mali_timestamp.h" +*/ + +_mali_osk_errcode_t _mali_ukk_vsync_event_report(_mali_uk_vsync_event_report_s *args) +{ + _mali_uk_vsync_event event = (_mali_uk_vsync_event)args->event; + MALI_IGNORE(event); /* event is not used for release code, and that is OK */ +/* u64 ts = _mali_timestamp_get(); + */ + + MALI_DEBUG_PRINT(4, ("Received VSYNC event: %d\n", event)); + + MALI_SUCCESS; +} + diff --git a/drivers/gpu/arm/mali/common/mali_osk.h b/drivers/gpu/arm/mali/common/mali_osk.h index a287a6af7dc..77a96dcfb50 100755 --- a/drivers/gpu/arm/mali/common/mali_osk.h +++ b/drivers/gpu/arm/mali/common/mali_osk.h @@ -54,7 +54,7 @@ extern "C" /** @brief Mali Boolean type which uses MALI_TRUE and MALI_FALSE */ typedef unsigned long mali_bool; - + #ifndef MALI_TRUE #define MALI_TRUE ((mali_bool)1) #endif @@ -700,6 +700,16 @@ void _mali_osk_irq_schedulework( _mali_osk_irq_t *irq ); * resource whose IRQ handling is to be terminated. */ void _mali_osk_irq_term( _mali_osk_irq_t *irq ); + +/** @brief flushing workqueue. + * + * This will flush the workqueue. + * + * @param irq a pointer to the _mali_osk_irq_t object corresponding to the + * resource whose IRQ handling is to be terminated. + */ +void _mali_osk_flush_workqueue( _mali_osk_irq_t *irq ); + /** @} */ /* end group _mali_osk_irq */ @@ -871,7 +881,7 @@ void *_mali_osk_memset( void *s, u32 c, u32 n ); /** @brief Checks the amount of memory allocated * - * Checks that not more than \a max_allocated bytes are allocated. + * Checks that not more than \a max_allocated bytes are allocated. * * Some OS bring up an interactive out of memory dialogue when the * system runs out of memory. This can stall non-interactive @@ -879,7 +889,7 @@ void *_mali_osk_memset( void *s, u32 c, u32 n ); * not trigger the OOM dialogue by keeping allocations * within a certain limit. * - * @return MALI_TRUE when \a max_allocated bytes are not in use yet. MALI_FALSE + * @return MALI_TRUE when \a max_allocated bytes are not in use yet. MALI_FALSE * when at least \a max_allocated bytes are in use. */ mali_bool _mali_osk_mem_check_allocated( u32 max_allocated ); @@ -1147,7 +1157,7 @@ void _mali_osk_cache_flushall( void ); * * Some OS do not perform a full cache flush (including all outer caches) for uncached mapped memory. * They zero the memory through a cached mapping, then flush the inner caches but not the outer caches. - * This is required for MALI to have the correct view of the memory. + * This is required for MALI to have the correct view of the memory. */ void _mali_osk_cache_ensure_uncached_range_flushed( void *uncached_mapping, u32 offset, u32 size ); @@ -1303,6 +1313,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. @@ -1511,7 +1532,7 @@ u32 _mali_osk_time_tickcount( void ); void _mali_osk_time_ubusydelay( u32 usecs ); /** @brief Return time in nano seconds, since any given reference. - * + * * @return Time in nano seconds */ u64 _mali_osk_time_get_ns( void ); @@ -1548,6 +1569,18 @@ u32 _mali_osk_clz( u32 val ); */ void _mali_osk_dbgmsg( const char *fmt, ... ); +/** @brief Print fmt into buf. + * + * The interpretation of \a fmt is the same as the \c format parameter in + * _mali_osu_vsnprintf(). + * + * @param buf a pointer to the result buffer + * @param size the total number of bytes allowed to write to \a buf + * @param fmt a _mali_osu_vsnprintf() style format string + * @param ... a variable-number of parameters suitable for \a fmt + */ +u32 _mali_osk_snprintf( char *buf, u32 size, const char *fmt, ... ); + /** @brief Abnormal process abort. * * Terminates the caller-process if this function is called. diff --git a/drivers/gpu/arm/mali/common/mali_osk_list.h b/drivers/gpu/arm/mali/common/mali_osk_list.h index bfa6cdbe88a..a8d15f2a107 100755 --- a/drivers/gpu/arm/mali/common/mali_osk_list.h +++ b/drivers/gpu/arm/mali/common/mali_osk_list.h @@ -126,7 +126,7 @@ MALI_STATIC_INLINE void _mali_osk_list_delinit( _mali_osk_list_t *list ) * An empty list is one that contains a single element that points to itself. * * @param list the list to check. - * @return non-zero if the list it empty, and zero otherwise. + * @return non-zero if the list is empty, and zero otherwise. */ MALI_STATIC_INLINE int _mali_osk_list_empty( _mali_osk_list_t *list ) { diff --git a/drivers/gpu/arm/mali/common/mali_uk_types.h b/drivers/gpu/arm/mali/common/mali_uk_types.h index 6af29f39b44..dc40b2bad2d 100755 --- a/drivers/gpu/arm/mali/common/mali_uk_types.h +++ b/drivers/gpu/arm/mali/common/mali_uk_types.h @@ -55,6 +55,7 @@ typedef enum _MALI_UK_GP_SUBSYSTEM, /**< Vertex Processor Group of U/K calls */ _MALI_UK_PROFILING_SUBSYSTEM, /**< Profiling Group of U/K calls */ _MALI_UK_PMM_SUBSYSTEM, /**< Power Management Module Group of U/K calls */ + _MALI_UK_VSYNC_SUBSYSTEM, /**< VSYNC Group of U/K calls */ } _mali_uk_subsystem_t; /** Within a function group each function has its unique sequence number @@ -125,6 +126,10 @@ typedef enum /** Power Management Module Functions */ _MALI_UK_PMM_EVENT_MESSAGE = 0, /**< Raise an event message */ #endif + + /** VSYNC reporting fuctions */ + _MALI_UK_VSYNC_EVENT_REPORT = 0, /**< _mali_ukk_vsync_event_report() */ + } _mali_uk_functions; /** @brief Get the size necessary for system info @@ -613,7 +618,6 @@ typedef enum { /** core notifications */ - _MALI_NOTIFICATION_CORE_TIMEOUT = (_MALI_UK_CORE_SUBSYSTEM << 16) | 0x10, _MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS = (_MALI_UK_CORE_SUBSYSTEM << 16) | 0x20, _MALI_NOTIFICATION_APPLICATION_QUIT = (_MALI_UK_CORE_SUBSYSTEM << 16) | 0x40, @@ -647,13 +651,6 @@ typedef enum * * Interpreting the data union member depends on the notification type: * - * - type == _MALI_NOTIFICATION_CORE_TIMEOUT - * - A notification timeout has occurred, since the code.timeout member was - * exceeded. - * - In this case, the value of the data union member is undefined. - * - This is used so that the client can check other user-space state. - * The client may repeat the call to _mali_ukk_wait_for_notification() to - * continue reception of notifications. * - type == _MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS * - The kernel side is shutting down. No further * _mali_uk_wait_for_notification() calls should be made. @@ -736,7 +733,7 @@ typedef struct * The 16bit integer is stored twice in a 32bit integer * For example, for version 1 the value would be 0x00010001 */ -#define _MALI_API_VERSION 7 +#define _MALI_API_VERSION 8 #define _MALI_UK_API_VERSION _MAKE_VERSION_ID(_MALI_API_VERSION) /** @@ -1105,7 +1102,7 @@ typedef u32 mali_pmm_message_data; /** @brief Arguments to _mali_ukk_pmm_event_message() */ -typedef struct +typedef struct { void *ctx; /**< [in,out] user-kernel context (trashed on output) */ u32 id; /**< [in] event id */ @@ -1115,6 +1112,31 @@ typedef struct /** @} */ /* end group _mali_uk_pmm */ #endif /* USING_MALI_PMM */ +/** @defgroup _mali_uk_vsync U/K VSYNC Wait Reporting Module + * @{ */ + +/** @brief VSYNC events + * + * These events are reported when DDK starts to wait for vsync and when the + * vsync has occured and the DDK can continue on the next frame. + */ +typedef enum _mali_uk_vsync_event +{ + _MALI_UK_VSYNC_EVENT_BEGIN_WAIT = 0, + _MALI_UK_VSYNC_EVENT_END_WAIT +} _mali_uk_vsync_event; + +/** @brief Arguments to _mali_ukk_vsync_event() + * + */ +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + _mali_uk_vsync_event event; /**< [in] VSYNCH event type */ +} _mali_uk_vsync_event_report_s; + +/** @} */ /* end group _mali_uk_vsync */ + /** @} */ /* end group u_k_api */ /** @} */ /* end group uddapi */ diff --git a/drivers/gpu/arm/mali/common/mali_ukk.h b/drivers/gpu/arm/mali/common/mali_ukk.h index 981a1f07c53..ccd9ac80cd5 100755 --- a/drivers/gpu/arm/mali/common/mali_ukk.h +++ b/drivers/gpu/arm/mali/common/mali_ukk.h @@ -663,7 +663,7 @@ _mali_osk_errcode_t _mali_ukk_profiling_start(_mali_uk_profiling_start_s *args); _mali_osk_errcode_t _mali_ukk_profiling_add_event(_mali_uk_profiling_add_event_s *args); /** @brief Stop recording profiling events. - * + * * @param args see _mali_uk_profiling_stop_s in "mali_uk_types.h" */ _mali_osk_errcode_t _mali_ukk_profiling_stop(_mali_uk_profiling_stop_s *args); @@ -683,6 +683,21 @@ _mali_osk_errcode_t _mali_ukk_profiling_clear(_mali_uk_profiling_clear_s *args); /** @} */ /* end group _mali_uk_profiling */ #endif +/** @addtogroup _mali_uk_vsync U/K VSYNC reporting module + * @{ */ + +/** @brief Report events related to vsync. + * + * @note Events should be reported when starting to wait for vsync and when the + * waiting is finished. This information can then be used in kernel space to + * complement the GPU utilization metric. + * + * @param args see _mali_uk_vsync_event_report_s in "mali_uk_types.h" + */ +_mali_osk_errcode_t _mali_ukk_vsync_event_report(_mali_uk_vsync_event_report_s *args); + +/** @} */ /* end group _mali_uk_vsync */ + /** @} */ /* end group u_k_api */ /** @} */ /* end group uddapi */ diff --git a/drivers/gpu/arm/mali/common/pmm/mali_pmm.c b/drivers/gpu/arm/mali/common/pmm/mali_pmm.c index 39a5a6e21d5..dd8f5e3a284 100755 --- a/drivers/gpu/arm/mali/common/pmm/mali_pmm.c +++ b/drivers/gpu/arm/mali/common/pmm/mali_pmm.c @@ -30,10 +30,7 @@ static _mali_pmm_internal_state_t *pmm_state = NULL; /* Mali kernel subsystem id */ static mali_kernel_subsystem_identifier mali_subsystem_pmm_id = -1; -/* lock for SMP */ -#ifdef CONFIG_SMP -_mali_osk_lock_t *mali_pmm_lock; -#endif /* CONFIG_SMP */ +static u32 pmm_cores_registered_mask = 0; #define GET_PMM_STATE_PTR (pmm_state) @@ -68,6 +65,10 @@ _mali_osk_errcode_t malipmm_kernel_load_complete( mali_kernel_subsystem_identifi */ void malipmm_kernel_subsystem_terminate( mali_kernel_subsystem_identifier id ); +#if MALI_STATE_TRACKING +u32 malipmm_subsystem_dump_state( char *buf, u32 size ); +#endif + /* This will be one of the subsystems in the array of subsystems: static struct mali_kernel_subsystem * subsystems[]; @@ -82,7 +83,10 @@ struct mali_kernel_subsystem mali_subsystem_pmm= NULL, NULL, NULL, -} ; +#if MALI_STATE_TRACKING + malipmm_subsystem_dump_state, /* dump_state */ +#endif +}; #if PMM_OS_TEST @@ -192,7 +196,7 @@ void _mali_ukk_pmm_event_message( _mali_uk_pmm_message_s *args ) { /* Internal PMM message */ _mali_osk_notification_queue_send( pmm->iqueue, msg ); - #if MALI_PMM_TRACE + #if (MALI_PMM_TRACE || MALI_STATE_TRACKING) pmm->imessages_sent++; #endif } @@ -200,7 +204,7 @@ void _mali_ukk_pmm_event_message( _mali_uk_pmm_message_s *args ) { /* Real event */ _mali_osk_notification_queue_send( pmm->queue, msg ); - #if MALI_PMM_TRACE + #if (MALI_PMM_TRACE || MALI_STATE_TRACKING) pmm->messages_sent++; #endif } @@ -293,7 +297,7 @@ _mali_osk_errcode_t _mali_pmm_get_policy( mali_pmm_policy *policy ) MALI_ERROR( _MALI_OSK_ERR_INVALID_ARGS ); } -#if MALI_PMM_TRACE +#if ( MALI_PMM_TRACE || MALI_STATE_TRACKING ) /* Event names - order must match mali_pmm_event_id enum */ static char *pmm_trace_events[] = { @@ -305,19 +309,6 @@ static char *pmm_trace_events[] = { "TIMEOUT", }; -/* UK event names - order must match mali_pmm_event_id enum */ -static char *pmm_trace_events_uk[] = { - "UKS", - "UK_EXAMPLE", -}; - -/* Internal event names - order must match mali_pmm_event_id enum */ -static char *pmm_trace_events_internal[] = { - "INTERNALS", - "INTERNAL_POWER_UP_ACK", - "INTERNAL_POWER_DOWN_ACK", -}; - /* State names - order must match mali_pmm_state enum */ static char *pmm_trace_state[] = { "UNAVAILABLE", @@ -333,6 +324,35 @@ static char *pmm_trace_policy[] = { "JOB CONTROL", }; +/* Status names - order must match mali_pmm_status enum */ +static char *pmm_trace_status[] = { + "MALI_PMM_STATUS_IDLE", /**< PMM is waiting next event */ + "MALI_PMM_STATUS_POLICY_POWER_DOWN", /**< Policy initiated power down */ + "MALI_PMM_STATUS_POLICY_POWER_UP", /**< Policy initiated power down */ + "MALI_PMM_STATUS_OS_WAITING", /**< PMM is waiting for OS power up */ + "MALI_PMM_STATUS_OS_POWER_DOWN", /**< OS initiated power down */ + "MALI_PMM_STATUS_RUNTIME_IDLE_IN_PROGRESS", + "MALI_PMM_STATUS_DVFS_PAUSE", /**< PMM DVFS Status Pause */ + "MALI_PMM_STATUS_OS_POWER_UP", /**< OS initiated power up */ + "MALI_PMM_STATUS_OFF", /**< PMM is not active */ +}; + +#endif /* MALI_PMM_TRACE || MALI_STATE_TRACKING */ +#if MALI_PMM_TRACE + +/* UK event names - order must match mali_pmm_event_id enum */ +static char *pmm_trace_events_uk[] = { + "UKS", + "UK_EXAMPLE", +}; + +/* Internal event names - order must match mali_pmm_event_id enum */ +static char *pmm_trace_events_internal[] = { + "INTERNALS", + "INTERNAL_POWER_UP_ACK", + "INTERNAL_POWER_DOWN_ACK", +}; + void _mali_pmm_trace_hardware_change( mali_pmm_core_mask old, mali_pmm_core_mask newstate ) { const char *dname; @@ -499,10 +519,6 @@ _mali_osk_errcode_t malipmm_create(_mali_osk_resource_t *resource) "PMM handler" ); if( !pmm_state->irq ) goto pmm_fail_cleanup; -#ifdef CONFIG_SMP - mali_pmm_lock = _mali_osk_lock_init((_mali_osk_lock_flags_t)( _MALI_OSK_LOCKFLAG_READERWRITER | _MALI_OSK_LOCKFLAG_ORDERED), 0, 0); - if( !mali_pmm_lock ) goto pmm_fail_cleanup; -#endif /* CONFIG_SMP */ pmm_state->lock = _mali_osk_lock_init((_mali_osk_lock_flags_t)(_MALI_OSK_LOCKFLAG_READERWRITER | _MALI_OSK_LOCKFLAG_ORDERED), 0, 75); if( !pmm_state->lock ) goto pmm_fail_cleanup; @@ -549,6 +565,29 @@ _mali_osk_errcode_t malipmm_kernel_load_complete( mali_kernel_subsystem_identifi return pmm_policy_init( pmm ); } +void malipmm_force_powerup( void ) +{ + _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR; + MALI_DEBUG_ASSERT_POINTER(pmm); + MALI_PMM_LOCK(pmm); + pmm->status = MALI_PMM_STATUS_OFF; + pmm_cores_registered_mask = pmm->cores_registered; + MALI_PMM_UNLOCK(pmm); + + /* flush PMM workqueue */ + _mali_osk_flush_workqueue( pmm->irq ); + + if (pmm->cores_powered == 0) + { + mali_platform_powerup(pmm_cores_registered_mask); + } +} + +void malipmm_force_powerdown( void ) +{ + mali_platform_powerdown(pmm_cores_registered_mask); +} + void malipmm_kernel_subsystem_terminate( mali_kernel_subsystem_identifier id ) { /* Check this is the right system */ @@ -563,14 +602,17 @@ void malipmm_kernel_subsystem_terminate( mali_kernel_subsystem_identifier id ) #endif /* Get the lock so we can shutdown */ MALI_PMM_LOCK(pmm_state); +#if MALI_STATE_TRACKING + pmm_state->mali_pmm_lock_acquired = 1; +#endif /* MALI_STATE_TRACKING */ pmm_state->status = MALI_PMM_STATUS_OFF; +#if MALI_STATE_TRACKING + pmm_state->mali_pmm_lock_acquired = 0; +#endif /* MALI_STATE_TRACKING */ MALI_PMM_UNLOCK(pmm_state); + _mali_osk_pmm_ospmm_cleanup(); pmm_policy_term(pmm_state); _mali_osk_irq_term( pmm_state->irq ); -#ifdef CONFIG_SMP - _mali_osk_lock_term(mali_pmm_lock); -#endif /* CONFIG_SMP */ - _mali_osk_notification_queue_term( pmm_state->queue ); _mali_osk_notification_queue_term( pmm_state->iqueue ); if( pmm_state->pmu_initialized ) mali_platform_deinit(&t); @@ -602,6 +644,11 @@ _mali_osk_errcode_t malipmm_core_register( mali_pmm_core_id core ) MALI_PMM_LOCK(pmm); +#if MALI_STATE_TRACKING + pmm->mali_pmm_lock_acquired = 1; +#endif /* MALI_STATE_TRACKING */ + + /* Check if the core is registered more than once in PMM */ MALI_DEBUG_ASSERT( (pmm->cores_registered & core) == 0 ); @@ -634,6 +681,10 @@ _mali_osk_errcode_t malipmm_core_register( mali_pmm_core_id core ) err, core, pmm_trace_get_core_name(core)) ); } +#if MALI_STATE_TRACKING + pmm->mali_pmm_lock_acquired = 0; +#endif /* MALI_STATE_TRACKING */ + MALI_PMM_UNLOCK(pmm); return err; @@ -645,6 +696,10 @@ void malipmm_core_unregister( mali_pmm_core_id core ) MALI_DEBUG_ASSERT_POINTER(pmm); MALI_PMM_LOCK(pmm); +#if MALI_STATE_TRACKING + pmm->mali_pmm_lock_acquired = 1; +#endif /* MALI_STATE_TRACKING */ + /* Check if the core is registered in PMM */ MALI_PMM_DEBUG_ASSERT_CORES_SUBSET( pmm->cores_registered, core ); @@ -655,16 +710,6 @@ void malipmm_core_unregister( mali_pmm_core_id core ) #if MALI_PMM_TRACE mali_pmm_core_mask old_power = pmm->cores_powered; #endif - -#if !MALI_PMM_NO_PMU - /* Turn off the core */ - if( mali_platform_powerdown( core ) != _MALI_OSK_ERR_OK ) - { - MALI_PRINT_ERROR( ("PMM: Error powering down unregistered core: (0x%x) %s\n", - core, pmm_trace_get_core_name(core)) ); - } -#endif - /* Remove the core from the system */ pmm->cores_registered &= (~core); pmm->cores_idle &= (~core); @@ -681,6 +726,10 @@ void malipmm_core_unregister( mali_pmm_core_id core ) #endif } +#if MALI_STATE_TRACKING + pmm->mali_pmm_lock_acquired = 0; +#endif /* MALI_STATE_TRACKING */ + MALI_PMM_UNLOCK(pmm); } void malipmm_core_power_down_okay( mali_pmm_core_id core ) @@ -722,18 +771,20 @@ void malipmm_irq_bhandler(void *data) if( power_test_check() ) return; #endif -#ifdef CONFIG_SMP - _mali_osk_lock_wait( mali_pmm_lock, _MALI_OSK_LOCKMODE_RW ); -#endif /* CONFIG_SMP */ MALI_PMM_LOCK(pmm); +#if MALI_STATE_TRACKING + pmm->mali_pmm_lock_acquired = 1; +#endif /* MALI_STATE_TRACKING */ /* Quick out when we are shutting down */ if( pmm->status == MALI_PMM_STATUS_OFF ) { + + #if MALI_STATE_TRACKING + pmm->mali_pmm_lock_acquired = 0; + #endif /* MALI_STATE_TRACKING */ + MALI_PMM_UNLOCK(pmm); -#ifdef CONFIG_SMP - _mali_osk_lock_signal( mali_pmm_lock, _MALI_OSK_LOCKMODE_RW ); -#endif /* CONFIG_SMP */ return; } @@ -761,10 +812,11 @@ void malipmm_irq_bhandler(void *data) } } +#if MALI_STATE_TRACKING + pmm->mali_pmm_lock_acquired = 0; +#endif /* MALI_STATE_TRACKING */ + MALI_PMM_UNLOCK(pmm); -#ifdef CONFIG_SMP - _mali_osk_lock_signal(mali_pmm_lock, _MALI_OSK_LOCKMODE_RW ); -#endif /* CONFIG_SMP */ } static void pmm_event_process( void ) @@ -805,10 +857,10 @@ static void pmm_event_process( void ) return; } else - { - #if MALI_PMM_TRACE + { + #if (MALI_PMM_TRACE || MALI_STATE_TRACKING) pmm->messages_received++; - #endif + #endif } } else @@ -821,9 +873,9 @@ static void pmm_event_process( void ) } else { - #if MALI_PMM_TRACE + #if (MALI_PMM_TRACE || MALI_STATE_TRACKING) pmm->imessages_received++; - #endif + #endif } MALI_DEBUG_ASSERT_POINTER( msg ); @@ -872,22 +924,37 @@ static void pmm_event_process( void ) } } -#ifdef DEBUG -void malipmm_state_dump() +#if MALI_STATE_TRACKING +u32 malipmm_subsystem_dump_state(char *buf, u32 size) { + int len = 0; _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR; if( !pmm ) { - MALI_PRINT(("PMM: Null state\n")); + len += _mali_osk_snprintf(buf + len, size + len, "PMM: Null state\n"); } else { - MALI_PRINT(("PMM state:\nstatus=%d\npolicy=%d\ncheck_policy=%d\nstate=%d\n", pmm->status, pmm->policy, pmm->check_policy, pmm->state)); - MALI_PRINT(("PMM cores:\ncores_registered=%d\ncores_powered=%d\ncores_idle=%d\ncores_pend_down=%d\ncores_pend_up=%d\ncores_ack_down=%d\ncores_ack_up=%d\n", pmm->cores_registered, pmm->cores_powered, pmm->cores_idle, pmm->cores_pend_down, pmm->cores_pend_up, pmm->cores_ack_down, pmm->cores_ack_up)); - MALI_PRINT(("PMM misc:\npmu_init=%d\nmessages_queued=%d\nwaiting=%d\nno_events=%d\nmissed=%d\nfatal_power_err=%d\n", pmm->pmu_initialized, _mali_osk_atomic_read( &(pmm->messages_queued) ), pmm->waiting, pmm->no_events, pmm->missed, pmm->fatal_power_err)); + len += _mali_osk_snprintf(buf+len, size+len, "Locks:\n PMM lock acquired: %s\n", + pmm->mali_pmm_lock_acquired ? "true" : "false"); + len += _mali_osk_snprintf(buf+len, size+len, + "PMM state:\n Previous status: %s\n Status: %s\n Current event: %s\n Policy: %s\n Check policy: %s\n State: %s\n", + pmm_trace_status[pmm->mali_last_pmm_status], pmm_trace_status[pmm->status], + pmm_trace_events[pmm->mali_new_event_status], pmm_trace_policy[pmm->policy], + pmm->check_policy ? "true" : "false", pmm_trace_state[pmm->state]); + len += _mali_osk_snprintf(buf+len, size+len, + "PMM cores:\n Cores registered: %d\n Cores powered: %d\n Cores idle: %d\n" + " Cores pending down: %d\n Cores pending up: %d\n Cores ack down: %d\n Cores ack up: %d\n", + pmm->cores_registered, pmm->cores_powered, pmm->cores_idle, pmm->cores_pend_down, + pmm->cores_pend_up, pmm->cores_ack_down, pmm->cores_ack_up); + len += _mali_osk_snprintf(buf+len, size+len, "PMM misc:\n PMU init: %s\n Messages queued: %d\n" + " Waiting: %d\n No events: %d\n Missed events: %d\n Fatal power error: %s\n", + pmm->pmu_initialized ? "true" : "false", _mali_osk_atomic_read(&(pmm->messages_queued)), + pmm->waiting, pmm->no_events, pmm->missed, pmm->fatal_power_err ? "true" : "false"); } + return len; } -#endif +#endif /* MALI_STATE_TRACKING */ #endif /* USING_MALI_PMM */ diff --git a/drivers/gpu/arm/mali/common/pmm/mali_pmm.h b/drivers/gpu/arm/mali/common/pmm/mali_pmm.h index 74a61b1cd45..7b45fd36eea 100755 --- a/drivers/gpu/arm/mali/common/pmm/mali_pmm.h +++ b/drivers/gpu/arm/mali/common/pmm/mali_pmm.h @@ -40,7 +40,7 @@ extern "C" /** @brief Compile option to switch between always on or job control PMM policy */ #define MALI_PMM_ALWAYS_ON 0 -/** @brief Overrides hardware PMU and uses software simulation instead +/** @brief Overrides hardware PMU and uses software simulation instead * @note This even stops intialization of PMU and cores being powered on at start up */ #define MALI_PMM_NO_PMU 0 @@ -52,7 +52,7 @@ extern "C" /** @brief power management event message identifiers. */ -/* These must match up with the pmm_trace_events & pmm_trace_events_internal +/* These must match up with the pmm_trace_events & pmm_trace_events_internal * arrays */ typedef enum mali_pmm_event_id @@ -137,7 +137,6 @@ typedef enum mali_pmm_policy_tag MALI_PMM_POLICY_RUNTIME_JOB_CONTROL = 3 /**< Run time power management control policy */ } mali_pmm_policy; - /** @brief Function to report to the OS when the power down has finished * * @param data The event message data that initiated the power down @@ -150,7 +149,7 @@ void _mali_osk_pmm_power_down_done(mali_pmm_message_data data); */ void _mali_osk_pmm_power_up_done(mali_pmm_message_data data); -/** @brief Function to report that DVFS operation done +/** @brief Function to report that DVFS operation done * * @param data The event message data */ @@ -165,6 +164,18 @@ void _mali_osk_pmm_policy_events_notifications(mali_pmm_event_id event_id); #endif +/** @brief Function to power up MALI + * + * @note powers up the MALI during MALI device driver is unloaded + */ +void malipmm_force_powerup( void ); + +/** @brief Function to power down MALI + * + * @note powers down the MALI during MALI device driver is unloaded + */ +void malipmm_force_powerdown( void ); + /** @brief Function to report the OS that device is idle * * @note inform the OS that device is idle @@ -177,6 +188,12 @@ _mali_osk_errcode_t _mali_osk_pmm_dev_idle( void ); */ void _mali_osk_pmm_dev_activate( void ); +/** @brief Function to report OS PMM for cleanup + * + * @note Function to report OS PMM for cleanup + */ +void _mali_osk_pmm_ospmm_cleanup( void ); + /** @brief Queries the current state of the PMM software * * @note the state of the PMM can change after this call has returned @@ -303,11 +320,11 @@ void _mali_pmm_trace_event_message( mali_pmm_message_t *event, mali_bool receive #endif /* MALI_PMM_TRACE */ -#ifdef DEBUG -/** @brief Dumps the current state of the PMM +/** @brief Dumps the current state of OS PMM thread */ -void malipmm_state_dump(void); -#endif +#if MALI_STATE_TRACKING +u32 mali_pmm_dump_os_thread_state( char *buf, u32 size ); +#endif /* MALI_STATE_TRACKING */ /** @} */ /* end group pmmapi */ diff --git a/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy.h b/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy.h index 83cb7f29a92..739c4c4ef17 100755 --- a/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy.h +++ b/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy.h @@ -46,7 +46,7 @@ typedef struct _pmm_policy_timer /** @brief Policy timer initialization * * This will create a timer for use in policies, but won't start it - * + * * @param pptimer An empty timer structure to be initialized * @param timeout Timeout in ticks for the timer * @param id Event id that will be raised on timeout @@ -59,7 +59,7 @@ _mali_osk_errcode_t pmm_policy_timer_init( _pmm_policy_timer_t *pptimer, u32 tim * * This will clean up a timer that was previously used in policies, it * will also stop it if started - * + * * @param pptimer An initialized timer structure to be terminated */ void pmm_policy_timer_term( _pmm_policy_timer_t *pptimer ); @@ -67,10 +67,10 @@ void pmm_policy_timer_term( _pmm_policy_timer_t *pptimer ); /** @brief Policy timer start * * This will start a previously created timer for use in policies - * When the timer expires after the initialized timeout it will raise + * When the timer expires after the initialized timeout it will raise * a PMM event of the event id given on initialization * As data for the event it will pass the start time of the timer - * + * * @param pptimer A previously initialized policy timer * @return MALI_TRUE if the timer was started, MALI_FALSE if it is already started */ @@ -79,7 +79,7 @@ mali_bool pmm_policy_timer_start( _pmm_policy_timer_t *pptimer ); /** @brief Policy timer stop * * This will stop a previously created timer for use in policies - * + * * @param pptimer A previously started policy timer * @return MALI_TRUE if the timer was stopped, MALI_FALSE if it is already stopped */ @@ -88,7 +88,7 @@ mali_bool pmm_policy_timer_stop( _pmm_policy_timer_t *pptimer ); /** @brief Policy timer stop * * This raise an event for an expired timer - * + * * @param pptimer An expired policy timer * @return MALI_TRUE if an event was raised, else MALI_FALSE */ @@ -97,7 +97,7 @@ mali_bool pmm_policy_timer_raise_event( _pmm_policy_timer_t *pptimer ); /** @brief Policy timer valid checker * * This will check that a timer was started after a given time - * + * * @param timer_start Time the timer was started * @param other_start Time when another event or action occurred * @return MALI_TRUE if the timer was started after the other time, else MALI_FALSE @@ -106,7 +106,7 @@ mali_bool pmm_policy_timer_valid( u32 timer_start, u32 other_start ); /** @brief Common policy initialization - * + * * This will initialize the current policy * * @note Any previously initialized policy should be terminated first diff --git a/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy_jobcontrol.c b/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy_jobcontrol.c index 192647d6306..8450bd722f4 100755 --- a/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy_jobcontrol.c +++ b/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy_jobcontrol.c @@ -173,6 +173,10 @@ _mali_osk_errcode_t pmm_policy_process_job_control( _mali_pmm_internal_state_t * /* Mainly the data is the cores */ cores = pmm_cores_from_event_data( pmm, event ); +#if MALI_STATE_TRACKING + pmm->mali_last_pmm_status = pmm->status; +#endif /* MALI_STATE_TRACKING */ + switch( pmm->status ) { /**************** IDLE ****************/ @@ -217,7 +221,7 @@ _mali_osk_errcode_t pmm_policy_process_job_control( _mali_pmm_internal_state_t * } } pmm->status = MALI_PMM_STATUS_DVFS_PAUSE; - _mali_osk_pmm_dvfs_operation_done( 0 ); + _mali_osk_pmm_dvfs_operation_done(0); break; case MALI_PMM_EVENT_OS_POWER_DOWN: @@ -300,7 +304,7 @@ _mali_osk_errcode_t pmm_policy_process_job_control( _mali_pmm_internal_state_t * { case MALI_PMM_EVENT_DVFS_RESUME: - if ( pmm->cores_powered !=0) + if ( pmm->cores_powered != 0 ) { pmm->cores_ack_down =0; pmm_power_down_cancel( pmm ); @@ -316,9 +320,9 @@ _mali_osk_errcode_t pmm_policy_process_job_control( _mali_pmm_internal_state_t * case MALI_PMM_EVENT_OS_POWER_DOWN: /* Set waiting status */ pmm->status = MALI_PMM_STATUS_OS_WAITING; - if ( pmm->cores_powered != 0) + if ( pmm->cores_powered != 0 ) { - if( pmm_invoke_power_down( pmm ) ) + if ( pmm_invoke_power_down( pmm ) ) { _mali_osk_pmm_power_down_done( 0 ); break; @@ -373,7 +377,7 @@ _mali_osk_errcode_t pmm_policy_process_job_control( _mali_pmm_internal_state_t * if( pmm_power_down_okay( pmm ) ) { pmm->is_dvfs_active = 0; - pmm->status = MALI_PMM_STATUS_DVFS_PAUSE; + pmm->status = MALI_PMM_STATUS_DVFS_PAUSE; _mali_osk_pmm_dvfs_operation_done( pmm_retrieve_os_event_data( pmm ) ); } break; @@ -436,6 +440,10 @@ _mali_osk_errcode_t pmm_policy_process_job_control( _mali_pmm_internal_state_t * /* Update the PMM state */ pmm_update_system_state( pmm ); +#if MALI_STATE_TRACKING + pmm->mali_new_event_status = event->id; +#endif /* MALI_STATE_TRACKING */ + MALIPMM_DEBUG_PRINT( ("PMM: Job control policy process end - status=%d and event=%d\n", pmm->status,event->id) ); MALI_SUCCESS; diff --git a/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy_jobcontrol.h b/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy_jobcontrol.h index 455234b80bc..f1e7c2d9a82 100755 --- a/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy_jobcontrol.h +++ b/drivers/gpu/arm/mali/common/pmm/mali_pmm_policy_jobcontrol.h @@ -27,10 +27,10 @@ extern "C" * @{ */ -/** @brief The jobcontrol policy inactivity latency timeout (in ticks) +/** @brief The jobcontrol policy inactivity latency timeout (in ticks) * before the hardware is switched off * - * @note Setting this low whilst tracing or producing debug output can + * @note Setting this low whilst tracing or producing debug output can * cause alot of timeouts to fire which can affect the PMM behaviour */ #define MALI_PMM_POLICY_JOBCONTROL_INACTIVITY_TIMEOUT 50 diff --git a/drivers/gpu/arm/mali/common/pmm/mali_pmm_state.c b/drivers/gpu/arm/mali/common/pmm/mali_pmm_state.c index 69193a25459..a0ac1c7790c 100755 --- a/drivers/gpu/arm/mali/common/pmm/mali_pmm_state.c +++ b/drivers/gpu/arm/mali/common/pmm/mali_pmm_state.c @@ -167,6 +167,10 @@ mali_pmm_core_mask pmm_cores_to_power_down( _mali_pmm_internal_state_t *pmm, mal * as the core is unregistered before we tell it to power * down, but it does not matter as we are terminating */ +#if MALI_STATE_TRACKING + pmm->mali_pmm_lock_acquired = 0; +#endif /* MALI_STATE_TRACKING */ + MALI_PMM_UNLOCK(pmm); /* Signal the core to power down * If it is busy (not idle) it will set a pending power down flag @@ -177,6 +181,11 @@ mali_pmm_core_mask pmm_cores_to_power_down( _mali_pmm_internal_state_t *pmm, mal err = mali_core_signal_power_down( cores_list[n], immediate_only ); MALI_PMM_LOCK(pmm); +#if MALI_STATE_TRACKING + pmm->mali_pmm_lock_acquired = 1; +#endif /* MALI_STATE_TRACKING */ + + /* Re-read cores_subset in case it has changed */ cores_subset = (*ppowered & cores); @@ -244,12 +253,19 @@ void pmm_power_down_cancel( _mali_pmm_internal_state_t *pmm ) * as the core is unregistered before we tell it to power * up, but it does not matter as we are terminating */ +#if MALI_STATE_TRACKING + pmm->mali_pmm_lock_acquired = 0; +#endif /* MALI_STATE_TRACKING */ + MALI_PMM_UNLOCK(pmm); /* As we are cancelling - only move the cores back to the queue - * no reset needed */ err = mali_core_signal_power_up( cores_list[n], MALI_TRUE ); MALI_PMM_LOCK(pmm); +#if MALI_STATE_TRACKING + pmm->mali_pmm_lock_acquired = 1; +#endif /* MALI_STATE_TRACKING */ /* Update pending list with the current registered cores */ pd &= (*pregistered); @@ -374,10 +390,19 @@ mali_bool pmm_invoke_power_up( _mali_pmm_internal_state_t *pmm ) * as the core is unregistered before we tell it to power * up, but it does not matter as we are terminating */ +#if MALI_STATE_TRACKING + pmm->mali_pmm_lock_acquired = 0; +#endif /* MALI_STATE_TRACKING */ + MALI_PMM_UNLOCK(pmm); err = mali_core_signal_power_up( cores_list[n], MALI_FALSE ); MALI_PMM_LOCK(pmm); +#if MALI_STATE_TRACKING + pmm->mali_pmm_lock_acquired = 1; +#endif /* MALI_STATE_TRACKING */ + + if( err != _MALI_OSK_ERR_OK ) { MALI_DEBUG_ASSERT( (err == _MALI_OSK_ERR_FAULT && @@ -527,10 +552,18 @@ void pmm_fatal_reset( _mali_pmm_internal_state_t *pmm ) { if( (cores_list[n] & (*pregistered)) != 0 ) { +#if MALI_STATE_TRACKING + pmm->mali_pmm_lock_acquired = 0; +#endif /* MALI_STATE_TRACKING */ + MALI_PMM_UNLOCK(pmm); /* Core is now active - so try putting it in the idle queue */ err = mali_core_signal_power_up( cores_list[n], MALI_FALSE ); MALI_PMM_LOCK(pmm); +#if MALI_STATE_TRACKING + pmm->mali_pmm_lock_acquired = 1; +#endif /* MALI_STATE_TRACKING */ + /* We either succeeded, or we were not off anyway, or we have * just be deregistered */ diff --git a/drivers/gpu/arm/mali/common/pmm/mali_pmm_state.h b/drivers/gpu/arm/mali/common/pmm/mali_pmm_state.h index f019fb67b77..c2fb32171c4 100755 --- a/drivers/gpu/arm/mali/common/pmm/mali_pmm_state.h +++ b/drivers/gpu/arm/mali/common/pmm/mali_pmm_state.h @@ -55,8 +55,7 @@ typedef enum mali_pmm_status_tag MALI_PMM_STATUS_POLICY_POWER_DOWN, /**< Policy initiated power down */ MALI_PMM_STATUS_POLICY_POWER_UP, /**< Policy initiated power down */ MALI_PMM_STATUS_OS_WAITING, /**< PMM is waiting for OS power up */ - MALI_PMM_STATUS_OS_POWER_DOWN, /**< OS initiated power down */ - MALI_PMM_STATUS_RUNTIME_IDLE_IN_PROGRESS, + MALI_PMM_STATUS_OS_POWER_DOWN, /**< OS initiated power down */ MALI_PMM_STATUS_DVFS_PAUSE, /**< PMM DVFS Status Pause */ MALI_PMM_STATUS_OS_POWER_UP, /**< OS initiated power up */ MALI_PMM_STATUS_OFF, /**< PMM is not active */ @@ -95,8 +94,14 @@ typedef struct _mali_pmm_internal_state u32 missed; /**< PMM missed events due to OOM */ mali_bool fatal_power_err; /**< PMM has had a fatal power error? */ u32 is_dvfs_active; /**< PMM DVFS activity */ - -#if MALI_PMM_TRACE + +#if MALI_STATE_TRACKING + mali_pmm_status mali_last_pmm_status; /**< The previous PMM status */ + mali_pmm_event_id mali_new_event_status;/**< The type of the last PMM event */ + mali_bool mali_pmm_lock_acquired; /**< Is the PMM lock held somewhere or not */ +#endif + +#if (MALI_PMM_TRACE || MALI_STATE_TRACKING) u32 messages_sent; /**< Total event messages sent */ u32 messages_received; /**< Total event messages received */ u32 imessages_sent; /**< Total event internal messages sent */ @@ -127,11 +132,11 @@ mali_pmm_core_mask pmm_cores_from_event_data( _mali_pmm_internal_state_t *pmm, m /** @brief Sort out which cores need to be powered up from the given core mask * - * All cores that can be powered up will be put into a pending state + * All cores that can be powered up will be put into a pending state * * @param pmm internal PMM state * @param cores mask of cores to check if they need to be powered up - * @return mask of cores that need to be powered up, this can be 0 if all cores + * @return mask of cores that need to be powered up, this can be 0 if all cores * are powered up already */ mali_pmm_core_mask pmm_cores_to_power_up( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores ); @@ -147,7 +152,7 @@ mali_pmm_core_mask pmm_cores_to_power_up( _mali_pmm_internal_state_t *pmm, mali_ * @param cores mask of cores to check if they need to be powered down * @param immediate_only MALI_TRUE means that only cores that can power down now will * be put into a pending state - * @return mask of cores that need to be powered down, this can be 0 if all cores + * @return mask of cores that need to be powered down, this can be 0 if all cores * are powered down already */ mali_pmm_core_mask pmm_cores_to_power_down( _mali_pmm_internal_state_t *pmm, mali_pmm_core_mask cores, mali_bool immediate_only ); @@ -171,7 +176,7 @@ mali_bool pmm_power_down_okay( _mali_pmm_internal_state_t *pmm ); /** @brief Try to make all the pending cores power down * - * If all the pending cores have acknowledged they can power down, this will call the + * If all the pending cores have acknowledged they can power down, this will call the * PMU power down function to turn them off * * @param pmm internal PMM state @@ -224,7 +229,7 @@ mali_pmm_core_mask pmm_cores_set_idle( _mali_pmm_internal_state_t *pmm, mali_pmm /** @brief Set the cores that have acknowledged a pending power down * - * Updates which cores have acknowledged the pending power down and are now ready + * Updates which cores have acknowledged the pending power down and are now ready * to be turned off * * @param pmm internal PMM state @@ -247,15 +252,15 @@ mali_pmm_core_mask pmm_cores_set_up_ack( _mali_pmm_internal_state_t *pmm, mali_p /** @brief Tries to reset the PMM and PMU hardware to a known state after any fatal issues * - * This will try and make all the cores powered up and reset the PMM state - * to its initial state after core registration - all cores powered but not + * This will try and make all the cores powered up and reset the PMM state + * to its initial state after core registration - all cores powered but not * pending or active. * All events in the event queues will be thrown away. * * @note: Any pending power down will be cancelled including the OS calling for power down */ void pmm_fatal_reset( _mali_pmm_internal_state_t *pmm ); - + /** @brief Save the OS specific data for an OS power up/down event * * @param pmm internal PMM state diff --git a/drivers/gpu/arm/mali/linux/license/gpl/mali_kernel_license.h b/drivers/gpu/arm/mali/linux/license/gpl/mali_kernel_license.h index e9e5e55a082..2220b3b35ef 100644 --- a/drivers/gpu/arm/mali/linux/license/gpl/mali_kernel_license.h +++ b/drivers/gpu/arm/mali/linux/license/gpl/mali_kernel_license.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 ARM Limited. All rights reserved. + * Copyright (C) 2010-2011 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. diff --git a/drivers/gpu/arm/mali/linux/mali_device_pause_resume.c b/drivers/gpu/arm/mali/linux/mali_device_pause_resume.c index 1c1bf306688..7a69ae95011 100755 --- a/drivers/gpu/arm/mali/linux/mali_device_pause_resume.c +++ b/drivers/gpu/arm/mali/linux/mali_device_pause_resume.c @@ -31,13 +31,8 @@ int mali_dev_pause() { int err = 0; _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); - if ((mali_dvfs_device_state == _MALI_DEVICE_SUSPEND) || (mali_device_state == _MALI_DEVICE_SUSPEND_IN_PROGRESS) - || (mali_device_state == _MALI_DEVICE_SUSPEND) -#ifdef CONFIG_HAS_EARLYSUSPEND - || (mali_device_state == _MALI_DEVICE_EARLYSUSPEND_DISABLE_FB)) -#else - ) -#endif + if ((mali_dvfs_device_state == _MALI_DEVICE_SUSPEND) + || (mali_device_state == _MALI_DEVICE_SUSPEND) ) { err = -EPERM; } @@ -56,13 +51,8 @@ int mali_dev_resume() { int err = 0; _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); - if ((mali_dvfs_device_state == _MALI_DEVICE_RESUME) || (mali_device_state == _MALI_DEVICE_SUSPEND_IN_PROGRESS) - || (mali_device_state == _MALI_DEVICE_SUSPEND) -#ifdef CONFIG_HAS_EARLYSUSPEND - || (mali_device_state == _MALI_DEVICE_EARLYSUSPEND_DISABLE_FB)) -#else - ) -#endif + if ((mali_dvfs_device_state == _MALI_DEVICE_RESUME) + || (mali_device_state == _MALI_DEVICE_SUSPEND) ) { err = -EPERM; } diff --git a/drivers/gpu/arm/mali/linux/mali_kernel_ioctl.h b/drivers/gpu/arm/mali/linux/mali_kernel_ioctl.h index 87d94db7886..30a6fa041db 100755 --- a/drivers/gpu/arm/mali/linux/mali_kernel_ioctl.h +++ b/drivers/gpu/arm/mali/linux/mali_kernel_ioctl.h @@ -37,6 +37,7 @@ extern "C" #define MALI_IOC_PP_BASE (_MALI_UK_PP_SUBSYSTEM + MALI_IOC_BASE) #define MALI_IOC_GP_BASE (_MALI_UK_GP_SUBSYSTEM + MALI_IOC_BASE) #define MALI_IOC_PROFILING_BASE (_MALI_UK_PROFILING_SUBSYSTEM + MALI_IOC_BASE) +#define MALI_IOC_VSYNC_BASE (_MALI_UK_VSYNC_SUBSYSTEM + MALI_IOC_BASE) #define MALI_IOC_GET_SYSTEM_INFO_SIZE _IOR (MALI_IOC_CORE_BASE, _MALI_UK_GET_SYSTEM_INFO_SIZE, _mali_uk_get_system_info_s *) #define MALI_IOC_GET_SYSTEM_INFO _IOR (MALI_IOC_CORE_BASE, _MALI_UK_GET_SYSTEM_INFO, _mali_uk_get_system_info_s *) @@ -67,6 +68,7 @@ extern "C" #define MALI_IOC_PROFILING_STOP _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_STOP, _mali_uk_profiling_stop_s *) #define MALI_IOC_PROFILING_GET_EVENT _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_GET_EVENT, _mali_uk_profiling_get_event_s *) #define MALI_IOC_PROFILING_CLEAR _IOWR(MALI_IOC_PROFILING_BASE, _MALI_UK_PROFILING_CLEAR, _mali_uk_profiling_clear_s *) +#define MALI_IOC_VSYNC_EVENT_REPORT _IOW (MALI_IOC_VSYNC_BASE, _MALI_UK_VSYNC_EVENT_REPORT, _mali_uk_vsync_event_report_s *) #ifdef __cplusplus } diff --git a/drivers/gpu/arm/mali/linux/mali_kernel_linux.c b/drivers/gpu/arm/mali/linux/mali_kernel_linux.c index 70d9bfd5b83..382be6802b2 100755 --- a/drivers/gpu/arm/mali/linux/mali_kernel_linux.c +++ b/drivers/gpu/arm/mali/linux/mali_kernel_linux.c @@ -16,7 +16,6 @@ #include /* file system operations */ #include /* character device definitions */ #include /* memory mananger definitions */ -#include /* user space access */ #include /* the mali kernel subsystem types */ @@ -24,7 +23,6 @@ /* A memory subsystem always exists, so no need to conditionally include it */ #include "mali_kernel_common.h" -#include "mali_kernel_mem.h" #include "mali_kernel_session_manager.h" #include "mali_kernel_core.h" @@ -35,6 +33,8 @@ #include "mali_ukk_wrappers.h" #include "mali_kernel_pm.h" +#include "mali_kernel_sysfs.h" + /* */ #include "mali_kernel_license.h" @@ -60,19 +60,18 @@ extern int mali_max_job_runtime; 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"); -struct mali_dev -{ - struct cdev cdev; -#if MALI_LICENSE_IS_GPL - struct class * mali_class; +#if defined(USING_MALI400_L2_CACHE) +extern int mali_l2_max_reads; +module_param(mali_l2_max_reads, int, S_IRUSR | S_IRGRP | S_IROTH); +MODULE_PARM_DESC(mali_l2_max_reads, "Maximum reads for Mali L2 cache"); #endif -}; static char mali_dev_name[] = "mali"; /* should be const, but the functions we call requires non-cost */ /* the mali device */ static struct mali_dev device; + static int mali_open(struct inode *inode, struct file *filp); static int mali_release(struct inode *inode, struct file *filp); #ifdef HAVE_UNLOCKED_IOCTL @@ -104,47 +103,40 @@ int mali_driver_init(void) #if USING_MALI_PMM #if MALI_LICENSE_IS_GPL #ifdef CONFIG_PM - err = _mali_dev_platform_register(); - if (err) - { - return err; - } + err = _mali_dev_platform_register(); + if (err) + { + return err; + } #endif #endif #endif - err = mali_kernel_constructor(); - if (_MALI_OSK_ERR_OK != err) - { - MALI_PRINT(("Failed to initialize driver (error %d)\n", err)); - return -EFAULT; - } + err = mali_kernel_constructor(); + if (_MALI_OSK_ERR_OK != err) + { +#if USING_MALI_PMM +#if MALI_LICENSE_IS_GPL +#ifdef CONFIG_PM + _mali_dev_platform_unregister(); +#endif +#endif +#endif + MALI_PRINT(("Failed to initialize driver (error %d)\n", err)); + return -EFAULT; + } return 0; } void mali_driver_exit(void) { - #if USING_MALI_PMM -#if MALI_LICENSE_IS_GPL -#ifdef CONFIG_PM_RUNTIME -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON - - _mali_osk_pmm_dev_activate(); -#endif + malipmm_force_powerup(); #endif -#endif -#endif - mali_kernel_destructor(); + mali_kernel_destructor(); #if USING_MALI_PMM -#if MALI_LICENSE_IS_GPL -#ifdef CONFIG_PM_RUNTIME -#if MALI_PMM_RUNTIME_JOB_CONTROL_ON - _mali_osk_pmm_dev_idle(); -#endif -#endif -#endif + malipmm_force_powerdown(); #endif #if USING_MALI_PMM @@ -174,45 +166,39 @@ int initialize_kernel_device(void) err = register_chrdev_region(dev, 1/*count*/, mali_dev_name); } - if (0 == err) + if (err) { - memset(&device, 0, sizeof(device)); + goto init_chrdev_err; + } - /* initialize our char dev data */ - cdev_init(&device.cdev, &mali_fops); - device.cdev.owner = THIS_MODULE; - device.cdev.ops = &mali_fops; + memset(&device, 0, sizeof(device)); - /* register char dev with the kernel */ - err = cdev_add(&device.cdev, dev, 1/*count*/); + /* initialize our char dev data */ + cdev_init(&device.cdev, &mali_fops); + device.cdev.owner = THIS_MODULE; + device.cdev.ops = &mali_fops; - if (0 == err) - { -#if MALI_LICENSE_IS_GPL - device.mali_class = class_create(THIS_MODULE, mali_dev_name); - if (IS_ERR(device.mali_class)) - { - err = PTR_ERR(device.mali_class); - } - else - { - struct device * mdev; - mdev = device_create(device.mali_class, NULL, dev, NULL, mali_dev_name); - if (!IS_ERR(mdev)) - { - return 0; - } - - err = PTR_ERR(mdev); - } - cdev_del(&device.cdev); -#else - return 0; -#endif - } - unregister_chrdev_region(dev, 1/*count*/); + /* register char dev with the kernel */ + err = cdev_add(&device.cdev, dev, 1/*count*/); + if (err) + { + goto init_cdev_err; } + err = mali_sysfs_register(&device, dev, mali_dev_name); + if (err) + { + goto init_sysfs_err; + } + + /* Success! */ + return 0; + +init_sysfs_err: + cdev_del(&device.cdev); +init_cdev_err: + unregister_chrdev_region(dev, 1/*count*/); +init_chrdev_err: return err; } @@ -220,11 +206,9 @@ int initialize_kernel_device(void) void terminate_kernel_device(void) { dev_t dev = MKDEV(mali_major, 0); + + mali_sysfs_unregister(&device, dev, mali_dev_name); -#if MALI_LICENSE_IS_GPL - device_destroy(device.mali_class, dev); - class_destroy(device.mali_class); -#endif /* unregister char device */ cdev_del(&device.cdev); /* free major */ @@ -427,7 +411,7 @@ static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, case MALI_IOC_MEM_ATTACH_UMP: case MALI_IOC_MEM_RELEASE_UMP: /* FALL-THROUGH */ - MALI_DEBUG_PRINT(2, ("UMP not supported\n", cmd, arg)); + MALI_DEBUG_PRINT(2, ("UMP not supported\n")); err = -ENOTTY; break; #endif @@ -468,6 +452,10 @@ static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, err = gp_suspend_response_wrapper(session_data, (_mali_uk_gp_suspend_response_s __user *)arg); break; + case MALI_IOC_VSYNC_EVENT_REPORT: + err = vsync_event_report_wrapper(session_data, (_mali_uk_vsync_event_report_s __user *)arg); + break; + default: MALI_DEBUG_PRINT(2, ("No handler for ioctl 0x%08X 0x%08lX\n", cmd, arg)); err = -ENOTTY; @@ -476,6 +464,7 @@ static int mali_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, return err; } + module_init(mali_driver_init); module_exit(mali_driver_exit); diff --git a/drivers/gpu/arm/mali/linux/mali_kernel_linux.h b/drivers/gpu/arm/mali/linux/mali_kernel_linux.h index 785eaca4889..485c27e1ecb 100755 --- a/drivers/gpu/arm/mali/linux/mali_kernel_linux.h +++ b/drivers/gpu/arm/mali/linux/mali_kernel_linux.h @@ -16,9 +16,23 @@ extern "C" { #endif +#include /* character device definitions */ +#include "mali_kernel_license.h" + +struct mali_dev +{ + struct cdev cdev; +#if MALI_LICENSE_IS_GPL + struct class * mali_class; +#endif +}; + _mali_osk_errcode_t initialize_kernel_device(void); void terminate_kernel_device(void); +void mali_osk_low_level_mem_init(void); +void mali_osk_low_level_mem_term(void); + #ifdef __cplusplus } #endif diff --git a/drivers/gpu/arm/mali/linux/mali_kernel_pm.c b/drivers/gpu/arm/mali/linux/mali_kernel_pm.c index e6c78c2f6e7..3969466f39e 100755 --- a/drivers/gpu/arm/mali/linux/mali_kernel_pm.c +++ b/drivers/gpu/arm/mali/linux/mali_kernel_pm.c @@ -15,9 +15,6 @@ #if USING_MALI_PMM #include -#ifdef CONFIG_HAS_EARLYSUSPEND -#include -#endif /* CONFIG_HAS_EARLYSUSPEND */ #ifdef CONFIG_PM_RUNTIME #include @@ -51,6 +48,8 @@ unsigned int pwr_mgmt_status_reg = 0; #endif /* CONFIG_PM */ #endif /* MALI_POWER_MGMT_TEST_SUITE */ +static int is_os_pmm_thread_waiting = 0; + /* kernel should be configured with power management support */ #ifdef CONFIG_PM @@ -70,10 +69,6 @@ unsigned int pwr_mgmt_status_reg = 0; static const char* const mali_states[_MALI_MAX_DEBUG_OPERATIONS] = { [_MALI_DEVICE_SUSPEND] = "suspend", [_MALI_DEVICE_RESUME] = "resume", -#ifdef CONFIG_HAS_EARLYSUSPEND - [_MALI_DEVICE_EARLYSUSPEND_DISABLE_FB] = "early_suspend_level_disable_framebuffer", - [_MALI_DEVICE_LATERESUME] = "late_resume", -#endif /* CONFIG_HAS_EARLYSUSPEND */ [_MALI_DVFS_PAUSE_EVENT] = "dvfs_pause", [_MALI_DVFS_RESUME_EVENT] = "dvfs_resume", }; @@ -86,13 +81,11 @@ extern void set_mali_parent_power_domain(struct platform_device* dev); #ifdef CONFIG_PM_RUNTIME #if MALI_PMM_RUNTIME_JOB_CONTROL_ON -#ifndef CONFIG_HAS_EARLYSUSPEND static int mali_pwr_suspend_notifier(struct notifier_block *nb,unsigned long event,void* dummy); static struct notifier_block mali_pwr_notif_block = { .notifier_call = mali_pwr_suspend_notifier }; -#endif /* CONFIG_HAS_EARLYSUSPEND */ #endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */ #endif /* CONFIG_PM_RUNTIME */ @@ -143,12 +136,6 @@ static int mali_device_runtime_resume(struct device *dev); #endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */ #endif /* CONFIG_PM_RUNTIME */ -/* Early suspend functions */ -#ifdef CONFIG_HAS_EARLYSUSPEND -static void mali_pm_early_suspend(struct early_suspend *mali_dev); -static void mali_pm_late_resume(struct early_suspend *mali_dev); -#endif /* CONFIG_HAS_EARLYSUSPEND */ - /* OS suspend and resume callbacks */ #if !MALI_PMM_RUNTIME_JOB_CONTROL_ON #ifndef CONFIG_PM_RUNTIME @@ -231,15 +218,6 @@ static struct platform_driver mali_plat_driver = { }, }; -#ifdef CONFIG_HAS_EARLYSUSPEND -/* Early suspend hooks */ -static struct early_suspend mali_dev_early_suspend = { - .suspend = mali_pm_early_suspend, - .resume = mali_pm_late_resume, - .level = EARLY_SUSPEND_LEVEL_DISABLE_FB, -}; -#endif /* CONFIG_HAS_EARLYSUSPEND */ - /* Mali GPU platform device */ struct platform_device mali_gpu_device = { .name = "mali_dev", @@ -308,7 +286,9 @@ int mali_device_suspend(unsigned int event_id, struct task_struct **pwr_mgmt_thr *pwr_mgmt_thread = current; MALI_DEBUG_PRINT(4, ("OSPMM: MALI device is being suspended\n" )); _mali_ukk_pmm_event_message(&event); + is_os_pmm_thread_waiting = 1; err = mali_wait_for_power_management_policy_event(); + is_os_pmm_thread_waiting = 0; return err; } @@ -322,17 +302,11 @@ static int mali_pm_suspend(struct device *dev) #if MALI_GPU_UTILIZATION mali_utilization_suspend(); #endif /* MALI_GPU_UTILIZATION */ - if ((mali_device_state == _MALI_DEVICE_SUSPEND) -#ifdef CONFIG_HAS_EARLYSUSPEND - || mali_device_state == (_MALI_DEVICE_EARLYSUSPEND_DISABLE_FB)) -#else - ) -#endif /* CONFIG_HAS_EARLYSUSPEND */ + if ((mali_device_state == _MALI_DEVICE_SUSPEND)) { _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); return err; } - mali_device_state = _MALI_DEVICE_SUSPEND_IN_PROGRESS; err = mali_device_suspend(MALI_PMM_EVENT_OS_POWER_DOWN, &pm_thread); mali_device_state = _MALI_DEVICE_SUSPEND; _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); @@ -356,7 +330,6 @@ static int mali_pm_os_suspend(struct device *dev) #ifdef CONFIG_PM_RUNTIME #if MALI_PMM_RUNTIME_JOB_CONTROL_ON -#ifndef CONFIG_HAS_EARLYSUSPEND static int mali_pwr_suspend_notifier(struct notifier_block *nb,unsigned long event,void* dummy) { int err = 0; @@ -374,7 +347,6 @@ static int mali_pwr_suspend_notifier(struct notifier_block *nb,unsigned long eve } return 0; } -#endif /* CONFIG_HAS_EARLYSUSPEND */ #endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */ #endif /* CONFIG_PM_RUNTIME */ @@ -391,7 +363,9 @@ int mali_device_resume(unsigned int event_id, struct task_struct **pwr_mgmt_thre MALI_DEBUG_PRINT(4, ("OSPMM: MALI device is being resumed\n" )); _mali_ukk_pmm_event_message(&event); MALI_DEBUG_PRINT(4, ("OSPMM: MALI Power up event is scheduled\n" )); + is_os_pmm_thread_waiting = 1; err = mali_wait_for_power_management_policy_event(); + is_os_pmm_thread_waiting = 0; return err; } @@ -463,69 +437,6 @@ static int mali_device_runtime_resume(struct device *dev) #endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */ #endif /* CONFIG_PM_RUNTIME */ -#ifdef CONFIG_HAS_EARLYSUSPEND - -/* This function is called from android framework. - */ -static void mali_pm_early_suspend(struct early_suspend *mali_dev) -{ - switch(mali_dev->level) - { - /* Screen should be turned off but framebuffer will be accessible */ - case EARLY_SUSPEND_LEVEL_BLANK_SCREEN: - MALI_DEBUG_PRINT(4, ("PMMDEBUG: Screen is off\n" )); - break; - - case EARLY_SUSPEND_LEVEL_STOP_DRAWING: - MALI_DEBUG_PRINT(4, ("PMMDEBUG: Suspend level stop drawing\n" )); - break; - - /* Turn off the framebuffer. In our case No Mali GPU operation */ - case EARLY_SUSPEND_LEVEL_DISABLE_FB: - MALI_DEBUG_PRINT(4, ("PMMDEBUG: Suspend level Disable framebuffer\n" )); - _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); -#if MALI_GPU_UTILIZATION - mali_utilization_suspend(); -#endif /* MALI_GPU_UTILIZATION */ - if ((mali_device_state == _MALI_DEVICE_SUSPEND) || (mali_device_state == _MALI_DEVICE_EARLYSUSPEND_DISABLE_FB)) - { - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return; - } - mali_device_suspend(MALI_PMM_EVENT_OS_POWER_DOWN, &pm_thread); - mali_device_state = _MALI_DEVICE_EARLYSUSPEND_DISABLE_FB; - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - break; - - default: - MALI_DEBUG_PRINT(4, ("PMMDEBUG: Invalid Suspend Mode\n" )); - break; - } -} - -/* This function is invoked from android framework when mali device needs to be - * resumed. - */ -static void mali_pm_late_resume(struct early_suspend *mali_dev) -{ - _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); - if (mali_device_state == _MALI_DEVICE_RESUME) - { - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return; - } - if (mali_device_state == _MALI_DEVICE_EARLYSUSPEND_DISABLE_FB) - { - mali_device_resume(MALI_PMM_EVENT_OS_POWER_UP, &pm_thread); - mali_dvfs_device_state = _MALI_DEVICE_RESUME; - mali_device_state = _MALI_DEVICE_RESUME; - } - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - -} - -#endif /* CONFIG_HAS_EARLYSUSPEND */ - #ifdef CONFIG_PM_DEBUG /** This function is used for debugging purposes when the user want to see @@ -557,9 +468,6 @@ static ssize_t show_file(struct device *dev, struct device_attribute *attr, char static ssize_t store_file(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int err = 0; -#ifdef CONFIG_HAS_EARLYSUSPEND - struct early_suspend mali_dev; -#endif /* CONFIG_HAS_EARLYSUSPEND */ #if MALI_POWER_MGMT_TEST_SUITE int test_flag_dvfs = 0; @@ -597,19 +505,6 @@ static ssize_t store_file(struct device *dev, struct device_attribute *attr, con MALI_DEBUG_PRINT(4, ("PMMDEBUG: MALI Resume Power operation is scheduled\n" )); err = mali_pm_resume(NULL); } -#ifdef CONFIG_HAS_EARLYSUSPEND - else if (!strncmp(buf,mali_states[_MALI_DEVICE_EARLYSUSPEND_DISABLE_FB],strlen(mali_states[_MALI_DEVICE_EARLYSUSPEND_DISABLE_FB]))) - { - mali_dev.level = EARLY_SUSPEND_LEVEL_DISABLE_FB; - MALI_DEBUG_PRINT(4, ("PMMDEBUG: Android early suspend operation is scheduled\n" )); - mali_pm_early_suspend(&mali_dev); - } - else if (!strncmp(buf,mali_states[_MALI_DEVICE_LATERESUME],strlen(mali_states[_MALI_DEVICE_LATERESUME]))) - { - MALI_DEBUG_PRINT(4, ("PMMDEBUG: MALI Resume Power operation is scheduled\n" )); - mali_pm_late_resume(NULL); - } -#endif /* CONFIG_HAS_EARLYSUSPEND */ else if (!strncmp(buf,mali_states[_MALI_DVFS_PAUSE_EVENT],strlen(mali_states[_MALI_DVFS_PAUSE_EVENT]))) { MALI_DEBUG_PRINT(4, ("PMMDEBUG: MALI DVFS Pause Power operation is scheduled\n" )); @@ -694,7 +589,6 @@ int _mali_dev_platform_register(void) #endif #ifdef CONFIG_PM_RUNTIME -#ifndef CONFIG_HAS_EARLYSUSPEND #if MALI_PMM_RUNTIME_JOB_CONTROL_ON err = register_pm_notifier(&mali_pwr_notif_block); if (err) @@ -702,28 +596,19 @@ int _mali_dev_platform_register(void) return err; } #endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */ -#endif /* CONFIG_HAS_EARLYSUSPEND */ #endif /* CONFIG_PM_RUNTIME */ err = platform_device_register(&mali_gpu_device); lock = _mali_osk_lock_init((_mali_osk_lock_flags_t)( _MALI_OSK_LOCKFLAG_READERWRITER | _MALI_OSK_LOCKFLAG_ORDERED), 0, 0); if (!err) { err = platform_driver_register(&mali_plat_driver); - if (!err) - { -#ifdef CONFIG_HAS_EARLYSUSPEND - register_early_suspend(&mali_dev_early_suspend); -#endif /* CONFIG_HAS_EARLYSUSPEND */ - } - else + if (err) { _mali_osk_lock_term(lock); #ifdef CONFIG_PM_RUNTIME -#ifndef CONFIG_HAS_EARLYSUSPEND #if MALI_PMM_RUNTIME_JOB_CONTROL_ON unregister_pm_notifier(&mali_pwr_notif_block); #endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */ -#endif /* CONFIG_HAS_EARLYSUSPEND */ #endif /* CONFIG_PM_RUNTIME */ platform_device_unregister(&mali_gpu_device); } @@ -737,22 +622,28 @@ void _mali_dev_platform_unregister(void) { _mali_osk_lock_term(lock); -#ifdef CONFIG_HAS_EARLYSUSPEND - unregister_early_suspend(&mali_dev_early_suspend); -#endif /* CONFIG_HAS_EARLYSUSPEND */ - #ifdef CONFIG_PM_RUNTIME -#ifndef CONFIG_HAS_EARLYSUSPEND #if MALI_PMM_RUNTIME_JOB_CONTROL_ON unregister_pm_notifier(&mali_pwr_notif_block); #endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */ -#endif /* CONFIG_HAS_EARLYSUSPEND */ #endif /* CONFIG_PM_RUNTIME */ platform_driver_unregister(&mali_plat_driver); platform_device_unregister(&mali_gpu_device); } +int mali_get_ospmm_thread_state(void) +{ + return is_os_pmm_thread_waiting; +} + #endif /* MALI_LICENSE_IS_GPL */ #endif /* CONFIG_PM */ + +#if MALI_STATE_TRACKING +u32 mali_pmm_dump_os_thread_state( char *buf, u32 size ) +{ + return snprintf(buf, size, "OSPMM: OS PMM thread is waiting: %s\n", is_os_pmm_thread_waiting ? "true" : "false"); +} +#endif /* MALI_STATE_TRACKING */ #endif /* USING_MALI_PMM */ diff --git a/drivers/gpu/arm/mali/linux/mali_kernel_sysfs.c b/drivers/gpu/arm/mali/linux/mali_kernel_sysfs.c new file mode 100644 index 00000000000..62c7fba8791 --- /dev/null +++ b/drivers/gpu/arm/mali/linux/mali_kernel_sysfs.c @@ -0,0 +1,137 @@ +/** + * Copyright (C) 2011 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +/** + * @file mali_kernel_sysfs.c + * Implementation of some sysfs data exports + */ +#include /* file system operations */ +#include +#include +#include + +/* the mali kernel subsystem types */ +#include "mali_kernel_subsystem.h" + +#include "mali_kernel_linux.h" +#include "mali_kernel_sysfs.h" + +#include "mali_kernel_license.h" + +#if MALI_LICENSE_IS_GPL +static struct dentry *mali_debugfs_dir; +#endif + + +#if MALI_STATE_TRACKING +static int mali_seq_internal_state_show(struct seq_file *seq_file, void *v) +{ + u32 len = 0; + u32 size; + char *buf; + + size = seq_get_buf(seq_file, &buf); + + if(!size) + { + return -ENOMEM; + } + + /* Create the internal state dump. */ + len = snprintf(buf+len, size-len, "Mali device driver %s\n", SVN_REV_STRING); + len += snprintf(buf+len, size-len, "License: %s\n\n", MALI_KERNEL_LINUX_LICENSE); + + len += _mali_kernel_core_dump_state(buf + len, size - len); + + seq_commit(seq_file, len); + + return 0; +} + +static int mali_seq_internal_state_open(struct inode *inode, struct file *file) +{ + return single_open(file, mali_seq_internal_state_show, NULL); +} + +static const struct file_operations mali_seq_internal_state_fops = { + .owner = THIS_MODULE, + .open = mali_seq_internal_state_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +#endif /* MALI_STATE_TRACKING */ + +int mali_sysfs_register(struct mali_dev *device, dev_t dev, const char *mali_dev_name) +{ + int err = 0; +#if MALI_LICENSE_IS_GPL + struct device * mdev; + + device->mali_class = class_create(THIS_MODULE, mali_dev_name); + if (IS_ERR(device->mali_class)) + { + err = PTR_ERR(device->mali_class); + goto init_class_err; + } + mdev = device_create(device->mali_class, NULL, dev, NULL, mali_dev_name); + if (IS_ERR(mdev)) + { + err = PTR_ERR(mdev); + goto init_mdev_err; + } + + mali_debugfs_dir = debugfs_create_dir(mali_dev_name, NULL); + if(ERR_PTR(-ENODEV) == mali_debugfs_dir) { + /* Debugfs not supported. */ + mali_debugfs_dir = NULL; + } else { + if(NULL != mali_debugfs_dir) + { + /* Debugfs directory created successfully; create files now */ +#if MALI_STATE_TRACKING + debugfs_create_file("state_dump", 0400, mali_debugfs_dir, NULL, &mali_seq_internal_state_fops); +#endif + } + } +#endif /* MALI_LICENSE_IS_GPL */ + + /* Success! */ + return 0; + + /* Error handling */ +#if MALI_LICENSE_IS_GPL + if(NULL != mali_debugfs_dir) + { + debugfs_remove_recursive(mali_debugfs_dir); + } + device_destroy(device->mali_class, dev); +init_mdev_err: + class_destroy(device->mali_class); +init_class_err: +#endif + return err; +} + +int mali_sysfs_unregister(struct mali_dev *device, dev_t dev, const char *mali_dev_name) +{ +#if MALI_LICENSE_IS_GPL + if(NULL != mali_debugfs_dir) + { + debugfs_remove_recursive(mali_debugfs_dir); + } + device_destroy(device->mali_class, dev); + class_destroy(device->mali_class); +#endif + + return 0; +} + diff --git a/drivers/gpu/arm/mali/linux/mali_kernel_sysfs.h b/drivers/gpu/arm/mali/linux/mali_kernel_sysfs.h new file mode 100644 index 00000000000..d79a8862269 --- /dev/null +++ b/drivers/gpu/arm/mali/linux/mali_kernel_sysfs.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2011 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_KERNEL_SYSFS_H__ +#define __MALI_KERNEL_SYSFS_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define MALI_PROC_DIR "driver/mali" + +int mali_sysfs_register(struct mali_dev *mali_class, dev_t dev, const char *mali_dev_name); + +int mali_sysfs_unregister(struct mali_dev *mali_class, dev_t dev, const char *mali_dev_name); + + +#ifdef __cplusplus +} +#endif + +#endif /* __MALI_KERNEL_LINUX_H__ */ diff --git a/drivers/gpu/arm/mali/linux/mali_linux_dvfs_pause_resume.c b/drivers/gpu/arm/mali/linux/mali_linux_dvfs_pause_resume.c new file mode 100644 index 00000000000..3d60d18e005 --- /dev/null +++ b/drivers/gpu/arm/mali/linux/mali_linux_dvfs_pause_resume.c @@ -0,0 +1,72 @@ +/** + * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_linux_dvfs_pause_resume.c + * Implementation of the Mali pause/resume functionality + */ +#if USING_MALI_PMM +#include +#include +#include +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_platform.h" +#include "mali_linux_pm.h" +#include "mali_linux_dvfs_pause_resume.h" +#include "mali_pmm.h" +#include "mali_kernel_license.h" +#ifdef CONFIG_PM +#if MALI_LICENSE_IS_GPL + +/* Mali Pause Resume APIs */ +int mali_dev_dvfs_pause() +{ + int err = 0; + _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); + if ((mali_dvfs_device_state == _MALI_DEVICE_SUSPEND) || (mali_device_state == _MALI_DEVICE_SUSPEND_IN_PROGRESS) + || (mali_device_state == _MALI_DEVICE_SUSPEND)) + { + err = -EPERM; + } + if ((mali_dvfs_device_state == _MALI_DEVICE_RESUME) && (!err)) + { + mali_device_suspend(MALI_PMM_EVENT_DVFS_PAUSE, &dvfs_pm_thread); + mali_dvfs_device_state = _MALI_DEVICE_SUSPEND; + } + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return err; +} + +EXPORT_SYMBOL(mali_dev_dvfs_pause); + +int mali_dev_dvfs_resume() +{ + int err = 0; + _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); + if ((mali_dvfs_device_state == _MALI_DEVICE_RESUME) || (mali_device_state == _MALI_DEVICE_SUSPEND_IN_PROGRESS) + || (mali_device_state == _MALI_DEVICE_SUSPEND)) + { + err = -EPERM; + } + if (!err) + { + mali_device_resume(MALI_PMM_EVENT_DVFS_RESUME, &dvfs_pm_thread); + mali_dvfs_device_state = _MALI_DEVICE_RESUME; + } + _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); + return err; +} + +EXPORT_SYMBOL(mali_dev_dvfs_resume); + +#endif /* MALI_LICENSE_IS_GPL */ +#endif /* CONFIG_PM */ +#endif /* USING_MALI_PMM */ diff --git a/drivers/gpu/arm/mali/linux/mali_linux_pm.h b/drivers/gpu/arm/mali/linux/mali_linux_pm.h index 614d5e1deee..d401697f2f4 100755 --- a/drivers/gpu/arm/mali/linux/mali_linux_pm.h +++ b/drivers/gpu/arm/mali/linux/mali_linux_pm.h @@ -20,18 +20,13 @@ typedef enum { _MALI_DEVICE_SUSPEND, /* Suspend */ _MALI_DEVICE_RESUME, /* Resume */ -#ifdef CONFIG_HAS_EARLYSUSPEND - _MALI_DEVICE_EARLYSUSPEND_DISABLE_FB, /* Early suspend */ - _MALI_DEVICE_LATERESUME, /* Late resume */ -#endif /* CONFIG_HAS_EARLYSUSPEND */ - _MALI_DEVICE_SUSPEND_IN_PROGRESS, /* Suspend in progress */ _MALI_DEVICE_MAX_POWER_STATES, /* Maximum power states */ } _mali_device_power_states; /* Number of DVFS events */ typedef enum { - _MALI_DVFS_PAUSE_EVENT = _MALI_DEVICE_MAX_POWER_STATES-1, /* DVFS Pause event */ + _MALI_DVFS_PAUSE_EVENT = _MALI_DEVICE_MAX_POWER_STATES, /* DVFS Pause event */ _MALI_DVFS_RESUME_EVENT, /* DVFS Resume event */ _MALI_MAX_DEBUG_OPERATIONS, } _mali_device_dvfs_events; @@ -51,6 +46,7 @@ extern struct task_struct *pm_thread; int mali_device_suspend(u32 event_id, struct task_struct **pwr_mgmt_thread); int mali_device_resume(u32 event_id, struct task_struct **pwr_mgmt_thread); +int mali_get_ospmm_thread_state(void); #endif /* CONFIG_PM */ #endif /* USING_MALI_PMM */ diff --git a/drivers/gpu/arm/mali/linux/mali_linux_pm_testsuite.h b/drivers/gpu/arm/mali/linux/mali_linux_pm_testsuite.h index d6a920827c9..c80b0b0a5e3 100755 --- a/drivers/gpu/arm/mali/linux/mali_linux_pm_testsuite.h +++ b/drivers/gpu/arm/mali/linux/mali_linux_pm_testsuite.h @@ -13,7 +13,6 @@ #if USING_MALI_PMM #if MALI_POWER_MGMT_TEST_SUITE #ifdef CONFIG_PM -#define MALI_PMM_INTERNAL_TESTING 1 typedef enum { @@ -28,10 +27,7 @@ extern unsigned int mali_timeout_event_recording_on; extern unsigned int mali_job_scheduling_events_recording_on; extern unsigned int pwr_mgmt_status_reg; extern unsigned int is_mali_pmm_testsuite_enabled; - -#if MALI_PMM_INTERNAL_TESTING extern unsigned int is_mali_pmu_present; -#endif /* MALI_PMM_INTERNAL_TESTING */ #endif /* CONFIG_PM */ #endif /* MALI_POWER_MGMT_TEST_SUITE */ diff --git a/drivers/gpu/arm/mali/linux/mali_osk_irq.c b/drivers/gpu/arm/mali/linux/mali_osk_irq.c index 73ab8182815..b667961a0ac 100755 --- a/drivers/gpu/arm/mali/linux/mali_osk_irq.c +++ b/drivers/gpu/arm/mali/linux/mali_osk_irq.c @@ -136,7 +136,7 @@ _mali_osk_irq_t *_mali_osk_irq_init( u32 irqnum, _mali_osk_irq_uhandler_t uhandl #if MALI_LICENSE_IS_GPL if ( _MALI_OSK_IRQ_NUMBER_PMM == irqnum ) { - pmm_wq = create_workqueue("mali-pmm-wq"); + pmm_wq = create_singlethread_workqueue("mali-pmm-wq"); } #endif @@ -149,7 +149,7 @@ void _mali_osk_irq_schedulework( _mali_osk_irq_t *irq ) #if MALI_LICENSE_IS_GPL if ( irq_object->irqnum == _MALI_OSK_IRQ_NUMBER_PMM ) { - queue_work(pmm_wq,&irq_object->work_queue_irq_handle); + queue_work( pmm_wq,&irq_object->work_queue_irq_handle ); } else { @@ -160,6 +160,17 @@ void _mali_osk_irq_schedulework( _mali_osk_irq_t *irq ) #endif } +void _mali_osk_flush_workqueue( _mali_osk_irq_t *irq ) +{ +#if MALI_LICENSE_IS_GPL + mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)irq; + if(irq_object->irqnum == _MALI_OSK_IRQ_NUMBER_PMM ) + { + flush_workqueue(pmm_wq); + } +#endif +} + void _mali_osk_irq_term( _mali_osk_irq_t *irq ) { mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)irq; diff --git a/drivers/gpu/arm/mali/linux/mali_osk_locks.c b/drivers/gpu/arm/mali/linux/mali_osk_locks.c index 79010fcdc5a..139dc5e3de3 100755 --- a/drivers/gpu/arm/mali/linux/mali_osk_locks.c +++ b/drivers/gpu/arm/mali/linux/mali_osk_locks.c @@ -29,12 +29,6 @@ #include "mali_osk.h" #include "mali_kernel_common.h" -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) -#define LOCK_INIT(x) sema_init(x,1) -#else -#define LOCK_INIT(x) init_MUTEX(x) -#endif - /* These are all the locks we implement: */ typedef enum { @@ -67,7 +61,6 @@ struct _mali_osk_lock_t_struct MALI_DEBUG_CODE( /** original flags for debug checking */ _mali_osk_lock_flags_t orig_flags; - _mali_osk_lock_mode_t locked_as; ); /* MALI_DEBUG_CODE */ }; @@ -82,10 +75,10 @@ _mali_osk_lock_t *_mali_osk_lock_init( _mali_osk_lock_flags_t flags, u32 initial | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE | _MALI_OSK_LOCKFLAG_READERWRITER | _MALI_OSK_LOCKFLAG_ORDERED - | _MALI_OSK_LOCKFLAG_ONELOCK)) ); + | _MALI_OSK_LOCKFLAG_ONELOCK )) ); /* Spinlocks are always non-interruptable */ MALI_DEBUG_ASSERT( (((flags & _MALI_OSK_LOCKFLAG_SPINLOCK) || (flags & _MALI_OSK_LOCKFLAG_SPINLOCK_IRQ)) && (flags & _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE)) - || !(flags & _MALI_OSK_LOCKFLAG_SPINLOCK) ); + || !(flags & _MALI_OSK_LOCKFLAG_SPINLOCK)); /* Parameter initial SBZ - for future expansion */ MALI_DEBUG_ASSERT( 0 == initial ); @@ -130,13 +123,12 @@ _mali_osk_lock_t *_mali_osk_lock_init( _mali_osk_lock_flags_t flags, u32 initial } /* Initially unlocked */ - LOCK_INIT( &lock->obj.sema ); + sema_init( &lock->obj.sema, 1 ); } MALI_DEBUG_CODE( /* Debug tracking of flags */ lock->orig_flags = flags; - lock->locked_as = _MALI_OSK_LOCKMODE_UNDEF; ); /* MALI_DEBUG_CODE */ return lock; @@ -196,17 +188,6 @@ _mali_osk_errcode_t _mali_osk_lock_wait( _mali_osk_lock_t *lock, _mali_osk_lock_ break; } - /* DEBUG tracking of previously locked state - occurs after lock obtained */ - MALI_DEBUG_CODE( - if ( _MALI_OSK_ERR_OK == err ) - { - /* Assert that this is not currently locked */ - MALI_DEBUG_ASSERT( _MALI_OSK_LOCKMODE_UNDEF == lock->locked_as ); - - lock->locked_as = mode; - } - ); /* MALI_DEBUG_CODE */ - return err; } @@ -224,12 +205,6 @@ void _mali_osk_lock_signal( _mali_osk_lock_t *lock, _mali_osk_lock_mode_t mode ) MALI_DEBUG_ASSERT( _MALI_OSK_LOCKMODE_RW == mode || (_MALI_OSK_LOCKMODE_RO == mode && (_MALI_OSK_LOCKFLAG_READERWRITER & lock->orig_flags)) ); - /* For DEBUG only, assert that we previously locked this, and in the same way (RW/RO) */ - MALI_DEBUG_ASSERT( mode == lock->locked_as ); - - /* DEBUG tracking of previously locked state - occurs before lock released */ - MALI_DEBUG_CODE( lock->locked_as = _MALI_OSK_LOCKMODE_UNDEF ); - switch ( lock->type ) { case _MALI_OSK_INTERNAL_LOCKTYPE_SPIN: @@ -269,9 +244,6 @@ void _mali_osk_lock_term( _mali_osk_lock_t *lock ) /* Parameter validation */ MALI_DEBUG_ASSERT_POINTER( lock ); - /* For DEBUG only, assert that this is not currently locked */ - MALI_DEBUG_ASSERT( _MALI_OSK_LOCKMODE_UNDEF == lock->locked_as ); - /* Linux requires no explicit termination of spinlocks, semaphores, or rw_semaphores */ kfree(lock); } diff --git a/drivers/gpu/arm/mali/linux/mali_osk_low_level_mem.c b/drivers/gpu/arm/mali/linux/mali_osk_low_level_mem.c index 730ee814e38..40373427d44 100755 --- a/drivers/gpu/arm/mali/linux/mali_osk_low_level_mem.c +++ b/drivers/gpu/arm/mali/linux/mali_osk_low_level_mem.c @@ -21,7 +21,6 @@ #include #include #include -#include #include "mali_osk.h" #include "mali_ukk.h" /* required to hook in _mali_ukk_mem_mmap handling */ @@ -38,6 +37,7 @@ static int mali_kernel_memory_cpu_page_fault_handler(struct vm_area_struct *vma, static unsigned long mali_kernel_memory_cpu_page_fault_handler(struct vm_area_struct * vma, unsigned long address); #endif + typedef struct mali_vma_usage_tracker { int references; @@ -50,9 +50,9 @@ typedef struct mali_vma_usage_tracker */ struct AllocationList { - struct AllocationList *next; - u32 offset; - u32 physaddr; + struct AllocationList *next; + u32 offset; + u32 physaddr; }; typedef struct AllocationList AllocationList; @@ -63,11 +63,28 @@ typedef struct AllocationList AllocationList; struct MappingInfo { struct vm_area_struct *vma; - struct AllocationList *list; + struct AllocationList *list; }; typedef struct MappingInfo MappingInfo; + +static u32 _kernel_page_allocate(void); +static void _kernel_page_release(u32 physical_address); +static AllocationList * _allocation_list_item_get(void); +static void _allocation_list_item_release(AllocationList * item); + + +/* Variable declarations */ +spinlock_t allocation_list_spinlock; +static AllocationList * pre_allocated_memory = (AllocationList*) NULL ; +static int pre_allocated_memory_size_current = 0; +#ifdef MALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB + static int pre_allocated_memory_size_max = MALI_OS_MEMORY_KERNEL_BUFFER_SIZE_IN_MB * 1024 * 1024; +#else + static int pre_allocated_memory_size_max = 6 * 1024 * 1024; /* 6 MiB */ +#endif + static struct vm_operations_struct mali_kernel_vm_ops = { .open = mali_kernel_memory_vma_open, @@ -80,6 +97,108 @@ static struct vm_operations_struct mali_kernel_vm_ops = }; +void mali_osk_low_level_mem_init(void) +{ + spin_lock_init( &allocation_list_spinlock ); + pre_allocated_memory = (AllocationList*) NULL ; +} + +void mali_osk_low_level_mem_term(void) +{ + while ( NULL != pre_allocated_memory ) + { + AllocationList *item; + item = pre_allocated_memory; + pre_allocated_memory = item->next; + _kernel_page_release(item->physaddr); + _mali_osk_free( item ); + } + pre_allocated_memory_size_current = 0; +} + +static u32 _kernel_page_allocate(void) +{ + struct page *new_page; + u32 linux_phys_addr; + + new_page = alloc_page(GFP_HIGHUSER | __GFP_ZERO | __GFP_REPEAT | __GFP_NOWARN | __GFP_COLD); + + if ( NULL == new_page ) + { + return 0; + } + + /* Ensure page is flushed from CPU caches. */ + linux_phys_addr = dma_map_page(NULL, new_page, 0, PAGE_SIZE, DMA_BIDIRECTIONAL); + + return linux_phys_addr; +} + +static void _kernel_page_release(u32 physical_address) +{ + struct page *unmap_page; + + #if 1 + dma_unmap_page(NULL, physical_address, PAGE_SIZE, DMA_BIDIRECTIONAL); + #endif + + unmap_page = pfn_to_page( physical_address >> PAGE_SHIFT ); + MALI_DEBUG_ASSERT_POINTER( unmap_page ); + __free_page( unmap_page ); +} + +static AllocationList * _allocation_list_item_get(void) +{ + AllocationList *item = NULL; + unsigned long flags; + + spin_lock_irqsave(&allocation_list_spinlock,flags); + if ( pre_allocated_memory ) + { + item = pre_allocated_memory; + pre_allocated_memory = pre_allocated_memory->next; + pre_allocated_memory_size_current -= PAGE_SIZE; + + spin_unlock_irqrestore(&allocation_list_spinlock,flags); + return item; + } + spin_unlock_irqrestore(&allocation_list_spinlock,flags); + + item = _mali_osk_malloc( sizeof(AllocationList) ); + if ( NULL == item) + { + return NULL; + } + + item->physaddr = _kernel_page_allocate(); + if ( 0 == item->physaddr ) + { + /* Non-fatal error condition, out of memory. Upper levels will handle this. */ + _mali_osk_free( item ); + return NULL; + } + return item; +} + +static void _allocation_list_item_release(AllocationList * item) +{ + unsigned long flags; + spin_lock_irqsave(&allocation_list_spinlock,flags); + if ( pre_allocated_memory_size_current < pre_allocated_memory_size_max) + { + item->next = pre_allocated_memory; + pre_allocated_memory = item; + pre_allocated_memory_size_current += PAGE_SIZE; + spin_unlock_irqrestore(&allocation_list_spinlock,flags); + return; + } + spin_unlock_irqrestore(&allocation_list_spinlock,flags); + + _kernel_page_release(item->physaddr); + _mali_osk_free( item ); +} + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) static int mali_kernel_memory_cpu_page_fault_handler(struct vm_area_struct *vma, struct vm_fault *vmf) #else @@ -108,7 +227,7 @@ static unsigned long mali_kernel_memory_cpu_page_fault_handler(struct vm_area_st static void mali_kernel_memory_vma_open(struct vm_area_struct * vma) { mali_vma_usage_tracker * vma_usage_tracker; - MALI_DEBUG_PRINT(2, ("Open called on vma %p\n", vma)); + MALI_DEBUG_PRINT(4, ("Open called on vma %p\n", vma)); vma_usage_tracker = (mali_vma_usage_tracker*)vma->vm_private_data; vma_usage_tracker->references++; @@ -154,17 +273,17 @@ static void mali_kernel_memory_vma_close(struct vm_area_struct * vma) void _mali_osk_mem_barrier( void ) { - mb(); + mb(); } mali_io_address _mali_osk_mem_mapioregion( u32 phys, u32 size, const char *description ) { - return (mali_io_address)ioremap_nocache(phys, size); + return (mali_io_address)ioremap_nocache(phys, size); } void _mali_osk_mem_unmapioregion( u32 phys, u32 size, mali_io_address virt ) { - iounmap((void*)virt); + iounmap((void*)virt); } mali_io_address _mali_osk_mem_allocioregion( u32 *phys, u32 size ) @@ -204,27 +323,27 @@ void _mali_osk_mem_freeioregion( u32 phys, u32 size, mali_io_address virt ) _mali_osk_errcode_t inline _mali_osk_mem_reqregion( u32 phys, u32 size, const char *description ) { - return ((NULL == request_mem_region(phys, size, description)) ? _MALI_OSK_ERR_NOMEM : _MALI_OSK_ERR_OK); + return ((NULL == request_mem_region(phys, size, description)) ? _MALI_OSK_ERR_NOMEM : _MALI_OSK_ERR_OK); } void inline _mali_osk_mem_unreqregion( u32 phys, u32 size ) { - release_mem_region(phys, size); + release_mem_region(phys, size); } u32 inline _mali_osk_mem_ioread32( volatile mali_io_address addr, u32 offset ) { - return ioread32(((u8*)addr) + offset); + return ioread32(((u8*)addr) + offset); } void inline _mali_osk_mem_iowrite32( volatile mali_io_address addr, u32 offset, u32 val ) { - iowrite32(val, ((u8*)addr) + offset); + iowrite32(val, ((u8*)addr) + offset); } void _mali_osk_cache_flushall( void ) { - /** @note Cached memory is not currently supported in this implementation */ + /** @note Cached memory is not currently supported in this implementation */ } void _mali_osk_cache_ensure_uncached_range_flushed( void *uncached_mapping, u32 offset, u32 size ) @@ -274,6 +393,7 @@ _mali_osk_errcode_t _mali_osk_mem_mapregion_init( mali_memory_allocation * descr */ vma->vm_flags |= VM_IO; vma->vm_flags |= VM_RESERVED; + vma->vm_flags |= VM_DONTCOPY; vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); vma->vm_ops = &mali_kernel_vm_ops; /* Operations used on any memory system */ @@ -334,14 +454,14 @@ _mali_osk_errcode_t _mali_osk_mem_mapregion_map( mali_memory_allocation * descri MALI_DEBUG_ASSERT( 0 == (offset & ~_MALI_OSK_CPU_PAGE_MASK)); - if (NULL == descriptor->mapping) return _MALI_OSK_ERR_INVALID_ARGS; + if (NULL == descriptor->mapping) return _MALI_OSK_ERR_INVALID_ARGS; - if (size > (descriptor->size - offset)) - { - MALI_DEBUG_PRINT(1,("_mali_osk_mem_mapregion_map: virtual memory area not large enough to map physical 0x%x size %x into area 0x%x at offset 0x%xr\n", - *phys_addr, size, descriptor->mapping, offset)); - return _MALI_OSK_ERR_FAULT; - } + if (size > (descriptor->size - offset)) + { + MALI_DEBUG_PRINT(1,("_mali_osk_mem_mapregion_map: virtual memory area not large enough to map physical 0x%x size %x into area 0x%x at offset 0x%xr\n", + *phys_addr, size, descriptor->mapping, offset)); + return _MALI_OSK_ERR_FAULT; + } mappingInfo = (MappingInfo *)descriptor->process_addr_mapping_info; @@ -351,57 +471,35 @@ _mali_osk_errcode_t _mali_osk_mem_mapregion_map( mali_memory_allocation * descri if (NULL == vma ) return _MALI_OSK_ERR_FAULT; - MALI_DEBUG_PRINT(7, ("Process map: mapping 0x%08X to process address 0x%08lX length 0x%08X\n", phys_addr, (long unsigned int)(descriptor->mapping + offset), size)); + MALI_DEBUG_PRINT(7, ("Process map: mapping 0x%08X to process address 0x%08lX length 0x%08X\n", *phys_addr, (long unsigned int)(descriptor->mapping + offset), size)); if ( MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC == *phys_addr ) { _mali_osk_errcode_t ret; + AllocationList *alloc_item; u32 linux_phys_frame_num; - u32 linux_phys_addr; - AllocationList *allocItem; - struct page *new_page; - allocItem = _mali_osk_malloc( sizeof(AllocationList) ); - if ( NULL == allocItem ) - { - /* Out of memory. Try another allocator */ - return _MALI_OSK_ERR_NOMEM; - } + alloc_item = _allocation_list_item_get(); - { - new_page = alloc_page(GFP_HIGHUSER | __GFP_ZERO | __GFP_NORETRY | __GFP_NOWARN | __GFP_COLD); - - if ( NULL == new_page ) - { - /* Non-fatal error condition, out of memory. Upper levels will handle this. */ - _mali_osk_free( allocItem ); - return _MALI_OSK_ERR_NOMEM; - } - - /* Ensure page is flushed from CPU caches. */ - linux_phys_addr = dma_map_page(NULL, new_page, 0, PAGE_SIZE, DMA_BIDIRECTIONAL); - - linux_phys_frame_num = linux_phys_addr >> PAGE_SHIFT; - } + linux_phys_frame_num = alloc_item->physaddr >> PAGE_SHIFT; ret = ( remap_pfn_range( vma, ((u32)descriptor->mapping) + offset, linux_phys_frame_num, size, vma->vm_page_prot) ) ? _MALI_OSK_ERR_FAULT : _MALI_OSK_ERR_OK; if ( ret != _MALI_OSK_ERR_OK) { - dma_unmap_page(NULL, linux_phys_addr, PAGE_SIZE, DMA_BIDIRECTIONAL); - __free_page( new_page ); - _mali_osk_free( allocItem ); + _allocation_list_item_release(alloc_item); return ret; } - /* Put our allocItem into the list of allocations on success */ - allocItem->next = mappingInfo->list; - allocItem->offset = offset; - allocItem->physaddr = linux_phys_addr; - mappingInfo->list = allocItem; + /* Put our alloc_item into the list of allocations on success */ + alloc_item->next = mappingInfo->list; + alloc_item->offset = offset; + + /*alloc_item->physaddr = linux_phys_addr;*/ + mappingInfo->list = alloc_item; /* Write out new physical address on success */ - *phys_addr = linux_phys_addr; + *phys_addr = alloc_item->physaddr; return ret; } @@ -427,56 +525,50 @@ void _mali_osk_mem_mapregion_unmap( mali_memory_allocation * descriptor, u32 off MALI_DEBUG_ASSERT( 0 == (offset & ~_MALI_OSK_CPU_PAGE_MASK) ); - if (NULL == descriptor->mapping) return; + if (NULL == descriptor->mapping) return; - if (size > (descriptor->size - offset)) - { - MALI_DEBUG_PRINT(1,("_mali_osk_mem_mapregion_unmap: virtual memory area not large enough to unmap size %x from area 0x%x at offset 0x%x\n", + if (size > (descriptor->size - offset)) + { + MALI_DEBUG_PRINT(1,("_mali_osk_mem_mapregion_unmap: virtual memory area not large enough to unmap size %x from area 0x%x at offset 0x%x\n", size, descriptor->mapping, offset)); - return; - } + return; + } mappingInfo = (MappingInfo *)descriptor->process_addr_mapping_info; MALI_DEBUG_ASSERT_POINTER( mappingInfo ); if ( 0 != (flags & _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR) ) { - /* This physical RAM was allocated in _mali_osk_mem_mapregion_map and - * so needs to be unmapped - */ - while (size) + /* This physical RAM was allocated in _mali_osk_mem_mapregion_map and + * so needs to be unmapped + */ + while (size) { - /* First find the allocation in the list of allocations */ - AllocationList *alloc = mappingInfo->list; - AllocationList **prev = &(mappingInfo->list); - while (NULL != alloc && alloc->offset != offset) - { - prev = &(alloc->next); - alloc = alloc->next; - } - if (alloc == NULL) { - MALI_DEBUG_PRINT(1, ("Unmapping memory that isn't mapped\n")); - size -= _MALI_OSK_CPU_PAGE_SIZE; - offset += _MALI_OSK_CPU_PAGE_SIZE; - continue; - } - + /* First find the allocation in the list of allocations */ + AllocationList *alloc = mappingInfo->list; + AllocationList **prev = &(mappingInfo->list); + while (NULL != alloc && alloc->offset != offset) { - struct page *unmap_page; - unmap_page = pfn_to_page( alloc->physaddr >> PAGE_SHIFT ); - MALI_DEBUG_ASSERT_POINTER( unmap_page ); - dma_unmap_page(NULL, alloc->physaddr, PAGE_SIZE, DMA_BIDIRECTIONAL); - __free_page( unmap_page ); + prev = &(alloc->next); + alloc = alloc->next; } + if (alloc == NULL) { + MALI_DEBUG_PRINT(1, ("Unmapping memory that isn't mapped\n")); + size -= _MALI_OSK_CPU_PAGE_SIZE; + offset += _MALI_OSK_CPU_PAGE_SIZE; + continue; + } + + _kernel_page_release(alloc->physaddr); - /* Remove the allocation from the list */ - *prev = alloc->next; - _mali_osk_free( alloc ); + /* Remove the allocation from the list */ + *prev = alloc->next; + _mali_osk_free( alloc ); - /* Move onto the next allocation */ - size -= _MALI_OSK_CPU_PAGE_SIZE; - offset += _MALI_OSK_CPU_PAGE_SIZE; - } + /* Move onto the next allocation */ + size -= _MALI_OSK_CPU_PAGE_SIZE; + offset += _MALI_OSK_CPU_PAGE_SIZE; + } } /* Linux does the right thing as part of munmap to remove the mapping */ diff --git a/drivers/gpu/arm/mali/linux/mali_osk_mali.c b/drivers/gpu/arm/mali/linux/mali_osk_mali.c index d6c4b41ebc0..5b84549ef86 100755 --- a/drivers/gpu/arm/mali/linux/mali_osk_mali.c +++ b/drivers/gpu/arm/mali/linux/mali_osk_mali.c @@ -18,21 +18,24 @@ #include "mali_kernel_common.h" /* MALI_xxx macros */ #include "mali_osk.h" /* kernel side OS functions */ #include "mali_uk_types.h" -#include "mali_kernel_linux.h" /* exports initialize/terminate_kernel_device() */ +#include "mali_kernel_linux.h" /* exports initialize/terminate_kernel_device() definition of mali_osk_low_level_mem_init() and term */ #include -#include /* contains the configuration of the arch we are compiling for */ +#include /* contains the configuration of the arch we are compiling for */ /* is called from mali_kernel_constructor in common code */ _mali_osk_errcode_t _mali_osk_init( void ) { if (0 != initialize_kernel_device()) MALI_ERROR(_MALI_OSK_ERR_FAULT); + mali_osk_low_level_mem_init(); + MALI_SUCCESS; } /* is called from mali_kernel_deconstructor in common code */ void _mali_osk_term( void ) { + mali_osk_low_level_mem_term(); terminate_kernel_device(); } diff --git a/drivers/gpu/arm/mali/linux/mali_osk_misc.c b/drivers/gpu/arm/mali/linux/mali_osk_misc.c index 3afd2da736c..12f4299ee9b 100755 --- a/drivers/gpu/arm/mali/linux/mali_osk_misc.c +++ b/drivers/gpu/arm/mali/linux/mali_osk_misc.c @@ -27,6 +27,18 @@ void _mali_osk_dbgmsg( const char *fmt, ... ) va_end(args); } +u32 _mali_osk_snprintf( char *buf, u32 size, const char *fmt, ... ) +{ + int res; + va_list args; + va_start(args, fmt); + + res = vsnprintf(buf, (size_t)size, fmt, args); + + va_end(args); + return res; +} + void _mali_osk_abort(void) { /* make a simple fault by dereferencing a NULL pointer */ diff --git a/drivers/gpu/arm/mali/linux/mali_osk_notification.c b/drivers/gpu/arm/mali/linux/mali_osk_notification.c old mode 100755 new mode 100644 index 6eb277f3724..539f9ab68b0 --- a/drivers/gpu/arm/mali/linux/mali_osk_notification.c +++ b/drivers/gpu/arm/mali/linux/mali_osk_notification.c @@ -20,7 +20,6 @@ #include #include -#include #include #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) #include @@ -28,12 +27,6 @@ #include #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) -#define LOCK_INIT(x) sema_init(x,1) -#else -#define LOCK_INIT(x) init_MUTEX(x) -#endif - /** * Declaration of the notification queue object type * Contains a linked list of notification pending delivery to user space. @@ -60,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; - LOCK_INIT(&result->mutex); + sema_init(&result->mutex, 1); init_waitqueue_head(&result->receive_queue); INIT_LIST_HEAD(&result->head); @@ -72,7 +65,7 @@ _mali_osk_notification_t *_mali_osk_notification_create( u32 type, u32 size ) /* OPT Recycling of notification objects */ _mali_osk_notification_wrapper_t *notification; - notification = (_mali_osk_notification_wrapper_t *)kmalloc( sizeof(_mali_osk_notification_wrapper_t), GFP_KERNEL ); + notification = (_mali_osk_notification_wrapper_t *)kmalloc( sizeof(_mali_osk_notification_wrapper_t) + size, GFP_KERNEL ); if (NULL == notification) { MALI_DEBUG_PRINT(1, ("Failed to create a notification object\n")); @@ -82,21 +75,13 @@ _mali_osk_notification_t *_mali_osk_notification_create( u32 type, u32 size ) /* Init the list */ INIT_LIST_HEAD(¬ification->list); - /* allocate memory for the buffer requested */ if (0 != size) { - notification->data.result_buffer = kmalloc( size, GFP_KERNEL ); - if ( NULL == notification->data.result_buffer ) - { - /* failed to buffer, cleanup */ - MALI_DEBUG_PRINT(1, ("Failed to allocate memory for notification object buffer of size %d\n", size)); - kfree(notification); - return NULL; - } + notification->data.result_buffer = ((u8*)notification) + sizeof(_mali_osk_notification_wrapper_t); } else { - notification->data.result_buffer = 0; + notification->data.result_buffer = NULL; } /* set up the non-allocating fields */ @@ -116,8 +101,6 @@ void _mali_osk_notification_delete( _mali_osk_notification_t *object ) /* Remove from the list */ list_del(¬ification->list); - /* Free the buffer */ - kfree(notification->data.result_buffer); /* Free the container */ kfree(notification); } @@ -159,6 +142,13 @@ static int _mali_notification_queue_is_empty( _mali_osk_notification_queue_t *qu 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; diff --git a/drivers/gpu/arm/mali/linux/mali_osk_pm.c b/drivers/gpu/arm/mali/linux/mali_osk_pm.c old mode 100755 new mode 100644 index f1363167292..f9c9e5ce2e8 --- a/drivers/gpu/arm/mali/linux/mali_osk_pm.c +++ b/drivers/gpu/arm/mali/linux/mali_osk_pm.c @@ -33,11 +33,13 @@ #include "mali_linux_pm.h" #include "mali_linux_pm_testsuite.h" +#if MALI_LICENSE_IS_GPL #if MALI_PMM_RUNTIME_JOB_CONTROL_ON #ifdef CONFIG_PM_RUNTIME static int is_runtime =0; #endif /* CONFIG_PM_RUNTIME */ #endif /* MALI_PMM_RUNTIME_JOB_CONTROL_ON */ +#endif /* MALI_LICENSE_IS_GPL */ #if MALI_POWER_MGMT_TEST_SUITE @@ -118,12 +120,10 @@ void _mali_osk_pmm_power_down_done(mali_pmm_message_data data) #ifdef CONFIG_PM is_wake_up_needed = 1; #if MALI_POWER_MGMT_TEST_SUITE -#if MALI_PMM_INTERNAL_TESTING if (is_mali_pmu_present == 0) { pwr_mgmt_status_reg = _mali_pmm_cores_list(); } -#endif /* MALI_PMM_INTERNAL_TESTING */ #endif /* MALI_POWER_MGMT_TEST_SUITE */ wake_up_process(pm_thread); MALI_DEBUG_PRINT(4, ("OSPMM: MALI Power down Done\n" )); @@ -182,6 +182,20 @@ void _mali_osk_pmm_dev_activate(void) #endif /* MALI_LICENSE_IS_GPL */ } +void _mali_osk_pmm_ospmm_cleanup( void ) +{ +#if MALI_LICENSE_IS_GPL +#ifdef CONFIG_PM + int thread_state; + thread_state = mali_get_ospmm_thread_state(); + if (thread_state) + { + _mali_osk_pmm_dvfs_operation_done(0); + } +#endif /* CONFIG_PM */ +#endif /* MALI_LICENSE_IS_GPL */ +} + void _mali_osk_pmm_dvfs_operation_done(mali_pmm_message_data data) { #if MALI_LICENSE_IS_GPL diff --git a/drivers/gpu/arm/mali/linux/mali_osk_timers.c b/drivers/gpu/arm/mali/linux/mali_osk_timers.c old mode 100755 new mode 100644 index 1cffce37461..3dfba76bcb3 --- a/drivers/gpu/arm/mali/linux/mali_osk_timers.c +++ b/drivers/gpu/arm/mali/linux/mali_osk_timers.c @@ -51,7 +51,6 @@ void _mali_osk_timer_del( _mali_osk_timer_t *tim ) del_timer_sync(&(tim->timer)); } - void _mali_osk_timer_setcallback( _mali_osk_timer_t *tim, _mali_osk_timer_callback_t callback, void *data ) { MALI_DEBUG_ASSERT_POINTER(tim); diff --git a/drivers/gpu/arm/mali/linux/mali_ukk_core.c b/drivers/gpu/arm/mali/linux/mali_ukk_core.c old mode 100755 new mode 100644 index a10d1ba8a5e..0f745492613 --- a/drivers/gpu/arm/mali/linux/mali_ukk_core.c +++ b/drivers/gpu/arm/mali/linux/mali_ukk_core.c @@ -105,7 +105,7 @@ int wait_for_notification_wrapper(struct mali_session_data *session_data, _mali_ err = _mali_ukk_wait_for_notification(&kargs); if (_MALI_OSK_ERR_OK != err) return map_errcode(err); - if( !(_MALI_NOTIFICATION_CORE_TIMEOUT == kargs.type || _MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS == kargs.type ) ) + if(_MALI_NOTIFICATION_CORE_SHUTDOWN_IN_PROGRESS != kargs.type) { kargs.ctx = NULL; /* prevent kernel address to be returned to user space */ if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_wait_for_notification_s))) return -EFAULT; diff --git a/drivers/gpu/arm/mali/linux/mali_ukk_gp.c b/drivers/gpu/arm/mali/linux/mali_ukk_gp.c index 58ff1de5108..a6f355fd459 100644 --- a/drivers/gpu/arm/mali/linux/mali_ukk_gp.c +++ b/drivers/gpu/arm/mali/linux/mali_ukk_gp.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 ARM Limited. All rights reserved. + * Copyright (C) 2010-2011 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. diff --git a/drivers/gpu/arm/mali/linux/mali_ukk_vsync.c b/drivers/gpu/arm/mali/linux/mali_ukk_vsync.c new file mode 100644 index 00000000000..965ee411535 --- /dev/null +++ b/drivers/gpu/arm/mali/linux/mali_ukk_vsync.c @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2011 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include /* file system operations */ +#include /* user space access */ + +#include "mali_ukk.h" +#include "mali_osk.h" +#include "mali_kernel_common.h" +#include "mali_kernel_session_manager.h" +#include "mali_ukk_wrappers.h" + + +int vsync_event_report_wrapper(struct mali_session_data *session_data, _mali_uk_vsync_event_report_s __user *uargs) +{ + _mali_uk_vsync_event_report_s kargs; + _mali_osk_errcode_t err; + + MALI_CHECK_NON_NULL(uargs, -EINVAL); + + if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_vsync_event_report_s))) + { + return -EFAULT; + } + + kargs.ctx = session_data; + err = _mali_ukk_vsync_event_report(&kargs); + if (_MALI_OSK_ERR_OK != err) + { + return map_errcode(err); + } + + return 0; +} + diff --git a/drivers/gpu/arm/mali/linux/mali_ukk_wrappers.h b/drivers/gpu/arm/mali/linux/mali_ukk_wrappers.h index 0bc6b87e69c..54e3f656b37 100755 --- a/drivers/gpu/arm/mali/linux/mali_ukk_wrappers.h +++ b/drivers/gpu/arm/mali/linux/mali_ukk_wrappers.h @@ -59,6 +59,8 @@ int profiling_stop_wrapper(struct mali_session_data *session_data, _mali_uk_prof int profiling_get_event_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_get_event_s __user *uargs); int profiling_clear_wrapper(struct mali_session_data *session_data, _mali_uk_profiling_clear_s __user *uargs); +int vsync_event_report_wrapper(struct mali_session_data *session_data, _mali_uk_vsync_event_report_s __user *uargs); + int map_errcode( _mali_osk_errcode_t err ); #ifdef __cplusplus diff --git a/drivers/gpu/arm/mali/platform/mali_platform.h b/drivers/gpu/arm/mali/platform/mali_platform.h old mode 100755 new mode 100644 index 96812562127..b381070235e --- a/drivers/gpu/arm/mali/platform/mali_platform.h +++ b/drivers/gpu/arm/mali/platform/mali_platform.h @@ -24,10 +24,14 @@ #define MALI_PLATFORM_SYSTEM 0 #endif +#ifdef __cplusplus +extern "C" { +#endif + /** @brief Platform specific setup and initialisation of MALI - * + * * This is called from the entrypoint of the driver to initialize the platform - * When using PMM, it is also called from the PMM start up to initialise the + * When using PMM, it is also called from the PMM start up to initialise the * system PMU * * @param resource This is NULL when called on first driver start up, else it will @@ -37,7 +41,7 @@ _mali_osk_errcode_t mali_platform_init(_mali_osk_resource_t *resource); /** @brief Platform specific deinitialisation of MALI - * + * * This is called on the exit of the driver to terminate the platform * When using PMM, it is also called from the PMM termination code to clean up the * system PMU @@ -49,7 +53,7 @@ _mali_osk_errcode_t mali_platform_init(_mali_osk_resource_t *resource); _mali_osk_errcode_t mali_platform_deinit(_mali_osk_resource_type_t *type); /** @brief Platform specific powerdown sequence of MALI - * + * * Called as part of platform init if there is no PMM support, else the * PMM will call it. * @@ -60,7 +64,7 @@ _mali_osk_errcode_t mali_platform_deinit(_mali_osk_resource_type_t *type); _mali_osk_errcode_t mali_platform_powerdown(u32 cores); /** @brief Platform specific powerup sequence of MALI - * + * * Called as part of platform deinit if there is no PMM support, else the * PMM will call it. * @@ -90,3 +94,7 @@ void mali_gpu_utilization_handler(u32 utilization); u32 pmu_get_power_up_down_info(void); #endif #endif + +#ifdef __cplusplus +} +#endif diff --git a/drivers/gpu/arm/mali/timestamp-arm11-cc/mali_timestamp.h b/drivers/gpu/arm/mali/timestamp-arm11-cc/mali_timestamp.h index 96b709bc166..3279daede45 100755 --- a/drivers/gpu/arm/mali/timestamp-arm11-cc/mali_timestamp.h +++ b/drivers/gpu/arm/mali/timestamp-arm11-cc/mali_timestamp.h @@ -11,7 +11,7 @@ #ifndef __MALI_TIMESTAMP_H__ #define __MALI_TIMESTAMP_H__ -#include "mali_osk.h" +#include "mali_osk.h" MALI_STATIC_INLINE _mali_osk_errcode_t _mali_timestamp_reset(void) { diff --git a/drivers/gpu/arm/mali/timestamp-default/mali_timestamp.h b/drivers/gpu/arm/mali/timestamp-default/mali_timestamp.h index 11031d675ca..94b842a1008 100755 --- a/drivers/gpu/arm/mali/timestamp-default/mali_timestamp.h +++ b/drivers/gpu/arm/mali/timestamp-default/mali_timestamp.h @@ -11,7 +11,7 @@ #ifndef __MALI_TIMESTAMP_H__ #define __MALI_TIMESTAMP_H__ -#include "mali_osk.h" +#include "mali_osk.h" MALI_STATIC_INLINE _mali_osk_errcode_t _mali_timestamp_reset(void) { diff --git a/drivers/gpu/arm/ump/Kconfig b/drivers/gpu/arm/ump/Kconfig index db7b45b03de..62f1cec9311 100644 --- a/drivers/gpu/arm/ump/Kconfig +++ b/drivers/gpu/arm/ump/Kconfig @@ -1,6 +1,6 @@ config UMP bool "Enable UMP(Unified Memory Provider)" - default y + default n ---help--- This enables UMP memory provider diff --git a/drivers/gpu/arm/ump/Makefile b/drivers/gpu/arm/ump/Makefile index 7e2501d8087..9c1b214b998 100755 --- a/drivers/gpu/arm/ump/Makefile +++ b/drivers/gpu/arm/ump/Makefile @@ -22,7 +22,7 @@ UDD_FILE_PREFIX := drivers/gpu/arm/ump/ ifeq (($CONFIG_UMP_DEBUG),y) EXTRA_CFLAGS += -DDEBUG endif - +EXTRA_CFLAGS += -DMALI_STATE_TRACKING=0 USING_MEMORY_TYPE ?=0 # 0: dedicated memory 1: OS memory EXTRA_CFLAGS += -I$(UDD_FILE_PREFIX) -I$(UDD_FILE_PREFIX)/common -I$(UDD_FILE_PREFIX)/linux -I$(UDD_FILE_PREFIX)/../mali/common -I$(UDD_FILE_PREFIX)/../mali/linux -I$(UDD_FILE_PREFIX)/include diff --git a/drivers/gpu/arm/ump/common/ump_kernel_api.c b/drivers/gpu/arm/ump/common/ump_kernel_api.c index 719370c3de7..329a3ac115c 100755 --- a/drivers/gpu/arm/ump/common/ump_kernel_api.c +++ b/drivers/gpu/arm/ump/common/ump_kernel_api.c @@ -296,15 +296,21 @@ _mali_osk_errcode_t _ump_ukk_size_get( _ump_uk_size_get_s *user_interaction ) void _ump_ukk_msync( _ump_uk_msync_s *args ) { ump_dd_mem * mem = NULL; + void *virtual = NULL; + u32 size = 0; + u32 offset = 0; _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); ump_descriptor_mapping_get(device.secure_id_map, (int)args->secure_id, (void**)&mem); - _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); - if (NULL==mem) + if (NULL == mem) { + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); DBG_MSG(1, ("Failed to look up mapping in _ump_ukk_msync(). ID: %u\n", (ump_secure_id)args->secure_id)); return; } + /* Ensure the memory doesn't dissapear when we are flushing it. */ + ump_dd_reference_add(mem); + _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW); /* Returns the cache settings back to Userspace */ args->is_cached=mem->is_cached; @@ -313,17 +319,44 @@ void _ump_ukk_msync( _ump_uk_msync_s *args ) if ( _UMP_UK_MSYNC_READOUT_CACHE_ENABLED==args->op ) { DBG_MSG(3, ("_ump_ukk_msync READOUT ID: %u Enabled: %d\n", (ump_secure_id)args->secure_id, mem->is_cached)); - return; + goto msync_release_and_return; } /* Nothing to do if the memory is not caches */ if ( 0==mem->is_cached ) { DBG_MSG(3, ("_ump_ukk_msync IGNORING ID: %u Enabled: %d OP: %d\n", (ump_secure_id)args->secure_id, mem->is_cached, args->op)); - return ; + goto msync_release_and_return; + } + DBG_MSG(3, ("_ump_ukk_msync FLUSHING ID: %u Enabled: %d OP: %d Address: 0x%08x Mapping: 0x%08x\n", + (ump_secure_id)args->secure_id, mem->is_cached, args->op, args->address, args->mapping)); + + if ( args->address ) + { + virtual = ((u32)args->address); + offset = (u32)((args->address) - (args->mapping)); + } else { + /* Flush entire mapping when no address is specified. */ + virtual = args->mapping; + } + if ( args->size ) + { + size = args->size; + } else { + /* Flush entire mapping when no size is specified. */ + size = mem->size_bytes - offset; + } + + if ( (offset + size) > mem->size_bytes ) + { + DBG_MSG(1, ("Trying to flush more than the entire UMP allocation: offset: %u + size: %u > %u\n", offset, size, mem->size_bytes)); + goto msync_release_and_return; } - DBG_MSG(3, ("_ump_ukk_msync FLUSHING ID: %u Enabled: %d OP: %d\n", (ump_secure_id)args->secure_id, mem->is_cached, args->op)); /* The actual cache flush - Implemented for each OS*/ - _ump_osk_msync( mem , args->op); + _ump_osk_msync( mem, virtual, offset, size, args->op); + +msync_release_and_return: + ump_dd_reference_release(mem); + return; } diff --git a/drivers/gpu/arm/ump/common/ump_kernel_common.c b/drivers/gpu/arm/ump/common/ump_kernel_common.c index 5575a5e3b1b..b99c3e7c7d2 100755 --- a/drivers/gpu/arm/ump/common/ump_kernel_common.c +++ b/drivers/gpu/arm/ump/common/ump_kernel_common.c @@ -280,12 +280,6 @@ _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; diff --git a/drivers/gpu/arm/ump/common/ump_osk.h b/drivers/gpu/arm/ump/common/ump_osk.h index 73284f02b47..3e2be49b80d 100755 --- a/drivers/gpu/arm/ump/common/ump_osk.h +++ b/drivers/gpu/arm/ump/common/ump_osk.h @@ -39,7 +39,7 @@ _mali_osk_errcode_t _ump_osk_mem_mapregion_map( ump_memory_allocation * descript void _ump_osk_mem_mapregion_term( ump_memory_allocation * descriptor ); -void _ump_osk_msync( ump_dd_mem * mem, ump_uk_msync_op op ); +void _ump_osk_msync( ump_dd_mem * mem, void * virt, u32 offset, u32 size, ump_uk_msync_op op ); #ifdef __cplusplus } diff --git a/drivers/gpu/arm/ump/linux/license/gpl/ump_kernel_license.h b/drivers/gpu/arm/ump/linux/license/gpl/ump_kernel_license.h index 17b930d2c57..a5f4b529f0d 100644 --- a/drivers/gpu/arm/ump/linux/license/gpl/ump_kernel_license.h +++ b/drivers/gpu/arm/ump/linux/license/gpl/ump_kernel_license.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 ARM Limited. All rights reserved. + * Copyright (C) 2010-2011 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. diff --git a/drivers/gpu/arm/ump/linux/ump_kernel_memory_backend_dedicated.c b/drivers/gpu/arm/ump/linux/ump_kernel_memory_backend_dedicated.c index e53ed444977..91440296459 100755 --- a/drivers/gpu/arm/ump/linux/ump_kernel_memory_backend_dedicated.c +++ b/drivers/gpu/arm/ump/linux/ump_kernel_memory_backend_dedicated.c @@ -222,6 +222,7 @@ static int block_allocator_allocate(void* ctx, ump_dd_mem * mem) mem->backend_info = last_allocated; up(&allocator->mutex); + mem->is_cached=0; return 1; } diff --git a/drivers/gpu/arm/ump/linux/ump_kernel_memory_backend_os.c b/drivers/gpu/arm/ump/linux/ump_kernel_memory_backend_os.c index 09f303f78f9..938cf496440 100755 --- a/drivers/gpu/arm/ump/linux/ump_kernel_memory_backend_os.c +++ b/drivers/gpu/arm/ump/linux/ump_kernel_memory_backend_os.c @@ -142,10 +142,11 @@ static int os_allocate(void* ctx, ump_dd_mem * descriptor) if (is_cached) { - new_page = alloc_page(GFP_HIGHUSER | __GFP_ZERO | __GFP_NORETRY | __GFP_NOWARN ); + /* Only allocate lowmem pages when using cached memory. */ + new_page = alloc_page(GFP_USER | __GFP_ZERO | __GFP_REPEAT | __GFP_NOWARN); } else { - new_page = alloc_page(GFP_HIGHUSER | __GFP_ZERO | __GFP_NORETRY | __GFP_NOWARN | __GFP_COLD); + new_page = alloc_page(GFP_HIGHUSER | __GFP_ZERO | __GFP_REPEAT | __GFP_NOWARN | __GFP_COLD); } if (NULL == new_page) { diff --git a/drivers/gpu/arm/ump/linux/ump_osk_low_level_mem.c b/drivers/gpu/arm/ump/linux/ump_osk_low_level_mem.c index 7a1c5e97886..3a3a6f78fcc 100755 --- a/drivers/gpu/arm/ump/linux/ump_osk_low_level_mem.c +++ b/drivers/gpu/arm/ump/linux/ump_osk_low_level_mem.c @@ -26,6 +26,7 @@ #include #include +#include /* to verify pointers from user space */ #include #include @@ -206,38 +207,92 @@ _mali_osk_errcode_t _ump_osk_mem_mapregion_map( ump_memory_allocation * descript } -void _ump_osk_msync( ump_dd_mem * mem, ump_uk_msync_op op ) +void _ump_osk_msync( ump_dd_mem * mem, void * virt, u32 offset, u32 size, ump_uk_msync_op op ) { int i; - DBG_MSG(3, ("Flushing nr of blocks: %u. First: paddr: 0x%08x vaddr: 0x%08x size:%dB\n", mem->nr_blocks, mem->block_array[0].addr, phys_to_virt(mem->block_array[0].addr), mem->block_array[0].size)); + const void *start_v, *end_v; - /* TODO: Use args->size and args->address to select a subrange of this allocation to flush */ - for (i=0 ; inr_blocks; i++) + DBG_MSG(3, ("Flushing nr of blocks: %u, size: %u. First: paddr: 0x%08x vaddr: 0x%08x offset: 0x%08x size:%uB\n", + mem->nr_blocks, mem->size_bytes, mem->block_array[0].addr, virt, offset, size)); + + /* Flush L1 using virtual address, the entire range in one go. + * Only flush if user space process has a valid write mapping on given address. */ + if(access_ok(VERIFY_WRITE, virt, size)) + { + start_v = (void *)virt; + 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); + } + else { - /* TODO: Find out which flush method is best of 1)Dma OR 2)Normal flush functions */ - /* TODO: Use args->op to select the flushing method: CLEAN_AND_INVALIDATE or CLEAN */ - /*#define USING_DMA_FLUSH*/ - #ifdef USING_DMA_FLUSH - DEBUG_ASSERT( (PAGE_SIZE==mem->block_array[i].size)); - dma_map_page(NULL, pfn_to_page(mem->block_array[i].addr >> PAGE_SHIFT), 0, PAGE_SIZE, DMA_BIDIRECTIONAL ); - /*dma_unmap_page(NULL, mem->block_array[i].addr, PAGE_SIZE, DMA_BIDIRECTIONAL);*/ - #else - /* Normal style flush */ - ump_dd_physical_block *block; - u32 start_p, end_p; - const void *start_v, *end_v; - block = &mem->block_array[i]; - - start_p = (u32)block->addr; - start_v = phys_to_virt( start_p ) ; - - end_p = start_p + block->size-1; - end_v = phys_to_virt( end_p ) ; - - dmac_flush_range(start_v, end_v); - outer_flush_range(start_p, end_p); - #endif + DBG_MSG(1, ("Attempt to flush %d@%x as part of ID %u rejected: there is no valid mapping.\n", + size, virt, mem->secure_id)); + return; } - return ; + /* Flush L2 using physical addresses, block for block. */ + for (i=0 ; i < mem->nr_blocks; i++) + { + u32 start_p, end_p; + ump_dd_physical_block *block; + block = &mem->block_array[i]; + + if(offset >= block->size) + { + offset -= block->size; + continue; + } + + if(offset) + { + start_p = (u32)block->addr + offset; + /* We'll zero the offset later, after using it to calculate end_p. */ + } + else + { + start_p = (u32)block->addr; + } + + if(size < block->size - offset) + { + end_p = start_p + size - 1; + size = 0; + } + else + { + if(offset) + { + end_p = start_p + (block->size - offset - 1); + size -= block->size - offset; + offset = 0; + } + else + { + end_p = start_p + block->size - 1; + size -= block->size; + } + } + + switch(op) + { + case _UMP_UK_MSYNC_CLEAN: + outer_clean_range(start_p, end_p); + break; + case _UMP_UK_MSYNC_CLEAN_AND_INVALIDATE: + outer_flush_range(start_p, end_p); + break; + default: + break; + } + + if(0 == size) + { + /* Nothing left to flush. */ + break; + } + } + + return; } diff --git a/drivers/gpu/arm/ump/linux/ump_ukk_wrappers.c b/drivers/gpu/arm/ump/linux/ump_ukk_wrappers.c index d14b631246c..d986e9f51d6 100755 --- a/drivers/gpu/arm/ump/linux/ump_ukk_wrappers.c +++ b/drivers/gpu/arm/ump/linux/ump_ukk_wrappers.c @@ -138,9 +138,9 @@ int ump_size_get_wrapper(u32 __user * argument, struct ump_session_data * sessi } /* - * IOCTL operation; Return size for specified UMP memory. + * IOCTL operation; Do cache maintenance on specified UMP memory. */ - int ump_msync_wrapper(u32 __user * argument, struct ump_session_data * session_data) +int ump_msync_wrapper(u32 __user * argument, struct ump_session_data * session_data) { _ump_uk_msync_s user_interaction; -- cgit v1.2.3