Skip to content

Commit 7c1e768

Browse files
Venkatesh PallipadiKAGA-KOKO
authored andcommitted
clockevents: prevent clockevent event_handler ending up handler_noop
There is a ordering related problem with clockevents code, due to which clockevents_register_device() called after tickless/highres switch will not work. The new clockevent ends up with clockevents_handle_noop as event handler, resulting in no timer activity. The problematic path seems to be * old device already has hrtimer_interrupt as the event_handler * new clockevent device registers with a higher rating * tick_check_new_device() is called * clockevents_exchange_device() gets called * old->event_handler is set to clockevents_handle_noop * tick_setup_device() is called for the new device * which sets new->event_handler using the old->event_handler which is noop. Change the ordering so that new device inherits the proper handler. This does not have any issue in normal case as most likely all the clockevent devices are setup before the highres switch. But, can potentially be affecting some corner case where HPET force detect happens after the highres switch. This was a problem with HPET in MSI mode code that we have been experimenting with. Signed-off-by: Venkatesh Pallipadi <[email protected]> Signed-off-by: Shaohua Li <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Signed-off-by: Ingo Molnar <[email protected]>
1 parent d210baf commit 7c1e768

File tree

3 files changed

+4
-2
lines changed

3 files changed

+4
-2
lines changed

include/linux/clockchips.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ extern int clockevents_register_notifier(struct notifier_block *nb);
127127
extern int clockevents_program_event(struct clock_event_device *dev,
128128
ktime_t expires, ktime_t now);
129129

130+
extern void clockevents_handle_noop(struct clock_event_device *dev);
131+
130132
#ifdef CONFIG_GENERIC_CLOCKEVENTS
131133
extern void clockevents_notify(unsigned long reason, void *arg);
132134
#else

kernel/time/clockevents.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ void clockevents_register_device(struct clock_event_device *dev)
177177
/*
178178
* Noop handler when we shut down an event device
179179
*/
180-
static void clockevents_handle_noop(struct clock_event_device *dev)
180+
void clockevents_handle_noop(struct clock_event_device *dev)
181181
{
182182
}
183183

@@ -199,7 +199,6 @@ void clockevents_exchange_device(struct clock_event_device *old,
199199
* released list and do a notify add later.
200200
*/
201201
if (old) {
202-
old->event_handler = clockevents_handle_noop;
203202
clockevents_set_mode(old, CLOCK_EVT_MODE_UNUSED);
204203
list_del(&old->list);
205204
list_add(&old->list, &clockevents_released);

kernel/time/tick-common.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ static void tick_setup_device(struct tick_device *td,
161161
} else {
162162
handler = td->evtdev->event_handler;
163163
next_event = td->evtdev->next_event;
164+
td->evtdev->event_handler = clockevents_handle_noop;
164165
}
165166

166167
td->evtdev = newdev;

0 commit comments

Comments
 (0)