diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2007-10-12 17:04:23 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@inhelltoy.tec.linutronix.de> | 2007-10-12 17:04:23 -0400 |
commit | 9f75e9b74a45d7d3c343c8979f49d5e6b92bbce3 (patch) | |
tree | ca7115bd03031db131dda5912e2d9cd302046608 /arch/x86/kernel | |
parent | 2f0798a3b1c2155b8f30858e853557aef9da2e4e (diff) |
x86_64: remove now unused code
Remove the unused code after the switch to clock events.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Chris Wright <chrisw@sous-sol.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/Makefile_32 | 4 | ||||
-rw-r--r-- | arch/x86/kernel/Makefile_64 | 4 | ||||
-rw-r--r-- | arch/x86/kernel/apic_64.c | 106 | ||||
-rw-r--r-- | arch/x86/kernel/hpet.c (renamed from arch/x86/kernel/hpet_32.c) | 0 | ||||
-rw-r--r-- | arch/x86/kernel/hpet_64.c | 444 | ||||
-rw-r--r-- | arch/x86/kernel/i8253.c (renamed from arch/x86/kernel/i8253_32.c) | 0 | ||||
-rw-r--r-- | arch/x86/kernel/time_64.c | 42 |
7 files changed, 5 insertions, 595 deletions
diff --git a/arch/x86/kernel/Makefile_32 b/arch/x86/kernel/Makefile_32 index 10356443998..7ff02063b85 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,7 +37,7 @@ 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 mfgpt_32.o | 42 | obj-$(CONFIG_MGEODE_LX) += geode_32.o mfgpt_32.o |
43 | 43 | ||
diff --git a/arch/x86/kernel/Makefile_64 b/arch/x86/kernel/Makefile_64 index 080154e3150..43da66213a4 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_32.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 i8253_32.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/apic_64.c b/arch/x86/kernel/apic_64.c index 118830cba1a..1231365404c 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c | |||
@@ -41,7 +41,6 @@ | |||
41 | #include <asm/apic.h> | 41 | #include <asm/apic.h> |
42 | 42 | ||
43 | int apic_verbosity; | 43 | int apic_verbosity; |
44 | int apic_runs_main_timer; | ||
45 | int apic_calibrate_pmtmr __initdata; | 44 | int apic_calibrate_pmtmr __initdata; |
46 | 45 | ||
47 | int disable_apic_timer __cpuinitdata; | 46 | int disable_apic_timer __cpuinitdata; |
@@ -129,15 +128,6 @@ static void lapic_timer_broadcast(cpumask_t mask) | |||
129 | #endif | 128 | #endif |
130 | } | 129 | } |
131 | 130 | ||
132 | /* | ||
133 | * cpu_mask that denotes the CPUs that needs timer interrupt coming in as | ||
134 | * IPIs in place of local APIC timers | ||
135 | */ | ||
136 | static cpumask_t timer_interrupt_broadcast_ipi_mask; | ||
137 | |||
138 | /* Using APIC to generate smp_local_timer_interrupt? */ | ||
139 | int using_apic_timer __read_mostly = 0; | ||
140 | |||
141 | static void apic_pm_activate(void); | 131 | static void apic_pm_activate(void); |
142 | 132 | ||
143 | void apic_wait_icr_idle(void) | 133 | void apic_wait_icr_idle(void) |
@@ -973,84 +963,6 @@ void __cpuinit setup_secondary_APIC_clock(void) | |||
973 | setup_APIC_timer(); | 963 | setup_APIC_timer(); |
974 | } | 964 | } |
975 | 965 | ||
976 | void disable_APIC_timer(void) | ||
977 | { | ||
978 | if (using_apic_timer) { | ||
979 | unsigned long v; | ||
980 | |||
981 | v = apic_read(APIC_LVTT); | ||
982 | /* | ||
983 | * When an illegal vector value (0-15) is written to an LVT | ||
984 | * entry and delivery mode is Fixed, the APIC may signal an | ||
985 | * illegal vector error, with out regard to whether the mask | ||
986 | * bit is set or whether an interrupt is actually seen on input. | ||
987 | * | ||
988 | * Boot sequence might call this function when the LVTT has | ||
989 | * '0' vector value. So make sure vector field is set to | ||
990 | * valid value. | ||
991 | */ | ||
992 | v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); | ||
993 | apic_write(APIC_LVTT, v); | ||
994 | } | ||
995 | } | ||
996 | |||
997 | void enable_APIC_timer(void) | ||
998 | { | ||
999 | int cpu = smp_processor_id(); | ||
1000 | |||
1001 | if (using_apic_timer && | ||
1002 | !cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask)) { | ||
1003 | unsigned long v; | ||
1004 | |||
1005 | v = apic_read(APIC_LVTT); | ||
1006 | apic_write(APIC_LVTT, v & ~APIC_LVT_MASKED); | ||
1007 | } | ||
1008 | } | ||
1009 | |||
1010 | void switch_APIC_timer_to_ipi(void *cpumask) | ||
1011 | { | ||
1012 | cpumask_t mask = *(cpumask_t *)cpumask; | ||
1013 | int cpu = smp_processor_id(); | ||
1014 | |||
1015 | if (cpu_isset(cpu, mask) && | ||
1016 | !cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask)) { | ||
1017 | disable_APIC_timer(); | ||
1018 | cpu_set(cpu, timer_interrupt_broadcast_ipi_mask); | ||
1019 | } | ||
1020 | } | ||
1021 | EXPORT_SYMBOL(switch_APIC_timer_to_ipi); | ||
1022 | |||
1023 | void smp_send_timer_broadcast_ipi(void) | ||
1024 | { | ||
1025 | int cpu = smp_processor_id(); | ||
1026 | cpumask_t mask; | ||
1027 | |||
1028 | cpus_and(mask, cpu_online_map, timer_interrupt_broadcast_ipi_mask); | ||
1029 | |||
1030 | if (cpu_isset(cpu, mask)) { | ||
1031 | cpu_clear(cpu, mask); | ||
1032 | add_pda(apic_timer_irqs, 1); | ||
1033 | smp_local_timer_interrupt(); | ||
1034 | } | ||
1035 | |||
1036 | if (!cpus_empty(mask)) { | ||
1037 | send_IPI_mask(mask, LOCAL_TIMER_VECTOR); | ||
1038 | } | ||
1039 | } | ||
1040 | |||
1041 | void switch_ipi_to_APIC_timer(void *cpumask) | ||
1042 | { | ||
1043 | cpumask_t mask = *(cpumask_t *)cpumask; | ||
1044 | int cpu = smp_processor_id(); | ||
1045 | |||
1046 | if (cpu_isset(cpu, mask) && | ||
1047 | cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask)) { | ||
1048 | cpu_clear(cpu, timer_interrupt_broadcast_ipi_mask); | ||
1049 | enable_APIC_timer(); | ||
1050 | } | ||
1051 | } | ||
1052 | EXPORT_SYMBOL(switch_ipi_to_APIC_timer); | ||
1053 | |||
1054 | int setup_profiling_timer(unsigned int multiplier) | 966 | int setup_profiling_timer(unsigned int multiplier) |
1055 | { | 967 | { |
1056 | return -EINVAL; | 968 | return -EINVAL; |
@@ -1297,21 +1209,7 @@ static __init int setup_noapictimer(char *str) | |||
1297 | disable_apic_timer = 1; | 1209 | disable_apic_timer = 1; |
1298 | return 1; | 1210 | return 1; |
1299 | } | 1211 | } |
1300 | 1212 | __setup("noapictimer", setup_noapictimer); | |
1301 | static __init int setup_apicmaintimer(char *str) | ||
1302 | { | ||
1303 | apic_runs_main_timer = 1; | ||
1304 | |||
1305 | return 1; | ||
1306 | } | ||
1307 | __setup("apicmaintimer", setup_apicmaintimer); | ||
1308 | |||
1309 | static __init int setup_noapicmaintimer(char *str) | ||
1310 | { | ||
1311 | apic_runs_main_timer = -1; | ||
1312 | return 1; | ||
1313 | } | ||
1314 | __setup("noapicmaintimer", setup_noapicmaintimer); | ||
1315 | 1213 | ||
1316 | static __init int setup_apicpmtimer(char *s) | 1214 | static __init int setup_apicpmtimer(char *s) |
1317 | { | 1215 | { |
@@ -1321,5 +1219,3 @@ static __init int setup_apicpmtimer(char *s) | |||
1321 | } | 1219 | } |
1322 | __setup("apicpmtimer", setup_apicpmtimer); | 1220 | __setup("apicpmtimer", setup_apicpmtimer); |
1323 | 1221 | ||
1324 | __setup("noapictimer", setup_noapictimer); | ||
1325 | |||
diff --git a/arch/x86/kernel/hpet_32.c b/arch/x86/kernel/hpet.c index dbe0e1d4411..dbe0e1d4411 100644 --- a/arch/x86/kernel/hpet_32.c +++ b/arch/x86/kernel/hpet.c | |||
diff --git a/arch/x86/kernel/hpet_64.c b/arch/x86/kernel/hpet_64.c deleted file mode 100644 index 1ebce2ec7ea..00000000000 --- a/arch/x86/kernel/hpet_64.c +++ /dev/null | |||
@@ -1,444 +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 | #ifdef CONFIG_HPET_EMULATE_RTC | ||
188 | /* HPET in LegacyReplacement Mode eats up RTC interrupt line. When, HPET | ||
189 | * is enabled, we support RTC interrupt functionality in software. | ||
190 | * RTC has 3 kinds of interrupts: | ||
191 | * 1) Update Interrupt - generate an interrupt, every sec, when RTC clock | ||
192 | * is updated | ||
193 | * 2) Alarm Interrupt - generate an interrupt at a specific time of day | ||
194 | * 3) Periodic Interrupt - generate periodic interrupt, with frequencies | ||
195 | * 2Hz-8192Hz (2Hz-64Hz for non-root user) (all freqs in powers of 2) | ||
196 | * (1) and (2) above are implemented using polling at a frequency of | ||
197 | * 64 Hz. The exact frequency is a tradeoff between accuracy and interrupt | ||
198 | * overhead. (DEFAULT_RTC_INT_FREQ) | ||
199 | * For (3), we use interrupts at 64Hz or user specified periodic | ||
200 | * frequency, whichever is higher. | ||
201 | */ | ||
202 | #include <linux/rtc.h> | ||
203 | |||
204 | #define DEFAULT_RTC_INT_FREQ 64 | ||
205 | #define RTC_NUM_INTS 1 | ||
206 | |||
207 | static unsigned long UIE_on; | ||
208 | static unsigned long prev_update_sec; | ||
209 | |||
210 | static unsigned long AIE_on; | ||
211 | static struct rtc_time alarm_time; | ||
212 | |||
213 | static unsigned long PIE_on; | ||
214 | static unsigned long PIE_freq = DEFAULT_RTC_INT_FREQ; | ||
215 | static unsigned long PIE_count; | ||
216 | |||
217 | static unsigned long hpet_rtc_int_freq; /* RTC interrupt frequency */ | ||
218 | static unsigned int hpet_t1_cmp; /* cached comparator register */ | ||
219 | |||
220 | int is_hpet_enabled(void) | ||
221 | { | ||
222 | return hpet_address != 0; | ||
223 | } | ||
224 | |||
225 | /* | ||
226 | * Timer 1 for RTC, we do not use periodic interrupt feature, | ||
227 | * even if HPET supports periodic interrupts on Timer 1. | ||
228 | * The reason being, to set up a periodic interrupt in HPET, we need to | ||
229 | * stop the main counter. And if we do that everytime someone diables/enables | ||
230 | * RTC, we will have adverse effect on main kernel timer running on Timer 0. | ||
231 | * So, for the time being, simulate the periodic interrupt in software. | ||
232 | * | ||
233 | * hpet_rtc_timer_init() is called for the first time and during subsequent | ||
234 | * interuppts reinit happens through hpet_rtc_timer_reinit(). | ||
235 | */ | ||
236 | int hpet_rtc_timer_init(void) | ||
237 | { | ||
238 | unsigned int cfg, cnt; | ||
239 | unsigned long flags; | ||
240 | |||
241 | if (!is_hpet_enabled()) | ||
242 | return 0; | ||
243 | /* | ||
244 | * Set the counter 1 and enable the interrupts. | ||
245 | */ | ||
246 | if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ)) | ||
247 | hpet_rtc_int_freq = PIE_freq; | ||
248 | else | ||
249 | hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ; | ||
250 | |||
251 | local_irq_save(flags); | ||
252 | |||
253 | cnt = hpet_readl(HPET_COUNTER); | ||
254 | cnt += ((hpet_tick*HZ)/hpet_rtc_int_freq); | ||
255 | hpet_writel(cnt, HPET_T1_CMP); | ||
256 | hpet_t1_cmp = cnt; | ||
257 | |||
258 | cfg = hpet_readl(HPET_T1_CFG); | ||
259 | cfg &= ~HPET_TN_PERIODIC; | ||
260 | cfg |= HPET_TN_ENABLE | HPET_TN_32BIT; | ||
261 | hpet_writel(cfg, HPET_T1_CFG); | ||
262 | |||
263 | local_irq_restore(flags); | ||
264 | |||
265 | return 1; | ||
266 | } | ||
267 | |||
268 | static void hpet_rtc_timer_reinit(void) | ||
269 | { | ||
270 | unsigned int cfg, cnt, ticks_per_int, lost_ints; | ||
271 | |||
272 | if (unlikely(!(PIE_on | AIE_on | UIE_on))) { | ||
273 | cfg = hpet_readl(HPET_T1_CFG); | ||
274 | cfg &= ~HPET_TN_ENABLE; | ||
275 | hpet_writel(cfg, HPET_T1_CFG); | ||
276 | return; | ||
277 | } | ||
278 | |||
279 | if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ)) | ||
280 | hpet_rtc_int_freq = PIE_freq; | ||
281 | else | ||
282 | hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ; | ||
283 | |||
284 | /* It is more accurate to use the comparator value than current count.*/ | ||
285 | ticks_per_int = hpet_tick * HZ / hpet_rtc_int_freq; | ||
286 | hpet_t1_cmp += ticks_per_int; | ||
287 | hpet_writel(hpet_t1_cmp, HPET_T1_CMP); | ||
288 | |||
289 | /* | ||
290 | * If the interrupt handler was delayed too long, the write above tries | ||
291 | * to schedule the next interrupt in the past and the hardware would | ||
292 | * not interrupt until the counter had wrapped around. | ||
293 | * So we have to check that the comparator wasn't set to a past time. | ||
294 | */ | ||
295 | cnt = hpet_readl(HPET_COUNTER); | ||
296 | if (unlikely((int)(cnt - hpet_t1_cmp) > 0)) { | ||
297 | lost_ints = (cnt - hpet_t1_cmp) / ticks_per_int + 1; | ||
298 | /* Make sure that, even with the time needed to execute | ||
299 | * this code, the next scheduled interrupt has been moved | ||
300 | * back to the future: */ | ||
301 | lost_ints++; | ||
302 | |||
303 | hpet_t1_cmp += lost_ints * ticks_per_int; | ||
304 | hpet_writel(hpet_t1_cmp, HPET_T1_CMP); | ||
305 | |||
306 | if (PIE_on) | ||
307 | PIE_count += lost_ints; | ||
308 | |||
309 | if (printk_ratelimit()) | ||
310 | printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", | ||
311 | hpet_rtc_int_freq); | ||
312 | } | ||
313 | } | ||
314 | |||
315 | /* | ||
316 | * The functions below are called from rtc driver. | ||
317 | * Return 0 if HPET is not being used. | ||
318 | * Otherwise do the necessary changes and return 1. | ||
319 | */ | ||
320 | int hpet_mask_rtc_irq_bit(unsigned long bit_mask) | ||
321 | { | ||
322 | if (!is_hpet_enabled()) | ||
323 | return 0; | ||
324 | |||
325 | if (bit_mask & RTC_UIE) | ||
326 | UIE_on = 0; | ||
327 | if (bit_mask & RTC_PIE) | ||
328 | PIE_on = 0; | ||
329 | if (bit_mask & RTC_AIE) | ||
330 | AIE_on = 0; | ||
331 | |||
332 | return 1; | ||
333 | } | ||
334 | |||
335 | int hpet_set_rtc_irq_bit(unsigned long bit_mask) | ||
336 | { | ||
337 | int timer_init_reqd = 0; | ||
338 | |||
339 | if (!is_hpet_enabled()) | ||
340 | return 0; | ||
341 | |||
342 | if (!(PIE_on | AIE_on | UIE_on)) | ||
343 | timer_init_reqd = 1; | ||
344 | |||
345 | if (bit_mask & RTC_UIE) { | ||
346 | UIE_on = 1; | ||
347 | } | ||
348 | if (bit_mask & RTC_PIE) { | ||
349 | PIE_on = 1; | ||
350 | PIE_count = 0; | ||
351 | } | ||
352 | if (bit_mask & RTC_AIE) { | ||
353 | AIE_on = 1; | ||
354 | } | ||
355 | |||
356 | if (timer_init_reqd) | ||
357 | hpet_rtc_timer_init(); | ||
358 | |||
359 | return 1; | ||
360 | } | ||
361 | |||
362 | int hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned char sec) | ||
363 | { | ||
364 | if (!is_hpet_enabled()) | ||
365 | return 0; | ||
366 | |||
367 | alarm_time.tm_hour = hrs; | ||
368 | alarm_time.tm_min = min; | ||
369 | alarm_time.tm_sec = sec; | ||
370 | |||
371 | return 1; | ||
372 | } | ||
373 | |||
374 | int hpet_set_periodic_freq(unsigned long freq) | ||
375 | { | ||
376 | if (!is_hpet_enabled()) | ||
377 | return 0; | ||
378 | |||
379 | PIE_freq = freq; | ||
380 | PIE_count = 0; | ||
381 | |||
382 | return 1; | ||
383 | } | ||
384 | |||
385 | int hpet_rtc_dropped_irq(void) | ||
386 | { | ||
387 | if (!is_hpet_enabled()) | ||
388 | return 0; | ||
389 | |||
390 | return 1; | ||
391 | } | ||
392 | |||
393 | irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) | ||
394 | { | ||
395 | struct rtc_time curr_time; | ||
396 | unsigned long rtc_int_flag = 0; | ||
397 | int call_rtc_interrupt = 0; | ||
398 | |||
399 | hpet_rtc_timer_reinit(); | ||
400 | |||
401 | if (UIE_on | AIE_on) { | ||
402 | rtc_get_rtc_time(&curr_time); | ||
403 | } | ||
404 | if (UIE_on) { | ||
405 | if (curr_time.tm_sec != prev_update_sec) { | ||
406 | /* Set update int info, call real rtc int routine */ | ||
407 | call_rtc_interrupt = 1; | ||
408 | rtc_int_flag = RTC_UF; | ||
409 | prev_update_sec = curr_time.tm_sec; | ||
410 | } | ||
411 | } | ||
412 | if (PIE_on) { | ||
413 | PIE_count++; | ||
414 | if (PIE_count >= hpet_rtc_int_freq/PIE_freq) { | ||
415 | /* Set periodic int info, call real rtc int routine */ | ||
416 | call_rtc_interrupt = 1; | ||
417 | rtc_int_flag |= RTC_PF; | ||
418 | PIE_count = 0; | ||
419 | } | ||
420 | } | ||
421 | if (AIE_on) { | ||
422 | if ((curr_time.tm_sec == alarm_time.tm_sec) && | ||
423 | (curr_time.tm_min == alarm_time.tm_min) && | ||
424 | (curr_time.tm_hour == alarm_time.tm_hour)) { | ||
425 | /* Set alarm int info, call real rtc int routine */ | ||
426 | call_rtc_interrupt = 1; | ||
427 | rtc_int_flag |= RTC_AF; | ||
428 | } | ||
429 | } | ||
430 | if (call_rtc_interrupt) { | ||
431 | rtc_int_flag |= (RTC_IRQF | (RTC_NUM_INTS << 8)); | ||
432 | rtc_interrupt(rtc_int_flag, dev_id); | ||
433 | } | ||
434 | return IRQ_HANDLED; | ||
435 | } | ||
436 | #endif | ||
437 | |||
438 | static int __init nohpet_setup(char *s) | ||
439 | { | ||
440 | nohpet = 1; | ||
441 | return 1; | ||
442 | } | ||
443 | |||
444 | __setup("nohpet", nohpet_setup); | ||
diff --git a/arch/x86/kernel/i8253_32.c b/arch/x86/kernel/i8253.c index ac15e4cbd9c..ac15e4cbd9c 100644 --- a/arch/x86/kernel/i8253_32.c +++ b/arch/x86/kernel/i8253.c | |||
diff --git a/arch/x86/kernel/time_64.c b/arch/x86/kernel/time_64.c index aca081c3788..e0134d6c88d 100644 --- a/arch/x86/kernel/time_64.c +++ b/arch/x86/kernel/time_64.c | |||
@@ -150,48 +150,6 @@ int update_persistent_clock(struct timespec now) | |||
150 | return set_rtc_mmss(now.tv_sec); | 150 | return set_rtc_mmss(now.tv_sec); |
151 | } | 151 | } |
152 | 152 | ||
153 | void main_timer_handler(void) | ||
154 | { | ||
155 | /* | ||
156 | * Here we are in the timer irq handler. We have irqs locally disabled (so we | ||
157 | * don't need spin_lock_irqsave()) but we don't know if the timer_bh is running | ||
158 | * on the other CPU, so we need a lock. We also need to lock the vsyscall | ||
159 | * variables, because both do_timer() and us change them -arca+vojtech | ||
160 | */ | ||
161 | |||
162 | write_seqlock(&xtime_lock); | ||
163 | |||
164 | /* | ||
165 | * Do the timer stuff. | ||
166 | */ | ||
167 | |||
168 | do_timer(1); | ||
169 | #ifndef CONFIG_SMP | ||
170 | update_process_times(user_mode(get_irq_regs())); | ||
171 | #endif | ||
172 | |||
173 | /* | ||
174 | * In the SMP case we use the local APIC timer interrupt to do the profiling, | ||
175 | * except when we simulate SMP mode on a uniprocessor system, in that case we | ||
176 | * have to call the local interrupt handler. | ||
177 | */ | ||
178 | |||
179 | if (!using_apic_timer) | ||
180 | smp_local_timer_interrupt(); | ||
181 | |||
182 | write_sequnlock(&xtime_lock); | ||
183 | } | ||
184 | |||
185 | static irqreturn_t timer_interrupt(int irq, void *dev_id) | ||
186 | { | ||
187 | if (apic_runs_main_timer > 1) | ||
188 | return IRQ_HANDLED; | ||
189 | main_timer_handler(); | ||
190 | if (using_apic_timer) | ||
191 | smp_send_timer_broadcast_ipi(); | ||
192 | return IRQ_HANDLED; | ||
193 | } | ||
194 | |||
195 | static irqreturn_t timer_event_interrupt(int irq, void *dev_id) | 153 | static irqreturn_t timer_event_interrupt(int irq, void *dev_id) |
196 | { | 154 | { |
197 | add_pda(irq0_irqs, 1); | 155 | add_pda(irq0_irqs, 1); |