--- zzzz-none-000/linux-4.4.60/drivers/cpufreq/cpufreq_stats.c 2017-04-08 07:53:53.000000000 +0000 +++ scorpion-7490-727/linux-4.4.60/drivers/cpufreq/cpufreq_stats.c 2021-02-04 17:41:59.000000000 +0000 @@ -14,6 +14,8 @@ #include #include #include +#include +#include static spinlock_t cpufreq_stats_lock; @@ -22,21 +24,42 @@ unsigned long long last_time; unsigned int max_state; unsigned int state_num; - unsigned int last_index; + int last_index; u64 *time_in_state; + int *tempMax; + int *tempMin; + u32 *tempCount; //maximum: 0xffffffff which + #define TEMPCOUNT_MAX 0xffffffff //represents the overflow state + u64 *tempSum; unsigned int *freq_table; #ifdef CONFIG_CPU_FREQ_STAT_DETAILS unsigned int *trans_table; #endif }; -static int cpufreq_stats_update(struct cpufreq_stats *stats) +static int cpufreq_stats_update(struct cpufreq_stats *stats, int *temp) { unsigned long long cur_time = get_jiffies_64(); spin_lock(&cpufreq_stats_lock); stats->time_in_state[stats->last_index] += cur_time - stats->last_time; stats->last_time = cur_time; + + if(temp) { + if(stats->tempCount[stats->last_index] == 0) { + stats->tempMax[stats->last_index]= *temp; + stats->tempMin[stats->last_index]= *temp; + stats->tempCount[stats->last_index] = 1; + } else { + if(stats->tempMax[stats->last_index] < *temp) { stats->tempMax[stats->last_index] = *temp; } + if(stats->tempMin[stats->last_index] > *temp) { stats->tempMin[stats->last_index] = *temp; } + if( stats->tempCount[stats->last_index] < TEMPCOUNT_MAX ) { stats->tempCount[stats->last_index]++; } //thus TEMPCOUNT_MAX indicates overflow with high probability + } + + if( *temp < 0 ) { *temp=0; } //CPU should never be able to reach negative temperatures. If it does we might consider overclocking for more performance. + stats->tempSum[stats->last_index] += *temp; + } + spin_unlock(&cpufreq_stats_lock); return 0; } @@ -46,18 +69,87 @@ return sprintf(buf, "%d\n", policy->stats->total_trans); } +ssize_t store_time_in_state(struct cpufreq_policy *policy, const char *buf, size_t count) +{ + + struct cpufreq_stats *stats = policy->stats; + + if (!stats) + return -EIO; + + //clear the current statistics + memset( stats->time_in_state, + 0, + stats->max_state * sizeof( *(stats->time_in_state) ) ); + memset( stats->tempMax, + 0, + stats->max_state * sizeof( *(stats->tempMax) ) ); + memset( stats->tempMin, + 0, + stats->max_state * sizeof( *(stats->tempMin) ) ); + memset( stats->tempCount, + 0, + stats->max_state * sizeof( *(stats->tempCount) ) ); + memset( stats->tempSum, + 0, + stats->max_state * sizeof( *(stats->tempSum) ) ); + + return count; +} + + static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf) { struct cpufreq_stats *stats = policy->stats; ssize_t len = 0; int i; + int temp = -1337; + + if (TemperatureSensorGetCurrentTemp(0, NULL, &temp)) { + printk(KERN_ERR "Could not get KPI temperature."); + cpufreq_stats_update(stats, 0); + } else { + cpufreq_stats_update(stats, &temp); + } + + len += sprintf(buf + len, "{Frequency TimeInFrequencyState " + "TemperatureMin(1/10 °) TemperatureSum(1/10 °) " + "TemperatureMeasurements TemperatureMax(1/10 °)}" + "[%d]:\n", stats->state_num); + - cpufreq_stats_update(stats); for (i = 0; i < stats->state_num; i++) { - len += sprintf(buf + len, "%u %llu\n", stats->freq_table[i], - (unsigned long long) - jiffies_64_to_clock_t(stats->time_in_state[i])); + if( stats->tempCount[i] == 0 ) { + len += sprintf(buf + len, "%u %llu none none " + "none none ", stats->freq_table[i], + (unsigned long long) + cputime64_to_clock_t( + stats->time_in_state[i]) + ); + } else if(stats->tempCount[i]==TEMPCOUNT_MAX) { + len += sprintf(buf + len, "%u %llu %d overflow " + "overflow %d ", stats->freq_table[i], + (unsigned long long) + cputime64_to_clock_t( + stats->time_in_state[i]), + stats->tempMin[i], + stats->tempMax[i] + ); + } else { + len += sprintf(buf + len, "%u %llu %d %llu %u %d ", + stats->freq_table[i], + (unsigned long long) + cputime64_to_clock_t(stats->time_in_state[i]), + stats->tempMin[i], + stats->tempSum[i], + stats->tempCount[i], + stats->tempMax[i] + ); + } } + + len += sprintf(buf + len, "\n"); + return len; } @@ -67,6 +159,14 @@ struct cpufreq_stats *stats = policy->stats; ssize_t len = 0; int i, j; + int temp = -1337; + + if (TemperatureSensorGetCurrentTemp(0, NULL, &temp)) { + printk(KERN_ERR "Could not get KPI temperature."); + cpufreq_stats_update(stats, 0); + } else { + cpufreq_stats_update(stats, &temp); + } len += snprintf(buf + len, PAGE_SIZE - len, " From : To\n"); len += snprintf(buf + len, PAGE_SIZE - len, " : "); @@ -106,7 +206,7 @@ #endif cpufreq_freq_attr_ro(total_trans); -cpufreq_freq_attr_ro(time_in_state); +cpufreq_freq_attr_rw(time_in_state); static struct attribute *default_attrs[] = { &total_trans.attr, @@ -189,6 +289,28 @@ #ifdef CONFIG_CPU_FREQ_STAT_DETAILS alloc_size += count * count * sizeof(int); #endif + stats->max_state = count; + + //add space for the current temperature statistics + + alloc_size += count * sizeof( *(stats->tempMax) ); + alloc_size += count * sizeof( *(stats->tempSum) ); + alloc_size += count * sizeof( *(stats->tempMin) ); + alloc_size += count * sizeof( *(stats->tempCount) ); + + stats->time_in_state = kzalloc(alloc_size, GFP_KERNEL); + if (!stats->time_in_state) { + ret = -ENOMEM; + goto free_stat; + } + + //poke current temperature statistics out of the allocated chunk + stats->tempMax = (int *)(stats->time_in_state + count); + stats->tempSum = (u64 *)(stats->tempMax + count); + stats->tempMin = (int *)(stats->tempSum + count); + stats->tempCount = (u32 *)(stats->tempMin + count); + + stats->freq_table = (unsigned int *)(stats->tempCount + count); /* Allocate memory for time_in_state/freq_table/trans_table in one go */ stats->time_in_state = kzalloc(alloc_size, GFP_KERNEL); @@ -264,12 +386,14 @@ struct cpufreq_policy *policy = cpufreq_cpu_get(freq->cpu); struct cpufreq_stats *stats; int old_index, new_index; + int temp = -1337; if (!policy) { pr_err("%s: No policy found\n", __func__); return 0; } + if (val != CPUFREQ_POSTCHANGE) goto put_policy; @@ -280,21 +404,33 @@ stats = policy->stats; + if (val == CPUFREQ_NOCHANGE) { + if (TemperatureSensorGetCurrentTemp(0, NULL, &temp)) { + cpufreq_stats_update(stats, 0); + } else { + cpufreq_stats_update(stats, &temp); + } + return 0; + } + old_index = stats->last_index; new_index = freq_table_get_index(stats, freq->new); - /* We can't do stats->time_in_state[-1]= .. */ - if (old_index == -1 || new_index == -1) - goto put_policy; - if (old_index == new_index) goto put_policy; - cpufreq_stats_update(stats); + if (TemperatureSensorGetCurrentTemp(0, NULL, &temp)) { + cpufreq_stats_update(stats, 0); + } else { + cpufreq_stats_update(stats, &temp); + } stats->last_index = new_index; #ifdef CONFIG_CPU_FREQ_STAT_DETAILS - stats->trans_table[old_index * stats->max_state + new_index]++; + /* From old_index ... to new_index */ + if (old_index >= 0 && new_index >= 0) { + stat->trans_table[old_index * stat->max_state + new_index]++; + } #endif stats->total_trans++;