fbcon: Call con2fb_map functions directly
[sfrench/cifs-2.6.git] / drivers / video / fbdev / core / fbcon.c
index 786f9aab55df6bdd4bb5504010b453c9991bd076..31d6a4e54436d37bc229f6184b1cb422cad567b3 100644 (file)
@@ -76,6 +76,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/crc32.h> /* For counting font checksums */
+#include <linux/uaccess.h>
 #include <asm/fb.h>
 #include <asm/irq.h>
 
@@ -93,7 +94,7 @@ enum {
        FBCON_LOGO_DONTSHOW     = -3    /* do not show the logo */
 };
 
-static struct display fb_display[MAX_NR_CONSOLES];
+static struct fbcon_display fb_display[MAX_NR_CONSOLES];
 
 static signed char con2fb_map[MAX_NR_CONSOLES];
 static signed char con2fb_map_boot[MAX_NR_CONSOLES];
@@ -112,7 +113,6 @@ static int softback_lines;
 static int first_fb_vc;
 static int last_fb_vc = MAX_NR_CONSOLES - 1;
 static int fbcon_is_default = 1; 
-static int fbcon_has_exited;
 static int primary_device = -1;
 static int fbcon_has_console_bind;
 
@@ -185,11 +185,11 @@ static __inline__ void ywrap_up(struct vc_data *vc, int count);
 static __inline__ void ywrap_down(struct vc_data *vc, int count);
 static __inline__ void ypan_up(struct vc_data *vc, int count);
 static __inline__ void ypan_down(struct vc_data *vc, int count);
-static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int sx,
+static void fbcon_bmove_rec(struct vc_data *vc, struct fbcon_display *p, int sy, int sx,
                            int dy, int dx, int height, int width, u_int y_break);
 static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
                           int unit);
