[CPUFREQ] Re-enable cpufreq suspend and resume code

Commit 4bc5d3413503 is broken and causes regressions:

(1) cpufreq_driver->resume() and ->suspend() were only called on
__powerpc__, but you could set them on all architectures. In fact,
->resume() was defined and used before the PPC-related commit
42d4dc3f4e1e complained about in 4bc5d3413503.

(2) Therfore, the resume functions in acpi_cpufreq and speedstep-smi
would never be called.

(3) This means speedstep-smi would be unusuable after suspend or resume.

The _real_ problem was calling cpufreq_driver->get() with interrupts
off, but it re-enabling interrupts on some platforms. Why is ->get()
necessary?

Some systems like to change the CPU frequency behind our
back, especially during BIOS-intensive operations like suspend or
resume. If such systems also use a CPU frequency-dependant timing loop,
delays might be off by large factors. Therefore, we need to ascertain
as soon as possible that the CPU frequency is indeed at the speed we
think it is. You can do this two ways: either setting it anew, or trying
to get it. The latter is what was done, the former also has the same IRQ
issue.

So, let's try something different: defer the checking to after interrupts
are re-enabled, by calling cpufreq_update_policy() (via schedule_work()).
Timings may be off until this later stage, so let's watch out for
resume regressions caused by the deferred handling of frequency changes
behind the kernel's back.

Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Signed-off-by: Dave Jones <davej@redhat.com>

authored by Dominik Brodowski and committed by Dave Jones ce6c3997 37d0892c

+7 -88
+7 -88
drivers/cpufreq/cpufreq.c
··· 1250 { 1251 int ret = 0; 1252 1253 - #ifdef __powerpc__ 1254 int cpu = sysdev->id; 1255 - unsigned int cur_freq = 0; 1256 struct cpufreq_policy *cpu_policy; 1257 1258 dprintk("suspending cpu %u\n", cpu); 1259 - 1260 - /* 1261 - * This whole bogosity is here because Powerbooks are made of fail. 1262 - * No sane platform should need any of the code below to be run. 1263 - * (it's entirely the wrong thing to do, as driver->get may 1264 - * reenable interrupts on some architectures). 1265 - */ 1266 1267 if (!cpu_online(cpu)) 1268 return 0; ··· 1273 1274 if (cpufreq_driver->suspend) { 1275 ret = cpufreq_driver->suspend(cpu_policy, pmsg); 1276 - if (ret) { 1277 printk(KERN_ERR "cpufreq: suspend failed in ->suspend " 1278 "step on CPU %u\n", cpu_policy->cpu); 1279 - goto out; 1280 - } 1281 - } 1282 - 1283 - if (cpufreq_driver->flags & CPUFREQ_CONST_LOOPS) 1284 - goto out; 1285 - 1286 - if (cpufreq_driver->get) 1287 - cur_freq = cpufreq_driver->get(cpu_policy->cpu); 1288 - 1289 - if (!cur_freq || !cpu_policy->cur) { 1290 - printk(KERN_ERR "cpufreq: suspend failed to assert current " 1291 - "frequency is what timing core thinks it is.\n"); 1292 - goto out; 1293 - } 1294 - 1295 - if (unlikely(cur_freq != cpu_policy->cur)) { 1296 - struct cpufreq_freqs freqs; 1297 - 1298 - if (!(cpufreq_driver->flags & CPUFREQ_PM_NO_WARN)) 1299 - dprintk("Warning: CPU frequency is %u, " 1300 - "cpufreq assumed %u kHz.\n", 1301 - cur_freq, cpu_policy->cur); 1302 - 1303 - freqs.cpu = cpu; 1304 - freqs.old = cpu_policy->cur; 1305 - freqs.new = cur_freq; 1306 - 1307 - srcu_notifier_call_chain(&cpufreq_transition_notifier_list, 1308 - CPUFREQ_SUSPENDCHANGE, &freqs); 1309 - adjust_jiffies(CPUFREQ_SUSPENDCHANGE, &freqs); 1310 - 1311 - cpu_policy->cur = cur_freq; 1312 } 1313 1314 out: 1315 cpufreq_cpu_put(cpu_policy); 1316 - #endif /* __powerpc__ */ 1317 return ret; 1318 } 1319 ··· 1287 * cpufreq_resume - restore proper CPU frequency handling after resume 1288 * 1289 * 1.) resume CPUfreq hardware support (cpufreq_driver->resume()) 1290 - * 2.) if ->target and !CPUFREQ_CONST_LOOPS: verify we're in sync 1291 - * 3.) schedule call cpufreq_update_policy() ASAP as interrupts are 1292 - * restored. 1293 */ 1294 static int cpufreq_resume(struct sys_device *sysdev) 1295 { 1296 int ret = 0; 1297 1298 - #ifdef __powerpc__ 1299 int cpu = sysdev->id; 1300 struct cpufreq_policy *cpu_policy; 1301 1302 dprintk("resuming cpu %u\n", cpu); 1303 - 1304 - /* As with the ->suspend method, all the code below is 1305 - * only necessary because Powerbooks suck. 1306 - * See commit 42d4dc3f4e1e for jokes. */ 1307 1308 if (!cpu_online(cpu)) 1309 return 0; ··· 1327 } 1328 } 1329 1330 - if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { 1331 - unsigned int cur_freq = 0; 1332 - 1333 - if (cpufreq_driver->get) 1334 - cur_freq = cpufreq_driver->get(cpu_policy->cpu); 1335 - 1336 - if (!cur_freq || !cpu_policy->cur) { 1337 - printk(KERN_ERR "cpufreq: resume failed to assert " 1338 - "current frequency is what timing core " 1339 - "thinks it is.\n"); 1340 - goto out; 1341 - } 1342 - 1343 - if (unlikely(cur_freq != cpu_policy->cur)) { 1344 - struct cpufreq_freqs freqs; 1345 - 1346 - if (!(cpufreq_driver->flags & CPUFREQ_PM_NO_WARN)) 1347 - dprintk("Warning: CPU frequency " 1348 - "is %u, cpufreq assumed %u kHz.\n", 1349 - cur_freq, cpu_policy->cur); 1350 - 1351 - freqs.cpu = cpu; 1352 - freqs.old = cpu_policy->cur; 1353 - freqs.new = cur_freq; 1354 - 1355 - srcu_notifier_call_chain( 1356 - &cpufreq_transition_notifier_list, 1357 - CPUFREQ_RESUMECHANGE, &freqs); 1358 - adjust_jiffies(CPUFREQ_RESUMECHANGE, &freqs); 1359 - 1360 - cpu_policy->cur = cur_freq; 1361 - } 1362 - } 1363 - 1364 - out: 1365 schedule_work(&cpu_policy->update); 1366 fail: 1367 cpufreq_cpu_put(cpu_policy); 1368 - #endif /* __powerpc__ */ 1369 return ret; 1370 } 1371
··· 1250 { 1251 int ret = 0; 1252 1253 int cpu = sysdev->id; 1254 struct cpufreq_policy *cpu_policy; 1255 1256 dprintk("suspending cpu %u\n", cpu); 1257 1258 if (!cpu_online(cpu)) 1259 return 0; ··· 1282 1283 if (cpufreq_driver->suspend) { 1284 ret = cpufreq_driver->suspend(cpu_policy, pmsg); 1285 + if (ret) 1286 printk(KERN_ERR "cpufreq: suspend failed in ->suspend " 1287 "step on CPU %u\n", cpu_policy->cpu); 1288 } 1289 1290 out: 1291 cpufreq_cpu_put(cpu_policy); 1292 return ret; 1293 } 1294 ··· 1330 * cpufreq_resume - restore proper CPU frequency handling after resume 1331 * 1332 * 1.) resume CPUfreq hardware support (cpufreq_driver->resume()) 1333 + * 2.) schedule call cpufreq_update_policy() ASAP as interrupts are 1334 + * restored. It will verify that the current freq is in sync with 1335 + * what we believe it to be. This is a bit later than when it 1336 + * should be, but nonethteless it's better than calling 1337 + * cpufreq_driver->get() here which might re-enable interrupts... 1338 */ 1339 static int cpufreq_resume(struct sys_device *sysdev) 1340 { 1341 int ret = 0; 1342 1343 int cpu = sysdev->id; 1344 struct cpufreq_policy *cpu_policy; 1345 1346 dprintk("resuming cpu %u\n", cpu); 1347 1348 if (!cpu_online(cpu)) 1349 return 0; ··· 1373 } 1374 } 1375 1376 schedule_work(&cpu_policy->update); 1377 + 1378 fail: 1379 cpufreq_cpu_put(cpu_policy); 1380 return ret; 1381 } 1382