static ssize_t gp_all_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id)
{
	char buf[64];
	long val;
	int ret;
	u32 num_groups;
	int i;

	if (cnt >= sizeof(buf))
	{
		return -EINVAL;
	}

	if (copy_from_user(&buf, ubuf, cnt))
	{
		return -EFAULT;
	}

	buf[cnt] = 0;

	ret = strict_strtol(buf, 10, &val);
	if (ret < 0)
	{
		return ret;
	}

	if (val < 0)
	{
		/* any negative input will disable counter */
		val = MALI_HW_CORE_NO_COUNTER;
	}

	num_groups = mali_group_get_glob_num_groups();
	for (i = 0; i < num_groups; i++)
	{
		struct mali_group *group = mali_group_get_glob_group(i);

		struct mali_gp_core *gp_core = mali_group_get_gp_core(group);
		if (NULL != gp_core)
		{
			if (0 == src_id)
			{
				if (MALI_TRUE != mali_gp_job_set_gp_counter_src0((u32)val))
				{
					return 0;
				}
			}
			else
			{
				if (MALI_TRUE != mali_gp_job_set_gp_counter_src1((u32)val))
				{
					return 0;
				}
			}
		}
	}

	*gpos += cnt;
	return cnt;
}
static ssize_t profiling_counter_src_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
{
	u32 is_pp = PRIVATE_DATA_COUNTER_IS_PP((uintptr_t)filp->private_data);
	u32 src_id = PRIVATE_DATA_COUNTER_GET_SRC((uintptr_t)filp->private_data);
	mali_bool is_sub_job = PRIVATE_DATA_COUNTER_IS_SUB_JOB((uintptr_t)filp->private_data);
	u32 sub_job = PRIVATE_DATA_COUNTER_GET_SUB_JOB((uintptr_t)filp->private_data);
	char buf[64];
	long val;
	int ret;

	if (cnt >= sizeof(buf)) {
		return -EINVAL;
	}

	if (copy_from_user(&buf, ubuf, cnt)) {
		return -EFAULT;
	}

	buf[cnt] = 0;

	ret = kstrtol(buf, 10, &val);
	if (ret < 0) {
		return ret;
	}

	if (val < 0) {
		/* any negative input will disable counter */
		val = MALI_HW_CORE_NO_COUNTER;
	}

	if (MALI_TRUE == is_pp) {
		/* PP counter */
		if (MALI_TRUE == is_sub_job) {
			/* Set counter for a particular sub job */
			if (0 == src_id) {
				mali_pp_job_set_pp_counter_sub_job_src0(sub_job, (u32)val);
			} else {
				mali_pp_job_set_pp_counter_sub_job_src1(sub_job, (u32)val);
			}
		} else {
			/* Set default counter for all PP sub jobs */
			if (0 == src_id) {
				mali_pp_job_set_pp_counter_global_src0((u32)val);
			} else {
				mali_pp_job_set_pp_counter_global_src1((u32)val);
			}
		}
	} else {
		/* GP counter */
		if (0 == src_id) {
			mali_gp_job_set_gp_counter_src0((u32)val);
		} else {
			mali_gp_job_set_gp_counter_src1((u32)val);
		}
	}

	*ppos += cnt;
	return cnt;
}
/**
 * Called by gator.ko to set HW counters
 *
 * @param counter_id The counter ID.
 * @param event_id Event ID that the counter should count (HW counter value from TRM).
 *
 * @return 1 on success, 0 on failure.
 */
int _mali_profiling_set_event(u32 counter_id, s32 event_id)
{
	if (COUNTER_VP_0_C0 == counter_id)
	{
		if (MALI_TRUE == mali_gp_job_set_gp_counter_src0(event_id))
		{
			return 1;
		}
	}

	if (COUNTER_VP_0_C1 == counter_id)
	{
		if (MALI_TRUE == mali_gp_job_set_gp_counter_src1(event_id))
		{
			return 1;
		}
	}

	if (COUNTER_FP_0_C0 == counter_id)
	{
		if (MALI_TRUE == mali_pp_job_set_pp_counter_src0(event_id))
		{
			return 1;
		}
	}

	if (COUNTER_FP_0_C1 == counter_id)
	{
		if (MALI_TRUE == mali_pp_job_set_pp_counter_src1(event_id))
		{
			return 1;
		}
	}

	if (COUNTER_L2_0_C0 <= counter_id && COUNTER_L2_2_C1 >= counter_id)
	{
		u32 core_id = (counter_id - COUNTER_L2_0_C0) >> 1;
		struct mali_l2_cache_core* l2_cache_core = mali_l2_cache_core_get_glob_l2_core(core_id);

		if (NULL != l2_cache_core)
		{
			u32 counter_src = (counter_id - COUNTER_L2_0_C0) & 1;
			if (0 == counter_src)
			{
				if (MALI_TRUE == mali_l2_cache_core_set_counter_src0(l2_cache_core, event_id))
				{
					return 1;
				}
			}
			else
			{
				if (MALI_TRUE == mali_l2_cache_core_set_counter_src1(l2_cache_core, event_id))
				{
					return 1;
				}
			}
		}
	}
static ssize_t gp_gpx_counter_srcx_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *gpos, u32 src_id)
{
	char buf[64];
	long val;
	int ret;

	if (cnt >= sizeof(buf))
	{
		return -EINVAL;
	}

	if (copy_from_user(&buf, ubuf, cnt))
	{
		return -EFAULT;
	}

	buf[cnt] = 0;

	ret = strict_strtol(buf, 10, &val);
	if (ret < 0)
	{
		return ret;
	}

	if (val < 0)
	{
		/* any negative input will disable counter */
		val = MALI_HW_CORE_NO_COUNTER;
	}

	if (0 == src_id)
	{
		if (MALI_TRUE != mali_gp_job_set_gp_counter_src0((u32)val))
		{
			return 0;
		}
	}
	else
	{
		if (MALI_TRUE != mali_gp_job_set_gp_counter_src1((u32)val))
		{
			return 0;
		}
	}

	*gpos += cnt;
	return cnt;
}
/**
 * Called by gator.ko to set HW counters
 *
 * @param counter_id The counter ID.
 * @param event_id Event ID that the counter should count (HW counter value from TRM).
 *
 * @return 1 on success, 0 on failure.
 */
int _mali_profiling_set_event(u32 counter_id, s32 event_id)
{
	if (COUNTER_VP_0_C0 == counter_id) {
		mali_gp_job_set_gp_counter_src0(event_id);
	} else if (COUNTER_VP_0_C1 == counter_id) {
		mali_gp_job_set_gp_counter_src1(event_id);
	} else if (COUNTER_FP_0_C0 <= counter_id && COUNTER_FP_7_C1 >= counter_id) {
		/*
		 * Two compatibility notes for this function:
		 *
		 * 1) Previously the DDK allowed per core counters.
		 *
		 *    This did not make much sense on Mali-450 with the "virtual PP core" concept,
		 *    so this option was removed, and only the same pair of HW counters was allowed on all cores,
		 *    beginning with r3p2 release.
		 *
		 *    Starting with r4p0, it is now possible to set different HW counters for the different sub jobs.
		 *    This should be almost the same, since sub job 0 is designed to run on core 0,
		 *    sub job 1 on core 1, and so on.
		 *
		 *    The scheduling of PP sub jobs is not predictable, and this often led to situations where core 0 ran 2
		 *    sub jobs, while for instance core 1 ran zero. Having the counters set per sub job would thus increase
		 *    the predictability of the returned data (as you would be guaranteed data for all the selected HW counters).
		 *
		 *    PS: Core scaling needs to be disabled in order to use this reliably (goes for both solutions).
		 *
		 *    The framework/#defines with Gator still indicates that the counter is for a particular core,
		 *    but this is internally used as a sub job ID instead (no translation needed).
		 *
		 *  2) Global/default vs per sub job counters
		 *
		 *     Releases before r3p2 had only per PP core counters.
		 *     r3p2 releases had only one set of default/global counters which applied to all PP cores
		 *     Starting with r4p0, we have both a set of default/global counters,
		 *     and individual counters per sub job (equal to per core).
		 *
		 *     To keep compatibility with Gator/DS-5/streamline, the following scheme is used:
		 *
		 *     r3p2 release; only counters set for core 0 is handled,
		 *     this is applied as the default/global set of counters, and will thus affect all cores.
		 *
		 *     r4p0 release; counters set for core 0 is applied as both the global/default set of counters,
		 *     and counters for sub job 0.
		 *     Counters set for core 1-7 is only applied for the corresponding sub job.
		 *
		 *     This should allow the DS-5/Streamline GUI to have a simple mode where it only allows setting the
		 *     values for core 0, and thus this will be applied to all PP sub jobs/cores.
		 *     Advanced mode will also be supported, where individual pairs of HW counters can be selected.
		 *
		 *     The GUI will (until it is updated) still refer to cores instead of sub jobs, but this is probably
		 *     something we can live with!
		 *
		 *     Mali-450 note: Each job is not divided into a deterministic number of sub jobs, as the HW DLBU
		 *     automatically distributes the load between whatever number of cores is available at this particular time.
		 *     A normal PP job on Mali-450 is thus considered a single (virtual) job, and it will thus only be possible
		 *     to use a single pair of HW counters (even if the job ran on multiple PP cores).
		 *     In other words, only the global/default pair of PP HW counters will be used for normal Mali-450 jobs.
		 */
		u32 sub_job = (counter_id - COUNTER_FP_0_C0) >> 1;
		u32 counter_src = (counter_id - COUNTER_FP_0_C0) & 1;
		if (0 == counter_src) {
			mali_pp_job_set_pp_counter_sub_job_src0(sub_job, event_id);
			if (0 == sub_job) {
				mali_pp_job_set_pp_counter_global_src0(event_id);
			}
		} else {
			mali_pp_job_set_pp_counter_sub_job_src1(sub_job, event_id);
			if (0 == sub_job) {
				mali_pp_job_set_pp_counter_global_src1(event_id);
			}
		}
	} else if (COUNTER_L2_0_C0 <= counter_id && COUNTER_L2_2_C1 >= counter_id) {