asm-generic updates for 6.13

These are a number of unrelated cleanups, generally simplifying the
 architecture specific header files:
 
  - A series from Al Viro simplifies asm/vga.h, after it turns out that
    most of it can be generalized.
 
  - A series from Julian Vetter adds a common version of
    memcpy_{to,from}io() and memset_io() and changes most architectures
    to use that instead of their own implementation
 
  - A series from Niklas Schnelle concludes his work to make PC
    style inb()/outb() optional
 
  - Nicolas Pitre contributes improvements for the generic do_div()
    helper
 
  - Christoph Hellwig adds a generic version of page_to_phys()
    and phys_to_page(), replacing the slightly different architecture
    specific definitions.
 
  - Uwe Kleine-Koenig has a minor cleanup for ioctl definitions
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEiK/NIGsWEZVxh/FrYKtH/8kJUicFAmc+Z0gACgkQYKtH/8kJ
 UicqzA/8CcqVdcWKlFAyiFI62DCkd3iYm/joNK3/JhvUIvVFvY+HI0+XpTeOEN1r
 dfYBNg/KTVSbia5MEEy28Lk5WdoA3X7p9E8NuYC1ik/qvH3Y0kXDU2NiRcJDwalq
 u56tGUwDITFUzRo47a4Z53JpV60FlGaUVjuKp1jJiOQkcs/iussVYuti8mNVb1ud
 1tf21TEAIywq43IC8CxevIRsBkJBqMhalaGWYgKw3ZTwXdiKaXed6RH7IjPodanN
 6b7R6aFEqlT7usFX9vLOYNRGzd3HIueXOT1iqiiGI1lm5u/iutxKH+8eS4q381oN
 WJL0jQdo4sv2MxtSHYrjpzPRQpSp/qrin29h3PVjwBjZF3i5WvFeTYgfjQEEkqe0
 fpTXjUsr5n1F1pGV90DtJHwaD5TxKD4VYFLDRCDGUiAnWPkZ7EYUBL3SA6GqEkXB
 1lVRPsEBo0y867/WQcoCZA/x7ANZDI6bDZ6fjumwx8OCZOHZeN6FGtqQJHcVZR5O
 +nu/j3I8YH1tZGKbA+wliyQwt/T60Oxs62HHcFzFLGakARwUEDYO53IGCJUByFwk
 kCrgNVvzFklwWpqqyTADqb5lkQKpZr5gIdpst185qttCQkb+EFWiCi9w2inXTjHl
 2oCc7Uf0cvoxnhVlJAw73eGTtpqS37KCWK+iNyrQbOfy+hgIv+w=
 =zEHk
 -----END PGP SIGNATURE-----

Merge tag 'asm-generic-3.13' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic

Pull asm-generic updates from Arnd Bergmann:
 "These are a number of unrelated cleanups, generally simplifying the
  architecture specific header files:

   - A series from Al Viro simplifies asm/vga.h, after it turns out that
     most of it can be generalized.

   - A series from Julian Vetter adds a common version of
     memcpy_{to,from}io() and memset_io() and changes most architectures
     to use that instead of their own implementation

   - A series from Niklas Schnelle concludes his work to make PC style
     inb()/outb() optional

   - Nicolas Pitre contributes improvements for the generic do_div()
     helper

   - Christoph Hellwig adds a generic version of page_to_phys() and
     phys_to_page(), replacing the slightly different architecture
     specific definitions.

   - Uwe Kleine-Koenig has a minor cleanup for ioctl definitions"

* tag 'asm-generic-3.13' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic: (24 commits)
  empty include/asm-generic/vga.h
  sparc: get rid of asm/vga.h
  asm/vga.h: don't bother with scr_mem{cpy,move}v() unless we need to
  vt_buffer.h: get rid of dead code in default scr_...() instances
  tty: serial: export serial_8250_warn_need_ioport
  lib/iomem_copy: fix kerneldoc format style
  hexagon: simplify asm/io.h for !HAS_IOPORT
  loongarch: Use new fallback IO memcpy/memset
  csky: Use new fallback IO memcpy/memset
  arm64: Use new fallback IO memcpy/memset
  New implementation for IO memcpy and IO memset
  watchdog: Add HAS_IOPORT dependency for SBC8360 and SBC7240
  __arch_xprod64(): make __always_inline when optimizing for performance
  ARM: div64: improve __arch_xprod_64()
  asm-generic/div64: optimize/simplify __div64_const32()
  lib/math/test_div64: add some edge cases relevant to __div64_const32()
  asm-generic: add an optional pfn_valid check to page_to_phys
  asm-generic: provide generic page_to_phys and phys_to_page implementations
  asm-generic/io.h: Remove I/O port accessors for HAS_IOPORT=n
  tty: serial: handle HAS_IOPORT dependencies
  ...
This commit is contained in:
Linus Torvalds 2024-11-20 15:13:02 -08:00
commit 79caa6c88a
63 changed files with 486 additions and 929 deletions

View File

@ -88,7 +88,6 @@ static inline void * phys_to_virt(unsigned long address)
#define virt_to_phys virt_to_phys
#define phys_to_virt phys_to_virt
#define page_to_phys(page) page_to_pa(page)
/* Maximum PIO space address supported? */
#define IO_SPACE_LIMIT 0xffff

View File

