Skip to content

Commit d05d24a

Browse files
author
Ingo Molnar
committed
Merge branch 'fortglx/3.14/time' of git://git.linaro.org/people/john.stultz/linux into timers/core
Pull timekeeping updates from John Stultz. Signed-off-by: Ingo Molnar <mingo@kernel.org>
2 parents dba8614 + 38aef31 commit d05d24a

File tree

5 files changed

+80
-28
lines changed

5 files changed

+80
-28
lines changed

drivers/rtc/rtc-cmos.c

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@
3434
#include <linux/interrupt.h>
3535
#include <linux/spinlock.h>
3636
#include <linux/platform_device.h>
37-
#include <linux/mod_devicetable.h>
3837
#include <linux/log2.h>
3938
#include <linux/pm.h>
4039
#include <linux/of.h>
4140
#include <linux/of_platform.h>
41+
#include <linux/dmi.h>
4242

4343
/* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
4444
#include <asm-generic/rtc.h>
@@ -377,6 +377,51 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
377377
return 0;
378378
}
379379

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+
380425
static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled)
381426
{
382427
struct cmos_rtc *cmos = dev_get_drvdata(dev);
@@ -385,6 +430,9 @@ static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled)
385430
if (!is_valid_irq(cmos->irq))
386431
return -EINVAL;
387432

433+
if (alarm_disable_quirk)
434+
return 0;
435+
388436
spin_lock_irqsave(&rtc_lock, flags);
389437

390438
if (enabled)
@@ -1157,6 +1205,8 @@ static int __init cmos_init(void)
11571205
platform_driver_registered = true;
11581206
}
11591207

1208+
dmi_check_system(rtc_quirks);
1209+
11601210
if (retval == 0)
11611211
return 0;
11621212

kernel/time/tick-common.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ static void tick_periodic(int cpu)
8585

8686
do_timer(1);
8787
write_sequnlock(&jiffies_lock);
88+
update_wall_time();
8889
}
8990

9091
update_process_times(user_mode(get_irq_regs()));

kernel/time/tick-internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,3 +155,4 @@ static inline int tick_device_is_functional(struct clock_event_device *dev)
155155
#endif
156156

157157
extern void do_timer(unsigned long ticks);
158+
extern void update_wall_time(void);

kernel/time/tick-sched.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ static void tick_do_update_jiffies64(ktime_t now)
8686
tick_next_period = ktime_add(last_jiffies_update, tick_period);
8787
}
8888
write_sequnlock(&jiffies_lock);
89+
update_wall_time();
8990
}
9091

9192
/*

kernel/time/timekeeping.c

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ static void tk_set_wall_to_mono(struct timekeeper *tk, struct timespec wtm)
7777
tk->wall_to_monotonic = wtm;
7878
set_normalized_timespec(&tmp, -wtm.tv_sec, -wtm.tv_nsec);
7979
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));
8181
}
8282

8383
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)
9090
}
9191

9292
/**
93-
* timekeeper_setup_internals - Set up internals to use clocksource clock.
93+
* tk_setup_internals - Set up internals to use clocksource clock.
9494
*
95+
* @tk: The target timekeeper to setup.
9596
* @clock: Pointer to clocksource.
9697
*
9798
* Calculates a fixed cycle/nsec interval for a given clocksource/adjustment
@@ -595,7 +596,7 @@ s32 timekeeping_get_tai_offset(void)
595596
static void __timekeeping_set_tai_offset(struct timekeeper *tk, s32 tai_offset)
596597
{
597598
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));
599600
}
600601

601602
/**
@@ -610,6 +611,7 @@ void timekeeping_set_tai_offset(s32 tai_offset)
610611
raw_spin_lock_irqsave(&timekeeper_lock, flags);
611612
write_seqcount_begin(&timekeeper_seq);
612613
__timekeeping_set_tai_offset(tk, tai_offset);
614+
timekeeping_update(tk, TK_MIRROR | TK_CLOCK_WAS_SET);
613615
write_seqcount_end(&timekeeper_seq);
614616
raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
615617
clock_was_set();
@@ -1023,6 +1025,8 @@ static int timekeeping_suspend(void)
10231025
timekeeping_suspend_time =
10241026
timespec_add(timekeeping_suspend_time, delta_delta);
10251027
}
1028+
1029+
timekeeping_update(tk, TK_MIRROR);
10261030
write_seqcount_end(&timekeeper_seq);
10271031
raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
10281032

@@ -1130,16 +1134,6 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset)
11301134
* we can adjust by 1.
11311135
*/
11321136
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-
*/
11431137
if (likely(error <= interval))
11441138
adj = 1;
11451139
else
@@ -1255,7 +1249,7 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset)
12551249
static inline unsigned int accumulate_nsecs_to_secs(struct timekeeper *tk)
12561250
{
12571251
u64 nsecps = (u64)NSEC_PER_SEC << tk->shift;
1258-
unsigned int action = 0;
1252+
unsigned int clock_set = 0;
12591253

12601254
while (tk->xtime_nsec >= nsecps) {
12611255
int leap;
@@ -1277,11 +1271,10 @@ static inline unsigned int accumulate_nsecs_to_secs(struct timekeeper *tk)
12771271

12781272
__timekeeping_set_tai_offset(tk, tk->tai_offset - leap);
12791273

1280-
clock_was_set_delayed();
1281-
action = TK_CLOCK_WAS_SET;
1274+
clock_set = TK_CLOCK_WAS_SET;
12821275
}
12831276
}
1284-
return action;
1277+
return clock_set;
12851278
}
12861279

