Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fbdev: Move framebuffer I/O helpers into <asm/fb.h>

Implement framebuffer I/O helpers, such as fb_read*() and fb_write*(),
in the architecture's <asm/fb.h> header file or the generic one.

The common case has been the use of regular I/O functions, such as
__raw_readb() or memset_io(). A few architectures used plain system-
memory reads and writes. Sparc used helpers for its SBus.

The architectures that used special cases provide the same code in
their __raw_*() I/O helpers. So the patch replaces this code with the
__raw_*() functions and moves it to <asm-generic/fb.h> for all
architectures.

v8:
* remove garbage after commit-message tags
v6:
* fix fb_readq()/fb_writeq() on 64-bit mips (kernel test robot)
v5:
* include <linux/io.h> in <asm-generic/fb>; fix s390 build
v4:
* ia64, loongarch, sparc64: add fb_mem*() to arch headers
to keep current semantics (Arnd)
v3:
* implement all architectures with generic helpers
* support reordering and native byte order (Geert, Arnd)

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Tested-by: Sui Jingfeng <suijingfeng@loongson.cn>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20230512102444.5438-7-tzimmermann@suse.de

+185 -53
+20
arch/ia64/include/asm/fb.h
··· 2 2 #ifndef _ASM_FB_H_ 3 3 #define _ASM_FB_H_ 4 4 5 + #include <linux/compiler.h> 5 6 #include <linux/efi.h> 7 + #include <linux/string.h> 6 8 7 9 #include <asm/page.h> 8 10 ··· 19 17 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); 20 18 } 21 19 #define fb_pgprotect fb_pgprotect 20 + 21 + static inline void fb_memcpy_fromfb(void *to, const volatile void __iomem *from, size_t n) 22 + { 23 + memcpy(to, (void __force *)from, n); 24 + } 25 + #define fb_memcpy_fromfb fb_memcpy_fromfb 26 + 27 + static inline void fb_memcpy_tofb(volatile void __iomem *to, const void *from, size_t n) 28 + { 29 + memcpy((void __force *)to, from, n); 30 + } 31 + #define fb_memcpy_tofb fb_memcpy_tofb 32 + 33 + static inline void fb_memset(volatile void __iomem *addr, int c, size_t n) 34 + { 35 + memset((void __force *)addr, c, n); 36 + } 37 + #define fb_memset fb_memset 22 38 23 39 #include <asm-generic/fb.h> 24 40
+21
arch/loongarch/include/asm/fb.h
··· 5 5 #ifndef _ASM_FB_H_ 6 6 #define _ASM_FB_H_ 7 7 8 + #include <linux/compiler.h> 9 + #include <linux/string.h> 10 + 11 + static inline void fb_memcpy_fromfb(void *to, const volatile void __iomem *from, size_t n) 12 + { 13 + memcpy(to, (void __force *)from, n); 14 + } 15 + #define fb_memcpy_fromfb fb_memcpy_fromfb 16 + 17 + static inline void fb_memcpy_tofb(volatile void __iomem *to, const void *from, size_t n) 18 + { 19 + memcpy((void __force *)to, from, n); 20 + } 21 + #define fb_memcpy_tofb fb_memcpy_tofb 22 + 23 + static inline void fb_memset(volatile void __iomem *addr, int c, size_t n) 24 + { 25 + memset((void __force *)addr, c, n); 26 + } 27 + #define fb_memset fb_memset 28 + 8 29 #include <asm-generic/fb.h> 9 30 10 31 #endif /* _ASM_FB_H_ */
+22
arch/mips/include/asm/fb.h
··· 12 12 } 13 13 #define fb_pgprotect fb_pgprotect 14 14 15 + /* 16 + * MIPS doesn't define __raw_ I/O macros, so the helpers 17 + * in <asm-generic/fb.h> don't generate fb_readq() and 18 + * fb_write(). We have to provide them here. 19 + * 20 + * TODO: Convert MIPS to generic I/O. The helpers below can 21 + * then be removed. 22 + */ 23 + #ifdef CONFIG_64BIT 24 + static inline u64 fb_readq(const volatile void __iomem *addr) 25 + { 26 + return __raw_readq(addr); 27 + } 28 + #define fb_readq fb_readq 29 + 30 + static inline void fb_writeq(u64 b, volatile void __iomem *addr) 31 + { 32 + __raw_writeq(b, addr); 33 + } 34 + #define fb_writeq fb_writeq 35 + #endif 36 + 15 37 #include <asm-generic/fb.h> 16 38 17 39 #endif /* _ASM_FB_H_ */
+20
arch/sparc/include/asm/fb.h
··· 2 2 #ifndef _SPARC_FB_H_ 3 3 #define _SPARC_FB_H_ 4 4 5 + #include <linux/io.h> 6 + 5 7 struct fb_info; 6 8 struct file; 7 9 struct vm_area_struct; ··· 17 15 18 16 int fb_is_primary_device(struct fb_info *info); 19 17 #define fb_is_primary_device fb_is_primary_device 18 + 19 + static inline void fb_memcpy_fromfb(void *to, const volatile void __iomem *from, size_t n) 20 + { 21 + sbus_memcpy_fromio(to, from, n); 22 + } 23 + #define fb_memcpy_fromfb fb_memcpy_fromfb 24 + 25 + static inline void fb_memcpy_tofb(volatile void __iomem *to, const void *from, size_t n) 26 + { 27 + sbus_memcpy_toio(to, from, n); 28 + } 29 + #define fb_memcpy_tofb fb_memcpy_tofb 30 + 31 + static inline void fb_memset(volatile void __iomem *addr, int c, size_t n) 32 + { 33 + sbus_memset_io(addr, c, n); 34 + } 35 + #define fb_memset fb_memset 20 36 21 37 #include <asm-generic/fb.h> 22 38
+102
include/asm-generic/fb.h
··· 7 7 * Only include this header file from your architecture's <asm/fb.h>. 8 8 */ 9 9 10 + #include <linux/io.h> 10 11 #include <linux/mm_types.h> 11 12 #include <linux/pgtable.h> 12 13 ··· 29 28 { 30 29 return 0; 31 30 } 31 + #endif 32 + 33 + /* 34 + * I/O helpers for the framebuffer. Prefer these functions over their 35 + * regular counterparts. The regular I/O functions provide in-order 36 + * access and swap bytes to/from little-endian ordering. Neither is 37 + * required for framebuffers. Instead, the helpers read and write 38 + * raw framebuffer data. Independent operations can be reordered for 39 + * improved performance. 40 + */ 41 + 42 + #ifndef fb_readb 43 + static inline u8 fb_readb(const volatile void __iomem *addr) 44 + { 45 + return __raw_readb(addr); 46 + } 47 + #define fb_readb fb_readb 48 + #endif 49 + 50 + #ifndef fb_readw 51 + static inline u16 fb_readw(const volatile void __iomem *addr) 52 + { 53 + return __raw_readw(addr); 54 + } 55 + #define fb_readw fb_readw 56 + #endif 57 + 58 + #ifndef fb_readl 59 + static inline u32 fb_readl(const volatile void __iomem *addr) 60 + { 61 + return __raw_readl(addr); 62 + } 63 + #define fb_readl fb_readl 64 + #endif 65 + 66 + #ifndef fb_readq 67 + #if defined(__raw_readq) 68 + static inline u64 fb_readq(const volatile void __iomem *addr) 69 + { 70 + return __raw_readq(addr); 71 + } 72 + #define fb_readq fb_readq 73 + #endif 74 + #endif 75 + 76 + #ifndef fb_writeb 77 + static inline void fb_writeb(u8 b, volatile void __iomem *addr) 78 + { 79 + __raw_writeb(b, addr); 80 + } 81 + #define fb_writeb fb_writeb 82 + #endif 83 + 84 + #ifndef fb_writew 85 + static inline void fb_writew(u16 b, volatile void __iomem *addr) 86 + { 87 + __raw_writew(b, addr); 88 + } 89 + #define fb_writew fb_writew 90 + #endif 91 + 92 + #ifndef fb_writel 93 + static inline void fb_writel(u32 b, volatile void __iomem *addr) 94 + { 95 + __raw_writel(b, addr); 96 + } 97 + #define fb_writel fb_writel 98 + #endif 99 + 100 + #ifndef fb_writeq 101 + #if defined(__raw_writeq) 102 + static inline void fb_writeq(u64 b, volatile void __iomem *addr) 103 + { 104 + __raw_writeq(b, addr); 105 + } 106 + #define fb_writeq fb_writeq 107 + #endif 108 + #endif 109 + 110 + #ifndef fb_memcpy_fromfb 111 + static inline void fb_memcpy_fromfb(void *to, const volatile void __iomem *from, size_t n) 112 + { 113 + memcpy_fromio(to, from, n); 114 + } 115 + #define fb_memcpy_fromfb fb_memcpy_fromfb 116 + #endif 117 + 118 + #ifndef fb_memcpy_tofb 119 + static inline void fb_memcpy_tofb(volatile void __iomem *to, const void *from, size_t n) 120 + { 121 + memcpy_toio(to, from, n); 122 + } 123 + #define fb_memcpy_tofb fb_memcpy_tofb 124 + #endif 125 + 126 + #ifndef fb_memset 127 + static inline void fb_memset(volatile void __iomem *addr, int c, size_t n) 128 + { 129 + memset_io(addr, c, n); 130 + } 131 + #define fb_memset fb_memset 32 132 #endif 33 133 34 134 #endif /* __ASM_GENERIC_FB_H_ */
-53
include/linux/fb.h
··· 17 17 #include <linux/slab.h> 18 18 19 19 #include <asm/fb.h> 20 - #include <asm/io.h> 21 20 22 21 struct vm_area_struct; 23 22 struct fb_info; ··· 511 512 * But for now, we leave it broken with the following define 512 513 */ 513 514 #define STUPID_ACCELF_TEXT_SHIT 514 - 515 - // This will go away 516 - #if defined(__sparc__) 517 - 518 - /* We map all of our framebuffers such that big-endian accesses 519 - * are what we want, so the following is sufficient. 520 - */ 521 - 522 - // This will go away 523 - #define fb_readb sbus_readb 524 - #define fb_readw sbus_readw 525 - #define fb_readl sbus_readl 526 - #define fb_readq sbus_readq 527 - #define fb_writeb sbus_writeb 528 - #define fb_writew sbus_writew 529 - #define fb_writel sbus_writel 530 - #define fb_writeq sbus_writeq 531 - #define fb_memset sbus_memset_io 532 - #define fb_memcpy_fromfb sbus_memcpy_fromio 533 - #define fb_memcpy_tofb sbus_memcpy_toio 534 - 535 - #elif defined(__i386__) || defined(__alpha__) || defined(__x86_64__) || \ 536 - defined(__hppa__) || defined(__sh__) || defined(__powerpc__) || \ 537 - defined(__arm__) || defined(__aarch64__) || defined(__mips__) 538 - 539 - #define fb_readb __raw_readb 540 - #define fb_readw __raw_readw 541 - #define fb_readl __raw_readl 542 - #define fb_readq __raw_readq 543 - #define fb_writeb __raw_writeb 544 - #define fb_writew __raw_writew 545 - #define fb_writel __raw_writel 546 - #define fb_writeq __raw_writeq 547 - #define fb_memset memset_io 548 - #define fb_memcpy_fromfb memcpy_fromio 549 - #define fb_memcpy_tofb memcpy_toio 550 - 551 - #else 552 - 553 - #define fb_readb(addr) (*(volatile u8 *) (addr)) 554 - #define fb_readw(addr) (*(volatile u16 *) (addr)) 555 - #define fb_readl(addr) (*(volatile u32 *) (addr)) 556 - #define fb_readq(addr) (*(volatile u64 *) (addr)) 557 - #define fb_writeb(b,addr) (*(volatile u8 *) (addr) = (b)) 558 - #define fb_writew(b,addr) (*(volatile u16 *) (addr) = (b)) 559 - #define fb_writel(b,addr) (*(volatile u32 *) (addr) = (b)) 560 - #define fb_writeq(b,addr) (*(volatile u64 *) (addr) = (b)) 561 - #define fb_memset memset 562 - #define fb_memcpy_fromfb memcpy 563 - #define fb_memcpy_tofb memcpy 564 - 565 - #endif 566 515 567 516 #define FB_LEFT_POS(p, bpp) (fb_be_math(p) ? (32 - (bpp)) : 0) 568 517 #define FB_SHIFT_HIGH(p, val, bits) (fb_be_math(p) ? (val) >> (bits) : \