Back-ported to 2.6.18.8 by Simon Horman
Signed-off-by: Ivan Kokshaysky <ink@xxxxxxxxxxxxxxxxxxxx>
Signed-off-by: Matthew Wilcox <willy@xxxxxxxxxxxxxxx>
Signed-off-by: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>
Signed-off-by: Simon Horman <horms@xxxxxxxxxxxx>
---
Test machine: HP dc7800
x86_64: This patch is needed to allow mcfg_ioremap() to work.
That is, it is needed for the system to boot with
the previous patch applied.
i386: This patch is needed for the system to boot.
Index: linux-2.6.18-xen.hg/arch/x86_64/pci/mmconfig.c
===================================================================
--- linux-2.6.18-xen.hg.orig/arch/x86_64/pci/mmconfig.c 2009-08-13
11:06:24.000000000 +0900
+++ linux-2.6.18-xen.hg/arch/x86_64/pci/mmconfig.c 2009-08-13
11:08:14.000000000 +0900
@@ -17,12 +17,6 @@
#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 i
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 s
/* 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
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;
}
Index: linux-2.6.18-xen.hg/arch/i386/pci/mmconfig.c
===================================================================
--- linux-2.6.18-xen.hg.orig/arch/i386/pci/mmconfig.c 2008-11-04
09:47:13.000000000 +0900
+++ linux-2.6.18-xen.hg/arch/i386/pci/mmconfig.c 2009-08-13
11:08:00.000000000 +0900
@@ -19,16 +19,11 @@
#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 se
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 s
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
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();
}
--
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|