aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time/clocksource.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/time/clocksource.c')
-rw-r--r--kernel/time/clocksource.c112
1 files changed, 44 insertions, 68 deletions
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index f18c9a6bdcf4..a1657b5fdeb9 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -109,35 +109,17 @@ EXPORT_SYMBOL(timecounter_cyc2time);
109/*[Clocksource internal variables]--------- 109/*[Clocksource internal variables]---------
110 * curr_clocksource: 110 * curr_clocksource:
111 * currently selected clocksource. 111 * currently selected clocksource.
112 * next_clocksource:
113 * pending next selected clocksource.
114 * clocksource_list: 112 * clocksource_list:
115 * linked list with the registered clocksources 113 * linked list with the registered clocksources
116 * clocksource_lock: 114 * clocksource_mutex:
117 * protects manipulations to curr_clocksource and next_clocksource 115 * protects manipulations to curr_clocksource and the clocksource_list
118 * and the clocksource_list
119 * override_name: 116 * override_name:
120 * Name of the user-specified clocksource. 117 * Name of the user-specified clocksource.
121 */ 118 */
122static struct clocksource *curr_clocksource; 119static struct clocksource *curr_clocksource;
123static struct clocksource *next_clocksource;
124static LIST_HEAD(clocksource_list); 120static LIST_HEAD(clocksource_list);
125static DEFINE_SPINLOCK(clocksource_lock); 121static DEFINE_MUTEX(clocksource_mutex);
126static char override_name[32]; 122static char override_name[32];
127static int finished_booting;
128
129/* clocksource_done_booting - Called near the end of core bootup
130 *
131 * Hack to avoid lots of clocksource churn at boot time.
132 * We use fs_initcall because we want this to start before
133 * device_initcall but after subsys_initcall.
134 */
135static int __init clocksource_done_booting(void)
136{
137 finished_booting = 1;
138 return 0;
139}
140fs_initcall(clocksource_done_booting);
141 123
142#ifdef CONFIG_CLOCKSOURCE_WATCHDOG 124#ifdef CONFIG_CLOCKSOURCE_WATCHDOG
143static LIST_HEAD(watchdog_list); 125static LIST_HEAD(watchdog_list);
@@ -356,18 +338,16 @@ static inline void clocksource_resume_watchdog(void) { }
356void clocksource_resume(void) 338void clocksource_resume(void)
357{ 339{
358 struct clocksource *cs; 340 struct clocksource *cs;
359 unsigned long flags;
360 341
361 spin_lock_irqsave(&clocksource_lock, flags); 342 mutex_lock(&clocksource_mutex);
362 343
363 list_for_each_entry(cs, &clocksource_list, list) { 344 list_for_each_entry(cs, &clocksource_list, list)
364 if (cs->resume) 345 if (cs->resume)
365 cs->resume(); 346 cs->resume();
366 }
367 347
368 clocksource_resume_watchdog(); 348 clocksource_resume_watchdog();
369 349
370 spin_unlock_irqrestore(&clocksource_lock, flags); 350 mutex_unlock(&clocksource_mutex);
371} 351}
372 352
373/** 353/**
@@ -383,28 +363,13 @@ void clocksource_touch_watchdog(void)
383} 363}
384 364
385#ifdef CONFIG_GENERIC_TIME 365#ifdef CONFIG_GENERIC_TIME
386/**
387 * clocksource_get_next - Returns the selected clocksource
388 *
389 */
390struct clocksource *clocksource_get_next(void)
391{
392 unsigned long flags;
393 366
394 spin_lock_irqsave(&clocksource_lock, flags); 367static int finished_booting;
395 if (next_clocksource && finished_booting) {
396 curr_clocksource = next_clocksource;
397 next_clocksource = NULL;
398 }
399 spin_unlock_irqrestore(&clocksource_lock, flags);
400
401 return curr_clocksource;
402}
403 368
404/** 369/**
405 * clocksource_select - Select the best clocksource available 370 * clocksource_select - Select the best clocksource available
406 * 371 *
407 * Private function. Must hold clocksource_lock when called. 372 * Private function. Must hold clocksource_mutex when called.
408 * 373 *
409 * Select the clocksource with the best rating, or the clocksource, 374 * Select the clocksource with the best rating, or the clocksource,
410 * which is selected by userspace override. 375 * which is selected by userspace override.
@@ -413,7 +378,7 @@ static void clocksource_select(void)
413{ 378{
414 struct clocksource *best, *cs; 379 struct clocksource *best, *cs;
415 380
416 if (list_empty(&clocksource_list)) 381 if (!finished_booting || list_empty(&clocksource_list))
417 return; 382 return;
418 /* First clocksource on the list has the best rating. */ 383 /* First clocksource on the list has the best rating. */
419 best = list_first_entry(&clocksource_list, struct clocksource, list); 384 best = list_first_entry(&clocksource_list, struct clocksource, list);
@@ -438,13 +403,31 @@ static void clocksource_select(void)
438 best = cs; 403 best = cs;
439 break; 404 break;
440 } 405 }
441 if (curr_clocksource != best) 406 if (curr_clocksource != best) {
442 next_clocksource = best; 407 printk(KERN_INFO "Switching to clocksource %s\n", best->name);
408 curr_clocksource = best;
409 timekeeping_notify(curr_clocksource);
410 }
443} 411}
444 412
413/*
414 * clocksource_done_booting - Called near the end of core bootup
415 *
416 * Hack to avoid lots of clocksource churn at boot time.
417 * We use fs_initcall because we want this to start before
418 * device_initcall but after subsys_initcall.
419 */
420static int __init clocksource_done_booting(void)
421{
422 finished_booting = 1;
423 clocksource_select();
424 return 0;
425}
426fs_initcall(clocksource_done_booting);
427
445#else /* CONFIG_GENERIC_TIME */ 428#else /* CONFIG_GENERIC_TIME */
446 429
447static void clocksource_select(void) { } 430static inline void clocksource_select(void) { }
448 431
449#endif 432#endif
450 433
@@ -471,13 +454,11 @@ static void clocksource_enqueue(struct clocksource *cs)
471 */ 454 */
472int clocksource_register(struct clocksource *cs) 455int clocksource_register(struct clocksource *cs)
473{ 456{
474 unsigned long flags; 457 mutex_lock(&clocksource_mutex);
475
476 spin_lock_irqsave(&clocksource_lock, flags);
477 clocksource_enqueue(cs); 458 clocksource_enqueue(cs);
478 clocksource_select(); 459 clocksource_select();
479 spin_unlock_irqrestore(&clocksource_lock, flags);
480 clocksource_enqueue_watchdog(cs); 460 clocksource_enqueue_watchdog(cs);
461 mutex_unlock(&clocksource_mutex);
481 return 0; 462 return 0;
482} 463}
483EXPORT_SYMBOL(clocksource_register); 464EXPORT_SYMBOL(clocksource_register);
@@ -487,14 +468,12 @@ EXPORT_SYMBOL(clocksource_register);
487 */ 468 */
488void clocksource_change_rating(struct clocksource *cs, int rating) 469void clocksource_change_rating(struct clocksource *cs, int rating)
489{ 470{
490 unsigned long flags; 471 mutex_lock(&clocksource_mutex);
491
492 spin_lock_irqsave(&clocksource_lock, flags);
493 list_del(&cs->list); 472 list_del(&cs->list);
494 cs->rating = rating; 473 cs->rating = rating;
495 clocksource_enqueue(cs); 474 clocksource_enqueue(cs);
496 clocksource_select(); 475 clocksource_select();
497 spin_unlock_irqrestore(&clocksource_lock, flags); 476 mutex_unlock(&clocksource_mutex);
498} 477}
499EXPORT_SYMBOL(clocksource_change_rating); 478EXPORT_SYMBOL(clocksource_change_rating);
500 479
@@ -503,13 +482,11 @@ EXPORT_SYMBOL(clocksource_change_rating);
503 */ 482 */
504void clocksource_unregister(struct clocksource *cs) 483void clocksource_unregister(struct clocksource *cs)
505{ 484{
506 unsigned long flags; 485 mutex_lock(&clocksource_mutex);
507
508 clocksource_dequeue_watchdog(cs); 486 clocksource_dequeue_watchdog(cs);
509 spin_lock_irqsave(&clocksource_lock, flags);
510 list_del(&cs->list); 487 list_del(&cs->list);
511 clocksource_select(); 488 clocksource_select();
512 spin_unlock_irqrestore(&clocksource_lock, flags); 489 mutex_unlock(&clocksource_mutex);
513} 490}
514EXPORT_SYMBOL(clocksource_unregister); 491EXPORT_SYMBOL(clocksource_unregister);
515 492
@@ -527,9 +504,9 @@ sysfs_show_current_clocksources(struct sys_device *dev,
527{ 504{
528 ssize_t count = 0; 505 ssize_t count = 0;
529 506
530 spin_lock_irq(&clocksource_lock); 507 mutex_lock(&clocksource_mutex);
531 count = snprintf(buf, PAGE_SIZE, "%s\n", curr_clocksource->name); 508 count = snprintf(buf, PAGE_SIZE, "%s\n", curr_clocksource->name);
532 spin_unlock_irq(&clocksource_lock); 509 mutex_unlock(&clocksource_mutex);
533 510
534 return count; 511 return count;
535} 512}
@@ -557,14 +534,14 @@ static ssize_t sysfs_override_clocksource(struct sys_device *dev,
557 if (buf[count-1] == '\n') 534 if (buf[count-1] == '\n')
558 count--; 535 count--;
559 536
560 spin_lock_irq(&clocksource_lock); 537 mutex_lock(&clocksource_mutex);
561 538
562 if (count > 0) 539 if (count > 0)
563 memcpy(override_name, buf, count); 540 memcpy(override_name, buf, count);
564 override_name[count] = 0; 541 override_name[count] = 0;
565 clocksource_select(); 542 clocksource_select();
566 543
567 spin_unlock_irq(&clocksource_lock); 544 mutex_unlock(&clocksource_mutex);
568 545
569 return ret; 546 return ret;
570} 547}
@@ -584,7 +561,7 @@ sysfs_show_available_clocksources(struct sys_device *dev,
584 struct clocksource *src; 561 struct clocksource *src;
585 ssize_t count = 0; 562 ssize_t count = 0;
586 563
587 spin_lock_irq(&clocksource_lock); 564 mutex_lock(&clocksource_mutex);
588 list_for_each_entry(src, &clocksource_list, list) { 565 list_for_each_entry(src, &clocksource_list, list) {
589 /* 566 /*
590 * Don't show non-HRES clocksource if the tick code is 567 * Don't show non-HRES clocksource if the tick code is
@@ -596,7 +573,7 @@ sysfs_show_available_clocksources(struct sys_device *dev,
596 max((ssize_t)PAGE_SIZE - count, (ssize_t)0), 573 max((ssize_t)PAGE_SIZE - count, (ssize_t)0),
597 "%s ", src->name); 574 "%s ", src->name);
598 } 575 }
599 spin_unlock_irq(&clocksource_lock); 576 mutex_unlock(&clocksource_mutex);
600 577
601 count += snprintf(buf + count, 578 count += snprintf(buf + count,
602 max((ssize_t)PAGE_SIZE - count, (ssize_t)0), "\n"); 579 max((ssize_t)PAGE_SIZE - count, (ssize_t)0), "\n");
@@ -651,11 +628,10 @@ device_initcall(init_clocksource_sysfs);
651 */ 628 */
652static int __init boot_override_clocksource(char* str) 629static int __init boot_override_clocksource(char* str)
653{ 630{
654 unsigned long flags; 631 mutex_lock(&clocksource_mutex);
655 spin_lock_irqsave(&clocksource_lock, flags);
656 if (str) 632 if (str)
657 strlcpy(override_name, str, sizeof(override_name)); 633 strlcpy(override_name, str, sizeof(override_name));
658 spin_unlock_irqrestore(&clocksource_lock, flags); 634 mutex_unlock(&clocksource_mutex);
659 return 1; 635 return 1;
660} 636}
661 637