aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2015-04-02 20:05:15 -0400
committerIngo Molnar <mingo@kernel.org>2015-04-03 02:44:33 -0400
commit1fe5d5c3c9ba0c4ade18e3325cba0ffe35127941 (patch)
treeb07d74d6468aa0bf1e2b107bb82d62b9fe6638d4 /kernel/time
parent89feddbfe7023ccfb4a6d7f5e3f5161d91b28b18 (diff)
clockevents: Provide explicit broadcast oneshot control functions
clockevents_notify() is a leftover from the early design of the clockevents facility. It's really not a notification mechanism, it's a multiplex call. We are way better off to have explicit calls instead of this monstrosity. Split out the broadcast oneshot control into a separate function and provide inline helpers. Switch clockevents_notify() over. This will go away once all callers are converted. This also gets rid of the nested locking of clockevents_lock and broadcast_lock. The broadcast oneshot control functions do not require clockevents_lock. Only the managing functions (setup/shutdown/suspend/resume of the broadcast device require clockevents_lock. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Cc: Alexandre Courbot <gnurou@gmail.com> Cc: Daniel Lezcano <daniel.lezcano@linaro.org> Cc: Len Brown <lenb@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephen Warren <swarren@wwwdotorg.org> Cc: Thierry Reding <thierry.reding@gmail.com> Cc: Tony Lindgren <tony@atomide.com> Link: http://lkml.kernel.org/r/13000649.8qZuEDV0OA@vostro.rjw.lan Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/time')
-rw-r--r--kernel/time/clockevents.c4
-rw-r--r--kernel/time/tick-broadcast.c28
-rw-r--r--kernel/time/tick-internal.h2
3 files changed, 20 insertions, 14 deletions
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c
index dba0b83708b3..7791b1c94ef2 100644
--- a/kernel/time/clockevents.c
+++ b/kernel/time/clockevents.c
@@ -656,8 +656,10 @@ int clockevents_notify(unsigned long reason, void *arg)
656 656
657 switch (reason) { 657 switch (reason) {
658 case CLOCK_EVT_NOTIFY_BROADCAST_ENTER: 658 case CLOCK_EVT_NOTIFY_BROADCAST_ENTER:
659 tick_broadcast_enter();
660 break;
659 case CLOCK_EVT_NOTIFY_BROADCAST_EXIT: 661 case CLOCK_EVT_NOTIFY_BROADCAST_EXIT:
660 ret = tick_broadcast_oneshot_control(reason); 662 tick_broadcast_exit();
661 break; 663 break;
662 664
663 case CLOCK_EVT_NOTIFY_CPU_DYING: 665 case CLOCK_EVT_NOTIFY_CPU_DYING:
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index 1a0bee04ef8c..55e43f20987a 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -687,18 +687,23 @@ void hotplug_cpu__broadcast_tick_pull(int deadcpu)
687 raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags); 687 raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
688} 688}
689 689
690/* 690/**
691 * Powerstate information: The system enters/leaves a state, where 691 * tick_broadcast_oneshot_control - Enter/exit broadcast oneshot mode
692 * affected devices might stop 692 * @state: The target state (enter/exit)
693 *
694 * The system enters/leaves a state, where affected devices might stop
693 * Returns 0 on success, -EBUSY if the cpu is used to broadcast wakeups. 695 * Returns 0 on success, -EBUSY if the cpu is used to broadcast wakeups.
696 *
697 * Called with interrupts disabled, so clockevents_lock is not
698 * required here because the local clock event device cannot go away
699 * under us.
694 */ 700 */
695int tick_broadcast_oneshot_control(unsigned long reason) 701int tick_broadcast_oneshot_control(enum tick_broadcast_state state)
696{ 702{
697 struct clock_event_device *bc, *dev; 703 struct clock_event_device *bc, *dev;
698 struct tick_device *td; 704 struct tick_device *td;
699 unsigned long flags;
700 ktime_t now;
701 int cpu, ret = 0; 705 int cpu, ret = 0;
706 ktime_t now;
702 707
703 /* 708 /*
704 * Periodic mode does not care about the enter/exit of power 709 * Periodic mode does not care about the enter/exit of power
@@ -711,17 +716,17 @@ int tick_broadcast_oneshot_control(unsigned long reason)
711 * We are called with preemtion disabled from the depth of the 716 * We are called with preemtion disabled from the depth of the
712 * idle code, so we can't be moved away. 717 * idle code, so we can't be moved away.
713 */ 718 */
714 cpu = smp_processor_id(); 719 td = this_cpu_ptr(&tick_cpu_device);
715 td = &per_cpu(tick_cpu_device, cpu);
716 dev = td->evtdev; 720 dev = td->evtdev;
717 721
718 if (!(dev->features & CLOCK_EVT_FEAT_C3STOP)) 722 if (!(dev->features & CLOCK_EVT_FEAT_C3STOP))
719 return 0; 723 return 0;
720 724
725 raw_spin_lock(&tick_broadcast_lock);
721 bc = tick_broadcast_device.evtdev; 726 bc = tick_broadcast_device.evtdev;
727 cpu = smp_processor_id();
722 728
723 raw_spin_lock_irqsave(&tick_broadcast_lock, flags); 729 if (state == TICK_BROADCAST_ENTER) {
724 if (reason == CLOCK_EVT_NOTIFY_BROADCAST_ENTER) {
725 if (!cpumask_test_and_set_cpu(cpu, tick_broadcast_oneshot_mask)) { 730 if (!cpumask_test_and_set_cpu(cpu, tick_broadcast_oneshot_mask)) {
726 WARN_ON_ONCE(cpumask_test_cpu(cpu, tick_broadcast_pending_mask)); 731 WARN_ON_ONCE(cpumask_test_cpu(cpu, tick_broadcast_pending_mask));
727 broadcast_shutdown_local(bc, dev); 732 broadcast_shutdown_local(bc, dev);
@@ -813,9 +818,10 @@ int tick_broadcast_oneshot_control(unsigned long reason)
813 } 818 }
814 } 819 }
815out: 820out:
816 raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags); 821 raw_spin_unlock(&tick_broadcast_lock);
817 return ret; 822 return ret;
818} 823}
824EXPORT_SYMBOL_GPL(tick_broadcast_oneshot_control);
819 825
820/* 826/*
821 * Reset the one shot broadcast for a cpu 827 * Reset the one shot broadcast for a cpu
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h
index 62e331d1bc76..0266f9dbd114 100644
--- a/kernel/time/tick-internal.h
+++ b/kernel/time/tick-internal.h
@@ -117,7 +117,6 @@ static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
117/* Functions related to oneshot broadcasting */ 117/* Functions related to oneshot broadcasting */
118#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT) 118#if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT)
119extern void tick_broadcast_setup_oneshot(struct clock_event_device *bc); 119extern void tick_broadcast_setup_oneshot(struct clock_event_device *bc);
120extern int tick_broadcast_oneshot_control(unsigned long reason);
121extern void tick_broadcast_switch_to_oneshot(void); 120extern void tick_broadcast_switch_to_oneshot(void);
122extern void tick_shutdown_broadcast_oneshot(unsigned int *cpup); 121extern void tick_shutdown_broadcast_oneshot(unsigned int *cpup);
123extern int tick_broadcast_oneshot_active(void); 122extern int tick_broadcast_oneshot_active(void);
@@ -126,7 +125,6 @@ bool tick_broadcast_oneshot_available(void);
126extern struct cpumask *tick_get_broadcast_oneshot_mask(void); 125extern struct cpumask *tick_get_broadcast_oneshot_mask(void);
127#else /* !(BROADCAST && ONESHOT): */ 126#else /* !(BROADCAST && ONESHOT): */
128static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc) { BUG(); } 127static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc) { BUG(); }
129static inline int tick_broadcast_oneshot_control(unsigned long reason) { return 0; }
130static inline void tick_broadcast_switch_to_oneshot(void) { } 128static inline void tick_broadcast_switch_to_oneshot(void) { }
131static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { } 129static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { }
132static inline int tick_broadcast_oneshot_active(void) { return 0; } 130static inline int tick_broadcast_oneshot_active(void) { return 0; }