-static void fbcon_redraw_move(struct vc_data *vc, struct display *p,
+static void fbcon_redraw_move(struct vc_data *vc, struct fbcon_display *p,
                              int line, int count, int dy);
 static void fbcon_modechanged(struct fb_info *info);
 static void fbcon_set_all_vcs(struct fb_info *info);
@@ -220,7 +220,7 @@ static void fbcon_rotate(struct fb_info *info, u32 rotate)
        fb_info = registered_fb[con2fb_map[ops->currcon]];
 
        if (info == fb_info) {
-               struct display *p = &fb_display[ops->currcon];
+               struct fbcon_display *p = &fb_display[ops->currcon];
 
                if (rotate < 4)
                        p->con_rotate = rotate;
@@ -235,7 +235,7 @@ static void fbcon_rotate_all(struct fb_info *info, u32 rotate)
 {
        struct fbcon_ops *ops = info->fbcon_par;
        struct vc_data *vc;
-       struct display *p;
+       struct fbcon_display *p;
        int i;
 
        if (!ops || ops->currcon < 0 || rotate > 3)
@@ -900,7 +900,7 @@ static int set_con2fb_map(int unit, int newidx, int user)
  *  Low Level Operations
  */
 /* NOTE: fbcon cannot be __init: it may be called from do_take_over_console later */
-static int var_to_display(struct display *disp,
+static int var_to_display(struct fbcon_display *disp,
                          struct fb_var_screeninfo *var,
                          struct fb_info *info)
 {
@@ -925,7 +925,7 @@ static int var_to_display(struct display *disp,
 }
 
 static void display_to_var(struct fb_var_screeninfo *var,
-                          struct display *disp)
+                          struct fbcon_display *disp)
 {
        fb_videomode_to_var(var, disp->mode);
        var->xres_virtual = disp->xres_virtual;
@@ -946,7 +946,7 @@ static void display_to_var(struct fb_var_screeninfo *var,
 static const char *fbcon_startup(void)
 {
        const char *display_desc = "frame buffer device";
-       struct display *p = &fb_display[fg_console];
+       struct fbcon_display *p = &fb_display[fg_console];
        struct vc_data *vc = vc_cons[fg_console].d;
        const struct font_desc *font = NULL;
        struct module *owner;
@@ -1050,23 +1050,26 @@ static const char *fbcon_startup(void)
                info->var.bits_per_pixel);
 
        fbcon_add_cursor_timer(info);
-       fbcon_has_exited = 0;
        return display_desc;
 }
 
 static void fbcon_init(struct vc_data *vc, int init)
 {
-       struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
+       struct fb_info *info;
        struct fbcon_ops *ops;
        struct vc_data **default_mode = vc->vc_display_fg;
        struct vc_data *svc = *default_mode;
-       struct display *t, *p = &fb_display[vc->vc_num];
+       struct fbcon_display *t, *p = &fb_display[vc->vc_num];
        int logo = 1, new_rows, new_cols, rows, cols, charcnt = 256;
        int cap, ret;
 
-       if (info_idx == -1 || info == NULL)
+       if (WARN_ON(info_idx == -1))
            return;
 
+       if (con2fb_map[vc->vc_num] == -1)
+               con2fb_map[vc->vc_num] = info_idx;
+
+       info = registered_fb[con2fb_map[vc->vc_num]];
        cap = info->flags;
 
        if (logo_shown < 0 && console_loglevel <= CONSOLE_LOGLEVEL_QUIET)
@@ -1203,7 +1206,7 @@ static void fbcon_init(struct vc_data *vc, int init)
        ops->p = &fb_display[fg_console];
 }
 
-static void fbcon_free_font(struct display *p, bool freefont)
+static void fbcon_free_font(struct fbcon_display *p, bool freefont)
 {
        if (freefont && p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0))
                kfree(p->fontdata - FONT_EXTRA_WORDS * sizeof(int));
@@ -1215,7 +1218,7 @@ static void set_vc_hi_font(struct vc_data *vc, bool set);
 
 static void fbcon_deinit(struct vc_data *vc)
 {
-       struct display *p = &fb_display[vc->vc_num];
+       struct fbcon_display *p = &fb_display[vc->vc_num];
        struct fb_info *info;
        struct fbcon_ops *ops;
        int idx;
@@ -1248,7 +1251,7 @@ finished:
        if (free_font)
                vc->vc_font.data = NULL;
 
-       if (vc->vc_hi_font_mask)
+       if (vc->vc_hi_font_mask && vc->vc_screenbuf)
                set_vc_hi_font(vc, false);
 
        if (!con_is_bound(&fb_con))
@@ -1288,7 +1291,7 @@ static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height,
        struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
        struct fbcon_ops *ops = info->fbcon_par;
 
-       struct display *p = &fb_display[vc->vc_num];
+       struct fbcon_display *p = &fb_display[vc->vc_num];
        u_int y_break;
 
        if (fbcon_is_inactive(vc, info))
@@ -1324,7 +1327,7 @@ static void fbcon_putcs(struct vc_data *vc, const unsigned short *s,
                        int count, int ypos, int xpos)
 {
        struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
-       struct display *p = &fb_display[vc->vc_num];
+       struct fbcon_display *p = &fb_display[vc->vc_num];
        struct fbcon_ops *ops = info->fbcon_par;
 
        if (!fbcon_is_inactive(vc, info))
@@ -1388,7 +1391,7 @@ static int scrollback_current = 0;
 static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
                           int unit)
 {
-       struct display *p, *t;
+       struct fbcon_display *p, *t;
        struct vc_data **default_mode, *vc;
        struct vc_data *svc;
        struct fbcon_ops *ops = info->fbcon_par;
@@ -1457,7 +1460,7 @@ static __inline__ void ywrap_up(struct vc_data *vc, int count)
 {
        struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
        struct fbcon_ops *ops = info->fbcon_par;
-       struct display *p = &fb_display[vc->vc_num];
+       struct fbcon_display *p = &fb_display[vc->vc_num];
        
        p->yscroll += count;
        if (p->yscroll >= p->vrows)     /* Deal with wrap */
@@ -1476,7 +1479,7 @@ static __inline__ void ywrap_down(struct vc_data *vc, int count)
 {
        struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
        struct fbcon_ops *ops = info->fbcon_par;
-       struct display *p = &fb_display[vc->vc_num];
+       struct fbcon_display *p = &fb_display[vc->vc_num];
        
        p->yscroll -= count;
        if (p->yscroll < 0)     /* Deal with wrap */
@@ -1494,7 +1497,7 @@ static __inline__ void ywrap_down(struct vc_data *vc, int count)
 static __inline__ void ypan_up(struct vc_data *vc, int count)
 {
        struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
-       struct display *p = &fb_display[vc->vc_num];
+       struct fbcon_display *p = &fb_display[vc->vc_num];
        struct fbcon_ops *ops = info->fbcon_par;
 
        p->yscroll += count;
@@ -1519,7 +1522,7 @@ static __inline__ void ypan_up_redraw(struct vc_data *vc, int t, int count)
 {
        struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
        struct fbcon_ops *ops = info->fbcon_par;
-       struct display *p = &fb_display[vc->vc_num];
+       struct fbcon_display *p = &fb_display[vc->vc_num];
 
        p->yscroll += count;
 
@@ -1542,7 +1545,7 @@ static __inline__ void ypan_up_redraw(struct vc_data *vc, int t, int count)
 static __inline__ void ypan_down(struct vc_data *vc, int count)
 {
        struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
-       struct display *p = &fb_display[vc->vc_num];
+       struct fbcon_display *p = &fb_display[vc->vc_num];
        struct fbcon_ops *ops = info->fbcon_par;
        
        p->yscroll -= count;
@@ -1567,7 +1570,7 @@ static __inline__ void ypan_down_redraw(struct vc_data *vc, int t, int count)
 {
        struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
        struct fbcon_ops *ops = info->fbcon_par;
-       struct display *p = &fb_display[vc->vc_num];
+       struct fbcon_display *p = &fb_display[vc->vc_num];
 
        p->yscroll -= count;
 
@@ -1587,7 +1590,7 @@ static __inline__ void ypan_down_redraw(struct vc_data *vc, int t, int count)
        scrollback_current = 0;
 }
 
-static void fbcon_redraw_softback(struct vc_data *vc, struct display *p,
+static void fbcon_redraw_softback(struct vc_data *vc, struct fbcon_display *p,
                                  long delta)
 {
        int count = vc->vc_rows;
@@ -1680,7 +1683,7 @@ static void fbcon_redraw_softback(struct vc_data *vc, struct display *p,
        }
 }
 
-static void fbcon_redraw_move(struct vc_data *vc, struct display *p,
+static void fbcon_redraw_move(struct vc_data *vc, struct fbcon_display *p,
                              int line, int count, int dy)
 {
        unsigned short *s = (unsigned short *)
@@ -1715,7 +1718,7 @@ static void fbcon_redraw_move(struct vc_data *vc, struct display *p,
 }
 
 static void fbcon_redraw_blit(struct vc_data *vc, struct fb_info *info,
-                       struct display *p, int line, int count, int ycount)
+                       struct fbcon_display *p, int line, int count, int ycount)
 {
        int offset = ycount * vc->vc_cols;
        unsigned short *d = (unsigned short *)
@@ -1764,7 +1767,7 @@ static void fbcon_redraw_blit(struct vc_data *vc, struct fb_info *info,
        }
 }
 
-static void fbcon_redraw(struct vc_data *vc, struct display *p,
+static void fbcon_redraw(struct vc_data *vc, struct fbcon_display *p,
                         int line, int count, int offset)
 {
        unsigned short *d = (unsigned short *)
@@ -1848,7 +1851,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
                enum con_scroll dir, unsigned int count)
 {
        struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
-       struct display *p = &fb_display[vc->vc_num];
+       struct fbcon_display *p = &fb_display[vc->vc_num];
        int scroll_partial = info->flags & FBINFO_PARTIAL_PAN_OK;
 
        if (fbcon_is_inactive(vc, info))
@@ -2052,7 +2055,7 @@ static void fbcon_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx,
                        int height, int width)
 {
        struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
-       struct display *p = &fb_display[vc->vc_num];
+       struct fbcon_display *p = &fb_display[vc->vc_num];
        
        if (fbcon_is_inactive(vc, info))
                return;
@@ -2071,7 +2074,7 @@ static void fbcon_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx,
                        p->vrows - p->yscroll);
 }
 
-static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int sx, 
+static void fbcon_bmove_rec(struct vc_data *vc, struct fbcon_display *p, int sy, int sx,
                            int dy, int dx, int height, int width, u_int y_break)
 {
        struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
@@ -2113,7 +2116,7 @@ static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int s
                   height, width);
 }
 
-static void updatescrollmode(struct display *p,
+static void updatescrollmode(struct fbcon_display *p,
                                        struct fb_info *info,
                                        struct vc_data *vc)
 {
@@ -2165,7 +2168,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
 {
        struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
        struct fbcon_ops *ops = info->fbcon_par;
-       struct display *p = &fb_display[vc->vc_num];
+       struct fbcon_display *p = &fb_display[vc->vc_num];
        struct fb_var_screeninfo var = info->var;
        int x_diff, y_diff, virt_w, virt_h, virt_fw, virt_fh;
 
@@ -2210,7 +2213,7 @@ static int fbcon_switch(struct vc_data *vc)
 {
        struct fb_info *info, *old_info = NULL;
        struct fbcon_ops *ops;
-       struct display *p = &fb_display[vc->vc_num];
+       struct fbcon_display *p = &fb_display[vc->vc_num];
        struct fb_var_screeninfo var;
        int i, ret, prev_console, charcnt = 256;
 
@@ -2348,8 +2351,6 @@ static int fbcon_switch(struct vc_data *vc)
 static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info,
                                int blank)
 {
-       struct fb_event event;
-
        if (blank) {
                unsigned short charmask = vc->vc_hi_font_mask ?
                        0x1ff : 0xff;
@@ -2360,14 +2361,6 @@ static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info,
                fbcon_clear(vc, 0, 0, vc->vc_rows, vc->vc_cols);
                vc->vc_video_erase_char = oldc;
        }
-
-
-       if (!lock_fb_info(info))
-               return;
-       event.info = info;
-       event.data = &blank;
-       fb_notifier_call_chain(FB_EVENT_CONBLANK, &event);
-       unlock_fb_info(info);
 }
 
 static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
@@ -2394,9 +2387,8 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
                        fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);
                        ops->cursor_flash = (!blank);
 
-                       if (!(info->flags & FBINFO_MISC_USEREVENT))
-                               if (fb_blank(info, blank))
-                                       fbcon_generic_blank(vc, info, blank);
+                       if (fb_blank(info, blank))
+                               fbcon_generic_blank(vc, info, blank);
                }
 
                if (!blank)
@@ -2553,7 +2545,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
 {
        struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
        struct fbcon_ops *ops = info->fbcon_par;
-       struct display *p = &fb_display[vc->vc_num];
+       struct fbcon_display *p = &fb_display[vc->vc_num];
        int resize;
        int cnt;
        char *old_data = NULL;
@@ -2601,7 +2593,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
 
 static int fbcon_copy_font(struct vc_data *vc, int con)
 {
-       struct display *od = &fb_display[con];
+       struct fbcon_display *od = &fb_display[con];
        struct console_font *f = &vc->vc_font;
 
        if (od->fontdata == f->data)
@@ -2826,7 +2818,7 @@ static void fbcon_scrolldelta(struct vc_data *vc, int lines)
 {
        struct fb_info *info = registered_fb[con2fb_map[fg_console]];
        struct fbcon_ops *ops = info->fbcon_par;
-       struct display *disp = &fb_display[fg_console];
+       struct fbcon_display *disp = &fb_display[fg_console];
        int offset, limit, scrollback_old;
 
        if (softback_top) {
@@ -2918,7 +2910,7 @@ static int fbcon_set_origin(struct vc_data *vc)
        return 0;
 }
 
-static void fbcon_suspended(struct fb_info *info)
+void fbcon_suspended(struct fb_info *info)
 {
        struct vc_data *vc = NULL;
        struct fbcon_ops *ops = info->fbcon_par;
@@ -2931,7 +2923,7 @@ static void fbcon_suspended(struct fb_info *info)
        fbcon_cursor(vc, CM_ERASE);
 }
 
-static void fbcon_resumed(struct fb_info *info)
+void fbcon_resumed(struct fb_info *info)
 {
        struct vc_data *vc;
        struct fbcon_ops *ops = info->fbcon_par;
@@ -2947,7 +2939,7 @@ static void fbcon_modechanged(struct fb_info *info)
 {
        struct fbcon_ops *ops = info->fbcon_par;
        struct vc_data *vc;
-       struct display *p;
+       struct fbcon_display *p;
        int rows, cols;
 
        if (!ops || ops->currcon < 0)
@@ -2987,7 +2979,7 @@ static void fbcon_set_all_vcs(struct fb_info *info)
 {
        struct fbcon_ops *ops = info->fbcon_par;
        struct vc_data *vc;
-       struct display *p;
+       struct fbcon_display *p;
        int i, rows, cols, fg = -1;
 
        if (!ops || ops->currcon < 0)
@@ -3018,11 +3010,20 @@ static void fbcon_set_all_vcs(struct fb_info *info)
                fbcon_modechanged(info);
 }
 
-static int fbcon_mode_deleted(struct fb_info *info,
-                             struct fb_videomode *mode)
+
+void fbcon_update_vcs(struct fb_info *info, bool all)
+{
+       if (all)
+               fbcon_set_all_vcs(info);
+       else
+               fbcon_modechanged(info);
+}
+
+int fbcon_mode_deleted(struct fb_info *info,
+                      struct fb_videomode *mode)
 {
        struct fb_info *fb_info;
-       struct display *p;
+       struct fbcon_display *p;
        int i, j, found = 0;
 
        /* before deletion, ensure that mode is not in use */
@@ -3045,7 +3046,7 @@ static int fbcon_mode_deleted(struct fb_info *info,
 }
 
 #ifdef CONFIG_VT_HW_CONSOLE_BINDING
-static int fbcon_unbind(void)
+static void fbcon_unbind(void)
 {
        int ret;
 
@@ -3054,25 +3055,21 @@ static int fbcon_unbind(void)
 
        if (!ret)
                fbcon_has_console_bind = 0;
-
-       return ret;
 }
 #else
-static inline int fbcon_unbind(void)
-{
-       return -EINVAL;
-}
+static inline void fbcon_unbind(void) {}
 #endif /* CONFIG_VT_HW_CONSOLE_BINDING */
 
 /* called with console_lock held */
-static int fbcon_fb_unbind(int idx)
+void fbcon_fb_unbind(struct fb_info *info)
 {
        int i, new_idx = -1, ret = 0;
+       int idx = info->node;
 
        WARN_CONSOLE_UNLOCKED();
 
        if (!fbcon_has_console_bind)
-               return 0;
+               return;
 
        for (i = first_fb_vc; i <= last_fb_vc; i++) {
                if (con2fb_map[i] != idx &&
@@ -3105,26 +3102,24 @@ static int fbcon_fb_unbind(int idx)
                                                                     idx, 0);
                                        if (ret) {
                                                con2fb_map[i] = idx;
-                                               return ret;
+                                               return;
                                        }
                                }
                        }
                }
-               ret = fbcon_unbind();
+               fbcon_unbind();
        }
-
-       return ret;
 }
 
 /* called with console_lock held */
-static int fbcon_fb_unregistered(struct fb_info *info)
+void fbcon_fb_unregistered(struct fb_info *info)
 {
        int i, idx;
 
        WARN_CONSOLE_UNLOCKED();
 
        if (deferred_takeover)
-               return 0;
+               return;
 
        idx = info->node;
        for (i = first_fb_vc; i <= last_fb_vc; i++) {
@@ -3153,21 +3148,18 @@ static int fbcon_fb_unregistered(struct fb_info *info)
 
        if (!num_registered_fb)
                do_unregister_con_driver(&fb_con);
-
-       return 0;
 }
 
-/* called with console_lock held */
-static void fbcon_remap_all(int idx)
+void fbcon_remap_all(struct fb_info *info)
 {
-       int i;
-
-       WARN_CONSOLE_UNLOCKED();
+       int i, idx = info->node;
 
+       console_lock();
        if (deferred_takeover) {
                for (i = first_fb_vc; i <= last_fb_vc; i++)
                        con2fb_map_boot[i] = idx;
                fbcon_map_override();
+               console_unlock();
                return;
        }
 
@@ -3180,6 +3172,7 @@ static void fbcon_remap_all(int idx)
                       first_fb_vc + 1, last_fb_vc + 1);
                info_idx = idx;
        }
+       console_unlock();
 }
 
 #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
@@ -3213,7 +3206,7 @@ static inline void fbcon_select_primary(struct fb_info *info)
 #endif /* CONFIG_FRAMEBUFFER_DETECT_PRIMARY */
 
 /* called with console_lock held */
-static int fbcon_fb_registered(struct fb_info *info)
+int fbcon_fb_registered(struct fb_info *info)
 {
        int ret = 0, i, idx;
 
@@ -3247,7 +3240,7 @@ static int fbcon_fb_registered(struct fb_info *info)
        return ret;
 }
 
-static void fbcon_fb_blanked(struct fb_info *info, int blank)
+void fbcon_fb_blanked(struct fb_info *info, int blank)
 {
        struct fbcon_ops *ops = info->fbcon_par;
        struct vc_data *vc;
@@ -3269,7 +3262,7 @@ static void fbcon_fb_blanked(struct fb_info *info, int blank)
        ops->blank_state = blank;
 }
 
-static void fbcon_new_modelist(struct fb_info *info)
+void fbcon_new_modelist(struct fb_info *info)
 {
        int i;
        struct vc_data *vc;
@@ -3290,11 +3283,11 @@ static void fbcon_new_modelist(struct fb_info *info)
        }
 }
 
-static void fbcon_get_requirement(struct fb_info *info,
-                                 struct fb_blit_caps *caps)
+void fbcon_get_requirement(struct fb_info *info,
+                          struct fb_blit_caps *caps)
 {
        struct vc_data *vc;
-       struct display *p;
+       struct fbcon_display *p;
 
        if (caps->flags) {
                int i, charcnt;
@@ -3326,80 +3319,47 @@ static void fbcon_get_requirement(struct fb_info *info,
        }
 }
 
-static int fbcon_event_notify(struct notifier_block *self,
-                             unsigned long action, void *data)
+int fbcon_set_con2fb_map_ioctl(void __user *argp)
 {
-       struct fb_event *event = data;
-       struct fb_info *info = event->info;
-       struct fb_videomode *mode;
-       struct fb_con2fbmap *con2fb;
-       struct fb_blit_caps *caps;
-       int idx, ret = 0;
-
-       /*
-        * ignore all events except driver registration and deregistration
-        * if fbcon is not active
-        */
-       if (fbcon_has_exited && !(action == FB_EVENT_FB_REGISTERED ||
-                                 action == FB_EVENT_FB_UNREGISTERED))
-               goto done;
+       struct fb_con2fbmap con2fb;
+       int ret;
 
-       switch(action) {
-       case FB_EVENT_SUSPEND:
-               fbcon_suspended(info);
-               break;
-       case FB_EVENT_RESUME:
-               fbcon_resumed(info);
-               break;
-       case FB_EVENT_MODE_CHANGE:
-               fbcon_modechanged(info);
-               break;
-       case FB_EVENT_MODE_CHANGE_ALL:
-               fbcon_set_all_vcs(info);
-               break;
-       case FB_EVENT_MODE_DELETE:
-               mode = event->data;
-               ret = fbcon_mode_deleted(info, mode);
-               break;
-       case FB_EVENT_FB_UNBIND:
-               idx = info->node;
-               ret = fbcon_fb_unbind(idx);
-               break;
-       case FB_EVENT_FB_REGISTERED:
-               ret = fbcon_fb_registered(info);
-               break;
-       case FB_EVENT_FB_UNREGISTERED:
-               ret = fbcon_fb_unregistered(info);
-               break;
-       case FB_EVENT_SET_CONSOLE_MAP:
-               /* called with console lock held */
-               con2fb = event->data;
-               ret = set_con2fb_map(con2fb->console - 1,
-                                    con2fb->framebuffer, 1);
-               break;
-       case FB_EVENT_GET_CONSOLE_MAP:
-               con2fb = event->data;
-               con2fb->framebuffer = con2fb_map[con2fb->console - 1];
-               break;
-       case FB_EVENT_BLANK:
-               fbcon_fb_blanked(info, *(int *)event->data);
-               break;
-       case FB_EVENT_NEW_MODELIST:
-               fbcon_new_modelist(info);
-               break;
-       case FB_EVENT_GET_REQ:
-               caps = event->data;
-               fbcon_get_requirement(info, caps);
-               break;
-       case FB_EVENT_REMAP_ALL_CONSOLE:
-               idx = info->node;
-               fbcon_remap_all(idx);
-               break;
+       if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
+               return -EFAULT;
+       if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
+               return -EINVAL;
+       if (con2fb.framebuffer >= FB_MAX)
+               return -EINVAL;
+       if (!registered_fb[con2fb.framebuffer])
+               request_module("fb%d", con2fb.framebuffer);
+       if (!registered_fb[con2fb.framebuffer]) {
+               return -EINVAL;
        }
-done:
+
+       console_lock();
+       ret = set_con2fb_map(con2fb.console - 1,
+                            con2fb.framebuffer, 1);
+       console_unlock();
+
        return ret;
 }
 
+int fbcon_get_con2fb_map_ioctl(void __user *argp)
+{
+       struct fb_con2fbmap con2fb;
+
+       if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
+               return -EFAULT;
+       if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
+               return -EINVAL;
+
+       console_lock();
+       con2fb.framebuffer = con2fb_map[con2fb.console - 1];
+       console_unlock();
+
+       return copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0;
+}
+
 /*
  *  The console `switch' structure for the frame buffer based console
  */
@@ -3431,10 +3391,6 @@ static const struct consw fb_con = {
        .con_debug_leave        = fbcon_debug_leave,
 };
 
-static struct notifier_block fbcon_event_notifier = {
-       .notifier_call  = fbcon_event_notify,
-};
-
 static ssize_t store_rotate(struct device *device,
                            struct device_attribute *attr, const char *buf,
                            size_t count)
@@ -3443,9 +3399,6 @@ static ssize_t store_rotate(struct device *device,
        int rotate, idx;
        char **last = NULL;
 
-       if (fbcon_has_exited)
-               return count;
-
        console_lock();
        idx = con2fb_map[fg_console];
 
@@ -3468,9 +3421,6 @@ static ssize_t store_rotate_all(struct device *device,
        int rotate, idx;
        char **last = NULL;
 
-       if (fbcon_has_exited)
-               return count;
-
        console_lock();
        idx = con2fb_map[fg_console];
 
@@ -3491,9 +3441,6 @@ static ssize_t show_rotate(struct device *device,
        struct fb_info *info;
        int rotate = 0, idx;
 
-       if (fbcon_has_exited)
-               return 0;
-
        console_lock();
        idx = con2fb_map[fg_console];
 
@@ -3514,9 +3461,6 @@ static ssize_t show_cursor_blink(struct device *device,
        struct fbcon_ops *ops;
        int idx, blink = -1;
 
-       if (fbcon_has_exited)
-               return 0;
-
        console_lock();
        idx = con2fb_map[fg_console];
 
@@ -3543,9 +3487,6 @@ static ssize_t store_cursor_blink(struct device *device,
        int blink, idx;
        char **last = NULL;
 
-       if (fbcon_has_exited)
-               return count;
-
        console_lock();
        idx = con2fb_map[fg_console];
 
@@ -3668,9 +3609,6 @@ static void fbcon_exit(void)
        struct fb_info *info;
        int i, j, mapped;
 
-       if (fbcon_has_exited)
-               return;
-
 #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER
        if (deferred_takeover) {
                dummycon_unregister_output_notifier(&fbcon_output_nb);
@@ -3695,7 +3633,7 @@ static void fbcon_exit(void)
                for (j = first_fb_vc; j <= last_fb_vc; j++) {
                        if (con2fb_map[j] == i) {
                                mapped = 1;
-                               break;
+                               con2fb_map[j] = -1;
                        }
                }
 
@@ -3718,8 +3656,6 @@ static void fbcon_exit(void)
                                info->queue.func = NULL;
                }
        }
-
-       fbcon_has_exited = 1;
 }
 
 void __init fb_console_init(void)
@@ -3727,7 +3663,6 @@ void __init fb_console_init(void)
        int i;
 
        console_lock();
-       fb_register_client(&fbcon_event_notifier);
        fbcon_device = device_create(fb_class, NULL, MKDEV(0, 0), NULL,
                                     "fbcon");
 
@@ -3763,7 +3698,6 @@ static void __exit fbcon_deinit_device(void)
 void __exit fb_console_exit(void)
 {
        console_lock();
-       fb_unregister_client(&fbcon_event_notifier);
        fbcon_deinit_device();
        device_destroy(fb_class, MKDEV(0, 0));
        fbcon_exit();