aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-11 23:01:33 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-11 23:01:33 -0500
commit1ebaf4f4e6912199f8a4e30ba3ab55da2b71bcdf (patch)
treed2073d669e6eaf15ece6fc6ce563438d74824412
parent743aa456c1834f76982af44e8b71d1a0b2a82e21 (diff)
parent5074b85bdd3a464efe7b6de2ec163f4c07696a20 (diff)
Merge branch 'x86-timers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 timer update from Ingo Molnar: "This tree includes HPET fixes and also implements a calibration-free, TSC match driven APIC timer interrupt mode: 'TSC deadline mode' supported in SandyBridge and later CPUs." * 'x86-timers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86: hpet: Fix inverted return value check in arch_setup_hpet_msi() x86: hpet: Fix masking of MSI interrupts x86: apic: Use tsc deadline for oneshot when available
-rw-r--r--Documentation/kernel-parameters.txt4
-rw-r--r--arch/x86/include/asm/msr-index.h2
-rw-r--r--arch/x86/kernel/apic/apic.c73
-rw-r--r--arch/x86/kernel/apic/io_apic.c5
-rw-r--r--arch/x86/kernel/hpet.c4
5 files changed, 64 insertions, 24 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 5190f1706414..28bd0f0e32c5 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1304,6 +1304,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
1304 lapic [X86-32,APIC] Enable the local APIC even if BIOS 1304 lapic [X86-32,APIC] Enable the local APIC even if BIOS
1305 disabled it. 1305 disabled it.
1306 1306
1307 lapic= [x86,APIC] "notscdeadline" Do not use TSC deadline
1308 value for LAPIC timer one-shot implementation. Default
1309 back to the programmable timer unit in the LAPIC.
1310
1307 lapic_timer_c2_ok [X86,APIC] trust the local apic timer 1311 lapic_timer_c2_ok [X86,APIC] trust the local apic timer
1308 in C2 power state. 1312 in C2 power state.
1309 1313
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 7f0edceb7563..e400cdb2dd65 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -337,6 +337,8 @@
337#define MSR_IA32_MISC_ENABLE_TURBO_DISABLE (1ULL << 38) 337#define MSR_IA32_MISC_ENABLE_TURBO_DISABLE (1ULL << 38)
338#define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE (1ULL << 39) 338#define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE (1ULL << 39)
339 339
340#define MSR_IA32_TSC_DEADLINE 0x000006E0
341
340/* P4/Xeon+ specific */ 342/* P4/Xeon+ specific */
341#define MSR_IA32_MCG_EAX 0x00000180 343#define MSR_IA32_MCG_EAX 0x00000180
342#define MSR_IA32_MCG_EBX 0x00000181 344#define MSR_IA32_MCG_EBX 0x00000181
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index b17416e72fbd..b994cc84aa7e 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -90,21 +90,6 @@ EXPORT_EARLY_PER_CPU_SYMBOL(x86_bios_cpu_apicid);
90 */ 90 */
91DEFINE_EARLY_PER_CPU_READ_MOSTLY(int, x86_cpu_to_logical_apicid, BAD_APICID); 91DEFINE_EARLY_PER_CPU_READ_MOSTLY(int, x86_cpu_to_logical_apicid, BAD_APICID);
92 92
93/*
94 * Knob to control our willingness to enable the local APIC.
95 *
96 * +1=force-enable
97 */
98static int force_enable_local_apic __initdata;
99/*
100 * APIC command line parameters
101 */
102static int __init parse_lapic(char *arg)
103{
104 force_enable_local_apic = 1;
105 return 0;
106}
107early_param("lapic", parse_lapic);
108/* Local APIC was disabled by the BIOS and enabled by the kernel */ 93/* Local APIC was disabled by the BIOS and enabled by the kernel */
109static int enabled_via_apicbase; 94static int enabled_via_apicbase;
110 95
@@ -133,6 +118,25 @@ static inline void imcr_apic_to_pic(void)
133} 118}
134#endif 119#endif
135 120
121/*
122 * Knob to control our willingness to enable the local APIC.
123 *
124 * +1=force-enable
125 */
126static int force_enable_local_apic __initdata;
127/*
128 * APIC command line parameters
129 */
130static int __init parse_lapic(char *arg)
131{
132 if (config_enabled(CONFIG_X86_32) && !arg)
133 force_enable_local_apic = 1;
134 else if (!strncmp(arg, "notscdeadline", 13))
135 setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER);
136 return 0;
137}
138early_param("lapic", parse_lapic);
139
136#ifdef CONFIG_X86_64 140#ifdef CONFIG_X86_64
137static int apic_calibrate_pmtmr __initdata; 141static int apic_calibrate_pmtmr __initdata;
138static __init int setup_apicpmtimer(char *s) 142static __init int setup_apicpmtimer(char *s)
@@ -315,6 +319,7 @@ int lapic_get_maxlvt(void)
315 319
316/* Clock divisor */ 320/* Clock divisor */
317#define APIC_DIVISOR 16 321#define APIC_DIVISOR 16
322#define TSC_DIVISOR 32
318 323
319/* 324/*
320 * This function sets up the local APIC timer, with a timeout of 325 * This function sets up the local APIC timer, with a timeout of
@@ -333,6 +338,9 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
333 lvtt_value = LOCAL_TIMER_VECTOR; 338 lvtt_value = LOCAL_TIMER_VECTOR;
334 if (!oneshot) 339 if (!oneshot)
335 lvtt_value |= APIC_LVT_TIMER_PERIODIC; 340 lvtt_value |= APIC_LVT_TIMER_PERIODIC;
341 else if (boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER))
342 lvtt_value |= APIC_LVT_TIMER_TSCDEADLINE;
343
336 if (!lapic_is_integrated()) 344 if (!lapic_is_integrated())
337 lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV); 345 lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV);
338 346
@@ -341,6 +349,11 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
341 349
342 apic_write(APIC_LVTT, lvtt_value); 350 apic_write(APIC_LVTT, lvtt_value);
343 351
352 if (lvtt_value & APIC_LVT_TIMER_TSCDEADLINE) {
353 printk_once(KERN_DEBUG "TSC deadline timer enabled\n");
354 return;
355 }
356
344 /* 357 /*
345 * Divide PICLK by 16 358 * Divide PICLK by 16
346 */ 359 */
@@ -453,6 +466,16 @@ static int lapic_next_event(unsigned long delta,
453 return 0; 466 return 0;
454} 467}
455 468
469static int lapic_next_deadline(unsigned long delta,
470 struct clock_event_device *evt)
471{
472 u64 tsc;
473
474 rdtscll(tsc);
475 wrmsrl(MSR_IA32_TSC_DEADLINE, tsc + (((u64) delta) * TSC_DIVISOR));
476 return 0;
477}
478
456/* 479/*
457 * Setup the lapic timer in periodic or oneshot mode 480 * Setup the lapic timer in periodic or oneshot mode
458 */ 481 */
@@ -533,7 +556,15 @@ static void __cpuinit setup_APIC_timer(void)
533 memcpy(levt, &lapic_clockevent, sizeof(*levt)); 556 memcpy(levt, &lapic_clockevent, sizeof(*levt));
534 levt->cpumask = cpumask_of(smp_processor_id()); 557 levt->cpumask = cpumask_of(smp_processor_id());
535 558
536 clockevents_register_device(levt); 559 if (this_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER)) {
560 levt->features &= ~(CLOCK_EVT_FEAT_PERIODIC |
561 CLOCK_EVT_FEAT_DUMMY);
562 levt->set_next_event = lapic_next_deadline;
563 clockevents_config_and_register(levt,
564 (tsc_khz / TSC_DIVISOR) * 1000,
565 0xF, ~0UL);
566 } else
567 clockevents_register_device(levt);
537} 568}
538 569
539/* 570/*
@@ -661,7 +692,9 @@ static int __init calibrate_APIC_clock(void)
661 * in the clockevent structure and return. 692 * in the clockevent structure and return.
662 */ 693 */
663 694
664 if (lapic_timer_frequency) { 695 if (boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER)) {
696 return 0;
697 } else if (lapic_timer_frequency) {
665 apic_printk(APIC_VERBOSE, "lapic timer already calibrated %d\n", 698 apic_printk(APIC_VERBOSE, "lapic timer already calibrated %d\n",
666 lapic_timer_frequency); 699 lapic_timer_frequency);
667 lapic_clockevent.mult = div_sc(lapic_timer_frequency/APIC_DIVISOR, 700 lapic_clockevent.mult = div_sc(lapic_timer_frequency/APIC_DIVISOR,
@@ -674,6 +707,9 @@ static int __init calibrate_APIC_clock(void)
674 return 0; 707 return 0;
675 } 708 }
676 709
710 apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"
711 "calibrating APIC timer ...\n");
712
677 local_irq_disable(); 713 local_irq_disable();
678 714
679 /* Replace the global interrupt handler */ 715 /* Replace the global interrupt handler */
@@ -811,9 +847,6 @@ void __init setup_boot_APIC_clock(void)
811 return; 847 return;
812 } 848 }
813 849
814 apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"
815 "calibrating APIC timer ...\n");
816
817 if (calibrate_APIC_clock()) { 850 if (calibrate_APIC_clock()) {
818 /* No broadcast on UP ! */ 851 /* No broadcast on UP ! */
819 if (num_possible_cpus() > 1) 852 if (num_possible_cpus() > 1)
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 70aa621df118..b739d398bb29 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -3305,8 +3305,9 @@ int arch_setup_hpet_msi(unsigned int irq, unsigned int id)
3305 int ret; 3305 int ret;
3306 3306
3307 if (irq_remapping_enabled) { 3307 if (irq_remapping_enabled) {
3308 if (!setup_hpet_msi_remapped(irq, id)) 3308 ret = setup_hpet_msi_remapped(irq, id);
3309 return -1; 3309 if (ret)
3310 return ret;
3310 } 3311 }
3311 3312
3312 ret = msi_compose_msg(NULL, irq, &msg, id); 3313 ret = msi_compose_msg(NULL, irq, &msg, id);
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 1460a5df92f7..e28670f9a589 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -434,7 +434,7 @@ void hpet_msi_unmask(struct irq_data *data)
434 434
435 /* unmask it */ 435 /* unmask it */
436 cfg = hpet_readl(HPET_Tn_CFG(hdev->num)); 436 cfg = hpet_readl(HPET_Tn_CFG(hdev->num));
437 cfg |= HPET_TN_FSB; 437 cfg |= HPET_TN_ENABLE | HPET_TN_FSB;
438 hpet_writel(cfg, HPET_Tn_CFG(hdev->num)); 438 hpet_writel(cfg, HPET_Tn_CFG(hdev->num));
439} 439}
440 440
@@ -445,7 +445,7 @@ void hpet_msi_mask(struct irq_data *data)
445 445
446 /* mask it */ 446 /* mask it */
447 cfg = hpet_readl(HPET_Tn_CFG(hdev->num)); 447 cfg = hpet_readl(HPET_Tn_CFG(hdev->num));
448 cfg &= ~HPET_TN_FSB; 448 cfg &= ~(HPET_TN_ENABLE | HPET_TN_FSB);
449 hpet_writel(cfg, HPET_Tn_CFG(hdev->num)); 449 hpet_writel(cfg, HPET_Tn_CFG(hdev->num));
450} 450}
451 451