Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a5acbfbd authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branch 'pm-cpufreq-governor' into pm-cpufreq

parents edd4a893 adaf9fcd
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ config CPU_FREQ
if CPU_FREQ

config CPU_FREQ_GOV_COMMON
	select IRQ_WORK
	bool

config CPU_FREQ_BOOST_SW
+4 −4
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@
#include <asm/msr.h>
#include <asm/cpufeature.h>

#include "cpufreq_governor.h"
#include "cpufreq_ondemand.h"

#define MSR_AMD64_FREQ_SENSITIVITY_ACTUAL	0xc0010080
#define MSR_AMD64_FREQ_SENSITIVITY_REFERENCE	0xc0010081
@@ -45,10 +45,10 @@ static unsigned int amd_powersave_bias_target(struct cpufreq_policy *policy,
	long d_actual, d_reference;
	struct msr actual, reference;
	struct cpu_data_t *data = &per_cpu(cpu_data, policy->cpu);
	struct dbs_data *od_data = policy->governor_data;
	struct policy_dbs_info *policy_dbs = policy->governor_data;
	struct dbs_data *od_data = policy_dbs->dbs_data;
	struct od_dbs_tuners *od_tuners = od_data->tuners;
	struct od_cpu_dbs_info_s *od_info =
		od_data->cdata->get_cpu_dbs_info_s(policy->cpu);
	struct od_policy_dbs_info *od_info = to_dbs_info(policy_dbs);

	if (!od_info->freq_table)
		return freq_next;
+67 −98
Original line number Diff line number Diff line
@@ -64,7 +64,6 @@ static LIST_HEAD(cpufreq_governor_list);
static struct cpufreq_driver *cpufreq_driver;
static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data);
static DEFINE_RWLOCK(cpufreq_driver_lock);
DEFINE_MUTEX(cpufreq_governor_lock);

/* Flag to suspend/resume CPUFreq governors */
static bool cpufreq_suspended;
@@ -75,10 +74,8 @@ static inline bool has_target(void)
}

/* internal prototypes */
static int __cpufreq_governor(struct cpufreq_policy *policy,
		unsigned int event);
static int cpufreq_governor(struct cpufreq_policy *policy, unsigned int event);
static unsigned int __cpufreq_get(struct cpufreq_policy *policy);
static void handle_update(struct work_struct *work);

/**
 * Two notifier lists: the "policy" list is involved in the
@@ -955,30 +952,38 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, unsigned int cp
	if (cpumask_test_cpu(cpu, policy->cpus))
		return 0;

	down_write(&policy->rwsem);
	if (has_target()) {
		ret = __cpufreq_governor(policy, CPUFREQ_GOV_STOP);
		ret = cpufreq_governor(policy, CPUFREQ_GOV_STOP);
		if (ret) {
			pr_err("%s: Failed to stop governor\n", __func__);
			return ret;
			goto unlock;
		}
	}

	down_write(&policy->rwsem);
	cpumask_set_cpu(cpu, policy->cpus);
	up_write(&policy->rwsem);

	if (has_target()) {
		ret = __cpufreq_governor(policy, CPUFREQ_GOV_START);
		ret = cpufreq_governor(policy, CPUFREQ_GOV_START);
		if (!ret)
			ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
			ret = cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);

		if (ret) {
		if (ret)
			pr_err("%s: Failed to start governor\n", __func__);
			return ret;
	}

unlock:
	up_write(&policy->rwsem);
	return ret;
}

	return 0;
static void handle_update(struct work_struct *work)
{
	struct cpufreq_policy *policy =
		container_of(work, struct cpufreq_policy, update);
	unsigned int cpu = policy->cpu;
	pr_debug("handle_update for cpu %u called\n", cpu);
	cpufreq_update_policy(cpu);
}

static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
@@ -1267,9 +1272,10 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
	return ret;
}

static void cpufreq_offline_prepare(unsigned int cpu)
static void cpufreq_offline(unsigned int cpu)
{
	struct cpufreq_policy *policy;
	int ret;

	pr_debug("%s: unregistering CPU %u\n", __func__, cpu);

@@ -1279,13 +1285,13 @@ static void cpufreq_offline_prepare(unsigned int cpu)
		return;
	}

	down_write(&policy->rwsem);
	if (has_target()) {
		int ret = __cpufreq_governor(policy, CPUFREQ_GOV_STOP);
		ret = cpufreq_governor(policy, CPUFREQ_GOV_STOP);
		if (ret)
			pr_err("%s: Failed to stop governor\n", __func__);
	}

	down_write(&policy->rwsem);
	cpumask_clear_cpu(cpu, policy->cpus);

	if (policy_is_inactive(policy)) {
@@ -1298,39 +1304,27 @@ static void cpufreq_offline_prepare(unsigned int cpu)
		/* Nominate new CPU */
		policy->cpu = cpumask_any(policy->cpus);
	}
	up_write(&policy->rwsem);

	/* Start governor again for active policy */
	if (!policy_is_inactive(policy)) {
		if (has_target()) {
			int ret = __cpufreq_governor(policy, CPUFREQ_GOV_START);
			ret = cpufreq_governor(policy, CPUFREQ_GOV_START);
			if (!ret)
				ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
				ret = cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);

			if (ret)
				pr_err("%s: Failed to start governor\n", __func__);
		}
	} else if (cpufreq_driver->stop_cpu) {
		cpufreq_driver->stop_cpu(policy);
	}
}

