Commit 05bf58ca4b8f0be7d7af830f943f6d6b2c9ccee1

Authored by Linus Torvalds

Merge branch 'sched-idle-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull sched/idle changes from Ingo Molnar:
 "More idle code reorganization, to prepare for more integration.

  (Sent separately because it depended on pending timer work, which is
  now upstream)"

* 'sched-idle-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  sched/idle: Add more comments to the code
  sched/idle: Move idle conditions in cpuidle_idle main function
  sched/idle: Reorganize the idle loop
  cpuidle/idle: Move the cpuidle_idle_call function to idle.c
  idle/cpuidle: Split cpuidle_idle_call main function into smaller functions

Showing 3 changed files Side-by-side Diff

drivers/cpuidle/cpuidle.c
... ... @@ -65,6 +65,26 @@
65 65 }
66 66  
67 67 /**
  68 + * cpuidle_enabled - check if the cpuidle framework is ready
  69 + * @dev: cpuidle device for this cpu
  70 + * @drv: cpuidle driver for this cpu
  71 + *
  72 + * Return 0 on success, otherwise:
  73 + * -NODEV : the cpuidle framework is not available
  74 + * -EBUSY : the cpuidle framework is not initialized
  75 + */
  76 +int cpuidle_enabled(struct cpuidle_driver *drv, struct cpuidle_device *dev)
  77 +{
  78 + if (off || !initialized)
  79 + return -ENODEV;
  80 +
  81 + if (!drv || !dev || !dev->enabled)
  82 + return -EBUSY;
  83 +
  84 + return 0;
  85 +}
  86 +
  87 +/**
68 88 * cpuidle_enter_state - enter the state and update stats
69 89 * @dev: cpuidle device for this cpu
70 90 * @drv: cpuidle driver for this cpu
71 91  
72 92  
73 93  
74 94  
75 95  
76 96  
... ... @@ -109,63 +129,48 @@
109 129 }
110 130  
111 131 /**
112   - * cpuidle_idle_call - the main idle loop
  132 + * cpuidle_select - ask the cpuidle framework to choose an idle state
113 133 *
114   - * NOTE: no locks or semaphores should be used here
115   - * return non-zero on failure
  134 + * @drv: the cpuidle driver
  135 + * @dev: the cpuidle device
  136 + *
  137 + * Returns the index of the idle state.
116 138 */
117   -int cpuidle_idle_call(void)
  139 +int cpuidle_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
118 140 {
119   - struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
120   - struct cpuidle_driver *drv;
121   - int next_state, entered_state;
122   - bool broadcast;
  141 + return cpuidle_curr_governor->select(drv, dev);
  142 +}
123 143  
124   - if (off || !initialized)
125   - return -ENODEV;
  144 +/**
  145 + * cpuidle_enter - enter into the specified idle state
  146 + *
  147 + * @drv: the cpuidle driver tied with the cpu
  148 + * @dev: the cpuidle device
  149 + * @index: the index in the idle state table
  150 + *
  151 + * Returns the index in the idle state, < 0 in case of error.
  152 + * The error code depends on the backend driver
  153 + */
  154 +int cpuidle_enter(struct cpuidle_driver *drv, struct cpuidle_device *dev,
  155 + int index)
  156 +{
  157 + if (cpuidle_state_is_coupled(dev, drv, index))
  158 + return cpuidle_enter_state_coupled(dev, drv, index);
  159 + return cpuidle_enter_state(dev, drv, index);
  160 +}
