diff mbox series

[SCHEME,2] powernv/cpuidle: Add support for new idle state device-tree format

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

Commit Message

Akshay Adiga May 31, 2018, 2:53 a.m. UTC
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(-)

Comments

Akshay Adiga May 31, 2018, 4:41 a.m. UTC | #1
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/
kernel test robot June 1, 2018, 4:39 p.m. UTC | #2
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 mbox series

Patch

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