Commit c5f33785 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull tty/serial fixes from Greg KH:
 "Here are some tty and serial driver fixes for 5.7-rc3.

  The "largest" in here are a number of reverts for previous changes to
  the uartps serial driver that turned out to not be a good idea at all.

  The others are just small fixes found by people and tools. Included in
  here is a much-reported symbol export needed by previous changes that
  happened in 5.7-rc1. All of these have been in linux-next for a while
  with no reported issues"

* tag 'tty-5.7-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
  tty: hvc: fix buffer overflow during hvc_alloc().
  tty: rocket, avoid OOB access
  tty: serial: bcm63xx: fix missing clk_put() in bcm63xx_uart
  vt: don't hardcode the mem allocation upper bound
  tty: serial: owl: add "much needed" clk_prepare_enable()
  vt: don't use kmalloc() for the unicode screen buffer
  tty/sysrq: Export sysrq_mask(), sysrq_toggle_support()
  serial: sh-sci: Make sure status register SCxSR is read in correct sequence
  serial: sunhv: Initialize lock for non-registered console
  Revert "serial: uartps: Register own uart console and driver structures"
  Revert "serial: uartps: Move Port ID to device data structure"
  Revert "serial: uartps: Change uart ID port allocation"
  Revert "serial: uartps: Do not allow use aliases >= MAX_UART_INSTANCES"
  Revert "serial: uartps: Fix error path when alloc failed"
  Revert "serial: uartps: Use the same dynamic major number for all ports"
  Revert "serial: uartps: Fix uartps_major handling"
