diff mbox

[v5,4/4] powerpc/85xx: add sysfs for pw20 state and altivec idle

Message ID 1381828871-17110-4-git-send-email-dongsheng.wang@freescale.com (mailing list archive)
State Superseded
Delegated to: Scott Wood
Headers show

Commit Message

Dongsheng Wang Oct. 15, 2013, 9:21 a.m. UTC
From: Wang Dongsheng <dongsheng.wang@freescale.com>

Add a sys interface to enable/diable pw20 state or altivec idle, and
control the 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 <dongsheng.wang@freescale.com>
---
*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.

Comments

Bharat Bhushan Oct. 16, 2013, 5:01 p.m. UTC | #1
> -----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; Wang Dongsheng-B40534
> Subject: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and altivec idle
> 
> From: Wang Dongsheng <dongsheng.wang@freescale.com>
> 
> Add a sys interface to enable/diable pw20 state or altivec idle, and control the
> 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 <dongsheng.wang@freescale.com>
> ---
> *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.c index
> 27a90b9..10d1128 100644
> --- a/arch/powerpc/kernel/sysfs.c
> +++ b/arch/powerpc/kernel/sysfs.c
> @@ -85,6 +85,284 @@ __setup("smt-snooze-delay=", setup_smt_snooze_delay);
> 
>  #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 >= 10000)
> +		cycle = div_u64(ns + 500, 1000) * tb_ticks_per_usec;
> +	else
> +		cycle = div_u64(ns * tb_ticks_per_usec, 1000);
> +
> +	if (!cycle)
> +		return 0;
> +
> +	return ilog2(cycle);
> +}
> +
> +static void do_show_pwrmgtcr0(void *val) {
> +	u32 *value = val;
> +
> +	*value = mfspr(SPRN_PWRMGTCR0);
> +}
> +
> +static ssize_t show_pw20_state(struct device *dev,
> +				struct device_attribute *attr, char *buf) {
> +	u32 value;
> +	unsigned int cpu = dev->id;
> +
> +	smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
> +
> +	value &= PWRMGTCR0_PW20_WAIT;
> +
> +	return sprintf(buf, "%u\n", value ? 1 : 0); }
> +
> +static void do_store_pw20_state(void *val) {
> +	u32 *value = val;
> +	u32 pw20_state;
> +
> +	pw20_state = mfspr(SPRN_PWRMGTCR0);
> +
> +	if (*value)
> +		pw20_state |= PWRMGTCR0_PW20_WAIT;
> +	else
> +		pw20_state &= ~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 = 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 = dev->id;
> +
> +	if (!pw20_wt) {
> +		smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
> +		value = (value & PWRMGTCR0_PW20_ENT) >>
> +					PWRMGTCR0_PW20_ENT_SHIFT;
> +
> +		tb_cycle = (1 << (MAX_BIT - value)) * 2;

Is value = 0 and value = 1 legal? These will make tb_cycle = 0,

> +		time = div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1;

And time = -1;


> +	} else {
> +		time = pw20_wt;
> +	}
> +
> +	return sprintf(buf, "%llu\n", time > 0 ? time : 0);
> }
> +
> +static void set_pw20_wait_entry_bit(void *val) {
> +	u32 *value = val;
> +	u32 pw20_idle;
> +
> +	pw20_idle = mfspr(SPRN_PWRMGTCR0);
> +
> +	/* Set Automatic PW20 Core Idle Count */
> +	/* clear count */
> +	pw20_idle &= ~PWRMGTCR0_PW20_ENT;
> +
> +	/* set count */
> +	pw20_idle |= ((MAX_BIT - *value) << PWRMGTCR0_PW20_ENT_SHIFT);
> +
> +	mtspr(SPRN_PWRMGTCR0, pw20_idle);
> +}
> +
> +static ssize_t store_pw20_wait_time(struct device *dev,
> +				struct device_attribute *attr,
> +				const char *buf, size_t count)
> +{
> +	u32 entry_bit;
> +	u64 value;
> +
> +	unsigned int cpu = dev->id;
> +
> +	if (kstrtou64(buf, 0, &value))
> +		return -EINVAL;
> +
> +	if (!value)
> +		return -EINVAL;
> +
> +	entry_bit = get_idle_ticks_bit(value);
> +	if (entry_bit > MAX_BIT)
> +		return -EINVAL;
> +
> +	pw20_wt = value;
> +	smp_call_function_single(cpu, set_pw20_wait_entry_bit,
> +				&entry_bit, 1);
> +
> +	return count;
> +}
> +
> +static ssize_t show_altivec_idle(struct device *dev,
> +				struct device_attribute *attr, char *buf) {
> +	u32 value;
> +	unsigned int cpu = dev->id;
> +
> +	smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
> +
> +	value &= PWRMGTCR0_AV_IDLE_PD_EN;
> +
> +	return sprintf(buf, "%u\n", value ? 1 : 0); }
> +
> +static void do_store_altivec_idle(void *val) {
> +	u32 *value = val;
> +	u32 altivec_idle;
> +
> +	altivec_idle = mfspr(SPRN_PWRMGTCR0);
> +
> +	if (*value)
> +		altivec_idle |= PWRMGTCR0_AV_IDLE_PD_EN;
> +	else
> +		altivec_idle &= ~PWRMGTCR0_AV_IDLE_PD_EN;
> +
> +	mtspr(SPRN_PWRMGTCR0, altivec_idle);
> +}
> +
> +static ssize_t store_altivec_idle(struct device *dev,
> +				struct device_attribute *attr,
> +				const char *buf, size_t count)
> +{
> +	u32 value;
> +	unsigned int cpu = dev->id;
> +
> +	if (kstrtou32(buf, 0, &value))
> +		return -EINVAL;
> +
> +	if (value > 1)
> +		return -EINVAL;
> +
> +	smp_call_function_single(cpu, do_store_altivec_idle, &value, 1);
> +
> +	return count;
> +}
> +
> +static ssize_t show_altivec_idle_wait_time(struct device *dev,
> +				struct device_attribute *attr, char *buf) {
> +	u32 value;
> +	u64 tb_cycle;
> +	s64 time;
> +
> +	unsigned int cpu = dev->id;
> +
> +	if (!altivec_idle_wt) {
> +		smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
> +		value = (value & PWRMGTCR0_AV_IDLE_CNT) >>
> +					PWRMGTCR0_AV_IDLE_CNT_SHIFT;
> +
> +		tb_cycle = (1 << (MAX_BIT - value)) * 2;
> +		time = div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1;

Likewise

Thanks
-Bharat

> +	} else {
> +		time = altivec_idle_wt;
> +	}
> +
> +	return sprintf(buf, "%llu\n", time > 0 ? time : 0); }
> +
> +static void set_altivec_idle_wait_entry_bit(void *val) {
> +	u32 *value = val;
> +	u32 altivec_idle;
> +
> +	altivec_idle = mfspr(SPRN_PWRMGTCR0);
> +
> +	/* Set Automatic AltiVec Idle Count */
> +	/* clear count */
> +	altivec_idle &= ~PWRMGTCR0_AV_IDLE_CNT;
> +
> +	/* set count */
> +	altivec_idle |= ((MAX_BIT - *value) << PWRMGTCR0_AV_IDLE_CNT_SHIFT);
> +
> +	mtspr(SPRN_PWRMGTCR0, altivec_idle);
> +}
> +
> +static ssize_t store_altivec_idle_wait_time(struct device *dev,
> +				struct device_attribute *attr,
> +				const char *buf, size_t count)
> +{
> +	u32 entry_bit;
> +	u64 value;
> +
> +	unsigned int cpu = dev->id;
> +
> +	if (kstrtou64(buf, 0, &value))
> +		return -EINVAL;
> +
> +	if (!value)
> +		return -EINVAL;
> +
> +	entry_bit = get_idle_ticks_bit(value);
> +	if (entry_bit > MAX_BIT)
> +		return -EINVAL;
> +
> +	altivec_idle_wt = value;
> +	smp_call_function_single(cpu, set_altivec_idle_wait_entry_bit,
> +				&entry_bit, 1);
> +
> +	return count;
> +}
> +
> +/*
> + * Enable/Disable interface:
> + * 0, disable. 1, enable.
> + */
> +static DEVICE_ATTR(pw20_state, 0600, show_pw20_state,
> +store_pw20_state); static DEVICE_ATTR(altivec_idle, 0600,
> +show_altivec_idle, store_altivec_idle);
> +
> +/*
> + * Set wait time interface:(Nanosecond)
> + * 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]
> + * ...
> + */
> +static DEVICE_ATTR(pw20_wait_time, 0600,
> +			show_pw20_wait_time,
> +			store_pw20_wait_time);
> +static DEVICE_ATTR(altivec_idle_wait_time, 0600,
> +			show_altivec_idle_wait_time,
> +			store_altivec_idle_wait_time);
> +#endif
> +
>  /*
>   * Enabling PMCs will slow partition context switch times so we only do
>   * it the first time we write to the PMCs.
> @@ -407,6 +685,15 @@ static void register_cpu_online(unsigned int cpu)
>  		device_create_file(s, &dev_attr_pir);  #endif /* CONFIG_PPC64 */
> 
> +#ifdef CONFIG_FSL_SOC
> +	if (PVR_VER(cur_cpu_spec->pvr_value) == PVR_VER_E6500) {
> +		device_create_file(s, &dev_attr_pw20_state);
> +		device_create_file(s, &dev_attr_pw20_wait_time);
> +
> +		device_create_file(s, &dev_attr_altivec_idle);
> +		device_create_file(s, &dev_attr_altivec_idle_wait_time);
> +	}
> +#endif
>  	cacheinfo_cpu_online(cpu);
>  }
> 
> @@ -479,6 +766,15 @@ static void unregister_cpu_online(unsigned int cpu)
>  		device_remove_file(s, &dev_attr_pir);  #endif /* CONFIG_PPC64 */
> 
> +#ifdef CONFIG_FSL_SOC
> +	if (PVR_VER(cur_cpu_spec->pvr_value) == PVR_VER_E6500) {
> +		device_remove_file(s, &dev_attr_pw20_state);
> +		device_remove_file(s, &dev_attr_pw20_wait_time);
> +
> +		device_remove_file(s, &dev_attr_altivec_idle);
> +		device_remove_file(s, &dev_attr_altivec_idle_wait_time);
> +	}
> +#endif
>  	cacheinfo_cpu_offline(cpu);
>  }
> 
> --
> 1.8.0
Wang Dongsheng-B40534 Oct. 17, 2013, 2:46 a.m. UTC | #2
> -----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
> 
> 
> 
> > -----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; Wang
> Dongsheng-B40534
> > Subject: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and
> altivec idle
> >
> > From: Wang Dongsheng <dongsheng.wang@freescale.com>
> >
> > Add a sys interface to enable/diable pw20 state or altivec idle, and
> control the
> > 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 <dongsheng.wang@freescale.com>
> > ---
> > *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.c
> index
> > 27a90b9..10d1128 100644
> > --- a/arch/powerpc/kernel/sysfs.c
> > +++ b/arch/powerpc/kernel/sysfs.c
> > @@ -85,6 +85,284 @@ __setup("smt-snooze-delay=",
> setup_smt_snooze_delay);
> >
> >  #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 >= 10000)
> > +		cycle = div_u64(ns + 500, 1000) * tb_ticks_per_usec;
> > +	else
> > +		cycle = div_u64(ns * tb_ticks_per_usec, 1000);
> > +
> > +	if (!cycle)
> > +		return 0;
> > +
> > +	return ilog2(cycle);
> > +}
> > +
> > +static void do_show_pwrmgtcr0(void *val) {
> > +	u32 *value = val;
> > +
> > +	*value = mfspr(SPRN_PWRMGTCR0);
> > +}
> > +
> > +static ssize_t show_pw20_state(struct device *dev,
> > +				struct device_attribute *attr, char *buf) {
> > +	u32 value;
> > +	unsigned int cpu = dev->id;
> > +
> > +	smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
> > +
> > +	value &= PWRMGTCR0_PW20_WAIT;
> > +
> > +	return sprintf(buf, "%u\n", value ? 1 : 0); }
> > +
> > +static void do_store_pw20_state(void *val) {
> > +	u32 *value = val;
> > +	u32 pw20_state;
> > +
> > +	pw20_state = mfspr(SPRN_PWRMGTCR0);
> > +
> > +	if (*value)
> > +		pw20_state |= PWRMGTCR0_PW20_WAIT;
> > +	else
> > +		pw20_state &= ~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 = 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 = dev->id;
> > +
> > +	if (!pw20_wt) {
> > +		smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
> > +		value = (value & PWRMGTCR0_PW20_ENT) >>
> > +					PWRMGTCR0_PW20_ENT_SHIFT;
> > +
> > +		tb_cycle = (1 << (MAX_BIT - value)) * 2;
> 
> Is value = 0 and value = 1 legal? These will make tb_cycle = 0,
> 
> > +		time = div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1;
> 
> And time = -1;
> 
Please look at the end of the function, :)

"return sprintf(buf, "%llu\n", time > 0 ? time : 0);"

-dongsheng

> 
> > +	} else {
> > +		time = pw20_wt;
> > +	}
> > +
> > +	return sprintf(buf, "%llu\n", time > 0 ? time : 0);
> > }
> > +
Bharat Bhushan Oct. 17, 2013, 3:19 a.m. UTC | #3
> -----Original Message-----
> From: Wang Dongsheng-B40534
> Sent: Thursday, October 17, 2013 8:16 AM
> To: Bhushan Bharat-R65777; 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
> 
> 
> 
> > -----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
> >
> >
> >
> > > -----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; Wang
> > Dongsheng-B40534
> > > Subject: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and
> > altivec idle
> > >
> > > From: Wang Dongsheng <dongsheng.wang@freescale.com>
> > >
> > > Add a sys interface to enable/diable pw20 state or altivec idle, and
> > control the
> > > 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 <dongsheng.wang@freescale.com>
> > > ---
> > > *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.c
> > index
> > > 27a90b9..10d1128 100644
> > > --- a/arch/powerpc/kernel/sysfs.c
> > > +++ b/arch/powerpc/kernel/sysfs.c
> > > @@ -85,6 +85,284 @@ __setup("smt-snooze-delay=",
> > setup_smt_snooze_delay);
> > >
> > >  #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 >= 10000)
> > > +		cycle = div_u64(ns + 500, 1000) * tb_ticks_per_usec;
> > > +	else
> > > +		cycle = div_u64(ns * tb_ticks_per_usec, 1000);
> > > +
> > > +	if (!cycle)
> > > +		return 0;
> > > +
> > > +	return ilog2(cycle);
> > > +}
> > > +
> > > +static void do_show_pwrmgtcr0(void *val) {
> > > +	u32 *value = val;
> > > +
> > > +	*value = mfspr(SPRN_PWRMGTCR0);
> > > +}
> > > +
> > > +static ssize_t show_pw20_state(struct device *dev,
> > > +				struct device_attribute *attr, char *buf) {
> > > +	u32 value;
> > > +	unsigned int cpu = dev->id;
> > > +
> > > +	smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
> > > +
> > > +	value &= PWRMGTCR0_PW20_WAIT;
> > > +
> > > +	return sprintf(buf, "%u\n", value ? 1 : 0); }
> > > +
> > > +static void do_store_pw20_state(void *val) {
> > > +	u32 *value = val;
> > > +	u32 pw20_state;
> > > +
> > > +	pw20_state = mfspr(SPRN_PWRMGTCR0);
> > > +
> > > +	if (*value)
> > > +		pw20_state |= PWRMGTCR0_PW20_WAIT;
> > > +	else
> > > +		pw20_state &= ~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 = 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 = dev->id;
> > > +
> > > +	if (!pw20_wt) {
> > > +		smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
> > > +		value = (value & PWRMGTCR0_PW20_ENT) >>
> > > +					PWRMGTCR0_PW20_ENT_SHIFT;
> > > +
> > > +		tb_cycle = (1 << (MAX_BIT - value)) * 2;
> >
> > Is value = 0 and value = 1 legal? These will make tb_cycle = 0,
> >
> > > +		time = div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1;
> >
> > And time = -1;
> >
> Please look at the end of the function, :)
> 
> "return sprintf(buf, "%llu\n", time > 0 ? time : 0);"

I know you return 0 if value = 0/1, my question was that, is this correct as per specification?

Ahh, also for "value" upto 7 you will return 0, no?

-Bharat

> 
> -dongsheng
> 
> >
> > > +	} else {
> > > +		time = pw20_wt;
> > > +	}
> > > +
> > > +	return sprintf(buf, "%llu\n", time > 0 ? time : 0);
> > > }
> > > +
Wang Dongsheng-B40534 Oct. 17, 2013, 5:51 a.m. UTC | #4
> -----Original Message-----
> From: Bhushan Bharat-R65777
> Sent: Thursday, October 17, 2013 11:20 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
> 
> 
> 
> > -----Original Message-----
> > From: Wang Dongsheng-B40534
> > Sent: Thursday, October 17, 2013 8:16 AM
> > To: Bhushan Bharat-R65777; 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
> >
> >
> >
> > > -----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
> > >
> > >
> > >
> > > > -----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; Wang
> > > Dongsheng-B40534
> > > > Subject: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and
> > > altivec idle
> > > >
> > > > From: Wang Dongsheng <dongsheng.wang@freescale.com>
> > > >
> > > > Add a sys interface to enable/diable pw20 state or altivec idle,
> > > > and
> > > control the
> > > > 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 <dongsheng.wang@freescale.com>
> > > > ---
> > > > *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.c
> > > index
> > > > 27a90b9..10d1128 100644
> > > > --- a/arch/powerpc/kernel/sysfs.c
> > > > +++ b/arch/powerpc/kernel/sysfs.c
> > > > @@ -85,6 +85,284 @@ __setup("smt-snooze-delay=",
> > > setup_smt_snooze_delay);
> > > >
> > > >  #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 >= 10000)
> > > > +		cycle = div_u64(ns + 500, 1000) * tb_ticks_per_usec;
> > > > +	else
> > > > +		cycle = div_u64(ns * tb_ticks_per_usec, 1000);
> > > > +
> > > > +	if (!cycle)
> > > > +		return 0;
> > > > +
> > > > +	return ilog2(cycle);
> > > > +}
> > > > +
> > > > +static void do_show_pwrmgtcr0(void *val) {
> > > > +	u32 *value = val;
> > > > +
> > > > +	*value = mfspr(SPRN_PWRMGTCR0);
> > > > +}
> > > > +
> > > > +static ssize_t show_pw20_state(struct device *dev,
> > > > +				struct device_attribute *attr, char *buf) {
> > > > +	u32 value;
> > > > +	unsigned int cpu = dev->id;
> > > > +
> > > > +	smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
> > > > +
> > > > +	value &= PWRMGTCR0_PW20_WAIT;
> > > > +
> > > > +	return sprintf(buf, "%u\n", value ? 1 : 0); }
> > > > +
> > > > +static void do_store_pw20_state(void *val) {
> > > > +	u32 *value = val;
> > > > +	u32 pw20_state;
> > > > +
> > > > +	pw20_state = mfspr(SPRN_PWRMGTCR0);
> > > > +
> > > > +	if (*value)
> > > > +		pw20_state |= PWRMGTCR0_PW20_WAIT;
> > > > +	else
> > > > +		pw20_state &= ~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 = 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 = dev->id;
> > > > +
> > > > +	if (!pw20_wt) {
> > > > +		smp_call_function_single(cpu, do_show_pwrmgtcr0, &value,
> 1);
> > > > +		value = (value & PWRMGTCR0_PW20_ENT) >>
> > > > +					PWRMGTCR0_PW20_ENT_SHIFT;
> > > > +
> > > > +		tb_cycle = (1 << (MAX_BIT - value)) * 2;
> > >
> > > Is value = 0 and value = 1 legal? These will make tb_cycle = 0,
> > >
> > > > +		time = div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1;
> > >
> > > And time = -1;
> > >
> > Please look at the end of the function, :)
> >
> > "return sprintf(buf, "%llu\n", time > 0 ? time : 0);"
> 
> I know you return 0 if value = 0/1, my question was that, is this correct
> as per specification?
> 
> Ahh, also for "value" upto 7 you will return 0, no?
> 
If value = 0, MAX_BIT - value = 63
tb_cycle = 0xffffffff_ffffffff, tb_cycle * 1000 will overflow, but this situation is not possible.
Because if the "value = 0" means this feature will be "disable".
Now The default wait bit is 50(MAX_BIT - value, value = 13), the PW20/Altivec Idle wait entry time is about 1ms, this time is very long for wait idle time, and it's cannot be increased(means (MAX_BIT - value) cannot greater than 50).
	
If (MAX_BIT-value) = 0, tb_cycle = 2,
div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1 = ((2 * 1000) / 41) - 1 = 48 - 1 = 47

the return value is 47

> -Bharat
> 
> >
> > -dongsheng
> >
> > >
> > > > +	} else {
> > > > +		time = pw20_wt;
> > > > +	}
> > > > +
> > > > +	return sprintf(buf, "%llu\n", time > 0 ? time : 0);
> > > > }
> > > > +
Bharat Bhushan Oct. 17, 2013, 6 a.m. UTC | #5
> -----Original Message-----
> From: Wang Dongsheng-B40534
> Sent: Thursday, October 17, 2013 11:22 AM
> To: Bhushan Bharat-R65777; 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
> 
> 
> 
> > -----Original Message-----
> > From: Bhushan Bharat-R65777
> > Sent: Thursday, October 17, 2013 11:20 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
> >
> >
> >
> > > -----Original Message-----
> > > From: Wang Dongsheng-B40534
> > > Sent: Thursday, October 17, 2013 8:16 AM
> > > To: Bhushan Bharat-R65777; 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
> > >
> > >
> > >
> > > > -----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
> > > >
> > > >
> > > >
> > > > > -----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; Wang
> > > > Dongsheng-B40534
> > > > > Subject: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state
> > > > > and
> > > > altivec idle
> > > > >
> > > > > From: Wang Dongsheng <dongsheng.wang@freescale.com>
> > > > >
> > > > > Add a sys interface to enable/diable pw20 state or altivec idle,
> > > > > and
> > > > control the
> > > > > 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 <dongsheng.wang@freescale.com>
> > > > > ---
> > > > > *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.c
> > > > index
> > > > > 27a90b9..10d1128 100644
> > > > > --- a/arch/powerpc/kernel/sysfs.c
> > > > > +++ b/arch/powerpc/kernel/sysfs.c
> > > > > @@ -85,6 +85,284 @@ __setup("smt-snooze-delay=",
> > > > setup_smt_snooze_delay);
> > > > >
> > > > >  #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 >= 10000)
> > > > > +		cycle = div_u64(ns + 500, 1000) * tb_ticks_per_usec;
> > > > > +	else
> > > > > +		cycle = div_u64(ns * tb_ticks_per_usec, 1000);
> > > > > +
> > > > > +	if (!cycle)
> > > > > +		return 0;
> > > > > +
> > > > > +	return ilog2(cycle);
> > > > > +}
> > > > > +
> > > > > +static void do_show_pwrmgtcr0(void *val) {
> > > > > +	u32 *value = val;
> > > > > +
> > > > > +	*value = mfspr(SPRN_PWRMGTCR0); }
> > > > > +
> > > > > +static ssize_t show_pw20_state(struct device *dev,
> > > > > +				struct device_attribute *attr, char *buf) {
> > > > > +	u32 value;
> > > > > +	unsigned int cpu = dev->id;
> > > > > +
> > > > > +	smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
> > > > > +
> > > > > +	value &= PWRMGTCR0_PW20_WAIT;
> > > > > +
> > > > > +	return sprintf(buf, "%u\n", value ? 1 : 0); }
> > > > > +
> > > > > +static void do_store_pw20_state(void *val) {
> > > > > +	u32 *value = val;
> > > > > +	u32 pw20_state;
> > > > > +
> > > > > +	pw20_state = mfspr(SPRN_PWRMGTCR0);
> > > > > +
> > > > > +	if (*value)
> > > > > +		pw20_state |= PWRMGTCR0_PW20_WAIT;
> > > > > +	else
> > > > > +		pw20_state &= ~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 = 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 = dev->id;
> > > > > +
> > > > > +	if (!pw20_wt) {
> > > > > +		smp_call_function_single(cpu, do_show_pwrmgtcr0, &value,
> > 1);
> > > > > +		value = (value & PWRMGTCR0_PW20_ENT) >>
> > > > > +					PWRMGTCR0_PW20_ENT_SHIFT;
> > > > > +
> > > > > +		tb_cycle = (1 << (MAX_BIT - value)) * 2;
> > > >
> > > > Is value = 0 and value = 1 legal? These will make tb_cycle = 0,
> > > >
> > > > > +		time = div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1;
> > > >
> > > > And time = -1;
> > > >
> > > Please look at the end of the function, :)
> > >
> > > "return sprintf(buf, "%llu\n", time > 0 ? time : 0);"
> >
> > I know you return 0 if value = 0/1, my question was that, is this
> > correct as per specification?
> >
> > Ahh, also for "value" upto 7 you will return 0, no?
> >
> If value = 0, MAX_BIT - value = 63
> tb_cycle = 0xffffffff_ffffffff, tb_cycle * 1000 will overflow, but this
> situation is not possible.
> Because if the "value = 0" means this feature will be "disable".
> Now The default wait bit is 50(MAX_BIT - value, value = 13), the PW20/Altivec
> Idle wait entry time is about 1ms, this time is very long for wait idle time,
> and it's cannot be increased(means (MAX_BIT - value) cannot greater than 50).

What you said is not obvious from code and so at least write a comment that value will be always >= 13 or value will never be less than < 8 and below calculation will not overflow. may be error out if value is less than 8.

-Bharat

> 
> If (MAX_BIT-value) = 0, tb_cycle = 2,
> div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1 = ((2 * 1000) / 41) - 1 = 48 - 1
> = 47
> 
> the return value is 47
> 
> > -Bharat
> >
> > >
> > > -dongsheng
> > >
> > > >
> > > > > +	} else {
> > > > > +		time = pw20_wt;
> > > > > +	}
> > > > > +
> > > > > +	return sprintf(buf, "%llu\n", time > 0 ? time : 0);
> > > > > }
> > > > > +
Wang Dongsheng-B40534 Oct. 17, 2013, 6:34 a.m. UTC | #6
> -----Original Message-----
> From: Bhushan Bharat-R65777
> Sent: Thursday, October 17, 2013 2:00 PM
> 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
> 
> 
> 
> > -----Original Message-----
> > From: Wang Dongsheng-B40534
> > Sent: Thursday, October 17, 2013 11:22 AM
> > To: Bhushan Bharat-R65777; 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
> >
> >
> >
> > > -----Original Message-----
> > > From: Bhushan Bharat-R65777
> > > Sent: Thursday, October 17, 2013 11:20 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
> > >
> > >
> > >
> > > > -----Original Message-----
> > > > From: Wang Dongsheng-B40534
> > > > Sent: Thursday, October 17, 2013 8:16 AM
> > > > To: Bhushan Bharat-R65777; 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
> > > >
> > > >
> > > >
> > > > > -----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
> > > > >
> > > > >
> > > > >
> > > > > > -----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; Wang
> > > > > Dongsheng-B40534
> > > > > > Subject: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state
> > > > > > and
> > > > > altivec idle
> > > > > >
> > > > > > From: Wang Dongsheng <dongsheng.wang@freescale.com>
> > > > > >
> > > > > > Add a sys interface to enable/diable pw20 state or altivec
> > > > > > idle, and
> > > > > control the
> > > > > > 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 <dongsheng.wang@freescale.com>
> > > > > > ---
> > > > > > *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.c
> > > > > index
> > > > > > 27a90b9..10d1128 100644
> > > > > > --- a/arch/powerpc/kernel/sysfs.c
> > > > > > +++ b/arch/powerpc/kernel/sysfs.c
> > > > > > @@ -85,6 +85,284 @@ __setup("smt-snooze-delay=",
> > > > > setup_smt_snooze_delay);
> > > > > >
> > > > > >  #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 >= 10000)
> > > > > > +		cycle = div_u64(ns + 500, 1000) * tb_ticks_per_usec;
> > > > > > +	else
> > > > > > +		cycle = div_u64(ns * tb_ticks_per_usec, 1000);
> > > > > > +
> > > > > > +	if (!cycle)
> > > > > > +		return 0;
> > > > > > +
> > > > > > +	return ilog2(cycle);
> > > > > > +}
> > > > > > +
> > > > > > +static void do_show_pwrmgtcr0(void *val) {
> > > > > > +	u32 *value = val;
> > > > > > +
> > > > > > +	*value = mfspr(SPRN_PWRMGTCR0); }
> > > > > > +
> > > > > > +static ssize_t show_pw20_state(struct device *dev,
> > > > > > +				struct device_attribute *attr, char *buf) {
> > > > > > +	u32 value;
> > > > > > +	unsigned int cpu = dev->id;
> > > > > > +
> > > > > > +	smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
> > > > > > +
> > > > > > +	value &= PWRMGTCR0_PW20_WAIT;
> > > > > > +
> > > > > > +	return sprintf(buf, "%u\n", value ? 1 : 0); }
> > > > > > +
> > > > > > +static void do_store_pw20_state(void *val) {
> > > > > > +	u32 *value = val;
> > > > > > +	u32 pw20_state;
> > > > > > +
> > > > > > +	pw20_state = mfspr(SPRN_PWRMGTCR0);
> > > > > > +
> > > > > > +	if (*value)
> > > > > > +		pw20_state |= PWRMGTCR0_PW20_WAIT;
> > > > > > +	else
> > > > > > +		pw20_state &= ~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 = 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 = dev->id;
> > > > > > +
> > > > > > +	if (!pw20_wt) {
> > > > > > +		smp_call_function_single(cpu, do_show_pwrmgtcr0, &value,
> > > 1);
> > > > > > +		value = (value & PWRMGTCR0_PW20_ENT) >>
> > > > > > +					PWRMGTCR0_PW20_ENT_SHIFT;
> > > > > > +
> > > > > > +		tb_cycle = (1 << (MAX_BIT - value)) * 2;
> > > > >
> > > > > Is value = 0 and value = 1 legal? These will make tb_cycle = 0,
> > > > >
> > > > > > +		time = div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1;
> > > > >
> > > > > And time = -1;
> > > > >
> > > > Please look at the end of the function, :)
> > > >
> > > > "return sprintf(buf, "%llu\n", time > 0 ? time : 0);"
> > >
> > > I know you return 0 if value = 0/1, my question was that, is this
> > > correct as per specification?
> > >
> > > Ahh, also for "value" upto 7 you will return 0, no?
> > >
> > If value = 0, MAX_BIT - value = 63
> > tb_cycle = 0xffffffff_ffffffff, tb_cycle * 1000 will overflow, but
> > this situation is not possible.
> > Because if the "value = 0" means this feature will be "disable".
> > Now The default wait bit is 50(MAX_BIT - value, value = 13), the
> > PW20/Altivec Idle wait entry time is about 1ms, this time is very long
> > for wait idle time, and it's cannot be increased(means (MAX_BIT - value)
> cannot greater than 50).
> 
> What you said is not obvious from code and so at least write a comment
> that value will be always >= 13 or value will never be less than < 8 and
> below calculation will not overflow. may be error out if value is less
> than 8.
> 
The "value" less than 10, this will overflow.
There is not error, The code I knew it could not be less than 10, that's why I use the following code. :)

