aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/common/bL_switcher.c78
1 files changed, 77 insertions, 1 deletions
diff --git a/arch/arm/common/bL_switcher.c b/arch/arm/common/bL_switcher.c
index 4caca71c906f..50e95d894e35 100644
--- a/arch/arm/common/bL_switcher.c
+++ b/arch/arm/common/bL_switcher.c
@@ -289,18 +289,94 @@ int bL_switch_request(unsigned int cpu, unsigned int new_cluster_id)
289} 289}
290EXPORT_SYMBOL_GPL(bL_switch_request); 290EXPORT_SYMBOL_GPL(bL_switch_request);
291 291
292/*
293 * Activation and configuration code.
294 */
295
296static cpumask_t bL_switcher_removed_logical_cpus;
297
298static void __init bL_switcher_restore_cpus(void)
299{
300 int i;
301
302 for_each_cpu(i, &bL_switcher_removed_logical_cpus)
303 cpu_up(i);
304}
305
306static int __init bL_switcher_halve_cpus(void)
307{
308 int cpu, cluster, i, ret;
309 cpumask_t cluster_mask[2], common_mask;
310
311 cpumask_clear(&bL_switcher_removed_logical_cpus);
312 cpumask_clear(&cluster_mask[0]);
313 cpumask_clear(&cluster_mask[1]);
314
315 for_each_online_cpu(i) {
316 cpu = cpu_logical_map(i) & 0xff;
317 cluster = (cpu_logical_map(i) >> 8) & 0xff;
318 if (cluster >= 2) {
319 pr_err("%s: only dual cluster systems are supported\n", __func__);
320 return -EINVAL;
321 }
322 cpumask_set_cpu(cpu, &cluster_mask[cluster]);
323 }
324
325 if (!cpumask_and(&common_mask, &cluster_mask[0], &cluster_mask[1])) {
326 pr_err("%s: no common set of CPUs\n", __func__);
327 return -EINVAL;
328 }
329
330 for_each_online_cpu(i) {
331 cpu = cpu_logical_map(i) & 0xff;
332 cluster = (cpu_logical_map(i) >> 8) & 0xff;
333
334 if (cpumask_test_cpu(cpu, &common_mask)) {
335 /*
336 * We keep only those logical CPUs which number
337 * is equal to their physical CPU number. This is
338 * not perfect but good enough for now.
339 */
340 if (cpu == i)
341 continue;
342 }
343
344 ret = cpu_down(i);
345 if (ret) {
346 bL_switcher_restore_cpus();
347 return ret;
348 }
349 cpumask_set_cpu(i, &bL_switcher_removed_logical_cpus);
350 }
351
352 return 0;
353}
354
292static int __init bL_switcher_init(void) 355static int __init bL_switcher_init(void)
293{ 356{
294 int cpu; 357 int cpu, ret;
295 358
296 pr_info("big.LITTLE switcher initializing\n"); 359 pr_info("big.LITTLE switcher initializing\n");
297 360
361 if (MAX_NR_CLUSTERS != 2) {
362 pr_err("%s: only dual cluster systems are supported\n", __func__);
363 return -EINVAL;
364 }
365
366 cpu_hotplug_driver_lock();
367 ret = bL_switcher_halve_cpus();
368 if (ret) {
369 cpu_hotplug_driver_unlock();
370 return ret;
371 }
372
298 for_each_online_cpu(cpu) { 373 for_each_online_cpu(cpu) {
299 struct bL_thread *t = &bL_threads[cpu]; 374 struct bL_thread *t = &bL_threads[cpu];
300 init_waitqueue_head(&t->wq); 375 init_waitqueue_head(&t->wq);
301 t->wanted_cluster = -1; 376 t->wanted_cluster = -1;
302 t->task = bL_switcher_thread_create(cpu, t); 377 t->task = bL_switcher_thread_create(cpu, t);
303 } 378 }
379 cpu_hotplug_driver_unlock();
304 380
305 pr_info("big.LITTLE switcher initialized\n"); 381 pr_info("big.LITTLE switcher initialized\n");
306 return 0; 382 return 0;