12871280
/**
@@ -1294,7 +1287,8 @@ static inline unsigned int accumulate_nsecs_to_secs(struct timekeeper *tk)
12941287
* Returns the unconsumed cycles.
12951288
*/
12961289
static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset,
1297-
u32 shift)
1290+
u32 shift,
1291+
unsigned int *clock_set)
12981292
{
12991293
cycle_t interval = tk->cycle_interval << shift;
13001294
u64 raw_nsecs;
@@ -1308,7 +1302,7 @@ static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset,
13081302
tk->cycle_last += interval;
13091303

13101304
tk->xtime_nsec += tk->xtime_interval << shift;
1311-
accumulate_nsecs_to_secs(tk);
1305+
*clock_set |= accumulate_nsecs_to_secs(tk);
13121306

13131307
/* Accumulate raw time */
13141308
raw_nsecs = (u64)tk->raw_interval << shift;
@@ -1359,14 +1353,14 @@ static inline void old_vsyscall_fixup(struct timekeeper *tk)
13591353
* update_wall_time - Uses the current clocksource to increment the wall time
13601354
*
13611355
*/
1362-
static void update_wall_time(void)
1356+
void update_wall_time(void)
13631357
{
13641358
struct clocksource *clock;
13651359
struct timekeeper *real_tk = &timekeeper;
13661360
struct timekeeper *tk = &shadow_timekeeper;
13671361
cycle_t offset;
13681362
int shift = 0, maxshift;
1369-
unsigned int action;
1363+
unsigned int clock_set = 0;
13701364
unsigned long flags;
13711365

13721366
raw_spin_lock_irqsave(&timekeeper_lock, flags);
@@ -1401,7 +1395,8 @@ static void update_wall_time(void)
14011395
maxshift = (64 - (ilog2(ntp_tick_length())+1)) - 1;
14021396
shift = min(shift, maxshift);
14031397
while (offset >= tk->cycle_interval) {
1404-
offset = logarithmic_accumulation(tk, offset, shift);
1398+
offset = logarithmic_accumulation(tk, offset, shift,
1399+
&clock_set);
14051400
if (offset < tk->cycle_interval<<shift)
14061401
shift--;
14071402
}
@@ -1419,7 +1414,7 @@ static void update_wall_time(void)
14191414
* Finally, make sure that after the rounding
14201415
* xtime_nsec isn't larger than NSEC_PER_SEC
14211416
*/
1422-
action = accumulate_nsecs_to_secs(tk);
1417+
clock_set |= accumulate_nsecs_to_secs(tk);
14231418

14241419
write_seqcount_begin(&timekeeper_seq);
14251420
/* Update clock->cycle_last with the new value */
@@ -1435,10 +1430,12 @@ static void update_wall_time(void)
14351430
* updating.
14361431
*/
14371432
memcpy(real_tk, tk, sizeof(*tk));
1438-
timekeeping_update(real_tk, action);
1433+
timekeeping_update(real_tk, clock_set);
14391434
write_seqcount_end(&timekeeper_seq);
14401435
out:
14411436
raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
1437+
if (clock_set)
1438+
clock_was_set();
14421439
}
14431440

14441441
/**
@@ -1583,7 +1580,6 @@ struct timespec get_monotonic_coarse(void)
15831580
void do_timer(unsigned long ticks)
15841581
{
15851582
jiffies_64 += ticks;
1586-
update_wall_time();
15871583
calc_global_load(ticks);
15881584
}
15891585

@@ -1698,12 +1694,14 @@ int do_adjtimex(struct timex *txc)
16981694

16991695
if (tai != orig_tai) {
17001696
__timekeeping_set_tai_offset(tk, tai);
1701-
update_pvclock_gtod(tk, true);
1702-
clock_was_set_delayed();
1697+
timekeeping_update(tk, TK_MIRROR | TK_CLOCK_WAS_SET);
17031698
}
17041699
write_seqcount_end(&timekeeper_seq);
17051700
raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
17061701

1702+
if (tai != orig_tai)
1703+
clock_was_set();
1704+
17071705
ntp_notify_cmos_timer();
17081706

17091707
return ret;
@@ -1739,4 +1737,5 @@ void xtime_update(unsigned long ticks)
17391737
write_seqlock(&jiffies_lock);
17401738
do_timer(ticks);
17411739
write_sequnlock(&jiffies_lock);
1740+
update_wall_time();
17421741
}

0 commit comments

Comments
 (0)