[PATCH] fbdev: Fix incorrect unaligned access in little-endian machines
authorAntonino A. Daplas <adaplas@gmail.com>
Tue, 13 Dec 2005 06:17:21 +0000 (22:17 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Tue, 13 Dec 2005 06:31:17 +0000 (22:31 -0800)
The drawing function cfbfillrect does not work correctly when access is not
unsigned-long aligned.  It manifests as extra lines of pixels that are not
complete drawn.  Reversing the shift operator solves the problem, so I would
presume that this bug would manifest only on little endian machines.  The
function cfbcopyarea may also have this bug.

Aligned access should present no problems.

Signed-off-by: Antonino Daplas <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
drivers/video/cfbcopyarea.c
drivers/video/cfbfillrect.c
drivers/video/cfbimgblt.c
include/linux/fb.h

index cdc71572cf356d26955ec256d42e6c1149663108..74415325b016db9d6e9e4f2e6983e188f28f0816 100644 (file)
@@ -64,8 +64,8 @@ bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src
        int const shift = dst_idx-src_idx;
        int left, right;
 
-       first = ~0UL >> dst_idx;
-       last = ~(~0UL >> ((dst_idx+n) % bits));
+       first = FB_SHIFT_HIGH(~0UL, dst_idx);
+       last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
 
        if (!shift) {
                // Same alignment for source and dest
@@ -216,8 +216,8 @@ bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem
 
        shift = dst_idx-src_idx;
 
-       first = ~0UL << (bits - 1 - dst_idx);
-       last = ~(~0UL << (bits - 1 - ((dst_idx-n) % bits)));
+       first = FB_SHIFT_LOW(~0UL, bits - 1 - dst_idx);
+       last = ~(FB_SHIFT_LOW(~0UL, bits - 1 - ((dst_idx-n) % bits)));
 
        if (!shift) {
                // Same alignment for source and dest
index 167d9314e6eb49c6ae25683e940563ef92f6ca1c..e5ff62e9cfb81c1952823c99ea4b4be17c8e9761 100644 (file)
@@ -110,8 +110,8 @@ bitfill_aligned(unsigned long __iomem *dst, int dst_idx, unsigned long pat, unsi
        if (!n)
                return;
 
-       first = ~0UL >> dst_idx;
-       last = ~(~0UL >> ((dst_idx+n) % bits));
+       first = FB_SHIFT_HIGH(~0UL, dst_idx);
+       last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
 
        if (dst_idx+n <= bits) {
                // Single word
@@ -167,8 +167,8 @@ bitfill_unaligned(unsigned long __iomem *dst, int dst_idx, unsigned long pat,
        if (!n)
                return;
 
-       first = ~0UL >> dst_idx;
-       last = ~(~0UL >> ((dst_idx+n) % bits));
+       first = FB_SHIFT_HIGH(~0UL, dst_idx);
+       last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
 
        if (dst_idx+n <= bits) {
                // Single word
@@ -221,8 +221,8 @@ bitfill_aligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat,
        if (!n)
                return;
 
-       first = ~0UL >> dst_idx;
-       last = ~(~0UL >> ((dst_idx+n) % bits));
+       first = FB_SHIFT_HIGH(~0UL, dst_idx);
+       last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
 
        if (dst_idx+n <= bits) {
                // Single word
@@ -290,8 +290,8 @@ bitfill_unaligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat
        if (!n)
                return;
 
-       first = ~0UL >> dst_idx;
-       last = ~(~0UL >> ((dst_idx+n) % bits));
+       first = FB_SHIFT_HIGH(~0UL, dst_idx);
+       last = ~(FB_SHIFT_HIGH(~0UL, (dst_idx+n) % bits));
 
        if (dst_idx+n <= bits) {
                // Single word
index 7a01742a82af0519181ad69ff5056ca0589e2668..910e2338a27e3a38c7c182bcfcfe6f7e9d9c2864 100644 (file)
@@ -76,18 +76,6 @@ static u32 cfb_tab32[] = {
 #define FB_WRITEL fb_writel
 #define FB_READL  fb_readl
 
-#if defined (__BIG_ENDIAN)
-#define LEFT_POS(bpp)          (32 - bpp)
-#define SHIFT_HIGH(val, bits)  ((val) >> (bits))
-#define SHIFT_LOW(val, bits)   ((val) << (bits))
-#define BIT_NR(b)              (7 - (b))
-#else
-#define LEFT_POS(bpp)          (0)
-#define SHIFT_HIGH(val, bits)  ((val) << (bits))
-#define SHIFT_LOW(val, bits)   ((val) >> (bits))
-#define BIT_NR(b)              (b)
-#endif
-
 static inline void color_imageblit(const struct fb_image *image, 
                                   struct fb_info *p, u8 __iomem *dst1, 
                                   u32 start_index,
@@ -109,7 +97,7 @@ static inline void color_imageblit(const struct fb_image *image,
                val = 0;
                
                if (start_index) {
-                       u32 start_mask = ~(SHIFT_HIGH(~(u32)0, start_index));
+                       u32 start_mask = ~(FB_SHIFT_HIGH(~(u32)0, start_index));
                        val = FB_READL(dst) & start_mask;
                        shift = start_index;
                }
@@ -119,20 +107,20 @@ static inline void color_imageblit(const struct fb_image *image,
                                color = palette[*src];
                        else
                                color = *src;
-                       color <<= LEFT_POS(bpp);
-                       val |= SHIFT_HIGH(color, shift);
+                       color <<= FB_LEFT_POS(bpp);
+                       val |= FB_SHIFT_HIGH(color, shift);
                        if (shift >= null_bits) {
                                FB_WRITEL(val, dst++);
        
                                val = (shift == null_bits) ? 0 : 
-                                       SHIFT_LOW(color, 32 - shift);
+                                       FB_SHIFT_LOW(color, 32 - shift);
                        }
                        shift += bpp;
                        shift &= (32 - 1);
                        src++;
                }
                if (shift) {
-                       u32 end_mask = SHIFT_HIGH(~(u32)0, shift);
+                       u32 end_mask = FB_SHIFT_HIGH(~(u32)0, shift);
 
                        FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);
                }
@@ -162,8 +150,8 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
        u32 i, j, l;
        
        dst2 = (u32 __iomem *) dst1;
-       fgcolor <<= LEFT_POS(bpp);
-       bgcolor <<= LEFT_POS(bpp);
+       fgcolor <<= FB_LEFT_POS(bpp);
+       bgcolor <<= FB_LEFT_POS(bpp);
 
        for (i = image->height; i--; ) {
                shift = val = 0;
@@ -174,21 +162,21 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
 
                /* write leading bits */
                if (start_index) {
-                       u32 start_mask = ~(SHIFT_HIGH(~(u32)0, start_index));
+                       u32 start_mask = ~(FB_SHIFT_HIGH(~(u32)0,start_index));
                        val = FB_READL(dst) & start_mask;
                        shift = start_index;
                }
 
                while (j--) {
                        l--;
-                       color = (*s & 1 << (BIT_NR(l))) ? fgcolor : bgcolor;
-                       val |= SHIFT_HIGH(color, shift);
+                       color = (*s & 1 << (FB_BIT_NR(l))) ? fgcolor : bgcolor;
+                       val |= FB_SHIFT_HIGH(color, shift);
                        
                        /* Did the bitshift spill bits to the next long? */
                        if (shift >= null_bits) {
                                FB_WRITEL(val, dst++);
                                val = (shift == null_bits) ? 0 :
-                                        SHIFT_LOW(color,32 - shift);
+                                       FB_SHIFT_LOW(color,32 - shift);
                        }
                        shift += bpp;
                        shift &= (32 - 1);
@@ -197,7 +185,7 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
 
                /* write trailing bits */
                if (shift) {
-                       u32 end_mask = SHIFT_HIGH(~(u32)0, shift);
+                       u32 end_mask = FB_SHIFT_HIGH(~(u32)0, shift);
 
                        FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);
                }
index dab3a4decb44bff3f479790e717cc38a56ab76fc..a973be2cfe61abb2fb774bc5409225556649c2d1 100644 (file)
@@ -833,6 +833,18 @@ struct fb_info {
 #define fb_writeq(b,addr) (*(volatile u64 *) (addr) = (b))
 #define fb_memset memset
 
+#endif
+
+#if defined (__BIG_ENDIAN)
+#define FB_LEFT_POS(bpp)          (32 - bpp)
+#define FB_SHIFT_HIGH(val, bits)  ((val) >> (bits))
+#define FB_SHIFT_LOW(val, bits)   ((val) << (bits))
+#define FB_BIT_NR(b)              (7 - (b))
+#else
+#define FB_LEFT_POS(bpp)          (0)
+#define FB_SHIFT_HIGH(val, bits)  ((val) << (bits))
+#define FB_SHIFT_LOW(val, bits)   ((val) >> (bits))
+#define FB_BIT_NR(b)              (b)
 #endif
 
     /*