All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/2] WFE for long delays
@ 2017-09-29 10:52 Julien Thierry
  2017-09-29 10:52 ` [PATCH v3 1/2] arm_arch_timer: Expose event stream status Julien Thierry
  2017-09-29 10:52 ` [PATCH v3 2/2] arm64: use WFE for long delays Julien Thierry
  0 siblings, 2 replies; 15+ messages in thread
From: Julien Thierry @ 2017-09-29 10:52 UTC (permalink / raw)
  To: linux-arm-kernel

It was pointed out that there are some windows where the event stream might not
be configured, meaning we cannot safely use WFE (e.g. when using PSCI
CPU_SUSPEND for idle, PSCI might reset CPU state).

The first patch provide a function to check whether the task is in state where
it can expect events from the event stream.

Second patch actually makes use of WFE in delays.

Changes since v1:
- Keep track of event stream state
- Do not use WFE when event stream might be misconfigured

Changes since v2:
- Use cpumask to track event stream state instead of percpu variable
- Tidy a bit code in arm64/lib/delay
- Do not factor asm-generic/delay code

Julien Thierry (2):
  arm_arch_timer: Expose event stream status
  arm64: use WFE for long delays

 arch/arm/include/asm/arch_timer.h    |  1 +
 arch/arm64/include/asm/arch_timer.h  |  1 +
 arch/arm64/lib/delay.c               | 23 +++++++++++++++++++----
 drivers/clocksource/arm_arch_timer.c | 20 ++++++++++++++++++--
 include/clocksource/arm_arch_timer.h | 10 +++++++++-
 5 files changed, 48 insertions(+), 7 deletions(-)

--
1.9.1

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 1/2] arm_arch_timer: Expose event stream status
  2017-09-29 10:52 [PATCH v3 0/2] WFE for long delays Julien Thierry
@ 2017-09-29 10:52 ` Julien Thierry
  2017-10-11 15:14   ` Will Deacon
  2017-10-12  9:27   ` Suzuki K Poulose
  2017-09-29 10:52 ` [PATCH v3 2/2] arm64: use WFE for long delays Julien Thierry
  1 sibling, 2 replies; 15+ messages in thread
From: Julien Thierry @ 2017-09-29 10:52 UTC (permalink / raw)
  To: linux-arm-kernel

The arch timer configuration for a CPU might get reset after suspending
said CPU.

In order to reliably use the event stream in the kernel (e.g. for delays),
we keep track of the state where we can safely concider the event stream as
properly configured.

Signed-off-by: Julien Thierry <julien.thierry@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
---
 arch/arm/include/asm/arch_timer.h    |  1 +
 arch/arm64/include/asm/arch_timer.h  |  1 +
 drivers/clocksource/arm_arch_timer.c | 20 ++++++++++++++++++--
 include/clocksource/arm_arch_timer.h |  6 ++++++
 4 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h
index d4ebf56..0b6e104 100644
--- a/arch/arm/include/asm/arch_timer.h
+++ b/arch/arm/include/asm/arch_timer.h
@@ -106,6 +106,7 @@ static inline u32 arch_timer_get_cntkctl(void)
 static inline void arch_timer_set_cntkctl(u32 cntkctl)
 {
 	asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl));
+	isb();
 }

 #endif
diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h
index a652ce0..bdedd8f 100644
--- a/arch/arm64/include/asm/arch_timer.h
+++ b/arch/arm64/include/asm/arch_timer.h
@@ -144,6 +144,7 @@ static inline u32 arch_timer_get_cntkctl(void)
 static inline void arch_timer_set_cntkctl(u32 cntkctl)
 {
 	write_sysreg(cntkctl, cntkctl_el1);
+	isb();
 }

 static inline u64 arch_counter_get_cntpct(void)
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index fd4b7f6..47cf15e 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -77,6 +77,7 @@ struct arch_timer {
 static bool arch_counter_suspend_stop;
 static bool vdso_default = true;

+static cpumask_t evtstrm_available;
 static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM);

 static int __init early_evtstrm_cfg(char *buf)
@@ -740,6 +741,7 @@ static void arch_timer_evtstrm_enable(int divider)
 #ifdef CONFIG_COMPAT
 	compat_elf_hwcap |= COMPAT_HWCAP_EVTSTRM;
 #endif
+	cpumask_set_cpu(smp_processor_id(), &evtstrm_available);
 }

 static void arch_timer_configure_evtstream(void)
@@ -864,6 +866,11 @@ u32 arch_timer_get_rate(void)
 	return arch_timer_rate;
 }

+bool arch_timer_evtstrm_available(void)
+{
+	return !!cpumask_test_cpu(smp_processor_id(), &evtstrm_available);
+}
+
 static u64 arch_counter_get_cntvct_mem(void)
 {
 	u32 vct_lo, vct_hi, tmp_hi;
@@ -929,6 +936,8 @@ static int arch_timer_dying_cpu(unsigned int cpu)
 {
 	struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt);

+	cpumask_clear_cpu(smp_processor_id(), &evtstrm_available);
+
 	arch_timer_stop(clk);
 	return 0;
 }
@@ -938,10 +947,16 @@ static int arch_timer_dying_cpu(unsigned int cpu)
 static int arch_timer_cpu_pm_notify(struct notifier_block *self,
 				    unsigned long action, void *hcpu)
 {
-	if (action == CPU_PM_ENTER)
+	if (action == CPU_PM_ENTER) {
 		__this_cpu_write(saved_cntkctl, arch_timer_get_cntkctl());
-	else if (action == CPU_PM_ENTER_FAILED || action == CPU_PM_EXIT)
+
+		cpumask_clear_cpu(smp_processor_id(), &evtstrm_available);
+	} else if (action == CPU_PM_ENTER_FAILED || action == CPU_PM_EXIT) {
 		arch_timer_set_cntkctl(__this_cpu_read(saved_cntkctl));
+
+		if (elf_hwcap & HWCAP_EVTSTRM)
+			cpumask_set_cpu(smp_processor_id(), &evtstrm_available);
+	}
 	return NOTIFY_OK;
 }

@@ -1017,6 +1032,7 @@ static int __init arch_timer_register(void)
 	if (err)
 		goto out_unreg_notify;

