aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/pci/mmconfig.c
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2005-12-13 01:17:10 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-12-13 01:31:16 -0500
commit928cf8c62763349efc550a12f6518e52c3390906 (patch)
tree5fb257cbdaaebc3814e6df85100712127cdb8526 /arch/i386/pci/mmconfig.c
parentbf5421c309bb89e5106452bc840983b1b4754d61 (diff)
[PATCH] i386/x86-64 Fall back to type 1 access when no entry found
When there is no entry for a bus in MCFG fall back to type1. This is especially important on K8 systems where always some devices can't be accessed using mmconfig (in particular the builtin northbridge doesn't support it for its own devices) Cc: <gregkh@suse.de> Cc: <jgarzik@pobox.com> Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/i386/pci/mmconfig.c')
-rw-r--r--arch/i386/pci/mmconfig.c24
1 files changed, 16 insertions, 8 deletions
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c
index dfbf80cff834..cc787a7c030c 100644
--- a/arch/i386/pci/mmconfig.c
+++ b/arch/i386/pci/mmconfig.c
@@ -30,10 +30,8 @@ static u32 get_base_addr(unsigned int seg, int bus)
30 while (1) { 30 while (1) {
31 ++cfg_num; 31 ++cfg_num;
32 if (cfg_num >= pci_mmcfg_config_num) { 32 if (cfg_num >= pci_mmcfg_config_num) {
33 /* something bad is going on, no cfg table is found. */ 33 /* Not found - fallback to type 1 */
34 /* so we fall back to the old way we used to do this */ 34 return 0;
35 /* and just rely on the first entry to be correct. */
36 return pci_mmcfg_config[0].base_address;
37 } 35 }
38 cfg = &pci_mmcfg_config[cfg_num]; 36 cfg = &pci_mmcfg_config[cfg_num];
39 if (cfg->pci_segment_group_number != seg) 37 if (cfg->pci_segment_group_number != seg)
@@ -44,9 +42,9 @@ static u32 get_base_addr(unsigned int seg, int bus)
44 } 42 }
45} 43}
46 44
47static inline void pci_exp_set_dev_base(unsigned int seg, int bus, int devfn) 45static inline void pci_exp_set_dev_base(unsigned int base, int bus, int devfn)
48{ 46{
49 u32 dev_base = get_base_addr(seg, bus) | (bus << 20) | (devfn << 12); 47 u32 dev_base = base | (bus << 20) | (devfn << 12);
50 if (dev_base != mmcfg_last_accessed_device) { 48 if (dev_base != mmcfg_last_accessed_device) {
51 mmcfg_last_accessed_device = dev_base; 49 mmcfg_last_accessed_device = dev_base;
52 set_fixmap_nocache(FIX_PCIE_MCFG, dev_base); 50 set_fixmap_nocache(FIX_PCIE_MCFG, dev_base);
@@ -57,13 +55,18 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
57 unsigned int devfn, int reg, int len, u32 *value) 55 unsigned int devfn, int reg, int len, u32 *value)
58{ 56{
59 unsigned long flags; 57 unsigned long flags;
58 u32 base;
60 59
61 if (!value || (bus > 255) || (devfn > 255) || (reg > 4095)) 60 if (!value || (bus > 255) || (devfn > 255) || (reg > 4095))
62 return -EINVAL; 61 return -EINVAL;
63 62
63 base = get_base_addr(seg, bus);
64 if (!base)
65 return pci_conf1_read(seg,bus,devfn,reg,len,value);
66
64 spin_lock_irqsave(&pci_config_lock, flags); 67 spin_lock_irqsave(&pci_config_lock, flags);
65 68
66 pci_exp_set_dev_base(seg, bus, devfn); 69 pci_exp_set_dev_base(base, bus, devfn);
67 70
68 switch (len) { 71 switch (len) {
69 case 1: 72 case 1:
@@ -86,13 +89,18 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
86 unsigned int devfn, int reg, int len, u32 value) 89 unsigned int devfn, int reg, int len, u32 value)
87{ 90{
88 unsigned long flags; 91 unsigned long flags;
92 u32 base;
89 93
90 if ((bus > 255) || (devfn > 255) || (reg > 4095)) 94 if ((bus > 255) || (devfn > 255) || (reg > 4095))
91 return -EINVAL; 95 return -EINVAL;
92 96
97 base = get_base_addr(seg, bus);
98 if (!base)
99 return pci_conf1_write(seg,bus,devfn,reg,len,value);
100
93 spin_lock_irqsave(&pci_config_lock, flags); 101 spin_lock_irqsave(&pci_config_lock, flags);
94 102
95 pci_exp_set_dev_base(seg, bus, devfn); 103 pci_exp_set_dev_base(base, bus, devfn);
96 104
97 switch (len) { 105 switch (len) {
98 case 1: 106 case 1: