Message ID | 20230425142846.730-6-tzimmermann@suse.de (mailing list archive) |
---|---|
State | Not Applicable |
Headers | show |
Series | drm,fbdev: Use fbdev's I/O helpers | expand |
Thomas Zimmermann <tzimmermann@suse.de> writes: > Move the existing CFB read and write code for I/O memory into > the new helpers fb_cfb_read() and fb_cfb_write(). Make them the > default fp_ops. No functional changes. > It would be nice to get an explanation here about why moving these make sense. I guess you are doing this because is going to be used in DRM but still would be good to explain it in the commit message. > Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> > --- Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Hi Thomas, kernel test robot noticed the following build warnings: [auto build test WARNING on drm-misc/drm-misc-next] [also build test WARNING on linus/master next-20230425] [cannot apply to v6.3] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Thomas-Zimmermann/fbdev-Return-number-of-bytes-read-or-written/20230425-223011 base: git://anongit.freedesktop.org/drm/drm-misc drm-misc-next patch link: https://lore.kernel.org/r/20230425142846.730-6-tzimmermann%40suse.de patch subject: [PATCH 5/6] fbdev: Move CFB read and write code into helper functions config: riscv-randconfig-s033-20230423 (https://download.01.org/0day-ci/archive/20230426/202304261317.QAEwArcB-lkp@intel.com/config) compiler: riscv64-linux-gcc (GCC) 12.1.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # apt-get install sparse # sparse version: v0.6.4-39-gce1a6720-dirty # https://github.com/intel-lab-lkp/linux/commit/d4a150f3dfa8e73f2e92f1c7efc9271e17632cc2 git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Thomas-Zimmermann/fbdev-Return-number-of-bytes-read-or-written/20230425-223011 git checkout d4a150f3dfa8e73f2e92f1c7efc9271e17632cc2 # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=riscv olddefconfig COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=riscv SHELL=/bin/bash drivers/video/fbdev/core/ If you fix the issue, kindly add following tag where applicable | Reported-by: kernel test robot <lkp@intel.com> | Link: https://lore.kernel.org/oe-kbuild-all/202304261317.QAEwArcB-lkp@intel.com/ sparse warnings: (new ones prefixed by >>) WARNING: invalid argument to '-march': '_zihintpause' >> drivers/video/fbdev/core/fb_cfb_fops.c:44:39: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected void const * @@ got unsigned char [noderef] [usertype] __iomem *[assigned] src @@ drivers/video/fbdev/core/fb_cfb_fops.c:44:39: sparse: expected void const * drivers/video/fbdev/core/fb_cfb_fops.c:44:39: sparse: got unsigned char [noderef] [usertype] __iomem *[assigned] src >> drivers/video/fbdev/core/fb_cfb_fops.c:113:32: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void * @@ got unsigned char [noderef] [usertype] __iomem *[assigned] dst @@ drivers/video/fbdev/core/fb_cfb_fops.c:113:32: sparse: expected void * drivers/video/fbdev/core/fb_cfb_fops.c:113:32: sparse: got unsigned char [noderef] [usertype] __iomem *[assigned] dst vim +44 drivers/video/fbdev/core/fb_cfb_fops.c 6 7 ssize_t fb_cfb_read(struct fb_info *info, char __user *buf, size_t count, loff_t *ppos) 8 { 9 unsigned long p = *ppos; 10 u8 *buffer, *dst; 11 u8 __iomem *src; 12 int c, cnt = 0, err = 0; 13 unsigned long total_size; 14 15 if (!info->screen_base) 16 return -ENODEV; 17 18 total_size = info->screen_size; 19 20 if (total_size == 0) 21 total_size = info->fix.smem_len; 22 23 if (p >= total_size) 24 return 0; 25 26 if (count >= total_size) 27 count = total_size; 28 29 if (count + p > total_size) 30 count = total_size - p; 31 32 buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL); 33 if (!buffer) 34 return -ENOMEM; 35 36 src = (u8 __iomem *)(info->screen_base + p); 37 38 if (info->fbops->fb_sync) 39 info->fbops->fb_sync(info); 40 41 while (count) { 42 c = (count > PAGE_SIZE) ? PAGE_SIZE : count; 43 dst = buffer; > 44 fb_memcpy_fromfb(dst, src, c); 45 dst += c; 46 src += c; 47 48 if (copy_to_user(buf, buffer, c)) { 49 err = -EFAULT; 50 break; 51 } 52 *ppos += c; 53 buf += c; 54 cnt += c; 55 count -= c; 56 } 57 58 kfree(buffer); 59 60 return cnt ? cnt : err; 61 } 62 EXPORT_SYMBOL(fb_cfb_read); 63 64 ssize_t fb_cfb_write(struct fb_info *info, const char __user *buf, size_t count, loff_t *ppos) 65 { 66 unsigned long p = *ppos; 67 u8 *buffer, *src; 68 u8 __iomem *dst; 69 int c, cnt = 0, err = 0; 70 unsigned long total_size; 71 72 if (!info->screen_base) 73 return -ENODEV; 74 75 total_size = info->screen_size; 76 77 if (total_size == 0) 78 total_size = info->fix.smem_len; 79 80 if (p > total_size) 81 return -EFBIG; 82 83 if (count > total_size) { 84 err = -EFBIG; 85 count = total_size; 86 } 87 88 if (count + p > total_size) { 89 if (!err) 90 err = -ENOSPC; 91 92 count = total_size - p; 93 } 94 95 buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL); 96 if (!buffer) 97 return -ENOMEM; 98 99 dst = (u8 __iomem *)(info->screen_base + p); 100 101 if (info->fbops->fb_sync) 102 info->fbops->fb_sync(info); 103 104 while (count) { 105 c = (count > PAGE_SIZE) ? PAGE_SIZE : count; 106 src = buffer; 107 108 if (copy_from_user(src, buf, c)) { 109 err = -EFAULT; 110 break; 111 } 112 > 113 fb_memcpy_tofb(dst, src, c);
Hi Thomas, kernel test robot noticed the following build warnings: [auto build test WARNING on drm-misc/drm-misc-next] [also build test WARNING on linus/master next-20230425] [cannot apply to v6.3] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Thomas-Zimmermann/fbdev-Return-number-of-bytes-read-or-written/20230425-223011 base: git://anongit.freedesktop.org/drm/drm-misc drm-misc-next patch link: https://lore.kernel.org/r/20230425142846.730-6-tzimmermann%40suse.de patch subject: [PATCH 5/6] fbdev: Move CFB read and write code into helper functions config: nios2-randconfig-s031-20230423 (https://download.01.org/0day-ci/archive/20230426/202304261333.9giYEbEl-lkp@intel.com/config) compiler: nios2-linux-gcc (GCC) 12.1.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # apt-get install sparse # sparse version: v0.6.4-39-gce1a6720-dirty # https://github.com/intel-lab-lkp/linux/commit/d4a150f3dfa8e73f2e92f1c7efc9271e17632cc2 git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Thomas-Zimmermann/fbdev-Return-number-of-bytes-read-or-written/20230425-223011 git checkout d4a150f3dfa8e73f2e92f1c7efc9271e17632cc2 # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=nios2 olddefconfig COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=nios2 SHELL=/bin/bash drivers/video/fbdev/core/ If you fix the issue, kindly add following tag where applicable | Reported-by: kernel test robot <lkp@intel.com> | Link: https://lore.kernel.org/oe-kbuild-all/202304261333.9giYEbEl-lkp@intel.com/ sparse warnings: (new ones prefixed by >>) >> drivers/video/fbdev/core/fb_cfb_fops.c:44:39: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected void const *s @@ got unsigned char [noderef] [usertype] __iomem *[assigned] src @@ drivers/video/fbdev/core/fb_cfb_fops.c:44:39: sparse: expected void const *s drivers/video/fbdev/core/fb_cfb_fops.c:44:39: sparse: got unsigned char [noderef] [usertype] __iomem *[assigned] src >> drivers/video/fbdev/core/fb_cfb_fops.c:113:32: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *d @@ got unsigned char [noderef] [usertype] __iomem *[assigned] dst @@ drivers/video/fbdev/core/fb_cfb_fops.c:113:32: sparse: expected void *d drivers/video/fbdev/core/fb_cfb_fops.c:113:32: sparse: got unsigned char [noderef] [usertype] __iomem *[assigned] dst vim +44 drivers/video/fbdev/core/fb_cfb_fops.c 6 7 ssize_t fb_cfb_read(struct fb_info *info, char __user *buf, size_t count, loff_t *ppos) 8 { 9 unsigned long p = *ppos; 10 u8 *buffer, *dst; 11 u8 __iomem *src; 12 int c, cnt = 0, err = 0; 13 unsigned long total_size; 14 15 if (!info->screen_base) 16 return -ENODEV; 17 18 total_size = info->screen_size; 19 20 if (total_size == 0) 21 total_size = info->fix.smem_len; 22 23 if (p >= total_size) 24 return 0; 25 26 if (count >= total_size) 27 count = total_size; 28 29 if (count + p > total_size) 30 count = total_size - p; 31 32 buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL); 33 if (!buffer) 34 return -ENOMEM; 35 36 src = (u8 __iomem *)(info->screen_base + p); 37 38 if (info->fbops->fb_sync) 39 info->fbops->fb_sync(info); 40 41 while (count) { 42 c = (count > PAGE_SIZE) ? PAGE_SIZE : count; 43 dst = buffer; > 44 fb_memcpy_fromfb(dst, src, c); 45 dst += c; 46 src += c; 47 48 if (copy_to_user(buf, buffer, c)) { 49 err = -EFAULT; 50 break; 51 } 52 *ppos += c; 53 buf += c; 54 cnt += c; 55 count -= c; 56 } 57 58 kfree(buffer); 59 60 return cnt ? cnt : err; 61 } 62 EXPORT_SYMBOL(fb_cfb_read); 63 64 ssize_t fb_cfb_write(struct fb_info *info, const char __user *buf, size_t count, loff_t *ppos) 65 { 66 unsigned long p = *ppos; 67 u8 *buffer, *src; 68 u8 __iomem *dst; 69 int c, cnt = 0, err = 0; 70 unsigned long total_size; 71 72 if (!info->screen_base) 73 return -ENODEV; 74 75 total_size = info->screen_size; 76 77 if (total_size == 0) 78 total_size = info->fix.smem_len; 79 80 if (p > total_size) 81 return -EFBIG; 82 83 if (count > total_size) { 84 err = -EFBIG; 85 count = total_size; 86 } 87 88 if (count + p > total_size) { 89 if (!err) 90 err = -ENOSPC; 91 92 count = total_size - p; 93 } 94 95 buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL); 96 if (!buffer) 97 return -ENOMEM; 98 99 dst = (u8 __iomem *)(info->screen_base + p); 100 101 if (info->fbops->fb_sync) 102 info->fbops->fb_sync(info); 103 104 while (count) { 105 c = (count > PAGE_SIZE) ? PAGE_SIZE : count; 106 src = buffer; 107 108 if (copy_from_user(src, buf, c)) { 109 err = -EFAULT; 110 break; 111 } 112 > 113 fb_memcpy_tofb(dst, src, c);
Hi Thomas, kernel test robot noticed the following build warnings: [auto build test WARNING on drm-misc/drm-misc-next] [also build test WARNING on linus/master next-20230425] [cannot apply to v6.3] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Thomas-Zimmermann/fbdev-Return-number-of-bytes-read-or-written/20230425-223011 base: git://anongit.freedesktop.org/drm/drm-misc drm-misc-next patch link: https://lore.kernel.org/r/20230425142846.730-6-tzimmermann%40suse.de patch subject: [PATCH 5/6] fbdev: Move CFB read and write code into helper functions config: openrisc-randconfig-s052-20230423 (https://download.01.org/0day-ci/archive/20230426/202304261419.LvfW9HTa-lkp@intel.com/config) compiler: or1k-linux-gcc (GCC) 12.1.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # apt-get install sparse # sparse version: v0.6.4-39-gce1a6720-dirty # https://github.com/intel-lab-lkp/linux/commit/d4a150f3dfa8e73f2e92f1c7efc9271e17632cc2 git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Thomas-Zimmermann/fbdev-Return-number-of-bytes-read-or-written/20230425-223011 git checkout d4a150f3dfa8e73f2e92f1c7efc9271e17632cc2 # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=openrisc olddefconfig COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=openrisc SHELL=/bin/bash drivers/video/fbdev/core/ If you fix the issue, kindly add following tag where applicable | Reported-by: kernel test robot <lkp@intel.com> | Link: https://lore.kernel.org/oe-kbuild-all/202304261419.LvfW9HTa-lkp@intel.com/ sparse warnings: (new ones prefixed by >>) >> drivers/video/fbdev/core/fb_cfb_fops.c:44:39: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected void const *src @@ got unsigned char [noderef] [usertype] __iomem *[assigned] src @@ drivers/video/fbdev/core/fb_cfb_fops.c:44:39: sparse: expected void const *src drivers/video/fbdev/core/fb_cfb_fops.c:44:39: sparse: got unsigned char [noderef] [usertype] __iomem *[assigned] src >> drivers/video/fbdev/core/fb_cfb_fops.c:113:32: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void *dest @@ got unsigned char [noderef] [usertype] __iomem *[assigned] dst @@ drivers/video/fbdev/core/fb_cfb_fops.c:113:32: sparse: expected void *dest drivers/video/fbdev/core/fb_cfb_fops.c:113:32: sparse: got unsigned char [noderef] [usertype] __iomem *[assigned] dst vim +44 drivers/video/fbdev/core/fb_cfb_fops.c 6 7 ssize_t fb_cfb_read(struct fb_info *info, char __user *buf, size_t count, loff_t *ppos) 8 { 9 unsigned long p = *ppos; 10 u8 *buffer, *dst; 11 u8 __iomem *src; 12 int c, cnt = 0, err = 0; 13 unsigned long total_size; 14 15 if (!info->screen_base) 16 return -ENODEV; 17 18 total_size = info->screen_size; 19 20 if (total_size == 0) 21 total_size = info->fix.smem_len; 22 23 if (p >= total_size) 24 return 0; 25 26 if (count >= total_size) 27 count = total_size; 28 29 if (count + p > total_size) 30 count = total_size - p; 31 32 buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL); 33 if (!buffer) 34 return -ENOMEM; 35 36 src = (u8 __iomem *)(info->screen_base + p); 37 38 if (info->fbops->fb_sync) 39 info->fbops->fb_sync(info); 40 41 while (count) { 42 c = (count > PAGE_SIZE) ? PAGE_SIZE : count; 43 dst = buffer; > 44 fb_memcpy_fromfb(dst, src, c); 45 dst += c; 46 src += c; 47 48 if (copy_to_user(buf, buffer, c)) { 49 err = -EFAULT; 50 break; 51 } 52 *ppos += c; 53 buf += c; 54 cnt += c; 55 count -= c; 56 } 57 58 kfree(buffer); 59 60 return cnt ? cnt : err; 61 } 62 EXPORT_SYMBOL(fb_cfb_read); 63 64 ssize_t fb_cfb_write(struct fb_info *info, const char __user *buf, size_t count, loff_t *ppos) 65 { 66 unsigned long p = *ppos; 67 u8 *buffer, *src; 68 u8 __iomem *dst; 69 int c, cnt = 0, err = 0; 70 unsigned long total_size; 71 72 if (!info->screen_base) 73 return -ENODEV; 74 75 total_size = info->screen_size; 76 77 if (total_size == 0) 78 total_size = info->fix.smem_len; 79 80 if (p > total_size) 81 return -EFBIG; 82 83 if (count > total_size) { 84 err = -EFBIG; 85 count = total_size; 86 } 87 88 if (count + p > total_size) { 89 if (!err) 90 err = -ENOSPC; 91 92 count = total_size - p; 93 } 94 95 buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL); 96 if (!buffer) 97 return -ENOMEM; 98 99 dst = (u8 __iomem *)(info->screen_base + p); 100 101 if (info->fbops->fb_sync) 102 info->fbops->fb_sync(info); 103 104 while (count) { 105 c = (count > PAGE_SIZE) ? PAGE_SIZE : count; 106 src = buffer; 107 108 if (copy_from_user(src, buf, c)) { 109 err = -EFAULT; 110 break; 111 } 112 > 113 fb_memcpy_tofb(dst, src, c);
Tested-by: Sui Jingfeng <suijingfeng@loongson.cn> On 2023/4/25 22:28, Thomas Zimmermann wrote: > Move the existing CFB read and write code for I/O memory into > the new helpers fb_cfb_read() and fb_cfb_write(). Make them the > default fp_ops. No functional changes. > > Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> > Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> > --- > drivers/video/fbdev/core/Makefile | 2 +- > drivers/video/fbdev/core/fb_cfb_fops.c | 126 +++++++++++++++++++++++++ > drivers/video/fbdev/core/fbmem.c | 113 +--------------------- > include/linux/fb.h | 10 ++ > 4 files changed, 139 insertions(+), 112 deletions(-) > create mode 100644 drivers/video/fbdev/core/fb_cfb_fops.c > > diff --git a/drivers/video/fbdev/core/Makefile b/drivers/video/fbdev/core/Makefile > index 08fabce76b74..cb7534a80305 100644 > --- a/drivers/video/fbdev/core/Makefile > +++ b/drivers/video/fbdev/core/Makefile > @@ -2,7 +2,7 @@ > obj-$(CONFIG_FB_NOTIFY) += fb_notify.o > obj-$(CONFIG_FB) += fb.o > fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \ > - modedb.o fbcvt.o fb_cmdline.o > + modedb.o fbcvt.o fb_cmdline.o fb_cfb_fops.o > fb-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o > > ifeq ($(CONFIG_FRAMEBUFFER_CONSOLE),y) > diff --git a/drivers/video/fbdev/core/fb_cfb_fops.c b/drivers/video/fbdev/core/fb_cfb_fops.c > new file mode 100644 > index 000000000000..f6000166eda4 > --- /dev/null > +++ b/drivers/video/fbdev/core/fb_cfb_fops.c > @@ -0,0 +1,126 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +#include <linux/fb.h> > +#include <linux/module.h> > +#include <linux/uaccess.h> > + > +ssize_t fb_cfb_read(struct fb_info *info, char __user *buf, size_t count, loff_t *ppos) > +{ > + unsigned long p = *ppos; > + u8 *buffer, *dst; > + u8 __iomem *src; > + int c, cnt = 0, err = 0; > + unsigned long total_size; > + > + if (!info->screen_base) > + return -ENODEV; > + > + total_size = info->screen_size; > + > + if (total_size == 0) > + total_size = info->fix.smem_len; > + > + if (p >= total_size) > + return 0; > + > + if (count >= total_size) > + count = total_size; > + > + if (count + p > total_size) > + count = total_size - p; > + > + buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL); > + if (!buffer) > + return -ENOMEM; > + > + src = (u8 __iomem *)(info->screen_base + p); > + > + if (info->fbops->fb_sync) > + info->fbops->fb_sync(info); > + > + while (count) { > + c = (count > PAGE_SIZE) ? PAGE_SIZE : count; > + dst = buffer; > + fb_memcpy_fromfb(dst, src, c); > + dst += c; > + src += c; > + > + if (copy_to_user(buf, buffer, c)) { > + err = -EFAULT; > + break; > + } > + *ppos += c; > + buf += c; > + cnt += c; > + count -= c; > + } > + > + kfree(buffer); > + > + return cnt ? cnt : err; > +} > +EXPORT_SYMBOL(fb_cfb_read); > + > +ssize_t fb_cfb_write(struct fb_info *info, const char __user *buf, size_t count, loff_t *ppos) > +{ > + unsigned long p = *ppos; > + u8 *buffer, *src; > + u8 __iomem *dst; > + int c, cnt = 0, err = 0; > + unsigned long total_size; > + > + if (!info->screen_base) > + return -ENODEV; > + > + total_size = info->screen_size; > + > + if (total_size == 0) > + total_size = info->fix.smem_len; > + > + if (p > total_size) > + return -EFBIG; > + > + if (count > total_size) { > + err = -EFBIG; > + count = total_size; > + } > + > + if (count + p > total_size) { > + if (!err) > + err = -ENOSPC; > + > + count = total_size - p; > + } > + > + buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL); > + if (!buffer) > + return -ENOMEM; > + > + dst = (u8 __iomem *)(info->screen_base + p); > + > + if (info->fbops->fb_sync) > + info->fbops->fb_sync(info); > + > + while (count) { > + c = (count > PAGE_SIZE) ? PAGE_SIZE : count; > + src = buffer; > + > + if (copy_from_user(src, buf, c)) { > + err = -EFAULT; > + break; > + } > + > + fb_memcpy_tofb(dst, src, c); > + dst += c; > + src += c; > + *ppos += c; > + buf += c; > + cnt += c; > + count -= c; > + } > + > + kfree(buffer); > + > + return (cnt) ? cnt : err; > +} > +EXPORT_SYMBOL(fb_cfb_write); > diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c > index b993bb97058f..be6c75f3dfd0 100644 > --- a/drivers/video/fbdev/core/fbmem.c > +++ b/drivers/video/fbdev/core/fbmem.c > @@ -761,12 +761,7 @@ static struct fb_info *file_fb_info(struct file *file) > static ssize_t > fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) > { > - unsigned long p = *ppos; > struct fb_info *info = file_fb_info(file); > - u8 *buffer, *dst; > - u8 __iomem *src; > - int c, cnt = 0, err = 0; > - unsigned long total_size; > > if (!info) > return -ENODEV; > @@ -777,64 +772,13 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) > if (info->fbops->fb_read) > return info->fbops->fb_read(info, buf, count, ppos); > > - if (!info->screen_base) > - return -ENODEV; > - > - total_size = info->screen_size; > - > - if (total_size == 0) > - total_size = info->fix.smem_len; > - > - if (p >= total_size) > - return 0; > - > - if (count >= total_size) > - count = total_size; > - > - if (count + p > total_size) > - count = total_size - p; > - > - buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, > - GFP_KERNEL); > - if (!buffer) > - return -ENOMEM; > - > - src = (u8 __iomem *) (info->screen_base + p); > - > - if (info->fbops->fb_sync) > - info->fbops->fb_sync(info); > - > - while (count) { > - c = (count > PAGE_SIZE) ? PAGE_SIZE : count; > - dst = buffer; > - fb_memcpy_fromfb(dst, src, c); > - dst += c; > - src += c; > - > - if (copy_to_user(buf, buffer, c)) { > - err = -EFAULT; > - break; > - } > - *ppos += c; > - buf += c; > - cnt += c; > - count -= c; > - } > - > - kfree(buffer); > - > - return cnt ? cnt : err; > + return fb_cfb_read(info, buf, count, ppos); > } > > static ssize_t > fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) > { > - unsigned long p = *ppos; > struct fb_info *info = file_fb_info(file); > - u8 *buffer, *src; > - u8 __iomem *dst; > - int c, cnt = 0, err = 0; > - unsigned long total_size; > > if (!info) > return -ENODEV; > @@ -845,60 +789,7 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) > if (info->fbops->fb_write) > return info->fbops->fb_write(info, buf, count, ppos); > > - if (!info->screen_base) > - return -ENODEV; > - > - total_size = info->screen_size; > - > - if (total_size == 0) > - total_size = info->fix.smem_len; > - > - if (p > total_size) > - return -EFBIG; > - > - if (count > total_size) { > - err = -EFBIG; > - count = total_size; > - } > - > - if (count + p > total_size) { > - if (!err) > - err = -ENOSPC; > - > - count = total_size - p; > - } > - > - buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, > - GFP_KERNEL); > - if (!buffer) > - return -ENOMEM; > - > - dst = (u8 __iomem *) (info->screen_base + p); > - > - if (info->fbops->fb_sync) > - info->fbops->fb_sync(info); > - > - while (count) { > - c = (count > PAGE_SIZE) ? PAGE_SIZE : count; > - src = buffer; > - > - if (copy_from_user(src, buf, c)) { > - err = -EFAULT; > - break; > - } > - > - fb_memcpy_tofb(dst, src, c); > - dst += c; > - src += c; > - *ppos += c; > - buf += c; > - cnt += c; > - count -= c; > - } > - > - kfree(buffer); > - > - return (cnt) ? cnt : err; > + return fb_cfb_write(info, buf, count, ppos); > } > > int > diff --git a/include/linux/fb.h b/include/linux/fb.h > index 08cb47da71f8..3b1644c79973 100644 > --- a/include/linux/fb.h > +++ b/include/linux/fb.h > @@ -576,9 +576,19 @@ struct fb_info { > extern int fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var); > extern int fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var); > extern int fb_blank(struct fb_info *info, int blank); > + > +/* > + * Drawing operations where framebuffer is in video RAM > + */ > + > extern void cfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect); > extern void cfb_copyarea(struct fb_info *info, const struct fb_copyarea *area); > extern void cfb_imageblit(struct fb_info *info, const struct fb_image *image); > +extern ssize_t fb_cfb_read(struct fb_info *info, char __user *buf, size_t count, > + loff_t *ppos); > +extern ssize_t fb_cfb_write(struct fb_info *info, const char __user *buf, > + size_t count, loff_t *ppos); > + > /* > * Drawing operations where framebuffer is in system RAM > */
Hi Am 26.04.23 um 07:16 schrieb kernel test robot: > Hi Thomas, > > kernel test robot noticed the following build warnings: FYI these errors come from systems that use volatile __iomem pointers with plain memcpy(). See my patchset at [1] for an improvement. Best regards Thomas [1] https://patchwork.freedesktop.org/series/116985/ > > [auto build test WARNING on drm-misc/drm-misc-next] > [also build test WARNING on linus/master next-20230425] > [cannot apply to v6.3] > [If your patch is applied to the wrong git tree, kindly drop us a note. > And when submitting patch, we suggest to use '--base' as documented in > https://git-scm.com/docs/git-format-patch#_base_tree_information] > > url: https://github.com/intel-lab-lkp/linux/commits/Thomas-Zimmermann/fbdev-Return-number-of-bytes-read-or-written/20230425-223011 > base: git://anongit.freedesktop.org/drm/drm-misc drm-misc-next > patch link: https://lore.kernel.org/r/20230425142846.730-6-tzimmermann%40suse.de > patch subject: [PATCH 5/6] fbdev: Move CFB read and write code into helper functions > config: riscv-randconfig-s033-20230423 (https://download.01.org/0day-ci/archive/20230426/202304261317.QAEwArcB-lkp@intel.com/config) > compiler: riscv64-linux-gcc (GCC) 12.1.0 > reproduce: > wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross > chmod +x ~/bin/make.cross > # apt-get install sparse > # sparse version: v0.6.4-39-gce1a6720-dirty > # https://github.com/intel-lab-lkp/linux/commit/d4a150f3dfa8e73f2e92f1c7efc9271e17632cc2 > git remote add linux-review https://github.com/intel-lab-lkp/linux > git fetch --no-tags linux-review Thomas-Zimmermann/fbdev-Return-number-of-bytes-read-or-written/20230425-223011 > git checkout d4a150f3dfa8e73f2e92f1c7efc9271e17632cc2 > # save the config file > mkdir build_dir && cp config build_dir/.config > COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=riscv olddefconfig > COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=riscv SHELL=/bin/bash drivers/video/fbdev/core/ > > If you fix the issue, kindly add following tag where applicable > | Reported-by: kernel test robot <lkp@intel.com> > | Link: https://lore.kernel.org/oe-kbuild-all/202304261317.QAEwArcB-lkp@intel.com/ > > sparse warnings: (new ones prefixed by >>) > WARNING: invalid argument to '-march': '_zihintpause' >>> drivers/video/fbdev/core/fb_cfb_fops.c:44:39: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected void const * @@ got unsigned char [noderef] [usertype] __iomem *[assigned] src @@ > drivers/video/fbdev/core/fb_cfb_fops.c:44:39: sparse: expected void const * > drivers/video/fbdev/core/fb_cfb_fops.c:44:39: sparse: got unsigned char [noderef] [usertype] __iomem *[assigned] src >>> drivers/video/fbdev/core/fb_cfb_fops.c:113:32: sparse: sparse: incorrect type in argument 1 (different address spaces) @@ expected void * @@ got unsigned char [noderef] [usertype] __iomem *[assigned] dst @@ > drivers/video/fbdev/core/fb_cfb_fops.c:113:32: sparse: expected void * > drivers/video/fbdev/core/fb_cfb_fops.c:113:32: sparse: got unsigned char [noderef] [usertype] __iomem *[assigned] dst > > vim +44 drivers/video/fbdev/core/fb_cfb_fops.c > > 6 > 7 ssize_t fb_cfb_read(struct fb_info *info, char __user *buf, size_t count, loff_t *ppos) > 8 { > 9 unsigned long p = *ppos; > 10 u8 *buffer, *dst; > 11 u8 __iomem *src; > 12 int c, cnt = 0, err = 0; > 13 unsigned long total_size; > 14 > 15 if (!info->screen_base) > 16 return -ENODEV; > 17 > 18 total_size = info->screen_size; > 19 > 20 if (total_size == 0) > 21 total_size = info->fix.smem_len; > 22 > 23 if (p >= total_size) > 24 return 0; > 25 > 26 if (count >= total_size) > 27 count = total_size; > 28 > 29 if (count + p > total_size) > 30 count = total_size - p; > 31 > 32 buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL); > 33 if (!buffer) > 34 return -ENOMEM; > 35 > 36 src = (u8 __iomem *)(info->screen_base + p); > 37 > 38 if (info->fbops->fb_sync) > 39 info->fbops->fb_sync(info); > 40 > 41 while (count) { > 42 c = (count > PAGE_SIZE) ? PAGE_SIZE : count; > 43 dst = buffer; > > 44 fb_memcpy_fromfb(dst, src, c); > 45 dst += c; > 46 src += c; > 47 > 48 if (copy_to_user(buf, buffer, c)) { > 49 err = -EFAULT; > 50 break; > 51 } > 52 *ppos += c; > 53 buf += c; > 54 cnt += c; > 55 count -= c; > 56 } > 57 > 58 kfree(buffer); > 59 > 60 return cnt ? cnt : err; > 61 } > 62 EXPORT_SYMBOL(fb_cfb_read); > 63 > 64 ssize_t fb_cfb_write(struct fb_info *info, const char __user *buf, size_t count, loff_t *ppos) > 65 { > 66 unsigned long p = *ppos; > 67 u8 *buffer, *src; > 68 u8 __iomem *dst; > 69 int c, cnt = 0, err = 0; > 70 unsigned long total_size; > 71 > 72 if (!info->screen_base) > 73 return -ENODEV; > 74 > 75 total_size = info->screen_size; > 76 > 77 if (total_size == 0) > 78 total_size = info->fix.smem_len; > 79 > 80 if (p > total_size) > 81 return -EFBIG; > 82 > 83 if (count > total_size) { > 84 err = -EFBIG; > 85 count = total_size; > 86 } > 87 > 88 if (count + p > total_size) { > 89 if (!err) > 90 err = -ENOSPC; > 91 > 92 count = total_size - p; > 93 } > 94 > 95 buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL); > 96 if (!buffer) > 97 return -ENOMEM; > 98 > 99 dst = (u8 __iomem *)(info->screen_base + p); > 100 > 101 if (info->fbops->fb_sync) > 102 info->fbops->fb_sync(info); > 103 > 104 while (count) { > 105 c = (count > PAGE_SIZE) ? PAGE_SIZE : count; > 106 src = buffer; > 107 > 108 if (copy_from_user(src, buf, c)) { > 109 err = -EFAULT; > 110 break; > 111 } > 112 > > 113 fb_memcpy_tofb(dst, src, c); >
Hi Thomas, On Tue, Apr 25, 2023 at 4:28 PM Thomas Zimmermann <tzimmermann@suse.de> wrote: > Move the existing CFB read and write code for I/O memory into > the new helpers fb_cfb_read() and fb_cfb_write(). Make them the > default fp_ops. No functional changes. > > Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> > --- > drivers/video/fbdev/core/Makefile | 2 +- > drivers/video/fbdev/core/fb_cfb_fops.c | 126 +++++++++++++++++++++++++ > drivers/video/fbdev/core/fbmem.c | 113 +--------------------- > include/linux/fb.h | 10 ++ > 4 files changed, 139 insertions(+), 112 deletions(-) > create mode 100644 drivers/video/fbdev/core/fb_cfb_fops.c While the general idea is fine, please do not call any of this "cfb", as it is not related to chunky color frame buffer formats. All of these operate on the raw frame buffer contents. > --- /dev/null > +++ b/drivers/video/fbdev/core/fb_cfb_fops.c > @@ -0,0 +1,126 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +#include <linux/fb.h> > +#include <linux/module.h> > +#include <linux/uaccess.h> > + > +ssize_t fb_cfb_read(struct fb_info *info, char __user *buf, size_t count, loff_t *ppos) > +{ [...] > + while (count) { > + c = (count > PAGE_SIZE) ? PAGE_SIZE : count; > + dst = buffer; > + fb_memcpy_fromfb(dst, src, c); > + dst += c; > + src += c; > + > + if (copy_to_user(buf, buffer, c)) { So here's still the buggy copy_to_user() handling, copied from fb_read(). > + err = -EFAULT; > + break; > + } > + *ppos += c; > + buf += c; > + cnt += c; > + count -= c; > + } > + > + kfree(buffer); > + > + return cnt ? cnt : err; > +} > +EXPORT_SYMBOL(fb_cfb_read); > + > +ssize_t fb_cfb_write(struct fb_info *info, const char __user *buf, size_t count, loff_t *ppos) > +{ [...] > + while (count) { > + c = (count > PAGE_SIZE) ? PAGE_SIZE : count; > + src = buffer; > + > + if (copy_from_user(src, buf, c)) { And copy_from_user(), too... > + err = -EFAULT; > + break; > + } > + > + fb_memcpy_tofb(dst, src, c); > + dst += c; > + src += c; > + *ppos += c; > + buf += c; > + cnt += c; > + count -= c; > + } > + > + kfree(buffer); > + > + return (cnt) ? cnt : err; > +} Gr{oetje,eeting}s, Geert
Hi Am 26.04.23 um 17:01 schrieb Geert Uytterhoeven: > Hi Thomas, > > On Tue, Apr 25, 2023 at 4:28 PM Thomas Zimmermann <tzimmermann@suse.de> wrote: >> Move the existing CFB read and write code for I/O memory into >> the new helpers fb_cfb_read() and fb_cfb_write(). Make them the >> default fp_ops. No functional changes. >> >> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> >> --- >> drivers/video/fbdev/core/Makefile | 2 +- >> drivers/video/fbdev/core/fb_cfb_fops.c | 126 +++++++++++++++++++++++++ >> drivers/video/fbdev/core/fbmem.c | 113 +--------------------- >> include/linux/fb.h | 10 ++ >> 4 files changed, 139 insertions(+), 112 deletions(-) >> create mode 100644 drivers/video/fbdev/core/fb_cfb_fops.c > > While the general idea is fine, please do not call any of this "cfb", > as it is not related to chunky color frame buffer formats. > All of these operate on the raw frame buffer contents. Shall I call it fb_raw_() or fb_io_()? CFB is used by the drawing helpers, which are usually used together with this code. Hence the current naming. Best regards Thomas > >> --- /dev/null >> +++ b/drivers/video/fbdev/core/fb_cfb_fops.c >> @@ -0,0 +1,126 @@ >> +// SPDX-License-Identifier: GPL-2.0 >> + >> +#include <linux/fb.h> >> +#include <linux/module.h> >> +#include <linux/uaccess.h> >> + >> +ssize_t fb_cfb_read(struct fb_info *info, char __user *buf, size_t count, loff_t *ppos) >> +{ > > [...] > >> + while (count) { >> + c = (count > PAGE_SIZE) ? PAGE_SIZE : count; >> + dst = buffer; >> + fb_memcpy_fromfb(dst, src, c); >> + dst += c; >> + src += c; >> + >> + if (copy_to_user(buf, buffer, c)) { > > So here's still the buggy copy_to_user() handling, copied from fb_read(). > >> + err = -EFAULT; >> + break; >> + } >> + *ppos += c; >> + buf += c; >> + cnt += c; >> + count -= c; >> + } >> + >> + kfree(buffer); >> + >> + return cnt ? cnt : err; >> +} >> +EXPORT_SYMBOL(fb_cfb_read); >> + >> +ssize_t fb_cfb_write(struct fb_info *info, const char __user *buf, size_t count, loff_t *ppos) >> +{ > > [...] > >> + while (count) { >> + c = (count > PAGE_SIZE) ? PAGE_SIZE : count; >> + src = buffer; >> + >> + if (copy_from_user(src, buf, c)) { > > And copy_from_user(), too... > >> + err = -EFAULT; >> + break; >> + } >> + >> + fb_memcpy_tofb(dst, src, c); >> + dst += c; >> + src += c; >> + *ppos += c; >> + buf += c; >> + cnt += c; >> + count -= c; >> + } >> + >> + kfree(buffer); >> + >> + return (cnt) ? cnt : err; >> +} > > Gr{oetje,eeting}s, > > Geert >
Hi Thomas, On Wed, Apr 26, 2023 at 5:06 PM Thomas Zimmermann <tzimmermann@suse.de> wrote: > Am 26.04.23 um 17:01 schrieb Geert Uytterhoeven: > > On Tue, Apr 25, 2023 at 4:28 PM Thomas Zimmermann <tzimmermann@suse.de> wrote: > >> Move the existing CFB read and write code for I/O memory into > >> the new helpers fb_cfb_read() and fb_cfb_write(). Make them the > >> default fp_ops. No functional changes. > >> > >> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> > >> --- > >> drivers/video/fbdev/core/Makefile | 2 +- > >> drivers/video/fbdev/core/fb_cfb_fops.c | 126 +++++++++++++++++++++++++ > >> drivers/video/fbdev/core/fbmem.c | 113 +--------------------- > >> include/linux/fb.h | 10 ++ > >> 4 files changed, 139 insertions(+), 112 deletions(-) > >> create mode 100644 drivers/video/fbdev/core/fb_cfb_fops.c > > > > While the general idea is fine, please do not call any of this "cfb", > > as it is not related to chunky color frame buffer formats. > > All of these operate on the raw frame buffer contents. > > Shall I call it fb_raw_() or fb_io_()? Given fb_memcpy_fromfb() is mapped to memcpy_fromio() on most architectures, I'd go for fb_io_*(). > CFB is used by the drawing helpers, which are usually used together with > this code. Hence the current naming. That's because your drawing helpers operate (only) on chunky color frame buffer formats ;-) Gr{oetje,eeting}s, Geert
Hi Am 26.04.23 um 17:21 schrieb Geert Uytterhoeven: > Hi Thomas, > > On Wed, Apr 26, 2023 at 5:06 PM Thomas Zimmermann <tzimmermann@suse.de> wrote: >> Am 26.04.23 um 17:01 schrieb Geert Uytterhoeven: >>> On Tue, Apr 25, 2023 at 4:28 PM Thomas Zimmermann <tzimmermann@suse.de> wrote: >>>> Move the existing CFB read and write code for I/O memory into >>>> the new helpers fb_cfb_read() and fb_cfb_write(). Make them the >>>> default fp_ops. No functional changes. >>>> >>>> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> >>>> --- >>>> drivers/video/fbdev/core/Makefile | 2 +- >>>> drivers/video/fbdev/core/fb_cfb_fops.c | 126 +++++++++++++++++++++++++ >>>> drivers/video/fbdev/core/fbmem.c | 113 +--------------------- >>>> include/linux/fb.h | 10 ++ >>>> 4 files changed, 139 insertions(+), 112 deletions(-) >>>> create mode 100644 drivers/video/fbdev/core/fb_cfb_fops.c >>> >>> While the general idea is fine, please do not call any of this "cfb", >>> as it is not related to chunky color frame buffer formats. >>> All of these operate on the raw frame buffer contents. >> >> Shall I call it fb_raw_() or fb_io_()? > > Given fb_memcpy_fromfb() is mapped to memcpy_fromio() on > most architectures, I'd go for fb_io_*(). Ok, makes sense. > >> CFB is used by the drawing helpers, which are usually used together with >> this code. Hence the current naming. > > That's because your drawing helpers operate (only) on chunky color > frame buffer formats ;-) Should we rename the CFB drawing functions to fb_io_ then? AFAICT they are the same algorithms as in the fb_sys_ functions; just with I/O memory. Best regards Thomas > > Gr{oetje,eeting}s, > > Geert >
Hi Thomas, On Fri, Apr 28, 2023 at 1:20 PM Thomas Zimmermann <tzimmermann@suse.de> wrote: > Am 26.04.23 um 17:21 schrieb Geert Uytterhoeven: > > On Wed, Apr 26, 2023 at 5:06 PM Thomas Zimmermann <tzimmermann@suse.de> wrote: > >> Am 26.04.23 um 17:01 schrieb Geert Uytterhoeven: > >>> On Tue, Apr 25, 2023 at 4:28 PM Thomas Zimmermann <tzimmermann@suse.de> wrote: > >>>> Move the existing CFB read and write code for I/O memory into > >>>> the new helpers fb_cfb_read() and fb_cfb_write(). Make them the > >>>> default fp_ops. No functional changes. > >>>> > >>>> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> > >>>> --- > >>>> drivers/video/fbdev/core/Makefile | 2 +- > >>>> drivers/video/fbdev/core/fb_cfb_fops.c | 126 +++++++++++++++++++++++++ > >>>> drivers/video/fbdev/core/fbmem.c | 113 +--------------------- > >>>> include/linux/fb.h | 10 ++ > >>>> 4 files changed, 139 insertions(+), 112 deletions(-) > >>>> create mode 100644 drivers/video/fbdev/core/fb_cfb_fops.c > >>> > >>> While the general idea is fine, please do not call any of this "cfb", > >>> as it is not related to chunky color frame buffer formats. > >>> All of these operate on the raw frame buffer contents. > >> > >> Shall I call it fb_raw_() or fb_io_()? > > > > Given fb_memcpy_fromfb() is mapped to memcpy_fromio() on > > most architectures, I'd go for fb_io_*(). > > Ok, makes sense. > > >> CFB is used by the drawing helpers, which are usually used together with > >> this code. Hence the current naming. > > > > That's because your drawing helpers operate (only) on chunky color > > frame buffer formats ;-) > > Should we rename the CFB drawing functions to fb_io_ then? AFAICT they > are the same algorithms as in the fb_sys_ functions; just with I/O memory. I don't know if that's worth the churn. Historically, the frame buffer was usually located in dedicated memory, hence the drawing operations operated on I/O memory. With the advent of unified memory architectures, the fb_sys_*() functions were introduced. Gr{oetje,eeting}s, Geert
diff --git a/drivers/video/fbdev/core/Makefile b/drivers/video/fbdev/core/Makefile index 08fabce76b74..cb7534a80305 100644 --- a/drivers/video/fbdev/core/Makefile +++ b/drivers/video/fbdev/core/Makefile @@ -2,7 +2,7 @@ obj-$(CONFIG_FB_NOTIFY) += fb_notify.o obj-$(CONFIG_FB) += fb.o fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \ - modedb.o fbcvt.o fb_cmdline.o + modedb.o fbcvt.o fb_cmdline.o fb_cfb_fops.o fb-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o ifeq ($(CONFIG_FRAMEBUFFER_CONSOLE),y) diff --git a/drivers/video/fbdev/core/fb_cfb_fops.c b/drivers/video/fbdev/core/fb_cfb_fops.c new file mode 100644 index 000000000000..f6000166eda4 --- /dev/null +++ b/drivers/video/fbdev/core/fb_cfb_fops.c @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/fb.h> +#include <linux/module.h> +#include <linux/uaccess.h> + +ssize_t fb_cfb_read(struct fb_info *info, char __user *buf, size_t count, loff_t *ppos) +{ + unsigned long p = *ppos; + u8 *buffer, *dst; + u8 __iomem *src; + int c, cnt = 0, err = 0; + unsigned long total_size; + + if (!info->screen_base) + return -ENODEV; + + total_size = info->screen_size; + + if (total_size == 0) + total_size = info->fix.smem_len; + + if (p >= total_size) + return 0; + + if (count >= total_size) + count = total_size; + + if (count + p > total_size) + count = total_size - p; + + buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + src = (u8 __iomem *)(info->screen_base + p); + + if (info->fbops->fb_sync) + info->fbops->fb_sync(info); + + while (count) { + c = (count > PAGE_SIZE) ? PAGE_SIZE : count; + dst = buffer; + fb_memcpy_fromfb(dst, src, c); + dst += c; + src += c; + + if (copy_to_user(buf, buffer, c)) { + err = -EFAULT; + break; + } + *ppos += c; + buf += c; + cnt += c; + count -= c; + } + + kfree(buffer); + + return cnt ? cnt : err; +} +EXPORT_SYMBOL(fb_cfb_read); + +ssize_t fb_cfb_write(struct fb_info *info, const char __user *buf, size_t count, loff_t *ppos) +{ + unsigned long p = *ppos; + u8 *buffer, *src; + u8 __iomem *dst; + int c, cnt = 0, err = 0; + unsigned long total_size; + + if (!info->screen_base) + return -ENODEV; + + total_size = info->screen_size; + + if (total_size == 0) + total_size = info->fix.smem_len; + + if (p > total_size) + return -EFBIG; + + if (count > total_size) { + err = -EFBIG; + count = total_size; + } + + if (count + p > total_size) { + if (!err) + err = -ENOSPC; + + count = total_size - p; + } + + buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + dst = (u8 __iomem *)(info->screen_base + p); + + if (info->fbops->fb_sync) + info->fbops->fb_sync(info); + + while (count) { + c = (count > PAGE_SIZE) ? PAGE_SIZE : count; + src = buffer; + + if (copy_from_user(src, buf, c)) { + err = -EFAULT; + break; + } + + fb_memcpy_tofb(dst, src, c); + dst += c; + src += c; + *ppos += c; + buf += c; + cnt += c; + count -= c; + } + + kfree(buffer); + + return (cnt) ? cnt : err; +} +EXPORT_SYMBOL(fb_cfb_write); diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index b993bb97058f..be6c75f3dfd0 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -761,12 +761,7 @@ static struct fb_info *file_fb_info(struct file *file) static ssize_t fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - unsigned long p = *ppos; struct fb_info *info = file_fb_info(file); - u8 *buffer, *dst; - u8 __iomem *src; - int c, cnt = 0, err = 0; - unsigned long total_size; if (!info) return -ENODEV; @@ -777,64 +772,13 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) if (info->fbops->fb_read) return info->fbops->fb_read(info, buf, count, ppos); - if (!info->screen_base) - return -ENODEV; - - total_size = info->screen_size; - - if (total_size == 0) - total_size = info->fix.smem_len; - - if (p >= total_size) - return 0; - - if (count >= total_size) - count = total_size; - - if (count + p > total_size) - count = total_size - p; - - buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, - GFP_KERNEL); - if (!buffer) - return -ENOMEM; - - src = (u8 __iomem *) (info->screen_base + p); - - if (info->fbops->fb_sync) - info->fbops->fb_sync(info); - - while (count) { - c = (count > PAGE_SIZE) ? PAGE_SIZE : count; - dst = buffer; - fb_memcpy_fromfb(dst, src, c); - dst += c; - src += c; - - if (copy_to_user(buf, buffer, c)) { - err = -EFAULT; - break; - } - *ppos += c; - buf += c; - cnt += c; - count -= c; - } - - kfree(buffer); - - return cnt ? cnt : err; + return fb_cfb_read(info, buf, count, ppos); } static ssize_t fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - unsigned long p = *ppos; struct fb_info *info = file_fb_info(file); - u8 *buffer, *src; - u8 __iomem *dst; - int c, cnt = 0, err = 0; - unsigned long total_size; if (!info) return -ENODEV; @@ -845,60 +789,7 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) if (info->fbops->fb_write) return info->fbops->fb_write(info, buf, count, ppos); - if (!info->screen_base) - return -ENODEV; - - total_size = info->screen_size; - - if (total_size == 0) - total_size = info->fix.smem_len; - - if (p > total_size) - return -EFBIG; - - if (count > total_size) { - err = -EFBIG; - count = total_size; - } - - if (count + p > total_size) { - if (!err) - err = -ENOSPC; - - count = total_size - p; - } - - buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, - GFP_KERNEL); - if (!buffer) - return -ENOMEM; - - dst = (u8 __iomem *) (info->screen_base + p); - - if (info->fbops->fb_sync) - info->fbops->fb_sync(info); - - while (count) { - c = (count > PAGE_SIZE) ? PAGE_SIZE : count; - src = buffer; - - if (copy_from_user(src, buf, c)) { - err = -EFAULT; - break; - } - - fb_memcpy_tofb(dst, src, c); - dst += c; - src += c; - *ppos += c; - buf += c; - cnt += c; - count -= c; - } - - kfree(buffer); - - return (cnt) ? cnt : err; + return fb_cfb_write(info, buf, count, ppos); } int diff --git a/include/linux/fb.h b/include/linux/fb.h index 08cb47da71f8..3b1644c79973 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -576,9 +576,19 @@ struct fb_info { extern int fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var); extern int fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var); extern int fb_blank(struct fb_info *info, int blank); + +/* + * Drawing operations where framebuffer is in video RAM + */ + extern void cfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect); extern void cfb_copyarea(struct fb_info *info, const struct fb_copyarea *area); extern void cfb_imageblit(struct fb_info *info, const struct fb_image *image); +extern ssize_t fb_cfb_read(struct fb_info *info, char __user *buf, size_t count, + loff_t *ppos); +extern ssize_t fb_cfb_write(struct fb_info *info, const char __user *buf, + size_t count, loff_t *ppos); + /* * Drawing operations where framebuffer is in system RAM */
Move the existing CFB read and write code for I/O memory into the new helpers fb_cfb_read() and fb_cfb_write(). Make them the default fp_ops. No functional changes. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> --- drivers/video/fbdev/core/Makefile | 2 +- drivers/video/fbdev/core/fb_cfb_fops.c | 126 +++++++++++++++++++++++++ drivers/video/fbdev/core/fbmem.c | 113 +--------------------- include/linux/fb.h | 10 ++ 4 files changed, 139 insertions(+), 112 deletions(-) create mode 100644 drivers/video/fbdev/core/fb_cfb_fops.c