Skip to content

Commit 540d6d7

Browse files
tiwaigregkh
authored andcommitted
fbcon: Fix vc attr at deinit
commit 8aac7f34369726d1a158788ae8aff3002d5eb528 upstream. fbcon can deal with vc_hi_font_mask (the upper 256 chars) and adjust the vc attrs dynamically when vc_hi_font_mask is changed at fbcon_init(). When the vc_hi_font_mask is set, it remaps the attrs in the existing console buffer with one bit shift up (for 9 bits), while it remaps with one bit shift down (for 8 bits) when the value is cleared. It works fine as long as the font gets updated after fbcon was initialized. However, we hit a bizarre problem when the console is switched to another fb driver (typically from vesafb or efifb to drmfb). At switching to the new fb driver, we temporarily rebind the console to the dummy console, then rebind to the new driver. During the switching, we leave the modified attrs as is. Thus, the new fbcon takes over the old buffer as if it were to contain 8 bits chars (although the attrs are still shifted for 9 bits), and effectively this results in the yellow color texts instead of the original white color, as found in the bugzilla entry below. An easy fix for this is to re-adjust the attrs before leaving the fbcon at con_deinit callback. Since the code to adjust the attrs is already present in the current fbcon code, in this patch, we simply factor out the relevant code, and call it from fbcon_deinit(). Bugzilla: https://bugzilla.suse.com/show_bug.cgi?id=1000619 Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Cc: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent ac60197 commit 540d6d7

1 file changed

Lines changed: 40 additions & 27 deletions

File tree

drivers/video/console/fbcon.c

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1168,6 +1168,8 @@ static void fbcon_free_font(struct display *p, bool freefont)
11681168
p->userfont = 0;
11691169
}
11701170

1171+
static void set_vc_hi_font(struct vc_data *vc, bool set);
1172+
11711173
static void fbcon_deinit(struct vc_data *vc)
11721174
{
11731175
struct display *p = &fb_display[vc->vc_num];
@@ -1203,6 +1205,9 @@ static void fbcon_deinit(struct vc_data *vc)
12031205
if (free_font)
12041206
vc->vc_font.data = NULL;
12051207

1208+
if (vc->vc_hi_font_mask)
1209+
set_vc_hi_font(vc, false);
1210+
12061211
if (!con_is_bound(&fb_con))
12071212
fbcon_exit();
12081213

@@ -2439,32 +2444,10 @@ static int fbcon_get_font(struct vc_data *vc, struct console_font *font)
24392444
return 0;
24402445
}
24412446

2442-
static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
2443-
const u8 * data, int userfont)
2447+
/* set/clear vc_hi_font_mask and update vc attrs accordingly */
2448+
static void set_vc_hi_font(struct vc_data *vc, bool set)
24442449
{
2445-
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
2446-
struct fbcon_ops *ops = info->fbcon_par;
2447-
struct display *p = &fb_display[vc->vc_num];
2448-
int resize;
2449-
int cnt;
2450-
char *old_data = NULL;
2451-
2452-
if (CON_IS_VISIBLE(vc) && softback_lines)
2453-
fbcon_set_origin(vc);
2454-
2455-
resize = (w != vc->vc_font.width) || (h != vc->vc_font.height);
2456-
if (p->userfont)
2457-
old_data = vc->vc_font.data;
2458-
if (userfont)
2459-
cnt = FNTCHARCNT(data);
2460-
else
2461-
cnt = 256;
2462-
vc->vc_font.data = (void *)(p->fontdata = data);
2463-
if ((p->userfont = userfont))
2464-
REFCOUNT(data)++;
2465-
vc->vc_font.width = w;
2466-
vc->vc_font.height = h;
2467-
if (vc->vc_hi_font_mask && cnt == 256) {
2450+
if (!set) {
24682451
vc->vc_hi_font_mask = 0;
24692452
if (vc->vc_can_do_color) {
24702453
vc->vc_complement_mask >>= 1;
@@ -2487,7 +2470,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
24872470
((c & 0xfe00) >> 1) | (c & 0xff);
24882471
vc->vc_attr >>= 1;
24892472
}
2490-
} else if (!vc->vc_hi_font_mask && cnt == 512) {
2473+
} else {
24912474
vc->vc_hi_font_mask = 0x100;
24922475
if (vc->vc_can_do_color) {
24932476
vc->vc_complement_mask <<= 1;
@@ -2519,8 +2502,38 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
25192502
} else
25202503
vc->vc_video_erase_char = c & ~0x100;
25212504
}
2522-
25232505
}
2506+
}
2507+
2508+
static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
2509+
const u8 * data, int userfont)
2510+
{
2511+
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
2512+
struct fbcon_ops *ops = info->fbcon_par;
2513+
struct display *p = &fb_display[vc->vc_num];
2514+
int resize;
2515+
int cnt;
2516+
char *old_data = NULL;
2517+
2518+
if (CON_IS_VISIBLE(vc) && softback_lines)
2519+
fbcon_set_origin(vc);
2520+
2521+
resize = (w != vc->vc_font.width) || (h != vc->vc_font.height);
2522+
if (p->userfont)
2523+
old_data = vc->vc_font.data;
2524+
if (userfont)
2525+
cnt = FNTCHARCNT(data);
2526+
else
2527+
cnt = 256;
2528+
vc->vc_font.data = (void *)(p->fontdata = data);
2529+
if ((p->userfont = userfont))
2530+
REFCOUNT(data)++;
2531+
vc->vc_font.width = w;
2532+
vc->vc_font.height = h;
2533+
if (vc->vc_hi_font_mask && cnt == 256)
2534+
set_vc_hi_font(vc, false);
2535+
else if (!vc->vc_hi_font_mask && cnt == 512)
2536+
set_vc_hi_font(vc, true);
25242537

25252538
if (resize) {
25262539
int cols, rows;

0 commit comments

Comments
 (0)