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 */
|
/* too large for caller's buffer */
|
||||||
ret = -EOVERFLOW;
|
ret = -EOVERFLOW;
|
||||||
} else {
|
} else {
|
||||||
|
__set_current_state(TASK_RUNNING);
|
||||||
if (copy_to_user(buf, rbuf->buf, rbuf->count))
|
if (copy_to_user(buf, rbuf->buf, rbuf->count))
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
else
|
else
|
||||||
|
|
|
@ -1070,16 +1070,17 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialise interrupt backoff work if required */
|
/* Initialise interrupt backoff work if required */
|
||||||
if (up->overrun_backoff_time_ms > 0) {
|
if (up->overrun_backoff_time_ms > 0) {
|
||||||
uart->overrun_backoff_time_ms = up->overrun_backoff_time_ms;
|
uart->overrun_backoff_time_ms =
|
||||||
|
up->overrun_backoff_time_ms;
|
||||||
INIT_DELAYED_WORK(&uart->overrun_backoff,
|
INIT_DELAYED_WORK(&uart->overrun_backoff,
|
||||||
serial_8250_overrun_backoff_work);
|
serial_8250_overrun_backoff_work);
|
||||||
} else {
|
} else {
|
||||||
uart->overrun_backoff_time_ms = 0;
|
uart->overrun_backoff_time_ms = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mutex_unlock(&serial_mutex);
|
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 */
|
/* 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);
|
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;
|
unsigned int mctrl = TIOCM_DSR | TIOCM_CAR;
|
||||||
u32 geni_ios;
|
u32 geni_ios;
|
||||||
|
|
||||||
if (uart_console(uport) || !uart_cts_enabled(uport)) {
|
if (uart_console(uport)) {
|
||||||
mctrl |= TIOCM_CTS;
|
mctrl |= TIOCM_CTS;
|
||||||
} else {
|
} else {
|
||||||
geni_ios = readl_relaxed(uport->membase + SE_GENI_IOS);
|
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;
|
u32 uart_manual_rfr = 0;
|
||||||
|
|
||||||
if (uart_console(uport) || !uart_cts_enabled(uport))
|
if (uart_console(uport))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!(mctrl & TIOCM_RTS))
|
if (!(mctrl & TIOCM_RTS))
|
||||||
|
|
|
@ -550,10 +550,12 @@ static int uart_put_char(struct tty_struct *tty, unsigned char c)
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
circ = &state->xmit;
|
circ = &state->xmit;
|
||||||
if (!circ->buf)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
port = uart_port_lock(state, flags);
|
port = uart_port_lock(state, flags);
|
||||||
|
if (!circ->buf) {
|
||||||
|
uart_port_unlock(port, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (port && uart_circ_chars_free(circ) != 0) {
|
if (port && uart_circ_chars_free(circ) != 0) {
|
||||||
circ->buf[circ->head] = c;
|
circ->buf[circ->head] = c;
|
||||||
circ->head = (circ->head + 1) & (UART_XMIT_SIZE - 1);
|
circ->head = (circ->head + 1) & (UART_XMIT_SIZE - 1);
|
||||||
|
@ -586,11 +588,13 @@ static int uart_write(struct tty_struct *tty,
|
||||||
return -EL3HLT;
|
return -EL3HLT;
|
||||||
}
|
}
|
||||||
|
|
||||||
circ = &state->xmit;
|
|
||||||
if (!circ->buf)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
port = uart_port_lock(state, flags);
|
port = uart_port_lock(state, flags);
|
||||||
|
circ = &state->xmit;
|
||||||
|
if (!circ->buf) {
|
||||||
|
uart_port_unlock(port, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
while (port) {
|
while (port) {
|
||||||
c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
|
c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
|
||||||
if (count < c)
|
if (count < c)
|
||||||
|
|
|
@ -2189,6 +2189,7 @@ static int tiocsti(struct tty_struct *tty, char __user *p)
|
||||||
ld = tty_ldisc_ref_wait(tty);
|
ld = tty_ldisc_ref_wait(tty);
|
||||||
if (!ld)
|
if (!ld)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
if (ld->ops->receive_buf)
|
||||||
ld->ops->receive_buf(tty, &ch, &mbz, 1);
|
ld->ops->receive_buf(tty, &ch, &mbz, 1);
|
||||||
tty_ldisc_deref(ld);
|
tty_ldisc_deref(ld);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -1272,6 +1272,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
|
||||||
if (con_is_visible(vc))
|
if (con_is_visible(vc))
|
||||||
update_screen(vc);
|
update_screen(vc);
|
||||||
vt_event_post(VT_EVENT_RESIZE, vc->vc_num, vc->vc_num);
|
vt_event_post(VT_EVENT_RESIZE, vc->vc_num, vc->vc_num);
|
||||||
|
notify_update(vc);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2764,8 +2765,8 @@ rescan_last_byte:
|
||||||
con_flush(vc, draw_from, draw_to, &draw_x);
|
con_flush(vc, draw_from, draw_to, &draw_x);
|
||||||
vc_uniscr_debug_check(vc);
|
vc_uniscr_debug_check(vc);
|
||||||
console_conditional_schedule();
|
console_conditional_schedule();
|
||||||
console_unlock();
|
|
||||||
notify_update(vc);
|
notify_update(vc);
|
||||||
|
console_unlock();
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2884,8 +2885,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
|
||||||
unsigned char c;
|
unsigned char c;
|
||||||
static DEFINE_SPINLOCK(printing_lock);
|
static DEFINE_SPINLOCK(printing_lock);
|
||||||
const ushort *start;
|
const ushort *start;
|
||||||
ushort cnt = 0;
|
ushort start_x, cnt;
|
||||||
ushort myx;
|
|
||||||
int kmsg_console;
|
int kmsg_console;
|
||||||
|
|
||||||
/* console busy or not yet initialized */
|
/* 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))
|
if (kmsg_console && vc_cons_allocated(kmsg_console - 1))
|
||||||
vc = vc_cons[kmsg_console - 1].d;
|
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)) {
|
if (!vc_cons_allocated(fg_console)) {
|
||||||
/* impossible */
|
/* impossible */
|
||||||
/* printk("vt_console_print: tty %d not allocated ??\n", currcons+1); */
|
/* 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);
|
hide_cursor(vc);
|
||||||
|
|
||||||
start = (ushort *)vc->vc_pos;
|
start = (ushort *)vc->vc_pos;
|
||||||
|
start_x = vc->vc_x;
|
||||||
/* Contrived structure to try to emulate original need_wrap behaviour
|
cnt = 0;
|
||||||
* Problems caused when we have need_wrap set on '\n' character */
|
|
||||||
while (count--) {
|
while (count--) {
|
||||||
c = *b++;
|
c = *b++;
|
||||||
if (c == 10 || c == 13 || c == 8 || vc->vc_need_wrap) {
|
if (c == 10 || c == 13 || c == 8 || vc->vc_need_wrap) {
|
||||||
if (cnt > 0) {
|
if (cnt && con_is_visible(vc))
|
||||||
if (con_is_visible(vc))
|
vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, start_x);
|
||||||
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;
|
cnt = 0;
|
||||||
}
|
|
||||||
if (c == 8) { /* backspace */
|
if (c == 8) { /* backspace */
|
||||||
bs(vc);
|
bs(vc);
|
||||||
start = (ushort *)vc->vc_pos;
|
start = (ushort *)vc->vc_pos;
|
||||||
myx = vc->vc_x;
|
start_x = vc->vc_x;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (c != 13)
|
if (c != 13)
|
||||||
lf(vc);
|
lf(vc);
|
||||||
cr(vc);
|
cr(vc);
|
||||||
start = (ushort *)vc->vc_pos;
|
start = (ushort *)vc->vc_pos;
|
||||||
myx = vc->vc_x;
|
start_x = vc->vc_x;
|
||||||
if (c == 10 || c == 13)
|
if (c == 10 || c == 13)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
vc_uniscr_putc(vc, c);
|
||||||
scr_writew((vc->vc_attr << 8) + c, (unsigned short *)vc->vc_pos);
|
scr_writew((vc->vc_attr << 8) + c, (unsigned short *)vc->vc_pos);
|
||||||
notify_write(vc, c);
|
notify_write(vc, c);
|
||||||
cnt++;
|
cnt++;
|
||||||
if (myx == vc->vc_cols - 1) {
|
if (vc->vc_x == vc->vc_cols - 1) {
|
||||||
vc->vc_need_wrap = 1;
|
vc->vc_need_wrap = 1;
|
||||||
continue;
|
} else {
|
||||||
}
|
|
||||||
vc->vc_pos += 2;
|
vc->vc_pos += 2;
|
||||||
myx++;
|
vc->vc_x++;
|
||||||
}
|
|
||||||
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--;
|
|
||||||
vc->vc_need_wrap = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (cnt && con_is_visible(vc))
|
||||||
|
vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, start_x);
|
||||||
set_cursor(vc);
|
set_cursor(vc);
|
||||||
notify_update(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)
|
static void vgacon_restore_screen(struct vc_data *c)
|
||||||
{
|
{
|
||||||
|
c->vc_origin = c->vc_visible_origin;
|
||||||
vgacon_scrollback_cur->save = 0;
|
vgacon_scrollback_cur->save = 0;
|
||||||
|
|
||||||
if (!vga_is_gfx && !vgacon_scrollback_cur->restore) {
|
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;
|
int start, end, count, soff;
|
||||||
|
|
||||||
if (!lines) {
|
if (!lines) {
|
||||||
c->vc_visible_origin = c->vc_origin;
|
vgacon_restore_screen(c);
|
||||||
vga_set_mem_top(c);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,6 +298,7 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
|
||||||
if (!vgacon_scrollback_cur->save) {
|
if (!vgacon_scrollback_cur->save) {
|
||||||
vgacon_cursor(c, CM_ERASE);
|
vgacon_cursor(c, CM_ERASE);
|
||||||
vgacon_save_screen(c);
|
vgacon_save_screen(c);
|
||||||
|
c->vc_origin = (unsigned long)c->vc_screenbuf;
|
||||||
vgacon_scrollback_cur->save = 1;
|
vgacon_scrollback_cur->save = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,7 +336,7 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
|
||||||
int copysize;
|
int copysize;
|
||||||
|
|
||||||
int diff = c->vc_rows - count;
|
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;
|
void *s = (void *) c->vc_screenbuf;
|
||||||
|
|
||||||
count *= c->vc_size_row;
|
count *= c->vc_size_row;
|
||||||
|
|
Loading…
Reference in New Issue