#include <linux/mm.h>
#include <linux/delay.h>
#include <linux/bootmem.h>
-#include <linux/smp_lock.h>
#include <linux/interrupt.h>
#include <linux/mc146818rtc.h>
#include <linux/kernel_stat.h>
static int local_apic_timer_verify_ok;
/* Disable local APIC timer from the kernel commandline or via dmi quirk */
static int local_apic_timer_disabled;
+/* Local APIC timer works in C2 */
+int local_apic_timer_c2_ok;
+EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok);
/*
* Debug level, exported for io_apic.c
return lapic_get_version() >= 0x14;
}
+void apic_wait_icr_idle(void)
+{
+ while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
+ cpu_relax();
+}
+
+unsigned long safe_apic_wait_icr_idle(void)
+{
+ unsigned long send_status;
+ int timeout;
+
+ timeout = 0;
+ do {
+ send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
+ if (!send_status)
+ break;
+ udelay(100);
+ } while (timeout++ < 1000);
+
+ return send_status;
+}
+
/**
* enable_NMI_through_LVT0 - enable NMI through local vector table 0
*/
clockevents_register_device(levt);
}
-/*
- * Detect systems with known broken BIOS implementations
- */
-static int __init lapic_check_broken_bios(struct dmi_system_id *d)
-{
- printk(KERN_NOTICE "%s detected: disabling lapic timer.\n",
- d->ident);
- local_apic_timer_disabled = 1;
- return 0;
-}
-
-static struct dmi_system_id __initdata broken_bios_dmi_table[] = {
- {
- /*
- * BIOS exports only C1 state, but uses deeper power
- * modes behind the kernels back.
- */
- .callback = lapic_check_broken_bios,
- .ident = "HP nx6325",
- .matches = {
- DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6325"),
- },
- },
- {}
-};
-
/*
* In this functions we calibrate APIC bus clocks to the external timer.
*
long delta, deltapm;
int pm_referenced = 0;
- /* Detect know broken systems */
- dmi_check_system(broken_bios_dmi_table);
+ if (boot_cpu_has(X86_FEATURE_LAPIC_TIMER_BROKEN))
+ local_apic_timer_disabled = 1;
/*
* The local apic timer can be disabled via the kernel
- * commandline or from the dmi quirk above. Register the lapic
+ * commandline or from the test above. Register the lapic
* timer as a dummy clock event source on SMP systems, so the
* broadcast mechanism is used. On UP systems simply ignore it.
*/
apic_printk(APIC_VERBOSE, "... jiffies result ok\n");
else
local_apic_timer_verify_ok = 0;
- }
+ } else
+ local_irq_enable();
if (!local_apic_timer_verify_ok) {
printk(KERN_WARNING
}
early_param("nolapic_timer", parse_disable_lapic_timer);
+static int __init parse_lapic_timer_c2_ok(char *arg)
+{
+ local_apic_timer_c2_ok = 1;
+ return 0;
+}
+early_param("lapic_timer_c2_ok", parse_lapic_timer_c2_ok);
+
static int __init apic_set_verbosity(char *str)
{
if (strcmp("debug", str) == 0)