Commit 42b34a8d authored by Linus Torvalds's avatar Linus Torvalds

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

Pull tty / serial driver fixes from Greg KH:
 "Here are some small tty and serial driver fixes for reported problems
  for 6.11-rc3. Included in here are:

   - sc16is7xx serial driver fixes

   - uartclk bugfix for a divide by zero issue

   - conmakehash userspace build issue fix

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

* tag 'tty-6.11-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
  tty: vt: conmakehash: cope with abs_srctree no longer in env
  serial: sc16is7xx: fix invalid FIFO access with special register set
  serial: sc16is7xx: fix TX fifo corruption
  serial: core: check uartclk for zero to avoid divide by zero
parents 84e6da57 6e20753d
...@@ -327,6 +327,7 @@ struct sc16is7xx_one { ...@@ -327,6 +327,7 @@ struct sc16is7xx_one {
struct kthread_work reg_work; struct kthread_work reg_work;
struct kthread_delayed_work ms_work; struct kthread_delayed_work ms_work;
struct sc16is7xx_one_config config; struct sc16is7xx_one_config config;
unsigned char buf[SC16IS7XX_FIFO_SIZE]; /* Rx buffer. */
unsigned int old_mctrl; unsigned int old_mctrl;
u8 old_lcr; /* Value before EFR access. */ u8 old_lcr; /* Value before EFR access. */
bool irda_mode; bool irda_mode;
...@@ -340,7 +341,6 @@ struct sc16is7xx_port { ...@@ -340,7 +341,6 @@ struct sc16is7xx_port {
unsigned long gpio_valid_mask; unsigned long gpio_valid_mask;
#endif #endif
u8 mctrl_mask; u8 mctrl_mask;
unsigned char buf[SC16IS7XX_FIFO_SIZE];
struct kthread_worker kworker; struct kthread_worker kworker;
struct task_struct *kworker_task; struct task_struct *kworker_task;
struct sc16is7xx_one p[]; struct sc16is7xx_one p[];
...@@ -592,6 +592,8 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud) ...@@ -592,6 +592,8 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud)
SC16IS7XX_MCR_CLKSEL_BIT, SC16IS7XX_MCR_CLKSEL_BIT,
prescaler == 1 ? 0 : SC16IS7XX_MCR_CLKSEL_BIT); prescaler == 1 ? 0 : SC16IS7XX_MCR_CLKSEL_BIT);
mutex_lock(&one->efr_lock);
/* Backup LCR and access special register set (DLL/DLH) */ /* Backup LCR and access special register set (DLL/DLH) */
lcr = sc16is7xx_port_read(port, SC16IS7XX_LCR_REG); lcr = sc16is7xx_port_read(port, SC16IS7XX_LCR_REG);
sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, sc16is7xx_port_write(port, SC16IS7XX_LCR_REG,
...@@ -606,24 +608,26 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud) ...@@ -606,24 +608,26 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud)
/* Restore LCR and access to general register set */ /* Restore LCR and access to general register set */
sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr); sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr);
mutex_unlock(&one->efr_lock);
return DIV_ROUND_CLOSEST((clk / prescaler) / 16, div); return DIV_ROUND_CLOSEST((clk / prescaler) / 16, div);
} }
static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen, static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen,
unsigned int iir) unsigned int iir)
{ {
struct sc16is7xx_port *s = dev_get_drvdata(port->dev); struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
unsigned int lsr = 0, bytes_read, i; unsigned int lsr = 0, bytes_read, i;
bool read_lsr = (iir == SC16IS7XX_IIR_RLSE_SRC) ? true : false; bool read_lsr = (iir == SC16IS7XX_IIR_RLSE_SRC) ? true : false;
u8 ch, flag; u8 ch, flag;
if (unlikely(rxlen >= sizeof(s->buf))) { if (unlikely(rxlen >= sizeof(one->buf))) {
dev_warn_ratelimited(port->dev, dev_warn_ratelimited(port->dev,
"ttySC%i: Possible RX FIFO overrun: %d\n", "ttySC%i: Possible RX FIFO overrun: %d\n",
port->line, rxlen); port->line, rxlen);
port->icount.buf_overrun++; port->icount.buf_overrun++;
/* Ensure sanity of RX level */ /* Ensure sanity of RX level */
rxlen = sizeof(s->buf); rxlen = sizeof(one->buf);
} }
while (rxlen) { while (rxlen) {
...@@ -636,10 +640,10 @@ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen, ...@@ -636,10 +640,10 @@ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen,
lsr = 0; lsr = 0;
if (read_lsr) { if (read_lsr) {
s->buf[0] = sc16is7xx_port_read(port, SC16IS7XX_RHR_REG); one->buf[0] = sc16is7xx_port_read(port, SC16IS7XX_RHR_REG);
bytes_read = 1; bytes_read = 1;
} else { } else {
sc16is7xx_fifo_read(port, s->buf, rxlen); sc16is7xx_fifo_read(port, one->buf, rxlen);
bytes_read = rxlen; bytes_read = rxlen;
} }
...@@ -672,7 +676,7 @@ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen, ...@@ -672,7 +676,7 @@ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen,
} }
for (i = 0; i < bytes_read; ++i) { for (i = 0; i < bytes_read; ++i) {
ch = s->buf[i]; ch = one->buf[i];
if (uart_handle_sysrq_char(port, ch)) if (uart_handle_sysrq_char(port, ch))
continue; continue;
...@@ -690,10 +694,10 @@ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen, ...@@ -690,10 +694,10 @@ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen,
static void sc16is7xx_handle_tx(struct uart_port *port) static void sc16is7xx_handle_tx(struct uart_port *port)
{ {
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
struct tty_port *tport = &port->state->port; struct tty_port *tport = &port->state->port;
unsigned long flags; unsigned long flags;
unsigned int txlen; unsigned int txlen;
unsigned char *tail;
if (unlikely(port->x_char)) { if (unlikely(port->x_char)) {
sc16is7xx_port_write(port, SC16IS7XX_THR_REG, port->x_char); sc16is7xx_port_write(port, SC16IS7XX_THR_REG, port->x_char);
...@@ -718,8 +722,9 @@ static void sc16is7xx_handle_tx(struct uart_port *port) ...@@ -718,8 +722,9 @@ static void sc16is7xx_handle_tx(struct uart_port *port)
txlen = 0; txlen = 0;
} }
txlen = uart_fifo_out(port, s->buf, txlen); txlen = kfifo_out_linear_ptr(&tport->xmit_fifo, &tail, txlen);
sc16is7xx_fifo_write(port, s->buf, txlen); sc16is7xx_fifo_write(port, tail, txlen);
uart_xmit_advance(port, txlen);
uart_port_lock_irqsave(port, &flags); uart_port_lock_irqsave(port, &flags);
if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
......
...@@ -881,6 +881,14 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port, ...@@ -881,6 +881,14 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
new_flags = (__force upf_t)new_info->flags; new_flags = (__force upf_t)new_info->flags;
old_custom_divisor = uport->custom_divisor; old_custom_divisor = uport->custom_divisor;
if (!(uport->flags & UPF_FIXED_PORT)) {
unsigned int uartclk = new_info->baud_base * 16;
/* check needs to be done here before other settings made */
if (uartclk == 0) {
retval = -EINVAL;
goto exit;
}
}
if (!capable(CAP_SYS_ADMIN)) { if (!capable(CAP_SYS_ADMIN)) {
retval = -EPERM; retval = -EPERM;
if (change_irq || change_port || if (change_irq || change_port ||
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
* Copyright (C) 1995-1997 H. Peter Anvin * Copyright (C) 1995-1997 H. Peter Anvin
*/ */
#include <libgen.h>
#include <linux/limits.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sysexits.h> #include <sysexits.h>
...@@ -76,8 +78,8 @@ static void addpair(int fp, int un) ...@@ -76,8 +78,8 @@ static void addpair(int fp, int un)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
FILE *ctbl; FILE *ctbl;
const char *tblname, *rel_tblname; const char *tblname;
const char *abs_srctree; char base_tblname[PATH_MAX];
char buffer[65536]; char buffer[65536];
int fontlen; int fontlen;
int i, nuni, nent; int i, nuni, nent;
...@@ -102,16 +104,6 @@ int main(int argc, char *argv[]) ...@@ -102,16 +104,6 @@ int main(int argc, char *argv[])
} }
} }
abs_srctree = getenv("abs_srctree");
if (abs_srctree && !strncmp(abs_srctree, tblname, strlen(abs_srctree)))
{
rel_tblname = tblname + strlen(abs_srctree);
while (*rel_tblname == '/')
++rel_tblname;
}
else
rel_tblname = tblname;
/* For now we assume the default font is always 256 characters. */ /* For now we assume the default font is always 256 characters. */
fontlen = 256; fontlen = 256;
...@@ -253,6 +245,8 @@ int main(int argc, char *argv[]) ...@@ -253,6 +245,8 @@ int main(int argc, char *argv[])
for ( i = 0 ; i < fontlen ; i++ ) for ( i = 0 ; i < fontlen ; i++ )
nuni += unicount[i]; nuni += unicount[i];
strncpy(base_tblname, tblname, PATH_MAX);
base_tblname[PATH_MAX - 1] = 0;
printf("\ printf("\
/*\n\ /*\n\
* Do not edit this file; it was automatically generated by\n\ * Do not edit this file; it was automatically generated by\n\
...@@ -264,7 +258,7 @@ int main(int argc, char *argv[]) ...@@ -264,7 +258,7 @@ int main(int argc, char *argv[])
#include <linux/types.h>\n\ #include <linux/types.h>\n\
\n\ \n\
u8 dfont_unicount[%d] = \n\ u8 dfont_unicount[%d] = \n\
{\n\t", rel_tblname, fontlen); {\n\t", basename(base_tblname), fontlen);
for ( i = 0 ; i < fontlen ; i++ ) for ( i = 0 ; i < fontlen ; i++ )
{ {
......
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