From: Om Narasimhan <om.turyx@gmail.com>
To: linux-kernel@vger.kernel.org
Cc: randy.dunlap@oracle.com, omanakuttan.potty@sun.com,
clemens@ladisch.de, ak@muc.de, vojtech@suse.cz, bob.picco@hp.com,
venkatesh.pallipadi@intel.com, omanakuttan@imap.cc
Subject: HPET : Legacy Routing Replacement Enable - 3rd try.
Date: Wed, 25 Oct 2006 00:13:47 -0700 [thread overview]
Message-ID: <200610250013.48194.om.turyx@gmail.com> (raw)
I have incorporated Randy's comments.
CC-ing HPET developers.
Patch here.
Signed-off-by: Om Narasimhan <om.turyx@gmail.com>
Documentation/hpet.txt | 56 +++++++++++++++++++++++++++++++++++
Documentation/kernel-parameters.txt | 9 ++++++
arch/i386/kernel/acpi/boot.c | 18 +++++++++++
arch/i386/kernel/time_hpet.c | 3 +-
arch/x86_64/kernel/time.c | 16 +++++++---
include/asm-x86_64/hpet.h | 1 +
include/linux/acpi.h | 1 +
include/linux/hpet.h | 7 ++++
8 files changed, 105 insertions(+), 6 deletions(-)
diff --git a/Documentation/hpet.txt b/Documentation/hpet.txt
index b7a3dc3..ca62b69 100644
--- a/Documentation/hpet.txt
+++ b/Documentation/hpet.txt
@@ -298,3 +298,59 @@ members of the hpet_task structure befor
hpet_control simply vectors to the hpet_ioctl routine and has the same
commands and respective arguments as the user API. hpet_unregister
is used to terminate usage of the HPET timer reserved by hpet_register.
+
+ HPET Legacy Replacement Route option (hpet_lrr)
+
+HPET is capable of replacing the IRQ0 (connected INT0 PIN) routing for
+timer interrupt. The capability register (at offset 0 of HPET
+base address) has a bit specifying if HPET chip is capbale of doing
+this. OS can read the bit either from HW or ACPI table. (HPET ACPI
+description table -> Event Timer block -> bit 15, page 30 of HPET
+spec). Ideally (I think so!) BIOS should set the ACPI table than letting
+the OS read H/W, which gives the BIOS a way to configure either legacy
+or Legacy replacement modes.
+
+Typically the motherboard has BIOS configured / hardwired IRQ0 to INT0
+(pin of APIC) connection. Linux assumes IRQ0 connected to INT0 unless it is
+supplied using an override parameter in the MPTable. Some NVidia chipsets /
+BIOS initialization code had configured to override IRQ0 -> INT0 connection
+and later a parameter was introduce (acpi_skip_timer_override) to get IRQ0 ->
+INT0 connection right.
+
+But a number of bioses (both phoenix and AMI) are not working as
+expected. (I have an AMI BIOS which sets ACPI table bit 15 to 0 and then
+connect IRQ0 -> INT2 internally, Another bios I have sets the ACPI table bit
+15 to 0, but does not connect IRQ0 -> INT2. Both would result in a hang in
+calibrate_delay() since there would not be any timer interrupts So I have
+provided a command line parameter which overrides
+the BIOS ACPI entry. So, irrespctive of the BIOS' HPET ACPI Descriptor
+table settings, if the parameter hpet_lrr=[0,1] is specified, it takes
+precedence.
+
+* When to use this parameter?
+
+Some latest versions CK-804 (e.g),(Actually the code initializes the
+CK804 in the BIOS), would correctly set the HPET such that there would not
+be any interrupts on INT0. Linux does not handle this situation very well
+because in linux, if HW is LRR capable, it is enabled from the OS. Still the
+timer interrupt handler is setup for IRQ0. Under this situation, you can
+force the parameter hpet_lrr=1, so that IRQ2 is timer interrupts.
+
+[root@mophia ~]# cat /proc/interrupts | grep 2:
+ 2: 163 0 0 0 1 7
+207 955341 IO-APIC-edge timer
+
+[root@mophia ~]# uptime
+ 22:52:38 up 15 min, 2 users, load average: 0.00, 0.01, 0.02
+
+[root@mophia ~]# dmesg | grep -i MP-BIOS
+
+For 15 mts (900 sec), around 95k interrupts on timer looks kinda fine.
+
+* Known Bugs:
+I have tested it only with Nvidia CK-804. There seem to be some kind of timing
+issue between enabling the HPET with LRR set and start of tinerrupts. As a
+result of which, calibrate_delay() hangs because there are no interrupts. If
+you run into such a case, pass lpj=<bogomips * 500> as a work around. i.e, if
+your bogomips is 5000, pass lpj=2500000
+
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index dd00fd5..7916ff5 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -366,6 +366,15 @@ and is between 256 and 4096 characters.
hpet= [IA-32,HPET] option to disable HPET and use PIT.
Format: disable
+ hpet_lrr= [IA32,X86_64,HPET] Option to enable/disable the HPET
+ Legacy replacement route. Please read Documentation/
+ hpet.txt for more info.
+ Format : {"0" | "1"}
+ 0 -> Disables Legacy Route Replacement. (Default)
+ 1 -> Enables LRR. Please consult your BIOS
+ documentation before doing this.
+
+
cm206= [HW,CD]
Format: { auto | [<io>,][<irq>] }
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index ab974ff..2c5a798 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -82,6 +82,17 @@ EXPORT_SYMBOL(acpi_strict);
acpi_interrupt_flags acpi_sci_flags __initdata;
int acpi_sci_override_gsi __initdata;
int acpi_skip_timer_override __initdata;
+/* HPET Legacy routing replacement option passed through ACPI Table */
+int acpi_hpet_lrr;
+/* cmdline opt. for faulty bioses not setting ACPI HPET entry right */
+int hpet_lrr_force;
+
+static int hpet_lrr_setup (char *str)
+{
+ get_option(&str, &hpet_lrr_force);
+ return 1;
+}
+__setup ("hpet_lrr=", hpet_lrr_setup);
#ifdef CONFIG_X86_LOCAL_APIC
static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
@@ -669,6 +680,13 @@ #define HPET_RESOURCE_NAME_SIZE 9
"HPET %u", hpet_tbl->number);
hpet_res->end = (1 * 1024) - 1;
}
+ acpi_hpet_lrr = (hpet_tbl->id & ACPI_HPET_LRR_CAP) ? 1 : 0;
+ /* Print a message about the bios HPET ACPI Desc Table passed.
+ * LRR bit should not be set in the table unless IRQ0->INT2 is
+ * connected. But BIOS may be faulty ...
+ */
+ printk(KERN_INFO PREFIX "HPET id: %#x. ACPI LRR bit %s SET\n",
+ hpet_tbl->id, acpi_hpet_lrr ? "": "NOT");
#ifdef CONFIG_X86_64
vxtime.hpet_address = hpet_tbl->addr.addrl |
diff --git a/arch/i386/kernel/time_hpet.c b/arch/i386/kernel/time_hpet.c
index 1a2a979..01b2f67 100644
--- a/arch/i386/kernel/time_hpet.c
+++ b/arch/i386/kernel/time_hpet.c
@@ -94,7 +94,8 @@ static int hpet_timer_stop_set_go(unsign
* Go!
*/
cfg = hpet_readl(HPET_CFG);
- if (hpet_use_timer)
+ /* Ideally the following should be &&(acpi_hpet_lrr || hpet_lrr_force) */
+ if (hpet_use_timer && hpet_lrr_force)
cfg |= HPET_CFG_LEGACY;
cfg |= HPET_CFG_ENABLE;
hpet_writel(cfg, HPET_CFG);
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index 1ba5a44..0f5d990 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -46,9 +46,6 @@ #include <asm/apic.h>
#ifdef CONFIG_CPU_FREQ
static void cpufreq_delayed_get(void);
#endif
-extern void i8254_timer_resume(void);
-extern int using_apic_timer;
-
static char *timename = NULL;
DEFINE_SPINLOCK(rtc_lock);
@@ -783,7 +780,10 @@ static int hpet_timer_stop_set_go(unsign
HPET_TN_32BIT, HPET_T0_CFG);
hpet_writel(hpet_tick, HPET_T0_CMP); /* next interrupt */
hpet_writel(hpet_tick, HPET_T0_CMP); /* period */
- cfg |= HPET_CFG_LEGACY;
+ /* Ideal value (acpi_hpet_lrr || hpet_lrr_force) */
+ if (hpet_lrr_force)
+ cfg |= HPET_CFG_LEGACY;
+
}
/*
* Go!
@@ -887,6 +887,7 @@ time_cpu_notifier(struct notifier_block
void __init time_init(void)
{
+ int timer_irq = 0;
if (nohpet)
vxtime.hpet_address = 0;
@@ -906,6 +907,10 @@ void __init time_init(void)
tick_nsec = TICK_NSEC_HPET;
cpu_khz = hpet_calibrate_tsc();
timename = "HPET";
+ /* Ideal value is (acpi_hpet_lrr || hpet_lrr_force) */
+ if (hpet_lrr_force)
+ timer_irq = HPET_TIMER_LRR_IRQ;
+
#ifdef CONFIG_X86_PM_TIMER
} else if (pmtmr_ioport && !vxtime.hpet_address) {
vxtime_hz = PM_TIMER_FREQUENCY;
@@ -924,7 +929,8 @@ #endif
vxtime.tsc_quot = (USEC_PER_MSEC << US_SCALE) / cpu_khz;
vxtime.last_tsc = get_cycles_sync();
set_cyc2ns_scale(cpu_khz);
- setup_irq(0, &irq0);
+ printk(KERN_WARNING PREFIX "Registering Timer IRQ = %d\n", timer_irq);
+ setup_irq(timer_irq, &irq0);
hotcpu_notifier(time_cpu_notifier, 0);
time_cpu_notifier(NULL, CPU_ONLINE, (void *)(long)smp_processor_id());
diff --git a/include/asm-x86_64/hpet.h b/include/asm-x86_64/hpet.h
index b390984..2d18b39 100644
--- a/include/asm-x86_64/hpet.h
+++ b/include/asm-x86_64/hpet.h
@@ -37,6 +37,7 @@ #define HPET_CFG_ENABLE 0x001
#define HPET_CFG_LEGACY 0x002
#define HPET_LEGACY_8254 2
#define HPET_LEGACY_RTC 8
+#define HPET_TIMER_LRR_IRQ 2
#define HPET_TN_LEVEL 0x0002
#define HPET_TN_ENABLE 0x0004
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 2b0c955..62dab08 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -220,6 +220,7 @@ enum acpi_interrupt_id {
};
#define ACPI_SPACE_MEM 0
+#define ACPI_HPET_LRR_CAP 0x8000
struct acpi_gen_regaddr {
u8 space_id;
diff --git a/include/linux/hpet.h b/include/linux/hpet.h
index 707f7cb..6c31473 100644
--- a/include/linux/hpet.h
+++ b/include/linux/hpet.h
@@ -119,6 +119,13 @@ int hpet_register(struct hpet_task *, in
int hpet_unregister(struct hpet_task *);
int hpet_control(struct hpet_task *, unsigned int, unsigned long);
+
+/* these are used by time.c */
+extern void i8254_timer_resume(void);
+extern int using_apic_timer;
+extern int acpi_hpet_lrr;
+extern int hpet_lrr_force;
+
#endif /* __KERNEL__ */
struct hpet_info {
next reply other threads:[~2006-10-25 7:14 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-10-25 7:13 Om Narasimhan [this message]
2006-10-25 18:53 ` HPET : Legacy Routing Replacement Enable - 3rd try Andi Kleen
2006-10-25 20:09 ` Om Narasimhan
2006-10-25 20:13 ` Om Narasimhan
-- strict thread matches above, loose matches on Subject: below --
2006-10-25 20:21 Pallipadi, Venkatesh
2006-10-25 21:20 ` Om Narasimhan
2006-10-27 2:42 ` Andi Kleen
2006-10-27 5:57 ` Vojtech Pavlik
2006-10-27 6:29 ` Mika Penttilä
2006-10-27 7:03 ` Vojtech Pavlik
2006-10-27 22:31 ` Om Narasimhan
2006-10-27 6:11 ` Om Narasimhan
2006-10-27 14:59 ` Andi Kleen
2006-10-28 17:49 ` Andi Kleen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200610250013.48194.om.turyx@gmail.com \
--to=om.turyx@gmail.com \
--cc=ak@muc.de \
--cc=bob.picco@hp.com \
--cc=clemens@ladisch.de \
--cc=linux-kernel@vger.kernel.org \
--cc=omanakuttan.potty@sun.com \
--cc=omanakuttan@imap.cc \
--cc=randy.dunlap@oracle.com \
--cc=venkatesh.pallipadi@intel.com \
--cc=vojtech@suse.cz \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.