diff options
Diffstat (limited to 'drivers/cpufreq/cpufreq_stats.c')
-rw-r--r-- | drivers/cpufreq/cpufreq_stats.c | 44 |
1 files changed, 25 insertions, 19 deletions
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index e1fe0a945639..5d7bf9b1dfc5 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c | |||
@@ -164,12 +164,13 @@ static void cpufreq_stats_free_table(unsigned int cpu) | |||
164 | 164 | ||
165 | static int __cpufreq_stats_create_table(struct cpufreq_policy *policy) | 165 | static int __cpufreq_stats_create_table(struct cpufreq_policy *policy) |
166 | { | 166 | { |
167 | unsigned int i, count = 0, ret = 0; | 167 | unsigned int i = 0, count = 0, ret = -ENOMEM; |
168 | struct cpufreq_stats *stats; | 168 | struct cpufreq_stats *stats; |
169 | unsigned int alloc_size; | 169 | unsigned int alloc_size; |
170 | unsigned int cpu = policy->cpu; | 170 | unsigned int cpu = policy->cpu; |
171 | struct cpufreq_frequency_table *pos, *table; | 171 | struct cpufreq_frequency_table *pos, *table; |
172 | 172 | ||
173 | /* We need cpufreq table for creating stats table */ | ||
173 | table = cpufreq_frequency_get_table(cpu); | 174 | table = cpufreq_frequency_get_table(cpu); |
174 | if (unlikely(!table)) | 175 | if (unlikely(!table)) |
175 | return 0; | 176 | return 0; |
@@ -179,15 +180,10 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy) | |||
179 | return -EEXIST; | 180 | return -EEXIST; |
180 | 181 | ||
181 | stats = kzalloc(sizeof(*stats), GFP_KERNEL); | 182 | stats = kzalloc(sizeof(*stats), GFP_KERNEL); |
182 | if ((stats) == NULL) | 183 | if (!stats) |
183 | return -ENOMEM; | 184 | return -ENOMEM; |
184 | 185 | ||
185 | ret = sysfs_create_group(&policy->kobj, &stats_attr_group); | 186 | /* Find total allocation size */ |
186 | if (ret) | ||
187 | goto error_out; | ||
188 | |||
189 | policy->stats = stats; | ||
190 | |||
191 | cpufreq_for_each_valid_entry(pos, table) | 187 | cpufreq_for_each_valid_entry(pos, table) |
192 | count++; | 188 | count++; |
193 | 189 | ||
@@ -196,32 +192,42 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy) | |||
196 | #ifdef CONFIG_CPU_FREQ_STAT_DETAILS | 192 | #ifdef CONFIG_CPU_FREQ_STAT_DETAILS |
197 | alloc_size += count * count * sizeof(int); | 193 | alloc_size += count * count * sizeof(int); |
198 | #endif | 194 | #endif |
199 | stats->max_state = count; | 195 | |
196 | /* Allocate memory for time_in_state/freq_table/trans_table in one go */ | ||
200 | stats->time_in_state = kzalloc(alloc_size, GFP_KERNEL); | 197 | stats->time_in_state = kzalloc(alloc_size, GFP_KERNEL); |
201 | if (!stats->time_in_state) { | 198 | if (!stats->time_in_state) |
202 | ret = -ENOMEM; | 199 | goto free_stat; |
203 | goto error_alloc; | 200 | |
204 | } | ||
205 | stats->freq_table = (unsigned int *)(stats->time_in_state + count); | 201 | stats->freq_table = (unsigned int *)(stats->time_in_state + count); |
206 | 202 | ||
207 | #ifdef CONFIG_CPU_FREQ_STAT_DETAILS | 203 | #ifdef CONFIG_CPU_FREQ_STAT_DETAILS |
208 | stats->trans_table = stats->freq_table + count; | 204 | stats->trans_table = stats->freq_table + count; |
209 | #endif | 205 | #endif |
210 | i = 0; | 206 | |
207 | stats->max_state = count; | ||
208 | |||
209 | /* Find valid-unique entries */ | ||
211 | cpufreq_for_each_valid_entry(pos, table) | 210 | cpufreq_for_each_valid_entry(pos, table) |
212 | if (freq_table_get_index(stats, pos->frequency) == -1) | 211 | if (freq_table_get_index(stats, pos->frequency) == -1) |
213 | stats->freq_table[i++] = pos->frequency; | 212 | stats->freq_table[i++] = pos->frequency; |
214 | stats->state_num = i; | 213 | stats->state_num = i; |
214 | |||
215 | spin_lock(&cpufreq_stats_lock); | 215 | spin_lock(&cpufreq_stats_lock); |
216 | stats->last_time = get_jiffies_64(); | 216 | stats->last_time = get_jiffies_64(); |
217 | stats->last_index = freq_table_get_index(stats, policy->cur); | 217 | stats->last_index = freq_table_get_index(stats, policy->cur); |
218 | spin_unlock(&cpufreq_stats_lock); | 218 | spin_unlock(&cpufreq_stats_lock); |
219 | return 0; | 219 | |
220 | error_alloc: | 220 | policy->stats = stats; |
221 | sysfs_remove_group(&policy->kobj, &stats_attr_group); | 221 | ret = sysfs_create_group(&policy->kobj, &stats_attr_group); |
222 | error_out: | 222 | if (!ret) |
223 | kfree(stats); | 223 | return 0; |
224 | |||
225 | /* We failed, release resources */ | ||
224 | policy->stats = NULL; | 226 | policy->stats = NULL; |
227 | kfree(stats->time_in_state); | ||
228 | free_stat: | ||
229 | kfree(stats); | ||
230 | |||
225 | return ret; | 231 | return ret; |
226 | } | 232 | } |
227 | 233 | ||