aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@linux-mips.org>2007-10-16 04:29:56 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-16 12:43:23 -0400
commitb738b990468d2acd5be7fe177fb750448bfa0b37 (patch)
tree496295879208953b67ed5e8aaa49f675c68423f2 /drivers/video
parent4d8a2d986d3ee3ece9c3cefbb23425a22132492c (diff)
tgafb: fix an out-of-range shift in mono imageblit
The pixel mask calculation in tgafb_mono_imageblit() uses a variable left-shift on a 32-bit data type by up to 32. Shifting by the width of a data type or more produces an unpredictable result according to the C standard. Rather than widening the data type this fix makes sure the count is between 0 and 31. The reason is not to penalise 32-bit platforms with operation on a "long long" type for a marginal case that is meant not to happen (blitting an image of a zero width). The reason it has escaped for so long is the Alpha, being purely 64-bit, :-) does not mask the shift out to 32 bits. This is a valid implementation -- producing the correct result certainly falls within "unpredictable behaviour". It does trigger on MIPS though and it is the recent merge of the TC support which only enabled the driver for use on anything other than the Alpha. For MIPS when the width is 32 the mask ends up being 0 rather than 0xffffffff as it should be and the frame buffer is not updated. Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org> Cc: Antonino Daplas <adaplas@pol.net> Cc: Jay Estabrook <Jay.Estabrook@hp.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/tgafb.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c
index d292a37ec7d6..5539f4d9cb74 100644
--- a/drivers/video/tgafb.c
+++ b/drivers/video/tgafb.c
@@ -5,7 +5,7 @@
5 * Copyright (C) 1997 Geert Uytterhoeven 5 * Copyright (C) 1997 Geert Uytterhoeven
6 * Copyright (C) 1999,2000 Martin Lucina, Tom Zerucha 6 * Copyright (C) 1999,2000 Martin Lucina, Tom Zerucha
7 * Copyright (C) 2002 Richard Henderson 7 * Copyright (C) 2002 Richard Henderson
8 * Copyright (C) 2006 Maciej W. Rozycki 8 * Copyright (C) 2006, 2007 Maciej W. Rozycki
9 * 9 *
10 * This file is subject to the terms and conditions of the GNU General Public 10 * This file is subject to the terms and conditions of the GNU General Public
11 * License. See the file COPYING in the main directory of this archive for 11 * License. See the file COPYING in the main directory of this archive for
@@ -13,6 +13,7 @@
13 */ 13 */
14 14
15#include <linux/bitrev.h> 15#include <linux/bitrev.h>
16#include <linux/compiler.h>
16#include <linux/delay.h> 17#include <linux/delay.h>
17#include <linux/device.h> 18#include <linux/device.h>
18#include <linux/errno.h> 19#include <linux/errno.h>
@@ -654,6 +655,9 @@ tgafb_mono_imageblit(struct fb_info *info, const struct fb_image *image)
654 line_length = info->fix.line_length; 655 line_length = info->fix.line_length;
655 rincr = (width + 7) / 8; 656 rincr = (width + 7) / 8;
656 657
658 /* A shift below cannot cope with. */
659 if (unlikely(width == 0))
660 return;
657 /* Crop the image to the screen. */ 661 /* Crop the image to the screen. */
658 if (dx > vxres || dy > vyres) 662 if (dx > vxres || dy > vyres)
659 return; 663 return;
@@ -709,9 +713,10 @@ tgafb_mono_imageblit(struct fb_info *info, const struct fb_image *image)
709 unsigned long bwidth; 713 unsigned long bwidth;
710 714
711 /* Handle common case of imaging a single character, in 715 /* Handle common case of imaging a single character, in
712 a font less than 32 pixels wide. */ 716 a font less than or 32 pixels wide. */
713 717
714 pixelmask = (1 << width) - 1; 718 /* Avoid a shift by 32; width > 0 implied. */
719 pixelmask = (2ul << (width - 1)) - 1;
715 pixelmask <<= shift; 720 pixelmask <<= shift;
716 __raw_writel(pixelmask, regs_base + TGA_PIXELMASK_REG); 721 __raw_writel(pixelmask, regs_base + TGA_PIXELMASK_REG);
717 wmb(); 722 wmb();