1734efb46Sjohn stultz /* 2734efb46Sjohn stultz * linux/kernel/time/clocksource.c 3734efb46Sjohn stultz * 4734efb46Sjohn stultz * This file contains the functions which manage clocksource drivers. 5734efb46Sjohn stultz * 6734efb46Sjohn stultz * Copyright (C) 2004, 2005 IBM, John Stultz (johnstul@us.ibm.com) 7734efb46Sjohn stultz * 8734efb46Sjohn stultz * This program is free software; you can redistribute it and/or modify 9734efb46Sjohn stultz * it under the terms of the GNU General Public License as published by 10734efb46Sjohn stultz * the Free Software Foundation; either version 2 of the License, or 11734efb46Sjohn stultz * (at your option) any later version. 12734efb46Sjohn stultz * 13734efb46Sjohn stultz * This program is distributed in the hope that it will be useful, 14734efb46Sjohn stultz * but WITHOUT ANY WARRANTY; without even the implied warranty of 15734efb46Sjohn stultz * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16734efb46Sjohn stultz * GNU General Public License for more details. 17734efb46Sjohn stultz * 18734efb46Sjohn stultz * You should have received a copy of the GNU General Public License 19734efb46Sjohn stultz * along with this program; if not, write to the Free Software 20734efb46Sjohn stultz * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21734efb46Sjohn stultz * 22734efb46Sjohn stultz * TODO WishList: 23734efb46Sjohn stultz * o Allow clocksource drivers to be unregistered 24734efb46Sjohn stultz */ 25734efb46Sjohn stultz 26d369a5d8SKay Sievers #include <linux/device.h> 27734efb46Sjohn stultz #include <linux/clocksource.h> 28734efb46Sjohn stultz #include <linux/init.h> 29734efb46Sjohn stultz #include <linux/module.h> 30dc29a365SMathieu Desnoyers #include <linux/sched.h> /* for spin_unlock_irq() using preempt_count() m68k */ 3179bf2bb3SThomas Gleixner #include <linux/tick.h> 3201548f4dSMartin Schwidefsky #include <linux/kthread.h> 33734efb46Sjohn stultz 3403e13cf5SThomas Gleixner #include "tick-internal.h" 353a978377SThomas Gleixner #include "timekeeping_internal.h" 3603e13cf5SThomas Gleixner 37a038a353SPatrick Ohly void timecounter_init(struct timecounter *tc, 38a038a353SPatrick Ohly const struct cyclecounter *cc, 39a038a353SPatrick Ohly u64 start_tstamp) 40a038a353SPatrick Ohly { 41a038a353SPatrick Ohly tc->cc = cc; 42a038a353SPatrick Ohly tc->cycle_last = cc->read(cc); 43a038a353SPatrick Ohly tc->nsec = start_tstamp; 44a038a353SPatrick Ohly } 453586e0a9SDavid S. Miller EXPORT_SYMBOL_GPL(timecounter_init); 46a038a353SPatrick Ohly 47a038a353SPatrick Ohly /** 48a038a353SPatrick Ohly * timecounter_read_delta - get nanoseconds since last call of this function 49a038a353SPatrick Ohly * @tc: Pointer to time counter 50a038a353SPatrick Ohly * 51a038a353SPatrick Ohly * When the underlying cycle counter runs over, this will be handled 52a038a353SPatrick Ohly * correctly as long as it does not run over more than once between 53a038a353SPatrick Ohly * calls. 54a038a353SPatrick Ohly * 55a038a353SPatrick Ohly * The first call to this function for a new time counter initializes 56a038a353SPatrick Ohly * the time tracking and returns an undefined result. 57a038a353SPatrick Ohly */ 58a038a353SPatrick Ohly static u64 timecounter_read_delta(struct timecounter *tc) 59a038a353SPatrick Ohly { 60a038a353SPatrick Ohly cycle_t cycle_now, cycle_delta; 61a038a353SPatrick Ohly u64 ns_offset; 62a038a353SPatrick Ohly 63a038a353SPatrick Ohly /* read cycle counter: */ 64a038a353SPatrick Ohly cycle_now = tc->cc->read(tc->cc); 65a038a353SPatrick Ohly 66a038a353SPatrick Ohly /* calculate the delta since the last timecounter_read_delta(): */ 67a038a353SPatrick Ohly cycle_delta = (cycle_now - tc->cycle_last) & tc->cc->mask; 68a038a353SPatrick Ohly 69a038a353SPatrick Ohly /* convert to nanoseconds: */ 70a038a353SPatrick Ohly ns_offset = cyclecounter_cyc2ns(tc->cc, cycle_delta); 71a038a353SPatrick Ohly 72a038a353SPatrick Ohly /* update time stamp of timecounter_read_delta() call: */ 73a038a353SPatrick Ohly tc->cycle_last = cycle_now; 74a038a353SPatrick Ohly 75a038a353SPatrick Ohly return ns_offset; 76a038a353SPatrick Ohly } 77a038a353SPatrick Ohly 78a038a353SPatrick Ohly u64 timecounter_read(struct timecounter *tc) 79a038a353SPatrick Ohly { 80a038a353SPatrick Ohly u64 nsec; 81a038a353SPatrick Ohly 82a038a353SPatrick Ohly /* increment time by nanoseconds since last call */ 83a038a353SPatrick Ohly nsec = timecounter_read_delta(tc); 84a038a353SPatrick Ohly nsec += tc->nsec; 85a038a353SPatrick Ohly tc->nsec = nsec; 86a038a353SPatrick Ohly 87a038a353SPatrick Ohly return nsec; 88a038a353SPatrick Ohly } 893586e0a9SDavid S. Miller EXPORT_SYMBOL_GPL(timecounter_read); 90a038a353SPatrick Ohly 91a038a353SPatrick Ohly u64 timecounter_cyc2time(struct timecounter *tc, 92a038a353SPatrick Ohly cycle_t cycle_tstamp) 93a038a353SPatrick Ohly { 94a038a353SPatrick Ohly u64 cycle_delta = (cycle_tstamp - tc->cycle_last) & tc->cc->mask; 95a038a353SPatrick Ohly u64 nsec; 96a038a353SPatrick Ohly 97a038a353SPatrick Ohly /* 98a038a353SPatrick Ohly * Instead of always treating cycle_tstamp as more recent 99a038a353SPatrick Ohly * than tc->cycle_last, detect when it is too far in the 100a038a353SPatrick Ohly * future and treat it as old time stamp instead. 101a038a353SPatrick Ohly */ 102a038a353SPatrick Ohly if (cycle_delta > tc->cc->mask / 2) { 103a038a353SPatrick Ohly cycle_delta = (tc->cycle_last - cycle_tstamp) & tc->cc->mask; 104a038a353SPatrick Ohly nsec = tc->nsec - cyclecounter_cyc2ns(tc->cc, cycle_delta); 105a038a353SPatrick Ohly } else { 106a038a353SPatrick Ohly nsec = cyclecounter_cyc2ns(tc->cc, cycle_delta) + tc->nsec; 107a038a353SPatrick Ohly } 108a038a353SPatrick Ohly 109a038a353SPatrick Ohly return nsec; 110a038a353SPatrick Ohly } 1113586e0a9SDavid S. Miller EXPORT_SYMBOL_GPL(timecounter_cyc2time); 112a038a353SPatrick Ohly 1137d2f944aSThomas Gleixner /** 1147d2f944aSThomas Gleixner * clocks_calc_mult_shift - calculate mult/shift factors for scaled math of clocks 1157d2f944aSThomas Gleixner * @mult: pointer to mult variable 1167d2f944aSThomas Gleixner * @shift: pointer to shift variable 1177d2f944aSThomas Gleixner * @from: frequency to convert from 1187d2f944aSThomas Gleixner * @to: frequency to convert to 1195fdade95SNicolas Pitre * @maxsec: guaranteed runtime conversion range in seconds 1207d2f944aSThomas Gleixner * 1217d2f944aSThomas Gleixner * The function evaluates the shift/mult pair for the scaled math 1227d2f944aSThomas Gleixner * operations of clocksources and clockevents. 1237d2f944aSThomas Gleixner * 1247d2f944aSThomas Gleixner * @to and @from are frequency values in HZ. For clock sources @to is 1257d2f944aSThomas Gleixner * NSEC_PER_SEC == 1GHz and @from is the counter frequency. For clock 1267d2f944aSThomas Gleixner * event @to is the counter frequency and @from is NSEC_PER_SEC. 1277d2f944aSThomas Gleixner * 1285fdade95SNicolas Pitre * The @maxsec conversion range argument controls the time frame in 1297d2f944aSThomas Gleixner * seconds which must be covered by the runtime conversion with the 1307d2f944aSThomas Gleixner * calculated mult and shift factors. This guarantees that no 64bit 1317d2f944aSThomas Gleixner * overflow happens when the input value of the conversion is 1327d2f944aSThomas Gleixner * multiplied with the calculated mult factor. Larger ranges may 1337d2f944aSThomas Gleixner * reduce the conversion accuracy by chosing smaller mult and shift 1347d2f944aSThomas Gleixner * factors. 1357d2f944aSThomas Gleixner */ 1367d2f944aSThomas Gleixner void 1375fdade95SNicolas Pitre clocks_calc_mult_shift(u32 *mult, u32 *shift, u32 from, u32 to, u32 maxsec) 1387d2f944aSThomas Gleixner { 1397d2f944aSThomas Gleixner u64 tmp; 1407d2f944aSThomas Gleixner u32 sft, sftacc= 32; 1417d2f944aSThomas Gleixner 1427d2f944aSThomas Gleixner /* 1437d2f944aSThomas Gleixner * Calculate the shift factor which is limiting the conversion 1447d2f944aSThomas Gleixner * range: 1457d2f944aSThomas Gleixner */ 1465fdade95SNicolas Pitre tmp = ((u64)maxsec * from) >> 32; 1477d2f944aSThomas Gleixner while (tmp) { 1487d2f944aSThomas Gleixner tmp >>=1; 1497d2f944aSThomas Gleixner sftacc--; 1507d2f944aSThomas Gleixner } 1517d2f944aSThomas Gleixner 1527d2f944aSThomas Gleixner /* 1537d2f944aSThomas Gleixner * Find the conversion shift/mult pair which has the best 1547d2f944aSThomas Gleixner * accuracy and fits the maxsec conversion range: 1557d2f944aSThomas Gleixner */ 1567d2f944aSThomas Gleixner for (sft = 32; sft > 0; sft--) { 1577d2f944aSThomas Gleixner tmp = (u64) to << sft; 158b5776c4aSjohn stultz tmp += from / 2; 1597d2f944aSThomas Gleixner do_div(tmp, from); 1607d2f944aSThomas Gleixner if ((tmp >> sftacc) == 0) 1617d2f944aSThomas Gleixner break; 1627d2f944aSThomas Gleixner } 1637d2f944aSThomas Gleixner *mult = tmp; 1647d2f944aSThomas Gleixner *shift = sft; 1657d2f944aSThomas Gleixner } 1667d2f944aSThomas Gleixner 167734efb46Sjohn stultz /*[Clocksource internal variables]--------- 168734efb46Sjohn stultz * curr_clocksource: 169f1b82746SMartin Schwidefsky * currently selected clocksource. 170734efb46Sjohn stultz * clocksource_list: 171734efb46Sjohn stultz * linked list with the registered clocksources 17275c5158fSMartin Schwidefsky * clocksource_mutex: 17375c5158fSMartin Schwidefsky * protects manipulations to curr_clocksource and the clocksource_list 174734efb46Sjohn stultz * override_name: 175734efb46Sjohn stultz * Name of the user-specified clocksource. 176734efb46Sjohn stultz */ 177f1b82746SMartin Schwidefsky static struct clocksource *curr_clocksource; 178734efb46Sjohn stultz static LIST_HEAD(clocksource_list); 17975c5158fSMartin Schwidefsky static DEFINE_MUTEX(clocksource_mutex); 18029b54078SThomas Gleixner static char override_name[CS_NAME_LEN]; 18154a6bc0bSThomas Gleixner static int finished_booting; 182734efb46Sjohn stultz 1835d8b34fdSThomas Gleixner #ifdef CONFIG_CLOCKSOURCE_WATCHDOG 184f79e0258SMartin Schwidefsky static void clocksource_watchdog_work(struct work_struct *work); 185332962f2SThomas Gleixner static void clocksource_select(void); 186f79e0258SMartin Schwidefsky 1875d8b34fdSThomas Gleixner static LIST_HEAD(watchdog_list); 1885d8b34fdSThomas Gleixner static struct clocksource *watchdog; 1895d8b34fdSThomas Gleixner static struct timer_list watchdog_timer; 190f79e0258SMartin Schwidefsky static DECLARE_WORK(watchdog_work, clocksource_watchdog_work); 1915d8b34fdSThomas Gleixner static DEFINE_SPINLOCK(watchdog_lock); 192fb63a0ebSMartin Schwidefsky static int watchdog_running; 1939fb60336SThomas Gleixner static atomic_t watchdog_reset_pending; 194b52f52a0SThomas Gleixner 19501548f4dSMartin Schwidefsky static int clocksource_watchdog_kthread(void *data); 196d0981a1bSThomas Gleixner static void __clocksource_change_rating(struct clocksource *cs, int rating); 197c55c87c8SMartin Schwidefsky 1985d8b34fdSThomas Gleixner /* 19935c35d1aSDaniel Walker * Interval: 0.5sec Threshold: 0.0625s 2005d8b34fdSThomas Gleixner */ 2015d8b34fdSThomas Gleixner #define WATCHDOG_INTERVAL (HZ >> 1) 20235c35d1aSDaniel Walker #define WATCHDOG_THRESHOLD (NSEC_PER_SEC >> 4) 2035d8b34fdSThomas Gleixner 20401548f4dSMartin Schwidefsky static void clocksource_watchdog_work(struct work_struct *work) 20501548f4dSMartin Schwidefsky { 20601548f4dSMartin Schwidefsky /* 20701548f4dSMartin Schwidefsky * If kthread_run fails the next watchdog scan over the 20801548f4dSMartin Schwidefsky * watchdog_list will find the unstable clock again. 20901548f4dSMartin Schwidefsky */ 21001548f4dSMartin Schwidefsky kthread_run(clocksource_watchdog_kthread, NULL, "kwatchdog"); 21101548f4dSMartin Schwidefsky } 21201548f4dSMartin Schwidefsky 2137285dd7fSThomas Gleixner static void __clocksource_unstable(struct clocksource *cs) 2147285dd7fSThomas Gleixner { 2157285dd7fSThomas Gleixner cs->flags &= ~(CLOCK_SOURCE_VALID_FOR_HRES | CLOCK_SOURCE_WATCHDOG); 2167285dd7fSThomas Gleixner cs->flags |= CLOCK_SOURCE_UNSTABLE; 21754a6bc0bSThomas Gleixner if (finished_booting) 2187285dd7fSThomas Gleixner schedule_work(&watchdog_work); 2197285dd7fSThomas Gleixner } 2207285dd7fSThomas Gleixner 2218cf4e750SMartin Schwidefsky static void clocksource_unstable(struct clocksource *cs, int64_t delta) 2225d8b34fdSThomas Gleixner { 2235d8b34fdSThomas Gleixner printk(KERN_WARNING "Clocksource %s unstable (delta = %Ld ns)\n", 2245d8b34fdSThomas Gleixner cs->name, delta); 2257285dd7fSThomas Gleixner __clocksource_unstable(cs); 2267285dd7fSThomas Gleixner } 2277285dd7fSThomas Gleixner 2287285dd7fSThomas Gleixner /** 2297285dd7fSThomas Gleixner * clocksource_mark_unstable - mark clocksource unstable via watchdog 2307285dd7fSThomas Gleixner * @cs: clocksource to be marked unstable 2317285dd7fSThomas Gleixner * 2327285dd7fSThomas Gleixner * This function is called instead of clocksource_change_rating from 2337285dd7fSThomas Gleixner * cpu hotplug code to avoid a deadlock between the clocksource mutex 2347285dd7fSThomas Gleixner * and the cpu hotplug mutex. It defers the update of the clocksource 2357285dd7fSThomas Gleixner * to the watchdog thread. 2367285dd7fSThomas Gleixner */ 2377285dd7fSThomas Gleixner void clocksource_mark_unstable(struct clocksource *cs) 2387285dd7fSThomas Gleixner { 2397285dd7fSThomas Gleixner unsigned long flags; 2407285dd7fSThomas Gleixner 2417285dd7fSThomas Gleixner spin_lock_irqsave(&watchdog_lock, flags); 2427285dd7fSThomas Gleixner if (!(cs->flags & CLOCK_SOURCE_UNSTABLE)) { 2437285dd7fSThomas Gleixner if (list_empty(&cs->wd_list)) 2447285dd7fSThomas Gleixner list_add(&cs->wd_list, &watchdog_list); 2457285dd7fSThomas Gleixner __clocksource_unstable(cs); 2467285dd7fSThomas Gleixner } 2477285dd7fSThomas Gleixner spin_unlock_irqrestore(&watchdog_lock, flags); 2485d8b34fdSThomas Gleixner } 2495d8b34fdSThomas Gleixner 2505d8b34fdSThomas Gleixner static void clocksource_watchdog(unsigned long data) 2515d8b34fdSThomas Gleixner { 252c55c87c8SMartin Schwidefsky struct clocksource *cs; 2533a978377SThomas Gleixner cycle_t csnow, wdnow, delta; 2545d8b34fdSThomas Gleixner int64_t wd_nsec, cs_nsec; 2559fb60336SThomas Gleixner int next_cpu, reset_pending; 2565d8b34fdSThomas Gleixner 2575d8b34fdSThomas Gleixner spin_lock(&watchdog_lock); 258fb63a0ebSMartin Schwidefsky if (!watchdog_running) 259fb63a0ebSMartin Schwidefsky goto out; 2605d8b34fdSThomas Gleixner 2619fb60336SThomas Gleixner reset_pending = atomic_read(&watchdog_reset_pending); 2629fb60336SThomas Gleixner 263c55c87c8SMartin Schwidefsky list_for_each_entry(cs, &watchdog_list, wd_list) { 264c55c87c8SMartin Schwidefsky 265c55c87c8SMartin Schwidefsky /* Clocksource already marked unstable? */ 26601548f4dSMartin Schwidefsky if (cs->flags & CLOCK_SOURCE_UNSTABLE) { 26754a6bc0bSThomas Gleixner if (finished_booting) 26801548f4dSMartin Schwidefsky schedule_work(&watchdog_work); 269c55c87c8SMartin Schwidefsky continue; 27001548f4dSMartin Schwidefsky } 271c55c87c8SMartin Schwidefsky 272b5199515SThomas Gleixner local_irq_disable(); 2738e19608eSMagnus Damm csnow = cs->read(cs); 274b5199515SThomas Gleixner wdnow = watchdog->read(watchdog); 275b5199515SThomas Gleixner local_irq_enable(); 276b52f52a0SThomas Gleixner 2778cf4e750SMartin Schwidefsky /* Clocksource initialized ? */ 2789fb60336SThomas Gleixner if (!(cs->flags & CLOCK_SOURCE_WATCHDOG) || 2799fb60336SThomas Gleixner atomic_read(&watchdog_reset_pending)) { 2808cf4e750SMartin Schwidefsky cs->flags |= CLOCK_SOURCE_WATCHDOG; 281b5199515SThomas Gleixner cs->wd_last = wdnow; 282b5199515SThomas Gleixner cs->cs_last = csnow; 283b52f52a0SThomas Gleixner continue; 284b52f52a0SThomas Gleixner } 285b52f52a0SThomas Gleixner 2863a978377SThomas Gleixner delta = clocksource_delta(wdnow, cs->wd_last, watchdog->mask); 2873a978377SThomas Gleixner wd_nsec = clocksource_cyc2ns(delta, watchdog->mult, 2883a978377SThomas Gleixner watchdog->shift); 289b5199515SThomas Gleixner 2903a978377SThomas Gleixner delta = clocksource_delta(csnow, cs->cs_last, cs->mask); 2913a978377SThomas Gleixner cs_nsec = clocksource_cyc2ns(delta, cs->mult, cs->shift); 292b5199515SThomas Gleixner cs->cs_last = csnow; 293b5199515SThomas Gleixner cs->wd_last = wdnow; 294b5199515SThomas Gleixner 2959fb60336SThomas Gleixner if (atomic_read(&watchdog_reset_pending)) 2969fb60336SThomas Gleixner continue; 2979fb60336SThomas Gleixner 298b5199515SThomas Gleixner /* Check the deviation from the watchdog clocksource. */ 2999fb60336SThomas Gleixner if ((abs(cs_nsec - wd_nsec) > WATCHDOG_THRESHOLD)) { 3008cf4e750SMartin Schwidefsky clocksource_unstable(cs, cs_nsec - wd_nsec); 3018cf4e750SMartin Schwidefsky continue; 3028cf4e750SMartin Schwidefsky } 3038cf4e750SMartin Schwidefsky 3048cf4e750SMartin Schwidefsky if (!(cs->flags & CLOCK_SOURCE_VALID_FOR_HRES) && 3058cf4e750SMartin Schwidefsky (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) && 3065d8b34fdSThomas Gleixner (watchdog->flags & CLOCK_SOURCE_IS_CONTINUOUS)) { 307332962f2SThomas Gleixner /* Mark it valid for high-res. */ 3085d8b34fdSThomas Gleixner cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES; 309332962f2SThomas Gleixner 31079bf2bb3SThomas Gleixner /* 311332962f2SThomas Gleixner * clocksource_done_booting() will sort it if 312332962f2SThomas Gleixner * finished_booting is not set yet. 31379bf2bb3SThomas Gleixner */ 314332962f2SThomas Gleixner if (!finished_booting) 315332962f2SThomas Gleixner continue; 316332962f2SThomas Gleixner 317332962f2SThomas Gleixner /* 318332962f2SThomas Gleixner * If this is not the current clocksource let 319332962f2SThomas Gleixner * the watchdog thread reselect it. Due to the 320332962f2SThomas Gleixner * change to high res this clocksource might 321332962f2SThomas Gleixner * be preferred now. If it is the current 322332962f2SThomas Gleixner * clocksource let the tick code know about 323332962f2SThomas Gleixner * that change. 324332962f2SThomas Gleixner */ 325332962f2SThomas Gleixner if (cs != curr_clocksource) { 326332962f2SThomas Gleixner cs->flags |= CLOCK_SOURCE_RESELECT; 327332962f2SThomas Gleixner schedule_work(&watchdog_work); 328332962f2SThomas Gleixner } else { 32979bf2bb3SThomas Gleixner tick_clock_notify(); 3305d8b34fdSThomas Gleixner } 3315d8b34fdSThomas Gleixner } 332332962f2SThomas Gleixner } 3335d8b34fdSThomas Gleixner 3346993fc5bSAndi Kleen /* 3359fb60336SThomas Gleixner * We only clear the watchdog_reset_pending, when we did a 3369fb60336SThomas Gleixner * full cycle through all clocksources. 3379fb60336SThomas Gleixner */ 3389fb60336SThomas Gleixner if (reset_pending) 3399fb60336SThomas Gleixner atomic_dec(&watchdog_reset_pending); 3409fb60336SThomas Gleixner 3419fb60336SThomas Gleixner /* 342c55c87c8SMartin Schwidefsky * Cycle through CPUs to check if the CPUs stay synchronized 343c55c87c8SMartin Schwidefsky * to each other. 3446993fc5bSAndi Kleen */ 345c55c87c8SMartin Schwidefsky next_cpu = cpumask_next(raw_smp_processor_id(), cpu_online_mask); 346cad0e458SMike Travis if (next_cpu >= nr_cpu_ids) 3476b954823SRusty Russell next_cpu = cpumask_first(cpu_online_mask); 3486993fc5bSAndi Kleen watchdog_timer.expires += WATCHDOG_INTERVAL; 3496993fc5bSAndi Kleen add_timer_on(&watchdog_timer, next_cpu); 350fb63a0ebSMartin Schwidefsky out: 3515d8b34fdSThomas Gleixner spin_unlock(&watchdog_lock); 3525d8b34fdSThomas Gleixner } 3530f8e8ef7SMartin Schwidefsky 354fb63a0ebSMartin Schwidefsky static inline void clocksource_start_watchdog(void) 355fb63a0ebSMartin Schwidefsky { 356fb63a0ebSMartin Schwidefsky if (watchdog_running || !watchdog || list_empty(&watchdog_list)) 357fb63a0ebSMartin Schwidefsky return; 358fb63a0ebSMartin Schwidefsky init_timer(&watchdog_timer); 359fb63a0ebSMartin Schwidefsky watchdog_timer.function = clocksource_watchdog; 360fb63a0ebSMartin Schwidefsky watchdog_timer.expires = jiffies + WATCHDOG_INTERVAL; 361fb63a0ebSMartin Schwidefsky add_timer_on(&watchdog_timer, cpumask_first(cpu_online_mask)); 362fb63a0ebSMartin Schwidefsky watchdog_running = 1; 363fb63a0ebSMartin Schwidefsky } 364fb63a0ebSMartin Schwidefsky 365fb63a0ebSMartin Schwidefsky static inline void clocksource_stop_watchdog(void) 366fb63a0ebSMartin Schwidefsky { 367fb63a0ebSMartin Schwidefsky if (!watchdog_running || (watchdog && !list_empty(&watchdog_list))) 368fb63a0ebSMartin Schwidefsky return; 369fb63a0ebSMartin Schwidefsky del_timer(&watchdog_timer); 370fb63a0ebSMartin Schwidefsky watchdog_running = 0; 371fb63a0ebSMartin Schwidefsky } 372fb63a0ebSMartin Schwidefsky 3730f8e8ef7SMartin Schwidefsky static inline void clocksource_reset_watchdog(void) 3740f8e8ef7SMartin Schwidefsky { 3750f8e8ef7SMartin Schwidefsky struct clocksource *cs; 3760f8e8ef7SMartin Schwidefsky 3770f8e8ef7SMartin Schwidefsky list_for_each_entry(cs, &watchdog_list, wd_list) 3780f8e8ef7SMartin Schwidefsky cs->flags &= ~CLOCK_SOURCE_WATCHDOG; 3790f8e8ef7SMartin Schwidefsky } 3800f8e8ef7SMartin Schwidefsky 381b52f52a0SThomas Gleixner static void clocksource_resume_watchdog(void) 382b52f52a0SThomas Gleixner { 3839fb60336SThomas Gleixner atomic_inc(&watchdog_reset_pending); 384b52f52a0SThomas Gleixner } 385b52f52a0SThomas Gleixner 386fb63a0ebSMartin Schwidefsky static void clocksource_enqueue_watchdog(struct clocksource *cs) 3875d8b34fdSThomas Gleixner { 3885d8b34fdSThomas Gleixner unsigned long flags; 3895d8b34fdSThomas Gleixner 3905d8b34fdSThomas Gleixner spin_lock_irqsave(&watchdog_lock, flags); 3915d8b34fdSThomas Gleixner if (cs->flags & CLOCK_SOURCE_MUST_VERIFY) { 392fb63a0ebSMartin Schwidefsky /* cs is a clocksource to be watched. */ 3935d8b34fdSThomas Gleixner list_add(&cs->wd_list, &watchdog_list); 394fb63a0ebSMartin Schwidefsky cs->flags &= ~CLOCK_SOURCE_WATCHDOG; 395948ac6d7SThomas Gleixner } else { 396fb63a0ebSMartin Schwidefsky /* cs is a watchdog. */ 397948ac6d7SThomas Gleixner if (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) 3985d8b34fdSThomas Gleixner cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES; 399fb63a0ebSMartin Schwidefsky /* Pick the best watchdog. */ 4005d8b34fdSThomas Gleixner if (!watchdog || cs->rating > watchdog->rating) { 4015d8b34fdSThomas Gleixner watchdog = cs; 4025d8b34fdSThomas Gleixner /* Reset watchdog cycles */ 4030f8e8ef7SMartin Schwidefsky clocksource_reset_watchdog(); 4045d8b34fdSThomas Gleixner } 4055d8b34fdSThomas Gleixner } 406fb63a0ebSMartin Schwidefsky /* Check if the watchdog timer needs to be started. */ 407fb63a0ebSMartin Schwidefsky clocksource_start_watchdog(); 4085d8b34fdSThomas Gleixner spin_unlock_irqrestore(&watchdog_lock, flags); 4095d8b34fdSThomas Gleixner } 410fb63a0ebSMartin Schwidefsky 411fb63a0ebSMartin Schwidefsky static void clocksource_dequeue_watchdog(struct clocksource *cs) 412fb63a0ebSMartin Schwidefsky { 413fb63a0ebSMartin Schwidefsky unsigned long flags; 414fb63a0ebSMartin Schwidefsky 415fb63a0ebSMartin Schwidefsky spin_lock_irqsave(&watchdog_lock, flags); 416a89c7edbSThomas Gleixner if (cs != watchdog) { 417fb63a0ebSMartin Schwidefsky if (cs->flags & CLOCK_SOURCE_MUST_VERIFY) { 418fb63a0ebSMartin Schwidefsky /* cs is a watched clocksource. */ 419fb63a0ebSMartin Schwidefsky list_del_init(&cs->wd_list); 420fb63a0ebSMartin Schwidefsky /* Check if the watchdog timer needs to be stopped. */ 421fb63a0ebSMartin Schwidefsky clocksource_stop_watchdog(); 422a89c7edbSThomas Gleixner } 423a89c7edbSThomas Gleixner } 424fb63a0ebSMartin Schwidefsky spin_unlock_irqrestore(&watchdog_lock, flags); 425fb63a0ebSMartin Schwidefsky } 426fb63a0ebSMartin Schwidefsky 427332962f2SThomas Gleixner static int __clocksource_watchdog_kthread(void) 428c55c87c8SMartin Schwidefsky { 429c55c87c8SMartin Schwidefsky struct clocksource *cs, *tmp; 430c55c87c8SMartin Schwidefsky unsigned long flags; 4316ea41d25SThomas Gleixner LIST_HEAD(unstable); 432332962f2SThomas Gleixner int select = 0; 433c55c87c8SMartin Schwidefsky 434c55c87c8SMartin Schwidefsky spin_lock_irqsave(&watchdog_lock, flags); 435332962f2SThomas Gleixner list_for_each_entry_safe(cs, tmp, &watchdog_list, wd_list) { 436c55c87c8SMartin Schwidefsky if (cs->flags & CLOCK_SOURCE_UNSTABLE) { 437c55c87c8SMartin Schwidefsky list_del_init(&cs->wd_list); 4386ea41d25SThomas Gleixner list_add(&cs->wd_list, &unstable); 439332962f2SThomas Gleixner select = 1; 440332962f2SThomas Gleixner } 441332962f2SThomas Gleixner if (cs->flags & CLOCK_SOURCE_RESELECT) { 442332962f2SThomas Gleixner cs->flags &= ~CLOCK_SOURCE_RESELECT; 443332962f2SThomas Gleixner select = 1; 444332962f2SThomas Gleixner } 445c55c87c8SMartin Schwidefsky } 446c55c87c8SMartin Schwidefsky /* Check if the watchdog timer needs to be stopped. */ 447c55c87c8SMartin Schwidefsky clocksource_stop_watchdog(); 4486ea41d25SThomas Gleixner spin_unlock_irqrestore(&watchdog_lock, flags); 4496ea41d25SThomas Gleixner 4506ea41d25SThomas Gleixner /* Needs to be done outside of watchdog lock */ 4516ea41d25SThomas Gleixner list_for_each_entry_safe(cs, tmp, &unstable, wd_list) { 4526ea41d25SThomas Gleixner list_del_init(&cs->wd_list); 453d0981a1bSThomas Gleixner __clocksource_change_rating(cs, 0); 4546ea41d25SThomas Gleixner } 455332962f2SThomas Gleixner return select; 456332962f2SThomas Gleixner } 457332962f2SThomas Gleixner 458332962f2SThomas Gleixner static int clocksource_watchdog_kthread(void *data) 459332962f2SThomas Gleixner { 460332962f2SThomas Gleixner mutex_lock(&clocksource_mutex); 461332962f2SThomas Gleixner if (__clocksource_watchdog_kthread()) 462332962f2SThomas Gleixner clocksource_select(); 463d0981a1bSThomas Gleixner mutex_unlock(&clocksource_mutex); 46401548f4dSMartin Schwidefsky return 0; 465c55c87c8SMartin Schwidefsky } 466c55c87c8SMartin Schwidefsky 4677eaeb343SThomas Gleixner static bool clocksource_is_watchdog(struct clocksource *cs) 4687eaeb343SThomas Gleixner { 4697eaeb343SThomas Gleixner return cs == watchdog; 4707eaeb343SThomas Gleixner } 4717eaeb343SThomas Gleixner 472fb63a0ebSMartin Schwidefsky #else /* CONFIG_CLOCKSOURCE_WATCHDOG */ 473fb63a0ebSMartin Schwidefsky 474fb63a0ebSMartin Schwidefsky static void clocksource_enqueue_watchdog(struct clocksource *cs) 4755d8b34fdSThomas Gleixner { 4765d8b34fdSThomas Gleixner if (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) 4775d8b34fdSThomas Gleixner cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES; 4785d8b34fdSThomas Gleixner } 479b52f52a0SThomas Gleixner 480fb63a0ebSMartin Schwidefsky static inline void clocksource_dequeue_watchdog(struct clocksource *cs) { } 481b52f52a0SThomas Gleixner static inline void clocksource_resume_watchdog(void) { } 482332962f2SThomas Gleixner static inline int __clocksource_watchdog_kthread(void) { return 0; } 4837eaeb343SThomas Gleixner static bool clocksource_is_watchdog(struct clocksource *cs) { return false; } 484397bbf6dSPrarit Bhargava void clocksource_mark_unstable(struct clocksource *cs) { } 485fb63a0ebSMartin Schwidefsky 486fb63a0ebSMartin Schwidefsky #endif /* CONFIG_CLOCKSOURCE_WATCHDOG */ 4875d8b34fdSThomas Gleixner 488734efb46Sjohn stultz /** 489c54a42b1SMagnus Damm * clocksource_suspend - suspend the clocksource(s) 490c54a42b1SMagnus Damm */ 491c54a42b1SMagnus Damm void clocksource_suspend(void) 492c54a42b1SMagnus Damm { 493c54a42b1SMagnus Damm struct clocksource *cs; 494c54a42b1SMagnus Damm 495c54a42b1SMagnus Damm list_for_each_entry_reverse(cs, &clocksource_list, list) 496c54a42b1SMagnus Damm if (cs->suspend) 497c54a42b1SMagnus Damm cs->suspend(cs); 498c54a42b1SMagnus Damm } 499c54a42b1SMagnus Damm 500c54a42b1SMagnus Damm /** 501b52f52a0SThomas Gleixner * clocksource_resume - resume the clocksource(s) 502b52f52a0SThomas Gleixner */ 503b52f52a0SThomas Gleixner void clocksource_resume(void) 504b52f52a0SThomas Gleixner { 5052e197586SMatthias Kaehlcke struct clocksource *cs; 506b52f52a0SThomas Gleixner 50775c5158fSMartin Schwidefsky list_for_each_entry(cs, &clocksource_list, list) 508b52f52a0SThomas Gleixner if (cs->resume) 50917622339SMagnus Damm cs->resume(cs); 510b52f52a0SThomas Gleixner 511b52f52a0SThomas Gleixner clocksource_resume_watchdog(); 512b52f52a0SThomas Gleixner } 513b52f52a0SThomas Gleixner 514b52f52a0SThomas Gleixner /** 5157c3078b6SJason Wessel * clocksource_touch_watchdog - Update watchdog 5167c3078b6SJason Wessel * 5177c3078b6SJason Wessel * Update the watchdog after exception contexts such as kgdb so as not 5187b7422a5SThomas Gleixner * to incorrectly trip the watchdog. This might fail when the kernel 5197b7422a5SThomas Gleixner * was stopped in code which holds watchdog_lock. 5207c3078b6SJason Wessel */ 5217c3078b6SJason Wessel void clocksource_touch_watchdog(void) 5227c3078b6SJason Wessel { 5237c3078b6SJason Wessel clocksource_resume_watchdog(); 5247c3078b6SJason Wessel } 5257c3078b6SJason Wessel 526734efb46Sjohn stultz /** 527d65670a7SJohn Stultz * clocksource_max_adjustment- Returns max adjustment amount 528d65670a7SJohn Stultz * @cs: Pointer to clocksource 529d65670a7SJohn Stultz * 530d65670a7SJohn Stultz */ 531d65670a7SJohn Stultz static u32 clocksource_max_adjustment(struct clocksource *cs) 532d65670a7SJohn Stultz { 533d65670a7SJohn Stultz u64 ret; 534d65670a7SJohn Stultz /* 53588b28adfSJim Cromie * We won't try to correct for more than 11% adjustments (110,000 ppm), 536d65670a7SJohn Stultz */ 537d65670a7SJohn Stultz ret = (u64)cs->mult * 11; 538d65670a7SJohn Stultz do_div(ret,100); 539d65670a7SJohn Stultz return (u32)ret; 540d65670a7SJohn Stultz } 541d65670a7SJohn Stultz 542d65670a7SJohn Stultz /** 54387d8b9ebSStephen Boyd * clocks_calc_max_nsecs - Returns maximum nanoseconds that can be converted 54487d8b9ebSStephen Boyd * @mult: cycle to nanosecond multiplier 54587d8b9ebSStephen Boyd * @shift: cycle to nanosecond divisor (power of two) 54687d8b9ebSStephen Boyd * @maxadj: maximum adjustment value to mult (~11%) 54787d8b9ebSStephen Boyd * @mask: bitmask for two's complement subtraction of non 64 bit counters 54898962465SJon Hunter */ 54987d8b9ebSStephen Boyd u64 clocks_calc_max_nsecs(u32 mult, u32 shift, u32 maxadj, u64 mask) 55098962465SJon Hunter { 55198962465SJon Hunter u64 max_nsecs, max_cycles; 55298962465SJon Hunter 55398962465SJon Hunter /* 55498962465SJon Hunter * Calculate the maximum number of cycles that we can pass to the 55598962465SJon Hunter * cyc2ns function without overflowing a 64-bit signed result. The 55687d8b9ebSStephen Boyd * maximum number of cycles is equal to ULLONG_MAX/(mult+maxadj) 557d65670a7SJohn Stultz * which is equivalent to the below. 55887d8b9ebSStephen Boyd * max_cycles < (2^63)/(mult + maxadj) 55987d8b9ebSStephen Boyd * max_cycles < 2^(log2((2^63)/(mult + maxadj))) 56087d8b9ebSStephen Boyd * max_cycles < 2^(log2(2^63) - log2(mult + maxadj)) 56187d8b9ebSStephen Boyd * max_cycles < 2^(63 - log2(mult + maxadj)) 56287d8b9ebSStephen Boyd * max_cycles < 1 << (63 - log2(mult + maxadj)) 56398962465SJon Hunter * Please note that we add 1 to the result of the log2 to account for 56498962465SJon Hunter * any rounding errors, ensure the above inequality is satisfied and 56598962465SJon Hunter * no overflow will occur. 56698962465SJon Hunter */ 56787d8b9ebSStephen Boyd max_cycles = 1ULL << (63 - (ilog2(mult + maxadj) + 1)); 56898962465SJon Hunter 56998962465SJon Hunter /* 57098962465SJon Hunter * The actual maximum number of cycles we can defer the clocksource is 57187d8b9ebSStephen Boyd * determined by the minimum of max_cycles and mask. 572d65670a7SJohn Stultz * Note: Here we subtract the maxadj to make sure we don't sleep for 573d65670a7SJohn Stultz * too long if there's a large negative adjustment. 57498962465SJon Hunter */ 57587d8b9ebSStephen Boyd max_cycles = min(max_cycles, mask); 57687d8b9ebSStephen Boyd max_nsecs = clocksource_cyc2ns(max_cycles, mult - maxadj, shift); 57798962465SJon Hunter 57887d8b9ebSStephen Boyd return max_nsecs; 57987d8b9ebSStephen Boyd } 58087d8b9ebSStephen Boyd 58187d8b9ebSStephen Boyd /** 58287d8b9ebSStephen Boyd * clocksource_max_deferment - Returns max time the clocksource can be deferred 58387d8b9ebSStephen Boyd * @cs: Pointer to clocksource 58487d8b9ebSStephen Boyd * 58587d8b9ebSStephen Boyd */ 58687d8b9ebSStephen Boyd static u64 clocksource_max_deferment(struct clocksource *cs) 58787d8b9ebSStephen Boyd { 58887d8b9ebSStephen Boyd u64 max_nsecs; 58987d8b9ebSStephen Boyd 59087d8b9ebSStephen Boyd max_nsecs = clocks_calc_max_nsecs(cs->mult, cs->shift, cs->maxadj, 59187d8b9ebSStephen Boyd cs->mask); 59298962465SJon Hunter /* 59398962465SJon Hunter * To ensure that the clocksource does not wrap whilst we are idle, 59498962465SJon Hunter * limit the time the clocksource can be deferred by 12.5%. Please 59598962465SJon Hunter * note a margin of 12.5% is used because this can be computed with 59698962465SJon Hunter * a shift, versus say 10% which would require division. 59798962465SJon Hunter */ 598b1f91966SYang Honggang (Joseph) return max_nsecs - (max_nsecs >> 3); 59998962465SJon Hunter } 60098962465SJon Hunter 601592913ecSJohn Stultz #ifndef CONFIG_ARCH_USES_GETTIMEOFFSET 602734efb46Sjohn stultz 603f5a2e343SThomas Gleixner static struct clocksource *clocksource_find_best(bool oneshot, bool skipcur) 6045d33b883SThomas Gleixner { 6055d33b883SThomas Gleixner struct clocksource *cs; 6065d33b883SThomas Gleixner 6075d33b883SThomas Gleixner if (!finished_booting || list_empty(&clocksource_list)) 6085d33b883SThomas Gleixner return NULL; 6095d33b883SThomas Gleixner 6105d33b883SThomas Gleixner /* 6115d33b883SThomas Gleixner * We pick the clocksource with the highest rating. If oneshot 6125d33b883SThomas Gleixner * mode is active, we pick the highres valid clocksource with 6135d33b883SThomas Gleixner * the best rating. 6145d33b883SThomas Gleixner */ 6155d33b883SThomas Gleixner list_for_each_entry(cs, &clocksource_list, list) { 616f5a2e343SThomas Gleixner if (skipcur && cs == curr_clocksource) 617f5a2e343SThomas Gleixner continue; 6185d33b883SThomas Gleixner if (oneshot && !(cs->flags & CLOCK_SOURCE_VALID_FOR_HRES)) 6195d33b883SThomas Gleixner continue; 6205d33b883SThomas Gleixner return cs; 6215d33b883SThomas Gleixner } 6225d33b883SThomas Gleixner return NULL; 6235d33b883SThomas Gleixner } 6245d33b883SThomas Gleixner 625f5a2e343SThomas Gleixner static void __clocksource_select(bool skipcur) 626734efb46Sjohn stultz { 6275d33b883SThomas Gleixner bool oneshot = tick_oneshot_mode_active(); 628f1b82746SMartin Schwidefsky struct clocksource *best, *cs; 6295d8b34fdSThomas Gleixner 6305d33b883SThomas Gleixner /* Find the best suitable clocksource */ 631f5a2e343SThomas Gleixner best = clocksource_find_best(oneshot, skipcur); 6325d33b883SThomas Gleixner if (!best) 633f1b82746SMartin Schwidefsky return; 6345d33b883SThomas Gleixner 635f1b82746SMartin Schwidefsky /* Check for the override clocksource. */ 636f1b82746SMartin Schwidefsky list_for_each_entry(cs, &clocksource_list, list) { 637f5a2e343SThomas Gleixner if (skipcur && cs == curr_clocksource) 638f5a2e343SThomas Gleixner continue; 639f1b82746SMartin Schwidefsky if (strcmp(cs->name, override_name) != 0) 640f1b82746SMartin Schwidefsky continue; 641f1b82746SMartin Schwidefsky /* 642f1b82746SMartin Schwidefsky * Check to make sure we don't switch to a non-highres 643f1b82746SMartin Schwidefsky * capable clocksource if the tick code is in oneshot 644f1b82746SMartin Schwidefsky * mode (highres or nohz) 645f1b82746SMartin Schwidefsky */ 6465d33b883SThomas Gleixner if (!(cs->flags & CLOCK_SOURCE_VALID_FOR_HRES) && oneshot) { 647f1b82746SMartin Schwidefsky /* Override clocksource cannot be used. */ 648f1b82746SMartin Schwidefsky printk(KERN_WARNING "Override clocksource %s is not " 649f1b82746SMartin Schwidefsky "HRT compatible. Cannot switch while in " 650f1b82746SMartin Schwidefsky "HRT/NOHZ mode\n", cs->name); 651f1b82746SMartin Schwidefsky override_name[0] = 0; 652f1b82746SMartin Schwidefsky } else 653f1b82746SMartin Schwidefsky /* Override clocksource can be used. */ 654f1b82746SMartin Schwidefsky best = cs; 655f1b82746SMartin Schwidefsky break; 656734efb46Sjohn stultz } 657ba919d1cSThomas Gleixner 658ba919d1cSThomas Gleixner if (curr_clocksource != best && !timekeeping_notify(best)) { 659ba919d1cSThomas Gleixner pr_info("Switched to clocksource %s\n", best->name); 66075c5158fSMartin Schwidefsky curr_clocksource = best; 661f1b82746SMartin Schwidefsky } 66275c5158fSMartin Schwidefsky } 66375c5158fSMartin Schwidefsky 664f5a2e343SThomas Gleixner /** 665f5a2e343SThomas Gleixner * clocksource_select - Select the best clocksource available 666f5a2e343SThomas Gleixner * 667f5a2e343SThomas Gleixner * Private function. Must hold clocksource_mutex when called. 668f5a2e343SThomas Gleixner * 669f5a2e343SThomas Gleixner * Select the clocksource with the best rating, or the clocksource, 670f5a2e343SThomas Gleixner * which is selected by userspace override. 671f5a2e343SThomas Gleixner */ 672f5a2e343SThomas Gleixner static void clocksource_select(void) 673f5a2e343SThomas Gleixner { 674f5a2e343SThomas Gleixner return __clocksource_select(false); 675f5a2e343SThomas Gleixner } 676f5a2e343SThomas Gleixner 6777eaeb343SThomas Gleixner static void clocksource_select_fallback(void) 6787eaeb343SThomas Gleixner { 6797eaeb343SThomas Gleixner return __clocksource_select(true); 6807eaeb343SThomas Gleixner } 6817eaeb343SThomas Gleixner 682592913ecSJohn Stultz #else /* !CONFIG_ARCH_USES_GETTIMEOFFSET */ 68354a6bc0bSThomas Gleixner 68454a6bc0bSThomas Gleixner static inline void clocksource_select(void) { } 6851eaff672SThomas Gleixner static inline void clocksource_select_fallback(void) { } 68654a6bc0bSThomas Gleixner 68754a6bc0bSThomas Gleixner #endif 68854a6bc0bSThomas Gleixner 68975c5158fSMartin Schwidefsky /* 69075c5158fSMartin Schwidefsky * clocksource_done_booting - Called near the end of core bootup 69175c5158fSMartin Schwidefsky * 69275c5158fSMartin Schwidefsky * Hack to avoid lots of clocksource churn at boot time. 69375c5158fSMartin Schwidefsky * We use fs_initcall because we want this to start before 69475c5158fSMartin Schwidefsky * device_initcall but after subsys_initcall. 69575c5158fSMartin Schwidefsky */ 69675c5158fSMartin Schwidefsky static int __init clocksource_done_booting(void) 69775c5158fSMartin Schwidefsky { 698ad6759fbSjohn stultz mutex_lock(&clocksource_mutex); 699ad6759fbSjohn stultz curr_clocksource = clocksource_default_clock(); 70075c5158fSMartin Schwidefsky finished_booting = 1; 70154a6bc0bSThomas Gleixner /* 70254a6bc0bSThomas Gleixner * Run the watchdog first to eliminate unstable clock sources 70354a6bc0bSThomas Gleixner */ 704332962f2SThomas Gleixner __clocksource_watchdog_kthread(); 70575c5158fSMartin Schwidefsky clocksource_select(); 706e6c73305SThomas Gleixner mutex_unlock(&clocksource_mutex); 70775c5158fSMartin Schwidefsky return 0; 70875c5158fSMartin Schwidefsky } 70975c5158fSMartin Schwidefsky fs_initcall(clocksource_done_booting); 710f1b82746SMartin Schwidefsky 71192c7e002SThomas Gleixner /* 71292c7e002SThomas Gleixner * Enqueue the clocksource sorted by rating 713734efb46Sjohn stultz */ 714f1b82746SMartin Schwidefsky static void clocksource_enqueue(struct clocksource *cs) 715734efb46Sjohn stultz { 716f1b82746SMartin Schwidefsky struct list_head *entry = &clocksource_list; 717f1b82746SMartin Schwidefsky struct clocksource *tmp; 718734efb46Sjohn stultz 719f1b82746SMartin Schwidefsky list_for_each_entry(tmp, &clocksource_list, list) 72092c7e002SThomas Gleixner /* Keep track of the place, where to insert */ 721f1b82746SMartin Schwidefsky if (tmp->rating >= cs->rating) 722f1b82746SMartin Schwidefsky entry = &tmp->list; 723f1b82746SMartin Schwidefsky list_add(&cs->list, entry); 724734efb46Sjohn stultz } 725734efb46Sjohn stultz 726d7e81c26SJohn Stultz /** 727852db46dSJohn Stultz * __clocksource_updatefreq_scale - Used update clocksource with new freq 728b1b73d09SKusanagi Kouichi * @cs: clocksource to be registered 729852db46dSJohn Stultz * @scale: Scale factor multiplied against freq to get clocksource hz 730852db46dSJohn Stultz * @freq: clocksource frequency (cycles per second) divided by scale 731852db46dSJohn Stultz * 732852db46dSJohn Stultz * This should only be called from the clocksource->enable() method. 733852db46dSJohn Stultz * 734852db46dSJohn Stultz * This *SHOULD NOT* be called directly! Please use the 735852db46dSJohn Stultz * clocksource_updatefreq_hz() or clocksource_updatefreq_khz helper functions. 736852db46dSJohn Stultz */ 737852db46dSJohn Stultz void __clocksource_updatefreq_scale(struct clocksource *cs, u32 scale, u32 freq) 738852db46dSJohn Stultz { 739c0e299b1SThomas Gleixner u64 sec; 740852db46dSJohn Stultz /* 741724ed53eSThomas Gleixner * Calc the maximum number of seconds which we can run before 742724ed53eSThomas Gleixner * wrapping around. For clocksources which have a mask > 32bit 743724ed53eSThomas Gleixner * we need to limit the max sleep time to have a good 744724ed53eSThomas Gleixner * conversion precision. 10 minutes is still a reasonable 745724ed53eSThomas Gleixner * amount. That results in a shift value of 24 for a 746724ed53eSThomas Gleixner * clocksource with mask >= 40bit and f >= 4GHz. That maps to 747724ed53eSThomas Gleixner * ~ 0.06ppm granularity for NTP. We apply the same 12.5% 748724ed53eSThomas Gleixner * margin as we do in clocksource_max_deferment() 749852db46dSJohn Stultz */ 750b1f91966SYang Honggang (Joseph) sec = (cs->mask - (cs->mask >> 3)); 751724ed53eSThomas Gleixner do_div(sec, freq); 752724ed53eSThomas Gleixner do_div(sec, scale); 753724ed53eSThomas Gleixner if (!sec) 754724ed53eSThomas Gleixner sec = 1; 755724ed53eSThomas Gleixner else if (sec > 600 && cs->mask > UINT_MAX) 756724ed53eSThomas Gleixner sec = 600; 757724ed53eSThomas Gleixner 758852db46dSJohn Stultz clocks_calc_mult_shift(&cs->mult, &cs->shift, freq, 759724ed53eSThomas Gleixner NSEC_PER_SEC / scale, sec * scale); 760d65670a7SJohn Stultz 761d65670a7SJohn Stultz /* 762d65670a7SJohn Stultz * for clocksources that have large mults, to avoid overflow. 763d65670a7SJohn Stultz * Since mult may be adjusted by ntp, add an safety extra margin 764d65670a7SJohn Stultz * 765d65670a7SJohn Stultz */ 766d65670a7SJohn Stultz cs->maxadj = clocksource_max_adjustment(cs); 767d65670a7SJohn Stultz while ((cs->mult + cs->maxadj < cs->mult) 768d65670a7SJohn Stultz || (cs->mult - cs->maxadj > cs->mult)) { 769d65670a7SJohn Stultz cs->mult >>= 1; 770d65670a7SJohn Stultz cs->shift--; 771d65670a7SJohn Stultz cs->maxadj = clocksource_max_adjustment(cs); 772d65670a7SJohn Stultz } 773d65670a7SJohn Stultz 774852db46dSJohn Stultz cs->max_idle_ns = clocksource_max_deferment(cs); 775852db46dSJohn Stultz } 776852db46dSJohn Stultz EXPORT_SYMBOL_GPL(__clocksource_updatefreq_scale); 777852db46dSJohn Stultz 778852db46dSJohn Stultz /** 779d7e81c26SJohn Stultz * __clocksource_register_scale - Used to install new clocksources 780b1b73d09SKusanagi Kouichi * @cs: clocksource to be registered 781d7e81c26SJohn Stultz * @scale: Scale factor multiplied against freq to get clocksource hz 782d7e81c26SJohn Stultz * @freq: clocksource frequency (cycles per second) divided by scale 783d7e81c26SJohn Stultz * 784d7e81c26SJohn Stultz * Returns -EBUSY if registration fails, zero otherwise. 785d7e81c26SJohn Stultz * 786d7e81c26SJohn Stultz * This *SHOULD NOT* be called directly! Please use the 787d7e81c26SJohn Stultz * clocksource_register_hz() or clocksource_register_khz helper functions. 788d7e81c26SJohn Stultz */ 789d7e81c26SJohn Stultz int __clocksource_register_scale(struct clocksource *cs, u32 scale, u32 freq) 790d7e81c26SJohn Stultz { 791d7e81c26SJohn Stultz 792b595076aSUwe Kleine-König /* Initialize mult/shift and max_idle_ns */ 793852db46dSJohn Stultz __clocksource_updatefreq_scale(cs, scale, freq); 794d7e81c26SJohn Stultz 795be278e98SJames Hartley /* Add clocksource to the clocksource list */ 796d7e81c26SJohn Stultz mutex_lock(&clocksource_mutex); 797d7e81c26SJohn Stultz clocksource_enqueue(cs); 798d7e81c26SJohn Stultz clocksource_enqueue_watchdog(cs); 799e05b2efbSjohn stultz clocksource_select(); 800d7e81c26SJohn Stultz mutex_unlock(&clocksource_mutex); 801d7e81c26SJohn Stultz return 0; 802d7e81c26SJohn Stultz } 803d7e81c26SJohn Stultz EXPORT_SYMBOL_GPL(__clocksource_register_scale); 804d7e81c26SJohn Stultz 805d7e81c26SJohn Stultz 806734efb46Sjohn stultz /** 807a2752549Sjohn stultz * clocksource_register - Used to install new clocksources 808b1b73d09SKusanagi Kouichi * @cs: clocksource to be registered 809734efb46Sjohn stultz * 810734efb46Sjohn stultz * Returns -EBUSY if registration fails, zero otherwise. 811734efb46Sjohn stultz */ 812f1b82746SMartin Schwidefsky int clocksource_register(struct clocksource *cs) 813734efb46Sjohn stultz { 814d65670a7SJohn Stultz /* calculate max adjustment for given mult/shift */ 815d65670a7SJohn Stultz cs->maxadj = clocksource_max_adjustment(cs); 816d65670a7SJohn Stultz WARN_ONCE(cs->mult + cs->maxadj < cs->mult, 817d65670a7SJohn Stultz "Clocksource %s might overflow on 11%% adjustment\n", 818d65670a7SJohn Stultz cs->name); 819d65670a7SJohn Stultz 82098962465SJon Hunter /* calculate max idle time permitted for this clocksource */ 82198962465SJon Hunter cs->max_idle_ns = clocksource_max_deferment(cs); 82298962465SJon Hunter 82375c5158fSMartin Schwidefsky mutex_lock(&clocksource_mutex); 824f1b82746SMartin Schwidefsky clocksource_enqueue(cs); 825fb63a0ebSMartin Schwidefsky clocksource_enqueue_watchdog(cs); 826e05b2efbSjohn stultz clocksource_select(); 82775c5158fSMartin Schwidefsky mutex_unlock(&clocksource_mutex); 828f1b82746SMartin Schwidefsky return 0; 829734efb46Sjohn stultz } 830a2752549Sjohn stultz EXPORT_SYMBOL(clocksource_register); 831734efb46Sjohn stultz 832d0981a1bSThomas Gleixner static void __clocksource_change_rating(struct clocksource *cs, int rating) 833d0981a1bSThomas Gleixner { 834d0981a1bSThomas Gleixner list_del(&cs->list); 835d0981a1bSThomas Gleixner cs->rating = rating; 836d0981a1bSThomas Gleixner clocksource_enqueue(cs); 837d0981a1bSThomas Gleixner } 838d0981a1bSThomas Gleixner 839734efb46Sjohn stultz /** 84092c7e002SThomas Gleixner * clocksource_change_rating - Change the rating of a registered clocksource 841b1b73d09SKusanagi Kouichi * @cs: clocksource to be changed 842b1b73d09SKusanagi Kouichi * @rating: new rating 843734efb46Sjohn stultz */ 84492c7e002SThomas Gleixner void clocksource_change_rating(struct clocksource *cs, int rating) 845734efb46Sjohn stultz { 84675c5158fSMartin Schwidefsky mutex_lock(&clocksource_mutex); 847d0981a1bSThomas Gleixner __clocksource_change_rating(cs, rating); 848332962f2SThomas Gleixner clocksource_select(); 84975c5158fSMartin Schwidefsky mutex_unlock(&clocksource_mutex); 850734efb46Sjohn stultz } 851fb63a0ebSMartin Schwidefsky EXPORT_SYMBOL(clocksource_change_rating); 852734efb46Sjohn stultz 8537eaeb343SThomas Gleixner /* 8547eaeb343SThomas Gleixner * Unbind clocksource @cs. Called with clocksource_mutex held 8557eaeb343SThomas Gleixner */ 8567eaeb343SThomas Gleixner static int clocksource_unbind(struct clocksource *cs) 8577eaeb343SThomas Gleixner { 8587eaeb343SThomas Gleixner /* 8597eaeb343SThomas Gleixner * I really can't convince myself to support this on hardware 8607eaeb343SThomas Gleixner * designed by lobotomized monkeys. 8617eaeb343SThomas Gleixner */ 8627eaeb343SThomas Gleixner if (clocksource_is_watchdog(cs)) 8637eaeb343SThomas Gleixner return -EBUSY; 8647eaeb343SThomas Gleixner 8657eaeb343SThomas Gleixner if (cs == curr_clocksource) { 8667eaeb343SThomas Gleixner /* Select and try to install a replacement clock source */ 8677eaeb343SThomas Gleixner clocksource_select_fallback(); 8687eaeb343SThomas Gleixner if (curr_clocksource == cs) 8697eaeb343SThomas Gleixner return -EBUSY; 8707eaeb343SThomas Gleixner } 8717eaeb343SThomas Gleixner clocksource_dequeue_watchdog(cs); 8727eaeb343SThomas Gleixner list_del_init(&cs->list); 8737eaeb343SThomas Gleixner return 0; 8747eaeb343SThomas Gleixner } 8757eaeb343SThomas Gleixner 8764713e22cSThomas Gleixner /** 8774713e22cSThomas Gleixner * clocksource_unregister - remove a registered clocksource 878b1b73d09SKusanagi Kouichi * @cs: clocksource to be unregistered 8794713e22cSThomas Gleixner */ 880a89c7edbSThomas Gleixner int clocksource_unregister(struct clocksource *cs) 8814713e22cSThomas Gleixner { 882a89c7edbSThomas Gleixner int ret = 0; 883a89c7edbSThomas Gleixner 88475c5158fSMartin Schwidefsky mutex_lock(&clocksource_mutex); 885a89c7edbSThomas Gleixner if (!list_empty(&cs->list)) 886a89c7edbSThomas Gleixner ret = clocksource_unbind(cs); 88775c5158fSMartin Schwidefsky mutex_unlock(&clocksource_mutex); 888a89c7edbSThomas Gleixner return ret; 8894713e22cSThomas Gleixner } 890fb63a0ebSMartin Schwidefsky EXPORT_SYMBOL(clocksource_unregister); 8914713e22cSThomas Gleixner 8922b013700SDaniel Walker #ifdef CONFIG_SYSFS 893734efb46Sjohn stultz /** 894734efb46Sjohn stultz * sysfs_show_current_clocksources - sysfs interface for current clocksource 895734efb46Sjohn stultz * @dev: unused 896b1b73d09SKusanagi Kouichi * @attr: unused 897734efb46Sjohn stultz * @buf: char buffer to be filled with clocksource list 898734efb46Sjohn stultz * 899734efb46Sjohn stultz * Provides sysfs interface for listing current clocksource. 900734efb46Sjohn stultz */ 901734efb46Sjohn stultz static ssize_t 902d369a5d8SKay Sievers sysfs_show_current_clocksources(struct device *dev, 903d369a5d8SKay Sievers struct device_attribute *attr, char *buf) 904734efb46Sjohn stultz { 9055e2cb101SMiao Xie ssize_t count = 0; 906734efb46Sjohn stultz 90775c5158fSMartin Schwidefsky mutex_lock(&clocksource_mutex); 9085e2cb101SMiao Xie count = snprintf(buf, PAGE_SIZE, "%s\n", curr_clocksource->name); 90975c5158fSMartin Schwidefsky mutex_unlock(&clocksource_mutex); 910734efb46Sjohn stultz 9115e2cb101SMiao Xie return count; 912734efb46Sjohn stultz } 913734efb46Sjohn stultz 914891292a7SPatrick Palka ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt) 91529b54078SThomas Gleixner { 91629b54078SThomas Gleixner size_t ret = cnt; 91729b54078SThomas Gleixner 91829b54078SThomas Gleixner /* strings from sysfs write are not 0 terminated! */ 91929b54078SThomas Gleixner if (!cnt || cnt >= CS_NAME_LEN) 92029b54078SThomas Gleixner return -EINVAL; 92129b54078SThomas Gleixner 92229b54078SThomas Gleixner /* strip of \n: */ 92329b54078SThomas Gleixner if (buf[cnt-1] == '\n') 92429b54078SThomas Gleixner cnt--; 92529b54078SThomas Gleixner if (cnt > 0) 92629b54078SThomas Gleixner memcpy(dst, buf, cnt); 92729b54078SThomas Gleixner dst[cnt] = 0; 92829b54078SThomas Gleixner return ret; 92929b54078SThomas Gleixner } 93029b54078SThomas Gleixner 931734efb46Sjohn stultz /** 932734efb46Sjohn stultz * sysfs_override_clocksource - interface for manually overriding clocksource 933734efb46Sjohn stultz * @dev: unused 934b1b73d09SKusanagi Kouichi * @attr: unused 935734efb46Sjohn stultz * @buf: name of override clocksource 936734efb46Sjohn stultz * @count: length of buffer 937734efb46Sjohn stultz * 938734efb46Sjohn stultz * Takes input from sysfs interface for manually overriding the default 939b71a8eb0SUwe Kleine-König * clocksource selection. 940734efb46Sjohn stultz */ 941d369a5d8SKay Sievers static ssize_t sysfs_override_clocksource(struct device *dev, 942d369a5d8SKay Sievers struct device_attribute *attr, 943734efb46Sjohn stultz const char *buf, size_t count) 944734efb46Sjohn stultz { 945233bcb41SElad Wexler ssize_t ret; 946734efb46Sjohn stultz 94775c5158fSMartin Schwidefsky mutex_lock(&clocksource_mutex); 948734efb46Sjohn stultz 94903e13cf5SThomas Gleixner ret = sysfs_get_uname(buf, override_name, count); 95029b54078SThomas Gleixner if (ret >= 0) 951f1b82746SMartin Schwidefsky clocksource_select(); 952734efb46Sjohn stultz 95375c5158fSMartin Schwidefsky mutex_unlock(&clocksource_mutex); 954734efb46Sjohn stultz 955734efb46Sjohn stultz return ret; 956734efb46Sjohn stultz } 957734efb46Sjohn stultz 958734efb46Sjohn stultz /** 9597eaeb343SThomas Gleixner * sysfs_unbind_current_clocksource - interface for manually unbinding clocksource 9607eaeb343SThomas Gleixner * @dev: unused 9617eaeb343SThomas Gleixner * @attr: unused 9627eaeb343SThomas Gleixner * @buf: unused 9637eaeb343SThomas Gleixner * @count: length of buffer 9647eaeb343SThomas Gleixner * 9657eaeb343SThomas Gleixner * Takes input from sysfs interface for manually unbinding a clocksource. 9667eaeb343SThomas Gleixner */ 9677eaeb343SThomas Gleixner static ssize_t sysfs_unbind_clocksource(struct device *dev, 9687eaeb343SThomas Gleixner struct device_attribute *attr, 9697eaeb343SThomas Gleixner const char *buf, size_t count) 9707eaeb343SThomas Gleixner { 9717eaeb343SThomas Gleixner struct clocksource *cs; 9727eaeb343SThomas Gleixner char name[CS_NAME_LEN]; 973233bcb41SElad Wexler ssize_t ret; 9747eaeb343SThomas Gleixner 97503e13cf5SThomas Gleixner ret = sysfs_get_uname(buf, name, count); 9767eaeb343SThomas Gleixner if (ret < 0) 9777eaeb343SThomas Gleixner return ret; 9787eaeb343SThomas Gleixner 9797eaeb343SThomas Gleixner ret = -ENODEV; 9807eaeb343SThomas Gleixner mutex_lock(&clocksource_mutex); 9817eaeb343SThomas Gleixner list_for_each_entry(cs, &clocksource_list, list) { 9827eaeb343SThomas Gleixner if (strcmp(cs->name, name)) 9837eaeb343SThomas Gleixner continue; 9847eaeb343SThomas Gleixner ret = clocksource_unbind(cs); 9857eaeb343SThomas Gleixner break; 9867eaeb343SThomas Gleixner } 9877eaeb343SThomas Gleixner mutex_unlock(&clocksource_mutex); 9887eaeb343SThomas Gleixner 9897eaeb343SThomas Gleixner return ret ? ret : count; 9907eaeb343SThomas Gleixner } 9917eaeb343SThomas Gleixner 9927eaeb343SThomas Gleixner /** 993734efb46Sjohn stultz * sysfs_show_available_clocksources - sysfs interface for listing clocksource 994734efb46Sjohn stultz * @dev: unused 995b1b73d09SKusanagi Kouichi * @attr: unused 996734efb46Sjohn stultz * @buf: char buffer to be filled with clocksource list 997734efb46Sjohn stultz * 998734efb46Sjohn stultz * Provides sysfs interface for listing registered clocksources 999734efb46Sjohn stultz */ 1000734efb46Sjohn stultz static ssize_t 1001d369a5d8SKay Sievers sysfs_show_available_clocksources(struct device *dev, 1002d369a5d8SKay Sievers struct device_attribute *attr, 10034a0b2b4dSAndi Kleen char *buf) 1004734efb46Sjohn stultz { 10052e197586SMatthias Kaehlcke struct clocksource *src; 10065e2cb101SMiao Xie ssize_t count = 0; 1007734efb46Sjohn stultz 100875c5158fSMartin Schwidefsky mutex_lock(&clocksource_mutex); 10092e197586SMatthias Kaehlcke list_for_each_entry(src, &clocksource_list, list) { 1010cd6d95d8SThomas Gleixner /* 1011cd6d95d8SThomas Gleixner * Don't show non-HRES clocksource if the tick code is 1012cd6d95d8SThomas Gleixner * in one shot mode (highres=on or nohz=on) 1013cd6d95d8SThomas Gleixner */ 1014cd6d95d8SThomas Gleixner if (!tick_oneshot_mode_active() || 10153f68535aSjohn stultz (src->flags & CLOCK_SOURCE_VALID_FOR_HRES)) 10165e2cb101SMiao Xie count += snprintf(buf + count, 10175e2cb101SMiao Xie max((ssize_t)PAGE_SIZE - count, (ssize_t)0), 10185e2cb101SMiao Xie "%s ", src->name); 1019734efb46Sjohn stultz } 102075c5158fSMartin Schwidefsky mutex_unlock(&clocksource_mutex); 1021734efb46Sjohn stultz 10225e2cb101SMiao Xie count += snprintf(buf + count, 10235e2cb101SMiao Xie max((ssize_t)PAGE_SIZE - count, (ssize_t)0), "\n"); 1024734efb46Sjohn stultz 10255e2cb101SMiao Xie return count; 1026734efb46Sjohn stultz } 1027734efb46Sjohn stultz 1028734efb46Sjohn stultz /* 1029734efb46Sjohn stultz * Sysfs setup bits: 1030734efb46Sjohn stultz */ 1031d369a5d8SKay Sievers static DEVICE_ATTR(current_clocksource, 0644, sysfs_show_current_clocksources, 1032734efb46Sjohn stultz sysfs_override_clocksource); 1033734efb46Sjohn stultz 10347eaeb343SThomas Gleixner static DEVICE_ATTR(unbind_clocksource, 0200, NULL, sysfs_unbind_clocksource); 10357eaeb343SThomas Gleixner 1036d369a5d8SKay Sievers static DEVICE_ATTR(available_clocksource, 0444, 1037734efb46Sjohn stultz sysfs_show_available_clocksources, NULL); 1038734efb46Sjohn stultz 1039d369a5d8SKay Sievers static struct bus_type clocksource_subsys = { 1040af5ca3f4SKay Sievers .name = "clocksource", 1041d369a5d8SKay Sievers .dev_name = "clocksource", 1042734efb46Sjohn stultz }; 1043734efb46Sjohn stultz 1044d369a5d8SKay Sievers static struct device device_clocksource = { 1045734efb46Sjohn stultz .id = 0, 1046d369a5d8SKay Sievers .bus = &clocksource_subsys, 1047734efb46Sjohn stultz }; 1048734efb46Sjohn stultz 1049ad596171Sjohn stultz static int __init init_clocksource_sysfs(void) 1050734efb46Sjohn stultz { 1051d369a5d8SKay Sievers int error = subsys_system_register(&clocksource_subsys, NULL); 1052734efb46Sjohn stultz 1053734efb46Sjohn stultz if (!error) 1054d369a5d8SKay Sievers error = device_register(&device_clocksource); 1055734efb46Sjohn stultz if (!error) 1056d369a5d8SKay Sievers error = device_create_file( 1057734efb46Sjohn stultz &device_clocksource, 1058d369a5d8SKay Sievers &dev_attr_current_clocksource); 1059734efb46Sjohn stultz if (!error) 10607eaeb343SThomas Gleixner error = device_create_file(&device_clocksource, 10617eaeb343SThomas Gleixner &dev_attr_unbind_clocksource); 10627eaeb343SThomas Gleixner if (!error) 1063d369a5d8SKay Sievers error = device_create_file( 1064734efb46Sjohn stultz &device_clocksource, 1065d369a5d8SKay Sievers &dev_attr_available_clocksource); 1066734efb46Sjohn stultz return error; 1067734efb46Sjohn stultz } 1068734efb46Sjohn stultz 1069734efb46Sjohn stultz device_initcall(init_clocksource_sysfs); 10702b013700SDaniel Walker #endif /* CONFIG_SYSFS */ 1071734efb46Sjohn stultz 1072734efb46Sjohn stultz /** 1073734efb46Sjohn stultz * boot_override_clocksource - boot clock override 1074734efb46Sjohn stultz * @str: override name 1075734efb46Sjohn stultz * 1076734efb46Sjohn stultz * Takes a clocksource= boot argument and uses it 1077734efb46Sjohn stultz * as the clocksource override name. 1078734efb46Sjohn stultz */ 1079734efb46Sjohn stultz static int __init boot_override_clocksource(char* str) 1080734efb46Sjohn stultz { 108175c5158fSMartin Schwidefsky mutex_lock(&clocksource_mutex); 1082734efb46Sjohn stultz if (str) 1083734efb46Sjohn stultz strlcpy(override_name, str, sizeof(override_name)); 108475c5158fSMartin Schwidefsky mutex_unlock(&clocksource_mutex); 1085734efb46Sjohn stultz return 1; 1086734efb46Sjohn stultz } 1087734efb46Sjohn stultz 1088734efb46Sjohn stultz __setup("clocksource=", boot_override_clocksource); 1089734efb46Sjohn stultz 1090734efb46Sjohn stultz /** 1091734efb46Sjohn stultz * boot_override_clock - Compatibility layer for deprecated boot option 1092734efb46Sjohn stultz * @str: override name 1093734efb46Sjohn stultz * 1094734efb46Sjohn stultz * DEPRECATED! Takes a clock= boot argument and uses it 1095734efb46Sjohn stultz * as the clocksource override name 1096734efb46Sjohn stultz */ 1097734efb46Sjohn stultz static int __init boot_override_clock(char* str) 1098734efb46Sjohn stultz { 10995d0cf410Sjohn stultz if (!strcmp(str, "pmtmr")) { 11005d0cf410Sjohn stultz printk("Warning: clock=pmtmr is deprecated. " 11015d0cf410Sjohn stultz "Use clocksource=acpi_pm.\n"); 11025d0cf410Sjohn stultz return boot_override_clocksource("acpi_pm"); 11035d0cf410Sjohn stultz } 11045d0cf410Sjohn stultz printk("Warning! clock= boot option is deprecated. " 11055d0cf410Sjohn stultz "Use clocksource=xyz\n"); 1106734efb46Sjohn stultz return boot_override_clocksource(str); 1107734efb46Sjohn stultz } 1108734efb46Sjohn stultz 1109734efb46Sjohn stultz __setup("clock=", boot_override_clock); 1110