aboutsummaryrefslogblamecommitdiffstats
path: root/kernel/power/smp.c
blob: 911fc62b822546d0e1b05dddb0c2d8bdc771c056 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15













                                                                      
                      

                         
                                           

                               
                       
 











                                                                     
         
                                            
                                           


                              
                       
 











                                                                   
 
/*
 * drivers/power/smp.c - Functions for stopping other CPUs.
 *
 * Copyright 2004 Pavel Machek <pavel@suse.cz>
 * Copyright (C) 2002-2003 Nigel Cunningham <ncunningham@clear.net.nz>
 *
 * This file is released under the GPLv2.
 */

#undef DEBUG

#include <linux/smp_lock.h>
#include <linux/interrupt.h>
#include <linux/suspend.h>
#include <linux/module.h>
#include <linux/cpu.h>
#include <asm/atomic.h>
#include <asm/tlbflush.h>

/* This is protected by pm_sem semaphore */
static cpumask_t frozen_cpus;

void disable_nonboot_cpus(void)
{
	int cpu, error;

	error = 0;
	cpus_clear(frozen_cpus);
	printk("Freezing cpus ...\n");
	for_each_online_cpu(cpu) {
		if (cpu == 0)
			continue;
		error = cpu_down(cpu);
		if (!error) {
			cpu_set(cpu, frozen_cpus);
			printk("CPU%d is down\n", cpu);
			continue;
		}
		printk("Error taking cpu %d down: %d\n", cpu, error);
	}
	BUG_ON(raw_smp_processor_id() != 0);
	if (error)
		panic("cpus not sleeping");
}

void enable_nonboot_cpus(void)
{
	int cpu, error;

	printk("Thawing cpus ...\n");
	for_each_cpu_mask(cpu, frozen_cpus) {
		error = smp_prepare_cpu(cpu);
		if (!error)
			error = cpu_up(cpu);
		if (!error) {
			printk("CPU%d is up\n", cpu);
			continue;
		}
		printk("Error taking cpu %d up: %d\n", cpu, error);
		panic("Not enough cpus");
	}
	cpus_clear(frozen_cpus);
}