Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/x86/pci/i386.c
26442 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Low-Level PCI Access for i386 machines
4
*
5
* Copyright 1993, 1994 Drew Eckhardt
6
* Visionary Computing
7
* (Unix and Linux consulting and custom programming)
8
* [email protected]
9
* +1 (303) 786-7975
10
*
11
* Drew's work was sponsored by:
12
* iX Multiuser Multitasking Magazine
13
* Hannover, Germany
14
* [email protected]
15
*
16
* Copyright 1997--2000 Martin Mares <[email protected]>
17
*
18
* For more information, please consult the following manuals (look at
19
* http://www.pcisig.com/ for how to get them):
20
*
21
* PCI BIOS Specification
22
* PCI Local Bus Specification
23
* PCI to PCI Bridge Specification
24
* PCI System Design Guide
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
* This list of dynamic mappings is for temporarily maintaining
45
* original BIOS BAR addresses for possible reinstatement.
46
*/
47
struct pcibios_fwaddrmap {
48
struct list_head list;
49
struct pci_dev *dev;
50
resource_size_t fw_addr[DEVICE_COUNT_RESOURCE];
51
};
52
53
static LIST_HEAD(pcibios_fwaddrmappings);
54
static DEFINE_SPINLOCK(pcibios_fwaddrmap_lock);
55
static bool pcibios_fw_addr_done;
56
57
/* Must be called with 'pcibios_fwaddrmap_lock' lock held. */
58
static 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
71
static void
72
pcibios_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
99
resource_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
117
static 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
132
static int
133
skip_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
* We need to avoid collisions with `mirrored' VGA ports
143
* and other strange ISA hardware, so we always want the
144
* addresses to be allocated in the 0x000-0x0ff region
145
* modulo 0x400.
146
*
147
* Why? Because some silly external IO cards only decode
148
* the low 10 bits of the IO address. The 0x00-0xff region
149
* is reserved for motherboard devices that decode all 16
150
* bits, so it's ok to allocate at, say, 0x2800-0x28ff,
151
* but we want to try to avoid allocating at 0x2900-0x2bff
152
* which might have be mirrored at 0x0100-0x03ff..
153
*/
154
resource_size_t
155
pcibios_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
/* The low 1MB range is reserved for ISA cards */
168
if (start < BIOS_END)
169
start = BIOS_END;
170
}
171
return start;
172
}
173
EXPORT_SYMBOL(pcibios_align_resource);
174
175
/*
176
* Handle resources of PCI devices. If the world were perfect, we could
177
* just allocate all the resource regions and do nothing more. It isn't.
178
* On the other hand, we cannot just re-allocate all devices, as it would
179
* require us to know lots of host bridge internals. So we attempt to
180
* keep as much of the original configuration as possible, but tweak it
181
* when it's found to be wrong.
182
*
183
* Known BIOS problems we have to work around:
184
* - I/O or memory regions not configured
185
* - regions configured, but not enabled in the command register
186
* - bogus I/O addresses above 64K used
187
* - expansion ROMs left enabled (this may sound harmless, but given
188
* the fact the PCI specs explicitly allow address decoders to be
189
* shared between expansion ROMs and other resource regions, it's
190
* at least dangerous)
191
* - bad resource sizes or overlaps with other regions
192
*
193
* Our solution:
194
* (1) Allocate resources for all buses behind PCI-to-PCI bridges.
195
* This gives us fixed barriers on where we can allocate.
196
* (2) Allocate resources for all enabled devices. If there is
197
* a collision, just mark the resource as unallocated. Also
198
* disable expansion ROMs during this step.
199
* (3) Try to allocate resources for disabled devices. If the
200
* resources were assigned correctly, everything goes well,
201
* if they weren't, they won't disturb allocation of other
202
* resources.
203
* (4) Assign new addresses to resources which were either
204
* not configured at all or misconfigured. If explicitly
205
* requested by the user, configure expansion ROM address
206
* as well.
207
*/
208
209
static 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) /* Already allocated */
219
continue;
220
if (!r->start || pci_claim_bridge_resource(dev, idx) < 0) {
221
/*
222
* Something is wrong with the region.
223
* Invalidate the resource to prevent
224
* child resource allocations in this
225
* range.
226
*/
227
r->start = r->end = 0;
228
r->flags = 0;
229
}
230
}
231
}
232
233
static void pcibios_allocate_bus_resources(struct pci_bus *bus)
234
{
235
struct pci_bus *child;
236
237
/* Depth-First Search on bus tree */
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
244
struct pci_check_idx_range {
245
int start;
246
int end;
247
};
248
249
static 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) /* Already allocated */
267
continue;
268
if (!r->start) /* Address not assigned at all */
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
/* We'll assign a new address later */
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
/* Turn the ROM off, leave the resource region,
296
* but keep it unregistered. */
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, &reg);
301
pci_write_config_dword(dev, dev->rom_base_reg,
302
reg & ~PCI_ROM_ADDRESS_ENABLE);
303
}
304
}
305
}
306
307
static 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
321
static void pcibios_allocate_dev_rom_resource(struct pci_dev *dev)
322
{
323
struct resource *r;
324
325
/*
326
* Try to use BIOS settings for ROMs, otherwise let
327
* pci_assign_unassigned_resources() allocate the new
328
* addresses.
329
*/
330
r = &dev->resource[PCI_ROM_RESOURCE];
331
if (!r->flags || !r->start)
332
return;
333
if (r->parent) /* Already allocated */
334
return;
335
336
if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) {
337
r->end -= r->start;
338
r->start = 0;
339
}
340
}
341
static 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
355
static 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
* This is an fs_initcall (one below subsys_initcall) in order to reserve
371
* resources properly.
372
*/
373
fs_initcall(pcibios_assign_resources);
374
375
void 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
388
void __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
* Insert the IO APIC resources after PCI initialization has
405
* occurred to handle IO APICS that are mapped in on a BAR in
406
* PCI space, but before trying to assign unassigned pci res.
407
*/
408
ioapic_insert_resources();
409
}
410
411