[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>
This commit is contained in:
Andi Kleen
2006-09-26 10:52:41 +02:00
committed by Andi Kleen
parent 8f60774a11
commit 0637a70a5d
12 changed files with 41 additions and 6 deletions

View File

@@ -1240,7 +1240,11 @@ running once the system is up.
bootloader. This is currently used on bootloader. This is currently used on
IXP2000 systems where the bus has to be IXP2000 systems where the bus has to be
configured a certain way for adjunct CPUs. configured a certain way for adjunct CPUs.
noearly [X86] Don't do any early type 1 scanning.
This might help on some broken boards which
machine check when some devices' config space
is read. But various workarounds are disabled
and some IOMMU drivers will not work.
pcmv= [HW,PCMCIA] BadgePAD 4 pcmv= [HW,PCMCIA] BadgePAD 4
pd. [PARIDE] pd. [PARIDE]

View File

@@ -48,7 +48,11 @@ void __init check_acpi_pci(void)
int num, slot, func; int num, slot, func;
/* Assume the machine supports type 1. If not it will /* Assume the machine supports type 1. If not it will
always read ffffffff and should not have any side effect. */ always read ffffffff and should not have any side effect.
Actually a few buggy systems can machine check. Allow the user
to disable it by command line option at least -AK */
if (!early_pci_allowed())
return;
/* Poor man's PCI discovery */ /* Poor man's PCI discovery */
for (num = 0; num < 32; num++) { for (num = 0; num < 32; num++) {

View File

@@ -242,6 +242,10 @@ char * __devinit pcibios_setup(char *str)
acpi_noirq_set(); acpi_noirq_set();
return NULL; return NULL;
} }
else if (!strcmp(str, "noearly")) {
pci_probe |= PCI_PROBE_NOEARLY;
return NULL;
}
#ifndef CONFIG_X86_VISWS #ifndef CONFIG_X86_VISWS
else if (!strcmp(str, "usepirqmask")) { else if (!strcmp(str, "usepirqmask")) {
pci_probe |= PCI_USE_PIRQ_MASK; pci_probe |= PCI_USE_PIRQ_MASK;

View File

@@ -1,6 +1,8 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/pci.h>
#include <asm/pci-direct.h> #include <asm/pci-direct.h>
#include <asm/io.h> #include <asm/io.h>
#include "pci.h"
/* Direct PCI access. This is used for PCI accesses in early boot before /* Direct PCI access. This is used for PCI accesses in early boot before
the PCI subsystem works. */ the PCI subsystem works. */
@@ -42,3 +44,9 @@ void write_pci_config(u8 bus, u8 slot, u8 func, u8 offset,
outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
outl(val, 0xcfc); outl(val, 0xcfc);
} }
int early_pci_allowed(void)
{
return (pci_probe & (PCI_PROBE_CONF1|PCI_PROBE_NOEARLY)) ==
PCI_PROBE_CONF1;
}

View File

@@ -17,6 +17,7 @@
#define PCI_PROBE_CONF2 0x0004 #define PCI_PROBE_CONF2 0x0004
#define PCI_PROBE_MMCONF 0x0008 #define PCI_PROBE_MMCONF 0x0008
#define PCI_PROBE_MASK 0x000f #define PCI_PROBE_MASK 0x000f
#define PCI_PROBE_NOEARLY 0x0010
#define PCI_NO_SORT 0x0100 #define PCI_NO_SORT 0x0100
#define PCI_BIOS_SORT 0x0200 #define PCI_BIOS_SORT 0x0200

View File

@@ -212,7 +212,7 @@ void __init iommu_hole_init(void)
u64 aper_base, last_aper_base = 0; u64 aper_base, last_aper_base = 0;
int valid_agp = 0; int valid_agp = 0;
if (iommu_aperture_disabled || !fix_aperture) if (iommu_aperture_disabled || !fix_aperture || !early_pci_allowed())
return; return;
printk("Checking aperture...\n"); printk("Checking aperture...\n");

View File

@@ -82,6 +82,10 @@ static struct chipset early_qrk[] = {
void __init early_quirks(void) void __init early_quirks(void)
{ {
int num, slot, func; int num, slot, func;
if (!early_pci_allowed())
return;
/* Poor man's PCI discovery */ /* Poor man's PCI discovery */
for (num = 0; num < 32; num++) { for (num = 0; num < 32; num++) {
for (slot = 0; slot < 32; slot++) { for (slot = 0; slot < 32; slot++) {

View File

@@ -924,6 +924,9 @@ void __init detect_calgary(void)
if (swiotlb || no_iommu || iommu_detected) if (swiotlb || no_iommu || iommu_detected)
return; return;
if (!early_pci_allowed())
return;
specified_table_size = determine_tce_table_size(end_pfn * PAGE_SIZE); specified_table_size = determine_tce_table_size(end_pfn * PAGE_SIZE);
for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) { for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) {

View File

@@ -20,6 +20,9 @@ static int __init vsmp_init(void)
void *address; void *address;
unsigned int cap, ctl; unsigned int cap, ctl;
if (!early_pci_allowed())
return 0;
/* Check if we are running on a ScaleMP vSMP box */ /* Check if we are running on a ScaleMP vSMP box */
if ((read_pci_config_16(0, 0x1f, 0, PCI_VENDOR_ID) != PCI_VENDOR_ID_SCALEMP) || if ((read_pci_config_16(0, 0x1f, 0, PCI_VENDOR_ID) != PCI_VENDOR_ID_SCALEMP) ||
(read_pci_config_16(0, 0x1f, 0, PCI_DEVICE_ID) != PCI_DEVICE_ID_SCALEMP_VSMP_CTL)) (read_pci_config_16(0, 0x1f, 0, PCI_DEVICE_ID) != PCI_DEVICE_ID_SCALEMP_VSMP_CTL))

View File

@@ -54,6 +54,9 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
nodes_clear(nodes_parsed); nodes_clear(nodes_parsed);
if (!early_pci_allowed())
return -1;
nb = find_northbridge(); nb = find_northbridge();
if (nb < 0) if (nb < 0)
return nb; return nb;

View File

@@ -953,13 +953,12 @@ static int __devinit pci_setup(char *str)
} }
str = k; str = k;
} }
return 1; return 0;
} }
early_param("pci", pci_setup);
device_initcall(pci_init); device_initcall(pci_init);
__setup("pci=", pci_setup);
#if defined(CONFIG_ISA) || defined(CONFIG_EISA) #if defined(CONFIG_ISA) || defined(CONFIG_EISA)
/* FIXME: Some boxes have multiple ISA bridges! */ /* FIXME: Some boxes have multiple ISA bridges! */
struct pci_dev *isa_bridge; struct pci_dev *isa_bridge;

View File

@@ -11,4 +11,6 @@ extern u8 read_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset);
extern u16 read_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset); extern u16 read_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset);
extern void write_pci_config(u8 bus, u8 slot, u8 func, u8 offset, u32 val); extern void write_pci_config(u8 bus, u8 slot, u8 func, u8 offset, u32 val);
extern int early_pci_allowed(void);
#endif #endif