ANDROID: cpufreq: interactive: Use idle-end notifiers

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>

[AmitP: Cherry-picked this patch from
        https://git.kernel.org/cgit/linux/kernel/git/vireshk/pm.git/log/?h=cpufreq/interactive-idle-notifier]
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c
index 2fa2b50..d6cac0e 100644
--- a/drivers/cpufreq/cpufreq_interactive.c
+++ b/drivers/cpufreq/cpufreq_interactive.c
@@ -113,6 +113,7 @@
 
 	struct irq_work irq_work;
 	u64 last_sample_time;
+	unsigned long next_sample_jiffies;
 	bool work_in_progress;
 
 	struct rw_semaphore enable_sem;
@@ -471,6 +472,26 @@
 	slack_timer_resched(icpu, smp_processor_id(), true);
 }
 
+static void cpufreq_interactive_idle_end(void)
+{
+	struct interactive_cpu *icpu = &per_cpu(interactive_cpu,
+						smp_processor_id());
+
+	if (!down_read_trylock(&icpu->enable_sem))
+		return;
+
+	if (icpu->ipolicy) {
+		/*
+		 * We haven't sampled load for more than sampling_rate time, do
+		 * it right now.
+		 */
+		if (time_after_eq(jiffies, icpu->next_sample_jiffies))
+			cpufreq_interactive_update(icpu);
+	}
+
+	up_read(&icpu->enable_sem);
+}
+
 static void cpufreq_interactive_get_policy_info(struct cpufreq_policy *policy,
 						unsigned int *pmax_freq,
 						u64 *phvt, u64 *pfvt)
@@ -989,6 +1010,19 @@
 	.sysfs_ops = &governor_sysfs_ops,
 };
 
+static int cpufreq_interactive_idle_notifier(struct notifier_block *nb,
+					     unsigned long val, void *data)
+{
+	if (val == IDLE_END)
+		cpufreq_interactive_idle_end();
+
+	return 0;
+}
+
+static struct notifier_block cpufreq_interactive_idle_nb = {
+	.notifier_call = cpufreq_interactive_idle_notifier,
+};
+
 /* Interactive Governor callbacks */
 struct interactive_governor {
 	struct cpufreq_governor gov;
@@ -1031,6 +1065,8 @@
 		return;
 
 	icpu->last_sample_time = time;
+	icpu->next_sample_jiffies = usecs_to_jiffies(tunables->sampling_rate) +
+				    jiffies;
 
 	icpu->work_in_progress = true;
 	irq_work_queue(&icpu->irq_work);
@@ -1046,6 +1082,7 @@
 		icpu = &per_cpu(interactive_cpu, cpu);
 
 		icpu->last_sample_time = 0;
+		icpu->next_sample_jiffies = 0;
 		cpufreq_add_update_util_hook(cpu, &icpu->update_util,
 					     update_util_handler);
 	}
@@ -1176,6 +1213,7 @@
 
 	/* One time initialization for governor */
 	if (!interactive_gov.usage_count++) {
+		idle_notifier_register(&cpufreq_interactive_idle_nb);
 		cpufreq_register_notifier(&cpufreq_notifier_block,
 					  CPUFREQ_TRANSITION_NOTIFIER);
 	}
@@ -1209,6 +1247,7 @@
 	if (!--interactive_gov.usage_count) {
 		cpufreq_unregister_notifier(&cpufreq_notifier_block,
 					    CPUFREQ_TRANSITION_NOTIFIER);
+		idle_notifier_unregister(&cpufreq_interactive_idle_nb);
 	}
 
 	count = gov_attr_set_put(&tunables->attr_set, &ipolicy->tunables_hook);