Skip to content

Commit

Permalink
[PATCH] Move early chipset quirks out to new file
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Andi Kleen authored and Andi Kleen committed Sep 26, 2006
1 parent edd9652 commit dfa4698
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 104 deletions.
2 changes: 1 addition & 1 deletion arch/x86_64/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
118 changes: 118 additions & 0 deletions arch/x86_64/kernel/early-quirks.c
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
}
101 changes: 0 additions & 101 deletions arch/x86_64/kernel/io_apic.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion arch/x86_64/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion include/asm-x86_64/proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit dfa4698

Please sign in to comment.