| From 5b789da8a7fc357661fc61faaf853e9161cc9700 Mon Sep 17 00:00:00 2001 |
| From: Mikulas Patocka <mpatocka@redhat.com> |
| Date: Tue, 16 Sep 2014 12:38:53 -0400 |
| Subject: framebuffer: fix screen corruption when copying |
| |
| From: Mikulas Patocka <mpatocka@redhat.com> |
| |
| commit 5b789da8a7fc357661fc61faaf853e9161cc9700 upstream. |
| |
| The function bitcpy_rev has a bug that may result in screen corruption. |
| The bug happens under these conditions: |
| * the end of the destination area of a copy operation is aligned on a long |
| word boundary |
| * the end of the source area is not aligned on a long word boundary |
| * we are copying more than one long word |
| |
| In this case, the variable shift is non-zero and the variable first is |
| zero. The statements FB_WRITEL(comp(d0, FB_READL(dst), first), dst) reads |
| the last long word of the destination and writes it back unchanged |
| (because first is zero). Correctly, we should write the variable d0 to the |
| last word of the destination in this case. |
| |
| This patch fixes the bug by introducing and extra test if first is zero. |
| |
| The patch also removes the references to fb_memmove in the code that is |
| commented out because fb_memmove was removed from framebuffer subsystem. |
| |
| Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> |
| Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/video/fbdev/core/cfbcopyarea.c | 13 ++++++++----- |
| 1 file changed, 8 insertions(+), 5 deletions(-) |
| |
| --- a/drivers/video/fbdev/core/cfbcopyarea.c |
| +++ b/drivers/video/fbdev/core/cfbcopyarea.c |
| @@ -55,8 +55,8 @@ bitcpy(struct fb_info *p, unsigned long |
| * If you suspect bug in this function, compare it with this simple |
| * memmove implementation. |
| */ |
| - fb_memmove((char *)dst + ((dst_idx & (bits - 1))) / 8, |
| - (char *)src + ((src_idx & (bits - 1))) / 8, n / 8); |
| + memmove((char *)dst + ((dst_idx & (bits - 1))) / 8, |
| + (char *)src + ((src_idx & (bits - 1))) / 8, n / 8); |
| return; |
| #endif |
| |
| @@ -221,8 +221,8 @@ bitcpy_rev(struct fb_info *p, unsigned l |
| * If you suspect bug in this function, compare it with this simple |
| * memmove implementation. |
| */ |
| - fb_memmove((char *)dst + ((dst_idx & (bits - 1))) / 8, |
| - (char *)src + ((src_idx & (bits - 1))) / 8, n / 8); |
| + memmove((char *)dst + ((dst_idx & (bits - 1))) / 8, |
| + (char *)src + ((src_idx & (bits - 1))) / 8, n / 8); |
| return; |
| #endif |
| |
| @@ -324,7 +324,10 @@ bitcpy_rev(struct fb_info *p, unsigned l |
| d0 = d0 << left | d1 >> right; |
| } |
| d0 = fb_rev_pixels_in_long(d0, bswapmask); |
| - FB_WRITEL(comp(d0, FB_READL(dst), first), dst); |
| + if (!first) |
| + FB_WRITEL(d0, dst); |
| + else |
| + FB_WRITEL(comp(d0, FB_READL(dst), first), dst); |
| d0 = d1; |
| dst--; |
| n -= dst_idx+1; |