Skip to content

Commit

Permalink
PM/gxfb: add hook to PM console layer that allows disabling of suspen…
Browse files Browse the repository at this point in the history
…d VT switch

Prior to suspend, we allocate and switch to a new VT; after suspend, we switch
back to the original VT.  This can be slow, and is completely unnecessary if
the framebuffer we're using can restore video properly.

This adds a hook that allows drivers to select whether or not to do this vt
switch, and changes the gxfb driver to call this hook.  It also adds a module
param to gxfb to allow controlling of the vt switch (defaulting to no switch).

(Note: I'm not convinced that console_sem is the best way to protect this, but
we should probably have some form of locking..)

[akpm@linux-foundation.org: build fix]
Signed-off-by: Andres Salomon <dilinger@debian.org>
Cc: Jordan Crouse <jordan.crouse@amd.com>
Cc: "Antonino A. Daplas" <adaplas@pol.net>
Cc: Pavel Machek <pavel@ucw.cz>
Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Andres Salomon authored and Linus Torvalds committed Apr 28, 2008
1 parent 46fb6f1 commit b6f448e
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 4 deletions.
3 changes: 2 additions & 1 deletion Documentation/fb/gxfb.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ Accepted options:
mode_option - specify the video mode. Of the form
<x>x<y>[-<bpp>][@<refresh>]
vram - size of video ram (normally auto-detected)

vt_switch - enable vt switching during suspend/resume. The vt
switch is slow, but harmless.

--
Andres Salomon <dilinger@debian.org>
7 changes: 7 additions & 0 deletions drivers/video/geode/gxfb_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/console.h>
#include <linux/suspend.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <asm/geode.h>
Expand All @@ -37,6 +38,7 @@

static char *mode_option;
static int vram;
static int vt_switch;

/* Modes relevant to the GX (taken from modedb.c) */
static const struct fb_videomode gx_modedb[] __initdata = {
Expand Down Expand Up @@ -382,6 +384,8 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i
gxfb_check_var(&info->var, info);
gxfb_set_par(info);

pm_set_vt_switch(vt_switch);

if (register_framebuffer(info) < 0) {
ret = -EINVAL;
goto err;
Expand Down Expand Up @@ -502,5 +506,8 @@ MODULE_PARM_DESC(mode_option, "video mode (<x>x<y>[-<bpp>][@<refr>])");
module_param(vram, int, 0);
MODULE_PARM_DESC(vram, "video memory size");

module_param(vt_switch, int, 0);
MODULE_PARM_DESC(vt_switch, "enable VT switch during suspend/resume");

MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode GX");
MODULE_LICENSE("GPL");
15 changes: 13 additions & 2 deletions include/linux/suspend.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,22 @@
#include <asm/errno.h>

#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE)
extern void pm_set_vt_switch(int);
extern int pm_prepare_console(void);
extern void pm_restore_console(void);
#else
static inline int pm_prepare_console(void) { return 0; }
static inline void pm_restore_console(void) {}
static inline void pm_set_vt_switch(int do_switch)
{
}

static inline int pm_prepare_console(void)
{
return 0;
}

static inline void pm_restore_console(void)
{
}
#endif

typedef int __bitwise suspend_state_t;
Expand Down
27 changes: 26 additions & 1 deletion kernel/power/console.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,39 @@
#include <linux/vt_kern.h>
#include <linux/kbd_kern.h>
#include <linux/console.h>
#include <linux/module.h>
#include "power.h"

#if defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE)
#define SUSPEND_CONSOLE (MAX_NR_CONSOLES-1)

static int orig_fgconsole, orig_kmsg;
static int disable_vt_switch;

/*
* Normally during a suspend, we allocate a new console and switch to it.
* When we resume, we switch back to the original console. This switch
* can be slow, so on systems where the framebuffer can handle restoration
* of video registers anyways, there's little point in doing the console
* switch. This function allows you to disable it by passing it '0'.
*/
void pm_set_vt_switch(int do_switch)
{
acquire_console_sem();
disable_vt_switch = !do_switch;
release_console_sem();
}
EXPORT_SYMBOL(pm_set_vt_switch);

int pm_prepare_console(void)
{
acquire_console_sem();

if (disable_vt_switch) {
release_console_sem();
return 0;
}

orig_fgconsole = fg_console;

if (vc_allocate(SUSPEND_CONSOLE)) {
Expand Down Expand Up @@ -50,9 +72,12 @@ int pm_prepare_console(void)
void pm_restore_console(void)
{
acquire_console_sem();
if (disable_vt_switch) {
release_console_sem();
return;
}
set_console(orig_fgconsole);
release_console_sem();
kmsg_redirect = orig_kmsg;
return;
}
#endif

0 comments on commit b6f448e

Please sign in to comment.