Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'pm-7.0-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull power management fixes from Rafael Wysocki:
"These fix an idle loop issue exposed by recent changes and a race
condition related to device removal in the runtime PM core code:

- Consolidate the handling of two special cases in the idle loop that
occur when only one CPU idle state is present (Rafael Wysocki)

- Fix a race condition related to device removal in the runtime PM
core code that may cause a stale device object pointer to be
dereferenced (Bart Van Assche)"

* tag 'pm-7.0-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
PM: runtime: Fix a race condition related to device removal
sched: idle: Consolidate the handling of two special cases

+22 -9
+1
drivers/base/power/runtime.c
··· 1895 1895 void pm_runtime_remove(struct device *dev) 1896 1896 { 1897 1897 __pm_runtime_disable(dev, false); 1898 + flush_work(&dev->power.work); 1898 1899 pm_runtime_reinit(dev); 1899 1900 } 1900 1901
+21 -9
kernel/sched/idle.c
··· 161 161 return cpuidle_enter(drv, dev, next_state); 162 162 } 163 163 164 + static void idle_call_stop_or_retain_tick(bool stop_tick) 165 + { 166 + if (stop_tick || tick_nohz_tick_stopped()) 167 + tick_nohz_idle_stop_tick(); 168 + else 169 + tick_nohz_idle_retain_tick(); 170 + } 171 + 164 172 /** 165 173 * cpuidle_idle_call - the main idle function 166 174 * ··· 178 170 * set, and it returns with polling set. If it ever stops polling, it 179 171 * must clear the polling bit. 180 172 */ 181 - static void cpuidle_idle_call(void) 173 + static void cpuidle_idle_call(bool stop_tick) 182 174 { 183 175 struct cpuidle_device *dev = cpuidle_get_device(); 184 176 struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); ··· 194 186 } 195 187 196 188 if (cpuidle_not_available(drv, dev)) { 197 - tick_nohz_idle_stop_tick(); 189 + idle_call_stop_or_retain_tick(stop_tick); 198 190 199 191 default_idle_call(); 200 192 goto exit_idle; ··· 230 222 next_state = cpuidle_find_deepest_state(drv, dev, max_latency_ns); 231 223 call_cpuidle(drv, dev, next_state); 232 224 } else if (drv->state_count > 1) { 233 - bool stop_tick = true; 225 + /* 226 + * stop_tick is expected to be true by default by cpuidle 227 + * governors, which allows them to select idle states with 228 + * target residency above the tick period length. 229 + */ 230 + stop_tick = true; 234 231 235 232 /* 236 233 * Ask the cpuidle framework to choose a convenient idle state. 237 234 */ 238 235 next_state = cpuidle_select(drv, dev, &stop_tick); 239 236 240 - if (stop_tick || tick_nohz_tick_stopped()) 241 - tick_nohz_idle_stop_tick(); 242 - else 243 - tick_nohz_idle_retain_tick(); 237 + idle_call_stop_or_retain_tick(stop_tick); 244 238 245 239 entered_state = call_cpuidle(drv, dev, next_state); 246 240 /* ··· 250 240 */ 251 241 cpuidle_reflect(dev, entered_state); 252 242 } else { 253 - tick_nohz_idle_retain_tick(); 243 + idle_call_stop_or_retain_tick(stop_tick); 254 244 255 245 /* 256 246 * If there is only a single idle state (or none), there is ··· 278 268 static void do_idle(void) 279 269 { 280 270 int cpu = smp_processor_id(); 271 + bool got_tick = false; 281 272 282 273 /* 283 274 * Check if we need to update blocked load ··· 349 338 tick_nohz_idle_restart_tick(); 350 339 cpu_idle_poll(); 351 340 } else { 352 - cpuidle_idle_call(); 341 + cpuidle_idle_call(got_tick); 353 342 } 343 + got_tick = tick_nohz_idle_got_tick(); 354 344 arch_cpu_idle_exit(); 355 345 } 356 346