Commit 15bc20c6 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'tty-5.9-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty

Pull tty/serial fixes from Greg KH:
 "Here are a few small TTY/Serial/vt fixes for 5.9-rc3

  Included in here are:
   - qcom serial fixes
   - vt ioctl and core bugfixes
   - pl011 serial driver fixes
   - 8250 serial driver fixes
   - other misc serial driver fixes

  and for good measure:
   - fbcon fix for syzbot found problem.

  All of these have been in linux-next for a while with no reported
  issues"

* tag 'tty-5.9-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
  tty: serial: imx: add dependence and build for earlycon
  serial: samsung: Removes the IRQ not found warning
  serial: 8250: change lock order in serial8250_do_startup()
  serial: stm32: avoid kernel warning on absence of optional IRQ
  serial: pl011: Fix oops on -EPROBE_DEFER
  serial: pl011: Don't leak amba_ports entry on driver register error
  serial: 8250_exar: Fix number of ports for Commtech PCIe cards
  tty: serial: qcom_geni_serial: Drop __init from qcom_geni_console_setup
  serial: qcom_geni_serial: Fix recent kdb hang
  vt_ioctl: change VT_RESIZEX ioctl to check for error return from vc_resize()
  fbcon: prevent user font height or width change from causing potential out-of-bounds access
  vt: defer kfree() of vc_screenbuf in vc_do_resize()
