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

Merge branch 'pm-cpuidle' into pm-sleep

+62 -39
+42 -13
drivers/cpuidle/cpuidle.c
··· 32 32 static int enabled_devices; 33 33 static int off __read_mostly; 34 34 static int initialized __read_mostly; 35 + static bool use_deepest_state __read_mostly; 35 36 36 37 int cpuidle_disabled(void) 37 38 { ··· 66 65 } 67 66 68 67 /** 69 - * cpuidle_enabled - check if the cpuidle framework is ready 70 - * @dev: cpuidle device for this cpu 71 - * @drv: cpuidle driver for this cpu 68 + * cpuidle_use_deepest_state - Enable/disable the "deepest idle" mode. 69 + * @enable: Whether enable or disable the feature. 72 70 * 73 - * Return 0 on success, otherwise: 74 - * -NODEV : the cpuidle framework is not available 75 - * -EBUSY : the cpuidle framework is not initialized 71 + * If the "deepest idle" mode is enabled, cpuidle will ignore the governor and 72 + * always use the state with the greatest exit latency (out of the states that 73 + * are not disabled). 74 + * 75 + * This function can only be called after cpuidle_pause() to avoid races. 76 76 */ 77 - int cpuidle_enabled(struct cpuidle_driver *drv, struct cpuidle_device *dev) 77 + void cpuidle_use_deepest_state(bool enable) 78 78 { 79 - if (off || !initialized) 80 - return -ENODEV; 79 + use_deepest_state = enable; 80 + } 81 81 82 - if (!drv || !dev || !dev->enabled) 83 - return -EBUSY; 82 + /** 83 + * cpuidle_find_deepest_state - Find the state of the greatest exit latency. 84 + * @drv: cpuidle driver for a given CPU. 85 + * @dev: cpuidle device for a given CPU. 86 + */ 87 + static int cpuidle_find_deepest_state(struct cpuidle_driver *drv, 88 + struct cpuidle_device *dev) 89 + { 90 + unsigned int latency_req = 0; 91 + int i, ret = CPUIDLE_DRIVER_STATE_START - 1; 84 92 85 - return 0; 93 + for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { 94 + struct cpuidle_state *s = &drv->states[i]; 95 + struct cpuidle_state_usage *su = &dev->states_usage[i]; 96 + 97 + if (s->disabled || su->disable || s->exit_latency <= latency_req) 98 + continue; 99 + 100 + latency_req = s->exit_latency; 101 + ret = i; 102 + } 103 + return ret; 86 104 } 87 105 88 106 /** ··· 158 138 */ 159 139 int cpuidle_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) 160 140 { 141 + if (off || !initialized) 142 + return -ENODEV; 143 + 144 + if (!drv || !dev || !dev->enabled) 145 + return -EBUSY; 146 + 147 + if (unlikely(use_deepest_state)) 148 + return cpuidle_find_deepest_state(drv, dev); 149 + 161 150 return cpuidle_curr_governor->select(drv, dev); 162 151 } 163 152 ··· 198 169 */ 199 170 void cpuidle_reflect(struct cpuidle_device *dev, int index) 200 171 { 201 - if (cpuidle_curr_governor->reflect) 172 + if (cpuidle_curr_governor->reflect && !unlikely(use_deepest_state)) 202 173 cpuidle_curr_governor->reflect(dev, index); 203 174 } 204 175
+9 -8
drivers/cpuidle/governors/menu.c
··· 296 296 data->needs_update = 0; 297 297 } 298 298 299 - data->last_state_idx = 0; 299 + data->last_state_idx = CPUIDLE_DRIVER_STATE_START - 1; 300 300 301 301 /* Special case when user has set very strict latency requirement */ 302 302 if (unlikely(latency_req == 0)) ··· 309 309 310 310 311 311 data->bucket = which_bucket(data->next_timer_us); 312 - 313 - /* 314 - * if the correction factor is 0 (eg first time init or cpu hotplug 315 - * etc), we actually want to start out with a unity factor. 316 - */ 317 - if (data->correction_factor[data->bucket] == 0) 318 - data->correction_factor[data->bucket] = RESOLUTION * DECAY; 319 312 320 313 /* 321 314 * Force the result of multiplication to be 64 bits even if both ··· 459 466 struct cpuidle_device *dev) 460 467 { 461 468 struct menu_device *data = &per_cpu(menu_devices, dev->cpu); 469 + int i; 462 470 463 471 memset(data, 0, sizeof(struct menu_device)); 472 + 473 + /* 474 + * if the correction factor is 0 (eg first time init or cpu hotplug 475 + * etc), we actually want to start out with a unity factor. 476 + */ 477 + for(i = 0; i < BUCKETS; i++) 478 + data->correction_factor[i] = RESOLUTION * DECAY; 464 479 465 480 return 0; 466 481 }
+2 -5
include/linux/cpuidle.h
··· 120 120 #ifdef CONFIG_CPU_IDLE 121 121 extern void disable_cpuidle(void); 122 122 123 - extern int cpuidle_enabled(struct cpuidle_driver *drv, 124 - struct cpuidle_device *dev); 125 123 extern int cpuidle_select(struct cpuidle_driver *drv, 126 124 struct cpuidle_device *dev); 127 125 extern int cpuidle_enter(struct cpuidle_driver *drv, ··· 143 145 extern int cpuidle_enable_device(struct cpuidle_device *dev); 144 146 extern void cpuidle_disable_device(struct cpuidle_device *dev); 145 147 extern int cpuidle_play_dead(void); 148 + extern void cpuidle_use_deepest_state(bool enable); 146 149 147 150 extern struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev); 148 151 #else 149 152 static inline void disable_cpuidle(void) { } 150 - static inline int cpuidle_enabled(struct cpuidle_driver *drv, 151 - struct cpuidle_device *dev) 152 - {return -ENODEV; } 153 153 static inline int cpuidle_select(struct cpuidle_driver *drv, 154 154 struct cpuidle_device *dev) 155 155 {return -ENODEV; } ··· 176 180 {return -ENODEV; } 177 181 static inline void cpuidle_disable_device(struct cpuidle_device *dev) { } 178 182 static inline int cpuidle_play_dead(void) {return -ENODEV; } 183 + static inline void cpuidle_use_deepest_state(bool enable) {} 179 184 static inline struct cpuidle_driver *cpuidle_get_cpu_driver( 180 185 struct cpuidle_device *dev) {return NULL; } 181 186 #endif
+2
kernel/power/suspend.c
··· 54 54 55 55 static void freeze_enter(void) 56 56 { 57 + cpuidle_use_deepest_state(true); 57 58 cpuidle_resume(); 58 59 wait_event(suspend_freeze_wait_head, suspend_freeze_wake); 59 60 cpuidle_pause(); 61 + cpuidle_use_deepest_state(false); 60 62 } 61 63 62 64 void freeze_wake(void)
+7 -13
kernel/sched/idle.c
··· 101 101 rcu_idle_enter(); 102 102 103 103 /* 104 - * Check if the cpuidle framework is ready, otherwise fallback 105 - * to the default arch specific idle method 104 + * Ask the cpuidle framework to choose a convenient idle state. 105 + * Fall back to the default arch specific idle method on errors. 106 106 */ 107 - ret = cpuidle_enabled(drv, dev); 107 + next_state = cpuidle_select(drv, dev); 108 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 - 109 + ret = next_state; 110 + if (ret >= 0) { 117 111 /* 118 112 * The idle task must be scheduled, it is pointless to 119 113 * go to idle, just update no idle residency and get ··· 134 140 CLOCK_EVT_NOTIFY_BROADCAST_ENTER, 135 141 &dev->cpu); 136 142 137 - if (!ret) { 143 + if (ret >= 0) { 138 144 trace_cpu_idle_rcuidle(next_state, dev->cpu); 139 145 140 146 /* ··· 169 175 * We can't use the cpuidle framework, let's use the default 170 176 * idle routine 171 177 */ 172 - if (ret) 178 + if (ret < 0) 173 179 arch_cpu_idle(); 174 180 175 181 __current_set_polling();