[patch 2.6.14-rc2] x86_64: Detect ATI timer quirk automatically

From: Chuck Ebbert
Date: Fri Sep 23 2005 - 03:46:58 EST


This patch is only lightly tested so far. It boots and works on IOAPIC + ACPI.
I tested with and without kernel option "enable_timer_pin_1" and it works as
expected on the affected ATI chipsets.

It's unknown whether disabling the ACPI timer override is a good idea in all cases.
Should I add a command-line override for it?

Since I had to rearrange the code, I cleaned it up a bit as well. I couldn't
test whether I broke the existing quirk code, though.

Patch: Automatically detect and enable timer quirk for ATI chipsets
Signed-off-by: Chuck Ebbert <76306.1226@xxxxxxxxxxxxxx>

arch/x86_64/kernel/io_apic.c | 105 +++++++++++++++++++++++++++++++------------
1 files changed, 77 insertions(+), 28 deletions(-)

--- 2.6.14-rc2-64.orig/arch/x86_64/kernel/io_apic.c
+++ 2.6.14-rc2-64/arch/x86_64/kernel/io_apic.c
@@ -252,7 +252,66 @@ __setup("apic", enable_ioapic_setup);

And another hack to disable the IOMMU on VIA chipsets.

+ Yet another to fix double speed clock on ATI RS480.
+
Kludge-O-Rama. */
+
+static int __init host_bridge_quirk(int vendor, int device)
+{
+ switch (vendor) {
+
+ case PCI_VENDOR_ID_ATI:
+ /* Some ATI chipsets have doubly-connected timers. Disable
+ IOAPIC timer pin. Also, ignore ACPI timer override. */
+ if (device == PCI_DEVICE_ID_ATI_RS480 ||
+ device == 0x5951 /* RED-PEN: what is this? */ ) {
+#ifdef CONFIG_ACPI
+ printk(KERN_INFO "Ignoring ACPI timer override.\n");
+ acpi_skip_timer_override = 1;
+#endif
+ if (++disable_timer_pin_1 <= 0)
+ return 1;
+ printk(KERN_INFO "ATI host bridge timer quirk detected."
+ " Disabling IOAPIC timer pin.\n");
+ return 1;
+ }
+ break;
+
+ }
+ return 0;
+}
+
+static int __init pci_bridge_quirk(int vendor, int device)
+{
+ switch (vendor) {
+
+ case PCI_VENDOR_ID_VIA:
+#ifdef CONFIG_GART_IOMMU
+ if ((end_pfn >= (0xffffffff>>PAGE_SHIFT) || force_iommu) &&
+ !iommu_aperture_allowed) {
+ printk(KERN_INFO "Looks like a VIA chipset."
+ " Disabling IOMMU."
+ " Overwrite with \"iommu=allowed\"\n");
+ iommu_aperture_disabled = 1;
+ }
+#endif
+ return 1;
+
+ case PCI_VENDOR_ID_NVIDIA:
+#ifdef CONFIG_ACPI
+ /* All timer overrides on Nvidia
+ seem to be wrong. Skip them. */
+ /* RED-PEN skip them on mptables too? */
+ printk(KERN_INFO "Nvidia board detected."
+ " Ignoring ACPI timer override.\n");
+ acpi_skip_timer_override = 1;
+#endif
+ return 1;
+
+ }
+ return 0;
+}
+
void __init check_ioapic(void)
{
int num,slot,func;
@@ -264,42 +323,32 @@ void __init check_ioapic(void)
for (slot = 0; slot < 32; slot++) {
for (func = 0; func < 8; func++) {
u32 class;
- u32 vendor;
+ u32 vend_dev;
+ u16 vendor, device;
u8 type;
+
class = read_pci_config(num,slot,func,
PCI_CLASS_REVISION);
if (class == 0xffffffff)
break;
+ class >>= 16;

- if ((class >> 16) != PCI_CLASS_BRIDGE_PCI)
+ if (class != PCI_CLASS_BRIDGE_PCI &&
+ class != PCI_CLASS_BRIDGE_HOST)
continue;

- vendor = read_pci_config(num, slot, func,
- PCI_VENDOR_ID);
- vendor &= 0xffff;
- switch (vendor) {
- case PCI_VENDOR_ID_VIA:
-#ifdef CONFIG_GART_IOMMU
- if ((end_pfn >= (0xffffffff>>PAGE_SHIFT) ||
- force_iommu) &&
- !iommu_aperture_allowed) {
- printk(KERN_INFO
- "Looks like a VIA chipset. Disabling IOMMU. Overwrite with \"iommu=allowed\"\n");
- iommu_aperture_disabled = 1;
- }
-#endif
- return;
- case PCI_VENDOR_ID_NVIDIA:
-#ifdef CONFIG_ACPI
- /* All timer overrides on Nvidia
- seem to be wrong. Skip them. */
- acpi_skip_timer_override = 1;
- printk(KERN_INFO
- "Nvidia board detected. Ignoring ACPI timer override.\n");
-#endif
- /* RED-PEN skip them on mptables too? */
- return;
- }
+ vend_dev = read_pci_config(num, slot, func,
+ PCI_VENDOR_ID);
+ vendor = vend_dev & 0xffff;
+ device = vend_dev >> 16;
+
+ if (class == PCI_CLASS_BRIDGE_HOST)
+ if (host_bridge_quirk(vendor, device))
+ return;
+
+ if (class == PCI_CLASS_BRIDGE_PCI)
+ if (pci_bridge_quirk(vendor, device))
+ return;

/* No multi-function device? */
type = read_pci_config_byte(num,slot,func,
__
Chuck
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/