diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-26 00:18:18 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-26 00:18:18 -0500 |
commit | 556f12f602ac0a18a82ca83e9f8e8547688fc633 (patch) | |
tree | d4051f6dd57968c8e8e660ad117c5bedc2aa7e8e /drivers/acpi | |
parent | fffddfd6c8e0c10c42c6e2cc54ba880fcc36ebbb (diff) | |
parent | 018ba0a6efada61b9bc17500101d81c3d35807c2 (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 'drivers/acpi')
-rw-r--r-- | drivers/acpi/Kconfig | 5 | ||||
-rw-r--r-- | drivers/acpi/internal.h | 6 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 24 | ||||
-rw-r--r-- | drivers/acpi/pci_irq.c | 102 | ||||
-rw-r--r-- | drivers/acpi/pci_root.c | 170 | ||||
-rw-r--r-- | drivers/acpi/pci_slot.c | 13 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 3 |
7 files changed, 200 insertions, 123 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 1a4ed64586a7..320006019e68 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
@@ -306,7 +306,7 @@ config ACPI_DEBUG_FUNC_TRACE | |||
306 | is about half of the penalty and is rarely useful. | 306 | is about half of the penalty and is rarely useful. |
307 | 307 | ||
308 | config ACPI_PCI_SLOT | 308 | config ACPI_PCI_SLOT |
309 | tristate "PCI slot detection driver" | 309 | bool "PCI slot detection driver" |
310 | depends on SYSFS | 310 | depends on SYSFS |
311 | default n | 311 | default n |
312 | help | 312 | help |
@@ -315,9 +315,6 @@ config ACPI_PCI_SLOT | |||
315 | i.e., segment/bus/device/function tuples, with physical slots in | 315 | i.e., segment/bus/device/function tuples, with physical slots in |
316 | the system. If you are unsure, say N. | 316 | the system. If you are unsure, say N. |
317 | 317 | ||
318 | To compile this driver as a module, choose M here: | ||
319 | the module will be called pci_slot. | ||
320 | |||
321 | config X86_PM_TIMER | 318 | config X86_PM_TIMER |
322 | bool "Power Management Timer Support" if EXPERT | 319 | bool "Power Management Timer Support" if EXPERT |
323 | depends on X86 | 320 | depends on X86 |
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 79092328cf06..c8b70b5b2814 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h | |||
@@ -25,8 +25,14 @@ | |||
25 | 25 | ||
26 | int init_acpi_device_notify(void); | 26 | int init_acpi_device_notify(void); |
27 | int acpi_scan_init(void); | 27 | int acpi_scan_init(void); |
28 | #ifdef CONFIG_ACPI_PCI_SLOT | ||
29 | void acpi_pci_slot_init(void); | ||
30 | #else | ||
31 | static inline void acpi_pci_slot_init(void) { } | ||
32 | #endif | ||
28 | void acpi_pci_root_init(void); | 33 | void acpi_pci_root_init(void); |
29 | void acpi_pci_link_init(void); | 34 | void acpi_pci_link_init(void); |
35 | void acpi_pci_root_hp_init(void); | ||
30 | void acpi_platform_init(void); | 36 | void acpi_platform_init(void); |
31 | int acpi_sysfs_init(void); | 37 | int acpi_sysfs_init(void); |
32 | void acpi_csrt_init(void); | 38 | void acpi_csrt_init(void); |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 8080588f88cb..586e7e993d3d 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -84,8 +84,7 @@ static acpi_osd_handler acpi_irq_handler; | |||
84 | static void *acpi_irq_context; | 84 | static void *acpi_irq_context; |
85 | static struct workqueue_struct *kacpid_wq; | 85 | static struct workqueue_struct *kacpid_wq; |
86 | static struct workqueue_struct *kacpi_notify_wq; | 86 | static struct workqueue_struct *kacpi_notify_wq; |
87 | struct workqueue_struct *kacpi_hotplug_wq; | 87 | static struct workqueue_struct *kacpi_hotplug_wq; |
88 | EXPORT_SYMBOL(kacpi_hotplug_wq); | ||
89 | 88 | ||
90 | /* | 89 | /* |
91 | * This list of permanent mappings is for memory that may be accessed from | 90 | * This list of permanent mappings is for memory that may be accessed from |
@@ -1778,3 +1777,24 @@ void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state, | |||
1778 | { | 1777 | { |
1779 | __acpi_os_prepare_sleep = func; | 1778 | __acpi_os_prepare_sleep = func; |
1780 | } | 1779 | } |
1780 | |||
1781 | void alloc_acpi_hp_work(acpi_handle handle, u32 type, void *context, | ||
1782 | void (*func)(struct work_struct *work)) | ||
1783 | { | ||
1784 | struct acpi_hp_work *hp_work; | ||
1785 | int ret; | ||
1786 | |||
1787 | hp_work = kmalloc(sizeof(*hp_work), GFP_KERNEL); | ||
1788 | if (!hp_work) | ||
1789 | return; | ||
1790 | |||
1791 | hp_work->handle = handle; | ||
1792 | hp_work->type = type; | ||
1793 | hp_work->context = context; | ||
1794 | |||
1795 | INIT_WORK(&hp_work->work, func); | ||
1796 | ret = queue_work(kacpi_hotplug_wq, &hp_work->work); | ||
1797 | if (!ret) | ||
1798 | kfree(hp_work); | ||
1799 | } | ||
1800 | EXPORT_SYMBOL_GPL(alloc_acpi_hp_work); | ||
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 68a921d03247..41c5e1b799ef 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c | |||
@@ -53,9 +53,6 @@ struct acpi_prt_entry { | |||
53 | u32 index; /* GSI, or link _CRS index */ | 53 | u32 index; /* GSI, or link _CRS index */ |
54 | }; | 54 | }; |
55 | 55 | ||
56 | static LIST_HEAD(acpi_prt_list); | ||
57 | static DEFINE_SPINLOCK(acpi_prt_lock); | ||
58 | |||
59 | static inline char pin_name(int pin) | 56 | static inline char pin_name(int pin) |
60 | { | 57 | { |
61 | return 'A' + pin - 1; | 58 | return 'A' + pin - 1; |
@@ -65,28 +62,6 @@ static inline char pin_name(int pin) | |||
65 | PCI IRQ Routing Table (PRT) Support | 62 | PCI IRQ Routing Table (PRT) Support |
66 | -------------------------------------------------------------------------- */ | 63 | -------------------------------------------------------------------------- */ |
67 | 64 | ||
68 | static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(struct pci_dev *dev, | ||
69 | int pin) | ||
70 | { | ||
71 | struct acpi_prt_entry *entry; | ||
72 | int segment = pci_domain_nr(dev->bus); | ||
73 | int bus = dev->bus->number; | ||
74 | int device = PCI_SLOT(dev->devfn); | ||
75 | |||
76 | spin_lock(&acpi_prt_lock); | ||
77 | list_for_each_entry(entry, &acpi_prt_list, list) { | ||
78 | if ((segment == entry->id.segment) | ||
79 | && (bus == entry->id.bus) | ||
80 | && (device == entry->id.device) | ||
81 | && (pin == entry->pin)) { | ||
82 | spin_unlock(&acpi_prt_lock); | ||
83 | return entry; | ||
84 | } | ||
85 | } | ||
86 | spin_unlock(&acpi_prt_lock); | ||
87 | return NULL; | ||
88 | } | ||
89 | |||
90 | /* http://bugzilla.kernel.org/show_bug.cgi?id=4773 */ | 65 | /* http://bugzilla.kernel.org/show_bug.cgi?id=4773 */ |
91 | static const struct dmi_system_id medion_md9580[] = { | 66 | static const struct dmi_system_id medion_md9580[] = { |
92 | { | 67 | { |
@@ -184,11 +159,19 @@ static void do_prt_fixups(struct acpi_prt_entry *entry, | |||
184 | } | 159 | } |
185 | } | 160 | } |
186 | 161 | ||
187 | static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus, | 162 | static int acpi_pci_irq_check_entry(acpi_handle handle, struct pci_dev *dev, |
188 | struct acpi_pci_routing_table *prt) | 163 | int pin, struct acpi_pci_routing_table *prt, |
164 | struct acpi_prt_entry **entry_ptr) | ||
189 | { | 165 | { |
166 | int segment = pci_domain_nr(dev->bus); | ||
167 | int bus = dev->bus->number; | ||
168 | int device = PCI_SLOT(dev->devfn); | ||
190 | struct acpi_prt_entry *entry; | 169 | struct acpi_prt_entry *entry; |
191 | 170 | ||
171 | if (((prt->address >> 16) & 0xffff) != device || | ||
172 | prt->pin + 1 != pin) | ||
173 | return -ENODEV; | ||
174 | |||
192 | entry = kzalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL); | 175 | entry = kzalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL); |
193 | if (!entry) | 176 | if (!entry) |
194 | return -ENOMEM; | 177 | return -ENOMEM; |
@@ -237,43 +220,37 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus, | |||
237 | entry->id.device, pin_name(entry->pin), | 220 | entry->id.device, pin_name(entry->pin), |
238 | prt->source, entry->index)); | 221 | prt->source, entry->index)); |
239 | 222 | ||
240 | spin_lock(&acpi_prt_lock); | 223 | *entry_ptr = entry; |
241 | list_add_tail(&entry->list, &acpi_prt_list); | ||
242 | spin_unlock(&acpi_prt_lock); | ||
243 | 224 | ||
244 | return 0; | 225 | return 0; |
245 | } | 226 | } |
246 | 227 | ||
247 | int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus) | 228 | static int acpi_pci_irq_find_prt_entry(struct pci_dev *dev, |
229 | int pin, struct acpi_prt_entry **entry_ptr) | ||
248 | { | 230 | { |
249 | acpi_status status; | 231 | acpi_status status; |
250 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 232 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
251 | struct acpi_pci_routing_table *entry; | 233 | struct acpi_pci_routing_table *entry; |
234 | acpi_handle handle = NULL; | ||
252 | 235 | ||
253 | /* 'handle' is the _PRT's parent (root bridge or PCI-PCI bridge) */ | 236 | if (dev->bus->bridge) |
254 | status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | 237 | handle = ACPI_HANDLE(dev->bus->bridge); |
255 | if (ACPI_FAILURE(status)) | ||
256 | return -ENODEV; | ||
257 | |||
258 | printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n", | ||
259 | (char *) buffer.pointer); | ||
260 | |||
261 | kfree(buffer.pointer); | ||
262 | 238 | ||
263 | buffer.length = ACPI_ALLOCATE_BUFFER; | 239 | if (!handle) |
264 | buffer.pointer = NULL; | 240 | return -ENODEV; |
265 | 241 | ||
242 | /* 'handle' is the _PRT's parent (root bridge or PCI-PCI bridge) */ | ||
266 | status = acpi_get_irq_routing_table(handle, &buffer); | 243 | status = acpi_get_irq_routing_table(handle, &buffer); |
267 | if (ACPI_FAILURE(status)) { | 244 | if (ACPI_FAILURE(status)) { |
268 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRT [%s]", | ||
269 | acpi_format_exception(status))); | ||
270 | kfree(buffer.pointer); | 245 | kfree(buffer.pointer); |
271 | return -ENODEV; | 246 | return -ENODEV; |
272 | } | 247 | } |
273 | 248 | ||
274 | entry = buffer.pointer; | 249 | entry = buffer.pointer; |
275 | while (entry && (entry->length > 0)) { | 250 | while (entry && (entry->length > 0)) { |
276 | acpi_pci_irq_add_entry(handle, segment, bus, entry); | 251 | if (!acpi_pci_irq_check_entry(handle, dev, pin, |
252 | entry, entry_ptr)) | ||
253 | break; | ||
277 | entry = (struct acpi_pci_routing_table *) | 254 | entry = (struct acpi_pci_routing_table *) |
278 | ((unsigned long)entry + entry->length); | 255 | ((unsigned long)entry + entry->length); |
279 | } | 256 | } |
@@ -282,23 +259,6 @@ int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus) | |||
282 | return 0; | 259 | return 0; |
283 | } | 260 | } |
284 | 261 | ||
285 | void acpi_pci_irq_del_prt(int segment, int bus) | ||
286 | { | ||
287 | struct acpi_prt_entry *entry, *tmp; | ||
288 | |||
289 | printk(KERN_DEBUG | ||
290 | "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n", | ||
291 | segment, bus); | ||
292 | spin_lock(&acpi_prt_lock); | ||
293 | list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) { | ||
294 | if (segment == entry->id.segment && bus == entry->id.bus) { | ||
295 | list_del(&entry->list); | ||
296 | kfree(entry); | ||
297 | } | ||
298 | } | ||
299 | spin_unlock(&acpi_prt_lock); | ||
300 | } | ||
301 | |||
302 | /* -------------------------------------------------------------------------- | 262 | /* -------------------------------------------------------------------------- |
303 | PCI Interrupt Routing Support | 263 | PCI Interrupt Routing Support |
304 | -------------------------------------------------------------------------- */ | 264 | -------------------------------------------------------------------------- */ |
@@ -359,12 +319,13 @@ static int acpi_reroute_boot_interrupt(struct pci_dev *dev, | |||
359 | 319 | ||
360 | static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin) | 320 | static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin) |
361 | { | 321 | { |
362 | struct acpi_prt_entry *entry; | 322 | struct acpi_prt_entry *entry = NULL; |
363 | struct pci_dev *bridge; | 323 | struct pci_dev *bridge; |
364 | u8 bridge_pin, orig_pin = pin; | 324 | u8 bridge_pin, orig_pin = pin; |
325 | int ret; | ||
365 | 326 | ||
366 | entry = acpi_pci_irq_find_prt_entry(dev, pin); | 327 | ret = acpi_pci_irq_find_prt_entry(dev, pin, &entry); |
367 | if (entry) { | 328 | if (!ret && entry) { |
368 | #ifdef CONFIG_X86_IO_APIC | 329 | #ifdef CONFIG_X86_IO_APIC |
369 | acpi_reroute_boot_interrupt(dev, entry); | 330 | acpi_reroute_boot_interrupt(dev, entry); |
370 | #endif /* CONFIG_X86_IO_APIC */ | 331 | #endif /* CONFIG_X86_IO_APIC */ |
@@ -373,7 +334,7 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin) | |||
373 | return entry; | 334 | return entry; |
374 | } | 335 | } |
375 | 336 | ||
376 | /* | 337 | /* |
377 | * Attempt to derive an IRQ for this device from a parent bridge's | 338 | * Attempt to derive an IRQ for this device from a parent bridge's |
378 | * PCI interrupt routing entry (eg. yenta bridge and add-in card bridge). | 339 | * PCI interrupt routing entry (eg. yenta bridge and add-in card bridge). |
379 | */ | 340 | */ |
@@ -393,8 +354,8 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin) | |||
393 | pin = bridge_pin; | 354 | pin = bridge_pin; |
394 | } | 355 | } |
395 | 356 | ||
396 | entry = acpi_pci_irq_find_prt_entry(bridge, pin); | 357 | ret = acpi_pci_irq_find_prt_entry(bridge, pin, &entry); |
397 | if (entry) { | 358 | if (!ret && entry) { |
398 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 359 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
399 | "Derived GSI for %s INT %c from %s\n", | 360 | "Derived GSI for %s INT %c from %s\n", |
400 | pci_name(dev), pin_name(orig_pin), | 361 | pci_name(dev), pin_name(orig_pin), |
@@ -470,6 +431,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev) | |||
470 | dev_warn(&dev->dev, "PCI INT %c: no GSI\n", | 431 | dev_warn(&dev->dev, "PCI INT %c: no GSI\n", |
471 | pin_name(pin)); | 432 | pin_name(pin)); |
472 | } | 433 | } |
434 | |||
473 | return 0; | 435 | return 0; |
474 | } | 436 | } |
475 | 437 | ||
@@ -477,6 +439,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev) | |||
477 | if (rc < 0) { | 439 | if (rc < 0) { |
478 | dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n", | 440 | dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n", |
479 | pin_name(pin)); | 441 | pin_name(pin)); |
442 | kfree(entry); | ||
480 | return rc; | 443 | return rc; |
481 | } | 444 | } |
482 | dev->irq = rc; | 445 | dev->irq = rc; |
@@ -491,6 +454,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev) | |||
491 | (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge", | 454 | (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge", |
492 | (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq); | 455 | (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq); |
493 | 456 | ||
457 | kfree(entry); | ||
494 | return 0; | 458 | return 0; |
495 | } | 459 | } |
496 | 460 | ||
@@ -513,6 +477,8 @@ void acpi_pci_irq_disable(struct pci_dev *dev) | |||
513 | else | 477 | else |
514 | gsi = entry->index; | 478 | gsi = entry->index; |
515 | 479 | ||
480 | kfree(entry); | ||
481 | |||
516 | /* | 482 | /* |
517 | * TBD: It might be worth clearing dev->irq by magic constant | 483 | * TBD: It might be worth clearing dev->irq by magic constant |
518 | * (e.g. PCI_UNDEFINED_IRQ). | 484 | * (e.g. PCI_UNDEFINED_IRQ). |
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index b3cc69c5caf1..0ac546d5e53f 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -103,24 +103,6 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) | |||
103 | } | 103 | } |
104 | EXPORT_SYMBOL(acpi_pci_unregister_driver); | 104 | EXPORT_SYMBOL(acpi_pci_unregister_driver); |
105 | 105 | ||
106 | acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus) | ||
107 | { | ||
108 | struct acpi_pci_root *root; | ||
109 | acpi_handle handle = NULL; | ||
110 | |||
111 | mutex_lock(&acpi_pci_root_lock); | ||
112 | list_for_each_entry(root, &acpi_pci_roots, node) | ||
113 | if ((root->segment == (u16) seg) && | ||
114 | (root->secondary.start == (u16) bus)) { | ||
115 | handle = root->device->handle; | ||
116 | break; | ||
117 | } | ||
118 | mutex_unlock(&acpi_pci_root_lock); | ||
119 | return handle; | ||
120 | } | ||
121 | |||
122 | EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle); | ||
123 | |||
124 | /** | 106 | /** |
125 | * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge | 107 | * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge |
126 | * @handle - the ACPI CA node in question. | 108 | * @handle - the ACPI CA node in question. |
@@ -431,7 +413,6 @@ static int acpi_pci_root_add(struct acpi_device *device, | |||
431 | acpi_status status; | 413 | acpi_status status; |
432 | int result; | 414 | int result; |
433 | struct acpi_pci_root *root; | 415 | struct acpi_pci_root *root; |
434 | acpi_handle handle; | ||
435 | struct acpi_pci_driver *driver; | 416 | struct acpi_pci_driver *driver; |
436 | u32 flags, base_flags; | 417 | u32 flags, base_flags; |
437 | bool is_osc_granted = false; | 418 | bool is_osc_granted = false; |
@@ -486,16 +467,6 @@ static int acpi_pci_root_add(struct acpi_device *device, | |||
486 | acpi_device_name(device), acpi_device_bid(device), | 467 | acpi_device_name(device), acpi_device_bid(device), |
487 | root->segment, &root->secondary); | 468 | root->segment, &root->secondary); |
488 | 469 | ||
489 | /* | ||
490 | * PCI Routing Table | ||
491 | * ----------------- | ||
492 | * Evaluate and parse _PRT, if exists. | ||
493 | */ | ||
494 | status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); | ||
495 | if (ACPI_SUCCESS(status)) | ||
496 | result = acpi_pci_irq_add_prt(device->handle, root->segment, | ||
497 | root->secondary.start); | ||
498 | |||
499 | root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle); | 470 | root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle); |
500 | 471 | ||
501 | /* | 472 | /* |
@@ -597,8 +568,10 @@ static int acpi_pci_root_add(struct acpi_device *device, | |||
597 | if (device->wakeup.flags.run_wake) | 568 | if (device->wakeup.flags.run_wake) |
598 | device_set_run_wake(root->bus->bridge, true); | 569 | device_set_run_wake(root->bus->bridge, true); |
599 | 570 | ||
600 | if (system_state != SYSTEM_BOOTING) | 571 | if (system_state != SYSTEM_BOOTING) { |
572 | pcibios_resource_survey_bus(root->bus); | ||
601 | pci_assign_unassigned_bus_resources(root->bus); | 573 | pci_assign_unassigned_bus_resources(root->bus); |
574 | } | ||
602 | 575 | ||
603 | mutex_lock(&acpi_pci_root_lock); | 576 | mutex_lock(&acpi_pci_root_lock); |
604 | list_for_each_entry(driver, &acpi_pci_drivers, node) | 577 | list_for_each_entry(driver, &acpi_pci_drivers, node) |
@@ -618,7 +591,6 @@ out_del_root: | |||
618 | list_del(&root->node); | 591 | list_del(&root->node); |
619 | mutex_unlock(&acpi_pci_root_lock); | 592 | mutex_unlock(&acpi_pci_root_lock); |
620 | 593 | ||
621 | acpi_pci_irq_del_prt(root->segment, root->secondary.start); | ||
622 | end: | 594 | end: |
623 | kfree(root); | 595 | kfree(root); |
624 | return result; | 596 | return result; |
@@ -626,8 +598,6 @@ end: | |||
626 | 598 | ||
627 | static void acpi_pci_root_remove(struct acpi_device *device) | 599 | static void acpi_pci_root_remove(struct acpi_device *device) |
628 | { | 600 | { |
629 | acpi_status status; | ||
630 | acpi_handle handle; | ||
631 | struct acpi_pci_root *root = acpi_driver_data(device); | 601 | struct acpi_pci_root *root = acpi_driver_data(device); |
632 | struct acpi_pci_driver *driver; | 602 | struct acpi_pci_driver *driver; |
633 | 603 | ||
@@ -642,10 +612,6 @@ static void acpi_pci_root_remove(struct acpi_device *device) | |||
642 | device_set_run_wake(root->bus->bridge, false); | 612 | device_set_run_wake(root->bus->bridge, false); |
643 | pci_acpi_remove_bus_pm_notifier(device); | 613 | pci_acpi_remove_bus_pm_notifier(device); |
644 | 614 | ||
645 | status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle); | ||
646 | if (ACPI_SUCCESS(status)) | ||
647 | acpi_pci_irq_del_prt(root->segment, root->secondary.start); | ||
648 | |||
649 | pci_remove_root_bus(root->bus); | 615 | pci_remove_root_bus(root->bus); |
650 | 616 | ||
651 | mutex_lock(&acpi_pci_root_lock); | 617 | mutex_lock(&acpi_pci_root_lock); |
@@ -663,3 +629,133 @@ void __init acpi_pci_root_init(void) | |||
663 | acpi_scan_add_handler(&pci_root_handler); | 629 | acpi_scan_add_handler(&pci_root_handler); |
664 | } | 630 | } |
665 | } | 631 | } |
632 | /* Support root bridge hotplug */ | ||
633 | |||
634 | static void handle_root_bridge_insertion(acpi_handle handle) | ||
635 | { | ||
636 | struct acpi_device *device; | ||
637 | |||
638 | if (!acpi_bus_get_device(handle, &device)) { | ||
639 | printk(KERN_DEBUG "acpi device exists...\n"); | ||
640 | return; | ||
641 | } | ||
642 | |||
643 | if (acpi_bus_scan(handle)) | ||
644 | printk(KERN_ERR "cannot add bridge to acpi list\n"); | ||
645 | } | ||
646 | |||
647 | static void handle_root_bridge_removal(struct acpi_device *device) | ||
648 | { | ||
649 | struct acpi_eject_event *ej_event; | ||
650 | |||
651 | ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); | ||
652 | if (!ej_event) { | ||
653 | /* Inform firmware the hot-remove operation has error */ | ||
654 | (void) acpi_evaluate_hotplug_ost(device->handle, | ||
655 | ACPI_NOTIFY_EJECT_REQUEST, | ||
656 | ACPI_OST_SC_NON_SPECIFIC_FAILURE, | ||
657 | NULL); | ||
658 | return; | ||
659 | } | ||
660 | |||
661 | ej_event->device = device; | ||
662 | ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; | ||
663 | |||
664 | acpi_bus_hot_remove_device(ej_event); | ||
665 | } | ||
666 | |||
667 | static void _handle_hotplug_event_root(struct work_struct *work) | ||
668 | { | ||
669 | struct acpi_pci_root *root; | ||
670 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER }; | ||
671 | struct acpi_hp_work *hp_work; | ||
672 | acpi_handle handle; | ||
673 | u32 type; | ||
674 | |||
675 | hp_work = container_of(work, struct acpi_hp_work, work); | ||
676 | handle = hp_work->handle; | ||
677 | type = hp_work->type; | ||
678 | |||
679 | root = acpi_pci_find_root(handle); | ||
680 | |||
681 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | ||
682 | |||
683 | switch (type) { | ||
684 | case ACPI_NOTIFY_BUS_CHECK: | ||
685 | /* bus enumerate */ | ||
686 | printk(KERN_DEBUG "%s: Bus check notify on %s\n", __func__, | ||
687 | (char *)buffer.pointer); | ||
688 | if (!root) | ||
689 | handle_root_bridge_insertion(handle); | ||
690 | |||
691 | break; | ||
692 | |||
693 | case ACPI_NOTIFY_DEVICE_CHECK: | ||
694 | /* device check */ | ||
695 | printk(KERN_DEBUG "%s: Device check notify on %s\n", __func__, | ||
696 | (char *)buffer.pointer); | ||
697 | if (!root) | ||
698 | handle_root_bridge_insertion(handle); | ||
699 | break; | ||
700 | |||
701 | case ACPI_NOTIFY_EJECT_REQUEST: | ||
702 | /* request device eject */ | ||
703 | printk(KERN_DEBUG "%s: Device eject notify on %s\n", __func__, | ||
704 | (char *)buffer.pointer); | ||
705 | if (root) | ||
706 | handle_root_bridge_removal(root->device); | ||
707 | break; | ||
708 | default: | ||
709 | printk(KERN_WARNING "notify_handler: unknown event type 0x%x for %s\n", | ||
710 | type, (char *)buffer.pointer); | ||
711 | break; | ||
712 | } | ||
713 | |||
714 | kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ | ||
715 | kfree(buffer.pointer); | ||
716 | } | ||
717 | |||
718 | static void handle_hotplug_event_root(acpi_handle handle, u32 type, | ||
719 | void *context) | ||
720 | { | ||
721 | alloc_acpi_hp_work(handle, type, context, | ||
722 | _handle_hotplug_event_root); | ||
723 | } | ||
724 | |||
725 | static acpi_status __init | ||
726 | find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) | ||
727 | { | ||
728 | acpi_status status; | ||
729 | char objname[64]; | ||
730 | struct acpi_buffer buffer = { .length = sizeof(objname), | ||
731 | .pointer = objname }; | ||
732 | int *count = (int *)context; | ||
733 | |||
734 | if (!acpi_is_root_bridge(handle)) | ||
735 | return AE_OK; | ||
736 | |||
737 | (*count)++; | ||
738 | |||
739 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | ||
740 | |||
741 | status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | ||
742 | handle_hotplug_event_root, NULL); | ||
743 | if (ACPI_FAILURE(status)) | ||
744 | printk(KERN_DEBUG "acpi root: %s notify handler is not installed, exit status: %u\n", | ||
745 | objname, (unsigned int)status); | ||
746 | else | ||
747 | printk(KERN_DEBUG "acpi root: %s notify handler is installed\n", | ||
748 | objname); | ||
749 | |||
750 | return AE_OK; | ||
751 | } | ||
752 | |||
753 | void __init acpi_pci_root_hp_init(void) | ||
754 | { | ||
755 | int num = 0; | ||
756 | |||
757 | acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
758 | ACPI_UINT32_MAX, find_root_bridges, NULL, &num, NULL); | ||
759 | |||
760 | printk(KERN_DEBUG "Found %d acpi root devices\n", num); | ||
761 | } | ||
diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c index 2c630c006c2f..cd1434eb1de8 100644 --- a/drivers/acpi/pci_slot.c +++ b/drivers/acpi/pci_slot.c | |||
@@ -329,19 +329,8 @@ static struct dmi_system_id acpi_pci_slot_dmi_table[] __initdata = { | |||
329 | {} | 329 | {} |
330 | }; | 330 | }; |
331 | 331 | ||
332 | static int __init | 332 | void __init acpi_pci_slot_init(void) |
333 | acpi_pci_slot_init(void) | ||
334 | { | 333 | { |
335 | dmi_check_system(acpi_pci_slot_dmi_table); | 334 | dmi_check_system(acpi_pci_slot_dmi_table); |
336 | acpi_pci_register_driver(&acpi_pci_slot_driver); | 335 | acpi_pci_register_driver(&acpi_pci_slot_driver); |
337 | return 0; | ||
338 | } | 336 | } |
339 | |||
340 | static void __exit | ||
341 | acpi_pci_slot_exit(void) | ||
342 | { | ||
343 | acpi_pci_unregister_driver(&acpi_pci_slot_driver); | ||
344 | } | ||
345 | |||
346 | module_init(acpi_pci_slot_init); | ||
347 | module_exit(acpi_pci_slot_exit); | ||
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index daee7497efd3..4be408756adc 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -1783,6 +1783,7 @@ int __init acpi_scan_init(void) | |||
1783 | acpi_platform_init(); | 1783 | acpi_platform_init(); |
1784 | acpi_csrt_init(); | 1784 | acpi_csrt_init(); |
1785 | acpi_container_init(); | 1785 | acpi_container_init(); |
1786 | acpi_pci_slot_init(); | ||
1786 | 1787 | ||
1787 | mutex_lock(&acpi_scan_lock); | 1788 | mutex_lock(&acpi_scan_lock); |
1788 | /* | 1789 | /* |
@@ -1804,6 +1805,8 @@ int __init acpi_scan_init(void) | |||
1804 | 1805 | ||
1805 | acpi_update_all_gpes(); | 1806 | acpi_update_all_gpes(); |
1806 | 1807 | ||
1808 | acpi_pci_root_hp_init(); | ||
1809 | |||
1807 | out: | 1810 | out: |
1808 | mutex_unlock(&acpi_scan_lock); | 1811 | mutex_unlock(&acpi_scan_lock); |
1809 | return result; | 1812 | return result; |