Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull timer fixes from Ingo Molnar: "Misc fixes: a /dev/rtc regression fix, two APIC timer period calibration fixes, an ARM clocksource driver fix and a NOHZ power use regression fix" * 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/hpet: Fix /dev/rtc breakage caused by RTC cleanup x86/timers/apic: Inform TSC deadline clockevent device about recalibration x86/timers/apic: Fix imprecise timer interrupts by eliminating TSC clockevents frequency roundoff error timers: Fix get_next_timer_interrupt() computation clocksource/arm_arch_timer: Force per-CPU interrupt to be level-triggered
This commit is contained in:
@@ -313,7 +313,7 @@ int lapic_get_maxlvt(void)
|
||||
|
||||
/* Clock divisor */
|
||||
#define APIC_DIVISOR 16
|
||||
#define TSC_DIVISOR 32
|
||||
#define TSC_DIVISOR 8
|
||||
|
||||
/*
|
||||
* This function sets up the local APIC timer, with a timeout of
|
||||
@@ -565,12 +565,36 @@ static void setup_APIC_timer(void)
|
||||
CLOCK_EVT_FEAT_DUMMY);
|
||||
levt->set_next_event = lapic_next_deadline;
|
||||
clockevents_config_and_register(levt,
|
||||
(tsc_khz / TSC_DIVISOR) * 1000,
|
||||
tsc_khz * (1000 / TSC_DIVISOR),
|
||||
0xF, ~0UL);
|
||||
} else
|
||||
clockevents_register_device(levt);
|
||||
}
|
||||
|
||||
/*
|
||||
* Install the updated TSC frequency from recalibration at the TSC
|
||||
* deadline clockevent devices.
|
||||
*/
|
||||
static void __lapic_update_tsc_freq(void *info)
|
||||
{
|
||||
struct clock_event_device *levt = this_cpu_ptr(&lapic_events);
|
||||
|
||||
if (!this_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER))
|
||||
return;
|
||||
|
||||
clockevents_update_freq(levt, tsc_khz * (1000 / TSC_DIVISOR));
|
||||
}
|
||||
|
||||
void lapic_update_tsc_freq(void)
|
||||
{
|
||||
/*
|
||||
* The clockevent device's ->mult and ->shift can both be
|
||||
* changed. In order to avoid races, schedule the frequency
|
||||
* update code on each CPU.
|
||||
*/
|
||||
on_each_cpu(__lapic_update_tsc_freq, NULL, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* In this functions we calibrate APIC bus clocks to the external timer.
|
||||
*
|
||||
|
@@ -1242,7 +1242,7 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id)
|
||||
memset(&curr_time, 0, sizeof(struct rtc_time));
|
||||
|
||||
if (hpet_rtc_flags & (RTC_UIE | RTC_AIE))
|
||||
mc146818_set_time(&curr_time);
|
||||
mc146818_get_time(&curr_time);
|
||||
|
||||
if (hpet_rtc_flags & RTC_UIE &&
|
||||
curr_time.tm_sec != hpet_prev_update_sec) {
|
||||
|
@@ -22,6 +22,7 @@
|
||||
#include <asm/nmi.h>
|
||||
#include <asm/x86_init.h>
|
||||
#include <asm/geode.h>
|
||||
#include <asm/apic.h>
|
||||
|
||||
unsigned int __read_mostly cpu_khz; /* TSC clocks / usec, not used here */
|
||||
EXPORT_SYMBOL(cpu_khz);
|
||||
@@ -1249,6 +1250,9 @@ static void tsc_refine_calibration_work(struct work_struct *work)
|
||||
(unsigned long)tsc_khz / 1000,
|
||||
(unsigned long)tsc_khz % 1000);
|
||||
|
||||
/* Inform the TSC deadline clockevent devices about the recalibration */
|
||||
lapic_update_tsc_freq();
|
||||
|
||||
out:
|
||||
if (boot_cpu_has(X86_FEATURE_ART))
|
||||
art_related_clocksource = &clocksource_tsc;
|
||||
|
Reference in New Issue
Block a user