[PATCH v3 24/41] powerpc: add set_dec_or_work API for safely updating decrementer
Alexey Kardashevskiy
aik at ozlabs.ru
Mon Mar 22 20:38:35 AEDT 2021
On 06/03/2021 02:06, Nicholas Piggin wrote:
> Decrementer updates must always check for new irq work to avoid an
> irq work decrementer interrupt being lost.
>
> Add an API for this in the timer code so callers don't have to care
> about details.
>
> Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
Reviewed-by: Alexey Kardashevskiy <aik at ozlabs.ru>
> ---
> arch/powerpc/include/asm/time.h | 9 +++++++++
> arch/powerpc/kernel/time.c | 20 +++++++++++---------
> 2 files changed, 20 insertions(+), 9 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/time.h b/arch/powerpc/include/asm/time.h
> index 0128cd9769bc..d62bde57bf02 100644
> --- a/arch/powerpc/include/asm/time.h
> +++ b/arch/powerpc/include/asm/time.h
> @@ -78,6 +78,15 @@ static inline void set_dec(u64 val)
> mtspr(SPRN_DEC, val - 1);
> }
>
> +#ifdef CONFIG_IRQ_WORK
> +void set_dec_or_work(u64 val);
> +#else
> +static inline void set_dec_or_work(u64 val)
> +{
> + set_dec(val);
> +}
> +#endif
> +
> static inline unsigned long tb_ticks_since(unsigned long tstamp)
> {
> return mftb() - tstamp;
> diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
> index c5d524622c17..341cc8442e5e 100644
> --- a/arch/powerpc/kernel/time.c
> +++ b/arch/powerpc/kernel/time.c
> @@ -562,6 +562,15 @@ void arch_irq_work_raise(void)
> preempt_enable();
> }
>
> +void set_dec_or_work(u64 val)
> +{
> + set_dec(val);
> + /* We may have raced with new irq work */
> + if (unlikely(test_irq_work_pending()))
> + set_dec(1);
> +}
> +EXPORT_SYMBOL_GPL(set_dec_or_work);
> +
> #else /* CONFIG_IRQ_WORK */
>
> #define test_irq_work_pending() 0
> @@ -629,10 +638,7 @@ DEFINE_INTERRUPT_HANDLER_ASYNC(timer_interrupt)
> } else {
> now = *next_tb - now;
> if (now <= decrementer_max)
> - set_dec(now);
> - /* We may have raced with new irq work */
> - if (test_irq_work_pending())
> - set_dec(1);
> + set_dec_or_work(now);
> __this_cpu_inc(irq_stat.timer_irqs_others);
> }
>
> @@ -874,11 +880,7 @@ static int decrementer_set_next_event(unsigned long evt,
> struct clock_event_device *dev)
> {
> __this_cpu_write(decrementers_next_tb, get_tb() + evt);
> - set_dec(evt);
> -
> - /* We may have raced with new irq work */
> - if (test_irq_work_pending())
> - set_dec(1);
> + set_dec_or_work(evt);
>
> return 0;
> }
>
--
Alexey
More information about the Linuxppc-dev
mailing list