tb_cycle = (1 << (MAX_BIT - value)) * 2; 
time = div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1;

-dongsheng

> -Bharat
> 
> >
> > If (MAX_BIT-value) = 0, tb_cycle = 2,
> > div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1 = ((2 * 1000) / 41) -
> > 1 = 48 - 1 = 47
> >
> > the return value is 47
> >
> > > -Bharat
> > >
> > > >
> > > > -dongsheng
> > > >
> > > > >
> > > > > > +	} else {
> > > > > > +		time = pw20_wt;
> > > > > > +	}
> > > > > > +
> > > > > > +	return sprintf(buf, "%llu\n", time > 0 ? time : 0);
> > > > > > }
> > > > > > +
Bharat Bhushan Oct. 17, 2013, 6:45 a.m. UTC | #7
> > > -----Original Message-----
> > > From: Wang Dongsheng-B40534
> > > Sent: Thursday, October 17, 2013 11:22 AM
> > > To: Bhushan Bharat-R65777; 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
> > >
> > >
> > >
> > > > -----Original Message-----
> > > > From: Bhushan Bharat-R65777
> > > > Sent: Thursday, October 17, 2013 11:20 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
> > > >
> > > >
> > > >
> > > > > -----Original Message-----
> > > > > From: Wang Dongsheng-B40534
> > > > > Sent: Thursday, October 17, 2013 8:16 AM
> > > > > To: Bhushan Bharat-R65777; 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
> > > > >
> > > > >
> > > > >
> > > > > > -----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
> > > > > >
> > > > > >
> > > > > >
> > > > > > > -----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;
> > > > > > > Wang
> > > > > > Dongsheng-B40534
> > > > > > > Subject: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20
> > > > > > > state and
> > > > > > altivec idle
> > > > > > >
> > > > > > > From: Wang Dongsheng <dongsheng.wang@freescale.com>
> > > > > > >
> > > > > > > Add a sys interface to enable/diable pw20 state or altivec
> > > > > > > idle, and
> > > > > > control the
> > > > > > > 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 <dongsheng.wang@freescale.com>
> > > > > > > ---
> > > > > > > *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.c
> > > > > > index
> > > > > > > 27a90b9..10d1128 100644
> > > > > > > --- a/arch/powerpc/kernel/sysfs.c
> > > > > > > +++ b/arch/powerpc/kernel/sysfs.c
> > > > > > > @@ -85,6 +85,284 @@ __setup("smt-snooze-delay=",
> > > > > > setup_smt_snooze_delay);
> > > > > > >
> > > > > > >  #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 >= 10000)
> > > > > > > +		cycle = div_u64(ns + 500, 1000) * tb_ticks_per_usec;
> > > > > > > +	else
> > > > > > > +		cycle = div_u64(ns * tb_ticks_per_usec, 1000);
> > > > > > > +
> > > > > > > +	if (!cycle)
> > > > > > > +		return 0;
> > > > > > > +
> > > > > > > +	return ilog2(cycle);
> > > > > > > +}
> > > > > > > +
> > > > > > > +static void do_show_pwrmgtcr0(void *val) {
> > > > > > > +	u32 *value = val;
> > > > > > > +
> > > > > > > +	*value = mfspr(SPRN_PWRMGTCR0); }
> > > > > > > +
> > > > > > > +static ssize_t show_pw20_state(struct device *dev,
> > > > > > > +				struct device_attribute *attr, char *buf) {
> > > > > > > +	u32 value;
> > > > > > > +	unsigned int cpu = dev->id;
> > > > > > > +
> > > > > > > +	smp_call_function_single(cpu, do_show_pwrmgtcr0, &value,
> > > > > > > +1);
> > > > > > > +
> > > > > > > +	value &= PWRMGTCR0_PW20_WAIT;
> > > > > > > +
> > > > > > > +	return sprintf(buf, "%u\n", value ? 1 : 0); }
> > > > > > > +
> > > > > > > +static void do_store_pw20_state(void *val) {
> > > > > > > +	u32 *value = val;
> > > > > > > +	u32 pw20_state;
> > > > > > > +
> > > > > > > +	pw20_state = mfspr(SPRN_PWRMGTCR0);
> > > > > > > +
> > > > > > > +	if (*value)
> > > > > > > +		pw20_state |= PWRMGTCR0_PW20_WAIT;
> > > > > > > +	else
> > > > > > > +		pw20_state &= ~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 = 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 = dev->id;
> > > > > > > +
> > > > > > > +	if (!pw20_wt) {
> > > > > > > +		smp_call_function_single(cpu, do_show_pwrmgtcr0, &value,
> > > > 1);
> > > > > > > +		value = (value & PWRMGTCR0_PW20_ENT) >>
> > > > > > > +					PWRMGTCR0_PW20_ENT_SHIFT;
> > > > > > > +
> > > > > > > +		tb_cycle = (1 << (MAX_BIT - value)) * 2;
> > > > > >
> > > > > > Is value = 0 and value = 1 legal? These will make tb_cycle =
> > > > > > 0,
> > > > > >
> > > > > > > +		time = div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1;
> > > > > >
> > > > > > And time = -1;
> > > > > >
> > > > > Please look at the end of the function, :)
> > > > >
> > > > > "return sprintf(buf, "%llu\n", time > 0 ? time : 0);"
> > > >
> > > > I know you return 0 if value = 0/1, my question was that, is this
> > > > correct as per specification?
> > > >
> > > > Ahh, also for "value" upto 7 you will return 0, no?
> > > >
> > > If value = 0, MAX_BIT - value = 63
> > > tb_cycle = 0xffffffff_ffffffff, tb_cycle * 1000 will overflow, but
> > > this situation is not possible.
> > > Because if the "value = 0" means this feature will be "disable".
> > > Now The default wait bit is 50(MAX_BIT - value, value = 13), the
> > > PW20/Altivec Idle wait entry time is about 1ms, this time is very
> > > long for wait idle time, and it's cannot be increased(means (MAX_BIT
> > > - value)
> > cannot greater than 50).
> >
> > What you said is not obvious from code and so at least write a comment
> > that value will be always >= 13 or value will never be less than < 8
> > and below calculation will not overflow. may be error out if value is
> > less than 8.
> >
> The "value" less than 10, this will overflow.
> There is not error, The code I knew it could not be less than 10, that's why I
> use the following code. :)

I am sorry to persist but this is not about what you know, this is about how code is read and code does not say what you know, so add a comment at least and error out/warn when "value" is less than a certain number.

-Bharat

> 
> tb_cycle = (1 << (MAX_BIT - value)) * 2; time = div_u64(tb_cycle * 1000,
> tb_ticks_per_usec) - 1;
> 
> -dongsheng
> 
> > -Bharat
> >
> > >
> > > If (MAX_BIT-value) = 0, tb_cycle = 2, div_u64(tb_cycle * 1000,
> > > tb_ticks_per_usec) - 1 = ((2 * 1000) / 41) -
> > > 1 = 48 - 1 = 47
> > >
> > > the return value is 47
> > >
> > > > -Bharat
> > > >
> > > > >
> > > > > -dongsheng
> > > > >
> > > > > >
> > > > > > > +	} else {
> > > > > > > +		time = pw20_wt;
> > > > > > > +	}
> > > > > > > +
> > > > > > > +	return sprintf(buf, "%llu\n", time > 0 ? time : 0);
> > > > > > > }
> > > > > > > +
Scott Wood Oct. 17, 2013, 4:51 p.m. UTC | #8
On Thu, 2013-10-17 at 00:51 -0500, Wang Dongsheng-B40534 wrote:
> 
> > -----Original Message-----
> > From: Bhushan Bharat-R65777
> > Sent: Thursday, October 17, 2013 11:20 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
> > 
> > 
> > 
> > > -----Original Message-----
> > > From: Wang Dongsheng-B40534
> > > Sent: Thursday, October 17, 2013 8:16 AM
> > > To: Bhushan Bharat-R65777; 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
> > >
> > >
> > >
> > > > -----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
> > > >
> > > >
> > > >
> > > > > -----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; Wang
> > > > Dongsheng-B40534
> > > > > Subject: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and
> > > > altivec idle
> > > > >
> > > > > +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 = dev->id;
> > > > > +
> > > > > +	if (!pw20_wt) {
> > > > > +		smp_call_function_single(cpu, do_show_pwrmgtcr0, &value,
> > 1);
> > > > > +		value = (value & PWRMGTCR0_PW20_ENT) >>
> > > > > +					PWRMGTCR0_PW20_ENT_SHIFT;
> > > > > +
> > > > > +		tb_cycle = (1 << (MAX_BIT - value)) * 2;
> > > >
> > > > Is value = 0 and value = 1 legal? These will make tb_cycle = 0,
> > > >
> > > > > +		time = div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1;
> > > >
> > > > And time = -1;
> > > >
> > > Please look at the end of the function, :)
> > >
> > > "return sprintf(buf, "%llu\n", time > 0 ? time : 0);"
> > 
> > I know you return 0 if value = 0/1, my question was that, is this correct
> > as per specification?
> > 
> > Ahh, also for "value" upto 7 you will return 0, no?
> > 
> If value = 0, MAX_BIT - value = 63
> tb_cycle = 0xffffffff_ffffffff, 

Actually, tb_cycle will be undefined because you shifted a 32-bit value
(1) by more than 31 bits.  s/1/1ULL/

> tb_cycle * 1000 will overflow, but this situation is not possible.
> Because if the "value = 0" means this feature will be "disable".
> Now The default wait bit is 50(MAX_BIT - value, value = 13), the
> PW20/Altivec Idle wait entry time is about 1ms, this time is very long
> for wait idle time, and it's cannot be increased(means (MAX_BIT -
> value) cannot greater than 50).

Why can it not be increased?

-Scott
Wang Dongsheng-B40534 Oct. 18, 2013, 2:36 a.m. UTC | #9
> -----Original Message-----
> From: Wood Scott-B07421
> Sent: Friday, October 18, 2013 12:52 AM
> To: Wang Dongsheng-B40534
> Cc: Bhushan Bharat-R65777; Wood Scott-B07421; linuxppc-
> dev@lists.ozlabs.org
> Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and
> altivec idle
> 
> On Thu, 2013-10-17 at 00:51 -0500, Wang Dongsheng-B40534 wrote:
> >
> > > -----Original Message-----
> > > From: Bhushan Bharat-R65777
> > > Sent: Thursday, October 17, 2013 11:20 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
> > >
> > >
> > >
> > > > -----Original Message-----
> > > > From: Wang Dongsheng-B40534
> > > > Sent: Thursday, October 17, 2013 8:16 AM
> > > > To: Bhushan Bharat-R65777; 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
> > > >
> > > >
> > > >
> > > > > -----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
> > > > >
> > > > >
> > > > >
> > > > > > -----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; Wang
> > > > > Dongsheng-B40534
> > > > > > Subject: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state
> > > > > > and
> > > > > altivec idle
> > > > > >
> > > > > > +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 = dev->id;
> > > > > > +
> > > > > > +	if (!pw20_wt) {
> > > > > > +		smp_call_function_single(cpu, do_show_pwrmgtcr0, &value,
> > > 1);
> > > > > > +		value = (value & PWRMGTCR0_PW20_ENT) >>
> > > > > > +					PWRMGTCR0_PW20_ENT_SHIFT;
> > > > > > +
> > > > > > +		tb_cycle = (1 << (MAX_BIT - value)) * 2;
> > > > >
> > > > > Is value = 0 and value = 1 legal? These will make tb_cycle = 0,
> > > > >
> > > > > > +		time = div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1;
> > > > >
> > > > > And time = -1;
> > > > >
> > > > Please look at the end of the function, :)
> > > >
> > > > "return sprintf(buf, "%llu\n", time > 0 ? time : 0);"
> > >
> > > I know you return 0 if value = 0/1, my question was that, is this
> > > correct as per specification?
> > >
> > > Ahh, also for "value" upto 7 you will return 0, no?
> > >
> > If value = 0, MAX_BIT - value = 63
> > tb_cycle = 0xffffffff_ffffffff,
> 
> Actually, tb_cycle will be undefined because you shifted a 32-bit value
> (1) by more than 31 bits.  s/1/1ULL/
> 
Actually, we have been discussing this situation that could not have happened.
See !pw20_wt branch, this branch is read default wait bit.
The default wait bit is 50, the time is about 1ms.
The default wait bit cannot less than 50, means the wait entry time cannot greater than 1ms.
We have already begun benchmark test, and we got a preliminary results.
55, 56, 57bit looks good, but we need more benchmark to get the default bit.

	if (!pw20_wt) {
		smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
		value = (value & PWRMGTCR0_PW20_ENT) >>
					PWRMGTCR0_PW20_ENT_SHIFT;

		tb_cycle = (1 << (MAX_BIT - value)) * 2;
		time = div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1;
	} else {
		time = pw20_wt;
	}

If it caused confusion, we can add a comment. As I discuss with Bharat.

> > tb_cycle * 1000 will overflow, but this situation is not possible.
> > Because if the "value = 0" means this feature will be "disable".
> > Now The default wait bit is 50(MAX_BIT - value, value = 13), the
> > PW20/Altivec Idle wait entry time is about 1ms, this time is very long
> > for wait idle time, and it's cannot be increased(means (MAX_BIT -
> > value) cannot greater than 50).
> 
> Why can it not be increased?
>
see above, :)

-dongsheng
> -Scott
>
Wang Dongsheng-B40534 Oct. 18, 2013, 3:02 a.m. UTC | #10
> -----Original Message-----
> From: Bhushan Bharat-R65777
> Sent: Thursday, October 17, 2013 2:46 PM
> 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
> 
> 
> 
> > > > -----Original Message-----
> > > > From: Wang Dongsheng-B40534
> > > > Sent: Thursday, October 17, 2013 11:22 AM
> > > > To: Bhushan Bharat-R65777; 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
> > > >
> > > >
> > > >
> > > > > -----Original Message-----
> > > > > From: Bhushan Bharat-R65777
> > > > > Sent: Thursday, October 17, 2013 11:20 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
> > > > >
> > > > >
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: Wang Dongsheng-B40534
> > > > > > Sent: Thursday, October 17, 2013 8:16 AM
> > > > > > To: Bhushan Bharat-R65777; 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
> > > > > >
> > > > > >
> > > > > >
> > > > > > > -----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
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > > -----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;
> > > > > > > > Wang
> > > > > > > Dongsheng-B40534
> > > > > > > > Subject: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20
> > > > > > > > state and
> > > > > > > altivec idle
> > > > > > > >
> > > > > > > > From: Wang Dongsheng <dongsheng.wang@freescale.com>
> > > > > > > >
> > > > > > > > Add a sys interface to enable/diable pw20 state or altivec
> > > > > > > > idle, and
> > > > > > > control the
> > > > > > > > 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
> > > > > > > > <dongsheng.wang@freescale.com>
> > > > > > > > ---
> > > > > > > > *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.c
> > > > > > > index
> > > > > > > > 27a90b9..10d1128 100644
> > > > > > > > --- a/arch/powerpc/kernel/sysfs.c
> > > > > > > > +++ b/arch/powerpc/kernel/sysfs.c
> > > > > > > > @@ -85,6 +85,284 @@ __setup("smt-snooze-delay=",
> > > > > > > setup_smt_snooze_delay);
> > > > > > > >
> > > > > > > >  #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 >= 10000)
> > > > > > > > +		cycle = div_u64(ns + 500, 1000) *
> tb_ticks_per_usec;
> > > > > > > > +	else
> > > > > > > > +		cycle = div_u64(ns * tb_ticks_per_usec, 1000);
> > > > > > > > +
> > > > > > > > +	if (!cycle)
> > > > > > > > +		return 0;
> > > > > > > > +
> > > > > > > > +	return ilog2(cycle);
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +static void do_show_pwrmgtcr0(void *val) {
> > > > > > > > +	u32 *value = val;
> > > > > > > > +
> > > > > > > > +	*value = mfspr(SPRN_PWRMGTCR0); }
> > > > > > > > +
> > > > > > > > +static ssize_t show_pw20_state(struct device *dev,
> > > > > > > > +				struct device_attribute *attr, char
> *buf) {
> > > > > > > > +	u32 value;
> > > > > > > > +	unsigned int cpu = dev->id;
> > > > > > > > +
> > > > > > > > +	smp_call_function_single(cpu, do_show_pwrmgtcr0, &value,
> > > > > > > > +1);
> > > > > > > > +
> > > > > > > > +	value &= PWRMGTCR0_PW20_WAIT;
> > > > > > > > +
> > > > > > > > +	return sprintf(buf, "%u\n", value ? 1 : 0); }
> > > > > > > > +
> > > > > > > > +static void do_store_pw20_state(void *val) {
> > > > > > > > +	u32 *value = val;
> > > > > > > > +	u32 pw20_state;
> > > > > > > > +
> > > > > > > > +	pw20_state = mfspr(SPRN_PWRMGTCR0);
> > > > > > > > +
> > > > > > > > +	if (*value)
> > > > > > > > +		pw20_state |= PWRMGTCR0_PW20_WAIT;
> > > > > > > > +	else
> > > > > > > > +		pw20_state &= ~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 = 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 = dev->id;
> > > > > > > > +
> > > > > > > > +	if (!pw20_wt) {
> > > > > > > > +		smp_call_function_single(cpu, do_show_pwrmgtcr0,
> > > > > > > > +&value,
> > > > > 1);
> > > > > > > > +		value = (value & PWRMGTCR0_PW20_ENT) >>
> > > > > > > > +					PWRMGTCR0_PW20_ENT_SHIFT;
> > > > > > > > +
> > > > > > > > +		tb_cycle = (1 << (MAX_BIT - value)) * 2;
> > > > > > >
> > > > > > > Is value = 0 and value = 1 legal? These will make tb_cycle =
> > > > > > > 0,
> > > > > > >
> > > > > > > > +		time = div_u64(tb_cycle * 1000, tb_ticks_per_usec)
> - 1;
> > > > > > >
> > > > > > > And time = -1;
> > > > > > >
> > > > > > Please look at the end of the function, :)
> > > > > >
> > > > > > "return sprintf(buf, "%llu\n", time > 0 ? time : 0);"
> > > > >
> > > > > I know you return 0 if value = 0/1, my question was that, is
> > > > > this correct as per specification?
> > > > >
> > > > > Ahh, also for "value" upto 7 you will return 0, no?
> > > > >
> > > > If value = 0, MAX_BIT - value = 63 tb_cycle = 0xffffffff_ffffffff,
> > > > tb_cycle * 1000 will overflow, but this situation is not possible.
> > > > Because if the "value = 0" means this feature will be "disable".
> > > > Now The default wait bit is 50(MAX_BIT - value, value = 13), the
> > > > PW20/Altivec Idle wait entry time is about 1ms, this time is very
> > > > long for wait idle time, and it's cannot be increased(means
> > > > (MAX_BIT
> > > > - value)
> > > cannot greater than 50).
> > >
> > > What you said is not obvious from code and so at least write a
> > > comment that value will be always >= 13 or value will never be less
> > > than < 8 and below calculation will not overflow. may be error out
> > > if value is less than 8.
> > >
> > The "value" less than 10, this will overflow.
> > There is not error, The code I knew it could not be less than 10,
> > that's why I use the following code. :)
> 
> I am sorry to persist but this is not about what you know, this is about
> how code is read and code does not say what you know, so add a comment at
> least and error out/warn when "value" is less than a certain number.
> 
Sorry for the late to response the mail. If it caused confusion, we can add a comment.

How about the following comment?
/*
 * If the "value" less than 10, this will overflow.
 * From benchmark test, the default wait bit will not be set less than 10bit.
 * Because 10 bit corresponds to the wait entry time is 439375573401999609(ns),
 * for wait-entry-idle time this value looks too long, and we cannot use those
 * "long" time as a default wait-entry time. So overflow could not have happened
 * and we use this calculation method to get wait-entry-idle time.
 */

> -Bharat
Bharat Bhushan Oct. 18, 2013, 5:49 p.m. UTC | #11
> -----Original Message-----
> From: Wang Dongsheng-B40534
> Sent: Friday, October 18, 2013 8:07 AM
> To: Wood Scott-B07421
> Cc: Bhushan Bharat-R65777; linuxppc-dev@lists.ozlabs.org
> Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and altivec
> idle
> 
> 
> 
> > -----Original Message-----
> > From: Wood Scott-B07421
> > Sent: Friday, October 18, 2013 12:52 AM
> > To: Wang Dongsheng-B40534
> > Cc: Bhushan Bharat-R65777; Wood Scott-B07421; linuxppc-
> > dev@lists.ozlabs.org
> > Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and
> > altivec idle
> >
> > On Thu, 2013-10-17 at 00:51 -0500, Wang Dongsheng-B40534 wrote:
> > >
> > > > -----Original Message-----
> > > > From: Bhushan Bharat-R65777
> > > > Sent: Thursday, October 17, 2013 11:20 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
> > > >
> > > >
> > > >
> > > > > -----Original Message-----
> > > > > From: Wang Dongsheng-B40534
> > > > > Sent: Thursday, October 17, 2013 8:16 AM
> > > > > To: Bhushan Bharat-R65777; 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
> > > > >
> > > > >
> > > > >
> > > > > > -----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
> > > > > >
> > > > > >
> > > > > >
> > > > > > > -----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;
> > > > > > > Wang
> > > > > > Dongsheng-B40534
> > > > > > > Subject: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20
> > > > > > > state and
> > > > > > altivec idle
> > > > > > >
> > > > > > > +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 = dev->id;
> > > > > > > +
> > > > > > > +	if (!pw20_wt) {
> > > > > > > +		smp_call_function_single(cpu, do_show_pwrmgtcr0, &value,
> > > > 1);
> > > > > > > +		value = (value & PWRMGTCR0_PW20_ENT) >>
> > > > > > > +					PWRMGTCR0_PW20_ENT_SHIFT;
> > > > > > > +
> > > > > > > +		tb_cycle = (1 << (MAX_BIT - value)) * 2;
> > > > > >
> > > > > > Is value = 0 and value = 1 legal? These will make tb_cycle =
> > > > > > 0,
> > > > > >
> > > > > > > +		time = div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1;
> > > > > >
> > > > > > And time = -1;
> > > > > >
> > > > > Please look at the end of the function, :)
> > > > >
> > > > > "return sprintf(buf, "%llu\n", time > 0 ? time : 0);"
> > > >
> > > > I know you return 0 if value = 0/1, my question was that, is this
> > > > correct as per specification?
> > > >
> > > > Ahh, also for "value" upto 7 you will return 0, no?
> > > >
> > > If value = 0, MAX_BIT - value = 63
> > > tb_cycle = 0xffffffff_ffffffff,
> >
> > Actually, tb_cycle will be undefined because you shifted a 32-bit
> > value
> > (1) by more than 31 bits.  s/1/1ULL/
> >

What Scott is saying is the left shift of "1" for more than 31 will be undefined.
Scott this will be sign-extended, right?

-Bharat

> Actually, we have been discussing this situation that could not have happened.
> See !pw20_wt branch, this branch is read default wait bit.
> The default wait bit is 50, the time is about 1ms.
> The default wait bit cannot less than 50, means the wait entry time cannot
> greater than 1ms.
> We have already begun benchmark test, and we got a preliminary results.
> 55, 56, 57bit looks good, but we need more benchmark to get the default bit.
> 
> 	if (!pw20_wt) {
> 		smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
> 		value = (value & PWRMGTCR0_PW20_ENT) >>
> 					PWRMGTCR0_PW20_ENT_SHIFT;
> 
> 		tb_cycle = (1 << (MAX_BIT - value)) * 2;
> 		time = div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1;
> 	} else {
> 		time = pw20_wt;
> 	}
> 
> If it caused confusion, we can add a comment. As I discuss with Bharat.
> 
> > > tb_cycle * 1000 will overflow, but this situation is not possible.
> > > Because if the "value = 0" means this feature will be "disable".
> > > Now The default wait bit is 50(MAX_BIT - value, value = 13), the
> > > PW20/Altivec Idle wait entry time is about 1ms, this time is very
> > > long for wait idle time, and it's cannot be increased(means (MAX_BIT
> > > -
> > > value) cannot greater than 50).
> >
> > Why can it not be increased?
> >
> see above, :)