static void cpufreq_offline_finish(unsigned int cpu)
{
	struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);

	if (!policy) {
		pr_debug("%s: No cpu_data found\n", __func__);
		return;
		goto unlock;
	}

	/* Only proceed for inactive policies */
	if (!policy_is_inactive(policy))
		return;
	if (cpufreq_driver->stop_cpu)
		cpufreq_driver->stop_cpu(policy);

	/* If cpu is last user of policy, free policy */
	if (has_target()) {
		int ret = __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
		ret = cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
		if (ret)
			pr_err("%s: Failed to exit governor\n", __func__);
	}
@@ -1344,6 +1338,9 @@ static void cpufreq_offline_finish(unsigned int cpu)
		cpufreq_driver->exit(policy);
		policy->freq_table = NULL;
	}

unlock:
	up_write(&policy->rwsem);
}

/**
@@ -1359,10 +1356,8 @@ static void cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
	if (!policy)
		return;

	if (cpu_online(cpu)) {
		cpufreq_offline_prepare(cpu);
		cpufreq_offline_finish(cpu);
	}
	if (cpu_online(cpu))
		cpufreq_offline(cpu);

	cpumask_clear_cpu(cpu, policy->real_cpus);
	remove_cpu_dev_symlink(policy, cpu);
@@ -1371,15 +1366,6 @@ static void cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
		cpufreq_policy_free(policy, true);
}

static void handle_update(struct work_struct *work)
{
	struct cpufreq_policy *policy =
		container_of(work, struct cpufreq_policy, update);
	unsigned int cpu = policy->cpu;
	pr_debug("handle_update for cpu %u called\n", cpu);
	cpufreq_update_policy(cpu);
}

/**
 *	cpufreq_out_of_sync - If actual and saved CPU frequency differs, we're
 *	in deep trouble.
@@ -1542,6 +1528,7 @@ EXPORT_SYMBOL(cpufreq_generic_suspend);
void cpufreq_suspend(void)
{
	struct cpufreq_policy *policy;
	int ret;

	if (!cpufreq_driver)
		return;
@@ -1552,7 +1539,11 @@ void cpufreq_suspend(void)
	pr_debug("%s: Suspending Governors\n", __func__);

	for_each_active_policy(policy) {
		if (__cpufreq_governor(policy, CPUFREQ_GOV_STOP))
		down_write(&policy->rwsem);
		ret = cpufreq_governor(policy, CPUFREQ_GOV_STOP);
		up_write(&policy->rwsem);

		if (ret)
			pr_err("%s: Failed to stop governor for policy: %p\n",
				__func__, policy);
		else if (cpufreq_driver->suspend
@@ -1574,6 +1565,7 @@ void cpufreq_suspend(void)
void cpufreq_resume(void)
{
	struct cpufreq_policy *policy;
	int ret;

	if (!cpufreq_driver)
		return;
@@ -1586,14 +1578,21 @@ void cpufreq_resume(void)
	pr_debug("%s: Resuming Governors\n", __func__);

	for_each_active_policy(policy) {
		if (cpufreq_driver->resume && cpufreq_driver->resume(policy))
		if (cpufreq_driver->resume && cpufreq_driver->resume(policy)) {
			pr_err("%s: Failed to resume driver: %p\n", __func__,
				policy);
		else if (__cpufreq_governor(policy, CPUFREQ_GOV_START)
		    || __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))
		} else {
			down_write(&policy->rwsem);
			ret = cpufreq_governor(policy, CPUFREQ_GOV_START);
			if (!ret)
				cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
			up_write(&policy->rwsem);

			if (ret)
				pr_err("%s: Failed to start governor for policy: %p\n",
				       __func__, policy);
		}
	}

	/*
	 * schedule call cpufreq_update_policy() for first-online CPU, as that
@@ -1878,8 +1877,7 @@ __weak struct cpufreq_governor *cpufreq_fallback_governor(void)
	return NULL;
}

static int __cpufreq_governor(struct cpufreq_policy *policy,
					unsigned int event)
static int cpufreq_governor(struct cpufreq_policy *policy, unsigned int event)
{
	int ret;

@@ -1913,21 +1911,6 @@ static int __cpufreq_governor(struct cpufreq_policy *policy,

	pr_debug("%s: for CPU %u, event %u\n", __func__, policy->cpu, event);

	mutex_lock(&cpufreq_governor_lock);
	if ((policy->governor_enabled && event == CPUFREQ_GOV_START)
	    || (!policy->governor_enabled
	    && (event == CPUFREQ_GOV_LIMITS || event == CPUFREQ_GOV_STOP))) {
		mutex_unlock(&cpufreq_governor_lock);
		return -EBUSY;
	}

	if (event == CPUFREQ_GOV_STOP)
		policy->governor_enabled = false;
	else if (event == CPUFREQ_GOV_START)
		policy->governor_enabled = true;

	mutex_unlock(&cpufreq_governor_lock);

	ret = policy->governor->governor(policy, event);

	if (!ret) {
@@ -1935,14 +1918,6 @@ static int __cpufreq_governor(struct cpufreq_policy *policy,
			policy->governor->initialized++;
		else if (event == CPUFREQ_GOV_POLICY_EXIT)
			policy->governor->initialized--;
	} else {
		/* Restore original values */
		mutex_lock(&cpufreq_governor_lock);
		if (event == CPUFREQ_GOV_STOP)
			policy->governor_enabled = true;
		else if (event == CPUFREQ_GOV_START)
			policy->governor_enabled = false;
		mutex_unlock(&cpufreq_governor_lock);
	}

	if (((event == CPUFREQ_GOV_POLICY_INIT) && ret) ||
@@ -2097,7 +2072,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
	old_gov = policy->governor;
	/* end old governor */
	if (old_gov) {
		ret = __cpufreq_governor(policy, CPUFREQ_GOV_STOP);
		ret = cpufreq_governor(policy, CPUFREQ_GOV_STOP);
		if (ret) {
			/* This can happen due to race with other operations */
			pr_debug("%s: Failed to Stop Governor: %s (%d)\n",
@@ -2105,10 +2080,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
			return ret;
		}

		up_write(&policy->rwsem);
		ret = __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
		down_write(&policy->rwsem);

		ret = cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
		if (ret) {
			pr_err("%s: Failed to Exit Governor: %s (%d)\n",
			       __func__, old_gov->name, ret);
@@ -2118,32 +2090,30 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,

	/* start new governor */
	policy->governor = new_policy->governor;
	ret = __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT);
	ret = cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT);
	if (!ret) {
		ret = __cpufreq_governor(policy, CPUFREQ_GOV_START);
		ret = cpufreq_governor(policy, CPUFREQ_GOV_START);
		if (!ret)
			goto out;

		up_write(&policy->rwsem);
		__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
		down_write(&policy->rwsem);
		cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
	}

	/* new governor failed, so re-start old one */
	pr_debug("starting governor %s failed\n", policy->governor->name);
	if (old_gov) {
		policy->governor = old_gov;
		if (__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT))
		if (cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT))
			policy->governor = NULL;
		else
			__cpufreq_governor(policy, CPUFREQ_GOV_START);
			cpufreq_governor(policy, CPUFREQ_GOV_START);
	}

	return ret;

 out:
	pr_debug("governor: change or update limits\n");
	return __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
	return cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
}

/**
@@ -2210,11 +2180,7 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb,
		break;

	case CPU_DOWN_PREPARE:
		cpufreq_offline_prepare(cpu);
		break;

	case CPU_POST_DEAD:
		cpufreq_offline_finish(cpu);
		cpufreq_offline(cpu);
		break;

	case CPU_DOWN_FAILED:
@@ -2247,8 +2213,11 @@ static int cpufreq_boost_set_sw(int state)
				       __func__);
				break;
			}

			down_write(&policy->rwsem);
			policy->user_policy.max = policy->max;
			__cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
			cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
			up_write(&policy->rwsem);
		}
	}

+124 −152
Original line number Diff line number Diff line
@@ -14,6 +14,22 @@
#include <linux/slab.h>
#include "cpufreq_governor.h"

struct cs_policy_dbs_info {
	struct policy_dbs_info policy_dbs;
	unsigned int down_skip;
	unsigned int requested_freq;
};

static inline struct cs_policy_dbs_info *to_dbs_info(struct policy_dbs_info *policy_dbs)
{
	return container_of(policy_dbs, struct cs_policy_dbs_info, policy_dbs);
}

struct cs_dbs_tuners {
	unsigned int down_threshold;
	unsigned int freq_step;
};

/* Conservative governor macros */
#define DEF_FREQUENCY_UP_THRESHOLD		(80)
#define DEF_FREQUENCY_DOWN_THRESHOLD		(20)
@@ -21,18 +37,6 @@
#define DEF_SAMPLING_DOWN_FACTOR		(1)
#define MAX_SAMPLING_DOWN_FACTOR		(10)

