Skip to content

Commit 3bc6d8c

Browse files
committed
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
2 parents e6e7214 + 22cc1ca commit 3bc6d8c

File tree

6 files changed

+60
-7
lines changed

6 files changed

+60
-7
lines changed

arch/x86/include/asm/apic.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ extern void init_apic_mappings(void);
135135
void register_lapic_address(unsigned long address);
136136
extern void setup_boot_APIC_clock(void);
137137
extern void setup_secondary_APIC_clock(void);
138+
extern void lapic_update_tsc_freq(void);
138139
extern int APIC_init_uniprocessor(void);
139140

140141
#ifdef CONFIG_X86_64
@@ -170,6 +171,7 @@ static inline void init_apic_mappings(void) { }
170171
static inline void disable_local_APIC(void) { }
171172
# define setup_boot_APIC_clock x86_init_noop
172173
# define setup_secondary_APIC_clock x86_init_noop
174+
static inline void lapic_update_tsc_freq(void) { }
173175
#endif /* !CONFIG_X86_LOCAL_APIC */
174176

175177
#ifdef CONFIG_X86_X2APIC

arch/x86/kernel/apic/apic.c

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ int lapic_get_maxlvt(void)
313313

314314
/* Clock divisor */
315315
#define APIC_DIVISOR 16
316-
#define TSC_DIVISOR 32
316+
#define TSC_DIVISOR 8
317317

318318
/*
319319
* This function sets up the local APIC timer, with a timeout of
@@ -565,12 +565,36 @@ static void setup_APIC_timer(void)
565565
CLOCK_EVT_FEAT_DUMMY);
566566
levt->set_next_event = lapic_next_deadline;
567567
clockevents_config_and_register(levt,
568-
(tsc_khz / TSC_DIVISOR) * 1000,
568+
tsc_khz * (1000 / TSC_DIVISOR),
569569
0xF, ~0UL);
570570
} else
571571
clockevents_register_device(levt);
572572
}
573573

574+
/*
575+
* Install the updated TSC frequency from recalibration at the TSC
576+
* deadline clockevent devices.
577+
*/
578+
static void __lapic_update_tsc_freq(void *info)
579+
{
580+
struct clock_event_device *levt = this_cpu_ptr(&lapic_events);
581+
582+
if (!this_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER))
583+
return;
584+
585+
clockevents_update_freq(levt, tsc_khz * (1000 / TSC_DIVISOR));
586+
}
587+
588+
void lapic_update_tsc_freq(void)
589+
{
590+
/*
591+
* The clockevent device's ->mult and ->shift can both be
592+
* changed. In order to avoid races, schedule the frequency
593+
* update code on each CPU.
594+
*/
595+
on_each_cpu(__lapic_update_tsc_freq, NULL, 0);
596+
}
597+
574598
/*
575599
* In this functions we calibrate APIC bus clocks to the external timer.
576600
*

arch/x86/kernel/hpet.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1242,7 +1242,7 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id)
12421242
memset(&curr_time, 0, sizeof(struct rtc_time));
12431243

12441244
if (hpet_rtc_flags & (RTC_UIE | RTC_AIE))
1245-
mc146818_set_time(&curr_time);
1245+
mc146818_get_time(&curr_time);
12461246

12471247
if (hpet_rtc_flags & RTC_UIE &&
12481248
curr_time.tm_sec != hpet_prev_update_sec) {

arch/x86/kernel/tsc.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <asm/nmi.h>
2323
#include <asm/x86_init.h>
2424
#include <asm/geode.h>
25+
#include <asm/apic.h>
2526

2627
unsigned int __read_mostly cpu_khz; /* TSC clocks / usec, not used here */
2728
EXPORT_SYMBOL(cpu_khz);
@@ -1249,6 +1250,9 @@ static void tsc_refine_calibration_work(struct work_struct *work)
12491250
(unsigned long)tsc_khz / 1000,
12501251
(unsigned long)tsc_khz % 1000);
12511252

1253+
/* Inform the TSC deadline clockevent devices about the recalibration */
1254+
lapic_update_tsc_freq();
1255+
12521256
out:
12531257
if (boot_cpu_has(X86_FEATURE_ART))
12541258
art_related_clocksource = &clocksource_tsc;

drivers/clocksource/arm_arch_timer.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
* it under the terms of the GNU General Public License version 2 as
99
* published by the Free Software Foundation.
1010
*/
11+
12+
#define pr_fmt(fmt) "arm_arch_timer: " fmt
13+
1114
#include <linux/init.h>
1215
#include <linux/kernel.h>
1316
#include <linux/device.h>
@@ -370,16 +373,33 @@ static bool arch_timer_has_nonsecure_ppi(void)
370373
arch_timer_ppi[PHYS_NONSECURE_PPI]);
371374
}
372375

376+
static u32 check_ppi_trigger(int irq)
377+
{
378+
u32 flags = irq_get_trigger_type(irq);
379+
380+
if (flags != IRQF_TRIGGER_HIGH && flags != IRQF_TRIGGER_LOW) {
381+
pr_warn("WARNING: Invalid trigger for IRQ%d, assuming level low\n", irq);
382+
pr_warn("WARNING: Please fix your firmware\n");
383+
flags = IRQF_TRIGGER_LOW;
384+
}
385+
386+
return flags;
387+
}
388+
373389
static int arch_timer_starting_cpu(unsigned int cpu)
374390
{
375391
struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt);
392+
u32 flags;
376393

377394
__arch_timer_setup(ARCH_CP15_TIMER, clk);
378395

379-
enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], 0);
396+
flags = check_ppi_trigger(arch_timer_ppi[arch_timer_uses_ppi]);
397+
enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], flags);
380398

381-
if (arch_timer_has_nonsecure_ppi())
382-
enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], 0);
399+
if (arch_timer_has_nonsecure_ppi()) {
400+
flags = check_ppi_trigger(arch_timer_ppi[PHYS_NONSECURE_PPI]);
401+
enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], flags);
402+
}
383403

384404
arch_counter_set_user_access();
385405
if (evtstrm_enable)

kernel/time/timer.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1496,6 +1496,7 @@ u64 get_next_timer_interrupt(unsigned long basej, u64 basem)
14961496
struct timer_base *base = this_cpu_ptr(&timer_bases[BASE_STD]);
14971497
u64 expires = KTIME_MAX;
14981498
unsigned long nextevt;
1499+
bool is_max_delta;
14991500

15001501
/*
15011502
* Pretend that there is no timer pending if the cpu is offline.
@@ -1506,6 +1507,7 @@ u64 get_next_timer_interrupt(unsigned long basej, u64 basem)
15061507

15071508
spin_lock(&base->lock);
15081509
nextevt = __next_timer_interrupt(base);
1510+
is_max_delta = (nextevt == base->clk + NEXT_TIMER_MAX_DELTA);
15091511
base->next_expiry = nextevt;
15101512
/*
15111513
* We have a fresh next event. Check whether we can forward the base:
@@ -1519,7 +1521,8 @@ u64 get_next_timer_interrupt(unsigned long basej, u64 basem)
15191521
expires = basem;
15201522
base->is_idle = false;
15211523
} else {
1522-
expires = basem + (nextevt - basej) * TICK_NSEC;
1524+
if (!is_max_delta)
1525+
expires = basem + (nextevt - basej) * TICK_NSEC;
15231526
/*
15241527
* If we expect to sleep more than a tick, mark the base idle:
15251528
*/

0 commit comments

Comments
 (0)