[PATCH] Move early chipset quirks out to new file

They did not really belong into io_apic.c. Move them into a new file
and clean it up a bit.

Also remove outdated ATI quirk that was obsolete,

Signed-off-by: Andi Kleen <ak@suse.de>
This commit is contained in:
Andi Kleen 2006-09-26 10:52:30 +02:00 committed by Andi Kleen
parent edd9652296
commit dfa4698c50
5 changed files with 121 additions and 104 deletions

View File

@ -8,7 +8,7 @@ obj-y := process.o signal.o entry.o traps.o irq.o \
ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_x86_64.o \
x8664_ksyms.o i387.o syscall.o vsyscall.o \
setup64.o bootflag.o e820.o reboot.o quirks.o i8237.o \
pci-dma.o pci-nommu.o alternative.o
pci-dma.o pci-nommu.o alternative.o early-quirks.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-$(CONFIG_X86_MCE) += mce.o

View File

@ -0,0 +1,118 @@
/* Various workarounds for chipset bugs.
This code runs very early and can't use the regular PCI subsystem
The entries are keyed to PCI bridges which usually identify chipsets
uniquely.
This is only for whole classes of chipsets with specific problems which
need early invasive action (e.g. before the timers are initialized).
Most PCI device specific workarounds can be done later and should be
in standard PCI quirks
Mainboard specific bugs should be handled by DMI entries.
CPU specific bugs in setup.c */
#include <linux/pci.h>
#include <linux/acpi.h>
#include <linux/pci_ids.h>
#include <asm/pci-direct.h>
#include <asm/proto.h>
#include <asm/dma.h>
static void via_bugs(void)
{
#ifdef CONFIG_IOMMU
if ((end_pfn > MAX_DMA32_PFN || force_iommu) &&
!iommu_aperture_allowed) {
printk(KERN_INFO
"Looks like a VIA chipset. Disabling IOMMU. Override with iommu=allowed\n");
iommu_aperture_disabled = 1;
}
#endif
}
#ifdef CONFIG_ACPI
static int nvidia_hpet_detected __initdata;
static int __init nvidia_hpet_check(unsigned long phys, unsigned long size)
{
nvidia_hpet_detected = 1;
return 0;
}
#endif
static void nvidia_bugs(void)
{
#ifdef CONFIG_ACPI
/*
* All timer overrides on Nvidia are
* wrong unless HPET is enabled.
*/
nvidia_hpet_detected = 0;
acpi_table_parse(ACPI_HPET, nvidia_hpet_check);
if (nvidia_hpet_detected == 0) {
acpi_skip_timer_override = 1;
printk(KERN_INFO "Nvidia board "
"detected. Ignoring ACPI "
"timer override.\n");
}
#endif
/* RED-PEN skip them on mptables too? */
}
static void ati_bugs(void)
{
#if 1 /* for testing */
printk("ATI board detected\n");
#endif
/* No bugs right now */
}
struct chipset {
u16 vendor;
void (*f)(void);
};
static struct chipset early_qrk[] = {
{ PCI_VENDOR_ID_NVIDIA, nvidia_bugs },
{ PCI_VENDOR_ID_VIA, via_bugs },
{ PCI_VENDOR_ID_ATI, ati_bugs },
{}
};
void __init early_quirks(void)
{
int num, slot, func;
/* Poor man's PCI discovery */
for (num = 0; num < 32; num++) {
for (slot = 0; slot < 32; slot++) {
for (func = 0; func < 8; func++) {
u32 class;
u32 vendor;
u8 type;
int i;
class = read_pci_config(num,slot,func,
PCI_CLASS_REVISION);
if (class == 0xffffffff)
break;
if ((class >> 16) != PCI_CLASS_BRIDGE_PCI)
continue;
vendor = read_pci_config(num, slot, func,
PCI_VENDOR_ID);
vendor &= 0xffff;
for (i = 0; early_qrk[i].f; i++)
if (early_qrk[i].vendor == vendor) {
early_qrk[i].f();
return;
}
type = read_pci_config_byte(num, slot, func,
PCI_HEADER_TYPE);
if (!(type & 0x80))
break;
}
}
}
}

View File

@ -280,107 +280,6 @@ static int __init setup_enable_8254_timer(char *s)
__setup("disable_8254_timer", setup_disable_8254_timer);
__setup("enable_8254_timer", setup_enable_8254_timer);
#include <asm/pci-direct.h>
#include <linux/pci_ids.h>
#include <linux/pci.h>
#ifdef CONFIG_ACPI
static int nvidia_hpet_detected __initdata;
static int __init nvidia_hpet_check(unsigned long phys, unsigned long size)
{
nvidia_hpet_detected = 1;
return 0;
}
#endif
/* Temporary Hack. Nvidia and VIA boards currently only work with IO-APIC
off. Check for an Nvidia or VIA PCI bridge and turn it off.
Use pci direct infrastructure because this runs before the PCI subsystem.
Can be overwritten with "apic"
And another hack to disable the IOMMU on VIA chipsets.
... and others. Really should move this somewhere else.
Kludge-O-Rama. */
void __init check_ioapic(void)
{
int num,slot,func;
/* Poor man's PCI discovery */
for (num = 0; num < 32; num++) {
for (slot = 0; slot < 32; slot++) {
for (func = 0; func < 8; func++) {
u32 class;
u32 vendor;
u8 type;
class = read_pci_config(num,slot,func,
PCI_CLASS_REVISION);
if (class == 0xffffffff)
break;
if ((class >> 16) != PCI_CLASS_BRIDGE_PCI)
continue;
vendor = read_pci_config(num, slot, func,
PCI_VENDOR_ID);
vendor &= 0xffff;
switch (vendor) {
case PCI_VENDOR_ID_VIA:
#ifdef CONFIG_IOMMU
if ((end_pfn > MAX_DMA32_PFN ||
force_iommu) &&
!iommu_aperture_allowed) {
printk(KERN_INFO
"Looks like a VIA chipset. Disabling IOMMU. Override with \"iommu=allowed\"\n");
iommu_aperture_disabled = 1;
}
#endif
return;
case PCI_VENDOR_ID_NVIDIA:
#ifdef CONFIG_ACPI
/*
* All timer overrides on Nvidia are
* wrong unless HPET is enabled.
*/
nvidia_hpet_detected = 0;
acpi_table_parse(ACPI_HPET,
nvidia_hpet_check);
if (nvidia_hpet_detected == 0) {
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;
/* This should be actually default, but
for 2.6.16 let's do it for ATI only where
it's really needed. */
case PCI_VENDOR_ID_ATI:
if (timer_over_8254 == 1) {
timer_over_8254 = 0;
printk(KERN_INFO
"ATI board detected. Disabling timer routing over 8254.\n");
}
return;
}
/* No multi-function device? */
type = read_pci_config_byte(num,slot,func,
PCI_HEADER_TYPE);
if (!(type & 0x80))
break;
}
}
}
}
/*
* Find the IRQ entry number of a certain pin.

View File

@ -653,7 +653,7 @@ void __init setup_arch(char **cmdline_p)
paging_init();
check_ioapic();
early_quirks();
/*
* set this early, so we dont allocate cpu0

View File

@ -92,7 +92,7 @@ extern void syscall32_cpu_init(void);
extern void setup_node_bootmem(int nodeid, unsigned long start, unsigned long end);
extern void check_ioapic(void);
extern void early_quirks(void);
extern void check_efer(void);
extern int unhandled_signal(struct task_struct *tsk, int sig);