@ -42,9 +42,6 @@ static inline void ioport_unmap(void __iomem *addr)
#define iowrite16be(v,p) ({ __iowmb(); __raw_writew((__force u16)cpu_to_be16(v), p); })
#define iowrite32be(v,p) ({ __iowmb(); __raw_writel((__force u32)cpu_to_be32(v), p); })
/* Change struct page to physical address */
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
#define __raw_readb __raw_readb
static inline u8 __raw_readb(const volatile void __iomem *addr)
{

View File

@ -52,10 +52,17 @@ static inline uint32_t __div64_32(uint64_t *n, uint32_t base)
#else
static inline uint64_t __arch_xprod_64(uint64_t m, uint64_t n, bool bias)
#ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE
static __always_inline
#else
static inline
#endif
uint64_t __arch_xprod_64(uint64_t m, uint64_t n, bool bias)
{
unsigned long long res;
register unsigned int tmp asm("ip") = 0;
bool no_ovf = __builtin_constant_p(m) &&
((m >> 32) + (m & 0xffffffff) < 0x100000000);
if (!bias) {
asm ( "umull %Q0, %R0, %Q1, %Q2\n\t"
@ -63,7 +70,7 @@ static inline uint64_t __arch_xprod_64(uint64_t m, uint64_t n, bool bias)
: "=&r" (res)
: "r" (m), "r" (n)
: "cc");
} else if (!(m & ((1ULL << 63) | (1ULL << 31)))) {
} else if (no_ovf) {
res = m;
asm ( "umlal %Q0, %R0, %Q1, %Q2\n\t"
"mov %Q0, #0"
@ -80,7 +87,7 @@ static inline uint64_t __arch_xprod_64(uint64_t m, uint64_t n, bool bias)
: "cc");
}
if (!(m & ((1ULL << 63) | (1ULL << 31)))) {
if (no_ovf) {
asm ( "umlal %R0, %Q0, %R1, %Q2\n\t"
"umlal %R0, %Q0, %Q1, %R2\n\t"
"mov %R0, #0\n\t"

View File

@ -147,12 +147,6 @@ extern unsigned long vectors_base;
#define DTCM_OFFSET UL(0xfffe8000)
#endif
/*
* Convert a page to/from a physical address
*/
#define page_to_phys(page) (__pfn_to_phys(page_to_pfn(page)))
#define phys_to_page(phys) (pfn_to_page(__phys_to_pfn(phys)))
/*
* PLAT_PHYS_OFFSET is the offset (from zero) of the start of physical
* memory. This is used for XIP and NoMMU kernels, and on platforms that don't

View File

@ -129,17 +129,6 @@ static __always_inline u64 __raw_readq(const volatile void __iomem *addr)
#define IO_SPACE_LIMIT (PCI_IO_SIZE - 1)
#define PCI_IOBASE ((void __iomem *)PCI_IO_START)
/*
* String version of I/O memory access operations.
*/
extern void __memcpy_fromio(void *, const volatile void __iomem *, size_t);
extern void __memcpy_toio(volatile void __iomem *, const void *, size_t);
extern void __memset_io(volatile void __iomem *, int, size_t);
#define memset_io(c,v,l) __memset_io((c),(v),(l))
#define memcpy_fromio(a,c,l) __memcpy_fromio((a),(c),(l))
#define memcpy_toio(c,a,l) __memcpy_toio((c),(a),(l))
/*
* The ARM64 iowrite implementation is intended to support drivers that want to
* use write combining. For instance PCI drivers using write combining with a 64

View File

@ -353,12 +353,6 @@ extern phys_addr_t __phys_addr_symbol(unsigned long x);
#define __phys_to_virt(x) ((unsigned long)((x) - PHYS_OFFSET) | PAGE_OFFSET)
#define __phys_to_kimg(x) ((unsigned long)((x) + kimage_voffset))
/*
* Convert a page to/from a physical address
*/
#define page_to_phys(page) (__pfn_to_phys(page_to_pfn(page)))
#define phys_to_page(phys) (pfn_to_page(__phys_to_pfn(phys)))
/*
* Note: Drivers should NOT use these. They are the wrong
* translation for translating DMA addresses. Use the driver

View File

@ -9,34 +9,6 @@
#include <linux/types.h>
#include <linux/io.h>
/*
* Copy data from IO memory space to "real" memory space.
*/
void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count)
{
while (count && !IS_ALIGNED((unsigned long)from, 8)) {
*(u8 *)to = __raw_readb(from);
from++;
to++;
count--;
}
while (count >= 8) {
*(u64 *)to = __raw_readq(from);
from += 8;
to += 8;
count -= 8;
}
while (count) {
*(u8 *)to = __raw_readb(from);
from++;
to++;
count--;
}
}
EXPORT_SYMBOL(__memcpy_fromio);
/*
* This generates a memcpy that works on a from/to address which is aligned to
* bits. Count is in terms of the number of bits sized quantities to copy. It
@ -78,62 +50,3 @@ void __iowrite32_copy_full(void __iomem *to, const void *from, size_t count)
dgh();
}
EXPORT_SYMBOL(__iowrite32_copy_full);
/*
* Copy data from "real" memory space to IO memory space.
*/
void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count)
{
while (count && !IS_ALIGNED((unsigned long)to, 8)) {
__raw_writeb(*(u8 *)from, to);
from++;
to++;
count--;
}
while (count >= 8) {
__raw_writeq(*(u64 *)from, to);
from += 8;
to += 8;
count -= 8;
}
while (count) {
__raw_writeb(*(u8 *)from, to);
from++;
to++;
count--;
}
}
EXPORT_SYMBOL(__memcpy_toio);
/*
* "memset" on IO memory space.
*/
void __memset_io(volatile void __iomem *dst, int c, size_t count)
{
u64 qc = (u8)c;
qc |= qc << 8;
qc |= qc << 16;
qc |= qc << 32;
while (count && !IS_ALIGNED((unsigned long)dst, 8)) {
__raw_writeb(c, dst);
dst++;
count--;
}
while (count >= 8) {
__raw_writeq(qc, dst);
dst += 8;
count -= 8;
}
while (count) {
__raw_writeb(c, dst);
dst++;
count--;
}
}
EXPORT_SYMBOL(__memset_io);

View File

@ -31,17 +31,6 @@
#define writel(v,c) ({ wmb(); writel_relaxed((v),(c)); mb(); })
#endif
/*
* String version of I/O memory access operations.
*/
extern void __memcpy_fromio(void *, const volatile void __iomem *, size_t);
extern void __memcpy_toio(volatile void __iomem *, const void *, size_t);
extern void __memset_io(volatile void __iomem *, int, size_t);
#define memset_io(c,v,l) __memset_io((c),(v),(l))
#define memcpy_fromio(a,c,l) __memcpy_fromio((a),(c),(l))
#define memcpy_toio(c,a,l) __memcpy_toio((c),(a),(l))
/*
* I/O memory mapping functions.
*/

View File

@ -39,9 +39,6 @@ extern void *memcpy(void *to, const void *from, size_t l);
#define clear_page(page) memset((page), 0, PAGE_SIZE)
#define copy_page(to, from) memcpy((to), (from), PAGE_SIZE)
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
#define phys_to_page(paddr) (pfn_to_page(PFN_DOWN(paddr)))
struct page;
#include <abi/page.h>

View File

@ -2,7 +2,7 @@
extra-y := vmlinux.lds
obj-y += head.o entry.o atomic.o signal.o traps.o irq.o time.o vdso.o vdso/
obj-y += power.o syscall.o syscall_table.o setup.o io.o
obj-y += power.o syscall.o syscall_table.o setup.o
obj-y += process.o cpu-probe.o ptrace.o stacktrace.o
obj-y += probes/

View File

@ -1,91 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/export.h>
#include <linux/types.h>
#include <linux/io.h>
/*
* Copy data from IO memory space to "real" memory space.
*/
void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count)
{
while (count && !IS_ALIGNED((unsigned long)from, 4)) {
*(u8 *)to = __raw_readb(from);
from++;
to++;
count--;
}
while (count >= 4) {
*(u32 *)to = __raw_readl(from);
from += 4;
to += 4;
count -= 4;
}
while (count) {
*(u8 *)to = __raw_readb(from);
from++;
to++;
count--;
}
}
EXPORT_SYMBOL(__memcpy_fromio);
/*
* Copy data from "real" memory space to IO memory space.
*/
void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count)
{
while (count && !IS_ALIGNED((unsigned long)to, 4)) {
__raw_writeb(*(u8 *)from, to);
from++;
to++;
count--;
}
while (count >= 4) {
__raw_writel(*(u32 *)from, to);
from += 4;
to += 4;
count -= 4;
}
while (count) {
__raw_writeb(*(u8 *)from, to);
from++;
to++;
count--;
}
}
EXPORT_SYMBOL(__memcpy_toio);
/*
* "memset" on IO memory space.
*/
void __memset_io(volatile void __iomem *dst, int c, size_t count)
{
u32 qc = (u8)c;
qc |= qc << 8;
qc |= qc << 16;
while (count && !IS_ALIGNED((unsigned long)dst, 4)) {
__raw_writeb(c, dst);
dst++;
count--;
}
while (count >= 4) {
__raw_writel(qc, dst);
dst += 4;
count -= 4;
}
while (count) {
__raw_writeb(c, dst);
dst++;
count--;
}
}
EXPORT_SYMBOL(__memset_io);

View File

@ -30,8 +30,6 @@ config HEXAGON
select HAVE_ARCH_KGDB
select HAVE_ARCH_TRACEHOOK
select NEED_SG_DMA_LENGTH
select NO_IOPORT_MAP
select GENERIC_IOMAP
select GENERIC_IOREMAP
select GENERIC_SMP_IDLE_THREAD
select STACKTRACE_SUPPORT
@ -59,6 +57,9 @@ config EARLY_PRINTK
config MMU
def_bool y
config NO_IOPORT_MAP
def_bool y
config GENERIC_CSUM
def_bool y

View File

@ -8,38 +8,13 @@
#ifndef _ASM_IO_H
#define _ASM_IO_H
#ifdef __KERNEL__
#include <linux/types.h>
#include <asm/iomap.h>
#include <asm/page.h>
#include <asm/cacheflush.h>
/*
* We don't have PCI yet.
* _IO_BASE is pointing at what should be unused virtual space.
*/
#define IO_SPACE_LIMIT 0xffff
#define _IO_BASE ((void __iomem *)0xfe000000)
#define IOMEM(x) ((void __force __iomem *)(x))
extern int remap_area_pages(unsigned long start, unsigned long phys_addr,
unsigned long end, unsigned long flags);
/* Defined in lib/io.c, needed for smc91x driver. */
extern void __raw_readsw(const void __iomem *addr, void *data, int wordlen);
extern void __raw_writesw(void __iomem *addr, const void *data, int wordlen);
extern void __raw_readsl(const void __iomem *addr, void *data, int wordlen);
extern void __raw_writesl(void __iomem *addr, const void *data, int wordlen);
#define readsw(p, d, l) __raw_readsw(p, d, l)
#define writesw(p, d, l) __raw_writesw(p, d, l)
#define readsl(p, d, l) __raw_readsl(p, d, l)
#define writesl(p, d, l) __raw_writesl(p, d, l)
/*
* virt_to_phys - map virtual address to physical
* @address: address to map
@ -58,21 +33,12 @@ static inline void *phys_to_virt(unsigned long address)
return __va(address);
}
/*
* IO port access primitives. Hexagon doesn't have special IO access
* instructions; all I/O is memory mapped.
*
* in/out are used for "ports", but we don't have "port instructions",
* so these are really just memory mapped too.
*/
/*
* readb - read byte from memory mapped device
* @addr: pointer to memory
*
* Operates on "I/O bus memory space"
*/
static inline u8 readb(const volatile void __iomem *addr)
static inline u8 __raw_readb(const volatile void __iomem *addr)
{
u8 val;
asm volatile(
@ -82,8 +48,9 @@ static inline u8 readb(const volatile void __iomem *addr)
);
return val;
}
#define __raw_readb __raw_readb
static inline u16 readw(const volatile void __iomem *addr)
static inline u16 __raw_readw(const volatile void __iomem *addr)
{
u16 val;
asm volatile(
@ -93,8 +60,9 @@ static inline u16 readw(const volatile void __iomem *addr)
);
return val;
}
#define __raw_readw __raw_readw
static inline u32 readl(const volatile void __iomem *addr)
static inline u32 __raw_readl(const volatile void __iomem *addr)
{
u32 val;
asm volatile(
@ -104,6 +72,7 @@ static inline u32 readl(const volatile void __iomem *addr)
);
return val;
}
#define __raw_readl __raw_readl
/*
* writeb - write a byte to a memory location
@ -111,7 +80,7 @@ static inline u32 readl(const volatile void __iomem *addr)
* @addr: pointer to memory
*
*/
static inline void writeb(u8 data, volatile void __iomem *addr)
static inline void __raw_writeb(u8 data, volatile void __iomem *addr)
{
asm volatile(
"memb(%0) = %1;"
@ -120,8 +89,9 @@ static inline void writeb(u8 data, volatile void __iomem *addr)
: "memory"
);
}
#define __raw_writeb __raw_writeb
static inline void writew(u16 data, volatile void __iomem *addr)
static inline void __raw_writew(u16 data, volatile void __iomem *addr)
{
asm volatile(
"memh(%0) = %1;"
@ -131,8 +101,9 @@ static inline void writew(u16 data, volatile void __iomem *addr)
);
}
#define __raw_writew __raw_writew
static inline void writel(u32 data, volatile void __iomem *addr)
static inline void __raw_writel(u32 data, volatile void __iomem *addr)
{
asm volatile(
"memw(%0) = %1;"
@ -141,26 +112,7 @@ static inline void writel(u32 data, volatile void __iomem *addr)
: "memory"
);
}
#define __raw_writeb writeb
#define __raw_writew writew
#define __raw_writel writel
#define __raw_readb readb
#define __raw_readw readw
#define __raw_readl readl
/*
* http://comments.gmane.org/gmane.linux.ports.arm.kernel/117626
*/
#define readb_relaxed __raw_readb
#define readw_relaxed __raw_readw
#define readl_relaxed __raw_readl
#define writeb_relaxed __raw_writeb
#define writew_relaxed __raw_writew
#define writel_relaxed __raw_writel
#define __raw_writel __raw_writel
/*
* I/O memory mapping functions.
@ -168,140 +120,6 @@ static inline void writel(u32 data, volatile void __iomem *addr)
#define _PAGE_IOREMAP (_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
(__HEXAGON_C_DEV << 6))
#define __raw_writel writel
static inline void memcpy_fromio(void *dst, const volatile void __iomem *src,
int count)
{
memcpy(dst, (void *) src, count);
}
static inline void memcpy_toio(volatile void __iomem *dst, const void *src,
int count)
{
memcpy((void *) dst, src, count);
}
static inline void memset_io(volatile void __iomem *addr, int value,
size_t size)
{
memset((void __force *)addr, value, size);
}
#define PCI_IO_ADDR (volatile void __iomem *)
/*
* inb - read byte from I/O port or something
* @port: address in I/O space
*
* Operates on "I/O bus I/O space"
*/
static inline u8 inb(unsigned long port)
{
return readb(_IO_BASE + (port & IO_SPACE_LIMIT));
}
static inline u16 inw(unsigned long port)
{
return readw(_IO_BASE + (port & IO_SPACE_LIMIT));
}
static inline u32 inl(unsigned long port)
{
return readl(_IO_BASE + (port & IO_SPACE_LIMIT));
}
/*
* outb - write a byte to a memory location
* @data: data to write to
* @addr: address in I/O space
*/
static inline void outb(u8 data, unsigned long port)
{
writeb(data, _IO_BASE + (port & IO_SPACE_LIMIT));
}
static inline void outw(u16 data, unsigned long port)
{
writew(data, _IO_BASE + (port & IO_SPACE_LIMIT));
}
static inline void outl(u32 data, unsigned long port)
{
writel(data, _IO_BASE + (port & IO_SPACE_LIMIT));
}
#define outb_p outb
#define outw_p outw
#define outl_p outl
#define inb_p inb
#define inw_p inw
#define inl_p inl
static inline void insb(unsigned long port, void *buffer, int count)
{
if (count) {
u8 *buf = buffer;
do {
u8 x = inb(port);
*buf++ = x;
} while (--count);
}
}
static inline void insw(unsigned long port, void *buffer, int count)
{
if (count) {
u16 *buf = buffer;
do {
u16 x = inw(port);
*buf++ = x;
} while (--count);
}
}
static inline void insl(unsigned long port, void *buffer, int count)
{
if (count) {
u32 *buf = buffer;
do {
u32 x = inw(port);
*buf++ = x;
} while (--count);
}
}
static inline void outsb(unsigned long port, const void *buffer, int count)
{
if (count) {
const u8 *buf = buffer;
do {
outb(*buf++, port);
} while (--count);
}
}
static inline void outsw(unsigned long port, const void *buffer, int count)
{
if (count) {
const u16 *buf = buffer;
do {
outw(*buf++, port);
} while (--count);
}
}
static inline void outsl(unsigned long port, const void *buffer, int count)
{
if (count) {
const u32 *buf = buffer;
do {
outl(*buf++, port);
} while (--count);
}
}
/*
* These defines are necessary to use the generic io.h for filling in
* the missing parts of the API contract. This is because the platform
@ -310,23 +128,6 @@ static inline void outsl(unsigned long port, const void *buffer, int count)
*/
#define virt_to_phys virt_to_phys
#define phys_to_virt phys_to_virt
#define memset_io memset_io
#define memcpy_fromio memcpy_fromio
#define memcpy_toio memcpy_toio
#define readb readb
#define readw readw
#define readl readl
#define writeb writeb
#define writew writew
#define writel writel
#define insb insb
#define insw insw
#define insl insl
#define outsb outsb
#define outsw outsw
#define outsl outsl
#include <asm-generic/io.h>
#endif /* __KERNEL__ */
#endif

View File

@ -116,12 +116,6 @@ static inline void clear_page(void *page)
#define clear_user_page(page, vaddr, pg) clear_page(page)
#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
/*
* page_to_phys - convert page to physical address
* @page - pointer to page entry in mem_map
*/
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
static inline unsigned long virt_to_pfn(const void *kaddr)
{
return __pa(kaddr) >> PAGE_SHIFT;

View File

@ -2,5 +2,5 @@
#
# Makefile for hexagon-specific library files.
#
obj-y = checksum.o io.o memcpy.o memset.o memcpy_likely_aligned.o \
obj-y = checksum.o memcpy.o memset.o memcpy_likely_aligned.o \
divsi3.o modsi3.o udivsi3.o umodsi3.o

View File

@ -1,82 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* I/O access functions for Hexagon
*
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
*/
#include <asm/io.h>
/* These are all FIFO routines! */
/*
* __raw_readsw - read words a short at a time
* @addr: source address
* @data: data address
* @len: number of shorts to read
*/
void __raw_readsw(const void __iomem *addr, void *data, int len)
{
const volatile short int *src = (short int *) addr;
short int *dst = (short int *) data;
if ((u32)data & 0x1)
panic("unaligned pointer to readsw");
while (len-- > 0)
*dst++ = *src;
}
EXPORT_SYMBOL(__raw_readsw);
/*
* __raw_writesw - read words a short at a time
* @addr: source address
* @data: data address
* @len: number of shorts to read
*/
void __raw_writesw(void __iomem *addr, const void *data, int len)
{
const short int *src = (short int *)data;
volatile short int *dst = (short int *)addr;
if ((u32)data & 0x1)
panic("unaligned pointer to writesw");
while (len-- > 0)
*dst = *src++;
}
EXPORT_SYMBOL(__raw_writesw);
/* Pretty sure len is pre-adjusted for the length of the access already */
void __raw_readsl(const void __iomem *addr, void *data, int len)
{
const volatile long *src = (long *) addr;
long *dst = (long *) data;
if ((u32)data & 0x3)
panic("unaligned pointer to readsl");
while (len-- > 0)
*dst++ = *src;
}
EXPORT_SYMBOL(__raw_readsl);
void __raw_writesl(void __iomem *addr, const void *data, int len)
{
const long *src = (long *)data;
volatile long *dst = (long *)addr;
if ((u32)data & 0x3)
panic("unaligned pointer to writesl");
while (len-- > 0)
*dst = *src++;
}
EXPORT_SYMBOL(__raw_writesl);

View File

@ -62,16 +62,6 @@ static inline void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
#define mmiowb() wmb()
/*
* String version of I/O memory access operations.
*/
extern void __memset_io(volatile void __iomem *dst, int c, size_t count);
extern void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count);
extern void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count);
#define memset_io(c, v, l) __memset_io((c), (v), (l))
#define memcpy_fromio(a, c, l) __memcpy_fromio((a), (c), (l))
#define memcpy_toio(c, a, l) __memcpy_toio((c), (a), (l))
#define __io_aw() mmiowb()
#ifdef CONFIG_KFENCE

