diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-11-18 19:16:18 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-11-18 19:16:18 -0500 |
| commit | 5c6b4e84cbc59996bb14f88d997870751d675f3f (patch) | |
| tree | a86092c3ead87cd1fffba7fb808e02bcaeb9f3a2 | |
| parent | ddddefa99db4ae54a63dcd737d224bc3cc0f2d8a (diff) | |
| parent | 0d2f096b8785b67c38afcf6e1fbb9674af2e05ca (diff) | |
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
random: Fix handing of arch_get_random_long in get_random_bytes()
x86: Call stop_machine_text_poke() on all CPUs
x86, ioapic: Only print ioapic debug information for IRQs belonging to an ioapic chip
x86/mrst: Avoid reporting wrong nmi status
x86/mrst: Add support for Penwell clock calibration
x86/apic: Allow use of lapic timer early calibration result
x86/apic: Do not clear nr_irqs_gsi if no legacy irqs
x86/platform: Add a wallclock_init func to x86_platforms ops
x86/mce: Make mce_chrdev_ops 'static const'
| -rw-r--r-- | arch/x86/include/asm/apic.h | 1 | ||||
| -rw-r--r-- | arch/x86/include/asm/mach_traps.h | 2 | ||||
| -rw-r--r-- | arch/x86/include/asm/mce.h | 5 | ||||
| -rw-r--r-- | arch/x86/include/asm/mrst.h | 7 | ||||
| -rw-r--r-- | arch/x86/include/asm/x86_init.h | 3 | ||||
| -rw-r--r-- | arch/x86/kernel/alternative.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/apic.c | 33 | ||||
| -rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 9 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce-inject.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce.c | 25 | ||||
| -rw-r--r-- | arch/x86/kernel/nmi.c | 3 | ||||
| -rw-r--r-- | arch/x86/kernel/setup.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/x86_init.c | 4 | ||||
| -rw-r--r-- | arch/x86/platform/mrst/mrst.c | 46 |
14 files changed, 121 insertions, 23 deletions
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 9b7273cb2193..1a6c09af048f 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h | |||
| @@ -49,6 +49,7 @@ extern unsigned int apic_verbosity; | |||
| 49 | extern int local_apic_timer_c2_ok; | 49 | extern int local_apic_timer_c2_ok; |
| 50 | 50 | ||
| 51 | extern int disable_apic; | 51 | extern int disable_apic; |
| 52 | extern unsigned int lapic_timer_frequency; | ||
| 52 | 53 | ||
| 53 | #ifdef CONFIG_SMP | 54 | #ifdef CONFIG_SMP |
| 54 | extern void __inquire_remote_apic(int apicid); | 55 | extern void __inquire_remote_apic(int apicid); |
diff --git a/arch/x86/include/asm/mach_traps.h b/arch/x86/include/asm/mach_traps.h index 72a8b52e7dfd..a01e7ec7d237 100644 --- a/arch/x86/include/asm/mach_traps.h +++ b/arch/x86/include/asm/mach_traps.h | |||
| @@ -17,7 +17,7 @@ | |||
| 17 | #define NMI_REASON_CLEAR_IOCHK 0x08 | 17 | #define NMI_REASON_CLEAR_IOCHK 0x08 |
| 18 | #define NMI_REASON_CLEAR_MASK 0x0f | 18 | #define NMI_REASON_CLEAR_MASK 0x0f |
| 19 | 19 | ||
| 20 | static inline unsigned char get_nmi_reason(void) | 20 | static inline unsigned char default_get_nmi_reason(void) |
| 21 | { | 21 | { |
| 22 | return inb(NMI_REASON_PORT); | 22 | return inb(NMI_REASON_PORT); |
| 23 | } | 23 | } |
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h index c9321f34e55b..0e8ae57d3656 100644 --- a/arch/x86/include/asm/mce.h +++ b/arch/x86/include/asm/mce.h | |||
| @@ -201,7 +201,10 @@ int mce_notify_irq(void); | |||
| 201 | void mce_notify_process(void); | 201 | void mce_notify_process(void); |
| 202 | 202 | ||
| 203 | DECLARE_PER_CPU(struct mce, injectm); | 203 | DECLARE_PER_CPU(struct mce, injectm); |
| 204 | extern struct file_operations mce_chrdev_ops; | 204 | |
| 205 | extern void register_mce_write_callback(ssize_t (*)(struct file *filp, | ||
| 206 | const char __user *ubuf, | ||
| 207 | size_t usize, loff_t *off)); | ||
| 205 | 208 | ||
| 206 | /* | 209 | /* |
| 207 | * Exception handler | 210 | * Exception handler |
diff --git a/arch/x86/include/asm/mrst.h b/arch/x86/include/asm/mrst.h index 719f00b28ff5..e6283129c821 100644 --- a/arch/x86/include/asm/mrst.h +++ b/arch/x86/include/asm/mrst.h | |||
| @@ -44,6 +44,13 @@ enum mrst_timer_options { | |||
| 44 | 44 | ||
| 45 | extern enum mrst_timer_options mrst_timer_options; | 45 | extern enum mrst_timer_options mrst_timer_options; |
| 46 | 46 | ||
| 47 | /* | ||
| 48 | * Penwell uses spread spectrum clock, so the freq number is not exactly | ||
| 49 | * the same as reported by MSR based on SDM. | ||
| 50 | */ | ||
| 51 | #define PENWELL_FSB_FREQ_83SKU 83200 | ||
| 52 | #define PENWELL_FSB_FREQ_100SKU 99840 | ||
| 53 | |||
| 47 | #define SFI_MTMR_MAX_NUM 8 | 54 | #define SFI_MTMR_MAX_NUM 8 |
| 48 | #define SFI_MRTC_MAX 8 | 55 | #define SFI_MRTC_MAX 8 |
| 49 | 56 | ||
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h index d3d859035af9..1971e652d24b 100644 --- a/arch/x86/include/asm/x86_init.h +++ b/arch/x86/include/asm/x86_init.h | |||
| @@ -152,6 +152,7 @@ struct x86_cpuinit_ops { | |||
| 152 | /** | 152 | /** |
| 153 | * struct x86_platform_ops - platform specific runtime functions | 153 | * struct x86_platform_ops - platform specific runtime functions |
| 154 | * @calibrate_tsc: calibrate TSC | 154 | * @calibrate_tsc: calibrate TSC |
| 155 | * @wallclock_init: init the wallclock device | ||
| 155 | * @get_wallclock: get time from HW clock like RTC etc. | 156 | * @get_wallclock: get time from HW clock like RTC etc. |
| 156 | * @set_wallclock: set time back to HW clock | 157 | * @set_wallclock: set time back to HW clock |
| 157 | * @is_untracked_pat_range exclude from PAT logic | 158 | * @is_untracked_pat_range exclude from PAT logic |
| @@ -160,11 +161,13 @@ struct x86_cpuinit_ops { | |||
| 160 | */ | 161 | */ |
| 161 | struct x86_platform_ops { | 162 | struct x86_platform_ops { |
| 162 | unsigned long (*calibrate_tsc)(void); | 163 | unsigned long (*calibrate_tsc)(void); |
| 164 | void (*wallclock_init)(void); | ||
| 163 | unsigned long (*get_wallclock)(void); | 165 | unsigned long (*get_wallclock)(void); |
| 164 | int (*set_wallclock)(unsigned long nowtime); | 166 | int (*set_wallclock)(unsigned long nowtime); |
| 165 | void (*iommu_shutdown)(void); | 167 | void (*iommu_shutdown)(void); |
| 166 | bool (*is_untracked_pat_range)(u64 start, u64 end); | 168 | bool (*is_untracked_pat_range)(u64 start, u64 end); |
| 167 | void (*nmi_init)(void); | 169 | void (*nmi_init)(void); |
| 170 | unsigned char (*get_nmi_reason)(void); | ||
| 168 | int (*i8042_detect)(void); | 171 | int (*i8042_detect)(void); |
| 169 | }; | 172 | }; |
| 170 | 173 | ||
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index c63822816249..1f84794f0759 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c | |||
| @@ -738,5 +738,5 @@ void __kprobes text_poke_smp_batch(struct text_poke_param *params, int n) | |||
| 738 | 738 | ||
| 739 | atomic_set(&stop_machine_first, 1); | 739 | atomic_set(&stop_machine_first, 1); |
| 740 | wrote_text = 0; | 740 | wrote_text = 0; |
| 741 | __stop_machine(stop_machine_text_poke, (void *)&tpp, NULL); | 741 | __stop_machine(stop_machine_text_poke, (void *)&tpp, cpu_online_mask); |
| 742 | } | 742 | } |
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index a2fd72e0ab35..f98d84caf94c 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
| @@ -186,7 +186,7 @@ static struct resource lapic_resource = { | |||
| 186 | .flags = IORESOURCE_MEM | IORESOURCE_BUSY, | 186 | .flags = IORESOURCE_MEM | IORESOURCE_BUSY, |
| 187 | }; | 187 | }; |
| 188 | 188 | ||
| 189 | static unsigned int calibration_result; | 189 | unsigned int lapic_timer_frequency = 0; |
| 190 | 190 | ||
| 191 | static void apic_pm_activate(void); | 191 | static void apic_pm_activate(void); |
| 192 | 192 | ||
| @@ -454,7 +454,7 @@ static void lapic_timer_setup(enum clock_event_mode mode, | |||
| 454 | switch (mode) { | 454 | switch (mode) { |
| 455 | case CLOCK_EVT_MODE_PERIODIC: | 455 | case CLOCK_EVT_MODE_PERIODIC: |
| 456 | case CLOCK_EVT_MODE_ONESHOT: | 456 | case CLOCK_EVT_MODE_ONESHOT: |
| 457 | __setup_APIC_LVTT(calibration_result, | 457 | __setup_APIC_LVTT(lapic_timer_frequency, |
| 458 | mode != CLOCK_EVT_MODE_PERIODIC, 1); | 458 | mode != CLOCK_EVT_MODE_PERIODIC, 1); |
| 459 | break; | 459 | break; |
| 460 | case CLOCK_EVT_MODE_UNUSED: | 460 | case CLOCK_EVT_MODE_UNUSED: |
| @@ -638,6 +638,25 @@ static int __init calibrate_APIC_clock(void) | |||
| 638 | long delta, deltatsc; | 638 | long delta, deltatsc; |
| 639 | int pm_referenced = 0; | 639 | int pm_referenced = 0; |
| 640 | 640 | ||
| 641 | /** | ||
| 642 | * check if lapic timer has already been calibrated by platform | ||
| 643 | * specific routine, such as tsc calibration code. if so, we just fill | ||
| 644 | * in the clockevent structure and return. | ||
| 645 | */ | ||
| 646 | |||
| 647 | if (lapic_timer_frequency) { | ||
| 648 | apic_printk(APIC_VERBOSE, "lapic timer already calibrated %d\n", | ||
| 649 | lapic_timer_frequency); | ||
| 650 | lapic_clockevent.mult = div_sc(lapic_timer_frequency/APIC_DIVISOR, | ||
| 651 | TICK_NSEC, lapic_clockevent.shift); | ||
| 652 | lapic_clockevent.max_delta_ns = | ||
| 653 | clockevent_delta2ns(0x7FFFFF, &lapic_clockevent); | ||
| 654 | lapic_clockevent.min_delta_ns = | ||
| 655 | clockevent_delta2ns(0xF, &lapic_clockevent); | ||
| 656 | lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY; | ||
| 657 | return 0; | ||
| 658 | } | ||
| 659 | |||
| 641 | local_irq_disable(); | 660 | local_irq_disable(); |
| 642 | 661 | ||
| 643 | /* Replace the global interrupt handler */ | 662 | /* Replace the global interrupt handler */ |
| @@ -679,12 +698,12 @@ static int __init calibrate_APIC_clock(void) | |||
| 679 | lapic_clockevent.min_delta_ns = | 698 | lapic_clockevent.min_delta_ns = |
| 680 | clockevent_delta2ns(0xF, &lapic_clockevent); | 699 | clockevent_delta2ns(0xF, &lapic_clockevent); |
| 681 | 700 | ||
| 682 | calibration_result = (delta * APIC_DIVISOR) / LAPIC_CAL_LOOPS; | 701 | lapic_timer_frequency = (delta * APIC_DIVISOR) / LAPIC_CAL_LOOPS; |
| 683 | 702 | ||
| 684 | apic_printk(APIC_VERBOSE, "..... delta %ld\n", delta); | 703 | apic_printk(APIC_VERBOSE, "..... delta %ld\n", delta); |
| 685 | apic_printk(APIC_VERBOSE, "..... mult: %u\n", lapic_clockevent.mult); | 704 | apic_printk(APIC_VERBOSE, "..... mult: %u\n", lapic_clockevent.mult); |
| 686 | apic_printk(APIC_VERBOSE, "..... calibration result: %u\n", | 705 | apic_printk(APIC_VERBOSE, "..... calibration result: %u\n", |
| 687 | calibration_result); | 706 | lapic_timer_frequency); |
| 688 | 707 | ||
| 689 | if (cpu_has_tsc) { | 708 | if (cpu_has_tsc) { |
| 690 | apic_printk(APIC_VERBOSE, "..... CPU clock speed is " | 709 | apic_printk(APIC_VERBOSE, "..... CPU clock speed is " |
| @@ -695,13 +714,13 @@ static int __init calibrate_APIC_clock(void) | |||
| 695 | 714 | ||
| 696 | apic_printk(APIC_VERBOSE, "..... host bus clock speed is " | 715 | apic_printk(APIC_VERBOSE, "..... host bus clock speed is " |
| 697 | "%u.%04u MHz.\n", | 716 | "%u.%04u MHz.\n", |
| 698 | calibration_result / (1000000 / HZ), | 717 | lapic_timer_frequency / (1000000 / HZ), |
| 699 | calibration_result % (1000000 / HZ)); | 718 | lapic_timer_frequency % (1000000 / HZ)); |
| 700 | 719 | ||
| 701 | /* | 720 | /* |
| 702 | * Do a sanity check on the APIC calibration result | 721 | * Do a sanity check on the APIC calibration result |
| 703 | */ | 722 | */ |
| 704 | if (calibration_result < (1000000 / HZ)) { | 723 | if (lapic_timer_frequency < (1000000 / HZ)) { |
| 705 | local_irq_enable(); | 724 | local_irq_enable(); |
| 706 | pr_warning("APIC frequency too slow, disabling apic timer\n"); | 725 | pr_warning("APIC frequency too slow, disabling apic timer\n"); |
| 707 | return -1; | 726 | return -1; |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 3c31fa98af6d..6d939d7847e2 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
| @@ -193,10 +193,8 @@ int __init arch_early_irq_init(void) | |||
| 193 | struct irq_cfg *cfg; | 193 | struct irq_cfg *cfg; |
| 194 | int count, node, i; | 194 | int count, node, i; |
| 195 | 195 | ||
| 196 | if (!legacy_pic->nr_legacy_irqs) { | 196 | if (!legacy_pic->nr_legacy_irqs) |
| 197 | nr_irqs_gsi = 0; | ||
| 198 | io_apic_irqs = ~0UL; | 197 | io_apic_irqs = ~0UL; |
| 199 | } | ||
| 200 | 198 | ||
| 201 | for (i = 0; i < nr_ioapics; i++) { | 199 | for (i = 0; i < nr_ioapics; i++) { |
| 202 | ioapics[i].saved_registers = | 200 | ioapics[i].saved_registers = |
| @@ -1696,6 +1694,7 @@ __apicdebuginit(void) print_IO_APICs(void) | |||
| 1696 | int ioapic_idx; | 1694 | int ioapic_idx; |
| 1697 | struct irq_cfg *cfg; | 1695 | struct irq_cfg *cfg; |
| 1698 | unsigned int irq; | 1696 | unsigned int irq; |
| 1697 | struct irq_chip *chip; | ||
| 1699 | 1698 | ||
| 1700 | printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries); | 1699 | printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries); |
| 1701 | for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) | 1700 | for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) |
| @@ -1716,6 +1715,10 @@ __apicdebuginit(void) print_IO_APICs(void) | |||
| 1716 | for_each_active_irq(irq) { | 1715 | for_each_active_irq(irq) { |
| 1717 | struct irq_pin_list *entry; | 1716 | struct irq_pin_list *entry; |
| 1718 | 1717 | ||
| 1718 | chip = irq_get_chip(irq); | ||
| 1719 | if (chip != &ioapic_chip) | ||
| 1720 | continue; | ||
| 1721 | |||
| 1719 | cfg = irq_get_chip_data(irq); | 1722 | cfg = irq_get_chip_data(irq); |
| 1720 | if (!cfg) | 1723 | if (!cfg) |
| 1721 | continue; | 1724 | continue; |
diff --git a/arch/x86/kernel/cpu/mcheck/mce-inject.c b/arch/x86/kernel/cpu/mcheck/mce-inject.c index 6199232161cf..319882ef848d 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-inject.c +++ b/arch/x86/kernel/cpu/mcheck/mce-inject.c | |||
| @@ -208,7 +208,7 @@ static int inject_init(void) | |||
| 208 | if (!alloc_cpumask_var(&mce_inject_cpumask, GFP_KERNEL)) | 208 | if (!alloc_cpumask_var(&mce_inject_cpumask, GFP_KERNEL)) |
| 209 | return -ENOMEM; | 209 | return -ENOMEM; |
| 210 | printk(KERN_INFO "Machine check injector initialized\n"); | 210 | printk(KERN_INFO "Machine check injector initialized\n"); |
| 211 | mce_chrdev_ops.write = mce_write; | 211 | register_mce_write_callback(mce_write); |
| 212 | register_nmi_handler(NMI_LOCAL, mce_raise_notify, 0, | 212 | register_nmi_handler(NMI_LOCAL, mce_raise_notify, 0, |
| 213 | "mce_notify"); | 213 | "mce_notify"); |
| 214 | return 0; | 214 | return 0; |
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 362056aefeb4..2af127d4c3d1 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c | |||
| @@ -1634,16 +1634,35 @@ static long mce_chrdev_ioctl(struct file *f, unsigned int cmd, | |||
| 1634 | } | 1634 | } |
| 1635 | } | 1635 | } |
| 1636 | 1636 | ||
| 1637 | /* Modified in mce-inject.c, so not static or const */ | 1637 | static ssize_t (*mce_write)(struct file *filp, const char __user *ubuf, |
| 1638 | struct file_operations mce_chrdev_ops = { | 1638 | size_t usize, loff_t *off); |
| 1639 | |||
| 1640 | void register_mce_write_callback(ssize_t (*fn)(struct file *filp, | ||
| 1641 | const char __user *ubuf, | ||
| 1642 | size_t usize, loff_t *off)) | ||
| 1643 | { | ||
| 1644 | mce_write = fn; | ||
| 1645 | } | ||
| 1646 | EXPORT_SYMBOL_GPL(register_mce_write_callback); | ||
| 1647 | |||
| 1648 | ssize_t mce_chrdev_write(struct file *filp, const char __user *ubuf, | ||
| 1649 | size_t usize, loff_t *off) | ||
| 1650 | { | ||
| 1651 | if (mce_write) | ||
| 1652 | return mce_write(filp, ubuf, usize, off); | ||
| 1653 | else | ||
| 1654 | return -EINVAL; | ||
| 1655 | } | ||
| 1656 | |||
| 1657 | static const struct file_operations mce_chrdev_ops = { | ||
| 1639 | .open = mce_chrdev_open, | 1658 | .open = mce_chrdev_open, |
| 1640 | .release = mce_chrdev_release, | 1659 | .release = mce_chrdev_release, |
| 1641 | .read = mce_chrdev_read, | 1660 | .read = mce_chrdev_read, |
| 1661 | .write = mce_chrdev_write, | ||
| 1642 | .poll = mce_chrdev_poll, | 1662 | .poll = mce_chrdev_poll, |
| 1643 | .unlocked_ioctl = mce_chrdev_ioctl, | 1663 | .unlocked_ioctl = mce_chrdev_ioctl, |
| 1644 | .llseek = no_llseek, | 1664 | .llseek = no_llseek, |
| 1645 | }; | 1665 | }; |
| 1646 | EXPORT_SYMBOL_GPL(mce_chrdev_ops); | ||
| 1647 | 1666 | ||
| 1648 | static struct miscdevice mce_chrdev_device = { | 1667 | static struct miscdevice mce_chrdev_device = { |
| 1649 | MISC_MCELOG_MINOR, | 1668 | MISC_MCELOG_MINOR, |
diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c index b9c8628974af..e88f37b58ddd 100644 --- a/arch/x86/kernel/nmi.c +++ b/arch/x86/kernel/nmi.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <asm/traps.h> | 29 | #include <asm/traps.h> |
| 30 | #include <asm/mach_traps.h> | 30 | #include <asm/mach_traps.h> |
| 31 | #include <asm/nmi.h> | 31 | #include <asm/nmi.h> |
| 32 | #include <asm/x86_init.h> | ||
| 32 | 33 | ||
| 33 | #define NMI_MAX_NAMELEN 16 | 34 | #define NMI_MAX_NAMELEN 16 |
| 34 | struct nmiaction { | 35 | struct nmiaction { |
| @@ -348,7 +349,7 @@ static notrace __kprobes void default_do_nmi(struct pt_regs *regs) | |||
| 348 | 349 | ||
| 349 | /* Non-CPU-specific NMI: NMI sources can be processed on any CPU */ | 350 | /* Non-CPU-specific NMI: NMI sources can be processed on any CPU */ |
| 350 | raw_spin_lock(&nmi_reason_lock); | 351 | raw_spin_lock(&nmi_reason_lock); |
| 351 | reason = get_nmi_reason(); | 352 | reason = x86_platform.get_nmi_reason(); |
| 352 | 353 | ||
| 353 | if (reason & NMI_REASON_MASK) { | 354 | if (reason & NMI_REASON_MASK) { |
| 354 | if (reason & NMI_REASON_SERR) | 355 | if (reason & NMI_REASON_SERR) |
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index afaf38447ef5..cf0ef986cb6d 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
| @@ -1045,6 +1045,8 @@ void __init setup_arch(char **cmdline_p) | |||
| 1045 | 1045 | ||
| 1046 | x86_init.timers.wallclock_init(); | 1046 | x86_init.timers.wallclock_init(); |
| 1047 | 1047 | ||
| 1048 | x86_platform.wallclock_init(); | ||
| 1049 | |||
| 1048 | mcheck_init(); | 1050 | mcheck_init(); |
| 1049 | 1051 | ||
| 1050 | arch_init_ideal_nops(); | 1052 | arch_init_ideal_nops(); |
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c index 6f164bd5e14d..c1d6cd549397 100644 --- a/arch/x86/kernel/x86_init.c +++ b/arch/x86/kernel/x86_init.c | |||
| @@ -21,12 +21,14 @@ | |||
| 21 | #include <asm/pat.h> | 21 | #include <asm/pat.h> |
| 22 | #include <asm/tsc.h> | 22 | #include <asm/tsc.h> |
| 23 | #include <asm/iommu.h> | 23 | #include <asm/iommu.h> |
| 24 | #include <asm/mach_traps.h> | ||
| 24 | 25 | ||
| 25 | void __cpuinit x86_init_noop(void) { } | 26 | void __cpuinit x86_init_noop(void) { } |
| 26 | void __init x86_init_uint_noop(unsigned int unused) { } | 27 | void __init x86_init_uint_noop(unsigned int unused) { } |
| 27 | void __init x86_init_pgd_noop(pgd_t *unused) { } | 28 | void __init x86_init_pgd_noop(pgd_t *unused) { } |
| 28 | int __init iommu_init_noop(void) { return 0; } | 29 | int __init iommu_init_noop(void) { return 0; } |
| 29 | void iommu_shutdown_noop(void) { } | 30 | void iommu_shutdown_noop(void) { } |
| 31 | void wallclock_init_noop(void) { } | ||
| 30 | 32 | ||
| 31 | /* | 33 | /* |
| 32 | * The platform setup functions are preset with the default functions | 34 | * The platform setup functions are preset with the default functions |
| @@ -97,11 +99,13 @@ static int default_i8042_detect(void) { return 1; }; | |||
| 97 | 99 | ||
| 98 | struct x86_platform_ops x86_platform = { | 100 | struct x86_platform_ops x86_platform = { |
| 99 | .calibrate_tsc = native_calibrate_tsc, | 101 | .calibrate_tsc = native_calibrate_tsc, |
| 102 | .wallclock_init = wallclock_init_noop, | ||
| 100 | .get_wallclock = mach_get_cmos_time, | 103 | .get_wallclock = mach_get_cmos_time, |
| 101 | .set_wallclock = mach_set_rtc_mmss, | 104 | .set_wallclock = mach_set_rtc_mmss, |
| 102 | .iommu_shutdown = iommu_shutdown_noop, | 105 | .iommu_shutdown = iommu_shutdown_noop, |
| 103 | .is_untracked_pat_range = is_ISA_range, | 106 | .is_untracked_pat_range = is_ISA_range, |
| 104 | .nmi_init = default_nmi_init, | 107 | .nmi_init = default_nmi_init, |
| 108 | .get_nmi_reason = default_get_nmi_reason, | ||
| 105 | .i8042_detect = default_i8042_detect | 109 | .i8042_detect = default_i8042_detect |
| 106 | }; | 110 | }; |
| 107 | 111 | ||
diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c index 541020df0da6..b1489a06a49d 100644 --- a/arch/x86/platform/mrst/mrst.c +++ b/arch/x86/platform/mrst/mrst.c | |||
| @@ -187,11 +187,34 @@ int __init sfi_parse_mrtc(struct sfi_table_header *table) | |||
| 187 | static unsigned long __init mrst_calibrate_tsc(void) | 187 | static unsigned long __init mrst_calibrate_tsc(void) |
| 188 | { | 188 | { |
| 189 | unsigned long flags, fast_calibrate; | 189 | unsigned long flags, fast_calibrate; |
| 190 | 190 | if (__mrst_cpu_chip == MRST_CPU_CHIP_PENWELL) { | |
| 191 | local_irq_save(flags); | 191 | u32 lo, hi, ratio, fsb; |
| 192 | fast_calibrate = apbt_quick_calibrate(); | 192 | |
| 193 | local_irq_restore(flags); | 193 | rdmsr(MSR_IA32_PERF_STATUS, lo, hi); |
| 194 | 194 | pr_debug("IA32 perf status is 0x%x, 0x%0x\n", lo, hi); | |
| 195 | ratio = (hi >> 8) & 0x1f; | ||
| 196 | pr_debug("ratio is %d\n", ratio); | ||
| 197 | if (!ratio) { | ||
| 198 | pr_err("read a zero ratio, should be incorrect!\n"); | ||
| 199 | pr_err("force tsc ratio to 16 ...\n"); | ||
| 200 | ratio = 16; | ||
| 201 | } | ||
| 202 | rdmsr(MSR_FSB_FREQ, lo, hi); | ||
| 203 | if ((lo & 0x7) == 0x7) | ||
| 204 | fsb = PENWELL_FSB_FREQ_83SKU; | ||
| 205 | else | ||
| 206 | fsb = PENWELL_FSB_FREQ_100SKU; | ||
| 207 | fast_calibrate = ratio * fsb; | ||
| 208 | pr_debug("read penwell tsc %lu khz\n", fast_calibrate); | ||
| 209 | lapic_timer_frequency = fsb * 1000 / HZ; | ||
| 210 | /* mark tsc clocksource as reliable */ | ||
| 211 | set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE); | ||
| 212 | } else { | ||
| 213 | local_irq_save(flags); | ||
| 214 | fast_calibrate = apbt_quick_calibrate(); | ||
| 215 | local_irq_restore(flags); | ||
| 216 | } | ||
| 217 | |||
| 195 | if (fast_calibrate) | 218 | if (fast_calibrate) |
| 196 | return fast_calibrate; | 219 | return fast_calibrate; |
| 197 | 220 | ||
| @@ -254,6 +277,17 @@ static void mrst_reboot(void) | |||
| 254 | } | 277 | } |
| 255 | 278 | ||
| 256 | /* | 279 | /* |
| 280 | * Moorestown does not have external NMI source nor port 0x61 to report | ||
| 281 | * NMI status. The possible NMI sources are from pmu as a result of NMI | ||
| 282 | * watchdog or lock debug. Reading io port 0x61 results in 0xff which | ||
| 283 | * misled NMI handler. | ||
| 284 | */ | ||
| 285 | static unsigned char mrst_get_nmi_reason(void) | ||
| 286 | { | ||
| 287 | return 0; | ||
| 288 | } | ||
| 289 | |||
| 290 | /* | ||
| 257 | * Moorestown specific x86_init function overrides and early setup | 291 | * Moorestown specific x86_init function overrides and early setup |
| 258 | * calls. | 292 | * calls. |
| 259 | */ | 293 | */ |
| @@ -274,6 +308,8 @@ void __init x86_mrst_early_setup(void) | |||
| 274 | x86_platform.calibrate_tsc = mrst_calibrate_tsc; | 308 | x86_platform.calibrate_tsc = mrst_calibrate_tsc; |
| 275 | x86_platform.i8042_detect = mrst_i8042_detect; | 309 | x86_platform.i8042_detect = mrst_i8042_detect; |
| 276 | x86_init.timers.wallclock_init = mrst_rtc_init; | 310 | x86_init.timers.wallclock_init = mrst_rtc_init; |
| 311 | x86_platform.get_nmi_reason = mrst_get_nmi_reason; | ||
| 312 | |||
| 277 | x86_init.pci.init = pci_mrst_init; | 313 | x86_init.pci.init = pci_mrst_init; |
| 278 | x86_init.pci.fixup_irqs = x86_init_noop; | 314 | x86_init.pci.fixup_irqs = x86_init_noop; |
| 279 | 315 | ||
