aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time/tick-broadcast.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/time/tick-broadcast.c')
-rw-r--r--kernel/time/tick-broadcast.c28
1 files changed, 17 insertions, 11 deletions
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