diff options
Diffstat (limited to 'arch/x86/kernel/early-quirks.c')
-rw-r--r-- | arch/x86/kernel/early-quirks.c | 86 |
1 files changed, 65 insertions, 21 deletions
diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index 88bb83ec895f..b55258e49208 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c | |||
@@ -21,7 +21,30 @@ | |||
21 | #include <asm/gart.h> | 21 | #include <asm/gart.h> |
22 | #endif | 22 | #endif |
23 | 23 | ||
24 | static void __init via_bugs(void) | 24 | static void __init fix_hypertransport_config(int num, int slot, int func) |
25 | { | ||
26 | u32 htcfg; | ||
27 | /* | ||
28 | * we found a hypertransport bus | ||
29 | * make sure that we are broadcasting | ||
30 | * interrupts to all cpus on the ht bus | ||
31 | * if we're using extended apic ids | ||
32 | */ | ||
33 | htcfg = read_pci_config(num, slot, func, 0x68); | ||
34 | if (htcfg & (1 << 18)) { | ||
35 | printk(KERN_INFO "Detected use of extended apic ids on hypertransport bus\n"); | ||
36 | if ((htcfg & (1 << 17)) == 0) { | ||
37 | printk(KERN_INFO "Enabling hypertransport extended apic interrupt broadcast\n"); | ||
38 | printk(KERN_INFO "Note this is a bios bug, please contact your hw vendor\n"); | ||
39 | htcfg |= (1 << 17); | ||
40 | write_pci_config(num, slot, func, 0x68, htcfg); | ||
41 | } | ||
42 | } | ||
43 | |||
44 | |||
45 | } | ||
46 | |||
47 | static void __init via_bugs(int num, int slot, int func) | ||
25 | { | 48 | { |
26 | #ifdef CONFIG_GART_IOMMU | 49 | #ifdef CONFIG_GART_IOMMU |
27 | if ((end_pfn > MAX_DMA32_PFN || force_iommu) && | 50 | if ((end_pfn > MAX_DMA32_PFN || force_iommu) && |
@@ -44,7 +67,7 @@ static int __init nvidia_hpet_check(struct acpi_table_header *header) | |||
44 | #endif /* CONFIG_X86_IO_APIC */ | 67 | #endif /* CONFIG_X86_IO_APIC */ |
45 | #endif /* CONFIG_ACPI */ | 68 | #endif /* CONFIG_ACPI */ |
46 | 69 | ||
47 | static void __init nvidia_bugs(void) | 70 | static void __init nvidia_bugs(int num, int slot, int func) |
48 | { | 71 | { |
49 | #ifdef CONFIG_ACPI | 72 | #ifdef CONFIG_ACPI |
50 | #ifdef CONFIG_X86_IO_APIC | 73 | #ifdef CONFIG_X86_IO_APIC |
@@ -72,7 +95,7 @@ static void __init nvidia_bugs(void) | |||
72 | 95 | ||
73 | } | 96 | } |
74 | 97 | ||
75 | static void __init ati_bugs(void) | 98 | static void __init ati_bugs(int num, int slot, int func) |
76 | { | 99 | { |
77 | #ifdef CONFIG_X86_IO_APIC | 100 | #ifdef CONFIG_X86_IO_APIC |
78 | if (timer_over_8254 == 1) { | 101 | if (timer_over_8254 == 1) { |
@@ -83,15 +106,27 @@ static void __init ati_bugs(void) | |||
83 | #endif | 106 | #endif |
84 | } | 107 | } |
85 | 108 | ||
109 | #define QFLAG_APPLY_ONCE 0x1 | ||
110 | #define QFLAG_APPLIED 0x2 | ||
111 | #define QFLAG_DONE (QFLAG_APPLY_ONCE|QFLAG_APPLIED) | ||
86 | struct chipset { | 112 | struct chipset { |
87 | u16 vendor; | 113 | u32 vendor; |
88 | void (*f)(void); | 114 | u32 device; |
115 | u32 class; | ||
116 | u32 class_mask; | ||
117 | u32 flags; | ||
118 | void (*f)(int num, int slot, int func); | ||
89 | }; | 119 | }; |
90 | 120 | ||
91 | static struct chipset early_qrk[] __initdata = { | 121 | static struct chipset early_qrk[] __initdata = { |
92 | { PCI_VENDOR_ID_NVIDIA, nvidia_bugs }, | 122 | { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, |
93 | { PCI_VENDOR_ID_VIA, via_bugs }, | 123 | PCI_CLASS_BRIDGE_PCI, PCI_ANY_ID, QFLAG_APPLY_ONCE, nvidia_bugs }, |
94 | { PCI_VENDOR_ID_ATI, ati_bugs }, | 124 | { PCI_VENDOR_ID_VIA, PCI_ANY_ID, |
125 | PCI_CLASS_BRIDGE_PCI, PCI_ANY_ID, QFLAG_APPLY_ONCE, via_bugs }, | ||
126 | { PCI_VENDOR_ID_ATI, PCI_ANY_ID, | ||
127 | PCI_CLASS_BRIDGE_PCI, PCI_ANY_ID, QFLAG_APPLY_ONCE, ati_bugs }, | ||
128 | { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB, | ||
129 | PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, fix_hypertransport_config }, | ||
95 | {} | 130 | {} |
96 | }; | 131 | }; |
97 | 132 | ||
@@ -106,27 +141,36 @@ void __init early_quirks(void) | |||
106 | for (num = 0; num < 32; num++) { | 141 | for (num = 0; num < 32; num++) { |
107 | for (slot = 0; slot < 32; slot++) { | 142 | for (slot = 0; slot < 32; slot++) { |
108 | for (func = 0; func < 8; func++) { | 143 | for (func = 0; func < 8; func++) { |
109 | u32 class; | 144 | u16 class; |
110 | u32 vendor; | 145 | u16 vendor; |
146 | u16 device; | ||
111 | u8 type; | 147 | u8 type; |
112 | int i; | 148 | int i; |
113 | class = read_pci_config(num,slot,func, | 149 | |
150 | class = read_pci_config_16(num,slot,func, | ||
114 | PCI_CLASS_REVISION); | 151 | PCI_CLASS_REVISION); |
115 | if (class == 0xffffffff) | 152 | if (class == 0xffff) |
116 | break; | 153 | break; |
117 | 154 | ||
118 | if ((class >> 16) != PCI_CLASS_BRIDGE_PCI) | 155 | vendor = read_pci_config_16(num, slot, func, |
119 | continue; | ||
120 | |||
121 | vendor = read_pci_config(num, slot, func, | ||
122 | PCI_VENDOR_ID); | 156 | PCI_VENDOR_ID); |
123 | vendor &= 0xffff; | ||
124 | 157 | ||
125 | for (i = 0; early_qrk[i].f; i++) | 158 | device = read_pci_config_16(num, slot, func, |
126 | if (early_qrk[i].vendor == vendor) { | 159 | PCI_DEVICE_ID); |
127 | early_qrk[i].f(); | 160 | |
128 | return; | 161 | for(i=0;early_qrk[i].f != NULL;i++) { |
162 | if (((early_qrk[i].vendor == PCI_ANY_ID) || | ||
163 | (early_qrk[i].vendor == vendor)) && | ||
164 | ((early_qrk[i].device == PCI_ANY_ID) || | ||
165 | (early_qrk[i].device == device)) && | ||
166 | (!((early_qrk[i].class ^ class) & | ||
167 | early_qrk[i].class_mask))) { | ||
168 | if ((early_qrk[i].flags & QFLAG_DONE) != QFLAG_DONE) | ||
169 | early_qrk[i].f(num, slot, func); | ||
170 | early_qrk[i].flags |= QFLAG_APPLIED; | ||
171 | |||
129 | } | 172 | } |
173 | } | ||
130 | 174 | ||
131 | type = read_pci_config_byte(num, slot, func, | 175 | type = read_pci_config_byte(num, slot, func, |
132 | PCI_HEADER_TYPE); | 176 | PCI_HEADER_TYPE); |