Skip to content

Commit a10d15a

Browse files
committed
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"
2 parents 30f0920 + 43ff36c commit a10d15a

3 files changed

Lines changed: 76 additions & 79 deletions

File tree

drivers/acpi/processor_driver.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,8 @@ static int __acpi_processor_start(struct acpi_device *device)
166166
if (result && !IS_ENABLED(CONFIG_ACPI_CPU_FREQ_PSS))
167167
dev_dbg(&device->dev, "CPPC data invalid or not present\n");
168168

169-
acpi_processor_power_init(pr);
169+
if (cpuidle_get_driver() == &acpi_idle_driver)
170+
acpi_processor_power_init(pr);
170171

171172
acpi_pss_perf_init(pr);
172173

@@ -262,8 +263,6 @@ static int __init acpi_processor_driver_init(void)
262263
if (result < 0)
263264
return result;
264265

265-
acpi_processor_register_idle_driver();
266-
267266
result = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
268267
"acpi/cpu-drv:online",
269268
acpi_soft_cpu_online, NULL);
@@ -302,7 +301,6 @@ static void __exit acpi_processor_driver_exit(void)
302301

303302
cpuhp_remove_state_nocalls(hp_online);
304303
cpuhp_remove_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD);
305-
acpi_processor_unregister_idle_driver();
306304
driver_unregister(&acpi_processor_driver);
307305
}
308306

drivers/acpi/processor_idle.c

Lines changed: 46 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ module_param(latency_factor, uint, 0644);
5151

5252
static DEFINE_PER_CPU(struct cpuidle_device *, acpi_cpuidle_device);
5353

54-
static struct cpuidle_driver acpi_idle_driver = {
54+
struct cpuidle_driver acpi_idle_driver = {
5555
.name = "acpi_idle",
5656
.owner = THIS_MODULE,
5757
};
@@ -1357,102 +1357,79 @@ int acpi_processor_power_state_has_changed(struct acpi_processor *pr)
13571357
return 0;
13581358
}
13591359

