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 | |
| 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>
| -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 | ||
