--- zzzz-none-000/linux-4.1.38/drivers/cpufreq/cpufreq_stats.c 2017-01-18 18:48:06.000000000 +0000 +++ bcm63-7582-715/linux-4.1.38/drivers/cpufreq/cpufreq_stats.c 2020-11-25 10:06:48.000000000 +0000 @@ -14,6 +14,7 @@ #include #include #include +#include static spinlock_t cpufreq_stats_lock; @@ -24,19 +25,53 @@ unsigned int state_num; unsigned 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 +81,70 @@ 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; + + // clear the current statsistics + 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; - cpufreq_stats_update(stats); + if (TemperatureSensorGetCurrentTemp(0, NULL, &temp) != 0) { + pr_err("Could not get CPU 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); 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)jiffies_64_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)jiffies_64_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)jiffies_64_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; } @@ -106,7 +193,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, @@ -190,12 +277,26 @@ alloc_size += count * count * sizeof(int); #endif + //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)); + /* Allocate memory for time_in_state/freq_table/trans_table in one go */ stats->time_in_state = kzalloc(alloc_size, GFP_KERNEL); if (!stats->time_in_state) goto free_stat; - stats->freq_table = (unsigned int *)(stats->time_in_state + count); + //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); #ifdef CONFIG_CPU_FREQ_STAT_DETAILS stats->trans_table = stats->freq_table + count; @@ -264,15 +365,13 @@ 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; - if (!policy->stats) { pr_debug("%s: No stats found\n", __func__); goto put_policy; @@ -280,6 +379,18 @@ stats = policy->stats; + if (val == CPUFREQ_NOCHANGE) { + if (TemperatureSensorGetCurrentTemp(0, NULL, &temp) != 0) { + cpufreq_stats_update(stats, 0); + } else { + cpufreq_stats_update(stats, &temp); + } + return 0; + } + + if (val != CPUFREQ_POSTCHANGE) + goto put_policy; + old_index = stats->last_index; new_index = freq_table_get_index(stats, freq->new); @@ -290,7 +401,11 @@ if (old_index == new_index) goto put_policy; - cpufreq_stats_update(stats); + if (TemperatureSensorGetCurrentTemp(0, NULL, &temp) != 0) { + cpufreq_stats_update(stats, 0); + } else { + cpufreq_stats_update(stats, &temp); + } stats->last_index = new_index; #ifdef CONFIG_CPU_FREQ_STAT_DETAILS