+	cpumask_clear(&evtstrm_available);

 	/* Register and immediately configure the timer on the boot CPU */
 	err = cpuhp_setup_state(CPUHP_AP_ARM_ARCH_TIMER_STARTING,
diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h
index cc805b7..4e28283 100644
--- a/include/clocksource/arm_arch_timer.h
+++ b/include/clocksource/arm_arch_timer.h
@@ -93,6 +93,7 @@ struct arch_timer_mem {
 extern u32 arch_timer_get_rate(void);
 extern u64 (*arch_timer_read_counter)(void);
 extern struct arch_timer_kvm_info *arch_timer_get_kvm_info(void);
+extern bool arch_timer_evtstrm_available(void);

 #else

@@ -106,6 +107,11 @@ static inline u64 arch_timer_read_counter(void)
 	return 0;
 }

+static inline bool arch_timer_evtstrm_available(void)
+{
+	return false;
+}
+
 #endif

 #endif
--
1.9.1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 2/2] arm64: use WFE for long delays
  2017-09-29 10:52 [PATCH v3 0/2] WFE for long delays Julien Thierry
  2017-09-29 10:52 ` [PATCH v3 1/2] arm_arch_timer: Expose event stream status Julien Thierry
@ 2017-09-29 10:52 ` Julien Thierry
  2017-10-11 15:13   ` Will Deacon
  1 sibling, 1 reply; 15+ messages in thread
From: Julien Thierry @ 2017-09-29 10:52 UTC (permalink / raw)
  To: linux-arm-kernel

The current delay implementation uses the yield instruction, which is a
hint that it is beneficial to schedule another thread. As this is a hint,
it may be implemented as a NOP, causing all delays to be busy loops. This
is the case for many existing CPUs.

Taking advantage of the generic timer sending periodic events to all
cores, we can use WFE during delays to reduce power consumption. This is
beneficial only for delays longer than the period of the timer event
stream.

If timer event stream is not enabled, delays will behave as yield/busy
loops.

Signed-off-by: Julien Thierry <julien.thierry@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
---
 arch/arm64/lib/delay.c               | 23 +++++++++++++++++++----
 include/clocksource/arm_arch_timer.h |  4 +++-
 2 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/lib/delay.c b/arch/arm64/lib/delay.c
index dad4ec9..4dc27f3 100644
--- a/arch/arm64/lib/delay.c
+++ b/arch/arm64/lib/delay.c
@@ -24,10 +24,28 @@
 #include <linux/module.h>
 #include <linux/timex.h>

+#include <clocksource/arm_arch_timer.h>
+
+#define USECS_TO_CYCLES(TIME_USECS)			\
+	xloops_to_cycles((TIME_USECS) * 0x10C7UL)
+
+static inline unsigned long xloops_to_cycles(unsigned long xloops)
+{
+	return (xloops * loops_per_jiffy * HZ) >> 32;
+}
+
 void __delay(unsigned long cycles)
 {
 	cycles_t start = get_cycles();

+	if (arch_timer_evtstrm_available()) {
+		const cycles_t timer_evt_period =
+			USECS_TO_CYCLES(ARCH_TIMER_EVT_STREAM_PERIOD_US);
+
+		while ((get_cycles() - start + timer_evt_period) < cycles)
+			wfe();
+	}
+
 	while ((get_cycles() - start) < cycles)
 		cpu_relax();
 }
@@ -35,10 +53,7 @@ void __delay(unsigned long cycles)

 inline void __const_udelay(unsigned long xloops)
 {
-	unsigned long loops;
-
-	loops = xloops * loops_per_jiffy * HZ;
-	__delay(loops >> 32);
+	__delay(xloops_to_cycles(xloops));
 }
 EXPORT_SYMBOL(__const_udelay);

diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h
index 4e28283..349e595 100644
--- a/include/clocksource/arm_arch_timer.h
+++ b/include/clocksource/arm_arch_timer.h
@@ -67,7 +67,9 @@ enum arch_timer_spi_nr {
 #define ARCH_TIMER_USR_VT_ACCESS_EN	(1 << 8) /* virtual timer registers */
 #define ARCH_TIMER_USR_PT_ACCESS_EN	(1 << 9) /* physical timer registers */

-#define ARCH_TIMER_EVT_STREAM_FREQ	10000	/* 100us */
+#define ARCH_TIMER_EVT_STREAM_PERIOD_US	100
+#define ARCH_TIMER_EVT_STREAM_FREQ				\
+	(USEC_PER_SEC / ARCH_TIMER_EVT_STREAM_PERIOD_US)

 struct arch_timer_kvm_info {
 	struct timecounter timecounter;
--
1.9.1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 2/2] arm64: use WFE for long delays
  2017-09-29 10:52 ` [PATCH v3 2/2] arm64: use WFE for long delays Julien Thierry
@ 2017-10-11 15:13   ` Will Deacon
  2017-10-12  8:47     ` Julien Thierry
  0 siblings, 1 reply; 15+ messages in thread
From: Will Deacon @ 2017-10-11 15:13 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Julien,

On Fri, Sep 29, 2017 at 11:52:30AM +0100, Julien Thierry wrote:
> The current delay implementation uses the yield instruction, which is a
> hint that it is beneficial to schedule another thread. As this is a hint,
> it may be implemented as a NOP, causing all delays to be busy loops. This
> is the case for many existing CPUs.
> 
> Taking advantage of the generic timer sending periodic events to all
> cores, we can use WFE during delays to reduce power consumption. This is
> beneficial only for delays longer than the period of the timer event
> stream.
> 
> If timer event stream is not enabled, delays will behave as yield/busy
> loops.
> 
> Signed-off-by: Julien Thierry <julien.thierry@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> ---
>  arch/arm64/lib/delay.c               | 23 +++++++++++++++++++----
>  include/clocksource/arm_arch_timer.h |  4 +++-
>  2 files changed, 22 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/arm64/lib/delay.c b/arch/arm64/lib/delay.c
> index dad4ec9..4dc27f3 100644
> --- a/arch/arm64/lib/delay.c
> +++ b/arch/arm64/lib/delay.c
> @@ -24,10 +24,28 @@
>  #include <linux/module.h>
>  #include <linux/timex.h>
> 
> +#include <clocksource/arm_arch_timer.h>
> +
> +#define USECS_TO_CYCLES(TIME_USECS)			\
> +	xloops_to_cycles((TIME_USECS) * 0x10C7UL)

The macro parameter can be lower-case here.

> +static inline unsigned long xloops_to_cycles(unsigned long xloops)
> +{
> +	return (xloops * loops_per_jiffy * HZ) >> 32;
> +}
> +
>  void __delay(unsigned long cycles)
>  {
>  	cycles_t start = get_cycles();
> 
> +	if (arch_timer_evtstrm_available()) {

Hmm, is this never called in a context where preemption is enabled?
Maybe arch_timer_evtstrm_available should be using raw_smp_processor_id()
under the hood.

> +		const cycles_t timer_evt_period =
> +			USECS_TO_CYCLES(ARCH_TIMER_EVT_STREAM_PERIOD_US);
> +
> +		while ((get_cycles() - start + timer_evt_period) < cycles)
> +			wfe();
> +	}
> +
>  	while ((get_cycles() - start) < cycles)
>  		cpu_relax();
>  }
> @@ -35,10 +53,7 @@ void __delay(unsigned long cycles)
> 
>  inline void __const_udelay(unsigned long xloops)
>  {
> -	unsigned long loops;
> -
> -	loops = xloops * loops_per_jiffy * HZ;
> -	__delay(loops >> 32);
> +	__delay(xloops_to_cycles(xloops));
>  }
>  EXPORT_SYMBOL(__const_udelay);
> 
> diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h
> index 4e28283..349e595 100644
> --- a/include/clocksource/arm_arch_timer.h
> +++ b/include/clocksource/arm_arch_timer.h
> @@ -67,7 +67,9 @@ enum arch_timer_spi_nr {
>  #define ARCH_TIMER_USR_VT_ACCESS_EN	(1 << 8) /* virtual timer registers */
>  #define ARCH_TIMER_USR_PT_ACCESS_EN	(1 << 9) /* physical timer registers */
> 
> -#define ARCH_TIMER_EVT_STREAM_FREQ	10000	/* 100us */
> +#define ARCH_TIMER_EVT_STREAM_PERIOD_US	100
> +#define ARCH_TIMER_EVT_STREAM_FREQ				\
> +	(USEC_PER_SEC / ARCH_TIMER_EVT_STREAM_PERIOD_US)

This needs an ack from Marc or Mark.

Will

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 1/2] arm_arch_timer: Expose event stream status
  2017-09-29 10:52 ` [PATCH v3 1/2] arm_arch_timer: Expose event stream status Julien Thierry
@ 2017-10-11 15:14   ` Will Deacon
  2017-10-12  8:38     ` Julien Thierry
  2017-10-12  8:58     ` Julien Thierry
  2017-10-12  9:27   ` Suzuki K Poulose
  1 sibling, 2 replies; 15+ messages in thread
From: Will Deacon @ 2017-10-11 15:14 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Julien,

On Fri, Sep 29, 2017 at 11:52:29AM +0100, Julien Thierry wrote:
> The arch timer configuration for a CPU might get reset after suspending
> said CPU.
> 
> In order to reliably use the event stream in the kernel (e.g. for delays),
> we keep track of the state where we can safely concider the event stream as
> properly configured.
> 
> Signed-off-by: Julien Thierry <julien.thierry@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Cc: Russell King <linux@armlinux.org.uk>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> ---
>  arch/arm/include/asm/arch_timer.h    |  1 +
>  arch/arm64/include/asm/arch_timer.h  |  1 +
>  drivers/clocksource/arm_arch_timer.c | 20 ++++++++++++++++++--
>  include/clocksource/arm_arch_timer.h |  6 ++++++
>  4 files changed, 26 insertions(+), 2 deletions(-)

The arch-timer bits needs an ack from Marc or Mark.

> diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h
> index d4ebf56..0b6e104 100644
> --- a/arch/arm/include/asm/arch_timer.h
> +++ b/arch/arm/include/asm/arch_timer.h
> @@ -106,6 +106,7 @@ static inline u32 arch_timer_get_cntkctl(void)
>  static inline void arch_timer_set_cntkctl(u32 cntkctl)
>  {
>  	asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl));
> +	isb();
>  }
> 
>  #endif
> diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h
> index a652ce0..bdedd8f 100644
> --- a/arch/arm64/include/asm/arch_timer.h
> +++ b/arch/arm64/include/asm/arch_timer.h
> @@ -144,6 +144,7 @@ static inline u32 arch_timer_get_cntkctl(void)
>  static inline void arch_timer_set_cntkctl(u32 cntkctl)
>  {
>  	write_sysreg(cntkctl, cntkctl_el1);
> +	isb();
>  }
> 
>  static inline u64 arch_counter_get_cntpct(void)
> diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
> index fd4b7f6..47cf15e 100644
> --- a/drivers/clocksource/arm_arch_timer.c
> +++ b/drivers/clocksource/arm_arch_timer.c
> @@ -77,6 +77,7 @@ struct arch_timer {
>  static bool arch_counter_suspend_stop;
>  static bool vdso_default = true;
> 
> +static cpumask_t evtstrm_available;
>  static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM);
> 
>  static int __init early_evtstrm_cfg(char *buf)
> @@ -740,6 +741,7 @@ static void arch_timer_evtstrm_enable(int divider)
>  #ifdef CONFIG_COMPAT
>  	compat_elf_hwcap |= COMPAT_HWCAP_EVTSTRM;
>  #endif
> +	cpumask_set_cpu(smp_processor_id(), &evtstrm_available);
>  }
> 
>  static void arch_timer_configure_evtstream(void)
> @@ -864,6 +866,11 @@ u32 arch_timer_get_rate(void)
>  	return arch_timer_rate;
>  }
> 
> +bool arch_timer_evtstrm_available(void)
> +{
> +	return !!cpumask_test_cpu(smp_processor_id(), &evtstrm_available);
> +}

I don't think you need the '!!' prefix here.

> +
>  static u64 arch_counter_get_cntvct_mem(void)
>  {
>  	u32 vct_lo, vct_hi, tmp_hi;
> @@ -929,6 +936,8 @@ static int arch_timer_dying_cpu(unsigned int cpu)
>  {
>  	struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt);
> 
> +	cpumask_clear_cpu(smp_processor_id(), &evtstrm_available);
> +
>  	arch_timer_stop(clk);
>  	return 0;
>  }
> @@ -938,10 +947,16 @@ static int arch_timer_dying_cpu(unsigned int cpu)
>  static int arch_timer_cpu_pm_notify(struct notifier_block *self,
>  				    unsigned long action, void *hcpu)
>  {
> -	if (action == CPU_PM_ENTER)
> +	if (action == CPU_PM_ENTER) {
>  		__this_cpu_write(saved_cntkctl, arch_timer_get_cntkctl());
> -	else if (action == CPU_PM_ENTER_FAILED || action == CPU_PM_EXIT)
> +
> +		cpumask_clear_cpu(smp_processor_id(), &evtstrm_available);
> +	} else if (action == CPU_PM_ENTER_FAILED || action == CPU_PM_EXIT) {
>  		arch_timer_set_cntkctl(__this_cpu_read(saved_cntkctl));
> +
> +		if (elf_hwcap & HWCAP_EVTSTRM)
> +			cpumask_set_cpu(smp_processor_id(), &evtstrm_available);
> +	}
>  	return NOTIFY_OK;
>  }
> 
> @@ -1017,6 +1032,7 @@ static int __init arch_timer_register(void)
>  	if (err)
>  		goto out_unreg_notify;
> 
> +	cpumask_clear(&evtstrm_available);

This should already be ok by virtue of the mask being static, no?
Alternatively, you could use the CPU_MASK_NONE static initialiser.

Will

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 1/2] arm_arch_timer: Expose event stream status
  2017-10-11 15:14   ` Will Deacon
