This patch tries to optimize vexpress_cpufreq_of_init() routine of vexpress_bl cpufreq driver.
Following are the optimizations: - No need to allocate freq table array and copy it into struct cpufreq_frequency_table. This removes the need of _cpufreq_copy_table_from_array() routine too. - Use global freq_table variable instead of creating local copy freqtable. - replace kzalloc with kmalloc, as we are updating all the fields. - free_mem: path expects the clusters to be defined in ascending order, which shouldn't be enforced. Instead try to free freq_table for all clusters.
Signed-off-by: Viresh Kumar viresh.kumar@linaro.org --- Hi Sudeep,
I was going through cpufreq framework and took vexpress_bL_cpufreq.c as an reference. While going through its code, i realized it can be optimized. So this patch.
This is compiled tested only as i didn't had TC2 with me today. Can you please see if it looks fine? Then we can ask Tixy to get this into his tree.
-- viresh
drivers/cpufreq/vexpress_bL_cpufreq.c | 50 +++++++++++++---------------------- 1 file changed, 18 insertions(+), 32 deletions(-)
diff --git a/drivers/cpufreq/vexpress_bL_cpufreq.c b/drivers/cpufreq/vexpress_bL_cpufreq.c index 2c71b24..9af38cf 100644 --- a/drivers/cpufreq/vexpress_bL_cpufreq.c +++ b/drivers/cpufreq/vexpress_bL_cpufreq.c @@ -146,28 +146,14 @@ static unsigned int vexpress_cpufreq_get(unsigned int cpu) return freq_table[cur_cluster][freq_tab_idx].frequency; }
-/* translate the integer array into cpufreq_frequency_table entries */ -static inline void _cpufreq_copy_table_from_array(uint32_t *table, - struct cpufreq_frequency_table *freq_table, int size) -{ - int i; - for (i = 0; i < size; i++) { - freq_table[i].index = i; - freq_table[i].frequency = table[i] / 1000; /* in kHZ */ - } - freq_table[i].index = size; - freq_table[i].frequency = CPUFREQ_TABLE_END; -} - static int vexpress_cpufreq_of_init(void) { - uint32_t cpu_opp_num; - struct cpufreq_frequency_table *freqtable[VEXPRESS_MAX_CLUSTER]; - uint32_t *cpu_freqs; - int ret = 0, cluster_id = 0, len; struct device_node *cluster = NULL; const struct property *pp; + uint32_t cpu_opp_num; + int ret = 0, cluster_id = 0, len, i = -1; const u32 *hwid; + const __be32 *val;
while ((cluster = of_find_node_by_name(cluster, "cluster"))) { hwid = of_get_property(cluster, "reg", &len); @@ -175,33 +161,33 @@ static int vexpress_cpufreq_of_init(void) cluster_id = be32_to_cpup(hwid);
pp = of_find_property(cluster, "freqs", NULL); - if (!pp) + if (!pp || !pp->value || !pp->length) return -EINVAL; + cpu_opp_num = pp->length / sizeof(u32); if (!cpu_opp_num) return -ENODATA;
- cpu_freqs = kzalloc(sizeof(uint32_t) * cpu_opp_num, GFP_KERNEL); - freqtable[cluster_id] = - kzalloc(sizeof(struct cpufreq_frequency_table) * - (cpu_opp_num + 1), GFP_KERNEL); - if (!cpu_freqs || !freqtable[cluster_id]) { + freq_table[cluster_id] = kmalloc(sizeof(**freq_table) * + (cpu_opp_num + 1), GFP_KERNEL); + if (!freq_table[cluster_id]) { ret = -ENOMEM; goto free_mem; } - of_property_read_u32_array(cluster, "freqs", - cpu_freqs, cpu_opp_num); - _cpufreq_copy_table_from_array(cpu_freqs, - freqtable[cluster_id], cpu_opp_num); - freq_table[cluster_id] = freqtable[cluster_id];
- kfree(cpu_freqs); + val = pp->value; + while (++i < cpu_opp_num) { + freq_table[cluster_id][i].index = i; + freq_table[cluster_id][i].frequency = + be32_to_cpup(val++) / 1000; /* in kHZ */ + } + freq_table[cluster_id][i].index = i; + freq_table[cluster_id][i].frequency = CPUFREQ_TABLE_END; } return ret; free_mem: - while (cluster_id >= 0) - kfree(freqtable[cluster_id--]); - kfree(cpu_freqs); + for (i = 0; i < VEXPRESS_MAX_CLUSTER; i++) + kfree(freq_table[i]); return ret; }
On 8 October 2012 13:48, Viresh Kumar viresh.kumar@linaro.org wrote:
This patch tries to optimize vexpress_cpufreq_of_init() routine of vexpress_bl cpufreq driver.
Following are the optimizations:
- No need to allocate freq table array and copy it into struct cpufreq_frequency_table. This removes the need of _cpufreq_copy_table_from_array() routine too.
- Use global freq_table variable instead of creating local copy freqtable.
- replace kzalloc with kmalloc, as we are updating all the fields.
- free_mem: path expects the clusters to be defined in ascending order, which shouldn't be enforced. Instead try to free freq_table for all clusters.
Tested it today on TC2 and found to be working BUT with following fix :)
commit 3fb76ff621e023601bfff51326c8967c2fee0e7a Author: Viresh Kumar viresh.kumar@linaro.org Date: Tue Oct 9 11:25:43 2012 +0530
fixup! cpufreq: vexpress_bl: Optimize vexpress_cpufreq_of_init() --- drivers/cpufreq/vexpress_bL_cpufreq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/cpufreq/vexpress_bL_cpufreq.c b/drivers/cpufreq/vexpress_bL_cpufreq.c index 9af38cf..8b7ec18 100644 --- a/drivers/cpufreq/vexpress_bL_cpufreq.c +++ b/drivers/cpufreq/vexpress_bL_cpufreq.c @@ -151,7 +151,7 @@ static int vexpress_cpufreq_of_init(void) struct device_node *cluster = NULL; const struct property *pp; uint32_t cpu_opp_num; - int ret = 0, cluster_id = 0, len, i = -1; + int ret = 0, cluster_id = 0, len, i; const u32 *hwid; const __be32 *val;
@@ -176,7 +176,7 @@ static int vexpress_cpufreq_of_init(void) }
val = pp->value; - while (++i < cpu_opp_num) { + for (i = 0; i < cpu_opp_num; i++) { freq_table[cluster_id][i].index = i; freq_table[cluster_id][i].frequency = be32_to_cpup(val++) / 1000; /* in kHZ */
variable 'i' wasn't getting reset for the next loop on clusters.
-- viresh