[Nexus 4 Original Android Development] aventu:
It's pretty much rewritten, the last working code is yours.^^

diff --git a/arch/arm/kernel/mako_hotplug.c b/arch/arm/kernel/mako_hotplug.c
index ad7badf..dfd7c10 100644
--- a/arch/arm/kernel/mako_hotplug.c
+++ b/arch/arm/kernel/mako_hotplug.c
@@ -26,20 +26,21 @@

#include <mach/cpufreq.h>

-#define DEFAULT_FIRST_LEVEL 60
+#define DEFAULT_FIRST_LEVEL 90
+#define DEFAULT_SECOND_LEVEL 60
+#define DEFAULT_THIRD_LEVEL 30
#define DEFAULT_SUSPEND_FREQ 702000
#define DEFAULT_CORES_ON_TOUCH 2
-#define HIGH_LOAD_COUNTER 20
#define TIMER HZ

struct cpu_stats
{
- unsigned int total_cpus;
+ unsigned int online_cpus;
unsigned int default_first_level;
- unsigned int suspend_frequency;
+ unsigned int default_second_level;
+ unsigned int default_third_level;
unsigned int cores_on_touch;
-
- unsigned int counter[2];
+ unsigned int suspend_frequency;
};

static struct cpu_stats stats;
@@ -55,78 +56,98 @@ static void scale_interactive_tunables(unsigned int above_hispeed_delay,
scale_min_sample_time(min_sample_time);
}

-static void __cpuinit decide_hotplug_func(struct work_struct *work)
+static void online_core(void)
{
int cpu;
- int cpu_boost;
-
- if (unlikely(is_touching && num_online_cpus() < stats.cores_on_touch))
+
+ if (stats.online_cpus > 3)
+ return;
+
+ for_each_possible_cpu(cpu)
{
- for_each_possible_cpu(cpu_boost)
+ if (!cpu_online(cpu))
{
- if (!cpu_online(cpu_boost) && cpu_boost < stats.cores_on_touch)
- {
- cpu_up(cpu_boost);
- }
+ cpu_up(cpu);
+ pr_info("CPU %d up\n",cpu);
+ break;
}
- }
+ }
+}

- for_each_online_cpu(cpu)
+static void offline_core(int cpu)
+{
+ if (cpu_online(cpu) && cpu > 0)
{
- if (report_load_at_max_freq(cpu) >= stats.default_first_level)
- {
- if (likely(stats.counter[cpu] < HIGH_LOAD_COUNTER))
- stats.counter[cpu] += 2;
- }
+ cpu_down(cpu);
+ pr_info("CPU %d down\n",cpu);
+ }
+}

- else
- {
- if (stats.counter[cpu] > 0)
- stats.counter[cpu]--;
- }
+static void __cpuinit decide_hotplug_func(struct work_struct *work)
+{
+ int cpu, lowest_cpu = 0;
+ unsigned int i, cur_cpu, load, av_load = 0, lowest_cpu_load = 100;
+
+ pr_info("decide_hotplug_func start\n");

- if (cpu)
+ stats.online_cpus = num_online_cpus();
+
+ if (is_touching && stats.online_cpus < stats.cores_on_touch)
+ {
+ for(i = 0; i < (stats.cores_on_touch - stats.online_cpus); i++)
{
- cpu = 0;
- break;
+ online_core();
}
+ goto end;
}

- if (stats.counter[0] >= 10)
+ for_each_online_cpu(cpu)
{
- if (!cpu_online(2))
+ load = report_load_at_max_freq(cpu);
+
+ if (load >= stats.default_first_level)
{
- cpu_up(2);
- scale_interactive_tunables(0, 10000, 80000);
+ online_core();
+ goto end;
}
- }
- else
- {
- if (cpu_online(2))
+
+ if (load < lowest_cpu_load && cpu != 0)
{
- cpu_down(2);
- scale_interactive_tunables(20000, 40000, 20000);
- }
+ lowest_cpu = cpu;
+ lowest_cpu_load = load;
+ }
+
+ av_load += load;
}

- if (stats.counter[1] >= 10)
+ av_load = av_load / stats.online_cpus;
+
+ if (av_load >= stats.default_second_level)
{
- if (!cpu_online(3))
- {
- cpu_up(3);
- scale_interactive_tunables(0, 10000, 80000);
- }
+ online_core();
}
-
- else
+ else if (av_load <= stats.default_third_level)
+ {
+ offline_core(lowest_cpu);
+ }
+
+end:
+ cur_cpu = num_online_cpus();
+
+ if (stats.online_cpus != cur_cpu)
{
- if (cpu_online(3))
+ // above_hispeed_delay, timer_rate, min_sample_time
+ switch(cur_cpu)
{
- cpu_down(3);
- scale_interactive_tunables(20000, 40000, 20000);
- }
+ case 1: scale_interactive_tunables(10000, 20000, 40000); break;
+ case 2: scale_interactive_tunables(20000, 40000, 20000); break;
+ case 3: scale_interactive_tunables(20000, 30000, 40000); break;
+ case 4: scale_interactive_tunables(0, 20000, 80000); break;
+ }
}
-
+
+ pr_info("decide_hotplug_func end\n");
+
queue_delayed_work(wq, &decide_hotplug, msecs_to_jiffies(TIMER));
}