@ 2017-10-12  8:38     ` Julien Thierry
  2017-10-12  8:58     ` Julien Thierry
  1 sibling, 0 replies; 15+ messages in thread
From: Julien Thierry @ 2017-10-12  8:38 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Will,

On 11/10/17 16:14, Will Deacon wrote:
> Hi Julien,
> 
> On Fri, Sep 29, 2017 at 11:52:29AM +0100, Julien Thierry wrote:
>> The arch timer configuration for a CPU might get reset after suspending
>> said CPU.
>>
>> In order to reliably use the event stream in the kernel (e.g. for delays),
>> we keep track of the state where we can safely concider the event stream as
>> properly configured.
>>
>> Signed-off-by: Julien Thierry <julien.thierry@arm.com>
>> Cc: Mark Rutland <mark.rutland@arm.com>
>> Cc: Marc Zyngier <marc.zyngier@arm.com>
>> Cc: Russell King <linux@armlinux.org.uk>
>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> ---
>>   arch/arm/include/asm/arch_timer.h    |  1 +
>>   arch/arm64/include/asm/arch_timer.h  |  1 +
>>   drivers/clocksource/arm_arch_timer.c | 20 ++++++++++++++++++--
>>   include/clocksource/arm_arch_timer.h |  6 ++++++
>>   4 files changed, 26 insertions(+), 2 deletions(-)
> 
> The arch-timer bits needs an ack from Marc or Mark.
> 
>> diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h
>> index d4ebf56..0b6e104 100644
>> --- a/arch/arm/include/asm/arch_timer.h
>> +++ b/arch/arm/include/asm/arch_timer.h
>> @@ -106,6 +106,7 @@ static inline u32 arch_timer_get_cntkctl(void)
>>   static inline void arch_timer_set_cntkctl(u32 cntkctl)
>>   {
>>   	asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl));
>> +	isb();
>>   }
>>
>>   #endif
>> diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h
>> index a652ce0..bdedd8f 100644
>> --- a/arch/arm64/include/asm/arch_timer.h
>> +++ b/arch/arm64/include/asm/arch_timer.h
>> @@ -144,6 +144,7 @@ static inline u32 arch_timer_get_cntkctl(void)
>>   static inline void arch_timer_set_cntkctl(u32 cntkctl)
>>   {
>>   	write_sysreg(cntkctl, cntkctl_el1);
>> +	isb();
>>   }
>>
>>   static inline u64 arch_counter_get_cntpct(void)
>> diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
>> index fd4b7f6..47cf15e 100644
>> --- a/drivers/clocksource/arm_arch_timer.c
>> +++ b/drivers/clocksource/arm_arch_timer.c
>> @@ -77,6 +77,7 @@ struct arch_timer {
>>   static bool arch_counter_suspend_stop;
>>   static bool vdso_default = true;
>>
>> +static cpumask_t evtstrm_available;
>>   static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM);
>>
>>   static int __init early_evtstrm_cfg(char *buf)
>> @@ -740,6 +741,7 @@ static void arch_timer_evtstrm_enable(int divider)
>>   #ifdef CONFIG_COMPAT
>>   	compat_elf_hwcap |= COMPAT_HWCAP_EVTSTRM;
>>   #endif
>> +	cpumask_set_cpu(smp_processor_id(), &evtstrm_available);
>>   }
>>
>>   static void arch_timer_configure_evtstream(void)
>> @@ -864,6 +866,11 @@ u32 arch_timer_get_rate(void)
>>   	return arch_timer_rate;
>>   }
>>
>> +bool arch_timer_evtstrm_available(void)
>> +{
>> +	return !!cpumask_test_cpu(smp_processor_id(), &evtstrm_available);
>> +}
> 
> I don't think you need the '!!' prefix here.

True, I'll remove that.

> 
>> +
>>   static u64 arch_counter_get_cntvct_mem(void)
>>   {
>>   	u32 vct_lo, vct_hi, tmp_hi;
>> @@ -929,6 +936,8 @@ static int arch_timer_dying_cpu(unsigned int cpu)
>>   {
>>   	struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt);
>>
>> +	cpumask_clear_cpu(smp_processor_id(), &evtstrm_available);
>> +
>>   	arch_timer_stop(clk);
>>   	return 0;
>>   }
>> @@ -938,10 +947,16 @@ static int arch_timer_dying_cpu(unsigned int cpu)
>>   static int arch_timer_cpu_pm_notify(struct notifier_block *self,
>>   				    unsigned long action, void *hcpu)
>>   {
>> -	if (action == CPU_PM_ENTER)
>> +	if (action == CPU_PM_ENTER) {
>>   		__this_cpu_write(saved_cntkctl, arch_timer_get_cntkctl());
>> -	else if (action == CPU_PM_ENTER_FAILED || action == CPU_PM_EXIT)
>> +
>> +		cpumask_clear_cpu(smp_processor_id(), &evtstrm_available);
>> +	} else if (action == CPU_PM_ENTER_FAILED || action == CPU_PM_EXIT) {
>>   		arch_timer_set_cntkctl(__this_cpu_read(saved_cntkctl));
>> +
>> +		if (elf_hwcap & HWCAP_EVTSTRM)
>> +			cpumask_set_cpu(smp_processor_id(), &evtstrm_available);
>> +	}
>>   	return NOTIFY_OK;
>>   }
>>
>> @@ -1017,6 +1032,7 @@ static int __init arch_timer_register(void)
>>   	if (err)
>>   		goto out_unreg_notify;
>>
>> +	cpumask_clear(&evtstrm_available);
> 
> This should already be ok by virtue of the mask being static, no?
> Alternatively, you could use the CPU_MASK_NONE static initialiser.

Yes, I just prefer explicit initialisations. But you're right, I'll use 
CPU_MASK_NONE unless it is encouraged to rely on implicit intilisation.

Thanks,

-- 
Julien Thierry

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 2/2] arm64: use WFE for long delays
  2017-10-11 15:13   ` Will Deacon
@ 2017-10-12  8:47     ` Julien Thierry
  2017-10-12  8:52       ` Will Deacon
  0 siblings, 1 reply; 15+ messages in thread
From: Julien Thierry @ 2017-10-12  8:47 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Will,

On 11/10/17 16:13, Will Deacon wrote:
> Hi Julien,
> 
> On Fri, Sep 29, 2017 at 11:52:30AM +0100, Julien Thierry wrote:
>> The current delay implementation uses the yield instruction, which is a
>> hint that it is beneficial to schedule another thread. As this is a hint,
>> it may be implemented as a NOP, causing all delays to be busy loops. This
>> is the case for many existing CPUs.
>>
>> Taking advantage of the generic timer sending periodic events to all
>> cores, we can use WFE during delays to reduce power consumption. This is
>> beneficial only for delays longer than the period of the timer event
>> stream.
>>
>> If timer event stream is not enabled, delays will behave as yield/busy
>> loops.
>>
>> Signed-off-by: Julien Thierry <julien.thierry@arm.com>
>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> Cc: Mark Rutland <mark.rutland@arm.com>
>> ---
>>   arch/arm64/lib/delay.c               | 23 +++++++++++++++++++----
>>   include/clocksource/arm_arch_timer.h |  4 +++-
>>   2 files changed, 22 insertions(+), 5 deletions(-)
>>
>> diff --git a/arch/arm64/lib/delay.c b/arch/arm64/lib/delay.c
>> index dad4ec9..4dc27f3 100644
>> --- a/arch/arm64/lib/delay.c
>> +++ b/arch/arm64/lib/delay.c
>> @@ -24,10 +24,28 @@
>>   #include <linux/module.h>
>>   #include <linux/timex.h>
>>
>> +#include <clocksource/arm_arch_timer.h>
>> +
>> +#define USECS_TO_CYCLES(TIME_USECS)			\
>> +	xloops_to_cycles((TIME_USECS) * 0x10C7UL)
> 
> The macro parameter can be lower-case here.
> 

Noted, I'll change it.

>> +static inline unsigned long xloops_to_cycles(unsigned long xloops)
>> +{
>> +	return (xloops * loops_per_jiffy * HZ) >> 32;
>> +}
>> +
>>   void __delay(unsigned long cycles)
>>   {
>>   	cycles_t start = get_cycles();
>>
>> +	if (arch_timer_evtstrm_available()) {
> 
> Hmm, is this never called in a context where preemption is enabled?
> Maybe arch_timer_evtstrm_available should be using raw_smp_processor_id()
> under the hood.
> 

This can be called from a preemptible context. But when it is, the event 
stream is either enabled both on the preemptible context and on the 
context where a preempted context can be resumed, or the event stream is 
just disabled in the whole system.

Does using raw_smp_processor_id solve an issue here?

Thanks,

>> +		const cycles_t timer_evt_period =
>> +			USECS_TO_CYCLES(ARCH_TIMER_EVT_STREAM_PERIOD_US);
>> +
>> +		while ((get_cycles() - start + timer_evt_period) < cycles)
>> +			wfe();
>> +	}
>> +
>>   	while ((get_cycles() - start) < cycles)
>>   		cpu_relax();
>>   }
>> @@ -35,10 +53,7 @@ void __delay(unsigned long cycles)
>>
>>   inline void __const_udelay(unsigned long xloops)
>>   {
>> -	unsigned long loops;
>> -
>> -	loops = xloops * loops_per_jiffy * HZ;
>> -	__delay(loops >> 32);
>> +	__delay(xloops_to_cycles(xloops));
>>   }
>>   EXPORT_SYMBOL(__const_udelay);
>>
>> diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h
>> index 4e28283..349e595 100644
>> --- a/include/clocksource/arm_arch_timer.h
>> +++ b/include/clocksource/arm_arch_timer.h
>> @@ -67,7 +67,9 @@ enum arch_timer_spi_nr {
>>   #define ARCH_TIMER_USR_VT_ACCESS_EN	(1 << 8) /* virtual timer registers */
>>   #define ARCH_TIMER_USR_PT_ACCESS_EN	(1 << 9) /* physical timer registers */
>>
>> -#define ARCH_TIMER_EVT_STREAM_FREQ	10000	/* 100us */
>> +#define ARCH_TIMER_EVT_STREAM_PERIOD_US	100
>> +#define ARCH_TIMER_EVT_STREAM_FREQ				\
>> +	(USEC_PER_SEC / ARCH_TIMER_EVT_STREAM_PERIOD_US)
> 
> This needs an ack from Marc or Mark.
> 
> Will
> 

-- 
Julien Thierry

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 2/2] arm64: use WFE for long delays
  2017-10-12  8:47     ` Julien Thierry
@ 2017-10-12  8:52       ` Will Deacon
  2017-10-12  8:54         ` Julien Thierry
  0 siblings, 1 reply; 15+ messages in thread