> 
> -dongsheng
> > -Scott
> >
Scott Wood Oct. 18, 2013, 7:02 p.m. UTC | #12
On Fri, 2013-10-18 at 12:49 -0500, Bhushan Bharat-R65777 wrote:
> 
> > -----Original Message-----
> > From: Wang Dongsheng-B40534
> > Sent: Friday, October 18, 2013 8:07 AM
> > To: Wood Scott-B07421
> > Cc: Bhushan Bharat-R65777; linuxppc-dev@lists.ozlabs.org
> > Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and altivec
> > idle
> > 
> > 
> > 
> > > -----Original Message-----
> > > From: Wood Scott-B07421
> > > Sent: Friday, October 18, 2013 12:52 AM
> > > To: Wang Dongsheng-B40534
> > > Cc: Bhushan Bharat-R65777; Wood Scott-B07421; linuxppc-
> > > dev@lists.ozlabs.org
> > > Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and
> > > altivec idle
> > >
> > > On Thu, 2013-10-17 at 00:51 -0500, Wang Dongsheng-B40534 wrote:
> > > >
> > > > > -----Original Message-----
> > > > > From: Bhushan Bharat-R65777
> > > > > Sent: Thursday, October 17, 2013 11:20 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
> > > > >
> > > > >
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: Wang Dongsheng-B40534
> > > > > > Sent: Thursday, October 17, 2013 8:16 AM
> > > > > > To: Bhushan Bharat-R65777; 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
> > > > > >
> > > > > >
> > > > > >
> > > > > > > -----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
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > > -----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;
> > > > > > > > Wang
> > > > > > > Dongsheng-B40534
> > > > > > > > Subject: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20
> > > > > > > > state and
> > > > > > > altivec idle
> > > > > > > >
> > > > > > > > +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 = dev->id;
> > > > > > > > +
> > > > > > > > +	if (!pw20_wt) {
> > > > > > > > +		smp_call_function_single(cpu, do_show_pwrmgtcr0, &value,
> > > > > 1);
> > > > > > > > +		value = (value & PWRMGTCR0_PW20_ENT) >>
> > > > > > > > +					PWRMGTCR0_PW20_ENT_SHIFT;
> > > > > > > > +
> > > > > > > > +		tb_cycle = (1 << (MAX_BIT - value)) * 2;
> > > > > > >
> > > > > > > Is value = 0 and value = 1 legal? These will make tb_cycle =
> > > > > > > 0,
> > > > > > >
> > > > > > > > +		time = div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1;
> > > > > > >
> > > > > > > And time = -1;
> > > > > > >
> > > > > > Please look at the end of the function, :)
> > > > > >
> > > > > > "return sprintf(buf, "%llu\n", time > 0 ? time : 0);"
> > > > >
> > > > > I know you return 0 if value = 0/1, my question was that, is this
> > > > > correct as per specification?
> > > > >
> > > > > Ahh, also for "value" upto 7 you will return 0, no?
> > > > >
> > > > If value = 0, MAX_BIT - value = 63
> > > > tb_cycle = 0xffffffff_ffffffff,
> > >
> > > Actually, tb_cycle will be undefined because you shifted a 32-bit
> > > value
> > > (1) by more than 31 bits.  s/1/1ULL/
> > >
> 
> What Scott is saying is the left shift of "1" for more than 31 will be undefined.
> Scott this will be sign-extended, right?

It's undefined in C.  I don't know what GCC on PPC specifically will do.

-Scott
Scott Wood Oct. 18, 2013, 7:21 p.m. UTC | #13
On Thu, 2013-10-17 at 22:02 -0500, Wang Dongsheng-B40534 wrote:
> 
> > -----Original Message-----
> > From: Bhushan Bharat-R65777
> > Sent: Thursday, October 17, 2013 2:46 PM
> > 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
> > 
> > 
> > 
> > > > > -----Original Message-----
> > > > > From: Wang Dongsheng-B40534
> > > > > Sent: Thursday, October 17, 2013 11:22 AM
> > > > > To: Bhushan Bharat-R65777; 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
> > > > >
> > > > >
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: Bhushan Bharat-R65777
> > > > > > Sent: Thursday, October 17, 2013 11:20 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
> > > > > >
> > > > > >
> > > > > >
> > > > > > > -----Original Message-----
> > > > > > > From: Wang Dongsheng-B40534
> > > > > > > Sent: Thursday, October 17, 2013 8:16 AM
> > > > > > > To: Bhushan Bharat-R65777; 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
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > > -----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
> > > > > > > >
> > > > > > > >
> > > > > > > >
> > > > > > > > > -----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;
> > > > > > > > > Wang
> > > > > > > > Dongsheng-B40534
> > > > > > > > > Subject: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20
> > > > > > > > > state and
> > > > > > > > altivec idle
> > > > > > > > >
> > > > > > > > > From: Wang Dongsheng <dongsheng.wang@freescale.com>
> > > > > > > > >
> > > > > > > > > Add a sys interface to enable/diable pw20 state or altivec
> > > > > > > > > idle, and
> > > > > > > > control the
> > > > > > > > > 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
> > > > > > > > > <dongsheng.wang@freescale.com>
> > > > > > > > > ---
> > > > > > > > > *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.c
> > > > > > > > index
> > > > > > > > > 27a90b9..10d1128 100644
> > > > > > > > > --- a/arch/powerpc/kernel/sysfs.c
> > > > > > > > > +++ b/arch/powerpc/kernel/sysfs.c
> > > > > > > > > @@ -85,6 +85,284 @@ __setup("smt-snooze-delay=",
> > > > > > > > setup_smt_snooze_delay);
> > > > > > > > >
> > > > > > > > >  #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 >= 10000)
> > > > > > > > > +		cycle = div_u64(ns + 500, 1000) *
> > tb_ticks_per_usec;
> > > > > > > > > +	else
> > > > > > > > > +		cycle = div_u64(ns * tb_ticks_per_usec, 1000);
> > > > > > > > > +
> > > > > > > > > +	if (!cycle)
> > > > > > > > > +		return 0;
> > > > > > > > > +
> > > > > > > > > +	return ilog2(cycle);
> > > > > > > > > +}
> > > > > > > > > +
> > > > > > > > > +static void do_show_pwrmgtcr0(void *val) {
> > > > > > > > > +	u32 *value = val;
> > > > > > > > > +
> > > > > > > > > +	*value = mfspr(SPRN_PWRMGTCR0); }
> > > > > > > > > +
> > > > > > > > > +static ssize_t show_pw20_state(struct device *dev,
> > > > > > > > > +				struct device_attribute *attr, char
> > *buf) {
> > > > > > > > > +	u32 value;
> > > > > > > > > +	unsigned int cpu = dev->id;
> > > > > > > > > +
> > > > > > > > > +	smp_call_function_single(cpu, do_show_pwrmgtcr0, &value,
> > > > > > > > > +1);
> > > > > > > > > +
> > > > > > > > > +	value &= PWRMGTCR0_PW20_WAIT;
> > > > > > > > > +
> > > > > > > > > +	return sprintf(buf, "%u\n", value ? 1 : 0); }
> > > > > > > > > +
> > > > > > > > > +static void do_store_pw20_state(void *val) {
> > > > > > > > > +	u32 *value = val;
> > > > > > > > > +	u32 pw20_state;
> > > > > > > > > +
> > > > > > > > > +	pw20_state = mfspr(SPRN_PWRMGTCR0);
> > > > > > > > > +
> > > > > > > > > +	if (*value)
> > > > > > > > > +		pw20_state |= PWRMGTCR0_PW20_WAIT;
> > > > > > > > > +	else
> > > > > > > > > +		pw20_state &= ~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 = 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 = dev->id;
> > > > > > > > > +
> > > > > > > > > +	if (!pw20_wt) {
> > > > > > > > > +		smp_call_function_single(cpu, do_show_pwrmgtcr0,
> > > > > > > > > +&value,
> > > > > > 1);
> > > > > > > > > +		value = (value & PWRMGTCR0_PW20_ENT) >>
> > > > > > > > > +					PWRMGTCR0_PW20_ENT_SHIFT;
> > > > > > > > > +
> > > > > > > > > +		tb_cycle = (1 << (MAX_BIT - value)) * 2;
> > > > > > > >
> > > > > > > > Is value = 0 and value = 1 legal? These will make tb_cycle =
> > > > > > > > 0,
> > > > > > > >
> > > > > > > > > +		time = div_u64(tb_cycle * 1000, tb_ticks_per_usec)
> > - 1;
> > > > > > > >
> > > > > > > > And time = -1;
> > > > > > > >
> > > > > > > Please look at the end of the function, :)
> > > > > > >
> > > > > > > "return sprintf(buf, "%llu\n", time > 0 ? time : 0);"
> > > > > >
> > > > > > I know you return 0 if value = 0/1, my question was that, is
> > > > > > this correct as per specification?
> > > > > >
> > > > > > Ahh, also for "value" upto 7 you will return 0, no?
> > > > > >
> > > > > If value = 0, MAX_BIT - value = 63 tb_cycle = 0xffffffff_ffffffff,
> > > > > tb_cycle * 1000 will overflow, but this situation is not possible.
> > > > > Because if the "value = 0" means this feature will be "disable".
> > > > > Now The default wait bit is 50(MAX_BIT - value, value = 13), the
> > > > > PW20/Altivec Idle wait entry time is about 1ms, this time is very
> > > > > long for wait idle time, and it's cannot be increased(means
> > > > > (MAX_BIT
> > > > > - value)
> > > > cannot greater than 50).
> > > >
> > > > What you said is not obvious from code and so at least write a
> > > > comment that value will be always >= 13 or value will never be less
> > > > than < 8 and below calculation will not overflow. may be error out
> > > > if value is less than 8.
> > > >
> > > The "value" less than 10, this will overflow.
> > > There is not error, The code I knew it could not be less than 10,
> > > that's why I use the following code. :)
> > 
> > I am sorry to persist but this is not about what you know, this is about
> > how code is read and code does not say what you know, so add a comment at
> > least and error out/warn when "value" is less than a certain number.
> > 
> Sorry for the late to response the mail. If it caused confusion, we can add a comment.
> 
> How about the following comment?
> /*
>  * If the "value" less than 10, this will overflow.
>  * From benchmark test, the default wait bit will not be set less than 10bit.
>  * Because 10 bit corresponds to the wait entry time is 439375573401999609(ns),
>  * for wait-entry-idle time this value looks too long, and we cannot use those
>  * "long" time as a default wait-entry time. So overflow could not have happened
>  * and we use this calculation method to get wait-entry-idle time.
>  */

If there's to be a limit on the times we accept, make it explicit.
Check for it before doing any conversions, and return an error if
userspace tries to set it.

-Scott
Scott Wood Oct. 18, 2013, 7:23 p.m. UTC | #14
On Thu, 2013-10-17 at 21:36 -0500, Wang Dongsheng-B40534 wrote:
> 
> > -----Original Message-----
> > From: Wood Scott-B07421
> > Sent: Friday, October 18, 2013 12:52 AM
> > To: Wang Dongsheng-B40534
> > Cc: Bhushan Bharat-R65777; Wood Scott-B07421; linuxppc-
> > dev@lists.ozlabs.org
> > Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and
> > altivec idle
> > 
> > On Thu, 2013-10-17 at 00:51 -0500, Wang Dongsheng-B40534 wrote:
> > >
> > > > -----Original Message-----
> > > > From: Bhushan Bharat-R65777
> > > > Sent: Thursday, October 17, 2013 11:20 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
> > > >
> > > >
> > > >
> > > > > -----Original Message-----
> > > > > From: Wang Dongsheng-B40534
> > > > > Sent: Thursday, October 17, 2013 8:16 AM
> > > > > To: Bhushan Bharat-R65777; 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
> > > > >
> > > > >
> > > > >
> > > > > > -----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
> > > > > >
> > > > > >
> > > > > >
> > > > > > > -----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; Wang
> > > > > > Dongsheng-B40534
> > > > > > > Subject: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state
> > > > > > > and
> > > > > > altivec idle
> > > > > > >
> > > > > > > +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 = dev->id;
> > > > > > > +
> > > > > > > +	if (!pw20_wt) {
> > > > > > > +		smp_call_function_single(cpu, do_show_pwrmgtcr0, &value,
> > > > 1);
> > > > > > > +		value = (value & PWRMGTCR0_PW20_ENT) >>
> > > > > > > +					PWRMGTCR0_PW20_ENT_SHIFT;
> > > > > > > +
> > > > > > > +		tb_cycle = (1 << (MAX_BIT - value)) * 2;
> > > > > >
> > > > > > Is value = 0 and value = 1 legal? These will make tb_cycle = 0,
> > > > > >
> > > > > > > +		time = div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1;
> > > > > >
> > > > > > And time = -1;
> > > > > >
> > > > > Please look at the end of the function, :)
> > > > >
> > > > > "return sprintf(buf, "%llu\n", time > 0 ? time : 0);"
> > > >
> > > > I know you return 0 if value = 0/1, my question was that, is this
> > > > correct as per specification?
> > > >
> > > > Ahh, also for "value" upto 7 you will return 0, no?
> > > >
> > > If value = 0, MAX_BIT - value = 63
> > > tb_cycle = 0xffffffff_ffffffff,
> > 
> > Actually, tb_cycle will be undefined because you shifted a 32-bit value
> > (1) by more than 31 bits.  s/1/1ULL/
> > 
> Actually, we have been discussing this situation that could not have happened.
> See !pw20_wt branch, this branch is read default wait bit.
> The default wait bit is 50, the time is about 1ms.
> The default wait bit cannot less than 50, means the wait entry time cannot greater than 1ms.
> We have already begun benchmark test, and we got a preliminary results.
> 55, 56, 57bit looks good, but we need more benchmark to get the default bit.

What does the default have to do with it?  The user could have set a
different value, and then read it back.

Plus, how much time corresponds to bit 50 depends on the actual timebase
frequency which could vary.

-Scott
Bharat Bhushan Oct. 18, 2013, 7:24 p.m. UTC | #15
> -----Original Message-----
> From: Wood Scott-B07421
> Sent: Saturday, October 19, 2013 12:52 AM
> To: Wang Dongsheng-B40534
> Cc: Bhushan Bharat-R65777; Wood Scott-B07421; linuxppc-dev@lists.ozlabs.org
> Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and altivec
> idle
> 
> On Thu, 2013-10-17 at 22:02 -0500, Wang Dongsheng-B40534 wrote:
> >
> > > -----Original Message-----
> > > From: Bhushan Bharat-R65777
> > > Sent: Thursday, October 17, 2013 2:46 PM
> > > 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
> > >
> > >
> > >
> > > > > > -----Original Message-----
> > > > > > From: Wang Dongsheng-B40534
> > > > > > Sent: Thursday, October 17, 2013 11:22 AM
> > > > > > To: Bhushan Bharat-R65777; 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
> > > > > >
> > > > > >
> > > > > >
> > > > > > > -----Original Message-----
> > > > > > > From: Bhushan Bharat-R65777
> > > > > > > Sent: Thursday, October 17, 2013 11:20 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
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > > -----Original Message-----
> > > > > > > > From: Wang Dongsheng-B40534
> > > > > > > > Sent: Thursday, October 17, 2013 8:16 AM
> > > > > > > > To: Bhushan Bharat-R65777; 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
> > > > > > > >
> > > > > > > >
> > > > > > > >
> > > > > > > > > -----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
> > > > > > > > >
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > > -----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; Wang
> > > > > > > > > Dongsheng-B40534
> > > > > > > > > > Subject: [PATCH v5 4/4] powerpc/85xx: add sysfs for
> > > > > > > > > > pw20 state and
> > > > > > > > > altivec idle
> > > > > > > > > >
> > > > > > > > > > From: Wang Dongsheng <dongsheng.wang@freescale.com>
> > > > > > > > > >
> > > > > > > > > > Add a sys interface to enable/diable pw20 state or
> > > > > > > > > > altivec idle, and
> > > > > > > > > control the
> > > > > > > > > > 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
> > > > > > > > > > <dongsheng.wang@freescale.com>
> > > > > > > > > > ---
> > > > > > > > > > *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.c
> > > > > > > > > index
> > > > > > > > > > 27a90b9..10d1128 100644
> > > > > > > > > > --- a/arch/powerpc/kernel/sysfs.c
> > > > > > > > > > +++ b/arch/powerpc/kernel/sysfs.c
> > > > > > > > > > @@ -85,6 +85,284 @@ __setup("smt-snooze-delay=",
> > > > > > > > > setup_smt_snooze_delay);
> > > > > > > > > >
> > > > > > > > > >  #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 >= 10000)
> > > > > > > > > > +		cycle = div_u64(ns + 500, 1000) *
> > > tb_ticks_per_usec;
> > > > > > > > > > +	else
> > > > > > > > > > +		cycle = div_u64(ns * tb_ticks_per_usec, 1000);
> > > > > > > > > > +
> > > > > > > > > > +	if (!cycle)
> > > > > > > > > > +		return 0;
> > > > > > > > > > +
> > > > > > > > > > +	return ilog2(cycle); }
> > > > > > > > > > +
> > > > > > > > > > +static void do_show_pwrmgtcr0(void *val) {
> > > > > > > > > > +	u32 *value = val;
> > > > > > > > > > +
> > > > > > > > > > +	*value = mfspr(SPRN_PWRMGTCR0); }
> > > > > > > > > > +
> > > > > > > > > > +static ssize_t show_pw20_state(struct device *dev,
> > > > > > > > > > +				struct device_attribute *attr, char
> > > *buf) {
> > > > > > > > > > +	u32 value;
> > > > > > > > > > +	unsigned int cpu = dev->id;
> > > > > > > > > > +
> > > > > > > > > > +	smp_call_function_single(cpu, do_show_pwrmgtcr0,
> > > > > > > > > > +&value, 1);
> > > > > > > > > > +
> > > > > > > > > > +	value &= PWRMGTCR0_PW20_WAIT;
> > > > > > > > > > +
> > > > > > > > > > +	return sprintf(buf, "%u\n", value ? 1 : 0); }
> > > > > > > > > > +
> > > > > > > > > > +static void do_store_pw20_state(void *val) {
> > > > > > > > > > +	u32 *value = val;
> > > > > > > > > > +	u32 pw20_state;
> > > > > > > > > > +
> > > > > > > > > > +	pw20_state = mfspr(SPRN_PWRMGTCR0);
> > > > > > > > > > +
> > > > > > > > > > +	if (*value)
> > > > > > > > > > +		pw20_state |= PWRMGTCR0_PW20_WAIT;
> > > > > > > > > > +	else
> > > > > > > > > > +		pw20_state &= ~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 = 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 = dev->id;
> > > > > > > > > > +
> > > > > > > > > > +	if (!pw20_wt) {
> > > > > > > > > > +		smp_call_function_single(cpu, do_show_pwrmgtcr0,
> > > > > > > > > > +&value,
> > > > > > > 1);
> > > > > > > > > > +		value = (value & PWRMGTCR0_PW20_ENT) >>
> > > > > > > > > > +					PWRMGTCR0_PW20_ENT_SHIFT;
> > > > > > > > > > +
> > > > > > > > > > +		tb_cycle = (1 << (MAX_BIT - value)) * 2;
> > > > > > > > >
> > > > > > > > > Is value = 0 and value = 1 legal? These will make
> > > > > > > > > tb_cycle = 0,
> > > > > > > > >
> > > > > > > > > > +		time = div_u64(tb_cycle * 1000, tb_ticks_per_usec)
> > > - 1;
> > > > > > > > >
> > > > > > > > > And time = -1;
> > > > > > > > >
> > > > > > > > Please look at the end of the function, :)
> > > > > > > >
> > > > > > > > "return sprintf(buf, "%llu\n", time > 0 ? time : 0);"
> > > > > > >
> > > > > > > I know you return 0 if value = 0/1, my question was that, is
> > > > > > > this correct as per specification?
> > > > > > >
> > > > > > > Ahh, also for "value" upto 7 you will return 0, no?
> > > > > > >
> > > > > > If value = 0, MAX_BIT - value = 63 tb_cycle =
> > > > > > 0xffffffff_ffffffff, tb_cycle * 1000 will overflow, but this situation
> is not possible.
> > > > > > Because if the "value = 0" means this feature will be "disable".
> > > > > > Now The default wait bit is 50(MAX_BIT - value, value = 13),
> > > > > > the PW20/Altivec Idle wait entry time is about 1ms, this time
> > > > > > is very long for wait idle time, and it's cannot be
> > > > > > increased(means (MAX_BIT
> > > > > > - value)
> > > > > cannot greater than 50).
> > > > >
> > > > > What you said is not obvious from code and so at least write a
> > > > > comment that value will be always >= 13 or value will never be
> > > > > less than < 8 and below calculation will not overflow. may be
> > > > > error out if value is less than 8.
> > > > >
> > > > The "value" less than 10, this will overflow.
> > > > There is not error, The code I knew it could not be less than 10,
> > > > that's why I use the following code. :)
> > >
> > > I am sorry to persist but this is not about what you know, this is
> > > about how code is read and code does not say what you know, so add a
> > > comment at least and error out/warn when "value" is less than a certain
> number.
> > >
> > Sorry for the late to response the mail. If it caused confusion, we can add a
> comment.
> >
> > How about the following comment?
> > /*
> >  * If the "value" less than 10, this will overflow.
> >  * From benchmark test, the default wait bit will not be set less than 10bit.
> >  * Because 10 bit corresponds to the wait entry time is
> > 439375573401999609(ns),
> >  * for wait-entry-idle time this value looks too long, and we cannot
> > use those
> >  * "long" time as a default wait-entry time. So overflow could not
> > have happened
> >  * and we use this calculation method to get wait-entry-idle time.
> >  */
> 
> If there's to be a limit on the times we accept, make it explicit.
> Check for it before doing any conversions, and return an error if userspace
> tries to set it.

I agree. And accordingly comment will change and location of comment in code will also change :)

-Bharat