static DEFINE_PER_CPU(struct cs_cpu_dbs_info_s, cs_cpu_dbs_info);

static int cs_cpufreq_governor_dbs(struct cpufreq_policy *policy,
				   unsigned int event);

static struct cpufreq_governor cpufreq_gov_conservative = {
	.name			= "conservative",
	.governor		= cs_cpufreq_governor_dbs,
	.max_transition_latency	= TRANSITION_LATENCY_LIMIT,
	.owner			= THIS_MODULE,
};

static inline unsigned int get_freq_target(struct cs_dbs_tuners *cs_tuners,
					   struct cpufreq_policy *policy)
{
@@ -54,27 +58,28 @@ static inline unsigned int get_freq_target(struct cs_dbs_tuners *cs_tuners,
 * Any frequency increase takes it to the maximum frequency. Frequency reduction
 * happens at minimum steps of 5% (default) of maximum frequency
 */
static void cs_check_cpu(int cpu, unsigned int load)
static unsigned int cs_dbs_timer(struct cpufreq_policy *policy)
{
	struct cs_cpu_dbs_info_s *dbs_info = &per_cpu(cs_cpu_dbs_info, cpu);
	struct cpufreq_policy *policy = dbs_info->cdbs.shared->policy;
	struct dbs_data *dbs_data = policy->governor_data;
	struct policy_dbs_info *policy_dbs = policy->governor_data;
	struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy_dbs);
	struct dbs_data *dbs_data = policy_dbs->dbs_data;
	struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
	unsigned int load = dbs_update(policy);

	/*
	 * break out if we 'cannot' reduce the speed as the user might
	 * want freq_step to be zero
	 */
	if (cs_tuners->freq_step == 0)
		return;
		goto out;

	/* Check for frequency increase */
	if (load > cs_tuners->up_threshold) {
	if (load > dbs_data->up_threshold) {
		dbs_info->down_skip = 0;

		/* if we are already at full speed then break out early */
		if (dbs_info->requested_freq == policy->max)
			return;
			goto out;

		dbs_info->requested_freq += get_freq_target(cs_tuners, policy);

@@ -83,12 +88,12 @@ static void cs_check_cpu(int cpu, unsigned int load)

		__cpufreq_driver_target(policy, dbs_info->requested_freq,
			CPUFREQ_RELATION_H);
		return;
		goto out;
	}

	/* if sampling_down_factor is active break out early */
	if (++dbs_info->down_skip < cs_tuners->sampling_down_factor)
		return;
	if (++dbs_info->down_skip < dbs_data->sampling_down_factor)
		goto out;
	dbs_info->down_skip = 0;

	/* Check for frequency decrease */
@@ -98,7 +103,7 @@ static void cs_check_cpu(int cpu, unsigned int load)
		 * if we cannot reduce the frequency anymore, break out early
		 */
		if (policy->cur == policy->min)
			return;
			goto out;

		freq_target = get_freq_target(cs_tuners, policy);
		if (dbs_info->requested_freq > freq_target)
@@ -108,58 +113,25 @@ static void cs_check_cpu(int cpu, unsigned int load)

		__cpufreq_driver_target(policy, dbs_info->requested_freq,
				CPUFREQ_RELATION_L);
		return;
	}
	}

static unsigned int cs_dbs_timer(struct cpufreq_policy *policy, bool modify_all)
{
	struct dbs_data *dbs_data = policy->governor_data;
	struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;

	if (modify_all)
		dbs_check_cpu(dbs_data, policy->cpu);

	return delay_for_sampling_rate(cs_tuners->sampling_rate);
 out:
	return dbs_data->sampling_rate;
}

static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
		void *data)
{
	struct cpufreq_freqs *freq = data;
	struct cs_cpu_dbs_info_s *dbs_info =
					&per_cpu(cs_cpu_dbs_info, freq->cpu);
	struct cpufreq_policy *policy = cpufreq_cpu_get_raw(freq->cpu);

	if (!policy)
		return 0;

	/* policy isn't governed by conservative governor */
	if (policy->governor != &cpufreq_gov_conservative)
		return 0;

	/*
	 * we only care if our internally tracked freq moves outside the 'valid'
	 * ranges of frequency available to us otherwise we do not change it
	*/
	if (dbs_info->requested_freq > policy->max
			|| dbs_info->requested_freq < policy->min)
		dbs_info->requested_freq = freq->new;

	return 0;
}
				void *data);

