staging: binder: add __user annotation in binder.c
[GitHub/LineageOS/android_kernel_samsung_universal7580.git] / kernel / cpu.c
index b5e4ab2d427e874404347c7e20186ed4cfd2f488..c9f59f20bbcd493e16af42eeddf91348a1e7ec5c 100644 (file)
 #include <linux/gfp.h>
 #include <linux/suspend.h>
 
+#if defined(CONFIG_ARM_EXYNOS_MP_CPUFREQ) || defined(CONFIG_ARM_EXYNOS_SMP_CPUFREQ)
+#include <mach/cpufreq.h>
+#endif
+
 #include "smpboot.h"
 
 #ifdef CONFIG_SMP
 static DEFINE_MUTEX(cpu_add_remove_lock);
 
 /*
- * The following two API's must be used when attempting
- * to serialize the updates to cpu_online_mask, cpu_present_mask.
+ * The following two APIs (cpu_maps_update_begin/done) must be used when
+ * attempting to serialize the updates to cpu_online_mask & cpu_present_mask.
+ * The APIs cpu_notifier_register_begin/done() must be used to protect CPU
+ * hotplug callback (un)registration performed using __register_cpu_notifier()
+ * or __unregister_cpu_notifier().
  */
 void cpu_maps_update_begin(void)
 {
        mutex_lock(&cpu_add_remove_lock);
 }
+EXPORT_SYMBOL(cpu_notifier_register_begin);
 
 void cpu_maps_update_done(void)
 {
        mutex_unlock(&cpu_add_remove_lock);
 }
+EXPORT_SYMBOL(cpu_notifier_register_done);
 
 static RAW_NOTIFIER_HEAD(cpu_chain);
 
@@ -133,6 +142,27 @@ static void cpu_hotplug_done(void)
        mutex_unlock(&cpu_hotplug.lock);
 }
 
+/*
+ * Wait for currently running CPU hotplug operations to complete (if any) and
+ * disable future CPU hotplug (from sysfs). The 'cpu_add_remove_lock' protects
+ * the 'cpu_hotplug_disabled' flag. The same lock is also acquired by the
+ * hotplug path before performing hotplug operations. So acquiring that lock
+ * guarantees mutual exclusion from any currently running hotplug operations.
+ */
+void cpu_hotplug_disable(void)
+{
+       cpu_maps_update_begin();
+       cpu_hotplug_disabled = 1;
+       cpu_maps_update_done();
+}
+
+void cpu_hotplug_enable(void)
+{
+       cpu_maps_update_begin();
+       cpu_hotplug_disabled = 0;
+       cpu_maps_update_done();
+}
+
 #else /* #if CONFIG_HOTPLUG_CPU */
 static void cpu_hotplug_begin(void) {}
 static void cpu_hotplug_done(void) {}
@@ -148,6 +178,11 @@ int __ref register_cpu_notifier(struct notifier_block *nb)
        return ret;
 }
 
+int __ref __register_cpu_notifier(struct notifier_block *nb)
+{
+       return raw_notifier_chain_register(&cpu_chain, nb);
+}
+
 static int __cpu_notify(unsigned long val, void *v, int nr_to_call,
                        int *nr_calls)
 {
@@ -171,6 +206,7 @@ static void cpu_notify_nofail(unsigned long val, void *v)
        BUG_ON(cpu_notify(val, v));
 }
 EXPORT_SYMBOL(register_cpu_notifier);
+EXPORT_SYMBOL(__register_cpu_notifier);
 
 void __ref unregister_cpu_notifier(struct notifier_block *nb)
 {
@@ -180,6 +216,12 @@ void __ref unregister_cpu_notifier(struct notifier_block *nb)
 }
 EXPORT_SYMBOL(unregister_cpu_notifier);
 
+void __ref __unregister_cpu_notifier(struct notifier_block *nb)
+{
+       raw_notifier_chain_unregister(&cpu_chain, nb);
+}
+EXPORT_SYMBOL(__unregister_cpu_notifier);
+
 /**
  * clear_tasks_mm_cpumask - Safely clear tasks' mm_cpumask for a CPU
  * @cpu: a CPU id
@@ -460,6 +502,14 @@ static cpumask_var_t frozen_cpus;
 int disable_nonboot_cpus(void)
 {
        int cpu, first_cpu, error = 0;
+#if defined(CONFIG_ARM_EXYNOS_MP_CPUFREQ) || defined(CONFIG_ARM_EXYNOS_SMP_CPUFREQ)
+       int lated_cpu;
+
+       if (exynos_boot_cluster == CL_ZERO)
+               lated_cpu = NR_CLUST0_CPUS;
+       else
+               lated_cpu = NR_CLUST1_CPUS;
+#endif
 
        cpu_maps_update_begin();
        first_cpu = cpumask_first(cpu_online_mask);
@@ -471,7 +521,11 @@ int disable_nonboot_cpus(void)
 
        printk("Disabling non-boot CPUs ...\n");
        for_each_online_cpu(cpu) {
+#if defined(CONFIG_ARM_EXYNOS_MP_CPUFREQ) || defined(CONFIG_ARM_EXYNOS_SMP_CPUFREQ)
+               if (cpu == first_cpu || cpu == lated_cpu)
+#else
                if (cpu == first_cpu)
+#endif
                        continue;
                error = _cpu_down(cpu, 1);
                if (!error)
@@ -483,6 +537,16 @@ int disable_nonboot_cpus(void)
                }
        }
 
+#if defined(CONFIG_ARM_EXYNOS_MP_CPUFREQ) || defined(CONFIG_ARM_EXYNOS_SMP_CPUFREQ)
+       if (num_online_cpus() > 1) {
+               error = _cpu_down(lated_cpu, 1);
+               if (!error)
+                       cpumask_set_cpu(lated_cpu, frozen_cpus);
+               else
+                       printk(KERN_ERR "Error taking CPU%d down: %d\n",
+                               lated_cpu, error);
+       }
+#endif
        if (!error) {
                BUG_ON(num_online_cpus() > 1);
                /* Make sure the CPUs won't be enabled by someone else */
