diff options
| author | Thomas Gleixner <tglx@linutronix.de> | 2015-04-02 20:01:10 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2015-04-03 02:44:31 -0400 |
| commit | 592a438ff3fea61d303c5784c209b3f1fd3e16df (patch) | |
| tree | 8ce6cf8c2095a516e9226305649332bae70490a4 /kernel/time | |
| parent | 3ff70551a942b4c1d3c2e96e31a5c6e369a6d0be (diff) | |
clockevents: Provide explicit broadcast 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 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 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: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: Len Brown <lenb@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Tony Lindgren <tony@atomide.com>
Link: http://lkml.kernel.org/r/8086559.ttsuS0n1Xr@vostro.rjw.lan
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/time')
| -rw-r--r-- | kernel/time/clockevents.c | 6 | ||||
| -rw-r--r-- | kernel/time/tick-broadcast.c | 62 | ||||
| -rw-r--r-- | kernel/time/tick-internal.h | 2 |
3 files changed, 32 insertions, 38 deletions
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index 7af614829da1..599ff8d3fda5 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c | |||
| @@ -656,9 +656,13 @@ int clockevents_notify(unsigned long reason, void *arg) | |||
| 656 | 656 | ||
| 657 | switch (reason) { | 657 | switch (reason) { |
| 658 | case CLOCK_EVT_NOTIFY_BROADCAST_ON: | 658 | case CLOCK_EVT_NOTIFY_BROADCAST_ON: |
| 659 | tick_broadcast_enable(); | ||
| 660 | break; | ||
| 659 | case CLOCK_EVT_NOTIFY_BROADCAST_OFF: | 661 | case CLOCK_EVT_NOTIFY_BROADCAST_OFF: |
| 662 | tick_broadcast_disable(); | ||
| 663 | break; | ||
| 660 | case CLOCK_EVT_NOTIFY_BROADCAST_FORCE: | 664 | case CLOCK_EVT_NOTIFY_BROADCAST_FORCE: |
| 661 | tick_broadcast_on_off(reason, arg); | 665 | tick_broadcast_force(); |
| 662 | break; | 666 | break; |
| 663 | 667 | ||
| 664 | case CLOCK_EVT_NOTIFY_BROADCAST_ENTER: | 668 | case CLOCK_EVT_NOTIFY_BROADCAST_ENTER: |
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index f5e0fd5652dc..1a0bee04ef8c 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c | |||
| @@ -33,7 +33,7 @@ static cpumask_var_t tick_broadcast_mask; | |||
| 33 | static cpumask_var_t tick_broadcast_on; | 33 | static cpumask_var_t tick_broadcast_on; |
| 34 | static cpumask_var_t tmpmask; | 34 | static cpumask_var_t tmpmask; |
| 35 | static DEFINE_RAW_SPINLOCK(tick_broadcast_lock); | 35 | static DEFINE_RAW_SPINLOCK(tick_broadcast_lock); |
| 36 | static int tick_broadcast_force; | 36 | static int tick_broadcast_forced; |
| 37 | 37 | ||
| 38 | #ifdef CONFIG_TICK_ONESHOT | 38 | #ifdef CONFIG_TICK_ONESHOT |
| 39 | static void tick_broadcast_clear_oneshot(int cpu); | 39 | static void tick_broadcast_clear_oneshot(int cpu); |
| @@ -326,49 +326,54 @@ unlock: | |||
| 326 | raw_spin_unlock(&tick_broadcast_lock); | 326 | raw_spin_unlock(&tick_broadcast_lock); |
| 327 | } | 327 | } |
| 328 | 328 | ||
| 329 | /* | 329 | /** |
| 330 | * Powerstate information: The system enters/leaves a state, where | 330 | * tick_broadcast_control - Enable/disable or force broadcast mode |
| 331 | * affected devices might stop | 331 | * @mode: The selected broadcast mode |
| 332 | * | ||
| 333 | * Called when the system enters a state where affected tick devices | ||
| 334 | * might stop. Note: TICK_BROADCAST_FORCE cannot be undone. | ||
| 335 | * | ||
| 336 | * Called with interrupts disabled, so clockevents_lock is not | ||
| 337 | * required here because the local clock event device cannot go away | ||
| 338 | * under us. | ||
| 332 | */ | 339 | */ |
| 333 | static void tick_do_broadcast_on_off(unsigned long *reason) | 340 | void tick_broadcast_control(enum tick_broadcast_mode mode) |
| 334 | { | 341 | { |
| 335 | struct clock_event_device *bc, *dev; | 342 | struct clock_event_device *bc, *dev; |
| 336 | struct tick_device *td; | 343 | struct tick_device *td; |
| 337 | unsigned long flags; | ||
| 338 | int cpu, bc_stopped; | 344 | int cpu, bc_stopped; |
| 339 | 345 | ||
| 340 | raw_spin_lock_irqsave(&tick_broadcast_lock, flags); | 346 | td = this_cpu_ptr(&tick_cpu_device); |
| 341 | |||
| 342 | cpu = smp_processor_id(); | ||
| 343 | td = &per_cpu(tick_cpu_device, cpu); | ||
| 344 | dev = td->evtdev; | 347 | dev = td->evtdev; |
| 345 | bc = tick_broadcast_device.evtdev; | ||
| 346 | 348 | ||
| 347 | /* | 349 | /* |
| 348 | * Is the device not affected by the powerstate ? | 350 | * Is the device not affected by the powerstate ? |
| 349 | */ | 351 | */ |
| 350 | if (!dev || !(dev->features & CLOCK_EVT_FEAT_C3STOP)) | 352 | if (!dev || !(dev->features & CLOCK_EVT_FEAT_C3STOP)) |
| 351 | goto out; | 353 | return; |
| 352 | 354 | ||
| 353 | if (!tick_device_is_functional(dev)) | 355 | if (!tick_device_is_functional(dev)) |
| 354 | goto out; | 356 | return; |
| 355 | 357 | ||
| 358 | raw_spin_lock(&tick_broadcast_lock); | ||
| 359 | cpu = smp_processor_id(); | ||
| 360 | bc = tick_broadcast_device.evtdev; | ||
| 356 | bc_stopped = cpumask_empty(tick_broadcast_mask); | 361 | bc_stopped = cpumask_empty(tick_broadcast_mask); |
| 357 | 362 | ||
| 358 | switch (*reason) { | 363 | switch (mode) { |
| 359 | case CLOCK_EVT_NOTIFY_BROADCAST_ON: | 364 | case TICK_BROADCAST_FORCE: |
| 360 | case CLOCK_EVT_NOTIFY_BROADCAST_FORCE: | 365 | tick_broadcast_forced = 1; |
| 366 | case TICK_BROADCAST_ON: | ||
| 361 | cpumask_set_cpu(cpu, tick_broadcast_on); | 367 | cpumask_set_cpu(cpu, tick_broadcast_on); |
| 362 | if (!cpumask_test_and_set_cpu(cpu, tick_broadcast_mask)) { | 368 | if (!cpumask_test_and_set_cpu(cpu, tick_broadcast_mask)) { |
| 363 | if (tick_broadcast_device.mode == | 369 | if (tick_broadcast_device.mode == |
| 364 | TICKDEV_MODE_PERIODIC) | 370 | TICKDEV_MODE_PERIODIC) |
| 365 | clockevents_shutdown(dev); | 371 | clockevents_shutdown(dev); |
| 366 | } | 372 | } |
| 367 | if (*reason == CLOCK_EVT_NOTIFY_BROADCAST_FORCE) | ||
| 368 | tick_broadcast_force = 1; | ||
| 369 | break; | 373 | break; |
| 370 | case CLOCK_EVT_NOTIFY_BROADCAST_OFF: | 374 | |
| 371 | if (tick_broadcast_force) | 375 | case TICK_BROADCAST_OFF: |
| 376 | if (tick_broadcast_forced) | ||
| 372 | break; | 377 | break; |
| 373 | cpumask_clear_cpu(cpu, tick_broadcast_on); | 378 | cpumask_clear_cpu(cpu, tick_broadcast_on); |
| 374 | if (!tick_device_is_functional(dev)) | 379 | if (!tick_device_is_functional(dev)) |
| @@ -390,22 +395,9 @@ static void tick_do_broadcast_on_off(unsigned long *reason) | |||
| 390 | else | 395 | else |
| 391 | tick_broadcast_setup_oneshot(bc); | 396 | tick_broadcast_setup_oneshot(bc); |
| 392 | } | 397 | } |
| 393 | out: | 398 | raw_spin_unlock(&tick_broadcast_lock); |
| 394 | raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags); | ||
| 395 | } | ||
| 396 | |||
| 397 | /* | ||
| 398 | * Powerstate information: The system enters/leaves a state, where | ||
| 399 | * affected devices might stop. | ||
| 400 | */ | ||
| 401 | void tick_broadcast_on_off(unsigned long reason, int *oncpu) | ||
| 402 | { | ||
| 403 | if (!cpumask_test_cpu(*oncpu, cpu_online_mask)) | ||
| 404 | printk(KERN_ERR "tick-broadcast: ignoring broadcast for " | ||
| 405 | "offline CPU #%d\n", *oncpu); | ||
| 406 | else | ||
| 407 | tick_do_broadcast_on_off(&reason); | ||
| 408 | } | 399 | } |
| 400 | EXPORT_SYMBOL_GPL(tick_broadcast_control); | ||
| 409 | 401 | ||
| 410 | /* | 402 | /* |
| 411 | * Set the periodic handler depending on broadcast on/off | 403 | * Set the periodic handler depending on broadcast on/off |
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h index b6ba0a44e740..62e331d1bc76 100644 --- a/kernel/time/tick-internal.h +++ b/kernel/time/tick-internal.h | |||
| @@ -53,7 +53,6 @@ extern ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt); | |||
| 53 | extern int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu); | 53 | extern int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu); |
| 54 | extern void tick_install_broadcast_device(struct clock_event_device *dev); | 54 | extern void tick_install_broadcast_device(struct clock_event_device *dev); |
| 55 | extern int tick_is_broadcast_device(struct clock_event_device *dev); | 55 | extern int tick_is_broadcast_device(struct clock_event_device *dev); |
| 56 | extern void tick_broadcast_on_off(unsigned long reason, int *oncpu); | ||
| 57 | extern void tick_shutdown_broadcast(unsigned int *cpup); | 56 | extern void tick_shutdown_broadcast(unsigned int *cpup); |
| 58 | extern void tick_suspend_broadcast(void); | 57 | extern void tick_suspend_broadcast(void); |
| 59 | extern void tick_resume_broadcast(void); | 58 | extern void tick_resume_broadcast(void); |
| @@ -68,7 +67,6 @@ static inline void tick_install_broadcast_device(struct clock_event_device *dev) | |||
| 68 | static inline int tick_is_broadcast_device(struct clock_event_device *dev) { return 0; } | 67 | static inline int tick_is_broadcast_device(struct clock_event_device *dev) { return 0; } |
| 69 | static inline int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu) { return 0; } | 68 | static inline int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu) { return 0; } |
| 70 | static inline void tick_do_periodic_broadcast(struct clock_event_device *d) { } | 69 | static inline void tick_do_periodic_broadcast(struct clock_event_device *d) { } |
| 71 | static inline void tick_broadcast_on_off(unsigned long reason, int *oncpu) { } | ||
| 72 | static inline void tick_shutdown_broadcast(unsigned int *cpup) { } | 70 | static inline void tick_shutdown_broadcast(unsigned int *cpup) { } |
| 73 | static inline void tick_suspend_broadcast(void) { } | 71 | static inline void tick_suspend_broadcast(void) { } |
| 74 | static inline void tick_resume_broadcast(void) { } | 72 | static inline void tick_resume_broadcast(void) { } |