From: Will Deacon @ 2017-10-12  8:52 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Oct 12, 2017 at 09:47:26AM +0100, Julien Thierry wrote:
> Hi Will,
> 
> On 11/10/17 16:13, Will Deacon wrote:
> >Hi Julien,
> >
> >On Fri, Sep 29, 2017 at 11:52:30AM +0100, Julien Thierry wrote:
> >>The current delay implementation uses the yield instruction, which is a
> >>hint that it is beneficial to schedule another thread. As this is a hint,
> >>it may be implemented as a NOP, causing all delays to be busy loops. This
> >>is the case for many existing CPUs.
> >>
> >>Taking advantage of the generic timer sending periodic events to all
> >>cores, we can use WFE during delays to reduce power consumption. This is
> >>beneficial only for delays longer than the period of the timer event
> >>stream.
> >>
> >>If timer event stream is not enabled, delays will behave as yield/busy
> >>loops.
> >>
> >>Signed-off-by: Julien Thierry <julien.thierry@arm.com>
> >>Cc: Catalin Marinas <catalin.marinas@arm.com>
> >>Cc: Will Deacon <will.deacon@arm.com>
> >>Cc: Mark Rutland <mark.rutland@arm.com>
> >>---
> >>  arch/arm64/lib/delay.c               | 23 +++++++++++++++++++----
> >>  include/clocksource/arm_arch_timer.h |  4 +++-
> >>  2 files changed, 22 insertions(+), 5 deletions(-)
> >>
> >>diff --git a/arch/arm64/lib/delay.c b/arch/arm64/lib/delay.c
> >>index dad4ec9..4dc27f3 100644
> >>--- a/arch/arm64/lib/delay.c
> >>+++ b/arch/arm64/lib/delay.c
> >>@@ -24,10 +24,28 @@
> >>  #include <linux/module.h>
> >>  #include <linux/timex.h>
> >>
> >>+#include <clocksource/arm_arch_timer.h>
> >>+
> >>+#define USECS_TO_CYCLES(TIME_USECS)			\
> >>+	xloops_to_cycles((TIME_USECS) * 0x10C7UL)
> >
> >The macro parameter can be lower-case here.
> >
> 
> Noted, I'll change it.
> 
> >>+static inline unsigned long xloops_to_cycles(unsigned long xloops)
> >>+{
> >>+	return (xloops * loops_per_jiffy * HZ) >> 32;
> >>+}
> >>+
> >>  void __delay(unsigned long cycles)
> >>  {
> >>  	cycles_t start = get_cycles();
> >>
> >>+	if (arch_timer_evtstrm_available()) {
> >
> >Hmm, is this never called in a context where preemption is enabled?
> >Maybe arch_timer_evtstrm_available should be using raw_smp_processor_id()
> >under the hood.
> >
> 
> This can be called from a preemptible context. But when it is, the event
> stream is either enabled both on the preemptible context and on the context
> where a preempted context can be resumed, or the event stream is just
> disabled in the whole system.
> 
> Does using raw_smp_processor_id solve an issue here?

I thought that DEBUG_PREEMPT would splat if you called smp_processor_id()
from preemptible context?

Will

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 2/2] arm64: use WFE for long delays
  2017-10-12  8:52       ` Will Deacon
@ 2017-10-12  8:54         ` Julien Thierry
  0 siblings, 0 replies; 15+ messages in thread
From: Julien Thierry @ 2017-10-12  8:54 UTC (permalink / raw)
  To: linux-arm-kernel



On 12/10/17 09:52, Will Deacon wrote:
> On Thu, Oct 12, 2017 at 09:47:26AM +0100, Julien Thierry wrote:
>> Hi Will,
>>
>> On 11/10/17 16:13, Will Deacon wrote:
>>> Hi Julien,
>>>
>>> On Fri, Sep 29, 2017 at 11:52:30AM +0100, Julien Thierry wrote:
>>>> The current delay implementation uses the yield instruction, which is a
>>>> hint that it is beneficial to schedule another thread. As this is a hint,
>>>> it may be implemented as a NOP, causing all delays to be busy loops. This
>>>> is the case for many existing CPUs.
>>>>
>>>> Taking advantage of the generic timer sending periodic events to all
>>>> cores, we can use WFE during delays to reduce power consumption. This is
>>>> beneficial only for delays longer than the period of the timer event
>>>> stream.
>>>>
>>>> If timer event stream is not enabled, delays will behave as yield/busy
>>>> loops.
>>>>
>>>> Signed-off-by: Julien Thierry <julien.thierry@arm.com>
>>>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>>>> Cc: Will Deacon <will.deacon@arm.com>
>>>> Cc: Mark Rutland <mark.rutland@arm.com>
>>>> ---
>>>>   arch/arm64/lib/delay.c               | 23 +++++++++++++++++++----
>>>>   include/clocksource/arm_arch_timer.h |  4 +++-
>>>>   2 files changed, 22 insertions(+), 5 deletions(-)
>>>>
>>>> diff --git a/arch/arm64/lib/delay.c b/arch/arm64/lib/delay.c
>>>> index dad4ec9..4dc27f3 100644
>>>> --- a/arch/arm64/lib/delay.c
>>>> +++ b/arch/arm64/lib/delay.c
>>>> @@ -24,10 +24,28 @@
>>>>   #include <linux/module.h>
>>>>   #include <linux/timex.h>
>>>>
>>>> +#include <clocksource/arm_arch_timer.h>
>>>> +
>>>> +#define USECS_TO_CYCLES(TIME_USECS)			\
>>>> +	xloops_to_cycles((TIME_USECS) * 0x10C7UL)
>>>
>>> The macro parameter can be lower-case here.
>>>
>>
>> Noted, I'll change it.
>>
>>>> +static inline unsigned long xloops_to_cycles(unsigned long xloops)
>>>> +{
>>>> +	return (xloops * loops_per_jiffy * HZ) >> 32;
>>>> +}
>>>> +
>>>>   void __delay(unsigned long cycles)
>>>>   {
>>>>   	cycles_t start = get_cycles();
>>>>
>>>> +	if (arch_timer_evtstrm_available()) {
>>>
>>> Hmm, is this never called in a context where preemption is enabled?
>>> Maybe arch_timer_evtstrm_available should be using raw_smp_processor_id()
>>> under the hood.
>>>
>>
>> This can be called from a preemptible context. But when it is, the event
>> stream is either enabled both on the preemptible context and on the context
>> where a preempted context can be resumed, or the event stream is just
>> disabled in the whole system.
>>
>> Does using raw_smp_processor_id solve an issue here?
> 
> I thought that DEBUG_PREEMPT would splat if you called smp_processor_id()
> from preemptible context?

Oh right, it will splat indeed. I'll use raw_smp_processor_id as suggested.

Thanks,

-- 
Julien Thierry

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 1/2] arm_arch_timer: Expose event stream status
  2017-10-11 15:14   ` Will Deacon
  2017-10-12  8:38     ` Julien Thierry
@ 2017-10-12  8:58     ` Julien Thierry
  1 sibling, 0 replies; 15+ messages in thread
From: Julien Thierry @ 2017-10-12  8:58 UTC (permalink / raw)
  To: linux-arm-kernel

[resending as I don't see it on the ml]

Hi Will,

On 11/10/17 16:14, Will Deacon wrote:
> Hi Julien,
> 
> On Fri, Sep 29, 2017 at 11:52:29AM +0100, Julien Thierry wrote:
>> The arch timer configuration for a CPU might get reset after suspending
>> said CPU.
>>
>> In order to reliably use the event stream in the kernel (e.g. for delays),
>> we keep track of the state where we can safely concider the event stream as
>> properly configured.
>>
>> Signed-off-by: Julien Thierry <julien.thierry@arm.com>
>> Cc: Mark Rutland <mark.rutland@arm.com>
>> Cc: Marc Zyngier <marc.zyngier@arm.com>
>> Cc: Russell King <linux@armlinux.org.uk>
>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>> Cc: Will Deacon <will.deacon@arm.com>
>> ---
>>   arch/arm/include/asm/arch_timer.h    |  1 +
>>   arch/arm64/include/asm/arch_timer.h  |  1 +
>>   drivers/clocksource/arm_arch_timer.c | 20 ++++++++++++++++++--
>>   include/clocksource/arm_arch_timer.h |  6 ++++++
>>   4 files changed, 26 insertions(+), 2 deletions(-)
> 
> The arch-timer bits needs an ack from Marc or Mark.
> 
>> diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h
>> index d4ebf56..0b6e104 100644
>> --- a/arch/arm/include/asm/arch_timer.h
>> +++ b/arch/arm/include/asm/arch_timer.h
>> @@ -106,6 +106,7 @@ static inline u32 arch_timer_get_cntkctl(void)
>>   static inline void arch_timer_set_cntkctl(u32 cntkctl)
>>   {
>>   	asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl));
>> +	isb();
>>   }
>>
>>   #endif
>> diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h
>> index a652ce0..bdedd8f 100644
>> --- a/arch/arm64/include/asm/arch_timer.h
>> +++ b/arch/arm64/include/asm/arch_timer.h
>> @@ -144,6 +144,7 @@ static inline u32 arch_timer_get_cntkctl(void)
>>   static inline void arch_timer_set_cntkctl(u32 cntkctl)
>>   {
>>   	write_sysreg(cntkctl, cntkctl_el1);
>> +	isb();
>>   }
>>
>>   static inline u64 arch_counter_get_cntpct(void)
>> diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
>> index fd4b7f6..47cf15e 100644
>> --- a/drivers/clocksource/arm_arch_timer.c
>> +++ b/drivers/clocksource/arm_arch_timer.c
>> @@ -77,6 +77,7 @@ struct arch_timer {
>>   static bool arch_counter_suspend_stop;
>>   static bool vdso_default = true;
>>
>> +static cpumask_t evtstrm_available;
>>   static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM);
>>
>>   static int __init early_evtstrm_cfg(char *buf)
>> @@ -740,6 +741,7 @@ static void arch_timer_evtstrm_enable(int divider)
>>   #ifdef CONFIG_COMPAT
>>   	compat_elf_hwcap |= COMPAT_HWCAP_EVTSTRM;
>>   #endif
>> +	cpumask_set_cpu(smp_processor_id(), &evtstrm_available);
>>   }
>>
>>   static void arch_timer_configure_evtstream(void)
>> @@ -864,6 +866,11 @@ u32 arch_timer_get_rate(void)
>>   	return arch_timer_rate;
>>   }
>>
>> +bool arch_timer_evtstrm_available(void)
>> +{
>> +	return !!cpumask_test_cpu(smp_processor_id(), &evtstrm_available);
>> +}
> 
> I don't think you need the '!!' prefix here.

True, I'll remove that.

> 
>> +
>>   static u64 arch_counter_get_cntvct_mem(void)
>>   {
>>   	u32 vct_lo, vct_hi, tmp_hi;
>> @@ -929,6 +936,8 @@ static int arch_timer_dying_cpu(unsigned int cpu)
>>   {
>>   	struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt);
>>
>> +	cpumask_clear_cpu(smp_processor_id(), &evtstrm_available);
>> +
>>   	arch_timer_stop(clk);
>>   	return 0;
>>   }
>> @@ -938,10 +947,16 @@ static int arch_timer_dying_cpu(unsigned int cpu)
>>   static int arch_timer_cpu_pm_notify(struct notifier_block *self,
>>   				    unsigned long action, void *hcpu)
>>   {
>> -	if (action == CPU_PM_ENTER)
>> +	if (action == CPU_PM_ENTER) {
>>   		__this_cpu_write(saved_cntkctl, arch_timer_get_cntkctl());
>> -	else if (action == CPU_PM_ENTER_FAILED || action == CPU_PM_EXIT)
>> +
>> +		cpumask_clear_cpu(smp_processor_id(), &evtstrm_available);
>> +	} else if (action == CPU_PM_ENTER_FAILED || action == CPU_PM_EXIT) {
>>   		arch_timer_set_cntkctl(__this_cpu_read(saved_cntkctl));
>> +
>> +		if (elf_hwcap & HWCAP_EVTSTRM)
>> +			cpumask_set_cpu(smp_processor_id(), &evtstrm_available);
>> +	}
>>   	return NOTIFY_OK;
>>   }
>>
>> @@ -1017,6 +1032,7 @@ static int __init arch_timer_register(void)
>>   	if (err)
>>   		goto out_unreg_notify;
>>
>> +	cpumask_clear(&evtstrm_available);
> 
> This should already be ok by virtue of the mask being static, no?
> Alternatively, you could use the CPU_MASK_NONE static initialiser.

Yes, I just prefer explicit initialisations. But you're right, I'll use 
CPU_MASK_NONE unless it is encouraged to rely on implicit intilisation.

Thanks,

-- 
Julien Thierry

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 1/2] arm_arch_timer: Expose event stream status
  2017-09-29 10:52 ` [PATCH v3 1/2] arm_arch_timer: Expose event stream status Julien Thierry
  2017-10-11 15:14   ` Will Deacon
@ 2017-10-12  9:27   ` Suzuki K Poulose
  2017-10-12  9:30     ` Will Deacon
  1 sibling, 1 reply; 15+ messages in thread
From: Suzuki K Poulose @ 2017-10-12  9:27 UTC (permalink / raw)
  To: linux-arm-kernel

On 29/09/17 11:52, Julien Thierry wrote:
> The arch timer configuration for a CPU might get reset after suspending
> said CPU.
> 
> In order to reliably use the event stream in the kernel (e.g. for delays),
> we keep track of the state where we can safely concider the event stream as

nit: consider

> properly configured.
> 
> Signed-off-by: Julien Thierry <julien.thierry@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Cc: Russell King <linux@armlinux.org.uk>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> ---
>   arch/arm/include/asm/arch_timer.h    |  1 +
>   arch/arm64/include/asm/arch_timer.h  |  1 +
>   drivers/clocksource/arm_arch_timer.c | 20 ++++++++++++++++++--
>   include/clocksource/arm_arch_timer.h |  6 ++++++
>   4 files changed, 26 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h
> index d4ebf56..0b6e104 100644
> --- a/arch/arm/include/asm/arch_timer.h
> +++ b/arch/arm/include/asm/arch_timer.h
> @@ -106,6 +106,7 @@ static inline u32 arch_timer_get_cntkctl(void)
>   static inline void arch_timer_set_cntkctl(u32 cntkctl)
>   {
>   	asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl));
> +	isb();
>   }
> 
>   #endif
> diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h
> index a652ce0..bdedd8f 100644
> --- a/arch/arm64/include/asm/arch_timer.h
> +++ b/arch/arm64/include/asm/arch_timer.h
> @@ -144,6 +144,7 @@ static inline u32 arch_timer_get_cntkctl(void)
>   static inline void arch_timer_set_cntkctl(u32 cntkctl)
>   {
>   	write_sysreg(cntkctl, cntkctl_el1);
> +	isb();
>   }
> 
>   static inline u64 arch_counter_get_cntpct(void)
> diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
> index fd4b7f6..47cf15e 100644
> --- a/drivers/clocksource/arm_arch_timer.c
> +++ b/drivers/clocksource/arm_arch_timer.c
> @@ -77,6 +77,7 @@ struct arch_timer {
>   static bool arch_counter_suspend_stop;
>   static bool vdso_default = true;
> 
> +static cpumask_t evtstrm_available;
>   static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM);
> 
>   static int __init early_evtstrm_cfg(char *buf)
> @@ -740,6 +741,7 @@ static void arch_timer_evtstrm_enable(int divider)
>   #ifdef CONFIG_COMPAT
>   	compat_elf_hwcap |= COMPAT_HWCAP_EVTSTRM;
>   #endif
> +	cpumask_set_cpu(smp_processor_id(), &evtstrm_available);
>   }
> 
>   static void arch_timer_configure_evtstream(void)
> @@ -864,6 +866,11 @@ u32 arch_timer_get_rate(void)
>   	return arch_timer_rate;
>   }
> 
> +bool arch_timer_evtstrm_available(void)
> +{
> +	return !!cpumask_test_cpu(smp_processor_id(), &evtstrm_available);
> +}
> +

This could live in the header file as static inlin, if the evtstrm_available
is made global and could avoid a function call where it is used.

Suzuki

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 1/2] arm_arch_timer: Expose event stream status
  2017-10-12  9:27   ` Suzuki K Poulose
@ 2017-10-12  9:30     ` Will Deacon
  2017-10-12  9:40       ` Julien Thierry
  0 siblings, 1 reply; 15+ messages in thread
From: Will Deacon @ 2017-10-12  9:30 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Oct 12, 2017 at 10:27:06AM +0100, Suzuki K Poulose wrote:
> On 29/09/17 11:52, Julien Thierry wrote:
> >The arch timer configuration for a CPU might get reset after suspending
> >said CPU.
> >
> >In order to reliably use the event stream in the kernel (e.g. for delays),
> >we keep track of the state where we can safely concider the event stream as
> 
> nit: consider
> 
> >properly configured.
> >
> >Signed-off-by: Julien Thierry <julien.thierry@arm.com>
> >Cc: Mark Rutland <mark.rutland@arm.com>
> >Cc: Marc Zyngier <marc.zyngier@arm.com>
> >Cc: Russell King <linux@armlinux.org.uk>
> >Cc: Catalin Marinas <catalin.marinas@arm.com>
> >Cc: Will Deacon <will.deacon@arm.com>
> >---
> >  arch/arm/include/asm/arch_timer.h    |  1 +
> >  arch/arm64/include/asm/arch_timer.h  |  1 +
> >  drivers/clocksource/arm_arch_timer.c | 20 ++++++++++++++++++--
> >  include/clocksource/arm_arch_timer.h |  6 ++++++
> >  4 files changed, 26 insertions(+), 2 deletions(-)
> >
> >diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h
> >index d4ebf56..0b6e104 100644
> >--- a/arch/arm/include/asm/arch_timer.h
> >+++ b/arch/arm/include/asm/arch_timer.h
> >@@ -106,6 +106,7 @@ static inline u32 arch_timer_get_cntkctl(void)
> >  static inline void arch_timer_set_cntkctl(u32 cntkctl)
> >  {
> >  	asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl));
> >+	isb();
> >  }
> >
> >  #endif
> >diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h
> >index a652ce0..bdedd8f 100644
> >--- a/arch/arm64/include/asm/arch_timer.h
> >+++ b/arch/arm64/include/asm/arch_timer.h
> >@@ -144,6 +144,7 @@ static inline u32 arch_timer_get_cntkctl(void)
> >  static inline void arch_timer_set_cntkctl(u32 cntkctl)
> >  {
> >  	write_sysreg(cntkctl, cntkctl_el1);
> >+	isb();
> >  }
> >
> >  static inline u64 arch_counter_get_cntpct(void)
> >diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
> >index fd4b7f6..47cf15e 100644
> >--- a/drivers/clocksource/arm_arch_timer.c
> >+++ b/drivers/clocksource/arm_arch_timer.c
> >@@ -77,6 +77,7 @@ struct arch_timer {
> >  static bool arch_counter_suspend_stop;
> >  static bool vdso_default = true;
> >
> >+static cpumask_t evtstrm_available;
> >  static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM);
> >
> >  static int __init early_evtstrm_cfg(char *buf)
> >@@ -740,6 +741,7 @@ static void arch_timer_evtstrm_enable(int divider)
> >  #ifdef CONFIG_COMPAT
> >  	compat_elf_hwcap |= COMPAT_HWCAP_EVTSTRM;
> >  #endif
> >+	cpumask_set_cpu(smp_processor_id(), &evtstrm_available);
> >  }
> >
> >  static void arch_timer_configure_evtstream(void)
> >@@ -864,6 +866,11 @@ u32 arch_timer_get_rate(void)
> >  	return arch_timer_rate;
> >  }
> >
> >+bool arch_timer_evtstrm_available(void)
> >+{
> >+	return !!cpumask_test_cpu(smp_processor_id(), &evtstrm_available);
> >+}
> >+
> 
> This could live in the header file as static inlin, if the evtstrm_available
> is made global and could avoid a function call where it is used.

