aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2013-01-24 01:12:41 -0500
committerDave Airlie <airlied@redhat.com>2013-02-06 21:37:19 -0500
commitae1287865f5361fa138d4d3b1b6277908b54eac9 (patch)
tree22a6b13cd030d5f0fe06ce85bbe8b40a2a519d59 /drivers/video
parent2a2483072393b27f4336ab068a1f48ca19ff1c1e (diff)
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: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/console/fbcon.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index fdefa8fd72c4..f8dbe76a1b6f 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -990,7 +990,7 @@ static const char *fbcon_startup(void)
990 } 990 }
991 991
992 /* Setup default font */ 992 /* Setup default font */
993 if (!p->fontdata) { 993 if (!p->fontdata && !vc->vc_font.data) {
994 if (!fontname[0] || !(font = find_font(fontname))) 994 if (!fontname[0] || !(font = find_font(fontname)))
995 font = get_default_font(info->var.xres, 995 font = get_default_font(info->var.xres,
996 info->var.yres, 996 info->var.yres,
@@ -1000,6 +1000,8 @@ static const char *fbcon_startup(void)
1000 vc->vc_font.height = font->height; 1000 vc->vc_font.height = font->height;
1001 vc->vc_font.data = (void *)(p->fontdata = font->data); 1001 vc->vc_font.data = (void *)(p->fontdata = font->data);
1002 vc->vc_font.charcount = 256; /* FIXME Need to support more fonts */ 1002 vc->vc_font.charcount = 256; /* FIXME Need to support more fonts */
1003 } else {
1004 p->fontdata = vc->vc_font.data;
1003 } 1005 }
1004 1006
1005 cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); 1007 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 ops->p = &fb_display[fg_console]; 1161 ops->p = &fb_display[fg_console];
1160} 1162}
1161 1163
1162static void fbcon_free_font(struct display *p) 1164static void fbcon_free_font(struct display *p, bool freefont)
1163{ 1165{
1164 if (p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0)) 1166 if (freefont && p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0))
1165 kfree(p->fontdata - FONT_EXTRA_WORDS * sizeof(int)); 1167 kfree(p->fontdata - FONT_EXTRA_WORDS * sizeof(int));
1166 p->fontdata = NULL; 1168 p->fontdata = NULL;
1167 p->userfont = 0; 1169 p->userfont = 0;
@@ -1173,8 +1175,8 @@ static void fbcon_deinit(struct vc_data *vc)
1173 struct fb_info *info; 1175 struct fb_info *info;
1174 struct fbcon_ops *ops; 1176 struct fbcon_ops *ops;
1175 int idx; 1177 int idx;
1178 bool free_font = true;
1176 1179
1177 fbcon_free_font(p);
1178 idx = con2fb_map[vc->vc_num]; 1180 idx = con2fb_map[vc->vc_num];
1179 1181
1180 if (idx == -1) 1182 if (idx == -1)
@@ -1185,6 +1187,8 @@ static void fbcon_deinit(struct vc_data *vc)
1185 if (!info) 1187 if (!info)
1186 goto finished; 1188 goto finished;
1187 1189
1190 if (info->flags & FBINFO_MISC_FIRMWARE)
1191 free_font = false;
1188 ops = info->fbcon_par; 1192 ops = info->fbcon_par;
1189 1193
1190 if (!ops) 1194 if (!ops)
@@ -1196,6 +1200,8 @@ static void fbcon_deinit(struct vc_data *vc)
1196 ops->flags &= ~FBCON_FLAGS_INIT; 1200 ops->flags &= ~FBCON_FLAGS_INIT;
1197finished: 1201finished:
1198 1202
1203 fbcon_free_font(p, free_font);
1204
1199 if (!con_is_bound(&fb_con)) 1205 if (!con_is_bound(&fb_con))
1200 fbcon_exit(); 1206 fbcon_exit();
1201 1207