Skip to content

Commit

Permalink
Merge tag 'tty-5.8-rc7' of git://git.kernel.org/pub/scm/linux/kernel/…
Browse files Browse the repository at this point in the history
…git/gregkh/tty into master

Pull tty/serial/fbcon fixes from Greg KH:
 "Here are some small tty and serial and fbcon fixes for 5.8-rc7 to
  resolve some reported issues.

  The fbcon fix is in here as it was simpler to take it this way (and it
  was acked by the maintainer) as it was related to the vt console fix
  as well, both of which resolve syzbot-found issues in the console
  handling code.

  The other serial driver fixes are for small issues reported in the -rc
  releases.

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

* tag 'tty-5.8-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
  serial: exar: Fix GPIO configuration for Sealevel cards based on XR17V35X
  fbdev: Detect integer underflow at "struct fbcon_ops"->clear_margins.
  serial: 8250_mtk: Fix high-speed baud rates clamping
  serial: 8250: fix null-ptr-deref in serial8250_start_tx()
  serial: tegra: drop bogus NULL tty-port checks
  serial: tegra: fix CREAD handling for PIO
  tty: xilinx_uartps: Really fix id assignment
  vt: Reject zero-sized screen buffer size.
  • Loading branch information
torvalds committed Jul 26, 2020
2 parents 17f50e2 + 5fdbe13 commit 7d22af6
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 32 deletions.
2 changes: 1 addition & 1 deletion drivers/tty/serial/8250/8250_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,7 @@ static void __init serial8250_isa_init_ports(void)
*/
up->mcr_mask = ~ALPHA_KLUDGE_MCR;
up->mcr_force = ALPHA_KLUDGE_MCR;
serial8250_set_defaults(up);
}

/* chain base port ops to support Remote Supervisor Adapter */
Expand All @@ -547,7 +548,6 @@ static void __init serial8250_isa_init_ports(void)
port->membase = old_serial_port[i].iomem_base;
port->iotype = old_serial_port[i].io_type;
port->regshift = old_serial_port[i].iomem_reg_shift;
serial8250_set_defaults(up);

port->irqflags |= irqflag;
if (serial8250_isa_config != NULL)
Expand Down
12 changes: 11 additions & 1 deletion drivers/tty/serial/8250/8250_exar.c
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,17 @@ static void setup_gpio(struct pci_dev *pcidev, u8 __iomem *p)
* devices will export them as GPIOs, so we pre-configure them safely
* as inputs.
*/
u8 dir = pcidev->vendor == PCI_VENDOR_ID_EXAR ? 0xff : 0x00;

u8 dir = 0x00;

if ((pcidev->vendor == PCI_VENDOR_ID_EXAR) &&
(pcidev->subsystem_vendor != PCI_VENDOR_ID_SEALEVEL)) {
// Configure GPIO as inputs for Commtech adapters
dir = 0xff;
} else {
// Configure GPIO as outputs for SeaLevel adapters
dir = 0x00;
}

writeb(0x00, p + UART_EXAR_MPIOINT_7_0);
writeb(0x00, p + UART_EXAR_MPIOLVL_7_0);
Expand Down
18 changes: 18 additions & 0 deletions drivers/tty/serial/8250/8250_mtk.c
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,21 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios,
}
#endif

/*
* Store the requested baud rate before calling the generic 8250
* set_termios method. Standard 8250 port expects bauds to be
* no higher than (uartclk / 16) so the baud will be clamped if it
* gets out of that bound. Mediatek 8250 port supports speed
* higher than that, therefore we'll get original baud rate back
* after calling the generic set_termios method and recalculate
* the speed later in this method.
*/
baud = tty_termios_baud_rate(termios);

serial8250_do_set_termios(port, termios, old);

tty_termios_encode_baud_rate(termios, baud, baud);

/*
* Mediatek UARTs use an extra highspeed register (MTK_UART_HIGHS)
*
Expand Down Expand Up @@ -339,6 +352,11 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios,
*/
spin_lock_irqsave(&port->lock, flags);

/*
* Update the per-port timeout.
*/
uart_update_timeout(port, termios->c_cflag, baud);

/* set DLAB we have cval saved in up->lcr from the call to the core */
serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB);
serial_dl_write(up, quot);
Expand Down
16 changes: 7 additions & 9 deletions drivers/tty/serial/serial-tegra.c
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,7 @@ static void tegra_uart_handle_tx_pio(struct tegra_uart_port *tup)
}