You might need an EXPORT_SYMBOl as well if you go down that route.

Will

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 1/2] arm_arch_timer: Expose event stream status
  2017-10-12  9:30     ` Will Deacon
@ 2017-10-12  9:40       ` Julien Thierry
  2017-10-12 10:26         ` Will Deacon
  0 siblings, 1 reply; 15+ messages in thread
From: Julien Thierry @ 2017-10-12  9:40 UTC (permalink / raw)
  To: linux-arm-kernel



On 12/10/17 10:30, Will Deacon wrote:
> On Thu, Oct 12, 2017 at 10:27:06AM +0100, Suzuki K Poulose wrote:
>> On 29/09/17 11:52, Julien Thierry wrote:
>>> The arch timer configuration for a CPU might get reset after suspending
>>> said CPU.
>>>
>>> In order to reliably use the event stream in the kernel (e.g. for delays),
>>> we keep track of the state where we can safely concider the event stream as
>>
>> nit: consider
>>
>>> properly configured.
>>>
>>> Signed-off-by: Julien Thierry <julien.thierry@arm.com>
>>> Cc: Mark Rutland <mark.rutland@arm.com>
>>> Cc: Marc Zyngier <marc.zyngier@arm.com>
>>> Cc: Russell King <linux@armlinux.org.uk>
>>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>>> Cc: Will Deacon <will.deacon@arm.com>
>>> ---
>>>   arch/arm/include/asm/arch_timer.h    |  1 +
>>>   arch/arm64/include/asm/arch_timer.h  |  1 +
>>>   drivers/clocksource/arm_arch_timer.c | 20 ++++++++++++++++++--
>>>   include/clocksource/arm_arch_timer.h |  6 ++++++
>>>   4 files changed, 26 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h
>>> index d4ebf56..0b6e104 100644
>>> --- a/arch/arm/include/asm/arch_timer.h
>>> +++ b/arch/arm/include/asm/arch_timer.h
>>> @@ -106,6 +106,7 @@ static inline u32 arch_timer_get_cntkctl(void)
>>>   static inline void arch_timer_set_cntkctl(u32 cntkctl)
>>>   {
>>>   	asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl));
>>> +	isb();
>>>   }
>>>
>>>   #endif
>>> diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h
>>> index a652ce0..bdedd8f 100644
>>> --- a/arch/arm64/include/asm/arch_timer.h
>>> +++ b/arch/arm64/include/asm/arch_timer.h
>>> @@ -144,6 +144,7 @@ static inline u32 arch_timer_get_cntkctl(void)
>>>   static inline void arch_timer_set_cntkctl(u32 cntkctl)
>>>   {
>>>   	write_sysreg(cntkctl, cntkctl_el1);
>>> +	isb();
>>>   }
>>>
>>>   static inline u64 arch_counter_get_cntpct(void)
>>> diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
>>> index fd4b7f6..47cf15e 100644
>>> --- a/drivers/clocksource/arm_arch_timer.c
>>> +++ b/drivers/clocksource/arm_arch_timer.c
>>> @@ -77,6 +77,7 @@ struct arch_timer {
>>>   static bool arch_counter_suspend_stop;
>>>   static bool vdso_default = true;
>>>
>>> +static cpumask_t evtstrm_available;
>>>   static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM);
>>>
>>>   static int __init early_evtstrm_cfg(char *buf)
>>> @@ -740,6 +741,7 @@ static void arch_timer_evtstrm_enable(int divider)
>>>   #ifdef CONFIG_COMPAT
>>>   	compat_elf_hwcap |= COMPAT_HWCAP_EVTSTRM;
>>>   #endif
>>> +	cpumask_set_cpu(smp_processor_id(), &evtstrm_available);
>>>   }
>>>
>>>   static void arch_timer_configure_evtstream(void)
>>> @@ -864,6 +866,11 @@ u32 arch_timer_get_rate(void)
>>>   	return arch_timer_rate;
>>>   }
>>>
>>> +bool arch_timer_evtstrm_available(void)
>>> +{
>>> +	return !!cpumask_test_cpu(smp_processor_id(), &evtstrm_available);
>>> +}
>>> +
>>
>> This could live in the header file as static inlin, if the evtstrm_available
>> is made global and could avoid a function call where it is used.
> 
> You might need an EXPORT_SYMBOl as well if you go down that route.

Hmmm, I'm not fond of making the cpu mask global. I understand you can 
avoid the branch + ret of the function, but generally you want to check 
if the event stream is present to know if you can use wfe and wake up, 
so I don't think it might be used in a performance critical path.

So I'm wondering, is it really worth it?

Cheers,

-- 
Julien Thierry

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 1/2] arm_arch_timer: Expose event stream status
  2017-10-12  9:40       ` Julien Thierry
