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) {