/* Can NOT run in atomic context */
_mali_osk_errcode_t _mali_osk_pm_dev_ref_get_sync(void)
{
#ifdef CONFIG_PM_RUNTIME
    int err;
    MALI_DEBUG_ASSERT_POINTER(mali_platform_device);
    err = pm_runtime_get_sync(&(mali_platform_device->dev));
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
    pm_runtime_mark_last_busy(&(mali_platform_device->dev));
#endif
    if (0 > err) {
        MALI_PRINT_ERROR(("Mali OSK PM: pm_runtime_get_sync() returned error code %d\n", err));
        return _MALI_OSK_ERR_FAULT;
    }
#else
    _mali_osk_mutex_wait(mtk_pm_lock);
    mali_platform_power_mode_change(MALI_POWER_MODE_ON);
    if(_mali_osk_atomic_read(&mtk_mali_suspend_called))
    {	      		
        mali_pm_runtime_resume();
        _mali_osk_atomic_dec(&mtk_mali_suspend_called);
    }
    _mali_osk_atomic_inc(&mtk_mali_pm_ref_count);
    _mali_osk_mutex_signal(mtk_pm_lock);
#endif
    return _MALI_OSK_ERR_OK;
}
示例#2
0
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 MALI_TRACEPOINTS_ENABLED
	_mali_osk_profiling_add_event(event_id, data0);
#endif

	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;
}
示例#3
0
void _mali_ukk_pmm_event_message( _mali_uk_pmm_message_s *args )
{
	_mali_pmm_internal_state_t *pmm = GET_PMM_STATE_PTR;
	_mali_osk_notification_t *msg;
	mali_pmm_message_t *event;
	MALI_DEBUG_ASSERT_POINTER(pmm);
	MALI_DEBUG_ASSERT_POINTER(args);

	MALIPMM_DEBUG_PRINT( ("PMM: sending message\n") );

#if MALI_PMM_TRACE && MALI_PMM_TRACE_SENT_EVENTS
	_mali_pmm_trace_event_message( args, MALI_FALSE );
#endif

	msg = _mali_osk_notification_create( MALI_PMM_NOTIFICATION_TYPE, sizeof( mali_pmm_message_t ) );

	if( msg )
	{
		event = (mali_pmm_message_t *)msg->result_buffer;
		event->id = args->id;
		event->ts = _mali_osk_time_tickcount();
		event->data = args->data;
		
		_mali_osk_atomic_inc( &(pmm->messages_queued) );

		if( args->id > MALI_PMM_EVENT_INTERNALS )
		{
			/* Internal PMM message */
			_mali_osk_notification_queue_send( pmm->iqueue, msg );
			#if MALI_PMM_TRACE
				pmm->imessages_sent++;
			#endif
		}
		else
		{
			/* Real event */
			_mali_osk_notification_queue_send( pmm->queue, msg );
			#if MALI_PMM_TRACE
				pmm->messages_sent++;
			#endif
		}
	}
	else
	{
		MALI_PRINT_ERROR( ("PMM: Could not send message %d", args->id) );
		/* Make note of this OOM - which has caused a missed event */
		pmm->missed++;
	}
	
	/* Schedule time to look at the event or the fact we couldn't create an event */
	_mali_osk_irq_schedulework( pmm->irq );
}
static void MTK_mali_bottom_half_pm_suspend ( struct work_struct *work )
{    
    _mali_osk_mutex_wait(mtk_pm_lock);
    if((_mali_osk_atomic_read(&mtk_mali_pm_ref_count) == 0) &&
       (_mali_osk_atomic_read(&mtk_mali_suspend_called) == 0))
    {
        if (MALI_TRUE == mali_pm_runtime_suspend())
        {
            _mali_osk_atomic_inc(&mtk_mali_suspend_called);
            mali_platform_power_mode_change(MALI_POWER_MODE_DEEP_SLEEP);
        }
    }
    _mali_osk_mutex_signal(mtk_pm_lock);
}
示例#5
0
static void mali_bottom_half_pm ( struct work_struct *work )
{
    _mali_osk_lock_wait(pm_lock, _MALI_OSK_LOCKMODE_RW);     
     
    if((_mali_osk_atomic_read(&mali_pm_ref_count) == 0) &&
       (_mali_osk_atomic_read(&mali_suspend_called) == 0))
    {
        mali_pm_runtime_suspend();
        _mali_osk_atomic_inc(&mali_suspend_called);
        mali_platform_power_mode_change(MALI_POWER_MODE_DEEP_SLEEP);        
    }
     
    _mali_osk_lock_signal(pm_lock, _MALI_OSK_LOCKMODE_RW);
}
示例#6
0
mali_scheduler_mask mali_soft_job_system_timeout_job(struct mali_soft_job *job)
{
	mali_scheduler_mask schedule_mask = MALI_SCHEDULER_MASK_EMPTY;

	MALI_DEBUG_ASSERT_POINTER(job);
	MALI_DEBUG_ASSERT_POINTER(job->system);
	MALI_DEBUG_ASSERT_POINTER(job->system->session);
	MALI_DEBUG_ASSERT(MALI_TRUE == job->activated);

	MALI_DEBUG_PRINT(4, ("Mali Soft Job: Timeline timeout for soft job %u (0x%08X).\n", job->id, job));

	mali_soft_job_system_lock(job->system);

	MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_STARTED  == job->state ||
			  MALI_SOFT_JOB_STATE_SIGNALED == job->state);

	if (unlikely(job->system->session->is_aborting)) {
		/* The session is aborting.  This job will be released and destroyed by @ref
		 * mali_soft_job_system_abort(). */
		mali_soft_job_system_unlock(job->system);

		return MALI_SCHEDULER_MASK_EMPTY;
	}

	if (MALI_SOFT_JOB_STATE_STARTED != job->state) {
		MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_SIGNALED == job->state);

		/* The job is about to be signaled, ignore timeout. */
		MALI_DEBUG_PRINT(4, ("Mali Soft Job: Timeout on soft job %u (0x%08X) in signaled state.\n", job->id, job));
		mali_soft_job_system_unlock(job->system);
		return schedule_mask;
	}

	MALI_DEBUG_ASSERT(MALI_SOFT_JOB_STATE_STARTED == job->state);

	job->state = MALI_SOFT_JOB_STATE_TIMED_OUT;
	_mali_osk_atomic_inc(&job->refcount);

	mali_soft_job_system_unlock(job->system);

	schedule_mask = mali_timeline_tracker_release(&job->tracker);

	mali_soft_job_destroy(job);

	return schedule_mask;
}
/* Can NOT run in atomic context */
_mali_osk_errcode_t _mali_osk_pm_dev_ref_add(void)
{
#ifdef CONFIG_PM_RUNTIME
	int err;
	MALI_DEBUG_ASSERT_POINTER(mali_platform_device);
	err = pm_runtime_get_sync(&(mali_platform_device->dev));
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
	pm_runtime_mark_last_busy(&(mali_platform_device->dev));
#endif
	if (0 > err) {
		MALI_PRINT_ERROR(("Mali OSK PM: pm_runtime_get_sync() returned error code %d\n", err));
		return _MALI_OSK_ERR_FAULT;
	}
	_mali_osk_atomic_inc(&mali_pm_ref_count);
	MALI_DEBUG_PRINT(4, ("Mali OSK PM: Power ref taken (%u)\n", _mali_osk_atomic_read(&mali_pm_ref_count)));
#endif
	return _MALI_OSK_ERR_OK;
}
void mali_pp_job_set_pp_counter_sub_job_src1(u32 sub_job, u32 counter)
{
	MALI_DEBUG_ASSERT(sub_job < _MALI_PP_MAX_SUB_JOBS);

	if (MALI_HW_CORE_NO_COUNTER == pp_counter_per_sub_job_src1[sub_job]) {
		/* increment count since existing counter was disabled */
		_mali_osk_atomic_inc(&pp_counter_per_sub_job_count);
	}

	if (MALI_HW_CORE_NO_COUNTER == counter) {
		/* decrement count since new counter is disabled */
		_mali_osk_atomic_dec(&pp_counter_per_sub_job_count);
	}

	/* PS: A change from MALI_HW_CORE_NO_COUNTER to MALI_HW_CORE_NO_COUNTER will inc and dec, result will be 0 change */

	pp_counter_per_sub_job_src1[sub_job] = counter;
}
/* Can run in atomic context */
_mali_osk_errcode_t _mali_osk_pm_dev_ref_get_async(void)
{
#ifdef CONFIG_PM_RUNTIME
    int err;
    MALI_DEBUG_ASSERT_POINTER(mali_platform_device);
    err = pm_runtime_get(&(mali_platform_device->dev));
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
    pm_runtime_mark_last_busy(&(mali_platform_device->dev));
#endif
    if (0 > err && -EINPROGRESS != err) {
        MALI_PRINT_ERROR(("Mali OSK PM: pm_runtime_get() returned error code %d\n", err));
        return _MALI_OSK_ERR_FAULT;
    }
#else
    _mali_osk_atomic_inc(&mtk_mali_pm_ref_count);
    queue_work(mtk_mali_pm_wq2, &mtk_mali_pm_wq_work_handle2);
#endif
    return _MALI_OSK_ERR_OK;
}
inline void _mali_osk_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;
    }

    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);
}
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;
}