Skip to content

Commit 6121cd9

Browse files
committed
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
1 parent 3f8974f commit 6121cd9

4 files changed

Lines changed: 146 additions & 117 deletions

File tree

drivers/video/fbdev/core/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
obj-$(CONFIG_FB_NOTIFY) += fb_notify.o
33
obj-$(CONFIG_FB) += fb.o
44
fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \
5-
modedb.o fbcvt.o fb_cmdline.o
5+
modedb.o fbcvt.o fb_cmdline.o fb_io_fops.o
66
fb-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o
77

88
ifeq ($(CONFIG_FRAMEBUFFER_CONSOLE),y)
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <linux/fb.h>
4+
#include <linux/module.h>
5+
#include <linux/uaccess.h>
6+
7+
ssize_t fb_io_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, trailing;
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,
33+
GFP_KERNEL);
34+
if (!buffer)
35+
return -ENOMEM;
36+
37+
src = (u8 __iomem *) (info->screen_base + p);
38+
39+
if (info->fbops->fb_sync)
40+
info->fbops->fb_sync(info);
41+
42+
while (count) {
43+
c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
44+
dst = buffer;
45+
fb_memcpy_fromfb(dst, src, c);
46+
dst += c;
47+
src += c;
48+
49+
trailing = copy_to_user(buf, buffer, c);
50+
if (trailing == c) {
51+
err = -EFAULT;
52+
break;
53+
}
54+
c -= trailing;
55+
56+
*ppos += c;
57+
buf += c;
58+
cnt += c;
59+
count -= c;
60+
}
61+
62+
kfree(buffer);
63+
64+
return cnt ? cnt : err;
65+
}
66+
EXPORT_SYMBOL(fb_io_read);
67+
68+
ssize_t fb_io_write(struct fb_info *info, const char __user *buf, size_t count, loff_t *ppos)
69+
{
70+
unsigned long p = *ppos;
71+
u8 *buffer, *src;
72+
u8 __iomem *dst;
73+
int c, cnt = 0, err = 0;
74+
unsigned long total_size, trailing;
75+
76+
if (!info->screen_base)
77+
return -ENODEV;
78+
79+
total_size = info->screen_size;
80+
81+
if (total_size == 0)
82+
total_size = info->fix.smem_len;
83+
84+
if (p > total_size)
85+
return -EFBIG;
86+
87+
if (count > total_size) {
88+
err = -EFBIG;
89+
count = total_size;
90+
}
91+
92+
if (count + p > total_size) {
93+
if (!err)
94+
err = -ENOSPC;
95+
96+
count = total_size - p;
97+
}
98+
99+
buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
100+
GFP_KERNEL);
101+
if (!buffer)
102+
return -ENOMEM;
103+
104+
dst = (u8 __iomem *) (info->screen_base + p);
105+
106+
if (info->fbops->fb_sync)
107+
info->fbops->fb_sync(info);
108+
109+
while (count) {
110+
c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
111+
src = buffer;
112+
113+
trailing = copy_from_user(src, buf, c);
114+
if (trailing == c) {
115+
err = -EFAULT;
116+
break;
117+
}
118+
c -= trailing;
119+
120+
fb_memcpy_tofb(dst, src, c);
121+
dst += c;
122+
src += c;
123+
*ppos += c;
124+
buf += c;
125+
cnt += c;
126+
count -= c;
127+
}
128+
129+
kfree(buffer);
130+
131+
return (cnt) ? cnt : err;
132+
}
133+
EXPORT_SYMBOL(fb_io_write);

drivers/video/fbdev/core/fbmem.c

