Skip to content

Commit 23e8e59

Browse files
committed
Merge tag 'pm+acpi-3.13-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull ACPI and PM fixes and new device IDs from Rafael Wysocki: "These commits, except for one, are regression fixes and the remaining one fixes a divide error leading to a kernel panic. The majority of the regressions fixed here were introduced during the 3.12 cycle, one of them is from this cycle and one is older. Specifics: - VGA switcheroo was broken for some users as a result of the ACPI-based PCI hotplug (ACPIPHP) changes in 3.12, because some previously ignored hotplug events started to be handled. The fix causes them to be ignored again. - There are two more issues related to cpufreq's suspend/resume handling changes from the 3.12 cycle addressed by Viresh Kumar's fixes. - intel_pstate triggers a divide error in a timer function if the P-state information it needs is missing during initialization. This leads to kernel panics on nested KVM clients and is fixed by failing the initialization cleanly in those cases. - PCI initalization code changes during the 3.9 cycle uncovered BIOS issues related to ACPI wakeup notifications (some BIOSes send them for devices that aren't supposed to support ACPI wakeup). Work around them by installing an ACPI wakeup notify handler for all PCI devices with ACPI support. - The Calxeda cpuilde driver's probe function is tagged as __init, which is incorrect and causes a section mismatch to occur during build. Fix from Andre Przywara removes the __init tag from there. - During the 3.12 cycle ACPIPHP started to print warnings about missing _ADR for devices that legitimately don't have it. Fix from Toshi Kani makes it only print the warnings where they make sense" * tag 'pm+acpi-3.13-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: ACPIPHP / radeon / nouveau: Fix VGA switcheroo problem related to hotplug intel_pstate: Fail initialization if P-state information is missing ARM/cpuidle: remove __init tag from Calxeda cpuidle probe function PCI / ACPI: Install wakeup notify handlers for all PCI devs with ACPI cpufreq: preserve user_policy across suspend/resume cpufreq: Clean up after a failing light-weight initialization ACPI / PCI / hotplug: Avoid warning when _ADR not present
2 parents 7a262d2 + 0a405fe commit 23e8e59

File tree

9 files changed

+108
-33
lines changed

9 files changed

+108
-33
lines changed

drivers/acpi/bus.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,16 @@ int acpi_bus_get_private_data(acpi_handle handle, void **data)
156156
}
157157
EXPORT_SYMBOL(acpi_bus_get_private_data);
158158

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+
159169
static void acpi_print_osc_error(acpi_handle handle,
160170
struct acpi_osc_context *context, char *error)
161171
{

drivers/cpufreq/cpufreq.c

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -839,9 +839,6 @@ static void cpufreq_init_policy(struct cpufreq_policy *policy)
839839

840840
/* set default policy */
841841
ret = cpufreq_set_policy(policy, &new_policy);
842-
policy->user_policy.policy = policy->policy;
843-
policy->user_policy.governor = policy->governor;
844-
845842
if (ret) {
846843
pr_debug("setting policy failed\n");
847844
if (cpufreq_driver->exit)
@@ -1016,15 +1013,17 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
10161013
read_unlock_irqrestore(&cpufreq_driver_lock, flags);
10171014
#endif
10181015

1019-
if (frozen)
1020-
/* Restore the saved policy when doing light-weight init */
1021-
policy = cpufreq_policy_restore(cpu);
1022-
else
1016+
/*
1017+
* Restore the saved policy when doing light-weight init and fall back
1018+
* to the full init if that fails.
1019+
*/
1020+
policy = frozen ? cpufreq_policy_restore(cpu) : NULL;
1021+
if (!policy) {
1022+
frozen = false;
10231023
policy = cpufreq_policy_alloc();
1024-
1025-
if (!policy)
1026-
goto nomem_out;
1027-
1024+
if (!policy)
1025+
goto nomem_out;
1026+
}
10281027

10291028
/*
10301029
* 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,
10691068
*/
10701069
cpumask_and(policy->cpus, policy->cpus, cpu_online_mask);
10711070

1072-
policy->user_policy.min = policy->min;
1073-
policy->user_policy.max = policy->max;
1071+
if (!frozen) {
1072+
policy->user_policy.min = policy->min;
1073+
policy->user_policy.max = policy->max;
1074+
}
10741075

10751076
blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
10761077
CPUFREQ_START, policy);
@@ -1101,6 +1102,11 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
11011102

11021103
cpufreq_init_policy(policy);
11031104

1105+
if (!frozen) {
1106+
policy->user_policy.policy = policy->policy;
1107+
policy->user_policy.governor = policy->governor;
1108+
}
1109+
11041110
kobject_uevent(&policy->kobj, KOBJ_ADD);
11051111
up_read(&cpufreq_rwsem);
11061112

@@ -1118,8 +1124,11 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
11181124
if (cpufreq_driver->exit)
11191125
cpufreq_driver->exit(policy);
11201126
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;
11221130
cpufreq_policy_put_kobj(policy);
1131+
}
11231132
cpufreq_policy_free(policy);
11241133

11251134
nomem_out:

drivers/cpufreq/intel_pstate.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,11 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
614614
cpu = all_cpu_data[cpunum];
615615

616616
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+
}
617622

618623
cpu->cpu = cpunum;
619624

drivers/cpuidle/cpuidle-calxeda.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ static struct cpuidle_driver calxeda_idle_driver = {
6565
.state_count = 2,
6666
};
6767

68-
static int __init calxeda_cpuidle_probe(struct platform_device *pdev)
68+
static int calxeda_cpuidle_probe(struct platform_device *pdev)
6969
{
7070
return cpuidle_register(&calxeda_idle_driver, NULL);
7171
}

drivers/gpu/drm/nouveau/nouveau_acpi.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ static struct nouveau_dsm_priv {
5151
bool dsm_detected;
5252
bool optimus_detected;
5353
acpi_handle dhandle;
54+
acpi_handle other_handle;
5455
acpi_handle rom_handle;
5556
} nouveau_dsm_priv;
5657

@@ -260,9 +261,10 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev)
260261
if (!dhandle)
261262
return false;
262263

263-
if (!acpi_has_method(dhandle, "_DSM"))
264+
if (!acpi_has_method(dhandle, "_DSM")) {
265+
nouveau_dsm_priv.other_handle = dhandle;
264266
return false;
265-
267+
}
266268
if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER))
267269
retval |= NOUVEAU_DSM_HAS_MUX;
268270

@@ -338,6 +340,16 @@ static bool nouveau_dsm_detect(void)
338340
printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n",
339341
acpi_method_name);
340342
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);
341353
ret = true;
342354
}
343355

drivers/gpu/drm/radeon/radeon_atpx_handler.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ static struct radeon_atpx_priv {
3333
bool atpx_detected;
3434
/* handle for device - and atpx */
3535
acpi_handle dhandle;
36+
acpi_handle other_handle;
3637
struct radeon_atpx atpx;
3738
} radeon_atpx_priv;
3839

@@ -451,9 +452,10 @@ static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev)
451452
return false;
452453

453454
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;
455457
return false;
456-
458+
}
457459
radeon_atpx_priv.dhandle = dhandle;
458460
radeon_atpx_priv.atpx.handle = atpx_handle;
459461
return true;
@@ -530,6 +532,16 @@ static bool radeon_atpx_detect(void)
530532
printk(KERN_INFO "VGA switcheroo: detected switching method %s handle\n",
531533
acpi_method_name);
532534
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);
533545
return true;
534546
}
535547
return false;

drivers/pci/hotplug/acpiphp_glue.c

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,9 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,
279279

280280
status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
281281
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);
283285
return AE_OK;
284286
}
285287

@@ -643,6 +645,24 @@ static void disable_slot(struct acpiphp_slot *slot)
643645
slot->flags &= (~SLOT_ENABLED);
644646
}
645647

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+
}
646666

647667
/**
648668
* get_slot_status - get ACPI slot status
@@ -701,7 +721,8 @@ static void trim_stale_devices(struct pci_dev *dev)
701721
unsigned long long sta;
702722

703723
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);
705726
}
706727
if (!alive) {
707728
u32 v;
@@ -741,8 +762,9 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
741762
struct pci_dev *dev, *tmp;
742763

743764
mutex_lock(&slot->crit_sect);
744-
/* wake up all functions */
745-
if (get_slot_status(slot) == ACPI_STA_ALL) {
765+
if (slot_no_hotplug(slot)) {
766+
; /* do nothing */
767+
} else if (get_slot_status(slot) == ACPI_STA_ALL) {
746768
/* remove stale devices if any */
747769
list_for_each_entry_safe(dev, tmp, &bus->devices,
748770
bus_list)

drivers/pci/pci-acpi.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -330,29 +330,32 @@ static int acpi_pci_find_device(struct device *dev, acpi_handle *handle)
330330
static void pci_acpi_setup(struct device *dev)
331331
{
332332
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);
335334

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)
337340
return;
338341

339342
device_set_wakeup_capable(dev, true);
340343
acpi_pci_sleep_wake(pci_dev, false);
341-
342-
pci_acpi_add_pm_notifier(adev, pci_dev);
343344
if (adev->wakeup.flags.run_wake)
344345
device_set_run_wake(dev, true);
345346
}
346347

347348
static void pci_acpi_cleanup(struct device *dev)
348349
{
349-
acpi_handle handle = ACPI_HANDLE(dev);
350-
struct acpi_device *adev;
350+
struct acpi_device *adev = ACPI_COMPANION(dev);
351+
352+
if (!adev)
353+
return;
351354

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) {
353357
device_set_wakeup_capable(dev, false);
354358
device_set_run_wake(dev, false);
355-
pci_acpi_remove_pm_notifier(adev);
356359
}
357360
}
358361

include/acpi/acpi_bus.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,8 @@ struct acpi_device_flags {
169169
u32 ejectable:1;
170170
u32 power_manageable:1;
171171
u32 match_driver:1;
172-
u32 reserved:27;
172+
u32 no_hotplug:1;
173+
u32 reserved:26;
173174
};
174175

175176
/* File System */
@@ -344,6 +345,7 @@ extern struct kobject *acpi_kobj;
344345
extern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int);
345346
void acpi_bus_private_data_handler(acpi_handle, void *);
346347
int acpi_bus_get_private_data(acpi_handle, void **);
348+
void acpi_bus_no_hotplug(acpi_handle handle);
347349
extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32);
348350
extern int register_acpi_notifier(struct notifier_block *);
349351
extern int unregister_acpi_notifier(struct notifier_block *);

0 commit comments

Comments
 (0)