aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/i386/pci/mmconfig.c52
-rw-r--r--arch/x86_64/pci/mmconfig.c39
2 files changed, 54 insertions, 37 deletions
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c
index ee815c7d3e4c..2002c741a383 100644
--- a/arch/i386/pci/mmconfig.c
+++ b/arch/i386/pci/mmconfig.c
@@ -17,12 +17,15 @@
17 17
18#define MMCONFIG_APER_SIZE (256*1024*1024) 18#define MMCONFIG_APER_SIZE (256*1024*1024)
19 19
20/* Assume systems with more busses have correct MCFG */
21#define MAX_CHECK_BUS 16
22
20#define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG)) 23#define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))
21 24
22/* The base address of the last MMCONFIG device accessed */ 25/* The base address of the last MMCONFIG device accessed */
23static u32 mmcfg_last_accessed_device; 26static u32 mmcfg_last_accessed_device;
24 27
25static DECLARE_BITMAP(fallback_slots, 32); 28static DECLARE_BITMAP(fallback_slots, MAX_CHECK_BUS*32);
26 29
27/* 30/*
28 * Functions for accessing PCI configuration space with MMCONFIG accesses 31 * Functions for accessing PCI configuration space with MMCONFIG accesses
@@ -32,8 +35,8 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
32 int cfg_num = -1; 35 int cfg_num = -1;
33 struct acpi_table_mcfg_config *cfg; 36 struct acpi_table_mcfg_config *cfg;
34 37
35 if (seg == 0 && bus == 0 && 38 if (seg == 0 && bus < MAX_CHECK_BUS &&
36 test_bit(PCI_SLOT(devfn), fallback_slots)) 39 test_bit(PCI_SLOT(devfn) + 32*bus, fallback_slots))
37 return 0; 40 return 0;
38 41
39 while (1) { 42 while (1) {
@@ -149,29 +152,34 @@ static struct pci_raw_ops pci_mmcfg = {
149 Normally this can be expressed in the MCFG by not listing them 152 Normally this can be expressed in the MCFG by not listing them
150 and assigning suitable _SEGs, but this isn't implemented in some BIOS. 153 and assigning suitable _SEGs, but this isn't implemented in some BIOS.
151 Instead try to discover all devices on bus 0 that are unreachable using MM 154 Instead try to discover all devices on bus 0 that are unreachable using MM
152 and fallback for them. 155 and fallback for them. */
153 We only do this for bus 0/seg 0 */
154static __init void unreachable_devices(void) 156static __init void unreachable_devices(void)
155{ 157{
156 int i; 158 int i, k;
157 unsigned long flags; 159 unsigned long flags;
158 160
159 for (i = 0; i < 32; i++) { 161 for (k = 0; k < MAX_CHECK_BUS; k++) {
160 u32 val1; 162 for (i = 0; i < 32; i++) {
161 u32 addr; 163 u32 val1;
162 164 u32 addr;
163 pci_conf1_read(0, 0, PCI_DEVFN(i, 0), 0, 4, &val1); 165
164 if (val1 == 0xffffffff) 166 pci_conf1_read(0, k, PCI_DEVFN(i, 0), 0, 4, &val1);
165 continue; 167 if (val1 == 0xffffffff)
166 168 continue;
167 /* Locking probably not needed, but safer */ 169
168 spin_lock_irqsave(&pci_config_lock, flags); 170 /* Locking probably not needed, but safer */
169 addr = get_base_addr(0, 0, PCI_DEVFN(i, 0)); 171 spin_lock_irqsave(&pci_config_lock, flags);
170 if (addr != 0) 172 addr = get_base_addr(0, k, PCI_DEVFN(i, 0));
171 pci_exp_set_dev_base(addr, 0, PCI_DEVFN(i, 0)); 173 if (addr != 0)
172 if (addr == 0 || readl((u32 __iomem *)mmcfg_virt_addr) != val1) 174 pci_exp_set_dev_base(addr, k, PCI_DEVFN(i, 0));
173 set_bit(i, fallback_slots); 175 if (addr == 0 ||
174 spin_unlock_irqrestore(&pci_config_lock, flags); 176 readl((u32 __iomem *)mmcfg_virt_addr) != val1) {
177 set_bit(i, fallback_slots);
178 printk(KERN_NOTICE
179 "PCI: No mmconfig possible on %x:%x\n", k, i);
180 }
181 spin_unlock_irqrestore(&pci_config_lock, flags);
182 }
175 } 183 }
176} 184}
177 185
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c
index dfe84c322552..d4e25f38287d 100644
--- a/arch/x86_64/pci/mmconfig.c
+++ b/arch/x86_64/pci/mmconfig.c
@@ -14,8 +14,11 @@
14#include "pci.h" 14#include "pci.h"
15 15
16#define MMCONFIG_APER_SIZE (256*1024*1024) 16#define MMCONFIG_APER_SIZE (256*1024*1024)
17/* Verify the first 16 busses. We assume that systems with more busses
18 get MCFG right. */
19#define MAX_CHECK_BUS 16
17 20
18static DECLARE_BITMAP(fallback_slots, 32); 21static DECLARE_BITMAP(fallback_slots, 32*MAX_CHECK_BUS);
19 22
20/* Static virtual mapping of the MMCONFIG aperture */ 23/* Static virtual mapping of the MMCONFIG aperture */
21struct mmcfg_virt { 24struct mmcfg_virt {
@@ -57,7 +60,8 @@ static char __iomem *get_virt(unsigned int seg, unsigned bus)
57static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn) 60static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
58{ 61{
59 char __iomem *addr; 62 char __iomem *addr;
60 if (seg == 0 && bus == 0 && test_bit(PCI_SLOT(devfn), fallback_slots)) 63 if (seg == 0 && bus < MAX_CHECK_BUS &&
64 test_bit(32*bus + PCI_SLOT(devfn), fallback_slots))
61 return NULL; 65 return NULL;
62 addr = get_virt(seg, bus); 66 addr = get_virt(seg, bus);
63 if (!addr) 67 if (!addr)
@@ -131,21 +135,26 @@ static struct pci_raw_ops pci_mmcfg = {
131 Normally this can be expressed in the MCFG by not listing them 135 Normally this can be expressed in the MCFG by not listing them
132 and assigning suitable _SEGs, but this isn't implemented in some BIOS. 136 and assigning suitable _SEGs, but this isn't implemented in some BIOS.
133 Instead try to discover all devices on bus 0 that are unreachable using MM 137 Instead try to discover all devices on bus 0 that are unreachable using MM
134 and fallback for them. 138 and fallback for them. */
135 We only do this for bus 0/seg 0 */
136static __init void unreachable_devices(void) 139static __init void unreachable_devices(void)
137{ 140{
138 int i; 141 int i, k;
139 for (i = 0; i < 32; i++) { 142 /* Use the max bus number from ACPI here? */
140 u32 val1; 143 for (k = 0; i < MAX_CHECK_BUS; k++) {
141 char __iomem *addr; 144 for (i = 0; i < 32; i++) {
142 145 u32 val1;
143 pci_conf1_read(0, 0, PCI_DEVFN(i,0), 0, 4, &val1); 146 char __iomem *addr;
144 if (val1 == 0xffffffff) 147
145 continue; 148 pci_conf1_read(0, k, PCI_DEVFN(i,0), 0, 4, &val1);
146 addr = pci_dev_base(0, 0, PCI_DEVFN(i, 0)); 149 if (val1 == 0xffffffff)
147 if (addr == NULL|| readl(addr) != val1) { 150 continue;
148 set_bit(i, fallback_slots); 151 addr = pci_dev_base(0, k, PCI_DEVFN(i, 0));
152 if (addr == NULL|| readl(addr) != val1) {
153 set_bit(i + 32*k, fallback_slots);
154 printk(KERN_NOTICE
155 "PCI: No mmconfig possible on device %x:%x\n",
156 k, i);
157 }
149 } 158 }
150 } 159 }
151} 160}