> 
> -Scott
>
Wang Dongsheng-B40534 Oct. 21, 2013, 3:10 a.m. UTC | #16
> -----Original Message-----
> From: Wood Scott-B07421
> Sent: Saturday, October 19, 2013 3:22 AM
> To: Wang Dongsheng-B40534
> Cc: Bhushan Bharat-R65777; Wood Scott-B07421; linuxppc-
> dev@lists.ozlabs.org
> Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and
> altivec idle
> 
> On Thu, 2013-10-17 at 22:02 -0500, Wang Dongsheng-B40534 wrote:
> >
> > > -----Original Message-----
> > > From: Bhushan Bharat-R65777
> > > Sent: Thursday, October 17, 2013 2:46 PM
> > > 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
> > >
> > >
> > >
> > > > > > -----Original Message-----
> > > > > > From: Wang Dongsheng-B40534
> > > > > > Sent: Thursday, October 17, 2013 11:22 AM
> > > > > > To: Bhushan Bharat-R65777; 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
> > > > > >
> > > > > >
> > > > > >
> > > > > > > -----Original Message-----
> > > > > > > From: Bhushan Bharat-R65777
> > > > > > > Sent: Thursday, October 17, 2013 11:20 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
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > > -----Original Message-----
> > > > > > > > From: Wang Dongsheng-B40534
> > > > > > > > Sent: Thursday, October 17, 2013 8:16 AM
> > > > > > > > To: Bhushan Bharat-R65777; 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
> > > > > > > >
> > > > > > > >
> > > > > > > >
> > > > > > > > > -----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
> > > > > > > > >
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > > -----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; Wang
> > > > > > > > > Dongsheng-B40534
> > > > > > > > > > Subject: [PATCH v5 4/4] powerpc/85xx: add sysfs for
> > > > > > > > > > pw20 state and
> > > > > > > > > altivec idle
> > > > > > > > > >
> > > > > > > > > > From: Wang Dongsheng <dongsheng.wang@freescale.com>
> > > > > > > > > >
> > > > > > > > > > Add a sys interface to enable/diable pw20 state or
> > > > > > > > > > altivec idle, and
> > > > > > > > > control the
> > > > > > > > > > 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
> > > > > > > > > > <dongsheng.wang@freescale.com>
> > > > > > > > > > ---
> > > > > > > > > > *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.c
> > > > > > > > > index
> > > > > > > > > > 27a90b9..10d1128 100644
> > > > > > > > > > --- a/arch/powerpc/kernel/sysfs.c
> > > > > > > > > > +++ b/arch/powerpc/kernel/sysfs.c
> > > > > > > > > > @@ -85,6 +85,284 @@ __setup("smt-snooze-delay=",
> > > > > > > > > setup_smt_snooze_delay);
> > > > > > > > > >
> > > > > > > > > >  #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 >= 10000)
> > > > > > > > > > +		cycle = div_u64(ns + 500, 1000) *
> > > tb_ticks_per_usec;
> > > > > > > > > > +	else
> > > > > > > > > > +		cycle = div_u64(ns * tb_ticks_per_usec,
> 1000);
> > > > > > > > > > +
> > > > > > > > > > +	if (!cycle)
> > > > > > > > > > +		return 0;
> > > > > > > > > > +
> > > > > > > > > > +	return ilog2(cycle); }
> > > > > > > > > > +
> > > > > > > > > > +static void do_show_pwrmgtcr0(void *val) {
> > > > > > > > > > +	u32 *value = val;
> > > > > > > > > > +
> > > > > > > > > > +	*value = mfspr(SPRN_PWRMGTCR0); }
> > > > > > > > > > +
> > > > > > > > > > +static ssize_t show_pw20_state(struct device *dev,
> > > > > > > > > > +				struct device_attribute *attr,
> char
> > > *buf) {
> > > > > > > > > > +	u32 value;
> > > > > > > > > > +	unsigned int cpu = dev->id;
> > > > > > > > > > +
> > > > > > > > > > +	smp_call_function_single(cpu, do_show_pwrmgtcr0,
> > > > > > > > > > +&value, 1);
> > > > > > > > > > +
> > > > > > > > > > +	value &= PWRMGTCR0_PW20_WAIT;
> > > > > > > > > > +
> > > > > > > > > > +	return sprintf(buf, "%u\n", value ? 1 : 0); }
> > > > > > > > > > +
> > > > > > > > > > +static void do_store_pw20_state(void *val) {
> > > > > > > > > > +	u32 *value = val;
> > > > > > > > > > +	u32 pw20_state;
> > > > > > > > > > +
> > > > > > > > > > +	pw20_state = mfspr(SPRN_PWRMGTCR0);
> > > > > > > > > > +
> > > > > > > > > > +	if (*value)
> > > > > > > > > > +		pw20_state |= PWRMGTCR0_PW20_WAIT;
> > > > > > > > > > +	else
> > > > > > > > > > +		pw20_state &= ~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 = 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 = dev->id;
> > > > > > > > > > +
> > > > > > > > > > +	if (!pw20_wt) {
> > > > > > > > > > +		smp_call_function_single(cpu,
> do_show_pwrmgtcr0,
> > > > > > > > > > +&value,
> > > > > > > 1);
> > > > > > > > > > +		value = (value & PWRMGTCR0_PW20_ENT) >>
> > > > > > > > > > +					PWRMGTCR0_PW20_ENT_SHIFT;
> > > > > > > > > > +
> > > > > > > > > > +		tb_cycle = (1 << (MAX_BIT - value)) * 2;
> > > > > > > > >
> > > > > > > > > Is value = 0 and value = 1 legal? These will make
> > > > > > > > > tb_cycle = 0,
> > > > > > > > >
> > > > > > > > > > +		time = div_u64(tb_cycle * 1000,
> tb_ticks_per_usec)
> > > - 1;
> > > > > > > > >
> > > > > > > > > And time = -1;
> > > > > > > > >
> > > > > > > > Please look at the end of the function, :)
> > > > > > > >
> > > > > > > > "return sprintf(buf, "%llu\n", time > 0 ? time : 0);"
> > > > > > >
> > > > > > > I know you return 0 if value = 0/1, my question was that, is
> > > > > > > this correct as per specification?
> > > > > > >
> > > > > > > Ahh, also for "value" upto 7 you will return 0, no?
> > > > > > >
> > > > > > If value = 0, MAX_BIT - value = 63 tb_cycle =
> > > > > > 0xffffffff_ffffffff, tb_cycle * 1000 will overflow, but this
> situation is not possible.
> > > > > > Because if the "value = 0" means this feature will be "disable".
> > > > > > Now The default wait bit is 50(MAX_BIT - value, value = 13),
> > > > > > the PW20/Altivec Idle wait entry time is about 1ms, this time
> > > > > > is very long for wait idle time, and it's cannot be
> > > > > > increased(means (MAX_BIT
> > > > > > - value)
> > > > > cannot greater than 50).
> > > > >
> > > > > What you said is not obvious from code and so at least write a
> > > > > comment that value will be always >= 13 or value will never be
> > > > > less than < 8 and below calculation will not overflow. may be
> > > > > error out if value is less than 8.
> > > > >
> > > > The "value" less than 10, this will overflow.
> > > > There is not error, The code I knew it could not be less than 10,
> > > > that's why I use the following code. :)
> > >
> > > I am sorry to persist but this is not about what you know, this is
> > > about how code is read and code does not say what you know, so add a
> > > comment at least and error out/warn when "value" is less than a
> certain number.
> > >
> > Sorry for the late to response the mail. If it caused confusion, we can
> add a comment.
> >
> > How about the following comment?
> > /*
> >  * If the "value" less than 10, this will overflow.
> >  * From benchmark test, the default wait bit will not be set less than
> 10bit.
> >  * Because 10 bit corresponds to the wait entry time is
> > 439375573401999609(ns),
> >  * for wait-entry-idle time this value looks too long, and we cannot
> > use those
> >  * "long" time as a default wait-entry time. So overflow could not
> > have happened
> >  * and we use this calculation method to get wait-entry-idle time.
> >  */
> 
> If there's to be a limit on the times we accept, make it explicit.
> Check for it before doing any conversions, and return an error if
> userspace tries to set it.
> 
The branch only use to read default wait-entry-time.
We have no limit the user's input, and we can't restrict. Once the user set the wait-entry-time,
the code will do another branch.

> -Scott
>
Wang Dongsheng-B40534 Oct. 21, 2013, 3:27 a.m. UTC | #17
> -----Original Message-----
> From: Wood Scott-B07421
> Sent: Saturday, October 19, 2013 3:23 AM
> To: Wang Dongsheng-B40534
> Cc: Wood Scott-B07421; Bhushan Bharat-R65777; linuxppc-
> dev@lists.ozlabs.org
> Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and
> altivec idle
> 
> On Thu, 2013-10-17 at 21:36 -0500, Wang Dongsheng-B40534 wrote:
> >
> > > -----Original Message-----
> > > From: Wood Scott-B07421
> > > Sent: Friday, October 18, 2013 12:52 AM
> > > To: Wang Dongsheng-B40534
> > > Cc: Bhushan Bharat-R65777; Wood Scott-B07421; linuxppc-
> > > dev@lists.ozlabs.org
> > > Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state
> > > and altivec idle
> > >
> > > On Thu, 2013-10-17 at 00:51 -0500, Wang Dongsheng-B40534 wrote:
> > > >
> > > > > -----Original Message-----
> > > > > From: Bhushan Bharat-R65777
> > > > > Sent: Thursday, October 17, 2013 11:20 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
> > > > >
> > > > >
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: Wang Dongsheng-B40534
> > > > > > Sent: Thursday, October 17, 2013 8:16 AM
> > > > > > To: Bhushan Bharat-R65777; 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
> > > > > >
> > > > > >
> > > > > >
> > > > > > > -----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
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > > -----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;
> > > > > > > > Wang
> > > > > > > Dongsheng-B40534
> > > > > > > > Subject: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20
> > > > > > > > state and
> > > > > > > altivec idle
> > > > > > > >
> > > > > > > > +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 = dev->id;
> > > > > > > > +
> > > > > > > > +	if (!pw20_wt) {
> > > > > > > > +		smp_call_function_single(cpu, do_show_pwrmgtcr0,
> > > > > > > > +&value,
> > > > > 1);
> > > > > > > > +		value = (value & PWRMGTCR0_PW20_ENT) >>
> > > > > > > > +					PWRMGTCR0_PW20_ENT_SHIFT;
> > > > > > > > +
> > > > > > > > +		tb_cycle = (1 << (MAX_BIT - value)) * 2;
> > > > > > >
> > > > > > > Is value = 0 and value = 1 legal? These will make tb_cycle =
> > > > > > > 0,
> > > > > > >
> > > > > > > > +		time = div_u64(tb_cycle * 1000, tb_ticks_per_usec)
> - 1;
> > > > > > >
> > > > > > > And time = -1;
> > > > > > >
> > > > > > Please look at the end of the function, :)
> > > > > >
> > > > > > "return sprintf(buf, "%llu\n", time > 0 ? time : 0);"
> > > > >
> > > > > I know you return 0 if value = 0/1, my question was that, is
> > > > > this correct as per specification?
> > > > >
> > > > > Ahh, also for "value" upto 7 you will return 0, no?
> > > > >
> > > > If value = 0, MAX_BIT - value = 63 tb_cycle = 0xffffffff_ffffffff,
> > >
> > > Actually, tb_cycle will be undefined because you shifted a 32-bit
> > > value
> > > (1) by more than 31 bits.  s/1/1ULL/
> > >
> > Actually, we have been discussing this situation that could not have
> happened.
> > See !pw20_wt branch, this branch is read default wait bit.
> > The default wait bit is 50, the time is about 1ms.
> > The default wait bit cannot less than 50, means the wait entry time
> cannot greater than 1ms.
> > We have already begun benchmark test, and we got a preliminary results.
> > 55, 56, 57bit looks good, but we need more benchmark to get the default
> bit.
> 
> What does the default have to do with it?  The user could have set a
> different value, and then read it back.
> 
> Plus, how much time corresponds to bit 50 depends on the actual timebase
> frequency which could vary.
> 
	if (!pw20_wt) {
		smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
		value = (value & PWRMGTCR0_PW20_ENT) >>
					PWRMGTCR0_PW20_ENT_SHIFT;

		tb_cycle = (1 << (MAX_BIT - value)) * 2;
		time = tb_cycle * (1000 / tb_ticks_per_usec) - 1;
	} else {
		time = pw20_wt;
	}

As we have discussed before we need a variable to save To save the users to set wait-entry-time value.

See the code, if user have set a value, and the value will be set in pw20_wt. 
When the user read it back, the code will do "time = pw20_wt" branch.

When the user not set the wait-entry-time value and read this sys interface, the code will do the following branch.
		smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
		value = (value & PWRMGTCR0_PW20_ENT) >>
					PWRMGTCR0_PW20_ENT_SHIFT;

		tb_cycle = (1 << (MAX_BIT - value)) * 2;
		time = tb_cycle * (1000 / tb_ticks_per_usec) - 1;

-dongsheng

> -Scott
>
Wang Dongsheng-B40534 Nov. 4, 2013, 4:04 a.m. UTC | #18
> -----Original Message-----
> From: Wang Dongsheng-B40534
> Sent: Monday, October 21, 2013 11:11 AM
> To: Wood Scott-B07421
> Cc: Bhushan Bharat-R65777; linuxppc-dev@lists.ozlabs.org
> Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and
> altivec idle
> 
> 
> 
> > -----Original Message-----
> > From: Wood Scott-B07421
> > Sent: Saturday, October 19, 2013 3:22 AM
> > To: Wang Dongsheng-B40534
> > Cc: Bhushan Bharat-R65777; Wood Scott-B07421; linuxppc-
> > dev@lists.ozlabs.org
> > Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and
> > altivec idle
> >
> > On Thu, 2013-10-17 at 22:02 -0500, Wang Dongsheng-B40534 wrote:
> > >
> > > > -----Original Message-----
> > > > From: Bhushan Bharat-R65777
> > > > Sent: Thursday, October 17, 2013 2:46 PM
> > > > 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
> > > >
> > > >
> > > >
> > > > > > > -----Original Message-----
> > > > > > > From: Wang Dongsheng-B40534
> > > > > > > Sent: Thursday, October 17, 2013 11:22 AM
> > > > > > > To: Bhushan Bharat-R65777; 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
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > > -----Original Message-----
> > > > > > > > From: Bhushan Bharat-R65777
> > > > > > > > Sent: Thursday, October 17, 2013 11:20 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
> > > > > > > >
> > > > > > > >
> > > > > > > >
> > > > > > > > > -----Original Message-----
> > > > > > > > > From: Wang Dongsheng-B40534
> > > > > > > > > Sent: Thursday, October 17, 2013 8:16 AM
> > > > > > > > > To: Bhushan Bharat-R65777; 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
> > > > > > > > >
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > > -----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
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > > -----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; Wang
> > > > > > > > > > Dongsheng-B40534
> > > > > > > > > > > Subject: [PATCH v5 4/4] powerpc/85xx: add sysfs for
> > > > > > > > > > > pw20 state and
> > > > > > > > > > altivec idle
> > > > > > > > > > >
> > > > > > > > > > > From: Wang Dongsheng <dongsheng.wang@freescale.com>
> > > > > > > > > > >
> > > > > > > > > > > Add a sys interface to enable/diable pw20 state or
> > > > > > > > > > > altivec idle, and
> > > > > > > > > > control the
> > > > > > > > > > > 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
> > > > > > > > > > > <dongsheng.wang@freescale.com>
> > > > > > > > > > > ---
> > > > > > > > > > > *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.c
> > > > > > > > > > index
> > > > > > > > > > > 27a90b9..10d1128 100644
> > > > > > > > > > > --- a/arch/powerpc/kernel/sysfs.c
> > > > > > > > > > > +++ b/arch/powerpc/kernel/sysfs.c
> > > > > > > > > > > @@ -85,6 +85,284 @@ __setup("smt-snooze-delay=",
> > > > > > > > > > setup_smt_snooze_delay);
> > > > > > > > > > >
> > > > > > > > > > >  #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 >= 10000)
> > > > > > > > > > > +		cycle = div_u64(ns + 500, 1000) *
> > > > tb_ticks_per_usec;
> > > > > > > > > > > +	else
> > > > > > > > > > > +		cycle = div_u64(ns * tb_ticks_per_usec,
> > 1000);
> > > > > > > > > > > +
> > > > > > > > > > > +	if (!cycle)
> > > > > > > > > > > +		return 0;
> > > > > > > > > > > +
> > > > > > > > > > > +	return ilog2(cycle); }
> > > > > > > > > > > +
> > > > > > > > > > > +static void do_show_pwrmgtcr0(void *val) {
> > > > > > > > > > > +	u32 *value = val;
> > > > > > > > > > > +
> > > > > > > > > > > +	*value = mfspr(SPRN_PWRMGTCR0); }
> > > > > > > > > > > +
> > > > > > > > > > > +static ssize_t show_pw20_state(struct device *dev,
> > > > > > > > > > > +				struct device_attribute *attr,
> > char
> > > > *buf) {
> > > > > > > > > > > +	u32 value;
> > > > > > > > > > > +	unsigned int cpu = dev->id;
> > > > > > > > > > > +
> > > > > > > > > > > +	smp_call_function_single(cpu, do_show_pwrmgtcr0,
> > > > > > > > > > > +&value, 1);
> > > > > > > > > > > +
> > > > > > > > > > > +	value &= PWRMGTCR0_PW20_WAIT;
> > > > > > > > > > > +
> > > > > > > > > > > +	return sprintf(buf, "%u\n", value ? 1 : 0); }
> > > > > > > > > > > +
> > > > > > > > > > > +static void do_store_pw20_state(void *val) {
> > > > > > > > > > > +	u32 *value = val;
> > > > > > > > > > > +	u32 pw20_state;
> > > > > > > > > > > +
> > > > > > > > > > > +	pw20_state = mfspr(SPRN_PWRMGTCR0);
> > > > > > > > > > > +
> > > > > > > > > > > +	if (*value)
> > > > > > > > > > > +		pw20_state |= PWRMGTCR0_PW20_WAIT;
> > > > > > > > > > > +	else
> > > > > > > > > > > +		pw20_state &= ~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 = 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 = dev->id;
> > > > > > > > > > > +
> > > > > > > > > > > +	if (!pw20_wt) {
> > > > > > > > > > > +		smp_call_function_single(cpu,
> > do_show_pwrmgtcr0,
> > > > > > > > > > > +&value,
> > > > > > > > 1);
> > > > > > > > > > > +		value = (value & PWRMGTCR0_PW20_ENT) >>
> > > > > > > > > > > +					PWRMGTCR0_PW20_ENT_SHIFT;
> > > > > > > > > > > +
> > > > > > > > > > > +		tb_cycle = (1 << (MAX_BIT - value)) * 2;
> > > > > > > > > >
> > > > > > > > > > Is value = 0 and value = 1 legal? These will make
> > > > > > > > > > tb_cycle = 0,
> > > > > > > > > >
> > > > > > > > > > > +		time = div_u64(tb_cycle * 1000,
> > tb_ticks_per_usec)
> > > > - 1;
> > > > > > > > > >
> > > > > > > > > > And time = -1;
> > > > > > > > > >
> > > > > > > > > Please look at the end of the function, :)
> > > > > > > > >
> > > > > > > > > "return sprintf(buf, "%llu\n", time > 0 ? time : 0);"
> > > > > > > >
> > > > > > > > I know you return 0 if value = 0/1, my question was that,
> > > > > > > > is this correct as per specification?
> > > > > > > >
> > > > > > > > Ahh, also for "value" upto 7 you will return 0, no?
> > > > > > > >
> > > > > > > If value = 0, MAX_BIT - value = 63 tb_cycle =
> > > > > > > 0xffffffff_ffffffff, tb_cycle * 1000 will overflow, but this
> > situation is not possible.
> > > > > > > Because if the "value = 0" means this feature will be
> "disable".
> > > > > > > Now The default wait bit is 50(MAX_BIT - value, value = 13),
> > > > > > > the PW20/Altivec Idle wait entry time is about 1ms, this
> > > > > > > time is very long for wait idle time, and it's cannot be
> > > > > > > increased(means (MAX_BIT
> > > > > > > - value)
> > > > > > cannot greater than 50).
> > > > > >
> > > > > > What you said is not obvious from code and so at least write a
> > > > > > comment that value will be always >= 13 or value will never be
> > > > > > less than < 8 and below calculation will not overflow. may be
> > > > > > error out if value is less than 8.
> > > > > >
> > > > > The "value" less than 10, this will overflow.
> > > > > There is not error, The code I knew it could not be less than
> > > > > 10, that's why I use the following code. :)
> > > >
> > > > I am sorry to persist but this is not about what you know, this is
> > > > about how code is read and code does not say what you know, so add
> > > > a comment at least and error out/warn when "value" is less than a
> > certain number.
> > > >
> > > Sorry for the late to response the mail. If it caused confusion, we
> > > can
> > add a comment.
> > >
> > > How about the following comment?
> > > /*
> > >  * If the "value" less than 10, this will overflow.
> > >  * From benchmark test, the default wait bit will not be set less
> > > than
> > 10bit.
> > >  * Because 10 bit corresponds to the wait entry time is
> > > 439375573401999609(ns),
> > >  * for wait-entry-idle time this value looks too long, and we cannot
> > > use those
> > >  * "long" time as a default wait-entry time. So overflow could not
> > > have happened
> > >  * and we use this calculation method to get wait-entry-idle time.
> > >  */
> >
> > If there's to be a limit on the times we accept, make it explicit.
> > Check for it before doing any conversions, and return an error if
> > userspace tries to set it.
> >
> The branch only use to read default wait-entry-time.
> We have no limit the user's input, and we can't restrict. Once the user
> set the wait-entry-time, the code will do another branch.
> 

Hi scott,
Do you have any comments about this patch?
I will add the comment and send this patch again.

-dongsheng

> >
> >
Scott Wood Nov. 4, 2013, 9:51 p.m. UTC | #19
On Sun, 2013-11-03 at 22:04 -0600, Wang Dongsheng-B40534 wrote:
> > -----Original Message-----
> > From: Wang Dongsheng-B40534
> > Sent: Monday, October 21, 2013 11:11 AM
> > To: Wood Scott-B07421
> > Cc: Bhushan Bharat-R65777; linuxppc-dev@lists.ozlabs.org
> > Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and
> > altivec idle
> > 
> > 
> > 
> > > -----Original Message-----
> > > From: Wood Scott-B07421
> > > Sent: Saturday, October 19, 2013 3:22 AM
> > > To: Wang Dongsheng-B40534
> > > Cc: Bhushan Bharat-R65777; Wood Scott-B07421; linuxppc-
> > > dev@lists.ozlabs.org
> > > Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and
> > > altivec idle
> > >
> > > On Thu, 2013-10-17 at 22:02 -0500, Wang Dongsheng-B40534 wrote:
> > > >
> > > > > -----Original Message-----
> > > > > From: Bhushan Bharat-R65777
> > > > > Sent: Thursday, October 17, 2013 2:46 PM
> > > > > 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
> > > > >
> > > > >
> > > > >
> > > > > > > > -----Original Message-----
> > > > > > > > From: Wang Dongsheng-B40534
> > > > > > > > Sent: Thursday, October 17, 2013 11:22 AM
> > > > > > > > To: Bhushan Bharat-R65777; 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
> > > > > > > >
> > > > > > > >
> > > > > > > >
> > > > > > > > > -----Original Message-----
> > > > > > > > > From: Bhushan Bharat-R65777
> > > > > > > > > Sent: Thursday, October 17, 2013 11:20 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
> > > > > > > > >
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > > -----Original Message-----
> > > > > > > > > > From: Wang Dongsheng-B40534
> > > > > > > > > > Sent: Thursday, October 17, 2013 8:16 AM
> > > > > > > > > > To: Bhushan Bharat-R65777; 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
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > > -----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
> > > > > > > > > > >
> > > > > > > > > > >
> > > > > > > > > > >
> > > > > > > > > > > > -----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; Wang
> > > > > > > > > > > Dongsheng-B40534
> > > > > > > > > > > > Subject: [PATCH v5 4/4] powerpc/85xx: add sysfs for
> > > > > > > > > > > > pw20 state and
> > > > > > > > > > > altivec idle
> > > > > > > > > > > >
> > > > > > > > > > > > From: Wang Dongsheng <dongsheng.wang@freescale.com>
> > > > > > > > > > > >
> > > > > > > > > > > > Add a sys interface to enable/diable pw20 state or
> > > > > > > > > > > > altivec idle, and
> > > > > > > > > > > control the
> > > > > > > > > > > > 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
> > > > > > > > > > > > <dongsheng.wang@freescale.com>
> > > > > > > > > > > > ---
> > > > > > > > > > > > *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.c
> > > > > > > > > > > index
> > > > > > > > > > > > 27a90b9..10d1128 100644
> > > > > > > > > > > > --- a/arch/powerpc/kernel/sysfs.c
> > > > > > > > > > > > +++ b/arch/powerpc/kernel/sysfs.c
> > > > > > > > > > > > @@ -85,6 +85,284 @@ __setup("smt-snooze-delay=",
> > > > > > > > > > > setup_smt_snooze_delay);
> > > > > > > > > > > >
> > > > > > > > > > > >  #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 >= 10000)
> > > > > > > > > > > > +		cycle = div_u64(ns + 500, 1000) *
> > > > > tb_ticks_per_usec;
> > > > > > > > > > > > +	else
> > > > > > > > > > > > +		cycle = div_u64(ns * tb_ticks_per_usec,
> > > 1000);
> > > > > > > > > > > > +
> > > > > > > > > > > > +	if (!cycle)
> > > > > > > > > > > > +		return 0;
> > > > > > > > > > > > +
> > > > > > > > > > > > +	return ilog2(cycle); }
> > > > > > > > > > > > +
> > > > > > > > > > > > +static void do_show_pwrmgtcr0(void *val) {
> > > > > > > > > > > > +	u32 *value = val;
> > > > > > > > > > > > +
> > > > > > > > > > > > +	*value = mfspr(SPRN_PWRMGTCR0); }
> > > > > > > > > > > > +
> > > > > > > > > > > > +static ssize_t show_pw20_state(struct device *dev,
> > > > > > > > > > > > +				struct device_attribute *attr,
> > > char
> > > > > *buf) {
> > > > > > > > > > > > +	u32 value;
> > > > > > > > > > > > +	unsigned int cpu = dev->id;
> > > > > > > > > > > > +
> > > > > > > > > > > > +	smp_call_function_single(cpu, do_show_pwrmgtcr0,
> > > > > > > > > > > > +&value, 1);
> > > > > > > > > > > > +
> > > > > > > > > > > > +	value &= PWRMGTCR0_PW20_WAIT;
> > > > > > > > > > > > +
> > > > > > > > > > > > +	return sprintf(buf, "%u\n", value ? 1 : 0); }
> > > > > > > > > > > > +
> > > > > > > > > > > > +static void do_store_pw20_state(void *val) {
> > > > > > > > > > > > +	u32 *value = val;
> > > > > > > > > > > > +	u32 pw20_state;
> > > > > > > > > > > > +
> > > > > > > > > > > > +	pw20_state = mfspr(SPRN_PWRMGTCR0);
> > > > > > > > > > > > +
> > > > > > > > > > > > +	if (*value)
> > > > > > > > > > > > +		pw20_state |= PWRMGTCR0_PW20_WAIT;
> > > > > > > > > > > > +	else
> > > > > > > > > > > > +		pw20_state &= ~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 = 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 = dev->id;
> > > > > > > > > > > > +
> > > > > > > > > > > > +	if (!pw20_wt) {
> > > > > > > > > > > > +		smp_call_function_single(cpu,
> > > do_show_pwrmgtcr0,
> > > > > > > > > > > > +&value,
> > > > > > > > > 1);
> > > > > > > > > > > > +		value = (value & PWRMGTCR0_PW20_ENT) >>
> > > > > > > > > > > > +					PWRMGTCR0_PW20_ENT_SHIFT;
> > > > > > > > > > > > +
> > > > > > > > > > > > +		tb_cycle = (1 << (MAX_BIT - value)) * 2;
> > > > > > > > > > >
> > > > > > > > > > > Is value = 0 and value = 1 legal? These will make
> > > > > > > > > > > tb_cycle = 0,
> > > > > > > > > > >
> > > > > > > > > > > > +		time = div_u64(tb_cycle * 1000,
> > > tb_ticks_per_usec)
> > > > > - 1;
> > > > > > > > > > >
> > > > > > > > > > > And time = -1;
> > > > > > > > > > >
> > > > > > > > > > Please look at the end of the function, :)
> > > > > > > > > >
> > > > > > > > > > "return sprintf(buf, "%llu\n", time > 0 ? time : 0);"
> > > > > > > > >
> > > > > > > > > I know you return 0 if value = 0/1, my question was that,
> > > > > > > > > is this correct as per specification?
> > > > > > > > >
> > > > > > > > > Ahh, also for "value" upto 7 you will return 0, no?
> > > > > > > > >
> > > > > > > > If value = 0, MAX_BIT - value = 63 tb_cycle =
> > > > > > > > 0xffffffff_ffffffff, tb_cycle * 1000 will overflow, but this
> > > situation is not possible.
> > > > > > > > Because if the "value = 0" means this feature will be
> > "disable".
> > > > > > > > Now The default wait bit is 50(MAX_BIT - value, value = 13),
> > > > > > > > the PW20/Altivec Idle wait entry time is about 1ms, this
> > > > > > > > time is very long for wait idle time, and it's cannot be
> > > > > > > > increased(means (MAX_BIT
> > > > > > > > - value)
> > > > > > > cannot greater than 50).
> > > > > > >
> > > > > > > What you said is not obvious from code and so at least write a
> > > > > > > comment that value will be always >= 13 or value will never be
> > > > > > > less than < 8 and below calculation will not overflow. may be
> > > > > > > error out if value is less than 8.
> > > > > > >
> > > > > > The "value" less than 10, this will overflow.
> > > > > > There is not error, The code I knew it could not be less than
> > > > > > 10, that's why I use the following code. :)
> > > > >
> > > > > I am sorry to persist but this is not about what you know, this is
> > > > > about how code is read and code does not say what you know, so add
> > > > > a comment at least and error out/warn when "value" is less than a
> > > certain number.
> > > > >
> > > > Sorry for the late to response the mail. If it caused confusion, we
> > > > can
> > > add a comment.
> > > >
> > > > How about the following comment?
> > > > /*
> > > >  * If the "value" less than 10, this will overflow.
> > > >  * From benchmark test, the default wait bit will not be set less
> > > > than
> > > 10bit.
> > > >  * Because 10 bit corresponds to the wait entry time is
> > > > 439375573401999609(ns),
> > > >  * for wait-entry-idle time this value looks too long, and we cannot
> > > > use those
> > > >  * "long" time as a default wait-entry time. So overflow could not
> > > > have happened
> > > >  * and we use this calculation method to get wait-entry-idle time.
> > > >  */
> > >
> > > If there's to be a limit on the times we accept, make it explicit.
> > > Check for it before doing any conversions, and return an error if
> > > userspace tries to set it.
> > >
> > The branch only use to read default wait-entry-time.
> > We have no limit the user's input, and we can't restrict. Once the user
> > set the wait-entry-time, the code will do another branch.
> > 
> 
> Hi scott,
> Do you have any comments about this patch?
> I will add the comment and send this patch again.

What do you mean by "and we can't restrict"?  Why not?

Why is it only used to read the default, and not the current value?

-Scott
Scott Wood Nov. 4, 2013, 11:47 p.m. UTC | #20
On Sun, 2013-10-20 at 22:27 -0500, Wang Dongsheng-B40534 wrote:
> 
> > -----Original Message-----
> > From: Wood Scott-B07421
> > Sent: Saturday, October 19, 2013 3:23 AM
> > To: Wang Dongsheng-B40534
> > Cc: Wood Scott-B07421; Bhushan Bharat-R65777; linuxppc-
> > dev@lists.ozlabs.org
> > Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and
> > altivec idle
> > 
> > On Thu, 2013-10-17 at 21:36 -0500, Wang Dongsheng-B40534 wrote:
> > >
> > > > -----Original Message-----
> > > > From: Wood Scott-B07421
> > > > Sent: Friday, October 18, 2013 12:52 AM
> > > > To: Wang Dongsheng-B40534
> > > > Cc: Bhushan Bharat-R65777; Wood Scott-B07421; linuxppc-
> > > > dev@lists.ozlabs.org
> > > > Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state
> > > > and altivec idle
> > > >
> > > > On Thu, 2013-10-17 at 00:51 -0500, Wang Dongsheng-B40534 wrote:
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: Bhushan Bharat-R65777
> > > > > > Sent: Thursday, October 17, 2013 11:20 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
> > > > > >
> > > > > >
> > > > > >
> > > > > > > -----Original Message-----
> > > > > > > From: Wang Dongsheng-B40534
> > > > > > > Sent: Thursday, October 17, 2013 8:16 AM
> > > > > > > To: Bhushan Bharat-R65777; 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
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > > -----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
> > > > > > > >
> > > > > > > >
> > > > > > > >
> > > > > > > > > -----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;
> > > > > > > > > Wang
> > > > > > > > Dongsheng-B40534
> > > > > > > > > Subject: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20
> > > > > > > > > state and
> > > > > > > > altivec idle
> > > > > > > > >
> > > > > > > > > +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 = dev->id;
> > > > > > > > > +
> > > > > > > > > +	if (!pw20_wt) {
> > > > > > > > > +		smp_call_function_single(cpu, do_show_pwrmgtcr0,
> > > > > > > > > +&value,
> > > > > > 1);
> > > > > > > > > +		value = (value & PWRMGTCR0_PW20_ENT) >>
> > > > > > > > > +					PWRMGTCR0_PW20_ENT_SHIFT;
> > > > > > > > > +
> > > > > > > > > +		tb_cycle = (1 << (MAX_BIT - value)) * 2;
> > > > > > > >
> > > > > > > > Is value = 0 and value = 1 legal? These will make tb_cycle =
> > > > > > > > 0,
> > > > > > > >
> > > > > > > > > +		time = div_u64(tb_cycle * 1000, tb_ticks_per_usec)
> > - 1;
> > > > > > > >
> > > > > > > > And time = -1;
> > > > > > > >
> > > > > > > Please look at the end of the function, :)
> > > > > > >
> > > > > > > "return sprintf(buf, "%llu\n", time > 0 ? time : 0);"
> > > > > >
> > > > > > I know you return 0 if value = 0/1, my question was that, is
> > > > > > this correct as per specification?
> > > > > >
> > > > > > Ahh, also for "value" upto 7 you will return 0, no?
> > > > > >
> > > > > If value = 0, MAX_BIT - value = 63 tb_cycle = 0xffffffff_ffffffff,
> > > >
> > > > Actually, tb_cycle will be undefined because you shifted a 32-bit
> > > > value
> > > > (1) by more than 31 bits.  s/1/1ULL/
> > > >
> > > Actually, we have been discussing this situation that could not have
> > happened.
> > > See !pw20_wt branch, this branch is read default wait bit.
> > > The default wait bit is 50, the time is about 1ms.
> > > The default wait bit cannot less than 50, means the wait entry time
> > cannot greater than 1ms.
> > > We have already begun benchmark test, and we got a preliminary results.
> > > 55, 56, 57bit looks good, but we need more benchmark to get the default
> > bit.
> > 
> > What does the default have to do with it?  The user could have set a
> > different value, and then read it back.
> > 
> > Plus, how much time corresponds to bit 50 depends on the actual timebase
> > frequency which could vary.
> > 
> 	if (!pw20_wt) {
> 		smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
> 		value = (value & PWRMGTCR0_PW20_ENT) >>
> 					PWRMGTCR0_PW20_ENT_SHIFT;
> 
> 		tb_cycle = (1 << (MAX_BIT - value)) * 2;
> 		time = tb_cycle * (1000 / tb_ticks_per_usec) - 1;
> 	} else {
> 		time = pw20_wt;
> 	}
> 
> As we have discussed before we need a variable to save To save the users to set wait-entry-time value.
> 
> See the code, if user have set a value, and the value will be set in pw20_wt. 
> When the user read it back, the code will do "time = pw20_wt" branch.
> 
> When the user not set the wait-entry-time value and read this sys interface, the code will do the following branch.

Oh, so it's not that you "need" this, you already have it.

-Scott
Wang Dongsheng-B40534 Nov. 5, 2013, 2:11 a.m. UTC | #21
> -----Original Message-----
> From: Wood Scott-B07421
> Sent: Tuesday, November 05, 2013 7:48 AM
> To: Wang Dongsheng-B40534
> Cc: Wood Scott-B07421; Bhushan Bharat-R65777; linuxppc-
> dev@lists.ozlabs.org
> Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and
> altivec idle
> 
> On Sun, 2013-10-20 at 22:27 -0500, Wang Dongsheng-B40534 wrote:
> >
> > > -----Original Message-----
> > > From: Wood Scott-B07421
> > > Sent: Saturday, October 19, 2013 3:23 AM
> > > To: Wang Dongsheng-B40534
> > > Cc: Wood Scott-B07421; Bhushan Bharat-R65777; linuxppc-
> > > dev@lists.ozlabs.org
> > > Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state
> > > and altivec idle
> > >
> > > On Thu, 2013-10-17 at 21:36 -0500, Wang Dongsheng-B40534 wrote:
> > > >
> > > > > -----Original Message-----
> > > > > From: Wood Scott-B07421
> > > > > Sent: Friday, October 18, 2013 12:52 AM
> > > > > To: Wang Dongsheng-B40534
> > > > > Cc: Bhushan Bharat-R65777; Wood Scott-B07421; linuxppc-
> > > > > dev@lists.ozlabs.org
> > > > > Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20
> > > > > state and altivec idle
> > > > >
> > > > > On Thu, 2013-10-17 at 00:51 -0500, Wang Dongsheng-B40534 wrote:
> > > > > >
> > > > > > > -----Original Message-----
> > > > > > > From: Bhushan Bharat-R65777
> > > > > > > Sent: Thursday, October 17, 2013 11:20 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
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > > -----Original Message-----
> > > > > > > > From: Wang Dongsheng-B40534
> > > > > > > > Sent: Thursday, October 17, 2013 8:16 AM
> > > > > > > > To: Bhushan Bharat-R65777; 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
> > > > > > > >
> > > > > > > >
> > > > > > > >
> > > > > > > > > -----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
> > > > > > > > >
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > > -----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; Wang
> > > > > > > > > Dongsheng-B40534
> > > > > > > > > > Subject: [PATCH v5 4/4] powerpc/85xx: add sysfs for
> > > > > > > > > > pw20 state and
> > > > > > > > > altivec idle
> > > > > > > > > >
> > > > > > > > > > +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 = dev->id;
> > > > > > > > > > +
> > > > > > > > > > +	if (!pw20_wt) {
> > > > > > > > > > +		smp_call_function_single(cpu,
> do_show_pwrmgtcr0,
> > > > > > > > > > +&value,
> > > > > > > 1);
> > > > > > > > > > +		value = (value & PWRMGTCR0_PW20_ENT) >>
> > > > > > > > > > +					PWRMGTCR0_PW20_ENT_SHIFT;
> > > > > > > > > > +
> > > > > > > > > > +		tb_cycle = (1 << (MAX_BIT - value)) * 2;
> > > > > > > > >
> > > > > > > > > Is value = 0 and value = 1 legal? These will make
> > > > > > > > > tb_cycle = 0,
> > > > > > > > >
> > > > > > > > > > +		time = div_u64(tb_cycle * 1000,
> tb_ticks_per_usec)
> > > - 1;
> > > > > > > > >
> > > > > > > > > And time = -1;
> > > > > > > > >
> > > > > > > > Please look at the end of the function, :)
> > > > > > > >
> > > > > > > > "return sprintf(buf, "%llu\n", time > 0 ? time : 0);"
> > > > > > >
> > > > > > > I know you return 0 if value = 0/1, my question was that, is
> > > > > > > this correct as per specification?
> > > > > > >
> > > > > > > Ahh, also for "value" upto 7 you will return 0, no?
> > > > > > >
> > > > > > If value = 0, MAX_BIT - value = 63 tb_cycle =
> > > > > > 0xffffffff_ffffffff,
> > > > >
> > > > > Actually, tb_cycle will be undefined because you shifted a
> > > > > 32-bit value
> > > > > (1) by more than 31 bits.  s/1/1ULL/
> > > > >
> > > > Actually, we have been discussing this situation that could not
> > > > have
> > > happened.
> > > > See !pw20_wt branch, this branch is read default wait bit.
> > > > The default wait bit is 50, the time is about 1ms.
> > > > The default wait bit cannot less than 50, means the wait entry
> > > > time
> > > cannot greater than 1ms.
> > > > We have already begun benchmark test, and we got a preliminary
> results.
> > > > 55, 56, 57bit looks good, but we need more benchmark to get the
> > > > default
> > > bit.
> > >
> > > What does the default have to do with it?  The user could have set a
> > > different value, and then read it back.
> > >
> > > Plus, how much time corresponds to bit 50 depends on the actual
> > > timebase frequency which could vary.
> > >
> > 	if (!pw20_wt) {
> > 		smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
> > 		value = (value & PWRMGTCR0_PW20_ENT) >>
> > 					PWRMGTCR0_PW20_ENT_SHIFT;
> >
> > 		tb_cycle = (1 << (MAX_BIT - value)) * 2;
> > 		time = tb_cycle * (1000 / tb_ticks_per_usec) - 1;
> > 	} else {
> > 		time = pw20_wt;
> > 	}
> >
> > As we have discussed before we need a variable to save To save the
> users to set wait-entry-time value.
> >
> > See the code, if user have set a value, and the value will be set in
> pw20_wt.
> > When the user read it back, the code will do "time = pw20_wt" branch.
> >
> > When the user not set the wait-entry-time value and read this sys
> interface, the code will do the following branch.
> 
> Oh, so it's not that you "need" this, you already have it.
> 
Yes, we already have a variable. :)
Wang Dongsheng-B40534 Nov. 5, 2013, 3:09 a.m. UTC | #22
> -----Original Message-----
> From: Wood Scott-B07421
> Sent: Tuesday, November 05, 2013 5:52 AM
> To: Wang Dongsheng-B40534
> Cc: Wood Scott-B07421; Bhushan Bharat-R65777; linuxppc-
> dev@lists.ozlabs.org
> Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and
> altivec idle
> 
> On Sun, 2013-11-03 at 22:04 -0600, Wang Dongsheng-B40534 wrote:
> > > -----Original Message-----
> > > From: Wang Dongsheng-B40534
> > > Sent: Monday, October 21, 2013 11:11 AM
> > > To: Wood Scott-B07421
> > > Cc: Bhushan Bharat-R65777; linuxppc-dev@lists.ozlabs.org
> > > Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state
> > > and altivec idle
> > >
> > >
> > >
> > > > -----Original Message-----
> > > > From: Wood Scott-B07421
> > > > Sent: Saturday, October 19, 2013 3:22 AM
> > > > To: Wang Dongsheng-B40534
> > > > Cc: Bhushan Bharat-R65777; Wood Scott-B07421; linuxppc-
> > > > dev@lists.ozlabs.org
> > > > Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state
> > > > and altivec idle
> > > >
> > > > On Thu, 2013-10-17 at 22:02 -0500, Wang Dongsheng-B40534 wrote:
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: Bhushan Bharat-R65777
> > > > > > Sent: Thursday, October 17, 2013 2:46 PM
> > > > > > 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
> > > > > >
> > > > > >
> > > > > >
> > > > > > > > > -----Original Message-----
> > > > > > > > > From: Wang Dongsheng-B40534
> > > > > > > > > Sent: Thursday, October 17, 2013 11:22 AM
> > > > > > > > > To: Bhushan Bharat-R65777; 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
> > > > > > > > >
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > > -----Original Message-----
> > > > > > > > > > From: Bhushan Bharat-R65777
> > > > > > > > > > Sent: Thursday, October 17, 2013 11:20 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
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > > -----Original Message-----
> > > > > > > > > > > From: Wang Dongsheng-B40534
> > > > > > > > > > > Sent: Thursday, October 17, 2013 8:16 AM
> > > > > > > > > > > To: Bhushan Bharat-R65777; 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
> > > > > > > > > > >
> > > > > > > > > > >
> > > > > > > > > > >
> > > > > > > > > > > > -----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
> > > > > > > > > > > >
> > > > > > > > > > > >
> > > > > > > > > > > >
> > > > > > > > > > > > > -----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; Wang
> > > > > > > > > > > > Dongsheng-B40534
> > > > > > > > > > > > > Subject: [PATCH v5 4/4] powerpc/85xx: add sysfs
> > > > > > > > > > > > > for
> > > > > > > > > > > > > pw20 state and
> > > > > > > > > > > > altivec idle
> > > > > > > > > > > > >
> > > > > > > > > > > > > From: Wang Dongsheng
> > > > > > > > > > > > > <dongsheng.wang@freescale.com>
> > > > > > > > > > > > >
> > > > > > > > > > > > > Add a sys interface to enable/diable pw20 state
> > > > > > > > > > > > > or altivec idle, and
> > > > > > > > > > > > control the
> > > > > > > > > > > > > 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_t
> > > > > > > > > > > > > ime
> > > > > > > > > > > > > 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
> > > > > > > > > > > > > <dongsheng.wang@freescale.com>
> > > > > > > > > > > > > ---
> > > > > > > > > > > > > *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.c
> > > > > > > > > > > > index
> > > > > > > > > > > > > 27a90b9..10d1128 100644
> > > > > > > > > > > > > --- a/arch/powerpc/kernel/sysfs.c
> > > > > > > > > > > > > +++ b/arch/powerpc/kernel/sysfs.c
> > > > > > > > > > > > > @@ -85,6 +85,284 @@ __setup("smt-snooze-delay=",
> > > > > > > > > > > > setup_smt_snooze_delay);
> > > > > > > > > > > > >
> > > > > > > > > > > > >  #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 >= 10000)
> > > > > > > > > > > > > +		cycle = div_u64(ns + 500, 1000) *
> > > > > > tb_ticks_per_usec;
> > > > > > > > > > > > > +	else
> > > > > > > > > > > > > +		cycle = div_u64(ns *
> tb_ticks_per_usec,
> > > > 1000);
> > > > > > > > > > > > > +
> > > > > > > > > > > > > +	if (!cycle)
> > > > > > > > > > > > > +		return 0;
> > > > > > > > > > > > > +
> > > > > > > > > > > > > +	return ilog2(cycle); }
> > > > > > > > > > > > > +
> > > > > > > > > > > > > +static void do_show_pwrmgtcr0(void *val) {
> > > > > > > > > > > > > +	u32 *value = val;
> > > > > > > > > > > > > +
> > > > > > > > > > > > > +	*value = mfspr(SPRN_PWRMGTCR0); }
> > > > > > > > > > > > > +
> > > > > > > > > > > > > +static ssize_t show_pw20_state(struct device
> *dev,
> > > > > > > > > > > > > +				struct device_attribute
> *attr,
> > > > char
> > > > > > *buf) {
> > > > > > > > > > > > > +	u32 value;
> > > > > > > > > > > > > +	unsigned int cpu = dev->id;
> > > > > > > > > > > > > +
> > > > > > > > > > > > > +	smp_call_function_single(cpu,
> > > > > > > > > > > > > +do_show_pwrmgtcr0, &value, 1);
> > > > > > > > > > > > > +
> > > > > > > > > > > > > +	value &= PWRMGTCR0_PW20_WAIT;
> > > > > > > > > > > > > +
> > > > > > > > > > > > > +	return sprintf(buf, "%u\n", value ? 1 :
> 0); }
> > > > > > > > > > > > > +
> > > > > > > > > > > > > +static void do_store_pw20_state(void *val) {
> > > > > > > > > > > > > +	u32 *value = val;
> > > > > > > > > > > > > +	u32 pw20_state;
> > > > > > > > > > > > > +
> > > > > > > > > > > > > +	pw20_state = mfspr(SPRN_PWRMGTCR0);
> > > > > > > > > > > > > +
> > > > > > > > > > > > > +	if (*value)
> > > > > > > > > > > > > +		pw20_state |= PWRMGTCR0_PW20_WAIT;
> > > > > > > > > > > > > +	else
> > > > > > > > > > > > > +		pw20_state &= ~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 = 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 = dev->id;
> > > > > > > > > > > > > +
> > > > > > > > > > > > > +	if (!pw20_wt) {
> > > > > > > > > > > > > +		smp_call_function_single(cpu,
> > > > do_show_pwrmgtcr0,
> > > > > > > > > > > > > +&value,
> > > > > > > > > > 1);
> > > > > > > > > > > > > +		value = (value &
> PWRMGTCR0_PW20_ENT) >>
> > > > > > > > > > > > > +
> 	PWRMGTCR0_PW20_ENT_SHIFT;
> > > > > > > > > > > > > +
> > > > > > > > > > > > > +		tb_cycle = (1 << (MAX_BIT - value)) *
> 2;
> > > > > > > > > > > >
> > > > > > > > > > > > Is value = 0 and value = 1 legal? These will make
> > > > > > > > > > > > tb_cycle = 0,
> > > > > > > > > > > >
> > > > > > > > > > > > > +		time = div_u64(tb_cycle * 1000,
> > > > tb_ticks_per_usec)
> > > > > > - 1;
> > > > > > > > > > > >
> > > > > > > > > > > > And time = -1;
> > > > > > > > > > > >
> > > > > > > > > > > Please look at the end of the function, :)
> > > > > > > > > > >
> > > > > > > > > > > "return sprintf(buf, "%llu\n", time > 0 ? time : 0);"
> > > > > > > > > >
> > > > > > > > > > I know you return 0 if value = 0/1, my question was
> > > > > > > > > > that, is this correct as per specification?
> > > > > > > > > >
> > > > > > > > > > Ahh, also for "value" upto 7 you will return 0, no?
> > > > > > > > > >
> > > > > > > > > If value = 0, MAX_BIT - value = 63 tb_cycle =
> > > > > > > > > 0xffffffff_ffffffff, tb_cycle * 1000 will overflow, but
> > > > > > > > > this
> > > > situation is not possible.
> > > > > > > > > Because if the "value = 0" means this feature will be
> > > "disable".
> > > > > > > > > Now The default wait bit is 50(MAX_BIT - value, value =
> > > > > > > > > 13), the PW20/Altivec Idle wait entry time is about 1ms,
> > > > > > > > > this time is very long for wait idle time, and it's
> > > > > > > > > cannot be increased(means (MAX_BIT
> > > > > > > > > - value)
> > > > > > > > cannot greater than 50).
> > > > > > > >
> > > > > > > > What you said is not obvious from code and so at least
> > > > > > > > write a comment that value will be always >= 13 or value
> > > > > > > > will never be less than < 8 and below calculation will not
> > > > > > > > overflow. may be error out if value is less than 8.
> > > > > > > >
> > > > > > > The "value" less than 10, this will overflow.
> > > > > > > There is not error, The code I knew it could not be less
> > > > > > > than 10, that's why I use the following code. :)
> > > > > >
> > > > > > I am sorry to persist but this is not about what you know,
> > > > > > this is about how code is read and code does not say what you
> > > > > > know, so add a comment at least and error out/warn when
> > > > > > "value" is less than a
> > > > certain number.
> > > > > >
> > > > > Sorry for the late to response the mail. If it caused confusion,
> > > > > we can
> > > > add a comment.
> > > > >
> > > > > How about the following comment?
> > > > > /*
> > > > >  * If the "value" less than 10, this will overflow.
> > > > >  * From benchmark test, the default wait bit will not be set
> > > > > less than
> > > > 10bit.
> > > > >  * Because 10 bit corresponds to the wait entry time is
> > > > > 439375573401999609(ns),
> > > > >  * for wait-entry-idle time this value looks too long, and we
> > > > > cannot use those
> > > > >  * "long" time as a default wait-entry time. So overflow could
> > > > > not have happened
> > > > >  * and we use this calculation method to get wait-entry-idle time.
> > > > >  */
> > > >
> > > > If there's to be a limit on the times we accept, make it explicit.
> > > > Check for it before doing any conversions, and return an error if
> > > > userspace tries to set it.
> > > >
> > > The branch only use to read default wait-entry-time.
> > > We have no limit the user's input, and we can't restrict. Once the
> > > user set the wait-entry-time, the code will do another branch.
> > >
> >
> > Hi scott,
> > Do you have any comments about this patch?
> > I will add the comment and send this patch again.
> 
> What do you mean by "and we can't restrict"?  Why not?
> 
> Why is it only used to read the default, and not the current value?
> 
We already have a variable which value is set by the user, as we have discussed before.

When the system boot-up. Before user set the wait-entry-time, we need to return a default wait-entry-time, if the user read this sys-interface. The default wait-entry-time is converted by wait-bit.

Once the user set the sys-interface, a variable will be used to save it. And when the user read sys-interface we will return back the variable.

-dongsheng
Bharat Bhushan Nov. 6, 2013, 5:25 a.m. UTC | #23
> -----Original Message-----
> From: Wang Dongsheng-B40534
> Sent: Tuesday, November 05, 2013 8:40 AM
> To: Wood Scott-B07421
> Cc: Bhushan Bharat-R65777; linuxppc-dev@lists.ozlabs.org
> Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and altivec
> idle
> 
> 
> 
> > -----Original Message-----
> > From: Wood Scott-B07421
> > Sent: Tuesday, November 05, 2013 5:52 AM
> > To: Wang Dongsheng-B40534
> > Cc: Wood Scott-B07421; Bhushan Bharat-R65777; linuxppc-
> > dev@lists.ozlabs.org
> > Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and
> > altivec idle
> >
> > On Sun, 2013-11-03 at 22:04 -0600, Wang Dongsheng-B40534 wrote:
> > > > -----Original Message-----
> > > > From: Wang Dongsheng-B40534
> > > > Sent: Monday, October 21, 2013 11:11 AM
> > > > To: Wood Scott-B07421
> > > > Cc: Bhushan Bharat-R65777; linuxppc-dev@lists.ozlabs.org
> > > > Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state
> > > > and altivec idle
> > > >
> > > >
> > > >
> > > > > -----Original Message-----
> > > > > From: Wood Scott-B07421
> > > > > Sent: Saturday, October 19, 2013 3:22 AM
> > > > > To: Wang Dongsheng-B40534
> > > > > Cc: Bhushan Bharat-R65777; Wood Scott-B07421; linuxppc-
> > > > > dev@lists.ozlabs.org
> > > > > Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20
> > > > > state and altivec idle
> > > > >
> > > > > On Thu, 2013-10-17 at 22:02 -0500, Wang Dongsheng-B40534 wrote:
> > > > > >
> > > > > > > -----Original Message-----
> > > > > > > From: Bhushan Bharat-R65777
> > > > > > > Sent: Thursday, October 17, 2013 2:46 PM
> > > > > > > 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
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > > > > -----Original Message-----
> > > > > > > > > > From: Wang Dongsheng-B40534
> > > > > > > > > > Sent: Thursday, October 17, 2013 11:22 AM
> > > > > > > > > > To: Bhushan Bharat-R65777; 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
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > > -----Original Message-----
> > > > > > > > > > > From: Bhushan Bharat-R65777
> > > > > > > > > > > Sent: Thursday, October 17, 2013 11:20 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
> > > > > > > > > > >
> > > > > > > > > > >
> > > > > > > > > > >
> > > > > > > > > > > > -----Original Message-----
> > > > > > > > > > > > From: Wang Dongsheng-B40534
> > > > > > > > > > > > Sent: Thursday, October 17, 2013 8:16 AM
> > > > > > > > > > > > To: Bhushan Bharat-R65777; 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
> > > > > > > > > > > >
> > > > > > > > > > > >
> > > > > > > > > > > >
> > > > > > > > > > > > > -----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
> > > > > > > > > > > > >
> > > > > > > > > > > > >
> > > > > > > > > > > > >
> > > > > > > > > > > > > > -----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; Wang
> > > > > > > > > > > > > Dongsheng-B40534
> > > > > > > > > > > > > > Subject: [PATCH v5 4/4] powerpc/85xx: add
> > > > > > > > > > > > > > sysfs for
> > > > > > > > > > > > > > pw20 state and
> > > > > > > > > > > > > altivec idle
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > From: Wang Dongsheng
> > > > > > > > > > > > > > <dongsheng.wang@freescale.com>
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > Add a sys interface to enable/diable pw20
> > > > > > > > > > > > > > state or altivec idle, and
> > > > > > > > > > > > > control the
> > > > > > > > > > > > > > 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
> > > > > > > > > > > > > > _t
> > > > > > > > > > > > > > ime
> > > > > > > > > > > > > > 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
> > > > > > > > > > > > > > <dongsheng.wang@freescale.com>
> > > > > > > > > > > > > > ---
> > > > > > > > > > > > > > *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.c
> > > > > > > > > > > > > index
> > > > > > > > > > > > > > 27a90b9..10d1128 100644
> > > > > > > > > > > > > > --- a/arch/powerpc/kernel/sysfs.c
> > > > > > > > > > > > > > +++ b/arch/powerpc/kernel/sysfs.c
> > > > > > > > > > > > > > @@ -85,6 +85,284 @@
> > > > > > > > > > > > > > __setup("smt-snooze-delay=",
> > > > > > > > > > > > > setup_smt_snooze_delay);
> > > > > > > > > > > > > >
> > > > > > > > > > > > > >  #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 >= 10000)
> > > > > > > > > > > > > > +		cycle = div_u64(ns + 500, 1000) *
> > > > > > > tb_ticks_per_usec;
> > > > > > > > > > > > > > +	else
> > > > > > > > > > > > > > +		cycle = div_u64(ns *
> > tb_ticks_per_usec,
> > > > > 1000);
> > > > > > > > > > > > > > +
> > > > > > > > > > > > > > +	if (!cycle)
> > > > > > > > > > > > > > +		return 0;
> > > > > > > > > > > > > > +
> > > > > > > > > > > > > > +	return ilog2(cycle); }
> > > > > > > > > > > > > > +
> > > > > > > > > > > > > > +static void do_show_pwrmgtcr0(void *val) {
> > > > > > > > > > > > > > +	u32 *value = val;
> > > > > > > > > > > > > > +
> > > > > > > > > > > > > > +	*value = mfspr(SPRN_PWRMGTCR0); }
> > > > > > > > > > > > > > +
> > > > > > > > > > > > > > +static ssize_t show_pw20_state(struct device
> > *dev,
> > > > > > > > > > > > > > +				struct device_attribute
> > *attr,
> > > > > char
> > > > > > > *buf) {
> > > > > > > > > > > > > > +	u32 value;
> > > > > > > > > > > > > > +	unsigned int cpu = dev->id;
> > > > > > > > > > > > > > +
> > > > > > > > > > > > > > +	smp_call_function_single(cpu,
> > > > > > > > > > > > > > +do_show_pwrmgtcr0, &value, 1);
> > > > > > > > > > > > > > +
> > > > > > > > > > > > > > +	value &= PWRMGTCR0_PW20_WAIT;
> > > > > > > > > > > > > > +
> > > > > > > > > > > > > > +	return sprintf(buf, "%u\n", value ? 1 :
> > 0); }
> > > > > > > > > > > > > > +
> > > > > > > > > > > > > > +static void do_store_pw20_state(void *val) {
> > > > > > > > > > > > > > +	u32 *value = val;
> > > > > > > > > > > > > > +	u32 pw20_state;
> > > > > > > > > > > > > > +
> > > > > > > > > > > > > > +	pw20_state = mfspr(SPRN_PWRMGTCR0);
> > > > > > > > > > > > > > +
> > > > > > > > > > > > > > +	if (*value)
> > > > > > > > > > > > > > +		pw20_state |= PWRMGTCR0_PW20_WAIT;
> > > > > > > > > > > > > > +	else
> > > > > > > > > > > > > > +		pw20_state &= ~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 = 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 = dev->id;
> > > > > > > > > > > > > > +
> > > > > > > > > > > > > > +	if (!pw20_wt) {
> > > > > > > > > > > > > > +		smp_call_function_single(cpu,
> > > > > do_show_pwrmgtcr0,
> > > > > > > > > > > > > > +&value,
> > > > > > > > > > > 1);
> > > > > > > > > > > > > > +		value = (value &
> > PWRMGTCR0_PW20_ENT) >>
> > > > > > > > > > > > > > +
> > 	PWRMGTCR0_PW20_ENT_SHIFT;
> > > > > > > > > > > > > > +
> > > > > > > > > > > > > > +		tb_cycle = (1 << (MAX_BIT - value)) *
> > 2;
> > > > > > > > > > > > >
> > > > > > > > > > > > > Is value = 0 and value = 1 legal? These will
> > > > > > > > > > > > > make tb_cycle = 0,
> > > > > > > > > > > > >
> > > > > > > > > > > > > > +		time = div_u64(tb_cycle * 1000,
> > > > > tb_ticks_per_usec)
> > > > > > > - 1;
> > > > > > > > > > > > >
> > > > > > > > > > > > > And time = -1;
> > > > > > > > > > > > >
> > > > > > > > > > > > Please look at the end of the function, :)
> > > > > > > > > > > >
> > > > > > > > > > > > "return sprintf(buf, "%llu\n", time > 0 ? time : 0);"
> > > > > > > > > > >
> > > > > > > > > > > I know you return 0 if value = 0/1, my question was
> > > > > > > > > > > that, is this correct as per specification?
> > > > > > > > > > >
> > > > > > > > > > > Ahh, also for "value" upto 7 you will return 0, no?
> > > > > > > > > > >
> > > > > > > > > > If value = 0, MAX_BIT - value = 63 tb_cycle =
> > > > > > > > > > 0xffffffff_ffffffff, tb_cycle * 1000 will overflow,
> > > > > > > > > > but this
> > > > > situation is not possible.
> > > > > > > > > > Because if the "value = 0" means this feature will be
> > > > "disable".
> > > > > > > > > > Now The default wait bit is 50(MAX_BIT - value, value
> > > > > > > > > > = 13), the PW20/Altivec Idle wait entry time is about
> > > > > > > > > > 1ms, this time is very long for wait idle time, and
> > > > > > > > > > it's cannot be increased(means (MAX_BIT
> > > > > > > > > > - value)
> > > > > > > > > cannot greater than 50).
> > > > > > > > >
> > > > > > > > > What you said is not obvious from code and so at least
> > > > > > > > > write a comment that value will be always >= 13 or value
> > > > > > > > > will never be less than < 8 and below calculation will
> > > > > > > > > not overflow. may be error out if value is less than 8.
> > > > > > > > >
> > > > > > > > The "value" less than 10, this will overflow.
> > > > > > > > There is not error, The code I knew it could not be less
> > > > > > > > than 10, that's why I use the following code. :)
> > > > > > >
> > > > > > > I am sorry to persist but this is not about what you know,
> > > > > > > this is about how code is read and code does not say what
> > > > > > > you know, so add a comment at least and error out/warn when
> > > > > > > "value" is less than a
> > > > > certain number.
> > > > > > >
> > > > > > Sorry for the late to response the mail. If it caused
> > > > > > confusion, we can
> > > > > add a comment.
> > > > > >
> > > > > > How about the following comment?
> > > > > > /*
> > > > > >  * If the "value" less than 10, this will overflow.
> > > > > >  * From benchmark test, the default wait bit will not be set
> > > > > > less than
> > > > > 10bit.
> > > > > >  * Because 10 bit corresponds to the wait entry time is
> > > > > > 439375573401999609(ns),
> > > > > >  * for wait-entry-idle time this value looks too long, and we
> > > > > > cannot use those
> > > > > >  * "long" time as a default wait-entry time. So overflow could
> > > > > > not have happened
> > > > > >  * and we use this calculation method to get wait-entry-idle time.
> > > > > >  */
> > > > >
> > > > > If there's to be a limit on the times we accept, make it explicit.
> > > > > Check for it before doing any conversions, and return an error
> > > > > if userspace tries to set it.
> > > > >
> > > > The branch only use to read default wait-entry-time.
> > > > We have no limit the user's input, and we can't restrict. Once the
> > > > user set the wait-entry-time, the code will do another branch.
> > > >
> > >
> > > Hi scott,
> > > Do you have any comments about this patch?
> > > I will add the comment and send this patch again.
> >
> > What do you mean by "and we can't restrict"?  Why not?
> >
> > Why is it only used to read the default, and not the current value?
> >
> We already have a variable which value is set by the user, as we have discussed
> before.
> 
> When the system boot-up. Before user set the wait-entry-time, we need to return
> a default wait-entry-time, if the user read this sys-interface. The default
> wait-entry-time is converted by wait-bit.
> 
> Once the user set the sys-interface, a variable will be used to save it. And
> when the user read sys-interface we will return back the variable.

While we are not "restricting user defined value" or "define same restriction for user defined and default", can we have only one flow of calculation and setting rather than conditional based on user have set or not set? 

-Bharat

> 
> -dongsheng
Wang Dongsheng-B40534 Nov. 6, 2013, 7:50 a.m. UTC | #24
> -----Original Message-----
> From: Bhushan Bharat-R65777
> Sent: Wednesday, November 06, 2013 1:25 PM
> 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
> 
> 
> 
> > -----Original Message-----
> > From: Wang Dongsheng-B40534
> > Sent: Tuesday, November 05, 2013 8:40 AM
> > To: Wood Scott-B07421
> > Cc: Bhushan Bharat-R65777; linuxppc-dev@lists.ozlabs.org
> > Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and
> > altivec idle
> >
> >
> >
> > > -----Original Message-----
> > > From: Wood Scott-B07421
> > > Sent: Tuesday, November 05, 2013 5:52 AM
> > > To: Wang Dongsheng-B40534
> > > Cc: Wood Scott-B07421; Bhushan Bharat-R65777; linuxppc-
> > > dev@lists.ozlabs.org
> > > Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state
> > > and altivec idle
> > >
> > > On Sun, 2013-11-03 at 22:04 -0600, Wang Dongsheng-B40534 wrote:
> > > > > -----Original Message-----
> > > > > From: Wang Dongsheng-B40534
> > > > > Sent: Monday, October 21, 2013 11:11 AM
> > > > > To: Wood Scott-B07421
> > > > > Cc: Bhushan Bharat-R65777; linuxppc-dev@lists.ozlabs.org
> > > > > Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20
> > > > > state and altivec idle
> > > > >
> > > > >
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: Wood Scott-B07421
> > > > > > Sent: Saturday, October 19, 2013 3:22 AM
> > > > > > To: Wang Dongsheng-B40534
> > > > > > Cc: Bhushan Bharat-R65777; Wood Scott-B07421; linuxppc-
> > > > > > dev@lists.ozlabs.org
> > > > > > Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20
> > > > > > state and altivec idle
> > > > > >
> > > > > > On Thu, 2013-10-17 at 22:02 -0500, Wang Dongsheng-B40534 wrote:
> > > > > > >
> > > > > > > > -----Original Message-----
> > > > > > > > From: Bhushan Bharat-R65777
> > > > > > > > Sent: Thursday, October 17, 2013 2:46 PM
> > > > > > > > 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
> > > > > > > >
> > > > > > > >
> > > > > > > >
> > > > > > > > > > > -----Original Message-----
> > > > > > > > > > > From: Wang Dongsheng-B40534
> > > > > > > > > > > Sent: Thursday, October 17, 2013 11:22 AM
> > > > > > > > > > > To: Bhushan Bharat-R65777; 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
> > > > > > > > > > >
> > > > > > > > > > >
> > > > > > > > > > >
> > > > > > > > > > > > -----Original Message-----
> > > > > > > > > > > > From: Bhushan Bharat-R65777
> > > > > > > > > > > > Sent: Thursday, October 17, 2013 11:20 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
> > > > > > > > > > > >
> > > > > > > > > > > >
> > > > > > > > > > > >
> > > > > > > > > > > > > -----Original Message-----
> > > > > > > > > > > > > From: Wang Dongsheng-B40534
> > > > > > > > > > > > > Sent: Thursday, October 17, 2013 8:16 AM
> > > > > > > > > > > > > To: Bhushan Bharat-R65777; 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
> > > > > > > > > > > > >
> > > > > > > > > > > > >
> > > > > > > > > > > > >
> > > > > > > > > > > > > > -----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
> > > > > > > > > > > > > >
> > > > > > > > > > > > > >
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > > -----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; Wang
> > > > > > > > > > > > > > Dongsheng-B40534
> > > > > > > > > > > > > > > Subject: [PATCH v5 4/4] powerpc/85xx: add
> > > > > > > > > > > > > > > sysfs for
> > > > > > > > > > > > > > > pw20 state and
> > > > > > > > > > > > > > altivec idle
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > From: Wang Dongsheng
> > > > > > > > > > > > > > > <dongsheng.wang@freescale.com>
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > Add a sys interface to enable/diable pw20
> > > > > > > > > > > > > > > state or altivec idle, and
> > > > > > > > > > > > > > control the
> > > > > > > > > > > > > > > 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_wa
> > > > > > > > > > > > > > > it
> > > > > > > > > > > > > > > _t
> > > > > > > > > > > > > > > ime
> > > > > > > > > > > > > > > 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
> > > > > > > > > > > > > > > <dongsheng.wang@freescale.com>
> > > > > > > > > > > > > > > ---
> > > > > > > > > > > > > > > *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.c
> > > > > > > > > > > > > > index
> > > > > > > > > > > > > > > 27a90b9..10d1128 100644
> > > > > > > > > > > > > > > --- a/arch/powerpc/kernel/sysfs.c
> > > > > > > > > > > > > > > +++ b/arch/powerpc/kernel/sysfs.c
> > > > > > > > > > > > > > > @@ -85,6 +85,284 @@
> > > > > > > > > > > > > > > __setup("smt-snooze-delay=",
> > > > > > > > > > > > > > setup_smt_snooze_delay);
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > >  #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 >= 10000)
> > > > > > > > > > > > > > > +		cycle = div_u64(ns + 500, 1000) *
> > > > > > > > tb_ticks_per_usec;
> > > > > > > > > > > > > > > +	else
> > > > > > > > > > > > > > > +		cycle = div_u64(ns *
> > > tb_ticks_per_usec,
> > > > > > 1000);
> > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > +	if (!cycle)
> > > > > > > > > > > > > > > +		return 0;
> > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > +	return ilog2(cycle); }
> > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > +static void do_show_pwrmgtcr0(void *val) {
> > > > > > > > > > > > > > > +	u32 *value = val;
> > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > +	*value = mfspr(SPRN_PWRMGTCR0); }
> > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > +static ssize_t show_pw20_state(struct
> > > > > > > > > > > > > > > +device
> > > *dev,
> > > > > > > > > > > > > > > +				struct device_attribute
> > > *attr,
> > > > > > char
> > > > > > > > *buf) {
> > > > > > > > > > > > > > > +	u32 value;
> > > > > > > > > > > > > > > +	unsigned int cpu = dev->id;
> > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > +	smp_call_function_single(cpu,
> > > > > > > > > > > > > > > +do_show_pwrmgtcr0, &value, 1);
> > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > +	value &= PWRMGTCR0_PW20_WAIT;
> > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > +	return sprintf(buf, "%u\n", value ? 1 :
> > > 0); }
> > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > +static void do_store_pw20_state(void *val) {
> > > > > > > > > > > > > > > +	u32 *value = val;
> > > > > > > > > > > > > > > +	u32 pw20_state;
> > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > +	pw20_state = mfspr(SPRN_PWRMGTCR0);
> > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > +	if (*value)
> > > > > > > > > > > > > > > +		pw20_state |= PWRMGTCR0_PW20_WAIT;
> > > > > > > > > > > > > > > +	else
> > > > > > > > > > > > > > > +		pw20_state &= ~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 = 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 = dev->id;
> > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > +	if (!pw20_wt) {
> > > > > > > > > > > > > > > +		smp_call_function_single(cpu,
> > > > > > do_show_pwrmgtcr0,
> > > > > > > > > > > > > > > +&value,
> > > > > > > > > > > > 1);
> > > > > > > > > > > > > > > +		value = (value &
> > > PWRMGTCR0_PW20_ENT) >>
> > > > > > > > > > > > > > > +
> > > 	PWRMGTCR0_PW20_ENT_SHIFT;
> > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > +		tb_cycle = (1 << (MAX_BIT - value)) *
> > > 2;
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > Is value = 0 and value = 1 legal? These will
> > > > > > > > > > > > > > make tb_cycle = 0,
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > > +		time = div_u64(tb_cycle * 1000,
> > > > > > tb_ticks_per_usec)
> > > > > > > > - 1;
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > And time = -1;
> > > > > > > > > > > > > >
> > > > > > > > > > > > > Please look at the end of the function, :)
> > > > > > > > > > > > >
> > > > > > > > > > > > > "return sprintf(buf, "%llu\n", time > 0 ? time :
> 0);"
> > > > > > > > > > > >
> > > > > > > > > > > > I know you return 0 if value = 0/1, my question
> > > > > > > > > > > > was that, is this correct as per specification?
> > > > > > > > > > > >
> > > > > > > > > > > > Ahh, also for "value" upto 7 you will return 0, no?
> > > > > > > > > > > >
> > > > > > > > > > > If value = 0, MAX_BIT - value = 63 tb_cycle =
> > > > > > > > > > > 0xffffffff_ffffffff, tb_cycle * 1000 will overflow,
> > > > > > > > > > > but this
> > > > > > situation is not possible.
> > > > > > > > > > > Because if the "value = 0" means this feature will
> > > > > > > > > > > be
> > > > > "disable".
> > > > > > > > > > > Now The default wait bit is 50(MAX_BIT - value,
> > > > > > > > > > > value = 13), the PW20/Altivec Idle wait entry time
> > > > > > > > > > > is about 1ms, this time is very long for wait idle
> > > > > > > > > > > time, and it's cannot be increased(means (MAX_BIT
> > > > > > > > > > > - value)
> > > > > > > > > > cannot greater than 50).
> > > > > > > > > >
> > > > > > > > > > What you said is not obvious from code and so at least
> > > > > > > > > > write a comment that value will be always >= 13 or
> > > > > > > > > > value will never be less than < 8 and below
> > > > > > > > > > calculation will not overflow. may be error out if
> value is less than 8.
> > > > > > > > > >
> > > > > > > > > The "value" less than 10, this will overflow.
> > > > > > > > > There is not error, The code I knew it could not be less
> > > > > > > > > than 10, that's why I use the following code. :)
> > > > > > > >
> > > > > > > > I am sorry to persist but this is not about what you know,
> > > > > > > > this is about how code is read and code does not say what
> > > > > > > > you know, so add a comment at least and error out/warn
> > > > > > > > when "value" is less than a
> > > > > > certain number.
> > > > > > > >
> > > > > > > Sorry for the late to response the mail. If it caused
> > > > > > > confusion, we can
> > > > > > add a comment.
> > > > > > >
> > > > > > > How about the following comment?
> > > > > > > /*
> > > > > > >  * If the "value" less than 10, this will overflow.
> > > > > > >  * From benchmark test, the default wait bit will not be set
> > > > > > > less than
> > > > > > 10bit.
> > > > > > >  * Because 10 bit corresponds to the wait entry time is
> > > > > > > 439375573401999609(ns),
> > > > > > >  * for wait-entry-idle time this value looks too long, and
> > > > > > > we cannot use those
> > > > > > >  * "long" time as a default wait-entry time. So overflow
> > > > > > > could not have happened
> > > > > > >  * and we use this calculation method to get wait-entry-idle
> time.
> > > > > > >  */
> > > > > >
> > > > > > If there's to be a limit on the times we accept, make it
> explicit.
> > > > > > Check for it before doing any conversions, and return an error
> > > > > > if userspace tries to set it.
> > > > > >
> > > > > The branch only use to read default wait-entry-time.
> > > > > We have no limit the user's input, and we can't restrict. Once
> > > > > the user set the wait-entry-time, the code will do another branch.
> > > > >
> > > >
> > > > Hi scott,
> > > > Do you have any comments about this patch?
> > > > I will add the comment and send this patch again.
> > >
> > > What do you mean by "and we can't restrict"?  Why not?
> > >
> > > Why is it only used to read the default, and not the current value?
> > >
> > We already have a variable which value is set by the user, as we have
> > discussed before.
> >
> > When the system boot-up. Before user set the wait-entry-time, we need
> > to return a default wait-entry-time, if the user read this
> > sys-interface. The default wait-entry-time is converted by wait-bit.
> >
> > Once the user set the sys-interface, a variable will be used to save
> > it. And when the user read sys-interface we will return back the
> variable.
> 
> While we are not "restricting user defined value" or "define same
> restriction for user defined and default", can we have only one flow of
> calculation and setting rather than conditional based on user have set or
> not set?
> 
Yes, we can do that.
If we want to use one flow to handle it. We should do the following changes:

