Skip to content

Commit

Permalink
Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/…
Browse files Browse the repository at this point in the history
…linux/kernel/git/tip/tip

Pull core timer updates from Ingo Molnar:
 "The main changes in this cycle's merge are:

   - Implement shadow timekeeper to shorten in kernel reader side
     blocking, by Thomas Gleixner.

   - Posix timers enhancements by Pavel Emelyanov:

   - allocate timer ID per process, so that exact timer ID allocations
     can be re-created be checkpoint/restore code.

   - debuggability and tooling (/proc/PID/timers, etc.) improvements.

   - suspend/resume enhancements by Feng Tang: on certain new Intel Atom
     processors (Penwell and Cloverview), there is a feature that the
     TSC won't stop in S3 state, so the TSC value won't be reset to 0
     after resume.  This can be taken advantage of by the generic via
     the CLOCK_SOURCE_SUSPEND_NONSTOP flag: instead of using the RTC to
     recover/approximate sleep time, the main (and precise) clocksource
     can be used.

   - Fix /proc/timer_list for 4096 CPUs by Nathan Zimmer: on so many
     CPUs the file goes beyond 4MB of size and thus the current
     simplistic seqfile approach fails.  Convert /proc/timer_list to a
     proper seq_file with its own iterator.

   - Cleanups and refactorings of the core timekeeping code by John
     Stultz.

   - International Atomic Clock time is managed by the NTP code
     internally currently but not exposed externally.  Separate the TAI
     code out and add CLOCK_TAI support and TAI support to the hrtimer
     and posix-timer code, by John Stultz.

   - Add deep idle support enhacement to the broadcast clockevents core
     timer code, by Daniel Lezcano: add an opt-in CLOCK_EVT_FEAT_DYNIRQ
     clockevents feature (which will be utilized by future clockevents
     driver updates), which allows the use of IRQ affinities to avoid
     spurious wakeups of idle CPUs - the right CPU with an expiring
     timer will be woken.

   - Add new ARM bcm281xx clocksource driver, by Christian Daudt

   - ... various other fixes and cleanups"

* 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (52 commits)
  clockevents: Set dummy handler on CPU_DEAD shutdown
  timekeeping: Update tk->cycle_last in resume
  posix-timers: Remove unused variable
  clockevents: Switch into oneshot mode even if broadcast registered late
  timer_list: Convert timer list to be a proper seq_file
  timer_list: Split timer_list_show_tickdevices
  posix-timers: Show sigevent info in proc file
  posix-timers: Introduce /proc/PID/timers file
  posix timers: Allocate timer id per process (v2)
  timekeeping: Make sure to notify hrtimers when TAI offset changes
  hrtimer: Fix ktime_add_ns() overflow on 32bit architectures
  hrtimer: Add expiry time overflow check in hrtimer_interrupt
  timekeeping: Shorten seq_count region
  timekeeping: Implement a shadow timekeeper
  timekeeping: Delay update of clock->cycle_last
  timekeeping: Store cycle_last value in timekeeper struct as well
  ntp: Remove ntp_lock, using the timekeeping locks to protect ntp state
  timekeeping: Simplify tai updating from do_adjtimex
  timekeeping: Hold timekeepering locks in do_adjtimex and hardpps
  timekeeping: Move ADJ_SETOFFSET to top level do_adjtimex()
  ...
  • Loading branch information
torvalds committed Apr 30, 2013
2 parents 8700c95 + 6f7a05d commit ab86e97
Show file tree
Hide file tree
Showing 35 changed files with 1,178 additions and 385 deletions.
1 change: 1 addition & 0 deletions arch/arm/mach-bcm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ config ARCH_BCM
select ARM_ERRATA_764369 if SMP
select ARM_GIC
select CPU_V7
select CLKSRC_OF
select GENERIC_CLOCKEVENTS
select GENERIC_TIME
select GPIO_BCM
Expand Down
7 changes: 2 additions & 5 deletions arch/arm/mach-bcm/board_bcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,11 @@
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/irqchip.h>
#include <linux/clocksource.h>

#include <asm/mach/arch.h>
#include <asm/mach/time.h>

static void timer_init(void)
{
}


