diff options
author | Philippe Langlais <philippe.langlais@stericsson.com> | 2012-06-04 19:46:22 +0800 |
---|---|---|
committer | Philippe Langlais <philippe.langlais@stericsson.com> | 2012-06-04 19:46:22 +0800 |
commit | 1c4a401e4961ffda3c432504e69d12316cfdbdf3 (patch) | |
tree | 1fa2157f1d2712a7f838eadd236e35681957c323 /drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common | |
parent | c65e9ef43160d318d715d5a1c8752864aace85f0 (diff) | |
parent | fcddfa7f1d6cbdd5b841665b2337422627394cff (diff) |
Merge topic branch 'mali-android' into integration-android-ux500
Diffstat (limited to 'drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common')
40 files changed, 2011 insertions, 757 deletions
diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_block_allocator.c b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_block_allocator.c index fc80a20c813..5416ca9ea4d 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_block_allocator.c +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_block_allocator.c @@ -49,6 +49,7 @@ static void block_allocator_release(void * ctx, void * handle); static mali_physical_memory_allocation_result block_allocator_allocate_page_table_block(void * ctx, mali_page_table_block * block); static void block_allocator_release_page_table_block( mali_page_table_block *page_table_block ); static void block_allocator_destroy(mali_physical_memory_allocator * allocator); +static u32 block_allocator_stat(mali_physical_memory_allocator * allocator); mali_physical_memory_allocator * mali_block_allocator_create(u32 base_address, u32 cpu_usage_adjust, u32 size, const char *name) { @@ -97,6 +98,7 @@ mali_physical_memory_allocator * mali_block_allocator_create(u32 base_address, u allocator->allocate = block_allocator_allocate; allocator->allocate_page_table_block = block_allocator_allocate_page_table_block; allocator->destroy = block_allocator_destroy; + allocator->stat = block_allocator_stat; allocator->ctx = info; allocator->name = name; @@ -275,7 +277,8 @@ static void block_allocator_release(void * ctx, void * handle) _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); - _mali_osk_free( allocation );} + _mali_osk_free( allocation ); +} static mali_physical_memory_allocation_result block_allocator_allocate_page_table_block(void * ctx, mali_page_table_block * block) @@ -368,3 +371,21 @@ static void block_allocator_release_page_table_block( mali_page_table_block *pag _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); } +static u32 block_allocator_stat(mali_physical_memory_allocator * allocator) +{ + block_allocator * info; + block_info *block; + u32 free_blocks = 0; + + MALI_DEBUG_ASSERT_POINTER(allocator); + + info = (block_allocator*)allocator->ctx; + block = info->first_free; + + while(block) + { + free_blocks++; + block = block->next; + } + return (info->num_blocks - free_blocks) * MALI_BLOCK_SIZE; +} diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_block_allocator.h b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_block_allocator.h index c3b5761e23a..d3f0f9be60a 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_block_allocator.h +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_block_allocator.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * Copyright (C) 2010 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_cinstr_profiling_events_m200.h b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_cinstr_profiling_events_m200.h new file mode 100644 index 00000000000..dee50a359a1 --- /dev/null +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_cinstr_profiling_events_m200.h @@ -0,0 +1,117 @@ +/** + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms of + * such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef _CINSTR_PROFILING_EVENTS_M200_H_ +#define _CINSTR_PROFILING_EVENTS_M200_H_ + +/* + * The event ID is a 32 bit value consisting of different fields + * reserved, 4 bits, for future use + * event type, 4 bits, cinstr_profiling_event_type_t + * event channel, 8 bits, the source of the event. + * event data, 16 bit field, data depending on event type + */ + +/** + * Specifies what kind of event this is + */ +typedef enum +{ + MALI_PROFILING_EVENT_TYPE_SINGLE = 0 << 24, + MALI_PROFILING_EVENT_TYPE_START = 1 << 24, + MALI_PROFILING_EVENT_TYPE_STOP = 2 << 24, + MALI_PROFILING_EVENT_TYPE_SUSPEND = 3 << 24, + MALI_PROFILING_EVENT_TYPE_RESUME = 4 << 24, +} cinstr_profiling_event_type_t; + + +/** + * Secifies the channel/source of the event + */ +typedef enum +{ + MALI_PROFILING_EVENT_CHANNEL_SOFTWARE = 0 << 16, + MALI_PROFILING_EVENT_CHANNEL_GP0 = 1 << 16, + MALI_PROFILING_EVENT_CHANNEL_PP0 = 5 << 16, + MALI_PROFILING_EVENT_CHANNEL_PP1 = 6 << 16, + MALI_PROFILING_EVENT_CHANNEL_PP2 = 7 << 16, + MALI_PROFILING_EVENT_CHANNEL_PP3 = 8 << 16, + MALI_PROFILING_EVENT_CHANNEL_PP4 = 9 << 16, + MALI_PROFILING_EVENT_CHANNEL_PP5 = 10 << 16, + MALI_PROFILING_EVENT_CHANNEL_PP6 = 11 << 16, + MALI_PROFILING_EVENT_CHANNEL_PP7 = 12 << 16, + MALI_PROFILING_EVENT_CHANNEL_GPU = 21 << 16, +} cinstr_profiling_event_channel_t; + + +#define MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(num) (((MALI_PROFILING_EVENT_CHANNEL_GP0 >> 16) + (num)) << 16) +#define MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(num) (((MALI_PROFILING_EVENT_CHANNEL_PP0 >> 16) + (num)) << 16) + +/** + * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SINGLE is used from software channel + */ +typedef enum +{ + MALI_PROFILING_EVENT_REASON_SINGLE_SW_NONE = 0, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_EGL_NEW_FRAME = 1, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_FLUSH = 2, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_EGL_SWAP_BUFFERS = 3, + MALI_PROFILING_EVENT_REASON_SINGLE_SW_FB_EVENT = 4 +} cinstr_profiling_event_reason_single_sw_t; + +/** + * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_START/STOP is used from software channel + */ +typedef enum +{ + MALI_PROFILING_EVENT_REASON_START_STOP_SW_NONE = 0, + MALI_PROFILING_EVENT_REASON_START_STOP_MALI = 1, +} cinstr_profiling_event_reason_start_stop_sw_t; + +/** + * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SUSPEND/RESUME is used from software channel + */ +typedef enum +{ + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_NONE = 0, + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_PIPELINE_FULL = 1, + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VSYNC = 26, + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_FB_IFRAME_WAIT= 27, + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_FB_IFRAME_SYNC= 28, + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VG_WAIT_FILTER_CLEANUP = 29, + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_VG_WAIT_TEXTURE = 30, + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_GLES_WAIT_MIPLEVEL = 31, + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_GLES_WAIT_READPIXELS = 32, + MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_EGL_WAIT_SWAP_IMMEDIATE= 33, +} cinstr_profiling_event_reason_suspend_resume_sw_t; + +/** + * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SINGLE is used from a HW channel (GPx+PPx) + */ +typedef enum +{ + MALI_PROFILING_EVENT_REASON_SINGLE_HW_NONE = 0, + MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT = 1, + MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH = 2, +} cinstr_profiling_event_reason_single_hw_t; + +/** + * These events are applicable when the type MALI_PROFILING_EVENT_TYPE_SINGLE is used from the GPU channel + */ +typedef enum +{ + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_NONE = 0, + MALI_PROFILING_EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE = 1, +} cinstr_profiling_event_reason_single_gpu_t; + +#endif /*_CINSTR_PROFILING_EVENTS_M200_H_*/ diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_GP2.c b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_GP2.c index e91abe120cb..dd357dec3b9 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_GP2.c +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_GP2.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. @@ -15,8 +15,8 @@ #include "mali_kernel_rendercore.h" #include "mali_osk.h" #include "mali_osk_list.h" -#if MALI_TIMELINE_PROFILING_ENABLED -#include "mali_kernel_profiling.h" +#if MALI_TIMELINE_PROFILING_ENABLED +#include "mali_osk_profiling.h" #endif #if defined(USING_MALI400_L2_CACHE) #include "mali_kernel_l2_cache.h" @@ -80,7 +80,7 @@ typedef struct maligp_job u32 perf_counter_l2_val1; #endif -#if MALI_TIMELINE_PROFILING_ENABLED +#if MALI_TIMELINE_PROFILING_ENABLED u32 pid; u32 tid; #endif @@ -102,7 +102,7 @@ static _mali_osk_errcode_t maligp_renderunit_create(_mali_osk_resource_t * resou static void maligp_subsystem_broadcast_notification(mali_core_notification_message message, u32 data); #endif #if MALI_STATE_TRACKING -void maligp_subsystem_dump_state(void); +u32 maligp_subsystem_dump_state(char *buf, u32 size); #endif /* Internal support functions */ @@ -583,8 +583,9 @@ static void maligp_initialize_registers_mgmt(mali_core_renderunit *core ) MALI_DEBUG_PRINT(6, ("Mali GP: maligp_initialize_registers_mgmt: %s\n", core->description)) ; for(i=0 ; i< (sizeof(default_mgmt_regs)/sizeof(*default_mgmt_regs)) ; ++i) { - mali_core_renderunit_register_write(core, default_mgmt_regs[i].address, default_mgmt_regs[i].value); + mali_core_renderunit_register_write_relaxed(core, default_mgmt_regs[i].address, default_mgmt_regs[i].value); } + _mali_osk_write_mem_barrier(); } @@ -627,17 +628,43 @@ static _mali_osk_errcode_t subsystem_maligp_start_job(mali_core_job * job, mali_ &(jobgp->user_input.frame_registers[0]), sizeof(jobgp->user_input.frame_registers)/sizeof(jobgp->user_input.frame_registers[0])); +#if MALI_TIMELINE_PROFILING_ENABLED + /* + * If the hardware counters are not turned on, ask the external profiler + * if they should be. + */ + if (jobgp->user_input.perf_counter_flag == 0) + { + mali_bool src0_enabled = _mali_osk_profiling_query_hw_counter(COUNTER_VP_C0, + &(jobgp->user_input.perf_counter_src0)); + mali_bool src1_enabled = _mali_osk_profiling_query_hw_counter(COUNTER_VP_C1, + &(jobgp->user_input.perf_counter_src1)); + + if (src0_enabled == MALI_TRUE) + { + jobgp->user_input.perf_counter_flag |= + _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE; + } + + if (src1_enabled == MALI_TRUE) + { + jobgp->user_input.perf_counter_flag |= + _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE; + } + } +#endif /* MALI_TIMELINE_PROFILING_ENABLED */ + /* This selects which performance counters we are reading */ if ( 0 != jobgp->user_input.perf_counter_flag ) { if ( jobgp->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE) { - mali_core_renderunit_register_write( + mali_core_renderunit_register_write_relaxed( core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_SRC, jobgp->user_input.perf_counter_src0); - mali_core_renderunit_register_write( + mali_core_renderunit_register_write_relaxed( core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE); @@ -645,12 +672,12 @@ static _mali_osk_errcode_t subsystem_maligp_start_job(mali_core_job * job, mali_ if ( jobgp->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE) { - mali_core_renderunit_register_write( + mali_core_renderunit_register_write_relaxed( core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_SRC, jobgp->user_input.perf_counter_src1); - mali_core_renderunit_register_write( + mali_core_renderunit_register_write_relaxed( core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE); @@ -689,13 +716,13 @@ static _mali_osk_errcode_t subsystem_maligp_start_job(mali_core_job * job, mali_ jobgp->have_extended_progress_checking = 1; - mali_core_renderunit_register_write( + mali_core_renderunit_register_write_relaxed( core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_SRC, MALIGP2_REG_VAL_PERF_CNT1_SRC_NUMBER_OF_VERTICES_PROCESSED ); - mali_core_renderunit_register_write( + mali_core_renderunit_register_write_relaxed( core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALIGP2_REG_VAL_PERF_CNT_ENABLE); @@ -704,14 +731,20 @@ 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, MALIGP2_REG_ADDR_MGMT_CMD, startcmd); + _mali_osk_write_mem_barrier(); -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number), jobgp->pid, jobgp->tid, 0, 0, 0); +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number) | MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH, + jobgp->user_input.frame_builder_id, jobgp->user_input.flush_id, 0, 0, 0); + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number), jobgp->pid, jobgp->tid, 0, 0, 0); #endif MALI_SUCCESS; @@ -729,12 +762,16 @@ static u32 subsystem_maligp_irq_handler_upper_half(mali_core_renderunit * core) irq_readout = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_INT_STAT); - MALI_DEBUG_PRINT(5, ("Mali GP: IRQ: %04x\n", irq_readout)) ; if ( MALIGP2_REG_VAL_IRQ_MASK_NONE != irq_readout ) { /* Mask out all IRQs from this core until IRQ is handled */ - mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_MASK , MALIGP2_REG_VAL_IRQ_MASK_NONE); + mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_MASK, MALIGP2_REG_VAL_IRQ_MASK_NONE); + +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number)|MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT, irq_readout, 0, 0, 0, 0); +#endif + /* We do need to handle this in a bottom half, return 1 */ return 1; } @@ -792,15 +829,17 @@ static int subsystem_maligp_irq_handler_bottom_half(mali_core_renderunit* core) if ( 0 != jobgp->is_stalled_waiting_for_more_memory ) { -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status? */ -#endif - /* Readback the performance counters */ if (jobgp->user_input.perf_counter_flag & (_MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE|_MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE) ) { jobgp->perf_counter0 = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_VALUE); jobgp->perf_counter1 = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE); + +#if MALI_TIMELINE_PROFILING_ENABLED + /* Report the hardware counter values to the external profiler */ + _mali_osk_profiling_report_hw_counter(COUNTER_VP_C0, jobgp->perf_counter0); + _mali_osk_profiling_report_hw_counter(COUNTER_VP_C1, jobgp->perf_counter1); +#endif /* MALI_TIMELINE_PROFILING_ENABLED */ } #if defined(USING_MALI400_L2_CACHE) @@ -832,16 +871,19 @@ static int subsystem_maligp_irq_handler_bottom_half(mali_core_renderunit* core) } #endif +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status? */ +#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 ? */ else if (0 == (core_status & MALIGP2_REG_VAL_STATUS_MASK_ACTIVE)) { -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status? */ -#endif - #ifdef DEBUG MALI_DEBUG_PRINT(4, ("Mali GP: Registers On job end:\n")); maligp_print_regs(4, core); @@ -859,6 +901,12 @@ static int subsystem_maligp_irq_handler_bottom_half(mali_core_renderunit* core) { jobgp->perf_counter0 = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_0_VALUE); jobgp->perf_counter1 = mali_core_renderunit_register_read(core, MALIGP2_REG_ADDR_MGMT_PERF_CNT_1_VALUE); + +#if MALI_TIMELINE_PROFILING_ENABLED + /* Report the hardware counter values to the external profiler */ + _mali_osk_profiling_report_hw_counter(COUNTER_VP_C0, jobgp->perf_counter0); + _mali_osk_profiling_report_hw_counter(COUNTER_VP_C1, jobgp->perf_counter1); +#endif /* MALI_TIMELINE_PROFILING_ENABLED */ } #if defined(USING_MALI400_L2_CACHE) @@ -891,8 +939,25 @@ static int subsystem_maligp_irq_handler_bottom_half(mali_core_renderunit* core) #endif } +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number), + jobgp->perf_counter0, jobgp->perf_counter1, + jobgp->user_input.perf_counter_src0 | (jobgp->user_input.perf_counter_src1 << 8) +#if defined(USING_MALI400_L2_CACHE) + | (jobgp->user_input.perf_counter_l2_src0 << 16) | (jobgp->user_input.perf_counter_l2_src1 << 24), + jobgp->perf_counter_l2_val0, + jobgp->perf_counter_l2_val1 +#else + ,0, 0 +#endif + ); +#endif + 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 ? */ @@ -910,8 +975,8 @@ static int subsystem_maligp_irq_handler_bottom_half(mali_core_renderunit* core) { /* no progress detected, killed by the watchdog */ -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status? */ +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status? */ #endif MALI_DEBUG_PRINT(1, ("Mali GP: SW-Timeout. Regs:\n")); @@ -922,6 +987,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 */ @@ -932,8 +1002,8 @@ static int subsystem_maligp_irq_handler_bottom_half(mali_core_renderunit* core) _mali_osk_notification_t *notific; _mali_uk_gp_job_suspended_s * suspended_job; -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SUSPEND|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status? */ +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SUSPEND|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status? */ #endif session = job->session; @@ -1013,8 +1083,8 @@ static int subsystem_maligp_irq_handler_bottom_half(mali_core_renderunit* core) /* Else there must be some error */ else { -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status? */ +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status? */ #endif MALI_DEBUG_PRINT(1, ("Mali GP: Core crashed? *IRQ: 0x%x Status: 0x%x\n", irq_readout, core_status )); @@ -1022,6 +1092,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; } } @@ -1032,7 +1105,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; @@ -1071,7 +1144,7 @@ static _mali_osk_errcode_t subsystem_maligp_get_new_job_from_user(struct mali_co jobgp->is_stalled_waiting_for_more_memory = 0; -#if MALI_TIMELINE_PROFILING_ENABLED +#if MALI_TIMELINE_PROFILING_ENABLED jobgp->pid = _mali_osk_get_pid(); jobgp->tid = _mali_osk_get_tid(); #endif @@ -1154,6 +1227,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); } @@ -1197,12 +1280,13 @@ static _mali_osk_errcode_t subsystem_maligp_suspend_response(struct mali_core_se mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_CLEAR, (MALIGP2_REG_VAL_IRQ_PLBU_OUT_OF_MEM | MALIGP2_REG_VAL_IRQ_HANG)); mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_INT_MASK, jobgp->active_mask); - mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR, suspend_response->arguments[0]); - mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_END_ADDR, suspend_response->arguments[1]); + mali_core_renderunit_register_write_relaxed(core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_START_ADDR, suspend_response->arguments[0]); + mali_core_renderunit_register_write_relaxed(core, MALIGP2_REG_ADDR_MGMT_PLBU_ALLOC_END_ADDR, suspend_response->arguments[1]); mali_core_renderunit_register_write(core, MALIGP2_REG_ADDR_MGMT_CMD, MALIGP2_REG_VAL_CMD_UPDATE_PLBU_ALLOC); + _mali_osk_write_mem_barrier(); -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_RESUME|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number), 0, 0, 0, 0, 0); +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_RESUME|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(core->core_number), 0, 0, 0, 0, 0); #endif MALI_DEBUG_PRINT(4, ("GP resumed with new heap\n")); @@ -1281,6 +1365,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; @@ -1411,8 +1498,8 @@ _mali_osk_errcode_t maligp_signal_power_down( mali_bool immediate_only ) #endif #if MALI_STATE_TRACKING -void maligp_subsystem_dump_state(void) +u32 maligp_subsystem_dump_state(char *buf, u32 size) { - mali_core_renderunit_dump_state(&subsystem_maligp); + return mali_core_renderunit_dump_state(&subsystem_maligp, buf, size); } #endif diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_MALI200.c b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_MALI200.c index 0ac49379bea..d861b2288d3 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_MALI200.c +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_MALI200.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. @@ -15,8 +15,8 @@ #include "mali_kernel_core.h" #include "regs/mali_200_regs.h" #include "mali_kernel_rendercore.h" -#if MALI_TIMELINE_PROFILING_ENABLED -#include "mali_kernel_profiling.h" +#if MALI_TIMELINE_PROFILING_ENABLED +#include "mali_osk_profiling.h" #endif #ifdef USING_MALI400_L2_CACHE #include "mali_kernel_l2_cache.h" @@ -71,8 +71,8 @@ typedef struct mali200_job u32 perf_counter_l2_val1_raw; #endif -#if MALI_TIMELINE_PROFILING_ENABLED - u32 pid; +#if MALI_TIMELINE_PROFILING_ENABLED + u32 pid; u32 tid; #endif } mali200_job; @@ -94,7 +94,7 @@ static _mali_osk_errcode_t mali200_renderunit_create(_mali_osk_resource_t * reso static void mali200_subsystem_broadcast_notification(mali_core_notification_message message, u32 data); #endif #if MALI_STATE_TRACKING -void mali200_subsystem_dump_state(void); +u32 mali200_subsystem_dump_state(char *buf, u32 size); #endif /* Internal support functions */ @@ -572,17 +572,49 @@ static _mali_osk_errcode_t subsystem_mali200_start_job(mali_core_job * job, mali &(job200->user_input.wb2_registers[0]), MALI200_NUM_REGS_WBx); +#if MALI_TIMELINE_PROFILING_ENABLED + /* + * If the hardware counters are not turned on, ask the external profiler + * if they should be. + */ + if (job200->user_input.perf_counter_flag == 0) + { + /* + * Work out the correct counter offset to use. Each fragment processor + * has two hardware counters. + */ + u32 counter0_offset = MALI_PROFILING_PP_CORE_COUNTER0_OFFSET(core->core_number); + u32 counter1_offset = MALI_PROFILING_PP_CORE_COUNTER1_OFFSET(core->core_number); + + mali_bool src0_enabled = _mali_osk_profiling_query_hw_counter(counter0_offset, + &(job200->user_input.perf_counter_src0)); + mali_bool src1_enabled = _mali_osk_profiling_query_hw_counter(counter1_offset, + &(job200->user_input.perf_counter_src1)); + + if (src0_enabled == MALI_TRUE) + { + job200->user_input.perf_counter_flag |= + _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE; + } + + if (src1_enabled == MALI_TRUE) + { + job200->user_input.perf_counter_flag |= + _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE; + } + } +#endif /* MALI_TIMELINE_PROFILING_ENABLED */ /* This selects which performance counters we are reading */ if ( 0 != job200->user_input.perf_counter_flag ) { if ( job200->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE) { - mali_core_renderunit_register_write( + mali_core_renderunit_register_write_relaxed( core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE); - mali_core_renderunit_register_write( + mali_core_renderunit_register_write_relaxed( core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, job200->user_input.perf_counter_src0); @@ -591,11 +623,11 @@ static _mali_osk_errcode_t subsystem_mali200_start_job(mali_core_job * job, mali if ( job200->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE) { - mali_core_renderunit_register_write( + mali_core_renderunit_register_write_relaxed( core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE); - mali_core_renderunit_register_write( + mali_core_renderunit_register_write_relaxed( core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, job200->user_input.perf_counter_src1); @@ -630,16 +662,21 @@ 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, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_START_RENDERING); + _mali_osk_write_mem_barrier(); #if MALI_TIMELINE_PROFILING_ENABLED - _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_number), job200->pid, job200->tid, 0, 0, 0); + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_number) | MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH, job200->user_input.frame_builder_id, job200->user_input.flush_id, 0, 0, 0); + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_number), job200->pid, job200->tid, 0, 0, 0); #endif MALI_SUCCESS; @@ -653,13 +690,17 @@ static u32 subsystem_mali200_irq_handler_upper_half(mali_core_renderunit * core) return (core->current_job ? 1 : 0); /* simulate irq is pending when a job is pending */ } - MALI_DEBUG_PRINT(5, ("Mali PP: subsystem_mali200_irq_handler_upper_half: %s\n", core->description)) ; irq_readout = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_INT_STATUS); if ( MALI200_REG_VAL_IRQ_MASK_NONE != irq_readout ) { /* Mask out all IRQs from this core until IRQ is handled */ mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_NONE); + +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_number)|MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT, irq_readout, 0, 0, 0, 0); +#endif + return 1; } return 0; @@ -710,16 +751,24 @@ static int subsystem_mali200_irq_handler_bottom_half(struct mali_core_renderunit mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_FLUSH_CACHES); #endif -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status */ -#endif - if (0 != job200->user_input.perf_counter_flag ) { if (job200->user_input.perf_counter_flag & (_MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE|_MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE) ) { +#if MALI_TIMELINE_PROFILING_ENABLED + /* Work out the counter offsets for the core number */ + u32 counter0_offset = MALI_PROFILING_PP_CORE_COUNTER0_OFFSET(core->core_number); + u32 counter1_offset = MALI_PROFILING_PP_CORE_COUNTER1_OFFSET(core->core_number); +#endif /* MALI_TIMELINE_PROFILING_ENABLED */ + job200->perf_counter0 = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE); job200->perf_counter1 = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE); + +#if MALI_TIMELINE_PROFILING_ENABLED + /* Report the counter values */ + _mali_osk_profiling_report_hw_counter(counter0_offset, job200->perf_counter0); + _mali_osk_profiling_report_hw_counter(counter1_offset, job200->perf_counter1); +#endif /* MALI_TIMELINE_PROFILING_ENABLED */ } #if defined(USING_MALI400_L2_CACHE) @@ -757,6 +806,23 @@ static int subsystem_mali200_irq_handler_bottom_half(struct mali_core_renderunit } +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_number), + job200->perf_counter0, job200->perf_counter1, + job200->user_input.perf_counter_src0 | (job200->user_input.perf_counter_src1 << 8) +#if defined(USING_MALI400_L2_CACHE) + | (job200->user_input.perf_counter_l2_src0 << 16) | (job200->user_input.perf_counter_l2_src1 << 24), + job200->perf_counter_l2_val0, job200->perf_counter_l2_val1 +#else + , 0, 0 +#endif + ); +#endif + + +#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,12 +831,17 @@ static int subsystem_mali200_irq_handler_bottom_half(struct mali_core_renderunit ((CORE_HANG_CHECK_TIMEOUT == core->state) && (current_tile_addr == job200->last_tile_list_addr)) ) { -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status */ +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status */ #endif /* 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? */ @@ -796,8 +867,8 @@ static int subsystem_mali200_irq_handler_bottom_half(struct mali_core_renderunit } else { -#if MALI_TIMELINE_PROFILING_ENABLED - _mali_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status */ +#if MALI_TIMELINE_PROFILING_ENABLED + _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_number), 0, 0, 0, 0, 0); /* add GP and L2 counters and return status */ #endif MALI_DEBUG_PRINT(1, ("Mali PP: Job: 0x%08x CRASH? Rawstat: 0x%x Tile_addr: 0x%x Status: 0x%x\n", @@ -814,6 +885,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 */ } } @@ -824,7 +898,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; @@ -872,7 +946,7 @@ static _mali_osk_errcode_t subsystem_mali200_get_new_job_from_user(struct mali_c job_priority_set(job, job200->user_input.priority); job_watchdog_set(job, job200->user_input.watchdog_msecs ); -#if MALI_TIMELINE_PROFILING_ENABLED +#if MALI_TIMELINE_PROFILING_ENABLED job200->pid = _mali_osk_get_pid(); job200->tid = _mali_osk_get_tid(); #endif @@ -954,6 +1028,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); } @@ -1026,6 +1110,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; @@ -1180,8 +1267,8 @@ _mali_osk_errcode_t malipp_signal_power_down( u32 core_num, mali_bool immediate_ #endif #if MALI_STATE_TRACKING -void mali200_subsystem_dump_state(void) +u32 mali200_subsystem_dump_state(char *buf, u32 size) { - mali_core_renderunit_dump_state(&subsystem_mali200); + return mali_core_renderunit_dump_state(&subsystem_mali200, buf, size); } #endif diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_common.h b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_common.h index 08516c56a9f..1a9459bff2b 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_common.h +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_common.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * Copyright (C) 2010 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_core.c b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_core.c index a40808bd2d8..f8ca4030fd8 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_core.c +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_core.c @@ -52,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 @@ -105,15 +106,15 @@ static struct mali_kernel_subsystem mali_subsystem_core = static struct mali_kernel_subsystem * subsystems[] = { - /* always initialize the hw subsystems first */ - /* always included */ - &mali_subsystem_memory, #if USING_MALI_PMM /* The PMM must be initialized before any cores - including L2 cache */ &mali_subsystem_pmm, #endif + /* always included */ + &mali_subsystem_memory, + /* The rendercore subsystem must be initialized before any subsystem based on the * rendercores is started e.g. mali_subsystem_mali200 and mali_subsystem_gp2 */ &mali_subsystem_rendercore, @@ -154,7 +155,7 @@ _mali_osk_errcode_t mali_kernel_constructor( void ) { _mali_osk_errcode_t err; - err = mali_platform_init(NULL); + err = mali_platform_init(); if (_MALI_OSK_ERR_OK != err) goto error1; err = _mali_osk_init(); @@ -177,7 +178,7 @@ error3: _mali_osk_term(); error2: MALI_PRINT(("Mali device driver init failed\n")); - if (_MALI_OSK_ERR_OK != mali_platform_deinit(NULL)) + if (_MALI_OSK_ERR_OK != mali_platform_deinit()) { MALI_PRINT(("Failed to deinit platform\n")); } @@ -191,10 +192,13 @@ void mali_kernel_destructor( void ) { MALI_DEBUG_PRINT(2, ("\n")); MALI_DEBUG_PRINT(2, ("Unloading Mali v%d device driver.\n",_MALI_API_VERSION)); +#if USING_MALI_PMM + malipmm_force_powerup(); +#endif terminate_subsystems(); /* subsystems are responsible for their registered resources */ _mali_osk_term(); - if (_MALI_OSK_ERR_OK != mali_platform_deinit(NULL)) + if (_MALI_OSK_ERR_OK != mali_platform_deinit()) { MALI_PRINT(("Failed to deinit platform\n")); } @@ -304,6 +308,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) @@ -341,6 +348,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) { @@ -406,25 +437,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); @@ -873,20 +886,26 @@ _mali_osk_errcode_t mali_core_signal_power_down( mali_pmm_core_id core, mali_boo #endif - #if MALI_STATE_TRACKING -void _mali_kernel_core_dump_state(void) +u32 _mali_kernel_core_dump_state(char* buf, u32 size) { - int i; + int i, n; + char *original_buf = buf; for (i = 0; i < SUBSYSTEMS_COUNT; ++i) - { + { if (NULL != subsystems[i]->dump_state) { - subsystems[i]->dump_state(); + n = subsystems[i]->dump_state(buf, size); + size -= n; + buf += n; } - } + } #if USING_MALI_PMM - mali_pmm_dump_os_thread_state(); + 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/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_core.h b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_core.h index 3819ecc5e1c..ced6b8fb118 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_core.h +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/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/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_descriptor_mapping.c b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_descriptor_mapping.c index 45c280edd6a..8b2a97d1545 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_descriptor_mapping.c +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_descriptor_mapping.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * Copyright (C) 2010 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_descriptor_mapping.h b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_descriptor_mapping.h index f626aa59455..745be9235e7 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_descriptor_mapping.h +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_descriptor_mapping.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * Copyright (C) 2010 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_l2_cache.c b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_l2_cache.c index fded5c93ab9..3c4c68d74bd 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_l2_cache.c +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_l2_cache.c @@ -495,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; @@ -502,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/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_mem_buddy.c b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_mem_buddy.c index 8277fd1e1c6..60f5ebd77ec 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_mem_buddy.c +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_mem_buddy.c @@ -24,6 +24,8 @@ #include "mali_osk_indir_mmap.h" #endif +#error Support for non-MMU builds is no longer supported and is planned for removal. + /** * Minimum memory allocation size */ @@ -55,7 +57,7 @@ typedef struct mali_memory_bank _mali_osk_list_t list; /* links multiple banks together */ _mali_osk_lock_t *lock; u32 base_addr; /* Mali seen address of bank */ - u32 cpu_usage_adjust; /* Adjustmen factor for what the CPU sees */ + u32 cpu_usage_adjust; /* Adjustment factor for what the CPU sees */ u32 size; /* the effective size */ u32 real_size; /* the real size of the bank, as given by to the subsystem */ int min_order; diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_mem_mmu.c b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_mem_mmu.c index 7a48e27ede7..46eaea8eea5 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_mem_mmu.c +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_mem_mmu.c @@ -18,6 +18,7 @@ #include "mali_kernel_mem_os.h" #include "mali_kernel_session_manager.h" #include "mali_kernel_core.h" +#include "mali_kernel_rendercore.h" #if defined USING_MALI400_L2_CACHE #include "mali_kernel_l2_cache.h" @@ -205,6 +206,7 @@ typedef struct mali_kernel_memory_mmu memory_session * active_session; /**< Active session, NULL if no session is active */ u32 usage_count; /**< Number of nested activations of the active session */ _mali_osk_list_t callbacks; /**< Callback registered for MMU idle notification */ + void *core; int in_page_fault_handler; @@ -329,10 +331,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 +378,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); @@ -533,7 +562,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); @@ -544,6 +573,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); } @@ -630,8 +660,9 @@ static _mali_osk_errcode_t mali_memory_core_session_begin(struct mali_session_da for (i = 0; i < MALI_MMU_PAGE_SIZE/4; i++) { /* mark each page table as not present */ - _mali_osk_mem_iowrite32(session_data->page_directory_mapped, sizeof(u32) * i, 0); + _mali_osk_mem_iowrite32_relaxed(session_data->page_directory_mapped, sizeof(u32) * i, 0); } + _mali_osk_write_mem_barrier(); /* page_table_mapped[] is already set to NULL by _mali_osk_calloc call */ @@ -813,8 +844,9 @@ static _mali_osk_errcode_t fill_page(mali_io_address mapping, u32 data) for(i = 0; i < MALI_MMU_PAGE_SIZE/4; i++) { - _mali_osk_mem_iowrite32( mapping, i * sizeof(u32), data); + _mali_osk_mem_iowrite32_relaxed( mapping, i * sizeof(u32), data); } + _mali_osk_mem_barrier(); MALI_SUCCESS; } @@ -887,7 +919,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")); @@ -992,7 +1024,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 */ @@ -1021,7 +1053,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")); @@ -1157,6 +1189,7 @@ static _mali_osk_errcode_t mali_kernel_memory_mmu_interrupt_handler_upper_half(v { mali_kernel_memory_mmu * mmu; u32 int_stat; + mali_core_renderunit *core; if (mali_benchmark) MALI_SUCCESS; @@ -1164,15 +1197,19 @@ static _mali_osk_errcode_t mali_kernel_memory_mmu_interrupt_handler_upper_half(v MALI_DEBUG_ASSERT_POINTER(mmu); + core = (mali_core_renderunit *)mmu->core; + if(core && (CORE_OFF == core->state)) + { + MALI_SUCCESS; + } + /* check if it was our device which caused the interrupt (we could be sharing the IRQ line) */ int_stat = mali_mmu_register_read(mmu, MALI_MMU_REGISTER_INT_STATUS); if (0 == int_stat) { - MALI_DEBUG_PRINT(5, ("Ignoring shared interrupt\n")); MALI_ERROR(_MALI_OSK_ERR_FAULT); /* no bits set, we are sharing the IRQ line and someone else caused the interrupt */ } - MALI_DEBUG_PRINT(1, ("mali_kernel_memory_mmu_interrupt_handler_upper_half\n")); mali_mmu_register_write(mmu, MALI_MMU_REGISTER_INT_MASK, 0); @@ -1180,13 +1217,10 @@ static _mali_osk_errcode_t mali_kernel_memory_mmu_interrupt_handler_upper_half(v if (int_stat & MALI_MMU_INTERRUPT_PAGE_FAULT) { - MALI_PRINT(("Page fault on %s\n", mmu->description)); - _mali_osk_irq_schedulework(mmu->irq); } if (int_stat & MALI_MMU_INTERRUPT_READ_BUS_ERROR) { - MALI_PRINT(("Bus read error on %s\n", mmu->description)); /* clear interrupt flag */ mali_mmu_register_write(mmu, MALI_MMU_REGISTER_INT_CLEAR, MALI_MMU_INTERRUPT_READ_BUS_ERROR); /* reenable it */ @@ -1219,6 +1253,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); @@ -1239,16 +1276,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); @@ -1258,6 +1302,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; @@ -1273,10 +1412,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); } @@ -1302,6 +1441,7 @@ static void mali_kernel_memory_mmu_interrupt_handler_bottom_half(void * data) { mali_kernel_memory_mmu * mmu; u32 raw, fault_address, status; + mali_core_renderunit *core; if (NULL == data) { @@ -1310,11 +1450,19 @@ static void mali_kernel_memory_mmu_interrupt_handler_bottom_half(void * data) } mmu = (mali_kernel_memory_mmu*)data; - MALI_DEBUG_PRINT(4, ("Locking subsystems\n")); /* lock all subsystems */ _mali_kernel_core_broadcast_subsystem_message(MMU_KILL_STEP0_LOCK_SUBSYSTEM, (u32)mmu); + /* Pointer to core holding this MMU */ + core = (mali_core_renderunit *)mmu->core; + + if(CORE_OFF == core->state) + { + _mali_kernel_core_broadcast_subsystem_message(MMU_KILL_STEP4_UNLOCK_SUBSYSTEM, (u32)mmu); + return; + } + raw = mali_mmu_register_read(mmu, MALI_MMU_REGISTER_INT_RAWSTAT); status = mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS); @@ -1404,7 +1552,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) { @@ -1575,6 +1722,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; @@ -1594,14 +1742,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")); @@ -1629,7 +1782,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; @@ -1768,7 +1927,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; @@ -1781,13 +1940,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")); @@ -1815,7 +1979,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; @@ -1870,6 +2040,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) @@ -1941,7 +2113,14 @@ _mali_osk_errcode_t mali_mmu_get_table_page(u32 *table_page, mali_io_address *ma _mali_osk_set_nonatomic_bit(0, alloc->usage_map); - _mali_osk_list_add(&alloc->list, &page_table_cache.partial); + if (alloc->num_pages > 1) + { + _mali_osk_list_add(&alloc->list, &page_table_cache.partial); + } + else + { + _mali_osk_list_add(&alloc->list, &page_table_cache.full); + } _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); *table_page = alloc->pages.phys_base; /* return the first page */ @@ -2001,8 +2180,21 @@ void mali_mmu_release_table_page(u32 pa) _mali_osk_memset((void*)( ((u32)alloc->pages.mapping) + (pa - start) ), 0, MALI_MMU_PAGE_SIZE); - /* transfer to partial list */ - _mali_osk_list_move(&alloc->list, &page_table_cache.partial); + + if (0 == alloc->usage_count) + { + /* empty, release whole page alloc */ + _mali_osk_list_del(&alloc->list); + alloc->pages.release(&alloc->pages); + _mali_osk_free(alloc->usage_map); + _mali_osk_free(alloc); + } + else + { + /* transfer to partial list */ + _mali_osk_list_move(&alloc->list, &page_table_cache.partial); + } + _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); MALI_DEBUG_PRINT(4, ("(full list)Released table page 0x%08X to the cache\n", pa)); return; @@ -2014,6 +2206,17 @@ void mali_mmu_release_table_page(u32 pa) _mali_osk_lock_signal(page_table_cache.lock, _MALI_OSK_LOCKMODE_RW); } +void mali_memory_core_mmu_owner(void *core, void *mmu_ptr) +{ + mali_kernel_memory_mmu *mmu; + + MALI_DEBUG_ASSERT_POINTER(mmu_ptr); + MALI_DEBUG_ASSERT_POINTER(core); + + mmu = (mali_kernel_memory_mmu *)mmu_ptr; + mmu->core = core; +} + void* mali_memory_core_mmu_lookup(u32 id) { mali_kernel_memory_mmu * mmu, * temp_mmu; @@ -2030,24 +2233,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) @@ -2517,8 +2706,9 @@ static _mali_osk_errcode_t mali_address_manager_map(mali_memory_allocation * des for ( ; mali_address < mali_address_end; mali_address += MALI_MMU_PAGE_SIZE, current_phys_addr += MALI_MMU_PAGE_SIZE) { MALI_DEBUG_ASSERT_POINTER(session_data->page_entries_mapped[MALI_MMU_PDE_ENTRY(mali_address)]); - _mali_osk_mem_iowrite32(session_data->page_entries_mapped[MALI_MMU_PDE_ENTRY(mali_address)], MALI_MMU_PTE_ENTRY(mali_address) * sizeof(u32), current_phys_addr | MALI_MMU_FLAGS_WRITE_PERMISSION | MALI_MMU_FLAGS_READ_PERMISSION | MALI_MMU_FLAGS_PRESENT); + _mali_osk_mem_iowrite32_relaxed(session_data->page_entries_mapped[MALI_MMU_PDE_ENTRY(mali_address)], MALI_MMU_PTE_ENTRY(mali_address) * sizeof(u32), current_phys_addr | MALI_MMU_FLAGS_WRITE_PERMISSION | MALI_MMU_FLAGS_READ_PERMISSION | MALI_MMU_FLAGS_PRESENT); } + _mali_osk_write_mem_barrier(); #if defined USING_MALI400_L2_CACHE if (1 == has_active_mmus) @@ -2574,7 +2764,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)) { @@ -2587,12 +2777,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); } @@ -2618,7 +2805,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; @@ -2641,24 +2828,34 @@ 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; - + u32 status; + status = mali_mmu_register_read(mmu, MALI_MMU_REGISTER_STATUS); + if ( MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE == (status & MALI_MMU_STATUS_BIT_PAGE_FAULT_ACTIVE) ) { + MALI_DEBUG_PRINT(2, ("Stopped stall attempt for mmu with id %d since it is in page fault mode.\n", mmu->id)); + continue; + } _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 */ @@ -2671,10 +2868,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 */ @@ -2682,6 +2881,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); @@ -2695,20 +2895,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 */ @@ -2922,3 +3136,8 @@ _mali_osk_errcode_t _mali_ukk_free_big_block( _mali_uk_free_big_block_s *args ) MALI_IGNORE( args ); return _MALI_OSK_ERR_FAULT; } + +u32 _mali_ukk_report_memory_usage(void) +{ + return mali_allocation_engine_memory_usage(physical_memory_allocators); +} diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_mem_mmu.h b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_mem_mmu.h index a199fd66b5a..98610803978 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_mem_mmu.h +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_mem_mmu.h @@ -21,6 +21,15 @@ void* mali_memory_core_mmu_lookup(u32 id); /** + * Set the core pointer of MMU to core owner of MMU + * + * @param core Core holding this MMU + * @param mmu_ptr The MMU whose core pointer needs set to core holding the MMU + * + */ +void mali_memory_core_mmu_owner(void *core, void *mmu_ptr); + +/** * Activate a user session with its address space on the given MMU. * If the session can't be activated due to that the MMU is busy and * a callback pointer is given, the callback will be called once the MMU becomes idle. diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_mem_os.c b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_mem_os.c index 845de935ec9..65958576c7a 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_mem_os.c +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_mem_os.c @@ -44,6 +44,7 @@ static mali_physical_memory_allocation_result os_allocator_allocate_page_table_b static void os_allocator_release(void * ctx, void * handle); static void os_allocator_page_table_block_release( mali_page_table_block *page_table_block ); static void os_allocator_destroy(mali_physical_memory_allocator * allocator); +static u32 os_allocator_stat(mali_physical_memory_allocator * allocator); mali_physical_memory_allocator * mali_os_allocator_create(u32 max_allocation, u32 cpu_usage_adjust, const char *name) { @@ -70,6 +71,7 @@ mali_physical_memory_allocator * mali_os_allocator_create(u32 max_allocation, u3 allocator->allocate = os_allocator_allocate; allocator->allocate_page_table_block = os_allocator_allocate_page_table_block; allocator->destroy = os_allocator_destroy; + allocator->stat = os_allocator_stat; allocator->ctx = info; allocator->name = name; @@ -83,6 +85,13 @@ mali_physical_memory_allocator * mali_os_allocator_create(u32 max_allocation, u3 return NULL; } +static u32 os_allocator_stat(mali_physical_memory_allocator * allocator) +{ + os_allocator * info; + info = (os_allocator*)allocator->ctx; + return info->num_pages_allocated * _MALI_OSK_MALI_PAGE_SIZE; +} + static void os_allocator_destroy(mali_physical_memory_allocator * allocator) { os_allocator * info; @@ -158,6 +167,9 @@ static mali_physical_memory_allocation_result os_allocator_allocate(void* ctx, m *offset += _MALI_OSK_CPU_PAGE_SIZE; } + if (left) MALI_PRINT(("Out of memory. Mali memory allocated: %d kB Configured maximum OS memory usage: %d kB\n", + (info->num_pages_allocated * _MALI_OSK_CPU_PAGE_SIZE)/1024, (info->num_pages_max* _MALI_OSK_CPU_PAGE_SIZE)/1024)); + /* Loop termination; decide on result */ if (pages_allocated) { @@ -167,7 +179,7 @@ static mali_physical_memory_allocation_result os_allocator_allocate(void* ctx, m /* 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. */ _mali_osk_cache_ensure_uncached_range_flushed( (void *)descriptor, allocation->offset_start, pages_allocated *_MALI_OSK_CPU_PAGE_SIZE ); allocation->num_pages = pages_allocated; @@ -231,10 +243,9 @@ static void os_allocator_release(void * ctx, void * handle) static mali_physical_memory_allocation_result os_allocator_allocate_page_table_block(void * ctx, mali_page_table_block * block) { - const int allocation_order = 6; /* _MALI_OSK_CPU_PAGE_SIZE << 6 */ - void *virt; - const u32 pages_to_allocate = 1 << allocation_order; - const u32 size = _MALI_OSK_CPU_PAGE_SIZE << allocation_order; + int allocation_order = 6; /* _MALI_OSK_CPU_PAGE_SIZE << 6 */ + void *virt = NULL; + u32 size = _MALI_OSK_CPU_PAGE_SIZE << allocation_order; os_allocator * info; u32 cpu_phys_base; @@ -245,22 +256,48 @@ static mali_physical_memory_allocation_result os_allocator_allocate_page_table_b /* Ensure we don't allocate more than we're supposed to from the ctx */ if (_MALI_OSK_ERR_OK != _mali_osk_lock_wait(info->mutex, _MALI_OSK_LOCKMODE_RW)) return MALI_MEM_ALLOC_INTERNAL_FAILURE; - if ( (info->num_pages_allocated + pages_to_allocate > info->num_pages_max) && _mali_osk_mem_check_allocated(info->num_pages_max * _MALI_OSK_CPU_PAGE_SIZE) ) + /* if the number of pages to be requested lead to exceeding the memory + * limit in info->num_pages_max, reduce the size that is to be requested. */ + while ( (info->num_pages_allocated + (1 << allocation_order) > info->num_pages_max) + && _mali_osk_mem_check_allocated(info->num_pages_max * _MALI_OSK_CPU_PAGE_SIZE) ) { - /* return OOM */ - _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); - return MALI_MEM_ALLOC_NONE; + if ( allocation_order > 0 ) { + --allocation_order; + } else { + /* return OOM */ + _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); + return MALI_MEM_ALLOC_NONE; + } } - virt = _mali_osk_mem_allocioregion( &cpu_phys_base, size ); + /* try to allocate 2^(allocation_order) pages, if that fails, try + * allocation_order-1 to allocation_order 0 (inclusive) */ + while ( allocation_order >= 0 ) + { + size = _MALI_OSK_CPU_PAGE_SIZE << allocation_order; + virt = _mali_osk_mem_allocioregion( &cpu_phys_base, size ); + + if (NULL != virt) break; + + --allocation_order; + } if ( NULL == virt ) { + MALI_DEBUG_PRINT(1, ("Failed to allocate consistent memory. Is CONSISTENT_DMA_SIZE set too low?\n")); /* return OOM */ _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); return MALI_MEM_ALLOC_NONE; } + MALI_DEBUG_PRINT(5, ("os_allocator_allocate_page_table_block: Allocation of order %i succeeded\n", + allocation_order)); + + /* we now know the size of the allocation since we know for what + * allocation_order the allocation succeeded */ + size = _MALI_OSK_CPU_PAGE_SIZE << allocation_order; + + block->release = os_allocator_page_table_block_release; block->ctx = ctx; block->handle = (void*)allocation_order; @@ -268,7 +305,7 @@ static mali_physical_memory_allocation_result os_allocator_allocate_page_table_b block->phys_base = cpu_phys_base - info->cpu_usage_adjust; block->mapping = virt; - info->num_pages_allocated += pages_to_allocate; + info->num_pages_allocated += (1 << allocation_order); _mali_osk_lock_signal(info->mutex, _MALI_OSK_LOCKMODE_RW); diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_mem_os.h b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_mem_os.h index ff49f8a816a..0946169f79d 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_mem_os.h +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_mem_os.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * Copyright (C) 2010 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_memory_engine.c b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_memory_engine.c index 3b4ace05f01..f6860c78a0b 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_memory_engine.c +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_memory_engine.c @@ -123,7 +123,7 @@ _mali_osk_errcode_t mali_allocation_engine_allocate_memory(mali_allocation_engin } } - MALI_DEBUG_PRINT(3, ("Non-fatal OOM, have to cleanup, stopped at offset %d for size %d\n", offset, descriptor->size)); + MALI_PRINT(("Memory allocate failed, could not allocate size %d kB.\n", descriptor->size/1024)); /* allocation failure, start cleanup */ /* loop over any potential partial allocations */ @@ -346,3 +346,18 @@ void mali_allocation_engine_report_allocators( mali_physical_memory_allocator * } } + +u32 mali_allocation_engine_memory_usage(mali_physical_memory_allocator *allocator) +{ + u32 sum = 0; + while(NULL != allocator) + { + /* Only count allocators that have set up a stat function. */ + if(allocator->stat) + sum += allocator->stat(allocator); + + allocator = allocator->next; + } + + return sum; +} diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_memory_engine.h b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_memory_engine.h index 80a2b4bb3a7..1ef7a089e95 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_memory_engine.h +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_memory_engine.h @@ -47,7 +47,7 @@ typedef enum /** * Supplying this 'magic' physical address requests that the OS allocate the - * physical address at page commit time, rather than commiting a specific page + * physical address at page commit time, rather than committing a specific page */ #define MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC ((u32)(-1)) @@ -78,6 +78,7 @@ typedef struct mali_physical_memory_allocator mali_physical_memory_allocation_result (*allocate)(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info); mali_physical_memory_allocation_result (*allocate_page_table_block)(void * ctx, mali_page_table_block * block); /* MALI_MEM_ALLOC_PARTIAL not allowed */ void (*destroy)(struct mali_physical_memory_allocator * allocator); + u32 (*stat)(struct mali_physical_memory_allocator * allocator); void * ctx; const char * name; /**< Descriptive name for use in mali_allocation_engine_report_allocators, or NULL */ u32 alloc_order; /**< Order in which the allocations should happen */ @@ -96,7 +97,7 @@ typedef struct mali_kernel_mem_address_manager * @param[in] off Offset from the start of range * @param[in,out] phys_addr A pointer to the physical address of the start of the * physical block. When *phys_addr == MALI_MEMORY_ALLOCATION_OS_ALLOCATED_PHYSADDR_MAGIC - * is used, this requests the function must allocate the physical page + * is used, this requests the function to allocate the physical page * itself, and return it through the pointer provided. * @param[in] size Length in bytes of the physical block * @return _MALI_OSK_ERR_OK on success. @@ -142,4 +143,6 @@ int mali_allocation_engine_allocate_page_tables(mali_allocation_engine, mali_pag void mali_allocation_engine_report_allocators(mali_physical_memory_allocator * physical_provider); +u32 mali_allocation_engine_memory_usage(mali_physical_memory_allocator *allocator); + #endif /* __MALI_KERNEL_MEMORY_ENGINE_H__ */ diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_profiling.c b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_profiling.c deleted file mode 100644 index 07bb894b1b4..00000000000 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_profiling.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - * 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. - */ - -#include "mali_kernel_common.h" -#include "mali_osk.h" -#include "mali_osk_mali.h" -#include "mali_ukk.h" -#include "mali_timestamp.h" - -#define MALI_PROFILING_MAX_BUFFER_ENTRIES 1048576 - -typedef struct mali_profiling_entry -{ - u64 timestamp; - u32 event_id; - u32 data[5]; -} mali_profiling_entry; - - -typedef enum mali_profiling_state -{ - MALI_PROFILING_STATE_UNINITIALIZED, - MALI_PROFILING_STATE_IDLE, - MALI_PROFILING_STATE_RUNNING, - MALI_PROFILING_STATE_RETURN, -} mali_profiling_state; - - -static _mali_osk_lock_t *lock = NULL; -static mali_profiling_state prof_state = MALI_PROFILING_STATE_UNINITIALIZED; -static mali_profiling_entry* profile_entries = NULL; -static u32 profile_entry_count = 0; -static _mali_osk_atomic_t profile_insert_index; -static _mali_osk_atomic_t profile_entries_written; - - -_mali_osk_errcode_t _mali_profiling_init(void) -{ - profile_entries = NULL; - profile_entry_count = 0; - _mali_osk_atomic_init(&profile_insert_index, 0); - _mali_osk_atomic_init(&profile_entries_written, 0); - - lock = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, 0 ); - if (NULL == lock) - { - return _MALI_OSK_ERR_FAULT; - } - - prof_state = MALI_PROFILING_STATE_IDLE; - - return _MALI_OSK_ERR_OK; -} - -void _mali_profiling_term(void) -{ - prof_state = MALI_PROFILING_STATE_UNINITIALIZED; - - /* wait for all elements to be completely inserted into array */ - while (_mali_osk_atomic_read(&profile_insert_index) != _mali_osk_atomic_read(&profile_entries_written)) - { - /* do nothing */; - } - - if (NULL != profile_entries) - { - _mali_osk_free(profile_entries); - profile_entries = NULL; - } - - if (NULL != lock) - { - _mali_osk_lock_term(lock); - lock = NULL; - } -} - -inline _mali_osk_errcode_t _mali_profiling_add_event(u32 event_id, u32 data0, u32 data1, u32 data2, u32 data3, u32 data4) -{ - u32 cur_index = _mali_osk_atomic_inc_return(&profile_insert_index) - 1; - - if (prof_state != MALI_PROFILING_STATE_RUNNING || cur_index >= profile_entry_count) - { - /* - * Not in recording mode, or buffer is full - * Decrement index again, and early out - */ - _mali_osk_atomic_dec(&profile_insert_index); - return _MALI_OSK_ERR_FAULT; - } - - profile_entries[cur_index].timestamp = _mali_timestamp_get(); - profile_entries[cur_index].event_id = event_id; - profile_entries[cur_index].data[0] = data0; - profile_entries[cur_index].data[1] = data1; - profile_entries[cur_index].data[2] = data2; - profile_entries[cur_index].data[3] = data3; - profile_entries[cur_index].data[4] = data4; - - _mali_osk_atomic_inc(&profile_entries_written); - - return _MALI_OSK_ERR_OK; -} - - -_mali_osk_errcode_t _mali_ukk_profiling_start(_mali_uk_profiling_start_s *args) -{ - _mali_osk_errcode_t ret; - - _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); - - if (prof_state != MALI_PROFILING_STATE_IDLE) - { - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ - } - - if (args->limit > MALI_PROFILING_MAX_BUFFER_ENTRIES) - { - args->limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; - } - - profile_entries = _mali_osk_malloc(args->limit * sizeof(mali_profiling_entry)); - profile_entry_count = args->limit; - if (NULL == profile_entries) - { - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_NOMEM; - } - - ret = _mali_timestamp_reset(); - - if (ret == _MALI_OSK_ERR_OK) - { - prof_state = MALI_PROFILING_STATE_RUNNING; - } - else - { - _mali_osk_free(profile_entries); - profile_entries = NULL; - } - - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return ret; -} - -_mali_osk_errcode_t _mali_ukk_profiling_add_event(_mali_uk_profiling_add_event_s *args) -{ - /* Always add process and thread identificator in the first two data elements for events from user space */ - return _mali_profiling_add_event(args->event_id, _mali_osk_get_pid(), _mali_osk_get_tid(), args->data[2], args->data[3], args->data[4]); -} - -_mali_osk_errcode_t _mali_ukk_profiling_stop(_mali_uk_profiling_stop_s *args) -{ - _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); - - if (prof_state != MALI_PROFILING_STATE_RUNNING) - { - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ - } - - /* go into return state (user to retreive events), no more events will be added after this */ - prof_state = MALI_PROFILING_STATE_RETURN; - - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - - /* wait for all elements to be completely inserted into array */ - while (_mali_osk_atomic_read(&profile_insert_index) != _mali_osk_atomic_read(&profile_entries_written)) - { - /* do nothing */; - } - - args->count = _mali_osk_atomic_read(&profile_insert_index); - - return _MALI_OSK_ERR_OK; -} - - -_mali_osk_errcode_t _mali_ukk_profiling_get_event(_mali_uk_profiling_get_event_s *args) -{ - u32 index = args->index; - - _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); - - if (prof_state != MALI_PROFILING_STATE_RETURN) - { - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ - } - - if (index >= _mali_osk_atomic_read(&profile_entries_written)) - { - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_FAULT; - } - - args->timestamp = profile_entries[index].timestamp; - args->event_id = profile_entries[index].event_id; - args->data[0] = profile_entries[index].data[0]; - args->data[1] = profile_entries[index].data[1]; - args->data[2] = profile_entries[index].data[2]; - args->data[3] = profile_entries[index].data[3]; - args->data[4] = profile_entries[index].data[4]; - - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_OK; -} - -_mali_osk_errcode_t _mali_ukk_profiling_clear(_mali_uk_profiling_clear_s *args) -{ - _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW); - - if (prof_state != MALI_PROFILING_STATE_RETURN) - { - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */ - } - - prof_state = MALI_PROFILING_STATE_IDLE; - profile_entry_count = 0; - _mali_osk_atomic_init(&profile_insert_index, 0); - _mali_osk_atomic_init(&profile_entries_written, 0); - if (NULL != profile_entries) - { - _mali_osk_free(profile_entries); - profile_entries = NULL; - } - - _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW); - return _MALI_OSK_ERR_OK; -} - diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_profiling.h b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_profiling.h deleted file mode 100644 index 5d3aa6eb841..00000000000 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_profiling.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. - * - * This program is free software and is provided to you under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. - * - * A copy of the licence is included with the program, and can also be obtained from Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef __MALI_KERNEL_PROFILING_H__ -#define __MALI_KERNEL_PROFILING_H__ - -#if MALI_TIMELINE_PROFILING_ENABLED - -#include <../../../include/cinstr/mali_cinstr_profiling_events_m200.h> - -/** - * Initialize the profiling module. - * @return _MALI_OSK_ERR_OK on success, otherwise failure. - */ -_mali_osk_errcode_t _mali_profiling_init(void); - -/* - * Terminate the profiling module. - */ -void _mali_profiling_term(void); - -/** - * Add an profiling event - * - * @param event_id The event identificator. - * @param data0 - First data parameter, depending on event_id specified. - * @param data1 - Second data parameter, depending on event_id specified. - * @param data2 - Third data parameter, depending on event_id specified. - * @param data3 - Fourth data parameter, depending on event_id specified. - * @param data4 - Fifth data parameter, depending on event_id specified. - * @return _MALI_OSK_ERR_OK on success, otherwise failure. - */ -_mali_osk_errcode_t _mali_profiling_add_event(u32 event_id, u32 data0, u32 data1, u32 data2, u32 data3, u32 data4); - -#endif /* MALI_TIMELINE_PROFILING_ENABLED */ - -#endif /* __MALI_KERNEL_PROFILING_H__ */ - - diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_rendercore.c b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_rendercore.c index 1db8f3ad5ab..f06b17bcb31 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_rendercore.c +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_rendercore.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. @@ -11,7 +11,6 @@ #include "mali_kernel_common.h" #include "mali_kernel_core.h" #include "mali_osk.h" -#include "mali_kernel_pp.h" #include "mali_kernel_subsystem.h" #include "mali_kernel_rendercore.h" #include "mali_osk_list.h" @@ -19,7 +18,7 @@ #include "mali_kernel_utilization.h" #endif #if MALI_TIMELINE_PROFILING_ENABLED -#include "mali_kernel_profiling.h" +#include "mali_osk_profiling.h" #endif #if USING_MMU #include "mali_kernel_mem_mmu.h" @@ -42,6 +41,10 @@ int mali_hang_check_interval = HANG_CHECK_MSECS_DEFAULT; int mali_max_job_runtime = WATCHDOG_MSECS_DEFAULT; +#if MALI_TIMELINE_PROFILING_ENABLED +int mali_boot_profiling = 0; +#endif + /* Subsystem entrypoints: */ static _mali_osk_errcode_t rendercore_subsystem_startup(mali_kernel_subsystem_identifier id); static void rendercore_subsystem_terminate(mali_kernel_subsystem_identifier id); @@ -157,7 +160,7 @@ static _mali_osk_errcode_t rendercore_subsystem_startup(mali_kernel_subsystem_id #endif #if MALI_TIMELINE_PROFILING_ENABLED - if (_mali_profiling_init() != _MALI_OSK_ERR_OK) + if (_mali_osk_profiling_init(mali_boot_profiling ? MALI_TRUE : MALI_FALSE) != _MALI_OSK_ERR_OK) { /* No biggie if we wheren't able to initialize the profiling */ MALI_PRINT_ERROR(("Rendercore: Failed to initialize profiling, feature will be unavailable\n")) ; @@ -187,7 +190,7 @@ static void rendercore_subsystem_terminate(mali_kernel_subsystem_identifier id) MALI_DEBUG_ASSERT_POINTER( rendercores_global_mutex ); #if MALI_TIMELINE_PROFILING_ENABLED - _mali_profiling_term(); + _mali_osk_profiling_term(); #endif #if MALI_GPU_UTILIZATION @@ -258,104 +261,6 @@ static void rendercore_subsystem_broadcast_notification(mali_core_notification_m * Functions inherited by the subsystems that extend the ''rendercore''. */ -u32 mali_core_renderunit_register_read(mali_core_renderunit *core, u32 relative_address) -{ - u32 read_val; - - #if USING_MALI_PMM - if( core->state == CORE_OFF ) - { - MALI_PRINT_ERROR(("Core is OFF during read: Core:%s Addr:0x%04X\n", - core->description,relative_address)); - return 0xDEADBEEF; - } - #endif - - MALI_DEBUG_ASSERT((relative_address & 0x03) == 0); - - if (mali_benchmark) return 0; - - if (relative_address >= core->size) - { - MALI_PRINT_ERROR(("Trying to read from illegal register: 0x%04x in core: %s\n", - relative_address, core->description)); - return 0xDEADBEEF; - } - - read_val = _mali_osk_mem_ioread32(core->registers_mapped, relative_address); - - MALI_DEBUG_PRINT(6, ("Core: renderunit_register_read: Core:%s Addr:0x%04X Val:0x%08x\n", - core->description,relative_address, read_val)); - - return read_val; -} - -void mali_core_renderunit_register_read_array(mali_core_renderunit *core, - u32 relative_address, - u32 * result_array, - u32 nr_of_regs - ) -{ - /* NOTE Do not use burst reads against the registers */ - - u32 i; - - for(i=0; i<nr_of_regs; ++i) - { - result_array[i] = mali_core_renderunit_register_read(core, relative_address + i*4); - } - - MALI_DEBUG_PRINT(6, ("Core: renderunit_register_read_array: Core:%s Addr:0x%04X Nr_regs: %u\n", - core->description,relative_address, nr_of_regs)); -} - -void mali_core_renderunit_register_write(mali_core_renderunit *core, u32 relative_address, u32 new_val) -{ - #if USING_MALI_PMM - if( core->state == CORE_OFF ) - { - MALI_PRINT_ERROR(("Core is OFF during write: Core:%s Addr:0x%04X Val:0x%08x\n", - core->description,relative_address, new_val)); - return; - } - #endif - - MALI_DEBUG_ASSERT((relative_address & 0x03) == 0); - - if (mali_benchmark) return; - - if (relative_address >= core->size) - { - MALI_PRINT_ERROR(("Trying to write to illegal register: 0x%04x in core: %s", - relative_address, core->description)); - return; - } - - MALI_DEBUG_PRINT(6, ("mali_core_renderunit_register_write: Core:%s Addr:0x%04X Val:0x%08x\n", - core->description,relative_address, new_val)); - - _mali_osk_mem_iowrite32(core->registers_mapped, relative_address, new_val); -} - - -void mali_core_renderunit_register_write_array(mali_core_renderunit *core, - u32 relative_address, - u32 * source_array, - u32 nr_of_regs) -{ - - u32 i; - MALI_DEBUG_PRINT(6, ("Core: renderunit_register_write_array: Core:%s Addr:0x%04X Nr_regs: %u\n", - core->description,relative_address, nr_of_regs)); - - /* Do not use burst writes against the registers */ - - for( i = 0; i< nr_of_regs; i++) - { - mali_core_renderunit_register_write(core, relative_address + i*4, source_array[i]); - } -} - void mali_core_renderunit_timeout_function_hang_detection(void *arg) { mali_bool action = MALI_FALSE; @@ -364,8 +269,8 @@ void mali_core_renderunit_timeout_function_hang_detection(void *arg) core = (mali_core_renderunit *) arg; if( !core ) return; - /* if NOT idle OR has TIMED_OUT */ - if ( !((CORE_WATCHDOG_TIMEOUT == core->state ) || (CORE_IDLE== core->state)) ) + /* if NOT idle OR NOT powered off OR has TIMED_OUT */ + if ( !((CORE_WATCHDOG_TIMEOUT == core->state ) || (CORE_IDLE== core->state) || (CORE_OFF == core->state)) ) { core->state = CORE_HANG_CHECK_TIMEOUT; action = MALI_TRUE; @@ -615,6 +520,7 @@ void mali_core_subsystem_attach_mmu(mali_core_subsystem* subsys) core = mali_core_renderunit_get_mali_core_nr(subsys,i); if ( NULL==core ) break; core->mmu = mali_memory_core_mmu_lookup(core->mmu_id); + mali_memory_core_mmu_owner(core,core->mmu); MALI_DEBUG_PRINT(2, ("Attach mmu: 0x%x to core: %s in subsystem: %s\n", core->mmu, core->description, subsys->name)); } @@ -871,11 +777,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) @@ -1067,15 +973,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 ); @@ -1098,6 +996,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 */ @@ -1398,6 +1305,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) ) ; @@ -1440,7 +1354,6 @@ void mali_core_session_close(mali_core_session * session) core = _MALI_OSK_LIST_ENTRY(session->renderunits_working_head.next, mali_core_renderunit, list); MALI_DEBUG_PRINT(3, ("Core: session_close: Core was working: %s\n", core->description )) ; mali_core_renderunit_detach_job_from_core(core, SUBSYSTEM_RESCHEDULE, JOB_STATUS_END_SHUTDOWN ); - break; } _MALI_OSK_INIT_LIST_HEAD(&session->renderunits_working_head); /* Not necessary - we will _mali_osk_free session*/ @@ -1749,6 +1662,11 @@ static _mali_osk_errcode_t mali_core_irq_handler_upper_half (void * data) core = (mali_core_renderunit * )data; + if(core && (CORE_OFF == core->state)) + { + MALI_SUCCESS; + } + if ( (NULL == core) || (NULL == core->subsystem) || (NULL == core->subsystem->irq_handler_upper_half) ) @@ -1785,7 +1703,7 @@ static void mali_core_irq_handler_bottom_half ( void *data ) MALI_CHECK_SUBSYSTEM(subsystem); MALI_CORE_SUBSYSTEM_MUTEX_GRAB( subsystem ); - if ( CORE_IDLE == core->state ) goto end_function; + if ( CORE_IDLE == core->state || CORE_OFF == core->state ) goto end_function; MALI_DEBUG_PRINT(5, ("IRQ: handling irq from core %s\n", core->description )) ; @@ -1856,7 +1774,7 @@ _mali_osk_errcode_t mali_core_subsystem_signal_power_down(mali_core_subsystem *s { /* Couldn't find the core */ MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys); - MALI_DEBUG_PRINT( 5, ("Core: Failed to find core to power down\n") ); + MALI_DEBUG_PRINT( 1, ("Core: Failed to find core to power down\n") ); MALI_ERROR(_MALI_OSK_ERR_FAULT); } else if ( core->state != CORE_IDLE ) @@ -1896,7 +1814,7 @@ _mali_osk_errcode_t mali_core_subsystem_signal_power_up(mali_core_subsystem *sub { /* Couldn't find the core */ MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys); - MALI_DEBUG_PRINT( 5, ("Core: Failed to find core to power up\n") ); + MALI_DEBUG_PRINT( 1, ("Core: Failed to find core to power up\n") ); MALI_ERROR(_MALI_OSK_ERR_FAULT); } else if( core->state != CORE_OFF ) @@ -1904,7 +1822,7 @@ _mali_osk_errcode_t mali_core_subsystem_signal_power_up(mali_core_subsystem *sub /* This will usually happen because we are trying to cancel a pending power down */ core->pend_power_down = MALI_FALSE; MALI_CORE_SUBSYSTEM_MUTEX_RELEASE(subsys); - MALI_DEBUG_PRINT( 5, ("Core: No powered off core to power up (cancelled power down?)\n") ); + MALI_DEBUG_PRINT( 1, ("Core: No powered off core to power up (cancelled power down?)\n") ); MALI_ERROR(_MALI_OSK_ERR_BUSY); } @@ -1945,88 +1863,126 @@ _mali_osk_errcode_t mali_core_subsystem_signal_power_up(mali_core_subsystem *sub #endif /* USING_MALI_PMM */ #if MALI_STATE_TRACKING -void mali_core_renderunit_dump_state(mali_core_subsystem* subsystem) +u32 mali_core_renderunit_dump_state(mali_core_subsystem* subsystem, char *buf, u32 size) { - u32 i; + 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 ); - MALI_PRINT(("Subsystem;\n")); - MALI_PRINT((" Name: %s\n", subsystem->name)); + 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++) { - MALI_PRINT((" Core: #%u\n", subsystem->mali_core_array[i]->core_number)); - MALI_PRINT((" Description: %s\n", subsystem->mali_core_array[i]->description)); + 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: - MALI_PRINT((" State: CORE_IDLE\n")); + len += _mali_osk_snprintf(buf + len, size - len, " State: CORE_IDLE\n"); break; case CORE_WORKING: - MALI_PRINT((" State: CORE_WORKING\n")); + len += _mali_osk_snprintf(buf + len, size - len, " State: CORE_WORKING\n"); break; case CORE_WATCHDOG_TIMEOUT: - MALI_PRINT((" State: CORE_WATCHDOG_TIMEOUT\n")); + len += _mali_osk_snprintf(buf + len, size - len, " State: CORE_WATCHDOG_TIMEOUT\n"); break; case CORE_POLL: - MALI_PRINT((" State: CORE_POLL\n")); + len += _mali_osk_snprintf(buf + len, size - len, " State: CORE_POLL\n"); break; case CORE_HANG_CHECK_TIMEOUT: - MALI_PRINT((" State: CORE_HANG_CHECK_TIMEOUT\n")); + len += _mali_osk_snprintf(buf + len, size - len, " State: CORE_HANG_CHECK_TIMEOUT\n"); break; case CORE_OFF: - MALI_PRINT((" State: CORE_OFF\n")); + len += _mali_osk_snprintf(buf + len, size - len, " State: CORE_OFF\n"); break; default: - MALI_PRINT((" State: Unknown (0x%X)\n", subsystem->mali_core_array[i]->state)); + len += _mali_osk_snprintf(buf + len, size - len, " State: Unknown (0x%X)\n", + subsystem->mali_core_array[i]->state); break; } - MALI_PRINT((" Current job: 0x%x\n", (u32)(subsystem->mali_core_array[i]->current_job))); - MALI_PRINT((" Core version: 0x%x\n", subsystem->mali_core_array[i]->core_version)); + 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 - MALI_PRINT((" PMM id: 0x%x\n", subsystem->mali_core_array[i]->pmm_id)); - MALI_PRINT((" Power down requested: %s\n", subsystem->mali_core_array[i]->pend_power_down ? "TRUE" : "FALSE")); + 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 } - MALI_PRINT((" Cores on idle list:\n")); + 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) { - MALI_PRINT((" Core #%u\n", core->core_number)); + len += _mali_osk_snprintf(buf + len, size - len, " Core #%u\n", core->core_number); } - MALI_PRINT((" Cores on off list:\n")); + 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) { - MALI_PRINT((" Core #%u\n", core->core_number)); + len += _mali_osk_snprintf(buf + len, size - len, " Core #%u\n", core->core_number); } - MALI_PRINT((" Connected sessions:\n")); + 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) { - MALI_PRINT((" Session 0x%X:\n", (u32)session)); - MALI_PRINT((" Waiting job: 0x%X\n", (u32)session->job_waiting_to_run)); - MALI_PRINT((" Notification queue: %s\n", _mali_osk_notification_queue_is_empty(session->notification_queue) ? "EMPTY" : "NON-EMPTY")); - } - - MALI_PRINT((" Waiting sessions sum all priorities: %u\n", subsystem->awaiting_sessions_sum_all_priorities)); + 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++) { - MALI_PRINT((" 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, " 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) { - MALI_PRINT((" Session 0x%X:\n", (u32)session)); - MALI_PRINT((" Waiting job: 0x%X\n", (u32)session->job_waiting_to_run)); - MALI_PRINT((" Notification queue: %s\n", _mali_osk_notification_queue_is_empty(session->notification_queue) ? "EMPTY" : "NON-EMPTY")); + 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/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_rendercore.h b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_rendercore.h index 94bce94d4e1..c4a13796ba9 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_rendercore.h +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/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; /* @@ -309,11 +317,117 @@ typedef struct register_array_user if ( rendercores_global_mutex_owner != _mali_osk_get_tid() ) MALI_PRINT_ERROR(("Owner mismatch"));\ } while (0) +MALI_STATIC_INLINE _mali_osk_errcode_t mali_core_renderunit_register_rw_check(mali_core_renderunit *core, + u32 relative_address) +{ +#if USING_MALI_PMM + if( core->state == CORE_OFF ) + { + MALI_PRINT_ERROR(("Core is OFF during access: Core: %s Addr: 0x%04X\n", + core->description,relative_address)); + MALI_ERROR(_MALI_OSK_ERR_FAULT); + } +#endif + + MALI_DEBUG_ASSERT((relative_address & 0x03) == 0); + + if (mali_benchmark) MALI_ERROR(_MALI_OSK_ERR_FAULT); + + MALI_DEBUG_CODE(if (relative_address >= core->size) + { + MALI_PRINT_ERROR(("Trying to access illegal register: 0x%04x in core: %s", + relative_address, core->description)); + MALI_ERROR(_MALI_OSK_ERR_FAULT); + }) + + MALI_SUCCESS; +} -u32 mali_core_renderunit_register_read(struct mali_core_renderunit *core, u32 relative_address); -void mali_core_renderunit_register_read_array(struct mali_core_renderunit *core, u32 relative_address, u32 * result_array, u32 nr_of_regs); -void mali_core_renderunit_register_write(struct mali_core_renderunit *core, u32 relative_address, u32 new_val); -void mali_core_renderunit_register_write_array(struct mali_core_renderunit *core, u32 relative_address, u32 * write_array, u32 nr_of_regs); + +MALI_STATIC_INLINE u32 mali_core_renderunit_register_read(struct mali_core_renderunit *core, u32 relative_address) +{ + u32 read_val; + + if(_MALI_OSK_ERR_FAULT == mali_core_renderunit_register_rw_check(core, relative_address)) + return 0xDEADBEEF; + + read_val = _mali_osk_mem_ioread32(core->registers_mapped, relative_address); + + MALI_DEBUG_PRINT(6, ("Core: renderunit_register_read: Core:%s Addr:0x%04X Val:0x%08x\n", + core->description,relative_address, read_val)); + + return read_val; +} + +MALI_STATIC_INLINE void mali_core_renderunit_register_read_array(struct mali_core_renderunit *core, + u32 relative_address, + u32 * result_array, + u32 nr_of_regs) +{ + /* NOTE Do not use burst reads against the registers */ + u32 i; + + MALI_DEBUG_PRINT(6, ("Core: renderunit_register_read_array: Core:%s Addr:0x%04X Nr_regs: %u\n", + core->description,relative_address, nr_of_regs)); + + for(i=0; i<nr_of_regs; ++i) + { + result_array[i] = mali_core_renderunit_register_read(core, relative_address + i*4); + } +} + +/* + * Write to a core register, and bypass implied memory barriers. + * + * On some systems, _mali_osk_mem_iowrite32() implies a memory barrier. This + * can be a performance problem when doing many writes in sequence. + * + * When using this function, ensure proper barriers are put in palce. Most + * likely a _mali_osk_mem_barrier() is needed after all related writes are + * completed. + * + */ +MALI_STATIC_INLINE void mali_core_renderunit_register_write_relaxed(mali_core_renderunit *core, + u32 relative_address, + u32 new_val) +{ + if(_MALI_OSK_ERR_FAULT == mali_core_renderunit_register_rw_check(core, relative_address)) + return; + + MALI_DEBUG_PRINT(6, ("mali_core_renderunit_register_write_relaxed: Core:%s Addr:0x%04X Val:0x%08x\n", + core->description,relative_address, new_val)); + + _mali_osk_mem_iowrite32_relaxed(core->registers_mapped, relative_address, new_val); +} + +MALI_STATIC_INLINE void mali_core_renderunit_register_write(struct mali_core_renderunit *core, + u32 relative_address, + u32 new_val) +{ + MALI_DEBUG_PRINT(6, ("mali_core_renderunit_register_write: Core:%s Addr:0x%04X Val:0x%08x\n", + core->description,relative_address, new_val)); + + if(_MALI_OSK_ERR_FAULT == mali_core_renderunit_register_rw_check(core, relative_address)) + return; + + _mali_osk_mem_iowrite32(core->registers_mapped, relative_address, new_val); +} + +MALI_STATIC_INLINE void mali_core_renderunit_register_write_array(struct mali_core_renderunit *core, + u32 relative_address, + u32 * write_array, + u32 nr_of_regs) +{ + u32 i; + MALI_DEBUG_PRINT(6, ("Core: renderunit_register_write_array: Core:%s Addr:0x%04X Nr_regs: %u\n", + core->description,relative_address, nr_of_regs)); + + /* Do not use burst writes against the registers */ + for( i = 0; i< nr_of_regs; i++) + { + mali_core_renderunit_register_write_relaxed(core, relative_address + i*4, write_array[i]); + } +} _mali_osk_errcode_t mali_core_renderunit_init(struct mali_core_renderunit * core); void mali_core_renderunit_term(struct mali_core_renderunit * core); @@ -349,7 +463,7 @@ _mali_osk_errcode_t mali_core_subsystem_signal_power_up(mali_core_subsystem *sub #endif #if MALI_STATE_TRACKING -void mali_core_renderunit_dump_state(mali_core_subsystem* subsystem); +u32 mali_core_renderunit_dump_state(mali_core_subsystem* subsystem, char *buf, u32 size); #endif #endif /* __MALI_RENDERCORE_H__ */ diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_session_manager.h b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_session_manager.h index ce290d0c1c9..8cc41d7f937 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_session_manager.h +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_session_manager.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * Copyright (C) 2010 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_subsystem.h b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_subsystem.h index e8c6530668c..9efba566bd9 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_subsystem.h +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_kernel_subsystem.h @@ -74,7 +74,7 @@ typedef struct mali_kernel_subsystem #if MALI_STATE_TRACKING /** Dump the current state of the subsystem */ - void (*dump_state)(void); + u32 (*dump_state)(char *buf, u32 size); #endif } mali_kernel_subsystem; @@ -100,7 +100,7 @@ void _mali_kernel_core_broadcast_subsystem_message(mali_core_notification_messag /** * Tell all subsystems to dump their current state */ -void _mali_kernel_core_dump_state(void); +u32 _mali_kernel_core_dump_state(char *buf, u32 size); #endif diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_osk.h b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_osk.h index c35d90577a3..35737e68cb3 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_osk.h +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_osk.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. @@ -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 */ @@ -785,6 +795,10 @@ void _mali_osk_atomic_term( _mali_osk_atomic_t *atom ); * Returns a buffer capable of containing at least \a n elements of \a size * bytes each. The buffer is initialized to zero. * + * If there is a need for a bigger block of memory (16KB or bigger), then + * consider to use _mali_osk_vmalloc() instead, as this function might + * map down to a OS function with size limitations. + * * The buffer is suitably aligned for storage and subsequent access of every * type that the compiler supports. Therefore, the pointer to the start of the * buffer may be cast into any pointer type, and be subsequently accessed from @@ -807,6 +821,10 @@ void *_mali_osk_calloc( u32 n, u32 size ); * Returns a buffer capable of containing at least \a size bytes. The * contents of the buffer are undefined. * + * If there is a need for a bigger block of memory (16KB or bigger), then + * consider to use _mali_osk_vmalloc() instead, as this function might + * map down to a OS function with size limitations. + * * The buffer is suitably aligned for storage and subsequent access of every * type that the compiler supports. Therefore, the pointer to the start of the * buffer may be cast into any pointer type, and be subsequently accessed from @@ -840,6 +858,46 @@ void *_mali_osk_malloc( u32 size ); */ void _mali_osk_free( void *ptr ); +/** @brief Allocate memory. + * + * Returns a buffer capable of containing at least \a size bytes. The + * contents of the buffer are undefined. + * + * This function is potentially slower than _mali_osk_malloc() and _mali_osk_calloc(), + * but do support bigger sizes. + * + * The buffer is suitably aligned for storage and subsequent access of every + * type that the compiler supports. Therefore, the pointer to the start of the + * buffer may be cast into any pointer type, and be subsequently accessed from + * such a pointer, without loss of information. + * + * When the buffer is no longer in use, it must be freed with _mali_osk_free(). + * Failure to do so will cause a memory leak. + * + * @note Most toolchains supply memory allocation functions that meet the + * compiler's alignment requirements. + * + * Remember to free memory using _mali_osk_free(). + * @param size Number of bytes to allocate + * @return On success, the buffer allocated. NULL on failure. + */ +void *_mali_osk_valloc( u32 size ); + +/** @brief Free memory. + * + * Reclaims the buffer pointed to by the parameter \a ptr for the system. + * All memory returned from _mali_osk_valloc() must be freed before the + * application exits. Otherwise a memory leak will occur. + * + * Memory must be freed once. It is an error to free the same non-NULL pointer + * more than once. + * + * It is legal to free the NULL pointer. + * + * @param ptr Pointer to buffer to free + */ +void _mali_osk_vfree( void *ptr ); + /** @brief Copies memory. * * Copies the \a len bytes from the buffer pointed by the parameter \a src @@ -871,7 +929,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 +937,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 ); @@ -971,12 +1029,18 @@ void _mali_osk_lock_term( _mali_osk_lock_t *lock ); /** @brief Issue a memory barrier * - * This defines an arbitrary memory barrier operation, which affects memory - * mapped by _mali_osk_mem_mapregion. It will not be needed for memory - * mapped through _mali_osk_mem_mapioregion. + * This defines an arbitrary memory barrier operation, which forces an ordering constraint + * on memory read and write operations. */ void _mali_osk_mem_barrier( void ); +/** @brief Issue a write memory barrier + * + * This defines an write memory barrier operation which forces an ordering constraint + * on memory write operations. + */ +void _mali_osk_write_mem_barrier( void ); + /** @brief Map a physically contiguous region into kernel space * * This is primarily used for mapping in registers from resources, and Mali-MMU @@ -1120,7 +1184,21 @@ void _mali_osk_mem_unreqregion( u32 phys, u32 size ); u32 _mali_osk_mem_ioread32( volatile mali_io_address mapping, u32 offset ); /** @brief Write to a location currently mapped in through - * _mali_osk_mem_mapioregion + * _mali_osk_mem_mapioregion without memory barriers + * + * This write a 32-bit word to a 32-bit aligned location without using memory barrier. + * It is a programming error to provide unaligned locations, or to write to memory that is not + * mapped in, or not mapped through either _mali_osk_mem_mapioregion() or + * _mali_osk_mem_allocioregion(). + * + * @param mapping Mali IO address to write to + * @param offset Byte offset from the given IO address to operate on, must be a multiple of 4 + * @param val the 32-bit word to write. + */ +void _mali_osk_mem_iowrite32_relaxed( volatile mali_io_address addr, u32 offset, u32 val ); + +/** @brief Write to a location currently mapped in through + * _mali_osk_mem_mapioregion with write memory barrier * * This write a 32-bit word to a 32-bit aligned location. It is a programming * error to provide unaligned locations, or to write to memory that is not @@ -1147,7 +1225,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 ); @@ -1522,7 +1600,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 ); @@ -1559,6 +1637,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. @@ -1594,8 +1684,13 @@ u32 _mali_osk_get_pid(void); */ u32 _mali_osk_get_tid(void); -/** @} */ /* end group _mali_osk_miscellaneous */ +/** @brief Return a handle to the current task. + * + * @return An OS-specific handle to the current task. + */ +void * _mali_osk_get_task(void); +/** @} */ /* end group _mali_osk_miscellaneous */ /** @} */ /* end group osuapi */ diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_osk_bitops.h b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_osk_bitops.h index 28026ba1e6d..f262f7dad37 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_osk_bitops.h +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_osk_bitops.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * Copyright (C) 2010 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_osk_profiling.h b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_osk_profiling.h new file mode 100644 index 00000000000..a291bd1965b --- /dev/null +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_osk_profiling.h @@ -0,0 +1,183 @@ +/** + * Copyright (C) 2010-2012 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms of + * such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __MALI_OSK_PROFILING_H__ +#define __MALI_OSK_PROFILING_H__ + +#if MALI_TIMELINE_PROFILING_ENABLED + +#if defined (CONFIG_TRACEPOINTS) && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED +#include "mali_linux_trace.h" +#endif /* CONFIG_TRACEPOINTS && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED */ + +#include "mali_cinstr_profiling_events_m200.h" + +#define MALI_PROFILING_MAX_BUFFER_ENTRIES 1048576 + +#define MALI_PROFILING_PP_CORE_COUNTER0_OFFSET(core_number) (((core_number) * 2) + COUNTER_FP0_C0) +#define MALI_PROFILING_PP_CORE_COUNTER1_OFFSET(core_number) (((core_number) * 2) + COUNTER_FP0_C1) + +/** @defgroup _mali_osk_profiling External profiling connectivity + * @{ */ + +/** + * Initialize the profiling module. + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +_mali_osk_errcode_t _mali_osk_profiling_init(mali_bool auto_start); + +/* + * Terminate the profiling module. + */ +void _mali_osk_profiling_term(void); + +/** + * Start recording profiling data + * + * The specified limit will determine how large the capture buffer is. + * MALI_PROFILING_MAX_BUFFER_ENTRIES determines the maximum size allowed by the device driver. + * + * @param limit The desired maximum number of events to record on input, the actual maximum on output. + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +_mali_osk_errcode_t _mali_osk_profiling_start(u32 * limit); + +/** + * Add an profiling event + * + * @param event_id The event identificator. + * @param data0 First data parameter, depending on event_id specified. + * @param data1 Second data parameter, depending on event_id specified. + * @param data2 Third data parameter, depending on event_id specified. + * @param data3 Fourth data parameter, depending on event_id specified. + * @param data4 Fifth data parameter, depending on event_id specified. + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +#if defined (CONFIG_TRACEPOINTS) && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED +/* + * On platforms where we are using Linux tracepoints and we aren't forcing + * internal profiling we can call through to the tracepoint directly and + * avoid the overhead of the function call. + */ +#define _mali_osk_profiling_add_event(event_id, data0, data1, data2, data3, data4) \ + trace_mali_timeline_event((event_id), (data0), (data1), (u32)_mali_osk_get_task(), (data3), (data4)) +#else +void _mali_osk_profiling_add_event(u32 event_id, u32 data0, u32 data1, u32 data2, u32 data3, u32 data4); +#endif /* CONFIG_TRACEPOINTS && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED */ + +/** + * Report a hardware counter event. + * + * @param counter_id The ID of the counter. + * @param value The value of the counter. + */ +#if defined (CONFIG_TRACEPOINTS) && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED +/* + * On platforms where we are using Linux tracepoints and we aren't forcing + * internal profiling we can call through to the tracepoint directly and + * avoid the overhead of the function call. + */ +#define _mali_osk_profiling_report_hw_counter trace_mali_hw_counter +#else +void _mali_osk_profiling_report_hw_counter(u32 counter_id, u32 value); +#endif /* CONFIG_TRACEPOINTS && !MALI_INTERNAL_TIMELINE_PROFILING_ENABLED */ + +/** + * Query a hardware counter. Given a counter ID, check which event the + * counter should report and update the given pointer with that event + * number before returning MALI_TRUE. If the counter has been disabled + * by the profiling tool, returns MALI_FALSE and does not update the + * pointer. + * + * MALI_FALSE is also returned if the counter is not a valid hardware + * counter ID. In this case the event value is not updated. + * + * @param counter_id The counter ID. + * @param event_id A pointer to a u32 value that will be updated with + * the event ID that should be counted, should the counter have been + * enabled by the profiling tool. + * + * @return MALI_TRUE if the counter should be enabled, MALI_FALSE otherwise. + */ +mali_bool _mali_osk_profiling_query_hw_counter(u32 counter_id, u32 *event_id); + +/** + * Stop recording profiling data + * + * @param count Returns the number of recorded events. + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +_mali_osk_errcode_t _mali_osk_profiling_stop(u32 * count); + +/** + * Retrieves the number of events that can be retrieved + * + * @return The number of recorded events that can be retrieved. + */ +u32 _mali_osk_profiling_get_count(void); + +/** + * Retrieve an event + * + * @param index Event index (start with 0 and continue until this function fails to retrieve all events) + * @param timestamp The timestamp for the retrieved event will be stored here. + * @param event_id The event ID for the retrieved event will be stored here. + * @param data The 5 data values for the retrieved event will be stored here. + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +_mali_osk_errcode_t _mali_osk_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5]); + +/** + * Clear the recorded buffer. + * + * This is needed in order to start another recording. + * + * @return _MALI_OSK_ERR_OK on success, otherwise failure. + */ +_mali_osk_errcode_t _mali_osk_profiling_clear(void); + +/** + * Checks if a recording of profiling data is in progress + * + * @return MALI_TRUE if recording of profiling data is in progress, MALI_FALSE if not + */ +mali_bool _mali_osk_profiling_is_recording(void); + +/** + * Checks if profiling data is available for retrival + * + * @return MALI_TRUE if profiling data is avaiable, MALI_FALSE if not + */ +mali_bool _mali_osk_profiling_have_recording(void); + +/** + * Enable or disable profiling events as default for new sessions (applications) + * + * @param enable MALI_TRUE if profiling events should be turned on, otherwise MALI_FALSE + */ +void _mali_osk_profiling_set_default_enable_state(mali_bool enable); + +/** + * Get current default enable state for new sessions (applications) + * + * @return MALI_TRUE if profiling events should be turned on, otherwise MALI_FALSE + */ +mali_bool _mali_osk_profiling_get_default_enable_state(void); + +/** @} */ /* end group _mali_osk_profiling */ + +#endif /* MALI_TIMELINE_PROFILING_ENABLED */ + +#endif /* __MALI_OSK_PROFILING_H__ */ + + diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_uk_types.h b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_uk_types.h index 9a1583658c9..433de1fc537 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_uk_types.h +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_uk_types.h @@ -121,6 +121,7 @@ typedef enum _MALI_UK_PROFILING_STOP, /**< __mali_uku_profiling_stop() */ _MALI_UK_PROFILING_GET_EVENT, /**< __mali_uku_profiling_get_event() */ _MALI_UK_PROFILING_CLEAR, /**< __mali_uku_profiling_clear() */ + _MALI_UK_PROFILING_GET_CONFIG, /**< __mali_uku_profiling_get_config() */ #if USING_MALI_PMM /** Power Management Module Functions */ @@ -461,6 +462,8 @@ typedef struct u32 abort_id; /**< [in] abort id of this job, used to identify this job for later abort requests */ u32 perf_counter_l2_src0; /**< [in] soruce id for Mali-400 MP L2 cache performance counter 0 */ u32 perf_counter_l2_src1; /**< [in] source id for Mali-400 MP L2 cache performance counter 1 */ + u32 frame_builder_id; /**< [in] id of the originating frame builder */ + u32 flush_id; /**< [in] flush id within the originating frame builder */ } _mali_uk_gp_start_job_s; #define _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE (1<<0) /**< Enable performance counter SRC0 for a job */ @@ -574,6 +577,8 @@ typedef struct u32 abort_id; /**< [in] abort id of this job, used to identify this job for later abort requests */ u32 perf_counter_l2_src0; /**< [in] soruce id for Mali-400 MP L2 cache performance counter 0 */ u32 perf_counter_l2_src1; /**< [in] source id for Mali-400 MP L2 cache performance counter 1 */ + u32 frame_builder_id; /**< [in] id of the originating frame builder */ + u32 flush_id; /**< [in] flush id within the originating frame builder */ } _mali_uk_pp_start_job_s; /** @} */ /* end group _mali_uk_ppstartjob_s */ @@ -733,7 +738,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 8 +#define _MALI_API_VERSION 9 #define _MALI_UK_API_VERSION _MAKE_VERSION_ID(_MALI_API_VERSION) /** @@ -1019,6 +1024,11 @@ typedef struct void *ctx; /**< [in,out] user-kernel context (trashed on output) */ } _mali_uk_profiling_clear_s; +typedef struct +{ + void *ctx; /**< [in,out] user-kernel context (trashed on output) */ + u32 enable_events; /**< [out]Â 1 if user space process should generate events, 0 if not */ +} _mali_uk_profiling_get_config_s; /** @} */ /* end group _mali_uk_gp */ @@ -1102,7 +1112,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 */ diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_ukk.h b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_ukk.h index d066046901d..c70dccc3c20 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/mali_ukk.h +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/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); @@ -680,6 +680,13 @@ _mali_osk_errcode_t _mali_ukk_profiling_get_event(_mali_uk_profiling_get_event_s */ _mali_osk_errcode_t _mali_ukk_profiling_clear(_mali_uk_profiling_clear_s *args); +/** @brief Get the profiling config applicable for calling process. + * + * @param args see _mali_uk_profiling_get_config_s in "mali_uk_types.h" + */ +_mali_osk_errcode_t _mali_ukk_profiling_get_config(_mali_uk_profiling_get_config_s *args); + + /** @} */ /* end group _mali_uk_profiling */ #endif @@ -702,6 +709,7 @@ _mali_osk_errcode_t _mali_ukk_vsync_event_report(_mali_uk_vsync_event_report_s * /** @} */ /* end group uddapi */ +u32 _mali_ukk_report_memory_usage(void); #ifdef __cplusplus } diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm.c b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm.c index eeb29589ddc..1b17a9ffe95 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm.c +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm.c @@ -23,6 +23,7 @@ #include "mali_pmm_system.h" #include "mali_pmm_state.h" #include "mali_pmm_policy.h" +#include "mali_pmm_pmu.h" #include "mali_platform.h" /* Internal PMM subsystem state */ @@ -64,7 +65,7 @@ _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 - void malipmm_subsystem_dump_state( void ); +u32 malipmm_subsystem_dump_state( char *buf, u32 size ); #endif @@ -295,7 +296,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[] = { @@ -307,19 +308,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", @@ -335,6 +323,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; @@ -480,11 +497,11 @@ _mali_osk_errcode_t malipmm_create(_mali_osk_resource_t *resource) /* Set up assumes all values are initialized to NULL or MALI_FALSE, so * we can exit halfway through set up and perform clean up */ -#if !MALI_PMM_NO_PMU - if( mali_platform_init(resource) != _MALI_OSK_ERR_OK ) goto pmm_fail_cleanup; - pmm_state->pmu_initialized = MALI_TRUE; -#endif +#if USING_MALI_PMU + if( mali_pmm_pmu_init(resource) != _MALI_OSK_ERR_OK ) goto pmm_fail_cleanup; + pmm_state->pmu_initialized = MALI_TRUE; +#endif pmm_state->queue = _mali_osk_notification_queue_init(); if( !pmm_state->queue ) goto pmm_fail_cleanup; @@ -518,12 +535,18 @@ pmm_fail_cleanup: MALI_PRINT_ERROR( ("PMM: subsystem failed to be created\n") ); if( pmm_state ) { - _mali_osk_resource_type_t t = PMU; if( pmm_state->lock ) _mali_osk_lock_term( pmm_state->lock ); if( pmm_state->irq ) _mali_osk_irq_term( pmm_state->irq ); if( pmm_state->queue ) _mali_osk_notification_queue_term( pmm_state->queue ); if( pmm_state->iqueue ) _mali_osk_notification_queue_term( pmm_state->iqueue ); - if( pmm_state->pmu_initialized ) ( mali_platform_deinit(&t) ); +#if USING_MALI_PMU + if( pmm_state->pmu_initialized ) + { + _mali_osk_resource_type_t t = PMU; + mali_pmm_pmu_deinit(&t); + } +#endif /* USING_MALI_PMU */ + _mali_osk_free(pmm_state); pmm_state = NULL; } @@ -547,6 +570,23 @@ _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; + MALI_PMM_UNLOCK(pmm); + + /* flush PMM workqueue */ + _mali_osk_flush_workqueue( pmm->irq ); + + if (pmm->cores_powered == 0) + { + malipmm_powerup(pmm->cores_registered); + } +} + void malipmm_kernel_subsystem_terminate( mali_kernel_subsystem_identifier id ) { /* Check this is the right system */ @@ -555,7 +595,6 @@ void malipmm_kernel_subsystem_terminate( mali_kernel_subsystem_identifier id ) if( pmm_state ) { - _mali_osk_resource_type_t t = PMU; #if PMM_OS_TEST power_test_end(); #endif @@ -569,11 +608,20 @@ void malipmm_kernel_subsystem_terminate( mali_kernel_subsystem_identifier id ) 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 ); _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); + if (pmm_state->cores_registered) malipmm_powerdown(pmm_state->cores_registered,MALI_POWER_MODE_LIGHT_SLEEP); +#if USING_MALI_PMU + if( pmm_state->pmu_initialized ) + { + _mali_osk_resource_type_t t = PMU; + mali_pmm_pmu_deinit(&t); + } +#endif /* USING_MALI_PMU */ + _mali_osk_atomic_term( &(pmm_state->messages_queued) ); MALI_PMM_LOCK_TERM(pmm_state); _mali_osk_free(pmm_state); @@ -583,6 +631,47 @@ void malipmm_kernel_subsystem_terminate( mali_kernel_subsystem_identifier id ) MALIPMM_DEBUG_PRINT( ("PMM: subsystem terminated\n") ); } +_mali_osk_errcode_t malipmm_powerup( u32 cores ) +{ + _mali_osk_errcode_t err = _MALI_OSK_ERR_OK; + _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR; + + /* If all the cores are powered down, power up the MALI */ + if (pmm->cores_powered == 0) + { + mali_platform_power_mode_change(MALI_POWER_MODE_ON); +#if MALI_PMM_RUNTIME_JOB_CONTROL_ON + /* Initiate the power up */ + _mali_osk_pmm_dev_activate(); +#endif + } + +#if USING_MALI_PMU + err = mali_pmm_pmu_powerup( cores ); +#endif + return err; +} + +_mali_osk_errcode_t malipmm_powerdown( u32 cores, mali_power_mode power_mode ) +{ + _mali_osk_errcode_t err = _MALI_OSK_ERR_OK; + _mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR; +#if USING_MALI_PMU + err = mali_pmm_pmu_powerdown( cores ); +#endif + + /* If all cores are powered down, power off the MALI */ + if (pmm->cores_powered == 0) + { +#if MALI_PMM_RUNTIME_JOB_CONTROL_ON + /* Initiate the power down */ + _mali_osk_pmm_dev_idle(); +#endif + mali_platform_power_mode_change(power_mode); + } + return err; +} + _mali_osk_errcode_t malipmm_core_register( mali_pmm_core_id core ) { _mali_osk_errcode_t err; @@ -614,7 +703,7 @@ _mali_osk_errcode_t malipmm_core_register( mali_pmm_core_id core ) #if !MALI_PMM_NO_PMU /* Make sure the core is powered up */ - err = mali_platform_powerup( core ); + err = malipmm_powerup( core ); #else err = _MALI_OSK_ERR_OK; #endif @@ -668,18 +757,7 @@ 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); pmm->cores_powered &= (~core); pmm->cores_pend_down &= (~core); @@ -740,7 +818,7 @@ void malipmm_irq_bhandler(void *data) #endif MALI_PMM_LOCK(pmm); -#ifdef MALI_STATE_TRACKING +#if MALI_STATE_TRACKING pmm->mali_pmm_lock_acquired = 1; #endif /* MALI_STATE_TRACKING */ @@ -825,10 +903,10 @@ static void pmm_event_process( void ) return; } else - { + { #if (MALI_PMM_TRACE || MALI_STATE_TRACKING) pmm->messages_received++; - #endif + #endif } } else @@ -843,7 +921,7 @@ static void pmm_event_process( void ) { #if (MALI_PMM_TRACE || MALI_STATE_TRACKING) pmm->imessages_received++; - #endif + #endif } MALI_DEBUG_ASSERT_POINTER( msg ); @@ -893,29 +971,36 @@ static void pmm_event_process( void ) } #if MALI_STATE_TRACKING -void malipmm_subsystem_dump_state(void) -{ - malipmm_state_dump(); -} -#endif - -#if (defined(DEBUG) || MALI_STATE_TRACKING) -void malipmm_state_dump() +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(("Locks::\nPMM_LOCK_STATUS=%ld",pmm->mali_pmm_lock_acquired)); - MALI_PRINT(("PMM state:\nPrevious_status=%d\nstatus=%d\nCurrent_event=%d\npolicy=%d\ncheck_policy=%d\nstate=%d\n", pmm->mali_last_pmm_status,pmm->status, pmm->mali_new_event_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/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm.h b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm.h index fe7a046cb47..6157746da0c 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm.h +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm.h @@ -18,6 +18,7 @@ /* For mali_pmm_message_data and MALI_PMM_EVENT_UK_* defines */ #include "mali_uk_types.h" +#include "mali_platform.h" #ifdef __cplusplus extern "C" @@ -40,7 +41,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 +53,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 @@ -95,6 +96,7 @@ typedef enum mali_pmm_core_id_tag MALI_PMM_CORE_PP_ALL = 0x0000003C /**< Mali 200 pixel processors 0-3 */ } mali_pmm_core_id; + /* @brief PMM bitmask of mali_pmm_core_ids */ typedef u32 mali_pmm_core_mask; @@ -137,6 +139,23 @@ 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 power up MALI + * + * @param cores core mask to power up the cores + * + * @return error code if MALI fails to power up + */ +_mali_osk_errcode_t malipmm_powerup( u32 cores ); + +/** @brief Function to power down MALI + * + * @param cores core mask to power down the cores + * @param The power mode to which MALI transitions + * + * @return error code if MALI fails to power down + */ +_mali_osk_errcode_t malipmm_powerdown( u32 cores, mali_power_mode power_mode ); + /** @brief Function to report to the OS when the power down has finished * * @param data The event message data that initiated the power down @@ -149,7 +168,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 */ @@ -164,6 +183,12 @@ 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 report the OS that device is idle * * @note inform the OS that device is idle @@ -176,6 +201,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 @@ -305,15 +336,9 @@ void _mali_pmm_trace_event_message( mali_pmm_message_t *event, mali_bool receive /** @brief Dumps the current state of OS PMM thread */ #if MALI_STATE_TRACKING -void mali_pmm_dump_os_thread_state( void ); +u32 mali_pmm_dump_os_thread_state( char *buf, u32 size ); #endif /* MALI_STATE_TRACKING */ -#if (defined(DEBUG) || MALI_STATE_TRACKING) -/** @brief Dumps the current state of the PMM - */ -void malipmm_state_dump( void ); -#endif - /** @} */ /* end group pmmapi */ #ifdef __cplusplus diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_pmu.c b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_pmu.c new file mode 100644 index 00000000000..da8957724e8 --- /dev/null +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_pmu.c @@ -0,0 +1,350 @@ +/* + * 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_pmm_pmu.c + * Mali driver functions for Mali 400 PMU hardware + */ +#include "mali_kernel_common.h" +#include "mali_osk.h" +#include "mali_platform.h" + +#if USING_MALI_PMU +#if USING_MALI_PMM + +#include "mali_pmm.h" + +/* Internal test on/off */ +#define PMU_TEST 0 + +#if MALI_POWER_MGMT_TEST_SUITE +#include "mali_platform_pmu_internal_testing.h" +#endif /* MALI_POWER_MGMT_TEST_SUITE */ + +/** @brief PMU hardware info + */ +typedef struct platform_pmu +{ + u32 reg_base_addr; /**< PMU registers base address */ + u32 reg_size; /**< PMU registers size */ + const char *name; /**< PMU name */ + u32 irq_num; /**< PMU irq number */ + + mali_io_address reg_mapped; /**< IO-mapped pointer to registers */ +} platform_pmu_t; + +static platform_pmu_t *pmu_info = NULL; + +/** @brief Register layout for hardware PMU + */ +typedef enum { + PMU_REG_ADDR_MGMT_POWER_UP = 0x00, /*< Power up register */ + PMU_REG_ADDR_MGMT_POWER_DOWN = 0x04, /*< Power down register */ + PMU_REG_ADDR_MGMT_STATUS = 0x08, /*< Core sleep status register */ + PMU_REG_ADDR_MGMT_INT_MASK = 0x0C, /*< Interrupt mask register */ + PMU_REG_ADDR_MGMT_INT_RAWSTAT = 0x10, /*< Interrupt raw status register */ + PMU_REG_ADDR_MGMT_INT_STAT = 0x14, /*< Interrupt status register */ + PMU_REG_ADDR_MGMT_INT_CLEAR = 0x18, /*< Interrupt clear register */ + PMU_REG_ADDR_MGMT_SW_DELAY = 0x1C, /*< Software delay register */ + PMU_REG_ADDR_MGMT_MASTER_PWR_UP = 0x24, /*< Master power up register */ + PMU_REGISTER_ADDRESS_SPACE_SIZE = 0x28, /*< Size of register space */ +} pmu_reg_addr_mgmt_addr; + +/* Internal functions */ +static u32 pmu_reg_read(platform_pmu_t *pmu, u32 relative_address); +static void pmu_reg_write(platform_pmu_t *pmu, u32 relative_address, u32 new_val); +static mali_pmm_core_mask pmu_translate_cores_to_pmu(mali_pmm_core_mask cores); +#if PMU_TEST +static void pmm_pmu_dump_regs( platform_pmu_t *pmu ); +static pmm_pmu_test( platform_pmu_t *pmu, u32 cores ); +#endif + +_mali_osk_errcode_t mali_pmm_pmu_init(_mali_osk_resource_t *resource) +{ + + if( resource->type == PMU ) + { + if( (resource->base == 0) || + (resource->description == NULL) ) + { + /* NOTE: We currently don't care about any other resource settings */ + MALI_PRINT_ERROR(("PLATFORM mali400-pmu: Missing PMU set up information\n")); + MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); + } + pmu_info = (platform_pmu_t *)_mali_osk_malloc(sizeof(*pmu_info)); + MALI_CHECK_NON_NULL( pmu_info, _MALI_OSK_ERR_NOMEM ); + + /* All values get 0 as default */ + _mali_osk_memset(pmu_info, 0, sizeof(*pmu_info)); + + pmu_info->reg_base_addr = resource->base; + pmu_info->reg_size = (u32)PMU_REGISTER_ADDRESS_SPACE_SIZE; + pmu_info->name = resource->description; + pmu_info->irq_num = resource->irq; + + if( _MALI_OSK_ERR_OK != _mali_osk_mem_reqregion(pmu_info->reg_base_addr, pmu_info->reg_size, pmu_info->name) ) + { + MALI_PRINT_ERROR(("PLATFORM mali400-pmu: Could not request register region (0x%08X - 0x%08X) for %s\n", + pmu_info->reg_base_addr, pmu_info->reg_base_addr + pmu_info->reg_size - 1, pmu_info->name)); + goto cleanup; + } + else + { + MALI_DEBUG_PRINT( 4, ("PLATFORM mali400-pmu: Success: request_mem_region: (0x%08X - 0x%08X) for %s\n", + pmu_info->reg_base_addr, pmu_info->reg_base_addr + pmu_info->reg_size - 1, pmu_info->name)); + } + + pmu_info->reg_mapped = _mali_osk_mem_mapioregion( pmu_info->reg_base_addr, pmu_info->reg_size, pmu_info->name ); + + if( 0 == pmu_info->reg_mapped ) + { + MALI_PRINT_ERROR(("PLATFORM mali400-pmu: Could not ioremap registers for %s .\n", pmu_info->name)); + _mali_osk_mem_unreqregion( pmu_info->reg_base_addr, pmu_info->reg_size ); + goto cleanup; + } + else + { + MALI_DEBUG_PRINT( 4, ("PLATFORM mali400-pmu: Success: ioremap_nocache: Internal ptr: (0x%08X - 0x%08X) for %s\n", + (u32) pmu_info->reg_mapped, + ((u32)pmu_info->reg_mapped)+ pmu_info->reg_size - 1, + pmu_info->name)); + } + + MALI_DEBUG_PRINT( 4, ("PLATFORM mali400-pmu: Success: Mapping registers to %s\n", pmu_info->name)); + +#if PMU_TEST + pmu_test(pmu_info, (MALI_PMM_CORE_GP)); + pmu_test(pmu_info, (MALI_PMM_CORE_GP|MALI_PMM_CORE_L2|MALI_PMM_CORE_PP0)); +#endif + + MALI_DEBUG_PRINT( 4, ("PLATFORM mali400-pmu: Initialized - %s\n", pmu_info->name) ); + } + else + { + /* Didn't expect a different resource */ + MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); + } + + MALI_SUCCESS; + +cleanup: + _mali_osk_free(pmu_info); + pmu_info = NULL; + MALI_ERROR(_MALI_OSK_ERR_NOMEM); +} + +_mali_osk_errcode_t mali_pmm_pmu_deinit(_mali_osk_resource_type_t *type) +{ + if (*type == PMU) + { + if( pmu_info ) + { + _mali_osk_mem_unmapioregion(pmu_info->reg_base_addr, pmu_info->reg_size, pmu_info->reg_mapped); + _mali_osk_mem_unreqregion(pmu_info->reg_base_addr, pmu_info->reg_size); + _mali_osk_free(pmu_info); + pmu_info = NULL; + MALI_DEBUG_PRINT( 4, ("PLATFORM mali400-pmu: Terminated PMU\n") ); + } + } + else + { + /* Didn't expect a different resource */ + MALI_ERROR(_MALI_OSK_ERR_INVALID_ARGS); + } + + MALI_SUCCESS; + +} + +_mali_osk_errcode_t mali_pmm_pmu_powerdown(u32 cores) +{ + u32 stat; + u32 timeout; + u32 cores_pmu; + + MALI_DEBUG_ASSERT_POINTER(pmu_info); + MALI_DEBUG_ASSERT( cores != 0 ); /* Shouldn't receive zero from PMM */ + MALI_DEBUG_PRINT( 4, ("PLATFORM mali400-pmu: power down (0x%x)\n", cores) ); + + cores_pmu = pmu_translate_cores_to_pmu(cores); + pmu_reg_write( pmu_info, (u32)PMU_REG_ADDR_MGMT_POWER_DOWN, cores_pmu ); + + /* Wait for cores to be powered down */ + timeout = 10; /* 10ms */ + do + { + /* Get status of sleeping cores */ + stat = pmu_reg_read( pmu_info, (u32)PMU_REG_ADDR_MGMT_STATUS ); + stat &= cores_pmu; + if( stat == cores_pmu ) break; /* All cores we wanted are now asleep */ + _mali_osk_time_ubusydelay(1000); /* 1ms */ + timeout--; + } while( timeout > 0 ); + + if( timeout == 0 ) MALI_ERROR(_MALI_OSK_ERR_TIMEOUT); + + MALI_SUCCESS; +} + +_mali_osk_errcode_t mali_pmm_pmu_powerup(u32 cores) +{ + u32 cores_pmu; + u32 stat; + u32 timeout; + + MALI_DEBUG_ASSERT_POINTER(pmu_info); + MALI_DEBUG_ASSERT( cores != 0 ); /* Shouldn't receive zero from PMM */ + MALI_DEBUG_PRINT( 4, ("PLATFORM mali400-pmu: power up (0x%x)\n", cores) ); + + /* Don't use interrupts - just poll status */ + pmu_reg_write( pmu_info, (u32)PMU_REG_ADDR_MGMT_INT_MASK, 0 ); + cores_pmu = pmu_translate_cores_to_pmu(cores); + pmu_reg_write( pmu_info, (u32)PMU_REG_ADDR_MGMT_POWER_UP, cores_pmu ); + + timeout = 10; /* 10ms */ + do + { + /* Get status of sleeping cores */ + stat = pmu_reg_read( pmu_info, (u32)PMU_REG_ADDR_MGMT_STATUS ); + stat &= cores_pmu; + if( stat == 0 ) break; /* All cores we wanted are now awake */ + _mali_osk_time_ubusydelay(1000); /* 1ms */ + timeout--; + } while( timeout > 0 ); + + if( timeout == 0 ) MALI_ERROR(_MALI_OSK_ERR_TIMEOUT); + + MALI_SUCCESS; +} + + +/***** INTERNAL *****/ + +/** @brief Internal PMU function to translate the cores bit mask + * into something the hardware PMU understands + * + * @param cores PMM cores bitmask + * @return PMU hardware cores bitmask + */ +static u32 pmu_translate_cores_to_pmu(mali_pmm_core_mask cores) +{ + /* For Mali 400 PMU the cores mask is already the same as what + * the hardware PMU expects. + * For other hardware, some translation can be done here, by + * translating the MALI_PMM_CORE_* bits into specific hardware + * bits + */ + return cores; +} + +/** @brief Internal PMU function to read a PMU register + * + * @param pmu handle that identifies the PMU hardware + * @param relative_address relative PMU hardware address to read from + * @return 32-bit value that was read from the address + */ +static u32 pmu_reg_read(platform_pmu_t *pmu, u32 relative_address) +{ + u32 read_val; + + MALI_DEBUG_ASSERT_POINTER(pmu); + MALI_DEBUG_ASSERT((relative_address & 0x03) == 0); + MALI_DEBUG_ASSERT(relative_address < pmu->reg_size); + + read_val = _mali_osk_mem_ioread32(pmu->reg_mapped, relative_address); + + MALI_DEBUG_PRINT( 5, ("PMU: reg_read: %s Addr:0x%04X Val:0x%08x\n", + pmu->name, relative_address, read_val)); + + return read_val; +} + +/** @brief Internal PMU function to write to a PMU register + * + * @param pmu handle that identifies the PMU hardware + * @param relative_address relative PMU hardware address to write to + * @param new_val new 32-bit value to write into the address + */ +static void pmu_reg_write(platform_pmu_t *pmu, u32 relative_address, u32 new_val) +{ + MALI_DEBUG_ASSERT_POINTER(pmu); + MALI_DEBUG_ASSERT((relative_address & 0x03) == 0); + MALI_DEBUG_ASSERT(relative_address < pmu->reg_size); + + MALI_DEBUG_PRINT( 5, ("PMU: reg_write: %s Addr:0x%04X Val:0x%08x\n", + pmu->name, relative_address, new_val)); + + _mali_osk_mem_iowrite32(pmu->reg_mapped, relative_address, new_val); +} + +#if PMU_TEST + +/***** TEST *****/ + +static void pmu_dump_regs( platform_pmu_t *pmu ) +{ + u32 addr; + for( addr = 0x0; addr < PMU_REGISTER_ADDRESS_SPACE_SIZE; addr += 0x4 ) + { + MALI_PRINT( ("PMU_REG: 0x%08x: 0x%04x\n", (addr + pmu->reg_base_addr), pmu_reg_read( pmu, addr ) ) ); + } +} + +/* This function is an internal test for the PMU without any Mali h/w interaction */ +static void pmu_test( platform_pmu_t *pmu, u32 cores ) +{ + u32 stat; + u32 timeout; + + MALI_PRINT( ("PMU_TEST: Start\n") ); + + pmu_dump_regs( pmu ); + + MALI_PRINT( ("PMU_TEST: Power down cores: 0x%x\n", cores) ); + _mali_pmm_pmu_power_down( pmu, cores, MALI_TRUE ); + + stat = pmu_reg_read( pmu, (u32)PMU_REG_ADDR_MGMT_STATUS ); + MALI_PRINT( ("PMU_TEST: %s\n", (stat & cores) == cores ? "SUCCESS" : "FAIL" ) ); + + pmu_dump_regs( pmu ); + + MALI_PRINT( ("PMU_TEST: Power up cores: 0x%x\n", cores) ); + _mali_pmm_pmu_power_up( pmu, cores, MALI_FALSE ); + + MALI_PRINT( ("PMU_TEST: Waiting for power up...\n") ); + timeout = 1000; /* 1 sec */ + while( !_mali_pmm_pmu_irq_power_up(pmu) && timeout > 0 ) + { + _mali_osk_time_ubusydelay(1000); /* 1ms */ + timeout--; + } + + MALI_PRINT( ("PMU_TEST: Waited %dms for interrupt\n", (1000-timeout)) ); + stat = pmu_reg_read( pmu, (u32)PMU_REG_ADDR_MGMT_STATUS ); + MALI_PRINT( ("PMU_TEST: %s\n", (stat & cores) == 0 ? "SUCCESS" : "FAIL" ) ); + + _mali_pmm_pmu_irq_power_up_clear(pmu); + + pmu_dump_regs( pmu ); + + MALI_PRINT( ("PMU_TEST: Finish\n") ); +} +#endif /* PMU_TEST */ + +#if MALI_POWER_MGMT_TEST_SUITE + +u32 pmu_get_power_up_down_info(void) +{ + return pmu_reg_read(pmu_info, (u32)PMU_REG_ADDR_MGMT_STATUS); +} + +#endif /* MALI_POWER_MGMT_TEST_SUITE */ +#endif /* USING_MALI_PMM */ +#endif /* USING_MALI_PMU */ diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_pmu.h b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_pmu.h new file mode 100644 index 00000000000..112074b2010 --- /dev/null +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_pmu.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained from Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file mali_platform.h + * Platform specific Mali driver functions + */ + +#include "mali_osk.h" + +#if !USING_MALI_PMM +/* @brief System power up/down cores that can be passed into mali_platform_powerdown/up() */ +#define MALI_PLATFORM_SYSTEM 0 +#endif + +#if USING_MALI_PMM +#if USING_MALI_PMU +#include "mali_pmm.h" + +/** @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 + * system PMU + * + * @param resource This is NULL when called on first driver start up, else it will + * be a pointer to a PMU resource + * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. + */ +_mali_osk_errcode_t mali_pmm_pmu_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 + * + * @param type This is NULL when called on driver exit, else it will + * be a pointer to a PMU resource type (not the full resource) + * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. + */ +_mali_osk_errcode_t mali_pmm_pmu_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. + * + * @param cores This is MALI_PLATFORM_SYSTEM when called without PMM, else it will + * be a mask of cores to power down based on the mali_pmm_core_id enum + * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. + */ +_mali_osk_errcode_t mali_pmm_pmu_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. + * + * @param cores This is MALI_PLATFORM_SYSTEM when called without PMM, else it will + * be a mask of cores to power down based on the mali_pmm_core_id enum + * @return _MALI_OSK_ERR_OK on success otherwise, a suitable _mali_osk_errcode_t error. + */ +_mali_osk_errcode_t mali_pmm_pmu_powerup(u32 cores); + +#if MALI_POWER_MGMT_TEST_SUITE +#if USING_MALI_PMM +#if USING_MALI_PMU +/** @brief function to get status of individual cores + * + * This function is used by power management test suite to get the status of powered up/down the number + * of cores + * @param utilization The workload utilization of the Mali GPU. 0 = no utilization, 256 = full utilization. + */ +u32 pmu_get_power_up_down_info(void); +#endif +#endif +#endif +#endif +#endif diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_policy.h b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_policy.h index 83cb7f29a92..739c4c4ef17 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_policy.h +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/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/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_policy_alwayson.c b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_policy_alwayson.c index 643bb04553b..a4b893b21e6 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_policy_alwayson.c +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_policy_alwayson.c @@ -21,7 +21,6 @@ #include "mali_pmm.h" #include "mali_pmm_system.h" #include "mali_pmm_state.h" -#include "mali_pmm_policy.h" #include "mali_pmm_policy_alwayson.h" _mali_osk_errcode_t pmm_policy_init_always_on(void) diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_policy_alwayson.h b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_policy_alwayson.h index a158b09f610..da13224d955 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_policy_alwayson.h +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_policy_alwayson.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 ARM Limited. All rights reserved. + * Copyright (C) 2010 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence. diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_policy_jobcontrol.c b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_policy_jobcontrol.c index 8450bd722f4..7f339718354 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_policy_jobcontrol.c +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_policy_jobcontrol.c @@ -231,7 +231,7 @@ _mali_osk_errcode_t pmm_policy_process_job_control( _mali_pmm_internal_state_t * if( cores_subset != 0 ) { /* There are some cores that need powering down */ - if( !pmm_invoke_power_down( pmm ) ) + if( !pmm_invoke_power_down( pmm, MALI_POWER_MODE_DEEP_SLEEP ) ) { /* We need to wait until they are idle */ @@ -242,6 +242,11 @@ _mali_osk_errcode_t pmm_policy_process_job_control( _mali_pmm_internal_state_t * break; } } + else + { + mali_platform_power_mode_change(MALI_POWER_MODE_DEEP_SLEEP); + + } /* Set waiting status */ pmm->status = MALI_PMM_STATUS_OS_WAITING; /* All cores now down - respond to OS power event */ @@ -280,7 +285,7 @@ _mali_osk_errcode_t pmm_policy_process_job_control( _mali_pmm_internal_state_t * /* Check if we can really power down, if not then we are not * really in-active */ - if( !pmm_invoke_power_down( pmm ) ) + if( !pmm_invoke_power_down( pmm, MALI_POWER_MODE_LIGHT_SLEEP ) ) { pmm_power_down_cancel( pmm ); } @@ -322,12 +327,16 @@ _mali_osk_errcode_t pmm_policy_process_job_control( _mali_pmm_internal_state_t * pmm->status = MALI_PMM_STATUS_OS_WAITING; if ( pmm->cores_powered != 0 ) { - if ( pmm_invoke_power_down( pmm ) ) + if ( pmm_invoke_power_down( pmm, MALI_POWER_MODE_DEEP_SLEEP ) ) { _mali_osk_pmm_power_down_done( 0 ); break; } } + else + { + mali_platform_power_mode_change(MALI_POWER_MODE_DEEP_SLEEP); + } _mali_osk_pmm_power_down_done( 0 ); break; default: @@ -384,7 +393,7 @@ _mali_osk_errcode_t pmm_policy_process_job_control( _mali_pmm_internal_state_t * } /* Now check if we can power down */ - if( pmm_invoke_power_down( pmm ) ) + if( pmm_invoke_power_down( pmm, MALI_POWER_MODE_DEEP_SLEEP ) ) { if( pmm->status == MALI_PMM_STATUS_OS_POWER_DOWN ) { diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_policy_jobcontrol.h b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_policy_jobcontrol.h index 455234b80bc..f1e7c2d9a82 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_policy_jobcontrol.h +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/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/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_state.c b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_state.c index a0ac1c7790c..2e05555cf29 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_state.c +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_state.c @@ -199,6 +199,7 @@ mali_pmm_core_mask pmm_cores_to_power_down( _mali_pmm_internal_state_t *pmm, mal } else { + MALI_DEBUG_PRINT(1,("The error in PMM is ...%x...%x",err,*ppowered)); MALI_DEBUG_ASSERT( err == _MALI_OSK_ERR_BUSY || (err == _MALI_OSK_ERR_FAULT && (*ppowered & cores_list[n]) == 0) ); @@ -297,7 +298,7 @@ mali_bool pmm_power_down_okay( _mali_pmm_internal_state_t *pmm ) return ( pmm->cores_pend_down == pmm->cores_ack_down ? MALI_TRUE : MALI_FALSE ); } -mali_bool pmm_invoke_power_down( _mali_pmm_internal_state_t *pmm ) +mali_bool pmm_invoke_power_down( _mali_pmm_internal_state_t *pmm, mali_power_mode power_mode ) { _mali_osk_errcode_t err; MALI_DEBUG_ASSERT_POINTER(pmm); @@ -315,8 +316,9 @@ mali_bool pmm_invoke_power_down( _mali_pmm_internal_state_t *pmm ) } else { + pmm->cores_powered &= ~(pmm->cores_pend_down); #if !MALI_PMM_NO_PMU - err = mali_platform_powerdown( pmm->cores_pend_down ); + err = malipmm_powerdown( pmm->cores_pend_down, power_mode); #else err = _MALI_OSK_ERR_OK; #endif @@ -327,7 +329,6 @@ mali_bool pmm_invoke_power_down( _mali_pmm_internal_state_t *pmm ) mali_pmm_core_mask old_power = pmm->cores_powered; #endif /* Remove powered down cores from idle and powered list */ - pmm->cores_powered &= ~(pmm->cores_pend_down); pmm->cores_idle &= ~(pmm->cores_pend_down); /* Reset pending/acknowledged status */ pmm->cores_pend_down = 0; @@ -338,6 +339,7 @@ mali_bool pmm_invoke_power_down( _mali_pmm_internal_state_t *pmm ) } else { + pmm->cores_powered |= pmm->cores_pend_down; MALI_PRINT_ERROR( ("PMM: Failed to get PMU to power down cores - (0x%x) %s", pmm->cores_pend_down, pmm_trace_get_core_name(pmm->cores_pend_down)) ); pmm->fatal_power_err = MALI_TRUE; @@ -429,7 +431,7 @@ mali_bool pmm_invoke_power_up( _mali_pmm_internal_state_t *pmm ) { #if !MALI_PMM_NO_PMU /* Power up must now be done */ - err = mali_platform_powerup( pmm->cores_pend_up ); + err = malipmm_powerup( pmm->cores_pend_up ); #else err = _MALI_OSK_ERR_OK; #endif @@ -537,7 +539,7 @@ void pmm_fatal_reset( _mali_pmm_internal_state_t *pmm ) int n; volatile mali_pmm_core_mask *pregistered = &(pmm->cores_registered); #if !MALI_PMM_NO_PMU - err = mali_platform_powerup( pmm->cores_registered ); + err = malipmm_powerup( pmm->cores_registered ); #endif if( err != _MALI_OSK_ERR_OK ) { diff --git a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_state.h b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_state.h index 3c8c31f066d..849fe8b8048 100644 --- a/drivers/gpu/mali/mali400ko/driver/src/devicedrv/mali/common/pmm/mali_pmm_state.h +++ b/drivers/gpu/mali/mali400ko/driver/src/devicedrv/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 */ @@ -96,12 +95,12 @@ typedef struct _mali_pmm_internal_state mali_bool fatal_power_err; /**< PMM has had a fatal power error? */ u32 is_dvfs_active; /**< PMM DVFS activity */ -#if (defined(DEBUG) || MALI_STATE_TRACKING) - u32 mali_last_pmm_status; - u32 mali_new_event_status; - u32 mali_pmm_lock_acquired; +#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 */ @@ -133,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 ); @@ -153,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 ); @@ -177,13 +176,13 @@ 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 * @return MALI_TRUE if the pending cores have been powered down, else MALI_FALSE */ -mali_bool pmm_invoke_power_down( _mali_pmm_internal_state_t *pmm ); +mali_bool pmm_invoke_power_down( _mali_pmm_internal_state_t *pmm, mali_power_mode power_mode ); /** @brief Check if all the pending cores to power up have done so * @@ -230,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 @@ -253,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 |