Message ID | 1527735200-24653-1-git-send-email-akshay.adiga@linux.vnet.ibm.com (mailing list archive) |
---|---|
State | RFC |
Headers | show |
Series | [SCHEME,2] powernv/cpuidle: Add support for new idle state device-tree format | expand |
On Thu, May 31, 2018 at 08:23:20AM +0530, Akshay Adiga wrote: > This patch adds support for new device-tree format for idle state > description. > > Previously if a older kernel runs on a newer firmware, it may enable > all available states irrespective of its capability of handling it. > New device tree format adds a compatible flag, so that only kernel > which has the capability to handle the version of stop state will enable > it. > > Older kernel will still see stop0 and stop0_lite in older format and we > will depricate it after some time. > > Idea is to bump up the version in firmware if we find a bug or > regression in stop states. A fix will be provided in linux which would > now know about the bumped up version of stop states, where as kernel > without fixes would ignore the states. > > New idle state device tree format : > > power-mgt { > ibm,cpu-idle-state-names = "stop0_lite", "stop0"; > ibm,cpu-idle-state-residency-ns = <0x2710 0x4e20>; > ibm,cpu-idle-state-latencies-ns = <0x3e8 0x7d0>; > ibm,cpu-idle-state-psscr-mask = <0x0 0x3003ff 0x0 0x3003ff>; > ibm,cpu-idle-state-psscr = <0x0 0x330 0x0 0x300330>; > ibm,cpu-idle-state-flags = <0x100000 0x101000>; > ibm,enabled-stop-levels = <0xec000000>; > ibm,idle-states { > ibm,cpu-idle-state-names = "stop1", "stop2", "stop4", "stop5"; > ibm,cpu-idle-state-residency-ns = <0xc350 0x186a0 0x989680 > 0x1312d00>; > ibm,cpu-idle-state-latencies-ns = <0x1388 0x2710 0x186a0 > 0x30d40>; > ibm,cpu-idle-state-psscr-mask = <0x0 0x3003ff 0x0 0x3003ff 0x0 > 0x3003ff 0x0 0x3003ff>; > ibm,cpu-idle-state-psscr = <0x0 0x300331 0x0 0x300332 0x0 > 0x300374 0x0 0x300375>; > ibm,cpu-idle-state-versions = "ibm,idle-state-v1 > ", "ibm,idle-state-v1", "ibm,idle-state-v1", "ibm,idle-state-v1"; > ibm,cpu-idle-state-flags = <0x101000 0x101000 0x207000 > 0x207000>; > } > } > > Signed-off-by: Akshay Adiga <akshay.adiga@linux.vnet.ibm.com> > --- This patch is intended to be a RFC. The skiboot patch has been posted here : https://patchwork.ozlabs.org/patch/923121/
Hi Akshay, Thank you for the patch! Yet something to improve: [auto build test ERROR on powerpc/next] [also build test ERROR on v4.17-rc7 next-20180531] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Akshay-Adiga/powernv-cpuidle-Add-support-for-new-idle-state-device-tree-format/20180601-202708 base: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next config: powerpc-allmodconfig (attached as .config) compiler: powerpc64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree make.cross ARCH=powerpc All errors (new ones prefixed by >>): drivers//cpuidle/cpuidle-powernv.c: In function 'powernv_add_idle_states': >> drivers//cpuidle/cpuidle-powernv.c:403:36: error: 'versions' undeclared (first use in this function) "ibm,cpu-idle-state-versions", versions, additional_states) < 0) { ^~~~~~~~ drivers//cpuidle/cpuidle-powernv.c:403:36: note: each undeclared identifier is reported only once for each function it appears in >> drivers//cpuidle/cpuidle-powernv.c:436:17: error: 'version' undeclared (first use in this function); did you mean 'versions'? if (!( strcmp(version[i] , "ibm,idle-state-v1")) ^~~~~~~ versions >> drivers//cpuidle/cpuidle-powernv.c:437:5: error: expected ')' before 'continue' continue; ^~~~~~~~ >> drivers//cpuidle/cpuidle-powernv.c:511:2: error: expected expression before '}' token } ^ drivers//cpuidle/cpuidle-powernv.c:426:8: warning: unused variable 'stops_timebase' [-Wunused-variable] bool stops_timebase = false; ^~~~~~~~~~~~~~ drivers//cpuidle/cpuidle-powernv.c:425:30: warning: unused variable 'target_residency' [-Wunused-variable] unsigned int exit_latency, target_residency; ^~~~~~~~~~~~~~~~ drivers//cpuidle/cpuidle-powernv.c:425:16: warning: unused variable 'exit_latency' [-Wunused-variable] unsigned int exit_latency, target_residency; ^~~~~~~~~~~~ At top level: drivers//cpuidle/cpuidle-powernv.c:121:12: warning: 'stop_loop' defined but not used [-Wunused-function] static int stop_loop(struct cpuidle_device *dev, ^~~~~~~~~ drivers//cpuidle/cpuidle-powernv.c:95:12: warning: 'fastsleep_loop' defined but not used [-Wunused-function] static int fastsleep_loop(struct cpuidle_device *dev, ^~~~~~~~~~~~~~ drivers//cpuidle/cpuidle-powernv.c:84:12: warning: 'nap_loop' defined but not used [-Wunused-function] static int nap_loop(struct cpuidle_device *dev, ^~~~~~~~ vim +/versions +403 drivers//cpuidle/cpuidle-powernv.c 240 241 extern u32 pnv_get_supported_cpuidle_states(void); 242 static int powernv_add_idle_states(void) 243 { 244 struct device_node *power_mgt,*np_new; 245 int nr_idle_states = 1; /* Snooze */ 246 int dt_idle_states, count, additional_states; 247 u32 latency_ns[CPUIDLE_STATE_MAX]; 248 u32 residency_ns[CPUIDLE_STATE_MAX]; 249 u32 flags[CPUIDLE_STATE_MAX]; 250 u64 psscr_val[CPUIDLE_STATE_MAX]; 251 u64 psscr_mask[CPUIDLE_STATE_MAX]; 252 const char *names[CPUIDLE_STATE_MAX]; 253 u32 has_stop_states = 0; 254 int i, rc; 255 u32 supported_flags = pnv_get_supported_cpuidle_states(); 256 257 258 /* Currently we have snooze statically defined */ 259 260 power_mgt = of_find_node_by_path("/ibm,opal/power-mgt"); 261 if (!power_mgt) { 262 pr_warn("opal: PowerMgmt Node not found\n"); 263 goto out; 264 } 265 266 /* Read values of any property to determine the num of idle states */ 267 dt_idle_states = of_property_count_u32_elems(power_mgt, "ibm,cpu-idle-state-flags"); 268 if (dt_idle_states < 0) { 269 pr_warn("cpuidle-powernv: no idle states found in the DT\n"); 270 goto out; 271 } 272 273 count = of_property_count_u32_elems(power_mgt, 274 "ibm,cpu-idle-state-latencies-ns"); 275 276 if (validate_dt_prop_sizes("ibm,cpu-idle-state-flags", dt_idle_states, 277 "ibm,cpu-idle-state-latencies-ns", 278 count) != 0) 279 goto out; 280 281 count = of_property_count_strings(power_mgt, 282 "ibm,cpu-idle-state-names"); 283 if (validate_dt_prop_sizes("ibm,cpu-idle-state-flags", dt_idle_states, 284 "ibm,cpu-idle-state-names", 285 count) != 0) 286 goto out; 287 288 /* 289 * Since snooze is used as first idle state, max idle states allowed is 290 * CPUIDLE_STATE_MAX -1 291 */ 292 if (dt_idle_states > CPUIDLE_STATE_MAX - 1) { 293 pr_warn("cpuidle-powernv: discovered idle states more than allowed"); 294 dt_idle_states = CPUIDLE_STATE_MAX - 1; 295 } 296 297 if (of_property_read_u32_array(power_mgt, 298 "ibm,cpu-idle-state-flags", flags, dt_idle_states)) { 299 pr_warn("cpuidle-powernv : missing ibm,cpu-idle-state-flags in DT\n"); 300 goto out; 301 } 302 303 if (of_property_read_u32_array(power_mgt, 304 "ibm,cpu-idle-state-latencies-ns", latency_ns, 305 dt_idle_states)) { 306 pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-latencies-ns in DT\n"); 307 goto out; 308 } 309 if (of_property_read_string_array(power_mgt, 310 "ibm,cpu-idle-state-names", names, dt_idle_states) < 0) { 311 pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-names in DT\n"); 312 goto out; 313 } 314 315 /* 316 * If the idle states use stop instruction, probe for psscr values 317 * and psscr mask which are necessary to specify required stop level. 318 */ 319 has_stop_states = (flags[0] & 320 (OPAL_PM_STOP_INST_FAST | OPAL_PM_STOP_INST_DEEP)); 321 if (has_stop_states) { 322 count = of_property_count_u64_elems(power_mgt, 323 "ibm,cpu-idle-state-psscr"); 324 if (validate_dt_prop_sizes("ibm,cpu-idle-state-flags", 325 dt_idle_states, 326 "ibm,cpu-idle-state-psscr", 327 count) != 0) 328 goto out; 329 330 count = of_property_count_u64_elems(power_mgt, 331 "ibm,cpu-idle-state-psscr-mask"); 332 if (validate_dt_prop_sizes("ibm,cpu-idle-state-flags", 333 dt_idle_states, 334 "ibm,cpu-idle-state-psscr-mask", 335 count) != 0) 336 goto out; 337 338 if (of_property_read_u64_array(power_mgt, 339 "ibm,cpu-idle-state-psscr", psscr_val, dt_idle_states)) { 340 pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-psscr in DT\n"); 341 goto out; 342 } 343 344 if (of_property_read_u64_array(power_mgt, 345 "ibm,cpu-idle-state-psscr-mask", 346 psscr_mask, dt_idle_states)) { 347 pr_warn("cpuidle-powernv:Missing ibm,cpu-idle-state-psscr-mask in DT\n"); 348 goto out; 349 } 350 } 351 352 count = of_property_count_u32_elems(power_mgt, 353 "ibm,cpu-idle-state-residency-ns"); 354 355 if (count < 0) { 356 rc = count; 357 } else if (validate_dt_prop_sizes("ibm,cpu-idle-state-flags", 358 dt_idle_states, 359 "ibm,cpu-idle-state-residency-ns", 360 count) != 0) { 361 goto out; 362 } else { 363 rc = of_property_read_u32_array(power_mgt, 364 "ibm,cpu-idle-state-residency-ns", 365 residency_ns, dt_idle_states); 366 } 367 368 /* Support new dt format for idle states */ 369 370 np_new = of_find_node_by_path("/ibm,opal/power-mgt/ibm,idle-states"); 371 if (!np_new) { 372 pr_info("opal: PowerMgmt/ibm,idle-states Node not found\n"); 373 } else { 374 additional_states = of_property_count_u32_elems(np_new, 375 "ibm,cpu-idle-state-flags"); 376 if (additional_states < 0) 377 pr_info("cpuidle-powernv: no idle states found in the DT\n"); 378 else { 379 if (of_property_read_u32_array(np_new, 380 "ibm,cpu-idle-state-flags", flags+dt_idle_states, additional_states)) { 381 pr_warn("cpuidle-powernv : missing ibm,cpu-idle-state-flags in DT\n"); 382 goto out; 383 } 384 385 if (of_property_read_u32_array(np_new, 386 "ibm,cpu-idle-state-latencies-ns", latency_ns+dt_idle_states, 387 additional_states)) { 388 pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-latencies-ns in DT\n"); 389 goto out; 390 } 391 if (of_property_read_u32_array(np_new, 392 "ibm,cpu-idle-state-residencies-ns", residency_ns+dt_idle_states, 393 additional_states)) { 394 pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-residencies-ns in DT\n"); 395 goto out; 396 } 397 if (of_property_read_string_array(np_new, 398 "ibm,cpu-idle-state-names", names+dt_idle_states, additional_states) < 0) { 399 pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-names in DT\n"); 400 goto out; 401 } 402 if (of_property_read_string_array(np_new, > 403 "ibm,cpu-idle-state-versions", versions, additional_states) < 0) { 404 pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-names in DT\n"); 405 goto out; 406 } 407 if (of_property_read_u64_array(np_new, 408 "ibm,cpu-idle-state-psscr", psscr_val+ dt_idle_states, additional_states)) { 409 pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-psscr in DT\n"); 410 goto out; 411 } 412 413 if (of_property_read_u64_array(power_mgt, 414 "ibm,cpu-idle-state-psscr-mask", 415 psscr_mask + dt_idle_states,additional_states)) { 416 pr_warn("cpuidle-powernv:Missing ibm,cpu-idle-state-psscr-mask in DT\n"); 417 goto out; 418 } 419 420 421 dt_idle_states += additional_states; 422 } 423 } 424 for (i = 0; i < dt_idle_states; i++) { 425 unsigned int exit_latency, target_residency; 426 bool stops_timebase = false; 427 428 /* 429 * Skip the platform idle state whose flag isn't in 430 * the supported_cpuidle_states flag mask. 431 */ 432 if ((flags[i] & supported_flags) != flags[i]) 433 continue; 434 435 /* Supported version */ > 436 if (!( strcmp(version[i] , "ibm,idle-state-v1")) > 437 continue; 438 439 /* 440 * If an idle state has exit latency beyond 441 * POWERNV_THRESHOLD_LATENCY_NS then don't use it 442 * in cpu-idle. 443 */ 444 if (latency_ns[i] > POWERNV_THRESHOLD_LATENCY_NS) 445 continue; 446 /* 447 * Firmware passes residency and latency values in ns. 448 * cpuidle expects it in us. 449 */ 450 exit_latency = DIV_ROUND_UP(latency_ns[i], 1000); 451 if (!rc) 452 target_residency = DIV_ROUND_UP(residency_ns[i], 1000); 453 else 454 target_residency = 0; 455 456 if (has_stop_states) { 457 int err = validate_psscr_val_mask(&psscr_val[i], 458 &psscr_mask[i], 459 flags[i]); 460 if (err) { 461 report_invalid_psscr_val(psscr_val[i], err); 462 continue; 463 } 464 } 465 466 if (flags[i] & OPAL_PM_TIMEBASE_STOP) 467 stops_timebase = true; 468 469 /* 470 * For nap and fastsleep, use default target_residency 471 * values if f/w does not expose it. 472 */ 473 if (flags[i] & OPAL_PM_NAP_ENABLED) { 474 if (!rc) 475 target_residency = 100; 476 /* Add NAP state */ 477 add_powernv_state(nr_idle_states, "Nap", 478 CPUIDLE_FLAG_NONE, nap_loop, 479 target_residency, exit_latency, 0, 0); 480 } else if (has_stop_states && !stops_timebase) { 481 add_powernv_state(nr_idle_states, names[i], 482 CPUIDLE_FLAG_NONE, stop_loop, 483 target_residency, exit_latency, 484 psscr_val[i], psscr_mask[i]); 485 } 486 487 /* 488 * All cpuidle states with CPUIDLE_FLAG_TIMER_STOP set must come 489 * within this config dependency check. 490 */ 491 #ifdef CONFIG_TICK_ONESHOT 492 else if (flags[i] & OPAL_PM_SLEEP_ENABLED || 493 flags[i] & OPAL_PM_SLEEP_ENABLED_ER1) { 494 if (!rc) 495 target_residency = 300000; 496 /* Add FASTSLEEP state */ 497 add_powernv_state(nr_idle_states, "FastSleep", 498 CPUIDLE_FLAG_TIMER_STOP, 499 fastsleep_loop, 500 target_residency, exit_latency, 0, 0); 501 } else if (has_stop_states && stops_timebase) { 502 add_powernv_state(nr_idle_states, names[i], 503 CPUIDLE_FLAG_TIMER_STOP, stop_loop, 504 target_residency, exit_latency, 505 psscr_val[i], psscr_mask[i]); 506 } 507 #endif 508 else 509 continue; 510 nr_idle_states++; > 511 } 512 out: 513 return nr_idle_states; 514 } 515 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c index 1f12ab1..ab52665 100644 --- a/arch/powerpc/platforms/powernv/idle.c +++ b/arch/powerpc/platforms/powernv/idle.c @@ -622,8 +622,8 @@ int validate_psscr_val_mask(u64 *psscr_val, u64 *psscr_mask, u32 flags) * @dt_idle_states: Number of idle state entries * Returns 0 on success */ -static int __init pnv_power9_idle_init(struct device_node *np, u32 *flags, - int dt_idle_states) +static int __init pnv_power9_idle_init(struct device_node *np, struct device_node *np_new,u32 *flags, + int dt_idle_states, int additional_states) { u64 *psscr_val = NULL; u64 *psscr_mask = NULL; @@ -631,9 +631,10 @@ static int __init pnv_power9_idle_init(struct device_node *np, u32 *flags, u64 max_residency_ns = 0; int rc = 0, i; - psscr_val = kcalloc(dt_idle_states, sizeof(*psscr_val), GFP_KERNEL); - psscr_mask = kcalloc(dt_idle_states, sizeof(*psscr_mask), GFP_KERNEL); - residency_ns = kcalloc(dt_idle_states, sizeof(*residency_ns), + /* TODO: remove ugliness of using additional_states count*/ + psscr_val = kcalloc(dt_idle_states+additional_states, sizeof(*psscr_val), GFP_KERNEL); + psscr_mask = kcalloc(dt_idle_states+additional_states, sizeof(*psscr_mask), GFP_KERNEL); + residency_ns = kcalloc(dt_idle_states+additional_states, sizeof(*residency_ns), GFP_KERNEL); if (!psscr_val || !psscr_mask || !residency_ns) { @@ -648,6 +649,13 @@ static int __init pnv_power9_idle_init(struct device_node *np, u32 *flags, rc = -1; goto out; } + if (of_property_read_u64_array(np_new, + "ibm,cpu-idle-state-psscr", + psscr_val + dt_idle_states, additional_states)) { + pr_warn("cpuidle-powernv: missing addtional ibm,cpu-idle-state-psscr in DT\n"); + rc = -1; + goto out; + } if (of_property_read_u64_array(np, "ibm,cpu-idle-state-psscr-mask", @@ -656,6 +664,13 @@ static int __init pnv_power9_idle_init(struct device_node *np, u32 *flags, rc = -1; goto out; } + if (of_property_read_u64_array(np_new, + "ibm,cpu-idle-state-psscr-mask", + psscr_mask + dt_idle_states, additional_states)) { + pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-psscr-mask in DT\n"); + rc = -1; + goto out; + } if (of_property_read_u32_array(np, "ibm,cpu-idle-state-residency-ns", @@ -664,7 +679,13 @@ static int __init pnv_power9_idle_init(struct device_node *np, u32 *flags, rc = -1; goto out; } - + if (of_property_read_u32_array(np_new, + "ibm,cpu-idle-state-residency-ns", + residency_ns + dt_idle_states,additional_states)) { + pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-residency-ns in DT\n"); + rc = -1; + goto out; + } /* * Set pnv_first_deep_stop_state, pnv_deepest_stop_psscr_{val,mask}, * and the pnv_default_stop_{val,mask}. @@ -679,7 +700,7 @@ static int __init pnv_power9_idle_init(struct device_node *np, u32 *flags, * the shallowest (OPAL_PM_STOP_INST_FAST) loss-less stop state. */ pnv_first_deep_stop_state = MAX_STOP_STATE; - for (i = 0; i < dt_idle_states; i++) { + for (i = 0; i < dt_idle_states+additional_states; i++) { int err; u64 psscr_rl = psscr_val[i] & PSSCR_RL_MASK; @@ -740,10 +761,11 @@ static int __init pnv_power9_idle_init(struct device_node *np, u32 *flags, */ static void __init pnv_probe_idle_states(void) { - struct device_node *np; + struct device_node *np,*np_new; int dt_idle_states; u32 *flags = NULL; int i; + int additional_states=0; np = of_find_node_by_path("/ibm,opal/power-mgt"); if (!np) { @@ -756,21 +778,37 @@ static void __init pnv_probe_idle_states(void) pr_warn("cpuidle-powernv: no idle states found in the DT\n"); goto out; } + /* Support new device tree */ + np_new = of_find_node_by_path("/ibm,opal/power-mgt/ibm,idle-states"); + if (!np_new) { + pr_info("opal: PowerMgmt/ibm,idle-states Node not found\n"); + } else { + additional_states = of_property_count_u32_elems(np_new, + "ibm,cpu-idle-state-flags"); + if (additional_states < 0) + pr_info("cpuidle-powernv: no idle states found in the DT\n"); + } - flags = kcalloc(dt_idle_states, sizeof(*flags), GFP_KERNEL); + flags = kcalloc(dt_idle_states + additional_states, sizeof(*flags), GFP_KERNEL); if (of_property_read_u32_array(np, "ibm,cpu-idle-state-flags", flags, dt_idle_states)) { pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-flags in DT\n"); goto out; } + if (of_property_read_u32_array(np_new, + "ibm,cpu-idle-state-flags", flags + dt_idle_states, additional_states)) { + pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-flags in DT\n"); + goto out; + } + if (cpu_has_feature(CPU_FTR_ARCH_300)) { - if (pnv_power9_idle_init(np, flags, dt_idle_states)) + if (pnv_power9_idle_init(np, np_new, flags, dt_idle_states,additional_states)) goto out; } - for (i = 0; i < dt_idle_states; i++) + for (i = 0; i < dt_idle_states+additional_states; i++) supported_cpuidle_states |= flags[i]; out: diff --git a/drivers/cpuidle/cpuidle-powernv.c b/drivers/cpuidle/cpuidle-powernv.c index 1a8234e..8060a96 100644 --- a/drivers/cpuidle/cpuidle-powernv.c +++ b/drivers/cpuidle/cpuidle-powernv.c @@ -241,9 +241,9 @@ static inline int validate_dt_prop_sizes(const char *prop1, int prop1_len, extern u32 pnv_get_supported_cpuidle_states(void); static int powernv_add_idle_states(void) { - struct device_node *power_mgt; + struct device_node *power_mgt,*np_new; int nr_idle_states = 1; /* Snooze */ - int dt_idle_states, count; + int dt_idle_states, count, additional_states; u32 latency_ns[CPUIDLE_STATE_MAX]; u32 residency_ns[CPUIDLE_STATE_MAX]; u32 flags[CPUIDLE_STATE_MAX]; @@ -365,6 +365,62 @@ static int powernv_add_idle_states(void) residency_ns, dt_idle_states); } + /* Support new dt format for idle states */ + + np_new = of_find_node_by_path("/ibm,opal/power-mgt/ibm,idle-states"); + if (!np_new) { + pr_info("opal: PowerMgmt/ibm,idle-states Node not found\n"); + } else { + additional_states = of_property_count_u32_elems(np_new, + "ibm,cpu-idle-state-flags"); + if (additional_states < 0) + pr_info("cpuidle-powernv: no idle states found in the DT\n"); + else { + if (of_property_read_u32_array(np_new, + "ibm,cpu-idle-state-flags", flags+dt_idle_states, additional_states)) { + pr_warn("cpuidle-powernv : missing ibm,cpu-idle-state-flags in DT\n"); + goto out; + } + + if (of_property_read_u32_array(np_new, + "ibm,cpu-idle-state-latencies-ns", latency_ns+dt_idle_states, + additional_states)) { + pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-latencies-ns in DT\n"); + goto out; + } + if (of_property_read_u32_array(np_new, + "ibm,cpu-idle-state-residencies-ns", residency_ns+dt_idle_states, + additional_states)) { + pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-residencies-ns in DT\n"); + goto out; + } + if (of_property_read_string_array(np_new, + "ibm,cpu-idle-state-names", names+dt_idle_states, additional_states) < 0) { + pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-names in DT\n"); + goto out; + } + if (of_property_read_string_array(np_new, + "ibm,cpu-idle-state-versions", versions, additional_states) < 0) { + pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-names in DT\n"); + goto out; + } + if (of_property_read_u64_array(np_new, + "ibm,cpu-idle-state-psscr", psscr_val+ dt_idle_states, additional_states)) { + pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-psscr in DT\n"); + goto out; + } + + if (of_property_read_u64_array(power_mgt, + "ibm,cpu-idle-state-psscr-mask", + psscr_mask + dt_idle_states,additional_states)) { + pr_warn("cpuidle-powernv:Missing ibm,cpu-idle-state-psscr-mask in DT\n"); + goto out; + } + + + dt_idle_states += additional_states; + } + } for (i = 0; i < dt_idle_states; i++) { unsigned int exit_latency, target_residency; bool stops_timebase = false; @@ -375,6 +431,11 @@ static int powernv_add_idle_states(void) */ if ((flags[i] & supported_flags) != flags[i]) continue; + + /* Supported version */ + if (!( strcmp(version[i] , "ibm,idle-state-v1")) + continue; + /* * If an idle state has exit latency beyond * POWERNV_THRESHOLD_LATENCY_NS then don't use it
This patch adds support for new device-tree format for idle state description. Previously if a older kernel runs on a newer firmware, it may enable all available states irrespective of its capability of handling it. New device tree format adds a compatible flag, so that only kernel which has the capability to handle the version of stop state will enable it. Older kernel will still see stop0 and stop0_lite in older format and we will depricate it after some time. Idea is to bump up the version in firmware if we find a bug or regression in stop states. A fix will be provided in linux which would now know about the bumped up version of stop states, where as kernel without fixes would ignore the states. New idle state device tree format : power-mgt { ibm,cpu-idle-state-names = "stop0_lite", "stop0"; ibm,cpu-idle-state-residency-ns = <0x2710 0x4e20>; ibm,cpu-idle-state-latencies-ns = <0x3e8 0x7d0>; ibm,cpu-idle-state-psscr-mask = <0x0 0x3003ff 0x0 0x3003ff>; ibm,cpu-idle-state-psscr = <0x0 0x330 0x0 0x300330>; ibm,cpu-idle-state-flags = <0x100000 0x101000>; ibm,enabled-stop-levels = <0xec000000>; ibm,idle-states { ibm,cpu-idle-state-names = "stop1", "stop2", "stop4", "stop5"; ibm,cpu-idle-state-residency-ns = <0xc350 0x186a0 0x989680 0x1312d00>; ibm,cpu-idle-state-latencies-ns = <0x1388 0x2710 0x186a0 0x30d40>; ibm,cpu-idle-state-psscr-mask = <0x0 0x3003ff 0x0 0x3003ff 0x0 0x3003ff 0x0 0x3003ff>; ibm,cpu-idle-state-psscr = <0x0 0x300331 0x0 0x300332 0x0 0x300374 0x0 0x300375>; ibm,cpu-idle-state-versions = "ibm,idle-state-v1 ", "ibm,idle-state-v1", "ibm,idle-state-v1", "ibm,idle-state-v1"; ibm,cpu-idle-state-flags = <0x101000 0x101000 0x207000 0x207000>; } } Signed-off-by: Akshay Adiga <akshay.adiga@linux.vnet.ibm.com> --- arch/powerpc/platforms/powernv/idle.c | 60 ++++++++++++++++++++++++++------ drivers/cpuidle/cpuidle-powernv.c | 65 +++++++++++++++++++++++++++++++++-- 2 files changed, 112 insertions(+), 13 deletions(-)