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
This commit is contained in:
Thomas Zimmermann 2023-05-12 12:24:43 +02:00
parent 8ff1541da3
commit 8f8eaa1b02
6 changed files with 185 additions and 53 deletions

View File

@ -2,7 +2,9 @@
#ifndef _ASM_FB_H_
#define _ASM_FB_H_
#include <linux/compiler.h>
#include <linux/efi.h>
#include <linux/string.h>
#include <asm/page.h>
@ -18,6 +20,24 @@ static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
}
#define fb_pgprotect fb_pgprotect
static inline void fb_memcpy_fromfb(void *to, const volatile void __iomem *from, size_t n)
{
memcpy(to, (void __force *)from, n);
}
#define fb_memcpy_fromfb fb_memcpy_fromfb
static inline void fb_memcpy_tofb(volatile void __iomem *to, const void *from, size_t n)
{
memcpy((void __force *)to, from, n);
}
#define fb_memcpy_tofb fb_memcpy_tofb
static inline void fb_memset(volatile void __iomem *addr, int c, size_t n)
{
memset((void __force *)addr, c, n);
}
#define fb_memset fb_memset
#include <asm-generic/fb.h>
#endif /* _ASM_FB_H_ */

View File

@ -5,6 +5,27 @@
#ifndef _ASM_FB_H_
#define _ASM_FB_H_
#include <linux/compiler.h>
#include <linux/string.h>
static inline void fb_memcpy_fromfb(void *to, const volatile void __iomem *from, size_t n)
{
memcpy(to, (void __force *)from, n);
}
#define fb_memcpy_fromfb fb_memcpy_fromfb
static inline void fb_memcpy_tofb(volatile void __iomem *to, const void *from, size_t n)
{
memcpy((void __force *)to, from, n);
}
#define fb_memcpy_tofb fb_memcpy_tofb
static inline void fb_memset(volatile void __iomem *addr, int c, size_t n)
{
memset((void __force *)addr, c, n);
}
#define fb_memset fb_memset
#include <asm-generic/fb.h>
#endif /* _ASM_FB_H_ */

View File

@ -12,6 +12,28 @@ static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
}
#define fb_pgprotect fb_pgprotect
/*
* MIPS doesn't define __raw_ I/O macros, so the helpers
* in <asm-generic/fb.h> don't generate fb_readq() and
* fb_write(). We have to provide them here.
*
* TODO: Convert MIPS to generic I/O. The helpers below can
* then be removed.
*/
#ifdef CONFIG_64BIT
static inline u64 fb_readq(const volatile void __iomem *addr)
{
return __raw_readq(addr);
}
#define fb_readq fb_readq
static inline void fb_writeq(u64 b, volatile void __iomem *addr)
{
__raw_writeq(b, addr);
}
#define fb_writeq fb_writeq
#endif
#include <asm-generic/fb.h>
#endif /* _ASM_FB_H_ */

View File

@ -2,6 +2,8 @@
#ifndef _SPARC_FB_H_
#define _SPARC_FB_H_
#include <linux/io.h>
struct fb_info;
struct file;
struct vm_area_struct;
@ -16,6 +18,24 @@ static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
int fb_is_primary_device(struct fb_info *info);
#define fb_is_primary_device fb_is_primary_device
static inline void fb_memcpy_fromfb(void *to, const volatile void __iomem *from, size_t n)
{
sbus_memcpy_fromio(to, from, n);
}
#define fb_memcpy_fromfb fb_memcpy_fromfb
static inline void fb_memcpy_tofb(volatile void __iomem *to, const void *from, size_t n)
{
sbus_memcpy_toio(to, from, n);
}
#define fb_memcpy_tofb fb_memcpy_tofb
static inline void fb_memset(volatile void __iomem *addr, int c, size_t n)
{
sbus_memset_io(addr, c, n);
}
#define fb_memset fb_memset
#include <asm-generic/fb.h>
#endif /* _SPARC_FB_H_ */

View File

@ -7,6 +7,7 @@
* Only include this header file from your architecture's <asm/fb.h>.
*/
#include <linux/io.h>
#include <linux/mm_types.h>
#include <linux/pgtable.h>
@ -30,4 +31,105 @@ static inline int fb_is_primary_device(struct fb_info *info)
}
#endif
/*
* I/O helpers for the framebuffer. Prefer these functions over their
* regular counterparts. The regular I/O functions provide in-order
* access and swap bytes to/from little-endian ordering. Neither is
* required for framebuffers. Instead, the helpers read and write
* raw framebuffer data. Independent operations can be reordered for
* improved performance.
*/
#ifndef fb_readb
static inline u8 fb_readb(const volatile void __iomem *addr)
{
return __raw_readb(addr);
}
#define fb_readb fb_readb
#endif
#ifndef fb_readw
static inline u16 fb_readw(const volatile void __iomem *addr)
{
return __raw_readw(addr);
}
#define fb_readw fb_readw
#endif
#ifndef fb_readl
static inline u32 fb_readl(const volatile void __iomem *addr)
{
return __raw_readl(addr);
}
#define fb_readl fb_readl
#endif
#ifndef fb_readq
#if defined(__raw_readq)
static inline u64 fb_readq(const volatile void __iomem *addr)
{
return __raw_readq(addr);
}
#define fb_readq fb_readq
#endif
#endif
#ifndef fb_writeb
static inline void fb_writeb(u8 b, volatile void __iomem *addr)
{
__raw_writeb(b, addr);
}
#define fb_writeb fb_writeb
#endif
#ifndef fb_writew
static inline void fb_writew(u16 b, volatile void __iomem *addr)
{
__raw_writew(b, addr);
}
#define fb_writew fb_writew
#endif
#ifndef fb_writel
static inline void fb_writel(u32 b, volatile void __iomem *addr)
{
__raw_writel(b, addr);
}
#define fb_writel fb_writel
#endif
#ifndef fb_writeq
#if defined(__raw_writeq)
static inline void fb_writeq(u64 b, volatile void __iomem *addr)
{
__raw_writeq(b, addr);
}
#define fb_writeq fb_writeq
#endif
#endif
#ifndef fb_memcpy_fromfb
static inline void fb_memcpy_fromfb(void *to, const volatile void __iomem *from, size_t n)
{
memcpy_fromio(to, from, n);
}
#define fb_memcpy_fromfb fb_memcpy_fromfb
#endif
#ifndef fb_memcpy_tofb
static inline void fb_memcpy_tofb(volatile void __iomem *to, const void *from, size_t n)
{
memcpy_toio(to, from, n);
}
#define fb_memcpy_tofb fb_memcpy_tofb
#endif
#ifndef fb_memset
static inline void fb_memset(volatile void __iomem *addr, int c, size_t n)
{
memset_io(addr, c, n);
}
#define fb_memset fb_memset
#endif
#endif /* __ASM_GENERIC_FB_H_ */

View File

@ -17,7 +17,6 @@
#include <linux/slab.h>
#include <asm/fb.h>
#include <asm/io.h>
struct vm_area_struct;
struct fb_info;
@ -513,58 +512,6 @@ struct fb_info {
*/
#define STUPID_ACCELF_TEXT_SHIT
// This will go away
#if defined(__sparc__)
/* We map all of our framebuffers such that big-endian accesses
* are what we want, so the following is sufficient.
*/
// This will go away
#define fb_readb sbus_readb
#define fb_readw sbus_readw
#define fb_readl sbus_readl
#define fb_readq sbus_readq
#define fb_writeb sbus_writeb
#define fb_writew sbus_writew
#define fb_writel sbus_writel
#define fb_writeq sbus_writeq
#define fb_memset sbus_memset_io
#define fb_memcpy_fromfb sbus_memcpy_fromio
#define fb_memcpy_tofb sbus_memcpy_toio
#elif defined(__i386__) || defined(__alpha__) || defined(__x86_64__) || \
defined(__hppa__) || defined(__sh__) || defined(__powerpc__) || \
defined(__arm__) || defined(__aarch64__) || defined(__mips__)
#define fb_readb __raw_readb
#define fb_readw __raw_readw
#define fb_readl __raw_readl
#define fb_readq __raw_readq
#define fb_writeb __raw_writeb
#define fb_writew __raw_writew
#define fb_writel __raw_writel
#define fb_writeq __raw_writeq
#define fb_memset memset_io
#define fb_memcpy_fromfb memcpy_fromio
#define fb_memcpy_tofb memcpy_toio
#else
#define fb_readb(addr) (*(volatile u8 *) (addr))
#define fb_readw(addr) (*(volatile u16 *) (addr))
#define fb_readl(addr) (*(volatile u32 *) (addr))
#define fb_readq(addr) (*(volatile u64 *) (addr))
#define fb_writeb(b,addr) (*(volatile u8 *) (addr) = (b))
#define fb_writew(b,addr) (*(volatile u16 *) (addr) = (b))
#define fb_writel(b,addr) (*(volatile u32 *) (addr) = (b))
#define fb_writeq(b,addr) (*(volatile u64 *) (addr) = (b))
#define fb_memset memset
#define fb_memcpy_fromfb memcpy
#define fb_memcpy_tofb memcpy
#endif
#define FB_LEFT_POS(p, bpp) (fb_be_math(p) ? (32 - (bpp)) : 0)
#define FB_SHIFT_HIGH(p, val, bits) (fb_be_math(p) ? (val) >> (bits) : \
(val) << (bits))