126 161  
127   - /* check if the device is ready */
128   - if (!dev || !dev->enabled)
129   - return -EBUSY;
130   -
131   - drv = cpuidle_get_cpu_driver(dev);
132   -
133   - /* ask the governor for the next state */
134   - next_state = cpuidle_curr_governor->select(drv, dev);
135   - if (need_resched()) {
136   - dev->last_residency = 0;
137   - /* give the governor an opportunity to reflect on the outcome */
138   - if (cpuidle_curr_governor->reflect)
139   - cpuidle_curr_governor->reflect(dev, next_state);
140   - local_irq_enable();
141   - return 0;
142   - }
143   -
144   - broadcast = !!(drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP);
145   -
146   - if (broadcast &&
147   - clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu))
148   - return -EBUSY;
149   -
150   -
151   - trace_cpu_idle_rcuidle(next_state, dev->cpu);
152   -
153   - if (cpuidle_state_is_coupled(dev, drv, next_state))
154   - entered_state = cpuidle_enter_state_coupled(dev, drv,
155   - next_state);
156   - else
157   - entered_state = cpuidle_enter_state(dev, drv, next_state);
158   -
159   - trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu);
160   -
161   - if (broadcast)
162   - clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
163   -
164   - /* give the governor an opportunity to reflect on the outcome */
  162 +/**
  163 + * cpuidle_reflect - tell the underlying governor what was the state
  164 + * we were in
  165 + *
  166 + * @dev : the cpuidle device
  167 + * @index: the index in the idle state table
  168 + *
  169 + */
  170 +void cpuidle_reflect(struct cpuidle_device *dev, int index)
  171 +{
165 172 if (cpuidle_curr_governor->reflect)
166   - cpuidle_curr_governor->reflect(dev, entered_state);
167   -
168   - return 0;
  173 + cpuidle_curr_governor->reflect(dev, index);
169 174 }
170 175  
171 176 /**
include/linux/cpuidle.h
... ... @@ -119,7 +119,15 @@
119 119  
120 120 #ifdef CONFIG_CPU_IDLE
121 121 extern void disable_cpuidle(void);
122   -extern int cpuidle_idle_call(void);
  122 +
  123 +extern int cpuidle_enabled(struct cpuidle_driver *drv,
  124 + struct cpuidle_device *dev);
  125 +extern int cpuidle_select(struct cpuidle_driver *drv,
  126 + struct cpuidle_device *dev);
  127 +extern int cpuidle_enter(struct cpuidle_driver *drv,
  128 + struct cpuidle_device *dev, int index);
  129 +extern void cpuidle_reflect(struct cpuidle_device *dev, int index);
  130 +
123 131 extern int cpuidle_register_driver(struct cpuidle_driver *drv);
124 132 extern struct cpuidle_driver *cpuidle_get_driver(void);
125 133 extern struct cpuidle_driver *cpuidle_driver_ref(void);
... ... @@ -141,7 +149,16 @@
141 149 extern struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev);
142 150 #else
143 151 static inline void disable_cpuidle(void) { }
144   -static inline int cpuidle_idle_call(void) { return -ENODEV; }
  152 +static inline int cpuidle_enabled(struct cpuidle_driver *drv,
  153 + struct cpuidle_device *dev)
  154 +{return -ENODEV; }
  155 +static inline int cpuidle_select(struct cpuidle_driver *drv,
  156 + struct cpuidle_device *dev)
  157 +{return -ENODEV; }
  158 +static inline int cpuidle_enter(struct cpuidle_driver *drv,
  159 + struct cpuidle_device *dev, int index)
  160 +{return -ENODEV; }
  161 +static inline void cpuidle_reflect(struct cpuidle_device *dev, int index) { }
145 162 static inline int cpuidle_register_driver(struct cpuidle_driver *drv)
146 163 {return -ENODEV; }
147 164 static inline struct cpuidle_driver *cpuidle_get_driver(void) {return NULL; }
... ... @@ -163,6 +180,8 @@
163 180 {return -ENODEV; }
164 181 static inline void cpuidle_disable_device(struct cpuidle_device *dev) { }
165 182 static inline int cpuidle_play_dead(void) {return -ENODEV; }
  183 +static inline struct cpuidle_driver *cpuidle_get_cpu_driver(
  184 + struct cpuidle_device *dev) {return NULL; }
166 185 #endif
167 186  
168 187 #ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED
... ... @@ -63,6 +63,136 @@
63 63 local_irq_enable();
64 64 }
65 65  
  66 +/**
  67 + * cpuidle_idle_call - the main idle function
  68 + *
  69 + * NOTE: no locks or semaphores should be used here
  70 + * return non-zero on failure
  71 + */
  72 +static int cpuidle_idle_call(void)
  73 +{
  74 + struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
  75 + struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
  76 + int next_state, entered_state, ret;
  77 + bool broadcast;
  78 +
  79 + /*
  80 + * Check if the idle task must be rescheduled. If it is the
  81 + * case, exit the function after re-enabling the local irq and
  82 + * set again the polling flag
  83 + */
  84 + if (current_clr_polling_and_test()) {
  85 + local_irq_enable();
  86 + __current_set_polling();
  87 + return 0;
  88 + }
  89 +
  90 + /*
  91 + * During the idle period, stop measuring the disabled irqs
  92 + * critical sections latencies
  93 + */
  94 + stop_critical_timings();
  95 +
  96 + /*
  97 + * Tell the RCU framework we are entering an idle section,
  98 + * so no more rcu read side critical sections and one more
  99 + * step to the grace period
  100 + */
  101 + rcu_idle_enter();
  102 +
  103 + /*
  104 + * Check if the cpuidle framework is ready, otherwise fallback
  105 + * to the default arch specific idle method
  106 + */
  107 + ret = cpuidle_enabled(drv, dev);
  108 +
  109 + if (!ret) {
  110 + /*
  111 + * Ask the governor to choose an idle state it thinks
  112 + * it is convenient to go to. There is *always* a
  113 + * convenient idle state
  114 + */
  115 + next_state = cpuidle_select(drv, dev);
  116 +
  117 + /*
  118 + * The idle task must be scheduled, it is pointless to
  119 + * go to idle, just update no idle residency and get
  120 + * out of this function
  121 + */
  122 + if (current_clr_polling_and_test()) {
  123 + dev->last_residency = 0;
  124 + entered_state = next_state;
  125 + local_irq_enable();
  126 + } else {
  127 + broadcast = !!(drv->states[next_state].flags &
  128 + CPUIDLE_FLAG_TIMER_STOP);
  129 +
  130 + if (broadcast)
  131 + /*
  132 + * Tell the time framework to switch
  133 + * to a broadcast timer because our
  134 + * local timer will be shutdown. If a
  135 + * local timer is used from another
  136 + * cpu as a broadcast timer, this call
  137 + * may fail if it is not available
  138 + */
  139 + ret = clockevents_notify(
  140 + CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
  141 + &dev->cpu);
  142 +
  143 + if (!ret) {
  144 + trace_cpu_idle_rcuidle(next_state, dev->cpu);
  145 +
  146 + /*
  147 + * Enter the idle state previously
  148 + * returned by the governor
  149 + * decision. This function will block
  150 + * until an interrupt occurs and will
  151 + * take care of re-enabling the local
  152 + * interrupts
  153 + */
  154 + entered_state = cpuidle_enter(drv, dev,
  155 + next_state);
  156 +
  157 + trace_cpu_idle_rcuidle(PWR_EVENT_EXIT,
  158 + dev->cpu);
  159 +
  160 + if (broadcast)
  161 + clockevents_notify(
  162 + CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
  163 + &dev->cpu);
  164 +
  165 + /*
  166 + * Give the governor an opportunity to reflect on the
  167 + * outcome
  168 + */
  169 + cpuidle_reflect(dev, entered_state);
  170 + }
  171 + }
  172 + }
  173 +
  174 + /*
  175 + * We can't use the cpuidle framework, let's use the default
  176 + * idle routine
  177 + */
  178 + if (ret)
  179 + arch_cpu_idle();
  180 +
  181 + __current_set_polling();
  182 +
  183 + /*
  184 + * It is up to the idle functions to enable back the local
  185 + * interrupt
  186 + */
  187 + if (WARN_ON_ONCE(irqs_disabled()))
  188 + local_irq_enable();
  189 +
  190 + rcu_idle_exit();
  191 + start_critical_timings();
  192 +
  193 + return 0;
  194 +}
  195 +
66 196 /*
67 197 * Generic idle loop implementation
68 198 */
69 199  
... ... @@ -90,23 +220,11 @@
90 220 * know that the IPI is going to arrive right
91 221 * away
92 222 */
93   - if (cpu_idle_force_poll || tick_check_broadcast_expired()) {
  223 + if (cpu_idle_force_poll || tick_check_broadcast_expired())
94 224 cpu_idle_poll();
95   - } else {
96   - if (!current_clr_polling_and_test()) {
97   - stop_critical_timings();
98   - rcu_idle_enter();
99   - if (cpuidle_idle_call())
100   - arch_cpu_idle();
101   - if (WARN_ON_ONCE(irqs_disabled()))
102   - local_irq_enable();
103   - rcu_idle_exit();
104   - start_critical_timings();
105   - } else {
106   - local_irq_enable();
107   - }
108   - __current_set_polling();
109   - }
  225 + else
  226 + cpuidle_idle_call();
  227 +
110 228 arch_cpu_idle_exit();
111 229 }
112 230