@ 2017-10-12 10:26         ` Will Deacon
  2017-10-12 12:28           ` Julien Thierry
  0 siblings, 1 reply; 15+ messages in thread
From: Will Deacon @ 2017-10-12 10:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Oct 12, 2017 at 10:40:57AM +0100, Julien Thierry wrote:
> 
> 
> On 12/10/17 10:30, Will Deacon wrote:
> >On Thu, Oct 12, 2017 at 10:27:06AM +0100, Suzuki K Poulose wrote:
> >>On 29/09/17 11:52, Julien Thierry wrote:
> >>>The arch timer configuration for a CPU might get reset after suspending
> >>>said CPU.
> >>>
> >>>In order to reliably use the event stream in the kernel (e.g. for delays),
> >>>we keep track of the state where we can safely concider the event stream as
> >>
> >>nit: consider
> >>
> >>>properly configured.
> >>>
> >>>Signed-off-by: Julien Thierry <julien.thierry@arm.com>
> >>>Cc: Mark Rutland <mark.rutland@arm.com>
> >>>Cc: Marc Zyngier <marc.zyngier@arm.com>
> >>>Cc: Russell King <linux@armlinux.org.uk>
> >>>Cc: Catalin Marinas <catalin.marinas@arm.com>
> >>>Cc: Will Deacon <will.deacon@arm.com>
> >>>---
> >>>  arch/arm/include/asm/arch_timer.h    |  1 +
> >>>  arch/arm64/include/asm/arch_timer.h  |  1 +
> >>>  drivers/clocksource/arm_arch_timer.c | 20 ++++++++++++++++++--
> >>>  include/clocksource/arm_arch_timer.h |  6 ++++++
> >>>  4 files changed, 26 insertions(+), 2 deletions(-)
> >>>
> >>>diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h
> >>>index d4ebf56..0b6e104 100644
> >>>--- a/arch/arm/include/asm/arch_timer.h
> >>>+++ b/arch/arm/include/asm/arch_timer.h
> >>>@@ -106,6 +106,7 @@ static inline u32 arch_timer_get_cntkctl(void)
> >>>  static inline void arch_timer_set_cntkctl(u32 cntkctl)
> >>>  {
> >>>  	asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl));
> >>>+	isb();
> >>>  }
> >>>
> >>>  #endif
> >>>diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h
> >>>index a652ce0..bdedd8f 100644
> >>>--- a/arch/arm64/include/asm/arch_timer.h
> >>>+++ b/arch/arm64/include/asm/arch_timer.h
> >>>@@ -144,6 +144,7 @@ static inline u32 arch_timer_get_cntkctl(void)
> >>>  static inline void arch_timer_set_cntkctl(u32 cntkctl)
> >>>  {
> >>>  	write_sysreg(cntkctl, cntkctl_el1);
> >>>+	isb();
> >>>  }
> >>>
> >>>  static inline u64 arch_counter_get_cntpct(void)
> >>>diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
> >>>index fd4b7f6..47cf15e 100644
> >>>--- a/drivers/clocksource/arm_arch_timer.c
> >>>+++ b/drivers/clocksource/arm_arch_timer.c
> >>>@@ -77,6 +77,7 @@ struct arch_timer {
> >>>  static bool arch_counter_suspend_stop;
> >>>  static bool vdso_default = true;
> >>>
> >>>+static cpumask_t evtstrm_available;
> >>>  static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM);
> >>>
> >>>  static int __init early_evtstrm_cfg(char *buf)
> >>>@@ -740,6 +741,7 @@ static void arch_timer_evtstrm_enable(int divider)
> >>>  #ifdef CONFIG_COMPAT
> >>>  	compat_elf_hwcap |= COMPAT_HWCAP_EVTSTRM;
> >>>  #endif
> >>>+	cpumask_set_cpu(smp_processor_id(), &evtstrm_available);
> >>>  }
> >>>
> >>>  static void arch_timer_configure_evtstream(void)
> >>>@@ -864,6 +866,11 @@ u32 arch_timer_get_rate(void)
> >>>  	return arch_timer_rate;
> >>>  }
> >>>
> >>>+bool arch_timer_evtstrm_available(void)
> >>>+{
> >>>+	return !!cpumask_test_cpu(smp_processor_id(), &evtstrm_available);
> >>>+}
> >>>+
> >>
> >>This could live in the header file as static inlin, if the evtstrm_available
> >>is made global and could avoid a function call where it is used.
> >
> >You might need an EXPORT_SYMBOl as well if you go down that route.
> 
> Hmmm, I'm not fond of making the cpu mask global. I understand you can avoid
> the branch + ret of the function, but generally you want to check if the
> event stream is present to know if you can use wfe and wake up, so I don't
> think it might be used in a performance critical path.
> 
> So I'm wondering, is it really worth it?