static struct notifier_block cs_cpufreq_notifier_block = {
	.notifier_call = dbs_cpufreq_notifier,
};

/************************** sysfs interface ************************/
static struct common_dbs_data cs_dbs_cdata;
static struct dbs_governor cs_dbs_gov;

static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data,
		const char *buf, size_t count)
{
	struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
	unsigned int input;
	int ret;
	ret = sscanf(buf, "%u", &input);
@@ -167,22 +139,7 @@ static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data,
	if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
		return -EINVAL;

	cs_tuners->sampling_down_factor = input;
	return count;
}

static ssize_t store_sampling_rate(struct dbs_data *dbs_data, const char *buf,
		size_t count)
{
	struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
	unsigned int input;
	int ret;
	ret = sscanf(buf, "%u", &input);

	if (ret != 1)
		return -EINVAL;

	cs_tuners->sampling_rate = max(input, dbs_data->min_sampling_rate);
	dbs_data->sampling_down_factor = input;
	return count;
}

@@ -197,7 +154,7 @@ static ssize_t store_up_threshold(struct dbs_data *dbs_data, const char *buf,
	if (ret != 1 || input > 100 || input <= cs_tuners->down_threshold)
		return -EINVAL;

	cs_tuners->up_threshold = input;
	dbs_data->up_threshold = input;
	return count;
}

@@ -211,7 +168,7 @@ static ssize_t store_down_threshold(struct dbs_data *dbs_data, const char *buf,

	/* cannot be lower than 11 otherwise freq will not fall */
	if (ret != 1 || input < 11 || input > 100 ||
			input >= cs_tuners->up_threshold)
			input >= dbs_data->up_threshold)
		return -EINVAL;

	cs_tuners->down_threshold = input;
