Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull clocksource fixes from Thomas Gleixner:
"The recent addition of the early TSC clocksource breaks on machines
which have an unstable TSC because in case that TSC is disabled, then
the clocksource selection logic falls back to the early TSC which is
obviously bogus.

That also unearthed a few robustness issues in the clocksource
derating code which are addressed as well"

* 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
clocksource: Rework stale comment
clocksource: Consistent de-rate when marking unstable
x86/tsc: Fix mark_tsc_unstable()
clocksource: Initialize cs->wd_list
clocksource: Allow clocksource_mark_unstable() on unregistered clocksources
x86/tsc: Always unregister clocksource_tsc_early

+55 -30
+11 -11
arch/x86/kernel/tsc.c
··· 1067 1067 .resume = tsc_resume, 1068 1068 .mark_unstable = tsc_cs_mark_unstable, 1069 1069 .tick_stable = tsc_cs_tick_stable, 1070 + .list = LIST_HEAD_INIT(clocksource_tsc_early.list), 1070 1071 }; 1071 1072 1072 1073 /* ··· 1087 1086 .resume = tsc_resume, 1088 1087 .mark_unstable = tsc_cs_mark_unstable, 1089 1088 .tick_stable = tsc_cs_tick_stable, 1089 + .list = LIST_HEAD_INIT(clocksource_tsc.list), 1090 1090 }; 1091 1091 1092 1092 void mark_tsc_unstable(char *reason) ··· 1100 1098 clear_sched_clock_stable(); 1101 1099 disable_sched_clock_irqtime(); 1102 1100 pr_info("Marking TSC unstable due to %s\n", reason); 1103 - /* Change only the rating, when not registered */ 1104 - if (clocksource_tsc.mult) { 1105 - clocksource_mark_unstable(&clocksource_tsc); 1106 - } else { 1107 - clocksource_tsc.flags |= CLOCK_SOURCE_UNSTABLE; 1108 - clocksource_tsc.rating = 0; 1109 - } 1101 + 1102 + clocksource_mark_unstable(&clocksource_tsc_early); 1103 + clocksource_mark_unstable(&clocksource_tsc); 1110 1104 } 1111 1105 1112 1106 EXPORT_SYMBOL_GPL(mark_tsc_unstable); ··· 1242 1244 1243 1245 /* Don't bother refining TSC on unstable systems */ 1244 1246 if (tsc_unstable) 1245 - return; 1247 + goto unreg; 1246 1248 1247 1249 /* 1248 1250 * Since the work is started early in boot, we may be ··· 1295 1297 1296 1298 out: 1297 1299 if (tsc_unstable) 1298 - return; 1300 + goto unreg; 1299 1301 1300 1302 if (boot_cpu_has(X86_FEATURE_ART)) 1301 1303 art_related_clocksource = &clocksource_tsc; 1302 1304 clocksource_register_khz(&clocksource_tsc, tsc_khz); 1305 + unreg: 1303 1306 clocksource_unregister(&clocksource_tsc_early); 1304 1307 } 1305 1308 ··· 1310 1311 if (!boot_cpu_has(X86_FEATURE_TSC) || tsc_disabled > 0 || !tsc_khz) 1311 1312 return 0; 1312 1313 1313 - if (check_tsc_unstable()) 1314 - return 0; 1314 + if (tsc_unstable) 1315 + goto unreg; 1315 1316 1316 1317 if (tsc_clocksource_reliable) 1317 1318 clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY; ··· 1327 1328 if (boot_cpu_has(X86_FEATURE_ART)) 1328 1329 art_related_clocksource = &clocksource_tsc; 1329 1330 clocksource_register_khz(&clocksource_tsc, tsc_khz); 1331 + unreg: 1330 1332 clocksource_unregister(&clocksource_tsc_early); 1331 1333 return 0; 1332 1334 }
+44 -19
kernel/time/clocksource.c
··· 119 119 static int watchdog_running; 120 120 static atomic_t watchdog_reset_pending; 121 121 122 + static void inline clocksource_watchdog_lock(unsigned long *flags) 123 + { 124 + spin_lock_irqsave(&watchdog_lock, *flags); 125 + } 126 + 127 + static void inline clocksource_watchdog_unlock(unsigned long *flags) 128 + { 129 + spin_unlock_irqrestore(&watchdog_lock, *flags); 130 + } 131 + 122 132 static int clocksource_watchdog_kthread(void *data); 123 133 static void __clocksource_change_rating(struct clocksource *cs, int rating); 124 134 ··· 152 142 cs->flags &= ~(CLOCK_SOURCE_VALID_FOR_HRES | CLOCK_SOURCE_WATCHDOG); 153 143 cs->flags |= CLOCK_SOURCE_UNSTABLE; 154 144 145 + /* 146 + * If the clocksource is registered clocksource_watchdog_kthread() will 147 + * re-rate and re-select. 148 + */ 149 + if (list_empty(&cs->list)) { 150 + cs->rating = 0; 151 + return; 152 + } 153 + 155 154 if (cs->mark_unstable) 156 155 cs->mark_unstable(cs); 157 156 157 + /* kick clocksource_watchdog_kthread() */ 158 158 if (finished_booting) 159 159 schedule_work(&watchdog_work); 160 160 } ··· 173 153 * clocksource_mark_unstable - mark clocksource unstable via watchdog 174 154 * @cs: clocksource to be marked unstable 175 155 * 176 - * This function is called instead of clocksource_change_rating from 177 - * cpu hotplug code to avoid a deadlock between the clocksource mutex 178 - * and the cpu hotplug mutex. It defers the update of the clocksource 179 - * to the watchdog thread. 156 + * This function is called by the x86 TSC code to mark clocksources as unstable; 157 + * it defers demotion and re-selection to a kthread. 180 158 */ 181 159 void clocksource_mark_unstable(struct clocksource *cs) 182 160 { ··· 182 164 183 165 spin_lock_irqsave(&watchdog_lock, flags); 184 166 if (!(cs->flags & CLOCK_SOURCE_UNSTABLE)) { 185 - if (list_empty(&cs->wd_list)) 167 + if (!list_empty(&cs->list) && list_empty(&cs->wd_list)) 186 168 list_add(&cs->wd_list, &watchdog_list); 187 169 __clocksource_unstable(cs); 188 170 } ··· 337 319 338 320 static void clocksource_enqueue_watchdog(struct clocksource *cs) 339 321 { 340 - unsigned long flags; 322 + INIT_LIST_HEAD(&cs->wd_list); 341 323 342 - spin_lock_irqsave(&watchdog_lock, flags); 343 324 if (cs->flags & CLOCK_SOURCE_MUST_VERIFY) { 344 325 /* cs is a clocksource to be watched. */ 345 326 list_add(&cs->wd_list, &watchdog_list); ··· 348 331 if (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) 349 332 cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES; 350 333 } 351 - spin_unlock_irqrestore(&watchdog_lock, flags); 352 334 } 353 335 354 336 static void clocksource_select_watchdog(bool fallback) ··· 389 373 390 374 static void clocksource_dequeue_watchdog(struct clocksource *cs) 391 375 { 392 - unsigned long flags; 393 - 394 - spin_lock_irqsave(&watchdog_lock, flags); 395 376 if (cs != watchdog) { 396 377 if (cs->flags & CLOCK_SOURCE_MUST_VERIFY) { 397 378 /* cs is a watched clocksource. */ ··· 397 384 clocksource_stop_watchdog(); 398 385 } 399 386 } 400 - spin_unlock_irqrestore(&watchdog_lock, flags); 401 387 } 402 388 403 389 static int __clocksource_watchdog_kthread(void) 404 390 { 405 391 struct clocksource *cs, *tmp; 406 392 unsigned long flags; 407 - LIST_HEAD(unstable); 408 393 int select = 0; 409 394 410 395 spin_lock_irqsave(&watchdog_lock, flags); 411 396 list_for_each_entry_safe(cs, tmp, &watchdog_list, wd_list) { 412 397 if (cs->flags & CLOCK_SOURCE_UNSTABLE) { 413 398 list_del_init(&cs->wd_list); 414 - list_add(&cs->wd_list, &unstable); 399 + __clocksource_change_rating(cs, 0); 415 400 select = 1; 416 401 } 417 402 if (cs->flags & CLOCK_SOURCE_RESELECT) { ··· 421 410 clocksource_stop_watchdog(); 422 411 spin_unlock_irqrestore(&watchdog_lock, flags); 423 412 424 - /* Needs to be done outside of watchdog lock */ 425 - list_for_each_entry_safe(cs, tmp, &unstable, wd_list) { 426 - list_del_init(&cs->wd_list); 427 - __clocksource_change_rating(cs, 0); 428 - } 429 413 return select; 430 414 } 431 415 ··· 452 446 static inline int __clocksource_watchdog_kthread(void) { return 0; } 453 447 static bool clocksource_is_watchdog(struct clocksource *cs) { return false; } 454 448 void clocksource_mark_unstable(struct clocksource *cs) { } 449 + 450 + static void inline clocksource_watchdog_lock(unsigned long *flags) { } 451 + static void inline clocksource_watchdog_unlock(unsigned long *flags) { } 455 452 456 453 #endif /* CONFIG_CLOCKSOURCE_WATCHDOG */ 457 454 ··· 788 779 */ 789 780 int __clocksource_register_scale(struct clocksource *cs, u32 scale, u32 freq) 790 781 { 782 + unsigned long flags; 791 783 792 784 /* Initialize mult/shift and max_idle_ns */ 793 785 __clocksource_update_freq_scale(cs, scale, freq); 794 786 795 787 /* Add clocksource to the clocksource list */ 796 788 mutex_lock(&clocksource_mutex); 789 + 790 + clocksource_watchdog_lock(&flags); 797 791 clocksource_enqueue(cs); 798 792 clocksource_enqueue_watchdog(cs); 793 + clocksource_watchdog_unlock(&flags); 794 + 799 795 clocksource_select(); 800 796 clocksource_select_watchdog(false); 801 797 mutex_unlock(&clocksource_mutex); ··· 822 808 */ 823 809 void clocksource_change_rating(struct clocksource *cs, int rating) 824 810 { 811 + unsigned long flags; 812 + 825 813 mutex_lock(&clocksource_mutex); 814 + clocksource_watchdog_lock(&flags); 826 815 __clocksource_change_rating(cs, rating); 816 + clocksource_watchdog_unlock(&flags); 817 + 827 818 clocksource_select(); 828 819 clocksource_select_watchdog(false); 829 820 mutex_unlock(&clocksource_mutex); ··· 840 821 */ 841 822 static int clocksource_unbind(struct clocksource *cs) 842 823 { 824 + unsigned long flags; 825 + 843 826 if (clocksource_is_watchdog(cs)) { 844 827 /* Select and try to install a replacement watchdog. */ 845 828 clocksource_select_watchdog(true); ··· 855 834 if (curr_clocksource == cs) 856 835 return -EBUSY; 857 836 } 837 + 838 + clocksource_watchdog_lock(&flags); 858 839 clocksource_dequeue_watchdog(cs); 859 840 list_del_init(&cs->list); 841 + clocksource_watchdog_unlock(&flags); 842 + 860 843 return 0; 861 844 } 862 845