@@ -502,6 +566,11 @@ void __weak arch_enable_nonboot_cpus_end(void)
 {
 }
 
+#if defined(CONFIG_SCHED_HMP) && defined(CONFIG_EXYNOS5_DYNAMIC_CPU_HOTPLUG)
+extern struct cpumask hmp_slow_cpu_mask;
+extern int disable_dm_hotplug_before_suspend;
+#endif
+
 void __ref enable_nonboot_cpus(void)
 {
        int cpu, error;
@@ -516,6 +585,11 @@ void __ref enable_nonboot_cpus(void)
 
        arch_enable_nonboot_cpus_begin();
 
+#if defined(CONFIG_SCHED_HMP) && defined(CONFIG_EXYNOS5_DYNAMIC_CPU_HOTPLUG)
+       if (!disable_dm_hotplug_before_suspend)
+               cpumask_and(frozen_cpus, frozen_cpus, &hmp_slow_cpu_mask);
+#endif
+
        for_each_cpu(cpu, frozen_cpus) {
                error = _cpu_up(cpu, 1);
                if (!error) {
@@ -540,36 +614,6 @@ static int __init alloc_frozen_cpus(void)
 }
 core_initcall(alloc_frozen_cpus);
 
-/*
- * Prevent regular CPU hotplug from racing with the freezer, by disabling CPU
- * hotplug when tasks are about to be frozen. Also, don't allow the freezer
- * to continue until any currently running CPU hotplug operation gets
- * completed.
- * To modify the 'cpu_hotplug_disabled' flag, we need to acquire the
- * 'cpu_add_remove_lock'. And this same lock is also taken by the regular
- * CPU hotplug path and released only after it is complete. Thus, we
- * (and hence the freezer) will block here until any currently running CPU
- * hotplug operation gets completed.
- */
-void cpu_hotplug_disable_before_freeze(void)
-{
-       cpu_maps_update_begin();
-       cpu_hotplug_disabled = 1;
-       cpu_maps_update_done();
-}
-
-
-/*
- * When tasks have been thawed, re-enable regular CPU hotplug (which had been
- * disabled while beginning to freeze tasks).
- */
-void cpu_hotplug_enable_after_thaw(void)
-{
-       cpu_maps_update_begin();
-       cpu_hotplug_disabled = 0;
-       cpu_maps_update_done();
-}
-
 /*
  * When callbacks for CPU hotplug notifications are being executed, we must
  * ensure that the state of the system with respect to the tasks being frozen
@@ -589,12 +633,12 @@ cpu_hotplug_pm_callback(struct notifier_block *nb,
 
        case PM_SUSPEND_PREPARE:
        case PM_HIBERNATION_PREPARE:
-               cpu_hotplug_disable_before_freeze();
+               cpu_hotplug_disable();
                break;
 
        case PM_POST_SUSPEND:
        case PM_POST_HIBERNATION:
-               cpu_hotplug_enable_after_thaw();
+               cpu_hotplug_enable();
                break;
 
        default:
@@ -707,10 +751,12 @@ void set_cpu_present(unsigned int cpu, bool present)
 
 void set_cpu_online(unsigned int cpu, bool online)
 {
-       if (online)
+       if (online) {
                cpumask_set_cpu(cpu, to_cpumask(cpu_online_bits));
-       else
+               cpumask_set_cpu(cpu, to_cpumask(cpu_active_bits));
+       } else {
                cpumask_clear_cpu(cpu, to_cpumask(cpu_online_bits));
+       }
 }
 
 void set_cpu_active(unsigned int cpu, bool active)
@@ -735,3 +781,23 @@ void init_cpu_online(const struct cpumask *src)
 {
        cpumask_copy(to_cpumask(cpu_online_bits), src);
 }
+
+static ATOMIC_NOTIFIER_HEAD(idle_notifier);
+
+void idle_notifier_register(struct notifier_block *n)
+{
+       atomic_notifier_chain_register(&idle_notifier, n);
+}
+EXPORT_SYMBOL_GPL(idle_notifier_register);
+
+void idle_notifier_unregister(struct notifier_block *n)
+{
+       atomic_notifier_chain_unregister(&idle_notifier, n);
+}
+EXPORT_SYMBOL_GPL(idle_notifier_unregister);
+
+void idle_notifier_call_chain(unsigned long val)
+{
+       atomic_notifier_call_chain(&idle_notifier, val, NULL);
+}
+EXPORT_SYMBOL_GPL(idle_notifier_call_chain);