devfreq: msm_adreno_tz: Import Sony Changes

Signed-off-by: Sorayukii <sorayukii69@gmail.com>
This commit is contained in:
Sorayukii 2026-02-15 05:29:38 +07:00
commit 84b9e8c0d8

View file

@ -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: