From 32e7402f038e85d6f12a367295b49b70f61be99c Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 17 Jul 2007 04:05:33 -0700 Subject: [PATCH] --- yaml --- r: 60895 b: refs/heads/master c: cfafca8067c6defbaeb28cb898b7b3f8abdfe20d h: refs/heads/master i: 60893: 15172f930d1ba0c73bf51c373f55153615254408 60891: 4aae8efddba7fda4d67abf2f4a592e22e9c6e486 60887: d5ef974ae0b7cb2cdee0ff17b51da720ee17fd6f 60879: 72a93c8aa6aa913a84cf4cf49650fb5606037cd8 60863: d562a4ff7b617f698eb143f75da844d32bc65e74 v: v3 --- [refs] | 2 +- trunk/drivers/video/console/fbcon.c | 42 +++++++++++++++++++++++++++++ trunk/drivers/video/fbmem.c | 26 +++++++++++++++--- trunk/include/linux/fb.h | 2 ++ 4 files changed, 67 insertions(+), 5 deletions(-) diff --git a/[refs] b/[refs] index 473d6af81ff1..ad4cd0cdcd22 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: afd1db1632c3f8f95cbc2786bfa122cead79db58 +refs/heads/master: cfafca8067c6defbaeb28cb898b7b3f8abdfe20d diff --git a/trunk/drivers/video/console/fbcon.c b/trunk/drivers/video/console/fbcon.c index 9b66331020dd..decfdc8eb9cc 100644 --- a/trunk/drivers/video/console/fbcon.c +++ b/trunk/drivers/video/console/fbcon.c @@ -3003,6 +3003,45 @@ static int fbcon_mode_deleted(struct fb_info *info, return found; } +#ifdef CONFIG_VT_HW_CONSOLE_BINDING +static int fbcon_unbind(void) +{ + int ret; + + ret = unbind_con_driver(&fb_con, first_fb_vc, last_fb_vc, + fbcon_is_default); + return ret; +} +#else +static inline int fbcon_unbind(void) +{ + return -EINVAL; +} +#endif /* CONFIG_VT_HW_CONSOLE_BINDING */ + +static int fbcon_fb_unbind(int idx) +{ + int i, new_idx = -1, ret = 0; + + for (i = first_fb_vc; i <= last_fb_vc; i++) { + if (con2fb_map[i] != idx && + con2fb_map[i] != -1) { + new_idx = i; + break; + } + } + + if (new_idx != -1) { + for (i = first_fb_vc; i <= last_fb_vc; i++) { + if (con2fb_map[i] == idx) + set_con2fb_map(i, new_idx, 0); + } + } else + ret = fbcon_unbind(); + + return ret; +} + static int fbcon_fb_unregistered(struct fb_info *info) { int i, idx = info->node; @@ -3210,6 +3249,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); break; diff --git a/trunk/drivers/video/fbmem.c b/trunk/drivers/video/fbmem.c index 8d6dbe8b8dd1..7f3a0cca0fd4 100644 --- a/trunk/drivers/video/fbmem.c +++ b/trunk/drivers/video/fbmem.c @@ -1334,17 +1334,34 @@ register_framebuffer(struct fb_info *fb_info) * * Returns negative errno on error, or zero for success. * + * This function will also notify the framebuffer console + * to release the driver. + * + * This is meant to be called within a driver's module_exit() + * function. If this is called outside module_exit(), ensure + * that the driver implements fb_open() and fb_release() to + * check that no processes are using the device. */ int unregister_framebuffer(struct fb_info *fb_info) { struct fb_event event; - int i; + int i, ret = 0; i = fb_info->node; - if (!registered_fb[i]) - return -EINVAL; + if (!registered_fb[i]) { + ret = -EINVAL; + goto done; + } + + event.info = fb_info; + ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event); + + if (ret) { + ret = -EINVAL; + goto done; + } if (fb_info->pixmap.addr && (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) @@ -1356,7 +1373,8 @@ unregister_framebuffer(struct fb_info *fb_info) device_destroy(fb_class, MKDEV(FB_MAJOR, i)); event.info = fb_info; fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); - return 0; +done: + return ret; } /** diff --git a/trunk/include/linux/fb.h b/trunk/include/linux/fb.h index 66226824ab68..8628423c6dd3 100644 --- a/trunk/include/linux/fb.h +++ b/trunk/include/linux/fb.h @@ -529,6 +529,8 @@ struct fb_cursor_user { #define FB_EVENT_CONBLANK 0x0C /* Get drawing requirements */ #define FB_EVENT_GET_REQ 0x0D +/* Unbind from the console if possible */ +#define FB_EVENT_FB_UNBIND 0x0E struct fb_event { struct fb_info *info;