diff options
author | Antonino A. Daplas <adaplas@gmail.com> | 2007-07-17 07:05:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-17 13:23:11 -0400 |
commit | d1baa4ffa677bf6986c460fcfd4cdaf8bfe66f0e (patch) | |
tree | bb1670cd6842187babf0b6e2792f9c736646dbbc /drivers/video/console | |
parent | 2f7bb99fc9eb7a3d3840dc0a507049b7be1daba8 (diff) |
fbcon: set_con2fb_map fixes
set_con2fb_map() has regressed for some time. Using fbcon=map:01, for
example, works only if there is only 1 working framebuffer. Trying to do a
set_con2fb_map() on a non-allocated vc will freeze the system.
- ensure that succeeding drivers after the first gets mapped to the console
- remove fbcon_preset_display() and modify fbcon_set_display() to include the
former's functionality
- ensure that binding and unbinding succeeds if multiple drivers are mapped to
the console
Signed-off-by: Antonino Daplas <adaplas@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/video/console')
-rw-r--r-- | drivers/video/console/fbcon.c | 64 |
1 files changed, 25 insertions, 39 deletions
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 7ba21eb1676c..13b67ee8b3c0 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c | |||
@@ -192,9 +192,7 @@ static __inline__ void ypan_down(struct vc_data *vc, int count); | |||
192 | static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int sx, | 192 | static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int sx, |
193 | int dy, int dx, int height, int width, u_int y_break); | 193 | int dy, int dx, int height, int width, u_int y_break); |
194 | static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, | 194 | static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, |
195 | struct vc_data *vc); | 195 | int unit); |
196 | static void fbcon_preset_disp(struct fb_info *info, struct fb_var_screeninfo *var, | ||
197 | int unit); | ||
198 | static void fbcon_redraw_move(struct vc_data *vc, struct display *p, | 196 | static void fbcon_redraw_move(struct vc_data *vc, struct display *p, |
199 | int line, int count, int dy); | 197 | int line, int count, int dy); |
200 | static void fbcon_modechanged(struct fb_info *info); | 198 | static void fbcon_modechanged(struct fb_info *info); |
@@ -745,7 +743,9 @@ static int con2fb_acquire_newinfo(struct vc_data *vc, struct fb_info *info, | |||
745 | 743 | ||
746 | if (!err) { | 744 | if (!err) { |
747 | info->fbcon_par = ops; | 745 | info->fbcon_par = ops; |
748 | set_blitting_type(vc, info); | 746 | |
747 | if (vc) | ||
748 | set_blitting_type(vc, info); | ||
749 | } | 749 | } |
750 | 750 | ||
751 | if (err) { | 751 | if (err) { |
@@ -807,11 +807,7 @@ static void con2fb_init_display(struct vc_data *vc, struct fb_info *info, | |||
807 | 807 | ||
808 | ops->flags |= FBCON_FLAGS_INIT; | 808 | ops->flags |= FBCON_FLAGS_INIT; |
809 | ops->graphics = 0; | 809 | ops->graphics = 0; |
810 | 810 | fbcon_set_disp(info, &info->var, unit); | |
811 | if (vc) | ||
812 | fbcon_set_disp(info, &info->var, vc); | ||
813 | else | ||
814 | fbcon_preset_disp(info, &info->var, unit); | ||
815 | 811 | ||
816 | if (show_logo) { | 812 | if (show_logo) { |
817 | struct vc_data *fg_vc = vc_cons[fg_console].d; | 813 | struct vc_data *fg_vc = vc_cons[fg_console].d; |
@@ -1116,6 +1112,9 @@ static void fbcon_init(struct vc_data *vc, int init) | |||
1116 | if (var_to_display(p, &info->var, info)) | 1112 | if (var_to_display(p, &info->var, info)) |
1117 | return; | 1113 | return; |
1118 | 1114 | ||
1115 | if (!info->fbcon_par) | ||
1116 | con2fb_acquire_newinfo(vc, info, vc->vc_num, -1); | ||
1117 | |||
1119 | /* If we are not the first console on this | 1118 | /* If we are not the first console on this |
1120 | fb, copy the font from that console */ | 1119 | fb, copy the font from that console */ |
1121 | t = &fb_display[fg_console]; | 1120 | t = &fb_display[fg_console]; |
@@ -1382,36 +1381,29 @@ static int scrollback_phys_max = 0; | |||
1382 | static int scrollback_max = 0; | 1381 | static int scrollback_max = 0; |
1383 | static int scrollback_current = 0; | 1382 | static int scrollback_current = 0; |
1384 | 1383 | ||
1385 | /* | ||
1386 | * If no vc is existent yet, just set struct display | ||
1387 | */ | ||
1388 | static void fbcon_preset_disp(struct fb_info *info, struct fb_var_screeninfo *var, | ||
1389 | int unit) | ||
1390 | { | ||
1391 | struct display *p = &fb_display[unit]; | ||
1392 | struct display *t = &fb_display[fg_console]; | ||
1393 | |||
1394 | if (var_to_display(p, var, info)) | ||
1395 | return; | ||
1396 | |||
1397 | p->fontdata = t->fontdata; | ||
1398 | p->userfont = t->userfont; | ||
1399 | if (p->userfont) | ||
1400 | REFCOUNT(p->fontdata)++; | ||
1401 | } | ||
1402 | |||
1403 | static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, | 1384 | static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, |
1404 | struct vc_data *vc) | 1385 | int unit) |
1405 | { | 1386 | { |
1406 | struct display *p = &fb_display[vc->vc_num], *t; | 1387 | struct display *p, *t; |
1407 | struct vc_data **default_mode = vc->vc_display_fg; | 1388 | struct vc_data **default_mode, *vc; |
1408 | struct vc_data *svc = *default_mode; | 1389 | struct vc_data *svc; |
1409 | struct fbcon_ops *ops = info->fbcon_par; | 1390 | struct fbcon_ops *ops = info->fbcon_par; |
1410 | int rows, cols, charcnt = 256; | 1391 | int rows, cols, charcnt = 256; |
1411 | 1392 | ||
1393 | p = &fb_display[unit]; | ||
1394 | |||
1412 | if (var_to_display(p, var, info)) | 1395 | if (var_to_display(p, var, info)) |
1413 | return; | 1396 | return; |
1397 | |||
1398 | vc = vc_cons[unit].d; | ||
1399 | |||
1400 | if (!vc) | ||
1401 | return; | ||
1402 | |||
1403 | default_mode = vc->vc_display_fg; | ||
1404 | svc = *default_mode; | ||
1414 | t = &fb_display[svc->vc_num]; | 1405 | t = &fb_display[svc->vc_num]; |
1406 | |||
1415 | if (!vc->vc_font.data) { | 1407 | if (!vc->vc_font.data) { |
1416 | vc->vc_font.data = (void *)(p->fontdata = t->fontdata); | 1408 | vc->vc_font.data = (void *)(p->fontdata = t->fontdata); |
1417 | vc->vc_font.width = (*default_mode)->vc_font.width; | 1409 | vc->vc_font.width = (*default_mode)->vc_font.width; |
@@ -3118,8 +3110,7 @@ static int fbcon_fb_registered(struct fb_info *info) | |||
3118 | ret = fbcon_takeover(1); | 3110 | ret = fbcon_takeover(1); |
3119 | } else { | 3111 | } else { |
3120 | for (i = first_fb_vc; i <= last_fb_vc; i++) { | 3112 | for (i = first_fb_vc; i <= last_fb_vc; i++) { |
3121 | if (con2fb_map_boot[i] == idx && | 3113 | if (con2fb_map_boot[i] == idx) |
3122 | con2fb_map[i] == -1) | ||
3123 | set_con2fb_map(i, idx, 0); | 3114 | set_con2fb_map(i, idx, 0); |
3124 | } | 3115 | } |
3125 | } | 3116 | } |
@@ -3167,12 +3158,7 @@ static void fbcon_new_modelist(struct fb_info *info) | |||
3167 | mode = fb_find_nearest_mode(fb_display[i].mode, | 3158 | mode = fb_find_nearest_mode(fb_display[i].mode, |
3168 | &info->modelist); | 3159 | &info->modelist); |
3169 | fb_videomode_to_var(&var, mode); | 3160 | fb_videomode_to_var(&var, mode); |
3170 | 3161 | fbcon_set_disp(info, &var, vc->vc_num); | |
3171 | if (vc) | ||
3172 | fbcon_set_disp(info, &var, vc); | ||
3173 | else | ||
3174 | fbcon_preset_disp(info, &var, i); | ||
3175 | |||
3176 | } | 3162 | } |
3177 | } | 3163 | } |
3178 | 3164 | ||