static void tegra_uart_handle_rx_pio(struct tegra_uart_port *tup,
struct tty_port *tty)
struct tty_port *port)
{
do {
char flag = TTY_NORMAL;
Expand All @@ -653,16 +653,18 @@ static void tegra_uart_handle_rx_pio(struct tegra_uart_port *tup,
ch = (unsigned char) tegra_uart_read(tup, UART_RX);
tup->uport.icount.rx++;

if (!uart_handle_sysrq_char(&tup->uport, ch) && tty)
tty_insert_flip_char(tty, ch, flag);
if (uart_handle_sysrq_char(&tup->uport, ch))
continue;

if (tup->uport.ignore_status_mask & UART_LSR_DR)
continue;

tty_insert_flip_char(port, ch, flag);
} while (1);
}

static void tegra_uart_copy_rx_to_tty(struct tegra_uart_port *tup,
struct tty_port *tty,
struct tty_port *port,
unsigned int count)
{
int copied;
Expand All @@ -672,17 +674,13 @@ static void tegra_uart_copy_rx_to_tty(struct tegra_uart_port *tup,
return;

tup->uport.icount.rx += count;
if (!tty) {
dev_err(tup->uport.dev, "No tty port\n");
return;
}

if (tup->uport.ignore_status_mask & UART_LSR_DR)
return;

dma_sync_single_for_cpu(tup->uport.dev, tup->rx_dma_buf_phys,
count, DMA_FROM_DEVICE);
copied = tty_insert_flip_string(tty,
copied = tty_insert_flip_string(port,
((unsigned char *)(tup->rx_dma_buf_virt)), count);
if (copied != count) {
WARN_ON(1);
Expand Down
8 changes: 6 additions & 2 deletions drivers/tty/serial/xilinx_uartps.c
Original file line number Diff line number Diff line change
Expand Up @@ -1580,8 +1580,10 @@ static int cdns_uart_probe(struct platform_device *pdev)
* If register_console() don't assign value, then console_port pointer
* is cleanup.
*/
if (!console_port)
if (!console_port) {
cdns_uart_console.index = id;
console_port = port;
}
#endif

rc = uart_add_one_port(&cdns_uart_uart_driver, port);
Expand All @@ -1594,8 +1596,10 @@ static int cdns_uart_probe(struct platform_device *pdev)
#ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE
/* This is not port which is used for console that's why clean it up */
if (console_port == port &&
!(cdns_uart_uart_driver.cons->flags & CON_ENABLED))
!(cdns_uart_uart_driver.cons->flags & CON_ENABLED)) {
console_port = NULL;
cdns_uart_console.index = -1;
}
#endif

cdns_uart_data->cts_override = of_property_read_bool(pdev->dev.of_node,
Expand Down
29 changes: 18 additions & 11 deletions drivers/tty/vt/vt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1092,10 +1092,19 @@ static const struct tty_port_operations vc_port_ops = {
.destruct = vc_port_destruct,
};

/*
* Change # of rows and columns (0 means unchanged/the size of fg_console)
* [this is to be used together with some user program
* like resize that changes the hardware videomode]
*/
#define VC_MAXCOL (32767)
#define VC_MAXROW (32767)

int vc_allocate(unsigned int currcons) /* return 0 on success */
{
struct vt_notifier_param param;
struct vc_data *vc;
int err;

WARN_CONSOLE_UNLOCKED();

Expand Down Expand Up @@ -1125,6 +1134,11 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
if (!*vc->vc_uni_pagedir_loc)
con_set_default_unimap(vc);

err = -EINVAL;
if (vc->vc_cols > VC_MAXCOL || vc->vc_rows > VC_MAXROW ||
vc->vc_screenbuf_size > KMALLOC_MAX_SIZE || !vc->vc_screenbuf_size)
goto err_free;
err = -ENOMEM;
vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_KERNEL);
if (!vc->vc_screenbuf)
goto err_free;
Expand All @@ -1143,7 +1157,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
visual_deinit(vc);
kfree(vc);
vc_cons[currcons].d = NULL;
return -ENOMEM;
return err;
}

static inline int resize_screen(struct vc_data *vc, int width, int height,
Expand All @@ -1158,14 +1172,6 @@ static inline int resize_screen(struct vc_data *vc, int width, int height,
return err;
}

/*
* Change # of rows and columns (0 means unchanged/the size of fg_console)
* [this is to be used together with some user program
* like resize that changes the hardware videomode]
*/
#define VC_RESIZE_MAXCOL (32767)
#define VC_RESIZE_MAXROW (32767)

/**
* vc_do_resize - resizing method for the tty
* @tty: tty being resized
Expand Down Expand Up @@ -1201,7 +1207,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
user = vc->vc_resize_user;
vc->vc_resize_user = 0;

if (cols > VC_RESIZE_MAXCOL || lines > VC_RESIZE_MAXROW)
if (cols > VC_MAXCOL || lines > VC_MAXROW)
return -EINVAL;

new_cols = (cols ? cols : vc->vc_cols);
Expand All @@ -1212,7 +1218,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
return 0;

if (new_screen_size > KMALLOC_MAX_SIZE)
if (new_screen_size > KMALLOC_MAX_SIZE || !new_screen_size)
return -EINVAL;
newscreen = kzalloc(new_screen_size, GFP_USER);
if (!newscreen)
Expand Down Expand Up @@ -3393,6 +3399,7 @@ static int __init con_init(void)
INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
tty_port_init(&vc->port);
visual_init(vc, currcons, 1);
/* Assuming vc->vc_{cols,rows,screenbuf_size} are sane here. */
vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT);
vc_init(vc, vc->vc_rows, vc->vc_cols,
currcons || !vc->vc_sw->con_save_screen);
Expand Down
4 changes: 2 additions & 2 deletions drivers/video/fbdev/core/bitblit.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,15 +216,15 @@ static void bit_clear_margins(struct vc_data *vc, struct fb_info *info,
region.color = color;
region.rop = ROP_COPY;

if (rw && !bottom_only) {
if ((int) rw > 0 && !bottom_only) {
region.dx = info->var.xoffset + rs;
region.dy = 0;
region.width = rw;
region.height = info->var.yres_virtual;
info->fbops->fb_fillrect(info, &region);
}

if (bh) {
if ((int) bh > 0) {
region.dx = info->var.xoffset;
region.dy = info->var.yoffset + bs;
region.width = rs;
Expand Down
4 changes: 2 additions & 2 deletions drivers/video/fbdev/core/fbcon_ccw.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,15 +201,15 @@ static void ccw_clear_margins(struct vc_data *vc, struct fb_info *info,
region.color = color;
region.rop = ROP_COPY;

if (rw && !bottom_only) {
if ((int) rw > 0 && !bottom_only) {
region.dx = 0;
region.dy = info->var.yoffset;
region.height = rw;
region.width = info->var.xres_virtual;
info->fbops->fb_fillrect(info, &region);
}

if (bh) {
if ((int) bh > 0) {
region.dx = info->var.xoffset + bs;
region.dy = 0;
region.height = info->var.yres_virtual;
Expand Down
4 changes: 2 additions & 2 deletions drivers/video/fbdev/core/fbcon_cw.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,15 +184,15 @@ static void cw_clear_margins(struct vc_data *vc, struct fb_info *info,
region.color = color;
region.rop = ROP_COPY;

if (rw && !bottom_only) {
if ((int) rw > 0 && !bottom_only) {
region.dx = 0;
region.dy = info->var.yoffset + rs;
region.height = rw;
region.width = info->var.xres_virtual;
info->fbops->fb_fillrect(info, &region);
}

if (bh) {
if ((int) bh > 0) {
region.dx = info->var.xoffset;
region.dy = info->var.yoffset;
region.height = info->var.yres;
Expand Down
4 changes: 2 additions & 2 deletions drivers/video/fbdev/core/fbcon_ud.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,15 +231,15 @@ static void ud_clear_margins(struct vc_data *vc, struct fb_info *info,
region.color = color;
region.rop = ROP_COPY;

if (rw && !bottom_only) {
if ((int) rw > 0 && !bottom_only) {
region.dy = 0;
region.dx = info->var.xoffset;
region.width = rw;
region.height = info->var.yres_virtual;
info->fbops->fb_fillrect(info, &region);
}

if (bh) {
if ((int) bh > 0) {
region.dy = info->var.yoffset;
region.dx = info->var.xoffset;
region.height = bh;
Expand Down

0 comments on commit 7d22af6

Please sign in to comment.