View File

@ -76,9 +76,6 @@ struct page *tlb_virt_to_page(unsigned long kaddr);
#define pfn_to_phys(pfn) __pfn_to_phys(pfn)
#define phys_to_pfn(paddr) __phys_to_pfn(paddr)
#define page_to_phys(page) pfn_to_phys(page_to_pfn(page))
#define phys_to_page(paddr) pfn_to_page(phys_to_pfn(paddr))
#ifndef CONFIG_KFENCE
#define page_to_virt(page) __va(page_to_phys(page))

View File

@ -8,7 +8,7 @@ OBJECT_FILES_NON_STANDARD_head.o := y
extra-y := vmlinux.lds
obj-y += head.o cpu-probe.o cacheinfo.o env.o setup.o entry.o genex.o \
traps.o irq.o idle.o process.o dma.o mem.o io.o reset.o switch.o \
traps.o irq.o idle.o process.o dma.o mem.o reset.o switch.o \
elf.o syscall.o signal.o time.o topology.o inst.o ptrace.o vdso.o \
alternative.o unwind.o

View File

@ -1,94 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
*/
#include <linux/export.h>
#include <linux/types.h>
#include <linux/io.h>
/*
* Copy data from IO memory space to "real" memory space.
*/
void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count)
{
while (count && !IS_ALIGNED((unsigned long)from, 8)) {
*(u8 *)to = __raw_readb(from);
from++;
to++;
count--;
}
while (count >= 8) {
*(u64 *)to = __raw_readq(from);
from += 8;
to += 8;
count -= 8;
}
while (count) {
*(u8 *)to = __raw_readb(from);
from++;
to++;
count--;
}
}
EXPORT_SYMBOL(__memcpy_fromio);
/*
* Copy data from "real" memory space to IO memory space.
*/
void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count)
{
while (count && !IS_ALIGNED((unsigned long)to, 8)) {
__raw_writeb(*(u8 *)from, to);
from++;
to++;
count--;
}
while (count >= 8) {
__raw_writeq(*(u64 *)from, to);
from += 8;
to += 8;
count -= 8;
}
while (count) {
__raw_writeb(*(u8 *)from, to);
from++;
to++;
count--;
}
}
EXPORT_SYMBOL(__memcpy_toio);
/*
* "memset" on IO memory space.
*/
void __memset_io(volatile void __iomem *dst, int c, size_t count)
{
u64 qc = (u8)c;
qc |= qc << 8;
qc |= qc << 16;
qc |= qc << 32;
while (count && !IS_ALIGNED((unsigned long)dst, 8)) {
__raw_writeb(c, dst);
dst++;
count--;
}
while (count >= 8) {
__raw_writeq(qc, dst);
dst += 8;
count -= 8;
}
while (count) {
__raw_writeb(c, dst);
dst++;
count--;
}
}
EXPORT_SYMBOL(__memset_io);

View File

@ -28,9 +28,6 @@ static inline void *phys_to_virt(unsigned long address)
return __va(address);
}
/* Permanent address of a page. */
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
/*
* IO bus memory addresses are 1:1 with the physical address,
* deprecated globally but still used on two machines.

View File

@ -98,7 +98,6 @@ extern int page_is_ram(unsigned long pfn);
# define virt_to_page(kaddr) (pfn_to_page(__pa(kaddr) >> PAGE_SHIFT))
# define page_to_virt(page) __va(page_to_pfn(page) << PAGE_SHIFT)
# define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
# define ARCH_PFN_OFFSET (memory_start >> PAGE_SHIFT)
# endif /* __ASSEMBLY__ */

View File

@ -125,11 +125,6 @@ static inline unsigned long isa_virt_to_bus(volatile void *address)
return virt_to_phys(address);
}
/*
* Change "struct page" to physical address.
*/
#define page_to_phys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
unsigned long prot_val);
void iounmap(const volatile void __iomem *addr);

View File

@ -47,10 +47,6 @@ static inline void scr_memsetw(u16 *s, u16 v, unsigned int count)
memset16(s, cpu_to_le16(v), count / 2);
}
#define scr_memcpyw(d, s, c) memcpy(d, s, c)
#define scr_memmovew(d, s, c) memmove(d, s, c)
#define VT_BUF_HAVE_MEMCPYW
#define VT_BUF_HAVE_MEMMOVEW
#define VT_BUF_HAVE_MEMSETW
#endif /* _ASM_VGA_H */

View File

@ -28,9 +28,6 @@
void __iomem *ioremap(unsigned long physaddr, unsigned long size);
void iounmap(void __iomem *addr);
/* Pages to physical address... */
#define page_to_phys(page) virt_to_phys(page_to_virt(page))
/* Macros used for converting between virtual and physical mappings. */
#define phys_to_virt(vaddr) \
((void *)((unsigned long)(vaddr) | CONFIG_NIOS2_KERNEL_REGION_BASE))

View File

@ -71,8 +71,6 @@ static inline unsigned long virt_to_pfn(const void *kaddr)
#define virt_to_page(addr) \
(mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT))
#define page_to_phys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
#define virt_addr_valid(kaddr) (pfn_valid(virt_to_pfn(kaddr)))
#endif /* __ASSEMBLY__ */

View File

@ -166,7 +166,6 @@ extern int npmem_ranges;
#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
#include <asm-generic/memory_model.h>

View File

