Commit ae128786 authored by Dave Airlie's avatar Dave Airlie

fbcon: don't lose the console font across generic->chip driver switch

If grub2 loads efifb/vesafb, then when systemd starts it can set the console
font on that framebuffer device, however when we then load the native KMS
driver, the first thing it does is tear down the generic framebuffer driver.

The thing is the generic code is doing the right thing, it frees the font
because otherwise it would leak memory. However we can assume that if you
are removing the generic firmware driver (vesa/efi/offb), that a new driver
*should* be loading soon after, so we effectively leak the font.

However the old code left a dangling pointer in vc->vc_font.data and we
can now reuse that dangling pointer to load the font into the new
driver, now that we aren't freeing it.

Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=892340

Cc: Kay Sievers <kay.sievers@vrfy.org>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 2a248307
...@@ -990,7 +990,7 @@ static const char *fbcon_startup(void) ...@@ -990,7 +990,7 @@ static const char *fbcon_startup(void)
} }
/* Setup default font */ /* Setup default font */
if (!p->fontdata) { if (!p->fontdata && !vc->vc_font.data) {
if (!fontname[0] || !(font = find_font(fontname))) if (!fontname[0] || !(font = find_font(fontname)))
font = get_default_font(info->var.xres, font = get_default_font(info->var.xres,
info->var.yres, info->var.yres,
...@@ -1000,6 +1000,8 @@ static const char *fbcon_startup(void) ...@@ -1000,6 +1000,8 @@ static const char *fbcon_startup(void)
vc->vc_font.height = font->height; vc->vc_font.height = font->height;
vc->vc_font.data = (void *)(p->fontdata = font->data); vc->vc_font.data = (void *)(p->fontdata = font->data);
vc->vc_font.charcount = 256; /* FIXME Need to support more fonts */ vc->vc_font.charcount = 256; /* FIXME Need to support more fonts */
} else {
p->fontdata = vc->vc_font.data;
} }
cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
...@@ -1159,9 +1161,9 @@ static void fbcon_init(struct vc_data *vc, int init) ...@@ -1159,9 +1161,9 @@ static void fbcon_init(struct vc_data *vc, int init)
ops->p = &fb_display[fg_console]; ops->p = &fb_display[fg_console];
} }
static void fbcon_free_font(struct display *p) static void fbcon_free_font(struct display *p, bool freefont)
{ {
if (p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0)) if (freefont && p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0))
kfree(p->fontdata - FONT_EXTRA_WORDS * sizeof(int)); kfree(p->fontdata - FONT_EXTRA_WORDS * sizeof(int));
p->fontdata = NULL; p->fontdata = NULL;
p->userfont = 0; p->userfont = 0;
...@@ -1173,8 +1175,8 @@ static void fbcon_deinit(struct vc_data *vc) ...@@ -1173,8 +1175,8 @@ static void fbcon_deinit(struct vc_data *vc)
struct fb_info *info; struct fb_info *info;
struct fbcon_ops *ops; struct fbcon_ops *ops;
int idx; int idx;
bool free_font = true;
fbcon_free_font(p);
idx = con2fb_map[vc->vc_num]; idx = con2fb_map[vc->vc_num];
if (idx == -1) if (idx == -1)
...@@ -1185,6 +1187,8 @@ static void fbcon_deinit(struct vc_data *vc) ...@@ -1185,6 +1187,8 @@ static void fbcon_deinit(struct vc_data *vc)
if (!info) if (!info)
goto finished; goto finished;
if (info->flags & FBINFO_MISC_FIRMWARE)
free_font = false;
ops = info->fbcon_par; ops = info->fbcon_par;
if (!ops) if (!ops)
...@@ -1196,6 +1200,8 @@ static void fbcon_deinit(struct vc_data *vc) ...@@ -1196,6 +1200,8 @@ static void fbcon_deinit(struct vc_data *vc)
ops->flags &= ~FBCON_FLAGS_INIT; ops->flags &= ~FBCON_FLAGS_INIT;
finished: finished:
fbcon_free_font(p, free_font);
if (!con_is_bound(&fb_con)) if (!con_is_bound(&fb_con))
fbcon_exit(); fbcon_exit();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment