Hi,
This is my third attempt to migrate clockevent drivers to use set_dev_mode(). I have tried to fix all issues raised by Frederic/Kevin on V2.
Please let me know if I missed something. Though patches 2-7 look big, it should be fairly easy to review them now, so do try that :)
---------
A clockevent device should be stopped, or its events should be masked, if next event is expected at KTIME_MAX, i.e. no events are required for very long time.
This would normally happen with NO_HZ (both NO_HZ_IDLE and NO_HZ_FULL) when tick-sched timer is removed and we don't have any more timers scheduled for long.
If we don't STOP clockevent device, we are guaranteed to receive at least one spurious interrupt, as hrtimer_force_reprogram() isn't reprogramming the event device (on expires == KTIME_MAX). Depending on particular implementation of clockevent device, this can be a spurious interrupt at tick-rate.. (When driver is emulating ONESHOT over PERIODIC mode. This was observed on at-least one implementation: arm_arch_timer.c).
A simple (yet hacky) solution to get this fixed could be: update hrtimer_force_reprogram() to always reprogram clockevent device and update clockevent drivers to STOP generating events (or delay it to max time), when 'expires' is set to KTIME_MAX. But the drawback here is that every clockevent driver has to be hacked for this particular case and its very easy for new ones to miss this.
However, Thomas suggested to add an optional mode: ONESHOT_STOPPED (lkml.org/lkml/2014/5/9/508) to solve this problem.
clockevents core would need to reconfigure mode later, when event is required again, for platforms that implement ONESHOT_STOPPED mode and so it must know which platforms implement it and which don't. This requires ->set_mode() callback to have capability to return 'success' or 'failure'. Currently its return type is 'void'.
To change return type of set_mode(), Thomas suggested to implement another callback: ->set_dev_mode(), with return type 'int'. We can then convert clockevent drivers to use this interface instead of existing ->set_mode() and then finally remove ->set_mode()'s support.
This patchset first adds another callback with return capability, set_dev_mode(), then it migrates all drivers one by one and finally removes earlier callback set_mode() when nobody is using it.
NOTE: Following issue is still unresolved as this patchset isn't making it worse. But it should be fixed before addition of ONESHOT_STOPPED mode.
Few clockevent drivers have disabled clock events as soon as we enter their ->set_dev_mode() callbacks and so they stay disabled for unsupported modes as well.
All clockevent drivers are handling modes in ->set_dev_mode() with help of a 'switch' block. For the currently available modes none of them would ever get down to the 'default case' of switch block.
And so we would never hit the BUG where we failed to change mode and still disabled clock events.
But as soon as any new mode would be introduced in clockevents core, some of these might behave unexpectedly. Like, core may expect events to be enabled as call to ->set_dev_mode() returned failure and may not try enabling events again.
V2->V3: - s/WARN_ON/WARN_ON_ONCE - improved logs - V2 had code belonging to problem mentioned in "NOTE" above, its dropped now and would be addressed separately.
Viresh Kumar (8): clockevents: add ->set_dev_mode() to struct clock_event_device clockevents: arm: migrate to ->set_dev_mode() clockevents: mips: migrate to ->set_dev_mode() clockevents: sparc: migrate to ->set_dev_mode() clockevents: x86: migrate to ->set_dev_mode() clockevents: drivers/: migrate to ->set_dev_mode() clockevents: misc: migrate to ->set_dev_mode() clockevents: remove ->set_mode() from struct clock_event_device
arch/alpha/kernel/time.c | 32 ++++++++++++++++++---- arch/arc/kernel/time.c | 11 +++++--- arch/arm/common/timer-sp.c | 9 ++++--- arch/arm/kernel/smp_twd.c | 10 ++++--- arch/arm/mach-at91/at91rm9200_time.c | 7 +++-- arch/arm/mach-at91/at91sam926x_time.c | 11 ++++---- arch/arm/mach-clps711x/common.c | 9 ++++--- arch/arm/mach-cns3xxx/core.c | 10 ++++--- arch/arm/mach-davinci/time.c | 7 +++-- arch/arm/mach-footbridge/dc21285-timer.c | 7 +++-- arch/arm/mach-gemini/time.c | 7 ++--- arch/arm/mach-imx/epit.c | 11 ++++---- arch/arm/mach-imx/time.c | 11 ++++---- arch/arm/mach-integrator/integrator_ap.c | 8 +++--- arch/arm/mach-ixp4xx/common.c | 8 +++--- arch/arm/mach-ks8695/time.c | 22 ++++++++++----- arch/arm/mach-lpc32xx/timer.c | 11 ++++---- arch/arm/mach-mmp/time.c | 12 +++++---- arch/arm/mach-netx/time.c | 11 ++++---- arch/arm/mach-omap1/time.c | 7 +++-- arch/arm/mach-omap1/timer32k.c | 7 +++-- arch/arm/mach-omap2/timer.c | 7 +++-- arch/arm/mach-pxa/time.c | 8 +++--- arch/arm/mach-sa1100/time.c | 8 +++--- arch/arm/mach-spear/time.c | 10 +++---- arch/arm/mach-w90x900/time.c | 7 +++-- arch/arm/plat-iop/time.c | 8 +++--- arch/arm/plat-orion/time.c | 20 ++++++++++---- arch/avr32/kernel/time.c | 7 ++--- arch/blackfin/kernel/time-ts.c | 14 +++++++--- arch/c6x/platforms/timer64.c | 7 +++-- arch/hexagon/kernel/time.c | 11 +++++--- arch/m68k/platform/coldfire/pit.c | 7 +++-- arch/microblaze/kernel/timer.c | 7 +++-- arch/mips/alchemy/common/time.c | 14 ++++++++-- arch/mips/include/asm/cevt-r4k.h | 2 +- arch/mips/jazz/irq.c | 14 ++++++++-- arch/mips/jz4740/time.c | 9 ++++--- arch/mips/kernel/cevt-bcm1480.c | 11 +++++--- arch/mips/kernel/cevt-ds1287.c | 12 ++++++--- arch/mips/kernel/cevt-gic.c | 14 ++++++++-- arch/mips/kernel/cevt-gt641xx.c | 12 ++++++--- arch/mips/kernel/cevt-r4k.c | 14 ++++++++-- arch/mips/kernel/cevt-sb1250.c | 11 +++++--- arch/mips/kernel/cevt-smtc.c | 2 +- arch/mips/kernel/cevt-txx9.c | 7 +++-- arch/mips/loongson/common/cs5536/cs5536_mfgpt.c | 12 ++++----- arch/mips/ralink/cevt-rt3352.c | 13 +++++---- arch/mips/sgi-ip27/ip27-timer.c | 14 ++++++++-- arch/mips/sni/time.c | 9 ++++--- arch/mn10300/kernel/cevt-mn10300.c | 14 ++++++++-- arch/openrisc/kernel/time.c | 11 ++++---- arch/powerpc/kernel/time.c | 16 ++++++++--- arch/s390/kernel/time.c | 14 ++++++++-- arch/score/kernel/time.c | 8 +++--- arch/sh/kernel/localtimer.c | 15 +++++++++-- arch/sparc/kernel/time_32.c | 18 ++++++++----- arch/sparc/kernel/time_64.c | 11 ++++---- arch/tile/kernel/time.c | 16 ++++++++--- arch/um/kernel/time.c | 7 +++-- arch/unicore32/kernel/time.c | 8 +++--- arch/x86/kernel/apic/apic.c | 10 ++++--- arch/x86/kernel/hpet.c | 19 +++++++------ arch/x86/lguest/boot.c | 9 ++++--- arch/x86/platform/uv/uv_time.c | 10 ++++--- arch/x86/xen/time.c | 23 +++++++--------- arch/xtensa/kernel/time.c | 9 ++++--- drivers/clocksource/arm_arch_timer.c | 36 ++++++++++++++----------- drivers/clocksource/arm_global_timer.c | 9 ++++--- drivers/clocksource/bcm2835_timer.c | 8 +++--- drivers/clocksource/bcm_kona_timer.c | 10 ++++--- drivers/clocksource/cadence_ttc_timer.c | 7 +++-- drivers/clocksource/cs5535-clockevt.c | 17 +++++++++--- drivers/clocksource/dummy_timer.c | 15 +++++++++-- drivers/clocksource/dw_apb_timer.c | 7 +++-- drivers/clocksource/em_sti.c | 11 +++++--- drivers/clocksource/exynos_mct.c | 16 +++++++---- drivers/clocksource/i8253.c | 8 ++++-- drivers/clocksource/metag_generic.c | 11 ++++---- drivers/clocksource/moxart_timer.c | 8 +++--- drivers/clocksource/mxs_timer.c | 10 +++---- drivers/clocksource/nomadik-mtu.c | 7 +++-- drivers/clocksource/qcom-timer.c | 11 ++++---- drivers/clocksource/samsung_pwm_timer.c | 7 +++-- drivers/clocksource/sh_cmt.c | 9 ++++--- drivers/clocksource/sh_mtu2.c | 9 ++++--- drivers/clocksource/sh_tmu.c | 9 ++++--- drivers/clocksource/sun4i_timer.c | 9 ++++--- drivers/clocksource/tcb_clksrc.c | 11 +++++--- drivers/clocksource/tegra20_timer.c | 7 +++-- drivers/clocksource/time-armada-370-xp.c | 20 +++++++++----- drivers/clocksource/time-efm32.c | 7 +++-- drivers/clocksource/time-orion.c | 17 +++++++++--- drivers/clocksource/timer-keystone.c | 9 ++++--- drivers/clocksource/timer-marco.c | 10 ++++--- drivers/clocksource/timer-prima2.c | 10 +++---- drivers/clocksource/timer-sun5i.c | 10 ++++--- drivers/clocksource/timer-u300.c | 7 +++-- drivers/clocksource/vf_pit_timer.c | 12 ++++++--- drivers/clocksource/vt8500_timer.c | 8 +++--- drivers/clocksource/zevio-timer.c | 9 +++---- include/linux/clockchips.h | 4 +-- kernel/time/clockevents.c | 7 +++-- kernel/time/tick-broadcast-hrtimer.c | 11 +++++--- kernel/time/timer_list.c | 2 +- 105 files changed, 756 insertions(+), 376 deletions(-)