diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/time.c | 88 | ||||
-rw-r--r-- | kernel/time/ntp.c | 10 | ||||
-rw-r--r-- | kernel/time/timekeeping.c | 4 | ||||
-rw-r--r-- | kernel/timer.c | 188 |
4 files changed, 0 insertions, 290 deletions
diff --git a/kernel/time.c b/kernel/time.c index ffe19149d770..e325597f5bf5 100644 --- a/kernel/time.c +++ b/kernel/time.c | |||
@@ -136,7 +136,6 @@ static inline void warp_clock(void) | |||
136 | write_seqlock_irq(&xtime_lock); | 136 | write_seqlock_irq(&xtime_lock); |
137 | wall_to_monotonic.tv_sec -= sys_tz.tz_minuteswest * 60; | 137 | wall_to_monotonic.tv_sec -= sys_tz.tz_minuteswest * 60; |
138 | xtime.tv_sec += sys_tz.tz_minuteswest * 60; | 138 | xtime.tv_sec += sys_tz.tz_minuteswest * 60; |
139 | time_interpolator_reset(); | ||
140 | write_sequnlock_irq(&xtime_lock); | 139 | write_sequnlock_irq(&xtime_lock); |
141 | clock_was_set(); | 140 | clock_was_set(); |
142 | } | 141 | } |
@@ -309,92 +308,6 @@ struct timespec timespec_trunc(struct timespec t, unsigned gran) | |||
309 | } | 308 | } |
310 | EXPORT_SYMBOL(timespec_trunc); | 309 | EXPORT_SYMBOL(timespec_trunc); |
311 | 310 | ||
312 | #ifdef CONFIG_TIME_INTERPOLATION | ||
313 | void getnstimeofday (struct timespec *tv) | ||
314 | { | ||
315 | unsigned long seq,sec,nsec; | ||
316 | |||
317 | do { | ||
318 | seq = read_seqbegin(&xtime_lock); | ||
319 | sec = xtime.tv_sec; | ||
320 | nsec = xtime.tv_nsec+time_interpolator_get_offset(); | ||
321 | } while (unlikely(read_seqretry(&xtime_lock, seq))); | ||
322 | |||
323 | while (unlikely(nsec >= NSEC_PER_SEC)) { | ||
324 | nsec -= NSEC_PER_SEC; | ||
325 | ++sec; | ||
326 | } | ||
327 | tv->tv_sec = sec; | ||
328 | tv->tv_nsec = nsec; | ||
329 | } | ||
330 | EXPORT_SYMBOL_GPL(getnstimeofday); | ||
331 | |||
332 | int do_settimeofday (struct timespec *tv) | ||
333 | { | ||
334 | time_t wtm_sec, sec = tv->tv_sec; | ||
335 | long wtm_nsec, nsec = tv->tv_nsec; | ||
336 | |||
337 | if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) | ||
338 | return -EINVAL; | ||
339 | |||
340 | write_seqlock_irq(&xtime_lock); | ||
341 | { | ||
342 | wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); | ||
343 | wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); | ||
344 | |||
345 | set_normalized_timespec(&xtime, sec, nsec); | ||
346 | set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); | ||
347 | |||
348 | time_adjust = 0; /* stop active adjtime() */ | ||
349 | time_status |= STA_UNSYNC; | ||
350 | time_maxerror = NTP_PHASE_LIMIT; | ||
351 | time_esterror = NTP_PHASE_LIMIT; | ||
352 | time_interpolator_reset(); | ||
353 | } | ||
354 | write_sequnlock_irq(&xtime_lock); | ||
355 | clock_was_set(); | ||
356 | return 0; | ||
357 | } | ||
358 | EXPORT_SYMBOL(do_settimeofday); | ||
359 | |||
360 | void do_gettimeofday (struct timeval *tv) | ||
361 | { | ||
362 | unsigned long seq, nsec, usec, sec, offset; | ||
363 | do { | ||
364 | seq = read_seqbegin(&xtime_lock); | ||
365 | offset = time_interpolator_get_offset(); | ||
366 | sec = xtime.tv_sec; | ||
367 | nsec = xtime.tv_nsec; | ||
368 | } while (unlikely(read_seqretry(&xtime_lock, seq))); | ||
369 | |||
370 | usec = (nsec + offset) / 1000; | ||
371 | |||
372 | while (unlikely(usec >= USEC_PER_SEC)) { | ||
373 | usec -= USEC_PER_SEC; | ||
374 | ++sec; | ||
375 | } | ||
376 | |||
377 | tv->tv_sec = sec; | ||
378 | tv->tv_usec = usec; | ||
379 | |||
380 | /* | ||
381 | * Make sure xtime.tv_sec [returned by sys_time()] always | ||
382 | * follows the gettimeofday() result precisely. This | ||
383 | * condition is extremely unlikely, it can hit at most | ||
384 | * once per second: | ||
385 | */ | ||
386 | if (unlikely(xtime.tv_sec != tv->tv_sec)) { | ||
387 | unsigned long flags; | ||
388 | |||
389 | write_seqlock_irqsave(&xtime_lock, flags); | ||
390 | update_wall_time(); | ||
391 | write_sequnlock_irqrestore(&xtime_lock, flags); | ||
392 | } | ||
393 | } | ||
394 | EXPORT_SYMBOL(do_gettimeofday); | ||
395 | |||
396 | #else /* CONFIG_TIME_INTERPOLATION */ | ||
397 | |||
398 | #ifndef CONFIG_GENERIC_TIME | 311 | #ifndef CONFIG_GENERIC_TIME |
399 | /* | 312 | /* |
400 | * Simulate gettimeofday using do_gettimeofday which only allows a timeval | 313 | * Simulate gettimeofday using do_gettimeofday which only allows a timeval |
@@ -410,7 +323,6 @@ void getnstimeofday(struct timespec *tv) | |||
410 | } | 323 | } |
411 | EXPORT_SYMBOL_GPL(getnstimeofday); | 324 | EXPORT_SYMBOL_GPL(getnstimeofday); |
412 | #endif | 325 | #endif |
413 | #endif /* CONFIG_TIME_INTERPOLATION */ | ||
414 | 326 | ||
415 | /* Converts Gregorian date to seconds since 1970-01-01 00:00:00. | 327 | /* Converts Gregorian date to seconds since 1970-01-01 00:00:00. |
416 | * Assumes input in normal date format, i.e. 1980-12-31 23:59:59 | 328 | * Assumes input in normal date format, i.e. 1980-12-31 23:59:59 |
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index 438c6b723ee2..b5e352597cbb 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c | |||
@@ -116,11 +116,6 @@ void second_overflow(void) | |||
116 | if (xtime.tv_sec % 86400 == 0) { | 116 | if (xtime.tv_sec % 86400 == 0) { |
117 | xtime.tv_sec--; | 117 | xtime.tv_sec--; |
118 | wall_to_monotonic.tv_sec++; | 118 | wall_to_monotonic.tv_sec++; |
119 | /* | ||
120 | * The timer interpolator will make time change | ||
121 | * gradually instead of an immediate jump by one second | ||
122 | */ | ||
123 | time_interpolator_update(-NSEC_PER_SEC); | ||
124 | time_state = TIME_OOP; | 119 | time_state = TIME_OOP; |
125 | printk(KERN_NOTICE "Clock: inserting leap second " | 120 | printk(KERN_NOTICE "Clock: inserting leap second " |
126 | "23:59:60 UTC\n"); | 121 | "23:59:60 UTC\n"); |
@@ -130,11 +125,6 @@ void second_overflow(void) | |||
130 | if ((xtime.tv_sec + 1) % 86400 == 0) { | 125 | if ((xtime.tv_sec + 1) % 86400 == 0) { |
131 | xtime.tv_sec++; | 126 | xtime.tv_sec++; |
132 | wall_to_monotonic.tv_sec--; | 127 | wall_to_monotonic.tv_sec--; |
133 | /* | ||
134 | * Use of time interpolator for a gradual change of | ||
135 | * time | ||
136 | */ | ||
137 | time_interpolator_update(NSEC_PER_SEC); | ||
138 | time_state = TIME_WAIT; | 128 | time_state = TIME_WAIT; |
139 | printk(KERN_NOTICE "Clock: deleting leap second " | 129 | printk(KERN_NOTICE "Clock: deleting leap second " |
140 | "23:59:59 UTC\n"); | 130 | "23:59:59 UTC\n"); |
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 728cedfd3cbd..027d46c906e0 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
@@ -466,10 +466,6 @@ void update_wall_time(void) | |||
466 | second_overflow(); | 466 | second_overflow(); |
467 | } | 467 | } |
468 | 468 | ||
469 | /* interpolator bits */ | ||
470 | time_interpolator_update(clock->xtime_interval | ||
471 | >> clock->shift); | ||
472 | |||
473 | /* accumulate error between NTP and clock interval */ | 469 | /* accumulate error between NTP and clock interval */ |
474 | clock->error += current_tick_length(); | 470 | clock->error += current_tick_length(); |
475 | clock->error -= clock->xtime_interval << (TICK_LENGTH_SHIFT - clock->shift); | 471 | clock->error -= clock->xtime_interval << (TICK_LENGTH_SHIFT - clock->shift); |
diff --git a/kernel/timer.c b/kernel/timer.c index b7792fb03387..dbc03ab14eed 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
@@ -1349,194 +1349,6 @@ void __init init_timers(void) | |||
1349 | open_softirq(TIMER_SOFTIRQ, run_timer_softirq, NULL); | 1349 | open_softirq(TIMER_SOFTIRQ, run_timer_softirq, NULL); |
1350 | } | 1350 | } |
1351 | 1351 | ||
1352 | #ifdef CONFIG_TIME_INTERPOLATION | ||
1353 | |||
1354 | struct time_interpolator *time_interpolator __read_mostly; | ||
1355 | static struct time_interpolator *time_interpolator_list __read_mostly; | ||
1356 | static DEFINE_SPINLOCK(time_interpolator_lock); | ||
1357 | |||
1358 | static inline cycles_t time_interpolator_get_cycles(unsigned int src) | ||
1359 | { | ||
1360 | unsigned long (*x)(void); | ||
1361 | |||
1362 | switch (src) | ||
1363 | { | ||
1364 | case TIME_SOURCE_FUNCTION: | ||
1365 | x = time_interpolator->addr; | ||
1366 | return x(); | ||
1367 | |||
1368 | case TIME_SOURCE_MMIO64 : | ||
1369 | return readq_relaxed((void __iomem *)time_interpolator->addr); | ||
1370 | |||
1371 | case TIME_SOURCE_MMIO32 : | ||
1372 | return readl_relaxed((void __iomem *)time_interpolator->addr); | ||
1373 | |||
1374 | default: return get_cycles(); | ||
1375 | } | ||
1376 | } | ||
1377 | |||
1378 | static inline u64 time_interpolator_get_counter(int writelock) | ||
1379 | { | ||
1380 | unsigned int src = time_interpolator->source; | ||
1381 | |||
1382 | if (time_interpolator->jitter) | ||
1383 | { | ||
1384 | cycles_t lcycle; | ||
1385 | cycles_t now; | ||
1386 | |||
1387 | do { | ||
1388 | lcycle = time_interpolator->last_cycle; | ||
1389 | now = time_interpolator_get_cycles(src); | ||
1390 | if (lcycle && time_after(lcycle, now)) | ||
1391 | return lcycle; | ||
1392 | |||
1393 | /* When holding the xtime write lock, there's no need | ||
1394 | * to add the overhead of the cmpxchg. Readers are | ||
1395 | * force to retry until the write lock is released. | ||
1396 | */ | ||
1397 | if (writelock) { | ||
1398 | time_interpolator->last_cycle = now; | ||
1399 | return now; | ||
1400 | } | ||
1401 | /* Keep track of the last timer value returned. The use of cmpxchg here | ||
1402 | * will cause contention in an SMP environment. | ||
1403 | */ | ||
1404 | } while (unlikely(cmpxchg(&time_interpolator->last_cycle, lcycle, now) != lcycle)); | ||
1405 | return now; | ||
1406 | } | ||
1407 | else | ||
1408 | return time_interpolator_get_cycles(src); | ||
1409 | } | ||
1410 | |||
1411 | void time_interpolator_reset(void) | ||
1412 | { | ||
1413 | time_interpolator->offset = 0; | ||
1414 | time_interpolator->last_counter = time_interpolator_get_counter(1); | ||
1415 | } | ||
1416 | |||
1417 | #define GET_TI_NSECS(count,i) (((((count) - i->last_counter) & (i)->mask) * (i)->nsec_per_cyc) >> (i)->shift) | ||
1418 | |||
1419 | unsigned long time_interpolator_get_offset(void) | ||
1420 | { | ||
1421 | /* If we do not have a time interpolator set up then just return zero */ | ||
1422 | if (!time_interpolator) | ||
1423 | return 0; | ||
1424 | |||
1425 | return time_interpolator->offset + | ||
1426 | GET_TI_NSECS(time_interpolator_get_counter(0), time_interpolator); | ||
1427 | } | ||
1428 | |||
1429 | #define INTERPOLATOR_ADJUST 65536 | ||
1430 | #define INTERPOLATOR_MAX_SKIP 10*INTERPOLATOR_ADJUST | ||
1431 | |||
1432 | void time_interpolator_update(long delta_nsec) | ||
1433 | { | ||
1434 | u64 counter; | ||
1435 | unsigned long offset; | ||
1436 | |||
1437 | /* If there is no time interpolator set up then do nothing */ | ||
1438 | if (!time_interpolator) | ||
1439 | return; | ||
1440 | |||
1441 | /* | ||
1442 | * The interpolator compensates for late ticks by accumulating the late | ||
1443 | * time in time_interpolator->offset. A tick earlier than expected will | ||
1444 | * lead to a reset of the offset and a corresponding jump of the clock | ||
1445 | * forward. Again this only works if the interpolator clock is running | ||
1446 | * slightly slower than the regular clock and the tuning logic insures | ||
1447 | * that. | ||
1448 | */ | ||
1449 | |||
1450 | counter = time_interpolator_get_counter(1); | ||
1451 | offset = time_interpolator->offset + | ||
1452 | GET_TI_NSECS(counter, time_interpolator); | ||
1453 | |||
1454 | if (delta_nsec < 0 || (unsigned long) delta_nsec < offset) | ||
1455 | time_interpolator->offset = offset - delta_nsec; | ||
1456 | else { | ||
1457 | time_interpolator->skips++; | ||
1458 | time_interpolator->ns_skipped += delta_nsec - offset; | ||
1459 | time_interpolator->offset = 0; | ||
1460 | } | ||
1461 | time_interpolator->last_counter = counter; | ||
1462 | |||
1463 | /* Tuning logic for time interpolator invoked every minute or so. | ||
1464 | * Decrease interpolator clock speed if no skips occurred and an offset is carried. | ||
1465 | * Increase interpolator clock speed if we skip too much time. | ||
1466 | */ | ||
1467 | if (jiffies % INTERPOLATOR_ADJUST == 0) | ||
1468 | { | ||
1469 | if (time_interpolator->skips == 0 && time_interpolator->offset > tick_nsec) | ||
1470 | time_interpolator->nsec_per_cyc--; | ||
1471 | if (time_interpolator->ns_skipped > INTERPOLATOR_MAX_SKIP && time_interpolator->offset == 0) | ||
1472 | time_interpolator->nsec_per_cyc++; | ||
1473 | time_interpolator->skips = 0; | ||
1474 | time_interpolator->ns_skipped = 0; | ||
1475 | } | ||
1476 | } | ||
1477 | |||
1478 | static inline int | ||
1479 | is_better_time_interpolator(struct time_interpolator *new) | ||
1480 | { | ||
1481 | if (!time_interpolator) | ||
1482 | return 1; | ||
1483 | return new->frequency > 2*time_interpolator->frequency || | ||
1484 | (unsigned long)new->drift < (unsigned long)time_interpolator->drift; | ||
1485 | } | ||
1486 | |||
1487 | void | ||
1488 | register_time_interpolator(struct time_interpolator *ti) | ||
1489 | { | ||
1490 | unsigned long flags; | ||
1491 | |||
1492 | /* Sanity check */ | ||
1493 | BUG_ON(ti->frequency == 0 || ti->mask == 0); | ||
1494 | |||
1495 | ti->nsec_per_cyc = ((u64)NSEC_PER_SEC << ti->shift) / ti->frequency; | ||
1496 | spin_lock(&time_interpolator_lock); | ||
1497 | write_seqlock_irqsave(&xtime_lock, flags); | ||
1498 | if (is_better_time_interpolator(ti)) { | ||
1499 | time_interpolator = ti; | ||
1500 | time_interpolator_reset(); | ||
1501 | } | ||
1502 | write_sequnlock_irqrestore(&xtime_lock, flags); | ||
1503 | |||
1504 | ti->next = time_interpolator_list; | ||
1505 | time_interpolator_list = ti; | ||
1506 | spin_unlock(&time_interpolator_lock); | ||
1507 | } | ||
1508 | |||
1509 | void | ||
1510 | unregister_time_interpolator(struct time_interpolator *ti) | ||
1511 | { | ||
1512 | struct time_interpolator *curr, **prev; | ||
1513 | unsigned long flags; | ||
1514 | |||
1515 | spin_lock(&time_interpolator_lock); | ||
1516 | prev = &time_interpolator_list; | ||
1517 | for (curr = *prev; curr; curr = curr->next) { | ||
1518 | if (curr == ti) { | ||
1519 | *prev = curr->next; | ||
1520 | break; | ||
1521 | } | ||
1522 | prev = &curr->next; | ||
1523 | } | ||
1524 | |||
1525 | write_seqlock_irqsave(&xtime_lock, flags); | ||
1526 | if (ti == time_interpolator) { | ||
1527 | /* we lost the best time-interpolator: */ | ||
1528 | time_interpolator = NULL; | ||
1529 | /* find the next-best interpolator */ | ||
1530 | for (curr = time_interpolator_list; curr; curr = curr->next) | ||
1531 | if (is_better_time_interpolator(curr)) | ||
1532 | time_interpolator = curr; | ||
1533 | time_interpolator_reset(); | ||
1534 | } | ||
1535 | write_sequnlock_irqrestore(&xtime_lock, flags); | ||
1536 | spin_unlock(&time_interpolator_lock); | ||
1537 | } | ||
1538 | #endif /* CONFIG_TIME_INTERPOLATION */ | ||
1539 | |||
1540 | /** | 1352 | /** |
1541 | * msleep - sleep safely even with waitqueue interruptions | 1353 | * msleep - sleep safely even with waitqueue interruptions |
1542 | * @msecs: Time in milliseconds to sleep for | 1354 | * @msecs: Time in milliseconds to sleep for |