Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PM/gxfb: add hook to PM console layer that allows disabling of suspend 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>

authored by

Andres Salomon and committed by
Linus Torvalds
b6f448e9 46fb6f11

+48 -4
+2 -1
Documentation/fb/gxfb.txt
··· 45 45 mode_option - specify the video mode. Of the form 46 46 <x>x<y>[-<bpp>][@<refresh>] 47 47 vram - size of video ram (normally auto-detected) 48 - 48 + vt_switch - enable vt switching during suspend/resume. The vt 49 + switch is slow, but harmless. 49 50 50 51 -- 51 52 Andres Salomon <dilinger@debian.org>
+7
drivers/video/geode/gxfb_core.c
··· 29 29 #include <linux/delay.h> 30 30 #include <linux/fb.h> 31 31 #include <linux/console.h> 32 + #include <linux/suspend.h> 32 33 #include <linux/init.h> 33 34 #include <linux/pci.h> 34 35 #include <asm/geode.h> ··· 38 37 39 38 static char *mode_option; 40 39 static int vram; 40 + static int vt_switch; 41 41 42 42 /* Modes relevant to the GX (taken from modedb.c) */ 43 43 static const struct fb_videomode gx_modedb[] __initdata = { ··· 384 382 gxfb_check_var(&info->var, info); 385 383 gxfb_set_par(info); 386 384 385 + pm_set_vt_switch(vt_switch); 386 + 387 387 if (register_framebuffer(info) < 0) { 388 388 ret = -EINVAL; 389 389 goto err; ··· 505 501 506 502 module_param(vram, int, 0); 507 503 MODULE_PARM_DESC(vram, "video memory size"); 504 + 505 + module_param(vt_switch, int, 0); 506 + MODULE_PARM_DESC(vt_switch, "enable VT switch during suspend/resume"); 508 507 509 508 MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode GX"); 510 509 MODULE_LICENSE("GPL");
+13 -2
include/linux/suspend.h
··· 12 12 #include <asm/errno.h> 13 13 14 14 #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE) 15 + extern void pm_set_vt_switch(int); 15 16 extern int pm_prepare_console(void); 16 17 extern void pm_restore_console(void); 17 18 #else 18 - static inline int pm_prepare_console(void) { return 0; } 19 - static inline void pm_restore_console(void) {} 19 + static inline void pm_set_vt_switch(int do_switch) 20 + { 21 + } 22 + 23 + static inline int pm_prepare_console(void) 24 + { 25 + return 0; 26 + } 27 + 28 + static inline void pm_restore_console(void) 29 + { 30 + } 20 31 #endif 21 32 22 33 typedef int __bitwise suspend_state_t;
+26 -1
kernel/power/console.c
··· 7 7 #include <linux/vt_kern.h> 8 8 #include <linux/kbd_kern.h> 9 9 #include <linux/console.h> 10 + #include <linux/module.h> 10 11 #include "power.h" 11 12 12 13 #if defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE) 13 14 #define SUSPEND_CONSOLE (MAX_NR_CONSOLES-1) 14 15 15 16 static int orig_fgconsole, orig_kmsg; 17 + static int disable_vt_switch; 18 + 19 + /* 20 + * Normally during a suspend, we allocate a new console and switch to it. 21 + * When we resume, we switch back to the original console. This switch 22 + * can be slow, so on systems where the framebuffer can handle restoration 23 + * of video registers anyways, there's little point in doing the console 24 + * switch. This function allows you to disable it by passing it '0'. 25 + */ 26 + void pm_set_vt_switch(int do_switch) 27 + { 28 + acquire_console_sem(); 29 + disable_vt_switch = !do_switch; 30 + release_console_sem(); 31 + } 32 + EXPORT_SYMBOL(pm_set_vt_switch); 16 33 17 34 int pm_prepare_console(void) 18 35 { 19 36 acquire_console_sem(); 37 + 38 + if (disable_vt_switch) { 39 + release_console_sem(); 40 + return 0; 41 + } 20 42 21 43 orig_fgconsole = fg_console; 22 44 ··· 72 50 void pm_restore_console(void) 73 51 { 74 52 acquire_console_sem(); 53 + if (disable_vt_switch) { 54 + release_console_sem(); 55 + return; 56 + } 75 57 set_console(orig_fgconsole); 76 58 release_console_sem(); 77 59 kmsg_redirect = orig_kmsg; 78 - return; 79 60 } 80 61 #endif