@ -969,18 +969,6 @@ static inline void * phys_to_virt(unsigned long address)
}
#define phys_to_virt phys_to_virt
/*
* Change "struct page" to physical address.
*/
static inline phys_addr_t page_to_phys(struct page *page)
{
unsigned long pfn = page_to_pfn(page);
WARN_ON(IS_ENABLED(CONFIG_DEBUG_VIRTUAL) && !pfn_valid(pfn));
return PFN_PHYS(pfn);
}
/*
* 32 bits still uses virt_to_bus() for its implementation of DMA
* mappings se we have to keep it defined here. We also have some old

View File

@ -40,11 +40,6 @@ static inline void scr_memsetw(u16 *s, u16 v, unsigned int n)
memset16(s, cpu_to_le16(v), n / 2);
}
#define VT_BUF_HAVE_MEMCPYW
#define VT_BUF_HAVE_MEMMOVEW
#define scr_memcpyw memcpy
#define scr_memmovew memmove
#endif /* !CONFIG_VGA_CONSOLE && !CONFIG_MDA_CONSOLE */
#ifdef __powerpc64__

View File

@ -192,9 +192,6 @@ extern phys_addr_t __phys_addr_symbol(unsigned long x);
#define virt_to_page(vaddr) (pfn_to_page(virt_to_pfn(vaddr)))
#define page_to_virt(page) (pfn_to_virt(page_to_pfn(page)))
#define page_to_phys(page) (pfn_to_phys(page_to_pfn(page)))
#define phys_to_page(paddr) (pfn_to_page(phys_to_pfn(paddr)))
#define sym_to_pfn(x) __phys_to_pfn(__pa_symbol(x))
unsigned long kaslr_offset(void);

View File

@ -241,9 +241,7 @@ static inline unsigned long __phys_addr(unsigned long x, bool is_31bit)
#define phys_to_pfn(phys) ((phys) >> PAGE_SHIFT)
#define pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT)
#define phys_to_page(phys) pfn_to_page(phys_to_pfn(phys))
#define phys_to_folio(phys) page_folio(phys_to_page(phys))
#define page_to_phys(page) pfn_to_phys(page_to_pfn(page))
#define folio_to_phys(page) pfn_to_phys(folio_pfn(folio))
static inline void *pfn_to_virt(unsigned long pfn)

View File

@ -145,7 +145,6 @@ typedef struct page *pgtable_t;
#endif
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
/*
* PFN = physical frame number (ie PFN 0 == physical address 0)

View File

@ -1,7 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_SH_VGA_H
#define __ASM_SH_VGA_H
/* Stupid drivers. */
#endif /* __ASM_SH_VGA_H */

View File

@ -2,8 +2,6 @@
#ifndef ___ASM_SPARC_PAGE_H
#define ___ASM_SPARC_PAGE_H
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
#if defined(__sparc__) && defined(__arch64__)
#include <asm/page_64.h>
#else

View File

@ -1,60 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Access to VGA videoram
*
* (c) 1998 Martin Mares <mj@ucw.cz>
*/
#ifndef _LINUX_ASM_VGA_H_
#define _LINUX_ASM_VGA_H_
#include <linux/bug.h>
#include <linux/string.h>
#include <asm/types.h>
#define VT_BUF_HAVE_RW
#define VT_BUF_HAVE_MEMSETW
#define VT_BUF_HAVE_MEMCPYW
#define VT_BUF_HAVE_MEMMOVEW
#undef scr_writew
#undef scr_readw
static inline void scr_writew(u16 val, u16 *addr)
{
BUG_ON((long) addr >= 0);
*addr = val;
}
static inline u16 scr_readw(const u16 *addr)
{
BUG_ON((long) addr >= 0);
return *addr;
}
static inline void scr_memsetw(u16 *p, u16 v, unsigned int n)
{
BUG_ON((long) p >= 0);
memset16(p, cpu_to_le16(v), n / 2);
}
static inline void scr_memcpyw(u16 *d, u16 *s, unsigned int n)
{
BUG_ON((long) d >= 0);
memcpy(d, s, n);
}
static inline void scr_memmovew(u16 *d, u16 *s, unsigned int n)
{
BUG_ON((long) d >= 0);
memmove(d, s, n);
}
#define VGA_MAP_MEM(x,s) (x)
#endif

View File

@ -287,9 +287,7 @@ static inline int pte_same(pte_t pte_a, pte_t pte_b)
* and a page entry and page directory to the page they refer to.
*/
#define phys_to_page(phys) pfn_to_page(phys_to_pfn(phys))
#define __virt_to_page(virt) phys_to_page(__pa(virt))
#define page_to_phys(page) pfn_to_phys(page_to_pfn(page))
#define virt_to_page(addr) __virt_to_page((const unsigned long) addr)
#define mk_pte(page, pgprot) \

View File

@ -151,11 +151,6 @@ static inline void *phys_to_virt(phys_addr_t address)
}
#define phys_to_virt phys_to_virt
/*
* Change "struct page" to physical address.
*/
#define page_to_phys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
/*
* ISA I/O bus memory addresses are 1:1 with the physical address.
* However, we truncate the address to unsigned int to avoid undesirable

View File

@ -189,7 +189,6 @@ static inline unsigned long ___pa(unsigned long va)
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
#define page_to_virt(page) __va(page_to_pfn(page) << PAGE_SHIFT)
#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
#endif /* __ASSEMBLY__ */

View File

@ -336,7 +336,7 @@ config BT_HCIBFUSB
config BT_HCIDTL1
tristate "HCI DTL1 (PC Card) driver"
depends on PCMCIA
depends on PCMCIA && HAS_IOPORT
help
Bluetooth HCI DTL1 (PC Card) driver.
This driver provides support for Bluetooth PCMCIA devices with
@ -349,7 +349,7 @@ config BT_HCIDTL1
config BT_HCIBT3C
tristate "HCI BT3C (PC Card) driver"
depends on PCMCIA
depends on PCMCIA && HAS_IOPORT
select FW_LOADER
help
Bluetooth HCI BT3C (PC Card) driver.
@ -363,7 +363,7 @@ config BT_HCIBT3C
config BT_HCIBLUECARD
tristate "HCI BlueCard (PC Card) driver"
depends on PCMCIA
depends on PCMCIA && HAS_IOPORT
help
Bluetooth HCI BlueCard (PC Card) driver.
This driver provides support for Bluetooth PCMCIA devices with

View File

@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config DRM_GMA500
tristate "Intel GMA500/600/3600/3650 KMS Framebuffer"
depends on DRM && PCI && X86 && MMU
depends on DRM && PCI && X86 && MMU && HAS_IOPORT
select DRM_KMS_HELPER
select FB_IOMEM_HELPERS if DRM_FBDEV_EMULATION
select I2C

View File

@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config DRM_QXL
tristate "QXL virtual GPU"
depends on DRM && PCI && MMU
depends on DRM && PCI && MMU && HAS_IOPORT
select DRM_KMS_HELPER
select DRM_TTM
select DRM_TTM_HELPER

View File

@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <linux/bug.h>
#include <linux/module.h>
#include <linux/pci.h>
@ -95,12 +96,17 @@ struct bochs_device {
/* ---------------------------------------------------------------------- */
static __always_inline bool bochs_uses_mmio(struct bochs_device *bochs)
{
return !IS_ENABLED(CONFIG_HAS_IOPORT) || bochs->mmio;
}
static void bochs_vga_writeb(struct bochs_device *bochs, u16 ioport, u8 val)
{
if (WARN_ON(ioport < 0x3c0 || ioport > 0x3df))
return;
if (bochs->mmio) {
if (bochs_uses_mmio(bochs)) {
int offset = ioport - 0x3c0 + 0x400;
writeb(val, bochs->mmio + offset);
@ -114,7 +120,7 @@ static u8 bochs_vga_readb(struct bochs_device *bochs, u16 ioport)
if (WARN_ON(ioport < 0x3c0 || ioport > 0x3df))
return 0xff;
if (bochs->mmio) {
if (bochs_uses_mmio(bochs)) {
int offset = ioport - 0x3c0 + 0x400;
return readb(bochs->mmio + offset);
@ -127,7 +133,7 @@ static u16 bochs_dispi_read(struct bochs_device *bochs, u16 reg)
{
u16 ret = 0;
if (bochs->mmio) {
if (bochs_uses_mmio(bochs)) {
int offset = 0x500 + (reg << 1);
ret = readw(bochs->mmio + offset);
@ -140,7 +146,7 @@ static u16 bochs_dispi_read(struct bochs_device *bochs, u16 reg)
static void bochs_dispi_write(struct bochs_device *bochs, u16 reg, u16 val)
{
if (bochs->mmio) {
if (bochs_uses_mmio(bochs)) {
int offset = 0x500 + (reg << 1);
writew(val, bochs->mmio + offset);
@ -228,7 +234,7 @@ static int bochs_hw_init(struct drm_device *dev)
DRM_ERROR("Cannot map mmio region\n");
return -ENOMEM;
}
} else {
} else if (IS_ENABLED(CONFIG_HAS_IOPORT)) {
ioaddr = VBE_DISPI_IOPORT_INDEX;
iosize = 2;
if (!request_region(ioaddr, iosize, "bochs-drm")) {
@ -236,6 +242,9 @@ static int bochs_hw_init(struct drm_device *dev)
return -EBUSY;
}
bochs->ioports = 1;
} else {
dev_err(dev->dev, "I/O ports are not supported\n");
return -EIO;
}
id = bochs_dispi_read(bochs, VBE_DISPI_INDEX_ID);

View File

@ -509,8 +509,10 @@ static void cirrus_crtc_helper_atomic_enable(struct drm_crtc *crtc,
cirrus_mode_set(cirrus, &crtc_state->mode);
#ifdef CONFIG_HAS_IOPORT
/* Unblank (needed on S3 resume, vgabios doesn't do it then) */
outb(VGA_AR_ENABLE_DISPLAY, VGA_ATT_W);
#endif
drm_dev_exit(idx);
}

View File

@ -49,7 +49,7 @@ config DRM_XE
config DRM_XE_DISPLAY
bool "Enable display support"
depends on DRM_XE && DRM_XE=m
depends on DRM_XE && DRM_XE=m && HAS_IOPORT
select FB_IOMEM_HELPERS
select I2C
select I2C_ALGOBIT

View File

@ -220,7 +220,7 @@ config MOXA_INTELLIO
config MOXA_SMARTIO
tristate "Moxa SmartIO support v. 2.0"
depends on SERIAL_NONSTANDARD && PCI
depends on SERIAL_NONSTANDARD && PCI && HAS_IOPORT
help
Say Y here if you have a Moxa SmartIO multiport serial card and/or
want to help develop a new version of this driver.
@ -302,7 +302,7 @@ config GOLDFISH_TTY_EARLY_CONSOLE
config IPWIRELESS
tristate "IPWireless 3G UMTS PCMCIA card support"
depends on PCMCIA && NETDEVICES
depends on PCMCIA && NETDEVICES && HAS_IOPORT
select PPP
help
This is a driver for 3G UMTS PCMCIA card from IPWireless company. In

View File

@ -46,8 +46,10 @@ static unsigned int serial8250_early_in(struct uart_port *port, int offset)
return readl(port->membase + offset);
case UPIO_MEM32BE:
return ioread32be(port->membase + offset);
#ifdef CONFIG_HAS_IOPORT
case UPIO_PORT:
return inb(port->iobase + offset);
#endif
default:
return 0;
}
@ -70,9 +72,11 @@ static void serial8250_early_out(struct uart_port *port, int offset, int value)
case UPIO_MEM32BE:
iowrite32be(value, port->membase + offset);
break;
#ifdef CONFIG_HAS_IOPORT
case UPIO_PORT:
outb(value, port->iobase + offset);
break;
#endif
}
}

View File

@ -964,6 +964,9 @@ static int pci_ite887x_init(struct pci_dev *dev)
struct resource *iobase = NULL;
u32 miscr, uartbar, ioport;
if (!IS_ENABLED(CONFIG_HAS_IOPORT))
return serial_8250_warn_need_ioport(dev);
/* search for the base-ioport */
for (i = 0; i < ARRAY_SIZE(inta_addr); i++) {
iobase = request_region(inta_addr[i], ITE_887x_IOSIZE,
@ -1514,6 +1517,9 @@ static int pci_quatech_init(struct pci_dev *dev)
const struct pci_device_id *match;
bool amcc = false;
if (!IS_ENABLED(CONFIG_HAS_IOPORT))
return serial_8250_warn_need_ioport(dev);
match = pci_match_id(quatech_cards, dev);
if (match)
amcc = match->driver_data;
@ -1538,6 +1544,9 @@ static int pci_quatech_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
{
if (!IS_ENABLED(CONFIG_HAS_IOPORT))
return serial_8250_warn_need_ioport(priv->dev);
/* Needed by pci_quatech calls below */
port->port.iobase = pci_resource_start(priv->dev, FL_GET_BASE(board->flags));
/* Set up the clocking */
@ -1655,6 +1664,9 @@ static int pci_fintek_setup(struct serial_private *priv,
u8 config_base;
u16 iobase;
if (!IS_ENABLED(CONFIG_HAS_IOPORT))
return serial_8250_warn_need_ioport(pdev);
config_base = 0x40 + 0x08 * idx;
/* Get the io address from configuration space */
@ -1686,6 +1698,9 @@ static int pci_fintek_init(struct pci_dev *dev)
u8 config_base;
struct serial_private *priv = pci_get_drvdata(dev);
if (!IS_ENABLED(CONFIG_HAS_IOPORT))
return serial_8250_warn_need_ioport(dev);
if (!(pci_resource_flags(dev, 5) & IORESOURCE_IO) ||
!(pci_resource_flags(dev, 4) & IORESOURCE_IO) ||
!(pci_resource_flags(dev, 3) & IORESOURCE_IO))
@ -1864,6 +1879,9 @@ static int kt_serial_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
{
if (!IS_ENABLED(CONFIG_HAS_IOPORT))
return serial_8250_warn_need_ioport(priv->dev);
port->port.flags |= UPF_BUG_THRE;
port->port.serial_in = kt_serial_in;
port->port.handle_break = kt_handle_break;
@ -1884,6 +1902,9 @@ pci_wch_ch353_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
{
if (!IS_ENABLED(CONFIG_HAS_IOPORT))
return serial_8250_warn_need_ioport(priv->dev);
port->port.flags |= UPF_FIXED_TYPE;
port->port.type = PORT_16550A;
return pci_default_setup(priv, board, port, idx);
@ -1894,6 +1915,9 @@ pci_wch_ch355_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
{
if (!IS_ENABLED(CONFIG_HAS_IOPORT))
return serial_8250_warn_need_ioport(priv->dev);
port->port.flags |= UPF_FIXED_TYPE;
port->port.type = PORT_16550A;
return pci_default_setup(priv, board, port, idx);
@ -1904,6 +1928,9 @@ pci_wch_ch38x_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
{
if (!IS_ENABLED(CONFIG_HAS_IOPORT))
return serial_8250_warn_need_ioport(priv->dev);
port->port.flags |= UPF_FIXED_TYPE;
port->port.type = PORT_16850;
return pci_default_setup(priv, board, port, idx);
@ -1918,6 +1945,8 @@ static int pci_wch_ch38x_init(struct pci_dev *dev)
int max_port;
unsigned long iobase;
if (!IS_ENABLED(CONFIG_HAS_IOPORT))
return serial_8250_warn_need_ioport(dev);
switch (dev->device) {
case 0x3853: /* 8 ports */
@ -1937,6 +1966,11 @@ static void pci_wch_ch38x_exit(struct pci_dev *dev)
{
unsigned long iobase;
if (!IS_ENABLED(CONFIG_HAS_IOPORT)) {
serial_8250_warn_need_ioport(dev);
return;
}
iobase = pci_resource_start(dev, 0);
outb(0x0, iobase + CH384_XINT_ENABLE_REG);
}
@ -2052,6 +2086,9 @@ static int pci_moxa_init(struct pci_dev *dev)
unsigned int i, num_ports = moxa_get_nports(device);
u8 val, init_mode = MOXA_RS232;
if (!IS_ENABLED(CONFIG_HAS_IOPORT))
return serial_8250_warn_need_ioport(dev);
if (!(pci_moxa_supported_rs(dev) & MOXA_SUPP_RS232)) {
init_mode = MOXA_RS422;
}
@ -2084,6 +2121,9 @@ pci_moxa_setup(struct serial_private *priv,
unsigned int bar = FL_GET_BASE(board->flags);
int offset;
if (!IS_ENABLED(CONFIG_HAS_IOPORT))
return serial_8250_warn_need_ioport(priv->dev);
if (board->num_ports == 4 && idx == 3)
offset = 7 * board->uart_offset;
else

View File

@ -12,6 +12,15 @@
#include "8250.h"
#include "8250_pcilib.h"
int serial_8250_warn_need_ioport(struct pci_dev *dev)
{
dev_warn(&dev->dev,
"Serial port not supported because of missing I/O resource\n");
return -ENXIO;
}
EXPORT_SYMBOL_NS_GPL(serial_8250_warn_need_ioport, SERIAL_8250_PCI);
int serial8250_pci_setup_port(struct pci_dev *dev, struct uart_8250_port *port,
u8 bar, unsigned int offset, int regshift)
{
@ -27,12 +36,14 @@ int serial8250_pci_setup_port(struct pci_dev *dev, struct uart_8250_port *port,
port->port.mapbase = pci_resource_start(dev, bar) + offset;
port->port.membase = pcim_iomap_table(dev)[bar] + offset;
port->port.regshift = regshift;
} else {
} else if (IS_ENABLED(CONFIG_HAS_IOPORT)) {
port->port.iotype = UPIO_PORT;
port->port.iobase = pci_resource_start(dev, bar) + offset;
port->port.mapbase = 0;
port->port.membase = NULL;
port->port.regshift = 0;
} else {
return serial_8250_warn_need_ioport(dev);
}
return 0;
}

View File

@ -13,3 +13,5 @@ struct uart_8250_port;
int serial8250_pci_setup_port(struct pci_dev *dev, struct uart_8250_port *port, u8 bar,
unsigned int offset, int regshift);
int serial_8250_warn_need_ioport(struct pci_dev *dev);

View File

@ -338,6 +338,7 @@ static void default_serial_dl_write(struct uart_8250_port *up, u32 value)
serial_out(up, UART_DLM, value >> 8 & 0xff);
}
#ifdef CONFIG_HAS_IOPORT
static unsigned int hub6_serial_in(struct uart_port *p, int offset)
{
offset = offset << p->regshift;
@ -351,6 +352,7 @@ static void hub6_serial_out(struct uart_port *p, int offset, int value)
outb(p->hub6 - 1 + offset, p->iobase);
outb(value, p->iobase + 1);
}
#endif /* CONFIG_HAS_IOPORT */
static unsigned int mem_serial_in(struct uart_port *p, int offset)
{
@ -400,6 +402,7 @@ static unsigned int mem32be_serial_in(struct uart_port *p, int offset)
return ioread32be(p->membase + offset);
}
#ifdef CONFIG_HAS_IOPORT
static unsigned int io_serial_in(struct uart_port *p, int offset)
{
offset = offset << p->regshift;
@ -411,6 +414,15 @@ static void io_serial_out(struct uart_port *p, int offset, int value)
offset = offset << p->regshift;
outb(value, p->iobase + offset);
}
#endif
static unsigned int no_serial_in(struct uart_port *p, int offset)
{
return (unsigned int)-1;
}
static void no_serial_out(struct uart_port *p, int offset, int value)
{
}
static int serial8250_default_handle_irq(struct uart_port *port);
@ -422,10 +434,12 @@ static void set_io_from_upio(struct uart_port *p)
up->dl_write = default_serial_dl_write;
switch (p->iotype) {
#ifdef CONFIG_HAS_IOPORT
case UPIO_HUB6:
p->serial_in = hub6_serial_in;
p->serial_out = hub6_serial_out;
break;
#endif
case UPIO_MEM:
p->serial_in = mem_serial_in;
@ -446,11 +460,16 @@ static void set_io_from_upio(struct uart_port *p)
p->serial_in = mem32be_serial_in;
p->serial_out = mem32be_serial_out;
break;
default:
#ifdef CONFIG_HAS_IOPORT
case UPIO_PORT:
p->serial_in = io_serial_in;
p->serial_out = io_serial_out;
break;
#endif
default:
WARN(1, "Unsupported UART type %x\n", p->iotype);
p->serial_in = no_serial_in;
p->serial_out = no_serial_out;
}
/* Remember loaded iotype */
up->cur_iotype = p->iotype;
@ -1174,7 +1193,7 @@ static void autoconfig(struct uart_8250_port *up)
*/
scratch = serial_in(up, UART_IER);
serial_out(up, UART_IER, 0);
#ifdef __i386__
#if defined(__i386__) && defined(CONFIG_HAS_IOPORT)
outb(0xff, 0x080);
#endif
/*
@ -1183,7 +1202,7 @@ static void autoconfig(struct uart_8250_port *up)
*/
scratch2 = serial_in(up, UART_IER) & UART_IER_ALL_INTR;
serial_out(up, UART_IER, UART_IER_ALL_INTR);
#ifdef __i386__
#if defined(__i386__) && defined(CONFIG_HAS_IOPORT)
outb(0, 0x080);
#endif
scratch3 = serial_in(up, UART_IER) & UART_IER_ALL_INTR;

View File

@ -72,7 +72,7 @@ config SERIAL_8250_16550A_VARIANTS
config SERIAL_8250_FINTEK
bool "Support for Fintek variants"
depends on SERIAL_8250
depends on SERIAL_8250 && HAS_IOPORT
help
Selecting this option will add support for the RS232 and RS485
capabilities of the Fintek F81216A LPC to 4 UART as well similar
@ -163,7 +163,7 @@ config SERIAL_8250_HP300
config SERIAL_8250_CS
tristate "8250/16550 PCMCIA device support"
depends on PCMCIA && SERIAL_8250
depends on PCMCIA && SERIAL_8250 && HAS_IOPORT
help
Say Y here to enable support for 16-bit PCMCIA serial devices,
including serial port cards, modems, and the modem functions of

View File

@ -877,7 +877,7 @@ config SERIAL_TXX9_STDSERIAL
config SERIAL_JSM
tristate "Digi International NEO and Classic PCI Support"
depends on PCI
depends on PCI && HAS_IOPORT
select SERIAL_CORE
help
This is a driver for Digi International's Neo and Classic series

View File

@ -1519,7 +1519,7 @@ config 60XX_WDT
config SBC8360_WDT
tristate "SBC8360 Watchdog Timer"
depends on X86_32
depends on X86_32 && HAS_IOPORT
help
This is the driver for the hardware watchdog on the SBC8360 Single
@ -1532,7 +1532,7 @@ config SBC8360_WDT
config SBC7240_WDT
tristate "SBC Nano 7240 Watchdog Timer"
depends on X86_32 && !UML
depends on X86_32 && HAS_IOPORT
help
This is the driver for the hardware watchdog found on the IEI
single board computers EPIC Nano 7240 (and likely others). This

View File

@ -74,7 +74,8 @@
* do the trick here). \
*/ \
uint64_t ___res, ___x, ___t, ___m, ___n = (n); \
uint32_t ___p, ___bias; \
uint32_t ___p; \
bool ___bias = false; \
\
/* determine MSB of b */ \
___p = 1 << ilog2(___b); \
@ -87,22 +88,14 @@
___x = ~0ULL / ___b * ___b - 1; \
\
/* test our ___m with res = m * x / (p << 64) */ \
___res = ((___m & 0xffffffff) * (___x & 0xffffffff)) >> 32; \
___t = ___res += (___m & 0xffffffff) * (___x >> 32); \
___res += (___x & 0xffffffff) * (___m >> 32); \
___t = (___res < ___t) ? (1ULL << 32) : 0; \
___res = (___res >> 32) + ___t; \
___res += (___m >> 32) * (___x >> 32); \
___res /= ___p; \
___res = (___m & 0xffffffff) * (___x & 0xffffffff); \
___t = (___m & 0xffffffff) * (___x >> 32) + (___res >> 32); \
___res = (___m >> 32) * (___x >> 32) + (___t >> 32); \
___t = (___m >> 32) * (___x & 0xffffffff) + (___t & 0xffffffff);\
___res = (___res + (___t >> 32)) / ___p; \
\
/* Now sanitize and optimize what we've got. */ \
if (~0ULL % (___b / (___b & -___b)) == 0) { \
/* special case, can be simplified to ... */ \
___n /= (___b & -___b); \
___m = ~0ULL / (___b / (___b & -___b)); \
___p = 1; \
___bias = 1; \
} else if (___res != ___x / ___b) { \
/* Now validate what we've got. */ \
if (___res != ___x / ___b) { \
/* \
* We can't get away without a bias to compensate \
* for bit truncation errors. To avoid it we'd need an \
@ -111,45 +104,18 @@
* \
* Instead we do m = p / b and n / b = (n * m + m) / p. \
*/ \
___bias = 1; \
___bias = true; \
/* Compute m = (p << 64) / b */ \
___m = (~0ULL / ___b) * ___p; \
___m += ((~0ULL % ___b + 1) * ___p) / ___b; \
} else { \
/* \
* Reduce m / p, and try to clear bit 31 of m when \
* possible, otherwise that'll need extra overflow \
* handling later. \
*/ \
uint32_t ___bits = -(___m & -___m); \
___bits |= ___m >> 32; \
___bits = (~___bits) << 1; \
/* \
* If ___bits == 0 then setting bit 31 is unavoidable. \
* Simply apply the maximum possible reduction in that \
* case. Otherwise the MSB of ___bits indicates the \
* best reduction we should apply. \
*/ \
if (!___bits) { \
___p /= (___m & -___m); \
___m /= (___m & -___m); \
} else { \
___p >>= ilog2(___bits); \
___m >>= ilog2(___bits); \
} \
/* No bias needed. */ \
___bias = 0; \
} \
\
/* Reduce m / p to help avoid overflow handling later. */ \
___p /= (___m & -___m); \
___m /= (___m & -___m); \
\
/* \
* Now we have a combination of 2 conditions: \
* \
* 1) whether or not we need to apply a bias, and \
* \
* 2) whether or not there might be an overflow in the cross \
* product determined by (___m & ((1 << 63) | (1 << 31))). \
* \
* Select the best way to do (m_bias + m * n) / (1 << 64). \
* Perform (m_bias + m * n) / (1 << 64). \
* From now on there will be actual runtime code generated. \
*/ \
___res = __arch_xprod_64(___m, ___n, ___bias); \
@ -165,47 +131,42 @@
* Semantic: retval = ((bias ? m : 0) + m * n) >> 64
*
* The product is a 128-bit value, scaled down to 64 bits.
* Assuming constant propagation to optimize away unused conditional code.
* Hoping for compile-time optimization of conditional code.
* Architectures may provide their own optimized assembly implementation.
*/
static inline uint64_t __arch_xprod_64(const uint64_t m, uint64_t n, bool bias)
#ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE
static __always_inline
#else
static inline
#endif
uint64_t __arch_xprod_64(const uint64_t m, uint64_t n, bool bias)
{
uint32_t m_lo = m;
uint32_t m_hi = m >> 32;
uint32_t n_lo = n;
uint32_t n_hi = n >> 32;
uint64_t res;
uint32_t res_lo, res_hi, tmp;
uint64_t x, y;
if (!bias) {
res = ((uint64_t)m_lo * n_lo) >> 32;
} else if (!(m & ((1ULL << 63) | (1ULL << 31)))) {
/* there can't be any overflow here */
res = (m + (uint64_t)m_lo * n_lo) >> 32;
/* Determine if overflow handling can be dispensed with. */
bool no_ovf = __builtin_constant_p(m) &&
((m >> 32) + (m & 0xffffffff) < 0x100000000);
if (no_ovf) {
x = (uint64_t)m_lo * n_lo + (bias ? m : 0);
x >>= 32;
x += (uint64_t)m_lo * n_hi;
x += (uint64_t)m_hi * n_lo;
x >>= 32;
x += (uint64_t)m_hi * n_hi;
} else {
res = m + (uint64_t)m_lo * n_lo;
res_lo = res >> 32;
res_hi = (res_lo < m_hi);
res = res_lo | ((uint64_t)res_hi << 32);
x = (uint64_t)m_lo * n_lo + (bias ? m_lo : 0);
y = (uint64_t)m_lo * n_hi + (uint32_t)(x >> 32) + (bias ? m_hi : 0);
x = (uint64_t)m_hi * n_hi + (uint32_t)(y >> 32);
y = (uint64_t)m_hi * n_lo + (uint32_t)y;
x += (uint32_t)(y >> 32);
}
if (!(m & ((1ULL << 63) | (1ULL << 31)))) {
/* there can't be any overflow here */
res += (uint64_t)m_lo * n_hi;
res += (uint64_t)m_hi * n_lo;
res >>= 32;
} else {
res += (uint64_t)m_lo * n_hi;
tmp = res >> 32;
res += (uint64_t)m_hi * n_lo;
res_lo = res >> 32;
res_hi = (res_lo < tmp);
res = res_lo | ((uint64_t)res_hi << 32);
}
res += (uint64_t)m_hi * n_hi;
return res;
return x;
}
#endif

View File

@ -540,6 +540,7 @@ static inline void writesq(volatile void __iomem *addr, const void *buffer,
#if !defined(inb) && !defined(_inb)
#define _inb _inb
#ifdef CONFIG_HAS_IOPORT
static inline u8 _inb(unsigned long addr)
{
u8 val;
@ -549,10 +550,15 @@ static inline u8 _inb(unsigned long addr)
__io_par(val);
return val;
}
#else
u8 _inb(unsigned long addr)
__compiletime_error("inb()) requires CONFIG_HAS_IOPORT");
#endif
#endif
#if !defined(inw) && !defined(_inw)
#define _inw _inw
#ifdef CONFIG_HAS_IOPORT
static inline u16 _inw(unsigned long addr)
{
u16 val;
@ -562,10 +568,15 @@ static inline u16 _inw(unsigned long addr)
__io_par(val);
return val;
}
#else
u16 _inw(unsigned long addr)
__compiletime_error("inw() requires CONFIG_HAS_IOPORT");
#endif
#endif
#if !defined(inl) && !defined(_inl)
#define _inl _inl
#ifdef CONFIG_HAS_IOPORT
static inline u32 _inl(unsigned long addr)
{
u32 val;
@ -575,36 +586,55 @@ static inline u32 _inl(unsigned long addr)
__io_par(val);
return val;
}
#else
u32 _inl(unsigned long addr)
__compiletime_error("inl() requires CONFIG_HAS_IOPORT");
#endif
#endif
#if !defined(outb) && !defined(_outb)
#define _outb _outb
#ifdef CONFIG_HAS_IOPORT
static inline void _outb(u8 value, unsigned long addr)
{
__io_pbw();
__raw_writeb(value, PCI_IOBASE + addr);
__io_paw();
}
#else
void _outb(u8 value, unsigned long addr)
__compiletime_error("outb() requires CONFIG_HAS_IOPORT");
#endif
#endif
#if !defined(outw) && !defined(_outw)
#define _outw _outw
#ifdef CONFIG_HAS_IOPORT
static inline void _outw(u16 value, unsigned long addr)
{
__io_pbw();
__raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr);
__io_paw();
}
#else
void _outw(u16 value, unsigned long addr)
__compiletime_error("outw() requires CONFIG_HAS_IOPORT");
#endif
#endif
#if !defined(outl) && !defined(_outl)
#define _outl _outl
#ifdef CONFIG_HAS_IOPORT
static inline void _outl(u32 value, unsigned long addr)
{
__io_pbw();
__raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr);
__io_paw();
}
#else
void _outl(u32 value, unsigned long addr)
__compiletime_error("outl() requires CONFIG_HAS_IOPORT");
#endif
#endif
#include <linux/logic_pio.h>
@ -688,53 +718,83 @@ static inline void outl_p(u32 value, unsigned long addr)
#ifndef insb
#define insb insb
#ifdef CONFIG_HAS_IOPORT
static inline void insb(unsigned long addr, void *buffer, unsigned int count)
{
readsb(PCI_IOBASE + addr, buffer, count);
}
#else
void insb(unsigned long addr, void *buffer, unsigned int count)
__compiletime_error("insb() requires HAS_IOPORT");
#endif
#endif
#ifndef insw
#define insw insw
#ifdef CONFIG_HAS_IOPORT
static inline void insw(unsigned long addr, void *buffer, unsigned int count)
{
readsw(PCI_IOBASE + addr, buffer, count);
}
#else
void insw(unsigned long addr, void *buffer, unsigned int count)
__compiletime_error("insw() requires HAS_IOPORT");
#endif
#endif
#ifndef insl
#define insl insl
#ifdef CONFIG_HAS_IOPORT
static inline void insl(unsigned long addr, void *buffer, unsigned int count)
{
readsl(PCI_IOBASE + addr, buffer, count);
}
#else
void insl(unsigned long addr, void *buffer, unsigned int count)
__compiletime_error("insl() requires HAS_IOPORT");
#endif
#endif
#ifndef outsb
#define outsb outsb
#ifdef CONFIG_HAS_IOPORT
static inline void outsb(unsigned long addr, const void *buffer,
unsigned int count)
{
writesb(PCI_IOBASE + addr, buffer, count);
}
#else
void outsb(unsigned long addr, const void *buffer, unsigned int count)
__compiletime_error("outsb() requires HAS_IOPORT");
#endif
#endif
#ifndef outsw
#define outsw outsw
#ifdef CONFIG_HAS_IOPORT
static inline void outsw(unsigned long addr, const void *buffer,
unsigned int count)
{
writesw(PCI_IOBASE + addr, buffer, count);
}
#else
void outsw(unsigned long addr, const void *buffer, unsigned int count)
__compiletime_error("outsw() requires HAS_IOPORT");
#endif
#endif
#ifndef outsl
#define outsl outsl
#ifdef CONFIG_HAS_IOPORT
static inline void outsl(unsigned long addr, const void *buffer,
unsigned int count)
{
writesl(PCI_IOBASE + addr, buffer, count);
}
#else
void outsl(unsigned long addr, const void *buffer, unsigned int count)
__compiletime_error("outsl() requires HAS_IOPORT");
#endif
#endif
#ifndef insb_p
@ -1151,7 +1211,6 @@ static inline void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
#endif
#ifndef memset_io
#define memset_io memset_io
/**
* memset_io Set a range of I/O memory to a constant value
* @addr: The beginning of the I/O-memory range to set
@ -1160,15 +1219,10 @@ static inline void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
*
* Set a range of I/O memory to a given value.
*/
static inline void memset_io(volatile void __iomem *addr, int value,
size_t size)
{
memset(__io_virt(addr), value, size);
}
void memset_io(volatile void __iomem *addr, int val, size_t count);
#endif
#ifndef memcpy_fromio
#define memcpy_fromio memcpy_fromio
/**
* memcpy_fromio Copy a block of data from I/O memory
* @dst: The (RAM) destination for the copy
@ -1177,16 +1231,10 @@ static inline void memset_io(volatile void __iomem *addr, int value,
*
* Copy a block of data from I/O memory.
*/
static inline void memcpy_fromio(void *buffer,
const volatile void __iomem *addr,
size_t size)
{
memcpy(buffer, __io_virt(addr), size);
}
void memcpy_fromio(void *dst, const volatile void __iomem *src, size_t count);
#endif
#ifndef memcpy_toio
#define memcpy_toio memcpy_toio
/**
* memcpy_toio Copy a block of data into I/O memory
* @dst: The (I/O memory) destination for the copy
@ -1195,11 +1243,7 @@ static inline void memcpy_fromio(void *buffer,
*
* Copy a block of data to I/O memory.
*/
static inline void memcpy_toio(volatile void __iomem *addr, const void *buffer,
size_t size)
{
memcpy(__io_virt(addr), buffer, size);
}
void memcpy_toio(volatile void __iomem *dst, const void *src, size_t count);
#endif
extern int devmem_is_allowed(unsigned long pfn);

View File

@ -64,6 +64,19 @@ static inline int pfn_valid(unsigned long pfn)
#define page_to_pfn __page_to_pfn
#define pfn_to_page __pfn_to_page
#ifdef CONFIG_DEBUG_VIRTUAL
#define page_to_phys(page) \
({ \
unsigned long __pfn = page_to_pfn(page); \
\
WARN_ON_ONCE(!pfn_valid(__pfn)); \
PFN_PHYS(__pfn); \
})
#else
#define page_to_phys(page) PFN_PHYS(page_to_pfn(page))
#endif /* CONFIG_DEBUG_VIRTUAL */
#define phys_to_page(phys) pfn_to_page(PHYS_PFN(phys))
#endif /* __ASSEMBLY__ */
#endif

View File

@ -1,25 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Access to VGA videoram
*
* (c) 1998 Martin Mares <mj@ucw.cz>
*/
#ifndef __ASM_GENERIC_VGA_H
#define __ASM_GENERIC_VGA_H
/*
* On most architectures that support VGA, we can just
* recalculate addresses and then access the videoram
* directly without any black magic.
*
* Everyone else needs to ioremap the address and use
* proper I/O accesses.
*/
#ifndef VGA_MAP_MEM
#define VGA_MAP_MEM(x, s) (unsigned long)phys_to_virt(x)
#endif
#define vga_readb(x) (*(x))
#define vga_writeb(x, y) (*(y) = (x))
#endif /* _ASM_GENERIC_VGA_H */
#endif /* __ASM_GENERIC_VGA_H */

View File

@ -505,7 +505,11 @@ struct uart_port {
* The remaining bits are serial-core specific and not modifiable by
* userspace.
*/
#ifdef CONFIG_HAS_IOPORT
#define UPF_FOURPORT ((__force upf_t) ASYNC_FOURPORT /* 1 */ )
#else
#define UPF_FOURPORT 0
#endif
#define UPF_SAK ((__force upf_t) ASYNC_SAK /* 2 */ )
#define UPF_SPD_HI ((__force upf_t) ASYNC_SPD_HI /* 4 */ )
#define UPF_SPD_VHI ((__force upf_t) ASYNC_SPD_VHI /* 5 */ )

View File

@ -28,45 +28,21 @@
#ifndef VT_BUF_HAVE_MEMSETW
static inline void scr_memsetw(u16 *s, u16 c, unsigned int count)
{
#ifdef VT_BUF_HAVE_RW
count /= 2;
while (count--)
scr_writew(c, s++);
#else
memset16(s, c, count / 2);
#endif
}
#endif
#ifndef VT_BUF_HAVE_MEMCPYW
static inline void scr_memcpyw(u16 *d, const u16 *s, unsigned int count)
{
#ifdef VT_BUF_HAVE_RW
count /= 2;
while (count--)
scr_writew(scr_readw(s++), d++);
#else
memcpy(d, s, count);
#endif
}
#endif
#ifndef VT_BUF_HAVE_MEMMOVEW
static inline void scr_memmovew(u16 *d, const u16 *s, unsigned int count)
{
#ifdef VT_BUF_HAVE_RW
if (d < s)
scr_memcpyw(d, s, count);
else {
count /= 2;
d += count;
s += count;
while (count--)
scr_writew(scr_readw(--s), --d);
}
#else
memmove(d, s, count);
#endif
}
#endif

View File

@ -83,12 +83,12 @@
* means userland is reading and kernel is writing.
*/
#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOR_BAD(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
#define _IOW_BAD(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
#define _IOWR_BAD(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
#define _IOR(type,nr,argtype) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(argtype)))
#define _IOW(type,nr,argtype) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(argtype)))
#define _IOWR(type,nr,argtype) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(argtype)))
#define _IOR_BAD(type,nr,argtype) _IOC(_IOC_READ,(type),(nr),sizeof(argtype))
#define _IOW_BAD(type,nr,argtype) _IOC(_IOC_WRITE,(type),(nr),sizeof(argtype))
#define _IOWR_BAD(type,nr,argtype) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(argtype))
/* used to decode ioctl numbers.. */
#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)

View File

@ -35,7 +35,7 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \
is_single_threaded.o plist.o decompress.o kobject_uevent.o \
earlycpio.o seq_buf.o siphash.o dec_and_lock.o \
nmi_backtrace.o win_minmax.o memcat_p.o \
buildid.o objpool.o union_find.o
buildid.o objpool.o union_find.o iomem_copy.o
lib-$(CONFIG_PRINTK) += dump_stack.o
lib-$(CONFIG_SMP) += cpumask.o

136
lib/iomem_copy.c Normal file
View File

@ -0,0 +1,136 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2024 Kalray, Inc. All Rights Reserved.
*/
#include <linux/align.h>
#include <linux/export.h>
#include <linux/io.h>
#include <linux/types.h>
#include <linux/unaligned.h>
#ifndef memset_io
/**
* memset_io() - Set a range of I/O memory to a constant value
* @addr: The beginning of the I/O-memory range to set
* @val: The value to set the memory to
* @count: The number of bytes to set
*
* Set a range of I/O memory to a given value.
*/
void memset_io(volatile void __iomem *addr, int val, size_t count)
{
long qc = (u8)val;
qc *= ~0UL / 0xff;
while (count && !IS_ALIGNED((long)addr, sizeof(long))) {
__raw_writeb(val, addr);
addr++;
count--;
}
while (count >= sizeof(long)) {
#ifdef CONFIG_64BIT
__raw_writeq(qc, addr);
#else
__raw_writel(qc, addr);
#endif
addr += sizeof(long);
count -= sizeof(long);
}
while (count) {
__raw_writeb(val, addr);
addr++;
count--;
}
}
EXPORT_SYMBOL(memset_io);
#endif
#ifndef memcpy_fromio
/**
* memcpy_fromio() - Copy a block of data from I/O memory
* @dst: The (RAM) destination for the copy
* @src: The (I/O memory) source for the data
* @count: The number of bytes to copy
*
* Copy a block of data from I/O memory.
*/
void memcpy_fromio(void *dst, const volatile void __iomem *src, size_t count)
{
while (count && !IS_ALIGNED((long)src, sizeof(long))) {
*(u8 *)dst = __raw_readb(src);
src++;
dst++;
count--;
}
while (count >= sizeof(long)) {
#ifdef CONFIG_64BIT
long val = __raw_readq(src);
#else
long val = __raw_readl(src);
#endif
put_unaligned(val, (long *)dst);
src += sizeof(long);
dst += sizeof(long);
count -= sizeof(long);
}
while (count) {
*(u8 *)dst = __raw_readb(src);
src++;
dst++;
count--;
}
}
EXPORT_SYMBOL(memcpy_fromio);
#endif
#ifndef memcpy_toio
/**
* memcpy_toio() -Copy a block of data into I/O memory
* @dst: The (I/O memory) destination for the copy
* @src: The (RAM) source for the data
* @count: The number of bytes to copy
*
* Copy a block of data to I/O memory.
*/
void memcpy_toio(volatile void __iomem *dst, const void *src, size_t count)
{
while (count && !IS_ALIGNED((long)dst, sizeof(long))) {
__raw_writeb(*(u8 *)src, dst);
src++;
dst++;
count--;
}
while (count >= sizeof(long)) {
long val = get_unaligned((long *)src);
#ifdef CONFIG_64BIT
__raw_writeq(val, dst);
#else
__raw_writel(val, dst);
#endif
src += sizeof(long);
dst += sizeof(long);
count -= sizeof(long);
}
while (count) {
__raw_writeb(*(u8 *)src, dst);
src++;
dst++;
count--;
}
}
EXPORT_SYMBOL(memcpy_toio);
#endif

View File

@ -26,6 +26,9 @@ static const u64 test_div64_dividends[] = {
0x0072db27380dd689,
0x0842f488162e2284,
0xf66745411d8ab063,
0xfffffffffffffffb,
0xfffffffffffffffc,
0xffffffffffffffff,
};
#define SIZE_DIV64_DIVIDENDS ARRAY_SIZE(test_div64_dividends)
@ -37,7 +40,10 @@ static const u64 test_div64_dividends[] = {
#define TEST_DIV64_DIVISOR_5 0x0008a880
#define TEST_DIV64_DIVISOR_6 0x003fd3ae
#define TEST_DIV64_DIVISOR_7 0x0b658fac
#define TEST_DIV64_DIVISOR_8 0xdc08b349
#define TEST_DIV64_DIVISOR_8 0x80000001
#define TEST_DIV64_DIVISOR_9 0xdc08b349
#define TEST_DIV64_DIVISOR_A 0xfffffffe
#define TEST_DIV64_DIVISOR_B 0xffffffff
static const u32 test_div64_divisors[] = {
TEST_DIV64_DIVISOR_0,
@ -49,13 +55,16 @@ static const u32 test_div64_divisors[] = {
TEST_DIV64_DIVISOR_6,
TEST_DIV64_DIVISOR_7,
TEST_DIV64_DIVISOR_8,
TEST_DIV64_DIVISOR_9,
TEST_DIV64_DIVISOR_A,
TEST_DIV64_DIVISOR_B,
};
#define SIZE_DIV64_DIVISORS ARRAY_SIZE(test_div64_divisors)
static const struct {
u64 quotient;
u32 remainder;
} test_div64_results[SIZE_DIV64_DIVISORS][SIZE_DIV64_DIVIDENDS] = {
} test_div64_results[SIZE_DIV64_DIVIDENDS][SIZE_DIV64_DIVISORS] = {
{
{ 0x0000000013045e47, 0x00000001 },
{ 0x000000000161596c, 0x00000030 },
@ -65,6 +74,9 @@ static const struct {
{ 0x00000000000013c4, 0x0004ce80 },
{ 0x00000000000002ae, 0x001e143c },
{ 0x000000000000000f, 0x0033e56c },
{ 0x0000000000000001, 0x2b27507f },
{ 0x0000000000000000, 0xab275080 },
{ 0x0000000000000000, 0xab275080 },
{ 0x0000000000000000, 0xab275080 },
}, {
{ 0x00000001c45c02d1, 0x00000000 },
@ -75,7 +87,10 @@ static const struct {
{ 0x000000000001d637, 0x0004e5d9 },
{ 0x0000000000003fc9, 0x000713bb },
{ 0x0000000000000165, 0x029abe7d },
{ 0x000000000000001f, 0x673c193a },
{ 0x0000000000000012, 0x6e9f7e37 },
{ 0x000000000000000f, 0xe73c1977 },
{ 0x000000000000000f, 0xe73c1968 },
}, {
{ 0x000000197a3a0cf7, 0x00000002 },
{ 0x00000001d9632e5c, 0x00000021 },
@ -85,7 +100,10 @@ static const struct {
{ 0x00000000001a7bb3, 0x00072331 },
{ 0x00000000000397ad, 0x0002c61b },
{ 0x000000000000141e, 0x06ea2e89 },
{ 0x00000000000001ca, 0x4c0a72e7 },
{ 0x000000000000010a, 0xab002ad7 },
{ 0x00000000000000e5, 0x4c0a767b },
{ 0x00000000000000e5, 0x4c0a7596 },
}, {
{ 0x0000017949e37538, 0x00000001 },
{ 0x0000001b62441f37, 0x00000055 },
@ -95,7 +113,10 @@ static const struct {
{ 0x0000000001882ec6, 0x0005cbf9 },
{ 0x000000000035333b, 0x0017abdf },
{ 0x00000000000129f1, 0x0ab4520d },
{ 0x0000000000001a87, 0x18ff0472 },
{ 0x0000000000000f6e, 0x8ac0ce9b },
{ 0x0000000000000d43, 0x98ff397f },
{ 0x0000000000000d43, 0x98ff2c3c },
}, {
{ 0x000011f321a74e49, 0x00000006 },
{ 0x0000014d8481d211, 0x0000005b },
@ -105,7 +126,10 @@ static const struct {
{ 0x0000000012a88828, 0x00036c97 },
{ 0x000000000287f16f, 0x002c2a25 },
{ 0x00000000000e2cc7, 0x02d581e3 },
{ 0x0000000000014318, 0x2ee07d7f },
{ 0x000000000000bbf4, 0x1ba08c03 },
{ 0x000000000000a18c, 0x2ee303af },
{ 0x000000000000a18c, 0x2ee26223 },
}, {
{ 0x0000d8db8f72935d, 0x00000005 },
{ 0x00000fbd5aed7a2e, 0x00000002 },
@ -115,7 +139,10 @@ static const struct {
{ 0x00000000e16b20fa, 0x0002a14a },
{ 0x000000001e940d22, 0x00353b2e },
{ 0x0000000000ab40ac, 0x06fba6ba },
{ 0x00000000000f3f70, 0x0af7eeda },
{ 0x000000000008debd, 0x72d98365 },
{ 0x0000000000079fb8, 0x0b166dba },
{ 0x0000000000079fb8, 0x0b0ece02 },
}, {
{ 0x000cc3045b8fc281, 0x00000000 },
{ 0x0000ed1f48b5c9fc, 0x00000079 },
@ -125,7 +152,10 @@ static const struct {
{ 0x0000000d43fce827, 0x00082b09 },
{ 0x00000001ccaba11a, 0x0037e8dd },
{ 0x000000000a13f729, 0x0566dffd },
{ 0x0000000000e5b64e, 0x3728203b },
{ 0x000000000085a14b, 0x23d36726 },
{ 0x000000000072db27, 0x38f38cd7 },
{ 0x000000000072db27, 0x3880b1b0 },
}, {
{ 0x00eafeb9c993592b, 0x00000001 },
{ 0x00110e5befa9a991, 0x00000048 },
@ -135,7 +165,10 @@ static const struct {
{ 0x000000f4459740fc, 0x00084484 },
{ 0x0000002122c47bf9, 0x002ca446 },
{ 0x00000000b9936290, 0x004979c4 },
{ 0x000000001085e910, 0x05a83974 },
{ 0x00000000099ca89d, 0x9db446bf },
{ 0x000000000842f488, 0x26b40b94 },
{ 0x000000000842f488, 0x1e71170c },
}, {
{ 0x1b60cece589da1d2, 0x00000001 },
{ 0x01fcb42be1453f5b, 0x0000004f },
@ -145,7 +178,49 @@ static const struct {
{ 0x00001c757dfab350, 0x00048863 },
{ 0x000003dc4979c652, 0x00224ea7 },
{ 0x000000159edc3144, 0x06409ab3 },
{ 0x00000001ecce8a7e, 0x30bc25e5 },
{ 0x000000011eadfee3, 0xa99c48a8 },
{ 0x00000000f6674543, 0x0a593ae9 },
{ 0x00000000f6674542, 0x13f1f5a5 },
}, {
{ 0x1c71c71c71c71c71, 0x00000002 },
{ 0x0210842108421084, 0x0000000b },
{ 0x007f01fc07f01fc0, 0x000000fb },
{ 0x00014245eabf1f9a, 0x0000a63d },
{ 0x0000ffffffffffff, 0x0000fffb },
{ 0x00001d913cecc509, 0x0007937b },
{ 0x00000402c70c678f, 0x0005bfc9 },
{ 0x00000016766cb70b, 0x045edf97 },
{ 0x00000001fffffffb, 0x80000000 },
{ 0x0000000129d84b3a, 0xa2e8fe71 },
{ 0x0000000100000001, 0xfffffffd },
{ 0x0000000100000000, 0xfffffffb },
}, {
{ 0x1c71c71c71c71c71, 0x00000003 },
{ 0x0210842108421084, 0x0000000c },
{ 0x007f01fc07f01fc0, 0x000000fc },
{ 0x00014245eabf1f9a, 0x0000a63e },
{ 0x0000ffffffffffff, 0x0000fffc },
{ 0x00001d913cecc509, 0x0007937c },
{ 0x00000402c70c678f, 0x0005bfca },
{ 0x00000016766cb70b, 0x045edf98 },
{ 0x00000001fffffffc, 0x00000000 },
{ 0x0000000129d84b3a, 0xa2e8fe72 },
{ 0x0000000100000002, 0x00000000 },
{ 0x0000000100000000, 0xfffffffc },
}, {
{ 0x1c71c71c71c71c71, 0x00000006 },
{ 0x0210842108421084, 0x0000000f },
{ 0x007f01fc07f01fc0, 0x000000ff },
{ 0x00014245eabf1f9a, 0x0000a641 },
{ 0x0000ffffffffffff, 0x0000ffff },
{ 0x00001d913cecc509, 0x0007937f },
{ 0x00000402c70c678f, 0x0005bfcd },
{ 0x00000016766cb70b, 0x045edf9b },
{ 0x00000001fffffffc, 0x00000003 },
{ 0x0000000129d84b3a, 0xa2e8fe75 },
{ 0x0000000100000002, 0x00000003 },
{ 0x0000000100000001, 0x00000000 },
},
};
@ -208,6 +283,12 @@ static bool __init test_div64(void)
return false;
if (!test_div64_one(dividend, TEST_DIV64_DIVISOR_8, i, 8))
return false;
if (!test_div64_one(dividend, TEST_DIV64_DIVISOR_9, i, 9))
return false;
if (!test_div64_one(dividend, TEST_DIV64_DIVISOR_A, i, 10))
return false;
if (!test_div64_one(dividend, TEST_DIV64_DIVISOR_B, i, 11))
return false;
for (j = 0; j < SIZE_DIV64_DIVISORS; j++) {
if (!test_div64_one(dividend, test_div64_divisors[j],
i, j))