Lines changed: 2 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -761,12 +761,7 @@ static struct fb_info *file_fb_info(struct file *file)
761761
static ssize_t
762762
fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
763763
{
764-
unsigned long p = *ppos;
765764
struct fb_info *info = file_fb_info(file);
766-
u8 *buffer, *dst;
767-
u8 __iomem *src;
768-
int c, cnt = 0, err = 0;
769-
unsigned long total_size, trailing;
770765

771766
if (!info)
772767
return -ENODEV;
@@ -777,67 +772,13 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
777772
if (info->fbops->fb_read)
778773
return info->fbops->fb_read(info, buf, count, ppos);
779774

780-
if (!info->screen_base)
781-
return -ENODEV;
782-
783-
total_size = info->screen_size;
784-
785-
if (total_size == 0)
786-
total_size = info->fix.smem_len;
787-
788-
if (p >= total_size)
789-
return 0;
790-
791-
if (count >= total_size)
792-
count = total_size;
793-
794-
if (count + p > total_size)
795-
count = total_size - p;
796-
797-
buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
798-
GFP_KERNEL);
799-
if (!buffer)
800-
return -ENOMEM;
801-
802-
src = (u8 __iomem *) (info->screen_base + p);
803-
804-
if (info->fbops->fb_sync)
805-
info->fbops->fb_sync(info);
806-
807-
while (count) {
808-
c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
809-
dst = buffer;
810-
fb_memcpy_fromfb(dst, src, c);
811-
dst += c;
812-
src += c;
813-
814-
trailing = copy_to_user(buf, buffer, c);
815-
if (trailing == c) {
816-
err = -EFAULT;
817-
break;
818-
}
819-
c -= trailing;
820-
821-
*ppos += c;
822-
buf += c;
823-
cnt += c;
824-
count -= c;
825-
}
826-
827-
kfree(buffer);
828-
829-
return cnt ? cnt : err;
775+
return fb_io_read(info, buf, count, ppos);
830776
}
831777

832778
static ssize_t
833779
fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
834780
{
835-
unsigned long p = *ppos;
836781
struct fb_info *info = file_fb_info(file);
837-
u8 *buffer, *src;
838-
u8 __iomem *dst;
839-
int c, cnt = 0, err = 0;
840-
unsigned long total_size, trailing;
841782

842783
if (!info)
843784
return -ENODEV;
@@ -848,62 +789,7 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
848789
if (info->fbops->fb_write)
849790
return info->fbops->fb_write(info, buf, count, ppos);
850791

851-
if (!info->screen_base)
852-
return -ENODEV;
853-
854-
total_size = info->screen_size;
855-
856-
if (total_size == 0)
857-
total_size = info->fix.smem_len;
858-
859-
if (p > total_size)
860-
return -EFBIG;
861-
862-
if (count > total_size) {
863-
err = -EFBIG;
864-
count = total_size;
865-
}
866-
867-
if (count + p > total_size) {
868-
if (!err)
869-
err = -ENOSPC;
870-
871-
count = total_size - p;
872-
}
873-
874-
buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
875-
GFP_KERNEL);
876-
if (!buffer)
877-
return -ENOMEM;
878-
879-
dst = (u8 __iomem *) (info->screen_base + p);
880-
881-
if (info->fbops->fb_sync)
882-
info->fbops->fb_sync(info);
883-
884-
while (count) {
885-
c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
886-
src = buffer;
887-
888-
trailing = copy_from_user(src, buf, c);
889-
if (trailing == c) {
890-
err = -EFAULT;
891-
break;
892-
}
893-
c -= trailing;
894-
895-
fb_memcpy_tofb(dst, src, c);
896-
dst += c;
897-
src += c;
898-
*ppos += c;
899-
buf += c;
900-
cnt += c;
901-
count -= c;
902-
}
903-
904-
kfree(buffer);
905-
906-
return (cnt) ? cnt : err;
792+
return fb_io_write(info, buf, count, ppos);
907793
}
908794

909795
int

include/linux/fb.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,9 +576,19 @@ struct fb_info {
576576
extern int fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var);
577577
extern int fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var);
578578
extern int fb_blank(struct fb_info *info, int blank);
579+
580+
/*
581+
* Drawing operations where framebuffer is in I/O memory
582+
*/
583+
579584
extern void cfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
580585
extern void cfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
581586
extern void cfb_imageblit(struct fb_info *info, const struct fb_image *image);
587+
extern ssize_t fb_io_read(struct fb_info *info, char __user *buf,
588+
size_t count, loff_t *ppos);
589+
extern ssize_t fb_io_write(struct fb_info *info, const char __user *buf,
590+
size_t count, loff_t *ppos);
591+
582592
/*
583593
* Drawing operations where framebuffer is in system RAM
584594
*/

0 commit comments

Comments
 (0)