2018-05-31 02:56:05

by Akshay Adiga

[permalink] [raw]
Subject: [PATCH] [SCHEME 2]powernv/cpuidle: Add support for new idle state device-tree format

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 <[email protected]>
---
arch/powerpc/platforms/powernv/idle.c | 60 ++++++++++++++++++++++++++------
drivers/cpuidle/cpuidle-powernv.c | 65 +++++++++++++++++++++++++++++++++--
2 files changed, 112 insertions(+), 13 deletions(-)

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
--
2.5.5



2018-05-31 04:42:48

by Akshay Adiga

[permalink] [raw]
Subject: Re: [PATCH] [SCHEME 2]powernv/cpuidle: Add support for new idle state device-tree format

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 <[email protected]>
> ---

This patch is intended to be a RFC.
The skiboot patch has been posted here :
https://patchwork.ozlabs.org/patch/923121/


2018-06-01 16:40:34

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH] [SCHEME 2]powernv/cpuidle: Add support for new idle state device-tree format

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


Attachments:
(No filename) (13.45 kB)
.config.gz (54.92 kB)
Download all attachments