]> xenbits.xensource.com Git - people/royger/linux-2.6.18-xen.git/commitdiff
PCI x86: always use conf1 to access config space below 256 bytes
authorKeir Fraser <keir.fraser@citrix.com>
Fri, 14 Aug 2009 09:54:33 +0000 (10:54 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Fri, 14 Aug 2009 09:54:33 +0000 (10:54 +0100)
Back-ported to 2.6.18.8 by Simon Horman

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>
Signed-off-by: Simon Horman <horms@verge.net.au>
arch/i386/pci/mmconfig.c
arch/x86_64/pci/mmconfig.c

index 972180f738d9ae0d15fe059953fe2985cf454c09..445052a707f5e2bb72f75d8115fecf5453ec425c 100644 (file)
 #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);
-
 /*
  * Functions for accessing PCI configuration space with MMCONFIG accesses
  */
@@ -37,10 +32,6 @@ 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))
-               return 0;
-
        while (1) {
                ++cfg_num;
                if (cfg_num >= pci_mmcfg_config_num) {
@@ -83,13 +74,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);
 
@@ -121,9 +115,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);
 
@@ -151,42 +148,6 @@ static struct pci_raw_ops pci_mmcfg = {
        .write =        pci_mmcfg_write,
 };
 
-/* 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 __init void unreachable_devices(void)
-{
-       int i, k;
-       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);
-               }
-       }
-}
-
 void __init pci_mmcfg_init(void)
 {
        if ((pci_probe & PCI_PROBE_MMCONF) == 0)
@@ -210,6 +171,4 @@ void __init pci_mmcfg_init(void)
        printk(KERN_INFO "PCI: Using MMCONFIG\n");
        raw_pci_ops = &pci_mmcfg;
        pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
-
-       unreachable_devices();
 }
index 7a7b66a243f95bbf2d6a4fb7eef2f1ee99502b9c..a939652bcc9f99f80ae4a0d697add323926775d4 100644 (file)
 #define MMCONFIG_APER_MIN      (2 * 1024*1024)
 #define MMCONFIG_APER_MAX      (256 * 1024*1024)
 
-/* Verify the first 16 busses. We assume that systems with more busses
-   get MCFG right. */
-#define MAX_CHECK_BUS 16
-
-static DECLARE_BITMAP(fallback_slots, 32*MAX_CHECK_BUS);
-
 /* Static virtual mapping of the MMCONFIG aperture */
 struct mmcfg_virt {
        struct acpi_table_mcfg_config *cfg;
@@ -87,9 +81,6 @@ 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 < MAX_CHECK_BUS &&
-               test_bit(32*bus + PCI_SLOT(devfn), fallback_slots))
-               return NULL;
        addr = get_virt(seg, bus);
        if (!addr)
                return NULL;
@@ -103,13 +94,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:
@@ -135,9 +129,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:
@@ -159,35 +156,6 @@ static struct pci_raw_ops pci_mmcfg = {
        .write =        pci_mmcfg_write,
 };
 
-/* 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 __init void unreachable_devices(void)
-{
-       int i, k;
-       /* Use the max bus number from ACPI here? */
-       for (k = 0; k < MAX_CHECK_BUS; k++) {
-               for (i = 0; i < 32; i++) {
-                       u32 val1;
-                       char __iomem *addr;
-
-                       pci_conf1_read(0, k, PCI_DEVFN(i,0), 0, 4, &val1);
-                       if (val1 == 0xffffffff)
-                               continue;
-                       addr = pci_dev_base(0, k, PCI_DEVFN(i, 0));
-                       if (addr == NULL|| readl(addr) != val1) {
-                               set_bit(i + 32*k, fallback_slots);
-                               printk(KERN_NOTICE
-                               "PCI: No mmconfig possible on device %x:%x\n",
-                                       k, i);
-                       }
-               }
-       }
-}
-
 void __init pci_mmcfg_init(void)
 {
        int i;
@@ -226,8 +194,6 @@ void __init pci_mmcfg_init(void)
                }
        }
 
-       unreachable_devices();
-
        raw_pci_ops = &pci_mmcfg;
        pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
 }