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

cpuidle:powernv: Add helper function to populate powernv idle states.

In the current code for powernv_add_idle_states, there is a lot of code
duplication while initializing an idle state in powernv_states table.

Add an inline helper function to populate the powernv_states[] table
for a given idle state. Invoke this for populating the "Nap",
"Fastsleep" and the stop states in powernv_add_idle_states.

Signed-off-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
Acked-by: Balbir Singh <bsingharora@gmail.com>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

authored by

Gautham R. Shenoy and committed by
Michael Ellerman
9e9fc6f0 dd34c74c

+54 -36
+53 -36
drivers/cpuidle/cpuidle-powernv.c
··· 20 20 #include <asm/opal.h> 21 21 #include <asm/runlatch.h> 22 22 23 + /* 24 + * Expose only those Hardware idle states via the cpuidle framework 25 + * that have latency value below POWERNV_THRESHOLD_LATENCY_NS. 26 + */ 23 27 #define POWERNV_THRESHOLD_LATENCY_NS 200000 24 28 25 29 static struct cpuidle_driver powernv_idle_driver = { ··· 171 167 return 0; 172 168 } 173 169 170 + static inline void add_powernv_state(int index, const char *name, 171 + unsigned int flags, 172 + int (*idle_fn)(struct cpuidle_device *, 173 + struct cpuidle_driver *, 174 + int), 175 + unsigned int target_residency, 176 + unsigned int exit_latency, 177 + u64 psscr_val) 178 + { 179 + strlcpy(powernv_states[index].name, name, CPUIDLE_NAME_LEN); 180 + strlcpy(powernv_states[index].desc, name, CPUIDLE_NAME_LEN); 181 + powernv_states[index].flags = flags; 182 + powernv_states[index].target_residency = target_residency; 183 + powernv_states[index].exit_latency = exit_latency; 184 + powernv_states[index].enter = idle_fn; 185 + stop_psscr_table[index] = psscr_val; 186 + } 187 + 174 188 static int powernv_add_idle_states(void) 175 189 { 176 190 struct device_node *power_mgt; ··· 258 236 "ibm,cpu-idle-state-residency-ns", residency_ns, dt_idle_states); 259 237 260 238 for (i = 0; i < dt_idle_states; i++) { 239 + unsigned int exit_latency, target_residency; 261 240 /* 262 241 * If an idle state has exit latency beyond 263 242 * POWERNV_THRESHOLD_LATENCY_NS then don't use it ··· 266 243 */ 267 244 if (latency_ns[i] > POWERNV_THRESHOLD_LATENCY_NS) 268 245 continue; 246 + /* 247 + * Firmware passes residency and latency values in ns. 248 + * cpuidle expects it in us. 249 + */ 250 + exit_latency = latency_ns[i] / 1000; 251 + if (!rc) 252 + target_residency = residency_ns[i] / 1000; 253 + else 254 + target_residency = 0; 269 255 270 256 /* 271 - * Cpuidle accepts exit_latency and target_residency in us. 272 - * Use default target_residency values if f/w does not expose it. 257 + * For nap and fastsleep, use default target_residency 258 + * values if f/w does not expose it. 273 259 */ 274 260 if (flags[i] & OPAL_PM_NAP_ENABLED) { 261 + if (!rc) 262 + target_residency = 100; 275 263 /* Add NAP state */ 276 - strcpy(powernv_states[nr_idle_states].name, "Nap"); 277 - strcpy(powernv_states[nr_idle_states].desc, "Nap"); 278 - powernv_states[nr_idle_states].flags = 0; 279 - powernv_states[nr_idle_states].target_residency = 100; 280 - powernv_states[nr_idle_states].enter = nap_loop; 264 + add_powernv_state(nr_idle_states, "Nap", 265 + CPUIDLE_FLAG_NONE, nap_loop, 266 + target_residency, exit_latency, 0); 281 267 } else if ((flags[i] & OPAL_PM_STOP_INST_FAST) && 282 268 !(flags[i] & OPAL_PM_TIMEBASE_STOP)) { 283 - strncpy(powernv_states[nr_idle_states].name, 284 - names[i], CPUIDLE_NAME_LEN); 285 - strncpy(powernv_states[nr_idle_states].desc, 286 - names[i], CPUIDLE_NAME_LEN); 287 - powernv_states[nr_idle_states].flags = 0; 288 - 289 - powernv_states[nr_idle_states].enter = stop_loop; 290 - stop_psscr_table[nr_idle_states] = psscr_val[i]; 269 + add_powernv_state(nr_idle_states, names[i], 270 + CPUIDLE_FLAG_NONE, stop_loop, 271 + target_residency, exit_latency, 272 + psscr_val[i]); 291 273 } 292 274 293 275 /* ··· 302 274 #ifdef CONFIG_TICK_ONESHOT 303 275 if (flags[i] & OPAL_PM_SLEEP_ENABLED || 304 276 flags[i] & OPAL_PM_SLEEP_ENABLED_ER1) { 277 + if (!rc) 278 + target_residency = 300000; 305 279 /* Add FASTSLEEP state */ 306 - strcpy(powernv_states[nr_idle_states].name, "FastSleep"); 307 - strcpy(powernv_states[nr_idle_states].desc, "FastSleep"); 308 - powernv_states[nr_idle_states].flags = CPUIDLE_FLAG_TIMER_STOP; 309 - powernv_states[nr_idle_states].target_residency = 300000; 310 - powernv_states[nr_idle_states].enter = fastsleep_loop; 280 + add_powernv_state(nr_idle_states, "FastSleep", 281 + CPUIDLE_FLAG_TIMER_STOP, 282 + fastsleep_loop, 283 + target_residency, exit_latency, 0); 311 284 } else if ((flags[i] & OPAL_PM_STOP_INST_DEEP) && 312 285 (flags[i] & OPAL_PM_TIMEBASE_STOP)) { 313 - strncpy(powernv_states[nr_idle_states].name, 314 - names[i], CPUIDLE_NAME_LEN); 315 - strncpy(powernv_states[nr_idle_states].desc, 316 - names[i], CPUIDLE_NAME_LEN); 317 - 318 - powernv_states[nr_idle_states].flags = CPUIDLE_FLAG_TIMER_STOP; 319 - powernv_states[nr_idle_states].enter = stop_loop; 320 - stop_psscr_table[nr_idle_states] = psscr_val[i]; 286 + add_powernv_state(nr_idle_states, names[i], 287 + CPUIDLE_FLAG_TIMER_STOP, stop_loop, 288 + target_residency, exit_latency, 289 + psscr_val[i]); 321 290 } 322 291 #endif 323 - powernv_states[nr_idle_states].exit_latency = 324 - ((unsigned int)latency_ns[i]) / 1000; 325 - 326 - if (!rc) { 327 - powernv_states[nr_idle_states].target_residency = 328 - ((unsigned int)residency_ns[i]) / 1000; 329 - } 330 - 331 292 nr_idle_states++; 332 293 } 333 294 out:
+1
include/linux/cpuidle.h
··· 62 62 }; 63 63 64 64 /* Idle State Flags */ 65 + #define CPUIDLE_FLAG_NONE (0x00) 65 66 #define CPUIDLE_FLAG_COUPLED (0x02) /* state applies to multiple cpus */ 66 67 #define CPUIDLE_FLAG_TIMER_STOP (0x04) /* timer is stopped on this state */ 67 68