diff options
author | Philippe Langlais <philippe.langlais@linaro.org> | 2011-07-01 16:41:10 +0200 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@stericsson.com> | 2011-09-19 15:15:42 +0200 |
commit | ca36d68fd19bc9d5a30923b05e68aadb5fef3c62 (patch) | |
tree | 7055b93cf6747013967dab45b1b6f3b5b5f0cb23 /drivers/cpufreq | |
parent | a699c9e3a18ef2bc37e4e55a767f1e0288e64d0b (diff) |
ux500: cpufreq: try to fix merge regressions
Signed-off-by: Philippe Langlais <philippe.langlais@linaro.org>
Diffstat (limited to 'drivers/cpufreq')
-rw-r--r-- | drivers/cpufreq/db8500-cpufreq.c | 70 |
1 files changed, 62 insertions, 8 deletions
diff --git a/drivers/cpufreq/db8500-cpufreq.c b/drivers/cpufreq/db8500-cpufreq.c index d90456a809f..298962fd5ee 100644 --- a/drivers/cpufreq/db8500-cpufreq.c +++ b/drivers/cpufreq/db8500-cpufreq.c @@ -18,29 +18,72 @@ static struct cpufreq_frequency_table freq_table[] = { [0] = { .index = 0, - .frequency = 300000, + .frequency = 200000, }, [1] = { .index = 1, - .frequency = 600000, + .frequency = 300000, }, [2] = { - /* Used for MAX_OPP, if available */ .index = 2, - .frequency = CPUFREQ_TABLE_END, + .frequency = 600000, }, [3] = { + /* Used for MAX_OPP, if available */ .index = 3, .frequency = CPUFREQ_TABLE_END, }, + [4] = { + .index = 4, + .frequency = CPUFREQ_TABLE_END, + }, }; static enum arm_opp idx2opp[] = { + ARM_EXTCLK, ARM_50_OPP, ARM_100_OPP, ARM_MAX_OPP }; +/* + * Below is a temporary workaround for wlan performance issues + */ + +#include <linux/kernel_stat.h> +#include <linux/workqueue.h> +#include <linux/cpu.h> + +#include <mach/irqs.h> + +#define WLAN_PROBE_DELAY 3000 /* 3 seconds */ +#define WLAN_LIMIT (3000/3) /* If we have more than 1000 irqs per second */ + +static struct delayed_work work_wlan_workaround; +bool wlan_mode_on; + +static void wlan_load(struct work_struct *work) +{ + int cpu; + unsigned int num_irqs = 0; + static unsigned int old_num_irqs = UINT_MAX; + + for_each_online_cpu(cpu) + num_irqs += kstat_irqs_cpu(IRQ_DB8500_SDMMC1, cpu); + + if ((num_irqs > old_num_irqs) && + (num_irqs - old_num_irqs) > WLAN_LIMIT) + wlan_mode_on = true; + else + wlan_mode_on = false; + + old_num_irqs = num_irqs; + + schedule_delayed_work_on(0, + &work_wlan_workaround, + msecs_to_jiffies(WLAN_PROBE_DELAY)); +} + static struct freq_attr *db8500_cpufreq_attr[] = { &cpufreq_freq_attr_scaling_available_freqs, NULL, @@ -64,6 +107,10 @@ static int db8500_cpufreq_target(struct cpufreq_policy *policy, if (target_freq > policy->cpuinfo.max_freq) target_freq = policy->cpuinfo.max_freq; + /* A work around for wlan performance issues */ + if (wlan_mode_on) + target_freq = policy->cpuinfo.max_freq; + /* Lookup the next frequency */ if (cpufreq_frequency_table_target (policy, freq_table, target_freq, relation, &idx)) { @@ -108,13 +155,20 @@ static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy) BUILD_BUG_ON(ARRAY_SIZE(idx2opp) + 1 != ARRAY_SIZE(freq_table)); - if (cpu_is_u8500v2() && !prcmu_is_u8400()) { - freq_table[0].frequency = 400000; - freq_table[1].frequency = 800000; + if (!prcmu_is_u8400()) { + freq_table[1].frequency = 400000; + freq_table[2].frequency = 800000; if (prcmu_has_arm_maxopp()) - freq_table[2].frequency = 1000000; + freq_table[3].frequency = 1000000; } + INIT_DELAYED_WORK_DEFERRABLE(&work_wlan_workaround, + wlan_load); + + schedule_delayed_work_on(0, + &work_wlan_workaround, + msecs_to_jiffies(WLAN_PROBE_DELAY)); + /* get policy fields based on the table */ res = cpufreq_frequency_table_cpuinfo(policy, freq_table); if (!res) |