TTY/Serial driver fixes for 5.0-rc4
Here are a number of small tty core and serial driver fixes for 5.0-rc4 to resolve some reported issues. Nothing major, the small serial driver fixes, a tty core fixup for a crash that was reported, and some good vt fixes from Nicolas Pitre as he seems to be auditing that chunk of code a lot lately. All of these have been in linux-next for a while with no reported issues. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCXEr9zw8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ylgaQCcCpv3UHszx+ZemlyPUB3ZGEa1l48AoLd3VB46 cRO5Cf78Dr/FO73bWjLR =zjYg -----END PGP SIGNATURE----- Merge tag 'tty-5.0-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty Pull tty/serial driver fixes from Greg KH: "Here are a number of small tty core and serial driver fixes for 5.0-rc4 to resolve some reported issues. Nothing major, the small serial driver fixes, a tty core fixup for a crash that was reported, and some good vt fixes from Nicolas Pitre as he seems to be auditing that chunk of code a lot lately. All of these have been in linux-next for a while with no reported issues" * tag 'tty-5.0-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: serial: fsl_lpuart: fix maximum acceptable baud rate with over-sampling tty: serial: qcom_geni_serial: Allow mctrl when flow control is disabled tty: Handle problem if line discipline does not have receive_buf vgacon: unconfuse vc_origin when using soft scrollback vt: invoke notifier on screen size change vt: always call notifier with the console lock held vt: make vt_console_print() compatible with the unicode screen buffer tty/n_hdlc: fix __might_sleep warning serial: 8250: Fix serial8250 initialization crash uart: Fix crash in uart_write and uart_put_char
This commit is contained in:
commit
473721f9c6
|
@ -597,6 +597,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
|
|||
/* too large for caller's buffer */
|
||||
ret = -EOVERFLOW;
|
||||
} else {
|
||||
__set_current_state(TASK_RUNNING);
|
||||
if (copy_to_user(buf, rbuf->buf, rbuf->count))
|
||||
ret = -EFAULT;
|
||||
else
|
||||
|
|
|
@ -1070,15 +1070,16 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
|
|||
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialise interrupt backoff work if required */
|
||||
if (up->overrun_backoff_time_ms > 0) {
|
||||
uart->overrun_backoff_time_ms = up->overrun_backoff_time_ms;
|
||||
INIT_DELAYED_WORK(&uart->overrun_backoff,
|
||||
serial_8250_overrun_backoff_work);
|
||||
} else {
|
||||
uart->overrun_backoff_time_ms = 0;
|
||||
/* Initialise interrupt backoff work if required */
|
||||
if (up->overrun_backoff_time_ms > 0) {
|
||||
uart->overrun_backoff_time_ms =
|
||||
up->overrun_backoff_time_ms;
|
||||
INIT_DELAYED_WORK(&uart->overrun_backoff,
|
||||
serial_8250_overrun_backoff_work);
|
||||
} else {
|
||||
uart->overrun_backoff_time_ms = 0;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&serial_mutex);
|
||||
|
|
|
@ -1697,7 +1697,7 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||
}
|
||||
|
||||
/* ask the core to calculate the divisor */
|
||||
baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 16);
|
||||
baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 4);
|
||||
|
||||
spin_lock_irqsave(&sport->port.lock, flags);
|
||||
|
||||
|
|
|
@ -225,7 +225,7 @@ static unsigned int qcom_geni_serial_get_mctrl(struct uart_port *uport)
|
|||
unsigned int mctrl = TIOCM_DSR | TIOCM_CAR;
|
||||
u32 geni_ios;
|
||||
|
||||
if (uart_console(uport) || !uart_cts_enabled(uport)) {
|
||||
if (uart_console(uport)) {
|
||||
mctrl |= TIOCM_CTS;
|
||||
} else {
|
||||
geni_ios = readl_relaxed(uport->membase + SE_GENI_IOS);
|
||||
|
@ -241,7 +241,7 @@ static void qcom_geni_serial_set_mctrl(struct uart_port *uport,
|
|||
{
|
||||
u32 uart_manual_rfr = 0;
|
||||
|
||||
if (uart_console(uport) || !uart_cts_enabled(uport))
|
||||
if (uart_console(uport))
|
||||
return;
|
||||
|
||||
if (!(mctrl & TIOCM_RTS))
|
||||
|
|
|
@ -550,10 +550,12 @@ static int uart_put_char(struct tty_struct *tty, unsigned char c)
|
|||
int ret = 0;
|
||||
|
||||
circ = &state->xmit;
|
||||
if (!circ->buf)
|
||||
return 0;
|
||||
|
||||
port = uart_port_lock(state, flags);
|
||||
if (!circ->buf) {
|
||||
uart_port_unlock(port, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (port && uart_circ_chars_free(circ) != 0) {
|
||||
circ->buf[circ->head] = c;
|
||||
circ->head = (circ->head + 1) & (UART_XMIT_SIZE - 1);
|
||||
|
@ -586,11 +588,13 @@ static int uart_write(struct tty_struct *tty,
|
|||
return -EL3HLT;
|
||||
}
|
||||
|
||||
circ = &state->xmit;
|
||||
if (!circ->buf)
|
||||
return 0;
|
||||
|
||||
port = uart_port_lock(state, flags);
|
||||
circ = &state->xmit;
|
||||
if (!circ->buf) {
|
||||
uart_port_unlock(port, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (port) {
|
||||
c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
|
||||
if (count < c)
|
||||
|
|
|
@ -2189,7 +2189,8 @@ static int tiocsti(struct tty_struct *tty, char __user *p)
|
|||
ld = tty_ldisc_ref_wait(tty);
|
||||
if (!ld)
|
||||
return -EIO;
|
||||
ld->ops->receive_buf(tty, &ch, &mbz, 1);
|
||||
if (ld->ops->receive_buf)
|
||||
ld->ops->receive_buf(tty, &ch, &mbz, 1);
|
||||
tty_ldisc_deref(ld);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1272,6 +1272,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
|
|||
if (con_is_visible(vc))
|
||||
update_screen(vc);
|
||||
vt_event_post(VT_EVENT_RESIZE, vc->vc_num, vc->vc_num);
|
||||
notify_update(vc);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -2764,8 +2765,8 @@ rescan_last_byte:
|
|||
con_flush(vc, draw_from, draw_to, &draw_x);
|
||||
vc_uniscr_debug_check(vc);
|
||||
console_conditional_schedule();
|
||||
console_unlock();
|
||||
notify_update(vc);
|
||||
console_unlock();
|
||||
return n;
|
||||
}
|
||||
|
||||
|
@ -2884,8 +2885,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
|
|||
unsigned char c;
|
||||
static DEFINE_SPINLOCK(printing_lock);
|
||||
const ushort *start;
|
||||
ushort cnt = 0;
|
||||
ushort myx;
|
||||
ushort start_x, cnt;
|
||||
int kmsg_console;
|
||||
|
||||
/* console busy or not yet initialized */
|
||||
|
@ -2898,10 +2898,6 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
|
|||
if (kmsg_console && vc_cons_allocated(kmsg_console - 1))
|
||||
vc = vc_cons[kmsg_console - 1].d;
|
||||
|
||||
/* read `x' only after setting currcons properly (otherwise
|
||||
the `x' macro will read the x of the foreground console). */
|
||||
myx = vc->vc_x;
|
||||
|
||||
if (!vc_cons_allocated(fg_console)) {
|
||||
/* impossible */
|
||||
/* printk("vt_console_print: tty %d not allocated ??\n", currcons+1); */
|
||||
|
@ -2916,53 +2912,41 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
|
|||
hide_cursor(vc);
|
||||
|
||||
start = (ushort *)vc->vc_pos;
|
||||
|
||||
/* Contrived structure to try to emulate original need_wrap behaviour
|
||||
* Problems caused when we have need_wrap set on '\n' character */
|
||||
start_x = vc->vc_x;
|
||||
cnt = 0;
|
||||
while (count--) {
|
||||
c = *b++;
|
||||
if (c == 10 || c == 13 || c == 8 || vc->vc_need_wrap) {
|
||||
if (cnt > 0) {
|
||||
if (con_is_visible(vc))
|
||||
vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x);
|
||||
vc->vc_x += cnt;
|
||||
if (vc->vc_need_wrap)
|
||||
vc->vc_x--;
|
||||
cnt = 0;
|
||||
}
|
||||
if (cnt && con_is_visible(vc))
|
||||
vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, start_x);
|
||||
cnt = 0;
|
||||
if (c == 8) { /* backspace */
|
||||
bs(vc);
|
||||
start = (ushort *)vc->vc_pos;
|
||||
myx = vc->vc_x;
|
||||
start_x = vc->vc_x;
|
||||
continue;
|
||||
}
|
||||
if (c != 13)
|
||||
lf(vc);
|
||||
cr(vc);
|
||||
start = (ushort *)vc->vc_pos;
|
||||
myx = vc->vc_x;
|
||||
start_x = vc->vc_x;
|
||||
if (c == 10 || c == 13)
|
||||
continue;
|
||||
}
|
||||
vc_uniscr_putc(vc, c);
|
||||
scr_writew((vc->vc_attr << 8) + c, (unsigned short *)vc->vc_pos);
|
||||
notify_write(vc, c);
|
||||
cnt++;
|
||||
if (myx == vc->vc_cols - 1) {
|
||||
vc->vc_need_wrap = 1;
|
||||
continue;
|
||||
}
|
||||
vc->vc_pos += 2;
|
||||
myx++;
|
||||
}
|
||||
if (cnt > 0) {
|
||||
if (con_is_visible(vc))
|
||||
vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x);
|
||||
vc->vc_x += cnt;
|
||||
if (vc->vc_x == vc->vc_cols) {
|
||||
vc->vc_x--;
|
||||
if (vc->vc_x == vc->vc_cols - 1) {
|
||||
vc->vc_need_wrap = 1;
|
||||
} else {
|
||||
vc->vc_pos += 2;
|
||||
vc->vc_x++;
|
||||
}
|
||||
}
|
||||
if (cnt && con_is_visible(vc))
|
||||
vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, start_x);
|
||||
set_cursor(vc);
|
||||
notify_update(vc);
|
||||
|
||||
|
|
|
@ -271,6 +271,7 @@ static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
|
|||
|
||||
static void vgacon_restore_screen(struct vc_data *c)
|
||||
{
|
||||
c->vc_origin = c->vc_visible_origin;
|
||||
vgacon_scrollback_cur->save = 0;
|
||||
|
||||
if (!vga_is_gfx && !vgacon_scrollback_cur->restore) {
|
||||
|
@ -287,8 +288,7 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
|
|||
int start, end, count, soff;
|
||||
|
||||
if (!lines) {
|
||||
c->vc_visible_origin = c->vc_origin;
|
||||
vga_set_mem_top(c);
|
||||
vgacon_restore_screen(c);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -298,6 +298,7 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
|
|||
if (!vgacon_scrollback_cur->save) {
|
||||
vgacon_cursor(c, CM_ERASE);
|
||||
vgacon_save_screen(c);
|
||||
c->vc_origin = (unsigned long)c->vc_screenbuf;
|
||||
vgacon_scrollback_cur->save = 1;
|
||||
}
|
||||
|
||||
|
@ -335,7 +336,7 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
|
|||
int copysize;
|
||||
|
||||
int diff = c->vc_rows - count;
|
||||
void *d = (void *) c->vc_origin;
|
||||
void *d = (void *) c->vc_visible_origin;
|
||||
void *s = (void *) c->vc_screenbuf;
|
||||
|
||||
count *= c->vc_size_row;
|
||||
|
|
Loading…
Reference in New Issue