diff options
-rw-r--r-- | drivers/rtc/rtc-cmos.c | 52 | ||||
-rw-r--r-- | kernel/time/tick-common.c | 1 | ||||
-rw-r--r-- | kernel/time/tick-internal.h | 1 | ||||
-rw-r--r-- | kernel/time/tick-sched.c | 1 | ||||
-rw-r--r-- | kernel/time/timekeeping.c | 53 |
5 files changed, 80 insertions, 28 deletions
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index f14876256a4a..a2325bc5e497 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -34,11 +34,11 @@ | |||
34 | #include <linux/interrupt.h> | 34 | #include <linux/interrupt.h> |
35 | #include <linux/spinlock.h> | 35 | #include <linux/spinlock.h> |
36 | #include <linux/platform_device.h> | 36 | #include <linux/platform_device.h> |
37 | #include <linux/mod_devicetable.h> | ||
38 | #include <linux/log2.h> | 37 | #include <linux/log2.h> |
39 | #include <linux/pm.h> | 38 | #include <linux/pm.h> |
40 | #include <linux/of.h> | 39 | #include <linux/of.h> |
41 | #include <linux/of_platform.h> | 40 | #include <linux/of_platform.h> |
41 | #include <linux/dmi.h> | ||
42 | 42 | ||
43 | /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ | 43 | /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ |
44 | #include <asm-generic/rtc.h> | 44 | #include <asm-generic/rtc.h> |
@@ -377,6 +377,51 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
377 | return 0; | 377 | return 0; |
378 | } | 378 | } |
379 | 379 | ||
380 | /* | ||
381 | * Do not disable RTC alarm on shutdown - workaround for b0rked BIOSes. | ||
382 | */ | ||
383 | static bool alarm_disable_quirk; | ||
384 | |||
385 | static int __init set_alarm_disable_quirk(const struct dmi_system_id *id) | ||
386 | { | ||
387 | alarm_disable_quirk = true; | ||
388 | pr_info("rtc-cmos: BIOS has alarm-disable quirk. "); | ||
389 | pr_info("RTC alarms disabled\n"); | ||
390 | return 0; | ||
391 | } | ||
392 | |||
393 | static const struct dmi_system_id rtc_quirks[] __initconst = { | ||
394 | /* https://bugzilla.novell.com/show_bug.cgi?id=805740 */ | ||
395 | { | ||
396 | .callback = set_alarm_disable_quirk, | ||
397 | .ident = "IBM Truman", | ||
398 | .matches = { | ||
399 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | ||
400 | DMI_MATCH(DMI_PRODUCT_NAME, "4852570"), | ||
401 | }, | ||
402 | }, | ||
403 | /* https://bugzilla.novell.com/show_bug.cgi?id=812592 */ | ||
404 | { | ||
405 | .callback = set_alarm_disable_quirk, | ||
406 | .ident = "Gigabyte GA-990XA-UD3", | ||
407 | .matches = { | ||
408 | DMI_MATCH(DMI_SYS_VENDOR, | ||
409 | "Gigabyte Technology Co., Ltd."), | ||
410 | DMI_MATCH(DMI_PRODUCT_NAME, "GA-990XA-UD3"), | ||
411 | }, | ||
412 | }, | ||
413 | /* http://permalink.gmane.org/gmane.linux.kernel/1604474 */ | ||
414 | { | ||
415 | .callback = set_alarm_disable_quirk, | ||
416 | .ident = "Toshiba Satellite L300", | ||
417 | .matches = { | ||
418 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | ||
419 | DMI_MATCH(DMI_PRODUCT_NAME, "Satellite L300"), | ||
420 | }, | ||
421 | }, | ||
422 | {} | ||
423 | }; | ||
424 | |||
380 | static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled) | 425 | static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled) |
381 | { | 426 | { |
382 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | 427 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
@@ -385,6 +430,9 @@ static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled) | |||
385 | if (!is_valid_irq(cmos->irq)) | 430 | if (!is_valid_irq(cmos->irq)) |
386 | return -EINVAL; | 431 | return -EINVAL; |
387 | 432 | ||
433 | if (alarm_disable_quirk) | ||
434 | return 0; | ||
435 | |||
388 | spin_lock_irqsave(&rtc_lock, flags); | 436 | spin_lock_irqsave(&rtc_lock, flags); |
389 | 437 | ||
390 | if (enabled) | 438 | if (enabled) |
@@ -1157,6 +1205,8 @@ static int __init cmos_init(void) | |||
1157 | platform_driver_registered = true; | 1205 | platform_driver_registered = true; |
1158 | } | 1206 | } |
1159 | 1207 | ||
1208 | dmi_check_system(rtc_quirks); | ||
1209 | |||
1160 | if (retval == 0) | 1210 | if (retval == 0) |
1161 | return 0; | 1211 | return 0; |
1162 | 1212 | ||
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index 162b03ab0ad2..20b2fe37d105 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c | |||
@@ -85,6 +85,7 @@ static void tick_periodic(int cpu) | |||
85 | 85 | ||
86 | do_timer(1); | 86 | do_timer(1); |
87 | write_sequnlock(&jiffies_lock); | 87 | write_sequnlock(&jiffies_lock); |
88 | update_wall_time(); | ||
88 | } | 89 | } |
89 | 90 | ||
90 | update_process_times(user_mode(get_irq_regs())); | 91 | update_process_times(user_mode(get_irq_regs())); |
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h index e2bced59b6dd..8329669b51ec 100644 --- a/kernel/time/tick-internal.h +++ b/kernel/time/tick-internal.h | |||
@@ -155,3 +155,4 @@ static inline int tick_device_is_functional(struct clock_event_device *dev) | |||
155 | #endif | 155 | #endif |
156 | 156 | ||
157 | extern void do_timer(unsigned long ticks); | 157 | extern void do_timer(unsigned long ticks); |
158 | extern void update_wall_time(void); | ||
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 52cee12b3302..0ddd020bbaf2 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
@@ -86,6 +86,7 @@ static void tick_do_update_jiffies64(ktime_t now) | |||
86 | tick_next_period = ktime_add(last_jiffies_update, tick_period); | 86 | tick_next_period = ktime_add(last_jiffies_update, tick_period); |
87 | } | 87 | } |
88 | write_sequnlock(&jiffies_lock); | 88 | write_sequnlock(&jiffies_lock); |
89 | update_wall_time(); | ||
89 | } | 90 | } |
90 | 91 | ||
91 | /* | 92 | /* |
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 87b4f00284c9..0aa4ce81bc16 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
@@ -77,7 +77,7 @@ static void tk_set_wall_to_mono(struct timekeeper *tk, struct timespec wtm) | |||
77 | tk->wall_to_monotonic = wtm; | 77 | tk->wall_to_monotonic = wtm; |
78 | set_normalized_timespec(&tmp, -wtm.tv_sec, -wtm.tv_nsec); | 78 | set_normalized_timespec(&tmp, -wtm.tv_sec, -wtm.tv_nsec); |
79 | tk->offs_real = timespec_to_ktime(tmp); | 79 | tk->offs_real = timespec_to_ktime(tmp); |
80 | tk->offs_tai = ktime_sub(tk->offs_real, ktime_set(tk->tai_offset, 0)); | 80 | tk->offs_tai = ktime_add(tk->offs_real, ktime_set(tk->tai_offset, 0)); |
81 | } | 81 | } |
82 | 82 | ||
83 | static void tk_set_sleep_time(struct timekeeper *tk, struct timespec t) | 83 | static void tk_set_sleep_time(struct timekeeper *tk, struct timespec t) |
@@ -90,8 +90,9 @@ static void tk_set_sleep_time(struct timekeeper *tk, struct timespec t) | |||
90 | } | 90 | } |
91 | 91 | ||
92 | /** | 92 | /** |
93 | * timekeeper_setup_internals - Set up internals to use clocksource clock. | 93 | * tk_setup_internals - Set up internals to use clocksource clock. |
94 | * | 94 | * |
95 | * @tk: The target timekeeper to setup. | ||
95 | * @clock: Pointer to clocksource. | 96 | * @clock: Pointer to clocksource. |
96 | * | 97 | * |
97 | * Calculates a fixed cycle/nsec interval for a given clocksource/adjustment | 98 | * Calculates a fixed cycle/nsec interval for a given clocksource/adjustment |
@@ -595,7 +596,7 @@ s32 timekeeping_get_tai_offset(void) | |||
595 | static void __timekeeping_set_tai_offset(struct timekeeper *tk, s32 tai_offset) | 596 | static void __timekeeping_set_tai_offset(struct timekeeper *tk, s32 tai_offset) |
596 | { | 597 | { |
597 | tk->tai_offset = tai_offset; | 598 | tk->tai_offset = tai_offset; |
598 | tk->offs_tai = ktime_sub(tk->offs_real, ktime_set(tai_offset, 0)); | 599 | tk->offs_tai = ktime_add(tk->offs_real, ktime_set(tai_offset, 0)); |
599 | } | 600 | } |
600 | 601 | ||
601 | /** | 602 | /** |
@@ -610,6 +611,7 @@ void timekeeping_set_tai_offset(s32 tai_offset) | |||
610 | raw_spin_lock_irqsave(&timekeeper_lock, flags); | 611 | raw_spin_lock_irqsave(&timekeeper_lock, flags); |
611 | write_seqcount_begin(&timekeeper_seq); | 612 | write_seqcount_begin(&timekeeper_seq); |
612 | __timekeeping_set_tai_offset(tk, tai_offset); | 613 | __timekeeping_set_tai_offset(tk, tai_offset); |
614 | timekeeping_update(tk, TK_MIRROR | TK_CLOCK_WAS_SET); | ||
613 | write_seqcount_end(&timekeeper_seq); | 615 | write_seqcount_end(&timekeeper_seq); |
614 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); | 616 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); |
615 | clock_was_set(); | 617 | clock_was_set(); |
@@ -1023,6 +1025,8 @@ static int timekeeping_suspend(void) | |||
1023 | timekeeping_suspend_time = | 1025 | timekeeping_suspend_time = |
1024 | timespec_add(timekeeping_suspend_time, delta_delta); | 1026 | timespec_add(timekeeping_suspend_time, delta_delta); |
1025 | } | 1027 | } |
1028 | |||
1029 | timekeeping_update(tk, TK_MIRROR); | ||
1026 | write_seqcount_end(&timekeeper_seq); | 1030 | write_seqcount_end(&timekeeper_seq); |
1027 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); | 1031 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); |
1028 | 1032 | ||
@@ -1130,16 +1134,6 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset) | |||
1130 | * we can adjust by 1. | 1134 | * we can adjust by 1. |
1131 | */ | 1135 | */ |
1132 | error >>= 2; | 1136 | error >>= 2; |
1133 | /* | ||
1134 | * XXX - In update_wall_time, we round up to the next | ||
1135 | * nanosecond, and store the amount rounded up into | ||
1136 | * the error. This causes the likely below to be unlikely. | ||
1137 | * | ||
1138 | * The proper fix is to avoid rounding up by using | ||
1139 | * the high precision tk->xtime_nsec instead of | ||
1140 | * xtime.tv_nsec everywhere. Fixing this will take some | ||
1141 | * time. | ||
1142 | */ | ||
1143 | if (likely(error <= interval)) | 1137 | if (likely(error <= interval)) |
1144 | adj = 1; | 1138 | adj = 1; |
1145 | else | 1139 | else |
@@ -1255,7 +1249,7 @@ out_adjust: | |||
1255 | static inline unsigned int accumulate_nsecs_to_secs(struct timekeeper *tk) | 1249 | static inline unsigned int accumulate_nsecs_to_secs(struct timekeeper *tk) |
1256 | { | 1250 | { |
1257 | u64 nsecps = (u64)NSEC_PER_SEC << tk->shift; | 1251 | u64 nsecps = (u64)NSEC_PER_SEC << tk->shift; |
1258 | unsigned int action = 0; | 1252 | unsigned int clock_set = 0; |
1259 | 1253 | ||
1260 | while (tk->xtime_nsec >= nsecps) { | 1254 | while (tk->xtime_nsec >= nsecps) { |
1261 | int leap; | 1255 | int leap; |
@@ -1277,11 +1271,10 @@ static inline unsigned int accumulate_nsecs_to_secs(struct timekeeper *tk) | |||
1277 | 1271 | ||
1278 | __timekeeping_set_tai_offset(tk, tk->tai_offset - leap); | 1272 | __timekeeping_set_tai_offset(tk, tk->tai_offset - leap); |
1279 | 1273 | ||
1280 | clock_was_set_delayed(); | 1274 | clock_set = TK_CLOCK_WAS_SET; |
1281 | action = TK_CLOCK_WAS_SET; | ||
1282 | } | 1275 | } |
1283 | } | 1276 | } |
1284 | return action; | 1277 | return clock_set; |
1285 | } | 1278 | } |
1286 | 1279 | ||
1287 | /** | 1280 | /** |
@@ -1294,7 +1287,8 @@ static inline unsigned int accumulate_nsecs_to_secs(struct timekeeper *tk) | |||
1294 | * Returns the unconsumed cycles. | 1287 | * Returns the unconsumed cycles. |
1295 | */ | 1288 | */ |
1296 | static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset, | 1289 | static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset, |
1297 | u32 shift) | 1290 | u32 shift, |
1291 | unsigned int *clock_set) | ||
1298 | { | 1292 | { |
1299 | cycle_t interval = tk->cycle_interval << shift; | 1293 | cycle_t interval = tk->cycle_interval << shift; |
1300 | u64 raw_nsecs; | 1294 | u64 raw_nsecs; |
@@ -1308,7 +1302,7 @@ static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset, | |||
1308 | tk->cycle_last += interval; | 1302 | tk->cycle_last += interval; |
1309 | 1303 | ||
1310 | tk->xtime_nsec += tk->xtime_interval << shift; | 1304 | tk->xtime_nsec += tk->xtime_interval << shift; |
1311 | accumulate_nsecs_to_secs(tk); | 1305 | *clock_set |= accumulate_nsecs_to_secs(tk); |
1312 | 1306 | ||
1313 | /* Accumulate raw time */ | 1307 | /* Accumulate raw time */ |
1314 | raw_nsecs = (u64)tk->raw_interval << shift; | 1308 | raw_nsecs = (u64)tk->raw_interval << shift; |
@@ -1359,14 +1353,14 @@ static inline void old_vsyscall_fixup(struct timekeeper *tk) | |||
1359 | * update_wall_time - Uses the current clocksource to increment the wall time | 1353 | * update_wall_time - Uses the current clocksource to increment the wall time |
1360 | * | 1354 | * |
1361 | */ | 1355 | */ |
1362 | static void update_wall_time(void) | 1356 | void update_wall_time(void) |
1363 | { | 1357 | { |
1364 | struct clocksource *clock; | 1358 | struct clocksource *clock; |
1365 | struct timekeeper *real_tk = &timekeeper; | 1359 | struct timekeeper *real_tk = &timekeeper; |
1366 | struct timekeeper *tk = &shadow_timekeeper; | 1360 | struct timekeeper *tk = &shadow_timekeeper; |
1367 | cycle_t offset; | 1361 | cycle_t offset; |
1368 | int shift = 0, maxshift; | 1362 | int shift = 0, maxshift; |
1369 | unsigned int action; | 1363 | unsigned int clock_set = 0; |
1370 | unsigned long flags; | 1364 | unsigned long flags; |
1371 | 1365 | ||
1372 | raw_spin_lock_irqsave(&timekeeper_lock, flags); | 1366 | raw_spin_lock_irqsave(&timekeeper_lock, flags); |
@@ -1401,7 +1395,8 @@ static void update_wall_time(void) | |||
1401 | maxshift = (64 - (ilog2(ntp_tick_length())+1)) - 1; | 1395 | maxshift = (64 - (ilog2(ntp_tick_length())+1)) - 1; |
1402 | shift = min(shift, maxshift); | 1396 | shift = min(shift, maxshift); |
1403 | while (offset >= tk->cycle_interval) { | 1397 | while (offset >= tk->cycle_interval) { |
1404 | offset = logarithmic_accumulation(tk, offset, shift); | 1398 | offset = logarithmic_accumulation(tk, offset, shift, |
1399 | &clock_set); | ||
1405 | if (offset < tk->cycle_interval<<shift) | 1400 | if (offset < tk->cycle_interval<<shift) |
1406 | shift--; | 1401 | shift--; |
1407 | } | 1402 | } |
@@ -1419,7 +1414,7 @@ static void update_wall_time(void) | |||
1419 | * Finally, make sure that after the rounding | 1414 | * Finally, make sure that after the rounding |
1420 | * xtime_nsec isn't larger than NSEC_PER_SEC | 1415 | * xtime_nsec isn't larger than NSEC_PER_SEC |
1421 | */ | 1416 | */ |
1422 | action = accumulate_nsecs_to_secs(tk); | 1417 | clock_set |= accumulate_nsecs_to_secs(tk); |
1423 | 1418 | ||
1424 | write_seqcount_begin(&timekeeper_seq); | 1419 | write_seqcount_begin(&timekeeper_seq); |
1425 | /* Update clock->cycle_last with the new value */ | 1420 | /* Update clock->cycle_last with the new value */ |
@@ -1435,10 +1430,12 @@ static void update_wall_time(void) | |||
1435 | * updating. | 1430 | * updating. |
1436 | */ | 1431 | */ |
1437 | memcpy(real_tk, tk, sizeof(*tk)); | 1432 | memcpy(real_tk, tk, sizeof(*tk)); |
1438 | timekeeping_update(real_tk, action); | 1433 | timekeeping_update(real_tk, clock_set); |
1439 | write_seqcount_end(&timekeeper_seq); | 1434 | write_seqcount_end(&timekeeper_seq); |
1440 | out: | 1435 | out: |
1441 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); | 1436 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); |
1437 | if (clock_set) | ||
1438 | clock_was_set(); | ||
1442 | } | 1439 | } |
1443 | 1440 | ||
1444 | /** | 1441 | /** |
@@ -1583,7 +1580,6 @@ struct timespec get_monotonic_coarse(void) | |||
1583 | void do_timer(unsigned long ticks) | 1580 | void do_timer(unsigned long ticks) |
1584 | { | 1581 | { |
1585 | jiffies_64 += ticks; | 1582 | jiffies_64 += ticks; |
1586 | update_wall_time(); | ||
1587 | calc_global_load(ticks); | 1583 | calc_global_load(ticks); |
1588 | } | 1584 | } |
1589 | 1585 | ||
@@ -1698,12 +1694,14 @@ int do_adjtimex(struct timex *txc) | |||
1698 | 1694 | ||
1699 | if (tai != orig_tai) { | 1695 | if (tai != orig_tai) { |
1700 | __timekeeping_set_tai_offset(tk, tai); | 1696 | __timekeeping_set_tai_offset(tk, tai); |
1701 | update_pvclock_gtod(tk, true); | 1697 | timekeeping_update(tk, TK_MIRROR | TK_CLOCK_WAS_SET); |
1702 | clock_was_set_delayed(); | ||
1703 | } | 1698 | } |
1704 | write_seqcount_end(&timekeeper_seq); | 1699 | write_seqcount_end(&timekeeper_seq); |
1705 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); | 1700 | raw_spin_unlock_irqrestore(&timekeeper_lock, flags); |
1706 | 1701 | ||
1702 | if (tai != orig_tai) | ||
1703 | clock_was_set(); | ||
1704 | |||
1707 | ntp_notify_cmos_timer(); | 1705 | ntp_notify_cmos_timer(); |
1708 | 1706 | ||
1709 | return ret; | 1707 | return ret; |
@@ -1739,4 +1737,5 @@ void xtime_update(unsigned long ticks) | |||
1739 | write_seqlock(&jiffies_lock); | 1737 | write_seqlock(&jiffies_lock); |
1740 | do_timer(ticks); | 1738 | do_timer(ticks); |
1741 | write_sequnlock(&jiffies_lock); | 1739 | write_sequnlock(&jiffies_lock); |
1740 | update_wall_time(); | ||
1742 | } | 1741 | } |