linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / arch / i386 / pci / mmconfig.c
index 972180f..0ee8a98 100644 (file)
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/acpi.h>
-#include <asm/e820.h>
 #include "pci.h"
 
-/* aperture is up to 256MB but BIOS may reserve less */
-#define MMCONFIG_APER_MIN      (2 * 1024*1024)
-#define MMCONFIG_APER_MAX      (256 * 1024*1024)
-
-/* Assume systems with more busses have correct MCFG */
-#define MAX_CHECK_BUS 16
-
 #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))
 
 /* The base address of the last MMCONFIG device accessed */
 static u32 mmcfg_last_accessed_device;
 
-static DECLARE_BITMAP(fallback_slots, MAX_CHECK_BUS*32);
+static DECLARE_BITMAP(fallback_slots, 32);
 
 /*
  * Functions for accessing PCI configuration space with MMCONFIG accesses
@@ -37,8 +29,8 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
        int cfg_num = -1;
        struct acpi_table_mcfg_config *cfg;
 
-       if (seg == 0 && bus < MAX_CHECK_BUS &&
-           test_bit(PCI_SLOT(devfn) + 32*bus, fallback_slots))
+       if (seg == 0 && bus == 0 &&
+           test_bit(PCI_SLOT(devfn), fallback_slots))
                return 0;
 
        while (1) {
@@ -82,10 +74,8 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
        unsigned long flags;
        u32 base;
 
-       if ((bus > 255) || (devfn > 255) || (reg > 4095)) {
-               *value = -1;
+       if (!value || (bus > 255) || (devfn > 255) || (reg > 4095))
                return -EINVAL;
-       }
 
        base = get_base_addr(seg, bus, devfn);
        if (!base)
@@ -156,60 +146,51 @@ static struct pci_raw_ops pci_mmcfg = {
    Normally this can be expressed in the MCFG by not listing them
    and assigning suitable _SEGs, but this isn't implemented in some BIOS.
    Instead try to discover all devices on bus 0 that are unreachable using MM
-   and fallback for them. */
+   and fallback for them.
+   We only do this for bus 0/seg 0 */
 static __init void unreachable_devices(void)
 {
-       int i, k;
+       int i;
        unsigned long flags;
 
-       for (k = 0; k < MAX_CHECK_BUS; k++) {
-               for (i = 0; i < 32; i++) {
-                       u32 val1;
-                       u32 addr;
-
-                       pci_conf1_read(0, k, PCI_DEVFN(i, 0), 0, 4, &val1);
-                       if (val1 == 0xffffffff)
-                               continue;
-
-                       /* Locking probably not needed, but safer */
-                       spin_lock_irqsave(&pci_config_lock, flags);
-                       addr = get_base_addr(0, k, PCI_DEVFN(i, 0));
-                       if (addr != 0)
-                               pci_exp_set_dev_base(addr, k, PCI_DEVFN(i, 0));
-                       if (addr == 0 ||
-                           readl((u32 __iomem *)mmcfg_virt_addr) != val1) {
-                               set_bit(i + 32*k, fallback_slots);
-                               printk(KERN_NOTICE
-                       "PCI: No mmconfig possible on %x:%x\n", k, i);
-                       }
-                       spin_unlock_irqrestore(&pci_config_lock, flags);
-               }
+       for (i = 0; i < 32; i++) {
+               u32 val1;
+               u32 addr;
+
+               pci_conf1_read(0, 0, PCI_DEVFN(i, 0), 0, 4, &val1);
+               if (val1 == 0xffffffff)
+                       continue;
+
+               /* Locking probably not needed, but safer */
+               spin_lock_irqsave(&pci_config_lock, flags);
+               addr = get_base_addr(0, 0, PCI_DEVFN(i, 0));
+               if (addr != 0)
+                       pci_exp_set_dev_base(addr, 0, PCI_DEVFN(i, 0));
+               if (addr == 0 || readl((u32 __iomem *)mmcfg_virt_addr) != val1)
+                       set_bit(i, fallback_slots);
+               spin_unlock_irqrestore(&pci_config_lock, flags);
        }
 }
 
-void __init pci_mmcfg_init(void)
+static int __init pci_mmcfg_init(void)
 {
        if ((pci_probe & PCI_PROBE_MMCONF) == 0)
-               return;
+               goto out;
 
        acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
        if ((pci_mmcfg_config_num == 0) ||
            (pci_mmcfg_config == NULL) ||
            (pci_mmcfg_config[0].base_address == 0))
-               return;
-
-       if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
-                       pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
-                       E820_RESERVED)) {
-               printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
-                               pci_mmcfg_config[0].base_address);
-               printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
-               return;
-       }
+               goto out;
 
        printk(KERN_INFO "PCI: Using MMCONFIG\n");
        raw_pci_ops = &pci_mmcfg;
        pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
 
        unreachable_devices();
+
+ out:
+       return 0;
 }
+
+arch_initcall(pci_mmcfg_init);