parents 27563ab6 ea1fc02e
......@@ -744,6 +744,24 @@ static const struct exar8250_board pbn_exar_XR17V35x = {
.exit = pci_xr17v35x_exit,
};
static const struct exar8250_board pbn_fastcom35x_2 = {
.num_ports = 2,
.setup = pci_xr17v35x_setup,
.exit = pci_xr17v35x_exit,
};
static const struct exar8250_board pbn_fastcom35x_4 = {
.num_ports = 4,
.setup = pci_xr17v35x_setup,
.exit = pci_xr17v35x_exit,
};
static const struct exar8250_board pbn_fastcom35x_8 = {
.num_ports = 8,
.setup = pci_xr17v35x_setup,
.exit = pci_xr17v35x_exit,
};
static const struct exar8250_board pbn_exar_XR17V4358 = {
.num_ports = 12,
.setup = pci_xr17v35x_setup,
......@@ -811,9 +829,9 @@ static const struct pci_device_id exar_pci_tbl[] = {
EXAR_DEVICE(EXAR, XR17V358, pbn_exar_XR17V35x),
EXAR_DEVICE(EXAR, XR17V4358, pbn_exar_XR17V4358),
EXAR_DEVICE(EXAR, XR17V8358, pbn_exar_XR17V8358),
EXAR_DEVICE(COMMTECH, 4222PCIE, pbn_exar_XR17V35x),
EXAR_DEVICE(COMMTECH, 4224PCIE, pbn_exar_XR17V35x),
EXAR_DEVICE(COMMTECH, 4228PCIE, pbn_exar_XR17V35x),
EXAR_DEVICE(COMMTECH, 4222PCIE, pbn_fastcom35x_2),
EXAR_DEVICE(COMMTECH, 4224PCIE, pbn_fastcom35x_4),
EXAR_DEVICE(COMMTECH, 4228PCIE, pbn_fastcom35x_8),
EXAR_DEVICE(COMMTECH, 4222PCI335, pbn_fastcom335_2),
EXAR_DEVICE(COMMTECH, 4224PCI335, pbn_fastcom335_4),
......
......@@ -2275,6 +2275,10 @@ int serial8250_do_startup(struct uart_port *port)
if (port->irq && !(up->port.flags & UPF_NO_THRE_TEST)) {
unsigned char iir1;
if (port->irqflags & IRQF_SHARED)
disable_irq_nosync(port->irq);
/*
* Test for UARTs that do not reassert THRE when the
* transmitter is idle and the interrupt has already
......@@ -2284,8 +2288,6 @@ int serial8250_do_startup(struct uart_port *port)
* allow register changes to become visible.
*/
spin_lock_irqsave(&port->lock, flags);
if (up->port.irqflags & IRQF_SHARED)
disable_irq_nosync(port->irq);
wait_for_xmitr(up, UART_LSR_THRE);
serial_port_out_sync(port, UART_IER, UART_IER_THRI);
......@@ -2297,9 +2299,10 @@ int serial8250_do_startup(struct uart_port *port)
iir = serial_port_in(port, UART_IIR);
serial_port_out(port, UART_IER, 0);
spin_unlock_irqrestore(&port->lock, flags);
if (port->irqflags & IRQF_SHARED)
enable_irq(port->irq);
spin_unlock_irqrestore(&port->lock, flags);
/*
* If the interrupt is not reasserted, or we otherwise
......
......@@ -517,6 +517,7 @@ config SERIAL_IMX_CONSOLE
config SERIAL_IMX_EARLYCON
bool "Earlycon on IMX serial port"
depends on ARCH_MXC || COMPILE_TEST
depends on OF
select SERIAL_EARLYCON
help
......
......@@ -43,6 +43,7 @@ obj-$(CONFIG_SERIAL_ZS) += zs.o
obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o
obj-$(CONFIG_SERIAL_CPM) += cpm_uart/
obj-$(CONFIG_SERIAL_IMX) += imx.o
obj-$(CONFIG_SERIAL_IMX_EARLYCON) += imx_earlycon.o
obj-$(CONFIG_SERIAL_MPC52xx) += mpc52xx_uart.o
obj-$(CONFIG_SERIAL_ICOM) += icom.o
obj-$(CONFIG_SERIAL_MESON) += meson_uart.o
......
......@@ -2241,8 +2241,7 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
clk_disable(uap->clk);
}
static void __init
pl011_console_get_options(struct uart_amba_port *uap, int *baud,
static void pl011_console_get_options(struct uart_amba_port *uap, int *baud,
int *parity, int *bits)
{
if (pl011_read(uap, REG_CR) & UART01x_CR_UARTEN) {
......@@ -2276,7 +2275,7 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud,
}
}
static int __init pl011_console_setup(struct console *co, char *options)
static int pl011_console_setup(struct console *co, char *options)
{
struct uart_amba_port *uap;
int baud = 38400;
......@@ -2344,7 +2343,7 @@ static int __init pl011_console_setup(struct console *co, char *options)
*
* Returns 0 if console matches; otherwise non-zero to use default matching
*/
static int __init pl011_console_match(struct console *co, char *name, int idx,
static int pl011_console_match(struct console *co, char *name, int idx,
char *options)
{
unsigned char iotype;
......@@ -2615,7 +2614,7 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap,
static int pl011_register_port(struct uart_amba_port *uap)
{
int ret;
int ret, i;
/* Ensure interrupts from this UART are masked and cleared */
pl011_write(0, uap, REG_IMSC);
......@@ -2626,6 +2625,9 @@ static int pl011_register_port(struct uart_amba_port *uap)
if (ret < 0) {
dev_err(uap->port.dev,
"Failed to register AMBA-PL011 driver\n");
for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
if (amba_ports[i] == uap)
amba_ports[i] = NULL;
return ret;
}
}
......
......@@ -361,11 +361,16 @@ static int qcom_geni_serial_get_char(struct uart_port *uport)
return NO_POLL_CHAR;
if (word_cnt == 1 && (status & RX_LAST))
/*
* NOTE: If RX_LAST_BYTE_VALID is 0 it needs to be
* treated as if it was BYTES_PER_FIFO_WORD.
*/
private_data->poll_cached_bytes_cnt =
(status & RX_LAST_BYTE_VALID_MSK) >>
RX_LAST_BYTE_VALID_SHFT;
else
private_data->poll_cached_bytes_cnt = 4;
if (private_data->poll_cached_bytes_cnt == 0)
private_data->poll_cached_bytes_cnt = BYTES_PER_FIFO_WORD;
private_data->poll_cached_bytes =
readl(uport->membase + SE_GENI_RX_FIFOn);
......@@ -1098,7 +1103,7 @@ static unsigned int qcom_geni_serial_tx_empty(struct uart_port *uport)
}
#ifdef CONFIG_SERIAL_QCOM_GENI_CONSOLE
static int __init qcom_geni_console_setup(struct console *co, char *options)
static int qcom_geni_console_setup(struct console *co, char *options)
{
struct uart_port *uport;
struct qcom_geni_serial_port *port;
......
......@@ -1905,9 +1905,11 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
ourport->tx_irq = ret + 1;
}
if (!s3c24xx_serial_has_interrupt_mask(port)) {
ret = platform_get_irq(platdev, 1);
if (ret > 0)
ourport->tx_irq = ret;
}
/*
* DMA is currently supported only on DT platforms, if DMA properties
* are specified.
......
......@@ -970,7 +970,7 @@ static int stm32_init_port(struct stm32_port *stm32port,
return ret;
if (stm32port->info->cfg.has_wakeup) {
stm32port->wakeirq = platform_get_irq(pdev, 1);
stm32port->wakeirq = platform_get_irq_optional(pdev, 1);
if (stm32port->wakeirq <= 0 && stm32port->wakeirq != -ENXIO)
return stm32port->wakeirq ? : -ENODEV;
}
......
......@@ -1201,7 +1201,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
unsigned int old_rows, old_row_size, first_copied_row;
unsigned int new_cols, new_rows, new_row_size, new_screen_size;
unsigned int user;
unsigned short *newscreen;
unsigned short *oldscreen, *newscreen;
struct uni_screen *new_uniscr = NULL;
WARN_CONSOLE_UNLOCKED();
......@@ -1299,10 +1299,11 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
if (new_scr_end > new_origin)
scr_memsetw((void *)new_origin, vc->vc_video_erase_char,
new_scr_end - new_origin);
kfree(vc->vc_screenbuf);
oldscreen = vc->vc_screenbuf;
vc->vc_screenbuf = newscreen;
vc->vc_screenbuf_size = new_screen_size;
set_origin(vc);
kfree(oldscreen);
/* do part of a reset_terminal() */
vc->vc_top = 0;
......
......@@ -806,12 +806,22 @@ static int vt_resizex(struct vc_data *vc, struct vt_consize __user *cs)
console_lock();
vcp = vc_cons[i].d;
if (vcp) {
int ret;
int save_scan_lines = vcp->vc_scan_lines;
int save_font_height = vcp->vc_font.height;
if (v.v_vlin)
vcp->vc_scan_lines = v.v_vlin;
if (v.v_clin)
vcp->vc_font.height = v.v_clin;
vcp->vc_resize_user = 1;
vc_resize(vcp, v.v_cols, v.v_rows);
ret = vc_resize(vcp, v.v_cols, v.v_rows);
if (ret) {
vcp->vc_scan_lines = save_scan_lines;
vcp->vc_font.height = save_font_height;
console_unlock();
return ret;
}
}
console_unlock();
}
......
......@@ -2191,6 +2191,9 @@ static void updatescrollmode(struct fbcon_display *p,
}
}
#define PITCH(w) (((w) + 7) >> 3)
#define CALC_FONTSZ(h, p, c) ((h) * (p) * (c)) /* size = height * pitch * charcount */
static int fbcon_resize(struct vc_data *vc, unsigned int width,
unsigned int height, unsigned int user)
{
......@@ -2200,6 +2203,24 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
struct fb_var_screeninfo var = info->var;
int x_diff, y_diff, virt_w, virt_h, virt_fw, virt_fh;
if (ops->p && ops->p->userfont && FNTSIZE(vc->vc_font.data)) {
int size;
int pitch = PITCH(vc->vc_font.width);
/*
* If user font, ensure that a possible change to user font
* height or width will not allow a font data out-of-bounds access.
* NOTE: must use original charcount in calculation as font
* charcount can change and cannot be used to determine the
* font data allocated size.
*/
if (pitch <= 0)
return -EINVAL;
size = CALC_FONTSZ(vc->vc_font.height, pitch, FNTCHARCNT(vc->vc_font.data));
if (size > FNTSIZE(vc->vc_font.data))
return -EINVAL;
}
virt_w = FBCON_SWAP(ops->rotate, width, height);
virt_h = FBCON_SWAP(ops->rotate, height, width);
virt_fw = FBCON_SWAP(ops->rotate, vc->vc_font.width,
......@@ -2652,7 +2673,7 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font,
int size;
int i, csum;
u8 *new_data, *data = font->data;
int pitch = (font->width+7) >> 3;
int pitch = PITCH(font->width);
/* Is there a reason why fbconsole couldn't handle any charcount >256?
* If not this check should be changed to charcount < 256 */
......@@ -2668,7 +2689,7 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font,
if (fbcon_invalid_charcount(info, charcount))
return -EINVAL;
size = h * pitch * charcount;
size = CALC_FONTSZ(h, pitch, charcount);
new_data = kmalloc(FONT_EXTRA_WORDS * sizeof(int) + size, GFP_USER);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment