Kick off the suspend sequence from the keyboard in a SWI rather than

in the hardware interrupt context (even if it is likely just an
ithread).  We don't document that suspend/resume routines are run from
such a context and some of the things that happen in those routines
aren't interrupt safe.  Since there's no real need to run from that
context, this restores assumptions that suspend routines have made.

This fixes Thierry Herbelot's 'Trying to sleep while sleeping is
prohibited' problem.
This commit is contained in:
Warner Losh 2005-11-09 07:32:01 +00:00
parent 2002eaadb7
commit 161604d863
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=152222

View File

@ -32,10 +32,20 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/power.h>
#include <sys/taskqueue.h>
static u_int power_pm_type = POWER_PM_TYPE_NONE;
static power_pm_fn_t power_pm_fn = NULL;
static void *power_pm_arg = NULL;
static struct task power_pm_task;
static void
power_pm_deferred_fn(void *arg, int pending)
{
int state = (int)arg;
power_pm_fn(POWER_CMD_SUSPEND, power_pm_arg, state);
}
int
power_pm_register(u_int pm_type, power_pm_fn_t pm_fn, void *pm_arg)
@ -48,6 +58,7 @@ power_pm_register(u_int pm_type, power_pm_fn_t pm_fn, void *pm_arg)
power_pm_fn = pm_fn;
power_pm_arg = pm_arg;
error = 0;
TASK_INIT(&power_pm_task, 0, power_pm_deferred_fn, NULL);
} else {
error = ENXIO;
}
@ -72,8 +83,8 @@ power_pm_suspend(int state)
state != POWER_SLEEP_STATE_SUSPEND &&
state != POWER_SLEEP_STATE_HIBERNATE)
return;
power_pm_fn(POWER_CMD_SUSPEND, power_pm_arg, state);
power_pm_task.ta_context = (void *)state;
taskqueue_enqueue(taskqueue_swi, &power_pm_task);
}
/*