Merge tag 'bcm2835-dt-next-2018-04-30' into devicetree/next
[platform/kernel/linux-rpi.git] / kernel / sched / idle.c
index 2975f19..1a3e9bd 100644 (file)
@@ -141,13 +141,15 @@ static void cpuidle_idle_call(void)
        }
 
        /*
-        * Tell the RCU framework we are entering an idle section,
-        * so no more rcu read side critical sections and one more
+        * The RCU framework needs to be told that we are entering an idle
+        * section, so no more rcu read side critical sections and one more
         * step to the grace period
         */
-       rcu_idle_enter();
 
        if (cpuidle_not_available(drv, dev)) {
+               tick_nohz_idle_stop_tick();
+               rcu_idle_enter();
+
                default_idle_call();
                goto exit_idle;
        }
@@ -164,20 +166,37 @@ static void cpuidle_idle_call(void)
 
        if (idle_should_enter_s2idle() || dev->use_deepest_state) {
                if (idle_should_enter_s2idle()) {
+                       rcu_idle_enter();
+
                        entered_state = cpuidle_enter_s2idle(drv, dev);
                        if (entered_state > 0) {
                                local_irq_enable();
                                goto exit_idle;
                        }
+
+                       rcu_idle_exit();
                }
 
+               tick_nohz_idle_stop_tick();
+               rcu_idle_enter();
+
                next_state = cpuidle_find_deepest_state(drv, dev);
                call_cpuidle(drv, dev, next_state);
        } else {
+               bool stop_tick = true;
+
                /*
                 * Ask the cpuidle framework to choose a convenient idle state.
                 */
-               next_state = cpuidle_select(drv, dev);
+               next_state = cpuidle_select(drv, dev, &stop_tick);
+
+               if (stop_tick)
+                       tick_nohz_idle_stop_tick();
+               else
+                       tick_nohz_idle_retain_tick();
+
+               rcu_idle_enter();
+
                entered_state = call_cpuidle(drv, dev, next_state);
                /*
                 * Give the governor an opportunity to reflect on the outcome
@@ -222,6 +241,7 @@ static void do_idle(void)
                rmb();
 
                if (cpu_is_offline(cpu)) {
+                       tick_nohz_idle_stop_tick_protected();
                        cpuhp_report_idle_dead();
                        arch_cpu_idle_dead();
                }
@@ -235,10 +255,12 @@ static void do_idle(void)
                 * broadcast device expired for us, we don't want to go deep
                 * idle as we know that the IPI is going to arrive right away.
                 */
-               if (cpu_idle_force_poll || tick_check_broadcast_expired())
+               if (cpu_idle_force_poll || tick_check_broadcast_expired()) {
+                       tick_nohz_idle_restart_tick();
                        cpu_idle_poll();
-               else
+               } else {
                        cpuidle_idle_call();
+               }
                arch_cpu_idle_exit();
        }