/* ------------- interrupt handling below ------------------ */ static _mali_osk_errcode_t mali_pp_upper_half(void *data) { struct mali_pp_core *core = (struct mali_pp_core *)data; u32 irq_readout; #if !defined(MSTAR_RIU_ENABLED) || (MSTAR_RIU_ADDRESS_TYPE == 32) irq_readout = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS); #else irq_readout = mali_hw_core_register_read_no_lock(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS); #endif if (MALI200_REG_VAL_IRQ_MASK_NONE != irq_readout) { /* Mask out all IRQs from this core until IRQ is handled */ #if !defined(MSTAR_RIU_ENABLED) || (MSTAR_RIU_ADDRESS_TYPE == 32) mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_NONE); #else mali_hw_core_register_write_no_lock(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_NONE); #endif #if MALI_TIMELINE_PROFILING_ENABLED _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id)|MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT, irq_readout, 0, 0, 0, 0); #endif /* We do need to handle this in a bottom half */ _mali_osk_irq_schedulework(core->irq); return _MALI_OSK_ERR_OK; } return _MALI_OSK_ERR_FAULT; }
static _mali_osk_errcode_t mali_pp_upper_half(void *data) { struct mali_pp_core *core = (struct mali_pp_core *)data; u32 irq_readout = 0; #if MALI_SHARED_INTERRUPTS mali_pm_lock(); if (MALI_TRUE == mali_pm_is_powered_on()) { #endif irq_readout = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_STATUS); #if MALI_SHARED_INTERRUPTS } mali_pm_unlock(); #endif if (MALI200_REG_VAL_IRQ_MASK_NONE != irq_readout) { mali_hw_core_register_write(&core->hw_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_id)|MALI_PROFILING_EVENT_REASON_SINGLE_HW_INTERRUPT, irq_readout, 0, 0, 0, 0); #endif _mali_osk_irq_schedulework(core->irq); return _MALI_OSK_ERR_OK; } return _MALI_OSK_ERR_FAULT; }
static u32 subsystem_mali200_irq_handler_upper_half(mali_core_renderunit * core) { u32 irq_readout; if (mali_benchmark) { return (core->current_job ? 1 : 0); /* simulate irq is pending when a job is pending */ } 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_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; }
/* ------ local helper functions below --------- */ static void mali_pp_post_process_job(struct mali_pp_core *core) { MALI_ASSERT_GROUP_LOCKED(core->group); if (NULL != core->running_job) { u32 val0 = 0; u32 val1 = 0; #if MALI_TIMELINE_PROFILING_ENABLED int counter_index = COUNTER_FP0_C0 + (2 * core->core_id); #endif if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) { val0 = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE); if (mali_pp_job_get_perf_counter_flag(core->running_job) && _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE && mali_pp_job_get_perf_counter_src0(core->running_job) == core->counter_src0_used) { /* We retrieved the counter that user space asked for, so return the value through the job object */ mali_pp_job_set_perf_counter_value0(core->running_job, core->running_sub_job, val0); } else { /* User space asked for a counter, but this is not what we retrived (overridden by counter src set on core) */ mali_pp_job_set_perf_counter_value0(core->running_job, core->running_sub_job, MALI_HW_CORE_INVALID_VALUE); } #if MALI_TIMELINE_PROFILING_ENABLED _mali_osk_profiling_report_hw_counter(counter_index, val0); #endif } if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) { val1 = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE); if (mali_pp_job_get_perf_counter_flag(core->running_job) && _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE && mali_pp_job_get_perf_counter_src1(core->running_job) == core->counter_src1_used) { /* We retrieved the counter that user space asked for, so return the value through the job object */ mali_pp_job_set_perf_counter_value1(core->running_job, core->running_sub_job, val1); } else { /* User space asked for a counter, but this is not what we retrived (overridden by counter src set on core) */ mali_pp_job_set_perf_counter_value1(core->running_job, core->running_sub_job, MALI_HW_CORE_INVALID_VALUE); } #if MALI_TIMELINE_PROFILING_ENABLED _mali_osk_profiling_report_hw_counter(counter_index + 1, val1); #endif } #if MALI_TIMELINE_PROFILING_ENABLED _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id), val0, val1, core->counter_src0_used | (core->counter_src1_used << 8), 0, 0); #endif /* We are no longer running a job... */ core->running_job = NULL; _mali_osk_timer_del(core->timeout_timer); } }
void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 sub_job) { u32 *frame_registers = mali_pp_job_get_frame_registers(job); u32 *wb0_registers = mali_pp_job_get_wb0_registers(job); u32 *wb1_registers = mali_pp_job_get_wb1_registers(job); u32 *wb2_registers = mali_pp_job_get_wb2_registers(job); core->counter_src0_used = core->counter_src0; core->counter_src1_used = core->counter_src1; MALI_DEBUG_ASSERT_POINTER(core); MALI_ASSERT_GROUP_LOCKED(core->group); mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_FRAME, frame_registers, MALI200_NUM_REGS_FRAME, mali_frame_registers_reset_values); _mali_osk_mem_barrier(); if (0 != sub_job) { /* * There are two frame registers which are different for each sub job. * For the first sub job, these are correctly represented in the frame register array, * but we need to patch these for all other sub jobs */ mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_FRAME, mali_pp_job_get_addr_frame(job, sub_job)); mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_STACK, mali_pp_job_get_addr_stack(job, sub_job), mali_frame_registers_reset_values[MALI200_REG_ADDR_STACK/4]); } if (wb0_registers[0]) /* M200_WB0_REG_SOURCE_SELECT register */ { mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB0, wb0_registers, MALI200_NUM_REGS_WBx, mali_wb_registers_reset_values); } else { mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB0, 0, mali_wb_registers_reset_values[0] ); } if (wb1_registers[0]) /* M200_WB1_REG_SOURCE_SELECT register */ { mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB1, wb1_registers, MALI200_NUM_REGS_WBx, mali_wb_registers_reset_values); } else { mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB1, 0, mali_wb_registers_reset_values[0] ); } if (wb2_registers[0]) /* M200_WB2_REG_SOURCE_SELECT register */ { mali_hw_core_register_write_array_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB2, wb2_registers, MALI200_NUM_REGS_WBx, mali_wb_registers_reset_values); } else { mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_WB2, 0, mali_wb_registers_reset_values[0] ); } /* This selects which performance counters we are reading */ if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used || MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) { /* global_config has enabled HW counters, this will override anything specified by user space */ if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) { mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value); } if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) { mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value); } } else { /* Use HW counters from job object, if any */ u32 perf_counter_flag = mali_pp_job_get_perf_counter_flag(job); if (0 != perf_counter_flag) { if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE) { core->counter_src0_used = mali_pp_job_get_perf_counter_src0(job); mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value); } if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE) { core->counter_src1_used = mali_pp_job_get_perf_counter_src1(job); mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); mali_hw_core_register_write_relaxed_conditional(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE, mali_perf_cnt_enable_reset_value); } } } MALI_DEBUG_PRINT(3, ("Mali PP: Starting job 0x%08X part %u/%u on PP core %s\n", job, sub_job + 1, mali_pp_job_get_sub_job_count(job), core->hw_core.description)); /* Adding barrier to make sure all rester writes are finished */ _mali_osk_write_mem_barrier(); /* This is the command that starts the core. */ mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_START_RENDERING); /* Adding barrier to make sure previous rester writes is finished */ _mali_osk_write_mem_barrier(); /* Setup the timeout timer value and save the job id for the job running on the pp core */ _mali_osk_timer_add(core->timeout_timer, _mali_osk_time_mstoticks(mali_max_job_runtime)); core->timeout_job_id = mali_pp_job_get_id(job); #if MALI_TIMELINE_PROFILING_ENABLED _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id) | MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH, mali_pp_job_get_frame_builder_id(job), mali_pp_job_get_flush_id(job), 0, 0, 0); _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id), mali_pp_job_get_pid(job), mali_pp_job_get_tid(job), 0, 0, 0); #endif core->running_job = job; core->running_sub_job = sub_job; }
static int subsystem_mali200_irq_handler_bottom_half(struct mali_core_renderunit* core) { u32 irq_readout; u32 current_tile_addr; u32 core_status; mali_core_job * job; mali200_job * job200; job = core->current_job; job200 = GET_JOB200_PTR(job); if (mali_benchmark) { irq_readout = MALI200_REG_VAL_IRQ_END_OF_FRAME; current_tile_addr = 0; core_status = 0; } else { irq_readout = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT) & MALI200_REG_VAL_IRQ_MASK_USED; current_tile_addr = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_CURRENT_REND_LIST_ADDR); core_status = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_STATUS); } if (NULL == job) { MALI_DEBUG_ASSERT(CORE_IDLE==core->state); if ( 0 != irq_readout ) { MALI_PRINT_ERROR(("Interrupt from a core not running a job. IRQ: 0x%04x Status: 0x%04x", irq_readout, core_status)); } return JOB_STATUS_END_UNKNOWN_ERR; } MALI_DEBUG_ASSERT(CORE_IDLE!=core->state); job200->irq_status |= irq_readout; MALI_DEBUG_PRINT_IF( 3, ( 0 != irq_readout ), ("Mali PP: Job: 0x%08x IRQ RECEIVED Rawstat: 0x%x Tile_addr: 0x%x Status: 0x%x\n", (u32)job200->user_input.user_job_ptr, irq_readout ,current_tile_addr ,core_status)); if ( MALI200_REG_VAL_IRQ_END_OF_FRAME & irq_readout) { #if defined(USING_MALI200) mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_FLUSH_CACHES); #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) ) { 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 defined(USING_MALI400_L2_CACHE) if (job200->user_input.perf_counter_flag & (_MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC0_ENABLE|_MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC1_ENABLE) ) { u32 src0; u32 val0; u32 src1; u32 val1; mali_kernel_l2_cache_get_perf_counters(&src0, &val0, &src1, &val1); if (job200->perf_counter_l2_src0 == src0) { job200->perf_counter_l2_val0_raw = val0; job200->perf_counter_l2_val0 = val0 - job200->perf_counter_l2_val0; } else { job200->perf_counter_l2_val0_raw = 0; job200->perf_counter_l2_val0 = 0; } if (job200->perf_counter_l2_src1 == src1) { job200->perf_counter_l2_val1_raw = val1; job200->perf_counter_l2_val1 = val1 - job200->perf_counter_l2_val1; } else { job200->perf_counter_l2_val1_raw = 0; job200->perf_counter_l2_val1 = 0; } } #endif } #if MALI_TIMELINE_PROFILING_ENABLED _mali_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_raw, job200->perf_counter_l2_val1_raw #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)? */ else if ( (CORE_WATCHDOG_TIMEOUT == core->state) || ((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 */ #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? */ else if ((CORE_HANG_CHECK_TIMEOUT == core->state) || (irq_readout & job200->active_mask & MALI200_REG_VAL_IRQ_HANG)) { /* check interval in ms */ u32 timeout = mali_core_hang_check_timeout_get(); MALI_DEBUG_PRINT(3, ("M200: HW/SW Watchdog triggered, checking for progress in %d ms\n", timeout)); job200->last_tile_list_addr = current_tile_addr; /* hw watchdog triggered, set up a progress checker every HANGCHECK ms */ _mali_osk_timer_add(core->timer_hang_detection, _mali_osk_time_mstoticks(timeout)); job200->active_mask &= ~MALI200_REG_VAL_IRQ_HANG; /* ignore the hw watchdoig from now on */ mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_CLEAR, irq_readout & ~MALI200_REG_VAL_IRQ_HANG); mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_MASK, job200->active_mask); return JOB_STATUS_CONTINUE_RUN; /* not finished */ } /* No irq pending, core still busy */ else if ((0 == (irq_readout & MALI200_REG_VAL_IRQ_MASK_USED)) && ( 0 != (core_status & MALI200_REG_VAL_STATUS_RENDERING_ACTIVE))) { mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_CLEAR, irq_readout); mali_core_renderunit_register_write(core, MALI200_REG_ADDR_MGMT_INT_MASK, job200->active_mask); return JOB_STATUS_CONTINUE_RUN; /* Not finished */ } 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 */ #endif MALI_DEBUG_PRINT(1, ("Mali PP: Job: 0x%08x CRASH? Rawstat: 0x%x Tile_addr: 0x%x Status: 0x%x\n", (u32)job200->user_input.user_job_ptr, irq_readout ,current_tile_addr ,core_status) ) ; if (irq_readout & MALI200_REG_VAL_IRQ_BUS_ERROR) { u32 bus_error = mali_core_renderunit_register_read(core, MALI200_REG_ADDR_MGMT_BUS_ERROR_STATUS); MALI_DEBUG_PRINT(1, ("Bus error status: 0x%08X\n", bus_error)); MALI_DEBUG_PRINT_IF(1, (bus_error & 0x01), ("Bus write error from id 0x%02x\n", (bus_error>>2) & 0x0F)); MALI_DEBUG_PRINT_IF(1, (bus_error & 0x02), ("Bus read error from id 0x%02x\n", (bus_error>>6) & 0x0F)); MALI_DEBUG_PRINT_IF(1, (0 == (bus_error & 0x03)), ("Bus error but neither read or write was set as the error reason\n")); (void)bus_error; } #if MALI_STATE_TRACKING _mali_osk_atomic_inc(&job->session->jobs_ended); #endif return JOB_STATUS_END_UNKNOWN_ERR; /* reschedule */ }
/* Start this job on this core. Return MALI_TRUE if the job was started. */ static _mali_osk_errcode_t subsystem_mali200_start_job(mali_core_job * job, mali_core_renderunit * core) { mali200_job *job200; /* The local extended version of the general structs */ job200 = _MALI_OSK_CONTAINER_OF(job, mali200_job, embedded_core_job); if ( (0 == job200->user_input.frame_registers[0]) || (0 == job200->user_input.frame_registers[1]) ) { MALI_DEBUG_PRINT(4, ("Mali PP: Job: 0x%08x WILL NOT START SINCE JOB HAS ILLEGAL ADDRESSES\n", (u32)job200->user_input.user_job_ptr)); MALI_ERROR(_MALI_OSK_ERR_FAULT); } MALI_DEBUG_PRINT(4, ("Mali PP: Job: 0x%08x START_RENDER Tile_list: 0x%08x\n", (u32)job200->user_input.user_job_ptr, job200->user_input.frame_registers[0])); MALI_DEBUG_PRINT(6, ("Mali PP: RSW base addr: 0x%08x Vertex base addr: 0x%08x\n", job200->user_input.frame_registers[1], job200->user_input.frame_registers[2])); /* Frame registers. Copy from mem to physical registers */ mali_core_renderunit_register_write_array( core, MALI200_REG_ADDR_FRAME, &(job200->user_input.frame_registers[0]), MALI200_NUM_REGS_FRAME); /* Write Back unit 0. Copy from mem to physical registers only if the WB unit will be used. */ if (job200->user_input.wb0_registers[0]) { mali_core_renderunit_register_write_array( core, MALI200_REG_ADDR_WB0, &(job200->user_input.wb0_registers[0]), MALI200_NUM_REGS_WBx); } /* Write Back unit 1. Copy from mem to physical registers only if the WB unit will be used. */ if (job200->user_input.wb1_registers[0]) { mali_core_renderunit_register_write_array( core, MALI200_REG_ADDR_WB1, &(job200->user_input.wb1_registers[0]), MALI200_NUM_REGS_WBx); } /* Write Back unit 2. Copy from mem to physical registers only if the WB unit will be used. */ if (job200->user_input.wb2_registers[0]) { mali_core_renderunit_register_write_array( core, MALI200_REG_ADDR_WB2, &(job200->user_input.wb2_registers[0]), MALI200_NUM_REGS_WBx); } /* 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_relaxed( core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE); mali_core_renderunit_register_write_relaxed( core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, job200->user_input.perf_counter_src0); } if ( job200->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE) { 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_relaxed( core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, job200->user_input.perf_counter_src1); } #if defined(USING_MALI400_L2_CACHE) if ( job200->user_input.perf_counter_flag & (_MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC0_ENABLE|_MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC1_ENABLE) ) { int force_reset = ( job200->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_L2_RESET ) ? 1 : 0; u32 src0 = 0; u32 src1 = 0; if ( job200->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC0_ENABLE ) { src0 = job200->user_input.perf_counter_l2_src0; } if ( job200->user_input.perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_L2_SRC1_ENABLE ) { src1 = job200->user_input.perf_counter_l2_src1; } mali_kernel_l2_cache_set_perf_counters(src0, src1, force_reset); /* will activate and possibly reset counters */ /* Now, retrieve the current values, so we can substract them when the job has completed */ mali_kernel_l2_cache_get_perf_counters(&job200->perf_counter_l2_src0, &job200->perf_counter_l2_val0, &job200->perf_counter_l2_src1, &job200->perf_counter_l2_val1); } #endif } subsystem_flush_mapped_mem_cache(); #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_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_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_number), job200->pid, job200->tid, #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, 0 #endif ); #endif MALI_SUCCESS; }
static void mali_pp_post_process_job(struct mali_pp_core *core) { MALI_ASSERT_GROUP_LOCKED(core->group); if (NULL != core->running_job) { u32 val0 = 0; u32 val1 = 0; #if MALI_TIMELINE_PROFILING_ENABLED int counter_index = COUNTER_FP0_C0 + (2 * core->core_id); #endif if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) { val0 = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE); if (mali_pp_job_get_perf_counter_flag(core->running_job) && _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE && mali_pp_job_get_perf_counter_src0(core->running_job) == core->counter_src0_used) { mali_pp_job_set_perf_counter_value0(core->running_job, core->running_sub_job, val0); } else { mali_pp_job_set_perf_counter_value0(core->running_job, core->running_sub_job, MALI_HW_CORE_INVALID_VALUE); } #if MALI_TIMELINE_PROFILING_ENABLED _mali_osk_profiling_report_hw_counter(counter_index, val0); #endif } if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) { val1 = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE); if (mali_pp_job_get_perf_counter_flag(core->running_job) && _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE && mali_pp_job_get_perf_counter_src1(core->running_job) == core->counter_src1_used) { mali_pp_job_set_perf_counter_value1(core->running_job, core->running_sub_job, val1); } else { mali_pp_job_set_perf_counter_value1(core->running_job, core->running_sub_job, MALI_HW_CORE_INVALID_VALUE); } #if MALI_TIMELINE_PROFILING_ENABLED _mali_osk_profiling_report_hw_counter(counter_index + 1, val1); #endif } #if MALI_TIMELINE_PROFILING_ENABLED _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id), val0, val1, core->counter_src0_used | (core->counter_src1_used << 8), 0, 0); #endif core->running_job = NULL; _mali_osk_timer_del(core->timeout_timer); } }
void mali_pp_job_start(struct mali_pp_core *core, struct mali_pp_job *job, u32 sub_job) { u32 *frame_registers = mali_pp_job_get_frame_registers(job); u32 *wb0_registers = mali_pp_job_get_wb0_registers(job); u32 *wb1_registers = mali_pp_job_get_wb1_registers(job); u32 *wb2_registers = mali_pp_job_get_wb2_registers(job); core->counter_src0_used = core->counter_src0; core->counter_src1_used = core->counter_src1; MALI_DEBUG_ASSERT_POINTER(core); MALI_ASSERT_GROUP_LOCKED(core->group); mali_hw_core_register_write_array_relaxed(&core->hw_core, MALI200_REG_ADDR_FRAME, frame_registers, MALI200_NUM_REGS_FRAME); if (0 != sub_job) { mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_FRAME, mali_pp_job_get_addr_frame(job, sub_job)); mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_STACK, mali_pp_job_get_addr_stack(job, sub_job)); } if (wb0_registers[0]) { mali_hw_core_register_write_array_relaxed(&core->hw_core, MALI200_REG_ADDR_WB0, wb0_registers, MALI200_NUM_REGS_WBx); } if (wb1_registers[0]) { mali_hw_core_register_write_array_relaxed(&core->hw_core, MALI200_REG_ADDR_WB1, wb1_registers, MALI200_NUM_REGS_WBx); } if (wb2_registers[0]) { mali_hw_core_register_write_array_relaxed(&core->hw_core, MALI200_REG_ADDR_WB2, wb2_registers, MALI200_NUM_REGS_WBx); } if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used || MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) { if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used) { mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE); } if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used) { mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE); } } else { u32 perf_counter_flag = mali_pp_job_get_perf_counter_flag(job); if (0 != perf_counter_flag) { if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC0_ENABLE) { core->counter_src0_used = mali_pp_job_get_perf_counter_src0(job); mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_SRC, core->counter_src0_used); mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE); } if (perf_counter_flag & _MALI_PERFORMANCE_COUNTER_FLAG_SRC1_ENABLE) { core->counter_src1_used = mali_pp_job_get_perf_counter_src1(job); mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_SRC, core->counter_src1_used); mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_ENABLE, MALI200_REG_VAL_PERF_CNT_ENABLE); } } } MALI_DEBUG_PRINT(3, ("Mali PP: Starting job 0x%08X part %u/%u on PP core %s\n", job, sub_job + 1, mali_pp_job_get_sub_job_count(job), core->hw_core.description)); _mali_osk_write_mem_barrier(); mali_hw_core_register_write_relaxed(&core->hw_core, MALI200_REG_ADDR_MGMT_CTRL_MGMT, MALI200_REG_VAL_CTRL_MGMT_START_RENDERING); _mali_osk_write_mem_barrier(); _mali_osk_timer_add(core->timeout_timer, _mali_osk_time_mstoticks(mali_max_job_runtime)); core->timeout_job_id = mali_pp_job_get_id(job); #if MALI_TIMELINE_PROFILING_ENABLED _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SINGLE | MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id) | MALI_PROFILING_EVENT_REASON_SINGLE_HW_FLUSH, job->frame_builder_id, job->flush_id, 0, 0, 0); _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START|MALI_PROFILING_MAKE_EVENT_CHANNEL_PP(core->core_id), job->pid, job->tid, 0, 0, 0); #endif core->running_job = job; core->running_sub_job = sub_job; }