Skip to content

Commit fe2a449

Browse files
bibo-maoKAGA-KOKO
authored andcommitted
tick: Do not set device to detached state in tick_shutdown()
tick_shutdown() sets the state of the clockevent device to detached first and the invokes clockevents_exchange_device(), which in turn invokes clockevents_switch_state(). But clockevents_switch_state() returns without invoking the device shutdown callback as the device is already in detached state. As a consequence the timer device is not shutdown when a CPU goes offline. tick_shutdown() does this because it was originally invoked on a online CPU and not on the outgoing CPU. It therefore could not access the clockevent device of the already offlined CPU and just set the state. Since commit 3b1596a tick_shutdown() is called on the outgoing CPU, so the hardware device can be accessed. Remove the state set before calling clockevents_exchange_device(), so that the subsequent clockevents_switch_state() handles the state transition and invokes the shutdown callback of the clockevent device. [ tglx: Massaged change log ] Fixes: 3b1596a ("clockevents: Shutdown and unregister current clockevents at CPUHP_AP_TICK_DYING") Signed-off-by: Bibo Mao <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Reviewed-by: Frederic Weisbecker <[email protected]> Link: https://lore.kernel.org/all/[email protected]
1 parent 3c3af56 commit fe2a449

File tree

3 files changed

+7
-13
lines changed

3 files changed

+7
-13
lines changed

kernel/time/clockevents.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,7 @@ void tick_offline_cpu(unsigned int cpu)
633633
raw_spin_lock(&clockevents_lock);
634634

635635
tick_broadcast_offline(cpu);
636-
tick_shutdown(cpu);
636+
tick_shutdown();
637637

638638
/*
639639
* Unregister the clock event devices which were

kernel/time/tick-common.c

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -411,24 +411,18 @@ int tick_cpu_dying(unsigned int dying_cpu)
411411
}
412412

413413
/*
414-
* Shutdown an event device on a given cpu:
414+
* Shutdown an event device on the outgoing CPU:
415415
*
416-
* This is called on a life CPU, when a CPU is dead. So we cannot
417-
* access the hardware device itself.
418-
* We just set the mode and remove it from the lists.
416+
* Called by the dying CPU during teardown, with clockevents_lock held
417+
* and interrupts disabled.
419418
*/
420-
void tick_shutdown(unsigned int cpu)
419+
void tick_shutdown(void)
421420
{
422-
struct tick_device *td = &per_cpu(tick_cpu_device, cpu);
421+
struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
423422
struct clock_event_device *dev = td->evtdev;
424423

425424
td->mode = TICKDEV_MODE_PERIODIC;
426425
if (dev) {
427-
/*
428-
* Prevent that the clock events layer tries to call
429-
* the set mode function!
430-
*/
431-
clockevent_set_state(dev, CLOCK_EVT_STATE_DETACHED);
432426
clockevents_exchange_device(dev, NULL);
433427
dev->event_handler = clockevents_handle_noop;
434428
td->evtdev = NULL;

kernel/time/tick-internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ extern void tick_setup_periodic(struct clock_event_device *dev, int broadcast);
2626
extern void tick_handle_periodic(struct clock_event_device *dev);
2727
extern void tick_check_new_device(struct clock_event_device *dev);
2828
extern void tick_offline_cpu(unsigned int cpu);
29-
extern void tick_shutdown(unsigned int cpu);
29+
extern void tick_shutdown(void);
3030
extern void tick_suspend(void);
3131
extern void tick_resume(void);
3232
extern bool tick_check_replacement(struct clock_event_device *curdev,

0 commit comments

Comments
 (0)