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

Commit 7e4ab026 authored by Ashwini Jain's avatar Ashwini Jain Committed by laxman
Browse files

porting target load for power consumption issue

Change-Id: Ied7c808e1262000facaa676cbca7e0c6d61f7020
parent e58d0cd5
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -771,3 +771,4 @@ CONFIG_SLA_ALGO=y
CONFIG_RATP=y
CONFIG_RATP=y
CONFIG_QCOM_QDSS_BRIDGE=y
CONFIG_QCOM_QDSS_BRIDGE=y
CONFIG_CPUFREQ_BOUNCING=y
CONFIG_CPUFREQ_BOUNCING=y
CONFIG_OPLUS_FEATURE_SUGOV_TL=y
+1 −0
Original line number Original line Diff line number Diff line
@@ -835,3 +835,4 @@ CONFIG_SLA=y
CONFIG_SLA_ALGO=y
CONFIG_SLA_ALGO=y
CONFIG_RATP=y
CONFIG_RATP=y
CONFIG_CPUFREQ_BOUNCING=y
CONFIG_CPUFREQ_BOUNCING=y
CONFIG_OPLUS_FEATURE_SUGOV_TL=y
+60 −0
Original line number Original line Diff line number Diff line
@@ -901,6 +901,66 @@ TRACE_EVENT(memlat_dev_update,
		__entry->vote)
		__entry->vote)
);
);


#ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL
TRACE_EVENT(sugov_next_freq_tl,
	    TP_PROTO(unsigned int cpu, unsigned long util, unsigned long max,
		     unsigned int freq, unsigned int laf, unsigned int prev_freq),
	    TP_ARGS(cpu, util, max, freq, laf, prev_freq),
	    TP_STRUCT__entry(
		    __field(unsigned int, cpu)
		    __field(unsigned long, util)
		    __field(unsigned long, max)
		    __field(unsigned int, freq)
		    __field(unsigned int, laf)
		    __field(unsigned int, prev_freq)
	    ),
	    TP_fast_assign(
		    __entry->cpu = cpu;
		    __entry->util = util;
		    __entry->max = max;
		    __entry->freq = freq;
		    __entry->laf = laf;
		    __entry->prev_freq = prev_freq;
	    ),
	    TP_printk("cpu=%u util=%lu max=%lu freq=%u laf=%u, prev_freq=%u",
		      __entry->cpu,
		      __entry->util,
		      __entry->max,
		      __entry->freq,
		      __entry->laf,
		      __entry->prev_freq)
);

TRACE_EVENT(choose_freq,
	    TP_PROTO(unsigned int freq, unsigned int prevfreq, unsigned int freqmax,
		     unsigned int freqmin, unsigned int tl, int index),
	    TP_ARGS(freq, prevfreq, freqmax, freqmin, tl, index),
	    TP_STRUCT__entry(
		    __field(unsigned int, freq)
		    __field(unsigned int, prevfreq)
		    __field(unsigned int, freqmax)
		    __field(unsigned int, freqmin)
		    __field(unsigned int, tl)
		    __field(int, index)
	    ),
	    TP_fast_assign(
		    __entry->freq = freq;
		    __entry->prevfreq = prevfreq;
		    __entry->freqmax = freqmax;
		    __entry->freqmin = freqmin;
		    __entry->tl = tl;
		    __entry->index = index;
	    ),
	    TP_printk("freq=%u prevfreq=%u freqmax=%u freqmin=%u tl=%u index=%d",
		      __entry->freq,
		      __entry->prevfreq,
		      __entry->freqmax,
		      __entry->freqmin,
		      __entry->tl,
		      __entry->index)
);
#endif

#endif /* _TRACE_POWER_H */
#endif /* _TRACE_POWER_H */


/* This part must be outside protection */
/* This part must be outside protection */
+233 −1
Original line number Original line Diff line number Diff line
@@ -26,6 +26,12 @@
#endif
#endif
#include <linux/oem/cpufreq_bouncing.h>
#include <linux/oem/cpufreq_bouncing.h>


#ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL
/* Target load. Lower values result in higher CPU speeds. */
#define DEFAULT_TARGET_LOAD 80
static unsigned int default_target_loads[] = {DEFAULT_TARGET_LOAD};
#endif

struct sugov_tunables {
struct sugov_tunables {
	struct gov_attr_set	attr_set;
	struct gov_attr_set	attr_set;
	unsigned int		up_rate_limit_us;
	unsigned int		up_rate_limit_us;
@@ -34,6 +40,11 @@ struct sugov_tunables {
	unsigned int		hispeed_freq;
	unsigned int		hispeed_freq;
	unsigned int		rtg_boost_freq;
	unsigned int		rtg_boost_freq;
	bool			pl;
	bool			pl;
#ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL
	spinlock_t		target_loads_lock;
	unsigned int		*target_loads;
	int			ntarget_loads;
#endif /* CONFIG_OPLUS_FEATURE_SUGOV_TL */
};
};


struct sugov_policy {
struct sugov_policy {
@@ -318,6 +329,111 @@ static void sugov_deferred_update(struct sugov_policy *sg_policy, u64 time,
}
}


#define TARGET_LOAD 80
#define TARGET_LOAD 80

#ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL
static unsigned int freq_to_targetload(
	struct sugov_tunables *tunables, unsigned int freq)
{
	int i;
	unsigned int ret;
	unsigned long flags;

	spin_lock_irqsave(&tunables->target_loads_lock, flags);

	for (i = 0; i < tunables->ntarget_loads - 1 &&
		     freq >= tunables->target_loads[i+1]; i += 2)
		;

