tty: goldfish: Introduce gf_ioread32()/gf_iowrite32()
commit2e2ac4a332
upstream. The goldfish TTY device was clearly defined as having little-endian registers, but the switch to __raw_{read,write}l(() broke its driver when running on big-endian kernels (if anyone ever tried this). The m68k qemu implementation got this wrong, and assumed native-endian registers. While this is a bug in qemu, it is probably impossible to fix that since there is no way of knowing which other operating systems have started relying on that bug over the years. Hence revert commitda31de35cd
("tty: goldfish: use __raw_writel()/__raw_readl()", and define gf_ioread32()/gf_iowrite32() to be able to use accessors defined by the architecture. Cc: stable@vger.kernel.org # v5.11+ Fixes:da31de35cd
("tty: goldfish: use __raw_writel()/__raw_readl()") Signed-off-by: Laurent Vivier <laurent@vivier.eu> Link: https://lore.kernel.org/r/20220406201523.243733-2-laurent@vivier.eu [geert: Add rationale based on Arnd's comments] Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Родитель
b3485d2b09
Коммит
0b011b408f
|
@ -61,13 +61,13 @@ static void do_rw_io(struct goldfish_tty *qtty,
|
||||||
spin_lock_irqsave(&qtty->lock, irq_flags);
|
spin_lock_irqsave(&qtty->lock, irq_flags);
|
||||||
gf_write_ptr((void *)address, base + GOLDFISH_TTY_REG_DATA_PTR,
|
gf_write_ptr((void *)address, base + GOLDFISH_TTY_REG_DATA_PTR,
|
||||||
base + GOLDFISH_TTY_REG_DATA_PTR_HIGH);
|
base + GOLDFISH_TTY_REG_DATA_PTR_HIGH);
|
||||||
__raw_writel(count, base + GOLDFISH_TTY_REG_DATA_LEN);
|
gf_iowrite32(count, base + GOLDFISH_TTY_REG_DATA_LEN);
|
||||||
|
|
||||||
if (is_write)
|
if (is_write)
|
||||||
__raw_writel(GOLDFISH_TTY_CMD_WRITE_BUFFER,
|
gf_iowrite32(GOLDFISH_TTY_CMD_WRITE_BUFFER,
|
||||||
base + GOLDFISH_TTY_REG_CMD);
|
base + GOLDFISH_TTY_REG_CMD);
|
||||||
else
|
else
|
||||||
__raw_writel(GOLDFISH_TTY_CMD_READ_BUFFER,
|
gf_iowrite32(GOLDFISH_TTY_CMD_READ_BUFFER,
|
||||||
base + GOLDFISH_TTY_REG_CMD);
|
base + GOLDFISH_TTY_REG_CMD);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&qtty->lock, irq_flags);
|
spin_unlock_irqrestore(&qtty->lock, irq_flags);
|
||||||
|
@ -142,7 +142,7 @@ static irqreturn_t goldfish_tty_interrupt(int irq, void *dev_id)
|
||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
u32 count;
|
u32 count;
|
||||||
|
|
||||||
count = __raw_readl(base + GOLDFISH_TTY_REG_BYTES_READY);
|
count = gf_ioread32(base + GOLDFISH_TTY_REG_BYTES_READY);
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
return IRQ_NONE;
|
return IRQ_NONE;
|
||||||
|
|
||||||
|
@ -159,7 +159,7 @@ static int goldfish_tty_activate(struct tty_port *port, struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
struct goldfish_tty *qtty = container_of(port, struct goldfish_tty,
|
struct goldfish_tty *qtty = container_of(port, struct goldfish_tty,
|
||||||
port);
|
port);
|
||||||
__raw_writel(GOLDFISH_TTY_CMD_INT_ENABLE, qtty->base + GOLDFISH_TTY_REG_CMD);
|
gf_iowrite32(GOLDFISH_TTY_CMD_INT_ENABLE, qtty->base + GOLDFISH_TTY_REG_CMD);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ static void goldfish_tty_shutdown(struct tty_port *port)
|
||||||
{
|
{
|
||||||
struct goldfish_tty *qtty = container_of(port, struct goldfish_tty,
|
struct goldfish_tty *qtty = container_of(port, struct goldfish_tty,
|
||||||
port);
|
port);
|
||||||
__raw_writel(GOLDFISH_TTY_CMD_INT_DISABLE, qtty->base + GOLDFISH_TTY_REG_CMD);
|
gf_iowrite32(GOLDFISH_TTY_CMD_INT_DISABLE, qtty->base + GOLDFISH_TTY_REG_CMD);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int goldfish_tty_open(struct tty_struct *tty, struct file *filp)
|
static int goldfish_tty_open(struct tty_struct *tty, struct file *filp)
|
||||||
|
@ -202,7 +202,7 @@ static unsigned int goldfish_tty_chars_in_buffer(struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
struct goldfish_tty *qtty = &goldfish_ttys[tty->index];
|
struct goldfish_tty *qtty = &goldfish_ttys[tty->index];
|
||||||
void __iomem *base = qtty->base;
|
void __iomem *base = qtty->base;
|
||||||
return __raw_readl(base + GOLDFISH_TTY_REG_BYTES_READY);
|
return gf_ioread32(base + GOLDFISH_TTY_REG_BYTES_READY);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void goldfish_tty_console_write(struct console *co, const char *b,
|
static void goldfish_tty_console_write(struct console *co, const char *b,
|
||||||
|
@ -357,7 +357,7 @@ static int goldfish_tty_probe(struct platform_device *pdev)
|
||||||
* on Ranchu emulator (qemu2) returns 1 here and
|
* on Ranchu emulator (qemu2) returns 1 here and
|
||||||
* driver will use physical addresses.
|
* driver will use physical addresses.
|
||||||
*/
|
*/
|
||||||
qtty->version = __raw_readl(base + GOLDFISH_TTY_REG_VERSION);
|
qtty->version = gf_ioread32(base + GOLDFISH_TTY_REG_VERSION);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Goldfish TTY device on Ranchu emulator (qemu2)
|
* Goldfish TTY device on Ranchu emulator (qemu2)
|
||||||
|
@ -376,7 +376,7 @@ static int goldfish_tty_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__raw_writel(GOLDFISH_TTY_CMD_INT_DISABLE, base + GOLDFISH_TTY_REG_CMD);
|
gf_iowrite32(GOLDFISH_TTY_CMD_INT_DISABLE, base + GOLDFISH_TTY_REG_CMD);
|
||||||
|
|
||||||
ret = request_irq(irq, goldfish_tty_interrupt, IRQF_SHARED,
|
ret = request_irq(irq, goldfish_tty_interrupt, IRQF_SHARED,
|
||||||
"goldfish_tty", qtty);
|
"goldfish_tty", qtty);
|
||||||
|
@ -438,7 +438,7 @@ static int goldfish_tty_remove(struct platform_device *pdev)
|
||||||
#ifdef CONFIG_GOLDFISH_TTY_EARLY_CONSOLE
|
#ifdef CONFIG_GOLDFISH_TTY_EARLY_CONSOLE
|
||||||
static void gf_early_console_putchar(struct uart_port *port, int ch)
|
static void gf_early_console_putchar(struct uart_port *port, int ch)
|
||||||
{
|
{
|
||||||
__raw_writel(ch, port->membase);
|
gf_iowrite32(ch, port->membase);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gf_early_write(struct console *con, const char *s, unsigned int n)
|
static void gf_early_write(struct console *con, const char *s, unsigned int n)
|
||||||
|
|
|
@ -8,14 +8,21 @@
|
||||||
|
|
||||||
/* Helpers for Goldfish virtual platform */
|
/* Helpers for Goldfish virtual platform */
|
||||||
|
|
||||||
|
#ifndef gf_ioread32
|
||||||
|
#define gf_ioread32 ioread32
|
||||||
|
#endif
|
||||||
|
#ifndef gf_iowrite32
|
||||||
|
#define gf_iowrite32 iowrite32
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline void gf_write_ptr(const void *ptr, void __iomem *portl,
|
static inline void gf_write_ptr(const void *ptr, void __iomem *portl,
|
||||||
void __iomem *porth)
|
void __iomem *porth)
|
||||||
{
|
{
|
||||||
const unsigned long addr = (unsigned long)ptr;
|
const unsigned long addr = (unsigned long)ptr;
|
||||||
|
|
||||||
__raw_writel(lower_32_bits(addr), portl);
|
gf_iowrite32(lower_32_bits(addr), portl);
|
||||||
#ifdef CONFIG_64BIT
|
#ifdef CONFIG_64BIT
|
||||||
__raw_writel(upper_32_bits(addr), porth);
|
gf_iowrite32(upper_32_bits(addr), porth);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,9 +30,9 @@ static inline void gf_write_dma_addr(const dma_addr_t addr,
|
||||||
void __iomem *portl,
|
void __iomem *portl,
|
||||||
void __iomem *porth)
|
void __iomem *porth)
|
||||||
{
|
{
|
||||||
__raw_writel(lower_32_bits(addr), portl);
|
gf_iowrite32(lower_32_bits(addr), portl);
|
||||||
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
||||||
__raw_writel(upper_32_bits(addr), porth);
|
gf_iowrite32(upper_32_bits(addr), porth);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче