aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2006-09-26 04:52:41 -0400
committerAndi Kleen <andi@basil.nowhere.org>2006-09-26 04:52:41 -0400
commit0637a70a5db98182d9ad3d6ae1ee30acf20afde9 (patch)
tree36b625e24f3fe11a97cd9926ca2be6b2df1cbf89
parent8f60774a116ced9b73ae3913d511687889efe725 (diff)
[PATCH] x86: Allow disabling early pci scans with pci=noearly or disallowing conf1
Some buggy systems can machine check when config space accesses happen for some non existent devices. i386/x86-64 do some early device scans that might trigger this. Allow pci=noearly to disable this. Also when type 1 is disabling also don't do any early accesses which are always type1. This moves the pci= configuration parsing to be a early parameter. I don't think this can break anything because it only changes a single global that is only used by PCI. Cc: gregkh@suse.de Cc: Trammell Hudson <hudson@osresearch.net> Signed-off-by: Andi Kleen <ak@suse.de>
-rw-r--r--Documentation/kernel-parameters.txt6
-rw-r--r--arch/i386/kernel/acpi/earlyquirk.c6
-rw-r--r--arch/i386/pci/common.c4
-rw-r--r--arch/i386/pci/early.c8
-rw-r--r--arch/i386/pci/pci.h1
-rw-r--r--arch/x86_64/kernel/aperture.c2
-rw-r--r--arch/x86_64/kernel/early-quirks.c4
-rw-r--r--arch/x86_64/kernel/pci-calgary.c3
-rw-r--r--arch/x86_64/kernel/vsmp.c3
-rw-r--r--arch/x86_64/mm/k8topology.c3
-rw-r--r--drivers/pci/pci.c5
-rw-r--r--include/asm-x86_64/pci-direct.h2
12 files changed, 41 insertions, 6 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 71d05f481727..4ae99f6e9938 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1240,7 +1240,11 @@ running once the system is up.
1240 bootloader. This is currently used on 1240 bootloader. This is currently used on
1241 IXP2000 systems where the bus has to be 1241 IXP2000 systems where the bus has to be
1242 configured a certain way for adjunct CPUs. 1242 configured a certain way for adjunct CPUs.
1243 1243 noearly [X86] Don't do any early type 1 scanning.
1244 This might help on some broken boards which
1245 machine check when some devices' config space
1246 is read. But various workarounds are disabled
1247 and some IOMMU drivers will not work.
1244 pcmv= [HW,PCMCIA] BadgePAD 4 1248 pcmv= [HW,PCMCIA] BadgePAD 4
1245 1249
1246 pd. [PARIDE] 1250 pd. [PARIDE]
diff --git a/arch/i386/kernel/acpi/earlyquirk.c b/arch/i386/kernel/acpi/earlyquirk.c
index 1649a175a206..fe799b11ac0a 100644
--- a/arch/i386/kernel/acpi/earlyquirk.c
+++ b/arch/i386/kernel/acpi/earlyquirk.c
@@ -48,7 +48,11 @@ void __init check_acpi_pci(void)
48 int num, slot, func; 48 int num, slot, func;
49 49
50 /* Assume the machine supports type 1. If not it will 50 /* Assume the machine supports type 1. If not it will
51 always read ffffffff and should not have any side effect. */ 51 always read ffffffff and should not have any side effect.
52 Actually a few buggy systems can machine check. Allow the user
53 to disable it by command line option at least -AK */
54 if (!early_pci_allowed())
55 return;
52 56
53 /* Poor man's PCI discovery */ 57 /* Poor man's PCI discovery */
54 for (num = 0; num < 32; num++) { 58 for (num = 0; num < 32; num++) {
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c
index 0a362e3aeac5..68bce194e688 100644
--- a/arch/i386/pci/common.c
+++ b/arch/i386/pci/common.c
@@ -242,6 +242,10 @@ char * __devinit pcibios_setup(char *str)
242 acpi_noirq_set(); 242 acpi_noirq_set();
243 return NULL; 243 return NULL;
244 } 244 }
245 else if (!strcmp(str, "noearly")) {
246 pci_probe |= PCI_PROBE_NOEARLY;
247 return NULL;
248 }
245#ifndef CONFIG_X86_VISWS 249#ifndef CONFIG_X86_VISWS
246 else if (!strcmp(str, "usepirqmask")) { 250 else if (!strcmp(str, "usepirqmask")) {
247 pci_probe |= PCI_USE_PIRQ_MASK; 251 pci_probe |= PCI_USE_PIRQ_MASK;
diff --git a/arch/i386/pci/early.c b/arch/i386/pci/early.c
index b1f7f40d809b..713d6c866cae 100644
--- a/arch/i386/pci/early.c
+++ b/arch/i386/pci/early.c
@@ -1,6 +1,8 @@
1#include <linux/kernel.h> 1#include <linux/kernel.h>
2#include <linux/pci.h>
2#include <asm/pci-direct.h> 3#include <asm/pci-direct.h>
3#include <asm/io.h> 4#include <asm/io.h>
5#include "pci.h"
4 6
5/* Direct PCI access. This is used for PCI accesses in early boot before 7/* Direct PCI access. This is used for PCI accesses in early boot before
6 the PCI subsystem works. */ 8 the PCI subsystem works. */
@@ -42,3 +44,9 @@ void write_pci_config(u8 bus, u8 slot, u8 func, u8 offset,
42 outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); 44 outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
43 outl(val, 0xcfc); 45 outl(val, 0xcfc);
44} 46}
47
48int early_pci_allowed(void)
49{
50 return (pci_probe & (PCI_PROBE_CONF1|PCI_PROBE_NOEARLY)) ==
51 PCI_PROBE_CONF1;
52}
diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h
index 8a7cf1f23684..1814f74569c6 100644
--- a/arch/i386/pci/pci.h
+++ b/arch/i386/pci/pci.h
@@ -17,6 +17,7 @@
17#define PCI_PROBE_CONF2 0x0004 17#define PCI_PROBE_CONF2 0x0004
18#define PCI_PROBE_MMCONF 0x0008 18#define PCI_PROBE_MMCONF 0x0008
19#define PCI_PROBE_MASK 0x000f 19#define PCI_PROBE_MASK 0x000f
20#define PCI_PROBE_NOEARLY 0x0010
20 21
21#define PCI_NO_SORT 0x0100 22#define PCI_NO_SORT 0x0100
22#define PCI_BIOS_SORT 0x0200 23#define PCI_BIOS_SORT 0x0200
diff --git a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c
index f851e1f9c82a..b487396c4c5b 100644
--- a/arch/x86_64/kernel/aperture.c
+++ b/arch/x86_64/kernel/aperture.c
@@ -212,7 +212,7 @@ void __init iommu_hole_init(void)
212 u64 aper_base, last_aper_base = 0; 212 u64 aper_base, last_aper_base = 0;
213 int valid_agp = 0; 213 int valid_agp = 0;
214 214
215 if (iommu_aperture_disabled || !fix_aperture) 215 if (iommu_aperture_disabled || !fix_aperture || !early_pci_allowed())
216 return; 216 return;
217 217
218 printk("Checking aperture...\n"); 218 printk("Checking aperture...\n");
diff --git a/arch/x86_64/kernel/early-quirks.c b/arch/x86_64/kernel/early-quirks.c
index d637cff1c4b1..208e38a372c1 100644
--- a/arch/x86_64/kernel/early-quirks.c
+++ b/arch/x86_64/kernel/early-quirks.c
@@ -82,6 +82,10 @@ static struct chipset early_qrk[] = {
82void __init early_quirks(void) 82void __init early_quirks(void)
83{ 83{
84 int num, slot, func; 84 int num, slot, func;
85
86 if (!early_pci_allowed())
87 return;
88
85 /* Poor man's PCI discovery */ 89 /* Poor man's PCI discovery */
86 for (num = 0; num < 32; num++) { 90 for (num = 0; num < 32; num++) {
87 for (slot = 0; slot < 32; slot++) { 91 for (slot = 0; slot < 32; slot++) {
diff --git a/arch/x86_64/kernel/pci-calgary.c b/arch/x86_64/kernel/pci-calgary.c
index 466588f95601..cfb09b07ae99 100644
--- a/arch/x86_64/kernel/pci-calgary.c
+++ b/arch/x86_64/kernel/pci-calgary.c
@@ -924,6 +924,9 @@ void __init detect_calgary(void)
924 if (swiotlb || no_iommu || iommu_detected) 924 if (swiotlb || no_iommu || iommu_detected)
925 return; 925 return;
926 926
927 if (!early_pci_allowed())
928 return;
929
927 specified_table_size = determine_tce_table_size(end_pfn * PAGE_SIZE); 930 specified_table_size = determine_tce_table_size(end_pfn * PAGE_SIZE);
928 931
929 for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) { 932 for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) {
diff --git a/arch/x86_64/kernel/vsmp.c b/arch/x86_64/kernel/vsmp.c
index 92f70c74965f..044e852bd25e 100644
--- a/arch/x86_64/kernel/vsmp.c
+++ b/arch/x86_64/kernel/vsmp.c
@@ -20,6 +20,9 @@ static int __init vsmp_init(void)
20 void *address; 20 void *address;
21 unsigned int cap, ctl; 21 unsigned int cap, ctl;
22 22
23 if (!early_pci_allowed())
24 return 0;
25
23 /* Check if we are running on a ScaleMP vSMP box */ 26 /* Check if we are running on a ScaleMP vSMP box */
24 if ((read_pci_config_16(0, 0x1f, 0, PCI_VENDOR_ID) != PCI_VENDOR_ID_SCALEMP) || 27 if ((read_pci_config_16(0, 0x1f, 0, PCI_VENDOR_ID) != PCI_VENDOR_ID_SCALEMP) ||
25 (read_pci_config_16(0, 0x1f, 0, PCI_DEVICE_ID) != PCI_DEVICE_ID_SCALEMP_VSMP_CTL)) 28 (read_pci_config_16(0, 0x1f, 0, PCI_DEVICE_ID) != PCI_DEVICE_ID_SCALEMP_VSMP_CTL))
diff --git a/arch/x86_64/mm/k8topology.c b/arch/x86_64/mm/k8topology.c
index 7c45c2d2b8b2..5cf594f9230d 100644
--- a/arch/x86_64/mm/k8topology.c
+++ b/arch/x86_64/mm/k8topology.c
@@ -54,6 +54,9 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
54 54
55 nodes_clear(nodes_parsed); 55 nodes_clear(nodes_parsed);
56 56
57 if (!early_pci_allowed())
58 return -1;
59
57 nb = find_northbridge(); 60 nb = find_northbridge();
58 if (nb < 0) 61 if (nb < 0)
59 return nb; 62 return nb;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 9f79dd6d51ab..684deb6b03aa 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -953,13 +953,12 @@ static int __devinit pci_setup(char *str)
953 } 953 }
954 str = k; 954 str = k;
955 } 955 }
956 return 1; 956 return 0;
957} 957}
958early_param("pci", pci_setup);
958 959
959device_initcall(pci_init); 960device_initcall(pci_init);
960 961
961__setup("pci=", pci_setup);
962
963#if defined(CONFIG_ISA) || defined(CONFIG_EISA) 962#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
964/* FIXME: Some boxes have multiple ISA bridges! */ 963/* FIXME: Some boxes have multiple ISA bridges! */
965struct pci_dev *isa_bridge; 964struct pci_dev *isa_bridge;
diff --git a/include/asm-x86_64/pci-direct.h b/include/asm-x86_64/pci-direct.h
index 9d916cdaa18e..eba9cb471df3 100644
--- a/include/asm-x86_64/pci-direct.h
+++ b/include/asm-x86_64/pci-direct.h
@@ -11,4 +11,6 @@ extern u8 read_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset);
11extern u16 read_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset); 11extern u16 read_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset);
12extern void write_pci_config(u8 bus, u8 slot, u8 func, u8 offset, u32 val); 12extern void write_pci_config(u8 bus, u8 slot, u8 func, u8 offset, u32 val);
13 13
14extern int early_pci_allowed(void);
15
14#endif 16#endif