1360-
void acpi_processor_register_idle_driver(void)
1361-
{
1362-
struct acpi_processor *pr;
1363-
int ret = -ENODEV;
1364-
int cpu;
1365-
1366-
/*
1367-
* Acpi idle driver is used by all possible CPUs.
1368-
* Install the idle handler by the processor power info of one in them.
1369-
* Note that we use previously set idle handler will be used on
1370-
* platforms that only support C1.
1371-
*/
1372-
for_each_cpu(cpu, (struct cpumask *)cpu_possible_mask) {
1373-
pr = per_cpu(processors, cpu);
1374-
if (!pr)
1375-
continue;
1376-
1377-
ret = acpi_processor_get_power_info(pr);
1378-
if (!ret) {
1379-
pr->flags.power_setup_done = 1;
1380-
acpi_processor_setup_cpuidle_states(pr);
1381-
break;
1382-
}
1383-
}
1384-
1385-
if (ret) {
1386-
pr_debug("No ACPI power information from any CPUs.\n");
1387-
return;
1388-
}
1360+
static int acpi_processor_registered;
13891361

1390-
ret = cpuidle_register_driver(&acpi_idle_driver);
1391-
if (ret) {
1392-
pr_debug("register %s failed.\n", acpi_idle_driver.name);
1393-
return;
1394-
}
1395-
pr_debug("%s registered with cpuidle.\n", acpi_idle_driver.name);
1396-
}
1397-
1398-
void acpi_processor_unregister_idle_driver(void)
1399-
{
1400-
cpuidle_unregister_driver(&acpi_idle_driver);
1401-
}
1402-
1403-
void acpi_processor_power_init(struct acpi_processor *pr)
1362+
int acpi_processor_power_init(struct acpi_processor *pr)
14041363
{
1364+
int retval;
14051365
struct cpuidle_device *dev;
14061366

1407-
/*
1408-
* The code below only works if the current cpuidle driver is the ACPI
1409-
* idle driver.
1410-
*/
1411-
if (cpuidle_get_driver() != &acpi_idle_driver)
1412-
return;
1413-
14141367
if (disabled_by_idle_boot_param())
1415-
return;
1368+
return 0;
14161369

14171370
acpi_processor_cstate_first_run_checks();
14181371

14191372
if (!acpi_processor_get_power_info(pr))
14201373
pr->flags.power_setup_done = 1;
14211374

1422-
if (!pr->flags.power)
1423-
return;
1424-
1425-
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1426-
if (!dev)
1427-
return;
1375+
/*
1376+
* Install the idle handler if processor power management is supported.
1377+
* Note that we use previously set idle handler will be used on
1378+
* platforms that only support C1.
1379+
*/
1380+
if (pr->flags.power) {
1381+
/* Register acpi_idle_driver if not already registered */
1382+
if (!acpi_processor_registered) {
1383+
acpi_processor_setup_cpuidle_states(pr);
1384+
retval = cpuidle_register_driver(&acpi_idle_driver);
1385+
if (retval)
1386+
return retval;
1387+
pr_debug("%s registered with cpuidle\n",
1388+
acpi_idle_driver.name);
1389+
}
14281390

1429-
per_cpu(acpi_cpuidle_device, pr->id) = dev;
1391+
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1392+
if (!dev)
1393+
return -ENOMEM;
1394+
per_cpu(acpi_cpuidle_device, pr->id) = dev;
14301395

1431-
acpi_processor_setup_cpuidle_dev(pr, dev);
1396+
acpi_processor_setup_cpuidle_dev(pr, dev);
14321397

1433-
/*
1434-
* Register a cpuidle device for this CPU. The cpuidle driver using
1435-
* this device is expected to be registered.
1436-
*/
1437-
if (cpuidle_register_device(dev)) {
1438-
per_cpu(acpi_cpuidle_device, pr->id) = NULL;
1439-
kfree(dev);
1398+
/* Register per-cpu cpuidle_device. Cpuidle driver
1399+
* must already be registered before registering device
1400+
*/
1401+
retval = cpuidle_register_device(dev);
1402+
if (retval) {
1403+
if (acpi_processor_registered == 0)
1404+
cpuidle_unregister_driver(&acpi_idle_driver);
1405+
1406+
per_cpu(acpi_cpuidle_device, pr->id) = NULL;
1407+
kfree(dev);
1408+
return retval;
1409+
}
1410+
acpi_processor_registered++;
14401411
}
1412+
return 0;
14411413
}
14421414

1443-
void acpi_processor_power_exit(struct acpi_processor *pr)
1415+
int acpi_processor_power_exit(struct acpi_processor *pr)
14441416
{
14451417
struct cpuidle_device *dev = per_cpu(acpi_cpuidle_device, pr->id);
14461418

14471419
if (disabled_by_idle_boot_param())
1448-
return;
1420+
return 0;
14491421

14501422
if (pr->flags.power) {
14511423
cpuidle_unregister_device(dev);
1424+
acpi_processor_registered--;
1425+
if (acpi_processor_registered == 0)
1426+
cpuidle_unregister_driver(&acpi_idle_driver);
1427+
14521428
kfree(dev);
14531429
}
14541430

14551431
pr->flags.power_setup_done = 0;
1432+
return 0;
14561433
}
14571434

14581435
MODULE_IMPORT_NS("ACPI_PROCESSOR_IDLE");

include/acpi/processor.h

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -417,15 +417,32 @@ static inline void acpi_processor_throttling_init(void) {}
417417
#endif /* CONFIG_ACPI_CPU_FREQ_PSS */
418418

419419
/* in processor_idle.c */
420+
extern struct cpuidle_driver acpi_idle_driver;
420421
#ifdef CONFIG_ACPI_PROCESSOR_IDLE
421-
void acpi_processor_power_init(struct acpi_processor *pr);
422-
void acpi_processor_power_exit(struct acpi_processor *pr);
422+
int acpi_processor_power_init(struct acpi_processor *pr);
423+
int acpi_processor_power_exit(struct acpi_processor *pr);
423424
int acpi_processor_power_state_has_changed(struct acpi_processor *pr);
424425
int acpi_processor_hotplug(struct acpi_processor *pr);
425-
void acpi_processor_register_idle_driver(void);
426-
void acpi_processor_unregister_idle_driver(void);
427-
int acpi_processor_ffh_lpi_probe(unsigned int cpu);
428-
int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi);
426+
#else
427+
static inline int acpi_processor_power_init(struct acpi_processor *pr)
428+
{
429+
return -ENODEV;
430+
}
431+
432+
static inline int acpi_processor_power_exit(struct acpi_processor *pr)
433+
{
434+
return -ENODEV;
435+
}
436+
437+
static inline int acpi_processor_power_state_has_changed(struct acpi_processor *pr)
438+
{
439+
return -ENODEV;
440+
}
441+
442+
static inline int acpi_processor_hotplug(struct acpi_processor *pr)
443+
{
444+
return -ENODEV;
445+
}
429446
#endif /* CONFIG_ACPI_PROCESSOR_IDLE */
430447

431448
/* in processor_thermal.c */
@@ -448,6 +465,11 @@ static inline void acpi_thermal_cpufreq_exit(struct cpufreq_policy *policy)
448465
}
449466
#endif /* CONFIG_CPU_FREQ */
450467

468+
#ifdef CONFIG_ACPI_PROCESSOR_IDLE
469+
extern int acpi_processor_ffh_lpi_probe(unsigned int cpu);
470+
extern int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi);
471+
#endif
472+
451473
void acpi_processor_init_invariance_cppc(void);
452474

453475
#endif

0 commit comments

Comments
 (0)