[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 1250 { 1251 1251 int ret = 0; 1252 1252 1253 - #ifdef __powerpc__ 1254 1253 int cpu = sysdev->id; 1255 - unsigned int cur_freq = 0; 1256 1254 struct cpufreq_policy *cpu_policy; 1257 1255 1258 1256 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 1257 1267 1258 if (!cpu_online(cpu)) 1268 1259 return 0; ··· 1273 1282 1274 1283 if (cpufreq_driver->suspend) { 1275 1284 ret = cpufreq_driver->suspend(cpu_policy, pmsg); 1276 - if (ret) { 1285 + if (ret) 1277 1286 printk(KERN_ERR "cpufreq: suspend failed in ->suspend " 1278 1287 "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 1288 } 1313 1289 1314 1290 out: 1315 1291 cpufreq_cpu_put(cpu_policy); 1316 - #endif /* __powerpc__ */ 1317 1292 return ret; 1318 1293 } 1319 1294 ··· 1287 1330 * cpufreq_resume - restore proper CPU frequency handling after resume 1288 1331 * 1289 1332 * 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. 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... 1293 1338 */ 1294 1339 static int cpufreq_resume(struct sys_device *sysdev) 1295 1340 { 1296 1341 int ret = 0; 1297 1342 1298 - #ifdef __powerpc__ 1299 1343 int cpu = sysdev->id; 1300 1344 struct cpufreq_policy *cpu_policy; 1301 1345 1302 1346 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 1347 1308 1348 if (!cpu_online(cpu)) 1309 1349 return 0; ··· 1327 1373 } 1328 1374 } 1329 1375 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 1376 schedule_work(&cpu_policy->update); 1377 + 1366 1378 fail: 1367 1379 cpufreq_cpu_put(cpu_policy); 1368 - #endif /* __powerpc__ */ 1369 1380 return ret; 1370 1381 } 1371 1382