summaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorThomas Zimmermann <tzimmermann@suse.de>2023-04-28 14:24:51 +0200
committerThomas Zimmermann <tzimmermann@suse.de>2023-05-08 15:28:34 +0200
commit6121cd9ef911432b14c2a17aefaf8cd2f3cfcdff (patch)
tree6db707c245921b6460cbda1c20f22e1a737f7f59 /drivers/video
parent3f8974f68f408f4983443b745a3cf95b06112469 (diff)
downloadlinux-stable-6121cd9ef911432b14c2a17aefaf8cd2f3cfcdff.tar.gz
linux-stable-6121cd9ef911432b14c2a17aefaf8cd2f3cfcdff.tar.bz2
linux-stable-6121cd9ef911432b14c2a17aefaf8cd2f3cfcdff.zip
fbdev: Move I/O read and write code into helper functions
Move the existing I/O 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. In the near term, the new functions will be useful to the DRM subsystem, which currently provides it's own implementation. It can then use the shared code. In the longer term, it might make sense to revise the I/O helper's default status and make them opt-in by the driver. Systems that don't use them would not contain the code any longer. v2: * add detailed commit message (Javier) * rename fb_cfb_() to fb_io_() (Geert) * add fixes that got lost while moving the code (Geert) Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Tested-by: Sui Jingfeng <suijingfeng@loongson.cn> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Acked-by: Helge Deller <deller@gmx.de> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20230428122452.4856-19-tzimmermann@suse.de
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/fbdev/core/Makefile2
-rw-r--r--drivers/video/fbdev/core/fb_io_fops.c133
-rw-r--r--drivers/video/fbdev/core/fbmem.c118
3 files changed, 136 insertions, 117 deletions
diff --git a/drivers/video/fbdev/core/Makefile b/drivers/video/fbdev/core/Makefile
index 08fabce76b74..8f0060160ffb 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_io_fops.o
fb-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o
ifeq ($(CONFIG_FRAMEBUFFER_CONSOLE),y)
diff --git a/drivers/video/fbdev/core/fb_io_fops.c b/drivers/video/fbdev/core/fb_io_fops.c
new file mode 100644
index 000000000000..f5299d50f33b
--- /dev/null
+++ b/drivers/video/fbdev/core/fb_io_fops.c
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/fb.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+
+ssize_t fb_io_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, trailing;
+
+ 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;
+
+ trailing = copy_to_user(buf, buffer, c);
+ if (trailing == c) {
+ err = -EFAULT;
+ break;
+ }
+ c -= trailing;
+
+ *ppos += c;
+ buf += c;
+ cnt += c;
+ count -= c;
+ }
+
+ kfree(buffer);
+
+ return cnt ? cnt : err;
+}
+EXPORT_SYMBOL(fb_io_read);
+
+ssize_t fb_io_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, trailing;
+
+ 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;
+
+ trailing = copy_from_user(src, buf, c);
+ if (trailing == c) {
+ err = -EFAULT;
+ break;
+ }
+ c -= trailing;
+
+ 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_io_write);
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index bf5a0780457e..63af40831d7d 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, trailing;
if (!info)
return -ENODEV;
@@ -777,67 +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;
-
- trailing = copy_to_user(buf, buffer, c);
- if (trailing == c) {
- err = -EFAULT;
- break;
- }
- c -= trailing;
-
- *ppos += c;
- buf += c;
- cnt += c;
- count -= c;
- }
-
- kfree(buffer);
-
- return cnt ? cnt : err;
+ return fb_io_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, trailing;
if (!info)
return -ENODEV;
@@ -848,62 +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;
-
- trailing = copy_from_user(src, buf, c);
- if (trailing == c) {
- err = -EFAULT;
- break;
- }
- c -= trailing;
-
- 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_io_write(info, buf, count, ppos);
}
int