Merge branch 'pm-cpuidle' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
authorIngo Molnar <mingo@kernel.org>
Thu, 22 May 2014 08:37:06 +0000 (10:37 +0200)
committerIngo Molnar <mingo@kernel.org>
Thu, 22 May 2014 08:37:06 +0000 (10:37 +0200)
Pull scheduling related CPU idle updates from Rafael J. Wysocki.

Conflicts:
kernel/sched/idle.c

Signed-off-by: Ingo Molnar <mingo@kernel.org>
1  2 
kernel/sched/idle.c

index 34083c9ac976ecf7e26e1a08566e7eb18c5f04c2,a8f12247ce7c015dc334fbbda54fee98039a0a88..25b9423abce9fa54052abb49946ad6561f1dfed7
@@@ -98,74 -101,77 +98,69 @@@ static void cpuidle_idle_call(void
        rcu_idle_enter();
  
        /*
-        * Check if the cpuidle framework is ready, otherwise fallback
-        * to the default arch specific idle method
+        * Ask the cpuidle framework to choose a convenient idle state.
 -       * Fall back to the default arch specific idle method on errors.
++       * Fall back to the default arch idle method on errors.
         */
-       if (cpuidle_enabled(drv, dev)) {
+       next_state = cpuidle_select(drv, dev);
 -
 -      ret = next_state;
 -      if (ret >= 0) {
++      if (next_state < 0) {
 +use_default:
                /*
 -               * The idle task must be scheduled, it is pointless to
 -               * go to idle, just update no idle residency and get
 -               * out of this function
 +               * We can't use the cpuidle framework, let's use the default
 +               * idle routine.
                 */
 -              if (current_clr_polling_and_test()) {
 -                      dev->last_residency = 0;
 -                      entered_state = next_state;
 +              if (current_clr_polling_and_test())
                        local_irq_enable();
 -              } else {
 -                      broadcast = !!(drv->states[next_state].flags &
 -                                     CPUIDLE_FLAG_TIMER_STOP);
 -
 -                      if (broadcast)
 -                              /*
 -                               * Tell the time framework to switch
 -                               * to a broadcast timer because our
 -                               * local timer will be shutdown. If a
 -                               * local timer is used from another
 -                               * cpu as a broadcast timer, this call
 -                               * may fail if it is not available
 -                               */
 -                              ret = clockevents_notify(
 -                                      CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
 -                                      &dev->cpu);
 -
 -                      if (ret >= 0) {
 -                              trace_cpu_idle_rcuidle(next_state, dev->cpu);
 -
 -                              /*
 -                               * Enter the idle state previously
 -                               * returned by the governor
 -                               * decision. This function will block
 -                               * until an interrupt occurs and will
 -                               * take care of re-enabling the local
 -                               * interrupts
 -                               */
 -                              entered_state = cpuidle_enter(drv, dev,
 -                                                            next_state);
 -
 -                              trace_cpu_idle_rcuidle(PWR_EVENT_EXIT,
 -                                                     dev->cpu);
 -
 -                              if (broadcast)
 -                                      clockevents_notify(
 -                                              CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
 -                                              &dev->cpu);
 -
 -                              /*
 -                               * Give the governor an opportunity to reflect on the
 -                               * outcome
 -                               */
 -                              cpuidle_reflect(dev, entered_state);
 -                      }
 -              }
 +              else
 +                      arch_cpu_idle();
 +
 +              goto exit_idle;
 +      }
 +
-       /*
-        * Ask the governor to choose an idle state it thinks
-        * it is convenient to go to. There is *always* a
-        * convenient idle state
-        */
-       next_state = cpuidle_select(drv, dev);
 +
 +      /*
 +       * The idle task must be scheduled, it is pointless to
 +       * go to idle, just update no idle residency and get
 +       * out of this function
 +       */
 +      if (current_clr_polling_and_test()) {
 +              dev->last_residency = 0;
 +              entered_state = next_state;
 +              local_irq_enable();
 +              goto exit_idle;
        }
  
 +      broadcast = !!(drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP);
 +
 +      /*
 +       * Tell the time framework to switch to a broadcast timer
 +       * because our local timer will be shutdown. If a local timer
 +       * is used from another cpu as a broadcast timer, this call may
 +       * fail if it is not available
 +       */
 +      if (broadcast &&
 +          clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu))
 +              goto use_default;
 +
 +      trace_cpu_idle_rcuidle(next_state, dev->cpu);
 +
        /*
 -       * We can't use the cpuidle framework, let's use the default
 -       * idle routine
 +       * Enter the idle state previously returned by the governor decision.
 +       * This function will block until an interrupt occurs and will take
 +       * care of re-enabling the local interrupts
         */
 -      if (ret < 0)
 -              arch_cpu_idle();
 +      entered_state = cpuidle_enter(drv, dev, next_state);
 +
 +      trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu);
  
 +      if (broadcast)
 +              clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
 +
 +      /*
 +       * Give the governor an opportunity to reflect on the outcome
 +       */
 +      cpuidle_reflect(dev, entered_state);
 +
 +exit_idle:
        __current_set_polling();
  
        /*