diff options
-rw-r--r-- | drivers/cpufreq/cpufreq.c | 66 |
1 files changed, 26 insertions, 40 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 0f17ad8585d7..b03771d4787c 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/cpu.h> | 28 | #include <linux/cpu.h> |
29 | #include <linux/completion.h> | 29 | #include <linux/completion.h> |
30 | #include <linux/mutex.h> | 30 | #include <linux/mutex.h> |
31 | #include <linux/syscore_ops.h> | ||
31 | 32 | ||
32 | #include <trace/events/power.h> | 33 | #include <trace/events/power.h> |
33 | 34 | ||
@@ -1340,35 +1341,31 @@ out: | |||
1340 | } | 1341 | } |
1341 | EXPORT_SYMBOL(cpufreq_get); | 1342 | EXPORT_SYMBOL(cpufreq_get); |
1342 | 1343 | ||
1344 | static struct sysdev_driver cpufreq_sysdev_driver = { | ||
1345 | .add = cpufreq_add_dev, | ||
1346 | .remove = cpufreq_remove_dev, | ||
1347 | }; | ||
1348 | |||
1343 | 1349 | ||
1344 | /** | 1350 | /** |
1345 | * cpufreq_suspend - let the low level driver prepare for suspend | 1351 | * cpufreq_bp_suspend - Prepare the boot CPU for system suspend. |
1352 | * | ||
1353 | * This function is only executed for the boot processor. The other CPUs | ||
1354 | * have been put offline by means of CPU hotplug. | ||
1346 | */ | 1355 | */ |
1347 | 1356 | static int cpufreq_bp_suspend(void) | |
1348 | static int cpufreq_suspend(struct sys_device *sysdev, pm_message_t pmsg) | ||
1349 | { | 1357 | { |
1350 | int ret = 0; | 1358 | int ret = 0; |
1351 | 1359 | ||
1352 | int cpu = sysdev->id; | 1360 | int cpu = smp_processor_id(); |
1353 | struct cpufreq_policy *cpu_policy; | 1361 | struct cpufreq_policy *cpu_policy; |
1354 | 1362 | ||
1355 | dprintk("suspending cpu %u\n", cpu); | 1363 | dprintk("suspending cpu %u\n", cpu); |
1356 | 1364 | ||
1357 | if (!cpu_online(cpu)) | 1365 | /* If there's no policy for the boot CPU, we have nothing to do. */ |
1358 | return 0; | ||
1359 | |||
1360 | /* we may be lax here as interrupts are off. Nonetheless | ||
1361 | * we need to grab the correct cpu policy, as to check | ||
1362 | * whether we really run on this CPU. | ||
1363 | */ | ||
1364 | |||
1365 | cpu_policy = cpufreq_cpu_get(cpu); | 1366 | cpu_policy = cpufreq_cpu_get(cpu); |
1366 | if (!cpu_policy) | 1367 | if (!cpu_policy) |
1367 | return -EINVAL; | 1368 | return 0; |
1368 | |||
1369 | /* only handle each CPU group once */ | ||
1370 | if (unlikely(cpu_policy->cpu != cpu)) | ||
1371 | goto out; | ||
1372 | 1369 | ||
1373 | if (cpufreq_driver->suspend) { | 1370 | if (cpufreq_driver->suspend) { |
1374 | ret = cpufreq_driver->suspend(cpu_policy); | 1371 | ret = cpufreq_driver->suspend(cpu_policy); |
@@ -1377,13 +1374,12 @@ static int cpufreq_suspend(struct sys_device *sysdev, pm_message_t pmsg) | |||
1377 | "step on CPU %u\n", cpu_policy->cpu); | 1374 | "step on CPU %u\n", cpu_policy->cpu); |
1378 | } | 1375 | } |
1379 | 1376 | ||
1380 | out: | ||
1381 | cpufreq_cpu_put(cpu_policy); | 1377 | cpufreq_cpu_put(cpu_policy); |
1382 | return ret; | 1378 | return ret; |
1383 | } | 1379 | } |
1384 | 1380 | ||
1385 | /** | 1381 | /** |
1386 | * cpufreq_resume - restore proper CPU frequency handling after resume | 1382 | * cpufreq_bp_resume - Restore proper frequency handling of the boot CPU. |
1387 | * | 1383 | * |
1388 | * 1.) resume CPUfreq hardware support (cpufreq_driver->resume()) | 1384 | * 1.) resume CPUfreq hardware support (cpufreq_driver->resume()) |
1389 | * 2.) schedule call cpufreq_update_policy() ASAP as interrupts are | 1385 | * 2.) schedule call cpufreq_update_policy() ASAP as interrupts are |
@@ -1391,31 +1387,23 @@ out: | |||
1391 | * what we believe it to be. This is a bit later than when it | 1387 | * what we believe it to be. This is a bit later than when it |
1392 | * should be, but nonethteless it's better than calling | 1388 | * should be, but nonethteless it's better than calling |
1393 | * cpufreq_driver->get() here which might re-enable interrupts... | 1389 | * cpufreq_driver->get() here which might re-enable interrupts... |
1390 | * | ||
1391 | * This function is only executed for the boot CPU. The other CPUs have not | ||
1392 | * been turned on yet. | ||
1394 | */ | 1393 | */ |
1395 | static int cpufreq_resume(struct sys_device *sysdev) | 1394 | static void cpufreq_bp_resume(void) |
1396 | { | 1395 | { |
1397 | int ret = 0; | 1396 | int ret = 0; |
1398 | 1397 | ||
1399 | int cpu = sysdev->id; | 1398 | int cpu = smp_processor_id(); |
1400 | struct cpufreq_policy *cpu_policy; | 1399 | struct cpufreq_policy *cpu_policy; |
1401 | 1400 | ||
1402 | dprintk("resuming cpu %u\n", cpu); | 1401 | dprintk("resuming cpu %u\n", cpu); |
1403 | 1402 | ||
1404 | if (!cpu_online(cpu)) | 1403 | /* If there's no policy for the boot CPU, we have nothing to do. */ |
1405 | return 0; | ||
1406 | |||
1407 | /* we may be lax here as interrupts are off. Nonetheless | ||
1408 | * we need to grab the correct cpu policy, as to check | ||
1409 | * whether we really run on this CPU. | ||
1410 | */ | ||
1411 | |||
1412 | cpu_policy = cpufreq_cpu_get(cpu); | 1404 | cpu_policy = cpufreq_cpu_get(cpu); |
1413 | if (!cpu_policy) | 1405 | if (!cpu_policy) |
1414 | return -EINVAL; | 1406 | return; |
1415 | |||
1416 | /* only handle each CPU group once */ | ||
1417 | if (unlikely(cpu_policy->cpu != cpu)) | ||
1418 | goto fail; | ||
1419 | 1407 | ||
1420 | if (cpufreq_driver->resume) { | 1408 | if (cpufreq_driver->resume) { |
1421 | ret = cpufreq_driver->resume(cpu_policy); | 1409 | ret = cpufreq_driver->resume(cpu_policy); |
@@ -1430,14 +1418,11 @@ static int cpufreq_resume(struct sys_device *sysdev) | |||
1430 | 1418 | ||
1431 | fail: | 1419 | fail: |
1432 | cpufreq_cpu_put(cpu_policy); | 1420 | cpufreq_cpu_put(cpu_policy); |
1433 | return ret; | ||
1434 | } | 1421 | } |
1435 | 1422 | ||
1436 | static struct sysdev_driver cpufreq_sysdev_driver = { | 1423 | static struct syscore_ops cpufreq_syscore_ops = { |
1437 | .add = cpufreq_add_dev, | 1424 | .suspend = cpufreq_bp_suspend, |
1438 | .remove = cpufreq_remove_dev, | 1425 | .resume = cpufreq_bp_resume, |
1439 | .suspend = cpufreq_suspend, | ||
1440 | .resume = cpufreq_resume, | ||
1441 | }; | 1426 | }; |
1442 | 1427 | ||
1443 | 1428 | ||
@@ -2002,6 +1987,7 @@ static int __init cpufreq_core_init(void) | |||
2002 | cpufreq_global_kobject = kobject_create_and_add("cpufreq", | 1987 | cpufreq_global_kobject = kobject_create_and_add("cpufreq", |
2003 | &cpu_sysdev_class.kset.kobj); | 1988 | &cpu_sysdev_class.kset.kobj); |
2004 | BUG_ON(!cpufreq_global_kobject); | 1989 | BUG_ON(!cpufreq_global_kobject); |
1990 | register_syscore_ops(&cpufreq_syscore_ops); | ||
2005 | 1991 | ||
2006 | return 0; | 1992 | return 0; |
2007 | } | 1993 | } |