RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and altivec idle
From: Wang Dongsheng-B40534 <hidden>
Date: 2013-10-17 02:46:09
-----Original Message----- From: Bhushan Bharat-R65777 Sent: Thursday, October 17, 2013 1:01 AM To: Wang Dongsheng-B40534; Wood Scott-B07421 Cc: linuxppc-dev@lists.ozlabs.org Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and altivec idle =20 =20 =20quoted
-----Original Message----- From: Wang Dongsheng-B40534 Sent: Tuesday, October 15, 2013 2:51 PM To: Wood Scott-B07421 Cc: Bhushan Bharat-R65777; linuxppc-dev@lists.ozlabs.org; WangDongsheng-B40534quoted
Subject: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state andaltivec idlequoted
From: Wang Dongsheng <redacted> Add a sys interface to enable/diable pw20 state or altivec idle, andcontrol thequoted
wait entry time. Enable/Disable interface: 0, disable. 1, enable. /sys/devices/system/cpu/cpuX/pw20_state /sys/devices/system/cpu/cpuX/altivec_idle Set wait time interface:(Nanosecond) /sys/devices/system/cpu/cpuX/pw20_wait_time /sys/devices/system/cpu/cpuX/altivec_idle_wait_time Example: Base on TBfreq is 41MHZ. 1~48(ns): TB[63] 49~97(ns): TB[62] 98~195(ns): TB[61] 196~390(ns): TB[60] 391~780(ns): TB[59] 781~1560(ns): TB[58] ... Signed-off-by: Wang Dongsheng <redacted> --- *v5: Change get_idle_ticks_bit function implementation. *v4: Move code from 85xx/common.c to kernel/sysfs.c. Remove has_pw20_altivec_idle function. Change wait "entry_bit" to wait time.diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.cindexquoted
27a90b9..10d1128 100644--- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c@@ -85,6 +85,284 @@ __setup("smt-snooze-delay=3D",setup_smt_snooze_delay);quoted
#endif /* CONFIG_PPC64 */ +#ifdef CONFIG_FSL_SOC +#define MAX_BIT 63 + +static u64 pw20_wt; +static u64 altivec_idle_wt; + +static unsigned int get_idle_ticks_bit(u64 ns) { + u64 cycle; + + if (ns >=3D 10000) + cycle =3D div_u64(ns + 500, 1000) * tb_ticks_per_usec; + else + cycle =3D div_u64(ns * tb_ticks_per_usec, 1000); + + if (!cycle) + return 0; + + return ilog2(cycle); +} + +static void do_show_pwrmgtcr0(void *val) { + u32 *value =3D val; + + *value =3D mfspr(SPRN_PWRMGTCR0); +} + +static ssize_t show_pw20_state(struct device *dev, + struct device_attribute *attr, char *buf) { + u32 value; + unsigned int cpu =3D dev->id; + + smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1); + + value &=3D PWRMGTCR0_PW20_WAIT; + + return sprintf(buf, "%u\n", value ? 1 : 0); } + +static void do_store_pw20_state(void *val) { + u32 *value =3D val; + u32 pw20_state; + + pw20_state =3D mfspr(SPRN_PWRMGTCR0); + + if (*value) + pw20_state |=3D PWRMGTCR0_PW20_WAIT; + else + pw20_state &=3D ~PWRMGTCR0_PW20_WAIT; + + mtspr(SPRN_PWRMGTCR0, pw20_state); +} + +static ssize_t store_pw20_state(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + u32 value; + unsigned int cpu =3D dev->id; + + if (kstrtou32(buf, 0, &value)) + return -EINVAL; + + if (value > 1) + return -EINVAL; + + smp_call_function_single(cpu, do_store_pw20_state, &value, 1); + + return count; +} + +static ssize_t show_pw20_wait_time(struct device *dev, + struct device_attribute *attr, char *buf) { + u32 value; + u64 tb_cycle; + s64 time; + + unsigned int cpu =3D dev->id; + + if (!pw20_wt) { + smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1); + value =3D (value & PWRMGTCR0_PW20_ENT) >> + PWRMGTCR0_PW20_ENT_SHIFT; + + tb_cycle =3D (1 << (MAX_BIT - value)) * 2;=20 Is value =3D 0 and value =3D 1 legal? These will make tb_cycle =3D 0, =20quoted
+ time =3D div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1;=20 And time =3D -1; =20
Please look at the end of the function, :) "return sprintf(buf, "%llu\n", time > 0 ? time : 0);" -dongsheng
=20quoted
+ } else { + time =3D pw20_wt; + } + + return sprintf(buf, "%llu\n", time > 0 ? time : 0); } +