I have no strong preference, but I think you'll need o EXPORT something
either way so that delay and friends can be used from modules.

Will

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 1/2] arm_arch_timer: Expose event stream status
  2017-10-12 10:26         ` Will Deacon
@ 2017-10-12 12:28           ` Julien Thierry
  0 siblings, 0 replies; 15+ messages in thread
From: Julien Thierry @ 2017-10-12 12:28 UTC (permalink / raw)
  To: linux-arm-kernel



On 12/10/17 11:26, Will Deacon wrote:
> On Thu, Oct 12, 2017 at 10:40:57AM +0100, Julien Thierry wrote:
>>
>>
>> On 12/10/17 10:30, Will Deacon wrote:
>>> On Thu, Oct 12, 2017 at 10:27:06AM +0100, Suzuki K Poulose wrote:
>>>> On 29/09/17 11:52, Julien Thierry wrote:
>>>>> The arch timer configuration for a CPU might get reset after suspending
>>>>> said CPU.
>>>>>
>>>>> In order to reliably use the event stream in the kernel (e.g. for delays),
>>>>> we keep track of the state where we can safely concider the event stream as
>>>>
>>>> nit: consider
>>>>
>>>>> properly configured.
>>>>>
>>>>> Signed-off-by: Julien Thierry <julien.thierry@arm.com>
>>>>> Cc: Mark Rutland <mark.rutland@arm.com>
>>>>> Cc: Marc Zyngier <marc.zyngier@arm.com>
>>>>> Cc: Russell King <linux@armlinux.org.uk>
>>>>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>>>>> Cc: Will Deacon <will.deacon@arm.com>
>>>>> ---
>>>>>   arch/arm/include/asm/arch_timer.h    |  1 +
>>>>>   arch/arm64/include/asm/arch_timer.h  |  1 +
>>>>>   drivers/clocksource/arm_arch_timer.c | 20 ++++++++++++++++++--
>>>>>   include/clocksource/arm_arch_timer.h |  6 ++++++
>>>>>   4 files changed, 26 insertions(+), 2 deletions(-)
>>>>>
>>>>> diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h
>>>>> index d4ebf56..0b6e104 100644
>>>>> --- a/arch/arm/include/asm/arch_timer.h
>>>>> +++ b/arch/arm/include/asm/arch_timer.h
>>>>> @@ -106,6 +106,7 @@ static inline u32 arch_timer_get_cntkctl(void)
>>>>>   static inline void arch_timer_set_cntkctl(u32 cntkctl)
>>>>>   {
>>>>>   	asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl));
>>>>> +	isb();
>>>>>   }
>>>>>
>>>>>   #endif
>>>>> diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h
>>>>> index a652ce0..bdedd8f 100644
>>>>> --- a/arch/arm64/include/asm/arch_timer.h
>>>>> +++ b/arch/arm64/include/asm/arch_timer.h
>>>>> @@ -144,6 +144,7 @@ static inline u32 arch_timer_get_cntkctl(void)
>>>>>   static inline void arch_timer_set_cntkctl(u32 cntkctl)
>>>>>   {
>>>>>   	write_sysreg(cntkctl, cntkctl_el1);
>>>>> +	isb();
>>>>>   }
>>>>>
>>>>>   static inline u64 arch_counter_get_cntpct(void)
>>>>> diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
>>>>> index fd4b7f6..47cf15e 100644
>>>>> --- a/drivers/clocksource/arm_arch_timer.c
>>>>> +++ b/drivers/clocksource/arm_arch_timer.c
>>>>> @@ -77,6 +77,7 @@ struct arch_timer {
>>>>>   static bool arch_counter_suspend_stop;
>>>>>   static bool vdso_default = true;
>>>>>
>>>>> +static cpumask_t evtstrm_available;
>>>>>   static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM);
>>>>>
>>>>>   static int __init early_evtstrm_cfg(char *buf)
>>>>> @@ -740,6 +741,7 @@ static void arch_timer_evtstrm_enable(int divider)
>>>>>   #ifdef CONFIG_COMPAT
>>>>>   	compat_elf_hwcap |= COMPAT_HWCAP_EVTSTRM;
>>>>>   #endif
>>>>> +	cpumask_set_cpu(smp_processor_id(), &evtstrm_available);
>>>>>   }
>>>>>
>>>>>   static void arch_timer_configure_evtstream(void)
>>>>> @@ -864,6 +866,11 @@ u32 arch_timer_get_rate(void)
>>>>>   	return arch_timer_rate;
>>>>>   }
>>>>>
>>>>> +bool arch_timer_evtstrm_available(void)
>>>>> +{
>>>>> +	return !!cpumask_test_cpu(smp_processor_id(), &evtstrm_available);
>>>>> +}
>>>>> +
>>>>
>>>> This could live in the header file as static inlin, if the evtstrm_available
>>>> is made global and could avoid a function call where it is used.
>>>
>>> You might need an EXPORT_SYMBOl as well if you go down that route.
>>
>> Hmmm, I'm not fond of making the cpu mask global. I understand you can avoid
>> the branch + ret of the function, but generally you want to check if the
>> event stream is present to know if you can use wfe and wake up, so I don't
>> think it might be used in a performance critical path.
>>
>> So I'm wondering, is it really worth it?
> 
> I have no strong preference, but I think you'll need o EXPORT something
> either way so that delay and friends can be used from modules.
> 

Turns out this is not the case. arch_timer_evtstrm_available is called 
by __delay which is itself exported and available for module.

So unless a module needs to check availability of the event stream there 
is no need to export it. I'll leave it like this for now unless there is 
a strong case to be able to inline or export arch_timer_evtstrm_available.

Thanks,

-- 
Julien Thierry

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2017-10-12 12:28 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-29 10:52 [PATCH v3 0/2] WFE for long delays Julien Thierry
2017-09-29 10:52 ` [PATCH v3 1/2] arm_arch_timer: Expose event stream status Julien Thierry
2017-10-11 15:14   ` Will Deacon
2017-10-12  8:38     ` Julien Thierry
2017-10-12  8:58     ` Julien Thierry
2017-10-12  9:27   ` Suzuki K Poulose
2017-10-12  9:30     ` Will Deacon
2017-10-12  9:40       ` Julien Thierry
2017-10-12 10:26         ` Will Deacon
2017-10-12 12:28           ` Julien Thierry
2017-09-29 10:52 ` [PATCH v3 2/2] arm64: use WFE for long delays Julien Thierry
2017-10-11 15:13   ` Will Deacon
2017-10-12  8:47     ` Julien Thierry
2017-10-12  8:52       ` Will Deacon
2017-10-12  8:54         ` Julien Thierry

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.