freebsd-dev/sys/dev/syscons/apm/apm_saver.c
Warner Losh d708737568 APM was calling the suspend process from a timeout. This meant that
other timeouts could not happen while suspending, including timeouts
for things like msleep.  This caused the system to hang on suspend
when the cbb was enabled, since its suspend path powered down the
socket which used a timeout to wait for it to be done.

APM now creates a thread when it is enabled, and deletes the thread
when it is disabled.  This thread takes the place of the timeout by
doing its polling every ~.9s.  When the thread is disabled, it will
wakeup early, otherwise it times out and polls the varius things the
old timeout polled (APM events, suspend delays, etc).

This makes my Sony VAIO 505TS suspend/resume correctly when APM is
enabled (ACPI is black listed on my 505TS).

This will likely fix other problems with the suspend path where
drivers would sleep with msleep and/or do other timeouts.  Maybe
there's some special case code that would use DELAY while suspending
and msleep otherwise that can be revisited and removed.

This was also tested by glebius@, who pointed out that in the patch I
sent him, I'd forgotten apm_saver.c

MFC After: 3 weeks
2006-05-25 23:06:38 +00:00

94 lines
2.7 KiB
C

/*-
* Copyright (c) 1999 Nick Sayer (who stole shamelessly from blank_saver)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer,
* without modification, immediately at the beginning of the file.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/condvar.h>
#include <sys/kernel.h>
#include <sys/kthread.h>
#include <sys/lock.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/consio.h>
#include <sys/fbio.h>
#include <dev/fb/fbreg.h>
#include <dev/fb/splashreg.h>
#include <dev/syscons/syscons.h>
#include <sys/selinfo.h>
#include <machine/apm_bios.h>
#include <machine/pc/bios.h>
#include <machine/bus.h>
#include <i386/bios/apm.h>
extern int apm_display(int newstate);
extern struct apm_softc apm_softc;
static int blanked=0;
static int
apm_saver(video_adapter_t *adp, int blank)
{
if (!apm_softc.initialized || !apm_softc.active)
return 0;
if (blank==blanked)
return 0;
blanked=blank;
apm_display(!blanked);
return 0;
}
static int
apm_init(video_adapter_t *adp)
{
if (!apm_softc.initialized || !apm_softc.active)
printf("WARNING: apm_saver module requires apm enabled\n");
return 0;
}
static int
apm_term(video_adapter_t *adp)
{
return 0;
}
static scrn_saver_t apm_module = {
"apm_saver", apm_init, apm_term, apm_saver, NULL,
};
SAVER_MODULE(apm_saver, apm_module);
MODULE_DEPEND(apm_saver, apm, 1, 1, 1);