aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/fbmem.c
diff options
context:
space:
mode:
authorJames Hogan <james@albanarts.com>2010-10-27 18:33:28 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-27 21:03:08 -0400
commitf11b478d461b7113eb4603b3914aaf15b7788e87 (patch)
tree84e673927a071c64658d8b24ae423de86948b573 /drivers/video/fbmem.c
parentc9c62dce35e7fc54beebafb071393a0008989e49 (diff)
fbmem: fix fb_read, fb_write unaligned accesses
fb_{read,write} access the framebuffer using lots of fb_{read,write}l's but don't check that the file position is aligned which can cause problems on some architectures which do not support unaligned accesses. Since the operations are essentially memcpy_{from,to}io, new fb_memcpy_{from,to}fb macros have been defined and these are used instead. For Sparc, fb_{read,write} macros use sbus_{read,write}, so this defines new sbus_memcpy_{from,to}io functions the same as memcpy_{from,to}io but using sbus_{read,write}b instead of {read,write}b. Signed-off-by: James Hogan <james@albanarts.com> Acked-by: David S. Miller <davem@davemloft.net> Acked-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/video/fbmem.c')
-rw-r--r--drivers/video/fbmem.c46
1 files changed, 14 insertions, 32 deletions
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index a43442341ddd..0e6aa3d96a42 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -697,9 +697,9 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
697 struct inode *inode = file->f_path.dentry->d_inode; 697 struct inode *inode = file->f_path.dentry->d_inode;
698 int fbidx = iminor(inode); 698 int fbidx = iminor(inode);
699 struct fb_info *info = registered_fb[fbidx]; 699 struct fb_info *info = registered_fb[fbidx];
700 u32 *buffer, *dst; 700 u8 *buffer, *dst;
701 u32 __iomem *src; 701 u8 __iomem *src;
702 int c, i, cnt = 0, err = 0; 702 int c, cnt = 0, err = 0;
703 unsigned long total_size; 703 unsigned long total_size;
704 704
705 if (!info || ! info->screen_base) 705 if (!info || ! info->screen_base)
@@ -730,7 +730,7 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
730 if (!buffer) 730 if (!buffer)
731 return -ENOMEM; 731 return -ENOMEM;
732 732
733 src = (u32 __iomem *) (info->screen_base + p); 733 src = (u8 __iomem *) (info->screen_base + p);
734 734
735 if (info->fbops->fb_sync) 735 if (info->fbops->fb_sync)
736 info->fbops->fb_sync(info); 736 info->fbops->fb_sync(info);
@@ -738,17 +738,9 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
738 while (count) { 738 while (count) {
739 c = (count > PAGE_SIZE) ? PAGE_SIZE : count; 739 c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
740 dst = buffer; 740 dst = buffer;
741 for (i = c >> 2; i--; ) 741 fb_memcpy_fromfb(dst, src, c);
742 *dst++ = fb_readl(src++); 742 dst += c;
743 if (c & 3) { 743 src += c;
744 u8 *dst8 = (u8 *) dst;
745 u8 __iomem *src8 = (u8 __iomem *) src;
746
747 for (i = c & 3; i--;)
748 *dst8++ = fb_readb(src8++);
749
750 src = (u32 __iomem *) src8;
751 }
752 744
753 if (copy_to_user(buf, buffer, c)) { 745 if (copy_to_user(buf, buffer, c)) {
754 err = -EFAULT; 746 err = -EFAULT;
@@ -772,9 +764,9 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
772 struct inode *inode = file->f_path.dentry->d_inode; 764 struct inode *inode = file->f_path.dentry->d_inode;
773 int fbidx = iminor(inode); 765 int fbidx = iminor(inode);
774 struct fb_info *info = registered_fb[fbidx]; 766 struct fb_info *info = registered_fb[fbidx];
775 u32 *buffer, *src; 767 u8 *buffer, *src;
776 u32 __iomem *dst; 768 u8 __iomem *dst;
777 int c, i, cnt = 0, err = 0; 769 int c, cnt = 0, err = 0;
778 unsigned long total_size; 770 unsigned long total_size;
779 771
780 if (!info || !info->screen_base) 772 if (!info || !info->screen_base)
@@ -811,7 +803,7 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
811 if (!buffer) 803 if (!buffer)
812 return -ENOMEM; 804 return -ENOMEM;
813 805
814 dst = (u32 __iomem *) (info->screen_base + p); 806 dst = (u8 __iomem *) (info->screen_base + p);
815 807
816 if (info->fbops->fb_sync) 808 if (info->fbops->fb_sync)
817 info->fbops->fb_sync(info); 809 info->fbops->fb_sync(info);
@@ -825,19 +817,9 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
825 break; 817 break;
826 } 818 }
827 819
828 for (i = c >> 2; i--; ) 820 fb_memcpy_tofb(dst, src, c);
829 fb_writel(*src++, dst++); 821 dst += c;
830 822 src += c;
831 if (c & 3) {
832 u8 *src8 = (u8 *) src;
833 u8 __iomem *dst8 = (u8 __iomem *) dst;
834
835 for (i = c & 3; i--; )
836 fb_writeb(*src8++, dst8++);
837
838 dst = (u32 __iomem *) dst8;
839 }
840
841 *ppos += c; 823 *ppos += c;
842 buf += c; 824 buf += c;
843 cnt += c; 825 cnt += c;