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
28#include <linux/types.h>
29#include <linux/kernel.h>
30#include <linux/export.h>
31#include <linux/pci.h>
32#include <linux/init.h>
33#include <linux/ioport.h>
34#include <linux/errno.h>
35#include <linux/memblock.h>
36
37#include <asm/memtype.h>
38#include <asm/e820/api.h>
39#include <asm/pci_x86.h>
40#include <asm/io_apic.h>
41
42
43
44
45
46
47struct pcibios_fwaddrmap {
48 struct list_head list;
49 struct pci_dev *dev;
50 resource_size_t fw_addr[DEVICE_COUNT_RESOURCE];
51};
52
53static LIST_HEAD(pcibios_fwaddrmappings);
54static DEFINE_SPINLOCK(pcibios_fwaddrmap_lock);
55static bool pcibios_fw_addr_done;
56
57
58static struct pcibios_fwaddrmap *pcibios_fwaddrmap_lookup(struct pci_dev *dev)
59{
60 struct pcibios_fwaddrmap *map;
61
62 lockdep_assert_held(&pcibios_fwaddrmap_lock);
63
64 list_for_each_entry(map, &pcibios_fwaddrmappings, list)
65 if (map->dev == dev)
66 return map;
67
68 return NULL;
69}
70
71static void
72pcibios_save_fw_addr(struct pci_dev *dev, int idx, resource_size_t fw_addr)
73{
74 unsigned long flags;
75 struct pcibios_fwaddrmap *map;
76
77 if (pcibios_fw_addr_done)
78 return;
79
80 spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags);
81 map = pcibios_fwaddrmap_lookup(dev);
82 if (!map) {
83 spin_unlock_irqrestore(&pcibios_fwaddrmap_lock, flags);
84 map = kzalloc(sizeof(*map), GFP_KERNEL);
85 if (!map)
86 return;
87
88 map->dev = pci_dev_get(dev);
89 map->fw_addr[idx] = fw_addr;
90 INIT_LIST_HEAD(&map->list);
91
92 spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags);
93 list_add_tail(&map->list, &pcibios_fwaddrmappings);
94 } else
95 map->fw_addr[idx] = fw_addr;
96 spin_unlock_irqrestore(&pcibios_fwaddrmap_lock, flags);
97}
98
99resource_size_t pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx)
100{
101 unsigned long flags;
102 struct pcibios_fwaddrmap *map;
103 resource_size_t fw_addr = 0;
104
105 if (pcibios_fw_addr_done)
106 return 0;
107
108 spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags);
109 map = pcibios_fwaddrmap_lookup(dev);
110 if (map)
111 fw_addr = map->fw_addr[idx];
112 spin_unlock_irqrestore(&pcibios_fwaddrmap_lock, flags);
113
114 return fw_addr;
115}
116
117static void __init pcibios_fw_addr_list_del(void)
118{
119 unsigned long flags;
120 struct pcibios_fwaddrmap *entry, *next;
121
122 spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags);
123 list_for_each_entry_safe(entry, next, &pcibios_fwaddrmappings, list) {
124 list_del(&entry->list);
125 pci_dev_put(entry->dev);
126 kfree(entry);
127 }
128 spin_unlock_irqrestore(&pcibios_fwaddrmap_lock, flags);
129 pcibios_fw_addr_done = true;
130}
131
132static int
133skip_isa_ioresource_align(struct pci_dev *dev) {
134
135 if ((pci_probe & PCI_CAN_SKIP_ISA_ALIGN) &&
136 !(dev->bus->bridge_ctl & PCI_BRIDGE_CTL_ISA))
137 return 1;
138 return 0;
139}
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154resource_size_t
155pcibios_align_resource(void *data, const struct resource *res,
156 resource_size_t size, resource_size_t align)
157{
158 struct pci_dev *dev = data;
159 resource_size_t start = res->start;
160
161 if (res->flags & IORESOURCE_IO) {
162 if (skip_isa_ioresource_align(dev))
163 return start;
164 if (start & 0x300)
165 start = (start + 0x3ff) & ~0x3ff;
166 } else if (res->flags & IORESOURCE_MEM) {
167
168 if (start < BIOS_END)
169 start = BIOS_END;
170 }
171 return start;
172}
173EXPORT_SYMBOL(pcibios_align_resource);
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
204
205
206
207
208
209static void pcibios_allocate_bridge_resources(struct pci_dev *dev)
210{
211 int idx;
212 struct resource *r;
213
214 for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
215 r = &dev->resource[idx];
216 if (!r->flags)
217 continue;
218 if (r->parent)
219 continue;
220 if (!r->start || pci_claim_bridge_resource(dev, idx) < 0) {
221
222
223
224
225
226
227 r->start = r->end = 0;
228 r->flags = 0;
229 }
230 }
231}
232
233static void pcibios_allocate_bus_resources(struct pci_bus *bus)
234{
235 struct pci_bus *child;
236
237
238 if (bus->self)
239 pcibios_allocate_bridge_resources(bus->self);
240 list_for_each_entry(child, &bus->children, node)
241 pcibios_allocate_bus_resources(child);
242}
243
244struct pci_check_idx_range {
245 int start;
246 int end;
247};
248
249static void pcibios_allocate_dev_resources(struct pci_dev *dev, int pass)
250{
251 int idx, disabled, i;
252 u16 command;
253 struct resource *r;
254
255 struct pci_check_idx_range idx_range[] = {
256 { PCI_STD_RESOURCES, PCI_STD_RESOURCE_END },
257#ifdef CONFIG_PCI_IOV
258 { PCI_IOV_RESOURCES, PCI_IOV_RESOURCE_END },
259#endif
260 };
261
262 pci_read_config_word(dev, PCI_COMMAND, &command);
263 for (i = 0; i < ARRAY_SIZE(idx_range); i++)
264 for (idx = idx_range[i].start; idx <= idx_range[i].end; idx++) {
265 r = &dev->resource[idx];
266 if (r->parent)
267 continue;
268 if (!r->start)
269 continue;
270 if (r->flags & IORESOURCE_IO)
271 disabled = !(command & PCI_COMMAND_IO);
272 else
273 disabled = !(command & PCI_COMMAND_MEMORY);
274 if (pass == disabled) {
275 dev_dbg(&dev->dev,
276 "BAR %d: reserving %pr (d=%d, p=%d)\n",
277 idx, r, disabled, pass);
278 if (pci_claim_resource(dev, idx) < 0) {
279 if (r->flags & IORESOURCE_PCI_FIXED) {
280 dev_info(&dev->dev, "BAR %d %pR is immovable\n",
281 idx, r);
282 } else {
283
284 pcibios_save_fw_addr(dev,
285 idx, r->start);
286 r->end -= r->start;
287 r->start = 0;
288 }
289 }
290 }
291 }
292 if (!pass) {
293 r = &dev->resource[PCI_ROM_RESOURCE];
294 if (r->flags & IORESOURCE_ROM_ENABLE) {
295
296
297 u32 reg;
298 dev_dbg(&dev->dev, "disabling ROM %pR\n", r);
299 r->flags &= ~IORESOURCE_ROM_ENABLE;
300 pci_read_config_dword(dev, dev->rom_base_reg, ®);
301 pci_write_config_dword(dev, dev->rom_base_reg,
302 reg & ~PCI_ROM_ADDRESS_ENABLE);
303 }
304 }
305}
306
307static void pcibios_allocate_resources(struct pci_bus *bus, int pass)
308{
309 struct pci_dev *dev;
310 struct pci_bus *child;
311
312 list_for_each_entry(dev, &bus->devices, bus_list) {
313 pcibios_allocate_dev_resources(dev, pass);
314
315 child = dev->subordinate;
316 if (child)
317 pcibios_allocate_resources(child, pass);
318 }
319}
320
321static void pcibios_allocate_dev_rom_resource(struct pci_dev *dev)
322{
323 struct resource *r;
324
325
326
327
328
329
330 r = &dev->resource[PCI_ROM_RESOURCE];
331 if (!r->flags || !r->start)
332 return;
333 if (r->parent)
334 return;
335
336 if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) {
337 r->end -= r->start;
338 r->start = 0;
339 }
340}
341static void pcibios_allocate_rom_resources(struct pci_bus *bus)
342{
343 struct pci_dev *dev;
344 struct pci_bus *child;
345
346 list_for_each_entry(dev, &bus->devices, bus_list) {
347 pcibios_allocate_dev_rom_resource(dev);
348
349 child = dev->subordinate;
350 if (child)
351 pcibios_allocate_rom_resources(child);
352 }
353}
354
355static int __init pcibios_assign_resources(void)
356{
357 struct pci_bus *bus;
358
359 if (!(pci_probe & PCI_ASSIGN_ROMS))
360 list_for_each_entry(bus, &pci_root_buses, node)
361 pcibios_allocate_rom_resources(bus);
362
363 pci_assign_unassigned_resources();
364 pcibios_fw_addr_list_del();
365
366 return 0;
367}
368
369
370
371
372
373fs_initcall(pcibios_assign_resources);
374
375void pcibios_resource_survey_bus(struct pci_bus *bus)
376{
377 dev_printk(KERN_DEBUG, &bus->dev, "Allocating resources\n");
378
379 pcibios_allocate_bus_resources(bus);
380
381 pcibios_allocate_resources(bus, 0);
382 pcibios_allocate_resources(bus, 1);
383
384 if (!(pci_probe & PCI_ASSIGN_ROMS))
385 pcibios_allocate_rom_resources(bus);
386}
387
388void __init pcibios_resource_survey(void)
389{
390 struct pci_bus *bus;
391
392 DBG("PCI: Allocating resources\n");
393
394 list_for_each_entry(bus, &pci_root_buses, node)
395 pcibios_allocate_bus_resources(bus);
396
397 list_for_each_entry(bus, &pci_root_buses, node)
398 pcibios_allocate_resources(bus, 0);
399 list_for_each_entry(bus, &pci_root_buses, node)
400 pcibios_allocate_resources(bus, 1);
401
402 e820__reserve_resources_late();
403
404
405
406
407
408 ioapic_insert_resources();
409}
410