Merge branches 'acpi-pci-pm' and 'acpi-pci-hotplug'

* acpi-pci-pm:
PCI / ACPI: Install wakeup notify handlers for all PCI devs with ACPI

* acpi-pci-hotplug:
ACPIPHP / radeon / nouveau: Fix VGA switcheroo problem related to hotplug
ACPI / PCI / hotplug: Avoid warning when _ADR not present

Changed files
+79 -18
drivers
acpi
gpu
pci
include
acpi
+10
drivers/acpi/bus.c
··· 156 156 } 157 157 EXPORT_SYMBOL(acpi_bus_get_private_data); 158 158 159 + void acpi_bus_no_hotplug(acpi_handle handle) 160 + { 161 + struct acpi_device *adev = NULL; 162 + 163 + acpi_bus_get_device(handle, &adev); 164 + if (adev) 165 + adev->flags.no_hotplug = true; 166 + } 167 + EXPORT_SYMBOL_GPL(acpi_bus_no_hotplug); 168 + 159 169 static void acpi_print_osc_error(acpi_handle handle, 160 170 struct acpi_osc_context *context, char *error) 161 171 {
+14 -2
drivers/gpu/drm/nouveau/nouveau_acpi.c
··· 51 51 bool dsm_detected; 52 52 bool optimus_detected; 53 53 acpi_handle dhandle; 54 + acpi_handle other_handle; 54 55 acpi_handle rom_handle; 55 56 } nouveau_dsm_priv; 56 57 ··· 261 260 if (!dhandle) 262 261 return false; 263 262 264 - if (!acpi_has_method(dhandle, "_DSM")) 263 + if (!acpi_has_method(dhandle, "_DSM")) { 264 + nouveau_dsm_priv.other_handle = dhandle; 265 265 return false; 266 - 266 + } 267 267 if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER)) 268 268 retval |= NOUVEAU_DSM_HAS_MUX; 269 269 ··· 340 338 printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n", 341 339 acpi_method_name); 342 340 nouveau_dsm_priv.dsm_detected = true; 341 + /* 342 + * On some systems hotplug events are generated for the device 343 + * being switched off when _DSM is executed. They cause ACPI 344 + * hotplug to trigger and attempt to remove the device from 345 + * the system, which causes it to break down. Prevent that from 346 + * happening by setting the no_hotplug flag for the involved 347 + * ACPI device objects. 348 + */ 349 + acpi_bus_no_hotplug(nouveau_dsm_priv.dhandle); 350 + acpi_bus_no_hotplug(nouveau_dsm_priv.other_handle); 343 351 ret = true; 344 352 } 345 353
+14 -2
drivers/gpu/drm/radeon/radeon_atpx_handler.c
··· 33 33 bool atpx_detected; 34 34 /* handle for device - and atpx */ 35 35 acpi_handle dhandle; 36 + acpi_handle other_handle; 36 37 struct radeon_atpx atpx; 37 38 } radeon_atpx_priv; 38 39 ··· 452 451 return false; 453 452 454 453 status = acpi_get_handle(dhandle, "ATPX", &atpx_handle); 455 - if (ACPI_FAILURE(status)) 454 + if (ACPI_FAILURE(status)) { 455 + radeon_atpx_priv.other_handle = dhandle; 456 456 return false; 457 - 457 + } 458 458 radeon_atpx_priv.dhandle = dhandle; 459 459 radeon_atpx_priv.atpx.handle = atpx_handle; 460 460 return true; ··· 532 530 printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n", 533 531 acpi_method_name); 534 532 radeon_atpx_priv.atpx_detected = true; 533 + /* 534 + * On some systems hotplug events are generated for the device 535 + * being switched off when ATPX is executed. They cause ACPI 536 + * hotplug to trigger and attempt to remove the device from 537 + * the system, which causes it to break down. Prevent that from 538 + * happening by setting the no_hotplug flag for the involved 539 + * ACPI device objects. 540 + */ 541 + acpi_bus_no_hotplug(radeon_atpx_priv.dhandle); 542 + acpi_bus_no_hotplug(radeon_atpx_priv.other_handle); 535 543 return true; 536 544 } 537 545 return false;
+26 -4
drivers/pci/hotplug/acpiphp_glue.c
··· 279 279 280 280 status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); 281 281 if (ACPI_FAILURE(status)) { 282 - acpi_handle_warn(handle, "can't evaluate _ADR (%#x)\n", status); 282 + if (status != AE_NOT_FOUND) 283 + acpi_handle_warn(handle, 284 + "can't evaluate _ADR (%#x)\n", status); 283 285 return AE_OK; 284 286 } 285 287 ··· 645 643 slot->flags &= (~SLOT_ENABLED); 646 644 } 647 645 646 + static bool acpiphp_no_hotplug(acpi_handle handle) 647 + { 648 + struct acpi_device *adev = NULL; 649 + 650 + acpi_bus_get_device(handle, &adev); 651 + return adev && adev->flags.no_hotplug; 652 + } 653 + 654 + static bool slot_no_hotplug(struct acpiphp_slot *slot) 655 + { 656 + struct acpiphp_func *func; 657 + 658 + list_for_each_entry(func, &slot->funcs, sibling) 659 + if (acpiphp_no_hotplug(func_to_handle(func))) 660 + return true; 661 + 662 + return false; 663 + } 648 664 649 665 /** 650 666 * get_slot_status - get ACPI slot status ··· 721 701 unsigned long long sta; 722 702 723 703 status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); 724 - alive = ACPI_SUCCESS(status) && sta == ACPI_STA_ALL; 704 + alive = (ACPI_SUCCESS(status) && sta == ACPI_STA_ALL) 705 + || acpiphp_no_hotplug(handle); 725 706 } 726 707 if (!alive) { 727 708 u32 v; ··· 762 741 struct pci_dev *dev, *tmp; 763 742 764 743 mutex_lock(&slot->crit_sect); 765 - /* wake up all functions */ 766 - if (get_slot_status(slot) == ACPI_STA_ALL) { 744 + if (slot_no_hotplug(slot)) { 745 + ; /* do nothing */ 746 + } else if (get_slot_status(slot) == ACPI_STA_ALL) { 767 747 /* remove stale devices if any */ 768 748 list_for_each_entry_safe(dev, tmp, &bus->devices, 769 749 bus_list)
+12 -9
drivers/pci/pci-acpi.c
··· 330 330 static void pci_acpi_setup(struct device *dev) 331 331 { 332 332 struct pci_dev *pci_dev = to_pci_dev(dev); 333 - acpi_handle handle = ACPI_HANDLE(dev); 334 - struct acpi_device *adev; 333 + struct acpi_device *adev = ACPI_COMPANION(dev); 335 334 336 - if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid) 335 + if (!adev) 336 + return; 337 + 338 + pci_acpi_add_pm_notifier(adev, pci_dev); 339 + if (!adev->wakeup.flags.valid) 337 340 return; 338 341 339 342 device_set_wakeup_capable(dev, true); 340 343 acpi_pci_sleep_wake(pci_dev, false); 341 - 342 - pci_acpi_add_pm_notifier(adev, pci_dev); 343 344 if (adev->wakeup.flags.run_wake) 344 345 device_set_run_wake(dev, true); 345 346 } 346 347 347 348 static void pci_acpi_cleanup(struct device *dev) 348 349 { 349 - acpi_handle handle = ACPI_HANDLE(dev); 350 - struct acpi_device *adev; 350 + struct acpi_device *adev = ACPI_COMPANION(dev); 351 351 352 - if (!acpi_bus_get_device(handle, &adev) && adev->wakeup.flags.valid) { 352 + if (!adev) 353 + return; 354 + 355 + pci_acpi_remove_pm_notifier(adev); 356 + if (adev->wakeup.flags.valid) { 353 357 device_set_wakeup_capable(dev, false); 354 358 device_set_run_wake(dev, false); 355 - pci_acpi_remove_pm_notifier(adev); 356 359 } 357 360 } 358 361
+3 -1
include/acpi/acpi_bus.h
··· 169 169 u32 ejectable:1; 170 170 u32 power_manageable:1; 171 171 u32 match_driver:1; 172 - u32 reserved:27; 172 + u32 no_hotplug:1; 173 + u32 reserved:26; 173 174 }; 174 175 175 176 /* File System */ ··· 345 344 extern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int); 346 345 void acpi_bus_private_data_handler(acpi_handle, void *); 347 346 int acpi_bus_get_private_data(acpi_handle, void **); 347 + void acpi_bus_no_hotplug(acpi_handle handle); 348 348 extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32); 349 349 extern int register_acpi_notifier(struct notifier_block *); 350 350 extern int unregister_acpi_notifier(struct notifier_block *);