aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2015-01-06 10:39:11 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-01-23 17:06:44 -0500
commita685c6d023c77303ca8700f37bf06eb85ffbf06a (patch)
treefc2cdcee6690d4ac5282423f9f3c1f98d9691d47 /drivers/cpufreq
parentd9f354460db8b58a8395936d323b4ca6e8428b9d (diff)
cpufreq: stats: create sysfs group once we are ready
Userspace is free to read value of any file from cpufreq/stats directory once they are created. __cpufreq_stats_create_table() is creating the sysfs files first and then allocating resources for them. Though it would be quite difficult to trigger the racy situation here, but for the sake of keeping sensible code lets create sysfs entries only after we are ready to go. This also does some makeup to the routine to make it look better. Reviewed-by: Prarit Bhargava <prarit@redhat.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/cpufreq')
-rw-r--r--drivers/cpufreq/cpufreq_stats.c44
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
165static int __cpufreq_stats_create_table(struct cpufreq_policy *policy) 165static 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
220error_alloc: 220 policy->stats = stats;
221 sysfs_remove_group(&policy->kobj, &stats_attr_group); 221 ret = sysfs_create_group(&policy->kobj, &stats_attr_group);
222error_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);
228free_stat:
229 kfree(stats);
230
225 return ret; 231 return ret;
226} 232}
227 233