diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 1bbb45b..7580942 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -2851,8 +2851,24 @@ static int con_is_graphics(const struct consw *csw, int first, int last) return retval; } -static int unbind_con_driver(const struct consw *csw, int first, int last, - int deflt) +/** + * unbind_con_driver - unbind a console driver + * @csw: pointer to console driver to unregister + * @first: first in range of consoles that @csw should be unbound from + * @last: last in range of consoles that @csw should be unbound from + * @deflt: should next bound console driver be default after @csw is unbound? + * + * To unbind a driver from all possible consoles, pass 0 as @first and + * %MAX_NR_CONSOLES as @last. + * + * @deflt controls whether the console that ends up replacing @csw should be + * the default console. + * + * RETURNS: + * -ENODEV if @csw isn't a registered console driver or can't be unregistered + * or 0 on success. + */ +int unbind_con_driver(const struct consw *csw, int first, int last, int deflt) { struct module *owner = csw->owner; const struct consw *defcsw = NULL; @@ -2937,6 +2953,7 @@ err: return retval; } +EXPORT_SYMBOL(unbind_con_driver); static int vt_bind(struct con_driver *con) { diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 0429fd2..7e8c98b 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -563,8 +563,10 @@ static int fbcon_takeover(int show_logo) for (i = first_fb_vc; i <= last_fb_vc; i++) con2fb_map[i] = info_idx; + printk(KERN_ERR "calling take_over_console, return value: "); err = take_over_console(&fb_con, first_fb_vc, last_fb_vc, fbcon_is_default); + printk(KERN_ERR "%d\n", err); if (err) { for (i = first_fb_vc; i <= last_fb_vc; i++) { @@ -2896,6 +2898,21 @@ static int fbcon_mode_deleted(struct fb_info *info, return found; } +static int fbcon_fb_unbind(int idx) +{ + int i; + + for (i = 0; i < MAX_NR_CONSOLES; i++) { + /* Assure we do not unbind other drivers */ + if (idx == con2fb_map[i]) + /* can be optimize to minimize multiple calls to + unbind_con_driver() */ + unbind_con_driver(&fb_con, i, i, 0); + } + + return 0; +} + static int fbcon_fb_unregistered(int idx) { int i; @@ -2933,6 +2950,7 @@ static int fbcon_fb_registered(int idx) { int ret = 0, i; + printk(KERN_ERR "fbcon registration called\n"); if (info_idx == -1) { for (i = first_fb_vc; i <= last_fb_vc; i++) { if (con2fb_map_boot[i] == idx) { @@ -2941,8 +2959,10 @@ static int fbcon_fb_registered(int idx) } } - if (info_idx != -1) + if (info_idx != -1) { + printk(KERN_ERR "fb taking over console\n"); ret = fbcon_takeover(1); + } } else { for (i = first_fb_vc; i <= last_fb_vc; i++) { if (con2fb_map_boot[i] == idx && @@ -3036,6 +3056,9 @@ static int fbcon_event_notify(struct notifier_block *self, mode = event->data; ret = fbcon_mode_deleted(info, mode); break; + case FB_EVENT_FB_UNBIND: + ret = fbcon_fb_unbind(info->node); + break; case FB_EVENT_FB_REGISTERED: ret = fbcon_fb_registered(info->node); break; diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 2822526..4c9f071 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1349,6 +1349,8 @@ unregister_framebuffer(struct fb_info *fb_info) if (!registered_fb[i]) return -EINVAL; + event.info = fb_info; + fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event); if (fb_info->pixmap.addr && (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) kfree(fb_info->pixmap.addr); diff --git a/include/linux/console.h b/include/linux/console.h index de25ee3..53d44e5 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -64,6 +64,7 @@ extern const struct consw vga_con; /* VGA text console */ extern const struct consw newport_con; /* SGI Newport console */ extern const struct consw prom_con; /* SPARC PROM console */ +int unbind_con_driver(const struct consw *csw, int first, int last, int deflt); int con_is_bound(const struct consw *csw); int register_con_driver(const struct consw *csw, int first, int last); int unregister_con_driver(const struct consw *csw); diff --git a/include/linux/fb.h b/include/linux/fb.h index be913ec..6aecb6e 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -525,6 +525,8 @@ struct fb_cursor_user { #define FB_EVENT_MODE_CHANGE_ALL 0x0B /* A software display blank change occured */ #define FB_EVENT_CONBLANK 0x0C +/* Unbind from the console if possible */ +#define FB_EVENT_FB_UNBIND 0x0E struct fb_event { struct fb_info *info;