Hi,
Here goes the fourth version and its very much light weight compared to earlier versions. I hope I haven't missed any review comments here :)
More or less all patches are updated to get rid of all unrelated changes, like removing unsupported modes OR not disabling events for default cases..
So, please review them again :)
Here goes the mainline version of cover-letter:
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 fake 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.
With this proposal, introducing a new ONESHOT_STOPPED mode would require the core to know whether the platform implements this mode so it could be reprogrammed later.
In order for the core to tell if the mode is implemented, ->set_mode() callback needs to be able to return success or failure.
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 to it and finally removes earlier callback set_mode() when it has no more users.
FIXME: There are two issues which *may* be required to fix separately.
1. Few drivers still have 'switch cases' for handling unsupported modes (like: drivers not supporting ONESHOT have a 'case: ONESHOT' with or without a WARN/BUG/pr_err/etc). As we now have a WARN() in core, we don't need these in individual drivers and they can be removed.
2. Few clockevent drivers have disabled clock events as soon as we enter their ->set_dev_mode() callbacks and so they stay disabled for 'default case' as well. We *may* need to fix these drivers in case we don't want them to disable events in 'default case'. After this series we will never hit 'default case' as we are handling all cases separately, but it might be required to fix them before ONESHOT_STOPPED series gets in.
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 | 8 ++++-- arch/arm/mach-clps711x/common.c | 7 +++-- 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 | 7 +++-- arch/arm/mach-imx/time.c | 7 +++-- arch/arm/mach-integrator/integrator_ap.c | 9 ++++--- arch/arm/mach-ixp4xx/common.c | 8 +++--- arch/arm/mach-ks8695/time.c | 22 ++++++++++----- arch/arm/mach-lpc32xx/timer.c | 7 +++-- arch/arm/mach-mmp/time.c | 11 +++++--- 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 | 7 +++-- arch/arm/mach-sa1100/time.c | 7 +++-- 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 | 9 ++++--- 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 | 9 ++++--- arch/mips/kernel/cevt-smtc.c | 2 +- arch/mips/kernel/cevt-txx9.c | 7 +++-- arch/mips/loongson/common/cs5536/cs5536_mfgpt.c | 8 ++++-- arch/mips/ralink/cevt-rt3352.c | 13 +++++---- arch/mips/sgi-ip27/ip27-timer.c | 14 ++++++++-- arch/mips/sni/time.c | 7 +++-- arch/mn10300/kernel/cevt-mn10300.c | 14 ++++++++-- arch/openrisc/kernel/time.c | 7 +++-- arch/powerpc/kernel/time.c | 18 ++++++++++--- arch/s390/kernel/time.c | 14 ++++++++-- arch/score/kernel/time.c | 7 ++--- arch/sh/kernel/localtimer.c | 15 +++++++++-- arch/sparc/kernel/time_32.c | 18 ++++++++----- arch/sparc/kernel/time_64.c | 7 +++-- arch/tile/kernel/time.c | 16 ++++++++--- arch/um/kernel/time.c | 7 +++-- arch/unicore32/kernel/time.c | 7 +++-- arch/x86/kernel/apic/apic.c | 10 ++++--- arch/x86/kernel/hpet.c | 19 +++++++------ arch/x86/lguest/boot.c | 7 +++-- arch/x86/platform/uv/uv_time.c | 9 ++++--- arch/x86/xen/time.c | 14 +++++++--- 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 | 7 +++-- drivers/clocksource/moxart_timer.c | 8 +++--- drivers/clocksource/mxs_timer.c | 7 +++-- drivers/clocksource/nomadik-mtu.c | 7 +++-- drivers/clocksource/qcom-timer.c | 9 ++++--- 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 | 7 +++-- drivers/clocksource/timer-sun5i.c | 9 ++++--- drivers/clocksource/timer-u300.c | 7 +++-- drivers/clocksource/vf_pit_timer.c | 12 ++++++--- drivers/clocksource/vt8500_timer.c | 7 +++-- drivers/clocksource/zevio-timer.c | 8 +++--- 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, 757 insertions(+), 311 deletions(-)
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 fake 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.
With this proposal, introducing a new ONESHOT_STOPPED mode would require the core to know whether the platform implements this mode so it could be reprogrammed later.
In order for the core to tell if the mode is implemented, ->set_mode() callback needs to be able to return success or failure.
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 patch adds support for ->set_dev_mode() in clockevents core.
For now, just add a WARN_ON_ONCE() to callers of ->set_dev_mode() as none of currently implemented modes are expected/allowed to fail.
Reviewed-by: Preeti U Murthy preeti@linux.vnet.ibm.com Signed-off-by: Viresh Kumar viresh.kumar@linaro.org --- include/linux/clockchips.h | 5 ++++- kernel/time/clockevents.c | 17 ++++++++++++++--- kernel/time/timer_list.c | 5 ++++- 3 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h index 2e4cb67..8ab1a86 100644 --- a/include/linux/clockchips.h +++ b/include/linux/clockchips.h @@ -81,7 +81,8 @@ enum clock_event_mode { * @mode: operating mode assigned by the management code * @features: features * @retries: number of forced programming retries - * @set_mode: set mode function + * @set_dev_mode: set dev mode function + * @set_mode: set mode function (deprecated, use set_dev_mode instead) * @broadcast: function to broadcast events * @min_delta_ticks: minimum delta value in ticks stored for reconfiguration * @max_delta_ticks: maximum delta value in ticks stored for reconfiguration @@ -109,6 +110,8 @@ struct clock_event_device { unsigned long retries;
void (*broadcast)(const struct cpumask *mask); + int (*set_dev_mode)(enum clock_event_mode mode, + struct clock_event_device *); void (*set_mode)(enum clock_event_mode mode, struct clock_event_device *); void (*suspend)(struct clock_event_device *); diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index ad362c2..c9bef22 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -105,7 +105,12 @@ void clockevents_set_mode(struct clock_event_device *dev, enum clock_event_mode mode) { if (dev->mode != mode) { - dev->set_mode(mode, dev); + /* WARN_ON? Currently available modes shouldn't fail */ + if (dev->set_dev_mode) + WARN_ON_ONCE(dev->set_dev_mode(mode, dev)); + else + dev->set_mode(mode, dev); + dev->mode = mode;
/* @@ -446,8 +451,14 @@ int __clockevents_update_freq(struct clock_event_device *dev, u32 freq) if (dev->mode == CLOCK_EVT_MODE_ONESHOT) return clockevents_program_event(dev, dev->next_event, false);
- if (dev->mode == CLOCK_EVT_MODE_PERIODIC) - dev->set_mode(CLOCK_EVT_MODE_PERIODIC, dev); + if (dev->mode == CLOCK_EVT_MODE_PERIODIC) { + /* WARN_ON? Shouldn't fail while setting PERIODIC MODE */ + if (dev->set_dev_mode) + WARN_ON_ONCE(dev->set_dev_mode(CLOCK_EVT_MODE_PERIODIC, + dev)); + else + dev->set_mode(CLOCK_EVT_MODE_PERIODIC, dev); + }
return 0; } diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c index 61ed862..957a049 100644 --- a/kernel/time/timer_list.c +++ b/kernel/time/timer_list.c @@ -229,7 +229,10 @@ print_tickdevice(struct seq_file *m, struct tick_device *td, int cpu) SEQ_printf(m, "\n");
SEQ_printf(m, " set_mode: "); - print_name_offset(m, dev->set_mode); + if (dev->set_dev_mode) + print_name_offset(m, dev->set_dev_mode); + else + print_name_offset(m, dev->set_mode); SEQ_printf(m, "\n");
SEQ_printf(m, " event_handler: ");
Clockevents core now supports ->set_dev_mode() (as a replacement to ->set_mode()), with capability to return error codes.
Migrate all ARM specific clockevent drivers to implement this new callback.
Drivers now return -ENOSYS when a unsupported mode is passed to their ->set_dev_mode() callbacks and return 0 on success.
Most of the changes are automated with help of Coccinelle (http://coccinelle.lip6.fr/) and the ones left are around the switch block which are handled manually.
Some drivers had a WARN()/BUG()/pr_err()/empty-implementation for unsupported modes. These statements and unsupported modes are removed now as proper error handling with a WARN_ON() is done at clockevents core.
A simplified version of the semantic patch is:
@@ identifier m,c,setmode; @@ -void +int setmode(enum clock_event_mode m, struct clock_event_device *c);
@@ identifier setmode; @@ -void +int setmode(enum clock_event_mode, struct clock_event_device *);
@fixret@ identifier m,c,setmode; @@ -void +int setmode(enum clock_event_mode m, struct clock_event_device *c) { ... + return 0; }
@depends on fixret@ identifier ced; identifier fixret.setmode; @@ ... struct clock_event_device ced = { ..., -.set_mode +.set_dev_mode = setmode, };
@depends on fixret@ expression ced; identifier fixret.setmode; @@ - ced->set_mode + ced->set_dev_mode = setmode
@depends on fixret@ identifier fixret.setmode; @@ { . -set_mode +set_dev_mode = setmode }
@depends on fixret@ expression ced; identifier fixret.setmode; @@ - ced.set_mode + ced.set_dev_mode = setmode
Signed-off-by: Viresh Kumar viresh.kumar@linaro.org --- 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 | 8 ++++++-- arch/arm/mach-clps711x/common.c | 7 +++++-- 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 | 7 +++++-- arch/arm/mach-imx/time.c | 7 +++++-- arch/arm/mach-integrator/integrator_ap.c | 9 +++++---- arch/arm/mach-ixp4xx/common.c | 8 +++++--- arch/arm/mach-ks8695/time.c | 22 ++++++++++++++++------ arch/arm/mach-lpc32xx/timer.c | 7 +++++-- arch/arm/mach-mmp/time.c | 11 +++++++---- 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 | 7 +++++-- arch/arm/mach-sa1100/time.c | 7 +++++-- 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 +++++++++++++++----- 26 files changed, 158 insertions(+), 76 deletions(-)
diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c index fd6bff0..9ed3845 100644 --- a/arch/arm/common/timer-sp.c +++ b/arch/arm/common/timer-sp.c @@ -127,7 +127,7 @@ static irqreturn_t sp804_timer_interrupt(int irq, void *dev_id) return IRQ_HANDLED; }
-static void sp804_set_mode(enum clock_event_mode mode, +static int sp804_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE; @@ -147,11 +147,14 @@ static void sp804_set_mode(enum clock_event_mode mode,
case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: - default: + case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; }
writel(ctrl, clkevt_base + TIMER_CTRL); + return 0; }
static int sp804_set_next_event(unsigned long next, @@ -168,7 +171,7 @@ static int sp804_set_next_event(unsigned long next, static struct clock_event_device sp804_clockevent = { .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_DYNIRQ, - .set_mode = sp804_set_mode, + .set_dev_mode = sp804_set_mode, .set_next_event = sp804_set_next_event, .rating = 300, }; diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index dfc3213..f45420d 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -36,7 +36,7 @@ static DEFINE_PER_CPU(bool, percpu_setup_called); static struct clock_event_device __percpu *twd_evt; static int twd_ppi;
-static void twd_set_mode(enum clock_event_mode mode, +static int twd_set_mode(enum clock_event_mode mode, struct clock_event_device *clk) { unsigned long ctrl; @@ -54,11 +54,15 @@ static void twd_set_mode(enum clock_event_mode mode, break; case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: - default: + case CLOCK_EVT_MODE_RESUME: ctrl = 0; + break; + default: + return -ENOSYS; }
writel_relaxed(ctrl, twd_base + TWD_TIMER_CONTROL); + return 0; }
static int twd_set_next_event(unsigned long evt, @@ -296,7 +300,7 @@ static void twd_timer_setup(void) clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP; clk->rating = 350; - clk->set_mode = twd_set_mode; + clk->set_dev_mode = twd_set_mode; clk->set_next_event = twd_set_next_event; clk->irq = twd_ppi; clk->cpumask = cpumask_of(cpu); diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c index 7fd13ae..aefece8 100644 --- a/arch/arm/mach-at91/at91rm9200_time.c +++ b/arch/arm/mach-at91/at91rm9200_time.c @@ -112,7 +112,7 @@ static struct clocksource clk32k = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, };
-static void +static int clkevt32k_mode(enum clock_event_mode mode, struct clock_event_device *dev) { /* Disable and flush pending timer interrupts */ @@ -138,8 +138,11 @@ clkevt32k_mode(enum clock_event_mode mode, struct clock_event_device *dev) case CLOCK_EVT_MODE_RESUME: irqmask = 0; break; + default: + return -ENOSYS; } at91_st_write(AT91_ST_IER, irqmask); + return 0; }
static int @@ -177,7 +180,7 @@ static struct clock_event_device clkevt = { .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .rating = 150, .set_next_event = clkevt32k_next_event, - .set_mode = clkevt32k_mode, + .set_dev_mode = clkevt32k_mode, };
void __iomem *at91_st_base; diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c index 0a9e2fc..f274220 100644 --- a/arch/arm/mach-at91/at91sam926x_time.c +++ b/arch/arm/mach-at91/at91sam926x_time.c @@ -83,7 +83,7 @@ static struct clocksource pit_clk = { /* * Clockevent device: interrupts every 1/HZ (== pit_cycles * MCK/16) */ -static void +static int pit_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) { switch (mode) { @@ -103,7 +103,11 @@ pit_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) break; case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + + return 0; }
static void at91sam926x_pit_suspend(struct clock_event_device *cedev) @@ -135,7 +139,7 @@ static struct clock_event_device pit_clkevt = { .features = CLOCK_EVT_FEAT_PERIODIC, .shift = 32, .rating = 100, - .set_mode = pit_clkevt_mode, + .set_dev_mode = pit_clkevt_mode, .suspend = at91sam926x_pit_suspend, .resume = at91sam926x_pit_resume, }; diff --git a/arch/arm/mach-clps711x/common.c b/arch/arm/mach-clps711x/common.c index aee81fa..4ca75e6 100644 --- a/arch/arm/mach-clps711x/common.c +++ b/arch/arm/mach-clps711x/common.c @@ -69,7 +69,7 @@ static u64 notrace clps711x_sched_clock_read(void) return ~readw_relaxed(CLPS711X_VIRT_BASE + TC1D); }
-static void clps711x_clockevent_set_mode(enum clock_event_mode mode, +static int clps711x_clockevent_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { disable_irq(IRQ_TC2OI); @@ -85,14 +85,17 @@ static void clps711x_clockevent_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_RESUME: /* Left event sources disabled, no more interrupts appear */ break; + default: + return -ENOSYS; } + return 0; }
static struct clock_event_device clockevent_clps711x = { .name = "clps711x-clockevent", .rating = 300, .features = CLOCK_EVT_FEAT_PERIODIC, - .set_mode = clps711x_clockevent_set_mode, + .set_dev_mode = clps711x_clockevent_set_mode, };
static irqreturn_t clps711x_timer_interrupt(int irq, void *dev_id) diff --git a/arch/arm/mach-cns3xxx/core.c b/arch/arm/mach-cns3xxx/core.c index 2ae28a6..9746501 100644 --- a/arch/arm/mach-cns3xxx/core.c +++ b/arch/arm/mach-cns3xxx/core.c @@ -113,7 +113,7 @@ void cns3xxx_power_off(void) */ static void __iomem *cns3xxx_tmr1;
-static void cns3xxx_timer_set_mode(enum clock_event_mode mode, +static int cns3xxx_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *clk) { unsigned long ctrl = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET); @@ -132,11 +132,15 @@ static void cns3xxx_timer_set_mode(enum clock_event_mode mode, break; case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: - default: + case CLOCK_EVT_MODE_RESUME: ctrl = 0; + break; + default: + return -ENOSYS; }
writel(ctrl, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET); + return 0; }
static int cns3xxx_timer_set_next_event(unsigned long evt, @@ -153,7 +157,7 @@ static int cns3xxx_timer_set_next_event(unsigned long evt, static struct clock_event_device cns3xxx_tmr1_clockevent = { .name = "cns3xxx timer1", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_mode = cns3xxx_timer_set_mode, + .set_dev_mode = cns3xxx_timer_set_mode, .set_next_event = cns3xxx_timer_set_next_event, .rating = 350, .cpumask = cpu_all_mask, diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c index 24ad30f..7ab6a6c 100644 --- a/arch/arm/mach-davinci/time.c +++ b/arch/arm/mach-davinci/time.c @@ -303,7 +303,7 @@ static int davinci_set_next_event(unsigned long cycles, return 0; }
-static void davinci_set_mode(enum clock_event_mode mode, +static int davinci_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { struct timer_s *t = &timers[TID_CLOCKEVENT]; @@ -326,13 +326,16 @@ static void davinci_set_mode(enum clock_event_mode mode, break; case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
static struct clock_event_device clockevent_davinci = { .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .set_next_event = davinci_set_next_event, - .set_mode = davinci_set_mode, + .set_dev_mode = davinci_set_mode, };
diff --git a/arch/arm/mach-footbridge/dc21285-timer.c b/arch/arm/mach-footbridge/dc21285-timer.c index bf7aa7d..c949daf 100644 --- a/arch/arm/mach-footbridge/dc21285-timer.c +++ b/arch/arm/mach-footbridge/dc21285-timer.c @@ -57,7 +57,7 @@ static int ckevt_dc21285_set_next_event(unsigned long delta, return 0; }
-static void ckevt_dc21285_set_mode(enum clock_event_mode mode, +static int ckevt_dc21285_set_mode(enum clock_event_mode mode, struct clock_event_device *c) { switch (mode) { @@ -74,7 +74,10 @@ static void ckevt_dc21285_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_SHUTDOWN: *CSR_TIMER1_CNTL = 0; break; + default: + return -ENOSYS; } + return 0; }
static struct clock_event_device ckevt_dc21285 = { @@ -84,7 +87,7 @@ static struct clock_event_device ckevt_dc21285 = { .rating = 200, .irq = IRQ_TIMER1, .set_next_event = ckevt_dc21285_set_next_event, - .set_mode = ckevt_dc21285_set_mode, + .set_dev_mode = ckevt_dc21285_set_mode, };
static irqreturn_t timer1_interrupt(int irq, void *dev_id) diff --git a/arch/arm/mach-gemini/time.c b/arch/arm/mach-gemini/time.c index 0a63c4d..8fea6f3 100644 --- a/arch/arm/mach-gemini/time.c +++ b/arch/arm/mach-gemini/time.c @@ -59,7 +59,7 @@ static int gemini_timer_set_next_event(unsigned long cycles, return 0; }
-static void gemini_timer_set_mode(enum clock_event_mode mode, +static int gemini_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { u32 period = DIV_ROUND_CLOSEST(tick_rate, HZ); @@ -91,8 +91,9 @@ static void gemini_timer_set_mode(enum clock_event_mode mode, writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE))); break; default: - break; + return -ENOSYS; } + return 0; }
/* Use TIMER2 as clock event */ @@ -101,7 +102,7 @@ static struct clock_event_device gemini_clockevent = { .rating = 300, /* Reasonably fast and accurate clock event */ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .set_next_event = gemini_timer_set_next_event, - .set_mode = gemini_timer_set_mode, + .set_dev_mode = gemini_timer_set_mode, };
/* diff --git a/arch/arm/mach-imx/epit.c b/arch/arm/mach-imx/epit.c index 074b1a8..b5f86da 100644 --- a/arch/arm/mach-imx/epit.c +++ b/arch/arm/mach-imx/epit.c @@ -106,7 +106,7 @@ static int epit_set_next_event(unsigned long evt, return 0; }
-static void epit_set_mode(enum clock_event_mode mode, +static int epit_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { unsigned long flags; @@ -152,7 +152,10 @@ static void epit_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_RESUME: /* Left event sources disabled, no more interrupts appear */ break; + default: + return -ENOSYS; } + return 0; }
/* @@ -178,7 +181,7 @@ static struct irqaction epit_timer_irq = { static struct clock_event_device clockevent_epit = { .name = "epit", .features = CLOCK_EVT_FEAT_ONESHOT, - .set_mode = epit_set_mode, + .set_dev_mode = epit_set_mode, .set_next_event = epit_set_next_event, .rating = 200, }; diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c index 65222ea..a1aa7c2 100644 --- a/arch/arm/mach-imx/time.c +++ b/arch/arm/mach-imx/time.c @@ -179,7 +179,7 @@ static const char *clock_event_mode_label[] = { }; #endif /* DEBUG */
-static void mxc_set_mode(enum clock_event_mode mode, +static int mxc_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { unsigned long flags; @@ -237,7 +237,10 @@ static void mxc_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_RESUME: /* Left event sources disabled, no more interrupts appear */ break; + default: + return -ENOSYS; } + return 0; }
/* @@ -269,7 +272,7 @@ static struct irqaction mxc_timer_irq = { static struct clock_event_device clockevent_mxc = { .name = "mxc_timer1", .features = CLOCK_EVT_FEAT_ONESHOT, - .set_mode = mxc_set_mode, + .set_dev_mode = mxc_set_mode, .set_next_event = mx1_2_set_next_event, .rating = 200, }; diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index dd0cc67..39e797c 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c @@ -307,7 +307,7 @@ static irqreturn_t integrator_timer_interrupt(int irq, void *dev_id) return IRQ_HANDLED; }
-static void clkevt_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) +static int clkevt_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { u32 ctrl = readl(clkevt_base + TIMER_CTRL) & ~TIMER_CTRL_ENABLE;
@@ -329,11 +329,12 @@ static void clkevt_set_mode(enum clock_event_mode mode, struct clock_event_devic case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: case CLOCK_EVT_MODE_RESUME: - default: /* Just leave in disabled state */ break; + default: + return -ENOSYS; } - + return 0; }
static int clkevt_set_next_event(unsigned long next, struct clock_event_device *evt) @@ -350,7 +351,7 @@ static int clkevt_set_next_event(unsigned long next, struct clock_event_device * static struct clock_event_device integrator_clockevent = { .name = "timer1", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_mode = clkevt_set_mode, + .set_dev_mode = clkevt_set_mode, .set_next_event = clkevt_set_next_event, .rating = 300, }; diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index fc4b7b2..05c050a 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -521,7 +521,7 @@ static int ixp4xx_set_next_event(unsigned long evt, return 0; }
-static void ixp4xx_set_mode(enum clock_event_mode mode, +static int ixp4xx_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK; @@ -544,19 +544,21 @@ static void ixp4xx_set_mode(enum clock_event_mode mode, opts |= IXP4XX_OST_ENABLE; break; case CLOCK_EVT_MODE_UNUSED: - default: osrt = opts = 0; break; + default: + return -ENOSYS; }
*IXP4XX_OSRT1 = osrt | opts; + return 0; }
static struct clock_event_device clockevent_ixp4xx = { .name = "ixp4xx timer1", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .rating = 200, - .set_mode = ixp4xx_set_mode, + .set_dev_mode = ixp4xx_set_mode, .set_next_event = ixp4xx_set_next_event, };
diff --git a/arch/arm/mach-ks8695/time.c b/arch/arm/mach-ks8695/time.c index a197874..8d2149c 100644 --- a/arch/arm/mach-ks8695/time.c +++ b/arch/arm/mach-ks8695/time.c @@ -54,14 +54,15 @@ /* Timer0 Timeout Counter Register */ #define T0TC_WATCHDOG (0xff) /* Enable watchdog mode */
-static void ks8695_set_mode(enum clock_event_mode mode, +static int ks8695_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { - u32 tmcon; + u32 tmcon, rate, half;
- if (mode == CLOCK_EVT_FEAT_PERIODIC) { - u32 rate = DIV_ROUND_CLOSEST(KS8695_CLOCK_RATE, HZ); - u32 half = DIV_ROUND_CLOSEST(rate, 2); + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + rate = DIV_ROUND_CLOSEST(KS8695_CLOCK_RATE, HZ); + half = DIV_ROUND_CLOSEST(rate, 2);
/* Disable timer 1 */ tmcon = readl_relaxed(KS8695_TMR_VA + KS8695_TMCON); @@ -75,7 +76,16 @@ static void ks8695_set_mode(enum clock_event_mode mode, /* Re-enable timer1 */ tmcon |= TMCON_T1EN; writel_relaxed(tmcon, KS8695_TMR_VA + KS8695_TMCON); + break; + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: + case CLOCK_EVT_MODE_UNUSED: + break; + default: + return -ENOSYS; } + return 0; }
static int ks8695_set_next_event(unsigned long cycles, @@ -106,7 +116,7 @@ static struct clock_event_device clockevent_ks8695 = { .rating = 300, /* Reasonably fast and accurate clock event */ .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, .set_next_event = ks8695_set_next_event, - .set_mode = ks8695_set_mode, + .set_dev_mode = ks8695_set_mode, };
/* diff --git a/arch/arm/mach-lpc32xx/timer.c b/arch/arm/mach-lpc32xx/timer.c index 4e58372..ac19492 100644 --- a/arch/arm/mach-lpc32xx/timer.c +++ b/arch/arm/mach-lpc32xx/timer.c @@ -43,7 +43,7 @@ static int lpc32xx_clkevt_next_event(unsigned long delta, return 0; }
-static void lpc32xx_clkevt_mode(enum clock_event_mode mode, +static int lpc32xx_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) { switch (mode) { @@ -64,7 +64,10 @@ static void lpc32xx_clkevt_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
static struct clock_event_device lpc32xx_clkevt = { @@ -72,7 +75,7 @@ static struct clock_event_device lpc32xx_clkevt = { .features = CLOCK_EVT_FEAT_ONESHOT, .rating = 300, .set_next_event = lpc32xx_clkevt_next_event, - .set_mode = lpc32xx_clkevt_mode, + .set_dev_mode = lpc32xx_clkevt_mode, };
static irqreturn_t lpc32xx_timer_interrupt(int irq, void *dev_id) diff --git a/arch/arm/mach-mmp/time.c b/arch/arm/mach-mmp/time.c index 2756351..3df05ac 100644 --- a/arch/arm/mach-mmp/time.c +++ b/arch/arm/mach-mmp/time.c @@ -124,24 +124,27 @@ static int timer_set_next_event(unsigned long delta, return 0; }
-static void timer_set_mode(enum clock_event_mode mode, +static int timer_set_mode(enum clock_event_mode mode, struct clock_event_device *dev) { unsigned long flags;
- local_irq_save(flags); switch (mode) { case CLOCK_EVT_MODE_ONESHOT: case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: /* disable the matching interrupt */ + local_irq_save(flags); __raw_writel(0x00, mmp_timer_base + TMR_IER(0)); + local_irq_restore(flags); break; case CLOCK_EVT_MODE_RESUME: case CLOCK_EVT_MODE_PERIODIC: break; + default: + return -ENOSYS; } - local_irq_restore(flags); + return 0; }
static struct clock_event_device ckevt = { @@ -149,7 +152,7 @@ static struct clock_event_device ckevt = { .features = CLOCK_EVT_FEAT_ONESHOT, .rating = 200, .set_next_event = timer_set_next_event, - .set_mode = timer_set_mode, + .set_dev_mode = timer_set_mode, };
static cycle_t clksrc_read(struct clocksource *cs) diff --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c index 5fb2a59..4f0f9db 100644 --- a/arch/arm/mach-netx/time.c +++ b/arch/arm/mach-netx/time.c @@ -34,7 +34,7 @@ #define TIMER_CLOCKEVENT 0 #define TIMER_CLOCKSOURCE 1
-static void netx_set_mode(enum clock_event_mode mode, +static int netx_set_mode(enum clock_event_mode mode, struct clock_event_device *clk) { u32 tmode; @@ -56,18 +56,17 @@ static void netx_set_mode(enum clock_event_mode mode, NETX_GPIO_COUNTER_CTRL_RUN; break;
- default: - WARN(1, "%s: unhandled mode %d\n", __func__, mode); - /* fall through */ - case CLOCK_EVT_MODE_SHUTDOWN: case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_RESUME: tmode = 0; break; + default: + return -ENOSYS; }
writel(tmode, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKEVENT)); + return 0; }
static int netx_set_next_event(unsigned long evt, @@ -81,7 +80,7 @@ static struct clock_event_device netx_clockevent = { .name = "netx-timer" __stringify(TIMER_CLOCKEVENT), .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .set_next_event = netx_set_next_event, - .set_mode = netx_set_mode, + .set_dev_mode = netx_set_mode, };
/* diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c index a7588cf..b2bcd25 100644 --- a/arch/arm/mach-omap1/time.c +++ b/arch/arm/mach-omap1/time.c @@ -124,7 +124,7 @@ static int omap_mpu_set_next_event(unsigned long cycles, return 0; }
-static void omap_mpu_set_mode(enum clock_event_mode mode, +static int omap_mpu_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { switch (mode) { @@ -139,14 +139,17 @@ static void omap_mpu_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_SHUTDOWN: case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
static struct clock_event_device clockevent_mpu_timer1 = { .name = "mpu_timer1", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .set_next_event = omap_mpu_set_next_event, - .set_mode = omap_mpu_set_mode, + .set_dev_mode = omap_mpu_set_mode, };
static irqreturn_t omap_mpu_timer1_interrupt(int irq, void *dev_id) diff --git a/arch/arm/mach-omap1/timer32k.c b/arch/arm/mach-omap1/timer32k.c index 107e7ab..6cf8962 100644 --- a/arch/arm/mach-omap1/timer32k.c +++ b/arch/arm/mach-omap1/timer32k.c @@ -119,7 +119,7 @@ static int omap_32k_timer_set_next_event(unsigned long delta, return 0; }
-static void omap_32k_timer_set_mode(enum clock_event_mode mode, +static int omap_32k_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { omap_32k_timer_stop(); @@ -134,14 +134,17 @@ static void omap_32k_timer_set_mode(enum clock_event_mode mode, break; case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
static struct clock_event_device clockevent_32k_timer = { .name = "32k-timer", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .set_next_event = omap_32k_timer_set_next_event, - .set_mode = omap_32k_timer_set_mode, + .set_dev_mode = omap_32k_timer_set_mode, };
static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id) diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index b62de9f..749774f 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -101,7 +101,7 @@ static int omap2_gp_timer_set_next_event(unsigned long cycles, return 0; }
-static void omap2_gp_timer_set_mode(enum clock_event_mode mode, +static int omap2_gp_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { u32 period; @@ -125,14 +125,17 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_SHUTDOWN: case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
static struct clock_event_device clockevent_gpt = { .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .rating = 300, .set_next_event = omap2_gp_timer_set_next_event, - .set_mode = omap2_gp_timer_set_mode, + .set_dev_mode = omap2_gp_timer_set_mode, };
static struct property device_disabled = { diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index fca174e..57a9fc8 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c @@ -67,7 +67,7 @@ pxa_osmr0_set_next_event(unsigned long delta, struct clock_event_device *dev) return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0; }
-static void +static int pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev) { switch (mode) { @@ -86,7 +86,10 @@ pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev) case CLOCK_EVT_MODE_RESUME: case CLOCK_EVT_MODE_PERIODIC: break; + default: + return -ENOSYS; } + return 0; }
#ifdef CONFIG_PM @@ -130,7 +133,7 @@ static struct clock_event_device ckevt_pxa_osmr0 = { .features = CLOCK_EVT_FEAT_ONESHOT, .rating = 200, .set_next_event = pxa_osmr0_set_next_event, - .set_mode = pxa_osmr0_set_mode, + .set_dev_mode = pxa_osmr0_set_mode, .suspend = pxa_timer_suspend, .resume = pxa_timer_resume, }; diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c index 1dea6cf..ac3e064 100644 --- a/arch/arm/mach-sa1100/time.c +++ b/arch/arm/mach-sa1100/time.c @@ -56,7 +56,7 @@ sa1100_osmr0_set_next_event(unsigned long delta, struct clock_event_device *c) return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0; }
-static void +static int sa1100_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *c) { switch (mode) { @@ -70,7 +70,10 @@ sa1100_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *c) case CLOCK_EVT_MODE_RESUME: case CLOCK_EVT_MODE_PERIODIC: break; + default: + return -ENOSYS; } + return 0; }
#ifdef CONFIG_PM @@ -109,7 +112,7 @@ static struct clock_event_device ckevt_sa1100_osmr0 = { .features = CLOCK_EVT_FEAT_ONESHOT, .rating = 200, .set_next_event = sa1100_osmr0_set_next_event, - .set_mode = sa1100_osmr0_set_mode, + .set_dev_mode = sa1100_osmr0_set_mode, .suspend = sa1100_timer_suspend, .resume = sa1100_timer_resume, }; diff --git a/arch/arm/mach-spear/time.c b/arch/arm/mach-spear/time.c index 26fda4e..6bfc536 100644 --- a/arch/arm/mach-spear/time.c +++ b/arch/arm/mach-spear/time.c @@ -66,7 +66,7 @@ static __iomem void *gpt_base; static struct clk *gpt_clk;
-static void clockevent_set_mode(enum clock_event_mode mode, +static int clockevent_set_mode(enum clock_event_mode mode, struct clock_event_device *clk_event_dev); static int clockevent_next_event(unsigned long evt, struct clock_event_device *clk_event_dev); @@ -98,12 +98,12 @@ static void __init spear_clocksource_init(void) static struct clock_event_device clkevt = { .name = "tmr0", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_mode = clockevent_set_mode, + .set_dev_mode = clockevent_set_mode, .set_next_event = clockevent_next_event, .shift = 0, /* to be computed */ };
-static void clockevent_set_mode(enum clock_event_mode mode, +static int clockevent_set_mode(enum clock_event_mode mode, struct clock_event_device *clk_event_dev) { u32 period; @@ -138,9 +138,9 @@ static void clockevent_set_mode(enum clock_event_mode mode,
break; default: - pr_err("Invalid mode requested\n"); - break; + return -ENOSYS; } + return 0; }
static int clockevent_next_event(unsigned long cycles, diff --git a/arch/arm/mach-w90x900/time.c b/arch/arm/mach-w90x900/time.c index 9230d37..e4a8067 100644 --- a/arch/arm/mach-w90x900/time.c +++ b/arch/arm/mach-w90x900/time.c @@ -48,7 +48,7 @@
static unsigned int timer0_load;
-static void nuc900_clockevent_setmode(enum clock_event_mode mode, +static int nuc900_clockevent_setmode(enum clock_event_mode mode, struct clock_event_device *clk) { unsigned int val; @@ -70,9 +70,12 @@ static void nuc900_clockevent_setmode(enum clock_event_mode mode, case CLOCK_EVT_MODE_SHUTDOWN: case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; }
__raw_writel(val, REG_TCSR0); + return 0; }
static int nuc900_clockevent_setnextevent(unsigned long evt, @@ -92,7 +95,7 @@ static int nuc900_clockevent_setnextevent(unsigned long evt, static struct clock_event_device nuc900_clockevent_device = { .name = "nuc900-timer0", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_mode = nuc900_clockevent_setmode, + .set_dev_mode = nuc900_clockevent_setmode, .set_next_event = nuc900_clockevent_setnextevent, .rating = 300, }; diff --git a/arch/arm/plat-iop/time.c b/arch/arm/plat-iop/time.c index 6ad65d8..a21a18c 100644 --- a/arch/arm/plat-iop/time.c +++ b/arch/arm/plat-iop/time.c @@ -77,7 +77,7 @@ static int iop_set_next_event(unsigned long delta,
static unsigned long ticks_per_jiffy;
-static void iop_set_mode(enum clock_event_mode mode, +static int iop_set_mode(enum clock_event_mode mode, struct clock_event_device *unused) { u32 tmr = read_tmr0(); @@ -98,12 +98,14 @@ static void iop_set_mode(enum clock_event_mode mode, break; case CLOCK_EVT_MODE_SHUTDOWN: case CLOCK_EVT_MODE_UNUSED: - default: tmr &= ~IOP_TMR_EN; break; + default: + return -ENOSYS; }
write_tmr0(tmr); + return 0; }
static struct clock_event_device iop_clockevent = { @@ -111,7 +113,7 @@ static struct clock_event_device iop_clockevent = { .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .rating = 300, .set_next_event = iop_set_next_event, - .set_mode = iop_set_mode, + .set_dev_mode = iop_set_mode, };
static irqreturn_t diff --git a/arch/arm/plat-orion/time.c b/arch/arm/plat-orion/time.c index 261258f..7dc5cc8 100644 --- a/arch/arm/plat-orion/time.c +++ b/arch/arm/plat-orion/time.c @@ -106,14 +106,15 @@ orion_clkevt_next_event(unsigned long delta, struct clock_event_device *dev) return 0; }
-static void +static int orion_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) { unsigned long flags; u32 u;
local_irq_save(flags); - if (mode == CLOCK_EVT_MODE_PERIODIC) { + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: /* * Setup timer to fire at 1/HZ intervals. */ @@ -132,7 +133,12 @@ orion_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) u = readl(timer_base + TIMER_CTRL_OFF); writel(u | TIMER1_EN | TIMER1_RELOAD_EN, timer_base + TIMER_CTRL_OFF); - } else { + break; + + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: /* * Disable timer. */ @@ -149,9 +155,13 @@ orion_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) * ACK pending timer interrupt. */ writel(bridge_timer1_clr_mask, bridge_base + BRIDGE_CAUSE_OFF); - + break; + default: + local_irq_restore(flags); + return -ENOSYS; } local_irq_restore(flags); + return 0; }
static struct clock_event_device orion_clkevt = { @@ -159,7 +169,7 @@ static struct clock_event_device orion_clkevt = { .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, .rating = 300, .set_next_event = orion_clkevt_next_event, - .set_mode = orion_clkevt_mode, + .set_dev_mode = orion_clkevt_mode, };
static irqreturn_t orion_timer_interrupt(int irq, void *dev_id)
Viresh Kumar viresh.kumar@linaro.org writes:
Clockevents core now supports ->set_dev_mode() (as a replacement to ->set_mode()), with capability to return error codes.
Migrate all ARM specific clockevent drivers to implement this new callback.
Drivers now return -ENOSYS when a unsupported mode is passed to their ->set_dev_mode() callbacks and return 0 on success.
Most of the changes are automated with help of Coccinelle (http://coccinelle.lip6.fr/) and the ones left are around the switch block which are handled manually.
Some drivers had a WARN()/BUG()/pr_err()/empty-implementation for unsupported modes. These statements and unsupported modes are removed now as proper error handling with a WARN_ON() is done at clockevents core.
A simplified version of the semantic patch is:
@@ identifier m,c,setmode; @@ -void +int setmode(enum clock_event_mode m, struct clock_event_device *c);
@@ identifier setmode; @@ -void +int setmode(enum clock_event_mode, struct clock_event_device *);
@fixret@ identifier m,c,setmode; @@ -void +int setmode(enum clock_event_mode m, struct clock_event_device *c) { ...
- return 0;
}
@depends on fixret@ identifier ced; identifier fixret.setmode; @@ ... struct clock_event_device ced = { ..., -.set_mode +.set_dev_mode = setmode, };
@depends on fixret@ expression ced; identifier fixret.setmode; @@
- ced->set_mode
- ced->set_dev_mode
= setmode
@depends on fixret@ identifier fixret.setmode; @@ { . -set_mode +set_dev_mode = setmode }
@depends on fixret@ expression ced; identifier fixret.setmode; @@
- ced.set_mode
- ced.set_dev_mode
= setmode
Signed-off-by: Viresh Kumar viresh.kumar@linaro.org
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 | 8 ++++++-- arch/arm/mach-clps711x/common.c | 7 +++++-- 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 | 7 +++++-- arch/arm/mach-imx/time.c | 7 +++++-- arch/arm/mach-integrator/integrator_ap.c | 9 +++++---- arch/arm/mach-ixp4xx/common.c | 8 +++++--- arch/arm/mach-ks8695/time.c | 22 ++++++++++++++++------ arch/arm/mach-lpc32xx/timer.c | 7 +++++-- arch/arm/mach-mmp/time.c | 11 +++++++---- 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 | 7 +++++-- arch/arm/mach-sa1100/time.c | 7 +++++-- 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 +++++++++++++++----- 26 files changed, 158 insertions(+), 76 deletions(-)
diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c index fd6bff0..9ed3845 100644 --- a/arch/arm/common/timer-sp.c +++ b/arch/arm/common/timer-sp.c @@ -127,7 +127,7 @@ static irqreturn_t sp804_timer_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static void sp804_set_mode(enum clock_event_mode mode, +static int sp804_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE; @@ -147,11 +147,14 @@ static void sp804_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN:
- default:
- case CLOCK_EVT_MODE_RESUME: break;
- default:
}return -ENOSYS;
You missed some previous comments.
Note that the early 'return' changes the *functional* behavior of this code. e.g. it used to do 2 writes to this register, but now it does one. Assuming this is well-behaved hardware, it's probably fine but we just don't know.
As I mentioned in an earlier review, to preserve the *behavior* of the current code used to disable timers, you should not mess with any of the register accesses.
Instead, add an 'int ret = 0' at the beginning, 'ret = -ENOSYS' in the default case and 'return ret' at the end.
This not only makes the code easier to review for those who are not intimately familiar with each of these clockevent devices, but it's much more obvious on inspection that you are not changing the *behavior* of the code.
The same problem exists on several of the following changes, so I stopped reviewing after I saw 3-4 of them.
Kevin
On 2 June 2014 21:31, Kevin Hilman khilman@linaro.org wrote:
You missed some previous comments.
That's very bad :(
Note that the early 'return' changes the *functional* behavior of this code. e.g. it used to do 2 writes to this register, but now it does one. Assuming this is well-behaved hardware, it's probably fine but we just don't know.
I had the impression that you meant that only for the currently available modes and not for 'default case' in general and so kept it that way..
As I mentioned in an earlier review, to preserve the *behavior* of the current code used to disable timers, you should not mess with any of the register accesses.
Instead, add an 'int ret = 0' at the beginning, 'ret = -ENOSYS' in the default case and 'return ret' at the end.
This not only makes the code easier to review for those who are not intimately familiar with each of these clockevent devices, but it's much more obvious on inspection that you are not changing the *behavior* of the code.
The same problem exists on several of the following changes, so I stopped reviewing after I saw 3-4 of them.
Will keep behavior of 'default case' as is .. Will try to send a V5 soon, if that's the only complaint you have.
Clockevents core now supports ->set_dev_mode() (as a replacement to ->set_mode()), with capability to return error codes.
Migrate all MIPS specific clockevent drivers to implement this new callback.
Drivers now return -ENOSYS when a unsupported mode is passed to their ->set_dev_mode() callbacks and return 0 on success.
Most of the changes are automated with help of Coccinelle (http://coccinelle.lip6.fr/) and the ones left are around the switch block which are handled manually.
Some drivers had a WARN()/BUG()/pr_err()/empty-implementation for unsupported modes. These statements and unsupported modes are removed now as proper error handling with a WARN_ON() is done at clockevents core.
A simplified version of the semantic patch is:
@@ identifier m,c,setmode; @@ -void +int setmode(enum clock_event_mode m, struct clock_event_device *c);
@@ identifier setmode; @@ -void +int setmode(enum clock_event_mode, struct clock_event_device *);
@fixret@ identifier m,c,setmode; @@ -void +int setmode(enum clock_event_mode m, struct clock_event_device *c) { ... + return 0; }
@depends on fixret@ identifier ced; identifier fixret.setmode; @@ ... struct clock_event_device ced = { ..., -.set_mode +.set_dev_mode = setmode, };
@depends on fixret@ expression ced; identifier fixret.setmode; @@ - ced->set_mode + ced->set_dev_mode = setmode
@depends on fixret@ identifier fixret.setmode; @@ { . -set_mode +set_dev_mode = setmode }
@depends on fixret@ expression ced; identifier fixret.setmode; @@ - ced.set_mode + ced.set_dev_mode = setmode
Signed-off-by: Viresh Kumar viresh.kumar@linaro.org --- 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 | 9 ++++++--- 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 | 9 ++++++--- arch/mips/kernel/cevt-smtc.c | 2 +- arch/mips/kernel/cevt-txx9.c | 7 +++++-- arch/mips/loongson/common/cs5536/cs5536_mfgpt.c | 8 ++++++-- arch/mips/ralink/cevt-rt3352.c | 13 ++++++++----- arch/mips/sgi-ip27/ip27-timer.c | 14 ++++++++++++-- arch/mips/sni/time.c | 7 +++++-- 16 files changed, 122 insertions(+), 38 deletions(-)
diff --git a/arch/mips/alchemy/common/time.c b/arch/mips/alchemy/common/time.c index 93fa586..4af4ed2 100644 --- a/arch/mips/alchemy/common/time.c +++ b/arch/mips/alchemy/common/time.c @@ -70,9 +70,19 @@ static int au1x_rtcmatch2_set_next_event(unsigned long delta, return 0; }
-static void au1x_rtcmatch2_set_mode(enum clock_event_mode mode, +static int au1x_rtcmatch2_set_mode(enum clock_event_mode mode, struct clock_event_device *cd) { + switch (mode) { + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: + break; + default: + return -ENOSYS; + } + return 0; }
static irqreturn_t au1x_rtcmatch2_irq(int irq, void *dev_id) @@ -87,7 +97,7 @@ static struct clock_event_device au1x_rtcmatch2_clockdev = { .features = CLOCK_EVT_FEAT_ONESHOT, .rating = 1500, .set_next_event = au1x_rtcmatch2_set_next_event, - .set_mode = au1x_rtcmatch2_set_mode, + .set_dev_mode = au1x_rtcmatch2_set_mode, .cpumask = cpu_all_mask, };
diff --git a/arch/mips/include/asm/cevt-r4k.h b/arch/mips/include/asm/cevt-r4k.h index 65f9bdd..e4872df 100644 --- a/arch/mips/include/asm/cevt-r4k.h +++ b/arch/mips/include/asm/cevt-r4k.h @@ -21,7 +21,7 @@ DECLARE_PER_CPU(struct clock_event_device, mips_clockevent_device);
void mips_event_handler(struct clock_event_device *dev); int c0_compare_int_usable(void); -void mips_set_clock_mode(enum clock_event_mode, struct clock_event_device *); +int mips_set_clock_mode(enum clock_event_mode, struct clock_event_device *); irqreturn_t c0_compare_interrupt(int, void *);
extern struct irqaction c0_compare_irqaction; diff --git a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c index e1ea4f6..1ceee92 100644 --- a/arch/mips/jazz/irq.c +++ b/arch/mips/jazz/irq.c @@ -110,10 +110,20 @@ asmlinkage void plat_irq_dispatch(void) } }
-static void r4030_set_mode(enum clock_event_mode mode, +static int r4030_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: /* Nothing to do ... */ + break; + default: + return -ENOSYS; + } + return 0; }
struct clock_event_device r4030_clockevent = { @@ -121,7 +131,7 @@ struct clock_event_device r4030_clockevent = { .features = CLOCK_EVT_FEAT_PERIODIC, .rating = 300, .irq = JAZZ_TIMER_IRQ, - .set_mode = r4030_set_mode, + .set_dev_mode = r4030_set_mode, };
static irqreturn_t r4030_timer_interrupt(int irq, void *dev_id) diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c index 5e430ce..2eb3fe1 100644 --- a/arch/mips/jz4740/time.c +++ b/arch/mips/jz4740/time.c @@ -57,7 +57,7 @@ static irqreturn_t jz4740_clockevent_irq(int irq, void *devid) return IRQ_HANDLED; }
-static void jz4740_clockevent_set_mode(enum clock_event_mode mode, +static int jz4740_clockevent_set_mode(enum clock_event_mode mode, struct clock_event_device *cd) { switch (mode) { @@ -72,9 +72,12 @@ static void jz4740_clockevent_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_SHUTDOWN: jz4740_timer_disable(TIMER_CLOCKEVENT); break; - default: + case CLOCK_EVT_MODE_UNUSED: break; + default: + return -ENOSYS; } + return 0; }
static int jz4740_clockevent_set_next(unsigned long evt, @@ -91,7 +94,7 @@ static struct clock_event_device jz4740_clockevent = { .name = "jz4740-timer", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .set_next_event = jz4740_clockevent_set_next, - .set_mode = jz4740_clockevent_set_mode, + .set_dev_mode = jz4740_clockevent_set_mode, .rating = 200, .irq = JZ4740_IRQ_TCU0, }; diff --git a/arch/mips/kernel/cevt-bcm1480.c b/arch/mips/kernel/cevt-bcm1480.c index 7976457..0dadec4 100644 --- a/arch/mips/kernel/cevt-bcm1480.c +++ b/arch/mips/kernel/cevt-bcm1480.c @@ -40,7 +40,7 @@ * The general purpose timer ticks at 1MHz independent if * the rest of the system */ -static void sibyte_set_mode(enum clock_event_mode mode, +static int sibyte_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { unsigned int cpu = smp_processor_id(); @@ -65,8 +65,11 @@ static void sibyte_set_mode(enum clock_event_mode mode,
case CLOCK_EVT_MODE_UNUSED: /* shuddup gcc */ case CLOCK_EVT_MODE_RESUME: - ; + break; + default: + return -ENOSYS; } + return 0; }
static int sibyte_next_event(unsigned long delta, struct clock_event_device *cd) @@ -130,7 +133,7 @@ void sb1480_clockevent_init(void) cd->irq = irq; cd->cpumask = cpumask_of(cpu); cd->set_next_event = sibyte_next_event; - cd->set_mode = sibyte_set_mode; + cd->set_dev_mode = sibyte_set_mode; clockevents_register_device(cd);
bcm1480_mask_irq(cpu, irq); diff --git a/arch/mips/kernel/cevt-ds1287.c b/arch/mips/kernel/cevt-ds1287.c index ff1f01b..f86642a 100644 --- a/arch/mips/kernel/cevt-ds1287.c +++ b/arch/mips/kernel/cevt-ds1287.c @@ -59,7 +59,7 @@ static int ds1287_set_next_event(unsigned long delta, return -EINVAL; }
-static void ds1287_set_mode(enum clock_event_mode mode, +static int ds1287_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { u8 val; @@ -72,14 +72,20 @@ static void ds1287_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_PERIODIC: val |= RTC_PIE; break; - default: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: val &= ~RTC_PIE; break; + default: + spin_unlock(&rtc_lock); + return -ENOSYS; }
CMOS_WRITE(val, RTC_REG_B);
spin_unlock(&rtc_lock); + return 0; }
static void ds1287_event_handler(struct clock_event_device *dev) @@ -90,7 +96,7 @@ static struct clock_event_device ds1287_clockevent = { .name = "ds1287", .features = CLOCK_EVT_FEAT_PERIODIC, .set_next_event = ds1287_set_next_event, - .set_mode = ds1287_set_mode, + .set_dev_mode = ds1287_set_mode, .event_handler = ds1287_event_handler, };
diff --git a/arch/mips/kernel/cevt-gic.c b/arch/mips/kernel/cevt-gic.c index 594cbbf..ae4b1ee 100644 --- a/arch/mips/kernel/cevt-gic.c +++ b/arch/mips/kernel/cevt-gic.c @@ -31,10 +31,20 @@ static int gic_next_event(unsigned long delta, struct clock_event_device *evt) return res; }
-void gic_set_clock_mode(enum clock_event_mode mode, +int gic_set_clock_mode(enum clock_event_mode mode, struct clock_event_device *evt) { + switch (mode) { + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: /* Nothing to do ... */ + break; + default: + return -ENOSYS; + } + return 0; }
irqreturn_t gic_compare_interrupt(int irq, void *dev_id) @@ -85,7 +95,7 @@ int gic_clockevent_init(void) cd->irq = irq; cd->cpumask = cpumask_of(cpu); cd->set_next_event = gic_next_event; - cd->set_mode = gic_set_clock_mode; + cd->set_dev_mode = gic_set_clock_mode; cd->event_handler = gic_event_handler;
clockevents_register_device(cd); diff --git a/arch/mips/kernel/cevt-gt641xx.c b/arch/mips/kernel/cevt-gt641xx.c index f069460..7c152ba 100644 --- a/arch/mips/kernel/cevt-gt641xx.c +++ b/arch/mips/kernel/cevt-gt641xx.c @@ -64,7 +64,7 @@ static int gt641xx_timer0_set_next_event(unsigned long delta, return 0; }
-static void gt641xx_timer0_set_mode(enum clock_event_mode mode, +static int gt641xx_timer0_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { u32 ctrl; @@ -81,13 +81,19 @@ static void gt641xx_timer0_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_ONESHOT: ctrl |= GT_TC_CONTROL_ENTC0_MSK; break; - default: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: break; + default: + raw_spin_unlock(>641xx_timer_lock); + return -ENOSYS; }
GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
raw_spin_unlock(>641xx_timer_lock); + return 0; }
static void gt641xx_timer0_event_handler(struct clock_event_device *dev) @@ -99,7 +105,7 @@ static struct clock_event_device gt641xx_timer0_clockevent = { .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .irq = GT641XX_TIMER0_IRQ, .set_next_event = gt641xx_timer0_set_next_event, - .set_mode = gt641xx_timer0_set_mode, + .set_dev_mode = gt641xx_timer0_set_mode, .event_handler = gt641xx_timer0_event_handler, };
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index 50d3f5a..3ad0f42 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c @@ -38,10 +38,20 @@ static int mips_next_event(unsigned long delta,
#endif /* CONFIG_MIPS_MT_SMTC */
-void mips_set_clock_mode(enum clock_event_mode mode, +int mips_set_clock_mode(enum clock_event_mode mode, struct clock_event_device *evt) { + switch (mode) { + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: /* Nothing to do ... */ + break; + default: + return -ENOSYS; + } + return 0; }
DEFINE_PER_CPU(struct clock_event_device, mips_clockevent_device); @@ -207,7 +217,7 @@ int r4k_clockevent_init(void) cd->irq = irq; cd->cpumask = cpumask_of(cpu); cd->set_next_event = mips_next_event; - cd->set_mode = mips_set_clock_mode; + cd->set_dev_mode = mips_set_clock_mode; cd->event_handler = mips_event_handler;
#ifdef CONFIG_CEVT_GIC diff --git a/arch/mips/kernel/cevt-sb1250.c b/arch/mips/kernel/cevt-sb1250.c index 5ea6d6b..d33b3b9 100644 --- a/arch/mips/kernel/cevt-sb1250.c +++ b/arch/mips/kernel/cevt-sb1250.c @@ -38,7 +38,7 @@ * The general purpose timer ticks at 1MHz independent if * the rest of the system */ -static void sibyte_set_mode(enum clock_event_mode mode, +static int sibyte_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { unsigned int cpu = smp_processor_id(); @@ -63,8 +63,11 @@ static void sibyte_set_mode(enum clock_event_mode mode,
case CLOCK_EVT_MODE_UNUSED: /* shuddup gcc */ case CLOCK_EVT_MODE_RESUME: - ; + break; + default: + return -ENOSYS; } + return 0; }
static int sibyte_next_event(unsigned long delta, struct clock_event_device *cd) @@ -129,7 +132,7 @@ void sb1250_clockevent_init(void) cd->irq = irq; cd->cpumask = cpumask_of(cpu); cd->set_next_event = sibyte_next_event; - cd->set_mode = sibyte_set_mode; + cd->set_dev_mode = sibyte_set_mode; clockevents_register_device(cd);
sb1250_mask_irq(cpu, irq); diff --git a/arch/mips/kernel/cevt-smtc.c b/arch/mips/kernel/cevt-smtc.c index b6cf0a6..0d41366 100644 --- a/arch/mips/kernel/cevt-smtc.c +++ b/arch/mips/kernel/cevt-smtc.c @@ -297,7 +297,7 @@ int smtc_clockevent_init(void) cd->irq = irq; cd->cpumask = cpumask_of(cpu); cd->set_next_event = mips_next_event; - cd->set_mode = mips_set_clock_mode; + cd->set_dev_mode = mips_set_clock_mode; cd->event_handler = mips_event_handler;
clockevents_register_device(cd); diff --git a/arch/mips/kernel/cevt-txx9.c b/arch/mips/kernel/cevt-txx9.c index 2ae0846..05bd5ce 100644 --- a/arch/mips/kernel/cevt-txx9.c +++ b/arch/mips/kernel/cevt-txx9.c @@ -76,7 +76,7 @@ static void txx9tmr_stop_and_clear(struct txx9_tmr_reg __iomem *tmrptr) __raw_writel(0, &tmrptr->tisr); }
-static void txx9tmr_set_mode(enum clock_event_mode mode, +static int txx9tmr_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { struct txx9_clock_event_device *txx9_cd = @@ -105,7 +105,10 @@ static void txx9tmr_set_mode(enum clock_event_mode mode, __raw_writel(TIMER_CCD, &tmrptr->ccdr); __raw_writel(0, &tmrptr->itmr); break; + default: + return -ENOSYS; } + return 0; }
static int txx9tmr_set_next_event(unsigned long delta, @@ -128,7 +131,7 @@ static struct txx9_clock_event_device txx9_clock_event_device = { .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .rating = 200, - .set_mode = txx9tmr_set_mode, + .set_dev_mode = txx9tmr_set_mode, .set_next_event = txx9tmr_set_next_event, }, }; diff --git a/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c b/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c index c639b9d..16f9f6f 100644 --- a/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c +++ b/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c @@ -52,7 +52,7 @@ void enable_mfgpt0_counter(void) } EXPORT_SYMBOL(enable_mfgpt0_counter);
-static void init_mfgpt_timer(enum clock_event_mode mode, +static int init_mfgpt_timer(enum clock_event_mode mode, struct clock_event_device *evt) { spin_lock(&mfgpt_lock); @@ -78,14 +78,18 @@ static void init_mfgpt_timer(enum clock_event_mode mode, case CLOCK_EVT_MODE_RESUME: /* Nothing to do here */ break; + default: + spin_unlock(&mfgpt_lock); + return -ENOSYS; } spin_unlock(&mfgpt_lock); + return 0; }
static struct clock_event_device mfgpt_clockevent = { .name = "mfgpt", .features = CLOCK_EVT_FEAT_PERIODIC, - .set_mode = init_mfgpt_timer, + .set_dev_mode = init_mfgpt_timer, .irq = CS5536_MFGPT_INTR, };
diff --git a/arch/mips/ralink/cevt-rt3352.c b/arch/mips/ralink/cevt-rt3352.c index 24bf057..c92b211 100644 --- a/arch/mips/ralink/cevt-rt3352.c +++ b/arch/mips/ralink/cevt-rt3352.c @@ -36,7 +36,7 @@ struct systick_device { int freq_scale; };
-static void systick_set_clock_mode(enum clock_event_mode mode, +static int systick_set_clock_mode(enum clock_event_mode mode, struct clock_event_device *evt);
static int systick_next_event(unsigned long delta, @@ -76,7 +76,7 @@ static struct systick_device systick = { .rating = 310, .features = CLOCK_EVT_FEAT_ONESHOT, .set_next_event = systick_next_event, - .set_mode = systick_set_clock_mode, + .set_dev_mode = systick_set_clock_mode, .event_handler = systick_event_handler, }, }; @@ -87,7 +87,7 @@ static struct irqaction systick_irqaction = { .dev_id = &systick.dev, };
-static void systick_set_clock_mode(enum clock_event_mode mode, +static int systick_set_clock_mode(enum clock_event_mode mode, struct clock_event_device *evt) { struct systick_device *sdev; @@ -110,10 +110,13 @@ static void systick_set_clock_mode(enum clock_event_mode mode, iowrite32(0, systick.membase + SYSTICK_CONFIG); break;
- default: - pr_err("%s: Unhandeled mips clock_mode\n", systick.dev.name); + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
static void __init ralink_systick_init(struct device_node *np) diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index 1d97eab..5d5e90c 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -63,10 +63,20 @@ static int rt_next_event(unsigned long delta, struct clock_event_device *evt) return LOCAL_HUB_L(PI_RT_COUNT) >= cnt ? -ETIME : 0; }
-static void rt_set_mode(enum clock_event_mode mode, +static int rt_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { + switch (mode) { + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: /* Nothing to do ... */ + break; + default: + return -ENOSYS; + } + return 0; }
unsigned int rt_timer_irq; @@ -123,7 +133,7 @@ void hub_rt_clock_event_init(void) cd->irq = irq; cd->cpumask = cpumask_of(cpu); cd->set_next_event = rt_next_event; - cd->set_mode = rt_set_mode; + cd->set_dev_mode = rt_set_mode; clockevents_register_device(cd); }
diff --git a/arch/mips/sni/time.c b/arch/mips/sni/time.c index cf8ec56..d68720c 100644 --- a/arch/mips/sni/time.c +++ b/arch/mips/sni/time.c @@ -14,7 +14,7 @@ #define SNI_COUNTER2_DIV 64 #define SNI_COUNTER0_DIV ((SNI_CLOCK_TICK_RATE / SNI_COUNTER2_DIV) / HZ)
-static void a20r_set_mode(enum clock_event_mode mode, +static int a20r_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { switch (mode) { @@ -40,7 +40,10 @@ static void a20r_set_mode(enum clock_event_mode mode, break; case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
static struct clock_event_device a20r_clockevent_device = { @@ -51,7 +54,7 @@ static struct clock_event_device a20r_clockevent_device = {
.rating = 300, .irq = SNI_A20R_IRQ_TIMER, - .set_mode = a20r_set_mode, + .set_dev_mode = a20r_set_mode, };
static irqreturn_t a20r_interrupt(int irq, void *dev_id)
Clockevents core now supports ->set_dev_mode() (as a replacement to ->set_mode()), with capability to return error codes.
Migrate all SPARC specific clockevent drivers to implement this new callback.
Drivers now return -ENOSYS when a unsupported mode is passed to their ->set_dev_mode() callbacks and return 0 on success.
Most of the changes are automated with help of Coccinelle (http://coccinelle.lip6.fr/) and the ones left are around the switch block which are handled manually.
Some drivers had a WARN()/BUG()/pr_err()/empty-implementation for unsupported modes. These statements and unsupported modes are removed now as proper error handling with a WARN_ON() is done at clockevents core.
A simplified version of the semantic patch is:
@@ identifier m,c,setmode; @@ -void +int setmode(enum clock_event_mode m, struct clock_event_device *c);
@@ identifier setmode; @@ -void +int setmode(enum clock_event_mode, struct clock_event_device *);
@fixret@ identifier m,c,setmode; @@ -void +int setmode(enum clock_event_mode m, struct clock_event_device *c) { ... + return 0; }
@depends on fixret@ identifier ced; identifier fixret.setmode; @@ ... struct clock_event_device ced = { ..., -.set_mode +.set_dev_mode = setmode, };
@depends on fixret@ expression ced; identifier fixret.setmode; @@ - ced->set_mode + ced->set_dev_mode = setmode
@depends on fixret@ identifier fixret.setmode; @@ { . -set_mode +set_dev_mode = setmode }
@depends on fixret@ expression ced; identifier fixret.setmode; @@ - ced.set_mode + ced.set_dev_mode = setmode
Signed-off-by: Viresh Kumar viresh.kumar@linaro.org --- arch/sparc/kernel/time_32.c | 18 ++++++++++++------ arch/sparc/kernel/time_64.c | 7 +++++-- 2 files changed, 17 insertions(+), 8 deletions(-)
diff --git a/arch/sparc/kernel/time_32.c b/arch/sparc/kernel/time_32.c index c4c27b0..4861c53 100644 --- a/arch/sparc/kernel/time_32.c +++ b/arch/sparc/kernel/time_32.c @@ -107,7 +107,7 @@ irqreturn_t notrace timer_interrupt(int dummy, void *dev_id) return IRQ_HANDLED; }
-static void timer_ce_set_mode(enum clock_event_mode mode, +static int timer_ce_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { switch (mode) { @@ -118,10 +118,13 @@ static void timer_ce_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_SHUTDOWN: timer_ce_enabled = 0; break; - default: + case CLOCK_EVT_MODE_UNUSED: break; + default: + return -ENOSYS; } smp_mb(); + return 0; }
static __init void setup_timer_ce(void) @@ -133,7 +136,7 @@ static __init void setup_timer_ce(void) ce->name = "timer_ce"; ce->rating = 100; ce->features = CLOCK_EVT_FEAT_PERIODIC; - ce->set_mode = timer_ce_set_mode; + ce->set_dev_mode = timer_ce_set_mode; ce->cpumask = cpu_possible_mask; ce->shift = 32; ce->mult = div_sc(sparc_config.clock_rate, NSEC_PER_SEC, @@ -193,7 +196,7 @@ static __init int setup_timer_cs(void) }
#ifdef CONFIG_SMP -static void percpu_ce_setup(enum clock_event_mode mode, +static int percpu_ce_setup(enum clock_event_mode mode, struct clock_event_device *evt) { int cpu = __first_cpu(evt->cpumask); @@ -208,9 +211,12 @@ static void percpu_ce_setup(enum clock_event_mode mode, case CLOCK_EVT_MODE_UNUSED: sparc_config.load_profile_irq(cpu, 0); break; - default: + case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
static int percpu_ce_set_next_event(unsigned long delta, @@ -234,7 +240,7 @@ void register_percpu_ce(int cpu) ce->name = "percpu_ce"; ce->rating = 200; ce->features = features; - ce->set_mode = percpu_ce_setup; + ce->set_dev_mode = percpu_ce_setup; ce->set_next_event = percpu_ce_set_next_event; ce->cpumask = cpumask_of(cpu); ce->shift = 32; diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c index 3fddf64..461ed68 100644 --- a/arch/sparc/kernel/time_64.c +++ b/arch/sparc/kernel/time_64.c @@ -691,7 +691,7 @@ static int sparc64_next_event(unsigned long delta, return tick_ops->add_compare(delta) ? -ETIME : 0; }
-static void sparc64_timer_setup(enum clock_event_mode mode, +static int sparc64_timer_setup(enum clock_event_mode mode, struct clock_event_device *evt) { switch (mode) { @@ -707,12 +707,15 @@ static void sparc64_timer_setup(enum clock_event_mode mode, case CLOCK_EVT_MODE_UNUSED: WARN_ON(1); break; + default: + return -ENOSYS; } + return 0; }
static struct clock_event_device sparc64_clockevent = { .features = CLOCK_EVT_FEAT_ONESHOT, - .set_mode = sparc64_timer_setup, + .set_dev_mode = sparc64_timer_setup, .set_next_event = sparc64_next_event, .rating = 100, .shift = 30,
Clockevents core now supports ->set_dev_mode() (as a replacement to ->set_mode()), with capability to return error codes.
Migrate all x86 specific clockevent drivers to implement this new callback.
Drivers now return -ENOSYS when a unsupported mode is passed to their ->set_dev_mode() callbacks and return 0 on success.
Most of the changes are automated with help of Coccinelle (http://coccinelle.lip6.fr/) and the ones left are around the switch block which are handled manually.
Some drivers had a WARN()/BUG()/pr_err()/empty-implementation for unsupported modes. These statements and unsupported modes are removed now as proper error handling with a WARN_ON() is done at clockevents core.
A simplified version of the semantic patch is:
@@ identifier m,c,setmode; @@ -void +int setmode(enum clock_event_mode m, struct clock_event_device *c);
@@ identifier setmode; @@ -void +int setmode(enum clock_event_mode, struct clock_event_device *);
@fixret@ identifier m,c,setmode; @@ -void +int setmode(enum clock_event_mode m, struct clock_event_device *c) { ... + return 0; }
@depends on fixret@ identifier ced; identifier fixret.setmode; @@ ... struct clock_event_device ced = { ..., -.set_mode +.set_dev_mode = setmode, };
@depends on fixret@ expression ced; identifier fixret.setmode; @@ - ced->set_mode + ced->set_dev_mode = setmode
@depends on fixret@ identifier fixret.setmode; @@ { . -set_mode +set_dev_mode = setmode }
@depends on fixret@ expression ced; identifier fixret.setmode; @@ - ced.set_mode + ced.set_dev_mode = setmode
Reviewed-by: Preeti U Murthy preeti@linux.vnet.ibm.com Signed-off-by: Viresh Kumar viresh.kumar@linaro.org --- arch/x86/kernel/apic/apic.c | 10 +++++++--- arch/x86/kernel/hpet.c | 19 +++++++++++-------- arch/x86/lguest/boot.c | 7 +++++-- arch/x86/platform/uv/uv_time.c | 9 ++++++--- arch/x86/xen/time.c | 14 ++++++++++---- 5 files changed, 39 insertions(+), 20 deletions(-)
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index ad28db7..f89084e 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -495,7 +495,7 @@ static int lapic_next_deadline(unsigned long delta, /* * Setup the lapic timer in periodic or oneshot mode */ -static void lapic_timer_setup(enum clock_event_mode mode, +static int lapic_timer_setup(enum clock_event_mode mode, struct clock_event_device *evt) { unsigned long flags; @@ -503,7 +503,7 @@ static void lapic_timer_setup(enum clock_event_mode mode,
/* Lapic used as dummy for broadcast ? */ if (evt->features & CLOCK_EVT_FEAT_DUMMY) - return; + return 0;
local_irq_save(flags);
@@ -523,9 +523,13 @@ static void lapic_timer_setup(enum clock_event_mode mode, case CLOCK_EVT_MODE_RESUME: /* Nothing to do here */ break; + default: + local_irq_restore(flags); + return -ENOSYS; }
local_irq_restore(flags); + return 0; }
/* @@ -547,7 +551,7 @@ static struct clock_event_device lapic_clockevent = { .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP | CLOCK_EVT_FEAT_DUMMY, .shift = 32, - .set_mode = lapic_timer_setup, + .set_dev_mode = lapic_timer_setup, .set_next_event = lapic_next_event, .broadcast = lapic_timer_broadcast, .rating = 100, diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index 4177bfb..8cab472 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -228,7 +228,7 @@ static void hpet_reserve_platform_timers(unsigned int id) { } */ static unsigned long hpet_freq;
-static void hpet_legacy_set_mode(enum clock_event_mode mode, +static int hpet_legacy_set_mode(enum clock_event_mode mode, struct clock_event_device *evt); static int hpet_legacy_next_event(unsigned long delta, struct clock_event_device *evt); @@ -239,7 +239,7 @@ static int hpet_legacy_next_event(unsigned long delta, static struct clock_event_device hpet_clockevent = { .name = "hpet", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_mode = hpet_legacy_set_mode, + .set_dev_mode = hpet_legacy_set_mode, .set_next_event = hpet_legacy_next_event, .irq = 0, .rating = 50, @@ -310,7 +310,7 @@ static void hpet_legacy_clockevent_register(void)
static int hpet_setup_msi_irq(unsigned int irq);
-static void hpet_set_mode(enum clock_event_mode mode, +static int hpet_set_mode(enum clock_event_mode mode, struct clock_event_device *evt, int timer) { unsigned int cfg, cmp, now; @@ -367,7 +367,10 @@ static void hpet_set_mode(enum clock_event_mode mode, } hpet_print_config(); break; + default: + return -ENOSYS; } + return 0; }
static int hpet_next_event(unsigned long delta, @@ -407,10 +410,10 @@ static int hpet_next_event(unsigned long delta, return res < HPET_MIN_CYCLES ? -ETIME : 0; }
-static void hpet_legacy_set_mode(enum clock_event_mode mode, +static int hpet_legacy_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { - hpet_set_mode(mode, evt, 0); + return hpet_set_mode(mode, evt, 0); }
static int hpet_legacy_next_event(unsigned long delta, @@ -462,11 +465,11 @@ void hpet_msi_read(struct hpet_dev *hdev, struct msi_msg *msg) msg->address_hi = 0; }
-static void hpet_msi_set_mode(enum clock_event_mode mode, +static int hpet_msi_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt); - hpet_set_mode(mode, evt, hdev->num); + return hpet_set_mode(mode, evt, hdev->num); }
static int hpet_msi_next_event(unsigned long delta, @@ -558,7 +561,7 @@ static void init_one_hpet_msi_clockevent(struct hpet_dev *hdev, int cpu) if (hdev->flags & HPET_DEV_PERI_CAP) evt->features |= CLOCK_EVT_FEAT_PERIODIC;
- evt->set_mode = hpet_msi_set_mode; + evt->set_dev_mode = hpet_msi_set_mode; evt->set_next_event = hpet_msi_next_event; evt->cpumask = cpumask_of(hdev->cpu);
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index aae9413..9d29f0d 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -962,7 +962,7 @@ static int lguest_clockevent_set_next_event(unsigned long delta, return 0; }
-static void lguest_clockevent_set_mode(enum clock_event_mode mode, +static int lguest_clockevent_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { switch (mode) { @@ -978,7 +978,10 @@ static void lguest_clockevent_set_mode(enum clock_event_mode mode, BUG(); case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
/* This describes our primitive timer chip. */ @@ -986,7 +989,7 @@ static struct clock_event_device lguest_clockevent = { .name = "lguest", .features = CLOCK_EVT_FEAT_ONESHOT, .set_next_event = lguest_clockevent_set_next_event, - .set_mode = lguest_clockevent_set_mode, + .set_dev_mode = lguest_clockevent_set_mode, .rating = INT_MAX, .mult = 1, .shift = 0, diff --git a/arch/x86/platform/uv/uv_time.c b/arch/x86/platform/uv/uv_time.c index 5c86786..54f6b0c 100644 --- a/arch/x86/platform/uv/uv_time.c +++ b/arch/x86/platform/uv/uv_time.c @@ -32,7 +32,7 @@
static cycle_t uv_read_rtc(struct clocksource *cs); static int uv_rtc_next_event(unsigned long, struct clock_event_device *); -static void uv_rtc_timer_setup(enum clock_event_mode, +static int uv_rtc_timer_setup(enum clock_event_mode, struct clock_event_device *);
static struct clocksource clocksource_uv = { @@ -50,7 +50,7 @@ static struct clock_event_device clock_event_device_uv = { .rating = 400, .irq = -1, .set_next_event = uv_rtc_next_event, - .set_mode = uv_rtc_timer_setup, + .set_dev_mode = uv_rtc_timer_setup, .event_handler = NULL, };
@@ -323,7 +323,7 @@ static int uv_rtc_next_event(unsigned long delta, /* * Setup the RTC timer in oneshot mode */ -static void uv_rtc_timer_setup(enum clock_event_mode mode, +static int uv_rtc_timer_setup(enum clock_event_mode mode, struct clock_event_device *evt) { int ced_cpu = cpumask_first(evt->cpumask); @@ -338,7 +338,10 @@ static void uv_rtc_timer_setup(enum clock_event_mode mode, case CLOCK_EVT_MODE_SHUTDOWN: uv_rtc_unset_timer(ced_cpu, 1); break; + default: + return -ENOSYS; } + return 0; }
static void uv_rtc_interrupt(void) diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index 7b78f88..27cede5 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -274,7 +274,7 @@ static s64 get_abs_timeout(unsigned long delta) return xen_clocksource_read() + delta; }
-static void xen_timerop_set_mode(enum clock_event_mode mode, +static int xen_timerop_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { switch (mode) { @@ -291,7 +291,10 @@ static void xen_timerop_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_SHUTDOWN: HYPERVISOR_set_timer_op(0); /* cancel timeout */ break; + default: + return -ENOSYS; } + return 0; }
static int xen_timerop_set_next_event(unsigned long delta, @@ -320,13 +323,13 @@ static const struct clock_event_device xen_timerop_clockevent = { .shift = 0, .rating = 500,
- .set_mode = xen_timerop_set_mode, + .set_dev_mode = xen_timerop_set_mode, .set_next_event = xen_timerop_set_next_event, };
-static void xen_vcpuop_set_mode(enum clock_event_mode mode, +static int xen_vcpuop_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { int cpu = smp_processor_id(); @@ -349,7 +352,10 @@ static void xen_vcpuop_set_mode(enum clock_event_mode mode, break; case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
static int xen_vcpuop_set_next_event(unsigned long delta, @@ -382,7 +388,7 @@ static const struct clock_event_device xen_vcpuop_clockevent = { .shift = 0, .rating = 500,
- .set_mode = xen_vcpuop_set_mode, + .set_dev_mode = xen_vcpuop_set_mode, .set_next_event = xen_vcpuop_set_next_event, };
Clockevents core now supports ->set_dev_mode() (as a replacement to ->set_mode()), with capability to return error codes.
Migrate all drivers in 'drivers/clocksource' to implement this new callback.
Drivers now return -ENOSYS when a unsupported mode is passed to their ->set_dev_mode() callbacks and return 0 on success.
Most of the changes are automated with help of Coccinelle (http://coccinelle.lip6.fr/) and the ones left are around the switch block which are handled manually.
Some drivers had a WARN()/BUG()/pr_err()/empty-implementation for unsupported modes. These statements and unsupported modes are removed now as proper error handling with a WARN_ON() is done at clockevents core.
A simplified version of the semantic patch is:
@@ identifier m,c,setmode; @@ -void +int setmode(enum clock_event_mode m, struct clock_event_device *c);
@@ identifier setmode; @@ -void +int setmode(enum clock_event_mode, struct clock_event_device *);
@fixret@ identifier m,c,setmode; @@ -void +int setmode(enum clock_event_mode m, struct clock_event_device *c) { ... + return 0; }
@depends on fixret@ identifier ced; identifier fixret.setmode; @@ ... struct clock_event_device ced = { ..., -.set_mode +.set_dev_mode = setmode, };
@depends on fixret@ expression ced; identifier fixret.setmode; @@ - ced->set_mode + ced->set_dev_mode = setmode
@depends on fixret@ identifier fixret.setmode; @@ { . -set_mode +set_dev_mode = setmode }
@depends on fixret@ expression ced; identifier fixret.setmode; @@ - ced.set_mode + ced.set_dev_mode = setmode
Reviewed-by: Preeti U Murthy preeti@linux.vnet.ibm.com Signed-off-by: Viresh Kumar viresh.kumar@linaro.org --- 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 | 7 +++++-- drivers/clocksource/moxart_timer.c | 8 ++++--- drivers/clocksource/mxs_timer.c | 7 +++++-- drivers/clocksource/nomadik-mtu.c | 7 +++++-- drivers/clocksource/qcom-timer.c | 9 +++++--- 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 | 7 +++++-- drivers/clocksource/timer-sun5i.c | 9 +++++--- drivers/clocksource/timer-u300.c | 7 +++++-- drivers/clocksource/vf_pit_timer.c | 12 ++++++++--- drivers/clocksource/vt8500_timer.c | 7 +++++-- drivers/clocksource/zevio-timer.c | 8 ++++--- 34 files changed, 246 insertions(+), 110 deletions(-)
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 5163ec1..44f1eaa 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -179,7 +179,7 @@ static irqreturn_t arch_timer_handler_virt_mem(int irq, void *dev_id) return timer_handler(ARCH_TIMER_MEM_VIRT_ACCESS, evt); }
-static __always_inline void timer_set_mode(const int access, int mode, +static __always_inline int timer_set_mode(const int access, int mode, struct clock_event_device *clk) { unsigned long ctrl; @@ -190,33 +190,37 @@ static __always_inline void timer_set_mode(const int access, int mode, ctrl &= ~ARCH_TIMER_CTRL_ENABLE; arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk); break; - default: + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
-static void arch_timer_set_mode_virt(enum clock_event_mode mode, +static int arch_timer_set_mode_virt(enum clock_event_mode mode, struct clock_event_device *clk) { - timer_set_mode(ARCH_TIMER_VIRT_ACCESS, mode, clk); + return timer_set_mode(ARCH_TIMER_VIRT_ACCESS, mode, clk); }
-static void arch_timer_set_mode_phys(enum clock_event_mode mode, +static int arch_timer_set_mode_phys(enum clock_event_mode mode, struct clock_event_device *clk) { - timer_set_mode(ARCH_TIMER_PHYS_ACCESS, mode, clk); + return timer_set_mode(ARCH_TIMER_PHYS_ACCESS, mode, clk); }
-static void arch_timer_set_mode_virt_mem(enum clock_event_mode mode, +static int arch_timer_set_mode_virt_mem(enum clock_event_mode mode, struct clock_event_device *clk) { - timer_set_mode(ARCH_TIMER_MEM_VIRT_ACCESS, mode, clk); + return timer_set_mode(ARCH_TIMER_MEM_VIRT_ACCESS, mode, clk); }
-static void arch_timer_set_mode_phys_mem(enum clock_event_mode mode, +static int arch_timer_set_mode_phys_mem(enum clock_event_mode mode, struct clock_event_device *clk) { - timer_set_mode(ARCH_TIMER_MEM_PHYS_ACCESS, mode, clk); + return timer_set_mode(ARCH_TIMER_MEM_PHYS_ACCESS, mode, clk); }
static __always_inline void set_next_event(const int access, unsigned long evt, @@ -271,11 +275,11 @@ static void __arch_timer_setup(unsigned type, clk->cpumask = cpumask_of(smp_processor_id()); if (arch_timer_use_virtual) { clk->irq = arch_timer_ppi[VIRT_PPI]; - clk->set_mode = arch_timer_set_mode_virt; + clk->set_dev_mode = arch_timer_set_mode_virt; clk->set_next_event = arch_timer_set_next_event_virt; } else { clk->irq = arch_timer_ppi[PHYS_SECURE_PPI]; - clk->set_mode = arch_timer_set_mode_phys; + clk->set_dev_mode = arch_timer_set_mode_phys; clk->set_next_event = arch_timer_set_next_event_phys; } } else { @@ -284,17 +288,17 @@ static void __arch_timer_setup(unsigned type, clk->rating = 400; clk->cpumask = cpu_all_mask; if (arch_timer_mem_use_virtual) { - clk->set_mode = arch_timer_set_mode_virt_mem; + clk->set_dev_mode = arch_timer_set_mode_virt_mem; clk->set_next_event = arch_timer_set_next_event_virt_mem; } else { - clk->set_mode = arch_timer_set_mode_phys_mem; + clk->set_dev_mode = arch_timer_set_mode_phys_mem; clk->set_next_event = arch_timer_set_next_event_phys_mem; } }
- clk->set_mode(CLOCK_EVT_MODE_SHUTDOWN, clk); + clk->set_dev_mode(CLOCK_EVT_MODE_SHUTDOWN, clk);
clockevents_config_and_register(clk, arch_timer_rate, 0xf, 0x7fffffff); } @@ -457,7 +461,7 @@ static void arch_timer_stop(struct clock_event_device *clk) disable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI]); }
- clk->set_mode(CLOCK_EVT_MODE_UNUSED, clk); + clk->set_dev_mode(CLOCK_EVT_MODE_UNUSED, clk); }
static int arch_timer_cpu_notify(struct notifier_block *self, diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c index 0fc31d0..937e039 100644 --- a/drivers/clocksource/arm_global_timer.c +++ b/drivers/clocksource/arm_global_timer.c @@ -107,7 +107,7 @@ static void gt_compare_set(unsigned long delta, int periodic) writel(ctrl, gt_base + GT_CONTROL); }
-static void gt_clockevent_set_mode(enum clock_event_mode mode, +static int gt_clockevent_set_mode(enum clock_event_mode mode, struct clock_event_device *clk) { unsigned long ctrl; @@ -124,9 +124,12 @@ static void gt_clockevent_set_mode(enum clock_event_mode mode, GT_CONTROL_IRQ_ENABLE | GT_CONTROL_AUTO_INC); writel(ctrl, gt_base + GT_CONTROL); break; - default: + case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
static int gt_clockevent_set_next_event(unsigned long evt, @@ -171,7 +174,7 @@ static int gt_clockevents_init(struct clock_event_device *clk) clk->name = "arm_global_timer"; clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERCPU; - clk->set_mode = gt_clockevent_set_mode; + clk->set_dev_mode = gt_clockevent_set_mode; clk->set_next_event = gt_clockevent_set_next_event; clk->cpumask = cpumask_of(cpu); clk->rating = 300; diff --git a/drivers/clocksource/bcm2835_timer.c b/drivers/clocksource/bcm2835_timer.c index 26ed331..455b5dd 100644 --- a/drivers/clocksource/bcm2835_timer.c +++ b/drivers/clocksource/bcm2835_timer.c @@ -54,7 +54,7 @@ static u64 notrace bcm2835_sched_read(void) return readl_relaxed(system_clock); }
-static void bcm2835_time_set_mode(enum clock_event_mode mode, +static int bcm2835_time_set_mode(enum clock_event_mode mode, struct clock_event_device *evt_dev) { switch (mode) { @@ -64,9 +64,9 @@ static void bcm2835_time_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_RESUME: break; default: - WARN(1, "%s: unhandled event mode %d\n", __func__, mode); - break; + return -ENOSYS; } + return 0; }
static int bcm2835_time_set_next_event(unsigned long event, @@ -129,7 +129,7 @@ static void __init bcm2835_timer_init(struct device_node *node) timer->evt.name = node->name; timer->evt.rating = 300; timer->evt.features = CLOCK_EVT_FEAT_ONESHOT; - timer->evt.set_mode = bcm2835_time_set_mode; + timer->evt.set_dev_mode = bcm2835_time_set_mode; timer->evt.set_next_event = bcm2835_time_set_next_event; timer->evt.cpumask = cpumask_of(0); timer->act.name = node->name; diff --git a/drivers/clocksource/bcm_kona_timer.c b/drivers/clocksource/bcm_kona_timer.c index 0595dc6..a3899f4 100644 --- a/drivers/clocksource/bcm_kona_timer.c +++ b/drivers/clocksource/bcm_kona_timer.c @@ -128,7 +128,7 @@ static int kona_timer_set_next_event(unsigned long clc, return 0; }
-static void kona_timer_set_mode(enum clock_event_mode mode, +static int kona_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *unused) { switch (mode) { @@ -137,16 +137,20 @@ static void kona_timer_set_mode(enum clock_event_mode mode, break; case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: - default: + case CLOCK_EVT_MODE_RESUME: kona_timer_disable_and_clear(timers.tmr_regs); + break; + default: + return -ENOSYS; } + return 0; }
static struct clock_event_device kona_clockevent_timer = { .name = "timer 1", .features = CLOCK_EVT_FEAT_ONESHOT, .set_next_event = kona_timer_set_next_event, - .set_mode = kona_timer_set_mode + .set_dev_mode = kona_timer_set_mode };
static void __init kona_timer_clockevents_init(void) diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c index 49fbe28..3d355ec 100644 --- a/drivers/clocksource/cadence_ttc_timer.c +++ b/drivers/clocksource/cadence_ttc_timer.c @@ -196,7 +196,7 @@ static int ttc_set_next_event(unsigned long cycles, * @mode: Mode to be set * @evt: Address of clock event instance **/ -static void ttc_set_mode(enum clock_event_mode mode, +static int ttc_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt); @@ -224,7 +224,10 @@ static void ttc_set_mode(enum clock_event_mode mode, __raw_writel(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); break; + default: + return -ENOSYS; } + return 0; }
static int ttc_rate_change_clocksource_cb(struct notifier_block *nb, @@ -428,7 +431,7 @@ static void __init ttc_setup_clockevent(struct clk *clk, ttcce->ce.name = "ttc_clockevent"; ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; ttcce->ce.set_next_event = ttc_set_next_event; - ttcce->ce.set_mode = ttc_set_mode; + ttcce->ce.set_dev_mode = ttc_set_mode; ttcce->ce.rating = 200; ttcce->ce.irq = irq; ttcce->ce.cpumask = cpu_possible_mask; diff --git a/drivers/clocksource/cs5535-clockevt.c b/drivers/clocksource/cs5535-clockevt.c index db21052..c1b1f7f 100644 --- a/drivers/clocksource/cs5535-clockevt.c +++ b/drivers/clocksource/cs5535-clockevt.c @@ -77,15 +77,26 @@ static void start_timer(struct cs5535_mfgpt_timer *timer, uint16_t delta) MFGPT_SETUP_CNTEN | MFGPT_SETUP_CMP2); }
-static void mfgpt_set_mode(enum clock_event_mode mode, +static int mfgpt_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { disable_timer(cs5535_event_clock);
- if (mode == CLOCK_EVT_MODE_PERIODIC) + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: start_timer(cs5535_event_clock, MFGPT_PERIODIC); + break; + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: + break; + default: + return -ENOSYS; + }
cs5535_tick_mode = mode; + return 0; }
static int mfgpt_next_event(unsigned long delta, struct clock_event_device *evt) @@ -97,7 +108,7 @@ static int mfgpt_next_event(unsigned long delta, struct clock_event_device *evt) static struct clock_event_device cs5535_clockevent = { .name = DRV_NAME, .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_mode = mfgpt_set_mode, + .set_dev_mode = mfgpt_set_mode, .set_next_event = mfgpt_next_event, .rating = 250, }; diff --git a/drivers/clocksource/dummy_timer.c b/drivers/clocksource/dummy_timer.c index ad35725..2d0cc09 100644 --- a/drivers/clocksource/dummy_timer.c +++ b/drivers/clocksource/dummy_timer.c @@ -16,13 +16,24 @@
static DEFINE_PER_CPU(struct clock_event_device, dummy_timer_evt);
-static void dummy_timer_set_mode(enum clock_event_mode mode, +static int dummy_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: /* * Core clockevents code will call this when exchanging timer devices. * We don't need to do anything here. */ + break; + default: + return -ENOSYS; + } + return 0; }
static void dummy_timer_setup(void) @@ -35,7 +46,7 @@ static void dummy_timer_setup(void) CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_DUMMY; evt->rating = 100; - evt->set_mode = dummy_timer_set_mode; + evt->set_dev_mode = dummy_timer_set_mode; evt->cpumask = cpumask_of(cpu);
clockevents_register_device(evt); diff --git a/drivers/clocksource/dw_apb_timer.c b/drivers/clocksource/dw_apb_timer.c index f3656a6b..15ac39c 100644 --- a/drivers/clocksource/dw_apb_timer.c +++ b/drivers/clocksource/dw_apb_timer.c @@ -110,7 +110,7 @@ static void apbt_enable_int(struct dw_apb_timer *timer) apbt_writel(timer, ctrl, APBTMR_N_CONTROL); }
-static void apbt_set_mode(enum clock_event_mode mode, +static int apbt_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { unsigned long ctrl; @@ -173,7 +173,10 @@ static void apbt_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_RESUME: apbt_enable_int(&dw_ced->timer); break; + default: + return -ENOSYS; } + return 0; }
static int apbt_next_event(unsigned long delta, @@ -232,7 +235,7 @@ dw_apb_clockevent_init(int cpu, const char *name, unsigned rating, dw_ced->ced.min_delta_ns = clockevent_delta2ns(5000, &dw_ced->ced); dw_ced->ced.cpumask = cpumask_of(cpu); dw_ced->ced.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; - dw_ced->ced.set_mode = apbt_set_mode; + dw_ced->ced.set_dev_mode = apbt_set_mode; dw_ced->ced.set_next_event = apbt_next_event; dw_ced->ced.irq = dw_ced->timer.irq; dw_ced->ced.rating = rating; diff --git a/drivers/clocksource/em_sti.c b/drivers/clocksource/em_sti.c index 9d17083..34b9a01 100644 --- a/drivers/clocksource/em_sti.c +++ b/drivers/clocksource/em_sti.c @@ -251,7 +251,7 @@ static struct em_sti_priv *ced_to_em_sti(struct clock_event_device *ced) return container_of(ced, struct em_sti_priv, ced); }
-static void em_sti_clock_event_mode(enum clock_event_mode mode, +static int em_sti_clock_event_mode(enum clock_event_mode mode, struct clock_event_device *ced) { struct em_sti_priv *p = ced_to_em_sti(ced); @@ -275,9 +275,12 @@ static void em_sti_clock_event_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_UNUSED: em_sti_stop(p, USER_CLOCKEVENT); break; - default: + case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
static int em_sti_clock_event_next(unsigned long delta, @@ -303,11 +306,11 @@ static void em_sti_register_clockevent(struct em_sti_priv *p) ced->rating = 200; ced->cpumask = cpu_possible_mask; ced->set_next_event = em_sti_clock_event_next; - ced->set_mode = em_sti_clock_event_mode; + ced->set_dev_mode = em_sti_clock_event_mode;
dev_info(&p->pdev->dev, "used for clock events\n");
- /* Register with dummy 1 Hz value, gets updated in ->set_mode() */ + /* Register with dummy 1 Hz value, gets updated in ->set_dev_mode() */ clockevents_config_and_register(ced, 1, 2, 0xffffffff); }
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c index acf5a32..f4c70d3 100644 --- a/drivers/clocksource/exynos_mct.c +++ b/drivers/clocksource/exynos_mct.c @@ -242,7 +242,7 @@ static int exynos4_comp_set_next_event(unsigned long cycles, return 0; }
-static void exynos4_comp_set_mode(enum clock_event_mode mode, +static int exynos4_comp_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { unsigned long cycles_per_jiffy; @@ -260,7 +260,10 @@ static void exynos4_comp_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_SHUTDOWN: case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
static struct clock_event_device mct_comp_device = { @@ -268,7 +271,7 @@ static struct clock_event_device mct_comp_device = { .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .rating = 250, .set_next_event = exynos4_comp_set_next_event, - .set_mode = exynos4_comp_set_mode, + .set_dev_mode = exynos4_comp_set_mode, };
static irqreturn_t exynos4_mct_comp_isr(int irq, void *dev_id) @@ -344,7 +347,7 @@ static int exynos4_tick_set_next_event(unsigned long cycles, return 0; }
-static inline void exynos4_tick_set_mode(enum clock_event_mode mode, +static inline int exynos4_tick_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick); @@ -364,7 +367,10 @@ static inline void exynos4_tick_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_SHUTDOWN: case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
static int exynos4_mct_tick_clear(struct mct_clock_event_device *mevt) @@ -413,7 +419,7 @@ static int exynos4_local_timer_setup(struct clock_event_device *evt) evt->name = mevt->name; evt->cpumask = cpumask_of(cpu); evt->set_next_event = exynos4_tick_set_next_event; - evt->set_mode = exynos4_tick_set_mode; + evt->set_dev_mode = exynos4_tick_set_mode; evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; evt->rating = 450;
@@ -440,7 +446,7 @@ static int exynos4_local_timer_setup(struct clock_event_device *evt)
static void exynos4_local_timer_stop(struct clock_event_device *evt) { - evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); + evt->set_dev_mode(CLOCK_EVT_MODE_UNUSED, evt); if (mct_int_type == MCT_INT_SPI) free_irq(evt->irq, this_cpu_ptr(&percpu_mct_tick)); else diff --git a/drivers/clocksource/i8253.c b/drivers/clocksource/i8253.c index 14ee3ef..936da9c 100644 --- a/drivers/clocksource/i8253.c +++ b/drivers/clocksource/i8253.c @@ -105,7 +105,7 @@ int __init clocksource_i8253_init(void) * * This is also called after resume to bring the PIT into operation again. */ -static void init_pit_timer(enum clock_event_mode mode, +static int init_pit_timer(enum clock_event_mode mode, struct clock_event_device *evt) { raw_spin_lock(&i8253_lock); @@ -136,8 +136,12 @@ static void init_pit_timer(enum clock_event_mode mode, case CLOCK_EVT_MODE_RESUME: /* Nothing to do here */ break; + default: + raw_spin_unlock(&i8253_lock); + return -ENOSYS; } raw_spin_unlock(&i8253_lock); + return 0; }
/* @@ -162,7 +166,7 @@ static int pit_next_event(unsigned long delta, struct clock_event_device *evt) struct clock_event_device i8253_clockevent = { .name = "pit", .features = CLOCK_EVT_FEAT_PERIODIC, - .set_mode = init_pit_timer, + .set_dev_mode = init_pit_timer, .set_next_event = pit_next_event, };
diff --git a/drivers/clocksource/metag_generic.c b/drivers/clocksource/metag_generic.c index 9e4db41..ba6e876 100644 --- a/drivers/clocksource/metag_generic.c +++ b/drivers/clocksource/metag_generic.c @@ -56,7 +56,7 @@ static int metag_timer_set_next_event(unsigned long delta, return 0; }
-static void metag_timer_set_mode(enum clock_event_mode mode, +static int metag_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { switch (mode) { @@ -72,7 +72,10 @@ static void metag_timer_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_UNUSED: WARN_ON(1); break; + default: + return -ENOSYS; }; + return 0; }
static cycle_t metag_clocksource_read(struct clocksource *cs) @@ -129,7 +132,7 @@ static void arch_timer_setup(unsigned int cpu) clk->rating = 200, clk->shift = 12, clk->irq = tbisig_map(TBID_SIGNUM_TRT), - clk->set_mode = metag_timer_set_mode, + clk->set_dev_mode = metag_timer_set_mode, clk->set_next_event = metag_timer_set_next_event,
clk->mult = div_sc(hwtimer_freq, NSEC_PER_SEC, clk->shift); diff --git a/drivers/clocksource/moxart_timer.c b/drivers/clocksource/moxart_timer.c index 5eb2c35..edae259 100644 --- a/drivers/clocksource/moxart_timer.c +++ b/drivers/clocksource/moxart_timer.c @@ -58,7 +58,7 @@ static void __iomem *base; static unsigned int clock_count_per_tick;
-static void moxart_clkevt_mode(enum clock_event_mode mode, +static int moxart_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *clk) { switch (mode) { @@ -73,10 +73,12 @@ static void moxart_clkevt_mode(enum clock_event_mode mode, break; case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: - default: writel(TIMER1_DISABLE, base + TIMER_CR); break; + default: + return -ENOSYS; } + return 0; }
static int moxart_clkevt_next_event(unsigned long cycles, @@ -98,7 +100,7 @@ static struct clock_event_device moxart_clockevent = { .name = "moxart_timer", .rating = 200, .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_mode = moxart_clkevt_mode, + .set_dev_mode = moxart_clkevt_mode, .set_next_event = moxart_clkevt_next_event, };
diff --git a/drivers/clocksource/mxs_timer.c b/drivers/clocksource/mxs_timer.c index 445b68a..b6e4576 100644 --- a/drivers/clocksource/mxs_timer.c +++ b/drivers/clocksource/mxs_timer.c @@ -150,7 +150,7 @@ static const char *clock_event_mode_label[] const = { }; #endif /* DEBUG */
-static void mxs_set_mode(enum clock_event_mode mode, +static int mxs_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { /* Disable interrupt in timer module */ @@ -190,13 +190,16 @@ static void mxs_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_RESUME: /* Left event sources disabled, no more interrupts appear */ break; + default: + return -ENOSYS; } + return 0; }
static struct clock_event_device mxs_clockevent_device = { .name = "mxs_timrot", .features = CLOCK_EVT_FEAT_ONESHOT, - .set_mode = mxs_set_mode, + .set_dev_mode = mxs_set_mode, .set_next_event = timrotv2_set_next_event, .rating = 200, }; diff --git a/drivers/clocksource/nomadik-mtu.c b/drivers/clocksource/nomadik-mtu.c index a709cfa..8c3d355 100644 --- a/drivers/clocksource/nomadik-mtu.c +++ b/drivers/clocksource/nomadik-mtu.c @@ -119,7 +119,7 @@ static void nmdk_clkevt_reset(void) } }
-static void nmdk_clkevt_mode(enum clock_event_mode mode, +static int nmdk_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) { switch (mode) { @@ -140,7 +140,10 @@ static void nmdk_clkevt_mode(enum clock_event_mode mode, break; case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
static void nmdk_clksrc_reset(void) @@ -167,7 +170,7 @@ static struct clock_event_device nmdk_clkevt = { .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_DYNIRQ, .rating = 200, - .set_mode = nmdk_clkevt_mode, + .set_dev_mode = nmdk_clkevt_mode, .set_next_event = nmdk_clkevt_next, .resume = nmdk_clkevt_resume, }; diff --git a/drivers/clocksource/qcom-timer.c b/drivers/clocksource/qcom-timer.c index e807acf..b34ef31 100644 --- a/drivers/clocksource/qcom-timer.c +++ b/drivers/clocksource/qcom-timer.c @@ -75,7 +75,7 @@ static int msm_timer_set_next_event(unsigned long cycles, return 0; }
-static void msm_timer_set_mode(enum clock_event_mode mode, +static int msm_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { u32 ctrl; @@ -93,8 +93,11 @@ static void msm_timer_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: break; + default: + return -ENOSYS; } writel_relaxed(ctrl, event_base + TIMER_ENABLE); + return 0; }
static struct clock_event_device __percpu *msm_evt; @@ -126,7 +129,7 @@ static int msm_local_timer_setup(struct clock_event_device *evt) evt->name = "msm_timer"; evt->features = CLOCK_EVT_FEAT_ONESHOT; evt->rating = 200; - evt->set_mode = msm_timer_set_mode; + evt->set_dev_mode = msm_timer_set_mode; evt->set_next_event = msm_timer_set_next_event; evt->cpumask = cpumask_of(cpu);
@@ -147,7 +150,7 @@ static int msm_local_timer_setup(struct clock_event_device *evt)
static void msm_local_timer_stop(struct clock_event_device *evt) { - evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); + evt->set_dev_mode(CLOCK_EVT_MODE_UNUSED, evt); disable_percpu_irq(evt->irq); }
diff --git a/drivers/clocksource/samsung_pwm_timer.c b/drivers/clocksource/samsung_pwm_timer.c index 5645cfc..4ce11bf 100644 --- a/drivers/clocksource/samsung_pwm_timer.c +++ b/drivers/clocksource/samsung_pwm_timer.c @@ -207,7 +207,7 @@ static int samsung_set_next_event(unsigned long cycles, return 0; }
-static void samsung_set_mode(enum clock_event_mode mode, +static int samsung_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { samsung_time_stop(pwm.event_id); @@ -225,7 +225,10 @@ static void samsung_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_SHUTDOWN: case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
static void samsung_clockevent_resume(struct clock_event_device *cev) @@ -244,7 +247,7 @@ static struct clock_event_device time_event_device = { .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .rating = 200, .set_next_event = samsung_set_next_event, - .set_mode = samsung_set_mode, + .set_dev_mode = samsung_set_mode, .resume = samsung_clockevent_resume, };
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index 0b1836a..ed4e5d0 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -585,7 +585,7 @@ static void sh_cmt_clock_event_start(struct sh_cmt_priv *p, int periodic) sh_cmt_set_next(p, p->max_match_value); }
-static void sh_cmt_clock_event_mode(enum clock_event_mode mode, +static int sh_cmt_clock_event_mode(enum clock_event_mode mode, struct clock_event_device *ced) { struct sh_cmt_priv *p = ced_to_sh_cmt(ced); @@ -613,9 +613,12 @@ static void sh_cmt_clock_event_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_UNUSED: sh_cmt_stop(p, FLAG_CLOCKEVENT); break; - default: + case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
static int sh_cmt_clock_event_next(unsigned long delta, @@ -661,7 +664,7 @@ static void sh_cmt_register_clockevent(struct sh_cmt_priv *p, ced->rating = rating; ced->cpumask = cpumask_of(0); ced->set_next_event = sh_cmt_clock_event_next; - ced->set_mode = sh_cmt_clock_event_mode; + ced->set_dev_mode = sh_cmt_clock_event_mode; ced->suspend = sh_cmt_clock_event_suspend; ced->resume = sh_cmt_clock_event_resume;
diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c index e30d76e..3d51350 100644 --- a/drivers/clocksource/sh_mtu2.c +++ b/drivers/clocksource/sh_mtu2.c @@ -184,7 +184,7 @@ static struct sh_mtu2_priv *ced_to_sh_mtu2(struct clock_event_device *ced) return container_of(ced, struct sh_mtu2_priv, ced); }
-static void sh_mtu2_clock_event_mode(enum clock_event_mode mode, +static int sh_mtu2_clock_event_mode(enum clock_event_mode mode, struct clock_event_device *ced) { struct sh_mtu2_priv *p = ced_to_sh_mtu2(ced); @@ -210,9 +210,12 @@ static void sh_mtu2_clock_event_mode(enum clock_event_mode mode, sh_mtu2_disable(p); break; case CLOCK_EVT_MODE_SHUTDOWN: - default: + case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
static void sh_mtu2_clock_event_suspend(struct clock_event_device *ced) @@ -237,7 +240,7 @@ static void sh_mtu2_register_clockevent(struct sh_mtu2_priv *p, ced->features = CLOCK_EVT_FEAT_PERIODIC; ced->rating = rating; ced->cpumask = cpumask_of(0); - ced->set_mode = sh_mtu2_clock_event_mode; + ced->set_dev_mode = sh_mtu2_clock_event_mode; ced->suspend = sh_mtu2_clock_event_suspend; ced->resume = sh_mtu2_clock_event_resume;
diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index ecd7b60..e8f9573 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c @@ -321,7 +321,7 @@ static void sh_tmu_clock_event_start(struct sh_tmu_priv *p, int periodic) } }
-static void sh_tmu_clock_event_mode(enum clock_event_mode mode, +static int sh_tmu_clock_event_mode(enum clock_event_mode mode, struct clock_event_device *ced) { struct sh_tmu_priv *p = ced_to_sh_tmu(ced); @@ -352,9 +352,12 @@ static void sh_tmu_clock_event_mode(enum clock_event_mode mode, sh_tmu_disable(p); break; case CLOCK_EVT_MODE_SHUTDOWN: - default: + case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
static int sh_tmu_clock_event_next(unsigned long delta, @@ -393,7 +396,7 @@ static void sh_tmu_register_clockevent(struct sh_tmu_priv *p, ced->rating = rating; ced->cpumask = cpumask_of(0); ced->set_next_event = sh_tmu_clock_event_next; - ced->set_mode = sh_tmu_clock_event_mode; + ced->set_dev_mode = sh_tmu_clock_event_mode; ced->suspend = sh_tmu_clock_event_suspend; ced->resume = sh_tmu_clock_event_resume;
diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c index efb17c3..b755fcb 100644 --- a/drivers/clocksource/sun4i_timer.c +++ b/drivers/clocksource/sun4i_timer.c @@ -81,7 +81,7 @@ static void sun4i_clkevt_time_start(u8 timer, bool periodic) timer_base + TIMER_CTL_REG(timer)); }
-static void sun4i_clkevt_mode(enum clock_event_mode mode, +static int sun4i_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *clk) { switch (mode) { @@ -96,10 +96,13 @@ static void sun4i_clkevt_mode(enum clock_event_mode mode, break; case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: - default: + case CLOCK_EVT_MODE_RESUME: sun4i_clkevt_time_stop(0); break; + default: + return -ENOSYS; } + return 0; }
static int sun4i_clkevt_next_event(unsigned long evt, @@ -116,7 +119,7 @@ static struct clock_event_device sun4i_clockevent = { .name = "sun4i_tick", .rating = 350, .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_mode = sun4i_clkevt_mode, + .set_dev_mode = sun4i_clkevt_mode, .set_next_event = sun4i_clkevt_next_event, };
diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c index 00fdd11..b6b23f1 100644 --- a/drivers/clocksource/tcb_clksrc.c +++ b/drivers/clocksource/tcb_clksrc.c @@ -91,7 +91,7 @@ static struct tc_clkevt_device *to_tc_clkevt(struct clock_event_device *clkevt) */ static u32 timer_clock;
-static void tc_mode(enum clock_event_mode m, struct clock_event_device *d) +static int tc_mode(enum clock_event_mode m, struct clock_event_device *d) { struct tc_clkevt_device *tcd = to_tc_clkevt(d); void __iomem *regs = tcd->regs; @@ -137,9 +137,14 @@ static void tc_mode(enum clock_event_mode m, struct clock_event_device *d) /* set_next_event() configures and starts the timer */ break;
- default: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
static int tc_next_event(unsigned long delta, struct clock_event_device *d) @@ -160,7 +165,7 @@ static struct tc_clkevt_device clkevt = { /* Should be lower than at91rm9200's system timer */ .rating = 125, .set_next_event = tc_next_event, - .set_mode = tc_mode, + .set_dev_mode = tc_mode, }, };
diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c index d1869f0..aa0d3e9 100644 --- a/drivers/clocksource/tegra20_timer.c +++ b/drivers/clocksource/tegra20_timer.c @@ -69,7 +69,7 @@ static int tegra_timer_set_next_event(unsigned long cycles, return 0; }
-static void tegra_timer_set_mode(enum clock_event_mode mode, +static int tegra_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { u32 reg; @@ -87,7 +87,10 @@ static void tegra_timer_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_SHUTDOWN: case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
static struct clock_event_device tegra_clockevent = { @@ -95,7 +98,7 @@ static struct clock_event_device tegra_clockevent = { .rating = 300, .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, .set_next_event = tegra_timer_set_next_event, - .set_mode = tegra_timer_set_mode, + .set_dev_mode = tegra_timer_set_mode, };
static u64 notrace tegra_read_sched_clock(void) diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c index 0451e62..8aa35c1 100644 --- a/drivers/clocksource/time-armada-370-xp.c +++ b/drivers/clocksource/time-armada-370-xp.c @@ -120,12 +120,12 @@ armada_370_xp_clkevt_next_event(unsigned long delta, return 0; }
-static void +static int armada_370_xp_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) { - if (mode == CLOCK_EVT_MODE_PERIODIC) { - + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: /* * Setup timer to fire at 1/HZ intervals. */ @@ -136,7 +136,11 @@ armada_370_xp_clkevt_mode(enum clock_event_mode mode, * Enable timer. */ local_timer_ctrl_clrset(0, TIMER0_RELOAD_EN | enable_mask); - } else { + break; + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: /* * Disable timer. */ @@ -146,7 +150,11 @@ armada_370_xp_clkevt_mode(enum clock_event_mode mode, * ACK pending timer interrupt. */ writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS); + break; + default: + return -ENOSYS; } + return 0; }
static int armada_370_xp_clkevt_irq; @@ -184,7 +192,7 @@ static int armada_370_xp_timer_setup(struct clock_event_device *evt) evt->shift = 32, evt->rating = 300, evt->set_next_event = armada_370_xp_clkevt_next_event, - evt->set_mode = armada_370_xp_clkevt_mode, + evt->set_dev_mode = armada_370_xp_clkevt_mode, evt->irq = armada_370_xp_clkevt_irq; evt->cpumask = cpumask_of(cpu);
@@ -196,7 +204,7 @@ static int armada_370_xp_timer_setup(struct clock_event_device *evt)
static void armada_370_xp_timer_stop(struct clock_event_device *evt) { - evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); + evt->set_dev_mode(CLOCK_EVT_MODE_UNUSED, evt); disable_percpu_irq(evt->irq); }
diff --git a/drivers/clocksource/time-efm32.c b/drivers/clocksource/time-efm32.c index 1a6205b..6e5af98 100644 --- a/drivers/clocksource/time-efm32.c +++ b/drivers/clocksource/time-efm32.c @@ -48,7 +48,7 @@ struct efm32_clock_event_ddata { unsigned periodic_top; };
-static void efm32_clock_event_set_mode(enum clock_event_mode mode, +static int efm32_clock_event_set_mode(enum clock_event_mode mode, struct clock_event_device *evtdev) { struct efm32_clock_event_ddata *ddata = @@ -81,7 +81,10 @@ static void efm32_clock_event_set_mode(enum clock_event_mode mode,
case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
static int efm32_clock_event_set_next_event(unsigned long evt, @@ -112,7 +115,7 @@ static struct efm32_clock_event_ddata clock_event_ddata = { .evtdev = { .name = "efm32 clockevent", .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_MODE_PERIODIC, - .set_mode = efm32_clock_event_set_mode, + .set_dev_mode = efm32_clock_event_set_mode, .set_next_event = efm32_clock_event_set_next_event, .rating = 200, }, diff --git a/drivers/clocksource/time-orion.c b/drivers/clocksource/time-orion.c index 0b3ce03..3a26ce9 100644 --- a/drivers/clocksource/time-orion.c +++ b/drivers/clocksource/time-orion.c @@ -60,21 +60,30 @@ static int orion_clkevt_next_event(unsigned long delta, return 0; }
-static void orion_clkevt_mode(enum clock_event_mode mode, +static int orion_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) { - if (mode == CLOCK_EVT_MODE_PERIODIC) { + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: /* setup and enable periodic timer at 1/HZ intervals */ writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD); writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL); atomic_io_modify(timer_base + TIMER_CTRL, TIMER1_RELOAD_EN | TIMER1_EN, TIMER1_RELOAD_EN | TIMER1_EN); - } else { + break; + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: /* disable timer */ atomic_io_modify(timer_base + TIMER_CTRL, TIMER1_RELOAD_EN | TIMER1_EN, 0); + break; + default: + return -ENOSYS; } + return 0; }
static struct clock_event_device orion_clkevt = { @@ -83,7 +92,7 @@ static struct clock_event_device orion_clkevt = { .shift = 32, .rating = 300, .set_next_event = orion_clkevt_next_event, - .set_mode = orion_clkevt_mode, + .set_dev_mode = orion_clkevt_mode, };
static irqreturn_t orion_clkevt_irq_handler(int irq, void *dev_id) diff --git a/drivers/clocksource/timer-keystone.c b/drivers/clocksource/timer-keystone.c index 0250354..722c7e3 100644 --- a/drivers/clocksource/timer-keystone.c +++ b/drivers/clocksource/timer-keystone.c @@ -141,7 +141,7 @@ static int keystone_set_next_event(unsigned long cycles, return keystone_timer_config(cycles, evt->mode); }
-static void keystone_set_mode(enum clock_event_mode mode, +static int keystone_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { switch (mode) { @@ -153,9 +153,12 @@ static void keystone_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_ONESHOT: keystone_timer_disable(); break; - default: + case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
static void __init keystone_timer_init(struct device_node *np) @@ -222,7 +225,7 @@ static void __init keystone_timer_init(struct device_node *np) /* setup clockevent */ event_dev->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; event_dev->set_next_event = keystone_set_next_event; - event_dev->set_mode = keystone_set_mode; + event_dev->set_dev_mode = keystone_set_mode; event_dev->cpumask = cpu_all_mask; event_dev->owner = THIS_MODULE; event_dev->name = TIMER_NAME; diff --git a/drivers/clocksource/timer-marco.c b/drivers/clocksource/timer-marco.c index b52e1c0..4f202eb 100644 --- a/drivers/clocksource/timer-marco.c +++ b/drivers/clocksource/timer-marco.c @@ -114,18 +114,22 @@ static int sirfsoc_timer_set_next_event(unsigned long delta, return 0; }
-static void sirfsoc_timer_set_mode(enum clock_event_mode mode, +static int sirfsoc_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *ce) { switch (mode) { case CLOCK_EVT_MODE_ONESHOT: /* enable in set_next_event */ + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: break; default: - break; + return -ENOSYS; }
sirfsoc_timer_count_disable(smp_processor_id()); + return 0; }
static void sirfsoc_clocksource_suspend(struct clocksource *cs) @@ -190,7 +194,7 @@ static int sirfsoc_local_timer_setup(struct clock_event_device *ce) ce->name = "local_timer"; ce->features = CLOCK_EVT_FEAT_ONESHOT; ce->rating = 200; - ce->set_mode = sirfsoc_timer_set_mode; + ce->set_dev_mode = sirfsoc_timer_set_mode; ce->set_next_event = sirfsoc_timer_set_next_event; clockevents_calc_mult_shift(ce, MARCO_CLOCK_FREQ, 60); ce->max_delta_ns = clockevent_delta2ns(-2, ce); diff --git a/drivers/clocksource/timer-prima2.c b/drivers/clocksource/timer-prima2.c index 1a6b2d6..9d79858 100644 --- a/drivers/clocksource/timer-prima2.c +++ b/drivers/clocksource/timer-prima2.c @@ -99,7 +99,7 @@ static int sirfsoc_timer_set_next_event(unsigned long delta, return next - now > delta ? -ETIME : 0; }
-static void sirfsoc_timer_set_mode(enum clock_event_mode mode, +static int sirfsoc_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *ce) { u32 val = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN); @@ -116,7 +116,10 @@ static void sirfsoc_timer_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
static void sirfsoc_clocksource_suspend(struct clocksource *cs) @@ -144,7 +147,7 @@ static struct clock_event_device sirfsoc_clockevent = { .name = "sirfsoc_clockevent", .rating = 200, .features = CLOCK_EVT_FEAT_ONESHOT, - .set_mode = sirfsoc_timer_set_mode, + .set_dev_mode = sirfsoc_timer_set_mode, .set_next_event = sirfsoc_timer_set_next_event, };
diff --git a/drivers/clocksource/timer-sun5i.c b/drivers/clocksource/timer-sun5i.c index deebcd6..4e288a9 100644 --- a/drivers/clocksource/timer-sun5i.c +++ b/drivers/clocksource/timer-sun5i.c @@ -79,7 +79,7 @@ static void sun5i_clkevt_time_start(u8 timer, bool periodic) timer_base + TIMER_CTL_REG(timer)); }
-static void sun5i_clkevt_mode(enum clock_event_mode mode, +static int sun5i_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *clk) { switch (mode) { @@ -94,10 +94,13 @@ static void sun5i_clkevt_mode(enum clock_event_mode mode, break; case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: - default: + case CLOCK_EVT_MODE_RESUME: sun5i_clkevt_time_stop(0); break; + default: + return -ENOSYS; } + return 0; }
static int sun5i_clkevt_next_event(unsigned long evt, @@ -114,7 +117,7 @@ static struct clock_event_device sun5i_clockevent = { .name = "sun5i_tick", .rating = 340, .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_mode = sun5i_clkevt_mode, + .set_dev_mode = sun5i_clkevt_mode, .set_next_event = sun5i_clkevt_next_event, };
diff --git a/drivers/clocksource/timer-u300.c b/drivers/clocksource/timer-u300.c index 5dcf756..000a865 100644 --- a/drivers/clocksource/timer-u300.c +++ b/drivers/clocksource/timer-u300.c @@ -192,7 +192,7 @@ struct u300_clockevent_data { * have oneshot timer active, the oneshot scheduling function * u300_set_next_event() is called immediately after. */ -static void u300_set_mode(enum clock_event_mode mode, +static int u300_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { struct u300_clockevent_data *cevdata = @@ -265,7 +265,10 @@ static void u300_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_RESUME: /* Ignore this call */ break; + default: + return -ENOSYS; } + return 0; }
/* @@ -315,7 +318,7 @@ static struct u300_clockevent_data u300_clockevent_data = { .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .set_next_event = u300_set_next_event, - .set_mode = u300_set_mode, + .set_dev_mode = u300_set_mode, }, };
diff --git a/drivers/clocksource/vf_pit_timer.c b/drivers/clocksource/vf_pit_timer.c index a918bc4..a34e5c8 100644 --- a/drivers/clocksource/vf_pit_timer.c +++ b/drivers/clocksource/vf_pit_timer.c @@ -86,16 +86,22 @@ static int pit_set_next_event(unsigned long delta, return 0; }
-static void pit_set_mode(enum clock_event_mode mode, +static int pit_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { switch (mode) { case CLOCK_EVT_MODE_PERIODIC: pit_set_next_event(cycle_per_jiffy, evt); break; - default: + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
static irqreturn_t pit_timer_interrupt(int irq, void *dev_id) @@ -121,7 +127,7 @@ static irqreturn_t pit_timer_interrupt(int irq, void *dev_id) static struct clock_event_device clockevent_pit = { .name = "VF pit timer", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_mode = pit_set_mode, + .set_dev_mode = pit_set_mode, .set_next_event = pit_set_next_event, .rating = 300, }; diff --git a/drivers/clocksource/vt8500_timer.c b/drivers/clocksource/vt8500_timer.c index 1098ed3..71e4b02 100644 --- a/drivers/clocksource/vt8500_timer.c +++ b/drivers/clocksource/vt8500_timer.c @@ -88,7 +88,7 @@ static int vt8500_timer_set_next_event(unsigned long cycles, return 0; }
-static void vt8500_timer_set_mode(enum clock_event_mode mode, +static int vt8500_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { switch (mode) { @@ -102,7 +102,10 @@ static void vt8500_timer_set_mode(enum clock_event_mode mode, regbase + TIMER_CTRL_VAL); writel(0, regbase + TIMER_IER_VAL); break; + default: + return -ENOSYS; } + return 0; }
static struct clock_event_device clockevent = { @@ -110,7 +113,7 @@ static struct clock_event_device clockevent = { .features = CLOCK_EVT_FEAT_ONESHOT, .rating = 200, .set_next_event = vt8500_timer_set_next_event, - .set_mode = vt8500_timer_set_mode, + .set_dev_mode = vt8500_timer_set_mode, };
static irqreturn_t vt8500_timer_interrupt(int irq, void *dev_id) diff --git a/drivers/clocksource/zevio-timer.c b/drivers/clocksource/zevio-timer.c index 7ce4421..59bd496 100644 --- a/drivers/clocksource/zevio-timer.c +++ b/drivers/clocksource/zevio-timer.c @@ -76,7 +76,7 @@ static int zevio_timer_set_event(unsigned long delta, return 0; }
-static void zevio_timer_set_mode(enum clock_event_mode mode, +static int zevio_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *dev) { struct zevio_timer *timer = container_of(dev, struct zevio_timer, @@ -98,10 +98,12 @@ static void zevio_timer_set_mode(enum clock_event_mode mode, writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL); break; case CLOCK_EVT_MODE_PERIODIC: - default: /* Unsupported */ break; + default: + return -ENOSYS; } + return 0; }
static irqreturn_t zevio_timer_interrupt(int irq, void *dev_id) @@ -162,7 +164,7 @@ static int __init zevio_timer_add(struct device_node *node) if (timer->interrupt_regs && irqnr) { timer->clkevt.name = timer->clockevent_name; timer->clkevt.set_next_event = zevio_timer_set_event; - timer->clkevt.set_mode = zevio_timer_set_mode; + timer->clkevt.set_dev_mode = zevio_timer_set_mode; timer->clkevt.rating = 200; timer->clkevt.cpumask = cpu_all_mask; timer->clkevt.features = CLOCK_EVT_FEAT_ONESHOT;
Clockevents core now supports ->set_dev_mode() (as a replacement to ->set_mode()), with capability to return error codes.
This patch migrates clockevent drivers for all architectures that had a single clockevent driver (in order to limit patch count).
Drivers now return -ENOSYS when a unsupported mode is passed to their ->set_dev_mode() callbacks and return 0 on success.
Most of the changes are automated with help of Coccinelle (http://coccinelle.lip6.fr/) and the ones left are around the switch block which are handled manually.
Some drivers had a WARN()/BUG()/pr_err()/empty-implementation for unsupported modes. These statements and unsupported modes are removed now as proper error handling with a WARN_ON() is done at clockevents core.
A simplified version of the semantic patch is:
@@ identifier m,c,setmode; @@ -void +int setmode(enum clock_event_mode m, struct clock_event_device *c);
@@ identifier setmode; @@ -void +int setmode(enum clock_event_mode, struct clock_event_device *);
@fixret@ identifier m,c,setmode; @@ -void +int setmode(enum clock_event_mode m, struct clock_event_device *c) { ... + return 0; }
@depends on fixret@ identifier ced; identifier fixret.setmode; @@ ... struct clock_event_device ced = { ..., -.set_mode +.set_dev_mode = setmode, };
@depends on fixret@ expression ced; identifier fixret.setmode; @@ - ced->set_mode + ced->set_dev_mode = setmode
@depends on fixret@ identifier fixret.setmode; @@ { . -set_mode +set_dev_mode = setmode }
@depends on fixret@ expression ced; identifier fixret.setmode; @@ - ced.set_mode + ced.set_dev_mode = setmode
Signed-off-by: Viresh Kumar viresh.kumar@linaro.org --- arch/alpha/kernel/time.c | 32 +++++++++++++++++++++++++++----- arch/arc/kernel/time.c | 11 +++++++---- 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/mn10300/kernel/cevt-mn10300.c | 14 ++++++++++++-- arch/openrisc/kernel/time.c | 7 +++++-- arch/powerpc/kernel/time.c | 18 ++++++++++++++---- arch/s390/kernel/time.c | 14 ++++++++++++-- arch/score/kernel/time.c | 7 ++++--- arch/sh/kernel/localtimer.c | 15 +++++++++++++-- arch/tile/kernel/time.c | 16 +++++++++++++--- arch/um/kernel/time.c | 7 +++++-- arch/unicore32/kernel/time.c | 7 +++++-- arch/xtensa/kernel/time.c | 9 +++++---- kernel/time/tick-broadcast-hrtimer.c | 11 ++++++++--- 19 files changed, 167 insertions(+), 54 deletions(-)
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c index ee39cee..97b8bac 100644 --- a/arch/alpha/kernel/time.c +++ b/arch/alpha/kernel/time.c @@ -104,11 +104,22 @@ rtc_timer_interrupt(int irq, void *dev) return IRQ_HANDLED; }
-static void +static int rtc_ce_set_mode(enum clock_event_mode mode, struct clock_event_device *ce) { /* The mode member of CE is updated in generic code. Since we only support periodic events, nothing to do. */ + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: + break; + + default: + return -ENOSYS; + } + return 0; }
static int @@ -129,7 +140,7 @@ init_rtc_clockevent(void) .features = CLOCK_EVT_FEAT_PERIODIC, .rating = 100, .cpumask = cpumask_of(cpu), - .set_mode = rtc_ce_set_mode, + .set_dev_mode = rtc_ce_set_mode, .set_next_event = rtc_ce_set_next_event, };
@@ -161,12 +172,23 @@ static struct clocksource qemu_cs = { * The QEMU alarm as a clock_event_device primitive. */
-static void +static int qemu_ce_set_mode(enum clock_event_mode mode, struct clock_event_device *ce) { /* The mode member of CE is updated for us in generic code. Just make sure that the event is disabled. */ - qemu_set_alarm_abs(0); + switch (mode) { + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: + qemu_set_alarm_abs(0); + break; + + default: + return -ENOSYS; + } + return 0; }
static int @@ -197,7 +219,7 @@ init_qemu_clockevent(void) .features = CLOCK_EVT_FEAT_ONESHOT, .rating = 400, .cpumask = cpumask_of(cpu), - .set_mode = qemu_ce_set_mode, + .set_dev_mode = qemu_ce_set_mode, .set_next_event = qemu_ce_set_next_event, };
diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c index 71c4252..5a9d348 100644 --- a/arch/arc/kernel/time.c +++ b/arch/arc/kernel/time.c @@ -163,7 +163,7 @@ static int arc_clkevent_set_next_event(unsigned long delta, return 0; }
-static void arc_clkevent_set_mode(enum clock_event_mode mode, +static int arc_clkevent_set_mode(enum clock_event_mode mode, struct clock_event_device *dev) { switch (mode) { @@ -171,12 +171,15 @@ static void arc_clkevent_set_mode(enum clock_event_mode mode, arc_timer_event_setup(arc_get_core_freq() / HZ); break; case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: break; default: - break; + return -ENOSYS; }
- return; + return 0; }
static DEFINE_PER_CPU(struct clock_event_device, arc_clockevent_device) = { @@ -186,7 +189,7 @@ static DEFINE_PER_CPU(struct clock_event_device, arc_clockevent_device) = { .rating = 300, .irq = TIMER0_IRQ, /* hardwired, no need for resources */ .set_next_event = arc_clkevent_set_next_event, - .set_mode = arc_clkevent_set_mode, + .set_dev_mode = arc_clkevent_set_mode, };
static irqreturn_t timer_irq_handler(int irq, void *dev_id) diff --git a/arch/avr32/kernel/time.c b/arch/avr32/kernel/time.c index d0f771b..3f82011 100644 --- a/arch/avr32/kernel/time.c +++ b/arch/avr32/kernel/time.c @@ -80,7 +80,7 @@ static int comparator_next_event(unsigned long delta, return 0; }
-static void comparator_mode(enum clock_event_mode mode, +static int comparator_mode(enum clock_event_mode mode, struct clock_event_device *evdev) { switch (mode) { @@ -108,8 +108,9 @@ static void comparator_mode(enum clock_event_mode mode, } break; default: - BUG(); + return -ENOSYS; } + return 0; }
static struct clock_event_device comparator = { @@ -118,7 +119,7 @@ static struct clock_event_device comparator = { .shift = 16, .rating = 50, .set_next_event = comparator_next_event, - .set_mode = comparator_mode, + .set_dev_mode = comparator_mode, };
void read_persistent_clock(struct timespec *ts) diff --git a/arch/blackfin/kernel/time-ts.c b/arch/blackfin/kernel/time-ts.c index cb0a484..b1592a1 100644 --- a/arch/blackfin/kernel/time-ts.c +++ b/arch/blackfin/kernel/time-ts.c @@ -136,7 +136,7 @@ static int bfin_gptmr0_set_next_event(unsigned long cycles, return 0; }
-static void bfin_gptmr0_set_mode(enum clock_event_mode mode, +static int bfin_gptmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { switch (mode) { @@ -173,7 +173,10 @@ static void bfin_gptmr0_set_mode(enum clock_event_mode mode, break; case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
static void bfin_gptmr0_ack(void) @@ -217,7 +220,7 @@ static struct clock_event_device clockevent_gptmr0 = { .shift = 32, .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .set_next_event = bfin_gptmr0_set_next_event, - .set_mode = bfin_gptmr0_set_mode, + .set_dev_mode = bfin_gptmr0_set_mode, };
static void __init bfin_gptmr0_clockevent_init(struct clock_event_device *evt) @@ -250,7 +253,7 @@ static int bfin_coretmr_set_next_event(unsigned long cycles, return 0; }
-static void bfin_coretmr_set_mode(enum clock_event_mode mode, +static int bfin_coretmr_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { switch (mode) { @@ -279,7 +282,10 @@ static void bfin_coretmr_set_mode(enum clock_event_mode mode, break; case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
void bfin_coretmr_init(void) @@ -335,7 +341,7 @@ void bfin_coretmr_clockevent_init(void) evt->shift = 32; evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; evt->set_next_event = bfin_coretmr_set_next_event; - evt->set_mode = bfin_coretmr_set_mode; + evt->set_dev_mode = bfin_coretmr_set_mode;
clock_tick = get_cclk() / TIME_SCALE; evt->mult = div_sc(clock_tick, NSEC_PER_SEC, evt->shift); diff --git a/arch/c6x/platforms/timer64.c b/arch/c6x/platforms/timer64.c index 3c73d74..3eef8fb 100644 --- a/arch/c6x/platforms/timer64.c +++ b/arch/c6x/platforms/timer64.c @@ -126,7 +126,7 @@ static int next_event(unsigned long delta, return 0; }
-static void set_clock_mode(enum clock_event_mode mode, +static int set_clock_mode(enum clock_event_mode mode, struct clock_event_device *evt) { switch (mode) { @@ -146,14 +146,17 @@ static void set_clock_mode(enum clock_event_mode mode, break; case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
static struct clock_event_device t64_clockevent_device = { .name = "TIMER64_EVT32_TIMER", .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, .rating = 200, - .set_mode = set_clock_mode, + .set_dev_mode = set_clock_mode, .set_next_event = next_event, };
diff --git a/arch/hexagon/kernel/time.c b/arch/hexagon/kernel/time.c index 17fbf45..540b138 100644 --- a/arch/hexagon/kernel/time.c +++ b/arch/hexagon/kernel/time.c @@ -100,15 +100,20 @@ static int set_next_event(unsigned long delta, struct clock_event_device *evt) /* * Sets the mode (periodic, shutdown, oneshot, etc) of a timer. */ -static void set_mode(enum clock_event_mode mode, +static int set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { switch (mode) { case CLOCK_EVT_MODE_SHUTDOWN: /* XXX implement me */ - default: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
#ifdef CONFIG_SMP @@ -125,7 +130,7 @@ static struct clock_event_device hexagon_clockevent_dev = { .rating = 400, .irq = RTOS_TIMER_INT, .set_next_event = set_next_event, - .set_mode = set_mode, + .set_dev_mode = set_mode, #ifdef CONFIG_SMP .broadcast = broadcast, #endif diff --git a/arch/m68k/platform/coldfire/pit.c b/arch/m68k/platform/coldfire/pit.c index 493b311..993561a 100644 --- a/arch/m68k/platform/coldfire/pit.c +++ b/arch/m68k/platform/coldfire/pit.c @@ -42,7 +42,7 @@ static u32 pit_cnt; * This is also called after resume to bring the PIT into operation again. */
-static void init_cf_pit_timer(enum clock_event_mode mode, +static int init_cf_pit_timer(enum clock_event_mode mode, struct clock_event_device *evt) { switch (mode) { @@ -72,7 +72,10 @@ static void init_cf_pit_timer(enum clock_event_mode mode, case CLOCK_EVT_MODE_RESUME: /* Nothing to do here */ break; + default: + return -ENOSYS; } + return 0; }
/* @@ -90,7 +93,7 @@ static int cf_pit_next_event(unsigned long delta, struct clock_event_device cf_pit_clockevent = { .name = "pit", .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_mode = init_cf_pit_timer, + .set_dev_mode = init_cf_pit_timer, .set_next_event = cf_pit_next_event, .shift = 32, .irq = MCF_IRQ_PIT1, diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c index dd96f0e..21c17db 100644 --- a/arch/microblaze/kernel/timer.c +++ b/arch/microblaze/kernel/timer.c @@ -121,7 +121,7 @@ static int xilinx_timer_set_next_event(unsigned long delta, return 0; }
-static void xilinx_timer_set_mode(enum clock_event_mode mode, +static int xilinx_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { switch (mode) { @@ -142,7 +142,10 @@ static void xilinx_timer_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_RESUME: pr_info("%s: resume\n", __func__); break; + default: + return -ENOSYS; } + return 0; }
static struct clock_event_device clockevent_xilinx_timer = { @@ -151,7 +154,7 @@ static struct clock_event_device clockevent_xilinx_timer = { .shift = 8, .rating = 300, .set_next_event = xilinx_timer_set_next_event, - .set_mode = xilinx_timer_set_mode, + .set_dev_mode = xilinx_timer_set_mode, };
static inline void timer_ack(void) diff --git a/arch/mn10300/kernel/cevt-mn10300.c b/arch/mn10300/kernel/cevt-mn10300.c index 60f64ca..668906a 100644 --- a/arch/mn10300/kernel/cevt-mn10300.c +++ b/arch/mn10300/kernel/cevt-mn10300.c @@ -41,10 +41,20 @@ static int next_event(unsigned long delta, return 0; }
-static void set_clock_mode(enum clock_event_mode mode, +static int set_clock_mode(enum clock_event_mode mode, struct clock_event_device *evt) { + switch (mode) { + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: /* Nothing to do ... */ + break; + default: + return -ENOSYS; + } + return 0; }
static DEFINE_PER_CPU(struct clock_event_device, mn10300_clockevent_device); @@ -108,7 +118,7 @@ int __init init_clockevents(void)
cd->rating = 200; cd->cpumask = cpumask_of(smp_processor_id()); - cd->set_mode = set_clock_mode; + cd->set_dev_mode = set_clock_mode; cd->event_handler = event_handler; cd->set_next_event = next_event;
diff --git a/arch/openrisc/kernel/time.c b/arch/openrisc/kernel/time.c index 7c52e94..024bc1f 100644 --- a/arch/openrisc/kernel/time.c +++ b/arch/openrisc/kernel/time.c @@ -48,7 +48,7 @@ static int openrisc_timer_set_next_event(unsigned long delta, return 0; }
-static void openrisc_timer_set_mode(enum clock_event_mode mode, +static int openrisc_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { switch (mode) { @@ -68,7 +68,10 @@ static void openrisc_timer_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_RESUME: pr_debug(KERN_INFO "%s: resume\n", __func__); break; + default: + return -ENOSYS; } + return 0; }
/* This is the clock event device based on the OR1K tick timer. @@ -82,7 +85,7 @@ static struct clock_event_device clockevent_openrisc_timer = { .features = CLOCK_EVT_FEAT_ONESHOT, .rating = 300, .set_next_event = openrisc_timer_set_next_event, - .set_mode = openrisc_timer_set_mode, + .set_dev_mode = openrisc_timer_set_mode, };
static inline void timer_ack(void) diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 122a580..a6be92c 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -98,7 +98,7 @@ static struct clocksource clocksource_timebase = {
static int decrementer_set_next_event(unsigned long evt, struct clock_event_device *dev); -static void decrementer_set_mode(enum clock_event_mode mode, +static int decrementer_set_mode(enum clock_event_mode mode, struct clock_event_device *dev);
struct clock_event_device decrementer_clockevent = { @@ -106,7 +106,7 @@ struct clock_event_device decrementer_clockevent = { .rating = 200, .irq = 0, .set_next_event = decrementer_set_next_event, - .set_mode = decrementer_set_mode, + .set_dev_mode = decrementer_set_mode, .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP, }; EXPORT_SYMBOL(decrementer_clockevent); @@ -826,11 +826,21 @@ static int decrementer_set_next_event(unsigned long evt, return 0; }
-static void decrementer_set_mode(enum clock_event_mode mode, +static int decrementer_set_mode(enum clock_event_mode mode, struct clock_event_device *dev) { - if (mode != CLOCK_EVT_MODE_ONESHOT) + switch (mode) { + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: decrementer_set_next_event(DECREMENTER_MAX, dev); + break; + case CLOCK_EVT_MODE_ONESHOT: + break; + default: + return -ENOSYS; + } + return 0; }
/* Interrupt handler for the timer broadcast IPI */ diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 386d37a..49e3812 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -116,9 +116,19 @@ static int s390_next_event(unsigned long delta, return 0; }
-static void s390_set_mode(enum clock_event_mode mode, +static int s390_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { + switch (mode) { + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: + break; + default: + return -ENOSYS; + } + return 0; }
/* @@ -144,7 +154,7 @@ void init_cpu_timer(void) cd->rating = 400; cd->cpumask = cpumask_of(cpu); cd->set_next_event = s390_next_event; - cd->set_mode = s390_set_mode; + cd->set_dev_mode = s390_set_mode;
clockevents_register_device(cd);
diff --git a/arch/score/kernel/time.c b/arch/score/kernel/time.c index f0a43aff..e573b60 100644 --- a/arch/score/kernel/time.c +++ b/arch/score/kernel/time.c @@ -55,7 +55,7 @@ static int score_timer_set_next_event(unsigned long delta, return 0; }
-static void score_timer_set_mode(enum clock_event_mode mode, +static int score_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *evdev) { switch (mode) { @@ -70,8 +70,9 @@ static void score_timer_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_UNUSED: break; default: - BUG(); + return -ENOSYS; } + return 0; }
static struct clock_event_device score_clockevent = { @@ -79,7 +80,7 @@ static struct clock_event_device score_clockevent = { .features = CLOCK_EVT_FEAT_PERIODIC, .shift = 16, .set_next_event = score_timer_set_next_event, - .set_mode = score_timer_set_mode, + .set_dev_mode = score_timer_set_mode, };
void __init time_init(void) diff --git a/arch/sh/kernel/localtimer.c b/arch/sh/kernel/localtimer.c index 8bfc6df..7d48435 100644 --- a/arch/sh/kernel/localtimer.c +++ b/arch/sh/kernel/localtimer.c @@ -39,9 +39,20 @@ void local_timer_interrupt(void) irq_exit(); }
-static void dummy_timer_set_mode(enum clock_event_mode mode, +static int dummy_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *clk) { + switch (mode) { + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_PERIODIC: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: + break; + default: + return -ENOSYS; + } + return 0; }
void local_timer_setup(unsigned int cpu) @@ -54,7 +65,7 @@ void local_timer_setup(unsigned int cpu) CLOCK_EVT_FEAT_DUMMY; clk->rating = 400; clk->mult = 1; - clk->set_mode = dummy_timer_set_mode; + clk->set_dev_mode = dummy_timer_set_mode; clk->broadcast = smp_timer_broadcast; clk->cpumask = cpumask_of(cpu);
diff --git a/arch/tile/kernel/time.c b/arch/tile/kernel/time.c index 462dcd0..40d532b 100644 --- a/arch/tile/kernel/time.c +++ b/arch/tile/kernel/time.c @@ -140,10 +140,20 @@ static int tile_timer_set_next_event(unsigned long ticks, * Whenever anyone tries to change modes, we just mask interrupts * and wait for the next event to get set. */ -static void tile_timer_set_mode(enum clock_event_mode mode, +static int tile_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { - arch_local_irq_mask_now(INT_TILE_TIMER); + switch (mode) { + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: + arch_local_irq_mask_now(INT_TILE_TIMER); + break; + default: + return -ENOSYS; + } + return 0; }
/* @@ -157,7 +167,7 @@ static DEFINE_PER_CPU(struct clock_event_device, tile_timer) = { .rating = 100, .irq = -1, .set_next_event = tile_timer_set_next_event, - .set_mode = tile_timer_set_mode, + .set_dev_mode = tile_timer_set_mode, };
void setup_tile_timer(void) diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index 117568d..fdcd4eb 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c @@ -22,7 +22,7 @@ void timer_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) local_irq_restore(flags); }
-static void itimer_set_mode(enum clock_event_mode mode, +static int itimer_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { switch (mode) { @@ -38,7 +38,10 @@ static void itimer_set_mode(enum clock_event_mode mode,
case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
static int itimer_next_event(unsigned long delta, @@ -52,7 +55,7 @@ static struct clock_event_device itimer_clockevent = { .rating = 250, .cpumask = cpu_all_mask, .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_mode = itimer_set_mode, + .set_dev_mode = itimer_set_mode, .set_next_event = itimer_next_event, .shift = 32, .irq = 0, diff --git a/arch/unicore32/kernel/time.c b/arch/unicore32/kernel/time.c index d3824b2..2a3f4c3 100644 --- a/arch/unicore32/kernel/time.c +++ b/arch/unicore32/kernel/time.c @@ -46,7 +46,7 @@ puv3_osmr0_set_next_event(unsigned long delta, struct clock_event_device *c) return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0; }
-static void +static int puv3_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *c) { switch (mode) { @@ -60,7 +60,10 @@ puv3_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *c) case CLOCK_EVT_MODE_RESUME: case CLOCK_EVT_MODE_PERIODIC: break; + default: + return -ENOSYS; } + return 0; }
static struct clock_event_device ckevt_puv3_osmr0 = { @@ -68,7 +71,7 @@ static struct clock_event_device ckevt_puv3_osmr0 = { .features = CLOCK_EVT_FEAT_ONESHOT, .rating = 200, .set_next_event = puv3_osmr0_set_next_event, - .set_mode = puv3_osmr0_set_mode, + .set_dev_mode = puv3_osmr0_set_mode, };
static cycle_t puv3_read_oscr(struct clocksource *cs) diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index 2a1823d..529f060 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c @@ -52,7 +52,7 @@ static struct clocksource ccount_clocksource = {
static int ccount_timer_set_next_event(unsigned long delta, struct clock_event_device *dev); -static void ccount_timer_set_mode(enum clock_event_mode mode, +static int ccount_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *evt); struct ccount_timer { struct clock_event_device evt; @@ -77,7 +77,7 @@ static int ccount_timer_set_next_event(unsigned long delta, return ret; }
-static void ccount_timer_set_mode(enum clock_event_mode mode, +static int ccount_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { struct ccount_timer *timer = @@ -104,8 +104,9 @@ static void ccount_timer_set_mode(enum clock_event_mode mode, timer->irq_enabled = 1; } default: - break; + return -ENOSYS; } + return 0; }
static irqreturn_t timer_interrupt(int irq, void *dev_id); @@ -126,7 +127,7 @@ void local_timer_setup(unsigned cpu) clockevent->features = CLOCK_EVT_FEAT_ONESHOT; clockevent->rating = 300; clockevent->set_next_event = ccount_timer_set_next_event; - clockevent->set_mode = ccount_timer_set_mode; + clockevent->set_dev_mode = ccount_timer_set_mode; clockevent->cpumask = cpumask_of(cpu); clockevent->irq = irq_create_mapping(NULL, LINUX_TIMER_INT); if (WARN(!clockevent->irq, "error: can't map timer irq")) diff --git a/kernel/time/tick-broadcast-hrtimer.c b/kernel/time/tick-broadcast-hrtimer.c index eb682d5..de2e5e2 100644 --- a/kernel/time/tick-broadcast-hrtimer.c +++ b/kernel/time/tick-broadcast-hrtimer.c @@ -18,7 +18,7 @@
static struct hrtimer bctimer;
-static void bc_set_mode(enum clock_event_mode mode, +static int bc_set_mode(enum clock_event_mode mode, struct clock_event_device *bc) { switch (mode) { @@ -38,9 +38,14 @@ static void bc_set_mode(enum clock_event_mode mode, */ hrtimer_try_to_cancel(&bctimer); break; - default: + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_RESUME: break; + default: + return -ENOSYS; } + return 0; }
/* @@ -72,7 +77,7 @@ static int bc_set_next(ktime_t expires, struct clock_event_device *bc) }
static struct clock_event_device ce_broadcast_hrtimer = { - .set_mode = bc_set_mode, + .set_dev_mode = bc_set_mode, .set_next_ktime = bc_set_next, .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_KTIME |
All clockevent drivers are migrated to use the new callback ->set_dev_mode(). Get rid of the deprecated ->dev_mode() callback now.
Signed-off-by: Viresh Kumar viresh.kumar@linaro.org --- include/linux/clockchips.h | 3 --- kernel/time/clockevents.c | 16 ++++------------ kernel/time/timer_list.c | 5 +---- 3 files changed, 5 insertions(+), 19 deletions(-)
diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h index 8ab1a86..08b203e 100644 --- a/include/linux/clockchips.h +++ b/include/linux/clockchips.h @@ -82,7 +82,6 @@ enum clock_event_mode { * @features: features * @retries: number of forced programming retries * @set_dev_mode: set dev mode function - * @set_mode: set mode function (deprecated, use set_dev_mode instead) * @broadcast: function to broadcast events * @min_delta_ticks: minimum delta value in ticks stored for reconfiguration * @max_delta_ticks: maximum delta value in ticks stored for reconfiguration @@ -112,8 +111,6 @@ struct clock_event_device { void (*broadcast)(const struct cpumask *mask); int (*set_dev_mode)(enum clock_event_mode mode, struct clock_event_device *); - void (*set_mode)(enum clock_event_mode mode, - struct clock_event_device *); void (*suspend)(struct clock_event_device *); void (*resume)(struct clock_event_device *); unsigned long min_delta_ticks; diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index c9bef22..d911839 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -106,10 +106,7 @@ void clockevents_set_mode(struct clock_event_device *dev, { if (dev->mode != mode) { /* WARN_ON? Currently available modes shouldn't fail */ - if (dev->set_dev_mode) - WARN_ON_ONCE(dev->set_dev_mode(mode, dev)); - else - dev->set_mode(mode, dev); + WARN_ON_ONCE(dev->set_dev_mode(mode, dev));
dev->mode = mode;
@@ -451,14 +448,9 @@ int __clockevents_update_freq(struct clock_event_device *dev, u32 freq) if (dev->mode == CLOCK_EVT_MODE_ONESHOT) return clockevents_program_event(dev, dev->next_event, false);
- if (dev->mode == CLOCK_EVT_MODE_PERIODIC) { - /* WARN_ON? Shouldn't fail while setting PERIODIC MODE */ - if (dev->set_dev_mode) - WARN_ON_ONCE(dev->set_dev_mode(CLOCK_EVT_MODE_PERIODIC, - dev)); - else - dev->set_mode(CLOCK_EVT_MODE_PERIODIC, dev); - } + /* WARN_ON? Shouldn't fail while setting PERIODIC MODE */ + if (dev->mode == CLOCK_EVT_MODE_PERIODIC) + WARN_ON_ONCE(dev->set_dev_mode(CLOCK_EVT_MODE_PERIODIC, dev));
return 0; } diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c index 957a049..8e43c9f 100644 --- a/kernel/time/timer_list.c +++ b/kernel/time/timer_list.c @@ -229,10 +229,7 @@ print_tickdevice(struct seq_file *m, struct tick_device *td, int cpu) SEQ_printf(m, "\n");
SEQ_printf(m, " set_mode: "); - if (dev->set_dev_mode) - print_name_offset(m, dev->set_dev_mode); - else - print_name_offset(m, dev->set_mode); + print_name_offset(m, dev->set_dev_mode); SEQ_printf(m, "\n");
SEQ_printf(m, " event_handler: ");
On 06/02/2014 08:33 PM, Viresh Kumar wrote:
Hi,
Here goes the fourth version and its very much light weight compared to earlier versions. I hope I haven't missed any review comments here :)
More or less all patches are updated to get rid of all unrelated changes, like removing unsupported modes OR not disabling events for default cases..
So, please review them again :)
Here goes the mainline version of cover-letter:
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
You might want to remove the brackets around "on expires == KTIME_MAX". Its quite a while since we mentioned that this is the case we are solving, so best to mention it as a part of the main sentence.
clockevent device, this can be a fake 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.
With this proposal, introducing a new ONESHOT_STOPPED mode would require the core to know whether the platform implements this mode so it could be reprogrammed later.
The core would need to know if the platform implements this mode so as to warn the callers if the mode is not implemented. They can take appropriate actions then. We will be handling the ONESHOT_STOPPED devices in the same way whether the platform implements this mode or not right? In either case we would need to reprogram the clock devices when necessary.
Regards Preeti U Murthy
On 4 June 2014 13:02, Preeti U Murthy preeti@linux.vnet.ibm.com wrote:
You might want to remove the brackets around "on expires == KTIME_MAX". Its quite a while since we mentioned that this is the case we are solving, so best to mention it as a part of the main sentence.
Okay.
clockevent device, this can be a fake 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.
With this proposal, introducing a new ONESHOT_STOPPED mode would require the core to know whether the platform implements this mode so it could be reprogrammed later.
The core would need to know if the platform implements this mode so as to warn the callers if the mode is not implemented.
No, this mode is optional. Core would need to reconfigure ONESHOT mode later if ONESHOT_STOPPED has happened.
We will be handling the ONESHOT_STOPPED devices in the same way whether the platform implements this mode or not right? In either case we would need to reprogram the clock devices when necessary.
We would need to reprogram the next event later but mode will be required to be reconfigured if mode is changed to ONESHOT_STOPPED earlier.
-- viresh
linaro-kernel@lists.linaro.org