PCI x86: always use conf1 to access config space below 256 bytes
authorIvan Kokshaysky <ink@jurassic.park.msu.ru>
Mon, 14 Jan 2008 22:31:09 +0000 (17:31 -0500)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Sun, 10 Feb 2008 20:52:45 +0000 (12:52 -0800)
Thanks to Loic Prylli <loic@myri.com>, who originally proposed
this idea.

Always using legacy configuration mechanism for the legacy config space
and extended mechanism (mmconf) for the extended config space is
a simple and very logical approach. It's supposed to resolve all
known mmconf problems. It still allows per-device quirks (tweaking
dev->cfg_size). It also allows to get rid of mmconf fallback code.

Signed-off-by: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Signed-off-by: Matthew Wilcox <willy@linux.intel.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
arch/x86/pci/mmconfig-shared.c
arch/x86/pci/mmconfig_32.c
arch/x86/pci/mmconfig_64.c
arch/x86/pci/pci.h

index 4df637e..6b521d3 100644 (file)
 #define MMCONFIG_APER_MIN      (2 * 1024*1024)
 #define MMCONFIG_APER_MAX      (256 * 1024*1024)
 
-DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS);
-
 /* Indicate if the mmcfg resources have been placed into the resource table. */
 static int __initdata pci_mmcfg_resources_inserted;
 
-/* K8 systems have some devices (typically in the builtin northbridge)
-   that are only accessible using type1
-   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. */
-static void __init unreachable_devices(void)
-{
-       int i, bus;
-       /* Use the max bus number from ACPI here? */
-       for (bus = 0; bus < PCI_MMCFG_MAX_CHECK_BUS; bus++) {
-               for (i = 0; i < 32; i++) {
-                       unsigned int devfn = PCI_DEVFN(i, 0);
-                       u32 val1, val2;
-
-                       pci_conf1_read(0, bus, devfn, 0, 4, &val1);
-                       if (val1 == 0xffffffff)
-                               continue;
-
-                       if (pci_mmcfg_arch_reachable(0, bus, devfn)) {
-                               raw_pci_ops->read(0, bus, devfn, 0, 4, &val2);
-                               if (val1 == val2)
-                                       continue;
-                       }
-                       set_bit(i + 32 * bus, pci_mmcfg_fallback_slots);
-                       printk(KERN_NOTICE "PCI: No mmconfig possible on device"
-                              " %02x:%02x\n", bus, i);
-               }
-       }
-}
-
 static const char __init *pci_mmcfg_e7520(void)
 {
        u32 win;
@@ -270,8 +237,6 @@ void __init pci_mmcfg_init(int type)
                return;
 
        if (pci_mmcfg_arch_init()) {
-               if (type == 1)
-                       unreachable_devices();
                if (known_bridge)
                        pci_mmcfg_insert_resources(IORESOURCE_BUSY);
                pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
index 1bf5816..7b75e65 100644 (file)
@@ -30,10 +30,6 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
        struct acpi_mcfg_allocation *cfg;
        int cfg_num;
 
-       if (seg == 0 && bus < PCI_MMCFG_MAX_CHECK_BUS &&
-           test_bit(PCI_SLOT(devfn) + 32*bus, pci_mmcfg_fallback_slots))
-               return 0;
-
        for (cfg_num = 0; cfg_num < pci_mmcfg_config_num; cfg_num++) {
                cfg = &pci_mmcfg_config[cfg_num];
                if (cfg->pci_segment == seg &&
@@ -68,13 +64,16 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
        u32 base;
 
        if ((bus > 255) || (devfn > 255) || (reg > 4095)) {
-               *value = -1;
+err:           *value = -1;
                return -EINVAL;
        }
 
+       if (reg < 256)
+               return pci_conf1_read(seg,bus,devfn,reg,len,value);
+
        base = get_base_addr(seg, bus, devfn);
        if (!base)
-               return pci_conf1_read(seg,bus,devfn,reg,len,value);
+               goto err;
 
        spin_lock_irqsave(&pci_config_lock, flags);
 
@@ -105,9 +104,12 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
        if ((bus > 255) || (devfn > 255) || (reg > 4095))
                return -EINVAL;
 
+       if (reg < 256)
+               return pci_conf1_write(seg,bus,devfn,reg,len,value);
+
        base = get_base_addr(seg, bus, devfn);
        if (!base)
-               return pci_conf1_write(seg,bus,devfn,reg,len,value);
+               return -EINVAL;
 
        spin_lock_irqsave(&pci_config_lock, flags);
 
@@ -134,12 +136,6 @@ static struct pci_raw_ops pci_mmcfg = {
        .write =        pci_mmcfg_write,
 };
 
-int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus,
-                                   unsigned int devfn)
-{
-       return get_base_addr(seg, bus, devfn) != 0;
-}
-
 int __init pci_mmcfg_arch_init(void)
 {
        printk(KERN_INFO "PCI: Using MMCONFIG\n");
index 4095e4d..c4cf318 100644 (file)
@@ -40,9 +40,7 @@ static char __iomem *get_virt(unsigned int seg, unsigned bus)
 static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
 {
        char __iomem *addr;
-       if (seg == 0 && bus < PCI_MMCFG_MAX_CHECK_BUS &&
-               test_bit(32*bus + PCI_SLOT(devfn), pci_mmcfg_fallback_slots))
-               return NULL;
+
        addr = get_virt(seg, bus);
        if (!addr)
                return NULL;
@@ -56,13 +54,16 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
 
        /* Why do we have this when nobody checks it. How about a BUG()!? -AK */
        if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) {
-               *value = -1;
+err:           *value = -1;
                return -EINVAL;
        }
 
+       if (reg < 256)
+               return pci_conf1_read(seg,bus,devfn,reg,len,value);
+
        addr = pci_dev_base(seg, bus, devfn);
        if (!addr)
-               return pci_conf1_read(seg,bus,devfn,reg,len,value);
+               goto err;
 
        switch (len) {
        case 1:
@@ -88,9 +89,12 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
        if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095)))
                return -EINVAL;
 
+       if (reg < 256)
+               return pci_conf1_write(seg,bus,devfn,reg,len,value);
+
        addr = pci_dev_base(seg, bus, devfn);
        if (!addr)
-               return pci_conf1_write(seg,bus,devfn,reg,len,value);
+               return -EINVAL;
 
        switch (len) {
        case 1:
@@ -126,12 +130,6 @@ static void __iomem * __init mcfg_ioremap(struct acpi_mcfg_allocation *cfg)
        return addr;
 }
 
-int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus,
-                                   unsigned int devfn)
-{
-       return pci_dev_base(seg, bus, devfn) != NULL;
-}
-
 int __init pci_mmcfg_arch_init(void)
 {
        int i;
index ac56d39..36cb44c 100644 (file)
@@ -98,13 +98,6 @@ extern void pcibios_sort(void);
 
 /* pci-mmconfig.c */
 
-/* Verify the first 16 busses. We assume that systems with more busses
-   get MCFG right. */
-#define PCI_MMCFG_MAX_CHECK_BUS 16
-extern DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS);
-
-extern int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus,
-                                          unsigned int devfn);
 extern int __init pci_mmcfg_arch_init(void);
 
 /*