static void __init board_init(void)
{
Expand All @@ -35,7 +32,7 @@ static const char * const bcm11351_dt_compat[] = { "bcm,bcm11351", NULL, };

DT_MACHINE_START(BCM11351_DT, "Broadcom Application Processor")
.init_irq = irqchip_init,
.init_time = timer_init,
.init_time = clocksource_of_init,
.init_machine = board_init,
.dt_compat = bcm11351_dt_compat,
MACHINE_END
1 change: 1 addition & 0 deletions arch/x86/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ config X86
select OLD_SIGSUSPEND3 if X86_32 || IA32_EMULATION
select OLD_SIGACTION if X86_32
select COMPAT_OLD_SIGACTION if IA32_EMULATION
select RTC_LIB

config INSTRUCTION_DECODER
def_bool y
Expand Down
1 change: 1 addition & 0 deletions arch/x86/include/asm/cpufeature.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
#define X86_FEATURE_AMD_DCM (3*32+27) /* multi-node processor */
#define X86_FEATURE_APERFMPERF (3*32+28) /* APERFMPERF */
#define X86_FEATURE_EAGER_FPU (3*32+29) /* "eagerfpu" Non lazy FPU restore */
#define X86_FEATURE_NONSTOP_TSC_S3 (3*32+30) /* TSC doesn't stop in S3 state */

/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
#define X86_FEATURE_XMM3 (4*32+ 0) /* "pni" SSE-3 */
Expand Down
12 changes: 12 additions & 0 deletions arch/x86/kernel/cpu/intel.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,18 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
sched_clock_stable = 1;
}

/* Penwell and Cloverview have the TSC which doesn't sleep on S3 */
if (c->x86 == 6) {
switch (c->x86_model) {
case 0x27: /* Penwell */
case 0x35: /* Cloverview */
set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC_S3);
break;
default:
break;
}
}

/*
* There is a known erratum on Pentium III and Core Solo
* and Core Duo CPUs.
Expand Down
69 changes: 12 additions & 57 deletions arch/x86/kernel/rtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <asm/x86_init.h>
#include <asm/time.h>
#include <asm/mrst.h>
#include <asm/rtc.h>

#ifdef CONFIG_X86_32
/*
Expand All @@ -36,70 +37,24 @@ EXPORT_SYMBOL(rtc_lock);
* nowtime is written into the registers of the CMOS clock, it will
* jump to the next second precisely 500 ms later. Check the Motorola
* MC146818A or Dallas DS12887 data sheet for details.
*
* BUG: This routine does not handle hour overflow properly; it just
* sets the minutes. Usually you'll only notice that after reboot!
*/
int mach_set_rtc_mmss(unsigned long nowtime)
{
int real_seconds, real_minutes, cmos_minutes;
unsigned char save_control, save_freq_select;
unsigned long flags;
struct rtc_time tm;
int retval = 0;

spin_lock_irqsave(&rtc_lock, flags);

/* tell the clock it's being set */
save_control = CMOS_READ(RTC_CONTROL);
CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);

/* stop and reset prescaler */
save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);

cmos_minutes = CMOS_READ(RTC_MINUTES);
if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
cmos_minutes = bcd2bin(cmos_minutes);

/*
* since we're only adjusting minutes and seconds,
* don't interfere with hour overflow. This avoids
* messing with unknown time zones but requires your
* RTC not to be off by more than 15 minutes
*/
real_seconds = nowtime % 60;
real_minutes = nowtime / 60;
/* correct for half hour time zone */
if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
real_minutes += 30;
real_minutes %= 60;

if (abs(real_minutes - cmos_minutes) < 30) {
if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
real_seconds = bin2bcd(real_seconds);
real_minutes = bin2bcd(real_minutes);
}
CMOS_WRITE(real_seconds, RTC_SECONDS);
CMOS_WRITE(real_minutes, RTC_MINUTES);
rtc_time_to_tm(nowtime, &tm);
if (!rtc_valid_tm(&tm)) {
retval = set_rtc_time(&tm);
if (retval)
printk(KERN_ERR "%s: RTC write failed with error %d\n",
__FUNCTION__, retval);
} else {
printk_once(KERN_NOTICE
"set_rtc_mmss: can't update from %d to %d\n",
cmos_minutes, real_minutes);
retval = -1;
printk(KERN_ERR
"%s: Invalid RTC value: write of %lx to RTC failed\n",
__FUNCTION__, nowtime);
retval = -EINVAL;
}

/* The following flags have to be released exactly in this order,
* otherwise the DS12887 (popular MC146818A clone with integrated
* battery and quartz) will not reset the oscillator and will not
* update precisely 500 ms later. You won't find this mentioned in
* the Dallas Semiconductor data sheets, but who believes data
* sheets anyway ... -- Markus Kuhn
*/
CMOS_WRITE(save_control, RTC_CONTROL);
CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);

spin_unlock_irqrestore(&rtc_lock, flags);

return retval;
}

Expand Down
6 changes: 5 additions & 1 deletion arch/x86/kernel/tsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -768,7 +768,8 @@ static cycle_t read_tsc(struct clocksource *cs)