#ifdef CONFIG_FSL_SOC
#include <linux/slab.h>
#endif

static u64 *pw20_wt;
static u64 *altivec_idle_wt;

static ssize_t show_pw20_wait_time(struct device *dev,
                                struct device_attribute *attr, char *buf)
{
	return sprintf(buf, "%llu\n", pw20_wt[dev->id]);
}

static ssize_t store_pw20_wait_time(struct device *dev,
                                struct device_attribute *attr,
                                const char *buf, size_t count)
{
...
pw20_wt[cpu] = value;
...
}

static ssize_t show_altivec_idle_wait_time(struct device *dev,
                                struct device_attribute *attr, char *buf)
{
	return sprintf(buf, "%llu\n", altivec_idle_wt[dev->id]);
}

static ssize_t store_altivec_idle_wait_time(struct device *dev,
                                struct device_attribute *attr,
                                const char *buf, size_t count)
{
...
altivec_idle_wt[cpu] = value;
...
}

static void register_cpu_online(unsigned int cpu)
{
...
#ifdef CONFIG_FSL_SOC
        u32 value, pw20_value, altivec_value;
        u64 tb_cycle;
#endif
...
#ifdef CONFIG_FSL_SOC
        if (PVR_VER(cur_cpu_spec->pvr_value) == PVR_VER_E6500) {
                device_create_file(s, &dev_attr_pw20_state);
                device_create_file(s, &dev_attr_pw20_wait_time);

                device_create_file(s, &dev_attr_altivec_idle);
                device_create_file(s, &dev_attr_altivec_idle_wait_time);
        }

        if (!pw20_wt)
                pw20_wt = kzalloc(nr_cpu_ids * sizeof(*pw20_wt), GFP_KERNEL);

	  if (!altivec_idle_wt)
		    altivec_idle_wt = kzalloc(nr_cpu_ids * sizeof(*altivec_idle_wt), GFP_KERNEL);

        smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);

        pw20_value = (value & PWRMGTCR0_PW20_ENT) >> PWRMGTCR0_PW20_ENT_SHIFT;
        tb_cycle = (1 << (MAX_BIT - pw20_value)) * 2;
        pw20_wt[cpu] = div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1;

        altivec_value = (value & PWRMGTCR0_AV_IDLE_CNT) >> PWRMGTCR0_AV_IDLE_CNT_SHIFT;
        tb_cycle = (1 << (MAX_BIT - altivec_value)) * 2;
        altivec_idle_wt[cpu] = div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1;
#endif
...
}
Scott Wood Nov. 7, 2013, 1:20 a.m. UTC | #25
On Wed, 2013-11-06 at 01:50 -0600, Wang Dongsheng-B40534 wrote:
> 
> > -----Original Message-----
> > From: Bhushan Bharat-R65777
> > Sent: Wednesday, November 06, 2013 1:25 PM
> > 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
> > 
> > 
> > 
> > > -----Original Message-----
> > > From: Wang Dongsheng-B40534
> > > Sent: Tuesday, November 05, 2013 8:40 AM
> > > To: Wood Scott-B07421
> > > Cc: Bhushan Bharat-R65777; linuxppc-dev@lists.ozlabs.org
> > > Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and
> > > altivec idle
> > >
> > >
> > >
> > > > -----Original Message-----
> > > > From: Wood Scott-B07421
> > > > Sent: Tuesday, November 05, 2013 5:52 AM
> > > > To: Wang Dongsheng-B40534
> > > > Cc: Wood Scott-B07421; Bhushan Bharat-R65777; linuxppc-
> > > > dev@lists.ozlabs.org
> > > > Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state
> > > > and altivec idle
> > > >
> > > > On Sun, 2013-11-03 at 22:04 -0600, Wang Dongsheng-B40534 wrote:
> > > > > > -----Original Message-----
> > > > > > From: Wang Dongsheng-B40534
> > > > > > Sent: Monday, October 21, 2013 11:11 AM
> > > > > > To: Wood Scott-B07421
> > > > > > Cc: Bhushan Bharat-R65777; linuxppc-dev@lists.ozlabs.org
> > > > > > Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20
> > > > > > state and altivec idle
> > > > > >
> > > > > >
> > > > > >
> > > > > > > -----Original Message-----
> > > > > > > From: Wood Scott-B07421
> > > > > > > Sent: Saturday, October 19, 2013 3:22 AM
> > > > > > > To: Wang Dongsheng-B40534
> > > > > > > Cc: Bhushan Bharat-R65777; Wood Scott-B07421; linuxppc-
> > > > > > > dev@lists.ozlabs.org
> > > > > > > Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20
> > > > > > > state and altivec idle
> > > > > > >
> > > > > > > On Thu, 2013-10-17 at 22:02 -0500, Wang Dongsheng-B40534 wrote:
> > > > > > > >
> > > > > > > > > -----Original Message-----
> > > > > > > > > From: Bhushan Bharat-R65777
> > > > > > > > > Sent: Thursday, October 17, 2013 2:46 PM
> > > > > > > > > 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
> > > > > > > > >
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > > > > -----Original Message-----
> > > > > > > > > > > > From: Wang Dongsheng-B40534
> > > > > > > > > > > > Sent: Thursday, October 17, 2013 11:22 AM
> > > > > > > > > > > > To: Bhushan Bharat-R65777; 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
> > > > > > > > > > > >
> > > > > > > > > > > >
> > > > > > > > > > > >
> > > > > > > > > > > > > -----Original Message-----
> > > > > > > > > > > > > From: Bhushan Bharat-R65777
> > > > > > > > > > > > > Sent: Thursday, October 17, 2013 11:20 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
> > > > > > > > > > > > >
> > > > > > > > > > > > >
> > > > > > > > > > > > >
> > > > > > > > > > > > > > -----Original Message-----
> > > > > > > > > > > > > > From: Wang Dongsheng-B40534
> > > > > > > > > > > > > > Sent: Thursday, October 17, 2013 8:16 AM
> > > > > > > > > > > > > > To: Bhushan Bharat-R65777; 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
> > > > > > > > > > > > > >
> > > > > > > > > > > > > >
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > > -----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
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > -----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; Wang
> > > > > > > > > > > > > > > Dongsheng-B40534
> > > > > > > > > > > > > > > > Subject: [PATCH v5 4/4] powerpc/85xx: add
> > > > > > > > > > > > > > > > sysfs for
> > > > > > > > > > > > > > > > pw20 state and
> > > > > > > > > > > > > > > altivec idle
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > From: Wang Dongsheng
> > > > > > > > > > > > > > > > <dongsheng.wang@freescale.com>
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > Add a sys interface to enable/diable pw20
> > > > > > > > > > > > > > > > state or altivec idle, and
> > > > > > > > > > > > > > > control the
> > > > > > > > > > > > > > > > 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_wa
> > > > > > > > > > > > > > > > it
> > > > > > > > > > > > > > > > _t
> > > > > > > > > > > > > > > > ime
> > > > > > > > > > > > > > > > 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
> > > > > > > > > > > > > > > > <dongsheng.wang@freescale.com>
> > > > > > > > > > > > > > > > ---
> > > > > > > > > > > > > > > > *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.c
> > > > > > > > > > > > > > > index
> > > > > > > > > > > > > > > > 27a90b9..10d1128 100644
> > > > > > > > > > > > > > > > --- a/arch/powerpc/kernel/sysfs.c
> > > > > > > > > > > > > > > > +++ b/arch/powerpc/kernel/sysfs.c
> > > > > > > > > > > > > > > > @@ -85,6 +85,284 @@
> > > > > > > > > > > > > > > > __setup("smt-snooze-delay=",
> > > > > > > > > > > > > > > setup_smt_snooze_delay);
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > >  #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 >= 10000)
> > > > > > > > > > > > > > > > +		cycle = div_u64(ns + 500, 1000) *
> > > > > > > > > tb_ticks_per_usec;
> > > > > > > > > > > > > > > > +	else
> > > > > > > > > > > > > > > > +		cycle = div_u64(ns *
> > > > tb_ticks_per_usec,
> > > > > > > 1000);
> > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > +	if (!cycle)
> > > > > > > > > > > > > > > > +		return 0;
> > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > +	return ilog2(cycle); }
> > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > +static void do_show_pwrmgtcr0(void *val) {
> > > > > > > > > > > > > > > > +	u32 *value = val;
> > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > +	*value = mfspr(SPRN_PWRMGTCR0); }
> > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > +static ssize_t show_pw20_state(struct
> > > > > > > > > > > > > > > > +device
> > > > *dev,
> > > > > > > > > > > > > > > > +				struct device_attribute
> > > > *attr,
> > > > > > > char
> > > > > > > > > *buf) {
> > > > > > > > > > > > > > > > +	u32 value;
> > > > > > > > > > > > > > > > +	unsigned int cpu = dev->id;
> > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > +	smp_call_function_single(cpu,
> > > > > > > > > > > > > > > > +do_show_pwrmgtcr0, &value, 1);
> > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > +	value &= PWRMGTCR0_PW20_WAIT;
> > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > +	return sprintf(buf, "%u\n", value ? 1 :
> > > > 0); }
> > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > +static void do_store_pw20_state(void *val) {
> > > > > > > > > > > > > > > > +	u32 *value = val;
> > > > > > > > > > > > > > > > +	u32 pw20_state;
> > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > +	pw20_state = mfspr(SPRN_PWRMGTCR0);
> > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > +	if (*value)
> > > > > > > > > > > > > > > > +		pw20_state |= PWRMGTCR0_PW20_WAIT;
> > > > > > > > > > > > > > > > +	else
> > > > > > > > > > > > > > > > +		pw20_state &= ~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 = 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 = dev->id;
> > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > +	if (!pw20_wt) {
> > > > > > > > > > > > > > > > +		smp_call_function_single(cpu,
> > > > > > > do_show_pwrmgtcr0,
> > > > > > > > > > > > > > > > +&value,
> > > > > > > > > > > > > 1);
> > > > > > > > > > > > > > > > +		value = (value &
> > > > PWRMGTCR0_PW20_ENT) >>
> > > > > > > > > > > > > > > > +
> > > > 	PWRMGTCR0_PW20_ENT_SHIFT;
> > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > +		tb_cycle = (1 << (MAX_BIT - value)) *
> > > > 2;
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > Is value = 0 and value = 1 legal? These will
> > > > > > > > > > > > > > > make tb_cycle = 0,
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > +		time = div_u64(tb_cycle * 1000,
> > > > > > > tb_ticks_per_usec)
> > > > > > > > > - 1;
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > And time = -1;
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > Please look at the end of the function, :)
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > "return sprintf(buf, "%llu\n", time > 0 ? time :
> > 0);"
> > > > > > > > > > > > >
> > > > > > > > > > > > > I know you return 0 if value = 0/1, my question
> > > > > > > > > > > > > was that, is this correct as per specification?
> > > > > > > > > > > > >
> > > > > > > > > > > > > Ahh, also for "value" upto 7 you will return 0, no?
> > > > > > > > > > > > >
> > > > > > > > > > > > If value = 0, MAX_BIT - value = 63 tb_cycle =
> > > > > > > > > > > > 0xffffffff_ffffffff, tb_cycle * 1000 will overflow,
> > > > > > > > > > > > but this
> > > > > > > situation is not possible.
> > > > > > > > > > > > Because if the "value = 0" means this feature will
> > > > > > > > > > > > be
> > > > > > "disable".
> > > > > > > > > > > > Now The default wait bit is 50(MAX_BIT - value,
> > > > > > > > > > > > value = 13), the PW20/Altivec Idle wait entry time
> > > > > > > > > > > > is about 1ms, this time is very long for wait idle
> > > > > > > > > > > > time, and it's cannot be increased(means (MAX_BIT
> > > > > > > > > > > > - value)
> > > > > > > > > > > cannot greater than 50).
> > > > > > > > > > >
> > > > > > > > > > > What you said is not obvious from code and so at least
> > > > > > > > > > > write a comment that value will be always >= 13 or
> > > > > > > > > > > value will never be less than < 8 and below
> > > > > > > > > > > calculation will not overflow. may be error out if
> > value is less than 8.
> > > > > > > > > > >
> > > > > > > > > > The "value" less than 10, this will overflow.
> > > > > > > > > > There is not error, The code I knew it could not be less
> > > > > > > > > > than 10, that's why I use the following code. :)
> > > > > > > > >
> > > > > > > > > I am sorry to persist but this is not about what you know,
> > > > > > > > > this is about how code is read and code does not say what
> > > > > > > > > you know, so add a comment at least and error out/warn
> > > > > > > > > when "value" is less than a
> > > > > > > certain number.
> > > > > > > > >
> > > > > > > > Sorry for the late to response the mail. If it caused
> > > > > > > > confusion, we can
> > > > > > > add a comment.
> > > > > > > >
> > > > > > > > How about the following comment?
> > > > > > > > /*
> > > > > > > >  * If the "value" less than 10, this will overflow.
> > > > > > > >  * From benchmark test, the default wait bit will not be set
> > > > > > > > less than
> > > > > > > 10bit.
> > > > > > > >  * Because 10 bit corresponds to the wait entry time is
> > > > > > > > 439375573401999609(ns),
> > > > > > > >  * for wait-entry-idle time this value looks too long, and
> > > > > > > > we cannot use those
> > > > > > > >  * "long" time as a default wait-entry time. So overflow
> > > > > > > > could not have happened
> > > > > > > >  * and we use this calculation method to get wait-entry-idle
> > time.
> > > > > > > >  */
> > > > > > >
> > > > > > > If there's to be a limit on the times we accept, make it
> > explicit.
> > > > > > > Check for it before doing any conversions, and return an error
> > > > > > > if userspace tries to set it.
> > > > > > >
> > > > > > The branch only use to read default wait-entry-time.
> > > > > > We have no limit the user's input, and we can't restrict. Once
> > > > > > the user set the wait-entry-time, the code will do another branch.
> > > > > >
> > > > >
> > > > > Hi scott,
> > > > > Do you have any comments about this patch?
> > > > > I will add the comment and send this patch again.
> > > >
> > > > What do you mean by "and we can't restrict"?  Why not?
> > > >
> > > > Why is it only used to read the default, and not the current value?
> > > >
> > > We already have a variable which value is set by the user, as we have
> > > discussed before.
> > >
> > > When the system boot-up. Before user set the wait-entry-time, we need
> > > to return a default wait-entry-time, if the user read this
> > > sys-interface. The default wait-entry-time is converted by wait-bit.
> > >
> > > Once the user set the sys-interface, a variable will be used to save
> > > it. And when the user read sys-interface we will return back the
> > variable.
> > 
> > While we are not "restricting user defined value" or "define same
> > restriction for user defined and default", can we have only one flow of
> > calculation and setting rather than conditional based on user have set or
> > not set?
> > 
> Yes, we can do that.
> If we want to use one flow to handle it. We should do the following changes:
> 
> #ifdef CONFIG_FSL_SOC
> #include <linux/slab.h>
> #endif

