aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie2013-01-24 00:12:41 -0600
committerGreg Kroah-Hartman2013-02-28 08:32:27 -0600
commit90523879cdf0051a208a660a6ce475ed7ac51e99 (patch)
tree7dcb9ff4a68d2afcaa3982c67faa47646aafdbd9
parent9c3f628b6004454a3867b4c0dad9c9738405dd75 (diff)
downloadkernel-common-90523879cdf0051a208a660a6ce475ed7ac51e99.tar.gz
kernel-common-90523879cdf0051a208a660a6ce475ed7ac51e99.tar.xz
kernel-common-90523879cdf0051a208a660a6ce475ed7ac51e99.zip
fbcon: don't lose the console font across generic->chip driver switch
commit ae1287865f5361fa138d4d3b1b6277908b54eac9 upstream. 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 Signed-off-by: Dave Airlie <airlied@redhat.com> Cc: Kay Sievers <kay.sievers@vrfy.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-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 bf9a9b773de..b27a91c9880 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -991,7 +991,7 @@ static const char *fbcon_startup(void)
991 } 991 }
992 992
993 /* Setup default font */ 993 /* Setup default font */
994 if (!p->fontdata) { 994 if (!p->fontdata && !vc->vc_font.data) {
995 if (!fontname[0] || !(font = find_font(fontname))) 995 if (!fontname[0] || !(font = find_font(fontname)))
996 font = get_default_font(info->var.xres, 996 font = get_default_font(info->var.xres,
997 info->var.yres, 997 info->var.yres,
@@ -1001,6 +1001,8 @@ static const char *fbcon_startup(void)
1001 vc->vc_font.height = font->height; 1001 vc->vc_font.height = font->height;
1002 vc->vc_font.data = (void *)(p->fontdata = font->data); 1002 vc->vc_font.data = (void *)(p->fontdata = font->data);
1003 vc->vc_font.charcount = 256; /* FIXME Need to support more fonts */ 1003 vc->vc_font.charcount = 256; /* FIXME Need to support more fonts */
1004 } else {
1005 p->fontdata = vc->vc_font.data;
1004 } 1006 }
1005 1007
1006 cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); 1008 cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
@@ -1160,9 +1162,9 @@ static void fbcon_init(struct vc_data *vc, int init)
1160 ops->p = &fb_display[fg_console]; 1162 ops->p = &fb_display[fg_console];
1161} 1163}
1162 1164
1163static void fbcon_free_font(struct display *p) 1165static void fbcon_free_font(struct display *p, bool freefont)
1164{ 1166{
1165 if (p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0)) 1167 if (freefont && p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0))
1166 kfree(p->fontdata - FONT_EXTRA_WORDS * sizeof(int)); 1168 kfree(p->fontdata - FONT_EXTRA_WORDS * sizeof(int));
1167 p->fontdata = NULL; 1169 p->fontdata = NULL;
1168 p->userfont = 0; 1170 p->userfont = 0;
@@ -1174,8 +1176,8 @@ static void fbcon_deinit(struct vc_data *vc)
1174 struct fb_info *info; 1176 struct fb_info *info;
1175 struct fbcon_ops *ops; 1177 struct fbcon_ops *ops;
1176 int idx; 1178 int idx;
1179 bool free_font = true;
1177 1180
1178 fbcon_free_font(p);
1179 idx = con2fb_map[vc->vc_num]; 1181 idx = con2fb_map[vc->vc_num];
1180 1182
1181 if (idx == -1) 1183 if (idx == -1)
@@ -1186,6 +1188,8 @@ static void fbcon_deinit(struct vc_data *vc)
1186 if (!info) 1188 if (!info)
1187 goto finished; 1189 goto finished;
1188 1190
1191 if (info->flags & FBINFO_MISC_FIRMWARE)
1192 free_font = false;
1189 ops = info->fbcon_par; 1193 ops = info->fbcon_par;
1190 1194
1191 if (!ops) 1195 if (!ops)
@@ -1197,6 +1201,8 @@ static void fbcon_deinit(struct vc_data *vc)
1197 ops->flags &= ~FBCON_FLAGS_INIT; 1201 ops->flags &= ~FBCON_FLAGS_INIT;
1198finished: 1202finished:
1199 1203
1204 fbcon_free_font(p, free_font);
1205
1200 if (!con_is_bound(&fb_con)) 1206 if (!con_is_bound(&fb_con))
1201 fbcon_exit(); 1207 fbcon_exit();
1202 1208