Hi,
Here goes the fifth 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..
V4->V5: don't change behavior of 'default case' apart from returning error, it must behave exactly in the same way as it was doing earlier.
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 | 31 ++++++++++++++++++--- arch/arc/kernel/time.c | 11 +++++--- arch/arm/common/timer-sp.c | 10 ++++--- arch/arm/kernel/smp_twd.c | 11 +++++--- arch/arm/mach-at91/at91rm9200_time.c | 9 +++++-- arch/arm/mach-at91/at91sam926x_time.c | 8 ++++-- arch/arm/mach-clps711x/common.c | 7 +++-- arch/arm/mach-cns3xxx/core.c | 12 ++++++--- 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 | 9 ++++--- 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 | 9 ++++--- 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 | 8 ++++-- arch/arm/plat-iop/time.c | 9 ++++--- 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 | 10 +++++-- 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 | 9 +++++-- arch/mips/ralink/cevt-rt3352.c | 12 ++++++--- 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 | 20 +++++++++++--- arch/s390/kernel/time.c | 14 ++++++++-- arch/score/kernel/time.c | 7 ++--- arch/sh/kernel/localtimer.c | 15 +++++++++-- arch/sparc/kernel/time_32.c | 20 +++++++++----- arch/sparc/kernel/time_64.c | 7 +++-- arch/tile/kernel/time.c | 15 +++++++++-- 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 | 12 ++++++--- 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 | 10 ++++--- drivers/clocksource/mxs_timer.c | 7 +++-- drivers/clocksource/nomadik-mtu.c | 7 +++-- drivers/clocksource/qcom-timer.c | 10 ++++--- 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 | 11 +++++--- 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 | 19 ++++++++++--- drivers/clocksource/timer-keystone.c | 9 ++++--- drivers/clocksource/timer-marco.c | 12 ++++++--- drivers/clocksource/timer-prima2.c | 7 +++-- drivers/clocksource/timer-sun5i.c | 11 +++++--- 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, 783 insertions(+), 305 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: ");
Looks like you did another unintentional reply-to-me only :), cc'ing others again..
On 3 June 2014 01:53, Kevin Hilman khilman@linaro.org wrote:
Viresh Kumar viresh.kumar@linaro.org writes:
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 */
nit: Why the WARN_ON and '?' in the comment?
@@ -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 */
and here?
I tried to write both question and answer in the same line :) WARN_ON ?, i.e. why do we have WARN_ON_ONCE() here? Answer: Shouldn't fail while setting PERIODIC MODE
Let me know how should I write it to make it more clear. Maybe jus:
/* Shouldn't fail while setting PERIODIC MODE */
On 2 June 2014 23:49, Viresh Kumar viresh.kumar@linaro.org wrote:
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);
I was looking to do this modification here to add some debugging prints as well. Please see if it makes sense:
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index c9bef22..5b85ac8 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -105,11 +105,14 @@ void clockevents_set_mode(struct clock_event_device *dev, enum clock_event_mode mode) { 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 + if (dev->set_dev_mode) { + int ret = dev->set_dev_mode(mode, dev); + + /* Currently available modes shouldn't fail */ + WARN_ONCE(ret, "Requested mode: %d, error: %d\n", mode, ret); + } else { dev->set_mode(mode, dev); + }
dev->mode = mode;
On 06/04/2014 01:33 PM, Viresh Kumar wrote:
On 2 June 2014 23:49, Viresh Kumar viresh.kumar@linaro.org wrote:
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);
I was looking to do this modification here to add some debugging prints as well. Please see if it makes sense:
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index c9bef22..5b85ac8 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -105,11 +105,14 @@ void clockevents_set_mode(struct clock_event_device *dev, enum clock_event_mode mode) { 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
if (dev->set_dev_mode) {
int ret = dev->set_dev_mode(mode, dev);
/* Currently available modes shouldn't fail */
WARN_ONCE(ret, "Requested mode: %d, error:
%d\n", mode, ret);
} else { dev->set_mode(mode, dev);
} dev->mode = mode;
Looks good to me.
Regards Preeti U Murthy
Viresh Kumar viresh.kumar@linaro.org writes:
On 2 June 2014 23:49, Viresh Kumar viresh.kumar@linaro.org wrote:
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);
I was looking to do this modification here to add some debugging prints as well. Please see if it makes sense:
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index c9bef22..5b85ac8 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -105,11 +105,14 @@ void clockevents_set_mode(struct clock_event_device *dev, enum clock_event_mode mode) { 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
if (dev->set_dev_mode) {
int ret = dev->set_dev_mode(mode, dev);
/* Currently available modes shouldn't fail */
WARN_ONCE(ret, "Requested mode: %d, error:
%d\n", mode, ret);
} else { dev->set_mode(mode, dev);
} dev->mode = mode;
Yes, looks good.
Kevin
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 | 10 +++++++--- arch/arm/kernel/smp_twd.c | 11 ++++++++--- arch/arm/mach-at91/at91rm9200_time.c | 9 +++++++-- arch/arm/mach-at91/at91sam926x_time.c | 8 ++++++-- arch/arm/mach-clps711x/common.c | 7 +++++-- arch/arm/mach-cns3xxx/core.c | 12 ++++++++---- 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 | 9 ++++++--- 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 | 9 +++++---- 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 | 8 ++++++-- arch/arm/plat-iop/time.c | 9 ++++++--- arch/arm/plat-orion/time.c | 20 +++++++++++++++----- 26 files changed, 166 insertions(+), 75 deletions(-)
diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c index fd6bff0..bdf6329 100644 --- a/arch/arm/common/timer-sp.c +++ b/arch/arm/common/timer-sp.c @@ -127,10 +127,11 @@ 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; + int ret = 0;
writel(ctrl, clkevt_base + TIMER_CTRL);
@@ -147,11 +148,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: + ret = -ENOSYS; }
writel(ctrl, clkevt_base + TIMER_CTRL); + return ret; }
static int sp804_set_next_event(unsigned long next, @@ -168,7 +172,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..7d30b6e 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -36,10 +36,11 @@ 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; + int ret = 0;
switch (mode) { case CLOCK_EVT_MODE_PERIODIC: @@ -52,13 +53,17 @@ static void twd_set_mode(enum clock_event_mode mode, /* period set, and timer enabled in 'next_event' hook */ ctrl = TWD_TIMER_CONTROL_IT_ENABLE | TWD_TIMER_CONTROL_ONESHOT; break; + default: + ret = -ENOSYS; case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: - default: + case CLOCK_EVT_MODE_RESUME: ctrl = 0; + break; }
writel_relaxed(ctrl, twd_base + TWD_TIMER_CONTROL); + return ret; }
static int twd_set_next_event(unsigned long evt, @@ -296,7 +301,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..01a2dc6 100644 --- a/arch/arm/mach-at91/at91rm9200_time.c +++ b/arch/arm/mach-at91/at91rm9200_time.c @@ -112,9 +112,11 @@ 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) { + int ret = 0; + /* Disable and flush pending timer interrupts */ at91_st_write(AT91_ST_IDR, AT91_ST_PITS | AT91_ST_ALMS); at91_st_read(AT91_ST_SR); @@ -138,8 +140,11 @@ clkevt32k_mode(enum clock_event_mode mode, struct clock_event_device *dev) case CLOCK_EVT_MODE_RESUME: irqmask = 0; break; + default: + ret = -ENOSYS; } at91_st_write(AT91_ST_IER, irqmask); + return ret; }
static int @@ -177,7 +182,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..aea2855 100644 --- a/arch/arm/mach-cns3xxx/core.c +++ b/arch/arm/mach-cns3xxx/core.c @@ -113,12 +113,12 @@ 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); int pclk = cns3xxx_cpu_clock() / 8; - int reload; + int reload, ret = 0;
switch (mode) { case CLOCK_EVT_MODE_PERIODIC: @@ -130,13 +130,17 @@ static void cns3xxx_timer_set_mode(enum clock_event_mode mode, /* period set, and timer enabled in 'next_event' hook */ ctrl |= (1 << 2) | (1 << 9); break; + default: + ret = -ENOSYS; case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: - default: + case CLOCK_EVT_MODE_RESUME: ctrl = 0; + break; }
writel(ctrl, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET); + return ret; }
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..b9c3455 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -521,11 +521,12 @@ 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; unsigned long osrt = *IXP4XX_OSRT1 & ~IXP4XX_OST_RELOAD_MASK; + int ret = 0;
switch (mode) { case CLOCK_EVT_MODE_PERIODIC: @@ -543,20 +544,22 @@ static void ixp4xx_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_RESUME: opts |= IXP4XX_OST_ENABLE; break; - case CLOCK_EVT_MODE_UNUSED: default: + ret = -ENOSYS; + case CLOCK_EVT_MODE_UNUSED: osrt = opts = 0; break; }
*IXP4XX_OSRT1 = osrt | opts; + return ret; }
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..0cca71c 100644 --- a/arch/arm/mach-netx/time.c +++ b/arch/arm/mach-netx/time.c @@ -34,10 +34,11 @@ #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; + int ret = 0;
/* disable timer */ writel(0, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKEVENT)); @@ -57,9 +58,8 @@ static void netx_set_mode(enum clock_event_mode mode, break;
default: - WARN(1, "%s: unhandled mode %d\n", __func__, mode); + ret = -ENOSYS; /* fall through */ - case CLOCK_EVT_MODE_SHUTDOWN: case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_RESUME: @@ -68,6 +68,7 @@ static void netx_set_mode(enum clock_event_mode mode, }
writel(tmode, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKEVENT)); + return ret; }
static int netx_set_next_event(unsigned long evt, @@ -81,7 +82,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..4702060 100644 --- a/arch/arm/mach-w90x900/time.c +++ b/arch/arm/mach-w90x900/time.c @@ -48,10 +48,11 @@
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; + int ret = 0;
val = __raw_readl(REG_TCSR0); val &= ~(0x03 << 27); @@ -70,9 +71,12 @@ static void nuc900_clockevent_setmode(enum clock_event_mode mode, case CLOCK_EVT_MODE_SHUTDOWN: case CLOCK_EVT_MODE_RESUME: break; + default: + ret = -ENOSYS; }
__raw_writel(val, REG_TCSR0); + return ret; }
static int nuc900_clockevent_setnextevent(unsigned long evt, @@ -92,7 +96,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..53d27da 100644 --- a/arch/arm/plat-iop/time.c +++ b/arch/arm/plat-iop/time.c @@ -77,10 +77,11 @@ 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(); + int ret = 0;
switch (mode) { case CLOCK_EVT_MODE_PERIODIC: @@ -96,14 +97,16 @@ static void iop_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_RESUME: tmr |= IOP_TMR_EN; break; + default: + ret = -ENOSYS; case CLOCK_EVT_MODE_SHUTDOWN: case CLOCK_EVT_MODE_UNUSED: - default: tmr &= ~IOP_TMR_EN; break; }
write_tmr0(tmr); + return ret; }
static struct clock_event_device iop_clockevent = { @@ -111,7 +114,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..987c49f 100644 --- a/arch/arm/plat-orion/time.c +++ b/arch/arm/plat-orion/time.c @@ -106,14 +106,16 @@ 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; + int ret = 0; 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 +134,14 @@ 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; + + default: + ret = -ENOSYS; + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: /* * Disable timer. */ @@ -149,9 +158,10 @@ 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; } local_irq_restore(flags); + return ret; }
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)
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 | 10 ++++++++-- 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 | 9 +++++++-- arch/mips/ralink/cevt-rt3352.c | 12 ++++++++---- arch/mips/sgi-ip27/ip27-timer.c | 14 ++++++++++++-- arch/mips/sni/time.c | 7 +++++-- 16 files changed, 122 insertions(+), 36 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..db58c38 100644 --- a/arch/mips/kernel/cevt-ds1287.c +++ b/arch/mips/kernel/cevt-ds1287.c @@ -59,10 +59,11 @@ 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; + int ret = 0;
spin_lock(&rtc_lock);
@@ -73,6 +74,10 @@ static void ds1287_set_mode(enum clock_event_mode mode, val |= RTC_PIE; break; default: + ret = -ENOSYS; + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: val &= ~RTC_PIE; break; } @@ -80,6 +85,7 @@ static void ds1287_set_mode(enum clock_event_mode mode, CMOS_WRITE(val, RTC_REG_B);
spin_unlock(&rtc_lock); + return ret; }
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..664c007 100644 --- a/arch/mips/kernel/cevt-gt641xx.c +++ b/arch/mips/kernel/cevt-gt641xx.c @@ -64,10 +64,11 @@ 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; + int ret = 0;
raw_spin_lock(>641xx_timer_lock);
@@ -81,13 +82,18 @@ 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: + ret = -ENOSYS; }
GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
raw_spin_unlock(>641xx_timer_lock); + return ret; }
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..9f7b474 100644 --- a/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c +++ b/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c @@ -52,9 +52,11 @@ 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) { + int ret = 0; + spin_lock(&mfgpt_lock);
switch (mode) { @@ -78,14 +80,17 @@ static void init_mfgpt_timer(enum clock_event_mode mode, case CLOCK_EVT_MODE_RESUME: /* Nothing to do here */ break; + default: + ret = -ENOSYS; } spin_unlock(&mfgpt_lock); + return ret; }
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..18128f7 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,14 @@ static void systick_set_clock_mode(enum clock_event_mode mode, iowrite32(0, systick.membase + SYSTICK_CONFIG); break;
- default: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_RESUME: pr_err("%s: Unhandeled mips clock_mode\n", systick.dev.name); 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 | 20 ++++++++++++++------ arch/sparc/kernel/time_64.c | 7 +++++-- 2 files changed, 19 insertions(+), 8 deletions(-)
diff --git a/arch/sparc/kernel/time_32.c b/arch/sparc/kernel/time_32.c index c4c27b0..0a68117 100644 --- a/arch/sparc/kernel/time_32.c +++ b/arch/sparc/kernel/time_32.c @@ -107,9 +107,11 @@ 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) { + int ret = 0; + switch (mode) { case CLOCK_EVT_MODE_PERIODIC: case CLOCK_EVT_MODE_RESUME: @@ -118,10 +120,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: + ret = -ENOSYS; } smp_mb(); + return ret; }
static __init void setup_timer_ce(void) @@ -133,7 +138,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 +198,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 +213,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 +242,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 | 12 ++++++++--- 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 | 10 ++++++--- drivers/clocksource/mxs_timer.c | 7 +++++-- drivers/clocksource/nomadik-mtu.c | 7 +++++-- drivers/clocksource/qcom-timer.c | 10 ++++++--- 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 | 11 +++++++--- 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 | 19 +++++++++++++---- drivers/clocksource/timer-keystone.c | 9 +++++--- drivers/clocksource/timer-marco.c | 12 ++++++++--- drivers/clocksource/timer-prima2.c | 7 +++++-- drivers/clocksource/timer-sun5i.c | 11 +++++++--- 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, 260 insertions(+), 109 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..a79c348 100644 --- a/drivers/clocksource/bcm_kona_timer.c +++ b/drivers/clocksource/bcm_kona_timer.c @@ -128,25 +128,31 @@ 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) { + int ret = 0; + switch (mode) { case CLOCK_EVT_MODE_ONESHOT: /* by default mode is one shot don't do any thing */ break; + default: + ret = -ENOSYS; 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; } + return ret; }
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..5c3ed02 100644 --- a/drivers/clocksource/moxart_timer.c +++ b/drivers/clocksource/moxart_timer.c @@ -58,9 +58,11 @@ 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) { + int ret = 0; + switch (mode) { case CLOCK_EVT_MODE_RESUME: case CLOCK_EVT_MODE_ONESHOT: @@ -71,12 +73,14 @@ static void moxart_clkevt_mode(enum clock_event_mode mode, writel(clock_count_per_tick, base + TIMER1_BASE + REG_LOAD); writel(TIMER1_ENABLE, base + TIMER_CR); break; + default: + ret = -ENOSYS; case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: - default: writel(TIMER1_DISABLE, base + TIMER_CR); break; } + return ret; }
static int moxart_clkevt_next_event(unsigned long cycles, @@ -98,7 +102,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..cbf9d2e 100644 --- a/drivers/clocksource/qcom-timer.c +++ b/drivers/clocksource/qcom-timer.c @@ -75,10 +75,11 @@ 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; + int ret = 0;
ctrl = readl_relaxed(event_base + TIMER_ENABLE); ctrl &= ~(TIMER_ENABLE_EN | TIMER_ENABLE_CLR_ON_MATCH_EN); @@ -93,8 +94,11 @@ static void msm_timer_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: break; + default: + ret = -ENOSYS; } writel_relaxed(ctrl, event_base + TIMER_ENABLE); + return ret; }
static struct clock_event_device __percpu *msm_evt; @@ -126,7 +130,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 +151,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..33f4d7c 100644 --- a/drivers/clocksource/sun4i_timer.c +++ b/drivers/clocksource/sun4i_timer.c @@ -81,9 +81,11 @@ 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) { + int ret = 0; + switch (mode) { case CLOCK_EVT_MODE_PERIODIC: sun4i_clkevt_time_stop(0); @@ -94,12 +96,15 @@ static void sun4i_clkevt_mode(enum clock_event_mode mode, sun4i_clkevt_time_stop(0); sun4i_clkevt_time_start(0, false); break; + default: + ret = -ENOSYS; case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: - default: + case CLOCK_EVT_MODE_RESUME: sun4i_clkevt_time_stop(0); break; } + return ret; }
static int sun4i_clkevt_next_event(unsigned long evt, @@ -116,7 +121,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..909bf93 100644 --- a/drivers/clocksource/time-armada-370-xp.c +++ b/drivers/clocksource/time-armada-370-xp.c @@ -120,12 +120,14 @@ 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) { + int ret = 0;
+ switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: /* * Setup timer to fire at 1/HZ intervals. */ @@ -136,7 +138,13 @@ armada_370_xp_clkevt_mode(enum clock_event_mode mode, * Enable timer. */ local_timer_ctrl_clrset(0, TIMER0_RELOAD_EN | enable_mask); - } else { + break; + default: + ret = -ENOSYS; + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: /* * Disable timer. */ @@ -146,7 +154,9 @@ 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; } + return ret; }
static int armada_370_xp_clkevt_irq; @@ -184,7 +194,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 +206,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..415d9b0 100644 --- a/drivers/clocksource/time-orion.c +++ b/drivers/clocksource/time-orion.c @@ -60,21 +60,32 @@ 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) { + int ret = 0; + + 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; + default: + ret = -ENOSYS; + 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; } + return ret; }
static struct clock_event_device orion_clkevt = { @@ -83,7 +94,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..ad909ce 100644 --- a/drivers/clocksource/timer-marco.c +++ b/drivers/clocksource/timer-marco.c @@ -114,18 +114,24 @@ 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) { + int ret = 0; + 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; + ret = -ENOSYS; }
sirfsoc_timer_count_disable(smp_processor_id()); + return ret; }
static void sirfsoc_clocksource_suspend(struct clocksource *cs) @@ -190,7 +196,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..96b01d4 100644 --- a/drivers/clocksource/timer-sun5i.c +++ b/drivers/clocksource/timer-sun5i.c @@ -79,9 +79,11 @@ 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) { + int ret = 0; + switch (mode) { case CLOCK_EVT_MODE_PERIODIC: sun5i_clkevt_time_stop(0); @@ -92,12 +94,15 @@ static void sun5i_clkevt_mode(enum clock_event_mode mode, sun5i_clkevt_time_stop(0); sun5i_clkevt_time_start(0, false); break; + default: + ret = -ENOSYS; case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: - default: + case CLOCK_EVT_MODE_RESUME: sun5i_clkevt_time_stop(0); break; } + return ret; }
static int sun5i_clkevt_next_event(unsigned long evt, @@ -114,7 +119,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 | 31 +++++++++++++++++++++++++++---- 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 | 20 ++++++++++++++++---- arch/s390/kernel/time.c | 14 ++++++++++++-- arch/score/kernel/time.c | 7 ++++--- arch/sh/kernel/localtimer.c | 15 +++++++++++++-- arch/tile/kernel/time.c | 15 +++++++++++++-- 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, 169 insertions(+), 52 deletions(-)
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c index ee39cee..bae51cd 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,24 @@ 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: + break; + + default: + return -ENOSYS; + } + return 0; }
static int @@ -197,7 +220,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..a254fd1 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,23 @@ 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) + int ret = 0; + + switch (mode) { + default: + ret = -ENOSYS; + 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; + } + return ret; }
/* 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..d5cc16d 100644 --- a/arch/tile/kernel/time.c +++ b/arch/tile/kernel/time.c @@ -140,10 +140,21 @@ 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: + break; + default: + return -ENOSYS; + } + return 0; }
/* @@ -157,7 +168,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 |
On 06/02/2014 11:50 PM, Viresh Kumar wrote:
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 | 31 +++++++++++++++++++++++++++---- 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 | 20 ++++++++++++++++---- arch/s390/kernel/time.c | 14 ++++++++++++-- arch/score/kernel/time.c | 7 ++++--- arch/sh/kernel/localtimer.c | 15 +++++++++++++-- arch/tile/kernel/time.c | 15 +++++++++++++-- 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, 169 insertions(+), 52 deletions(-)
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 122a580..a254fd1 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,23 @@ 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)
- int ret = 0;
- switch (mode) {
- default:
ret = -ENOSYS;
- 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;
- }
- return ret;
The ordering of the cases and the indentation got messed up here?
For the powerpc part : Reviewed-by: Preeti U Murthy preeti@linux.vnet.ibm.com
On 4 June 2014 14:51, Preeti U Murthy preeti@linux.vnet.ibm.com wrote:
-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)
int ret = 0;
switch (mode) {
default:
ret = -ENOSYS;
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;
}
return ret;
The ordering of the cases and the indentation got messed up here?
No, what looked awkward to you ?
On 06/04/2014 02:58 PM, Viresh Kumar wrote:
On 4 June 2014 14:51, Preeti U Murthy preeti@linux.vnet.ibm.com wrote:
-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)
int ret = 0;
switch (mode) {
default:
ret = -ENOSYS;
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;
}
return ret;
The ordering of the cases and the indentation got messed up here?
No, what looked awkward to you ?
In the above the default case comes first followed by the other cases. This will compile and run fine but this is not a conventional way of writing switch cases right?
Regards Preeti U Murthy
On 4 June 2014 15:35, Preeti U Murthy preeti@linux.vnet.ibm.com wrote:
On 06/04/2014 02:58 PM, Viresh Kumar wrote:
On 4 June 2014 14:51, Preeti U Murthy preeti@linux.vnet.ibm.com wrote:
-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)
int ret = 0;
switch (mode) {
default:
ret = -ENOSYS;
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;
}
return ret;
The ordering of the cases and the indentation got messed up here?
No, what looked awkward to you ?
In the above the default case comes first followed by the other cases. This will compile and run fine but this is not a conventional way of writing switch cases right?
decrementer_set_next_event(DECREMENTER_MAX, dev);
was required to be called for default case as well and so did it this way. Normally we keep default towards the end as it doesn't do anything, but for such cases we can have this implementation to get rid of code redundancy..
-- viresh
On 06/02/2014 11:50 PM, Viresh Kumar wrote:
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 | 31 +++++++++++++++++++++++++++---- 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 | 20 ++++++++++++++++---- arch/s390/kernel/time.c | 14 ++++++++++++-- arch/score/kernel/time.c | 7 ++++--- arch/sh/kernel/localtimer.c | 15 +++++++++++++-- arch/tile/kernel/time.c | 15 +++++++++++++-- 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, 169 insertions(+), 52 deletions(-)
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c index ee39cee..bae51cd 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_next_event = rtc_ce_set_next_event, };.set_dev_mode = rtc_ce_set_mode,
@@ -161,12 +172,24 @@ 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:
break;
- default:
return -ENOSYS;
- }
- return 0;
}
static int @@ -197,7 +220,7 @@ init_qemu_clockevent(void) .features = CLOCK_EVT_FEAT_ONESHOT, .rating = 400, .cpumask = cpumask_of(cpu),
.set_mode = qemu_ce_set_mode,
.set_next_event = qemu_ce_set_next_event, };.set_dev_mode = qemu_ce_set_mode,
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..a254fd1 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,23 @@ 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)
- int ret = 0;
- switch (mode) {
- default:
ret = -ENOSYS;
- case CLOCK_EVT_MODE_UNUSED:
- case CLOCK_EVT_MODE_SHUTDOWN:
- case CLOCK_EVT_MODE_RESUME: decrementer_set_next_event(DECREMENTER_MAX, dev);
break;
What about CLOCK_EVT_MODE_PERIODIC? That can come along with the other modes above.
- case CLOCK_EVT_MODE_ONESHOT:
break;
- }
- return ret;
}
Regards Preeti U Murthy
On 4 June 2014 14:55, Preeti U Murthy preeti@linux.vnet.ibm.com wrote:
-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)
int ret = 0;
switch (mode) {
default:
ret = -ENOSYS;
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
case CLOCK_EVT_MODE_RESUME: decrementer_set_next_event(DECREMENTER_MAX, dev);
break;
What about CLOCK_EVT_MODE_PERIODIC? That can come along with the other modes above.
Its not supported by this driver.
On 06/04/2014 03:06 PM, Viresh Kumar wrote:
On 4 June 2014 14:55, Preeti U Murthy preeti@linux.vnet.ibm.com wrote:
-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)
int ret = 0;
switch (mode) {
default:
ret = -ENOSYS;
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
case CLOCK_EVT_MODE_RESUME: decrementer_set_next_event(DECREMENTER_MAX, dev);
break;
What about CLOCK_EVT_MODE_PERIODIC? That can come along with the other modes above.
Its not supported by this driver.
Right, sorry overlooked this.
Regards Preeti U Murthy
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: ");
Viresh Kumar viresh.kumar@linaro.org writes:
Hi,
Here goes the fifth 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..
V4->V5: don't change behavior of 'default case' apart from returning error, it must behave exactly in the same way as it was doing earlier.
Might I suggest you wait a day before sending updated versions and to be sure you've understood and addressed all the comments? You're quickly on a path to burn out reviewers.
I was typing some of the following up in reply to V4 but then noticed you already had a V5, so I'll reply here.
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.
You need to describe why KTIME_MAX is special here. You say "should be stopped" but you don't say why. This needs to be summarized better here.
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.
- 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.
This is very unclear. What is the "issue" and would be the fix?
- 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.
In general, your cover letters and change logs still mix up what things are like currently and what things will be like (or should be like) after this series. Now your adding another layer of adding things that will likely need fix *in addition to* this series. IMO, all three categories are still mixed up in the descriptions.
Kevin
On 3 June 2014 01:51, Kevin Hilman khilman@linaro.org wrote:
Might I suggest you wait a day before sending updated versions and to be sure you've understood and addressed all the comments? You're quickly on a path to burn out reviewers.
Sigh, I have been trying to wait for few days before sending new version since sometime now to avoid that and this time it looked like that was the only comment you had.. Probably got confused when you said, you are stopping review after seeing the default behavior changed :)
I was typing some of the following up in reply to V4 but then noticed you already had a V5, so I'll reply here.
So sorry :(, will re-post only tomorrow now :)
You need to describe why KTIME_MAX is special here. You say "should be stopped" but you don't say why. This needs to be summarized better here.
Hmm, yes you are right..
- 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.
This is very unclear. What is the "issue" and would be the fix?
Will try something better..
- 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.
In general, your cover letters and change logs still mix up what things are like currently and what things will be like (or should be like) after this series. Now your adding another layer of adding things that will likely need fix *in addition to* this series. IMO, all three categories are still mixed up in the descriptions.
I will try to write that again clearly..
On 3 June 2014 01:51, Kevin Hilman khilman@linaro.org wrote:
In general, your cover letters and change logs still mix up what things are like currently and what things will be like (or should be like) after this series. Now your adding another layer of adding things that will likely need fix *in addition to* this series. IMO, all three categories are still mixed up in the descriptions.
Another try :)
A clockevent device is used to service timers and hrtimers requests and the next event (when it should fire) is decided by the timer/hrtimer expiring next. When no timers/hrtimers are pending to be serviced, the expiry time is set to a special value: KTIME_MAX. This means that no events are required for indefinite amount of 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.
At this time the clockevent device can be stopped, or its events can be masked in order to reduce latency added due to these unwanted interrupts (as hrtimer_interrupt() wouldn't have anything to do when called) OR to save some power associated with clockevent device & running extra code to handle these interrupts.
This wouldn't have any side effects of missing events when they are added later, as we will reprogram the next event again then.
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(), it then migrates all drivers one by one to start using it and finally removes existing callback set_mode() when it has no more users.
FIXME: It _might_ be required to fix two issues separately after applying this series:
1. Few drivers have 'switch cases' for ONESHOT or PERIODIC modes, when these modes aren't supported by '.features' field of 'struct clock_event_device'. These drivers are doing WARN/BUG/pr_err/empty/etc for these cases. Its guaranteed that core wouldn't try to set PERIODIC/ONESHOT modes if they aren't specified in .features field for a particular driver. And if this happens due to some bug at driver/core, then we do have proper handling at core level while calling ->set_dev_mode(). Drivers can be simplified by removing code around these unsupported cases and return -ENOSYS from 'default' case.
2. Few clockevent drivers are always disabling clock events from 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 currently available cases separately, but it might be required to fix them before ONESHOT_STOPPED series gets in.
On 06/02/2014 10:21 PM, Kevin Hilman wrote:
Viresh Kumar viresh.kumar@linaro.org writes:
Hi,
Here goes the fifth 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..
V4->V5: don't change behavior of 'default case' apart from returning error, it must behave exactly in the same way as it was doing earlier.
Might I suggest you wait a day before sending updated versions and to be sure you've understood and addressed all the comments? You're quickly on a path to burn out reviewers.
Yeah, really Viresh ... sounds like some of us already told you that.
We have other patchset to review also, if you flood with X versions with your patchset in a small amount of time resulting each time with comments, some of us (like I) will just give up to review and will wait a patchset to stand there without comment during some days before reviewing it. The result will be the opposite at you want: the patches will take more time to be merged.
You can resend a patchset immediately if all the patches are acked and there are a couple of trivial changes (typo or whatever). Otherwise take the time to do your *own* review. Don't "hope" you "haven't missed any review comments here".
I was typing some of the following up in reply to V4 but then noticed you already had a V5, so I'll reply here.
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.
You need to describe why KTIME_MAX is special here. You say "should be stopped" but you don't say why. This needs to be summarized better here.
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.
- 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.
This is very unclear. What is the "issue" and would be the fix?
- 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.
In general, your cover letters and change logs still mix up what things are like currently and what things will be like (or should be like) after this series. Now your adding another layer of adding things that will likely need fix *in addition to* this series. IMO, all three categories are still mixed up in the descriptions.
Kevin
On 3 June 2014 14:26, Daniel Lezcano daniel.lezcano@linaro.org wrote:
Yeah, really Viresh ... sounds like some of us already told you that.
/me nods :)
On 3 June 2014 01:51, Kevin Hilman khilman@linaro.org wrote:
In general, your cover letters and change logs still mix up what things are like currently and what things will be like (or should be like) after this series. Now your adding another layer of adding things that will likely need fix *in addition to* this series. IMO, all three categories are still mixed up in the descriptions.
Hmm.. I tried to rewrite it a bit again after I found some more corner cases where we might have problems.. Tried to make it as clear as possible. Please have a look if it makes it more clear now:
A clockevent device is used to service timers/hrtimers requests and the next event (when it should fire) is decided by the timer/hrtimer expiring next. When no timers/hrtimers are pending to be serviced, the expiry time is set to a special value: KTIME_MAX. This means that no events are required for indefinite amount of time.
This would normally happen with NO_HZ_{IDLE|FULL} in both LOWRES/HIGHRES modes.
When expiry == KTIME_MAX, either we cancel the tick-sched hrtimer (NOHZ_MODE_HIGHRES) or skip reprogramming clockevent device (NOHZ_MODE_LOWRES). But, the clockevent device is already reprogrammed from tick-handler for next tick.
So, the clockevent device will fire one more time. In NOHZ_MODE_HIGHRES, we will consider it as a spurious interrupt and just return from hrtimer_interrupt(). In NOHZ_MODE_LOWRES, we schedule the next tick again from tick_nohz_handler()? (This is what I could read from the code, not very sure though. Otherwise, it means that in NOHZ_MODE_LOWRES we are never tickless).
Ideally, as the clock event device is programmed in ONESHOT mode it should just fire one more time and that's it. But many implementations (like arm_arch_timer, etc) only have PERIODIC mode available and their drivers emulate ONESHOT over that. Which means that on these platforms we will get spurious interrupts at tick rate and that will hurt our tickless-ness badly.
At this time the clockevent device should be stopped, or its interrupts may be masked in order to get these issues fixed.
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. Also, NOHZ_MODE_LOWRES problem mentioned above wouldn't be fixed by 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.
linaro-kernel@lists.linaro.org