aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-26 00:18:18 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-26 00:18:18 -0500
commit556f12f602ac0a18a82ca83e9f8e8547688fc633 (patch)
treed4051f6dd57968c8e8e660ad117c5bedc2aa7e8e /arch/x86
parentfffddfd6c8e0c10c42c6e2cc54ba880fcc36ebbb (diff)
parent018ba0a6efada61b9bc17500101d81c3d35807c2 (diff)
Merge tag 'pci-v3.9-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI changes from Bjorn Helgaas: "Host bridge hotplug - Major overhaul of ACPI host bridge add/start (Rafael Wysocki, Yinghai Lu) - Major overhaul of PCI/ACPI binding (Rafael Wysocki, Yinghai Lu) - Split out ACPI host bridge and ACPI PCI device hotplug (Yinghai Lu) - Stop caching _PRT and make independent of bus numbers (Yinghai Lu) PCI device hotplug - Clean up cpqphp dead code (Sasha Levin) - Disable ARI unless device and upstream bridge support it (Yijing Wang) - Initialize all hot-added devices (not functions 0-7) (Yijing Wang) Power management - Don't touch ASPM if disabled (Joe Lawrence) - Fix ASPM link state management (Myron Stowe) Miscellaneous - Fix PCI_EXP_FLAGS accessor (Alex Williamson) - Disable Bus Master in pci_device_shutdown (Konstantin Khlebnikov) - Document hotplug resource and MPS parameters (Yijing Wang) - Add accessor for PCIe capabilities (Myron Stowe) - Drop pciehp suspend/resume messages (Paul Bolle) - Make pci_slot built-in only (not a module) (Jiang Liu) - Remove unused PCI/ACPI bind ops (Jiang Liu) - Removed used pci_root_bus (Bjorn Helgaas)" * tag 'pci-v3.9-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (51 commits) PCI/ACPI: Don't cache _PRT, and don't associate them with bus numbers PCI: Fix PCI Express Capability accessors for PCI_EXP_FLAGS ACPI / PCI: Make pci_slot built-in only, not a module PCI/PM: Clear state_saved during suspend PCI: Use atomic_inc_return() rather than atomic_add_return() PCI: Catch attempts to disable already-disabled devices PCI: Disable Bus Master unconditionally in pci_device_shutdown() PCI: acpiphp: Remove dead code for PCI host bridge hotplug PCI: acpiphp: Create companion ACPI devices before creating PCI devices PCI: Remove unused "rc" in virtfn_add_bus() PCI: pciehp: Drop suspend/resume ENTRY messages PCI/ASPM: Don't touch ASPM if forcibly disabled PCI/ASPM: Deallocate upstream link state even if device is not PCIe PCI: Document MPS parameters pci=pcie_bus_safe, pci=pcie_bus_perf, etc PCI: Document hpiosize= and hpmemsize= resource reservation parameters PCI: Use PCI Express Capability accessor PCI: Introduce accessor to retrieve PCIe Capabilities Register PCI: Put pci_dev in device tree as early as possible PCI: Skip attaching driver in device_add() PCI: acpiphp: Keep driver loaded even if no slots found ...
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/include/asm/pci.h3
-rw-r--r--arch/x86/include/asm/pci_x86.h1
-rw-r--r--arch/x86/pci/acpi.c9
-rw-r--r--arch/x86/pci/common.c1
-rw-r--r--arch/x86/pci/i386.c185
-rw-r--r--arch/x86/pci/legacy.c2
-rw-r--r--arch/x86/pci/numaq_32.c2
7 files changed, 135 insertions, 68 deletions
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index c28fd02f4bf7..d9e9e6c7ed32 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -14,6 +14,9 @@
14struct pci_sysdata { 14struct pci_sysdata {
15 int domain; /* PCI domain */ 15 int domain; /* PCI domain */
16 int node; /* NUMA node */ 16 int node; /* NUMA node */
17#ifdef CONFIG_ACPI
18 void *acpi; /* ACPI-specific data */
19#endif
17#ifdef CONFIG_X86_64 20#ifdef CONFIG_X86_64
18 void *iommu; /* IOMMU private data */ 21 void *iommu; /* IOMMU private data */
19#endif 22#endif
diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h
index 747e5a38b590..fa1195dae425 100644
--- a/arch/x86/include/asm/pci_x86.h
+++ b/arch/x86/include/asm/pci_x86.h
@@ -54,7 +54,6 @@ void pcibios_set_cache_line_size(void);
54/* pci-pc.c */ 54/* pci-pc.c */
55 55
56extern int pcibios_last_bus; 56extern int pcibios_last_bus;
57extern struct pci_bus *pci_root_bus;
58extern struct pci_ops pci_root_ops; 57extern struct pci_ops pci_root_ops;
59 58
60void pcibios_scan_specific_bus(int busn); 59void pcibios_scan_specific_bus(int busn);
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 53ea60458e01..3e724256dbee 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -521,6 +521,7 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
521 sd = &info->sd; 521 sd = &info->sd;
522 sd->domain = domain; 522 sd->domain = domain;
523 sd->node = node; 523 sd->node = node;
524 sd->acpi = device->handle;
524 /* 525 /*
525 * Maybe the desired pci bus has been already scanned. In such case 526 * Maybe the desired pci bus has been already scanned. In such case
526 * it is unnecessary to scan the pci bus with the given domain,busnum. 527 * it is unnecessary to scan the pci bus with the given domain,busnum.
@@ -592,6 +593,14 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
592 return bus; 593 return bus;
593} 594}
594 595
596int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
597{
598 struct pci_sysdata *sd = bridge->bus->sysdata;
599
600 ACPI_HANDLE_SET(&bridge->dev, sd->acpi);
601 return 0;
602}
603
595int __init pci_acpi_init(void) 604int __init pci_acpi_init(void)
596{ 605{
597 struct pci_dev *dev = NULL; 606 struct pci_dev *dev = NULL;
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index ccd0ab3ab899..901177d75ff5 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -34,7 +34,6 @@ int noioapicreroute = 1;
34#endif 34#endif
35int pcibios_last_bus = -1; 35int pcibios_last_bus = -1;
36unsigned long pirq_table_addr; 36unsigned long pirq_table_addr;
37struct pci_bus *pci_root_bus;
38const struct pci_raw_ops *__read_mostly raw_pci_ops; 37const struct pci_raw_ops *__read_mostly raw_pci_ops;
39const struct pci_raw_ops *__read_mostly raw_pci_ext_ops; 38const struct pci_raw_ops *__read_mostly raw_pci_ext_ops;
40 39
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index dd8ca6f7223b..94919e307f8e 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -51,6 +51,7 @@ struct pcibios_fwaddrmap {
51 51
52static LIST_HEAD(pcibios_fwaddrmappings); 52static LIST_HEAD(pcibios_fwaddrmappings);
53static DEFINE_SPINLOCK(pcibios_fwaddrmap_lock); 53static DEFINE_SPINLOCK(pcibios_fwaddrmap_lock);
54static bool pcibios_fw_addr_done;
54 55
55/* Must be called with 'pcibios_fwaddrmap_lock' lock held. */ 56/* Must be called with 'pcibios_fwaddrmap_lock' lock held. */
56static struct pcibios_fwaddrmap *pcibios_fwaddrmap_lookup(struct pci_dev *dev) 57static struct pcibios_fwaddrmap *pcibios_fwaddrmap_lookup(struct pci_dev *dev)
@@ -72,6 +73,9 @@ pcibios_save_fw_addr(struct pci_dev *dev, int idx, resource_size_t fw_addr)
72 unsigned long flags; 73 unsigned long flags;
73 struct pcibios_fwaddrmap *map; 74 struct pcibios_fwaddrmap *map;
74 75
76 if (pcibios_fw_addr_done)
77 return;
78
75 spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags); 79 spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags);
76 map = pcibios_fwaddrmap_lookup(dev); 80 map = pcibios_fwaddrmap_lookup(dev);
77 if (!map) { 81 if (!map) {
@@ -97,6 +101,9 @@ resource_size_t pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx)
97 struct pcibios_fwaddrmap *map; 101 struct pcibios_fwaddrmap *map;
98 resource_size_t fw_addr = 0; 102 resource_size_t fw_addr = 0;
99 103
104 if (pcibios_fw_addr_done)
105 return 0;
106
100 spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags); 107 spin_lock_irqsave(&pcibios_fwaddrmap_lock, flags);
101 map = pcibios_fwaddrmap_lookup(dev); 108 map = pcibios_fwaddrmap_lookup(dev);
102 if (map) 109 if (map)
@@ -106,7 +113,7 @@ resource_size_t pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx)
106 return fw_addr; 113 return fw_addr;
107} 114}
108 115
109static void pcibios_fw_addr_list_del(void) 116static void __init pcibios_fw_addr_list_del(void)
110{ 117{
111 unsigned long flags; 118 unsigned long flags;
112 struct pcibios_fwaddrmap *entry, *next; 119 struct pcibios_fwaddrmap *entry, *next;
@@ -118,6 +125,7 @@ static void pcibios_fw_addr_list_del(void)
118 kfree(entry); 125 kfree(entry);
119 } 126 }
120 spin_unlock_irqrestore(&pcibios_fwaddrmap_lock, flags); 127 spin_unlock_irqrestore(&pcibios_fwaddrmap_lock, flags);
128 pcibios_fw_addr_done = true;
121} 129}
122 130
123static int 131static int
@@ -193,46 +201,46 @@ EXPORT_SYMBOL(pcibios_align_resource);
193 * as well. 201 * as well.
194 */ 202 */
195 203
196static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) 204static void pcibios_allocate_bridge_resources(struct pci_dev *dev)
197{ 205{
198 struct pci_bus *bus;
199 struct pci_dev *dev;
200 int idx; 206 int idx;
201 struct resource *r; 207 struct resource *r;
202 208
203 /* Depth-First Search on bus tree */ 209 for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
204 list_for_each_entry(bus, bus_list, node) { 210 r = &dev->resource[idx];
205 if ((dev = bus->self)) { 211 if (!r->flags)
206 for (idx = PCI_BRIDGE_RESOURCES; 212 continue;
207 idx < PCI_NUM_RESOURCES; idx++) { 213 if (!r->start || pci_claim_resource(dev, idx) < 0) {
208 r = &dev->resource[idx]; 214 /*
209 if (!r->flags) 215 * Something is wrong with the region.
210 continue; 216 * Invalidate the resource to prevent
211 if (!r->start || 217 * child resource allocations in this
212 pci_claim_resource(dev, idx) < 0) { 218 * range.
213 /* 219 */
214 * Something is wrong with the region. 220 r->start = r->end = 0;
215 * Invalidate the resource to prevent 221 r->flags = 0;
216 * child resource allocations in this
217 * range.
218 */
219 r->start = r->end = 0;
220 r->flags = 0;
221 }
222 }
223 } 222 }
224 pcibios_allocate_bus_resources(&bus->children);
225 } 223 }
226} 224}
227 225
226static void pcibios_allocate_bus_resources(struct pci_bus *bus)
227{
228 struct pci_bus *child;
229
230 /* Depth-First Search on bus tree */
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
228struct pci_check_idx_range { 237struct pci_check_idx_range {
229 int start; 238 int start;
230 int end; 239 int end;
231}; 240};
232 241
233static void __init pcibios_allocate_resources(int pass) 242static void pcibios_allocate_dev_resources(struct pci_dev *dev, int pass)
234{ 243{
235 struct pci_dev *dev = NULL;
236 int idx, disabled, i; 244 int idx, disabled, i;
237 u16 command; 245 u16 command;
238 struct resource *r; 246 struct resource *r;
@@ -244,14 +252,13 @@ static void __init pcibios_allocate_resources(int pass)
244#endif 252#endif
245 }; 253 };
246 254
247 for_each_pci_dev(dev) { 255 pci_read_config_word(dev, PCI_COMMAND, &command);
248 pci_read_config_word(dev, PCI_COMMAND, &command); 256 for (i = 0; i < ARRAY_SIZE(idx_range); i++)
249 for (i = 0; i < ARRAY_SIZE(idx_range); i++)
250 for (idx = idx_range[i].start; idx <= idx_range[i].end; idx++) { 257 for (idx = idx_range[i].start; idx <= idx_range[i].end; idx++) {
251 r = &dev->resource[idx]; 258 r = &dev->resource[idx];
252 if (r->parent) /* Already allocated */ 259 if (r->parent) /* Already allocated */
253 continue; 260 continue;
254 if (!r->start) /* Address not assigned at all */ 261 if (!r->start) /* Address not assigned at all */
255 continue; 262 continue;
256 if (r->flags & IORESOURCE_IO) 263 if (r->flags & IORESOURCE_IO)
257 disabled = !(command & PCI_COMMAND_IO); 264 disabled = !(command & PCI_COMMAND_IO);
@@ -270,44 +277,74 @@ static void __init pcibios_allocate_resources(int pass)
270 } 277 }
271 } 278 }
272 } 279 }
273 if (!pass) { 280 if (!pass) {
274 r = &dev->resource[PCI_ROM_RESOURCE]; 281 r = &dev->resource[PCI_ROM_RESOURCE];
275 if (r->flags & IORESOURCE_ROM_ENABLE) { 282 if (r->flags & IORESOURCE_ROM_ENABLE) {
276 /* Turn the ROM off, leave the resource region, 283 /* Turn the ROM off, leave the resource region,
277 * but keep it unregistered. */ 284 * but keep it unregistered. */
278 u32 reg; 285 u32 reg;
279 dev_dbg(&dev->dev, "disabling ROM %pR\n", r); 286 dev_dbg(&dev->dev, "disabling ROM %pR\n", r);
280 r->flags &= ~IORESOURCE_ROM_ENABLE; 287 r->flags &= ~IORESOURCE_ROM_ENABLE;
281 pci_read_config_dword(dev, 288 pci_read_config_dword(dev, dev->rom_base_reg, &reg);
282 dev->rom_base_reg, &reg); 289 pci_write_config_dword(dev, dev->rom_base_reg,
283 pci_write_config_dword(dev, dev->rom_base_reg,
284 reg & ~PCI_ROM_ADDRESS_ENABLE); 290 reg & ~PCI_ROM_ADDRESS_ENABLE);
285 }
286 } 291 }
287 } 292 }
288} 293}
289 294
290static int __init pcibios_assign_resources(void) 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)
291{ 310{
292 struct pci_dev *dev = NULL;
293 struct resource *r; 311 struct resource *r;
294 312
295 if (!(pci_probe & PCI_ASSIGN_ROMS)) { 313 /*
296 /* 314 * Try to use BIOS settings for ROMs, otherwise let
297 * Try to use BIOS settings for ROMs, otherwise let 315 * pci_assign_unassigned_resources() allocate the new
298 * pci_assign_unassigned_resources() allocate the new 316 * addresses.
299 * addresses. 317 */
300 */ 318 r = &dev->resource[PCI_ROM_RESOURCE];
301 for_each_pci_dev(dev) { 319 if (!r->flags || !r->start)
302 r = &dev->resource[PCI_ROM_RESOURCE]; 320 return;
303 if (!r->flags || !r->start) 321
304 continue; 322 if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) {
305 if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) { 323 r->end -= r->start;
306 r->end -= r->start; 324 r->start = 0;
307 r->start = 0;
308 }
309 }
310 } 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);
311 348
312 pci_assign_unassigned_resources(); 349 pci_assign_unassigned_resources();
313 pcibios_fw_addr_list_del(); 350 pcibios_fw_addr_list_del();
@@ -315,12 +352,32 @@ static int __init pcibios_assign_resources(void)
315 return 0; 352 return 0;
316} 353}
317 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
318void __init pcibios_resource_survey(void) 368void __init pcibios_resource_survey(void)
319{ 369{
370 struct pci_bus *bus;
371
320 DBG("PCI: Allocating resources\n"); 372 DBG("PCI: Allocating resources\n");
321 pcibios_allocate_bus_resources(&pci_root_buses); 373
322 pcibios_allocate_resources(0); 374 list_for_each_entry(bus, &pci_root_buses, node)
323 pcibios_allocate_resources(1); 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);
324 381
325 e820_reserve_resources_late(); 382 e820_reserve_resources_late();
326 /* 383 /*
diff --git a/arch/x86/pci/legacy.c b/arch/x86/pci/legacy.c
index 4a2ab9cb3659..4db96fb1c232 100644
--- a/arch/x86/pci/legacy.c
+++ b/arch/x86/pci/legacy.c
@@ -30,7 +30,7 @@ int __init pci_legacy_init(void)
30 } 30 }
31 31
32 printk("PCI: Probing PCI hardware\n"); 32 printk("PCI: Probing PCI hardware\n");
33 pci_root_bus = pcibios_scan_root(0); 33 pcibios_scan_root(0);
34 return 0; 34 return 0;
35} 35}
36 36
diff --git a/arch/x86/pci/numaq_32.c b/arch/x86/pci/numaq_32.c
index b96b14c250b6..72c229f9ebcf 100644
--- a/arch/x86/pci/numaq_32.c
+++ b/arch/x86/pci/numaq_32.c
@@ -152,7 +152,7 @@ int __init pci_numaq_init(void)
152 152
153 raw_pci_ops = &pci_direct_conf1_mq; 153 raw_pci_ops = &pci_direct_conf1_mq;
154 154
155 pci_root_bus = pcibios_scan_root(0); 155 pcibios_scan_root(0);
156 if (num_online_nodes() > 1) 156 if (num_online_nodes() > 1)
157 for_each_online_node(quad) { 157 for_each_online_node(quad) {
158 if (quad == 0) 158 if (quad == 0)