From cfafca8067c6defbaeb28cb898b7b3f8abdfe20d Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 17 Jul 2007 04:05:33 -0700 Subject: fbdev: fbcon: console unregistration from unregister_framebuffer This allows for proper console unregistration via the VT layer, and updates the FB layer to use it. This makes debugging new console drivers much easier, since you can properly clean them up before unloading. [adaplas] unregister_framebuffer() is typically called as part of the driver's module_exit(). Doing so otherwise will freeze the machine as the VT layer is holding reference counts on fbcon, and fbcon on the driver. With this change, it allows unregister_framebuffer() to be called safely anywhere as needed. Additions from the original: If multiple drivers are used by fbcon, and if one of them unregisters, a driver will take over the consoles vacated by the outgoing one (via set_con2fb_map). Once only the outgoing driver remains, then fbcon will unbind from the VT layer (if CONFIG_HW_CONSOLE_UNBINDING is set to y). It is important that these drivers implement fb_open() and fb_release() just to ensure that no other process is using the driver. Likewise, these drivers _must_ check the return value of unregister_framebuffer(). [akpm@linux-foundation.org: make fbcon_unbind() stub inline] Signed-off-by: Jesse Barnes Signed-off-by: Antonino Daplas Cc: Geert Uytterhoeven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/fbmem.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'drivers/video/fbmem.c') diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 8d6dbe8b8dd..7f3a0cca0fd 100644 --- a/drivers/video/fbmem.c +++ b/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; } /** -- cgit v1.2.3