1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#include <linux/types.h>
28#include <linux/kernel.h>
29#include <linux/export.h>
30#include <linux/pci.h>
31#include <linux/init.h>
32#include <linux/ioport.h>
33#include <linux/errno.h>
34#include <linux/bootmem.h>
35
36#include <asm/pat.h>
37#include <asm/e820.h>
38#include <asm/pci_x86.h>
39#include <asm/io_apic.h>
40
41
42
43
44
45
46struct pcibios_fwaddrmap {
47 struct list_head list;
48 struct pci_dev *dev;
49 resource_size_t fw_addr[DEVICE_COUNT_RESOURCE];
50};
51
52static LIST_HEAD(pcibios_fwaddrmappings);
53static DEFINE_SPINLOCK(pcibios_fwaddrmap_lock);
54static bool pcibios_fw_addr_done;
55
56
57static struct pcibios_fwaddrmap *pcibios_fwaddrmap_lookup(struct pci_dev *dev)
58{
59 struct pcibios_fwaddrmap *map;
60
61 WARN_ON_SMP(!spin_is_locked(&pcibios_fwaddrmap_lock));
62
63 list_for_each_entry(map, &pcibios_fwaddrmappings, list)
64 if (map->dev == dev)
65 return map;
66
67 return NULL;
68}
69
70static void
71pcibios_save_fw_addr(struct pci_dev *dev, int idx, resource_size_t fw_addr)
72{
73 unsigned long flags;
74 struct pcibios_fwaddrmap *map;
75
76 if (pcibios_fw_addr_done)
77 return;
78
79 spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags);
80 map = pcibios_fwaddrmap_lookup(dev);
81 if (!map) {
82 spin_unlock_irqrestore(&pcibios_fwaddrmap_lock, flags);
83 map = kzalloc(sizeof(*map), GFP_KERNEL);
84 if (!map)
85 return;
86
87 map->dev = pci_dev_get(dev);
88 map->fw_addr[idx] = fw_addr;
89 INIT_LIST_HEAD(&map->list);
90
91 spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags);
92 list_add_tail(&map->list, &pcibios_fwaddrmappings);
93 } else
94 map->fw_addr[idx] = fw_addr;
95 spin_unlock_irqrestore(&pcibios_fwaddrmap_lock, flags);
96}
97
98resource_size_t pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx)
99{
100 unsigned long flags;
101 struct pcibios_fwaddrmap *map;
102 resource_size_t fw_addr = 0;
103
104 if (pcibios_fw_addr_done)
105 return 0;
106
107 spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags);
108 map = pcibios_fwaddrmap_lookup(dev);
109 if (map)
110 fw_addr = map->fw_addr[idx];
111 spin_unlock_irqrestore(&pcibios_fwaddrmap_lock, flags);
112
113 return fw_addr;
114}
115
116static void __init pcibios_fw_addr_list_del(void)
117{
118 unsigned long flags;
119 struct pcibios_fwaddrmap *entry, *next;
120
121 spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags);
122 list_for_each_entry_safe(entry, next, &pcibios_fwaddrmappings, list) {
123 list_del(&entry->list);
124 pci_dev_put(entry->dev);
125 kfree(entry);
126 }
127 spin_unlock_irqrestore(&pcibios_fwaddrmap_lock, flags);
128 pcibios_fw_addr_done = true;
129}
130
131static int
132skip_isa_ioresource_align(struct pci_dev *dev) {
133
134 if ((pci_probe & PCI_CAN_SKIP_ISA_ALIGN) &&
135 !(dev->bus->bridge_ctl & PCI_BRIDGE_CTL_ISA))
136 return 1;
137 return 0;
138}
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153resource_size_t
154pcibios_align_resource(void *data, const struct resource *res,
155 resource_size_t size, resource_size_t align)
156{
157 struct pci_dev *dev = data;
158 resource_size_t start = res->start;
159
160 if (res->flags & IORESOURCE_IO) {
161 if (skip_isa_ioresource_align(dev))
162 return start;
163 if (start & 0x300)
164 start = (start + 0x3ff) & ~0x3ff;
165 }
166 return start;
167}
168EXPORT_SYMBOL(pcibios_align_resource);
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204static void pcibios_allocate_bridge_resources(struct pci_dev *dev)
205{
206 int idx;
207 struct resource *r;
208
209 for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
210 r = &dev->resource[idx];
211 if (!r->flags)
212 continue;
213 if (!r->start || pci_claim_resource(dev, idx) < 0) {
214
215
216
217
218
219
220 r->start = r->end = 0;
221 r->flags = 0;
222 }
223 }
224}
225
226static void pcibios_allocate_bus_resources(struct pci_bus *bus)
227{
228 struct pci_bus *child;
229
230
231 if (bus->self)
232 pcibios_allocate_bridge_resources(bus->self);
233 list_for_each_entry(child, &bus->children, node)
234 pcibios_allocate_bus_resources(child);
235}
236
237struct pci_check_idx_range {
238 int start;
239 int end;
240};
241
242static void pcibios_allocate_dev_resources(struct pci_dev *dev, int pass)
243{
244 int idx, disabled, i;
245 u16 command;
246 struct resource *r;
247
248 struct pci_check_idx_range idx_range[] = {
249 { PCI_STD_RESOURCES, PCI_STD_RESOURCE_END },
250#ifdef CONFIG_PCI_IOV
251 { PCI_IOV_RESOURCES, PCI_IOV_RESOURCE_END },
252#endif
253 };
254
255 pci_read_config_word(dev, PCI_COMMAND, &command);
256 for (i = 0; i < ARRAY_SIZE(idx_range); i++)
257 for (idx = idx_range[i].start; idx <= idx_range[i].end; idx++) {
258 r = &dev->resource[idx];
259 if (r->parent)
260 continue;
261 if (!r->start)
262 continue;
263 if (r->flags & IORESOURCE_IO)
264 disabled = !(command & PCI_COMMAND_IO);
265 else
266 disabled = !(command & PCI_COMMAND_MEMORY);
267 if (pass == disabled) {
268 dev_dbg(&dev->dev,
269 "BAR %d: reserving %pr (d=%d, p=%d)\n",
270 idx, r, disabled, pass);
271 if (pci_claim_resource(dev, idx) < 0) {
272
273 pcibios_save_fw_addr(dev,
274 idx, r->start);
275 r->end -= r->start;
276 r->start = 0;
277 }
278 }
279 }
280 if (!pass) {
281 r = &dev->resource[PCI_ROM_RESOURCE];
282 if (r->flags & IORESOURCE_ROM_ENABLE) {
283
284
285 u32 reg;
286 dev_dbg(&dev->dev, "disabling ROM %pR\n", r);
287 r->flags &= ~IORESOURCE_ROM_ENABLE;
288 pci_read_config_dword(dev, dev->rom_base_reg, ®);
289 pci_write_config_dword(dev, dev->rom_base_reg,
290 reg & ~PCI_ROM_ADDRESS_ENABLE);
291 }
292 }
293}
294
295static void pcibios_allocate_resources(struct pci_bus *bus, int pass)
296{
297 struct pci_dev *dev;
298 struct pci_bus *child;
299
300 list_for_each_entry(dev, &bus->devices, bus_list) {
301 pcibios_allocate_dev_resources(dev, pass);
302
303 child = dev->subordinate;
304 if (child)
305 pcibios_allocate_resources(child, pass);
306 }
307}
308
309static void pcibios_allocate_dev_rom_resource(struct pci_dev *dev)
310{
311 struct resource *r;
312
313
314
315
316
317
318 r = &dev->resource[PCI_ROM_RESOURCE];
319 if (!r->flags || !r->start)
320 return;
321
322 if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) {
323 r->end -= r->start;
324 r->start = 0;
325 }
326}
327static void pcibios_allocate_rom_resources(struct pci_bus *bus)
328{
329 struct pci_dev *dev;
330 struct pci_bus *child;
331
332 list_for_each_entry(dev, &bus->devices, bus_list) {
333 pcibios_allocate_dev_rom_resource(dev);
334
335 child = dev->subordinate;
336 if (child)
337 pcibios_allocate_rom_resources(child);
338 }
339}
340
341static int __init pcibios_assign_resources(void)
342{
343 struct pci_bus *bus;
344
345 if (!(pci_probe & PCI_ASSIGN_ROMS))
346 list_for_each_entry(bus, &pci_root_buses, node)
347 pcibios_allocate_rom_resources(bus);
348
349 pci_assign_unassigned_resources();
350 pcibios_fw_addr_list_del();
351
352 return 0;
353}
354
355void pcibios_resource_survey_bus(struct pci_bus *bus)
356{
357 dev_printk(KERN_DEBUG, &bus->dev, "Allocating resources\n");
358
359 pcibios_allocate_bus_resources(bus);
360
361 pcibios_allocate_resources(bus, 0);
362 pcibios_allocate_resources(bus, 1);
363
364 if (!(pci_probe & PCI_ASSIGN_ROMS))
365 pcibios_allocate_rom_resources(bus);
366}
367
368void __init pcibios_resource_survey(void)
369{
370 struct pci_bus *bus;
371
372 DBG("PCI: Allocating resources\n");
373
374 list_for_each_entry(bus, &pci_root_buses, node)
375 pcibios_allocate_bus_resources(bus);
376
377 list_for_each_entry(bus, &pci_root_buses, node)
378 pcibios_allocate_resources(bus, 0);
379 list_for_each_entry(bus, &pci_root_buses, node)
380 pcibios_allocate_resources(bus, 1);
381
382 e820_reserve_resources_late();
383
384
385
386
387
388 ioapic_insert_resources();
389}
390
391
392
393
394
395fs_initcall(pcibios_assign_resources);
396
397static const struct vm_operations_struct pci_mmap_ops = {
398 .access = generic_access_phys,
399};
400
401int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
402 enum pci_mmap_state mmap_state, int write_combine)
403{
404 unsigned long prot;
405
406
407
408
409 if (mmap_state == pci_mmap_io)
410 return -EINVAL;
411
412 prot = pgprot_val(vma->vm_page_prot);
413
414
415
416
417
418
419 if (!pat_enabled && write_combine)
420 return -EINVAL;
421
422 if (pat_enabled && write_combine)
423 prot |= _PAGE_CACHE_WC;
424 else if (pat_enabled || boot_cpu_data.x86 > 3)
425
426
427
428
429
430 prot |= _PAGE_CACHE_UC_MINUS;
431
432 prot |= _PAGE_IOMAP;
433
434 vma->vm_page_prot = __pgprot(prot);
435
436 if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
437 vma->vm_end - vma->vm_start,
438 vma->vm_page_prot))
439 return -EAGAIN;
440
441 vma->vm_ops = &pci_mmap_ops;
442
443 return 0;
444}
445