aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/video/console/fbcon.c42
-rw-r--r--drivers/video/fbmem.c26
-rw-r--r--include/linux/fb.h2
3 files changed, 66 insertions, 4 deletions
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 9b66331020dd..decfdc8eb9cc 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -3003,6 +3003,45 @@ static int fbcon_mode_deleted(struct fb_info *info,
3003 return found; 3003 return found;
3004} 3004}
3005 3005
3006#ifdef CONFIG_VT_HW_CONSOLE_BINDING
3007static int fbcon_unbind(void)
3008{
3009 int ret;
3010
3011 ret = unbind_con_driver(&fb_con, first_fb_vc, last_fb_vc,
3012 fbcon_is_default);
3013 return ret;
3014}
3015#else
3016static inline int fbcon_unbind(void)
3017{
3018 return -EINVAL;
3019}
3020#endif /* CONFIG_VT_HW_CONSOLE_BINDING */
3021
3022static int fbcon_fb_unbind(int idx)
3023{
3024 int i, new_idx = -1, ret = 0;
3025
3026 for (i = first_fb_vc; i <= last_fb_vc; i++) {
3027 if (con2fb_map[i] != idx &&
3028 con2fb_map[i] != -1) {
3029 new_idx = i;
3030 break;
3031 }
3032 }
3033
3034 if (new_idx != -1) {
3035 for (i = first_fb_vc; i <= last_fb_vc; i++) {
3036 if (con2fb_map[i] == idx)
3037 set_con2fb_map(i, new_idx, 0);
3038 }
3039 } else
3040 ret = fbcon_unbind();
3041
3042 return ret;
3043}
3044
3006static int fbcon_fb_unregistered(struct fb_info *info) 3045static int fbcon_fb_unregistered(struct fb_info *info)
3007{ 3046{
3008 int i, idx = info->node; 3047 int i, idx = info->node;
@@ -3210,6 +3249,9 @@ static int fbcon_event_notify(struct notifier_block *self,
3210 mode = event->data; 3249 mode = event->data;
3211 ret = fbcon_mode_deleted(info, mode); 3250 ret = fbcon_mode_deleted(info, mode);
3212 break; 3251 break;
3252 case FB_EVENT_FB_UNBIND:
3253 ret = fbcon_fb_unbind(info->node);
3254 break;
3213 case FB_EVENT_FB_REGISTERED: 3255 case FB_EVENT_FB_REGISTERED:
3214 ret = fbcon_fb_registered(info); 3256 ret = fbcon_fb_registered(info);
3215 break; 3257 break;
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 8d6dbe8b8dd1..7f3a0cca0fd4 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1334,17 +1334,34 @@ register_framebuffer(struct fb_info *fb_info)
1334 * 1334 *
1335 * Returns negative errno on error, or zero for success. 1335 * Returns negative errno on error, or zero for success.
1336 * 1336 *
1337 * This function will also notify the framebuffer console
1338 * to release the driver.
1339 *
1340 * This is meant to be called within a driver's module_exit()
1341 * function. If this is called outside module_exit(), ensure
1342 * that the driver implements fb_open() and fb_release() to
1343 * check that no processes are using the device.
1337 */ 1344 */
1338 1345
1339int 1346int
1340unregister_framebuffer(struct fb_info *fb_info) 1347unregister_framebuffer(struct fb_info *fb_info)
1341{ 1348{
1342 struct fb_event event; 1349 struct fb_event event;
1343 int i; 1350 int i, ret = 0;
1344 1351
1345 i = fb_info->node; 1352 i = fb_info->node;
1346 if (!registered_fb[i]) 1353 if (!registered_fb[i]) {
1347 return -EINVAL; 1354 ret = -EINVAL;
1355 goto done;
1356 }
1357
1358 event.info = fb_info;
1359 ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event);
1360
1361 if (ret) {
1362 ret = -EINVAL;
1363 goto done;
1364 }
1348 1365
1349 if (fb_info->pixmap.addr && 1366 if (fb_info->pixmap.addr &&
1350 (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) 1367 (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
@@ -1356,7 +1373,8 @@ unregister_framebuffer(struct fb_info *fb_info)
1356 device_destroy(fb_class, MKDEV(FB_MAJOR, i)); 1373 device_destroy(fb_class, MKDEV(FB_MAJOR, i));
1357 event.info = fb_info; 1374 event.info = fb_info;
1358 fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); 1375 fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
1359 return 0; 1376done:
1377 return ret;
1360} 1378}
1361 1379
1362/** 1380/**
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 66226824ab68..8628423c6dd3 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -529,6 +529,8 @@ struct fb_cursor_user {
529#define FB_EVENT_CONBLANK 0x0C 529#define FB_EVENT_CONBLANK 0x0C
530/* Get drawing requirements */ 530/* Get drawing requirements */
531#define FB_EVENT_GET_REQ 0x0D 531#define FB_EVENT_GET_REQ 0x0D
532/* Unbind from the console if possible */
533#define FB_EVENT_FB_UNBIND 0x0E
532 534
533struct fb_event { 535struct fb_event {
534 struct fb_info *info; 536 struct fb_info *info;