	ret = tunables->target_loads[i];
	spin_unlock_irqrestore(&tunables->target_loads_lock, flags);
	return ret;
}


static unsigned int choose_freq(struct sugov_policy *sg_policy,
		unsigned int loadadjfreq)
{
	struct cpufreq_policy *policy = sg_policy->policy;
	unsigned int freq = policy->cur;
	unsigned int prevfreq, freqmin, freqmax;
	unsigned int tl;
	int index;

	freqmin = 0;
	freqmax = UINT_MAX;

	do {
		prevfreq = freq;
		tl = freq_to_targetload(sg_policy->tunables, freq);

		/*
		 * Find the lowest frequency where the computed load is less
		 * than or equal to the target load.
		 */

		index = cpufreq_frequency_table_target(policy,
						       loadadjfreq / tl,
						       CPUFREQ_RELATION_L);
		freq = policy->freq_table[index].frequency;

		trace_choose_freq(freq, prevfreq, freqmax, freqmin, tl, index);

		if (freq > prevfreq) {
			/* The previous frequency is too low. */
			freqmin = prevfreq;

			if (freq >= freqmax) {
				/*
				 * Find the highest frequency that is less
				 * than freqmax.
				 */
				index = cpufreq_frequency_table_target(
					    policy,
					    freqmax - 1, CPUFREQ_RELATION_H);
				freq = policy->freq_table[index].frequency;

				if (freq == freqmin) {
					/*
					 * The first frequency below freqmax
					 * has already been found to be too
					 * low.  freqmax is the lowest speed
					 * we found that is fast enough.
					 */
					freq = freqmax;
					break;
				}
			}
		} else if (freq < prevfreq) {
			/* The previous frequency is high enough. */
			freqmax = prevfreq;

			if (freq <= freqmin) {
				/*
				 * Find the lowest frequency that is higher
				 * than freqmin.
				 */
				index = cpufreq_frequency_table_target(
					    policy,
					    freqmin + 1, CPUFREQ_RELATION_L);
				freq = policy->freq_table[index].frequency;

				/*
				 * If freqmax is the first frequency above
				 * freqmin then we have already found that
				 * this speed is fast enough.
				 */
				if (freq == freqmax)
					break;
			}
		}

		/* If same frequency chosen as previous then done. */
	} while (freq != prevfreq);

	return freq;
}
#endif /* CONFIG_OPLUS_FEATURE_SUGOV_TL */

/**
/**
 * get_next_freq - Compute a new frequency for a given cpufreq policy.
 * get_next_freq - Compute a new frequency for a given cpufreq policy.
 * @sg_policy: schedutil policy object to compute the new frequency for.
 * @sg_policy: schedutil policy object to compute the new frequency for.
@@ -349,8 +465,15 @@ static unsigned int get_next_freq(struct sugov_policy *sg_policy,
#ifdef CONFIG_CONTROL_CENTER
#ifdef CONFIG_CONTROL_CENTER
	unsigned int req_freq;
	unsigned int req_freq;


	freq = map_util_freq(util, freq, max);
#ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL
	unsigned int prev_freq = freq;
	unsigned int prev_laf = prev_freq * util * 100 / max;


	freq = choose_freq(sg_policy, prev_laf);
	trace_sugov_next_freq_tl(policy->cpu, util, max, freq, prev_laf, prev_freq);
#else
	freq = map_util_freq(util, freq, max);
#endif
	if (freq == sg_policy->cached_raw_freq && !sg_policy->need_freq_update) {
	if (freq == sg_policy->cached_raw_freq && !sg_policy->need_freq_update) {
		req_freq = sg_policy->next_freq;
		req_freq = sg_policy->next_freq;
		goto out;
		goto out;
@@ -364,9 +487,17 @@ static unsigned int get_next_freq(struct sugov_policy *sg_policy,
	sg_policy->policy->req_freq = req_freq;
	sg_policy->policy->req_freq = req_freq;
	trace_sugov_next_freq(policy->cpu, util, max, freq, req_freq);
	trace_sugov_next_freq(policy->cpu, util, max, freq, req_freq);
	return req_freq;
	return req_freq;
#else
#ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL
	unsigned int prev_freq = freq;
	unsigned int prev_laf = prev_freq * util * 100 / max;

	freq = choose_freq(sg_policy, prev_laf);
	trace_sugov_next_freq_tl(policy->cpu, util, max, freq, prev_laf, prev_freq);
#else
#else
	freq = map_util_freq(util, freq, max);
	freq = map_util_freq(util, freq, max);
	trace_sugov_next_freq(policy->cpu, util, max, freq);
	trace_sugov_next_freq(policy->cpu, util, max, freq);
#endif


	if (freq == sg_policy->cached_raw_freq && !sg_policy->need_freq_update)
	if (freq == sg_policy->cached_raw_freq && !sg_policy->need_freq_update)
		return sg_policy->next_freq;
		return sg_policy->next_freq;
@@ -1123,11 +1254,103 @@ static ssize_t pl_store(struct gov_attr_set *attr_set, const char *buf,
	return count;
	return count;
}
}


#ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL
static ssize_t target_loads_show(struct gov_attr_set *attr_set, char *buf)
{
	struct sugov_tunables *tunables = to_sugov_tunables(attr_set);
	int i;
	ssize_t ret = 0;
	unsigned long flags;

	spin_lock_irqsave(&tunables->target_loads_lock, flags);
	for (i = 0; i < tunables->ntarget_loads; i++)
		ret += snprintf(buf + ret, PAGE_SIZE - ret - 1, "%u%s", tunables->target_loads[i],
			i & 0x1 ? ":" : " ");

	snprintf(buf + ret - 1, PAGE_SIZE - ret - 1, "\n");
	spin_unlock_irqrestore(&tunables->target_loads_lock, flags);
	return ret;
}

static unsigned int *get_tokenized_data(const char *buf, int *num_tokens)
{
	const char *cp;
	int i;
	int ntokens = 1;
	unsigned int *tokenized_data;
	int err = -EINVAL;

	cp = buf;
	while ((cp = strpbrk(cp + 1, " :")))
		ntokens++;

	if (!(ntokens & 0x1))
		goto err;

	tokenized_data = kmalloc(ntokens * sizeof(unsigned int), GFP_KERNEL);
	if (!tokenized_data) {
		err = -ENOMEM;
		goto err;
	}

	cp = buf;
	i = 0;
	while (i < ntokens) {
		if (sscanf(cp, "%u", &tokenized_data[i++]) != 1)
			goto err_kfree;

		cp = strpbrk(cp, " :");
		if (!cp)
			break;
		cp++;
	}

	if (i != ntokens)
		goto err_kfree;

	*num_tokens = ntokens;

	return tokenized_data;
err_kfree:
	kfree(tokenized_data);
err:
	return ERR_PTR(err);
}

static ssize_t target_loads_store(struct gov_attr_set *attr_set, const char *buf,
					size_t count)
{
	int ntokens;
	unsigned int *new_target_loads = NULL;
	unsigned long flags;
	struct sugov_tunables *tunables = to_sugov_tunables(attr_set);

	new_target_loads = get_tokenized_data(buf, &ntokens);
	if (IS_ERR(new_target_loads))
		return PTR_ERR(new_target_loads);

	spin_lock_irqsave(&tunables->target_loads_lock, flags);
	if (tunables->target_loads != default_target_loads)
		kfree(tunables->target_loads);

	tunables->target_loads = new_target_loads;
	tunables->ntarget_loads = ntokens;
	spin_unlock_irqrestore(&tunables->target_loads_lock, flags);

	return count;
}
#endif /* CONFIG_OPLUS_FEATURE_SUGOV_TL */

static struct governor_attr hispeed_load = __ATTR_RW(hispeed_load);
static struct governor_attr hispeed_load = __ATTR_RW(hispeed_load);
static struct governor_attr hispeed_freq = __ATTR_RW(hispeed_freq);
static struct governor_attr hispeed_freq = __ATTR_RW(hispeed_freq);
static struct governor_attr rtg_boost_freq = __ATTR_RW(rtg_boost_freq);
static struct governor_attr rtg_boost_freq = __ATTR_RW(rtg_boost_freq);
static struct governor_attr pl = __ATTR_RW(pl);
static struct governor_attr pl = __ATTR_RW(pl);


#ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL
static struct governor_attr target_loads =
	__ATTR(target_loads, 0664, target_loads_show, target_loads_store);
#endif /* CONFIG_OPLUS_FEATURE_SUGOV_TL */

static struct attribute *sugov_attributes[] = {
static struct attribute *sugov_attributes[] = {
	&up_rate_limit_us.attr,
	&up_rate_limit_us.attr,
	&down_rate_limit_us.attr,
	&down_rate_limit_us.attr,
@@ -1135,6 +1358,9 @@ static struct attribute *sugov_attributes[] = {
	&hispeed_freq.attr,
	&hispeed_freq.attr,
	&rtg_boost_freq.attr,
	&rtg_boost_freq.attr,
	&pl.attr,
	&pl.attr,
#ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL
	&target_loads.attr,
#endif /* CONFIG_OPLUS_FEATURE_SUGOV_TL */
	NULL
	NULL
};
};


@@ -1326,6 +1552,12 @@ static int sugov_init(struct cpufreq_policy *policy)
	tunables->hispeed_load = DEFAULT_HISPEED_LOAD;
	tunables->hispeed_load = DEFAULT_HISPEED_LOAD;
	tunables->hispeed_freq = 0;
	tunables->hispeed_freq = 0;


#ifdef CONFIG_OPLUS_FEATURE_SUGOV_TL
	tunables->target_loads = default_target_loads;
	tunables->ntarget_loads = ARRAY_SIZE(default_target_loads);
	spin_lock_init(&tunables->target_loads_lock);
#endif /* CONFIG_OPLUS_FEATURE_SUGOV_TL */

	switch (policy->cpu) {
	switch (policy->cpu) {
	default:
	default:
	case 0:
	case 0: