diff options
Diffstat (limited to 'arch/x86')
85 files changed, 1432 insertions, 1113 deletions
diff --git a/arch/x86/kernel/Makefile_32 b/arch/x86/kernel/Makefile_32 index c624193740fd..7ff02063b858 100644 --- a/arch/x86/kernel/Makefile_32 +++ b/arch/x86/kernel/Makefile_32 | |||
@@ -7,7 +7,7 @@ extra-y := head_32.o init_task_32.o vmlinux.lds | |||
7 | obj-y := process_32.o signal_32.o entry_32.o traps_32.o irq_32.o \ | 7 | obj-y := process_32.o signal_32.o entry_32.o traps_32.o irq_32.o \ |
8 | ptrace_32.o time_32.o ioport_32.o ldt_32.o setup_32.o i8259_32.o sys_i386_32.o \ | 8 | ptrace_32.o time_32.o ioport_32.o ldt_32.o setup_32.o i8259_32.o sys_i386_32.o \ |
9 | pci-dma_32.o i386_ksyms_32.o i387_32.o bootflag.o e820_32.o\ | 9 | pci-dma_32.o i386_ksyms_32.o i387_32.o bootflag.o e820_32.o\ |
10 | quirks.o i8237.o topology.o alternative.o i8253_32.o tsc_32.o | 10 | quirks.o i8237.o topology.o alternative.o i8253.o tsc_32.o |
11 | 11 | ||
12 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | 12 | obj-$(CONFIG_STACKTRACE) += stacktrace.o |
13 | obj-y += cpu/ | 13 | obj-y += cpu/ |
@@ -37,9 +37,9 @@ obj-$(CONFIG_EFI) += efi_32.o efi_stub_32.o | |||
37 | obj-$(CONFIG_DOUBLEFAULT) += doublefault_32.o | 37 | obj-$(CONFIG_DOUBLEFAULT) += doublefault_32.o |
38 | obj-$(CONFIG_VM86) += vm86_32.o | 38 | obj-$(CONFIG_VM86) += vm86_32.o |
39 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | 39 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o |
40 | obj-$(CONFIG_HPET_TIMER) += hpet_32.o | 40 | obj-$(CONFIG_HPET_TIMER) += hpet.o |
41 | obj-$(CONFIG_K8_NB) += k8.o | 41 | obj-$(CONFIG_K8_NB) += k8.o |
42 | obj-$(CONFIG_MGEODE_LX) += geode_32.o | 42 | obj-$(CONFIG_MGEODE_LX) += geode_32.o mfgpt_32.o |
43 | 43 | ||
44 | obj-$(CONFIG_VMI) += vmi_32.o vmiclock_32.o | 44 | obj-$(CONFIG_VMI) += vmi_32.o vmiclock_32.o |
45 | obj-$(CONFIG_PARAVIRT) += paravirt_32.o | 45 | obj-$(CONFIG_PARAVIRT) += paravirt_32.o |
diff --git a/arch/x86/kernel/Makefile_64 b/arch/x86/kernel/Makefile_64 index 3ab017a0a3b9..43da66213a47 100644 --- a/arch/x86/kernel/Makefile_64 +++ b/arch/x86/kernel/Makefile_64 | |||
@@ -8,8 +8,8 @@ obj-y := process_64.o signal_64.o entry_64.o traps_64.o irq_64.o \ | |||
8 | ptrace_64.o time_64.o ioport_64.o ldt_64.o setup_64.o i8259_64.o sys_x86_64.o \ | 8 | ptrace_64.o time_64.o ioport_64.o ldt_64.o setup_64.o i8259_64.o sys_x86_64.o \ |
9 | x8664_ksyms_64.o i387_64.o syscall_64.o vsyscall_64.o \ | 9 | x8664_ksyms_64.o i387_64.o syscall_64.o vsyscall_64.o \ |
10 | setup64.o bootflag.o e820_64.o reboot_64.o quirks.o i8237.o \ | 10 | setup64.o bootflag.o e820_64.o reboot_64.o quirks.o i8237.o \ |
11 | pci-dma_64.o pci-nommu_64.o alternative.o hpet_64.o tsc_64.o bugs_64.o \ | 11 | pci-dma_64.o pci-nommu_64.o alternative.o hpet.o tsc_64.o bugs_64.o \ |
12 | perfctr-watchdog.o | 12 | perfctr-watchdog.o i8253.o |
13 | 13 | ||
14 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | 14 | obj-$(CONFIG_STACKTRACE) += stacktrace.o |
15 | obj-$(CONFIG_X86_MCE) += mce_64.o therm_throt.o | 15 | obj-$(CONFIG_X86_MCE) += mce_64.o therm_throt.o |
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index bd72d94e713e..11b03d3c6fda 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <asm/pgtable.h> | 10 | #include <asm/pgtable.h> |
11 | #include <asm/mce.h> | 11 | #include <asm/mce.h> |
12 | #include <asm/nmi.h> | 12 | #include <asm/nmi.h> |
13 | #include <asm/vsyscall.h> | ||
13 | 14 | ||
14 | #define MAX_PATCH_LEN (255-1) | 15 | #define MAX_PATCH_LEN (255-1) |
15 | 16 | ||
diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 925758dbca0c..09b82093bc75 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/sysdev.h> | 25 | #include <linux/sysdev.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/ioport.h> | 27 | #include <linux/ioport.h> |
28 | #include <linux/clockchips.h> | ||
28 | 29 | ||
29 | #include <asm/atomic.h> | 30 | #include <asm/atomic.h> |
30 | #include <asm/smp.h> | 31 | #include <asm/smp.h> |
@@ -39,12 +40,9 @@ | |||
39 | #include <asm/hpet.h> | 40 | #include <asm/hpet.h> |
40 | #include <asm/apic.h> | 41 | #include <asm/apic.h> |
41 | 42 | ||
42 | int apic_mapped; | ||
43 | int apic_verbosity; | 43 | int apic_verbosity; |
44 | int apic_runs_main_timer; | 44 | int disable_apic_timer __cpuinitdata; |
45 | int apic_calibrate_pmtmr __initdata; | 45 | static int apic_calibrate_pmtmr __initdata; |
46 | |||
47 | int disable_apic_timer __initdata; | ||
48 | 46 | ||
49 | /* Local APIC timer works in C2? */ | 47 | /* Local APIC timer works in C2? */ |
50 | int local_apic_timer_c2_ok; | 48 | int local_apic_timer_c2_ok; |
@@ -56,14 +54,78 @@ static struct resource lapic_resource = { | |||
56 | .flags = IORESOURCE_MEM | IORESOURCE_BUSY, | 54 | .flags = IORESOURCE_MEM | IORESOURCE_BUSY, |
57 | }; | 55 | }; |
58 | 56 | ||
57 | static unsigned int calibration_result; | ||
58 | |||
59 | static int lapic_next_event(unsigned long delta, | ||
60 | struct clock_event_device *evt); | ||
61 | static void lapic_timer_setup(enum clock_event_mode mode, | ||
62 | struct clock_event_device *evt); | ||
63 | |||
64 | static void lapic_timer_broadcast(cpumask_t mask); | ||
65 | |||
66 | static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen); | ||
67 | |||
68 | static struct clock_event_device lapic_clockevent = { | ||
69 | .name = "lapic", | ||
70 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | ||
71 | | CLOCK_EVT_FEAT_C3STOP | CLOCK_EVT_FEAT_DUMMY, | ||
72 | .shift = 32, | ||
73 | .set_mode = lapic_timer_setup, | ||
74 | .set_next_event = lapic_next_event, | ||
75 | .broadcast = lapic_timer_broadcast, | ||
76 | .rating = 100, | ||
77 | .irq = -1, | ||
78 | }; | ||
79 | static DEFINE_PER_CPU(struct clock_event_device, lapic_events); | ||
80 | |||
81 | static int lapic_next_event(unsigned long delta, | ||
82 | struct clock_event_device *evt) | ||
83 | { | ||
84 | apic_write(APIC_TMICT, delta); | ||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | static void lapic_timer_setup(enum clock_event_mode mode, | ||
89 | struct clock_event_device *evt) | ||
90 | { | ||
91 | unsigned long flags; | ||
92 | unsigned int v; | ||
93 | |||
94 | /* Lapic used as dummy for broadcast ? */ | ||
95 | if (evt->features & CLOCK_EVT_FEAT_DUMMY) | ||
96 | return; | ||
97 | |||
98 | local_irq_save(flags); | ||
99 | |||
100 | switch (mode) { | ||
101 | case CLOCK_EVT_MODE_PERIODIC: | ||
102 | case CLOCK_EVT_MODE_ONESHOT: | ||
103 | __setup_APIC_LVTT(calibration_result, | ||
104 | mode != CLOCK_EVT_MODE_PERIODIC, 1); | ||
105 | break; | ||
106 | case CLOCK_EVT_MODE_UNUSED: | ||
107 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
108 | v = apic_read(APIC_LVTT); | ||
109 | v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); | ||
110 | apic_write(APIC_LVTT, v); | ||
111 | break; | ||
112 | case CLOCK_EVT_MODE_RESUME: | ||
113 | /* Nothing to do here */ | ||
114 | break; | ||
115 | } | ||
116 | |||
117 | local_irq_restore(flags); | ||
118 | } | ||
119 | |||
59 | /* | 120 | /* |
60 | * cpu_mask that denotes the CPUs that needs timer interrupt coming in as | 121 | * Local APIC timer broadcast function |
61 | * IPIs in place of local APIC timers | ||
62 | */ | 122 | */ |
63 | static cpumask_t timer_interrupt_broadcast_ipi_mask; | 123 | static void lapic_timer_broadcast(cpumask_t mask) |
64 | 124 | { | |
65 | /* Using APIC to generate smp_local_timer_interrupt? */ | 125 | #ifdef CONFIG_SMP |
66 | int using_apic_timer __read_mostly = 0; | 126 | send_IPI_mask(mask, LOCAL_TIMER_VECTOR); |
127 | #endif | ||
128 | } | ||
67 | 129 | ||
68 | static void apic_pm_activate(void); | 130 | static void apic_pm_activate(void); |
69 | 131 | ||
@@ -184,7 +246,10 @@ void disconnect_bsp_APIC(int virt_wire_setup) | |||
184 | apic_write(APIC_SPIV, value); | 246 | apic_write(APIC_SPIV, value); |
185 | 247 | ||
186 | if (!virt_wire_setup) { | 248 | if (!virt_wire_setup) { |
187 | /* For LVT0 make it edge triggered, active high, external and enabled */ | 249 | /* |
250 | * For LVT0 make it edge triggered, active high, | ||
251 | * external and enabled | ||
252 | */ | ||
188 | value = apic_read(APIC_LVT0); | 253 | value = apic_read(APIC_LVT0); |
189 | value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING | | 254 | value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING | |
190 | APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | | 255 | APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | |
@@ -420,10 +485,12 @@ void __cpuinit setup_local_APIC (void) | |||
420 | value = apic_read(APIC_LVT0) & APIC_LVT_MASKED; | 485 | value = apic_read(APIC_LVT0) & APIC_LVT_MASKED; |
421 | if (!smp_processor_id() && !value) { | 486 | if (!smp_processor_id() && !value) { |
422 | value = APIC_DM_EXTINT; | 487 | value = APIC_DM_EXTINT; |
423 | apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", smp_processor_id()); | 488 | apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", |
489 | smp_processor_id()); | ||
424 | } else { | 490 | } else { |
425 | value = APIC_DM_EXTINT | APIC_LVT_MASKED; | 491 | value = APIC_DM_EXTINT | APIC_LVT_MASKED; |
426 | apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", smp_processor_id()); | 492 | apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", |
493 | smp_processor_id()); | ||
427 | } | 494 | } |
428 | apic_write(APIC_LVT0, value); | 495 | apic_write(APIC_LVT0, value); |
429 | 496 | ||
@@ -706,8 +773,8 @@ void __init init_apic_mappings(void) | |||
706 | apic_phys = mp_lapic_addr; | 773 | apic_phys = mp_lapic_addr; |
707 | 774 | ||
708 | set_fixmap_nocache(FIX_APIC_BASE, apic_phys); | 775 | set_fixmap_nocache(FIX_APIC_BASE, apic_phys); |
709 | apic_mapped = 1; | 776 | apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n", |
710 | apic_printk(APIC_VERBOSE,"mapped APIC to %16lx (%16lx)\n", APIC_BASE, apic_phys); | 777 | APIC_BASE, apic_phys); |
711 | 778 | ||
712 | /* Put local APIC into the resource map. */ | 779 | /* Put local APIC into the resource map. */ |
713 | lapic_resource.start = apic_phys; | 780 | lapic_resource.start = apic_phys; |
@@ -730,12 +797,14 @@ void __init init_apic_mappings(void) | |||
730 | if (smp_found_config) { | 797 | if (smp_found_config) { |
731 | ioapic_phys = mp_ioapics[i].mpc_apicaddr; | 798 | ioapic_phys = mp_ioapics[i].mpc_apicaddr; |
732 | } else { | 799 | } else { |
733 | ioapic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE); | 800 | ioapic_phys = (unsigned long) |
801 | alloc_bootmem_pages(PAGE_SIZE); | ||
734 | ioapic_phys = __pa(ioapic_phys); | 802 | ioapic_phys = __pa(ioapic_phys); |
735 | } | 803 | } |
736 | set_fixmap_nocache(idx, ioapic_phys); | 804 | set_fixmap_nocache(idx, ioapic_phys); |
737 | apic_printk(APIC_VERBOSE,"mapped IOAPIC to %016lx (%016lx)\n", | 805 | apic_printk(APIC_VERBOSE, |
738 | __fix_to_virt(idx), ioapic_phys); | 806 | "mapped IOAPIC to %016lx (%016lx)\n", |
807 | __fix_to_virt(idx), ioapic_phys); | ||
739 | idx++; | 808 | idx++; |
740 | 809 | ||
741 | if (ioapic_res != NULL) { | 810 | if (ioapic_res != NULL) { |
@@ -758,16 +827,14 @@ void __init init_apic_mappings(void) | |||
758 | * P5 APIC double write bug. | 827 | * P5 APIC double write bug. |
759 | */ | 828 | */ |
760 | 829 | ||
761 | #define APIC_DIVISOR 16 | 830 | static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) |
762 | |||
763 | static void __setup_APIC_LVTT(unsigned int clocks) | ||
764 | { | 831 | { |
765 | unsigned int lvtt_value, tmp_value; | 832 | unsigned int lvtt_value, tmp_value; |
766 | int cpu = smp_processor_id(); | ||
767 | 833 | ||
768 | lvtt_value = APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR; | 834 | lvtt_value = LOCAL_TIMER_VECTOR; |
769 | 835 | if (!oneshot) | |
770 | if (cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask)) | 836 | lvtt_value |= APIC_LVT_TIMER_PERIODIC; |
837 | if (!irqen) | ||
771 | lvtt_value |= APIC_LVT_MASKED; | 838 | lvtt_value |= APIC_LVT_MASKED; |
772 | 839 | ||
773 | apic_write(APIC_LVTT, lvtt_value); | 840 | apic_write(APIC_LVTT, lvtt_value); |
@@ -780,44 +847,18 @@ static void __setup_APIC_LVTT(unsigned int clocks) | |||
780 | & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) | 847 | & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) |
781 | | APIC_TDR_DIV_16); | 848 | | APIC_TDR_DIV_16); |
782 | 849 | ||
783 | apic_write(APIC_TMICT, clocks/APIC_DIVISOR); | 850 | if (!oneshot) |
851 | apic_write(APIC_TMICT, clocks); | ||
784 | } | 852 | } |
785 | 853 | ||
786 | static void setup_APIC_timer(unsigned int clocks) | 854 | static void setup_APIC_timer(void) |
787 | { | 855 | { |
788 | unsigned long flags; | 856 | struct clock_event_device *levt = &__get_cpu_var(lapic_events); |
789 | 857 | ||
790 | local_irq_save(flags); | 858 | memcpy(levt, &lapic_clockevent, sizeof(*levt)); |
859 | levt->cpumask = cpumask_of_cpu(smp_processor_id()); | ||
791 | 860 | ||
792 | /* wait for irq slice */ | 861 | clockevents_register_device(levt); |
793 | if (hpet_address && hpet_use_timer) { | ||
794 | u32 trigger = hpet_readl(HPET_T0_CMP); | ||
795 | while (hpet_readl(HPET_T0_CMP) == trigger) | ||
796 | /* do nothing */ ; | ||
797 | } else { | ||
798 | int c1, c2; | ||
799 | outb_p(0x00, 0x43); | ||
800 | c2 = inb_p(0x40); | ||
801 | c2 |= inb_p(0x40) << 8; | ||
802 | do { | ||
803 | c1 = c2; | ||
804 | outb_p(0x00, 0x43); | ||
805 | c2 = inb_p(0x40); | ||
806 | c2 |= inb_p(0x40) << 8; | ||
807 | } while (c2 - c1 < 300); | ||
808 | } | ||
809 | __setup_APIC_LVTT(clocks); | ||
810 | /* Turn off PIT interrupt if we use APIC timer as main timer. | ||
811 | Only works with the PM timer right now | ||
812 | TBD fix it for HPET too. */ | ||
813 | if ((pmtmr_ioport != 0) && | ||
814 | smp_processor_id() == boot_cpu_id && | ||
815 | apic_runs_main_timer == 1 && | ||
816 | !cpu_isset(boot_cpu_id, timer_interrupt_broadcast_ipi_mask)) { | ||
817 | stop_timer_interrupt(); | ||
818 | apic_runs_main_timer++; | ||
819 | } | ||
820 | local_irq_restore(flags); | ||
821 | } | 862 | } |
822 | 863 | ||
823 | /* | 864 | /* |
@@ -835,17 +876,22 @@ static void setup_APIC_timer(unsigned int clocks) | |||
835 | 876 | ||
836 | #define TICK_COUNT 100000000 | 877 | #define TICK_COUNT 100000000 |
837 | 878 | ||
838 | static int __init calibrate_APIC_clock(void) | 879 | static void __init calibrate_APIC_clock(void) |
839 | { | 880 | { |
840 | unsigned apic, apic_start; | 881 | unsigned apic, apic_start; |
841 | unsigned long tsc, tsc_start; | 882 | unsigned long tsc, tsc_start; |
842 | int result; | 883 | int result; |
884 | |||
885 | local_irq_disable(); | ||
886 | |||
843 | /* | 887 | /* |
844 | * Put whatever arbitrary (but long enough) timeout | 888 | * Put whatever arbitrary (but long enough) timeout |
845 | * value into the APIC clock, we just want to get the | 889 | * value into the APIC clock, we just want to get the |
846 | * counter running for calibration. | 890 | * counter running for calibration. |
891 | * | ||
892 | * No interrupt enable ! | ||
847 | */ | 893 | */ |
848 | __setup_APIC_LVTT(4000000000); | 894 | __setup_APIC_LVTT(250000000, 0, 0); |
849 | 895 | ||
850 | apic_start = apic_read(APIC_TMCCT); | 896 | apic_start = apic_read(APIC_TMCCT); |
851 | #ifdef CONFIG_X86_PM_TIMER | 897 | #ifdef CONFIG_X86_PM_TIMER |
@@ -867,123 +913,88 @@ static int __init calibrate_APIC_clock(void) | |||
867 | result = (apic_start - apic) * 1000L * tsc_khz / | 913 | result = (apic_start - apic) * 1000L * tsc_khz / |
868 | (tsc - tsc_start); | 914 | (tsc - tsc_start); |
869 | } | 915 | } |
870 | printk("result %d\n", result); | ||
871 | 916 | ||
917 | local_irq_enable(); | ||
918 | |||
919 | printk(KERN_DEBUG "APIC timer calibration result %d\n", result); | ||
872 | 920 | ||
873 | printk(KERN_INFO "Detected %d.%03d MHz APIC timer.\n", | 921 | printk(KERN_INFO "Detected %d.%03d MHz APIC timer.\n", |
874 | result / 1000 / 1000, result / 1000 % 1000); | 922 | result / 1000 / 1000, result / 1000 % 1000); |
875 | 923 | ||
876 | return result * APIC_DIVISOR / HZ; | 924 | /* Calculate the scaled math multiplication factor */ |
877 | } | 925 | lapic_clockevent.mult = div_sc(result, NSEC_PER_SEC, 32); |
926 | lapic_clockevent.max_delta_ns = | ||
927 | clockevent_delta2ns(0x7FFFFF, &lapic_clockevent); | ||
928 | lapic_clockevent.min_delta_ns = | ||
929 | clockevent_delta2ns(0xF, &lapic_clockevent); | ||
878 | 930 | ||
879 | static unsigned int calibration_result; | 931 | calibration_result = result / HZ; |
932 | } | ||
880 | 933 | ||
881 | void __init setup_boot_APIC_clock (void) | 934 | void __init setup_boot_APIC_clock (void) |
882 | { | 935 | { |
936 | /* | ||
937 | * The local apic timer can be disabled via the kernel commandline. | ||
938 | * Register the lapic timer as a dummy clock event source on SMP | ||
939 | * systems, so the broadcast mechanism is used. On UP systems simply | ||
940 | * ignore it. | ||
941 | */ | ||
883 | if (disable_apic_timer) { | 942 | if (disable_apic_timer) { |
884 | printk(KERN_INFO "Disabling APIC timer\n"); | 943 | printk(KERN_INFO "Disabling APIC timer\n"); |
944 | /* No broadcast on UP ! */ | ||
945 | if (num_possible_cpus() > 1) | ||
946 | setup_APIC_timer(); | ||
885 | return; | 947 | return; |
886 | } | 948 | } |
887 | 949 | ||
888 | printk(KERN_INFO "Using local APIC timer interrupts.\n"); | 950 | printk(KERN_INFO "Using local APIC timer interrupts.\n"); |
889 | using_apic_timer = 1; | 951 | calibrate_APIC_clock(); |
890 | |||
891 | local_irq_disable(); | ||
892 | 952 | ||
893 | calibration_result = calibrate_APIC_clock(); | ||
894 | /* | 953 | /* |
895 | * Now set up the timer for real. | 954 | * If nmi_watchdog is set to IO_APIC, we need the |
955 | * PIT/HPET going. Otherwise register lapic as a dummy | ||
956 | * device. | ||
896 | */ | 957 | */ |
897 | setup_APIC_timer(calibration_result); | 958 | if (nmi_watchdog != NMI_IO_APIC) |
898 | 959 | lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY; | |
899 | local_irq_enable(); | 960 | else |
900 | } | 961 | printk(KERN_WARNING "APIC timer registered as dummy," |
901 | 962 | " due to nmi_watchdog=1!\n"); | |
902 | void __cpuinit setup_secondary_APIC_clock(void) | ||
903 | { | ||
904 | local_irq_disable(); /* FIXME: Do we need this? --RR */ | ||
905 | setup_APIC_timer(calibration_result); | ||
906 | local_irq_enable(); | ||
907 | } | ||
908 | |||
909 | void disable_APIC_timer(void) | ||
910 | { | ||
911 | if (using_apic_timer) { | ||
912 | unsigned long v; | ||
913 | 963 | ||
914 | v = apic_read(APIC_LVTT); | 964 | setup_APIC_timer(); |
915 | /* | ||
916 | * When an illegal vector value (0-15) is written to an LVT | ||
917 | * entry and delivery mode is Fixed, the APIC may signal an | ||
918 | * illegal vector error, with out regard to whether the mask | ||
919 | * bit is set or whether an interrupt is actually seen on input. | ||
920 | * | ||
921 | * Boot sequence might call this function when the LVTT has | ||
922 | * '0' vector value. So make sure vector field is set to | ||
923 | * valid value. | ||
924 | */ | ||
925 | v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); | ||
926 | apic_write(APIC_LVTT, v); | ||
927 | } | ||
928 | } | 965 | } |
929 | 966 | ||
930 | void enable_APIC_timer(void) | 967 | /* |
968 | * AMD C1E enabled CPUs have a real nasty problem: Some BIOSes set the | ||
969 | * C1E flag only in the secondary CPU, so when we detect the wreckage | ||
970 | * we already have enabled the boot CPU local apic timer. Check, if | ||
971 | * disable_apic_timer is set and the DUMMY flag is cleared. If yes, | ||
972 | * set the DUMMY flag again and force the broadcast mode in the | ||
973 | * clockevents layer. | ||
974 | */ | ||
975 | void __cpuinit check_boot_apic_timer_broadcast(void) | ||
931 | { | 976 | { |
932 | int cpu = smp_processor_id(); | 977 | struct clock_event_device *levt = &per_cpu(lapic_events, boot_cpu_id); |
933 | 978 | ||
934 | if (using_apic_timer && | 979 | if (!disable_apic_timer || |
935 | !cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask)) { | 980 | (lapic_clockevent.features & CLOCK_EVT_FEAT_DUMMY)) |
936 | unsigned long v; | 981 | return; |
937 | 982 | ||
938 | v = apic_read(APIC_LVTT); | 983 | printk(KERN_INFO "AMD C1E detected late. Force timer broadcast.\n"); |
939 | apic_write(APIC_LVTT, v & ~APIC_LVT_MASKED); | 984 | lapic_clockevent.features |= CLOCK_EVT_FEAT_DUMMY; |
940 | } | 985 | levt->features |= CLOCK_EVT_FEAT_DUMMY; |
941 | } | ||
942 | 986 | ||
943 | void switch_APIC_timer_to_ipi(void *cpumask) | 987 | local_irq_enable(); |
944 | { | 988 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_FORCE, &boot_cpu_id); |
945 | cpumask_t mask = *(cpumask_t *)cpumask; | 989 | local_irq_disable(); |
946 | int cpu = smp_processor_id(); | ||
947 | |||
948 | if (cpu_isset(cpu, mask) && | ||
949 | !cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask)) { | ||
950 | disable_APIC_timer(); | ||
951 | cpu_set(cpu, timer_interrupt_broadcast_ipi_mask); | ||
952 | } | ||
953 | } | 990 | } |
954 | EXPORT_SYMBOL(switch_APIC_timer_to_ipi); | ||
955 | 991 | ||
956 | void smp_send_timer_broadcast_ipi(void) | 992 | void __cpuinit setup_secondary_APIC_clock(void) |
957 | { | 993 | { |
958 | int cpu = smp_processor_id(); | 994 | check_boot_apic_timer_broadcast(); |
959 | cpumask_t mask; | 995 | setup_APIC_timer(); |
960 | |||
961 | cpus_and(mask, cpu_online_map, timer_interrupt_broadcast_ipi_mask); | ||
962 | |||
963 | if (cpu_isset(cpu, mask)) { | ||
964 | cpu_clear(cpu, mask); | ||
965 | add_pda(apic_timer_irqs, 1); | ||
966 | smp_local_timer_interrupt(); | ||
967 | } | ||
968 | |||
969 | if (!cpus_empty(mask)) { | ||
970 | send_IPI_mask(mask, LOCAL_TIMER_VECTOR); | ||
971 | } | ||
972 | } | 996 | } |
973 | 997 | ||
974 | void switch_ipi_to_APIC_timer(void *cpumask) | ||
975 | { | ||
976 | cpumask_t mask = *(cpumask_t *)cpumask; | ||
977 | int cpu = smp_processor_id(); | ||
978 | |||
979 | if (cpu_isset(cpu, mask) && | ||
980 | cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask)) { | ||
981 | cpu_clear(cpu, timer_interrupt_broadcast_ipi_mask); | ||
982 | enable_APIC_timer(); | ||
983 | } | ||
984 | } | ||
985 | EXPORT_SYMBOL(switch_ipi_to_APIC_timer); | ||
986 | |||
987 | int setup_profiling_timer(unsigned int multiplier) | 998 | int setup_profiling_timer(unsigned int multiplier) |
988 | { | 999 | { |
989 | return -EINVAL; | 1000 | return -EINVAL; |
@@ -997,8 +1008,6 @@ void setup_APIC_extended_lvt(unsigned char lvt_off, unsigned char vector, | |||
997 | apic_write(reg, v); | 1008 | apic_write(reg, v); |
998 | } | 1009 | } |
999 | 1010 | ||
1000 | #undef APIC_DIVISOR | ||
1001 | |||
1002 | /* | 1011 | /* |
1003 | * Local timer interrupt handler. It does both profiling and | 1012 | * Local timer interrupt handler. It does both profiling and |
1004 | * process statistics/rescheduling. | 1013 | * process statistics/rescheduling. |
@@ -1011,22 +1020,34 @@ void setup_APIC_extended_lvt(unsigned char lvt_off, unsigned char vector, | |||
1011 | 1020 | ||
1012 | void smp_local_timer_interrupt(void) | 1021 | void smp_local_timer_interrupt(void) |
1013 | { | 1022 | { |
1014 | profile_tick(CPU_PROFILING); | 1023 | int cpu = smp_processor_id(); |
1015 | #ifdef CONFIG_SMP | 1024 | struct clock_event_device *evt = &per_cpu(lapic_events, cpu); |
1016 | update_process_times(user_mode(get_irq_regs())); | 1025 | |
1017 | #endif | ||
1018 | if (apic_runs_main_timer > 1 && smp_processor_id() == boot_cpu_id) | ||
1019 | main_timer_handler(); | ||
1020 | /* | 1026 | /* |
1021 | * We take the 'long' return path, and there every subsystem | 1027 | * Normally we should not be here till LAPIC has been initialized but |
1022 | * grabs the appropriate locks (kernel lock/ irq lock). | 1028 | * in some cases like kdump, its possible that there is a pending LAPIC |
1029 | * timer interrupt from previous kernel's context and is delivered in | ||
1030 | * new kernel the moment interrupts are enabled. | ||
1023 | * | 1031 | * |
1024 | * We might want to decouple profiling from the 'long path', | 1032 | * Interrupts are enabled early and LAPIC is setup much later, hence |
1025 | * and do the profiling totally in assembly. | 1033 | * its possible that when we get here evt->event_handler is NULL. |
1026 | * | 1034 | * Check for event_handler being NULL and discard the interrupt as |
1027 | * Currently this isn't too much of an issue (performance wise), | 1035 | * spurious. |
1028 | * we can take more than 100K local irqs per second on a 100 MHz P5. | 1036 | */ |
1037 | if (!evt->event_handler) { | ||
1038 | printk(KERN_WARNING | ||
1039 | "Spurious LAPIC timer interrupt on cpu %d\n", cpu); | ||
1040 | /* Switch it off */ | ||
1041 | lapic_timer_setup(CLOCK_EVT_MODE_SHUTDOWN, evt); | ||
1042 | return; | ||
1043 | } | ||
1044 | |||
1045 | /* | ||
1046 | * the NMI deadlock-detector uses this. | ||
1029 | */ | 1047 | */ |
1048 | add_pda(apic_timer_irqs, 1); | ||
1049 | |||
1050 | evt->event_handler(evt); | ||
1030 | } | 1051 | } |
1031 | 1052 | ||
1032 | /* | 1053 | /* |
@@ -1042,11 +1063,6 @@ void smp_apic_timer_interrupt(struct pt_regs *regs) | |||
1042 | struct pt_regs *old_regs = set_irq_regs(regs); | 1063 | struct pt_regs *old_regs = set_irq_regs(regs); |
1043 | 1064 | ||
1044 | /* | 1065 | /* |
1045 | * the NMI deadlock-detector uses this. | ||
1046 | */ | ||
1047 | add_pda(apic_timer_irqs, 1); | ||
1048 | |||
1049 | /* | ||
1050 | * NOTE! We'd better ACK the irq immediately, | 1066 | * NOTE! We'd better ACK the irq immediately, |
1051 | * because timer handling can be slow. | 1067 | * because timer handling can be slow. |
1052 | */ | 1068 | */ |
@@ -1225,29 +1241,13 @@ static __init int setup_noapictimer(char *str) | |||
1225 | disable_apic_timer = 1; | 1241 | disable_apic_timer = 1; |
1226 | return 1; | 1242 | return 1; |
1227 | } | 1243 | } |
1228 | 1244 | __setup("noapictimer", setup_noapictimer); | |
1229 | static __init int setup_apicmaintimer(char *str) | ||
1230 | { | ||
1231 | apic_runs_main_timer = 1; | ||
1232 | nohpet = 1; | ||
1233 | return 1; | ||
1234 | } | ||
1235 | __setup("apicmaintimer", setup_apicmaintimer); | ||
1236 | |||
1237 | static __init int setup_noapicmaintimer(char *str) | ||
1238 | { | ||
1239 | apic_runs_main_timer = -1; | ||
1240 | return 1; | ||
1241 | } | ||
1242 | __setup("noapicmaintimer", setup_noapicmaintimer); | ||
1243 | 1245 | ||
1244 | static __init int setup_apicpmtimer(char *s) | 1246 | static __init int setup_apicpmtimer(char *s) |
1245 | { | 1247 | { |
1246 | apic_calibrate_pmtmr = 1; | 1248 | apic_calibrate_pmtmr = 1; |
1247 | notsc_setup(NULL); | 1249 | notsc_setup(NULL); |
1248 | return setup_apicmaintimer(NULL); | 1250 | return 0; |
1249 | } | 1251 | } |
1250 | __setup("apicpmtimer", setup_apicpmtimer); | 1252 | __setup("apicpmtimer", setup_apicpmtimer); |
1251 | 1253 | ||
1252 | __setup("noapictimer", setup_noapictimer); | ||
1253 | |||
diff --git a/arch/x86/kernel/bugs_64.c b/arch/x86/kernel/bugs_64.c index 4e5e9d364d63..9a189cef6404 100644 --- a/arch/x86/kernel/bugs_64.c +++ b/arch/x86/kernel/bugs_64.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/x86_64/kernel/bugs.c | ||
3 | * | ||
4 | * Copyright (C) 1994 Linus Torvalds | 2 | * Copyright (C) 1994 Linus Torvalds |
5 | * Copyright (C) 2000 SuSE | 3 | * Copyright (C) 2000 SuSE |
6 | */ | 4 | */ |
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 59266f03d1cd..205fd5ba57f7 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/i386/cpu/bugs.c | ||
3 | * | ||
4 | * Copyright (C) 1994 Linus Torvalds | 2 | * Copyright (C) 1994 Linus Torvalds |
5 | * | 3 | * |
6 | * Cyrix stuff, June 1998 by: | 4 | * Cyrix stuff, June 1998 by: |
diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index b6434a7ef8b2..ffd01e5dcb52 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | |||
@@ -646,7 +646,6 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
646 | policy->cpuinfo.transition_latency = | 646 | policy->cpuinfo.transition_latency = |
647 | perf->states[i].transition_latency * 1000; | 647 | perf->states[i].transition_latency * 1000; |
648 | } | 648 | } |
649 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
650 | 649 | ||
651 | data->max_freq = perf->states[0].core_frequency * 1000; | 650 | data->max_freq = perf->states[0].core_frequency * 1000; |
652 | /* table init */ | 651 | /* table init */ |
diff --git a/arch/x86/kernel/cpu/cpufreq/cpufreq-nforce2.c b/arch/x86/kernel/cpu/cpufreq/cpufreq-nforce2.c index 66acd5039918..32f0bda3fc95 100644 --- a/arch/x86/kernel/cpu/cpufreq/cpufreq-nforce2.c +++ b/arch/x86/kernel/cpu/cpufreq/cpufreq-nforce2.c | |||
@@ -363,7 +363,6 @@ static int nforce2_cpu_init(struct cpufreq_policy *policy) | |||
363 | policy->cur = nforce2_get(policy->cpu); | 363 | policy->cur = nforce2_get(policy->cpu); |
364 | policy->min = policy->cpuinfo.min_freq; | 364 | policy->min = policy->cpuinfo.min_freq; |
365 | policy->max = policy->cpuinfo.max_freq; | 365 | policy->max = policy->cpuinfo.max_freq; |
366 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
367 | 366 | ||
368 | return 0; | 367 | return 0; |
369 | } | 368 | } |
diff --git a/arch/x86/kernel/cpu/cpufreq/e_powersaver.c b/arch/x86/kernel/cpu/cpufreq/e_powersaver.c index f43d98e11cc7..c11baaf9f2b4 100644 --- a/arch/x86/kernel/cpu/cpufreq/e_powersaver.c +++ b/arch/x86/kernel/cpu/cpufreq/e_powersaver.c | |||
@@ -253,7 +253,6 @@ static int eps_cpu_init(struct cpufreq_policy *policy) | |||
253 | f_table[k].frequency = CPUFREQ_TABLE_END; | 253 | f_table[k].frequency = CPUFREQ_TABLE_END; |
254 | } | 254 | } |
255 | 255 | ||
256 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
257 | policy->cpuinfo.transition_latency = 140000; /* 844mV -> 700mV in ns */ | 256 | policy->cpuinfo.transition_latency = 140000; /* 844mV -> 700mV in ns */ |
258 | policy->cur = fsb * current_multiplier; | 257 | policy->cur = fsb * current_multiplier; |
259 | 258 | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/elanfreq.c b/arch/x86/kernel/cpu/cpufreq/elanfreq.c index f317276afa7a..1e7ae7dafcf6 100644 --- a/arch/x86/kernel/cpu/cpufreq/elanfreq.c +++ b/arch/x86/kernel/cpu/cpufreq/elanfreq.c | |||
@@ -219,7 +219,6 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy) | |||
219 | } | 219 | } |
220 | 220 | ||
221 | /* cpuinfo and default policy values */ | 221 | /* cpuinfo and default policy values */ |
222 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
223 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; | 222 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; |
224 | policy->cur = elanfreq_get_cpu_frequency(0); | 223 | policy->cur = elanfreq_get_cpu_frequency(0); |
225 | 224 | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c b/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c index 461dabc4e495..ed2bda127c44 100644 --- a/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c +++ b/arch/x86/kernel/cpu/cpufreq/gx-suspmod.c | |||
@@ -420,7 +420,6 @@ static int cpufreq_gx_cpu_init(struct cpufreq_policy *policy) | |||
420 | policy->min = maxfreq / POLICY_MIN_DIV; | 420 | policy->min = maxfreq / POLICY_MIN_DIV; |
421 | policy->max = maxfreq; | 421 | policy->max = maxfreq; |
422 | policy->cur = curfreq; | 422 | policy->cur = curfreq; |
423 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
424 | policy->cpuinfo.min_freq = maxfreq / max_duration; | 423 | policy->cpuinfo.min_freq = maxfreq / max_duration; |
425 | policy->cpuinfo.max_freq = maxfreq; | 424 | policy->cpuinfo.max_freq = maxfreq; |
426 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; | 425 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; |
diff --git a/arch/x86/kernel/cpu/cpufreq/longhaul.c b/arch/x86/kernel/cpu/cpufreq/longhaul.c index f0cce3c2dc3a..5045f5d583c8 100644 --- a/arch/x86/kernel/cpu/cpufreq/longhaul.c +++ b/arch/x86/kernel/cpu/cpufreq/longhaul.c | |||
@@ -710,6 +710,10 @@ static int enable_arbiter_disable(void) | |||
710 | reg = 0x78; | 710 | reg = 0x78; |
711 | dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0, | 711 | dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0, |
712 | NULL); | 712 | NULL); |
713 | /* Find PM133/VT8605 host bridge */ | ||
714 | if (dev == NULL) | ||
715 | dev = pci_get_device(PCI_VENDOR_ID_VIA, | ||
716 | PCI_DEVICE_ID_VIA_8605_0, NULL); | ||
713 | /* Find CLE266 host bridge */ | 717 | /* Find CLE266 host bridge */ |
714 | if (dev == NULL) { | 718 | if (dev == NULL) { |
715 | reg = 0x76; | 719 | reg = 0x76; |
@@ -918,7 +922,6 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy) | |||
918 | if ((longhaul_version != TYPE_LONGHAUL_V1) && (scale_voltage != 0)) | 922 | if ((longhaul_version != TYPE_LONGHAUL_V1) && (scale_voltage != 0)) |
919 | longhaul_setup_voltagescaling(); | 923 | longhaul_setup_voltagescaling(); |
920 | 924 | ||
921 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
922 | policy->cpuinfo.transition_latency = 200000; /* nsec */ | 925 | policy->cpuinfo.transition_latency = 200000; /* nsec */ |
923 | policy->cur = calc_speed(longhaul_get_cpu_mult()); | 926 | policy->cur = calc_speed(longhaul_get_cpu_mult()); |
924 | 927 | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c index 4c76b511e194..8eb414b906d2 100644 --- a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c +++ b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c | |||
@@ -229,7 +229,6 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) | |||
229 | cpufreq_frequency_table_get_attr(p4clockmod_table, policy->cpu); | 229 | cpufreq_frequency_table_get_attr(p4clockmod_table, policy->cpu); |
230 | 230 | ||
231 | /* cpuinfo and default policy values */ | 231 | /* cpuinfo and default policy values */ |
232 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
233 | policy->cpuinfo.transition_latency = 1000000; /* assumed */ | 232 | policy->cpuinfo.transition_latency = 1000000; /* assumed */ |
234 | policy->cur = stock_freq; | 233 | policy->cur = stock_freq; |
235 | 234 | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k6.c b/arch/x86/kernel/cpu/cpufreq/powernow-k6.c index f89524051e4a..6d0285339317 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k6.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k6.c | |||
@@ -160,7 +160,6 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy) | |||
160 | } | 160 | } |
161 | 161 | ||
162 | /* cpuinfo and default policy values */ | 162 | /* cpuinfo and default policy values */ |
163 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
164 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; | 163 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; |
165 | policy->cur = busfreq * max_multiplier; | 164 | policy->cur = busfreq * max_multiplier; |
166 | 165 | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k7.c b/arch/x86/kernel/cpu/cpufreq/powernow-k7.c index ca3e1d341889..7decd6a50ffa 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k7.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k7.c | |||
@@ -637,8 +637,6 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy) | |||
637 | printk (KERN_INFO PFX "Minimum speed %d MHz. Maximum speed %d MHz.\n", | 637 | printk (KERN_INFO PFX "Minimum speed %d MHz. Maximum speed %d MHz.\n", |
638 | minimum_speed/1000, maximum_speed/1000); | 638 | minimum_speed/1000, maximum_speed/1000); |
639 | 639 | ||
640 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
641 | |||
642 | policy->cpuinfo.transition_latency = cpufreq_scale(2000000UL, fsb, latency); | 640 | policy->cpuinfo.transition_latency = cpufreq_scale(2000000UL, fsb, latency); |
643 | 641 | ||
644 | policy->cur = powernow_get(0); | 642 | policy->cur = powernow_get(0); |
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c index 34ed53a06730..b273b69cfddf 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c | |||
@@ -76,7 +76,10 @@ static u32 find_khz_freq_from_fid(u32 fid) | |||
76 | /* Return a frequency in MHz, given an input fid and did */ | 76 | /* Return a frequency in MHz, given an input fid and did */ |
77 | static u32 find_freq_from_fiddid(u32 fid, u32 did) | 77 | static u32 find_freq_from_fiddid(u32 fid, u32 did) |
78 | { | 78 | { |
79 | return 100 * (fid + 0x10) >> did; | 79 | if (current_cpu_data.x86 == 0x10) |
80 | return 100 * (fid + 0x10) >> did; | ||
81 | else | ||
82 | return 100 * (fid + 0x8) >> did; | ||
80 | } | 83 | } |
81 | 84 | ||
82 | static u32 find_khz_freq_from_fiddid(u32 fid, u32 did) | 85 | static u32 find_khz_freq_from_fiddid(u32 fid, u32 did) |
@@ -1208,7 +1211,6 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) | |||
1208 | /* run on any CPU again */ | 1211 | /* run on any CPU again */ |
1209 | set_cpus_allowed(current, oldmask); | 1212 | set_cpus_allowed(current, oldmask); |
1210 | 1213 | ||
1211 | pol->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
1212 | if (cpu_family == CPU_HW_PSTATE) | 1214 | if (cpu_family == CPU_HW_PSTATE) |
1213 | pol->cpus = cpumask_of_cpu(pol->cpu); | 1215 | pol->cpus = cpumask_of_cpu(pol->cpu); |
1214 | else | 1216 | else |
@@ -1325,21 +1327,16 @@ static struct cpufreq_driver cpufreq_amd64_driver = { | |||
1325 | static int __cpuinit powernowk8_init(void) | 1327 | static int __cpuinit powernowk8_init(void) |
1326 | { | 1328 | { |
1327 | unsigned int i, supported_cpus = 0; | 1329 | unsigned int i, supported_cpus = 0; |
1328 | unsigned int booted_cores = 1; | ||
1329 | 1330 | ||
1330 | for_each_online_cpu(i) { | 1331 | for_each_online_cpu(i) { |
1331 | if (check_supported_cpu(i)) | 1332 | if (check_supported_cpu(i)) |
1332 | supported_cpus++; | 1333 | supported_cpus++; |
1333 | } | 1334 | } |
1334 | 1335 | ||
1335 | #ifdef CONFIG_SMP | ||
1336 | booted_cores = cpu_data[0].booted_cores; | ||
1337 | #endif | ||
1338 | |||
1339 | if (supported_cpus == num_online_cpus()) { | 1336 | if (supported_cpus == num_online_cpus()) { |
1340 | printk(KERN_INFO PFX "Found %d %s " | 1337 | printk(KERN_INFO PFX "Found %d %s " |
1341 | "processors (%d cpu cores) (" VERSION ")\n", | 1338 | "processors (%d cpu cores) (" VERSION ")\n", |
1342 | supported_cpus/booted_cores, | 1339 | num_online_nodes(), |
1343 | boot_cpu_data.x86_model_id, supported_cpus); | 1340 | boot_cpu_data.x86_model_id, supported_cpus); |
1344 | return cpufreq_register_driver(&cpufreq_amd64_driver); | 1341 | return cpufreq_register_driver(&cpufreq_amd64_driver); |
1345 | } | 1342 | } |
diff --git a/arch/x86/kernel/cpu/cpufreq/sc520_freq.c b/arch/x86/kernel/cpu/cpufreq/sc520_freq.c index b8fb4b521c62..d9f3e90a7ae0 100644 --- a/arch/x86/kernel/cpu/cpufreq/sc520_freq.c +++ b/arch/x86/kernel/cpu/cpufreq/sc520_freq.c | |||
@@ -111,7 +111,6 @@ static int sc520_freq_cpu_init(struct cpufreq_policy *policy) | |||
111 | return -ENODEV; | 111 | return -ENODEV; |
112 | 112 | ||
113 | /* cpuinfo and default policy values */ | 113 | /* cpuinfo and default policy values */ |
114 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
115 | policy->cpuinfo.transition_latency = 1000000; /* 1ms */ | 114 | policy->cpuinfo.transition_latency = 1000000; /* 1ms */ |
116 | policy->cur = sc520_freq_get_cpu_frequency(0); | 115 | policy->cur = sc520_freq_get_cpu_frequency(0); |
117 | 116 | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c index 6c5dc2c85aeb..811d47438546 100644 --- a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c +++ b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c | |||
@@ -393,7 +393,6 @@ static int centrino_cpu_init(struct cpufreq_policy *policy) | |||
393 | 393 | ||
394 | freq = get_cur_freq(policy->cpu); | 394 | freq = get_cur_freq(policy->cpu); |
395 | 395 | ||
396 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
397 | policy->cpuinfo.transition_latency = 10000; /* 10uS transition latency */ | 396 | policy->cpuinfo.transition_latency = 10000; /* 10uS transition latency */ |
398 | policy->cur = freq; | 397 | policy->cur = freq; |
399 | 398 | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c index a5b2346faf1f..36685e8f7be1 100644 --- a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c +++ b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c | |||
@@ -348,7 +348,6 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) | |||
348 | (speed / 1000)); | 348 | (speed / 1000)); |
349 | 349 | ||
350 | /* cpuinfo and default policy values */ | 350 | /* cpuinfo and default policy values */ |
351 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
352 | policy->cur = speed; | 351 | policy->cur = speed; |
353 | 352 | ||
354 | result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs); | 353 | result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs); |
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c b/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c index e1c509aa3054..f2b5a621d27b 100644 --- a/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c +++ b/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c | |||
@@ -290,7 +290,6 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) | |||
290 | (speed / 1000)); | 290 | (speed / 1000)); |
291 | 291 | ||
292 | /* cpuinfo and default policy values */ | 292 | /* cpuinfo and default policy values */ |
293 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
294 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; | 293 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; |
295 | policy->cur = speed; | 294 | policy->cur = speed; |
296 | 295 | ||
diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c index 5c2faa10e9fa..f4548c93ccf5 100644 --- a/arch/x86/kernel/cpuid.c +++ b/arch/x86/kernel/cpuid.c | |||
@@ -11,8 +11,6 @@ | |||
11 | * ----------------------------------------------------------------------- */ | 11 | * ----------------------------------------------------------------------- */ |
12 | 12 | ||
13 | /* | 13 | /* |
14 | * cpuid.c | ||
15 | * | ||
16 | * x86 CPUID access device | 14 | * x86 CPUID access device |
17 | * | 15 | * |
18 | * This device is accessed by lseek() to the appropriate CPUID level | 16 | * This device is accessed by lseek() to the appropriate CPUID level |
diff --git a/arch/x86/kernel/crash_dump_32.c b/arch/x86/kernel/crash_dump_32.c index 3f532df488bc..32e75d0731a9 100644 --- a/arch/x86/kernel/crash_dump_32.c +++ b/arch/x86/kernel/crash_dump_32.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * kernel/crash_dump.c - Memory preserving reboot related code. | 2 | * Memory preserving reboot related code. |
3 | * | 3 | * |
4 | * Created by: Hariprasad Nellitheertha (hari@in.ibm.com) | 4 | * Created by: Hariprasad Nellitheertha (hari@in.ibm.com) |
5 | * Copyright (C) IBM Corporation, 2004. All rights reserved | 5 | * Copyright (C) IBM Corporation, 2004. All rights reserved |
diff --git a/arch/x86/kernel/crash_dump_64.c b/arch/x86/kernel/crash_dump_64.c index 942deac4d43a..15e6c6bc4a46 100644 --- a/arch/x86/kernel/crash_dump_64.c +++ b/arch/x86/kernel/crash_dump_64.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * kernel/crash_dump.c - Memory preserving reboot related code. | 2 | * Memory preserving reboot related code. |
3 | * | 3 | * |
4 | * Created by: Hariprasad Nellitheertha (hari@in.ibm.com) | 4 | * Created by: Hariprasad Nellitheertha (hari@in.ibm.com) |
5 | * Copyright (C) IBM Corporation, 2004. All rights reserved | 5 | * Copyright (C) IBM Corporation, 2004. All rights reserved |
diff --git a/arch/x86/kernel/geode_32.c b/arch/x86/kernel/geode_32.c index 41e8aec4c61d..f12d8c5d9809 100644 --- a/arch/x86/kernel/geode_32.c +++ b/arch/x86/kernel/geode_32.c | |||
@@ -145,10 +145,14 @@ EXPORT_SYMBOL_GPL(geode_gpio_setup_event); | |||
145 | 145 | ||
146 | static int __init geode_southbridge_init(void) | 146 | static int __init geode_southbridge_init(void) |
147 | { | 147 | { |
148 | int timers; | ||
149 | |||
148 | if (!is_geode()) | 150 | if (!is_geode()) |
149 | return -ENODEV; | 151 | return -ENODEV; |
150 | 152 | ||
151 | init_lbars(); | 153 | init_lbars(); |
154 | timers = geode_mfgpt_detect(); | ||
155 | printk(KERN_INFO "geode: %d MFGPT timers available.\n", timers); | ||
152 | return 0; | 156 | return 0; |
153 | } | 157 | } |
154 | 158 | ||
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 6c34bdd22e26..8561f626edad 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/x86_64/kernel/head64.c -- prepare to run common code | 2 | * prepare to run common code |
3 | * | 3 | * |
4 | * Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE | 4 | * Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE |
5 | */ | 5 | */ |
diff --git a/arch/x86/kernel/hpet_32.c b/arch/x86/kernel/hpet.c index 533d4932bc79..f8367074da0d 100644 --- a/arch/x86/kernel/hpet_32.c +++ b/arch/x86/kernel/hpet.c | |||
@@ -1,5 +1,6 @@ | |||
1 | #include <linux/clocksource.h> | 1 | #include <linux/clocksource.h> |
2 | #include <linux/clockchips.h> | 2 | #include <linux/clockchips.h> |
3 | #include <linux/delay.h> | ||
3 | #include <linux/errno.h> | 4 | #include <linux/errno.h> |
4 | #include <linux/hpet.h> | 5 | #include <linux/hpet.h> |
5 | #include <linux/init.h> | 6 | #include <linux/init.h> |
@@ -7,11 +8,11 @@ | |||
7 | #include <linux/pm.h> | 8 | #include <linux/pm.h> |
8 | #include <linux/delay.h> | 9 | #include <linux/delay.h> |
9 | 10 | ||
11 | #include <asm/fixmap.h> | ||
10 | #include <asm/hpet.h> | 12 | #include <asm/hpet.h> |
13 | #include <asm/i8253.h> | ||
11 | #include <asm/io.h> | 14 | #include <asm/io.h> |
12 | 15 | ||
13 | extern struct clock_event_device *global_clock_event; | ||
14 | |||
15 | #define HPET_MASK CLOCKSOURCE_MASK(32) | 16 | #define HPET_MASK CLOCKSOURCE_MASK(32) |
16 | #define HPET_SHIFT 22 | 17 | #define HPET_SHIFT 22 |
17 | 18 | ||
@@ -22,9 +23,9 @@ extern struct clock_event_device *global_clock_event; | |||
22 | * HPET address is set in acpi/boot.c, when an ACPI entry exists | 23 | * HPET address is set in acpi/boot.c, when an ACPI entry exists |
23 | */ | 24 | */ |
24 | unsigned long hpet_address; | 25 | unsigned long hpet_address; |
25 | static void __iomem * hpet_virt_address; | 26 | static void __iomem *hpet_virt_address; |
26 | 27 | ||
27 | static inline unsigned long hpet_readl(unsigned long a) | 28 | unsigned long hpet_readl(unsigned long a) |
28 | { | 29 | { |
29 | return readl(hpet_virt_address + a); | 30 | return readl(hpet_virt_address + a); |
30 | } | 31 | } |
@@ -34,6 +35,36 @@ static inline void hpet_writel(unsigned long d, unsigned long a) | |||
34 | writel(d, hpet_virt_address + a); | 35 | writel(d, hpet_virt_address + a); |
35 | } | 36 | } |
36 | 37 | ||
38 | #ifdef CONFIG_X86_64 | ||
39 | |||
40 | #include <asm/pgtable.h> | ||
41 | |||
42 | static inline void hpet_set_mapping(void) | ||
43 | { | ||
44 | set_fixmap_nocache(FIX_HPET_BASE, hpet_address); | ||
45 | __set_fixmap(VSYSCALL_HPET, hpet_address, PAGE_KERNEL_VSYSCALL_NOCACHE); | ||
46 | hpet_virt_address = (void __iomem *)fix_to_virt(FIX_HPET_BASE); | ||
47 | } | ||
48 | |||
49 | static inline void hpet_clear_mapping(void) | ||
50 | { | ||
51 | hpet_virt_address = NULL; | ||
52 | } | ||
53 | |||
54 | #else | ||
55 | |||
56 | static inline void hpet_set_mapping(void) | ||
57 | { | ||
58 | hpet_virt_address = ioremap_nocache(hpet_address, HPET_MMAP_SIZE); | ||
59 | } | ||
60 | |||
61 | static inline void hpet_clear_mapping(void) | ||
62 | { | ||
63 | iounmap(hpet_virt_address); | ||
64 | hpet_virt_address = NULL; | ||
65 | } | ||
66 | #endif | ||
67 | |||
37 | /* | 68 | /* |
38 | * HPET command line enable / disable | 69 | * HPET command line enable / disable |
39 | */ | 70 | */ |
@@ -49,6 +80,13 @@ static int __init hpet_setup(char* str) | |||
49 | } | 80 | } |
50 | __setup("hpet=", hpet_setup); | 81 | __setup("hpet=", hpet_setup); |
51 | 82 | ||
83 | static int __init disable_hpet(char *str) | ||
84 | { | ||
85 | boot_hpet_disable = 1; | ||
86 | return 1; | ||
87 | } | ||
88 | __setup("nohpet", disable_hpet); | ||
89 | |||
52 | static inline int is_hpet_capable(void) | 90 | static inline int is_hpet_capable(void) |
53 | { | 91 | { |
54 | return (!boot_hpet_disable && hpet_address); | 92 | return (!boot_hpet_disable && hpet_address); |
@@ -83,7 +121,7 @@ static void hpet_reserve_platform_timers(unsigned long id) | |||
83 | 121 | ||
84 | memset(&hd, 0, sizeof (hd)); | 122 | memset(&hd, 0, sizeof (hd)); |
85 | hd.hd_phys_address = hpet_address; | 123 | hd.hd_phys_address = hpet_address; |
86 | hd.hd_address = hpet_virt_address; | 124 | hd.hd_address = hpet; |
87 | hd.hd_nirqs = nrtimers; | 125 | hd.hd_nirqs = nrtimers; |
88 | hd.hd_flags = HPET_DATA_PLATFORM; | 126 | hd.hd_flags = HPET_DATA_PLATFORM; |
89 | hpet_reserve_timer(&hd, 0); | 127 | hpet_reserve_timer(&hd, 0); |
@@ -111,9 +149,9 @@ static void hpet_reserve_platform_timers(unsigned long id) { } | |||
111 | */ | 149 | */ |
112 | static unsigned long hpet_period; | 150 | static unsigned long hpet_period; |
113 | 151 | ||
114 | static void hpet_set_mode(enum clock_event_mode mode, | 152 | static void hpet_legacy_set_mode(enum clock_event_mode mode, |
115 | struct clock_event_device *evt); | 153 | struct clock_event_device *evt); |
116 | static int hpet_next_event(unsigned long delta, | 154 | static int hpet_legacy_next_event(unsigned long delta, |
117 | struct clock_event_device *evt); | 155 | struct clock_event_device *evt); |
118 | 156 | ||
119 | /* | 157 | /* |
@@ -122,10 +160,11 @@ static int hpet_next_event(unsigned long delta, | |||
122 | static struct clock_event_device hpet_clockevent = { | 160 | static struct clock_event_device hpet_clockevent = { |
123 | .name = "hpet", | 161 | .name = "hpet", |
124 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | 162 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, |
125 | .set_mode = hpet_set_mode, | 163 | .set_mode = hpet_legacy_set_mode, |
126 | .set_next_event = hpet_next_event, | 164 | .set_next_event = hpet_legacy_next_event, |
127 | .shift = 32, | 165 | .shift = 32, |
128 | .irq = 0, | 166 | .irq = 0, |
167 | .rating = 50, | ||
129 | }; | 168 | }; |
130 | 169 | ||
131 | static void hpet_start_counter(void) | 170 | static void hpet_start_counter(void) |
@@ -140,7 +179,18 @@ static void hpet_start_counter(void) | |||
140 | hpet_writel(cfg, HPET_CFG); | 179 | hpet_writel(cfg, HPET_CFG); |
141 | } | 180 | } |
142 | 181 | ||
143 | static void hpet_enable_int(void) | 182 | static void hpet_resume_device(void) |
183 | { | ||
184 | force_hpet_resume(); | ||
185 | } | ||
186 | |||
187 | static void hpet_restart_counter(void) | ||
188 | { | ||
189 | hpet_resume_device(); | ||
190 | hpet_start_counter(); | ||
191 | } | ||
192 | |||
193 | static void hpet_enable_legacy_int(void) | ||
144 | { | 194 | { |
145 | unsigned long cfg = hpet_readl(HPET_CFG); | 195 | unsigned long cfg = hpet_readl(HPET_CFG); |
146 | 196 | ||
@@ -149,7 +199,39 @@ static void hpet_enable_int(void) | |||
149 | hpet_legacy_int_enabled = 1; | 199 | hpet_legacy_int_enabled = 1; |
150 | } | 200 | } |
151 | 201 | ||
152 | static void hpet_set_mode(enum clock_event_mode mode, | 202 | static void hpet_legacy_clockevent_register(void) |
203 | { | ||
204 | uint64_t hpet_freq; | ||
205 | |||
206 | /* Start HPET legacy interrupts */ | ||
207 | hpet_enable_legacy_int(); | ||
208 | |||
209 | /* | ||
210 | * The period is a femto seconds value. We need to calculate the | ||
211 | * scaled math multiplication factor for nanosecond to hpet tick | ||
212 | * conversion. | ||
213 | */ | ||
214 | hpet_freq = 1000000000000000ULL; | ||
215 | do_div(hpet_freq, hpet_period); | ||
216 | hpet_clockevent.mult = div_sc((unsigned long) hpet_freq, | ||
217 | NSEC_PER_SEC, 32); | ||
218 | /* Calculate the min / max delta */ | ||
219 | hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF, | ||
220 | &hpet_clockevent); | ||
221 | hpet_clockevent.min_delta_ns = clockevent_delta2ns(0x30, | ||
222 | &hpet_clockevent); | ||
223 | |||
224 | /* | ||
225 | * Start hpet with the boot cpu mask and make it | ||
226 | * global after the IO_APIC has been initialized. | ||
227 | */ | ||
228 | hpet_clockevent.cpumask = cpumask_of_cpu(smp_processor_id()); | ||
229 | clockevents_register_device(&hpet_clockevent); | ||
230 | global_clock_event = &hpet_clockevent; | ||
231 | printk(KERN_DEBUG "hpet clockevent registered\n"); | ||
232 | } | ||
233 | |||
234 | static void hpet_legacy_set_mode(enum clock_event_mode mode, | ||
153 | struct clock_event_device *evt) | 235 | struct clock_event_device *evt) |
154 | { | 236 | { |
155 | unsigned long cfg, cmp, now; | 237 | unsigned long cfg, cmp, now; |
@@ -190,12 +272,12 @@ static void hpet_set_mode(enum clock_event_mode mode, | |||
190 | break; | 272 | break; |
191 | 273 | ||
192 | case CLOCK_EVT_MODE_RESUME: | 274 | case CLOCK_EVT_MODE_RESUME: |
193 | hpet_enable_int(); | 275 | hpet_enable_legacy_int(); |
194 | break; | 276 | break; |
195 | } | 277 | } |
196 | } | 278 | } |
197 | 279 | ||
198 | static int hpet_next_event(unsigned long delta, | 280 | static int hpet_legacy_next_event(unsigned long delta, |
199 | struct clock_event_device *evt) | 281 | struct clock_event_device *evt) |
200 | { | 282 | { |
201 | unsigned long cnt; | 283 | unsigned long cnt; |
@@ -215,6 +297,13 @@ static cycle_t read_hpet(void) | |||
215 | return (cycle_t)hpet_readl(HPET_COUNTER); | 297 | return (cycle_t)hpet_readl(HPET_COUNTER); |
216 | } | 298 | } |
217 | 299 | ||
300 | #ifdef CONFIG_X86_64 | ||
301 | static cycle_t __vsyscall_fn vread_hpet(void) | ||
302 | { | ||
303 | return readl((const void __iomem *)fix_to_virt(VSYSCALL_HPET) + 0xf0); | ||
304 | } | ||
305 | #endif | ||
306 | |||
218 | static struct clocksource clocksource_hpet = { | 307 | static struct clocksource clocksource_hpet = { |
219 | .name = "hpet", | 308 | .name = "hpet", |
220 | .rating = 250, | 309 | .rating = 250, |
@@ -222,61 +311,17 @@ static struct clocksource clocksource_hpet = { | |||
222 | .mask = HPET_MASK, | 311 | .mask = HPET_MASK, |
223 | .shift = HPET_SHIFT, | 312 | .shift = HPET_SHIFT, |
224 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 313 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
225 | .resume = hpet_start_counter, | 314 | .resume = hpet_restart_counter, |
315 | #ifdef CONFIG_X86_64 | ||
316 | .vread = vread_hpet, | ||
317 | #endif | ||
226 | }; | 318 | }; |
227 | 319 | ||
228 | /* | 320 | static int hpet_clocksource_register(void) |
229 | * Try to setup the HPET timer | ||
230 | */ | ||
231 | int __init hpet_enable(void) | ||
232 | { | 321 | { |
233 | unsigned long id; | ||
234 | uint64_t hpet_freq; | ||
235 | u64 tmp, start, now; | 322 | u64 tmp, start, now; |
236 | cycle_t t1; | 323 | cycle_t t1; |
237 | 324 | ||
238 | if (!is_hpet_capable()) | ||
239 | return 0; | ||
240 | |||
241 | hpet_virt_address = ioremap_nocache(hpet_address, HPET_MMAP_SIZE); | ||
242 | |||
243 | /* | ||
244 | * Read the period and check for a sane value: | ||
245 | */ | ||
246 | hpet_period = hpet_readl(HPET_PERIOD); | ||
247 | if (hpet_period < HPET_MIN_PERIOD || hpet_period > HPET_MAX_PERIOD) | ||
248 | goto out_nohpet; | ||
249 | |||
250 | /* | ||
251 | * The period is a femto seconds value. We need to calculate the | ||
252 | * scaled math multiplication factor for nanosecond to hpet tick | ||
253 | * conversion. | ||
254 | */ | ||
255 | hpet_freq = 1000000000000000ULL; | ||
256 | do_div(hpet_freq, hpet_period); | ||
257 | hpet_clockevent.mult = div_sc((unsigned long) hpet_freq, | ||
258 | NSEC_PER_SEC, 32); | ||
259 | /* Calculate the min / max delta */ | ||
260 | hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF, | ||
261 | &hpet_clockevent); | ||
262 | hpet_clockevent.min_delta_ns = clockevent_delta2ns(0x30, | ||
263 | &hpet_clockevent); | ||
264 | |||
265 | /* | ||
266 | * Read the HPET ID register to retrieve the IRQ routing | ||
267 | * information and the number of channels | ||
268 | */ | ||
269 | id = hpet_readl(HPET_ID); | ||
270 | |||
271 | #ifdef CONFIG_HPET_EMULATE_RTC | ||
272 | /* | ||
273 | * The legacy routing mode needs at least two channels, tick timer | ||
274 | * and the rtc emulation channel. | ||
275 | */ | ||
276 | if (!(id & HPET_ID_NUMBER)) | ||
277 | goto out_nohpet; | ||
278 | #endif | ||
279 | |||
280 | /* Start the counter */ | 325 | /* Start the counter */ |
281 | hpet_start_counter(); | 326 | hpet_start_counter(); |
282 | 327 | ||
@@ -298,7 +343,7 @@ int __init hpet_enable(void) | |||
298 | if (t1 == read_hpet()) { | 343 | if (t1 == read_hpet()) { |
299 | printk(KERN_WARNING | 344 | printk(KERN_WARNING |
300 | "HPET counter not counting. HPET disabled\n"); | 345 | "HPET counter not counting. HPET disabled\n"); |
301 | goto out_nohpet; | 346 | return -ENODEV; |
302 | } | 347 | } |
303 | 348 | ||
304 | /* Initialize and register HPET clocksource | 349 | /* Initialize and register HPET clocksource |
@@ -319,27 +364,84 @@ int __init hpet_enable(void) | |||
319 | 364 | ||
320 | clocksource_register(&clocksource_hpet); | 365 | clocksource_register(&clocksource_hpet); |
321 | 366 | ||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | /* | ||
371 | * Try to setup the HPET timer | ||
372 | */ | ||
373 | int __init hpet_enable(void) | ||
374 | { | ||
375 | unsigned long id; | ||
376 | |||
377 | if (!is_hpet_capable()) | ||
378 | return 0; | ||
379 | |||
380 | hpet_set_mapping(); | ||
381 | |||
382 | /* | ||
383 | * Read the period and check for a sane value: | ||
384 | */ | ||
385 | hpet_period = hpet_readl(HPET_PERIOD); | ||
386 | if (hpet_period < HPET_MIN_PERIOD || hpet_period > HPET_MAX_PERIOD) | ||
387 | goto out_nohpet; | ||
388 | |||
389 | /* | ||
390 | * Read the HPET ID register to retrieve the IRQ routing | ||
391 | * information and the number of channels | ||
392 | */ | ||
393 | id = hpet_readl(HPET_ID); | ||
394 | |||
395 | #ifdef CONFIG_HPET_EMULATE_RTC | ||
396 | /* | ||
397 | * The legacy routing mode needs at least two channels, tick timer | ||
398 | * and the rtc emulation channel. | ||
399 | */ | ||
400 | if (!(id & HPET_ID_NUMBER)) | ||
401 | goto out_nohpet; | ||
402 | #endif | ||
403 | |||
404 | if (hpet_clocksource_register()) | ||
405 | goto out_nohpet; | ||
406 | |||
322 | if (id & HPET_ID_LEGSUP) { | 407 | if (id & HPET_ID_LEGSUP) { |
323 | hpet_enable_int(); | 408 | hpet_legacy_clockevent_register(); |
324 | hpet_reserve_platform_timers(id); | ||
325 | /* | ||
326 | * Start hpet with the boot cpu mask and make it | ||
327 | * global after the IO_APIC has been initialized. | ||
328 | */ | ||
329 | hpet_clockevent.cpumask = cpumask_of_cpu(smp_processor_id()); | ||
330 | clockevents_register_device(&hpet_clockevent); | ||
331 | global_clock_event = &hpet_clockevent; | ||
332 | return 1; | 409 | return 1; |
333 | } | 410 | } |
334 | return 0; | 411 | return 0; |
335 | 412 | ||
336 | out_nohpet: | 413 | out_nohpet: |
337 | iounmap(hpet_virt_address); | 414 | hpet_clear_mapping(); |
338 | hpet_virt_address = NULL; | ||
339 | boot_hpet_disable = 1; | 415 | boot_hpet_disable = 1; |
340 | return 0; | 416 | return 0; |
341 | } | 417 | } |
342 | 418 | ||
419 | /* | ||
420 | * Needs to be late, as the reserve_timer code calls kalloc ! | ||
421 | * | ||
422 | * Not a problem on i386 as hpet_enable is called from late_time_init, | ||
423 | * but on x86_64 it is necessary ! | ||
424 | */ | ||
425 | static __init int hpet_late_init(void) | ||
426 | { | ||
427 | if (boot_hpet_disable) | ||
428 | return -ENODEV; | ||
429 | |||
430 | if (!hpet_address) { | ||
431 | if (!force_hpet_address) | ||
432 | return -ENODEV; | ||
433 | |||
434 | hpet_address = force_hpet_address; | ||
435 | hpet_enable(); | ||
436 | if (!hpet_virt_address) | ||
437 | return -ENODEV; | ||
438 | } | ||
439 | |||
440 | hpet_reserve_platform_timers(hpet_readl(HPET_ID)); | ||
441 | |||
442 | return 0; | ||
443 | } | ||
444 | fs_initcall(hpet_late_init); | ||
343 | 445 | ||
344 | #ifdef CONFIG_HPET_EMULATE_RTC | 446 | #ifdef CONFIG_HPET_EMULATE_RTC |
345 | 447 | ||
diff --git a/arch/x86/kernel/hpet_64.c b/arch/x86/kernel/hpet_64.c deleted file mode 100644 index e2d1b912e154..000000000000 --- a/arch/x86/kernel/hpet_64.c +++ /dev/null | |||
@@ -1,493 +0,0 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/sched.h> | ||
3 | #include <linux/init.h> | ||
4 | #include <linux/mc146818rtc.h> | ||
5 | #include <linux/time.h> | ||
6 | #include <linux/clocksource.h> | ||
7 | #include <linux/ioport.h> | ||
8 | #include <linux/acpi.h> | ||
9 | #include <linux/hpet.h> | ||
10 | #include <asm/pgtable.h> | ||
11 | #include <asm/vsyscall.h> | ||
12 | #include <asm/timex.h> | ||
13 | #include <asm/hpet.h> | ||
14 | |||
15 | #define HPET_MASK 0xFFFFFFFF | ||
16 | #define HPET_SHIFT 22 | ||
17 | |||
18 | /* FSEC = 10^-15 NSEC = 10^-9 */ | ||
19 | #define FSEC_PER_NSEC 1000000 | ||
20 | |||
21 | int nohpet __initdata; | ||
22 | |||
23 | unsigned long hpet_address; | ||
24 | unsigned long hpet_period; /* fsecs / HPET clock */ | ||
25 | unsigned long hpet_tick; /* HPET clocks / interrupt */ | ||
26 | |||
27 | int hpet_use_timer; /* Use counter of hpet for time keeping, | ||
28 | * otherwise PIT | ||
29 | */ | ||
30 | |||
31 | #ifdef CONFIG_HPET | ||
32 | static __init int late_hpet_init(void) | ||
33 | { | ||
34 | struct hpet_data hd; | ||
35 | unsigned int ntimer; | ||
36 | |||
37 | if (!hpet_address) | ||
38 | return 0; | ||
39 | |||
40 | memset(&hd, 0, sizeof(hd)); | ||
41 | |||
42 | ntimer = hpet_readl(HPET_ID); | ||
43 | ntimer = (ntimer & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT; | ||
44 | ntimer++; | ||
45 | |||
46 | /* | ||
47 | * Register with driver. | ||
48 | * Timer0 and Timer1 is used by platform. | ||
49 | */ | ||
50 | hd.hd_phys_address = hpet_address; | ||
51 | hd.hd_address = (void __iomem *)fix_to_virt(FIX_HPET_BASE); | ||
52 | hd.hd_nirqs = ntimer; | ||
53 | hd.hd_flags = HPET_DATA_PLATFORM; | ||
54 | hpet_reserve_timer(&hd, 0); | ||
55 | #ifdef CONFIG_HPET_EMULATE_RTC | ||
56 | hpet_reserve_timer(&hd, 1); | ||
57 | #endif | ||
58 | hd.hd_irq[0] = HPET_LEGACY_8254; | ||
59 | hd.hd_irq[1] = HPET_LEGACY_RTC; | ||
60 | if (ntimer > 2) { | ||
61 | struct hpet *hpet; | ||
62 | struct hpet_timer *timer; | ||
63 | int i; | ||
64 | |||
65 | hpet = (struct hpet *) fix_to_virt(FIX_HPET_BASE); | ||
66 | timer = &hpet->hpet_timers[2]; | ||
67 | for (i = 2; i < ntimer; timer++, i++) | ||
68 | hd.hd_irq[i] = (timer->hpet_config & | ||
69 | Tn_INT_ROUTE_CNF_MASK) >> | ||
70 | Tn_INT_ROUTE_CNF_SHIFT; | ||
71 | |||
72 | } | ||
73 | |||
74 | hpet_alloc(&hd); | ||
75 | return 0; | ||
76 | } | ||
77 | fs_initcall(late_hpet_init); | ||
78 | #endif | ||
79 | |||
80 | int hpet_timer_stop_set_go(unsigned long tick) | ||
81 | { | ||
82 | unsigned int cfg; | ||
83 | |||
84 | /* | ||
85 | * Stop the timers and reset the main counter. | ||
86 | */ | ||
87 | |||
88 | cfg = hpet_readl(HPET_CFG); | ||
89 | cfg &= ~(HPET_CFG_ENABLE | HPET_CFG_LEGACY); | ||
90 | hpet_writel(cfg, HPET_CFG); | ||
91 | hpet_writel(0, HPET_COUNTER); | ||
92 | hpet_writel(0, HPET_COUNTER + 4); | ||
93 | |||
94 | /* | ||
95 | * Set up timer 0, as periodic with first interrupt to happen at hpet_tick, | ||
96 | * and period also hpet_tick. | ||
97 | */ | ||
98 | if (hpet_use_timer) { | ||
99 | hpet_writel(HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL | | ||
100 | HPET_TN_32BIT, HPET_T0_CFG); | ||
101 | hpet_writel(hpet_tick, HPET_T0_CMP); /* next interrupt */ | ||
102 | hpet_writel(hpet_tick, HPET_T0_CMP); /* period */ | ||
103 | cfg |= HPET_CFG_LEGACY; | ||
104 | } | ||
105 | /* | ||
106 | * Go! | ||
107 | */ | ||
108 | |||
109 | cfg |= HPET_CFG_ENABLE; | ||
110 | hpet_writel(cfg, HPET_CFG); | ||
111 | |||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static cycle_t read_hpet(void) | ||
116 | { | ||
117 | return (cycle_t)hpet_readl(HPET_COUNTER); | ||
118 | } | ||
119 | |||
120 | static cycle_t __vsyscall_fn vread_hpet(void) | ||
121 | { | ||
122 | return readl((void __iomem *)fix_to_virt(VSYSCALL_HPET) + 0xf0); | ||
123 | } | ||
124 | |||
125 | struct clocksource clocksource_hpet = { | ||
126 | .name = "hpet", | ||
127 | .rating = 250, | ||
128 | .read = read_hpet, | ||
129 | .mask = (cycle_t)HPET_MASK, | ||
130 | .mult = 0, /* set below */ | ||
131 | .shift = HPET_SHIFT, | ||
132 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
133 | .vread = vread_hpet, | ||
134 | }; | ||
135 | |||
136 | int __init hpet_arch_init(void) | ||
137 | { | ||
138 | unsigned int id; | ||
139 | u64 tmp; | ||
140 | |||
141 | if (!hpet_address) | ||
142 | return -1; | ||
143 | set_fixmap_nocache(FIX_HPET_BASE, hpet_address); | ||
144 | __set_fixmap(VSYSCALL_HPET, hpet_address, PAGE_KERNEL_VSYSCALL_NOCACHE); | ||
145 | |||
146 | /* | ||
147 | * Read the period, compute tick and quotient. | ||
148 | */ | ||
149 | |||
150 | id = hpet_readl(HPET_ID); | ||
151 | |||
152 | if (!(id & HPET_ID_VENDOR) || !(id & HPET_ID_NUMBER)) | ||
153 | return -1; | ||
154 | |||
155 | hpet_period = hpet_readl(HPET_PERIOD); | ||
156 | if (hpet_period < 100000 || hpet_period > 100000000) | ||
157 | return -1; | ||
158 | |||
159 | hpet_tick = (FSEC_PER_TICK + hpet_period / 2) / hpet_period; | ||
160 | |||
161 | hpet_use_timer = (id & HPET_ID_LEGSUP); | ||
162 | |||
163 | /* | ||
164 | * hpet period is in femto seconds per cycle | ||
165 | * so we need to convert this to ns/cyc units | ||
166 | * aproximated by mult/2^shift | ||
167 | * | ||
168 | * fsec/cyc * 1nsec/1000000fsec = nsec/cyc = mult/2^shift | ||
169 | * fsec/cyc * 1ns/1000000fsec * 2^shift = mult | ||
170 | * fsec/cyc * 2^shift * 1nsec/1000000fsec = mult | ||
171 | * (fsec/cyc << shift)/1000000 = mult | ||
172 | * (hpet_period << shift)/FSEC_PER_NSEC = mult | ||
173 | */ | ||
174 | tmp = (u64)hpet_period << HPET_SHIFT; | ||
175 | do_div(tmp, FSEC_PER_NSEC); | ||
176 | clocksource_hpet.mult = (u32)tmp; | ||
177 | clocksource_register(&clocksource_hpet); | ||
178 | |||
179 | return hpet_timer_stop_set_go(hpet_tick); | ||
180 | } | ||
181 | |||
182 | int hpet_reenable(void) | ||
183 | { | ||
184 | return hpet_timer_stop_set_go(hpet_tick); | ||
185 | } | ||
186 | |||
187 | /* | ||
188 | * calibrate_tsc() calibrates the processor TSC in a very simple way, comparing | ||
189 | * it to the HPET timer of known frequency. | ||
190 | */ | ||
191 | |||
192 | #define TICK_COUNT 100000000 | ||
193 | #define SMI_THRESHOLD 50000 | ||
194 | #define MAX_TRIES 5 | ||
195 | |||
196 | /* | ||
197 | * Some platforms take periodic SMI interrupts with 5ms duration. Make sure none | ||
198 | * occurs between the reads of the hpet & TSC. | ||
199 | */ | ||
200 | static void __init read_hpet_tsc(int *hpet, int *tsc) | ||
201 | { | ||
202 | int tsc1, tsc2, hpet1, i; | ||
203 | |||
204 | for (i = 0; i < MAX_TRIES; i++) { | ||
205 | tsc1 = get_cycles_sync(); | ||
206 | hpet1 = hpet_readl(HPET_COUNTER); | ||
207 | tsc2 = get_cycles_sync(); | ||
208 | if ((tsc2 - tsc1) < SMI_THRESHOLD) | ||
209 | break; | ||
210 | } | ||
211 | *hpet = hpet1; | ||
212 | *tsc = tsc2; | ||
213 | } | ||
214 | |||
215 | unsigned int __init hpet_calibrate_tsc(void) | ||
216 | { | ||
217 | int tsc_start, hpet_start; | ||
218 | int tsc_now, hpet_now; | ||
219 | unsigned long flags; | ||
220 | |||
221 | local_irq_save(flags); | ||
222 | |||
223 | read_hpet_tsc(&hpet_start, &tsc_start); | ||
224 | |||
225 | do { | ||
226 | local_irq_disable(); | ||
227 | read_hpet_tsc(&hpet_now, &tsc_now); | ||
228 | local_irq_restore(flags); | ||
229 | } while ((tsc_now - tsc_start) < TICK_COUNT && | ||
230 | (hpet_now - hpet_start) < TICK_COUNT); | ||
231 | |||
232 | return (tsc_now - tsc_start) * 1000000000L | ||
233 | / ((hpet_now - hpet_start) * hpet_period / 1000); | ||
234 | } | ||
235 | |||
236 | #ifdef CONFIG_HPET_EMULATE_RTC | ||
237 | /* HPET in LegacyReplacement Mode eats up RTC interrupt line. When, HPET | ||
238 | * is enabled, we support RTC interrupt functionality in software. | ||
239 | * RTC has 3 kinds of interrupts: | ||
240 | * 1) Update Interrupt - generate an interrupt, every sec, when RTC clock | ||
241 | * is updated | ||
242 | * 2) Alarm Interrupt - generate an interrupt at a specific time of day | ||
243 | * 3) Periodic Interrupt - generate periodic interrupt, with frequencies | ||
244 | * 2Hz-8192Hz (2Hz-64Hz for non-root user) (all freqs in powers of 2) | ||
245 | * (1) and (2) above are implemented using polling at a frequency of | ||
246 | * 64 Hz. The exact frequency is a tradeoff between accuracy and interrupt | ||
247 | * overhead. (DEFAULT_RTC_INT_FREQ) | ||
248 | * For (3), we use interrupts at 64Hz or user specified periodic | ||
249 | * frequency, whichever is higher. | ||
250 | */ | ||
251 | #include <linux/rtc.h> | ||
252 | |||
253 | #define DEFAULT_RTC_INT_FREQ 64 | ||
254 | #define RTC_NUM_INTS 1 | ||
255 | |||
256 | static unsigned long UIE_on; | ||
257 | static unsigned long prev_update_sec; | ||
258 | |||
259 | static unsigned long AIE_on; | ||
260 | static struct rtc_time alarm_time; | ||
261 | |||
262 | static unsigned long PIE_on; | ||
263 | static unsigned long PIE_freq = DEFAULT_RTC_INT_FREQ; | ||
264 | static unsigned long PIE_count; | ||
265 | |||
266 | static unsigned long hpet_rtc_int_freq; /* RTC interrupt frequency */ | ||
267 | static unsigned int hpet_t1_cmp; /* cached comparator register */ | ||
268 | |||
269 | int is_hpet_enabled(void) | ||
270 | { | ||
271 | return hpet_address != 0; | ||
272 | } | ||
273 | |||
274 | /* | ||
275 | * Timer 1 for RTC, we do not use periodic interrupt feature, | ||
276 | * even if HPET supports periodic interrupts on Timer 1. | ||
277 | * The reason being, to set up a periodic interrupt in HPET, we need to | ||
278 | * stop the main counter. And if we do that everytime someone diables/enables | ||
279 | * RTC, we will have adverse effect on main kernel timer running on Timer 0. | ||
280 | * So, for the time being, simulate the periodic interrupt in software. | ||
281 | * | ||
282 | * hpet_rtc_timer_init() is called for the first time and during subsequent | ||
283 | * interuppts reinit happens through hpet_rtc_timer_reinit(). | ||
284 | */ | ||
285 | int hpet_rtc_timer_init(void) | ||
286 | { | ||
287 | unsigned int cfg, cnt; | ||
288 | unsigned long flags; | ||
289 | |||
290 | if (!is_hpet_enabled()) | ||
291 | return 0; | ||
292 | /* | ||
293 | * Set the counter 1 and enable the interrupts. | ||
294 | */ | ||
295 | if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ)) | ||
296 | hpet_rtc_int_freq = PIE_freq; | ||
297 | else | ||
298 | hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ; | ||
299 | |||
300 | local_irq_save(flags); | ||
301 | |||
302 | cnt = hpet_readl(HPET_COUNTER); | ||
303 | cnt += ((hpet_tick*HZ)/hpet_rtc_int_freq); | ||
304 | hpet_writel(cnt, HPET_T1_CMP); | ||
305 | hpet_t1_cmp = cnt; | ||
306 | |||
307 | cfg = hpet_readl(HPET_T1_CFG); | ||
308 | cfg &= ~HPET_TN_PERIODIC; | ||
309 | cfg |= HPET_TN_ENABLE | HPET_TN_32BIT; | ||
310 | hpet_writel(cfg, HPET_T1_CFG); | ||
311 | |||
312 | local_irq_restore(flags); | ||
313 | |||
314 | return 1; | ||
315 | } | ||
316 | |||
317 | static void hpet_rtc_timer_reinit(void) | ||
318 | { | ||
319 | unsigned int cfg, cnt, ticks_per_int, lost_ints; | ||
320 | |||
321 | if (unlikely(!(PIE_on | AIE_on | UIE_on))) { | ||
322 | cfg = hpet_readl(HPET_T1_CFG); | ||
323 | cfg &= ~HPET_TN_ENABLE; | ||
324 | hpet_writel(cfg, HPET_T1_CFG); | ||
325 | return; | ||
326 | } | ||
327 | |||
328 | if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ)) | ||
329 | hpet_rtc_int_freq = PIE_freq; | ||
330 | else | ||
331 | hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ; | ||
332 | |||
333 | /* It is more accurate to use the comparator value than current count.*/ | ||
334 | ticks_per_int = hpet_tick * HZ / hpet_rtc_int_freq; | ||
335 | hpet_t1_cmp += ticks_per_int; | ||
336 | hpet_writel(hpet_t1_cmp, HPET_T1_CMP); | ||
337 | |||
338 | /* | ||
339 | * If the interrupt handler was delayed too long, the write above tries | ||
340 | * to schedule the next interrupt in the past and the hardware would | ||
341 | * not interrupt until the counter had wrapped around. | ||
342 | * So we have to check that the comparator wasn't set to a past time. | ||
343 | */ | ||
344 | cnt = hpet_readl(HPET_COUNTER); | ||
345 | if (unlikely((int)(cnt - hpet_t1_cmp) > 0)) { | ||
346 | lost_ints = (cnt - hpet_t1_cmp) / ticks_per_int + 1; | ||
347 | /* Make sure that, even with the time needed to execute | ||
348 | * this code, the next scheduled interrupt has been moved | ||
349 | * back to the future: */ | ||
350 | lost_ints++; | ||
351 | |||
352 | hpet_t1_cmp += lost_ints * ticks_per_int; | ||
353 | hpet_writel(hpet_t1_cmp, HPET_T1_CMP); | ||
354 | |||
355 | if (PIE_on) | ||
356 | PIE_count += lost_ints; | ||
357 | |||
358 | if (printk_ratelimit()) | ||
359 | printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", | ||
360 | hpet_rtc_int_freq); | ||
361 | } | ||
362 | } | ||
363 | |||
364 | /* | ||
365 | * The functions below are called from rtc driver. | ||
366 | * Return 0 if HPET is not being used. | ||
367 | * Otherwise do the necessary changes and return 1. | ||
368 | */ | ||
369 | int hpet_mask_rtc_irq_bit(unsigned long bit_mask) | ||
370 | { | ||
371 | if (!is_hpet_enabled()) | ||
372 | return 0; | ||
373 | |||
374 | if (bit_mask & RTC_UIE) | ||
375 | UIE_on = 0; | ||
376 | if (bit_mask & RTC_PIE) | ||
377 | PIE_on = 0; | ||
378 | if (bit_mask & RTC_AIE) | ||
379 | AIE_on = 0; | ||
380 | |||
381 | return 1; | ||
382 | } | ||
383 | |||
384 | int hpet_set_rtc_irq_bit(unsigned long bit_mask) | ||
385 | { | ||
386 | int timer_init_reqd = 0; | ||
387 | |||
388 | if (!is_hpet_enabled()) | ||
389 | return 0; | ||
390 | |||
391 | if (!(PIE_on | AIE_on | UIE_on)) | ||
392 | timer_init_reqd = 1; | ||
393 | |||
394 | if (bit_mask & RTC_UIE) { | ||
395 | UIE_on = 1; | ||
396 | } | ||
397 | if (bit_mask & RTC_PIE) { | ||
398 | PIE_on = 1; | ||
399 | PIE_count = 0; | ||
400 | } | ||
401 | if (bit_mask & RTC_AIE) { | ||
402 | AIE_on = 1; | ||
403 | } | ||
404 | |||
405 | if (timer_init_reqd) | ||
406 | hpet_rtc_timer_init(); | ||
407 | |||
408 | return 1; | ||
409 | } | ||
410 | |||
411 | int hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned char sec) | ||
412 | { | ||
413 | if (!is_hpet_enabled()) | ||
414 | return 0; | ||
415 | |||
416 | alarm_time.tm_hour = hrs; | ||
417 | alarm_time.tm_min = min; | ||
418 | alarm_time.tm_sec = sec; | ||
419 | |||
420 | return 1; | ||
421 | } | ||
422 | |||
423 | int hpet_set_periodic_freq(unsigned long freq) | ||
424 | { | ||
425 | if (!is_hpet_enabled()) | ||
426 | return 0; | ||
427 | |||
428 | PIE_freq = freq; | ||
429 | PIE_count = 0; | ||
430 | |||
431 | return 1; | ||
432 | } | ||
433 | |||
434 | int hpet_rtc_dropped_irq(void) | ||
435 | { | ||
436 | if (!is_hpet_enabled()) | ||
437 | return 0; | ||
438 | |||
439 | return 1; | ||
440 | } | ||
441 | |||
442 | irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) | ||
443 | { | ||
444 | struct rtc_time curr_time; | ||
445 | unsigned long rtc_int_flag = 0; | ||
446 | int call_rtc_interrupt = 0; | ||
447 | |||
448 | hpet_rtc_timer_reinit(); | ||
449 | |||
450 | if (UIE_on | AIE_on) { | ||
451 | rtc_get_rtc_time(&curr_time); | ||
452 | } | ||
453 | if (UIE_on) { | ||
454 | if (curr_time.tm_sec != prev_update_sec) { | ||
455 | /* Set update int info, call real rtc int routine */ | ||
456 | call_rtc_interrupt = 1; | ||
457 | rtc_int_flag = RTC_UF; | ||
458 | prev_update_sec = curr_time.tm_sec; | ||
459 | } | ||
460 | } | ||
461 | if (PIE_on) { | ||
462 | PIE_count++; | ||
463 | if (PIE_count >= hpet_rtc_int_freq/PIE_freq) { | ||
464 | /* Set periodic int info, call real rtc int routine */ | ||
465 | call_rtc_interrupt = 1; | ||
466 | rtc_int_flag |= RTC_PF; | ||
467 | PIE_count = 0; | ||
468 | } | ||
469 | } | ||
470 | if (AIE_on) { | ||
471 | if ((curr_time.tm_sec == alarm_time.tm_sec) && | ||
472 | (curr_time.tm_min == alarm_time.tm_min) && | ||
473 | (curr_time.tm_hour == alarm_time.tm_hour)) { | ||
474 | /* Set alarm int info, call real rtc int routine */ | ||
475 | call_rtc_interrupt = 1; | ||
476 | rtc_int_flag |= RTC_AF; | ||
477 | } | ||
478 | } | ||
479 | if (call_rtc_interrupt) { | ||
480 | rtc_int_flag |= (RTC_IRQF | (RTC_NUM_INTS << 8)); | ||
481 | rtc_interrupt(rtc_int_flag, dev_id); | ||
482 | } | ||
483 | return IRQ_HANDLED; | ||
484 | } | ||
485 | #endif | ||
486 | |||
487 | static int __init nohpet_setup(char *s) | ||
488 | { | ||
489 | nohpet = 1; | ||
490 | return 1; | ||
491 | } | ||
492 | |||
493 | __setup("nohpet", nohpet_setup); | ||
diff --git a/arch/x86/kernel/i387_32.c b/arch/x86/kernel/i387_32.c index 665847281ed2..7d2e12f6c78b 100644 --- a/arch/x86/kernel/i387_32.c +++ b/arch/x86/kernel/i387_32.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/i386/kernel/i387.c | ||
3 | * | ||
4 | * Copyright (C) 1994 Linus Torvalds | 2 | * Copyright (C) 1994 Linus Torvalds |
5 | * | 3 | * |
6 | * Pentium III FXSR, SSE support | 4 | * Pentium III FXSR, SSE support |
diff --git a/arch/x86/kernel/i387_64.c b/arch/x86/kernel/i387_64.c index 1d58c13bc6bc..56c1f1147109 100644 --- a/arch/x86/kernel/i387_64.c +++ b/arch/x86/kernel/i387_64.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/x86_64/kernel/i387.c | ||
3 | * | ||
4 | * Copyright (C) 1994 Linus Torvalds | 2 | * Copyright (C) 1994 Linus Torvalds |
5 | * Copyright (C) 2002 Andi Kleen, SuSE Labs | 3 | * Copyright (C) 2002 Andi Kleen, SuSE Labs |
6 | * | 4 | * |
diff --git a/arch/x86/kernel/i8237.c b/arch/x86/kernel/i8237.c index 6f508e8d7c57..29313832df0c 100644 --- a/arch/x86/kernel/i8237.c +++ b/arch/x86/kernel/i8237.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * i8237.c: 8237A DMA controller suspend functions. | 2 | * 8237A DMA controller suspend functions. |
3 | * | 3 | * |
4 | * Written by Pierre Ossman, 2005. | 4 | * Written by Pierre Ossman, 2005. |
5 | * | 5 | * |
diff --git a/arch/x86/kernel/i8253_32.c b/arch/x86/kernel/i8253.c index 6d839f2f1b1a..5cc8841ca2c6 100644 --- a/arch/x86/kernel/i8253_32.c +++ b/arch/x86/kernel/i8253.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * i8253.c 8253/PIT functions | 2 | * 8253/PIT functions |
3 | * | 3 | * |
4 | */ | 4 | */ |
5 | #include <linux/clockchips.h> | 5 | #include <linux/clockchips.h> |
@@ -13,7 +13,6 @@ | |||
13 | #include <asm/delay.h> | 13 | #include <asm/delay.h> |
14 | #include <asm/i8253.h> | 14 | #include <asm/i8253.h> |
15 | #include <asm/io.h> | 15 | #include <asm/io.h> |
16 | #include <asm/timer.h> | ||
17 | 16 | ||
18 | DEFINE_SPINLOCK(i8253_lock); | 17 | DEFINE_SPINLOCK(i8253_lock); |
19 | EXPORT_SYMBOL(i8253_lock); | 18 | EXPORT_SYMBOL(i8253_lock); |
@@ -120,6 +119,7 @@ void __init setup_pit_timer(void) | |||
120 | global_clock_event = &pit_clockevent; | 119 | global_clock_event = &pit_clockevent; |
121 | } | 120 | } |
122 | 121 | ||
122 | #ifndef CONFIG_X86_64 | ||
123 | /* | 123 | /* |
124 | * Since the PIT overflows every tick, its not very useful | 124 | * Since the PIT overflows every tick, its not very useful |
125 | * to just read by itself. So use jiffies to emulate a free | 125 | * to just read by itself. So use jiffies to emulate a free |
@@ -204,3 +204,5 @@ static int __init init_pit_clocksource(void) | |||
204 | return clocksource_register(&clocksource_pit); | 204 | return clocksource_register(&clocksource_pit); |
205 | } | 205 | } |
206 | arch_initcall(init_pit_clocksource); | 206 | arch_initcall(init_pit_clocksource); |
207 | |||
208 | #endif | ||
diff --git a/arch/x86/kernel/i8259_32.c b/arch/x86/kernel/i8259_32.c index 0499cbe9871a..679bb33acbf1 100644 --- a/arch/x86/kernel/i8259_32.c +++ b/arch/x86/kernel/i8259_32.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include <linux/sysdev.h> | 10 | #include <linux/sysdev.h> |
11 | #include <linux/bitops.h> | 11 | #include <linux/bitops.h> |
12 | 12 | ||
13 | #include <asm/8253pit.h> | ||
14 | #include <asm/atomic.h> | 13 | #include <asm/atomic.h> |
15 | #include <asm/system.h> | 14 | #include <asm/system.h> |
16 | #include <asm/io.h> | 15 | #include <asm/io.h> |
diff --git a/arch/x86/kernel/i8259_64.c b/arch/x86/kernel/i8259_64.c index 948cae646099..eb72976cc13c 100644 --- a/arch/x86/kernel/i8259_64.c +++ b/arch/x86/kernel/i8259_64.c | |||
@@ -444,46 +444,6 @@ void __init init_ISA_irqs (void) | |||
444 | } | 444 | } |
445 | } | 445 | } |
446 | 446 | ||
447 | static void setup_timer_hardware(void) | ||
448 | { | ||
449 | outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */ | ||
450 | udelay(10); | ||
451 | outb_p(LATCH & 0xff , 0x40); /* LSB */ | ||
452 | udelay(10); | ||
453 | outb(LATCH >> 8 , 0x40); /* MSB */ | ||
454 | } | ||
455 | |||
456 | static int timer_resume(struct sys_device *dev) | ||
457 | { | ||
458 | setup_timer_hardware(); | ||
459 | return 0; | ||
460 | } | ||
461 | |||
462 | void i8254_timer_resume(void) | ||
463 | { | ||
464 | setup_timer_hardware(); | ||
465 | } | ||
466 | |||
467 | static struct sysdev_class timer_sysclass = { | ||
468 | set_kset_name("timer_pit"), | ||
469 | .resume = timer_resume, | ||
470 | }; | ||
471 | |||
472 | static struct sys_device device_timer = { | ||
473 | .id = 0, | ||
474 | .cls = &timer_sysclass, | ||
475 | }; | ||
476 | |||
477 | static int __init init_timer_sysfs(void) | ||
478 | { | ||
479 | int error = sysdev_class_register(&timer_sysclass); | ||
480 | if (!error) | ||
481 | error = sysdev_register(&device_timer); | ||
482 | return error; | ||
483 | } | ||
484 | |||
485 | device_initcall(init_timer_sysfs); | ||
486 | |||
487 | void __init init_IRQ(void) | 447 | void __init init_IRQ(void) |
488 | { | 448 | { |
489 | int i; | 449 | int i; |
@@ -533,12 +493,6 @@ void __init init_IRQ(void) | |||
533 | set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); | 493 | set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); |
534 | set_intr_gate(ERROR_APIC_VECTOR, error_interrupt); | 494 | set_intr_gate(ERROR_APIC_VECTOR, error_interrupt); |
535 | 495 | ||
536 | /* | ||
537 | * Set the clock to HZ Hz, we already have a valid | ||
538 | * vector now: | ||
539 | */ | ||
540 | setup_timer_hardware(); | ||
541 | |||
542 | if (!acpi_ioapic) | 496 | if (!acpi_ioapic) |
543 | setup_irq(2, &irq2); | 497 | setup_irq(2, &irq2); |
544 | } | 498 | } |
diff --git a/arch/x86/kernel/ioport_32.c b/arch/x86/kernel/ioport_32.c index 3d310a946d76..4ed48dc8df1e 100644 --- a/arch/x86/kernel/ioport_32.c +++ b/arch/x86/kernel/ioport_32.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/i386/kernel/ioport.c | ||
3 | * | ||
4 | * This contains the io-permission bitmap code - written by obz, with changes | 2 | * This contains the io-permission bitmap code - written by obz, with changes |
5 | * by Linus. | 3 | * by Linus. |
6 | */ | 4 | */ |
diff --git a/arch/x86/kernel/ioport_64.c b/arch/x86/kernel/ioport_64.c index 653efa30b0f4..5f62fad64dab 100644 --- a/arch/x86/kernel/ioport_64.c +++ b/arch/x86/kernel/ioport_64.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/x86_64/kernel/ioport.c | ||
3 | * | ||
4 | * This contains the io-permission bitmap code - written by obz, with changes | 2 | * This contains the io-permission bitmap code - written by obz, with changes |
5 | * by Linus. | 3 | * by Linus. |
6 | */ | 4 | */ |
diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c index 4f681bcdb1fc..e173b763f148 100644 --- a/arch/x86/kernel/irq_32.c +++ b/arch/x86/kernel/irq_32.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/i386/kernel/irq.c | ||
3 | * | ||
4 | * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar | 2 | * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar |
5 | * | 3 | * |
6 | * This file contains the lowest level x86-specific interrupt | 4 | * This file contains the lowest level x86-specific interrupt |
diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c index bd11e42b22bf..865669efc540 100644 --- a/arch/x86/kernel/irq_64.c +++ b/arch/x86/kernel/irq_64.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/x86_64/kernel/irq.c | ||
3 | * | ||
4 | * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar | 2 | * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar |
5 | * | 3 | * |
6 | * This file contains the lowest level x86_64-specific interrupt | 4 | * This file contains the lowest level x86_64-specific interrupt |
diff --git a/arch/x86/kernel/kprobes_32.c b/arch/x86/kernel/kprobes_32.c index 448a50b1324c..c2d03e96ae9f 100644 --- a/arch/x86/kernel/kprobes_32.c +++ b/arch/x86/kernel/kprobes_32.c | |||
@@ -1,6 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Kernel Probes (KProbes) | 2 | * Kernel Probes (KProbes) |
3 | * arch/i386/kernel/kprobes.c | ||
4 | * | 3 | * |
5 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by | 5 | * it under the terms of the GNU General Public License as published by |
diff --git a/arch/x86/kernel/kprobes_64.c b/arch/x86/kernel/kprobes_64.c index a30e004682e2..1df17a0ec0c9 100644 --- a/arch/x86/kernel/kprobes_64.c +++ b/arch/x86/kernel/kprobes_64.c | |||
@@ -1,6 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Kernel Probes (KProbes) | 2 | * Kernel Probes (KProbes) |
3 | * arch/x86_64/kernel/kprobes.c | ||
4 | * | 3 | * |
5 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by | 5 | * it under the terms of the GNU General Public License as published by |
diff --git a/arch/x86/kernel/ldt_32.c b/arch/x86/kernel/ldt_32.c index e0b2d17f4f10..a8b18421863a 100644 --- a/arch/x86/kernel/ldt_32.c +++ b/arch/x86/kernel/ldt_32.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/i386/kernel/ldt.c | ||
3 | * | ||
4 | * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds | 2 | * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds |
5 | * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com> | 3 | * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com> |
6 | */ | 4 | */ |
diff --git a/arch/x86/kernel/ldt_64.c b/arch/x86/kernel/ldt_64.c index bc9ffd5c19cc..3796523d616a 100644 --- a/arch/x86/kernel/ldt_64.c +++ b/arch/x86/kernel/ldt_64.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/x86_64/kernel/ldt.c | ||
3 | * | ||
4 | * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds | 2 | * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds |
5 | * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com> | 3 | * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com> |
6 | * Copyright (C) 2002 Andi Kleen | 4 | * Copyright (C) 2002 Andi Kleen |
diff --git a/arch/x86/kernel/machine_kexec_32.c b/arch/x86/kernel/machine_kexec_32.c index 91966bafb3dc..deda9a221cf2 100644 --- a/arch/x86/kernel/machine_kexec_32.c +++ b/arch/x86/kernel/machine_kexec_32.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * machine_kexec.c - handle transition of Linux booting another kernel | 2 | * handle transition of Linux booting another kernel |
3 | * Copyright (C) 2002-2005 Eric Biederman <ebiederm@xmission.com> | 3 | * Copyright (C) 2002-2005 Eric Biederman <ebiederm@xmission.com> |
4 | * | 4 | * |
5 | * This source code is licensed under the GNU General Public License, | 5 | * This source code is licensed under the GNU General Public License, |
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c index c3a554703672..cd1899a2f0c5 100644 --- a/arch/x86/kernel/machine_kexec_64.c +++ b/arch/x86/kernel/machine_kexec_64.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * machine_kexec.c - handle transition of Linux booting another kernel | 2 | * handle transition of Linux booting another kernel |
3 | * Copyright (C) 2002-2005 Eric Biederman <ebiederm@xmission.com> | 3 | * Copyright (C) 2002-2005 Eric Biederman <ebiederm@xmission.com> |
4 | * | 4 | * |
5 | * This source code is licensed under the GNU General Public License, | 5 | * This source code is licensed under the GNU General Public License, |
diff --git a/arch/x86/kernel/mca_32.c b/arch/x86/kernel/mca_32.c index b83672b89527..9482033ed0fe 100644 --- a/arch/x86/kernel/mca_32.c +++ b/arch/x86/kernel/mca_32.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/i386/kernel/mca.c | ||
3 | * Written by Martin Kolinek, February 1996 | 2 | * Written by Martin Kolinek, February 1996 |
4 | * | 3 | * |
5 | * Changes: | 4 | * Changes: |
diff --git a/arch/x86/kernel/mfgpt_32.c b/arch/x86/kernel/mfgpt_32.c new file mode 100644 index 000000000000..0ab680f2d9db --- /dev/null +++ b/arch/x86/kernel/mfgpt_32.c | |||
@@ -0,0 +1,362 @@ | |||
1 | /* | ||
2 | * Driver/API for AMD Geode Multi-Function General Purpose Timers (MFGPT) | ||
3 | * | ||
4 | * Copyright (C) 2006, Advanced Micro Devices, Inc. | ||
5 | * Copyright (C) 2007, Andres Salomon <dilinger@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of version 2 of the GNU General Public License | ||
9 | * as published by the Free Software Foundation. | ||
10 | * | ||
11 | * The MFGPTs are documented in AMD Geode CS5536 Companion Device Data Book. | ||
12 | */ | ||
13 | |||
14 | /* | ||
15 | * We are using the 32Khz input clock - its the only one that has the | ||
16 | * ranges we find desirable. The following table lists the suitable | ||
17 | * divisors and the associated hz, minimum interval | ||
18 | * and the maximum interval: | ||
19 | * | ||
20 | * Divisor Hz Min Delta (S) Max Delta (S) | ||
21 | * 1 32000 .0005 2.048 | ||
22 | * 2 16000 .001 4.096 | ||
23 | * 4 8000 .002 8.192 | ||
24 | * 8 4000 .004 16.384 | ||
25 | * 16 2000 .008 32.768 | ||
26 | * 32 1000 .016 65.536 | ||
27 | * 64 500 .032 131.072 | ||
28 | * 128 250 .064 262.144 | ||
29 | * 256 125 .128 524.288 | ||
30 | */ | ||
31 | |||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/interrupt.h> | ||
34 | #include <linux/module.h> | ||
35 | #include <asm/geode.h> | ||
36 | |||
37 | #define F_AVAIL 0x01 | ||
38 | |||
39 | static struct mfgpt_timer_t { | ||
40 | int flags; | ||
41 | struct module *owner; | ||
42 | } mfgpt_timers[MFGPT_MAX_TIMERS]; | ||
43 | |||
44 | /* Selected from the table above */ | ||
45 | |||
46 | #define MFGPT_DIVISOR 16 | ||
47 | #define MFGPT_SCALE 4 /* divisor = 2^(scale) */ | ||
48 | #define MFGPT_HZ (32000 / MFGPT_DIVISOR) | ||
49 | #define MFGPT_PERIODIC (MFGPT_HZ / HZ) | ||
50 | |||
51 | #ifdef CONFIG_GEODE_MFGPT_TIMER | ||
52 | static int __init mfgpt_timer_setup(void); | ||
53 | #else | ||
54 | #define mfgpt_timer_setup() (0) | ||
55 | #endif | ||
56 | |||
57 | /* Allow for disabling of MFGPTs */ | ||
58 | static int disable; | ||
59 | static int __init mfgpt_disable(char *s) | ||
60 | { | ||
61 | disable = 1; | ||
62 | return 1; | ||
63 | } | ||
64 | __setup("nomfgpt", mfgpt_disable); | ||
65 | |||
66 | /* | ||
67 | * Check whether any MFGPTs are available for the kernel to use. In most | ||
68 | * cases, firmware that uses AMD's VSA code will claim all timers during | ||
69 | * bootup; we certainly don't want to take them if they're already in use. | ||
70 | * In other cases (such as with VSAless OpenFirmware), the system firmware | ||
71 | * leaves timers available for us to use. | ||
72 | */ | ||
73 | int __init geode_mfgpt_detect(void) | ||
74 | { | ||
75 | int count = 0, i; | ||
76 | u16 val; | ||
77 | |||
78 | if (disable) { | ||
79 | printk(KERN_INFO "geode-mfgpt: Skipping MFGPT setup\n"); | ||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | for (i = 0; i < MFGPT_MAX_TIMERS; i++) { | ||
84 | val = geode_mfgpt_read(i, MFGPT_REG_SETUP); | ||
85 | if (!(val & MFGPT_SETUP_SETUP)) { | ||
86 | mfgpt_timers[i].flags = F_AVAIL; | ||
87 | count++; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | /* set up clock event device, if desired */ | ||
92 | i = mfgpt_timer_setup(); | ||
93 | |||
94 | return count; | ||
95 | } | ||
96 | |||
97 | int geode_mfgpt_toggle_event(int timer, int cmp, int event, int enable) | ||
98 | { | ||
99 | u32 msr, mask, value, dummy; | ||
100 | int shift = (cmp == MFGPT_CMP1) ? 0 : 8; | ||
101 | |||
102 | if (timer < 0 || timer >= MFGPT_MAX_TIMERS) | ||
103 | return -EIO; | ||
104 | |||
105 | /* | ||
106 | * The register maps for these are described in sections 6.17.1.x of | ||
107 | * the AMD Geode CS5536 Companion Device Data Book. | ||
108 | */ | ||
109 | switch (event) { | ||
110 | case MFGPT_EVENT_RESET: | ||
111 | /* | ||
112 | * XXX: According to the docs, we cannot reset timers above | ||
113 | * 6; that is, resets for 7 and 8 will be ignored. Is this | ||
114 | * a problem? -dilinger | ||
115 | */ | ||
116 | msr = MFGPT_NR_MSR; | ||
117 | mask = 1 << (timer + 24); | ||
118 | break; | ||
119 | |||
120 | case MFGPT_EVENT_NMI: | ||
121 | msr = MFGPT_NR_MSR; | ||
122 | mask = 1 << (timer + shift); | ||
123 | break; | ||
124 | |||
125 | case MFGPT_EVENT_IRQ: | ||
126 | msr = MFGPT_IRQ_MSR; | ||
127 | mask = 1 << (timer + shift); | ||
128 | break; | ||
129 | |||
130 | default: | ||
131 | return -EIO; | ||
132 | } | ||
133 | |||
134 | rdmsr(msr, value, dummy); | ||
135 | |||
136 | if (enable) | ||
137 | value |= mask; | ||
138 | else | ||
139 | value &= ~mask; | ||
140 | |||
141 | wrmsr(msr, value, dummy); | ||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | int geode_mfgpt_set_irq(int timer, int cmp, int irq, int enable) | ||
146 | { | ||
147 | u32 val, dummy; | ||
148 | int offset; | ||
149 | |||
150 | if (timer < 0 || timer >= MFGPT_MAX_TIMERS) | ||
151 | return -EIO; | ||
152 | |||
153 | if (geode_mfgpt_toggle_event(timer, cmp, MFGPT_EVENT_IRQ, enable)) | ||
154 | return -EIO; | ||
155 | |||
156 | rdmsr(MSR_PIC_ZSEL_LOW, val, dummy); | ||
157 | |||
158 | offset = (timer % 4) * 4; | ||
159 | |||
160 | val &= ~((0xF << offset) | (0xF << (offset + 16))); | ||
161 | |||
162 | if (enable) { | ||
163 | val |= (irq & 0x0F) << (offset); | ||
164 | val |= (irq & 0x0F) << (offset + 16); | ||
165 | } | ||
166 | |||
167 | wrmsr(MSR_PIC_ZSEL_LOW, val, dummy); | ||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | static int mfgpt_get(int timer, struct module *owner) | ||
172 | { | ||
173 | mfgpt_timers[timer].flags &= ~F_AVAIL; | ||
174 | mfgpt_timers[timer].owner = owner; | ||
175 | printk(KERN_INFO "geode-mfgpt: Registered timer %d\n", timer); | ||
176 | return timer; | ||
177 | } | ||
178 | |||
179 | int geode_mfgpt_alloc_timer(int timer, int domain, struct module *owner) | ||
180 | { | ||
181 | int i; | ||
182 | |||
183 | if (!geode_get_dev_base(GEODE_DEV_MFGPT)) | ||
184 | return -ENODEV; | ||
185 | if (timer >= MFGPT_MAX_TIMERS) | ||
186 | return -EIO; | ||
187 | |||
188 | if (timer < 0) { | ||
189 | /* Try to find an available timer */ | ||
190 | for (i = 0; i < MFGPT_MAX_TIMERS; i++) { | ||
191 | if (mfgpt_timers[i].flags & F_AVAIL) | ||
192 | return mfgpt_get(i, owner); | ||
193 | |||
194 | if (i == 5 && domain == MFGPT_DOMAIN_WORKING) | ||
195 | break; | ||
196 | } | ||
197 | } else { | ||
198 | /* If they requested a specific timer, try to honor that */ | ||
199 | if (mfgpt_timers[timer].flags & F_AVAIL) | ||
200 | return mfgpt_get(timer, owner); | ||
201 | } | ||
202 | |||
203 | /* No timers available - too bad */ | ||
204 | return -1; | ||
205 | } | ||
206 | |||
207 | |||
208 | #ifdef CONFIG_GEODE_MFGPT_TIMER | ||
209 | |||
210 | /* | ||
211 | * The MFPGT timers on the CS5536 provide us with suitable timers to use | ||
212 | * as clock event sources - not as good as a HPET or APIC, but certainly | ||
213 | * better then the PIT. This isn't a general purpose MFGPT driver, but | ||
214 | * a simplified one designed specifically to act as a clock event source. | ||
215 | * For full details about the MFGPT, please consult the CS5536 data sheet. | ||
216 | */ | ||
217 | |||
218 | #include <linux/clocksource.h> | ||
219 | #include <linux/clockchips.h> | ||
220 | |||
221 | static unsigned int mfgpt_tick_mode = CLOCK_EVT_MODE_SHUTDOWN; | ||
222 | static u16 mfgpt_event_clock; | ||
223 | |||
224 | static int irq = 7; | ||
225 | static int __init mfgpt_setup(char *str) | ||
226 | { | ||
227 | get_option(&str, &irq); | ||
228 | return 1; | ||
229 | } | ||
230 | __setup("mfgpt_irq=", mfgpt_setup); | ||
231 | |||
232 | static inline void mfgpt_disable_timer(u16 clock) | ||
233 | { | ||
234 | u16 val = geode_mfgpt_read(clock, MFGPT_REG_SETUP); | ||
235 | geode_mfgpt_write(clock, MFGPT_REG_SETUP, val & ~MFGPT_SETUP_CNTEN); | ||
236 | } | ||
237 | |||
238 | static int mfgpt_next_event(unsigned long, struct clock_event_device *); | ||
239 | static void mfgpt_set_mode(enum clock_event_mode, struct clock_event_device *); | ||
240 | |||
241 | static struct clock_event_device mfgpt_clockevent = { | ||
242 | .name = "mfgpt-timer", | ||
243 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | ||
244 | .set_mode = mfgpt_set_mode, | ||
245 | .set_next_event = mfgpt_next_event, | ||
246 | .rating = 250, | ||
247 | .cpumask = CPU_MASK_ALL, | ||
248 | .shift = 32 | ||
249 | }; | ||
250 | |||
251 | static inline void mfgpt_start_timer(u16 clock, u16 delta) | ||
252 | { | ||
253 | geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_CMP2, (u16) delta); | ||
254 | geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_COUNTER, 0); | ||
255 | |||
256 | geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_SETUP, | ||
257 | MFGPT_SETUP_CNTEN | MFGPT_SETUP_CMP2); | ||
258 | } | ||
259 | |||
260 | static void mfgpt_set_mode(enum clock_event_mode mode, | ||
261 | struct clock_event_device *evt) | ||
262 | { | ||
263 | mfgpt_disable_timer(mfgpt_event_clock); | ||
264 | |||
265 | if (mode == CLOCK_EVT_MODE_PERIODIC) | ||
266 | mfgpt_start_timer(mfgpt_event_clock, MFGPT_PERIODIC); | ||
267 | |||
268 | mfgpt_tick_mode = mode; | ||
269 | } | ||
270 | |||
271 | static int mfgpt_next_event(unsigned long delta, struct clock_event_device *evt) | ||
272 | { | ||
273 | mfgpt_start_timer(mfgpt_event_clock, delta); | ||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | /* Assume (foolishly?), that this interrupt was due to our tick */ | ||
278 | |||
279 | static irqreturn_t mfgpt_tick(int irq, void *dev_id) | ||
280 | { | ||
281 | if (mfgpt_tick_mode == CLOCK_EVT_MODE_SHUTDOWN) | ||
282 | return IRQ_HANDLED; | ||
283 | |||
284 | /* Turn off the clock */ | ||
285 | mfgpt_disable_timer(mfgpt_event_clock); | ||
286 | |||
287 | /* Clear the counter */ | ||
288 | geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_COUNTER, 0); | ||
289 | |||
290 | /* Restart the clock in periodic mode */ | ||
291 | |||
292 | if (mfgpt_tick_mode == CLOCK_EVT_MODE_PERIODIC) { | ||
293 | geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_SETUP, | ||
294 | MFGPT_SETUP_CNTEN | MFGPT_SETUP_CMP2); | ||
295 | } | ||
296 | |||
297 | mfgpt_clockevent.event_handler(&mfgpt_clockevent); | ||
298 | return IRQ_HANDLED; | ||
299 | } | ||
300 | |||
301 | static struct irqaction mfgptirq = { | ||
302 | .handler = mfgpt_tick, | ||
303 | .flags = IRQF_DISABLED | IRQF_NOBALANCING, | ||
304 | .mask = CPU_MASK_NONE, | ||
305 | .name = "mfgpt-timer" | ||
306 | }; | ||
307 | |||
308 | static int __init mfgpt_timer_setup(void) | ||
309 | { | ||
310 | int timer, ret; | ||
311 | u16 val; | ||
312 | |||
313 | timer = geode_mfgpt_alloc_timer(MFGPT_TIMER_ANY, MFGPT_DOMAIN_WORKING, | ||
314 | THIS_MODULE); | ||
315 | if (timer < 0) { | ||
316 | printk(KERN_ERR | ||
317 | "mfgpt-timer: Could not allocate a MFPGT timer\n"); | ||
318 | return -ENODEV; | ||
319 | } | ||
320 | |||
321 | mfgpt_event_clock = timer; | ||
322 | /* Set the clock scale and enable the event mode for CMP2 */ | ||
323 | val = MFGPT_SCALE | (3 << 8); | ||
324 | |||
325 | geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_SETUP, val); | ||
326 | |||
327 | /* Set up the IRQ on the MFGPT side */ | ||
328 | if (geode_mfgpt_setup_irq(mfgpt_event_clock, MFGPT_CMP2, irq)) { | ||
329 | printk(KERN_ERR "mfgpt-timer: Could not set up IRQ %d\n", irq); | ||
330 | return -EIO; | ||
331 | } | ||
332 | |||
333 | /* And register it with the kernel */ | ||
334 | ret = setup_irq(irq, &mfgptirq); | ||
335 | |||
336 | if (ret) { | ||
337 | printk(KERN_ERR | ||
338 | "mfgpt-timer: Unable to set up the interrupt.\n"); | ||
339 | goto err; | ||
340 | } | ||
341 | |||
342 | /* Set up the clock event */ | ||
343 | mfgpt_clockevent.mult = div_sc(MFGPT_HZ, NSEC_PER_SEC, 32); | ||
344 | mfgpt_clockevent.min_delta_ns = clockevent_delta2ns(0xF, | ||
345 | &mfgpt_clockevent); | ||
346 | mfgpt_clockevent.max_delta_ns = clockevent_delta2ns(0xFFFE, | ||
347 | &mfgpt_clockevent); | ||
348 | |||
349 | printk(KERN_INFO | ||
350 | "mfgpt-timer: registering the MFGT timer as a clock event.\n"); | ||
351 | clockevents_register_device(&mfgpt_clockevent); | ||
352 | |||
353 | return 0; | ||
354 | |||
355 | err: | ||
356 | geode_mfgpt_release_irq(mfgpt_event_clock, MFGPT_CMP2, irq); | ||
357 | printk(KERN_ERR | ||
358 | "mfgpt-timer: Unable to set up the MFGPT clock source\n"); | ||
359 | return -EIO; | ||
360 | } | ||
361 | |||
362 | #endif | ||
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c index 0c1069b8d638..c044de310b69 100644 --- a/arch/x86/kernel/msr.c +++ b/arch/x86/kernel/msr.c | |||
@@ -11,8 +11,6 @@ | |||
11 | * ----------------------------------------------------------------------- */ | 11 | * ----------------------------------------------------------------------- */ |
12 | 12 | ||
13 | /* | 13 | /* |
14 | * msr.c | ||
15 | * | ||
16 | * x86 MSR access device | 14 | * x86 MSR access device |
17 | * | 15 | * |
18 | * This device is accessed by lseek() to the appropriate register number | 16 | * This device is accessed by lseek() to the appropriate register number |
diff --git a/arch/x86/kernel/nmi_32.c b/arch/x86/kernel/nmi_32.c index c7227e2180f8..f803ed0ed1c4 100644 --- a/arch/x86/kernel/nmi_32.c +++ b/arch/x86/kernel/nmi_32.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/i386/nmi.c | ||
3 | * | ||
4 | * NMI watchdog support on APIC systems | 2 | * NMI watchdog support on APIC systems |
5 | * | 3 | * |
6 | * Started by Ingo Molnar <mingo@redhat.com> | 4 | * Started by Ingo Molnar <mingo@redhat.com> |
@@ -353,7 +351,8 @@ __kprobes int nmi_watchdog_tick(struct pt_regs * regs, unsigned reason) | |||
353 | * Take the local apic timer and PIT/HPET into account. We don't | 351 | * Take the local apic timer and PIT/HPET into account. We don't |
354 | * know which one is active, when we have highres/dyntick on | 352 | * know which one is active, when we have highres/dyntick on |
355 | */ | 353 | */ |
356 | sum = per_cpu(irq_stat, cpu).apic_timer_irqs + kstat_cpu(cpu).irqs[0]; | 354 | sum = per_cpu(irq_stat, cpu).apic_timer_irqs + |
355 | per_cpu(irq_stat, cpu).irq0_irqs; | ||
357 | 356 | ||
358 | /* if the none of the timers isn't firing, this cpu isn't doing much */ | 357 | /* if the none of the timers isn't firing, this cpu isn't doing much */ |
359 | if (!touched && last_irq_sums[cpu] == sum) { | 358 | if (!touched && last_irq_sums[cpu] == sum) { |
diff --git a/arch/x86/kernel/nmi_64.c b/arch/x86/kernel/nmi_64.c index 0ec6d2ddb931..a576fd740062 100644 --- a/arch/x86/kernel/nmi_64.c +++ b/arch/x86/kernel/nmi_64.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/x86_64/nmi.c | ||
3 | * | ||
4 | * NMI watchdog support on APIC systems | 2 | * NMI watchdog support on APIC systems |
5 | * | 3 | * |
6 | * Started by Ingo Molnar <mingo@redhat.com> | 4 | * Started by Ingo Molnar <mingo@redhat.com> |
@@ -329,7 +327,7 @@ int __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason) | |||
329 | touched = 1; | 327 | touched = 1; |
330 | } | 328 | } |
331 | 329 | ||
332 | sum = read_pda(apic_timer_irqs); | 330 | sum = read_pda(apic_timer_irqs) + read_pda(irq0_irqs); |
333 | if (__get_cpu_var(nmi_touch)) { | 331 | if (__get_cpu_var(nmi_touch)) { |
334 | __get_cpu_var(nmi_touch) = 0; | 332 | __get_cpu_var(nmi_touch) = 0; |
335 | touched = 1; | 333 | touched = 1; |
diff --git a/arch/x86/kernel/pci-dma_32.c b/arch/x86/kernel/pci-dma_32.c index 048f09b62553..0aae2f3847a5 100644 --- a/arch/x86/kernel/pci-dma_32.c +++ b/arch/x86/kernel/pci-dma_32.c | |||
@@ -63,7 +63,8 @@ void dma_free_coherent(struct device *dev, size_t size, | |||
63 | { | 63 | { |
64 | struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL; | 64 | struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL; |
65 | int order = get_order(size); | 65 | int order = get_order(size); |
66 | 66 | ||
67 | WARN_ON(irqs_disabled()); /* for portability */ | ||
67 | if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) { | 68 | if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) { |
68 | int page = (vaddr - mem->virt_base) >> PAGE_SHIFT; | 69 | int page = (vaddr - mem->virt_base) >> PAGE_SHIFT; |
69 | 70 | ||
diff --git a/arch/x86/kernel/pci-dma_64.c b/arch/x86/kernel/pci-dma_64.c index 29711445c818..9576a2eb375e 100644 --- a/arch/x86/kernel/pci-dma_64.c +++ b/arch/x86/kernel/pci-dma_64.c | |||
@@ -167,6 +167,7 @@ EXPORT_SYMBOL(dma_alloc_coherent); | |||
167 | void dma_free_coherent(struct device *dev, size_t size, | 167 | void dma_free_coherent(struct device *dev, size_t size, |
168 | void *vaddr, dma_addr_t bus) | 168 | void *vaddr, dma_addr_t bus) |
169 | { | 169 | { |
170 | WARN_ON(irqs_disabled()); /* for portability */ | ||
170 | if (dma_ops->unmap_single) | 171 | if (dma_ops->unmap_single) |
171 | dma_ops->unmap_single(dev, bus, size, 0); | 172 | dma_ops->unmap_single(dev, bus, size, 0); |
172 | free_pages((unsigned long)vaddr, get_order(size)); | 173 | free_pages((unsigned long)vaddr, get_order(size)); |
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 84664710b784..097aeafce5ff 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/i386/kernel/process.c | ||
3 | * | ||
4 | * Copyright (C) 1995 Linus Torvalds | 2 | * Copyright (C) 1995 Linus Torvalds |
5 | * | 3 | * |
6 | * Pentium III FXSR, SSE support | 4 | * Pentium III FXSR, SSE support |
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 98956555450b..7352d4b377e6 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/x86-64/kernel/process.c | ||
3 | * | ||
4 | * Copyright (C) 1995 Linus Torvalds | 2 | * Copyright (C) 1995 Linus Torvalds |
5 | * | 3 | * |
6 | * Pentium III FXSR, SSE support | 4 | * Pentium III FXSR, SSE support |
@@ -38,6 +36,7 @@ | |||
38 | #include <linux/notifier.h> | 36 | #include <linux/notifier.h> |
39 | #include <linux/kprobes.h> | 37 | #include <linux/kprobes.h> |
40 | #include <linux/kdebug.h> | 38 | #include <linux/kdebug.h> |
39 | #include <linux/tick.h> | ||
41 | 40 | ||
42 | #include <asm/uaccess.h> | 41 | #include <asm/uaccess.h> |
43 | #include <asm/pgtable.h> | 42 | #include <asm/pgtable.h> |
@@ -208,6 +207,8 @@ void cpu_idle (void) | |||
208 | if (__get_cpu_var(cpu_idle_state)) | 207 | if (__get_cpu_var(cpu_idle_state)) |
209 | __get_cpu_var(cpu_idle_state) = 0; | 208 | __get_cpu_var(cpu_idle_state) = 0; |
210 | 209 | ||
210 | tick_nohz_stop_sched_tick(); | ||
211 | |||
211 | rmb(); | 212 | rmb(); |
212 | idle = pm_idle; | 213 | idle = pm_idle; |
213 | if (!idle) | 214 | if (!idle) |
@@ -228,6 +229,7 @@ void cpu_idle (void) | |||
228 | __exit_idle(); | 229 | __exit_idle(); |
229 | } | 230 | } |
230 | 231 | ||
232 | tick_nohz_restart_sched_tick(); | ||
231 | preempt_enable_no_resched(); | 233 | preempt_enable_no_resched(); |
232 | schedule(); | 234 | schedule(); |
233 | preempt_disable(); | 235 | preempt_disable(); |
diff --git a/arch/x86/kernel/ptrace_32.c b/arch/x86/kernel/ptrace_32.c index 7c1b92522e95..0cecd7513c97 100644 --- a/arch/x86/kernel/ptrace_32.c +++ b/arch/x86/kernel/ptrace_32.c | |||
@@ -1,4 +1,3 @@ | |||
1 | /* ptrace.c */ | ||
2 | /* By Ross Biro 1/23/92 */ | 1 | /* By Ross Biro 1/23/92 */ |
3 | /* | 2 | /* |
4 | * Pentium III FXSR, SSE support | 3 | * Pentium III FXSR, SSE support |
diff --git a/arch/x86/kernel/ptrace_64.c b/arch/x86/kernel/ptrace_64.c index eea3702427b4..c0cac42df3b6 100644 --- a/arch/x86/kernel/ptrace_64.c +++ b/arch/x86/kernel/ptrace_64.c | |||
@@ -1,4 +1,3 @@ | |||
1 | /* ptrace.c */ | ||
2 | /* By Ross Biro 1/23/92 */ | 1 | /* By Ross Biro 1/23/92 */ |
3 | /* | 2 | /* |
4 | * Pentium III FXSR, SSE support | 3 | * Pentium III FXSR, SSE support |
diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index 6722469c2633..d769e204f942 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c | |||
@@ -4,6 +4,8 @@ | |||
4 | #include <linux/pci.h> | 4 | #include <linux/pci.h> |
5 | #include <linux/irq.h> | 5 | #include <linux/irq.h> |
6 | 6 | ||
7 | #include <asm/hpet.h> | ||
8 | |||
7 | #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP) && defined(CONFIG_PCI) | 9 | #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP) && defined(CONFIG_PCI) |
8 | 10 | ||
9 | static void __devinit quirk_intel_irqbalance(struct pci_dev *dev) | 11 | static void __devinit quirk_intel_irqbalance(struct pci_dev *dev) |
@@ -47,3 +49,206 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quir | |||
47 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_intel_irqbalance); | 49 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_intel_irqbalance); |
48 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, quirk_intel_irqbalance); | 50 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, quirk_intel_irqbalance); |
49 | #endif | 51 | #endif |
52 | |||
53 | #if defined(CONFIG_HPET_TIMER) | ||
54 | unsigned long force_hpet_address; | ||
55 | |||
56 | static enum { | ||
57 | NONE_FORCE_HPET_RESUME, | ||
58 | OLD_ICH_FORCE_HPET_RESUME, | ||
59 | ICH_FORCE_HPET_RESUME | ||
60 | } force_hpet_resume_type; | ||
61 | |||
62 | static void __iomem *rcba_base; | ||
63 | |||
64 | static void ich_force_hpet_resume(void) | ||
65 | { | ||
66 | u32 val; | ||
67 | |||
68 | if (!force_hpet_address) | ||
69 | return; | ||
70 | |||
71 | if (rcba_base == NULL) | ||
72 | BUG(); | ||
73 | |||
74 | /* read the Function Disable register, dword mode only */ | ||
75 | val = readl(rcba_base + 0x3404); | ||
76 | if (!(val & 0x80)) { | ||
77 | /* HPET disabled in HPTC. Trying to enable */ | ||
78 | writel(val | 0x80, rcba_base + 0x3404); | ||
79 | } | ||
80 | |||
81 | val = readl(rcba_base + 0x3404); | ||
82 | if (!(val & 0x80)) | ||
83 | BUG(); | ||
84 | else | ||
85 | printk(KERN_DEBUG "Force enabled HPET at resume\n"); | ||
86 | |||
87 | return; | ||
88 | } | ||
89 | |||
90 | static void ich_force_enable_hpet(struct pci_dev *dev) | ||
91 | { | ||
92 | u32 val; | ||
93 | u32 uninitialized_var(rcba); | ||
94 | int err = 0; | ||
95 | |||
96 | if (hpet_address || force_hpet_address) | ||
97 | return; | ||
98 | |||
99 | pci_read_config_dword(dev, 0xF0, &rcba); | ||
100 | rcba &= 0xFFFFC000; | ||
101 | if (rcba == 0) { | ||
102 | printk(KERN_DEBUG "RCBA disabled. Cannot force enable HPET\n"); | ||
103 | return; | ||
104 | } | ||
105 | |||
106 | /* use bits 31:14, 16 kB aligned */ | ||
107 | rcba_base = ioremap_nocache(rcba, 0x4000); | ||
108 | if (rcba_base == NULL) { | ||
109 | printk(KERN_DEBUG "ioremap failed. Cannot force enable HPET\n"); | ||
110 | return; | ||
111 | } | ||
112 | |||
113 | /* read the Function Disable register, dword mode only */ | ||
114 | val = readl(rcba_base + 0x3404); | ||
115 | |||
116 | if (val & 0x80) { | ||
117 | /* HPET is enabled in HPTC. Just not reported by BIOS */ | ||
118 | val = val & 0x3; | ||
119 | force_hpet_address = 0xFED00000 | (val << 12); | ||
120 | printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n", | ||
121 | force_hpet_address); | ||
122 | iounmap(rcba_base); | ||
123 | return; | ||
124 | } | ||
125 | |||
126 | /* HPET disabled in HPTC. Trying to enable */ | ||
127 | writel(val | 0x80, rcba_base + 0x3404); | ||
128 | |||
129 | val = readl(rcba_base + 0x3404); | ||
130 | if (!(val & 0x80)) { | ||
131 | err = 1; | ||
132 | } else { | ||
133 | val = val & 0x3; | ||
134 | force_hpet_address = 0xFED00000 | (val << 12); | ||
135 | } | ||
136 | |||
137 | if (err) { | ||
138 | force_hpet_address = 0; | ||
139 | iounmap(rcba_base); | ||
140 | printk(KERN_DEBUG "Failed to force enable HPET\n"); | ||
141 | } else { | ||
142 | force_hpet_resume_type = ICH_FORCE_HPET_RESUME; | ||
143 | printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n", | ||
144 | force_hpet_address); | ||
145 | } | ||
146 | } | ||
147 | |||
148 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0, | ||
149 | ich_force_enable_hpet); | ||
150 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, | ||
151 | ich_force_enable_hpet); | ||
152 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, | ||
153 | ich_force_enable_hpet); | ||
154 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, | ||
155 | ich_force_enable_hpet); | ||
156 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, | ||
157 | ich_force_enable_hpet); | ||
158 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_1, | ||
159 | ich_force_enable_hpet); | ||
160 | |||
161 | |||
162 | static struct pci_dev *cached_dev; | ||
163 | |||
164 | static void old_ich_force_hpet_resume(void) | ||
165 | { | ||
166 | u32 val; | ||
167 | u32 uninitialized_var(gen_cntl); | ||
168 | |||
169 | if (!force_hpet_address || !cached_dev) | ||
170 | return; | ||
171 | |||
172 | pci_read_config_dword(cached_dev, 0xD0, &gen_cntl); | ||
173 | gen_cntl &= (~(0x7 << 15)); | ||
174 | gen_cntl |= (0x4 << 15); | ||
175 | |||
176 | pci_write_config_dword(cached_dev, 0xD0, gen_cntl); | ||
177 | pci_read_config_dword(cached_dev, 0xD0, &gen_cntl); | ||
178 | val = gen_cntl >> 15; | ||
179 | val &= 0x7; | ||
180 | if (val == 0x4) | ||
181 | printk(KERN_DEBUG "Force enabled HPET at resume\n"); | ||
182 | else | ||
183 | BUG(); | ||
184 | } | ||
185 | |||
186 | static void old_ich_force_enable_hpet(struct pci_dev *dev) | ||
187 | { | ||
188 | u32 val; | ||
189 | u32 uninitialized_var(gen_cntl); | ||
190 | |||
191 | if (hpet_address || force_hpet_address) | ||
192 | return; | ||
193 | |||
194 | pci_read_config_dword(dev, 0xD0, &gen_cntl); | ||
195 | /* | ||
196 | * Bit 17 is HPET enable bit. | ||
197 | * Bit 16:15 control the HPET base address. | ||
198 | */ | ||
199 | val = gen_cntl >> 15; | ||
200 | val &= 0x7; | ||
201 | if (val & 0x4) { | ||
202 | val &= 0x3; | ||
203 | force_hpet_address = 0xFED00000 | (val << 12); | ||
204 | printk(KERN_DEBUG "HPET at base address 0x%lx\n", | ||
205 | force_hpet_address); | ||
206 | return; | ||
207 | } | ||
208 | |||
209 | /* | ||
210 | * HPET is disabled. Trying enabling at FED00000 and check | ||
211 | * whether it sticks | ||
212 | */ | ||
213 | gen_cntl &= (~(0x7 << 15)); | ||
214 | gen_cntl |= (0x4 << 15); | ||
215 | pci_write_config_dword(dev, 0xD0, gen_cntl); | ||
216 | |||
217 | pci_read_config_dword(dev, 0xD0, &gen_cntl); | ||
218 | |||
219 | val = gen_cntl >> 15; | ||
220 | val &= 0x7; | ||
221 | if (val & 0x4) { | ||
222 | /* HPET is enabled in HPTC. Just not reported by BIOS */ | ||
223 | val &= 0x3; | ||
224 | force_hpet_address = 0xFED00000 | (val << 12); | ||
225 | printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n", | ||
226 | force_hpet_address); | ||
227 | cached_dev = dev; | ||
228 | force_hpet_resume_type = OLD_ICH_FORCE_HPET_RESUME; | ||
229 | return; | ||
230 | } | ||
231 | |||
232 | printk(KERN_DEBUG "Failed to force enable HPET\n"); | ||
233 | } | ||
234 | |||
235 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, | ||
236 | old_ich_force_enable_hpet); | ||
237 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_12, | ||
238 | old_ich_force_enable_hpet); | ||
239 | |||
240 | void force_hpet_resume(void) | ||
241 | { | ||
242 | switch (force_hpet_resume_type) { | ||
243 | case ICH_FORCE_HPET_RESUME: | ||
244 | return ich_force_hpet_resume(); | ||
245 | |||
246 | case OLD_ICH_FORCE_HPET_RESUME: | ||
247 | return old_ich_force_hpet_resume(); | ||
248 | |||
249 | default: | ||
250 | break; | ||
251 | } | ||
252 | } | ||
253 | |||
254 | #endif | ||
diff --git a/arch/x86/kernel/reboot_32.c b/arch/x86/kernel/reboot_32.c index b37ed226830a..9e2269d00918 100644 --- a/arch/x86/kernel/reboot_32.c +++ b/arch/x86/kernel/reboot_32.c | |||
@@ -1,7 +1,3 @@ | |||
1 | /* | ||
2 | * linux/arch/i386/kernel/reboot.c | ||
3 | */ | ||
4 | |||
5 | #include <linux/mm.h> | 1 | #include <linux/mm.h> |
6 | #include <linux/module.h> | 2 | #include <linux/module.h> |
7 | #include <linux/delay.h> | 3 | #include <linux/delay.h> |
diff --git a/arch/x86/kernel/reboot_fixups_32.c b/arch/x86/kernel/reboot_fixups_32.c index 03e1cce58f49..8b30b26ad069 100644 --- a/arch/x86/kernel/reboot_fixups_32.c +++ b/arch/x86/kernel/reboot_fixups_32.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/i386/kernel/reboot_fixups.c | ||
3 | * | ||
4 | * This is a good place to put board specific reboot fixups. | 2 | * This is a good place to put board specific reboot fixups. |
5 | * | 3 | * |
6 | * List of supported fixups: | 4 | * List of supported fixups: |
@@ -11,6 +9,7 @@ | |||
11 | 9 | ||
12 | #include <asm/delay.h> | 10 | #include <asm/delay.h> |
13 | #include <linux/pci.h> | 11 | #include <linux/pci.h> |
12 | #include <linux/interrupt.h> | ||
14 | #include <asm/reboot_fixups.h> | 13 | #include <asm/reboot_fixups.h> |
15 | #include <asm/msr.h> | 14 | #include <asm/msr.h> |
16 | 15 | ||
@@ -56,6 +55,11 @@ void mach_reboot_fixups(void) | |||
56 | struct pci_dev *dev; | 55 | struct pci_dev *dev; |
57 | int i; | 56 | int i; |
58 | 57 | ||
58 | /* we can be called from sysrq-B code. In such a case it is | ||
59 | * prohibited to dig PCI */ | ||
60 | if (in_interrupt()) | ||
61 | return; | ||
62 | |||
59 | for (i=0; i < ARRAY_SIZE(fixups_table); i++) { | 63 | for (i=0; i < ARRAY_SIZE(fixups_table); i++) { |
60 | cur = &(fixups_table[i]); | 64 | cur = &(fixups_table[i]); |
61 | dev = pci_get_device(cur->vendor, cur->device, NULL); | 65 | dev = pci_get_device(cur->vendor, cur->device, NULL); |
diff --git a/arch/x86/kernel/scx200_32.c b/arch/x86/kernel/scx200_32.c index c7d3df23f589..87bc159d29df 100644 --- a/arch/x86/kernel/scx200_32.c +++ b/arch/x86/kernel/scx200_32.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* linux/arch/i386/kernel/scx200.c | 1 | /* |
2 | 2 | * Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com> | |
3 | Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com> | 3 | * |
4 | 4 | * National Semiconductor SCx200 support. | |
5 | National Semiconductor SCx200 support. */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/module.h> | 7 | #include <linux/module.h> |
8 | #include <linux/errno.h> | 8 | #include <linux/errno.h> |
@@ -24,7 +24,7 @@ MODULE_DESCRIPTION("NatSemi SCx200 Driver"); | |||
24 | MODULE_LICENSE("GPL"); | 24 | MODULE_LICENSE("GPL"); |
25 | 25 | ||
26 | unsigned scx200_gpio_base = 0; | 26 | unsigned scx200_gpio_base = 0; |
27 | long scx200_gpio_shadow[2]; | 27 | unsigned long scx200_gpio_shadow[2]; |
28 | 28 | ||
29 | unsigned scx200_cb_base = 0; | 29 | unsigned scx200_cb_base = 0; |
30 | 30 | ||
diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c index d474cd639bcb..c8e1bc38d421 100644 --- a/arch/x86/kernel/setup_32.c +++ b/arch/x86/kernel/setup_32.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/i386/kernel/setup.c | ||
3 | * | ||
4 | * Copyright (C) 1995 Linus Torvalds | 2 | * Copyright (C) 1995 Linus Torvalds |
5 | * | 3 | * |
6 | * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999 | 4 | * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999 |
diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c index af838f6b0b7f..b7da90e79c78 100644 --- a/arch/x86/kernel/setup_64.c +++ b/arch/x86/kernel/setup_64.c | |||
@@ -1,10 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/x86-64/kernel/setup.c | ||
3 | * | ||
4 | * Copyright (C) 1995 Linus Torvalds | 2 | * Copyright (C) 1995 Linus Torvalds |
5 | * | ||
6 | * Nov 2001 Dave Jones <davej@suse.de> | ||
7 | * Forked from i386 setup code. | ||
8 | */ | 3 | */ |
9 | 4 | ||
10 | /* | 5 | /* |
@@ -546,6 +541,37 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c) | |||
546 | #endif | 541 | #endif |
547 | } | 542 | } |
548 | 543 | ||
544 | #define ENABLE_C1E_MASK 0x18000000 | ||
545 | #define CPUID_PROCESSOR_SIGNATURE 1 | ||
546 | #define CPUID_XFAM 0x0ff00000 | ||
547 | #define CPUID_XFAM_K8 0x00000000 | ||
548 | #define CPUID_XFAM_10H 0x00100000 | ||
549 | #define CPUID_XFAM_11H 0x00200000 | ||
550 | #define CPUID_XMOD 0x000f0000 | ||
551 | #define CPUID_XMOD_REV_F 0x00040000 | ||
552 | |||
553 | /* AMD systems with C1E don't have a working lAPIC timer. Check for that. */ | ||
554 | static __cpuinit int amd_apic_timer_broken(void) | ||
555 | { | ||
556 | u32 lo, hi; | ||
557 | u32 eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE); | ||
558 | switch (eax & CPUID_XFAM) { | ||
559 | case CPUID_XFAM_K8: | ||
560 | if ((eax & CPUID_XMOD) < CPUID_XMOD_REV_F) | ||
561 | break; | ||
562 | case CPUID_XFAM_10H: | ||
563 | case CPUID_XFAM_11H: | ||
564 | rdmsr(MSR_K8_ENABLE_C1E, lo, hi); | ||
565 | if (lo & ENABLE_C1E_MASK) | ||
566 | return 1; | ||
567 | break; | ||
568 | default: | ||
569 | /* err on the side of caution */ | ||
570 | return 1; | ||
571 | } | ||
572 | return 0; | ||
573 | } | ||
574 | |||
549 | static void __cpuinit init_amd(struct cpuinfo_x86 *c) | 575 | static void __cpuinit init_amd(struct cpuinfo_x86 *c) |
550 | { | 576 | { |
551 | unsigned level; | 577 | unsigned level; |
@@ -617,6 +643,9 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) | |||
617 | /* Family 10 doesn't support C states in MWAIT so don't use it */ | 643 | /* Family 10 doesn't support C states in MWAIT so don't use it */ |
618 | if (c->x86 == 0x10 && !force_mwait) | 644 | if (c->x86 == 0x10 && !force_mwait) |
619 | clear_bit(X86_FEATURE_MWAIT, &c->x86_capability); | 645 | clear_bit(X86_FEATURE_MWAIT, &c->x86_capability); |
646 | |||
647 | if (amd_apic_timer_broken()) | ||
648 | disable_apic_timer = 1; | ||
620 | } | 649 | } |
621 | 650 | ||
622 | static void __cpuinit detect_ht(struct cpuinfo_x86 *c) | 651 | static void __cpuinit detect_ht(struct cpuinfo_x86 *c) |
diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c index c03570f7fe8e..d01d51fcce2a 100644 --- a/arch/x86/kernel/signal_32.c +++ b/arch/x86/kernel/signal_32.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/i386/kernel/signal.c | ||
3 | * | ||
4 | * Copyright (C) 1991, 1992 Linus Torvalds | 2 | * Copyright (C) 1991, 1992 Linus Torvalds |
5 | * | 3 | * |
6 | * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson | 4 | * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson |
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 739175b01e06..683802bec419 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/x86_64/kernel/signal.c | ||
3 | * | ||
4 | * Copyright (C) 1991, 1992 Linus Torvalds | 2 | * Copyright (C) 1991, 1992 Linus Torvalds |
5 | * Copyright (C) 2000, 2001, 2002 Andi Kleen SuSE Labs | 3 | * Copyright (C) 2000, 2001, 2002 Andi Kleen SuSE Labs |
6 | * | 4 | * |
diff --git a/arch/x86/kernel/smpboot_64.c b/arch/x86/kernel/smpboot_64.c index 32f50783edc8..720a7d1f8862 100644 --- a/arch/x86/kernel/smpboot_64.c +++ b/arch/x86/kernel/smpboot_64.c | |||
@@ -223,8 +223,6 @@ void __cpuinit smp_callin(void) | |||
223 | local_irq_disable(); | 223 | local_irq_disable(); |
224 | Dprintk("Stack at about %p\n",&cpuid); | 224 | Dprintk("Stack at about %p\n",&cpuid); |
225 | 225 | ||
226 | disable_APIC_timer(); | ||
227 | |||
228 | /* | 226 | /* |
229 | * Save our processor parameters | 227 | * Save our processor parameters |
230 | */ | 228 | */ |
@@ -337,19 +335,12 @@ void __cpuinit start_secondary(void) | |||
337 | */ | 335 | */ |
338 | check_tsc_sync_target(); | 336 | check_tsc_sync_target(); |
339 | 337 | ||
340 | Dprintk("cpu %d: setting up apic clock\n", smp_processor_id()); | ||
341 | setup_secondary_APIC_clock(); | ||
342 | |||
343 | Dprintk("cpu %d: enabling apic timer\n", smp_processor_id()); | ||
344 | |||
345 | if (nmi_watchdog == NMI_IO_APIC) { | 338 | if (nmi_watchdog == NMI_IO_APIC) { |
346 | disable_8259A_irq(0); | 339 | disable_8259A_irq(0); |
347 | enable_NMI_through_LVT0(NULL); | 340 | enable_NMI_through_LVT0(NULL); |
348 | enable_8259A_irq(0); | 341 | enable_8259A_irq(0); |
349 | } | 342 | } |
350 | 343 | ||
351 | enable_APIC_timer(); | ||
352 | |||
353 | /* | 344 | /* |
354 | * The sibling maps must be set before turing the online map on for | 345 | * The sibling maps must be set before turing the online map on for |
355 | * this cpu | 346 | * this cpu |
@@ -378,6 +369,8 @@ void __cpuinit start_secondary(void) | |||
378 | 369 | ||
379 | unlock_ipi_call_lock(); | 370 | unlock_ipi_call_lock(); |
380 | 371 | ||
372 | setup_secondary_APIC_clock(); | ||
373 | |||
381 | cpu_idle(); | 374 | cpu_idle(); |
382 | } | 375 | } |
383 | 376 | ||
diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c index cb9109113584..413e527cdeb9 100644 --- a/arch/x86/kernel/stacktrace.c +++ b/arch/x86/kernel/stacktrace.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/x86_64/kernel/stacktrace.c | ||
3 | * | ||
4 | * Stack trace management functions | 2 | * Stack trace management functions |
5 | * | 3 | * |
6 | * Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> | 4 | * Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> |
diff --git a/arch/x86/kernel/summit_32.c b/arch/x86/kernel/summit_32.c index d0e01a3acf35..91c7acc8d999 100644 --- a/arch/x86/kernel/summit_32.c +++ b/arch/x86/kernel/summit_32.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * arch/i386/kernel/summit.c - IBM Summit-Specific Code | 2 | * IBM Summit-Specific Code |
3 | * | 3 | * |
4 | * Written By: Matthew Dobson, IBM Corporation | 4 | * Written By: Matthew Dobson, IBM Corporation |
5 | * | 5 | * |
diff --git a/arch/x86/kernel/sys_i386_32.c b/arch/x86/kernel/sys_i386_32.c index 42147304de88..f8bae9ba0324 100644 --- a/arch/x86/kernel/sys_i386_32.c +++ b/arch/x86/kernel/sys_i386_32.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/i386/kernel/sys_i386.c | ||
3 | * | ||
4 | * This file contains various random system calls that | 2 | * This file contains various random system calls that |
5 | * have a non-standard calling sequence on the Linux/i386 | 3 | * have a non-standard calling sequence on the Linux/i386 |
6 | * platform. | 4 | * platform. |
diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c index 4770b7a2052c..907942ee6e76 100644 --- a/arch/x86/kernel/sys_x86_64.c +++ b/arch/x86/kernel/sys_x86_64.c | |||
@@ -1,7 +1,3 @@ | |||
1 | /* | ||
2 | * linux/arch/x86_64/kernel/sys_x86_64.c | ||
3 | */ | ||
4 | |||
5 | #include <linux/errno.h> | 1 | #include <linux/errno.h> |
6 | #include <linux/sched.h> | 2 | #include <linux/sched.h> |
7 | #include <linux/syscalls.h> | 3 | #include <linux/syscalls.h> |
diff --git a/arch/x86/kernel/sysenter_32.c b/arch/x86/kernel/sysenter_32.c index 4eb2e408764f..5a2d951e2608 100644 --- a/arch/x86/kernel/sysenter_32.c +++ b/arch/x86/kernel/sysenter_32.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/i386/kernel/sysenter.c | ||
3 | * | ||
4 | * (C) Copyright 2002 Linus Torvalds | 2 | * (C) Copyright 2002 Linus Torvalds |
5 | * Portions based on the vdso-randomization code from exec-shield: | 3 | * Portions based on the vdso-randomization code from exec-shield: |
6 | * Copyright(C) 2005-2006, Red Hat, Inc., Ingo Molnar | 4 | * Copyright(C) 2005-2006, Red Hat, Inc., Ingo Molnar |
diff --git a/arch/x86/kernel/time_32.c b/arch/x86/kernel/time_32.c index 19a6c678d02e..8a322c96bc23 100644 --- a/arch/x86/kernel/time_32.c +++ b/arch/x86/kernel/time_32.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/i386/kernel/time.c | ||
3 | * | ||
4 | * Copyright (C) 1991, 1992, 1995 Linus Torvalds | 2 | * Copyright (C) 1991, 1992, 1995 Linus Torvalds |
5 | * | 3 | * |
6 | * This file contains the PC-specific time handling details: | 4 | * This file contains the PC-specific time handling details: |
@@ -157,6 +155,9 @@ EXPORT_SYMBOL(profile_pc); | |||
157 | */ | 155 | */ |
158 | irqreturn_t timer_interrupt(int irq, void *dev_id) | 156 | irqreturn_t timer_interrupt(int irq, void *dev_id) |
159 | { | 157 | { |
158 | /* Keep nmi watchdog up to date */ | ||
159 | per_cpu(irq_stat, smp_processor_id()).irq0_irqs++; | ||
160 | |||
160 | #ifdef CONFIG_X86_IO_APIC | 161 | #ifdef CONFIG_X86_IO_APIC |
161 | if (timer_ack) { | 162 | if (timer_ack) { |
162 | /* | 163 | /* |
diff --git a/arch/x86/kernel/time_64.c b/arch/x86/kernel/time_64.c index 6d48a4e826d9..c821edc32216 100644 --- a/arch/x86/kernel/time_64.c +++ b/arch/x86/kernel/time_64.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/x86-64/kernel/time.c | ||
3 | * | ||
4 | * "High Precision Event Timer" based timekeeping. | 2 | * "High Precision Event Timer" based timekeeping. |
5 | * | 3 | * |
6 | * Copyright (c) 1991,1992,1995 Linus Torvalds | 4 | * Copyright (c) 1991,1992,1995 Linus Torvalds |
@@ -28,11 +26,12 @@ | |||
28 | #include <linux/cpu.h> | 26 | #include <linux/cpu.h> |
29 | #include <linux/kallsyms.h> | 27 | #include <linux/kallsyms.h> |
30 | #include <linux/acpi.h> | 28 | #include <linux/acpi.h> |
29 | #include <linux/clockchips.h> | ||
30 | |||
31 | #ifdef CONFIG_ACPI | 31 | #ifdef CONFIG_ACPI |
32 | #include <acpi/achware.h> /* for PM timer frequency */ | 32 | #include <acpi/achware.h> /* for PM timer frequency */ |
33 | #include <acpi/acpi_bus.h> | 33 | #include <acpi/acpi_bus.h> |
34 | #endif | 34 | #endif |
35 | #include <asm/8253pit.h> | ||
36 | #include <asm/i8253.h> | 35 | #include <asm/i8253.h> |
37 | #include <asm/pgtable.h> | 36 | #include <asm/pgtable.h> |
38 | #include <asm/vsyscall.h> | 37 | #include <asm/vsyscall.h> |
@@ -47,12 +46,8 @@ | |||
47 | #include <asm/nmi.h> | 46 | #include <asm/nmi.h> |
48 | #include <asm/vgtod.h> | 47 | #include <asm/vgtod.h> |
49 | 48 | ||
50 | static char *timename = NULL; | ||
51 | |||
52 | DEFINE_SPINLOCK(rtc_lock); | 49 | DEFINE_SPINLOCK(rtc_lock); |
53 | EXPORT_SYMBOL(rtc_lock); | 50 | EXPORT_SYMBOL(rtc_lock); |
54 | DEFINE_SPINLOCK(i8253_lock); | ||
55 | EXPORT_SYMBOL(i8253_lock); | ||
56 | 51 | ||
57 | volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES; | 52 | volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES; |
58 | 53 | ||
@@ -153,45 +148,12 @@ int update_persistent_clock(struct timespec now) | |||
153 | return set_rtc_mmss(now.tv_sec); | 148 | return set_rtc_mmss(now.tv_sec); |
154 | } | 149 | } |
155 | 150 | ||
156 | void main_timer_handler(void) | 151 | static irqreturn_t timer_event_interrupt(int irq, void *dev_id) |
157 | { | 152 | { |
158 | /* | 153 | add_pda(irq0_irqs, 1); |
159 | * Here we are in the timer irq handler. We have irqs locally disabled (so we | ||
160 | * don't need spin_lock_irqsave()) but we don't know if the timer_bh is running | ||
161 | * on the other CPU, so we need a lock. We also need to lock the vsyscall | ||
162 | * variables, because both do_timer() and us change them -arca+vojtech | ||
163 | */ | ||
164 | |||
165 | write_seqlock(&xtime_lock); | ||
166 | |||
167 | /* | ||
168 | * Do the timer stuff. | ||
169 | */ | ||
170 | 154 | ||
171 | do_timer(1); | 155 | global_clock_event->event_handler(global_clock_event); |
172 | #ifndef CONFIG_SMP | ||
173 | update_process_times(user_mode(get_irq_regs())); | ||
174 | #endif | ||
175 | |||
176 | /* | ||
177 | * In the SMP case we use the local APIC timer interrupt to do the profiling, | ||
178 | * except when we simulate SMP mode on a uniprocessor system, in that case we | ||
179 | * have to call the local interrupt handler. | ||
180 | */ | ||
181 | |||
182 | if (!using_apic_timer) | ||
183 | smp_local_timer_interrupt(); | ||
184 | 156 | ||
185 | write_sequnlock(&xtime_lock); | ||
186 | } | ||
187 | |||
188 | static irqreturn_t timer_interrupt(int irq, void *dev_id) | ||
189 | { | ||
190 | if (apic_runs_main_timer > 1) | ||
191 | return IRQ_HANDLED; | ||
192 | main_timer_handler(); | ||
193 | if (using_apic_timer) | ||
194 | smp_send_timer_broadcast_ipi(); | ||
195 | return IRQ_HANDLED; | 157 | return IRQ_HANDLED; |
196 | } | 158 | } |
197 | 159 | ||
@@ -292,97 +254,21 @@ static unsigned int __init tsc_calibrate_cpu_khz(void) | |||
292 | return pmc_now * tsc_khz / (tsc_now - tsc_start); | 254 | return pmc_now * tsc_khz / (tsc_now - tsc_start); |
293 | } | 255 | } |
294 | 256 | ||
295 | /* | ||
296 | * pit_calibrate_tsc() uses the speaker output (channel 2) of | ||
297 | * the PIT. This is better than using the timer interrupt output, | ||
298 | * because we can read the value of the speaker with just one inb(), | ||
299 | * where we need three i/o operations for the interrupt channel. | ||
300 | * We count how many ticks the TSC does in 50 ms. | ||
301 | */ | ||
302 | |||
303 | static unsigned int __init pit_calibrate_tsc(void) | ||
304 | { | ||
305 | unsigned long start, end; | ||
306 | unsigned long flags; | ||
307 | |||
308 | spin_lock_irqsave(&i8253_lock, flags); | ||
309 | |||
310 | outb((inb(0x61) & ~0x02) | 0x01, 0x61); | ||
311 | |||
312 | outb(0xb0, 0x43); | ||
313 | outb((PIT_TICK_RATE / (1000 / 50)) & 0xff, 0x42); | ||
314 | outb((PIT_TICK_RATE / (1000 / 50)) >> 8, 0x42); | ||
315 | start = get_cycles_sync(); | ||
316 | while ((inb(0x61) & 0x20) == 0); | ||
317 | end = get_cycles_sync(); | ||
318 | |||
319 | spin_unlock_irqrestore(&i8253_lock, flags); | ||
320 | |||
321 | return (end - start) / 50; | ||
322 | } | ||
323 | |||
324 | #define PIT_MODE 0x43 | ||
325 | #define PIT_CH0 0x40 | ||
326 | |||
327 | static void __pit_init(int val, u8 mode) | ||
328 | { | ||
329 | unsigned long flags; | ||
330 | |||
331 | spin_lock_irqsave(&i8253_lock, flags); | ||
332 | outb_p(mode, PIT_MODE); | ||
333 | outb_p(val & 0xff, PIT_CH0); /* LSB */ | ||
334 | outb_p(val >> 8, PIT_CH0); /* MSB */ | ||
335 | spin_unlock_irqrestore(&i8253_lock, flags); | ||
336 | } | ||
337 | |||
338 | void __init pit_init(void) | ||
339 | { | ||
340 | __pit_init(LATCH, 0x34); /* binary, mode 2, LSB/MSB, ch 0 */ | ||
341 | } | ||
342 | |||
343 | void pit_stop_interrupt(void) | ||
344 | { | ||
345 | __pit_init(0, 0x30); /* mode 0 */ | ||
346 | } | ||
347 | |||
348 | void stop_timer_interrupt(void) | ||
349 | { | ||
350 | char *name; | ||
351 | if (hpet_address) { | ||
352 | name = "HPET"; | ||
353 | hpet_timer_stop_set_go(0); | ||
354 | } else { | ||
355 | name = "PIT"; | ||
356 | pit_stop_interrupt(); | ||
357 | } | ||
358 | printk(KERN_INFO "timer: %s interrupt stopped.\n", name); | ||
359 | } | ||
360 | |||
361 | static struct irqaction irq0 = { | 257 | static struct irqaction irq0 = { |
362 | .handler = timer_interrupt, | 258 | .handler = timer_event_interrupt, |
363 | .flags = IRQF_DISABLED | IRQF_IRQPOLL, | 259 | .flags = IRQF_DISABLED | IRQF_IRQPOLL | IRQF_NOBALANCING, |
364 | .mask = CPU_MASK_NONE, | 260 | .mask = CPU_MASK_NONE, |
365 | .name = "timer" | 261 | .name = "timer" |
366 | }; | 262 | }; |
367 | 263 | ||
368 | void __init time_init(void) | 264 | void __init time_init(void) |
369 | { | 265 | { |
370 | if (nohpet) | 266 | if (!hpet_enable()) |
371 | hpet_address = 0; | 267 | setup_pit_timer(); |
372 | 268 | ||
373 | if (hpet_arch_init()) | 269 | setup_irq(0, &irq0); |
374 | hpet_address = 0; | ||
375 | 270 | ||
376 | if (hpet_use_timer) { | 271 | tsc_calibrate(); |
377 | /* set tick_nsec to use the proper rate for HPET */ | ||
378 | tick_nsec = TICK_NSEC_HPET; | ||
379 | tsc_khz = hpet_calibrate_tsc(); | ||
380 | timename = "HPET"; | ||
381 | } else { | ||
382 | pit_init(); | ||
383 | tsc_khz = pit_calibrate_tsc(); | ||
384 | timename = "PIT"; | ||
385 | } | ||
386 | 272 | ||
387 | cpu_khz = tsc_khz; | 273 | cpu_khz = tsc_khz; |
388 | if (cpu_has(&boot_cpu_data, X86_FEATURE_CONSTANT_TSC) && | 274 | if (cpu_has(&boot_cpu_data, X86_FEATURE_CONSTANT_TSC) && |
@@ -398,50 +284,7 @@ void __init time_init(void) | |||
398 | else | 284 | else |
399 | vgetcpu_mode = VGETCPU_LSL; | 285 | vgetcpu_mode = VGETCPU_LSL; |
400 | 286 | ||
401 | set_cyc2ns_scale(tsc_khz); | ||
402 | printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n", | 287 | printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n", |
403 | cpu_khz / 1000, cpu_khz % 1000); | 288 | cpu_khz / 1000, cpu_khz % 1000); |
404 | init_tsc_clocksource(); | 289 | init_tsc_clocksource(); |
405 | |||
406 | setup_irq(0, &irq0); | ||
407 | } | ||
408 | |||
409 | /* | ||
410 | * sysfs support for the timer. | ||
411 | */ | ||
412 | |||
413 | static int timer_suspend(struct sys_device *dev, pm_message_t state) | ||
414 | { | ||
415 | return 0; | ||
416 | } | ||
417 | |||
418 | static int timer_resume(struct sys_device *dev) | ||
419 | { | ||
420 | if (hpet_address) | ||
421 | hpet_reenable(); | ||
422 | else | ||
423 | i8254_timer_resume(); | ||
424 | return 0; | ||
425 | } | 290 | } |
426 | |||
427 | static struct sysdev_class timer_sysclass = { | ||
428 | .resume = timer_resume, | ||
429 | .suspend = timer_suspend, | ||
430 | set_kset_name("timer"), | ||
431 | }; | ||
432 | |||
433 | /* XXX this sysfs stuff should probably go elsewhere later -john */ | ||
434 | static struct sys_device device_timer = { | ||
435 | .id = 0, | ||
436 | .cls = &timer_sysclass, | ||
437 | }; | ||
438 | |||
439 | static int time_init_device(void) | ||
440 | { | ||
441 | int error = sysdev_class_register(&timer_sysclass); | ||
442 | if (!error) | ||
443 | error = sysdev_register(&device_timer); | ||
444 | return error; | ||
445 | } | ||
446 | |||
447 | device_initcall(time_init_device); | ||
diff --git a/arch/x86/kernel/topology.c b/arch/x86/kernel/topology.c index 45782356a618..c25f23eb397c 100644 --- a/arch/x86/kernel/topology.c +++ b/arch/x86/kernel/topology.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * arch/i386/kernel/topology.c - Populate sysfs with topology information | 2 | * Populate sysfs with topology information |
3 | * | 3 | * |
4 | * Written by: Matthew Dobson, IBM Corporation | 4 | * Written by: Matthew Dobson, IBM Corporation |
5 | * Original Code: Paul Dorwin, IBM Corporation, Patrick Mochel, OSDL | 5 | * Original Code: Paul Dorwin, IBM Corporation, Patrick Mochel, OSDL |
diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c index 47b0bef335bd..05c27ecaf2a7 100644 --- a/arch/x86/kernel/traps_32.c +++ b/arch/x86/kernel/traps_32.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/i386/traps.c | ||
3 | * | ||
4 | * Copyright (C) 1991, 1992 Linus Torvalds | 2 | * Copyright (C) 1991, 1992 Linus Torvalds |
5 | * | 3 | * |
6 | * Pentium III FXSR, SSE support | 4 | * Pentium III FXSR, SSE support |
diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c index 03888420775d..bc7116acf8ff 100644 --- a/arch/x86/kernel/traps_64.c +++ b/arch/x86/kernel/traps_64.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/x86-64/traps.c | ||
3 | * | ||
4 | * Copyright (C) 1991, 1992 Linus Torvalds | 2 | * Copyright (C) 1991, 1992 Linus Torvalds |
5 | * Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs | 3 | * Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs |
6 | * | 4 | * |
diff --git a/arch/x86/kernel/tsc_32.c b/arch/x86/kernel/tsc_32.c index 3ed0ae8c918d..b85ad754f70e 100644 --- a/arch/x86/kernel/tsc_32.c +++ b/arch/x86/kernel/tsc_32.c | |||
@@ -1,9 +1,3 @@ | |||
1 | /* | ||
2 | * This code largely moved from arch/i386/kernel/timer/timer_tsc.c | ||
3 | * which was originally moved from arch/i386/kernel/time.c. | ||
4 | * See comments there for proper credits. | ||
5 | */ | ||
6 | |||
7 | #include <linux/sched.h> | 1 | #include <linux/sched.h> |
8 | #include <linux/clocksource.h> | 2 | #include <linux/clocksource.h> |
9 | #include <linux/workqueue.h> | 3 | #include <linux/workqueue.h> |
diff --git a/arch/x86/kernel/tsc_64.c b/arch/x86/kernel/tsc_64.c index 2a59bde663f2..9f22e542c374 100644 --- a/arch/x86/kernel/tsc_64.c +++ b/arch/x86/kernel/tsc_64.c | |||
@@ -6,7 +6,9 @@ | |||
6 | #include <linux/time.h> | 6 | #include <linux/time.h> |
7 | #include <linux/acpi.h> | 7 | #include <linux/acpi.h> |
8 | #include <linux/cpufreq.h> | 8 | #include <linux/cpufreq.h> |
9 | #include <linux/acpi_pmtmr.h> | ||
9 | 10 | ||
11 | #include <asm/hpet.h> | ||
10 | #include <asm/timex.h> | 12 | #include <asm/timex.h> |
11 | 13 | ||
12 | static int notsc __initdata = 0; | 14 | static int notsc __initdata = 0; |
@@ -18,7 +20,7 @@ EXPORT_SYMBOL(tsc_khz); | |||
18 | 20 | ||
19 | static unsigned int cyc2ns_scale __read_mostly; | 21 | static unsigned int cyc2ns_scale __read_mostly; |
20 | 22 | ||
21 | void set_cyc2ns_scale(unsigned long khz) | 23 | static inline void set_cyc2ns_scale(unsigned long khz) |
22 | { | 24 | { |
23 | cyc2ns_scale = (NSEC_PER_MSEC << NS_SCALE) / khz; | 25 | cyc2ns_scale = (NSEC_PER_MSEC << NS_SCALE) / khz; |
24 | } | 26 | } |
@@ -118,6 +120,95 @@ core_initcall(cpufreq_tsc); | |||
118 | 120 | ||
119 | #endif | 121 | #endif |
120 | 122 | ||
123 | #define MAX_RETRIES 5 | ||
124 | #define SMI_TRESHOLD 50000 | ||
125 | |||
126 | /* | ||
127 | * Read TSC and the reference counters. Take care of SMI disturbance | ||
128 | */ | ||
129 | static unsigned long __init tsc_read_refs(unsigned long *pm, | ||
130 | unsigned long *hpet) | ||
131 | { | ||
132 | unsigned long t1, t2; | ||
133 | int i; | ||
134 | |||
135 | for (i = 0; i < MAX_RETRIES; i++) { | ||
136 | t1 = get_cycles_sync(); | ||
137 | if (hpet) | ||
138 | *hpet = hpet_readl(HPET_COUNTER) & 0xFFFFFFFF; | ||
139 | else | ||
140 | *pm = acpi_pm_read_early(); | ||
141 | t2 = get_cycles_sync(); | ||
142 | if ((t2 - t1) < SMI_TRESHOLD) | ||
143 | return t2; | ||
144 | } | ||
145 | return ULONG_MAX; | ||
146 | } | ||
147 | |||
148 | /** | ||
149 | * tsc_calibrate - calibrate the tsc on boot | ||
150 | */ | ||
151 | void __init tsc_calibrate(void) | ||
152 | { | ||
153 | unsigned long flags, tsc1, tsc2, tr1, tr2, pm1, pm2, hpet1, hpet2; | ||
154 | int hpet = is_hpet_enabled(); | ||
155 | |||
156 | local_irq_save(flags); | ||
157 | |||
158 | tsc1 = tsc_read_refs(&pm1, hpet ? &hpet1 : NULL); | ||
159 | |||
160 | outb((inb(0x61) & ~0x02) | 0x01, 0x61); | ||
161 | |||
162 | outb(0xb0, 0x43); | ||
163 | outb((CLOCK_TICK_RATE / (1000 / 50)) & 0xff, 0x42); | ||
164 | outb((CLOCK_TICK_RATE / (1000 / 50)) >> 8, 0x42); | ||
165 | tr1 = get_cycles_sync(); | ||
166 | while ((inb(0x61) & 0x20) == 0); | ||
167 | tr2 = get_cycles_sync(); | ||
168 | |||
169 | tsc2 = tsc_read_refs(&pm2, hpet ? &hpet2 : NULL); | ||
170 | |||
171 | local_irq_restore(flags); | ||
172 | |||
173 | /* | ||
174 | * Preset the result with the raw and inaccurate PIT | ||
175 | * calibration value | ||
176 | */ | ||
177 | tsc_khz = (tr2 - tr1) / 50; | ||
178 | |||
179 | /* hpet or pmtimer available ? */ | ||
180 | if (!hpet && !pm1 && !pm2) { | ||
181 | printk(KERN_INFO "TSC calibrated against PIT\n"); | ||
182 | return; | ||
183 | } | ||
184 | |||
185 | /* Check, whether the sampling was disturbed by an SMI */ | ||
186 | if (tsc1 == ULONG_MAX || tsc2 == ULONG_MAX) { | ||
187 | printk(KERN_WARNING "TSC calibration disturbed by SMI, " | ||
188 | "using PIT calibration result\n"); | ||
189 | return; | ||
190 | } | ||
191 | |||
192 | tsc2 = (tsc2 - tsc1) * 1000000L; | ||
193 | |||
194 | if (hpet) { | ||
195 | printk(KERN_INFO "TSC calibrated against HPET\n"); | ||
196 | if (hpet2 < hpet1) | ||
197 | hpet2 += 0x100000000; | ||
198 | hpet2 -= hpet1; | ||
199 | tsc1 = (hpet2 * hpet_readl(HPET_PERIOD)) / 1000000; | ||
200 | } else { | ||
201 | printk(KERN_INFO "TSC calibrated against PM_TIMER\n"); | ||
202 | if (pm2 < pm1) | ||
203 | pm2 += ACPI_PM_OVRRUN; | ||
204 | pm2 -= pm1; | ||
205 | tsc1 = (pm2 * 1000000000) / PMTMR_TICKS_PER_SEC; | ||
206 | } | ||
207 | |||
208 | tsc_khz = tsc2 / tsc1; | ||
209 | set_cyc2ns_scale(tsc_khz); | ||
210 | } | ||
211 | |||
121 | /* | 212 | /* |
122 | * Make an educated guess if the TSC is trustworthy and synchronized | 213 | * Make an educated guess if the TSC is trustworthy and synchronized |
123 | * over all CPUs. | 214 | * over all CPUs. |
diff --git a/arch/x86/kernel/tsc_sync.c b/arch/x86/kernel/tsc_sync.c index 355f5f506c81..9125efe66a06 100644 --- a/arch/x86/kernel/tsc_sync.c +++ b/arch/x86/kernel/tsc_sync.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * arch/x86_64/kernel/tsc_sync.c: check TSC synchronization. | 2 | * check TSC synchronization. |
3 | * | 3 | * |
4 | * Copyright (C) 2006, Red Hat, Inc., Ingo Molnar | 4 | * Copyright (C) 2006, Red Hat, Inc., Ingo Molnar |
5 | * | 5 | * |
diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c index f2dcd1d27c0a..157e4bedd3c5 100644 --- a/arch/x86/kernel/vm86_32.c +++ b/arch/x86/kernel/vm86_32.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/kernel/vm86.c | ||
3 | * | ||
4 | * Copyright (C) 1994 Linus Torvalds | 2 | * Copyright (C) 1994 Linus Torvalds |
5 | * | 3 | * |
6 | * 29 dec 2001 - Fixed oopses caused by unchecked access to the vm86 | 4 | * 29 dec 2001 - Fixed oopses caused by unchecked access to the vm86 |
diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c index 06c34949bfdc..93847d848157 100644 --- a/arch/x86/kernel/vsyscall_64.c +++ b/arch/x86/kernel/vsyscall_64.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/x86_64/kernel/vsyscall.c | ||
3 | * | ||
4 | * Copyright (C) 2001 Andrea Arcangeli <andrea@suse.de> SuSE | 2 | * Copyright (C) 2001 Andrea Arcangeli <andrea@suse.de> SuSE |
5 | * Copyright 2003 Andi Kleen, SuSE Labs. | 3 | * Copyright 2003 Andi Kleen, SuSE Labs. |
6 | * | 4 | * |
diff --git a/arch/x86/lib/copy_user_nocache_64.S b/arch/x86/lib/copy_user_nocache_64.S index 4620efb12f13..5196762b3b0e 100644 --- a/arch/x86/lib/copy_user_nocache_64.S +++ b/arch/x86/lib/copy_user_nocache_64.S | |||
@@ -117,6 +117,7 @@ ENTRY(__copy_user_nocache) | |||
117 | popq %rbx | 117 | popq %rbx |
118 | CFI_ADJUST_CFA_OFFSET -8 | 118 | CFI_ADJUST_CFA_OFFSET -8 |
119 | CFI_RESTORE rbx | 119 | CFI_RESTORE rbx |
120 | sfence | ||
120 | ret | 121 | ret |
121 | CFI_RESTORE_STATE | 122 | CFI_RESTORE_STATE |
122 | 123 | ||
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index bc8a44bddaa7..2d88f7c6d6ac 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c | |||
@@ -2,15 +2,199 @@ | |||
2 | #include <linux/acpi.h> | 2 | #include <linux/acpi.h> |
3 | #include <linux/init.h> | 3 | #include <linux/init.h> |
4 | #include <linux/irq.h> | 4 | #include <linux/irq.h> |
5 | #include <linux/dmi.h> | ||
5 | #include <asm/numa.h> | 6 | #include <asm/numa.h> |
6 | #include "pci.h" | 7 | #include "pci.h" |
7 | 8 | ||
9 | static int __devinit can_skip_ioresource_align(const struct dmi_system_id *d) | ||
10 | { | ||
11 | pci_probe |= PCI_CAN_SKIP_ISA_ALIGN; | ||
12 | printk(KERN_INFO "PCI: %s detected, can skip ISA alignment\n", d->ident); | ||
13 | return 0; | ||
14 | } | ||
15 | |||
16 | static struct dmi_system_id acpi_pciprobe_dmi_table[] = { | ||
17 | /* | ||
18 | * Systems where PCI IO resource ISA alignment can be skipped | ||
19 | * when the ISA enable bit in the bridge control is not set | ||
20 | */ | ||
21 | { | ||
22 | .callback = can_skip_ioresource_align, | ||
23 | .ident = "IBM System x3800", | ||
24 | .matches = { | ||
25 | DMI_MATCH(DMI_SYS_VENDOR, "IBM"), | ||
26 | DMI_MATCH(DMI_PRODUCT_NAME, "x3800"), | ||
27 | }, | ||
28 | }, | ||
29 | { | ||
30 | .callback = can_skip_ioresource_align, | ||
31 | .ident = "IBM System x3850", | ||
32 | .matches = { | ||
33 | DMI_MATCH(DMI_SYS_VENDOR, "IBM"), | ||
34 | DMI_MATCH(DMI_PRODUCT_NAME, "x3850"), | ||
35 | }, | ||
36 | }, | ||
37 | { | ||
38 | .callback = can_skip_ioresource_align, | ||
39 | .ident = "IBM System x3950", | ||
40 | .matches = { | ||
41 | DMI_MATCH(DMI_SYS_VENDOR, "IBM"), | ||
42 | DMI_MATCH(DMI_PRODUCT_NAME, "x3950"), | ||
43 | }, | ||
44 | }, | ||
45 | {} | ||
46 | }; | ||
47 | |||
48 | struct pci_root_info { | ||
49 | char *name; | ||
50 | unsigned int res_num; | ||
51 | struct resource *res; | ||
52 | struct pci_bus *bus; | ||
53 | int busnum; | ||
54 | }; | ||
55 | |||
56 | static acpi_status | ||
57 | resource_to_addr(struct acpi_resource *resource, | ||
58 | struct acpi_resource_address64 *addr) | ||
59 | { | ||
60 | acpi_status status; | ||
61 | |||
62 | status = acpi_resource_to_address64(resource, addr); | ||
63 | if (ACPI_SUCCESS(status) && | ||
64 | (addr->resource_type == ACPI_MEMORY_RANGE || | ||
65 | addr->resource_type == ACPI_IO_RANGE) && | ||
66 | addr->address_length > 0 && | ||
67 | addr->producer_consumer == ACPI_PRODUCER) { | ||
68 | return AE_OK; | ||
69 | } | ||
70 | return AE_ERROR; | ||
71 | } | ||
72 | |||
73 | static acpi_status | ||
74 | count_resource(struct acpi_resource *acpi_res, void *data) | ||
75 | { | ||
76 | struct pci_root_info *info = data; | ||
77 | struct acpi_resource_address64 addr; | ||
78 | acpi_status status; | ||
79 | |||
80 | status = resource_to_addr(acpi_res, &addr); | ||
81 | if (ACPI_SUCCESS(status)) | ||
82 | info->res_num++; | ||
83 | return AE_OK; | ||
84 | } | ||
85 | |||
86 | static acpi_status | ||
87 | setup_resource(struct acpi_resource *acpi_res, void *data) | ||
88 | { | ||
89 | struct pci_root_info *info = data; | ||
90 | struct resource *res; | ||
91 | struct acpi_resource_address64 addr; | ||
92 | acpi_status status; | ||
93 | unsigned long flags; | ||
94 | struct resource *root; | ||
95 | |||
96 | status = resource_to_addr(acpi_res, &addr); | ||
97 | if (!ACPI_SUCCESS(status)) | ||
98 | return AE_OK; | ||
99 | |||
100 | if (addr.resource_type == ACPI_MEMORY_RANGE) { | ||
101 | root = &iomem_resource; | ||
102 | flags = IORESOURCE_MEM; | ||
103 | if (addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY) | ||
104 | flags |= IORESOURCE_PREFETCH; | ||
105 | } else if (addr.resource_type == ACPI_IO_RANGE) { | ||
106 | root = &ioport_resource; | ||
107 | flags = IORESOURCE_IO; | ||
108 | } else | ||
109 | return AE_OK; | ||
110 | |||
111 | res = &info->res[info->res_num]; | ||
112 | res->name = info->name; | ||
113 | res->flags = flags; | ||
114 | res->start = addr.minimum + addr.translation_offset; | ||
115 | res->end = res->start + addr.address_length - 1; | ||
116 | res->child = NULL; | ||
117 | |||
118 | if (insert_resource(root, res)) { | ||
119 | printk(KERN_ERR "PCI: Failed to allocate 0x%lx-0x%lx " | ||
120 | "from %s for %s\n", (unsigned long) res->start, | ||
121 | (unsigned long) res->end, root->name, info->name); | ||
122 | } else { | ||
123 | info->bus->resource[info->res_num] = res; | ||
124 | info->res_num++; | ||
125 | } | ||
126 | return AE_OK; | ||
127 | } | ||
128 | |||
129 | static void | ||
130 | adjust_transparent_bridge_resources(struct pci_bus *bus) | ||
131 | { | ||
132 | struct pci_dev *dev; | ||
133 | |||
134 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
135 | int i; | ||
136 | u16 class = dev->class >> 8; | ||
137 | |||
138 | if (class == PCI_CLASS_BRIDGE_PCI && dev->transparent) { | ||
139 | for(i = 3; i < PCI_BUS_NUM_RESOURCES; i++) | ||
140 | dev->subordinate->resource[i] = | ||
141 | dev->bus->resource[i - 3]; | ||
142 | } | ||
143 | } | ||
144 | } | ||
145 | |||
146 | static void | ||
147 | get_current_resources(struct acpi_device *device, int busnum, | ||
148 | struct pci_bus *bus) | ||
149 | { | ||
150 | struct pci_root_info info; | ||
151 | size_t size; | ||
152 | |||
153 | info.bus = bus; | ||
154 | info.res_num = 0; | ||
155 | acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource, | ||
156 | &info); | ||
157 | if (!info.res_num) | ||
158 | return; | ||
159 | |||
160 | size = sizeof(*info.res) * info.res_num; | ||
161 | info.res = kmalloc(size, GFP_KERNEL); | ||
162 | if (!info.res) | ||
163 | goto res_alloc_fail; | ||
164 | |||
165 | info.name = kmalloc(12, GFP_KERNEL); | ||
166 | if (!info.name) | ||
167 | goto name_alloc_fail; | ||
168 | sprintf(info.name, "PCI Bus #%02x", busnum); | ||
169 | |||
170 | info.res_num = 0; | ||
171 | acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource, | ||
172 | &info); | ||
173 | if (info.res_num) | ||
174 | adjust_transparent_bridge_resources(bus); | ||
175 | |||
176 | return; | ||
177 | |||
178 | name_alloc_fail: | ||
179 | kfree(info.res); | ||
180 | res_alloc_fail: | ||
181 | return; | ||
182 | } | ||
183 | |||
8 | struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum) | 184 | struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum) |
9 | { | 185 | { |
10 | struct pci_bus *bus; | 186 | struct pci_bus *bus; |
11 | struct pci_sysdata *sd; | 187 | struct pci_sysdata *sd; |
12 | int pxm; | 188 | int pxm; |
13 | 189 | ||
190 | dmi_check_system(acpi_pciprobe_dmi_table); | ||
191 | |||
192 | if (domain && !pci_domains_supported) { | ||
193 | printk(KERN_WARNING "PCI: Multiple domains not supported " | ||
194 | "(dom %d, bus %d)\n", domain, busnum); | ||
195 | return NULL; | ||
196 | } | ||
197 | |||
14 | /* Allocate per-root-bus (not per bus) arch-specific data. | 198 | /* Allocate per-root-bus (not per bus) arch-specific data. |
15 | * TODO: leak; this memory is never freed. | 199 | * TODO: leak; this memory is never freed. |
16 | * It's arguable whether it's worth the trouble to care. | 200 | * It's arguable whether it's worth the trouble to care. |
@@ -21,12 +205,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do | |||
21 | return NULL; | 205 | return NULL; |
22 | } | 206 | } |
23 | 207 | ||
24 | if (domain != 0) { | 208 | sd->domain = domain; |
25 | printk(KERN_WARNING "PCI: Multiple domains not supported\n"); | ||
26 | kfree(sd); | ||
27 | return NULL; | ||
28 | } | ||
29 | |||
30 | sd->node = -1; | 209 | sd->node = -1; |
31 | 210 | ||
32 | pxm = acpi_get_pxm(device->handle); | 211 | pxm = acpi_get_pxm(device->handle); |
@@ -47,6 +226,9 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do | |||
47 | } | 226 | } |
48 | } | 227 | } |
49 | #endif | 228 | #endif |
229 | |||
230 | if (bus && (pci_probe & PCI_USE__CRS)) | ||
231 | get_current_resources(device, busnum, bus); | ||
50 | 232 | ||
51 | return bus; | 233 | return bus; |
52 | } | 234 | } |
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 07d5223442bf..2d71bbc411d2 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c | |||
@@ -29,12 +29,14 @@ struct pci_raw_ops *raw_pci_ops; | |||
29 | 29 | ||
30 | static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) | 30 | static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) |
31 | { | 31 | { |
32 | return raw_pci_ops->read(0, bus->number, devfn, where, size, value); | 32 | return raw_pci_ops->read(pci_domain_nr(bus), bus->number, |
33 | devfn, where, size, value); | ||
33 | } | 34 | } |
34 | 35 | ||
35 | static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) | 36 | static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) |
36 | { | 37 | { |
37 | return raw_pci_ops->write(0, bus->number, devfn, where, size, value); | 38 | return raw_pci_ops->write(pci_domain_nr(bus), bus->number, |
39 | devfn, where, size, value); | ||
38 | } | 40 | } |
39 | 41 | ||
40 | struct pci_ops pci_root_ops = { | 42 | struct pci_ops pci_root_ops = { |
@@ -287,6 +289,16 @@ static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = { | |||
287 | DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL685c G1"), | 289 | DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL685c G1"), |
288 | }, | 290 | }, |
289 | }, | 291 | }, |
292 | #ifdef __i386__ | ||
293 | { | ||
294 | .callback = assign_all_busses, | ||
295 | .ident = "Compaq EVO N800c", | ||
296 | .matches = { | ||
297 | DMI_MATCH(DMI_SYS_VENDOR, "Compaq"), | ||
298 | DMI_MATCH(DMI_PRODUCT_NAME, "EVO N800c"), | ||
299 | }, | ||
300 | }, | ||
301 | #endif | ||
290 | {} | 302 | {} |
291 | }; | 303 | }; |
292 | 304 | ||
@@ -426,6 +438,9 @@ char * __devinit pcibios_setup(char *str) | |||
426 | } else if (!strcmp(str, "assign-busses")) { | 438 | } else if (!strcmp(str, "assign-busses")) { |
427 | pci_probe |= PCI_ASSIGN_ALL_BUSSES; | 439 | pci_probe |= PCI_ASSIGN_ALL_BUSSES; |
428 | return NULL; | 440 | return NULL; |
441 | } else if (!strcmp(str, "use_crs")) { | ||
442 | pci_probe |= PCI_USE__CRS; | ||
443 | return NULL; | ||
429 | } else if (!strcmp(str, "routeirq")) { | 444 | } else if (!strcmp(str, "routeirq")) { |
430 | pci_routeirq = 1; | 445 | pci_routeirq = 1; |
431 | return NULL; | 446 | return NULL; |
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c index c82cbf4c7226..6cff66dd0c91 100644 --- a/arch/x86/pci/fixup.c +++ b/arch/x86/pci/fixup.c | |||
@@ -353,6 +353,53 @@ static void __devinit pci_fixup_video(struct pci_dev *pdev) | |||
353 | } | 353 | } |
354 | DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video); | 354 | DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video); |
355 | 355 | ||
356 | |||
357 | static struct dmi_system_id __devinitdata msi_k8t_dmi_table[] = { | ||
358 | { | ||
359 | .ident = "MSI-K8T-Neo2Fir", | ||
360 | .matches = { | ||
361 | DMI_MATCH(DMI_SYS_VENDOR, "MSI"), | ||
362 | DMI_MATCH(DMI_PRODUCT_NAME, "MS-6702E"), | ||
363 | }, | ||
364 | }, | ||
365 | {} | ||
366 | }; | ||
367 | |||
368 | /* | ||
369 | * The AMD-Athlon64 board MSI "K8T Neo2-FIR" disables the onboard sound | ||
370 | * card if a PCI-soundcard is added. | ||
371 | * | ||
372 | * The BIOS only gives options "DISABLED" and "AUTO". This code sets | ||
373 | * the corresponding register-value to enable the soundcard. | ||
374 | * | ||
375 | * The soundcard is only enabled, if the mainborad is identified | ||
376 | * via DMI-tables and the soundcard is detected to be off. | ||
377 | */ | ||
378 | static void __devinit pci_fixup_msi_k8t_onboard_sound(struct pci_dev *dev) | ||
379 | { | ||
380 | unsigned char val; | ||
381 | if (!dmi_check_system(msi_k8t_dmi_table)) | ||
382 | return; /* only applies to MSI K8T Neo2-FIR */ | ||
383 | |||
384 | pci_read_config_byte(dev, 0x50, &val); | ||
385 | if (val & 0x40) { | ||
386 | pci_write_config_byte(dev, 0x50, val & (~0x40)); | ||
387 | |||
388 | /* verify the change for status output */ | ||
389 | pci_read_config_byte(dev, 0x50, &val); | ||
390 | if (val & 0x40) | ||
391 | printk(KERN_INFO "PCI: Detected MSI K8T Neo2-FIR, " | ||
392 | "can't enable onboard soundcard!\n"); | ||
393 | else | ||
394 | printk(KERN_INFO "PCI: Detected MSI K8T Neo2-FIR, " | ||
395 | "enabled onboard soundcard.\n"); | ||
396 | } | ||
397 | } | ||
398 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, | ||
399 | pci_fixup_msi_k8t_onboard_sound); | ||
400 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, | ||
401 | pci_fixup_msi_k8t_onboard_sound); | ||
402 | |||
356 | /* | 403 | /* |
357 | * Some Toshiba laptops need extra code to enable their TI TSB43AB22/A. | 404 | * Some Toshiba laptops need extra code to enable their TI TSB43AB22/A. |
358 | * | 405 | * |
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index bcd2f94b732c..42ba0e2da1a0 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c | |||
@@ -33,6 +33,15 @@ | |||
33 | 33 | ||
34 | #include "pci.h" | 34 | #include "pci.h" |
35 | 35 | ||
36 | static int | ||
37 | skip_isa_ioresource_align(struct pci_dev *dev) { | ||
38 | |||
39 | if ((pci_probe & PCI_CAN_SKIP_ISA_ALIGN) && | ||
40 | !(dev->bus->bridge_ctl & PCI_BRIDGE_CTL_ISA)) | ||
41 | return 1; | ||
42 | return 0; | ||
43 | } | ||
44 | |||
36 | /* | 45 | /* |
37 | * We need to avoid collisions with `mirrored' VGA ports | 46 | * We need to avoid collisions with `mirrored' VGA ports |
38 | * and other strange ISA hardware, so we always want the | 47 | * and other strange ISA hardware, so we always want the |
@@ -50,9 +59,13 @@ void | |||
50 | pcibios_align_resource(void *data, struct resource *res, | 59 | pcibios_align_resource(void *data, struct resource *res, |
51 | resource_size_t size, resource_size_t align) | 60 | resource_size_t size, resource_size_t align) |
52 | { | 61 | { |
62 | struct pci_dev *dev = data; | ||
63 | |||
53 | if (res->flags & IORESOURCE_IO) { | 64 | if (res->flags & IORESOURCE_IO) { |
54 | resource_size_t start = res->start; | 65 | resource_size_t start = res->start; |
55 | 66 | ||
67 | if (skip_isa_ioresource_align(dev)) | ||
68 | return; | ||
56 | if (start & 0x300) { | 69 | if (start & 0x300) { |
57 | start = (start + 0x3ff) & ~0x3ff; | 70 | start = (start + 0x3ff) & ~0x3ff; |
58 | res->start = start; | 71 | res->start = start; |
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c index d98c6b096f8e..c52150fdf82b 100644 --- a/arch/x86/pci/irq.c +++ b/arch/x86/pci/irq.c | |||
@@ -492,6 +492,26 @@ static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq | |||
492 | return 1; | 492 | return 1; |
493 | } | 493 | } |
494 | 494 | ||
495 | /* | ||
496 | * PicoPower PT86C523 | ||
497 | */ | ||
498 | static int pirq_pico_get(struct pci_dev *router, struct pci_dev *dev, int pirq) | ||
499 | { | ||
500 | outb(0x10 + ((pirq - 1) >> 1), 0x24); | ||
501 | return ((pirq - 1) & 1) ? (inb(0x26) >> 4) : (inb(0x26) & 0xf); | ||
502 | } | ||
503 | |||
504 | static int pirq_pico_set(struct pci_dev *router, struct pci_dev *dev, int pirq, | ||
505 | int irq) | ||
506 | { | ||
507 | unsigned int x; | ||
508 | outb(0x10 + ((pirq - 1) >> 1), 0x24); | ||
509 | x = inb(0x26); | ||
510 | x = ((pirq - 1) & 1) ? ((x & 0x0f) | (irq << 4)) : ((x & 0xf0) | (irq)); | ||
511 | outb(x, 0x26); | ||
512 | return 1; | ||
513 | } | ||
514 | |||
495 | #ifdef CONFIG_PCI_BIOS | 515 | #ifdef CONFIG_PCI_BIOS |
496 | 516 | ||
497 | static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) | 517 | static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) |
@@ -721,6 +741,24 @@ static __init int amd_router_probe(struct irq_router *r, struct pci_dev *router, | |||
721 | return 1; | 741 | return 1; |
722 | } | 742 | } |
723 | 743 | ||
744 | static __init int pico_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) | ||
745 | { | ||
746 | switch (device) { | ||
747 | case PCI_DEVICE_ID_PICOPOWER_PT86C523: | ||
748 | r->name = "PicoPower PT86C523"; | ||
749 | r->get = pirq_pico_get; | ||
750 | r->set = pirq_pico_set; | ||
751 | return 1; | ||
752 | |||
753 | case PCI_DEVICE_ID_PICOPOWER_PT86C523BBP: | ||
754 | r->name = "PicoPower PT86C523 rev. BB+"; | ||
755 | r->get = pirq_pico_get; | ||
756 | r->set = pirq_pico_set; | ||
757 | return 1; | ||
758 | } | ||
759 | return 0; | ||
760 | } | ||
761 | |||
724 | static __initdata struct irq_router_handler pirq_routers[] = { | 762 | static __initdata struct irq_router_handler pirq_routers[] = { |
725 | { PCI_VENDOR_ID_INTEL, intel_router_probe }, | 763 | { PCI_VENDOR_ID_INTEL, intel_router_probe }, |
726 | { PCI_VENDOR_ID_AL, ali_router_probe }, | 764 | { PCI_VENDOR_ID_AL, ali_router_probe }, |
@@ -732,6 +770,7 @@ static __initdata struct irq_router_handler pirq_routers[] = { | |||
732 | { PCI_VENDOR_ID_VLSI, vlsi_router_probe }, | 770 | { PCI_VENDOR_ID_VLSI, vlsi_router_probe }, |
733 | { PCI_VENDOR_ID_SERVERWORKS, serverworks_router_probe }, | 771 | { PCI_VENDOR_ID_SERVERWORKS, serverworks_router_probe }, |
734 | { PCI_VENDOR_ID_AMD, amd_router_probe }, | 772 | { PCI_VENDOR_ID_AMD, amd_router_probe }, |
773 | { PCI_VENDOR_ID_PICOPOWER, pico_router_probe }, | ||
735 | /* Someone with docs needs to add the ATI Radeon IGP */ | 774 | /* Someone with docs needs to add the ATI Radeon IGP */ |
736 | { 0, NULL } | 775 | { 0, NULL } |
737 | }; | 776 | }; |
diff --git a/arch/x86/pci/pci.h b/arch/x86/pci/pci.h index 8c66f275756f..ac56d3916c50 100644 --- a/arch/x86/pci/pci.h +++ b/arch/x86/pci/pci.h | |||
@@ -26,6 +26,8 @@ | |||
26 | #define PCI_ASSIGN_ROMS 0x1000 | 26 | #define PCI_ASSIGN_ROMS 0x1000 |
27 | #define PCI_BIOS_IRQ_SCAN 0x2000 | 27 | #define PCI_BIOS_IRQ_SCAN 0x2000 |
28 | #define PCI_ASSIGN_ALL_BUSSES 0x4000 | 28 | #define PCI_ASSIGN_ALL_BUSSES 0x4000 |
29 | #define PCI_CAN_SKIP_ISA_ALIGN 0x8000 | ||
30 | #define PCI_USE__CRS 0x10000 | ||
29 | 31 | ||
30 | extern unsigned int pci_probe; | 32 | extern unsigned int pci_probe; |
31 | extern unsigned long pirq_table_addr; | 33 | extern unsigned long pirq_table_addr; |