diff options
Diffstat (limited to 'arch/i386/pci')
-rw-r--r-- | arch/i386/pci/direct.c | 4 | ||||
-rw-r--r-- | arch/i386/pci/mmconfig.c | 24 | ||||
-rw-r--r-- | arch/i386/pci/pci.h | 7 |
3 files changed, 25 insertions, 10 deletions
diff --git a/arch/i386/pci/direct.c b/arch/i386/pci/direct.c index 94331d6be7a3..e3ac502bf2fb 100644 --- a/arch/i386/pci/direct.c +++ b/arch/i386/pci/direct.c | |||
@@ -13,7 +13,7 @@ | |||
13 | #define PCI_CONF1_ADDRESS(bus, devfn, reg) \ | 13 | #define PCI_CONF1_ADDRESS(bus, devfn, reg) \ |
14 | (0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3)) | 14 | (0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3)) |
15 | 15 | ||
16 | static int pci_conf1_read(unsigned int seg, unsigned int bus, | 16 | int pci_conf1_read(unsigned int seg, unsigned int bus, |
17 | unsigned int devfn, int reg, int len, u32 *value) | 17 | unsigned int devfn, int reg, int len, u32 *value) |
18 | { | 18 | { |
19 | unsigned long flags; | 19 | unsigned long flags; |
@@ -42,7 +42,7 @@ static int pci_conf1_read(unsigned int seg, unsigned int bus, | |||
42 | return 0; | 42 | return 0; |
43 | } | 43 | } |
44 | 44 | ||
45 | static int pci_conf1_write(unsigned int seg, unsigned int bus, | 45 | int pci_conf1_write(unsigned int seg, unsigned int bus, |
46 | unsigned int devfn, int reg, int len, u32 value) | 46 | unsigned int devfn, int reg, int len, u32 value) |
47 | { | 47 | { |
48 | unsigned long flags; | 48 | unsigned long flags; |
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 | ||
47 | static inline void pci_exp_set_dev_base(unsigned int seg, int bus, int devfn) | 45 | static 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: |
diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h index 127d53ad16be..f550781ec310 100644 --- a/arch/i386/pci/pci.h +++ b/arch/i386/pci/pci.h | |||
@@ -74,3 +74,10 @@ extern spinlock_t pci_config_lock; | |||
74 | 74 | ||
75 | extern int (*pcibios_enable_irq)(struct pci_dev *dev); | 75 | extern int (*pcibios_enable_irq)(struct pci_dev *dev); |
76 | extern void (*pcibios_disable_irq)(struct pci_dev *dev); | 76 | extern void (*pcibios_disable_irq)(struct pci_dev *dev); |
77 | |||
78 | extern int pci_conf1_write(unsigned int seg, unsigned int bus, | ||
79 | unsigned int devfn, int reg, int len, u32 value); | ||
80 | extern int pci_conf1_read(unsigned int seg, unsigned int bus, | ||
81 | unsigned int devfn, int reg, int len, u32 *value); | ||
82 | |||
83 | |||