Merge branch 'merge'
[pandora-kernel.git] / arch / x86_64 / pci / mmconfig.c
1 /*
2  * mmconfig.c - Low-level direct PCI config space access via MMCONFIG
3  * 
4  * This is an 64bit optimized version that always keeps the full mmconfig
5  * space mapped. This allows lockless config space operation.
6  */
7
8 #include <linux/pci.h>
9 #include <linux/init.h>
10 #include <linux/acpi.h>
11 #include <linux/bitmap.h>
12 #include <linux/dmi.h>
13 #include <asm/e820.h>
14
15 #include "pci.h"
16
17 /* aperture is up to 256MB but BIOS may reserve less */
18 #define MMCONFIG_APER_MIN       (2 * 1024*1024)
19 #define MMCONFIG_APER_MAX       (256 * 1024*1024)
20
21 /* Verify the first 16 busses. We assume that systems with more busses
22    get MCFG right. */
23 #define MAX_CHECK_BUS 16
24
25 static DECLARE_BITMAP(fallback_slots, 32*MAX_CHECK_BUS);
26
27 /* Static virtual mapping of the MMCONFIG aperture */
28 struct mmcfg_virt {
29         struct acpi_table_mcfg_config *cfg;
30         char __iomem *virt;
31 };
32 static struct mmcfg_virt *pci_mmcfg_virt;
33
34 static char __iomem *get_virt(unsigned int seg, unsigned bus)
35 {
36         int cfg_num = -1;
37         struct acpi_table_mcfg_config *cfg;
38
39         while (1) {
40                 ++cfg_num;
41                 if (cfg_num >= pci_mmcfg_config_num)
42                         break;
43                 cfg = pci_mmcfg_virt[cfg_num].cfg;
44                 if (cfg->pci_segment_group_number != seg)
45                         continue;
46                 if ((cfg->start_bus_number <= bus) &&
47                     (cfg->end_bus_number >= bus))
48                         return pci_mmcfg_virt[cfg_num].virt;
49         }
50
51         /* Handle more broken MCFG tables on Asus etc.
52            They only contain a single entry for bus 0-0. Assume
53            this applies to all busses. */
54         cfg = &pci_mmcfg_config[0];
55         if (pci_mmcfg_config_num == 1 &&
56                 cfg->pci_segment_group_number == 0 &&
57                 (cfg->start_bus_number | cfg->end_bus_number) == 0)
58                 return pci_mmcfg_virt[0].virt;
59
60         /* Fall back to type 0 */
61         return NULL;
62 }
63
64 static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
65 {
66         char __iomem *addr;
67         if (seg == 0 && bus < MAX_CHECK_BUS &&
68                 test_bit(32*bus + PCI_SLOT(devfn), fallback_slots))
69                 return NULL;
70         addr = get_virt(seg, bus);
71         if (!addr)
72                 return NULL;
73         return addr + ((bus << 20) | (devfn << 12));
74 }
75
76 static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
77                           unsigned int devfn, int reg, int len, u32 *value)
78 {
79         char __iomem *addr;
80
81         /* Why do we have this when nobody checks it. How about a BUG()!? -AK */
82         if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) {
83                 *value = -1;
84                 return -EINVAL;
85         }
86
87         addr = pci_dev_base(seg, bus, devfn);
88         if (!addr)
89                 return pci_conf1_read(seg,bus,devfn,reg,len,value);
90
91         switch (len) {
92         case 1:
93                 *value = readb(addr + reg);
94                 break;
95         case 2:
96                 *value = readw(addr + reg);
97                 break;
98         case 4:
99                 *value = readl(addr + reg);
100                 break;
101         }
102
103         return 0;
104 }
105
106 static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
107                            unsigned int devfn, int reg, int len, u32 value)
108 {
109         char __iomem *addr;
110
111         /* Why do we have this when nobody checks it. How about a BUG()!? -AK */
112         if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095)))
113                 return -EINVAL;
114
115         addr = pci_dev_base(seg, bus, devfn);
116         if (!addr)
117                 return pci_conf1_write(seg,bus,devfn,reg,len,value);
118
119         switch (len) {
120         case 1:
121                 writeb(value, addr + reg);
122                 break;
123         case 2:
124                 writew(value, addr + reg);
125                 break;
126         case 4:
127                 writel(value, addr + reg);
128                 break;
129         }
130
131         return 0;
132 }
133
134 static struct pci_raw_ops pci_mmcfg = {
135         .read =         pci_mmcfg_read,
136         .write =        pci_mmcfg_write,
137 };
138
139 /* K8 systems have some devices (typically in the builtin northbridge)
140    that are only accessible using type1
141    Normally this can be expressed in the MCFG by not listing them
142    and assigning suitable _SEGs, but this isn't implemented in some BIOS.
143    Instead try to discover all devices on bus 0 that are unreachable using MM
144    and fallback for them. */
145 static __init void unreachable_devices(void)
146 {
147         int i, k;
148         /* Use the max bus number from ACPI here? */
149         for (k = 0; k < MAX_CHECK_BUS; k++) {
150                 for (i = 0; i < 32; i++) {
151                         u32 val1;
152                         char __iomem *addr;
153
154                         pci_conf1_read(0, k, PCI_DEVFN(i,0), 0, 4, &val1);
155                         if (val1 == 0xffffffff)
156                                 continue;
157                         addr = pci_dev_base(0, k, PCI_DEVFN(i, 0));
158                         if (addr == NULL|| readl(addr) != val1) {
159                                 set_bit(i + 32*k, fallback_slots);
160                                 printk(KERN_NOTICE
161                                 "PCI: No mmconfig possible on device %x:%x\n",
162                                         k, i);
163                         }
164                 }
165         }
166 }
167
168 static int disable_mcfg(struct dmi_system_id *d)
169 {
170         printk("PCI: %s detected. Disabling MCFG.\n", d->ident);
171         pci_probe &= ~PCI_PROBE_MMCONF;
172         return 0;
173 }
174
175 static struct dmi_system_id __initdata dmi_bad_mcfg[] = {
176         /* Has broken MCFG table that makes the system hang when used */
177         {
178          .callback = disable_mcfg,
179          .ident = "Intel D3C5105 SDV",
180          .matches = {
181                      DMI_MATCH(DMI_BIOS_VENDOR, "Intel"),
182                      DMI_MATCH(DMI_BOARD_NAME, "D26928"),
183                      },
184          },
185          {}
186 };
187
188 void __init pci_mmcfg_init(void)
189 {
190         int i;
191
192         dmi_check_system(dmi_bad_mcfg);
193
194         if ((pci_probe & (PCI_PROBE_MMCONF|PCI_PROBE_MMCONF_FORCE)) == 0)
195                 return;
196
197         acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
198         if ((pci_mmcfg_config_num == 0) ||
199             (pci_mmcfg_config == NULL) ||
200             (pci_mmcfg_config[0].base_address == 0))
201                 return;
202
203         /* RED-PEN i386 doesn't do _nocache right now */
204         pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);
205         if (pci_mmcfg_virt == NULL) {
206                 printk("PCI: Can not allocate memory for mmconfig structures\n");
207                 return;
208         }
209         for (i = 0; i < pci_mmcfg_config_num; ++i) {
210                 pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i];
211                 pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address,
212                                                          MMCONFIG_APER_MAX);
213                 if (!pci_mmcfg_virt[i].virt) {
214                         printk("PCI: Cannot map mmconfig aperture for segment %d\n",
215                                pci_mmcfg_config[i].pci_segment_group_number);
216                         return;
217                 }
218                 printk(KERN_INFO "PCI: Using MMCONFIG at %x\n", pci_mmcfg_config[i].base_address);
219         }
220
221         unreachable_devices();
222
223         raw_pci_ops = &pci_mmcfg;
224         pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
225 }