Don't ifdef headers.

> static u64 *pw20_wt;
> static u64 *altivec_idle_wt;
> 
> static ssize_t show_pw20_wait_time(struct device *dev,
>                                 struct device_attribute *attr, char *buf)
> {
> 	return sprintf(buf, "%llu\n", pw20_wt[dev->id]);
> }
> 
> static ssize_t store_pw20_wait_time(struct device *dev,
>                                 struct device_attribute *attr,
>                                 const char *buf, size_t count)
> {
> ...
> pw20_wt[cpu] = value;
> ...
> }
> 
> static ssize_t show_altivec_idle_wait_time(struct device *dev,
>                                 struct device_attribute *attr, char *buf)
> {
> 	return sprintf(buf, "%llu\n", altivec_idle_wt[dev->id]);
> }
> 
> static ssize_t store_altivec_idle_wait_time(struct device *dev,
>                                 struct device_attribute *attr,
>                                 const char *buf, size_t count)
> {
> ...
> altivec_idle_wt[cpu] = value;
> ...
> }
> 
> static void register_cpu_online(unsigned int cpu)
> {
> ...
> #ifdef CONFIG_FSL_SOC
>         u32 value, pw20_value, altivec_value;
>         u64 tb_cycle;
> #endif
> ...
> #ifdef CONFIG_FSL_SOC
>         if (PVR_VER(cur_cpu_spec->pvr_value) == PVR_VER_E6500) {
>                 device_create_file(s, &dev_attr_pw20_state);
>                 device_create_file(s, &dev_attr_pw20_wait_time);
> 
>                 device_create_file(s, &dev_attr_altivec_idle);
>                 device_create_file(s, &dev_attr_altivec_idle_wait_time);
>         }
> 
>         if (!pw20_wt)
>                 pw20_wt = kzalloc(nr_cpu_ids * sizeof(*pw20_wt), GFP_KERNEL);
> 
> 	  if (!altivec_idle_wt)
> 		    altivec_idle_wt = kzalloc(nr_cpu_ids * sizeof(*altivec_idle_wt), GFP_KERNEL);
> 
>         smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
> 
>         pw20_value = (value & PWRMGTCR0_PW20_ENT) >> PWRMGTCR0_PW20_ENT_SHIFT;
>         tb_cycle = (1 << (MAX_BIT - pw20_value)) * 2;
>         pw20_wt[cpu] = div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1;
> 
>         altivec_value = (value & PWRMGTCR0_AV_IDLE_CNT) >> PWRMGTCR0_AV_IDLE_CNT_SHIFT;
>         tb_cycle = (1 << (MAX_BIT - altivec_value)) * 2;
>         altivec_idle_wt[cpu] = div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1;
> #endif
> ...
> }

Move this stuff to its own function.  The only ifdef should be in a
header that provides an inline stub when it's not available.

Could you explain what you're changing and why?  A diff from your
previous patch would help.

-Scott
Dongsheng Wang Nov. 7, 2013, 2:17 a.m. UTC | #26
> -----Original Message-----
> From: Wood Scott-B07421
> Sent: Thursday, November 07, 2013 9:20 AM
> To: Wang Dongsheng-B40534
> Cc: Bhushan Bharat-R65777; Wood Scott-B07421; linuxppc-
> dev@lists.ozlabs.org
> Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and
> altivec idle
> 
> On Wed, 2013-11-06 at 01:50 -0600, Wang Dongsheng-B40534 wrote:
> >
> > > -----Original Message-----
> > > From: Bhushan Bharat-R65777
> > > Sent: Wednesday, November 06, 2013 1:25 PM
> > > 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
> > >
> > >
> > >
> > > > -----Original Message-----
> > > > From: Wang Dongsheng-B40534
> > > > Sent: Tuesday, November 05, 2013 8:40 AM
> > > > To: Wood Scott-B07421
> > > > Cc: Bhushan Bharat-R65777; linuxppc-dev@lists.ozlabs.org
> > > > Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state
> > > > and altivec idle
> > > >
> > > >
> > > >
> > > > > -----Original Message-----
> > > > > From: Wood Scott-B07421
> > > > > Sent: Tuesday, November 05, 2013 5:52 AM
> > > > > To: Wang Dongsheng-B40534
> > > > > Cc: Wood Scott-B07421; Bhushan Bharat-R65777; linuxppc-
> > > > > dev@lists.ozlabs.org
> > > > > Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20
> > > > > state and altivec idle
> > > > >
> > > > > On Sun, 2013-11-03 at 22:04 -0600, Wang Dongsheng-B40534 wrote:
> > > > > > > -----Original Message-----
> > > > > > > From: Wang Dongsheng-B40534
> > > > > > > Sent: Monday, October 21, 2013 11:11 AM
> > > > > > > To: Wood Scott-B07421
> > > > > > > Cc: Bhushan Bharat-R65777; linuxppc-dev@lists.ozlabs.org
> > > > > > > Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20
> > > > > > > state and altivec idle
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > > -----Original Message-----
> > > > > > > > From: Wood Scott-B07421
> > > > > > > > Sent: Saturday, October 19, 2013 3:22 AM
> > > > > > > > To: Wang Dongsheng-B40534
> > > > > > > > Cc: Bhushan Bharat-R65777; Wood Scott-B07421; linuxppc-
> > > > > > > > dev@lists.ozlabs.org
> > > > > > > > Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for
> > > > > > > > pw20 state and altivec idle
> > > > > > > >
> > > > > > > > On Thu, 2013-10-17 at 22:02 -0500, Wang Dongsheng-B40534
> wrote:
> > > > > > > > >
> > > > > > > > > > -----Original Message-----
> > > > > > > > > > From: Bhushan Bharat-R65777
> > > > > > > > > > Sent: Thursday, October 17, 2013 2:46 PM
> > > > > > > > > > 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
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > > > > -----Original Message-----
> > > > > > > > > > > > > From: Wang Dongsheng-B40534
> > > > > > > > > > > > > Sent: Thursday, October 17, 2013 11:22 AM
> > > > > > > > > > > > > To: Bhushan Bharat-R65777; 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
> > > > > > > > > > > > >
> > > > > > > > > > > > >
> > > > > > > > > > > > >
> > > > > > > > > > > > > > -----Original Message-----
> > > > > > > > > > > > > > From: Bhushan Bharat-R65777
> > > > > > > > > > > > > > Sent: Thursday, October 17, 2013 11:20 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
> > > > > > > > > > > > > >
> > > > > > > > > > > > > >
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > > -----Original Message-----
> > > > > > > > > > > > > > > From: Wang Dongsheng-B40534
> > > > > > > > > > > > > > > Sent: Thursday, October 17, 2013 8:16 AM
> > > > > > > > > > > > > > > To: Bhushan Bharat-R65777; 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
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > -----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
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > -----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; Wang
> > > > > > > > > > > > > > > > Dongsheng-B40534
> > > > > > > > > > > > > > > > > Subject: [PATCH v5 4/4] powerpc/85xx:
> > > > > > > > > > > > > > > > > add sysfs for
> > > > > > > > > > > > > > > > > pw20 state and
> > > > > > > > > > > > > > > > altivec idle
> > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > From: Wang Dongsheng
> > > > > > > > > > > > > > > > > <dongsheng.wang@freescale.com>
> > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > Add a sys interface to enable/diable
> > > > > > > > > > > > > > > > > pw20 state or altivec idle, and
> > > > > > > > > > > > > > > > control the
> > > > > > > > > > > > > > > > > wait entry time.
> > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > Enable/Disable interface:
> > > > > > > > > > > > > > > > > 0, disable. 1, enable.
> > > > > > > > > > > > > > > > > /sys/devices/system/cpu/cpuX/pw20_state
> > > > > > > > > > > > > > > > > /sys/devices/system/cpu/cpuX/altivec_idl
> > > > > > > > > > > > > > > > > e
> > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > Set wait time interface:(Nanosecond)
> > > > > > > > > > > > > > > > > /sys/devices/system/cpu/cpuX/pw20_wait_t
> > > > > > > > > > > > > > > > > ime
> > > > > > > > > > > > > > > > > /sys/devices/system/cpu/cpuX/altivec_idl
> > > > > > > > > > > > > > > > > e_wa
> > > > > > > > > > > > > > > > > it
> > > > > > > > > > > > > > > > > _t
> > > > > > > > > > > > > > > > > ime
> > > > > > > > > > > > > > > > > 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
> > > > > > > > > > > > > > > > > <dongsheng.wang@freescale.com>
> > > > > > > > > > > > > > > > > ---
> > > > > > > > > > > > > > > > > *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.c
> > > > > > > > > > > > > > > > index
> > > > > > > > > > > > > > > > > 27a90b9..10d1128 100644
> > > > > > > > > > > > > > > > > --- a/arch/powerpc/kernel/sysfs.c
> > > > > > > > > > > > > > > > > +++ b/arch/powerpc/kernel/sysfs.c
> > > > > > > > > > > > > > > > > @@ -85,6 +85,284 @@
> > > > > > > > > > > > > > > > > __setup("smt-snooze-delay=",
> > > > > > > > > > > > > > > > setup_smt_snooze_delay);
> > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > >  #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 >= 10000)
> > > > > > > > > > > > > > > > > +		cycle = div_u64(ns + 500, 1000)
> *
> > > > > > > > > > tb_ticks_per_usec;
> > > > > > > > > > > > > > > > > +	else
> > > > > > > > > > > > > > > > > +		cycle = div_u64(ns *
> > > > > tb_ticks_per_usec,
> > > > > > > > 1000);
> > > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > > +	if (!cycle)
> > > > > > > > > > > > > > > > > +		return 0;
> > > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > > +	return ilog2(cycle); }
> > > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > > +static void do_show_pwrmgtcr0(void *val)
> {
> > > > > > > > > > > > > > > > > +	u32 *value = val;
> > > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > > +	*value = mfspr(SPRN_PWRMGTCR0); }
> > > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > > +static ssize_t show_pw20_state(struct
> > > > > > > > > > > > > > > > > +device
> > > > > *dev,
> > > > > > > > > > > > > > > > > +				struct
> device_attribute
> > > > > *attr,
> > > > > > > > char
> > > > > > > > > > *buf) {
> > > > > > > > > > > > > > > > > +	u32 value;
> > > > > > > > > > > > > > > > > +	unsigned int cpu = dev->id;
> > > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > > +	smp_call_function_single(cpu,
> > > > > > > > > > > > > > > > > +do_show_pwrmgtcr0, &value, 1);
> > > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > > +	value &= PWRMGTCR0_PW20_WAIT;
> > > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > > +	return sprintf(buf, "%u\n", value ?
> 1 :
> > > > > 0); }
> > > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > > +static void do_store_pw20_state(void
> *val) {
> > > > > > > > > > > > > > > > > +	u32 *value = val;
> > > > > > > > > > > > > > > > > +	u32 pw20_state;
> > > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > > +	pw20_state = mfspr(SPRN_PWRMGTCR0);
> > > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > > +	if (*value)
> > > > > > > > > > > > > > > > > +		pw20_state |=
> PWRMGTCR0_PW20_WAIT;
> > > > > > > > > > > > > > > > > +	else
> > > > > > > > > > > > > > > > > +		pw20_state &=
> ~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 = 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 = dev->id;
> > > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > > +	if (!pw20_wt) {
> > > > > > > > > > > > > > > > > +		smp_call_function_single(cpu,
> > > > > > > > do_show_pwrmgtcr0,
> > > > > > > > > > > > > > > > > +&value,
> > > > > > > > > > > > > > 1);
> > > > > > > > > > > > > > > > > +		value = (value &
> > > > > PWRMGTCR0_PW20_ENT) >>
> > > > > > > > > > > > > > > > > +
> > > > > 	PWRMGTCR0_PW20_ENT_SHIFT;
> > > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > > +		tb_cycle = (1 << (MAX_BIT -
> value)) *
> > > > > 2;
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > Is value = 0 and value = 1 legal? These
> > > > > > > > > > > > > > > > will make tb_cycle = 0,
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > +		time = div_u64(tb_cycle * 1000,
> > > > > > > > tb_ticks_per_usec)
> > > > > > > > > > - 1;
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > And time = -1;
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > Please look at the end of the function, :)
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > "return sprintf(buf, "%llu\n", time > 0 ?
> time :
> > > 0);"
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > I know you return 0 if value = 0/1, my
> > > > > > > > > > > > > > question was that, is this correct as per
> specification?
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > Ahh, also for "value" upto 7 you will return 0,
> no?
> > > > > > > > > > > > > >
> > > > > > > > > > > > > If value = 0, MAX_BIT - value = 63 tb_cycle =
> > > > > > > > > > > > > 0xffffffff_ffffffff, tb_cycle * 1000 will
> > > > > > > > > > > > > overflow, but this
> > > > > > > > situation is not possible.
> > > > > > > > > > > > > Because if the "value = 0" means this feature
> > > > > > > > > > > > > will be
> > > > > > > "disable".
> > > > > > > > > > > > > Now The default wait bit is 50(MAX_BIT - value,
> > > > > > > > > > > > > value = 13), the PW20/Altivec Idle wait entry
> > > > > > > > > > > > > time is about 1ms, this time is very long for
> > > > > > > > > > > > > wait idle time, and it's cannot be
> > > > > > > > > > > > > increased(means (MAX_BIT
> > > > > > > > > > > > > - value)
> > > > > > > > > > > > cannot greater than 50).
> > > > > > > > > > > >
> > > > > > > > > > > > What you said is not obvious from code and so at
> > > > > > > > > > > > least write a comment that value will be always >=
> > > > > > > > > > > > 13 or value will never be less than < 8 and below
> > > > > > > > > > > > calculation will not overflow. may be error out if
> > > value is less than 8.
> > > > > > > > > > > >
> > > > > > > > > > > The "value" less than 10, this will overflow.
> > > > > > > > > > > There is not error, The code I knew it could not be
> > > > > > > > > > > less than 10, that's why I use the following code.
> > > > > > > > > > > :)
> > > > > > > > > >
> > > > > > > > > > I am sorry to persist but this is not about what you
> > > > > > > > > > know, this is about how code is read and code does not
> > > > > > > > > > say what you know, so add a comment at least and error
> > > > > > > > > > out/warn when "value" is less than a
> > > > > > > > certain number.
> > > > > > > > > >
> > > > > > > > > Sorry for the late to response the mail. If it caused
> > > > > > > > > confusion, we can
> > > > > > > > add a comment.
> > > > > > > > >
> > > > > > > > > How about the following comment?
> > > > > > > > > /*
> > > > > > > > >  * If the "value" less than 10, this will overflow.
> > > > > > > > >  * From benchmark test, the default wait bit will not be
> > > > > > > > > set less than
> > > > > > > > 10bit.
> > > > > > > > >  * Because 10 bit corresponds to the wait entry time is
> > > > > > > > > 439375573401999609(ns),
> > > > > > > > >  * for wait-entry-idle time this value looks too long,
> > > > > > > > > and we cannot use those
> > > > > > > > >  * "long" time as a default wait-entry time. So overflow
> > > > > > > > > could not have happened
> > > > > > > > >  * and we use this calculation method to get
> > > > > > > > > wait-entry-idle
> > > time.
> > > > > > > > >  */
> > > > > > > >
> > > > > > > > If there's to be a limit on the times we accept, make it
> > > explicit.
> > > > > > > > Check for it before doing any conversions, and return an
> > > > > > > > error if userspace tries to set it.
> > > > > > > >
> > > > > > > The branch only use to read default wait-entry-time.
> > > > > > > We have no limit the user's input, and we can't restrict.
> > > > > > > Once the user set the wait-entry-time, the code will do
> another branch.
> > > > > > >
> > > > > >
> > > > > > Hi scott,
> > > > > > Do you have any comments about this patch?
> > > > > > I will add the comment and send this patch again.
> > > > >
> > > > > What do you mean by "and we can't restrict"?  Why not?
> > > > >
> > > > > Why is it only used to read the default, and not the current
> value?
> > > > >
> > > > We already have a variable which value is set by the user, as we
> > > > have discussed before.
> > > >
> > > > When the system boot-up. Before user set the wait-entry-time, we
> > > > need to return a default wait-entry-time, if the user read this
> > > > sys-interface. The default wait-entry-time is converted by wait-bit.
> > > >
> > > > Once the user set the sys-interface, a variable will be used to
> > > > save it. And when the user read sys-interface we will return back
> > > > the
> > > variable.
> > >
> > > While we are not "restricting user defined value" or "define same
> > > restriction for user defined and default", can we have only one flow
> > > of calculation and setting rather than conditional based on user
> > > have set or not set?
> > >
> > Yes, we can do that.
> > If we want to use one flow to handle it. We should do the following
> changes:
> >
> > #ifdef CONFIG_FSL_SOC
> > #include <linux/slab.h>
> > #endif
> 
> Don't ifdef headers.
> 
> > static u64 *pw20_wt;
> > static u64 *altivec_idle_wt;
> >
> > static ssize_t show_pw20_wait_time(struct device *dev,
> >                                 struct device_attribute *attr, char
> > *buf) {
> > 	return sprintf(buf, "%llu\n", pw20_wt[dev->id]); }
> >
> > static ssize_t store_pw20_wait_time(struct device *dev,
> >                                 struct device_attribute *attr,
> >                                 const char *buf, size_t count) { ...
> > pw20_wt[cpu] = value;
> > ...
> > }
> >
> > static ssize_t show_altivec_idle_wait_time(struct device *dev,
> >                                 struct device_attribute *attr, char
> > *buf) {
> > 	return sprintf(buf, "%llu\n", altivec_idle_wt[dev->id]); }
> >
> > static ssize_t store_altivec_idle_wait_time(struct device *dev,
> >                                 struct device_attribute *attr,
> >                                 const char *buf, size_t count) { ...
> > altivec_idle_wt[cpu] = value;
> > ...
> > }
> >
> > static void register_cpu_online(unsigned int cpu) { ...
> > #ifdef CONFIG_FSL_SOC
> >         u32 value, pw20_value, altivec_value;
> >         u64 tb_cycle;
> > #endif
> > ...
> > #ifdef CONFIG_FSL_SOC
> >         if (PVR_VER(cur_cpu_spec->pvr_value) == PVR_VER_E6500) {
> >                 device_create_file(s, &dev_attr_pw20_state);
> >                 device_create_file(s, &dev_attr_pw20_wait_time);
> >
> >                 device_create_file(s, &dev_attr_altivec_idle);
> >                 device_create_file(s, &dev_attr_altivec_idle_wait_time);
> >         }
> >
> >         if (!pw20_wt)
> >                 pw20_wt = kzalloc(nr_cpu_ids * sizeof(*pw20_wt),
> > GFP_KERNEL);
> >
> > 	  if (!altivec_idle_wt)
> > 		    altivec_idle_wt = kzalloc(nr_cpu_ids *
> sizeof(*altivec_idle_wt),
> > GFP_KERNEL);
> >
> >         smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
> >
> >         pw20_value = (value & PWRMGTCR0_PW20_ENT) >>
> PWRMGTCR0_PW20_ENT_SHIFT;
> >         tb_cycle = (1 << (MAX_BIT - pw20_value)) * 2;
> >         pw20_wt[cpu] = div_u64(tb_cycle * 1000, tb_ticks_per_usec) -
> > 1;
> >
> >         altivec_value = (value & PWRMGTCR0_AV_IDLE_CNT) >>
> PWRMGTCR0_AV_IDLE_CNT_SHIFT;
> >         tb_cycle = (1 << (MAX_BIT - altivec_value)) * 2;
> >         altivec_idle_wt[cpu] = div_u64(tb_cycle * 1000,
> > tb_ticks_per_usec) - 1; #endif ...
> > }
> 
> Move this stuff to its own function.  The only ifdef should be in a
> header that provides an inline stub when it's not available.
> 
> Could you explain what you're changing and why?  A diff from your
> previous patch would help.
> 
Those codes just for discuss with Bharat. He want to make one flow at "show_pw20_wait_time"/" show_altivec_idle_wait_time" function. If we do that, we need to initialize pw20_wt/altivec_idle_wt.

-dongsheng
Dongsheng Wang Nov. 11, 2013, 2:13 a.m. UTC | #27
> -----Original Message-----
> From: Wang Dongsheng-B40534
> Sent: Thursday, November 07, 2013 10:13 AM
> To: Wood Scott-B07421
> Cc: Bhushan Bharat-R65777; linuxppc-dev@lists.ozlabs.org
> Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and
> altivec idle
> 
> 
> 
> > -----Original Message-----
> > From: Wood Scott-B07421
> > Sent: Thursday, November 07, 2013 9:20 AM
> > To: Wang Dongsheng-B40534
> > Cc: Bhushan Bharat-R65777; Wood Scott-B07421; linuxppc-
> > dev@lists.ozlabs.org
> > Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20 state and
> > altivec idle
> >
> > On Wed, 2013-11-06 at 01:50 -0600, Wang Dongsheng-B40534 wrote:
> > >
> > > > -----Original Message-----
> > > > From: Bhushan Bharat-R65777
> > > > Sent: Wednesday, November 06, 2013 1:25 PM
> > > > 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
> > > >
> > > >
> > > >
> > > > > -----Original Message-----
> > > > > From: Wang Dongsheng-B40534
> > > > > Sent: Tuesday, November 05, 2013 8:40 AM
> > > > > To: Wood Scott-B07421
> > > > > Cc: Bhushan Bharat-R65777; linuxppc-dev@lists.ozlabs.org
> > > > > Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20
> state
> > > > > and altivec idle
> > > > >
> > > > >
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: Wood Scott-B07421
> > > > > > Sent: Tuesday, November 05, 2013 5:52 AM
> > > > > > To: Wang Dongsheng-B40534
> > > > > > Cc: Wood Scott-B07421; Bhushan Bharat-R65777; linuxppc-
> > > > > > dev@lists.ozlabs.org
> > > > > > Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for pw20
> > > > > > state and altivec idle
> > > > > >
> > > > > > On Sun, 2013-11-03 at 22:04 -0600, Wang Dongsheng-B40534 wrote:
> > > > > > > > -----Original Message-----
> > > > > > > > From: Wang Dongsheng-B40534
> > > > > > > > Sent: Monday, October 21, 2013 11:11 AM
> > > > > > > > To: Wood Scott-B07421
> > > > > > > > Cc: Bhushan Bharat-R65777; linuxppc-dev@lists.ozlabs.org
> > > > > > > > Subject: RE: [PATCH v5 4/4] powerpc/85xx: add sysfs for
> pw20
> > > > > > > > state and altivec idle
> > > > > > > >
> > > > > > > >
> > > > > > > >
> > > > > > > > > -----Original Message-----
> > > > > > > > > From: Wood Scott-B07421
> > > > > > > > > Sent: Saturday, October 19, 2013 3:22 AM
> > > > > > > > > To: Wang Dongsheng-B40534
> > > > > > > > > Cc: Bhushan Bharat-R65777; Wood Scott-B07421; linuxppc-
> > > > > > > > > dev@lists.ozlabs.org
> > > > > > > > > Subject: Re: [PATCH v5 4/4] powerpc/85xx: add sysfs for
> > > > > > > > > pw20 state and altivec idle
> > > > > > > > >
> > > > > > > > > On Thu, 2013-10-17 at 22:02 -0500, Wang Dongsheng-B40534
> > wrote:
> > > > > > > > > >
> > > > > > > > > > > -----Original Message-----
> > > > > > > > > > > From: Bhushan Bharat-R65777
> > > > > > > > > > > Sent: Thursday, October 17, 2013 2:46 PM
> > > > > > > > > > > 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
> > > > > > > > > > >
> > > > > > > > > > >
> > > > > > > > > > >
> > > > > > > > > > > > > > -----Original Message-----
> > > > > > > > > > > > > > From: Wang Dongsheng-B40534
> > > > > > > > > > > > > > Sent: Thursday, October 17, 2013 11:22 AM
> > > > > > > > > > > > > > To: Bhushan Bharat-R65777; 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
> > > > > > > > > > > > > >
> > > > > > > > > > > > > >
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > > -----Original Message-----
> > > > > > > > > > > > > > > From: Bhushan Bharat-R65777
> > > > > > > > > > > > > > > Sent: Thursday, October 17, 2013 11:20 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
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > -----Original Message-----
> > > > > > > > > > > > > > > > From: Wang Dongsheng-B40534
> > > > > > > > > > > > > > > > Sent: Thursday, October 17, 2013 8:16 AM
> > > > > > > > > > > > > > > > To: Bhushan Bharat-R65777; 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
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > -----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
> > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > -----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; Wang
> > > > > > > > > > > > > > > > > Dongsheng-B40534
> > > > > > > > > > > > > > > > > > Subject: [PATCH v5 4/4] powerpc/85xx:
> > > > > > > > > > > > > > > > > > add sysfs for
> > > > > > > > > > > > > > > > > > pw20 state and
> > > > > > > > > > > > > > > > > altivec idle
> > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > From: Wang Dongsheng
> > > > > > > > > > > > > > > > > > <dongsheng.wang@freescale.com>
> > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > Add a sys interface to enable/diable
> > > > > > > > > > > > > > > > > > pw20 state or altivec idle, and
> > > > > > > > > > > > > > > > > control the
> > > > > > > > > > > > > > > > > > wait entry time.
> > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > Enable/Disable interface:
> > > > > > > > > > > > > > > > > > 0, disable. 1, enable.
> > > > > > > > > > > > > > > > > > /sys/devices/system/cpu/cpuX/pw20_state
> > > > > > > > > > > > > > > > > >
> /sys/devices/system/cpu/cpuX/altivec_idl
> > > > > > > > > > > > > > > > > > e
> > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > Set wait time interface:(Nanosecond)
> > > > > > > > > > > > > > > > > >
> /sys/devices/system/cpu/cpuX/pw20_wait_t
> > > > > > > > > > > > > > > > > > ime
> > > > > > > > > > > > > > > > > >
> /sys/devices/system/cpu/cpuX/altivec_idl
> > > > > > > > > > > > > > > > > > e_wa
> > > > > > > > > > > > > > > > > > it
> > > > > > > > > > > > > > > > > > _t
> > > > > > > > > > > > > > > > > > ime
> > > > > > > > > > > > > > > > > > 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
> > > > > > > > > > > > > > > > > > <dongsheng.wang@freescale.com>
> > > > > > > > > > > > > > > > > > ---
> > > > > > > > > > > > > > > > > > *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.c
> > > > > > > > > > > > > > > > > index
> > > > > > > > > > > > > > > > > > 27a90b9..10d1128 100644
> > > > > > > > > > > > > > > > > > --- a/arch/powerpc/kernel/sysfs.c
> > > > > > > > > > > > > > > > > > +++ b/arch/powerpc/kernel/sysfs.c
> > > > > > > > > > > > > > > > > > @@ -85,6 +85,284 @@
> > > > > > > > > > > > > > > > > > __setup("smt-snooze-delay=",
> > > > > > > > > > > > > > > > > setup_smt_snooze_delay);
> > > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > >  #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 >= 10000)
> > > > > > > > > > > > > > > > > > +		cycle = div_u64(ns + 500, 1000)
> > *
> > > > > > > > > > > tb_ticks_per_usec;
> > > > > > > > > > > > > > > > > > +	else
> > > > > > > > > > > > > > > > > > +		cycle = div_u64(ns *
> > > > > > tb_ticks_per_usec,
> > > > > > > > > 1000);
> > > > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > > > +	if (!cycle)
> > > > > > > > > > > > > > > > > > +		return 0;
> > > > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > > > +	return ilog2(cycle); }
> > > > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > > > +static void do_show_pwrmgtcr0(void
> *val)
> > {
> > > > > > > > > > > > > > > > > > +	u32 *value = val;
> > > > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > > > +	*value = mfspr(SPRN_PWRMGTCR0); }
> > > > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > > > +static ssize_t show_pw20_state(struct
> > > > > > > > > > > > > > > > > > +device
> > > > > > *dev,
> > > > > > > > > > > > > > > > > > +				struct
> > device_attribute
> > > > > > *attr,
> > > > > > > > > char
> > > > > > > > > > > *buf) {
> > > > > > > > > > > > > > > > > > +	u32 value;
> > > > > > > > > > > > > > > > > > +	unsigned int cpu = dev->id;
> > > > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > > > +	smp_call_function_single(cpu,
> > > > > > > > > > > > > > > > > > +do_show_pwrmgtcr0, &value, 1);
> > > > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > > > +	value &= PWRMGTCR0_PW20_WAIT;
> > > > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > > > +	return sprintf(buf, "%u\n", value ?
> > 1 :
> > > > > > 0); }
> > > > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > > > +static void do_store_pw20_state(void
> > *val) {
> > > > > > > > > > > > > > > > > > +	u32 *value = val;
> > > > > > > > > > > > > > > > > > +	u32 pw20_state;
> > > > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > > > +	pw20_state = mfspr(SPRN_PWRMGTCR0);
> > > > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > > > +	if (*value)
> > > > > > > > > > > > > > > > > > +		pw20_state |=
> > PWRMGTCR0_PW20_WAIT;
> > > > > > > > > > > > > > > > > > +	else
> > > > > > > > > > > > > > > > > > +		pw20_state &=
> > ~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 = 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 = dev->id;
> > > > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > > > +	if (!pw20_wt) {
> > > > > > > > > > > > > > > > > > +		smp_call_function_single(cpu,
> > > > > > > > > do_show_pwrmgtcr0,
> > > > > > > > > > > > > > > > > > +&value,
> > > > > > > > > > > > > > > 1);
> > > > > > > > > > > > > > > > > > +		value = (value &
> > > > > > PWRMGTCR0_PW20_ENT) >>
> > > > > > > > > > > > > > > > > > +
> > > > > > 	PWRMGTCR0_PW20_ENT_SHIFT;
> > > > > > > > > > > > > > > > > > +
> > > > > > > > > > > > > > > > > > +		tb_cycle = (1 << (MAX_BIT -
> > value)) *
> > > > > > 2;
> > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > Is value = 0 and value = 1 legal? These
> > > > > > > > > > > > > > > > > will make tb_cycle = 0,
> > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > > +		time = div_u64(tb_cycle * 1000,
> > > > > > > > > tb_ticks_per_usec)
> > > > > > > > > > > - 1;
> > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > > And time = -1;
> > > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > Please look at the end of the function, :)
> > > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > > "return sprintf(buf, "%llu\n", time > 0 ?
> > time :
> > > > 0);"
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > I know you return 0 if value = 0/1, my
> > > > > > > > > > > > > > > question was that, is this correct as per
> > specification?
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > > Ahh, also for "value" upto 7 you will return
> 0,
> > no?
> > > > > > > > > > > > > > >
> > > > > > > > > > > > > > If value = 0, MAX_BIT - value = 63 tb_cycle =
> > > > > > > > > > > > > > 0xffffffff_ffffffff, tb_cycle * 1000 will
> > > > > > > > > > > > > > overflow, but this
> > > > > > > > > situation is not possible.
> > > > > > > > > > > > > > Because if the "value = 0" means this feature
> > > > > > > > > > > > > > will be
> > > > > > > > "disable".
> > > > > > > > > > > > > > Now The default wait bit is 50(MAX_BIT - value,
> > > > > > > > > > > > > > value = 13), the PW20/Altivec Idle wait entry
> > > > > > > > > > > > > > time is about 1ms, this time is very long for
> > > > > > > > > > > > > > wait idle time, and it's cannot be
> > > > > > > > > > > > > > increased(means (MAX_BIT
> > > > > > > > > > > > > > - value)
> > > > > > > > > > > > > cannot greater than 50).
> > > > > > > > > > > > >
> > > > > > > > > > > > > What you said is not obvious from code and so at
> > > > > > > > > > > > > least write a comment that value will be
> always >=
> > > > > > > > > > > > > 13 or value will never be less than < 8 and below
> > > > > > > > > > > > > calculation will not overflow. may be error out
> if
> > > > value is less than 8.
> > > > > > > > > > > > >
> > > > > > > > > > > > The "value" less than 10, this will overflow.
> > > > > > > > > > > > There is not error, The code I knew it could not be
> > > > > > > > > > > > less than 10, that's why I use the following code.
> > > > > > > > > > > > :)
> > > > > > > > > > >
> > > > > > > > > > > I am sorry to persist but this is not about what you
> > > > > > > > > > > know, this is about how code is read and code does
> not
> > > > > > > > > > > say what you know, so add a comment at least and
> error
> > > > > > > > > > > out/warn when "value" is less than a
> > > > > > > > > certain number.
> > > > > > > > > > >
> > > > > > > > > > Sorry for the late to response the mail. If it caused
> > > > > > > > > > confusion, we can
> > > > > > > > > add a comment.
> > > > > > > > > >
> > > > > > > > > > How about the following comment?
> > > > > > > > > > /*
> > > > > > > > > >  * If the "value" less than 10, this will overflow.
> > > > > > > > > >  * From benchmark test, the default wait bit will not
> be
> > > > > > > > > > set less than
> > > > > > > > > 10bit.
> > > > > > > > > >  * Because 10 bit corresponds to the wait entry time is
> > > > > > > > > > 439375573401999609(ns),
> > > > > > > > > >  * for wait-entry-idle time this value looks too long,
> > > > > > > > > > and we cannot use those
> > > > > > > > > >  * "long" time as a default wait-entry time. So
> overflow
> > > > > > > > > > could not have happened
> > > > > > > > > >  * and we use this calculation method to get
> > > > > > > > > > wait-entry-idle
> > > > time.
> > > > > > > > > >  */
> > > > > > > > >
> > > > > > > > > If there's to be a limit on the times we accept, make it
> > > > explicit.
> > > > > > > > > Check for it before doing any conversions, and return an
> > > > > > > > > error if userspace tries to set it.
> > > > > > > > >
> > > > > > > > The branch only use to read default wait-entry-time.
> > > > > > > > We have no limit the user's input, and we can't restrict.
> > > > > > > > Once the user set the wait-entry-time, the code will do
> > another branch.
> > > > > > > >
> > > > > > >
> > > > > > > Hi scott,
> > > > > > > Do you have any comments about this patch?
> > > > > > > I will add the comment and send this patch again.
> > > > > >
> > > > > > What do you mean by "and we can't restrict"?  Why not?
> > > > > >
> > > > > > Why is it only used to read the default, and not the current
> > value?
> > > > > >
> > > > > We already have a variable which value is set by the user, as we
> > > > > have discussed before.
> > > > >
> > > > > When the system boot-up. Before user set the wait-entry-time, we
> > > > > need to return a default wait-entry-time, if the user read this
> > > > > sys-interface. The default wait-entry-time is converted by wait-
> bit.
> > > > >
> > > > > Once the user set the sys-interface, a variable will be used to
> > > > > save it. And when the user read sys-interface we will return back
> > > > > the
> > > > variable.
> > > >
> > > > While we are not "restricting user defined value" or "define same
> > > > restriction for user defined and default", can we have only one
> flow
> > > > of calculation and setting rather than conditional based on user
> > > > have set or not set?
> > > >
> > > Yes, we can do that.
> > > If we want to use one flow to handle it. We should do the following
> > changes:
> > >
> > > #ifdef CONFIG_FSL_SOC
> > > #include <linux/slab.h>
> > > #endif
> >
> > Don't ifdef headers.
> >
> > > static u64 *pw20_wt;
> > > static u64 *altivec_idle_wt;
> > >
> > > static ssize_t show_pw20_wait_time(struct device *dev,
> > >                                 struct device_attribute *attr, char
> > > *buf) {
> > > 	return sprintf(buf, "%llu\n", pw20_wt[dev->id]); }
> > >
> > > static ssize_t store_pw20_wait_time(struct device *dev,
> > >                                 struct device_attribute *attr,
> > >                                 const char *buf, size_t count) { ...
> > > pw20_wt[cpu] = value;
> > > ...
> > > }
> > >
> > > static ssize_t show_altivec_idle_wait_time(struct device *dev,
> > >                                 struct device_attribute *attr, char
> > > *buf) {
> > > 	return sprintf(buf, "%llu\n", altivec_idle_wt[dev->id]); }
> > >
> > > static ssize_t store_altivec_idle_wait_time(struct device *dev,
> > >                                 struct device_attribute *attr,
> > >                                 const char *buf, size_t count) { ...
> > > altivec_idle_wt[cpu] = value;
> > > ...
> > > }
> > >
> > > static void register_cpu_online(unsigned int cpu) { ...
> > > #ifdef CONFIG_FSL_SOC
> > >         u32 value, pw20_value, altivec_value;
> > >         u64 tb_cycle;
> > > #endif
> > > ...
> > > #ifdef CONFIG_FSL_SOC
> > >         if (PVR_VER(cur_cpu_spec->pvr_value) == PVR_VER_E6500) {
> > >                 device_create_file(s, &dev_attr_pw20_state);
> > >                 device_create_file(s, &dev_attr_pw20_wait_time);
> > >
> > >                 device_create_file(s, &dev_attr_altivec_idle);
> > >                 device_create_file(s,
> &dev_attr_altivec_idle_wait_time);
> > >         }
> > >
> > >         if (!pw20_wt)
> > >                 pw20_wt = kzalloc(nr_cpu_ids * sizeof(*pw20_wt),
> > > GFP_KERNEL);
> > >
> > > 	  if (!altivec_idle_wt)
> > > 		    altivec_idle_wt = kzalloc(nr_cpu_ids *
> > sizeof(*altivec_idle_wt),
> > > GFP_KERNEL);
> > >
> > >         smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
> > >
> > >         pw20_value = (value & PWRMGTCR0_PW20_ENT) >>
> > PWRMGTCR0_PW20_ENT_SHIFT;
> > >         tb_cycle = (1 << (MAX_BIT - pw20_value)) * 2;
> > >         pw20_wt[cpu] = div_u64(tb_cycle * 1000, tb_ticks_per_usec) -
> > > 1;
> > >
> > >         altivec_value = (value & PWRMGTCR0_AV_IDLE_CNT) >>
> > PWRMGTCR0_AV_IDLE_CNT_SHIFT;
> > >         tb_cycle = (1 << (MAX_BIT - altivec_value)) * 2;
> > >         altivec_idle_wt[cpu] = div_u64(tb_cycle * 1000,
> > > tb_ticks_per_usec) - 1; #endif ...
> > > }
> >
> > Move this stuff to its own function.  The only ifdef should be in a
> > header that provides an inline stub when it's not available.
> >
> > Could you explain what you're changing and why?  A diff from your
> > previous patch would help.
> >
> Those codes just for discuss with Bharat. He want to make one flow at
> "show_pw20_wait_time"/" show_altivec_idle_wait_time" function. If we do
> that, we need to initialize pw20_wt/altivec_idle_wt.
> 
I will keep this stuff at "show_pw20_wait_time"/"show_altivec_idle_wait_time" and add a comment before our discussion.

/*
 * If the "value" less than 10, this will overflow.
 * From benchmark test, the default wait bit will not be set less than 10bit.
 * Because 10 bit corresponds to the wait entry time is 439375573401999609(ns),
 * for wait-entry-idle time this value looks too long, and we cannot use those
 * "long" time as a default wait-entry time. So overflow could not have happened
 * and we use this calculation method to get wait-entry-idle time.
 */
> -dongsheng
Bharat Bhushan Nov. 11, 2013, 4:11 a.m. UTC | #28
> > Those codes just for discuss with Bharat. He want to make one flow at
> > "show_pw20_wait_time"/" show_altivec_idle_wait_time" function. If we
> > do that, we need to initialize pw20_wt/altivec_idle_wt.
> >
> I will keep this stuff at "show_pw20_wait_time"/"show_altivec_idle_wait_time"
> and add a comment before our discussion.
> 
> /*
>  * If the "value" less than 10, this will overflow.
>  * From benchmark test, the default wait bit will not be set less than 10bit.
>  * Because 10 bit corresponds to the wait entry time is 439375573401999609(ns),
>  * for wait-entry-idle time this value looks too long, and we cannot use those
>  * "long" time as a default wait-entry time. So overflow could not have happened
>  * and we use this calculation method to get wait-entry-idle time.
>  */

I think now we will use same calculation code for default value and user set value, so adding the comment is not sufficient, we should error out from the code if value is less than 10. As default value is not less than 10 so this will always work with default value but if user tries to set less than 10 then error out and ask user to try more than 9.

-Bharat
Dongsheng Wang Dec. 16, 2013, 5:53 a.m. UTC | #29
> -----Original Message-----
> From: Bhushan Bharat-R65777
> Sent: Monday, November 11, 2013 12:11 PM
> 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
> 
> > > Those codes just for discuss with Bharat. He want to make one flow at
> > > "show_pw20_wait_time"/" show_altivec_idle_wait_time" function. If we
> > > do that, we need to initialize pw20_wt/altivec_idle_wt.
> > >
> > I will keep this stuff at "show_pw20_wait_time"/"show_altivec_idle_wait_time"
> > and add a comment before our discussion.
> >
> > /*
> >  * If the "value" less than 10, this will overflow.
> >  * From benchmark test, the default wait bit will not be set less than 10bit.
> >  * Because 10 bit corresponds to the wait entry time is 439375573401999609(ns),
> >  * for wait-entry-idle time this value looks too long, and we cannot use those
> >  * "long" time as a default wait-entry time. So overflow could not have
> happened
> >  * and we use this calculation method to get wait-entry-idle time.
> >  */
> 
> I think now we will use same calculation code for default value and user set
> value, so adding the comment is not sufficient, we should error out from the
> code if value is less than 10. As default value is not less than 10 so this will
> always work with default value but if user tries to set less than 10 then error
> out and ask user to try more than 9.
> 
Again, once the user has set up a time, the code will go to another branch.

else {
	time = pw20_wt;
}

We do so much for this a little function processing is not worth it. If we can't
agree on this sys interface. I will change this sys interface to show_pw20_wait_bit. :)

code e.g:
static ssize_t show_pw20_wait_bit(struct device *dev,
                                struct device_attribute *attr, char *buf)
{
        u32 entry_bit;
        unsigned int cpu = dev->id;

        smp_call_function_single(cpu, do_show_pwrmgtcr0, &entry_bit, 1);
        entry_bit = (entry_bit & PWRMGTCR0_PW20_ENT) >>
                PWRMGTCR0_PW20_ENT_SHIFT;

        return sprintf(buf, "%u\n", entry_bit);
}

-dongsheng

> -Bharat
Scott Wood Dec. 16, 2013, 6:26 p.m. UTC | #30
On Sun, 2013-12-15 at 23:53 -0600, Wang Dongsheng-B40534 wrote:
> 
> > -----Original Message-----
> > From: Bhushan Bharat-R65777
> > Sent: Monday, November 11, 2013 12:11 PM
> > 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
> > 
> > > > Those codes just for discuss with Bharat. He want to make one flow at
> > > > "show_pw20_wait_time"/" show_altivec_idle_wait_time" function. If we
> > > > do that, we need to initialize pw20_wt/altivec_idle_wt.
> > > >
> > > I will keep this stuff at "show_pw20_wait_time"/"show_altivec_idle_wait_time"
> > > and add a comment before our discussion.
> > >
> > > /*
> > >  * If the "value" less than 10, this will overflow.
> > >  * From benchmark test, the default wait bit will not be set less than 10bit.
> > >  * Because 10 bit corresponds to the wait entry time is 439375573401999609(ns),
> > >  * for wait-entry-idle time this value looks too long, and we cannot use those
> > >  * "long" time as a default wait-entry time. So overflow could not have
> > happened
> > >  * and we use this calculation method to get wait-entry-idle time.
> > >  */
> > 
> > I think now we will use same calculation code for default value and user set
> > value, so adding the comment is not sufficient, we should error out from the
> > code if value is less than 10. As default value is not less than 10 so this will
> > always work with default value but if user tries to set less than 10 then error
> > out and ask user to try more than 9.
> > 
> Again, once the user has set up a time, the code will go to another branch.
> 
> else {
> 	time = pw20_wt;
> }
> 
> We do so much for this a little function processing is not worth it. If we can't
> agree on this sys interface. I will change this sys interface to show_pw20_wait_bit. :)

Please don't change it.

-Scott
diff mbox

Patch

diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 27a90b9..10d1128 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -85,6 +85,284 @@  __setup("smt-snooze-delay=", setup_smt_snooze_delay);
 
 #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 >= 10000)
+		cycle = div_u64(ns + 500, 1000) * tb_ticks_per_usec;
+	else
+		cycle = div_u64(ns * tb_ticks_per_usec, 1000);
+
+	if (!cycle)
+		return 0;
+
+	return ilog2(cycle);
+}
+
+static void do_show_pwrmgtcr0(void *val)
+{
+	u32 *value = val;
+
+	*value = mfspr(SPRN_PWRMGTCR0);
+}
+
+static ssize_t show_pw20_state(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	u32 value;
+	unsigned int cpu = dev->id;
+
+	smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
+
+	value &= PWRMGTCR0_PW20_WAIT;
+
+	return sprintf(buf, "%u\n", value ? 1 : 0);
+}
+
+static void do_store_pw20_state(void *val)
+{
+	u32 *value = val;
+	u32 pw20_state;
+
+	pw20_state = mfspr(SPRN_PWRMGTCR0);
+
+	if (*value)
+		pw20_state |= PWRMGTCR0_PW20_WAIT;
+	else
+		pw20_state &= ~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 = 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 = dev->id;
+
+	if (!pw20_wt) {
+		smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
+		value = (value & PWRMGTCR0_PW20_ENT) >>
+					PWRMGTCR0_PW20_ENT_SHIFT;
+
+		tb_cycle = (1 << (MAX_BIT - value)) * 2;
+		time = div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1;
+	} else {
+		time = pw20_wt;
+	}
+
+	return sprintf(buf, "%llu\n", time > 0 ? time : 0);
+}
+
+static void set_pw20_wait_entry_bit(void *val)
+{
+	u32 *value = val;
+	u32 pw20_idle;
+
+	pw20_idle = mfspr(SPRN_PWRMGTCR0);
+
+	/* Set Automatic PW20 Core Idle Count */
+	/* clear count */
+	pw20_idle &= ~PWRMGTCR0_PW20_ENT;
+
+	/* set count */
+	pw20_idle |= ((MAX_BIT - *value) << PWRMGTCR0_PW20_ENT_SHIFT);
+
+	mtspr(SPRN_PWRMGTCR0, pw20_idle);
+}
+
+static ssize_t store_pw20_wait_time(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	u32 entry_bit;
+	u64 value;
+
+	unsigned int cpu = dev->id;
+
+	if (kstrtou64(buf, 0, &value))
+		return -EINVAL;
+
+	if (!value)
+		return -EINVAL;
+
+	entry_bit = get_idle_ticks_bit(value);
+	if (entry_bit > MAX_BIT)
+		return -EINVAL;
+
+	pw20_wt = value;
+	smp_call_function_single(cpu, set_pw20_wait_entry_bit,
+				&entry_bit, 1);
+
+	return count;
+}
+
+static ssize_t show_altivec_idle(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	u32 value;
+	unsigned int cpu = dev->id;
+
+	smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
+
+	value &= PWRMGTCR0_AV_IDLE_PD_EN;
+
+	return sprintf(buf, "%u\n", value ? 1 : 0);
+}
+
+static void do_store_altivec_idle(void *val)
+{
+	u32 *value = val;
+	u32 altivec_idle;
+
+	altivec_idle = mfspr(SPRN_PWRMGTCR0);
+
+	if (*value)
+		altivec_idle |= PWRMGTCR0_AV_IDLE_PD_EN;
+	else
+		altivec_idle &= ~PWRMGTCR0_AV_IDLE_PD_EN;
+
+	mtspr(SPRN_PWRMGTCR0, altivec_idle);
+}
+
+static ssize_t store_altivec_idle(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	u32 value;
+	unsigned int cpu = dev->id;
+
+	if (kstrtou32(buf, 0, &value))
+		return -EINVAL;
+
+	if (value > 1)
+		return -EINVAL;
+
+	smp_call_function_single(cpu, do_store_altivec_idle, &value, 1);
+
+	return count;
+}
+
+static ssize_t show_altivec_idle_wait_time(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	u32 value;
+	u64 tb_cycle;
+	s64 time;
+
+	unsigned int cpu = dev->id;
+
+	if (!altivec_idle_wt) {
+		smp_call_function_single(cpu, do_show_pwrmgtcr0, &value, 1);
+		value = (value & PWRMGTCR0_AV_IDLE_CNT) >>
+					PWRMGTCR0_AV_IDLE_CNT_SHIFT;
+
+		tb_cycle = (1 << (MAX_BIT - value)) * 2;
+		time = div_u64(tb_cycle * 1000, tb_ticks_per_usec) - 1;
+	} else {
+		time = altivec_idle_wt;
+	}
+
+	return sprintf(buf, "%llu\n", time > 0 ? time : 0);
+}
+
+static void set_altivec_idle_wait_entry_bit(void *val)
+{
+	u32 *value = val;
+	u32 altivec_idle;
+
+	altivec_idle = mfspr(SPRN_PWRMGTCR0);
+
+	/* Set Automatic AltiVec Idle Count */
+	/* clear count */
+	altivec_idle &= ~PWRMGTCR0_AV_IDLE_CNT;
+
+	/* set count */
+	altivec_idle |= ((MAX_BIT - *value) << PWRMGTCR0_AV_IDLE_CNT_SHIFT);
+
+	mtspr(SPRN_PWRMGTCR0, altivec_idle);
+}
+
+static ssize_t store_altivec_idle_wait_time(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	u32 entry_bit;
+	u64 value;
+
+	unsigned int cpu = dev->id;
+
+	if (kstrtou64(buf, 0, &value))
+		return -EINVAL;
+
+	if (!value)
+		return -EINVAL;
+
+	entry_bit = get_idle_ticks_bit(value);
+	if (entry_bit > MAX_BIT)
+		return -EINVAL;
+
+	altivec_idle_wt = value;
+	smp_call_function_single(cpu, set_altivec_idle_wait_entry_bit,
+				&entry_bit, 1);
+
+	return count;
+}
+
+/*
+ * Enable/Disable interface:
+ * 0, disable. 1, enable.
+ */
+static DEVICE_ATTR(pw20_state, 0600, show_pw20_state, store_pw20_state);
+static DEVICE_ATTR(altivec_idle, 0600, show_altivec_idle, store_altivec_idle);
+
+/*
+ * Set wait time interface:(Nanosecond)
+ * 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]
+ * ...
+ */
+static DEVICE_ATTR(pw20_wait_time, 0600,
+			show_pw20_wait_time,
+			store_pw20_wait_time);
+static DEVICE_ATTR(altivec_idle_wait_time, 0600,
+			show_altivec_idle_wait_time,
+			store_altivec_idle_wait_time);
+#endif
+
 /*
  * Enabling PMCs will slow partition context switch times so we only do
  * it the first time we write to the PMCs.
@@ -407,6 +685,15 @@  static void register_cpu_online(unsigned int cpu)
 		device_create_file(s, &dev_attr_pir);
 #endif /* CONFIG_PPC64 */
 
+#ifdef CONFIG_FSL_SOC
+	if (PVR_VER(cur_cpu_spec->pvr_value) == PVR_VER_E6500) {
+		device_create_file(s, &dev_attr_pw20_state);
+		device_create_file(s, &dev_attr_pw20_wait_time);
+
+		device_create_file(s, &dev_attr_altivec_idle);
+		device_create_file(s, &dev_attr_altivec_idle_wait_time);
+	}
+#endif
 	cacheinfo_cpu_online(cpu);
 }
 
@@ -479,6 +766,15 @@  static void unregister_cpu_online(unsigned int cpu)
 		device_remove_file(s, &dev_attr_pir);
 #endif /* CONFIG_PPC64 */
 
+#ifdef CONFIG_FSL_SOC
+	if (PVR_VER(cur_cpu_spec->pvr_value) == PVR_VER_E6500) {
+		device_remove_file(s, &dev_attr_pw20_state);
+		device_remove_file(s, &dev_attr_pw20_wait_time);
+
+		device_remove_file(s, &dev_attr_altivec_idle);
+		device_remove_file(s, &dev_attr_altivec_idle_wait_time);
+	}
+#endif
 	cacheinfo_cpu_offline(cpu);
 }