parents f6da8bd1 9a9fc42b
...@@ -302,10 +302,6 @@ int hvc_instantiate(uint32_t vtermno, int index, const struct hv_ops *ops) ...@@ -302,10 +302,6 @@ int hvc_instantiate(uint32_t vtermno, int index, const struct hv_ops *ops)
vtermnos[index] = vtermno; vtermnos[index] = vtermno;
cons_ops[index] = ops; cons_ops[index] = ops;
/* reserve all indices up to and including this index */
if (last_hvc < index)
last_hvc = index;
/* check if we need to re-register the kernel console */ /* check if we need to re-register the kernel console */
hvc_check_console(index); hvc_check_console(index);
...@@ -960,13 +956,22 @@ struct hvc_struct *hvc_alloc(uint32_t vtermno, int data, ...@@ -960,13 +956,22 @@ struct hvc_struct *hvc_alloc(uint32_t vtermno, int data,
cons_ops[i] == hp->ops) cons_ops[i] == hp->ops)
break; break;
/* no matching slot, just use a counter */ if (i >= MAX_NR_HVC_CONSOLES) {
if (i >= MAX_NR_HVC_CONSOLES)
i = ++last_hvc; /* find 'empty' slot for console */
for (i = 0; i < MAX_NR_HVC_CONSOLES && vtermnos[i] != -1; i++) {
}
/* no matching slot, just use a counter */
if (i == MAX_NR_HVC_CONSOLES)
i = ++last_hvc + MAX_NR_HVC_CONSOLES;
}
hp->index = i; hp->index = i;
cons_ops[i] = ops; if (i < MAX_NR_HVC_CONSOLES) {
vtermnos[i] = vtermno; cons_ops[i] = ops;
vtermnos[i] = vtermno;
}
list_add_tail(&(hp->next), &hvc_structs); list_add_tail(&(hp->next), &hvc_structs);
mutex_unlock(&hvc_structs_mutex); mutex_unlock(&hvc_structs_mutex);
......
...@@ -632,18 +632,21 @@ init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev) ...@@ -632,18 +632,21 @@ init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev)
tty_port_init(&info->port); tty_port_init(&info->port);
info->port.ops = &rocket_port_ops; info->port.ops = &rocket_port_ops;
info->flags &= ~ROCKET_MODE_MASK; info->flags &= ~ROCKET_MODE_MASK;
switch (pc104[board][line]) { if (board < ARRAY_SIZE(pc104) && line < ARRAY_SIZE(pc104_1))
case 422: switch (pc104[board][line]) {
info->flags |= ROCKET_MODE_RS422; case 422:
break; info->flags |= ROCKET_MODE_RS422;
case 485: break;
info->flags |= ROCKET_MODE_RS485; case 485:
break; info->flags |= ROCKET_MODE_RS485;
case 232: break;
default: case 232:
default:
info->flags |= ROCKET_MODE_RS232;
break;
}
else
info->flags |= ROCKET_MODE_RS232; info->flags |= ROCKET_MODE_RS232;
break;
}
info->intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD | DELTA_CTS | DELTA_DSR; info->intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD | DELTA_CTS | DELTA_DSR;
if (sInitChan(ctlp, &info->channel, aiop, chan) == 0) { if (sInitChan(ctlp, &info->channel, aiop, chan) == 0) {
......
...@@ -843,8 +843,10 @@ static int bcm_uart_probe(struct platform_device *pdev) ...@@ -843,8 +843,10 @@ static int bcm_uart_probe(struct platform_device *pdev)
if (IS_ERR(clk) && pdev->dev.of_node) if (IS_ERR(clk) && pdev->dev.of_node)
clk = of_clk_get(pdev->dev.of_node, 0); clk = of_clk_get(pdev->dev.of_node, 0);
if (IS_ERR(clk)) if (IS_ERR(clk)) {
clk_put(clk);
return -ENODEV; return -ENODEV;
}
port->iotype = UPIO_MEM; port->iotype = UPIO_MEM;
port->irq = res_irq->start; port->irq = res_irq->start;
......
...@@ -680,6 +680,12 @@ static int owl_uart_probe(struct platform_device *pdev) ...@@ -680,6 +680,12 @@ static int owl_uart_probe(struct platform_device *pdev)
return PTR_ERR(owl_port->clk); return PTR_ERR(owl_port->clk);
} }
ret = clk_prepare_enable(owl_port->clk);
if (ret) {
dev_err(&pdev->dev, "could not enable clk\n");
return ret;
}
owl_port->port.dev = &pdev->dev; owl_port->port.dev = &pdev->dev;
owl_port->port.line = pdev->id; owl_port->port.line = pdev->id;
owl_port->port.type = PORT_OWL; owl_port->port.type = PORT_OWL;
...@@ -712,6 +718,7 @@ static int owl_uart_remove(struct platform_device *pdev) ...@@ -712,6 +718,7 @@ static int owl_uart_remove(struct platform_device *pdev)
uart_remove_one_port(&owl_uart_driver, &owl_port->port); uart_remove_one_port(&owl_uart_driver, &owl_port->port);
owl_uart_ports[pdev->id] = NULL; owl_uart_ports[pdev->id] = NULL;
clk_disable_unprepare(owl_port->clk);
return 0; return 0;
} }
......
...@@ -870,9 +870,16 @@ static void sci_receive_chars(struct uart_port *port) ...@@ -870,9 +870,16 @@ static void sci_receive_chars(struct uart_port *port)
tty_insert_flip_char(tport, c, TTY_NORMAL); tty_insert_flip_char(tport, c, TTY_NORMAL);
} else { } else {
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
char c = serial_port_in(port, SCxRDR); char c;
status = serial_port_in(port, SCxSR); if (port->type == PORT_SCIF ||
port->type == PORT_HSCIF) {
status = serial_port_in(port, SCxSR);
c = serial_port_in(port, SCxRDR);
} else {
c = serial_port_in(port, SCxRDR);
status = serial_port_in(port, SCxSR);
}
if (uart_handle_sysrq_char(port, c)) { if (uart_handle_sysrq_char(port, c)) {
count--; i--; count--; i--;
continue; continue;
......
...@@ -567,6 +567,9 @@ static int hv_probe(struct platform_device *op) ...@@ -567,6 +567,9 @@ static int hv_probe(struct platform_device *op)
sunserial_console_match(&sunhv_console, op->dev.of_node, sunserial_console_match(&sunhv_console, op->dev.of_node,
&sunhv_reg, port->line, false); &sunhv_reg, port->line, false);
/* We need to initialize lock even for non-registered console */
spin_lock_init(&port->lock);
err = uart_add_one_port(&sunhv_reg, port); err = uart_add_one_port(&sunhv_reg, port);
if (err) if (err)
goto out_unregister_driver; goto out_unregister_driver;
......
This diff is collapsed.
...@@ -74,6 +74,7 @@ int sysrq_mask(void) ...@@ -74,6 +74,7 @@ int sysrq_mask(void)
return 1; return 1;
return sysrq_enabled; return sysrq_enabled;
} }
EXPORT_SYMBOL_GPL(sysrq_mask);
/* /*
* A value of 1 means 'all', other nonzero values are an op mask: * A value of 1 means 'all', other nonzero values are an op mask:
...@@ -1058,6 +1059,7 @@ int sysrq_toggle_support(int enable_mask) ...@@ -1058,6 +1059,7 @@ int sysrq_toggle_support(int enable_mask)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(sysrq_toggle_support);
static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p, static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p,
struct sysrq_key_op *remove_op_p) struct sysrq_key_op *remove_op_p)
......
...@@ -81,6 +81,7 @@ ...@@ -81,6 +81,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/kd.h> #include <linux/kd.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/major.h> #include <linux/major.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/console.h> #include <linux/console.h>
...@@ -350,7 +351,7 @@ static struct uni_screen *vc_uniscr_alloc(unsigned int cols, unsigned int rows) ...@@ -350,7 +351,7 @@ static struct uni_screen *vc_uniscr_alloc(unsigned int cols, unsigned int rows)
/* allocate everything in one go */ /* allocate everything in one go */
memsize = cols * rows * sizeof(char32_t); memsize = cols * rows * sizeof(char32_t);
memsize += rows * sizeof(char32_t *); memsize += rows * sizeof(char32_t *);
p = kmalloc(memsize, GFP_KERNEL); p = vmalloc(memsize);
if (!p) if (!p)
return NULL; return NULL;
...@@ -366,7 +367,7 @@ static struct uni_screen *vc_uniscr_alloc(unsigned int cols, unsigned int rows) ...@@ -366,7 +367,7 @@ static struct uni_screen *vc_uniscr_alloc(unsigned int cols, unsigned int rows)
static void vc_uniscr_set(struct vc_data *vc, struct uni_screen *new_uniscr) static void vc_uniscr_set(struct vc_data *vc, struct uni_screen *new_uniscr)
{ {
kfree(vc->vc_uni_screen); vfree(vc->vc_uni_screen);
vc->vc_uni_screen = new_uniscr; vc->vc_uni_screen = new_uniscr;
} }
...@@ -1206,7 +1207,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, ...@@ -1206,7 +1207,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) if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
return 0; return 0;
if (new_screen_size > (4 << 20)) if (new_screen_size > KMALLOC_MAX_SIZE)
return -EINVAL; return -EINVAL;
newscreen = kzalloc(new_screen_size, GFP_USER); newscreen = kzalloc(new_screen_size, GFP_USER);
if (!newscreen) if (!newscreen)
......
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