|
@@ -687,18 +687,23 @@ void hotplug_cpu__broadcast_tick_pull(int deadcpu)
|
|
raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
|
|
raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
|
|
}
|
|
}
|
|
|
|
|
|
-/*
|
|
|
|
- * Powerstate information: The system enters/leaves a state, where
|
|
|
|
- * affected devices might stop
|
|
|
|
|
|
+/**
|
|
|
|
+ * tick_broadcast_oneshot_control - Enter/exit broadcast oneshot mode
|
|
|
|
+ * @state: The target state (enter/exit)
|
|
|
|
+ *
|
|
|
|
+ * The system enters/leaves a state, where affected devices might stop
|
|
* Returns 0 on success, -EBUSY if the cpu is used to broadcast wakeups.
|
|
* Returns 0 on success, -EBUSY if the cpu is used to broadcast wakeups.
|
|
|
|
+ *
|
|
|
|
+ * Called with interrupts disabled, so clockevents_lock is not
|
|
|
|
+ * required here because the local clock event device cannot go away
|
|
|
|
+ * under us.
|
|
*/
|
|
*/
|
|
-int tick_broadcast_oneshot_control(unsigned long reason)
|
|
|
|
|
|
+int tick_broadcast_oneshot_control(enum tick_broadcast_state state)
|
|
{
|
|
{
|
|
struct clock_event_device *bc, *dev;
|
|
struct clock_event_device *bc, *dev;
|
|
struct tick_device *td;
|
|
struct tick_device *td;
|
|
- unsigned long flags;
|
|
|
|
- ktime_t now;
|
|
|
|
int cpu, ret = 0;
|
|
int cpu, ret = 0;
|
|
|
|
+ ktime_t now;
|
|
|
|
|
|
/*
|
|
/*
|
|
* Periodic mode does not care about the enter/exit of power
|
|
* Periodic mode does not care about the enter/exit of power
|
|
@@ -711,17 +716,17 @@ int tick_broadcast_oneshot_control(unsigned long reason)
|
|
* We are called with preemtion disabled from the depth of the
|
|
* We are called with preemtion disabled from the depth of the
|
|
* idle code, so we can't be moved away.
|
|
* idle code, so we can't be moved away.
|
|
*/
|
|
*/
|
|
- cpu = smp_processor_id();
|
|
|
|
- td = &per_cpu(tick_cpu_device, cpu);
|
|
|
|
|
|
+ td = this_cpu_ptr(&tick_cpu_device);
|
|
dev = td->evtdev;
|
|
dev = td->evtdev;
|
|
|
|
|
|
if (!(dev->features & CLOCK_EVT_FEAT_C3STOP))
|
|
if (!(dev->features & CLOCK_EVT_FEAT_C3STOP))
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
|
|
+ raw_spin_lock(&tick_broadcast_lock);
|
|
bc = tick_broadcast_device.evtdev;
|
|
bc = tick_broadcast_device.evtdev;
|
|
|
|
+ cpu = smp_processor_id();
|
|
|
|
|
|
- raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
|
|
|
|
- if (reason == CLOCK_EVT_NOTIFY_BROADCAST_ENTER) {
|
|
|
|
|
|
+ if (state == TICK_BROADCAST_ENTER) {
|
|
if (!cpumask_test_and_set_cpu(cpu, tick_broadcast_oneshot_mask)) {
|
|
if (!cpumask_test_and_set_cpu(cpu, tick_broadcast_oneshot_mask)) {
|
|
WARN_ON_ONCE(cpumask_test_cpu(cpu, tick_broadcast_pending_mask));
|
|
WARN_ON_ONCE(cpumask_test_cpu(cpu, tick_broadcast_pending_mask));
|
|
broadcast_shutdown_local(bc, dev);
|
|
broadcast_shutdown_local(bc, dev);
|
|
@@ -813,9 +818,10 @@ int tick_broadcast_oneshot_control(unsigned long reason)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
out:
|
|
out:
|
|
- raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
|
|
|
|
|
|
+ raw_spin_unlock(&tick_broadcast_lock);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
+EXPORT_SYMBOL_GPL(tick_broadcast_oneshot_control);
|
|
|
|
|
|
/*
|
|
/*
|
|
* Reset the one shot broadcast for a cpu
|
|
* Reset the one shot broadcast for a cpu
|