diff options
| -rw-r--r-- | drivers/acpi/bus.c | 10 | ||||
| -rw-r--r-- | drivers/cpufreq/cpufreq.c | 37 | ||||
| -rw-r--r-- | drivers/cpufreq/intel_pstate.c | 5 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_acpi.c | 16 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_atpx_handler.c | 16 | ||||
| -rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 30 | ||||
| -rw-r--r-- | drivers/pci/pci-acpi.c | 21 | ||||
| -rw-r--r-- | include/acpi/acpi_bus.h | 4 |
8 files changed, 107 insertions, 32 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index bba9b72e25f8..0710004055c8 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
| @@ -156,6 +156,16 @@ int acpi_bus_get_private_data(acpi_handle handle, void **data) | |||
| 156 | } | 156 | } |
| 157 | EXPORT_SYMBOL(acpi_bus_get_private_data); | 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 | static void acpi_print_osc_error(acpi_handle handle, | 169 | static void acpi_print_osc_error(acpi_handle handle, |
| 160 | struct acpi_osc_context *context, char *error) | 170 | struct acpi_osc_context *context, char *error) |
| 161 | { | 171 | { |
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 16d7b4ac94be..8d19f7c06010 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
| @@ -839,9 +839,6 @@ static void cpufreq_init_policy(struct cpufreq_policy *policy) | |||
| 839 | 839 | ||
| 840 | /* set default policy */ | 840 | /* set default policy */ |
| 841 | ret = cpufreq_set_policy(policy, &new_policy); | 841 | ret = cpufreq_set_policy(policy, &new_policy); |
| 842 | policy->user_policy.policy = policy->policy; | ||
| 843 | policy->user_policy.governor = policy->governor; | ||
| 844 | |||
| 845 | if (ret) { | 842 | if (ret) { |
| 846 | pr_debug("setting policy failed\n"); | 843 | pr_debug("setting policy failed\n"); |
| 847 | if (cpufreq_driver->exit) | 844 | if (cpufreq_driver->exit) |
| @@ -1016,15 +1013,17 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, | |||
| 1016 | read_unlock_irqrestore(&cpufreq_driver_lock, flags); | 1013 | read_unlock_irqrestore(&cpufreq_driver_lock, flags); |
| 1017 | #endif | 1014 | #endif |
| 1018 | 1015 | ||
| 1019 | if (frozen) | 1016 | /* |
| 1020 | /* Restore the saved policy when doing light-weight init */ | 1017 | * Restore the saved policy when doing light-weight init and fall back |
| 1021 | policy = cpufreq_policy_restore(cpu); | 1018 | * to the full init if that fails. |
| 1022 | else | 1019 | */ |
| 1020 | policy = frozen ? cpufreq_policy_restore(cpu) : NULL; | ||
| 1021 | if (!policy) { | ||
| 1022 | frozen = false; | ||
| 1023 | policy = cpufreq_policy_alloc(); | 1023 | policy = cpufreq_policy_alloc(); |
| 1024 | 1024 | if (!policy) | |
| 1025 | if (!policy) | 1025 | goto nomem_out; |
| 1026 | goto nomem_out; | 1026 | } |
| 1027 | |||
| 1028 | 1027 | ||
| 1029 | /* | 1028 | /* |
| 1030 | * In the resume path, since we restore a saved policy, the assignment | 1029 | * In the resume path, since we restore a saved policy, the assignment |
| @@ -1069,8 +1068,10 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, | |||
| 1069 | */ | 1068 | */ |
| 1070 | cpumask_and(policy->cpus, policy->cpus, cpu_online_mask); | 1069 | cpumask_and(policy->cpus, policy->cpus, cpu_online_mask); |
| 1071 | 1070 | ||
| 1072 | policy->user_policy.min = policy->min; | 1071 | if (!frozen) { |
| 1073 | policy->user_policy.max = policy->max; | 1072 | policy->user_policy.min = policy->min; |
| 1073 | policy->user_policy.max = policy->max; | ||
| 1074 | } | ||
| 1074 | 1075 | ||
| 1075 | blocking_notifier_call_chain(&cpufreq_policy_notifier_list, | 1076 | blocking_notifier_call_chain(&cpufreq_policy_notifier_list, |
| 1076 | CPUFREQ_START, policy); | 1077 | CPUFREQ_START, policy); |
| @@ -1101,6 +1102,11 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, | |||
| 1101 | 1102 | ||
| 1102 | cpufreq_init_policy(policy); | 1103 | cpufreq_init_policy(policy); |
| 1103 | 1104 | ||
| 1105 | if (!frozen) { | ||
| 1106 | policy->user_policy.policy = policy->policy; | ||
| 1107 | policy->user_policy.governor = policy->governor; | ||
| 1108 | } | ||
| 1109 | |||
| 1104 | kobject_uevent(&policy->kobj, KOBJ_ADD); | 1110 | kobject_uevent(&policy->kobj, KOBJ_ADD); |
| 1105 | up_read(&cpufreq_rwsem); | 1111 | up_read(&cpufreq_rwsem); |
| 1106 | 1112 | ||
| @@ -1118,8 +1124,11 @@ err_get_freq: | |||
| 1118 | if (cpufreq_driver->exit) | 1124 | if (cpufreq_driver->exit) |
| 1119 | cpufreq_driver->exit(policy); | 1125 | cpufreq_driver->exit(policy); |
| 1120 | err_set_policy_cpu: | 1126 | err_set_policy_cpu: |
| 1121 | if (frozen) | 1127 | if (frozen) { |
| 1128 | /* Do not leave stale fallback data behind. */ | ||
| 1129 | per_cpu(cpufreq_cpu_data_fallback, cpu) = NULL; | ||
| 1122 | cpufreq_policy_put_kobj(policy); | 1130 | cpufreq_policy_put_kobj(policy); |
| 1131 | } | ||
| 1123 | cpufreq_policy_free(policy); | 1132 | cpufreq_policy_free(policy); |
| 1124 | 1133 | ||
| 1125 | nomem_out: | 1134 | nomem_out: |
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 5f1cbae36961..f9d561e198ab 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c | |||
| @@ -614,6 +614,11 @@ static int intel_pstate_init_cpu(unsigned int cpunum) | |||
| 614 | cpu = all_cpu_data[cpunum]; | 614 | cpu = all_cpu_data[cpunum]; |
| 615 | 615 | ||
| 616 | intel_pstate_get_cpu_pstates(cpu); | 616 | intel_pstate_get_cpu_pstates(cpu); |
| 617 | if (!cpu->pstate.current_pstate) { | ||
| 618 | all_cpu_data[cpunum] = NULL; | ||
| 619 | kfree(cpu); | ||
| 620 | return -ENODATA; | ||
| 621 | } | ||
| 617 | 622 | ||
| 618 | cpu->cpu = cpunum; | 623 | cpu->cpu = cpunum; |
| 619 | 624 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 95c740454049..ba0183fb84f3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c | |||
| @@ -51,6 +51,7 @@ static struct nouveau_dsm_priv { | |||
| 51 | bool dsm_detected; | 51 | bool dsm_detected; |
| 52 | bool optimus_detected; | 52 | bool optimus_detected; |
| 53 | acpi_handle dhandle; | 53 | acpi_handle dhandle; |
| 54 | acpi_handle other_handle; | ||
| 54 | acpi_handle rom_handle; | 55 | acpi_handle rom_handle; |
| 55 | } nouveau_dsm_priv; | 56 | } nouveau_dsm_priv; |
| 56 | 57 | ||
| @@ -260,9 +261,10 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev) | |||
| 260 | if (!dhandle) | 261 | if (!dhandle) |
| 261 | return false; | 262 | return false; |
| 262 | 263 | ||
| 263 | if (!acpi_has_method(dhandle, "_DSM")) | 264 | if (!acpi_has_method(dhandle, "_DSM")) { |
| 265 | nouveau_dsm_priv.other_handle = dhandle; | ||
| 264 | return false; | 266 | return false; |
| 265 | 267 | } | |
| 266 | if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER)) | 268 | if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER)) |
| 267 | retval |= NOUVEAU_DSM_HAS_MUX; | 269 | retval |= NOUVEAU_DSM_HAS_MUX; |
| 268 | 270 | ||
| @@ -338,6 +340,16 @@ static bool nouveau_dsm_detect(void) | |||
| 338 | printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n", | 340 | printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n", |
| 339 | acpi_method_name); | 341 | acpi_method_name); |
| 340 | nouveau_dsm_priv.dsm_detected = true; | 342 | nouveau_dsm_priv.dsm_detected = true; |
| 343 | /* | ||
| 344 | * On some systems hotplug events are generated for the device | ||
| 345 | * being switched off when _DSM is executed. They cause ACPI | ||
| 346 | * hotplug to trigger and attempt to remove the device from | ||
| 347 | * the system, which causes it to break down. Prevent that from | ||
| 348 | * happening by setting the no_hotplug flag for the involved | ||
| 349 | * ACPI device objects. | ||
| 350 | */ | ||
| 351 | acpi_bus_no_hotplug(nouveau_dsm_priv.dhandle); | ||
| 352 | acpi_bus_no_hotplug(nouveau_dsm_priv.other_handle); | ||
| 341 | ret = true; | 353 | ret = true; |
| 342 | } | 354 | } |
| 343 | 355 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index 9d302eaeea15..485848f889f5 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c | |||
| @@ -33,6 +33,7 @@ static struct radeon_atpx_priv { | |||
| 33 | bool atpx_detected; | 33 | bool atpx_detected; |
| 34 | /* handle for device - and atpx */ | 34 | /* handle for device - and atpx */ |
| 35 | acpi_handle dhandle; | 35 | acpi_handle dhandle; |
| 36 | acpi_handle other_handle; | ||
| 36 | struct radeon_atpx atpx; | 37 | struct radeon_atpx atpx; |
| 37 | } radeon_atpx_priv; | 38 | } radeon_atpx_priv; |
| 38 | 39 | ||
| @@ -451,9 +452,10 @@ static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev) | |||
| 451 | return false; | 452 | return false; |
| 452 | 453 | ||
| 453 | status = acpi_get_handle(dhandle, "ATPX", &atpx_handle); | 454 | status = acpi_get_handle(dhandle, "ATPX", &atpx_handle); |
| 454 | if (ACPI_FAILURE(status)) | 455 | if (ACPI_FAILURE(status)) { |
| 456 | radeon_atpx_priv.other_handle = dhandle; | ||
| 455 | return false; | 457 | return false; |
| 456 | 458 | } | |
| 457 | radeon_atpx_priv.dhandle = dhandle; | 459 | radeon_atpx_priv.dhandle = dhandle; |
| 458 | radeon_atpx_priv.atpx.handle = atpx_handle; | 460 | radeon_atpx_priv.atpx.handle = atpx_handle; |
| 459 | return true; | 461 | return true; |
| @@ -530,6 +532,16 @@ static bool radeon_atpx_detect(void) | |||
| 530 | printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n", | 532 | printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n", |
| 531 | acpi_method_name); | 533 | acpi_method_name); |
| 532 | radeon_atpx_priv.atpx_detected = true; | 534 | radeon_atpx_priv.atpx_detected = true; |
| 535 | /* | ||
| 536 | * On some systems hotplug events are generated for the device | ||
| 537 | * being switched off when ATPX is executed. They cause ACPI | ||
| 538 | * hotplug to trigger and attempt to remove the device from | ||
| 539 | * the system, which causes it to break down. Prevent that from | ||
| 540 | * happening by setting the no_hotplug flag for the involved | ||
| 541 | * ACPI device objects. | ||
| 542 | */ | ||
| 543 | acpi_bus_no_hotplug(radeon_atpx_priv.dhandle); | ||
| 544 | acpi_bus_no_hotplug(radeon_atpx_priv.other_handle); | ||
| 533 | return true; | 545 | return true; |
| 534 | } | 546 | } |
| 535 | return false; | 547 | return false; |
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 1cf605f67673..e86439283a5d 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
| @@ -279,7 +279,9 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, | |||
| 279 | 279 | ||
| 280 | status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); | 280 | status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); |
| 281 | if (ACPI_FAILURE(status)) { | 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 | return AE_OK; | 285 | return AE_OK; |
| 284 | } | 286 | } |
| 285 | 287 | ||
| @@ -643,6 +645,24 @@ static void disable_slot(struct acpiphp_slot *slot) | |||
| 643 | slot->flags &= (~SLOT_ENABLED); | 645 | slot->flags &= (~SLOT_ENABLED); |
| 644 | } | 646 | } |
| 645 | 647 | ||
| 648 | static bool acpiphp_no_hotplug(acpi_handle handle) | ||
| 649 | { | ||
| 650 | struct acpi_device *adev = NULL; | ||
| 651 | |||
| 652 | acpi_bus_get_device(handle, &adev); | ||
| 653 | return adev && adev->flags.no_hotplug; | ||
| 654 | } | ||
| 655 | |||
| 656 | static bool slot_no_hotplug(struct acpiphp_slot *slot) | ||
| 657 | { | ||
| 658 | struct acpiphp_func *func; | ||
| 659 | |||
| 660 | list_for_each_entry(func, &slot->funcs, sibling) | ||
| 661 | if (acpiphp_no_hotplug(func_to_handle(func))) | ||
| 662 | return true; | ||
| 663 | |||
| 664 | return false; | ||
| 665 | } | ||
| 646 | 666 | ||
| 647 | /** | 667 | /** |
| 648 | * get_slot_status - get ACPI slot status | 668 | * get_slot_status - get ACPI slot status |
| @@ -701,7 +721,8 @@ static void trim_stale_devices(struct pci_dev *dev) | |||
| 701 | unsigned long long sta; | 721 | unsigned long long sta; |
| 702 | 722 | ||
| 703 | status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); | 723 | status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); |
| 704 | alive = ACPI_SUCCESS(status) && sta == ACPI_STA_ALL; | 724 | alive = (ACPI_SUCCESS(status) && sta == ACPI_STA_ALL) |
| 725 | || acpiphp_no_hotplug(handle); | ||
| 705 | } | 726 | } |
| 706 | if (!alive) { | 727 | if (!alive) { |
| 707 | u32 v; | 728 | u32 v; |
| @@ -741,8 +762,9 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge) | |||
| 741 | struct pci_dev *dev, *tmp; | 762 | struct pci_dev *dev, *tmp; |
| 742 | 763 | ||
| 743 | mutex_lock(&slot->crit_sect); | 764 | mutex_lock(&slot->crit_sect); |
| 744 | /* wake up all functions */ | 765 | if (slot_no_hotplug(slot)) { |
| 745 | if (get_slot_status(slot) == ACPI_STA_ALL) { | 766 | ; /* do nothing */ |
| 767 | } else if (get_slot_status(slot) == ACPI_STA_ALL) { | ||
| 746 | /* remove stale devices if any */ | 768 | /* remove stale devices if any */ |
| 747 | list_for_each_entry_safe(dev, tmp, &bus->devices, | 769 | list_for_each_entry_safe(dev, tmp, &bus->devices, |
| 748 | bus_list) | 770 | bus_list) |
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 577074efbe62..f7ebdba14bde 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
| @@ -330,29 +330,32 @@ static int acpi_pci_find_device(struct device *dev, acpi_handle *handle) | |||
| 330 | static void pci_acpi_setup(struct device *dev) | 330 | static void pci_acpi_setup(struct device *dev) |
| 331 | { | 331 | { |
| 332 | struct pci_dev *pci_dev = to_pci_dev(dev); | 332 | struct pci_dev *pci_dev = to_pci_dev(dev); |
| 333 | acpi_handle handle = ACPI_HANDLE(dev); | 333 | struct acpi_device *adev = ACPI_COMPANION(dev); |
| 334 | struct acpi_device *adev; | ||
| 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 | return; | 340 | return; |
| 338 | 341 | ||
| 339 | device_set_wakeup_capable(dev, true); | 342 | device_set_wakeup_capable(dev, true); |
| 340 | acpi_pci_sleep_wake(pci_dev, false); | 343 | acpi_pci_sleep_wake(pci_dev, false); |
| 341 | |||
| 342 | pci_acpi_add_pm_notifier(adev, pci_dev); | ||
| 343 | if (adev->wakeup.flags.run_wake) | 344 | if (adev->wakeup.flags.run_wake) |
| 344 | device_set_run_wake(dev, true); | 345 | device_set_run_wake(dev, true); |
| 345 | } | 346 | } |
| 346 | 347 | ||
| 347 | static void pci_acpi_cleanup(struct device *dev) | 348 | static void pci_acpi_cleanup(struct device *dev) |
| 348 | { | 349 | { |
| 349 | acpi_handle handle = ACPI_HANDLE(dev); | 350 | struct acpi_device *adev = ACPI_COMPANION(dev); |
| 350 | struct acpi_device *adev; | 351 | |
| 352 | if (!adev) | ||
| 353 | return; | ||
| 351 | 354 | ||
| 352 | if (!acpi_bus_get_device(handle, &adev) && adev->wakeup.flags.valid) { | 355 | pci_acpi_remove_pm_notifier(adev); |
| 356 | if (adev->wakeup.flags.valid) { | ||
| 353 | device_set_wakeup_capable(dev, false); | 357 | device_set_wakeup_capable(dev, false); |
| 354 | device_set_run_wake(dev, false); | 358 | device_set_run_wake(dev, false); |
| 355 | pci_acpi_remove_pm_notifier(adev); | ||
| 356 | } | 359 | } |
| 357 | } | 360 | } |
| 358 | 361 | ||
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index c602c7718421..ddabed1f51c2 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
| @@ -169,7 +169,8 @@ struct acpi_device_flags { | |||
| 169 | u32 ejectable:1; | 169 | u32 ejectable:1; |
| 170 | u32 power_manageable:1; | 170 | u32 power_manageable:1; |
| 171 | u32 match_driver:1; | 171 | u32 match_driver:1; |
| 172 | u32 reserved:27; | 172 | u32 no_hotplug:1; |
| 173 | u32 reserved:26; | ||
| 173 | }; | 174 | }; |
| 174 | 175 | ||
| 175 | /* File System */ | 176 | /* File System */ |
| @@ -344,6 +345,7 @@ extern struct kobject *acpi_kobj; | |||
| 344 | extern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int); | 345 | extern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int); |
| 345 | void acpi_bus_private_data_handler(acpi_handle, void *); | 346 | void acpi_bus_private_data_handler(acpi_handle, void *); |
| 346 | int acpi_bus_get_private_data(acpi_handle, void **); | 347 | int acpi_bus_get_private_data(acpi_handle, void **); |
| 348 | void acpi_bus_no_hotplug(acpi_handle handle); | ||
| 347 | extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32); | 349 | extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32); |
| 348 | extern int register_acpi_notifier(struct notifier_block *); | 350 | extern int register_acpi_notifier(struct notifier_block *); |
| 349 | extern int unregister_acpi_notifier(struct notifier_block *); | 351 | extern int unregister_acpi_notifier(struct notifier_block *); |