static void resume_tsc(struct clocksource *cs)
{
clocksource_tsc.cycle_last = 0;
if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC_S3))
clocksource_tsc.cycle_last = 0;
}

static struct clocksource clocksource_tsc = {
Expand Down Expand Up @@ -939,6 +940,9 @@ static int __init init_tsc_clocksource(void)
clocksource_tsc.flags &= ~CLOCK_SOURCE_IS_CONTINUOUS;
}

if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC_S3))
clocksource_tsc.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP;

/*
* Trust the results of the earlier calibration on systems
* exporting a reliable TSC.
Expand Down
24 changes: 16 additions & 8 deletions arch/x86/platform/efi/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
#include <asm/x86_init.h>
#include <asm/rtc.h>

#define EFI_DEBUG 1

Expand Down Expand Up @@ -352,24 +353,31 @@ static efi_status_t __init phys_efi_get_time(efi_time_t *tm,

int efi_set_rtc_mmss(unsigned long nowtime)
{
int real_seconds, real_minutes;
efi_status_t status;
efi_time_t eft;
efi_time_cap_t cap;
struct rtc_time tm;

status = efi.get_time(&eft, &cap);
if (status != EFI_SUCCESS) {
pr_err("Oops: efitime: can't read time!\n");
return -1;
}

real_seconds = nowtime % 60;
real_minutes = nowtime / 60;
if (((abs(real_minutes - eft.minute) + 15)/30) & 1)
real_minutes += 30;
real_minutes %= 60;
eft.minute = real_minutes;
eft.second = real_seconds;
rtc_time_to_tm(nowtime, &tm);
if (!rtc_valid_tm(&tm)) {
eft.year = tm.tm_year + 1900;
eft.month = tm.tm_mon + 1;
eft.day = tm.tm_mday;
eft.minute = tm.tm_min;
eft.second = tm.tm_sec;
eft.nanosecond = 0;
} else {
printk(KERN_ERR
"%s: Invalid EFI RTC value: write of %lx to EFI RTC failed\n",
__FUNCTION__, nowtime);
return -1;
}

status = efi.set_time(&eft);
if (status != EFI_SUCCESS) {
Expand Down
44 changes: 26 additions & 18 deletions arch/x86/platform/mrst/vrtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,27 +85,35 @@ unsigned long vrtc_get_time(void)
return mktime(year, mon, mday, hour, min, sec);
}

/* Only care about the minutes and seconds */
int vrtc_set_mmss(unsigned long nowtime)
{
int real_sec, real_min;
unsigned long flags;
int vrtc_min;

spin_lock_irqsave(&rtc_lock, flags);
vrtc_min = vrtc_cmos_read(RTC_MINUTES);

real_sec = nowtime % 60;
real_min = nowtime / 60;
if (((abs(real_min - vrtc_min) + 15)/30) & 1)
real_min += 30;
real_min %= 60;

vrtc_cmos_write(real_sec, RTC_SECONDS);
vrtc_cmos_write(real_min, RTC_MINUTES);
spin_unlock_irqrestore(&rtc_lock, flags);

return 0;
struct rtc_time tm;
int year;
int retval = 0;

rtc_time_to_tm(nowtime, &tm);
if (!rtc_valid_tm(&tm) && tm.tm_year >= 72) {
/*
* tm.year is the number of years since 1900, and the
* vrtc need the years since 1972.
*/
year = tm.tm_year - 72;
spin_lock_irqsave(&rtc_lock, flags);
vrtc_cmos_write(year, RTC_YEAR);
vrtc_cmos_write(tm.tm_mon, RTC_MONTH);
vrtc_cmos_write(tm.tm_mday, RTC_DAY_OF_MONTH);
vrtc_cmos_write(tm.tm_hour, RTC_HOURS);
vrtc_cmos_write(tm.tm_min, RTC_MINUTES);
vrtc_cmos_write(tm.tm_sec, RTC_SECONDS);
spin_unlock_irqrestore(&rtc_lock, flags);
} else {
printk(KERN_ERR
"%s: Invalid vRTC value: write of %lx to vRTC failed\n",
__FUNCTION__, nowtime);
retval = -EINVAL;
}
return retval;
}

void __init mrst_rtc_init(void)
Expand Down
1 change: 1 addition & 0 deletions drivers/clocksource/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ obj-$(CONFIG_ARCH_BCM2835) += bcm2835_timer.o
obj-$(CONFIG_SUNXI_TIMER) += sunxi_timer.o
obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o
obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o
obj-$(CONFIG_ARCH_BCM) += bcm_kona_timer.o

obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o
obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o
Loading

0 comments on commit ab86e97

Please sign in to comment.