From: Greg Kroah-Hartman Date: Wed, 14 May 2014 16:10:31 +0000 (+0200) Subject: 3.4-stable patches X-Git-Tag: v3.4.91~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0681f850f228c0ff9d043b80baee794e066fb85f;p=thirdparty%2Fkernel%2Fstable-queue.git 3.4-stable patches added patches: tgafb-fix-mode-setting-with-fbset.patch --- diff --git a/queue-3.4/series b/queue-3.4/series index e3a15650589..a9d5dcf0c80 100644 --- a/queue-3.4/series +++ b/queue-3.4/series @@ -6,3 +6,4 @@ net-add-net_ratelimited_function-and-net_-level-_ratelimited-macros.patch netfilter-can-t-fail-and-free-after-table-replacement.patch tracepoint-do-not-waste-memory-on-mods-with-no-tracepoints.patch powerpc-add-vr-save-restore-functions.patch +tgafb-fix-mode-setting-with-fbset.patch diff --git a/queue-3.4/tgafb-fix-mode-setting-with-fbset.patch b/queue-3.4/tgafb-fix-mode-setting-with-fbset.patch new file mode 100644 index 00000000000..8b21dd2c2d7 --- /dev/null +++ b/queue-3.4/tgafb-fix-mode-setting-with-fbset.patch @@ -0,0 +1,127 @@ +From 624966589041deb32a2626ee2e176e8274581101 Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Thu, 23 Jan 2014 14:42:43 -0500 +Subject: tgafb: fix mode setting with fbset + +From: Mikulas Patocka + +commit 624966589041deb32a2626ee2e176e8274581101 upstream. + +Mode setting in the TGA driver is broken for these reasons: + +- info->fix.line_length is set just once in tgafb_init_fix function. If + we change videomode, info->fix.line_length is not recalculated - so + the video mode is changed but the screen is corrupted because of wrong + info->fix.line_length. + +- info->fix.smem_len is set in tgafb_init_fix to the size of the default + video mode (640x480). If we set a higher resolution, + info->fix.smem_len is smaller than the current screen size, preventing + the userspace program from mapping the framebuffer. + +This patch fixes it: + +- info->fix.line_length initialization is moved to tgafb_set_par so that + it is recalculated with each mode change. + +- info->fix.smem_len is set to a fixed value representing the real + amount of video ram (the values are taken from xfree86 driver). + +- add a check to tgafb_check_var to prevent us from setting a videomode + that doesn't fit into videoram. + +- in tgafb_register, tgafb_init_fix is moved upwards, to be called + before fb_find_mode (because fb_find_mode already needs the videoram + size set in tgafb_init_fix). + +Signed-off-by: Mikulas Patocka +Signed-off-by: Tomi Valkeinen +Signed-off-by: Greg Kroah-Hartman + + +--- + drivers/video/tgafb.c | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +--- a/drivers/video/tgafb.c ++++ b/drivers/video/tgafb.c +@@ -192,6 +192,8 @@ tgafb_check_var(struct fb_var_screeninfo + + if (var->xres_virtual != var->xres || var->yres_virtual != var->yres) + return -EINVAL; ++ if (var->xres * var->yres * (var->bits_per_pixel >> 3) > info->fix.smem_len) ++ return -EINVAL; + if (var->nonstd) + return -EINVAL; + if (1000000000 / var->pixclock > TGA_PLL_MAX_FREQ) +@@ -272,6 +274,7 @@ tgafb_set_par(struct fb_info *info) + par->yres = info->var.yres; + par->pll_freq = pll_freq = 1000000000 / info->var.pixclock; + par->bits_per_pixel = info->var.bits_per_pixel; ++ info->fix.line_length = par->xres * (par->bits_per_pixel >> 3); + + tga_type = par->tga_type; + +@@ -1318,6 +1321,7 @@ tgafb_init_fix(struct fb_info *info) + int tga_bus_tc = TGA_BUS_TC(par->dev); + u8 tga_type = par->tga_type; + const char *tga_type_name = NULL; ++ unsigned memory_size; + + switch (tga_type) { + case TGA_TYPE_8PLANE: +@@ -1325,21 +1329,25 @@ tgafb_init_fix(struct fb_info *info) + tga_type_name = "Digital ZLXp-E1"; + if (tga_bus_tc) + tga_type_name = "Digital ZLX-E1"; ++ memory_size = 2097152; + break; + case TGA_TYPE_24PLANE: + if (tga_bus_pci) + tga_type_name = "Digital ZLXp-E2"; + if (tga_bus_tc) + tga_type_name = "Digital ZLX-E2"; ++ memory_size = 8388608; + break; + case TGA_TYPE_24PLUSZ: + if (tga_bus_pci) + tga_type_name = "Digital ZLXp-E3"; + if (tga_bus_tc) + tga_type_name = "Digital ZLX-E3"; ++ memory_size = 16777216; + break; + default: + tga_type_name = "Unknown"; ++ memory_size = 16777216; + break; + } + +@@ -1351,9 +1359,8 @@ tgafb_init_fix(struct fb_info *info) + ? FB_VISUAL_PSEUDOCOLOR + : FB_VISUAL_DIRECTCOLOR); + +- info->fix.line_length = par->xres * (par->bits_per_pixel >> 3); + info->fix.smem_start = (size_t) par->tga_fb_base; +- info->fix.smem_len = info->fix.line_length * par->yres; ++ info->fix.smem_len = memory_size; + info->fix.mmio_start = (size_t) par->tga_regs_base; + info->fix.mmio_len = 512; + +@@ -1478,6 +1485,9 @@ tgafb_register(struct device *dev) + modedb_tga = &modedb_tc; + modedbsize_tga = 1; + } ++ ++ tgafb_init_fix(info); ++ + ret = fb_find_mode(&info->var, info, + mode_option ? mode_option : mode_option_tga, + modedb_tga, modedbsize_tga, NULL, +@@ -1495,7 +1505,6 @@ tgafb_register(struct device *dev) + } + + tgafb_set_par(info); +- tgafb_init_fix(info); + + if (register_framebuffer(info) < 0) { + printk(KERN_ERR "tgafb: Could not register framebuffer\n");