TTY/Serial/fbcon fixes for 5.8-rc7
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. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCXx1ivg8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ym+LQCbBFMk78aB+Vb5PpH36m6oNroBB2MAoMUJSWLx Wm7QhLYa1Cbsb1rC7t5x =kf5B -----END PGP SIGNATURE----- Merge tag 'tty-5.8-rc7' of git://git.kernel.org/pub/scm/linux/kernel/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.
This commit is contained in:
Коммит
7d22af6c5b
|
@ -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 */
|
||||
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
*
|
||||
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
@ -1143,7 +1157,7 @@ err_free:
|
|||
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,
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
|
|
@ -216,7 +216,7 @@ 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;
|
||||
|
@ -224,7 +224,7 @@ static void bit_clear_margins(struct vc_data *vc, struct fb_info *info,
|
|||
info->fbops->fb_fillrect(info, ®ion);
|
||||
}
|
||||
|
||||
if (bh) {
|
||||
if ((int) bh > 0) {
|
||||
region.dx = info->var.xoffset;
|
||||
region.dy = info->var.yoffset + bs;
|
||||
region.width = rs;
|
||||
|
|
|
@ -201,7 +201,7 @@ 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;
|
||||
|
@ -209,7 +209,7 @@ static void ccw_clear_margins(struct vc_data *vc, struct fb_info *info,
|
|||
info->fbops->fb_fillrect(info, ®ion);
|
||||
}
|
||||
|
||||
if (bh) {
|
||||
if ((int) bh > 0) {
|
||||
region.dx = info->var.xoffset + bs;
|
||||
region.dy = 0;
|
||||
region.height = info->var.yres_virtual;
|
||||
|
|
|
@ -184,7 +184,7 @@ 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;
|
||||
|
@ -192,7 +192,7 @@ static void cw_clear_margins(struct vc_data *vc, struct fb_info *info,
|
|||
info->fbops->fb_fillrect(info, ®ion);
|
||||
}
|
||||
|
||||
if (bh) {
|
||||
if ((int) bh > 0) {
|
||||
region.dx = info->var.xoffset;
|
||||
region.dy = info->var.yoffset;
|
||||
region.height = info->var.yres;
|
||||
|
|
|
@ -231,7 +231,7 @@ 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;
|
||||
|
@ -239,7 +239,7 @@ static void ud_clear_margins(struct vc_data *vc, struct fb_info *info,
|
|||
info->fbops->fb_fillrect(info, ®ion);
|
||||
}
|
||||
|
||||
if (bh) {
|
||||
if ((int) bh > 0) {
|
||||
region.dy = info->var.yoffset;
|
||||
region.dx = info->var.xoffset;
|
||||
region.height = bh;
|
||||
|
|
Загрузка…
Ссылка в новой задаче