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 {
struct kthread_work reg_work;
struct kthread_delayed_work ms_work;
struct sc16is7xx_one_config config;
unsigned char buf[SC16IS7XX_FIFO_SIZE]; /* Rx buffer. */
unsigned int old_mctrl;
u8 old_lcr; /* Value before EFR access. */
bool irda_mode;
......@@ -340,7 +341,6 @@ struct sc16is7xx_port {
unsigned long gpio_valid_mask;
#endif
u8 mctrl_mask;
unsigned char buf[SC16IS7XX_FIFO_SIZE];
struct kthread_worker kworker;
struct task_struct *kworker_task;
struct sc16is7xx_one p[];
......@@ -592,6 +592,8 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud)
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) */
lcr = sc16is7xx_port_read(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)
/* Restore LCR and access to general register set */
sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr);
mutex_unlock(&one->efr_lock);
return DIV_ROUND_CLOSEST((clk / prescaler) / 16, div);
}
static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen,
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;
bool read_lsr = (iir == SC16IS7XX_IIR_RLSE_SRC) ? true : false;
u8 ch, flag;
if (unlikely(rxlen >= sizeof(s->buf))) {
if (unlikely(rxlen >= sizeof(one->buf))) {
dev_warn_ratelimited(port->dev,
"ttySC%i: Possible RX FIFO overrun: %d\n",
port->line, rxlen);
port->icount.buf_overrun++;
/* Ensure sanity of RX level */
rxlen = sizeof(s->buf);
rxlen = sizeof(one->buf);
}
while (rxlen) {
......@@ -636,10 +640,10 @@ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen,
lsr = 0;
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;
} else {
sc16is7xx_fifo_read(port, s->buf, rxlen);
sc16is7xx_fifo_read(port, one->buf, rxlen);
bytes_read = rxlen;
}
......@@ -672,7 +676,7 @@ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen,
}
for (i = 0; i < bytes_read; ++i) {
ch = s->buf[i];
ch = one->buf[i];
if (uart_handle_sysrq_char(port, ch))
continue;
......@@ -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)
{
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
struct tty_port *tport = &port->state->port;
unsigned long flags;
unsigned int txlen;
unsigned char *tail;
if (unlikely(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)
txlen = 0;
}
txlen = uart_fifo_out(port, s->buf, txlen);
sc16is7xx_fifo_write(port, s->buf, txlen);
txlen = kfifo_out_linear_ptr(&tport->xmit_fifo, &tail, txlen);
sc16is7xx_fifo_write(port, tail, txlen);
uart_xmit_advance(port, txlen);
uart_port_lock_irqsave(port, &flags);
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,
new_flags = (__force upf_t)new_info->flags;
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)) {
retval = -EPERM;
if (change_irq || change_port ||
......
......@@ -11,6 +11,8 @@
* Copyright (C) 1995-1997 H. Peter Anvin
*/
#include <libgen.h>
#include <linux/limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <sysexits.h>
......@@ -76,8 +78,8 @@ static void addpair(int fp, int un)
int main(int argc, char *argv[])
{
FILE *ctbl;
const char *tblname, *rel_tblname;
const char *abs_srctree;
const char *tblname;
char base_tblname[PATH_MAX];
char buffer[65536];
int fontlen;
int i, nuni, nent;
......@@ -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. */
fontlen = 256;
......@@ -253,6 +245,8 @@ int main(int argc, char *argv[])
for ( i = 0 ; i < fontlen ; i++ )
nuni += unicount[i];
strncpy(base_tblname, tblname, PATH_MAX);
base_tblname[PATH_MAX - 1] = 0;
printf("\
/*\n\
* Do not edit this file; it was automatically generated by\n\
......@@ -264,7 +258,7 @@ int main(int argc, char *argv[])
#include <linux/types.h>\n\
\n\
u8 dfont_unicount[%d] = \n\
{\n\t", rel_tblname, fontlen);
{\n\t", basename(base_tblname), fontlen);
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