Blame view
drivers/pci/setup-res.c
12.7 KB
b24413180 License cleanup: ... |
1 |
// SPDX-License-Identifier: GPL-2.0 |
1da177e4c Linux-2.6.12-rc2 |
2 |
/* |
df62ab5e0 PCI: Tidy comments |
3 |
* Support routines for initializing a PCI subsystem |
1da177e4c Linux-2.6.12-rc2 |
4 5 6 7 8 9 |
* * Extruded from code written by * Dave Rusling (david.rusling@reo.mts.dec.com) * David Mosberger (davidm@cs.arizona.edu) * David Miller (davem@redhat.com) * |
df62ab5e0 PCI: Tidy comments |
10 11 |
* Fixed for multiple PCI buses, 1999 Andrea Arcangeli <andrea@suse.de> * |
1da177e4c Linux-2.6.12-rc2 |
12 13 14 |
* Nov 2000, Ivan Kokshaysky <ink@jurassic.park.msu.ru> * Resource sorting */ |
1da177e4c Linux-2.6.12-rc2 |
15 |
#include <linux/kernel.h> |
363c75db1 pci: Fix files ne... |
16 |
#include <linux/export.h> |
1da177e4c Linux-2.6.12-rc2 |
17 18 19 20 21 22 |
#include <linux/pci.h> #include <linux/errno.h> #include <linux/ioport.h> #include <linux/cache.h> #include <linux/slab.h> #include "pci.h" |
6ffa2489c PCI: Separate VF ... |
23 |
static void pci_std_update_resource(struct pci_dev *dev, int resno) |
1da177e4c Linux-2.6.12-rc2 |
24 25 |
{ struct pci_bus_region region; |
9aac537e0 PCI: disable MEM ... |
26 27 |
bool disable; u16 cmd; |
1da177e4c Linux-2.6.12-rc2 |
28 29 |
u32 new, check, mask; int reg; |
14add80b5 PCI: remove unnec... |
30 |
struct resource *res = dev->resource + resno; |
1da177e4c Linux-2.6.12-rc2 |
31 |
|
63880b230 PCI: Ignore BAR u... |
32 33 |
/* Per SR-IOV spec 3.4.1.11, VF BARs are RO zero */ if (dev->is_virtfn) |
70675e0b6 PCI: Don't try to... |
34 |
return; |
70675e0b6 PCI: Don't try to... |
35 |
|
fb0f2b40f PCI legacy resour... |
36 37 38 39 |
/* * Ignore resources for unimplemented BARs and unused resource slots * for 64 bit BARs. */ |
cf7bee5a0 [PATCH] Fix resto... |
40 41 |
if (!res->flags) return; |
cd8a4d365 PCI: Check IORESO... |
42 43 |
if (res->flags & IORESOURCE_UNSET) return; |
fb0f2b40f PCI legacy resour... |
44 45 46 |
/* * Ignore non-moveable resources. This might be legacy resources for * which no functional BAR register exists or another important |
80ccba118 PCI: use dev_prin... |
47 |
* system resource we shouldn't move around. |
fb0f2b40f PCI legacy resour... |
48 49 50 |
*/ if (res->flags & IORESOURCE_PCI_FIXED) return; |
fc2798502 PCI: Convert pcib... |
51 |
pcibios_resource_to_bus(dev->bus, ®ion, res); |
45d004f4a PCI: Update BARs ... |
52 |
new = region.start; |
1da177e4c Linux-2.6.12-rc2 |
53 |
|
45d004f4a PCI: Update BARs ... |
54 |
if (res->flags & IORESOURCE_IO) { |
1da177e4c Linux-2.6.12-rc2 |
55 |
mask = (u32)PCI_BASE_ADDRESS_IO_MASK; |
45d004f4a PCI: Update BARs ... |
56 57 |
new |= res->flags & ~PCI_BASE_ADDRESS_IO_MASK; } else if (resno == PCI_ROM_RESOURCE) { |
76dc52684 PCI: Make PCI_ROM... |
58 |
mask = PCI_ROM_ADDRESS_MASK; |
45d004f4a PCI: Update BARs ... |
59 |
} else { |
1da177e4c Linux-2.6.12-rc2 |
60 |
mask = (u32)PCI_BASE_ADDRESS_MEM_MASK; |
45d004f4a PCI: Update BARs ... |
61 62 |
new |= res->flags & ~PCI_BASE_ADDRESS_MEM_MASK; } |
1da177e4c Linux-2.6.12-rc2 |
63 |
|
286c2378a PCI: Remove pci_r... |
64 65 66 |
if (resno < PCI_ROM_RESOURCE) { reg = PCI_BASE_ADDRESS_0 + 4 * resno; } else if (resno == PCI_ROM_RESOURCE) { |
0b457dde3 PCI: Add comments... |
67 68 69 70 |
/* * Apparently some Matrox devices have ROM BARs that read * as zero when disabled, so don't update ROM BARs unless |
16bbbc874 PCI: Replace lkml... |
71 72 |
* they're enabled. See * https://lore.kernel.org/r/43147B3D.1030309@vc.cvut.cz/ |
0b457dde3 PCI: Add comments... |
73 |
*/ |
755528c86 Ignore disabled R... |
74 75 |
if (!(res->flags & IORESOURCE_ROM_ENABLE)) return; |
286c2378a PCI: Remove pci_r... |
76 77 |
reg = dev->rom_base_reg; |
755528c86 Ignore disabled R... |
78 |
new |= PCI_ROM_ADDRESS_ENABLE; |
286c2378a PCI: Remove pci_r... |
79 80 |
} else return; |
1da177e4c Linux-2.6.12-rc2 |
81 |
|
9aac537e0 PCI: disable MEM ... |
82 83 84 85 86 87 88 89 90 91 92 |
/* * We can't update a 64-bit BAR atomically, so when possible, * disable decoding so that a half-updated BAR won't conflict * with another device. */ disable = (res->flags & IORESOURCE_MEM_64) && !dev->mmio_always_on; if (disable) { pci_read_config_word(dev, PCI_COMMAND, &cmd); pci_write_config_word(dev, PCI_COMMAND, cmd & ~PCI_COMMAND_MEMORY); } |
1da177e4c Linux-2.6.12-rc2 |
93 94 95 96 |
pci_write_config_dword(dev, reg, new); pci_read_config_dword(dev, reg, &check); if ((new ^ check) & mask) { |
7506dc798 PCI: Add wrappers... |
97 98 |
pci_err(dev, "BAR %d: error updating (%#08x != %#08x) ", |
80ccba118 PCI: use dev_prin... |
99 |
resno, new, check); |
1da177e4c Linux-2.6.12-rc2 |
100 |
} |
28c6821a0 PCI: fold pci_cal... |
101 |
if (res->flags & IORESOURCE_MEM_64) { |
cf7bee5a0 [PATCH] Fix resto... |
102 |
new = region.start >> 16 >> 16; |
1da177e4c Linux-2.6.12-rc2 |
103 104 105 |
pci_write_config_dword(dev, reg + 4, new); pci_read_config_dword(dev, reg + 4, &check); if (check != new) { |
7506dc798 PCI: Add wrappers... |
106 107 |
pci_err(dev, "BAR %d: error updating (high %#08x != %#08x) ", |
227f06470 PCI: Merge multi-... |
108 |
resno, new, check); |
1da177e4c Linux-2.6.12-rc2 |
109 110 |
} } |
9aac537e0 PCI: disable MEM ... |
111 112 113 |
if (disable) pci_write_config_word(dev, PCI_COMMAND, cmd); |
1da177e4c Linux-2.6.12-rc2 |
114 |
} |
6ffa2489c PCI: Separate VF ... |
115 116 117 118 119 120 121 122 123 |
void pci_update_resource(struct pci_dev *dev, int resno) { if (resno <= PCI_ROM_RESOURCE) pci_std_update_resource(dev, resno); #ifdef CONFIG_PCI_IOV else if (resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END) pci_iov_update_resource(dev, resno); #endif } |
96bde06a2 pci: do not mark ... |
124 |
int pci_claim_resource(struct pci_dev *dev, int resource) |
1da177e4c Linux-2.6.12-rc2 |
125 126 |
{ struct resource *res = &dev->resource[resource]; |
966f3a757 PCI: for address ... |
127 |
struct resource *root, *conflict; |
1da177e4c Linux-2.6.12-rc2 |
128 |
|
29003beb7 PCI: Don't try to... |
129 |
if (res->flags & IORESOURCE_UNSET) { |
7506dc798 PCI: Add wrappers... |
130 131 |
pci_info(dev, "can't claim BAR %d %pR: no address assigned ", |
29003beb7 PCI: Don't try to... |
132 133 134 |
resource, res); return -EINVAL; } |
16d917b13 PCI: Don't attemp... |
135 136 137 138 139 140 141 |
/* * If we have a shadow copy in RAM, the PCI device doesn't respond * to the shadow range, so we don't need to claim it, and upstream * bridges don't need to route the range to the device. */ if (res->flags & IORESOURCE_ROM_SHADOW) return 0; |
cebd78a8c Fix pci_claim_res... |
142 |
root = pci_find_parent_resource(dev, res); |
865df576e PCI: improve disc... |
143 |
if (!root) { |
7506dc798 PCI: Add wrappers... |
144 145 |
pci_info(dev, "can't claim BAR %d %pR: no compatible bridge window ", |
29003beb7 PCI: Don't try to... |
146 |
resource, res); |
c770cb4cb PCI: Mark invalid... |
147 |
res->flags |= IORESOURCE_UNSET; |
865df576e PCI: improve disc... |
148 |
return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
149 |
} |
966f3a757 PCI: for address ... |
150 151 |
conflict = request_resource_conflict(root, res); if (conflict) { |
7506dc798 PCI: Add wrappers... |
152 153 |
pci_info(dev, "can't claim BAR %d %pR: address conflict with %s %pR ", |
29003beb7 PCI: Don't try to... |
154 |
resource, res, conflict->name, conflict); |
c770cb4cb PCI: Mark invalid... |
155 |
res->flags |= IORESOURCE_UNSET; |
966f3a757 PCI: for address ... |
156 157 |
return -EBUSY; } |
865df576e PCI: improve disc... |
158 |
|
966f3a757 PCI: for address ... |
159 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
160 |
} |
eaa959df2 PCI: export pci_c... |
161 |
EXPORT_SYMBOL(pci_claim_resource); |
1da177e4c Linux-2.6.12-rc2 |
162 |
|
32a9a682b PCI: allow assign... |
163 164 |
void pci_disable_bridge_window(struct pci_dev *dev) { |
32a9a682b PCI: allow assign... |
165 166 167 168 169 170 171 172 |
/* MMIO Base/Limit */ pci_write_config_dword(dev, PCI_MEMORY_BASE, 0x0000fff0); /* Prefetchable MMIO Base/Limit */ pci_write_config_dword(dev, PCI_PREF_LIMIT_UPPER32, 0); pci_write_config_dword(dev, PCI_PREF_MEMORY_BASE, 0x0000fff0); pci_write_config_dword(dev, PCI_PREF_BASE_UPPER32, 0xffffffff); } |
2bbc69422 PCI : ability to ... |
173 |
|
6535943fb x86/PCI: Convert ... |
174 175 176 177 178 179 180 181 182 183 184 185 186 |
/* * Generic function that returns a value indicating that the device's * original BIOS BAR address was not saved and so is not available for * reinstatement. * * Can be over-ridden by architecture specific code that implements * reinstatement functionality rather than leaving it disabled when * normal allocation attempts fail. */ resource_size_t __weak pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx) { return 0; } |
f7625980f PCI: Fix whitespa... |
187 |
static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev, |
2bbc69422 PCI : ability to ... |
188 189 190 |
int resno, resource_size_t size) { struct resource *root, *conflict; |
6535943fb x86/PCI: Convert ... |
191 |
resource_size_t fw_addr, start, end; |
58c84eda0 PCI: fall back to... |
192 |
|
6535943fb x86/PCI: Convert ... |
193 194 |
fw_addr = pcibios_retrieve_fw_addr(dev, resno); if (!fw_addr) |
947788359 PCI: Return conve... |
195 |
return -ENOMEM; |
6535943fb x86/PCI: Convert ... |
196 |
|
2bbc69422 PCI : ability to ... |
197 198 |
start = res->start; end = res->end; |
6535943fb x86/PCI: Convert ... |
199 |
res->start = fw_addr; |
2bbc69422 PCI : ability to ... |
200 |
res->end = res->start + size - 1; |
0b26cd694 PCI: Clear IORESO... |
201 |
res->flags &= ~IORESOURCE_UNSET; |
351fc6d1a PCI: Fix starting... |
202 203 204 205 206 207 208 209 |
root = pci_find_parent_resource(dev, res); if (!root) { if (res->flags & IORESOURCE_IO) root = &ioport_resource; else root = &iomem_resource; } |
7506dc798 PCI: Add wrappers... |
210 211 |
pci_info(dev, "BAR %d: trying firmware assignment %pR ", |
2bbc69422 PCI : ability to ... |
212 213 214 |
resno, res); conflict = request_resource_conflict(root, res); if (conflict) { |
7506dc798 PCI: Add wrappers... |
215 216 |
pci_info(dev, "BAR %d: %pR conflicts with %s %pR ", |
947788359 PCI: Return conve... |
217 |
resno, res, conflict->name, conflict); |
2bbc69422 PCI : ability to ... |
218 219 |
res->start = start; res->end = end; |
0b26cd694 PCI: Clear IORESO... |
220 |
res->flags |= IORESOURCE_UNSET; |
947788359 PCI: Return conve... |
221 |
return -EBUSY; |
2bbc69422 PCI : ability to ... |
222 |
} |
947788359 PCI: Return conve... |
223 |
return 0; |
2bbc69422 PCI : ability to ... |
224 |
} |
ecf677c8d PCI: Add a generi... |
225 226 227 228 229 230 231 232 233 234 235 236 |
/* * We don't have to worry about legacy ISA devices, so nothing to do here. * This is marked as __weak because multiple architectures define it; it should * eventually go away. */ resource_size_t __weak pcibios_align_resource(void *data, const struct resource *res, resource_size_t size, resource_size_t align) { return res->start; } |
fe6dacdb1 PCI: reorder __pc... |
237 238 239 240 241 242 243 244 |
static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev, int resno, resource_size_t size, resource_size_t align) { struct resource *res = dev->resource + resno; resource_size_t min; int ret; min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM; |
67d29b5c6 PCI: Add resource... |
245 246 247 248 249 250 251 |
/* * First, try exact prefetching match. Even if a 64-bit * prefetchable bridge window is below 4GB, we can't put a 32-bit * prefetchable resource in it because pbus_size_mem() assumes a * 64-bit window will contain no 32-bit resources. If we assign * things differently than they were sized, not everything will fit. */ |
fe6dacdb1 PCI: reorder __pc... |
252 |
ret = pci_bus_alloc_resource(bus, res, size, align, min, |
5b2854155 PCI: Restrict 64-... |
253 |
IORESOURCE_PREFETCH | IORESOURCE_MEM_64, |
fe6dacdb1 PCI: reorder __pc... |
254 |
pcibios_align_resource, dev); |
d3689df04 PCI: Simplify __p... |
255 256 |
if (ret == 0) return 0; |
fe6dacdb1 PCI: reorder __pc... |
257 |
|
67d29b5c6 PCI: Add resource... |
258 259 260 261 |
/* * If the prefetchable window is only 32 bits wide, we can put * 64-bit prefetchable resources in it. */ |
d3689df04 PCI: Simplify __p... |
262 |
if ((res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) == |
5b2854155 PCI: Restrict 64-... |
263 |
(IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) { |
5b2854155 PCI: Restrict 64-... |
264 265 |
ret = pci_bus_alloc_resource(bus, res, size, align, min, IORESOURCE_PREFETCH, |
fe6dacdb1 PCI: reorder __pc... |
266 |
pcibios_align_resource, dev); |
d3689df04 PCI: Simplify __p... |
267 268 |
if (ret == 0) return 0; |
fe6dacdb1 PCI: reorder __pc... |
269 |
} |
5b2854155 PCI: Restrict 64-... |
270 |
|
67d29b5c6 PCI: Add resource... |
271 272 273 274 275 276 277 |
/* * If we didn't find a better match, we can put any memory resource * in a non-prefetchable window. If this resource is 32 bits and * non-prefetchable, the first call already tried the only possibility * so we don't need to try again. */ if (res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) |
fe6dacdb1 PCI: reorder __pc... |
278 279 |
ret = pci_bus_alloc_resource(bus, res, size, align, min, 0, pcibios_align_resource, dev); |
67d29b5c6 PCI: Add resource... |
280 |
|
fe6dacdb1 PCI: reorder __pc... |
281 282 |
return ret; } |
d6776e6d5 PCI: fix truncati... |
283 284 |
static int _pci_assign_resource(struct pci_dev *dev, int resno, resource_size_t size, resource_size_t min_align) |
2bbc69422 PCI : ability to ... |
285 |
{ |
2bbc69422 PCI : ability to ... |
286 287 |
struct pci_bus *bus; int ret; |
58c84eda0 PCI: fall back to... |
288 |
|
2bbc69422 PCI : ability to ... |
289 290 291 292 293 294 |
bus = dev->bus; while ((ret = __pci_assign_resource(bus, dev, resno, size, min_align))) { if (!bus->parent || !bus->self->transparent) break; bus = bus->parent; } |
2bbc69422 PCI : ability to ... |
295 296 |
return ret; } |
d09ee9687 PCI: improve reso... |
297 298 299 |
int pci_assign_resource(struct pci_dev *dev, int resno) { struct resource *res = dev->resource + resno; |
2bbc69422 PCI : ability to ... |
300 |
resource_size_t align, size; |
d09ee9687 PCI: improve reso... |
301 |
int ret; |
2ea4adf75 PCI: Don't assign... |
302 303 |
if (res->flags & IORESOURCE_PCI_FIXED) return 0; |
bd064f0a2 PCI: Mark resourc... |
304 |
res->flags |= IORESOURCE_UNSET; |
6faf17f6f PCI SR-IOV: corre... |
305 |
align = pci_resource_alignment(dev, res); |
d09ee9687 PCI: improve reso... |
306 |
if (!align) { |
7506dc798 PCI: Add wrappers... |
307 308 |
pci_info(dev, "BAR %d: can't assign %pR (bogus alignment) ", |
227f06470 PCI: Merge multi-... |
309 |
resno, res); |
d09ee9687 PCI: improve reso... |
310 311 |
return -EINVAL; } |
2bbc69422 PCI : ability to ... |
312 313 |
size = resource_size(res); ret = _pci_assign_resource(dev, resno, size, align); |
d09ee9687 PCI: improve reso... |
314 |
|
2bbc69422 PCI : ability to ... |
315 316 317 318 319 |
/* * If we failed to assign anything, let's try the address * where firmware left it. That at least has a chance of * working, which is better than just leaving it disabled. */ |
64da465e9 PCI: Tidy resourc... |
320 |
if (ret < 0) { |
7506dc798 PCI: Add wrappers... |
321 322 |
pci_info(dev, "BAR %d: no space for %pR ", resno, res); |
2bbc69422 PCI : ability to ... |
323 |
ret = pci_revert_fw_address(res, dev, resno, size); |
64da465e9 PCI: Tidy resourc... |
324 |
} |
d09ee9687 PCI: improve reso... |
325 |
|
64da465e9 PCI: Tidy resourc... |
326 |
if (ret < 0) { |
7506dc798 PCI: Add wrappers... |
327 328 |
pci_info(dev, "BAR %d: failed to assign %pR ", resno, res); |
28f6dbe2c PCI: Cleanup cont... |
329 |
return ret; |
64da465e9 PCI: Tidy resourc... |
330 |
} |
28f6dbe2c PCI: Cleanup cont... |
331 332 333 |
res->flags &= ~IORESOURCE_UNSET; res->flags &= ~IORESOURCE_STARTALIGN; |
7506dc798 PCI: Add wrappers... |
334 335 |
pci_info(dev, "BAR %d: assigned %pR ", resno, res); |
28f6dbe2c PCI: Cleanup cont... |
336 337 338 339 |
if (resno < PCI_BRIDGE_RESOURCES) pci_update_resource(dev, resno); return 0; |
d09ee9687 PCI: improve reso... |
340 |
} |
b7fe94342 PCI: Move EXPORT_... |
341 |
EXPORT_SYMBOL(pci_assign_resource); |
d09ee9687 PCI: improve reso... |
342 |
|
fe6dacdb1 PCI: reorder __pc... |
343 344 345 346 |
int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsize, resource_size_t min_align) { struct resource *res = dev->resource + resno; |
c33377082 PCI: Keep origina... |
347 |
unsigned long flags; |
fe6dacdb1 PCI: reorder __pc... |
348 349 |
resource_size_t new_size; int ret; |
2ea4adf75 PCI: Don't assign... |
350 351 |
if (res->flags & IORESOURCE_PCI_FIXED) return 0; |
c33377082 PCI: Keep origina... |
352 |
flags = res->flags; |
bd064f0a2 PCI: Mark resourc... |
353 |
res->flags |= IORESOURCE_UNSET; |
fe6dacdb1 PCI: reorder __pc... |
354 |
if (!res->parent) { |
7506dc798 PCI: Add wrappers... |
355 356 |
pci_info(dev, "BAR %d: can't reassign an unassigned resource %pR ", |
227f06470 PCI: Merge multi-... |
357 |
resno, res); |
fe6dacdb1 PCI: reorder __pc... |
358 359 360 361 362 363 |
return -EINVAL; } /* already aligned with min_align */ new_size = resource_size(res) + addsize; ret = _pci_assign_resource(dev, resno, new_size, min_align); |
28f6dbe2c PCI: Cleanup cont... |
364 |
if (ret) { |
c33377082 PCI: Keep origina... |
365 |
res->flags = flags; |
7506dc798 PCI: Add wrappers... |
366 367 |
pci_info(dev, "BAR %d: %pR (failed to expand by %#llx) ", |
c33377082 PCI: Keep origina... |
368 |
resno, res, (unsigned long long) addsize); |
28f6dbe2c PCI: Cleanup cont... |
369 |
return ret; |
fe6dacdb1 PCI: reorder __pc... |
370 |
} |
c33377082 PCI: Keep origina... |
371 |
|
28f6dbe2c PCI: Cleanup cont... |
372 373 |
res->flags &= ~IORESOURCE_UNSET; res->flags &= ~IORESOURCE_STARTALIGN; |
7506dc798 PCI: Add wrappers... |
374 375 |
pci_info(dev, "BAR %d: reassigned %pR (expanded by %#llx) ", |
64da465e9 PCI: Tidy resourc... |
376 |
resno, res, (unsigned long long) addsize); |
28f6dbe2c PCI: Cleanup cont... |
377 378 379 380 |
if (resno < PCI_BRIDGE_RESOURCES) pci_update_resource(dev, resno); return 0; |
fe6dacdb1 PCI: reorder __pc... |
381 |
} |
8bb705e3e PCI: Add pci_resi... |
382 383 384 |
void pci_release_resource(struct pci_dev *dev, int resno) { struct resource *res = dev->resource + resno; |
7506dc798 PCI: Add wrappers... |
385 386 |
pci_info(dev, "BAR %d: releasing %pR ", resno, res); |
c37406e05 PCI: Allow releas... |
387 388 389 |
if (!res->parent) return; |
8bb705e3e PCI: Add pci_resi... |
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 |
release_resource(res); res->end = resource_size(res) - 1; res->start = 0; res->flags |= IORESOURCE_UNSET; } EXPORT_SYMBOL(pci_release_resource); int pci_resize_resource(struct pci_dev *dev, int resno, int size) { struct resource *res = dev->resource + resno; int old, ret; u32 sizes; u16 cmd; /* Make sure the resource isn't assigned before resizing it. */ if (!(res->flags & IORESOURCE_UNSET)) return -EBUSY; pci_read_config_word(dev, PCI_COMMAND, &cmd); if (cmd & PCI_COMMAND_MEMORY) return -EBUSY; sizes = pci_rebar_get_possible_sizes(dev, resno); if (!sizes) return -ENOTSUPP; if (!(sizes & BIT(size))) return -EINVAL; old = pci_rebar_get_current_size(dev, resno); if (old < 0) return old; ret = pci_rebar_set_size(dev, resno, size); if (ret) return ret; res->end = res->start + pci_rebar_size_to_bytes(size) - 1; /* Check if the new config works by trying to assign everything. */ |
d09ddd819 PCI: Allow pci_re... |
430 431 432 433 434 |
if (dev->bus->self) { ret = pci_reassign_bridge_resources(dev->bus->self, res->flags); if (ret) goto error_resize; } |
8bb705e3e PCI: Add pci_resi... |
435 436 437 438 439 440 441 442 |
return 0; error_resize: pci_rebar_set_size(dev, resno, old); res->end = res->start + pci_rebar_size_to_bytes(old) - 1; return ret; } EXPORT_SYMBOL(pci_resize_resource); |
842de40d9 PCI: add generic ... |
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 |
int pci_enable_resources(struct pci_dev *dev, int mask) { u16 cmd, old_cmd; int i; struct resource *r; pci_read_config_word(dev, PCI_COMMAND, &cmd); old_cmd = cmd; for (i = 0; i < PCI_NUM_RESOURCES; i++) { if (!(mask & (1 << i))) continue; r = &dev->resource[i]; if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM))) continue; if ((i == PCI_ROM_RESOURCE) && (!(r->flags & IORESOURCE_ROM_ENABLE))) continue; |
3cedcc362 PCI: Don't enable... |
463 |
if (r->flags & IORESOURCE_UNSET) { |
7506dc798 PCI: Add wrappers... |
464 465 |
pci_err(dev, "can't enable device: BAR %d %pR not assigned ", |
3cedcc362 PCI: Don't enable... |
466 467 468 |
i, r); return -EINVAL; } |
842de40d9 PCI: add generic ... |
469 |
if (!r->parent) { |
7506dc798 PCI: Add wrappers... |
470 471 |
pci_err(dev, "can't enable device: BAR %d %pR not claimed ", |
3cedcc362 PCI: Don't enable... |
472 |
i, r); |
842de40d9 PCI: add generic ... |
473 474 475 476 477 478 479 480 481 482 |
return -EINVAL; } if (r->flags & IORESOURCE_IO) cmd |= PCI_COMMAND_IO; if (r->flags & IORESOURCE_MEM) cmd |= PCI_COMMAND_MEMORY; } if (cmd != old_cmd) { |
7506dc798 PCI: Add wrappers... |
483 484 |
pci_info(dev, "enabling device (%04x -> %04x) ", old_cmd, cmd); |
842de40d9 PCI: add generic ... |
485 486 487 488 |
pci_write_config_word(dev, PCI_COMMAND, cmd); } return 0; } |