From 84b9e8c0d8765b52e99278bbc4675af2dda64aab Mon Sep 17 00:00:00 2001 From: Sorayukii Date: Sun, 15 Feb 2026 05:29:38 +0700 Subject: [PATCH] devfreq: msm_adreno_tz: Import Sony Changes Signed-off-by: Sorayukii --- drivers/devfreq/governor_msm_adreno_tz.c | 231 ++++++++++++++++++++++- 1 file changed, 229 insertions(+), 2 deletions(-) diff --git a/drivers/devfreq/governor_msm_adreno_tz.c b/drivers/devfreq/governor_msm_adreno_tz.c index 4937801106cb..54b2e61f6b3d 100644 --- a/drivers/devfreq/governor_msm_adreno_tz.c +++ b/drivers/devfreq/governor_msm_adreno_tz.c @@ -26,6 +26,7 @@ static DEFINE_SPINLOCK(tz_lock); static DEFINE_SPINLOCK(sample_lock); +static DEFINE_SPINLOCK(sample_load_lock); static DEFINE_SPINLOCK(suspend_lock); /* * FLOOR is 5msec to capture up to 3 re-draws @@ -58,9 +59,26 @@ static DEFINE_SPINLOCK(suspend_lock); #define TAG "msm_adreno_tz: " -static u64 suspend_time; -static u64 suspend_start; +#define USEC_PER_MINUTE (1*60*1000*1000) +#define NMAX (15*60*60+1) + +struct gpu_load_data { + unsigned long total_time; + unsigned long busy_time; + u64 update_time; +}; + +struct gpu_load_queue { + struct gpu_load_data *gpu_load; + int head; + int tail; +}; + +static u64 suspend_time, suspend_time_idd; +static u64 suspend_start, suspend_start_idd; static unsigned long acc_total, acc_relative_busy; +static unsigned long gpu_load_total, gpu_load_rel_busy; +static struct gpu_load_queue *gpu_load_infos; static struct msm_adreno_extended_profile *partner_gpu_profile; static void do_partner_start_event(struct work_struct *work); @@ -88,6 +106,21 @@ u64 suspend_time_ms(void) return time_diff; } +u64 suspend_time_ms_idd(void) +{ + u64 suspend_sampling_time; + u64 time_diff = 0; + + if (suspend_start_idd == 0) + return 0; + + suspend_sampling_time = (u64)ktime_to_ms(ktime_get()); + time_diff = suspend_sampling_time - suspend_start_idd; + /* Update the suspend_start sample again */ + suspend_start_idd = suspend_sampling_time; + return time_diff; +} + static ssize_t gpu_load_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -109,6 +142,135 @@ static ssize_t gpu_load_show(struct device *dev, return snprintf(buf, PAGE_SIZE, "%lu\n", sysfs_busy_perc); } +int findItem(int head, int tail, u64 refTime) +{ + int low = head, high = tail, middle; + u64 update_time; + + while (low < high) { + middle = (low + high) / 2; + update_time = + gpu_load_infos->gpu_load[middle % NMAX].update_time; + + if (update_time <= refTime) + low = middle + 1; + else if (update_time > refTime) + high = middle - 1; + } + + update_time = gpu_load_infos->gpu_load[low % NMAX].update_time; + if (update_time > refTime) + low = low - 1; + + if (low < tail) { + u64 l = gpu_load_infos->gpu_load[low % NMAX].update_time; + u64 r = gpu_load_infos->gpu_load[(low+1) % NMAX].update_time; + + if (r - refTime < refTime - l) + low = low + 1; + } + return low % NMAX; +} + +unsigned long cal_gpu_load(u64 current_time, u64 update_time, + u64 begin_time, int minutes) +{ + unsigned long sysfs_busy_perc; + unsigned long tmp_act_relative_busy, tmp_act_total; + int tail = gpu_load_infos->tail, head = gpu_load_infos->head; + + if (current_time - update_time > minutes * USEC_PER_MINUTE) { + sysfs_busy_perc = 0; + } else { + int tmpIndex = head; + + if (current_time - begin_time <= minutes * USEC_PER_MINUTE) { + tmpIndex = head; + } else { + u64 begin = current_time - minutes * USEC_PER_MINUTE; + int tmpTail = (tail < head) ? tail + NMAX : tail; + + tmpIndex = findItem(head, tmpTail-1, begin); + } + + tmp_act_relative_busy = + gpu_load_infos->gpu_load[tail-1].busy_time - + gpu_load_infos->gpu_load[tmpIndex].busy_time; + + tmp_act_total = current_time - + gpu_load_infos->gpu_load[tmpIndex].update_time; + + sysfs_busy_perc = (tmp_act_relative_busy * 100 * 10) / + tmp_act_total; + } + return sysfs_busy_perc; +} + +void convert_int_to_string(unsigned long perc, char *str, unsigned int size) +{ + char low[6] = "0"; + char mid[] = "."; + + snprintf(str, sizeof(low), "%lu", (perc / 10)); + snprintf(low, sizeof(low), "%lu", (perc % 10)); + strlcat(str, mid, size); + strlcat(str, low, size); +} + +static ssize_t gpu_period_load_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + unsigned long sysfs_busy_perc[3]; + int tail, head; + char load[3][6] = {"0", "0", "0"}; + int i; + unsigned int size; + spin_lock(&sample_load_lock); + tail = gpu_load_infos->tail; + head = gpu_load_infos->head; + + if (tail == head) { + sysfs_busy_perc[0] = 0; + sysfs_busy_perc[1] = 0; + sysfs_busy_perc[2] = 0; + } else { + u64 current_time = (u64)ktime_to_us(ktime_get()); + u64 update_time = gpu_load_infos->gpu_load[tail-1].update_time; + u64 begin_time = gpu_load_infos->gpu_load[head].update_time; + + sysfs_busy_perc[0] = cal_gpu_load(current_time, + update_time, begin_time, 1); + sysfs_busy_perc[1] = cal_gpu_load(current_time, + update_time, begin_time, 5); + sysfs_busy_perc[2] = cal_gpu_load(current_time, + update_time, begin_time, 15); + } + for (i = 0; i < 3; i++) { + size = sizeof(load[i]); + convert_int_to_string(sysfs_busy_perc[i], load[i], size); + } + + spin_unlock(&sample_load_lock); + return snprintf(buf, PAGE_SIZE, "%s %s %s\n", + load[0], + load[1], + load[2] + ); +} + +static ssize_t gpu_load_idd_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + unsigned long busy, total; + spin_lock(&sample_load_lock); + busy = gpu_load_rel_busy; + total = gpu_load_total; + spin_unlock(&sample_load_lock); + return snprintf(buf, PAGE_SIZE, "%lu %lu\n", busy, total); +} + /* * Returns the time in ms for which gpu was in suspend state * since last time the entry is read. @@ -134,7 +296,30 @@ static ssize_t suspend_time_show(struct device *dev, return snprintf(buf, PAGE_SIZE, "%llu\n", time_diff); } +static ssize_t suspend_time_idd_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + u64 time_diff = 0; + + spin_lock(&suspend_lock); + time_diff = suspend_time_ms_idd(); + /* + * Adding the previous suspend time also as the gpu + * can go and come out of suspend states in between + * reads also and we should have the total suspend + * since last read. + */ + suspend_time_idd += time_diff; + spin_unlock(&suspend_lock); + + return snprintf(buf, PAGE_SIZE, "%llu\n", suspend_time_idd); +} + static DEVICE_ATTR(gpu_load, 0444, gpu_load_show, NULL); +static DEVICE_ATTR(gpu_period_load, 0444, gpu_period_load_show, NULL); +static DEVICE_ATTR(gpu_load_idd, 0444, gpu_load_idd_show, NULL); +static DEVICE_ATTR(gpu_suspend_idd, 0444, suspend_time_idd_show, NULL); static DEVICE_ATTR(suspend_time, 0444, suspend_time_show, @@ -142,10 +327,30 @@ static DEVICE_ATTR(suspend_time, 0444, static const struct device_attribute *adreno_tz_attr_list[] = { &dev_attr_gpu_load, + &dev_attr_gpu_period_load, + &dev_attr_gpu_load_idd, + &dev_attr_gpu_suspend_idd, &dev_attr_suspend_time, NULL }; +void store_work_load(unsigned long gpu_load_total, unsigned long gpu_load_busy) +{ + /* Queue item to gpu_load_queue */ + int index = gpu_load_infos->tail; + int head = gpu_load_infos->head; + + gpu_load_infos->gpu_load[index].total_time = gpu_load_total; + gpu_load_infos->gpu_load[index].busy_time = gpu_load_busy; + gpu_load_infos->gpu_load[index].update_time = + (u64)ktime_to_us(ktime_get()); + + if ((index + 1) % NMAX == head) + gpu_load_infos->head = (head + 1) % NMAX; + + gpu_load_infos->tail = (index + 1) % NMAX; +} + void compute_work_load(struct devfreq_dev_status *stats, struct devfreq_msm_adreno_tz_data *priv, struct devfreq *devfreq) @@ -164,6 +369,15 @@ void compute_work_load(struct devfreq_dev_status *stats, acc_relative_busy += busy; spin_unlock(&sample_lock); + + spin_lock(&sample_load_lock); + gpu_load_total += stats->total_time; + gpu_load_rel_busy += (stats->busy_time * stats->current_frequency) / + devfreq->profile->freq_table[0]; + + store_work_load(gpu_load_total, gpu_load_rel_busy); + + spin_unlock(&sample_load_lock); } /* Trap into the TrustZone, and call funcs there. */ @@ -236,6 +450,14 @@ static int __secure_tz_update_entry3(unsigned int *scm_data, u32 size_scm_data, return ret; } +static void tz_init_gpuloadinfos(void) +{ + gpu_load_infos = kzalloc(sizeof(struct gpu_load_queue), GFP_KERNEL); + gpu_load_infos->head = gpu_load_infos->tail = 0; + gpu_load_infos->gpu_load = + kcalloc(NMAX, sizeof(struct gpu_load_data), GFP_KERNEL); +} + static int tz_init_ca(struct devfreq_msm_adreno_tz_data *priv) { unsigned int tz_ca_data[2]; @@ -275,6 +497,8 @@ static int tz_init(struct devfreq_msm_adreno_tz_data *priv, unsigned int *version, u32 size_version) { int ret; + + tz_init_gpuloadinfos(); /* Make sure all CMD IDs are avaialble */ if (scm_is_call_available(SCM_SVC_DCVS, TZ_INIT_ID)) { ret = scm_call(SCM_SVC_DCVS, TZ_INIT_ID, tz_pwrlevels, @@ -575,6 +799,7 @@ static int tz_handler(struct devfreq *devfreq, unsigned int event, void *data) spin_lock(&suspend_lock); /* Collect the start sample for suspend time */ suspend_start = (u64)ktime_to_ms(ktime_get()); + suspend_start_idd = suspend_start; spin_unlock(&suspend_lock); } break; @@ -582,8 +807,10 @@ static int tz_handler(struct devfreq *devfreq, unsigned int event, void *data) case DEVFREQ_GOV_RESUME: spin_lock(&suspend_lock); suspend_time += suspend_time_ms(); + suspend_time_idd += suspend_time_ms_idd(); /* Reset the suspend_start when gpu resumes */ suspend_start = 0; + suspend_start_idd = 0; spin_unlock(&suspend_lock); /* fallthrough */ case DEVFREQ_GOV_INTERVAL: