mirror of https://github.com/torvalds/linux.git
Urgent ACPI support fix for 6.18
Revert a commit that attempted to make the code in the ACPI processor driver more straightforward, but it turned out to cause the kernel to crash on at least one system, along with some further cleanups on top of it. -----BEGIN PGP SIGNATURE----- iQFGBAABCAAwFiEEcM8Aw/RY0dgsiRUR7l+9nS/U47UFAmkm9t4SHHJqd0Byand5 c29ja2kubmV0AAoJEO5fvZ0v1OO1cB8H/iPHijCAzh3zyFmKRju3j8MFCWCqTVse RwLKY4NJba+4WorxVTtBcNLclz6rGf+/Qj/Xyv25zH0nGRhZtcbr/pGq9b4r0UMH IxqpN8BfON+UGCT5sIs9yMFl+Lt14+OAtLUI3NBQU8n4o9PznFQi2fe0sgpweP0A wO4Y9SVEYB3kWca0HqQ8ZWlhsAEDnxm6GvZ6ks18ShOYYE08c1X/dWkuYz2A7tCg BunwzVePwWBgd3JNlpdtscI5JhsA3WsNiB1vnL96toyh/SK0oRaKydmxOvfrw6Mz JvDn6YKUfr4zBiKRGMcwRQWnL3yi2PAq8wD8qie6rt8jaAo2bg9EUJI= =K5ke -----END PGP SIGNATURE----- Merge tag 'acpi-6.18-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm Pull ACPI fix from Rafael Wysocki: "Revert a commit that attempted to make the code in the ACPI processor driver more straightforward, but it turned out to cause the kernel to crash on at least one system, along with some further cleanups on top of it" * tag 'acpi-6.18-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: Revert "ACPI: processor: idle: Optimize ACPI idle driver registration" Revert "ACPI: processor: Remove unused empty stubs of some functions" Revert "ACPI: processor: idle: Rearrange declarations in header file" Revert "ACPI: processor: idle: Redefine two functions as void" Revert "ACPI: processor: Do not expose global variable acpi_idle_driver"
This commit is contained in:
commit
a10d15a08f
|
|
@ -166,7 +166,8 @@ static int __acpi_processor_start(struct acpi_device *device)
|
|||
if (result && !IS_ENABLED(CONFIG_ACPI_CPU_FREQ_PSS))
|
||||
dev_dbg(&device->dev, "CPPC data invalid or not present\n");
|
||||
|
||||
acpi_processor_power_init(pr);
|
||||
if (cpuidle_get_driver() == &acpi_idle_driver)
|
||||
acpi_processor_power_init(pr);
|
||||
|
||||
acpi_pss_perf_init(pr);
|
||||
|
||||
|
|
@ -262,8 +263,6 @@ static int __init acpi_processor_driver_init(void)
|
|||
if (result < 0)
|
||||
return result;
|
||||
|
||||
acpi_processor_register_idle_driver();
|
||||
|
||||
result = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
|
||||
"acpi/cpu-drv:online",
|
||||
acpi_soft_cpu_online, NULL);
|
||||
|
|
@ -302,7 +301,6 @@ static void __exit acpi_processor_driver_exit(void)
|
|||
|
||||
cpuhp_remove_state_nocalls(hp_online);
|
||||
cpuhp_remove_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD);
|
||||
acpi_processor_unregister_idle_driver();
|
||||
driver_unregister(&acpi_processor_driver);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ module_param(latency_factor, uint, 0644);
|
|||
|
||||
static DEFINE_PER_CPU(struct cpuidle_device *, acpi_cpuidle_device);
|
||||
|
||||
static struct cpuidle_driver acpi_idle_driver = {
|
||||
struct cpuidle_driver acpi_idle_driver = {
|
||||
.name = "acpi_idle",
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
|
@ -1357,102 +1357,79 @@ int acpi_processor_power_state_has_changed(struct acpi_processor *pr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void acpi_processor_register_idle_driver(void)
|
||||
{
|
||||
struct acpi_processor *pr;
|
||||
int ret = -ENODEV;
|
||||
int cpu;
|
||||
|
||||
/*
|
||||
* Acpi idle driver is used by all possible CPUs.
|
||||
* Install the idle handler by the processor power info of one in them.
|
||||
* Note that we use previously set idle handler will be used on
|
||||
* platforms that only support C1.
|
||||
*/
|
||||
for_each_cpu(cpu, (struct cpumask *)cpu_possible_mask) {
|
||||
pr = per_cpu(processors, cpu);
|
||||
if (!pr)
|
||||
continue;
|
||||
|
||||
ret = acpi_processor_get_power_info(pr);
|
||||
if (!ret) {
|
||||
pr->flags.power_setup_done = 1;
|
||||
acpi_processor_setup_cpuidle_states(pr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
pr_debug("No ACPI power information from any CPUs.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = cpuidle_register_driver(&acpi_idle_driver);
|
||||
if (ret) {
|
||||
pr_debug("register %s failed.\n", acpi_idle_driver.name);
|
||||
return;
|
||||
}
|
||||
pr_debug("%s registered with cpuidle.\n", acpi_idle_driver.name);
|
||||
}
|
||||
|
||||
void acpi_processor_unregister_idle_driver(void)
|
||||
{
|
||||
cpuidle_unregister_driver(&acpi_idle_driver);
|
||||
}
|
||||
|
||||
void acpi_processor_power_init(struct acpi_processor *pr)
|
||||
static int acpi_processor_registered;
|
||||
|
||||
int acpi_processor_power_init(struct acpi_processor *pr)
|
||||
{
|
||||
int retval;
|
||||
struct cpuidle_device *dev;
|
||||
|
||||
/*
|
||||
* The code below only works if the current cpuidle driver is the ACPI
|
||||
* idle driver.
|
||||
*/
|
||||
if (cpuidle_get_driver() != &acpi_idle_driver)
|
||||
return;
|
||||
|
||||
if (disabled_by_idle_boot_param())
|
||||
return;
|
||||
return 0;
|
||||
|
||||
acpi_processor_cstate_first_run_checks();
|
||||
|
||||
if (!acpi_processor_get_power_info(pr))
|
||||
pr->flags.power_setup_done = 1;
|
||||
|
||||
if (!pr->flags.power)
|
||||
return;
|
||||
|
||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
per_cpu(acpi_cpuidle_device, pr->id) = dev;
|
||||
|
||||
acpi_processor_setup_cpuidle_dev(pr, dev);
|
||||
|
||||
/*
|
||||
* Register a cpuidle device for this CPU. The cpuidle driver using
|
||||
* this device is expected to be registered.
|
||||
* Install the idle handler if processor power management is supported.
|
||||
* Note that we use previously set idle handler will be used on
|
||||
* platforms that only support C1.
|
||||
*/
|
||||
if (cpuidle_register_device(dev)) {
|
||||
per_cpu(acpi_cpuidle_device, pr->id) = NULL;
|
||||
kfree(dev);
|
||||
if (pr->flags.power) {
|
||||
/* Register acpi_idle_driver if not already registered */
|
||||
if (!acpi_processor_registered) {
|
||||
acpi_processor_setup_cpuidle_states(pr);
|
||||
retval = cpuidle_register_driver(&acpi_idle_driver);
|
||||
if (retval)
|
||||
return retval;
|
||||
pr_debug("%s registered with cpuidle\n",
|
||||
acpi_idle_driver.name);
|
||||
}
|
||||
|
||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
per_cpu(acpi_cpuidle_device, pr->id) = dev;
|
||||
|
||||
acpi_processor_setup_cpuidle_dev(pr, dev);
|
||||
|
||||
/* Register per-cpu cpuidle_device. Cpuidle driver
|
||||
* must already be registered before registering device
|
||||
*/
|
||||
retval = cpuidle_register_device(dev);
|
||||
if (retval) {
|
||||
if (acpi_processor_registered == 0)
|
||||
cpuidle_unregister_driver(&acpi_idle_driver);
|
||||
|
||||
per_cpu(acpi_cpuidle_device, pr->id) = NULL;
|
||||
kfree(dev);
|
||||
return retval;
|
||||
}
|
||||
acpi_processor_registered++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void acpi_processor_power_exit(struct acpi_processor *pr)
|
||||
int acpi_processor_power_exit(struct acpi_processor *pr)
|
||||
{
|
||||
struct cpuidle_device *dev = per_cpu(acpi_cpuidle_device, pr->id);
|
||||
|
||||
if (disabled_by_idle_boot_param())
|
||||
return;
|
||||
return 0;
|
||||
|
||||
if (pr->flags.power) {
|
||||
cpuidle_unregister_device(dev);
|
||||
acpi_processor_registered--;
|
||||
if (acpi_processor_registered == 0)
|
||||
cpuidle_unregister_driver(&acpi_idle_driver);
|
||||
|
||||
kfree(dev);
|
||||
}
|
||||
|
||||
pr->flags.power_setup_done = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_IMPORT_NS("ACPI_PROCESSOR_IDLE");
|
||||
|
|
|
|||
|
|
@ -417,15 +417,32 @@ static inline void acpi_processor_throttling_init(void) {}
|
|||
#endif /* CONFIG_ACPI_CPU_FREQ_PSS */
|
||||
|
||||
/* in processor_idle.c */
|
||||
extern struct cpuidle_driver acpi_idle_driver;
|
||||
#ifdef CONFIG_ACPI_PROCESSOR_IDLE
|
||||
void acpi_processor_power_init(struct acpi_processor *pr);
|
||||
void acpi_processor_power_exit(struct acpi_processor *pr);
|
||||
int acpi_processor_power_init(struct acpi_processor *pr);
|
||||
int acpi_processor_power_exit(struct acpi_processor *pr);
|
||||
int acpi_processor_power_state_has_changed(struct acpi_processor *pr);
|
||||
int acpi_processor_hotplug(struct acpi_processor *pr);
|
||||
void acpi_processor_register_idle_driver(void);
|
||||
void acpi_processor_unregister_idle_driver(void);
|
||||
int acpi_processor_ffh_lpi_probe(unsigned int cpu);
|
||||
int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi);
|
||||
#else
|
||||
static inline int acpi_processor_power_init(struct acpi_processor *pr)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int acpi_processor_power_exit(struct acpi_processor *pr)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int acpi_processor_power_state_has_changed(struct acpi_processor *pr)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int acpi_processor_hotplug(struct acpi_processor *pr)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif /* CONFIG_ACPI_PROCESSOR_IDLE */
|
||||
|
||||
/* in processor_thermal.c */
|
||||
|
|
@ -448,6 +465,11 @@ static inline void acpi_thermal_cpufreq_exit(struct cpufreq_policy *policy)
|
|||
}
|
||||
#endif /* CONFIG_CPU_FREQ */
|
||||
|
||||
#ifdef CONFIG_ACPI_PROCESSOR_IDLE
|
||||
extern int acpi_processor_ffh_lpi_probe(unsigned int cpu);
|
||||
extern int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi);
|
||||
#endif
|
||||
|
||||
void acpi_processor_init_invariance_cppc(void);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue