[Nexus 4 Original Android Development] Skkip:
[MENTION=535343]all[/MENTION]: I'd like to share my latest hotplug with you. :) I changed some things me and stratosk spoke about.

/*
* Dynamic Hotplug for mako
*
* Copyright (C) 2013 Stratos Karafotis <stratosk@semaphore.gr>
* (C) 2013 Skip <sskkiipp@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Depends on cpufreq average utilization and cpufreq_quick_get_util
* to get the CPU utilization (drivers/cpufreq/cpufreq.c):
*
* void cpufreq_notify_utilization(struct cpufreq_policy *policy,
* unsigned int util)
* {
*if (policy)
*policy->util = (policy->util + util)/2;
* }
*
* unsigned int cpufreq_quick_get_util(unsigned int cpu)
* {
* struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
* unsigned int ret_util = 0;
*
* if (policy) {
* ret_util = policy->util;
* cpufreq_cpu_put(policy);
* }
*
* return ret_util;
* }
* EXPORT_SYMBOL(cpufreq_quick_get_util);
*
*/

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/cpu.h>
#include <linux/workqueue.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/cpufreq.h>
#include <linux/delay.h>
#include <linux/slab.h>

static unsigned int sampling_rate_ms = 500;
static unsigned int up_delay_multiplier = 2;
static unsigned int down_delay_multiplier = 5;
static unsigned int up_threshold = 75;
static unsigned int down_threshold = 25;
static unsigned int min_online = 2;
static unsigned int max_online = 4;
static unsigned long last_change_time;

/*************** Module parameters ****************/
module_param(sampling_rate_ms, uint, 0644);
module_param(up_delay_multiplier, uint, 0644);
module_param(down_delay_multiplier, uint, 0644);
module_param(up_threshold, uint, 0644);
module_param(down_threshold, uint, 0644);
module_param(min_online, uint, 0644);
module_param(max_online, uint, 0644);
/************ end of module parameters ************/

static struct workqueue_struct *workq;
static struct delayed_work dyn_hotplug;

/* Bring online the first found offline one */
static inline void up_one(void)
{
unsigned int cpu;

/* All wanted CPUs or more are online, return */
if (num_online_cpus() >= max_online)
return;

cpu = cpumask_next_zero(0, cpu_online_mask);
if (cpu < nr_cpu_ids)
cpu_up(cpu);
}

/* Iterate through online CPUs and bring down the one with lowest load*/
static inline void down_one(void)
{
unsigned int cpu = nr_cpu_ids;
unsigned int rate = UINT_MAX;
unsigned int i;

/* Min online CPUs, return */
if (num_online_cpus() <= min_online)
return;

for_each_online_cpu(i){
if ((i > 0) && (rate > cpufreq_quick_get(i))) {
cpu = i;
rate = cpufreq_quick_get(i);
}
}

cpu_down(cpu);
}

/*
* Every sampling_rate_ms, check the average load of online CPUs. If the average
* load is above up_threshold bring online one more CPU if up_delay has expired.
* If the average load is below down_threshold offline one more CPU if the
* down_delay has expired.
*/
static __cpuinit void load_timer(struct work_struct *work)
{
unsigned int cpu;
unsigned int avg_load = 0;
unsigned long now = jiffies;

for_each_online_cpu(cpu)
avg_load += cpufreq_quick_get_util(cpu);

avg_load /= num_online_cpus();

if ((now - last_change_time) >= msecs_to_jiffies(sampling_rate_ms * up_delay_multiplier)) {
if (avg_load >= up_threshold) {
last_change_time = now;
up_one();
}
}

if ((now - last_change_time) >= msecs_to_jiffies(sampling_rate_ms * down_delay_multiplier)) {
if (avg_load <= down_threshold) {
last_change_time = now;
down_one();
}
}

queue_delayed_work(workq, &dyn_hotplug, msecs_to_jiffies(sampling_rate_ms));
}

static int __init dyn_hp_init(void)
{
workq = alloc_workqueue("dyn_hotplug_workqueue",
WQ_UNBOUND | WQ_RESCUER | WQ_FREEZABLE, 1);
if (!workq)
return -ENOMEM;

INIT_DELAYED_WORK(&dyn_hotplug, load_timer);

/* Wait 15 Seconds after boot for everything to be ready*/
queue_delayed_work(workq, &dyn_hotplug, HZ*15);

return 0;
}

static void __exit dyn_hp_exit(void)
{
cancel_delayed_work(&dyn_hotplug);
flush_scheduled_work();
destroy_workqueue(workq);
}

MODULE_AUTHOR("Stratos Karafotis <stratosk@semaphore.gr");
MODULE_AUTHOR("Sebastian Küppers <sskkiipp@gmail.com>");
MODULE_DESCRIPTION("'dyn_hotplug' - A dynamic hotplug driver for mako");
MODULE_LICENSE("GPL");

module_init(dyn_hp_init);
module_exit(dyn_hp_exit);

[MENTION=3750240]stratosk[/MENTION]: What does min_online 1 on screen off change in terms of battery life? Greetings from my vacation :)

Gesendet von meinem Nexus 7 mit Tapatalk 4