cpufreq: Use syscore_ops for boot CPU suspend/resume (v2)

The cpufreq subsystem uses sysdev suspend and resume for
executing cpufreq_suspend() and cpufreq_resume(), respectively,
during system suspend, after interrupts have been switched off on the
boot CPU, and during system resume, while interrupts are still off on
the boot CPU. In both cases the other CPUs are off-line at the
relevant point (either they have been switched off via CPU hotplug
during suspend, or they haven't been switched on yet during resume).
For this reason, although it may seem that cpufreq_suspend() and
cpufreq_resume() are executed for all CPUs in the system, they are
only called for the boot CPU in fact, which is quite confusing.

To remove the confusion and to prepare for elimiating sysdev
suspend and resume operations from the kernel enirely, convernt
cpufreq to using a struct syscore_ops object for the boot CPU
suspend and resume and rename the callbacks so that their names
reflect their purpose. In addition, put some explanatory remarks
into their kerneldoc comments.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>

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