@@ -221,8 +178,7 @@ static ssize_t store_down_threshold(struct dbs_data *dbs_data, const char *buf,
static ssize_t store_ignore_nice_load(struct dbs_data *dbs_data,
		const char *buf, size_t count)
{
	struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
	unsigned int input, j;
	unsigned int input;
	int ret;

	ret = sscanf(buf, "%u", &input);
@@ -232,21 +188,14 @@ static ssize_t store_ignore_nice_load(struct dbs_data *dbs_data,
	if (input > 1)
		input = 1;

	if (input == cs_tuners->ignore_nice_load) /* nothing to do */
	if (input == dbs_data->ignore_nice_load) /* nothing to do */
		return count;

	cs_tuners->ignore_nice_load = input;
	dbs_data->ignore_nice_load = input;

	/* we need to re-evaluate prev_cpu_idle */
	for_each_online_cpu(j) {
		struct cs_cpu_dbs_info_s *dbs_info;
		dbs_info = &per_cpu(cs_cpu_dbs_info, j);
		dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j,
					&dbs_info->cdbs.prev_cpu_wall, 0);
		if (cs_tuners->ignore_nice_load)
			dbs_info->cdbs.prev_cpu_nice =
				kcpustat_cpu(j).cpustat[CPUTIME_NICE];
	}
	gov_update_cpu_data(dbs_data);

	return count;
}

@@ -272,55 +221,47 @@ static ssize_t store_freq_step(struct dbs_data *dbs_data, const char *buf,
	return count;
}

show_store_one(cs, sampling_rate);
show_store_one(cs, sampling_down_factor);
show_store_one(cs, up_threshold);
show_store_one(cs, down_threshold);
show_store_one(cs, ignore_nice_load);
show_store_one(cs, freq_step);
declare_show_sampling_rate_min(cs);

gov_sys_pol_attr_rw(sampling_rate);
gov_sys_pol_attr_rw(sampling_down_factor);
gov_sys_pol_attr_rw(up_threshold);
gov_sys_pol_attr_rw(down_threshold);
gov_sys_pol_attr_rw(ignore_nice_load);
gov_sys_pol_attr_rw(freq_step);
gov_sys_pol_attr_ro(sampling_rate_min);

static struct attribute *dbs_attributes_gov_sys[] = {
	&sampling_rate_min_gov_sys.attr,
	&sampling_rate_gov_sys.attr,
	&sampling_down_factor_gov_sys.attr,
	&up_threshold_gov_sys.attr,
	&down_threshold_gov_sys.attr,
	&ignore_nice_load_gov_sys.attr,
	&freq_step_gov_sys.attr,
gov_show_one_common(sampling_rate);
gov_show_one_common(sampling_down_factor);
gov_show_one_common(up_threshold);
gov_show_one_common(ignore_nice_load);
gov_show_one_common(min_sampling_rate);
gov_show_one(cs, down_threshold);
gov_show_one(cs, freq_step);

gov_attr_rw(sampling_rate);
gov_attr_rw(sampling_down_factor);
gov_attr_rw(up_threshold);
gov_attr_rw(ignore_nice_load);
gov_attr_ro(min_sampling_rate);
gov_attr_rw(down_threshold);
gov_attr_rw(freq_step);

static struct attribute *cs_attributes[] = {
	&min_sampling_rate.attr,
	&sampling_rate.attr,
	&sampling_down_factor.attr,
	&up_threshold.attr,
	&down_threshold.attr,
	&ignore_nice_load.attr,
	&freq_step.attr,
	NULL
};

static struct attribute_group cs_attr_group_gov_sys = {
	.attrs = dbs_attributes_gov_sys,
	.name = "conservative",
};
/************************** sysfs end ************************/

static struct attribute *dbs_attributes_gov_pol[] = {
	&sampling_rate_min_gov_pol.attr,
	&sampling_rate_gov_pol.attr,
	&sampling_down_factor_gov_pol.attr,
	&up_threshold_gov_pol.attr,
	&down_threshold_gov_pol.attr,
	&ignore_nice_load_gov_pol.attr,
	&freq_step_gov_pol.attr,
	NULL
};
static struct policy_dbs_info *cs_alloc(void)
{
	struct cs_policy_dbs_info *dbs_info;

static struct attribute_group cs_attr_group_gov_pol = {
	.attrs = dbs_attributes_gov_pol,
	.name = "conservative",
};
	dbs_info = kzalloc(sizeof(*dbs_info), GFP_KERNEL);
	return dbs_info ? &dbs_info->policy_dbs : NULL;
}

/************************** sysfs end ************************/
static void cs_free(struct policy_dbs_info *policy_dbs)
{
	kfree(to_dbs_info(policy_dbs));
}

static int cs_init(struct dbs_data *dbs_data, bool notify)
{
@@ -332,11 +273,11 @@ static int cs_init(struct dbs_data *dbs_data, bool notify)
		return -ENOMEM;
	}

	tuners->up_threshold = DEF_FREQUENCY_UP_THRESHOLD;
	tuners->down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD;
	tuners->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR;
	tuners->ignore_nice_load = 0;
	tuners->freq_step = DEF_FREQUENCY_STEP;
	dbs_data->up_threshold = DEF_FREQUENCY_UP_THRESHOLD;
	dbs_data->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR;
	dbs_data->ignore_nice_load = 0;

	dbs_data->tuners = tuners;
	dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO *
@@ -358,35 +299,66 @@ static void cs_exit(struct dbs_data *dbs_data, bool notify)
	kfree(dbs_data->tuners);
}

define_get_cpu_dbs_routines(cs_cpu_dbs_info);
static void cs_start(struct cpufreq_policy *policy)
{
	struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data);

	dbs_info->down_skip = 0;
	dbs_info->requested_freq = policy->cur;
}

static struct common_dbs_data cs_dbs_cdata = {
	.governor = GOV_CONSERVATIVE,
	.attr_group_gov_sys = &cs_attr_group_gov_sys,
	.attr_group_gov_pol = &cs_attr_group_gov_pol,
	.get_cpu_cdbs = get_cpu_cdbs,
	.get_cpu_dbs_info_s = get_cpu_dbs_info_s,
static struct dbs_governor cs_dbs_gov = {
	.gov = {
		.name = "conservative",
		.governor = cpufreq_governor_dbs,
		.max_transition_latency = TRANSITION_LATENCY_LIMIT,
		.owner = THIS_MODULE,
	},
	.kobj_type = { .default_attrs = cs_attributes },
	.gov_dbs_timer = cs_dbs_timer,
	.gov_check_cpu = cs_check_cpu,
	.alloc = cs_alloc,
	.free = cs_free,
	.init = cs_init,
	.exit = cs_exit,
	.mutex = __MUTEX_INITIALIZER(cs_dbs_cdata.mutex),
	.start = cs_start,
};

static int cs_cpufreq_governor_dbs(struct cpufreq_policy *policy,
				   unsigned int event)
#define CPU_FREQ_GOV_CONSERVATIVE	(&cs_dbs_gov.gov)

static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
				void *data)
{
	return cpufreq_governor_dbs(policy, &cs_dbs_cdata, event);
	struct cpufreq_freqs *freq = data;
	struct cpufreq_policy *policy = cpufreq_cpu_get_raw(freq->cpu);
	struct cs_policy_dbs_info *dbs_info;

	if (!policy)
		return 0;

	/* policy isn't governed by conservative governor */
	if (policy->governor != CPU_FREQ_GOV_CONSERVATIVE)
		return 0;

	dbs_info = to_dbs_info(policy->governor_data);
	/*
	 * we only care if our internally tracked freq moves outside the 'valid'
	 * ranges of frequency available to us otherwise we do not change it
	*/
	if (dbs_info->requested_freq > policy->max
			|| dbs_info->requested_freq < policy->min)
		dbs_info->requested_freq = freq->new;

	return 0;
}

static int __init cpufreq_gov_dbs_init(void)
{
	return cpufreq_register_governor(&cpufreq_gov_conservative);
	return cpufreq_register_governor(CPU_FREQ_GOV_CONSERVATIVE);
}

static void __exit cpufreq_gov_dbs_exit(void)
{
	cpufreq_unregister_governor(&cpufreq_gov_conservative);
	cpufreq_unregister_governor(CPU_FREQ_GOV_CONSERVATIVE);
}

MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>");
@@ -398,7 +370,7 @@ MODULE_LICENSE("GPL");
#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
struct cpufreq_governor *cpufreq_default_governor(void)
{
	return &cpufreq_gov_conservative;
	return CPU_FREQ_GOV_CONSERVATIVE;
}

fs_initcall(cpufreq_gov_dbs_init);
+403 −363

File changed.

Preview size limit exceeded, changes collapsed.

Loading