@@ -147,7 +168,7 @@ static void __cpuinit mako_hotplug_early_suspend(struct early_suspend *handler)
cpu_down(cpu);
}
}
-
+ scale_interactive_tunables(10000, 20000, 40000);

/* cap max frequency to 702MHz by default */
msm_cpufreq_set_freq_limits(0, MSM_CPUFREQ_NO_LIMIT,
@@ -168,9 +189,7 @@ static void __cpuinit mako_hotplug_late_resume(struct early_suspend *handler)
cpu_up(cpu);
}
}
-
- stats.counter[0] = 0;
- stats.counter[1] = 0;
+ scale_interactive_tunables(0, 20000, 80000);

/* restore max frequency */
msm_cpufreq_set_freq_limits(0, MSM_CPUFREQ_NO_LIMIT, MSM_CPUFREQ_NO_LIMIT);
@@ -193,6 +212,16 @@ void update_first_level(unsigned int level)
stats.default_first_level = level;
}

+void update_second_level(unsigned int level)
+{
+ stats.default_second_level = level;
+}
+
+void update_third_level(unsigned int level)
+{
+ stats.default_third_level = level;
+}
+
void update_suspend_frequency(unsigned int freq)
{
stats.suspend_frequency = freq;
@@ -208,6 +237,16 @@ unsigned int get_first_level()
return stats.default_first_level;
}

+unsigned int get_second_level()
+{
+ return stats.default_second_level;
+}
+
+unsigned int get_third_level()
+{
+ return stats.default_third_level;
+}
+
unsigned int get_suspend_frequency()
{
return stats.suspend_frequency;
@@ -224,12 +263,11 @@ int __init mako_hotplug_init(void)
pr_info("Mako Hotplug driver started.\n");

/* init everything here */
- stats.total_cpus = num_present_cpus();
stats.default_first_level = DEFAULT_FIRST_LEVEL;
+ stats.default_second_level = DEFAULT_SECOND_LEVEL;
+ stats.default_third_level = DEFAULT_THIRD_LEVEL;
stats.suspend_frequency = DEFAULT_SUSPEND_FREQ;
stats.cores_on_touch = DEFAULT_CORES_ON_TOUCH;
- stats.counter[0] = 0;
- stats.counter[1] = 0;

wq = alloc_workqueue("mako_hotplug_workqueue",
WQ_UNBOUND | WQ_RESCUER | WQ_FREEZABLE, 1);
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c
index 3bdcc41..5d3a9f0 100644
--- a/drivers/cpufreq/cpufreq_interactive.c
+++ b/drivers/cpufreq/cpufreq_interactive.c
@@ -260,10 +260,6 @@ static void cpufreq_interactive_timer(unsigned long data)
}

new_freq = pcpu->freq_table[index].frequency;
-
- /* if the cpu load is >= 50% lets bump the cpu to hispeed_freq */
- if (cpu_load >= HISPEED_FREQ_LOAD && new_freq < hispeed_freq)
- new_freq = hispeed_freq;

/*
* we want cpu0 to be the only core blocked for freq changes while
diff --git a/drivers/misc/mako_hotplug_control.c b/drivers/misc/mako_hotplug_control.c
index bdb9d21..4bf28ff 100644
--- a/drivers/misc/mako_hotplug_control.c
+++ b/drivers/misc/mako_hotplug_control.c
@@ -36,6 +36,44 @@ static ssize_t first_level_store(struct device *dev, struct device_attribute *at
return size;
}

+static ssize_t second_level_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%u\n", get_second_level());
+}
+
+static ssize_t second_level_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ unsigned int new_val;
+
+ sscanf(buf, "%u", &new_val);
+
+ if (new_val != get_second_level() && new_val >= 0 && new_val <= 100)
+ {
+ update_second_level(new_val);
+ }
+
+ return size;
+}
+
+static ssize_t third_level_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%u\n", get_third_level());
+}
+
+static ssize_t third_level_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
+{
+ unsigned int new_val;
+
+ sscanf(buf, "%u", &new_val);
+
+ if (new_val != get_third_level() && new_val >= 0 && new_val <= 100)
+ {
+ update_third_level(new_val);
+ }
+
+ return size;
+}
+
static ssize_t suspend_frequency_show(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%u\n", get_suspend_frequency());
@@ -80,6 +118,8 @@ static ssize_t mako_hotplug_control_version(struct device *dev, struct device_at
}

static DEVICE_ATTR(first_level, 0777, first_level_show, first_level_store);
+static DEVICE_ATTR(second_level, 0777, second_level_show, second_level_store);
+static DEVICE_ATTR(third_level, 0777, third_level_show, third_level_store);
static DEVICE_ATTR(suspend_frequency, 0777, suspend_frequency_show, suspend_frequency_store);
static DEVICE_ATTR(cores_on_touch, 0777, cores_on_touch_show, cores_on_touch_store);
static DEVICE_ATTR(version, 0777 , mako_hotplug_control_version, NULL);
@@ -87,6 +127,8 @@ static DEVICE_ATTR(version, 0777 , mako_hotplug_control_version, NULL);
static struct attribute *mako_hotplug_control_attributes[] =
{
&dev_attr_first_level.attr,
+ &dev_attr_second_level.attr,
+ &dev_attr_third_level.attr,
&dev_attr_suspend_frequency.attr,
&dev_attr_cores_on_touch.attr,
&dev_attr_version.attr,