2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* 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>
|
2005-06-26 05:55:06 +08:00
|
|
|
#include <linux/cpu.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <asm/atomic.h>
|
|
|
|
#include <asm/tlbflush.h>
|
|
|
|
|
2005-06-26 05:55:06 +08:00
|
|
|
/* This is protected by pm_sem semaphore */
|
|
|
|
static cpumask_t frozen_cpus;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
void disable_nonboot_cpus(void)
|
|
|
|
{
|
2005-06-26 05:55:06 +08:00
|
|
|
int cpu, error;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2005-06-26 05:55:06 +08:00
|
|
|
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);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2005-06-26 05:55:06 +08:00
|
|
|
BUG_ON(smp_processor_id() != 0);
|
|
|
|
if (error)
|
|
|
|
panic("cpus not sleeping");
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void enable_nonboot_cpus(void)
|
|
|
|
{
|
2005-06-26 05:55:06 +08:00
|
|
|
int cpu, error;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2005-06-26 05:55:06 +08:00
|
|
|
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);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|